Skip to content
New issue

Have a question about this project? Sign up for a free GitHub account to open an issue and contact its maintainers and the community.

By clicking “Sign up for GitHub”, you agree to our terms of service and privacy statement. We’ll occasionally send you account related emails.

Already on GitHub? Sign in to your account

MeerDAG:support block foreach #581

Merged
merged 5 commits into from
Dec 8, 2023
Merged
Show file tree
Hide file tree
Changes from all commits
Commits
File filter

Filter by extension

Filter by extension

Conversations
Failed to load comments.
Loading
Jump to
Jump to file
Failed to load files.
Loading
Diff view
Diff view
2 changes: 2 additions & 0 deletions consensus/model/block.go
Original file line number Diff line number Diff line change
Expand Up @@ -7,4 +7,6 @@ type Block interface {
GetHash() *hash.Hash
GetState() BlockState
GetOrder() uint
HasParents() bool
GetMainParent() uint
}
4 changes: 4 additions & 0 deletions consensus/model/block_chain.go
Original file line number Diff line number Diff line change
Expand Up @@ -3,6 +3,7 @@ package model
import (
"github.com/Qitmeer/qng/common/hash"
"github.com/Qitmeer/qng/core/types"
"github.com/Qitmeer/qng/core/types/pow"
)

type BlockChain interface {
Expand All @@ -20,6 +21,9 @@ type BlockChain interface {
Stop() error
GetBlockByOrder(order uint64) Block
GetBlockById(id uint) Block
GetMainChainTip() Block
FetchBlockByHash(hash *hash.Hash) (*types.SerializedBlock, error)
GetBlockOrderByHash(hash *hash.Hash) (uint, error)
GetBlockHeader(block Block) *types.BlockHeader
ForeachBlueBlocks(start Block, depth uint, powType pow.PowType, fn func(block Block, header *types.BlockHeader) error) error
}
23 changes: 21 additions & 2 deletions core/blockchain/blockindex.go
Original file line number Diff line number Diff line change
Expand Up @@ -7,6 +7,7 @@ import (
"github.com/Qitmeer/qng/consensus/forks"
"github.com/Qitmeer/qng/consensus/model"
"github.com/Qitmeer/qng/core/types"
"github.com/Qitmeer/qng/core/types/pow"
"github.com/Qitmeer/qng/meerdag"
)

Expand Down Expand Up @@ -59,6 +60,10 @@ func (b *BlockChain) GetBlockById(id uint) model.Block {
return b.bd.GetBlockById(id)
}

func (b *BlockChain) GetMainChainTip() model.Block {
return b.bd.GetMainChainTip()
}

// BlockOrderByHash returns the order of the block with the given hash in the
// chain.
//
Expand Down Expand Up @@ -338,8 +343,9 @@ func (b *BlockChain) fetchHeaderByHash(hash *hash.Hash) (*types.BlockHeader, err
return nil, fmt.Errorf("unable to find block header %v db %v", hash, err)
}

func (b *BlockChain) GetBlockHeader(ib meerdag.IBlock) *types.BlockHeader {
if ib == nil {
func (b *BlockChain) GetBlockHeader(block model.Block) *types.BlockHeader {
ib, ok := block.(meerdag.IBlock)
if ib == nil || !ok {
return nil
}
if ib.GetData() != nil {
Expand All @@ -357,3 +363,16 @@ func (b *BlockChain) GetBlockHeader(ib meerdag.IBlock) *types.BlockHeader {
}
return header
}

func (b *BlockChain) ForeachBlueBlocks(start model.Block, depth uint, powType pow.PowType, fn func(block model.Block, header *types.BlockHeader) error) error {
return b.bd.Foreach(start.(meerdag.IBlock), depth, meerdag.Blue, func(block meerdag.IBlock) (bool, error) {
blockHeader := b.GetBlockHeader(block)
if blockHeader == nil {
return false, fmt.Errorf("No blockHeader:%s", block.GetHash().String())
}
if blockHeader.Pow.GetPowType() != powType {
return false, nil
}
return true, fn(block, blockHeader)
})
}
71 changes: 71 additions & 0 deletions meerdag/blocktransf.go
Original file line number Diff line number Diff line change
Expand Up @@ -4,6 +4,20 @@ import (
"fmt"
"github.com/Qitmeer/qng/common/hash"
"sort"
"time"
)

type FilterType byte

const (
// all
All FilterType = 0

// only blocks in blue set
Blue FilterType = 1

// only blocks in red set
Red FilterType = 2
)

// Is there a block in DAG?
Expand Down Expand Up @@ -418,3 +432,60 @@ func (bd *MeerDAG) locateBlocksFuzzy(gs *GraphState, maxHashes uint) []*hash.Has
func (bd *MeerDAG) GetLayer(id uint) uint {
return bd.GetBlockById(id).GetLayer()
}

func (bd *MeerDAG) Foreach(start IBlock, depth uint, filter FilterType, fn func(block IBlock) (bool, error)) error {
if _, ok := bd.instance.(*Phantom); !ok {
return fmt.Errorf("Not support Foreach:%s", bd.instance.GetName())
}
count := uint(0)
cost := time.Now()
cur := start
for count < depth && cur != nil {
if cur.GetID() != start.GetID() {
ret, err := fn(cur)
if err != nil {
return err
}
if ret {
count++
if count >= depth {
break
}
}
}
if cur.GetID() == 0 {
break
}
das := cur.(*PhantomBlock).GetDiffAnticoneList(filter)
if len(das) > 0 {
for i := len(das) - 1; i >= 0; i-- {
if das[i] == MaxId {
continue
}
block := bd.GetBlockById(das[i])
if block == nil {
return fmt.Errorf("No block:id=%d", das[i])
}
pBlock := block.(*PhantomBlock)
ret, err := fn(pBlock)
if err != nil {
return err
}
if ret {
count++
}
}
}

mp := bd.GetBlockById(cur.GetMainParent())
if mp == nil {
return fmt.Errorf("No block:id=%d", cur.GetMainParent())
}
cur = mp
}
if count == 0 {
return nil
}
log.Trace("Foreach dag blocks", "count", count, "depth", depth, "time", time.Since(cost))
return nil
}
29 changes: 29 additions & 0 deletions meerdag/pantomblock.go
Original file line number Diff line number Diff line change
Expand Up @@ -162,6 +162,35 @@ func (pb *PhantomBlock) GetRedDiffAnticone() *IdSet {
return pb.redDiffAnticone
}

func (pb *PhantomBlock) GetDiffAnticoneList(filterType FilterType) []uint {
if pb.GetDiffAnticoneSize() <= 0 {
return nil
}
list := []uint{}
for i := 0; i < pb.GetDiffAnticoneSize(); i++ {
list = append(list, MaxId)
}
if filterType == Blue ||
filterType == All {
if pb.GetBlueDiffAnticoneSize() > 0 {
for k, v := range pb.GetBlueDiffAnticone().GetMap() {
idx := v.(uint) - 1
list[idx] = k
}
}
}
if filterType == Red ||
filterType == All {
if pb.GetRedDiffAnticoneSize() > 0 {
for k, v := range pb.GetRedDiffAnticone().GetMap() {
idx := v.(uint) - 1
list[idx] = k
}
}
}
return list
}

func (pb *PhantomBlock) GetBlueDiffAnticoneSize() int {
if pb.blueDiffAnticone == nil {
return 0
Expand Down
87 changes: 87 additions & 0 deletions meerdag/test/phantom_test.go
Original file line number Diff line number Diff line change
Expand Up @@ -456,3 +456,90 @@ func checkLoad(t *testing.T) {
t.Fatal(err)
}
}

func Test_ForeachFig1(t *testing.T) {
ibd := InitBlockDAG(meerdag.PHANTOM, "PH_fig1-blocks")
if ibd == nil {
t.FailNow()
}
ph := ibd.(*meerdag.Phantom)
order := []uint{bd.GetMainChainTip().GetID()}

ph.UpdateVirtualBlockOrder()

err := bd.Foreach(bd.GetMainChainTip(), meerdag.MaxId, meerdag.All, func(block meerdag.IBlock) (bool, error) {
t.Logf("block id:%d hash:%s order:%d", block.GetID(), block.GetHash().String(), block.GetOrder())
order = append(order, block.GetID())
return true, nil
})
if err != nil {
t.Fatal(err)
}
order = reverseBlockList(order)
target := changeToIDList(testData.PH_OrderFig1.Output)
for i := 0; i < len(order); i++ {
if order[i] != target[i] {
t.FailNow()
}
}
fmt.Printf("The Fig.1 Order from mainTip: ")
printBlockChainTag(order)
}

func Test_ForeachFig2(t *testing.T) {
ibd := InitBlockDAG(meerdag.PHANTOM, "PH_fig2-blocks")
if ibd == nil {
t.FailNow()
}
ph := ibd.(*meerdag.Phantom)
order := []uint{bd.GetMainChainTip().GetID()}

ph.UpdateVirtualBlockOrder()

err := bd.Foreach(bd.GetMainChainTip(), meerdag.MaxId, meerdag.All, func(block meerdag.IBlock) (bool, error) {
t.Logf("block id:%d hash:%s order:%d", block.GetID(), block.GetHash().String(), block.GetOrder())
order = append(order, block.GetID())
return true, nil
})
if err != nil {
t.Fatal(err)
}
order = reverseBlockList(order)
target := changeToIDList(testData.PH_OrderFig2.Output)
for i := 0; i < len(order); i++ {
if order[i] != target[i] {
t.FailNow()
}
}
fmt.Printf("The Fig.1 Order from mainTip: ")
printBlockChainTag(order)
}

func Test_ForeachFig4(t *testing.T) {
ibd := InitBlockDAG(meerdag.PHANTOM, "PH_fig4-blocks")
if ibd == nil {
t.FailNow()
}
ph := ibd.(*meerdag.Phantom)
order := []uint{bd.GetMainChainTip().GetID()}

ph.UpdateVirtualBlockOrder()

err := bd.Foreach(bd.GetMainChainTip(), meerdag.MaxId, meerdag.All, func(block meerdag.IBlock) (bool, error) {
t.Logf("block id:%d hash:%s order:%d", block.GetID(), block.GetHash().String(), block.GetOrder())
order = append(order, block.GetID())
return true, nil
})
if err != nil {
t.Fatal(err)
}
order = reverseBlockList(order)
target := changeToIDList(testData.PH_OrderFig4.Output)
for i := 0; i < len(order); i++ {
if order[i] != target[i] {
t.FailNow()
}
}
fmt.Printf("The Fig.1 Order from mainTip: ")
printBlockChainTag(order)
}
Loading