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

     1  package modules
     2  
     3  import (
     4  	"errors"
     5  
     6  	"gitlab.com/SiaPrime/SiaPrime/crypto"
     7  	"gitlab.com/SiaPrime/SiaPrime/persist"
     8  	"gitlab.com/SiaPrime/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  }