diff --git a/script.go b/script.go index 7cbef226..8540812c 100644 --- a/script.go +++ b/script.go @@ -86,6 +86,12 @@ var StackErrScriptUnfinished = errors.New("Error check when script unfinished") // when the scripts have finished executing. var StackErrEmptyStack = errors.New("Stack empty at end of execution") +// StackErrP2SHNonPushOnly is returned when a Pay-to-Script-Hash transaction +// is encountered and the ScriptSig does operations other than push data (in +// violation of bip16). +var StackErrP2SHNonPushOnly = errors.New("pay to script hash with non " + + "pushonly input") + // Bip16Activation is the timestamp where BIP0016 is valid to use in the // blockchain. To be used to determine if BIP0016 should be called for or not. // This timestamp corresponds to Sun Apr 1 00:00:00 UTC 2012. @@ -319,8 +325,7 @@ func NewScript(scriptSig []byte, scriptPubKey []byte, txidx int, tx *btcwire.Msg // if we are pay to scripthash then we only accept input // scripts that push data if !isPushOnly(m.scripts[0]) { - return nil, errors.New("pay to script hash with non " + - "pushonly input") + return nil, StackErrP2SHNonPushOnly } m.bip16 = true } diff --git a/script_test.go b/script_test.go index 4edfff11..00df549e 100644 --- a/script_test.go +++ b/script_test.go @@ -15,12 +15,13 @@ type txTest struct { name string tx *btcwire.MsgTx pkScript []byte // output script of previous tx - idx int - bip16 bool - err error - shouldFail bool - nSigOps int - sigOpsErr error + idx int // tx idx to be run. + bip16 bool // is bip16 active? + parseErr error // failure of NewScript + err error // Failure of Executre + shouldFail bool // Execute should fail with nonspecified error. + nSigOps int // result of GetPreciseSigOpsCount + sigOpsErr error // failure of GetPreciseSigOpsCount() } var txTests = []txTest{ @@ -1072,14 +1073,77 @@ var txTests = []txTest{ btcscript.OP_DATA_20, 0xd4, 0x8c, 0xe8, 0x6c, 0x69, 0x8f, 0x24, 0x68, 0x29, 0x92, 0x1b, 0xa9, 0xfb, 0x2a, 0x84, 0x4a, 0xe2, 0xad, - 0xba, 0x67, + 0xba, 0x67, btcscript.OP_EQUAL, }, - idx: 0, - err: btcscript.StackErrShortScript, - bip16: true, + idx: 0, + err: btcscript.StackErrShortScript, + bip16: true, sigOpsErr: btcscript.StackErrShortScript, }, + txTest{ + // sigscript changed so to be non pushonly. + name: "P2SH - non pushonly", + tx: &btcwire.MsgTx{ + Version: 1, + TxIn: []*btcwire.TxIn{ + &btcwire.TxIn{ + PreviousOutpoint: btcwire.OutPoint{ + Hash: btcwire.ShaHash([32]byte{ + 0x6d, 0x58, 0xf8, 0xa3, + 0xaa, 0x43, 0x0b, 0x84, + 0x78, 0x52, 0x3a, 0x65, + 0xc2, 0x03, 0xa2, 0x7b, + 0xb8, 0x81, 0x17, 0x8c, + 0xb1, 0x23, 0x13, 0xaf, + 0xde, 0x29, 0xf9, 0x2e, + 0xd7, 0x56, 0xaa, 0x7e, + }), + Index: 0, + }, + // doesn't have to match signature. + // will never run. + SignatureScript: []byte{ + + btcscript.OP_DATA_2, + // pushed script. + btcscript.OP_DATA_1, 0x1, + btcscript.OP_DUP, + }, + Sequence: 4294967295, + }, + }, + TxOut: []*btcwire.TxOut{ + &btcwire.TxOut{ + Value: 1000000, + PkScript: []byte{ + btcscript.OP_DUP, + btcscript.OP_HASH160, + btcscript.OP_DATA_20, + 0x5b, 0x69, 0xd8, 0xb9, 0xdf, + 0xa6, 0xe4, 0x12, 0x26, 0x47, + 0xe1, 0x79, 0x4e, 0xaa, 0x3b, + 0xfc, 0x11, 0x1f, 0x70, 0xef, + btcscript.OP_EQUALVERIFY, + btcscript.OP_CHECKSIG, + }, + }, + }, + LockTime: 0, + }, + pkScript: []byte{ + btcscript.OP_HASH160, + btcscript.OP_DATA_20, + 0x43, 0x3e, 0xc2, 0xac, 0x1f, 0xfa, 0x1b, 0x7b, 0x7d, + 0x02, 0x7f, 0x56, 0x45, 0x29, 0xc5, 0x71, 0x97, 0xf9, + 0xae, 0x88, + btcscript.OP_EQUAL, + }, + idx: 0, + parseErr: btcscript.StackErrP2SHNonPushOnly, + bip16: true, + nSigOps: 0, // no signature ops in the pushed script. + }, } // Test a number of tx from the blockchain to test otherwise difficult to test @@ -1093,9 +1157,16 @@ func testTx(t *testing.T, test txTest) { test.tx.TxIn[test.idx].SignatureScript, test.pkScript, test.idx, test.tx, 70001, test.bip16) if err != nil { - t.Errorf("Failed to parse %s: %v", test.name, err) + if err != test.parseErr { + t.Errorf("Failed to parse %s: got \"%v\" expected "+ + "\"%v\"", test.name, err, test.parseErr) + } return } + if test.parseErr != nil { + t.Errorf("%s: parse succeeded when expecting \"%v\"", test.name, + test.parseErr) + } err = engine.Execute() if err != nil { @@ -1152,32 +1223,32 @@ func TestGetPreciseSignOps(t *testing.T) { // conditions in the P2SH cases.. type psocTest struct { - name string + name string scriptSig []byte - nSigOps int - err error + nSigOps int + err error } psocTests := []psocTest{ psocTest{ - name: "scriptSig doesn't parse", + name: "scriptSig doesn't parse", scriptSig: []byte{btcscript.OP_PUSHDATA1, 2}, - err: btcscript.StackErrShortScript, + err: btcscript.StackErrShortScript, }, psocTest{ - name: "scriptSig isn't push only", + name: "scriptSig isn't push only", scriptSig: []byte{btcscript.OP_1, btcscript.OP_DUP}, - nSigOps: 0, + nSigOps: 0, }, psocTest{ - name: "scriptSig length 0", + name: "scriptSig length 0", scriptSig: []byte{}, - nSigOps: 0, + nSigOps: 0, }, psocTest{ name: "No script at the end", // No script at end but still push only. scriptSig: []byte{btcscript.OP_1, btcscript.OP_1}, - nSigOps: 0, + nSigOps: 0, }, // pushed script doesn't parse. psocTest{ @@ -1204,8 +1275,8 @@ func TestGetPreciseSignOps(t *testing.T) { // all tx currently parse if err != nil { if err != test.err { - t.Errorf("%s: unexpected error. got \"%v\" exp: \"%v\"", - test.name, err, test.err) + t.Errorf("%s: unexpected error. got \"%v\" exp: \"%v\"", + test.name, err, test.err) } continue } diff --git a/test_coverage.txt b/test_coverage.txt index 72c84a56..15e53197 100644 --- a/test_coverage.txt +++ b/test_coverage.txt @@ -1,59 +1,60 @@ +github.com/conformal/btcscript/script.go NewScript 100.00% (19/19) github.com/conformal/btcscript/stack.go asInt 100.00% (18/18) github.com/conformal/btcscript/script.go GetPreciseSigOpCount 100.00% (17/17) github.com/conformal/btcscript/stack.go fromInt 100.00% (14/14) github.com/conformal/btcscript/opcode.go opcodeWithin 100.00% (13/13) +github.com/conformal/btcscript/stack.go Stack.nipN 100.00% (12/12) github.com/conformal/btcscript/opcode.go parsedOpcode.print 100.00% (12/12) github.com/conformal/btcscript/opcode.go parsedOpcode.bytes 100.00% (12/12) -github.com/conformal/btcscript/stack.go Stack.nipN 100.00% (12/12) github.com/conformal/btcscript/opcode.go opcodeIf 100.00% (11/11) github.com/conformal/btcscript/opcode.go opcodeNotIf 100.00% (11/11) -github.com/conformal/btcscript/opcode.go opcodeMin 100.00% (10/10) +github.com/conformal/btcscript/opcode.go opcodeLessThanOrEqual 100.00% (10/10) github.com/conformal/btcscript/opcode.go opcodeMax 100.00% (10/10) +github.com/conformal/btcscript/opcode.go opcodeMin 100.00% (10/10) +github.com/conformal/btcscript/opcode.go opcodeGreaterThanOrEqual 100.00% (10/10) github.com/conformal/btcscript/stack.go Stack.Tuck 100.00% (10/10) +github.com/conformal/btcscript/opcode.go opcodeBoolAnd 100.00% (10/10) github.com/conformal/btcscript/opcode.go opcodeBoolOr 100.00% (10/10) +github.com/conformal/btcscript/script.go getSigOpCount 100.00% (10/10) github.com/conformal/btcscript/opcode.go opcodeNumEqual 100.00% (10/10) github.com/conformal/btcscript/opcode.go opcodeNumNotEqual 100.00% (10/10) github.com/conformal/btcscript/opcode.go opcodeLessThan 100.00% (10/10) github.com/conformal/btcscript/opcode.go opcodeGreaterThan 100.00% (10/10) -github.com/conformal/btcscript/opcode.go opcodeBoolAnd 100.00% (10/10) -github.com/conformal/btcscript/opcode.go opcodeLessThanOrEqual 100.00% (10/10) -github.com/conformal/btcscript/opcode.go opcodeGreaterThanOrEqual 100.00% (10/10) -github.com/conformal/btcscript/script.go getSigOpCount 100.00% (10/10) -github.com/conformal/btcscript/stack.go Stack.OverN 100.00% (9/9) github.com/conformal/btcscript/stack.go Stack.SwapN 100.00% (9/9) -github.com/conformal/btcscript/script.go DisasmString 100.00% (9/9) +github.com/conformal/btcscript/stack.go Stack.OverN 100.00% (9/9) github.com/conformal/btcscript/stack.go Stack.RotN 100.00% (9/9) -github.com/conformal/btcscript/opcode.go opcodeAdd 100.00% (8/8) +github.com/conformal/btcscript/script.go DisasmString 100.00% (9/9) github.com/conformal/btcscript/opcode.go opcodeSub 100.00% (8/8) -github.com/conformal/btcscript/stack.go Stack.DupN 100.00% (8/8) +github.com/conformal/btcscript/opcode.go opcodeAdd 100.00% (8/8) github.com/conformal/btcscript/opcode.go opcodeEqual 100.00% (8/8) +github.com/conformal/btcscript/stack.go Stack.DupN 100.00% (8/8) github.com/conformal/btcscript/stack.go Stack.DropN 100.00% (7/7) -github.com/conformal/btcscript/opcode.go opcode0NotEqual 100.00% (7/7) github.com/conformal/btcscript/opcode.go opcodePick 100.00% (7/7) github.com/conformal/btcscript/opcode.go opcodeRoll 100.00% (7/7) github.com/conformal/btcscript/opcode.go opcodeNot 100.00% (7/7) +github.com/conformal/btcscript/opcode.go opcode0NotEqual 100.00% (7/7) +github.com/conformal/btcscript/opcode.go opcodeIfDup 100.00% (6/6) +github.com/conformal/btcscript/opcode.go parsedOpcode.conditional 100.00% (6/6) github.com/conformal/btcscript/opcode.go opcodeElse 100.00% (6/6) github.com/conformal/btcscript/opcode.go opcodeVerify 100.00% (6/6) -github.com/conformal/btcscript/opcode.go parsedOpcode.conditional 100.00% (6/6) -github.com/conformal/btcscript/opcode.go opcodeIfDup 100.00% (6/6) -github.com/conformal/btcscript/stack.go Stack.RollN 100.00% (5/5) +github.com/conformal/btcscript/opcode.go opcodeFromAltStack 100.00% (5/5) +github.com/conformal/btcscript/opcode.go opcodeAbs 100.00% (5/5) +github.com/conformal/btcscript/opcode.go opcodeRipemd160 100.00% (5/5) +github.com/conformal/btcscript/opcode.go opcodeSha256 100.00% (5/5) +github.com/conformal/btcscript/opcode.go opcodeHash160 100.00% (5/5) +github.com/conformal/btcscript/opcode.go opcodeHash256 100.00% (5/5) +github.com/conformal/btcscript/opcode.go opcodeToAltStack 100.00% (5/5) github.com/conformal/btcscript/opcode.go opcodeSize 100.00% (5/5) -github.com/conformal/btcscript/script.go removeOpcode 100.00% (5/5) +github.com/conformal/btcscript/stack.go Stack.PickN 100.00% (5/5) +github.com/conformal/btcscript/stack.go Stack.RollN 100.00% (5/5) github.com/conformal/btcscript/opcode.go opcode1Add 100.00% (5/5) github.com/conformal/btcscript/opcode.go opcode1Sub 100.00% (5/5) github.com/conformal/btcscript/opcode.go opcodeNegate 100.00% (5/5) -github.com/conformal/btcscript/script.go Script.validPC 100.00% (5/5) -github.com/conformal/btcscript/opcode.go opcodeFromAltStack 100.00% (5/5) -github.com/conformal/btcscript/opcode.go opcodeHash160 100.00% (5/5) -github.com/conformal/btcscript/opcode.go opcodeSha256 100.00% (5/5) -github.com/conformal/btcscript/opcode.go opcodeRipemd160 100.00% (5/5) -github.com/conformal/btcscript/opcode.go opcodeAbs 100.00% (5/5) -github.com/conformal/btcscript/opcode.go opcodeToAltStack 100.00% (5/5) -github.com/conformal/btcscript/opcode.go opcodeHash256 100.00% (5/5) -github.com/conformal/btcscript/stack.go Stack.PickN 100.00% (5/5) -github.com/conformal/btcscript/script.go removeOpcodeByData 100.00% (5/5) github.com/conformal/btcscript/opcode.go parsedOpcode.exec 100.00% (5/5) +github.com/conformal/btcscript/script.go removeOpcode 100.00% (5/5) +github.com/conformal/btcscript/script.go Script.validPC 100.00% (5/5) +github.com/conformal/btcscript/script.go removeOpcodeByData 100.00% (5/5) github.com/conformal/btcscript/stack.go Stack.PeekBool 100.00% (4/4) github.com/conformal/btcscript/opcode.go opcodeEndif 100.00% (4/4) github.com/conformal/btcscript/opcode.go opcodeEqualVerify 100.00% (4/4) @@ -76,34 +77,25 @@ github.com/conformal/btcscript/address.go ScriptType.String 100.00% (3/3) github.com/conformal/btcscript/script.go scriptUInt16 100.00% (3/3) github.com/conformal/btcscript/script.go scriptUInt8 100.00% (3/3) github.com/conformal/btcscript/script.go scriptUInt32 100.00% (3/3) -github.com/conformal/btcscript/opcode.go opcodeCodeSeparator 100.00% (2/2) +github.com/conformal/btcscript/opcode.go opcodeFalse 100.00% (2/2) github.com/conformal/btcscript/opcode.go calcHash 100.00% (2/2) +github.com/conformal/btcscript/opcode.go opcodeCodeSeparator 100.00% (2/2) github.com/conformal/btcscript/stack.go Stack.Depth 100.00% (2/2) github.com/conformal/btcscript/stack.go Stack.NipN 100.00% (2/2) +github.com/conformal/btcscript/opcode.go opcodeN 100.00% (2/2) +github.com/conformal/btcscript/opcode.go opcodeDepth 100.00% (2/2) github.com/conformal/btcscript/opcode.go opcode1Negate 100.00% (2/2) github.com/conformal/btcscript/opcode.go opcodePushData 100.00% (2/2) -github.com/conformal/btcscript/opcode.go opcodeN 100.00% (2/2) -github.com/conformal/btcscript/opcode.go opcodeFalse 100.00% (2/2) -github.com/conformal/btcscript/opcode.go opcodeDepth 100.00% (2/2) -github.com/conformal/btcscript/log.go newLogClosure 100.00% (1/1) -github.com/conformal/btcscript/stack.go Stack.PushBool 100.00% (1/1) -github.com/conformal/btcscript/opcode.go calcHash160 100.00% (1/1) +github.com/conformal/btcscript/opcode.go opcodeNop 100.00% (1/1) +github.com/conformal/btcscript/opcode.go opcode3Dup 100.00% (1/1) github.com/conformal/btcscript/opcode.go opcode2Dup 100.00% (1/1) github.com/conformal/btcscript/opcode.go opcode2Drop 100.00% (1/1) -github.com/conformal/btcscript/opcode.go opcodeReturn 100.00% (1/1) -github.com/conformal/btcscript/opcode.go opcode3Dup 100.00% (1/1) github.com/conformal/btcscript/stack.go Stack.PushByteArray 100.00% (1/1) github.com/conformal/btcscript/stack.go Stack.PushInt 100.00% (1/1) -github.com/conformal/btcscript/opcode.go opcodeNop 100.00% (1/1) +github.com/conformal/btcscript/opcode.go opcodeReturn 100.00% (1/1) github.com/conformal/btcscript/stack.go Stack.PopByteArray 100.00% (1/1) -github.com/conformal/btcscript/opcode.go opcodeInvalid 100.00% (1/1) github.com/conformal/btcscript/script.go Script.GetStack 100.00% (1/1) -github.com/conformal/btcscript/opcode.go opcodeReserved 100.00% (1/1) -github.com/conformal/btcscript/script.go Script.SetStack 100.00% (1/1) -github.com/conformal/btcscript/opcode.go opcodeDisabled 100.00% (1/1) -github.com/conformal/btcscript/opcode.go init 100.00% (1/1) -github.com/conformal/btcscript/script.go isPubkeyHash 100.00% (1/1) -github.com/conformal/btcscript/script.go isScriptHash 100.00% (1/1) +github.com/conformal/btcscript/opcode.go opcodeInvalid 100.00% (1/1) github.com/conformal/btcscript/log.go UseLogger 100.00% (1/1) github.com/conformal/btcscript/log.go init 100.00% (1/1) github.com/conformal/btcscript/script.go Script.disasm 100.00% (1/1) @@ -117,16 +109,24 @@ github.com/conformal/btcscript/opcode.go opcodeDup 100.00% (1/1) github.com/conformal/btcscript/opcode.go opcodeDrop 100.00% (1/1) github.com/conformal/btcscript/opcode.go opcode2Swap 100.00% (1/1) github.com/conformal/btcscript/opcode.go opcode2Rot 100.00% (1/1) +github.com/conformal/btcscript/opcode.go calcHash160 100.00% (1/1) github.com/conformal/btcscript/opcode.go opcode2Over 100.00% (1/1) +github.com/conformal/btcscript/script.go Script.SetStack 100.00% (1/1) +github.com/conformal/btcscript/opcode.go opcodeReserved 100.00% (1/1) +github.com/conformal/btcscript/opcode.go opcodeDisabled 100.00% (1/1) +github.com/conformal/btcscript/opcode.go init 100.00% (1/1) +github.com/conformal/btcscript/stack.go Stack.PushBool 100.00% (1/1) github.com/conformal/btcscript/script.go Script.subScript 100.00% (1/1) -github.com/conformal/btcscript/script.go Script.SetAltStack 100.00% (1/1) +github.com/conformal/btcscript/log.go newLogClosure 100.00% (1/1) github.com/conformal/btcscript/script.go Script.GetAltStack 100.00% (1/1) github.com/conformal/btcscript/script.go isPubkey 100.00% (1/1) +github.com/conformal/btcscript/script.go isPubkeyHash 100.00% (1/1) +github.com/conformal/btcscript/script.go isScriptHash 100.00% (1/1) +github.com/conformal/btcscript/script.go Script.SetAltStack 100.00% (1/1) github.com/conformal/btcscript/opcode.go opcodeCheckMultiSig 98.21% (55/56) github.com/conformal/btcscript/script.go Script.Step 97.30% (36/37) github.com/conformal/btcscript/opcode.go opcodeCheckSig 96.15% (25/26) github.com/conformal/btcscript/address.go ScriptToAddress 94.92% (56/59) -github.com/conformal/btcscript/script.go NewScript 94.74% (18/19) github.com/conformal/btcscript/script.go parseScript 93.75% (30/32) github.com/conformal/btcscript/script.go typeOfScript 83.33% (5/6) github.com/conformal/btcscript/script.go Script.DisasmScript 80.00% (4/5) @@ -138,5 +138,5 @@ github.com/conformal/btcscript/opcode.go opcodeSha1 60.00% (3/5) github.com/conformal/btcscript/script.go Script.Execute 44.44% (8/18) github.com/conformal/btcscript/log.go SetLogWriter 0.00% (0/7) github.com/conformal/btcscript/log.go logClosure.String 0.00% (0/1) -github.com/conformal/btcscript -------------------------- 94.60% (876/926) +github.com/conformal/btcscript -------------------------- 94.71% (877/926)