Exemplo n.º 1
0
// 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)
	}
}