From 3fc244430933e69c079abd7c7f90d0be0d14fc6d Mon Sep 17 00:00:00 2001
From: Dave Collins <davec@conformal.com>
Date: Mon, 20 Apr 2015 16:50:25 -0500
Subject: [PATCH] txscript: Separate signing code.

This commit separate the transaction signing code into sign.go and the
related tests into sign_test.go.
---
 txscript/script.go      |  397 ---------
 txscript/script_test.go | 1700 --------------------------------------
 txscript/sign.go        |  411 ++++++++++
 txscript/sign_test.go   | 1714 +++++++++++++++++++++++++++++++++++++++
 4 files changed, 2125 insertions(+), 2097 deletions(-)
 create mode 100644 txscript/sign.go
 create mode 100644 txscript/sign_test.go

diff --git a/txscript/script.go b/txscript/script.go
index 22ec65dea..e611579b3 100644
--- a/txscript/script.go
+++ b/txscript/script.go
@@ -13,7 +13,6 @@ import (
 	"time"
 
 	"github.com/btcsuite/btcd/btcec"
-	"github.com/btcsuite/btcd/chaincfg"
 	"github.com/btcsuite/btcd/wire"
 	"github.com/btcsuite/btcutil"
 )
@@ -770,402 +769,6 @@ func MultiSigScript(pubkeys []*btcutil.AddressPubKey, nrequired int) ([]byte, er
 	return builder.Script()
 }
 
-// SignatureScript creates an input signature script for tx to spend
-// BTC sent from a previous output to the owner of privKey. tx must
-// include all transaction inputs and outputs, however txin scripts are
-// allowed to be filled or empty. The returned script is calculated to
-// be used as the idx'th txin sigscript for tx. subscript is the PkScript
-// of the previous output being used as the idx'th input. privKey is
-// serialized in either a compressed or uncompressed format based on
-// compress. This format must match the same format used to generate
-// the payment address, or the script validation will fail.
-func SignatureScript(tx *wire.MsgTx, idx int, subscript []byte, hashType SigHashType, privKey *btcec.PrivateKey, compress bool) ([]byte, error) {
-	sig, err := RawTxInSignature(tx, idx, subscript, hashType, privKey)
-	if err != nil {
-		return nil, err
-	}
-
-	pk := (*btcec.PublicKey)(&privKey.PublicKey)
-	var pkData []byte
-	if compress {
-		pkData = pk.SerializeCompressed()
-	} else {
-		pkData = pk.SerializeUncompressed()
-	}
-
-	return NewScriptBuilder().AddData(sig).AddData(pkData).Script()
-}
-
-// RawTxInSignature returns the serialized ECDSA signature for the input
-// idx of the given transaction, with hashType appended to it.
-func RawTxInSignature(tx *wire.MsgTx, idx int, 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 := calcScriptHash(parsedScript, hashType, tx, idx)
-	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 p2pkSignatureScript(tx *wire.MsgTx, idx int, subScript []byte, hashType SigHashType, privKey *btcec.PrivateKey) ([]byte, error) {
-	sig, err := RawTxInSignature(tx, idx, subScript, hashType, privKey)
-	if err != nil {
-		return nil, err
-	}
-
-	return NewScriptBuilder().AddData(sig).Script()
-}
-
-// signMultiSig signs as many of the outputs in the provided multisig script as
-// possible. It returns the generated script and a boolean if the script fulfils
-// the contract (i.e. nrequired signatures are provided).  Since it is arguably
-// legal to not be able to sign any of the outputs, no error is returned.
-func signMultiSig(tx *wire.MsgTx, idx int, subScript []byte, hashType SigHashType,
-	addresses []btcutil.Address, nRequired int, kdb KeyDB) ([]byte, bool) {
-	// We start with a single OP_FALSE to work around the (now standard)
-	// but in the reference implementation that causes a spurious pop at
-	// the end of OP_CHECKMULTISIG.
-	builder := NewScriptBuilder().AddOp(OP_FALSE)
-	signed := 0
-	for _, addr := range addresses {
-		key, _, err := kdb.GetKey(addr)
-		if err != nil {
-			continue
-		}
-		sig, err := RawTxInSignature(tx, idx, subScript, hashType, key)
-		if err != nil {
-			continue
-		}
-
-		builder.AddData(sig)
-		signed++
-		if signed == nRequired {
-			break
-		}
-
-	}
-
-	script, _ := builder.Script()
-	return script, signed == nRequired
-}
-
-func sign(chainParams *chaincfg.Params, tx *wire.MsgTx, idx int,
-	subScript []byte, 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:
-		// look up key for address
-		key, _, err := kdb.GetKey(addresses[0])
-		if err != nil {
-			return nil, class, nil, 0, err
-		}
-
-		script, err := p2pkSignatureScript(tx, idx, subScript, hashType,
-			key)
-		if err != nil {
-			return nil, class, nil, 0, err
-		}
-
-		return script, class, addresses, nrequired, nil
-	case PubKeyHashTy:
-		// look up key for address
-		key, compressed, err := kdb.GetKey(addresses[0])
-		if err != nil {
-			return nil, class, nil, 0, err
-		}
-
-		script, err := SignatureScript(tx, idx, subScript, hashType,
-			key, compressed)
-		if err != nil {
-			return nil, class, nil, 0, err
-		}
-
-		return script, class, addresses, nrequired, nil
-	case ScriptHashTy:
-		script, err := sdb.GetScript(addresses[0])
-		if err != nil {
-			return nil, class, nil, 0, err
-		}
-
-		return script, class, addresses, nrequired, nil
-	case MultiSigTy:
-		script, _ := signMultiSig(tx, idx, subScript, hashType,
-			addresses, nrequired, kdb)
-		return script, 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")
-	}
-}
-
-// 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.
-func mergeScripts(chainParams *chaincfg.Params, tx *wire.MsgTx, idx int,
-	pkScript []byte, class ScriptClass, addresses []btcutil.Address,
-	nRequired int, sigScript, prevScript []byte) []byte {
-
-	// TODO(oga) the scripthash and multisig paths here are overly
-	// inefficient in that they will recompute already known data.
-	// some internal refactoring could probably make this avoid needless
-	// extra calculations.
-	switch class {
-	case ScriptHashTy:
-		// Remove the last push in the script and then recurse.
-		// this could be a lot less inefficient.
-		sigPops, err := parseScript(sigScript)
-		if err != nil || len(sigPops) == 0 {
-			return prevScript
-		}
-		prevPops, err := parseScript(prevScript)
-		if err != nil || len(prevPops) == 0 {
-			return sigScript
-		}
-
-		// assume that script in sigPops is the correct one, we just
-		// made it.
-		script := sigPops[len(sigPops)-1].data
-
-		// We already know this information somewhere up the stack.
-		class, addresses, nrequired, err :=
-			ExtractPkScriptAddrs(script, chainParams)
-
-		// regenerate scripts.
-		sigScript, _ := unparseScript(sigPops)
-		prevScript, _ := unparseScript(prevPops)
-
-		// Merge
-		mergedScript := mergeScripts(chainParams, tx, idx, script,
-			class, addresses, nrequired, sigScript, prevScript)
-
-		// Reappend the script and return the result.
-		builder := NewScriptBuilder()
-		builder.script = mergedScript
-		builder.AddData(script)
-		finalScript, _ := builder.Script()
-		return finalScript
-	case MultiSigTy:
-		return mergeMultiSig(tx, idx, addresses, nRequired, pkScript,
-			sigScript, prevScript)
-
-	// It doesn't actualy make sense to merge anything other than multiig
-	// and scripthash (because it could contain multisig). Everything else
-	// has either zero signature, can't be spent, or has a single signature
-	// which is either present or not. The other two cases are handled
-	// above. In the conflict case here we just assume the longest is
-	// correct (this matches behaviour of the reference implementation).
-	default:
-		if len(sigScript) > len(prevScript) {
-			return sigScript
-		}
-		return prevScript
-	}
-}
-
-// mergeMultiSig combines the two signature scripts sigScript and prevScript
-// that both provide signatures for pkScript in output idx of tx. addresses
-// and nRequired should be the results from extracting the addresses from
-// pkScript. Since this function is internal only we assume that the arguments
-// have come from other functions internally and thus are all consistent with
-// each other, behaviour is undefined if this contract is broken.
-func mergeMultiSig(tx *wire.MsgTx, idx int, addresses []btcutil.Address,
-	nRequired int, pkScript, sigScript, prevScript []byte) []byte {
-
-	// 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)
-
-	sigPops, err := parseScript(sigScript)
-	if err != nil || len(sigPops) == 0 {
-		return prevScript
-	}
-
-	prevPops, err := parseScript(prevScript)
-	if err != nil || len(prevPops) == 0 {
-		return sigScript
-	}
-
-	// Convenience function to avoid duplication.
-	extractSigs := func(pops []parsedOpcode, sigs [][]byte) [][]byte {
-		for _, pop := range pops {
-			if len(pop.data) != 0 {
-				sigs = append(sigs, pop.data)
-			}
-		}
-		return sigs
-	}
-
-	possibleSigs := make([][]byte, 0, len(sigPops)+len(prevPops))
-	possibleSigs = extractSigs(sigPops, possibleSigs)
-	possibleSigs = extractSigs(prevPops, possibleSigs)
-
-	// Now we need to match the signatures to pubkeys, the only real way to
-	// do that is to try to verify them all and match it to the pubkey
-	// that verifies it. we then can go through the addresses in order
-	// to build our script. Anything that doesn't parse or doesn't verify we
-	// throw away.
-	addrToSig := make(map[string][]byte)
-sigLoop:
-	for _, sig := range possibleSigs {
-
-		// can't have a valid signature that doesn't at least have a
-		// hashtype, in practise it is even longer than this. but
-		// that'll be checked next.
-		if len(sig) < 1 {
-			continue
-		}
-		tSig := sig[:len(sig)-1]
-		hashType := SigHashType(sig[len(sig)-1])
-
-		pSig, err := btcec.ParseDERSignature(tSig, btcec.S256())
-		if err != nil {
-			continue
-		}
-
-		// We have to do this each round since hash types may vary
-		// between signatures and so the hash will vary. We can,
-		// however, assume no sigs etc are in the script since that
-		// would make the transaction nonstandard and thus not
-		// MultiSigTy, so we just need to hash the full thing.
-		hash := calcScriptHash(pkPops, hashType, tx, idx)
-
-		for _, addr := range addresses {
-			// All multisig addresses should be pubkey addreses
-			// it is an error to call this internal function with
-			// bad input.
-			pkaddr := addr.(*btcutil.AddressPubKey)
-
-			pubKey := pkaddr.PubKey()
-
-			// If it matches we put it in the map. We only
-			// can take one signature per public key so if we
-			// already have one, we can throw this away.
-			if pSig.Verify(hash, pubKey) {
-				aStr := addr.EncodeAddress()
-				if _, ok := addrToSig[aStr]; !ok {
-					addrToSig[aStr] = sig
-				}
-				continue sigLoop
-			}
-		}
-	}
-
-	// Extra opcode to handle the extra arg consumed (due to previous bugs
-	// in the reference implementation).
-	builder := NewScriptBuilder().AddOp(OP_FALSE)
-	doneSigs := 0
-	// This assumes that addresses are in the same order as in the script.
-	for _, addr := range addresses {
-		sig, ok := addrToSig[addr.EncodeAddress()]
-		if !ok {
-			continue
-		}
-		builder.AddData(sig)
-		doneSigs++
-		if doneSigs == nRequired {
-			break
-		}
-	}
-
-	// padding for missing ones.
-	for i := doneSigs; i < nRequired; i++ {
-		builder.AddOp(OP_0)
-	}
-
-	script, _ := builder.Script()
-	return script
-}
-
-// KeyDB is an interface type provided to SignTxOutput, it encapsulates
-// any user state required to get the private keys for an address.
-type KeyDB interface {
-	GetKey(btcutil.Address) (*btcec.PrivateKey, bool, error)
-}
-
-// KeyClosure implements ScriptDB with a closure
-type KeyClosure func(btcutil.Address) (*btcec.PrivateKey, bool, error)
-
-// GetKey implements KeyDB by returning the result of calling the closure
-func (kc KeyClosure) GetKey(address btcutil.Address) (*btcec.PrivateKey,
-	bool, error) {
-	return kc(address)
-}
-
-// ScriptDB is an interface type provided to SignTxOutput, it encapsulates
-// any user state required to get the scripts for an pay-to-script-hash address.
-type ScriptDB interface {
-	GetScript(btcutil.Address) ([]byte, error)
-}
-
-// ScriptClosure implements ScriptDB with a closure
-type ScriptClosure func(btcutil.Address) ([]byte, error)
-
-// GetScript implements ScriptDB by returning the result of calling the closure
-func (sc ScriptClosure) GetScript(address btcutil.Address) ([]byte, error) {
-	return sc(address)
-}
-
-// SignTxOutput signs output idx of the given tx to resolve the script given in
-// pkScript with a signature type of hashType. Any keys required will be
-// looked up by calling getKey() with the string of the given address.
-// Any pay-to-script-hash signatures will be similarly looked up by calling
-// getScript. If previousScript is provided then the results in previousScript
-// will be merged in a type-dependant manner with the newly generated.
-// signature script.
-func SignTxOutput(chainParams *chaincfg.Params, tx *wire.MsgTx, idx int,
-	pkScript []byte, hashType SigHashType, kdb KeyDB, sdb ScriptDB,
-	previousScript []byte) ([]byte, error) {
-
-	sigScript, class, addresses, nrequired, err := sign(chainParams, tx,
-		idx, pkScript, hashType, kdb, sdb)
-	if err != nil {
-		return nil, err
-	}
-
-	if class == ScriptHashTy {
-		// TODO keep the sub addressed and pass down to merge.
-		realSigScript, _, _, _, err := sign(chainParams, tx, idx,
-			sigScript, hashType, kdb, sdb)
-		if err != nil {
-			return nil, err
-		}
-
-		// This is a bad thing. Append the p2sh script as the last
-		// push in the script.
-		builder := NewScriptBuilder()
-		builder.script = realSigScript
-		builder.AddData(sigScript)
-
-		sigScript, _ = builder.Script()
-		// TODO keep a copy of the script for merging.
-	}
-
-	// Merge scripts. with any previous data, if any.
-	mergedScript := mergeScripts(chainParams, tx, idx, pkScript, class,
-		addresses, nrequired, sigScript, previousScript)
-	return mergedScript, nil
-}
-
 // expectedInputs returns the number of arguments required by a script.
 // If the script is of unnown type such that the number can not be determined
 // then -1 is returned. We are an internal function and thus assume that class
diff --git a/txscript/script_test.go b/txscript/script_test.go
index 9bc60ad19..af290679e 100644
--- a/txscript/script_test.go
+++ b/txscript/script_test.go
@@ -6,11 +6,8 @@ package txscript_test
 
 import (
 	"bytes"
-	"errors"
-	"fmt"
 	"testing"
 
-	"github.com/btcsuite/btcd/btcec"
 	"github.com/btcsuite/btcd/chaincfg"
 	"github.com/btcsuite/btcd/txscript"
 	"github.com/btcsuite/btcd/wire"
@@ -2418,339 +2415,6 @@ func TestIsPayToScriptHash(t *testing.T) {
 	}
 }
 
