github.com/bcnmy/go-ethereum@v1.10.27/p2p/simulations/README.md (about)

     1  # devp2p Simulations
     2  
     3  The `p2p/simulations` package implements a simulation framework that supports
     4  creating a collection of devp2p nodes, connecting them 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. The default
    69  service is used if a node is created without an explicit service. The 
    70  network has exposed methods for creating, starting, stopping, connecting 
    71  and disconnecting nodes. It also emits 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).
    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 that 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 that 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 that 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).