Skip to content

Commit

Permalink
Merge pull request #581 from lochjin/dev1.2
Browse files Browse the repository at this point in the history
MeerDAG:support block foreach
  • Loading branch information
dindinw authored Dec 8, 2023
2 parents 6e1b63e + 7544fd8 commit 1a155f5
Show file tree
Hide file tree
Showing 6 changed files with 214 additions and 2 deletions.
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)
}

0 comments on commit 1a155f5

Please sign in to comment.