This repository has been archived by the owner on Jun 17, 2022. It is now read-only.
-
Notifications
You must be signed in to change notification settings - Fork 72
/
epoch.go
123 lines (102 loc) · 2.99 KB
/
epoch.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
101
102
103
104
105
106
107
108
109
110
111
112
113
114
115
116
117
118
119
120
121
122
123
package poset
import (
"fmt"
"sync/atomic"
"github.com/ethereum/go-ethereum/common"
"github.com/ethereum/go-ethereum/rlp"
"golang.org/x/crypto/sha3"
"github.com/Fantom-foundation/go-lachesis/src/hash"
"github.com/Fantom-foundation/go-lachesis/src/inter"
"github.com/Fantom-foundation/go-lachesis/src/inter/idx"
"github.com/Fantom-foundation/go-lachesis/src/inter/pos"
)
const (
// EpochLen is a count of frames per epoch.
EpochLen idx.Frame = 100
firstFrame = idx.Frame(1)
firstEpoch = idx.Epoch(1)
)
// state of previous Epoch
type GenesisState struct {
Epoch idx.Epoch
Time inter.Timestamp // consensus time of the last atropos
LastAtropos hash.Event
StateHash common.Hash // hash of txs state
}
func (g *GenesisState) Hash() common.Hash {
hasher := sha3.New256()
if err := rlp.Encode(hasher, g); err != nil {
panic(err)
}
return hash.FromBytes(hasher.Sum(nil))
}
func (g *GenesisState) EpochName() string {
return fmt.Sprintf("epoch%d", g.Epoch)
}
type epoch struct {
// stored values
// these values change only after a change of epoch
EpochN idx.Epoch
PrevEpoch GenesisState
Members pos.Members
}
func (p *Poset) loadEpoch() {
p.epoch = *p.store.GetEpoch()
}
func (p *Poset) nextEpoch(atropos hash.Event) {
// new PrevEpoch state
p.PrevEpoch.Time = p.LastConsensusTime
p.PrevEpoch.Epoch = p.EpochN
p.PrevEpoch.LastAtropos = atropos
p.PrevEpoch.StateHash = p.checkpoint.StateHash
// new members list
p.Members = p.NextMembers.Top()
p.NextMembers = p.Members.Copy()
// reset internal epoch DB
p.store.recreateEpochDb()
// reset election & vectorindex
p.seeVec.Reset(p.Members, p.store.epochTable.VectorIndex) // this DB is pruned after .pruneTempDb()
p.election.Reset(p.Members, firstFrame)
p.LastDecidedFrame = 0
// move to new epoch
p.EpochN++
// commit
p.store.SetEpoch(&p.epoch)
p.saveCheckpoint()
}
// GetEpoch returns current epoch num to 3rd party.
func (p *Poset) GetEpoch() idx.Epoch {
return idx.Epoch(atomic.LoadUint32((*uint32)(&p.EpochN)))
}
// EpochMembers returns members of current epoch.
func (p *Poset) GetMembers() pos.Members {
return p.Members.Copy()
}
// rootForklessSeeRoot returns hash of root B, if root A strongly sees root B.
// Due to a fork, there may be many roots B with the same slot,
// but strongly seen may be only one of them (if no more than 1/3n are Byzantine), with a specific hash.
func (p *Poset) rootForklessSeeRoot(a hash.Event, bNode common.Address, bFrame idx.Frame) *hash.Event {
var bHash *hash.Event
p.store.ForEachRootFrom(bFrame, bNode, func(f idx.Frame, from common.Address, b hash.Event) bool {
if f != bFrame {
p.Log.Crit("frame mismatch")
}
if from != bNode {
p.Log.Crit("node mismatch")
}
if p.seeVec.ForklessSee(a, b) {
bHash = &b
return false
}
return true
})
return bHash
}
// GetGenesisHash is a genesis getter.
func (p *Poset) GetGenesisHash() common.Hash {
epoch := p.store.GetGenesis()
if epoch == nil {
p.Log.Crit("no genesis found")
}
return epoch.PrevEpoch.Hash()
}