github.com/avahowell/sia@v0.5.1-beta.0.20160524050156-83dcc3d37c94/modules/wallet/transactionbuilder_test.go (about) 1 package wallet 2 3 import ( 4 "testing" 5 6 "github.com/NebulousLabs/Sia/modules" 7 "github.com/NebulousLabs/Sia/types" 8 ) 9 10 // TestViewAdded checks that 'ViewAdded' returns sane-seeming values when 11 // indicating which elements have been added automatically to a transaction 12 // set. 13 func TestViewAdded(t *testing.T) { 14 if testing.Short() { 15 t.SkipNow() 16 } 17 wt, err := createWalletTester("TestViewAdded") 18 if err != nil { 19 t.Fatal(err) 20 } 21 defer wt.closeWt() 22 23 // Mine an extra block to get more outputs - the wallet is going to be 24 // loading two transactions at the same time. 25 _, err = wt.miner.AddBlock() 26 if err != nil { 27 t.Fatal(err) 28 } 29 30 // Create a transaction, add money to it, spend the money in a miner fee 31 // but do not sign the transaction. The format of this test mimics the way 32 // that the host-renter protocol behaves when building a file contract 33 // transaction. 34 b := wt.wallet.StartTransaction() 35 txnFund := types.NewCurrency64(100e9) 36 err = b.FundSiacoins(txnFund) 37 if err != nil { 38 t.Fatal(err) 39 } 40 _ = b.AddMinerFee(txnFund) 41 _ = b.AddSiacoinOutput(types.SiacoinOutput{Value: txnFund}) 42 unfinishedTxn, unfinishedParents := b.View() 43 44 // Create a second builder that extends the first, unsigned transaction. Do 45 // not sign the transaction, but do give the extensions to the original 46 // builder. 47 b2 := wt.wallet.RegisterTransaction(unfinishedTxn, unfinishedParents) 48 err = b2.FundSiacoins(txnFund) 49 if err != nil { 50 t.Fatal(err) 51 } 52 unfinishedTxn2, unfinishedParents2 := b2.View() 53 newParentIndices, newInputIndices, _, _ := b2.ViewAdded() 54 55 // Add the new elements from b2 to b and sign the transaction, fetching the 56 // signature for b. 57 for _, parentIndex := range newParentIndices { 58 b.AddParents([]types.Transaction{unfinishedParents2[parentIndex]}) 59 } 60 for _, inputIndex := range newInputIndices { 61 b.AddSiacoinInput(unfinishedTxn2.SiacoinInputs[inputIndex]) 62 } 63 // Signing with WholeTransaction=true makes the transaction more brittle to 64 // construction mistakes, meaning that an error is more likely to turn up. 65 set1, err := b.Sign(true) 66 if err != nil { 67 t.Fatal(err) 68 } 69 if set1[len(set1)-1].ID() == unfinishedTxn.ID() { 70 t.Error("seems like there's memory sharing happening between txn calls") 71 } 72 // Set1 should be missing some signatures. 73 err = wt.tpool.AcceptTransactionSet(set1) 74 if err == nil { 75 t.Fatal(err) 76 } 77 unfinishedTxn3, _ := b.View() 78 // Only the new signatures are needed because the previous call to 'View' 79 // included everything else. 80 _, _, _, newTxnSignaturesIndices := b.ViewAdded() 81 82 // Add the new signatures to b2, and then sign b2's inputs. The resulting 83 // set from b2 should be valid. 84 for _, sigIndex := range newTxnSignaturesIndices { 85 b2.AddTransactionSignature(unfinishedTxn3.TransactionSignatures[sigIndex]) 86 } 87 set2, err := b2.Sign(true) 88 err = wt.tpool.AcceptTransactionSet(set2) 89 if err != nil { 90 t.Fatal(err) 91 } 92 finishedTxn, _ := b2.View() 93 _, _, _, newTxnSignaturesIndices3 := b2.ViewAdded() 94 95 // Add the new signatures from b2 to the b1 transaction, which should 96 // complete the transaction and create a transaction set in 'b' that is 97 // identical to the transaction set that is in b2. 98 for _, sigIndex := range newTxnSignaturesIndices3 { 99 b.AddTransactionSignature(finishedTxn.TransactionSignatures[sigIndex]) 100 } 101 set3Txn, set3Parents := b.View() 102 err = wt.tpool.AcceptTransactionSet(append(set3Parents, set3Txn)) 103 if err != modules.ErrDuplicateTransactionSet { 104 t.Fatal(err) 105 } 106 } 107 108 // TestDoubleSignError checks that an error is returned if there is a problem 109 // when trying to call 'Sign' on a transaction twice. 110 func TestDoubleSignError(t *testing.T) { 111 if testing.Short() { 112 t.SkipNow() 113 } 114 wt, err := createWalletTester("TestDoubleSignError") 115 if err != nil { 116 t.Fatal(err) 117 } 118 defer wt.closeWt() 119 120 // Create a transaction, add money to it, and then call sign twice. 121 b := wt.wallet.StartTransaction() 122 txnFund := types.NewCurrency64(100e9) 123 err = b.FundSiacoins(txnFund) 124 if err != nil { 125 t.Fatal(err) 126 } 127 _ = b.AddMinerFee(txnFund) 128 txnSet, err := b.Sign(true) 129 if err != nil { 130 t.Fatal(err) 131 } 132 txnSet2, err := b.Sign(true) 133 if err != errBuilderAlreadySigned { 134 t.Error("the wrong error is being returned after a double call to sign") 135 } 136 if err != nil && txnSet2 != nil { 137 t.Error("errored call to sign did not return a nil txn set") 138 } 139 err = wt.tpool.AcceptTransactionSet(txnSet) 140 if err != nil { 141 t.Fatal(err) 142 } 143 }