Add CalcScriptInfo entrypoint to return info about scriptpairs.

Specficially the class of the pkScript, the  expected numbers of
arguments and the number of sigops.
This commit is contained in:
Owain G. Ainsworth 2013-10-09 00:13:52 +01:00
parent 003a41f66f
commit 40c75b27ac
4 changed files with 442 additions and 90 deletions

101
script.go
View file

@ -109,6 +109,10 @@ var StackErrInvalidAddrOffset = errors.New("internal error: invalid offset found
// a function. // a function.
var StackErrInvalidIndex = errors.New("Invalid script index") var StackErrInvalidIndex = errors.New("Invalid script index")
// StackErrNonPushOnly is returned when ScriptInfo is called with a pkScript
// that peforms operations other that pushing data to the stack.
var StackErrNonPushOnly = errors.New("SigScript is non pushonly")
// Bip16Activation is the timestamp where BIP0016 is valid to use in the // Bip16Activation is the timestamp where BIP0016 is valid to use in the
// blockchain. To be used to determine if BIP0016 should be called for or not. // blockchain. To be used to determine if BIP0016 should be called for or not.
// This timestamp corresponds to Sun Apr 1 00:00:00 UTC 2012. // This timestamp corresponds to Sun Apr 1 00:00:00 UTC 2012.
@ -975,3 +979,100 @@ func sigDER(r, s *big.Int) []byte {
copy(b[offset+2:], s.Bytes()) copy(b[offset+2:], s.Bytes())
return b return b
} }
// expectedInputs returns the number of arguments required by a script.
// If the script is of unnown type such that the number can not be determined
// then -1 is returned. We are an interanl function and thus assume that class
// is the real class of pops (and we can thus assume things that were
// determined while finding out the type).
func expectedInputs(pops []parsedOpcode, class ScriptClass) int {
// count needed inputs.
switch class {
case PubKeyTy:
return 1
case PubKeyHashTy:
return 2
case ScriptHashTy:
// Not including script, handled below.
return 1
case MultiSigTy:
// Standard multisig has a push a small number for the number
// of sigs and number of keys.
// Check the first push instrution to see how many arguments are
// expected. typoeOfScript already checked this so that we know
// it'll be one of OP_1 - OP_16.
return int(pops[0].opcode.value - (OP_1 - 1))
default:
return -1
}
}
type ScriptInfo struct {
// The class of the sigscript, equivalent to calling GetScriptClass
// on the sigScript.
PkScriptClass ScriptClass
// the number of inputs provided by the pkScript
NumInputs int
// the number of outputs required by sigScript and any
// pay-to-script-hash scripts. The number will be -1 if unknown.
ExpectedInputs int
// The nubmer of signature operations in the scriptpair.
SigOps int
}
// CalcScriptInfo returns a structure providing data about the scriptpair that
// are provided as arguments. It will error if the pair is in someway invalid
// such taht they can not be analysed, i.e. if they do not parse or the
// pkScript is not a push-only script
func CalcScriptInfo(sigscript, pkscript []byte, bip16 bool) (*ScriptInfo, error) {
si := new(ScriptInfo)
// parse both scripts.
sigPops, err := parseScript(sigscript)
if err != nil {
return nil, err
}
pkPops, err := parseScript(pkscript)
if err != nil {
return nil, err
}
// push only sigScript makes little sense.
si.PkScriptClass = typeOfScript(pkPops)
// Can't have a pkScript that doesn't just push data.
if !isPushOnly(sigPops) {
return nil, StackErrNonPushOnly
}
si.ExpectedInputs = expectedInputs(pkPops, si.PkScriptClass)
// all entries push to stack (or are OP_RESERVED and exec will fail).
si.NumInputs = len(sigPops)
if si.PkScriptClass == ScriptHashTy && bip16 {
// grab the last push instruction in the script and pull out the
// data.
script := sigPops[len(sigPops)-1].data
// check for existance and error else.
shPops, err := parseScript(script)
if err != nil {
return nil, err
}
shClass := typeOfScript(shPops)
shInputs := expectedInputs(shPops, shClass)
if shInputs == -1 {
// We have no fucking clue, then.
si.ExpectedInputs = -1
} else {
si.ExpectedInputs += shInputs
}
si.SigOps = getSigOpCount(shPops, true)
} else {
si.SigOps = getSigOpCount(pkPops, true)
}
return si, nil
}

View file

