Skip to content

Commit 84a8f24

Browse files
committed
add cross header settlement logic and corresponding tests
1 parent 062a592 commit 84a8f24

2 files changed

Lines changed: 138 additions & 0 deletions

File tree

Lines changed: 50 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -0,0 +1,50 @@
1+
package track
2+
3+
import (
4+
"bytes"
5+
6+
"github.com/multiversx/mx-chain-core-go/core/check"
7+
"github.com/multiversx/mx-chain-core-go/data"
8+
)
9+
10+
// IsSettledCrossHeader returns true if the header can no longer change: a proofed child extending
11+
// it is known locally, from the tracked headers or from the headers pool
12+
func (bbt *baseBlockTrack) IsSettledCrossHeader(header data.HeaderHandler, headerHash []byte) bool {
13+
if check.IfNil(header) || len(headerHash) == 0 {
14+
return false
15+
}
16+
17+
shardID := header.GetShardID()
18+
childNonce := header.GetNonce() + 1
19+
20+
trackedChildren, trackedChildrenHashes := bbt.GetTrackedHeadersWithNonce(shardID, childNonce)
21+
if bbt.holdProofedChild(trackedChildren, trackedChildrenHashes, headerHash, shardID) {
22+
return true
23+
}
24+
25+
pooledChildren, pooledChildrenHashes, err := bbt.headersPool.GetHeadersByNonceAndShardId(childNonce, shardID)
26+
if err != nil {
27+
return false
28+
}
29+
30+
return bbt.holdProofedChild(pooledChildren, pooledChildrenHashes, headerHash, shardID)
31+
}
32+
33+
func (bbt *baseBlockTrack) holdProofedChild(
34+
children []data.HeaderHandler,
35+
childrenHashes [][]byte,
36+
parentHash []byte,
37+
shardID uint32,
38+
) bool {
39+
for i, child := range children {
40+
if check.IfNil(child) || !bytes.Equal(child.GetPrevHash(), parentHash) {
41+
continue
42+
}
43+
44+
if bbt.proofsPool.HasProof(shardID, childrenHashes[i]) {
45+
return true
46+
}
47+
}
48+
49+
return false
50+
}
Lines changed: 88 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -0,0 +1,88 @@
1+
package track_test
2+
3+
import (
4+
"testing"
5+
6+
"github.com/multiversx/mx-chain-core-go/data/block"
7+
"github.com/stretchr/testify/require"
8+
9+
"github.com/multiversx/mx-chain-go/process/track"
10+
)
11+
12+
func TestBaseBlockTrack_IsSettledCrossHeader(t *testing.T) {
13+
t.Parallel()
14+
15+
headerHash := []byte("headerHash")
16+
header := &block.Header{Nonce: 5, Round: 10}
17+
18+
t.Run("nil header or empty hash returns false", func(t *testing.T) {
19+
t.Parallel()
20+
21+
args, _, _ := createProofPullTrackerScaffold(true)
22+
sbt, err := track.NewShardBlockTrack(args)
23+
require.Nil(t, err)
24+
_ = sbt.Close()
25+
26+
require.False(t, sbt.IsSettledCrossHeader(nil, headerHash))
27+
require.False(t, sbt.IsSettledCrossHeader(header, nil))
28+
})
29+
30+
t.Run("no child known returns false", func(t *testing.T) {
31+
t.Parallel()
32+
33+
args, _, _ := createProofPullTrackerScaffold(true)
34+
sbt, err := track.NewShardBlockTrack(args)
35+
require.Nil(t, err)
36+
_ = sbt.Close()
37+
38+
require.False(t, sbt.IsSettledCrossHeader(header, headerHash))
39+
})
40+
41+
t.Run("tracked proofed child extending the header settles it", func(t *testing.T) {
42+
t.Parallel()
43+
44+
args, _, _ := createProofPullTrackerScaffold(true)
45+
sbt, err := track.NewShardBlockTrack(args)
46+
require.Nil(t, err)
47+
_ = sbt.Close()
48+
49+
child := &block.Header{Nonce: 6, Round: 11, PrevHash: headerHash}
50+
sbt.AddTrackedHeader(child, []byte("childHash"))
51+
52+
// no proof for the child yet
53+
require.False(t, sbt.IsSettledCrossHeader(header, headerHash))
54+
55+
_ = args.PoolsHolder.Proofs().AddProof(&block.HeaderProof{HeaderHash: []byte("childHash"), HeaderNonce: 6, HeaderRound: 11})
56+
require.True(t, sbt.IsSettledCrossHeader(header, headerHash))
57+
})
58+
59+
t.Run("proofed child of a sibling does not settle the header", func(t *testing.T) {
60+
t.Parallel()
61+
62+
args, _, _ := createProofPullTrackerScaffold(true)
63+
sbt, err := track.NewShardBlockTrack(args)
64+
require.Nil(t, err)
65+
_ = sbt.Close()
66+
67+
siblingChild := &block.Header{Nonce: 6, Round: 11, PrevHash: []byte("siblingHash")}
68+
sbt.AddTrackedHeader(siblingChild, []byte("siblingChildHash"))
69+
_ = args.PoolsHolder.Proofs().AddProof(&block.HeaderProof{HeaderHash: []byte("siblingChildHash"), HeaderNonce: 6, HeaderRound: 11})
70+
71+
require.False(t, sbt.IsSettledCrossHeader(header, headerHash))
72+
})
73+
74+
t.Run("proofed child known only from the headers pool settles it", func(t *testing.T) {
75+
t.Parallel()
76+
77+
args, _, _ := createProofPullTrackerScaffold(true)
78+
sbt, err := track.NewShardBlockTrack(args)
79+
require.Nil(t, err)
80+
_ = sbt.Close()
81+
82+
child := &block.Header{Nonce: 6, Round: 11, PrevHash: headerHash}
83+
args.PoolsHolder.Headers().AddHeader([]byte("childHash"), child)
84+
_ = args.PoolsHolder.Proofs().AddProof(&block.HeaderProof{HeaderHash: []byte("childHash"), HeaderNonce: 6, HeaderRound: 11})
85+
86+
require.True(t, sbt.IsSettledCrossHeader(header, headerHash))
87+
})
88+
}

0 commit comments

Comments
 (0)