[NOD-1517] Properly initialize consensus with Genesis block (#1009)

* [NOD-1517] Properly initialize consensus with Genesis block

* [NOD-1517] Remove redundant AddHeaderTip

* [NOD-1517] Don't return nil from dbHash<->DomainHash converters

* [NOD-1517] Use pointer receivers

* [NOD-1517] Use domain block in dagParams

* [NOD-1517] Remove boolean from SelectedTip

* [NOD-1517] Rename hasHeader to isHeadersOnlyBlock

* [NOD-1517] Add comment

* [NOD-1517] Change genesis version

* [NOD-1517] Rename TestNewFactory->TestNewConsensus
This commit is contained in:
Ori Newman 2020-11-08 05:17:20 -08:00 committed by GitHub
parent 281944762d
commit 9a344152aa
No known key found for this signature in database
GPG Key ID: 4AEE18F83AFDEB23
32 changed files with 412 additions and 186 deletions

View File

@ -1,12 +1,20 @@
package serialization
import "github.com/kaspanet/kaspad/domain/consensus/model"
import (
"github.com/kaspanet/kaspad/domain/consensus/model"
"github.com/kaspanet/kaspad/domain/consensus/model/externalapi"
)
// BlockGHOSTDAGDataToDBBlockGHOSTDAGData converts BlockGHOSTDAGData to DbBlockGhostdagData
func BlockGHOSTDAGDataToDBBlockGHOSTDAGData(blockGHOSTDAGData *model.BlockGHOSTDAGData) *DbBlockGhostdagData {
var selectedParent *DbHash
if blockGHOSTDAGData.SelectedParent != nil {
selectedParent = DomainHashToDbHash(blockGHOSTDAGData.SelectedParent)
}
return &DbBlockGhostdagData{
BlueScore: blockGHOSTDAGData.BlueScore,
SelectedParent: DomainHashToDbHash(blockGHOSTDAGData.SelectedParent),
SelectedParent: selectedParent,
MergeSetBlues: DomainHashesToDbHashes(blockGHOSTDAGData.MergeSetBlues),
MergeSetReds: DomainHashesToDbHashes(blockGHOSTDAGData.MergeSetReds),
BluesAnticoneSizes: bluesAnticoneSizesToDBBluesAnticoneSizes(blockGHOSTDAGData.BluesAnticoneSizes),
@ -15,9 +23,13 @@ func BlockGHOSTDAGDataToDBBlockGHOSTDAGData(blockGHOSTDAGData *model.BlockGHOSTD
// DBBlockGHOSTDAGDataToBlockGHOSTDAGData converts DbBlockGhostdagData to BlockGHOSTDAGData
func DBBlockGHOSTDAGDataToBlockGHOSTDAGData(dbBlockGHOSTDAGData *DbBlockGhostdagData) (*model.BlockGHOSTDAGData, error) {
selectedParent, err := DbHashToDomainHash(dbBlockGHOSTDAGData.SelectedParent)
if err != nil {
return nil, err
var selectedParent *externalapi.DomainHash
if dbBlockGHOSTDAGData.SelectedParent != nil {
var err error
selectedParent, err = DbHashToDomainHash(dbBlockGHOSTDAGData.SelectedParent)
if err != nil {
return nil, err
}
}
mergetSetBlues, err := DbHashesToDomainHashes(dbBlockGHOSTDAGData.MergeSetBlues)

View File

@ -2,12 +2,18 @@ package serialization
import (
"github.com/kaspanet/kaspad/domain/consensus/model"
"github.com/kaspanet/kaspad/domain/consensus/model/externalapi"
)
func reachablityTreeNodeToDBReachablityTreeNode(reachabilityTreeNode *model.ReachabilityTreeNode) *DbReachabilityTreeNode {
var parent *DbHash
if reachabilityTreeNode.Parent != nil {
parent = DomainHashToDbHash(reachabilityTreeNode.Parent)
}
return &DbReachabilityTreeNode{
Children: DomainHashesToDbHashes(reachabilityTreeNode.Children),
Parent: DomainHashToDbHash(reachabilityTreeNode.Parent),
Parent: parent,
Interval: reachablityIntervalToDBReachablityInterval(reachabilityTreeNode.Interval),
}
}
@ -18,9 +24,13 @@ func dbReachablityTreeNodeToReachablityTreeNode(dbReachabilityTreeNode *DbReacha
return nil, err
}
parent, err := DbHashToDomainHash(dbReachabilityTreeNode.Parent)
if err != nil {
return nil, err
var parent *externalapi.DomainHash
if dbReachabilityTreeNode.Parent != nil {
var err error
parent, err = DbHashToDomainHash(dbReachabilityTreeNode.Parent)
if err != nil {
return nil, err
}
}
return &model.ReachabilityTreeNode{

View File

@ -9,23 +9,23 @@ type dbTransaction struct {
transaction database.Transaction
}
func (d dbTransaction) Put(key model.DBKey, value []byte) error {
func (d *dbTransaction) Put(key model.DBKey, value []byte) error {
return d.transaction.Put(dbKeyToDatabaseKey(key), value)
}
func (d dbTransaction) Delete(key model.DBKey) error {
func (d *dbTransaction) Delete(key model.DBKey) error {
return d.transaction.Delete(dbKeyToDatabaseKey(key))
}
func (d dbTransaction) Rollback() error {
func (d *dbTransaction) Rollback() error {
return d.transaction.Rollback()
}
func (d dbTransaction) Commit() error {
return d.Commit()
func (d *dbTransaction) Commit() error {
return d.transaction.Commit()
}
func (d dbTransaction) RollbackUnlessClosed() error {
func (d *dbTransaction) RollbackUnlessClosed() error {
return d.RollbackUnlessClosed()
}

View File

@ -63,6 +63,14 @@ func (brs *blockRelationStore) BlockRelation(dbContext model.DBReader, blockHash
return brs.deserializeBlockRelations(blockRelationsBytes)
}
func (brs *blockRelationStore) Has(dbContext model.DBReader, blockHash *externalapi.DomainHash) (bool, error) {
if _, ok := brs.staging[*blockHash]; ok {
return true, nil
}
return dbContext.Has(brs.hashAsKey(blockHash))
}
func (brs *blockRelationStore) hashAsKey(hash *externalapi.DomainHash) model.DBKey {
return bucket.Key(hash[:])
}

View File

@ -18,14 +18,14 @@ func New() model.ConsensusStateStore {
return &consensusStateStore{}
}
func (c consensusStateStore) Discard() {
func (c *consensusStateStore) Discard() {
c.stagedTips = nil
c.stagedVirtualUTXODiff = nil
c.stagedVirtualDiffParents = nil
c.stagedVirtualUTXOSet = nil
}
func (c consensusStateStore) Commit(dbTx model.DBTransaction) error {
func (c *consensusStateStore) Commit(dbTx model.DBTransaction) error {
err := c.commitTips(dbTx)
if err != nil {
return err
@ -50,7 +50,7 @@ func (c consensusStateStore) Commit(dbTx model.DBTransaction) error {
return nil
}
func (c consensusStateStore) IsStaged() bool {
func (c *consensusStateStore) IsStaged() bool {
return c.stagedTips != nil ||
c.stagedVirtualDiffParents != nil ||
c.stagedVirtualUTXODiff != nil

View File

@ -9,7 +9,7 @@ import (
var tipsKey = dbkeys.MakeBucket().Key([]byte("tips"))
func (c consensusStateStore) Tips(dbContext model.DBReader) ([]*externalapi.DomainHash, error) {
func (c *consensusStateStore) Tips(dbContext model.DBReader) ([]*externalapi.DomainHash, error) {
if c.stagedTips != nil {
return c.stagedTips, nil
}
@ -22,11 +22,11 @@ func (c consensusStateStore) Tips(dbContext model.DBReader) ([]*externalapi.Doma
return hashes.DeserializeHashSlice(tipsBytes)
}
func (c consensusStateStore) StageTips(tipHashes []*externalapi.DomainHash) {
func (c *consensusStateStore) StageTips(tipHashes []*externalapi.DomainHash) {
c.stagedTips = tipHashes
}
func (c consensusStateStore) commitTips(dbTx model.DBTransaction) error {
func (c *consensusStateStore) commitTips(dbTx model.DBTransaction) error {
tipsBytes := hashes.SerializeHashSlice(c.stagedTips)
err := dbTx.Put(tipsKey, tipsBytes)

View File

@ -18,7 +18,7 @@ func utxoKey(outpoint *externalapi.DomainOutpoint) (model.DBKey, error) {
return utxoSetBucket.Key(serializedOutpoint), nil
}
func (c consensusStateStore) StageVirtualUTXODiff(virtualUTXODiff *model.UTXODiff) error {
func (c *consensusStateStore) StageVirtualUTXODiff(virtualUTXODiff *model.UTXODiff) error {
if c.stagedVirtualUTXOSet != nil {
return errors.New("cannot stage virtual UTXO diff while virtual UTXO set is staged")
}
@ -27,11 +27,15 @@ func (c consensusStateStore) StageVirtualUTXODiff(virtualUTXODiff *model.UTXODif
return nil
}
func (c consensusStateStore) commitVirtualUTXODiff(dbTx model.DBTransaction) error {
func (c *consensusStateStore) commitVirtualUTXODiff(dbTx model.DBTransaction) error {
if c.stagedVirtualUTXOSet != nil {
return errors.New("cannot commit virtual UTXO diff while virtual UTXO set is staged")
}
if c.stagedVirtualUTXODiff == nil {
return nil
}
for toRemoveOutpoint := range c.stagedVirtualUTXODiff.ToRemove {
dbKey, err := utxoKey(&toRemoveOutpoint)
if err != nil {
@ -61,7 +65,7 @@ func (c consensusStateStore) commitVirtualUTXODiff(dbTx model.DBTransaction) err
return nil
}
func (c consensusStateStore) commitVirtualUTXOSet(dbTx model.DBTransaction) error {
func (c *consensusStateStore) commitVirtualUTXOSet(dbTx model.DBTransaction) error {
if c.stagedVirtualUTXODiff != nil {
return errors.New("cannot commit virtual UTXO set while virtual UTXO diff is staged")
}
@ -84,7 +88,7 @@ func (c consensusStateStore) commitVirtualUTXOSet(dbTx model.DBTransaction) erro
return nil
}
func (c consensusStateStore) UTXOByOutpoint(dbContext model.DBReader, outpoint *externalapi.DomainOutpoint) (
func (c *consensusStateStore) UTXOByOutpoint(dbContext model.DBReader, outpoint *externalapi.DomainOutpoint) (
*externalapi.UTXOEntry, error) {
if c.stagedVirtualUTXOSet != nil {
@ -94,7 +98,7 @@ func (c consensusStateStore) UTXOByOutpoint(dbContext model.DBReader, outpoint *
return c.utxoByOutpointFromStagedVirtualUTXODiff(dbContext, outpoint)
}
func (c consensusStateStore) utxoByOutpointFromStagedVirtualUTXODiff(dbContext model.DBReader,
func (c *consensusStateStore) utxoByOutpointFromStagedVirtualUTXODiff(dbContext model.DBReader,
outpoint *externalapi.DomainOutpoint) (
*externalapi.UTXOEntry, error) {
@ -120,7 +124,7 @@ func (c consensusStateStore) utxoByOutpointFromStagedVirtualUTXODiff(dbContext m
return deserializeUTXOEntry(serializedUTXOEntry)
}
func (c consensusStateStore) utxoByOutpointFromStagedVirtualUTXOSet(outpoint *externalapi.DomainOutpoint) (
func (c *consensusStateStore) utxoByOutpointFromStagedVirtualUTXOSet(outpoint *externalapi.DomainOutpoint) (
*externalapi.UTXOEntry, error) {
if utxoEntry, ok := c.stagedVirtualUTXOSet[*outpoint]; ok {
return utxoEntry, nil
@ -129,7 +133,7 @@ func (c consensusStateStore) utxoByOutpointFromStagedVirtualUTXOSet(outpoint *ex
return nil, errors.Errorf("outpoint was not found")
}
func (c consensusStateStore) HasUTXOByOutpoint(dbContext model.DBReader, outpoint *externalapi.DomainOutpoint) (bool, error) {
func (c *consensusStateStore) HasUTXOByOutpoint(dbContext model.DBReader, outpoint *externalapi.DomainOutpoint) (bool, error) {
if c.stagedVirtualUTXOSet != nil {
return c.hasUTXOByOutpointFromStagedVirtualUTXOSet(outpoint), nil
}
@ -137,7 +141,7 @@ func (c consensusStateStore) HasUTXOByOutpoint(dbContext model.DBReader, outpoin
return c.hasUTXOByOutpointFromStagedVirtualUTXODiff(dbContext, outpoint)
}
func (c consensusStateStore) hasUTXOByOutpointFromStagedVirtualUTXODiff(dbContext model.DBReader,
func (c *consensusStateStore) hasUTXOByOutpointFromStagedVirtualUTXODiff(dbContext model.DBReader,
outpoint *externalapi.DomainOutpoint) (bool, error) {
if _, ok := c.stagedVirtualUTXODiff.ToRemove[*outpoint]; ok {
return false, nil
@ -154,12 +158,12 @@ func (c consensusStateStore) hasUTXOByOutpointFromStagedVirtualUTXODiff(dbContex
return dbContext.Has(key)
}
func (c consensusStateStore) hasUTXOByOutpointFromStagedVirtualUTXOSet(outpoint *externalapi.DomainOutpoint) bool {
func (c *consensusStateStore) hasUTXOByOutpointFromStagedVirtualUTXOSet(outpoint *externalapi.DomainOutpoint) bool {
_, ok := c.stagedVirtualUTXOSet[*outpoint]
return ok
}
func (c consensusStateStore) VirtualUTXOSetIterator(dbContext model.DBReader) (model.ReadOnlyUTXOSetIterator, error) {
func (c *consensusStateStore) VirtualUTXOSetIterator(dbContext model.DBReader) (model.ReadOnlyUTXOSetIterator, error) {
cursor, err := dbContext.Cursor(utxoSetBucket)
if err != nil {
return nil, err
@ -204,7 +208,7 @@ func (u utxoSetIterator) Get() (outpoint *externalapi.DomainOutpoint, utxoEntry
return outpoint, utxoEntry, nil
}
func (c consensusStateStore) StageVirtualUTXOSet(virtualUTXOSetIterator model.ReadOnlyUTXOSetIterator) error {
func (c *consensusStateStore) StageVirtualUTXOSet(virtualUTXOSetIterator model.ReadOnlyUTXOSetIterator) error {
if c.stagedVirtualUTXODiff != nil {
return errors.New("cannot stage virtual UTXO set while virtual UTXO diff is staged")
}

View File

@ -9,7 +9,7 @@ import (
var virtualDiffParentsKey = dbkeys.MakeBucket().Key([]byte("virtual-diff-parents"))
func (c consensusStateStore) VirtualDiffParents(dbContext model.DBReader) ([]*externalapi.DomainHash, error) {
func (c *consensusStateStore) VirtualDiffParents(dbContext model.DBReader) ([]*externalapi.DomainHash, error) {
if c.stagedVirtualDiffParents != nil {
return c.stagedVirtualDiffParents, nil
}
@ -22,11 +22,11 @@ func (c consensusStateStore) VirtualDiffParents(dbContext model.DBReader) ([]*ex
return hashes.DeserializeHashSlice(virtualDiffParentsBytes)
}
func (c consensusStateStore) StageVirtualDiffParents(tipHashes []*externalapi.DomainHash) {
func (c *consensusStateStore) StageVirtualDiffParents(tipHashes []*externalapi.DomainHash) {
c.stagedVirtualDiffParents = tipHashes
}
func (c consensusStateStore) commitVirtualDiffParents(dbTx model.DBTransaction) error {
func (c *consensusStateStore) commitVirtualDiffParents(dbTx model.DBTransaction) error {
virtualDiffParentsBytes := hashes.SerializeHashSlice(c.stagedVirtualDiffParents)
err := dbTx.Put(virtualDiffParentsKey, virtualDiffParentsBytes)

View File

@ -14,28 +14,46 @@ type headerTipsStore struct {
staging []*externalapi.DomainHash
}
func (h headerTipsStore) Discard() {
func (h *headerTipsStore) HasTips(dbContext model.DBReader) (bool, error) {
if h.staging != nil {
return len(h.staging) > 0, nil
}
return dbContext.Has(headerTipsKey)
}
func (h *headerTipsStore) Discard() {
h.staging = nil
}
func (h headerTipsStore) Commit(dbTx model.DBTransaction) error {
func (h *headerTipsStore) Commit(dbTx model.DBTransaction) error {
if h.staging == nil {
return nil
}
tipsBytes, err := h.serializeTips(h.staging)
if err != nil {
return err
}
return dbTx.Put(headerTipsKey, tipsBytes)
err = dbTx.Put(headerTipsKey, tipsBytes)
if err != nil {
return err
}
h.Discard()
return nil
}
func (h headerTipsStore) Stage(tips []*externalapi.DomainHash) {
func (h *headerTipsStore) Stage(tips []*externalapi.DomainHash) {
h.staging = tips
}
func (h headerTipsStore) IsStaged() bool {
func (h *headerTipsStore) IsStaged() bool {
return h.staging != nil
}
func (h headerTipsStore) Tips(dbContext model.DBReader) ([]*externalapi.DomainHash, error) {
func (h *headerTipsStore) Tips(dbContext model.DBReader) ([]*externalapi.DomainHash, error) {
if h.staging != nil {
return h.staging, nil
}
@ -48,12 +66,12 @@ func (h headerTipsStore) Tips(dbContext model.DBReader) ([]*externalapi.DomainHa
return h.deserializeTips(tipsBytes)
}
func (h headerTipsStore) serializeTips(tips []*externalapi.DomainHash) ([]byte, error) {
func (h *headerTipsStore) serializeTips(tips []*externalapi.DomainHash) ([]byte, error) {
dbTips := serialization.HeaderTipsToDBHeaderTips(tips)
return proto.Marshal(dbTips)
}
func (h headerTipsStore) deserializeTips(tipsBytes []byte) ([]*externalapi.DomainHash, error) {
func (h *headerTipsStore) deserializeTips(tipsBytes []byte) ([]*externalapi.DomainHash, error) {
dbTips := &serialization.DbHeaderTips{}
err := proto.Unmarshal(tipsBytes, dbTips)
if err != nil {

View File

@ -41,24 +41,27 @@ func (ps *pruningStore) Discard() {
}
func (ps *pruningStore) Commit(dbTx model.DBTransaction) error {
pruningPointBytes, err := ps.serializePruningPoint(ps.pruningPointStaging)
if err != nil {
return err
if ps.pruningPointStaging != nil {
pruningPointBytes, err := ps.serializePruningPoint(ps.pruningPointStaging)
if err != nil {
return err
}
err = dbTx.Put(pruningBlockHashKey, pruningPointBytes)
if err != nil {
return err
}
}
err = dbTx.Put(pruningBlockHashKey, pruningPointBytes)
if err != nil {
return err
}
if ps.serializedUTXOSetStaging != nil {
utxoSetBytes, err := ps.serializeUTXOSetBytes(ps.serializedUTXOSetStaging)
if err != nil {
return err
}
utxoSetBytes, err := ps.serializeUTXOSetBytes(ps.serializedUTXOSetStaging)
if err != nil {
return err
}
err = dbTx.Put(pruningSerializedUTXOSetkey, utxoSetBytes)
if err != nil {
return err
err = dbTx.Put(pruningSerializedUTXOSetkey, utxoSetBytes)
if err != nil {
return err
}
}
ps.Discard()

View File

@ -88,6 +88,14 @@ func (rds *reachabilityDataStore) ReachabilityData(dbContext model.DBReader,
return rds.deserializeReachabilityData(reachabilityDataBytes)
}
func (rds *reachabilityDataStore) HasReachabilityData(dbContext model.DBReader, blockHash *externalapi.DomainHash) (bool, error) {
if _, ok := rds.reachabilityDataStaging[*blockHash]; ok {
return true, nil
}
return dbContext.Has(rds.reachabilityDataBlockHashAsKey(blockHash))
}
// ReachabilityReindexRoot returns the current reachability reindex root
func (rds *reachabilityDataStore) ReachabilityReindexRoot(dbContext model.DBReader) (*externalapi.DomainHash, error) {
if rds.reachabilityReindexRootStaging != nil {

View File

@ -221,7 +221,7 @@ func (f *factory) NewConsensus(dagParams *dagconfig.Params, db infrastructuredat
blockHeaderStore,
headerTipsStore)
return &consensus{
c := &consensus{
databaseContext: dbManager,
blockProcessor: blockProcessor,
@ -235,7 +235,21 @@ func (f *factory) NewConsensus(dagParams *dagconfig.Params, db infrastructuredat
pruningStore: pruningStore,
ghostdagDataStore: ghostdagDataStore,
blockStatusStore: blockStatusStore,
}, nil
}
genesisInfo, err := c.GetBlockInfo(genesisHash)
if err != nil {
return nil, err
}
if !genesisInfo.Exists {
err = c.ValidateAndInsertBlock(dagParams.GenesisBlock)
if err != nil {
return nil, err
}
}
return c, nil
}
// NewFactory creates a new Consensus factory

View File

@ -0,0 +1,29 @@
package consensus
import (
"github.com/kaspanet/kaspad/domain/dagconfig"
"github.com/kaspanet/kaspad/infrastructure/db/database/ldb"
"io/ioutil"
"testing"
)
func TestNewConsensus(t *testing.T) {
f := NewFactory()
dagParams := &dagconfig.DevnetParams
tmpDir, err := ioutil.TempDir("", "TestNewConsensus")
if err != nil {
return
}
db, err := ldb.NewLevelDB(tmpDir)
if err != nil {
t.Fatalf("error in NewLevelDB: %s", err)
}
_, err = f.NewConsensus(dagParams, db)
if err != nil {
t.Fatalf("error in NewConsensus: %+v", err)
}
}

View File

@ -4,6 +4,7 @@ package externalapi
// states of the consensus
const (
SyncStateNormal SyncState = iota
SyncStateMissingGenesis
SyncStateHeadersFirst
SyncStateMissingUTXOSet
SyncStateMissingBlockBodies

View File

@ -8,4 +8,5 @@ type BlockRelationStore interface {
StageBlockRelation(blockHash *externalapi.DomainHash, blockRelations *BlockRelations)
IsStaged() bool
BlockRelation(dbContext DBReader, blockHash *externalapi.DomainHash) (*BlockRelations, error)
Has(dbContext DBReader, blockHash *externalapi.DomainHash) (bool, error)
}

View File

@ -8,4 +8,5 @@ type HeaderTipsStore interface {
Stage(tips []*externalapi.DomainHash)
IsStaged() bool
Tips(dbContext DBReader) ([]*externalapi.DomainHash, error)
HasTips(dbContext DBReader) (bool, error)
}

View File

@ -9,5 +9,6 @@ type ReachabilityDataStore interface {
StageReachabilityReindexRoot(reachabilityReindexRoot *externalapi.DomainHash)
IsAnythingStaged() bool
ReachabilityData(dbContext DBReader, blockHash *externalapi.DomainHash) (*ReachabilityData, error)
HasReachabilityData(dbContext DBReader, blockHash *externalapi.DomainHash) (bool, error)
ReachabilityReindexRoot(dbContext DBReader) (*externalapi.DomainHash, error)
}

View File

@ -58,11 +58,6 @@ func (bp *blockProcessor) validateAndInsertBlock(block *externalapi.DomainBlock)
if err != nil {
return err
}
err = bp.headerTipsManager.AddHeaderTip(hash)
if err != nil {
return err
}
}
if mode.State == externalapi.SyncStateHeadersFirst {
@ -78,12 +73,21 @@ func (bp *blockProcessor) validateAndInsertBlock(block *externalapi.DomainBlock)
return err
}
oldHeadersSelectedTip, err := bp.headerTipsManager.SelectedTip()
hasTips, err := bp.headerTipsStore.HasTips(bp.databaseContext)
if err != nil {
return err
}
if mode.State == externalapi.SyncStateHeadersFirst {
var oldHeadersSelectedTip *externalapi.DomainHash
if hasTips {
var err error
oldHeadersSelectedTip, err = bp.headerTipsManager.SelectedTip()
if err != nil {
return err
}
}
if mode.State == externalapi.SyncStateHeadersFirst || mode.State == externalapi.SyncStateMissingGenesis {
err = bp.headerTipsManager.AddHeaderTip(hash)
if err != nil {
return err
@ -102,21 +106,26 @@ func (bp *blockProcessor) validateAndInsertBlock(block *externalapi.DomainBlock)
bp.headerTipsStore.Stage(tips)
}
err = bp.updateReachabilityReindexRoot(oldHeadersSelectedTip)
if err != nil {
return err
if mode.State != externalapi.SyncStateMissingGenesis {
err = bp.updateReachabilityReindexRoot(oldHeadersSelectedTip)
if err != nil {
return err
}
}
// Trigger pruning, which will check if the pruning point changed and delete the data if it did.
err = bp.pruningManager.FindNextPruningPoint()
if err != nil {
return err
if mode.State == externalapi.SyncStateNormal {
// Trigger pruning, which will check if the pruning point changed and delete the data if it did.
err = bp.pruningManager.FindNextPruningPoint()
if err != nil {
return err
}
}
return bp.commitAllChanges()
}
func (bp *blockProcessor) updateReachabilityReindexRoot(oldHeadersSelectedTip *externalapi.DomainHash) error {
headersSelectedTip, err := bp.headerTipsManager.SelectedTip()
if err != nil {
return err
@ -156,15 +165,28 @@ func (bp *blockProcessor) checkBlockStatus(hash *externalapi.DomainHash, mode *e
}
func (bp *blockProcessor) validateBlock(block *externalapi.DomainBlock, mode *externalapi.SyncInfo) error {
// If any validation until (included) proof-of-work fails, simply
// return an error without writing anything in the database.
// This is to prevent spamming attacks.
err := bp.validatePreProofOfWork(block)
blockHash := consensusserialization.HeaderHash(block.Header)
hasHeader, err := bp.hasHeader(blockHash)
if err != nil {
return err
}
if !hasHeader {
bp.blockHeaderStore.Stage(blockHash, block.Header)
err = bp.dagTopologyManager.SetParents(blockHash, block.Header.ParentHashes)
if err != nil {
return err
}
}
// If any validation until (included) proof-of-work fails, simply
// return an error without writing anything in the database.
// This is to prevent spamming attacks.
err = bp.validatePreProofOfWork(block)
if err != nil {
return err
}
blockHash := consensusserialization.BlockHash(block)
err = bp.blockValidator.ValidateProofOfWorkAndDifficulty(blockHash)
if err != nil {
return err
@ -224,12 +246,6 @@ func (bp *blockProcessor) validatePostProofOfWork(block *externalapi.DomainBlock
}
if !hasHeader {
bp.blockHeaderStore.Stage(blockHash, block.Header)
err := bp.dagTopologyManager.SetParents(blockHash, block.Header.ParentHashes)
if err != nil {
return err
}
err = bp.blockValidator.ValidateHeaderInContext(blockHash)
if err != nil {
return err

View File

@ -26,12 +26,12 @@ func (v *blockValidator) ValidateHeaderInContext(blockHash *externalapi.DomainHa
return err
}
status, err := v.blockStatusStore.Get(v.databaseContext, blockHash)
isHeadersOnlyBlock, err := v.isHeadersOnlyBlock(blockHash)
if err != nil {
return err
}
if status != externalapi.StatusHeaderOnly {
if !isHeadersOnlyBlock {
err = v.ghostdagManager.GHOSTDAG(blockHash)
if err != nil {
return err
@ -51,6 +51,24 @@ func (v *blockValidator) ValidateHeaderInContext(blockHash *externalapi.DomainHa
return nil
}
func (v *blockValidator) isHeadersOnlyBlock(blockHash *externalapi.DomainHash) (bool, error) {
exists, err := v.blockStatusStore.Exists(v.databaseContext, blockHash)
if err != nil {
return false, err
}
if !exists {
return false, nil
}
status, err := v.blockStatusStore.Get(v.databaseContext, blockHash)
if err != nil {
return false, err
}
return status == externalapi.StatusHeaderOnly, nil
}
// checkParentsIncest validates that no parent is an ancestor of another parent
func (v *blockValidator) checkParentsIncest(header *externalapi.DomainBlockHeader) error {
for _, parentA := range header.ParentHashes {

View File

@ -103,14 +103,22 @@ func isHashInSlice(hash *externalapi.DomainHash, hashes []*externalapi.DomainHas
}
func (dtm *dagTopologyManager) SetParents(blockHash *externalapi.DomainHash, parentHashes []*externalapi.DomainHash) error {
// Go over the block's current relations (if they exist), and remove the block from all it's current parents
// Note: In theory we should also remove the block from all it's children, however, in practice no block
// ever has it's relations updated after getting any children, therefore we skip this step
currentRelations, err := dtm.blockRelationStore.BlockRelation(dtm.databaseContext, blockHash)
hasRelations, err := dtm.blockRelationStore.Has(dtm.databaseContext, blockHash)
if err != nil {
return err
}
if currentRelations != nil {
if hasRelations {
// Go over the block's current relations (if they exist), and remove the block from all its current parents
// Note: In theory we should also remove the block from all its children, however, in practice no block
// ever has its relations updated after getting any children, therefore we skip this step
currentRelations, err := dtm.blockRelationStore.BlockRelation(dtm.databaseContext, blockHash)
if err != nil {
return err
}
for _, currentParent := range currentRelations.Parents {
parentRelations, err := dtm.blockRelationStore.BlockRelation(dtm.databaseContext, currentParent)
if err != nil {

View File

@ -35,14 +35,18 @@ func (gm *ghostdagManager) GHOSTDAG(blockHash *externalapi.DomainHash) error {
if err != nil {
return err
}
selectedParent, err := gm.findSelectedParent(blockParents)
if err != nil {
return err
}
newBlockData.SelectedParent = selectedParent
newBlockData.MergeSetBlues = append(newBlockData.MergeSetBlues, selectedParent)
newBlockData.BluesAnticoneSizes[*selectedParent] = 0
isGenesis := len(blockParents) == 0
if !isGenesis {
selectedParent, err := gm.findSelectedParent(blockParents)
if err != nil {
return err
}
newBlockData.SelectedParent = selectedParent
newBlockData.MergeSetBlues = append(newBlockData.MergeSetBlues, selectedParent)
newBlockData.BluesAnticoneSizes[*selectedParent] = 0
}
mergeSetWithoutSelectedParent, err := gm.mergeSetWithoutSelectedParent(newBlockData.SelectedParent, blockParents)
if err != nil {
@ -67,11 +71,16 @@ func (gm *ghostdagManager) GHOSTDAG(blockHash *externalapi.DomainHash) error {
}
}
selectedParentGHOSTDAGData, err := gm.ghostdagDataStore.Get(gm.databaseContext, newBlockData.SelectedParent)
if err != nil {
return err
if !isGenesis {
selectedParentGHOSTDAGData, err := gm.ghostdagDataStore.Get(gm.databaseContext, newBlockData.SelectedParent)
if err != nil {
return err
}
newBlockData.BlueScore = selectedParentGHOSTDAGData.BlueScore + uint64(len(newBlockData.MergeSetBlues))
} else {
// Genesis's blue score is defined to be 0.
newBlockData.BlueScore = 0
}
newBlockData.BlueScore = selectedParentGHOSTDAGData.BlueScore + uint64(len(newBlockData.MergeSetBlues))
gm.ghostdagDataStore.Stage(blockHash, newBlockData)
return nil

View File

@ -26,11 +26,20 @@ func New(databaseContext model.DBReader,
}
func (h headerTipsManager) AddHeaderTip(hash *externalapi.DomainHash) error {
tips, err := h.headerTipsStore.Tips(h.databaseContext)
tips := []*externalapi.DomainHash{}
hasTips, err := h.headerTipsStore.HasTips(h.databaseContext)
if err != nil {
return err
}
if hasTips {
var err error
tips, err = h.headerTipsStore.Tips(h.databaseContext)
if err != nil {
return err
}
}
newTips := make([]*externalapi.DomainHash, 0, len(tips)+1)
for _, tip := range tips {
isAncestorOf, err := h.dagTopologyManager.IsAncestorOf(tip, hash)

View File

@ -8,5 +8,10 @@ func (h headerTipsManager) SelectedTip() (*externalapi.DomainHash, error) {
return nil, err
}
return h.ghostdagManager.ChooseSelectedParent(tips...)
selectedTip, err := h.ghostdagManager.ChooseSelectedParent(tips...)
if err != nil {
return nil, err
}
return selectedTip, nil
}

View File

@ -45,6 +45,11 @@ func (mdm *mergeDepthManager) CheckBoundedMergeDepth(blockHash *externalapi.Doma
return err
}
// Return nil on genesis
if ghostdagData.SelectedParent == nil {
return nil
}
finalityPoint, err := mdm.finalityPoint(ghostdagData)
if err != nil {
return err

View File

@ -6,6 +6,18 @@ import (
)
func (rt *reachabilityManager) data(blockHash *externalapi.DomainHash) (*model.ReachabilityData, error) {
hasData, err := rt.reachabilityDataStore.HasReachabilityData(rt.databaseContext, blockHash)
if err != nil {
return nil, err
}
if !hasData {
return &model.ReachabilityData{
TreeNode: nil,
FutureCoveringSet: nil,
}, nil
}
return rt.reachabilityDataStore.ReachabilityData(rt.databaseContext, blockHash)
}

View File

@ -825,7 +825,7 @@ func (rt *reachabilityManager) findAncestorOfThisAmongChildrenOfOther(this, othe
ancestor, ok := rt.findAncestorOfNode(otherChildren, this)
if !ok {
return nil, errors.Errorf("node is not an ancestor of node")
return nil, errors.Errorf("node is not an ancestor of this")
}
return ancestor, nil

View File

@ -32,6 +32,15 @@ func (sm *syncManager) syncInfo() (*externalapi.SyncInfo, error) {
}
func (sm *syncManager) resolveSyncState() (externalapi.SyncState, error) {
hasTips, err := sm.headerTipsStore.HasTips(sm.databaseContext)
if err != nil {
return 0, err
}
if !hasTips {
return externalapi.SyncStateMissingGenesis, nil
}
headerVirtualSelectedParentHash, err := sm.headerVirtualSelectedParentHash()
if err != nil {
return 0, err

View File

@ -41,5 +41,6 @@ func serializeHeader(w io.Writer, header *externalapi.DomainBlockHeader) error {
return err
}
}
return writeElements(w, header.HashMerkleRoot, header.AcceptedIDMerkleRoot, header.UTXOCommitment, timestamp, header.Bits, header.Nonce)
return writeElements(w, &header.HashMerkleRoot, &header.AcceptedIDMerkleRoot, &header.UTXOCommitment, timestamp,
header.Bits, header.Nonce)
}

View File

@ -0,0 +1,26 @@
package transactionhelper
import (
"github.com/kaspanet/kaspad/domain/consensus/model/externalapi"
"github.com/kaspanet/kaspad/domain/consensus/utils/hashes"
)
// NewSubnetworkTransaction returns a new trsnactions in the specified subnetwork with specified gas and payload
func NewSubnetworkTransaction(version int32, inputs []*externalapi.DomainTransactionInput,
outputs []*externalapi.DomainTransactionOutput, subnetworkID *externalapi.DomainSubnetworkID,
gas uint64, payload []byte) *externalapi.DomainTransaction {
payloadHash := hashes.HashData(payload)
return &externalapi.DomainTransaction{
Version: version,
Inputs: inputs,
Outputs: outputs,
LockTime: 0,
SubnetworkID: *subnetworkID,
Gas: gas,
PayloadHash: *payloadHash,
Payload: payload,
Fee: 0,
Mass: 0,
}
}

View File

@ -5,13 +5,12 @@
package dagconfig
import (
"github.com/kaspanet/kaspad/app/appmessage"
"github.com/kaspanet/kaspad/domain/consensus/model/externalapi"
"github.com/kaspanet/kaspad/domain/consensus/utils/subnetworks"
"github.com/kaspanet/kaspad/util/mstime"
"github.com/kaspanet/kaspad/domain/consensus/utils/transactionhelper"
)
var genesisTxOuts = []*appmessage.TxOut{}
var genesisTxOuts = []*externalapi.DomainTransactionOutput{}
var genesisTxPayload = []byte{
0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, // Blue score
@ -23,16 +22,16 @@ var genesisTxPayload = []byte{
// genesisCoinbaseTx is the coinbase transaction for the genesis blocks for
// the main network.
var genesisCoinbaseTx = appmessage.NewSubnetworkMsgTx(1, []*appmessage.TxIn{}, genesisTxOuts,
var genesisCoinbaseTx = transactionhelper.NewSubnetworkTransaction(1, []*externalapi.DomainTransactionInput{}, genesisTxOuts,
&subnetworks.SubnetworkIDCoinbase, 0, genesisTxPayload)
// genesisHash is the hash of the first block in the block DAG for the main
// network (genesis block).
var genesisHash = externalapi.DomainHash{
0x67, 0x8b, 0x44, 0x41, 0x59, 0xe5, 0x99, 0xe0,
0x8e, 0x01, 0xad, 0x77, 0xce, 0x8b, 0x18, 0xe7,
0x1f, 0x61, 0x8c, 0x7d, 0x0c, 0x2f, 0x98, 0xbe,
0x63, 0xf4, 0x13, 0x89, 0x41, 0xc6, 0xdb, 0x9b,
0x37, 0xf9, 0x09, 0x98, 0x0e, 0x12, 0xf6, 0xa2,
0xaa, 0x0d, 0x09, 0xfa, 0x41, 0xad, 0x95, 0x1a,
0x5b, 0x38, 0x14, 0x12, 0xe9, 0x02, 0x14, 0xcd,
0xba, 0x64, 0xf6, 0x84, 0x72, 0xc4, 0xa4, 0x3a,
}
// genesisMerkleRoot is the hash of the first transaction in the genesis block
@ -46,21 +45,21 @@ var genesisMerkleRoot = externalapi.DomainHash{
// genesisBlock defines the genesis block of the block DAG which serves as the
// public transaction ledger for the main network.
var genesisBlock = appmessage.MsgBlock{
Header: appmessage.BlockHeader{
Version: 0x10000000,
var genesisBlock = externalapi.DomainBlock{
Header: &externalapi.DomainBlockHeader{
Version: 1,
ParentHashes: []*externalapi.DomainHash{},
HashMerkleRoot: &genesisMerkleRoot,
AcceptedIDMerkleRoot: &externalapi.DomainHash{},
UTXOCommitment: &externalapi.DomainHash{},
Timestamp: mstime.UnixMilliseconds(0x1730a81bdb4),
HashMerkleRoot: genesisMerkleRoot,
AcceptedIDMerkleRoot: externalapi.DomainHash{},
UTXOCommitment: externalapi.DomainHash{},
TimeInMilliseconds: 0x1730a81bdb4,
Bits: 0x207fffff,
Nonce: 0x1,
},
Transactions: []*appmessage.MsgTx{genesisCoinbaseTx},
Transactions: []*externalapi.DomainTransaction{genesisCoinbaseTx},
}
var devnetGenesisTxOuts = []*appmessage.TxOut{}
var devnetGenesisTxOuts = []*externalapi.DomainTransactionOutput{}
var devnetGenesisTxPayload = []byte{
0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, // Blue score
@ -73,44 +72,45 @@ var devnetGenesisTxPayload = []byte{
// devnetGenesisCoinbaseTx is the coinbase transaction for the genesis blocks for
// the development network.
var devnetGenesisCoinbaseTx = appmessage.NewSubnetworkMsgTx(1, []*appmessage.TxIn{}, devnetGenesisTxOuts,
var devnetGenesisCoinbaseTx = transactionhelper.NewSubnetworkTransaction(1,
[]*externalapi.DomainTransactionInput{}, devnetGenesisTxOuts,
&subnetworks.SubnetworkIDCoinbase, 0, devnetGenesisTxPayload)
// devGenesisHash is the hash of the first block in the block DAG for the development
// network (genesis block).
var devnetGenesisHash = externalapi.DomainHash{
0x3e, 0x0f, 0xb1, 0x20, 0x3b, 0xa1, 0x6f, 0xc5,
0x92, 0x63, 0x67, 0x09, 0x76, 0x38, 0x35, 0xea,
0x30, 0x89, 0xe6, 0x3a, 0x63, 0xe9, 0xf9, 0x6e,
0x31, 0x0a, 0x54, 0xb7, 0x24, 0x02, 0xd0, 0xec,
0xd3, 0xad, 0xd6, 0xe4, 0x6b, 0xc2, 0x33, 0xa9,
0x20, 0x03, 0x1e, 0xf3, 0xe6, 0x8a, 0xf4, 0x08,
0x91, 0xa1, 0x25, 0xc7, 0xc1, 0xf1, 0x5b, 0x3e,
0x74, 0x72, 0xb5, 0x8a, 0xa0, 0x10, 0x00, 0x00,
}
// devnetGenesisMerkleRoot is the hash of the first transaction in the genesis block
// for the devopment network.
var devnetGenesisMerkleRoot = externalapi.DomainHash{
0x68, 0x60, 0xe7, 0x77, 0x47, 0x74, 0x7f, 0xd5,
0x55, 0x58, 0x8a, 0xb5, 0xc2, 0x29, 0x0c, 0xa6,
0x65, 0x44, 0xb4, 0x4f, 0xfa, 0x31, 0x7a, 0xfa,
0x55, 0xe0, 0xcf, 0xac, 0x9c, 0x86, 0x30, 0x2a,
0x00, 0x94, 0xfd, 0xff, 0x4d, 0xb2, 0x4d, 0x18,
0x95, 0x21, 0x36, 0x2a, 0x14, 0xfb, 0x19, 0x7a,
0x99, 0x51, 0x7e, 0x3f, 0x44, 0xf6, 0x2e, 0x0b,
0xe7, 0xb3, 0xc0, 0xbb, 0x00, 0x3b, 0x0b, 0xbd,
}
// devnetGenesisBlock defines the genesis block of the block DAG which serves as the
// public transaction ledger for the development network.
var devnetGenesisBlock = appmessage.MsgBlock{
Header: appmessage.BlockHeader{
Version: 0x10000000,
var devnetGenesisBlock = externalapi.DomainBlock{
Header: &externalapi.DomainBlockHeader{
Version: 1,
ParentHashes: []*externalapi.DomainHash{},
HashMerkleRoot: &devnetGenesisMerkleRoot,
AcceptedIDMerkleRoot: &externalapi.DomainHash{},
UTXOCommitment: &externalapi.DomainHash{},
Timestamp: mstime.UnixMilliseconds(0x17305b05694),
HashMerkleRoot: devnetGenesisMerkleRoot,
AcceptedIDMerkleRoot: externalapi.DomainHash{},
UTXOCommitment: externalapi.DomainHash{},
TimeInMilliseconds: 0x17305b05694,
Bits: 0x1e7fffff,
Nonce: 0x10bb,
Nonce: 282366,
},
Transactions: []*appmessage.MsgTx{devnetGenesisCoinbaseTx},
Transactions: []*externalapi.DomainTransaction{devnetGenesisCoinbaseTx},
}
var simnetGenesisTxOuts = []*appmessage.TxOut{}
var simnetGenesisTxOuts = []*externalapi.DomainTransactionOutput{}
var simnetGenesisTxPayload = []byte{
0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, // Blue score
@ -122,16 +122,17 @@ var simnetGenesisTxPayload = []byte{
}
// simnetGenesisCoinbaseTx is the coinbase transaction for the simnet genesis block.
var simnetGenesisCoinbaseTx = appmessage.NewSubnetworkMsgTx(1, []*appmessage.TxIn{}, simnetGenesisTxOuts,
var simnetGenesisCoinbaseTx = transactionhelper.NewSubnetworkTransaction(1,
[]*externalapi.DomainTransactionInput{}, simnetGenesisTxOuts,
&subnetworks.SubnetworkIDCoinbase, 0, simnetGenesisTxPayload)
// simnetGenesisHash is the hash of the first block in the block DAG for
// the simnet (genesis block).
var simnetGenesisHash = externalapi.DomainHash{
0x9d, 0x89, 0xb0, 0x6e, 0xb3, 0x47, 0xb5, 0x6e,
0xcd, 0x6c, 0x63, 0x99, 0x45, 0x91, 0xd5, 0xce,
0x9b, 0x43, 0x05, 0xc1, 0xa5, 0x5e, 0x2a, 0xda,
0x90, 0x4c, 0xf0, 0x6c, 0x4d, 0x5f, 0xd3, 0x62,
0xad, 0x47, 0xba, 0xd5, 0x6e, 0x1e, 0x62, 0x99,
0x43, 0x81, 0xd2, 0xaf, 0xda, 0x1d, 0xe6, 0xda,
0x0b, 0x50, 0xcb, 0x76, 0x8e, 0x5d, 0x9e, 0x41,
0x20, 0x98, 0x28, 0xb1, 0x7e, 0x88, 0xb9, 0xb5,
}
// simnetGenesisMerkleRoot is the hash of the first transaction in the genesis block
@ -145,21 +146,21 @@ var simnetGenesisMerkleRoot = externalapi.DomainHash{
// simnetGenesisBlock defines the genesis block of the block DAG which serves as the
// public transaction ledger for the development network.
var simnetGenesisBlock = appmessage.MsgBlock{
Header: appmessage.BlockHeader{
Version: 0x10000000,
var simnetGenesisBlock = externalapi.DomainBlock{
Header: &externalapi.DomainBlockHeader{
Version: 1,
ParentHashes: []*externalapi.DomainHash{},
HashMerkleRoot: &simnetGenesisMerkleRoot,
AcceptedIDMerkleRoot: &externalapi.DomainHash{},
UTXOCommitment: &externalapi.DomainHash{},
Timestamp: mstime.UnixMilliseconds(0x173001df3d5),
HashMerkleRoot: simnetGenesisMerkleRoot,
AcceptedIDMerkleRoot: externalapi.DomainHash{},
UTXOCommitment: externalapi.DomainHash{},
TimeInMilliseconds: 0x173001df3d5,
Bits: 0x207fffff,
Nonce: 0x0,
},
Transactions: []*appmessage.MsgTx{simnetGenesisCoinbaseTx},
Transactions: []*externalapi.DomainTransaction{simnetGenesisCoinbaseTx},
}
var testnetGenesisTxOuts = []*appmessage.TxOut{}
var testnetGenesisTxOuts = []*externalapi.DomainTransactionOutput{}
var testnetGenesisTxPayload = []byte{
0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, // Blue score
@ -169,16 +170,17 @@ var testnetGenesisTxPayload = []byte{
}
// testnetGenesisCoinbaseTx is the coinbase transaction for the testnet genesis block.
var testnetGenesisCoinbaseTx = appmessage.NewSubnetworkMsgTx(1, []*appmessage.TxIn{}, testnetGenesisTxOuts,
var testnetGenesisCoinbaseTx = transactionhelper.NewSubnetworkTransaction(1,
[]*externalapi.DomainTransactionInput{}, testnetGenesisTxOuts,
&subnetworks.SubnetworkIDCoinbase, 0, testnetGenesisTxPayload)
// testnetGenesisHash is the hash of the first block in the block DAG for the test
// network (genesis block).
var testnetGenesisHash = externalapi.DomainHash{
0x91, 0xe2, 0x7f, 0x78, 0x4e, 0xe5, 0xf9, 0x3c,
0xff, 0x58, 0x45, 0xc3, 0xa6, 0x1f, 0x03, 0x80,
0x55, 0xbe, 0xf4, 0xf2, 0xd6, 0xdd, 0xe3, 0x38,
0xb7, 0xac, 0xd6, 0x3d, 0xc5, 0xb7, 0x1c, 0x73,
0x29, 0x0c, 0x43, 0x42, 0x66, 0x2d, 0x1b, 0x05,
0x0b, 0xc7, 0xb2, 0x26, 0x8d, 0x53, 0x16, 0xbf,
0x5a, 0x2d, 0x7e, 0xff, 0xee, 0x06, 0xb7, 0x2b,
0x41, 0x9f, 0xe8, 0xf0, 0xfa, 0xc7, 0xd1, 0x1a,
}
// testnetGenesisMerkleRoot is the hash of the first transaction in the genesis block
@ -192,16 +194,16 @@ var testnetGenesisMerkleRoot = externalapi.DomainHash{
// testnetGenesisBlock defines the genesis block of the block DAG which serves as the
// public transaction ledger for testnet.
var testnetGenesisBlock = appmessage.MsgBlock{
Header: appmessage.BlockHeader{
Version: 0x10000000,
var testnetGenesisBlock = externalapi.DomainBlock{
Header: &externalapi.DomainBlockHeader{
Version: 1,
ParentHashes: []*externalapi.DomainHash{},
HashMerkleRoot: &testnetGenesisMerkleRoot,
AcceptedIDMerkleRoot: &externalapi.DomainHash{},
UTXOCommitment: &externalapi.DomainHash{},
Timestamp: mstime.UnixMilliseconds(0x1730a66a9d9),
HashMerkleRoot: testnetGenesisMerkleRoot,
AcceptedIDMerkleRoot: externalapi.DomainHash{},
UTXOCommitment: externalapi.DomainHash{},
TimeInMilliseconds: 0x1730a66a9d9,
Bits: 0x1e7fffff,
Nonce: 0x162ca,
},
Transactions: []*appmessage.MsgTx{testnetGenesisCoinbaseTx},
Transactions: []*externalapi.DomainTransaction{testnetGenesisCoinbaseTx},
}

View File

@ -7,21 +7,17 @@ package dagconfig
import (
"testing"
"github.com/kaspanet/kaspad/app/appmessage"
"github.com/kaspanet/kaspad/domain/consensus/utils/consensusserialization"
"github.com/davecgh/go-spew/spew"
)
// TestGenesisBlock tests the genesis block of the main network for validity by
// checking the encoded hash.
func TestGenesisBlock(t *testing.T) {
// Check hash of the block against expected hash.
hash := consensusserialization.BlockHash(appmessage.MsgBlockToDomainBlock(MainnetParams.GenesisBlock))
hash := consensusserialization.BlockHash(MainnetParams.GenesisBlock)
if *MainnetParams.GenesisHash != *hash {
t.Fatalf("TestGenesisBlock: Genesis block hash does "+
"not appear valid - got %v, want %v", spew.Sdump(hash),
spew.Sdump(MainnetParams.GenesisHash))
"not appear valid - got %v, want %v", hash, MainnetParams.GenesisHash)
}
}
@ -29,11 +25,11 @@ func TestGenesisBlock(t *testing.T) {
// validity by checking the hash.
func TestTestnetGenesisBlock(t *testing.T) {
// Check hash of the block against expected hash.
hash := consensusserialization.BlockHash(appmessage.MsgBlockToDomainBlock(TestnetParams.GenesisBlock))
hash := consensusserialization.BlockHash(TestnetParams.GenesisBlock)
if *TestnetParams.GenesisHash != *hash {
t.Fatalf("TestTestnetGenesisBlock: Genesis block hash does "+
"not appear valid - got %v, want %v", spew.Sdump(hash),
spew.Sdump(TestnetParams.GenesisHash))
"not appear valid - got %v, want %v", hash,
TestnetParams.GenesisHash)
}
}
@ -41,11 +37,11 @@ func TestTestnetGenesisBlock(t *testing.T) {
// for validity by checking the hash.
func TestSimnetGenesisBlock(t *testing.T) {
// Check hash of the block against expected hash.
hash := consensusserialization.BlockHash(appmessage.MsgBlockToDomainBlock(SimnetParams.GenesisBlock))
hash := consensusserialization.BlockHash(SimnetParams.GenesisBlock)
if *SimnetParams.GenesisHash != *hash {
t.Fatalf("TestSimnetGenesisBlock: Genesis block hash does "+
"not appear valid - got %v, want %v", spew.Sdump(hash),
spew.Sdump(SimnetParams.GenesisHash))
"not appear valid - got %v, want %v", hash,
SimnetParams.GenesisHash)
}
}
@ -53,10 +49,10 @@ func TestSimnetGenesisBlock(t *testing.T) {
// for validity by checking the encoded hash.
func TestDevnetGenesisBlock(t *testing.T) {
// Check hash of the block against expected hash.
hash := consensusserialization.BlockHash(appmessage.MsgBlockToDomainBlock(DevnetParams.GenesisBlock))
hash := consensusserialization.BlockHash(DevnetParams.GenesisBlock)
if *DevnetParams.GenesisHash != *hash {
t.Fatalf("TestDevnetGenesisBlock: Genesis block hash does "+
"not appear valid - got %v, want %v", spew.Sdump(hash),
spew.Sdump(DevnetParams.GenesisHash))
"not appear valid - got %v, want %v", hash,
DevnetParams.GenesisHash)
}
}

View File

@ -80,7 +80,7 @@ type Params struct {
DNSSeeds []string
// GenesisBlock defines the first block of the DAG.
GenesisBlock *appmessage.MsgBlock
GenesisBlock *externalapi.DomainBlock
// GenesisHash is the starting block hash.
GenesisHash *externalapi.DomainHash