@ -15,15 +15,17 @@ import (
) )
type txTest struct { type txTest struct {
name string name string
tx *btcwire.MsgTx tx *btcwire.MsgTx
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?
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.
nSigOps int // result of GetPreciseSigOpsCount nSigOps int // result of GetPreciseSigOpsCount
scriptInfo btcscript.ScriptInfo // result of ScriptInfo
scriptInfoErr error // error return of ScriptInfo
} }
var txTests = []txTest{ var txTests = []txTest{
@ -127,6 +129,12 @@ var txTests = []txTest{
}, },
idx: 0, idx: 0,
nSigOps: 1, nSigOps: 1,
scriptInfo: btcscript.ScriptInfo{
PkScriptClass: btcscript.PubKeyTy,
NumInputs: 1,
ExpectedInputs: 1,
SigOps: 1,
},
}, },
// Previous test with the value of one output changed. // Previous test with the value of one output changed.
txTest{ txTest{
@ -228,6 +236,12 @@ var txTests = []txTest{
idx: 0, idx: 0,
err: btcscript.StackErrScriptFailed, err: btcscript.StackErrScriptFailed,
nSigOps: 1, nSigOps: 1,
scriptInfo: btcscript.ScriptInfo{
PkScriptClass: btcscript.PubKeyTy,
NumInputs: 1,
ExpectedInputs: 1,
SigOps: 1,
},
}, },
txTest{ txTest{
name: "CheckSig invalid signature", name: "CheckSig invalid signature",
@ -330,6 +344,12 @@ var txTests = []txTest{
idx: 0, idx: 0,
shouldFail: true, shouldFail: true,
nSigOps: 1, nSigOps: 1,
scriptInfo: btcscript.ScriptInfo{
PkScriptClass: btcscript.PubKeyTy,
NumInputs: 1,
ExpectedInputs: 1,
SigOps: 1,
},
}, },
txTest{ txTest{
name: "CheckSig invalid pubkey", name: "CheckSig invalid pubkey",
@ -431,6 +451,12 @@ var txTests = []txTest{
idx: 0, idx: 0,
shouldFail: true, shouldFail: true,
nSigOps: 1, nSigOps: 1,
scriptInfo: btcscript.ScriptInfo{
PkScriptClass: btcscript.PubKeyTy,
NumInputs: 1,
ExpectedInputs: 1,
SigOps: 1,
},
}, },
// tx 599e47a8114fe098103663029548811d2651991b62397e057f0c863c2bc9f9ea // tx 599e47a8114fe098103663029548811d2651991b62397e057f0c863c2bc9f9ea
// uses checksig with SigHashNone. // uses checksig with SigHashNone.
@ -533,6 +559,12 @@ var txTests = []txTest{
idx: 0, idx: 0,
bip16: true, // after threshold bip16: true, // after threshold
nSigOps: 1, 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
@ -657,6 +689,12 @@ var txTests = []txTest{
idx: 0, idx: 0,
bip16: true, // after threshold bip16: true, // after threshold
nSigOps: 1, nSigOps: 1,
scriptInfo: btcscript.ScriptInfo{
PkScriptClass: btcscript.PubKeyHashTy,
NumInputs: 2,
ExpectedInputs: 2,
SigOps: 1,
},
}, },
// tx 6d36bc17e947ce00bb6f12f8e7a56a1585c5a36188ffa2b05e10b4743273a74b // tx 6d36bc17e947ce00bb6f12f8e7a56a1585c5a36188ffa2b05e10b4743273a74b
// Uses OP_CODESEPARATOR and OP_CHECKMULTISIG // Uses OP_CODESEPARATOR and OP_CHECKMULTISIG
@ -777,9 +815,10 @@ var txTests = []txTest{
0x4f, 0x13, 0x4f, 0x13,
btcscript.OP_NOP2, btcscript.OP_DROP, btcscript.OP_NOP2, btcscript.OP_DROP,
}, },
idx: 1, idx: 1,
bip16: false, bip16: false,
nSigOps: 0, // multisig is in the pkScript! nSigOps: 0, // multisig is in the pkScript!
scriptInfoErr: btcscript.StackErrNonPushOnly,
}, },
// same as previous but with one byte changed to make signature fail // same as previous but with one byte changed to make signature fail
txTest{ txTest{
@ -899,10 +938,11 @@ var txTests = []txTest{
0x4f, 0x13, 0x4f, 0x13,
btcscript.OP_NOP2, btcscript.OP_DROP, btcscript.OP_NOP2, btcscript.OP_DROP,
}, },
idx: 1, idx: 1,
bip16: false, bip16: false,
err: btcscript.StackErrScriptFailed, err: btcscript.StackErrScriptFailed,
nSigOps: 0, // multisig is in the pkScript! nSigOps: 0, // multisig is in the pkScript!
scriptInfoErr: btcscript.StackErrNonPushOnly,
}, },
// tx e5779b9e78f9650debc2893fd9636d827b26b4ddfa6a8172fe8708c924f5c39d // tx e5779b9e78f9650debc2893fd9636d827b26b4ddfa6a8172fe8708c924f5c39d
// First P2SH transaction in the blockchain // First P2SH transaction in the blockchain
@ -962,6 +1002,12 @@ var txTests = []txTest{
idx: 0, idx: 0,
bip16: true, bip16: true,
nSigOps: 0, // no signature ops in the pushed script. nSigOps: 0, // no signature ops in the pushed script.
scriptInfo: btcscript.ScriptInfo{
PkScriptClass: btcscript.ScriptHashTy,
NumInputs: 1,
ExpectedInputs: -1, // p2sh script is non standard
SigOps: 0,
},
}, },
// next few tests are modified versions of previous to hit p2sh error // next few tests are modified versions of previous to hit p2sh error
// cases. // cases.
@ -1023,6 +1069,12 @@ var txTests = []txTest{
err: btcscript.StackErrScriptFailed, err: btcscript.StackErrScriptFailed,
bip16: true, bip16: true,
nSigOps: 0, // no signature ops in the pushed script. nSigOps: 0, // no signature ops in the pushed script.
scriptInfo: btcscript.ScriptInfo{
PkScriptClass: btcscript.ScriptHashTy,
NumInputs: 1,
ExpectedInputs: -1, // p2sh script is non standard
SigOps: 0,
},
}, },
txTest{ txTest{
// sigscript changed so that pkscript hash will not match. // sigscript changed so that pkscript hash will not match.
@ -1078,9 +1130,10 @@ var txTests = []txTest{
0xba, 0x67, 0xba, 0x67,
btcscript.OP_EQUAL, btcscript.OP_EQUAL,
}, },
idx: 0, idx: 0,
err: btcscript.StackErrShortScript, err: btcscript.StackErrShortScript,
bip16: true, bip16: true,
scriptInfoErr: btcscript.StackErrShortScript,
}, },
txTest{ txTest{
// sigscript changed so to be non pushonly. // sigscript changed so to be non pushonly.
@ -1140,10 +1193,11 @@ var txTests = []txTest{
0xae, 0x88, 0xae, 0x88,
btcscript.OP_EQUAL, btcscript.OP_EQUAL,
}, },
idx: 0, idx: 0,
parseErr: btcscript.StackErrP2SHNonPushOnly, parseErr: btcscript.StackErrP2SHNonPushOnly,
bip16: true, bip16: true,
nSigOps: 0, // no signature ops in the pushed script. nSigOps: 0, // no signature ops in the pushed script.
scriptInfoErr: btcscript.StackErrNonPushOnly,
}, },
txTest{ txTest{
// sigscript changed so to be non pushonly. // sigscript changed so to be non pushonly.
@ -1195,6 +1249,12 @@ var txTests = []txTest{
idx: 0, idx: 0,
bip16: true, bip16: true,
nSigOps: 0, // no signature ops in the pushed script. nSigOps: 0, // no signature ops in the pushed script.
scriptInfo: btcscript.ScriptInfo{
PkScriptClass: btcscript.NonStandardTy,
NumInputs: 1,
ExpectedInputs: -1,
SigOps: 0,
},
}, },
} }
@ -1319,6 +1379,195 @@ func TestGetPreciseSignOps(t *testing.T) {
} }
} }
type scriptInfoTest struct {
name string
sigScript []byte
pkScript []byte
bip16 bool
scriptInfo btcscript.ScriptInfo
scriptInfoErr error
}
func TestScriptInfo(t *testing.T) {
for _, test := range txTests {
si, err := btcscript.CalcScriptInfo(
test.tx.TxIn[test.idx].SignatureScript,
test.pkScript, test.bip16)
if err != nil {
if err != test.scriptInfoErr {
t.Errorf("scriptinfo test \"%s\": got \"%v\""+
"expected \"%v\"", test.name, err,
test.scriptInfoErr)
}
continue
}
if test.scriptInfoErr != nil {
t.Errorf("%s: succeeded when expecting \"%v\"",
test.name, test.scriptInfoErr)
continue
}
if *si != test.scriptInfo {
t.Errorf("%s: scriptinfo doesn't match expected. "+
"got: \"%v\" expected \"%v\"", test.name,
*si, test.scriptInfo)
continue
}
}
extraTests := []scriptInfoTest{
{
// Invented scripts, the hashes do not match
name: "pkscript doesn't parse",
sigScript: []byte{btcscript.OP_TRUE,
btcscript.OP_DATA_1, 81,
btcscript.OP_DATA_8,
btcscript.OP_2DUP, btcscript.OP_EQUAL,
btcscript.OP_NOT, btcscript.OP_VERIFY,
btcscript.OP_ABS, btcscript.OP_SWAP,
btcscript.OP_ABS, btcscript.OP_EQUAL,
},
// truncated version of test below:
pkScript: []byte{btcscript.OP_HASH160,
btcscript.OP_DATA_20,
0xfe, 0x44, 0x10, 0x65, 0xb6, 0x53, 0x22, 0x31,
0xde, 0x2f, 0xac, 0x56, 0x31, 0x52, 0x20, 0x5e,
0xc4, 0xf5, 0x9c,
},
bip16: true,
scriptInfoErr: btcscript.StackErrShortScript,
},
{
name: "sigScript doesn't parse",
// Truncated version of p2sh script below.
sigScript: []byte{btcscript.OP_TRUE,
btcscript.OP_DATA_1, 81,
btcscript.OP_DATA_8,
btcscript.OP_2DUP, btcscript.OP_EQUAL,
btcscript.OP_NOT, btcscript.OP_VERIFY,
btcscript.OP_ABS, btcscript.OP_SWAP,
btcscript.OP_ABS,
},
pkScript: []byte{btcscript.OP_HASH160,
btcscript.OP_DATA_20,
0xfe, 0x44, 0x10, 0x65, 0xb6, 0x53, 0x22, 0x31,
0xde, 0x2f, 0xac, 0x56, 0x31, 0x52, 0x20, 0x5e,
0xc4, 0xf5, 0x9c, 0x74, btcscript.OP_EQUAL,
},
bip16: true,
scriptInfoErr: btcscript.StackErrShortScript,
},
{
// Invented scripts, the hashes do not match
name: "p2sh standard script",
sigScript: []byte{btcscript.OP_TRUE,
btcscript.OP_DATA_1, 81,
btcscript.OP_DATA_25,
btcscript.OP_DUP, btcscript.OP_HASH160,
btcscript.OP_DATA_20, 0x1, 0x2, 0x3, 0x4, 0x5,
0x6, 0x7, 0x8, 0x9, 0xa, 0xb, 0xc, 0xd, 0xe,
0xf, 0x10, 0x11, 0x12, 0x13, 0x14,
btcscript.OP_EQUALVERIFY, btcscript.OP_CHECKSIG,
},
pkScript: []byte{btcscript.OP_HASH160,
btcscript.OP_DATA_20,
0xfe, 0x44, 0x10, 0x65, 0xb6, 0x53, 0x22, 0x31,
0xde, 0x2f, 0xac, 0x56, 0x31, 0x52, 0x20, 0x5e,
0xc4, 0xf5, 0x9c, 0x74, btcscript.OP_EQUAL,
},
bip16: true,
scriptInfo: btcscript.ScriptInfo{
PkScriptClass: btcscript.ScriptHashTy,
NumInputs: 3,
ExpectedInputs: 3, // nonstandard p2sh.
SigOps: 1,
},
},
{
// from 567a53d1ce19ce3d07711885168484439965501536d0d0294c5d46d46c10e53b
// from the blockchain.
name: "p2sh nonstandard script",
sigScript: []byte{btcscript.OP_TRUE,
btcscript.OP_DATA_1, 81,
btcscript.OP_DATA_8,
btcscript.OP_2DUP, btcscript.OP_EQUAL,
btcscript.OP_NOT, btcscript.OP_VERIFY,
btcscript.OP_ABS, btcscript.OP_SWAP,
btcscript.OP_ABS, btcscript.OP_EQUAL,
},
pkScript: []byte{btcscript.OP_HASH160,
btcscript.OP_DATA_20,
0xfe, 0x44, 0x10, 0x65, 0xb6, 0x53, 0x22, 0x31,
0xde, 0x2f, 0xac, 0x56, 0x31, 0x52, 0x20, 0x5e,
0xc4, 0xf5, 0x9c, 0x74, btcscript.OP_EQUAL,
},
bip16: true,
scriptInfo: btcscript.ScriptInfo{
PkScriptClass: btcscript.ScriptHashTy,
NumInputs: 3,
ExpectedInputs: -1, // nonstandard p2sh.
SigOps: 0,
},
},
{
// Script is invented, numbers all fake.
name: "multisig script",
sigScript: []byte{btcscript.OP_TRUE,
btcscript.OP_TRUE, btcscript.OP_TRUE,
},
pkScript: []byte{
btcscript.OP_3, btcscript.OP_DATA_33,
0x1, 0x2, 0x3, 0x4, 0x5, 0x6, 0x7, 0x8, 0x9,
0xa, 0xb, 0xc, 0xd, 0xe, 0xf, 0x10, 0x11, 0x12,
0x13, 0x14, 0x15, 0x16, 0x17, 0x18, 0x19, 0x1a,
0x1b, 0x1c, 0x1d, 0x1e, 0x1f, 0x20, 0x21,
btcscript.OP_DATA_33,
0x1, 0x2, 0x3, 0x4, 0x5, 0x6, 0x7, 0x8, 0x9,
0xa, 0xb, 0xc, 0xd, 0xe, 0xf, 0x10, 0x11, 0x12,
0x13, 0x14, 0x15, 0x16, 0x17, 0x18, 0x19, 0x1a,
0x1b, 0x1c, 0x1d, 0x1e, 0x1f, 0x20, 0x21,
btcscript.OP_DATA_33,
0x1, 0x2, 0x3, 0x4, 0x5, 0x6, 0x7, 0x8, 0x9,
0xa, 0xb, 0xc, 0xd, 0xe, 0xf, 0x10, 0x11, 0x12,
0x13, 0x14, 0x15, 0x16, 0x17, 0x18, 0x19, 0x1a,
0x1b, 0x1c, 0x1d, 0x1e, 0x1f, 0x20, 0x21,
btcscript.OP_3, btcscript.OP_CHECK_MULTISIG,
},
bip16: true,
scriptInfo: btcscript.ScriptInfo{
PkScriptClass: btcscript.MultiSigTy,
NumInputs: 3,
ExpectedInputs: 3,
SigOps: 3,
},
},
}
for _, test := range extraTests {
si, err := btcscript.CalcScriptInfo(test.sigScript,
test.pkScript, test.bip16)
if err != nil {
if err != test.scriptInfoErr {
t.Errorf("scriptinfo test \"%s\": got \"%v\""+
"expected \"%v\"", test.name, err,
test.scriptInfoErr)
}
continue
}
if test.scriptInfoErr != nil {
t.Errorf("%s: succeeded when expecting \"%v\"",
test.name, test.scriptInfoErr)
continue
}
if *si != test.scriptInfo {
t.Errorf("%s: scriptinfo doesn't match expected. "+
"got: \"%v\" expected \"%v\"", test.name,
*si, test.scriptInfo)
continue
}
}
}
type removeOpcodeTest struct { type removeOpcodeTest struct {
name string name string
before []byte before []byte

View file

@ -7,8 +7,8 @@ package btcscript_test
import ( import (
"bytes" "bytes"
"errors" "errors"
"github.com/conformal/btcscript"
"fmt" "fmt"
"github.com/conformal/btcscript"
"math/big" "math/big"
"testing" "testing"
) )
@ -254,7 +254,7 @@ var stackTests = []stackTest{
}, },
{ {
"popInt -1 leading 0", "popInt -1 leading 0",
[][]byte{{0x01,0x00, 0x00, 0x80}}, [][]byte{{0x01, 0x00, 0x00, 0x80}},
func(stack *btcscript.Stack) error { func(stack *btcscript.Stack) error {
v, err := stack.PopInt() v, err := stack.PopInt()
if err != nil { if err != nil {
@ -290,7 +290,7 @@ var stackTests = []stackTest{
// Confirm that the asInt code doesn't modify the base data. // Confirm that the asInt code doesn't modify the base data.
{ {
"peekint nomodify -1", "peekint nomodify -1",
[][]byte{{0x01,0x00, 0x00, 0x80}}, [][]byte{{0x01, 0x00, 0x00, 0x80}},
func(stack *btcscript.Stack) error { func(stack *btcscript.Stack) error {
v, err := stack.PeekInt(0) v, err := stack.PeekInt(0)
if err != nil { if err != nil {
@ -303,7 +303,7 @@ var stackTests = []stackTest{
return nil return nil
}, },
nil, nil,
[][]byte{{0x01,0x00, 0x00, 0x80}}, [][]byte{{0x01, 0x00, 0x00, 0x80}},
}, },
{ {
"PushInt 0", "PushInt 0",

View file

@ -2,70 +2,72 @@
github.com/conformal/btcscript/address.go scriptToAddrHashTemplate 100.00% (45/45) github.com/conformal/btcscript/address.go scriptToAddrHashTemplate 100.00% (45/45)
github.com/conformal/btcscript/script.go Script.Step 100.00% (37/37) 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/opcode.go parsedOpcode.bytes 100.00% (23/23) github.com/conformal/btcscript/opcode.go parsedOpcode.bytes 100.00% (23/23)
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 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 Stack.nipN 100.00% (14/14)
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/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/script.go GetPreciseSigOpCount 100.00% (13/13)
github.com/conformal/btcscript/opcode.go opcodeWithin 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/script.go sigDER 100.00% (11/11)
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/opcode.go opcodeLessThanOrEqual 100.00% (10/10)
github.com/conformal/btcscript/opcode.go opcodeMin 100.00% (10/10)
github.com/conformal/btcscript/opcode.go opcodeGreaterThan 100.00% (10/10)
github.com/conformal/btcscript/opcode.go opcodeNumNotEqual 100.00% (10/10)
github.com/conformal/btcscript/opcode.go opcodeLessThan 100.00% (10/10)
github.com/conformal/btcscript/script.go getSigOpCount 100.00% (10/10) github.com/conformal/btcscript/script.go getSigOpCount 100.00% (10/10)
github.com/conformal/btcscript/stack.go Stack.Tuck 100.00% (10/10) github.com/conformal/btcscript/stack.go Stack.Tuck 100.00% (10/10)
github.com/conformal/btcscript/opcode.go opcodeNumEqual 100.00% (10/10)
github.com/conformal/btcscript/opcode.go opcodeBoolOr 100.00% (10/10)
github.com/conformal/btcscript/opcode.go opcodeBoolAnd 100.00% (10/10) github.com/conformal/btcscript/opcode.go opcodeBoolAnd 100.00% (10/10)
github.com/conformal/btcscript/opcode.go opcodeBoolOr 100.00% (10/10)
github.com/conformal/btcscript/opcode.go opcodeNumEqual 100.00% (10/10)
github.com/conformal/btcscript/opcode.go opcodeNumNotEqual 100.00% (10/10)
github.com/conformal/btcscript/opcode.go opcodeLessThan 100.00% (10/10)
github.com/conformal/btcscript/opcode.go opcodeGreaterThan 100.00% (10/10)
github.com/conformal/btcscript/opcode.go opcodeLessThanOrEqual 100.00% (10/10)
github.com/conformal/btcscript/opcode.go opcodeGreaterThanOrEqual 100.00% (10/10) github.com/conformal/btcscript/opcode.go opcodeGreaterThanOrEqual 100.00% (10/10)
github.com/conformal/btcscript/stack.go Stack.SwapN 100.00% (9/9) github.com/conformal/btcscript/opcode.go opcodeMin 100.00% (10/10)
github.com/conformal/btcscript/script.go DisasmString 100.00% (9/9)
github.com/conformal/btcscript/stack.go Stack.RotN 100.00% (9/9) github.com/conformal/btcscript/stack.go Stack.RotN 100.00% (9/9)
github.com/conformal/btcscript/stack.go Stack.OverN 100.00% (9/9) github.com/conformal/btcscript/stack.go Stack.OverN 100.00% (9/9)
github.com/conformal/btcscript/stack.go Stack.SwapN 100.00% (9/9)
github.com/conformal/btcscript/script.go DisasmString 100.00% (9/9)
github.com/conformal/btcscript/stack.go Stack.DupN 100.00% (8/8)
github.com/conformal/btcscript/opcode.go opcodeSub 100.00% (8/8)
github.com/conformal/btcscript/opcode.go opcodeAdd 100.00% (8/8) github.com/conformal/btcscript/opcode.go opcodeAdd 100.00% (8/8)
github.com/conformal/btcscript/opcode.go opcodeEqual 100.00% (8/8) github.com/conformal/btcscript/opcode.go opcodeEqual 100.00% (8/8)
github.com/conformal/btcscript/opcode.go opcodeSub 100.00% (8/8)
github.com/conformal/btcscript/stack.go Stack.DupN 100.00% (8/8)
github.com/conformal/btcscript/script.go unparseScript 100.00% (7/7)
github.com/conformal/btcscript/opcode.go opcodePick 100.00% (7/7)
github.com/conformal/btcscript/opcode.go opcode0NotEqual 100.00% (7/7)
github.com/conformal/btcscript/opcode.go opcodeRoll 100.00% (7/7)
github.com/conformal/btcscript/stack.go Stack.DropN 100.00% (7/7) github.com/conformal/btcscript/stack.go Stack.DropN 100.00% (7/7)
github.com/conformal/btcscript/opcode.go opcodeRoll 100.00% (7/7)
github.com/conformal/btcscript/opcode.go opcodeNot 100.00% (7/7) github.com/conformal/btcscript/opcode.go opcodeNot 100.00% (7/7)
github.com/conformal/btcscript/opcode.go opcode0NotEqual 100.00% (7/7)
github.com/conformal/btcscript/opcode.go opcodePick 100.00% (7/7)
github.com/conformal/btcscript/script.go unparseScript 100.00% (7/7)
github.com/conformal/btcscript/opcode.go opcodeElse 100.00% (6/6)
github.com/conformal/btcscript/opcode.go opcodeEndif 100.00% (6/6) github.com/conformal/btcscript/opcode.go opcodeEndif 100.00% (6/6)
github.com/conformal/btcscript/opcode.go parsedOpcode.conditional 100.00% (6/6) github.com/conformal/btcscript/opcode.go parsedOpcode.conditional 100.00% (6/6)
github.com/conformal/btcscript/opcode.go opcodeIfDup 100.00% (6/6)
github.com/conformal/btcscript/opcode.go opcodeElse 100.00% (6/6)
github.com/conformal/btcscript/opcode.go opcodeVerify 100.00% (6/6)
github.com/conformal/btcscript/script.go typeOfScript 100.00% (6/6) github.com/conformal/btcscript/script.go typeOfScript 100.00% (6/6)
github.com/conformal/btcscript/opcode.go opcodeRipemd160 100.00% (5/5) github.com/conformal/btcscript/opcode.go opcodeVerify 100.00% (6/6)
github.com/conformal/btcscript/script.go expectedInputs 100.00% (6/6)
github.com/conformal/btcscript/opcode.go opcodeIfDup 100.00% (6/6)
github.com/conformal/btcscript/opcode.go opcodeFromAltStack 100.00% (5/5)
github.com/conformal/btcscript/script.go removeOpcodeByData 100.00% (5/5)
github.com/conformal/btcscript/opcode.go opcodeSha1 100.00% (5/5) github.com/conformal/btcscript/opcode.go opcodeSha1 100.00% (5/5)
github.com/conformal/btcscript/stack.go Stack.RollN 100.00% (5/5)
github.com/conformal/btcscript/stack.go Stack.PickN 100.00% (5/5)
github.com/conformal/btcscript/opcode.go opcodeHash160 100.00% (5/5)
github.com/conformal/btcscript/script.go Script.DisasmScript 100.00% (5/5)
github.com/conformal/btcscript/opcode.go opcodeHash256 100.00% (5/5)
github.com/conformal/btcscript/opcode.go opcodeSha256 100.00% (5/5)
github.com/conformal/btcscript/opcode.go opcodeSize 100.00% (5/5)
github.com/conformal/btcscript/opcode.go opcodeRipemd160 100.00% (5/5)
github.com/conformal/btcscript/opcode.go opcode1Add 100.00% (5/5) github.com/conformal/btcscript/opcode.go opcode1Add 100.00% (5/5)
github.com/conformal/btcscript/opcode.go opcode1Sub 100.00% (5/5) github.com/conformal/btcscript/opcode.go opcode1Sub 100.00% (5/5)
github.com/conformal/btcscript/opcode.go opcodeNegate 100.00% (5/5) github.com/conformal/btcscript/opcode.go opcodeNegate 100.00% (5/5)
github.com/conformal/btcscript/opcode.go opcodeAbs 100.00% (5/5) github.com/conformal/btcscript/opcode.go opcodeAbs 100.00% (5/5)
github.com/conformal/btcscript/opcode.go opcodeHash160 100.00% (5/5)
github.com/conformal/btcscript/opcode.go opcodeHash256 100.00% (5/5)
github.com/conformal/btcscript/opcode.go opcodeSha256 100.00% (5/5)
github.com/conformal/btcscript/stack.go Stack.PickN 100.00% (5/5)
github.com/conformal/btcscript/stack.go Stack.RollN 100.00% (5/5)
github.com/conformal/btcscript/opcode.go opcodeFromAltStack 100.00% (5/5)
github.com/conformal/btcscript/opcode.go opcodeToAltStack 100.00% (5/5)
github.com/conformal/btcscript/script.go removeOpcodeByData 100.00% (5/5)
github.com/conformal/btcscript/script.go removeOpcode 100.00% (5/5)
github.com/conformal/btcscript/script.go Script.validPC 100.00% (5/5) github.com/conformal/btcscript/script.go Script.validPC 100.00% (5/5)
github.com/conformal/btcscript/opcode.go parsedOpcode.exec 100.00% (5/5) github.com/conformal/btcscript/opcode.go parsedOpcode.exec 100.00% (5/5)
github.com/conformal/btcscript/script.go Script.DisasmScript 100.00% (5/5) github.com/conformal/btcscript/script.go removeOpcode 100.00% (5/5)
github.com/conformal/btcscript/opcode.go opcodeSize 100.00% (5/5) github.com/conformal/btcscript/opcode.go opcodeToAltStack 100.00% (5/5)
github.com/conformal/btcscript/opcode.go opcodePushData 100.00% (4/4) github.com/conformal/btcscript/opcode.go opcodePushData 100.00% (4/4)
github.com/conformal/btcscript/opcode.go opcodeEqualVerify 100.00% (4/4) github.com/conformal/btcscript/opcode.go opcodeEqualVerify 100.00% (4/4)
github.com/conformal/btcscript/opcode.go opcodeNumEqualVerify 100.00% (4/4) github.com/conformal/btcscript/opcode.go opcodeNumEqualVerify 100.00% (4/4)
@ -75,69 +77,69 @@ github.com/conformal/btcscript/stack.go asBool 100.00% (4/4)
github.com/conformal/btcscript/stack.go Stack.PeekByteArray 100.00% (4/4) github.com/conformal/btcscript/stack.go Stack.PeekByteArray 100.00% (4/4)
github.com/conformal/btcscript/stack.go Stack.PeekInt 100.00% (4/4) github.com/conformal/btcscript/stack.go Stack.PeekInt 100.00% (4/4)
github.com/conformal/btcscript/stack.go Stack.PopInt 100.00% (4/4) github.com/conformal/btcscript/stack.go Stack.PopInt 100.00% (4/4)
github.com/conformal/btcscript/script.go IsPayToScriptHash 100.00% (4/4)
github.com/conformal/btcscript/script.go isPushOnly 100.00% (4/4) github.com/conformal/btcscript/script.go isPushOnly 100.00% (4/4)
github.com/conformal/btcscript/script.go GetScriptClass 100.00% (4/4) github.com/conformal/btcscript/script.go GetScriptClass 100.00% (4/4)
github.com/conformal/btcscript/script.go Script.curPC 100.00% (4/4) github.com/conformal/btcscript/script.go Script.curPC 100.00% (4/4)
github.com/conformal/btcscript/script.go Script.DisasmPC 100.00% (4/4) github.com/conformal/btcscript/script.go Script.DisasmPC 100.00% (4/4)
github.com/conformal/btcscript/stack.go Stack.PeekBool 100.00% (4/4) github.com/conformal/btcscript/stack.go Stack.PeekBool 100.00% (4/4)
github.com/conformal/btcscript/script.go getStack 100.00% (4/4) github.com/conformal/btcscript/script.go getStack 100.00% (4/4)
github.com/conformal/btcscript/script.go scriptUInt16 100.00% (3/3) github.com/conformal/btcscript/script.go IsPayToScriptHash 100.00% (4/4)
github.com/conformal/btcscript/address.go ScriptType.String 100.00% (3/3) github.com/conformal/btcscript/address.go ScriptType.String 100.00% (3/3)
github.com/conformal/btcscript/script.go scriptUInt8 100.00% (3/3)
github.com/conformal/btcscript/script.go setStack 100.00% (3/3) github.com/conformal/btcscript/script.go setStack 100.00% (3/3)
github.com/conformal/btcscript/script.go scriptUInt16 100.00% (3/3)
github.com/conformal/btcscript/stack.go fromBool 100.00% (3/3) github.com/conformal/btcscript/stack.go fromBool 100.00% (3/3)
github.com/conformal/btcscript/script.go scriptUInt8 100.00% (3/3)
github.com/conformal/btcscript/script.go scriptUInt32 100.00% (3/3) github.com/conformal/btcscript/script.go scriptUInt32 100.00% (3/3)
github.com/conformal/btcscript/opcode.go opcodeCodeSeparator 100.00% (2/2)
github.com/conformal/btcscript/address.go ScriptToAddrHash 100.00% (2/2)
github.com/conformal/btcscript/stack.go Stack.NipN 100.00% (2/2)
github.com/conformal/btcscript/opcode.go opcodeDepth 100.00% (2/2)
github.com/conformal/btcscript/script.go GetSigOpCount 100.00% (2/2)
github.com/conformal/btcscript/opcode.go calcHash 100.00% (2/2) github.com/conformal/btcscript/opcode.go calcHash 100.00% (2/2)
github.com/conformal/btcscript/script.go PayToPubKeyHashScript 100.00% (2/2) github.com/conformal/btcscript/script.go GetSigOpCount 100.00% (2/2)
github.com/conformal/btcscript/opcode.go opcodeFalse 100.00% (2/2) github.com/conformal/btcscript/opcode.go opcodeCodeSeparator 100.00% (2/2)
github.com/conformal/btcscript/opcode.go opcodeDepth 100.00% (2/2)
github.com/conformal/btcscript/opcode.go opcodeN 100.00% (2/2) github.com/conformal/btcscript/opcode.go opcodeN 100.00% (2/2)
github.com/conformal/btcscript/script.go PayToPubKeyHashScript 100.00% (2/2)
github.com/conformal/btcscript/opcode.go opcode1Negate 100.00% (2/2) github.com/conformal/btcscript/opcode.go opcode1Negate 100.00% (2/2)
github.com/conformal/btcscript/stack.go Stack.Depth 100.00% (2/2) github.com/conformal/btcscript/stack.go Stack.Depth 100.00% (2/2)
github.com/conformal/btcscript/opcode.go opcodeNop 100.00% (1/1) github.com/conformal/btcscript/opcode.go opcodeFalse 100.00% (2/2)
github.com/conformal/btcscript/log.go DisableLog 100.00% (1/1) github.com/conformal/btcscript/stack.go Stack.NipN 100.00% (2/2)
github.com/conformal/btcscript/script.go isPubkey 100.00% (1/1) github.com/conformal/btcscript/address.go ScriptToAddrHash 100.00% (2/2)
github.com/conformal/btcscript/script.go isPubkeyHash 100.00% (1/1) github.com/conformal/btcscript/script.go isPubkeyHash 100.00% (1/1)
github.com/conformal/btcscript/script.go isScriptHash 100.00% (1/1) github.com/conformal/btcscript/script.go isScriptHash 100.00% (1/1)
github.com/conformal/btcscript/log.go UseLogger 100.00% (1/1) github.com/conformal/btcscript/script.go SignatureScript 100.00% (1/1)
github.com/conformal/btcscript/script.go Script.GetAltStack 100.00% (1/1)
github.com/conformal/btcscript/opcode.go opcodeInvalid 100.00% (1/1)
github.com/conformal/btcscript/script.go parseScript 100.00% (1/1) github.com/conformal/btcscript/script.go parseScript 100.00% (1/1)
github.com/conformal/btcscript/opcode.go opcodeInvalid 100.00% (1/1)
github.com/conformal/btcscript/opcode.go opcodeReserved 100.00% (1/1) github.com/conformal/btcscript/opcode.go opcodeReserved 100.00% (1/1)
github.com/conformal/btcscript/log.go UseLogger 100.00% (1/1)
github.com/conformal/btcscript/opcode.go opcodeDisabled 100.00% (1/1) github.com/conformal/btcscript/opcode.go opcodeDisabled 100.00% (1/1)
github.com/conformal/btcscript/opcode.go init 100.00% (1/1) github.com/conformal/btcscript/opcode.go init 100.00% (1/1)
github.com/conformal/btcscript/script.go SignatureScript 100.00% (1/1) github.com/conformal/btcscript/log.go DisableLog 100.00% (1/1)
github.com/conformal/btcscript/script.go Script.disasm 100.00% (1/1)
github.com/conformal/btcscript/log.go newLogClosure 100.00% (1/1) github.com/conformal/btcscript/log.go newLogClosure 100.00% (1/1)
github.com/conformal/btcscript/log.go init 100.00% (1/1) github.com/conformal/btcscript/log.go init 100.00% (1/1)
github.com/conformal/btcscript/stack.go Stack.PushByteArray 100.00% (1/1) github.com/conformal/btcscript/script.go Script.GetAltStack 100.00% (1/1)
github.com/conformal/btcscript/opcode.go opcodeRot 100.00% (1/1)
github.com/conformal/btcscript/opcode.go opcodeDup 100.00% (1/1)
github.com/conformal/btcscript/script.go Script.GetStack 100.00% (1/1)
github.com/conformal/btcscript/stack.go Stack.PopByteArray 100.00% (1/1) github.com/conformal/btcscript/stack.go Stack.PopByteArray 100.00% (1/1)
github.com/conformal/btcscript/opcode.go opcodeNip 100.00% (1/1)
github.com/conformal/btcscript/script.go Script.SetAltStack 100.00% (1/1)
github.com/conformal/btcscript/opcode.go opcodeDup 100.00% (1/1)
github.com/conformal/btcscript/opcode.go opcodeDrop 100.00% (1/1) github.com/conformal/btcscript/opcode.go opcodeDrop 100.00% (1/1)
github.com/conformal/btcscript/script.go Script.SetStack 100.00% (1/1)
github.com/conformal/btcscript/opcode.go opcode2Swap 100.00% (1/1) github.com/conformal/btcscript/opcode.go opcode2Swap 100.00% (1/1)
github.com/conformal/btcscript/opcode.go opcode2Rot 100.00% (1/1) github.com/conformal/btcscript/opcode.go opcode2Rot 100.00% (1/1)
github.com/conformal/btcscript/opcode.go opcode2Over 100.00% (1/1) github.com/conformal/btcscript/opcode.go opcode2Over 100.00% (1/1)
github.com/conformal/btcscript/script.go Script.SetAltStack 100.00% (1/1)
github.com/conformal/btcscript/opcode.go opcode3Dup 100.00% (1/1) github.com/conformal/btcscript/opcode.go opcode3Dup 100.00% (1/1)
github.com/conformal/btcscript/stack.go Stack.PushInt 100.00% (1/1)
github.com/conformal/btcscript/opcode.go opcode2Dup 100.00% (1/1) github.com/conformal/btcscript/opcode.go opcode2Dup 100.00% (1/1)
github.com/conformal/btcscript/opcode.go opcode2Drop 100.00% (1/1)
github.com/conformal/btcscript/opcode.go opcodeReturn 100.00% (1/1)
github.com/conformal/btcscript/stack.go Stack.PushBool 100.00% (1/1) github.com/conformal/btcscript/stack.go Stack.PushBool 100.00% (1/1)
github.com/conformal/btcscript/script.go Script.subScript 100.00% (1/1) github.com/conformal/btcscript/script.go Script.subScript 100.00% (1/1)
github.com/conformal/btcscript/script.go Script.disasm 100.00% (1/1) github.com/conformal/btcscript/opcode.go opcode2Drop 100.00% (1/1)
github.com/conformal/btcscript/opcode.go opcodeReturn 100.00% (1/1)
github.com/conformal/btcscript/opcode.go opcodeNop 100.00% (1/1)
github.com/conformal/btcscript/script.go isPubkey 100.00% (1/1)
github.com/conformal/btcscript/opcode.go opcodeOver 100.00% (1/1)
github.com/conformal/btcscript/script.go Script.GetStack 100.00% (1/1)
github.com/conformal/btcscript/opcode.go calcHash160 100.00% (1/1) github.com/conformal/btcscript/opcode.go calcHash160 100.00% (1/1)
github.com/conformal/btcscript/opcode.go opcodeTuck 100.00% (1/1) github.com/conformal/btcscript/opcode.go opcodeTuck 100.00% (1/1)
github.com/conformal/btcscript/opcode.go opcodeSwap 100.00% (1/1) github.com/conformal/btcscript/opcode.go opcodeSwap 100.00% (1/1)
github.com/conformal/btcscript/opcode.go opcodeOver 100.00% (1/1) github.com/conformal/btcscript/script.go Script.SetStack 100.00% (1/1)
github.com/conformal/btcscript/opcode.go opcodeNip 100.00% (1/1) github.com/conformal/btcscript/stack.go Stack.PushByteArray 100.00% (1/1)
github.com/conformal/btcscript/stack.go Stack.PushInt 100.00% (1/1)
github.com/conformal/btcscript/opcode.go opcodeRot 100.00% (1/1)
github.com/conformal/btcscript/opcode.go opcodeCheckMultiSig 98.21% (55/56) github.com/conformal/btcscript/opcode.go opcodeCheckMultiSig 98.21% (55/56)
github.com/conformal/btcscript/opcode.go opcodeCheckSig 96.15% (25/26) github.com/conformal/btcscript/opcode.go opcodeCheckSig 96.15% (25/26)
github.com/conformal/btcscript/script.go calcScriptHash 82.05% (32/39) github.com/conformal/btcscript/script.go calcScriptHash 82.05% (32/39)
@ -147,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.41% (939/974) github.com/conformal/btcscript --------------------------- 96.52% (970/1005)