kaspad/domain/consensus/consensus.go
2020-11-09 16:21:09 +02:00

180 lines
5.2 KiB
Go

package consensus
import (
"sync"
"github.com/kaspanet/kaspad/domain/consensus/model"
"github.com/kaspanet/kaspad/domain/consensus/model/externalapi"
)
type consensus struct {
lock *sync.RWMutex
databaseContext model.DBReader
blockProcessor model.BlockProcessor
blockBuilder model.BlockBuilder
consensusStateManager model.ConsensusStateManager
transactionValidator model.TransactionValidator
syncManager model.SyncManager
pastMedianTimeManager model.PastMedianTimeManager
blockStore model.BlockStore
blockHeaderStore model.BlockHeaderStore
pruningStore model.PruningStore
ghostdagDataStore model.GHOSTDAGDataStore
blockStatusStore model.BlockStatusStore
}
// BuildBlock builds a block over the current state, with the transactions
// selected by the given transactionSelector
func (s *consensus) BuildBlock(coinbaseData *externalapi.DomainCoinbaseData,
transactions []*externalapi.DomainTransaction) (*externalapi.DomainBlock, error) {
s.lock.RLock()
defer s.lock.RUnlock()
return s.blockBuilder.BuildBlock(coinbaseData, transactions)
}
// ValidateAndInsertBlock validates the given block and, if valid, applies it
// to the current state
func (s *consensus) ValidateAndInsertBlock(block *externalapi.DomainBlock) error {
s.lock.Lock()
defer s.lock.Unlock()
return s.blockProcessor.ValidateAndInsertBlock(block)
}
// ValidateTransactionAndPopulateWithConsensusData validates the given transaction
// and populates it with any missing consensus data
func (s *consensus) ValidateTransactionAndPopulateWithConsensusData(transaction *externalapi.DomainTransaction) error {
s.lock.RLock()
defer s.lock.RUnlock()
err := s.transactionValidator.ValidateTransactionInIsolation(transaction)
if err != nil {
return err
}
err = s.consensusStateManager.PopulateTransactionWithUTXOEntries(transaction)
if err != nil {
return err
}
virtualGHOSTDAGData, err := s.ghostdagDataStore.Get(s.databaseContext, model.VirtualBlockHash)
if err != nil {
return err
}
virtualSelectedParentMedianTime, err := s.pastMedianTimeManager.PastMedianTime(virtualGHOSTDAGData.SelectedParent)
if err != nil {
return err
}
return s.transactionValidator.ValidateTransactionInContextAndPopulateMassAndFee(transaction,
model.VirtualBlockHash, virtualSelectedParentMedianTime)
}
func (s *consensus) GetBlock(blockHash *externalapi.DomainHash) (*externalapi.DomainBlock, error) {
s.lock.RLock()
defer s.lock.RUnlock()
return s.blockStore.Block(s.databaseContext, blockHash)
}
func (s *consensus) GetBlockHeader(blockHash *externalapi.DomainHash) (*externalapi.DomainBlockHeader, error) {
s.lock.RLock()
defer s.lock.RUnlock()
return s.blockHeaderStore.BlockHeader(s.databaseContext, blockHash)
}
func (s *consensus) GetBlockInfo(blockHash *externalapi.DomainHash) (*externalapi.BlockInfo, error) {
s.lock.RLock()
defer s.lock.RUnlock()
blockInfo := &externalapi.BlockInfo{}
exists, err := s.blockStatusStore.Exists(s.databaseContext, blockHash)
if err != nil {
return nil, err
}
blockInfo.Exists = exists
if !exists {
return blockInfo, nil
}
blockStatus, err := s.blockStatusStore.Get(s.databaseContext, blockHash)
if err != nil {
return nil, err
}
blockInfo.BlockStatus = blockStatus
isBlockInHeaderPruningPointFuture, err := s.syncManager.IsBlockInHeaderPruningPointFuture(blockHash)
if err != nil {
return nil, err
}
blockInfo.IsBlockInHeaderPruningPointFuture = isBlockInHeaderPruningPointFuture
return blockInfo, nil
}
func (s *consensus) GetHashesBetween(lowHash, highHash *externalapi.DomainHash) ([]*externalapi.DomainHash, error) {
s.lock.RLock()
defer s.lock.RUnlock()
return s.syncManager.GetHashesBetween(lowHash, highHash)
}
func (s *consensus) GetMissingBlockBodyHashes(highHash *externalapi.DomainHash) ([]*externalapi.DomainHash, error) {
s.lock.RLock()
defer s.lock.RUnlock()
return s.syncManager.GetMissingBlockBodyHashes(highHash)
}
func (s *consensus) GetPruningPointUTXOSet() ([]byte, error) {
s.lock.RLock()
defer s.lock.RUnlock()
return s.pruningStore.PruningPointSerializedUTXOSet(s.databaseContext)
}
func (s *consensus) SetPruningPointUTXOSet(serializedUTXOSet []byte) error {
s.lock.RLock()
defer s.lock.RUnlock()
return s.consensusStateManager.SetPruningPointUTXOSet(serializedUTXOSet)
}
func (s *consensus) GetVirtualSelectedParent() (*externalapi.DomainBlock, error) {
s.lock.RLock()
defer s.lock.RUnlock()
virtualGHOSTDAGData, err := s.ghostdagDataStore.Get(s.databaseContext, model.VirtualBlockHash)
if err != nil {
return nil, err
}
return s.GetBlock(virtualGHOSTDAGData.SelectedParent)
}
func (s *consensus) CreateBlockLocator(lowHash, highHash *externalapi.DomainHash) (externalapi.BlockLocator, error) {
s.lock.RLock()
defer s.lock.RUnlock()
return s.syncManager.CreateBlockLocator(lowHash, highHash)
}
func (s *consensus) FindNextBlockLocatorBoundaries(blockLocator externalapi.BlockLocator) (lowHash, highHash *externalapi.DomainHash, err error) {
s.lock.RLock()
defer s.lock.RUnlock()
return s.syncManager.FindNextBlockLocatorBoundaries(blockLocator)
}
func (s *consensus) GetSyncInfo() (*externalapi.SyncInfo, error) {
s.lock.RLock()
defer s.lock.RUnlock()
return s.syncManager.GetSyncInfo()
}