Peer-to-peer (P2P) network
How to create a P2P network?
In ethp2psim, we provide two generators to assign weights to the nodes and edges of the peer-to-peer (P2P) network. By our terminology, edge weights represent communication latency on the communication channels (edges) of the P2P network, while node weights account for node relevance (i.e., portion of staked ether).
- class ethp2psim.network.NodeWeightGenerator(mode='random', seed=None)[source]
Reusable object to generate weights for Peer-to-peer network nodes
- Parameters:
mode ({'random', 'stake'}, default 'random') – Nodes are weighted either randomly, according to their staked Ethereum value
seed (int (optional)) – Random seed (disabled by default)
- generate(graph, rng=None)[source]
Generate node weights for the nodes of the input graph.
- Parameters:
graph (networkx.Graph) – Provide graph to generate node weights
rng (Optional[np.random._generator.Generator]) – Random number generator
- Return type:
dict
Examples
>>> import networkx as nx >>> G = nx.Graph() >>> G.add_edges_from([(0,1),(1,2),(2,0)]) >>> nw_gen = NodeWeightGenerator('stake') >>> len(nw_gen.generate(G)) 3
- class ethp2psim.network.EdgeWeightGenerator(mode='random', seed=None)[source]
Reusable object to generate latencies for connections between Peer-to-peer network nodes
- Parameters:
mode ({'random', 'normal', 'unweighted', 'custom'}, default 'random') – Choose setting for connection latency generation!
seed (int (optional)) – Random seed (disabled by default)
- generate(graph, rng=None)[source]
Generate edge weights (latency) for the edges of the input graph.
- Parameters:
graph (networkx.Graph) – Provide graph to generate connections latencies
rng (Optional[np.random._generator.Generator]) – Random number generator
- Return type:
dict
Examples
>>> import networkx as nx >>> G = nx.Graph() >>> G.add_edges_from([(0,1),(1,2),(2,3),(2,0)]) >>> ew_gen = EdgeWeightGenerator('normal') >>> len(ew_gen.generate(G)) 4
Using these generators, we can initialize the P2P network that is a random regular graph by default but you can also specify any custom graph as input, for instance, you can use the actual Ethereum P2P graph or some testnet’s P2P graph for your measurements. All network related actions are accessed through the network.Network
object.
- class ethp2psim.network.Network(node_weight_gen, edge_weight_gen, num_nodes=100, k=5, graph=None, seed=None)[source]
Peer-to-peer network abstraction
- Parameters:
node_weight_gen (NodeWeightGenerator) – Set generator for node weights. By default random node weights are used.
edge_weight_gen (EdgeWeightGenerator) – Set generator for edge weights. By default random edge weights are used.
num_nodes (int) – Number of nodes in the peer-to-peer (P2P) graph
k (int) – Regularity parameter
graph (networkx.Graph) – Provide custom graph otherwise a k-regular random graph is generated
seed (int (optional)) – Random seed (disabled by default)
- get_central_nodes(k, metric='degree')[source]
Get top central nodes of the P2P network
- Parameters:
k (int) – Number of central nodes to return
metric (str {'betweenness','pagerank','degree'}) – Choose centrality metric
Examples
>>> from .data import GoerliTestnet >>> nw_gen = NodeWeightGenerator('random') >>> ew_gen = EdgeWeightGenerator('normal') >>> goerli = GoerliTestnet() >>> net = Network(nw_gen, ew_gen, graph=goerli.graph) >>> net.get_central_nodes(3, 'degree') ['192', '772', '661']
- get_edge_weight(node1, node2, external=None)[source]
Get edge weight for node pair
- Parameters:
node1 (int) – First endpoint of the link to be removed
node2 (int) – Second endpoint of the link to be removed
- Return type:
Optional
[float
]
Examples
>>> import networkx as nx >>> G = nx.Graph() >>> G.add_weighted_edges_from([(0,1,0.1),(1,2,0.2),(2,0,0.3)], weight='latency') >>> nw_gen = NodeWeightGenerator('random') >>> ew_gen = EdgeWeightGenerator('custom') >>> net = Network(nw_gen, ew_gen, graph=G) >>> net.get_edge_weight(0, 2) 0.3 >>> net.get_edge_weight(0, 3) is None True
- remove_edge(node1, node2)[source]
Delete edge from the network. The functions returns whether edge removal was successful.
- Parameters:
node1 (int) – First endpoint of the link to be removed
node2 (int) – Second endpoint of the link to be removed
- Return type:
bool
Examples
>>> import networkx as nx >>> G = nx.Graph() >>> G.add_edges_from([(0,1),(1,2),(2,0),(2,3)]) >>> nw_gen = NodeWeightGenerator('random') >>> ew_gen = EdgeWeightGenerator('normal') >>> net = Network(nw_gen, ew_gen, graph=G) >>> net.remove_edge(2,3) True >>> net.remove_edge(2,3) False >>> net.remove_edge(0,2) True
- sample_random_nodes(count, replace, use_weights=False, exclude=None, rng=None)[source]
Sample network nodes uniformly at random
- Parameters:
count (int) – Number of nodes to sample
replace (bool) – Whether the sample is with or without replacement
use_weights (bool) – Set to sample nodes with respect to their weights
exclude (Optional[list]) – List of nodes to exclude from the sample
rng (Optional[np.random._generator.Generator]) – Random number generator
- Return type:
List
[int
]
Examples
>>> nw_gen = NodeWeightGenerator('random') >>> ew_gen = EdgeWeightGenerator('normal') >>> net = Network(nw_gen, ew_gen, num_nodes=5, k=2) >>> candidates = net.sample_random_nodes(3, False, exclude=[3,4]) >>> len(candidates) 3 >>> 3 in candidates False >>> 4 in candidates False
- update(graph, reset_edge_weights=False, reset_node_weights=False)[source]
Update P2P network.
- Parameters:
graph (networkx.Graph) – Update connections based on the provided graph.
reset_edge_weights (bool (default: False)) – Set whether to reset weights for existing edges
reset_node_weights (bool (default: False)) – Set whether to reset weights for existing nodes
- Return type:
NoReturn
Examples
>>> import networkx as nx >>> G1 = nx.Graph() >>> G1.add_edges_from([(0,1),(1,2),(2,0)]) >>> G2 = nx.Graph() >>> G2.add_edges_from([(2,3),(3,4),(4,0)]) >>> nw_gen = NodeWeightGenerator('random') >>> ew_gen = EdgeWeightGenerator('normal') >>> net = Network(nw_gen, ew_gen, graph=G1) >>> net.num_nodes 3 >>> net.update(G2) >>> net.num_nodes 5
Using real-world data
In our experiments, we compare the random regular graph model for simulating transactions with the underlying structure of the Goerli testnet. It is a good example on how to implement and add benchmark graph datasets to the experiments.
- class ethp2psim.data.GoerliTestnet[source]
Network container for the Goerli Testnet
Examples
>>> goerli = GoerliTestnet() >>> goerli.graph.number_of_nodes() 1355 >>> goerli.graph.number_of_edges() 19146
As a summary, let’s observe how to mimic the structure and properties of the real world Ethereum P2P network by incorporating
staked Ethereum values as node relevance
normal distribution of channel latencies
structure of the Goerli testnet
nw_gen = NodeWeightGenerator('stake')
ew_gen = EdgeWeightGenerator('normal')
goerli = GoerliTestnet()
net = Network(nw_gen, ew_gen, graph=goerli.graph)
Next, let’s discuss how to propagate messages over the P2P network using different message-passing protocols.