github.com/intfoundation/intchain@v0.0.0-20220727031208-4316ad31ca73/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 ### DockerAdapter 67 68 The `DockerAdapter` is similar to the `ExecAdapter` but executes `docker run` 69 to run the node in a Docker container using a Docker image containing the 70 simulation binary at `/bin/p2p-node`. 71 72 The Docker image is built using `docker build` when the adapter is initialised, 73 meaning no prior setup is necessary other than having a working Docker client. 74 75 Each node listens on the external IP of the container and the default p2p and 76 RPC ports (`30303` and `8546` respectively). 77 78 ## Network 79 80 A simulation network is created with an ID and default service (which is used 81 if a node is created without an explicit service), exposes methods for 82 creating, starting, stopping, connecting and disconnecting nodes, and emits 83 events when certain actions occur. 84 85 ### Events 86 87 A simulation network emits the following events: 88 89 * node event - when nodes are created / started / stopped 90 * connection event - when nodes are connected / disconnected 91 * message event - when a protocol message is sent between two nodes 92 93 The events have a "control" flag which when set indicates that the event is the 94 outcome of a controlled simulation action (e.g. creating a node or explicitly 95 connecting two nodes together). 96 97 This is in contrast to a non-control event, otherwise called a "live" event, 98 which is the outcome of something happening in the network as a result of a 99 control event (e.g. a node actually started up or a connection was actually 100 established between two nodes). 101 102 Live events are detected by the simulation network by subscribing to node peer 103 events via RPC when the nodes start up. 104 105 ## Testing Framework 106 107 The `Simulation` type can be used in tests to perform actions in a simulation 108 network and then wait for expectations to be met. 109 110 With a running simulation network, the `Simulation.Run` method can be called 111 with a `Step` which has the following fields: 112 113 * `Action` - a function which performs some action in the network 114 115 * `Expect` - an expectation function which returns whether or not a 116 given node meets the expectation 117 118 * `Trigger` - a channel which receives node IDs which then trigger a check 119 of the expectation function to be performed against that node 120 121 As a concrete example, consider a simulated network of Ethereum nodes. An 122 `Action` could be the sending of a transaction, `Expect` it being included in 123 a block, and `Trigger` a check for every block that is mined. 124 125 On return, the `Simulation.Run` method returns a `StepResult` which can be used 126 to determine if all nodes met the expectation, how long it took them to meet 127 the expectation and what network events were emitted during the step run. 128 129 ## HTTP API 130 131 The simulation framework includes a HTTP API which can be used to control the 132 simulation. 133 134 The API is initialised with a particular node adapter and has the following 135 endpoints: 136 137 ``` 138 GET / Get network information 139 POST /start Start all nodes in the network 140 POST /stop Stop all nodes in the network 141 GET /events Stream network events 142 GET /snapshot Take a network snapshot 143 POST /snapshot Load a network snapshot 144 POST /nodes Create a node 145 GET /nodes Get all nodes in the network 146 GET /nodes/:nodeid Get node information 147 POST /nodes/:nodeid/start Start a node 148 POST /nodes/:nodeid/stop Stop a node 149 POST /nodes/:nodeid/conn/:peerid Connect two nodes 150 DELETE /nodes/:nodeid/conn/:peerid Disconnect two nodes 151 GET /nodes/:nodeid/rpc Make RPC requests to a node via WebSocket 152 ``` 153 154 For convenience, `nodeid` in the URL can be the name of a node rather than its 155 ID. 156 157 ## Command line client 158 159 `p2psim` is a command line client for the HTTP API, located in 160 `cmd/p2psim`. 161 162 It provides the following commands: 163 164 ``` 165 p2psim show 166 p2psim events [--current] [--filter=FILTER] 167 p2psim snapshot 168 p2psim load 169 p2psim node create [--name=NAME] [--services=SERVICES] [--key=KEY] 170 p2psim node list 171 p2psim node show <node> 172 p2psim node start <node> 173 p2psim node stop <node> 174 p2psim node connect <node> <peer> 175 p2psim node disconnect <node> <peer> 176 p2psim node rpc <node> <method> [<args>] [--subscribe] 177 ``` 178 179 ## Example 180 181 See [p2p/simulations/examples/README.md](examples/README.md).