github.com/johnathanhowell/sia@v0.5.1-beta.0.20160524050156-83dcc3d37c94/modules/consensus.go (about)

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