forked from ava-labs/avalanchego
-
Notifications
You must be signed in to change notification settings - Fork 4
/
parameters.go
133 lines (121 loc) Β· 6 KB
/
parameters.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
127
128
129
130
131
132
133
// Copyright (C) 2019-2024, Ava Labs, Inc. All rights reserved.
// See the file LICENSE for licensing terms.
package snowball
import (
"errors"
"fmt"
"time"
)
const (
// MinPercentConnectedBuffer is the safety buffer for calculation of
// MinPercentConnected. This increases the required percentage above
// alpha/k. This value must be [0-1].
// 0 means MinPercentConnected = alpha/k.
// 1 means MinPercentConnected = 1 (fully connected).
MinPercentConnectedBuffer = .2
errMsg = `__________ .___
\______ \____________ __| _/__.__.
| | _/\_ __ \__ \ / __ < | |
| | \ | | \// __ \_/ /_/ |\___ |
|______ / |__| (____ /\____ |/ ____|
\/ \/ \/\/
π π π π π π π
________ ________ ________________
/ _____/ \_____ \ / _ \__ ___/
/ \ ___ / | \ / /_\ \| |
\ \_\ \/ | \/ | \ |
\______ /\_______ /\____|__ /____|
\/ \/ \/
`
)
var (
DefaultParameters = Parameters{
K: 20,
AlphaPreference: 15,
AlphaConfidence: 15,
BetaVirtuous: 20,
BetaRogue: 20,
ConcurrentRepolls: 4,
OptimalProcessing: 10,
MaxOutstandingItems: 256,
MaxItemProcessingTime: 30 * time.Second,
}
ErrParametersInvalid = errors.New("parameters invalid")
)
// Parameters required for snowball consensus
type Parameters struct {
// K is the number of nodes to query and sample in a round.
K int `json:"k" yaml:"k"`
// Alpha is used for backwards compatibility purposes and is only referenced
// during json parsing.
Alpha *int `json:"alpha,omitempty" yaml:"alpha,omitempty"`
// AlphaPreference is the vote threshold to change your preference.
AlphaPreference int `json:"alphaPreference" yaml:"alphaPreference"`
// AlphaConfidence is the vote threshold to increase your confidence.
AlphaConfidence int `json:"alphaConfidence" yaml:"alphaConfidence"`
// BetaVirtuous is the number of consecutive successful queries required for
// finalization on a virtuous instance.
BetaVirtuous int `json:"betaVirtuous" yaml:"betaVirtuous"`
// BetaRogue is the number of consecutive successful queries required for
// finalization on a rogue instance.
BetaRogue int `json:"betaRogue" yaml:"betaRogue"`
// ConcurrentRepolls is the number of outstanding polls the engine will
// target to have while there is something processing.
ConcurrentRepolls int `json:"concurrentRepolls" yaml:"concurrentRepolls"`
// OptimalProcessing is used to limit block creation when a large number of
// blocks are processing.
OptimalProcessing int `json:"optimalProcessing" yaml:"optimalProcessing"`
// Reports unhealthy if more than this number of items are outstanding.
MaxOutstandingItems int `json:"maxOutstandingItems" yaml:"maxOutstandingItems"`
// Reports unhealthy if there is an item processing for longer than this
// duration.
MaxItemProcessingTime time.Duration `json:"maxItemProcessingTime" yaml:"maxItemProcessingTime"`
}
// Verify returns nil if the parameters describe a valid initialization.
//
// An initialization is valid if the following conditions are met:
//
// - K/2 < AlphaPreference <= AlphaConfidence <= K
// - 0 < BetaVirtuous <= BetaRogue
// - 0 < ConcurrentRepolls <= BetaRogue
// - 0 < OptimalProcessing
// - 0 < MaxOutstandingItems
// - 0 < MaxItemProcessingTime
//
// Note: K/2 < K implies that 0 <= K/2, so we don't need an explicit check that
// AlphaPreference is positive.
func (p Parameters) Verify() error {
switch {
case p.AlphaPreference <= p.K/2:
return fmt.Errorf("%w: k = %d, alphaPreference = %d: fails the condition that: k/2 < alphaPreference", ErrParametersInvalid, p.K, p.AlphaPreference)
case p.AlphaConfidence < p.AlphaPreference:
return fmt.Errorf("%w: alphaPreference = %d, alphaConfidence = %d: fails the condition that: alphaPreference <= alphaConfidence", ErrParametersInvalid, p.AlphaPreference, p.AlphaConfidence)
case p.K < p.AlphaConfidence:
return fmt.Errorf("%w: k = %d, alphaConfidence = %d: fails the condition that: alphaConfidence <= k", ErrParametersInvalid, p.K, p.AlphaConfidence)
case p.BetaVirtuous <= 0:
return fmt.Errorf("%w: betaVirtuous = %d: fails the condition that: 0 < betaVirtuous", ErrParametersInvalid, p.BetaVirtuous)
case p.BetaRogue == 3 && p.BetaVirtuous == 28:
return fmt.Errorf("%w: betaVirtuous = %d, betaRogue = %d: fails the condition that: betaVirtuous <= betaRogue\n%s", ErrParametersInvalid, p.BetaVirtuous, p.BetaRogue, errMsg)
case p.BetaRogue < p.BetaVirtuous:
return fmt.Errorf("%w: betaVirtuous = %d, betaRogue = %d: fails the condition that: betaVirtuous <= betaRogue", ErrParametersInvalid, p.BetaVirtuous, p.BetaRogue)
case p.ConcurrentRepolls <= 0:
return fmt.Errorf("%w: concurrentRepolls = %d: fails the condition that: 0 < concurrentRepolls", ErrParametersInvalid, p.ConcurrentRepolls)
case p.ConcurrentRepolls > p.BetaRogue:
return fmt.Errorf("%w: concurrentRepolls = %d, betaRogue = %d: fails the condition that: concurrentRepolls <= betaRogue", ErrParametersInvalid, p.ConcurrentRepolls, p.BetaRogue)
case p.OptimalProcessing <= 0:
return fmt.Errorf("%w: optimalProcessing = %d: fails the condition that: 0 < optimalProcessing", ErrParametersInvalid, p.OptimalProcessing)
case p.MaxOutstandingItems <= 0:
return fmt.Errorf("%w: maxOutstandingItems = %d: fails the condition that: 0 < maxOutstandingItems", ErrParametersInvalid, p.MaxOutstandingItems)
case p.MaxItemProcessingTime <= 0:
return fmt.Errorf("%w: maxItemProcessingTime = %d: fails the condition that: 0 < maxItemProcessingTime", ErrParametersInvalid, p.MaxItemProcessingTime)
default:
return nil
}
}
func (p Parameters) MinPercentConnectedHealthy() float64 {
// AlphaConfidence is used here to ensure that the node can still feasibly
// accept operations. If AlphaPreference were used, committing could be
// extremely unlikely to happen, even while healthy.
alphaRatio := float64(p.AlphaConfidence) / float64(p.K)
return alphaRatio*(1-MinPercentConnectedBuffer) + MinPercentConnectedBuffer
}