github.com/fozzysec/SiaPrime@v0.0.0-20190612043147-66c8e8d11fe3/modules/renter/proto/contract_test.go (about) 1 package proto 2 3 import ( 4 "bytes" 5 "path/filepath" 6 "reflect" 7 "testing" 8 9 "SiaPrime/build" 10 "SiaPrime/crypto" 11 "SiaPrime/encoding" 12 "SiaPrime/modules" 13 "SiaPrime/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 c, err := cs.managedInsertContract(initialHeader, initialRoots) 41 if err != nil { 42 t.Fatal(err) 43 } 44 45 // apply an update to the contract, but don't commit it 46 sc := cs.mustAcquire(t, c.ID) 47 revisedHeader := contractHeader{ 48 Transaction: types.Transaction{ 49 FileContractRevisions: []types.FileContractRevision{{ 50 NewRevisionNumber: 2, 51 NewValidProofOutputs: []types.SiacoinOutput{{}, {}}, 52 UnlockConditions: types.UnlockConditions{ 53 PublicKeys: []types.SiaPublicKey{{}, {}}, 54 }, 55 }}, 56 }, 57 StorageSpending: types.NewCurrency64(7), 58 UploadSpending: types.NewCurrency64(17), 59 } 60 revisedRoots := []crypto.Hash{{1}, {2}} 61 fcr := revisedHeader.Transaction.FileContractRevisions[0] 62 newRoot := revisedRoots[1] 63 storageCost := revisedHeader.StorageSpending.Sub(initialHeader.StorageSpending) 64 bandwidthCost := revisedHeader.UploadSpending.Sub(initialHeader.UploadSpending) 65 walTxn, err := sc.recordUploadIntent(fcr, newRoot, storageCost, bandwidthCost) 66 if err != nil { 67 t.Fatal(err) 68 } 69 70 // the state of the contract should match the initial state 71 // NOTE: can't use reflect.DeepEqual for the header because it contains 72 // types.Currency fields 73 merkleRoots, err := sc.merkleRoots.merkleRoots() 74 if err != nil { 75 t.Fatal("failed to get merkle roots", err) 76 } 77 if !bytes.Equal(encoding.Marshal(sc.header), encoding.Marshal(initialHeader)) { 78 t.Fatal("contractHeader should match initial contractHeader") 79 } else if !reflect.DeepEqual(merkleRoots, initialRoots) { 80 t.Fatal("Merkle roots should match initial Merkle roots") 81 } 82 83 // close and reopen the contract set 84 cs.Close() 85 cs, err = NewContractSet(dir, modules.ProdDependencies) 86 if err != nil { 87 t.Fatal(err) 88 } 89 // the uncommitted transaction should be stored in the contract 90 sc = cs.mustAcquire(t, c.ID) 91 if len(sc.unappliedTxns) != 1 { 92 t.Fatal("expected 1 unappliedTxn, got", len(sc.unappliedTxns)) 93 } else if !bytes.Equal(sc.unappliedTxns[0].Updates[0].Instructions, walTxn.Updates[0].Instructions) { 94 t.Fatal("WAL transaction changed") 95 } 96 // the state of the contract should match the initial state 97 merkleRoots, err = sc.merkleRoots.merkleRoots() 98 if err != nil { 99 t.Fatal("failed to get merkle roots:", err) 100 } 101 if !bytes.Equal(encoding.Marshal(sc.header), encoding.Marshal(initialHeader)) { 102 t.Fatal("contractHeader should match initial contractHeader", sc.header, initialHeader) 103 } else if !reflect.DeepEqual(merkleRoots, initialRoots) { 104 t.Fatal("Merkle roots should match initial Merkle roots") 105 } 106 107 // apply the uncommitted transaction 108 err = sc.commitTxns() 109 if err != nil { 110 t.Fatal(err) 111 } 112 // the uncommitted transaction should be gone now 113 if len(sc.unappliedTxns) != 0 { 114 t.Fatal("expected 0 unappliedTxns, got", len(sc.unappliedTxns)) 115 } 116 // the state of the contract should now match the revised state 117 merkleRoots, err = sc.merkleRoots.merkleRoots() 118 if err != nil { 119 t.Fatal("failed to get merkle roots:", err) 120 } 121 if !bytes.Equal(encoding.Marshal(sc.header), encoding.Marshal(revisedHeader)) { 122 t.Fatal("contractHeader should match revised contractHeader", sc.header, revisedHeader) 123 } else if !reflect.DeepEqual(merkleRoots, revisedRoots) { 124 t.Fatal("Merkle roots should match revised Merkle roots") 125 } 126 }