-type TstSigScript struct {
-	name               string
-	inputs             []TstInput
-	hashType           txscript.SigHashType
-	compress           bool
-	scriptAtWrongIndex bool
-}
-
-type TstInput struct {
-	txout              *wire.TxOut
-	sigscriptGenerates bool
-	inputValidates     bool
-	indexOutOfRange    bool
-}
-
-var coinbaseOutPoint = &wire.OutPoint{
-	Index: (1 << 32) - 1,
-}
-
-// Pregenerated private key, with associated public key and pkScripts
-// for the uncompressed and compressed hash160.
-var (
-	privKeyD = []byte{0x6b, 0x0f, 0xd8, 0xda, 0x54, 0x22, 0xd0, 0xb7,
-		0xb4, 0xfc, 0x4e, 0x55, 0xd4, 0x88, 0x42, 0xb3, 0xa1, 0x65,
-		0xac, 0x70, 0x7f, 0x3d, 0xa4, 0x39, 0x5e, 0xcb, 0x3b, 0xb0,
-		0xd6, 0x0e, 0x06, 0x92}
-	pubkeyX = []byte{0xb2, 0x52, 0xf0, 0x49, 0x85, 0x78, 0x03, 0x03, 0xc8,
-		0x7d, 0xce, 0x51, 0x7f, 0xa8, 0x69, 0x0b, 0x91, 0x95, 0xf4,
-		0xf3, 0x5c, 0x26, 0x73, 0x05, 0x05, 0xa2, 0xee, 0xbc, 0x09,
-		0x38, 0x34, 0x3a}
-	pubkeyY = []byte{0xb7, 0xc6, 0x7d, 0xb2, 0xe1, 0xff, 0xc8, 0x43, 0x1f,
-		0x63, 0x32, 0x62, 0xaa, 0x60, 0xc6, 0x83, 0x30, 0xbd, 0x24,
-		0x7e, 0xef, 0xdb, 0x6f, 0x2e, 0x8d, 0x56, 0xf0, 0x3c, 0x9f,
-		0x6d, 0xb6, 0xf8}
-	uncompressedPkScript = []byte{0x76, 0xa9, 0x14, 0xd1, 0x7c, 0xb5,
-		0xeb, 0xa4, 0x02, 0xcb, 0x68, 0xe0, 0x69, 0x56, 0xbf, 0x32,
-		0x53, 0x90, 0x0e, 0x0a, 0x86, 0xc9, 0xfa, 0x88, 0xac}
-	compressedPkScript = []byte{0x76, 0xa9, 0x14, 0x27, 0x4d, 0x9f, 0x7f,
-		0x61, 0x7e, 0x7c, 0x7a, 0x1c, 0x1f, 0xb2, 0x75, 0x79, 0x10,
-		0x43, 0x65, 0x68, 0x27, 0x9d, 0x86, 0x88, 0xac}
-	shortPkScript = []byte{0x76, 0xa9, 0x14, 0xd1, 0x7c, 0xb5,
-		0xeb, 0xa4, 0x02, 0xcb, 0x68, 0xe0, 0x69, 0x56, 0xbf, 0x32,
-		0x53, 0x90, 0x0e, 0x0a, 0x88, 0xac}
-	uncompressedAddrStr = "1L6fd93zGmtzkK6CsZFVVoCwzZV3MUtJ4F"
-	compressedAddrStr   = "14apLppt9zTq6cNw8SDfiJhk9PhkZrQtYZ"
-)
-
-// Pretend output amounts.
-const coinbaseVal = 2500000000
-const fee = 5000000
-
-var SigScriptTests = []TstSigScript{
-	{
-		name: "one input uncompressed",
-		inputs: []TstInput{
-			{
-				txout:              wire.NewTxOut(coinbaseVal, uncompressedPkScript),
-				sigscriptGenerates: true,
-				inputValidates:     true,
-				indexOutOfRange:    false,
-			},
-		},
-		hashType:           txscript.SigHashAll,
-		compress:           false,
-		scriptAtWrongIndex: false,
-	},
-	{
-		name: "two inputs uncompressed",
-		inputs: []TstInput{
-			{
-				txout:              wire.NewTxOut(coinbaseVal, uncompressedPkScript),
-				sigscriptGenerates: true,
-				inputValidates:     true,
-				indexOutOfRange:    false,
-			},
-			{
-				txout:              wire.NewTxOut(coinbaseVal+fee, uncompressedPkScript),
-				sigscriptGenerates: true,
-				inputValidates:     true,
-				indexOutOfRange:    false,
-			},
-		},
-		hashType:           txscript.SigHashAll,
-		compress:           false,
-		scriptAtWrongIndex: false,
-	},
-	{
-		name: "one input compressed",
-		inputs: []TstInput{
-			{
-				txout:              wire.NewTxOut(coinbaseVal, compressedPkScript),
-				sigscriptGenerates: true,
-				inputValidates:     true,
-				indexOutOfRange:    false,
-			},
-		},
-		hashType:           txscript.SigHashAll,
-		compress:           true,
-		scriptAtWrongIndex: false,
-	},
-	{
-		name: "two inputs compressed",
-		inputs: []TstInput{
-			{
-				txout:              wire.NewTxOut(coinbaseVal, compressedPkScript),
-				sigscriptGenerates: true,
-				inputValidates:     true,
-				indexOutOfRange:    false,
-			},
-			{
-				txout:              wire.NewTxOut(coinbaseVal+fee, compressedPkScript),
-				sigscriptGenerates: true,
-				inputValidates:     true,
-				indexOutOfRange:    false,
-			},
-		},
-		hashType:           txscript.SigHashAll,
-		compress:           true,
-		scriptAtWrongIndex: false,
-	},
-	{
-		name: "hashType SigHashNone",
-		inputs: []TstInput{
-			{
-				txout:              wire.NewTxOut(coinbaseVal, uncompressedPkScript),
-				sigscriptGenerates: true,
-				inputValidates:     true,
-				indexOutOfRange:    false,
-			},
-		},
-		hashType:           txscript.SigHashNone,
-		compress:           false,
-		scriptAtWrongIndex: false,
-	},
-	{
-		name: "hashType SigHashSingle",
-		inputs: []TstInput{
-			{
-				txout:              wire.NewTxOut(coinbaseVal, uncompressedPkScript),
-				sigscriptGenerates: true,
-				inputValidates:     true,
-				indexOutOfRange:    false,
-			},
-		},
-		hashType:           txscript.SigHashSingle,
-		compress:           false,
-		scriptAtWrongIndex: false,
-	},
-	{
-		name: "hashType SigHashAnyoneCanPay",
-		inputs: []TstInput{
-			{
-				txout:              wire.NewTxOut(coinbaseVal, uncompressedPkScript),
-				sigscriptGenerates: true,
-				inputValidates:     true,
-				indexOutOfRange:    false,
-			},
-		},
-		hashType:           txscript.SigHashAnyOneCanPay,
-		compress:           false,
-		scriptAtWrongIndex: false,
-	},
-	{
-		name: "hashType non-standard",
-		inputs: []TstInput{
-			{
-				txout:              wire.NewTxOut(coinbaseVal, uncompressedPkScript),
-				sigscriptGenerates: true,
-				inputValidates:     true,
-				indexOutOfRange:    false,
-			},
-		},
-		hashType:           0x04,
-		compress:           false,
-		scriptAtWrongIndex: false,
-	},
-	{
-		name: "invalid compression",
-		inputs: []TstInput{
-			{
-				txout:              wire.NewTxOut(coinbaseVal, uncompressedPkScript),
-				sigscriptGenerates: true,
-				inputValidates:     false,
-				indexOutOfRange:    false,
-			},
-		},
-		hashType:           txscript.SigHashAll,
-		compress:           true,
-		scriptAtWrongIndex: false,
-	},
-	{
-		name: "short PkScript",
-		inputs: []TstInput{
-			{
-				txout:              wire.NewTxOut(coinbaseVal, shortPkScript),
-				sigscriptGenerates: false,
-				indexOutOfRange:    false,
-			},
-		},
-		hashType:           txscript.SigHashAll,
-		compress:           false,
-		scriptAtWrongIndex: false,
-	},
-	{
-		name: "valid script at wrong index",
-		inputs: []TstInput{
-			{
-				txout:              wire.NewTxOut(coinbaseVal, uncompressedPkScript),
-				sigscriptGenerates: true,
-				inputValidates:     true,
-				indexOutOfRange:    false,
-			},
-			{
-				txout:              wire.NewTxOut(coinbaseVal+fee, uncompressedPkScript),
-				sigscriptGenerates: true,
-				inputValidates:     true,
-				indexOutOfRange:    false,
-			},
-		},
-		hashType:           txscript.SigHashAll,
-		compress:           false,
-		scriptAtWrongIndex: true,
-	},
-	{
-		name: "index out of range",
-		inputs: []TstInput{
-			{
-				txout:              wire.NewTxOut(coinbaseVal, uncompressedPkScript),
-				sigscriptGenerates: true,
-				inputValidates:     true,
-				indexOutOfRange:    false,
-			},
-			{
-				txout:              wire.NewTxOut(coinbaseVal+fee, uncompressedPkScript),
-				sigscriptGenerates: true,
-				inputValidates:     true,
-				indexOutOfRange:    false,
-			},
-		},
-		hashType:           txscript.SigHashAll,
-		compress:           false,
-		scriptAtWrongIndex: true,
-	},
-}
-
-// Test the sigscript generation for valid and invalid inputs, all
-// hashTypes, and with and without compression.  This test creates
-// sigscripts to spend fake coinbase inputs, as sigscripts cannot be
-// created for the MsgTxs in txTests, since they come from the blockchain
-// and we don't have the private keys.
-func TestSignatureScript(t *testing.T) {
-	t.Parallel()
-
-	privKey, _ := btcec.PrivKeyFromBytes(btcec.S256(), privKeyD)
-
-nexttest:
-	for i := range SigScriptTests {
-		tx := wire.NewMsgTx()
-
-		output := wire.NewTxOut(500, []byte{txscript.OP_RETURN})
-		tx.AddTxOut(output)
-
-		for _ = range SigScriptTests[i].inputs {
-			txin := wire.NewTxIn(coinbaseOutPoint, nil)
-			tx.AddTxIn(txin)
-		}
-
-		var script []byte
-		var err error
-		for j := range tx.TxIn {
-			var idx int
-			if SigScriptTests[i].inputs[j].indexOutOfRange {
-				t.Errorf("at test %v", SigScriptTests[i].name)
-				idx = len(SigScriptTests[i].inputs)
-			} else {
-				idx = j
-			}
-			script, err = txscript.SignatureScript(tx, idx,
-				SigScriptTests[i].inputs[j].txout.PkScript,
-				SigScriptTests[i].hashType, privKey,
-				SigScriptTests[i].compress)
-
-			if (err == nil) != SigScriptTests[i].inputs[j].sigscriptGenerates {
-				if err == nil {
-					t.Errorf("passed test '%v' incorrectly",
-						SigScriptTests[i].name)
-				} else {
-					t.Errorf("failed test '%v': %v",
-						SigScriptTests[i].name, err)
-				}
-				continue nexttest
-			}
-			if !SigScriptTests[i].inputs[j].sigscriptGenerates {
-				// done with this test
-				continue nexttest
-			}
-
-			tx.TxIn[j].SignatureScript = script
-		}
-
-		// If testing using a correct sigscript but for an incorrect
-		// index, use last input script for first input.  Requires > 0
-		// inputs for test.
-		if SigScriptTests[i].scriptAtWrongIndex {
-			tx.TxIn[0].SignatureScript = script
-			SigScriptTests[i].inputs[0].inputValidates = false
-		}
-
-		// Validate tx input scripts
-		scriptFlags := txscript.ScriptBip16 | txscript.ScriptVerifyDERSignatures
-		for j := range tx.TxIn {
-			vm, err := txscript.NewEngine(SigScriptTests[i].
-				inputs[j].txout.PkScript, tx, j, scriptFlags)
-			if err != nil {
-				t.Errorf("cannot create script vm for test %v: %v",
-					SigScriptTests[i].name, err)
-				continue nexttest
-			}
-			err = vm.Execute()
-			if (err == nil) != SigScriptTests[i].inputs[j].inputValidates {
-				if err == nil {
-					t.Errorf("passed test '%v' validation incorrectly: %v",
-						SigScriptTests[i].name, err)
-				} else {
-					t.Errorf("failed test '%v' validation: %v",
-						SigScriptTests[i].name, err)
-				}
-				continue nexttest
-			}
-		}
-	}
-}
-
 func TestStringifyClass(t *testing.T) {
 	t.Parallel()
 
@@ -3138,1370 +2802,6 @@ func TestMultiSigScript(t *testing.T) {
 	}
 }
 
