1 package txscript
2 3 import (
4 "bytes"
5 "encoding/hex"
6 "encoding/json"
7 "errors"
8 "fmt"
9 "github.com/p9c/p9/pkg/amt"
10 "io/ioutil"
11 "strconv"
12 "strings"
13 "testing"
14 15 "github.com/p9c/p9/pkg/chainhash"
16 "github.com/p9c/p9/pkg/util"
17 "github.com/p9c/p9/pkg/wire"
18 )
19 20 // scriptTestName returns a descriptive test name for the given reference script test data.
21 func scriptTestName(test []interface{}) (string, error) {
22 // Account for any optional leading witness data.
23 var witnessOffset int
24 if _, ok := test[0].([]interface{}); ok {
25 witnessOffset++
26 }
27 // In addition to the optional leading witness data, the test must consist of at
28 // least a signature script, public key script, flags, and expected error.
29 // Finally, it may optionally contain a comment.
30 if len(test) < witnessOffset+4 || len(test) > witnessOffset+5 {
31 return "", fmt.Errorf("invalid test length %d", len(test))
32 }
33 // Use the comment for the test name if one is specified, otherwise, construct the name based on the signature
34 // script, public key script, and flags.
35 var name string
36 if len(test) == witnessOffset+5 {
37 name = fmt.Sprintf("test (%s)", test[witnessOffset+4])
38 } else {
39 name = fmt.Sprintf(
40 "test ([%s, %s, %s])", test[witnessOffset],
41 test[witnessOffset+1], test[witnessOffset+2],
42 )
43 }
44 return name, nil
45 }
46 47 // parse hex string into a []byte.
48 func parseHex(tok string) ([]byte, error) {
49 if !strings.HasPrefix(tok, "0x") {
50 return nil, errors.New("not a hex number")
51 }
52 return hex.DecodeString(tok[2:])
53 }
54 55 // parseWitnessStack parses a json array of witness items encoded as hex into a
56 // slice of witness elements.
57 func parseWitnessStack(elements []interface{}) ([][]byte, error) {
58 witness := make([][]byte, len(elements))
59 for i, e := range elements {
60 witElement, e := hex.DecodeString(e.(string))
61 if e != nil {
62 return nil, e
63 }
64 witness[i] = witElement
65 }
66 return witness, nil
67 }
68 69 // shortFormOps holds a map of opcode names to values for use in short form parsing. It is declared here so it only
70 // needs to be created once.
71 var shortFormOps map[string]byte
72 73 // parseShortForm parses a string as as used in the Bitcoin Core reference tests into the script it came from.
74 //
75 // The format used for these tests is pretty simple if ad-hoc:
76 //
77 // - Opcodes other than the push opcodes and unknown are present as either OP_NAME or just NAME
78 // - Plain numbers are made into push operations
79 // - Numbers beginning with 0x are inserted into the []byte as-is (so 0x14 is OP_DATA_20)
80 // - Single quoted strings are pushed as data
81 // - Anything else is an error
82 func parseShortForm(script string) ([]byte, error) {
83 // Only create the short form opcode map once.
84 if shortFormOps == nil {
85 ops := make(map[string]byte)
86 for opcodeName, opcodeValue := range OpcodeByName {
87 if strings.Contains(opcodeName, "OP_UNKNOWN") {
88 continue
89 }
90 ops[opcodeName] = opcodeValue
91 // The opcodes named OP_# can't have the OP_ prefix stripped or they would conflict with the plain numbers.
92 // Also, since OP_FALSE and OP_TRUE are aliases for the OP_0, and OP_1, respectively, they have the same
93 // value, so detect those by name and allow them.
94 if (opcodeName == "OP_FALSE" || opcodeName == "OP_TRUE") ||
95 (opcodeValue != OP_0 && (opcodeValue < OP_1 ||
96 opcodeValue > OP_16)) {
97 ops[strings.TrimPrefix(opcodeName, "OP_")] = opcodeValue
98 }
99 }
100 shortFormOps = ops
101 }
102 // Split only does one separator so convert all \n and tab into space.
103 script = strings.Replace(script, "\n", " ", -1)
104 script = strings.Replace(script, "\t", " ", -1)
105 tokens := strings.Split(script, " ")
106 builder := NewScriptBuilder()
107 for _, tok := range tokens {
108 if len(tok) == 0 {
109 continue
110 }
111 // if parses as a plain number
112 if num, e := strconv.ParseInt(tok, 10, 64); e == nil {
113 builder.AddInt64(num)
114 continue
115 } else if bts, e := parseHex(tok); e == nil {
116 // Concatenate the bytes manually since the test code intentionally creates scripts that are too large and
117 // would cause the builder to error otherwise.
118 if builder.err == nil {
119 builder.script = append(builder.script, bts...)
120 }
121 } else if len(tok) >= 2 &&
122 tok[0] == '\'' && tok[len(tok)-1] == '\'' {
123 builder.AddFullData([]byte(tok[1 : len(tok)-1]))
124 } else if opcode, ok := shortFormOps[tok]; ok {
125 builder.AddOp(opcode)
126 } else {
127 return nil, fmt.Errorf("bad token %q", tok)
128 }
129 }
130 return builder.Script()
131 }
132 133 // parseScriptFlags parses the provided flags string from the format used in the reference tests into ScriptFlags
134 // suitable for use in the script engine.
135 func parseScriptFlags(flagStr string) (ScriptFlags, error) {
136 var flags ScriptFlags
137 sFlags := strings.Split(flagStr, ",")
138 for _, flag := range sFlags {
139 switch flag {
140 case "":
141 // Nothing.
142 case "CHECKLOCKTIMEVERIFY":
143 flags |= ScriptVerifyCheckLockTimeVerify
144 case "CHECKSEQUENCEVERIFY":
145 flags |= ScriptVerifyCheckSequenceVerify
146 case "CLEANSTACK":
147 flags |= ScriptVerifyCleanStack
148 case "DERSIG":
149 flags |= ScriptVerifyDERSignatures
150 case "DISCOURAGE_UPGRADABLE_NOPS":
151 flags |= ScriptDiscourageUpgradableNops
152 case "LOW_S":
153 flags |= ScriptVerifyLowS
154 case "MINIMALDATA":
155 flags |= ScriptVerifyMinimalData
156 case "NONE":
157 // Nothing.
158 case "NULLDUMMY":
159 flags |= ScriptStrictMultiSig
160 case "NULLFAIL":
161 flags |= ScriptVerifyNullFail
162 case "P2SH":
163 flags |= ScriptBip16
164 case "SIGPUSHONLY":
165 flags |= ScriptVerifySigPushOnly
166 case "STRICTENC":
167 flags |= ScriptVerifyStrictEncoding
168 case "WITNESS":
169 flags |= ScriptVerifyWitness
170 case "DISCOURAGE_UPGRADABLE_WITNESS_PROGRAM":
171 flags |= ScriptVerifyDiscourageUpgradeableWitnessProgram
172 case "MINIMALIF":
173 flags |= ScriptVerifyMinimalIf
174 case "WITNESS_PUBKEYTYPE":
175 flags |= ScriptVerifyWitnessPubKeyType
176 default:
177 return flags, fmt.Errorf("invalid flag: %s", flag)
178 }
179 }
180 return flags, nil
181 }
182 183 // parseExpectedResult parses the provided expected result string into allowed script error codes. An error is returned
184 // if the expected result string is not supported.
185 func parseExpectedResult(expected string) ([]ErrorCode, error) {
186 switch expected {
187 case "OK":
188 return nil, nil
189 case "UNKNOWN_ERROR":
190 return []ErrorCode{ErrNumberTooBig, ErrMinimalData}, nil
191 case "PUBKEYTYPE":
192 return []ErrorCode{ErrPubKeyType}, nil
193 case "SIG_DER":
194 return []ErrorCode{
195 ErrSigTooShort, ErrSigTooLong,
196 ErrSigInvalidSeqID, ErrSigInvalidDataLen, ErrSigMissingSTypeID,
197 ErrSigMissingSLen, ErrSigInvalidSLen,
198 ErrSigInvalidRIntID, ErrSigZeroRLen, ErrSigNegativeR,
199 ErrSigTooMuchRPadding, ErrSigInvalidSIntID,
200 ErrSigZeroSLen, ErrSigNegativeS, ErrSigTooMuchSPadding,
201 ErrInvalidSigHashType,
202 }, nil
203 case "EVAL_FALSE":
204 return []ErrorCode{ErrEvalFalse, ErrEmptyStack}, nil
205 case "EQUALVERIFY":
206 return []ErrorCode{ErrEqualVerify}, nil
207 case "NULLFAIL":
208 return []ErrorCode{ErrNullFail}, nil
209 case "SIG_HIGH_S":
210 return []ErrorCode{ErrSigHighS}, nil
211 case "SIG_HASHTYPE":
212 return []ErrorCode{ErrInvalidSigHashType}, nil
213 case "SIG_NULLDUMMY":
214 return []ErrorCode{ErrSigNullDummy}, nil
215 case "SIG_PUSHONLY":
216 return []ErrorCode{ErrNotPushOnly}, nil
217 case "CLEANSTACK":
218 return []ErrorCode{ErrCleanStack}, nil
219 case "BAD_OPCODE":
220 return []ErrorCode{ErrReservedOpcode, ErrMalformedPush}, nil
221 case "UNBALANCED_CONDITIONAL":
222 return []ErrorCode{
223 ErrUnbalancedConditional,
224 ErrInvalidStackOperation,
225 }, nil
226 case "OP_RETURN":
227 return []ErrorCode{ErrEarlyReturn}, nil
228 case "VERIFY":
229 return []ErrorCode{ErrVerify}, nil
230 case "INVALID_STACK_OPERATION", "INVALID_ALTSTACK_OPERATION":
231 return []ErrorCode{ErrInvalidStackOperation}, nil
232 case "DISABLED_OPCODE":
233 return []ErrorCode{ErrDisabledOpcode}, nil
234 case "DISCOURAGE_UPGRADABLE_NOPS":
235 return []ErrorCode{ErrDiscourageUpgradableNOPs}, nil
236 case "PUSH_SIZE":
237 return []ErrorCode{ErrElementTooBig}, nil
238 case "OP_COUNT":
239 return []ErrorCode{ErrTooManyOperations}, nil
240 case "STACK_SIZE":
241 return []ErrorCode{ErrStackOverflow}, nil
242 case "SCRIPT_SIZE":
243 return []ErrorCode{ErrScriptTooBig}, nil
244 case "PUBKEY_COUNT":
245 return []ErrorCode{ErrInvalidPubKeyCount}, nil
246 case "SIG_COUNT":
247 return []ErrorCode{ErrInvalidSignatureCount}, nil
248 case "MINIMALDATA":
249 return []ErrorCode{ErrMinimalData}, nil
250 case "NEGATIVE_LOCKTIME":
251 return []ErrorCode{ErrNegativeLockTime}, nil
252 case "UNSATISFIED_LOCKTIME":
253 return []ErrorCode{ErrUnsatisfiedLockTime}, nil
254 case "MINIMALIF":
255 return []ErrorCode{ErrMinimalIf}, nil
256 case "DISCOURAGE_UPGRADABLE_WITNESS_PROGRAM":
257 return []ErrorCode{ErrDiscourageUpgradableWitnessProgram}, nil
258 case "WITNESS_PROGRAM_WRONG_LENGTH":
259 return []ErrorCode{ErrWitnessProgramWrongLength}, nil
260 case "WITNESS_PROGRAM_WITNESS_EMPTY":
261 return []ErrorCode{ErrWitnessProgramEmpty}, nil
262 case "WITNESS_PROGRAM_MISMATCH":
263 return []ErrorCode{ErrWitnessProgramMismatch}, nil
264 case "WITNESS_MALLEATED":
265 return []ErrorCode{ErrWitnessMalleated}, nil
266 case "WITNESS_MALLEATED_P2SH":
267 return []ErrorCode{ErrWitnessMalleatedP2SH}, nil
268 case "WITNESS_UNEXPECTED":
269 return []ErrorCode{ErrWitnessUnexpected}, nil
270 case "WITNESS_PUBKEYTYPE":
271 return []ErrorCode{ErrWitnessPubKeyType}, nil
272 }
273 return nil, fmt.Errorf(
274 "unrecognized expected result in test data: %v",
275 expected,
276 )
277 }
278 279 // createSpendTx generates a basic spending transaction given the passed
280 // signature, witness and public key scripts.
281 func createSpendingTx(
282 witness [][]byte, sigScript, pkScript []byte,
283 outputValue int64,
284 ) *wire.MsgTx {
285 coinbaseTx := wire.NewMsgTx(wire.TxVersion)
286 outPoint := wire.NewOutPoint(&chainhash.Hash{}, ^uint32(0))
287 txIn := wire.NewTxIn(outPoint, []byte{OP_0, OP_0}, nil)
288 txOut := wire.NewTxOut(outputValue, pkScript)
289 coinbaseTx.AddTxIn(txIn)
290 coinbaseTx.AddTxOut(txOut)
291 spendingTx := wire.NewMsgTx(wire.TxVersion)
292 coinbaseTxSha := coinbaseTx.TxHash()
293 outPoint = wire.NewOutPoint(&coinbaseTxSha, 0)
294 txIn = wire.NewTxIn(outPoint, sigScript, witness)
295 txOut = wire.NewTxOut(outputValue, nil)
296 spendingTx.AddTxIn(txIn)
297 spendingTx.AddTxOut(txOut)
298 return spendingTx
299 }
300 301 // scriptWithInputVal wraps a target pkScript with the value of the output in
302 // which it is contained. The inputVal is necessary in order to properly
303 // validate inputs which spend nested, or native witness programs.
304 type scriptWithInputVal struct {
305 inputVal int64
306 pkScript []byte
307 }
308 309 // testScripts ensures all of the passed script tests execute with the expected results with or without using a
310 // signature cache, as specified by the parameter.
311 func testScripts(t *testing.T, tests [][]interface{}, useSigCache bool) {
312 // Create a signature cache to use only if requested.
313 var sigCache *SigCache
314 if useSigCache {
315 sigCache = NewSigCache(10)
316 }
317 for i, test := range tests {
318 // "Format is: [[wit..., amount]?, scriptSig, scriptPubKey,
319 // flags, expected_scripterror, ... comments]"
320 // Skip single line comments.
321 if len(test) == 1 {
322 continue
323 }
324 // Construct a name for the test based on the comment and test data.
325 name, e := scriptTestName(test)
326 if e != nil {
327 t.Errorf("TestScripts: invalid test #%d: %v", i, e)
328 continue
329 }
330 var (
331 witness wire.TxWitness
332 inputAmt amt.Amount
333 )
334 // When the first field of the test data is a slice it contains witness data and
335 // everything else is offset by 1 as a result.
336 witnessOffset := 0
337 if witnessData, ok := test[0].([]interface{}); ok {
338 witnessOffset++
339 // If this is a witness test, then the final element within the slice is the
340 // input amount, so we ignore all but the last element in order to parse the
341 // witness stack.
342 strWitnesses := witnessData[:len(witnessData)-1]
343 witness, e = parseWitnessStack(strWitnesses)
344 if e != nil {
345 t.Errorf("%s: can't parse witness; %v", name, e)
346 continue
347 }
348 inputAmt, e = amt.NewAmount(witnessData[len(witnessData)-1].(float64))
349 if e != nil {
350 t.Errorf(
351 "%s: can't parse input amt: %v",
352 name, e,
353 )
354 continue
355 }
356 }
357 // Extract and parse the signature script from the test fields.
358 scriptSigStr, ok := test[witnessOffset].(string)
359 if !ok {
360 t.Errorf("%s: signature script is not a string", name)
361 continue
362 }
363 scriptSig, e := parseShortForm(scriptSigStr)
364 if e != nil {
365 t.Errorf(
366 "%s: can't parse signature script: %v", name,
367 e,
368 )
369 continue
370 }
371 // Extract and parse the public key script from the test fields.
372 scriptPubKeyStr, ok := test[witnessOffset+1].(string)
373 if !ok {
374 t.Errorf("%s: public key script is not a string", name)
375 continue
376 }
377 scriptPubKey, e := parseShortForm(scriptPubKeyStr)
378 if e != nil {
379 t.Errorf(
380 "%s: can't parse public key script: %v", name,
381 e,
382 )
383 continue
384 }
385 // Extract and parse the script flags from the test fields.
386 flagsStr, ok := test[witnessOffset+2].(string)
387 if !ok {
388 t.Errorf("%s: flags field is not a string", name)
389 continue
390 }
391 flags, e := parseScriptFlags(flagsStr)
392 if e != nil {
393 t.Errorf("%s: %v", name, e)
394 continue
395 }
396 // Extract and parse the expected result from the test fields. Convert the expected result string into the
397 // allowed script error codes. This is necessary because txscript is more fine grained with its errors than the
398 // reference test data, so some of the reference test data errors map to more than one possibility.
399 resultStr, ok := test[witnessOffset+3].(string)
400 if !ok {
401 t.Errorf("%s: result field is not a string", name)
402 continue
403 }
404 allowedErrorCodes, e := parseExpectedResult(resultStr)
405 if e != nil {
406 t.Errorf("%s: %v", name, e)
407 continue
408 }
409 // Generate a transaction pair such that one spends from the other and the provided signature and public key
410 // scripts are used, then create a new engine to execute the scripts.
411 tx := createSpendingTx(
412 witness, scriptSig, scriptPubKey,
413 int64(inputAmt),
414 )
415 vm, e := NewEngine(
416 scriptPubKey, tx, 0, flags, sigCache, nil,
417 int64(inputAmt),
418 )
419 if e == nil {
420 e = vm.Execute()
421 }
422 // Ensure there were no errors when the expected result is OK.
423 if resultStr == "OK" {
424 if e != nil {
425 t.Errorf("%s failed to execute: %v", name, e)
426 }
427 continue
428 }
429 // At this point an error was expected so ensure the result of the execution matches it.
430 success := false
431 for _, code := range allowedErrorCodes {
432 if IsErrorCode(e, code) {
433 success = true
434 break
435 }
436 }
437 if !success {
438 if serr, ok := e.(ScriptError); ok {
439 t.Errorf(
440 "%s: want error codes %v, got %v", name,
441 allowedErrorCodes, serr.ErrorCode,
442 )
443 continue
444 }
445 t.Errorf(
446 "%s: want error codes %v, got e: %v (%T)",
447 name, allowedErrorCodes, e, e,
448 )
449 continue
450 }
451 }
452 }
453 454 // TestScripts ensures all of the tests in script_tests.json execute with the expected results as defined in the test
455 // data.
456 func TestScripts(t *testing.T) {
457 file, e := ioutil.ReadFile("data/script_tests.json")
458 if e != nil {
459 t.Fatalf("TestScripts: %v\n", e)
460 }
461 var tests [][]interface{}
462 e = json.Unmarshal(file, &tests)
463 if e != nil {
464 t.Fatalf("TestScripts couldn't Unmarshal: %v", e)
465 }
466 // Run all script tests with and without the signature cache.
467 testScripts(t, tests, true)
468 testScripts(t, tests, false)
469 }
470 471 // testVecF64ToUint32 properly handles conversion of float64s read from the JSON test data to unsigned 32-bit integers.
472 // This is necessary because some of the test data uses -1 as a shortcut to mean max uint32 and direct conversion of a
473 // negative float to an unsigned int is implementation dependent and therefore doesn't result in the expected value on
474 // all platforms. This function woks around that limitation by converting to a 32-bit signed integer first and then to a
475 // 32-bit unsigned integer which results in the expected behavior on all platforms.
476 func testVecF64ToUint32(f float64) uint32 {
477 return uint32(int32(f))
478 }
479 480 // TestTxInvalidTests ensures all of the tests in tx_invalid.json fail as expected.
481 func TestTxInvalidTests(t *testing.T) {
482 file, e := ioutil.ReadFile("data/tx_invalid.json")
483 if e != nil {
484 t.Fatalf("TestTxInvalidTests: %v\n", e)
485 }
486 var tests [][]interface{}
487 e = json.Unmarshal(file, &tests)
488 if e != nil {
489 t.Fatalf("TestTxInvalidTests couldn't Unmarshal: %v\n", e)
490 }
491 // form is either:
492 // ["this is a comment "]
493 // or:
494 // [[[previous hash, previous index, previous scriptPubKey]...,]
495 // serializedTransaction, verifyFlags]
496 testloop:
497 for i, test := range tests {
498 inputs, ok := test[0].([]interface{})
499 if !ok {
500 continue
501 }
502 if len(test) != 3 {
503 t.Errorf("bad test (bad length) %d: %v", i, test)
504 continue
505 }
506 serializedhex, ok := test[1].(string)
507 if !ok {
508 t.Errorf("bad test (arg 2 not string) %d: %v", i, test)
509 continue
510 }
511 serializedTx, e := hex.DecodeString(serializedhex)
512 if e != nil {
513 t.Errorf(
514 "bad test (arg 2 not hex %v) %d: %v", e, i,
515 test,
516 )
517 continue
518 }
519 tx, e := util.NewTxFromBytes(serializedTx)
520 if e != nil {
521 t.Errorf(
522 "bad test (arg 2 not msgtx %v) %d: %v", e,
523 i, test,
524 )
525 continue
526 }
527 verifyFlags, ok := test[2].(string)
528 if !ok {
529 t.Errorf("bad test (arg 3 not string) %d: %v", i, test)
530 continue
531 }
532 flags, e := parseScriptFlags(verifyFlags)
533 if e != nil {
534 t.Errorf("bad test %d: %v", i, e)
535 continue
536 }
537 prevOuts := make(map[wire.OutPoint]scriptWithInputVal)
538 for j, iinput := range inputs {
539 input, ok := iinput.([]interface{})
540 if !ok {
541 t.Errorf(
542 "bad test (%dth input not array)"+
543 "%d: %v", j, i, test,
544 )
545 continue testloop
546 }
547 if len(input) < 3 || len(input) > 4 {
548 t.Errorf(
549 "bad test (%dth input wrong length)"+
550 "%d: %v", j, i, test,
551 )
552 continue testloop
553 }
554 previoustx, ok := input[0].(string)
555 if !ok {
556 t.Errorf(
557 "bad test (%dth input hash not string)"+
558 "%d: %v", j, i, test,
559 )
560 continue testloop
561 }
562 prevhash, e := chainhash.NewHashFromStr(previoustx)
563 if e != nil {
564 t.Errorf(
565 "bad test (%dth input hash not hash %v)"+
566 "%d: %v", j, e, i, test,
567 )
568 continue testloop
569 }
570 idxf, ok := input[1].(float64)
571 if !ok {
572 t.Errorf(
573 "bad test (%dth input idx not number)"+
574 "%d: %v", j, i, test,
575 )
576 continue testloop
577 }
578 idx := testVecF64ToUint32(idxf)
579 oscript, ok := input[2].(string)
580 if !ok {
581 t.Errorf(
582 "bad test (%dth input script not "+
583 "string) %d: %v", j, i, test,
584 )
585 continue testloop
586 }
587 script, e := parseShortForm(oscript)
588 if e != nil {
589 t.Errorf(
590 "bad test (%dth input script doesn't "+
591 "parse %v) %d: %v", j, e, i, test,
592 )
593 continue testloop
594 }
595 var inputValue float64
596 if len(input) == 4 {
597 inputValue, ok = input[3].(float64)
598 if !ok {
599 t.Errorf(
600 "bad test (%dth input value not int) "+
601 "%d: %v", j, i, test,
602 )
603 continue
604 }
605 }
606 v := scriptWithInputVal{
607 inputVal: int64(inputValue),
608 pkScript: script,
609 }
610 prevOuts[*wire.NewOutPoint(prevhash, idx)] = v
611 }
612 for k, txin := range tx.MsgTx().TxIn {
613 prevOut, ok := prevOuts[txin.PreviousOutPoint]
614 if !ok {
615 t.Errorf(
616 "bad test (missing %dth input) %d:%v",
617 k, i, test,
618 )
619 continue testloop
620 }
621 // These are meant to fail, so as soon as the first input fails the transaction has failed. (some of the
622 // test txns have good inputs, too..
623 vm, e := NewEngine(
624 prevOut.pkScript, tx.MsgTx(), k,
625 flags, nil, nil, prevOut.inputVal,
626 )
627 if e != nil {
628 continue testloop
629 }
630 e = vm.Execute()
631 if e != nil {
632 continue testloop
633 }
634 }
635 t.Errorf(
636 "test (%d:%v) succeeded when should fail",
637 i, test,
638 )
639 }
640 }
641 642 // TestTxValidTests ensures all of the tests in tx_valid.json pass as expected.
643 func TestTxValidTests(t *testing.T) {
644 file, e := ioutil.ReadFile("data/tx_valid.json")
645 if e != nil {
646 t.Fatalf("TestTxValidTests: %v\n", e)
647 }
648 var tests [][]interface{}
649 e = json.Unmarshal(file, &tests)
650 if e != nil {
651 t.Fatalf("TestTxValidTests couldn't Unmarshal: %v\n", e)
652 }
653 // form is either:
654 // ["this is a comment "]
655 // or:
656 // [[[previous hash, previous index, previous scriptPubKey, input value]...,]
657 // serializedTransaction, verifyFlags]
658 testloop:
659 for i, test := range tests {
660 inputs, ok := test[0].([]interface{})
661 if !ok {
662 continue
663 }
664 if len(test) != 3 {
665 t.Errorf("bad test (bad length) %d: %v", i, test)
666 continue
667 }
668 serializedhex, ok := test[1].(string)
669 if !ok {
670 t.Errorf("bad test (arg 2 not string) %d: %v", i, test)
671 continue
672 }
673 serializedTx, e := hex.DecodeString(serializedhex)
674 if e != nil {
675 t.Errorf(
676 "bad test (arg 2 not hex %v) %d: %v", e, i,
677 test,
678 )
679 continue
680 }
681 tx, e := util.NewTxFromBytes(serializedTx)
682 if e != nil {
683 t.Errorf(
684 "bad test (arg 2 not msgtx %v) %d: %v", e,
685 i, test,
686 )
687 continue
688 }
689 verifyFlags, ok := test[2].(string)
690 if !ok {
691 t.Errorf("bad test (arg 3 not string) %d: %v", i, test)
692 continue
693 }
694 flags, e := parseScriptFlags(verifyFlags)
695 if e != nil {
696 t.Errorf("bad test %d: %v", i, e)
697 continue
698 }
699 prevOuts := make(map[wire.OutPoint]scriptWithInputVal)
700 for j, iinput := range inputs {
701 input, ok := iinput.([]interface{})
702 if !ok {
703 t.Errorf(
704 "bad test (%dth input not array)"+
705 "%d: %v", j, i, test,
706 )
707 continue
708 }
709 if len(input) < 3 || len(input) > 4 {
710 t.Errorf(
711 "bad test (%dth input wrong length)"+
712 "%d: %v", j, i, test,
713 )
714 continue
715 }
716 previoustx, ok := input[0].(string)
717 if !ok {
718 t.Errorf(
719 "bad test (%dth input hash not string)"+
720 "%d: %v", j, i, test,
721 )
722 continue
723 }
724 prevhash, e := chainhash.NewHashFromStr(previoustx)
725 if e != nil {
726 t.Errorf(
727 "bad test (%dth input hash not hash %v)"+
728 "%d: %v", j, e, i, test,
729 )
730 continue
731 }
732 idxf, ok := input[1].(float64)
733 if !ok {
734 t.Errorf(
735 "bad test (%dth input idx not number)"+
736 "%d: %v", j, i, test,
737 )
738 continue
739 }
740 idx := testVecF64ToUint32(idxf)
741 oscript, ok := input[2].(string)
742 if !ok {
743 t.Errorf(
744 "bad test (%dth input script not "+
745 "string) %d: %v", j, i, test,
746 )
747 continue
748 }
749 script, e := parseShortForm(oscript)
750 if e != nil {
751 t.Errorf(
752 "bad test (%dth input script doesn't "+
753 "parse %v) %d: %v", j, e, i, test,
754 )
755 continue
756 }
757 var inputValue float64
758 if len(input) == 4 {
759 inputValue, ok = input[3].(float64)
760 if !ok {
761 t.Errorf(
762 "bad test (%dth input value not int) "+
763 "%d: %v", j, i, test,
764 )
765 continue
766 }
767 }
768 v := scriptWithInputVal{
769 inputVal: int64(inputValue),
770 pkScript: script,
771 }
772 prevOuts[*wire.NewOutPoint(prevhash, idx)] = v
773 }
774 for k, txin := range tx.MsgTx().TxIn {
775 prevOut, ok := prevOuts[txin.PreviousOutPoint]
776 if !ok {
777 t.Errorf(
778 "bad test (missing %dth input) %d:%v",
779 k, i, test,
780 )
781 continue testloop
782 }
783 vm, e := NewEngine(
784 prevOut.pkScript, tx.MsgTx(), k,
785 flags, nil, nil, prevOut.inputVal,
786 )
787 if e != nil {
788 t.Errorf(
789 "test (%d:%v:%d) failed to create "+
790 "script: %v", i, test, k, e,
791 )
792 continue
793 }
794 e = vm.Execute()
795 if e != nil {
796 t.Errorf(
797 "test (%d:%v:%d) failed to execute: "+
798 "%v", i, test, k, e,
799 )
800 continue
801 }
802 }
803 }
804 }
805 806 // TestCalcSignatureHash runs the Bitcoin Core signature hash calculation tests in sighash.json.
807 // https://github.com/bitcoin/bitcoin/blob/master/src/test/data/sighash.json
808 func TestCalcSignatureHash(t *testing.T) {
809 file, e := ioutil.ReadFile("data/sighash.json")
810 if e != nil {
811 t.Fatalf("TestCalcSignatureHash: %v\n", e)
812 }
813 var tests [][]interface{}
814 e = json.Unmarshal(file, &tests)
815 if e != nil {
816 t.Fatalf(
817 "TestCalcSignatureHash couldn't Unmarshal: %v\n",
818 e,
819 )
820 }
821 for i, test := range tests {
822 if i == 0 {
823 // Skip first line -- contains comments only.
824 continue
825 }
826 if len(test) != 5 {
827 t.Fatalf(
828 "TestCalcSignatureHash: Test #%d has "+
829 "wrong length.", i,
830 )
831 }
832 var tx wire.MsgTx
833 rawTx, _ := hex.DecodeString(test[0].(string))
834 e := tx.Deserialize(bytes.NewReader(rawTx))
835 if e != nil {
836 t.Errorf(
837 "TestCalcSignatureHash failed test #%d: "+
838 "Failed to parse transaction: %v", i, e,
839 )
840 continue
841 }
842 subScript, _ := hex.DecodeString(test[1].(string))
843 parsedScript, e := parseScript(subScript)
844 if e != nil {
845 t.Errorf(
846 "TestCalcSignatureHash failed test #%d: "+
847 "Failed to parse sub-script: %v", i, e,
848 )
849 continue
850 }
851 hashType := SigHashType(testVecF64ToUint32(test[3].(float64)))
852 hash := calcSignatureHash(
853 parsedScript, hashType, &tx,
854 int(test[2].(float64)),
855 )
856 expectedHash, _ := chainhash.NewHashFromStr(test[4].(string))
857 if !bytes.Equal(hash, expectedHash[:]) {
858 t.Errorf(
859 "TestCalcSignatureHash failed test #%d: "+
860 "Signature hash mismatch.", i,
861 )
862 }
863 }
864 }
865