-
Notifications
You must be signed in to change notification settings - Fork 176
/
incorporated_result_seals.go
109 lines (92 loc) · 3.78 KB
/
incorporated_result_seals.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
package consensus
import (
"github.com/rs/zerolog/log"
"github.com/onflow/flow-go/model/flow"
"github.com/onflow/flow-go/module/mempool"
"github.com/onflow/flow-go/storage"
"github.com/onflow/flow-go/utils/logging"
)
// IncorporatedResultSeals implements the incorporated result seals memory pool
// of the consensus nodes.
// ATTENTION: this is a temporary wrapper for `mempool.IncorporatedResultSeals`
// to enforce that there are at least 2 receipts from _different_ ENs
// committing to the same incorporated result.
// This wrapper should only be used with `Core`.
type IncorporatedResultSeals struct {
seals mempool.IncorporatedResultSeals // seals mempool that wrapped
receiptsDB storage.ExecutionReceipts // receipts DB to decide if we have multiple receipts for same result
}
// NewIncorporatedResultSeals creates a mempool for the incorporated result seals
func NewIncorporatedResultSeals(mempool mempool.IncorporatedResultSeals, receiptsDB storage.ExecutionReceipts) *IncorporatedResultSeals {
return &IncorporatedResultSeals{
seals: mempool,
receiptsDB: receiptsDB,
}
}
// Add adds an IncorporatedResultSeal to the mempool
func (ir *IncorporatedResultSeals) Add(seal *flow.IncorporatedResultSeal) (bool, error) {
return ir.seals.Add(seal)
}
// All returns all the items in the mempool
func (ir *IncorporatedResultSeals) All() []*flow.IncorporatedResultSeal {
unfiltered := ir.seals.All()
seals := make([]*flow.IncorporatedResultSeal, 0, len(unfiltered))
for _, s := range unfiltered {
if ir.resultHasMultipleReceipts(s.IncorporatedResult) {
seals = append(seals, s)
}
}
return seals
}
// resultHasMultipleReceipts implements an additional _temporary_ safety measure:
// only consider incorporatedResult sealable if there are at AT LEAST 2 RECEIPTS
// from _different_ ENs committing to the result.
func (ir *IncorporatedResultSeals) resultHasMultipleReceipts(incorporatedResult *flow.IncorporatedResult) bool {
blockID := incorporatedResult.Result.BlockID // block that was computed
resultID := incorporatedResult.Result.ID()
// get all receipts that are known for the block
receipts, err := ir.receiptsDB.ByBlockID(blockID)
if err != nil {
log.Error().Err(err).
Hex("block_id", logging.ID(blockID)).
Msg("could not get receipts by block ID")
return false
}
// Index receipts for given incorporatedResult by their executor. In case
// there are multiple receipts from the same executor, we keep the last one.
receiptsForIncorporatedResults := receipts.GroupByResultID().GetGroup(resultID)
return receiptsForIncorporatedResults.GroupByExecutorID().NumberGroups() >= 2
}
// ByID gets an IncorporatedResultSeal by IncorporatedResult ID
func (ir *IncorporatedResultSeals) ByID(id flow.Identifier) (*flow.IncorporatedResultSeal, bool) {
seal, ok := ir.seals.ByID(id)
if !ok {
return nil, false
}
// _temporary_ measure, return only receipts that have multiple commitments from different ENs.
if !ir.resultHasMultipleReceipts(seal.IncorporatedResult) {
return nil, false
}
return seal, true
}
// Limit returns the size limit of the mempool
func (ir *IncorporatedResultSeals) Limit() uint {
return ir.seals.Limit()
}
// Remove removes an IncorporatedResultSeal from the mempool
func (ir *IncorporatedResultSeals) Remove(id flow.Identifier) bool {
return ir.seals.Remove(id)
}
// Size returns the number of items in the mempool
func (ir *IncorporatedResultSeals) Size() uint {
return ir.seals.Size()
}
// Clear removes all entities from the pool.
func (ir *IncorporatedResultSeals) Clear() {
ir.seals.Clear()
}
// PruneUpToHeight remove all seals for blocks whose height is strictly
// smaller that height. Note: seals for blocks at height are retained.
func (ir *IncorporatedResultSeals) PruneUpToHeight(height uint64) error {
return ir.seals.PruneUpToHeight(height)
}