github.com/julesgoullee/go-ethereum@v1.9.7/p2p/simulations/README.md (about) 1 # devp2p Simulations 2 3 The `p2p/simulations` package implements a simulation framework which supports 4 creating a collection of devp2p nodes, connecting them together to form a 5 simulation network, performing simulation actions in that network and then 6 extracting useful information. 7 8 ## Nodes 9 10 Each node in a simulation network runs multiple services by wrapping a collection 11 of objects which implement the `node.Service` interface meaning they: 12 13 * can be started and stopped 14 * run p2p protocols 15 * expose RPC APIs 16 17 This means that any object which implements the `node.Service` interface can be 18 used to run a node in the simulation. 19 20 ## Services 21 22 Before running a simulation, a set of service initializers must be registered 23 which can then be used to run nodes in the network. 24 25 A service initializer is a function with the following signature: 26 27 ```go 28 func(ctx *adapters.ServiceContext) (node.Service, error) 29 ``` 30 31 These initializers should be registered by calling the `adapters.RegisterServices` 32 function in an `init()` hook: 33 34 ```go 35 func init() { 36 adapters.RegisterServices(adapters.Services{ 37 "service1": initService1, 38 "service2": initService2, 39 }) 40 } 41 ``` 42 43 ## Node Adapters 44 45 The simulation framework includes multiple "node adapters" which are 46 responsible for creating an environment in which a node runs. 47 48 ### SimAdapter 49 50 The `SimAdapter` runs nodes in-memory, connecting them using an in-memory, 51 synchronous `net.Pipe` and connecting to their RPC server using an in-memory 52 `rpc.Client`. 53 54 ### ExecAdapter 55 56 The `ExecAdapter` runs nodes as child processes of the running simulation. 57 58 It does this by executing the binary which is running the simulation but 59 setting `argv[0]` (i.e. the program name) to `p2p-node` which is then 60 detected by an init hook in the child process which runs the `node.Service` 61 using the devp2p node stack rather than executing `main()`. 62 63 The nodes listen for devp2p connections and WebSocket RPC clients on random 64 localhost ports. 65 66 ## Network 67 68 A simulation network is created with an ID and default service (which is used 69 if a node is created without an explicit service), exposes methods for 70 creating, starting, stopping, connecting and disconnecting nodes, and emits 71 events when certain actions occur. 72 73 ### Events 74 75 A simulation network emits the following events: 76 77 * node event - when nodes are created / started / stopped 78 * connection event - when nodes are connected / disconnected 79 * message event - when a protocol message is sent between two nodes 80 81 The events have a "control" flag which when set indicates that the event is the 82 outcome of a controlled simulation action (e.g. creating a node or explicitly 83 connecting two nodes together). 84 85 This is in contrast to a non-control event, otherwise called a "live" event, 86 which is the outcome of something happening in the network as a result of a 87 control event (e.g. a node actually started up or a connection was actually 88 established between two nodes). 89 90 Live events are detected by the simulation network by subscribing to node peer 91 events via RPC when the nodes start up. 92 93 ## Testing Framework 94 95 The `Simulation` type can be used in tests to perform actions in a simulation 96 network and then wait for expectations to be met. 97 98 With a running simulation network, the `Simulation.Run` method can be called 99 with a `Step` which has the following fields: 100 101 * `Action` - a function which performs some action in the network 102 103 * `Expect` - an expectation function which returns whether or not a 104 given node meets the expectation 105 106 * `Trigger` - a channel which receives node IDs which then trigger a check 107 of the expectation function to be performed against that node 108 109 As a concrete example, consider a simulated network of Ethereum nodes. An 110 `Action` could be the sending of a transaction, `Expect` it being included in 111 a block, and `Trigger` a check for every block that is mined. 112 113 On return, the `Simulation.Run` method returns a `StepResult` which can be used 114 to determine if all nodes met the expectation, how long it took them to meet 115 the expectation and what network events were emitted during the step run. 116 117 ## HTTP API 118 119 The simulation framework includes a HTTP API which can be used to control the 120 simulation. 121 122 The API is initialised with a particular node adapter and has the following 123 endpoints: 124 125 ``` 126 GET / Get network information 127 POST /start Start all nodes in the network 128 POST /stop Stop all nodes in the network 129 GET /events Stream network events 130 GET /snapshot Take a network snapshot 131 POST /snapshot Load a network snapshot 132 POST /nodes Create a node 133 GET /nodes Get all nodes in the network 134 GET /nodes/:nodeid Get node information 135 POST /nodes/:nodeid/start Start a node 136 POST /nodes/:nodeid/stop Stop a node 137 POST /nodes/:nodeid/conn/:peerid Connect two nodes 138 DELETE /nodes/:nodeid/conn/:peerid Disconnect two nodes 139 GET /nodes/:nodeid/rpc Make RPC requests to a node via WebSocket 140 ``` 141 142 For convenience, `nodeid` in the URL can be the name of a node rather than its 143 ID. 144 145 ## Command line client 146 147 `p2psim` is a command line client for the HTTP API, located in 148 `cmd/p2psim`. 149 150 It provides the following commands: 151 152 ``` 153 p2psim show 154 p2psim events [--current] [--filter=FILTER] 155 p2psim snapshot 156 p2psim load 157 p2psim node create [--name=NAME] [--services=SERVICES] [--key=KEY] 158 p2psim node list 159 p2psim node show <node> 160 p2psim node start <node> 161 p2psim node stop <node> 162 p2psim node connect <node> <peer> 163 p2psim node disconnect <node> <peer> 164 p2psim node rpc <node> <method> [<args>] [--subscribe] 165 ``` 166 167 ## Example 168 169 See [p2p/simulations/examples/README.md](examples/README.md).