msgtx_test.go raw
1 package wire
2
3 import (
4 "bytes"
5 "fmt"
6 "io"
7 "reflect"
8 "testing"
9
10 "github.com/davecgh/go-spew/spew"
11
12 "github.com/p9c/p9/pkg/chainhash"
13 )
14
15 // TestTx tests the MsgTx API.
16 func TestTx(t *testing.T) {
17 pver := ProtocolVersion
18 // Block 100000 hash.
19 hashStr := "3ba27aa200b1cecaad478d2b00432346c3f1f3986da1afd33e506"
20 hash, e := chainhash.NewHashFromStr(hashStr)
21 if e != nil {
22 t.Errorf("NewHashFromStr: %v", e)
23 }
24 // Ensure the command is expected value.
25 wantCmd := "tx"
26 msg := NewMsgTx(1)
27 if cmd := msg.Command(); cmd != wantCmd {
28 t.Errorf("NewMsgAddr: wrong command - got %v want %v",
29 cmd, wantCmd,
30 )
31 }
32 // Ensure max payload is expected value for latest protocol version.
33 wantPayload := uint32(1000 * 4000)
34 maxPayload := msg.MaxPayloadLength(pver)
35 if maxPayload != wantPayload {
36 t.Errorf("MaxPayloadLength: wrong max payload length for protocol version %d - got %v, want %v",
37 pver, maxPayload, wantPayload,
38 )
39 }
40 // Ensure we get the same transaction output point data back out. NOTE: This is a block hash and made up index, but
41 // we're only testing package functionality.
42 prevOutIndex := uint32(1)
43 prevOut := NewOutPoint(hash, prevOutIndex)
44 if !prevOut.Hash.IsEqual(hash) {
45 t.Errorf("NewOutPoint: wrong hash - got %v, want %v",
46 spew.Sprint(&prevOut.Hash), spew.Sprint(hash),
47 )
48 }
49 if prevOut.Index != prevOutIndex {
50 t.Errorf("NewOutPoint: wrong index - got %v, want %v",
51 prevOut.Index, prevOutIndex,
52 )
53 }
54 prevOutStr := fmt.Sprintf("%s:%d", hash.String(), prevOutIndex)
55 if s := prevOut.String(); s != prevOutStr {
56 t.Errorf("OutPoint.String: unexpected result - got %v, "+
57 "want %v", s, prevOutStr,
58 )
59 }
60 // Ensure we get the same transaction input back out.
61 sigScript := []byte{0x04, 0x31, 0xdc, 0x00, 0x1b, 0x01, 0x62}
62 witnessData := [][]byte{
63 {0x04, 0x31},
64 {0x01, 0x43},
65 }
66 txIn := NewTxIn(prevOut, sigScript, witnessData)
67 if !reflect.DeepEqual(&txIn.PreviousOutPoint, prevOut) {
68 t.Errorf("NewTxIn: wrong prev outpoint - got %v, want %v",
69 spew.Sprint(&txIn.PreviousOutPoint),
70 spew.Sprint(prevOut),
71 )
72 }
73 if !bytes.Equal(txIn.SignatureScript, sigScript) {
74 t.Errorf("NewTxIn: wrong signature script - got %v, want %v",
75 spew.Sdump(txIn.SignatureScript),
76 spew.Sdump(sigScript),
77 )
78 }
79 // if !reflect.DeepEqual(txIn.Witness, TxWitness(witnessData)) {
80 // t.Errorf("NewTxIn: wrong witness data - got %v, want %v",
81 // spew.Sdump(txIn.Witness),
82 // spew.Sdump(witnessData))
83 // }
84 // Ensure we get the same transaction output back out.
85 txValue := int64(5000000000)
86 pkScript := []byte{
87 0x41, // OP_DATA_65
88 0x04, 0xd6, 0x4b, 0xdf, 0xd0, 0x9e, 0xb1, 0xc5,
89 0xfe, 0x29, 0x5a, 0xbd, 0xeb, 0x1d, 0xca, 0x42,
90 0x81, 0xbe, 0x98, 0x8e, 0x2d, 0xa0, 0xb6, 0xc1,
91 0xc6, 0xa5, 0x9d, 0xc2, 0x26, 0xc2, 0x86, 0x24,
92 0xe1, 0x81, 0x75, 0xe8, 0x51, 0xc9, 0x6b, 0x97,
93 0x3d, 0x81, 0xb0, 0x1c, 0xc3, 0x1f, 0x04, 0x78,
94 0x34, 0xbc, 0x06, 0xd6, 0xd6, 0xed, 0xf6, 0x20,
95 0xd1, 0x84, 0x24, 0x1a, 0x6a, 0xed, 0x8b, 0x63,
96 0xa6, // 65-byte signature
97 0xac, // OP_CHECKSIG
98 }
99 txOut := NewTxOut(txValue, pkScript)
100 if txOut.Value != txValue {
101 t.Errorf("NewTxOut: wrong pk script - got %v, want %v",
102 txOut.Value, txValue,
103 )
104 }
105 if !bytes.Equal(txOut.PkScript, pkScript) {
106 t.Errorf("NewTxOut: wrong pk script - got %v, want %v",
107 spew.Sdump(txOut.PkScript),
108 spew.Sdump(pkScript),
109 )
110 }
111 // Ensure transaction inputs are added properly.
112 msg.AddTxIn(txIn)
113 if !reflect.DeepEqual(msg.TxIn[0], txIn) {
114 t.Errorf("AddTxIn: wrong transaction input added - got %v, want %v",
115 spew.Sprint(msg.TxIn[0]), spew.Sprint(txIn),
116 )
117 }
118 // Ensure transaction outputs are added properly.
119 msg.AddTxOut(txOut)
120 if !reflect.DeepEqual(msg.TxOut[0], txOut) {
121 t.Errorf("AddTxIn: wrong transaction output added - got %v, want %v",
122 spew.Sprint(msg.TxOut[0]), spew.Sprint(txOut),
123 )
124 }
125 // Ensure the copy produced an identical transaction message.
126 newMsg := msg.Copy()
127 if !reflect.DeepEqual(newMsg, msg) {
128 t.Errorf("Copy: mismatched tx messages - got %v, want %v",
129 spew.Sdump(newMsg), spew.Sdump(msg),
130 )
131 }
132 }
133
134 // TestTxHash tests the ability to generate the hash of a transaction accurately.
135 func TestTxHash(t *testing.T) {
136 // Hash of first transaction from block 113875.
137 hashStr := "f051e59b5e2503ac626d03aaeac8ab7be2d72ba4b7e97119c5852d70d52dcb86"
138 wantHash, e := chainhash.NewHashFromStr(hashStr)
139 if e != nil {
140 t.Errorf("NewHashFromStr: %v", e)
141 return
142 }
143 // First transaction from block 113875.
144 msgTx := NewMsgTx(1)
145 txIn := TxIn{
146 PreviousOutPoint: OutPoint{
147 Hash: chainhash.Hash{},
148 Index: 0xffffffff,
149 },
150 SignatureScript: []byte{0x04, 0x31, 0xdc, 0x00, 0x1b, 0x01, 0x62},
151 Sequence: 0xffffffff,
152 }
153 txOut := TxOut{
154 Value: 5000000000,
155 PkScript: []byte{
156 0x41, // OP_DATA_65
157 0x04, 0xd6, 0x4b, 0xdf, 0xd0, 0x9e, 0xb1, 0xc5,
158 0xfe, 0x29, 0x5a, 0xbd, 0xeb, 0x1d, 0xca, 0x42,
159 0x81, 0xbe, 0x98, 0x8e, 0x2d, 0xa0, 0xb6, 0xc1,
160 0xc6, 0xa5, 0x9d, 0xc2, 0x26, 0xc2, 0x86, 0x24,
161 0xe1, 0x81, 0x75, 0xe8, 0x51, 0xc9, 0x6b, 0x97,
162 0x3d, 0x81, 0xb0, 0x1c, 0xc3, 0x1f, 0x04, 0x78,
163 0x34, 0xbc, 0x06, 0xd6, 0xd6, 0xed, 0xf6, 0x20,
164 0xd1, 0x84, 0x24, 0x1a, 0x6a, 0xed, 0x8b, 0x63,
165 0xa6, // 65-byte signature
166 0xac, // OP_CHECKSIG
167 },
168 }
169 msgTx.AddTxIn(&txIn)
170 msgTx.AddTxOut(&txOut)
171 msgTx.LockTime = 0
172 // Ensure the hash produced is expected.
173 txHash := msgTx.TxHash()
174 if !txHash.IsEqual(wantHash) {
175 t.Errorf("TxHash: wrong hash - got %v, want %v",
176 spew.Sprint(txHash), spew.Sprint(wantHash),
177 )
178 }
179 }
180
181 // TestTxSha tests the ability to generate the wtxid, and txid of a transaction
182 // with witness inputs accurately.
183 func TestWTxSha(t *testing.T) {
184 hashStrTxid := "0f167d1385a84d1518cfee208b653fc9163b605ccf1b75347e2850b3e2eb19f3"
185 wantHashTxid, e := chainhash.NewHashFromStr(hashStrTxid)
186 if e != nil {
187 t.Errorf("NewShaHashFromStr: %v", e)
188 return
189 }
190 // hashStrWTxid := "0858eab78e77b6b033da30f46699996396cf48fcf625a783c85a51403e175e74"
191 // wantHashWTxid, e = chainhash.NewHashFromStr(hashStrWTxid)
192 // if e != nil {
193 // t.Errorf("NewShaHashFromStr: %v", e)
194 // return
195 // }
196 // From block 23157 in a past version of segnet.
197 msgTx := NewMsgTx(1)
198 txIn := TxIn{
199 PreviousOutPoint: OutPoint{
200 Hash: chainhash.Hash{
201 0xa5, 0x33, 0x52, 0xd5, 0x13, 0x57, 0x66, 0xf0,
202 0x30, 0x76, 0x59, 0x74, 0x18, 0x26, 0x3d, 0xa2,
203 0xd9, 0xc9, 0x58, 0x31, 0x59, 0x68, 0xfe, 0xa8,
204 0x23, 0x52, 0x94, 0x67, 0x48, 0x1f, 0xf9, 0xcd,
205 },
206 Index: 19,
207 },
208 // Witness: [][]byte{
209 // { // 70-byte signature
210 // 0x30, 0x43, 0x02, 0x1f, 0x4d, 0x23, 0x81, 0xdc,
211 // 0x97, 0xf1, 0x82, 0xab, 0xd8, 0x18, 0x5f, 0x51,
212 // 0x75, 0x30, 0x18, 0x52, 0x32, 0x12, 0xf5, 0xdd,
213 // 0xc0, 0x7c, 0xc4, 0xe6, 0x3a, 0x8d, 0xc0, 0x36,
214 // 0x58, 0xda, 0x19, 0x02, 0x20, 0x60, 0x8b, 0x5c,
215 // 0x4d, 0x92, 0xb8, 0x6b, 0x6d, 0xe7, 0xd7, 0x8e,
216 // 0xf2, 0x3a, 0x2f, 0xa7, 0x35, 0xbc, 0xb5, 0x9b,
217 // 0x91, 0x4a, 0x48, 0xb0, 0xe1, 0x87, 0xc5, 0xe7,
218 // 0x56, 0x9a, 0x18, 0x19, 0x70, 0x01,
219 // },
220 // { // 33-byte serialize pub key
221 // 0x03, 0x07, 0xea, 0xd0, 0x84, 0x80, 0x7e, 0xb7,
222 // 0x63, 0x46, 0xdf, 0x69, 0x77, 0x00, 0x0c, 0x89,
223 // 0x39, 0x2f, 0x45, 0xc7, 0x64, 0x25, 0xb2, 0x61,
224 // 0x81, 0xf5, 0x21, 0xd7, 0xf3, 0x70, 0x06, 0x6a,
225 // 0x8f,
226 // },
227 // },
228 Sequence: 0xffffffff,
229 }
230 txOut := TxOut{
231 Value: 395019,
232 PkScript: []byte{
233 0x00, // Version 0 witness program
234 0x14, // OP_DATA_20
235 0x9d, 0xda, 0xc6, 0xf3, 0x9d, 0x51, 0xe0, 0x39,
236 0x8e, 0x53, 0x2a, 0x22, 0xc4, 0x1b, 0xa1, 0x89,
237 0x40, 0x6a, 0x85, 0x23, // 20-byte pub key hash
238 },
239 }
240 msgTx.AddTxIn(&txIn)
241 msgTx.AddTxOut(&txOut)
242 msgTx.LockTime = 0
243 // Ensure the correct txid, and wtxid is produced as expected.
244 txid := msgTx.TxHash()
245 if !txid.IsEqual(wantHashTxid) {
246 t.Errorf("TxSha: wrong hash - got %v, want %v",
247 spew.Sprint(txid), spew.Sprint(wantHashTxid),
248 )
249 }
250 // wtxid := msgTx.WitnessHash()
251 // if !wtxid.IsEqual(wantHashWTxid) {
252 // t.Errorf("WTxSha: wrong hash - got %v, want %v",
253 // spew.Sprint(wtxid), spew.Sprint(wantHashWTxid))
254 // }
255 }
256
257 // TestTxWire tests the MsgTx wire encode and decode for various numbers of transaction inputs and outputs and protocol
258 // versions.
259 func TestTxWire(t *testing.T) {
260 // Empty tx message.
261 noTx := NewMsgTx(1)
262 noTx.Version = 1
263 noTxEncoded := []byte{
264 0x01, 0x00, 0x00, 0x00, // Version
265 0x00, // Varint for number of input transactions
266 0x00, // Varint for number of output transactions
267 0x00, 0x00, 0x00, 0x00, // Lock time
268 }
269 tests := []struct {
270 in *MsgTx // Message to encode
271 out *MsgTx // Expected decoded message
272 buf []byte // Wire encoding
273 pver uint32 // Protocol version for wire encoding
274 enc MessageEncoding // Message encoding format
275 }{
276 // Latest protocol version with no transactions.
277 {
278 noTx,
279 noTx, noTxEncoded,
280 ProtocolVersion,
281 BaseEncoding,
282 },
283 // Latest protocol version with multiple transactions.
284 {
285 multiTx,
286 multiTx,
287 multiTxEncoded,
288 ProtocolVersion,
289 BaseEncoding,
290 },
291 // Protocol version BIP0035Version with no transactions.
292 {
293 noTx,
294 noTx,
295 noTxEncoded,
296 BIP0035Version,
297 BaseEncoding,
298 },
299 // Protocol version BIP0035Version with multiple transactions.
300 {
301 multiTx,
302 multiTx,
303 multiTxEncoded,
304 BIP0035Version,
305 BaseEncoding,
306 },
307 // Protocol version BIP0031Version with no transactions.
308 {
309 noTx,
310 noTx,
311 noTxEncoded,
312 BIP0031Version,
313 BaseEncoding,
314 },
315 // Protocol version BIP0031Version with multiple transactions.
316 {
317 multiTx,
318 multiTx,
319 multiTxEncoded,
320 BIP0031Version,
321 BaseEncoding,
322 },
323 // Protocol version NetAddressTimeVersion with no transactions.
324 {
325 noTx,
326 noTx,
327 noTxEncoded,
328 NetAddressTimeVersion,
329 BaseEncoding,
330 },
331 // Protocol version NetAddressTimeVersion with multiple transactions.
332 {
333 multiTx,
334 multiTx,
335 multiTxEncoded,
336 NetAddressTimeVersion,
337 BaseEncoding,
338 },
339 // Protocol version MultipleAddressVersion with no transactions.
340 {
341 noTx,
342 noTx,
343 noTxEncoded,
344 MultipleAddressVersion,
345 BaseEncoding,
346 },
347 // Protocol version MultipleAddressVersion with multiple transactions.
348 {
349 multiTx,
350 multiTx,
351 multiTxEncoded,
352 MultipleAddressVersion,
353 BaseEncoding,
354 },
355 }
356 t.Logf("Running %d tests", len(tests))
357 for i, test := range tests {
358 // Encode the message to wire format.
359 var buf bytes.Buffer
360 e := test.in.BtcEncode(&buf, test.pver, test.enc)
361 if e != nil {
362 t.Errorf("BtcEncode #%d error %v", i, e)
363 continue
364 }
365 if !bytes.Equal(buf.Bytes(), test.buf) {
366 t.Errorf("BtcEncode #%d\n got: %s want: %s", i,
367 spew.Sdump(buf.Bytes()), spew.Sdump(test.buf),
368 )
369 continue
370 }
371 // Decode the message from wire format.
372 var msg MsgTx
373 rbuf := bytes.NewReader(test.buf)
374 e = msg.BtcDecode(rbuf, test.pver, test.enc)
375 if e != nil {
376 t.Errorf("BtcDecode #%d error %v", i, e)
377 continue
378 }
379 if !reflect.DeepEqual(&msg, test.out) {
380 t.Errorf("BtcDecode #%d\n got: %s want: %s", i,
381 spew.Sdump(&msg), spew.Sdump(test.out),
382 )
383 continue
384 }
385 }
386 }
387
388 // TestTxWireErrors performs negative tests against wire encode and decode of MsgTx to confirm error paths work
389 // correctly.
390 func TestTxWireErrors(t *testing.T) {
391 // Use protocol version 60002 specifically here instead of the latest because the test data is using bytes encoded
392 // with that protocol version.
393 pver := uint32(60002)
394 tests := []struct {
395 in *MsgTx // value to encode
396 buf []byte // Wire encoding
397 pver uint32 // Protocol version for wire encoding
398 enc MessageEncoding // Message encoding format
399 max int // Max size of fixed buffer to induce errors
400 writeErr error // Expected write error
401 readErr error // Expected read error
402 }{
403 // Force error in version.
404 {multiTx, multiTxEncoded, pver, BaseEncoding, 0, io.ErrShortWrite, io.EOF},
405 // Force error in number of transaction inputs.
406 {multiTx, multiTxEncoded, pver, BaseEncoding, 4, io.ErrShortWrite, io.EOF},
407 // Force error in transaction input previous block hash.
408 {multiTx, multiTxEncoded, pver, BaseEncoding, 5, io.ErrShortWrite, io.EOF},
409 // Force error in transaction input previous block output index.
410 {multiTx, multiTxEncoded, pver, BaseEncoding, 37, io.ErrShortWrite, io.EOF},
411 // Force error in transaction input signature script length.
412 {multiTx, multiTxEncoded, pver, BaseEncoding, 41, io.ErrShortWrite, io.EOF},
413 // Force error in transaction input signature script.
414 {multiTx, multiTxEncoded, pver, BaseEncoding, 42, io.ErrShortWrite, io.EOF},
415 // Force error in transaction input sequence.
416 {multiTx, multiTxEncoded, pver, BaseEncoding, 49, io.ErrShortWrite, io.EOF},
417 // Force error in number of transaction outputs.
418 {multiTx, multiTxEncoded, pver, BaseEncoding, 53, io.ErrShortWrite, io.EOF},
419 // Force error in transaction output value.
420 {multiTx, multiTxEncoded, pver, BaseEncoding, 54, io.ErrShortWrite, io.EOF},
421 // Force error in transaction output pk script length.
422 {multiTx, multiTxEncoded, pver, BaseEncoding, 62, io.ErrShortWrite, io.EOF},
423 // Force error in transaction output pk script.
424 {multiTx, multiTxEncoded, pver, BaseEncoding, 63, io.ErrShortWrite, io.EOF},
425 // Force error in transaction output lock time.
426 {multiTx, multiTxEncoded, pver, BaseEncoding, 206, io.ErrShortWrite, io.EOF},
427 }
428 t.Logf("Running %d tests", len(tests))
429 for i, test := range tests {
430 // Encode to wire format.
431 w := newFixedWriter(test.max)
432 e := test.in.BtcEncode(w, test.pver, test.enc)
433 if e != test.writeErr {
434 t.Errorf("BtcEncode #%d wrong error got: %v, want: %v",
435 i, e, test.writeErr,
436 )
437 continue
438 }
439 // Decode from wire format.
440 var msg MsgTx
441 r := newFixedReader(test.max, test.buf)
442 e = msg.BtcDecode(r, test.pver, test.enc)
443 if e != test.readErr {
444 t.Errorf("BtcDecode #%d wrong error got: %v, want: %v",
445 i, e, test.readErr,
446 )
447 continue
448 }
449 }
450 }
451
452 // TestTxSerialize tests MsgTx serialize and deserialize.
453 func TestTxSerialize(t *testing.T) {
454 noTx := NewMsgTx(1)
455 noTx.Version = 1
456 noTxEncoded := []byte{
457 0x01, 0x00, 0x00, 0x00, // Version
458 0x00, // Varint for number of input transactions
459 0x00, // Varint for number of output transactions
460 0x00, 0x00, 0x00, 0x00, // Lock time
461 }
462 tests := []struct {
463 in *MsgTx // Message to encode
464 out *MsgTx // Expected decoded message
465 buf []byte // Serialized data
466 pkScriptLocs []int // Expected output script locations
467 witness bool // Serialize using the witness encoding
468 }{
469 // No transactions.
470 {
471 noTx,
472 noTx,
473 noTxEncoded,
474 nil,
475 false,
476 },
477 // Multiple transactions.
478 {
479 multiTx,
480 multiTx,
481 multiTxEncoded,
482 multiTxPkScriptLocs,
483 false,
484 },
485 // // Multiple outputs witness transaction.
486 // {
487 // multiWitnessTx,
488 // multiWitnessTx,
489 // multiWitnessTxEncoded,
490 // multiWitnessTxPkScriptLocs,
491 // true,
492 // },
493 }
494 t.Logf("Running %d tests", len(tests))
495 for i, test := range tests {
496 // Serialize the transaction.
497 var buf bytes.Buffer
498 e := test.in.Serialize(&buf)
499 if e != nil {
500 t.Errorf("Serialize #%d error %v", i, e)
501 continue
502 }
503 if !bytes.Equal(buf.Bytes(), test.buf) {
504 t.Errorf("Serialize #%d\n got: %s want: %s", i,
505 spew.Sdump(buf.Bytes()), spew.Sdump(test.buf),
506 )
507 continue
508 }
509 // Deserialize the transaction.
510 var tx MsgTx
511 rbuf := bytes.NewReader(test.buf)
512 if test.witness {
513 e = tx.Deserialize(rbuf)
514 } else {
515 e = tx.DeserializeNoWitness(rbuf)
516 }
517 if e != nil {
518 t.Errorf("Deserialize #%d error %v", i, e)
519 continue
520 }
521 if !reflect.DeepEqual(&tx, test.out) {
522 t.Errorf("Deserialize #%d\n got: %s want: %s", i,
523 spew.Sdump(&tx), spew.Sdump(test.out),
524 )
525 continue
526 }
527 // Ensure the public key script locations are accurate.
528 pkScriptLocs := test.in.PkScriptLocs()
529 if !reflect.DeepEqual(pkScriptLocs, test.pkScriptLocs) {
530 t.Errorf("PkScriptLocs #%d\n got: %s want: %s", i,
531 spew.Sdump(pkScriptLocs),
532 spew.Sdump(test.pkScriptLocs),
533 )
534 continue
535 }
536 for j, loc := range pkScriptLocs {
537 wantPkScript := test.in.TxOut[j].PkScript
538 gotPkScript := test.buf[loc : loc+len(wantPkScript)]
539 if !bytes.Equal(gotPkScript, wantPkScript) {
540 t.Errorf("PkScriptLocs #%d:%d\n unexpected "+
541 "script got: %s want: %s", i, j,
542 spew.Sdump(gotPkScript),
543 spew.Sdump(wantPkScript),
544 )
545 }
546 }
547 }
548 }
549
550 // TestTxSerializeErrors performs negative tests against wire encode and decode of MsgTx to confirm error paths work
551 // correctly.
552 func TestTxSerializeErrors(t *testing.T) {
553 tests := []struct {
554 in *MsgTx // value to encode
555 buf []byte // Serialized data
556 max int // Max size of fixed buffer to induce errors
557 writeErr error // Expected write error
558 readErr error // Expected read error
559 }{
560 // Force error in version.
561 {multiTx, multiTxEncoded, 0, io.ErrShortWrite, io.EOF},
562 // Force error in number of transaction inputs.
563 {multiTx, multiTxEncoded, 4, io.ErrShortWrite, io.EOF},
564 // Force error in transaction input previous block hash.
565 {multiTx, multiTxEncoded, 5, io.ErrShortWrite, io.EOF},
566 // Force error in transaction input previous block output index.
567 {multiTx, multiTxEncoded, 37, io.ErrShortWrite, io.EOF},
568 // Force error in transaction input signature script length.
569 {multiTx, multiTxEncoded, 41, io.ErrShortWrite, io.EOF},
570 // Force error in transaction input signature script.
571 {multiTx, multiTxEncoded, 42, io.ErrShortWrite, io.EOF},
572 // Force error in transaction input sequence.
573 {multiTx, multiTxEncoded, 49, io.ErrShortWrite, io.EOF},
574 // Force error in number of transaction outputs.
575 {multiTx, multiTxEncoded, 53, io.ErrShortWrite, io.EOF},
576 // Force error in transaction output value.
577 {multiTx, multiTxEncoded, 54, io.ErrShortWrite, io.EOF},
578 // Force error in transaction output pk script length.
579 {multiTx, multiTxEncoded, 62, io.ErrShortWrite, io.EOF},
580 // Force error in transaction output pk script.
581 {multiTx, multiTxEncoded, 63, io.ErrShortWrite, io.EOF},
582 // Force error in transaction output lock time.
583 {multiTx, multiTxEncoded, 206, io.ErrShortWrite, io.EOF},
584 }
585 t.Logf("Running %d tests", len(tests))
586 for i, test := range tests {
587 // Serialize the transaction.
588 w := newFixedWriter(test.max)
589 e := test.in.Serialize(w)
590 if e != test.writeErr {
591 t.Errorf("Serialize #%d wrong error got: %v, want: %v",
592 i, e, test.writeErr,
593 )
594 continue
595 }
596 // Deserialize the transaction.
597 var tx MsgTx
598 r := newFixedReader(test.max, test.buf)
599 e = tx.Deserialize(r)
600 if e != test.readErr {
601 t.Errorf("Deserialize #%d wrong error got: %v, want: %v",
602 i, e, test.readErr,
603 )
604 continue
605 }
606 }
607 }
608
609 // TestTxOverflowErrors performs tests to ensure deserializing transactions which are intentionally crafted to use large
610 // values for the variable number of inputs and outputs are handled properly. This could otherwise potentially be used
611 // as an attack vector.
612 func TestTxOverflowErrors(t *testing.T) {
613 // Use protocol version 70001 and transaction version 1 specifically here instead of the latest values because the
614 // test data is using bytes encoded with those versions.
615 pver := uint32(70001)
616 txVer := uint32(1)
617 tests := []struct {
618 buf []byte // Wire encoding
619 pver uint32 // Protocol version for wire encoding
620 enc MessageEncoding // Message encoding format
621 version uint32 // Transaction version
622 e error // Expected error
623 }{
624 // Transaction that claims to have ~uint64(0) inputs.
625 {
626 []byte{
627 0x00, 0x00, 0x00, 0x01, // Version
628 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff,
629 0xff, // Varint for number of input transactions
630 }, pver, BaseEncoding, txVer, &MessageError{},
631 },
632 // Transaction that claims to have ~uint64(0) outputs.
633 {
634 []byte{
635 0x00, 0x00, 0x00, 0x01, // Version
636 0x00, // Varint for number of input transactions
637 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff,
638 0xff, // Varint for number of output transactions
639 }, pver, BaseEncoding, txVer, &MessageError{},
640 },
641 // Transaction that has an input with a signature script that claims to have ~uint64(0) length.
642 {
643 []byte{
644 0x00, 0x00, 0x00, 0x01, // Version
645 0x01, // Varint for number of input transactions
646 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00,
647 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00,
648 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00,
649 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, // Previous output hash
650 0xff, 0xff, 0xff, 0xff, // Prevous output index
651 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff,
652 0xff, // Varint for length of signature script
653 }, pver, BaseEncoding, txVer, &MessageError{},
654 },
655 // Transaction that has an output with a public key script that claims to have ~uint64(0) length.
656 {
657 []byte{
658 0x00, 0x00, 0x00, 0x01, // Version
659 0x01, // Varint for number of input transactions
660 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00,
661 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00,
662 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00,
663 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, // Previous output hash
664 0xff, 0xff, 0xff, 0xff, // Prevous output index
665 0x00, // Varint for length of signature script
666 0xff, 0xff, 0xff, 0xff, // Sequence
667 0x01, // Varint for number of output transactions
668 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, // Transaction amount
669 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff,
670 0xff, // Varint for length of public key script
671 }, pver, BaseEncoding, txVer, &MessageError{},
672 },
673 }
674 t.Logf("Running %d tests", len(tests))
675 for i, test := range tests {
676 // Decode from wire format.
677 var msg MsgTx
678 r := bytes.NewReader(test.buf)
679 e := msg.BtcDecode(r, test.pver, test.enc)
680 if reflect.TypeOf(e) != reflect.TypeOf(test.e) {
681 t.Errorf("BtcDecode #%d wrong error got: %v, want: %v",
682 i, e, reflect.TypeOf(test.e),
683 )
684 continue
685 }
686 // Decode from wire format.
687 r = bytes.NewReader(test.buf)
688 e = msg.Deserialize(r)
689 if reflect.TypeOf(e) != reflect.TypeOf(test.e) {
690 t.Errorf("Deserialize #%d wrong error got: %v, want: %v",
691 i, e, reflect.TypeOf(test.e),
692 )
693 continue
694 }
695 }
696 }
697
698 // TestTxSerializeSizeStripped performs tests to ensure the serialize size for various transactions is accurate.
699 func TestTxSerializeSizeStripped(t *testing.T) {
700 // Empty tx message.
701 noTx := NewMsgTx(1)
702 noTx.Version = 1
703 tests := []struct {
704 in *MsgTx // Tx to encode
705 size int // Expected serialized size
706 }{
707 // No inputs or outpus.
708 {noTx, 10},
709 // Transcaction with an input and an output.
710 {multiTx, 210},
711 // Transaction with an input which includes witness data, and one output. Note
712 // that this uses SerializeSizeStripped which excludes the additional bytes due
713 // to witness data encoding.
714 {multiWitnessTx, 82},
715 }
716 t.Logf("Running %d tests", len(tests))
717 for i, test := range tests {
718 serializedSize := test.in.SerializeSizeStripped()
719 if serializedSize != test.size {
720 t.Errorf("MsgTx.SerializeSizeStripped: #%d got: %d, want: %d", i,
721 serializedSize, test.size,
722 )
723 continue
724 }
725 }
726 }
727
728 // TestTxWitnessSize performs tests to ensure that the serialized size for
729 // various types of transactions that include witness data is accurate.
730 func TestTxWitnessSize(t *testing.T) {
731 tests := []struct {
732 in *MsgTx // Tx to encode
733 size int // Expected serialized size w/ witnesses
734 }{
735 // Transaction with an input which includes witness data, and one output.
736 {multiWitnessTx, 190},
737 }
738 t.Logf("Running %d tests", len(tests))
739 for i, test := range tests {
740 serializedSize := test.in.SerializeSize()
741 if serializedSize != test.size {
742 t.Errorf("MsgTx.SerializeSize: #%d got: %d, want: %d", i,
743 serializedSize, test.size,
744 )
745 continue
746 }
747 }
748 }
749
750 // multiTx is a MsgTx with an input and output and used in various tests.
751 var multiTx = &MsgTx{
752 Version: 1,
753 TxIn: []*TxIn{
754 {
755 PreviousOutPoint: OutPoint{
756 Hash: chainhash.Hash{},
757 Index: 0xffffffff,
758 },
759 SignatureScript: []byte{
760 0x04, 0x31, 0xdc, 0x00, 0x1b, 0x01, 0x62,
761 },
762 Sequence: 0xffffffff,
763 },
764 },
765 TxOut: []*TxOut{
766 {
767 Value: 0x12a05f200,
768 PkScript: []byte{
769 0x41, // OP_DATA_65
770 0x04, 0xd6, 0x4b, 0xdf, 0xd0, 0x9e, 0xb1, 0xc5,
771 0xfe, 0x29, 0x5a, 0xbd, 0xeb, 0x1d, 0xca, 0x42,
772 0x81, 0xbe, 0x98, 0x8e, 0x2d, 0xa0, 0xb6, 0xc1,
773 0xc6, 0xa5, 0x9d, 0xc2, 0x26, 0xc2, 0x86, 0x24,
774 0xe1, 0x81, 0x75, 0xe8, 0x51, 0xc9, 0x6b, 0x97,
775 0x3d, 0x81, 0xb0, 0x1c, 0xc3, 0x1f, 0x04, 0x78,
776 0x34, 0xbc, 0x06, 0xd6, 0xd6, 0xed, 0xf6, 0x20,
777 0xd1, 0x84, 0x24, 0x1a, 0x6a, 0xed, 0x8b, 0x63,
778 0xa6, // 65-byte signature
779 0xac, // OP_CHECKSIG
780 },
781 },
782 {
783 Value: 0x5f5e100,
784 PkScript: []byte{
785 0x41, // OP_DATA_65
786 0x04, 0xd6, 0x4b, 0xdf, 0xd0, 0x9e, 0xb1, 0xc5,
787 0xfe, 0x29, 0x5a, 0xbd, 0xeb, 0x1d, 0xca, 0x42,
788 0x81, 0xbe, 0x98, 0x8e, 0x2d, 0xa0, 0xb6, 0xc1,
789 0xc6, 0xa5, 0x9d, 0xc2, 0x26, 0xc2, 0x86, 0x24,
790 0xe1, 0x81, 0x75, 0xe8, 0x51, 0xc9, 0x6b, 0x97,
791 0x3d, 0x81, 0xb0, 0x1c, 0xc3, 0x1f, 0x04, 0x78,
792 0x34, 0xbc, 0x06, 0xd6, 0xd6, 0xed, 0xf6, 0x20,
793 0xd1, 0x84, 0x24, 0x1a, 0x6a, 0xed, 0x8b, 0x63,
794 0xa6, // 65-byte signature
795 0xac, // OP_CHECKSIG
796 },
797 },
798 },
799 LockTime: 0,
800 }
801
802 // multiTxEncoded is the wire encoded bytes for multiTx using protocol version 60002 and is used in the various tests.
803 var multiTxEncoded = []byte{
804 0x01, 0x00, 0x00, 0x00, // Version
805 0x01, // Varint for number of input transactions
806 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00,
807 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00,
808 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00,
809 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, // Previous output hash
810 0xff, 0xff, 0xff, 0xff, // Prevous output index
811 0x07, // Varint for length of signature script
812 0x04, 0x31, 0xdc, 0x00, 0x1b, 0x01, 0x62, // Signature script
813 0xff, 0xff, 0xff, 0xff, // Sequence
814 0x02, // Varint for number of output transactions
815 0x00, 0xf2, 0x05, 0x2a, 0x01, 0x00, 0x00, 0x00, // Transaction amount
816 0x43, // Varint for length of pk script
817 0x41, // OP_DATA_65
818 0x04, 0xd6, 0x4b, 0xdf, 0xd0, 0x9e, 0xb1, 0xc5,
819 0xfe, 0x29, 0x5a, 0xbd, 0xeb, 0x1d, 0xca, 0x42,
820 0x81, 0xbe, 0x98, 0x8e, 0x2d, 0xa0, 0xb6, 0xc1,
821 0xc6, 0xa5, 0x9d, 0xc2, 0x26, 0xc2, 0x86, 0x24,
822 0xe1, 0x81, 0x75, 0xe8, 0x51, 0xc9, 0x6b, 0x97,
823 0x3d, 0x81, 0xb0, 0x1c, 0xc3, 0x1f, 0x04, 0x78,
824 0x34, 0xbc, 0x06, 0xd6, 0xd6, 0xed, 0xf6, 0x20,
825 0xd1, 0x84, 0x24, 0x1a, 0x6a, 0xed, 0x8b, 0x63,
826 0xa6, // 65-byte signature
827 0xac, // OP_CHECKSIG
828 0x00, 0xe1, 0xf5, 0x05, 0x00, 0x00, 0x00, 0x00, // Transaction amount
829 0x43, // Varint for length of pk script
830 0x41, // OP_DATA_65
831 0x04, 0xd6, 0x4b, 0xdf, 0xd0, 0x9e, 0xb1, 0xc5,
832 0xfe, 0x29, 0x5a, 0xbd, 0xeb, 0x1d, 0xca, 0x42,
833 0x81, 0xbe, 0x98, 0x8e, 0x2d, 0xa0, 0xb6, 0xc1,
834 0xc6, 0xa5, 0x9d, 0xc2, 0x26, 0xc2, 0x86, 0x24,
835 0xe1, 0x81, 0x75, 0xe8, 0x51, 0xc9, 0x6b, 0x97,
836 0x3d, 0x81, 0xb0, 0x1c, 0xc3, 0x1f, 0x04, 0x78,
837 0x34, 0xbc, 0x06, 0xd6, 0xd6, 0xed, 0xf6, 0x20,
838 0xd1, 0x84, 0x24, 0x1a, 0x6a, 0xed, 0x8b, 0x63,
839 0xa6, // 65-byte signature
840 0xac, // OP_CHECKSIG
841 0x00, 0x00, 0x00, 0x00, // Lock time
842 }
843
844 // multiTxPkScriptLocs is the location information for the public key scripts located in multiTx.
845 var multiTxPkScriptLocs = []int{63, 139}
846
847 // multiWitnessTx is a MsgTx with an input with witness data, and an output used in various tests.
848 var multiWitnessTx = &MsgTx{
849 Version: 1,
850 TxIn: []*TxIn{
851 {
852 PreviousOutPoint: OutPoint{
853 Hash: chainhash.Hash{
854 0xa5, 0x33, 0x52, 0xd5, 0x13, 0x57, 0x66, 0xf0,
855 0x30, 0x76, 0x59, 0x74, 0x18, 0x26, 0x3d, 0xa2,
856 0xd9, 0xc9, 0x58, 0x31, 0x59, 0x68, 0xfe, 0xa8,
857 0x23, 0x52, 0x94, 0x67, 0x48, 0x1f, 0xf9, 0xcd,
858 },
859 Index: 19,
860 },
861 SignatureScript: []byte{},
862 // Witness: [][]byte{
863 // { // 70-byte signature
864 // 0x30, 0x43, 0x02, 0x1f, 0x4d, 0x23, 0x81, 0xdc,
865 // 0x97, 0xf1, 0x82, 0xab, 0xd8, 0x18, 0x5f, 0x51,
866 // 0x75, 0x30, 0x18, 0x52, 0x32, 0x12, 0xf5, 0xdd,
867 // 0xc0, 0x7c, 0xc4, 0xe6, 0x3a, 0x8d, 0xc0, 0x36,
868 // 0x58, 0xda, 0x19, 0x02, 0x20, 0x60, 0x8b, 0x5c,
869 // 0x4d, 0x92, 0xb8, 0x6b, 0x6d, 0xe7, 0xd7, 0x8e,
870 // 0xf2, 0x3a, 0x2f, 0xa7, 0x35, 0xbc, 0xb5, 0x9b,
871 // 0x91, 0x4a, 0x48, 0xb0, 0xe1, 0x87, 0xc5, 0xe7,
872 // 0x56, 0x9a, 0x18, 0x19, 0x70, 0x01,
873 // },
874 // { // 33-byte serialize pub key
875 // 0x03, 0x07, 0xea, 0xd0, 0x84, 0x80, 0x7e, 0xb7,
876 // 0x63, 0x46, 0xdf, 0x69, 0x77, 0x00, 0x0c, 0x89,
877 // 0x39, 0x2f, 0x45, 0xc7, 0x64, 0x25, 0xb2, 0x61,
878 // 0x81, 0xf5, 0x21, 0xd7, 0xf3, 0x70, 0x06, 0x6a,
879 // 0x8f,
880 // },
881 // },
882 Sequence: 0xffffffff,
883 },
884 },
885 TxOut: []*TxOut{
886 {
887 Value: 395019,
888 PkScript: []byte{ // p2wkh output
889 0x00, // Version 0 witness program
890 0x14, // OP_DATA_20
891 0x9d, 0xda, 0xc6, 0xf3, 0x9d, 0x51, 0xe0, 0x39,
892 0x8e, 0x53, 0x2a, 0x22, 0xc4, 0x1b, 0xa1, 0x89,
893 0x40, 0x6a, 0x85, 0x23, // 20-byte pub key hash
894 },
895 },
896 },
897 }
898
899 // multiWitnessTxEncoded is the wire encoded bytes for multiWitnessTx including
900 // inputs with witness data using protocol version 70012 and is used in the
901 // various tests.
902 var multiWitnessTxEncoded = []byte{
903 0x1, 0x0, 0x0, 0x0, // Version
904 0x0, // Marker byte indicating 0 inputs, or a segwit encoded tx
905 0x1, // Flag byte
906 0x1, // Varint for number of inputs
907 0xa5, 0x33, 0x52, 0xd5, 0x13, 0x57, 0x66, 0xf0,
908 0x30, 0x76, 0x59, 0x74, 0x18, 0x26, 0x3d, 0xa2,
909 0xd9, 0xc9, 0x58, 0x31, 0x59, 0x68, 0xfe, 0xa8,
910 0x23, 0x52, 0x94, 0x67, 0x48, 0x1f, 0xf9, 0xcd, // Previous output hash
911 0x13, 0x0, 0x0, 0x0, // Little endian previous output index
912 0x0, // No sig script (this is a witness input)
913 0xff, 0xff, 0xff, 0xff, // Sequence
914 0x1, // Varint for number of outputs
915 0xb, 0x7, 0x6, 0x0, 0x0, 0x0, 0x0, 0x0, // Output amount
916 0x16, // Varint for length of pk script
917 0x0, // Version 0 witness program
918 0x14, // OP_DATA_20
919 0x9d, 0xda, 0xc6, 0xf3, 0x9d, 0x51, 0xe0, 0x39,
920 0x8e, 0x53, 0x2a, 0x22, 0xc4, 0x1b, 0xa1, 0x89,
921 0x40, 0x6a, 0x85, 0x23, // 20-byte pub key hash
922 0x2, // Two items on the witness stack
923 0x46, // 70 byte stack item
924 0x30, 0x43, 0x2, 0x1f, 0x4d, 0x23, 0x81, 0xdc,
925 0x97, 0xf1, 0x82, 0xab, 0xd8, 0x18, 0x5f, 0x51,
926 0x75, 0x30, 0x18, 0x52, 0x32, 0x12, 0xf5, 0xdd,
927 0xc0, 0x7c, 0xc4, 0xe6, 0x3a, 0x8d, 0xc0, 0x36,
928 0x58, 0xda, 0x19, 0x2, 0x20, 0x60, 0x8b, 0x5c,
929 0x4d, 0x92, 0xb8, 0x6b, 0x6d, 0xe7, 0xd7, 0x8e,
930 0xf2, 0x3a, 0x2f, 0xa7, 0x35, 0xbc, 0xb5, 0x9b,
931 0x91, 0x4a, 0x48, 0xb0, 0xe1, 0x87, 0xc5, 0xe7,
932 0x56, 0x9a, 0x18, 0x19, 0x70, 0x1,
933 0x21, // 33 byte stack item
934 0x3, 0x7, 0xea, 0xd0, 0x84, 0x80, 0x7e, 0xb7,
935 0x63, 0x46, 0xdf, 0x69, 0x77, 0x0, 0xc, 0x89,
936 0x39, 0x2f, 0x45, 0xc7, 0x64, 0x25, 0xb2, 0x61,
937 0x81, 0xf5, 0x21, 0xd7, 0xf3, 0x70, 0x6, 0x6a,
938 0x8f,
939 0x0, 0x0, 0x0, 0x0, // Lock time
940 }
941
942 // // multiWitnessTxEncodedNonZeroFlag is an incorrect wire encoded bytes for multiWitnessTx including inputs with witness
943 // // data. Instead of the flag byte being set to 0x01, the flag is 0x00, which should trigger a decoding error.
944 // var multiWitnessTxEncodedNonZeroFlag = []byte{
945 // 0x1, 0x0, 0x0, 0x0, // Version
946 // 0x0, // Marker byte indicating 0 inputs, or a segwit encoded tx
947 // 0x0, // Incorrect flag byte (should be 0x01)
948 // 0x1, // Varint for number of inputs
949 // 0xa5, 0x33, 0x52, 0xd5, 0x13, 0x57, 0x66, 0xf0,
950 // 0x30, 0x76, 0x59, 0x74, 0x18, 0x26, 0x3d, 0xa2,
951 // 0xd9, 0xc9, 0x58, 0x31, 0x59, 0x68, 0xfe, 0xa8,
952 // 0x23, 0x52, 0x94, 0x67, 0x48, 0x1f, 0xf9, 0xcd, // Previous output hash
953 // 0x13, 0x0, 0x0, 0x0, // Little endian previous output index
954 // 0x0, // No sig script (this is a witness input)
955 // 0xff, 0xff, 0xff, 0xff, // Sequence
956 // 0x1, // Varint for number of outputs
957 // 0xb, 0x7, 0x6, 0x0, 0x0, 0x0, 0x0, 0x0, // Output amount
958 // 0x16, // Varint for length of pk script
959 // 0x0, // Version 0 witness program
960 // 0x14, // OP_DATA_20
961 // 0x9d, 0xda, 0xc6, 0xf3, 0x9d, 0x51, 0xe0, 0x39,
962 // 0x8e, 0x53, 0x2a, 0x22, 0xc4, 0x1b, 0xa1, 0x89,
963 // 0x40, 0x6a, 0x85, 0x23, // 20-byte pub key hash
964 // 0x2, // Two items on the witness stack
965 // 0x46, // 70 byte stack item
966 // 0x30, 0x43, 0x2, 0x1f, 0x4d, 0x23, 0x81, 0xdc,
967 // 0x97, 0xf1, 0x82, 0xab, 0xd8, 0x18, 0x5f, 0x51,
968 // 0x75, 0x30, 0x18, 0x52, 0x32, 0x12, 0xf5, 0xdd,
969 // 0xc0, 0x7c, 0xc4, 0xe6, 0x3a, 0x8d, 0xc0, 0x36,
970 // 0x58, 0xda, 0x19, 0x2, 0x20, 0x60, 0x8b, 0x5c,
971 // 0x4d, 0x92, 0xb8, 0x6b, 0x6d, 0xe7, 0xd7, 0x8e,
972 // 0xf2, 0x3a, 0x2f, 0xa7, 0x35, 0xbc, 0xb5, 0x9b,
973 // 0x91, 0x4a, 0x48, 0xb0, 0xe1, 0x87, 0xc5, 0xe7,
974 // 0x56, 0x9a, 0x18, 0x19, 0x70, 0x1,
975 // 0x21, // 33 byte stack item
976 // 0x3, 0x7, 0xea, 0xd0, 0x84, 0x80, 0x7e, 0xb7,
977 // 0x63, 0x46, 0xdf, 0x69, 0x77, 0x0, 0xc, 0x89,
978 // 0x39, 0x2f, 0x45, 0xc7, 0x64, 0x25, 0xb2, 0x61,
979 // 0x81, 0xf5, 0x21, 0xd7, 0xf3, 0x70, 0x6, 0x6a,
980 // 0x8f,
981 // 0x0, 0x0, 0x0, 0x0, // Lock time
982 // }
983 // // multiTxPkScriptLocs is the location information for the public key scripts located in multiWitnessTx.
984 // var multiWitnessTxPkScriptLocs = []int{58}
985