-
Notifications
You must be signed in to change notification settings - Fork 107
/
byzantine_beacon.go
154 lines (133 loc) · 4.93 KB
/
byzantine_beacon.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
package e2e
import (
"context"
"fmt"
beacon "github.com/oasisprotocol/oasis-core/go/beacon/api"
"github.com/oasisprotocol/oasis-core/go/common/crypto/signature"
"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 (
// ByzantineBeaconHonest is the honest byzantine beacon scenario.
ByzantineBeaconHonest scenario.Scenario = &byzantineBeaconImpl{
E2E: *NewE2E("byzantine/beacon-honest"),
extraArgs: []string{
"--" + byzantine.CfgBeaconMode, byzantine.ModeBeaconHonest.String(),
},
identitySeed: byzantineBeaconIdentitySeed,
}
// ByzantineBeaconCommitStraggler is the commit straggler byzantine beacon scenario.
ByzantineBeaconCommitStraggler scenario.Scenario = &byzantineBeaconImpl{
E2E: *NewE2E("byzantine/beacon-commit-straggler"),
extraArgs: []string{
"--" + byzantine.CfgBeaconMode, byzantine.ModeBeaconCommitStraggler.String(),
},
identitySeed: byzantineBeaconIdentitySeed,
}
// ByzantineBeaconRevealStraggler is the reveal straggler byzantine beacon scenario.
ByzantineBeaconRevealStraggler scenario.Scenario = &byzantineBeaconImpl{
E2E: *NewE2E("byzantine/beacon-reveal-straggler"),
extraArgs: []string{
"--" + byzantine.CfgBeaconMode, byzantine.ModeBeaconRevealStraggler.String(),
},
identitySeed: byzantineBeaconIdentitySeed,
}
)
type byzantineBeaconImpl struct {
E2E
extraArgs []string
identitySeed string
}
func (sc *byzantineBeaconImpl) Clone() scenario.Scenario {
return &byzantineBeaconImpl{
E2E: sc.E2E.Clone(),
extraArgs: sc.extraArgs,
identitySeed: sc.identitySeed,
}
}
func (sc *byzantineBeaconImpl) Fixture() (*oasis.NetworkFixture, error) {
f, err := sc.E2E.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: "beacon",
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)
}
node := f.ByzantineNodes[0]
pks, err := oasis.GenerateDeterministicNodeKeys(nil, node.IdentitySeed, []signature.SignerRole{signature.SignerNode})
if err != nil {
return nil, fmt.Errorf("byzantine/beacon: failed to derive node identity: %w", err)
}
f.Network.Beacon.PVSSParameters = &beacon.PVSSParameters{
DebugForcedParticipants: []signature.PublicKey{
pks[0],
},
}
// Make sure the byzantine node does at least 1 round (in)correctly.
f.ByzantineNodes[0].LogWatcherHandlerFactories = []log.WatcherHandlerFactory{
oasis.LogAssertEvent(byzantine.LogEventBeaconRoundCompleted, "byzantine node executed no rounds"),
}
return f, nil
}
func (sc *byzantineBeaconImpl) Run(childEnv *env.Env) error {
if err := sc.Net.Start(); err != nil {
return err
}
ctx := context.Background()
// 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()
}