-
Notifications
You must be signed in to change notification settings - Fork 14
/
consensus_cfg.go
126 lines (100 loc) · 3.14 KB
/
consensus_cfg.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
124
125
126
package pbft
import (
"log"
"os"
"time"
"go.opentelemetry.io/otel/trace"
"github.com/0xPolygon/pbft-consensus/stats"
)
const (
defaultTimeout = 2 * time.Second
maxTimeout = 300 * time.Second
maxTimeoutExponent = 8
)
type RoundTimeout func(round uint64) <-chan time.Time
type StatsCallback func(stats.Stats)
type ConfigOption func(*Config)
func WithLogger(l Logger) ConfigOption {
return func(c *Config) {
c.Logger = l
}
}
func WithTracer(t trace.Tracer) ConfigOption {
return func(c *Config) {
c.Tracer = t
}
}
func WithRoundTimeout(roundTimeout RoundTimeout) ConfigOption {
return func(c *Config) {
if roundTimeout != nil {
c.RoundTimeout = roundTimeout
}
}
}
func WithNotifier(notifier StateNotifier) ConfigOption {
return func(c *Config) {
if notifier != nil {
c.Notifier = notifier
}
}
}
type Config struct {
// ProposalTimeout is the time to wait for the proposal
// from the validator. It defaults to Timeout
ProposalTimeout time.Duration
// Timeout is the time to wait for validation and
// round change messages
Timeout time.Duration
// Logger is the logger to output info
Logger Logger
// Tracer is the OpenTelemetry tracer to log traces
Tracer trace.Tracer
// RoundTimeout is a function that calculates timeout based on a round number
RoundTimeout RoundTimeout
// Notifier is a reference to the struct which encapsulates handling messages and timeouts
Notifier StateNotifier
StatsCallback StatsCallback
}
func DefaultConfig() *Config {
return &Config{
Timeout: defaultTimeout,
ProposalTimeout: defaultTimeout,
Logger: log.New(os.Stderr, "", log.LstdFlags),
Tracer: trace.NewNoopTracerProvider().Tracer(""),
RoundTimeout: exponentialTimeout,
Notifier: &DefaultStateNotifier{},
}
}
func (c *Config) ApplyOps(opts ...ConfigOption) {
for _, opt := range opts {
opt(c)
}
}
// exponentialTimeout is the default RoundTimeout function
func exponentialTimeout(round uint64) <-chan time.Time {
return time.NewTimer(exponentialTimeoutDuration(round)).C
}
// --- package-level helper functions ---
// exponentialTimeout calculates the timeout duration depending on the current round.
// Round acts as an exponent when determining timeout (2^round).
func exponentialTimeoutDuration(round uint64) time.Duration {
timeout := defaultTimeout
// limit exponent to be in range of maxTimeout (<=8) otherwise use maxTimeout
// this prevents calculating timeout that is greater than maxTimeout and
// possible overflow for calculating timeout for rounds >33 since duration is in nanoseconds stored in int64
if round <= maxTimeoutExponent {
timeout += time.Duration(1<<round) * time.Second
} else {
timeout = maxTimeout
}
return timeout
}
// DefaultStateNotifier is a null object implementation of StateNotifier interface
type DefaultStateNotifier struct {
}
// HandleTimeout implements StateNotifier interface
func (d *DefaultStateNotifier) HandleTimeout(NodeID, MsgType, *View) {}
// ReadNextMessage is an implementation of StateNotifier interface
func (d *DefaultStateNotifier) ReadNextMessage(p *Pbft) (*MessageReq, []*MessageReq) {
return p.ReadMessageWithDiscards()
}