// TestValidFileContractRevisions probes the validFileContractRevisions method // of the consensus set. func TestValidFileContractRevisions(t *testing.T) { if testing.Short() { t.SkipNow() } t.Parallel() cst, err := createConsensusSetTester("TestValidFileContractRevisions") if err != nil { t.Fatal(err) } defer cst.Close() // Grab an address + unlock conditions for the transaction. unlockConditions, err := cst.wallet.NextAddress() if err != nil { t.Fatal(err) } // Create a file contract for which a storage proof can be created. var fcid types.FileContractID fcid[0] = 12 simFile := make([]byte, 64*1024) rand.Read(simFile) root := crypto.MerkleRoot(simFile) fc := types.FileContract{ FileSize: 64 * 1024, FileMerkleRoot: root, WindowStart: 102, WindowEnd: 1200, Payout: types.NewCurrency64(1), UnlockHash: unlockConditions.UnlockHash(), RevisionNumber: 1, } cst.cs.dbAddFileContract(fcid, fc) // Try a working file contract revision. txn := types.Transaction{ FileContractRevisions: []types.FileContractRevision{ { ParentID: fcid, UnlockConditions: unlockConditions, NewRevisionNumber: 2, }, }, } err = cst.cs.dbValidFileContractRevisions(txn) if err != nil { t.Error(err) } // Try a transaction with an insufficient revision number. txn = types.Transaction{ FileContractRevisions: []types.FileContractRevision{ { ParentID: fcid, UnlockConditions: unlockConditions, NewRevisionNumber: 1, }, }, } err = cst.cs.dbValidFileContractRevisions(txn) if err != errLowRevisionNumber { t.Error(err) } txn = types.Transaction{ FileContractRevisions: []types.FileContractRevision{ { ParentID: fcid, UnlockConditions: unlockConditions, NewRevisionNumber: 0, }, }, } err = cst.cs.dbValidFileContractRevisions(txn) if err != errLowRevisionNumber { t.Error(err) } // Submit a file contract revision pointing to an invalid parent. txn.FileContractRevisions[0].ParentID[0]-- err = cst.cs.dbValidFileContractRevisions(txn) if err != errNilItem { t.Error(err) } txn.FileContractRevisions[0].ParentID[0]++ // Submit a file contract revision for a file contract whose window has // already opened. fc, err = cst.cs.dbGetFileContract(fcid) if err != nil { t.Fatal(err) } fc.WindowStart = 0 cst.cs.dbRemoveFileContract(fcid) cst.cs.dbAddFileContract(fcid, fc) txn.FileContractRevisions[0].NewRevisionNumber = 3 err = cst.cs.dbValidFileContractRevisions(txn) if err != errLateRevision { t.Error(err) } // Submit a file contract revision with incorrect unlock conditions. fc.WindowStart = 100 cst.cs.dbRemoveFileContract(fcid) cst.cs.dbAddFileContract(fcid, fc) txn.FileContractRevisions[0].UnlockConditions.Timelock++ err = cst.cs.dbValidFileContractRevisions(txn) if err != errWrongUnlockConditions { t.Error(err) } txn.FileContractRevisions[0].UnlockConditions.Timelock-- // Submit file contract revisions for file contracts with altered payouts. txn.FileContractRevisions[0].NewValidProofOutputs = []types.SiacoinOutput{{ Value: types.NewCurrency64(1), }} txn.FileContractRevisions[0].NewMissedProofOutputs = []types.SiacoinOutput{{ Value: types.NewCurrency64(1), }} err = cst.cs.dbValidFileContractRevisions(txn) if err != errAlteredRevisionPayouts { t.Error(err) } txn.FileContractRevisions[0].NewValidProofOutputs = nil err = cst.cs.dbValidFileContractRevisions(txn) if err != errAlteredRevisionPayouts { t.Error(err) } txn.FileContractRevisions[0].NewValidProofOutputs = []types.SiacoinOutput{{ Value: types.NewCurrency64(1), }} txn.FileContractRevisions[0].NewMissedProofOutputs = nil err = cst.cs.dbValidFileContractRevisions(txn) if err != errAlteredRevisionPayouts { t.Error(err) } }