func TestConcurrentBuilders(t *testing.T) {
	if testing.Short() {
		t.SkipNow()
	}
	wt, err := createWalletTester(t.Name(), modules.ProdDependencies)
	if err != nil {
		t.Fatal(err)
	}
	defer wt.closeWt()
	for i := 0; i < 5; i++ {
		_, err := wt.miner.AddBlock()
		if err != nil {
			t.Fatal(err)
		}
	}
	startingSCConfirmed, _, _, err := wt.wallet.ConfirmedBalance()
	if err != nil {
		t.Fatal(err)
	}
	startingOutgoing, startingIncoming, err := wt.wallet.UnconfirmedBalance()
	if err != nil {
		t.Fatal(err)
	}
	if !startingOutgoing.IsZero() {
		t.Fatal(startingOutgoing)
	}
	if !startingIncoming.IsZero() {
		t.Fatal(startingIncoming)
	}
	builder1, err := wt.wallet.StartTransaction()
	if err != nil {
		t.Fatal(err)
	}
	builder2, err := wt.wallet.StartTransaction()
	if err != nil {
		t.Fatal(err)
	}
	funding := types.NewCurrency64(10e3).Mul(types.SiacoinPrecision)
	err = builder1.FundSiacoins(funding)
	if err != nil {
		t.Fatal(err)
	}
	err = builder2.FundSiacoins(funding)
	if err != nil {
		t.Fatal(err)
	}
	fundedSCConfirmed, _, _, err := wt.wallet.ConfirmedBalance()
	if err != nil {
		t.Fatal(err)
	}
	if !startingSCConfirmed.Equals(fundedSCConfirmed) {
		t.Fatal("confirmed siacoin balance changed when no blocks have been mined", startingSCConfirmed, fundedSCConfirmed)
	}
	builder1.AddMinerFee(types.NewCurrency64(25).Mul(types.SiacoinPrecision))
	builder2.AddMinerFee(types.NewCurrency64(25).Mul(types.SiacoinPrecision))
	output := types.SiacoinOutput{Value: types.NewCurrency64(9975).Mul(types.SiacoinPrecision)}
	builder1.AddSiacoinOutput(output)
	builder2.AddSiacoinOutput(output)
	tset1, err := builder1.Sign(true)
	if err != nil {
		t.Fatal(err)
	}
	tset2, err := builder2.Sign(true)
	if err != nil {
		t.Fatal(err)
	}
	err = wt.tpool.AcceptTransactionSet(tset1)
	if err != nil {
		t.Fatal(err)
	}
	err = wt.tpool.AcceptTransactionSet(tset2)
	if err != nil {
		t.Fatal(err)
	}
	_, err = wt.miner.AddBlock()
	if err != nil {
		t.Fatal(err)
	}
}
TestConcurrentBuilders checks that multiple transaction builders can safely
be opened at the same time, and that they will make valid transactions when
building concurrently.
package wallet
import (
	"sync"
	"testing"
	"github.com/NebulousLabs/Sia/modules"
	"github.com/NebulousLabs/Sia/types"
)
func (wt *walletTester) addBlockNoPayout() error {
	block, target, err := wt.miner.BlockForWork()
	if err != nil {
		return err
	}
	for i := range block.MinerPayouts {
		block.MinerPayouts[i].UnlockHash = types.UnlockHash{}
	}
	solvedBlock, _ := wt.miner.SolveBlock(block, target)
	err = wt.cs.AcceptBlock(solvedBlock)
	if err != nil {
		return err
	}
	return nil
}
func TestViewAdded(t *testing.T) {
	if testing.Short() {
		t.SkipNow()
	}
	wt, err := createWalletTester(t.Name(), modules.ProdDependencies)
	if err != nil {
		t.Fatal(err)
	}
	defer wt.closeWt()
	_, err = wt.miner.AddBlock()
	if err != nil {
		t.Fatal(err)
	}
	b, err := wt.wallet.StartTransaction()
	if err != nil {
		t.Fatal(err)
	}
	txnFund := types.NewCurrency64(100e9)
	err = b.FundSiacoins(txnFund)
	if err != nil {
		t.Fatal(err)
	}
	_ = b.AddMinerFee(txnFund)
	_ = b.AddSiacoinOutput(types.SiacoinOutput{Value: txnFund})
	unfinishedTxn, unfinishedParents := b.View()
	b2, err := wt.wallet.RegisterTransaction(unfinishedTxn, unfinishedParents)
	if err != nil {
		t.Fatal(err)
	}
	err = b2.FundSiacoins(txnFund)
	if err != nil {
		t.Fatal(err)
	}
	unfinishedTxn2, unfinishedParents2 := b2.View()
	newParentIndices, newInputIndices, _, _ := b2.ViewAdded()
	for _, parentIndex := range newParentIndices {
		b.AddParents([]types.Transaction{unfinishedParents2[parentIndex]})
	}
	for _, inputIndex := range newInputIndices {
		b.AddSiacoinInput(unfinishedTxn2.SiacoinInputs[inputIndex])
	}
	set1, err := b.Sign(true)
	if err != nil {
		t.Fatal(err)
	}
	if set1[len(set1)-1].ID() == unfinishedTxn.ID() {
		t.Error("seems like there's memory sharing happening between txn calls")
	}
	err = wt.tpool.AcceptTransactionSet(set1)
	if err == nil {
		t.Fatal(err)
	}
	unfinishedTxn3, _ := b.View()
	_, _, _, newTxnSignaturesIndices := b.ViewAdded()
	for _, sigIndex := range newTxnSignaturesIndices {
		b2.AddTransactionSignature(unfinishedTxn3.TransactionSignatures[sigIndex])
	}
	set2, err := b2.Sign(true)
	if err != nil {
		t.Fatal(err)
	}
	err = wt.tpool.AcceptTransactionSet(set2)
	if err != nil {
		t.Fatal(err)
	}
	finishedTxn, _ := b2.View()
	_, _, _, newTxnSignaturesIndices3 := b2.ViewAdded()
	for _, sigIndex := range newTxnSignaturesIndices3 {
		b.AddTransactionSignature(finishedTxn.TransactionSignatures[sigIndex])
	}
	set3Txn, set3Parents := b.View()
	err = wt.tpool.AcceptTransactionSet(append(set3Parents, set3Txn))
	if err != modules.ErrDuplicateTransactionSet {
		t.Fatal(err)
	}
}
func TestDoubleSignError(t *testing.T) {
	if testing.Short() {
		t.SkipNow()
	}
	wt, err := createWalletTester(t.Name(), modules.ProdDependencies)
	if err != nil {
		t.Fatal(err)
	}
	defer wt.closeWt()
	b, err := wt.wallet.StartTransaction()
	if err != nil {
		t.Fatal(err)
	}
	txnFund := types.NewCurrency64(100e9)
	err = b.FundSiacoins(txnFund)
	if err != nil {
		t.Fatal(err)
	}
	_ = b.AddMinerFee(txnFund)
	txnSet, err := b.Sign(true)
	if err != nil {
		t.Fatal(err)
	}
	txnSet2, err := b.Sign(true)
	if err != errBuilderAlreadySigned {
		t.Error("the wrong error is being returned after a double call to sign")
	}
	if err != nil && txnSet2 != nil {
		t.Error("errored call to sign did not return a nil txn set")
	}
	err = wt.tpool.AcceptTransactionSet(txnSet)
	if err != nil {
		t.Fatal(err)
	}
}