-
Notifications
You must be signed in to change notification settings - Fork 5
/
config.go
344 lines (310 loc) · 9.15 KB
/
config.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
134
135
136
137
138
139
140
141
142
143
144
145
146
147
148
149
150
151
152
153
154
155
156
157
158
159
160
161
162
163
164
165
166
167
168
169
170
171
172
173
174
175
176
177
178
179
180
181
182
183
184
185
186
187
188
189
190
191
192
193
194
195
196
197
198
199
200
201
202
203
204
205
206
207
208
209
210
211
212
213
214
215
216
217
218
219
220
221
222
223
224
225
226
227
228
229
230
231
232
233
234
235
236
237
238
239
240
241
242
243
244
245
246
247
248
249
250
251
252
253
254
255
256
257
258
259
260
261
262
263
264
265
266
267
268
269
270
271
272
273
274
275
276
277
278
279
280
281
282
283
284
285
286
287
288
289
290
291
292
293
294
295
296
297
298
299
300
301
302
303
304
305
306
307
308
309
310
311
312
313
314
315
316
317
318
319
320
321
322
323
324
325
326
327
328
329
330
331
332
333
334
335
336
337
338
339
340
341
342
343
344
package lib
import (
"errors"
"net"
"os"
"path"
"path/filepath"
"strconv"
"strings"
"time"
"github.com/BurntSushi/toml"
"github.com/ConsenSys/handel"
cf "github.com/ConsenSys/handel/bn256/cf"
golang "github.com/ConsenSys/handel/bn256/go"
"github.com/ConsenSys/handel/network"
"github.com/ConsenSys/handel/network/quic"
"github.com/ConsenSys/handel/network/udp"
"github.com/ConsenSys/handel/simul/monitor"
"github.com/go-kit/kit/log"
"github.com/go-kit/kit/log/level"
)
var resultsDir string
func init() {
currentDir, err := os.Getwd()
if err != nil {
panic(err)
}
resultsDir = path.Join(currentDir, "results")
os.MkdirAll(resultsDir, 0777)
}
// Message that will get signed
var Message = []byte("Everything that is beautiful and noble is the product of reason and calculation.")
// Config is read from a TOML encoded file and passed to Platform.Config and
// prepares the platform for specific system-wide configurations.
type Config struct {
// private fields do not get marshalled
configPath string
// which network should we use
// Valid value: "udp" (default)
Network string
// which "curve system" should we use
// Valid value: "bn256" (default)
Curve string
// which encoding should we use on the network
// valid value: "gob" (default)
Encoding string
// which allocator to use when experimenting failing nodes
// valid value: "round" (default) or "random"
Allocator string
// which is the port to send measurements to
MonitorPort int
// Debug forwards the debug output if set to != 0
Debug int
// which simulation are we running -
// valid values: "handel" (default) or "p2p/udp" or "p2p/libp2p"
Simulation string
// Maximum time to wait for the whole thing to finish
// string because of ugly format of TOML encoding ---
MaxTimeout string
// how many time should we repeat each experiment
Retrials int
// to which file should we write the results
ResultFile string
// config for each run
Runs []RunConfig
}
// RunConfig is the config holding parameters for a specific run. A platform can
// start multiple runs sequentially with different parameters each.
type RunConfig struct {
// How many nodes should we spin for this run
Nodes int
// threshold of signatures to wait for
Threshold int
// Number of failing nodes
Failing int
// Number of processes for this run
Processes int
// Handel items configurable - will be merged with defaults
Handel *HandelConfig
// extra for particular information for specific platform for examples
Extra map[string]string
}
// HandelConfig is a small config that will be converted to handel.Config during
// the simulation
type HandelConfig struct {
// Period of the periodic update loop
Period string
// Number of node do we contact for each periodic update
UpdateCount int
// Number of node do we contact when starting level + when finishing level
// XXX - maybe remove in the futur ! -
NodeCount int
// Timeout used to give to the LinearTimeout constructor
Timeout string
// UnsafeSleepTimeOnSigVerify
UnsafeSleepTimeOnSigVerify int
// which queue evaluator are we choosing
Evaluator string
}
// LoadConfig looks up the given file to unmarshal a TOML encoded Config.
func LoadConfig(path string) *Config {
c := new(Config)
_, err := toml.DecodeFile(path, c)
if err != nil {
panic(err)
}
if c.MonitorPort == 0 {
c.MonitorPort = monitor.DefaultSinkPort
}
if c.Simulation == "" {
c.Simulation = "handel"
}
c.configPath = path
return c
}
// WriteTo writes the config to the specified file path.
func (c *Config) WriteTo(path string) error {
file, err := os.Create(path)
defer file.Close()
if err != nil {
return err
}
enc := toml.NewEncoder(file)
return enc.Encode(c)
}
// Logger returns the logger set to the right verbosity with timestamp added
func (c *Config) Logger() handel.Logger {
var logger handel.Logger
if c.Debug != 0 {
logger = handel.NewKitLogger(level.AllowDebug())
} else {
logger = handel.NewKitLogger(level.AllowInfo())
}
//return logger.With("ts", log.DefaultTimestamp)
return logger.With("ts", log.TimestampFormat(time.Now, time.StampMilli))
}
// MaxNodes returns the maximum number of nodes to test
func (c *Config) MaxNodes() int {
max := 0
for _, rc := range c.Runs {
if max < rc.Nodes-rc.Failing {
max = rc.Nodes - rc.Failing
}
}
return max
}
// NewNetwork returns the network implementation designated by this config for this
// given identity
func (c *Config) NewNetwork(id handel.Identity) handel.Network {
if c.Network == "" {
c.Network = "udp"
}
netw, err := c.selectNetwork(id)
if err != nil {
panic(err)
}
return netw
}
func (c *Config) selectNetwork(id handel.Identity) (handel.Network, error) {
encoding := c.NewEncoding()
switch c.Network {
case "udp":
return udp.NewNetwork(id.Address(), encoding)
case "quic-test-insecure":
cfg := quic.NewInsecureTestConfig()
return quic.NewNetwork(id.Address(), encoding, cfg)
case "quic":
return nil, errors.New("quic implemented implemented only in test mode")
default:
return nil, errors.New("not implemented yet")
}
}
// NewEncoding returns the corresponding network encoding
func (c *Config) NewEncoding() network.Encoding {
newEnc := func() network.Encoding {
if c.Encoding == "" {
c.Encoding = "gob"
}
switch c.Encoding {
case "gob":
return network.NewGOBEncoding()
default:
panic("not implemented yet")
}
}
encoding := newEnc()
return network.NewCounterEncoding(encoding)
}
// NewConstructor returns a Constructor that is using the curve denoted by the
// curve field of the config. Valid input so far is "bn256".
func (c *Config) NewConstructor() Constructor {
if c.Curve == "" {
c.Curve = "bn256/cf"
}
switch c.Curve {
case "bn256":
fallthrough
case "bn256/cf":
return &SimulConstructor{cf.NewConstructor()}
case "bn256/go":
return &SimulConstructor{golang.NewConstructor()}
default:
panic("not implemented yet")
}
}
// NewAllocator returns the allocation determined by the "Allocator" string field
// of the config.
func (c *Config) NewAllocator() Allocator {
switch c.Allocator {
case "round":
return new(RoundRobin)
case "random":
return NewRoundRandomOffline()
default:
return new(RoundRobin)
}
}
// GetMaxTimeout returns the global maximum timeout specified in the config
func (c *Config) GetMaxTimeout() time.Duration {
dd, err := time.ParseDuration(c.MaxTimeout)
if err != nil {
panic(err)
}
return dd
}
// GetMonitorAddress returns a full IP address composed of the given address
// apprended with the port from the config.
func (c *Config) GetMonitorAddress(ip string) string {
return net.JoinHostPort(ip, strconv.Itoa(c.MonitorPort))
}
// GetCSVFile returns a name of the CSV file
func (c *Config) GetCSVFile() string {
csvName := strings.Replace(filepath.Base(c.configPath), ".toml", ".csv", 1)
return csvName
}
// GetResultsFile returns the path where to write the resulting csv file
func (c *Config) GetResultsFile() string {
return filepath.Join(resultsDir, c.GetCSVFile())
}
// GetResultsDir returns the directory where results will be written
func (c *Config) GetResultsDir() string {
return resultsDir
}
// GetBinaryPath returns the binary to compile
func (c *Config) GetBinaryPath() string {
base := "github.com/ConsenSys/handel/simul/"
simul := strings.ToLower(c.Simulation)
if strings.Contains(simul, "p2p") {
return filepath.Join(base, simul)
}
return filepath.Join(base, "node")
}
// GetThreshold returns the threshold to use for this run config - if 0 it
// returns the number of nodes
func (r *RunConfig) GetThreshold() int {
if r.Threshold == 0 {
return r.Nodes
}
return r.Threshold
}
// GetHandelConfig returns the config to pass down to handel instances
// Returns the default if not set
func (r *RunConfig) GetHandelConfig() *handel.Config {
ch := &handel.Config{}
if r.Handel == nil {
ch = handel.DefaultConfig(r.Nodes)
ch.Contributions = r.Threshold
}
period, err := time.ParseDuration(r.Handel.Period)
if err != nil {
panic(err)
}
ch.UpdatePeriod = period
ch.UpdateCount = r.Handel.UpdateCount
ch.FastPath = r.Handel.NodeCount
ch.Contributions = r.GetThreshold()
ch.UnsafeSleepTimeOnSigVerify = r.Handel.UnsafeSleepTimeOnSigVerify
dd, err := time.ParseDuration(r.Handel.Timeout)
if err == nil {
ch.NewTimeoutStrategy = handel.LinearTimeoutConstructor(dd)
}
switch r.Handel.Evaluator {
case "store":
ch.NewEvaluatorStrategy = handel.DefaultEvaluatorStrategy
case "equal":
ch.NewEvaluatorStrategy = func(handel.SignatureStore, *handel.Handel) handel.SigEvaluator { return new(handel.Evaluator1) }
}
return ch
}
// Duration is an alias for time.Duration
type Duration time.Duration
// UnmarshalText implements the TextUnmarshaler interface
func (d *Duration) UnmarshalText(text []byte) error {
dd, err := time.ParseDuration(string(text))
if err == nil {
*d = Duration(dd)
}
return err
}
// MarshalText implements the TextMarshaler interface
func (d *Duration) MarshalText() ([]byte, error) {
str := time.Duration(*d).String()
return []byte(str), nil
}
// Divmod returns the integer results and remainder of the division
func Divmod(numerator, denominator int) (quotient, remainder int) {
quotient = numerator / denominator // integer division, decimals are truncated
remainder = numerator % denominator
return
}