remove memory pressure from parseScript

This commit is contained in:
Brannon King 2021-08-09 08:40:03 -04:00
parent 9aa4259382
commit ccfa7af546
11 changed files with 160 additions and 64 deletions

View file

@ -65,11 +65,13 @@ func (h *handler) handleTxIns(ct *claimtrie.ClaimTrie) error {
if e == nil {
return errors.Errorf("missing input in view for %s", op.String())
}
cs, err := txscript.DecodeClaimScript(e.pkScript)
cs, closer, err := txscript.DecodeClaimScript(e.pkScript)
if err == txscript.ErrNotClaimScript {
closer()
continue
}
if err != nil {
closer()
return err
}
@ -89,6 +91,7 @@ func (h *handler) handleTxIns(ct *claimtrie.ClaimTrie) error {
copy(id[:], cs.ClaimID())
err = ct.SpendSupport(name, op, id)
}
closer()
if err != nil {
return errors.Wrapf(err, "handleTxIns")
}
@ -99,11 +102,13 @@ func (h *handler) handleTxIns(ct *claimtrie.ClaimTrie) error {
func (h *handler) handleTxOuts(ct *claimtrie.ClaimTrie) error {
for i, txOut := range h.tx.MsgTx().TxOut {
op := *wire.NewOutPoint(h.tx.Hash(), uint32(i))
cs, err := txscript.DecodeClaimScript(txOut.PkScript)
cs, closer, err := txscript.DecodeClaimScript(txOut.PkScript)
if err == txscript.ErrNotClaimScript {
closer()
continue
}
if err != nil {
closer()
return err
}
@ -127,12 +132,14 @@ func (h *handler) handleTxOuts(ct *claimtrie.ClaimTrie) error {
if !bytes.Equal(h.spent[id.Key()], normName) {
node.LogOnce(fmt.Sprintf("Invalid update operation: name or ID mismatch at %d for: %s, %s",
ct.Height(), normName, id.String()))
closer()
continue
}
delete(h.spent, id.Key())
err = ct.UpdateClaim(name, op, amt, id)
}
closer()
if err != nil {
return errors.Wrapf(err, "handleTxOuts")
}

View file

@ -86,6 +86,7 @@ out:
txIn.PreviousOutPoint, err, witness,
sigScript, pkScript)
err := ruleError(ErrScriptMalformed, str)
vm.Close()
v.sendResult(err)
break out
}
@ -100,11 +101,13 @@ out:
txIn.PreviousOutPoint, err, witness,
sigScript, pkScript)
err := ruleError(ErrScriptValidation, str)
vm.Close()
v.sendResult(err)
break out
}
// Validation succeeded.
vm.Close()
v.sendResult(nil)
case <-v.quitChan:

View file

