func mergeScripts(tx *wire.MsgTx, sigHashes *TxSigHashes, sigVersion int, idx int,
	amt int64, pkScript []byte, class ScriptClass, addresses []btcutil.Address,
	nRequired int, stack [][]byte, prevStack [][]byte) ([][]byte, error) {
	switch class {
	case ScriptHashTy:
		return nil, errors.New("cannot merge " + ScriptHashTy.String() + " type")
	case WitnessV0ScriptHashTy:
		return nil, errors.New("cannot merge " + WitnessV0ScriptHashTy.String() + " type")
	case MultiSigTy:
		return mergeMultiSig(tx, sigHashes, sigVersion, idx, amt, pkScript, addresses, nRequired,
			stack, prevStack)
	default:
		if len(stack) > len(prevStack) {
			return stack, nil
		}
		return prevStack, nil
	}
}
mergeScripts merges sigScript and prevScript assuming they are both
partial solutions for pkScript spending output idx of tx. class, addresses
and nrequired are the result of extracting the addresses from pkscript.
The return value is the best effort merging of the two scripts. Calling this
function with addresses, class and nrequired that do not match pkScript is
an error and results in undefined behaviour.
package txscript
import (
	"bytes"
	"errors"
	"fmt"
	"github.com/btcsuite/btcd/btcec"
	"github.com/btcsuite/btcd/chaincfg"
	"github.com/btcsuite/btcd/wire"
	"github.com/btcsuite/btcutil"
)
func RawTxInWitnessSignature(tx *wire.MsgTx, sigHashes *TxSigHashes, idx int,
	amt int64, subScript []byte, hashType SigHashType,
	key *btcec.PrivateKey) ([]byte, error) {
	parsedScript, err := parseScript(subScript)
	if err != nil {
		return nil, fmt.Errorf("cannot parse output script: %v", err)
	}
	hash, err := calcWitnessSignatureHash(parsedScript, sigHashes, hashType, tx,
		idx, amt)
	if err != nil {
		return nil, err
	}
	signature, err := key.Sign(hash)
	if err != nil {
		return nil, fmt.Errorf("cannot sign tx input: %s", err)
	}
	return append(signature.Serialize(), byte(hashType)), nil
}
func WitnessSignature(tx *wire.MsgTx, sigHashes *TxSigHashes, idx int, amt int64,
	subscript []byte, hashType SigHashType,
	privKey *btcec.PrivateKey, compress bool) (wire.TxWitness, error) {
	stack, err := signP2pkh(tx, sigHashes, idx, amt, subscript, 1,
		hashType, privKey, compress)
	if err != nil {
		return nil, err
	}
	return wire.TxWitness(stack), nil
}
func RawTxInSignature(tx *wire.MsgTx, idx int, subScript []byte,
	hashType SigHashType, key *btcec.PrivateKey) ([]byte, error) {
	hash, err := CalcSignatureHash(subScript, hashType, tx, idx)
	if err != nil {
		return nil, err
	}
	signature, err := key.Sign(hash)
	if err != nil {
		return nil, fmt.Errorf("cannot sign tx input: %s", err)
	}
	return append(signature.Serialize(), byte(hashType)), nil
}
func SignatureScript(tx *wire.MsgTx, idx int, subscript []byte, hashType SigHashType, privKey *btcec.PrivateKey, compress bool) ([]byte, error) {
	stack, err := signP2pkh(tx, nil, idx, 0, subscript, 0,
		hashType, privKey, compress)
	if err != nil {
		return nil, err
	}
	builder := NewScriptBuilder()
	for i := 0; i < len(stack); i++ {
		builder.AddData(stack[i])
	}
	return builder.Script()
}
func makeSignature(tx *wire.MsgTx, sigHashes *TxSigHashes, idx int,
	amt int64, subscript []byte, sigVersion int, hashType SigHashType,
	privKey *btcec.PrivateKey, compress bool) ([]byte, error) {
	if sigVersion == 1 {
		if !compress {
			return nil, errors.New("cannot use uncompressed keys with segwit")
		}
		if sigHashes == nil {
			return nil, errors.New("cannot sign segwit outputs without TxSigHashes")
		}
		return RawTxInWitnessSignature(tx, sigHashes, idx, amt, subscript, hashType, privKey)
	}
	return RawTxInSignature(tx, idx, subscript, hashType, privKey)
}
func signP2pkh(tx *wire.MsgTx, sigHashes *TxSigHashes, idx int,
	amt int64, subscript []byte, sigVersion int, hashType SigHashType,
	privKey *btcec.PrivateKey, compress bool) ([][]byte, error) {
	sig, err := makeSignature(tx, sigHashes, idx, amt, subscript, sigVersion,
		hashType, privKey, compress)
	if err != nil {
		return nil, err
	}
	pk := (*btcec.PublicKey)(&privKey.PublicKey)
	stack := make([][]byte, 2)
	stack[0] = sig
	if compress {
		stack[1] = pk.SerializeCompressed()
	} else {
		stack[1] = pk.SerializeUncompressed()
	}
	return stack, nil
}
func signP2pk(tx *wire.MsgTx, sigHashes *TxSigHashes, idx int,
	amt int64, subScript []byte, sigVersion int, hashType SigHashType,
	privKey *btcec.PrivateKey, compress bool) ([][]byte, error) {
	sig, err := makeSignature(tx, sigHashes, idx, amt, subScript, sigVersion,
		hashType, privKey, compress)
	if err != nil {
		return nil, err
	}
	stack := make([][]byte, 1)
	stack[0] = sig
	return stack, nil
}
func signMultiSig(tx *wire.MsgTx, sigHashes *TxSigHashes, idx int,
	amt int64, subScript []byte, sigVersion int, hashType SigHashType,
	addresses []btcutil.Address, nRequired int, kdb KeyDB) ([][]byte, bool, error) {
	signed := 0
	stack := make([][]byte, 1)
	stack[0] = nil
	for _, addr := range addresses {
		key, compressed, err := kdb.GetKey(addr)
		if err != nil {
			continue
		}
		sig, err := makeSignature(tx, sigHashes, idx, amt, subScript, sigVersion,
			hashType, key, compressed)
		if err != nil {
			return nil, false, err
		}
		stack = append(stack, sig)
		signed++
		if signed == nRequired {
			break
		}
	}
	return stack, signed == nRequired, nil
}
func sign(chainParams *chaincfg.Params, tx *wire.MsgTx, sigHashes *TxSigHashes, idx int,
	amt int64, subScript []byte, sigVersion int, hashType SigHashType,
	kdb KeyDB, sdb ScriptDB) ([][]byte, ScriptClass, []btcutil.Address, int, error) {
	class, addresses, nrequired, err := ExtractPkScriptAddrs(subScript,
		chainParams)
	if err != nil {
		return nil, NonStandardTy, nil, 0, err
	}
	switch class {
	case PubKeyTy:
		key, compressed, err := kdb.GetKey(addresses[0])
		if err != nil {
			return nil, class, nil, 0, err
		}
		stack, err := signP2pk(tx, sigHashes, idx, amt, subScript, sigVersion,
			hashType, key, compressed)
		if err != nil {
			return nil, class, nil, 0, err
		}
		return stack, class, addresses, nrequired, nil
	case PubKeyHashTy:
		key, compressed, err := kdb.GetKey(addresses[0])
		if err != nil {
			return nil, class, nil, 0, err
		}
		stack, err := signP2pkh(tx, sigHashes, idx, amt, subScript, sigVersion,
			hashType, key, compressed)
		if err != nil {
			return nil, class, nil, 0, err
		}
		return stack, class, addresses, nrequired, nil
	case WitnessV0PubKeyHashTy:
		return [][]byte{addresses[0].ScriptAddress()}, class, addresses, nrequired, nil
	case ScriptHashTy, WitnessV0ScriptHashTy:
		script, err := sdb.GetScript(addresses[0])
		if err != nil {
			return nil, class, nil, 0, err
		}
		return [][]byte{script}, class, addresses, nrequired, nil
	case MultiSigTy:
		stack, _, err := signMultiSig(tx, sigHashes, idx, amt, subScript, sigVersion,
			hashType, addresses, nrequired, kdb)
		if err != nil {
			return nil, class, nil, 0, err
		}
		return stack, class, addresses, nrequired, nil
	case NullDataTy:
		return nil, class, nil, 0,
			errors.New("can't sign NULLDATA transactions")
	default:
		return nil, class, nil, 0,
			errors.New("can't sign unknown transactions")
	}
}