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 }