@ -343,8 +343,9 @@ func (cb *chainConverter) processBlock() {
for _, txIn := range tx.MsgTx().TxIn {
prevOutpoint := txIn.PreviousOutPoint
pkScript := utxoPubScripts[prevOutpoint]
cs, err := txscript.DecodeClaimScript(pkScript)
cs, closer, err := txscript.DecodeClaimScript(pkScript)
if err == txscript.ErrNotClaimScript {
closer()
continue
}
if err != nil {
@ -371,12 +372,14 @@ func (cb *chainConverter) processBlock() {
}
changes = append(changes, chg)
closer()
}
op := *wire.NewOutPoint(tx.Hash(), 0)
for i, txOut := range tx.MsgTx().TxOut {
cs, err := txscript.DecodeClaimScript(txOut.PkScript)
cs, closer, err := txscript.DecodeClaimScript(txOut.PkScript)
if err == txscript.ErrNotClaimScript {
closer()
continue
}
@ -401,6 +404,7 @@ func (cb *chainConverter) processBlock() {
copy(chg.ClaimID[:], cs.ClaimID())
}
changes = append(changes, chg)
closer()
}
}
cb.stat.blocksProcessed++

View file

@ -323,7 +323,8 @@ func lookupValue(s *rpcServer, outpoint wire.OutPoint, includeValues *bool) (str
}
txo := msgTx.TxOut[outpoint.Index]
cs, err := txscript.DecodeClaimScript(txo.PkScript)
cs, closer, err := txscript.DecodeClaimScript(txo.PkScript)
defer closer()
if err != nil {
context := "Failed to decode the claim script"
return "", "", internalRPCError(err.Error(), context)

View file

@ -136,6 +136,20 @@ type Engine struct {
witnessVersion int
witnessProgram []byte
inputAmount int64
cleanups []func()
}
func (vm *Engine) Close() {
for i := range vm.cleanups {
vm.cleanups[i]()
}
vm.cleanups = nil
vm.scripts = nil
vm.savedFirstStack = nil
vm.witnessProgram = nil
vm.condStack = nil
vm.sigCache = nil
vm.hashCache = nil
}
// hasFlag returns whether the script engine instance has the passed flag set.
@ -269,8 +283,9 @@ func (vm *Engine) verifyWitnessProgram(witness [][]byte) error {
if err != nil {
return err
}
pops, err := parseScript(pkScript)
pops, closer, err := parseScript(pkScript)
if err != nil {
closer()
return err
}
@ -278,6 +293,7 @@ func (vm *Engine) verifyWitnessProgram(witness [][]byte) error {
// append the pkScript generated above as the next
// script to execute.
vm.scripts = append(vm.scripts, pops)
vm.cleanups = append(vm.cleanups, closer)
vm.SetStack(witness)
case payToWitnessScriptHashDataSize: // P2WSH
@ -310,8 +326,9 @@ func (vm *Engine) verifyWitnessProgram(witness [][]byte) error {
// With all the validity checks passed, parse the
// script into individual op-codes so w can execute it
// as the next script.
pops, err := parseScript(witnessScript)
pops, closer, err := parseScript(witnessScript)
if err != nil {
closer()
return err
}
@ -319,6 +336,7 @@ func (vm *Engine) verifyWitnessProgram(witness [][]byte) error {
// the stack, and set the witnessScript to be the next
// script executed.
vm.scripts = append(vm.scripts, pops)
vm.cleanups = append(vm.cleanups, closer)
vm.SetStack(witness[:len(witness)-1])
default:
@ -492,11 +510,13 @@ func (vm *Engine) Step() (done bool, err error) {
}
script := vm.savedFirstStack[len(vm.savedFirstStack)-1]
pops, err := parseScript(script)
pops, closer, err := parseScript(script)
if err != nil {
closer()
return false, err
}
vm.scripts = append(vm.scripts, pops)
vm.cleanups = append(vm.cleanups, closer)
// Set stack to be the stack from first script minus the
// script itself
@ -910,10 +930,13 @@ func NewEngine(scriptPubKey []byte, tx *wire.MsgTx, txIdx int, flags ScriptFlags
return nil, scriptError(ErrScriptTooBig, str)
}
var err error
vm.scripts[i], err = parseScript(scr)
var closer func()
vm.scripts[i], closer, err = parseScript(scr)
if err != nil {
closer()
return nil, err
}
vm.cleanups = append(vm.cleanups, closer)
}
// Advance the program counter to the public key script if the signature

View file

@ -55,27 +55,27 @@ func UpdateClaimScript(name string, claimID []byte, value string) ([]byte, error
}
// DecodeClaimScript ...
func DecodeClaimScript(script []byte) (*ClaimScript, error) {
func DecodeClaimScript(script []byte) (*ClaimScript, func(), error) {
if len(script) == 0 {
return nil, ErrNotClaimScript
return nil, func() {}, ErrNotClaimScript
}
op := script[0]
if op != OP_CLAIMNAME && op != OP_SUPPORTCLAIM && op != OP_UPDATECLAIM {
return nil, ErrNotClaimScript
return nil, func() {}, ErrNotClaimScript
}
pops, err := parseScript(script)
pops, closer, err := parseScript(script)
if err != nil {
return nil, err
return nil, closer, err
}
if isClaimName(pops) || isSupportClaim(pops) || isUpdateClaim(pops) {
cs := &ClaimScript{op: op, pops: pops}
if cs.Size() > MaxClaimScriptSize {
log.Infof("claim script of %d bytes is larger than %d", cs.Size(), MaxClaimScriptSize)
return nil, ErrInvalidClaimScript
return nil, closer, ErrInvalidClaimScript
}
return cs, nil
return cs, closer, nil
}
return nil, ErrInvalidClaimScript
return nil, closer, ErrInvalidClaimScript
}
// ClaimScript ...
@ -132,7 +132,8 @@ func (cs *ClaimScript) Size() int {
// StripClaimScriptPrefix ...
func StripClaimScriptPrefix(script []byte) []byte {
cs, err := DecodeClaimScript(script)
cs, closer, err := DecodeClaimScript(script)
defer closer()
if err != nil {
return script
}
@ -141,7 +142,8 @@ func StripClaimScriptPrefix(script []byte) []byte {
// claimNameSize returns size of the name in a claim script or 0 if script is not a claimtrie transaction.
func claimNameSize(script []byte) int {
cs, err := DecodeClaimScript(script)
cs, closer, err := DecodeClaimScript(script)
defer closer()
if err != nil {
return 0
}
@ -200,7 +202,8 @@ func isUpdateClaim(pops []parsedOpcode) bool {
const illegalChars = "=&#:*$@%?/;\\\b\n\t\r\x00"
func AllClaimsAreSane(script []byte, enforceSoftFork bool) error {
cs, err := DecodeClaimScript(script)
cs, closer, err := DecodeClaimScript(script)
defer closer()
if err != ErrNotClaimScript {
if err != nil {
return fmt.Errorf("invalid claim script: %s", err.Error())

View file

@ -12,12 +12,14 @@ func TestCreationParseLoopClaim(t *testing.T) {
claim, err := ClaimNameScript("tester", "value")
r.NoError(err)
parsed, err := parseScript(claim)
parsed, closer, err := parseScript(claim)
defer closer()
r.NoError(err)
r.True(isClaimName(parsed))
r.False(isSupportClaim(parsed))
r.False(isUpdateClaim(parsed))
script, err := DecodeClaimScript(claim)
script, closer2, err := DecodeClaimScript(claim)
defer closer2()
r.NoError(err)
r.Equal([]byte("tester"), script.Name())
r.Equal([]byte("value"), script.Value())
@ -30,12 +32,14 @@ func TestCreationParseLoopUpdate(t *testing.T) {
claimID := []byte("12345123451234512345")
claim, err := UpdateClaimScript("tester", claimID, "value")
r.NoError(err)
parsed, err := parseScript(claim)
parsed, closer, err := parseScript(claim)
defer closer()
r.NoError(err)
r.False(isSupportClaim(parsed))
r.False(isClaimName(parsed))
r.True(isUpdateClaim(parsed))
script, err := DecodeClaimScript(claim)
script, closer2, err := DecodeClaimScript(claim)
defer closer2()
r.NoError(err)
r.Equal([]byte("tester"), script.Name())
@ -50,12 +54,15 @@ func TestCreationParseLoopSupport(t *testing.T) {
claimID := []byte("12345123451234512345")
claim, err := SupportClaimScript("tester", claimID, []byte("value"))
r.NoError(err)
parsed, err := parseScript(claim)
parsed, closer, err := parseScript(claim)
defer closer()
r.NoError(err)
r.True(isSupportClaim(parsed))
r.False(isClaimName(parsed))
r.False(isUpdateClaim(parsed))
script, err := DecodeClaimScript(claim)
script, closer2, err := DecodeClaimScript(claim)
defer closer2()
r.NoError(err)
r.Equal([]byte("tester"), script.Name())
@ -64,7 +71,8 @@ func TestCreationParseLoopSupport(t *testing.T) {
claim, err = SupportClaimScript("tester", claimID, nil)
r.NoError(err)
script, err = DecodeClaimScript(claim)
script, closer, err = DecodeClaimScript(claim)
defer closer()
r.NoError(err)
r.Equal([]byte("tester"), script.Name())

View file

@ -211,7 +211,8 @@ func computeNonWitnessPkScript(sigScript []byte) (PkScript, error) {
// The redeem script will always be the last data push of the
// signature script, so we'll parse the script into opcodes to
// obtain it.
parsedOpcodes, err := parseScript(sigScript)
parsedOpcodes, closer, err := parseScript(sigScript)
defer closer()
if err != nil {
return PkScript{}, err
}

View file

@ -8,6 +8,7 @@ import (
"bytes"
"encoding/binary"
"fmt"
"sync"
"time"
"github.com/btcsuite/btcd/chaincfg/chainhash"
@ -63,7 +64,8 @@ func isScriptHash(pops []parsedOpcode) bool {
// IsPayToScriptHash returns true if the script is in the standard
// pay-to-script-hash (P2SH) format, false otherwise.
func IsPayToScriptHash(script []byte) bool {
pops, err := parseScript(script)
pops, closer, err := parseScript(script)
defer closer()
if err != nil {
return false
}
@ -81,7 +83,8 @@ func isWitnessScriptHash(pops []parsedOpcode) bool {
// IsPayToWitnessScriptHash returns true if the is in the standard
// pay-to-witness-script-hash (P2WSH) format, false otherwise.
func IsPayToWitnessScriptHash(script []byte) bool {
pops, err := parseScript(script)
pops, closer, err := parseScript(script)
defer closer()
if err != nil {
return false
}
@ -91,7 +94,8 @@ func IsPayToWitnessScriptHash(script []byte) bool {
// IsPayToWitnessPubKeyHash returns true if the is in the standard
// pay-to-witness-pubkey-hash (P2WKH) format, false otherwise.
func IsPayToWitnessPubKeyHash(script []byte) bool {
pops, err := parseScript(script)
pops, closer, err := parseScript(script)
defer closer()
if err != nil {
return false
}
@ -119,7 +123,8 @@ func IsWitnessProgram(script []byte) bool {
return false
}
pops, err := parseScript(script)
pops, closer, err := parseScript(script)
defer closer()
if err != nil {
return false
}
@ -143,7 +148,8 @@ func isWitnessProgram(pops []parsedOpcode) bool {
// ExtractWitnessProgramInfo attempts to extract the witness program version,
// as well as the witness program itself from the passed script.
func ExtractWitnessProgramInfo(script []byte) (int, []byte, error) {
pops, err := parseScript(script)
pops, closer, err := parseScript(script)
defer closer()
if err != nil {
return 0, nil, err
}
@ -184,18 +190,25 @@ func isPushOnly(pops []parsedOpcode) bool {
//
// False will be returned when the script does not parse.
func IsPushOnlyScript(script []byte) bool {
pops, err := parseScript(script)
pops, closer, err := parseScript(script)
defer closer()
if err != nil {
return false
}
return isPushOnly(pops)
}
var parsedPool = sync.Pool{
New: func() interface{} {
return make([]parsedOpcode, 0, 8)
},
}
// parseScriptTemplate is the same as parseScript but allows the passing of the
// 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.
func parseScriptTemplate(script []byte, opcodes *[256]opcode) ([]parsedOpcode, error) {
retScript := make([]parsedOpcode, 0, len(script))
func parseScriptTemplate(script []byte, opcodes *[256]opcode) ([]parsedOpcode, func(), error) {
retScript := parsedPool.Get().([]parsedOpcode)
var err error
for i := 0; i < len(script); {
instr := script[i]
@ -203,13 +216,19 @@ func parseScriptTemplate(script []byte, opcodes *[256]opcode) ([]parsedOpcode, e
pop := parsedOpcode{opcode: op}
i, err = pop.checkParseableInScript(script, i)
if err != nil {
return retScript, err
break
}
retScript = append(retScript, pop)
}
return retScript, nil
return retScript, func() {
for i := range retScript {
retScript[i].data = nil
retScript[i].opcode = nil
}
parsedPool.Put(retScript[:0])
}, err
}
// checkScriptTemplateParseable is the same as parseScriptTemplate but does not
@ -252,7 +271,7 @@ func checkScriptTemplateParseable(script []byte, opcodes *[256]opcode) (*byte, e
// parseScript preparses the script in bytes into a list of parsedOpcodes while
// applying a number of sanity checks.
func parseScript(script []byte) ([]parsedOpcode, error) {
func parseScript(script []byte) ([]parsedOpcode, func(), error) {
return parseScriptTemplate(script, &opcodeArray)
}
@ -277,7 +296,8 @@ func unparseScript(pops []parsedOpcode) ([]byte, error) {
// if the caller wants more information about the failure.
func DisasmString(buf []byte) (string, error) {
var disbuf bytes.Buffer
opcodes, err := parseScript(buf)
opcodes, closer, err := parseScript(buf)
defer closer()
for _, pop := range opcodes {
disbuf.WriteString(pop.print(true))
disbuf.WriteByte(' ')
@ -517,7 +537,8 @@ func calcWitnessSignatureHash(subScript []parsedOpcode, sigHashes *TxSigHashes,
func CalcWitnessSigHash(script []byte, sigHashes *TxSigHashes, hType SigHashType,
tx *wire.MsgTx, idx int, amt int64) ([]byte, error) {
parsedScript, err := parseScript(script)
parsedScript, closer, err := parseScript(script)
defer closer()
if err != nil {
return nil, fmt.Errorf("cannot parse output script: %v", err)
}
@ -558,7 +579,8 @@ func shallowCopyTx(tx *wire.MsgTx) wire.MsgTx {
// engine instance, calculate the signature hash to be used for signing and
// verification.
func CalcSignatureHash(script []byte, hashType SigHashType, tx *wire.MsgTx, idx int) ([]byte, error) {
parsedScript, err := parseScript(script)
parsedScript, closer, err := parseScript(script)
defer closer()
if err != nil {
return nil, fmt.Errorf("cannot parse output script: %v", err)
}
@ -711,7 +733,8 @@ func getSigOpCount(pops []parsedOpcode, precise bool) int {
func GetSigOpCount(script []byte) int {
// Don't check error since parseScript returns the parsed-up-to-error
// list of pops.
pops, _ := parseScript(script)
pops, closer, _ := parseScript(script)
defer closer()
return getSigOpCount(pops, false)
}
@ -723,7 +746,8 @@ func GetSigOpCount(script []byte) int {
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)
pops, closer1, _ := parseScript(scriptPubKey)
defer closer1()
// Treat non P2SH transactions as normal.
if !(bip16 && isScriptHash(pops)) {
@ -733,7 +757,9 @@ func GetPreciseSigOpCount(scriptSig, scriptPubKey []byte, bip16 bool) int {
// 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)
sigPops, closer2, err := parseScript(scriptSig)
defer closer2()
if err != nil {
return 0
}
@ -756,7 +782,9 @@ func GetPreciseSigOpCount(scriptSig, scriptPubKey []byte, bip16 bool) int {
// 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)
shPops, closer3, _ := parseScript(shScript)
defer closer3()
return getSigOpCount(shPops, true)
}
@ -776,7 +804,8 @@ func GetWitnessSigOpCount(sigScript, pkScript []byte, witness wire.TxWitness) in
// Next, we'll check the sigScript to see if this is a nested p2sh
// witness program. This is a case wherein the sigScript is actually a
// datapush of a p2wsh witness program.
sigPops, err := parseScript(sigScript)
sigPops, closer, err := parseScript(sigScript)
defer closer()
if err != nil {
return 0
}
@ -811,7 +840,8 @@ func getWitnessSigOps(pkScript []byte, witness wire.TxWitness) int {
len(witness) > 0:
witnessScript := witness[len(witness)-1]
pops, _ := parseScript(witnessScript)
pops, closer, _ := parseScript(witnessScript)
defer closer()
return getSigOpCount(pops, true)
}
}

View file

@ -22,7 +22,8 @@ func RawTxInWitnessSignature(tx *wire.MsgTx, sigHashes *TxSigHashes, idx int,
amt int64, subScript []byte, hashType SigHashType,
key *btcec.PrivateKey) ([]byte, error) {
parsedScript, err := parseScript(subScript)
parsedScript, closer, err := parseScript(subScript)
defer closer()
if err != nil {
return nil, fmt.Errorf("cannot parse output script: %v", err)
}
@ -232,11 +233,13 @@ func mergeScripts(chainParams *chaincfg.Params, tx *wire.MsgTx, idx int,
case ScriptHashTy:
// Remove the last push in the script and then recurse.
// this could be a lot less inefficient.
sigPops, err := parseScript(sigScript)
sigPops, closer1, err := parseScript(sigScript)
defer closer1()
if err != nil || len(sigPops) == 0 {
return prevScript
}
prevPops, err := parseScript(prevScript)
prevPops, closer2, err := parseScript(prevScript)
defer closer2()
if err != nil || len(prevPops) == 0 {
return sigScript
}
@ -293,14 +296,17 @@ func mergeMultiSig(tx *wire.MsgTx, idx int, addresses []btcutil.Address,
// This is an internal only function and we already parsed this script
// as ok for multisig (this is how we got here), so if this fails then
// all assumptions are broken and who knows which way is up?
pkPops, _ := parseScript(pkScript)
pkPops, closer1, _ := parseScript(pkScript)
defer closer1()
sigPops, err := parseScript(sigScript)
sigPops, closer2, err := parseScript(sigScript)
defer closer2()
if err != nil || len(sigPops) == 0 {
return prevScript
}
prevPops, err := parseScript(prevScript)
prevPops, closer3, err := parseScript(prevScript)
defer closer3()
if err != nil || len(prevPops) == 0 {
return sigScript
}

View file

@ -183,7 +183,8 @@ func typeOfScript(pops []parsedOpcode) ScriptClass {
//
// NonStandardTy will be returned when the script does not parse.
func GetScriptClass(script []byte) ScriptClass {
pops, err := parseScript(script)
pops, closer, err := parseScript(script)
defer closer()
if err != nil {
return NonStandardTy
}
@ -273,12 +274,14 @@ type ScriptInfo struct {
func CalcScriptInfo(sigScript, pkScript []byte, witness wire.TxWitness,
bip16, segwit bool) (*ScriptInfo, error) {
sigPops, err := parseScript(sigScript)
sigPops, closer1, err := parseScript(sigScript)
defer closer1()
if err != nil {
return nil, err
}
pkPops, err := parseScript(pkScript)
pkPops, closer2, err := parseScript(pkScript)
defer closer2()
if err != nil {
return nil, err
}
@ -301,7 +304,8 @@ func CalcScriptInfo(sigScript, pkScript []byte, witness wire.TxWitness,
// The pay-to-hash-script is the final data push of the
// signature script.
script := sigPops[len(sigPops)-1].data
shPops, err := parseScript(script)
shPops, closer3, err := parseScript(script)
defer closer3()
if err != nil {
return nil, err
}
@ -332,7 +336,8 @@ func CalcScriptInfo(sigScript, pkScript []byte, witness wire.TxWitness,
// Extract the pushed witness program from the sigScript so we
// can determine the number of expected inputs.
pkPops, _ := parseScript(sigScript[1:])
pkPops, closer4, _ := parseScript(sigScript[1:])
defer closer4()
shInputs := expectedInputs(pkPops, typeOfScript(pkPops))
if shInputs == -1 {
si.ExpectedInputs = -1
@ -351,7 +356,8 @@ func CalcScriptInfo(sigScript, pkScript []byte, witness wire.TxWitness,
// The witness script is the final element of the witness
// stack.
witnessScript := witness[len(witness)-1]
pops, _ := parseScript(witnessScript)
pops, closer5, _ := parseScript(witnessScript)
defer closer5()
shInputs := expectedInputs(pops, typeOfScript(pops))
if shInputs == -1 {
@ -378,7 +384,8 @@ func CalcScriptInfo(sigScript, pkScript []byte, witness wire.TxWitness,
// 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)
pops, closer, err := parseScript(script)
defer closer()
if err != nil {
return 0, 0, err
}
@ -519,7 +526,8 @@ func MultiSigScript(pubkeys []*btcutil.AddressPubKey, nrequired int) ([]byte, er
// 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)
pops, closer, err := parseScript(script)
defer closer()
if err != nil {
return nil, err
}
@ -547,7 +555,8 @@ func ExtractPkScriptAddrs(pkScript []byte, chainParams *chaincfg.Params) (Script
// No valid addresses or required signatures if the script doesn't
// parse.
pops, err := parseScript(stripped)
pops, closer, err := parseScript(stripped)
defer closer()
if err != nil {
return NonStandardTy, nil, 0, err
}
@ -669,7 +678,8 @@ type AtomicSwapDataPushes struct {
// This function is only defined in the txscript package due to API limitations
// which prevent callers using txscript to parse nonstandard scripts.
func ExtractAtomicSwapDataPushes(version uint16, pkScript []byte) (*AtomicSwapDataPushes, error) {
pops, err := parseScript(pkScript)
pops, closer, err := parseScript(pkScript)
defer closer()
if err != nil {
return nil, err
}