-
Notifications
You must be signed in to change notification settings - Fork 199
/
shardForkDetector.go
100 lines (83 loc) · 2.53 KB
/
shardForkDetector.go
1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
17
18
19
20
21
22
23
24
25
26
27
28
29
30
31
32
33
34
35
36
37
38
39
40
41
42
43
44
45
46
47
48
49
50
51
52
53
54
55
56
57
58
59
60
61
62
63
64
65
66
67
68
69
70
71
72
73
74
75
76
77
78
79
80
81
82
83
84
85
86
87
88
89
90
91
92
93
94
95
96
97
98
99
100
package sync
import (
"github.com/ElrondNetwork/elrond-go/consensus"
"github.com/ElrondNetwork/elrond-go/data"
"github.com/ElrondNetwork/elrond-go/process"
)
// shardForkDetector implements the shard fork detector mechanism
type shardForkDetector struct {
*baseForkDetector
}
// NewShardForkDetector method creates a new shardForkDetector object
func NewShardForkDetector(rounder consensus.Rounder) (*shardForkDetector, error) {
if rounder == nil || rounder.IsInterfaceNil() {
return nil, process.ErrNilRounder
}
bfd := &baseForkDetector{
rounder: rounder,
}
bfd.headers = make(map[uint64][]*headerInfo)
checkpoint := &checkpointInfo{}
bfd.setFinalCheckpoint(checkpoint)
bfd.addCheckpoint(checkpoint)
sfd := shardForkDetector{
baseForkDetector: bfd,
}
return &sfd, nil
}
// AddHeader method adds a new header to headers map
func (sfd *shardForkDetector) AddHeader(
header data.HeaderHandler,
headerHash []byte,
state process.BlockHeaderState,
finalHeaders []data.HeaderHandler,
finalHeadersHashes [][]byte,
) error {
if header == nil || header.IsInterfaceNil() {
return ErrNilHeader
}
if headerHash == nil {
return ErrNilHash
}
err := sfd.checkBlockBasicValidity(header, state)
if err != nil {
return err
}
err = sfd.shouldAddBlockInForkDetector(header, state, process.ShardBlockFinality)
if err != nil {
return err
}
if state == process.BHProcessed {
sfd.addFinalHeaders(finalHeaders, finalHeadersHashes)
sfd.addCheckpoint(&checkpointInfo{nonce: header.GetNonce(), round: header.GetRound()})
sfd.removePastOrInvalidRecords()
}
sfd.append(&headerInfo{
nonce: header.GetNonce(),
round: header.GetRound(),
hash: headerHash,
state: state,
})
probableHighestNonce := sfd.computeProbableHighestNonce()
sfd.setLastBlockRound(uint64(sfd.rounder.Index()))
sfd.setProbableHighestNonce(probableHighestNonce)
return nil
}
func (sfd *shardForkDetector) addFinalHeaders(finalHeaders []data.HeaderHandler, finalHeadersHashes [][]byte) {
finalCheckpointWasSet := false
for i := 0; i < len(finalHeaders); i++ {
isFinalHeaderNonceHigherThanGenesis := finalHeaders[i].GetNonce() > process.GenesisBlockNonce
if isFinalHeaderNonceHigherThanGenesis {
if !finalCheckpointWasSet {
sfd.setFinalCheckpoint(&checkpointInfo{nonce: finalHeaders[i].GetNonce(), round: finalHeaders[i].GetRound()})
finalCheckpointWasSet = true
}
sfd.append(&headerInfo{
nonce: finalHeaders[i].GetNonce(),
round: finalHeaders[i].GetRound(),
hash: finalHeadersHashes[i],
state: process.BHNotarized,
})
}
}
}