-
Notifications
You must be signed in to change notification settings - Fork 107
/
byzantine_beacon_vrf.go
140 lines (120 loc) · 4.56 KB
/
byzantine_beacon_vrf.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
package e2e
import (
"context"
"fmt"
"github.com/oasisprotocol/oasis-core/go/oasis-node/cmd/debug/byzantine"
"github.com/oasisprotocol/oasis-core/go/oasis-test-runner/env"
"github.com/oasisprotocol/oasis-core/go/oasis-test-runner/log"
"github.com/oasisprotocol/oasis-core/go/oasis-test-runner/oasis"
"github.com/oasisprotocol/oasis-core/go/oasis-test-runner/scenario"
)
const byzantineBeaconIdentitySeed = "ekiden byzantine node worker"
var (
// ByzantineVRFBeaconHonest is the honest byzantine VRF beacon scenario.
ByzantineVRFBeaconHonest scenario.Scenario = &byzantineVRFBeaconImpl{
Scenario: *NewScenario("byzantine/beacon-vrf-honest"),
extraArgs: []oasis.Argument{
{Name: byzantine.CfgVRFBeaconMode, Values: []string{byzantine.ModeVRFBeaconHonest.String()}},
},
identitySeed: byzantineBeaconIdentitySeed,
}
// ByzantineVRFBeaconEarly is the early-proof byzantine beacon scenario.
ByzantineVRFBeaconEarly scenario.Scenario = &byzantineVRFBeaconImpl{
Scenario: *NewScenario("byzantine/beacon-vrf-early"),
extraArgs: []oasis.Argument{
{Name: byzantine.CfgVRFBeaconMode, Values: []string{byzantine.ModeVRFBeaconEarly.String()}},
},
identitySeed: byzantineBeaconIdentitySeed,
}
// ByzantineVRFBeaconMissing is the missing-proof byzantine beacon scenario.
ByzantineVRFBeaconMissing scenario.Scenario = &byzantineVRFBeaconImpl{
Scenario: *NewScenario("byzantine/beacon-vrf-missing"),
extraArgs: []oasis.Argument{
{Name: byzantine.CfgVRFBeaconMode, Values: []string{byzantine.ModeVRFBeaconMissing.String()}},
},
identitySeed: byzantineBeaconIdentitySeed,
}
)
type byzantineVRFBeaconImpl struct {
Scenario
extraArgs []oasis.Argument
identitySeed string
}
func (sc *byzantineVRFBeaconImpl) Clone() scenario.Scenario {
return &byzantineVRFBeaconImpl{
Scenario: sc.Scenario.Clone(),
extraArgs: sc.extraArgs,
identitySeed: sc.identitySeed,
}
}
func (sc *byzantineVRFBeaconImpl) Fixture() (*oasis.NetworkFixture, error) {
f, err := sc.Scenario.Fixture()
if err != nil {
return nil, err
}
// The byzantine node requires deterministic identities.
f.Network.DeterministicIdentities = true
// The byzantine scenario requires mock epochtime as the byzantine node
// doesn't know how to handle epochs in which it is not scheduled.
f.Network.SetMockEpoch()
// Provision a Byzantine node.
f.ByzantineNodes = []oasis.ByzantineFixture{
{
Script: "vrfbeacon",
ExtraArgs: sc.extraArgs,
IdentitySeed: sc.identitySeed,
Entity: 1,
ActivationEpoch: 1,
Runtime: -1,
},
}
// Use really ugly hacks to force the byzantine node to participate.
if l := len(f.ByzantineNodes); l != 1 {
return nil, fmt.Errorf("byzantine/beacon: unexpected number of byzantine nodes: %d", l)
}
// Make sure the byzantine node does at least 1 round (in)correctly.
f.ByzantineNodes[0].LogWatcherHandlerFactories = []log.WatcherHandlerFactory{
oasis.LogAssertEvent(byzantine.LogEventVRFBeaconRoundCompleted, "byzantine node executed no rounds"),
}
return f, nil
}
func (sc *byzantineVRFBeaconImpl) Run(ctx context.Context, childEnv *env.Env) error {
if err := sc.Net.Start(); err != nil {
return err
}
// Wait for the validators to come up.
sc.Logger.Info("waiting for validators to initialize",
"num_validators", len(sc.Net.Validators()),
)
for _, n := range sc.Net.Validators() {
if err := n.WaitReady(ctx); err != nil {
return fmt.Errorf("failed to wait for a validator: %w", err)
}
}
sc.Logger.Info("triggering epoch transition")
if err := sc.Net.Controller().SetEpoch(ctx, 1); err != nil {
return fmt.Errorf("failed to set epoch: %w", err)
}
sc.Logger.Info("epoch transition done")
// Wait for the byzantine node to register.
sc.Logger.Info("waiting for (all) nodes to register",
"num_nodes", sc.Net.NumRegisterNodes(),
)
if err := sc.Net.Controller().WaitNodesRegistered(ctx, sc.Net.NumRegisterNodes()); err != nil {
return fmt.Errorf("failed to wait for nodes: %w", err)
}
// Trigger an epoch transition to start the beacon round.
sc.Logger.Info("triggering epoch transition - start beacon round")
if err := sc.Net.Controller().SetEpoch(ctx, 2); err != nil {
return fmt.Errorf("failed to set epoch: %w", err)
}
sc.Logger.Info("epoch transition done")
// Trigger an epoch transition so that we wait for the beacon round.
sc.Logger.Info("triggering epoch transition - finish beacon round")
if err := sc.Net.Controller().SetEpoch(ctx, 3); err != nil {
return err
}
sc.Logger.Info("epoch transition done")
// Make sure the byzantine beacon did the right thing.
return sc.Net.CheckLogWatchers()
}