Преглед изворни кода

doc: finalize dchat tutorial and add TODOs

lunar-mining пре 2 година
родитељ
комит
c03f162c78

+ 2 - 2
doc/src/learn/dchat/creating-dchatd/accept-addr.md

@@ -1,7 +1,7 @@
 # Accept addr
 
-To deploy the `RequestHandler` and start receiving `JSON-RPC` requests,
-we'll need to configure a `JSON-RPC` accept address.
+To start receiving `JSON-RPC` requests, we'll need to configure a
+`JSON-RPC` accept address.
 
 We'll add a `rpc_listen` address to our `Args` struct. It will look
 like this:

+ 2 - 0
doc/src/learn/dchat/creating-dchatd/part-2.md

@@ -11,3 +11,5 @@ This section will cover:
 * The `MessageSubsystem`
 * `MessageSubscription`
 * `Channel`
+* `JSON-RPC` `RequestHandler`
+* `StoppableTask`

+ 2 - 2
doc/src/learn/dchat/creating-dchatd/sending-messages.md

@@ -4,6 +4,8 @@ The core of our application has been built. All that's left is to make a
 python command-line tool that takes user input and sends it to `dchatd`
 over `JSON-RPC`. 
 
+However, we'll need to implement `JSON-RPC` on `dchatd` first.
+
 We'll implement a `JSON-RPC` method called `send` that takes some user
 data. When `dchatd` receives `send` it will create a `DchatMsg` and send
 it over the network using `p2p.broadcast`.
