txscript: Consolidate tests into txscript package.

Putting the test code in the same package makes it easier for forks
since they don't have to change the import paths as much and it also
gets rid of the need for internal_test.go to bridge.

Also, do some light cleanup on a few tests while here.
This commit is contained in:
Dave Collins 2016-10-20 01:18:31 -05:00
parent b60e3547d2
commit 59a3fc2f66
8 changed files with 4284 additions and 4403 deletions

View file

@ -2,13 +2,12 @@
// Use of this source code is governed by an ISC // Use of this source code is governed by an ISC
// license that can be found in the LICENSE file. // license that can be found in the LICENSE file.
package txscript_test package txscript
import ( import (
"testing" "testing"
"github.com/btcsuite/btcd/chaincfg/chainhash" "github.com/btcsuite/btcd/chaincfg/chainhash"
"github.com/btcsuite/btcd/txscript"
"github.com/btcsuite/btcd/wire" "github.com/btcsuite/btcd/wire"
) )
@ -17,19 +16,13 @@ import (
func TestBadPC(t *testing.T) { func TestBadPC(t *testing.T) {
t.Parallel() t.Parallel()
type pcTest struct { tests := []struct {
script, off int script, off int
}{
{script: 2, off: 0},
{script: 0, off: 2},
} }
pcTests := []pcTest{
{
script: 2,
off: 0,
},
{
script: 0,
off: 2,
},
}
// tx with almost empty scripts. // tx with almost empty scripts.
tx := &wire.MsgTx{ tx := &wire.MsgTx{
Version: 1, Version: 1,
@ -48,28 +41,27 @@ func TestBadPC(t *testing.T) {
}), }),
Index: 0, Index: 0,
}, },
SignatureScript: []uint8{txscript.OP_NOP}, SignatureScript: mustParseShortForm("NOP"),
Sequence: 4294967295, Sequence: 4294967295,
}, },
}, },
TxOut: []*wire.TxOut{ TxOut: []*wire.TxOut{{
{ Value: 1000000000,
Value: 1000000000, PkScript: nil,
PkScript: nil, }},
},
},
LockTime: 0, LockTime: 0,
} }
pkScript := []byte{txscript.OP_NOP} pkScript := mustParseShortForm("NOP")
for _, test := range pcTests { for _, test := range tests {
vm, err := txscript.NewEngine(pkScript, tx, 0, 0, nil) vm, err := NewEngine(pkScript, tx, 0, 0, nil)
if err != nil { if err != nil {
t.Errorf("Failed to create script: %v", err) t.Errorf("Failed to create script: %v", err)
} }
// set to after all scripts // set to after all scripts
vm.TstSetPC(test.script, test.off) vm.scriptIdx = test.script
vm.scriptOff = test.off
_, err = vm.Step() _, err = vm.Step()
if err == nil { if err == nil {
@ -93,48 +85,33 @@ func TestCheckErrorCondition(t *testing.T) {
// tx with almost empty scripts. // tx with almost empty scripts.
tx := &wire.MsgTx{ tx := &wire.MsgTx{
Version: 1, Version: 1,
TxIn: []*wire.TxIn{ TxIn: []*wire.TxIn{{
{ PreviousOutPoint: wire.OutPoint{
PreviousOutPoint: wire.OutPoint{ Hash: chainhash.Hash([32]byte{
Hash: chainhash.Hash([32]byte{ 0xc9, 0x97, 0xa5, 0xe5,
0xc9, 0x97, 0xa5, 0xe5, 0x6e, 0x10, 0x41, 0x02,
0x6e, 0x10, 0x41, 0x02, 0xfa, 0x20, 0x9c, 0x6a,
0xfa, 0x20, 0x9c, 0x6a, 0x85, 0x2d, 0xd9, 0x06,
0x85, 0x2d, 0xd9, 0x06, 0x60, 0xa2, 0x0b, 0x2d,
0x60, 0xa2, 0x0b, 0x2d, 0x9c, 0x35, 0x24, 0x23,
0x9c, 0x35, 0x24, 0x23, 0xed, 0xce, 0x25, 0x85,
0xed, 0xce, 0x25, 0x85, 0x7f, 0xcd, 0x37, 0x04,
0x7f, 0xcd, 0x37, 0x04, }),
}), Index: 0,
Index: 0,
},
SignatureScript: []uint8{},
Sequence: 4294967295,
}, },
}, SignatureScript: nil,
TxOut: []*wire.TxOut{ Sequence: 4294967295,
{ }},
Value: 1000000000, TxOut: []*wire.TxOut{{
PkScript: nil, Value: 1000000000,
}, PkScript: nil,
}, }},
LockTime: 0, LockTime: 0,
} }
pkScript := []byte{ pkScript := mustParseShortForm("NOP NOP NOP NOP NOP NOP NOP NOP NOP" +
txscript.OP_NOP, " NOP TRUE")
txscript.OP_NOP,
txscript.OP_NOP,
txscript.OP_NOP,
txscript.OP_NOP,
txscript.OP_NOP,
txscript.OP_NOP,
txscript.OP_NOP,
txscript.OP_NOP,
txscript.OP_NOP,
txscript.OP_TRUE,
}
vm, err := txscript.NewEngine(pkScript, tx, 0, 0, nil) vm, err := NewEngine(pkScript, tx, 0, 0, nil)
if err != nil { if err != nil {
t.Errorf("failed to create script: %v", err) t.Errorf("failed to create script: %v", err)
} }
@ -151,7 +128,7 @@ func TestCheckErrorCondition(t *testing.T) {
} }
err = vm.CheckErrorCondition(false) err = vm.CheckErrorCondition(false)
if err != txscript.ErrStackScriptUnfinished { if err != ErrStackScriptUnfinished {
t.Errorf("got unexepected error %v on %dth iteration", t.Errorf("got unexepected error %v on %dth iteration",
err, i) err, i)
return return
@ -178,8 +155,8 @@ func TestCheckErrorCondition(t *testing.T) {
func TestInvalidFlagCombinations(t *testing.T) { func TestInvalidFlagCombinations(t *testing.T) {
t.Parallel() t.Parallel()
tests := []txscript.ScriptFlags{ tests := []ScriptFlags{
txscript.ScriptVerifyCleanStack, ScriptVerifyCleanStack,
} }
// tx with almost empty scripts. // tx with almost empty scripts.
@ -200,7 +177,7 @@ func TestInvalidFlagCombinations(t *testing.T) {
}), }),
Index: 0, Index: 0,
}, },
SignatureScript: []uint8{txscript.OP_NOP}, SignatureScript: []uint8{OP_NOP},
Sequence: 4294967295, Sequence: 4294967295,
}, },
}, },
@ -212,11 +189,11 @@ func TestInvalidFlagCombinations(t *testing.T) {
}, },
LockTime: 0, LockTime: 0,
} }
pkScript := []byte{txscript.OP_NOP} pkScript := []byte{OP_NOP}
for i, test := range tests { for i, test := range tests {
_, err := txscript.NewEngine(pkScript, tx, 0, test, nil) _, err := NewEngine(pkScript, tx, 0, test, nil)
if err != txscript.ErrInvalidFlags { if err != ErrInvalidFlags {
t.Fatalf("TestInvalidFlagCombinations #%d unexpected "+ t.Fatalf("TestInvalidFlagCombinations #%d unexpected "+
"error: %v", i, err) "error: %v", i, err)
} }
@ -235,7 +212,7 @@ func TestCheckPubKeyEncoding(t *testing.T) {
}{ }{
{ {
name: "uncompressed ok", name: "uncompressed ok",
key: decodeHex("0411db93e1dcdb8a016b49840f8c53bc1eb68" + key: hexToBytes("0411db93e1dcdb8a016b49840f8c53bc1eb68" +
"a382e97b1482ecad7b148a6909a5cb2e0eaddfb84ccf" + "a382e97b1482ecad7b148a6909a5cb2e0eaddfb84ccf" +
"9744464f82e160bfa9b8b64f9d4c03f999b8643f656b" + "9744464f82e160bfa9b8b64f9d4c03f999b8643f656b" +
"412a3"), "412a3"),
@ -243,19 +220,19 @@ func TestCheckPubKeyEncoding(t *testing.T) {
}, },
{ {
name: "compressed ok", name: "compressed ok",
key: decodeHex("02ce0b14fb842b1ba549fdd675c98075f12e9" + key: hexToBytes("02ce0b14fb842b1ba549fdd675c98075f12e9" +
"c510f8ef52bd021a9a1f4809d3b4d"), "c510f8ef52bd021a9a1f4809d3b4d"),
isValid: true, isValid: true,
}, },
{ {
name: "compressed ok", name: "compressed ok",
key: decodeHex("032689c7c2dab13309fb143e0e8fe39634252" + key: hexToBytes("032689c7c2dab13309fb143e0e8fe39634252" +
"1887e976690b6b47f5b2a4b7d448e"), "1887e976690b6b47f5b2a4b7d448e"),
isValid: true, isValid: true,
}, },
{ {
name: "hybrid", name: "hybrid",
key: decodeHex("0679be667ef9dcbbac55a06295ce870b07029" + key: hexToBytes("0679be667ef9dcbbac55a06295ce870b07029" +
"bfcdb2dce28d959f2815b16f81798483ada7726a3c46" + "bfcdb2dce28d959f2815b16f81798483ada7726a3c46" +
"55da4fbfc0e1108a8fd17b448a68554199c47d08ffb1" + "55da4fbfc0e1108a8fd17b448a68554199c47d08ffb1" +
"0d4b8"), "0d4b8"),
@ -268,9 +245,9 @@ func TestCheckPubKeyEncoding(t *testing.T) {
}, },
} }
flags := txscript.ScriptVerifyStrictEncoding vm := Engine{flags: ScriptVerifyStrictEncoding}
for _, test := range tests { for _, test := range tests {
err := txscript.TstCheckPubKeyEncoding(test.key, flags) err := vm.checkPubKeyEncoding(test.key)
if err != nil && test.isValid { if err != nil && test.isValid {
t.Errorf("checkSignatureEncoding test '%s' failed "+ t.Errorf("checkSignatureEncoding test '%s' failed "+
"when it should have succeeded: %v", test.name, "when it should have succeeded: %v", test.name,
@ -295,7 +272,7 @@ func TestCheckSignatureEncoding(t *testing.T) {
}{ }{
{ {
name: "valid signature", name: "valid signature",
sig: decodeHex("304402204e45e16932b8af514961a1d3a1a25" + sig: hexToBytes("304402204e45e16932b8af514961a1d3a1a25" +
"fdf3f4f7732e9d624c6c61548ab5fb8cd41022018152" + "fdf3f4f7732e9d624c6c61548ab5fb8cd41022018152" +
"2ec8eca07de4860a4acdd12909d831cc56cbbac46220" + "2ec8eca07de4860a4acdd12909d831cc56cbbac46220" +
"82221a8768d1d09"), "82221a8768d1d09"),
@ -308,7 +285,7 @@ func TestCheckSignatureEncoding(t *testing.T) {
}, },
{ {
name: "bad magic", name: "bad magic",
sig: decodeHex("314402204e45e16932b8af514961a1d3a1a25" + sig: hexToBytes("314402204e45e16932b8af514961a1d3a1a25" +
"fdf3f4f7732e9d624c6c61548ab5fb8cd41022018152" + "fdf3f4f7732e9d624c6c61548ab5fb8cd41022018152" +
"2ec8eca07de4860a4acdd12909d831cc56cbbac46220" + "2ec8eca07de4860a4acdd12909d831cc56cbbac46220" +
"82221a8768d1d09"), "82221a8768d1d09"),
@ -316,7 +293,7 @@ func TestCheckSignatureEncoding(t *testing.T) {
}, },
{ {
name: "bad 1st int marker magic", name: "bad 1st int marker magic",
sig: decodeHex("304403204e45e16932b8af514961a1d3a1a25" + sig: hexToBytes("304403204e45e16932b8af514961a1d3a1a25" +
"fdf3f4f7732e9d624c6c61548ab5fb8cd41022018152" + "fdf3f4f7732e9d624c6c61548ab5fb8cd41022018152" +
"2ec8eca07de4860a4acdd12909d831cc56cbbac46220" + "2ec8eca07de4860a4acdd12909d831cc56cbbac46220" +
"82221a8768d1d09"), "82221a8768d1d09"),
@ -324,7 +301,7 @@ func TestCheckSignatureEncoding(t *testing.T) {
}, },
{ {
name: "bad 2nd int marker", name: "bad 2nd int marker",
sig: decodeHex("304402204e45e16932b8af514961a1d3a1a25" + sig: hexToBytes("304402204e45e16932b8af514961a1d3a1a25" +
"fdf3f4f7732e9d624c6c61548ab5fb8cd41032018152" + "fdf3f4f7732e9d624c6c61548ab5fb8cd41032018152" +
"2ec8eca07de4860a4acdd12909d831cc56cbbac46220" + "2ec8eca07de4860a4acdd12909d831cc56cbbac46220" +
"82221a8768d1d09"), "82221a8768d1d09"),
@ -332,7 +309,7 @@ func TestCheckSignatureEncoding(t *testing.T) {
}, },
{ {
name: "short len", name: "short len",
sig: decodeHex("304302204e45e16932b8af514961a1d3a1a25" + sig: hexToBytes("304302204e45e16932b8af514961a1d3a1a25" +
"fdf3f4f7732e9d624c6c61548ab5fb8cd41022018152" + "fdf3f4f7732e9d624c6c61548ab5fb8cd41022018152" +
"2ec8eca07de4860a4acdd12909d831cc56cbbac46220" + "2ec8eca07de4860a4acdd12909d831cc56cbbac46220" +
"82221a8768d1d09"), "82221a8768d1d09"),
@ -340,7 +317,7 @@ func TestCheckSignatureEncoding(t *testing.T) {
}, },
{ {
name: "long len", name: "long len",
sig: decodeHex("304502204e45e16932b8af514961a1d3a1a25" + sig: hexToBytes("304502204e45e16932b8af514961a1d3a1a25" +
"fdf3f4f7732e9d624c6c61548ab5fb8cd41022018152" + "fdf3f4f7732e9d624c6c61548ab5fb8cd41022018152" +
"2ec8eca07de4860a4acdd12909d831cc56cbbac46220" + "2ec8eca07de4860a4acdd12909d831cc56cbbac46220" +
"82221a8768d1d09"), "82221a8768d1d09"),
@ -348,7 +325,7 @@ func TestCheckSignatureEncoding(t *testing.T) {
}, },
{ {
name: "long X", name: "long X",
sig: decodeHex("304402424e45e16932b8af514961a1d3a1a25" + sig: hexToBytes("304402424e45e16932b8af514961a1d3a1a25" +
"fdf3f4f7732e9d624c6c61548ab5fb8cd41022018152" + "fdf3f4f7732e9d624c6c61548ab5fb8cd41022018152" +
"2ec8eca07de4860a4acdd12909d831cc56cbbac46220" + "2ec8eca07de4860a4acdd12909d831cc56cbbac46220" +
"82221a8768d1d09"), "82221a8768d1d09"),
@ -356,7 +333,7 @@ func TestCheckSignatureEncoding(t *testing.T) {
}, },
{ {
name: "long Y", name: "long Y",
sig: decodeHex("304402204e45e16932b8af514961a1d3a1a25" + sig: hexToBytes("304402204e45e16932b8af514961a1d3a1a25" +
"fdf3f4f7732e9d624c6c61548ab5fb8cd41022118152" + "fdf3f4f7732e9d624c6c61548ab5fb8cd41022118152" +
"2ec8eca07de4860a4acdd12909d831cc56cbbac46220" + "2ec8eca07de4860a4acdd12909d831cc56cbbac46220" +
"82221a8768d1d09"), "82221a8768d1d09"),
@ -364,7 +341,7 @@ func TestCheckSignatureEncoding(t *testing.T) {
}, },
{ {
name: "short Y", name: "short Y",
sig: decodeHex("304402204e45e16932b8af514961a1d3a1a25" + sig: hexToBytes("304402204e45e16932b8af514961a1d3a1a25" +
"fdf3f4f7732e9d624c6c61548ab5fb8cd41021918152" + "fdf3f4f7732e9d624c6c61548ab5fb8cd41021918152" +
"2ec8eca07de4860a4acdd12909d831cc56cbbac46220" + "2ec8eca07de4860a4acdd12909d831cc56cbbac46220" +
"82221a8768d1d09"), "82221a8768d1d09"),
@ -372,7 +349,7 @@ func TestCheckSignatureEncoding(t *testing.T) {
}, },
{ {
name: "trailing crap", name: "trailing crap",
sig: decodeHex("304402204e45e16932b8af514961a1d3a1a25" + sig: hexToBytes("304402204e45e16932b8af514961a1d3a1a25" +
"fdf3f4f7732e9d624c6c61548ab5fb8cd41022018152" + "fdf3f4f7732e9d624c6c61548ab5fb8cd41022018152" +
"2ec8eca07de4860a4acdd12909d831cc56cbbac46220" + "2ec8eca07de4860a4acdd12909d831cc56cbbac46220" +
"82221a8768d1d0901"), "82221a8768d1d0901"),
@ -380,7 +357,7 @@ func TestCheckSignatureEncoding(t *testing.T) {
}, },
{ {
name: "X == N ", name: "X == N ",
sig: decodeHex("30440220fffffffffffffffffffffffffffff" + sig: hexToBytes("30440220fffffffffffffffffffffffffffff" +
"ffebaaedce6af48a03bbfd25e8cd0364141022018152" + "ffebaaedce6af48a03bbfd25e8cd0364141022018152" +
"2ec8eca07de4860a4acdd12909d831cc56cbbac46220" + "2ec8eca07de4860a4acdd12909d831cc56cbbac46220" +
"82221a8768d1d09"), "82221a8768d1d09"),
@ -388,7 +365,7 @@ func TestCheckSignatureEncoding(t *testing.T) {
}, },
{ {
name: "X == N ", name: "X == N ",
sig: decodeHex("30440220fffffffffffffffffffffffffffff" + sig: hexToBytes("30440220fffffffffffffffffffffffffffff" +
"ffebaaedce6af48a03bbfd25e8cd0364142022018152" + "ffebaaedce6af48a03bbfd25e8cd0364142022018152" +
"2ec8eca07de4860a4acdd12909d831cc56cbbac46220" + "2ec8eca07de4860a4acdd12909d831cc56cbbac46220" +
"82221a8768d1d09"), "82221a8768d1d09"),
@ -396,7 +373,7 @@ func TestCheckSignatureEncoding(t *testing.T) {
}, },
{ {
name: "Y == N", name: "Y == N",
sig: decodeHex("304402204e45e16932b8af514961a1d3a1a25" + sig: hexToBytes("304402204e45e16932b8af514961a1d3a1a25" +
"fdf3f4f7732e9d624c6c61548ab5fb8cd410220fffff" + "fdf3f4f7732e9d624c6c61548ab5fb8cd410220fffff" +
"ffffffffffffffffffffffffffebaaedce6af48a03bb" + "ffffffffffffffffffffffffffebaaedce6af48a03bb" +
"fd25e8cd0364141"), "fd25e8cd0364141"),
@ -404,7 +381,7 @@ func TestCheckSignatureEncoding(t *testing.T) {
}, },
{ {
name: "Y > N", name: "Y > N",
sig: decodeHex("304402204e45e16932b8af514961a1d3a1a25" + sig: hexToBytes("304402204e45e16932b8af514961a1d3a1a25" +
"fdf3f4f7732e9d624c6c61548ab5fb8cd410220fffff" + "fdf3f4f7732e9d624c6c61548ab5fb8cd410220fffff" +
"ffffffffffffffffffffffffffebaaedce6af48a03bb" + "ffffffffffffffffffffffffffebaaedce6af48a03bb" +
"fd25e8cd0364142"), "fd25e8cd0364142"),
@ -412,19 +389,19 @@ func TestCheckSignatureEncoding(t *testing.T) {
}, },
{ {
name: "0 len X", name: "0 len X",
sig: decodeHex("302402000220181522ec8eca07de4860a4acd" + sig: hexToBytes("302402000220181522ec8eca07de4860a4acd" +
"d12909d831cc56cbbac4622082221a8768d1d09"), "d12909d831cc56cbbac4622082221a8768d1d09"),
isValid: false, isValid: false,
}, },
{ {
name: "0 len Y", name: "0 len Y",
sig: decodeHex("302402204e45e16932b8af514961a1d3a1a25" + sig: hexToBytes("302402204e45e16932b8af514961a1d3a1a25" +
"fdf3f4f7732e9d624c6c61548ab5fb8cd410200"), "fdf3f4f7732e9d624c6c61548ab5fb8cd410200"),
isValid: false, isValid: false,
}, },
{ {
name: "extra R padding", name: "extra R padding",
sig: decodeHex("30450221004e45e16932b8af514961a1d3a1a" + sig: hexToBytes("30450221004e45e16932b8af514961a1d3a1a" +
"25fdf3f4f7732e9d624c6c61548ab5fb8cd410220181" + "25fdf3f4f7732e9d624c6c61548ab5fb8cd410220181" +
"522ec8eca07de4860a4acdd12909d831cc56cbbac462" + "522ec8eca07de4860a4acdd12909d831cc56cbbac462" +
"2082221a8768d1d09"), "2082221a8768d1d09"),
@ -432,7 +409,7 @@ func TestCheckSignatureEncoding(t *testing.T) {
}, },
{ {
name: "extra S padding", name: "extra S padding",
sig: decodeHex("304502204e45e16932b8af514961a1d3a1a25" + sig: hexToBytes("304502204e45e16932b8af514961a1d3a1a25" +
"fdf3f4f7732e9d624c6c61548ab5fb8cd41022100181" + "fdf3f4f7732e9d624c6c61548ab5fb8cd41022100181" +
"522ec8eca07de4860a4acdd12909d831cc56cbbac462" + "522ec8eca07de4860a4acdd12909d831cc56cbbac462" +
"2082221a8768d1d09"), "2082221a8768d1d09"),
@ -440,9 +417,9 @@ func TestCheckSignatureEncoding(t *testing.T) {
}, },
} }
flags := txscript.ScriptVerifyStrictEncoding vm := Engine{flags: ScriptVerifyStrictEncoding}
for _, test := range tests { for _, test := range tests {
err := txscript.TstCheckSignatureEncoding(test.sig, flags) err := vm.checkSignatureEncoding(test.sig)
if err != nil && test.isValid { if err != nil && test.isValid {
t.Errorf("checkSignatureEncoding test '%s' failed "+ t.Errorf("checkSignatureEncoding test '%s' failed "+
"when it should have succeeded: %v", test.name, "when it should have succeeded: %v", test.name,

File diff suppressed because it is too large Load diff

View file

@ -1,16 +1,14 @@
// Copyright (c) 2013-2015 The btcsuite developers // Copyright (c) 2013-2016 The btcsuite developers
// Use of this source code is governed by an ISC // Use of this source code is governed by an ISC
// license that can be found in the LICENSE file. // license that can be found in the LICENSE file.
package txscript_test package txscript
import ( import (
"errors" "errors"
"io" "io"
"os" "os"
"testing" "testing"
"github.com/btcsuite/btcd/txscript"
) )
func TestSetLogWriter(t *testing.T) { func TestSetLogWriter(t *testing.T) {
@ -48,7 +46,7 @@ func TestSetLogWriter(t *testing.T) {
t.Logf("Running %d tests", len(tests)) t.Logf("Running %d tests", len(tests))
for i, test := range tests { for i, test := range tests {
err := txscript.SetLogWriter(test.w, test.level) err := SetLogWriter(test.w, test.level)
if err != nil { if err != nil {
if err.Error() != test.expected.Error() { if err.Error() != test.expected.Error() {
t.Errorf("SetLogWriter #%d (%s) wrong result\n"+ t.Errorf("SetLogWriter #%d (%s) wrong result\n"+

View file

@ -2,7 +2,7 @@
// Use of this source code is governed by an ISC // Use of this source code is governed by an ISC
// license that can be found in the LICENSE file. // license that can be found in the LICENSE file.
package txscript_test package txscript
import ( import (
"bytes" "bytes"
@ -16,7 +16,6 @@ import (
"testing" "testing"
"github.com/btcsuite/btcd/chaincfg/chainhash" "github.com/btcsuite/btcd/chaincfg/chainhash"
. "github.com/btcsuite/btcd/txscript"
"github.com/btcsuite/btcd/wire" "github.com/btcsuite/btcd/wire"
"github.com/btcsuite/btcutil" "github.com/btcsuite/btcutil"
) )
@ -102,7 +101,12 @@ func parseShortForm(script string) ([]byte, error) {
builder.AddInt64(num) builder.AddInt64(num)
continue continue
} else if bts, err := parseHex(tok); err == nil { } else if bts, err := parseHex(tok); err == nil {
builder.TstConcatRawScript(bts) // Concatenate the bytes manually since the test code
// intentionally creates scripts that are too large and
// would cause the builder to error otherwise.
if builder.err == nil {
builder.script = append(builder.script, bts...)
}
} else if len(tok) >= 2 && } else if len(tok) >= 2 &&
tok[0] == '\'' && tok[len(tok)-1] == '\'' { tok[0] == '\'' && tok[len(tok)-1] == '\'' {
builder.AddFullData([]byte(tok[1 : len(tok)-1])) builder.AddFullData([]byte(tok[1 : len(tok)-1]))
@ -648,7 +652,7 @@ func TestCalcSignatureHash(t *testing.T) {
} }
subScript, _ := hex.DecodeString(test[1].(string)) subScript, _ := hex.DecodeString(test[1].(string))
parsedScript, err := TstParseScript(subScript) parsedScript, err := parseScript(subScript)
if err != nil { if err != nil {
t.Errorf("TestCalcSignatureHash failed test #%d: "+ t.Errorf("TestCalcSignatureHash failed test #%d: "+
"Failed to parse sub-script: %v", i, err) "Failed to parse sub-script: %v", i, err)
@ -656,7 +660,7 @@ func TestCalcSignatureHash(t *testing.T) {
} }
hashType := SigHashType(testVecF64ToUint32(test[3].(float64))) hashType := SigHashType(testVecF64ToUint32(test[3].(float64)))
hash := TstCalcSignatureHash(parsedScript, hashType, tx, hash := calcSignatureHash(parsedScript, hashType, tx,
int(test[2].(float64))) int(test[2].(float64)))
expectedHash, _ := chainhash.NewHashFromStr(test[4].(string)) expectedHash, _ := chainhash.NewHashFromStr(test[4].(string))

File diff suppressed because it is too large Load diff

View file

@ -1,14 +1,12 @@
// Copyright (c) 2013-2015 The btcsuite developers // Copyright (c) 2013-2016 The btcsuite developers
// Use of this source code is governed by an ISC // Use of this source code is governed by an ISC
// license that can be found in the LICENSE file. // license that can be found in the LICENSE file.
package txscript_test package txscript
import ( import (
"bytes" "bytes"
"testing" "testing"
"github.com/btcsuite/btcd/txscript"
) )
// TestScriptBuilderAddOp tests that pushing opcodes to a script via the // TestScriptBuilderAddOp tests that pushing opcodes to a script via the
@ -23,23 +21,23 @@ func TestScriptBuilderAddOp(t *testing.T) {
}{ }{
{ {
name: "push OP_0", name: "push OP_0",
opcodes: []byte{txscript.OP_0}, opcodes: []byte{OP_0},
expected: []byte{txscript.OP_0}, expected: []byte{OP_0},
}, },
{ {
name: "push OP_1 OP_2", name: "push OP_1 OP_2",
opcodes: []byte{txscript.OP_1, txscript.OP_2}, opcodes: []byte{OP_1, OP_2},
expected: []byte{txscript.OP_1, txscript.OP_2}, expected: []byte{OP_1, OP_2},
}, },
{ {
name: "push OP_HASH160 OP_EQUAL", name: "push OP_HASH160 OP_EQUAL",
opcodes: []byte{txscript.OP_HASH160, txscript.OP_EQUAL}, opcodes: []byte{OP_HASH160, OP_EQUAL},
expected: []byte{txscript.OP_HASH160, txscript.OP_EQUAL}, expected: []byte{OP_HASH160, OP_EQUAL},
}, },
} }
// Run tests and individually add each op via AddOp. // Run tests and individually add each op via AddOp.
builder := txscript.NewScriptBuilder() builder := NewScriptBuilder()
t.Logf("Running %d tests", len(tests)) t.Logf("Running %d tests", len(tests))
for i, test := range tests { for i, test := range tests {
builder.Reset() builder.Reset()
@ -90,47 +88,47 @@ func TestScriptBuilderAddInt64(t *testing.T) {
val int64 val int64
expected []byte expected []byte
}{ }{
{name: "push -1", val: -1, expected: []byte{txscript.OP_1NEGATE}}, {name: "push -1", val: -1, expected: []byte{OP_1NEGATE}},
{name: "push small int 0", val: 0, expected: []byte{txscript.OP_0}}, {name: "push small int 0", val: 0, expected: []byte{OP_0}},
{name: "push small int 1", val: 1, expected: []byte{txscript.OP_1}}, {name: "push small int 1", val: 1, expected: []byte{OP_1}},
{name: "push small int 2", val: 2, expected: []byte{txscript.OP_2}}, {name: "push small int 2", val: 2, expected: []byte{OP_2}},
{name: "push small int 3", val: 3, expected: []byte{txscript.OP_3}}, {name: "push small int 3", val: 3, expected: []byte{OP_3}},
{name: "push small int 4", val: 4, expected: []byte{txscript.OP_4}}, {name: "push small int 4", val: 4, expected: []byte{OP_4}},
{name: "push small int 5", val: 5, expected: []byte{txscript.OP_5}}, {name: "push small int 5", val: 5, expected: []byte{OP_5}},
{name: "push small int 6", val: 6, expected: []byte{txscript.OP_6}}, {name: "push small int 6", val: 6, expected: []byte{OP_6}},
{name: "push small int 7", val: 7, expected: []byte{txscript.OP_7}}, {name: "push small int 7", val: 7, expected: []byte{OP_7}},
{name: "push small int 8", val: 8, expected: []byte{txscript.OP_8}}, {name: "push small int 8", val: 8, expected: []byte{OP_8}},
{name: "push small int 9", val: 9, expected: []byte{txscript.OP_9}}, {name: "push small int 9", val: 9, expected: []byte{OP_9}},
{name: "push small int 10", val: 10, expected: []byte{txscript.OP_10}}, {name: "push small int 10", val: 10, expected: []byte{OP_10}},
{name: "push small int 11", val: 11, expected: []byte{txscript.OP_11}}, {name: "push small int 11", val: 11, expected: []byte{OP_11}},
{name: "push small int 12", val: 12, expected: []byte{txscript.OP_12}}, {name: "push small int 12", val: 12, expected: []byte{OP_12}},
{name: "push small int 13", val: 13, expected: []byte{txscript.OP_13}}, {name: "push small int 13", val: 13, expected: []byte{OP_13}},
{name: "push small int 14", val: 14, expected: []byte{txscript.OP_14}}, {name: "push small int 14", val: 14, expected: []byte{OP_14}},
{name: "push small int 15", val: 15, expected: []byte{txscript.OP_15}}, {name: "push small int 15", val: 15, expected: []byte{OP_15}},
{name: "push small int 16", val: 16, expected: []byte{txscript.OP_16}}, {name: "push small int 16", val: 16, expected: []byte{OP_16}},
{name: "push 17", val: 17, expected: []byte{txscript.OP_DATA_1, 0x11}}, {name: "push 17", val: 17, expected: []byte{OP_DATA_1, 0x11}},
{name: "push 65", val: 65, expected: []byte{txscript.OP_DATA_1, 0x41}}, {name: "push 65", val: 65, expected: []byte{OP_DATA_1, 0x41}},
{name: "push 127", val: 127, expected: []byte{txscript.OP_DATA_1, 0x7f}}, {name: "push 127", val: 127, expected: []byte{OP_DATA_1, 0x7f}},
{name: "push 128", val: 128, expected: []byte{txscript.OP_DATA_2, 0x80, 0}}, {name: "push 128", val: 128, expected: []byte{OP_DATA_2, 0x80, 0}},
{name: "push 255", val: 255, expected: []byte{txscript.OP_DATA_2, 0xff, 0}}, {name: "push 255", val: 255, expected: []byte{OP_DATA_2, 0xff, 0}},
{name: "push 256", val: 256, expected: []byte{txscript.OP_DATA_2, 0, 0x01}}, {name: "push 256", val: 256, expected: []byte{OP_DATA_2, 0, 0x01}},
{name: "push 32767", val: 32767, expected: []byte{txscript.OP_DATA_2, 0xff, 0x7f}}, {name: "push 32767", val: 32767, expected: []byte{OP_DATA_2, 0xff, 0x7f}},
{name: "push 32768", val: 32768, expected: []byte{txscript.OP_DATA_3, 0, 0x80, 0}}, {name: "push 32768", val: 32768, expected: []byte{OP_DATA_3, 0, 0x80, 0}},
{name: "push -2", val: -2, expected: []byte{txscript.OP_DATA_1, 0x82}}, {name: "push -2", val: -2, expected: []byte{OP_DATA_1, 0x82}},
{name: "push -3", val: -3, expected: []byte{txscript.OP_DATA_1, 0x83}}, {name: "push -3", val: -3, expected: []byte{OP_DATA_1, 0x83}},
{name: "push -4", val: -4, expected: []byte{txscript.OP_DATA_1, 0x84}}, {name: "push -4", val: -4, expected: []byte{OP_DATA_1, 0x84}},
{name: "push -5", val: -5, expected: []byte{txscript.OP_DATA_1, 0x85}}, {name: "push -5", val: -5, expected: []byte{OP_DATA_1, 0x85}},
{name: "push -17", val: -17, expected: []byte{txscript.OP_DATA_1, 0x91}}, {name: "push -17", val: -17, expected: []byte{OP_DATA_1, 0x91}},
{name: "push -65", val: -65, expected: []byte{txscript.OP_DATA_1, 0xc1}}, {name: "push -65", val: -65, expected: []byte{OP_DATA_1, 0xc1}},
{name: "push -127", val: -127, expected: []byte{txscript.OP_DATA_1, 0xff}}, {name: "push -127", val: -127, expected: []byte{OP_DATA_1, 0xff}},
{name: "push -128", val: -128, expected: []byte{txscript.OP_DATA_2, 0x80, 0x80}}, {name: "push -128", val: -128, expected: []byte{OP_DATA_2, 0x80, 0x80}},
{name: "push -255", val: -255, expected: []byte{txscript.OP_DATA_2, 0xff, 0x80}}, {name: "push -255", val: -255, expected: []byte{OP_DATA_2, 0xff, 0x80}},
{name: "push -256", val: -256, expected: []byte{txscript.OP_DATA_2, 0x00, 0x81}}, {name: "push -256", val: -256, expected: []byte{OP_DATA_2, 0x00, 0x81}},
{name: "push -32767", val: -32767, expected: []byte{txscript.OP_DATA_2, 0xff, 0xff}}, {name: "push -32767", val: -32767, expected: []byte{OP_DATA_2, 0xff, 0xff}},
{name: "push -32768", val: -32768, expected: []byte{txscript.OP_DATA_3, 0x00, 0x80, 0x80}}, {name: "push -32768", val: -32768, expected: []byte{OP_DATA_3, 0x00, 0x80, 0x80}},
} }
builder := txscript.NewScriptBuilder() builder := NewScriptBuilder()
t.Logf("Running %d tests", len(tests)) t.Logf("Running %d tests", len(tests))
for i, test := range tests { for i, test := range tests {
builder.Reset().AddInt64(test.val) builder.Reset().AddInt64(test.val)
@ -161,70 +159,70 @@ func TestScriptBuilderAddData(t *testing.T) {
useFull bool // use AddFullData instead of AddData. useFull bool // use AddFullData instead of AddData.
}{ }{
// BIP0062: Pushing an empty byte sequence must use OP_0. // BIP0062: Pushing an empty byte sequence must use OP_0.
{name: "push empty byte sequence", data: nil, expected: []byte{txscript.OP_0}}, {name: "push empty byte sequence", data: nil, expected: []byte{OP_0}},
{name: "push 1 byte 0x00", data: []byte{0x00}, expected: []byte{txscript.OP_0}}, {name: "push 1 byte 0x00", data: []byte{0x00}, expected: []byte{OP_0}},
// BIP0062: Pushing a 1-byte sequence of byte 0x01 through 0x10 must use OP_n. // BIP0062: Pushing a 1-byte sequence of byte 0x01 through 0x10 must use OP_n.
{name: "push 1 byte 0x01", data: []byte{0x01}, expected: []byte{txscript.OP_1}}, {name: "push 1 byte 0x01", data: []byte{0x01}, expected: []byte{OP_1}},
{name: "push 1 byte 0x02", data: []byte{0x02}, expected: []byte{txscript.OP_2}}, {name: "push 1 byte 0x02", data: []byte{0x02}, expected: []byte{OP_2}},
{name: "push 1 byte 0x03", data: []byte{0x03}, expected: []byte{txscript.OP_3}}, {name: "push 1 byte 0x03", data: []byte{0x03}, expected: []byte{OP_3}},
{name: "push 1 byte 0x04", data: []byte{0x04}, expected: []byte{txscript.OP_4}}, {name: "push 1 byte 0x04", data: []byte{0x04}, expected: []byte{OP_4}},
{name: "push 1 byte 0x05", data: []byte{0x05}, expected: []byte{txscript.OP_5}}, {name: "push 1 byte 0x05", data: []byte{0x05}, expected: []byte{OP_5}},
{name: "push 1 byte 0x06", data: []byte{0x06}, expected: []byte{txscript.OP_6}}, {name: "push 1 byte 0x06", data: []byte{0x06}, expected: []byte{OP_6}},
{name: "push 1 byte 0x07", data: []byte{0x07}, expected: []byte{txscript.OP_7}}, {name: "push 1 byte 0x07", data: []byte{0x07}, expected: []byte{OP_7}},
{name: "push 1 byte 0x08", data: []byte{0x08}, expected: []byte{txscript.OP_8}}, {name: "push 1 byte 0x08", data: []byte{0x08}, expected: []byte{OP_8}},
{name: "push 1 byte 0x09", data: []byte{0x09}, expected: []byte{txscript.OP_9}}, {name: "push 1 byte 0x09", data: []byte{0x09}, expected: []byte{OP_9}},
{name: "push 1 byte 0x0a", data: []byte{0x0a}, expected: []byte{txscript.OP_10}}, {name: "push 1 byte 0x0a", data: []byte{0x0a}, expected: []byte{OP_10}},
{name: "push 1 byte 0x0b", data: []byte{0x0b}, expected: []byte{txscript.OP_11}}, {name: "push 1 byte 0x0b", data: []byte{0x0b}, expected: []byte{OP_11}},
{name: "push 1 byte 0x0c", data: []byte{0x0c}, expected: []byte{txscript.OP_12}}, {name: "push 1 byte 0x0c", data: []byte{0x0c}, expected: []byte{OP_12}},
{name: "push 1 byte 0x0d", data: []byte{0x0d}, expected: []byte{txscript.OP_13}}, {name: "push 1 byte 0x0d", data: []byte{0x0d}, expected: []byte{OP_13}},
{name: "push 1 byte 0x0e", data: []byte{0x0e}, expected: []byte{txscript.OP_14}}, {name: "push 1 byte 0x0e", data: []byte{0x0e}, expected: []byte{OP_14}},
{name: "push 1 byte 0x0f", data: []byte{0x0f}, expected: []byte{txscript.OP_15}}, {name: "push 1 byte 0x0f", data: []byte{0x0f}, expected: []byte{OP_15}},
{name: "push 1 byte 0x10", data: []byte{0x10}, expected: []byte{txscript.OP_16}}, {name: "push 1 byte 0x10", data: []byte{0x10}, expected: []byte{OP_16}},
// BIP0062: Pushing the byte 0x81 must use OP_1NEGATE. // BIP0062: Pushing the byte 0x81 must use OP_1NEGATE.
{name: "push 1 byte 0x81", data: []byte{0x81}, expected: []byte{txscript.OP_1NEGATE}}, {name: "push 1 byte 0x81", data: []byte{0x81}, expected: []byte{OP_1NEGATE}},
// BIP0062: Pushing any other byte sequence up to 75 bytes must // BIP0062: Pushing any other byte sequence up to 75 bytes must
// use the normal data push (opcode byte n, with n the number of // use the normal data push (opcode byte n, with n the number of
// bytes, followed n bytes of data being pushed). // bytes, followed n bytes of data being pushed).
{name: "push 1 byte 0x11", data: []byte{0x11}, expected: []byte{txscript.OP_DATA_1, 0x11}}, {name: "push 1 byte 0x11", data: []byte{0x11}, expected: []byte{OP_DATA_1, 0x11}},
{name: "push 1 byte 0x80", data: []byte{0x80}, expected: []byte{txscript.OP_DATA_1, 0x80}}, {name: "push 1 byte 0x80", data: []byte{0x80}, expected: []byte{OP_DATA_1, 0x80}},
{name: "push 1 byte 0x82", data: []byte{0x82}, expected: []byte{txscript.OP_DATA_1, 0x82}}, {name: "push 1 byte 0x82", data: []byte{0x82}, expected: []byte{OP_DATA_1, 0x82}},
{name: "push 1 byte 0xff", data: []byte{0xff}, expected: []byte{txscript.OP_DATA_1, 0xff}}, {name: "push 1 byte 0xff", data: []byte{0xff}, expected: []byte{OP_DATA_1, 0xff}},
{ {
name: "push data len 17", name: "push data len 17",
data: bytes.Repeat([]byte{0x49}, 17), data: bytes.Repeat([]byte{0x49}, 17),
expected: append([]byte{txscript.OP_DATA_17}, bytes.Repeat([]byte{0x49}, 17)...), expected: append([]byte{OP_DATA_17}, bytes.Repeat([]byte{0x49}, 17)...),
}, },
{ {
name: "push data len 75", name: "push data len 75",
data: bytes.Repeat([]byte{0x49}, 75), data: bytes.Repeat([]byte{0x49}, 75),
expected: append([]byte{txscript.OP_DATA_75}, bytes.Repeat([]byte{0x49}, 75)...), expected: append([]byte{OP_DATA_75}, bytes.Repeat([]byte{0x49}, 75)...),
}, },
// BIP0062: Pushing 76 to 255 bytes must use OP_PUSHDATA1. // BIP0062: Pushing 76 to 255 bytes must use OP_PUSHDATA1.
{ {
name: "push data len 76", name: "push data len 76",
data: bytes.Repeat([]byte{0x49}, 76), data: bytes.Repeat([]byte{0x49}, 76),
expected: append([]byte{txscript.OP_PUSHDATA1, 76}, bytes.Repeat([]byte{0x49}, 76)...), expected: append([]byte{OP_PUSHDATA1, 76}, bytes.Repeat([]byte{0x49}, 76)...),
}, },
{ {
name: "push data len 255", name: "push data len 255",
data: bytes.Repeat([]byte{0x49}, 255), data: bytes.Repeat([]byte{0x49}, 255),
expected: append([]byte{txscript.OP_PUSHDATA1, 255}, bytes.Repeat([]byte{0x49}, 255)...), expected: append([]byte{OP_PUSHDATA1, 255}, bytes.Repeat([]byte{0x49}, 255)...),
}, },
// BIP0062: Pushing 256 to 520 bytes must use OP_PUSHDATA2. // BIP0062: Pushing 256 to 520 bytes must use OP_PUSHDATA2.
{ {
name: "push data len 256", name: "push data len 256",
data: bytes.Repeat([]byte{0x49}, 256), data: bytes.Repeat([]byte{0x49}, 256),
expected: append([]byte{txscript.OP_PUSHDATA2, 0, 1}, bytes.Repeat([]byte{0x49}, 256)...), expected: append([]byte{OP_PUSHDATA2, 0, 1}, bytes.Repeat([]byte{0x49}, 256)...),
}, },
{ {
name: "push data len 520", name: "push data len 520",
data: bytes.Repeat([]byte{0x49}, 520), data: bytes.Repeat([]byte{0x49}, 520),
expected: append([]byte{txscript.OP_PUSHDATA2, 0x08, 0x02}, bytes.Repeat([]byte{0x49}, 520)...), expected: append([]byte{OP_PUSHDATA2, 0x08, 0x02}, bytes.Repeat([]byte{0x49}, 520)...),
}, },
// BIP0062: OP_PUSHDATA4 can never be used, as pushes over 520 // BIP0062: OP_PUSHDATA4 can never be used, as pushes over 520
@ -254,7 +252,7 @@ func TestScriptBuilderAddData(t *testing.T) {
{ {
name: "push data len 32767 (non-canonical)", name: "push data len 32767 (non-canonical)",
data: bytes.Repeat([]byte{0x49}, 32767), data: bytes.Repeat([]byte{0x49}, 32767),
expected: append([]byte{txscript.OP_PUSHDATA2, 255, 127}, bytes.Repeat([]byte{0x49}, 32767)...), expected: append([]byte{OP_PUSHDATA2, 255, 127}, bytes.Repeat([]byte{0x49}, 32767)...),
useFull: true, useFull: true,
}, },
@ -262,12 +260,12 @@ func TestScriptBuilderAddData(t *testing.T) {
{ {
name: "push data len 65536 (non-canonical)", name: "push data len 65536 (non-canonical)",
data: bytes.Repeat([]byte{0x49}, 65536), data: bytes.Repeat([]byte{0x49}, 65536),
expected: append([]byte{txscript.OP_PUSHDATA4, 0, 0, 1, 0}, bytes.Repeat([]byte{0x49}, 65536)...), expected: append([]byte{OP_PUSHDATA4, 0, 0, 1, 0}, bytes.Repeat([]byte{0x49}, 65536)...),
useFull: true, useFull: true,
}, },
} }
builder := txscript.NewScriptBuilder() builder := NewScriptBuilder()
t.Logf("Running %d tests", len(tests)) t.Logf("Running %d tests", len(tests))
for i, test := range tests { for i, test := range tests {
if !test.useFull { if !test.useFull {
@ -292,8 +290,7 @@ func TestExceedMaxScriptSize(t *testing.T) {
t.Parallel() t.Parallel()
// Start off by constructing a max size script. // Start off by constructing a max size script.
maxScriptSize := txscript.TstMaxScriptSize builder := NewScriptBuilder()
builder := txscript.NewScriptBuilder()
builder.Reset().AddFullData(make([]byte, maxScriptSize-3)) builder.Reset().AddFullData(make([]byte, maxScriptSize-3))
origScript, err := builder.Script() origScript, err := builder.Script()
if err != nil { if err != nil {
@ -303,7 +300,7 @@ func TestExceedMaxScriptSize(t *testing.T) {
// Ensure adding data that would exceed the maximum size of the script // Ensure adding data that would exceed the maximum size of the script
// does not add the data. // does not add the data.
script, err := builder.AddData([]byte{0x00}).Script() script, err := builder.AddData([]byte{0x00}).Script()
if _, ok := err.(txscript.ErrScriptNotCanonical); !ok || err == nil { if _, ok := err.(ErrScriptNotCanonical); !ok || err == nil {
t.Fatalf("ScriptBuilder.AddData allowed exceeding max script "+ t.Fatalf("ScriptBuilder.AddData allowed exceeding max script "+
"size: %v", len(script)) "size: %v", len(script))
} }
@ -315,8 +312,8 @@ func TestExceedMaxScriptSize(t *testing.T) {
// Ensure adding an opcode that would exceed the maximum size of the // Ensure adding an opcode that would exceed the maximum size of the
// script does not add the data. // script does not add the data.
builder.Reset().AddFullData(make([]byte, maxScriptSize-3)) builder.Reset().AddFullData(make([]byte, maxScriptSize-3))
script, err = builder.AddOp(txscript.OP_0).Script() script, err = builder.AddOp(OP_0).Script()
if _, ok := err.(txscript.ErrScriptNotCanonical); !ok || err == nil { if _, ok := err.(ErrScriptNotCanonical); !ok || err == nil {
t.Fatalf("ScriptBuilder.AddOp unexpected modified script - "+ t.Fatalf("ScriptBuilder.AddOp unexpected modified script - "+
"got len %d, want len %d", len(script), len(origScript)) "got len %d, want len %d", len(script), len(origScript))
} }
@ -329,7 +326,7 @@ func TestExceedMaxScriptSize(t *testing.T) {
// script does not add the data. // script does not add the data.
builder.Reset().AddFullData(make([]byte, maxScriptSize-3)) builder.Reset().AddFullData(make([]byte, maxScriptSize-3))
script, err = builder.AddInt64(0).Script() script, err = builder.AddInt64(0).Script()
if _, ok := err.(txscript.ErrScriptNotCanonical); !ok || err == nil { if _, ok := err.(ErrScriptNotCanonical); !ok || err == nil {
t.Fatalf("ScriptBuilder.AddInt64 unexpected modified script - "+ t.Fatalf("ScriptBuilder.AddInt64 unexpected modified script - "+
"got len %d, want len %d", len(script), len(origScript)) "got len %d, want len %d", len(script), len(origScript))
} }
@ -347,15 +344,14 @@ func TestErroredScript(t *testing.T) {
// Start off by constructing a near max size script that has enough // Start off by constructing a near max size script that has enough
// space left to add each data type without an error and force an // space left to add each data type without an error and force an
// initial error condition. // initial error condition.
maxScriptSize := txscript.TstMaxScriptSize builder := NewScriptBuilder()
builder := txscript.NewScriptBuilder()
builder.Reset().AddFullData(make([]byte, maxScriptSize-8)) builder.Reset().AddFullData(make([]byte, maxScriptSize-8))
origScript, err := builder.Script() origScript, err := builder.Script()
if err != nil { if err != nil {
t.Fatalf("ScriptBuilder.AddFullData unexpected error: %v", err) t.Fatalf("ScriptBuilder.AddFullData unexpected error: %v", err)
} }
script, err := builder.AddData([]byte{0x00, 0x00, 0x00, 0x00, 0x00}).Script() script, err := builder.AddData([]byte{0x00, 0x00, 0x00, 0x00, 0x00}).Script()
if _, ok := err.(txscript.ErrScriptNotCanonical); !ok || err == nil { if _, ok := err.(ErrScriptNotCanonical); !ok || err == nil {
t.Fatalf("ScriptBuilder.AddData allowed exceeding max script "+ t.Fatalf("ScriptBuilder.AddData allowed exceeding max script "+
"size: %v", len(script)) "size: %v", len(script))
} }
@ -367,7 +363,7 @@ func TestErroredScript(t *testing.T) {
// Ensure adding data, even using the non-canonical path, to a script // Ensure adding data, even using the non-canonical path, to a script
// that has errored doesn't succeed. // that has errored doesn't succeed.
script, err = builder.AddFullData([]byte{0x00}).Script() script, err = builder.AddFullData([]byte{0x00}).Script()
if _, ok := err.(txscript.ErrScriptNotCanonical); !ok || err == nil { if _, ok := err.(ErrScriptNotCanonical); !ok || err == nil {
t.Fatal("ScriptBuilder.AddFullData succeeded on errored script") t.Fatal("ScriptBuilder.AddFullData succeeded on errored script")
} }
if !bytes.Equal(script, origScript) { if !bytes.Equal(script, origScript) {
@ -378,7 +374,7 @@ func TestErroredScript(t *testing.T) {
// Ensure adding data to a script that has errored doesn't succeed. // Ensure adding data to a script that has errored doesn't succeed.
script, err = builder.AddData([]byte{0x00}).Script() script, err = builder.AddData([]byte{0x00}).Script()
if _, ok := err.(txscript.ErrScriptNotCanonical); !ok || err == nil { if _, ok := err.(ErrScriptNotCanonical); !ok || err == nil {
t.Fatal("ScriptBuilder.AddData succeeded on errored script") t.Fatal("ScriptBuilder.AddData succeeded on errored script")
} }
if !bytes.Equal(script, origScript) { if !bytes.Equal(script, origScript) {
@ -388,8 +384,8 @@ func TestErroredScript(t *testing.T) {
} }
// Ensure adding an opcode to a script that has errored doesn't succeed. // Ensure adding an opcode to a script that has errored doesn't succeed.
script, err = builder.AddOp(txscript.OP_0).Script() script, err = builder.AddOp(OP_0).Script()
if _, ok := err.(txscript.ErrScriptNotCanonical); !ok || err == nil { if _, ok := err.(ErrScriptNotCanonical); !ok || err == nil {
t.Fatal("ScriptBuilder.AddOp succeeded on errored script") t.Fatal("ScriptBuilder.AddOp succeeded on errored script")
} }
if !bytes.Equal(script, origScript) { if !bytes.Equal(script, origScript) {
@ -400,7 +396,7 @@ func TestErroredScript(t *testing.T) {
// Ensure adding an integer to a script that has errored doesn't // Ensure adding an integer to a script that has errored doesn't
// succeed. // succeed.
script, err = builder.AddInt64(0).Script() script, err = builder.AddInt64(0).Script()
if _, ok := err.(txscript.ErrScriptNotCanonical); !ok || err == nil { if _, ok := err.(ErrScriptNotCanonical); !ok || err == nil {
t.Fatal("ScriptBuilder.AddInt64 succeeded on errored script") t.Fatal("ScriptBuilder.AddInt64 succeeded on errored script")
} }
if !bytes.Equal(script, origScript) { if !bytes.Equal(script, origScript) {

View file

@ -2,7 +2,7 @@
// Use of this source code is governed by an ISC // Use of this source code is governed by an ISC
// license that can be found in the LICENSE file. // license that can be found in the LICENSE file.
package txscript_test package txscript
import ( import (
"errors" "errors"
@ -12,7 +12,6 @@ import (
"github.com/btcsuite/btcd/btcec" "github.com/btcsuite/btcd/btcec"
"github.com/btcsuite/btcd/chaincfg" "github.com/btcsuite/btcd/chaincfg"
"github.com/btcsuite/btcd/chaincfg/chainhash" "github.com/btcsuite/btcd/chaincfg/chainhash"
"github.com/btcsuite/btcd/txscript"
"github.com/btcsuite/btcd/wire" "github.com/btcsuite/btcd/wire"
"github.com/btcsuite/btcutil" "github.com/btcsuite/btcutil"
) )
@ -22,14 +21,14 @@ type addressToKey struct {
compressed bool compressed bool
} }
func mkGetKey(keys map[string]addressToKey) txscript.KeyDB { func mkGetKey(keys map[string]addressToKey) KeyDB {
if keys == nil { if keys == nil {
return txscript.KeyClosure(func(addr btcutil.Address) (*btcec.PrivateKey, return KeyClosure(func(addr btcutil.Address) (*btcec.PrivateKey,
bool, error) { bool, error) {
return nil, false, errors.New("nope") return nil, false, errors.New("nope")
}) })
} }
return txscript.KeyClosure(func(addr btcutil.Address) (*btcec.PrivateKey, return KeyClosure(func(addr btcutil.Address) (*btcec.PrivateKey,
bool, error) { bool, error) {
a2k, ok := keys[addr.EncodeAddress()] a2k, ok := keys[addr.EncodeAddress()]
if !ok { if !ok {
@ -39,15 +38,13 @@ func mkGetKey(keys map[string]addressToKey) txscript.KeyDB {
}) })
} }
func mkGetScript(scripts map[string][]byte) txscript.ScriptDB { func mkGetScript(scripts map[string][]byte) ScriptDB {
if scripts == nil { if scripts == nil {
return txscript.ScriptClosure(func(addr btcutil.Address) ( return ScriptClosure(func(addr btcutil.Address) ([]byte, error) {
[]byte, error) {
return nil, errors.New("nope") return nil, errors.New("nope")
}) })
} }
return txscript.ScriptClosure(func(addr btcutil.Address) ([]byte, return ScriptClosure(func(addr btcutil.Address) ([]byte, error) {
error) {
script, ok := scripts[addr.EncodeAddress()] script, ok := scripts[addr.EncodeAddress()]
if !ok { if !ok {
return nil, errors.New("nope") return nil, errors.New("nope")
@ -58,8 +55,8 @@ func mkGetScript(scripts map[string][]byte) txscript.ScriptDB {
func checkScripts(msg string, tx *wire.MsgTx, idx int, sigScript, pkScript []byte) error { func checkScripts(msg string, tx *wire.MsgTx, idx int, sigScript, pkScript []byte) error {
tx.TxIn[idx].SignatureScript = sigScript tx.TxIn[idx].SignatureScript = sigScript
vm, err := txscript.NewEngine(pkScript, tx, idx, vm, err := NewEngine(pkScript, tx, idx,
txscript.ScriptBip16|txscript.ScriptVerifyDERSignatures, nil) ScriptBip16|ScriptVerifyDERSignatures, nil)
if err != nil { if err != nil {
return fmt.Errorf("failed to make script engine for %s: %v", return fmt.Errorf("failed to make script engine for %s: %v",
msg, err) msg, err)
@ -75,11 +72,11 @@ func checkScripts(msg string, tx *wire.MsgTx, idx int, sigScript, pkScript []byt
} }
func signAndCheck(msg string, tx *wire.MsgTx, idx int, pkScript []byte, func signAndCheck(msg string, tx *wire.MsgTx, idx int, pkScript []byte,
hashType txscript.SigHashType, kdb txscript.KeyDB, sdb txscript.ScriptDB, hashType SigHashType, kdb KeyDB, sdb ScriptDB,
previousScript []byte) error { previousScript []byte) error {
sigScript, err := txscript.SignTxOutput(&chaincfg.TestNet3Params, tx, sigScript, err := SignTxOutput(&chaincfg.TestNet3Params, tx, idx,
idx, pkScript, hashType, kdb, sdb, nil) pkScript, hashType, kdb, sdb, nil)
if err != nil { if err != nil {
return fmt.Errorf("failed to sign output %s: %v", msg, err) return fmt.Errorf("failed to sign output %s: %v", msg, err)
} }
@ -93,14 +90,14 @@ func TestSignTxOutput(t *testing.T) {
// make key // make key
// make script based on key. // make script based on key.
// sign with magic pixie dust. // sign with magic pixie dust.
hashTypes := []txscript.SigHashType{ hashTypes := []SigHashType{
txscript.SigHashOld, // no longer used but should act like all SigHashOld, // no longer used but should act like all
txscript.SigHashAll, SigHashAll,
txscript.SigHashNone, SigHashNone,
txscript.SigHashSingle, SigHashSingle,
txscript.SigHashAll | txscript.SigHashAnyOneCanPay, SigHashAll | SigHashAnyOneCanPay,
txscript.SigHashNone | txscript.SigHashAnyOneCanPay, SigHashNone | SigHashAnyOneCanPay,
txscript.SigHashSingle | txscript.SigHashAnyOneCanPay, SigHashSingle | SigHashAnyOneCanPay,
} }
tx := &wire.MsgTx{ tx := &wire.MsgTx{
Version: 1, Version: 1,
@ -162,7 +159,7 @@ func TestSignTxOutput(t *testing.T) {
break break
} }
pkScript, err := txscript.PayToAddrScript(address) pkScript, err := PayToAddrScript(address)
if err != nil { if err != nil {
t.Errorf("failed to make pkscript "+ t.Errorf("failed to make pkscript "+
"for %s: %v", msg, err) "for %s: %v", msg, err)
@ -199,15 +196,15 @@ func TestSignTxOutput(t *testing.T) {
break break
} }
pkScript, err := txscript.PayToAddrScript(address) pkScript, err := PayToAddrScript(address)
if err != nil { if err != nil {
t.Errorf("failed to make pkscript "+ t.Errorf("failed to make pkscript "+
"for %s: %v", msg, err) "for %s: %v", msg, err)
} }
sigScript, err := txscript.SignTxOutput( sigScript, err := SignTxOutput(&chaincfg.TestNet3Params,
&chaincfg.TestNet3Params, tx, i, pkScript, tx, i, pkScript, hashType,
hashType, mkGetKey(map[string]addressToKey{ mkGetKey(map[string]addressToKey{
address.EncodeAddress(): {key, false}, address.EncodeAddress(): {key, false},
}), mkGetScript(nil), nil) }), mkGetScript(nil), nil)
if err != nil { if err != nil {
@ -218,9 +215,9 @@ func TestSignTxOutput(t *testing.T) {
// by the above loop, this should be valid, now sign // by the above loop, this should be valid, now sign
// again and merge. // again and merge.
sigScript, err = txscript.SignTxOutput( sigScript, err = SignTxOutput(&chaincfg.TestNet3Params,
&chaincfg.TestNet3Params, tx, i, pkScript, tx, i, pkScript, hashType,
hashType, mkGetKey(map[string]addressToKey{ mkGetKey(map[string]addressToKey{
address.EncodeAddress(): {key, false}, address.EncodeAddress(): {key, false},
}), mkGetScript(nil), sigScript) }), mkGetScript(nil), sigScript)
if err != nil { if err != nil {
@ -260,7 +257,7 @@ func TestSignTxOutput(t *testing.T) {
break break
} }
pkScript, err := txscript.PayToAddrScript(address) pkScript, err := PayToAddrScript(address)
if err != nil { if err != nil {
t.Errorf("failed to make pkscript "+ t.Errorf("failed to make pkscript "+
"for %s: %v", msg, err) "for %s: %v", msg, err)
@ -298,15 +295,15 @@ func TestSignTxOutput(t *testing.T) {
break break
} }
pkScript, err := txscript.PayToAddrScript(address) pkScript, err := PayToAddrScript(address)
if err != nil { if err != nil {
t.Errorf("failed to make pkscript "+ t.Errorf("failed to make pkscript "+
"for %s: %v", msg, err) "for %s: %v", msg, err)
} }
sigScript, err := txscript.SignTxOutput( sigScript, err := SignTxOutput(&chaincfg.TestNet3Params,
&chaincfg.TestNet3Params, tx, i, pkScript, tx, i, pkScript, hashType,
hashType, mkGetKey(map[string]addressToKey{ mkGetKey(map[string]addressToKey{
address.EncodeAddress(): {key, true}, address.EncodeAddress(): {key, true},
}), mkGetScript(nil), nil) }), mkGetScript(nil), nil)
if err != nil { if err != nil {
@ -317,9 +314,9 @@ func TestSignTxOutput(t *testing.T) {
// by the above loop, this should be valid, now sign // by the above loop, this should be valid, now sign
// again and merge. // again and merge.
sigScript, err = txscript.SignTxOutput( sigScript, err = SignTxOutput(&chaincfg.TestNet3Params,
&chaincfg.TestNet3Params, tx, i, pkScript, tx, i, pkScript, hashType,
hashType, mkGetKey(map[string]addressToKey{ mkGetKey(map[string]addressToKey{
address.EncodeAddress(): {key, true}, address.EncodeAddress(): {key, true},
}), mkGetScript(nil), sigScript) }), mkGetScript(nil), sigScript)
if err != nil { if err != nil {
@ -359,7 +356,7 @@ func TestSignTxOutput(t *testing.T) {
break break
} }
pkScript, err := txscript.PayToAddrScript(address) pkScript, err := PayToAddrScript(address)
if err != nil { if err != nil {
t.Errorf("failed to make pkscript "+ t.Errorf("failed to make pkscript "+
"for %s: %v", msg, err) "for %s: %v", msg, err)
@ -397,15 +394,15 @@ func TestSignTxOutput(t *testing.T) {
break break
} }
pkScript, err := txscript.PayToAddrScript(address) pkScript, err := PayToAddrScript(address)
if err != nil { if err != nil {
t.Errorf("failed to make pkscript "+ t.Errorf("failed to make pkscript "+
"for %s: %v", msg, err) "for %s: %v", msg, err)
} }
sigScript, err := txscript.SignTxOutput( sigScript, err := SignTxOutput(&chaincfg.TestNet3Params,
&chaincfg.TestNet3Params, tx, i, pkScript, tx, i, pkScript, hashType,
hashType, mkGetKey(map[string]addressToKey{ mkGetKey(map[string]addressToKey{
address.EncodeAddress(): {key, false}, address.EncodeAddress(): {key, false},
}), mkGetScript(nil), nil) }), mkGetScript(nil), nil)
if err != nil { if err != nil {
@ -416,9 +413,9 @@ func TestSignTxOutput(t *testing.T) {
// by the above loop, this should be valid, now sign // by the above loop, this should be valid, now sign
// again and merge. // again and merge.
sigScript, err = txscript.SignTxOutput( sigScript, err = SignTxOutput(&chaincfg.TestNet3Params,
&chaincfg.TestNet3Params, tx, i, pkScript, tx, i, pkScript, hashType,
hashType, mkGetKey(map[string]addressToKey{ mkGetKey(map[string]addressToKey{
address.EncodeAddress(): {key, false}, address.EncodeAddress(): {key, false},
}), mkGetScript(nil), sigScript) }), mkGetScript(nil), sigScript)
if err != nil { if err != nil {
@ -458,7 +455,7 @@ func TestSignTxOutput(t *testing.T) {
break break
} }
pkScript, err := txscript.PayToAddrScript(address) pkScript, err := PayToAddrScript(address)
if err != nil { if err != nil {
t.Errorf("failed to make pkscript "+ t.Errorf("failed to make pkscript "+
"for %s: %v", msg, err) "for %s: %v", msg, err)
@ -496,15 +493,15 @@ func TestSignTxOutput(t *testing.T) {
break break
} }
pkScript, err := txscript.PayToAddrScript(address) pkScript, err := PayToAddrScript(address)
if err != nil { if err != nil {
t.Errorf("failed to make pkscript "+ t.Errorf("failed to make pkscript "+
"for %s: %v", msg, err) "for %s: %v", msg, err)
} }
sigScript, err := txscript.SignTxOutput( sigScript, err := SignTxOutput(&chaincfg.TestNet3Params,
&chaincfg.TestNet3Params, tx, i, pkScript, tx, i, pkScript, hashType,
hashType, mkGetKey(map[string]addressToKey{ mkGetKey(map[string]addressToKey{
address.EncodeAddress(): {key, true}, address.EncodeAddress(): {key, true},
}), mkGetScript(nil), nil) }), mkGetScript(nil), nil)
if err != nil { if err != nil {
@ -515,9 +512,9 @@ func TestSignTxOutput(t *testing.T) {
// by the above loop, this should be valid, now sign // by the above loop, this should be valid, now sign
// again and merge. // again and merge.
sigScript, err = txscript.SignTxOutput( sigScript, err = SignTxOutput(&chaincfg.TestNet3Params,
&chaincfg.TestNet3Params, tx, i, pkScript, tx, i, pkScript, hashType,
hashType, mkGetKey(map[string]addressToKey{ mkGetKey(map[string]addressToKey{
address.EncodeAddress(): {key, true}, address.EncodeAddress(): {key, true},
}), mkGetScript(nil), sigScript) }), mkGetScript(nil), sigScript)
if err != nil { if err != nil {
@ -557,7 +554,7 @@ func TestSignTxOutput(t *testing.T) {
break break
} }
pkScript, err := txscript.PayToAddrScript(address) pkScript, err := PayToAddrScript(address)
if err != nil { if err != nil {
t.Errorf("failed to make pkscript "+ t.Errorf("failed to make pkscript "+
"for %s: %v", msg, err) "for %s: %v", msg, err)
@ -572,7 +569,7 @@ func TestSignTxOutput(t *testing.T) {
break break
} }
scriptPkScript, err := txscript.PayToAddrScript( scriptPkScript, err := PayToAddrScript(
scriptAddr) scriptAddr)
if err != nil { if err != nil {
t.Errorf("failed to make script pkscript for "+ t.Errorf("failed to make script pkscript for "+
@ -614,7 +611,7 @@ func TestSignTxOutput(t *testing.T) {
break break
} }
pkScript, err := txscript.PayToAddrScript(address) pkScript, err := PayToAddrScript(address)
if err != nil { if err != nil {
t.Errorf("failed to make pkscript "+ t.Errorf("failed to make pkscript "+
"for %s: %v", msg, err) "for %s: %v", msg, err)
@ -629,7 +626,7 @@ func TestSignTxOutput(t *testing.T) {
break break
} }
scriptPkScript, err := txscript.PayToAddrScript( scriptPkScript, err := PayToAddrScript(
scriptAddr) scriptAddr)
if err != nil { if err != nil {
t.Errorf("failed to make script pkscript for "+ t.Errorf("failed to make script pkscript for "+
@ -637,9 +634,9 @@ func TestSignTxOutput(t *testing.T) {
break break
} }
sigScript, err := txscript.SignTxOutput( sigScript, err := SignTxOutput(&chaincfg.TestNet3Params,
&chaincfg.TestNet3Params, tx, i, scriptPkScript, tx, i, scriptPkScript, hashType,
hashType, mkGetKey(map[string]addressToKey{ mkGetKey(map[string]addressToKey{
address.EncodeAddress(): {key, false}, address.EncodeAddress(): {key, false},
}), mkGetScript(map[string][]byte{ }), mkGetScript(map[string][]byte{
scriptAddr.EncodeAddress(): pkScript, scriptAddr.EncodeAddress(): pkScript,
@ -652,9 +649,9 @@ func TestSignTxOutput(t *testing.T) {
// by the above loop, this should be valid, now sign // by the above loop, this should be valid, now sign
// again and merge. // again and merge.
sigScript, err = txscript.SignTxOutput( sigScript, err = SignTxOutput(&chaincfg.TestNet3Params,
&chaincfg.TestNet3Params, tx, i, scriptPkScript, tx, i, scriptPkScript, hashType,
hashType, mkGetKey(map[string]addressToKey{ mkGetKey(map[string]addressToKey{
address.EncodeAddress(): {key, false}, address.EncodeAddress(): {key, false},
}), mkGetScript(map[string][]byte{ }), mkGetScript(map[string][]byte{
scriptAddr.EncodeAddress(): pkScript, scriptAddr.EncodeAddress(): pkScript,
@ -696,7 +693,7 @@ func TestSignTxOutput(t *testing.T) {
break break
} }
pkScript, err := txscript.PayToAddrScript(address) pkScript, err := PayToAddrScript(address)
if err != nil { if err != nil {
t.Errorf("failed to make pkscript "+ t.Errorf("failed to make pkscript "+
"for %s: %v", msg, err) "for %s: %v", msg, err)
@ -710,7 +707,7 @@ func TestSignTxOutput(t *testing.T) {
break break
} }
scriptPkScript, err := txscript.PayToAddrScript( scriptPkScript, err := PayToAddrScript(
scriptAddr) scriptAddr)
if err != nil { if err != nil {
t.Errorf("failed to make script pkscript for "+ t.Errorf("failed to make script pkscript for "+
@ -753,7 +750,7 @@ func TestSignTxOutput(t *testing.T) {
break break
} }
pkScript, err := txscript.PayToAddrScript(address) pkScript, err := PayToAddrScript(address)
if err != nil { if err != nil {
t.Errorf("failed to make pkscript "+ t.Errorf("failed to make pkscript "+
"for %s: %v", msg, err) "for %s: %v", msg, err)
@ -767,7 +764,7 @@ func TestSignTxOutput(t *testing.T) {
break break
} }
scriptPkScript, err := txscript.PayToAddrScript( scriptPkScript, err := PayToAddrScript(
scriptAddr) scriptAddr)
if err != nil { if err != nil {
t.Errorf("failed to make script pkscript for "+ t.Errorf("failed to make script pkscript for "+
@ -775,9 +772,9 @@ func TestSignTxOutput(t *testing.T) {
break break
} }
sigScript, err := txscript.SignTxOutput( sigScript, err := SignTxOutput(&chaincfg.TestNet3Params,
&chaincfg.TestNet3Params, tx, i, scriptPkScript, tx, i, scriptPkScript, hashType,
hashType, mkGetKey(map[string]addressToKey{ mkGetKey(map[string]addressToKey{
address.EncodeAddress(): {key, true}, address.EncodeAddress(): {key, true},
}), mkGetScript(map[string][]byte{ }), mkGetScript(map[string][]byte{
scriptAddr.EncodeAddress(): pkScript, scriptAddr.EncodeAddress(): pkScript,
@ -790,9 +787,9 @@ func TestSignTxOutput(t *testing.T) {
// by the above loop, this should be valid, now sign // by the above loop, this should be valid, now sign
// again and merge. // again and merge.
sigScript, err = txscript.SignTxOutput( sigScript, err = SignTxOutput(&chaincfg.TestNet3Params,
&chaincfg.TestNet3Params, tx, i, scriptPkScript, tx, i, scriptPkScript, hashType,
hashType, mkGetKey(map[string]addressToKey{ mkGetKey(map[string]addressToKey{
address.EncodeAddress(): {key, true}, address.EncodeAddress(): {key, true},
}), mkGetScript(map[string][]byte{ }), mkGetScript(map[string][]byte{
scriptAddr.EncodeAddress(): pkScript, scriptAddr.EncodeAddress(): pkScript,
@ -834,7 +831,7 @@ func TestSignTxOutput(t *testing.T) {
break break
} }
pkScript, err := txscript.PayToAddrScript(address) pkScript, err := PayToAddrScript(address)
if err != nil { if err != nil {
t.Errorf("failed to make pkscript "+ t.Errorf("failed to make pkscript "+
"for %s: %v", msg, err) "for %s: %v", msg, err)
@ -848,7 +845,7 @@ func TestSignTxOutput(t *testing.T) {
break break
} }
scriptPkScript, err := txscript.PayToAddrScript( scriptPkScript, err := PayToAddrScript(
scriptAddr) scriptAddr)
if err != nil { if err != nil {
t.Errorf("failed to make script pkscript for "+ t.Errorf("failed to make script pkscript for "+
@ -891,7 +888,7 @@ func TestSignTxOutput(t *testing.T) {
break break
} }
pkScript, err := txscript.PayToAddrScript(address) pkScript, err := PayToAddrScript(address)
if err != nil { if err != nil {
t.Errorf("failed to make pkscript "+ t.Errorf("failed to make pkscript "+
"for %s: %v", msg, err) "for %s: %v", msg, err)
@ -905,17 +902,16 @@ func TestSignTxOutput(t *testing.T) {
break break
} }
scriptPkScript, err := txscript.PayToAddrScript( scriptPkScript, err := PayToAddrScript(scriptAddr)
scriptAddr)
if err != nil { if err != nil {
t.Errorf("failed to make script pkscript for "+ t.Errorf("failed to make script pkscript for "+
"%s: %v", msg, err) "%s: %v", msg, err)
break break
} }
sigScript, err := txscript.SignTxOutput( sigScript, err := SignTxOutput(&chaincfg.TestNet3Params,
&chaincfg.TestNet3Params, tx, i, scriptPkScript, tx, i, scriptPkScript, hashType,
hashType, mkGetKey(map[string]addressToKey{ mkGetKey(map[string]addressToKey{
address.EncodeAddress(): {key, false}, address.EncodeAddress(): {key, false},
}), mkGetScript(map[string][]byte{ }), mkGetScript(map[string][]byte{
scriptAddr.EncodeAddress(): pkScript, scriptAddr.EncodeAddress(): pkScript,
@ -928,9 +924,9 @@ func TestSignTxOutput(t *testing.T) {
// by the above loop, this should be valid, now sign // by the above loop, this should be valid, now sign
// again and merge. // again and merge.
sigScript, err = txscript.SignTxOutput( sigScript, err = SignTxOutput(&chaincfg.TestNet3Params,
&chaincfg.TestNet3Params, tx, i, scriptPkScript, tx, i, scriptPkScript, hashType,
hashType, mkGetKey(map[string]addressToKey{ mkGetKey(map[string]addressToKey{
address.EncodeAddress(): {key, false}, address.EncodeAddress(): {key, false},
}), mkGetScript(map[string][]byte{ }), mkGetScript(map[string][]byte{
scriptAddr.EncodeAddress(): pkScript, scriptAddr.EncodeAddress(): pkScript,
@ -972,7 +968,7 @@ func TestSignTxOutput(t *testing.T) {
break break
} }
pkScript, err := txscript.PayToAddrScript(address) pkScript, err := PayToAddrScript(address)
if err != nil { if err != nil {
t.Errorf("failed to make pkscript "+ t.Errorf("failed to make pkscript "+
"for %s: %v", msg, err) "for %s: %v", msg, err)
@ -986,8 +982,7 @@ func TestSignTxOutput(t *testing.T) {
break break
} }
scriptPkScript, err := txscript.PayToAddrScript( scriptPkScript, err := PayToAddrScript(scriptAddr)
scriptAddr)
if err != nil { if err != nil {
t.Errorf("failed to make script pkscript for "+ t.Errorf("failed to make script pkscript for "+
"%s: %v", msg, err) "%s: %v", msg, err)
@ -1029,7 +1024,7 @@ func TestSignTxOutput(t *testing.T) {
break break
} }
pkScript, err := txscript.PayToAddrScript(address) pkScript, err := PayToAddrScript(address)
if err != nil { if err != nil {
t.Errorf("failed to make pkscript "+ t.Errorf("failed to make pkscript "+
"for %s: %v", msg, err) "for %s: %v", msg, err)
@ -1043,17 +1038,16 @@ func TestSignTxOutput(t *testing.T) {
break break
} }
scriptPkScript, err := txscript.PayToAddrScript( scriptPkScript, err := PayToAddrScript(scriptAddr)
scriptAddr)
if err != nil { if err != nil {
t.Errorf("failed to make script pkscript for "+ t.Errorf("failed to make script pkscript for "+
"%s: %v", msg, err) "%s: %v", msg, err)
break break
} }
sigScript, err := txscript.SignTxOutput( sigScript, err := SignTxOutput(&chaincfg.TestNet3Params,
&chaincfg.TestNet3Params, tx, i, scriptPkScript, tx, i, scriptPkScript, hashType,
hashType, mkGetKey(map[string]addressToKey{ mkGetKey(map[string]addressToKey{
address.EncodeAddress(): {key, true}, address.EncodeAddress(): {key, true},
}), mkGetScript(map[string][]byte{ }), mkGetScript(map[string][]byte{
scriptAddr.EncodeAddress(): pkScript, scriptAddr.EncodeAddress(): pkScript,
@ -1066,9 +1060,9 @@ func TestSignTxOutput(t *testing.T) {
// by the above loop, this should be valid, now sign // by the above loop, this should be valid, now sign
// again and merge. // again and merge.
sigScript, err = txscript.SignTxOutput( sigScript, err = SignTxOutput(&chaincfg.TestNet3Params,
&chaincfg.TestNet3Params, tx, i, scriptPkScript, tx, i, scriptPkScript, hashType,
hashType, mkGetKey(map[string]addressToKey{ mkGetKey(map[string]addressToKey{
address.EncodeAddress(): {key, true}, address.EncodeAddress(): {key, true},
}), mkGetScript(map[string][]byte{ }), mkGetScript(map[string][]byte{
scriptAddr.EncodeAddress(): pkScript, scriptAddr.EncodeAddress(): pkScript,
@ -1127,7 +1121,7 @@ func TestSignTxOutput(t *testing.T) {
break break
} }
pkScript, err := txscript.MultiSigScript( pkScript, err := MultiSigScript(
[]*btcutil.AddressPubKey{address1, address2}, []*btcutil.AddressPubKey{address1, address2},
2) 2)
if err != nil { if err != nil {
@ -1143,8 +1137,7 @@ func TestSignTxOutput(t *testing.T) {
break break
} }
scriptPkScript, err := txscript.PayToAddrScript( scriptPkScript, err := PayToAddrScript(scriptAddr)
scriptAddr)
if err != nil { if err != nil {
t.Errorf("failed to make script pkscript for "+ t.Errorf("failed to make script pkscript for "+
"%s: %v", msg, err) "%s: %v", msg, err)
@ -1204,7 +1197,7 @@ func TestSignTxOutput(t *testing.T) {
break break
} }
pkScript, err := txscript.MultiSigScript( pkScript, err := MultiSigScript(
[]*btcutil.AddressPubKey{address1, address2}, []*btcutil.AddressPubKey{address1, address2},
2) 2)
if err != nil { if err != nil {
@ -1220,17 +1213,16 @@ func TestSignTxOutput(t *testing.T) {
break break
} }
scriptPkScript, err := txscript.PayToAddrScript( scriptPkScript, err := PayToAddrScript(scriptAddr)
scriptAddr)
if err != nil { if err != nil {
t.Errorf("failed to make script pkscript for "+ t.Errorf("failed to make script pkscript for "+
"%s: %v", msg, err) "%s: %v", msg, err)
break break
} }
sigScript, err := txscript.SignTxOutput( sigScript, err := SignTxOutput(&chaincfg.TestNet3Params,
&chaincfg.TestNet3Params, tx, i, scriptPkScript, tx, i, scriptPkScript, hashType,
hashType, mkGetKey(map[string]addressToKey{ mkGetKey(map[string]addressToKey{
address1.EncodeAddress(): {key1, true}, address1.EncodeAddress(): {key1, true},
}), mkGetScript(map[string][]byte{ }), mkGetScript(map[string][]byte{
scriptAddr.EncodeAddress(): pkScript, scriptAddr.EncodeAddress(): pkScript,
@ -1249,9 +1241,9 @@ func TestSignTxOutput(t *testing.T) {
} }
// Sign with the other key and merge // Sign with the other key and merge
sigScript, err = txscript.SignTxOutput( sigScript, err = SignTxOutput(&chaincfg.TestNet3Params,
&chaincfg.TestNet3Params, tx, i, scriptPkScript, tx, i, scriptPkScript, hashType,
hashType, mkGetKey(map[string]addressToKey{ mkGetKey(map[string]addressToKey{
address2.EncodeAddress(): {key2, true}, address2.EncodeAddress(): {key2, true},
}), mkGetScript(map[string][]byte{ }), mkGetScript(map[string][]byte{
scriptAddr.EncodeAddress(): pkScript, scriptAddr.EncodeAddress(): pkScript,
@ -1311,7 +1303,7 @@ func TestSignTxOutput(t *testing.T) {
break break
} }
pkScript, err := txscript.MultiSigScript( pkScript, err := MultiSigScript(
[]*btcutil.AddressPubKey{address1, address2}, []*btcutil.AddressPubKey{address1, address2},
2) 2)
if err != nil { if err != nil {
@ -1327,17 +1319,16 @@ func TestSignTxOutput(t *testing.T) {
break break
} }
scriptPkScript, err := txscript.PayToAddrScript( scriptPkScript, err := PayToAddrScript(scriptAddr)
scriptAddr)
if err != nil { if err != nil {
t.Errorf("failed to make script pkscript for "+ t.Errorf("failed to make script pkscript for "+
"%s: %v", msg, err) "%s: %v", msg, err)
break break
} }
sigScript, err := txscript.SignTxOutput( sigScript, err := SignTxOutput(&chaincfg.TestNet3Params,
&chaincfg.TestNet3Params, tx, i, scriptPkScript, tx, i, scriptPkScript, hashType,
hashType, mkGetKey(map[string]addressToKey{ mkGetKey(map[string]addressToKey{
address1.EncodeAddress(): {key1, true}, address1.EncodeAddress(): {key1, true},
}), mkGetScript(map[string][]byte{ }), mkGetScript(map[string][]byte{
scriptAddr.EncodeAddress(): pkScript, scriptAddr.EncodeAddress(): pkScript,
@ -1356,9 +1347,9 @@ func TestSignTxOutput(t *testing.T) {
} }
// Sign with the other key and merge // Sign with the other key and merge
sigScript, err = txscript.SignTxOutput( sigScript, err = SignTxOutput(&chaincfg.TestNet3Params,
&chaincfg.TestNet3Params, tx, i, scriptPkScript, tx, i, scriptPkScript, hashType,
hashType, mkGetKey(map[string]addressToKey{ mkGetKey(map[string]addressToKey{
address1.EncodeAddress(): {key1, true}, address1.EncodeAddress(): {key1, true},
address2.EncodeAddress(): {key2, true}, address2.EncodeAddress(): {key2, true},
}), mkGetScript(map[string][]byte{ }), mkGetScript(map[string][]byte{
@ -1391,7 +1382,7 @@ type tstInput struct {
type tstSigScript struct { type tstSigScript struct {
name string name string
inputs []tstInput inputs []tstInput
hashType txscript.SigHashType hashType SigHashType
compress bool compress bool
scriptAtWrongIndex bool scriptAtWrongIndex bool
} }
@ -1443,7 +1434,7 @@ var sigScriptTests = []tstSigScript{
indexOutOfRange: false, indexOutOfRange: false,
}, },
}, },
hashType: txscript.SigHashAll, hashType: SigHashAll,
compress: false, compress: false,
scriptAtWrongIndex: false, scriptAtWrongIndex: false,
}, },
@ -1463,7 +1454,7 @@ var sigScriptTests = []tstSigScript{
indexOutOfRange: false, indexOutOfRange: false,
}, },
}, },
hashType: txscript.SigHashAll, hashType: SigHashAll,
compress: false, compress: false,
scriptAtWrongIndex: false, scriptAtWrongIndex: false,
}, },
@ -1477,7 +1468,7 @@ var sigScriptTests = []tstSigScript{
indexOutOfRange: false, indexOutOfRange: false,
}, },
}, },
hashType: txscript.SigHashAll, hashType: SigHashAll,
compress: true, compress: true,
scriptAtWrongIndex: false, scriptAtWrongIndex: false,
}, },
@ -1497,7 +1488,7 @@ var sigScriptTests = []tstSigScript{
indexOutOfRange: false, indexOutOfRange: false,
}, },
}, },
hashType: txscript.SigHashAll, hashType: SigHashAll,
compress: true, compress: true,
scriptAtWrongIndex: false, scriptAtWrongIndex: false,
}, },
@ -1511,7 +1502,7 @@ var sigScriptTests = []tstSigScript{
indexOutOfRange: false, indexOutOfRange: false,
}, },
}, },
hashType: txscript.SigHashNone, hashType: SigHashNone,
compress: false, compress: false,
scriptAtWrongIndex: false, scriptAtWrongIndex: false,
}, },
@ -1525,7 +1516,7 @@ var sigScriptTests = []tstSigScript{
indexOutOfRange: false, indexOutOfRange: false,
}, },
}, },
hashType: txscript.SigHashSingle, hashType: SigHashSingle,
compress: false, compress: false,
scriptAtWrongIndex: false, scriptAtWrongIndex: false,
}, },
@ -1539,7 +1530,7 @@ var sigScriptTests = []tstSigScript{
indexOutOfRange: false, indexOutOfRange: false,
}, },
}, },
hashType: txscript.SigHashAnyOneCanPay, hashType: SigHashAnyOneCanPay,
compress: false, compress: false,
scriptAtWrongIndex: false, scriptAtWrongIndex: false,
}, },
@ -1567,7 +1558,7 @@ var sigScriptTests = []tstSigScript{
indexOutOfRange: false, indexOutOfRange: false,
}, },
}, },
hashType: txscript.SigHashAll, hashType: SigHashAll,
compress: true, compress: true,
scriptAtWrongIndex: false, scriptAtWrongIndex: false,
}, },
@ -1580,7 +1571,7 @@ var sigScriptTests = []tstSigScript{
indexOutOfRange: false, indexOutOfRange: false,
}, },
}, },
hashType: txscript.SigHashAll, hashType: SigHashAll,
compress: false, compress: false,
scriptAtWrongIndex: false, scriptAtWrongIndex: false,
}, },
@ -1600,7 +1591,7 @@ var sigScriptTests = []tstSigScript{
indexOutOfRange: false, indexOutOfRange: false,
}, },
}, },
hashType: txscript.SigHashAll, hashType: SigHashAll,
compress: false, compress: false,
scriptAtWrongIndex: true, scriptAtWrongIndex: true,
}, },
@ -1620,7 +1611,7 @@ var sigScriptTests = []tstSigScript{
indexOutOfRange: false, indexOutOfRange: false,
}, },
}, },
hashType: txscript.SigHashAll, hashType: SigHashAll,
compress: false, compress: false,
scriptAtWrongIndex: true, scriptAtWrongIndex: true,
}, },
@ -1640,7 +1631,7 @@ nexttest:
for i := range sigScriptTests { for i := range sigScriptTests {
tx := wire.NewMsgTx() tx := wire.NewMsgTx()
output := wire.NewTxOut(500, []byte{txscript.OP_RETURN}) output := wire.NewTxOut(500, []byte{OP_RETURN})
tx.AddTxOut(output) tx.AddTxOut(output)
for range sigScriptTests[i].inputs { for range sigScriptTests[i].inputs {
@ -1658,7 +1649,7 @@ nexttest:
} else { } else {
idx = j idx = j
} }
script, err = txscript.SignatureScript(tx, idx, script, err = SignatureScript(tx, idx,
sigScriptTests[i].inputs[j].txout.PkScript, sigScriptTests[i].inputs[j].txout.PkScript,
sigScriptTests[i].hashType, privKey, sigScriptTests[i].hashType, privKey,
sigScriptTests[i].compress) sigScriptTests[i].compress)
@ -1690,10 +1681,10 @@ nexttest:
} }
// Validate tx input scripts // Validate tx input scripts
scriptFlags := txscript.ScriptBip16 | txscript.ScriptVerifyDERSignatures scriptFlags := ScriptBip16 | ScriptVerifyDERSignatures
for j := range tx.TxIn { for j := range tx.TxIn {
vm, err := txscript.NewEngine(sigScriptTests[i]. vm, err := NewEngine(sigScriptTests[i].inputs[j].txout.
inputs[j].txout.PkScript, tx, j, scriptFlags, nil) PkScript, tx, j, scriptFlags, nil)
if err != nil { if err != nil {
t.Errorf("cannot create script vm for test %v: %v", t.Errorf("cannot create script vm for test %v: %v",
sigScriptTests[i].name, err) sigScriptTests[i].name, err)

View file

@ -1,33 +1,18 @@
// Copyright (c) 2013-2015 The btcsuite developers // Copyright (c) 2013-2016 The btcsuite developers
// Use of this source code is governed by an ISC // Use of this source code is governed by an ISC
// license that can be found in the LICENSE file. // license that can be found in the LICENSE file.
package txscript_test package txscript
import ( import (
"bytes" "bytes"
"encoding/hex"
"reflect" "reflect"
"testing" "testing"
"github.com/btcsuite/btcd/chaincfg" "github.com/btcsuite/btcd/chaincfg"
"github.com/btcsuite/btcd/txscript"
"github.com/btcsuite/btcutil" "github.com/btcsuite/btcutil"
) )
// decodeHex decodes the passed hex string and returns the resulting bytes. It
// panics if an error occurs. This is only used in the tests as a helper since
// the only way it can fail is if there is an error in the test source code.
func decodeHex(hexStr string) []byte {
b, err := hex.DecodeString(hexStr)
if err != nil {
panic("invalid hex string in test source: err " + err.Error() +
", hex: " + hexStr)
}
return b
}
// mustParseShortForm parses the passed short form script and returns the // mustParseShortForm parses the passed short form script and returns the
// resulting bytes. It panics if an error occurs. This is only used in the // resulting bytes. It panics if an error occurs. This is only used in the
// tests as a helper since the only way it can fail is if there is an error in // tests as a helper since the only way it can fail is if there is an error in
@ -93,175 +78,175 @@ func TestExtractPkScriptAddrs(t *testing.T) {
script []byte script []byte
addrs []btcutil.Address addrs []btcutil.Address
reqSigs int reqSigs int
class txscript.ScriptClass class ScriptClass
}{ }{
{ {
name: "standard p2pk with compressed pubkey (0x02)", name: "standard p2pk with compressed pubkey (0x02)",
script: decodeHex("2102192d74d0cb94344c9569c2e7790157" + script: hexToBytes("2102192d74d0cb94344c9569c2e779015" +
"3d8d7903c3ebec3a957724895dca52c6b4ac"), "73d8d7903c3ebec3a957724895dca52c6b4ac"),
addrs: []btcutil.Address{ addrs: []btcutil.Address{
newAddressPubKey(decodeHex("02192d74d0cb94344" + newAddressPubKey(hexToBytes("02192d74d0cb9434" +
"c9569c2e77901573d8d7903c3ebec3a95772" + "4c9569c2e77901573d8d7903c3ebec3a9577" +
"4895dca52c6b4")), "24895dca52c6b4")),
}, },
reqSigs: 1, reqSigs: 1,
class: txscript.PubKeyTy, class: PubKeyTy,
}, },
{ {
name: "standard p2pk with uncompressed pubkey (0x04)", name: "standard p2pk with uncompressed pubkey (0x04)",
script: decodeHex("410411db93e1dcdb8a016b49840f8c53bc" + script: hexToBytes("410411db93e1dcdb8a016b49840f8c53b" +
"1eb68a382e97b1482ecad7b148a6909a5cb2e0eaddfb" + "c1eb68a382e97b1482ecad7b148a6909a5cb2e0eaddf" +
"84ccf9744464f82e160bfa9b8b64f9d4c03f999b8643" + "b84ccf9744464f82e160bfa9b8b64f9d4c03f999b864" +
"f656b412a3ac"), "3f656b412a3ac"),
addrs: []btcutil.Address{ addrs: []btcutil.Address{
newAddressPubKey(decodeHex("0411db93e1dcdb8a0" + newAddressPubKey(hexToBytes("0411db93e1dcdb8a" +
"16b49840f8c53bc1eb68a382e97b1482ecad" + "016b49840f8c53bc1eb68a382e97b1482eca" +
"7b148a6909a5cb2e0eaddfb84ccf9744464f" + "d7b148a6909a5cb2e0eaddfb84ccf9744464" +
"82e160bfa9b8b64f9d4c03f999b8643f656b" + "f82e160bfa9b8b64f9d4c03f999b8643f656" +
"412a3")), "b412a3")),
}, },
reqSigs: 1, reqSigs: 1,
class: txscript.PubKeyTy, class: PubKeyTy,
}, },
{ {
name: "standard p2pk with hybrid pubkey (0x06)", name: "standard p2pk with hybrid pubkey (0x06)",
script: decodeHex("4106192d74d0cb94344c9569c2e7790157" + script: hexToBytes("4106192d74d0cb94344c9569c2e779015" +
"3d8d7903c3ebec3a957724895dca52c6b40d45264838" + "73d8d7903c3ebec3a957724895dca52c6b40d4526483" +
"c0bd96852662ce6a847b197376830160c6d2eb5e6a4c" + "8c0bd96852662ce6a847b197376830160c6d2eb5e6a4" +
"44d33f453eac"), "c44d33f453eac"),
addrs: []btcutil.Address{ addrs: []btcutil.Address{
newAddressPubKey(decodeHex("06192d74d0cb94344" + newAddressPubKey(hexToBytes("06192d74d0cb9434" +
"c9569c2e77901573d8d7903c3ebec3a95772" + "4c9569c2e77901573d8d7903c3ebec3a9577" +
"4895dca52c6b40d45264838c0bd96852662c" + "24895dca52c6b40d45264838c0bd96852662" +
"e6a847b197376830160c6d2eb5e6a4c44d33" + "ce6a847b197376830160c6d2eb5e6a4c44d3" +
"f453e")), "3f453e")),
}, },
reqSigs: 1, reqSigs: 1,
class: txscript.PubKeyTy, class: PubKeyTy,
}, },
{ {
name: "standard p2pk with compressed pubkey (0x03)", name: "standard p2pk with compressed pubkey (0x03)",
script: decodeHex("2103b0bd634234abbb1ba1e986e884185c" + script: hexToBytes("2103b0bd634234abbb1ba1e986e884185" +
"61cf43e001f9137f23c2c409273eb16e65ac"), "c61cf43e001f9137f23c2c409273eb16e65ac"),
addrs: []btcutil.Address{ addrs: []btcutil.Address{
newAddressPubKey(decodeHex("03b0bd634234abbb1" + newAddressPubKey(hexToBytes("03b0bd634234abbb" +
"ba1e986e884185c61cf43e001f9137f23c2c" + "1ba1e986e884185c61cf43e001f9137f23c2" +
"409273eb16e65")), "c409273eb16e65")),
}, },
reqSigs: 1, reqSigs: 1,
class: txscript.PubKeyTy, class: PubKeyTy,
}, },
{ {
name: "2nd standard p2pk with uncompressed pubkey (0x04)", name: "2nd standard p2pk with uncompressed pubkey (0x04)",
script: decodeHex("4104b0bd634234abbb1ba1e986e884185c" + script: hexToBytes("4104b0bd634234abbb1ba1e986e884185" +
"61cf43e001f9137f23c2c409273eb16e6537a576782e" + "c61cf43e001f9137f23c2c409273eb16e6537a576782" +
"ba668a7ef8bd3b3cfb1edb7117ab65129b8a2e681f3c" + "eba668a7ef8bd3b3cfb1edb7117ab65129b8a2e681f3" +
"1e0908ef7bac"), "c1e0908ef7bac"),
addrs: []btcutil.Address{ addrs: []btcutil.Address{
newAddressPubKey(decodeHex("04b0bd634234abbb1" + newAddressPubKey(hexToBytes("04b0bd634234abbb" +
"ba1e986e884185c61cf43e001f9137f23c2c" + "1ba1e986e884185c61cf43e001f9137f23c2" +
"409273eb16e6537a576782eba668a7ef8bd3" + "c409273eb16e6537a576782eba668a7ef8bd" +
"b3cfb1edb7117ab65129b8a2e681f3c1e090" + "3b3cfb1edb7117ab65129b8a2e681f3c1e09" +
"8ef7b")), "08ef7b")),
}, },
reqSigs: 1, reqSigs: 1,
class: txscript.PubKeyTy, class: PubKeyTy,
}, },
{ {
name: "standard p2pk with hybrid pubkey (0x07)", name: "standard p2pk with hybrid pubkey (0x07)",
script: decodeHex("4107b0bd634234abbb1ba1e986e884185c" + script: hexToBytes("4107b0bd634234abbb1ba1e986e884185" +
"61cf43e001f9137f23c2c409273eb16e6537a576782e" + "c61cf43e001f9137f23c2c409273eb16e6537a576782" +
"ba668a7ef8bd3b3cfb1edb7117ab65129b8a2e681f3c" + "eba668a7ef8bd3b3cfb1edb7117ab65129b8a2e681f3" +
"1e0908ef7bac"), "c1e0908ef7bac"),
addrs: []btcutil.Address{ addrs: []btcutil.Address{
newAddressPubKey(decodeHex("07b0bd634234abbb1" + newAddressPubKey(hexToBytes("07b0bd634234abbb" +
"ba1e986e884185c61cf43e001f9137f23c2c" + "1ba1e986e884185c61cf43e001f9137f23c2" +
"409273eb16e6537a576782eba668a7ef8bd3" + "c409273eb16e6537a576782eba668a7ef8bd" +
"b3cfb1edb7117ab65129b8a2e681f3c1e090" + "3b3cfb1edb7117ab65129b8a2e681f3c1e09" +
"8ef7b")), "08ef7b")),
}, },
reqSigs: 1, reqSigs: 1,
class: txscript.PubKeyTy, class: PubKeyTy,
}, },
{ {
name: "standard p2pkh", name: "standard p2pkh",
script: decodeHex("76a914ad06dd6ddee55cbca9a9e3713bd7" + script: hexToBytes("76a914ad06dd6ddee55cbca9a9e3713bd" +
"587509a3056488ac"), "7587509a3056488ac"),
addrs: []btcutil.Address{ addrs: []btcutil.Address{
newAddressPubKeyHash(decodeHex("ad06dd6ddee55" + newAddressPubKeyHash(hexToBytes("ad06dd6ddee5" +
"cbca9a9e3713bd7587509a30564")), "5cbca9a9e3713bd7587509a30564")),
}, },
reqSigs: 1, reqSigs: 1,
class: txscript.PubKeyHashTy, class: PubKeyHashTy,
}, },
{ {
name: "standard p2sh", name: "standard p2sh",
script: decodeHex("a91463bcc565f9e68ee0189dd5cc67f1b0" + script: hexToBytes("a91463bcc565f9e68ee0189dd5cc67f1b" +
"e5f02f45cb87"), "0e5f02f45cb87"),
addrs: []btcutil.Address{ addrs: []btcutil.Address{
newAddressScriptHash(decodeHex("63bcc565f9e68" + newAddressScriptHash(hexToBytes("63bcc565f9e6" +
"ee0189dd5cc67f1b0e5f02f45cb")), "8ee0189dd5cc67f1b0e5f02f45cb")),
}, },
reqSigs: 1, reqSigs: 1,
class: txscript.ScriptHashTy, class: ScriptHashTy,
}, },
// from real tx 60a20bd93aa49ab4b28d514ec10b06e1829ce6818ec06cd3aabd013ebcdc4bb1, vout 0 // from real tx 60a20bd93aa49ab4b28d514ec10b06e1829ce6818ec06cd3aabd013ebcdc4bb1, vout 0
{ {
name: "standard 1 of 2 multisig", name: "standard 1 of 2 multisig",
script: decodeHex("514104cc71eb30d653c0c3163990c47b97" + script: hexToBytes("514104cc71eb30d653c0c3163990c47b9" +
"6f3fb3f37cccdcbedb169a1dfef58bbfbfaff7d8a473" + "76f3fb3f37cccdcbedb169a1dfef58bbfbfaff7d8a47" +
"e7e2e6d317b87bafe8bde97e3cf8f065dec022b51d11" + "3e7e2e6d317b87bafe8bde97e3cf8f065dec022b51d1" +
"fcdd0d348ac4410461cbdcc5409fb4b4d42b51d33381" + "1fcdd0d348ac4410461cbdcc5409fb4b4d42b51d3338" +
"354d80e550078cb532a34bfa2fcfdeb7d76519aecc62" + "1354d80e550078cb532a34bfa2fcfdeb7d76519aecc6" +
"770f5b0e4ef8551946d8a540911abe3e7854a26f39f5" + "2770f5b0e4ef8551946d8a540911abe3e7854a26f39f" +
"8b25c15342af52ae"), "58b25c15342af52ae"),
addrs: []btcutil.Address{ addrs: []btcutil.Address{
newAddressPubKey(decodeHex("04cc71eb30d653c0c" + newAddressPubKey(hexToBytes("04cc71eb30d653c0" +
"3163990c47b976f3fb3f37cccdcbedb169a1" + "c3163990c47b976f3fb3f37cccdcbedb169a" +
"dfef58bbfbfaff7d8a473e7e2e6d317b87ba" + "1dfef58bbfbfaff7d8a473e7e2e6d317b87b" +
"fe8bde97e3cf8f065dec022b51d11fcdd0d3" + "afe8bde97e3cf8f065dec022b51d11fcdd0d" +
"48ac4")), "348ac4")),
newAddressPubKey(decodeHex("0461cbdcc5409fb4b" + newAddressPubKey(hexToBytes("0461cbdcc5409fb4" +
"4d42b51d33381354d80e550078cb532a34bf" + "b4d42b51d33381354d80e550078cb532a34b" +
"a2fcfdeb7d76519aecc62770f5b0e4ef8551" + "fa2fcfdeb7d76519aecc62770f5b0e4ef855" +
"946d8a540911abe3e7854a26f39f58b25c15" + "1946d8a540911abe3e7854a26f39f58b25c1" +
"342af")), "5342af")),
}, },
reqSigs: 1, reqSigs: 1,
class: txscript.MultiSigTy, class: MultiSigTy,
}, },
// from real tx d646f82bd5fbdb94a36872ce460f97662b80c3050ad3209bef9d1e398ea277ab, vin 1 // from real tx d646f82bd5fbdb94a36872ce460f97662b80c3050ad3209bef9d1e398ea277ab, vin 1
{ {
name: "standard 2 of 3 multisig", name: "standard 2 of 3 multisig",
script: decodeHex("524104cb9c3c222c5f7a7d3b9bd152f363" + script: hexToBytes("524104cb9c3c222c5f7a7d3b9bd152f36" +
"a0b6d54c9eb312c4d4f9af1e8551b6c421a6a4ab0e29" + "3a0b6d54c9eb312c4d4f9af1e8551b6c421a6a4ab0e2" +
"105f24de20ff463c1c91fcf3bf662cdde4783d4799f7" + "9105f24de20ff463c1c91fcf3bf662cdde4783d4799f" +
"87cb7c08869b4104ccc588420deeebea22a7e900cc8b" + "787cb7c08869b4104ccc588420deeebea22a7e900cc8" +
"68620d2212c374604e3487ca08f1ff3ae12bdc639514" + "b68620d2212c374604e3487ca08f1ff3ae12bdc63951" +
"d0ec8612a2d3c519f084d9a00cbbe3b53d071e9b09e7" + "4d0ec8612a2d3c519f084d9a00cbbe3b53d071e9b09e" +
"1e610b036aa24104ab47ad1939edcb3db65f7fedea62" + "71e610b036aa24104ab47ad1939edcb3db65f7fedea6" +
"bbf781c5410d3f22a7a3a56ffefb2238af8627363bdf" + "2bbf781c5410d3f22a7a3a56ffefb2238af8627363bd" +
"2ed97c1f89784a1aecdb43384f11d2acc64443c7fc29" + "f2ed97c1f89784a1aecdb43384f11d2acc64443c7fc2" +
"9cef0400421a53ae"), "99cef0400421a53ae"),
addrs: []btcutil.Address{ addrs: []btcutil.Address{
newAddressPubKey(decodeHex("04cb9c3c222c5f7a7" + newAddressPubKey(hexToBytes("04cb9c3c222c5f7a" +
"d3b9bd152f363a0b6d54c9eb312c4d4f9af1" + "7d3b9bd152f363a0b6d54c9eb312c4d4f9af" +
"e8551b6c421a6a4ab0e29105f24de20ff463" + "1e8551b6c421a6a4ab0e29105f24de20ff46" +
"c1c91fcf3bf662cdde4783d4799f787cb7c0" + "3c1c91fcf3bf662cdde4783d4799f787cb7c" +
"8869b")), "08869b")),
newAddressPubKey(decodeHex("04ccc588420deeebe" + newAddressPubKey(hexToBytes("04ccc588420deeeb" +
"a22a7e900cc8b68620d2212c374604e3487c" + "ea22a7e900cc8b68620d2212c374604e3487" +
"a08f1ff3ae12bdc639514d0ec8612a2d3c51" + "ca08f1ff3ae12bdc639514d0ec8612a2d3c5" +
"9f084d9a00cbbe3b53d071e9b09e71e610b0" + "19f084d9a00cbbe3b53d071e9b09e71e610b" +
"36aa2")), "036aa2")),
newAddressPubKey(decodeHex("04ab47ad1939edcb3" + newAddressPubKey(hexToBytes("04ab47ad1939edcb" +
"db65f7fedea62bbf781c5410d3f22a7a3a56" + "3db65f7fedea62bbf781c5410d3f22a7a3a5" +
"ffefb2238af8627363bdf2ed97c1f89784a1" + "6ffefb2238af8627363bdf2ed97c1f89784a" +
"aecdb43384f11d2acc64443c7fc299cef040" + "1aecdb43384f11d2acc64443c7fc299cef04" +
"0421a")), "00421a")),
}, },
reqSigs: 2, reqSigs: 2,
class: txscript.MultiSigTy, class: MultiSigTy,
}, },
// The below are nonstandard script due to things such as // The below are nonstandard script due to things such as
@ -270,23 +255,23 @@ func TestExtractPkScriptAddrs(t *testing.T) {
{ {
name: "p2pk with uncompressed pk missing OP_CHECKSIG", name: "p2pk with uncompressed pk missing OP_CHECKSIG",
script: decodeHex("410411db93e1dcdb8a016b49840f8c53bc" + script: hexToBytes("410411db93e1dcdb8a016b49840f8c53b" +
"1eb68a382e97b1482ecad7b148a6909a5cb2e0eaddfb" + "c1eb68a382e97b1482ecad7b148a6909a5cb2e0eaddf" +
"84ccf9744464f82e160bfa9b8b64f9d4c03f999b8643" + "b84ccf9744464f82e160bfa9b8b64f9d4c03f999b864" +
"f656b412a3"), "3f656b412a3"),
addrs: nil, addrs: nil,
reqSigs: 0, reqSigs: 0,
class: txscript.NonStandardTy, class: NonStandardTy,
}, },
{ {
name: "valid signature from a sigscript - no addresses", name: "valid signature from a sigscript - no addresses",
script: decodeHex("47304402204e45e16932b8af514961a1d3" + script: hexToBytes("47304402204e45e16932b8af514961a1d" +
"a1a25fdf3f4f7732e9d624c6c61548ab5fb8cd410220" + "3a1a25fdf3f4f7732e9d624c6c61548ab5fb8cd41022" +
"181522ec8eca07de4860a4acdd12909d831cc56cbbac" + "0181522ec8eca07de4860a4acdd12909d831cc56cbba" +
"4622082221a8768d1d0901"), "c4622082221a8768d1d0901"),
addrs: nil, addrs: nil,
reqSigs: 0, reqSigs: 0,
class: txscript.NonStandardTy, class: NonStandardTy,
}, },
// Note the technically the pubkey is the second item on the // Note the technically the pubkey is the second item on the
// stack, but since the address extraction intentionally only // stack, but since the address extraction intentionally only
@ -294,70 +279,70 @@ func TestExtractPkScriptAddrs(t *testing.T) {
// addresses. // addresses.
{ {
name: "valid sigscript to reedeem p2pk - no addresses", name: "valid sigscript to reedeem p2pk - no addresses",
script: decodeHex("493046022100ddc69738bf2336318e4e04" + script: hexToBytes("493046022100ddc69738bf2336318e4e0" +
"1a5a77f305da87428ab1606f023260017854350ddc02" + "41a5a77f305da87428ab1606f023260017854350ddc0" +
"2100817af09d2eec36862d16009852b7e3a0f6dd7659" + "22100817af09d2eec36862d16009852b7e3a0f6dd765" +
"8290b7834e1453660367e07a014104cd4240c198e125" + "98290b7834e1453660367e07a014104cd4240c198e12" +
"23b6f9cb9f5bed06de1ba37e96a1bbd13745fcf9d11c" + "523b6f9cb9f5bed06de1ba37e96a1bbd13745fcf9d11" +
"25b1dff9a519675d198804ba9962d3eca2d5937d58e5" + "c25b1dff9a519675d198804ba9962d3eca2d5937d58e" +
"a75a71042d40388a4d307f887d"), "5a75a71042d40388a4d307f887d"),
addrs: nil, addrs: nil,
reqSigs: 0, reqSigs: 0,
class: txscript.NonStandardTy, class: NonStandardTy,
}, },
// from real tx 691dd277dc0e90a462a3d652a1171686de49cf19067cd33c7df0392833fb986a, vout 0 // from real tx 691dd277dc0e90a462a3d652a1171686de49cf19067cd33c7df0392833fb986a, vout 0
// invalid public keys // invalid public keys
{ {
name: "1 of 3 multisig with invalid pubkeys", name: "1 of 3 multisig with invalid pubkeys",
script: decodeHex("51411c2200007353455857696b696c6561" + script: hexToBytes("51411c2200007353455857696b696c656" +
"6b73204361626c6567617465204261636b75700a0a63" + "16b73204361626c6567617465204261636b75700a0a6" +
"61626c65676174652d3230313031323034313831312e" + "361626c65676174652d3230313031323034313831312" +
"377a0a0a446f41776e6c6f61642074686520666f6c6c" + "e377a0a0a446f41776e6c6f61642074686520666f6c6" +
"6f77696e67207472616e73616374696f6e7320776974" + "c6f77696e67207472616e73616374696f6e732077697" +
"68205361746f736869204e616b616d6f746f27732064" + "468205361746f736869204e616b616d6f746f2773206" +
"6f776e6c6f61416420746f6f6c2077686963680a6361" + "46f776e6c6f61416420746f6f6c2077686963680a636" +
"6e20626520666f756e6420696e207472616e73616374" + "16e20626520666f756e6420696e207472616e7361637" +
"696f6e20366335336364393837313139656637393764" + "4696f6e2036633533636439383731313965663739376" +
"35616463636453ae"), "435616463636453ae"),
addrs: []btcutil.Address{}, addrs: []btcutil.Address{},
reqSigs: 1, reqSigs: 1,
class: txscript.MultiSigTy, class: MultiSigTy,
}, },
// from real tx: 691dd277dc0e90a462a3d652a1171686de49cf19067cd33c7df0392833fb986a, vout 44 // from real tx: 691dd277dc0e90a462a3d652a1171686de49cf19067cd33c7df0392833fb986a, vout 44
// invalid public keys // invalid public keys
{ {
name: "1 of 3 multisig with invalid pubkeys 2", name: "1 of 3 multisig with invalid pubkeys 2",
script: decodeHex("5141346333656332353963373464616365" + script: hexToBytes("514134633365633235396337346461636" +
"36666430383862343463656638630a63363662633139" + "536666430383862343463656638630a6336366263313" +
"39366338623934613338313162333635363138666531" + "93936633862393461333831316233363536313866653" +
"65396231623541366361636365393933613339383861" + "16539623162354136636163636539393361333938386" +
"34363966636336643664616266640a32363633636661" + "134363966636336643664616266640a3236363363666" +
"39636634633033633630396335393363336539316665" + "13963663463303363363039633539336333653931666" +
"64653730323921313233646434326432353633396433" + "56465373032392131323364643432643235363339643" +
"38613663663530616234636434340a00000053ae"), "338613663663530616234636434340a00000053ae"),
addrs: []btcutil.Address{}, addrs: []btcutil.Address{},
reqSigs: 1, reqSigs: 1,
class: txscript.MultiSigTy, class: MultiSigTy,
}, },
{ {
name: "empty script", name: "empty script",
script: []byte{}, script: []byte{},
addrs: nil, addrs: nil,
reqSigs: 0, reqSigs: 0,
class: txscript.NonStandardTy, class: NonStandardTy,
}, },
{ {
name: "script that does not parse", name: "script that does not parse",
script: []byte{txscript.OP_DATA_45}, script: []byte{OP_DATA_45},
addrs: nil, addrs: nil,
reqSigs: 0, reqSigs: 0,
class: txscript.NonStandardTy, class: NonStandardTy,
}, },
} }
t.Logf("Running %d tests.", len(tests)) t.Logf("Running %d tests.", len(tests))
for i, test := range tests { for i, test := range tests {
class, addrs, reqSigs, err := txscript.ExtractPkScriptAddrs( class, addrs, reqSigs, err := ExtractPkScriptAddrs(
test.script, &chaincfg.MainNetParams) test.script, &chaincfg.MainNetParams)
if err != nil { if err != nil {
} }
@ -395,7 +380,7 @@ func TestCalcScriptInfo(t *testing.T) {
sigScript string sigScript string
pkScript string pkScript string
bip16 bool bip16 bool
scriptInfo txscript.ScriptInfo scriptInfo ScriptInfo
scriptInfoErr error scriptInfoErr error
}{ }{
{ {
@ -407,7 +392,7 @@ func TestCalcScriptInfo(t *testing.T) {
pkScript: "HASH160 DATA_20 0xfe441065b6532231de2fac56" + pkScript: "HASH160 DATA_20 0xfe441065b6532231de2fac56" +
"3152205ec4f59c", "3152205ec4f59c",
bip16: true, bip16: true,
scriptInfoErr: txscript.ErrStackShortScript, scriptInfoErr: ErrStackShortScript,
}, },
{ {
name: "sigScript doesn't parse", name: "sigScript doesn't parse",
@ -417,7 +402,7 @@ func TestCalcScriptInfo(t *testing.T) {
pkScript: "HASH160 DATA_20 0xfe441065b6532231de2fac56" + pkScript: "HASH160 DATA_20 0xfe441065b6532231de2fac56" +
"3152205ec4f59c74 EQUAL", "3152205ec4f59c74 EQUAL",
bip16: true, bip16: true,
scriptInfoErr: txscript.ErrStackShortScript, scriptInfoErr: ErrStackShortScript,
}, },
{ {
// Invented scripts, the hashes do not match // Invented scripts, the hashes do not match
@ -428,8 +413,8 @@ func TestCalcScriptInfo(t *testing.T) {
pkScript: "HASH160 DATA_20 0xfe441065b6532231de2fac56" + pkScript: "HASH160 DATA_20 0xfe441065b6532231de2fac56" +
"3152205ec4f59c74 EQUAL", "3152205ec4f59c74 EQUAL",
bip16: true, bip16: true,
scriptInfo: txscript.ScriptInfo{ scriptInfo: ScriptInfo{
PkScriptClass: txscript.ScriptHashTy, PkScriptClass: ScriptHashTy,
NumInputs: 3, NumInputs: 3,
ExpectedInputs: 3, // nonstandard p2sh. ExpectedInputs: 3, // nonstandard p2sh.
SigOps: 1, SigOps: 1,
@ -444,8 +429,8 @@ func TestCalcScriptInfo(t *testing.T) {
pkScript: "HASH160 DATA_20 0xfe441065b6532231de2fac56" + pkScript: "HASH160 DATA_20 0xfe441065b6532231de2fac56" +
"3152205ec4f59c74 EQUAL", "3152205ec4f59c74 EQUAL",
bip16: true, bip16: true,
scriptInfo: txscript.ScriptInfo{ scriptInfo: ScriptInfo{
PkScriptClass: txscript.ScriptHashTy, PkScriptClass: ScriptHashTy,
NumInputs: 3, NumInputs: 3,
ExpectedInputs: -1, // nonstandard p2sh. ExpectedInputs: -1, // nonstandard p2sh.
SigOps: 0, SigOps: 0,
@ -464,8 +449,8 @@ func TestCalcScriptInfo(t *testing.T) {
"5060708090a0b0c0d0e0f101112131415161718191a1" + "5060708090a0b0c0d0e0f101112131415161718191a1" +
"b1c1d1e1f2021 3 CHECKMULTISIG", "b1c1d1e1f2021 3 CHECKMULTISIG",
bip16: true, bip16: true,
scriptInfo: txscript.ScriptInfo{ scriptInfo: ScriptInfo{
PkScriptClass: txscript.MultiSigTy, PkScriptClass: MultiSigTy,
NumInputs: 4, NumInputs: 4,
ExpectedInputs: 4, ExpectedInputs: 4,
SigOps: 3, SigOps: 3,
@ -476,7 +461,7 @@ func TestCalcScriptInfo(t *testing.T) {
for _, test := range tests { for _, test := range tests {
sigScript := mustParseShortForm(test.sigScript) sigScript := mustParseShortForm(test.sigScript)
pkScript := mustParseShortForm(test.pkScript) pkScript := mustParseShortForm(test.pkScript)
si, err := txscript.CalcScriptInfo(sigScript, pkScript, si, err := CalcScriptInfo(sigScript, pkScript,
test.bip16) test.bip16)
if err != nil { if err != nil {
if err != test.scriptInfoErr { if err != test.scriptInfoErr {
@ -533,8 +518,8 @@ func TestPayToAddrScript(t *testing.T) {
t.Parallel() t.Parallel()
// 1MirQ9bwyQcGVJPwKUgapu5ouK2E2Ey4gX // 1MirQ9bwyQcGVJPwKUgapu5ouK2E2Ey4gX
p2pkhMain, err := btcutil.NewAddressPubKeyHash(decodeHex("e34cce70c863"+ p2pkhMain, err := btcutil.NewAddressPubKeyHash(hexToBytes("e34cce70c86"+
"73273efcc54ce7d2a491bb4a0e84"), &chaincfg.MainNetParams) "373273efcc54ce7d2a491bb4a0e84"), &chaincfg.MainNetParams)
if err != nil { if err != nil {
t.Errorf("Unable to create public key hash address: %v", err) t.Errorf("Unable to create public key hash address: %v", err)
return return
@ -542,7 +527,7 @@ func TestPayToAddrScript(t *testing.T) {
// Taken from transaction: // Taken from transaction:
// b0539a45de13b3e0403909b8bd1a555b8cbe45fd4e3f3fda76f3a5f52835c29d // b0539a45de13b3e0403909b8bd1a555b8cbe45fd4e3f3fda76f3a5f52835c29d
p2shMain, _ := btcutil.NewAddressScriptHashFromHash(decodeHex("e8c300"+ p2shMain, _ := btcutil.NewAddressScriptHashFromHash(hexToBytes("e8c300"+
"c87986efa84c37c0519929019ef86eb5b4"), &chaincfg.MainNetParams) "c87986efa84c37c0519929019ef86eb5b4"), &chaincfg.MainNetParams)
if err != nil { if err != nil {
t.Errorf("Unable to create script hash address: %v", err) t.Errorf("Unable to create script hash address: %v", err)
@ -550,16 +535,16 @@ func TestPayToAddrScript(t *testing.T) {
} }
// mainnet p2pk 13CG6SJ3yHUXo4Cr2RY4THLLJrNFuG3gUg // mainnet p2pk 13CG6SJ3yHUXo4Cr2RY4THLLJrNFuG3gUg
p2pkCompressedMain, err := btcutil.NewAddressPubKey(decodeHex("02192d74"+ p2pkCompressedMain, err := btcutil.NewAddressPubKey(hexToBytes("02192d"+
"d0cb94344c9569c2e77901573d8d7903c3ebec3a957724895dca52c6b4"), "74d0cb94344c9569c2e77901573d8d7903c3ebec3a957724895dca52c6b4"),
&chaincfg.MainNetParams) &chaincfg.MainNetParams)
if err != nil { if err != nil {
t.Errorf("Unable to create pubkey address (compressed): %v", t.Errorf("Unable to create pubkey address (compressed): %v",
err) err)
return return
} }
p2pkCompressed2Main, err := btcutil.NewAddressPubKey(decodeHex("03b0bd"+ p2pkCompressed2Main, err := btcutil.NewAddressPubKey(hexToBytes("03b0b"+
"634234abbb1ba1e986e884185c61cf43e001f9137f23c2c409273eb16e65"), "d634234abbb1ba1e986e884185c61cf43e001f9137f23c2c409273eb16e65"),
&chaincfg.MainNetParams) &chaincfg.MainNetParams)
if err != nil { if err != nil {
t.Errorf("Unable to create pubkey address (compressed 2): %v", t.Errorf("Unable to create pubkey address (compressed 2): %v",
@ -567,10 +552,10 @@ func TestPayToAddrScript(t *testing.T) {
return return
} }
p2pkUncompressedMain, err := btcutil.NewAddressPubKey(decodeHex("0411db"+ p2pkUncompressedMain, err := btcutil.NewAddressPubKey(hexToBytes("0411"+
"93e1dcdb8a016b49840f8c53bc1eb68a382e97b1482ecad7b148a6909a5cb2"+ "db93e1dcdb8a016b49840f8c53bc1eb68a382e97b1482ecad7b148a6909a5"+
"e0eaddfb84ccf9744464f82e160bfa9b8b64f9d4c03f999b8643f656b412a3"), "cb2e0eaddfb84ccf9744464f82e160bfa9b8b64f9d4c03f999b8643f656b4"+
&chaincfg.MainNetParams) "12a3"), &chaincfg.MainNetParams)
if err != nil { if err != nil {
t.Errorf("Unable to create pubkey address (uncompressed): %v", t.Errorf("Unable to create pubkey address (uncompressed): %v",
err) err)
@ -621,17 +606,17 @@ func TestPayToAddrScript(t *testing.T) {
}, },
// Supported address types with nil pointers. // Supported address types with nil pointers.
{(*btcutil.AddressPubKeyHash)(nil), "", txscript.ErrUnsupportedAddress}, {(*btcutil.AddressPubKeyHash)(nil), "", ErrUnsupportedAddress},
{(*btcutil.AddressScriptHash)(nil), "", txscript.ErrUnsupportedAddress}, {(*btcutil.AddressScriptHash)(nil), "", ErrUnsupportedAddress},
{(*btcutil.AddressPubKey)(nil), "", txscript.ErrUnsupportedAddress}, {(*btcutil.AddressPubKey)(nil), "", ErrUnsupportedAddress},
// Unsupported address type. // Unsupported address type.
{&bogusAddress{}, "", txscript.ErrUnsupportedAddress}, {&bogusAddress{}, "", ErrUnsupportedAddress},
} }
t.Logf("Running %d tests", len(tests)) t.Logf("Running %d tests", len(tests))
for i, test := range tests { for i, test := range tests {
pkScript, err := txscript.PayToAddrScript(test.in) pkScript, err := PayToAddrScript(test.in)
if err != test.err { if err != test.err {
t.Errorf("PayToAddrScript #%d unexpected error - "+ t.Errorf("PayToAddrScript #%d unexpected error - "+
"got %v, want %v", i, err, test.err) "got %v, want %v", i, err, test.err)
@ -653,16 +638,16 @@ func TestMultiSigScript(t *testing.T) {
t.Parallel() t.Parallel()
// mainnet p2pk 13CG6SJ3yHUXo4Cr2RY4THLLJrNFuG3gUg // mainnet p2pk 13CG6SJ3yHUXo4Cr2RY4THLLJrNFuG3gUg
p2pkCompressedMain, err := btcutil.NewAddressPubKey(decodeHex("02192d7"+ p2pkCompressedMain, err := btcutil.NewAddressPubKey(hexToBytes("02192d"+
"4d0cb94344c9569c2e77901573d8d7903c3ebec3a957724895dca52c6b4"), "74d0cb94344c9569c2e77901573d8d7903c3ebec3a957724895dca52c6b4"),
&chaincfg.MainNetParams) &chaincfg.MainNetParams)
if err != nil { if err != nil {
t.Errorf("Unable to create pubkey address (compressed): %v", t.Errorf("Unable to create pubkey address (compressed): %v",
err) err)
return return
} }
p2pkCompressed2Main, err := btcutil.NewAddressPubKey(decodeHex("03b0bd"+ p2pkCompressed2Main, err := btcutil.NewAddressPubKey(hexToBytes("03b0b"+
"634234abbb1ba1e986e884185c61cf43e001f9137f23c2c409273eb16e65"), "d634234abbb1ba1e986e884185c61cf43e001f9137f23c2c409273eb16e65"),
&chaincfg.MainNetParams) &chaincfg.MainNetParams)
if err != nil { if err != nil {
t.Errorf("Unable to create pubkey address (compressed 2): %v", t.Errorf("Unable to create pubkey address (compressed 2): %v",
@ -670,10 +655,10 @@ func TestMultiSigScript(t *testing.T) {
return return
} }
p2pkUncompressedMain, err := btcutil.NewAddressPubKey(decodeHex("0411d"+ p2pkUncompressedMain, err := btcutil.NewAddressPubKey(hexToBytes("0411"+
"b93e1dcdb8a016b49840f8c53bc1eb68a382e97b1482ecad7b148a6909a5c"+ "db93e1dcdb8a016b49840f8c53bc1eb68a382e97b1482ecad7b148a6909a5"+
"b2e0eaddfb84ccf9744464f82e160bfa9b8b64f9d4c03f999b8643f656b41"+ "cb2e0eaddfb84ccf9744464f82e160bfa9b8b64f9d4c03f999b8643f656b4"+
"2a3"), &chaincfg.MainNetParams) "12a3"), &chaincfg.MainNetParams)
if err != nil { if err != nil {
t.Errorf("Unable to create pubkey address (uncompressed): %v", t.Errorf("Unable to create pubkey address (uncompressed): %v",
err) err)
@ -717,7 +702,7 @@ func TestMultiSigScript(t *testing.T) {
}, },
3, 3,
"", "",
txscript.ErrBadNumRequired, ErrBadNumRequired,
}, },
{ {
[]*btcutil.AddressPubKey{ []*btcutil.AddressPubKey{
@ -736,14 +721,13 @@ func TestMultiSigScript(t *testing.T) {
}, },
2, 2,
"", "",
txscript.ErrBadNumRequired, ErrBadNumRequired,
}, },
} }
t.Logf("Running %d tests", len(tests)) t.Logf("Running %d tests", len(tests))
for i, test := range tests { for i, test := range tests {
script, err := txscript.MultiSigScript(test.keys, script, err := MultiSigScript(test.keys, test.nrequired)
test.nrequired)
if err != test.err { if err != test.err {
t.Errorf("MultiSigScript #%d unexpected error - "+ t.Errorf("MultiSigScript #%d unexpected error - "+
"got %v, want %v", i, err, test.err) "got %v, want %v", i, err, test.err)
@ -773,14 +757,14 @@ func TestCalcMultiSigStats(t *testing.T) {
name: "short script", name: "short script",
script: "0x046708afdb0fe5548271967f1a67130b7105cd6a828" + script: "0x046708afdb0fe5548271967f1a67130b7105cd6a828" +
"e03909a67962e0ea1f61d", "e03909a67962e0ea1f61d",
err: txscript.ErrStackShortScript, err: ErrStackShortScript,
}, },
{ {
name: "stack underflow", name: "stack underflow",
script: "RETURN DATA_41 0x046708afdb0fe5548271967f1a" + script: "RETURN DATA_41 0x046708afdb0fe5548271967f1a" +
"67130b7105cd6a828e03909a67962e0ea1f61deb649f6" + "67130b7105cd6a828e03909a67962e0ea1f61deb649f6" +
"bc3f4cef308", "bc3f4cef308",
err: txscript.ErrStackUnderflow, err: ErrStackUnderflow,
}, },
{ {
name: "multisig script", name: "multisig script",
@ -796,7 +780,7 @@ func TestCalcMultiSigStats(t *testing.T) {
for i, test := range tests { for i, test := range tests {
script := mustParseShortForm(test.script) script := mustParseShortForm(test.script)
if _, _, err := txscript.CalcMultiSigStats(script); err != test.err { if _, _, err := CalcMultiSigStats(script); err != test.err {
t.Errorf("CalcMultiSigStats #%d (%s) unexpected "+ t.Errorf("CalcMultiSigStats #%d (%s) unexpected "+
"error\ngot: %v\nwant: %v", i, test.name, err, "error\ngot: %v\nwant: %v", i, test.name, err,
test.err) test.err)
@ -811,21 +795,21 @@ func TestCalcMultiSigStats(t *testing.T) {
var scriptClassTests = []struct { var scriptClassTests = []struct {
name string name string
script string script string
class txscript.ScriptClass class ScriptClass
}{ }{
{ {
name: "Pay Pubkey", name: "Pay Pubkey",
script: "DATA_65 0x0411db93e1dcdb8a016b49840f8c53bc1eb68a382e" + script: "DATA_65 0x0411db93e1dcdb8a016b49840f8c53bc1eb68a382e" +
"97b1482ecad7b148a6909a5cb2e0eaddfb84ccf9744464f82e16" + "97b1482ecad7b148a6909a5cb2e0eaddfb84ccf9744464f82e16" +
"0bfa9b8b64f9d4c03f999b8643f656b412a3 CHECKSIG", "0bfa9b8b64f9d4c03f999b8643f656b412a3 CHECKSIG",
class: txscript.PubKeyTy, class: PubKeyTy,
}, },
// tx 599e47a8114fe098103663029548811d2651991b62397e057f0c863c2bc9f9ea // tx 599e47a8114fe098103663029548811d2651991b62397e057f0c863c2bc9f9ea
{ {
name: "Pay PubkeyHash", name: "Pay PubkeyHash",
script: "DUP HASH160 DATA_20 0x660d4ef3a743e3e696ad990364e555" + script: "DUP HASH160 DATA_20 0x660d4ef3a743e3e696ad990364e555" +
"c271ad504b EQUALVERIFY CHECKSIG", "c271ad504b EQUALVERIFY CHECKSIG",
class: txscript.PubKeyHashTy, class: PubKeyHashTy,
}, },
// part of tx 6d36bc17e947ce00bb6f12f8e7a56a1585c5a36188ffa2b05e10b4743273a74b // part of tx 6d36bc17e947ce00bb6f12f8e7a56a1585c5a36188ffa2b05e10b4743273a74b
// codeseparator parts have been elided. (bitcoin core's checks for // codeseparator parts have been elided. (bitcoin core's checks for
@ -834,45 +818,45 @@ var scriptClassTests = []struct {
name: "multisig", name: "multisig",
script: "1 DATA_33 0x0232abdc893e7f0631364d7fd01cb33d24da4" + script: "1 DATA_33 0x0232abdc893e7f0631364d7fd01cb33d24da4" +
"5329a00357b3a7886211ab414d55a 1 CHECKMULTISIG", "5329a00357b3a7886211ab414d55a 1 CHECKMULTISIG",
class: txscript.MultiSigTy, class: MultiSigTy,
}, },
// tx e5779b9e78f9650debc2893fd9636d827b26b4ddfa6a8172fe8708c924f5c39d // tx e5779b9e78f9650debc2893fd9636d827b26b4ddfa6a8172fe8708c924f5c39d
{ {
name: "P2SH", name: "P2SH",
script: "HASH160 DATA_20 0x433ec2ac1ffa1b7b7d027f564529c57197f" + script: "HASH160 DATA_20 0x433ec2ac1ffa1b7b7d027f564529c57197f" +
"9ae88 EQUAL", "9ae88 EQUAL",
class: txscript.ScriptHashTy, class: ScriptHashTy,
}, },
{ {
// Nulldata with no data at all. // Nulldata with no data at all.
name: "nulldata no data", name: "nulldata no data",
script: "RETURN", script: "RETURN",
class: txscript.NullDataTy, class: NullDataTy,
}, },
{ {
// Nulldata with single zero push. // Nulldata with single zero push.
name: "nulldata zero", name: "nulldata zero",
script: "RETURN 0", script: "RETURN 0",
class: txscript.NullDataTy, class: NullDataTy,
}, },
{ {
// Nulldata with small integer push. // Nulldata with small integer push.
name: "nulldata small int", name: "nulldata small int",
script: "RETURN 1", script: "RETURN 1",
class: txscript.NullDataTy, class: NullDataTy,
}, },
{ {
// Nulldata with max small integer push. // Nulldata with max small integer push.
name: "nulldata max small int", name: "nulldata max small int",
script: "RETURN 16", script: "RETURN 16",
class: txscript.NullDataTy, class: NullDataTy,
}, },
{ {
// Nulldata with small data push. // Nulldata with small data push.
name: "nulldata small data", name: "nulldata small data",
script: "RETURN DATA_8 0x046708afdb0fe554", script: "RETURN DATA_8 0x046708afdb0fe554",
class: txscript.NullDataTy, class: NullDataTy,
}, },
{ {
// Canonical nulldata with 60-byte data push. // Canonical nulldata with 60-byte data push.
@ -880,7 +864,7 @@ var scriptClassTests = []struct {
script: "RETURN 0x3c 0x046708afdb0fe5548271967f1a67130b7105cd" + script: "RETURN 0x3c 0x046708afdb0fe5548271967f1a67130b7105cd" +
"6a828e03909a67962e0ea1f61deb649f6bc3f4cef3046708afdb" + "6a828e03909a67962e0ea1f61deb649f6bc3f4cef3046708afdb" +
"0fe5548271967f1a67130b7105cd6a", "0fe5548271967f1a67130b7105cd6a",
class: txscript.NullDataTy, class: NullDataTy,
}, },
{ {
// Non-canonical nulldata with 60-byte data push. // Non-canonical nulldata with 60-byte data push.
@ -888,7 +872,7 @@ var scriptClassTests = []struct {
script: "RETURN PUSHDATA1 0x3c 0x046708afdb0fe5548271967f1a67" + script: "RETURN PUSHDATA1 0x3c 0x046708afdb0fe5548271967f1a67" +
"130b7105cd6a828e03909a67962e0ea1f61deb649f6bc3f4cef3" + "130b7105cd6a828e03909a67962e0ea1f61deb649f6bc3f4cef3" +
"046708afdb0fe5548271967f1a67130b7105cd6a", "046708afdb0fe5548271967f1a67130b7105cd6a",
class: txscript.NullDataTy, class: NullDataTy,
}, },
{ {
// Nulldata with max allowed data to be considered standard. // Nulldata with max allowed data to be considered standard.
@ -897,7 +881,7 @@ var scriptClassTests = []struct {
"130b7105cd6a828e03909a67962e0ea1f61deb649f6bc3f4cef3" + "130b7105cd6a828e03909a67962e0ea1f61deb649f6bc3f4cef3" +
"046708afdb0fe5548271967f1a67130b7105cd6a828e03909a67" + "046708afdb0fe5548271967f1a67130b7105cd6a828e03909a67" +
"962e0ea1f61deb649f6bc3f4cef3", "962e0ea1f61deb649f6bc3f4cef3",
class: txscript.NullDataTy, class: NullDataTy,
}, },
{ {
// Nulldata with more than max allowed data to be considered // Nulldata with more than max allowed data to be considered
@ -907,14 +891,14 @@ var scriptClassTests = []struct {
"130b7105cd6a828e03909a67962e0ea1f61deb649f6bc3f4cef3" + "130b7105cd6a828e03909a67962e0ea1f61deb649f6bc3f4cef3" +
"046708afdb0fe5548271967f1a67130b7105cd6a828e03909a67" + "046708afdb0fe5548271967f1a67130b7105cd6a828e03909a67" +
"962e0ea1f61deb649f6bc3f4cef308", "962e0ea1f61deb649f6bc3f4cef308",
class: txscript.NonStandardTy, class: NonStandardTy,
}, },
{ {
// Almost nulldata, but add an additional opcode after the data // Almost nulldata, but add an additional opcode after the data
// to make it nonstandard. // to make it nonstandard.
name: "almost nulldata", name: "almost nulldata",
script: "RETURN 4 TRUE", script: "RETURN 4 TRUE",
class: txscript.NonStandardTy, class: NonStandardTy,
}, },
// The next few are almost multisig (it is the more complex script type) // The next few are almost multisig (it is the more complex script type)
@ -924,13 +908,13 @@ var scriptClassTests = []struct {
name: "strange 1", name: "strange 1",
script: "DUP DATA_33 0x0232abdc893e7f0631364d7fd01cb33d24da45" + script: "DUP DATA_33 0x0232abdc893e7f0631364d7fd01cb33d24da45" +
"329a00357b3a7886211ab414d55a 1 CHECKMULTISIG", "329a00357b3a7886211ab414d55a 1 CHECKMULTISIG",
class: txscript.NonStandardTy, class: NonStandardTy,
}, },
{ {
// Multisig but invalid pubkey. // Multisig but invalid pubkey.
name: "strange 2", name: "strange 2",
script: "1 1 1 CHECKMULTISIG", script: "1 1 1 CHECKMULTISIG",
class: txscript.NonStandardTy, class: NonStandardTy,
}, },
{ {
// Multisig but no matching npubkeys opcode. // Multisig but no matching npubkeys opcode.
@ -939,25 +923,25 @@ var scriptClassTests = []struct {
"9a00357b3a7886211ab414d55a DATA_33 0x0232abdc893e7f0" + "9a00357b3a7886211ab414d55a DATA_33 0x0232abdc893e7f0" +
"631364d7fd01cb33d24da45329a00357b3a7886211ab414d55a " + "631364d7fd01cb33d24da45329a00357b3a7886211ab414d55a " +
"CHECKMULTISIG", "CHECKMULTISIG",
class: txscript.NonStandardTy, class: NonStandardTy,
}, },
{ {
// Multisig but with multisigverify. // Multisig but with multisigverify.
name: "strange 4", name: "strange 4",
script: "1 DATA_33 0x0232abdc893e7f0631364d7fd01cb33d24da4532" + script: "1 DATA_33 0x0232abdc893e7f0631364d7fd01cb33d24da4532" +
"9a00357b3a7886211ab414d55a 1 CHECKMULTISIGVERIFY", "9a00357b3a7886211ab414d55a 1 CHECKMULTISIGVERIFY",
class: txscript.NonStandardTy, class: NonStandardTy,
}, },
{ {
// Multisig but wrong length. // Multisig but wrong length.
name: "strange 5", name: "strange 5",
script: "1 CHECKMULTISIG", script: "1 CHECKMULTISIG",
class: txscript.NonStandardTy, class: NonStandardTy,
}, },
{ {
name: "doesn't parse", name: "doesn't parse",
script: "DATA_5 0x01020304", script: "DATA_5 0x01020304",
class: txscript.NonStandardTy, class: NonStandardTy,
}, },
{ {
name: "multisig script with wrong number of pubkeys", name: "multisig script with wrong number of pubkeys",
@ -969,7 +953,7 @@ var scriptClassTests = []struct {
"0x02c08f3de8ee2de9be7bd770f4c10eb0" + "0x02c08f3de8ee2de9be7bd770f4c10eb0" +
"d6ff1dd81ee96eedd3a9d4aeaf86695e80 " + "d6ff1dd81ee96eedd3a9d4aeaf86695e80 " +
"3 CHECKMULTISIG", "3 CHECKMULTISIG",
class: txscript.NonStandardTy, class: NonStandardTy,
}, },
} }
@ -980,7 +964,7 @@ func TestScriptClass(t *testing.T) {
for _, test := range scriptClassTests { for _, test := range scriptClassTests {
script := mustParseShortForm(test.script) script := mustParseShortForm(test.script)
class := txscript.GetScriptClass(script) class := GetScriptClass(script)
if class != test.class { if class != test.class {
t.Errorf("%s: expected %s got %s (script %x)", test.name, t.Errorf("%s: expected %s got %s (script %x)", test.name,
test.class, class, script) test.class, class, script)
@ -996,42 +980,42 @@ func TestStringifyClass(t *testing.T) {
tests := []struct { tests := []struct {
name string name string
class txscript.ScriptClass class ScriptClass
stringed string stringed string
}{ }{
{ {
name: "nonstandardty", name: "nonstandardty",
class: txscript.NonStandardTy, class: NonStandardTy,
stringed: "nonstandard", stringed: "nonstandard",
}, },
{ {
name: "pubkey", name: "pubkey",
class: txscript.PubKeyTy, class: PubKeyTy,
stringed: "pubkey", stringed: "pubkey",
}, },
{ {
name: "pubkeyhash", name: "pubkeyhash",
class: txscript.PubKeyHashTy, class: PubKeyHashTy,
stringed: "pubkeyhash", stringed: "pubkeyhash",
}, },
{ {
name: "scripthash", name: "scripthash",
class: txscript.ScriptHashTy, class: ScriptHashTy,
stringed: "scripthash", stringed: "scripthash",
}, },
{ {
name: "multisigty", name: "multisigty",
class: txscript.MultiSigTy, class: MultiSigTy,
stringed: "multisig", stringed: "multisig",
}, },
{ {
name: "nulldataty", name: "nulldataty",
class: txscript.NullDataTy, class: NullDataTy,
stringed: "nulldata", stringed: "nulldata",
}, },
{ {
name: "broken", name: "broken",
class: txscript.ScriptClass(255), class: ScriptClass(255),
stringed: "Invalid", stringed: "Invalid",
}, },
} }