-func signAndCheck(msg string, tx *wire.MsgTx, idx int, pkScript []byte,
-	hashType txscript.SigHashType, kdb txscript.KeyDB, sdb txscript.ScriptDB,
-	previousScript []byte) error {
-
-	sigScript, err := txscript.SignTxOutput(&chaincfg.TestNet3Params, tx,
-		idx, pkScript, hashType, kdb, sdb, []byte{})
-	if err != nil {
-		return fmt.Errorf("failed to sign output %s: %v", msg, err)
-	}
-
-	return checkScripts(msg, tx, idx, sigScript, pkScript)
-}
-
-func checkScripts(msg string, tx *wire.MsgTx, idx int, sigScript, pkScript []byte) error {
-	tx.TxIn[idx].SignatureScript = sigScript
-	vm, err := txscript.NewEngine(pkScript, tx, idx,
-		txscript.ScriptBip16|txscript.ScriptVerifyDERSignatures)
-	if err != nil {
-		return fmt.Errorf("failed to make script engine for %s: %v",
-			msg, err)
-	}
-
-	err = vm.Execute()
-	if err != nil {
-		return fmt.Errorf("invalid script signature for %s: %v", msg,
-			err)
-	}
-
-	return nil
-}
-
-type addressToKey struct {
-	key        *btcec.PrivateKey
-	compressed bool
-}
-
-func mkGetKey(keys map[string]addressToKey) txscript.KeyDB {
-	if keys == nil {
-		return txscript.KeyClosure(func(addr btcutil.Address) (*btcec.PrivateKey,
-			bool, error) {
-			return nil, false, errors.New("nope")
-		})
-	}
-	return txscript.KeyClosure(func(addr btcutil.Address) (*btcec.PrivateKey,
-		bool, error) {
-		a2k, ok := keys[addr.EncodeAddress()]
-		if !ok {
-			return nil, false, errors.New("nope")
-		}
-		return a2k.key, a2k.compressed, nil
-	})
-}
-
-func mkGetScript(scripts map[string][]byte) txscript.ScriptDB {
-	if scripts == nil {
-		return txscript.ScriptClosure(func(addr btcutil.Address) (
-			[]byte, error) {
-			return nil, errors.New("nope")
-		})
-	}
-	return txscript.ScriptClosure(func(addr btcutil.Address) ([]byte,
-		error) {
-		script, ok := scripts[addr.EncodeAddress()]
-		if !ok {
-			return nil, errors.New("nope")
-		}
-		return script, nil
-	})
-}
-
-func TestSignTxOutput(t *testing.T) {
-	t.Parallel()
-
-	// make key
-	// make script based on key.
-	// sign with magic pixie dust.
-	hashTypes := []txscript.SigHashType{
-		txscript.SigHashOld, // no longer used but should act like all
-		txscript.SigHashAll,
-		txscript.SigHashNone,
-		txscript.SigHashSingle,
-		txscript.SigHashAll | txscript.SigHashAnyOneCanPay,
-		txscript.SigHashNone | txscript.SigHashAnyOneCanPay,
-		txscript.SigHashSingle | txscript.SigHashAnyOneCanPay,
-	}
-	tx := &wire.MsgTx{
-		Version: 1,
-		TxIn: []*wire.TxIn{
-			&wire.TxIn{
-				PreviousOutPoint: wire.OutPoint{
-					Hash:  wire.ShaHash{},
-					Index: 0,
-				},
-				Sequence: 4294967295,
-			},
-			&wire.TxIn{
-				PreviousOutPoint: wire.OutPoint{
-					Hash:  wire.ShaHash{},
-					Index: 1,
-				},
-				Sequence: 4294967295,
-			},
-			&wire.TxIn{
-				PreviousOutPoint: wire.OutPoint{
-					Hash:  wire.ShaHash{},
-					Index: 2,
-				},
-				Sequence: 4294967295,
-			},
-		},
-		TxOut: []*wire.TxOut{
-			&wire.TxOut{
-				Value: 1,
-			},
-			&wire.TxOut{
-				Value: 2,
-			},
-			&wire.TxOut{
-				Value: 3,
-			},
-		},
-		LockTime: 0,
-	}
-
-	// Pay to Pubkey Hash (uncompressed)
-	for _, hashType := range hashTypes {
-		for i := range tx.TxIn {
-			msg := fmt.Sprintf("%d:%d", hashType, i)
-			key, err := btcec.NewPrivateKey(btcec.S256())
-			if err != nil {
-				t.Errorf("failed to make privKey for %s: %v",
-					msg, err)
-				break
-			}
-
-			pk := (*btcec.PublicKey)(&key.PublicKey).
-				SerializeUncompressed()
-			address, err := btcutil.NewAddressPubKeyHash(
-				btcutil.Hash160(pk), &chaincfg.TestNet3Params)
-			if err != nil {
-				t.Errorf("failed to make address for %s: %v",
-					msg, err)
-				break
-			}
-
-			pkScript, err := txscript.PayToAddrScript(address)
-			if err != nil {
-				t.Errorf("failed to make pkscript "+
-					"for %s: %v", msg, err)
-			}
-
-			if err := signAndCheck(msg, tx, i, pkScript, hashType,
-				mkGetKey(map[string]addressToKey{
-					address.EncodeAddress(): {key, false},
-				}), mkGetScript(nil), []byte{}); err != nil {
-				t.Error(err)
-				break
-			}
-		}
-	}
-
-	// Pay to Pubkey Hash (uncompressed) (merging with correct)
-	for _, hashType := range hashTypes {
-		for i := range tx.TxIn {
-			msg := fmt.Sprintf("%d:%d", hashType, i)
-			key, err := btcec.NewPrivateKey(btcec.S256())
-			if err != nil {
-				t.Errorf("failed to make privKey for %s: %v",
-					msg, err)
-				break
-			}
-
-			pk := (*btcec.PublicKey)(&key.PublicKey).
-				SerializeUncompressed()
-			address, err := btcutil.NewAddressPubKeyHash(
-				btcutil.Hash160(pk), &chaincfg.TestNet3Params)
-			if err != nil {
-				t.Errorf("failed to make address for %s: %v",
-					msg, err)
-				break
-			}
-
-			pkScript, err := txscript.PayToAddrScript(address)
-			if err != nil {
-				t.Errorf("failed to make pkscript "+
-					"for %s: %v", msg, err)
-			}
-
-			sigScript, err := txscript.SignTxOutput(
-				&chaincfg.TestNet3Params, tx, i, pkScript,
-				hashType, mkGetKey(map[string]addressToKey{
-					address.EncodeAddress(): {key, false},
-				}), mkGetScript(nil), []byte{})
-			if err != nil {
-				t.Errorf("failed to sign output %s: %v", msg,
-					err)
-				break
-			}
-
-			// by the above loop, this should be valid, now sign
-			// again and merge.
-			sigScript, err = txscript.SignTxOutput(
-				&chaincfg.TestNet3Params, tx, i, pkScript,
-				hashType, mkGetKey(map[string]addressToKey{
-					address.EncodeAddress(): {key, false},
-				}), mkGetScript(nil), sigScript)
-			if err != nil {
-				t.Errorf("failed to sign output %s a "+
-					"second time: %v", msg, err)
-				break
-			}
-
-			err = checkScripts(msg, tx, i, sigScript, pkScript)
-			if err != nil {
-				t.Errorf("twice signed script invalid for "+
-					"%s: %v", msg, err)
-				break
-			}
-		}
-	}
-
-	// Pay to Pubkey Hash (compressed)
-	for _, hashType := range hashTypes {
-		for i := range tx.TxIn {
-			msg := fmt.Sprintf("%d:%d", hashType, i)
-
-			key, err := btcec.NewPrivateKey(btcec.S256())
-			if err != nil {
-				t.Errorf("failed to make privKey for %s: %v",
-					msg, err)
-				break
-			}
-
-			pk := (*btcec.PublicKey)(&key.PublicKey).
-				SerializeCompressed()
-			address, err := btcutil.NewAddressPubKeyHash(
-				btcutil.Hash160(pk), &chaincfg.TestNet3Params)
-			if err != nil {
-				t.Errorf("failed to make address for %s: %v",
-					msg, err)
-				break
-			}
-
-			pkScript, err := txscript.PayToAddrScript(address)
-			if err != nil {
-				t.Errorf("failed to make pkscript "+
-					"for %s: %v", msg, err)
-			}
-
-			if err := signAndCheck(msg, tx, i, pkScript, hashType,
-				mkGetKey(map[string]addressToKey{
-					address.EncodeAddress(): {key, true},
-				}), mkGetScript(nil), []byte{}); err != nil {
-				t.Error(err)
-				break
-			}
-		}
-	}
-
-	// Pay to Pubkey Hash (compressed) with duplicate merge
-	for _, hashType := range hashTypes {
-		for i := range tx.TxIn {
-			msg := fmt.Sprintf("%d:%d", hashType, i)
-
-			key, err := btcec.NewPrivateKey(btcec.S256())
-			if err != nil {
-				t.Errorf("failed to make privKey for %s: %v",
-					msg, err)
-				break
-			}
-
-			pk := (*btcec.PublicKey)(&key.PublicKey).
-				SerializeCompressed()
-			address, err := btcutil.NewAddressPubKeyHash(
-				btcutil.Hash160(pk), &chaincfg.TestNet3Params)
-			if err != nil {
-				t.Errorf("failed to make address for %s: %v",
-					msg, err)
-				break
-			}
-
-			pkScript, err := txscript.PayToAddrScript(address)
-			if err != nil {
-				t.Errorf("failed to make pkscript "+
-					"for %s: %v", msg, err)
-			}
-
-			sigScript, err := txscript.SignTxOutput(
-				&chaincfg.TestNet3Params, tx, i, pkScript,
-				hashType, mkGetKey(map[string]addressToKey{
-					address.EncodeAddress(): {key, true},
-				}), mkGetScript(nil), []byte{})
-			if err != nil {
-				t.Errorf("failed to sign output %s: %v", msg,
-					err)
-				break
-			}
-
-			// by the above loop, this should be valid, now sign
-			// again and merge.
-			sigScript, err = txscript.SignTxOutput(
-				&chaincfg.TestNet3Params, tx, i, pkScript,
-				hashType, mkGetKey(map[string]addressToKey{
-					address.EncodeAddress(): {key, true},
-				}), mkGetScript(nil), sigScript)
-			if err != nil {
-				t.Errorf("failed to sign output %s a "+
-					"second time: %v", msg, err)
-				break
-			}
-
-			err = checkScripts(msg, tx, i, sigScript, pkScript)
-			if err != nil {
-				t.Errorf("twice signed script invalid for "+
-					"%s: %v", msg, err)
-				break
-			}
-		}
-	}
-
-	// Pay to PubKey (uncompressed)
-	for _, hashType := range hashTypes {
-		for i := range tx.TxIn {
-			msg := fmt.Sprintf("%d:%d", hashType, i)
-
-			key, err := btcec.NewPrivateKey(btcec.S256())
-			if err != nil {
-				t.Errorf("failed to make privKey for %s: %v",
-					msg, err)
-				break
-			}
-
-			pk := (*btcec.PublicKey)(&key.PublicKey).
-				SerializeUncompressed()
-			address, err := btcutil.NewAddressPubKey(pk,
-				&chaincfg.TestNet3Params)
-			if err != nil {
-				t.Errorf("failed to make address for %s: %v",
-					msg, err)
-				break
-			}
-
-			pkScript, err := txscript.PayToAddrScript(address)
-			if err != nil {
-				t.Errorf("failed to make pkscript "+
-					"for %s: %v", msg, err)
-			}
-
-			if err := signAndCheck(msg, tx, i, pkScript, hashType,
-				mkGetKey(map[string]addressToKey{
-					address.EncodeAddress(): {key, false},
-				}), mkGetScript(nil), []byte{}); err != nil {
-				t.Error(err)
-				break
-			}
-		}
-	}
-
-	// Pay to PubKey (uncompressed)
-	for _, hashType := range hashTypes {
-		for i := range tx.TxIn {
-			msg := fmt.Sprintf("%d:%d", hashType, i)
-
-			key, err := btcec.NewPrivateKey(btcec.S256())
-			if err != nil {
-				t.Errorf("failed to make privKey for %s: %v",
-					msg, err)
-				break
-			}
-
-			pk := (*btcec.PublicKey)(&key.PublicKey).
-				SerializeUncompressed()
-			address, err := btcutil.NewAddressPubKey(pk,
-				&chaincfg.TestNet3Params)
-			if err != nil {
-				t.Errorf("failed to make address for %s: %v",
-					msg, err)
-				break
-			}
-
-			pkScript, err := txscript.PayToAddrScript(address)
-			if err != nil {
-				t.Errorf("failed to make pkscript "+
-					"for %s: %v", msg, err)
-			}
-
-			sigScript, err := txscript.SignTxOutput(
-				&chaincfg.TestNet3Params, tx, i, pkScript,
-				hashType, mkGetKey(map[string]addressToKey{
-					address.EncodeAddress(): {key, false},
-				}), mkGetScript(nil), []byte{})
-			if err != nil {
-				t.Errorf("failed to sign output %s: %v", msg,
-					err)
-				break
-			}
-
-			// by the above loop, this should be valid, now sign
-			// again and merge.
-			sigScript, err = txscript.SignTxOutput(
-				&chaincfg.TestNet3Params, tx, i, pkScript,
-				hashType, mkGetKey(map[string]addressToKey{
-					address.EncodeAddress(): {key, false},
-				}), mkGetScript(nil), sigScript)
-			if err != nil {
-				t.Errorf("failed to sign output %s a "+
-					"second time: %v", msg, err)
-				break
-			}
-
-			err = checkScripts(msg, tx, i, sigScript, pkScript)
-			if err != nil {
-				t.Errorf("twice signed script invalid for "+
-					"%s: %v", msg, err)
-				break
-			}
-		}
-	}
-
-	// Pay to PubKey (compressed)
-	for _, hashType := range hashTypes {
-		for i := range tx.TxIn {
-			msg := fmt.Sprintf("%d:%d", hashType, i)
-
-			key, err := btcec.NewPrivateKey(btcec.S256())
-			if err != nil {
-				t.Errorf("failed to make privKey for %s: %v",
-					msg, err)
-				break
-			}
-
-			pk := (*btcec.PublicKey)(&key.PublicKey).
-				SerializeCompressed()
-			address, err := btcutil.NewAddressPubKey(pk,
-				&chaincfg.TestNet3Params)
-			if err != nil {
-				t.Errorf("failed to make address for %s: %v",
-					msg, err)
-				break
-			}
-
-			pkScript, err := txscript.PayToAddrScript(address)
-			if err != nil {
-				t.Errorf("failed to make pkscript "+
-					"for %s: %v", msg, err)
-			}
-
-			if err := signAndCheck(msg, tx, i, pkScript, hashType,
-				mkGetKey(map[string]addressToKey{
-					address.EncodeAddress(): {key, true},
-				}), mkGetScript(nil), []byte{}); err != nil {
-				t.Error(err)
-				break
-			}
-		}
-	}
-
-	// Pay to PubKey (compressed) with duplicate merge
-	for _, hashType := range hashTypes {
-		for i := range tx.TxIn {
-			msg := fmt.Sprintf("%d:%d", hashType, i)
-
-			key, err := btcec.NewPrivateKey(btcec.S256())
-			if err != nil {
-				t.Errorf("failed to make privKey for %s: %v",
-					msg, err)
-				break
-			}
-
-			pk := (*btcec.PublicKey)(&key.PublicKey).
-				SerializeCompressed()
-			address, err := btcutil.NewAddressPubKey(pk,
-				&chaincfg.TestNet3Params)
-			if err != nil {
-				t.Errorf("failed to make address for %s: %v",
-					msg, err)
-				break
-			}
-
-			pkScript, err := txscript.PayToAddrScript(address)
-			if err != nil {
-				t.Errorf("failed to make pkscript "+
-					"for %s: %v", msg, err)
-			}
-
-			sigScript, err := txscript.SignTxOutput(
-				&chaincfg.TestNet3Params, tx, i, pkScript,
-				hashType, mkGetKey(map[string]addressToKey{
-					address.EncodeAddress(): {key, true},
-				}), mkGetScript(nil), []byte{})
-			if err != nil {
-				t.Errorf("failed to sign output %s: %v", msg,
-					err)
-				break
-			}
-
-			// by the above loop, this should be valid, now sign
-			// again and merge.
-			sigScript, err = txscript.SignTxOutput(
-				&chaincfg.TestNet3Params, tx, i, pkScript,
-				hashType, mkGetKey(map[string]addressToKey{
-					address.EncodeAddress(): {key, true},
-				}), mkGetScript(nil), sigScript)
-			if err != nil {
-				t.Errorf("failed to sign output %s a "+
-					"second time: %v", msg, err)
-				break
-			}
-
-			err = checkScripts(msg, tx, i, sigScript, pkScript)
-			if err != nil {
-				t.Errorf("twice signed script invalid for "+
-					"%s: %v", msg, err)
-				break
-			}
-		}
-	}
-
-	// As before, but with p2sh now.
-	// Pay to Pubkey Hash (uncompressed)
-	for _, hashType := range hashTypes {
-		for i := range tx.TxIn {
-			msg := fmt.Sprintf("%d:%d", hashType, i)
-			key, err := btcec.NewPrivateKey(btcec.S256())
-			if err != nil {
-				t.Errorf("failed to make privKey for %s: %v",
-					msg, err)
-				break
-			}
-
-			pk := (*btcec.PublicKey)(&key.PublicKey).
-				SerializeUncompressed()
-			address, err := btcutil.NewAddressPubKeyHash(
-				btcutil.Hash160(pk), &chaincfg.TestNet3Params)
-			if err != nil {
-				t.Errorf("failed to make address for %s: %v",
-					msg, err)
-				break
-			}
-
-			pkScript, err := txscript.PayToAddrScript(address)
-			if err != nil {
-				t.Errorf("failed to make pkscript "+
-					"for %s: %v", msg, err)
-				break
-			}
-
-			scriptAddr, err := btcutil.NewAddressScriptHash(
-				pkScript, &chaincfg.TestNet3Params)
-			if err != nil {
-				t.Errorf("failed to make p2sh addr for %s: %v",
-					msg, err)
-				break
-			}
-
-			scriptPkScript, err := txscript.PayToAddrScript(
-				scriptAddr)
-			if err != nil {
-				t.Errorf("failed to make script pkscript for "+
-					"%s: %v", msg, err)
-				break
-			}
-
-			if err := signAndCheck(msg, tx, i, scriptPkScript,
-				hashType,
-				mkGetKey(map[string]addressToKey{
-					address.EncodeAddress(): {key, false},
-				}), mkGetScript(map[string][]byte{
-					scriptAddr.EncodeAddress(): pkScript,
-				}), []byte{}); err != nil {
-				t.Error(err)
-				break
-			}
-		}
-	}
-
-	// Pay to Pubkey Hash (uncompressed) with duplicate merge
-	for _, hashType := range hashTypes {
-		for i := range tx.TxIn {
-			msg := fmt.Sprintf("%d:%d", hashType, i)
-			key, err := btcec.NewPrivateKey(btcec.S256())
-			if err != nil {
-				t.Errorf("failed to make privKey for %s: %v",
-					msg, err)
-				break
-			}
-
-			pk := (*btcec.PublicKey)(&key.PublicKey).
-				SerializeUncompressed()
-			address, err := btcutil.NewAddressPubKeyHash(
-				btcutil.Hash160(pk), &chaincfg.TestNet3Params)
-			if err != nil {
-				t.Errorf("failed to make address for %s: %v",
-					msg, err)
-				break
-			}
-
-			pkScript, err := txscript.PayToAddrScript(address)
-			if err != nil {
-				t.Errorf("failed to make pkscript "+
-					"for %s: %v", msg, err)
-				break
-			}
-
-			scriptAddr, err := btcutil.NewAddressScriptHash(
-				pkScript, &chaincfg.TestNet3Params)
-			if err != nil {
-				t.Errorf("failed to make p2sh addr for %s: %v",
-					msg, err)
-				break
-			}
-
-			scriptPkScript, err := txscript.PayToAddrScript(
-				scriptAddr)
-			if err != nil {
-				t.Errorf("failed to make script pkscript for "+
-					"%s: %v", msg, err)
-				break
-			}
-
-			sigScript, err := txscript.SignTxOutput(
-				&chaincfg.TestNet3Params, tx, i, scriptPkScript,
-				hashType, mkGetKey(map[string]addressToKey{
-					address.EncodeAddress(): {key, false},
-				}), mkGetScript(map[string][]byte{
-					scriptAddr.EncodeAddress(): pkScript,
-				}), []byte{})
-			if err != nil {
-				t.Errorf("failed to sign output %s: %v", msg,
-					err)
-				break
-			}
-
-			// by the above loop, this should be valid, now sign
-			// again and merge.
-			sigScript, err = txscript.SignTxOutput(
-				&chaincfg.TestNet3Params, tx, i, scriptPkScript,
-				hashType, mkGetKey(map[string]addressToKey{
-					address.EncodeAddress(): {key, false},
-				}), mkGetScript(map[string][]byte{
-					scriptAddr.EncodeAddress(): pkScript,
-				}), []byte{})
-			if err != nil {
-				t.Errorf("failed to sign output %s a "+
-					"second time: %v", msg, err)
-				break
-			}
-
-			err = checkScripts(msg, tx, i, sigScript, scriptPkScript)
-			if err != nil {
-				t.Errorf("twice signed script invalid for "+
-					"%s: %v", msg, err)
-				break
-			}
-		}
-	}
-
-	// Pay to Pubkey Hash (compressed)
-	for _, hashType := range hashTypes {
-		for i := range tx.TxIn {
-			msg := fmt.Sprintf("%d:%d", hashType, i)
-
-			key, err := btcec.NewPrivateKey(btcec.S256())
-			if err != nil {
-				t.Errorf("failed to make privKey for %s: %v",
-					msg, err)
-				break
-			}
-
-			pk := (*btcec.PublicKey)(&key.PublicKey).
-				SerializeCompressed()
-			address, err := btcutil.NewAddressPubKeyHash(
-				btcutil.Hash160(pk), &chaincfg.TestNet3Params)
-			if err != nil {
-				t.Errorf("failed to make address for %s: %v",
-					msg, err)
-				break
-			}
-
-			pkScript, err := txscript.PayToAddrScript(address)
-			if err != nil {
-				t.Errorf("failed to make pkscript "+
-					"for %s: %v", msg, err)
-			}
-
-			scriptAddr, err := btcutil.NewAddressScriptHash(
-				pkScript, &chaincfg.TestNet3Params)
-			if err != nil {
-				t.Errorf("failed to make p2sh addr for %s: %v",
-					msg, err)
-				break
-			}
-
-			scriptPkScript, err := txscript.PayToAddrScript(
-				scriptAddr)
-			if err != nil {
-				t.Errorf("failed to make script pkscript for "+
-					"%s: %v", msg, err)
-				break
-			}
-
-			if err := signAndCheck(msg, tx, i, scriptPkScript,
-				hashType,
-				mkGetKey(map[string]addressToKey{
-					address.EncodeAddress(): {key, true},
-				}), mkGetScript(map[string][]byte{
-					scriptAddr.EncodeAddress(): pkScript,
-				}), []byte{}); err != nil {
-				t.Error(err)
-				break
-			}
-		}
-	}
-
-	// Pay to Pubkey Hash (compressed) with duplicate merge
-	for _, hashType := range hashTypes {
-		for i := range tx.TxIn {
-			msg := fmt.Sprintf("%d:%d", hashType, i)
-
-			key, err := btcec.NewPrivateKey(btcec.S256())
-			if err != nil {
-				t.Errorf("failed to make privKey for %s: %v",
-					msg, err)
-				break
-			}
-
-			pk := (*btcec.PublicKey)(&key.PublicKey).
-				SerializeCompressed()
-			address, err := btcutil.NewAddressPubKeyHash(
-				btcutil.Hash160(pk), &chaincfg.TestNet3Params)
-			if err != nil {
-				t.Errorf("failed to make address for %s: %v",
-					msg, err)
-				break
-			}
-
-			pkScript, err := txscript.PayToAddrScript(address)
-			if err != nil {
-				t.Errorf("failed to make pkscript "+
-					"for %s: %v", msg, err)
-			}
-
-			scriptAddr, err := btcutil.NewAddressScriptHash(
-				pkScript, &chaincfg.TestNet3Params)
-			if err != nil {
-				t.Errorf("failed to make p2sh addr for %s: %v",
-					msg, err)
-				break
-			}
-
-			scriptPkScript, err := txscript.PayToAddrScript(
-				scriptAddr)
-			if err != nil {
-				t.Errorf("failed to make script pkscript for "+
-					"%s: %v", msg, err)
-				break
-			}
-
-			sigScript, err := txscript.SignTxOutput(
-				&chaincfg.TestNet3Params, tx, i, scriptPkScript,
-				hashType, mkGetKey(map[string]addressToKey{
-					address.EncodeAddress(): {key, true},
-				}), mkGetScript(map[string][]byte{
-					scriptAddr.EncodeAddress(): pkScript,
-				}), []byte{})
-			if err != nil {
-				t.Errorf("failed to sign output %s: %v", msg,
-					err)
-				break
-			}
-
-			// by the above loop, this should be valid, now sign
-			// again and merge.
-			sigScript, err = txscript.SignTxOutput(
-				&chaincfg.TestNet3Params, tx, i, scriptPkScript,
-				hashType, mkGetKey(map[string]addressToKey{
-					address.EncodeAddress(): {key, true},
-				}), mkGetScript(map[string][]byte{
-					scriptAddr.EncodeAddress(): pkScript,
-				}), []byte{})
-			if err != nil {
-				t.Errorf("failed to sign output %s a "+
-					"second time: %v", msg, err)
-				break
-			}
-
-			err = checkScripts(msg, tx, i, sigScript, scriptPkScript)
-			if err != nil {
-				t.Errorf("twice signed script invalid for "+
-					"%s: %v", msg, err)
-				break
-			}
-		}
-	}
-
-	// Pay to PubKey (uncompressed)
-	for _, hashType := range hashTypes {
-		for i := range tx.TxIn {
-			msg := fmt.Sprintf("%d:%d", hashType, i)
-
-			key, err := btcec.NewPrivateKey(btcec.S256())
-			if err != nil {
-				t.Errorf("failed to make privKey for %s: %v",
-					msg, err)
-				break
-			}
-
-			pk := (*btcec.PublicKey)(&key.PublicKey).
-				SerializeUncompressed()
-			address, err := btcutil.NewAddressPubKey(pk,
-				&chaincfg.TestNet3Params)
-			if err != nil {
-				t.Errorf("failed to make address for %s: %v",
-					msg, err)
-				break
-			}
-
-			pkScript, err := txscript.PayToAddrScript(address)
-			if err != nil {
-				t.Errorf("failed to make pkscript "+
-					"for %s: %v", msg, err)
-			}
-
-			scriptAddr, err := btcutil.NewAddressScriptHash(
-				pkScript, &chaincfg.TestNet3Params)
-			if err != nil {
-				t.Errorf("failed to make p2sh addr for %s: %v",
-					msg, err)
-				break
-			}
-
-			scriptPkScript, err := txscript.PayToAddrScript(
-				scriptAddr)
-			if err != nil {
-				t.Errorf("failed to make script pkscript for "+
-					"%s: %v", msg, err)
-				break
-			}
-
-			if err := signAndCheck(msg, tx, i, scriptPkScript,
-				hashType,
-				mkGetKey(map[string]addressToKey{
-					address.EncodeAddress(): {key, false},
-				}), mkGetScript(map[string][]byte{
-					scriptAddr.EncodeAddress(): pkScript,
-				}), []byte{}); err != nil {
-				t.Error(err)
-				break
-			}
-		}
-	}
-
-	// Pay to PubKey (uncompressed) with duplicate merge
-	for _, hashType := range hashTypes {
-		for i := range tx.TxIn {
-			msg := fmt.Sprintf("%d:%d", hashType, i)
-
-			key, err := btcec.NewPrivateKey(btcec.S256())
-			if err != nil {
-				t.Errorf("failed to make privKey for %s: %v",
-					msg, err)
-				break
-			}
-
-			pk := (*btcec.PublicKey)(&key.PublicKey).
-				SerializeUncompressed()
-			address, err := btcutil.NewAddressPubKey(pk,
-				&chaincfg.TestNet3Params)
-			if err != nil {
-				t.Errorf("failed to make address for %s: %v",
-					msg, err)
-				break
-			}
-
-			pkScript, err := txscript.PayToAddrScript(address)
-			if err != nil {
-				t.Errorf("failed to make pkscript "+
-					"for %s: %v", msg, err)
-			}
-
-			scriptAddr, err := btcutil.NewAddressScriptHash(
-				pkScript, &chaincfg.TestNet3Params)
-			if err != nil {
-				t.Errorf("failed to make p2sh addr for %s: %v",
-					msg, err)
-				break
-			}
-
-			scriptPkScript, err := txscript.PayToAddrScript(
-				scriptAddr)
-			if err != nil {
-				t.Errorf("failed to make script pkscript for "+
-					"%s: %v", msg, err)
-				break
-			}
-
-			sigScript, err := txscript.SignTxOutput(
-				&chaincfg.TestNet3Params, tx, i, scriptPkScript,
-				hashType, mkGetKey(map[string]addressToKey{
-					address.EncodeAddress(): {key, false},
-				}), mkGetScript(map[string][]byte{
-					scriptAddr.EncodeAddress(): pkScript,
-				}), []byte{})
-			if err != nil {
-				t.Errorf("failed to sign output %s: %v", msg,
-					err)
-				break
-			}
-
-			// by the above loop, this should be valid, now sign
-			// again and merge.
-			sigScript, err = txscript.SignTxOutput(
-				&chaincfg.TestNet3Params, tx, i, scriptPkScript,
-				hashType, mkGetKey(map[string]addressToKey{
-					address.EncodeAddress(): {key, false},
-				}), mkGetScript(map[string][]byte{
-					scriptAddr.EncodeAddress(): pkScript,
-				}), []byte{})
-			if err != nil {
-				t.Errorf("failed to sign output %s a "+
-					"second time: %v", msg, err)
-				break
-			}
-
-			err = checkScripts(msg, tx, i, sigScript, scriptPkScript)
-			if err != nil {
-				t.Errorf("twice signed script invalid for "+
-					"%s: %v", msg, err)
-				break
-			}
-		}
-	}
-
-	// Pay to PubKey (compressed)
-	for _, hashType := range hashTypes {
-		for i := range tx.TxIn {
-			msg := fmt.Sprintf("%d:%d", hashType, i)
-
-			key, err := btcec.NewPrivateKey(btcec.S256())
-			if err != nil {
-				t.Errorf("failed to make privKey for %s: %v",
-					msg, err)
-				break
-			}
-
-			pk := (*btcec.PublicKey)(&key.PublicKey).
-				SerializeCompressed()
-			address, err := btcutil.NewAddressPubKey(pk,
-				&chaincfg.TestNet3Params)
-			if err != nil {
-				t.Errorf("failed to make address for %s: %v",
-					msg, err)
-				break
-			}
-
-			pkScript, err := txscript.PayToAddrScript(address)
-			if err != nil {
-				t.Errorf("failed to make pkscript "+
-					"for %s: %v", msg, err)
-			}
-
-			scriptAddr, err := btcutil.NewAddressScriptHash(
-				pkScript, &chaincfg.TestNet3Params)
-			if err != nil {
-				t.Errorf("failed to make p2sh addr for %s: %v",
-					msg, err)
-				break
-			}
-
-			scriptPkScript, err := txscript.PayToAddrScript(
-				scriptAddr)
-			if err != nil {
-				t.Errorf("failed to make script pkscript for "+
-					"%s: %v", msg, err)
-				break
-			}
-
-			if err := signAndCheck(msg, tx, i, scriptPkScript,
-				hashType,
-				mkGetKey(map[string]addressToKey{
-					address.EncodeAddress(): {key, true},
-				}), mkGetScript(map[string][]byte{
-					scriptAddr.EncodeAddress(): pkScript,
-				}), []byte{}); err != nil {
-				t.Error(err)
-				break
-			}
-		}
-	}
-
-	// Pay to PubKey (compressed)
-	for _, hashType := range hashTypes {
-		for i := range tx.TxIn {
-			msg := fmt.Sprintf("%d:%d", hashType, i)
-
-			key, err := btcec.NewPrivateKey(btcec.S256())
-			if err != nil {
-				t.Errorf("failed to make privKey for %s: %v",
-					msg, err)
-				break
-			}
-
-			pk := (*btcec.PublicKey)(&key.PublicKey).
-				SerializeCompressed()
-			address, err := btcutil.NewAddressPubKey(pk,
-				&chaincfg.TestNet3Params)
-			if err != nil {
-				t.Errorf("failed to make address for %s: %v",
-					msg, err)
-				break
-			}
-
-			pkScript, err := txscript.PayToAddrScript(address)
-			if err != nil {
-				t.Errorf("failed to make pkscript "+
-					"for %s: %v", msg, err)
-			}
-
-			scriptAddr, err := btcutil.NewAddressScriptHash(
-				pkScript, &chaincfg.TestNet3Params)
-			if err != nil {
-				t.Errorf("failed to make p2sh addr for %s: %v",
-					msg, err)
-				break
-			}
-
-			scriptPkScript, err := txscript.PayToAddrScript(
-				scriptAddr)
-			if err != nil {
-				t.Errorf("failed to make script pkscript for "+
-					"%s: %v", msg, err)
-				break
-			}
-
-			sigScript, err := txscript.SignTxOutput(
-				&chaincfg.TestNet3Params, tx, i, scriptPkScript,
-				hashType, mkGetKey(map[string]addressToKey{
-					address.EncodeAddress(): {key, true},
-				}), mkGetScript(map[string][]byte{
-					scriptAddr.EncodeAddress(): pkScript,
-				}), []byte{})
-			if err != nil {
-				t.Errorf("failed to sign output %s: %v", msg,
-					err)
-				break
-			}
-
-			// by the above loop, this should be valid, now sign
-			// again and merge.
-			sigScript, err = txscript.SignTxOutput(
-				&chaincfg.TestNet3Params, tx, i, scriptPkScript,
-				hashType, mkGetKey(map[string]addressToKey{
-					address.EncodeAddress(): {key, true},
-				}), mkGetScript(map[string][]byte{
-					scriptAddr.EncodeAddress(): pkScript,
-				}), []byte{})
-			if err != nil {
-				t.Errorf("failed to sign output %s a "+
-					"second time: %v", msg, err)
-				break
-			}
-
-			err = checkScripts(msg, tx, i, sigScript, scriptPkScript)
-			if err != nil {
-				t.Errorf("twice signed script invalid for "+
-					"%s: %v", msg, err)
-				break
-			}
-		}
-	}
-
-	// Basic Multisig
-	for _, hashType := range hashTypes {
-		for i := range tx.TxIn {
-			msg := fmt.Sprintf("%d:%d", hashType, i)
-
-			key1, err := btcec.NewPrivateKey(btcec.S256())
-			if err != nil {
-				t.Errorf("failed to make privKey for %s: %v",
-					msg, err)
-				break
-			}
-
-			pk1 := (*btcec.PublicKey)(&key1.PublicKey).
-				SerializeCompressed()
-			address1, err := btcutil.NewAddressPubKey(pk1,
-				&chaincfg.TestNet3Params)
-			if err != nil {
-				t.Errorf("failed to make address for %s: %v",
-					msg, err)
-				break
-			}
-
-			key2, err := btcec.NewPrivateKey(btcec.S256())
-			if err != nil {
-				t.Errorf("failed to make privKey 2 for %s: %v",
-					msg, err)
-				break
-			}
-
-			pk2 := (*btcec.PublicKey)(&key2.PublicKey).
-				SerializeCompressed()
-			address2, err := btcutil.NewAddressPubKey(pk2,
-				&chaincfg.TestNet3Params)
-			if err != nil {
-				t.Errorf("failed to make address 2 for %s: %v",
-					msg, err)
-				break
-			}
-
-			pkScript, err := txscript.MultiSigScript(
-				[]*btcutil.AddressPubKey{address1, address2},
-				2)
-			if err != nil {
-				t.Errorf("failed to make pkscript "+
-					"for %s: %v", msg, err)
-			}
-
-			scriptAddr, err := btcutil.NewAddressScriptHash(
-				pkScript, &chaincfg.TestNet3Params)
-			if err != nil {
-				t.Errorf("failed to make p2sh addr for %s: %v",
-					msg, err)
-				break
-			}
-
-			scriptPkScript, err := txscript.PayToAddrScript(
-				scriptAddr)
-			if err != nil {
-				t.Errorf("failed to make script pkscript for "+
-					"%s: %v", msg, err)
-				break
-			}
-
-			if err := signAndCheck(msg, tx, i, scriptPkScript,
-				hashType,
-				mkGetKey(map[string]addressToKey{
-					address1.EncodeAddress(): {key1, true},
-					address2.EncodeAddress(): {key2, true},
-				}), mkGetScript(map[string][]byte{
-					scriptAddr.EncodeAddress(): pkScript,
-				}), []byte{}); err != nil {
-				t.Error(err)
-				break
-			}
-		}
-	}
-
-	// Two part multisig, sign with one key then the other.
-	for _, hashType := range hashTypes {
-		for i := range tx.TxIn {
-			msg := fmt.Sprintf("%d:%d", hashType, i)
-
-			key1, err := btcec.NewPrivateKey(btcec.S256())
-			if err != nil {
-				t.Errorf("failed to make privKey for %s: %v",
-					msg, err)
-				break
-			}
-
-			pk1 := (*btcec.PublicKey)(&key1.PublicKey).
-				SerializeCompressed()
-			address1, err := btcutil.NewAddressPubKey(pk1,
-				&chaincfg.TestNet3Params)
-			if err != nil {
-				t.Errorf("failed to make address for %s: %v",
-					msg, err)
-				break
-			}
-
-			key2, err := btcec.NewPrivateKey(btcec.S256())
-			if err != nil {
-				t.Errorf("failed to make privKey 2 for %s: %v",
-					msg, err)
-				break
-			}
-
-			pk2 := (*btcec.PublicKey)(&key2.PublicKey).
-				SerializeCompressed()
-			address2, err := btcutil.NewAddressPubKey(pk2,
-				&chaincfg.TestNet3Params)
-			if err != nil {
-				t.Errorf("failed to make address 2 for %s: %v",
-					msg, err)
-				break
-			}
-
-			pkScript, err := txscript.MultiSigScript(
-				[]*btcutil.AddressPubKey{address1, address2},
-				2)
-			if err != nil {
-				t.Errorf("failed to make pkscript "+
-					"for %s: %v", msg, err)
-			}
-
-			scriptAddr, err := btcutil.NewAddressScriptHash(
-				pkScript, &chaincfg.TestNet3Params)
-			if err != nil {
-				t.Errorf("failed to make p2sh addr for %s: %v",
-					msg, err)
-				break
-			}
-
-			scriptPkScript, err := txscript.PayToAddrScript(
-				scriptAddr)
-			if err != nil {
-				t.Errorf("failed to make script pkscript for "+
-					"%s: %v", msg, err)
-				break
-			}
-
-			sigScript, err := txscript.SignTxOutput(
-				&chaincfg.TestNet3Params, tx, i, scriptPkScript,
-				hashType, mkGetKey(map[string]addressToKey{
-					address1.EncodeAddress(): {key1, true},
-				}), mkGetScript(map[string][]byte{
-					scriptAddr.EncodeAddress(): pkScript,
-				}), []byte{})
-			if err != nil {
-				t.Errorf("failed to sign output %s: %v", msg,
-					err)
-				break
-			}
-
-			// Only 1 out of 2 signed, this *should* fail.
-			if checkScripts(msg, tx, i, sigScript,
-				scriptPkScript) == nil {
-				t.Errorf("part signed script valid for %s", msg)
-				break
-			}
-
-			// Sign with the other key and merge
-			sigScript, err = txscript.SignTxOutput(
-				&chaincfg.TestNet3Params, tx, i, scriptPkScript,
-				hashType, mkGetKey(map[string]addressToKey{
-					address2.EncodeAddress(): {key2, true},
-				}), mkGetScript(map[string][]byte{
-					scriptAddr.EncodeAddress(): pkScript,
-				}), sigScript)
-			if err != nil {
-				t.Errorf("failed to sign output %s: %v", msg, err)
-				break
-			}
-
-			err = checkScripts(msg, tx, i, sigScript,
-				scriptPkScript)
-			if err != nil {
-				t.Errorf("fully signed script invalid for "+
-					"%s: %v", msg, err)
-				break
-			}
-		}
-	}
-
-	// Two part multisig, sign with one key then both, check key dedup
-	// correctly.
-	for _, hashType := range hashTypes {
-		for i := range tx.TxIn {
-			msg := fmt.Sprintf("%d:%d", hashType, i)
-
-			key1, err := btcec.NewPrivateKey(btcec.S256())
-			if err != nil {
-				t.Errorf("failed to make privKey for %s: %v",
-					msg, err)
-				break
-			}
-
-			pk1 := (*btcec.PublicKey)(&key1.PublicKey).
-				SerializeCompressed()
-			address1, err := btcutil.NewAddressPubKey(pk1,
-				&chaincfg.TestNet3Params)
-			if err != nil {
-				t.Errorf("failed to make address for %s: %v",
-					msg, err)
-				break
-			}
-
-			key2, err := btcec.NewPrivateKey(btcec.S256())
-			if err != nil {
-				t.Errorf("failed to make privKey 2 for %s: %v",
-					msg, err)
-				break
-			}
-
-			pk2 := (*btcec.PublicKey)(&key2.PublicKey).
-				SerializeCompressed()
-			address2, err := btcutil.NewAddressPubKey(pk2,
-				&chaincfg.TestNet3Params)
-			if err != nil {
-				t.Errorf("failed to make address 2 for %s: %v",
-					msg, err)
-				break
-			}
-
-			pkScript, err := txscript.MultiSigScript(
-				[]*btcutil.AddressPubKey{address1, address2},
-				2)
-			if err != nil {
-				t.Errorf("failed to make pkscript "+
-					"for %s: %v", msg, err)
-			}
-
-			scriptAddr, err := btcutil.NewAddressScriptHash(
-				pkScript, &chaincfg.TestNet3Params)
-			if err != nil {
-				t.Errorf("failed to make p2sh addr for %s: %v",
-					msg, err)
-				break
-			}
-
-			scriptPkScript, err := txscript.PayToAddrScript(
-				scriptAddr)
-			if err != nil {
-				t.Errorf("failed to make script pkscript for "+
-					"%s: %v", msg, err)
-				break
-			}
-
-			sigScript, err := txscript.SignTxOutput(
-				&chaincfg.TestNet3Params, tx, i, scriptPkScript,
-				hashType, mkGetKey(map[string]addressToKey{
-					address1.EncodeAddress(): {key1, true},
-				}), mkGetScript(map[string][]byte{
-					scriptAddr.EncodeAddress(): pkScript,
-				}), []byte{})
-			if err != nil {
-				t.Errorf("failed to sign output %s: %v", msg,
-					err)
-				break
-			}
-
-			// Only 1 out of 2 signed, this *should* fail.
-			if checkScripts(msg, tx, i, sigScript,
-				scriptPkScript) == nil {
-				t.Errorf("part signed script valid for %s", msg)
-				break
-			}
-
-			// Sign with the other key and merge
-			sigScript, err = txscript.SignTxOutput(
-				&chaincfg.TestNet3Params, tx, i, scriptPkScript,
-				hashType, mkGetKey(map[string]addressToKey{
-					address1.EncodeAddress(): {key1, true},
-					address2.EncodeAddress(): {key2, true},
-				}), mkGetScript(map[string][]byte{
-					scriptAddr.EncodeAddress(): pkScript,
-				}), sigScript)
-			if err != nil {
-				t.Errorf("failed to sign output %s: %v", msg, err)
-				break
-			}
-
-			// Now we should pass.
-			err = checkScripts(msg, tx, i, sigScript,
-				scriptPkScript)
-			if err != nil {
-				t.Errorf("fully signed script invalid for "+
-					"%s: %v", msg, err)
-				break
-			}
-		}
-	}
-}
-
 func TestCalcMultiSigStats(t *testing.T) {
 	t.Parallel()
 
diff --git a/txscript/sign.go b/txscript/sign.go
new file mode 100644
index 000000000..9aa5e631e
--- /dev/null
+++ b/txscript/sign.go
@@ -0,0 +1,411 @@
+// Copyright (c) 2013-2015 Conformal Systems LLC.
+// Use of this source code is governed by an ISC
+// license that can be found in the LICENSE file.
+
+package txscript
+
+import (
+	"errors"
+	"fmt"
+
+	"github.com/btcsuite/btcd/btcec"
+	"github.com/btcsuite/btcd/chaincfg"
+	"github.com/btcsuite/btcd/wire"
+	"github.com/btcsuite/btcutil"
+)
+
+// RawTxInSignature returns the serialized ECDSA signature for the input idx of
+// the given transaction, with hashType appended to it.
+func RawTxInSignature(tx *wire.MsgTx, idx int, 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 := calcScriptHash(parsedScript, hashType, tx, idx)
+	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
+}
+
+// SignatureScript creates an input signature script for tx to spend BTC sent
+// from a previous output to the owner of privKey. tx must include all
+// transaction inputs and outputs, however txin scripts are allowed to be filled
+// or empty. The returned script is calculated to be used as the idx'th txin
+// sigscript for tx. subscript is the PkScript of the previous output being used
+// as the idx'th input. privKey is serialized in either a compressed or
+// uncompressed format based on compress. This format must match the same format
+// used to generate the payment address, or the script validation will fail.
+func SignatureScript(tx *wire.MsgTx, idx int, subscript []byte, hashType SigHashType, privKey *btcec.PrivateKey, compress bool) ([]byte, error) {
+	sig, err := RawTxInSignature(tx, idx, subscript, hashType, privKey)
+	if err != nil {
+		return nil, err
+	}
+
+	pk := (*btcec.PublicKey)(&privKey.PublicKey)
+	var pkData []byte
+	if compress {
+		pkData = pk.SerializeCompressed()
+	} else {
+		pkData = pk.SerializeUncompressed()
+	}
+
+	return NewScriptBuilder().AddData(sig).AddData(pkData).Script()
+}
+
+func p2pkSignatureScript(tx *wire.MsgTx, idx int, subScript []byte, hashType SigHashType, privKey *btcec.PrivateKey) ([]byte, error) {
+	sig, err := RawTxInSignature(tx, idx, subScript, hashType, privKey)
+	if err != nil {
+		return nil, err
+	}
+
+	return NewScriptBuilder().AddData(sig).Script()
+}
+
+// signMultiSig signs as many of the outputs in the provided multisig script as
+// possible. It returns the generated script and a boolean if the script fulfils
+// the contract (i.e. nrequired signatures are provided).  Since it is arguably
+// legal to not be able to sign any of the outputs, no error is returned.
+func signMultiSig(tx *wire.MsgTx, idx int, subScript []byte, hashType SigHashType,
+	addresses []btcutil.Address, nRequired int, kdb KeyDB) ([]byte, bool) {
+	// We start with a single OP_FALSE to work around the (now standard)
+	// but in the reference implementation that causes a spurious pop at
+	// the end of OP_CHECKMULTISIG.
+	builder := NewScriptBuilder().AddOp(OP_FALSE)
+	signed := 0
+	for _, addr := range addresses {
+		key, _, err := kdb.GetKey(addr)
+		if err != nil {
+			continue
+		}
+		sig, err := RawTxInSignature(tx, idx, subScript, hashType, key)
+		if err != nil {
+			continue
+		}
+
+		builder.AddData(sig)
+		signed++
+		if signed == nRequired {
+			break
+		}
+
+	}
+
+	script, _ := builder.Script()
+	return script, signed == nRequired
+}
+
+func sign(chainParams *chaincfg.Params, tx *wire.MsgTx, idx int,
+	subScript []byte, 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:
+		// look up key for address
+		key, _, err := kdb.GetKey(addresses[0])
+		if err != nil {
+			return nil, class, nil, 0, err
+		}
+
+		script, err := p2pkSignatureScript(tx, idx, subScript, hashType,
+			key)
+		if err != nil {
+			return nil, class, nil, 0, err
+		}
+
+		return script, class, addresses, nrequired, nil
+	case PubKeyHashTy:
+		// look up key for address
+		key, compressed, err := kdb.GetKey(addresses[0])
+		if err != nil {
+			return nil, class, nil, 0, err
+		}
+
+		script, err := SignatureScript(tx, idx, subScript, hashType,
+			key, compressed)
+		if err != nil {
+			return nil, class, nil, 0, err
+		}
+
+		return script, class, addresses, nrequired, nil
+	case ScriptHashTy:
+		script, err := sdb.GetScript(addresses[0])
+		if err != nil {
+			return nil, class, nil, 0, err
+		}
+
+		return script, class, addresses, nrequired, nil
+	case MultiSigTy:
+		script, _ := signMultiSig(tx, idx, subScript, hashType,
+			addresses, nrequired, kdb)
+		return script, 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")
+	}
+}
+
+// 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.
+func mergeScripts(chainParams *chaincfg.Params, tx *wire.MsgTx, idx int,
+	pkScript []byte, class ScriptClass, addresses []btcutil.Address,
+	nRequired int, sigScript, prevScript []byte) []byte {
+
+	// TODO(oga) the scripthash and multisig paths here are overly
+	// inefficient in that they will recompute already known data.
+	// some internal refactoring could probably make this avoid needless
+	// extra calculations.
+	switch class {
+	case ScriptHashTy:
+		// Remove the last push in the script and then recurse.
+		// this could be a lot less inefficient.
+		sigPops, err := parseScript(sigScript)
+		if err != nil || len(sigPops) == 0 {
+			return prevScript
+		}
+		prevPops, err := parseScript(prevScript)
+		if err != nil || len(prevPops) == 0 {
+			return sigScript
+		}
+
+		// assume that script in sigPops is the correct one, we just
+		// made it.
+		script := sigPops[len(sigPops)-1].data
+
+		// We already know this information somewhere up the stack.
+		class, addresses, nrequired, err :=
+			ExtractPkScriptAddrs(script, chainParams)
+
+		// regenerate scripts.
+		sigScript, _ := unparseScript(sigPops)
+		prevScript, _ := unparseScript(prevPops)
+
+		// Merge
+		mergedScript := mergeScripts(chainParams, tx, idx, script,
+			class, addresses, nrequired, sigScript, prevScript)
+
+		// Reappend the script and return the result.
+		builder := NewScriptBuilder()
+		builder.script = mergedScript
+		builder.AddData(script)
+		finalScript, _ := builder.Script()
+		return finalScript
+	case MultiSigTy:
+		return mergeMultiSig(tx, idx, addresses, nRequired, pkScript,
+			sigScript, prevScript)
+
+	// It doesn't actualy make sense to merge anything other than multiig
+	// and scripthash (because it could contain multisig). Everything else
+	// has either zero signature, can't be spent, or has a single signature
+	// which is either present or not. The other two cases are handled
+	// above. In the conflict case here we just assume the longest is
+	// correct (this matches behaviour of the reference implementation).
+	default:
+		if len(sigScript) > len(prevScript) {
+			return sigScript
+		}
+		return prevScript
+	}
+}
+
+// mergeMultiSig combines the two signature scripts sigScript and prevScript
+// that both provide signatures for pkScript in output idx of tx. addresses
+// and nRequired should be the results from extracting the addresses from
+// pkScript. Since this function is internal only we assume that the arguments
+// have come from other functions internally and thus are all consistent with
+// each other, behaviour is undefined if this contract is broken.
+func mergeMultiSig(tx *wire.MsgTx, idx int, addresses []btcutil.Address,
+	nRequired int, pkScript, sigScript, prevScript []byte) []byte {
+
+	// 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)
+
+	sigPops, err := parseScript(sigScript)
+	if err != nil || len(sigPops) == 0 {
+		return prevScript
+	}
+
+	prevPops, err := parseScript(prevScript)
+	if err != nil || len(prevPops) == 0 {
+		return sigScript
+	}
+
+	// Convenience function to avoid duplication.
+	extractSigs := func(pops []parsedOpcode, sigs [][]byte) [][]byte {
+		for _, pop := range pops {
+			if len(pop.data) != 0 {
+				sigs = append(sigs, pop.data)
+			}
+		}
+		return sigs
+	}
+
+	possibleSigs := make([][]byte, 0, len(sigPops)+len(prevPops))
+	possibleSigs = extractSigs(sigPops, possibleSigs)
+	possibleSigs = extractSigs(prevPops, possibleSigs)
+
+	// Now we need to match the signatures to pubkeys, the only real way to
+	// do that is to try to verify them all and match it to the pubkey
+	// that verifies it. we then can go through the addresses in order
+	// to build our script. Anything that doesn't parse or doesn't verify we
+	// throw away.
+	addrToSig := make(map[string][]byte)
+sigLoop:
+	for _, sig := range possibleSigs {
+
+		// can't have a valid signature that doesn't at least have a
+		// hashtype, in practise it is even longer than this. but
+		// that'll be checked next.
+		if len(sig) < 1 {
+			continue
+		}
+		tSig := sig[:len(sig)-1]
+		hashType := SigHashType(sig[len(sig)-1])
+
+		pSig, err := btcec.ParseDERSignature(tSig, btcec.S256())
+		if err != nil {
+			continue
+		}
+
+		// We have to do this each round since hash types may vary
+		// between signatures and so the hash will vary. We can,
+		// however, assume no sigs etc are in the script since that
+		// would make the transaction nonstandard and thus not
+		// MultiSigTy, so we just need to hash the full thing.
+		hash := calcScriptHash(pkPops, hashType, tx, idx)
+
+		for _, addr := range addresses {
+			// All multisig addresses should be pubkey addreses
+			// it is an error to call this internal function with
+			// bad input.
+			pkaddr := addr.(*btcutil.AddressPubKey)
+
+			pubKey := pkaddr.PubKey()
+
+			// If it matches we put it in the map. We only
+			// can take one signature per public key so if we
+			// already have one, we can throw this away.
+			if pSig.Verify(hash, pubKey) {
+				aStr := addr.EncodeAddress()
+				if _, ok := addrToSig[aStr]; !ok {
+					addrToSig[aStr] = sig
+				}
+				continue sigLoop
+			}
+		}
+	}
+
+	// Extra opcode to handle the extra arg consumed (due to previous bugs
+	// in the reference implementation).
+	builder := NewScriptBuilder().AddOp(OP_FALSE)
+	doneSigs := 0
+	// This assumes that addresses are in the same order as in the script.
+	for _, addr := range addresses {
+		sig, ok := addrToSig[addr.EncodeAddress()]
+		if !ok {
+			continue
+		}
+		builder.AddData(sig)
+		doneSigs++
+		if doneSigs == nRequired {
+			break
+		}
+	}
+
+	// padding for missing ones.
+	for i := doneSigs; i < nRequired; i++ {
+		builder.AddOp(OP_0)
+	}
+
+	script, _ := builder.Script()
+	return script
+}
+
+// KeyDB is an interface type provided to SignTxOutput, it encapsulates
+// any user state required to get the private keys for an address.
+type KeyDB interface {
+	GetKey(btcutil.Address) (*btcec.PrivateKey, bool, error)
+}
+
+// KeyClosure implements ScriptDB with a closure
+type KeyClosure func(btcutil.Address) (*btcec.PrivateKey, bool, error)
+
+// GetKey implements KeyDB by returning the result of calling the closure
+func (kc KeyClosure) GetKey(address btcutil.Address) (*btcec.PrivateKey,
+	bool, error) {
+	return kc(address)
+}
+
+// ScriptDB is an interface type provided to SignTxOutput, it encapsulates any
+// user state required to get the scripts for an pay-to-script-hash address.
+type ScriptDB interface {
+	GetScript(btcutil.Address) ([]byte, error)
+}
+
+// ScriptClosure implements ScriptDB with a closure
+type ScriptClosure func(btcutil.Address) ([]byte, error)
+
+// GetScript implements ScriptDB by returning the result of calling the closure
+func (sc ScriptClosure) GetScript(address btcutil.Address) ([]byte, error) {
+	return sc(address)
+}
+
+// SignTxOutput signs output idx of the given tx to resolve the script given in
+// pkScript with a signature type of hashType. Any keys required will be
+// looked up by calling getKey() with the string of the given address.
+// Any pay-to-script-hash signatures will be similarly looked up by calling
+// getScript. If previousScript is provided then the results in previousScript
+// will be merged in a type-dependant manner with the newly generated.
+// signature script.
+func SignTxOutput(chainParams *chaincfg.Params, tx *wire.MsgTx, idx int,
+	pkScript []byte, hashType SigHashType, kdb KeyDB, sdb ScriptDB,
+	previousScript []byte) ([]byte, error) {
+
+	sigScript, class, addresses, nrequired, err := sign(chainParams, tx,
+		idx, pkScript, hashType, kdb, sdb)
+	if err != nil {
+		return nil, err
+	}
+
+	if class == ScriptHashTy {
+		// TODO keep the sub addressed and pass down to merge.
+		realSigScript, _, _, _, err := sign(chainParams, tx, idx,
+			sigScript, hashType, kdb, sdb)
+		if err != nil {
+			return nil, err
+		}
+
+		// This is a bad thing. Append the p2sh script as the last
+		// push in the script.
+		builder := NewScriptBuilder()
+		builder.script = realSigScript
+		builder.AddData(sigScript)
+
+		sigScript, _ = builder.Script()
+		// TODO keep a copy of the script for merging.
+	}
+
+	// Merge scripts. with any previous data, if any.
+	mergedScript := mergeScripts(chainParams, tx, idx, pkScript, class,
+		addresses, nrequired, sigScript, previousScript)
+	return mergedScript, nil
+}
diff --git a/txscript/sign_test.go b/txscript/sign_test.go
new file mode 100644
index 000000000..a391693ea
--- /dev/null
+++ b/txscript/sign_test.go
@@ -0,0 +1,1714 @@
+// Copyright (c) 2013-2015 Conformal Systems LLC.
+// Use of this source code is governed by an ISC
+// license that can be found in the LICENSE file.
+
+package txscript_test
+
+import (
+	"errors"
+	"fmt"
+	"testing"
+
+	"github.com/btcsuite/btcd/btcec"
+	"github.com/btcsuite/btcd/chaincfg"
+	"github.com/btcsuite/btcd/txscript"
+	"github.com/btcsuite/btcd/wire"
+	"github.com/btcsuite/btcutil"
+)
+
+type addressToKey struct {
+	key        *btcec.PrivateKey
+	compressed bool
+}
+
+func mkGetKey(keys map[string]addressToKey) txscript.KeyDB {
+	if keys == nil {
+		return txscript.KeyClosure(func(addr btcutil.Address) (*btcec.PrivateKey,
+			bool, error) {
+			return nil, false, errors.New("nope")
+		})
+	}
+	return txscript.KeyClosure(func(addr btcutil.Address) (*btcec.PrivateKey,
+		bool, error) {
+		a2k, ok := keys[addr.EncodeAddress()]
+		if !ok {
+			return nil, false, errors.New("nope")
+		}
+		return a2k.key, a2k.compressed, nil
+	})
+}
+
+func mkGetScript(scripts map[string][]byte) txscript.ScriptDB {
+	if scripts == nil {
+		return txscript.ScriptClosure(func(addr btcutil.Address) (
+			[]byte, error) {
+			return nil, errors.New("nope")
+		})
+	}
+	return txscript.ScriptClosure(func(addr btcutil.Address) ([]byte,
+		error) {
+		script, ok := scripts[addr.EncodeAddress()]
+		if !ok {
+			return nil, errors.New("nope")
+		}
+		return script, nil
+	})
+}
+
+func checkScripts(msg string, tx *wire.MsgTx, idx int, sigScript, pkScript []byte) error {
+	tx.TxIn[idx].SignatureScript = sigScript
+	vm, err := txscript.NewEngine(pkScript, tx, idx,
+		txscript.ScriptBip16|txscript.ScriptVerifyDERSignatures)
+	if err != nil {
+		return fmt.Errorf("failed to make script engine for %s: %v",
+			msg, err)
+	}
+
+	err = vm.Execute()
+	if err != nil {
+		return fmt.Errorf("invalid script signature for %s: %v", msg,
+			err)
+	}
+
+	return nil
+}
+
+func signAndCheck(msg string, tx *wire.MsgTx, idx int, pkScript []byte,
+	hashType txscript.SigHashType, kdb txscript.KeyDB, sdb txscript.ScriptDB,
+	previousScript []byte) error {
+
+	sigScript, err := txscript.SignTxOutput(&chaincfg.TestNet3Params, tx,
+		idx, pkScript, hashType, kdb, sdb, []byte{})
+	if err != nil {
+		return fmt.Errorf("failed to sign output %s: %v", msg, err)
+	}
+
+	return checkScripts(msg, tx, idx, sigScript, pkScript)
+}
+
+func TestSignTxOutput(t *testing.T) {
+	t.Parallel()
+
+	// make key
+	// make script based on key.
+	// sign with magic pixie dust.
+	hashTypes := []txscript.SigHashType{
+		txscript.SigHashOld, // no longer used but should act like all
+		txscript.SigHashAll,
+		txscript.SigHashNone,
+		txscript.SigHashSingle,
+		txscript.SigHashAll | txscript.SigHashAnyOneCanPay,
+		txscript.SigHashNone | txscript.SigHashAnyOneCanPay,
+		txscript.SigHashSingle | txscript.SigHashAnyOneCanPay,
+	}
+	tx := &wire.MsgTx{
+		Version: 1,
+		TxIn: []*wire.TxIn{
+			&wire.TxIn{
+				PreviousOutPoint: wire.OutPoint{
+					Hash:  wire.ShaHash{},
+					Index: 0,
+				},
+				Sequence: 4294967295,
+			},
+			&wire.TxIn{
+				PreviousOutPoint: wire.OutPoint{
+					Hash:  wire.ShaHash{},
+					Index: 1,
+				},
+				Sequence: 4294967295,
+			},
+			&wire.TxIn{
+				PreviousOutPoint: wire.OutPoint{
+					Hash:  wire.ShaHash{},
+					Index: 2,
+				},
+				Sequence: 4294967295,
+			},
+		},
+		TxOut: []*wire.TxOut{
+			&wire.TxOut{
+				Value: 1,
+			},
+			&wire.TxOut{
+				Value: 2,
+			},
+			&wire.TxOut{
+				Value: 3,
+			},
+		},
+		LockTime: 0,
+	}
+
+	// Pay to Pubkey Hash (uncompressed)
+	for _, hashType := range hashTypes {
+		for i := range tx.TxIn {
+			msg := fmt.Sprintf("%d:%d", hashType, i)
+			key, err := btcec.NewPrivateKey(btcec.S256())
+			if err != nil {
+				t.Errorf("failed to make privKey for %s: %v",
+					msg, err)
+				break
+			}
+
+			pk := (*btcec.PublicKey)(&key.PublicKey).
+				SerializeUncompressed()
+			address, err := btcutil.NewAddressPubKeyHash(
+				btcutil.Hash160(pk), &chaincfg.TestNet3Params)
+			if err != nil {
+				t.Errorf("failed to make address for %s: %v",
+					msg, err)
+				break
+			}
+
+			pkScript, err := txscript.PayToAddrScript(address)
+			if err != nil {
+				t.Errorf("failed to make pkscript "+
+					"for %s: %v", msg, err)
+			}
+
+			if err := signAndCheck(msg, tx, i, pkScript, hashType,
+				mkGetKey(map[string]addressToKey{
+					address.EncodeAddress(): {key, false},
+				}), mkGetScript(nil), []byte{}); err != nil {
+				t.Error(err)
+				break
+			}
+		}
+	}
+
+	// Pay to Pubkey Hash (uncompressed) (merging with correct)
+	for _, hashType := range hashTypes {
+		for i := range tx.TxIn {
+			msg := fmt.Sprintf("%d:%d", hashType, i)
+			key, err := btcec.NewPrivateKey(btcec.S256())
+			if err != nil {
+				t.Errorf("failed to make privKey for %s: %v",
+					msg, err)
+				break
+			}
+
+			pk := (*btcec.PublicKey)(&key.PublicKey).
+				SerializeUncompressed()
+			address, err := btcutil.NewAddressPubKeyHash(
+				btcutil.Hash160(pk), &chaincfg.TestNet3Params)
+			if err != nil {
+				t.Errorf("failed to make address for %s: %v",
+					msg, err)
+				break
+			}
+
+			pkScript, err := txscript.PayToAddrScript(address)
+			if err != nil {
+				t.Errorf("failed to make pkscript "+
+					"for %s: %v", msg, err)
+			}
+
+			sigScript, err := txscript.SignTxOutput(
+				&chaincfg.TestNet3Params, tx, i, pkScript,
+				hashType, mkGetKey(map[string]addressToKey{
+					address.EncodeAddress(): {key, false},
+				}), mkGetScript(nil), []byte{})
+			if err != nil {
+				t.Errorf("failed to sign output %s: %v", msg,
+					err)
+				break
+			}
+
+			// by the above loop, this should be valid, now sign
+			// again and merge.
+			sigScript, err = txscript.SignTxOutput(
+				&chaincfg.TestNet3Params, tx, i, pkScript,
+				hashType, mkGetKey(map[string]addressToKey{
+					address.EncodeAddress(): {key, false},
+				}), mkGetScript(nil), sigScript)
+			if err != nil {
+				t.Errorf("failed to sign output %s a "+
+					"second time: %v", msg, err)
+				break
+			}
+
+			err = checkScripts(msg, tx, i, sigScript, pkScript)
+			if err != nil {
+				t.Errorf("twice signed script invalid for "+
+					"%s: %v", msg, err)
+				break
+			}
+		}
+	}
+
+	// Pay to Pubkey Hash (compressed)
+	for _, hashType := range hashTypes {
+		for i := range tx.TxIn {
+			msg := fmt.Sprintf("%d:%d", hashType, i)
+
+			key, err := btcec.NewPrivateKey(btcec.S256())
+			if err != nil {
+				t.Errorf("failed to make privKey for %s: %v",
+					msg, err)
+				break
+			}
+
+			pk := (*btcec.PublicKey)(&key.PublicKey).
+				SerializeCompressed()
+			address, err := btcutil.NewAddressPubKeyHash(
+				btcutil.Hash160(pk), &chaincfg.TestNet3Params)
+			if err != nil {
+				t.Errorf("failed to make address for %s: %v",
+					msg, err)
+				break
+			}
+
+			pkScript, err := txscript.PayToAddrScript(address)
+			if err != nil {
+				t.Errorf("failed to make pkscript "+
+					"for %s: %v", msg, err)
+			}
+
+			if err := signAndCheck(msg, tx, i, pkScript, hashType,
+				mkGetKey(map[string]addressToKey{
+					address.EncodeAddress(): {key, true},
+				}), mkGetScript(nil), []byte{}); err != nil {
+				t.Error(err)
+				break
+			}
+		}
+	}
+
+	// Pay to Pubkey Hash (compressed) with duplicate merge
+	for _, hashType := range hashTypes {
+		for i := range tx.TxIn {
+			msg := fmt.Sprintf("%d:%d", hashType, i)
+
+			key, err := btcec.NewPrivateKey(btcec.S256())
+			if err != nil {
+				t.Errorf("failed to make privKey for %s: %v",
+					msg, err)
+				break
+			}
+
+			pk := (*btcec.PublicKey)(&key.PublicKey).
+				SerializeCompressed()
+			address, err := btcutil.NewAddressPubKeyHash(
+				btcutil.Hash160(pk), &chaincfg.TestNet3Params)
+			if err != nil {
+				t.Errorf("failed to make address for %s: %v",
+					msg, err)
+				break
+			}
+
+			pkScript, err := txscript.PayToAddrScript(address)
+			if err != nil {
+				t.Errorf("failed to make pkscript "+
+					"for %s: %v", msg, err)
+			}
+
+			sigScript, err := txscript.SignTxOutput(
+				&chaincfg.TestNet3Params, tx, i, pkScript,
+				hashType, mkGetKey(map[string]addressToKey{
+					address.EncodeAddress(): {key, true},
+				}), mkGetScript(nil), []byte{})
+			if err != nil {
+				t.Errorf("failed to sign output %s: %v", msg,
+					err)
+				break
+			}
+
+			// by the above loop, this should be valid, now sign
+			// again and merge.
+			sigScript, err = txscript.SignTxOutput(
+				&chaincfg.TestNet3Params, tx, i, pkScript,
+				hashType, mkGetKey(map[string]addressToKey{
+					address.EncodeAddress(): {key, true},
+				}), mkGetScript(nil), sigScript)
+			if err != nil {
+				t.Errorf("failed to sign output %s a "+
+					"second time: %v", msg, err)
+				break
+			}
+
+			err = checkScripts(msg, tx, i, sigScript, pkScript)
+			if err != nil {
+				t.Errorf("twice signed script invalid for "+
+					"%s: %v", msg, err)
+				break
+			}
+		}
+	}
+
+	// Pay to PubKey (uncompressed)
+	for _, hashType := range hashTypes {
+		for i := range tx.TxIn {
+			msg := fmt.Sprintf("%d:%d", hashType, i)
+
+			key, err := btcec.NewPrivateKey(btcec.S256())
+			if err != nil {
+				t.Errorf("failed to make privKey for %s: %v",
+					msg, err)
+				break
+			}
+
+			pk := (*btcec.PublicKey)(&key.PublicKey).
+				SerializeUncompressed()
+			address, err := btcutil.NewAddressPubKey(pk,
+				&chaincfg.TestNet3Params)
+			if err != nil {
+				t.Errorf("failed to make address for %s: %v",
+					msg, err)
+				break
+			}
+
+			pkScript, err := txscript.PayToAddrScript(address)
+			if err != nil {
+				t.Errorf("failed to make pkscript "+
+					"for %s: %v", msg, err)
+			}
+
+			if err := signAndCheck(msg, tx, i, pkScript, hashType,
+				mkGetKey(map[string]addressToKey{
+					address.EncodeAddress(): {key, false},
+				}), mkGetScript(nil), []byte{}); err != nil {
+				t.Error(err)
+				break
+			}
+		}
+	}
+
+	// Pay to PubKey (uncompressed)
+	for _, hashType := range hashTypes {
+		for i := range tx.TxIn {
+			msg := fmt.Sprintf("%d:%d", hashType, i)
+
+			key, err := btcec.NewPrivateKey(btcec.S256())
+			if err != nil {
+				t.Errorf("failed to make privKey for %s: %v",
+					msg, err)
+				break
+			}
+
+			pk := (*btcec.PublicKey)(&key.PublicKey).
+				SerializeUncompressed()
+			address, err := btcutil.NewAddressPubKey(pk,
+				&chaincfg.TestNet3Params)
+			if err != nil {
+				t.Errorf("failed to make address for %s: %v",
+					msg, err)
+				break
+			}
+
+			pkScript, err := txscript.PayToAddrScript(address)
+			if err != nil {
+				t.Errorf("failed to make pkscript "+
+					"for %s: %v", msg, err)
+			}
+
+			sigScript, err := txscript.SignTxOutput(
+				&chaincfg.TestNet3Params, tx, i, pkScript,
+				hashType, mkGetKey(map[string]addressToKey{
+					address.EncodeAddress(): {key, false},
+				}), mkGetScript(nil), []byte{})
+			if err != nil {
+				t.Errorf("failed to sign output %s: %v", msg,
+					err)
+				break
+			}
+
+			// by the above loop, this should be valid, now sign
+			// again and merge.
+			sigScript, err = txscript.SignTxOutput(
+				&chaincfg.TestNet3Params, tx, i, pkScript,
+				hashType, mkGetKey(map[string]addressToKey{
+					address.EncodeAddress(): {key, false},
+				}), mkGetScript(nil), sigScript)
+			if err != nil {
+				t.Errorf("failed to sign output %s a "+
+					"second time: %v", msg, err)
+				break
+			}
+
+			err = checkScripts(msg, tx, i, sigScript, pkScript)
+			if err != nil {
+				t.Errorf("twice signed script invalid for "+
+					"%s: %v", msg, err)
+				break
+			}
+		}
+	}
+
+	// Pay to PubKey (compressed)
+	for _, hashType := range hashTypes {
+		for i := range tx.TxIn {
+			msg := fmt.Sprintf("%d:%d", hashType, i)
+
+			key, err := btcec.NewPrivateKey(btcec.S256())
+			if err != nil {
+				t.Errorf("failed to make privKey for %s: %v",
+					msg, err)
+				break
+			}
+
+			pk := (*btcec.PublicKey)(&key.PublicKey).
+				SerializeCompressed()
+			address, err := btcutil.NewAddressPubKey(pk,
+				&chaincfg.TestNet3Params)
+			if err != nil {
+				t.Errorf("failed to make address for %s: %v",
+					msg, err)
+				break
+			}
+
+			pkScript, err := txscript.PayToAddrScript(address)
+			if err != nil {
+				t.Errorf("failed to make pkscript "+
+					"for %s: %v", msg, err)
+			}
+
+			if err := signAndCheck(msg, tx, i, pkScript, hashType,
+				mkGetKey(map[string]addressToKey{
+					address.EncodeAddress(): {key, true},
+				}), mkGetScript(nil), []byte{}); err != nil {
+				t.Error(err)
+				break
+			}
+		}
+	}
+
+	// Pay to PubKey (compressed) with duplicate merge
+	for _, hashType := range hashTypes {
+		for i := range tx.TxIn {
+			msg := fmt.Sprintf("%d:%d", hashType, i)
+
+			key, err := btcec.NewPrivateKey(btcec.S256())
+			if err != nil {
+				t.Errorf("failed to make privKey for %s: %v",
+					msg, err)
+				break
+			}
+
+			pk := (*btcec.PublicKey)(&key.PublicKey).
+				SerializeCompressed()
+			address, err := btcutil.NewAddressPubKey(pk,
+				&chaincfg.TestNet3Params)
+			if err != nil {
+				t.Errorf("failed to make address for %s: %v",
+					msg, err)
+				break
+			}
+
+			pkScript, err := txscript.PayToAddrScript(address)
+			if err != nil {
+				t.Errorf("failed to make pkscript "+
+					"for %s: %v", msg, err)
+			}
+
+			sigScript, err := txscript.SignTxOutput(
+				&chaincfg.TestNet3Params, tx, i, pkScript,
+				hashType, mkGetKey(map[string]addressToKey{
+					address.EncodeAddress(): {key, true},
+				}), mkGetScript(nil), []byte{})
+			if err != nil {
+				t.Errorf("failed to sign output %s: %v", msg,
+					err)
+				break
+			}
+
+			// by the above loop, this should be valid, now sign
+			// again and merge.
+			sigScript, err = txscript.SignTxOutput(
+				&chaincfg.TestNet3Params, tx, i, pkScript,
+				hashType, mkGetKey(map[string]addressToKey{
+					address.EncodeAddress(): {key, true},
+				}), mkGetScript(nil), sigScript)
+			if err != nil {
+				t.Errorf("failed to sign output %s a "+
+					"second time: %v", msg, err)
+				break
+			}
+
+			err = checkScripts(msg, tx, i, sigScript, pkScript)
+			if err != nil {
+				t.Errorf("twice signed script invalid for "+
+					"%s: %v", msg, err)
+				break
+			}
+		}
+	}
+
+	// As before, but with p2sh now.
+	// Pay to Pubkey Hash (uncompressed)
+	for _, hashType := range hashTypes {
+		for i := range tx.TxIn {
+			msg := fmt.Sprintf("%d:%d", hashType, i)
+			key, err := btcec.NewPrivateKey(btcec.S256())
+			if err != nil {
+				t.Errorf("failed to make privKey for %s: %v",
+					msg, err)
+				break
+			}
+
+			pk := (*btcec.PublicKey)(&key.PublicKey).
+				SerializeUncompressed()
+			address, err := btcutil.NewAddressPubKeyHash(
+				btcutil.Hash160(pk), &chaincfg.TestNet3Params)
+			if err != nil {
+				t.Errorf("failed to make address for %s: %v",
+					msg, err)
+				break
+			}
+
+			pkScript, err := txscript.PayToAddrScript(address)
+			if err != nil {
+				t.Errorf("failed to make pkscript "+
+					"for %s: %v", msg, err)
+				break
+			}
+
+			scriptAddr, err := btcutil.NewAddressScriptHash(
+				pkScript, &chaincfg.TestNet3Params)
+			if err != nil {
+				t.Errorf("failed to make p2sh addr for %s: %v",
+					msg, err)
+				break
+			}
+
+			scriptPkScript, err := txscript.PayToAddrScript(
+				scriptAddr)
+			if err != nil {
+				t.Errorf("failed to make script pkscript for "+
+					"%s: %v", msg, err)
+				break
+			}
+
+			if err := signAndCheck(msg, tx, i, scriptPkScript,
+				hashType,
+				mkGetKey(map[string]addressToKey{
+					address.EncodeAddress(): {key, false},
+				}), mkGetScript(map[string][]byte{
+					scriptAddr.EncodeAddress(): pkScript,
+				}), []byte{}); err != nil {
+				t.Error(err)
+				break
+			}
+		}
+	}
+
+	// Pay to Pubkey Hash (uncompressed) with duplicate merge
+	for _, hashType := range hashTypes {
+		for i := range tx.TxIn {
+			msg := fmt.Sprintf("%d:%d", hashType, i)
+			key, err := btcec.NewPrivateKey(btcec.S256())
+			if err != nil {
+				t.Errorf("failed to make privKey for %s: %v",
+					msg, err)
+				break
+			}
+
+			pk := (*btcec.PublicKey)(&key.PublicKey).
+				SerializeUncompressed()
+			address, err := btcutil.NewAddressPubKeyHash(
+				btcutil.Hash160(pk), &chaincfg.TestNet3Params)
+			if err != nil {
+				t.Errorf("failed to make address for %s: %v",
+					msg, err)
+				break
+			}
+
+			pkScript, err := txscript.PayToAddrScript(address)
+			if err != nil {
+				t.Errorf("failed to make pkscript "+
+					"for %s: %v", msg, err)
+				break
+			}
+
+			scriptAddr, err := btcutil.NewAddressScriptHash(
+				pkScript, &chaincfg.TestNet3Params)
+			if err != nil {
+				t.Errorf("failed to make p2sh addr for %s: %v",
+					msg, err)
+				break
+			}
+
+			scriptPkScript, err := txscript.PayToAddrScript(
+				scriptAddr)
+			if err != nil {
+				t.Errorf("failed to make script pkscript for "+
+					"%s: %v", msg, err)
+				break
+			}
+
+			sigScript, err := txscript.SignTxOutput(
+				&chaincfg.TestNet3Params, tx, i, scriptPkScript,
+				hashType, mkGetKey(map[string]addressToKey{
+					address.EncodeAddress(): {key, false},
+				}), mkGetScript(map[string][]byte{
+					scriptAddr.EncodeAddress(): pkScript,
+				}), []byte{})
+			if err != nil {
+				t.Errorf("failed to sign output %s: %v", msg,
+					err)
+				break
+			}
+
+			// by the above loop, this should be valid, now sign
+			// again and merge.
+			sigScript, err = txscript.SignTxOutput(
+				&chaincfg.TestNet3Params, tx, i, scriptPkScript,
+				hashType, mkGetKey(map[string]addressToKey{
+					address.EncodeAddress(): {key, false},
+				}), mkGetScript(map[string][]byte{
+					scriptAddr.EncodeAddress(): pkScript,
+				}), []byte{})
+			if err != nil {
+				t.Errorf("failed to sign output %s a "+
+					"second time: %v", msg, err)
+				break
+			}
+
+			err = checkScripts(msg, tx, i, sigScript, scriptPkScript)
+			if err != nil {
+				t.Errorf("twice signed script invalid for "+
+					"%s: %v", msg, err)
+				break
+			}
+		}
+	}
+
+	// Pay to Pubkey Hash (compressed)
+	for _, hashType := range hashTypes {
+		for i := range tx.TxIn {
+			msg := fmt.Sprintf("%d:%d", hashType, i)
+
+			key, err := btcec.NewPrivateKey(btcec.S256())
+			if err != nil {
+				t.Errorf("failed to make privKey for %s: %v",
+					msg, err)
+				break
+			}
+
+			pk := (*btcec.PublicKey)(&key.PublicKey).
+				SerializeCompressed()
+			address, err := btcutil.NewAddressPubKeyHash(
+				btcutil.Hash160(pk), &chaincfg.TestNet3Params)
+			if err != nil {
+				t.Errorf("failed to make address for %s: %v",
+					msg, err)
+				break
+			}
+
+			pkScript, err := txscript.PayToAddrScript(address)
+			if err != nil {
+				t.Errorf("failed to make pkscript "+
+					"for %s: %v", msg, err)
+			}
+
+			scriptAddr, err := btcutil.NewAddressScriptHash(
+				pkScript, &chaincfg.TestNet3Params)
+			if err != nil {
+				t.Errorf("failed to make p2sh addr for %s: %v",
+					msg, err)
+				break
+			}
+
+			scriptPkScript, err := txscript.PayToAddrScript(
+				scriptAddr)
+			if err != nil {
+				t.Errorf("failed to make script pkscript for "+
+					"%s: %v", msg, err)
+				break
+			}
+
+			if err := signAndCheck(msg, tx, i, scriptPkScript,
+				hashType,
+				mkGetKey(map[string]addressToKey{
+					address.EncodeAddress(): {key, true},
+				}), mkGetScript(map[string][]byte{
+					scriptAddr.EncodeAddress(): pkScript,
+				}), []byte{}); err != nil {
+				t.Error(err)
+				break
+			}
+		}
+	}
+
+	// Pay to Pubkey Hash (compressed) with duplicate merge
+	for _, hashType := range hashTypes {
+		for i := range tx.TxIn {
+			msg := fmt.Sprintf("%d:%d", hashType, i)
+
+			key, err := btcec.NewPrivateKey(btcec.S256())
+			if err != nil {
+				t.Errorf("failed to make privKey for %s: %v",
+					msg, err)
+				break
+			}
+
+			pk := (*btcec.PublicKey)(&key.PublicKey).
+				SerializeCompressed()
+			address, err := btcutil.NewAddressPubKeyHash(
+				btcutil.Hash160(pk), &chaincfg.TestNet3Params)
+			if err != nil {
+				t.Errorf("failed to make address for %s: %v",
+					msg, err)
+				break
+			}
+
+			pkScript, err := txscript.PayToAddrScript(address)
+			if err != nil {
+				t.Errorf("failed to make pkscript "+
+					"for %s: %v", msg, err)
+			}
+
+			scriptAddr, err := btcutil.NewAddressScriptHash(
+				pkScript, &chaincfg.TestNet3Params)
+			if err != nil {
+				t.Errorf("failed to make p2sh addr for %s: %v",
+					msg, err)
+				break
+			}
+
+			scriptPkScript, err := txscript.PayToAddrScript(
+				scriptAddr)
+			if err != nil {
+				t.Errorf("failed to make script pkscript for "+
+					"%s: %v", msg, err)
+				break
+			}
+
+			sigScript, err := txscript.SignTxOutput(
+				&chaincfg.TestNet3Params, tx, i, scriptPkScript,
+				hashType, mkGetKey(map[string]addressToKey{
+					address.EncodeAddress(): {key, true},
+				}), mkGetScript(map[string][]byte{
+					scriptAddr.EncodeAddress(): pkScript,
+				}), []byte{})
+			if err != nil {
+				t.Errorf("failed to sign output %s: %v", msg,
+					err)
+				break
+			}
+
+			// by the above loop, this should be valid, now sign
+			// again and merge.
+			sigScript, err = txscript.SignTxOutput(
+				&chaincfg.TestNet3Params, tx, i, scriptPkScript,
+				hashType, mkGetKey(map[string]addressToKey{
+					address.EncodeAddress(): {key, true},
+				}), mkGetScript(map[string][]byte{
+					scriptAddr.EncodeAddress(): pkScript,
+				}), []byte{})
+			if err != nil {
+				t.Errorf("failed to sign output %s a "+
+					"second time: %v", msg, err)
+				break
+			}
+
+			err = checkScripts(msg, tx, i, sigScript, scriptPkScript)
+			if err != nil {
+				t.Errorf("twice signed script invalid for "+
+					"%s: %v", msg, err)
+				break
+			}
+		}
+	}
+
+	// Pay to PubKey (uncompressed)
+	for _, hashType := range hashTypes {
+		for i := range tx.TxIn {
+			msg := fmt.Sprintf("%d:%d", hashType, i)
+
+			key, err := btcec.NewPrivateKey(btcec.S256())
+			if err != nil {
+				t.Errorf("failed to make privKey for %s: %v",
+					msg, err)
+				break
+			}
+
+			pk := (*btcec.PublicKey)(&key.PublicKey).
+				SerializeUncompressed()
+			address, err := btcutil.NewAddressPubKey(pk,
+				&chaincfg.TestNet3Params)
+			if err != nil {
+				t.Errorf("failed to make address for %s: %v",
+					msg, err)
+				break
+			}
+
+			pkScript, err := txscript.PayToAddrScript(address)
+			if err != nil {
+				t.Errorf("failed to make pkscript "+
+					"for %s: %v", msg, err)
+			}
+
+			scriptAddr, err := btcutil.NewAddressScriptHash(
+				pkScript, &chaincfg.TestNet3Params)
+			if err != nil {
+				t.Errorf("failed to make p2sh addr for %s: %v",
+					msg, err)
+				break
+			}
+
+			scriptPkScript, err := txscript.PayToAddrScript(
+				scriptAddr)
+			if err != nil {
+				t.Errorf("failed to make script pkscript for "+
+					"%s: %v", msg, err)
+				break
+			}
+
+			if err := signAndCheck(msg, tx, i, scriptPkScript,
+				hashType,
+				mkGetKey(map[string]addressToKey{
+					address.EncodeAddress(): {key, false},
+				}), mkGetScript(map[string][]byte{
+					scriptAddr.EncodeAddress(): pkScript,
+				}), []byte{}); err != nil {
+				t.Error(err)
+				break
+			}
+		}
+	}
+
+	// Pay to PubKey (uncompressed) with duplicate merge
+	for _, hashType := range hashTypes {
+		for i := range tx.TxIn {
+			msg := fmt.Sprintf("%d:%d", hashType, i)
+
+			key, err := btcec.NewPrivateKey(btcec.S256())
+			if err != nil {
+				t.Errorf("failed to make privKey for %s: %v",
+					msg, err)
+				break
+			}
+
+			pk := (*btcec.PublicKey)(&key.PublicKey).
+				SerializeUncompressed()
+			address, err := btcutil.NewAddressPubKey(pk,
+				&chaincfg.TestNet3Params)
+			if err != nil {
+				t.Errorf("failed to make address for %s: %v",
+					msg, err)
+				break
+			}
+
+			pkScript, err := txscript.PayToAddrScript(address)
+			if err != nil {
+				t.Errorf("failed to make pkscript "+
+					"for %s: %v", msg, err)
+			}
+
+			scriptAddr, err := btcutil.NewAddressScriptHash(
+				pkScript, &chaincfg.TestNet3Params)
+			if err != nil {
+				t.Errorf("failed to make p2sh addr for %s: %v",
+					msg, err)
+				break
+			}
+
+			scriptPkScript, err := txscript.PayToAddrScript(
+				scriptAddr)
+			if err != nil {
+				t.Errorf("failed to make script pkscript for "+
+					"%s: %v", msg, err)
+				break
+			}
+
+			sigScript, err := txscript.SignTxOutput(
+				&chaincfg.TestNet3Params, tx, i, scriptPkScript,
+				hashType, mkGetKey(map[string]addressToKey{
+					address.EncodeAddress(): {key, false},
+				}), mkGetScript(map[string][]byte{
+					scriptAddr.EncodeAddress(): pkScript,
+				}), []byte{})
+			if err != nil {
+				t.Errorf("failed to sign output %s: %v", msg,
+					err)
+				break
+			}
+
+			// by the above loop, this should be valid, now sign
+			// again and merge.
+			sigScript, err = txscript.SignTxOutput(
+				&chaincfg.TestNet3Params, tx, i, scriptPkScript,
+				hashType, mkGetKey(map[string]addressToKey{
+					address.EncodeAddress(): {key, false},
+				}), mkGetScript(map[string][]byte{
+					scriptAddr.EncodeAddress(): pkScript,
+				}), []byte{})
+			if err != nil {
+				t.Errorf("failed to sign output %s a "+
+					"second time: %v", msg, err)
+				break
+			}
+
+			err = checkScripts(msg, tx, i, sigScript, scriptPkScript)
+			if err != nil {
+				t.Errorf("twice signed script invalid for "+
+					"%s: %v", msg, err)
+				break
+			}
+		}
+	}
+
+	// Pay to PubKey (compressed)
+	for _, hashType := range hashTypes {
+		for i := range tx.TxIn {
+			msg := fmt.Sprintf("%d:%d", hashType, i)
+
+			key, err := btcec.NewPrivateKey(btcec.S256())
+			if err != nil {
+				t.Errorf("failed to make privKey for %s: %v",
+					msg, err)
+				break
+			}
+
+			pk := (*btcec.PublicKey)(&key.PublicKey).
+				SerializeCompressed()
+			address, err := btcutil.NewAddressPubKey(pk,
+				&chaincfg.TestNet3Params)
+			if err != nil {
+				t.Errorf("failed to make address for %s: %v",
+					msg, err)
+				break
+			}
+
+			pkScript, err := txscript.PayToAddrScript(address)
+			if err != nil {
+				t.Errorf("failed to make pkscript "+
+					"for %s: %v", msg, err)
+			}
+
+			scriptAddr, err := btcutil.NewAddressScriptHash(
+				pkScript, &chaincfg.TestNet3Params)
+			if err != nil {
+				t.Errorf("failed to make p2sh addr for %s: %v",
+					msg, err)
+				break
+			}
+
+			scriptPkScript, err := txscript.PayToAddrScript(
+				scriptAddr)
+			if err != nil {
+				t.Errorf("failed to make script pkscript for "+
+					"%s: %v", msg, err)
+				break
+			}
+
+			if err := signAndCheck(msg, tx, i, scriptPkScript,
+				hashType,
+				mkGetKey(map[string]addressToKey{
+					address.EncodeAddress(): {key, true},
+				}), mkGetScript(map[string][]byte{
+					scriptAddr.EncodeAddress(): pkScript,
+				}), []byte{}); err != nil {
+				t.Error(err)
+				break
+			}
+		}
+	}
+
+	// Pay to PubKey (compressed)
+	for _, hashType := range hashTypes {
+		for i := range tx.TxIn {
+			msg := fmt.Sprintf("%d:%d", hashType, i)
+
+			key, err := btcec.NewPrivateKey(btcec.S256())
+			if err != nil {
+				t.Errorf("failed to make privKey for %s: %v",
+					msg, err)
+				break
+			}
+
+			pk := (*btcec.PublicKey)(&key.PublicKey).
+				SerializeCompressed()
+			address, err := btcutil.NewAddressPubKey(pk,
+				&chaincfg.TestNet3Params)
+			if err != nil {
+				t.Errorf("failed to make address for %s: %v",
+					msg, err)
+				break
+			}
+
+			pkScript, err := txscript.PayToAddrScript(address)
+			if err != nil {
+				t.Errorf("failed to make pkscript "+
+					"for %s: %v", msg, err)
+			}
+
+			scriptAddr, err := btcutil.NewAddressScriptHash(
+				pkScript, &chaincfg.TestNet3Params)
+			if err != nil {
+				t.Errorf("failed to make p2sh addr for %s: %v",
+					msg, err)
+				break
+			}
+
+			scriptPkScript, err := txscript.PayToAddrScript(
+				scriptAddr)
+			if err != nil {
+				t.Errorf("failed to make script pkscript for "+
+					"%s: %v", msg, err)
+				break
+			}
+
+			sigScript, err := txscript.SignTxOutput(
+				&chaincfg.TestNet3Params, tx, i, scriptPkScript,
+				hashType, mkGetKey(map[string]addressToKey{
+					address.EncodeAddress(): {key, true},
+				}), mkGetScript(map[string][]byte{
+					scriptAddr.EncodeAddress(): pkScript,
+				}), []byte{})
+			if err != nil {
+				t.Errorf("failed to sign output %s: %v", msg,
+					err)
+				break
+			}
+
+			// by the above loop, this should be valid, now sign
+			// again and merge.
+			sigScript, err = txscript.SignTxOutput(
+				&chaincfg.TestNet3Params, tx, i, scriptPkScript,
+				hashType, mkGetKey(map[string]addressToKey{
+					address.EncodeAddress(): {key, true},
+				}), mkGetScript(map[string][]byte{
+					scriptAddr.EncodeAddress(): pkScript,
+				}), []byte{})
+			if err != nil {
+				t.Errorf("failed to sign output %s a "+
+					"second time: %v", msg, err)
+				break
+			}
+
+			err = checkScripts(msg, tx, i, sigScript, scriptPkScript)
+			if err != nil {
+				t.Errorf("twice signed script invalid for "+
+					"%s: %v", msg, err)
+				break
+			}
+		}
+	}
+
+	// Basic Multisig
+	for _, hashType := range hashTypes {
+		for i := range tx.TxIn {
+			msg := fmt.Sprintf("%d:%d", hashType, i)
+
+			key1, err := btcec.NewPrivateKey(btcec.S256())
+			if err != nil {
+				t.Errorf("failed to make privKey for %s: %v",
+					msg, err)
+				break
+			}
+
+			pk1 := (*btcec.PublicKey)(&key1.PublicKey).
+				SerializeCompressed()
+			address1, err := btcutil.NewAddressPubKey(pk1,
+				&chaincfg.TestNet3Params)
+			if err != nil {
+				t.Errorf("failed to make address for %s: %v",
+					msg, err)
+				break
+			}
+
+			key2, err := btcec.NewPrivateKey(btcec.S256())
+			if err != nil {
+				t.Errorf("failed to make privKey 2 for %s: %v",
+					msg, err)
+				break
+			}
+
+			pk2 := (*btcec.PublicKey)(&key2.PublicKey).
+				SerializeCompressed()
+			address2, err := btcutil.NewAddressPubKey(pk2,
+				&chaincfg.TestNet3Params)
+			if err != nil {
+				t.Errorf("failed to make address 2 for %s: %v",
+					msg, err)
+				break
+			}
+
+			pkScript, err := txscript.MultiSigScript(
+				[]*btcutil.AddressPubKey{address1, address2},
+				2)
+			if err != nil {
+				t.Errorf("failed to make pkscript "+
+					"for %s: %v", msg, err)
+			}
+
+			scriptAddr, err := btcutil.NewAddressScriptHash(
+				pkScript, &chaincfg.TestNet3Params)
+			if err != nil {
+				t.Errorf("failed to make p2sh addr for %s: %v",
+					msg, err)
+				break
+			}
+
+			scriptPkScript, err := txscript.PayToAddrScript(
+				scriptAddr)
+			if err != nil {
+				t.Errorf("failed to make script pkscript for "+
+					"%s: %v", msg, err)
+				break
+			}
+
+			if err := signAndCheck(msg, tx, i, scriptPkScript,
+				hashType,
+				mkGetKey(map[string]addressToKey{
+					address1.EncodeAddress(): {key1, true},
+					address2.EncodeAddress(): {key2, true},
+				}), mkGetScript(map[string][]byte{
+					scriptAddr.EncodeAddress(): pkScript,
+				}), []byte{}); err != nil {
+				t.Error(err)
+				break
+			}
+		}
+	}
+
+	// Two part multisig, sign with one key then the other.
+	for _, hashType := range hashTypes {
+		for i := range tx.TxIn {
+			msg := fmt.Sprintf("%d:%d", hashType, i)
+
+			key1, err := btcec.NewPrivateKey(btcec.S256())
+			if err != nil {
+				t.Errorf("failed to make privKey for %s: %v",
+					msg, err)
+				break
+			}
+
+			pk1 := (*btcec.PublicKey)(&key1.PublicKey).
+				SerializeCompressed()
+			address1, err := btcutil.NewAddressPubKey(pk1,
+				&chaincfg.TestNet3Params)
+			if err != nil {
+				t.Errorf("failed to make address for %s: %v",
+					msg, err)
+				break
+			}
+
+			key2, err := btcec.NewPrivateKey(btcec.S256())
+			if err != nil {
+				t.Errorf("failed to make privKey 2 for %s: %v",
+					msg, err)
+				break
+			}
+
+			pk2 := (*btcec.PublicKey)(&key2.PublicKey).
+				SerializeCompressed()
+			address2, err := btcutil.NewAddressPubKey(pk2,
+				&chaincfg.TestNet3Params)
+			if err != nil {
+				t.Errorf("failed to make address 2 for %s: %v",
+					msg, err)
+				break
+			}
+
+			pkScript, err := txscript.MultiSigScript(
+				[]*btcutil.AddressPubKey{address1, address2},
+				2)
+			if err != nil {
+				t.Errorf("failed to make pkscript "+
+					"for %s: %v", msg, err)
+			}
+
+			scriptAddr, err := btcutil.NewAddressScriptHash(
+				pkScript, &chaincfg.TestNet3Params)
+			if err != nil {
+				t.Errorf("failed to make p2sh addr for %s: %v",
+					msg, err)
+				break
+			}
+
+			scriptPkScript, err := txscript.PayToAddrScript(
+				scriptAddr)
+			if err != nil {
+				t.Errorf("failed to make script pkscript for "+
+					"%s: %v", msg, err)
+				break
+			}
+
+			sigScript, err := txscript.SignTxOutput(
+				&chaincfg.TestNet3Params, tx, i, scriptPkScript,
+				hashType, mkGetKey(map[string]addressToKey{
+					address1.EncodeAddress(): {key1, true},
+				}), mkGetScript(map[string][]byte{
+					scriptAddr.EncodeAddress(): pkScript,
+				}), []byte{})
+			if err != nil {
+				t.Errorf("failed to sign output %s: %v", msg,
+					err)
+				break
+			}
+
+			// Only 1 out of 2 signed, this *should* fail.
+			if checkScripts(msg, tx, i, sigScript,
+				scriptPkScript) == nil {
+				t.Errorf("part signed script valid for %s", msg)
+				break
+			}
+
+			// Sign with the other key and merge
+			sigScript, err = txscript.SignTxOutput(
+				&chaincfg.TestNet3Params, tx, i, scriptPkScript,
+				hashType, mkGetKey(map[string]addressToKey{
+					address2.EncodeAddress(): {key2, true},
+				}), mkGetScript(map[string][]byte{
+					scriptAddr.EncodeAddress(): pkScript,
+				}), sigScript)
+			if err != nil {
+				t.Errorf("failed to sign output %s: %v", msg, err)
+				break
+			}
+
+			err = checkScripts(msg, tx, i, sigScript,
+				scriptPkScript)
+			if err != nil {
+				t.Errorf("fully signed script invalid for "+
+					"%s: %v", msg, err)
+				break
+			}
+		}
+	}
+
+	// Two part multisig, sign with one key then both, check key dedup
+	// correctly.
+	for _, hashType := range hashTypes {
+		for i := range tx.TxIn {
+			msg := fmt.Sprintf("%d:%d", hashType, i)
+
+			key1, err := btcec.NewPrivateKey(btcec.S256())
+			if err != nil {
+				t.Errorf("failed to make privKey for %s: %v",
+					msg, err)
+				break
+			}
+
+			pk1 := (*btcec.PublicKey)(&key1.PublicKey).
+				SerializeCompressed()
+			address1, err := btcutil.NewAddressPubKey(pk1,
+				&chaincfg.TestNet3Params)
+			if err != nil {
+				t.Errorf("failed to make address for %s: %v",
+					msg, err)
+				break
+			}
+
+			key2, err := btcec.NewPrivateKey(btcec.S256())
+			if err != nil {
+				t.Errorf("failed to make privKey 2 for %s: %v",
+					msg, err)
+				break
+			}
+
+			pk2 := (*btcec.PublicKey)(&key2.PublicKey).
+				SerializeCompressed()
+			address2, err := btcutil.NewAddressPubKey(pk2,
+				&chaincfg.TestNet3Params)
+			if err != nil {
+				t.Errorf("failed to make address 2 for %s: %v",
+					msg, err)
+				break
+			}
+
+			pkScript, err := txscript.MultiSigScript(
+				[]*btcutil.AddressPubKey{address1, address2},
+				2)
+			if err != nil {
+				t.Errorf("failed to make pkscript "+
+					"for %s: %v", msg, err)
+			}
+
+			scriptAddr, err := btcutil.NewAddressScriptHash(
+				pkScript, &chaincfg.TestNet3Params)
+			if err != nil {
+				t.Errorf("failed to make p2sh addr for %s: %v",
+					msg, err)
+				break
+			}
+
+			scriptPkScript, err := txscript.PayToAddrScript(
+				scriptAddr)
+			if err != nil {
+				t.Errorf("failed to make script pkscript for "+
+					"%s: %v", msg, err)
+				break
+			}
+
+			sigScript, err := txscript.SignTxOutput(
+				&chaincfg.TestNet3Params, tx, i, scriptPkScript,
+				hashType, mkGetKey(map[string]addressToKey{
+					address1.EncodeAddress(): {key1, true},
+				}), mkGetScript(map[string][]byte{
+					scriptAddr.EncodeAddress(): pkScript,
+				}), []byte{})
+			if err != nil {
+				t.Errorf("failed to sign output %s: %v", msg,
+					err)
+				break
+			}
+
+			// Only 1 out of 2 signed, this *should* fail.
+			if checkScripts(msg, tx, i, sigScript,
+				scriptPkScript) == nil {
+				t.Errorf("part signed script valid for %s", msg)
+				break
+			}
+
+			// Sign with the other key and merge
+			sigScript, err = txscript.SignTxOutput(
+				&chaincfg.TestNet3Params, tx, i, scriptPkScript,
+				hashType, mkGetKey(map[string]addressToKey{
+					address1.EncodeAddress(): {key1, true},
+					address2.EncodeAddress(): {key2, true},
+				}), mkGetScript(map[string][]byte{
+					scriptAddr.EncodeAddress(): pkScript,
+				}), sigScript)
+			if err != nil {
+				t.Errorf("failed to sign output %s: %v", msg, err)
+				break
+			}
+
+			// Now we should pass.
+			err = checkScripts(msg, tx, i, sigScript,
+				scriptPkScript)
+			if err != nil {
+				t.Errorf("fully signed script invalid for "+
+					"%s: %v", msg, err)
+				break
+			}
+		}
+	}
+}
+
+type tstInput struct {
+	txout              *wire.TxOut
+	sigscriptGenerates bool
+	inputValidates     bool
+	indexOutOfRange    bool
+}
+
+type tstSigScript struct {
+	name               string
+	inputs             []tstInput
+	hashType           txscript.SigHashType
+	compress           bool
+	scriptAtWrongIndex bool
+}
+
+var coinbaseOutPoint = &wire.OutPoint{
+	Index: (1 << 32) - 1,
+}
+
+// Pregenerated private key, with associated public key and pkScripts
+// for the uncompressed and compressed hash160.
+var (
+	privKeyD = []byte{0x6b, 0x0f, 0xd8, 0xda, 0x54, 0x22, 0xd0, 0xb7,
+		0xb4, 0xfc, 0x4e, 0x55, 0xd4, 0x88, 0x42, 0xb3, 0xa1, 0x65,
+		0xac, 0x70, 0x7f, 0x3d, 0xa4, 0x39, 0x5e, 0xcb, 0x3b, 0xb0,
+		0xd6, 0x0e, 0x06, 0x92}
+	pubkeyX = []byte{0xb2, 0x52, 0xf0, 0x49, 0x85, 0x78, 0x03, 0x03, 0xc8,
+		0x7d, 0xce, 0x51, 0x7f, 0xa8, 0x69, 0x0b, 0x91, 0x95, 0xf4,
+		0xf3, 0x5c, 0x26, 0x73, 0x05, 0x05, 0xa2, 0xee, 0xbc, 0x09,
+		0x38, 0x34, 0x3a}
+	pubkeyY = []byte{0xb7, 0xc6, 0x7d, 0xb2, 0xe1, 0xff, 0xc8, 0x43, 0x1f,
+		0x63, 0x32, 0x62, 0xaa, 0x60, 0xc6, 0x83, 0x30, 0xbd, 0x24,
+		0x7e, 0xef, 0xdb, 0x6f, 0x2e, 0x8d, 0x56, 0xf0, 0x3c, 0x9f,
+		0x6d, 0xb6, 0xf8}
+	uncompressedPkScript = []byte{0x76, 0xa9, 0x14, 0xd1, 0x7c, 0xb5,
+		0xeb, 0xa4, 0x02, 0xcb, 0x68, 0xe0, 0x69, 0x56, 0xbf, 0x32,
+		0x53, 0x90, 0x0e, 0x0a, 0x86, 0xc9, 0xfa, 0x88, 0xac}
+	compressedPkScript = []byte{0x76, 0xa9, 0x14, 0x27, 0x4d, 0x9f, 0x7f,
+		0x61, 0x7e, 0x7c, 0x7a, 0x1c, 0x1f, 0xb2, 0x75, 0x79, 0x10,
+		0x43, 0x65, 0x68, 0x27, 0x9d, 0x86, 0x88, 0xac}
+	shortPkScript = []byte{0x76, 0xa9, 0x14, 0xd1, 0x7c, 0xb5,
+		0xeb, 0xa4, 0x02, 0xcb, 0x68, 0xe0, 0x69, 0x56, 0xbf, 0x32,
+		0x53, 0x90, 0x0e, 0x0a, 0x88, 0xac}
+	uncompressedAddrStr = "1L6fd93zGmtzkK6CsZFVVoCwzZV3MUtJ4F"
+	compressedAddrStr   = "14apLppt9zTq6cNw8SDfiJhk9PhkZrQtYZ"
+)
+
+// Pretend output amounts.
+const coinbaseVal = 2500000000
+const fee = 5000000
+
+var sigScriptTests = []tstSigScript{
+	{
+		name: "one input uncompressed",
+		inputs: []tstInput{
+			{
+				txout:              wire.NewTxOut(coinbaseVal, uncompressedPkScript),
+				sigscriptGenerates: true,
+				inputValidates:     true,
+				indexOutOfRange:    false,
+			},
+		},
+		hashType:           txscript.SigHashAll,
+		compress:           false,
+		scriptAtWrongIndex: false,
+	},
+	{
+		name: "two inputs uncompressed",
+		inputs: []tstInput{
+			{
+				txout:              wire.NewTxOut(coinbaseVal, uncompressedPkScript),
+				sigscriptGenerates: true,
+				inputValidates:     true,
+				indexOutOfRange:    false,
+			},
+			{
+				txout:              wire.NewTxOut(coinbaseVal+fee, uncompressedPkScript),
+				sigscriptGenerates: true,
+				inputValidates:     true,
+				indexOutOfRange:    false,
+			},
+		},
+		hashType:           txscript.SigHashAll,
+		compress:           false,
+		scriptAtWrongIndex: false,
+	},
+	{
+		name: "one input compressed",
+		inputs: []tstInput{
+			{
+				txout:              wire.NewTxOut(coinbaseVal, compressedPkScript),
+				sigscriptGenerates: true,
+				inputValidates:     true,
+				indexOutOfRange:    false,
+			},
+		},
+		hashType:           txscript.SigHashAll,
+		compress:           true,
+		scriptAtWrongIndex: false,
+	},
+	{
+		name: "two inputs compressed",
+		inputs: []tstInput{
+			{
+				txout:              wire.NewTxOut(coinbaseVal, compressedPkScript),
+				sigscriptGenerates: true,
+				inputValidates:     true,
+				indexOutOfRange:    false,
+			},
+			{
+				txout:              wire.NewTxOut(coinbaseVal+fee, compressedPkScript),
+				sigscriptGenerates: true,
+				inputValidates:     true,
+				indexOutOfRange:    false,
+			},
+		},
+		hashType:           txscript.SigHashAll,
+		compress:           true,
+		scriptAtWrongIndex: false,
+	},
+	{
+		name: "hashType SigHashNone",
+		inputs: []tstInput{
+			{
+				txout:              wire.NewTxOut(coinbaseVal, uncompressedPkScript),
+				sigscriptGenerates: true,
+				inputValidates:     true,
+				indexOutOfRange:    false,
+			},
+		},
+		hashType:           txscript.SigHashNone,
+		compress:           false,
+		scriptAtWrongIndex: false,
+	},
+	{
+		name: "hashType SigHashSingle",
+		inputs: []tstInput{
+			{
+				txout:              wire.NewTxOut(coinbaseVal, uncompressedPkScript),
+				sigscriptGenerates: true,
+				inputValidates:     true,
+				indexOutOfRange:    false,
+			},
+		},
+		hashType:           txscript.SigHashSingle,
+		compress:           false,
+		scriptAtWrongIndex: false,
+	},
+	{
+		name: "hashType SigHashAnyoneCanPay",
+		inputs: []tstInput{
+			{
+				txout:              wire.NewTxOut(coinbaseVal, uncompressedPkScript),
+				sigscriptGenerates: true,
+				inputValidates:     true,
+				indexOutOfRange:    false,
+			},
+		},
+		hashType:           txscript.SigHashAnyOneCanPay,
+		compress:           false,
+		scriptAtWrongIndex: false,
+	},
+	{
+		name: "hashType non-standard",
+		inputs: []tstInput{
+			{
+				txout:              wire.NewTxOut(coinbaseVal, uncompressedPkScript),
+				sigscriptGenerates: true,
+				inputValidates:     true,
+				indexOutOfRange:    false,
+			},
+		},
+		hashType:           0x04,
+		compress:           false,
+		scriptAtWrongIndex: false,
+	},
+	{
+		name: "invalid compression",
+		inputs: []tstInput{
+			{
+				txout:              wire.NewTxOut(coinbaseVal, uncompressedPkScript),
+				sigscriptGenerates: true,
+				inputValidates:     false,
+				indexOutOfRange:    false,
+			},
+		},
+		hashType:           txscript.SigHashAll,
+		compress:           true,
+		scriptAtWrongIndex: false,
+	},
+	{
+		name: "short PkScript",
+		inputs: []tstInput{
+			{
+				txout:              wire.NewTxOut(coinbaseVal, shortPkScript),
+				sigscriptGenerates: false,
+				indexOutOfRange:    false,
+			},
+		},
+		hashType:           txscript.SigHashAll,
+		compress:           false,
+		scriptAtWrongIndex: false,
+	},
+	{
+		name: "valid script at wrong index",
+		inputs: []tstInput{
+			{
+				txout:              wire.NewTxOut(coinbaseVal, uncompressedPkScript),
+				sigscriptGenerates: true,
+				inputValidates:     true,
+				indexOutOfRange:    false,
+			},
+			{
+				txout:              wire.NewTxOut(coinbaseVal+fee, uncompressedPkScript),
+				sigscriptGenerates: true,
+				inputValidates:     true,
+				indexOutOfRange:    false,
+			},
+		},
+		hashType:           txscript.SigHashAll,
+		compress:           false,
+		scriptAtWrongIndex: true,
+	},
+	{
+		name: "index out of range",
+		inputs: []tstInput{
+			{
+				txout:              wire.NewTxOut(coinbaseVal, uncompressedPkScript),
+				sigscriptGenerates: true,
+				inputValidates:     true,
+				indexOutOfRange:    false,
+			},
+			{
+				txout:              wire.NewTxOut(coinbaseVal+fee, uncompressedPkScript),
+				sigscriptGenerates: true,
+				inputValidates:     true,
+				indexOutOfRange:    false,
+			},
+		},
+		hashType:           txscript.SigHashAll,
+		compress:           false,
+		scriptAtWrongIndex: true,
+	},
+}
+
+// Test the sigscript generation for valid and invalid inputs, all
+// hashTypes, and with and without compression.  This test creates
+// sigscripts to spend fake coinbase inputs, as sigscripts cannot be
+// created for the MsgTxs in txTests, since they come from the blockchain
+// and we don't have the private keys.
+func TestSignatureScript(t *testing.T) {
+	t.Parallel()
+
+	privKey, _ := btcec.PrivKeyFromBytes(btcec.S256(), privKeyD)
+
+nexttest:
+	for i := range sigScriptTests {
+		tx := wire.NewMsgTx()
+
+		output := wire.NewTxOut(500, []byte{txscript.OP_RETURN})
+		tx.AddTxOut(output)
+
+		for _ = range sigScriptTests[i].inputs {
+			txin := wire.NewTxIn(coinbaseOutPoint, nil)
+			tx.AddTxIn(txin)
+		}
+
+		var script []byte
+		var err error
+		for j := range tx.TxIn {
+			var idx int
+			if sigScriptTests[i].inputs[j].indexOutOfRange {
+				t.Errorf("at test %v", sigScriptTests[i].name)
+				idx = len(sigScriptTests[i].inputs)
+			} else {
+				idx = j
+			}
+			script, err = txscript.SignatureScript(tx, idx,
+				sigScriptTests[i].inputs[j].txout.PkScript,
+				sigScriptTests[i].hashType, privKey,
+				sigScriptTests[i].compress)
+
+			if (err == nil) != sigScriptTests[i].inputs[j].sigscriptGenerates {
+				if err == nil {
+					t.Errorf("passed test '%v' incorrectly",
+						sigScriptTests[i].name)
+				} else {
+					t.Errorf("failed test '%v': %v",
+						sigScriptTests[i].name, err)
+				}
+				continue nexttest
+			}
+			if !sigScriptTests[i].inputs[j].sigscriptGenerates {
+				// done with this test
+				continue nexttest
+			}
+
+			tx.TxIn[j].SignatureScript = script
+		}
+
+		// If testing using a correct sigscript but for an incorrect
+		// index, use last input script for first input.  Requires > 0
+		// inputs for test.
+		if sigScriptTests[i].scriptAtWrongIndex {
+			tx.TxIn[0].SignatureScript = script
+			sigScriptTests[i].inputs[0].inputValidates = false
+		}
+
+		// Validate tx input scripts
+		scriptFlags := txscript.ScriptBip16 | txscript.ScriptVerifyDERSignatures
+		for j := range tx.TxIn {
+			vm, err := txscript.NewEngine(sigScriptTests[i].
+				inputs[j].txout.PkScript, tx, j, scriptFlags)
+			if err != nil {
+				t.Errorf("cannot create script vm for test %v: %v",
+					sigScriptTests[i].name, err)
+				continue nexttest
+			}
+			err = vm.Execute()
+			if (err == nil) != sigScriptTests[i].inputs[j].inputValidates {
+				if err == nil {
+					t.Errorf("passed test '%v' validation incorrectly: %v",
+						sigScriptTests[i].name, err)
+				} else {
+					t.Errorf("failed test '%v' validation: %v",
+						sigScriptTests[i].name, err)
+				}
+				continue nexttest
+			}
+		}
+	}
+}