2015-01-30 07:03:01 +01:00
|
|
|
// Copyright (c) 2013-2015 Conformal Systems LLC.
|
2013-06-12 23:35:27 +02:00
|
|
|
// Use of this source code is governed by an ISC
|
|
|
|
// license that can be found in the LICENSE file.
|
|
|
|
|
2015-01-30 07:03:01 +01:00
|
|
|
package txscript
|
2013-06-12 23:35:27 +02:00
|
|
|
|
|
|
|
import (
|
|
|
|
"bytes"
|
|
|
|
"encoding/binary"
|
|
|
|
"fmt"
|
2014-07-03 02:37:49 +02:00
|
|
|
"time"
|
|
|
|
|
2015-02-05 22:16:39 +01:00
|
|
|
"github.com/btcsuite/btcd/wire"
|
2015-01-15 17:42:26 +01:00
|
|
|
"github.com/btcsuite/btcutil"
|
2013-06-12 23:35:27 +02:00
|
|
|
)
|
|
|
|
|
2014-03-14 19:40:35 +01:00
|
|
|
const (
|
2015-02-28 14:50:38 +01:00
|
|
|
// maxDataCarrierSize is the maximum number of bytes allowed in pushed
|
|
|
|
// data to be considered a nulldata transaction
|
|
|
|
maxDataCarrierSize = 80
|
2014-03-14 19:40:35 +01:00
|
|
|
)
|
2014-03-14 19:35:36 +01:00
|
|
|
|
2013-06-12 23:35:27 +02:00
|
|
|
// Bip16Activation is the timestamp where BIP0016 is valid to use in the
|
|
|
|
// blockchain. To be used to determine if BIP0016 should be called for or not.
|
|
|
|
// This timestamp corresponds to Sun Apr 1 00:00:00 UTC 2012.
|
|
|
|
var Bip16Activation = time.Unix(1333238400, 0)
|
|
|
|
|
2014-10-11 21:55:28 +02:00
|
|
|
// SigHashType represents hash type bits at the end of a signature.
|
|
|
|
type SigHashType byte
|
|
|
|
|
2013-06-12 23:35:27 +02:00
|
|
|
// Hash type bits from the end of a signature.
|
|
|
|
const (
|
2014-10-11 21:55:28 +02:00
|
|
|
SigHashOld SigHashType = 0x0
|
|
|
|
SigHashAll SigHashType = 0x1
|
|
|
|
SigHashNone SigHashType = 0x2
|
|
|
|
SigHashSingle SigHashType = 0x3
|
|
|
|
SigHashAnyOneCanPay SigHashType = 0x80
|
2015-04-29 20:08:56 +02:00
|
|
|
|
|
|
|
// sigHashMask defines the number of bits of the hash type which is used
|
|
|
|
// to identify which outputs are signed.
|
|
|
|
sigHashMask = 0x1f
|
2013-06-12 23:35:27 +02:00
|
|
|
)
|
|
|
|
|
|
|
|
// These are the constants specified for maximums in individual scripts.
|
|
|
|
const (
|
|
|
|
MaxOpsPerScript = 201 // Max number of non-push operations.
|
|
|
|
MaxPubKeysPerMultiSig = 20 // Multisig can't have more sigs than this.
|
|
|
|
MaxScriptElementSize = 520 // Max bytes pushable to the stack.
|
|
|
|
)
|
|
|
|
|
2013-07-05 01:54:55 +02:00
|
|
|
// ScriptClass is an enumeration for the list of standard types of script.
|
|
|
|
type ScriptClass byte
|
2013-06-12 23:35:27 +02:00
|
|
|
|
2013-07-05 01:54:55 +02:00
|
|
|
// Classes of script payment known about in the blockchain.
|
2013-06-12 23:35:27 +02:00
|
|
|
const (
|
2013-11-14 22:05:20 +01:00
|
|
|
NonStandardTy ScriptClass = iota // None of the recognized forms.
|
|
|
|
PubKeyTy // Pay pubkey.
|
2013-07-31 02:31:27 +02:00
|
|
|
PubKeyHashTy // Pay pubkey hash.
|
|
|
|
ScriptHashTy // Pay to script hash.
|
|
|
|
MultiSigTy // Multi signature.
|
2013-11-14 22:05:20 +01:00
|
|
|
NullDataTy // Empty data-only (provably prunable).
|
2013-06-12 23:35:27 +02:00
|
|
|
)
|
|
|
|
|
2015-04-29 20:08:56 +02:00
|
|
|
// scriptClassToName houses the human-readable strings which describe each
|
|
|
|
// script class.
|
2013-11-06 01:10:16 +01:00
|
|
|
var scriptClassToName = []string{
|
2013-11-14 22:05:20 +01:00
|
|
|
NonStandardTy: "nonstandard",
|
2013-11-14 18:13:58 +01:00
|
|
|
PubKeyTy: "pubkey",
|
|
|
|
PubKeyHashTy: "pubkeyhash",
|
|
|
|
ScriptHashTy: "scripthash",
|
|
|
|
MultiSigTy: "multisig",
|
2013-11-14 22:05:20 +01:00
|
|
|
NullDataTy: "nulldata",
|
2013-11-06 01:10:16 +01:00
|
|
|
}
|
|
|
|
|
|
|
|
// String implements the Stringer interface by returning the name of
|
|
|
|
// the enum script class. If the enum is invalid then "Invalid" will be
|
|
|
|
// returned.
|
|
|
|
func (t ScriptClass) String() string {
|
|
|
|
if int(t) > len(scriptClassToName) || int(t) < 0 {
|
|
|
|
return "Invalid"
|
|
|
|
}
|
|
|
|
return scriptClassToName[t]
|
|
|
|
}
|
|
|
|
|
2014-02-19 23:17:02 +01:00
|
|
|
// isSmallInt returns whether or not the opcode is considered a small integer,
|
|
|
|
// which is an OP_0, or OP_1 through OP_16.
|
|
|
|
func isSmallInt(op *opcode) bool {
|
|
|
|
if op.value == OP_0 || (op.value >= OP_1 && op.value <= OP_16) {
|
|
|
|
return true
|
|
|
|
}
|
|
|
|
return false
|
|
|
|
}
|
|
|
|
|
2015-04-29 20:08:56 +02:00
|
|
|
// isPubkey returns true if the script passed is a pay-to-pubkey transaction,
|
|
|
|
// false otherwise.
|
2013-06-12 23:35:27 +02:00
|
|
|
func isPubkey(pops []parsedOpcode) bool {
|
2015-04-29 20:08:56 +02:00
|
|
|
// Valid pubkeys are either 33 or 65 bytes.
|
2013-06-12 23:35:27 +02:00
|
|
|
return len(pops) == 2 &&
|
2014-02-21 09:11:11 +01:00
|
|
|
(len(pops[0].data) == 33 || len(pops[0].data) == 65) &&
|
2013-06-12 23:35:27 +02:00
|
|
|
pops[1].opcode.value == OP_CHECKSIG
|
|
|
|
}
|
|
|
|
|
2015-04-29 20:08:56 +02:00
|
|
|
// isPubkeyHash returns true if the script passed is a pay-to-pubkey-hash
|
|
|
|
// transaction, false otherwise.
|
2013-06-12 23:35:27 +02:00
|
|
|
func isPubkeyHash(pops []parsedOpcode) bool {
|
|
|
|
return len(pops) == 5 &&
|
|
|
|
pops[0].opcode.value == OP_DUP &&
|
|
|
|
pops[1].opcode.value == OP_HASH160 &&
|
|
|
|
pops[2].opcode.value == OP_DATA_20 &&
|
|
|
|
pops[3].opcode.value == OP_EQUALVERIFY &&
|
|
|
|
pops[4].opcode.value == OP_CHECKSIG
|
|
|
|
|
|
|
|
}
|
|
|
|
|
2015-04-29 20:08:56 +02:00
|
|
|
// isScriptHash returns true if the script passed is a pay-to-script-hash
|
|
|
|
// transaction, false otherwise.
|
2013-06-12 23:35:27 +02:00
|
|
|
func isScriptHash(pops []parsedOpcode) bool {
|
|
|
|
return len(pops) == 3 &&
|
|
|
|
pops[0].opcode.value == OP_HASH160 &&
|
|
|
|
pops[1].opcode.value == OP_DATA_20 &&
|
|
|
|
pops[2].opcode.value == OP_EQUAL
|
|
|
|
}
|
|
|
|
|
2013-06-27 01:32:11 +02:00
|
|
|
// IsPayToScriptHash returns true if the script is in the standard
|
2015-04-29 20:08:56 +02:00
|
|
|
// pay-to-script-hash (P2SH) format, false otherwise.
|
2013-06-27 01:32:11 +02:00
|
|
|
func IsPayToScriptHash(script []byte) bool {
|
|
|
|
pops, err := parseScript(script)
|
|
|
|
if err != nil {
|
|
|
|
return false
|
|
|
|
}
|
|
|
|
return isScriptHash(pops)
|
|
|
|
}
|
|
|
|
|
2013-06-12 23:35:27 +02:00
|
|
|
// isMultiSig returns true if the passed script is a multisig transaction, false
|
|
|
|
// otherwise.
|
|
|
|
func isMultiSig(pops []parsedOpcode) bool {
|
2015-04-29 20:08:56 +02:00
|
|
|
// The absolute minimum is 1 pubkey:
|
|
|
|
// OP_0/OP_1-16 <pubkey> OP_1 OP_CHECKMULTISIG
|
2013-06-12 23:35:27 +02:00
|
|
|
l := len(pops)
|
|
|
|
if l < 4 {
|
|
|
|
return false
|
|
|
|
}
|
2014-02-19 23:17:02 +01:00
|
|
|
if !isSmallInt(pops[0].opcode) {
|
2013-06-12 23:35:27 +02:00
|
|
|
return false
|
|
|
|
}
|
2014-02-19 23:17:02 +01:00
|
|
|
if !isSmallInt(pops[l-2].opcode) {
|
2013-06-12 23:35:27 +02:00
|
|
|
return false
|
|
|
|
}
|
2014-01-04 22:13:29 +01:00
|
|
|
if pops[l-1].opcode.value != OP_CHECKMULTISIG {
|
2013-06-12 23:35:27 +02:00
|
|
|
return false
|
|
|
|
}
|
|
|
|
for _, pop := range pops[1 : l-2] {
|
2015-04-29 20:08:56 +02:00
|
|
|
// Valid pubkeys are either 33 or 65 bytes.
|
|
|
|
if len(pop.data) != 33 && len(pop.data) != 65 {
|
2013-06-12 23:35:27 +02:00
|
|
|
return false
|
|
|
|
}
|
|
|
|
}
|
|
|
|
return true
|
|
|
|
}
|
|
|
|
|
2013-11-14 22:05:20 +01:00
|
|
|
// isNullData returns true if the passed script is a null data transaction,
|
|
|
|
// false otherwise.
|
|
|
|
func isNullData(pops []parsedOpcode) bool {
|
|
|
|
// A nulldata transaction is either a single OP_RETURN or an
|
2015-04-29 20:08:56 +02:00
|
|
|
// OP_RETURN SMALLDATA (where SMALLDATA is a data push up to
|
2015-02-28 14:50:38 +01:00
|
|
|
// maxDataCarrierSize bytes).
|
2013-11-14 22:05:20 +01:00
|
|
|
l := len(pops)
|
|
|
|
if l == 1 && pops[0].opcode.value == OP_RETURN {
|
|
|
|
return true
|
|
|
|
}
|
|
|
|
|
|
|
|
return l == 2 &&
|
|
|
|
pops[0].opcode.value == OP_RETURN &&
|
|
|
|
pops[1].opcode.value <= OP_PUSHDATA4 &&
|
2015-02-28 14:50:38 +01:00
|
|
|
len(pops[1].data) <= maxDataCarrierSize
|
2013-11-14 22:05:20 +01:00
|
|
|
}
|
|
|
|
|
2013-06-12 23:35:27 +02:00
|
|
|
// isPushOnly returns true if the script only pushes data, false otherwise.
|
|
|
|
func isPushOnly(pops []parsedOpcode) bool {
|
2015-04-29 20:08:56 +02:00
|
|
|
// NOTE: This function does NOT verify opcodes directly since it is
|
|
|
|
// internal and is only called with parsed opcodes for scripts that did
|
|
|
|
// not have any parse errors. Thus, consensus is properly maintained.
|
|
|
|
|
2013-06-12 23:35:27 +02:00
|
|
|
for _, pop := range pops {
|
2015-04-29 20:08:56 +02:00
|
|
|
// All opcodes up to OP_16 are data push instructions.
|
|
|
|
// NOTE: This does consider OP_RESERVED to be a data push
|
|
|
|
// instruction, but execution of OP_RESERVED will fail anyways
|
|
|
|
// and matches the behavior required by consensus.
|
|
|
|
if pop.opcode.value > OP_16 {
|
2013-06-12 23:35:27 +02:00
|
|
|
return false
|
|
|
|
}
|
|
|
|
}
|
|
|
|
return true
|
|
|
|
}
|
|
|
|
|
2013-09-27 03:34:25 +02:00
|
|
|
// IsPushOnlyScript returns whether or not the passed script only pushes data.
|
2015-04-29 20:08:56 +02:00
|
|
|
//
|
|
|
|
// False will be returned when the script does not parse.
|
2013-09-27 03:34:25 +02:00
|
|
|
func IsPushOnlyScript(script []byte) bool {
|
|
|
|
pops, err := parseScript(script)
|
|
|
|
if err != nil {
|
|
|
|
return false
|
|
|
|
}
|
|
|
|
return isPushOnly(pops)
|
|
|
|
}
|
|
|
|
|
2013-06-12 23:35:27 +02:00
|
|
|
// scriptType returns the type of the script being inspected from the known
|
|
|
|
// standard types.
|
2013-07-05 01:54:55 +02:00
|
|
|
func typeOfScript(pops []parsedOpcode) ScriptClass {
|
2013-06-12 23:35:27 +02:00
|
|
|
if isPubkey(pops) {
|
2013-07-05 01:54:55 +02:00
|
|
|
return PubKeyTy
|
2013-06-12 23:35:27 +02:00
|
|
|
} else if isPubkeyHash(pops) {
|
2013-07-05 01:54:55 +02:00
|
|
|
return PubKeyHashTy
|
2013-06-12 23:35:27 +02:00
|
|
|
} else if isScriptHash(pops) {
|
2013-07-05 01:54:55 +02:00
|
|
|
return ScriptHashTy
|
2013-06-12 23:35:27 +02:00
|
|
|
} else if isMultiSig(pops) {
|
2013-07-05 01:54:55 +02:00
|
|
|
return MultiSigTy
|
2013-11-14 22:05:20 +01:00
|
|
|
} else if isNullData(pops) {
|
|
|
|
return NullDataTy
|
2013-06-12 23:35:27 +02:00
|
|
|
}
|
2013-07-05 01:54:55 +02:00
|
|
|
return NonStandardTy
|
2013-06-12 23:35:27 +02:00
|
|
|
}
|
|
|
|
|
2015-04-29 20:08:56 +02:00
|
|
|
// GetScriptClass returns the class of the script passed.
|
|
|
|
//
|
|
|
|
// NonStandardTy will be returned when the script does not parse.
|
|
|
|
func GetScriptClass(script []byte) ScriptClass {
|
|
|
|
pops, err := parseScript(script)
|
|
|
|
if err != nil {
|
|
|
|
return NonStandardTy
|
|
|
|
}
|
|
|
|
return typeOfScript(pops)
|
2013-06-28 01:46:34 +02:00
|
|
|
}
|
|
|
|
|
|
|
|
// parseScriptTemplate is the same as parseScript but allows the passing of the
|
2015-04-29 20:08:56 +02:00
|
|
|
// template list for testing purposes. When there are parse errors, it returns
|
|
|
|
// the list of parsed opcodes up to the point of failure along with the error.
|
2015-04-21 18:49:59 +02:00
|
|
|
func parseScriptTemplate(script []byte, opcodes *[256]opcode) ([]parsedOpcode, error) {
|
2013-09-25 18:38:20 +02:00
|
|
|
retScript := make([]parsedOpcode, 0, len(script))
|
2013-06-12 23:35:27 +02:00
|
|
|
for i := 0; i < len(script); {
|
|
|
|
instr := script[i]
|
2015-04-21 18:49:59 +02:00
|
|
|
op := opcodes[instr]
|
|
|
|
pop := parsedOpcode{opcode: &op}
|
2015-04-29 20:08:56 +02:00
|
|
|
|
|
|
|
// Parse data out of instruction.
|
2013-06-12 23:35:27 +02:00
|
|
|
switch {
|
2015-04-29 20:08:56 +02:00
|
|
|
// No additional data. Note that some of the opcodes, notably
|
|
|
|
// OP_1NEGATE, OP_0, and OP_[1-16] represent the data
|
|
|
|
// themselves.
|
2013-06-12 23:35:27 +02:00
|
|
|
case op.length == 1:
|
|
|
|
i++
|
2015-04-29 20:08:56 +02:00
|
|
|
|
|
|
|
// Data pushes of specific lengths -- OP_DATA_[1-75].
|
2013-06-12 23:35:27 +02:00
|
|
|
case op.length > 1:
|
|
|
|
if len(script[i:]) < op.length {
|
2014-10-12 23:40:09 +02:00
|
|
|
return retScript, ErrStackShortScript
|
2013-06-12 23:35:27 +02:00
|
|
|
}
|
2015-04-29 20:08:56 +02:00
|
|
|
|
|
|
|
// Slice out the data.
|
2013-06-12 23:35:27 +02:00
|
|
|
pop.data = script[i+1 : i+op.length]
|
|
|
|
i += op.length
|
2015-04-29 20:08:56 +02:00
|
|
|
|
|
|
|
// Data pushes with parsed lengths -- OP_PUSHDATAP{1,2,4}.
|
2013-06-12 23:35:27 +02:00
|
|
|
case op.length < 0:
|
|
|
|
var l uint
|
|
|
|
off := i + 1
|
2014-03-14 21:59:43 +01:00
|
|
|
|
|
|
|
if len(script[off:]) < -op.length {
|
2014-10-12 23:40:09 +02:00
|
|
|
return retScript, ErrStackShortScript
|
2014-03-14 21:59:43 +01:00
|
|
|
}
|
|
|
|
|
|
|
|
// Next -length bytes are little endian length of data.
|
2013-06-12 23:35:27 +02:00
|
|
|
switch op.length {
|
|
|
|
case -1:
|
2014-03-14 21:59:43 +01:00
|
|
|
l = uint(script[off])
|
2013-06-12 23:35:27 +02:00
|
|
|
case -2:
|
2014-03-14 21:59:43 +01:00
|
|
|
l = ((uint(script[off+1]) << 8) |
|
|
|
|
uint(script[off]))
|
2013-06-12 23:35:27 +02:00
|
|
|
case -4:
|
2014-03-14 21:59:43 +01:00
|
|
|
l = ((uint(script[off+3]) << 24) |
|
|
|
|
(uint(script[off+2]) << 16) |
|
|
|
|
(uint(script[off+1]) << 8) |
|
|
|
|
uint(script[off]))
|
2013-06-12 23:35:27 +02:00
|
|
|
default:
|
2013-07-25 16:40:11 +02:00
|
|
|
return retScript,
|
|
|
|
fmt.Errorf("invalid opcode length %d",
|
2013-07-31 02:31:27 +02:00
|
|
|
op.length)
|
2013-06-12 23:35:27 +02:00
|
|
|
}
|
|
|
|
|
2015-04-29 20:08:56 +02:00
|
|
|
// Move offset to beginning of the data.
|
|
|
|
off += -op.length
|
|
|
|
|
2013-10-09 00:21:40 +02:00
|
|
|
// Disallow entries that do not fit script or were
|
|
|
|
// sign extended.
|
2013-10-09 02:27:19 +02:00
|
|
|
if int(l) > len(script[off:]) || int(l) < 0 {
|
2014-10-12 23:40:09 +02:00
|
|
|
return retScript, ErrStackShortScript
|
2013-06-12 23:35:27 +02:00
|
|
|
}
|
2015-04-29 20:08:56 +02:00
|
|
|
|
2013-06-12 23:35:27 +02:00
|
|
|
pop.data = script[off : off+int(l)]
|
|
|
|
i += 1 - op.length + int(l)
|
|
|
|
}
|
2015-04-29 20:08:56 +02:00
|
|
|
|
2013-06-12 23:35:27 +02:00
|
|
|
retScript = append(retScript, pop)
|
|
|
|
}
|
2015-04-29 20:08:56 +02:00
|
|
|
|
2013-06-12 23:35:27 +02:00
|
|
|
return retScript, nil
|
|
|
|
}
|
|
|
|
|
2015-04-29 20:08:56 +02:00
|
|
|
// parseScript preparses the script in bytes into a list of parsedOpcodes while
|
|
|
|
// applying a number of sanity checks.
|
|
|
|
func parseScript(script []byte) ([]parsedOpcode, error) {
|
|
|
|
return parseScriptTemplate(script, &opcodeArray)
|
|
|
|
}
|
|
|
|
|
2013-06-12 23:35:27 +02:00
|
|
|
// unparseScript reversed the action of parseScript and returns the
|
|
|
|
// parsedOpcodes as a list of bytes
|
2013-09-10 17:39:29 +02:00
|
|
|
func unparseScript(pops []parsedOpcode) ([]byte, error) {
|
2013-09-25 18:38:20 +02:00
|
|
|
script := make([]byte, 0, len(pops))
|
2013-06-12 23:35:27 +02:00
|
|
|
for _, pop := range pops {
|
2013-09-10 17:39:29 +02:00
|
|
|
b, err := pop.bytes()
|
|
|
|
if err != nil {
|
|
|
|
return nil, err
|
|
|
|
}
|
|
|
|
script = append(script, b...)
|
2013-06-12 23:35:27 +02:00
|
|
|
}
|
2013-09-10 17:39:29 +02:00
|
|
|
return script, nil
|
2013-06-12 23:35:27 +02:00
|
|
|
}
|
|
|
|
|
2015-04-29 20:08:56 +02:00
|
|
|
// DisasmString formats a disassembled script for one line printing. When the
|
|
|
|
// script fails to parse, the returned string will contain the disassembled
|
|
|
|
// script up to the point the failure occurred along with the string '[error]'
|
|
|
|
// appended. In addition, the reason the script failed to parse is returned
|
|
|
|
// if the caller wants more information about the failure.
|
|
|
|
func DisasmString(buf []byte) (string, error) {
|
|
|
|
disbuf := ""
|
|
|
|
opcodes, err := parseScript(buf)
|
|
|
|
for _, pop := range opcodes {
|
|
|
|
disbuf += pop.print(true) + " "
|
|
|
|
}
|
|
|
|
if disbuf != "" {
|
|
|
|
disbuf = disbuf[:len(disbuf)-1]
|
|
|
|
}
|
|
|
|
if err != nil {
|
|
|
|
disbuf += "[error]"
|
|
|
|
}
|
|
|
|
return disbuf, err
|
|
|
|
}
|
|
|
|
|
2013-06-12 23:35:27 +02:00
|
|
|
// removeOpcode will remove any opcode matching ``opcode'' from the opcode
|
|
|
|
// stream in pkscript
|
|
|
|
func removeOpcode(pkscript []parsedOpcode, opcode byte) []parsedOpcode {
|
2013-09-25 18:38:20 +02:00
|
|
|
retScript := make([]parsedOpcode, 0, len(pkscript))
|
2013-06-12 23:35:27 +02:00
|
|
|
for _, pop := range pkscript {
|
|
|
|
if pop.opcode.value != opcode {
|
|
|
|
retScript = append(retScript, pop)
|
|
|
|
}
|
|
|
|
}
|
|
|
|
return retScript
|
|
|
|
}
|
|
|
|
|
2015-04-29 20:08:56 +02:00
|
|
|
// canonicalPush returns true if the object is either not a push instruction
|
|
|
|
// or the push instruction contained wherein is matches the canonical form
|
|
|
|
// or using the smallest instruction to do the job. False otherwise.
|
|
|
|
func canonicalPush(pop parsedOpcode) bool {
|
|
|
|
opcode := pop.opcode.value
|
|
|
|
data := pop.data
|
|
|
|
dataLen := len(pop.data)
|
|
|
|
if opcode > OP_16 {
|
|
|
|
return true
|
|
|
|
}
|
|
|
|
|
|
|
|
if opcode < OP_PUSHDATA1 && opcode > OP_0 && (dataLen == 1 && data[0] <= 16) {
|
|
|
|
return false
|
|
|
|
}
|
|
|
|
if opcode == OP_PUSHDATA1 && dataLen < OP_PUSHDATA1 {
|
|
|
|
return false
|
|
|
|
}
|
|
|
|
if opcode == OP_PUSHDATA2 && dataLen <= 0xff {
|
|
|
|
return false
|
|
|
|
}
|
|
|
|
if opcode == OP_PUSHDATA4 && dataLen <= 0xffff {
|
|
|
|
return false
|
|
|
|
}
|
|
|
|
return true
|
|
|
|
}
|
|
|
|
|
|
|
|
// removeOpcodeByData will return the script minus any opcodes that would push
|
|
|
|
// the passed data to the stack.
|
2013-06-12 23:35:27 +02:00
|
|
|
func removeOpcodeByData(pkscript []parsedOpcode, data []byte) []parsedOpcode {
|
2013-09-25 18:38:20 +02:00
|
|
|
retScript := make([]parsedOpcode, 0, len(pkscript))
|
2013-06-12 23:35:27 +02:00
|
|
|
for _, pop := range pkscript {
|
2014-03-18 18:54:29 +01:00
|
|
|
if !canonicalPush(pop) || !bytes.Contains(pop.data, data) {
|
2013-06-12 23:35:27 +02:00
|
|
|
retScript = append(retScript, pop)
|
|
|
|
}
|
|
|
|
}
|
|
|
|
return retScript
|
|
|
|
|
|
|
|
}
|
|
|
|
|
2015-04-29 20:08:56 +02:00
|
|
|
// calcSignatureHash will, given a script and hash type for the current script
|
|
|
|
// engine instance, calculate the signature hash to be used for signing and
|
|
|
|
// verification.
|
|
|
|
func calcSignatureHash(script []parsedOpcode, hashType SigHashType, tx *wire.MsgTx, idx int) []byte {
|
|
|
|
// The SigHashSingle signature type signs only the corresponding input
|
|
|
|
// and output (the output with the same index number as the input).
|
|
|
|
//
|
|
|
|
// Since transactions can have more inputs than outputs, this means it
|
|
|
|
// is improper to use SigHashSingle on input indices that don't have a
|
|
|
|
// corresponding output.
|
|
|
|
//
|
|
|
|
// A bug in the original Satoshi client implementation means specifying
|
|
|
|
// an index that is out of range results in a signature hash of 1 (as a
|
|
|
|
// uint256 little endian). The original intent appeared to be to
|
|
|
|
// indicate failure, but unfortunately, it was never checked and thus is
|
|
|
|
// treated as the actual signature hash. This buggy behavior is now
|
|
|
|
// part of the consensus and a hard fork would be required to fix it.
|
|
|
|
//
|
|
|
|
// Due to this, care must be taken by software that creates transactions
|
|
|
|
// which make use of SigHashSingle because it can lead to an extremely
|
|
|
|
// dangerous situation where the invalid inputs will end up signing a
|
|
|
|
// hash of 1. This in turn presents an opportunity for attackers to
|
|
|
|
// cleverly construct transactions which can steal those coins provided
|
|
|
|
// they can reuse signatures.
|
|
|
|
if hashType&sigHashMask == SigHashSingle && idx >= len(tx.TxOut) {
|
|
|
|
var hash wire.ShaHash
|
|
|
|
hash[0] = 0x01
|
|
|
|
return hash[:]
|
|
|
|
}
|
|
|
|
|
|
|
|
// Remove all instances of OP_CODESEPARATOR from the script.
|
2013-06-12 23:35:27 +02:00
|
|
|
script = removeOpcode(script, OP_CODESEPARATOR)
|
|
|
|
|
2015-04-29 20:08:56 +02:00
|
|
|
// Make a deep copy of the transaction, zeroing out the script for all
|
|
|
|
// inputs that are not currently being processed.
|
2013-09-10 17:39:29 +02:00
|
|
|
txCopy := tx.Copy()
|
2013-06-12 23:35:27 +02:00
|
|
|
for i := range txCopy.TxIn {
|
2015-02-05 22:16:39 +01:00
|
|
|
var txIn wire.TxIn
|
2013-06-12 23:35:27 +02:00
|
|
|
txIn = *txCopy.TxIn[i]
|
|
|
|
txCopy.TxIn[i] = &txIn
|
2013-09-10 17:39:29 +02:00
|
|
|
if i == idx {
|
2015-04-29 20:08:56 +02:00
|
|
|
// UnparseScript cannot fail here because removeOpcode
|
2013-09-10 17:39:29 +02:00
|
|
|
// above only returns a valid script.
|
2015-04-29 20:08:56 +02:00
|
|
|
sigScript, _ := unparseScript(script)
|
|
|
|
txCopy.TxIn[idx].SignatureScript = sigScript
|
2013-06-12 23:35:27 +02:00
|
|
|
} else {
|
2015-04-29 20:08:56 +02:00
|
|
|
txCopy.TxIn[i].SignatureScript = nil
|
2013-06-12 23:35:27 +02:00
|
|
|
}
|
|
|
|
}
|
2015-04-29 20:08:56 +02:00
|
|
|
|
|
|
|
// Default behavior has all outputs set up.
|
2013-06-12 23:35:27 +02:00
|
|
|
for i := range txCopy.TxOut {
|
2015-02-05 22:16:39 +01:00
|
|
|
var txOut wire.TxOut
|
2013-06-12 23:35:27 +02:00
|
|
|
txOut = *txCopy.TxOut[i]
|
|
|
|
txCopy.TxOut[i] = &txOut
|
|
|
|
}
|
|
|
|
|
2015-04-29 20:08:56 +02:00
|
|
|
switch hashType & sigHashMask {
|
2013-06-12 23:35:27 +02:00
|
|
|
case SigHashNone:
|
2015-04-29 20:08:56 +02:00
|
|
|
txCopy.TxOut = txCopy.TxOut[0:0] // Empty slice.
|
2013-06-12 23:35:27 +02:00
|
|
|
for i := range txCopy.TxIn {
|
2013-09-10 17:39:29 +02:00
|
|
|
if i != idx {
|
2013-06-12 23:35:27 +02:00
|
|
|
txCopy.TxIn[i].Sequence = 0
|
|
|
|
}
|
|
|
|
}
|
2015-04-29 20:08:56 +02:00
|
|
|
|
2013-06-12 23:35:27 +02:00
|
|
|
case SigHashSingle:
|
2013-07-30 23:45:26 +02:00
|
|
|
// Resize output array to up to and including requested index.
|
2013-09-10 17:39:29 +02:00
|
|
|
txCopy.TxOut = txCopy.TxOut[:idx+1]
|
2015-04-29 20:08:56 +02:00
|
|
|
|
|
|
|
// All but current output get zeroed out.
|
2013-09-10 17:39:29 +02:00
|
|
|
for i := 0; i < idx; i++ {
|
2013-06-12 23:35:27 +02:00
|
|
|
txCopy.TxOut[i].Value = -1
|
2015-04-29 20:08:56 +02:00
|
|
|
txCopy.TxOut[i].PkScript = nil
|
2013-06-12 23:35:27 +02:00
|
|
|
}
|
2015-04-29 20:08:56 +02:00
|
|
|
|
2013-06-12 23:35:27 +02:00
|
|
|
// Sequence on all other inputs is 0, too.
|
|
|
|
for i := range txCopy.TxIn {
|
2013-09-10 17:39:29 +02:00
|
|
|
if i != idx {
|
2013-06-12 23:35:27 +02:00
|
|
|
txCopy.TxIn[i].Sequence = 0
|
|
|
|
}
|
|
|
|
}
|
2015-04-29 20:08:56 +02:00
|
|
|
|
2013-06-12 23:35:27 +02:00
|
|
|
default:
|
2015-04-29 20:08:56 +02:00
|
|
|
// Consensus treats undefined hashtypes like normal SigHashAll
|
|
|
|
// for purposes of hash generation.
|
2013-06-12 23:35:27 +02:00
|
|
|
fallthrough
|
|
|
|
case SigHashOld:
|
|
|
|
fallthrough
|
|
|
|
case SigHashAll:
|
2015-04-29 20:08:56 +02:00
|
|
|
// Nothing special here.
|
2013-06-12 23:35:27 +02:00
|
|
|
}
|
|
|
|
if hashType&SigHashAnyOneCanPay != 0 {
|
2013-09-10 17:39:29 +02:00
|
|
|
txCopy.TxIn = txCopy.TxIn[idx : idx+1]
|
|
|
|
idx = 0
|
2013-06-12 23:35:27 +02:00
|
|
|
}
|
|
|
|
|
2015-04-29 20:08:56 +02:00
|
|
|
// The final hash is the double sha256 of both the serialized modified
|
|
|
|
// transaction and the hash type (encoded as a 4-byte little-endian
|
|
|
|
// value) appended.
|
2013-06-12 23:35:27 +02:00
|
|
|
var wbuf bytes.Buffer
|
2013-08-05 22:08:28 +02:00
|
|
|
txCopy.Serialize(&wbuf)
|
2013-06-12 23:35:27 +02:00
|
|
|
binary.Write(&wbuf, binary.LittleEndian, uint32(hashType))
|
2015-02-05 22:16:39 +01:00
|
|
|
return wire.DoubleSha256(wbuf.Bytes())
|
2013-06-12 23:35:27 +02:00
|
|
|
}
|
|
|
|
|
2015-04-29 20:08:56 +02:00
|
|
|
// asSmallInt returns the passed opcode, which must be true according to
|
|
|
|
// isSmallInt(), as an integer.
|
|
|
|
func asSmallInt(op *opcode) int {
|
|
|
|
if op.value == OP_0 {
|
2013-07-25 15:27:58 +02:00
|
|
|
return 0
|
2013-06-20 19:07:44 +02:00
|
|
|
}
|
|
|
|
|
2015-04-29 20:08:56 +02:00
|
|
|
return int(op.value - (OP_1 - 1))
|
2013-06-20 19:07:44 +02:00
|
|
|
}
|
|
|
|
|
|
|
|
// 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:
|
2013-06-21 02:33:56 +02:00
|
|
|
fallthrough
|
2013-06-20 19:07:44 +02:00
|
|
|
case OP_CHECKSIGVERIFY:
|
|
|
|
nSigs++
|
2014-01-04 22:13:29 +01:00
|
|
|
case OP_CHECKMULTISIG:
|
2013-06-21 02:33:56 +02:00
|
|
|
fallthrough
|
2013-06-20 19:07:44 +02:00
|
|
|
case OP_CHECKMULTISIGVERIFY:
|
|
|
|
// If we are being precise then look for familiar
|
|
|
|
// patterns for multisig, for now all we recognise is
|
2013-06-21 02:33:56 +02:00
|
|
|
// OP_1 - OP_16 to signify the number of pubkeys.
|
2013-06-20 19:07:44 +02:00
|
|
|
// Otherwise, we use the max of 20.
|
|
|
|
if precise && i > 0 &&
|
2013-06-21 02:33:56 +02:00
|
|
|
pops[i-1].opcode.value >= OP_1 &&
|
|
|
|
pops[i-1].opcode.value <= OP_16 {
|
2015-04-29 20:08:56 +02:00
|
|
|
nSigs += asSmallInt(pops[i-1].opcode)
|
2013-06-20 19:07:44 +02:00
|
|
|
} else {
|
|
|
|
nSigs += MaxPubKeysPerMultiSig
|
|
|
|
}
|
|
|
|
default:
|
2015-04-29 20:08:56 +02:00
|
|
|
// Not a sigop.
|
2013-06-20 19:07:44 +02:00
|
|
|
}
|
|
|
|
}
|
|
|
|
|
|
|
|
return nSigs
|
|
|
|
}
|
2013-09-10 17:39:29 +02:00
|
|
|
|
2015-04-29 20:08:56 +02:00
|
|
|
// 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.
|
|
|
|
// If the script fails to parse, then the count up to the point of failure is
|
|
|
|
// returned.
|
|
|
|
func GetSigOpCount(script []byte) int {
|
|
|
|
// Don't check error since parseScript returns the parsed-up-to-error
|
|
|
|
// list of pops.
|
|
|
|
pops, _ := parseScript(script)
|
|
|
|
return getSigOpCount(pops, false)
|
|
|
|
}
|
|
|
|
|
|
|
|
// 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. If the script fails to parse, then the count
|
|
|
|
// up to the point of failure is returned.
|
|
|
|
func GetPreciseSigOpCount(scriptSig, scriptPubKey []byte, bip16 bool) int {
|
|
|
|
// Don't check error since parseScript returns the parsed-up-to-error
|
|
|
|
// list of pops.
|
|
|
|
pops, _ := parseScript(scriptPubKey)
|
|
|
|
|
|
|
|
// Treat non P2SH transactions as normal.
|
|
|
|
if !(bip16 && isScriptHash(pops)) {
|
|
|
|
return getSigOpCount(pops, true)
|
|
|
|
}
|
|
|
|
|
|
|
|
// The public key script is a pay-to-script-hash, so parse the signature
|
|
|
|
// script to get the final item. Scripts that fail to fully parse count
|
|
|
|
// as 0 signature operations.
|
|
|
|
sigPops, err := parseScript(scriptSig)
|
|
|
|
if err != nil {
|
|
|
|
return 0
|
|
|
|
}
|
|
|
|
|
|
|
|
// The signature script must only push data to the stack for P2SH to be
|
|
|
|
// a valid pair, so the signature operation count is 0 when that is not
|
|
|
|
// the case.
|
|
|
|
if !isPushOnly(sigPops) || len(sigPops) == 0 {
|
|
|
|
return 0
|
|
|
|
}
|
|
|
|
|
|
|
|
// The P2SH script is the last item the signature script pushes to the
|
|
|
|
// stack. When the script is empty, there are no signature operations.
|
|
|
|
shScript := sigPops[len(sigPops)-1].data
|
|
|
|
if len(shScript) == 0 {
|
|
|
|
return 0
|
|
|
|
}
|
|
|
|
|
|
|
|
// Parse the P2SH script and don't check the error since parseScript
|
|
|
|
// returns the parsed-up-to-error list of pops and the consensus rules
|
|
|
|
// dictate signature operations are counted up to the first parse
|
|
|
|
// failure.
|
|
|
|
shPops, _ := parseScript(shScript)
|
|
|
|
return getSigOpCount(shPops, true)
|
|
|
|
}
|
|
|
|
|
2014-02-20 18:39:03 +01:00
|
|
|
// payToPubKeyHashScript creates a new script to pay a transaction
|
|
|
|
// output to a 20-byte pubkey hash. It is expected that the input is a valid
|
|
|
|
// hash.
|
2014-12-20 08:34:39 +01:00
|
|
|
func payToPubKeyHashScript(pubKeyHash []byte) ([]byte, error) {
|
2014-02-20 18:42:06 +01:00
|
|
|
return NewScriptBuilder().AddOp(OP_DUP).AddOp(OP_HASH160).
|
|
|
|
AddData(pubKeyHash).AddOp(OP_EQUALVERIFY).AddOp(OP_CHECKSIG).
|
2014-02-20 18:39:03 +01:00
|
|
|
Script()
|
2013-09-10 17:39:29 +02:00
|
|
|
}
|
|
|
|
|
2014-02-20 18:39:03 +01:00
|
|
|
// payToScriptHashScript creates a new script to pay a transaction output to a
|
|
|
|
// script hash. It is expected that the input is a valid hash.
|
2014-12-20 08:34:39 +01:00
|
|
|
func payToScriptHashScript(scriptHash []byte) ([]byte, error) {
|
2014-02-20 18:42:06 +01:00
|
|
|
return NewScriptBuilder().AddOp(OP_HASH160).AddData(scriptHash).
|
2014-02-21 09:09:55 +01:00
|
|
|
AddOp(OP_EQUAL).Script()
|
2014-01-03 20:35:31 +01:00
|
|
|
}
|
|
|
|
|
2014-02-20 19:37:42 +01:00
|
|
|
// payToPubkeyScript creates a new script to pay a transaction output to a
|
|
|
|
// public key. It is expected that the input is a valid pubkey.
|
2014-12-20 08:34:39 +01:00
|
|
|
func payToPubKeyScript(serializedPubKey []byte) ([]byte, error) {
|
2014-02-20 19:37:42 +01:00
|
|
|
return NewScriptBuilder().AddData(serializedPubKey).
|
2014-02-21 09:09:55 +01:00
|
|
|
AddOp(OP_CHECKSIG).Script()
|
2014-02-20 19:37:42 +01:00
|
|
|
}
|
|
|
|
|
2014-01-03 20:35:31 +01:00
|
|
|
// PayToAddrScript creates a new script to pay a transaction output to a the
|
2014-02-20 19:37:42 +01:00
|
|
|
// specified address.
|
2014-01-03 20:35:31 +01:00
|
|
|
func PayToAddrScript(addr btcutil.Address) ([]byte, error) {
|
|
|
|
switch addr := addr.(type) {
|
|
|
|
case *btcutil.AddressPubKeyHash:
|
|
|
|
if addr == nil {
|
|
|
|
return nil, ErrUnsupportedAddress
|
|
|
|
}
|
2014-12-20 08:34:39 +01:00
|
|
|
return payToPubKeyHashScript(addr.ScriptAddress())
|
2014-01-03 20:35:31 +01:00
|
|
|
|
|
|
|
case *btcutil.AddressScriptHash:
|
|
|
|
if addr == nil {
|
|
|
|
return nil, ErrUnsupportedAddress
|
|
|
|
}
|
2014-12-20 08:34:39 +01:00
|
|
|
return payToScriptHashScript(addr.ScriptAddress())
|
2014-02-20 19:37:42 +01:00
|
|
|
|
|
|
|
case *btcutil.AddressPubKey:
|
|
|
|
if addr == nil {
|
|
|
|
return nil, ErrUnsupportedAddress
|
|
|
|
}
|
2014-12-20 08:34:39 +01:00
|
|
|
return payToPubKeyScript(addr.ScriptAddress())
|
2014-01-03 20:35:31 +01:00
|
|
|
}
|
|
|
|
|
|
|
|
return nil, ErrUnsupportedAddress
|
|
|
|
}
|
|
|
|
|
2014-02-21 01:20:24 +01:00
|
|
|
// MultiSigScript returns a valid script for a multisignature redemption where
|
|
|
|
// nrequired of the keys in pubkeys are required to have signed the transaction
|
2015-04-29 20:08:56 +02:00
|
|
|
// for success. An ErrBadNumRequired will be returned if nrequired is larger
|
|
|
|
// than the number of keys provided.
|
2014-02-21 01:20:24 +01:00
|
|
|
func MultiSigScript(pubkeys []*btcutil.AddressPubKey, nrequired int) ([]byte, error) {
|
|
|
|
if len(pubkeys) < nrequired {
|
|
|
|
return nil, ErrBadNumRequired
|
|
|
|
}
|
|
|
|
|
|
|
|
builder := NewScriptBuilder().AddInt64(int64(nrequired))
|
2014-02-21 09:09:55 +01:00
|
|
|
for _, key := range pubkeys {
|
2014-02-21 01:20:24 +01:00
|
|
|
builder.AddData(key.ScriptAddress())
|
|
|
|
}
|
|
|
|
builder.AddInt64(int64(len(pubkeys)))
|
|
|
|
builder.AddOp(OP_CHECKMULTISIG)
|
|
|
|
|
2014-12-20 08:34:39 +01:00
|
|
|
return builder.Script()
|
2014-02-21 01:20:24 +01:00
|
|
|
}
|
|
|
|
|
2013-10-09 01:13:52 +02:00
|
|
|
// expectedInputs returns the number of arguments required by a script.
|
2015-04-29 20:08:56 +02:00
|
|
|
// If the script is of unknown type such that the number can not be determined
|
2014-02-20 18:19:48 +01:00
|
|
|
// then -1 is returned. We are an internal function and thus assume that class
|
2015-04-29 20:08:56 +02:00
|
|
|
// is the real class of pops (and we can thus assume things that were determined
|
|
|
|
// while finding out the type).
|
2013-10-09 01:13:52 +02:00
|
|
|
func expectedInputs(pops []parsedOpcode, class ScriptClass) int {
|
|
|
|
switch class {
|
|
|
|
case PubKeyTy:
|
|
|
|
return 1
|
2015-04-29 20:08:56 +02:00
|
|
|
|
2013-10-09 01:13:52 +02:00
|
|
|
case PubKeyHashTy:
|
|
|
|
return 2
|
2015-04-29 20:08:56 +02:00
|
|
|
|
2013-10-09 01:13:52 +02:00
|
|
|
case ScriptHashTy:
|
2015-04-29 20:08:56 +02:00
|
|
|
// Not including script. That is handled by the caller.
|
2013-10-09 01:13:52 +02:00
|
|
|
return 1
|
2015-04-29 20:08:56 +02:00
|
|
|
|
2013-10-09 01:13:52 +02:00
|
|
|
case MultiSigTy:
|
|
|
|
// Standard multisig has a push a small number for the number
|
2014-03-17 05:07:20 +01:00
|
|
|
// of sigs and number of keys. Check the first push instruction
|
|
|
|
// to see how many arguments are expected. typeOfScript already
|
|
|
|
// checked this so we know it'll be a small int. Also, due to
|
|
|
|
// the original bitcoind bug where OP_CHECKMULTISIG pops an
|
|
|
|
// additional item from the stack, add an extra expected input
|
|
|
|
// for the extra push that is required to compensate.
|
|
|
|
return asSmallInt(pops[0].opcode) + 1
|
2015-04-29 20:08:56 +02:00
|
|
|
|
2013-11-14 22:05:20 +01:00
|
|
|
case NullDataTy:
|
|
|
|
fallthrough
|
2013-10-09 01:13:52 +02:00
|
|
|
default:
|
|
|
|
return -1
|
|
|
|
}
|
|
|
|
}
|
|
|
|
|
2014-10-13 02:39:01 +02:00
|
|
|
// ScriptInfo houses information about a script pair that is determined by
|
|
|
|
// CalcScriptInfo.
|
2013-10-09 01:13:52 +02:00
|
|
|
type ScriptInfo struct {
|
2015-04-29 20:08:56 +02:00
|
|
|
// PkScriptClass is the class of the public key script and is equivalent
|
|
|
|
// to calling GetScriptClass on it.
|
2013-10-09 01:13:52 +02:00
|
|
|
PkScriptClass ScriptClass
|
2014-10-13 02:39:01 +02:00
|
|
|
|
2015-04-29 20:08:56 +02:00
|
|
|
// NumInputs is the number of inputs provided by the public key script.
|
2013-10-09 01:13:52 +02:00
|
|
|
NumInputs int
|
2014-10-13 02:39:01 +02:00
|
|
|
|
2015-04-29 20:08:56 +02:00
|
|
|
// ExpectedInputs is the number of outputs required by the signature
|
|
|
|
// script and any pay-to-script-hash scripts. The number will be -1 if
|
|
|
|
// unknown.
|
2013-10-09 01:13:52 +02:00
|
|
|
ExpectedInputs int
|
2014-10-13 02:39:01 +02:00
|
|
|
|
2015-04-29 20:08:56 +02:00
|
|
|
// SigOps is the number of signature operations in the script pair.
|
2013-10-09 01:13:52 +02:00
|
|
|
SigOps int
|
|
|
|
}
|
|
|
|
|
2015-04-29 20:08:56 +02:00
|
|
|
// CalcScriptInfo returns a structure providing data about the provided script
|
|
|
|
// pair. It will error if the pair is in someway invalid such that 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) {
|
|
|
|
sigPops, err := parseScript(sigScript)
|
2013-10-09 01:13:52 +02:00
|
|
|
if err != nil {
|
|
|
|
return nil, err
|
|
|
|
}
|
|
|
|
|
2015-04-29 20:08:56 +02:00
|
|
|
pkPops, err := parseScript(pkScript)
|
2013-10-09 01:13:52 +02:00
|
|
|
if err != nil {
|
|
|
|
return nil, err
|
|
|
|
}
|
|
|
|
|
2015-04-29 20:08:56 +02:00
|
|
|
// Push only sigScript makes little sense.
|
|
|
|
si := new(ScriptInfo)
|
2013-10-09 01:13:52 +02:00
|
|
|
si.PkScriptClass = typeOfScript(pkPops)
|
|
|
|
|
|
|
|
// Can't have a pkScript that doesn't just push data.
|
|
|
|
if !isPushOnly(sigPops) {
|
2014-10-12 23:40:09 +02:00
|
|
|
return nil, ErrStackNonPushOnly
|
2013-10-09 01:13:52 +02:00
|
|
|
}
|
|
|
|
|
|
|
|
si.ExpectedInputs = expectedInputs(pkPops, si.PkScriptClass)
|
2015-04-29 20:08:56 +02:00
|
|
|
|
|
|
|
// All entries pushed to stack (or are OP_RESERVED and exec will fail).
|
2013-10-09 01:13:52 +02:00
|
|
|
si.NumInputs = len(sigPops)
|
|
|
|
|
2015-04-29 20:08:56 +02:00
|
|
|
// Count sigops taking into account pay-to-script-hash.
|
2013-10-09 01:13:52 +02:00
|
|
|
if si.PkScriptClass == ScriptHashTy && bip16 {
|
2015-04-29 20:08:56 +02:00
|
|
|
// The pay-to-hash-script is the final data push of the
|
|
|
|
// signature script.
|
2013-10-09 01:13:52 +02:00
|
|
|
script := sigPops[len(sigPops)-1].data
|
|
|
|
shPops, err := parseScript(script)
|
|
|
|
if err != nil {
|
|
|
|
return nil, err
|
|
|
|
}
|
|
|
|
|
2015-04-29 20:08:56 +02:00
|
|
|
shInputs := expectedInputs(shPops, typeOfScript(shPops))
|
2013-10-09 01:13:52 +02:00
|
|
|
if shInputs == -1 {
|
|
|
|
si.ExpectedInputs = -1
|
|
|
|
} else {
|
|
|
|
si.ExpectedInputs += shInputs
|
|
|
|
}
|
|
|
|
si.SigOps = getSigOpCount(shPops, true)
|
|
|
|
} else {
|
|
|
|
si.SigOps = getSigOpCount(pkPops, true)
|
|
|
|
}
|
|
|
|
|
|
|
|
return si, nil
|
|
|
|
}
|
2013-11-14 18:14:25 +01:00
|
|
|
|
|
|
|
// CalcMultiSigStats returns the number of public keys and signatures from
|
|
|
|
// a multi-signature transaction script. The passed script MUST already be
|
|
|
|
// known to be a multi-signature script.
|
|
|
|
func CalcMultiSigStats(script []byte) (int, int, error) {
|
|
|
|
pops, err := parseScript(script)
|
|
|
|
if err != nil {
|
|
|
|
return 0, 0, err
|
|
|
|
}
|
|
|
|
|
|
|
|
// A multi-signature script is of the pattern:
|
|
|
|
// NUM_SIGS PUBKEY PUBKEY PUBKEY... NUM_PUBKEYS OP_CHECKMULTISIG
|
|
|
|
// Therefore the number of signatures is the oldest item on the stack
|
|
|
|
// and the number of pubkeys is the 2nd to last. Also, the absolute
|
|
|
|
// minimum for a multi-signature script is 1 pubkey, so at least 4
|
|
|
|
// items must be on the stack per:
|
|
|
|
// OP_1 PUBKEY OP_1 OP_CHECKMULTISIG
|
|
|
|
if len(pops) < 4 {
|
2014-10-12 23:40:09 +02:00
|
|
|
return 0, 0, ErrStackUnderflow
|
2013-11-14 18:14:25 +01:00
|
|
|
}
|
|
|
|
|
2014-02-19 23:17:02 +01:00
|
|
|
numSigs := asSmallInt(pops[0].opcode)
|
|
|
|
numPubKeys := asSmallInt(pops[len(pops)-2].opcode)
|
2013-11-14 18:14:25 +01:00
|
|
|
return numPubKeys, numSigs, nil
|
|
|
|
}
|
2014-05-08 19:14:01 +02:00
|
|
|
|
|
|
|
// PushedData returns an array of byte slices containing any pushed data found
|
|
|
|
// in the passed script. This includes OP_0, but not OP_1 - OP_16.
|
|
|
|
func PushedData(script []byte) ([][]byte, error) {
|
|
|
|
pops, err := parseScript(script)
|
|
|
|
if err != nil {
|
|
|
|
return nil, err
|
|
|
|
}
|
2015-04-29 20:08:56 +02:00
|
|
|
|
2014-05-08 19:14:01 +02:00
|
|
|
var data [][]byte
|
|
|
|
for _, pop := range pops {
|
|
|
|
if pop.data != nil {
|
|
|
|
data = append(data, pop.data)
|
|
|
|
} else if pop.opcode.value == OP_0 {
|
|
|
|
data = append(data, []byte{})
|
|
|
|
}
|
|
|
|
}
|
|
|
|
return data, nil
|
|
|
|
}
|