Add functions to count the number of signature operations in a script.

To be usd for validation. Most of the codepaths teste, a few tests
missing for cases needed tests in the validation codepaths too. To be
worked on in tree.
This commit is contained in:
Owain G. Ainsworth 2013-06-20 18:07:44 +01:00
parent 421a213a4f
commit 03696a8874
4 changed files with 274 additions and 48 deletions

View file

@ -542,6 +542,8 @@ type detailedTest struct {
altafter [][]byte
disassembly string
disassemblyerr error
nSigOps int // should have same return as disassembly error
nPreciseSigOps int // should have same return as disassembly error
}
var detailedTests = []detailedTest{
@ -2115,12 +2117,16 @@ var detailedTests = []detailedTest{
script: []byte{btcscript.OP_1, btcscript.OP_CHECKSIG},
expectedReturn: btcscript.StackErrUnderflow,
disassembly: "OP_1 OP_CHECKSIG",
nSigOps: 1,
nPreciseSigOps: 1,
},
{
name: "OP_CHECKSIG no arg",
script: []byte{btcscript.OP_CHECKSIG},
expectedReturn: btcscript.StackErrUnderflow,
disassembly: "OP_CHECKSIG",
nSigOps: 1,
nPreciseSigOps: 1,
},
{
name: "OP_CHECKSIGVERIFY one arg",
@ -2128,18 +2134,24 @@ var detailedTests = []detailedTest{
btcscript.OP_CHECKSIGVERIFY},
expectedReturn: btcscript.StackErrUnderflow,
disassembly: "OP_1 OP_CHECKSIGVERIFY",
nSigOps: 1,
nPreciseSigOps: 1,
},
{
name: "OP_CHECKSIGVERIFY no arg",
script: []byte{btcscript.OP_CHECKSIGVERIFY},
expectedReturn: btcscript.StackErrUnderflow,
disassembly: "OP_CHECKSIGVERIFY",
nSigOps: 1,
nPreciseSigOps: 1,
},
{
name: "OP_CHECK_MULTISIG no args",
script: []byte{btcscript.OP_CHECK_MULTISIG},
expectedReturn: btcscript.StackErrUnderflow,
disassembly: "OP_CHECK_MULTISIG",
nSigOps: 20,
nPreciseSigOps: 20,
},
{
name: "OP_CHECK_MULTISIG huge number",
@ -2148,6 +2160,8 @@ var detailedTests = []detailedTest{
btcscript.OP_CHECK_MULTISIG},
expectedReturn: btcscript.StackErrNumberTooBig,
disassembly: "010203040506070809 OP_CHECK_MULTISIG",
nSigOps: 20,
nPreciseSigOps: 20,
},
{
name: "OP_CHECK_MULTISIG too many keys",
@ -2155,6 +2169,8 @@ var detailedTests = []detailedTest{
btcscript.OP_CHECK_MULTISIG},
expectedReturn: btcscript.StackErrTooManyPubkeys,
disassembly: "15 OP_CHECK_MULTISIG",
nSigOps: 20,
nPreciseSigOps: 20,
},
{
name: "OP_CHECK_MULTISIG lying about pubkeys",
@ -2162,6 +2178,8 @@ var detailedTests = []detailedTest{
btcscript.OP_CHECK_MULTISIG},
expectedReturn: btcscript.StackErrUnderflow,
disassembly: "OP_1 OP_CHECK_MULTISIG",
nSigOps: 20,
nPreciseSigOps: 1,
},
{
// pubkey comes from blockchain
@ -2180,6 +2198,8 @@ var detailedTests = []detailedTest{
btcscript.OP_CHECK_MULTISIG},
expectedReturn: btcscript.StackErrUnderflow,
disassembly: "04ae1a62fe09c5f51b13905f07f06b99a2f7159b2225f374cd378d71302fa28414e7aab37397f554a7df5f142c21c1b7303b8a0626f1baded5c72a704f7e6cd84c OP_1 OP_CHECK_MULTISIG",
nSigOps: 20,
nPreciseSigOps: 1,
},
{
// pubkey comes from blockchain
@ -2200,6 +2220,8 @@ var detailedTests = []detailedTest{
btcscript.OP_CHECK_MULTISIG},
expectedReturn: btcscript.StackErrNumberTooBig,
disassembly: "010203040506070809 04ae1a62fe09c5f51b13905f07f06b99a2f7159b2225f374cd378d71302fa28414e7aab37397f554a7df5f142c21c1b7303b8a0626f1baded5c72a704f7e6cd84c OP_1 OP_CHECK_MULTISIG",
nSigOps: 20,
nPreciseSigOps: 1,
},
{
name: "OP_CHECK_MULTISIG too few sigs",
@ -2217,6 +2239,8 @@ var detailedTests = []detailedTest{
btcscript.OP_CHECK_MULTISIG},
expectedReturn: btcscript.StackErrUnderflow,
disassembly: "OP_1 04ae1a62fe09c5f51b13905f07f06b99a2f7159b2225f374cd378d71302fa28414e7aab37397f554a7df5f142c21c1b7303b8a0626f1baded5c72a704f7e6cd84c OP_1 OP_CHECK_MULTISIG",
nSigOps: 20,
nPreciseSigOps: 1,
},
{
// pubkey and sig comes from blockchain, are unrelated
@ -2245,6 +2269,8 @@ var detailedTests = []detailedTest{
btcscript.OP_CHECK_MULTISIG},
after: [][]byte{{0}},
disassembly: "OP_1 304402204e45e16932b8af514961a1d3a1a25fdf3f4f7732e9d624c6c61548ab5fb8cd410220181522ec8eca07de4860a4acdd12909d831cc56cbbac4622082221a8768d1d0901 OP_1 04ae1a62fe09c5f51b13905f07f06b99a2f7159b2225f374cd378d71302fa28414e7aab37397f554a7df5f142c21c1b7303b8a0626f1baded5c72a704f7e6cd84c OP_1 OP_CHECK_MULTISIG",
nSigOps: 20,
nPreciseSigOps: 1,
},
{
// invalid pubkey means that it fails to validate, not an
@ -2266,6 +2292,8 @@ var detailedTests = []detailedTest{
btcscript.OP_CHECK_MULTISIG},
after: [][]byte{{0}},
disassembly: "OP_1 304402204e45e16932b8af514961a1d3a1a25fdf3f4f7732e9d624c6c61548ab5fb8cd410220181522ec8eca07de4860a4acdd12909d831cc56cbbac4622082221a8768d1d0901 OP_1 OP_1 OP_1 OP_CHECK_MULTISIG",
nSigOps: 20,
nPreciseSigOps: 1,
},
// XXX(oga) Test multisig when extra arg is missing. needs valid sig.
// disabled opcodes
@ -2274,6 +2302,8 @@ var detailedTests = []detailedTest{
script: []byte{btcscript.OP_CHECKMULTISIGVERIFY},
expectedReturn: btcscript.StackErrUnderflow,
disassembly: "OP_CHECKMULTISIGVERIFY",
nSigOps: 20,
nPreciseSigOps: 20,
},
{
name: "OP_CHECKMULTISIGVERIFY huge number",
@ -2282,6 +2312,8 @@ var detailedTests = []detailedTest{
btcscript.OP_CHECKMULTISIGVERIFY},
expectedReturn: btcscript.StackErrNumberTooBig,
disassembly: "010203040506070809 OP_CHECKMULTISIGVERIFY",
nSigOps: 20,
nPreciseSigOps: 20,
},
{
name: "OP_CHECKMULTISIGVERIFY too many keys",
@ -2289,6 +2321,8 @@ var detailedTests = []detailedTest{
btcscript.OP_CHECKMULTISIGVERIFY},
expectedReturn: btcscript.StackErrTooManyPubkeys,
disassembly: "15 OP_CHECKMULTISIGVERIFY",
nSigOps: 20,
nPreciseSigOps: 20,
},
{
name: "OP_CHECKMULTISIGVERIFY lying about pubkeys",
@ -2296,6 +2330,8 @@ var detailedTests = []detailedTest{
btcscript.OP_CHECKMULTISIGVERIFY},
expectedReturn: btcscript.StackErrUnderflow,
disassembly: "OP_1 OP_CHECKMULTISIGVERIFY",
nSigOps: 20,
nPreciseSigOps: 1,
},
{
// pubkey comes from blockchain
@ -2314,6 +2350,8 @@ var detailedTests = []detailedTest{
btcscript.OP_CHECKMULTISIGVERIFY},
expectedReturn: btcscript.StackErrUnderflow,
disassembly: "04ae1a62fe09c5f51b13905f07f06b99a2f7159b2225f374cd378d71302fa28414e7aab37397f554a7df5f142c21c1b7303b8a0626f1baded5c72a704f7e6cd84c OP_1 OP_CHECKMULTISIGVERIFY",
nSigOps: 20,
nPreciseSigOps: 1,
},
{
name: "OP_CHECKMULTISIGVERIFY sigs huge no",
@ -2333,6 +2371,8 @@ var detailedTests = []detailedTest{
btcscript.OP_CHECKMULTISIGVERIFY},
expectedReturn: btcscript.StackErrNumberTooBig,
disassembly: "010203040506070809 04ae1a62fe09c5f51b13905f07f06b99a2f7159b2225f374cd378d71302fa28414e7aab37397f554a7df5f142c21c1b7303b8a0626f1baded5c72a704f7e6cd84c OP_1 OP_CHECKMULTISIGVERIFY",
nSigOps: 20,
nPreciseSigOps: 1,
},
{
name: "OP_CHECKMULTISIGVERIFY too few sigs",
@ -2350,6 +2390,8 @@ var detailedTests = []detailedTest{
btcscript.OP_CHECKMULTISIGVERIFY},
expectedReturn: btcscript.StackErrUnderflow,
disassembly: "OP_1 04ae1a62fe09c5f51b13905f07f06b99a2f7159b2225f374cd378d71302fa28414e7aab37397f554a7df5f142c21c1b7303b8a0626f1baded5c72a704f7e6cd84c OP_1 OP_CHECKMULTISIGVERIFY",
nSigOps: 20,
nPreciseSigOps: 1,
},
{
// pubkey and sig comes from blockchain, are unrelated
@ -2378,6 +2420,8 @@ var detailedTests = []detailedTest{
btcscript.OP_CHECKMULTISIGVERIFY},
expectedReturn: btcscript.StackErrVerifyFailed,
disassembly: "OP_1 304402204e45e16932b8af514961a1d3a1a25fdf3f4f7732e9d624c6c61548ab5fb8cd410220181522ec8eca07de4860a4acdd12909d831cc56cbbac4622082221a8768d1d0901 OP_1 04ae1a62fe09c5f51b13905f07f06b99a2f7159b2225f374cd378d71302fa28414e7aab37397f554a7df5f142c21c1b7303b8a0626f1baded5c72a704f7e6cd84c OP_1 OP_CHECKMULTISIGVERIFY",
nSigOps: 20,
nPreciseSigOps: 1,
},
{
// invalid pubkey means that it fails to validate, not an
@ -2399,6 +2443,8 @@ var detailedTests = []detailedTest{
btcscript.OP_CHECKMULTISIGVERIFY},
expectedReturn: btcscript.StackErrVerifyFailed,
disassembly: "OP_1 304402204e45e16932b8af514961a1d3a1a25fdf3f4f7732e9d624c6c61548ab5fb8cd410220181522ec8eca07de4860a4acdd12909d831cc56cbbac4622082221a8768d1d0901 OP_1 OP_1 OP_1 OP_CHECKMULTISIGVERIFY",
nSigOps: 20,
nPreciseSigOps: 1,
},
{
// 201 operations + one push, should just fit limits
@ -3032,6 +3078,8 @@ var detailedTests = []detailedTest{
},
expectedReturn: btcscript.StackErrTooManyOperations,
disassembly: "OP_1 OP_DUP OP_DROP OP_DUP OP_DROP OP_DUP OP_DROP OP_DUP OP_DROP OP_DUP OP_DROP OP_DUP OP_DROP OP_DUP OP_DROP OP_DUP OP_DROP OP_DUP OP_DROP OP_DUP OP_DROP OP_DUP OP_DROP OP_DUP OP_DROP OP_DUP OP_DROP OP_DUP OP_DROP OP_DUP OP_DROP OP_DUP OP_DROP OP_DUP OP_DROP OP_DUP OP_DROP OP_DUP OP_DROP OP_DUP OP_DROP OP_DUP OP_DROP OP_DUP OP_DROP OP_DUP OP_DROP OP_DUP OP_DROP OP_DUP OP_DROP OP_DUP OP_DROP OP_DUP OP_DROP OP_DUP OP_DROP OP_DUP OP_DROP OP_DUP OP_DROP OP_DUP OP_DROP OP_DUP OP_DROP OP_DUP OP_DROP OP_DUP OP_DROP OP_DUP OP_DROP OP_DUP OP_DROP OP_DUP OP_DROP OP_DUP OP_DROP OP_DUP OP_DROP OP_DUP OP_DROP OP_DUP OP_DROP OP_DUP OP_DROP OP_DUP OP_DROP OP_DUP OP_DROP OP_DUP OP_DROP OP_DUP OP_DROP OP_DUP OP_DROP OP_DUP OP_DROP OP_DUP OP_DROP OP_DUP OP_DROP OP_DUP OP_DROP OP_DUP OP_DROP OP_DUP OP_DROP OP_DUP OP_DROP OP_DUP OP_DROP OP_DUP OP_DROP OP_DUP OP_DROP OP_DUP OP_DROP OP_DUP OP_DROP OP_DUP OP_DROP OP_DUP OP_DROP OP_DUP OP_DROP OP_DUP OP_DROP OP_DUP OP_DROP OP_DUP OP_DROP OP_DUP OP_DROP OP_DUP OP_DROP OP_DUP OP_DROP OP_DUP OP_DROP OP_DUP OP_DROP OP_DUP OP_DROP OP_DUP OP_DROP OP_DUP OP_DROP OP_DUP OP_DROP OP_DUP OP_DROP OP_DUP OP_DROP OP_DUP OP_DROP OP_DUP OP_DROP OP_DUP OP_DROP OP_DUP OP_DROP OP_DUP OP_DROP OP_DUP OP_DROP OP_DUP OP_DROP OP_DUP OP_DROP OP_DUP OP_DROP OP_DUP OP_DROP OP_DUP OP_DROP OP_DUP OP_DROP OP_DUP OP_DROP OP_DUP OP_DROP OP_DUP OP_DROP OP_DUP OP_DROP OP_DUP OP_DROP OP_DUP OP_DROP OP_DUP OP_DROP OP_DUP OP_DROP OP_DUP OP_DROP OP_DUP OP_DROP OP_DUP OP_DROP OP_DUP OP_DROP OP_1 OP_1 OP_1 OP_1 OP_2 OP_CHECK_MULTISIG",
nSigOps: 20,
nPreciseSigOps: 2,
},
{
name: "OP_CAT disabled",
@ -3735,3 +3783,65 @@ func TestDisasmStrings(t *testing.T) {
testDisasmString(t, &detailedTests[i])
}
}
// A basic test of GetSigOpCount for most opcodes, we do this by
// running the same test for every one of the detailed tests. Since
// disassembly errors are always parse errors, and so are
// sigops count errors we use the same error code.
// While this isn't as precise as using full transaction scripts, this gives
// us coverage over a wider range of opcodes.
func TestSigOps(t *testing.T) {
for _, test := range detailedTests {
count, err := btcscript.GetSigOpCount(test.script)
if err != nil {
if err != test.disassemblyerr {
t.Errorf("%s: unexpected error. exp \"%v\""+
"got \"%v\"", test.name,
test.disassemblyerr, err)
}
continue
}
if test.disassemblyerr != nil {
t.Errorf("%s: no error when expected \"%v\"",
test.name, test.disassemblyerr)
continue
}
if count != test.nSigOps {
t.Errorf("%s: expected count of %d, got %d", test.name,
test.nSigOps, count)
}
}
}
// A basic test of GetPreciseSigOpCount for most opcodes, we do this by
// running the same test for every one of the detailed tests with a fake
// sigscript. Sicne disassembly errors are always parse errors, and so are
// sigops count errors we use the same error code.
// While this isn't as precise as using full transaction scripts, this gives
// us coverage over a wider range of opcodes. See script_test.go for tests
// using real transactions to provide a bit more coverage.
func TestPreciseSigOps(t *testing.T) {
for _, test := range detailedTests {
count, err := btcscript.GetPreciseSigOpCount(
[]byte{btcscript.OP_1}, test.script, false)
if err != nil {
if err != test.disassemblyerr {
t.Errorf("%s: unexpected error. exp \"%v\""+
"got \"%v\"", test.name,
test.disassemblyerr, err)
}
continue
}
if test.disassemblyerr != nil {
t.Errorf("%s: no error when expected \"%v\"",
test.name, test.disassemblyerr)
continue
}
if count != test.nPreciseSigOps {
t.Errorf("%s: expected count of %d, got %d", test.name,
test.nPreciseSigOps, count)
}
}
}

View file

@ -715,3 +715,87 @@ func (s *Script) GetAltStack() [][]byte {
func (s *Script) SetAltStack(data [][]byte) {
setStack(&s.astack, data)
}
// GetSigOpCount provides a quick count of the number of signature operations
// in a script. a CHECKSIG operations counts for 1, and a CHECK_MULTISIG for 20.
func GetSigOpCount(script [] byte) (int, error) {
pops, err := parseScript(script)
if err != nil {
return 0, err
}
return getSigOpCount(pops, false), nil
}
// GetPreciseSigOpCount returns the number of signature operations in
// scriptPubKey. If bip16 is true then scriptSig may be searched for the
// Pay-To-Script-Hash script in order to find the precise number of signature
// operations in the transaction.
func GetPreciseSigOpCount(scriptSig, scriptPubKey []byte, bip16 bool) (int, error) {
pops, err := parseScript(scriptPubKey)
if err != nil {
return 0, err
}
// non P2SH transactions just treated as normal.
if !(bip16 && isScriptHash(pops)) {
return getSigOpCount(pops, true), nil
}
// Ok so this is P2SH, get the contained script and count it..
sigPops, err := parseScript(scriptSig)
if err != nil {
return 0, err
}
if !isPushOnly(sigPops) || len(sigPops) == 0 {
return 0, nil
}
shScript := sigPops[len(sigPops) - 1].data
// Means that sigPops is jus OP_1 - OP_16, no sigops there.
if shScript == nil {
return 0, nil
}
shPops, err := parseScript(shScript)
if err != nil {
return 0, err
}
return getSigOpCount(shPops, true), nil
}
// getSigOpCount is the implementation function for counting the number of
// signature operations in the script provided by pops. If precise mode is
// requested then we attempt to count the number of operations for a multisig
// op. Otherwise we use the maximum.
func getSigOpCount(pops []parsedOpcode, precise bool) int {
nSigs := 0
for i, pop := range pops {
switch pop.opcode.value {
case OP_CHECKSIG:
fallthrough;
case OP_CHECKSIGVERIFY:
nSigs++
case OP_CHECK_MULTISIG:
fallthrough;
case OP_CHECKMULTISIGVERIFY:
// If we are being precise then look for familiar
// patterns for multisig, for now all we recognise is
// OP_1 - OP_16 to signify the number of pubkeys.
// Otherwise, we use the max of 20.
if precise && i > 0 &&
pops[i - 1].opcode.value >= OP_1 &&
pops[i - 1].opcode.value <= OP_16 {
nSigs += int(pops[i-1].opcode.value -
(OP_1 - 1))
} else {
nSigs += MaxPubKeysPerMultiSig
}
default:
// not a sigop.
}
}
return nSigs
}

View file

@ -19,6 +19,7 @@ type txTest struct {
bip16 bool
err error
shouldFail bool
nSigOps int
}
var txTests = []txTest{
@ -121,6 +122,7 @@ var txTests = []txTest{
0x12, 0xa3, btcscript.OP_CHECKSIG,
},
idx: 0,
nSigOps: 1,
},
// Previous test with the value of one output changed.
txTest{
@ -221,6 +223,7 @@ var txTests = []txTest{
},
idx: 0,
err: btcscript.StackErrScriptFailed,
nSigOps: 1,
},
txTest{
name: "CheckSig invalid signature",
@ -322,6 +325,7 @@ var txTests = []txTest{
},
idx: 0,
shouldFail: true,
nSigOps: 1,
},
txTest{
name: "CheckSig invalid pubkey",
@ -422,6 +426,7 @@ var txTests = []txTest{
},
idx: 0,
shouldFail: true,
nSigOps: 1,
},
// tx 599e47a8114fe098103663029548811d2651991b62397e057f0c863c2bc9f9ea
// uses checksig with SigHashNone.
@ -523,6 +528,7 @@ var txTests = []txTest{
},
idx: 0,
bip16: true, // after threshold
nSigOps: 1,
},
// tx 51bf528ecf3c161e7c021224197dbe84f9a8564212f6207baa014c01a1668e1e
// first instance of an AnyoneCanPay signature in the blockchain
@ -646,6 +652,7 @@ var txTests = []txTest{
},
idx: 0,
bip16: true, // after threshold
nSigOps: 1,
},
// tx 6d36bc17e947ce00bb6f12f8e7a56a1585c5a36188ffa2b05e10b4743273a74b
// Uses OP_CODESEPARATOR and OP_CHECKMULTISIG
@ -768,6 +775,7 @@ var txTests = []txTest{
},
idx: 1,
bip16: false,
nSigOps: 0, // multisig is in the pkScript!
},
// same as previous but with one byte changed to make signature fail
txTest{
@ -890,6 +898,7 @@ var txTests = []txTest{
idx: 1,
bip16: false,
err: btcscript.StackErrScriptFailed,
nSigOps: 0, // multisig is in the pkScript!
},
// tx e5779b9e78f9650debc2893fd9636d827b26b4ddfa6a8172fe8708c924f5c39d
// First P2SH transaction in the blockchain
@ -948,6 +957,7 @@ var txTests = []txTest{
},
idx: 0,
bip16: true,
nSigOps: 0, // no signature ops in the pushed script.
},
}
@ -990,6 +1000,25 @@ func TestTX(t *testing.T) {
}
}
func TestGetPreciseSignOps(t *testing.T) {
for _, test := range txTests {
count, err := btcscript.GetPreciseSigOpCount(
test.tx.TxIn[test.idx].SignatureScript, test.pkScript,
test.bip16)
// all tx currently parse
if err != nil {
t.Errorf("%s: unexpected error. got \"%v\"",
test.name, err)
continue
}
if count != test.nSigOps {
t.Errorf("%s: expected count of %d, got %d", test.name,
test.nSigOps, count)
}
}
}
type removeOpcodeTest struct {
name string
before []byte

View file

@ -2,56 +2,57 @@
github.com/conformal/btcscript/stack.go asInt 100.00% (18/18)
github.com/conformal/btcscript/stack.go fromInt 100.00% (14/14)
github.com/conformal/btcscript/opcode.go opcodeWithin 100.00% (13/13)
github.com/conformal/btcscript/opcode.go parsedOpcode.bytes 100.00% (12/12)
github.com/conformal/btcscript/stack.go Stack.nipN 100.00% (12/12)
github.com/conformal/btcscript/opcode.go parsedOpcode.print 100.00% (12/12)
github.com/conformal/btcscript/stack.go Stack.nipN 100.00% (12/12)
github.com/conformal/btcscript/opcode.go parsedOpcode.bytes 100.00% (12/12)
github.com/conformal/btcscript/opcode.go opcodeIf 100.00% (11/11)
github.com/conformal/btcscript/opcode.go opcodeNotIf 100.00% (11/11)
github.com/conformal/btcscript/stack.go Stack.Tuck 100.00% (10/10)
github.com/conformal/btcscript/script.go getSigOpCount 100.00% (10/10)
github.com/conformal/btcscript/opcode.go opcodeMax 100.00% (10/10)
github.com/conformal/btcscript/opcode.go opcodeMin 100.00% (10/10)
github.com/conformal/btcscript/opcode.go opcodeGreaterThanOrEqual 100.00% (10/10)
github.com/conformal/btcscript/opcode.go opcodeLessThanOrEqual 100.00% (10/10)
github.com/conformal/btcscript/opcode.go opcodeGreaterThan 100.00% (10/10)
github.com/conformal/btcscript/opcode.go opcodeLessThan 100.00% (10/10)
github.com/conformal/btcscript/opcode.go opcodeNumNotEqual 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 opcodeNumEqual 100.00% (10/10)
github.com/conformal/btcscript/opcode.go opcodeMax 100.00% (10/10)
github.com/conformal/btcscript/stack.go Stack.Tuck 100.00% (10/10)
github.com/conformal/btcscript/opcode.go opcodeMin 100.00% (10/10)
github.com/conformal/btcscript/opcode.go opcodeGreaterThanOrEqual 100.00% (10/10)
github.com/conformal/btcscript/stack.go Stack.RotN 100.00% (9/9)
github.com/conformal/btcscript/script.go DisasmString 100.00% (9/9)
github.com/conformal/btcscript/stack.go Stack.SwapN 100.00% (9/9)
github.com/conformal/btcscript/stack.go Stack.OverN 100.00% (9/9)
github.com/conformal/btcscript/opcode.go opcodeEqual 100.00% (8/8)
github.com/conformal/btcscript/script.go DisasmString 100.00% (9/9)
github.com/conformal/btcscript/opcode.go opcodeAdd 100.00% (8/8)
github.com/conformal/btcscript/opcode.go opcodeSub 100.00% (8/8)
github.com/conformal/btcscript/opcode.go opcodeEqual 100.00% (8/8)
github.com/conformal/btcscript/stack.go Stack.DupN 100.00% (8/8)
github.com/conformal/btcscript/opcode.go opcodePick 100.00% (7/7)
github.com/conformal/btcscript/opcode.go opcodeNot 100.00% (7/7)
github.com/conformal/btcscript/stack.go Stack.DropN 100.00% (7/7)
github.com/conformal/btcscript/opcode.go opcode0NotEqual 100.00% (7/7)
github.com/conformal/btcscript/opcode.go opcodeRoll 100.00% (7/7)
github.com/conformal/btcscript/opcode.go opcodeElse 100.00% (6/6)
github.com/conformal/btcscript/opcode.go opcodeIfDup 100.00% (6/6)
github.com/conformal/btcscript/opcode.go parsedOpcode.conditional 100.00% (6/6)
github.com/conformal/btcscript/opcode.go opcodePick 100.00% (7/7)
github.com/conformal/btcscript/opcode.go opcodeNot 100.00% (7/7)
github.com/conformal/btcscript/opcode.go opcodeVerify 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 parsedOpcode.conditional 100.00% (6/6)
github.com/conformal/btcscript/opcode.go opcodeHash256 100.00% (5/5)
github.com/conformal/btcscript/script.go removeOpcode 100.00% (5/5)
github.com/conformal/btcscript/script.go removeOpcodeByData 100.00% (5/5)
github.com/conformal/btcscript/stack.go Stack.PickN 100.00% (5/5)
github.com/conformal/btcscript/opcode.go parsedOpcode.exec 100.00% (5/5)
github.com/conformal/btcscript/stack.go Stack.RollN 100.00% (5/5)
github.com/conformal/btcscript/opcode.go opcodeToAltStack 100.00% (5/5)
github.com/conformal/btcscript/script.go Script.validPC 100.00% (5/5)
github.com/conformal/btcscript/opcode.go opcodeNegate 100.00% (5/5)
github.com/conformal/btcscript/opcode.go opcodeHash160 100.00% (5/5)
github.com/conformal/btcscript/opcode.go opcodeFromAltStack 100.00% (5/5)
github.com/conformal/btcscript/opcode.go opcodeSha256 100.00% (5/5)
github.com/conformal/btcscript/opcode.go opcodeRipemd160 100.00% (5/5)
github.com/conformal/btcscript/opcode.go opcodeNegate 100.00% (5/5)
github.com/conformal/btcscript/opcode.go opcodeHash160 100.00% (5/5)
github.com/conformal/btcscript/opcode.go opcodeAbs 100.00% (5/5)
github.com/conformal/btcscript/script.go Script.validPC 100.00% (5/5)
github.com/conformal/btcscript/opcode.go opcodeToAltStack 100.00% (5/5)
github.com/conformal/btcscript/opcode.go opcodeSize 100.00% (5/5)
github.com/conformal/btcscript/opcode.go opcode1Add 100.00% (5/5)
github.com/conformal/btcscript/opcode.go opcode1Sub 100.00% (5/5)
github.com/conformal/btcscript/opcode.go opcodeSize 100.00% (5/5)
github.com/conformal/btcscript/opcode.go parsedOpcode.exec 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/script.go removeOpcodeByData 100.00% (5/5)
github.com/conformal/btcscript/stack.go Stack.PeekBool 100.00% (4/4)
github.com/conformal/btcscript/opcode.go opcodeEndif 100.00% (4/4)
github.com/conformal/btcscript/opcode.go opcodeEqualVerify 100.00% (4/4)
@ -66,43 +67,47 @@ github.com/conformal/btcscript/script.go unparseScript 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 getStack 100.00% (4/4)
github.com/conformal/btcscript/script.go GetSigOpCount 100.00% (4/4)
github.com/conformal/btcscript/stack.go fromBool 100.00% (3/3)
github.com/conformal/btcscript/script.go setStack 100.00% (3/3)
github.com/conformal/btcscript/address.go ScriptType.String 100.00% (3/3)
github.com/conformal/btcscript/script.go scriptUInt16 100.00% (3/3)
github.com/conformal/btcscript/script.go setStack 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/stack.go Stack.NipN 100.00% (2/2)
github.com/conformal/btcscript/stack.go Stack.Depth 100.00% (2/2)
github.com/conformal/btcscript/opcode.go calcHash 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 opcodeCodeSeparator 100.00% (2/2)
github.com/conformal/btcscript/opcode.go opcode1Negate 100.00% (2/2)
github.com/conformal/btcscript/opcode.go opcodeFalse 100.00% (2/2)
github.com/conformal/btcscript/opcode.go opcodePushData 100.00% (2/2)
github.com/conformal/btcscript/opcode.go opcodeNop 100.00% (1/1)
github.com/conformal/btcscript/opcode.go opcode3Dup 100.00% (1/1)
github.com/conformal/btcscript/opcode.go calcHash 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/stack.go Stack.Depth 100.00% (2/2)
github.com/conformal/btcscript/opcode.go opcode1Negate 100.00% (2/2)
github.com/conformal/btcscript/stack.go Stack.NipN 100.00% (2/2)
github.com/conformal/btcscript/opcode.go opcodeN 100.00% (2/2)
github.com/conformal/btcscript/opcode.go opcodeFalse 100.00% (2/2)
github.com/conformal/btcscript/opcode.go init 100.00% (1/1)
github.com/conformal/btcscript/log.go newLogClosure 100.00% (1/1)
github.com/conformal/btcscript/stack.go Stack.PopByteArray 100.00% (1/1)
github.com/conformal/btcscript/opcode.go calcHash160 100.00% (1/1)
github.com/conformal/btcscript/opcode.go opcode2Dup 100.00% (1/1)
github.com/conformal/btcscript/opcode.go opcode2Drop 100.00% (1/1)
github.com/conformal/btcscript/opcode.go opcodeReturn 100.00% (1/1)
github.com/conformal/btcscript/opcode.go opcodeNop 100.00% (1/1)
github.com/conformal/btcscript/opcode.go opcode3Dup 100.00% (1/1)
github.com/conformal/btcscript/stack.go Stack.PushByteArray 100.00% (1/1)
github.com/conformal/btcscript/stack.go Stack.PushInt 100.00% (1/1)
github.com/conformal/btcscript/opcode.go opcode2Over 100.00% (1/1)
github.com/conformal/btcscript/stack.go Stack.PopByteArray 100.00% (1/1)
github.com/conformal/btcscript/script.go Script.GetStack 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 opcodeDisabled 100.00% (1/1)
github.com/conformal/btcscript/opcode.go init 100.00% (1/1)
github.com/conformal/btcscript/script.go Script.SetStack 100.00% (1/1)
github.com/conformal/btcscript/opcode.go opcodeDisabled 100.00% (1/1)
github.com/conformal/btcscript/script.go Script.GetAltStack 100.00% (1/1)
github.com/conformal/btcscript/log.go UseLogger 100.00% (1/1)
github.com/conformal/btcscript/script.go Script.SetAltStack 100.00% (1/1)
github.com/conformal/btcscript/script.go isPubkey 100.00% (1/1)
github.com/conformal/btcscript/script.go isPubkeyHash 100.00% (1/1)
github.com/conformal/btcscript/script.go isScriptHash 100.00% (1/1)
github.com/conformal/btcscript/log.go DisableLog 100.00% (1/1)
github.com/conformal/btcscript/script.go Script.GetAltStack 100.00% (1/1)
github.com/conformal/btcscript/log.go init 100.00% (1/1)
github.com/conformal/btcscript/script.go Script.SetAltStack 100.00% (1/1)
github.com/conformal/btcscript/script.go Script.disasm 100.00% (1/1)
github.com/conformal/btcscript/log.go init 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 opcodeRot 100.00% (1/1)
@ -112,22 +117,20 @@ github.com/conformal/btcscript/opcode.go opcodeDup 100.00% (1/1)
github.com/conformal/btcscript/opcode.go opcodeDrop 100.00% (1/1)
github.com/conformal/btcscript/opcode.go opcode2Swap 100.00% (1/1)
github.com/conformal/btcscript/opcode.go opcode2Rot 100.00% (1/1)
github.com/conformal/btcscript/script.go Script.GetStack 100.00% (1/1)
github.com/conformal/btcscript/log.go newLogClosure 100.00% (1/1)
github.com/conformal/btcscript/script.go isPubkey 100.00% (1/1)
github.com/conformal/btcscript/opcode.go opcode2Over 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/log.go UseLogger 100.00% (1/1)
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/script.go NewScript 95.24% (20/21)
github.com/conformal/btcscript/address.go ScriptToAddress 94.92% (56/59)
github.com/conformal/btcscript/script.go NewScript 94.74% (18/19)
github.com/conformal/btcscript/script.go parseScript 93.75% (30/32)
github.com/conformal/btcscript/script.go Script.Step 91.89% (34/37)
github.com/conformal/btcscript/script.go typeOfScript 83.33% (5/6)
github.com/conformal/btcscript/script.go Script.DisasmScript 80.00% (4/5)
github.com/conformal/btcscript/script.go isPushOnly 75.00% (3/4)
github.com/conformal/btcscript/script.go GetPreciseSigOpCount 77.78% (14/18)
github.com/conformal/btcscript/opcode.go opcodeCheckSigVerify 75.00% (3/4)
github.com/conformal/btcscript/script.go isPushOnly 75.00% (3/4)
github.com/conformal/btcscript/script.go Script.calcScriptHash 71.43% (25/35)
github.com/conformal/btcscript/script.go Script.CheckErrorCondition 71.43% (10/14)
github.com/conformal/btcscript/script.go isMultiSig 61.54% (8/13)
@ -135,5 +138,5 @@ github.com/conformal/btcscript/opcode.go opcodeSha1 60.00% (3/5)
github.com/conformal/btcscript/script.go Script.Execute 44.44% (8/18)
github.com/conformal/btcscript/log.go SetLogWriter 0.00% (0/7)
github.com/conformal/btcscript/log.go logClosure.String 0.00% (0/1)
github.com/conformal/btcscript -------------------------- 93.98% (843/897)
github.com/conformal/btcscript -------------------------- 93.74% (869/927)