msgmerkleblock_test.go raw
1 package wire
2
3 import (
4 "bytes"
5 "crypto/rand"
6 "io"
7 "reflect"
8 "testing"
9 "time"
10
11 "github.com/davecgh/go-spew/spew"
12
13 "github.com/p9c/p9/pkg/chainhash"
14 )
15
16 // TestMerkleBlock tests the MsgMerkleBlock API.
17 func TestMerkleBlock(t *testing.T) {
18 pver := ProtocolVersion
19 enc := BaseEncoding
20 // Block 1 header.
21 prevHash := &blockOne.Header.PrevBlock
22 merkleHash := &blockOne.Header.MerkleRoot
23 bits := blockOne.Header.Bits
24 nonce := blockOne.Header.Nonce
25 bh := NewBlockHeader(1, prevHash, merkleHash, bits, nonce)
26 // Ensure the command is expected value.
27 wantCmd := "merkleblock"
28 msg := NewMsgMerkleBlock(bh)
29 if cmd := msg.Command(); cmd != wantCmd {
30 t.Errorf("NewMsgBlock: wrong command - got %v want %v",
31 cmd, wantCmd,
32 )
33 }
34 // Ensure max payload is expected value for latest protocol version. Num addresses (varInt) + max allowed addresses.
35 wantPayload := uint32(4000000)
36 maxPayload := msg.MaxPayloadLength(pver)
37 if maxPayload != wantPayload {
38 t.Errorf("MaxPayloadLength: wrong max payload length for "+
39 "protocol version %d - got %v, want %v", pver,
40 maxPayload, wantPayload,
41 )
42 }
43 // Load maxTxPerBlock hashes
44 data := make([]byte, 32)
45 for i := 0; i < maxTxPerBlock; i++ {
46 _, _ = rand.Read(data)
47 hash, e := chainhash.NewHash(data)
48 if e != nil {
49 t.Errorf("NewHash failed: %v\n", e)
50 return
51 }
52 if e = msg.AddTxHash(hash); E.Chk(e) {
53 t.Errorf("AddTxHash failed: %v\n", e)
54 return
55 }
56 }
57 // Add one more Tx to test failure.
58 _, _ = rand.Read(data)
59 hash, e := chainhash.NewHash(data)
60 if e != nil {
61 t.Errorf("NewHash failed: %v\n", e)
62 return
63 }
64 if e = msg.AddTxHash(hash); e == nil {
65 t.Errorf("AddTxHash succeeded when it should have failed")
66 return
67 }
68 // Test encode with latest protocol version.
69 var buf bytes.Buffer
70 e = msg.BtcEncode(&buf, pver, enc)
71 if e != nil {
72 t.Errorf("encode of MsgMerkleBlock failed %v e <%v>", msg, e)
73 }
74 // Test decode with latest protocol version.
75 readmsg := MsgMerkleBlock{}
76 e = readmsg.BtcDecode(&buf, pver, enc)
77 if e != nil {
78 t.Errorf("decode of MsgMerkleBlock failed [%v] e <%v>", buf, e)
79 }
80 // Force extra hash to test maxTxPerBlock.
81 msg.Hashes = append(msg.Hashes, hash)
82 e = msg.BtcEncode(&buf, pver, enc)
83 if e == nil {
84 t.Errorf("encode of MsgMerkleBlock succeeded with too many " +
85 "tx hashes when it should have failed",
86 )
87 return
88 }
89 // Force too many flag bytes to test maxFlagsPerMerkleBlock. Reset the number of hashes back to a valid value.
90 msg.Hashes = msg.Hashes[len(msg.Hashes)-1:]
91 msg.Flags = make([]byte, maxFlagsPerMerkleBlock+1)
92 e = msg.BtcEncode(&buf, pver, enc)
93 if e == nil {
94 t.Errorf("encode of MsgMerkleBlock succeeded with too many " +
95 "flag bytes when it should have failed",
96 )
97 return
98 }
99 }
100
101 // TestMerkleBlockCrossProtocol tests the MsgMerkleBlock API when encoding with the latest protocol version and decoding
102 // with BIP0031Version.
103 func TestMerkleBlockCrossProtocol(t *testing.T) {
104 // Block 1 header.
105 prevHash := &blockOne.Header.PrevBlock
106 merkleHash := &blockOne.Header.MerkleRoot
107 bits := blockOne.Header.Bits
108 nonce := blockOne.Header.Nonce
109 bh := NewBlockHeader(1, prevHash, merkleHash, bits, nonce)
110 msg := NewMsgMerkleBlock(bh)
111 // Encode with latest protocol version.
112 var buf bytes.Buffer
113 e := msg.BtcEncode(&buf, ProtocolVersion, BaseEncoding)
114 if e != nil {
115 t.Errorf("encode of NewMsgFilterLoad failed %v e <%v>", msg,
116 e,
117 )
118 }
119 // Decode with old protocol version.
120 var readmsg MsgFilterLoad
121 e = readmsg.BtcDecode(&buf, BIP0031Version, BaseEncoding)
122 if e == nil {
123 t.Errorf("decode of MsgFilterLoad succeeded when it shouldn't have %v",
124 msg,
125 )
126 }
127 }
128
129 // TestMerkleBlockWire tests the MsgMerkleBlock wire encode and decode for various numbers of transaction hashes and
130 // protocol versions.
131 func TestMerkleBlockWire(t *testing.T) {
132 tests := []struct {
133 in *MsgMerkleBlock // Message to encode
134 out *MsgMerkleBlock // Expected decoded message
135 buf []byte // Wire encoding
136 pver uint32 // Protocol version for wire encoding
137 enc MessageEncoding // Message encoding format
138 }{
139 // Latest protocol version.
140 {
141 &merkleBlockOne, &merkleBlockOne, merkleBlockOneBytes,
142 ProtocolVersion, BaseEncoding,
143 },
144 // Protocol version BIP0037Version.
145 {
146 &merkleBlockOne, &merkleBlockOne, merkleBlockOneBytes,
147 BIP0037Version, BaseEncoding,
148 },
149 }
150 t.Logf("Running %d tests", len(tests))
151 for i, test := range tests {
152 // Encode the message to wire format.
153 var buf bytes.Buffer
154 e := test.in.BtcEncode(&buf, test.pver, test.enc)
155 if e != nil {
156 t.Errorf("BtcEncode #%d error %v", i, e)
157 continue
158 }
159 if !bytes.Equal(buf.Bytes(), test.buf) {
160 t.Errorf("BtcEncode #%d\n got: %s want: %s", i,
161 spew.Sdump(buf.Bytes()), spew.Sdump(test.buf),
162 )
163 continue
164 }
165 // Decode the message from wire format.
166 var msg MsgMerkleBlock
167 rbuf := bytes.NewReader(test.buf)
168 e = msg.BtcDecode(rbuf, test.pver, test.enc)
169 if e != nil {
170 t.Errorf("BtcDecode #%d error %v", i, e)
171 continue
172 }
173 if !reflect.DeepEqual(&msg, test.out) {
174 t.Errorf("BtcDecode #%d\n got: %s want: %s", i,
175 spew.Sdump(&msg), spew.Sdump(test.out),
176 )
177 continue
178 }
179 }
180 }
181
182 // TestMerkleBlockWireErrors performs negative tests against wire encode and decode of Block to confirm error paths
183 // work correctly.
184 func TestMerkleBlockWireErrors(t *testing.T) {
185 // Use protocol version 70001 specifically here instead of the latest because the test data is using bytes encoded
186 // with that protocol version.
187 pver := uint32(70001)
188 pverNoMerkleBlock := BIP0037Version - 1
189 wireErr := &MessageError{}
190 tests := []struct {
191 in *MsgMerkleBlock // value to encode
192 buf []byte // Wire encoding
193 pver uint32 // Protocol version for wire encoding
194 enc MessageEncoding // Message encoding format
195 max int // Max size of fixed buffer to induce errors
196 writeErr error // Expected write error
197 readErr error // Expected read error
198 }{
199 // Force error in version.
200 {
201 &merkleBlockOne, merkleBlockOneBytes, pver, BaseEncoding, 0,
202 io.ErrShortWrite, io.EOF,
203 },
204 // Force error in prev block hash.
205 {
206 &merkleBlockOne, merkleBlockOneBytes, pver, BaseEncoding, 4,
207 io.ErrShortWrite, io.EOF,
208 },
209 // Force error in merkle root.
210 {
211 &merkleBlockOne, merkleBlockOneBytes, pver, BaseEncoding, 36,
212 io.ErrShortWrite, io.EOF,
213 },
214 // Force error in timestamp.
215 {
216 &merkleBlockOne, merkleBlockOneBytes, pver, BaseEncoding, 68,
217 io.ErrShortWrite, io.EOF,
218 },
219 // Force error in difficulty bits.
220 {
221 &merkleBlockOne, merkleBlockOneBytes, pver, BaseEncoding, 72,
222 io.ErrShortWrite, io.EOF,
223 },
224 // Force error in header nonce.
225 {
226 &merkleBlockOne, merkleBlockOneBytes, pver, BaseEncoding, 76,
227 io.ErrShortWrite, io.EOF,
228 },
229 // Force error in transaction count.
230 {
231 &merkleBlockOne, merkleBlockOneBytes, pver, BaseEncoding, 80,
232 io.ErrShortWrite, io.EOF,
233 },
234 // Force error in num hashes.
235 {
236 &merkleBlockOne, merkleBlockOneBytes, pver, BaseEncoding, 84,
237 io.ErrShortWrite, io.EOF,
238 },
239 // Force error in hashes.
240 {
241 &merkleBlockOne, merkleBlockOneBytes, pver, BaseEncoding, 85,
242 io.ErrShortWrite, io.EOF,
243 },
244 // Force error in num flag bytes.
245 {
246 &merkleBlockOne, merkleBlockOneBytes, pver, BaseEncoding, 117,
247 io.ErrShortWrite, io.EOF,
248 },
249 // Force error in flag bytes.
250 {
251 &merkleBlockOne, merkleBlockOneBytes, pver, BaseEncoding, 118,
252 io.ErrShortWrite, io.EOF,
253 },
254 // Force error due to unsupported protocol version.
255 {
256 &merkleBlockOne, merkleBlockOneBytes, pverNoMerkleBlock,
257 BaseEncoding, 119, wireErr, wireErr,
258 },
259 }
260 t.Logf("Running %d tests", len(tests))
261 for i, test := range tests {
262 // Encode to wire format.
263 w := newFixedWriter(test.max)
264 e := test.in.BtcEncode(w, test.pver, test.enc)
265 if reflect.TypeOf(e) != reflect.TypeOf(test.writeErr) {
266 t.Errorf("BtcEncode #%d wrong error got: %v, want: %v",
267 i, e, test.writeErr,
268 )
269 continue
270 }
271 // For errors which are not of type MessageError, check them for equality.
272 if _, ok := e.(*MessageError); !ok {
273 if e != test.writeErr {
274 t.Errorf("BtcEncode #%d wrong error got: %v, "+
275 "want: %v", i, e, test.writeErr,
276 )
277 continue
278 }
279 }
280 // Decode from wire format.
281 var msg MsgMerkleBlock
282 r := newFixedReader(test.max, test.buf)
283 e = msg.BtcDecode(r, test.pver, test.enc)
284 if reflect.TypeOf(e) != reflect.TypeOf(test.readErr) {
285 t.Errorf("BtcDecode #%d wrong error got: %v, want: %v",
286 i, e, test.readErr,
287 )
288 continue
289 }
290 // For errors which are not of type MessageError, check them for equality.
291 if _, ok := e.(*MessageError); !ok {
292 if e != test.readErr {
293 t.Errorf("BtcDecode #%d wrong error got: %v, "+
294 "want: %v", i, e, test.readErr,
295 )
296 continue
297 }
298 }
299 }
300 }
301
302 // TestMerkleBlockOverflowErrors performs tests to ensure encoding and decoding merkle blocks that are intentionally
303 // crafted to use large values for the number of hashes and flags are handled properly. This could otherwise potentially
304 // be used as an attack vector.
305 func TestMerkleBlockOverflowErrors(t *testing.T) {
306 // Use protocol version 70001 specifically here instead of the latest protocol version because the test data is
307 // using bytes encoded with that version.
308 pver := uint32(70001)
309 // Create bytes for a merkle block that claims to have more than the max allowed tx hashes.
310 var buf bytes.Buffer
311 e := WriteVarInt(&buf, pver, maxTxPerBlock+1)
312 if e != nil {
313 t.Log(e)
314 }
315 numHashesOffset := 84
316 exceedMaxHashes := make([]byte, numHashesOffset)
317 copy(exceedMaxHashes, merkleBlockOneBytes[:numHashesOffset])
318 exceedMaxHashes = append(exceedMaxHashes, buf.Bytes()...)
319 // Create bytes for a merkle block that claims to have more than the max allowed flag bytes.
320 buf.Reset()
321 e = WriteVarInt(&buf, pver, maxFlagsPerMerkleBlock+1)
322 if e != nil {
323 t.Log(e)
324 }
325 numFlagBytesOffset := 117
326 exceedMaxFlagBytes := make([]byte, numFlagBytesOffset)
327 copy(exceedMaxFlagBytes, merkleBlockOneBytes[:numFlagBytesOffset])
328 exceedMaxFlagBytes = append(exceedMaxFlagBytes, buf.Bytes()...)
329 tests := []struct {
330 buf []byte // Wire encoding
331 pver uint32 // Protocol version for wire encoding
332 enc MessageEncoding // Message encoding format
333 e error // Expected error
334 }{
335 // Block that claims to have more than max allowed hashes.
336 {exceedMaxHashes, pver, BaseEncoding, &MessageError{}},
337 // Block that claims to have more than max allowed flag bytes.
338 {exceedMaxFlagBytes, pver, BaseEncoding, &MessageError{}},
339 }
340 t.Logf("Running %d tests", len(tests))
341 for i, test := range tests {
342 // Decode from wire format.
343 var msg MsgMerkleBlock
344 r := bytes.NewReader(test.buf)
345 e := msg.BtcDecode(r, test.pver, test.enc)
346 if reflect.TypeOf(e) != reflect.TypeOf(test.e) {
347 t.Errorf("BtcDecode #%d wrong error got: %v, want: %v",
348 i, e, reflect.TypeOf(test.e),
349 )
350 continue
351 }
352 }
353 }
354
355 // merkleBlockOne is a merkle block created from block one of the block chain where the first transaction matches.
356 var merkleBlockOne = MsgMerkleBlock{
357 Header: BlockHeader{
358 Version: 1,
359 PrevBlock: chainhash.Hash([chainhash.HashSize]byte{ // Make go vet happy.
360 0x6f, 0xe2, 0x8c, 0x0a, 0xb6, 0xf1, 0xb3, 0x72,
361 0xc1, 0xa6, 0xa2, 0x46, 0xae, 0x63, 0xf7, 0x4f,
362 0x93, 0x1e, 0x83, 0x65, 0xe1, 0x5a, 0x08, 0x9c,
363 0x68, 0xd6, 0x19, 0x00, 0x00, 0x00, 0x00, 0x00,
364 },
365 ),
366 MerkleRoot: chainhash.Hash([chainhash.HashSize]byte{ // Make go vet happy.
367 0x98, 0x20, 0x51, 0xfd, 0x1e, 0x4b, 0xa7, 0x44,
368 0xbb, 0xbe, 0x68, 0x0e, 0x1f, 0xee, 0x14, 0x67,
369 0x7b, 0xa1, 0xa3, 0xc3, 0x54, 0x0b, 0xf7, 0xb1,
370 0xcd, 0xb6, 0x06, 0xe8, 0x57, 0x23, 0x3e, 0x0e,
371 },
372 ),
373 Timestamp: time.Unix(0x4966bc61, 0), // 2009-01-08 20:54:25 -0600 CST
374 Bits: 0x1d00ffff, // 486604799
375 Nonce: 0x9962e301, // 2573394689
376 },
377 Transactions: 1,
378 Hashes: []*chainhash.Hash{
379 (*chainhash.Hash)(&[chainhash.HashSize]byte{ // Make go vet happy.
380 0x98, 0x20, 0x51, 0xfd, 0x1e, 0x4b, 0xa7, 0x44,
381 0xbb, 0xbe, 0x68, 0x0e, 0x1f, 0xee, 0x14, 0x67,
382 0x7b, 0xa1, 0xa3, 0xc3, 0x54, 0x0b, 0xf7, 0xb1,
383 0xcd, 0xb6, 0x06, 0xe8, 0x57, 0x23, 0x3e, 0x0e,
384 },
385 ),
386 },
387 Flags: []byte{0x80},
388 }
389
390 // merkleBlockOneBytes is the serialized bytes for a merkle block created from block one of the block chain where the
391 // first transaction matches.
392 var merkleBlockOneBytes = []byte{
393 0x01, 0x00, 0x00, 0x00, // Version 1
394 0x6f, 0xe2, 0x8c, 0x0a, 0xb6, 0xf1, 0xb3, 0x72,
395 0xc1, 0xa6, 0xa2, 0x46, 0xae, 0x63, 0xf7, 0x4f,
396 0x93, 0x1e, 0x83, 0x65, 0xe1, 0x5a, 0x08, 0x9c,
397 0x68, 0xd6, 0x19, 0x00, 0x00, 0x00, 0x00, 0x00, // PrevBlock
398 0x98, 0x20, 0x51, 0xfd, 0x1e, 0x4b, 0xa7, 0x44,
399 0xbb, 0xbe, 0x68, 0x0e, 0x1f, 0xee, 0x14, 0x67,
400 0x7b, 0xa1, 0xa3, 0xc3, 0x54, 0x0b, 0xf7, 0xb1,
401 0xcd, 0xb6, 0x06, 0xe8, 0x57, 0x23, 0x3e, 0x0e, // MerkleRoot
402 0x61, 0xbc, 0x66, 0x49, // Timestamp
403 0xff, 0xff, 0x00, 0x1d, // Bits
404 0x01, 0xe3, 0x62, 0x99, // Nonce
405 0x01, 0x00, 0x00, 0x00, // TxnCount
406 0x01, // Num hashes
407 0x98, 0x20, 0x51, 0xfd, 0x1e, 0x4b, 0xa7, 0x44,
408 0xbb, 0xbe, 0x68, 0x0e, 0x1f, 0xee, 0x14, 0x67,
409 0x7b, 0xa1, 0xa3, 0xc3, 0x54, 0x0b, 0xf7, 0xb1,
410 0xcd, 0xb6, 0x06, 0xe8, 0x57, 0x23, 0x3e, 0x0e, // Hash
411 0x01, // Num flag bytes
412 0x80, // Flags
413 }
414