github.com/fozzysec/SiaPrime@v0.0.0-20190612043147-66c8e8d11fe3/modules/consensus.go (about) 1 package modules 2 3 import ( 4 "errors" 5 6 "SiaPrime/crypto" 7 "SiaPrime/persist" 8 "SiaPrime/types" 9 ) 10 11 const ( 12 // ConsensusDir is the name of the directory used for all of the consensus 13 // persistence files. 14 ConsensusDir = "consensus" 15 16 // DiffApply indicates that a diff is being applied to the consensus set. 17 DiffApply DiffDirection = true 18 19 // DiffRevert indicates that a diff is being reverted from the consensus 20 // set. 21 DiffRevert DiffDirection = false 22 ) 23 24 var ( 25 // ConsensusChangeBeginning is a special consensus change id that tells the 26 // consensus set to provide all consensus changes starting from the very 27 // first diff, which includes the genesis block diff. 28 ConsensusChangeBeginning = ConsensusChangeID{} 29 30 // ConsensusChangeRecent is a special consensus change id that tells the 31 // consensus set to provide the most recent consensus change, instead of 32 // starting from a specific value (which may not be known to the caller). 33 ConsensusChangeRecent = ConsensusChangeID{1} 34 35 // ErrBlockKnown is an error indicating that a block is already in the 36 // database. 37 ErrBlockKnown = errors.New("block already present in database") 38 39 // ErrBlockUnsolved indicates that a block did not meet the required POW 40 // target. 41 ErrBlockUnsolved = errors.New("block does not meet target") 42 43 // ErrInvalidConsensusChangeID indicates that ConsensusSetPersistSubscribe 44 // was called with a consensus change id that is not recognized. Most 45 // commonly, this means that the consensus set was deleted or replaced and 46 // now the module attempting the subscription has desynchronized. This error 47 // should be handled by the module, and not reported to the user. 48 ErrInvalidConsensusChangeID = errors.New("consensus subscription has invalid id - files are inconsistent") 49 50 // ErrNonExtendingBlock indicates that a block is valid but does not result 51 // in a fork that is the heaviest known fork - the consensus set has not 52 // changed as a result of seeing the block. 53 ErrNonExtendingBlock = errors.New("block does not extend the longest fork") 54 ) 55 56 type ( 57 // ConsensusChangeID is the id of a consensus change. 58 ConsensusChangeID crypto.Hash 59 60 // A DiffDirection indicates the "direction" of a diff, either applied or 61 // reverted. A bool is used to restrict the value to these two possibilities. 62 DiffDirection bool 63 64 // A ConsensusSetSubscriber is an object that receives updates to the consensus 65 // set every time there is a change in consensus. 66 ConsensusSetSubscriber interface { 67 // ProcessConsensusChange sends a consensus update to a module through 68 // a function call. Updates will always be sent in the correct order. 69 // There may not be any reverted blocks, but there will always be 70 // applied blocks. 71 ProcessConsensusChange(ConsensusChange) 72 } 73 74 // A ConsensusChange enumerates a set of changes that occurred to the consensus set. 75 ConsensusChange struct { 76 // ID is a unique id for the consensus change derived from the reverted 77 // and applied blocks. 78 ID ConsensusChangeID 79 80 // RevertedBlocks is the list of blocks that were reverted by the change. 81 // The reverted blocks were always all reverted before the applied blocks 82 // were applied. The revered blocks are presented in the order that they 83 // were reverted. 84 RevertedBlocks []types.Block 85 86 // AppliedBlocks is the list of blocks that were applied by the change. The 87 // applied blocks are always all applied after all the reverted blocks were 88 // reverted. The applied blocks are presented in the order that they were 89 // applied. 90 AppliedBlocks []types.Block 91 92 // SiacoinOutputDiffs contains the set of siacoin diffs that were applied 93 // to the consensus set in the recent change. The direction for the set of 94 // diffs is 'DiffApply'. 95 SiacoinOutputDiffs []SiacoinOutputDiff 96 97 // FileContractDiffs contains the set of file contract diffs that were 98 // applied to the consensus set in the recent change. The direction for the 99 // set of diffs is 'DiffApply'. 100 FileContractDiffs []FileContractDiff 101 102 // SiafundOutputDiffs contains the set of siafund diffs that were applied 103 // to the consensus set in the recent change. The direction for the set of 104 // diffs is 'DiffApply'. 105 SiafundOutputDiffs []SiafundOutputDiff `json:"scod"` 106 107 // DelayedSiacoinOutputDiffs contains the set of delayed siacoin output 108 // diffs that were applied to the consensus set in the recent change. 109 DelayedSiacoinOutputDiffs []DelayedSiacoinOutputDiff `json:"dscod"` 110 111 // SiafundPoolDiffs are the siafund pool diffs that were applied to the 112 // consensus set in the recent change. 113 SiafundPoolDiffs []SiafundPoolDiff 114 115 // ChildTarget defines the target of any block that would be the child 116 // of the block most recently appended to the consensus set. 117 ChildTarget types.Target 118 119 // MinimumValidChildTimestamp defines the minimum allowed timestamp for 120 // any block that is the child of the block most recently appended to 121 // the consensus set. 122 MinimumValidChildTimestamp types.Timestamp 123 124 // Synced indicates whether or not the ConsensusSet is synced with its 125 // peers. 126 Synced bool 127 128 // TryTransactionSet is an unlocked version of 129 // ConsensusSet.TryTransactionSet. This allows the TryTransactionSet 130 // function to be called by a subscriber during 131 // ProcessConsensusChange. 132 TryTransactionSet func([]types.Transaction) (ConsensusChange, error) 133 } 134 135 // A SiacoinOutputDiff indicates the addition or removal of a SiacoinOutput in 136 // the consensus set. 137 SiacoinOutputDiff struct { 138 Direction DiffDirection 139 ID types.SiacoinOutputID 140 SiacoinOutput types.SiacoinOutput 141 } 142 143 // A FileContractDiff indicates the addition or removal of a FileContract in 144 // the consensus set. 145 FileContractDiff struct { 146 Direction DiffDirection 147 ID types.FileContractID 148 FileContract types.FileContract 149 } 150 151 // A SiafundOutputDiff indicates the addition or removal of a SiafundOutput in 152 // the consensus set. 153 SiafundOutputDiff struct { 154 Direction DiffDirection `json:"dir"` 155 ID types.SiafundOutputID `json:"id"` 156 SiafundOutput types.SiafundOutput `json:"sco"` 157 } 158 159 // A DelayedSiacoinOutputDiff indicates the introduction of a siacoin output 160 // that cannot be spent until after maturing for 144 blocks. When the output 161 // has matured, a SiacoinOutputDiff will be provided. 162 DelayedSiacoinOutputDiff struct { 163 Direction DiffDirection `json:"dir"` 164 ID types.SiacoinOutputID `json:"id"` 165 SiacoinOutput types.SiacoinOutput `json:"sco"` 166 MaturityHeight types.BlockHeight `json:"mh"` 167 } 168 169 // A SiafundPoolDiff contains the value of the siafundPool before the block 170 // was applied, and after the block was applied. When applying the diff, set 171 // siafundPool to 'Adjusted'. When reverting the diff, set siafundPool to 172 // 'Previous'. 173 SiafundPoolDiff struct { 174 Direction DiffDirection 175 Previous types.Currency 176 Adjusted types.Currency 177 } 178 179 // A ConsensusSet accepts blocks and builds an understanding of network 180 // consensus. 181 ConsensusSet interface { 182 // AcceptBlock adds a block to consensus. An error will be returned if the 183 // block is invalid, has been seen before, is an orphan, or doesn't 184 // contribute to the heaviest fork known to the consensus set. If the block 185 // does not become the head of the heaviest known fork but is otherwise 186 // valid, it will be remembered by the consensus set but an error will 187 // still be returned. 188 AcceptBlock(types.Block) error 189 190 // BlockAtHeight returns the block found at the input height, with a 191 // bool to indicate whether that block exists. 192 BlockAtHeight(types.BlockHeight) (types.Block, bool) 193 194 // BlocksByID returns a block found for a given ID and its height, with 195 // a bool to indicate whether that block exists. 196 BlockByID(types.BlockID) (types.Block, types.BlockHeight, bool) 197 198 // ChildTarget returns the target required to extend the current heaviest 199 // fork. This function is typically used by miners looking to extend the 200 // heaviest fork. 201 ChildTarget(types.BlockID) (types.Target, bool) 202 203 // Close will shut down the consensus set, giving the module enough time to 204 // run any required closing routines. 205 Close() error 206 207 // ConsensusSetSubscribe adds a subscriber to the list of subscribers 208 // and gives them every consensus change that has occurred since the 209 // change with the provided id. There are a few special cases, 210 // described by the ConsensusChangeX variables in this package. 211 // A channel can be provided to abort the subscription process. 212 ConsensusSetSubscribe(ConsensusSetSubscriber, ConsensusChangeID, <-chan struct{}) error 213 214 // CurrentBlock returns the latest block in the heaviest known 215 // blockchain. 216 CurrentBlock() types.Block 217 218 // Flush will cause the consensus set to finish all in-progress 219 // routines. 220 Flush() error 221 222 // Height returns the current height of consensus. 223 Height() types.BlockHeight 224 225 // Synced returns true if the consensus set is synced with the network. 226 Synced() bool 227 228 // InCurrentPath returns true if the block id presented is found in the 229 // current path, false otherwise. 230 InCurrentPath(types.BlockID) bool 231 232 // MinimumValidChildTimestamp returns the earliest timestamp that is 233 // valid on the current longest fork according to the consensus set. This is 234 // a required piece of information for the miner, who could otherwise be at 235 // risk of mining invalid blocks. 236 MinimumValidChildTimestamp(types.BlockID) (types.Timestamp, bool) 237 238 // StorageProofSegment returns the segment to be used in the storage proof for 239 // a given file contract. 240 StorageProofSegment(types.FileContractID) (uint64, error) 241 242 // TryTransactionSet checks whether the transaction set would be valid if 243 // it were added in the next block. A consensus change is returned 244 // detailing the diffs that would result from the application of the 245 // transaction. 246 TryTransactionSet([]types.Transaction) (ConsensusChange, error) 247 248 // Unsubscribe removes a subscriber from the list of subscribers, 249 // allowing for garbage collection and rescanning. If the subscriber is 250 // not found in the subscriber database, no action is taken. 251 Unsubscribe(ConsensusSetSubscriber) 252 253 Db() *persist.BoltDatabase 254 } 255 ) 256 257 // Append takes to ConsensusChange objects and adds all of their diffs together. 258 // 259 // NOTE: It is possible for diffs to overlap or be inconsistent. This function 260 // should only be used with consecutive or disjoint consensus change objects. 261 func (cc ConsensusChange) Append(cc2 ConsensusChange) ConsensusChange { 262 return ConsensusChange{ 263 RevertedBlocks: append(cc.RevertedBlocks, cc2.RevertedBlocks...), 264 AppliedBlocks: append(cc.AppliedBlocks, cc2.AppliedBlocks...), 265 SiacoinOutputDiffs: append(cc.SiacoinOutputDiffs, cc2.SiacoinOutputDiffs...), 266 FileContractDiffs: append(cc.FileContractDiffs, cc2.FileContractDiffs...), 267 SiafundOutputDiffs: append(cc.SiafundOutputDiffs, cc2.SiafundOutputDiffs...), 268 DelayedSiacoinOutputDiffs: append(cc.DelayedSiacoinOutputDiffs, cc2.DelayedSiacoinOutputDiffs...), 269 } 270 }