github.com/Synthesix/Sia@v1.3.3-0.20180413141344-f863baeed3ca/modules/renter/proto/contract_test.go (about) 1 package proto 2 3 import ( 4 "bytes" 5 "path/filepath" 6 "reflect" 7 "testing" 8 9 "github.com/Synthesix/Sia/build" 10 "github.com/Synthesix/Sia/crypto" 11 "github.com/Synthesix/Sia/encoding" 12 "github.com/Synthesix/Sia/modules" 13 "github.com/Synthesix/Sia/types" 14 ) 15 16 // TestContractUncommittedTxn tests that if a contract revision is left in an 17 // uncommitted state, either version of the contract can be recovered. 18 func TestContractUncommittedTxn(t *testing.T) { 19 if testing.Short() { 20 t.SkipNow() 21 } 22 // create contract set with one contract 23 dir := build.TempDir(filepath.Join("proto", t.Name())) 24 cs, err := NewContractSet(dir, modules.ProdDependencies) 25 if err != nil { 26 t.Fatal(err) 27 } 28 initialHeader := contractHeader{ 29 Transaction: types.Transaction{ 30 FileContractRevisions: []types.FileContractRevision{{ 31 NewRevisionNumber: 1, 32 NewValidProofOutputs: []types.SiacoinOutput{{}, {}}, 33 UnlockConditions: types.UnlockConditions{ 34 PublicKeys: []types.SiaPublicKey{{}, {}}, 35 }, 36 }}, 37 }, 38 } 39 initialRoots := []crypto.Hash{{1}} 40 id := initialHeader.ID() 41 _, err = cs.managedInsertContract(initialHeader, initialRoots) 42 if err != nil { 43 t.Fatal(err) 44 } 45 46 // apply an update to the contract, but don't commit it 47 sc := cs.mustAcquire(t, id) 48 revisedHeader := contractHeader{ 49 Transaction: types.Transaction{ 50 FileContractRevisions: []types.FileContractRevision{{ 51 NewRevisionNumber: 2, 52 NewValidProofOutputs: []types.SiacoinOutput{{}, {}}, 53 UnlockConditions: types.UnlockConditions{ 54 PublicKeys: []types.SiaPublicKey{{}, {}}, 55 }, 56 }}, 57 }, 58 StorageSpending: types.NewCurrency64(7), 59 UploadSpending: types.NewCurrency64(17), 60 } 61 revisedRoots := []crypto.Hash{{1}, {2}} 62 fcr := revisedHeader.Transaction.FileContractRevisions[0] 63 newRoot := revisedRoots[1] 64 storageCost := revisedHeader.StorageSpending.Sub(initialHeader.StorageSpending) 65 bandwidthCost := revisedHeader.UploadSpending.Sub(initialHeader.UploadSpending) 66 walTxn, err := sc.recordUploadIntent(fcr, newRoot, storageCost, bandwidthCost) 67 if err != nil { 68 t.Fatal(err) 69 } 70 71 // the state of the contract should match the initial state 72 // NOTE: can't use reflect.DeepEqual for the header because it contains 73 // types.Currency fields 74 if !bytes.Equal(encoding.Marshal(sc.header), encoding.Marshal(initialHeader)) { 75 t.Fatal("contractHeader should match initial contractHeader") 76 } else if !reflect.DeepEqual(sc.merkleRoots, initialRoots) { 77 t.Fatal("Merkle roots should match initial Merkle roots") 78 } 79 80 // close and reopen the contract set 81 cs.Close() 82 cs, err = NewContractSet(dir, modules.ProdDependencies) 83 if err != nil { 84 t.Fatal(err) 85 } 86 // the uncommitted transaction should be stored in the contract 87 sc = cs.mustAcquire(t, id) 88 if len(sc.unappliedTxns) != 1 { 89 t.Fatal("expected 1 unappliedTxn, got", len(sc.unappliedTxns)) 90 } else if !bytes.Equal(sc.unappliedTxns[0].Updates[0].Instructions, walTxn.Updates[0].Instructions) { 91 t.Fatal("WAL transaction changed") 92 } 93 // the state of the contract should match the initial state 94 if !bytes.Equal(encoding.Marshal(sc.header), encoding.Marshal(initialHeader)) { 95 t.Fatal("contractHeader should match initial contractHeader", sc.header, initialHeader) 96 } else if !reflect.DeepEqual(sc.merkleRoots, initialRoots) { 97 t.Fatal("Merkle roots should match initial Merkle roots") 98 } 99 100 // apply the uncommitted transaction 101 err = sc.commitTxns() 102 if err != nil { 103 t.Fatal(err) 104 } 105 // the uncommitted transaction should be gone now 106 if len(sc.unappliedTxns) != 0 { 107 t.Fatal("expected 0 unappliedTxns, got", len(sc.unappliedTxns)) 108 } 109 // the state of the contract should now match the revised state 110 if !bytes.Equal(encoding.Marshal(sc.header), encoding.Marshal(revisedHeader)) { 111 t.Fatal("contractHeader should match revised contractHeader", sc.header, revisedHeader) 112 } else if !reflect.DeepEqual(sc.merkleRoots, revisedRoots) { 113 t.Fatal("Merkle roots should match revised Merkle roots") 114 } 115 }