Skip to content

Commit d5b79e7

Browse files
chadsrfjl
authored andcommitted
p2p/simulations: add node properties support and utility functions (#20060)
1 parent 7300365 commit d5b79e7

File tree

3 files changed

+392
-8
lines changed

3 files changed

+392
-8
lines changed

p2p/simulations/adapters/types.go

Lines changed: 8 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -101,6 +101,11 @@ type NodeConfig struct {
101101
// services registered by calling the RegisterService function)
102102
Services []string
103103

104+
// Properties are the names of the properties this node should hold
105+
// within running services (e.g. "bootnode", "lightnode" or any custom values)
106+
// These values need to be checked and acted upon by node Services
107+
Properties []string
108+
104109
// Enode
105110
node *enode.Node
106111

@@ -120,6 +125,7 @@ type nodeConfigJSON struct {
120125
PrivateKey string `json:"private_key"`
121126
Name string `json:"name"`
122127
Services []string `json:"services"`
128+
Properties []string `json:"properties"`
123129
EnableMsgEvents bool `json:"enable_msg_events"`
124130
Port uint16 `json:"port"`
125131
}
@@ -131,6 +137,7 @@ func (n *NodeConfig) MarshalJSON() ([]byte, error) {
131137
ID: n.ID.String(),
132138
Name: n.Name,
133139
Services: n.Services,
140+
Properties: n.Properties,
134141
Port: n.Port,
135142
EnableMsgEvents: n.EnableMsgEvents,
136143
}
@@ -168,6 +175,7 @@ func (n *NodeConfig) UnmarshalJSON(data []byte) error {
168175

169176
n.Name = confJSON.Name
170177
n.Services = confJSON.Services
178+
n.Properties = confJSON.Properties
171179
n.Port = confJSON.Port
172180
n.EnableMsgEvents = confJSON.EnableMsgEvents
173181

p2p/simulations/network.go

Lines changed: 114 additions & 8 deletions
Original file line numberDiff line numberDiff line change
@@ -56,6 +56,9 @@ type Network struct {
5656
Nodes []*Node `json:"nodes"`
5757
nodeMap map[enode.ID]int
5858

59+
// Maps a node property string to node indexes of all nodes that hold this property
60+
propertyMap map[string][]int
61+
5962
Conns []*Conn `json:"conns"`
6063
connMap map[string]int
6164

@@ -71,6 +74,7 @@ func NewNetwork(nodeAdapter adapters.NodeAdapter, conf *NetworkConfig) *Network
7174
NetworkConfig: *conf,
7275
nodeAdapter: nodeAdapter,
7376
nodeMap: make(map[enode.ID]int),
77+
propertyMap: make(map[string][]int),
7478
connMap: make(map[string]int),
7579
quitc: make(chan struct{}),
7680
}
@@ -120,9 +124,16 @@ func (net *Network) NewNodeWithConfig(conf *adapters.NodeConfig) (*Node, error)
120124
Config: conf,
121125
}
122126
log.Trace("Node created", "id", conf.ID)
123-
net.nodeMap[conf.ID] = len(net.Nodes)
127+
128+
nodeIndex := len(net.Nodes)
129+
net.nodeMap[conf.ID] = nodeIndex
124130
net.Nodes = append(net.Nodes, node)
125131

132+
// Register any node properties with the network-level propertyMap
133+
for _, property := range conf.Properties {
134+
net.propertyMap[property] = append(net.propertyMap[property], nodeIndex)
135+
}
136+
126137
// emit a "control" event
127138
net.events.Send(ControlEvent(node))
128139

@@ -410,7 +421,7 @@ func (net *Network) getNode(id enode.ID) *Node {
410421
return net.Nodes[i]
411422
}
412423

413-
// GetNode gets the node with the given name, returning nil if the node does
424+
// GetNodeByName gets the node with the given name, returning nil if the node does
414425
// not exist
415426
func (net *Network) GetNodeByName(name string) *Node {
416427
net.lock.RLock()
@@ -427,19 +438,104 @@ func (net *Network) getNodeByName(name string) *Node {
427438
return nil
428439
}
429440

430-
// GetNodes returns the existing nodes
431-
func (net *Network) GetNodes() (nodes []*Node) {
441+
// GetNodeIDs returns the IDs of all existing nodes
442+
// Nodes can optionally be excluded by specifying their enode.ID.
443+
func (net *Network) GetNodeIDs(excludeIDs ...enode.ID) []enode.ID {
444+
net.lock.RLock()
445+
defer net.lock.RUnlock()
446+
447+
return net.getNodeIDs(excludeIDs)
448+
}
449+
450+
func (net *Network) getNodeIDs(excludeIDs []enode.ID) []enode.ID {
451+
// Get all curent nodeIDs
452+
nodeIDs := make([]enode.ID, 0, len(net.nodeMap))
453+
for id := range net.nodeMap {
454+
nodeIDs = append(nodeIDs, id)
455+
}
456+
457+
if len(excludeIDs) > 0 {
458+
// Return the difference of nodeIDs and excludeIDs
459+
return filterIDs(nodeIDs, excludeIDs)
460+
} else {
461+
return nodeIDs
462+
}
463+
}
464+
465+
// GetNodes returns the existing nodes.
466+
// Nodes can optionally be excluded by specifying their enode.ID.
467+
func (net *Network) GetNodes(excludeIDs ...enode.ID) []*Node {
468+
net.lock.RLock()
469+
defer net.lock.RUnlock()
470+
471+
return net.getNodes(excludeIDs)
472+
}
473+
474+
func (net *Network) getNodes(excludeIDs []enode.ID) []*Node {
475+
if len(excludeIDs) > 0 {
476+
nodeIDs := net.getNodeIDs(excludeIDs)
477+
return net.getNodesByID(nodeIDs)
478+
} else {
479+
return net.Nodes
480+
}
481+
}
482+
483+
// GetNodesByID returns existing nodes with the given enode.IDs.
484+
// If a node doesn't exist with a given enode.ID, it is ignored.
485+
func (net *Network) GetNodesByID(nodeIDs []enode.ID) []*Node {
486+
net.lock.RLock()
487+
defer net.lock.RUnlock()
488+
489+
return net.getNodesByID(nodeIDs)
490+
}
491+
492+
func (net *Network) getNodesByID(nodeIDs []enode.ID) []*Node {
493+
nodes := make([]*Node, 0, len(nodeIDs))
494+
for _, id := range nodeIDs {
495+
node := net.getNode(id)
496+
if node != nil {
497+
nodes = append(nodes, node)
498+
}
499+
}
500+
501+
return nodes
502+
}
503+
504+
// GetNodesByProperty returns existing nodes that have the given property string registered in their NodeConfig
505+
func (net *Network) GetNodesByProperty(property string) []*Node {
432506
net.lock.RLock()
433507
defer net.lock.RUnlock()
434508

435-
return net.getNodes()
509+
return net.getNodesByProperty(property)
436510
}
437511

438-
func (net *Network) getNodes() (nodes []*Node) {
439-
nodes = append(nodes, net.Nodes...)
512+
func (net *Network) getNodesByProperty(property string) []*Node {
513+
nodes := make([]*Node, 0, len(net.propertyMap[property]))
514+
for _, nodeIndex := range net.propertyMap[property] {
515+
nodes = append(nodes, net.Nodes[nodeIndex])
516+
}
517+
440518
return nodes
441519
}
442520

521+
// GetNodeIDsByProperty returns existing node's enode IDs that have the given property string registered in the NodeConfig
522+
func (net *Network) GetNodeIDsByProperty(property string) []enode.ID {
523+
net.lock.RLock()
524+
defer net.lock.RUnlock()
525+
526+
return net.getNodeIDsByProperty(property)
527+
}
528+
529+
func (net *Network) getNodeIDsByProperty(property string) []enode.ID {
530+
nodeIDs := make([]enode.ID, 0, len(net.propertyMap[property]))
531+
for _, nodeIndex := range net.propertyMap[property] {
532+
node := net.Nodes[nodeIndex]
533+
nodeIDs = append(nodeIDs, node.ID())
534+
}
535+
536+
return nodeIDs
537+
}
538+
443539
// GetRandomUpNode returns a random node on the network, which is running.
444540
func (net *Network) GetRandomUpNode(excludeIDs ...enode.ID) *Node {
445541
net.lock.RLock()
@@ -469,14 +565,21 @@ func (net *Network) GetRandomDownNode(excludeIDs ...enode.ID) *Node {
469565
}
470566

471567
func (net *Network) getDownNodeIDs() (ids []enode.ID) {
472-
for _, node := range net.getNodes() {
568+
for _, node := range net.Nodes {
473569
if !node.Up() {
474570
ids = append(ids, node.ID())
475571
}
476572
}
477573
return ids
478574
}
479575

576+
// GetRandomNode returns a random node on the network, regardless of whether it is running or not
577+
func (net *Network) GetRandomNode(excludeIDs ...enode.ID) *Node {
578+
net.lock.RLock()
579+
defer net.lock.RUnlock()
580+
return net.getRandomNode(net.getNodeIDs(nil), excludeIDs) // no need to exclude twice
581+
}
582+
480583
func (net *Network) getRandomNode(ids []enode.ID, excludeIDs []enode.ID) *Node {
481584
filtered := filterIDs(ids, excludeIDs)
482585

@@ -616,6 +719,7 @@ func (net *Network) Reset() {
616719
//re-initialize the maps
617720
net.connMap = make(map[string]int)
618721
net.nodeMap = make(map[enode.ID]int)
722+
net.propertyMap = make(map[string][]int)
619723

620724
net.Nodes = nil
621725
net.Conns = nil
@@ -634,12 +738,14 @@ type Node struct {
634738
upMu sync.RWMutex
635739
}
636740

741+
// Up returns whether the node is currently up (online)
637742
func (n *Node) Up() bool {
638743
n.upMu.RLock()
639744
defer n.upMu.RUnlock()
640745
return n.up
641746
}
642747

748+
// SetUp sets the up (online) status of the nodes with the given value
643749
func (n *Node) SetUp(up bool) {
644750
n.upMu.Lock()
645751
defer n.upMu.Unlock()

0 commit comments

Comments
 (0)