Add flag bitmask to NewScript for canonical sig checks.
This removes the bip16 bool from NewScript and adds it to flags (with the constant ScriptBip16), and also adds a new flag, ScriptCanonicalSignatures, which will call btcec.ParseDERSignature parsing a signature during an Execute. This is needed to emulate bitcoind behavior, as bitcoind performs canonical signature validation (DER format) in some places (like mempool acceptance) but not others (like block validation). Updated tests and test coverage file to reflect changes.
This commit is contained in:
parent
40c75b27ac
commit
8eead5217d
5 changed files with 286 additions and 25 deletions
14
opcode.go
14
opcode.go
|
@ -1682,7 +1682,12 @@ func opcodeCheckSig(op *parsedOpcode, s *Script) error {
|
||||||
return err
|
return err
|
||||||
}
|
}
|
||||||
|
|
||||||
signature, err := btcec.ParseSignature(sigStr, btcec.S256())
|
var signature *btcec.Signature
|
||||||
|
if s.der {
|
||||||
|
signature, err = btcec.ParseDERSignature(sigStr, btcec.S256())
|
||||||
|
} else {
|
||||||
|
signature, err = btcec.ParseSignature(sigStr, btcec.S256())
|
||||||
|
}
|
||||||
if err != nil {
|
if err != nil {
|
||||||
log.Warnf("can't parse signature from string: %v", err)
|
log.Warnf("can't parse signature from string: %v", err)
|
||||||
return err
|
return err
|
||||||
|
@ -1761,10 +1766,17 @@ func opcodeCheckMultiSig(op *parsedOpcode, s *Script) error {
|
||||||
return err
|
return err
|
||||||
}
|
}
|
||||||
// skip off the last byte for hashtype
|
// skip off the last byte for hashtype
|
||||||
|
if s.der {
|
||||||
|
signatures[i], err =
|
||||||
|
btcec.ParseDERSignature(
|
||||||
|
sigStrings[i][:len(sigStrings[i])-1],
|
||||||
|
btcec.S256())
|
||||||
|
} else {
|
||||||
signatures[i], err =
|
signatures[i], err =
|
||||||
btcec.ParseSignature(
|
btcec.ParseSignature(
|
||||||
sigStrings[i][:len(sigStrings[i])-1],
|
sigStrings[i][:len(sigStrings[i])-1],
|
||||||
btcec.S256())
|
btcec.S256())
|
||||||
|
}
|
||||||
if err != nil {
|
if err != nil {
|
||||||
return err
|
return err
|
||||||
}
|
}
|
||||||
|
|
|
@ -19,6 +19,7 @@ import (
|
||||||
// All run on a fake tx with a single in, single out.
|
// All run on a fake tx with a single in, single out.
|
||||||
type opcodeTest struct {
|
type opcodeTest struct {
|
||||||
script []byte
|
script []byte
|
||||||
|
canonical bool
|
||||||
shouldPass bool
|
shouldPass bool
|
||||||
shouldFail error
|
shouldFail error
|
||||||
}
|
}
|
||||||
|
@ -384,6 +385,18 @@ var opcodeTests = []opcodeTest{
|
||||||
0x8a, 0x06, 0x26, 0xf1, 0xba, 0xde, 0xd5, 0xc7, 0x2a, 0x70,
|
0x8a, 0x06, 0x26, 0xf1, 0xba, 0xde, 0xd5, 0xc7, 0x2a, 0x70,
|
||||||
0x4f, 0x7e, 0x6c, 0xd8, 0x4c,
|
0x4f, 0x7e, 0x6c, 0xd8, 0x4c,
|
||||||
btcscript.OP_1, btcscript.OP_CHECK_MULTISIG},
|
btcscript.OP_1, btcscript.OP_CHECK_MULTISIG},
|
||||||
|
canonical: false,
|
||||||
|
shouldPass: false},
|
||||||
|
{script: []byte{btcscript.OP_1, btcscript.OP_1, btcscript.OP_DATA_65,
|
||||||
|
0x04, 0xae, 0x1a, 0x62, 0xfe, 0x09, 0xc5, 0xf5, 0x1b, 0x13,
|
||||||
|
0x90, 0x5f, 0x07, 0xf0, 0x6b, 0x99, 0xa2, 0xf7, 0x15, 0x9b,
|
||||||
|
0x22, 0x25, 0xf3, 0x74, 0xcd, 0x37, 0x8d, 0x71, 0x30, 0x2f,
|
||||||
|
0xa2, 0x84, 0x14, 0xe7, 0xaa, 0xb3, 0x73, 0x97, 0xf5, 0x54,
|
||||||
|
0xa7, 0xdf, 0x5f, 0x14, 0x2c, 0x21, 0xc1, 0xb7, 0x30, 0x3b,
|
||||||
|
0x8a, 0x06, 0x26, 0xf1, 0xba, 0xde, 0xd5, 0xc7, 0x2a, 0x70,
|
||||||
|
0x4f, 0x7e, 0x6c, 0xd8, 0x4c,
|
||||||
|
btcscript.OP_1, btcscript.OP_CHECK_MULTISIG},
|
||||||
|
canonical: true,
|
||||||
shouldPass: false},
|
shouldPass: false},
|
||||||
/* up here because no defined error case. */
|
/* up here because no defined error case. */
|
||||||
{script: []byte{btcscript.OP_1, btcscript.OP_1, btcscript.OP_DATA_65,
|
{script: []byte{btcscript.OP_1, btcscript.OP_1, btcscript.OP_DATA_65,
|
||||||
|
@ -468,7 +481,7 @@ var opcodeTests = []opcodeTest{
|
||||||
{script: []byte{252}, shouldPass: false},
|
{script: []byte{252}, shouldPass: false},
|
||||||
}
|
}
|
||||||
|
|
||||||
func testScript(t *testing.T, script []byte) (err error) {
|
func testScript(t *testing.T, script []byte, canonical bool) (err error) {
|
||||||
// mock up fake tx.
|
// mock up fake tx.
|
||||||
tx := &btcwire.MsgTx{
|
tx := &btcwire.MsgTx{
|
||||||
Version: 1,
|
Version: 1,
|
||||||
|
@ -493,8 +506,13 @@ func testScript(t *testing.T, script []byte) (err error) {
|
||||||
|
|
||||||
tx.TxOut[0].PkScript = script
|
tx.TxOut[0].PkScript = script
|
||||||
|
|
||||||
|
var flags btcscript.ScriptFlags
|
||||||
|
if canonical {
|
||||||
|
flags = btcscript.ScriptCanonicalSignatures
|
||||||
|
}
|
||||||
|
|
||||||
engine, err := btcscript.NewScript(tx.TxIn[0].SignatureScript,
|
engine, err := btcscript.NewScript(tx.TxIn[0].SignatureScript,
|
||||||
tx.TxOut[0].PkScript, 0, tx, false)
|
tx.TxOut[0].PkScript, 0, tx, flags)
|
||||||
if err != nil {
|
if err != nil {
|
||||||
return err
|
return err
|
||||||
}
|
}
|
||||||
|
@ -514,7 +532,7 @@ func TestScripts(t *testing.T) {
|
||||||
for i := range opcodeTests {
|
for i := range opcodeTests {
|
||||||
shouldPass := opcodeTests[i].shouldPass
|
shouldPass := opcodeTests[i].shouldPass
|
||||||
shouldFail := opcodeTests[i].shouldFail
|
shouldFail := opcodeTests[i].shouldFail
|
||||||
err := testScript(t, opcodeTests[i].script)
|
err := testScript(t, opcodeTests[i].script, opcodeTests[i].canonical)
|
||||||
if shouldFail != nil {
|
if shouldFail != nil {
|
||||||
if err == nil {
|
if err == nil {
|
||||||
t.Errorf("test %d passed should fail with %v", i, err)
|
t.Errorf("test %d passed should fail with %v", i, err)
|
||||||
|
@ -4279,7 +4297,7 @@ func testOpcode(t *testing.T, test *detailedTest) {
|
||||||
tx.TxOut[0].PkScript = test.script
|
tx.TxOut[0].PkScript = test.script
|
||||||
|
|
||||||
engine, err := btcscript.NewScript(tx.TxIn[0].SignatureScript,
|
engine, err := btcscript.NewScript(tx.TxIn[0].SignatureScript,
|
||||||
tx.TxOut[0].PkScript, 0, tx, false)
|
tx.TxOut[0].PkScript, 0, tx, 0)
|
||||||
if err != nil {
|
if err != nil {
|
||||||
if err != test.expectedReturn {
|
if err != test.expectedReturn {
|
||||||
t.Errorf("Error return not expected %s: %v %v",
|
t.Errorf("Error return not expected %s: %v %v",
|
||||||
|
|
62
script.go
62
script.go
|
@ -159,6 +159,7 @@ type Script struct {
|
||||||
condStack []int
|
condStack []int
|
||||||
numOps int
|
numOps int
|
||||||
bip16 bool // treat execution as pay-to-script-hash
|
bip16 bool // treat execution as pay-to-script-hash
|
||||||
|
der bool // enforce DER encoding
|
||||||
savedFirstStack [][]byte // stack from first script for bip16 scripts
|
savedFirstStack [][]byte // stack from first script for bip16 scripts
|
||||||
}
|
}
|
||||||
|
|
||||||
|
@ -361,11 +362,35 @@ func unparseScript(pops []parsedOpcode) ([]byte, error) {
|
||||||
return script, nil
|
return script, nil
|
||||||
}
|
}
|
||||||
|
|
||||||
|
// ScriptFlags is a bitmask defining additional operations or
|
||||||
|
// tests that will be done when executing a Script.
|
||||||
|
type ScriptFlags uint32
|
||||||
|
|
||||||
|
const (
|
||||||
|
// ScriptBip16 defines whether the bip16 threshhold has passed and thus
|
||||||
|
// pay-to-script hash transactions will be fully validated.
|
||||||
|
ScriptBip16 ScriptFlags = 1 << iota
|
||||||
|
|
||||||
|
// ScriptCanonicalSignatures defines whether additional canonical
|
||||||
|
// signature checks are performed when parsing a signature.
|
||||||
|
//
|
||||||
|
// Canonical (DER) signatures are not required in the tx rules for
|
||||||
|
// block acceptance, but are checked in recent versions of bitcoind
|
||||||
|
// when accepting transactions to the mempool. Non-canonical (valid
|
||||||
|
// BER but not valid DER) transactions can potentially be changed
|
||||||
|
// before mined into a block, either by adding extra padding or
|
||||||
|
// flipping the sign of the R or S value in the signature, creating a
|
||||||
|
// transaction that still validates and spends the inputs, but is not
|
||||||
|
// recognized by creator of the transaction. Performing a canonical
|
||||||
|
// check enforces script signatures use a unique DER format.
|
||||||
|
ScriptCanonicalSignatures
|
||||||
|
)
|
||||||
|
|
||||||
// NewScript returns a new script engine for the provided tx and input idx with
|
// NewScript returns a new script engine for the provided tx and input idx with
|
||||||
// a signature script scriptSig and a pubkeyscript scriptPubKey. If bip16 is
|
// a signature script scriptSig and a pubkeyscript scriptPubKey. If bip16 is
|
||||||
// true then it will be treated as if the bip16 threshhold has passed and thus
|
// true then it will be treated as if the bip16 threshhold has passed and thus
|
||||||
// pay-to-script hash transactions will be fully validated.
|
// pay-to-script hash transactions will be fully validated.
|
||||||
func NewScript(scriptSig []byte, scriptPubKey []byte, txidx int, tx *btcwire.MsgTx, bip16 bool) (*Script, error) {
|
func NewScript(scriptSig []byte, scriptPubKey []byte, txidx int, tx *btcwire.MsgTx, flags ScriptFlags) (*Script, error) {
|
||||||
var m Script
|
var m Script
|
||||||
scripts := [][]byte{scriptSig, scriptPubKey}
|
scripts := [][]byte{scriptSig, scriptPubKey}
|
||||||
m.scripts = make([][]parsedOpcode, len(scripts))
|
m.scripts = make([][]parsedOpcode, len(scripts))
|
||||||
|
@ -385,6 +410,8 @@ func NewScript(scriptSig []byte, scriptPubKey []byte, txidx int, tx *btcwire.Msg
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
|
// Parse flags.
|
||||||
|
bip16 := flags&ScriptBip16 == ScriptBip16
|
||||||
if bip16 && isScriptHash(m.scripts[1]) {
|
if bip16 && isScriptHash(m.scripts[1]) {
|
||||||
// if we are pay to scripthash then we only accept input
|
// if we are pay to scripthash then we only accept input
|
||||||
// scripts that push data
|
// scripts that push data
|
||||||
|
@ -393,6 +420,9 @@ func NewScript(scriptSig []byte, scriptPubKey []byte, txidx int, tx *btcwire.Msg
|
||||||
}
|
}
|
||||||
m.bip16 = true
|
m.bip16 = true
|
||||||
}
|
}
|
||||||
|
if flags&ScriptCanonicalSignatures == ScriptCanonicalSignatures {
|
||||||
|
m.der = true
|
||||||
|
}
|
||||||
|
|
||||||
m.tx = *tx
|
m.tx = *tx
|
||||||
m.txidx = txidx
|
m.txidx = txidx
|
||||||
|
@ -964,19 +994,39 @@ func signatureScriptCustomReader(reader io.Reader, tx *btcwire.MsgTx, idx int,
|
||||||
//
|
//
|
||||||
// 0x30 <length> 0x02 <length r> r 0x02 <length s> s
|
// 0x30 <length> 0x02 <length r> r 0x02 <length s> s
|
||||||
func sigDER(r, s *big.Int) []byte {
|
func sigDER(r, s *big.Int) []byte {
|
||||||
|
// In DER format, a leading 0x00 octet must be prepended to
|
||||||
|
// the byte slice so it cannot be interpreted as a negative
|
||||||
|
// big-endian number. This is only done if the sign bit on
|
||||||
|
// the first byte is set.
|
||||||
|
var rb, sb []byte
|
||||||
|
if r.Bytes()[0]&0x80 != 0 {
|
||||||
|
paddedBytes := make([]byte, len(r.Bytes())+1)
|
||||||
|
copy(paddedBytes[1:], r.Bytes())
|
||||||
|
rb = paddedBytes
|
||||||
|
} else {
|
||||||
|
rb = r.Bytes()
|
||||||
|
}
|
||||||
|
if s.Bytes()[0]&0x80 != 0 {
|
||||||
|
paddedBytes := make([]byte, len(s.Bytes())+1)
|
||||||
|
copy(paddedBytes[1:], s.Bytes())
|
||||||
|
sb = paddedBytes
|
||||||
|
} else {
|
||||||
|
sb = s.Bytes()
|
||||||
|
}
|
||||||
|
|
||||||
// total length of returned signature is 1 byte for each magic and
|
// total length of returned signature is 1 byte for each magic and
|
||||||
// length (6 total), plus lengths of r and s
|
// length (6 total), plus lengths of r and s
|
||||||
length := 6 + len(r.Bytes()) + len(s.Bytes())
|
length := 6 + len(rb) + len(sb)
|
||||||
b := make([]byte, length, length)
|
b := make([]byte, length, length)
|
||||||
|
|
||||||
b[0] = 0x30
|
b[0] = 0x30
|
||||||
b[1] = byte(length - 2)
|
b[1] = byte(length - 2)
|
||||||
b[2] = 0x02
|
b[2] = 0x02
|
||||||
b[3] = byte(len(r.Bytes()))
|
b[3] = byte(len(rb))
|
||||||
offset := copy(b[4:], r.Bytes()) + 4
|
offset := copy(b[4:], rb) + 4
|
||||||
b[offset] = 0x02
|
b[offset] = 0x02
|
||||||
b[offset+1] = byte(len(s.Bytes()))
|
b[offset+1] = byte(len(sb))
|
||||||
copy(b[offset+2:], s.Bytes())
|
copy(b[offset+2:], sb)
|
||||||
return b
|
return b
|
||||||
}
|
}
|
||||||
|
|
||||||
|
|
189
script_test.go
189
script_test.go
|
@ -20,6 +20,7 @@ type txTest struct {
|
||||||
pkScript []byte // output script of previous tx
|
pkScript []byte // output script of previous tx
|
||||||
idx int // tx idx to be run.
|
idx int // tx idx to be run.
|
||||||
bip16 bool // is bip16 active?
|
bip16 bool // is bip16 active?
|
||||||
|
canonicalSigs bool // should signatures be validated as canonical?
|
||||||
parseErr error // failure of NewScript
|
parseErr error // failure of NewScript
|
||||||
err error // Failure of Executre
|
err error // Failure of Executre
|
||||||
shouldFail bool // Execute should fail with nonspecified error.
|
shouldFail bool // Execute should fail with nonspecified error.
|
||||||
|
@ -566,6 +567,178 @@ var txTests = []txTest{
|
||||||
SigOps: 1,
|
SigOps: 1,
|
||||||
},
|
},
|
||||||
},
|
},
|
||||||
|
txTest{
|
||||||
|
name: "Non-canonical signature: R value negative",
|
||||||
|
tx: &btcwire.MsgTx{
|
||||||
|
Version: 1,
|
||||||
|
TxIn: []*btcwire.TxIn{
|
||||||
|
&btcwire.TxIn{
|
||||||
|
PreviousOutpoint: btcwire.OutPoint{
|
||||||
|
Hash: btcwire.ShaHash([32]byte{
|
||||||
|
0xfe, 0x15, 0x62, 0xc4,
|
||||||
|
0x8b, 0x3a, 0xa6, 0x37,
|
||||||
|
0x3f, 0x42, 0xe9, 0x61,
|
||||||
|
0x51, 0x89, 0xcf, 0x73,
|
||||||
|
0x32, 0xd7, 0x33, 0x5c,
|
||||||
|
0xbe, 0xa7, 0x80, 0xbe,
|
||||||
|
0x69, 0x6a, 0xc6, 0xc6,
|
||||||
|
0x50, 0xfd, 0xda, 0x4a,
|
||||||
|
}),
|
||||||
|
Index: 1,
|
||||||
|
},
|
||||||
|
SignatureScript: []byte{
|
||||||
|
btcscript.OP_DATA_71,
|
||||||
|
0x30, 0x44, 0x02, 0x20, 0xa0,
|
||||||
|
0x42, 0xde, 0xe5, 0x52, 0x6b,
|
||||||
|
0xf2, 0x29, 0x4d, 0x3f, 0x3e,
|
||||||
|
0xb9, 0x5a, 0xa7, 0x73, 0x19,
|
||||||
|
0xd3, 0xff, 0x56, 0x7b, 0xcf,
|
||||||
|
0x36, 0x46, 0x07, 0x0c, 0x81,
|
||||||
|
0x12, 0x33, 0x01, 0xca, 0xce,
|
||||||
|
0xa9, 0x02, 0x20, 0xea, 0x48,
|
||||||
|
0xae, 0x58, 0xf5, 0x54, 0x10,
|
||||||
|
0x96, 0x3f, 0xa7, 0x03, 0xdb,
|
||||||
|
0x56, 0xf0, 0xba, 0xb2, 0x70,
|
||||||
|
0xb1, 0x08, 0x22, 0xc5, 0x1c,
|
||||||
|
0x68, 0x02, 0x6a, 0x97, 0x5c,
|
||||||
|
0x7d, 0xae, 0x11, 0x2e, 0x4f,
|
||||||
|
0x01,
|
||||||
|
btcscript.OP_DATA_65,
|
||||||
|
0x04, 0x49, 0x45, 0x33, 0x18,
|
||||||
|
0xbd, 0x5e, 0xcf, 0xea, 0x5f,
|
||||||
|
0x86, 0x32, 0x8c, 0x6d, 0x8e,
|
||||||
|
0xd4, 0x12, 0xb4, 0xde, 0x2c,
|
||||||
|
0xab, 0xd7, 0xb8, 0x56, 0x51,
|
||||||
|
0x2f, 0x8c, 0xb7, 0xfd, 0x25,
|
||||||
|
0xf6, 0x03, 0xb0, 0x55, 0xc5,
|
||||||
|
0xdf, 0xe6, 0x22, 0x4b, 0xc4,
|
||||||
|
0xfd, 0xbb, 0x6a, 0x7a, 0xa0,
|
||||||
|
0x58, 0xd7, 0x5d, 0xad, 0x92,
|
||||||
|
0x99, 0x45, 0x4f, 0x62, 0x1a,
|
||||||
|
0x95, 0xb4, 0xb0, 0x21, 0x0e,
|
||||||
|
0xc4, 0x09, 0x2b, 0xe5, 0x27,
|
||||||
|
},
|
||||||
|
Sequence: 4294967295,
|
||||||
|
},
|
||||||
|
&btcwire.TxIn{
|
||||||
|
PreviousOutpoint: btcwire.OutPoint{
|
||||||
|
Hash: btcwire.ShaHash([32]byte{
|
||||||
|
0x2a, 0xc7, 0xee, 0xf8,
|
||||||
|
0xa9, 0x62, 0x2d, 0xda,
|
||||||
|
0xec, 0x18, 0x3b, 0xba,
|
||||||
|
0xa9, 0x92, 0xb0, 0x7a,
|
||||||
|
0x70, 0x3b, 0x48, 0x86,
|
||||||
|
0x27, 0x9c, 0x46, 0xac,
|
||||||
|
0x25, 0xeb, 0x91, 0xec,
|
||||||
|
0x4c, 0x86, 0xd2, 0x9c,
|
||||||
|
}),
|
||||||
|
Index: 1,
|
||||||
|
},
|
||||||
|
SignatureScript: []byte{
|
||||||
|
btcscript.OP_DATA_71,
|
||||||
|
0x30, 0x44, 0x02, 0x20, 0xc3,
|
||||||
|
0x02, 0x3b, 0xed, 0x85, 0x0d,
|
||||||
|
0x94, 0x27, 0x8e, 0x06, 0xd2,
|
||||||
|
0x37, 0x92, 0x21, 0x55, 0x28,
|
||||||
|
0xdd, 0xdb, 0x63, 0xa4, 0xb6,
|
||||||
|
0x88, 0x33, 0x92, 0x06, 0xdd,
|
||||||
|
0xf9, 0xee, 0x72, 0x97, 0xa3,
|
||||||
|
0x08, 0x02, 0x20, 0x25, 0x00,
|
||||||
|
0x42, 0x8b, 0x26, 0x36, 0x45,
|
||||||
|
0x54, 0xcb, 0x11, 0xd3, 0x3e,
|
||||||
|
0x85, 0x35, 0x23, 0x49, 0x65,
|
||||||
|
0x82, 0x8e, 0x33, 0x6e, 0x1a,
|
||||||
|
0x4a, 0x72, 0x73, 0xeb, 0x5b,
|
||||||
|
0x8d, 0x1d, 0xd7, 0x02, 0xcc,
|
||||||
|
0x01,
|
||||||
|
btcscript.OP_DATA_65,
|
||||||
|
0x04, 0x49, 0x5c, 0x8f, 0x66,
|
||||||
|
0x90, 0x0d, 0xb7, 0x62, 0x69,
|
||||||
|
0x0b, 0x54, 0x49, 0xa1, 0xf4,
|
||||||
|
0xe7, 0xc2, 0xed, 0x1f, 0x4b,
|
||||||
|
0x34, 0x70, 0xfd, 0x42, 0x79,
|
||||||
|
0x68, 0xa1, 0x31, 0x76, 0x0c,
|
||||||
|
0x25, 0xf9, 0x12, 0x63, 0xad,
|
||||||
|
0x51, 0x73, 0x8e, 0x19, 0xb6,
|
||||||
|
0x07, 0xf5, 0xcf, 0x5f, 0x94,
|
||||||
|
0x27, 0x4a, 0x8b, 0xbc, 0x74,
|
||||||
|
0xba, 0x4b, 0x56, 0x0c, 0xe0,
|
||||||
|
0xb3, 0x08, 0x8f, 0x7f, 0x5c,
|
||||||
|
0x5f, 0xcf, 0xd6, 0xa0, 0x4b,
|
||||||
|
},
|
||||||
|
Sequence: 4294967295,
|
||||||
|
},
|
||||||
|
},
|
||||||
|
TxOut: []*btcwire.TxOut{
|
||||||
|
&btcwire.TxOut{
|
||||||
|
Value: 630320000,
|
||||||
|
PkScript: []byte{
|
||||||
|
btcscript.OP_DUP,
|
||||||
|
btcscript.OP_HASH160,
|
||||||
|
btcscript.OP_DATA_20,
|
||||||
|
0x43, 0xdc, 0x32, 0x1b, 0x66,
|
||||||
|
0x00, 0x51, 0x1f, 0xe0, 0xa9,
|
||||||
|
0x6a, 0x97, 0xc2, 0x59, 0x3a,
|
||||||
|
0x90, 0x54, 0x29, 0x74, 0xd6,
|
||||||
|
btcscript.OP_EQUALVERIFY,
|
||||||
|
btcscript.OP_CHECKSIG,
|
||||||
|
},
|
||||||
|
},
|
||||||
|
&btcwire.TxOut{
|
||||||
|
Value: 100000181,
|
||||||
|
PkScript: []byte{
|
||||||
|
btcscript.OP_DUP,
|
||||||
|
btcscript.OP_HASH160,
|
||||||
|
btcscript.OP_DATA_20,
|
||||||
|
0xa4, 0x05, 0xea, 0x18, 0x09,
|
||||||
|
0x14, 0xa9, 0x11, 0xd0, 0xb8,
|
||||||
|
0x07, 0x99, 0x19, 0x2b, 0x0b,
|
||||||
|
0x84, 0xae, 0x80, 0x1e, 0xbd,
|
||||||
|
btcscript.OP_EQUALVERIFY,
|
||||||
|
btcscript.OP_CHECKSIG,
|
||||||
|
},
|
||||||
|
},
|
||||||
|
&btcwire.TxOut{
|
||||||
|
Value: 596516343,
|
||||||
|
PkScript: []byte{
|
||||||
|
btcscript.OP_DUP,
|
||||||
|
btcscript.OP_HASH160,
|
||||||
|
btcscript.OP_DATA_20,
|
||||||
|
0x24, 0x56, 0x76, 0x45, 0x4f,
|
||||||
|
0x6f, 0xff, 0x28, 0x88, 0x39,
|
||||||
|
0x47, 0xea, 0x70, 0x23, 0x86,
|
||||||
|
0x9b, 0x8a, 0x71, 0xa3, 0x05,
|
||||||
|
btcscript.OP_EQUALVERIFY,
|
||||||
|
btcscript.OP_CHECKSIG,
|
||||||
|
},
|
||||||
|
},
|
||||||
|
},
|
||||||
|
LockTime: 0,
|
||||||
|
},
|
||||||
|
// Test input 0
|
||||||
|
pkScript: []byte{
|
||||||
|
btcscript.OP_DUP,
|
||||||
|
btcscript.OP_HASH160,
|
||||||
|
btcscript.OP_DATA_20,
|
||||||
|
0xfd, 0xf6, 0xea, 0xe7, 0x10,
|
||||||
|
0xa0, 0xc4, 0x49, 0x7a, 0x8d,
|
||||||
|
0x0f, 0xd2, 0x9a, 0xf6, 0x6b,
|
||||||
|
0xac, 0x94, 0xaf, 0x6c, 0x98,
|
||||||
|
btcscript.OP_EQUALVERIFY,
|
||||||
|
btcscript.OP_CHECKSIG,
|
||||||
|
},
|
||||||
|
idx: 0,
|
||||||
|
canonicalSigs: true,
|
||||||
|
shouldFail: true,
|
||||||
|
nSigOps: 1,
|
||||||
|
scriptInfo: btcscript.ScriptInfo{
|
||||||
|
PkScriptClass: btcscript.PubKeyHashTy,
|
||||||
|
NumInputs: 2,
|
||||||
|
ExpectedInputs: 2,
|
||||||
|
SigOps: 1,
|
||||||
|
},
|
||||||
|
},
|
||||||
|
|
||||||
// tx 51bf528ecf3c161e7c021224197dbe84f9a8564212f6207baa014c01a1668e1e
|
// tx 51bf528ecf3c161e7c021224197dbe84f9a8564212f6207baa014c01a1668e1e
|
||||||
// first instance of an AnyoneCanPay signature in the blockchain
|
// first instance of an AnyoneCanPay signature in the blockchain
|
||||||
txTest{
|
txTest{
|
||||||
|
@ -1265,9 +1438,16 @@ var txTests = []txTest{
|
||||||
// nothing in the blockchain that we have yet seen uses them, making it hard
|
// nothing in the blockchain that we have yet seen uses them, making it hard
|
||||||
// to confirm we implemented the spec correctly.
|
// to confirm we implemented the spec correctly.
|
||||||
func testTx(t *testing.T, test txTest) {
|
func testTx(t *testing.T, test txTest) {
|
||||||
|
var flags btcscript.ScriptFlags
|
||||||
|
if test.bip16 {
|
||||||
|
flags |= btcscript.ScriptBip16
|
||||||
|
}
|
||||||
|
if test.canonicalSigs {
|
||||||
|
flags |= btcscript.ScriptCanonicalSignatures
|
||||||
|
}
|
||||||
engine, err := btcscript.NewScript(
|
engine, err := btcscript.NewScript(
|
||||||
test.tx.TxIn[test.idx].SignatureScript, test.pkScript,
|
test.tx.TxIn[test.idx].SignatureScript, test.pkScript,
|
||||||
test.idx, test.tx, test.bip16)
|
test.idx, test.tx, flags)
|
||||||
if err != nil {
|
if err != nil {
|
||||||
if err != test.parseErr {
|
if err != test.parseErr {
|
||||||
t.Errorf("Failed to parse %s: got \"%v\" expected "+
|
t.Errorf("Failed to parse %s: got \"%v\" expected "+
|
||||||
|
@ -1983,7 +2163,7 @@ func TestBadPC(t *testing.T) {
|
||||||
|
|
||||||
for _, test := range pcTests {
|
for _, test := range pcTests {
|
||||||
engine, err := btcscript.NewScript(tx.TxIn[0].SignatureScript,
|
engine, err := btcscript.NewScript(tx.TxIn[0].SignatureScript,
|
||||||
pkScript, 0, tx, false)
|
pkScript, 0, tx, 0)
|
||||||
if err != nil {
|
if err != nil {
|
||||||
t.Errorf("Failed to create script: %v", err)
|
t.Errorf("Failed to create script: %v", err)
|
||||||
}
|
}
|
||||||
|
@ -2053,7 +2233,7 @@ func TestCheckErrorCondition(t *testing.T) {
|
||||||
}
|
}
|
||||||
|
|
||||||
engine, err := btcscript.NewScript(tx.TxIn[0].SignatureScript, pkScript,
|
engine, err := btcscript.NewScript(tx.TxIn[0].SignatureScript, pkScript,
|
||||||
0, tx, false)
|
0, tx, 0)
|
||||||
if err != nil {
|
if err != nil {
|
||||||
t.Errorf("failed to create script: %v", err)
|
t.Errorf("failed to create script: %v", err)
|
||||||
}
|
}
|
||||||
|
@ -2460,10 +2640,11 @@ nexttest:
|
||||||
}
|
}
|
||||||
|
|
||||||
// Validate tx input scripts
|
// Validate tx input scripts
|
||||||
|
scriptFlags := btcscript.ScriptBip16 | btcscript.ScriptCanonicalSignatures
|
||||||
for j, txin := range tx.TxIn {
|
for j, txin := range tx.TxIn {
|
||||||
engine, err := btcscript.NewScript(txin.SignatureScript,
|
engine, err := btcscript.NewScript(txin.SignatureScript,
|
||||||
SigScriptTests[i].inputs[j].txout.PkScript,
|
SigScriptTests[i].inputs[j].txout.PkScript,
|
||||||
j, tx, true)
|
j, tx, scriptFlags)
|
||||||
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)
|
||||||
|
|
|
@ -4,17 +4,17 @@ github.com/conformal/btcscript/script.go Script.Step 100.00% (37/37)
|
||||||
github.com/conformal/btcscript/script.go parseScriptTemplate 100.00% (30/30)
|
github.com/conformal/btcscript/script.go parseScriptTemplate 100.00% (30/30)
|
||||||
github.com/conformal/btcscript/script.go CalcScriptInfo 100.00% (25/25)
|
github.com/conformal/btcscript/script.go CalcScriptInfo 100.00% (25/25)
|
||||||
github.com/conformal/btcscript/opcode.go parsedOpcode.bytes 100.00% (23/23)
|
github.com/conformal/btcscript/opcode.go parsedOpcode.bytes 100.00% (23/23)
|
||||||
|
github.com/conformal/btcscript/script.go sigDER 100.00% (22/22)
|
||||||
|
github.com/conformal/btcscript/script.go NewScript 100.00% (21/21)
|
||||||
github.com/conformal/btcscript/stack.go asInt 100.00% (21/21)
|
github.com/conformal/btcscript/stack.go asInt 100.00% (21/21)
|
||||||
github.com/conformal/btcscript/script.go NewScript 100.00% (18/18)
|
|
||||||
github.com/conformal/btcscript/script.go signatureScriptCustomReader 100.00% (15/15)
|
github.com/conformal/btcscript/script.go signatureScriptCustomReader 100.00% (15/15)
|
||||||
github.com/conformal/btcscript/stack.go fromInt 100.00% (14/14)
|
github.com/conformal/btcscript/stack.go fromInt 100.00% (14/14)
|
||||||
github.com/conformal/btcscript/stack.go Stack.nipN 100.00% (14/14)
|
github.com/conformal/btcscript/stack.go Stack.nipN 100.00% (14/14)
|
||||||
|
github.com/conformal/btcscript/script.go GetPreciseSigOpCount 100.00% (13/13)
|
||||||
github.com/conformal/btcscript/opcode.go opcodeWithin 100.00% (13/13)
|
github.com/conformal/btcscript/opcode.go opcodeWithin 100.00% (13/13)
|
||||||
github.com/conformal/btcscript/script.go isMultiSig 100.00% (13/13)
|
github.com/conformal/btcscript/script.go isMultiSig 100.00% (13/13)
|
||||||
github.com/conformal/btcscript/script.go GetPreciseSigOpCount 100.00% (13/13)
|
|
||||||
github.com/conformal/btcscript/opcode.go parsedOpcode.print 100.00% (12/12)
|
github.com/conformal/btcscript/opcode.go parsedOpcode.print 100.00% (12/12)
|
||||||
github.com/conformal/btcscript/opcode.go opcodeNotIf 100.00% (11/11)
|
github.com/conformal/btcscript/opcode.go opcodeNotIf 100.00% (11/11)
|
||||||
github.com/conformal/btcscript/script.go sigDER 100.00% (11/11)
|
|
||||||
github.com/conformal/btcscript/opcode.go opcodeIf 100.00% (11/11)
|
github.com/conformal/btcscript/opcode.go opcodeIf 100.00% (11/11)
|
||||||
github.com/conformal/btcscript/opcode.go opcodeMax 100.00% (10/10)
|
github.com/conformal/btcscript/opcode.go opcodeMax 100.00% (10/10)
|
||||||
github.com/conformal/btcscript/script.go getSigOpCount 100.00% (10/10)
|
github.com/conformal/btcscript/script.go getSigOpCount 100.00% (10/10)
|
||||||
|
@ -140,8 +140,8 @@ github.com/conformal/btcscript/script.go Script.SetStack 100.00% (1/1)
|
||||||
github.com/conformal/btcscript/stack.go Stack.PushByteArray 100.00% (1/1)
|
github.com/conformal/btcscript/stack.go Stack.PushByteArray 100.00% (1/1)
|
||||||
github.com/conformal/btcscript/stack.go Stack.PushInt 100.00% (1/1)
|
github.com/conformal/btcscript/stack.go Stack.PushInt 100.00% (1/1)
|
||||||
github.com/conformal/btcscript/opcode.go opcodeRot 100.00% (1/1)
|
github.com/conformal/btcscript/opcode.go opcodeRot 100.00% (1/1)
|
||||||
github.com/conformal/btcscript/opcode.go opcodeCheckMultiSig 98.21% (55/56)
|
github.com/conformal/btcscript/opcode.go opcodeCheckMultiSig 98.28% (57/58)
|
||||||
github.com/conformal/btcscript/opcode.go opcodeCheckSig 96.15% (25/26)
|
github.com/conformal/btcscript/opcode.go opcodeCheckSig 96.55% (28/29)
|
||||||
github.com/conformal/btcscript/script.go calcScriptHash 82.05% (32/39)
|
github.com/conformal/btcscript/script.go calcScriptHash 82.05% (32/39)
|
||||||
github.com/conformal/btcscript/script.go Script.CheckErrorCondition 78.57% (11/14)
|
github.com/conformal/btcscript/script.go Script.CheckErrorCondition 78.57% (11/14)
|
||||||
github.com/conformal/btcscript/opcode.go opcodeCheckSigVerify 75.00% (3/4)
|
github.com/conformal/btcscript/opcode.go opcodeCheckSigVerify 75.00% (3/4)
|
||||||
|
@ -149,5 +149,5 @@ github.com/conformal/btcscript/script.go Script.Execute 44.44% (8/18)
|
||||||
github.com/conformal/btcscript/log.go SetLogWriter 0.00% (0/7)
|
github.com/conformal/btcscript/log.go SetLogWriter 0.00% (0/7)
|
||||||
github.com/conformal/btcscript/script.go IsPushOnlyScript 0.00% (0/4)
|
github.com/conformal/btcscript/script.go IsPushOnlyScript 0.00% (0/4)
|
||||||
github.com/conformal/btcscript/log.go logClosure.String 0.00% (0/1)
|
github.com/conformal/btcscript/log.go logClosure.String 0.00% (0/1)
|
||||||
github.com/conformal/btcscript --------------------------- 96.52% (970/1005)
|
github.com/conformal/btcscript --------------------------- 96.58% (989/1024)
|
||||||
|
|
||||||
|
|
Loading…
Reference in a new issue