@@ -20,5 +22,3 @@ pub async fn broadcast<M: Message>(&self, message: &M) {
 `broadcast` takes a generic `Message` type and sends it across all the
 channels that our node has access to.
 
-All that's left to do is to create a python command-line tool with
-`JSON-RPC` integration.

+ 0 - 2
doc/src/learn/dchat/dchat.md

@@ -16,5 +16,3 @@ the p2p network, in particular:
 
 The source code for this tutorial can be found at
 [example/dchat](https://github.com/darkrenaissance/darkfi/tree/master/example/dchat).
-
-TODO: `dchat-cli` is currently only partially implemented.

+ 2 - 2
doc/src/learn/dchat/deployment/getting-started.md

@@ -4,7 +4,7 @@ We'll create a new cargo directory and add DarkFi to our `Cargo.toml`,
 like so:
 
 ```
-{{#include ../../../../../example/dchat/Cargo.toml:darkfi}}
+{{#include ../../../../../example/dchat/dchatd/Cargo.toml:darkfi}}
 ```
 
 Be sure to replace the path to DarkFi with the correct path for your
@@ -15,7 +15,7 @@ dchat. We'll need a few more external libraries too, so add these
 dependencies:
 
 ```
-{{#include ../../../../../example/dchat/Cargo.toml:dependencies}}
+{{#include ../../../../../example/dchat/dchatd/Cargo.toml:dependencies}}
 ```
 
 

+ 1 - 1
doc/src/learn/dchat/deployment/part-1.md

@@ -6,4 +6,4 @@ introduce a number of key concepts:
 * p2p daemons
 * Inbound, outbound, manual and seed nodes
 * Understanding `Sessions`
-* `p2p.start()`, `p2p.run()` and `p2p.stop()`
+* `p2p.start` and `p2p.stop`

+ 1 - 2
doc/src/learn/dchat/deployment/seed-node.md

@@ -11,9 +11,8 @@ cargo build --all-features --package dchatd
 On first run, it will create a config file from the defaults we specified
 earlier. Run it as follows:
 
-```bash`
+```bash
 ./dchatd
-
 ```
 It should output the following:
 

+ 2 - 2
doc/src/learn/dchat/deployment/sessions.md

@@ -15,11 +15,11 @@ There behavior is as follows:
 address configured in settings.
 
 **Outbound**: Starts a connect loop for every connect slot configured in
-settings. Establishes a connection using `Connector.connect()`: a method
+settings. Establishes a connection using `Connector.connect`: a method
 that takes an address returns a `Channel`.
 
 **Manual**: Uses a `Connector` to connect to a single address that is passed
-to `ManualSession::connect()`. Used to create an explicit connection to
+to `ManualSession::connect`. Used to create an explicit connection to
 a specified address.
 
 **SeedSync**: Creates a connection to the seed nodes specified in settings.

+ 0 - 121
doc/src/learn/dchat/deployment/start-run-stop.md

@@ -1,121 +0,0 @@
-# Start-Stop
-
-Now that we have initialized the network settings we can create an
-instance of the p2p network.
-
-We will next create a `Dchat` struct that will store all the data required
-by dchat. For now, it will just hold a pointer to the p2p network.
-
-```rust
-struct Dchat {
-    p2p: net::P2pPtr,
-}
-
-impl Dchat {
-    fn new(
-        p2p: net::P2pPtr,
-    ) -> Self {
-        Self { p2p }
-    }
-}
-```
-
-Let's build out our `realmain` function as follows:
-
-```rust
-use log::info;
-
-async_daemonize!(realmain);
-async fn realmain(args: Args, ex: Arc<smol::Executor<'static>>) -> Result<()> {
-    let p2p = net::P2p::new(args.net.into(), ex.clone()).await;
-    info!("Starting P2P network");
-    p2p.clone().start().await?;
-
-    let (signals_handler, signals_task) = SignalHandler::new(ex)?;
-    signals_handler.wait_termination(signals_task).await?;
-    info!("Caught termination signal, cleaning up and exiting...");
-
-    info!("Stopping P2P network");
-    p2p.stop().await;
-
-    Ok(())
-}
-```
-
-Here, we instantiate the p2p network using `P2p::new`. We then start it
-by calling `start`, and handle shutdown signals to safely shutdown the
-network using `P2p::stop`.
-
-Let's take a quick look at the underlying p2p methods we're using here.
-
-## Start
-
-This is [start](https://github.com/darkrenaissance/darkfi/blob/master/src/net/p2p.rs#L126):
-
-```rust
-/// Starts inbound, outbound, and manual sessions.
-pub async fn start(self: Arc<Self>) -> Result<()> {
-    debug!(target: "net::p2p::start()", "P2P::start() [BEGIN]");
-    info!(target: "net::p2p::start()", "[P2P] Starting P2P subsystem");
-
-    // First attempt any set manual connections
-    for peer in &self.settings.peers {
-        self.session_manual().connect(peer.clone()).await;
-    }
-
-    // Start the inbound session
-    if let Err(err) = self.session_inbound().start().await {
-        error!(target: "net::p2p::start()", "Failed to start inbound session!: {}", err);
-        self.session_manual().stop().await;
-        return Err(err)
-    }
-
-    // Start the outbound session
-    self.session_outbound().start().await;
-
-    info!(target: "net::p2p::start()", "[P2P] P2P subsystem started");
-    Ok(())
-}
-```
-
-`start` attempts to start an `Inbound`, `Manual` or `Outbound` session,
-which will succeed or fail depending on how your TOML is configured. For
-example, if you are an outbound node, `session_inbound.start()` will
-return with the following message:
-
-```rust
-info!(target: "net", "Not configured for accepting incoming connections.");
-```
-
-The function calls in `start` trigger the following processes:
-
-`session_manual.connect()`: tries to connect to any `peer` addresses we
-have specified in the TOML, using a `Connector`.
-
-`session_inbound.start()`: starts an `Acceptor` on the inbound address
-specified in the TOML, then creates and registers a `Channel` on that
-address.
-
-`session_outbound.start()': tries to establish a connection using a
-`Connector` to the number of slots we have specified in the TOML field
-`outbound_connections`. For every `Slot`, `run` tries to find a valid
-address we can connect to through `PeerDiscovery`, which loops through
-all connected channels and sends out a `GetAddr` message. If we don't
-have any connected channels, `run` performs a `SeedSync`.
-
-## Stop
-
-This is [stop()](https://github.com/darkrenaissance/darkfi/blob/master/src/net/p2p.rs#L164).
-
-```rust
-/// Stop the running P2P subsystem
-pub async fn stop(&self) {
-    // Stop the sessions
-    self.session_manual().stop().await;
-    self.session_inbound().stop().await;
-    self.session_outbound().stop().await;
-}
-```
-
-`stop` transmits a shutdown signal to all channels subscribed to the
-stop signal and safely shuts down the network.

+ 0 - 50
doc/src/learn/dchat/network-tools/accept-addr.md

@@ -1,50 +0,0 @@
-# Accept addr
-
-To deploy the `JsonRpcInterface` and start receiving JSON-RPC requests,
-we'll need to configure a JSON-RPC accept address.
-
-Let's return to our functions `alice()` and `bob()`. To enable Alice and
-Bob to connect to JSON-RPC, we'll need to generalize this return a RPC
-`Url` as well as a `Settings`.
-
-Let's define a new struct called `AppSettings` that has two fields,
-`Url` and `Settings`.
-
-```rust
-{{#include ../../../../../example/dchat/src/main.rs:app_settings}}
-```
-
-Next, we'll change our `alice()` method to return a `AppSettings`
-instead of a `Settings`.
-
-```rust
-{{#include ../../../../../example/dchat/src/main.rs:alice}}
-```
-
-And the same for `bob()`:
-
-```rust
-{{#include ../../../../../example/dchat/src/main.rs:bob}}
-```
-
-Update `main()` with the new type:
-
-```rust
-#[async_std::main]
-async fn main() -> Result<()> {
-    let settings: Result<AppSettings> = match std::env::args().nth(1) {
-        Some(id) => match id.as_str() {
-            "a" => alice(),
-            "b" => bob(),
-            _ => Err(ErrorMissingSpecifier.into()),
-        },
-        None => Err(ErrorMissingSpecifier.into()),
-    };
-
-    let settings = settings?.clone();
-
-    let p2p = net::P2p::new(settings.net).await;
-    //...
-    }
-}
-```

+ 0 - 26
doc/src/learn/dchat/network-tools/debug.md

@@ -1,26 +0,0 @@
-# Debugging
-
-As a final step, let's quickly turn to the debug output of `dnetview`
-which is stored in `.local/darkfi/dnetview.log`.
-
-Run `dnetview` in `verbose` mode to enable debugging.
-
-```bash
-./dnetview -v
-```
-
-Here's an example output. This is Alice:
-
-```json
-[DEBUG] (16) jsonrpc-client: <-- {"jsonrpc":"2.0","id":8105306807249776489,"result":{"external_addr":"tcp://127.0.0.1:51554","session_inbound":{"connected":{"tcp://127.0.0.1:36428":[{"accept_addr":"tcp://127.0.0.1:51554"},{"last_msg":"addr","last_status":"recv","log":[[1659950874808537094,"send","version"],[1659950874810919251,"recv","version"],[1659950874811104471,"send","verack"],[1659950874811491950,"recv","verack"],[1659950874812397628,"send","getaddr"],[1659950874814847748,"recv","getaddr"],[1659950874815100189,"send","addr"],[1659950874816306644,"recv","addr"]],"random_id":2658393884,"remote_node_id":""}]}},"session_manual":{"key":110},"session_outbound":{"slots":[]},"state":"run"}}
-```
-
-This is Bob: 
-
-```json
-[DEBUG] (16) jsonrpc-client: <-- {"jsonrpc":"2.0","id":17000304364801751931,"result":{"external_addr":null,"session_inbound":{"connected":{}},"session_manual":{"key":110},"session_outbound":{"slots":[{"addr":null,"channel":null,"state":"open"},{"addr":null,"channel":null,"state":"open"},{"addr":"tcp://127.0.0.1:51554","channel":{"last_msg":"addr","last_status":"sent","log":[],"random_id":3924275147,"remote_node_id":""},"state":"connected"},{"addr":null,"channel":null,"state":"open"},{"addr":"tcp://127.0.0.1:50515","channel":{"last_msg":"addr","last_status":"sent","log":[],"random_id":2182348290,"remote_node_id":""},"state":"connected"}]},"state":"run"}}
-```
-
-The raw data might come in useful in some cases.
-
-Happy hacking!

+ 1 - 56
doc/src/learn/dchat/network-tools/get-info.md

@@ -1,58 +1,3 @@
 # get_info
 
-If you run Alice now, you'll see the following output:
-
-```
-[DEBUG] jsonrpc-server: Trying to bind listener on tcp://127.0.0.1:55054
-```
-
-That indicates that our JSON-RPC server is up and running. However,
-there's currently no client for us to connect to. That's where `dnetview`
-comes in. `dnetview` implements a JSON-RPC client that calls a single
-method: `get_info()`.
-
-To use it, let's return to our `JsonRpcInterface` and add the following
-method:
-
-```rust
-{{#include ../../../../../example/dchat/src/rpc.rs:get_info}}
-```
-
-And add it to `handle_request()`:
-
-```rust
-{{#include ../../../../../example/dchat/src/rpc.rs:req_match}}
-```
-
-This calls the p2p function `get_info()` and passes the returned data into a
-`JsonResponse`.
-
-Under the hood, this function triggers a hierarchy of `get_info()`
-calls which deliver info specific to a node, its inbound or outbound
-`Session`'s, and the `Channel`'s those `Session`'s run.
-
-Here's what happens:
-
-```rust
-{{#include ../../../../../src/net/p2p.rs:get_info}}
-```
-
-Here we return two pieces of info that are unique to a node:
-`external_addr` and `state`. We couple that data with `SessionInfo`
-by calling `get_info()` on each `Session`.
-
-`Session::get_info()` returns data related to a `Session`
-(for example, an Inbound `accept_addr` in the case of an
-inbound `Session`). `Session::get_info()` then calls the function
-`Channel::get_info()` which returns data specific to a `Channel`. This
-happens via a child struct called `ChannelInfo`.
-
-This is `ChannelInfo::get_info()`.
-
-```rust
-{{#include ../../../../../src/net/channel.rs:get_info}}
-```
-
-`dnetview` uses the info returned from `Channel` and `Session` and
-node-specific info like `external_addr` to display an overview of the
-p2p network.
+TODO

+ 0 - 17
doc/src/learn/dchat/network-tools/part-3.md

@@ -1,17 +0,0 @@
-# Network tools
-
-In its current state, dchat is ready to use. But there's steps we can
-take to improve it. If we connect dchat to JSON-RPC, we gain access to
-a tool called `dnetview` that allows us to visually explore connections
-and messages on the p2p network.
-
-As well as facilitating debugging, connecting
-`dnetview` is a good excuse to dive into DarkFi's [rpc
-module](https://github.com/darkrenaissance/darkfi/tree/master/src/rpc)
-which is essential to the DarkFi code base.
-
-This section will cover:
-
-* DarkFi's JSON-RPC interface
-* Exploring the p2p network topology using `dnetview`
-

+ 8 - 0
doc/src/learn/dchat/network-tools/part-4.md

@@ -0,0 +1,8 @@
+# Network tools
+
+In its current state, dchat is ready to use. But there's steps we can
+take to improve it. If we implement `dnet` we'll be able to visually
+explore connections and messages on the `dchat` network.
+
+This section will cover how to explore the p2p network using `dnet`.
+

+ 0 - 20
doc/src/learn/dchat/network-tools/pong.md

@@ -1,20 +0,0 @@
-# Methods
-
-We're ready to deploy our `JsonRpcInterface`. But right now now it just
-returns `JsonError::MethodNotFound`. So before testing out the JSON-RPC,
-let's implement some methods.
-
-We'll start with a simple `pong` method that replies to `ping`.
-
-```rust
-{{#include ../../../../../example/dchat/src/rpc.rs:pong}}
-```
-
-And add it to `handle_request()`:
-
-```rust
-        match req.method.as_str() {
-            Some("ping") => self.pong(req.id, req.params).await,
-            Some(_) | None => JsonError::new(ErrorCode::MethodNotFound, None, req.id).into(),
-            }
-```

+ 0 - 54
doc/src/learn/dchat/network-tools/rpc.md

@@ -1,54 +0,0 @@
-# RPC interface
-
-Let's begin connecting dchat up to JSON-RPC using DarkFi's [rpc
-module](https://github.com/darkrenaissance/darkfi/tree/master/src/rpc).
-
-We'll start by defining a new struct called `JsonRpcInterface` that
-takes two values, an accept `Url` that will receive JSON-RPC requests,
-and a pointer to the p2p network.
-
-```rust
-{{#include ../../../../../example/dchat/src/rpc.rs:jsonrpc}}
-```
-
-We'll need to implement a trait called `RequestHandler` for
-the `JsonRpcInterface`. `RequestHandler` exposes a method called
-`handle_request()` which is a handle for processing incoming
-JSON-RPC requests. `handle_request()` takes a `JsonRequest`
-and returns a `JsonResult`. These types are defined inside
-[jsonrpc.rs](https://github.com/darkrenaissance/darkfi/blob/master/src/rpc/jsonrpc.rs)
-
-This is `JsonResult`:
-```rust
-{{#include ../../../../../src/rpc/jsonrpc.rs:jsonresult}}
-```
-
-This is `JsonRequest`:
-
-```rust
-{{#include ../../../../../src/rpc/jsonrpc.rs:jsonrequest}}
-```
-
-We'll use `handle_request()` to run a match statement on
-`JsonRequest.method`.
-
-Running a match on `method` will allow us to branch out to functions
-that respond to methods received over JSON-RPC.  We haven't implemented
-any methods yet, so for now let's just return a `JsonError`.
-
-```rust
-#[async_trait]
-impl RequestHandler for JsonRpcInterface {
-    async fn handle_request(&self, req: JsonRequest) -> JsonResult {
-        if req.params.as_array().is_none() {
-            return JsonError::new(ErrorCode::InvalidRequest, None, req.id).into()
-        }
-
-        debug!(target: "RPC", "--> {}", serde_json::to_string(&req).unwrap());
-
-        match req.method.as_str() {
-            Some(_) | None => JsonError::new(ErrorCode::MethodNotFound, None, req.id).into(),
-        }
-    }
-}
-```

+ 0 - 32
doc/src/learn/dchat/network-tools/server.md

@@ -1,32 +0,0 @@
-# RPC server
-
-To deploy the `JsonRpcInterface`, we'll need to
-create an RPC server using `listen_and_serve()`.
-`listen_and_serve()` is a method defined in DarkFi's [rpc
-module](https://github.com/darkrenaissance/darkfi/tree/master/src/rpc/server.rs).
-It starts a JSON-RPC server that is bound to the provided accept URL
-and uses our previously implemented `RequestHandler` to handle incoming
-requests.
-
-Add the following lines to `main()`:
-
-```rust
-{{#include ../../../../../example/dchat/src/main.rs:json_init}}
-```
-
-We create a new `JsonRpcInterface` inside an `Arc` pointer and pass in our
-`accept_addr` and `p2p` object.
-
-Next, we create an async block that calls `listen_and_serve()`. The async
-block uses the `move` keyword to takes ownership of the `accept_addr`
-and `JsonRpcInterface` values and pass them into `listen_and_serve()`.
-We use an `executor` to spawn `listen_and_serve()` as a new thread and
-detach it in the background.
-
-We have enabled JSON-RPC.
-
-Here's what our complete `main()` function looks like:
-
-```rust
-{{#include ../../../../../example/dchat/src/main.rs:main}}
-```

+ 3 - 0
doc/src/learn/dchat/network-tools/using-dnet.md

@@ -0,0 +1,3 @@
+# Using dnet
+
+TODO

+ 0 - 68
doc/src/learn/dchat/network-tools/using-dnetview.md

@@ -1,68 +0,0 @@
-# Using dnetview
-
-Finally, we're ready to use `dnetview`. Go to the `dnetview` directory
-and spawn a new config file by running it once:
-
-```bash
-cd darkfi
-make BINS=dnetview
-./dnetview
-```
-
-You should see the following output:
-
-```
-Config file created in '"/home/USER/.config/darkfi/dnetview_config.toml"'. Please review it and try again.
- ```
-
-Edit the config file to include the JSON-RPC accept addresses for Alice
-and Bob:
-
-```toml
-[[nodes]]
-name = "alice"
-rpc_url="tcp://127.0.0.1:55054"
-
-[[nodes]]
-name = "bob"
-rpc_url="tcp://127.0.0.1:51054"
-```
-
-Now run `dnetview`:
-
-```bash
-./dnetview
-```
-
-This is what you should see:
-
-![](images/dnetview-offline.jpg)
-
-We haven't ran Alice and Bob yet, so `dnetview` can't connect to them. So
-let's run Alice and Bob.
-
-```bash
-cargo run a
-```
-
-```bash
-cargo run b
-```
-
-Now try running `dnetview` again.
-
-![](images/dnetview-online.jpg)
-
-That's fun. Use `j` and `k` to navigate. See what happens when you select
-a `Channel`.
-
-![](images/dnetview-msgs.jpg)
-
-On each `Channel`, we see a log of messages being sent across the network.
-What happens when we send a message?
-
-![](images/dnetview-dchatmsg.jpg)
-
-This is Bob receiving a DchatMsg message on the `Channel`
-`tcp://127.0.0.1:51554`. Pretty cool.
-