Skip to content
This repository was archived by the owner on Aug 2, 2021. It is now read-only.

Commit 26abce5

Browse files
committed
network/simulation: Basic bootnode support + expanded enode.ID exclusion
1 parent 9884069 commit 26abce5

File tree

3 files changed

+133
-25
lines changed

3 files changed

+133
-25
lines changed

network/simulation/node.go

Lines changed: 68 additions & 25 deletions
Original file line numberDiff line numberDiff line change
@@ -83,6 +83,13 @@ func AddNodeWithMsgEvents(enable bool) AddNodeOption {
8383
}
8484
}
8585

86+
// AddNodeAsBootNode toggles whether the node will be configured as a bootnode
87+
func AddNodeAsBootNode(enable bool) AddNodeOption {
88+
return func(o *adapters.NodeConfig) {
89+
o.BootNode = enable
90+
}
91+
}
92+
8693
// AddNodeWithService specifies a service that should be
8794
// started on a node. This option can be repeated as variadic
8895
// argument toe AddNode and other add node related methods.
@@ -108,18 +115,16 @@ func (s *Simulation) AddNode(opts ...AddNodeOption) (id enode.ID, err error) {
108115

109116
// add ENR records to the underlying node
110117
// most importantly the bzz overlay address
111-
//
112-
// for now we have no way of setting bootnodes or lightnodes in sims
113-
// so we just let them be set to false
114-
// they should perhaps be possible to override them with AddNodeOption
115118
bzzPrivateKey, err := BzzPrivateKeyFromConfig(conf)
116119
if err != nil {
117120
return enode.ID{}, err
118121
}
119122

120123
enodeParams := &network.EnodeParams{
121124
PrivateKey: bzzPrivateKey,
125+
Bootnode: conf.BootNode,
122126
}
127+
123128
record, err := network.NewEnodeRecord(enodeParams)
124129
conf.Record = *record
125130

@@ -148,6 +153,29 @@ func (s *Simulation) AddNodes(count int, opts ...AddNodeOption) (ids []enode.ID,
148153
return ids, nil
149154
}
150155

156+
// AddBootNode creates a bootnode using AddNode(opts) and appends it to Simulation.bootNodes
157+
func (s *Simulation) AddBootNode(opts ...AddNodeOption) (id enode.ID, err error) {
158+
opts = append(opts, AddNodeAsBootNode(true))
159+
id, err = s.AddNode(opts...)
160+
if err != nil {
161+
return id, err
162+
}
163+
164+
return id, nil
165+
}
166+
167+
// AddBootNodes creates count number of bootnodes using AddNodes(count, opts)
168+
// and appends them to Simulation.bootNodes
169+
func (s *Simulation) AddBootNodes(count int, opts ...AddNodeOption) (ids []enode.ID, err error) {
170+
opts = append(opts, AddNodeAsBootNode(true))
171+
ids, err = s.AddNodes(count, opts...)
172+
if err != nil {
173+
return nil, err
174+
}
175+
176+
return ids, err
177+
}
178+
151179
// AddNodesAndConnectFull is a helpper method that combines
152180
// AddNodes and ConnectNodesFull. Only new nodes will be connected.
153181
func (s *Simulation) AddNodesAndConnectFull(count int, opts ...AddNodeOption) (ids []enode.ID, err error) {
@@ -226,6 +254,28 @@ func (s *Simulation) AddNodesAndConnectStar(count int, opts ...AddNodeOption) (i
226254
return ids, nil
227255
}
228256

257+
// AddNodesAndConnectToBootNode is a helper method that combines
258+
// AddNodes, AddBootNode and ConnectNodesStar, where the center node is a new bootnode.
259+
// The count parameter excludes the bootnode.
260+
func (s *Simulation) AddNodesAndConnectToBootNode(count int, opts ...AddNodeOption) (ids []enode.ID, bootNodeID enode.ID, err error) {
261+
bootNodeID, err = s.AddBootNode(opts...)
262+
if err != nil {
263+
return nil, bootNodeID, err
264+
}
265+
266+
ids, err = s.AddNodes(count, opts...)
267+
if err != nil {
268+
return nil, bootNodeID, err
269+
}
270+
271+
err = s.Net.ConnectNodesStar(ids, bootNodeID)
272+
if err != nil {
273+
return nil, bootNodeID, err
274+
}
275+
276+
return ids, bootNodeID, nil
277+
}
278+
229279
// UploadSnapshot uploads a snapshot to the simulation
230280
// This method tries to open the json file provided, applies the config to all nodes
231281
// and then loads the snapshot into the Simulation network
@@ -267,19 +317,21 @@ func (s *Simulation) StartNode(id enode.ID) (err error) {
267317
}
268318

269319
// StartRandomNode starts a random node.
270-
func (s *Simulation) StartRandomNode() (id enode.ID, err error) {
271-
n := s.Net.GetRandomDownNode()
320+
// Nodes can be excluded by providing their enode.ID.
321+
func (s *Simulation) StartRandomNode(excludeIDs ...enode.ID) (id enode.ID, err error) {
322+
n := s.Net.GetRandomDownNode(excludeIDs...)
272323
if n == nil {
273324
return id, ErrNodeNotFound
274325
}
275326
return n.ID(), s.Net.Start(n.ID())
276327
}
277328

278-
// StartRandomNodes starts random nodes.
279-
func (s *Simulation) StartRandomNodes(count int) (ids []enode.ID, err error) {
329+
// StartRandomNodes starts random nodes. Nodes
330+
// Nodes can be excluded by providing their enode.ID.
331+
func (s *Simulation) StartRandomNodes(count int, excludeIDs ...enode.ID) (ids []enode.ID, err error) {
280332
ids = make([]enode.ID, 0, count)
281333
for i := 0; i < count; i++ {
282-
n := s.Net.GetRandomDownNode()
334+
n := s.Net.GetRandomDownNode(excludeIDs...)
283335
if n == nil {
284336
return nil, ErrNodeNotFound
285337
}
@@ -298,30 +350,21 @@ func (s *Simulation) StopNode(id enode.ID) (err error) {
298350
}
299351

300352
// StopRandomNode stops a random node.
301-
func (s *Simulation) StopRandomNode(protect ...enode.ID) (id enode.ID, err error) {
302-
found := false
303-
var n *simulations.Node
304-
outer:
305-
for !found {
306-
n = s.Net.GetRandomUpNode()
307-
for _, v := range protect {
308-
if bytes.Equal(n.ID().Bytes(), v.Bytes()) {
309-
continue outer
310-
}
311-
}
312-
found = true
313-
}
353+
// Nodes can be excluded by providing their enode.ID.
354+
func (s *Simulation) StopRandomNode(excludeIDs ...enode.ID) (id enode.ID, err error) {
355+
n := s.Net.GetRandomUpNode(excludeIDs...)
314356
if n == nil {
315357
return id, ErrNodeNotFound
316358
}
317359
return n.ID(), s.Net.Stop(n.ID())
318360
}
319361

320362
// StopRandomNodes stops random nodes.
321-
func (s *Simulation) StopRandomNodes(count int) (ids []enode.ID, err error) {
363+
// Nodes can be excluded by providing their enode.ID.
364+
func (s *Simulation) StopRandomNodes(count int, excludeIDs ...enode.ID) (ids []enode.ID, err error) {
322365
ids = make([]enode.ID, 0, count)
323366
for i := 0; i < count; i++ {
324-
n := s.Net.GetRandomUpNode()
367+
n := s.Net.GetRandomUpNode(excludeIDs...)
325368
if n == nil {
326369
return nil, ErrNodeNotFound
327370
}
@@ -339,7 +382,7 @@ func init() {
339382
rand.Seed(time.Now().UnixNano())
340383
}
341384

342-
// derive a private key for swarm for the node key
385+
// BzzPrivateKeyFromConfig derives a private key for swarm for the node key
343386
// returns the private key used to generate the bzz key
344387
func BzzPrivateKeyFromConfig(conf *adapters.NodeConfig) (*ecdsa.PrivateKey, error) {
345388
// pad the seed key some arbitrary data as ecdsa.GenerateKey takes 40 bytes seed data

network/simulation/node_test.go

Lines changed: 64 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -17,6 +17,7 @@
1717
package simulation
1818

1919
import (
20+
"bytes"
2021
"context"
2122
"fmt"
2223
"sync"
@@ -218,6 +219,69 @@ func TestAddNodes(t *testing.T) {
218219
}
219220
}
220221

222+
func TestAddBootNode(t *testing.T) {
223+
sim := NewInProc(noopServiceFuncMap)
224+
defer sim.Close()
225+
226+
id, err := sim.AddBootNode()
227+
if err != nil {
228+
t.Fatalf("Failed to add bootnode: %s", err)
229+
}
230+
231+
bootNode := sim.Net.GetNode(id)
232+
if !bootNode.Config.BootNode {
233+
t.Fatalf("Bootnode did not have the respective flag in its config")
234+
}
235+
236+
for _, node := range sim.Net.GetBootNodes() {
237+
if !bytes.Equal(node.ID().Bytes(), bootNode.ID().Bytes()) {
238+
t.Fatalf("Found an unexpected bootnode with ID: %s", node.ID().String())
239+
}
240+
}
241+
}
242+
243+
func TestAddBootNodes(t *testing.T) {
244+
bootNodeCount := 10
245+
246+
sim := NewInProc(noopServiceFuncMap)
247+
defer sim.Close()
248+
249+
ids, err := sim.AddBootNodes(bootNodeCount)
250+
if err != nil {
251+
t.Fatalf("Failed to add bootnodes: %s", err)
252+
}
253+
254+
bootNodes := sim.Net.GetBootNodes()
255+
for _, id := range ids {
256+
match := false
257+
for _, node := range bootNodes {
258+
if bytes.Equal(id.Bytes(), node.ID().Bytes()) {
259+
match = true
260+
}
261+
}
262+
263+
if !match {
264+
t.Fatalf("Added a bootnode with enode.ID, %s, but it was not found via GetBootNodes", id.String())
265+
}
266+
}
267+
}
268+
269+
func TestAddNodesAndConnectToBootNode(t *testing.T) {
270+
nodeCount := 20
271+
272+
sim := NewInProc(noopServiceFuncMap)
273+
defer sim.Close()
274+
275+
ids, bootNodeID, err := sim.AddNodesAndConnectToBootNode(nodeCount)
276+
if err != nil {
277+
t.Fatalf("AddNodesAndConnectToBootNode Failed: %s", err)
278+
}
279+
280+
// VerifyStar takes a map and an index to the bootnode, so append it and use the index
281+
ids = append(ids, bootNodeID)
282+
simulations.VerifyStar(t, sim.Net, ids, len(ids)-1)
283+
}
284+
221285
func TestAddNodesAndConnectFull(t *testing.T) {
222286
sim := NewInProc(noopServiceFuncMap)
223287
defer sim.Close()

network/simulation/simulation.go

Lines changed: 1 addition & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -114,6 +114,7 @@ func NewBzzInProc(services map[string]ServiceFunc) (s *Simulation) {
114114
OverlayAddr: addr.Over(),
115115
UnderlayAddr: addr.Under(),
116116
HiveParams: hp,
117+
BootnodeMode: ctx.Config.BootNode,
117118
}
118119
return network.NewBzz(config, kad, nil, nil, nil, nil, nil), nil, nil
119120
}

0 commit comments

Comments
 (0)