From c143fef9125f3ff51e96accbabcc4a1d34f873d2 Mon Sep 17 00:00:00 2001 From: mfahampshire Date: Tue, 8 Aug 2023 11:00:11 +0200 Subject: [PATCH] tweaks to tutorial --- .../tutorials/cosmos-service/client-src.md | 8 +++-- .../src/tutorials/cosmos-service/client.md | 8 ++--- .../src/tutorials/cosmos-service/intro.md | 6 ++-- .../src/tutorials/cosmos-service/lib.md | 33 +++++++++++++++---- .../src/tutorials/cosmos-service/overview.md | 9 +++-- .../tutorials/cosmos-service/preparing-env.md | 19 ++++------- .../tutorials/cosmos-service/service-src.md | 2 +- .../src/tutorials/cosmos-service/service.md | 6 ++-- 8 files changed, 53 insertions(+), 38 deletions(-) diff --git a/documentation/dev-portal/src/tutorials/cosmos-service/client-src.md b/documentation/dev-portal/src/tutorials/cosmos-service/client-src.md index b8b223357b..63fb82b99b 100644 --- a/documentation/dev-portal/src/tutorials/cosmos-service/client-src.md +++ b/documentation/dev-portal/src/tutorials/cosmos-service/client-src.md @@ -8,11 +8,13 @@ use crate::{handle_response, wait_for_non_empty_message, RequestTypes, DEFAULT_V use cosmrs::AccountId; use nym_sdk::mixnet::MixnetClient; use nym_sphinx_addressing::clients::Recipient; -use nym_validator_client::nyxd::Coin +use nym_validator_client::nyxd::Coin; ``` +As well as importing message-handling functionality, request types, and the default RPC endpoint, this file relies on the `AccountId` type to construct blockchain addresses, the `MixnetClient` for interacting with the mixnet, the `Recipient` type to construct mixnet recipient addresses, and the `Coin` type for properly handling the returned balance of the account that will be queried. + # Querying via the Mixnet -The following is used to construct a `BalanceRequest`, send this to the supplied `service` address, and then handle the response, matching it to a `ResponseType`, in this case the only expected response, a `BalanceResponse`. +The following is used to construct a `BalanceRequest`, send this to the supplied `service` address, and then handle the response, matching it to a `ResponseType` (in this case the only expected response, a `BalanceResponse`). The actual sending of the request is performed by `client.send_bytes`: sending the serialised `BalanceRequest` to the supplied Nym address (the `Recipient` imported from the `nym_sphinx_addressing` crate). It is sending the default number of SURBs along with the message, defined [here](https://github.com/nymtech/nym/blob/develop/sdk/rust/nym-sdk/src/mixnet/client.rs#L34). @@ -50,4 +52,4 @@ pub async fn query_balance( } ``` -That is all of the client code written: now to move on to the `service` that will be interacting with the blockchain on behalf of the `client`. +That is all the client code written: now to move on to the `service` that will be interacting with the blockchain on behalf of the `client`. diff --git a/documentation/dev-portal/src/tutorials/cosmos-service/client.md b/documentation/dev-portal/src/tutorials/cosmos-service/client.md index df3751c4dd..be9f142f09 100644 --- a/documentation/dev-portal/src/tutorials/cosmos-service/client.md +++ b/documentation/dev-portal/src/tutorials/cosmos-service/client.md @@ -43,10 +43,10 @@ struct QueryBalance { ``` ## `main()` -This is the root logic of the `client`. Using `[tokio](URL_TO_DO)` for the async runtime, this function performs the following functions: -* If not already existing, creates a Nym client with config at `/tmp/client`. Otherwise it loads the already existing client from this config. -* Matches the command from the CLI - in this instance, the `QueryBalance` function which will be defined in the next section. This will create a `BalanceRequest` and send this to the `service`, before returning the response sent back to it to the main thread and printing this to the console. -* Performs a proper shutdown of the running Nym client. +This is the root logic of the `client`. Using `[tokio](https://tokio.rs/)` for the async runtime, this function performs the following functions: +* If not already existing, create a Nym client with config at `/tmp/client`. Otherwise load the already existing client from this config. +* Matche the command from the CLI - in this instance, the `QueryBalance` function which will be defined in the next section. This creates a `BalanceRequest` and sends this to the `service`, before returning the response back to the main thread and print this to the console. +* Perform a proper shutdown of the Nym client. ```rust #[tokio::main] diff --git a/documentation/dev-portal/src/tutorials/cosmos-service/intro.md b/documentation/dev-portal/src/tutorials/cosmos-service/intro.md index 5b08d0ecfe..cf9dad5fd0 100644 --- a/documentation/dev-portal/src/tutorials/cosmos-service/intro.md +++ b/documentation/dev-portal/src/tutorials/cosmos-service/intro.md @@ -1,7 +1,7 @@ -# Building a Cosmos Blockchain Service with the Rust SDK +# Interacting with a Cosmos SDK Blockchain via the Mixnet with the Rust SDK -This tutorial is for Rust developers wanting to interact with the Rust SDK and take a first step at building a service with which to interact with a blockchain. +This tutorial is for Rust developers wanting to interact with the Rust SDK and take a first step at building a service with which to interact with a Cosmos SDK blockchain. -The key here is to think of the service as a proxy: it interacts with the blockchain _on the client's behalf_, shielding it from the Validator it interacts with, whilst also being shielded from the client by the mixnet. +The key here is to think of the service as a proxy: it interacts with the blockchain _on the client's behalf_, shielding the client from the Validator it interacts with, whilst also being shielded from the client by the mixnet. > This service also nicely highlights the limitations of the mixnet - even though with this code your metadata is shielded from the Validator, and even the service does not know your Nym address, application-level information such as a blockchain address is not made private, in virtue of the fact that using the mixnet provides solely network-level privacy. For information on what application-level privacy Nym offers, check out the [coconut credential SDK example](https://nymtech.net/docs/sdk/rust.html#coconut-credential-generation). diff --git a/documentation/dev-portal/src/tutorials/cosmos-service/lib.md b/documentation/dev-portal/src/tutorials/cosmos-service/lib.md index 8adb147bd4..0be72a690d 100644 --- a/documentation/dev-portal/src/tutorials/cosmos-service/lib.md +++ b/documentation/dev-portal/src/tutorials/cosmos-service/lib.md @@ -5,7 +5,7 @@ Now move on to preparing shared data structures and functions in `src/lib.rs`. These include the request and response types the client and the service will be passing through the mixnet, as well as shared functions such as client creation, and message parsing. ## Dependencies -The dependecies for the shared `lib` file are the following: +The dependencies for the shared `lib` file are the following: ```rust use anyhow::bail; use cosmrs::AccountId; @@ -31,7 +31,7 @@ pub const DEFAULT_DENOM: &str = "unym"; pub const DEFAULT_PREFIX: &str = "n"; ``` -These define the RPC endpoint your service will use to interact with the blockchain - in this case the Sandbox testnet - as well as the coin denomination and Bech32-prefix of the blockchain accounts. +These define the RPC endpoint your service will use to interact with the blockchain - in this case the Sandbox testnet - as well as the expected coin denomination, and Bech32-prefix of addresses. ## Shared Data Structures Define the following structs for our different request and responses that will be serialised and sent through the mixnet between your client and service binaries: @@ -79,17 +79,17 @@ impl ResponseTypes { } ``` -The above data types are pretty straightforward. Even though there are only one instance of a request type (sent from client -> service) and one of a response type (service -> client) so far, a pair of enums has been defined to contain additional response or request types that will be added in the future. +The above data types are pretty straightforward. Even though there are only one instance of a request type (sent from `client` -> mixnet -> `service`) and one of a response type (`service` -> mixnet -> `client`) so far, a pair of enums has been defined to contain additional response and request types that will be added in part 2 of this tutorial, when adding credential functionality. `BalanceRequest` will be used when requesting the service to query the token balance of the supplied address on the client's behalf. You can see the information that will be returned from the chain to the service, and from the service to the client, in `BalanceResponse`. -Custom serialistion and deserialisation have been implemented for each enum for ease of future modification if required, and testing. +Custom serialistion and deserialisation have been implemented for each enum for ease of future modification and testing. ## Shared Functions Now to define functions shared by the `client` and `service` binaries. ### Client Creation -The following function is called on startup by each binary, with the `config_path` being a filepath for storing client config. +The following function is called on startup by each binary, with the `config_path` being a filepath for storing client config: ```rust // create our client with specified path for key storage @@ -107,6 +107,25 @@ pub async fn create_client(config_path: PathBuf) -> MixnetClient { } ``` +If no config files exist at the location designated by `config_path` (in this case `/tmp/service`) then the following files are generated: + +```sh +service +├── ack_key.pem +├── db.sqlite +├── db.sqlite-shm +├── db.sqlite-wal +├── gateway_details.json +├── gateway_shared.pem +├── persistent_reply_store.sqlite +├── private_encryption.pem +├── private_identity.pem +├── public_encryption.pem +└── public_identity.pem + +1 directory, 11 files +``` + > If keys and config already exist at this location, re-running this function **will not** overwrite them. ### Listening for & Parsing Incoming messages @@ -114,7 +133,7 @@ Next to define two functions: one for listening _for_ messages from the mixnet ( Both functions attempt to deserialise the vec of `ReconstructedMessages` that are reconstructed by the client from delivered Sphinx packets after decryption. -`handle_request` performs one additional function - parsing the `sender_tag` from the incoming reconstructed message. This is the randomised alphanumeric string used to identify a bucket of _SURBs_ (Single Use Reply Blocks) that are sent along with any outgoing message by default. More information about them can be found [here](https://nymtech.net/docs/architecture/traffic-flow.html#private-replies-using-surbs) but all that is necessary to know for now is that these are pre-addressed packets that clients send out with their messages. Any reply to their message that is to be sent back to them back be written to the payload of these packets, but without the entity seeing the destination address. This allows for services to _anonymously reply_ to clients without being able to doxx them. +`handle_request` performs one additional function - parsing the `sender_tag` from the incoming reconstructed message. This is the randomised alphanumeric string used to identify a bucket of _SURBs_ (Single Use Reply Blocks) that are sent along with any outgoing message by default. More information about them can be found [here](https://nymtech.net/docs/architecture/traffic-flow.html#private-replies-using-surbs) but all that is necessary to know for now is that these are pre-addressed packets that clients send out with their messages. Any reply to their message that is to be sent back to them back be written to the payload of these packets, but without the replying party being able to see the destination that the reply is being sent to. This allows for services to **anonymously reply to clients without being able to doxx them by knowing their Nym address**. ```rust pub fn handle_response(message: ReconstructedMessage) -> anyhow::Result { @@ -129,7 +148,7 @@ pub fn handle_request( } ``` -Before moving on to the `client` and `service` code, one more function is needed. This allows for both binaries to parse empty incoming messages that they might receive. This is necessary as incoming SURBs as well as requests for more SURBs contain empty data fields. +Before moving on to the `client` and `service` code, one more function is needed. This allows for both binaries to parse empty incoming messages that they might receive. This is necessary as incoming SURBs, as well as requests for more SURBs, contain empty data fields. ```rust pub async fn wait_for_non_empty_message( diff --git a/documentation/dev-portal/src/tutorials/cosmos-service/overview.md b/documentation/dev-portal/src/tutorials/cosmos-service/overview.md index a422ea4047..829ef476ee 100644 --- a/documentation/dev-portal/src/tutorials/cosmos-service/overview.md +++ b/documentation/dev-portal/src/tutorials/cosmos-service/overview.md @@ -2,16 +2,15 @@ This tutorial involves writing two pieces of code in Rust: -- A client side binary used to (for now) construct a blockchain query and send this query to a service, which will interact with a Cosmos SDK blockchain on our behalf (bear in mind this principle works for all blockchains - we're just utilising the `cosmrs` library to interact with the Nyx blockchain in this tutorial). This query will be to query the balance of an account, in preparation for spending these tokens on a credential in a subsequent tutorial. +- A client side binary used to construct a blockchain query and send this query to a service, which will query the Cosmos SDK blockchain and then pass the response back to the client (bear in mind this principle works for all blockchains - we're just utilising the `cosmrs` library to interact with the Sandbox testnet blockchain in this tutorial). This query will be to query the balance of an account, in preparation for spending these tokens on a [bandwidth credential](https://nymtech.net/docs/bandwidth-credentials.html) in a subsequent tutorial. - A service which will listen out for requests from the mixnet, act on those requests, and anonymously reply to the client sending the requests. You will learn how to do the following with the Rust SDK: - Create clients with manual storage settings. -- Parse incoming traffic from the mixnet and reply anonymously using [SURBs](). +- Parse incoming traffic from the mixnet and reply anonymously using [SURBs](https://nymtech.net/docs/architecture/traffic-flow.html#private-replies-using-surbs). > Services usually run on remote servers to assure reliable uptime and to unlink sender and receiver metadata. For demonstration purposes however, you will run both components on your local machine, looping messages through the mixnet to yourself. - ``` TODO @@ -30,9 +29,9 @@ TUTORIAL ``` -You can find the code for these components [here](). You can use it as a reference while building or simply download it and follow along as you progress through the tutorial. +You can find the code for these components [here](https://github.com/nymtech/developer-tutorials). You can use it as a reference while building or simply download it and follow along as you progress through the tutorial. -Notice that this tutorial attempts to use very few external libraries. This tutorial is not showing you how to build production-grade code, but **to understand how to connect and send messages to, as well as recieve messages from, the mixnet.** +Notice that this tutorial attempts to use very few external libraries. This tutorial is not showing you how to build production-grade code, but **to understand how to connect and send messages to, as well as receive messages from, the mixnet.** ```admonish note title="Sidenote: What is a Service / Service Provider?" 'Service' or 'Service Provider' are catchall names used to refer to any type of app that can communicate with the mixnet via a Nym client - in this case, one embedded in its app process via the Rust SDK. diff --git a/documentation/dev-portal/src/tutorials/cosmos-service/preparing-env.md b/documentation/dev-portal/src/tutorials/cosmos-service/preparing-env.md index 474a3add08..e5016e2ef2 100644 --- a/documentation/dev-portal/src/tutorials/cosmos-service/preparing-env.md +++ b/documentation/dev-portal/src/tutorials/cosmos-service/preparing-env.md @@ -33,23 +33,18 @@ cosmrs = "=0.14.0" tokio = { version = "1.24.1", features = ["rt-multi-thread", "macros"] } serde = "1.0.152" serde_json = "1.0.91" +anyhow = "1.0.72" +``` + +These are non Nym-specific dependencies for the project. `clap` is for setting up the CLI commands, `cosmrs` for cosmos-specific types and functionality, `tokio` for the async/await environment, and `serde` for (de)serialisation. `anyhow` is for catch-all error handling. + +* Next add Nym-specific dependencies. Since these libraries are not yet on [crates io](https://crates.io) then you need to import them from the Nym monorepo: +``` nym-sdk = { git = "https://github.com/nymtech/nym", rev = "5dacf0c8f8775de6168d4da808fdce56e1ac2706" } nym-sphinx-addressing = { git = "https://github.com/nymtech/nym", rev = "5dacf0c8f8775de6168d4da808fdce56e1ac2706" } nym-validator-client = { git = "https://github.com/nymtech/nym", rev = "5dacf0c8f8775de6168d4da808fdce56e1ac2706" } nym-bin-common = { git = "https://github.com/nymtech/nym", rev = "5dacf0c8f8775de6168d4da808fdce56e1ac2706" } nym-sphinx-anonymous-replies = { git = "https://github.com/nymtech/nym", rev = "5dacf0c8f8775de6168d4da808fdce56e1ac2706" } -anyhow = "1.0.72" -``` - -These are non Nym-specific dependencies for the project. `anyhow` is for catch-all error handling, `clap` is for setting up the CLI commands, `cosmrs` for cosmos-specific types and functionality, `tokio` for the async/await environment, and `serde` for (de)serialisation. - -* Next add Nym-specific dependencies. Since these libraries are not yet on [crates io](https://crates.io) then you need to import them from the Nym monorepo: -``` -nym-sdk = { git = "https://github.com/nymtech/nym" } -nym-sphinx-addressing = { git = "https://github.com/nymtech/nym" } -nym-validator-client = { git = "https://github.com/nymtech/nym" } -nym-bin-common = { git = "https://github.com/nymtech/nym" } -nym-sphinx-anonymous-replies = { git = "https://github.com/nymtech/nym" } ``` The `sphinx` dependencies are for packet- and address-related functionality, the `validator-client` for Nyx blockchain specific configs, `common` for client logging, and the `sdk` for SDK functionality: creating and managing client storage and connections, and sending and receiving messages to and from the mixnet. diff --git a/documentation/dev-portal/src/tutorials/cosmos-service/service-src.md b/documentation/dev-portal/src/tutorials/cosmos-service/service-src.md index 6fb3324726..0e463362e8 100644 --- a/documentation/dev-portal/src/tutorials/cosmos-service/service-src.md +++ b/documentation/dev-portal/src/tutorials/cosmos-service/service-src.md @@ -3,7 +3,7 @@ Now to define the logic of creating the `broadcaster` for interacting with the blockchain, and querying it in `src/service.rs`. ## Dependencies -The following dependencies are for creating a client to interact with the blockchain, and deal with the returned `Coin` type expected from the balance query. +The following dependencies are for creating a client to interact with the blockchain, and deal with the returned `Coin` type in `BalanceResponse`. ```rust use crate::{BalanceResponse, DEFAULT_DENOM, DEFAULT_VALIDATOR_RPC}; diff --git a/documentation/dev-portal/src/tutorials/cosmos-service/service.md b/documentation/dev-portal/src/tutorials/cosmos-service/service.md index f8313bed8b..055bddfd00 100644 --- a/documentation/dev-portal/src/tutorials/cosmos-service/service.md +++ b/documentation/dev-portal/src/tutorials/cosmos-service/service.md @@ -18,16 +18,16 @@ The `AnonymousSenderTag` type is used for SURBs. ## main() Also using tokio for the async runtime, `main` does the following: -* If not already existing, creates a Nym client with config at `/tmp/client`. Otherwise it loads the already existing client from this config. +* Create a Nym client with config at `/tmp/service`, or load the existing client from this config directory. * Create a `broadcaster` - this is used by the service to interact with the blockchain, using the consts defined in `src/lib.rs` as chain config. * Listen out for incoming messages, and in much the same way as the `client`, handle and match the incoming request. -* Using the `sender_tag`, anonymously reply to the Nym client in `client` with the response from the blockchain. +* Using the `sender_tag`, anonymously reply to the `client` with the response from the blockchain **without having to know the client's Nym address**. ```rust #[tokio::main] async fn main() -> anyhow::Result<()> { setup_logging(); - let mut client = create_client("/tmp/service2".into()).await; + let mut client = create_client("/tmp/service".into()).await; let our_address = client.nym_address(); println!("\nservice's nym address: {our_address}"); // the httpclient we will use to broadcast our query to the blockchain