func (tx *withdrawalTx) addOutput(request OutputRequest) {
	log.Debugf("Added tx output sending %s to %s", request.Amount, request.Address)
	tx.outputs = append(tx.outputs, &withdrawalTxOut{request: request, amount: request.Amount})
}
addOutput adds a new output to this transaction.
package votingpool
import (
	"bytes"
	"crypto/sha256"
	"fmt"
	"math"
	"reflect"
	"sort"
	"strconv"
	"time"
	"github.com/gcash/bchd/txscript"
	"github.com/gcash/bchd/wire"
	"github.com/gcash/bchutil"
	"github.com/gcash/bchwallet/waddrmgr"
	"github.com/gcash/bchwallet/walletdb"
	"github.com/gcash/bchwallet/wtxmgr"
)
const txMaxSize = 100000
const feeIncrement = 1e3
type outputStatus byte
const (
	statusSuccess outputStatus = iota
	statusPartial
	statusSplit
)
type OutBailmentID string
type Ntxid string
type OutputRequest struct {
	Address  bchutil.Address
	Amount   bchutil.Amount
	PkScript []byte
	Server string
	Transaction uint32
	cachedHash []byte
}
type WithdrawalOutput struct {
	request OutputRequest
	status  outputStatus
	outpoints []OutBailmentOutpoint
}
type OutBailmentOutpoint struct {
	ntxid  Ntxid
	index  uint32
	amount bchutil.Amount
}
type changeAwareTx struct {
	*wire.MsgTx
	changeIdx int32  
}
type WithdrawalStatus struct {
	nextInputAddr  WithdrawalAddress
	nextChangeAddr ChangeAddress
	fees           bchutil.Amount
	outputs        map[OutBailmentID]*WithdrawalOutput
	sigs           map[Ntxid]TxSigs
	amounts        map[Ntxid]InputAmounts
	transactions   map[Ntxid]changeAwareTx
}
type withdrawalInfo struct {
	requests      []OutputRequest
	startAddress  WithdrawalAddress
	changeStart   ChangeAddress
	lastSeriesID  uint32
	dustThreshold bchutil.Amount
	status        WithdrawalStatus
}
type TxSigs [][]RawSig
type InputAmounts []bchutil.Amount
type RawSig []byte
type byAmount []OutputRequest
func (u byAmount) Len() int           { return len(u) }
func (u byAmount) Less(i, j int) bool { return u[i].Amount < u[j].Amount }
func (u byAmount) Swap(i, j int)      { u[i], u[j] = u[j], u[i] }
type byOutBailmentID []OutputRequest
func (s byOutBailmentID) Len() int      { return len(s) }
func (s byOutBailmentID) Swap(i, j int) { s[i], s[j] = s[j], s[i] }
func (s byOutBailmentID) Less(i, j int) bool {
	return bytes.Compare(s[i].outBailmentIDHash(), s[j].outBailmentIDHash()) < 0
}
func (s outputStatus) String() string {
	strings := map[outputStatus]string{
		statusSuccess: "success",
		statusPartial: "partial-",
		statusSplit:   "split",
	}
	return strings[s]
}
func (tx *changeAwareTx) addSelfToStore(store *wtxmgr.Store, txmgrNs walletdb.ReadWriteBucket) error {
	rec, err := wtxmgr.NewTxRecordFromMsgTx(tx.MsgTx, time.Now())
	if err != nil {
		return newError(ErrWithdrawalTxStorage, "error constructing TxRecord for storing", err)
	}
	if err := store.InsertTx(txmgrNs, rec, nil); err != nil {
		return newError(ErrWithdrawalTxStorage, "error adding tx to store", err)
	}
	if tx.changeIdx != -1 {
		if err = store.AddCredit(txmgrNs, rec, nil, uint32(tx.changeIdx), true); err != nil {
			return newError(ErrWithdrawalTxStorage, "error adding tx credits to store", err)
		}
	}
	return nil
}
func (s *WithdrawalStatus) Outputs() map[OutBailmentID]*WithdrawalOutput {
	return s.outputs
}
func (s *WithdrawalStatus) Sigs() map[Ntxid]TxSigs {
	return s.sigs
}
func (s *WithdrawalStatus) InputAmounts() map[Ntxid]InputAmounts {
	return s.amounts
}
func (s *WithdrawalStatus) Fees() bchutil.Amount {
	return s.fees
}
func (s *WithdrawalStatus) NextInputAddr() WithdrawalAddress {
	return s.nextInputAddr
}
func (s *WithdrawalStatus) NextChangeAddr() ChangeAddress {
	return s.nextChangeAddr
}
func (r OutputRequest) String() string {
	return fmt.Sprintf("OutputRequest %s to send %v to %s", r.outBailmentID(), r.Amount, r.Address)
}
func (r OutputRequest) outBailmentID() OutBailmentID {
	return OutBailmentID(fmt.Sprintf("%s:%d", r.Server, r.Transaction))
}
func (r OutputRequest) outBailmentIDHash() []byte {
	if r.cachedHash != nil {
		return r.cachedHash
	}
	str := r.Server + strconv.Itoa(int(r.Transaction))
	hasher := sha256.New()
	_, _ = hasher.Write([]byte(str))
	id := hasher.Sum(nil)
	r.cachedHash = id
	return id
}
func (o *WithdrawalOutput) String() string {
	return fmt.Sprintf("WithdrawalOutput for %s", o.request)
}
func (o *WithdrawalOutput) addOutpoint(outpoint OutBailmentOutpoint) {
	o.outpoints = append(o.outpoints, outpoint)
}
func (o *WithdrawalOutput) Status() string {
	return o.status.String()
}
func (o *WithdrawalOutput) Address() string {
	return o.request.Address.String()
}
func (o *WithdrawalOutput) Outpoints() []OutBailmentOutpoint {
	return o.outpoints
}
func (o OutBailmentOutpoint) Amount() bchutil.Amount {
	return o.amount
}
type withdrawal struct {
	roundID         uint32
	status          *WithdrawalStatus
	transactions    []*withdrawalTx
	pendingRequests []OutputRequest
	eligibleInputs  []Credit
	current         *withdrawalTx
	txOptions func(tx *withdrawalTx)
}
type withdrawalTxOut struct {
	request OutputRequest
	amount  bchutil.Amount
}
func (o *withdrawalTxOut) String() string {
	return fmt.Sprintf("withdrawalTxOut fulfilling %v of %s", o.amount, o.request)
}
func (o *withdrawalTxOut) pkScript() []byte {
	return o.request.PkScript
}
type withdrawalTx struct {
	inputs  []Credit
	outputs []*withdrawalTxOut
	fee     bchutil.Amount
	changeOutput *wire.TxOut
	calculateSize func() int
	calculateFee func() bchutil.Amount
}
func newWithdrawalTx(setOptions func(tx *withdrawalTx)) *withdrawalTx {
	tx := &withdrawalTx{}
	tx.calculateSize = func() int { return calculateTxSize(tx) }
	tx.calculateFee = func() bchutil.Amount {
		return bchutil.Amount(1+tx.calculateSize()/1000) * feeIncrement
	}
	setOptions(tx)
	return tx
}
func (tx *withdrawalTx) ntxid() Ntxid {
	msgtx := tx.toMsgTx()
	var empty []byte
	for _, txin := range msgtx.TxIn {
		txin.SignatureScript = empty
	}
	return Ntxid(msgtx.TxHash().String())
}
func (tx *withdrawalTx) isTooBig() bool {
	return tx.calculateSize() >= txMaxSize
}
func (tx *withdrawalTx) inputTotal() (total bchutil.Amount) {
	for _, input := range tx.inputs {
		total += input.Amount
	}
	return total
}
func (tx *withdrawalTx) outputTotal() (total bchutil.Amount) {
	for _, output := range tx.outputs {
		total += output.amount
	}
	return total
}
func (tx *withdrawalTx) hasChange() bool {
	return tx.changeOutput != nil
}
func (tx *withdrawalTx) toMsgTx() *wire.MsgTx {
	msgtx := wire.NewMsgTx(wire.TxVersion)
	for _, o := range tx.outputs {
		msgtx.AddTxOut(wire.NewTxOut(int64(o.amount), o.pkScript()))
	}
	if tx.hasChange() {
		msgtx.AddTxOut(tx.changeOutput)
	}
	for _, i := range tx.inputs {
		msgtx.AddTxIn(wire.NewTxIn(&i.OutPoint, []byte{}))
	}
	return msgtx
}