gitlab.com/SkynetLabs/skyd@v1.6.9/skymodules/renter/proto/negotiate_test.go (about) 1 package proto 2 3 import ( 4 "net" 5 "testing" 6 7 "gitlab.com/NebulousLabs/errors" 8 9 "gitlab.com/NebulousLabs/encoding" 10 "go.sia.tech/siad/crypto" 11 "go.sia.tech/siad/modules" 12 "go.sia.tech/siad/types" 13 ) 14 15 // TestNegotiateRevisionStopResponse tests that when the host sends 16 // StopResponse, the renter continues processing the revision instead of 17 // immediately terminating. 18 func TestNegotiateRevisionStopResponse(t *testing.T) { 19 // simulate a renter-host connection 20 rConn, hConn := net.Pipe() 21 22 // handle the host's half of the pipe 23 go func(c net.Conn) { 24 defer func() { 25 if err := c.Close(); err != nil { 26 t.Error(err) 27 } 28 }() 29 // read revision 30 encoding.ReadObject(hConn, new(types.FileContractRevision), 1<<22) 31 // write acceptance 32 modules.WriteNegotiationAcceptance(hConn) 33 // read txn signature 34 encoding.ReadObject(hConn, new(types.TransactionSignature), 1<<22) 35 // write StopResponse 36 modules.WriteNegotiationStop(hConn) 37 // write txn signature 38 encoding.WriteObject(hConn, types.TransactionSignature{}) 39 }(hConn) 40 41 // since the host wrote StopResponse, we should proceed to validating the 42 // transaction. This will return a known error because we are supplying an 43 // empty revision. 44 _, err := negotiateRevision(rConn, types.FileContractRevision{}, crypto.SecretKey{}, 0) 45 if !errors.Contains(err, types.ErrFileContractWindowStartViolation) { 46 t.Fatalf("expected %q, got \"%v\"", types.ErrFileContractWindowStartViolation, err) 47 } 48 rConn.Close() 49 50 // same as above, but send an error instead of StopResponse. The error 51 // should be returned by negotiateRevision immediately (if it is not, we 52 // should expect to see a transaction validation error instead). 53 rConn, hConn = net.Pipe() 54 go func(c net.Conn) { 55 defer func() { 56 if err := c.Close(); err != nil { 57 t.Error(err) 58 } 59 }() 60 encoding.ReadObject(hConn, new(types.FileContractRevision), 1<<22) 61 modules.WriteNegotiationAcceptance(hConn) 62 encoding.ReadObject(hConn, new(types.TransactionSignature), 1<<22) 63 // write a sentinel error 64 modules.WriteNegotiationRejection(hConn, errors.New("sentinel")) 65 encoding.WriteObject(hConn, types.TransactionSignature{}) 66 }(hConn) 67 expectedErr := "host did not accept transaction signature: sentinel" 68 _, err = negotiateRevision(rConn, types.FileContractRevision{}, crypto.SecretKey{}, 0) 69 if err == nil || err.Error() != expectedErr { 70 t.Fatalf("expected %q, got \"%v\"", expectedErr, err) 71 } 72 rConn.Close() 73 } 74 75 // TestNewRevisionFundChecks checks that underflow errors1 76 func TestNewRevisionFundChecks(t *testing.T) { 77 // helper func for revisions 78 revWithValues := func(renterFunds, hostCollateralAvailable uint64) types.FileContractRevision { 79 validOuts := make([]types.SiacoinOutput, 2) 80 missedOuts := make([]types.SiacoinOutput, 3) 81 82 // funds remaining for renter, and payout to host. 83 validOuts[0].Value = types.NewCurrency64(renterFunds) 84 validOuts[1].Value = types.NewCurrency64(0) 85 86 // Void payout from renter 87 missedOuts[0].Value = types.NewCurrency64(renterFunds) 88 89 // Collateral 90 missedOuts[1].Value = types.NewCurrency64(hostCollateralAvailable) 91 92 return types.FileContractRevision{ 93 NewValidProofOutputs: validOuts, 94 NewMissedProofOutputs: missedOuts, 95 } 96 } 97 98 // Cost is less than renter funds should be okay. 99 _, err := newDownloadRevision(revWithValues(100, 0), types.NewCurrency64(99)) 100 if err != nil { 101 t.Fatal(err) 102 } 103 // Cost equal to renter funds should be okay. 104 _, err = newDownloadRevision(revWithValues(100, 0), types.NewCurrency64(100)) 105 if err != nil { 106 t.Fatal(err) 107 } 108 // Cost is more than renter funds should fail. 109 _, err = newDownloadRevision(revWithValues(100, 0), types.NewCurrency64(101)) 110 if !errors.Contains(err, types.ErrRevisionCostTooHigh) { 111 t.Fatal(err) 112 } 113 114 // Collateral checks (in each, renter funds <= cost) 115 // 116 // Cost less than collateral should be okay. 117 _, err = newUploadRevision(revWithValues(100, 100), crypto.Hash{}, types.NewCurrency64(99), types.NewCurrency64(99)) 118 if err != nil { 119 t.Fatal(err) 120 } 121 // Using up all collateral should be okay. 122 _, err = newUploadRevision(revWithValues(100, 100), crypto.Hash{}, types.NewCurrency64(99), types.NewCurrency64(100)) 123 if err != nil { 124 t.Fatal(err) 125 } 126 // Not enough collateral should cause an error. 127 _, err = newUploadRevision(revWithValues(100, 100), crypto.Hash{}, types.NewCurrency64(99), types.NewCurrency64(100)) 128 if errors.Contains(err, types.ErrRevisionCollateralTooLow) { 129 t.Fatal(err) 130 } 131 }