From 0565215e35ebbaf136a34941fb263fe2ee5093f9 Mon Sep 17 00:00:00 2001
From: Guilherme Salgado <gsalgado@gmail.com>
Date: Tue, 7 Apr 2015 16:40:13 +0100
Subject: [PATCH] Migrate votingpool tests to use wtxmgr

---
 votingpool/example_test.go            |  22 ++-
 votingpool/factory_test.go            | 136 +++++++++++-------
 votingpool/input_selection.go         |  99 ++++++-------
 votingpool/input_selection_wb_test.go | 137 +++++++-----------
 votingpool/withdrawal.go              |  56 +++++---
 votingpool/withdrawal_test.go         |   2 +-
 votingpool/withdrawal_wb_test.go      | 194 ++++++++++++--------------
 7 files changed, 319 insertions(+), 327 deletions(-)

diff --git a/votingpool/example_test.go b/votingpool/example_test.go
index 79010638fe..206a9042ca 100644
--- a/votingpool/example_test.go
+++ b/votingpool/example_test.go
@@ -26,11 +26,11 @@ import (
 	"github.com/btcsuite/btcd/chaincfg"
 	"github.com/btcsuite/btcd/txscript"
 	"github.com/btcsuite/btcutil"
-	"github.com/btcsuite/btcwallet/legacy/txstore"
 	"github.com/btcsuite/btcwallet/votingpool"
 	"github.com/btcsuite/btcwallet/waddrmgr"
 	"github.com/btcsuite/btcwallet/walletdb"
 	_ "github.com/btcsuite/btcwallet/walletdb/bdb"
+	"github.com/btcsuite/btcwallet/wtxmgr"
 )
 
 var (
@@ -166,8 +166,7 @@ func Example_empowerSeries() {
 	//
 }
 
-// This example demonstrates how to empower a series by loading the private
-// key for one of the series' public keys.
+// This example demonstrates how to use the Pool.StartWithdrawal method.
 func Example_startWithdrawal() {
 	// Create the address manager and votingpool DB namespace. See the example
 	// for the Create() function for more info on how this is done.
@@ -319,11 +318,22 @@ func exampleCreatePoolAndSeries(mgr *waddrmgr.Manager, vpNamespace walletdb.Name
 	return pool, seriesID, nil
 }
 
-func exampleCreateTxStore() (*txstore.Store, func(), error) {
-	dir, err := ioutil.TempDir("", "tx.bin")
+func exampleCreateTxStore() (*wtxmgr.Store, func(), error) {
+	dir, err := ioutil.TempDir("", "pool_test_txstore")
+	if err != nil {
+		return nil, nil, err
+	}
+	db, err := walletdb.Create("bdb", filepath.Join(dir, "txstore.db"))
+	if err != nil {
+		return nil, nil, err
+	}
+	wtxmgrNamespace, err := db.Namespace([]byte("testtxstore"))
+	if err != nil {
+		return nil, nil, err
+	}
+	s, err := wtxmgr.Open(wtxmgrNamespace, &chaincfg.MainNetParams)
 	if err != nil {
 		return nil, nil, err
 	}
-	s := txstore.New(dir)
 	return s, func() { os.RemoveAll(dir) }, nil
 }
diff --git a/votingpool/factory_test.go b/votingpool/factory_test.go
index 917fded9cf..5a58c89046 100644
--- a/votingpool/factory_test.go
+++ b/votingpool/factory_test.go
@@ -25,15 +25,16 @@ import (
 	"path/filepath"
 	"sync/atomic"
 	"testing"
+	"time"
 
 	"github.com/btcsuite/btcd/chaincfg"
 	"github.com/btcsuite/btcd/txscript"
 	"github.com/btcsuite/btcd/wire"
 	"github.com/btcsuite/btcutil"
 	"github.com/btcsuite/btcutil/hdkeychain"
-	"github.com/btcsuite/btcwallet/legacy/txstore"
 	"github.com/btcsuite/btcwallet/waddrmgr"
 	"github.com/btcsuite/btcwallet/walletdb"
+	"github.com/btcsuite/btcwallet/wtxmgr"
 )
 
 var (
@@ -51,11 +52,10 @@ func getUniqueID() uint32 {
 }
 
 // createWithdrawalTx creates a withdrawalTx with the given input and output amounts.
-func createWithdrawalTx(t *testing.T, pool *Pool, store *txstore.Store, inputAmounts []int64,
-	outputAmounts []int64) *withdrawalTx {
+func createWithdrawalTx(t *testing.T, pool *Pool, inputAmounts []int64, outputAmounts []int64) *withdrawalTx {
 	net := pool.Manager().ChainParams()
 	tx := newWithdrawalTx()
-	_, credits := TstCreateCredits(t, pool, inputAmounts, store)
+	_, credits := TstCreateCreditsOnNewSeries(t, pool, inputAmounts)
 	for _, c := range credits {
 		tx.addInput(c)
 	}
@@ -136,12 +136,23 @@ func TstCreatePkScript(t *testing.T, p *Pool, seriesID uint32, branch Branch, id
 	return pkScript
 }
 
-func TstCreateTxStore(t *testing.T) (store *txstore.Store, tearDown func()) {
-	dir, err := ioutil.TempDir("", "tx.bin")
+func TstCreateTxStore(t *testing.T) (store *wtxmgr.Store, tearDown func()) {
+	dir, err := ioutil.TempDir("", "pool_test_txstore")
 	if err != nil {
-		t.Fatalf("Failed to create db file: %v", err)
+		t.Fatalf("Failed to create txstore dir: %v", err)
+	}
+	db, err := walletdb.Create("bdb", filepath.Join(dir, "txstore.db"))
+	if err != nil {
+		t.Fatalf("Failed to create walletdb: %v", err)
+	}
+	wtxmgrNamespace, err := db.Namespace([]byte("testtxstore"))
+	if err != nil {
+		t.Fatalf("Failed to create walletdb namespace: %v", err)
+	}
+	s, err := wtxmgr.Open(wtxmgrNamespace, &chaincfg.MainNetParams)
+	if err != nil {
+		t.Fatalf("Failed to create txstore: %v", err)
 	}
-	s := txstore.New(dir)
 	return s, func() { os.RemoveAll(dir) }
 }
 
@@ -201,15 +212,12 @@ func TstCreateSeriesDef(t *testing.T, pool *Pool, reqSigs uint32, keys []*hdkeyc
 		pubkey, _ := key.Neuter()
 		pubKeys[i] = pubkey.String()
 	}
-	seriesID := uint32(len(pool.seriesLookup))
-	if seriesID == 0 {
-		seriesID++
-	}
+	seriesID := uint32(len(pool.seriesLookup)) + 1
 	return TstSeriesDef{
 		ReqSigs: reqSigs, SeriesID: seriesID, PubKeys: pubKeys, PrivKeys: privKeys}
 }
 
-func TstCreatePoolAndTxStore(t *testing.T) (tearDown func(), pool *Pool, store *txstore.Store) {
+func TstCreatePoolAndTxStore(t *testing.T) (tearDown func(), pool *Pool, store *wtxmgr.Store) {
 	mgrTearDown, _, pool := TstCreatePool(t)
 	store, storeTearDown := TstCreateTxStore(t)
 	tearDown = func() {
@@ -219,12 +227,11 @@ func TstCreatePoolAndTxStore(t *testing.T) (tearDown func(), pool *Pool, store *
 	return tearDown, pool, store
 }
 
-// TstCreateCredits creates a new Series (with a unique ID) and a slice of
-// credits locked to the series' address with branch==1 and index==0. The new
-// Series will use a 2-of-3 configuration and will be empowered with all of its
-// private keys.
-func TstCreateCredits(t *testing.T, pool *Pool, amounts []int64, store *txstore.Store) (
-	uint32, []Credit) {
+// TstCreateCreditsOnNewSeries creates a new Series (with a unique ID) and a
+// slice of credits locked to the series' address with branch==1 and index==0.
+// The new Series will use a 2-of-3 configuration and will be empowered with
+// all of its private keys.
+func TstCreateCreditsOnNewSeries(t *testing.T, pool *Pool, amounts []int64) (uint32, []credit) {
 	masters := []*hdkeychain.ExtendedKey{
 		TstCreateMasterKey(t, bytes.Repeat(uint32ToBytes(getUniqueID()), 4)),
 		TstCreateMasterKey(t, bytes.Repeat(uint32ToBytes(getUniqueID()), 4)),
@@ -232,56 +239,87 @@ func TstCreateCredits(t *testing.T, pool *Pool, amounts []int64, store *txstore.
 	}
 	def := TstCreateSeriesDef(t, pool, 2, masters)
 	TstCreateSeries(t, pool, []TstSeriesDef{def})
-	return def.SeriesID, TstCreateCreditsOnSeries(t, pool, def.SeriesID, amounts, store)
+	return def.SeriesID, TstCreateSeriesCredits(t, pool, def.SeriesID, amounts)
 }
 
-// TstCreateCreditsOnSeries creates a slice of credits locked to the given
-// series' address with branch==1 and index==0.
-func TstCreateCreditsOnSeries(t *testing.T, pool *Pool, seriesID uint32, amounts []int64,
-	store *txstore.Store) []Credit {
+// TstCreateSeriesCredits creates a new credit for every item in the amounts
+// slice, locked to the given series' address with branch==1 and index==0.
+func TstCreateSeriesCredits(t *testing.T, pool *Pool, seriesID uint32, amounts []int64) []credit {
+	addr := TstNewWithdrawalAddress(t, pool, seriesID, Branch(1), Index(0))
+	pkScript, err := txscript.PayToAddrScript(addr.addr)
+	if err != nil {
+		t.Fatal(err)
+	}
+	msgTx := createMsgTx(pkScript, amounts)
+	txSha, err := msgTx.TxSha()
+	if err != nil {
+		t.Fatal(err)
+	}
+	credits := make([]credit, len(amounts))
+	for i := range msgTx.TxOut {
+		c := wtxmgr.Credit{
+			OutPoint: wire.OutPoint{
+				Hash:  txSha,
+				Index: uint32(i),
+			},
+			BlockMeta: wtxmgr.BlockMeta{
+				Block: wtxmgr.Block{Height: TstInputsBlock},
+			},
+			Amount:   btcutil.Amount(msgTx.TxOut[i].Value),
+			PkScript: msgTx.TxOut[i].PkScript,
+		}
+		credits[i] = newCredit(c, *addr)
+	}
+	return credits
+}
+
+// TstCreateSeriesCreditsOnStore inserts a new credit in the given store for
+// every item in the amounts slice. These credits are locked to the votingpool
+// address composed of the given seriesID, branch==1 and index==0.
+func TstCreateSeriesCreditsOnStore(t *testing.T, pool *Pool, seriesID uint32, amounts []int64,
+	store *wtxmgr.Store) []credit {
 	branch := Branch(1)
 	idx := Index(0)
 	pkScript := TstCreatePkScript(t, pool, seriesID, branch, idx)
-	eligible := make([]Credit, len(amounts))
-	for i, credit := range TstCreateInputs(t, store, pkScript, amounts) {
+	eligible := make([]credit, len(amounts))
+	for i, credit := range TstCreateCreditsOnStore(t, store, pkScript, amounts) {
 		eligible[i] = newCredit(credit, *TstNewWithdrawalAddress(t, pool, seriesID, branch, idx))
 	}
 	return eligible
 }
 
-// TstCreateInputs is a convenience function.  See TstCreateInputsOnBlock
-// for a more flexible version.
-func TstCreateInputs(t *testing.T, store *txstore.Store, pkScript []byte, amounts []int64) []txstore.Credit {
-	return TstCreateInputsOnBlock(t, store, 1, pkScript, amounts)
-}
-
-// TstCreateInputsOnBlock creates a number of inputs by creating a transaction
-// with a number of outputs corresponding to the elements of the amounts slice.
-//
-// The transaction is added to a block and the index and blockheight must be
-// specified.
-func TstCreateInputsOnBlock(t *testing.T, s *txstore.Store,
-	blockTxIndex int, pkScript []byte, amounts []int64) []txstore.Credit {
+// TstCreateCreditsOnStore inserts a new credit in the given store for
+// every item in the amounts slice.
+func TstCreateCreditsOnStore(t *testing.T, s *wtxmgr.Store, pkScript []byte,
+	amounts []int64) []wtxmgr.Credit {
 	msgTx := createMsgTx(pkScript, amounts)
-	block := &txstore.Block{
-		Height: TstInputsBlock,
+	meta := &wtxmgr.BlockMeta{
+		Block: wtxmgr.Block{Height: TstInputsBlock},
 	}
 
-	tx := btcutil.NewTx(msgTx)
-	tx.SetIndex(blockTxIndex)
-
-	r, err := s.InsertTx(tx, block)
+	rec, err := wtxmgr.NewTxRecordFromMsgTx(msgTx, time.Now())
 	if err != nil {
+		t.Fatal(err)
+	}
+
+	if err := s.InsertTx(rec, meta); err != nil {
 		t.Fatal("Failed to create inputs: ", err)
 	}
 
-	credits := make([]txstore.Credit, len(msgTx.TxOut))
+	credits := make([]wtxmgr.Credit, len(msgTx.TxOut))
 	for i := range msgTx.TxOut {
-		credit, err := r.AddCredit(uint32(i), false)
-		if err != nil {
+		if err := s.AddCredit(rec, meta, uint32(i), false); err != nil {
 			t.Fatal("Failed to create inputs: ", err)
 		}
-		credits[i] = credit
+		credits[i] = wtxmgr.Credit{
+			OutPoint: wire.OutPoint{
+				Hash:  rec.Hash,
+				Index: uint32(i),
+			},
+			BlockMeta: *meta,
+			Amount:    btcutil.Amount(msgTx.TxOut[i].Value),
+			PkScript:  msgTx.TxOut[i].PkScript,
+		}
 	}
 	return credits
 }
diff --git a/votingpool/input_selection.go b/votingpool/input_selection.go
index cb345dfb15..33206ef7f9 100644
--- a/votingpool/input_selection.go
+++ b/votingpool/input_selection.go
@@ -22,61 +22,31 @@ import (
 	"sort"
 
 	"github.com/btcsuite/btcd/chaincfg"
-	"github.com/btcsuite/btcd/wire"
+	"github.com/btcsuite/btcd/txscript"
 	"github.com/btcsuite/btcutil"
-	"github.com/btcsuite/btcwallet/legacy/txstore"
+	"github.com/btcsuite/btcwallet/wtxmgr"
 )
 
 const eligibleInputMinConfirmations = 100
 
-// Credit is an abstraction over txstore.Credit used in the construction of
+// credit is an abstraction over wtxmgr.Credit used in the construction of
 // voting pool withdrawal transactions.
-type Credit interface {
-	TxSha() *wire.ShaHash
-	OutputIndex() uint32
-	Address() WithdrawalAddress
-	Amount() btcutil.Amount
-	OutPoint() *wire.OutPoint
-	TxOut() *wire.TxOut
-}
-
-// credit implements the Credit interface.
 type credit struct {
-	txstore.Credit
+	wtxmgr.Credit
 	addr WithdrawalAddress
 }
 
-// newCredit initialises a new credit.
-func newCredit(c txstore.Credit, addr WithdrawalAddress) *credit {
-	return &credit{Credit: c, addr: addr}
+func newCredit(c wtxmgr.Credit, addr WithdrawalAddress) credit {
+	return credit{Credit: c, addr: addr}
 }
 
 func (c *credit) String() string {
-	return fmt.Sprintf("credit of %v to %v", c.Amount(), c.Address())
-}
-
-// TxSha returns the sha hash of the underlying transaction.
-func (c *credit) TxSha() *wire.ShaHash {
-	return c.Credit.TxRecord.Tx().Sha()
-}
-
-// OutputIndex returns the outputindex of the ouput in the underlying
-// transaction.
-func (c *credit) OutputIndex() uint32 {
-	return c.Credit.OutputIndex
+	return fmt.Sprintf("credit of %v locked to %v", c.Amount, c.addr)
 }
 
-// Address returns the voting pool address.
-func (c *credit) Address() WithdrawalAddress {
-	return c.addr
-}
-
-// Compile time check that credit implements Credit interface.
-var _ Credit = (*credit)(nil)
-
 // byAddress defines the methods needed to satisify sort.Interface to sort a
-// slice of Credits by their address.
-type byAddress []Credit
+// slice of credits by their address.
+type byAddress []credit
 
 func (c byAddress) Len() int      { return len(c) }
 func (c byAddress) Swap(i, j int) { c[i], c[j] = c[j], c[i] }
@@ -86,8 +56,8 @@ func (c byAddress) Swap(i, j int) { c[i], c[j] = c[j], c[i] }
 // the lexicographic ordering defined on the tuple (SeriesID, Index,
 // Branch, TxSha, OutputIndex).
 func (c byAddress) Less(i, j int) bool {
-	iAddr := c[i].Address()
-	jAddr := c[j].Address()
+	iAddr := c[i].addr
+	jAddr := c[j].addr
 	if iAddr.seriesID < jAddr.seriesID {
 		return true
 	}
@@ -112,7 +82,7 @@ func (c byAddress) Less(i, j int) bool {
 	}
 
 	// The seriesID, index, and branch are equal, so compare hash.
-	txidComparison := bytes.Compare(c[i].TxSha().Bytes(), c[j].TxSha().Bytes())
+	txidComparison := bytes.Compare(c[i].OutPoint.Hash.Bytes(), c[j].OutPoint.Hash.Bytes())
 	if txidComparison < 0 {
 		return true
 	}
@@ -122,14 +92,14 @@ func (c byAddress) Less(i, j int) bool {
 
 	// The seriesID, index, branch, and hash are equal, so compare output
 	// index.
-	return c[i].OutputIndex() < c[j].OutputIndex()
+	return c[i].OutPoint.Index < c[j].OutPoint.Index
 }
 
 // getEligibleInputs returns eligible inputs with addresses between startAddress
 // and the last used address of lastSeriesID.
-func (p *Pool) getEligibleInputs(store *txstore.Store, startAddress WithdrawalAddress,
+func (p *Pool) getEligibleInputs(store *wtxmgr.Store, startAddress WithdrawalAddress,
 	lastSeriesID uint32, dustThreshold btcutil.Amount, chainHeight int32,
-	minConf int) ([]Credit, error) {
+	minConf int) ([]credit, error) {
 
 	if p.Series(lastSeriesID) == nil {
 		str := fmt.Sprintf("lastSeriesID (%d) does not exist", lastSeriesID)
@@ -143,15 +113,16 @@ func (p *Pool) getEligibleInputs(store *txstore.Store, startAddress WithdrawalAd
 	if err != nil {
 		return nil, err
 	}
-	var inputs []Credit
+	var inputs []credit
 	address := startAddress
 	for {
 		log.Debugf("Looking for eligible inputs at address %v", address.addrIdentifier())
 		if candidates, ok := addrMap[address.addr.EncodeAddress()]; ok {
-			var eligibles []Credit
+			var eligibles []credit
 			for _, c := range candidates {
-				if p.isCreditEligible(c, minConf, chainHeight, dustThreshold) {
-					eligibles = append(eligibles, newCredit(c, address))
+				candidate := newCredit(c, address)
+				if p.isCreditEligible(candidate, minConf, chainHeight, dustThreshold) {
+					eligibles = append(eligibles, candidate)
 				}
 			}
 			// Make sure the eligibles are correctly sorted.
@@ -237,11 +208,11 @@ func (p *Pool) highestUsedSeriesIndex(seriesID uint32) (Index, error) {
 // groupCreditsByAddr converts a slice of credits to a map from the string
 // representation of an encoded address to the unspent outputs associated with
 // that address.
-func groupCreditsByAddr(credits []txstore.Credit, chainParams *chaincfg.Params) (
-	map[string][]txstore.Credit, error) {
-	addrMap := make(map[string][]txstore.Credit)
+func groupCreditsByAddr(credits []wtxmgr.Credit, chainParams *chaincfg.Params) (
+	map[string][]wtxmgr.Credit, error) {
+	addrMap := make(map[string][]wtxmgr.Credit)
 	for _, c := range credits {
-		_, addrs, _, err := c.Addresses(chainParams)
+		_, addrs, _, err := txscript.ExtractPkScriptAddrs(c.PkScript, chainParams)
 		if err != nil {
 			return nil, newError(ErrInputSelection, "failed to obtain input address", err)
 		}
@@ -255,7 +226,7 @@ func groupCreditsByAddr(credits []txstore.Credit, chainParams *chaincfg.Params)
 		if v, ok := addrMap[encAddr]; ok {
 			addrMap[encAddr] = append(v, c)
 		} else {
-			addrMap[encAddr] = []txstore.Credit{c}
+			addrMap[encAddr] = []wtxmgr.Credit{c}
 		}
 	}
 
@@ -265,12 +236,12 @@ func groupCreditsByAddr(credits []txstore.Credit, chainParams *chaincfg.Params)
 // isCreditEligible tests a given credit for eligibilty with respect
 // to number of confirmations, the dust threshold and that it is not
 // the charter output.
-func (p *Pool) isCreditEligible(c txstore.Credit, minConf int, chainHeight int32,
+func (p *Pool) isCreditEligible(c credit, minConf int, chainHeight int32,
 	dustThreshold btcutil.Amount) bool {
-	if c.Amount() < dustThreshold {
+	if c.Amount < dustThreshold {
 		return false
 	}
-	if !c.Confirmed(minConf, chainHeight) {
+	if confirms(c.BlockMeta.Block.Height, chainHeight) < int32(minConf) {
 		return false
 	}
 	if p.isCharterOutput(c) {
@@ -282,6 +253,18 @@ func (p *Pool) isCreditEligible(c txstore.Credit, minConf int, chainHeight int32
 
 // isCharterOutput - TODO: In order to determine this, we need the txid
 // and the output index of the current charter output, which we don't have yet.
-func (p *Pool) isCharterOutput(c txstore.Credit) bool {
+func (p *Pool) isCharterOutput(c credit) bool {
 	return false
 }
+
+// confirms returns the number of confirmations for a transaction in a block at
+// height txHeight (or -1 for an unconfirmed tx) given the chain height
+// curHeight.
+func confirms(txHeight, curHeight int32) int32 {
+	switch {
+	case txHeight == -1, txHeight > curHeight:
+		return 0
+	default:
+		return curHeight - txHeight + 1
+	}
+}
diff --git a/votingpool/input_selection_wb_test.go b/votingpool/input_selection_wb_test.go
index a6a0cf220d..7593924617 100644
--- a/votingpool/input_selection_wb_test.go
+++ b/votingpool/input_selection_wb_test.go
@@ -24,7 +24,7 @@ import (
 
 	"github.com/btcsuite/btcd/wire"
 	"github.com/btcsuite/btcutil"
-	"github.com/btcsuite/btcwallet/legacy/txstore"
+	"github.com/btcsuite/btcwallet/wtxmgr"
 )
 
 var (
@@ -48,17 +48,16 @@ func TestGetEligibleInputs(t *testing.T) {
 	// Create two eligible inputs locked to each of the PKScripts above.
 	expNoEligibleInputs := 2 * len(scripts)
 	eligibleAmounts := []int64{int64(dustThreshold + 1), int64(dustThreshold + 1)}
-	var inputs []txstore.Credit
+	var inputs []wtxmgr.Credit
 	for i := 0; i < len(scripts); i++ {
-		txIndex := int(i) + 1
-		created := TstCreateInputsOnBlock(t, store, txIndex, scripts[i], eligibleAmounts)
+		created := TstCreateCreditsOnStore(t, store, scripts[i], eligibleAmounts)
 		inputs = append(inputs, created...)
 	}
 
 	startAddr := TstNewWithdrawalAddress(t, pool, 1, 0, 0)
 	lastSeriesID := uint32(2)
 	currentBlock := int32(TstInputsBlock + eligibleInputMinConfirmations + 1)
-	var eligibles []Credit
+	var eligibles []credit
 	var err error
 	TstRunWithManagerUnlocked(t, pool.Manager(), func() {
 		eligibles, err = pool.getEligibleInputs(
@@ -213,23 +212,14 @@ func TestNextAddr(t *testing.T) {
 }
 
 func TestEligibleInputsAreEligible(t *testing.T) {
-	tearDown, pool, store := TstCreatePoolAndTxStore(t)
+	tearDown, pool, _ := TstCreatePoolAndTxStore(t)
 	defer tearDown()
-	seriesID := uint32(1)
-	branch := Branch(0)
-	index := Index(0)
-
-	// create the series
-	series := []TstSeriesDef{{ReqSigs: 3, PubKeys: TstPubKeys[1:6], SeriesID: seriesID}}
-	TstCreateSeries(t, pool, series)
 
-	// Create the input.
-	pkScript := TstCreatePkScript(t, pool, seriesID, branch, index)
 	var chainHeight int32 = 1000
-	c := TstCreateInputs(t, store, pkScript, []int64{int64(dustThreshold)})[0]
-
-	// Make sure credits is old enough to pass the minConf check.
-	c.BlockHeight = int32(eligibleInputMinConfirmations)
+	_, credits := TstCreateCreditsOnNewSeries(t, pool, []int64{int64(dustThreshold)})
+	c := credits[0]
+	// Make sure credit is old enough to pass the minConf check.
+	c.BlockMeta.Height = int32(eligibleInputMinConfirmations)
 
 	if !pool.isCreditEligible(c, eligibleInputMinConfirmations, chainHeight, dustThreshold) {
 		t.Errorf("Input is not eligible and it should be.")
@@ -237,36 +227,28 @@ func TestEligibleInputsAreEligible(t *testing.T) {
 }
 
 func TestNonEligibleInputsAreNotEligible(t *testing.T) {
-	tearDown, pool, store1 := TstCreatePoolAndTxStore(t)
-	store2, storeTearDown2 := TstCreateTxStore(t)
+	tearDown, pool, _ := TstCreatePoolAndTxStore(t)
 	defer tearDown()
-	defer storeTearDown2()
-	seriesID := uint32(1)
-	branch := Branch(0)
-	index := Index(0)
-
-	// create the series
-	series := []TstSeriesDef{{ReqSigs: 3, PubKeys: TstPubKeys[1:6], SeriesID: seriesID}}
-	TstCreateSeries(t, pool, series)
 
-	pkScript := TstCreatePkScript(t, pool, seriesID, branch, index)
 	var chainHeight int32 = 1000
+	_, credits := TstCreateCreditsOnNewSeries(t, pool, []int64{int64(dustThreshold - 1)})
+	c := credits[0]
+	// Make sure credit is old enough to pass the minConf check.
+	c.BlockMeta.Height = int32(eligibleInputMinConfirmations)
 
 	// Check that credit below dustThreshold is rejected.
-	c1 := TstCreateInputs(t, store1, pkScript, []int64{int64(dustThreshold - 1)})[0]
-	c1.BlockHeight = int32(100) // make sure it has enough confirmations.
-	if pool.isCreditEligible(c1, eligibleInputMinConfirmations, chainHeight, dustThreshold) {
+	if pool.isCreditEligible(c, eligibleInputMinConfirmations, chainHeight, dustThreshold) {
 		t.Errorf("Input is eligible and it should not be.")
 	}
 
 	// Check that a credit with not enough confirmations is rejected.
-	c2 := TstCreateInputs(t, store2, pkScript, []int64{int64(dustThreshold)})[0]
-	// the calculation of if it has been confirmed does this:
-	// chainheigt - bh + 1 >= target, which is quite weird, but the
-	// reason why I need to put 902 as *that* makes 1000 - 902 +1 = 99 >=
-	// 100 false
-	c2.BlockHeight = int32(902)
-	if pool.isCreditEligible(c2, eligibleInputMinConfirmations, chainHeight, dustThreshold) {
+	_, credits = TstCreateCreditsOnNewSeries(t, pool, []int64{int64(dustThreshold)})
+	c = credits[0]
+	// The calculation of if it has been confirmed does this: chainheigt - bh +
+	// 1 >= target, which is quite weird, but the reason why I need to put 902
+	// is *that* makes 1000 - 902 +1 = 99 >= 100 false
+	c.BlockMeta.Height = int32(902)
+	if pool.isCreditEligible(c, eligibleInputMinConfirmations, chainHeight, dustThreshold) {
 		t.Errorf("Input is eligible and it should not be.")
 	}
 }
@@ -284,21 +266,21 @@ func TestCreditSortingByAddress(t *testing.T) {
 	shaHash0 := bytes.Repeat([]byte{0}, 32)
 	shaHash1 := bytes.Repeat([]byte{1}, 32)
 	shaHash2 := bytes.Repeat([]byte{2}, 32)
-	c0 := TstNewFakeCredit(t, pool, 1, 0, 0, shaHash0, 0)
-	c1 := TstNewFakeCredit(t, pool, 1, 0, 0, shaHash0, 1)
-	c2 := TstNewFakeCredit(t, pool, 1, 0, 0, shaHash1, 0)
-	c3 := TstNewFakeCredit(t, pool, 1, 0, 0, shaHash2, 0)
-	c4 := TstNewFakeCredit(t, pool, 1, 0, 1, shaHash0, 0)
-	c5 := TstNewFakeCredit(t, pool, 1, 1, 0, shaHash0, 0)
-	c6 := TstNewFakeCredit(t, pool, 2, 0, 0, shaHash0, 0)
+	c0 := newDummyCredit(t, pool, 1, 0, 0, shaHash0, 0)
+	c1 := newDummyCredit(t, pool, 1, 0, 0, shaHash0, 1)
+	c2 := newDummyCredit(t, pool, 1, 0, 0, shaHash1, 0)
+	c3 := newDummyCredit(t, pool, 1, 0, 0, shaHash2, 0)
+	c4 := newDummyCredit(t, pool, 1, 0, 1, shaHash0, 0)
+	c5 := newDummyCredit(t, pool, 1, 1, 0, shaHash0, 0)
+	c6 := newDummyCredit(t, pool, 2, 0, 0, shaHash0, 0)
 
-	randomCredits := [][]Credit{
-		[]Credit{c6, c5, c4, c3, c2, c1, c0},
-		[]Credit{c2, c1, c0, c6, c5, c4, c3},
-		[]Credit{c6, c4, c5, c2, c3, c0, c1},
+	randomCredits := [][]credit{
+		[]credit{c6, c5, c4, c3, c2, c1, c0},
+		[]credit{c2, c1, c0, c6, c5, c4, c3},
+		[]credit{c6, c4, c5, c2, c3, c0, c1},
 	}
 
-	want := []Credit{c0, c1, c2, c3, c4, c5, c6}
+	want := []credit{c0, c1, c2, c3, c4, c5, c6}
 
 	for _, random := range randomCredits {
 		sort.Sort(byAddress(random))
@@ -318,28 +300,11 @@ func TestCreditSortingByAddress(t *testing.T) {
 	}
 }
 
-// TstFakeCredit is a structure implementing the Credit interface used to test
-// the byAddress sorting. It exists because to test the sorting properly we need
-// to be able to set the Credit's TxSha and OutputIndex.
-type TstFakeCredit struct {
-	addr        WithdrawalAddress
-	txSha       *wire.ShaHash
-	outputIndex uint32
-	amount      btcutil.Amount
-}
-
-func (c *TstFakeCredit) String() string             { return "" }
-func (c *TstFakeCredit) TxSha() *wire.ShaHash       { return c.txSha }
-func (c *TstFakeCredit) OutputIndex() uint32        { return c.outputIndex }
-func (c *TstFakeCredit) Address() WithdrawalAddress { return c.addr }
-func (c *TstFakeCredit) Amount() btcutil.Amount     { return c.amount }
-func (c *TstFakeCredit) TxOut() *wire.TxOut         { return nil }
-func (c *TstFakeCredit) OutPoint() *wire.OutPoint {
-	return &wire.OutPoint{Hash: *c.txSha, Index: c.outputIndex}
-}
-
-func TstNewFakeCredit(t *testing.T, pool *Pool, series uint32, index Index, branch Branch,
-	txSha []byte, outputIdx int) *TstFakeCredit {
+// newDummyCredit creates a new credit with the given hash and outpointIdx,
+// locked to the votingpool address identified by the given
+// series/index/branch.
+func newDummyCredit(t *testing.T, pool *Pool, series uint32, index Index, branch Branch,
+	txSha []byte, outpointIdx uint32) credit {
 	var hash wire.ShaHash
 	if err := hash.SetBytes(txSha); err != nil {
 		t.Fatal(err)
@@ -348,17 +313,15 @@ func TstNewFakeCredit(t *testing.T, pool *Pool, series uint32, index Index, bran
 	// the set of used addresses as that's a requirement of WithdrawalAddress.
 	TstEnsureUsedAddr(t, pool, series, branch, index)
 	addr := TstNewWithdrawalAddress(t, pool, series, branch, index)
-	return &TstFakeCredit{
-		addr:        *addr,
-		txSha:       &hash,
-		outputIndex: uint32(outputIdx),
+	c := wtxmgr.Credit{
+		OutPoint: wire.OutPoint{
+			Hash:  hash,
+			Index: outpointIdx,
+		},
 	}
+	return newCredit(c, *addr)
 }
 
-// Compile time check that TstFakeCredit implements the
-// Credit interface.
-var _ Credit = (*TstFakeCredit)(nil)
-
 func checkUniqueness(t *testing.T, credits byAddress) {
 	type uniq struct {
 		series      uint32
@@ -371,11 +334,11 @@ func checkUniqueness(t *testing.T, credits byAddress) {
 	uniqMap := make(map[uniq]bool)
 	for _, c := range credits {
 		u := uniq{
-			series:      c.Address().SeriesID(),
-			branch:      c.Address().Branch(),
-			index:       c.Address().Index(),
-			hash:        *c.TxSha(),
-			outputIndex: c.OutputIndex(),
+			series:      c.addr.SeriesID(),
+			branch:      c.addr.Branch(),
+			index:       c.addr.Index(),
+			hash:        c.OutPoint.Hash,
+			outputIndex: c.OutPoint.Index,
 		}
 		if _, exists := uniqMap[u]; exists {
 			t.Fatalf("Duplicate found: %v", u)
diff --git a/votingpool/withdrawal.go b/votingpool/withdrawal.go
index af3c846a10..43155744ab 100644
--- a/votingpool/withdrawal.go
+++ b/votingpool/withdrawal.go
@@ -22,12 +22,13 @@ import (
 	"math"
 	"sort"
 	"strconv"
+	"time"
 
 	"github.com/btcsuite/btcd/txscript"
 	"github.com/btcsuite/btcd/wire"
 	"github.com/btcsuite/btcutil"
-	"github.com/btcsuite/btcwallet/legacy/txstore"
 	"github.com/btcsuite/btcwallet/waddrmgr"
+	"github.com/btcsuite/btcwallet/wtxmgr"
 	"github.com/btcsuite/fastsha256"
 )
 
@@ -235,7 +236,7 @@ type withdrawal struct {
 	status          *WithdrawalStatus
 	transactions    []*withdrawalTx
 	pendingRequests []OutputRequest
-	eligibleInputs  []Credit
+	eligibleInputs  []credit
 	current         *withdrawalTx
 }
 
@@ -263,7 +264,7 @@ func (o *withdrawalTxOut) pkScript() []byte {
 
 // withdrawalTx represents a transaction constructed by the withdrawal process.
 type withdrawalTx struct {
-	inputs  []Credit
+	inputs  []credit
 	outputs []*withdrawalTxOut
 	fee     btcutil.Amount
 
@@ -290,7 +291,7 @@ func (tx *withdrawalTx) ntxid() Ntxid {
 // inputTotal returns the sum amount of all inputs in this tx.
 func (tx *withdrawalTx) inputTotal() (total btcutil.Amount) {
 	for _, input := range tx.inputs {
-		total += input.Amount()
+		total += input.Amount
 	}
 	return total
 }
@@ -321,7 +322,7 @@ func (tx *withdrawalTx) toMsgTx() *wire.MsgTx {
 	}
 
 	for _, i := range tx.inputs {
-		msgtx.AddTxIn(wire.NewTxIn(i.OutPoint(), []byte{}))
+		msgtx.AddTxIn(wire.NewTxIn(&i.OutPoint, []byte{}))
 	}
 	return msgtx
 }
@@ -341,16 +342,16 @@ func (tx *withdrawalTx) removeOutput() *withdrawalTxOut {
 }
 
 // addInput adds a new input to this transaction.
-func (tx *withdrawalTx) addInput(input Credit) {
-	log.Debugf("Added tx input with amount %v", input.Amount())
+func (tx *withdrawalTx) addInput(input credit) {
+	log.Debugf("Added tx input with amount %v", input.Amount)
 	tx.inputs = append(tx.inputs, input)
 }
 
 // removeInput removes the last added input and returns it.
-func (tx *withdrawalTx) removeInput() Credit {
+func (tx *withdrawalTx) removeInput() credit {
 	removed := tx.inputs[len(tx.inputs)-1]
 	tx.inputs = tx.inputs[:len(tx.inputs)-1]
-	log.Debugf("Removed tx input with amount %v", removed.Amount())
+	log.Debugf("Removed tx input with amount %v", removed.Amount)
 	return removed
 }
 
@@ -380,7 +381,7 @@ func (tx *withdrawalTx) addChange(pkScript []byte) bool {
 //
 // The tx needs to have two or more outputs. The case with only one output must
 // be handled separately (by the split output procedure).
-func (tx *withdrawalTx) rollBackLastOutput() ([]Credit, *withdrawalTxOut, error) {
+func (tx *withdrawalTx) rollBackLastOutput() ([]credit, *withdrawalTxOut, error) {
 	// Check precondition: At least two outputs are required in the transaction.
 	if len(tx.outputs) < 2 {
 		str := fmt.Sprintf("at least two outputs expected; got %d", len(tx.outputs))
@@ -389,7 +390,7 @@ func (tx *withdrawalTx) rollBackLastOutput() ([]Credit, *withdrawalTxOut, error)
 
 	removedOutput := tx.removeOutput()
 
-	var removedInputs []Credit
+	var removedInputs []credit
 	// Continue until sum(in) < sum(out) + fee
 	for tx.inputTotal() >= tx.outputTotal()+calculateTxFee(tx) {
 		removedInputs = append(removedInputs, tx.removeInput())
@@ -401,7 +402,7 @@ func (tx *withdrawalTx) rollBackLastOutput() ([]Credit, *withdrawalTxOut, error)
 	return removedInputs, removedOutput, nil
 }
 
-func newWithdrawal(roundID uint32, requests []OutputRequest, inputs []Credit,
+func newWithdrawal(roundID uint32, requests []OutputRequest, inputs []credit,
 	changeStart ChangeAddress) *withdrawal {
 	outputs := make(map[OutBailmentID]*WithdrawalOutput, len(requests))
 	for _, request := range requests {
@@ -429,7 +430,7 @@ func newWithdrawal(roundID uint32, requests []OutputRequest, inputs []Credit,
 // found at http://opentransactions.org/wiki/index.php/Startwithdrawal
 func (p *Pool) StartWithdrawal(roundID uint32, requests []OutputRequest,
 	startAddress WithdrawalAddress, lastSeriesID uint32, changeStart ChangeAddress,
-	txStore *txstore.Store, chainHeight int32, dustThreshold btcutil.Amount) (
+	txStore *wtxmgr.Store, chainHeight int32, dustThreshold btcutil.Amount) (
 	*WithdrawalStatus, error) {
 
 	eligible, err := p.getEligibleInputs(txStore, startAddress, lastSeriesID, dustThreshold,
@@ -465,7 +466,7 @@ func (w *withdrawal) pushRequest(request OutputRequest) {
 
 // popInput removes and returns the first input from the stack of eligible
 // inputs.
-func (w *withdrawal) popInput() Credit {
+func (w *withdrawal) popInput() credit {
 	input := w.eligibleInputs[0]
 	w.eligibleInputs = w.eligibleInputs[1:]
 	return input
@@ -475,8 +476,8 @@ func (w *withdrawal) popInput() Credit {
 // TODO: Reverse the stack semantics here as the current one generates a lot of
 // extra garbage since it always creates a new single-element slice and append
 // the rest of the items to it.
-func (w *withdrawal) pushInput(input Credit) {
-	w.eligibleInputs = append([]Credit{input}, w.eligibleInputs...)
+func (w *withdrawal) pushInput(input credit) {
+	w.eligibleInputs = append([]credit{input}, w.eligibleInputs...)
 }
 
 // If this returns it means we have added an output and the necessary inputs to fulfil that
@@ -599,7 +600,7 @@ func (w *withdrawal) finalizeCurrentTx() error {
 func (w *withdrawal) maybeDropRequests() {
 	inputAmount := btcutil.Amount(0)
 	for _, input := range w.eligibleInputs {
-		inputAmount += input.Amount()
+		inputAmount += input.Amount
 	}
 	outputAmount := btcutil.Amount(0)
 	for _, request := range w.pendingRequests {
@@ -717,7 +718,7 @@ func getRawSigs(transactions []*withdrawalTx) (map[Ntxid]TxSigs, error) {
 		msgtx := tx.toMsgTx()
 		ntxid := tx.ntxid()
 		for inputIdx, input := range tx.inputs {
-			creditAddr := input.Address()
+			creditAddr := input.addr
 			redeemScript := creditAddr.redeemScript()
 			series := creditAddr.series()
 			// The order of the raw signatures in the signature script must match the
@@ -769,10 +770,19 @@ func getRawSigs(transactions []*withdrawalTx) (map[Ntxid]TxSigs, error) {
 // manager) the redeem script for each of them and constructing the signature
 // script using that and the given raw signatures.
 // This function must be called with the manager unlocked.
-func SignTx(msgtx *wire.MsgTx, sigs TxSigs, mgr *waddrmgr.Manager, store *txstore.Store) error {
-	credits, err := store.FindPreviousCredits(btcutil.NewTx(msgtx))
-	for i, credit := range credits {
-		if err = signMultiSigUTXO(mgr, msgtx, i, credit.TxOut().PkScript, sigs[i]); err != nil {
+func SignTx(msgtx *wire.MsgTx, sigs TxSigs, mgr *waddrmgr.Manager, store *wtxmgr.Store) error {
+	// We use time.Now() here as we're not going to store the new TxRecord
+	// anywhere -- we just need it to pass to store.PreviousPkScripts().
+	rec, err := wtxmgr.NewTxRecordFromMsgTx(msgtx, time.Now())
+	if err != nil {
+		return newError(ErrTxSigning, "failed to construct TxRecord for signing", err)
+	}
+	pkScripts, err := store.PreviousPkScripts(rec, nil)
+	if err != nil {
+		return newError(ErrTxSigning, "failed to obtain pkScripts for signing", err)
+	}
+	for i, pkScript := range pkScripts {
+		if err = signMultiSigUTXO(mgr, msgtx, i, pkScript, sigs[i]); err != nil {
 			return err
 		}
 	}
@@ -896,7 +906,7 @@ var calculateTxSize = func(tx *withdrawalTx) int {
 		// Notice that we use 73 as the signature length as that's the maximum
 		// length they may have:
 		// https://en.bitcoin.it/wiki/Elliptic_Curve_Digital_Signature_Algorithm
-		addr := tx.inputs[i].Address()
+		addr := tx.inputs[i].addr
 		redeemScriptLen := len(addr.redeemScript())
 		n := wire.VarIntSerializeSize(uint64(redeemScriptLen))
 		sigScriptLen := 1 + (74 * int(addr.series().reqSigs)) + redeemScriptLen + 1 + n
diff --git a/votingpool/withdrawal_test.go b/votingpool/withdrawal_test.go
index 7ba6c89524..991864d06a 100644
--- a/votingpool/withdrawal_test.go
+++ b/votingpool/withdrawal_test.go
@@ -37,7 +37,7 @@ func TestStartWithdrawal(t *testing.T) {
 	def := vp.TstCreateSeriesDef(t, pool, 2, masters)
 	vp.TstCreateSeries(t, pool, []vp.TstSeriesDef{def})
 	// Create eligible inputs and the list of outputs we need to fulfil.
-	vp.TstCreateCreditsOnSeries(t, pool, def.SeriesID, []int64{5e6, 4e6}, store)
+	vp.TstCreateSeriesCreditsOnStore(t, pool, def.SeriesID, []int64{5e6, 4e6}, store)
 	address1 := "34eVkREKgvvGASZW7hkgE2uNc1yycntMK6"
 	address2 := "3PbExiaztsSYgh6zeMswC49hLUwhTQ86XG"
 	requests := []vp.OutputRequest{
diff --git a/votingpool/withdrawal_wb_test.go b/votingpool/withdrawal_wb_test.go
index 5ce5831826..c0f2007891 100644
--- a/votingpool/withdrawal_wb_test.go
+++ b/votingpool/withdrawal_wb_test.go
@@ -27,14 +27,13 @@ import (
 	"github.com/btcsuite/btcd/wire"
 	"github.com/btcsuite/btcutil"
 	"github.com/btcsuite/btcutil/hdkeychain"
-	"github.com/btcsuite/btcwallet/legacy/txstore"
 	"github.com/btcsuite/btcwallet/waddrmgr"
 )
 
 // TestOutputSplittingNotEnoughInputs checks that an output will get split if we
 // don't have enough inputs to fulfil it.
 func TestOutputSplittingNotEnoughInputs(t *testing.T) {
-	tearDown, pool, store := TstCreatePoolAndTxStore(t)
+	tearDown, pool, _ := TstCreatePoolAndTxStore(t)
 	defer tearDown()
 
 	net := pool.Manager().ChainParams()
@@ -47,7 +46,7 @@ func TestOutputSplittingNotEnoughInputs(t *testing.T) {
 		TstNewOutputRequest(t, 1, "34eVkREKgvvGASZW7hkgE2uNc1yycntMK6", output1Amount, net),
 		TstNewOutputRequest(t, 2, "34eVkREKgvvGASZW7hkgE2uNc1yycntMK6", output2Amount, net),
 	}
-	seriesID, eligible := TstCreateCredits(t, pool, []int64{7}, store)
+	seriesID, eligible := TstCreateCreditsOnNewSeries(t, pool, []int64{7})
 	w := newWithdrawal(0, requests, eligible, *TstNewChangeAddress(t, pool, seriesID, 0))
 
 	// Trigger an output split because of lack of inputs by forcing a high fee.
@@ -81,7 +80,7 @@ func TestOutputSplittingNotEnoughInputs(t *testing.T) {
 }
 
 func TestOutputSplittingOversizeTx(t *testing.T) {
-	tearDown, pool, store := TstCreatePoolAndTxStore(t)
+	tearDown, pool, _ := TstCreatePoolAndTxStore(t)
 	defer tearDown()
 
 	requestAmount := btcutil.Amount(5)
@@ -89,7 +88,7 @@ func TestOutputSplittingOversizeTx(t *testing.T) {
 	smallInput := int64(2)
 	request := TstNewOutputRequest(
 		t, 1, "34eVkREKgvvGASZW7hkgE2uNc1yycntMK6", requestAmount, pool.Manager().ChainParams())
-	seriesID, eligible := TstCreateCredits(t, pool, []int64{bigInput, smallInput}, store)
+	seriesID, eligible := TstCreateCreditsOnNewSeries(t, pool, []int64{bigInput, smallInput})
 	changeStart := TstNewChangeAddress(t, pool, seriesID, 0)
 	w := newWithdrawal(0, []OutputRequest{request}, eligible, *changeStart)
 	restoreCalculateTxFee := replaceCalculateTxFee(TstConstantFee(0))
@@ -136,11 +135,11 @@ func TestOutputSplittingOversizeTx(t *testing.T) {
 }
 
 func TestSplitLastOutputNoOutputs(t *testing.T) {
-	tearDown, pool, store := TstCreatePoolAndTxStore(t)
+	tearDown, pool, _ := TstCreatePoolAndTxStore(t)
 	defer tearDown()
 
-	w := newWithdrawal(0, []OutputRequest{}, []Credit{}, ChangeAddress{})
-	w.current = createWithdrawalTx(t, pool, store, []int64{}, []int64{})
+	w := newWithdrawal(0, []OutputRequest{}, []credit{}, ChangeAddress{})
+	w.current = createWithdrawalTx(t, pool, []int64{}, []int64{})
 
 	err := w.splitLastOutput()
 
@@ -150,12 +149,12 @@ func TestSplitLastOutputNoOutputs(t *testing.T) {
 // Check that all outputs requested in a withdrawal match the outputs of the generated
 // transaction(s).
 func TestWithdrawalTxOutputs(t *testing.T) {
-	tearDown, pool, store := TstCreatePoolAndTxStore(t)
+	tearDown, pool, _ := TstCreatePoolAndTxStore(t)
 	defer tearDown()
 	net := pool.Manager().ChainParams()
 
 	// Create eligible inputs and the list of outputs we need to fulfil.
-	seriesID, eligible := TstCreateCredits(t, pool, []int64{2e6, 4e6}, store)
+	seriesID, eligible := TstCreateCreditsOnNewSeries(t, pool, []int64{2e6, 4e6})
 	outputs := []OutputRequest{
 		TstNewOutputRequest(t, 1, "34eVkREKgvvGASZW7hkgE2uNc1yycntMK6", 3e6, net),
 		TstNewOutputRequest(t, 2, "3PbExiaztsSYgh6zeMswC49hLUwhTQ86XG", 2e6, net),
@@ -174,7 +173,7 @@ func TestWithdrawalTxOutputs(t *testing.T) {
 	tx := w.transactions[0]
 	// The created tx should include both eligible credits, so we expect it to have
 	// an input amount of 2e6+4e6 satoshis.
-	inputAmount := eligible[0].Amount() + eligible[1].Amount()
+	inputAmount := eligible[0].Amount + eligible[1].Amount
 	change := inputAmount - (outputs[0].Amount + outputs[1].Amount + calculateTxFee(tx))
 	expectedOutputs := append(
 		outputs, TstNewOutputRequest(t, 3, changeStart.addr.String(), change, net))
@@ -185,10 +184,10 @@ func TestWithdrawalTxOutputs(t *testing.T) {
 // Check that withdrawal.status correctly states that no outputs were fulfilled when we
 // don't have enough eligible credits for any of them.
 func TestFulfillRequestsNoSatisfiableOutputs(t *testing.T) {
-	tearDown, pool, store := TstCreatePoolAndTxStore(t)
+	tearDown, pool, _ := TstCreatePoolAndTxStore(t)
 	defer tearDown()
 
-	seriesID, eligible := TstCreateCredits(t, pool, []int64{1e6}, store)
+	seriesID, eligible := TstCreateCreditsOnNewSeries(t, pool, []int64{1e6})
 	request := TstNewOutputRequest(
 		t, 1, "3Qt1EaKRD9g9FeL2DGkLLswhK1AKmmXFSe", btcutil.Amount(3e6), pool.Manager().ChainParams())
 	changeStart := TstNewChangeAddress(t, pool, seriesID, 0)
@@ -217,12 +216,12 @@ func TestFulfillRequestsNoSatisfiableOutputs(t *testing.T) {
 // Check that some requested outputs are not fulfilled when we don't have credits for all
 // of them.
 func TestFulfillRequestsNotEnoughCreditsForAllRequests(t *testing.T) {
-	tearDown, pool, store := TstCreatePoolAndTxStore(t)
+	tearDown, pool, _ := TstCreatePoolAndTxStore(t)
 	defer tearDown()
 	net := pool.Manager().ChainParams()
 
 	// Create eligible inputs and the list of outputs we need to fulfil.
-	seriesID, eligible := TstCreateCredits(t, pool, []int64{2e6, 4e6}, store)
+	seriesID, eligible := TstCreateCreditsOnNewSeries(t, pool, []int64{2e6, 4e6})
 	out1 := TstNewOutputRequest(
 		t, 1, "34eVkREKgvvGASZW7hkgE2uNc1yycntMK6", btcutil.Amount(3e6), net)
 	out2 := TstNewOutputRequest(
@@ -240,7 +239,7 @@ func TestFulfillRequestsNotEnoughCreditsForAllRequests(t *testing.T) {
 	tx := w.transactions[0]
 	// The created tx should spend both eligible credits, so we expect it to have
 	// an input amount of 2e6+4e6 satoshis.
-	inputAmount := eligible[0].Amount() + eligible[1].Amount()
+	inputAmount := eligible[0].Amount + eligible[1].Amount
 	// We expect it to include outputs for requests 1 and 2, plus a change output, but
 	// output request #3 should not be there because we don't have enough credits.
 	change := inputAmount - (out1.Amount + out2.Amount + calculateTxFee(tx))
@@ -268,10 +267,10 @@ func TestFulfillRequestsNotEnoughCreditsForAllRequests(t *testing.T) {
 // TestRollbackLastOutput tests the case where we rollback one output
 // and one input, such that sum(in) >= sum(out) + fee.
 func TestRollbackLastOutput(t *testing.T) {
-	tearDown, pool, store := TstCreatePoolAndTxStore(t)
+	tearDown, pool, _ := TstCreatePoolAndTxStore(t)
 	defer tearDown()
 
-	tx := createWithdrawalTx(t, pool, store, []int64{3, 3, 2, 1, 3}, []int64{3, 3, 2, 2})
+	tx := createWithdrawalTx(t, pool, []int64{3, 3, 2, 1, 3}, []int64{3, 3, 2, 2})
 	initialInputs := tx.inputs
 	initialOutputs := tx.outputs
 
@@ -292,7 +291,7 @@ func TestRollbackLastOutput(t *testing.T) {
 		t.Fatalf("Unexpected number of inputs removed; got %d, want 1", len(removedInputs))
 	}
 	lastInput := initialInputs[len(initialInputs)-1]
-	if removedInputs[0] != lastInput {
+	if !reflect.DeepEqual(removedInputs[0], lastInput) {
 		t.Fatalf("Wrong rolled back input; got %s want %s", removedInputs[0], lastInput)
 	}
 
@@ -303,12 +302,12 @@ func TestRollbackLastOutput(t *testing.T) {
 }
 
 func TestRollbackLastOutputMultipleInputsRolledBack(t *testing.T) {
-	tearDown, pool, store := TstCreatePoolAndTxStore(t)
+	tearDown, pool, _ := TstCreatePoolAndTxStore(t)
 	defer tearDown()
 
 	// This tx will need the 3 last inputs to fulfill the second output, so they
 	// should all be rolled back and returned in the reverse order they were added.
-	tx := createWithdrawalTx(t, pool, store, []int64{1, 2, 3, 4}, []int64{1, 8})
+	tx := createWithdrawalTx(t, pool, []int64{1, 2, 3, 4}, []int64{1, 8})
 	initialInputs := tx.inputs
 	initialOutputs := tx.outputs
 
@@ -323,8 +322,8 @@ func TestRollbackLastOutputMultipleInputsRolledBack(t *testing.T) {
 		t.Fatalf("Unexpected number of inputs removed; got %d, want 3", len(removedInputs))
 	}
 	for i, amount := range []btcutil.Amount{4, 3, 2} {
-		if removedInputs[i].Amount() != amount {
-			t.Fatalf("Unexpected input amount; got %v, want %v", removedInputs[i].Amount(), amount)
+		if removedInputs[i].Amount != amount {
+			t.Fatalf("Unexpected input amount; got %v, want %v", removedInputs[i].Amount, amount)
 		}
 	}
 
@@ -337,10 +336,10 @@ func TestRollbackLastOutputMultipleInputsRolledBack(t *testing.T) {
 // TestRollbackLastOutputNoInputsRolledBack tests the case where we roll back
 // one output but don't need to roll back any inputs.
 func TestRollbackLastOutputNoInputsRolledBack(t *testing.T) {
-	tearDown, pool, store := TstCreatePoolAndTxStore(t)
+	tearDown, pool, _ := TstCreatePoolAndTxStore(t)
 	defer tearDown()
 
-	tx := createWithdrawalTx(t, pool, store, []int64{4}, []int64{2, 3})
+	tx := createWithdrawalTx(t, pool, []int64{4}, []int64{2, 3})
 	initialInputs := tx.inputs
 	initialOutputs := tx.outputs
 
@@ -385,11 +384,11 @@ func TestRollBackLastOutputInsufficientOutputs(t *testing.T) {
 // TestRollbackLastOutputWhenNewOutputAdded checks that we roll back the last
 // output if a tx becomes too big right after we add a new output to it.
 func TestRollbackLastOutputWhenNewOutputAdded(t *testing.T) {
-	tearDown, pool, store := TstCreatePoolAndTxStore(t)
+	tearDown, pool, _ := TstCreatePoolAndTxStore(t)
 	defer tearDown()
 
 	net := pool.Manager().ChainParams()
-	series, eligible := TstCreateCredits(t, pool, []int64{5, 5}, store)
+	series, eligible := TstCreateCreditsOnNewSeries(t, pool, []int64{5, 5})
 	requests := []OutputRequest{
 		// This is ordered by bailment ID
 		TstNewOutputRequest(t, 1, "34eVkREKgvvGASZW7hkgE2uNc1yycntMK6", 1, net),
@@ -433,11 +432,11 @@ func TestRollbackLastOutputWhenNewOutputAdded(t *testing.T) {
 // TestRollbackLastOutputWhenNewInputAdded checks that we roll back the last
 // output if a tx becomes too big right after we add a new input to it.
 func TestRollbackLastOutputWhenNewInputAdded(t *testing.T) {
-	tearDown, pool, store := TstCreatePoolAndTxStore(t)
+	tearDown, pool, _ := TstCreatePoolAndTxStore(t)
 	defer tearDown()
 
 	net := pool.Manager().ChainParams()
-	series, eligible := TstCreateCredits(t, pool, []int64{1, 2, 3, 4, 5, 6}, store)
+	series, eligible := TstCreateCreditsOnNewSeries(t, pool, []int64{1, 2, 3, 4, 5, 6})
 	requests := []OutputRequest{
 		// This is manually ordered by outBailmentIDHash, which is the order in
 		// which they're going to be fulfilled by w.fulfillRequests().
@@ -488,10 +487,10 @@ func TestRollbackLastOutputWhenNewInputAdded(t *testing.T) {
 }
 
 func TestWithdrawalTxRemoveOutput(t *testing.T) {
-	tearDown, pool, store := TstCreatePoolAndTxStore(t)
+	tearDown, pool, _ := TstCreatePoolAndTxStore(t)
 	defer tearDown()
 
-	tx := createWithdrawalTx(t, pool, store, []int64{}, []int64{1, 2})
+	tx := createWithdrawalTx(t, pool, []int64{}, []int64{1, 2})
 	outputs := tx.outputs
 	// Make sure we have created the transaction with the expected
 	// outputs.
@@ -516,10 +515,10 @@ func TestWithdrawalTxRemoveOutput(t *testing.T) {
 }
 
 func TestWithdrawalTxRemoveInput(t *testing.T) {
-	tearDown, pool, store := TstCreatePoolAndTxStore(t)
+	tearDown, pool, _ := TstCreatePoolAndTxStore(t)
 	defer tearDown()
 
-	tx := createWithdrawalTx(t, pool, store, []int64{1, 2}, []int64{})
+	tx := createWithdrawalTx(t, pool, []int64{1, 2}, []int64{})
 	inputs := tx.inputs
 	// Make sure we have created the transaction with the expected inputs
 	checkTxInputs(t, tx, inputs)
@@ -530,23 +529,23 @@ func TestWithdrawalTxRemoveInput(t *testing.T) {
 	gotRemovedInput := tx.removeInput()
 
 	// Check the popped input looks correct.
-	if gotRemovedInput != wantRemovedInput {
+	if !reflect.DeepEqual(gotRemovedInput, wantRemovedInput) {
 		t.Fatalf("Popped input wrong; got %v, want %v", gotRemovedInput, wantRemovedInput)
 	}
 	checkTxInputs(t, tx, inputs[0:1])
 
 	// Make sure that the remaining input is really the right one.
-	if tx.inputs[0] != remainingInput {
+	if !reflect.DeepEqual(tx.inputs[0], remainingInput) {
 		t.Fatalf("Wrong input: got %v, want %v", tx.inputs[0], remainingInput)
 	}
 }
 
 func TestWithdrawalTxAddChange(t *testing.T) {
-	tearDown, pool, store := TstCreatePoolAndTxStore(t)
+	tearDown, pool, _ := TstCreatePoolAndTxStore(t)
 	defer tearDown()
 
 	input, output, fee := int64(4e6), int64(3e6), int64(10)
-	tx := createWithdrawalTx(t, pool, store, []int64{input}, []int64{output})
+	tx := createWithdrawalTx(t, pool, []int64{input}, []int64{output})
 	restoreCalcTxFee := replaceCalculateTxFee(TstConstantFee(btcutil.Amount(fee)))
 	defer restoreCalcTxFee()
 
@@ -569,11 +568,11 @@ func TestWithdrawalTxAddChange(t *testing.T) {
 // add a change output when there's no satoshis left after paying all
 // outputs+fees.
 func TestWithdrawalTxAddChangeNoChange(t *testing.T) {
-	tearDown, pool, store := TstCreatePoolAndTxStore(t)
+	tearDown, pool, _ := TstCreatePoolAndTxStore(t)
 	defer tearDown()
 
 	input, output, fee := int64(4e6), int64(4e6), int64(0)
-	tx := createWithdrawalTx(t, pool, store, []int64{input}, []int64{output})
+	tx := createWithdrawalTx(t, pool, []int64{input}, []int64{output})
 	restoreCalcTxFee := replaceCalculateTxFee(TstConstantFee(btcutil.Amount(fee)))
 	defer restoreCalcTxFee()
 
@@ -587,20 +586,20 @@ func TestWithdrawalTxAddChangeNoChange(t *testing.T) {
 }
 
 func TestWithdrawalTxToMsgTxNoInputsOrOutputsOrChange(t *testing.T) {
-	tearDown, pool, store := TstCreatePoolAndTxStore(t)
+	tearDown, pool, _ := TstCreatePoolAndTxStore(t)
 	defer tearDown()
 
-	tx := createWithdrawalTx(t, pool, store, []int64{}, []int64{})
+	tx := createWithdrawalTx(t, pool, []int64{}, []int64{})
 	msgtx := tx.toMsgTx()
 	compareMsgTxAndWithdrawalTxOutputs(t, msgtx, tx)
 	compareMsgTxAndWithdrawalTxInputs(t, msgtx, tx)
 }
 
 func TestWithdrawalTxToMsgTxNoInputsOrOutputsWithChange(t *testing.T) {
-	tearDown, pool, store := TstCreatePoolAndTxStore(t)
+	tearDown, pool, _ := TstCreatePoolAndTxStore(t)
 	defer tearDown()
 
-	tx := createWithdrawalTx(t, pool, store, []int64{}, []int64{})
+	tx := createWithdrawalTx(t, pool, []int64{}, []int64{})
 	tx.changeOutput = wire.NewTxOut(int64(1), []byte{})
 
 	msgtx := tx.toMsgTx()
@@ -610,10 +609,10 @@ func TestWithdrawalTxToMsgTxNoInputsOrOutputsWithChange(t *testing.T) {
 }
 
 func TestWithdrawalTxToMsgTxWithInputButNoOutputsWithChange(t *testing.T) {
-	tearDown, pool, store := TstCreatePoolAndTxStore(t)
+	tearDown, pool, _ := TstCreatePoolAndTxStore(t)
 	defer tearDown()
 
-	tx := createWithdrawalTx(t, pool, store, []int64{1}, []int64{})
+	tx := createWithdrawalTx(t, pool, []int64{1}, []int64{})
 	tx.changeOutput = wire.NewTxOut(int64(1), []byte{})
 
 	msgtx := tx.toMsgTx()
@@ -623,11 +622,11 @@ func TestWithdrawalTxToMsgTxWithInputButNoOutputsWithChange(t *testing.T) {
 }
 
 func TestWithdrawalTxToMsgTxWithInputOutputsAndChange(t *testing.T) {
-	tearDown, pool, store := TstCreatePoolAndTxStore(t)
+	tearDown, pool, _ := TstCreatePoolAndTxStore(t)
 
 	defer tearDown()
 
-	tx := createWithdrawalTx(t, pool, store, []int64{1, 2, 3}, []int64{4, 5, 6})
+	tx := createWithdrawalTx(t, pool, []int64{1, 2, 3}, []int64{4, 5, 6})
 	tx.changeOutput = wire.NewTxOut(int64(7), []byte{})
 
 	msgtx := tx.toMsgTx()
@@ -637,10 +636,10 @@ func TestWithdrawalTxToMsgTxWithInputOutputsAndChange(t *testing.T) {
 }
 
 func TestWithdrawalTxInputTotal(t *testing.T) {
-	tearDown, pool, store := TstCreatePoolAndTxStore(t)
+	tearDown, pool, _ := TstCreatePoolAndTxStore(t)
 	defer tearDown()
 
-	tx := createWithdrawalTx(t, pool, store, []int64{5}, []int64{})
+	tx := createWithdrawalTx(t, pool, []int64{5}, []int64{})
 
 	if tx.inputTotal() != btcutil.Amount(5) {
 		t.Fatalf("Wrong total output; got %v, want %v", tx.outputTotal(), btcutil.Amount(5))
@@ -648,10 +647,10 @@ func TestWithdrawalTxInputTotal(t *testing.T) {
 }
 
 func TestWithdrawalTxOutputTotal(t *testing.T) {
-	tearDown, pool, store := TstCreatePoolAndTxStore(t)
+	tearDown, pool, _ := TstCreatePoolAndTxStore(t)
 	defer tearDown()
 
-	tx := createWithdrawalTx(t, pool, store, []int64{}, []int64{4})
+	tx := createWithdrawalTx(t, pool, []int64{}, []int64{4})
 	tx.changeOutput = wire.NewTxOut(int64(1), []byte{})
 
 	if tx.outputTotal() != btcutil.Amount(4) {
@@ -660,12 +659,12 @@ func TestWithdrawalTxOutputTotal(t *testing.T) {
 }
 
 func TestSignMultiSigUTXO(t *testing.T) {
-	tearDown, pool, store := TstCreatePoolAndTxStore(t)
+	tearDown, pool, _ := TstCreatePoolAndTxStore(t)
 	defer tearDown()
 
 	// Create a new tx with a single input that we're going to sign.
 	mgr := pool.Manager()
-	tx := createWithdrawalTx(t, pool, store, []int64{4e6}, []int64{4e6})
+	tx := createWithdrawalTx(t, pool, []int64{4e6}, []int64{4e6})
 	sigs, err := getRawSigs([]*withdrawalTx{tx})
 	if err != nil {
 		t.Fatal(err)
@@ -675,7 +674,7 @@ func TestSignMultiSigUTXO(t *testing.T) {
 	txSigs := sigs[tx.ntxid()]
 
 	idx := 0 // The index of the tx input we're going to sign.
-	pkScript := tx.inputs[idx].TxOut().PkScript
+	pkScript := tx.inputs[idx].PkScript
 	TstRunWithManagerUnlocked(t, mgr, func() {
 		if err = signMultiSigUTXO(mgr, msgtx, idx, pkScript, txSigs[idx]); err != nil {
 			t.Fatal(err)
@@ -684,11 +683,11 @@ func TestSignMultiSigUTXO(t *testing.T) {
 }
 
 func TestSignMultiSigUTXOUnparseablePkScript(t *testing.T) {
-	tearDown, pool, store := TstCreatePoolAndTxStore(t)
+	tearDown, pool, _ := TstCreatePoolAndTxStore(t)
 	defer tearDown()
 
 	mgr := pool.Manager()
-	tx := createWithdrawalTx(t, pool, store, []int64{4e6}, []int64{})
+	tx := createWithdrawalTx(t, pool, []int64{4e6}, []int64{})
 	msgtx := tx.toMsgTx()
 
 	unparseablePkScript := []byte{0x01}
@@ -698,11 +697,11 @@ func TestSignMultiSigUTXOUnparseablePkScript(t *testing.T) {
 }
 
 func TestSignMultiSigUTXOPkScriptNotP2SH(t *testing.T) {
-	tearDown, pool, store := TstCreatePoolAndTxStore(t)
+	tearDown, pool, _ := TstCreatePoolAndTxStore(t)
 	defer tearDown()
 
 	mgr := pool.Manager()
-	tx := createWithdrawalTx(t, pool, store, []int64{4e6}, []int64{})
+	tx := createWithdrawalTx(t, pool, []int64{4e6}, []int64{})
 	addr, _ := btcutil.DecodeAddress("1MirQ9bwyQcGVJPwKUgapu5ouK2E2Ey4gX", mgr.ChainParams())
 	pubKeyHashPkScript, _ := txscript.PayToAddrScript(addr.(*btcutil.AddressPubKeyHash))
 	msgtx := tx.toMsgTx()
@@ -713,11 +712,11 @@ func TestSignMultiSigUTXOPkScriptNotP2SH(t *testing.T) {
 }
 
 func TestSignMultiSigUTXORedeemScriptNotFound(t *testing.T) {
-	tearDown, pool, store := TstCreatePoolAndTxStore(t)
+	tearDown, pool, _ := TstCreatePoolAndTxStore(t)
 	defer tearDown()
 
 	mgr := pool.Manager()
-	tx := createWithdrawalTx(t, pool, store, []int64{4e6}, []int64{})
+	tx := createWithdrawalTx(t, pool, []int64{4e6}, []int64{})
 	// This is a P2SH address for which the addr manager doesn't have the redeem
 	// script.
 	addr, _ := btcutil.DecodeAddress("3Hb4xcebcKg4DiETJfwjh8sF4uDw9rqtVC", mgr.ChainParams())
@@ -733,11 +732,11 @@ func TestSignMultiSigUTXORedeemScriptNotFound(t *testing.T) {
 }
 
 func TestSignMultiSigUTXONotEnoughSigs(t *testing.T) {
-	tearDown, pool, store := TstCreatePoolAndTxStore(t)
+	tearDown, pool, _ := TstCreatePoolAndTxStore(t)
 	defer tearDown()
 
 	mgr := pool.Manager()
-	tx := createWithdrawalTx(t, pool, store, []int64{4e6}, []int64{})
+	tx := createWithdrawalTx(t, pool, []int64{4e6}, []int64{})
 	sigs, err := getRawSigs([]*withdrawalTx{tx})
 	if err != nil {
 		t.Fatal(err)
@@ -747,9 +746,9 @@ func TestSignMultiSigUTXONotEnoughSigs(t *testing.T) {
 
 	idx := 0 // The index of the tx input we're going to sign.
 	// Here we provide reqSigs-1 signatures to SignMultiSigUTXO()
-	reqSigs := tx.inputs[idx].Address().series().TstGetReqSigs()
+	reqSigs := tx.inputs[idx].addr.series().TstGetReqSigs()
 	txInSigs := txSigs[idx][:reqSigs-1]
-	pkScript := tx.inputs[idx].TxOut().PkScript
+	pkScript := tx.inputs[idx].PkScript
 	TstRunWithManagerUnlocked(t, mgr, func() {
 		err = signMultiSigUTXO(mgr, msgtx, idx, pkScript, txInSigs)
 	})
@@ -758,15 +757,15 @@ func TestSignMultiSigUTXONotEnoughSigs(t *testing.T) {
 }
 
 func TestSignMultiSigUTXOWrongRawSigs(t *testing.T) {
-	tearDown, pool, store := TstCreatePoolAndTxStore(t)
+	tearDown, pool, _ := TstCreatePoolAndTxStore(t)
 	defer tearDown()
 
 	mgr := pool.Manager()
-	tx := createWithdrawalTx(t, pool, store, []int64{4e6}, []int64{})
+	tx := createWithdrawalTx(t, pool, []int64{4e6}, []int64{})
 	sigs := []RawSig{RawSig{0x00}, RawSig{0x01}}
 
 	idx := 0 // The index of the tx input we're going to sign.
-	pkScript := tx.inputs[idx].TxOut().PkScript
+	pkScript := tx.inputs[idx].PkScript
 	var err error
 	TstRunWithManagerUnlocked(t, mgr, func() {
 		err = signMultiSigUTXO(mgr, tx.toMsgTx(), idx, pkScript, sigs)
@@ -776,10 +775,10 @@ func TestSignMultiSigUTXOWrongRawSigs(t *testing.T) {
 }
 
 func TestGetRawSigs(t *testing.T) {
-	tearDown, pool, store := TstCreatePoolAndTxStore(t)
+	tearDown, pool, _ := TstCreatePoolAndTxStore(t)
 	defer tearDown()
 
-	tx := createWithdrawalTx(t, pool, store, []int64{5e6, 4e6}, []int64{})
+	tx := createWithdrawalTx(t, pool, []int64{5e6, 4e6}, []int64{})
 
 	sigs, err := getRawSigs([]*withdrawalTx{tx})
 	if err != nil {
@@ -791,7 +790,7 @@ func TestGetRawSigs(t *testing.T) {
 		t.Fatalf("Unexpected number of sig lists; got %d, want %d", len(txSigs), len(tx.inputs))
 	}
 
-	checkNonEmptySigsForPrivKeys(t, txSigs, tx.inputs[0].Address().series().privateKeys)
+	checkNonEmptySigsForPrivKeys(t, txSigs, tx.inputs[0].addr.series().privateKeys)
 
 	// Since we have all the necessary signatures (m-of-n), we construct the
 	// sigsnature scripts and execute them to make sure the raw signatures are
@@ -800,12 +799,12 @@ func TestGetRawSigs(t *testing.T) {
 }
 
 func TestGetRawSigsOnlyOnePrivKeyAvailable(t *testing.T) {
-	tearDown, pool, store := TstCreatePoolAndTxStore(t)
+	tearDown, pool, _ := TstCreatePoolAndTxStore(t)
 	defer tearDown()
 
-	tx := createWithdrawalTx(t, pool, store, []int64{5e6, 4e6}, []int64{})
+	tx := createWithdrawalTx(t, pool, []int64{5e6, 4e6}, []int64{})
 	// Remove all private keys but the first one from the credit's series.
-	series := tx.inputs[0].Address().series()
+	series := tx.inputs[0].addr.series()
 	for i := range series.privateKeys[1:] {
 		series.privateKeys[i] = nil
 	}
@@ -824,13 +823,13 @@ func TestGetRawSigsOnlyOnePrivKeyAvailable(t *testing.T) {
 }
 
 func TestGetRawSigsUnparseableRedeemScript(t *testing.T) {
-	tearDown, pool, store := TstCreatePoolAndTxStore(t)
+	tearDown, pool, _ := TstCreatePoolAndTxStore(t)
 	defer tearDown()
 
-	tx := createWithdrawalTx(t, pool, store, []int64{5e6, 4e6}, []int64{})
+	tx := createWithdrawalTx(t, pool, []int64{5e6, 4e6}, []int64{})
 	// Change the redeem script for one of our tx inputs, to force an error in
 	// getRawSigs().
-	tx.inputs[0].Address().script = []byte{0x01}
+	tx.inputs[0].addr.script = []byte{0x01}
 
 	_, err := getRawSigs([]*withdrawalTx{tx})
 
@@ -838,13 +837,13 @@ func TestGetRawSigsUnparseableRedeemScript(t *testing.T) {
 }
 
 func TestGetRawSigsInvalidAddrBranch(t *testing.T) {
-	tearDown, pool, store := TstCreatePoolAndTxStore(t)
+	tearDown, pool, _ := TstCreatePoolAndTxStore(t)
 	defer tearDown()
 
-	tx := createWithdrawalTx(t, pool, store, []int64{5e6, 4e6}, []int64{})
+	tx := createWithdrawalTx(t, pool, []int64{5e6, 4e6}, []int64{})
 	// Change the branch of our input's address to an invalid value, to force
 	// an error in getRawSigs().
-	tx.inputs[0].Address().branch = Branch(999)
+	tx.inputs[0].addr.branch = Branch(999)
 
 	_, err := getRawSigs([]*withdrawalTx{tx})
 
@@ -870,10 +869,10 @@ func TestOutBailmentIDSort(t *testing.T) {
 }
 
 func TestTxTooBig(t *testing.T) {
-	tearDown, pool, store := TstCreatePoolAndTxStore(t)
+	tearDown, pool, _ := TstCreatePoolAndTxStore(t)
 	defer tearDown()
 
-	tx := createWithdrawalTx(t, pool, store, []int64{5}, []int64{1})
+	tx := createWithdrawalTx(t, pool, []int64{5}, []int64{1})
 
 	restoreCalcTxSize := replaceCalculateTxSize(func(tx *withdrawalTx) int { return txMaxSize - 1 })
 	if isTxTooBig(tx) {
@@ -899,10 +898,10 @@ func TestTxTooBig(t *testing.T) {
 }
 
 func TestTxSizeCalculation(t *testing.T) {
-	tearDown, pool, store := TstCreatePoolAndTxStore(t)
+	tearDown, pool, _ := TstCreatePoolAndTxStore(t)
 	defer tearDown()
 
-	tx := createWithdrawalTx(t, pool, store, []int64{1, 5}, []int64{2})
+	tx := createWithdrawalTx(t, pool, []int64{1, 5}, []int64{2})
 
 	size := calculateTxSize(tx)
 
@@ -912,7 +911,7 @@ func TestTxSizeCalculation(t *testing.T) {
 	// output.
 	restoreCalcTxFee := replaceCalculateTxFee(TstConstantFee(1))
 	defer restoreCalcTxFee()
-	seriesID := tx.inputs[0].Address().SeriesID()
+	seriesID := tx.inputs[0].addr.SeriesID()
 	tx.addChange(TstNewChangeAddress(t, pool, seriesID, 0).addr.ScriptAddress())
 	msgtx := tx.toMsgTx()
 	sigs, err := getRawSigs([]*withdrawalTx{tx})
@@ -925,7 +924,7 @@ func TestTxSizeCalculation(t *testing.T) {
 	// calculateTxSize() we use a dummy signature for the worst-case scenario (73
 	// bytes) so the estimate here can be up to 2 bytes bigger for every
 	// signature in every input's SigScript.
-	maxDiff := 2 * len(msgtx.TxIn) * int(tx.inputs[0].Address().series().reqSigs)
+	maxDiff := 2 * len(msgtx.TxIn) * int(tx.inputs[0].addr.series().reqSigs)
 	// To make things worse, there's a possibility that the length of the
 	// actual SignatureScript is at the upper boundary of one of the uint*
 	// types, and when that happens our dummy SignatureScript is likely to have
@@ -973,17 +972,6 @@ func TestTxFeeEstimationForLargeTx(t *testing.T) {
 	}
 }
 
-// lookupStoredTx returns the TxRecord from the given store whose SHA matches the
-// given ShaHash.
-func lookupStoredTx(store *txstore.Store, sha *wire.ShaHash) *txstore.TxRecord {
-	for _, r := range store.Records() {
-		if bytes.Equal(r.Tx().Sha()[:], sha[:]) {
-			return r
-		}
-	}
-	return nil
-}
-
 // checkNonEmptySigsForPrivKeys checks that every signature list in txSigs has
 // one non-empty signature for every non-nil private key in the given list. This
 // is to make sure every signature list matches the specification at
@@ -1044,12 +1032,12 @@ func checkMsgTxOutputs(t *testing.T, msgtx *wire.MsgTx, requests []OutputRequest
 }
 
 // checkTxInputs ensures that the tx.inputs match the given inputs.
-func checkTxInputs(t *testing.T, tx *withdrawalTx, inputs []Credit) {
+func checkTxInputs(t *testing.T, tx *withdrawalTx, inputs []credit) {
 	if len(tx.inputs) != len(inputs) {
 		t.Fatalf("Wrong number of inputs in tx; got %d, want %d", len(tx.inputs), len(inputs))
 	}
 	for i, input := range tx.inputs {
-		if input != inputs[i] {
+		if !reflect.DeepEqual(input, inputs[i]) {
 			t.Fatalf("Unexpected input; got %s, want %s", input, inputs[i])
 		}
 	}
@@ -1059,9 +1047,9 @@ func checkTxInputs(t *testing.T, tx *withdrawalTx, inputs []Credit) {
 // transaction (using the given raw signatures and the pkScripts from credits) and execute
 // those scripts to validate them.
 func signTxAndValidate(t *testing.T, mgr *waddrmgr.Manager, tx *wire.MsgTx, txSigs TxSigs,
-	credits []Credit) {
+	credits []credit) {
 	for i := range tx.TxIn {
-		pkScript := credits[i].TxOut().PkScript
+		pkScript := credits[i].PkScript
 		TstRunWithManagerUnlocked(t, mgr, func() {
 			if err := signMultiSigUTXO(mgr, tx, i, pkScript, txSigs[i]); err != nil {
 				t.Fatal(err)
@@ -1076,9 +1064,9 @@ func compareMsgTxAndWithdrawalTxInputs(t *testing.T, msgtx *wire.MsgTx, tx *with
 	}
 
 	for i, txin := range msgtx.TxIn {
-		outpoint := tx.inputs[i].OutPoint()
-		if txin.PreviousOutPoint != *outpoint {
-			t.Fatalf("Wrong outpoint; got %v expected %v", txin.PreviousOutPoint, *outpoint)
+		outpoint := tx.inputs[i].OutPoint
+		if txin.PreviousOutPoint != outpoint {
+			t.Fatalf("Wrong outpoint; got %v expected %v", txin.PreviousOutPoint, outpoint)
 		}
 	}
 }