Fix TestBlueBlockWindow (#1098)

* Fix TestBlueBlockWindow

* Add comments
This commit is contained in:
Ori Newman 2020-11-17 05:46:31 -08:00 committed by Svarog
parent d4993c1d06
commit 60c24d8dea
12 changed files with 271 additions and 64 deletions

View File

@ -6,6 +6,7 @@ import (
"github.com/pkg/errors"
)
// AddOrphan adds the block to the orphan set
func (f *FlowContext) AddOrphan(orphanBlock *externalapi.DomainBlock) {
f.orphansMutex.Lock()
defer f.orphansMutex.Unlock()
@ -14,6 +15,7 @@ func (f *FlowContext) AddOrphan(orphanBlock *externalapi.DomainBlock) {
f.orphans[*orphanHash] = orphanBlock
}
// UnorphanBlocks removes the block from the orphan set, and remove all of the blocks that are not orphans anymore.
func (f *FlowContext) UnorphanBlocks(rootBlock *externalapi.DomainBlock) ([]*externalapi.DomainBlock, error) {
f.orphansMutex.Lock()
defer f.orphansMutex.Unlock()

View File

@ -10,8 +10,9 @@ func bluesAnticoneSizesToDBBluesAnticoneSizes(bluesAnticoneSizes map[externalapi
dbBluesAnticoneSizes := make([]*DbBluesAnticoneSizes, len(bluesAnticoneSizes))
i := 0
for hash, anticoneSize := range bluesAnticoneSizes {
hashCopy := hash
dbBluesAnticoneSizes[i] = &DbBluesAnticoneSizes{
BlueHash: DomainHashToDbHash(&hash),
BlueHash: DomainHashToDbHash(&hashCopy),
AnticoneSize: uint32(anticoneSize),
}
i++

View File

@ -5,7 +5,7 @@ import "github.com/kaspanet/kaspad/domain/consensus/model/externalapi"
// DAGTraversalManager exposes methods for traversing blocks
// in the DAG
type DAGTraversalManager interface {
HighestChainBlockBelowBlueScore(highHash *externalapi.DomainHash, blueScore uint64) (*externalapi.DomainHash, error)
BlockAtDepth(highHash *externalapi.DomainHash, depth uint64) (*externalapi.DomainHash, error)
LowestChainBlockAboveOrEqualToBlueScore(highHash *externalapi.DomainHash, blueScore uint64) (*externalapi.DomainHash, error)
SelectedParentIterator(highHash *externalapi.DomainHash) BlockIterator
SelectedChildIterator(highHash, lowHash *externalapi.DomainHash) (BlockIterator, error)

View File

@ -99,12 +99,7 @@ func (bb *testBlockBuilder) buildBlockWithParents(
return nil, err
}
selectedParentStatus, err := bb.testConsensus.BlockStatusStore().Get(bb.databaseContext, ghostdagData.SelectedParent)
if err != nil {
return nil, err
}
selectedParentStatus, err = bb.testConsensus.ConsensusStateManager().ResolveBlockStatus(ghostdagData.SelectedParent)
selectedParentStatus, err := bb.testConsensus.ConsensusStateManager().ResolveBlockStatus(ghostdagData.SelectedParent)
if err != nil {
return nil, err
}

View File

@ -159,6 +159,9 @@ func (csm *consensusStateManager) maybeAcceptTransaction(transaction *externalap
}
isAccepted, accumulatedMassAfter = csm.checkTransactionMass(transaction, accumulatedMassBefore)
if !isAccepted {
return false, accumulatedMassBefore, nil
}
}
err = utxoalgebra.DiffAddTransaction(accumulatedUTXODiff, transaction, blockBlueScore)

View File

@ -28,20 +28,8 @@ func (csm *consensusStateManager) checkFinalityViolation(
func (csm *consensusStateManager) virtualFinalityPoint() (
*externalapi.DomainHash, error) {
virtualGHOSTDAGData, err := csm.ghostdagDataStore.Get(csm.databaseContext, model.VirtualBlockHash)
if err != nil {
return nil, err
}
finalityPointBlueScore := virtualGHOSTDAGData.BlueScore - csm.finalityDepth
if virtualGHOSTDAGData.BlueScore < csm.finalityDepth {
// if there's no `csm.finalityDepth` blocks in the DAG
// practically - returns the genesis
finalityPointBlueScore = 0
}
return csm.dagTraversalManager.HighestChainBlockBelowBlueScore(
model.VirtualBlockHash, finalityPointBlueScore)
return csm.dagTraversalManager.BlockAtDepth(
model.VirtualBlockHash, csm.finalityDepth)
}
func (csm *consensusStateManager) isViolatingFinality(

View File

@ -156,14 +156,5 @@ func (csm *consensusStateManager) HeaderTipsPruningPoint() (*externalapi.DomainH
}
defer csm.ghostdagDataStore.Discard()
virtualHeaderGHOSTDAGData, err := csm.ghostdagDataStore.Get(csm.databaseContext, virtualHeaderHash)
if err != nil {
return nil, err
}
blueScore := virtualHeaderGHOSTDAGData.BlueScore - csm.pruningDepth
if csm.pruningDepth > virtualHeaderGHOSTDAGData.BlueScore {
blueScore = 0
}
return csm.dagTraversalManager.HighestChainBlockBelowBlueScore(virtualHeaderHash, blueScore)
return csm.dagTraversalManager.BlockAtDepth(virtualHeaderHash, csm.pruningDepth)
}

View File

@ -64,17 +64,21 @@ func (dtm *dagTraversalManager) SelectedParentIterator(highHash *externalapi.Dom
}
}
// HighestChainBlockBelowBlueScore returns the hash of the
// highest block with a blue score lower than the given
// blueScore in the selected-parent-chain of the block
// with the given highHash's selected parent chain
func (dtm *dagTraversalManager) HighestChainBlockBelowBlueScore(highHash *externalapi.DomainHash, requiredBlueScore uint64) (*externalapi.DomainHash, error) {
// BlockAtDepth returns the hash of the highest block with a blue score
// lower than (highHash.blueSore - depth) in the selected-parent-chain
// of the block with the given highHash's selected parent chain.
func (dtm *dagTraversalManager) BlockAtDepth(highHash *externalapi.DomainHash, depth uint64) (*externalapi.DomainHash, error) {
currentBlockHash := highHash
highBlockGHOSTDAGData, err := dtm.ghostdagDataStore.Get(dtm.databaseContext, highHash)
if err != nil {
return nil, err
}
requiredBlueScore := uint64(0)
if highBlockGHOSTDAGData.BlueScore > depth {
requiredBlueScore = highBlockGHOSTDAGData.BlueScore - depth
}
currentBlockGHOSTDAGData := highBlockGHOSTDAGData
// If we used `BlockIterator` we'd need to do more calls to `ghostdagDataStore` so we can get the blueScore
for currentBlockGHOSTDAGData.BlueScore >= requiredBlueScore {

View File

@ -12,25 +12,156 @@ import (
)
func TestBlueBlockWindow(t *testing.T) {
testutils.ForAllNets(t, true, func(t *testing.T, params *dagconfig.Params) {
factory := consensus.NewFactory()
tc, tearDown, err := factory.NewTestConsensus(params, "TestBlueBlockWindow")
if err != nil {
t.Fatalf("NewTestConsensus: %s", err)
}
defer tearDown()
windowSize := uint64(10)
blockByIDMap := make(map[string]*externalapi.DomainHash)
idByBlockMap := make(map[externalapi.DomainHash]string)
blockByIDMap["A"] = params.GenesisHash
idByBlockMap[*params.GenesisHash] = "A"
blocksData := []*struct {
parents []string
id string //id is a virtual entity that is used only for tests so we can define relations between blocks without knowing their hash
expectedWindowWithGenesisPadding []string
}{
tests := map[string][]*struct {
parents []string
id string //id is a virtual entity that is used only for tests so we can define relations between blocks without knowing their hash
expectedWindowWithGenesisPadding []string
}{
"kaspa-mainnet": {
{
parents: []string{"A"},
id: "B",
expectedWindowWithGenesisPadding: []string{"A", "A", "A", "A", "A", "A", "A", "A", "A", "A"},
},
{
parents: []string{"B"},
id: "C",
expectedWindowWithGenesisPadding: []string{"B", "A", "A", "A", "A", "A", "A", "A", "A", "A"},
},
{
parents: []string{"B"},
id: "D",
expectedWindowWithGenesisPadding: []string{"B", "A", "A", "A", "A", "A", "A", "A", "A", "A"},
},
{
parents: []string{"C", "D"},
id: "E",
expectedWindowWithGenesisPadding: []string{"C", "D", "B", "A", "A", "A", "A", "A", "A", "A"},
},
{
parents: []string{"C", "D"},
id: "F",
expectedWindowWithGenesisPadding: []string{"C", "D", "B", "A", "A", "A", "A", "A", "A", "A"},
},
{
parents: []string{"A"},
id: "G",
expectedWindowWithGenesisPadding: []string{"A", "A", "A", "A", "A", "A", "A", "A", "A", "A"},
},
{
parents: []string{"G"},
id: "H",
expectedWindowWithGenesisPadding: []string{"G", "A", "A", "A", "A", "A", "A", "A", "A", "A"},
},
{
parents: []string{"H", "F"},
id: "I",
expectedWindowWithGenesisPadding: []string{"F", "C", "D", "B", "A", "A", "A", "A", "A", "A"},
},
{
parents: []string{"I"},
id: "J",
expectedWindowWithGenesisPadding: []string{"I", "F", "C", "D", "B", "A", "A", "A", "A", "A"},
},
{
parents: []string{"J"},
id: "K",
expectedWindowWithGenesisPadding: []string{"J", "I", "F", "C", "D", "B", "A", "A", "A", "A"},
},
{
parents: []string{"K"},
id: "L",
expectedWindowWithGenesisPadding: []string{"K", "J", "I", "F", "C", "D", "B", "A", "A", "A"},
},
{
parents: []string{"L"},
id: "M",
expectedWindowWithGenesisPadding: []string{"L", "K", "J", "I", "F", "C", "D", "B", "A", "A"},
},
{
parents: []string{"M"},
id: "N",
expectedWindowWithGenesisPadding: []string{"M", "L", "K", "J", "I", "F", "C", "D", "B", "A"},
},
{
parents: []string{"N"},
id: "O",
expectedWindowWithGenesisPadding: []string{"N", "M", "L", "K", "J", "I", "F", "C", "D", "B"},
},
},
"kaspa-testnet": {
{
parents: []string{"A"},
id: "B",
expectedWindowWithGenesisPadding: []string{"A", "A", "A", "A", "A", "A", "A", "A", "A", "A"},
},
{
parents: []string{"B"},
id: "C",
expectedWindowWithGenesisPadding: []string{"B", "A", "A", "A", "A", "A", "A", "A", "A", "A"},
},
{
parents: []string{"B"},
id: "D",
expectedWindowWithGenesisPadding: []string{"B", "A", "A", "A", "A", "A", "A", "A", "A", "A"},
},
{
parents: []string{"C", "D"},
id: "E",
expectedWindowWithGenesisPadding: []string{"C", "D", "B", "A", "A", "A", "A", "A", "A", "A"},
},
{
parents: []string{"C", "D"},
id: "F",
expectedWindowWithGenesisPadding: []string{"C", "D", "B", "A", "A", "A", "A", "A", "A", "A"},
},
{
parents: []string{"A"},
id: "G",
expectedWindowWithGenesisPadding: []string{"A", "A", "A", "A", "A", "A", "A", "A", "A", "A"},
},
{
parents: []string{"G"},
id: "H",
expectedWindowWithGenesisPadding: []string{"G", "A", "A", "A", "A", "A", "A", "A", "A", "A"},
},
{
parents: []string{"H", "F"},
id: "I",
expectedWindowWithGenesisPadding: []string{"F", "C", "D", "B", "A", "A", "A", "A", "A", "A"},
},
{
parents: []string{"I"},
id: "J",
expectedWindowWithGenesisPadding: []string{"I", "F", "C", "D", "B", "A", "A", "A", "A", "A"},
},
{
parents: []string{"J"},
id: "K",
expectedWindowWithGenesisPadding: []string{"J", "I", "F", "C", "D", "B", "A", "A", "A", "A"},
},
{
parents: []string{"K"},
id: "L",
expectedWindowWithGenesisPadding: []string{"K", "J", "I", "F", "C", "D", "B", "A", "A", "A"},
},
{
parents: []string{"L"},
id: "M",
expectedWindowWithGenesisPadding: []string{"L", "K", "J", "I", "F", "C", "D", "B", "A", "A"},
},
{
parents: []string{"M"},
id: "N",
expectedWindowWithGenesisPadding: []string{"M", "L", "K", "J", "I", "F", "C", "D", "B", "A"},
},
{
parents: []string{"N"},
id: "O",
expectedWindowWithGenesisPadding: []string{"N", "M", "L", "K", "J", "I", "F", "C", "D", "B"},
},
},
"kaspa-devnet": {
{
parents: []string{"A"},
id: "B",
@ -101,7 +232,96 @@ func TestBlueBlockWindow(t *testing.T) {
id: "O",
expectedWindowWithGenesisPadding: []string{"N", "M", "L", "K", "J", "I", "F", "D", "C", "B"},
},
},
"kaspa-simnet": {
{
parents: []string{"A"},
id: "B",
expectedWindowWithGenesisPadding: []string{"A", "A", "A", "A", "A", "A", "A", "A", "A", "A"},
},
{
parents: []string{"B"},
id: "C",
expectedWindowWithGenesisPadding: []string{"B", "A", "A", "A", "A", "A", "A", "A", "A", "A"},
},
{
parents: []string{"B"},
id: "D",
expectedWindowWithGenesisPadding: []string{"B", "A", "A", "A", "A", "A", "A", "A", "A", "A"},
},
{
parents: []string{"C", "D"},
id: "E",
expectedWindowWithGenesisPadding: []string{"D", "C", "B", "A", "A", "A", "A", "A", "A", "A"},
},
{
parents: []string{"C", "D"},
id: "F",
expectedWindowWithGenesisPadding: []string{"D", "C", "B", "A", "A", "A", "A", "A", "A", "A"},
},
{
parents: []string{"A"},
id: "G",
expectedWindowWithGenesisPadding: []string{"A", "A", "A", "A", "A", "A", "A", "A", "A", "A"},
},
{
parents: []string{"G"},
id: "H",
expectedWindowWithGenesisPadding: []string{"G", "A", "A", "A", "A", "A", "A", "A", "A", "A"},
},
{
parents: []string{"H", "F"},
id: "I",
expectedWindowWithGenesisPadding: []string{"F", "D", "C", "B", "A", "A", "A", "A", "A", "A"},
},
{
parents: []string{"I"},
id: "J",
expectedWindowWithGenesisPadding: []string{"I", "F", "D", "C", "B", "A", "A", "A", "A", "A"},
},
{
parents: []string{"J"},
id: "K",
expectedWindowWithGenesisPadding: []string{"J", "I", "F", "D", "C", "B", "A", "A", "A", "A"},
},
{
parents: []string{"K"},
id: "L",
expectedWindowWithGenesisPadding: []string{"K", "J", "I", "F", "D", "C", "B", "A", "A", "A"},
},
{
parents: []string{"L"},
id: "M",
expectedWindowWithGenesisPadding: []string{"L", "K", "J", "I", "F", "D", "C", "B", "A", "A"},
},
{
parents: []string{"M"},
id: "N",
expectedWindowWithGenesisPadding: []string{"M", "L", "K", "J", "I", "F", "D", "C", "B", "A"},
},
{
parents: []string{"N"},
id: "O",
expectedWindowWithGenesisPadding: []string{"N", "M", "L", "K", "J", "I", "F", "D", "C", "B"},
},
},
}
testutils.ForAllNets(t, true, func(t *testing.T, params *dagconfig.Params) {
params.K = 1
factory := consensus.NewFactory()
tc, tearDown, err := factory.NewTestConsensus(params, "TestBlueBlockWindow")
if err != nil {
t.Fatalf("NewTestConsensus: %s", err)
}
defer tearDown()
windowSize := uint64(10)
blockByIDMap := make(map[string]*externalapi.DomainHash)
idByBlockMap := make(map[externalapi.DomainHash]string)
blockByIDMap["A"] = params.GenesisHash
idByBlockMap[*params.GenesisHash] = "A"
blocksData := tests[params.Name]
for _, blockData := range blocksData {
parents := hashset.New()
@ -112,7 +332,7 @@ func TestBlueBlockWindow(t *testing.T) {
block, err := tc.AddBlock(parents.ToSlice(), nil, nil)
if err != nil {
t.Fatalf("AddBlock: %s", err)
t.Fatalf("AddBlock: %+v", err)
}
blockByIDMap[blockData.id] = block

View File

@ -50,7 +50,7 @@ func (mdm *mergeDepthManager) CheckBoundedMergeDepth(blockHash *externalapi.Doma
return nil
}
finalityPoint, err := mdm.finalityPoint(ghostdagData)
finalityPoint, err := mdm.finalityPoint(blockHash)
if err != nil {
return err
}
@ -88,7 +88,7 @@ func (mdm mergeDepthManager) NonBoundedMergeDepthViolatingBlues(blockHash *exter
nonBoundedMergeDepthViolatingBlues := make([]*externalapi.DomainHash, 0, len(ghostdagData.MergeSetBlues))
for _, blue := range ghostdagData.MergeSetBlues {
notViolatingFinality, err := mdm.hasFinalityPointInOthersSelectedChain(ghostdagData, blue)
notViolatingFinality, err := mdm.hasFinalityPointInOthersSelectedChain(blockHash, blue)
if err != nil {
return nil, err
}
@ -101,8 +101,8 @@ func (mdm mergeDepthManager) NonBoundedMergeDepthViolatingBlues(blockHash *exter
return nonBoundedMergeDepthViolatingBlues, nil
}
func (mdm *mergeDepthManager) hasFinalityPointInOthersSelectedChain(ghostdagData *model.BlockGHOSTDAGData, other *externalapi.DomainHash) (bool, error) {
finalityPoint, err := mdm.finalityPoint(ghostdagData)
func (mdm *mergeDepthManager) hasFinalityPointInOthersSelectedChain(this, other *externalapi.DomainHash) (bool, error) {
finalityPoint, err := mdm.finalityPoint(this)
if err != nil {
return false, err
}
@ -110,6 +110,6 @@ func (mdm *mergeDepthManager) hasFinalityPointInOthersSelectedChain(ghostdagData
return mdm.dagTopologyManager.IsInSelectedParentChainOf(finalityPoint, other)
}
func (mdm *mergeDepthManager) finalityPoint(ghostdagData *model.BlockGHOSTDAGData) (*externalapi.DomainHash, error) {
return mdm.dagTraversalManager.HighestChainBlockBelowBlueScore(ghostdagData.SelectedParent, ghostdagData.BlueScore-mdm.finalityDepth)
func (mdm *mergeDepthManager) finalityPoint(blockHash *externalapi.DomainHash) (*externalapi.DomainHash, error) {
return mdm.dagTraversalManager.BlockAtDepth(blockHash, mdm.finalityDepth)
}

View File

@ -98,7 +98,7 @@ func (pm *pruningManager) FindNextPruningPoint() error {
}
// get Virtual(pruningDepth)
candidatePHash, err := pm.dagTraversalManager.HighestChainBlockBelowBlueScore(model.VirtualBlockHash, pm.pruningDepth)
candidatePHash, err := pm.dagTraversalManager.BlockAtDepth(model.VirtualBlockHash, pm.pruningDepth)
if err != nil {
return err
}

View File

@ -152,6 +152,9 @@ func (mna *MinimalNetAdapter) handleHandshake(routes *Routes, ourID *id.ID) erro
err = routes.OutgoingRoute.Enqueue(&appmessage.MsgAddresses{
AddressList: []*appmessage.NetAddress{},
})
if err != nil {
return err
}
err = routes.OutgoingRoute.Enqueue(&appmessage.MsgRequestAddresses{
IncludeAllSubnetworks: true,