gitlab.com/SiaPrime/SiaPrime@v1.4.1/modules/consensus/applytransaction.go (about)

     1  package consensus
     2  
     3  // applytransaction.go handles applying a transaction to the consensus set.
     4  // There is an assumption that the transaction has already been verified.
     5  
     6  import (
     7  	bolt "github.com/coreos/bbolt"
     8  	"gitlab.com/SiaPrime/SiaPrime/build"
     9  	"gitlab.com/SiaPrime/SiaPrime/modules"
    10  	"gitlab.com/SiaPrime/SiaPrime/types"
    11  )
    12  
    13  // applySiacoinInputs takes all of the siacoin inputs in a transaction and
    14  // applies them to the state, updating the diffs in the processed block.
    15  func applySiacoinInputs(tx *bolt.Tx, pb *processedBlock, t types.Transaction) {
    16  	// Remove all siacoin inputs from the unspent siacoin outputs list.
    17  	for _, sci := range t.SiacoinInputs {
    18  		sco, err := getSiacoinOutput(tx, sci.ParentID)
    19  		if build.DEBUG && err != nil {
    20  			panic(err)
    21  		}
    22  		scod := modules.SiacoinOutputDiff{
    23  			Direction:     modules.DiffRevert,
    24  			ID:            sci.ParentID,
    25  			SiacoinOutput: sco,
    26  		}
    27  		pb.SiacoinOutputDiffs = append(pb.SiacoinOutputDiffs, scod)
    28  		commitSiacoinOutputDiff(tx, scod, modules.DiffApply)
    29  	}
    30  }
    31  
    32  // applySiacoinOutputs takes all of the siacoin outputs in a transaction and
    33  // applies them to the state, updating the diffs in the processed block.
    34  func applySiacoinOutputs(tx *bolt.Tx, pb *processedBlock, t types.Transaction) {
    35  	// Add all siacoin outputs to the unspent siacoin outputs list.
    36  	for i, sco := range t.SiacoinOutputs {
    37  		scoid := t.SiacoinOutputID(uint64(i))
    38  		scod := modules.SiacoinOutputDiff{
    39  			Direction:     modules.DiffApply,
    40  			ID:            scoid,
    41  			SiacoinOutput: sco,
    42  		}
    43  		pb.SiacoinOutputDiffs = append(pb.SiacoinOutputDiffs, scod)
    44  		commitSiacoinOutputDiff(tx, scod, modules.DiffApply)
    45  	}
    46  }
    47  
    48  // applyFileContracts iterates through all of the file contracts in a
    49  // transaction and applies them to the state, updating the diffs in the proccesed
    50  // block.
    51  func applyFileContracts(tx *bolt.Tx, pb *processedBlock, t types.Transaction) {
    52  	for i, fc := range t.FileContracts {
    53  		fcid := t.FileContractID(uint64(i))
    54  		fcd := modules.FileContractDiff{
    55  			Direction:    modules.DiffApply,
    56  			ID:           fcid,
    57  			FileContract: fc,
    58  		}
    59  		pb.FileContractDiffs = append(pb.FileContractDiffs, fcd)
    60  		commitFileContractDiff(tx, fcd, modules.DiffApply)
    61  
    62  		// Get the portion of the contract that goes into the siafund pool and
    63  		// add it to the siafund pool.
    64  		sfp := getSiafundPool(tx)
    65  		sfpd := modules.SiafundPoolDiff{
    66  			Direction: modules.DiffApply,
    67  			Previous:  sfp,
    68  			Adjusted:  sfp.Add(types.Tax(blockHeight(tx), fc.Payout)),
    69  		}
    70  		pb.SiafundPoolDiffs = append(pb.SiafundPoolDiffs, sfpd)
    71  		commitSiafundPoolDiff(tx, sfpd, modules.DiffApply)
    72  	}
    73  }
    74  
    75  // applyTxFileContractRevisions iterates through all of the file contract
    76  // revisions in a transaction and applies them to the state, updating the diffs
    77  // in the processed block.
    78  func applyFileContractRevisions(tx *bolt.Tx, pb *processedBlock, t types.Transaction) {
    79  	for _, fcr := range t.FileContractRevisions {
    80  		fc, err := getFileContract(tx, fcr.ParentID)
    81  		if build.DEBUG && err != nil {
    82  			panic(err)
    83  		}
    84  
    85  		// Add the diff to delete the old file contract.
    86  		fcd := modules.FileContractDiff{
    87  			Direction:    modules.DiffRevert,
    88  			ID:           fcr.ParentID,
    89  			FileContract: fc,
    90  		}
    91  		pb.FileContractDiffs = append(pb.FileContractDiffs, fcd)
    92  		commitFileContractDiff(tx, fcd, modules.DiffApply)
    93  
    94  		// Add the diff to add the revised file contract.
    95  		newFC := types.FileContract{
    96  			FileSize:           fcr.NewFileSize,
    97  			FileMerkleRoot:     fcr.NewFileMerkleRoot,
    98  			WindowStart:        fcr.NewWindowStart,
    99  			WindowEnd:          fcr.NewWindowEnd,
   100  			Payout:             fc.Payout,
   101  			ValidProofOutputs:  fcr.NewValidProofOutputs,
   102  			MissedProofOutputs: fcr.NewMissedProofOutputs,
   103  			UnlockHash:         fcr.NewUnlockHash,
   104  			RevisionNumber:     fcr.NewRevisionNumber,
   105  		}
   106  		fcd = modules.FileContractDiff{
   107  			Direction:    modules.DiffApply,
   108  			ID:           fcr.ParentID,
   109  			FileContract: newFC,
   110  		}
   111  		pb.FileContractDiffs = append(pb.FileContractDiffs, fcd)
   112  		commitFileContractDiff(tx, fcd, modules.DiffApply)
   113  	}
   114  }
   115  
   116  // applyTxStorageProofs iterates through all of the storage proofs in a
   117  // transaction and applies them to the state, updating the diffs in the processed
   118  // block.
   119  func applyStorageProofs(tx *bolt.Tx, pb *processedBlock, t types.Transaction) {
   120  	for _, sp := range t.StorageProofs {
   121  		fc, err := getFileContract(tx, sp.ParentID)
   122  		if build.DEBUG && err != nil {
   123  			panic(err)
   124  		}
   125  
   126  		// Add all of the outputs in the ValidProofOutputs of the contract.
   127  		for i, vpo := range fc.ValidProofOutputs {
   128  			spoid := sp.ParentID.StorageProofOutputID(types.ProofValid, uint64(i))
   129  			dscod := modules.DelayedSiacoinOutputDiff{
   130  				Direction:      modules.DiffApply,
   131  				ID:             spoid,
   132  				SiacoinOutput:  vpo,
   133  				MaturityHeight: pb.Height + types.MaturityDelay,
   134  			}
   135  			pb.DelayedSiacoinOutputDiffs = append(pb.DelayedSiacoinOutputDiffs, dscod)
   136  			commitDelayedSiacoinOutputDiff(tx, dscod, modules.DiffApply)
   137  		}
   138  
   139  		fcd := modules.FileContractDiff{
   140  			Direction:    modules.DiffRevert,
   141  			ID:           sp.ParentID,
   142  			FileContract: fc,
   143  		}
   144  		pb.FileContractDiffs = append(pb.FileContractDiffs, fcd)
   145  		commitFileContractDiff(tx, fcd, modules.DiffApply)
   146  	}
   147  }
   148  
   149  // applyTxSiafundInputs takes all of the siafund inputs in a transaction and
   150  // applies them to the state, updating the diffs in the processed block.
   151  func applySiafundInputs(tx *bolt.Tx, pb *processedBlock, t types.Transaction) {
   152  	for _, sfi := range t.SiafundInputs {
   153  		// Calculate the volume of siacoins to put in the claim output.
   154  		sfo, err := getSiafundOutput(tx, sfi.ParentID)
   155  		if build.DEBUG && err != nil {
   156  			panic(err)
   157  		}
   158  		claimPortion := getSiafundPool(tx).Sub(sfo.ClaimStart).Div(types.SiafundCount).Mul(sfo.Value)
   159  
   160  		// Add the claim output to the delayed set of outputs.
   161  		sco := types.SiacoinOutput{
   162  			Value:      claimPortion,
   163  			UnlockHash: sfi.ClaimUnlockHash,
   164  		}
   165  		sfoid := sfi.ParentID.SiaClaimOutputID()
   166  		dscod := modules.DelayedSiacoinOutputDiff{
   167  			Direction:      modules.DiffApply,
   168  			ID:             sfoid,
   169  			SiacoinOutput:  sco,
   170  			MaturityHeight: pb.Height + types.MaturityDelay,
   171  		}
   172  		pb.DelayedSiacoinOutputDiffs = append(pb.DelayedSiacoinOutputDiffs, dscod)
   173  		commitDelayedSiacoinOutputDiff(tx, dscod, modules.DiffApply)
   174  
   175  		// Create the siafund output diff and remove the output from the
   176  		// consensus set.
   177  		sfod := modules.SiafundOutputDiff{
   178  			Direction:     modules.DiffRevert,
   179  			ID:            sfi.ParentID,
   180  			SiafundOutput: sfo,
   181  		}
   182  		pb.SiafundOutputDiffs = append(pb.SiafundOutputDiffs, sfod)
   183  		commitSiafundOutputDiff(tx, sfod, modules.DiffApply)
   184  	}
   185  }
   186  
   187  // applySiafundOutput applies a siafund output to the consensus set.
   188  func applySiafundOutputs(tx *bolt.Tx, pb *processedBlock, t types.Transaction) {
   189  	for i, sfo := range t.SiafundOutputs {
   190  		sfoid := t.SiafundOutputID(uint64(i))
   191  		sfo.ClaimStart = getSiafundPool(tx)
   192  		sfod := modules.SiafundOutputDiff{
   193  			Direction:     modules.DiffApply,
   194  			ID:            sfoid,
   195  			SiafundOutput: sfo,
   196  		}
   197  		pb.SiafundOutputDiffs = append(pb.SiafundOutputDiffs, sfod)
   198  		commitSiafundOutputDiff(tx, sfod, modules.DiffApply)
   199  	}
   200  }
   201  
   202  // applyTransaction applies the contents of a transaction to the ConsensusSet.
   203  // This produces a set of diffs, which are stored in the blockNode containing
   204  // the transaction. No verification is done by this function.
   205  func applyTransaction(tx *bolt.Tx, pb *processedBlock, t types.Transaction) {
   206  	applySiacoinInputs(tx, pb, t)
   207  	applySiacoinOutputs(tx, pb, t)
   208  	applyFileContracts(tx, pb, t)
   209  	applyFileContractRevisions(tx, pb, t)
   210  	applyStorageProofs(tx, pb, t)
   211  	applySiafundInputs(tx, pb, t)
   212  	applySiafundOutputs(tx, pb, t)
   213  }