-
Notifications
You must be signed in to change notification settings - Fork 0
/
store_roots.go
93 lines (80 loc) · 2.32 KB
/
store_roots.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
package abft
import (
"bytes"
"fmt"
"github.com/Deepchain-foundation/lachesis-base/abft/election"
"github.com/Deepchain-foundation/lachesis-base/hash"
"github.com/Deepchain-foundation/lachesis-base/inter/dag"
"github.com/Deepchain-foundation/lachesis-base/inter/idx"
)
func rootRecordKey(r *election.RootAndSlot) []byte {
key := bytes.Buffer{}
key.Write(r.Slot.Frame.Bytes())
key.Write(r.Slot.Validator.Bytes())
key.Write(r.ID.Bytes())
return key.Bytes()
}
// AddRoot stores the new root
// Not safe for concurrent use due to the complex mutable cache!
func (s *Store) AddRoot(selfParentFrame idx.Frame, root dag.Event) {
for f := selfParentFrame + 1; f <= root.Frame(); f++ {
s.addRoot(root, f)
}
}
func (s *Store) addRoot(root dag.Event, frame idx.Frame) {
r := election.RootAndSlot{
Slot: election.Slot{
Frame: frame,
Validator: root.Creator(),
},
ID: root.ID(),
}
if err := s.epochTable.Roots.Put(rootRecordKey(&r), []byte{}); err != nil {
s.crit(err)
}
// Add to cache.
if c, ok := s.cache.FrameRoots.Get(frame); ok {
rr := c.([]election.RootAndSlot)
rr = append(rr, r)
s.cache.FrameRoots.Add(frame, rr, uint(len(rr)))
}
}
const (
frameSize = 4
validatorIDSize = 4
eventIDSize = 32
)
// GetFrameRoots returns all the roots in the specified frame
// Not safe for concurrent use due to the complex mutable cache!
func (s *Store) GetFrameRoots(f idx.Frame) []election.RootAndSlot {
// get data from LRU cache first.
if rr, ok := s.cache.FrameRoots.Get(f); ok {
return rr.([]election.RootAndSlot)
}
rr := make([]election.RootAndSlot, 0, 100)
it := s.epochTable.Roots.NewIterator(f.Bytes(), nil)
defer it.Release()
for it.Next() {
key := it.Key()
if len(key) != frameSize+validatorIDSize+eventIDSize {
s.crit(fmt.Errorf("roots table: incorrect key len=%d", len(key)))
}
r := election.RootAndSlot{
Slot: election.Slot{
Frame: idx.BytesToFrame(key[:frameSize]),
Validator: idx.BytesToValidatorID(key[frameSize : frameSize+validatorIDSize]),
},
ID: hash.BytesToEvent(key[frameSize+validatorIDSize:]),
}
if r.Slot.Frame != f {
s.crit(fmt.Errorf("roots table: invalid frame=%d, expected=%d", r.Slot.Frame, f))
}
rr = append(rr, r)
}
if it.Error() != nil {
s.crit(it.Error())
}
// Add to cache.
s.cache.FrameRoots.Add(f, rr, uint(len(rr)))
return rr
}