From 7e36595d8fa7706876880b42df1c998a4b8c1478 Mon Sep 17 00:00:00 2001 From: import this <97586125+serinko@users.noreply.github.com> Date: Tue, 6 Aug 2024 12:37:37 +0000 Subject: [PATCH 01/93] [DOCs/bugfix]: Fix broken URLs (#4745) * create archive nym connect page & add redirections * add info to socks5 page * fix dev-portal links * finish URL edits and redirection --- documentation/dev-portal/src/SUMMARY.md | 9 ++++-- .../dev-portal/src/binaries/building-nym.md | 4 +-- .../dev-portal/src/clients/socks5-client.md | 2 -- .../dev-portal/src/clients/socks5/setup.md | 9 ++++-- .../src/clients/websocket/examples.md | 2 ++ .../dev-portal/src/clients/websocket/usage.md | 28 +++++++++---------- .../dev-portal/src/examples/browser-only.md | 12 ++++---- .../dev-portal/src/examples/using-nrs.md | 16 +++++------ documentation/dev-portal/src/nymvpn/cli.md | 2 +- .../src/sdk/rust/examples/credential.md | 3 +- .../dev-portal/src/sdk/rust/examples/surbs.md | 2 +- documentation/docs/book.toml | 12 ++++++-- .../docs/src/architecture/nym-vs-others.md | 9 +++--- .../src/archive/nodes/gateway-setup.md | 23 ++++++++------- .../operators/src/binaries/building-nym.md | 6 ++-- .../operators/src/legal/exit-gateway.md | 26 ++++++++--------- documentation/operators/src/sandbox.md | 2 +- .../operators/src/testing/gateway-probe.md | 4 +-- .../operators/src/testing/performance.md | 10 +++---- .../src/testing/prometheus-grafana.md | 4 +-- .../operators/src/troubleshooting/vps-isp.md | 2 +- 21 files changed, 100 insertions(+), 87 deletions(-) diff --git a/documentation/dev-portal/src/SUMMARY.md b/documentation/dev-portal/src/SUMMARY.md index 948235c69f..355ed85568 100644 --- a/documentation/dev-portal/src/SUMMARY.md +++ b/documentation/dev-portal/src/SUMMARY.md @@ -2,7 +2,7 @@ - [Introduction](introduction.md) - [Clients Overview - Start Here!](clients-overview.md) -# SDKs +# SDKs - [Rust SDK](sdk/rust/rust.md) - [Message Types](sdk/rust/message-types.md) - [Message Helpers](sdk/rust/message-helpers.md) @@ -30,7 +30,7 @@ - [Using Your Client](clients/websocket/usage.md) - [Examples](clients/websocket/examples.md) - [Socks5 Client](clients/socks5-client.md) - - [Setup & Run](clients/socks5/setup.md) + - [Setup & Run](clients/socks5/setup.md) - [Using Your Client](clients/socks5/usage.md) - [Webassembly Client](clients/webassembly-client.md) @@ -54,8 +54,13 @@ # User Manuals - [NymVPN alpha](nymvpn/intro.md) - [CLI](nymvpn/cli.md) +--- + +# Archive +- [NymConnect Setup](archive/nym-connect.md) --- + # Misc. - [Code of Conduct](coc.md) - [Licensing](licensing.md) diff --git a/documentation/dev-portal/src/binaries/building-nym.md b/documentation/dev-portal/src/binaries/building-nym.md index 47fb637c61..0bbb5e0ed1 100644 --- a/documentation/dev-portal/src/binaries/building-nym.md +++ b/documentation/dev-portal/src/binaries/building-nym.md @@ -52,10 +52,10 @@ git checkout master # master branch has the latest release version: `develop` wi cargo build --release # build your binaries with **mainnet** configuration ``` -Quite a bit of stuff gets built. The key working parts for devs are the Client binaries and the CLI tool: +Quite a bit of stuff gets built. The key working parts for devs are the Client binaries and the CLI tool: * [websocket client](../clients/websocket-client.md): `nym-client` * [socks5 client](../clients/socks5-client.md): `nym-socks5-client` -* [nym-cli tool](https://nymtech.net/docs/tools/nym-cli.md): `nym-cli` +* [nym-cli tool](https://nymtech.net/docs/tools/nym-cli.html): `nym-cli` > You cannot build from GitHub's .zip or .tar.gz archive files on the releases page - the Nym build scripts automatically include the current git commit hash in the built binary during compilation, so the build will fail if you use the archive code (which isn't a Git repository). Check the code out from github using `git clone` instead. diff --git a/documentation/dev-portal/src/clients/socks5-client.md b/documentation/dev-portal/src/clients/socks5-client.md index 6fc1e6159f..8ef8aff80f 100644 --- a/documentation/dev-portal/src/clients/socks5-client.md +++ b/documentation/dev-portal/src/clients/socks5-client.md @@ -104,8 +104,6 @@ The `--use-reply-surbs` field denotes whether you wish to send [SURBs](https://n The `--provider` field needs to be filled with the Nym address of a Network Requester that can make network requests on your behalf. If you don't want to [run your own](https://nymtech.net/operators/nodes/network-requester.md) you can select one from the [mixnet explorer](https://explorer.nymtech.net/network-components/service-providers) by copying its `Client ID` and using this as the value of the `--provider` flag. Alternatively, you could use [this list](https://harbourmaster.nymtech.net/). -Since the nodes on this list are the infrastructure for [Nymconnect](https://nymtech.net/developers/quickstart/nymconnect-gui.html) they will support all apps on the [default whitelist](https://nymtech.net/operators/nodes/network-requester.md#network-requester-whitelist): Keybase, Telegram, Electrum, Blockstream Green, and Helios. - #### Choosing a Gateway By default - as in the example above - your client will choose a random gateway to connect to. diff --git a/documentation/dev-portal/src/clients/socks5/setup.md b/documentation/dev-portal/src/clients/socks5/setup.md index 55428dae75..a1fc1210a3 100644 --- a/documentation/dev-portal/src/clients/socks5/setup.md +++ b/documentation/dev-portal/src/clients/socks5/setup.md @@ -1,9 +1,14 @@ -# Setup +# Setup > `nym-socks5-client` now also supports SOCKS4 and SOCKS4A protocols as well as SOCKS5. The Nym socks5 client allows you to proxy traffic from a desktop application through the mixnet, meaning you can send and receive information from remote application servers without leaking metadata which can be used to deanonymise you, even if you're using an encrypted application such as Signal. +```admonish info +Since the beginning of 2024 NymConnect is no longer maintained. Nym is developing a new client called [NymVPN](https://nymvpn.com), an application routing all users traffic thorugh the mixnet. +If users want to route their traffic through socks5 we advice to use this client. If you want to run deprecated NymConnect, visit [NymConnect archive page](../../archive/nym-connect.md) with setup and application examples. +``` + ## Setup and Run ### Download or compile socks5 client @@ -38,5 +43,3 @@ Now your client is initialised, start it with the following: ``` ./nym-socks5-client run --id ``` - - diff --git a/documentation/dev-portal/src/clients/websocket/examples.md b/documentation/dev-portal/src/clients/websocket/examples.md index 7367c29180..df9eb6d657 100644 --- a/documentation/dev-portal/src/clients/websocket/examples.md +++ b/documentation/dev-portal/src/clients/websocket/examples.md @@ -12,4 +12,6 @@ All of these code examples will do the following: By varying the message content, you can easily build sophisticated service provider apps. For example, instead of printing the response received from the mixnet, your service provider might take some action on behalf of the user - perhaps initiating a network request, a blockchain transaction, or writing to a local data store. + diff --git a/documentation/dev-portal/src/clients/websocket/usage.md b/documentation/dev-portal/src/clients/websocket/usage.md index aab3af6b2b..ed8c0da6f1 100644 --- a/documentation/dev-portal/src/clients/websocket/usage.md +++ b/documentation/dev-portal/src/clients/websocket/usage.md @@ -1,17 +1,17 @@ # Using Your Client The Nym native client exposes a websocket interface that your code connects to. The **default** websocket port is `1977`, you can override that in the client config if you want. -Once you have a websocket connection, interacting with the client involves piping messages down the socket and listening for incoming messages. +Once you have a websocket connection, interacting with the client involves piping messages down the socket and listening for incoming messages. -# Message Requests -There are a number of message types that you can send up the websocket as defined [here](https://github.com/nymtech/nym/blob/develop/clients/native/websocket-requests/src/requests.rs): +# Message Requests +There are a number of message types that you can send up the websocket as defined [here](https://github.com/nymtech/nym/blob/develop/clients/native/websocket-requests/src/requests.rs): ```rust,noplayground {{#include ../../../../../clients/native/websocket-requests/src/requests.rs:55:97}} ``` ## Getting your own address -When you start your app, it is best practice to ask the native client to tell you what your own address is (from the generated configuration files - see [here](https://nymtech.net/docs/architecture/addressing-system.md) for more on Nym's addressing scheme). If you are running a service, you need to do this in order to know what address to give others. In a client-side piece of code you can also use this as a test to make sure your websocket connection is running smoothly. To do this, send: +When you start your app, it is best practice to ask the native client to tell you what your own address is (from the generated configuration files . If you are running a service, you need to do this in order to know what address to give others. In a client-side piece of code you can also use this as a test to make sure your websocket connection is running smoothly. To do this, send: ```json { @@ -28,9 +28,9 @@ You'll receive a response of the format: } ``` -See [here](https://github.com/nymtech/nym/blob/93cc281abc2cc951023b51746fa6f2ead1f56c46/clients/native/examples/python-examples/websocket/textsend.py#L16C9-L16C9) for an example of this being used. +See [here](https://github.com/nymtech/nym/blob/93cc281abc2cc951023b51746fa6f2ead1f56c46/clients/native/examples/python-examples/websocket/textsend.py#L16C9-L16C9) for an example of this being used. -> Note that all the pieces of native client example code begin with printing the selfAddress. Examples exist for Rust, Go, Javascript, and Python. +> Note that all the pieces of native client example code begin with printing the selfAddress. Examples exist for Rust, Go, Javascript, and Python. ## Sending text If you want to send text information through the mixnet, format a message like this one and poke it into the websocket: @@ -65,26 +65,26 @@ Your client will send along a number of `replySurbs` to the recipient of the mes ```json { "type": "sendAnonymous", - "message": "something you want to keep secret", - "recipient": "71od3ZAupdCdxeFNg8sdonqfZTnZZy1E86WYKEjxD4kj@FWYoUrnKuXryysptnCZgUYRTauHq4FnEFu2QGn5LZWbm", + "message": "something you want to keep secret", + "recipient": "71od3ZAupdCdxeFNg8sdonqfZTnZZy1E86WYKEjxD4kj@FWYoUrnKuXryysptnCZgUYRTauHq4FnEFu2QGn5LZWbm", "replySurbs": 20 // however many reply SURBs to send along with your message } ``` -See ['Replying to SURB Messages'](#replying-to-surb-messages) below for an example of how to deal with incoming messages that have SURBs attached. +See ['Replying to SURB Messages'](#replying-to-surb-messages) below for an example of how to deal with incoming messages that have SURBs attached. -Deciding on the amount of SURBs to generate and send along with outgoing messages depends on the expected size of the reply. You might want to send a lot of SURBs in order to make sure you get your response as quickly as possible (but accept the minor additional latency when sending, as your client has to generate and encrypt the packets), or you might just send a few (e.g. 20) and then if your response requires more SURBs, send them along, accepting the additional latency in getting your response. +Deciding on the amount of SURBs to generate and send along with outgoing messages depends on the expected size of the reply. You might want to send a lot of SURBs in order to make sure you get your response as quickly as possible (but accept the minor additional latency when sending, as your client has to generate and encrypt the packets), or you might just send a few (e.g. 20) and then if your response requires more SURBs, send them along, accepting the additional latency in getting your response. ## Sending binary data You can also send bytes instead of JSON. For that you have to send a binary websocket frame containing a binary encoded Nym [`ClientRequest`](https://github.com/nymtech/nym/blob/develop/clients/native/websocket-requests/src/requests.rs#L25) containing the same information. -> As a response the `native-client` will send a `ServerResponse` to be decoded. See [Message Responses](#message-responses) below for more. +> As a response the `native-client` will send a `ServerResponse` to be decoded. See [Message Responses](#message-responses) below for more. You can find examples of sending and receiving binary data in the [code examples](https://github.com/nymtech/nym/tree/master/clients/native/examples), and an example project from the Nym community [BTC-BC](https://github.com/sgeisler/btcbc-rs/): Bitcoin transaction transmission via Nym, a client and service provider written in Rust. ## Replying to SURB messages -Each bucket of `replySURBs`, when received as part of an incoming message, has a unique session identifier, which **only identifies the bucket of pre-addressed packets**. This is necessary to make sure that your app is replying to the correct people with the information meant for them in a situation where multiple clients are sending requests to a single service. +Each bucket of `replySURBs`, when received as part of an incoming message, has a unique session identifier, which **only identifies the bucket of pre-addressed packets**. This is necessary to make sure that your app is replying to the correct people with the information meant for them in a situation where multiple clients are sending requests to a single service. Constructing a reply with SURBs looks something like this (where `senderTag` was parsed from the incoming message) @@ -107,9 +107,9 @@ Errors from the app's client, or from the gateway, will be sent down the websock ``` ## LaneQueueLength -This is currently only used in the [Socks Client](../socks5-client.md) to keep track of the number of Sphinx packets waiting to be sent to the mixnet via being slotted amongst cover traffic. As this value becomes larger, the client signals to the application it should slow down the speed with which it writes to the proxy. This is to stop situations arising whereby an app connected to the client appears as if it has sent (e.g.) a bunch of messages and is awaiting a reply, when they in fact have not been sent through the mixnet yet. +This is currently only used in the [Socks Client](../socks5-client.md) to keep track of the number of Sphinx packets waiting to be sent to the mixnet via being slotted amongst cover traffic. As this value becomes larger, the client signals to the application it should slow down the speed with which it writes to the proxy. This is to stop situations arising whereby an app connected to the client appears as if it has sent (e.g.) a bunch of messages and is awaiting a reply, when they in fact have not been sent through the mixnet yet. -# Message Responses +# Message Responses Responses to your messages are defined [here](https://github.com/nymtech/nym/blob/develop/clients/native/websocket-requests/src/responses.rs): ```rust,noplayground diff --git a/documentation/dev-portal/src/examples/browser-only.md b/documentation/dev-portal/src/examples/browser-only.md index b41367d76e..01472bef22 100644 --- a/documentation/dev-portal/src/examples/browser-only.md +++ b/documentation/dev-portal/src/examples/browser-only.md @@ -1,12 +1,12 @@ # Browser only -With the Typescript SDK you can run a Nym client in a webworker - meaning you can connect to the mixnet through the browser without having to worry about any other code than your web framework. +With the Typescript SDK you can run a Nym client in a webworker - meaning you can connect to the mixnet through the browser without having to worry about any other code than your web framework. -- Oreowallet have integrated `mixFetch` into their browser-extension wallet to run transactions through the mixnet. - - [Codebase](https://github.com/oreoslabs/oreowallet-extension/tree/mixFetch) +- Oreowallet have integrated `mixFetch` into their browser-extension wallet to run transactions through the mixnet. + - [Codebase](https://github.com/oreoslabs/oreowallet-extension/tree/mixFetch) -- [NoTrustVerify](https://notrustverify.ch/) have set up an example application using [`mixFetch`](https://sdk.nymtech.net/examples/mix-fetch) to fetch crypto prices from CoinGecko over the mixnet. - - [Website](https://notrustverify.github.io/mixfetch-examples/) - - [Codebase](https://github.com/notrustverify/mixfetch-examples) +- [NoTrustVerify](https://notrustverify.ch/) have set up an example application using [`mixFetch`](https://sdk.nymtech.net/examples/mix-fetch) to fetch crypto prices from CoinGecko over the mixnet. + - [Website](https://notrustverify.github.io/mixfetch-examples/) + - [Codebase](https://github.com/notrustverify/mixfetch-examples) - There is a coconut-scheme based Credential Library playground [here](https://coco-demo.nymtech.net/). This is a WASM implementation of our Coconut libraries which generate raw Coconut credentials. Test it to create and re-randomize your own credentials. For more information on what is happening here check out the [Coconut docs](https://nymtech.net/docs/coconut.html). diff --git a/documentation/dev-portal/src/examples/using-nrs.md b/documentation/dev-portal/src/examples/using-nrs.md index 0732340b79..7111f62401 100644 --- a/documentation/dev-portal/src/examples/using-nrs.md +++ b/documentation/dev-portal/src/examples/using-nrs.md @@ -1,17 +1,17 @@ # Apps Using Network Requesters -These applications utilise custom app logic in the user-facing apps in order to communicate using the mixnet as a transport layer, without having to rely on custom server-side logic. Instead, they utilise existing Nym infrastructure - [Network Requesters](https://nymtech.net/operators/nodes/network-requester-setup.html) - with a custom whitelist addition. +These applications utilise custom app logic in the user-facing apps in order to communicate using the mixnet as a transport layer, without having to rely on custom server-side logic. Instead, they utilise existing Nym infrastructure - Network Requesters - now embeded in `nym-node` running as `exit-gateway`. -If you are sending 'normal' application traffic, and/or don't require and custom logic to be happening on the 'other side' of the mixnet, this is most likely the best option to take as a developer who wishes to privacy-enhance their application. +If you are sending 'normal' application traffic, and/or don't require and custom logic to be happening on the 'other side' of the mixnet, this is most likely the best option to take as a developer who wishes to privacy-enhance their application. + +> Nym will soon be switching from a whitelist-based approach to a blocklist-based approach to filtering traffic. As such, it will soon be even easier for developers to utilise the mixnet, as they will not have to run their own NRs or have to add their domains to the whitelist -> Nym will soon be switching from a whitelist-based approach to a blocklist-based approach to filtering traffic. As such, it will soon be even easier for developers to utilise the mixnet, as they will not have to run their own NRs or have to add their domains to the whitelist - - DarkFi over Nym leverages Nym’s mixnet as a pluggable transport for DarkIRC, their p2p IRC variant. Users can anonymously connect to peers over the network, ensuring secure and private communication within the DarkFi ecosystem. Written in **Rust**. - [Docs](https://darkrenaissance.github.io/darkfi/clients/nym_outbound.html?highlight=nym#3--run) - - [Github](https://github.com/darkrenaissance/darkfi/tree/master/doc) + - [Github](https://github.com/darkrenaissance/darkfi/tree/master/doc) -- MiniBolt is a complete guide to building a Bitcoin & Lightning full node on a personal computer. It has the capacity to run network traffic (transactions and syncing) over the mixnet, so you can privately sync your node and not expose your home IP to the wider world when interacting with the rest of the network! +- MiniBolt is a complete guide to building a Bitcoin & Lightning full node on a personal computer. It has the capacity to run network traffic (transactions and syncing) over the mixnet, so you can privately sync your node and not expose your home IP to the wider world when interacting with the rest of the network! - [Docs](https://v2.minibolt.info/bonus-guides/system/nym-mixnet#proxying-bitcoin-core) - [Codebase](https://github.com/minibolt-guide/minibolt) -- Email over Nym is a set of configuration options to set up a Network Requester to send and recieve emails over Nym, using something like Thunderbird. - - [Codebase](https://github.com/dial0ut/nymstr-email) \ No newline at end of file +- Email over Nym is a set of configuration options to set up a Network Requester to send and recieve emails over Nym, using something like Thunderbird. + - [Codebase](https://github.com/dial0ut/nymstr-email) diff --git a/documentation/dev-portal/src/nymvpn/cli.md b/documentation/dev-portal/src/nymvpn/cli.md index b921d4f859..8e682dc987 100644 --- a/documentation/dev-portal/src/nymvpn/cli.md +++ b/documentation/dev-portal/src/nymvpn/cli.md @@ -171,7 +171,7 @@ If you want to run NymVPN CLI in Nym Sandbox environment, there are a few adjust curl -o sandbox.env -L https://raw.githubusercontent.com/nymtech/nym/develop/envs/sandbox.env ``` -2. Check available Gateways at [nymvpn.com/en/alpha/api/gateways](https://nymvpn.com/en/alpha/api/gateways) +2. Check available Gateways at [Sandbox API](https://sandbox-nym-api1.nymtech.net/api/v1/gateways) or [Sandbox Swagger page](https://sandbox-nym-api1.nymtech.net/api/swagger/index.html) 3. Run with a flag `-c` ```sh diff --git a/documentation/dev-portal/src/sdk/rust/examples/credential.md b/documentation/dev-portal/src/sdk/rust/examples/credential.md index 979d021914..f29d6748ba 100644 --- a/documentation/dev-portal/src/sdk/rust/examples/credential.md +++ b/documentation/dev-portal/src/sdk/rust/examples/credential.md @@ -5,5 +5,4 @@ The following code shows how you can use the SDK to create and use a credential {{#include ../../../../../../sdk/rust/nym-sdk/examples/bandwidth.rs}} ``` -You can read more about Coconut credentials (also referred to as `zk-Nym`) [here](https://nymtech.net/docs/coconut.md). - +You can read more about Coconut credentials (also referred to as `zk-Nym`) [here](https://nymtech.net/docs/coconut.html). diff --git a/documentation/dev-portal/src/sdk/rust/examples/surbs.md b/documentation/dev-portal/src/sdk/rust/examples/surbs.md index 3cedd45ba1..d3b6b2da1b 100644 --- a/documentation/dev-portal/src/sdk/rust/examples/surbs.md +++ b/documentation/dev-portal/src/sdk/rust/examples/surbs.md @@ -1,7 +1,7 @@ # Anonymous Replies with SURBs (Single Use Reply Blocks) Both functions used to send messages through the mixnet (`send_message` and `send_plain_message`) send a pre-determined number of SURBs along with their messages by default. -You can read more about how SURBs function under the hood [here](https://nymtech.net/docs/architecture/traffic-flow.md#private-replies-using-surbs). +You can read more about how SURBs function under the hood [here](https://nymtech.net/docs/architecture/traffic-flow.html#private-replies-using-surbs). In order to reply to an incoming message using SURBs, you can construct a `recipient` from the `sender_tag` sent along with the message you wish to reply to: diff --git a/documentation/docs/book.toml b/documentation/docs/book.toml index 87087c093d..45eb6e51ae 100644 --- a/documentation/docs/book.toml +++ b/documentation/docs/book.toml @@ -18,8 +18,8 @@ pagetoc = true sidebar-width = "280px" content-max-width = "80%" root-font-size = "70%" -# if you need to change anything in the index.hbs file you need to turn this to `false`, rebuild the book, -# probably remove the additional `comment` that gets appended to the header, and then change this back to `true`. +# if you need to change anything in the index.hbs file you need to turn this to `false`, rebuild the book, +# probably remove the additional `comment` that gets appended to the header, and then change this back to `true`. # this is because of a bug in the `mdbook-theme` plugin turn-off = true @@ -103,3 +103,11 @@ copy-js = true # include Javascript code for search [output.linkcheck] warning-policy = "warn" + +[output.html.redirect] +"/sdk/rust/examples/socks.html" = "https://nymtech.net/developers/sdk/rust/examples/socks.html" +"/clients/overview.html" = "https://nymtech.net/developers/clients-overview.html" +"/sdk/rust/rust.html" = "https://nymtech.net/developers/sdk/rust/rust.html" +"/clients/socks5-client.html" = "https://nymtech.net/developers/clients/socks5-client.html" +"/clients/webassembly-client.html" = "https://nymtech.net/developers/clients/webassembly-client.html" +"/sdk/typescript.html" = "https://sdk/nymtech.net" diff --git a/documentation/docs/src/architecture/nym-vs-others.md b/documentation/docs/src/architecture/nym-vs-others.md index 27ec3a4f86..de654675ed 100644 --- a/documentation/docs/src/architecture/nym-vs-others.md +++ b/documentation/docs/src/architecture/nym-vs-others.md @@ -4,11 +4,12 @@ Nym is the first system we're aware of which provides integrated protection on both the network and transaction level at once. This seamless approach gives the best possible privacy protections, ensuring that nothing falls through the cracks between systems. -The diagram and brief explainer texts below give a high level overview of the difference between Nym and other comparable systems. +The diagram and brief explainer texts below give a high level overview of the difference between Nym and other comparable systems. -> If you want to dig more deeply into the way traffic is packetised and moved through the mixnet, check out the [Mixnet Traffic Flow](https://nymtech.net/docs/architecture/traffic-flow.html) page of the docs. - - +> If you want to dig more deeply into the way traffic is packetised and moved through the mixnet, check out the [Mixnet Traffic Flow](https://nymtech.net/docs/architecture/traffic-flow.html) page of the docs. + ### Nym vs VPNs diff --git a/documentation/operators/src/archive/nodes/gateway-setup.md b/documentation/operators/src/archive/nodes/gateway-setup.md index c48bc6608a..06b87fca1c 100644 --- a/documentation/operators/src/archive/nodes/gateway-setup.md +++ b/documentation/operators/src/archive/nodes/gateway-setup.md @@ -23,7 +23,7 @@ Make sure you do the preparation listed in the [preliminary steps page](initial- ## Gateway setup -Now that you have built the codebase, set up your wallet, and have a VPS with the `nym-gateway` binary, you can set up your gateway with the instructions below. +Now that you have built the codebase, set up your wallet, and have a VPS with the `nym-gateway` binary, you can set up your gateway with the instructions below. To begin, move to `/target/release` directory from which you run the node commands: @@ -47,10 +47,10 @@ You can also check the various arguments required for individual commands with: ## Initialising your Gateway -As Nym developers build towards [Exit Gateway](../../legal/exit-gateway.md) functionality, operators can now run their `nym-gateway` binary with inbuilt Network Requester and include the our new [exit policy](https://nymtech.net/.wellknown/network-requester/exit-policy.txt). Considering the plan to [*smoosh*](../faq/smoosh-faq.md) all the nodes into one binary and have wide opened Exit Gateways, we recommend this setup, instead of operating two separate binaries. +As Nym developers build towards [Exit Gateway](../../legal/exit-gateway.md) functionality, operators can now run their `nym-gateway` binary with inbuilt Network Requester and include the our new [exit policy](https://nymtech.net/.wellknown/network-requester/exit-policy.txt). Considering the plan to [*smoosh*](../faq/smoosh-faq.md) all the nodes into one binary and have wide opened Exit Gateways, we recommend this setup, instead of operating two separate binaries. ```admonish warning -Before you start an Exit Gateway, read our [Operators Legal Forum](../legal/exit-gateway.md) page and [*Project Smoosh FAQ*](../faq/smoosh-faq.md). +Before you start an Exit Gateway, read our [Operators Legal Forum](../../legal/exit-gateway.md) page and [*Project Smoosh FAQ*](../faq/smoosh-faq.md). ``` ```admonish info @@ -68,9 +68,9 @@ An operator can initialise the Exit Gateway functionality by adding Network Requ ``` -You can see that the printed information besides *identity* and *sphinx keys* also includes a long string called *address*. This is the address to be provided to your local [socks5 client](https://nymtech.net/docs/clients/socks5-client.html) as a `--provider` if you wish to connect to your own Exit Gateway. +You can see that the printed information besides *identity* and *sphinx keys* also includes a long string called *address*. This is the address to be provided to your local [socks5 client](https://nymtech.net/docs/clients/socks5-client.html) as a `--provider` if you wish to connect to your own Exit Gateway. -Additionally +Additionally #### Add Network Requester to an existing Gateway @@ -83,10 +83,10 @@ See the options: ``` -To setup Exit Gateway functionality with our new [exit policy](https://nymtech.net/.wellknown/network-requester/exit-policy.txt) add a flag `--with-exit-policy true`. +To setup Exit Gateway functionality with our new [exit policy](https://nymtech.net/.wellknown/network-requester/exit-policy.txt) add a flag `--with-exit-policy true`. ``` -./nym-gateway setup-network-requester --enabled true --with-exit-policy true --id +./nym-gateway setup-network-requester --enabled true --with-exit-policy true --id ``` Say we have a Gateway with `` as `new-gateway`, originally initialised and ran without the Exit Gateway functionality. To change the setup, run: @@ -156,7 +156,7 @@ The `run` command starts the Gateway: ## Bonding your Gateway ```admonish info -Before you bond your Gateway, please make sure the [firewall configuration](./maintenance.md#configure-your-firewall) is setup so your Gateway can be reached from the outside. You can also setup WSS and automate your Gateway to simplify the operation overhead. We highly recommend to run any of these steps before bonding to prevent disruption of your Gateway's routing score later on. +Before you bond your Gateway, please make sure the [firewall configuration](../../nodes/maintenance.md#configure-your-firewall) is setup so your Gateway can be reached from the outside. You can also setup WSS and automate your Gateway to simplify the operation overhead. We highly recommend to run any of these steps before bonding to prevent disruption of your Gateway's routing score later on. ``` ### Via the Desktop wallet (recommended) @@ -167,7 +167,7 @@ You can bond your Gateway via the Desktop wallet. **Make sure your Gateway is ru 2. Enter the `Amount`, `Operating cost` and press `Next`. -3. You will be asked to run a the `sign` command with your `gateway` - copy and paste the long signature `` and paste it as a value of `--contract-msg` in the following command: +3. You will be asked to run a the `sign` command with your `gateway` - copy and paste the long signature `` and paste it as a value of `--contract-msg` in the following command: ``` ./nym-gateway sign --id --contract-msg @@ -186,7 +186,7 @@ It will look something like this (as `` we used `supergateway`): |_| |_|\__, |_| |_| |_| |___/ - (nym-gateway - version v1.1.) + (nym-gateway - version v1.1.) >>> attempting to sign 2Mf8xYytgEeyJke9LA7TjhHoGQWNBEfgHZtTyy2krFJfGHSiqy7FLgTnauSkQepCZTqKN5Yfi34JQCuog9k6FGA2EjsdpNGAWHZiuUGDipyJ6UksNKRxnFKhYW7ri4MRduyZwbR98y5fQMLAwHne1Tjm9cXYCn8McfigNt77WAYwBk5bRRKmC34BJMmWcAxphcLES2v9RdSR68tkHSpy2C8STfdmAQs3tZg8bJS5Qa8pQdqx14TnfQAPLk3QYCynfUJvgcQTrg29aqCasceGRpKdQ3Tbn81MLXAGAs7JLBbiMEAhCezAr2kEN8kET1q54zXtKz6znTPgeTZoSbP8rzf4k2JKHZYWrHYF9JriXepuZTnyxAKAxvGFPBk8Z6KAQi33NRQkwd7MPyttatHna6kG9x7knffV6ebGzgRBf7NV27LurH8x4L1uUXwm1v1UYCA1WSBQ9Pp2JW69k5v5v7G9gBy8RUcZnMbeL26Qqb8WkuGcmuHhaFfoqSfV7PRHPpPT4M8uRqUyR4bjUtSJJM1yh6QSeZk9BEazzoJqPeYeGoiFDZ3LMj2jesbJweQR4caaYuRczK92UGSSqu9zBKmE45a @@ -206,7 +206,7 @@ It will look something like this (as `` we used `supergateway`): * And paste it into the wallet nodal, press `Next` and confirm the transaction. -![Paste Signature](../../images/wallet-screenshots/wallet-gateway-sign.png) +![Paste Signature](../../images/wallet-screenshots/wallet-gateway-sign.png) *This image is just an example, copy-paste your own base58-encoded signature.* * Your Gateway is now bonded. @@ -220,4 +220,3 @@ If you want to bond your Gateway via the CLI, then check out the [relevant secti ## Maintenance For Gateway upgrade, firewall setup, port configuration, API endpoints, VPS suggestions, automation, WSS setup and more, see the [maintenance page](../../nodes/maintenance.md) - diff --git a/documentation/operators/src/binaries/building-nym.md b/documentation/operators/src/binaries/building-nym.md index d0aa403376..42165b9bc8 100644 --- a/documentation/operators/src/binaries/building-nym.md +++ b/documentation/operators/src/binaries/building-nym.md @@ -56,9 +56,9 @@ Quite a bit of stuff gets built. The key working parts are: * [Nym Node](../nodes/nym-node.md): `nym-node` * [Validator](../nodes/validator-setup.md) -* [websocket client](https://nymtech.net/docs/clients/websocket-client.html): `nym-client` -* [socks5 client](https://nymtech.net/docs/clients/socks5-client.html): `nym-socks5-client` -* [webassembly client](https://nymtech.net/docs/clients/webassembly-client.html): `webassembly-client` +* [websocket client](https://nymtech.net/developers/clients/websocket-client.html): `nym-client` +* [socks5 client](https://nymtech.net/developers/clients/socks5-client.html): `nym-socks5-client` +* [webassembly client](https://nymtech.net/developers/clients/webassembly-client.html): `webassembly-client` * [nym-cli tool](https://nymtech.net/docs/tools/nym-cli.html): `nym-cli` * [nym-api](../nodes/nym-api.md): `nym-api` * [nymvisor](../nodes/nymvisor-upgrade.md): `nymvisor` diff --git a/documentation/operators/src/legal/exit-gateway.md b/documentation/operators/src/legal/exit-gateway.md index 9294e97837..7e0f5cc71c 100644 --- a/documentation/operators/src/legal/exit-gateway.md +++ b/documentation/operators/src/legal/exit-gateway.md @@ -6,7 +6,7 @@ The entire content of this page is under [Creative Commons Attribution 4.0 Inter This page is a part of Nym Community Legal Forum and its content is composed by shared advices in [Node Operators Legal Forum](https://matrix.to/#/!YfoUFsJjsXbWmijbPG:nymtech.chat?via=nymtech.chat&via=matrix.org) (Matrix chat) as well as though pull requests done by the node operators directly to our [repository](https://github.com/nymtech/nym/tree/develop/documentation/operators/src), reviewed by Nym DevRels. -This document presents an initiative to further support Nym’s mission of allowing privacy for everyone everywhere. This would be achieved with the support of Nym node operators operating Gateways and opening these to any online service. Such setup needs a **clear policy**, one which will remain the **same for all operators** running Nym nodes. The [proposed **Exit policy**](https://nymtech.net/.wellknown/network-requester/exit-policy.txt) is a combination of two existing safeguards: [Tor Null ‘deny’ list](https://tornull.org/) and [Tor reduced policy](https://tornull.org/tor-reduced-reduced-exit-policy.php). +This document presents an initiative to further support Nym’s mission of allowing privacy for everyone everywhere. This would be achieved with the support of Nym node operators operating Gateways and opening these to any online service. Such setup needs a **clear policy**, one which will remain the **same for all operators** running Nym nodes. The [proposed **Exit policy**](https://nymtech.net/.wellknown/network-requester/exit-policy.txt) is a combination of two existing safeguards: [Tor Null ‘deny’ list](https://tornull.org/) and Tor reduced policy. All the technical changes on the side of Nym nodes - ***Project Smoosh*** - are described in the [FAQ section](../archive/faq/smoosh-faq.md). @@ -17,13 +17,13 @@ Nym core team cannot provide comprehensive legal advice across all jurisdictions ## Summary -* This document outlines a plan to change Nym Gateways from operating with an ‘allow’ to a ‘deny’ list to enable broader uptake and usage of the Nym Mixnet. It provides operators with an overview of the plan, pros and cons, legal as well as technical advice. +* This document outlines a plan to change Nym Gateways from operating with an ‘allow’ to a ‘deny’ list to enable broader uptake and usage of the Nym Mixnet. It provides operators with an overview of the plan, pros and cons, legal as well as technical advice. * Nym is committed to ensuring privacy for all users, regardless of their location and for the broadest possible range of online services. In order to achieve this aim, the Nym Mixnet needs to increase its usability across a broad range of apps and services. -* Currently, Nym Gateway nodes only enable access to apps and services that are on an ‘allow’ list that is maintained by the core team. +* Currently, Nym Gateway nodes only enable access to apps and services that are on an ‘allow’ list that is maintained by the core team. -* To decentralise and enable privacy for a broader range of services, this initiative will have to transition from the current ‘allow’ list to a ‘deny’ list - [exit policy](https://nymtech.net/.wellknown/network-requester/exit-policy.txt). In accordance with the [Tor Null 'deny' list](https://tornull.org/) and [Tor reduced policy](https://tornull.org/tor-reduced-reduced-exit-policy.php), which are two established safeguards. +* To decentralise and enable privacy for a broader range of services, this initiative will have to transition from the current ‘allow’ list to a ‘deny’ list - [exit policy](https://nymtech.net/.wellknown/network-requester/exit-policy.txt). In accordance with the Tor Null 'deny' list and [Tor reduced policy](https://tornull.org/tor-reduced-reduced-exit-policy.php), which are two established safeguards. * This will enhance the usage and appeal of Nym products for end users. As a result, increased usage will ultimately lead to higher revenues for Nym operators. @@ -52,7 +52,7 @@ Previous setup: Running nodes supporting strict SOCKS5 app-based traffic | Technical | - No changes required in technical setup | | | Operational | - No impact on operators operations (e.g., relationships with VPS providers)
- Low overhead
- Can be run as an individual | | | Legal | - Limited legal risks for operators | | -| Financial | | - Low revenues for operators due to limited product traction | +| Financial | | - Low revenues for operators due to limited product traction | The new setup: Running nodes supporting traffic of any online service (with safeguards in the form of a denylist) @@ -66,11 +66,11 @@ The new setup: Running nodes supporting traffic of any online service (with safe ## Exit Gateways: New setup -In our previous technical setup, Network Requesters acted as a proxy, and only made requests that match an allow list. That was a default IP based list of allowed domains stored at Nym page in a centralised fashion possibly re-defined by any Network Requester operator. +In our previous technical setup, Network Requesters acted as a proxy, and only made requests that match an allow list. That was a default IP based list of allowed domains stored at Nym page in a centralised fashion possibly re-defined by any Network Requester operator. This restricts the hosts that the NymConnect app can connect to and has the effect of selectively supporting messaging services (e.g. Telegram, Matrix) or crypto wallets (e.g. Electrum or Monero). Operators of Network Requesters can have confidence that the infrastructure they run only connects to a limited set of public internet hosts. -The principal change in the new configuration is to make this short allow list more permissive. Nym's [exit policy](https://nymtech.net/.wellknown/network-requester/exit-policy.txt) will restrict the hosts to which Nym Mixnet and Nym VPN users are permitted to connect. This will be done in an effort to protect the operators, as Gateways will act both as SOCKS5 Network Requesters, and exit nodes for IP traffic from Nym Mixnet VPN and VPN clients (both wrapped in the same app). +The principal change in the new configuration is to make this short allow list more permissive. Nym's [exit policy](https://nymtech.net/.wellknown/network-requester/exit-policy.txt) will restrict the hosts to which Nym Mixnet and Nym VPN users are permitted to connect. This will be done in an effort to protect the operators, as Gateways will act both as SOCKS5 Network Requesters, and exit nodes for IP traffic from Nym Mixnet VPN and VPN clients (both wrapped in the same app). As of now we the Gateways will be defaulted to a combination of [Tor Null ‘deny’ list](https://tornull.org/) (note: Not affiliated with Tor) - reproduction permitted under Creative Commons Attribution 3.0 United States License which is IP-based, e.g., `ExitPolicy reject 5.188.10.0/23:*` and [Tor reduced policy](https://tornull.org/tor-reduced-reduced-exit-policy.php). Whether we will stick with this list, do modifications or compile another one is still a subject of discussion. In all cases, this policy will remain the same for all the nodes, without any option to modify it by Nym node operators to secure stable and reliable service for the end users. @@ -82,14 +82,14 @@ We also recommend operators to check the technical advice from [Tor](https://com Giving the legal similarity between Nym Exit Gateways and Tor Exit Relays, it is helpful to have a look in [Tor community Exit Guidelines](https://community.torproject.org/relay/community-resources/tor-exit-guidelines/). This chapter is an exert of tor page. -Note that Tor states: +Note that Tor states: > This FAQ is for informational purposes only and does not constitute legal advice. -*Check legal advice prior to running an exit relay* +*Check legal advice prior to running an exit relay* * Understand the risks associated with running an exit relay; E.g., know legal paragraphs relevant in the country of operations: - US [DMCA 512](https://www.law.cornell.edu/uscode/text/17/512); see [EFF's Legal FAQ for Tor Operators](https://community.torproject.org/relay/community-resources/eff-tor-legal-faq) (a very good and relevant read for other countries as well) - - Germany’s [TeleMedienGesetz 8](http://www.gesetze-im-internet.de/tmg/__8.html) and [15](http://www.gesetze-im-internet.de/tmg/__15.html) + - Germany’s [TeleMedienGesetz 8](https://www.gesetze-im-internet.de/tmg/__8.html) and 15](https://www.gesetze-im-internet.de/tmg/__15.html) - Netherlands: [Artikel 6:196c BW](http://wetten.overheid.nl/BWBR0005289/Boek6/Titel3/Afdeling4A/Artikel196c/) - Austria: [E-Commerce-Gesetz 13](http://www.ris.bka.gv.at/Dokument.wxe?Abfrage=Bundesnormen&Dokumentnummer=NOR40025809) - Sweden: [16-19 2002:562](https://lagen.nu/2002:562#P16S1) @@ -100,9 +100,9 @@ Note that Tor states: * Consult a lawyer / local digital rights association / the EFF prior to operating an exit relay, especially in a place where exit relay operators have been harassed or not operating before. Note that Tor DOES NOT provide legal advice for specific countries. It only provides general advice (itself or in partnership), eventually skewed towards [US audiences](https://www.eff.org/pages/legal-faq-tor-relay-operators). -*Run an exit relay within an entity* +*Run an exit relay within an entity* -As an organisation - it might help from a liability perspective +As an organisation - it might help from a liability perspective * Within your university * With a node operators’ association (e.g., a Torservers.net partner) * Within a company @@ -114,7 +114,7 @@ As an organisation - it might help from a liability perspective * Note that Tor states: *“We are not aware of any case that made it near a court, and we will do everything in our power to support you if it does.”* * Document experience with ISPs at [community.torproject.org/relay/community-resources/good-bad-isps](https://community.torproject.org/relay/community-resources/good-bad-isps/) -Useful links: +Useful links: * Tor abuse templates: - [community.torproject.org/relay/community-resources/tor-abuse-templates/](https://community.torproject.org/relay/community-resources/tor-abuse-templates/) diff --git a/documentation/operators/src/sandbox.md b/documentation/operators/src/sandbox.md index 4a24396085..dee07d0245 100644 --- a/documentation/operators/src/sandbox.md +++ b/documentation/operators/src/sandbox.md @@ -40,7 +40,7 @@ curl -o sandbox.env -L https://raw.githubusercontent.com/nymtech/nym/develop/env ![](images/sandbox.png) ~~~admonish tip -1. If you [built Nym from source](building-nym.md), you already have `sandbox.env` as a part of the monorepo (`nym/envs/sandbox.env`). Giving that you are likely to run `nym-node` from `nym/target/release`, the flag will look like this `--config-env-file ../../envs/sandbox.env` +1. If you [built Nym from source](../binaries/building-nym.md), you already have `sandbox.env` as a part of the monorepo (`nym/envs/sandbox.env`). Giving that you are likely to run `nym-node` from `nym/target/release`, the flag will look like this `--config-env-file ../../envs/sandbox.env` 2. You can export the path to `sandbox.env` to your enviromental variables: ```sh diff --git a/documentation/operators/src/testing/gateway-probe.md b/documentation/operators/src/testing/gateway-probe.md index 3fe82a19ea..235758faca 100644 --- a/documentation/operators/src/testing/gateway-probe.md +++ b/documentation/operators/src/testing/gateway-probe.md @@ -2,8 +2,8 @@ Nym Node operators running Gateway functionality are already familiar with the monitoring tool [Harbourmaster.nymtech.net](https://harbourmaster.nymtech.net). Under the hood of Nym Harbourmaster runs iterations of `nym-gateway-probe` doing various checks and displaying the results on the interface. Operators don't have to rely on the probe ran by Nym and wait for the data to refresh. With `nym-gateway-probe` everyone can check any Gateway's networking status from their own computer at any time. In one command the client queries data from: -- [`nym-api`](https://validator.nymtech.net/api/) -- [`explorer-api`](https://explorer.nymtech.net/api/) +- [`nym-api`](https://validator.nymtech.net/api/v1/gateways) +- [`explorer-api`](https://explorer.nymtech.net/api/v1/gateways) - [`harbour-master`](https://harbourmaster.nymtech.net/) diff --git a/documentation/operators/src/testing/performance.md b/documentation/operators/src/testing/performance.md index e6d0eeee0c..a9648b1529 100644 --- a/documentation/operators/src/testing/performance.md +++ b/documentation/operators/src/testing/performance.md @@ -4,7 +4,7 @@ Nym Mixnet has been running on mainnet for quite some time. There is still work As developers we need to be constantly improving the software. Operators have as much important role, keep their nodes up to date, monitor their performance and share their feedback with the rest of the community and core developers. -Therefore [monitoring](#monitoring) and [testing](#testing) are essential pieces of our common work. We call out all Nym operators to join the efforts! +Therefore [monitoring](#monitoring) and [testing](#testing) are essential pieces of our common work. We call out all Nym operators to join the efforts! ## Monitoring @@ -24,10 +24,10 @@ A list of different scripts, templates and guides for easier navigation: For the purpose of the performance testing Nym core developers plan to run instances of Prometheus and Grafana connected to Node explorer in the house. The network overall key insights we seek from these tests are primarily internal. We're focused on pinpointing bottlenecks, capacity loads, and monitoring cpu usage on the nodes' machines. -## Testing +## Testing ```admonish info -For the moment we paused Fast and Furious `perf` environment. Nym Mainnet environment will be used for future tests, please wait for further instructions. +For the moment we paused Fast and Furious `perf` environment. Nym Mainnet environment will be used for future tests, please wait for further instructions. ``` Nym asks its decentralised community of operators to join a series of performance testing events in order to **increase the overall quality of the Mixnet**. The main takeaways of such event are: @@ -45,7 +45,7 @@ Visit [Fast and Furious web page]({{performance_testing_webpage}}) and [Nym Harb ## Performance Testing Work Flow -* Nym runs a paralel network environment [validator.performance.nymte.ch]({{performance_validator}}) with a chain ID `perf` +* Nym runs a paralel network environment with a chain ID `perf` * Operators of Nym Nodes join by following easy steps on [performance testing web page]({{performance_testing_webpage}}), including simplified node authentication signature (while keep running their nodes on the mainnet) * Once signed in, operators will be asked to swap their binary for the modified version with metrics endpoint to be able to connect their own [monitoring system](#monitoring) * Core node data will be fed to a unique mixnet contract for the `perf` side chain @@ -57,5 +57,3 @@ Visit [Fast and Furious web page]({{performance_testing_webpage}}) and [Nym Harb ## More Information * What happens after the test or what operators get for participating is shared up to date on the [performance testing web page]({{performance_testing_webpage}}) - - diff --git a/documentation/operators/src/testing/prometheus-grafana.md b/documentation/operators/src/testing/prometheus-grafana.md index bd9f5af825..3ea0f88d5e 100644 --- a/documentation/operators/src/testing/prometheus-grafana.md +++ b/documentation/operators/src/testing/prometheus-grafana.md @@ -1,6 +1,6 @@ # Prometheus & Grafana -The combination of Prometheus and Grafana is a common stack used by Nym team for internal monitoring as well as by core community operators like [ExploreNym](https://github.com/ExploreNYM/vps-monitor) or [No Trust Verify](https://status.notrustverify.ch/d/CW3L7dVVk/nym-mixnet?orgId=1). +The combination of Prometheus and Grafana is a common stack used by Nym team for internal monitoring as well as by core community operators like [ExploreNym](https://github.com/ExploreNYM/self-hosted-monitor) or [No Trust Verify](https://status.notrustverify.ch/d/CW3L7dVVk/nym-mixnet?orgId=1). @@ -33,4 +33,4 @@ There are various ways how to setup this stack. You can chose based on your pref * [Prometheus documentation](https://prometheus.io/docs/introduction/overview/) * Installation [guide to install Prometheus](https://www.cherryservers.com/blog/install-prometheus-ubuntu) on Ubuntu by cherryservers * [Grafana installation guide](https://grafana.com/docs/grafana/latest/setup-grafana/installation/debian/) -* Nym's script [`prom_targets.py`](https://github.com/nymtech/nym/blob/promethus-is-our-friend/scripts/prom_targets.py) - a python program to request data from API and can be plugged to this stack +* Nym's script [`prom_targets.py`](https://github.com/nymtech/nym/blob/develop/scripts/prom_targets.py) - a python program to request data from API and can be plugged to this stack diff --git a/documentation/operators/src/troubleshooting/vps-isp.md b/documentation/operators/src/troubleshooting/vps-isp.md index 3a1c5d6d91..a7c8ce212b 100644 --- a/documentation/operators/src/troubleshooting/vps-isp.md +++ b/documentation/operators/src/troubleshooting/vps-isp.md @@ -64,7 +64,7 @@ Be extra careful editing this file since you may lock yourself out of the server Once finished, save the file and reboot the server. Now, running `ip a` command should return correct IPv4 and IPv6 addresses. -Finally re-run `network_tunnel_manager.sh` script, following the steps in node [IPv6 configuration chapter](https://github.com/nymtech/nym/nodes/configuration.md#ipv6-configuration). +Finally re-run `network_tunnel_manager.sh` script, following the steps in node [IPv6 configuration chapter](../nodes/configuration.md#ipv6-configuration). ## Other VPS troubleshooting From 5096c1e60e203dcf8be934823946e24fda16a9a3 Mon Sep 17 00:00:00 2001 From: import this <97586125+serinko@users.noreply.github.com> Date: Tue, 6 Aug 2024 13:22:30 +0000 Subject: [PATCH 02/93] [DOCs]: Create NymConnect archive page (#4750) --- .../dev-portal/src/archive/nym-connect.md | 85 +++++++++++++++++++ 1 file changed, 85 insertions(+) create mode 100644 documentation/dev-portal/src/archive/nym-connect.md diff --git a/documentation/dev-portal/src/archive/nym-connect.md b/documentation/dev-portal/src/archive/nym-connect.md new file mode 100644 index 0000000000..2dca063dd8 --- /dev/null +++ b/documentation/dev-portal/src/archive/nym-connect.md @@ -0,0 +1,85 @@ +# Archive page: NymConnect Setup + +```admonish warning +Since the beginning of 2024 NymConnect is no longer maintained. Nym is developing a new client called [NymVPN](https://nymvpn.com), an application routing all users traffic thorugh the mixnet. +If users want to route their traffic through socks5 we advice to use maintained [Nym Socks5 Client](../clients/socks5/setup.md). +``` + +In case you want to run deprecated NymConnect, follow these steps: + +1. Navigate to our [Github repository](https://github.com/nymtech/nym/releases?q=nym-connect&expanded=true) and download NymConnect binary +2. On Linux and Mac, make executable by opening terminal in the same directory and run: + +```sh +chmod +x ./nym-connect_.AppImage +``` + +1. Start the application +2. Click on `Connect` button to initialise the connection with the Mixnet +3. Anytime you'll need to setup Host and Port in your applications, click on `IP` and `Port` to copy the values to clipboard +4. In case you have problems such as `Gateway Issues`, try to reconnect or restart the application + +## Connect Privacy Enhanced Applications (PEApps) + +Here are some examples of applications which will work behind Socks5 proxy (`nym-socks5-client` or deprecated NymConnect), to enhance users privacy. + +### Electrum Bitcoin wallet via NymConnect + +To download Electrum visit the [official webpage](https://electrum.org/#download). To connect to the Mixnet follow these steps: + +1. Start and connect NymConnect (or [`nym-socks5-client`](../clients/socks5/setup.md)) +2. Start your Electrum Bitcoin wallet +3. Go to: *Tools* -> *Network* -> *Proxy* +4. Set *Use proxy* to ✅, choose `SOCKS5` from the drop-down and add (copy-paste) the values from your NymConnect application +5. Now your Electrum Bitcoin wallet runs through the Mixnet and it will be connected only if your NymConnect or `nym-socks5-client` are connected. + +![Electrum Bitcoin wallet setup](../images/electrum_tutorial/electrum.gif) + +### Monero wallet via NymConnect + +To download Monero wallet visit [getmonero.org](https://www.getmonero.org/downloads/). To connect to the Mixnet follow these steps: + +1. Start and connect NymConnect (or [`nym-socks5-client`](../clients/socks5/setup.md)) +2. Start your Monero wallet +3. Go to: *Settings* -> *Interface* -> *Socks5 proxy* -> Add values: IP address `127.0.0.1`, Port `1080` (the values copied from NymConnect) +5. Now your Monero wallet runs through the Mixnet and it will be connected only if your NymConnect or `nym-socks5-client` are connected. + +![Monero wallet setup](../images/monero_tutorial/monero-gui-NC.gif) + +### Matrix (Element) via NymConnect + +To download Element (chat client for Matrix) visit [element.io](https://element.io/download). To connect to the Mixnet follow these steps: + +1. Start and connect NymConnect (or [`nym-socks5-client`](../clients/socks5/setup.md)) +2. Start `element-desktop` with `--proxy-server` argument: + +**Linux** + +```sh +element-desktop --proxy-server=socks5://127.0.0.1:1080 +``` + +**Mac** + +```sh +open -a Element --args --proxy-server=socks5://127.0.0.1:1080 +``` + +To make the start of Element over NymConnect simplier, you can add this command to your key-binding shortcuts in your system settings. + +### Telegram via NymConnect + +1. Start and connect NymConnect (or [`nym-socks5-client`](../clients/socks5/setup.md)) +2. Start your Telegram chat application +3. Open the Telegram proxy settings. + - Linux: *Settings* -> *Advanced* -> *Connection type* -> *Use custom proxy* + - MacOS: *Settings* -> *Advanced* -> *Data & Storage* -> *Connection Type* -> *Use custom Proxy* + - Windows: *Settings* -> *Data and Storage* -> *Use proxy* +4. Add a proxy with the *Add proxy button*. +5. Select *SOCKS5* and make sure the port details are the same as those generated by NymConnect. Alternatively, follow this link: [https://t.me/socks?server=127.0.0.1&port=1080](https://t.me/socks?server=127.0.0.1&port=1080) +6. *Save the proxy settings* in Telegram. +7. Telegram is now running through the Nym Mixnet and is privacy-enhanced! This allows you to connect from regions which blocked Telegram. +8. Note if you remain idle on Telegram for a while you might lose connectivity and your messages might not get through via SOCKS5 proxy. If that happens reconnect your NymConnect and reset the proxy again. + + +Follow this [video](https://youtu.be/quj8H2qeOwY?t=97) to see the steps on Telegram setup. From 1db61f800c6884e284c5ab21e7abce3bc6d91d99 Mon Sep 17 00:00:00 2001 From: import this <97586125+serinko@users.noreply.github.com> Date: Tue, 6 Aug 2024 14:49:09 +0000 Subject: [PATCH 03/93] docs/hotfix (#4752) --- documentation/dev-portal/book.toml | 5 +++++ 1 file changed, 5 insertions(+) diff --git a/documentation/dev-portal/book.toml b/documentation/dev-portal/book.toml index b6978d78c7..014dfdb20f 100644 --- a/documentation/dev-portal/book.toml +++ b/documentation/dev-portal/book.toml @@ -108,3 +108,8 @@ copy-js = true # include Javascript code for search [output.linkcheck] warning-policy = "warn" + +[output.html.redirect] +"/faq/general-faq.html" = "https://nymtech.net/developers/faq/integrations-faq.html" +"/tutorials/simple-service-provider/user-client.html" = "https://nymtech.net/developers/examples/custom-services.html" +"/quickstart/socks-proxy.html" = "https://nymtech.net/developers/clients/socks5/setup.html" From f939cae3d9bed0d4d85b526e8003f6bf254e4aa0 Mon Sep 17 00:00:00 2001 From: =?UTF-8?q?Bogdan-=C8=98tefan=20Neac=C5=9Fu?= Date: Tue, 6 Aug 2024 18:14:29 +0200 Subject: [PATCH 04/93] Update peer refresh value (#4754) * Use a more proper timeout value * Move const to wireguard types --- common/wireguard-types/src/lib.rs | 7 +++++++ common/wireguard/src/peer_controller.rs | 19 +++++++++++++------ 2 files changed, 20 insertions(+), 6 deletions(-) diff --git a/common/wireguard-types/src/lib.rs b/common/wireguard-types/src/lib.rs index 18a01cd9e7..bdb8b575b7 100644 --- a/common/wireguard-types/src/lib.rs +++ b/common/wireguard-types/src/lib.rs @@ -6,10 +6,17 @@ pub mod error; pub mod public_key; pub mod registration; +use std::time::Duration; + pub use config::Config; pub use error::Error; pub use public_key::PeerPublicKey; pub use registration::{ClientMac, ClientMessage, GatewayClient, InitMessage, Nonce}; +// To avoid any problems, keep this stale check time bigger (>2x) then the bandwidth cap +// reset time (currently that one is 24h, at UTC midnight) +pub const DEFAULT_PEER_TIMEOUT: Duration = Duration::from_secs(60 * 60 * 24 * 3); // 3 days +pub const DEFAULT_PEER_TIMEOUT_CHECK: Duration = Duration::from_secs(5); // 5 seconds + #[cfg(feature = "verify")] pub use registration::HmacSha256; diff --git a/common/wireguard/src/peer_controller.rs b/common/wireguard/src/peer_controller.rs index 7a48a20857..9097f155ac 100644 --- a/common/wireguard/src/peer_controller.rs +++ b/common/wireguard/src/peer_controller.rs @@ -5,19 +5,15 @@ use chrono::{Timelike, Utc}; use defguard_wireguard_rs::{host::Peer, key::Key, WireguardInterfaceApi}; use nym_gateway_storage::Storage; use nym_wireguard_types::registration::{RemainingBandwidthData, BANDWIDTH_CAP_PER_DAY}; +use nym_wireguard_types::{DEFAULT_PEER_TIMEOUT, DEFAULT_PEER_TIMEOUT_CHECK}; use std::time::SystemTime; -use std::{collections::HashMap, sync::Arc, time::Duration}; +use std::{collections::HashMap, sync::Arc}; use tokio::sync::mpsc; use tokio_stream::{wrappers::IntervalStream, StreamExt}; use crate::error::Error; use crate::WgApiWrapper; -// To avoid any problems, keep this stale check time bigger (>2x) then the bandwidth cap -// reset time (currently that one is 24h, at UTC midnight) -const DEFAULT_PEER_TIMEOUT: Duration = Duration::from_secs(60 * 60 * 24 * 3); // 3 days -const DEFAULT_PEER_TIMEOUT_CHECK: Duration = Duration::from_secs(60); // 1 minute - pub enum PeerControlRequest { AddPeer(Peer), RemovePeer(Key), @@ -50,6 +46,7 @@ pub struct PeerController { active_peers: HashMap, suspended_peers: HashMap, last_seen_bandwidth: HashMap, + timeout_count: u8, } impl PeerController { @@ -82,6 +79,7 @@ impl PeerController { active_peers, suspended_peers, last_seen_bandwidth: HashMap::new(), + timeout_count: 0, } } @@ -144,6 +142,15 @@ impl PeerController { .iter() .map(|(key, peer)| (key.clone(), peer.rx_bytes + peer.tx_bytes)) .collect(); + + // Do in-memory updates of bandwidth every DEFAULT_PEER_TIMEOUT_CHECK + // and storage updates every 5 * DEFAULT_PEER_TIMEOUT_CHECK, because in-memory + // is more important for client query preciseness + self.timeout_count = self.timeout_count % 5 + 1; + if !reset && self.timeout_count < 5 { + return Ok(()); + } + if reset { self.active_peers = host.peers; for peer in self.active_peers.values() { From aaf3dca5b999ad7f19d2ff170078b43c9c4476c2 Mon Sep 17 00:00:00 2001 From: import this <97586125+serinko@users.noreply.github.com> Date: Tue, 6 Aug 2024 18:49:46 +0000 Subject: [PATCH 05/93] [DOCs]: Catching more broken URLs (#4755) * urls edit * finish PR - ready to merge --- documentation/dev-portal/src/clients/socks5-client.md | 2 +- documentation/dev-portal/src/clients/websocket/usage.md | 2 +- documentation/dev-portal/src/examples/using-nrs.md | 9 ++++++++- documentation/docs/book.toml | 3 ++- documentation/docs/src/binaries/building-nym.md | 6 +++--- documentation/operators/src/legal/exit-gateway.md | 3 ++- documentation/operators/src/testing/performance.md | 5 ++--- 7 files changed, 19 insertions(+), 11 deletions(-) diff --git a/documentation/dev-portal/src/clients/socks5-client.md b/documentation/dev-portal/src/clients/socks5-client.md index 8ef8aff80f..75159cc40d 100644 --- a/documentation/dev-portal/src/clients/socks5-client.md +++ b/documentation/dev-portal/src/clients/socks5-client.md @@ -60,7 +60,7 @@ There are 2 pieces of software that work together to send SOCKS traffic through The `nym-socks5-client` allows you to do the following from your local machine: * Take a TCP data stream from a application that can send traffic via SOCKS5. * Chop up the TCP stream into multiple Sphinx packets, assigning sequence numbers to them, while leaving the TCP connection open for more data -* Send the Sphinx packets through the mixnet to a [network requester](https://nymtech.net/operators/nodes/network-requester.md). Packets are shuffled and mixed as they transit the mixnet. +* Send the Sphinx packets through the Nym Network. Packets are shuffled and mixed as they transit the mixnet. The `nym-network-requester` then reassembles the original TCP stream using the packets' sequence numbers, and make the intended request. It will then chop up the response into Sphinx packets and send them back through the mixnet to your `nym-socks5-client`. The application will then receive its data, without even noticing that it wasn't talking to a "normal" SOCKS5 proxy! diff --git a/documentation/dev-portal/src/clients/websocket/usage.md b/documentation/dev-portal/src/clients/websocket/usage.md index ed8c0da6f1..ecc157d98d 100644 --- a/documentation/dev-portal/src/clients/websocket/usage.md +++ b/documentation/dev-portal/src/clients/websocket/usage.md @@ -58,7 +58,7 @@ In some applications, e.g. where people are chatting with friends who they know, **If that fits your security model, good. However, will probably be the case that you want to send anonymous replies using Single Use Reply Blocks (SURBs)**. -You can read more about SURBs [here](https://nymtech.net/docs/architecture/traffic-flow.md#private-replies-using-surbs) but in short they are ways for the receiver of this message to anonymously reply to you - the sender - **without them having to know your client address**. +You can read more about SURBs [here](https://nymtech.net/docs/architecture/traffic-flow.html#private-replies-using-surbs) but in short they are ways for the receiver of this message to anonymously reply to you - the sender - **without them having to know your client address**. Your client will send along a number of `replySurbs` to the recipient of the message. These are pre-addressed Sphinx packets that the recipient can write to the payload of (i.e. write response data to), but not view the final destination of. If the recipient is unable to fit the response data into the bucket of SURBs sent to it, it will use a SURB to request more SURBs be sent to it from your client. diff --git a/documentation/dev-portal/src/examples/using-nrs.md b/documentation/dev-portal/src/examples/using-nrs.md index 7111f62401..badcb7e7b7 100644 --- a/documentation/dev-portal/src/examples/using-nrs.md +++ b/documentation/dev-portal/src/examples/using-nrs.md @@ -5,13 +5,20 @@ If you are sending 'normal' application traffic, and/or don't require and custom > Nym will soon be switching from a whitelist-based approach to a blocklist-based approach to filtering traffic. As such, it will soon be even easier for developers to utilise the mixnet, as they will not have to run their own NRs or have to add their domains to the whitelist + +> Nym will soon be switching from a whitelist-based approach to a blocklist-based approach to filtering traffic. As such, it will soon be even easier for developers to utilise the mixnet, as they will not have to run their own NRs or have to add their domains to the whitelist + + + - MiniBolt is a complete guide to building a Bitcoin & Lightning full node on a personal computer. It has the capacity to run network traffic (transactions and syncing) over the mixnet, so you can privately sync your node and not expose your home IP to the wider world when interacting with the rest of the network! - [Docs](https://v2.minibolt.info/bonus-guides/system/nym-mixnet#proxying-bitcoin-core) - [Codebase](https://github.com/minibolt-guide/minibolt) + - Email over Nym is a set of configuration options to set up a Network Requester to send and recieve emails over Nym, using something like Thunderbird. - [Codebase](https://github.com/dial0ut/nymstr-email) diff --git a/documentation/docs/book.toml b/documentation/docs/book.toml index 45eb6e51ae..f645e940fa 100644 --- a/documentation/docs/book.toml +++ b/documentation/docs/book.toml @@ -110,4 +110,5 @@ warning-policy = "warn" "/sdk/rust/rust.html" = "https://nymtech.net/developers/sdk/rust/rust.html" "/clients/socks5-client.html" = "https://nymtech.net/developers/clients/socks5-client.html" "/clients/webassembly-client.html" = "https://nymtech.net/developers/clients/webassembly-client.html" -"/sdk/typescript.html" = "https://sdk/nymtech.net" +"/sdk/typescript.html" = "https://sdk.nymtech.net" +"/clients/websocket-client.html" = "https://nymtech.net/developers/clients/websocket-client.html" diff --git a/documentation/docs/src/binaries/building-nym.md b/documentation/docs/src/binaries/building-nym.md index dd9cd9f7fc..5b713c3f6d 100644 --- a/documentation/docs/src/binaries/building-nym.md +++ b/documentation/docs/src/binaries/building-nym.md @@ -56,9 +56,9 @@ Quite a bit of stuff gets built. The key working parts are: * [Nym Node](https://nymtech.net/operators/nodes/nym-node.html): `nym-node` * [Validator](https://nymtech.net/operators/nodes/validator-setup.html) -* [websocket client](https://nymtech.net/docs/clients/websocket-client.html): `nym-client` -* [socks5 client](https://nymtech.net/docs/clients/socks5-client.html): `nym-socks5-client` -* [webassembly client](https://nymtech.net/docs/clients/webassembly-client.html): `webassembly-client` +* [websocket client](https://nymtech.net/developers/clients/websocket-client.html): `nym-client` +* [socks5 client](https://nymtech.net/developers/clients/socks5-client.html): `nym-socks5-client` +* [webassembly client](https://nymtech.net/developers/clients/webassembly-client.html): `webassembly-client` * [nym-cli tool](https://nymtech.net/docs/tools/nym-cli.html): `nym-cli` * [nym-api](https://nymtech.net/operators/nodes/nym-api.html): `nym-api` * [nymvisor](https://nymtech.net/operators/nodes/nymvisor-upgrade.html): `nymvisor` diff --git a/documentation/operators/src/legal/exit-gateway.md b/documentation/operators/src/legal/exit-gateway.md index 7e0f5cc71c..df3394693a 100644 --- a/documentation/operators/src/legal/exit-gateway.md +++ b/documentation/operators/src/legal/exit-gateway.md @@ -6,7 +6,8 @@ The entire content of this page is under [Creative Commons Attribution 4.0 Inter This page is a part of Nym Community Legal Forum and its content is composed by shared advices in [Node Operators Legal Forum](https://matrix.to/#/!YfoUFsJjsXbWmijbPG:nymtech.chat?via=nymtech.chat&via=matrix.org) (Matrix chat) as well as though pull requests done by the node operators directly to our [repository](https://github.com/nymtech/nym/tree/develop/documentation/operators/src), reviewed by Nym DevRels. -This document presents an initiative to further support Nym’s mission of allowing privacy for everyone everywhere. This would be achieved with the support of Nym node operators operating Gateways and opening these to any online service. Such setup needs a **clear policy**, one which will remain the **same for all operators** running Nym nodes. The [proposed **Exit policy**](https://nymtech.net/.wellknown/network-requester/exit-policy.txt) is a combination of two existing safeguards: [Tor Null ‘deny’ list](https://tornull.org/) and Tor reduced policy. +This document presents an initiative to further support Nym’s mission of allowing privacy for everyone everywhere. This would be achieved with the support of Nym node operators operating Gateways and opening these to any online service. Such setup needs a **clear policy**, one which will remain the **same for all operators** running Nym nodes. The [proposed **Exit policy**](https://nymtech.net/.wellknown/network-requester/exit-policy.txt) is a combination of two existing safeguards: Tor Null ‘deny’ list and Tor reduced policy. + All the technical changes on the side of Nym nodes - ***Project Smoosh*** - are described in the [FAQ section](../archive/faq/smoosh-faq.md). diff --git a/documentation/operators/src/testing/performance.md b/documentation/operators/src/testing/performance.md index a9648b1529..af98086fbe 100644 --- a/documentation/operators/src/testing/performance.md +++ b/documentation/operators/src/testing/performance.md @@ -43,6 +43,7 @@ Nym asks its decentralised community of operators to join a series of performanc Visit [Fast and Furious web page]({{performance_testing_webpage}}) and [Nym Harbour Master](https://harbourmaster.nymtech.net/) Gateways monitoring page to read more about the performance testing and the results of it. + -## More Information - -* What happens after the test or what operators get for participating is shared up to date on the [performance testing web page]({{performance_testing_webpage}}) From 1e01a8e633e0d20b5664c01d010d2a5e49e42c69 Mon Sep 17 00:00:00 2001 From: import this <97586125+serinko@users.noreply.github.com> Date: Wed, 7 Aug 2024 13:20:17 +0000 Subject: [PATCH 06/93] [DOCs/operators]: Release detailed changelog for v2024.9 topdeck (#4757) * add changelog for new release * add more URLs redirection for socks5 specific apps * update exit policy page * finish changelog - ready for review * add tooling * clarify tornul note comment --- documentation/dev-portal/book.toml | 3 + documentation/docs/book.toml | 3 + documentation/operators/src/changelog.md | 165 ++++++++++++++++++ .../operators/src/legal/exit-gateway.md | 6 +- 4 files changed, 174 insertions(+), 3 deletions(-) diff --git a/documentation/dev-portal/book.toml b/documentation/dev-portal/book.toml index 014dfdb20f..e4bf22202c 100644 --- a/documentation/dev-portal/book.toml +++ b/documentation/dev-portal/book.toml @@ -113,3 +113,6 @@ warning-policy = "warn" "/faq/general-faq.html" = "https://nymtech.net/developers/faq/integrations-faq.html" "/tutorials/simple-service-provider/user-client.html" = "https://nymtech.net/developers/examples/custom-services.html" "/quickstart/socks-proxy.html" = "https://nymtech.net/developers/clients/socks5/setup.html" +"/tutorials/matrix.html" = "https://nymtech.net/developers/archive/nym-connect.html#matrix-element-via-nymconnect" +"/tutorials/monero.html" = "https://nymtech.net/developers/archive/nym-connect.html#monero-wallet-via-nymconnect" +"/tutorials/telegram.html" = "https://nymtech.net/developers/archive/nym-connect.html#telegram-via-nymconnect" diff --git a/documentation/docs/book.toml b/documentation/docs/book.toml index f645e940fa..9fe3643036 100644 --- a/documentation/docs/book.toml +++ b/documentation/docs/book.toml @@ -112,3 +112,6 @@ warning-policy = "warn" "/clients/webassembly-client.html" = "https://nymtech.net/developers/clients/webassembly-client.html" "/sdk/typescript.html" = "https://sdk.nymtech.net" "/clients/websocket-client.html" = "https://nymtech.net/developers/clients/websocket-client.html" +"/use-apps/blockstream-green" = "https://nymtech.net/developers/clients/socks5/usage.html" +"/use-apps/telegram" = "https://nymtech.net/developers/archive/nym-connect.html#telegram-via-nymconnect" + diff --git a/documentation/operators/src/changelog.md b/documentation/operators/src/changelog.md index 4e0adb3d1a..1d3e495664 100644 --- a/documentation/operators/src/changelog.md +++ b/documentation/operators/src/changelog.md @@ -2,6 +2,171 @@ This page displays a full list of all the changes during our release cycle from [`v2024.3-eclipse`](https://github.com/nymtech/nym/blob/nym-binaries-v2024.3-eclipse/CHANGELOG.md) onwards. Operators can find here the newest updates together with links to relevant documentation. The list is sorted so that the newest changes appear first. +## `v2024.9-topdeck` + +- [Release binaries](https://github.com/nymtech/nym/releases/tag/nym-binaries-v2024.9-topdeck) +- [Release CHANGELOG.md](https://github.com/nymtech/nym/blob/nym-binaries-v2024.9-topdeck/CHANGELOG.md) +- [`nym-node`](nodes/nym-node.md) version `1.1.6` + +~~~admonish example collapsible=true title='CHANGELOG.md' +- chore: fix 1.80 lint issues ([#4731]) +- Handle clients with different versions in IPR ([#4723]) +- Add 1GB/day/user bandwidth cap ([#4717]) +- Feature/merge back ([#4710]) +- removed mixnode/gateway config migration code and disabled cli without explicit flag ([#4706]) + +[#4731]: https://github.com/nymtech/nym/pull/4731 +[#4723]: https://github.com/nymtech/nym/pull/4723 +[#4717]: https://github.com/nymtech/nym/pull/4717 +[#4710]: https://github.com/nymtech/nym/pull/4710 +[#4706]: https://github.com/nymtech/nym/pull/4706 +~~~ + +### Features + +* [Removed `nym-mixnode` and `nym-gateway` config migration code and disabled CLI without explicit flag](https://github.com/nymtech/nym/pull/4706): Gateway and Mixnode commands now won't do anything without explicit `--force-run` to bypass the deprecation, instead it will tell an operator to run a `nym-node`. The next step, in say a month or so, is to completely remove all `cli` related things. +~~~admonish example collapsible=true title='Testing steps performed' +- Verify that the `nym-gateway` binary and `nym-mixnode` binary commands return the `_error message_` stating to *update to `nym-node`* +- Check that when adding the `--force-run` flag, it still allows the command to be run (aside from `init` which has been removed) and the message stating to update to `nym-node` is a `_warning_` now +- Check `nym-node` is not affected +- Review the changes in the PR +~~~ + +* [Add 1GB/day/user bandwidth cap](https://github.com/nymtech/nym/pull/4717) + +~~~admonish example collapsible=true title='Testing steps performed - Scenario 1: Bandwidth Decreasing Continuously' +1. Start the client and noted the initial bandwidth (e.g., 1GB). +2. Us the client and track bandwidth usage over time (e.g., decrease by 100MB every hour). +3. Restart the client after some usage. +4. Verify the bandwidth continued from the last recorded value, not reset. + +**Notes:** + The bandwidth continued decreasing without resetting upon restart. Logs and reports correctly reflected the decreasing bandwidth. +~~~ + +~~~admonish example collapsible=true title='Testing steps performed - Scenario 2: Bandwidth Reset Next Day' +1. Use the client normally until the end of the day. +2. Suspend some clients and kept others active. +3. Check bandwidth at midnight. +4. Verify that bandwidth reset to 1GB for both suspended and active clients. + +**Notes:** +Bandwidth reset to 1GB for all clients at midnight. Logs and reports correctly showed the reset. +~~~ + +~~~admonish example collapsible=true title='Testing steps performed - Scenario 3: Bandwidth Reset at a Different Time (e.g., Midday)' +1. Configure the system to reset bandwidth at midday. +2. Use the client and monitored bandwidth until midday. +3. Keep the client connected during the reset time. +4. Verify that bandwidth reset to 1GB live at midday. + +**Notes:** +Bandwidth reset to 1GB at midday while the client was connected. Logs and reports correctly reflected the reset. +~~~ + +* [Handle clients with different versions in IPR](https://github.com/nymtech/nym/pull/4723): Allow the IPR to handle clients connecting both using `v6` and `v7`, independently. The motivation is that we want to be able to roll out an API version change gradually for NymVPN clients without breaking backwards compatibility. The main feature on the new `v7` format that is not yet used, is that it adds signatures for connect/disconnect. +~~~admonish example collapsible=true title='Testing steps performed' +Run the same command (using same gateways deployed from this PR) on different versions of the `nym-vpn-cli`. + +Example: +```sh +sudo -E ./nym-vpn-cli -c ../qa.env run --entry-gateway-id $entry_gateway --exit-gateway-id $exit_gateway --enable-two-hop + +sudo -E ./nym-vpn-cli -c ../qa.env run --entry-gateway-id $entry_gateway --exit-gateway-id $exit_gateway --enable-two-hop +``` +~~~ + +### Bugfix + +* [Feature/merge back](https://github.com/nymtech/nym/pull/4710): Merge back from the release branch the changes that fix the `nym-node` upgrades. + +* [Fix version `1.x.x` not having template correspondent initially](https://github.com/nymtech/nym/pull/4733): This should fix the problem of config deserialisation when operators upgrade nodes and skip over multiple versions. +~~~admonish example collapsible=true title='Testing steps performed' +- Tested updating an old nym-node version and ensuring it did not throw any errors. +~~~ + +* [chore: fix 1.80 lint issues](https://github.com/nymtech/nym/pull/4731): +~~~admonish example collapsible=true title='Testing steps performed' +- Building all binaries is ok +- Running `cargo fmt` returns no issues +~~~ + +### Operators Guide updates + +* [Update Nym exit policy](https://nymtech.net/.wellknown/network-requester/exit-policy.txt): Based on the survey, AMA and following discussions we added several ports to Nym exit policy. The ports voted upon in the [forum governance](https://forum.nymtech.net/t/poll-a-new-nym-exit-policy-for-exit-gateways-and-the-nym-mixnet-is-inbound/464) have not been added yet due to the concerns raised. These ports were unrestricted: + +~~~admonish example collapsible=true title='Newly opened ports in Nym exit policy' +``` +22 # SSH +123 # NTP +445 # SMB file share Windows +465 # URD for SSM +587 # SMTP +853 # DNS over TLS +1433 # databases +1521 # databases +2049 # NFS +3074 # Xbox Live +3306 # databases +5000-5005 # RTP / VoIP +5432 # databases +6543 # databases +8080 # HTTP Proxies +8767 # TeamSpeak +8883 # Secure MQ Telemetry Transport - MQTT over SSL +9053 # Tari +9339 # gaming +9443 # alternative HTTPS +9735 # Lightning +25565 # Minecraft +27000-27050 # Steam and game servers +60000-61000 # MOSH +``` +~~~ + +* [Create a NymConnect archive page](https://nymtech.net/developers/archive/nym-connect.html), PR [\#4750](https://github.com/nymtech/nym/commit/5096c1e60e203dcf8be934823946e24fda16a9a3): Archive deprecated NymConnect for backward compatibility, show PEApps examples for both NC and maintained `nym-socks5-client`. + +* Fix broken URLs and correct redirection. PRs: [\#4745](https://github.com/nymtech/nym/commit/7e36595d8fa7706876880b42df1c998a4b8c1478), [\#4752](https://github.com/nymtech/nym/commit/1db61f800c6884e284c5ab21e7abce3bc6d91d99) [\#4755](https://github.com/nymtech/nym/commit/aaf3dca5b999ad7f19d2ff170078b43c9c4476c2), [\#4737](https://github.com/nymtech/nym/commit/6f669866e92e637772726ad05caa5c5501a830f3) +~~~admonish example collapsible=true title='Testing steps performed' +- Use [deadlinkchecker.com](https://www.deadlinkchecker.com/website-dead-link-checker.asp) to go over `nymtech.net` and correct all docs URLs +- Go over search engines and old medium articles and check that all dead URLs re-directing correctly +~~~ + +* [Clarify syntax on `nym-nodes` ports on VPS setup page](https://nymtech.net/operators/nodes/vps-setup.html#configure-your-firewall), PR [\#4734](https://github.com/nymtech/nym/commit/5e6417f83788f30b2a84e4dd73d6dd9619a2bb16): Make crystal clear that the addresses and ports in operators `config.toml` must be opened using [`ufw`](https://nymtech.net/operators/nodes/vps-setup.html#configure-your-firewall) and set up as in the example below: +~~~admonish example collapsible=true title='snap of binding addresses and ports in `config.toml`' +```toml +[host] +public_ips = [ +'' +] + +[mixnet] +bind_address = '0.0.0.0:1789' + +[http] +bind_address = '0.0.0.0:8080' + +[mixnode] +[mixnode.verloc] +bind_address = '0.0.0.0:1790' + +[entry_gateway] +bind_address = '0.0.0.0:9000' +``` +~~~ + +### Tooling + +* [Nym Harbourmaster](https://https://harbourmaster.nymtech.net/) has now several new functionalities: + - Tab for Mixnodes + - Tab with Charts + - New columns with: *Moniker (node description)*, *DP delegatee*, *Accepted T&Cs* - also part of a new category 🐼😀 + +* Nym has a new [Token page](https://nymtech.net/about/token) + +--- + + ## `v2024.8-wispa` - [Release binaries](https://github.com/nymtech/nym/releases/tag/nym-binaries-v2024.8-wispa) diff --git a/documentation/operators/src/legal/exit-gateway.md b/documentation/operators/src/legal/exit-gateway.md index df3394693a..bea236d28c 100644 --- a/documentation/operators/src/legal/exit-gateway.md +++ b/documentation/operators/src/legal/exit-gateway.md @@ -6,7 +6,7 @@ The entire content of this page is under [Creative Commons Attribution 4.0 Inter This page is a part of Nym Community Legal Forum and its content is composed by shared advices in [Node Operators Legal Forum](https://matrix.to/#/!YfoUFsJjsXbWmijbPG:nymtech.chat?via=nymtech.chat&via=matrix.org) (Matrix chat) as well as though pull requests done by the node operators directly to our [repository](https://github.com/nymtech/nym/tree/develop/documentation/operators/src), reviewed by Nym DevRels. -This document presents an initiative to further support Nym’s mission of allowing privacy for everyone everywhere. This would be achieved with the support of Nym node operators operating Gateways and opening these to any online service. Such setup needs a **clear policy**, one which will remain the **same for all operators** running Nym nodes. The [proposed **Exit policy**](https://nymtech.net/.wellknown/network-requester/exit-policy.txt) is a combination of two existing safeguards: Tor Null ‘deny’ list and Tor reduced policy. +This document presents an initiative to further support Nym’s mission of allowing privacy for everyone everywhere. This would be achieved with the support of Nym node operators operating Gateways and opening these to any online service. Such setup needs a **clear policy**, one which will remain the **same for all operators** running Nym nodes. [**Nym exit policy**](https://nymtech.net/.wellknown/network-requester/exit-policy.txt) is a combination of safeguards like (nowadays deprecated) `Tor Null deny list` and `Tor reduced policy` together with changes decided by Nym operators community through the governance (like in this [vote](https://forum.nymtech.net/t/poll-a-new-nym-exit-policy-for-exit-gateways-and-the-nym-mixnet-is-inbound/464)). This policy aims to find a healthy compromise between protecting the operators and NymVPN users against attacks while allowing for as wide experience when accessing the internet through Nym Network. All the technical changes on the side of Nym nodes - ***Project Smoosh*** - are described in the [FAQ section](../archive/faq/smoosh-faq.md). @@ -24,7 +24,7 @@ Nym core team cannot provide comprehensive legal advice across all jurisdictions * Currently, Nym Gateway nodes only enable access to apps and services that are on an ‘allow’ list that is maintained by the core team. -* To decentralise and enable privacy for a broader range of services, this initiative will have to transition from the current ‘allow’ list to a ‘deny’ list - [exit policy](https://nymtech.net/.wellknown/network-requester/exit-policy.txt). In accordance with the Tor Null 'deny' list and [Tor reduced policy](https://tornull.org/tor-reduced-reduced-exit-policy.php), which are two established safeguards. +* To decentralise and enable privacy for a broader range of services, this initiative will have to transition from the current ‘allow’ list to a ‘deny’ list - [exit policy](https://nymtech.net/.wellknown/network-requester/exit-policy.txt). In accordance with the (nowadays deprecated) `Tor Null deny list` and `Tor reduced policy` together with changes decided by Nym operators community through the governance (like in this [vote](https://forum.nymtech.net/t/poll-a-new-nym-exit-policy-for-exit-gateways-and-the-nym-mixnet-is-inbound/464)) * This will enhance the usage and appeal of Nym products for end users. As a result, increased usage will ultimately lead to higher revenues for Nym operators. @@ -73,7 +73,7 @@ This restricts the hosts that the NymConnect app can connect to and has the effe The principal change in the new configuration is to make this short allow list more permissive. Nym's [exit policy](https://nymtech.net/.wellknown/network-requester/exit-policy.txt) will restrict the hosts to which Nym Mixnet and Nym VPN users are permitted to connect. This will be done in an effort to protect the operators, as Gateways will act both as SOCKS5 Network Requesters, and exit nodes for IP traffic from Nym Mixnet VPN and VPN clients (both wrapped in the same app). -As of now we the Gateways will be defaulted to a combination of [Tor Null ‘deny’ list](https://tornull.org/) (note: Not affiliated with Tor) - reproduction permitted under Creative Commons Attribution 3.0 United States License which is IP-based, e.g., `ExitPolicy reject 5.188.10.0/23:*` and [Tor reduced policy](https://tornull.org/tor-reduced-reduced-exit-policy.php). Whether we will stick with this list, do modifications or compile another one is still a subject of discussion. In all cases, this policy will remain the same for all the nodes, without any option to modify it by Nym node operators to secure stable and reliable service for the end users. +As of now we the Gateways will be defaulted to a combination of (nowadays deprecated) `Tor Null deny list` (note: Tornull is not affiliated with Tor Project) - reproduction permitted under Creative Commons Attribution 3.0 United States License which is IP-based, e.g., `ExitPolicy reject 5.188.10.0/23:*` and `Tor reduced policy` together with changes decided by Nym operators community through the governance (like in this [vote](https://forum.nymtech.net/t/poll-a-new-nym-exit-policy-for-exit-gateways-and-the-nym-mixnet-is-inbound/464)). This policy will remain the same for all the nodes, without any option to modify it by Nym node operators individually, to secure stable and reliable service for the end users. For exit relays on ports 80 and 443, the Gateways will exhibit an HTML page resembling the one proposed by [Tor](https://gitlab.torproject.org/tpo/core/tor/-/raw/HEAD/contrib/operator-tools/tor-exit-notice.html). By doing so, the operator will be able to disclose details regarding their Gateway, including the currently configured exit policy, all without the need for direct correspondence with regulatory or law enforcement agencies. It also makes the behavior of Exit Gateways transparent and even computable (a possible feature would be to offer a machine readable form of the notice in JSON or YAML). From 3f6de8b10c7d7968095c51608fb3177b4c30ba7b Mon Sep 17 00:00:00 2001 From: =?UTF-8?q?Jon=20H=C3=A4ggblad?= Date: Fri, 9 Aug 2024 14:55:14 +0200 Subject: [PATCH 07/93] Remove duplicate stat count for retransmissions (#4756) --- .../client/real_messages_control/real_traffic_stream.rs | 7 ------- 1 file changed, 7 deletions(-) diff --git a/common/client-core/src/client/real_messages_control/real_traffic_stream.rs b/common/client-core/src/client/real_messages_control/real_traffic_stream.rs index ef91208f1b..f373fa0756 100644 --- a/common/client-core/src/client/real_messages_control/real_traffic_stream.rs +++ b/common/client-core/src/client/real_messages_control/real_traffic_stream.rs @@ -474,13 +474,6 @@ where Poll::Ready(Some((real_messages, conn_id))) => { log::trace!("handling real_messages: size: {}", real_messages.len()); - // This is the last step in the pipeline where we know the type of the message, so - // lets count the number of retransmissions here. - if conn_id == TransmissionLane::Retransmission { - self.stats_tx - .report(PacketStatisticsEvent::RetransmissionQueued); - } - // First store what we got for the given connection id self.transmission_buffer.store(&conn_id, real_messages); let real_next = self.pop_next_message().expect("we just added one"); From da8e5136271ecbcd7127ce57cc96125d1198505f Mon Sep 17 00:00:00 2001 From: import this <97586125+serinko@users.noreply.github.com> Date: Tue, 13 Aug 2024 13:05:52 +0000 Subject: [PATCH 08/93] [DOCs/operators]: WireGuard guide & changelog update (#4760) * wireguard documentation and changelog update * add review comments * add review comments --- documentation/operators/src/changelog.md | 131 ++++++++++++ .../operators/src/nodes/configuration.md | 195 +++++++----------- .../operators/src/nodes/maintenance.md | 10 +- documentation/operators/src/nodes/nym-node.md | 22 +- documentation/operators/src/nodes/setup.md | 25 ++- .../operators/src/nodes/vps-setup.md | 27 ++- 6 files changed, 254 insertions(+), 156 deletions(-) diff --git a/documentation/operators/src/changelog.md b/documentation/operators/src/changelog.md index 1d3e495664..088fe6e15a 100644 --- a/documentation/operators/src/changelog.md +++ b/documentation/operators/src/changelog.md @@ -93,6 +93,137 @@ sudo -E ./nym-vpn-cli -c ../qa.env run --entry-gateway-id $entry_gateway --exit- ### Operators Guide updates +* [WireGuard tunnel configuration guide](nodes/configuration.md#routing-configuration) for `nym-node` (currently Gateways functionalities). For simplicity we made a detailed step by step guide to upgrade an existing `nym-node` to the latest version and configure your VPS routing for WireGuard. Open by clicking on the example block below. + +~~~admonish example collapsible=true title='Upgrading `nym-node` with WG' +**Prerequisites** + +- **Nym Node Version:** You must be running the `2024.9-topdeck` release branch, which operates as `nym-node` version `1.1.6`. You can find the release here: [Nym 2024.9-topdeck Release](https://github.com/nymtech/nym/releases/tag/nym-binaries-v2024.9-topdeck). + +- **Important:** Before proceeding, make sure to [back up](nodes/maintenance.md#backup-a-node) your current `nym-node` configuration to avoid any potential data loss or issues. + + +- **Download Nym Node:** + - You can download the `nym-node` binary directly using the following command: +```bash +curl -s https://github.com/nymtech/nym/releases/tag/nym-binaries-v2024.9-topdeck/nym-node -o nym-node && chmod u+x nym-node +``` + +**Step 1: Update UFW Firewall Rules** + +- **Warning:** Enabling the firewall with UFW without allowing SSH port 22 first will lead to losing access over SSH. Make sure port 22 is allowed before proceeding with any UFW configurations. + +Run the following as root or with `sudo` prefix: + +1. Check the current status of UFW (Uncomplicated Firewall): +```bash +ufw status +``` + +2. Ensure that the following ports are allowed on your machine before adding the WireGuard port: + +```bash +ufw allow 22/tcp # SSH - you're in control of these ports +ufw allow 80/tcp # HTTP +ufw allow 443/tcp # HTTPS +ufw allow 1789/tcp # Nym specific +ufw allow 1790/tcp # Nym specific +ufw allow 8080/tcp # Nym specific - nym-node-api +ufw allow 9000/tcp # Nym Specific - clients port +ufw allow 9001/tcp # Nym specific - wss port +ufw allow 51822/udp # WireGuard +``` + +3. Confirm that the UFW rules have been updated: +```bash +ufw status +``` + +**Step 2: Download and Prepare the Network Tunnel Manager Script** + +1. Download the [`network_tunnel_manager.sh`](https://gist.github.com/tommyv1987/ccf6ca00ffb3d7e13192edda61bb2a77) script: +```bash +curl -L -o network_tunnel_manager.sh https://gist.githubusercontent.com/tommyv1987/ccf6ca00ffb3d7e13192edda61bb2a77/raw/3c0a38c1416f8fdf22906c013299dd08d1497183/network_tunnel_manager.sh +``` + +2. Make the script executable: +```bash +chmod u+x network_tunnel_manager.sh +``` + +3. Apply the WireGuard IPTables rules: +```bash +./network_tunnel_manager.sh apply_iptables_rules_wg +``` + +**Step 3: Update the Nym Node Service File** + +1. Modify your [`nym-node` service file](nodes/configuration.md#systemd) to enable WireGuard. Open the file (usually located at `/etc/systemd/system/nym-node.service`) and update the `[Service]` section as follows: + +```ini +[Service] +User= +Type=simple +#Environment=RUST_LOG=debug +# CAHNGE PATH IF YOU DON'T RUN IT FROM ROOT HOME DIRECTORY +ExecStart=/root/nym-node run --mode exit-gateway --id --accept-operator-terms-and-conditions --wireguard-enabled true +Restart=on-failure +RestartSec=30 +StartLimitInterval=350 +StartLimitBurst=10 +LimitNOFILE=65536 + +[Install] +WantedBy=multi-user.target + +# ADD OR TWEAK ANY CUSTOM SETTINGS +``` + +2. Reload the systemd daemon to apply the changes: +```bash +systemctl daemon-reload +``` + +3. Restart the `nym-node service`: +```bash +systemctl restart nym-node.service +``` + +4. Optionally, you can check if the node is running correctly by monitoring the service logs: +```bash +journalctl -u nym-node.service -f -n 100 +``` + +**Step 4: Run the Network Tunnel Manager Script** + +Finally, run the following command to initiate our favorite routing test - run the joke through the WireGuard tunnel: +```bash +./network_tunnel_manager.sh joke_through_wg_tunnel +``` +~~~ + +* [Change `--wireguard-enabled` flag to `true`](nodes/setup.md#-initialise--run): With a proper [routing configuration](nodes/configuration.md#routing-configuration) `nym-nodes` running as Gateways can now enable WG. See the example below: + +~~~admonish example collapsible=true title='Syntax to run `nym-node` with WG enabled' +For Exit Gateway: +```sh +./nym-node run --id --mode exit-gateway --public-ips "$(curl -4 https://ifconfig.me)" --hostname "" --http-bind-address 0.0.0.0:8080 --mixnet-bind-address 0.0.0.0:1789 --location --accept-operator-terms-and-conditions --wireguard-enabled true + +# is in format without 'https://' prefix +# is format like 'Jamaica', or two-letter alpha2 (e.g. 'JM'), three-letter alpha3 (e.g. 'JAM') or three-digit numeric-3 (e.g. '388') can be provided. +# wireguard can be enabled from version 1.1.6 onwards +``` + +For Entry Gateway: +```sh +./nym-node run --id --mode entry-gateway --public-ips "$(curl -4 https://ifconfig.me)" --hostname "" --http-bind-address 0.0.0.0:8080 --mixnet-bind-address 0.0.0.0:1789 --accept-operator-terms-and-conditions --wireguard-enabled true + +# is in format without 'https://' prefix +# is format like 'Jamaica', or two-letter alpha2 (e.g. 'JM'), three-letter alpha3 (e.g. 'JAM') or three-digit numeric-3 (e.g. '388') can be provided. +# wireguard can be enabled from version 1.1.6 onwards +``` +~~~ + * [Update Nym exit policy](https://nymtech.net/.wellknown/network-requester/exit-policy.txt): Based on the survey, AMA and following discussions we added several ports to Nym exit policy. The ports voted upon in the [forum governance](https://forum.nymtech.net/t/poll-a-new-nym-exit-policy-for-exit-gateways-and-the-nym-mixnet-is-inbound/464) have not been added yet due to the concerns raised. These ports were unrestricted: ~~~admonish example collapsible=true title='Newly opened ports in Nym exit policy' diff --git a/documentation/operators/src/nodes/configuration.md b/documentation/operators/src/nodes/configuration.md index 87d2f795ed..dd57723c31 100644 --- a/documentation/operators/src/nodes/configuration.md +++ b/documentation/operators/src/nodes/configuration.md @@ -140,7 +140,7 @@ Basically, you want the full `///nym-mixnode run --id [entry-gateway] -> [mixnode layer 1] -> [your mixnode] -> [IPv6 mixnode layer3] -> [exit-gateway] ``` In this (unusual) case your `mixnode` will not be able to route the packets. The node will drop the packets and its performance would go down. For that reason it's beneficial to have IPv6 enabled when running a `mixnode` functionality. -### Quick IPv6 Check +```admonish info +We recommend operators to configure their `nym-node` with the full routing configuration. -```admonish caution -Make sure to keep your IPv4 address enabled while setting up IPv6, as the majority of routing goes through that one! +However, most of the time the packets sent through the Mixnet are IPv4 based. The IPv6 packets are still pretty rare and therefore it's not mandatory from operational point of view to have this configuration implemented if you running only `mixnode` mode. + +If you preparing to run a `nym-node` with all modes enabled in the future, this setup is required. ``` +```admonish tip title="Delegation Program" +For everyone participating in Delegation Program or Service Grant program, this setup is a requirement! +``` + +### Quick IPv6 Check + You can always check IPv6 address and connectivity by using some of these methods: +~~~admonish example collapsible=true ```sh # locally listed IPv6 addresses ip -6 addr @@ -221,55 +231,69 @@ curl -6 https://ipv6.icanhazip.com # using telnet telnet -6 ipv6.telnetmyip.com ``` +~~~ -### IPv6 Configuration +```admonish caution +Make sure to keep your IPv4 address enabled while setting up IPv6, as the majority of routing goes through that one! +``` -While we're working on Rust implementation to have these settings as a part of the binary build, we wrote a script to solve these connectivity requirements in the meantime we wrote a script [`network_tunnel_manager.sh`](https://gist.github.com/tommyv1987/ccf6ca00ffb3d7e13192edda61bb2a77) to support the operators to configure their servers and address all the connectivity requirements. +### Routing Configuration + +While we're working on Rust implementation to have these settings as a part of the binary build, to solve these connectivity requirements in the meantime we wrote a script [`network_tunnel_manager.sh`](https://gist.github.com/tommyv1987/ccf6ca00ffb3d7e13192edda61bb2a77) to support the operators to configure their servers and address all the connectivity requirements. Networking configuration across different ISPs and various operation systems does not have a generic solution. If the provided configuration setup doesn't solve your problem check out [IPv6 troubleshooting](../troubleshooting/vps-isp.md#ipv6-troubleshooting) page. Be aware that you may have to do more research and customised adjustments. -#### Mode: `exit-gateway` The `nymtun0` interface is dynamically managed by the `exit-gateway` service. When the service is stopped, `nymtun0` disappears, and when started, `nymtun0` is recreated. -The script should be used in a context where `nym-node --mode exit-gateway` is running to fully utilise its capabilities, particularly for fetching IPv6 addresses or applying network rules that depend on the `nymtun0` interface. +The script should be used in a context where `nym-node`is running to fully utilise its capabilities, particularly for fetching IPv6 addresses or applying network rules that depend on the `nymtun0` interface and to establish a WireGuard tunnel. + +Before starting with the following, make sure you have the [latest `nym-node` binary](https://github.com/nymtech/nym/releases/) installed and your [VPS setup](vps-setup.md) finished properly! 1. Download `network_tunnel_manager.sh`, make executable and run: ```sh -curl -o network_tunnel_manager.sh -L https://gist.githubusercontent.com/tommyv1987/ccf6ca00ffb3d7e13192edda61bb2a77/raw/9d785d6ee3aa2970553633eccbd89a827f49fab5/network_tunnel_manager.sh && chmod +x network_tunnel_manager.sh && ./network_tunnel_manager.sh +curl -L -o network_tunnel_manager.sh https://gist.githubusercontent.com/tommyv1987/ccf6ca00ffb3d7e13192edda61bb2a77/raw/3c0a38c1416f8fdf22906c013299dd08d1497183/network_tunnel_manager.sh && \ +chmod +x network_tunnel_manager.sh && \ +./network_tunnel_manager.sh ``` -Here is a quick command explanation, for more details on the `network_tunnel_manager.sh` script, refer to the [overview](https://gist.github.com/tommyv1987/ccf6ca00ffb3d7e13192edda61bb2a77) under the code block. +2. Make sure your `nym-node` service is up and running +- **If you setting up a new node and not upgrading an existing one, keep it running and [bond](bonding.md) your node now**. Then come back here and follow the rest of the configuration. -~~~admonish example collapsible=true title="A summarized usage of `network_tunnel_manager.sh`" +```admonish tip title="" +Run the following steps as root or with `sudo` prefix! +``` + +3. Display IPv6: +- At this point you should see a `global ipv6` address. ```sh -summary: -This is a comprehensive script for configuring network packet forwarding and iptables rules, -aimed at ensuring smooth operation of a tunnel interface. -It includes functionality for both setup and tear-down of nymtun network configurations, -alongside diagnostics for verifying system settings and network connectivity. - -* fetch_ipv6_address_nym_tun - Fetches the IPv6 address assigned to the 'nymtun0'. -* fetch_and_display_ipv6 - Displays the IPv6 address on the default network device. -* apply_iptables_rules - Applies necessary IPv4 and IPv6 iptables rules. -* remove_iptables_rules - Removes applied IPv4 and IPv6 iptables rules. -* check_ipv6_ipv4_forwarding - Checks if IPv4 and IPv6 forwarding are enabled. -* check_nymtun_iptables - Check nymtun0 device -* perform_ipv4_ipv6_pings - Perform ipv4 and ipv6 pings to google -* check_ip6_ipv4_routing - Check ipv6 and ipv4 routing -* joke_through_the_mixnet - Run a joke through the mixnet via ipv4 and ipv6 +./network_tunnel_manager.sh fetch_and_display_ipv6 +``` +~~~admonish example collapsible=true title="Correct `./network_tunnel_manager.sh fetch_and_display_ipv6` output:" +```sh +iptables-persistent is already installed. +Using IPv6 address: 2001:db8:a160::1/112 #the address will be different for you +operation fetch_ipv6_address_nym_tun completed successfully. ``` ~~~ - - To run the script next time, just enter `./network_tunnel_manager ` - -2. Make sure your `nym-node --mode exit-gateway` service is up running - -3. Check Nymtun IP tables: +4. Apply the rules for IPv4 and IPv6: ```sh -sudo ./network_tunnel_manager.sh check_nymtun_iptables +./network_tunnel_manager.sh apply_iptables_rules +``` + +- The process may prompt you if you want to save current IPv4 and IPv6 rules, choose yes. + +![](../images/ip_table_prompt.png) + +5. Check Nymtun IP tables: +- If there's no process running it wouldn't return anything. +- In case you see `nymtun0` but not active, this is probably because you are setting up a new (never bonded) node and not upgrading an existing one. + +```sh +./network_tunnel_manager.sh check_nymtun_iptables ``` ~~~admonish example collapsible=true title="Correct `./network_tunnel_manager.sh check_nymtun_iptables` output:" @@ -303,40 +327,19 @@ operation check_nymtun_iptables completed successfully. ``` ~~~ - - If there's no process running it wouldn't return anything. - - In case you see `nymtun0` but not active, this is probably because you are setting up a new (never bonded) node and not upgrading an exisitng one. In that case you need to [bond](bonding.md) your node now. +6. Apply the rules for WG routing: -4. Display IPv6: ```sh -sudo ./network_tunnel_manager.sh fetch_and_display_ipv6 -``` - - if you have a `global ipv6` address this is good - -~~~admonish example collapsible=true title="Correct `./network_tunnel_manager.sh fetch_and_display_ipv6` output:" -```sh -iptables-persistent is already installed. -Using IPv6 address: 2001:db8:a160::1/112 #the address will be different for you -operation fetch_ipv6_address_nym_tun completed successfully. -``` -~~~ - -5. Apply the rules: -```sh -sudo ./network_tunnel_manager.sh apply_iptables_rules +./network_tunnel_manager.sh apply_iptables_rules_wg ``` - - The process may prompt you if you want to save current IPv4 and IPv6 rules, choose yes. +7. At this point your node needs to be [bonded](bonding.md) to the API for `nymtun0` to interact with the network. After bonding please follow up with the remaining steps below to ensure that your node is routing properly. -![](../images/ip_table_prompt.png) - - - check IPv6 again like in point 3 - -6. At this point your node needs to be [bonded](bonding.md) to the API for `nymtun0` to interact with the network. After bonding please follow up with the remaining streps below to ensure that your Exit Gateway is routing properly. - -7. Check `nymtun0` interface: +8. Check `nymtun0` interface: ```sh ip addr show nymtun0 ``` + ~~~admonish example collapsible=true title="Correct `ip addr show nymtun0` output:" ```sh # your addresses will be different @@ -351,82 +354,28 @@ ip addr show nymtun0 ``` ~~~ -8. Validate your IPv6 and IPv4 networking by running a joke via Mixnet: +9. Validate your IPv6 and IPv4 networking by running a joke test via Mixnet: ```sh -sudo ./network_tunnel_manager.sh joke_through_the_mixnet +./network_tunnel_manager.shjoke_through_the_mixnet ``` -Make sure that you get the validation of IPv4 and IPv6 connectivity. If there are still any problems, please refer to [troubleshooting section](../troubleshooting/vps-isp.md#incorrect-gateway-network-check). - -#### Mode: `mixnode` - -```admonish caution title="" -Most of the time the packets sent through the Mixnet are IPv4 based. The IPv6 packets are still pretty rare and therefore it's not mandatory from operational point of view. If you preparing to run a `nym-node` with all modes enabled once this option is implemented, then the IPv6 setup on your VPS is required. -``` - -1. Download `network_tunnel_manager.sh`, make executable and run: - +10. Validate your tunneling by running a joke test via WG: ```sh -curl -o network_tunnel_manager.sh -L https://gist.githubusercontent.com/tommyv1987/ccf6ca00ffb3d7e13192edda61bb2a77/raw/9d785d6ee3aa2970553633eccbd89a827f49fab5/network_tunnel_manager.sh && chmod +x network_tunnel_manager.sh && ./network_tunnel_manager.sh +./network_tunnel_manager.sh joke_through_wg_tunnel ``` -Here is a quick command explanation, for more details on the `network_tunnel_manager.sh` script, refer to the [overview](https://gist.github.com/tommyv1987/ccf6ca00ffb3d7e13192edda61bb2a77) under the code block. Mind that for `mixnode` VPS setup we will use only a few of the commands. - -~~~admonish example collapsible=true title="A summarized usage of `network_tunnel_manager.sh`" +11. Now you can run your node with the `--wireguard-enabled true` flag or add it to your [systemd service config](#systemd). Restart your `nym-node` or [systemd](#following-steps-for-nym-nodes-running-as-systemd-service) service (recommended): ```sh -summary: -This is a comprehensive script for configuring network packet forwarding and iptables rules, -aimed at ensuring smooth operation of a tunnel interface. -It includes functionality for both setup and tear-down of nymtun network configurations, -alongside diagnostics for verifying system settings and network connectivity. - -* fetch_ipv6_address_nym_tun - Fetches the IPv6 address assigned to the 'nymtun0'. -* fetch_and_display_ipv6 - Displays the IPv6 address on the default network device. -* apply_iptables_rules - Applies necessary IPv4 and IPv6 iptables rules. -* remove_iptables_rules - Removes applied IPv4 and IPv6 iptables rules. -* check_ipv6_ipv4_forwarding - Checks if IPv4 and IPv6 forwarding are enabled. -* check_nymtun_iptables - Check nymtun0 device -* perform_ipv4_ipv6_pings - Perform ipv4 and ipv6 pings to google -* check_ip6_ipv4_routing - Check ipv6 and ipv4 routing -* joke_through_the_mixnet - Run a joke through the mixnet via ipv4 and ipv6 - +systemctl daemon-reload && systemctl restart nym-node.service ``` -~~~ - - - To run the script next time, just enter `./network_tunnel_manager ` - -2. Display IPv6: +- Optionally, you can check if the node is running correctly by monitoring the service logs: ```sh -sudo ./network_tunnel_manager.sh fetch_and_display_ipv6 -``` - - if you have a `global ipv6` address this is good - -~~~admonish example collapsible=true title="Correct `./network_tunnel_manager.sh fetch_and_display_ipv6` output:" -```sh -iptables-persistent is already installed. -Using IPv6 address: 2001:db8:a160::1/112 #the address will be different for you -operation fetch_ipv6_address_nym_tun completed successfully. -``` -~~~ - -3. Apply the rules: -```sh -sudo ./network_tunnel_manager.sh apply_iptables_rules +journalctl -u nym-node.service -f -n 100 ``` - - The process may prompt you if you want to save current IPv4 and IPv6 rules, choose yes. +Make sure that you get the validation of all connectivity. If there are still any problems, please refer to [troubleshooting section](../troubleshooting/vps-isp.md#incorrect-gateway-network-check). -![](../images/ip_table_prompt.png) - - - check IPv6 again like in point 2 - -4. Check connectivity -```sh -telnet -6 ipv6.telnetmyip.com -``` - -Make sure that you get the validation of IPv4 and IPv6 connectivity. If there are still any problems, please refer to [troubleshooting section](../troubleshooting/vps-isp.md#incorrect-gateway-network-check). ## Next Steps -There are a few more good suggestions for `nym-node` VPS configuration, especially to be considered for `exit-gateway` functionality, like Web Secure Socket or Reversed Proxy setup. Visit [Proxy configuration](proxy-configuration.md) page to see the guides. +There are a few more good suggestions for `nym-node` configuration, like Web Secure Socket or Reversed Proxy setup. These are optional and you can skip them if you want. Visit [Proxy configuration](proxy-configuration.md) page to see the guides. diff --git a/documentation/operators/src/nodes/maintenance.md b/documentation/operators/src/nodes/maintenance.md index 00b91f1b69..df109c7f83 100644 --- a/documentation/operators/src/nodes/maintenance.md +++ b/documentation/operators/src/nodes/maintenance.md @@ -344,22 +344,18 @@ less ~/.nym/nym-nodes/default-nym-node/config/config.toml ## Ports All ``-specific port configuration can be found in `$HOME/.nym///config/config.toml`. If you do edit any port configs, remember to restart your client and node processes. -### Nym Node: Mixnode mode port reference +### Nym Node Port Reference | Default port | Use | | ------------ | ------------------------- | | `1789` | Listen for Mixnet traffic | | `1790` | Listen for VerLoc traffic | | `8080` | Metrics http API endpoint | - - -### Nym Node: Gateway modes port reference -| Default port | Use | -|--------------|---------------------------| | `1789` | Listen for Mixnet traffic | | `9000` | Listen for Client traffic | | `9001` | WSS | +| `51822/udp` | WireGuard | -### Validator port reference +### Validator Port Reference All validator-specific port configuration can be found in `$HOME/.nymd/config/config.toml`. If you do edit any port configs, remember to restart your validator. | Default port | Use | diff --git a/documentation/operators/src/nodes/nym-node.md b/documentation/operators/src/nodes/nym-node.md index c33cce3ef3..a95b67657a 100644 --- a/documentation/operators/src/nodes/nym-node.md +++ b/documentation/operators/src/nodes/nym-node.md @@ -6,21 +6,25 @@ If you are a `nym-mixnode` or `nym-gateway` operator and you are not familiar wi NYM NODE is a tool for running a node within the Nym network. Nym Nodes containing functionality such as `mixnode`, `entry-gateway` and `exit-gateway` are fundamental components of Nym Mixnet architecture. Nym Nodes are ran by decentralised node operators. -To setup any type of Nym Node, start with either building [Nym's platform](../binaries/building-nym.md) from source or download [pre-compiled binaries](../binaries/pre-built-binaries.md) on the [configured server (VPS)](vps-setup.md) where you want to run the node. Nym Node will need to be bond to [Nym's wallet](wallet-preparation.md). Follow [preliminary steps](preliminary-steps.md) page before you initialise and run a node. +To setup any type of Nym Node, start with either building [Nym's platform](../binaries/building-nym.md) from source or download [pre-compiled binaries](../binaries/pre-built-binaries.md) on the [configured server (VPS)](vps-setup.md) where you want to run the node. Your Nym Node will need to be bonded before it can be run. We recommend most users use the [Nym desktop wallet](wallet-preparation.md) for this. -```admonish info -**Migrating an existing node to a new `nym-node` is simple. The steps are documented on the [next page](setup.md#migrate)** -``` +**Follow [preliminary steps](preliminary-steps.md) page before you configure and run a `nym-node`!** ## Steps for Nym Node Operators -Once VPS and Nym wallet are configured, binaries ready, the operators of `nym-node` need to: +Once [VPS and Nym wallet are configured](preliminary-steps.md), binaries ready, the operators of `nym-node` need to: -1. **[Setup & Run](setup.md) the node** +1. **[Setup](setup.md) the node** -2. **[Configure](configuration.md) the node** (and optionally WSS, reversed proxy, automation) +2. **[Configure](configuration.md) the node and optionally automation, Wireguard, WSS, reversed proxy ...** -3. **[Bond](bonding.md) the node to the Nym API, using Nym wallet** +3. **[Run](setup.md#initialise--run) the node or [the service](configuration.md#following-steps-for-nym-nodes-running-as-systemd-service)** + +4. **[Bond](bonding.md) the node to the Nym API, using Nym wallet** + +Make sure to follow the steps thoroughly, in case you find any point difficult don't hesitate to ask in our [Operators channel](https://matrix.to/#/#operators:nymtech.chat). + + diff --git a/documentation/operators/src/nodes/setup.md b/documentation/operators/src/nodes/setup.md index f35185e040..542dc7d883 100644 --- a/documentation/operators/src/nodes/setup.md +++ b/documentation/operators/src/nodes/setup.md @@ -82,10 +82,8 @@ To list all available flags for each command, run `./nym-node --help` ``` ~~~ -```admonish bug -The Wireguard flags currently have limited functionality. This feature is under development and testing. - -**Keep Wireguard disabled for the time being!** +```admonish warning +The Wireguard flags currently have limited functionality. From version `1.1.6` ([`v2024.9-topdeck`](https://github.com/nymtech/nym/releases/tag/nym-binaries-v2024.9-topdeck)) wireguard is available and recommended to be switched on for nodes running as Gateways. Keep in mind that this option needs a bit of a special [configuration](configuration.md#wireguard-setup). ``` #### Flags Summary @@ -170,11 +168,11 @@ To prevent over-flooding of our documentation we cannot provide with every singl ./nym-node run --mode exit-gateway # with other options -./nym-node run --id --mode exit-gateway --public-ips "$(curl -4 https://ifconfig.me)" --hostname "" --http-bind-address 0.0.0.0:8080 --mixnet-bind-address 0.0.0.0:1789 --location --accept-operator-terms-and-conditions --wireguard-enabled false +./nym-node run --id --mode exit-gateway --public-ips "$(curl -4 https://ifconfig.me)" --hostname "" --http-bind-address 0.0.0.0:8080 --mixnet-bind-address 0.0.0.0:1789 --location --accept-operator-terms-and-conditions --wireguard-enabled true # is in format without 'https://' prefix # is format like 'Jamaica', or two-letter alpha2 (e.g. 'JM'), three-letter alpha3 (e.g. 'JAM') or three-digit numeric-3 (e.g. '388') can be provided. -# keep wireguard disabled +# wireguard can be enabled from version 1.1.6 onwards ``` **Initialise only** without running the node with `--init-only` command : @@ -184,11 +182,11 @@ To prevent over-flooding of our documentation we cannot provide with every singl ./nym-node run --init-only --mode exit-gateway # with a custom `--id` and other options -./nym-node run --id --init-only --mode exit-gateway --public-ips "$(curl -4 https://ifconfig.me)" --hostname "" --http-bind-address 0.0.0.0:8080 --mixnet-bind-address 0.0.0.0:1789 --location --accept-operator-terms-and-conditions --wireguard-enabled false +./nym-node run --id --init-only --mode exit-gateway --public-ips "$(curl -4 https://ifconfig.me)" --hostname "" --http-bind-address 0.0.0.0:8080 --mixnet-bind-address 0.0.0.0:1789 --location --accept-operator-terms-and-conditions --wireguard-enabled true # is in format without 'https://' prefix # is format like 'Jamaica', or two-letter alpha2 (e.g. 'JM'), three-letter alpha3 (e.g. 'JAM') or three-digit numeric-3 (e.g. '388') can be provided. -# keep wireguard disabled +# wireguard can be enabled from version 1.1.6 onwards ``` Run the node with custom `--id` without initialising, using `--deny-init` command @@ -203,7 +201,16 @@ Run the node with custom `--id` without initialising, using `--deny-init` comman ./nym-node run --mode entry-gateway ``` -Initialise only with a custom `--id` and `--init-only` command: +Initialise & run with all options +```sh +./nym-node run --id --mode entry-gateway --public-ips "$(curl -4 https://ifconfig.me)" --hostname "" --http-bind-address 0.0.0.0:8080 --mixnet-bind-address 0.0.0.0:1789 --accept-operator-terms-and-conditions --wireguard-enabled true + +# is in format without 'https://' prefix +# is format like 'Jamaica', or two-letter alpha2 (e.g. 'JM'), three-letter alpha3 (e.g. 'JAM') or three-digit numeric-3 (e.g. '388') can be provided. +# wireguard can be enabled from version 1.1.6 onwards +``` + +Initialise only, with an `--init-only` command (a custom `--id` used): ```sh ./nym-node run --id --init-only --mode entry-gateway --public-ips "$(curl -4 https://ifconfig.me)" --hostname "" --http-bind-address 0.0.0.0:8080 --mixnet-bind-address 0.0.0.0:1789 --accept-operator-terms-and-conditions ``` diff --git a/documentation/operators/src/nodes/vps-setup.md b/documentation/operators/src/nodes/vps-setup.md index 1594d6a147..6cbba86cdf 100644 --- a/documentation/operators/src/nodes/vps-setup.md +++ b/documentation/operators/src/nodes/vps-setup.md @@ -97,18 +97,26 @@ ufw enable ufw status ``` -2. Open all needed ports to have your firewall working correctly: +2. Open all needed ports to have your firewall for `nym-node` working correctly: ```sh -# for nym-node -ufw allow 1789,1790,8080,9000,9001,22/tcp +ufw allow 22/tcp # SSH - you're in control of these ports +ufw allow 80/tcp # HTTP +ufw allow 443/tcp # HTTPS +ufw allow 1789/tcp # Nym specific +ufw allow 1790/tcp # Nym specific +ufw allow 8080/tcp # Nym specific - nym-node-api +ufw allow 9000/tcp # Nym Specific - clients port +ufw allow 9001/tcp # Nym specific - wss port +ufw allow 51822/udp # WireGuard +``` -# in case of planning to setup a WSS (for Gateway functionality) -ufw allow 9001/tcp +- In case of reverse proxy setup add: +```sh +ufw allow 443/tcp +``` -# in case of reverse proxy for the swagger page (for Gateway optionality) -ufw allow 80,443/tcp - -# for validator +- For validator setup open these ports: +```sh ufw allow 1317,26656,26660,22,80,443/tcp ``` @@ -237,6 +245,7 @@ All node-specific port configuration can be found in `$HOME/.nym// Date: Tue, 13 Aug 2024 15:09:48 +0200 Subject: [PATCH 09/93] Remove deprecated mark_as_success and use new disarm (#4751) --- clients/native/src/websocket/handler.rs | 2 +- common/client-core/src/client/base_client/mod.rs | 4 ++-- common/client-libs/gateway-client/src/packet_router.rs | 4 ++-- common/client-libs/gateway-client/src/socket_state.rs | 4 ++-- common/mixnode-common/src/verloc/listener.rs | 2 +- common/mixnode-common/src/verloc/mod.rs | 2 +- common/mixnode-common/src/verloc/sender.rs | 2 +- common/socks5-client-core/src/socks/client.rs | 4 ++-- common/socks5/proxy-helpers/src/proxy_runner/inbound.rs | 2 +- common/socks5/proxy-helpers/src/proxy_runner/mod.rs | 2 +- common/socks5/proxy-helpers/src/proxy_runner/outbound.rs | 2 +- common/task/src/manager.rs | 6 +----- .../client_handling/websocket/connection_handler/mod.rs | 2 +- .../src/node/mixnet_handling/receiver/connection_handler.rs | 2 +- mixnode/src/node/listener/connection_handler/mod.rs | 2 +- service-providers/network-requester/src/core.rs | 2 +- 16 files changed, 20 insertions(+), 24 deletions(-) diff --git a/clients/native/src/websocket/handler.rs b/clients/native/src/websocket/handler.rs index 3185d71900..3d199cc152 100644 --- a/clients/native/src/websocket/handler.rs +++ b/clients/native/src/websocket/handler.rs @@ -422,7 +422,7 @@ impl Handler { ) { // We don't want a crash in the connection handler to trigger a shutdown of the whole // process. - task_client.mark_as_success(); + task_client.disarm(); let ws_stream = match accept_async(socket).await { Ok(ws_stream) => ws_stream, diff --git a/common/client-core/src/client/base_client/mod.rs b/common/client-core/src/client/base_client/mod.rs index 7d494bce35..c91a7569fc 100644 --- a/common/client-core/src/client/base_client/mod.rs +++ b/common/client-core/src/client/base_client/mod.rs @@ -455,7 +455,7 @@ where Err(ClientCoreError::CustomGatewaySelectionExpected) } else { // and make sure to invalidate the task client so we wouldn't cause premature shutdown - shutdown.mark_as_success(); + shutdown.disarm(); custom_gateway_transceiver.set_packet_router(packet_router)?; Ok(custom_gateway_transceiver) }; @@ -562,7 +562,7 @@ where if topology_config.disable_refreshing { // if we're not spawning the refresher, don't cause shutdown immediately info!("The topology refesher is not going to be started"); - shutdown.mark_as_success(); + shutdown.disarm(); } else { // don't spawn the refresher if we don't want to be refreshing the topology. // only use the initial values obtained diff --git a/common/client-libs/gateway-client/src/packet_router.rs b/common/client-libs/gateway-client/src/packet_router.rs index cd3cc23d51..ab94ecbac3 100644 --- a/common/client-libs/gateway-client/src/packet_router.rs +++ b/common/client-libs/gateway-client/src/packet_router.rs @@ -70,8 +70,8 @@ impl PacketRouter { Ok(()) } - pub fn mark_as_success(&mut self) { - self.shutdown.mark_as_success(); + pub fn disarm(&mut self) { + self.shutdown.disarm(); } } diff --git a/common/client-libs/gateway-client/src/socket_state.rs b/common/client-libs/gateway-client/src/socket_state.rs index 9b9982f852..d7754c5341 100644 --- a/common/client-libs/gateway-client/src/socket_state.rs +++ b/common/client-libs/gateway-client/src/socket_state.rs @@ -113,8 +113,8 @@ impl PartiallyDelegatedRouter { let return_res = match ret { Err(err) => self.stream_return.send(Err(err)), Ok(_) => { - self.packet_router.mark_as_success(); - task_client.mark_as_success(); + self.packet_router.disarm(); + task_client.disarm(); self.stream_return.send(Ok(split_stream)) } }; diff --git a/common/mixnode-common/src/verloc/listener.rs b/common/mixnode-common/src/verloc/listener.rs index fada769a76..aa58b56b8e 100644 --- a/common/mixnode-common/src/verloc/listener.rs +++ b/common/mixnode-common/src/verloc/listener.rs @@ -57,7 +57,7 @@ impl PacketListener { // cloning the arc as each accepted socket is handled in separate task let connection_handler = Arc::clone(&self.connection_handler); let mut handler_shutdown_listener = self.shutdown.clone(); - handler_shutdown_listener.mark_as_success(); + handler_shutdown_listener.disarm(); tokio::select! { socket = listener.accept() => { diff --git a/common/mixnode-common/src/verloc/mod.rs b/common/mixnode-common/src/verloc/mod.rs index 25c7bd8881..68004105d2 100644 --- a/common/mixnode-common/src/verloc/mod.rs +++ b/common/mixnode-common/src/verloc/mod.rs @@ -245,7 +245,7 @@ impl VerlocMeasurer { } let mut shutdown_listener = self.shutdown_listener.clone().named("VerlocMeasurement"); - shutdown_listener.mark_as_success(); + shutdown_listener.disarm(); for chunk in nodes_to_test.chunks(self.config.tested_nodes_batch_size) { let mut chunk_results = Vec::with_capacity(chunk.len()); diff --git a/common/mixnode-common/src/verloc/sender.rs b/common/mixnode-common/src/verloc/sender.rs index 1549af972f..5887a22a6e 100644 --- a/common/mixnode-common/src/verloc/sender.rs +++ b/common/mixnode-common/src/verloc/sender.rs @@ -84,7 +84,7 @@ impl PacketSender { tested_node: TestedNode, ) -> Result { let mut shutdown_listener = self.shutdown_listener.fork(tested_node.address.to_string()); - shutdown_listener.mark_as_success(); + shutdown_listener.disarm(); let mut conn = match tokio::time::timeout( self.connection_timeout, diff --git a/common/socks5-client-core/src/socks/client.rs b/common/socks5-client-core/src/socks/client.rs index cca9cd6b53..572849d296 100644 --- a/common/socks5-client-core/src/socks/client.rs +++ b/common/socks5-client-core/src/socks/client.rs @@ -218,7 +218,7 @@ impl SocksClient { packet_type: Option, ) -> Self { // If this task fails and exits, we don't want to send shutdown signal - shutdown_listener.mark_as_success(); + shutdown_listener.disarm(); let connection_id = Self::generate_random(); @@ -294,7 +294,7 @@ impl SocksClient { .shutdown() .await .map_err(|source| SocksProxyError::SocketShutdownFailure { source })?; - self.shutdown_listener.mark_as_success(); + self.shutdown_listener.disarm(); Ok(()) } diff --git a/common/socks5/proxy-helpers/src/proxy_runner/inbound.rs b/common/socks5/proxy-helpers/src/proxy_runner/inbound.rs index 82e6396a5f..e63df37851 100644 --- a/common/socks5/proxy-helpers/src/proxy_runner/inbound.rs +++ b/common/socks5/proxy-helpers/src/proxy_runner/inbound.rs @@ -172,6 +172,6 @@ where trace!("{} - inbound closed", connection_id); shutdown_notify.notify_one(); - shutdown_listener.mark_as_success(); + shutdown_listener.disarm(); reader } diff --git a/common/socks5/proxy-helpers/src/proxy_runner/mod.rs b/common/socks5/proxy-helpers/src/proxy_runner/mod.rs index 38499ea59c..970378d811 100644 --- a/common/socks5/proxy-helpers/src/proxy_runner/mod.rs +++ b/common/socks5/proxy-helpers/src/proxy_runner/mod.rs @@ -148,7 +148,7 @@ where } pub fn into_inner(mut self) -> (TcpStream, ConnectionReceiver) { - self.shutdown_listener.mark_as_success(); + self.shutdown_listener.disarm(); ( self.socket.take().unwrap(), self.mix_receiver.take().unwrap(), diff --git a/common/socks5/proxy-helpers/src/proxy_runner/outbound.rs b/common/socks5/proxy-helpers/src/proxy_runner/outbound.rs index 72d8824d2b..77f5ae2b59 100644 --- a/common/socks5/proxy-helpers/src/proxy_runner/outbound.rs +++ b/common/socks5/proxy-helpers/src/proxy_runner/outbound.rs @@ -90,6 +90,6 @@ pub(super) async fn run_outbound( trace!("{} - outbound closed", connection_id); shutdown_notify.notify_one(); - shutdown_listener.mark_as_success(); + shutdown_listener.disarm(); (writer, mix_receiver) } diff --git a/common/task/src/manager.rs b/common/task/src/manager.rs index ab03870dc0..f880629bac 100644 --- a/common/task/src/manager.rs +++ b/common/task/src/manager.rs @@ -470,12 +470,8 @@ impl TaskClient { // This listener should to *not* notify the ShutdownNotifier to shutdown when dropped. For // example when we clone the listener for a task handling connections, we often want to drop // without signal failure. - pub fn mark_as_success(&mut self) { - self.mode.set_should_not_signal_on_drop(); - } - pub fn disarm(&mut self) { - self.mark_as_success(); + self.mode.set_should_not_signal_on_drop(); } pub fn send_we_stopped(&mut self, err: SentError) { diff --git a/gateway/src/node/client_handling/websocket/connection_handler/mod.rs b/gateway/src/node/client_handling/websocket/connection_handler/mod.rs index ecb0aa48d7..aeebdb02fa 100644 --- a/gateway/src/node/client_handling/websocket/connection_handler/mod.rs +++ b/gateway/src/node/client_handling/websocket/connection_handler/mod.rs @@ -95,7 +95,7 @@ pub(crate) async fn handle_connection( St: Storage + Clone + 'static, { // If the connection handler abruptly stops, we shouldn't signal global shutdown - shutdown.mark_as_success(); + shutdown.disarm(); match shutdown .run_future(handle.perform_websocket_handshake()) diff --git a/gateway/src/node/mixnet_handling/receiver/connection_handler.rs b/gateway/src/node/mixnet_handling/receiver/connection_handler.rs index 7d6649530f..4ee18c77d5 100644 --- a/gateway/src/node/mixnet_handling/receiver/connection_handler.rs +++ b/gateway/src/node/mixnet_handling/receiver/connection_handler.rs @@ -203,7 +203,7 @@ impl ConnectionHandler { mut shutdown: TaskClient, ) { debug!("Starting connection handler for {:?}", remote); - shutdown.mark_as_success(); + shutdown.disarm(); let mut framed_conn = Framed::new(conn, NymCodec); while !shutdown.is_shutdown() { tokio::select! { diff --git a/mixnode/src/node/listener/connection_handler/mod.rs b/mixnode/src/node/listener/connection_handler/mod.rs index 08edd7d298..f4144c4f67 100644 --- a/mixnode/src/node/listener/connection_handler/mod.rs +++ b/mixnode/src/node/listener/connection_handler/mod.rs @@ -81,7 +81,7 @@ impl ConnectionHandler { mut shutdown: TaskClient, ) { debug!("Starting connection handler for {:?}", remote); - shutdown.mark_as_success(); + shutdown.disarm(); let mut framed_conn = Framed::new(conn, NymCodec); while !shutdown.is_shutdown() { tokio::select! { diff --git a/service-providers/network-requester/src/core.rs b/service-providers/network-requester/src/core.rs index 788064fcd5..f9a6b3e5aa 100644 --- a/service-providers/network-requester/src/core.rs +++ b/service-providers/network-requester/src/core.rs @@ -495,7 +495,7 @@ impl NRServiceProvider { .send(error_msg) .await .expect("InputMessageReceiver has stopped receiving!"); - shutdown.mark_as_success(); + shutdown.disarm(); return; } From ed4fd84503b2266a69b890f2d74900381e038c39 Mon Sep 17 00:00:00 2001 From: import this <97586125+serinko@users.noreply.github.com> Date: Tue, 13 Aug 2024 15:39:31 +0000 Subject: [PATCH 10/93] serinko/hotfix --- documentation/operators/src/changelog.md | 4 +++- 1 file changed, 3 insertions(+), 1 deletion(-) diff --git a/documentation/operators/src/changelog.md b/documentation/operators/src/changelog.md index 088fe6e15a..b4a77e5cc2 100644 --- a/documentation/operators/src/changelog.md +++ b/documentation/operators/src/changelog.md @@ -106,7 +106,7 @@ sudo -E ./nym-vpn-cli -c ../qa.env run --entry-gateway-id $entry_gateway --exit- - **Download Nym Node:** - You can download the `nym-node` binary directly using the following command: ```bash -curl -s https://github.com/nymtech/nym/releases/tag/nym-binaries-v2024.9-topdeck/nym-node -o nym-node && chmod u+x nym-node +curl -L https://github.com/nymtech/nym/releases/tag/nym-binaries-v2024.9-topdeck/nym-node -o nym-node && chmod u+x nym-node ``` **Step 1: Update UFW Firewall Rules** @@ -200,6 +200,8 @@ Finally, run the following command to initiate our favorite routing test - run t ```bash ./network_tunnel_manager.sh joke_through_wg_tunnel ``` + +- **Note:** Wireguard will return only IPv4 joke, not IPv6. WG IPv6 is under development. Running IPR joke through the mixnet with `./network_tunnel_manager.sh joke_through_the_mixnet` should work with both IPv4 and IPv6! ~~~ * [Change `--wireguard-enabled` flag to `true`](nodes/setup.md#-initialise--run): With a proper [routing configuration](nodes/configuration.md#routing-configuration) `nym-nodes` running as Gateways can now enable WG. See the example below: From 61471e9058b5d600fbe275e36a4d445eb27a3c53 Mon Sep 17 00:00:00 2001 From: import this <97586125+serinko@users.noreply.github.com> Date: Tue, 13 Aug 2024 15:41:16 +0000 Subject: [PATCH 11/93] add note about IPv6 --- documentation/operators/src/nodes/configuration.md | 2 ++ 1 file changed, 2 insertions(+) diff --git a/documentation/operators/src/nodes/configuration.md b/documentation/operators/src/nodes/configuration.md index dd57723c31..ed9b23e3ff 100644 --- a/documentation/operators/src/nodes/configuration.md +++ b/documentation/operators/src/nodes/configuration.md @@ -364,6 +364,8 @@ ip addr show nymtun0 ./network_tunnel_manager.sh joke_through_wg_tunnel ``` +- **Note:** WireGuard will return only IPv4 joke, not IPv6. WG IPv6 is under development. Running IPR joke through the mixnet with `./network_tunnel_manager.sh joke_through_the_mixnet` should work with both IPv4 and IPv6! + 11. Now you can run your node with the `--wireguard-enabled true` flag or add it to your [systemd service config](#systemd). Restart your `nym-node` or [systemd](#following-steps-for-nym-nodes-running-as-systemd-service) service (recommended): ```sh systemctl daemon-reload && systemctl restart nym-node.service From d473e8743e75e88873bcac20b5ae04a4fb750bdd Mon Sep 17 00:00:00 2001 From: shenpengfeng Date: Thu, 15 Aug 2024 00:49:54 +0800 Subject: [PATCH 12/93] chore: remove repetitive words Signed-off-by: shenpengfeng --- documentation/dev-portal/src/nymvpn/faq.md | 2 +- documentation/operators/src/legal/swiss.md | 2 +- nym-api/src/node_status_api/utils.rs | 2 +- 3 files changed, 3 insertions(+), 3 deletions(-) diff --git a/documentation/dev-portal/src/nymvpn/faq.md b/documentation/dev-portal/src/nymvpn/faq.md index d05df2d051..64830065ac 100644 --- a/documentation/dev-portal/src/nymvpn/faq.md +++ b/documentation/dev-portal/src/nymvpn/faq.md @@ -56,7 +56,7 @@ Project Smoosh is a code name for a process in which different components of Nym ## Exit Gateway -Part of the the transition under code name [Project Smoosh](#project-smoosh) is a creation of [Nym Exit Gateway](https://nymtech.net/operators/legal/exit-gateway.html) functionality. The operators running Gateways would have to “open” their nodes to a wider range of online services, in a similar fashion to Tor exit relays. The main change will be to expand the original short [allowed.list](https://nymtech.net/.wellknown/network-requester/standard-allowed-list.txt) to a more permissive setup. An [exit policy](https://nymtech.net/.wellknown/network-requester/exit-policy.txt) will constrain the hosts that the users of the Nym VPN and Mixnet can connect to. This will be done in an effort to protect the operators, as Gateways will act both as SOCKS5 Network Requesters, and exit nodes for IP traffic from Nym VPN and Mixnet clients. +Part of the transition under code name [Project Smoosh](#project-smoosh) is a creation of [Nym Exit Gateway](https://nymtech.net/operators/legal/exit-gateway.html) functionality. The operators running Gateways would have to “open” their nodes to a wider range of online services, in a similar fashion to Tor exit relays. The main change will be to expand the original short [allowed.list](https://nymtech.net/.wellknown/network-requester/standard-allowed-list.txt) to a more permissive setup. An [exit policy](https://nymtech.net/.wellknown/network-requester/exit-policy.txt) will constrain the hosts that the users of the Nym VPN and Mixnet can connect to. This will be done in an effort to protect the operators, as Gateways will act both as SOCKS5 Network Requesters, and exit nodes for IP traffic from Nym VPN and Mixnet clients. * Read more how the exit policy gets implemented [here](https://nymtech.net/operators/faq/smoosh-faq.html#how-will-the-exit-policy-be-implemented) * Check out [Nym Operators Legal Forum](https://nymtech.net/operators/legal/exit-gateway.html) diff --git a/documentation/operators/src/legal/swiss.md b/documentation/operators/src/legal/swiss.md index b879123d85..17e8a74aee 100644 --- a/documentation/operators/src/legal/swiss.md +++ b/documentation/operators/src/legal/swiss.md @@ -33,7 +33,7 @@ I therefore consider the risk for an exit node operator to become involved in a Nevertheless, in such a situation, exit node operators providers would have to provide the authorities with the information already available to them (Art. 22 Para. 3 SPTA), and they would have to tolerate monitoring by the authorities or by the persons commissioned by the service of the data which the monitored person transmits or stores using derived communications services (Art. 27 Para. 1 SPTA; see above, 5.1.1.2). There is no duty of data retention for providers of derived communication services, though. -The the risk for exit node operators of being upgraded according to Art. 22 Para. 4 SPTA is low to non existent for the reasons mentioned above. +The risk for exit node operators of being upgraded according to Art. 22 Para. 4 SPTA is low to non existent for the reasons mentioned above. #### Intelligence Service Law diff --git a/nym-api/src/node_status_api/utils.rs b/nym-api/src/node_status_api/utils.rs index 598fba5679..0682cf62ba 100644 --- a/nym-api/src/node_status_api/utils.rs +++ b/nym-api/src/node_status_api/utils.rs @@ -45,7 +45,7 @@ impl NodeUptimes { // If somehow we have more reports than the actual test runs it means something weird is going on // (or we just started running this code on old data, so if it appears for first 24h, it's fine and actually expected // as we would not have any run information from the past) - // Either way, bound the the number of "up" reports by number of test runs and log warnings + // Either way, bound the number of "up" reports by number of test runs and log warnings // if that happens let last_day_sum: f32 = if last_day.len() > last_day_test_runs { From dff82f946f3d8e3eddad0d1c72c101fa600bde3e Mon Sep 17 00:00:00 2001 From: =?UTF-8?q?Jon=20H=C3=A4ggblad?= Date: Thu, 15 Aug 2024 09:42:13 +0200 Subject: [PATCH 13/93] Make gateway latency check generic (#4759) * Replace concrete gateway type with trait in latency check * Rename to ConnectableGateway --- common/client-core/src/init/helpers.rs | 58 ++++++++++++++++++-------- 1 file changed, 40 insertions(+), 18 deletions(-) diff --git a/common/client-core/src/init/helpers.rs b/common/client-core/src/init/helpers.rs index f0fbe7c23f..7db4e3a01e 100644 --- a/common/client-core/src/init/helpers.rs +++ b/common/client-core/src/init/helpers.rs @@ -46,13 +46,34 @@ const MEASUREMENTS: usize = 3; const CONN_TIMEOUT: Duration = Duration::from_millis(1500); const PING_TIMEOUT: Duration = Duration::from_millis(1000); -struct GatewayWithLatency<'a> { - gateway: &'a gateway::Node, +// The abstraction that some of these helpers use +pub trait ConnectableGateway { + fn identity(&self) -> &identity::PublicKey; + fn clients_address(&self) -> String; + fn is_wss(&self) -> bool; +} + +impl ConnectableGateway for gateway::Node { + fn identity(&self) -> &identity::PublicKey { + self.identity() + } + + fn clients_address(&self) -> String { + self.clients_address() + } + + fn is_wss(&self) -> bool { + self.clients_wss_port.is_some() + } +} + +struct GatewayWithLatency<'a, G: ConnectableGateway> { + gateway: &'a G, latency: Duration, } -impl<'a> GatewayWithLatency<'a> { - fn new(gateway: &'a gateway::Node, latency: Duration) -> Self { +impl<'a, G: ConnectableGateway> GatewayWithLatency<'a, G> { + fn new(gateway: &'a G, latency: Duration) -> Self { GatewayWithLatency { gateway, latency } } } @@ -130,11 +151,14 @@ async fn connect(endpoint: &str) -> Result { JSWebsocket::new(endpoint).map_err(|_| ClientCoreError::GatewayJsConnectionFailure) } -async fn measure_latency(gateway: &gateway::Node) -> Result { +async fn measure_latency(gateway: &G) -> Result, ClientCoreError> +where + G: ConnectableGateway, +{ let addr = gateway.clients_address(); trace!( "establishing connection to {} ({addr})...", - gateway.identity_key, + gateway.identity(), ); let mut stream = connect(&addr).await?; @@ -177,7 +201,7 @@ async fn measure_latency(gateway: &gateway::Node) -> Result Result( +pub async fn choose_gateway_by_latency<'a, R: Rng, G: ConnectableGateway + Clone>( rng: &mut R, - gateways: &[gateway::Node], + gateways: &[G], must_use_tls: bool, -) -> Result { +) -> Result { let gateways = filter_by_tls(gateways, must_use_tls)?; info!( @@ -223,21 +247,19 @@ pub async fn choose_gateway_by_latency( info!( "chose gateway {} with average latency of {:?}", - chosen.gateway.identity_key, chosen.latency + chosen.gateway.identity(), + chosen.latency ); Ok(chosen.gateway.clone()) } -fn filter_by_tls( - gateways: &[gateway::Node], +fn filter_by_tls( + gateways: &[G], must_use_tls: bool, -) -> Result, ClientCoreError> { +) -> Result, ClientCoreError> { if must_use_tls { - let filtered = gateways - .iter() - .filter(|g| g.clients_wss_port.is_some()) - .collect::>(); + let filtered = gateways.iter().filter(|g| g.is_wss()).collect::>(); if filtered.is_empty() { return Err(ClientCoreError::NoWssGateways); From e2e49e7136301dcaa8ed4c916c8e566a0d5a7554 Mon Sep 17 00:00:00 2001 From: import this <97586125+serinko@users.noreply.github.com> Date: Sun, 18 Aug 2024 11:55:28 +0000 Subject: [PATCH 14/93] docs/hotfix --- documentation/operators/src/changelog.md | 2 +- 1 file changed, 1 insertion(+), 1 deletion(-) diff --git a/documentation/operators/src/changelog.md b/documentation/operators/src/changelog.md index b4a77e5cc2..707adc484c 100644 --- a/documentation/operators/src/changelog.md +++ b/documentation/operators/src/changelog.md @@ -106,7 +106,7 @@ sudo -E ./nym-vpn-cli -c ../qa.env run --entry-gateway-id $entry_gateway --exit- - **Download Nym Node:** - You can download the `nym-node` binary directly using the following command: ```bash -curl -L https://github.com/nymtech/nym/releases/tag/nym-binaries-v2024.9-topdeck/nym-node -o nym-node && chmod u+x nym-node +curl -L https://github.com/nymtech/nym/releases/download/nym-binaries-v2024.9-topdeck/nym-node -o nym-node && chmod u+x nym-node ``` **Step 1: Update UFW Firewall Rules** From 581cdd5bdf1c69ba844b25c36dbf58108a160ebe Mon Sep 17 00:00:00 2001 From: import this <97586125+serinko@users.noreply.github.com> Date: Sun, 18 Aug 2024 11:56:56 +0000 Subject: [PATCH 15/93] Update configuration.md --- documentation/operators/src/nodes/configuration.md | 2 +- 1 file changed, 1 insertion(+), 1 deletion(-) diff --git a/documentation/operators/src/nodes/configuration.md b/documentation/operators/src/nodes/configuration.md index ed9b23e3ff..b933c4dede 100644 --- a/documentation/operators/src/nodes/configuration.md +++ b/documentation/operators/src/nodes/configuration.md @@ -356,7 +356,7 @@ ip addr show nymtun0 9. Validate your IPv6 and IPv4 networking by running a joke test via Mixnet: ```sh -./network_tunnel_manager.shjoke_through_the_mixnet +./network_tunnel_manager.sh joke_through_the_mixnet ``` 10. Validate your tunneling by running a joke test via WG: From 2ae81f6da0e5121bb9f7099025662702eef0fa09 Mon Sep 17 00:00:00 2001 From: =?UTF-8?q?Bogdan-=C8=98tefan=20Neac=C5=9Fu?= Date: Tue, 20 Aug 2024 14:51:59 +0200 Subject: [PATCH 16/93] Avoid race on ip and registration structures (#4766) --- Cargo.lock | 1 - common/wireguard-types/Cargo.toml | 3 +- common/wireguard-types/src/registration.rs | 6 +- .../authenticator/src/mixnet_listener.rs | 79 ++++++++++++------- 4 files changed, 56 insertions(+), 33 deletions(-) diff --git a/Cargo.lock b/Cargo.lock index 68792a2ad6..2544f70511 100644 --- a/Cargo.lock +++ b/Cargo.lock @@ -6242,7 +6242,6 @@ name = "nym-wireguard-types" version = "0.1.0" dependencies = [ "base64 0.21.7", - "dashmap", "hmac", "log", "nym-config", diff --git a/common/wireguard-types/Cargo.toml b/common/wireguard-types/Cargo.toml index 807a59e857..27fe541f67 100644 --- a/common/wireguard-types/Cargo.toml +++ b/common/wireguard-types/Cargo.toml @@ -12,7 +12,6 @@ license.workspace = true [dependencies] base64 = { workspace = true } -dashmap = { workspace = true } log = { workspace = true } serde = { workspace = true, features = ["derive"] } thiserror = { workspace = true } @@ -35,7 +34,7 @@ x25519-dalek = { workspace = true, features = ["static_secrets"] } [dev-dependencies] rand = "0.8.5" -nym-crypto = { path = "../crypto", features = ["rand"]} +nym-crypto = { path = "../crypto", features = ["rand"] } [features] diff --git a/common/wireguard-types/src/registration.rs b/common/wireguard-types/src/registration.rs index 9d2d182f6d..ef90642b95 100644 --- a/common/wireguard-types/src/registration.rs +++ b/common/wireguard-types/src/registration.rs @@ -4,8 +4,8 @@ use crate::error::Error; use crate::PeerPublicKey; use base64::{engine::general_purpose, Engine}; -use dashmap::DashMap; use serde::{Deserialize, Serialize}; +use std::collections::HashMap; use std::net::IpAddr; use std::time::SystemTime; use std::{fmt, ops::Deref, str::FromStr}; @@ -17,8 +17,8 @@ use nym_crypto::asymmetric::encryption::PrivateKey; #[cfg(feature = "verify")] use sha2::Sha256; -pub type PendingRegistrations = DashMap; -pub type PrivateIPs = DashMap; +pub type PendingRegistrations = HashMap; +pub type PrivateIPs = HashMap; #[cfg(feature = "verify")] pub type HmacSha256 = Hmac; diff --git a/service-providers/authenticator/src/mixnet_listener.rs b/service-providers/authenticator/src/mixnet_listener.rs index b08b5054a5..df888113b7 100644 --- a/service-providers/authenticator/src/mixnet_listener.rs +++ b/service-providers/authenticator/src/mixnet_listener.rs @@ -24,7 +24,7 @@ use nym_wireguard_types::{ GatewayClient, InitMessage, PeerPublicKey, }; use rand::{prelude::IteratorRandom, thread_rng}; -use tokio::sync::mpsc::UnboundedReceiver; +use tokio::sync::{mpsc::UnboundedReceiver, RwLock}; use tokio_stream::wrappers::IntervalStream; use crate::{config::Config, error::*}; @@ -32,6 +32,20 @@ use crate::{config::Config, error::*}; type AuthenticatorHandleResult = Result; const DEFAULT_REGISTRATION_TIMEOUT_CHECK: Duration = Duration::from_secs(60); // 1 minute +pub(crate) struct RegistredAndFree { + registration_in_progres: PendingRegistrations, + free_private_network_ips: PrivateIPs, +} + +impl RegistredAndFree { + pub(crate) fn new(free_private_network_ips: PrivateIPs) -> Self { + RegistredAndFree { + registration_in_progres: Default::default(), + free_private_network_ips, + } + } +} + pub(crate) struct MixnetListener { // The configuration for the mixnet listener pub(crate) config: Config, @@ -43,12 +57,10 @@ pub(crate) struct MixnetListener { pub(crate) task_handle: TaskHandle, // Registrations awaiting confirmation - pub(crate) registration_in_progres: Arc, + pub(crate) registred_and_free: RwLock, pub(crate) peer_manager: PeerManager, - pub(crate) free_private_network_ips: Arc, - pub(crate) timeout_check_interval: IntervalStream, } @@ -63,15 +75,13 @@ impl MixnetListener { ) -> Self { let timeout_check_interval = IntervalStream::new(tokio::time::interval(DEFAULT_REGISTRATION_TIMEOUT_CHECK)); + let free_private_network_ips = private_ip_network.iter().map(|ip| (ip, None)).collect(); MixnetListener { config, mixnet_client, task_handle, - registration_in_progres: Default::default(), + registred_and_free: RwLock::new(RegistredAndFree::new(free_private_network_ips)), peer_manager: PeerManager::new(wireguard_gateway_data, response_rx), - free_private_network_ips: Arc::new( - private_ip_network.iter().map(|ip| (ip, None)).collect(), - ), timeout_check_interval, } } @@ -80,9 +90,15 @@ impl MixnetListener { self.peer_manager.wireguard_gateway_data.keypair() } - fn remove_stale_registrations(&self) -> Result<()> { - for reg in self.registration_in_progres.iter().map(|reg| reg.clone()) { - let mut ip = self + async fn remove_stale_registrations(&self) -> Result<()> { + let mut registred_and_free = self.registred_and_free.write().await; + let registred_values: Vec<_> = registred_and_free + .registration_in_progres + .values() + .cloned() + .collect(); + for reg in registred_values { + let ip = registred_and_free .free_private_network_ips .get_mut(®.gateway_data.private_ip) .ok_or(AuthenticatorError::InternalDataCorruption(format!( @@ -90,10 +106,9 @@ impl MixnetListener { reg.gateway_data.private_ip )))?; - let timestamp = ip.ok_or(AuthenticatorError::InternalDataCorruption(format!( - "timestamp should be set for IP {}", - ip.key() - )))?; + let timestamp = ip.ok_or(AuthenticatorError::InternalDataCorruption( + "timestamp should be set".to_string(), + ))?; let duration = SystemTime::now().duration_since(timestamp).map_err(|_| { AuthenticatorError::InternalDataCorruption( "set timestamp shouldn't have been set in the future".to_string(), @@ -101,7 +116,8 @@ impl MixnetListener { })?; if duration > DEFAULT_REGISTRATION_TIMEOUT_CHECK { *ip = None; - self.registration_in_progres + registred_and_free + .registration_in_progres .remove(®.gateway_data.pub_key()); log::debug!( "Removed stale registration of {}", @@ -120,9 +136,15 @@ impl MixnetListener { ) -> AuthenticatorHandleResult { let remote_public = init_message.pub_key(); let nonce: u64 = fastrand::u64(..); - if let Some(registration_data) = self.registration_in_progres.get(&remote_public) { + if let Some(registration_data) = self + .registred_and_free + .read() + .await + .registration_in_progres + .get(&remote_public) + { return Ok(AuthenticatorResponse::new_pending_registration_success( - registration_data.value().clone(), + registration_data.clone(), request_id, reply_to, )); @@ -145,18 +167,19 @@ impl MixnetListener { request_id, )); } - let mut private_ip_ref = self + let mut registred_and_free = self.registred_and_free.write().await; + let private_ip_ref = registred_and_free .free_private_network_ips .iter_mut() - .filter(|r| r.is_none()) + .filter(|r| r.1.is_none()) .choose(&mut thread_rng()) .ok_or(AuthenticatorError::NoFreeIp)?; // mark it as used, even though it's not final - *private_ip_ref = Some(SystemTime::now()); + *private_ip_ref.1 = Some(SystemTime::now()); let gateway_data = GatewayClient::new( self.keypair().private_key(), remote_public.inner(), - *private_ip_ref.key(), + *private_ip_ref.0, nonce, ); let registration_data = RegistrationData { @@ -164,7 +187,8 @@ impl MixnetListener { gateway_data, wg_port: self.config.authenticator.announced_port, }; - self.registration_in_progres + registred_and_free + .registration_in_progres .insert(remote_public, registration_data.clone()); Ok(AuthenticatorResponse::new_pending_registration_success( @@ -180,11 +204,11 @@ impl MixnetListener { request_id: u64, reply_to: Recipient, ) -> AuthenticatorHandleResult { - let registration_data = self + let mut registred_and_free = self.registred_and_free.write().await; + let registration_data = registred_and_free .registration_in_progres .get(&gateway_client.pub_key()) .ok_or(AuthenticatorError::RegistrationNotInProgress)? - .value() .clone(); if gateway_client @@ -192,7 +216,8 @@ impl MixnetListener { .is_ok() { self.peer_manager.add_peer(&gateway_client).await?; - self.registration_in_progres + registred_and_free + .registration_in_progres .remove(&gateway_client.pub_key()); Ok(AuthenticatorResponse::new_registered( @@ -294,7 +319,7 @@ impl MixnetListener { log::debug!("Authenticator [main loop]: received shutdown"); }, _ = self.timeout_check_interval.next() => { - if let Err(e) = self.remove_stale_registrations() { + if let Err(e) = self.remove_stale_registrations().await { log::error!("Could not clear stale registrations. The registration process might get jammed soon - {:?}", e); } } From 6296d09adff8f7fb1b1b56ab4d02d349d30392e1 Mon Sep 17 00:00:00 2001 From: import this <97586125+serinko@users.noreply.github.com> Date: Tue, 20 Aug 2024 13:10:05 +0000 Subject: [PATCH 17/93] [DOCs/developers]: Update NymVPN CLI guide (#4769) * creat guide to build nym-vpn-cli from source * update nymvpn cli guide --- documentation/dev-portal/src/nymvpn/cli.md | 94 ++++++++++++++++---- documentation/dev-portal/src/nymvpn/intro.md | 4 + 2 files changed, 82 insertions(+), 16 deletions(-) diff --git a/documentation/dev-portal/src/nymvpn/cli.md b/documentation/dev-portal/src/nymvpn/cli.md index 8e682dc987..925472cdcd 100644 --- a/documentation/dev-portal/src/nymvpn/cli.md +++ b/documentation/dev-portal/src/nymvpn/cli.md @@ -1,5 +1,9 @@ # NymVPN CLI Guide +```admonish tip title="web3summit testing" +**If you testing NymVPN CLI on web3summit Berlin, visit our event page with all info tailored for the event: [nym-vpn-cli.sandbox.nymtech.net/](https://nym-vpn-cli.sandbox.nymtech.net/).** +``` + ```admonish info To download NymVPN desktop version, visit [nymvpn.com/en/download](https://nymvpn.com/en/download). @@ -38,6 +42,32 @@ tar -xvf .tar.gz # tar -xvf nym-vpn-cli__ubuntu-22.04_x86_64.tar.gz ``` +### Building From Source + +NymVPN CLI can be built from source. This process is recommended for more advanced users as the installation may require different dependencies based on the operating system used. + +Start by installing [Go](https://go.dev/doc/install) and [Rust](https://rustup.rs/) languages on your system and then follow these steps: + +1. Clone NymVPN repository: +```sh +git clone https://github.com/nymtech/nym-vpn-client.git +``` + +2. Move to `nym-vpn-client` directory and compile `wireguard`: + +```sh +cd nym-vpn-client + +make build-wireguard +``` + +3. Compile NymVPN CLI +```sh +make build-nym-vpn-core +``` + +Now your NymVPN CLI is installed. Navigate to `nym-vpn-core/target/release` and use the commands the section below to run the client. + ## Running If you are running Debian/Ubuntu/PopOS or any other distributio supporting debian packages and systemd, see the [relevant section below](#debian-package-for-debianubuntupopos). @@ -125,7 +155,8 @@ To see all the possibilities run with `--help` flag: ```sh ./nym-vpn-cli --help ``` -~~~admonish example collapsible=true title="Console output" + +~~~admonish example collapsible=true title="nym-vpn-cli --help" ```sh Usage: nym-vpn-cli [OPTIONS] @@ -142,25 +173,56 @@ Options: ``` ~~~ -Here is a list of the options and their descriptions. Some are essential, some are more technical and not needed to be adjusted by users. +You can also run any command with `--help` flag to see a list of all options associated witht that command, the most important may be `run` command, like in this example. -**Fundamental commands and arguments** +~~~admonish example collapsible=true title="nym-vpn-cli run --help +" +```sh +Run the client -- `--entry-gateway-id`: paste one of the values labeled with a key `"identityKey"` (without `" "`) -- `--exit-gateway-id`: paste one of the values labeled with a key `"identityKey"` (without `" "`) -- `--exit-router-address`: paste one of the values labeled with a key `"address"` (without `" "`) -- `--enable-wireguard`: Enable the wireguard traffic between the client and the entry gateway. NymVPN uses Mullvad libraries for wrapping `wireguard-go` and to setup local routing rules to route all traffic to the TUN virtual network device -- `--wg-ip`: The address of the wireguard interface, you can get it [here](https://nymvpn.com/en/alpha) -- `--private-key`: get your private key for testing purposes [here](https://nymvpn.com/en/alpha) -- `--enable-two-hop` is a faster setup where the traffic is routed from the client to Entry Gateway and directly to Exit Gateway (default is 5-hops) +Usage: nym-vpn-cli run [OPTIONS] -**Advanced options** +Options: + --entry-gateway-id + Mixnet public ID of the entry gateway + --entry-gateway-country + Auto-select entry gateway by country ISO + --entry-gateway-low-latency + Auto-select entry gateway by latency + --exit-router-address + Mixnet recipient address + --exit-gateway-id + Mixnet public ID of the exit gateway + --exit-gateway-country + Auto-select exit gateway by country ISO + --wireguard-mode + Enable the wireguard mode + --nym-ipv4 + The IPv4 address of the nym TUN device that wraps IP packets in sphinx packets + --nym-ipv6 + The IPv6 address of the nym TUN device that wraps IP packets in sphinx packets + --nym-mtu + The MTU of the nym TUN device that wraps IP packets in sphinx packets + --dns + The DNS server to use + --disable-routing + Disable routing all traffic through the nym TUN device. When the flag is set, the nym TUN device will be created, but to route traffic through it you will need to do it manually, e.g. ping -Itun0 + --enable-two-hop + Enable two-hop mixnet traffic. This means that traffic jumps directly from entry gateway to exit gateway + --enable-poisson-rate + Enable Poisson process rate limiting of outbound traffic + --disable-background-cover-traffic + Disable constant rate background loop cover traffic + --enable-credentials-mode + Enable credentials mode + --min-mixnode-performance + Set the minimum performance level for mixnodes + -h, --help + Print help + +``` +~~~ -- `-c` is a path to an enviroment config, like [`sandbox.env`](https://raw.githubusercontent.com/nymtech/nym/develop/envs/sandbox.env) -- `--enable-poisson`: Enables process rate limiting of outbound traffic (disabled by default). It means that NymVPN client will send packets at a steady stream to the Entry Gateway. By default it's on average one sphinx packet per 20ms, but there is some randomness (poisson distribution). When there are no real data to fill the sphinx packets with, cover packets are generated instead. -- `--ip` is the IP address of the TUN device. That is the IP address of the local private network that is set up between local client and the Exit Gateway. -- `--mtu`: The MTU of the TUN device. That is the max IP packet size of the local private network that is set up between local client and the Exit Gateway. -- `--disable-routing`: Disable routing all traffic through the VPN TUN device. ## Testnet environment diff --git a/documentation/dev-portal/src/nymvpn/intro.md b/documentation/dev-portal/src/nymvpn/intro.md index cec127ae99..3b933597d5 100644 --- a/documentation/dev-portal/src/nymvpn/intro.md +++ b/documentation/dev-portal/src/nymvpn/intro.md @@ -2,6 +2,10 @@
+```admonish tip title="web3summit testing" +**If you testing NymVPN CLI on web3summit Berlin, visit our event page with all info tailored for the event: [nym-vpn-cli.sandbox.nymtech.net/](https://nym-vpn-cli.sandbox.nymtech.net/).** +``` + **NymVPN alpha** is a client that uses [Nym Mixnet](https://nymtech.net) to anonymise all of a user's internet traffic through either a 5-hop mixnet (for a full network privacy) or the faster 2-hop decentralised VPN (with some extra features). From f3ac17eb9d99944402af20a1295b0baeb3830829 Mon Sep 17 00:00:00 2001 From: import this <97586125+serinko@users.noreply.github.com> Date: Tue, 20 Aug 2024 14:41:29 +0000 Subject: [PATCH 18/93] [DOCs/developers]: syntax fix (#4770) * syntax-fix * syntax-fix --- documentation/dev-portal/src/nymvpn/cli.md | 5 ++--- documentation/dev-portal/src/nymvpn/intro.md | 2 +- 2 files changed, 3 insertions(+), 4 deletions(-) diff --git a/documentation/dev-portal/src/nymvpn/cli.md b/documentation/dev-portal/src/nymvpn/cli.md index 925472cdcd..ae74274cf3 100644 --- a/documentation/dev-portal/src/nymvpn/cli.md +++ b/documentation/dev-portal/src/nymvpn/cli.md @@ -1,7 +1,7 @@ # NymVPN CLI Guide ```admonish tip title="web3summit testing" -**If you testing NymVPN CLI on web3summit Berlin, visit our event page with all info tailored for the event: [nym-vpn-cli.sandbox.nymtech.net/](https://nym-vpn-cli.sandbox.nymtech.net/).** +**If you testing NymVPN CLI on Web3 Summit Berlin, visit our event page with all info tailored for the event: [nym-vpn-cli.sandbox.nymtech.net](https://nym-vpn-cli.sandbox.nymtech.net/).** ``` ```admonish info @@ -175,8 +175,7 @@ Options: You can also run any command with `--help` flag to see a list of all options associated witht that command, the most important may be `run` command, like in this example. -~~~admonish example collapsible=true title="nym-vpn-cli run --help -" +~~~admonish example collapsible=true title="nym-vpn-cli run --help" ```sh Run the client diff --git a/documentation/dev-portal/src/nymvpn/intro.md b/documentation/dev-portal/src/nymvpn/intro.md index 3b933597d5..02150ffe5a 100644 --- a/documentation/dev-portal/src/nymvpn/intro.md +++ b/documentation/dev-portal/src/nymvpn/intro.md @@ -3,7 +3,7 @@
```admonish tip title="web3summit testing" -**If you testing NymVPN CLI on web3summit Berlin, visit our event page with all info tailored for the event: [nym-vpn-cli.sandbox.nymtech.net/](https://nym-vpn-cli.sandbox.nymtech.net/).** +**If you testing NymVPN CLI on Web3 Summit Berlin, visit our event page with all info tailored for the event: [nym-vpn-cli.sandbox.nymtech.net](https://nym-vpn-cli.sandbox.nymtech.net/).** ``` **NymVPN alpha** is a client that uses [Nym Mixnet](https://nymtech.net) to anonymise all of a user's internet traffic through either a 5-hop mixnet (for a full network privacy) or the faster 2-hop decentralised VPN (with some extra features). From 7c1fca8ce48de5cb0ccacda7626dc3b9ed1c1dee Mon Sep 17 00:00:00 2001 From: =?UTF-8?q?Bogdan-=C8=98tefan=20Neac=C5=9Fu?= Date: Wed, 21 Aug 2024 11:26:14 +0200 Subject: [PATCH 19/93] Persist used wireguard private IPs (#4771) * Persist used wireguard private IPs * Fix imports * Remove unnecessary type specification --- common/gateway-storage/src/lib.rs | 2 +- common/wireguard/src/lib.rs | 3 ++- gateway/src/error.rs | 4 ++-- gateway/src/node/mod.rs | 22 ++++++++++++++++++- .../authenticator/src/authenticator.rs | 20 +++++++++++++++-- .../authenticator/src/cli/run.rs | 2 +- .../authenticator/src/mixnet_listener.rs | 4 +--- 7 files changed, 46 insertions(+), 11 deletions(-) diff --git a/common/gateway-storage/src/lib.rs b/common/gateway-storage/src/lib.rs index 7d3611fccf..a0a78fdb91 100644 --- a/common/gateway-storage/src/lib.rs +++ b/common/gateway-storage/src/lib.rs @@ -22,7 +22,7 @@ use tracing::{debug, error}; pub mod bandwidth; pub mod error; mod inboxes; -pub(crate) mod models; +pub mod models; mod shared_keys; mod tickets; #[cfg(feature = "wireguard")] diff --git a/common/wireguard/src/lib.rs b/common/wireguard/src/lib.rs index fa1c22b7cb..cf6ce7e857 100644 --- a/common/wireguard/src/lib.rs +++ b/common/wireguard/src/lib.rs @@ -84,6 +84,7 @@ pub struct WireguardData { #[cfg(target_os = "linux")] pub async fn start_wireguard( storage: St, + all_peers: Vec, task_client: nym_task::TaskClient, wireguard_data: WireguardData, control_tx: UnboundedSender, @@ -95,7 +96,7 @@ pub async fn start_wireguard( let mut peers = vec![]; let mut suspended_peers = vec![]; - for storage_peer in storage.get_all_wireguard_peers().await? { + for storage_peer in all_peers { let suspended = storage_peer.suspended; let peer = Peer::try_from(storage_peer)?; if suspended { diff --git a/gateway/src/error.rs b/gateway/src/error.rs index 8dc005a0a1..157f3f507e 100644 --- a/gateway/src/error.rs +++ b/gateway/src/error.rs @@ -204,8 +204,8 @@ pub enum GatewayError { WireguardInterfaceError(#[from] defguard_wireguard_rs::error::WireguardInterfaceError), #[cfg(all(feature = "wireguard", target_os = "linux"))] - #[error("wireguard not set")] - WireguardNotSet, + #[error("internal wireguard error {0}")] + InternalWireguardError(String), #[error("failed to start authenticator: {source}")] AuthenticatorStartError { diff --git a/gateway/src/node/mod.rs b/gateway/src/node/mod.rs index 5de29f806a..dc4ceec66f 100644 --- a/gateway/src/node/mod.rs +++ b/gateway/src/node/mod.rs @@ -267,12 +267,29 @@ impl Gateway { forwarding_channel, router_tx, ); + let all_peers = self.storage.get_all_wireguard_peers().await?; + let used_private_network_ips = all_peers + .iter() + .cloned() + .map(|wireguard_peer| { + defguard_wireguard_rs::host::Peer::try_from(wireguard_peer).map(|mut peer| { + peer.allowed_ips + .pop() + .ok_or(Box::new(GatewayError::InternalWireguardError(format!( + "no private IP set for peer {}", + peer.public_key + )))) + .map(|p| p.ip) + }) + }) + .collect::, _>, _>>()??; if let Some(wireguard_data) = self.wireguard_data.take() { let (on_start_tx, on_start_rx) = oneshot::channel(); let mut authenticator_server = nym_authenticator::Authenticator::new( opts.config.clone(), wireguard_data.inner.clone(), + used_private_network_ips, peer_response_rx, ) .with_custom_gateway_transceiver(Box::new(transceiver)) @@ -306,6 +323,7 @@ impl Gateway { let wg_api = nym_wireguard::start_wireguard( self.storage.clone(), + all_peers, shutdown, wireguard_data, peer_response_tx, @@ -317,7 +335,9 @@ impl Gateway { handle: LocalEmbeddedClientHandle::new(start_data.address, auth_mix_sender), }) } else { - Err(Box::new(GatewayError::WireguardNotSet)) + Err(Box::new(GatewayError::InternalWireguardError( + "wireguard not set".to_string(), + ))) } } diff --git a/service-providers/authenticator/src/authenticator.rs b/service-providers/authenticator/src/authenticator.rs index 04e77896a2..92de903913 100644 --- a/service-providers/authenticator/src/authenticator.rs +++ b/service-providers/authenticator/src/authenticator.rs @@ -1,7 +1,7 @@ // Copyright 2024 - Nym Technologies SA // SPDX-License-Identifier: Apache-2.0 -use std::path::Path; +use std::{net::IpAddr, path::Path, time::SystemTime}; use futures::channel::oneshot; use ipnetwork::IpNetwork; @@ -31,6 +31,7 @@ pub struct Authenticator { custom_topology_provider: Option>, custom_gateway_transceiver: Option>, wireguard_gateway_data: WireguardGatewayData, + used_private_network_ips: Vec, response_rx: UnboundedReceiver, shutdown: Option, on_start: Option>, @@ -40,6 +41,7 @@ impl Authenticator { pub fn new( config: Config, wireguard_gateway_data: WireguardGatewayData, + used_private_network_ips: Vec, response_rx: UnboundedReceiver, ) -> Self { Self { @@ -48,6 +50,7 @@ impl Authenticator { custom_topology_provider: None, custom_gateway_transceiver: None, wireguard_gateway_data, + used_private_network_ips, response_rx, shutdown: None, on_start: None, @@ -128,13 +131,26 @@ impl Authenticator { let self_address = *mixnet_client.nym_address(); + let used_private_network_ips = + std::collections::BTreeSet::from_iter(self.used_private_network_ips.iter()); let private_ip_network = IpNetwork::new( self.config.authenticator.private_ip, self.config.authenticator.private_network_prefix, )?; + let now = SystemTime::now(); + let free_private_network_ips = private_ip_network + .iter() + .map(|ip| { + if used_private_network_ips.contains(&ip) { + (ip, Some(now)) + } else { + (ip, None) + } + }) + .collect(); let mixnet_listener = crate::mixnet_listener::MixnetListener::new( self.config, - private_ip_network, + free_private_network_ips, self.wireguard_gateway_data, self.response_rx, mixnet_client, diff --git a/service-providers/authenticator/src/cli/run.rs b/service-providers/authenticator/src/cli/run.rs index 0abaa4b3cd..4844cd1284 100644 --- a/service-providers/authenticator/src/cli/run.rs +++ b/service-providers/authenticator/src/cli/run.rs @@ -55,7 +55,7 @@ pub(crate) async fn execute(args: &Run) -> Result<(), AuthenticatorError> { handler.run().await; }); let mut server = - nym_authenticator::Authenticator::new(config, wireguard_gateway_data, response_rx); + nym_authenticator::Authenticator::new(config, wireguard_gateway_data, vec![], response_rx); if let Some(custom_mixnet) = &args.common_args.custom_mixnet { server = server.with_stored_topology(custom_mixnet)? } diff --git a/service-providers/authenticator/src/mixnet_listener.rs b/service-providers/authenticator/src/mixnet_listener.rs index df888113b7..2bb32181db 100644 --- a/service-providers/authenticator/src/mixnet_listener.rs +++ b/service-providers/authenticator/src/mixnet_listener.rs @@ -8,7 +8,6 @@ use std::{ use crate::{error::AuthenticatorError, peer_manager::PeerManager}; use futures::StreamExt; -use ipnetwork::IpNetwork; use nym_authenticator_requests::v1::{ self, request::{AuthenticatorRequest, AuthenticatorRequestData}, @@ -67,7 +66,7 @@ pub(crate) struct MixnetListener { impl MixnetListener { pub fn new( config: Config, - private_ip_network: IpNetwork, + free_private_network_ips: PrivateIPs, wireguard_gateway_data: WireguardGatewayData, response_rx: UnboundedReceiver, mixnet_client: nym_sdk::mixnet::MixnetClient, @@ -75,7 +74,6 @@ impl MixnetListener { ) -> Self { let timeout_check_interval = IntervalStream::new(tokio::time::interval(DEFAULT_REGISTRATION_TIMEOUT_CHECK)); - let free_private_network_ips = private_ip_network.iter().map(|ip| (ip, None)).collect(); MixnetListener { config, mixnet_client, From 1ac262ec9080880be29440f11ba07602adbb89e6 Mon Sep 17 00:00:00 2001 From: Drazen Urch Date: Thu, 22 Aug 2024 10:29:36 +0100 Subject: [PATCH 20/93] New Network Monitor (#4610) * Initial commit * Cherry pick from develop * Keep track of fragments * A bunch of data formats, graphs * Use mix_id for display * Proper API routes * Add openapi + swagger ui * Update locustfile * Add node stats endpoint * Add Swagger and locust to readme * All node stats endpoint * Update dependencies to use workspace * Bunch of pedantic fixes * More version updates, fmt * More lints * Add new_from_env for NymTopology * Nym API endpoint to submit monitoring results (#4616) * Nym API endpoint to submit monitoring results * Add gateway monitoring results * Cleanup, ergonomics * Weaponize * Finalize results submissions * Monitor message signing and verification * Update README * Axum graceful shutdown * More grtacefulness * Restructure result submission * Less fragile routes * Remove gateway unique index on node_id --- .dockerignore | 7 + .gitignore | 5 +- Cargo.lock | 58 +++ Cargo.toml | 3 +- common/client-core/Cargo.toml | 1 + .../src/client/packet_statistics_control.rs | 4 +- .../real_messages_control/message_handler.rs | 1 + .../client-libs/validator-client/Cargo.toml | 4 +- .../validator-client/src/nym_api/routes.rs | 2 + .../src/nyxd/cosmwasm_client/mod.rs | 4 +- .../validator-client/src/nyxd/mod.rs | 4 +- .../validator-client/src/rpc/mod.rs | 8 +- common/node-tester-utils/Cargo.toml | 3 +- common/node-tester-utils/src/tester.rs | 4 + common/nymsphinx/Cargo.toml | 18 +- common/nymsphinx/chunking/Cargo.toml | 7 + common/nymsphinx/chunking/src/fragment.rs | 34 +- common/nymsphinx/chunking/src/lib.rs | 119 ++++++ .../nymsphinx/chunking/src/reconstruction.rs | 10 +- common/nymsphinx/src/preparer/mod.rs | 28 +- .../src/proxy_runner/outbound.rs | 2 +- common/topology/Cargo.toml | 19 +- common/topology/src/error.rs | 12 + common/topology/src/lib.rs | 58 ++- common/types/Cargo.toml | 2 +- common/types/src/lib.rs | 1 + common/types/src/monitoring.rs | 131 ++++++ common/wasm/utils/Cargo.toml | 8 +- envs/mainnet-local-api.env | 27 ++ nym-api/Cargo.toml | 18 +- .../20240524101449_monitor_v2_tables.sql | 31 ++ .../20240819170000_monitor_v2_tables_v2.sql | 19 + ...on_unique_gateway_idx_until_we_migrate.sql | 10 + nym-api/src/epoch_operations/mod.rs | 1 + .../monitor/summary_producer.rs | 38 +- nym-api/src/node_status_api/mod.rs | 2 + nym-api/src/node_status_api/routes.rs | 87 ++++ nym-api/src/support/storage/manager.rs | 89 +++- nym-api/src/support/storage/mod.rs | 2 +- nym-network-monitor.dockerfile | 14 + nym-network-monitor/Cargo.toml | 39 ++ nym-network-monitor/README.md | 47 +++ nym-network-monitor/entrypoint.sh | 21 + nym-network-monitor/locustfile.py | 7 + nym-network-monitor/src/accounting.rs | 382 ++++++++++++++++++ nym-network-monitor/src/handlers.rs | 295 ++++++++++++++ nym-network-monitor/src/http.rs | 94 +++++ nym-network-monitor/src/main.rs | 214 ++++++++++ sdk/rust/nym-sdk/src/mixnet/client.rs | 9 +- tools/nymvisor/src/tasks/launcher/mod.rs | 2 +- 50 files changed, 1913 insertions(+), 92 deletions(-) create mode 100644 .dockerignore create mode 100644 common/types/src/monitoring.rs create mode 100644 envs/mainnet-local-api.env create mode 100644 nym-api/migrations/20240524101449_monitor_v2_tables.sql create mode 100644 nym-api/migrations/20240819170000_monitor_v2_tables_v2.sql create mode 100644 nym-api/migrations/20240822110000_non_unique_gateway_idx_until_we_migrate.sql create mode 100644 nym-network-monitor.dockerfile create mode 100644 nym-network-monitor/Cargo.toml create mode 100644 nym-network-monitor/README.md create mode 100755 nym-network-monitor/entrypoint.sh create mode 100644 nym-network-monitor/locustfile.py create mode 100644 nym-network-monitor/src/accounting.rs create mode 100644 nym-network-monitor/src/handlers.rs create mode 100644 nym-network-monitor/src/http.rs create mode 100644 nym-network-monitor/src/main.rs diff --git a/.dockerignore b/.dockerignore new file mode 100644 index 0000000000..09ed129139 --- /dev/null +++ b/.dockerignore @@ -0,0 +1,7 @@ +.git +.github +.gitignore +**/node_modules +**/target +dist +documentation diff --git a/.gitignore b/.gitignore index 4dfbe52586..597794c0e3 100644 --- a/.gitignore +++ b/.gitignore @@ -48,4 +48,7 @@ foxyfox.env .next ppa-private-key.b64 -ppa-private-key.asc \ No newline at end of file +ppa-private-key.asc +nym-network-monitor/topology.json +nym-network-monitor/__pycache__ +nym-network-monitor/*.key \ No newline at end of file diff --git a/Cargo.lock b/Cargo.lock index 2544f70511..bd601c4412 100644 --- a/Cargo.lock +++ b/Cargo.lock @@ -1858,6 +1858,7 @@ dependencies = [ "lock_api", "once_cell", "parking_lot_core 0.9.10", + "serde", ] [[package]] @@ -2397,6 +2398,12 @@ dependencies = [ "windows-sys 0.52.0", ] +[[package]] +name = "fixedbitset" +version = "0.4.2" +source = "registry+https://github.com/rust-lang/crates.io-index" +checksum = "0ce7134b9999ecaf8bcd65542e436736ef32ddca1b3e06094cb6ec5755203b80" + [[package]] name = "flate2" version = "1.0.30" @@ -4253,6 +4260,7 @@ dependencies = [ "nym-sphinx", "nym-task", "nym-topology", + "nym-types", "nym-validator-client", "nym-vesting-contract-common", "okapi", @@ -4579,6 +4587,7 @@ dependencies = [ "nym-topology", "nym-validator-client", "rand 0.8.5", + "rand_chacha 0.3.1", "serde", "serde_json", "sha2 0.10.8", @@ -5410,6 +5419,36 @@ dependencies = [ "url", ] +[[package]] +name = "nym-network-monitor" +version = "0.1.0" +dependencies = [ + "anyhow", + "axum 0.7.5", + "clap 4.5.7", + "dashmap", + "futures", + "log", + "nym-bin-common", + "nym-crypto", + "nym-network-defaults", + "nym-sdk", + "nym-sphinx", + "nym-topology", + "nym-types", + "nym-validator-client", + "petgraph", + "rand 0.8.5", + "rand_chacha 0.3.1", + "reqwest 0.12.4", + "serde", + "serde_json", + "tokio", + "tokio-util", + "utoipa", + "utoipa-swagger-ui", +] + [[package]] name = "nym-network-requester" version = "1.1.40" @@ -5575,6 +5614,7 @@ dependencies = [ "nym-task", "nym-topology", "rand 0.8.5", + "rand_chacha 0.3.1", "serde", "serde_json", "thiserror", @@ -5858,6 +5898,7 @@ version = "0.1.0" dependencies = [ "log", "nym-crypto", + "nym-metrics", "nym-mixnet-contract-common", "nym-sphinx-acknowledgements", "nym-sphinx-addressing", @@ -5871,6 +5912,7 @@ dependencies = [ "nym-sphinx-types", "nym-topology", "rand 0.8.5", + "rand_chacha 0.3.1", "rand_distr", "thiserror", "tokio", @@ -5927,12 +5969,17 @@ dependencies = [ name = "nym-sphinx-chunking" version = "0.1.0" dependencies = [ + "dashmap", "log", + "nym-crypto", + "nym-metrics", "nym-sphinx-addressing", "nym-sphinx-params", "nym-sphinx-types", "rand 0.8.5", + "serde", "thiserror", + "utoipa", ] [[package]] @@ -6046,6 +6093,7 @@ dependencies = [ "nym-sphinx-routing", "nym-sphinx-types", "rand 0.8.5", + "reqwest 0.12.4", "semver 0.11.0", "serde", "serde_json", @@ -6682,6 +6730,16 @@ dependencies = [ "sha2 0.10.8", ] +[[package]] +name = "petgraph" +version = "0.6.5" +source = "registry+https://github.com/rust-lang/crates.io-index" +checksum = "b4c5cc86750666a3ed20bdaf5ca2a0344f9c67674cae0515bec2da16fbaa47db" +dependencies = [ + "fixedbitset", + "indexmap 2.2.6", +] + [[package]] name = "pin-project" version = "1.1.5" diff --git a/Cargo.toml b/Cargo.toml index 237f005d32..f100358f0d 100644 --- a/Cargo.toml +++ b/Cargo.toml @@ -14,7 +14,6 @@ panic = "abort" opt-level = 3 [workspace] - resolver = "2" members = [ "clients/native", @@ -106,6 +105,7 @@ members = [ "service-providers/common", "service-providers/ip-packet-router", "service-providers/network-requester", + "nym-network-monitor", "nym-api", "nym-browser-extension/storage", "nym-api/nym-api-requests", @@ -159,6 +159,7 @@ homepage = "https://nymtech.net" documentation = "https://nymtech.net" edition = "2021" license = "Apache-2.0" +rust-version = "1.80" [workspace.dependencies] addr = "0.15.6" diff --git a/common/client-core/Cargo.toml b/common/client-core/Cargo.toml index 763f0d8967..e23698259e 100644 --- a/common/client-core/Cargo.toml +++ b/common/client-core/Cargo.toml @@ -19,6 +19,7 @@ futures = { workspace = true } humantime-serde = { workspace = true } log = { workspace = true } rand = { workspace = true } +rand_chacha = { workspace = true } serde = { workspace = true, features = ["derive"] } serde_json = { workspace = true } sha2 = { workspace = true } diff --git a/common/client-core/src/client/packet_statistics_control.rs b/common/client-core/src/client/packet_statistics_control.rs index 499d5de092..60f0d36e6e 100644 --- a/common/client-core/src/client/packet_statistics_control.rs +++ b/common/client-core/src/client/packet_statistics_control.rs @@ -458,7 +458,7 @@ impl PacketStatisticsControl { fn report_rates(&self) { if let Some((_, rates)) = self.rates.back() { - log::info!("{}", rates.summary()); + log::debug!("{}", rates.summary()); log::debug!("{}", rates.detailed_summary()); } } @@ -486,7 +486,7 @@ impl PacketStatisticsControl { // Check what the number of retransmissions was during the recording window if let Some((_, start_stats)) = self.history.front() { let delta = self.stats.clone() - start_stats.clone(); - log::info!( + log::debug!( "mix packet retransmissions/real mix packets: {}/{}", delta.retransmissions_queued, delta.real_packets_queued, diff --git a/common/client-core/src/client/real_messages_control/message_handler.rs b/common/client-core/src/client/real_messages_control/message_handler.rs index 42a1993844..8262e5b996 100644 --- a/common/client-core/src/client/real_messages_control/message_handler.rs +++ b/common/client-core/src/client/real_messages_control/message_handler.rs @@ -453,6 +453,7 @@ where let mut pending_acks = Vec::with_capacity(fragments.len()); let mut real_messages = Vec::with_capacity(fragments.len()); + debug!("Splitting message into {} fragments", fragments.len()); for fragment in fragments { // we need to clone it because we need to keep it in memory in case we had to retransmit // it. And then we'd need to recreate entire ACK again. diff --git a/common/client-libs/validator-client/Cargo.toml b/common/client-libs/validator-client/Cargo.toml index a9a348a28e..2bf66895c0 100644 --- a/common/client-libs/validator-client/Cargo.toml +++ b/common/client-libs/validator-client/Cargo.toml @@ -90,4 +90,6 @@ default = ["http-client"] http-client = ["cosmrs/rpc"] generate-ts = [] contract-testing = ["nym-mixnet-contract-common/contract-testing"] - +# Features below are added to make clippy happy, it seems like they're unused we should remove them +tendermint-rpc-http-client = ["tendermint-rpc/http-client"] +tendermint-rpc-websocket-client = ["tendermint-rpc/websocket-client"] diff --git a/common/client-libs/validator-client/src/nym_api/routes.rs b/common/client-libs/validator-client/src/nym_api/routes.rs index c6a50db513..b77d6438b5 100644 --- a/common/client-libs/validator-client/src/nym_api/routes.rs +++ b/common/client-libs/validator-client/src/nym_api/routes.rs @@ -49,5 +49,7 @@ pub const COMPUTE_REWARD_ESTIMATION: &str = "compute-reward-estimation"; pub const AVG_UPTIME: &str = "avg_uptime"; pub const STAKE_SATURATION: &str = "stake-saturation"; pub const INCLUSION_CHANCE: &str = "inclusion-probability"; +pub const SUBMIT_GATEWAY: &str = "submit-gateway-monitoring-results"; +pub const SUBMIT_NODE: &str = "submit-node-monitoring-results"; pub const SERVICE_PROVIDERS: &str = "services"; diff --git a/common/client-libs/validator-client/src/nyxd/cosmwasm_client/mod.rs b/common/client-libs/validator-client/src/nyxd/cosmwasm_client/mod.rs index 3ededcb929..af33e8795c 100644 --- a/common/client-libs/validator-client/src/nyxd/cosmwasm_client/mod.rs +++ b/common/client-libs/validator-client/src/nyxd/cosmwasm_client/mod.rs @@ -300,8 +300,8 @@ where } #[cfg(any( - feature = "tendermint-rpc/http-client", - feature = "tendermint-rpc/websocket-client" + feature = "tendermint-rpc-http-client", + feature = "tendermint-rpc-websocket-client" ))] async fn wait_until_healthy(&self, timeout: T) -> Result<(), Error> where diff --git a/common/client-libs/validator-client/src/nyxd/mod.rs b/common/client-libs/validator-client/src/nyxd/mod.rs index fd3e40c379..60fc03fb38 100644 --- a/common/client-libs/validator-client/src/nyxd/mod.rs +++ b/common/client-libs/validator-client/src/nyxd/mod.rs @@ -820,8 +820,8 @@ where } #[cfg(any( - feature = "tendermint-rpc/http-client", - feature = "tendermint-rpc/websocket-client" + feature = "tendermint-rpc-http-client", + feature = "tendermint-rpc-websocket-client" ))] async fn wait_until_healthy(&self, timeout: T) -> Result<(), Error> where diff --git a/common/client-libs/validator-client/src/rpc/mod.rs b/common/client-libs/validator-client/src/rpc/mod.rs index bbab0cbc38..8db7575606 100644 --- a/common/client-libs/validator-client/src/rpc/mod.rs +++ b/common/client-libs/validator-client/src/rpc/mod.rs @@ -300,8 +300,8 @@ pub trait TendermintRpcClient { } #[cfg(any( - feature = "tendermint-rpc/http-client", - feature = "tendermint-rpc/websocket-client" + feature = "tendermint-rpc-http-client", + feature = "tendermint-rpc-websocket-client" ))] /// Poll the `/health` endpoint until it returns a successful result or /// the given `timeout` has elapsed. @@ -518,8 +518,8 @@ mod non_wasm { } #[cfg(any( - feature = "tendermint-rpc/http-client", - feature = "tendermint-rpc/websocket-client" + feature = "tendermint-rpc-http-client", + feature = "tendermint-rpc-websocket-client" ))] async fn wait_until_healthy(&self, timeout: T) -> Result<(), Error> where diff --git a/common/node-tester-utils/Cargo.toml b/common/node-tester-utils/Cargo.toml index cdb2ddb994..89e4043ad3 100644 --- a/common/node-tester-utils/Cargo.toml +++ b/common/node-tester-utils/Cargo.toml @@ -9,11 +9,12 @@ license.workspace = true [dependencies] futures = { workspace = true } rand = { workspace = true } +rand_chacha = { workspace = true } serde = { workspace = true } serde_json = { workspace = true } thiserror = { workspace = true } -tokio = { workspace = true, features = ["macros"]} +tokio = { workspace = true, features = ["macros"] } nym-crypto = { path = "../crypto", features = ["asymmetric"] } nym-task = { path = "../task" } diff --git a/common/node-tester-utils/src/tester.rs b/common/node-tester-utils/src/tester.rs index dd88e1469d..e31d632cc7 100644 --- a/common/node-tester-utils/src/tester.rs +++ b/common/node-tester-utils/src/tester.rs @@ -294,4 +294,8 @@ impl FragmentPreparer for NodeTester { fn average_ack_delay(&self) -> Duration { self.average_ack_delay } + + fn nonce(&self) -> i32 { + 1 + } } diff --git a/common/nymsphinx/Cargo.toml b/common/nymsphinx/Cargo.toml index 40769d2ec6..d377a8bdec 100644 --- a/common/nymsphinx/Cargo.toml +++ b/common/nymsphinx/Cargo.toml @@ -11,6 +11,7 @@ repository = { workspace = true } log = { workspace = true } rand = { workspace = true } rand_distr = { workspace = true } +rand_chacha = { workspace = true } thiserror = { workspace = true } nym-sphinx-acknowledgements = { path = "acknowledgements" } @@ -27,10 +28,13 @@ nym-sphinx-types = { path = "types" } # to separate crate? nym-crypto = { path = "../crypto", version = "0.4.0" } nym-topology = { path = "../topology" } +nym-metrics = { path = "../nym-metrics" } [dev-dependencies] nym-mixnet-contract-common = { path = "../cosmwasm-smart-contracts/mixnet-contract" } -nym-crypto = { path = "../crypto", version = "0.4.0", features = ["asymmetric"] } +nym-crypto = { path = "../crypto", version = "0.4.0", features = [ + "asymmetric", +] } # do not include this when compiling into wasm as it somehow when combined together with reqwest, it will require # net2 via tokio-util -> tokio -> mio -> net2 @@ -43,5 +47,13 @@ features = ["sync"] [features] default = ["sphinx"] -sphinx = ["nym-crypto/sphinx", "nym-sphinx-params/sphinx", "nym-sphinx-types/sphinx"] -outfox = ["nym-crypto/outfox", "nym-sphinx-params/outfox", "nym-sphinx-types/outfox"] +sphinx = [ + "nym-crypto/sphinx", + "nym-sphinx-params/sphinx", + "nym-sphinx-types/sphinx", +] +outfox = [ + "nym-crypto/outfox", + "nym-sphinx-params/outfox", + "nym-sphinx-types/outfox", +] diff --git a/common/nymsphinx/chunking/Cargo.toml b/common/nymsphinx/chunking/Cargo.toml index dc608a9718..6988d8ac81 100644 --- a/common/nymsphinx/chunking/Cargo.toml +++ b/common/nymsphinx/chunking/Cargo.toml @@ -13,7 +13,14 @@ repository = { workspace = true } log = { workspace = true } rand = { workspace = true } thiserror = { workspace = true } +dashmap = { workspace = true, features = ["serde"] } +serde = { workspace = true, features = ["derive"] } +utoipa = { workspace = true } nym-sphinx-addressing = { path = "../addressing" } nym-sphinx-params = { path = "../params" } nym-sphinx-types = { path = "../types" } +nym-metrics = { path = "../../nym-metrics" } +nym-crypto = { path = "../../crypto", version = "0.4.0", features = [ + "asymmetric", +] } diff --git a/common/nymsphinx/chunking/src/fragment.rs b/common/nymsphinx/chunking/src/fragment.rs index 73bce8344c..504cfa9ba0 100644 --- a/common/nymsphinx/chunking/src/fragment.rs +++ b/common/nymsphinx/chunking/src/fragment.rs @@ -3,6 +3,8 @@ use crate::ChunkingError; use nym_sphinx_params::{SerializedFragmentIdentifier, FRAG_ID_LEN}; +use serde::Serialize; +use utoipa::ToSchema; use std::fmt::{self, Debug, Formatter}; @@ -58,7 +60,7 @@ pub const COVER_FRAG_ID: FragmentIdentifier = FragmentIdentifier { /// and u8 position of the `Fragment` in the set. // TODO: this should really be redesigned, especially how cover and reply messages are really // "abusing" this. They should work with it natively instead. -#[derive(Debug, Clone, Copy, Hash, Eq, PartialEq, Ord, PartialOrd)] +#[derive(Debug, Clone, Copy, Hash, Eq, PartialEq, Ord, PartialOrd, Serialize)] pub struct FragmentIdentifier { set_id: i32, fragment_position: u8, @@ -75,6 +77,10 @@ impl fmt::Display for FragmentIdentifier { } impl FragmentIdentifier { + pub fn set_id(&self) -> i32 { + self.set_id + } + pub fn to_bytes(self) -> SerializedFragmentIdentifier { debug_assert_eq!(FRAG_ID_LEN, 5); @@ -125,6 +131,10 @@ impl Debug for Fragment { } impl Fragment { + pub fn header(&self) -> FragmentHeader { + self.header.clone() + } + /// Tries to encapsulate provided payload slice and metadata into a `Fragment`. /// It can fail if payload would not fully fit in a single `Fragment` or some of the metadata /// is malformed or self-contradictory, for example if current_fragment > total_fragments. @@ -216,6 +226,10 @@ impl Fragment { } } + pub fn seed(&self) -> i32 { + self.header().seed() + } + /// Gets the size of payload contained in this `Fragment`. pub fn payload_size(&self) -> usize { self.payload.len() @@ -297,8 +311,8 @@ impl Fragment { /// there is 7 bytes of overhead inside each sphinx packet sent /// and for the longest messages, without upper bound, there is usually also only 7 bytes /// of overhead apart from first and last fragments in each set that instead have 10 bytes of overhead. -#[derive(PartialEq, Clone, Debug)] -pub(crate) struct FragmentHeader { +#[derive(PartialEq, Clone, Debug, Serialize, ToSchema)] +pub struct FragmentHeader { /// ID associated with `FragmentSet` to which this particular `Fragment` belongs. /// Its value is restricted to (0, i32::MAX]. /// Note that it *excludes* 0, but *includes* i32::MAX. @@ -324,6 +338,20 @@ pub(crate) struct FragmentHeader { } impl FragmentHeader { + pub fn seed(&self) -> i32 { + let mut seed = self.id; + seed = seed.wrapping_mul(self.total_fragments as i32); + seed = seed.wrapping_mul(self.current_fragment as i32); + seed + } + + pub fn total_fragments(&self) -> u8 { + self.total_fragments + } + + pub fn current_fragment(&self) -> u8 { + self.current_fragment + } /// Tries to create a new `FragmentHeader` using provided metadata. Bunch of logical /// checks are performed to see if the data is not self-contradictory, /// for example if current_fragment > total_fragments. diff --git a/common/nymsphinx/chunking/src/lib.rs b/common/nymsphinx/chunking/src/lib.rs index 03ddd3541f..8f26757099 100644 --- a/common/nymsphinx/chunking/src/lib.rs +++ b/common/nymsphinx/chunking/src/lib.rs @@ -1,9 +1,16 @@ // Copyright 2021 - Nym Technologies SA // SPDX-License-Identifier: Apache-2.0 +use std::sync::LazyLock; + use crate::fragment::{linked_fragment_payload_max_len, unlinked_fragment_payload_max_len}; +use dashmap::DashMap; +use fragment::{Fragment, FragmentHeader}; +use nym_crypto::asymmetric::ed25519::PublicKey; +use serde::Serialize; pub use set::split_into_sets; use thiserror::Error; +use utoipa::ToSchema; pub const MIN_PADDING_OVERHEAD: usize = 1; @@ -22,6 +29,118 @@ pub mod fragment; pub mod reconstruction; pub mod set; +#[derive(Debug, Clone)] +pub struct FragmentMixParams { + destination: PublicKey, + hops: u8, +} + +impl FragmentMixParams { + pub fn destination(&self) -> &PublicKey { + &self.destination + } + + pub fn hops(&self) -> u8 { + self.hops + } +} + +#[derive(Debug, Clone, Serialize, ToSchema)] +pub struct SentFragment { + header: FragmentHeader, + at: u64, + client_nonce: i32, + #[serde(skip)] + mixnet_params: FragmentMixParams, +} + +impl SentFragment { + fn new( + header: FragmentHeader, + at: u64, + client_nonce: i32, + destination: PublicKey, + hops: u8, + ) -> Self { + let mixnet_params = FragmentMixParams { destination, hops }; + SentFragment { + header, + at, + client_nonce, + mixnet_params, + } + } + + pub fn header(&self) -> FragmentHeader { + self.header.clone() + } + + pub fn at(&self) -> u64 { + self.at + } + + pub fn client_nonce(&self) -> i32 { + self.client_nonce + } + + pub fn seed(&self) -> i32 { + self.header().seed().wrapping_mul(self.client_nonce()) + } + + pub fn mixnet_params(&self) -> FragmentMixParams { + self.mixnet_params.clone() + } +} + +#[derive(Debug, Clone, Serialize, ToSchema)] +pub struct ReceivedFragment { + header: FragmentHeader, + at: u64, +} + +impl ReceivedFragment { + fn new(header: FragmentHeader, at: u64) -> Self { + ReceivedFragment { header, at } + } + + pub fn header(&self) -> FragmentHeader { + self.header.clone() + } + + pub fn at(&self) -> u64 { + self.at + } +} + +pub static FRAGMENTS_RECEIVED: LazyLock>> = + LazyLock::new(DashMap::new); + +pub static FRAGMENTS_SENT: LazyLock>> = LazyLock::new(DashMap::new); + +#[macro_export] +macro_rules! now { + () => { + match std::time::SystemTime::now().duration_since(std::time::SystemTime::UNIX_EPOCH) { + Ok(n) => n.as_secs(), + Err(_) => 0, + } + }; +} + +pub fn fragment_received(fragment: &Fragment) { + let id = fragment.fragment_identifier().set_id(); + let mut entry = FRAGMENTS_RECEIVED.entry(id).or_default(); + let r = ReceivedFragment::new(fragment.header(), now!()); + entry.push(r); +} + +pub fn fragment_sent(fragment: &Fragment, client_nonce: i32, destination: PublicKey, hops: u8) { + let id = fragment.fragment_identifier().set_id(); + let mut entry = FRAGMENTS_SENT.entry(id).or_default(); + let s = SentFragment::new(fragment.header(), now!(), client_nonce, destination, hops); + entry.push(s); +} + /// The idea behind the process of chunking is to incur as little data overhead as possible due /// to very computationally costly sphinx encapsulation procedure. /// diff --git a/common/nymsphinx/chunking/src/reconstruction.rs b/common/nymsphinx/chunking/src/reconstruction.rs index e87495f2d2..13383b24ee 100644 --- a/common/nymsphinx/chunking/src/reconstruction.rs +++ b/common/nymsphinx/chunking/src/reconstruction.rs @@ -1,7 +1,7 @@ // Copyright 2021 - Nym Technologies SA // SPDX-License-Identifier: Apache-2.0 use crate::fragment::Fragment; -use crate::ChunkingError; +use crate::{fragment_received, ChunkingError}; use log::*; use std::collections::HashMap; @@ -66,6 +66,12 @@ impl ReconstructionBuffer { // if the set is complete. debug_assert!(self.is_complete); + debug!( + "Got {} fragments for set id {}", + self.fragments.len(), + self.fragments[0].as_ref().unwrap().id() + ); + self.fragments .into_iter() .map(|fragment| fragment.unwrap().extract_payload()) @@ -104,6 +110,8 @@ impl ReconstructionBuffer { } }); + fragment_received(&fragment); + let fragment_index = fragment.current_fragment() as usize - 1; if self.fragments[fragment_index].is_some() { // TODO: what to do in that case? give up on the message? overwrite it? panic? diff --git a/common/nymsphinx/src/preparer/mod.rs b/common/nymsphinx/src/preparer/mod.rs index b116cdadf9..7cdddd53a1 100644 --- a/common/nymsphinx/src/preparer/mod.rs +++ b/common/nymsphinx/src/preparer/mod.rs @@ -3,6 +3,7 @@ use crate::message::{NymMessage, ACK_OVERHEAD, OUTFOX_ACK_OVERHEAD}; use crate::NymPayloadBuilder; +use log::debug; use nym_crypto::asymmetric::encryption; use nym_crypto::Digest; use nym_sphinx_acknowledgements::surb_ack::SurbAck; @@ -11,12 +12,14 @@ use nym_sphinx_addressing::clients::Recipient; use nym_sphinx_addressing::nodes::NymNodeRoutingAddress; use nym_sphinx_anonymous_replies::reply_surb::ReplySurb; use nym_sphinx_chunking::fragment::{Fragment, FragmentIdentifier}; +use nym_sphinx_chunking::fragment_sent; use nym_sphinx_forwarding::packet::MixPacket; use nym_sphinx_params::packet_sizes::PacketSize; use nym_sphinx_params::{PacketType, ReplySurbKeyDigestAlgorithm, DEFAULT_NUM_MIX_HOPS}; use nym_sphinx_types::{Delay, NymPacket}; use nym_topology::{NymTopology, NymTopologyError}; -use rand::{CryptoRng, Rng}; +use rand::{CryptoRng, Rng, SeedableRng}; +use rand_chacha::ChaCha20Rng; use std::time::Duration; @@ -49,6 +52,7 @@ pub trait FragmentPreparer { type Rng: CryptoRng + Rng; fn rng(&mut self) -> &mut Self::Rng; + fn nonce(&self) -> i32; fn num_mix_hops(&self) -> u8; fn average_packet_delay(&self) -> Duration; fn average_ack_delay(&self) -> Duration; @@ -192,9 +196,18 @@ pub trait FragmentPreparer { packet_type: PacketType, mix_hops: Option, ) -> Result { + debug!("Preparing chunk for sending"); // each plain or repliable packet (i.e. not a reply) attaches an ephemeral public key so that the recipient // could perform diffie-hellman with its own keys followed by a kdf to re-derive // the packet encryption key + + let seed = fragment.seed().wrapping_mul(self.nonce()); + let mut rng = ChaCha20Rng::seed_from_u64(seed as u64); + + let destination = packet_recipient.gateway(); + let hops = mix_hops.unwrap_or(self.num_mix_hops()); + fragment_sent(&fragment, self.nonce(), *destination, hops); + let non_reply_overhead = encryption::PUBLIC_KEY_SIZE; let expected_plaintext = match packet_type { PacketType::Outfox => { @@ -228,10 +241,8 @@ pub trait FragmentPreparer { }; // generate pseudorandom route for the packet - let hops = mix_hops.unwrap_or(self.num_mix_hops()); log::trace!("Preparing chunk for sending with {} mix hops", hops); - let route = - topology.random_route_to_gateway(self.rng(), hops, packet_recipient.gateway())?; + let route = topology.random_route_to_gateway(&mut rng, hops, destination)?; let destination = packet_recipient.as_sphinx_destination(); // including set of delays @@ -313,6 +324,8 @@ pub struct MessagePreparer { /// Number of mix hops each packet ('real' message, ack, reply) is expected to take. /// Note that it does not include gateway hops. num_mix_hops: u8, + + nonce: i32, } impl MessagePreparer @@ -325,12 +338,15 @@ where average_packet_delay: Duration, average_ack_delay: Duration, ) -> Self { + let mut rng = rng; + let nonce = rng.gen(); MessagePreparer { rng, sender_address, average_packet_delay, average_ack_delay, num_mix_hops: DEFAULT_NUM_MIX_HOPS, + nonce, } } @@ -454,6 +470,10 @@ impl FragmentPreparer for MessagePreparer { fn average_ack_delay(&self) -> Duration { self.average_ack_delay } + + fn nonce(&self) -> i32 { + self.nonce + } } /* diff --git a/common/socks5/proxy-helpers/src/proxy_runner/outbound.rs b/common/socks5/proxy-helpers/src/proxy_runner/outbound.rs index 77f5ae2b59..63d49fb311 100644 --- a/common/socks5/proxy-helpers/src/proxy_runner/outbound.rs +++ b/common/socks5/proxy-helpers/src/proxy_runner/outbound.rs @@ -60,7 +60,7 @@ pub(super) async fn run_outbound( loop { select! { - connection_message = &mut mix_receiver.next() => { + connection_message = mix_receiver.next() => { if let Some(connection_message) = connection_message { if deal_with_message(connection_message, &mut writer, &local_destination_address, &remote_source_address, connection_id).await { break; diff --git a/common/topology/Cargo.toml b/common/topology/Cargo.toml index 471a8621a4..52eeaa55cc 100644 --- a/common/topology/Cargo.toml +++ b/common/topology/Cargo.toml @@ -5,7 +5,6 @@ edition = { workspace = true } authors = { workspace = true } license = { workspace = true } repository = { workspace = true } -readme = { workspace = true } homepage = { workspace = true } documentation = { workspace = true } @@ -15,9 +14,10 @@ documentation = { workspace = true } bs58 = { workspace = true } log = { workspace = true } rand = { workspace = true } +reqwest = { workspace = true, features = ["json"] } thiserror = { workspace = true } async-trait = { workspace = true, optional = true } -semver = "0.11" +semver = { version = "0.11" } # 'serializable' feature serde = { workspace = true, features = ["derive"], optional = true } @@ -28,20 +28,22 @@ tsify = { workspace = true, features = ["js"], optional = true } wasm-bindgen = { workspace = true, optional = true } ## internal +nym-bin-common = { path = "../bin-common" } +nym-config = { path = "../config" } nym-crypto = { path = "../crypto", features = ["sphinx", "outfox"] } nym-mixnet-contract-common = { path = "../cosmwasm-smart-contracts/mixnet-contract" } nym-sphinx-addressing = { path = "../nymsphinx/addressing" } -nym-sphinx-types = { path = "../nymsphinx/types", features = ["sphinx", "outfox"] } +nym-sphinx-types = { path = "../nymsphinx/types", features = [ + "sphinx", + "outfox", +] } nym-sphinx-routing = { path = "../nymsphinx/routing" } -nym-bin-common = { path = "../bin-common" } + # I'm not sure how to feel about pulling in this dependency here... nym-api-requests = { path = "../../nym-api/nym-api-requests" } -# 'serializable' feature -nym-config = { path = "../config", optional = true } - # 'wasm-serde-types' feature wasm-utils = { path = "../wasm/utils", default-features = false, optional = true } @@ -49,4 +51,5 @@ wasm-utils = { path = "../wasm/utils", default-features = false, optional = true default = ["provider-trait"] provider-trait = ["async-trait"] wasm-serde-types = ["tsify", "wasm-bindgen", "wasm-utils"] -serializable = ["serde", "nym-config", "serde_json"] \ No newline at end of file +serializable = ["serde", "serde_json"] +outfox = [] diff --git a/common/topology/src/error.rs b/common/topology/src/error.rs index 68f169ccc7..835ea37b1f 100644 --- a/common/topology/src/error.rs +++ b/common/topology/src/error.rs @@ -51,4 +51,16 @@ pub enum NymTopologyError { #[error("{0}")] PacketError(#[from] NymPacketError), + + #[error("{0}")] + ReqwestError(#[from] reqwest::Error), + + #[error("{0}")] + MixnodeConversionError(#[from] crate::mix::MixnodeConversionError), + + #[error("{0}")] + GatewayConversionError(#[from] crate::gateway::GatewayConversionError), + + #[error("{0}")] + VarError(#[from] std::env::VarError), } diff --git a/common/topology/src/lib.rs b/common/topology/src/lib.rs index a17e9baa6f..5630122d0c 100644 --- a/common/topology/src/lib.rs +++ b/common/topology/src/lib.rs @@ -6,7 +6,9 @@ use crate::filter::VersionFilterable; pub use error::NymTopologyError; -use log::{debug, warn}; +use log::{debug, info, warn}; +use mix::Node; +use nym_config::defaults::var_names::NYM_API; use nym_mixnet_contract_common::mixnode::MixNodeDetails; use nym_mixnet_contract_common::{GatewayBond, IdentityKeyRef, MixId}; use nym_sphinx_addressing::nodes::NodeIdentity; @@ -116,13 +118,40 @@ impl Display for NetworkAddress { pub type MixLayer = u8; -#[derive(Debug, Clone)] +#[derive(Debug, Clone, Default)] pub struct NymTopology { mixes: BTreeMap>, gateways: Vec, } impl NymTopology { + pub async fn new_from_env() -> Result { + let api_url = std::env::var(NYM_API)?; + + info!("Generating topology from {}", api_url); + + let mixnodes = reqwest::get(&format!("{}/v1/mixnodes", api_url)) + .await? + .json::>() + .await? + .into_iter() + .map(|details| details.bond_information) + .map(mix::Node::try_from) + .filter(Result::is_ok) + .collect::, _>>()?; + + let gateways = reqwest::get(&format!("{}/v1/gateways", api_url)) + .await? + .json::>() + .await? + .into_iter() + .map(gateway::Node::try_from) + .filter(Result::is_ok) + .collect::, _>>()?; + let topology = NymTopology::new_unordered(mixnodes, gateways); + Ok(topology) + } + pub fn new(mixes: BTreeMap>, gateways: Vec) -> Self { NymTopology { mixes, gateways } } @@ -270,7 +299,7 @@ impl NymTopology { &self, rng: &mut R, num_mix_hops: u8, - ) -> Result, NymTopologyError> + ) -> Result, NymTopologyError> where R: Rng + CryptoRng + ?Sized, { @@ -295,12 +324,32 @@ impl NymTopology { let random_mix = layer_mixes .choose(rng) .ok_or(NymTopologyError::EmptyMixLayer { layer })?; - route.push(random_mix.into()); + route.push(random_mix.clone()); } Ok(route) } + pub fn random_path_to_gateway( + &self, + rng: &mut R, + num_mix_hops: u8, + gateway_identity: &NodeIdentity, + ) -> Result<(Vec, gateway::Node), NymTopologyError> + where + R: Rng + CryptoRng + ?Sized, + { + let gateway = self.get_gateway(gateway_identity).ok_or( + NymTopologyError::NonExistentGatewayError { + identity_key: gateway_identity.to_base58_string(), + }, + )?; + + let path = self.random_mix_route(rng, num_mix_hops)?; + + Ok((path, gateway.clone())) + } + /// Tries to create a route to the specified gateway, such that it goes through mixnode on layer 1, /// mixnode on layer2, .... mixnode on layer n and finally the target gateway pub fn random_route_to_gateway( @@ -321,6 +370,7 @@ impl NymTopology { Ok(self .random_mix_route(rng, num_mix_hops)? .into_iter() + .map(|node| SphinxNode::from(&node)) .chain(std::iter::once(gateway.into())) .collect()) } diff --git a/common/types/Cargo.toml b/common/types/Cargo.toml index b438fcfb04..77f30ad7e2 100644 --- a/common/types/Cargo.toml +++ b/common/types/Cargo.toml @@ -4,7 +4,7 @@ version = "1.0.0" description = "Nym common types" authors.workspace = true edition = "2021" -rust-version = "1.58" +rust-version.workspace = true license.workspace = true [dependencies] diff --git a/common/types/src/lib.rs b/common/types/src/lib.rs index e44fa517df..76aa6b2662 100644 --- a/common/types/src/lib.rs +++ b/common/types/src/lib.rs @@ -11,6 +11,7 @@ pub mod gas; pub mod gateway; pub mod helpers; pub mod mixnode; +pub mod monitoring; pub mod pending_events; pub mod transaction; pub mod vesting; diff --git a/common/types/src/monitoring.rs b/common/types/src/monitoring.rs new file mode 100644 index 0000000000..f98d548446 --- /dev/null +++ b/common/types/src/monitoring.rs @@ -0,0 +1,131 @@ +use std::{collections::HashSet, sync::LazyLock, time::SystemTime}; + +use nym_crypto::asymmetric::identity::{PrivateKey, PublicKey, Signature}; +use nym_mixnet_contract_common::MixId; +use schemars::JsonSchema; +use serde::{Deserialize, Serialize}; + +static NETWORK_MONITORS: LazyLock> = LazyLock::new(|| { + let mut nm = HashSet::new(); + nm.insert("5VsPyLbsBCq9PAMWmjKkToteVAKNabNqex6QwDf5fWzt".to_string()); + nm +}); + +#[derive(Debug, Serialize, Deserialize, JsonSchema, Clone)] +pub struct NodeResult { + pub node_id: MixId, + pub identity: String, + pub reliability: u8, +} + +#[derive(Debug, Serialize, Deserialize, JsonSchema, Clone)] +pub struct MixnodeResult { + pub mix_id: MixId, + pub identity: String, + pub owner: String, + pub reliability: u8, +} + +impl MixnodeResult { + pub fn new(mix_id: MixId, identity: String, owner: String, reliability: u8) -> Self { + MixnodeResult { + mix_id, + identity, + owner, + reliability, + } + } +} + +#[derive(Debug, Deserialize, Serialize, JsonSchema, Clone)] +pub struct GatewayResult { + pub identity: String, + pub owner: String, + pub reliability: u8, + pub mix_id: MixId, +} + +impl GatewayResult { + pub fn new(identity: String, owner: String, reliability: u8) -> Self { + GatewayResult { + identity, + owner, + reliability, + mix_id: 0, + } + } +} + +#[derive(Serialize, Deserialize, JsonSchema)] +#[serde(untagged)] +pub enum MonitorResults { + Mixnode(Vec), + Gateway(Vec), +} + +#[derive(Serialize, Deserialize, JsonSchema)] +pub struct MonitorMessage { + results: Vec, + signature: String, + signer: String, + timestamp: i64, +} + +impl MonitorMessage { + fn message_to_sign(results: &[NodeResult], timestamp: i64) -> Vec { + let mut msg = match serde_json::to_vec(results) { + Ok(msg) => msg, + Err(_) => Vec::new(), + }; + msg.extend_from_slice(×tamp.to_le_bytes()); + msg + } + + pub fn timely(&self) -> bool { + let now = SystemTime::now() + .duration_since(SystemTime::UNIX_EPOCH) + .expect("Time went backwards") + .as_secs() as i64; + + now - self.timestamp < 5 + } + + pub fn new(results: Vec, private_key: &PrivateKey) -> Self { + let timestamp = SystemTime::now() + .duration_since(SystemTime::UNIX_EPOCH) + .expect("Time went backwards") + .as_secs() as i64; + + let msg = Self::message_to_sign(&results, timestamp); + let signature = private_key.sign(&msg); + let public_key = private_key.public_key(); + + MonitorMessage { + results, + signature: signature.to_base58_string(), + signer: public_key.to_base58_string(), + timestamp, + } + } + + pub fn from_allowed(&self) -> bool { + NETWORK_MONITORS.contains(&self.signer) + } + + pub fn results(&self) -> &[NodeResult] { + &self.results + } + + pub fn verify(&self) -> bool { + let msg = Self::message_to_sign(&self.results, self.timestamp); + + let signature = match Signature::from_base58_string(&self.signature) { + Ok(sig) => sig, + Err(_) => return false, + }; + + PublicKey::from_base58_string(&self.signer) + .map(|pk| pk.verify(msg, &signature).is_ok()) + .unwrap_or(false) + } +} diff --git a/common/wasm/utils/Cargo.toml b/common/wasm/utils/Cargo.toml index 76ebe5f3dd..7305908344 100644 --- a/common/wasm/utils/Cargo.toml +++ b/common/wasm/utils/Cargo.toml @@ -30,13 +30,9 @@ workspace = true optional = true [features] -default = ["sleep", "console_error_panic_hook"] +default = ["sleep"] sleep = ["web-sys", "web-sys/Window"] -websocket = [ - "getrandom", - "tungstenite", - "gloo-net" -] +websocket = ["getrandom", "tungstenite", "gloo-net"] crypto = [ "web-sys", "web-sys/Crypto", diff --git a/envs/mainnet-local-api.env b/envs/mainnet-local-api.env new file mode 100644 index 0000000000..d6683c937d --- /dev/null +++ b/envs/mainnet-local-api.env @@ -0,0 +1,27 @@ +CONFIGURED=true + +NETWORK_NAME=mainnet + +RUST_LOG=info +RUST_BACKTRACE=1 + +BECH32_PREFIX=n +MIX_DENOM=unym +MIX_DENOM_DISPLAY=nym +STAKE_DENOM=unyx +STAKE_DENOM_DISPLAY=nyx +DENOMS_EXPONENT=6 + +MIXNET_CONTRACT_ADDRESS=n17srjznxl9dvzdkpwpw24gg668wc73val88a6m5ajg6ankwvz9wtst0cznr +VESTING_CONTRACT_ADDRESS=n1nc5tatafv6eyq7llkr2gv50ff9e22mnf70qgjlv737ktmt4eswrq73f2nw +GROUP_CONTRACT_ADDRESS=n1e2zq4886zzewpvpucmlw8v9p7zv692f6yck4zjzxh699dkcmlrfqk2knsr +MULTISIG_CONTRACT_ADDRESS=n1txayqfz5g9qww3rlflpg025xd26m9payz96u54x4fe3s2ktz39xqk67gzx +COCONUT_DKG_CONTRACT_ADDRESS=n19604yflqggs9mk2z26mqygq43q2kr3n932egxx630svywd5mpxjsztfpvx + +REWARDING_VALIDATOR_ADDRESS=n10yyd98e2tuwu0f7ypz9dy3hhjw7v772q6287gy +STATISTICS_SERVICE_DOMAIN_ADDRESS="https://mainnet-stats.nymte.ch:8090" +NYXD="https://rpc.nymtech.net" +NYM_API="http://127.0.0.1:8000" +NYXD_WS="wss://rpc.nymtech.net/websocket" +EXPLORER_API="https://explorer.nymtech.net/api/" +NYM_VPN_API="https://nymvpn.com/api" diff --git a/nym-api/Cargo.toml b/nym-api/Cargo.toml index 551f682c13..9e58b24f1c 100644 --- a/nym-api/Cargo.toml +++ b/nym-api/Cargo.toml @@ -28,10 +28,13 @@ dirs = { workspace = true } futures = { workspace = true } itertools = { workspace = true } humantime-serde = { workspace = true } -k256 = { workspace = true, features = ["ecdsa-core"] } # needed for the Verifier trait; pull whatever version is used by other dependencies +k256 = { workspace = true, features = [ + "ecdsa-core", +] } # needed for the Verifier trait; pull whatever version is used by other dependencies log = { workspace = true } pin-project = { workspace = true } rand = { workspace = true } +rand_chacha = { workspace = true } reqwest = { workspace = true, features = ["json"] } rocket = { workspace = true, features = ["json"] } rocket_cors = { workspace = true } @@ -40,7 +43,12 @@ serde_json = { workspace = true } tap = { workspace = true } thiserror = { workspace = true } time = { workspace = true, features = ["serde-human-readable", "parsing"] } -tokio = { workspace = true, features = ["rt-multi-thread", "macros", "signal", "time"] } +tokio = { workspace = true, features = [ + "rt-multi-thread", + "macros", + "signal", + "time", +] } tokio-stream = { workspace = true } url = { workspace = true } @@ -82,7 +90,9 @@ nym-credentials-interface = { path = "../common/credentials-interface" } #nym-ephemera-common = { path = "../common/cosmwasm-smart-contracts/ephemera" } nym-config = { path = "../common/config" } cosmwasm-std = { workspace = true } -nym-credential-storage = { path = "../common/credential-storage", features = ["persistent-storage"] } +nym-credential-storage = { path = "../common/credential-storage", features = [ + "persistent-storage", +] } nym-credentials = { path = "../common/credentials" } nym-crypto = { path = "../common/crypto" } cw2 = { workspace = true } @@ -105,6 +115,7 @@ nym-validator-client = { path = "../common/client-libs/validator-client" } nym-bin-common = { path = "../common/bin-common", features = ["output_format"] } nym-node-tester-utils = { path = "../common/node-tester-utils" } nym-node-requests = { path = "../nym-node/nym-node-requests" } +nym-types = { path = "../common/types" } [features] no-reward = [] @@ -125,4 +136,3 @@ cw3 = { workspace = true } cw-utils = { workspace = true } rand_chacha = { workspace = true } sha2 = "0.9" - diff --git a/nym-api/migrations/20240524101449_monitor_v2_tables.sql b/nym-api/migrations/20240524101449_monitor_v2_tables.sql new file mode 100644 index 0000000000..bef99f2bda --- /dev/null +++ b/nym-api/migrations/20240524101449_monitor_v2_tables.sql @@ -0,0 +1,31 @@ +CREATE TABLE mixnode_details_v2 +( + id INTEGER NOT NULL PRIMARY KEY AUTOINCREMENT, + mix_id INTEGER NOT NULL UNIQUE, + owner VARCHAR NOT NULL, + identity_key VARCHAR NOT NULL +); + +CREATE TABLE mixnode_status_v2 +( + mixnode_details_id INTEGER NOT NULL, + reliability INTEGER NOT NULL, + timestamp INTEGER NOT NULL +); + +CREATE TABLE gateway_details_v2 +( + id INTEGER NOT NULL PRIMARY KEY AUTOINCREMENT, + owner VARCHAR NOT NULL, + identity VARCHAR NOT NULL UNIQUE +); + +CREATE TABLE gateway_status_v2 +( + gateway_details_id INTEGER NOT NULL, + reliability INTEGER NOT NULL, + timestamp INTEGER NOT NULL +); + + + diff --git a/nym-api/migrations/20240819170000_monitor_v2_tables_v2.sql b/nym-api/migrations/20240819170000_monitor_v2_tables_v2.sql new file mode 100644 index 0000000000..86c3137144 --- /dev/null +++ b/nym-api/migrations/20240819170000_monitor_v2_tables_v2.sql @@ -0,0 +1,19 @@ +DROP TABLE IF EXISTS mixnode_details_v2; + +CREATE TABLE mixnode_details_v2 +( + id INTEGER NOT NULL PRIMARY KEY AUTOINCREMENT, + node_id INTEGER NOT NULL UNIQUE, + identity_key VARCHAR NOT NULL +); + +DROP TABLE IF EXISTS gateway_details_v2; + +CREATE TABLE gateway_details_v2 +( + id INTEGER NOT NULL PRIMARY KEY AUTOINCREMENT, + node_id INTEGER NOT NULL UNIQUE, + identity VARCHAR NOT NULL UNIQUE +); + + diff --git a/nym-api/migrations/20240822110000_non_unique_gateway_idx_until_we_migrate.sql b/nym-api/migrations/20240822110000_non_unique_gateway_idx_until_we_migrate.sql new file mode 100644 index 0000000000..405f817da2 --- /dev/null +++ b/nym-api/migrations/20240822110000_non_unique_gateway_idx_until_we_migrate.sql @@ -0,0 +1,10 @@ +DROP TABLE IF EXISTS gateway_details_v2; + +CREATE TABLE gateway_details_v2 +( + id INTEGER NOT NULL PRIMARY KEY AUTOINCREMENT, + node_id INTEGER NOT NULL, + identity VARCHAR NOT NULL UNIQUE +); + + diff --git a/nym-api/src/epoch_operations/mod.rs b/nym-api/src/epoch_operations/mod.rs index c14fd7f90a..d8e4365eee 100644 --- a/nym-api/src/epoch_operations/mod.rs +++ b/nym-api/src/epoch_operations/mod.rs @@ -56,6 +56,7 @@ impl RewardedSetUpdater { } } + #[allow(clippy::doc_lazy_continuation)] // This is where the epoch gets advanced, and all epoch related transactions originate /// Upon each epoch having finished the following actions are executed by this nym-api: /// 1. it computes the rewards for each node using the ephemera channel for the epoch that diff --git a/nym-api/src/network_monitor/monitor/summary_producer.rs b/nym-api/src/network_monitor/monitor/summary_producer.rs index 1faca33238..0c09e196f6 100644 --- a/nym-api/src/network_monitor/monitor/summary_producer.rs +++ b/nym-api/src/network_monitor/monitor/summary_producer.rs @@ -4,8 +4,8 @@ use crate::network_monitor::monitor::preparer::InvalidNode; use crate::network_monitor::test_packet::NodeTestMessage; use crate::network_monitor::test_route::TestRoute; -use nym_mixnet_contract_common::MixId; use nym_node_tester_utils::node::{NodeType, TestableNode}; +use nym_types::monitoring::{GatewayResult, MixnodeResult}; use std::collections::HashMap; use std::fmt::{Display, Formatter}; @@ -20,42 +20,6 @@ const UNRELIABLE_THRESHOLD: u8 = 1; // 1 - 60 // from the average result, remove this data and recalculate scores. // const ALLOWED_RELIABILITY_DEVIATION: f32 = 5.0; -#[derive(Debug)] -pub(crate) struct MixnodeResult { - pub(crate) mix_id: MixId, - pub(crate) identity: String, - pub(crate) owner: String, - pub(crate) reliability: u8, -} - -impl MixnodeResult { - pub(crate) fn new(mix_id: MixId, identity: String, owner: String, reliability: u8) -> Self { - MixnodeResult { - mix_id, - identity, - owner, - reliability, - } - } -} - -#[derive(Debug)] -pub(crate) struct GatewayResult { - pub(crate) identity: String, - pub(crate) owner: String, - pub(crate) reliability: u8, -} - -impl GatewayResult { - pub(crate) fn new(identity: String, owner: String, reliability: u8) -> Self { - GatewayResult { - identity, - owner, - reliability, - } - } -} - #[derive(Debug, Clone)] pub(crate) struct RouteResult { pub(crate) route: TestRoute, diff --git a/nym-api/src/node_status_api/mod.rs b/nym-api/src/node_status_api/mod.rs index 684dac11ae..4800b5957a 100644 --- a/nym-api/src/node_status_api/mod.rs +++ b/nym-api/src/node_status_api/mod.rs @@ -54,6 +54,8 @@ pub(crate) fn node_status_routes( routes::get_gateways_detailed_unfiltered, routes::unstable::mixnode_test_results, routes::unstable::gateway_test_results, + routes::submit_gateway_monitoring_results, + routes::submit_node_monitoring_results, ] } else { // in the minimal variant we would not have access to endpoints relying on existence diff --git a/nym-api/src/node_status_api/routes.rs b/nym-api/src/node_status_api/routes.rs index 7f2f714a3f..19b6462d1d 100644 --- a/nym-api/src/node_status_api/routes.rs +++ b/nym-api/src/node_status_api/routes.rs @@ -10,6 +10,7 @@ use nym_api_requests::models::{ UptimeResponse, }; use nym_mixnet_contract_common::MixId; +use nym_types::monitoring::MonitorMessage; use rocket::serde::json::Json; use rocket::State; use rocket_okapi::openapi; @@ -29,6 +30,92 @@ use crate::node_status_api::models::ErrorResponse; use crate::storage::NymApiStorage; use crate::NymContractCache; +#[openapi(tag = "status")] +#[post("/submit-gateway-monitoring-results", data = "")] +pub(crate) async fn submit_gateway_monitoring_results( + message: Json, + storage: &State, +) -> Result<(), ErrorResponse> { + if !message.from_allowed() { + return Err(ErrorResponse::new( + "Monitor not registered to submit results".to_string(), + rocket::http::Status::Forbidden, + )); + } + + if !message.timely() { + return Err(ErrorResponse::new( + "Message is too old".to_string(), + rocket::http::Status::BadRequest, + )); + } + + if !message.verify() { + return Err(ErrorResponse::new( + "Invalid signature".to_string(), + rocket::http::Status::BadRequest, + )); + } + + match storage + .manager + .submit_gateway_statuses_v2(message.results()) + .await + { + Ok(_) => Ok(()), + Err(err) => { + error!("failed to submit gateway monitoring results: {}", err); + Err(ErrorResponse::new( + "failed to submit gateway monitoring results".to_string(), + rocket::http::Status::InternalServerError, + )) + } + } +} + +#[openapi(tag = "status")] +#[post("/submit-node-monitoring-results", data = "")] +pub(crate) async fn submit_node_monitoring_results( + message: Json, + storage: &State, +) -> Result<(), ErrorResponse> { + if !message.from_allowed() { + return Err(ErrorResponse::new( + "Monitor not registered to submit results".to_string(), + rocket::http::Status::Forbidden, + )); + } + + if !message.timely() { + return Err(ErrorResponse::new( + "Message is too old".to_string(), + rocket::http::Status::BadRequest, + )); + } + + if !message.verify() { + return Err(ErrorResponse::new( + "Invalid signature".to_string(), + rocket::http::Status::BadRequest, + )); + } + + match storage + .manager + .submit_mixnode_statuses_v2(message.results()) + .await + { + Ok(_) => Ok(()), + Err(err) => { + error!("failed to submit node monitoring results: {}", err); + Err(ErrorResponse::new( + "failed to submit node monitoring results".to_string(), + rocket::http::Status::InternalServerError, + )) + } + } +} + #[openapi(tag = "status")] #[get("/gateway//report")] pub(crate) async fn gateway_report( diff --git a/nym-api/src/support/storage/manager.rs b/nym-api/src/support/storage/manager.rs index a885359917..62bb77921b 100644 --- a/nym-api/src/support/storage/manager.rs +++ b/nym-api/src/support/storage/manager.rs @@ -1,6 +1,5 @@ // Copyright 2021 - Nym Technologies SA // SPDX-License-Identifier: GPL-3.0-only -use crate::network_monitor::monitor::summary_producer::{GatewayResult, MixnodeResult}; use crate::node_status_api::models::{HistoricalUptime, Uptime}; use crate::node_status_api::utils::{ActiveGatewayStatuses, ActiveMixnodeStatuses}; use crate::support::storage::models::{ @@ -8,6 +7,8 @@ use crate::support::storage::models::{ TestedGatewayStatus, TestedMixnodeStatus, TestingRoute, }; use nym_mixnet_contract_common::{EpochId, IdentityKey, MixId}; +use nym_types::monitoring::{GatewayResult, MixnodeResult, NodeResult}; +use time::OffsetDateTime; #[derive(Clone)] pub(crate) struct StorageManager { @@ -502,6 +503,47 @@ impl StorageManager { tx.commit().await } + pub(crate) async fn submit_mixnode_statuses_v2( + &self, + mixnode_results: &[NodeResult], + ) -> Result<(), sqlx::Error> { + info!("Inserting {} mixnode statuses", mixnode_results.len()); + + let timestamp = OffsetDateTime::now_utc().unix_timestamp(); + // insert it all in a transaction to make sure all nodes are updated at the same time + // (plus it's a nice guard against new nodes) + let mut tx = self.connection_pool.begin().await?; + for mixnode_result in mixnode_results { + let mixnode_id = sqlx::query!( + r#" + INSERT OR IGNORE INTO mixnode_details_v2(node_id, identity_key) VALUES (?, ?); + SELECT id FROM mixnode_details_v2 WHERE node_id = ?; + "#, + mixnode_result.node_id, + mixnode_result.identity, + mixnode_result.node_id, + ) + .fetch_one(&mut tx) + .await? + .id; + + // insert the actual status + sqlx::query!( + r#" + INSERT INTO mixnode_status_v2 (mixnode_details_id, reliability, timestamp) VALUES (?, ?, ?); + "#, + mixnode_id, + mixnode_result.reliability, + timestamp + ) + .execute(&mut tx) + .await?; + } + + // finally commit the transaction + tx.commit().await + } + /// Tries to submit gateway [`NodeResult`] from the network monitor to the database. /// /// # Arguments @@ -551,6 +593,51 @@ impl StorageManager { tx.commit().await } + pub(crate) async fn submit_gateway_statuses_v2( + &self, + gateway_results: &[NodeResult], + ) -> Result<(), sqlx::Error> { + info!("Inserting {} gateway statuses", gateway_results.len()); + + let timestamp = OffsetDateTime::now_utc().unix_timestamp(); + // insert it all in a transaction to make sure all nodes are updated at the same time + // (plus it's a nice guard against new nodes) + let mut tx = self.connection_pool.begin().await?; + + for gateway_result in gateway_results { + // if gateway info doesn't exist, insert it and get its id + + // same ID "problem" as described for mixnode insertion + let gateway_id = sqlx::query!( + r#" + INSERT OR IGNORE INTO gateway_details_v2(identity, node_id) VALUES (?, ?); + SELECT id FROM gateway_details_v2 WHERE identity = ?; + "#, + gateway_result.identity, + gateway_result.node_id, + gateway_result.identity, + ) + .fetch_one(&mut tx) + .await? + .id; + + // insert the actual status + sqlx::query!( + r#" + INSERT INTO gateway_status_v2 (gateway_details_id, reliability, timestamp) VALUES (?, ?, ?); + "#, + gateway_id, + gateway_result.reliability, + timestamp + ) + .execute(&mut tx) + .await?; + } + + // finally commit the transaction + tx.commit().await + } + /// Saves the information about which nodes were used as core nodes during this particular /// network monitor test run. /// diff --git a/nym-api/src/support/storage/mod.rs b/nym-api/src/support/storage/mod.rs index 201dfec366..32621aa619 100644 --- a/nym-api/src/support/storage/mod.rs +++ b/nym-api/src/support/storage/mod.rs @@ -1,7 +1,6 @@ // Copyright 2021 - Nym Technologies SA // SPDX-License-Identifier: GPL-3.0-only -use crate::network_monitor::monitor::summary_producer::{GatewayResult, MixnodeResult}; use crate::network_monitor::test_route::TestRoute; use crate::node_status_api::models::{ GatewayStatusReport, GatewayUptimeHistory, MixnodeStatusReport, MixnodeUptimeHistory, @@ -14,6 +13,7 @@ use crate::support::storage::models::{ GatewayDetails, MixnodeDetails, TestedGatewayStatus, TestedMixnodeStatus, }; use nym_mixnet_contract_common::MixId; +use nym_types::monitoring::{GatewayResult, MixnodeResult}; use rocket::fairing::AdHoc; use sqlx::ConnectOptions; use std::path::Path; diff --git a/nym-network-monitor.dockerfile b/nym-network-monitor.dockerfile new file mode 100644 index 0000000000..c85aeb7bf6 --- /dev/null +++ b/nym-network-monitor.dockerfile @@ -0,0 +1,14 @@ +FROM rust:latest AS builder + +COPY ./ /usr/src/nym +WORKDIR /usr/src/nym/nym-network-monitor +RUN cargo build --release + +FROM locustio/locust +EXPOSE 8089 +COPY --from=builder /usr/src/nym/target/release/nym-network-monitor /bin/nym-network-monitor +COPY --from=builder /usr/src/nym/nym-network-monitor/locustfile.py locustfile.py +COPY --from=builder /usr/src/nym/nym-network-monitor/entrypoint.sh entrypoint.sh +COPY --from=builder /usr/src/nym/envs/mainnet.env mainnet.env + +ENTRYPOINT ["./entrypoint.sh"] diff --git a/nym-network-monitor/Cargo.toml b/nym-network-monitor/Cargo.toml new file mode 100644 index 0000000000..939a8b7146 --- /dev/null +++ b/nym-network-monitor/Cargo.toml @@ -0,0 +1,39 @@ +[package] +name = "nym-network-monitor" +version = "0.1.0" +authors.workspace = true +repository.workspace = true +homepage.workspace = true +documentation.workspace = true +edition.workspace = true +license.workspace = true + +# See more keys and their definitions at https://doc.rust-lang.org/cargo/reference/manifest.html + +[dependencies] +anyhow = { workspace = true } +axum = { workspace = true, features = ["json"] } +clap = { workspace = true, features = ["derive"] } +dashmap = { workspace = true } +futures = { workspace = true } +log = { workspace = true } +petgraph = "0.6.5" +rand = { workspace = true } +rand_chacha = { workspace = true } +reqwest = { workspace = true, features = ["json"] } +serde = { workspace = true, features = ["derive"] } +serde_json = { workspace = true } +tokio = { workspace = true, features = ["macros", "time"] } +tokio-util = { workspace = true } +utoipa = { workspace = true, features = ["axum_extras"] } +utoipa-swagger-ui = { workspace = true, features = ["axum"] } + +# internal +nym-bin-common = { path = "../common/bin-common" } +nym-crypto = { path = "../common/crypto" } +nym-network-defaults = { path = "../common/network-defaults" } +nym-sdk = { path = "../sdk/rust/nym-sdk" } +nym-sphinx = { path = "../common/nymsphinx" } +nym-topology = { path = "../common/topology" } +nym-types = { path = "../common/types" } +nym-validator-client = { path = "../common/client-libs/validator-client" } diff --git a/nym-network-monitor/README.md b/nym-network-monitor/README.md new file mode 100644 index 0000000000..d63ba00814 --- /dev/null +++ b/nym-network-monitor/README.md @@ -0,0 +1,47 @@ +# Nym Network Monitor + +Monitors the Nym network by sending itself packages across the mixnet. + +Network monitor is running two tokio tasks, one manages mixnet clients and another manages monitoring itself. Monitor is designed to be driven externally, via an HTTP api. This means that it does not do any monitoring unless driven by something like [`locust`](https://locust.io/). This allows us to tailor the load externally, potentially distributing it across multiple monitors. + +### Client manager + +On start network monitor will spawn `C` clients, with 10 being the default. Random client is dropped every `T`, defaults to 60 seconds, and a new one is created. Clients chose a random gateway to connect to the mixnet. Meaning that on average all gateways will be tested in `NUMBER_OF_GATEWAYS/N*T`, assuming at least one request per client per T. + +### Network monitor API + +Swagger UI is available at `/v1/ui/`, ie `http://localhost:8080/v1/ui/` + +### Driving the monitor with Locust + ++ Head over to https://locust.io/ and get `locust` ++ Start everything +```bash +# Start the network monitor +cargo run --release + +# Start locus in a separate terminal +python -m locust -H http://127.0.0.1:8080 --processes 4 +``` ++ Head over to http://127.0.0.1:8089/ and start a testing run + +## Usage + +```bash +Usage: nym-network-monitor [OPTIONS] + +Options: + -C, --clients Number of clients to spawn [default: 10] + -T, --client-lifetime Lifetime of each client in seconds [default: 60] + --port Port to listen on [default: 8080] + --host Host to listen on [default: 127.0.0.1] + -t, --topology Path to the topology file + -e, --env Path to the environment file + -m, --mixnet-timeout [default: 10] + --generate-key-pair + --private-key + -h, --help Print help + -V, --version Print version +``` + + diff --git a/nym-network-monitor/entrypoint.sh b/nym-network-monitor/entrypoint.sh new file mode 100755 index 0000000000..acaaaf7430 --- /dev/null +++ b/nym-network-monitor/entrypoint.sh @@ -0,0 +1,21 @@ +#!/bin/bash +# Takes timeout in seconds as the first argument, defaults to 60 +# Takes number of users as the second argument, defaults to 10 + +set -ex + +users=${2:-10} +timeout=${1:-600} + +RUST_LOG=info nym-network-monitor --env mainnet.env --host 127.0.0.1 --port 8080 & +nnm_pid=$! + +sleep 10 + +python -m locust -H http://127.0.0.1:8080 --processes 4 --autostart --autoquit 60 -u "$users" -t "$timeout"s & +locust_pid=$! + +wait $locust_pid +kill -2 $nnm_pid + +exit $? diff --git a/nym-network-monitor/locustfile.py b/nym-network-monitor/locustfile.py new file mode 100644 index 0000000000..a89e58ec89 --- /dev/null +++ b/nym-network-monitor/locustfile.py @@ -0,0 +1,7 @@ +from locust import HttpUser, task + + +class SendMsg(HttpUser): + @task + def hello_world(self): + self.client.post("/v1/send") diff --git a/nym-network-monitor/src/accounting.rs b/nym-network-monitor/src/accounting.rs new file mode 100644 index 0000000000..d658e9dc63 --- /dev/null +++ b/nym-network-monitor/src/accounting.rs @@ -0,0 +1,382 @@ +use std::collections::{HashMap, HashSet}; + +use anyhow::Result; +use futures::{stream::FuturesUnordered, StreamExt}; +use log::{debug, info}; +use nym_sphinx::chunking::{SentFragment, FRAGMENTS_RECEIVED, FRAGMENTS_SENT}; +use nym_topology::{gateway, mix, NymTopology}; +use nym_types::monitoring::{MonitorMessage, NodeResult}; +use nym_validator_client::nym_api::routes::{API_VERSION, STATUS, SUBMIT_GATEWAY, SUBMIT_NODE}; +use rand::SeedableRng; +use rand_chacha::ChaCha8Rng; +use serde::{Deserialize, Serialize}; +use utoipa::ToSchema; + +use crate::{NYM_API_URL, PRIVATE_KEY, TOPOLOGY}; + +struct HydratedRoute { + mix_nodes: Vec, + gateway_node: gateway::Node, +} + +#[derive(Serialize, Deserialize, Debug, Default, ToSchema)] +struct GatewayStats(u32, u32, Option); + +impl GatewayStats { + fn new(sent: u32, recv: u32, owner: Option) -> Self { + GatewayStats(sent, recv, owner) + } + + fn success(&self) -> u32 { + self.0 + } + + fn failed(&self) -> u32 { + self.1 + } + + fn reliability(&self) -> f64 { + self.success() as f64 / (self.success() + self.failed()) as f64 + } + + fn incr_success(&mut self) { + self.0 += 1; + } + + fn incr_failure(&mut self) { + self.1 += 1; + } +} + +#[derive(Serialize, Deserialize, Debug, Default, ToSchema)] +pub struct NetworkAccount { + complete_fragment_sets: HashSet, + incomplete_fragment_sets: HashSet, + missing_fragments: HashMap>, + complete_routes: Vec>, + gateway_stats: HashMap, + incomplete_routes: Vec>, + #[serde(skip)] + topology: NymTopology, + tested_nodes: HashSet, + #[serde(skip)] + mix_details: HashMap, + #[serde(skip)] + gateway_details: HashMap, +} + +impl NetworkAccount { + pub fn tested_nodes(&self) -> &HashSet { + &self.tested_nodes + } + + pub fn node_stats(&self, id: u32) -> NodeStats { + let complete_routes = self.complete_for_id(id); + let incomplete_routes = self.incomplete_for_id(id); + let node = self + .mix_details + .get(&id) + .expect("Has to be in here, since we've put it in!"); + NodeStats::new( + id, + complete_routes, + incomplete_routes, + node.identity_key.to_base58_string(), + node.owner.clone(), + ) + } + + fn complete_for_id(&self, id: u32) -> usize { + self.complete_routes() + .iter() + .filter(|r| r.contains(&id)) + .count() + } + + fn incomplete_for_id(&self, id: u32) -> usize { + self.incomplete_routes() + .iter() + .filter(|r| r.contains(&id)) + .count() + } + + pub fn complete_routes(&self) -> &Vec> { + &self.complete_routes + } + + pub fn incomplete_routes(&self) -> &Vec> { + &self.incomplete_routes + } + + pub fn finalize() -> Result { + let mut account = NetworkAccount::new(); + account.find_missing_fragments(); + account.hydrate_all_fragments()?; + Ok(account) + } + + pub fn empty_buffers() { + FRAGMENTS_SENT.clear(); + FRAGMENTS_RECEIVED.clear(); + } + + fn new() -> Self { + let topology = TOPOLOGY.get().expect("Topology not set yet!").clone(); + let mut account = NetworkAccount { + topology, + ..Default::default() + }; + for fragment_set in FRAGMENTS_SENT.iter() { + let sent_fragments = fragment_set + .value() + .first() + .map(|f| f.header().total_fragments()) + .unwrap_or(0); + + debug!( + "SENT Fragment set {} has {} fragments", + fragment_set.key(), + sent_fragments + ); + + let recv = FRAGMENTS_RECEIVED.get(fragment_set.key()); + let recv_fragments = recv.as_ref().map(|r| r.value().len()).unwrap_or(0); + debug!( + "RECV Fragment set {} has {} fragments", + fragment_set.key(), + recv_fragments + ); + + // Due to retransmission we can recieve a fragment multiple times + if sent_fragments as usize <= recv_fragments { + account.push_complete(*fragment_set.key()); + } else { + account.push_incomplete(*fragment_set.key()); + } + } + account + } + + fn hydrate_route(&self, fragment: SentFragment) -> anyhow::Result { + let mut rng = ChaCha8Rng::seed_from_u64(fragment.seed() as u64); + let (nodes, gw) = self.topology.random_path_to_gateway( + &mut rng, + fragment.mixnet_params().hops(), + fragment.mixnet_params().destination(), + )?; + Ok(HydratedRoute { + mix_nodes: nodes, + gateway_node: gw, + }) + } + + fn hydrate_all_fragments(&mut self) -> Result<()> { + for fragment_set in FRAGMENTS_SENT.iter() { + let fragment_set_id = fragment_set.key(); + for fragment in fragment_set.value() { + let route = self.hydrate_route(fragment.clone())?; + let mix_ids = route + .mix_nodes + .iter() + .map(|n| n.mix_id) + .collect::>(); + self.tested_nodes.extend(&mix_ids); + self.mix_details + .extend(route.mix_nodes.iter().map(|n| (n.mix_id, n.clone()))); + let gateway_stats_entry = self + .gateway_stats + .entry(route.gateway_node.identity_key.to_base58_string()) + .or_insert(GatewayStats::new(0, 0, route.gateway_node.owner.clone())); + self.gateway_details.insert( + route.gateway_node.identity_key.to_base58_string(), + route.gateway_node, + ); + if self.complete_fragment_sets.contains(fragment_set_id) { + self.complete_routes.push(mix_ids); + gateway_stats_entry.incr_success(); + } else { + self.incomplete_routes.push(mix_ids); + gateway_stats_entry.incr_failure(); + } + } + } + Ok(()) + } + + fn find_missing_fragments(&mut self) { + let mut missing_fragments_map = HashMap::new(); + for fragment_set_id in &self.incomplete_fragment_sets { + if let Some(fragment_ref) = FRAGMENTS_RECEIVED.get(fragment_set_id) { + if let Some(ref_fragment) = fragment_ref.value().first() { + let ref_header = ref_fragment.header(); + let ref_id_set = (0..ref_header.total_fragments()).collect::>(); + let recieved_set = fragment_ref + .value() + .iter() + .map(|f| f.header().current_fragment()) + .collect::>(); + let missing_fragments = ref_id_set + .difference(&recieved_set) + .cloned() + .collect::>(); + missing_fragments_map.insert(*fragment_set_id, missing_fragments); + } + }; + } + self.missing_fragments = missing_fragments_map; + } + + fn push_complete(&mut self, id: i32) { + self.complete_fragment_sets.insert(id); + } + + fn push_incomplete(&mut self, id: i32) { + self.incomplete_fragment_sets.insert(id); + } +} + +#[derive(Serialize, Debug, Default, ToSchema)] +pub struct NetworkAccountStats { + complete_fragment_sets: usize, + incomplete_fragment_sets: usize, + missing_fragments: usize, + complete_routes: usize, + incomplete_routes: usize, + tested_nodes: usize, +} + +impl From for NetworkAccountStats { + fn from(account: NetworkAccount) -> Self { + NetworkAccountStats { + complete_fragment_sets: account.complete_fragment_sets.len(), + incomplete_fragment_sets: account.incomplete_fragment_sets.len(), + missing_fragments: account.missing_fragments.values().map(|v| v.len()).sum(), + complete_routes: account.complete_routes.len(), + incomplete_routes: account.incomplete_routes.len(), + tested_nodes: account.tested_nodes.len(), + } + } +} + +#[derive(Serialize, Debug, ToSchema)] +pub struct NodeStats { + mix_id: u32, + complete_routes: usize, + incomplete_routes: usize, + reliability: f64, + identity: String, + owner: Option, +} + +impl NodeStats { + pub fn new( + mix_id: u32, + complete_routes: usize, + incomplete_routes: usize, + identity: String, + owner: Option, + ) -> Self { + NodeStats { + mix_id, + complete_routes, + incomplete_routes, + reliability: complete_routes as f64 / (complete_routes + incomplete_routes) as f64, + identity, + owner, + } + } + + pub fn reliability(&self) -> f64 { + self.reliability + } + + pub fn into_node_results(self) -> NodeResult { + NodeResult { + node_id: self.mix_id, + identity: self.identity, + reliability: (self.reliability * 100.) as u8, + } + } +} + +pub async fn all_node_stats() -> anyhow::Result> { + let account = NetworkAccount::finalize()?; + Ok(account + .tested_nodes() + .iter() + .map(|id| account.node_stats(*id)) + .collect::>()) +} + +pub async fn monitor_gateway_results() -> anyhow::Result> { + let account = NetworkAccount::finalize()?; + Ok(account + .gateway_stats + .iter() + .map(into_gateway_result) + .collect()) +} + +pub async fn monitor_mixnode_results() -> anyhow::Result> { + let stats = all_node_stats().await?; + Ok(stats + .into_iter() + .map(NodeStats::into_node_results) + .collect()) +} + +pub async fn submit_metrics() -> anyhow::Result<()> { + let node_stats = monitor_mixnode_results().await?; + let gateway_stats = monitor_gateway_results().await?; + + info!("Submitting metrics to {}", *NYM_API_URL); + let client = reqwest::Client::new(); + + let node_submit_url = format!("{}/{API_VERSION}/{STATUS}/{SUBMIT_NODE}", &*NYM_API_URL); + let gateway_submit_url = format!("{}/{API_VERSION}/{STATUS}/{SUBMIT_GATEWAY}", &*NYM_API_URL); + + info!("Submitting {} mixnode measurements", node_stats.len()); + + node_stats + .chunks(10) + .map(|chunk| { + let monitor_message = + MonitorMessage::new(chunk.to_vec(), PRIVATE_KEY.get().expect("We've set this!")); + client.post(&node_submit_url).json(&monitor_message).send() + }) + .collect::>() + .collect::>>() + .await + .into_iter() + .collect::, _>>()?; + + info!("Submitting {} gateway measurements", gateway_stats.len()); + + gateway_stats + .chunks(10) + .map(|chunk| { + let monitor_message = + MonitorMessage::new(chunk.to_vec(), PRIVATE_KEY.get().expect("We've set this!")); + client + .post(&gateway_submit_url) + .json(&monitor_message) + .send() + }) + .collect::>() + .collect::>>() + .await + .into_iter() + .collect::, _>>()?; + + NetworkAccount::empty_buffers(); + + Ok(()) +} + +fn into_gateway_result((key, stats): (&String, &GatewayStats)) -> NodeResult { + NodeResult { + identity: key.clone(), + reliability: (stats.reliability() * 100.) as u8, + node_id: 0, + } +} diff --git a/nym-network-monitor/src/handlers.rs b/nym-network-monitor/src/handlers.rs new file mode 100644 index 0000000000..50c3ee749f --- /dev/null +++ b/nym-network-monitor/src/handlers.rs @@ -0,0 +1,295 @@ +use axum::{ + extract::{Path, State}, + http::StatusCode, + Json, +}; +use futures::StreamExt; +use log::{debug, error, warn}; +use nym_sdk::mixnet::MixnetMessageSender; +use nym_sphinx::chunking::{ReceivedFragment, SentFragment, FRAGMENTS_RECEIVED, FRAGMENTS_SENT}; +use petgraph::{dot::Dot, Graph}; +use rand::{distributions::Alphanumeric, seq::SliceRandom, Rng}; +use serde::Serialize; +use std::{ + collections::{HashMap, HashSet}, + sync::Arc, + time::Duration, +}; +use tokio::time::timeout; +use utoipa::ToSchema; + +use crate::{ + accounting::{all_node_stats, NetworkAccount, NetworkAccountStats, NodeStats}, + http::AppState, + MIXNET_TIMEOUT, +}; + +#[derive(ToSchema, Serialize)] +pub struct FragmentsSent(HashMap>); + +#[derive(ToSchema, Serialize)] +pub struct FragmentsReceived(HashMap>); + +#[utoipa::path( + get, + path = "/v1/stats", + responses( + (status = 200, description = "Returns statistics collected since startup", body = NetworkAccountStats), + ) +)] +pub async fn stats_handler() -> Result, StatusCode> { + let account = NetworkAccount::finalize().map_err(|_| StatusCode::INTERNAL_SERVER_ERROR)?; + Ok(Json(account.into())) +} + +#[utoipa::path( + get, + path = "/v1/node_stats/{mix_id}", + responses( + (status = 200, description = "Returns statistics for a given mix_id, collected since startup", body = NodeStats), + ) +)] +pub async fn node_stats_handler(Path(mix_id): Path) -> Result, StatusCode> { + let account = NetworkAccount::finalize().map_err(|_| StatusCode::INTERNAL_SERVER_ERROR)?; + Ok(Json(account.node_stats(mix_id))) +} + +#[utoipa::path( + get, + path = "/v1/node_stats", + responses( + (status = 200, description = "Returns statistics for all nodes, collected since startup, sorted by reliability", body = Vec), + ) +)] +pub async fn all_nodes_stats_handler() -> Result>, StatusCode> { + let mut stats = all_node_stats() + .await + .map_err(|_| StatusCode::INTERNAL_SERVER_ERROR)?; + stats.sort_by(|a, b| a.reliability().partial_cmp(&b.reliability()).unwrap()); + Ok(Json(stats)) +} + +#[utoipa::path( + get, + path = "/v1/accounting", + responses( + (status = 200, description = "Returns raw aggregated data collected since startup", body = NetworkAccount), + ) +)] +pub async fn accounting_handler() -> Result, StatusCode> { + NetworkAccount::finalize() + .map_err(|_| StatusCode::INTERNAL_SERVER_ERROR) + .map(Json) +} + +#[utoipa::path( + get, + path = "/v1/dot/{mix_id}", + responses( + (status = 200, description = "Returns Subgraph for a given *mix_id* in `dot` format", body = String), + ) +)] +pub async fn mix_dot_handler(Path(mix_id): Path) -> Result { + generate_dot(Some(mix_id)) +} + +#[utoipa::path( + get, + path = "/v1/dot", + responses( + (status = 200, description = "Returns entire tested network graph in `dot` format", body = String), + ) +)] +pub async fn graph_handler() -> Result { + generate_dot(None) +} + +#[utoipa::path( + get, + path = "/v1/sent", + responses( + (status = 200, description = "Returns a map of all fragments sent by the network monitor", body = FragmentsSent), + ) +)] +pub async fn sent_handler() -> Json { + Json(FragmentsSent( + (*FRAGMENTS_SENT) + .clone() + .into_iter() + .collect::>(), + )) +} + +#[utoipa::path( + get, + path = "/v1/received", + responses( + (status = 200, description = "Returns a map of all fragments received by the network monitor", body = FragmentsReceived), + ) +)] +pub async fn recv_handler() -> Json { + Json(FragmentsReceived( + (*FRAGMENTS_RECEIVED) + .clone() + .into_iter() + .collect::>(), + )) +} + +#[utoipa::path( + post, + path = "/v1/send", + responses( + (status = 200, description = "Sends a message to itself through the mixnet", body = String), + ) +)] +pub async fn send_handler(State(state): State) -> Result { + send_receive_mixnet(state).await +} + +#[utoipa::path( + get, + path = "/v1/mermaid", + responses( + (status = 200, description = "Returns entire tested network graph in `mermaid` format", body = String), + ) +)] +pub async fn mermaid_handler() -> Result { + let account = NetworkAccount::finalize().map_err(|_| StatusCode::INTERNAL_SERVER_ERROR)?; + let mut mermaid = String::new(); + mermaid.push_str("flowchart LR;\n"); + for route in account.complete_routes() { + mermaid.push_str( + route + .iter() + .map(|n| n.to_string()) + .collect::>() + .join("-->") + .as_str(), + ); + mermaid.push('\n') + } + for route in account.incomplete_routes() { + mermaid.push_str( + route + .iter() + .map(|n| n.to_string()) + .collect::>() + .join("-- ❌ -->") + .as_str(), + ); + mermaid.push('\n') + } + Ok(mermaid) +} + +async fn send_receive_mixnet(state: AppState) -> Result { + let msg: String = rand::thread_rng() + .sample_iter(&Alphanumeric) + .take(32) + .map(char::from) + .collect(); + let sent_msg = msg.clone(); + + let client = { + let mut clients = state.clients().write().await; + if let Some(client) = clients.make_contiguous().choose(&mut rand::thread_rng()) { + Arc::clone(client) + } else { + error!("No clients currently available"); + return Err(StatusCode::INTERNAL_SERVER_ERROR); + } + }; + + let recv = Arc::clone(&client); + let sender = Arc::clone(&client); + + let recv_handle = tokio::spawn(async move { + match timeout( + Duration::from_secs(*MIXNET_TIMEOUT.get().expect("Set at the begining")), + recv.write().await.next(), + ) + .await + { + Ok(Some(received)) => { + debug!("Received: {}", String::from_utf8_lossy(&received.message)); + } + Ok(None) => debug!("No message received"), + Err(e) => warn!("Failed to receive message: {e}"), + } + }); + + let send_handle = tokio::spawn(async move { + let mixnet_sender = sender.read().await.split_sender(); + let our_address = *sender.read().await.nym_address(); + match timeout( + Duration::from_secs(5), + mixnet_sender.send_plain_message(our_address, &msg), + ) + .await + { + Ok(_) => debug!("Sent message: {msg}"), + Err(e) => warn!("Failed to send message: {e}"), + }; + }); + + let results = futures::future::join_all(vec![send_handle, recv_handle]).await; + for result in results { + match result { + Ok(_) => {} + Err(e) => { + error!("Failed to send/receive message: {e}"); + return Err(StatusCode::INTERNAL_SERVER_ERROR); + } + } + } + + Ok(sent_msg) +} + +fn generate_dot(mix_id: Option) -> Result { + let account = NetworkAccount::finalize().map_err(|_| StatusCode::INTERNAL_SERVER_ERROR)?; + let mut nodes = HashSet::new(); + let mut edges: Vec<(u32, u32)> = vec![]; + let mut broken_edges: Vec<(u32, u32)> = vec![]; + + let mix_id = mix_id.unwrap_or(0); + + for route in account.complete_routes().iter() { + if mix_id == 0 || route.contains(&mix_id) { + for window in route.windows(2) { + nodes.insert(window[0]); + nodes.insert(window[1]); + edges.push((window[0], window[1])); + } + } + } + + for route in account.incomplete_routes().iter() { + if mix_id == 0 || route.contains(&mix_id) { + for window in route.windows(2) { + nodes.insert(window[0]); + nodes.insert(window[1]); + broken_edges.push((window[0], window[1])); + } + } + } + + let mut graph = Graph::new(); + + let node_indices: HashMap = nodes + .iter() + .map(|node| (*node, graph.add_node(*node))) + .collect(); + + for (from, to) in edges { + graph.add_edge(node_indices[&from], node_indices[&to], ""); + } + + for (from, to) in broken_edges { + graph.add_edge(node_indices[&from], node_indices[&to], "❌"); + } + + let dot = Dot::new(&graph); + Ok(dot.to_string()) +} diff --git a/nym-network-monitor/src/http.rs b/nym-network-monitor/src/http.rs new file mode 100644 index 0000000000..7255656344 --- /dev/null +++ b/nym-network-monitor/src/http.rs @@ -0,0 +1,94 @@ +use crate::accounting::{NetworkAccount, NetworkAccountStats, NodeStats}; +use crate::handlers::{ + accounting_handler, all_nodes_stats_handler, graph_handler, mermaid_handler, mix_dot_handler, + node_stats_handler, recv_handler, send_handler, sent_handler, stats_handler, FragmentsReceived, + FragmentsSent, +}; +use axum::routing::{get, post}; +use axum::Router; +use log::info; +use nym_sphinx::chunking::fragment::FragmentHeader; +use nym_sphinx::chunking::{ReceivedFragment, SentFragment}; +use std::net::SocketAddr; +use tokio_util::sync::CancellationToken; +use utoipa::OpenApi; +use utoipa_swagger_ui::SwaggerUi; + +use crate::ClientsWrapper; + +pub struct HttpServer { + listener: SocketAddr, + cancel: CancellationToken, +} + +#[derive(OpenApi)] +#[openapi( + paths( + crate::handlers::accounting_handler, + crate::handlers::graph_handler, + crate::handlers::mermaid_handler, + crate::handlers::mix_dot_handler, + crate::handlers::node_stats_handler, + crate::handlers::recv_handler, + crate::handlers::send_handler, + crate::handlers::sent_handler, + crate::handlers::all_nodes_stats_handler, + ), + components(schemas( + FragmentHeader, + FragmentsReceived, + FragmentsSent, + NetworkAccount, + NetworkAccountStats, + NodeStats, + ReceivedFragment, + SentFragment, + )) +)] +struct ApiDoc; + +#[derive(Clone)] +pub struct AppState { + clients: ClientsWrapper, +} + +impl AppState { + pub fn clients(&self) -> &ClientsWrapper { + &self.clients + } +} + +impl HttpServer { + pub fn new(listener: SocketAddr, cancel: CancellationToken) -> Self { + HttpServer { listener, cancel } + } + + pub async fn run(self, clients: ClientsWrapper) -> anyhow::Result<()> { + let n_clients = clients.read().await.len(); + let state = AppState { clients }; + let app = Router::new() + .route("/v1/send", post(send_handler).with_state(state)) + .merge(SwaggerUi::new("/v1/ui").url("/v1/docs/openapi.json", ApiDoc::openapi())) + .route("/v1/accounting", get(accounting_handler)) + .route("/v1/sent", get(sent_handler)) + .route("/v1/dot/:mix_id", get(mix_dot_handler)) + .route("/v1/dot", get(graph_handler)) + .route("/v1/mermaid", get(mermaid_handler)) + .route("/v1/stats", get(stats_handler)) + .route("/v1/node_stats/:mix_id", get(node_stats_handler)) + .route("/v1/node_stats", get(all_nodes_stats_handler)) + .route("/v1/received", get(recv_handler)); + let listener = tokio::net::TcpListener::bind(self.listener).await?; + + let server_future = + axum::serve(listener, app).with_graceful_shutdown(self.cancel.cancelled_owned()); + + info!("##########################################################################################"); + info!("######################### HTTP server running, with {} clients ############################################", n_clients); + info!("##########################################################################################"); + + server_future.await?; + + Ok(()) + } +} diff --git a/nym-network-monitor/src/main.rs b/nym-network-monitor/src/main.rs new file mode 100644 index 0000000000..d2ad40707e --- /dev/null +++ b/nym-network-monitor/src/main.rs @@ -0,0 +1,214 @@ +use crate::http::HttpServer; +use accounting::submit_metrics; +use anyhow::Result; +use clap::Parser; +use log::{info, warn}; +use nym_crypto::asymmetric::ed25519::PrivateKey; +use nym_network_defaults::setup_env; +use nym_network_defaults::var_names::NYM_API; +use nym_sdk::mixnet::{self, MixnetClient}; +use nym_topology::{HardcodedTopologyProvider, NymTopology}; +use std::fs::File; +use std::io::Write; +use std::sync::LazyLock; +use std::time::Duration; +use std::{ + collections::VecDeque, + net::{IpAddr, Ipv4Addr, SocketAddr}, + str::FromStr, + sync::Arc, +}; +use tokio::sync::OnceCell; +use tokio::{signal::ctrl_c, sync::RwLock}; +use tokio_util::sync::CancellationToken; + +static NYM_API_URL: LazyLock = LazyLock::new(|| { + std::env::var(NYM_API).unwrap_or_else(|_| panic!("{} env var not set", NYM_API)) +}); + +static MIXNET_TIMEOUT: OnceCell = OnceCell::const_new(); +static TOPOLOGY: OnceCell = OnceCell::const_new(); +static PRIVATE_KEY: OnceCell = OnceCell::const_new(); + +mod accounting; +mod handlers; +mod http; + +/// Simple program to greet a person +pub type ClientsWrapper = Arc>>>>; + +async fn make_clients( + clients: ClientsWrapper, + n_clients: usize, + lifetime: u64, + topology: NymTopology, +) { + loop { + let spawned_clients = clients.read().await.len(); + info!("Currently spawned clients: {}", spawned_clients); + // If we have enough clients, sleep for a minute and remove the oldest one + if spawned_clients >= n_clients { + info!("New client will be spawned in {} seconds", lifetime); + tokio::time::sleep(tokio::time::Duration::from_secs(lifetime)).await; + info!("Removing oldest client"); + if let Some(dropped_client) = clients.write().await.pop_front() { + loop { + if Arc::strong_count(&dropped_client) == 1 { + if let Some(client) = Arc::into_inner(dropped_client) { + client.into_inner().disconnect().await; + } else { + warn!("Failed to drop client, client had more then one strong ref") + } + break; + } + info!("Client still in use, waiting 2 seconds"); + tokio::time::sleep(tokio::time::Duration::from_secs(2)).await; + } + } + } + info!("Spawning new client"); + let client = match make_client(topology.clone()).await { + Ok(client) => client, + Err(err) => { + warn!("{}, moving on", err); + continue; + } + }; + clients + .write() + .await + .push_back(Arc::new(RwLock::new(client))); + } +} + +async fn make_client(topology: NymTopology) -> Result { + let net = mixnet::NymNetworkDetails::new_from_env(); + let topology_provider = Box::new(HardcodedTopologyProvider::new(topology)); + let mixnet_client = mixnet::MixnetClientBuilder::new_ephemeral() + .network_details(net) + .custom_topology_provider(topology_provider) + // .enable_credentials_mode() + .build()?; + + let client = mixnet_client.connect_to_mixnet().await?; + Ok(client) +} + +#[derive(Parser, Debug)] +#[command(version, about, long_about = None)] +struct Args { + /// Number of clients to spawn + #[arg(short = 'C', long = "clients", default_value_t = 10)] + n_clients: usize, + + /// Lifetime of each client in seconds + #[arg(short = 'T', long, default_value_t = 60)] + client_lifetime: u64, + + /// Port to listen on + #[arg(long, default_value_t = 8080)] + port: u16, + + /// Host to listen on + #[arg(long, default_value = "127.0.0.1")] + host: String, + + /// Path to the topology file + #[arg(short, long, default_value = None)] + topology: Option, + + /// Path to the environment file + #[arg(short, long, default_value = None)] + env: Option, + + #[arg(short, long, default_value_t = 10)] + mixnet_timeout: u64, + + #[arg(long, default_value_t = false)] + generate_key_pair: bool, + + #[arg(long)] + private_key: String, +} + +fn generate_key_pair() -> Result<()> { + let mut rng = rand::thread_rng(); + let keypair = nym_crypto::asymmetric::identity::KeyPair::new(&mut rng); + + let mut public_key_file = File::create("network-monitor-public")?; + public_key_file.write_all(keypair.public_key().to_base58_string().as_bytes())?; + + let mut private_key_file = File::create("network-monitor-private")?; + private_key_file.write_all(keypair.private_key().to_base58_string().as_bytes())?; + + info!("Generated keypair, public key to 'network-monitor-public', and private key to 'network-monitor-private', public key should be whitelisted with the nym-api"); + + Ok(()) +} + +#[tokio::main] +async fn main() -> Result<()> { + nym_bin_common::logging::setup_logging(); + + let args = Args::parse(); + + setup_env(args.env); // Defaults to mainnet if empty + + let cancel_token = CancellationToken::new(); + let server_cancel_token = cancel_token.clone(); + let clients = Arc::new(RwLock::new(VecDeque::with_capacity(args.n_clients))); + + if args.generate_key_pair { + generate_key_pair()?; + std::process::exit(0); + } + + let pk = PrivateKey::from_base58_string(&args.private_key)?; + PRIVATE_KEY.set(pk).ok(); + + TOPOLOGY + .set(if let Some(topology_file) = args.topology { + NymTopology::new_from_file(topology_file)? + } else { + NymTopology::new_from_env().await? + }) + .ok(); + + MIXNET_TIMEOUT.set(args.mixnet_timeout).ok(); + + let spawn_clients = Arc::clone(&clients); + tokio::spawn(make_clients( + spawn_clients, + args.n_clients, + args.client_lifetime, + TOPOLOGY.get().expect("Topology not set yet!").clone(), + )); + + let server_handle = tokio::spawn(async move { + let socket = SocketAddr::new(IpAddr::V4(Ipv4Addr::from_str(&args.host)?), args.port); + let server = HttpServer::new(socket, server_cancel_token); + server.run(clients).await + }); + + info!("Waiting for message (ctrl-c to exit)"); + + loop { + match tokio::time::timeout(Duration::from_secs(600), ctrl_c()).await { + Ok(_) => { + info!("Received kill signal, shutting down, submitting final batch of metrics"); + submit_metrics().await?; + break; + } + Err(_) => { + info!("Submitting metrics, cleaning metric buffers"); + submit_metrics().await?; + } + }; + } + + cancel_token.cancel(); + + server_handle.await??; + + Ok(()) +} diff --git a/sdk/rust/nym-sdk/src/mixnet/client.rs b/sdk/rust/nym-sdk/src/mixnet/client.rs index 7d26b1f9aa..22cf485b33 100644 --- a/sdk/rust/nym-sdk/src/mixnet/client.rs +++ b/sdk/rust/nym-sdk/src/mixnet/client.rs @@ -625,7 +625,8 @@ where /// /// - If the client is already registered with a gateway, use that gateway. /// - If no gateway is registered, but there is an existing configuration and key, use that. - /// - If no gateway is registered, and there is no pre-existing configuration or key, try to register a new gateway. + /// - If no gateway is registered, and there is no pre-existing configuration or key, try to + /// register a new gateway. /// /// # Example /// @@ -705,7 +706,8 @@ where /// /// - If the client is already registered with a gateway, use that gateway. /// - If no gateway is registered, but there is an existing configuration and key, use that. - /// - If no gateway is registered, and there is no pre-existing configuration or key, try to register a new gateway. + /// - If no gateway is registered, and there is no pre-existing configuration or key, try to + /// register a new gateway. /// /// # Example /// @@ -727,7 +729,8 @@ where let (mut started_client, nym_address) = self.connect_to_mixnet_common().await?; let client_input = started_client.client_input.register_producer(); let mut client_output = started_client.client_output.register_consumer(); - let client_state = started_client.client_state; + let client_state: nym_client_core::client::base_client::ClientState = + started_client.client_state; let identity_keys = started_client.identity_keys.clone(); let reconstructed_receiver = client_output.register_receiver()?; diff --git a/tools/nymvisor/src/tasks/launcher/mod.rs b/tools/nymvisor/src/tasks/launcher/mod.rs index 74e9195d8c..83eb804140 100644 --- a/tools/nymvisor/src/tasks/launcher/mod.rs +++ b/tools/nymvisor/src/tasks/launcher/mod.rs @@ -176,7 +176,7 @@ impl DaemonLauncher { info!("it finished with the following exit status: {exit_status}"); return Ok(false) } - event = &mut self.upgrade_plan_watcher.next() => { + event = self.upgrade_plan_watcher.next() => { let Some(event) = event else { // this is a critical failure since the file watcher task should NEVER terminate by itself error!("CRITICAL FAILURE: the upgrade plan watcher channel got closed"); From 72c86ebe7c93ab7ccee54a29d8fd1ccafd2321a1 Mon Sep 17 00:00:00 2001 From: =?UTF-8?q?Jon=20H=C3=A4ggblad?= Date: Mon, 26 Aug 2024 13:59:11 +0200 Subject: [PATCH 21/93] Fix clippy for unwrap_or_default (#4783) --- common/types/src/monitoring.rs | 5 +---- 1 file changed, 1 insertion(+), 4 deletions(-) diff --git a/common/types/src/monitoring.rs b/common/types/src/monitoring.rs index f98d548446..7769e61384 100644 --- a/common/types/src/monitoring.rs +++ b/common/types/src/monitoring.rs @@ -73,10 +73,7 @@ pub struct MonitorMessage { impl MonitorMessage { fn message_to_sign(results: &[NodeResult], timestamp: i64) -> Vec { - let mut msg = match serde_json::to_vec(results) { - Ok(msg) => msg, - Err(_) => Vec::new(), - }; + let mut msg = serde_json::to_vec(results).unwrap_or_default(); msg.extend_from_slice(×tamp.to_le_bytes()); msg } From f2d354f6ecf7f23d92c10194741dcdec955d37c7 Mon Sep 17 00:00:00 2001 From: =?UTF-8?q?Jon=20H=C3=A4ggblad?= Date: Mon, 26 Aug 2024 14:07:16 +0200 Subject: [PATCH 22/93] Enable dependabot version upgrades for root rust workspace (#4778) * Enable dependabot version upgrades for root rust workspace * Group patch updates * Fix syntax * Add explicit time * Set it to 12:20 during testing --- .github/dependabot.yml | 16 ++++++++++++++++ 1 file changed, 16 insertions(+) diff --git a/.github/dependabot.yml b/.github/dependabot.yml index b9ba159f7f..3859c6f19c 100644 --- a/.github/dependabot.yml +++ b/.github/dependabot.yml @@ -14,3 +14,19 @@ updates: prefix: build prefix-development: chore include: scope + # Update the root workspace (only). For now we don't include + # the contracts workspcae. + - package-ecosystem: cargo + directory: / + schedule: + interval: weekly + time: "12:20" + ignore: + - dependency-name: "cosmwasm-*" + - dependency-name: "cw*" + groups: + patch-updates: + patterns: + - "*" + update-types: + - "patch" From d859ad0a516e72c64bad7ce732dc570ad954e32f Mon Sep 17 00:00:00 2001 From: "dependabot[bot]" <49699333+dependabot[bot]@users.noreply.github.com> Date: Mon, 26 Aug 2024 14:25:32 +0200 Subject: [PATCH 23/93] build(deps): bump arduino/setup-protoc from 2 to 3 (#4788) Bumps [arduino/setup-protoc](https://github.com/arduino/setup-protoc) from 2 to 3. - [Release notes](https://github.com/arduino/setup-protoc/releases) - [Commits](https://github.com/arduino/setup-protoc/compare/v2...v3) --- updated-dependencies: - dependency-name: arduino/setup-protoc dependency-type: direct:production update-type: version-update:semver-major ... Signed-off-by: dependabot[bot] Co-authored-by: dependabot[bot] <49699333+dependabot[bot]@users.noreply.github.com> --- .github/workflows/nightly-build.yml | 2 +- 1 file changed, 1 insertion(+), 1 deletion(-) diff --git a/.github/workflows/nightly-build.yml b/.github/workflows/nightly-build.yml index 3cadf150a2..f529f62a9e 100644 --- a/.github/workflows/nightly-build.yml +++ b/.github/workflows/nightly-build.yml @@ -33,7 +33,7 @@ jobs: components: rustfmt, clippy - name: Install Protoc - uses: arduino/setup-protoc@v2 + uses: arduino/setup-protoc@v3 if: matrix.os == 'macos-latest' || matrix.os == 'windows-latest' with: repo-token: ${{ secrets.GITHUB_TOKEN }} From 519d999785896d3a2230bf192024d16cbeefd002 Mon Sep 17 00:00:00 2001 From: =?UTF-8?q?Jon=20H=C3=A4ggblad?= Date: Mon, 26 Aug 2024 15:59:25 +0200 Subject: [PATCH 24/93] Update dependabot (#4796) * Bump max number of dependabot rust PRs to 10 * Add readme entry to workspace package --- .github/dependabot.yml | 3 ++- Cargo.toml | 1 + 2 files changed, 3 insertions(+), 1 deletion(-) diff --git a/.github/dependabot.yml b/.github/dependabot.yml index 3859c6f19c..37d85d98d0 100644 --- a/.github/dependabot.yml +++ b/.github/dependabot.yml @@ -20,7 +20,7 @@ updates: directory: / schedule: interval: weekly - time: "12:20" + time: "09:00" ignore: - dependency-name: "cosmwasm-*" - dependency-name: "cw*" @@ -30,3 +30,4 @@ updates: - "*" update-types: - "patch" + open-pull-requests-limit: 10 diff --git a/Cargo.toml b/Cargo.toml index f100358f0d..3a4af4b32d 100644 --- a/Cargo.toml +++ b/Cargo.toml @@ -160,6 +160,7 @@ documentation = "https://nymtech.net" edition = "2021" license = "Apache-2.0" rust-version = "1.80" +readme = "README.md" [workspace.dependencies] addr = "0.15.6" From 92a1fb514f55f75c0b0204af0126d969f8491647 Mon Sep 17 00:00:00 2001 From: "dependabot[bot]" <49699333+dependabot[bot]@users.noreply.github.com> Date: Mon, 26 Aug 2024 16:08:58 +0200 Subject: [PATCH 25/93] build(deps): bump dtolnay/rust-toolchain from 1.70.0 to 1.90.0 (#4797) Bumps [dtolnay/rust-toolchain](https://github.com/dtolnay/rust-toolchain) from 1.70.0 to 1.90.0. - [Release notes](https://github.com/dtolnay/rust-toolchain/releases) - [Commits](https://github.com/dtolnay/rust-toolchain/compare/1.70.0...1.90.0) --- updated-dependencies: - dependency-name: dtolnay/rust-toolchain dependency-type: direct:production update-type: version-update:semver-minor ... Signed-off-by: dependabot[bot] Co-authored-by: dependabot[bot] <49699333+dependabot[bot]@users.noreply.github.com> --- .github/workflows/publish-nyms5-android-apk.yml | 2 +- 1 file changed, 1 insertion(+), 1 deletion(-) diff --git a/.github/workflows/publish-nyms5-android-apk.yml b/.github/workflows/publish-nyms5-android-apk.yml index 06f4c6c126..501cf7a42a 100644 --- a/.github/workflows/publish-nyms5-android-apk.yml +++ b/.github/workflows/publish-nyms5-android-apk.yml @@ -49,7 +49,7 @@ jobs: "build-tools;$SDK_BUILDTOOLS_VERSION" - name: Install Rust toolchain - uses: dtolnay/rust-toolchain@1.70.0 + uses: dtolnay/rust-toolchain@1.90.0 - name: Install rust android targets run: | From 5498bee893941f10368eab5d3336d2ed00936927 Mon Sep 17 00:00:00 2001 From: "dependabot[bot]" <49699333+dependabot[bot]@users.noreply.github.com> Date: Mon, 26 Aug 2024 16:15:09 +0200 Subject: [PATCH 26/93] build(deps): bump actions/configure-pages from 3 to 5 (#4798) Bumps [actions/configure-pages](https://github.com/actions/configure-pages) from 3 to 5. - [Release notes](https://github.com/actions/configure-pages/releases) - [Commits](https://github.com/actions/configure-pages/compare/v3...v5) --- updated-dependencies: - dependency-name: actions/configure-pages dependency-type: direct:production update-type: version-update:semver-major ... Signed-off-by: dependabot[bot] Co-authored-by: dependabot[bot] <49699333+dependabot[bot]@users.noreply.github.com> --- .github/workflows/deploy-github-pages.yml | 2 +- 1 file changed, 1 insertion(+), 1 deletion(-) diff --git a/.github/workflows/deploy-github-pages.yml b/.github/workflows/deploy-github-pages.yml index 7c7e689ee5..dda2ca57e6 100644 --- a/.github/workflows/deploy-github-pages.yml +++ b/.github/workflows/deploy-github-pages.yml @@ -32,7 +32,7 @@ jobs: - name: Checkout uses: actions/checkout@v3 - name: Setup Pages - uses: actions/configure-pages@v3 + uses: actions/configure-pages@v5 - name: Upload artifact uses: actions/upload-pages-artifact@v2 with: From 40e72ce37afee73fd827a171cfc5280597c20e19 Mon Sep 17 00:00:00 2001 From: "dependabot[bot]" <49699333+dependabot[bot]@users.noreply.github.com> Date: Tue, 27 Aug 2024 08:55:19 +0200 Subject: [PATCH 27/93] build(deps): bump actions/checkout from 2 to 4 (#4800) Bumps [actions/checkout](https://github.com/actions/checkout) from 2 to 4. - [Release notes](https://github.com/actions/checkout/releases) - [Changelog](https://github.com/actions/checkout/blob/main/CHANGELOG.md) - [Commits](https://github.com/actions/checkout/compare/v2...v4) --- updated-dependencies: - dependency-name: actions/checkout dependency-type: direct:production update-type: version-update:semver-major ... Signed-off-by: dependabot[bot] Co-authored-by: dependabot[bot] <49699333+dependabot[bot]@users.noreply.github.com> --- .github/workflows/cd-docs.yml | 2 +- .github/workflows/ci-binary-config-checker.yml | 2 +- .github/workflows/ci-build-ts.yml | 2 +- .github/workflows/ci-build-upload-binaries.yml | 2 +- .github/workflows/ci-build.yml | 2 +- .github/workflows/ci-cargo-deny.yml | 2 +- .github/workflows/ci-contracts-schema.yml | 2 +- .github/workflows/ci-contracts-upload-binaries.yml | 2 +- .github/workflows/ci-contracts.yml | 4 ++-- .github/workflows/ci-docs.yml | 2 +- .github/workflows/ci-lint-typescript.yml | 2 +- .github/workflows/ci-nym-api-tests.yml | 2 +- .github/workflows/ci-nym-network-explorer.yml | 2 +- .github/workflows/ci-nym-wallet-rust.yml | 2 +- .github/workflows/ci-nym-wallet-storybook.yml | 2 +- .github/workflows/ci-sdk-docs-typescript.yml | 2 +- .github/workflows/ci-sdk-wasm.yml | 2 +- .github/workflows/deploy-github-pages.yml | 2 +- .github/workflows/nightly-build.yml | 4 ++-- .github/workflows/nightly-check-merge-conflicts.yml | 6 +++--- .github/workflows/nightly-nym-wallet-build.yml | 4 ++-- .github/workflows/nightly-security-audit.yml | 4 ++-- .github/workflows/publish-nym-binaries.yml | 2 +- .github/workflows/publish-nym-contracts.yml | 2 +- .github/workflows/publish-nym-wallet-macos.yml | 2 +- .github/workflows/publish-nym-wallet-ubuntu.yml | 2 +- .github/workflows/publish-nym-wallet-win10.yml | 2 +- .github/workflows/publish-nyms5-android-apk.yml | 4 ++-- .github/workflows/publish-sdk-npm.yml | 2 +- .github/workflows/release-calculate-hash.yml | 2 +- 30 files changed, 37 insertions(+), 37 deletions(-) diff --git a/.github/workflows/cd-docs.yml b/.github/workflows/cd-docs.yml index aad003b7cd..8d2ac55071 100644 --- a/.github/workflows/cd-docs.yml +++ b/.github/workflows/cd-docs.yml @@ -7,7 +7,7 @@ jobs: build: runs-on: ubuntu-20.04-16-core steps: - - uses: actions/checkout@v3 + - uses: actions/checkout@v4 - name: Install Dependencies (Linux) run: sudo apt-get update && sudo apt-get install -y build-essential curl wget libssl-dev libudev-dev squashfs-tools protobuf-compiler git python3 && sudo apt-get update --fix-missing - name: Install pip3 diff --git a/.github/workflows/ci-binary-config-checker.yml b/.github/workflows/ci-binary-config-checker.yml index 07e14d6738..fc151c73dd 100644 --- a/.github/workflows/ci-binary-config-checker.yml +++ b/.github/workflows/ci-binary-config-checker.yml @@ -35,7 +35,7 @@ jobs: runs-on: ${{ matrix.platform }} steps: - - uses: actions/checkout@v3 + - uses: actions/checkout@v4 - name: Install Dependencies (Linux) run: sudo apt-get update && sudo apt-get -y install jq vim libwebkit2gtk-4.0-dev build-essential curl wget libssl-dev libgtk-3-dev libudev-dev squashfs-tools diff --git a/.github/workflows/ci-build-ts.yml b/.github/workflows/ci-build-ts.yml index 9dd6f238a2..9920f02540 100644 --- a/.github/workflows/ci-build-ts.yml +++ b/.github/workflows/ci-build-ts.yml @@ -10,7 +10,7 @@ jobs: build: runs-on: ubuntu-20.04-16-core steps: - - uses: actions/checkout@v2 + - uses: actions/checkout@v4 - name: Install rsync run: sudo apt-get install rsync continue-on-error: true diff --git a/.github/workflows/ci-build-upload-binaries.yml b/.github/workflows/ci-build-upload-binaries.yml index 00c28191bd..5784398f07 100644 --- a/.github/workflows/ci-build-upload-binaries.yml +++ b/.github/workflows/ci-build-upload-binaries.yml @@ -43,7 +43,7 @@ jobs: env: CARGO_TERM_COLOR: always steps: - - uses: actions/checkout@v3 + - uses: actions/checkout@v4 - name: Prepare build output directory shell: bash diff --git a/.github/workflows/ci-build.yml b/.github/workflows/ci-build.yml index 19d5fc327e..710b1e0d95 100644 --- a/.github/workflows/ci-build.yml +++ b/.github/workflows/ci-build.yml @@ -53,7 +53,7 @@ jobs: if: matrix.os == 'custom-linux' - name: Check out repository code - uses: actions/checkout@v2 + uses: actions/checkout@v4 - name: Install rust toolchain uses: actions-rs/toolchain@v1 diff --git a/.github/workflows/ci-cargo-deny.yml b/.github/workflows/ci-cargo-deny.yml index ab35b5fbf5..e695c17e51 100644 --- a/.github/workflows/ci-cargo-deny.yml +++ b/.github/workflows/ci-cargo-deny.yml @@ -13,7 +13,7 @@ jobs: - licenses bans sources steps: - - uses: actions/checkout@v3 + - uses: actions/checkout@v4 - uses: EmbarkStudios/cargo-deny-action@v1 with: log-level: warn diff --git a/.github/workflows/ci-contracts-schema.yml b/.github/workflows/ci-contracts-schema.yml index cb37e5d799..5f5ea4e538 100644 --- a/.github/workflows/ci-contracts-schema.yml +++ b/.github/workflows/ci-contracts-schema.yml @@ -15,7 +15,7 @@ jobs: CARGO_TERM_COLOR: always steps: - name: Check out repository code - uses: actions/checkout@v2 + uses: actions/checkout@v4 - name: Install Rust toolchain uses: actions-rs/toolchain@v1 diff --git a/.github/workflows/ci-contracts-upload-binaries.yml b/.github/workflows/ci-contracts-upload-binaries.yml index 14d0b63eae..77899f495a 100644 --- a/.github/workflows/ci-contracts-upload-binaries.yml +++ b/.github/workflows/ci-contracts-upload-binaries.yml @@ -21,7 +21,7 @@ jobs: env: CARGO_TERM_COLOR: always steps: - - uses: actions/checkout@v3 + - uses: actions/checkout@v4 - name: Prepare build output directory shell: bash diff --git a/.github/workflows/ci-contracts.yml b/.github/workflows/ci-contracts.yml index a88795c313..cb88ca85f3 100644 --- a/.github/workflows/ci-contracts.yml +++ b/.github/workflows/ci-contracts.yml @@ -17,7 +17,7 @@ jobs: matrix: ${{ steps.set-matrix.outputs.matrix }} steps: # creates the matrix strategy from ci-contracts-matrix-includes.json - - uses: actions/checkout@v2 + - uses: actions/checkout@v4 - id: set-matrix uses: JoshuaTheMiller/conditional-build-matrix@main with: @@ -34,7 +34,7 @@ jobs: fail-fast: false matrix: ${{fromJson(needs.matrix_prep.outputs.matrix)}} steps: - - uses: actions/checkout@v2 + - uses: actions/checkout@v4 - name: Setup rust uses: actions-rs/toolchain@v1 diff --git a/.github/workflows/ci-docs.yml b/.github/workflows/ci-docs.yml index 8c3da78984..44bc46ee85 100644 --- a/.github/workflows/ci-docs.yml +++ b/.github/workflows/ci-docs.yml @@ -11,7 +11,7 @@ jobs: build: runs-on: ubuntu-20.04-16-core steps: - - uses: actions/checkout@v3 + - uses: actions/checkout@v4 - name: Install Dependencies (Linux) run: sudo apt-get update && sudo apt-get install -y build-essential curl wget libssl-dev libudev-dev squashfs-tools protobuf-compiler git python3 && sudo apt-get update --fix-missing - name: Install pip3 diff --git a/.github/workflows/ci-lint-typescript.yml b/.github/workflows/ci-lint-typescript.yml index fec923c03d..bd658b0a15 100644 --- a/.github/workflows/ci-lint-typescript.yml +++ b/.github/workflows/ci-lint-typescript.yml @@ -15,7 +15,7 @@ jobs: build: runs-on: ubuntu-20.04-16-core steps: - - uses: actions/checkout@v2 + - uses: actions/checkout@v4 - uses: rlespinasse/github-slug-action@v3.x - uses: actions/setup-node@v3 diff --git a/.github/workflows/ci-nym-api-tests.yml b/.github/workflows/ci-nym-api-tests.yml index 8953956478..508e2718fc 100644 --- a/.github/workflows/ci-nym-api-tests.yml +++ b/.github/workflows/ci-nym-api-tests.yml @@ -15,7 +15,7 @@ jobs: name: nym-api tests runs-on: ubuntu-latest steps: - - uses: actions/checkout@v2 + - uses: actions/checkout@v4 - name: install yarn in root run: cd ../.. && yarn install diff --git a/.github/workflows/ci-nym-network-explorer.yml b/.github/workflows/ci-nym-network-explorer.yml index 04bf1f7688..4b39cd565a 100644 --- a/.github/workflows/ci-nym-network-explorer.yml +++ b/.github/workflows/ci-nym-network-explorer.yml @@ -14,7 +14,7 @@ jobs: build: runs-on: custom-linux steps: - - uses: actions/checkout@v2 + - uses: actions/checkout@v4 - name: Install rsync run: sudo apt-get install rsync continue-on-error: true diff --git a/.github/workflows/ci-nym-wallet-rust.yml b/.github/workflows/ci-nym-wallet-rust.yml index 8f865195e7..d9001ff24d 100644 --- a/.github/workflows/ci-nym-wallet-rust.yml +++ b/.github/workflows/ci-nym-wallet-rust.yml @@ -25,7 +25,7 @@ jobs: continue-on-error: true - name: Check out repository code - uses: actions/checkout@v2 + uses: actions/checkout@v4 - name: Install rust toolchain uses: actions-rs/toolchain@v1 diff --git a/.github/workflows/ci-nym-wallet-storybook.yml b/.github/workflows/ci-nym-wallet-storybook.yml index 9ba9cd3d9f..c830deed9e 100644 --- a/.github/workflows/ci-nym-wallet-storybook.yml +++ b/.github/workflows/ci-nym-wallet-storybook.yml @@ -9,7 +9,7 @@ jobs: build: runs-on: custom-linux steps: - - uses: actions/checkout@v2 + - uses: actions/checkout@v4 - name: Install rsync run: sudo apt-get install rsync diff --git a/.github/workflows/ci-sdk-docs-typescript.yml b/.github/workflows/ci-sdk-docs-typescript.yml index 8e734def63..937b07f2f3 100644 --- a/.github/workflows/ci-sdk-docs-typescript.yml +++ b/.github/workflows/ci-sdk-docs-typescript.yml @@ -10,7 +10,7 @@ jobs: build: runs-on: custom-linux steps: - - uses: actions/checkout@v2 + - uses: actions/checkout@v4 - name: Install rsync run: sudo apt-get install rsync continue-on-error: true diff --git a/.github/workflows/ci-sdk-wasm.yml b/.github/workflows/ci-sdk-wasm.yml index 074083042d..16e402ab6c 100644 --- a/.github/workflows/ci-sdk-wasm.yml +++ b/.github/workflows/ci-sdk-wasm.yml @@ -13,7 +13,7 @@ jobs: env: CARGO_TERM_COLOR: always steps: - - uses: actions/checkout@v2 + - uses: actions/checkout@v4 - uses: actions/setup-node@v3 with: diff --git a/.github/workflows/deploy-github-pages.yml b/.github/workflows/deploy-github-pages.yml index dda2ca57e6..2846188d90 100644 --- a/.github/workflows/deploy-github-pages.yml +++ b/.github/workflows/deploy-github-pages.yml @@ -30,7 +30,7 @@ jobs: runs-on: ubuntu-latest steps: - name: Checkout - uses: actions/checkout@v3 + uses: actions/checkout@v4 - name: Setup Pages uses: actions/configure-pages@v5 - name: Upload artifact diff --git a/.github/workflows/nightly-build.yml b/.github/workflows/nightly-build.yml index f529f62a9e..5049401781 100644 --- a/.github/workflows/nightly-build.yml +++ b/.github/workflows/nightly-build.yml @@ -18,7 +18,7 @@ jobs: continue-on-error: true steps: - name: Check out repository code - uses: actions/checkout@v3 + uses: actions/checkout@v4 - name: Install Dependencies (Linux) run: sudo apt-get update && sudo apt-get install -y build-essential curl wget libssl-dev libudev-dev squashfs-tools protobuf-compiler @@ -100,7 +100,7 @@ jobs: - name: Collect jobs status uses: technote-space/workflow-conclusion-action@v2 - name: Check out repository code - uses: actions/checkout@v3 + uses: actions/checkout@v4 - name: install npm uses: actions/setup-node@v3 if: env.WORKFLOW_CONCLUSION == 'failure' diff --git a/.github/workflows/nightly-check-merge-conflicts.yml b/.github/workflows/nightly-check-merge-conflicts.yml index fe03a6eda6..b9be7b98dd 100644 --- a/.github/workflows/nightly-check-merge-conflicts.yml +++ b/.github/workflows/nightly-check-merge-conflicts.yml @@ -15,7 +15,7 @@ jobs: output1: ${{ steps.step2.outputs.latest_release }} steps: - name: Check out repository code - uses: actions/checkout@v3 + uses: actions/checkout@v4 with: fetch-depth: 0 - name: Set output variable to latest release branch @@ -28,7 +28,7 @@ jobs: runs-on: ubuntu-latest steps: - name: Checkout repo - uses: actions/checkout@v3 + uses: actions/checkout@v4 with: fetch-depth: 0 - name: Setup git user @@ -47,7 +47,7 @@ jobs: runs-on: ubuntu-latest steps: - name: Checkout repo - uses: actions/checkout@v3 + uses: actions/checkout@v4 with: fetch-depth: 0 - name: Setup git user diff --git a/.github/workflows/nightly-nym-wallet-build.yml b/.github/workflows/nightly-nym-wallet-build.yml index b310ca4fa0..c98eed2fbd 100644 --- a/.github/workflows/nightly-nym-wallet-build.yml +++ b/.github/workflows/nightly-nym-wallet-build.yml @@ -18,7 +18,7 @@ jobs: continue-on-error: true steps: - name: Check out repository code - uses: actions/checkout@v3 + uses: actions/checkout@v4 - name: Install Dependencies (Linux) run: sudo apt-get update && sudo apt-get install -y libwebkit2gtk-4.0-dev build-essential curl wget libssl-dev libgtk-3-dev squashfs-tools @@ -63,7 +63,7 @@ jobs: - name: Collect jobs status uses: technote-space/workflow-conclusion-action@v2 - name: Check out repository code - uses: actions/checkout@v3 + uses: actions/checkout@v4 - name: install npm uses: actions/setup-node@v3 if: env.WORKFLOW_CONCLUSION == 'failure' diff --git a/.github/workflows/nightly-security-audit.yml b/.github/workflows/nightly-security-audit.yml index 808cc20144..8ccae9790d 100644 --- a/.github/workflows/nightly-security-audit.yml +++ b/.github/workflows/nightly-security-audit.yml @@ -8,7 +8,7 @@ jobs: runs-on: ubuntu-20.04 steps: - name: Checkout repository code - uses: actions/checkout@v2 + uses: actions/checkout@v4 - name: Install rust toolchain uses: actions-rs/toolchain@v1 with: @@ -29,7 +29,7 @@ jobs: runs-on: custom-linux steps: - name: Check out repository code - uses: actions/checkout@v2 + uses: actions/checkout@v4 - name: Download report from previous job uses: actions/download-artifact@v3 with: diff --git a/.github/workflows/publish-nym-binaries.yml b/.github/workflows/publish-nym-binaries.yml index be70c514ba..422b09dcda 100644 --- a/.github/workflows/publish-nym-binaries.yml +++ b/.github/workflows/publish-nym-binaries.yml @@ -40,7 +40,7 @@ jobs: cli_version: ${{ steps.binary-versions.outputs.cli_version }} steps: - - uses: actions/checkout@v3 + - uses: actions/checkout@v4 - name: Install Dependencies (Linux) run: sudo apt-get update && sudo apt-get -y install ripgrep libwebkit2gtk-4.0-dev build-essential curl wget libssl-dev libgtk-3-dev libudev-dev squashfs-tools diff --git a/.github/workflows/publish-nym-contracts.yml b/.github/workflows/publish-nym-contracts.yml index 493f99e8ac..de81793ad1 100644 --- a/.github/workflows/publish-nym-contracts.yml +++ b/.github/workflows/publish-nym-contracts.yml @@ -9,7 +9,7 @@ jobs: if: ${{ (startsWith(github.ref, 'refs/tags/nym-contracts-') && github.event_name == 'release') || github.event_name == 'workflow_dispatch' }} runs-on: [self-hosted, custom-ubuntu-20.04] steps: - - uses: actions/checkout@v2 + - uses: actions/checkout@v4 - name: Install Rust stable uses: actions-rs/toolchain@v1 diff --git a/.github/workflows/publish-nym-wallet-macos.yml b/.github/workflows/publish-nym-wallet-macos.yml index 4ecc48d276..d8a7a04f0b 100644 --- a/.github/workflows/publish-nym-wallet-macos.yml +++ b/.github/workflows/publish-nym-wallet-macos.yml @@ -25,7 +25,7 @@ jobs: file_hash: ${{ steps.release-info.outputs.file_hash }} steps: - - uses: actions/checkout@v2 + - uses: actions/checkout@v4 - name: Node uses: actions/setup-node@v3 diff --git a/.github/workflows/publish-nym-wallet-ubuntu.yml b/.github/workflows/publish-nym-wallet-ubuntu.yml index 1eaad9bef0..6f27780fac 100644 --- a/.github/workflows/publish-nym-wallet-ubuntu.yml +++ b/.github/workflows/publish-nym-wallet-ubuntu.yml @@ -25,7 +25,7 @@ jobs: file_hash: ${{ steps.release-info.outputs.file_hash }} steps: - - uses: actions/checkout@v2 + - uses: actions/checkout@v4 - name: Tauri dependencies run: > diff --git a/.github/workflows/publish-nym-wallet-win10.yml b/.github/workflows/publish-nym-wallet-win10.yml index 5bba585f18..0130d2b735 100644 --- a/.github/workflows/publish-nym-wallet-win10.yml +++ b/.github/workflows/publish-nym-wallet-win10.yml @@ -33,7 +33,7 @@ jobs: del /s /q /A:H nym rmdir /s /q nym - - uses: actions/checkout@v3 + - uses: actions/checkout@v4 - name: Import signing certificate env: diff --git a/.github/workflows/publish-nyms5-android-apk.yml b/.github/workflows/publish-nyms5-android-apk.yml index 501cf7a42a..da6db40ecb 100644 --- a/.github/workflows/publish-nyms5-android-apk.yml +++ b/.github/workflows/publish-nyms5-android-apk.yml @@ -22,7 +22,7 @@ jobs: steps: - name: Checkout - uses: actions/checkout@v3 + uses: actions/checkout@v4 - name: Install Java uses: actions/setup-java@v3 @@ -97,7 +97,7 @@ jobs: runs-on: custom-linux steps: - name: Checkout - uses: actions/checkout@v3 + uses: actions/checkout@v4 - name: Download binary artifact uses: actions/download-artifact@v3 with: diff --git a/.github/workflows/publish-sdk-npm.yml b/.github/workflows/publish-sdk-npm.yml index 32a8bc31f5..f6228b210a 100644 --- a/.github/workflows/publish-sdk-npm.yml +++ b/.github/workflows/publish-sdk-npm.yml @@ -6,7 +6,7 @@ jobs: publish: runs-on: ubuntu-20.04-16-core steps: - - uses: actions/checkout@v2 + - uses: actions/checkout@v4 - name: Install Node uses: actions/setup-node@v3 diff --git a/.github/workflows/release-calculate-hash.yml b/.github/workflows/release-calculate-hash.yml index fb493b8541..4b82bb3b98 100644 --- a/.github/workflows/release-calculate-hash.yml +++ b/.github/workflows/release-calculate-hash.yml @@ -20,7 +20,7 @@ jobs: runs-on: ubuntu-latest steps: - name: Check out repository code - uses: actions/checkout@v3 + uses: actions/checkout@v4 - uses: actions/setup-node@v3 with: node-version: 18 From 17686ddd9a27997889d82e9c157975d4cf8c68e1 Mon Sep 17 00:00:00 2001 From: "dependabot[bot]" <49699333+dependabot[bot]@users.noreply.github.com> Date: Tue, 27 Aug 2024 08:58:05 +0200 Subject: [PATCH 28/93] build(deps): bump actions/upload-pages-artifact from 2 to 3 (#4787) Bumps [actions/upload-pages-artifact](https://github.com/actions/upload-pages-artifact) from 2 to 3. - [Release notes](https://github.com/actions/upload-pages-artifact/releases) - [Commits](https://github.com/actions/upload-pages-artifact/compare/v2...v3) --- updated-dependencies: - dependency-name: actions/upload-pages-artifact dependency-type: direct:production update-type: version-update:semver-major ... Signed-off-by: dependabot[bot] Co-authored-by: dependabot[bot] <49699333+dependabot[bot]@users.noreply.github.com> --- .github/workflows/deploy-github-pages.yml | 2 +- 1 file changed, 1 insertion(+), 1 deletion(-) diff --git a/.github/workflows/deploy-github-pages.yml b/.github/workflows/deploy-github-pages.yml index 2846188d90..ee91090de6 100644 --- a/.github/workflows/deploy-github-pages.yml +++ b/.github/workflows/deploy-github-pages.yml @@ -34,7 +34,7 @@ jobs: - name: Setup Pages uses: actions/configure-pages@v5 - name: Upload artifact - uses: actions/upload-pages-artifact@v2 + uses: actions/upload-pages-artifact@v3 with: # Upload entire repository path: './ppa' From c521ee6702c98d4950c5cf779c0a86cca65c765b Mon Sep 17 00:00:00 2001 From: "dependabot[bot]" <49699333+dependabot[bot]@users.noreply.github.com> Date: Tue, 27 Aug 2024 12:45:26 +0200 Subject: [PATCH 29/93] build(deps): bump the patch-updates group with 23 updates (#4791) Bumps the patch-updates group with 23 updates: | Package | From | To | | --- | --- | --- | | [async-trait](https://github.com/dtolnay/async-trait) | `0.1.80` | `0.1.81` | | [blake3](https://github.com/BLAKE3-team/BLAKE3) | `1.5.1` | `1.5.4` | | [clap](https://github.com/clap-rs/clap) | `4.5.7` | `4.5.16` | | [clap_complete](https://github.com/clap-rs/clap) | `4.5.5` | `4.5.23` | | [clap_complete_fig](https://github.com/clap-rs/clap) | `4.5.1` | `4.5.2` | | [curve25519-dalek](https://github.com/dalek-cryptography/curve25519-dalek) | `4.1.2` | `4.1.3` | | [fastrand](https://github.com/smol-rs/fastrand) | `2.1.0` | `2.1.1` | | [flate2](https://github.com/rust-lang/flate2-rs) | `1.0.30` | `1.0.33` | | [log](https://github.com/rust-lang/log) | `0.4.21` | `0.4.22` | | [quote](https://github.com/dtolnay/quote) | `1.0.36` | `1.0.37` | | [regex](https://github.com/rust-lang/regex) | `1.10.5` | `1.10.6` | | [safer-ffi](https://github.com/getditto/safer_ffi) | `0.1.8` | `0.1.12` | | [serde](https://github.com/serde-rs/serde) | `1.0.203` | `1.0.209` | | [serde_bytes](https://github.com/serde-rs/bytes) | `0.11.14` | `0.11.15` | | [serde_derive](https://github.com/serde-rs/serde) | `1.0.203` | `1.0.209` | | [serde_json](https://github.com/serde-rs/json) | `1.0.117` | `1.0.127` | | [si-scale](https://github.com/graelo/si-scale) | `0.2.2` | `0.2.3` | | [thiserror](https://github.com/dtolnay/thiserror) | `1.0.61` | `1.0.63` | | [tokio](https://github.com/tokio-rs/tokio) | `1.39.2` | `1.39.3` | | [url](https://github.com/servo/rust-url) | `2.5.1` | `2.5.2` | | [bip32](https://github.com/iqlusioninc/crates) | `0.5.1` | `0.5.2` | | [wasm-bindgen](https://github.com/rustwasm/wasm-bindgen) | `0.2.92` | `0.2.93` | | [hyper-util](https://github.com/hyperium/hyper-util) | `0.1.5` | `0.1.7` | Updates `async-trait` from 0.1.80 to 0.1.81 - [Release notes](https://github.com/dtolnay/async-trait/releases) - [Commits](https://github.com/dtolnay/async-trait/compare/0.1.80...0.1.81) Updates `blake3` from 1.5.1 to 1.5.4 - [Release notes](https://github.com/BLAKE3-team/BLAKE3/releases) - [Commits](https://github.com/BLAKE3-team/BLAKE3/compare/1.5.1...1.5.4) Updates `clap` from 4.5.7 to 4.5.16 - [Release notes](https://github.com/clap-rs/clap/releases) - [Changelog](https://github.com/clap-rs/clap/blob/master/CHANGELOG.md) - [Commits](https://github.com/clap-rs/clap/compare/clap_complete-v4.5.7...clap_complete-v4.5.16) Updates `clap_complete` from 4.5.5 to 4.5.23 - [Release notes](https://github.com/clap-rs/clap/releases) - [Changelog](https://github.com/clap-rs/clap/blob/master/CHANGELOG.md) - [Commits](https://github.com/clap-rs/clap/compare/clap_complete-v4.5.5...clap_complete-v4.5.23) Updates `clap_complete_fig` from 4.5.1 to 4.5.2 - [Release notes](https://github.com/clap-rs/clap/releases) - [Changelog](https://github.com/clap-rs/clap/blob/master/CHANGELOG.md) - [Commits](https://github.com/clap-rs/clap/compare/clap_complete_fig-v4.5.1...clap_complete_fig-v4.5.2) Updates `curve25519-dalek` from 4.1.2 to 4.1.3 - [Release notes](https://github.com/dalek-cryptography/curve25519-dalek/releases) - [Commits](https://github.com/dalek-cryptography/curve25519-dalek/compare/curve25519-4.1.2...curve25519-4.1.3) Updates `fastrand` from 2.1.0 to 2.1.1 - [Release notes](https://github.com/smol-rs/fastrand/releases) - [Changelog](https://github.com/smol-rs/fastrand/blob/master/CHANGELOG.md) - [Commits](https://github.com/smol-rs/fastrand/compare/v2.1.0...v2.1.1) Updates `flate2` from 1.0.30 to 1.0.33 - [Release notes](https://github.com/rust-lang/flate2-rs/releases) - [Changelog](https://github.com/rust-lang/flate2-rs/blob/main/CHANGELOG.md) - [Commits](https://github.com/rust-lang/flate2-rs/compare/1.0.30...1.0.33) Updates `log` from 0.4.21 to 0.4.22 - [Release notes](https://github.com/rust-lang/log/releases) - [Changelog](https://github.com/rust-lang/log/blob/master/CHANGELOG.md) - [Commits](https://github.com/rust-lang/log/compare/0.4.21...0.4.22) Updates `quote` from 1.0.36 to 1.0.37 - [Release notes](https://github.com/dtolnay/quote/releases) - [Commits](https://github.com/dtolnay/quote/compare/1.0.36...1.0.37) Updates `regex` from 1.10.5 to 1.10.6 - [Release notes](https://github.com/rust-lang/regex/releases) - [Changelog](https://github.com/rust-lang/regex/blob/master/CHANGELOG.md) - [Commits](https://github.com/rust-lang/regex/compare/1.10.5...1.10.6) Updates `safer-ffi` from 0.1.8 to 0.1.12 - [Release notes](https://github.com/getditto/safer_ffi/releases) - [Commits](https://github.com/getditto/safer_ffi/compare/v0.1.8...v0.1.12) Updates `serde` from 1.0.203 to 1.0.209 - [Release notes](https://github.com/serde-rs/serde/releases) - [Commits](https://github.com/serde-rs/serde/compare/v1.0.203...v1.0.209) Updates `serde_bytes` from 0.11.14 to 0.11.15 - [Release notes](https://github.com/serde-rs/bytes/releases) - [Commits](https://github.com/serde-rs/bytes/compare/0.11.14...0.11.15) Updates `serde_derive` from 1.0.203 to 1.0.209 - [Release notes](https://github.com/serde-rs/serde/releases) - [Commits](https://github.com/serde-rs/serde/compare/v1.0.203...v1.0.209) Updates `serde_json` from 1.0.117 to 1.0.127 - [Release notes](https://github.com/serde-rs/json/releases) - [Commits](https://github.com/serde-rs/json/compare/v1.0.117...1.0.127) Updates `si-scale` from 0.2.2 to 0.2.3 - [Release notes](https://github.com/graelo/si-scale/releases) - [Changelog](https://github.com/graelo/si-scale/blob/main/CHANGELOG.md) - [Commits](https://github.com/graelo/si-scale/compare/0.2.2...v0.2.3) Updates `thiserror` from 1.0.61 to 1.0.63 - [Release notes](https://github.com/dtolnay/thiserror/releases) - [Commits](https://github.com/dtolnay/thiserror/compare/1.0.61...1.0.63) Updates `tokio` from 1.39.2 to 1.39.3 - [Release notes](https://github.com/tokio-rs/tokio/releases) - [Commits](https://github.com/tokio-rs/tokio/compare/tokio-1.39.2...tokio-1.39.3) Updates `url` from 2.5.1 to 2.5.2 - [Release notes](https://github.com/servo/rust-url/releases) - [Commits](https://github.com/servo/rust-url/compare/v2.5.1...v2.5.2) Updates `bip32` from 0.5.1 to 0.5.2 - [Commits](https://github.com/iqlusioninc/crates/compare/bip32/v0.5.1...secrecy/v0.5.2) Updates `wasm-bindgen` from 0.2.92 to 0.2.93 - [Release notes](https://github.com/rustwasm/wasm-bindgen/releases) - [Changelog](https://github.com/rustwasm/wasm-bindgen/blob/main/CHANGELOG.md) - [Commits](https://github.com/rustwasm/wasm-bindgen/compare/0.2.92...0.2.93) Updates `hyper-util` from 0.1.5 to 0.1.7 - [Release notes](https://github.com/hyperium/hyper-util/releases) - [Changelog](https://github.com/hyperium/hyper-util/blob/master/CHANGELOG.md) - [Commits](https://github.com/hyperium/hyper-util/compare/v0.1.5...v0.1.7) --- updated-dependencies: - dependency-name: async-trait dependency-type: direct:production update-type: version-update:semver-patch dependency-group: patch-updates - dependency-name: blake3 dependency-type: direct:production update-type: version-update:semver-patch dependency-group: patch-updates - dependency-name: clap dependency-type: direct:production update-type: version-update:semver-patch dependency-group: patch-updates - dependency-name: clap_complete dependency-type: direct:production update-type: version-update:semver-patch dependency-group: patch-updates - dependency-name: clap_complete_fig dependency-type: direct:production update-type: version-update:semver-patch dependency-group: patch-updates - dependency-name: curve25519-dalek dependency-type: direct:production update-type: version-update:semver-patch dependency-group: patch-updates - dependency-name: fastrand dependency-type: direct:production update-type: version-update:semver-patch dependency-group: patch-updates - dependency-name: flate2 dependency-type: direct:production update-type: version-update:semver-patch dependency-group: patch-updates - dependency-name: log dependency-type: direct:production update-type: version-update:semver-patch dependency-group: patch-updates - dependency-name: quote dependency-type: direct:production update-type: version-update:semver-patch dependency-group: patch-updates - dependency-name: regex dependency-type: direct:production update-type: version-update:semver-patch dependency-group: patch-updates - dependency-name: safer-ffi dependency-type: direct:production update-type: version-update:semver-patch dependency-group: patch-updates - dependency-name: serde dependency-type: direct:production update-type: version-update:semver-patch dependency-group: patch-updates - dependency-name: serde_bytes dependency-type: direct:production update-type: version-update:semver-patch dependency-group: patch-updates - dependency-name: serde_derive dependency-type: direct:production update-type: version-update:semver-patch dependency-group: patch-updates - dependency-name: serde_json dependency-type: direct:production update-type: version-update:semver-patch dependency-group: patch-updates - dependency-name: si-scale dependency-type: direct:production update-type: version-update:semver-patch dependency-group: patch-updates - dependency-name: thiserror dependency-type: direct:production update-type: version-update:semver-patch dependency-group: patch-updates - dependency-name: tokio dependency-type: direct:production update-type: version-update:semver-patch dependency-group: patch-updates - dependency-name: url dependency-type: direct:production update-type: version-update:semver-patch dependency-group: patch-updates - dependency-name: bip32 dependency-type: direct:production update-type: version-update:semver-patch dependency-group: patch-updates - dependency-name: wasm-bindgen dependency-type: direct:production update-type: version-update:semver-patch dependency-group: patch-updates - dependency-name: hyper-util dependency-type: direct:production update-type: version-update:semver-patch dependency-group: patch-updates ... Signed-off-by: dependabot[bot] Co-authored-by: dependabot[bot] <49699333+dependabot[bot]@users.noreply.github.com> --- Cargo.lock | 577 ++++++------------ Cargo.toml | 34 +- .../group-contract/Cargo.toml | 2 +- .../multisig-contract/Cargo.toml | 2 +- common/crypto/Cargo.toml | 2 +- common/nymsphinx/Cargo.toml | 2 +- common/nymsphinx/anonymous-replies/Cargo.toml | 2 +- 7 files changed, 223 insertions(+), 398 deletions(-) diff --git a/Cargo.lock b/Cargo.lock index bd601c4412..936d174d81 100644 --- a/Cargo.lock +++ b/Cargo.lock @@ -45,6 +45,12 @@ version = "1.0.2" source = "registry+https://github.com/rust-lang/crates.io-index" checksum = "f26201604c87b1e01bd3d98f8d5d9a8fcbb815e8cedb41ffccbeb4bf593a35fe" +[[package]] +name = "adler2" +version = "2.0.0" +source = "registry+https://github.com/rust-lang/crates.io-index" +checksum = "512761e0bb2578dd7380c6baaa0f4ce03e84f95e960231d1dec8bf4d7d6e2627" + [[package]] name = "aead" version = "0.5.2" @@ -174,9 +180,9 @@ dependencies = [ [[package]] name = "anstyle" -version = "1.0.7" +version = "1.0.8" source = "registry+https://github.com/rust-lang/crates.io-index" -checksum = "038dfcf04a5feb68e9c60b21c9625a54c2c0616e79b72b0fd87075a056ae1d1b" +checksum = "1bec1de6f59aedf83baf9ff929c98f2ad654b97c9510f4e70cf6f661d49fd5b1" [[package]] name = "anstyle-parse" @@ -271,9 +277,9 @@ dependencies = [ [[package]] name = "async-trait" -version = "0.1.80" +version = "0.1.81" source = "registry+https://github.com/rust-lang/crates.io-index" -checksum = "c6fa2087f2753a7da8cc1c0dbfcf89579dd57458e36769de5ac750b4671737ca" +checksum = "6e0c28dcc82d7c8ead5cb13beb15405b57b8546e93215673ff8ca0349a028107" dependencies = [ "proc-macro2", "quote", @@ -388,7 +394,7 @@ dependencies = [ "http 1.1.0", "http-body 1.0.0", "http-body-util", - "hyper 1.3.1", + "hyper 1.4.1", "hyper-util", "itoa", "matchit", @@ -480,7 +486,7 @@ dependencies = [ "cc", "cfg-if", "libc", - "miniz_oxide", + "miniz_oxide 0.7.3", "object", "rustc-demangle", ] @@ -532,9 +538,9 @@ dependencies = [ [[package]] name = "bip32" -version = "0.5.1" +version = "0.5.2" source = "registry+https://github.com/rust-lang/crates.io-index" -checksum = "7e141fb0f8be1c7b45887af94c88b182472b57c96b56773250ae00cd6a14a164" +checksum = "aa13fae8b6255872fd86f7faf4b41168661d7d78609f7bfe6771b85c6739a15b" dependencies = [ "bs58 0.5.1", "hmac", @@ -619,9 +625,9 @@ dependencies = [ [[package]] name = "blake3" -version = "1.5.1" +version = "1.5.4" source = "registry+https://github.com/rust-lang/crates.io-index" -checksum = "30cca6d3674597c30ddf2c587bf8d9d65c9a84d2326d941cc79c9842dfe0ef52" +checksum = "d82033247fd8e890df8f740e407ad4d038debb9eb1f40533fffb32e7d17dc6f7" dependencies = [ "arrayref", "arrayvec", @@ -796,9 +802,12 @@ checksum = "a2698f953def977c68f935bb0dfa959375ad4638570e969e2f1e9f433cbf1af6" [[package]] name = "cc" -version = "1.0.99" +version = "1.1.14" source = "registry+https://github.com/rust-lang/crates.io-index" -checksum = "96c51067fd44124faa7f870b4b1c969379ad32b2ba805aa959430ceaa384f695" +checksum = "50d2eb3cd3d1bf4529e31c215ee6f93ec5a3d536d9f578f93d9d33ee19562932" +dependencies = [ + "shlex", +] [[package]] name = "celes" @@ -928,9 +937,9 @@ dependencies = [ [[package]] name = "clap" -version = "4.5.7" +version = "4.5.16" source = "registry+https://github.com/rust-lang/crates.io-index" -checksum = "5db83dced34638ad474f39f250d7fea9598bdd239eaced1bdf45d597da0f433f" +checksum = "ed6719fffa43d0d87e5fd8caeab59be1554fb028cd30edc88fc4369b17971019" dependencies = [ "clap_builder", "clap_derive", @@ -938,9 +947,9 @@ dependencies = [ [[package]] name = "clap_builder" -version = "4.5.7" +version = "4.5.15" source = "registry+https://github.com/rust-lang/crates.io-index" -checksum = "f7e204572485eb3fbf28f871612191521df159bc3e15a9f5064c66dba3a8c05f" +checksum = "216aec2b177652e3846684cbfe25c9964d18ec45234f0f5da5157b207ed1aab6" dependencies = [ "anstream", "anstyle", @@ -950,28 +959,28 @@ dependencies = [ [[package]] name = "clap_complete" -version = "4.5.5" +version = "4.5.23" source = "registry+https://github.com/rust-lang/crates.io-index" -checksum = "d2020fa13af48afc65a9a87335bda648309ab3d154cd03c7ff95b378c7ed39c4" +checksum = "531d7959c5bbb6e266cecdd0f20213639c3a5c3e4d615f97db87661745f781ff" dependencies = [ - "clap 4.5.7", + "clap 4.5.16", ] [[package]] name = "clap_complete_fig" -version = "4.5.1" +version = "4.5.2" source = "registry+https://github.com/rust-lang/crates.io-index" -checksum = "fb4bc503cddc1cd320736fb555d6598309ad07c2ddeaa23891a10ffb759ee612" +checksum = "d494102c8ff3951810c72baf96910b980fb065ca5d3101243e6a8dc19747c86b" dependencies = [ - "clap 4.5.7", + "clap 4.5.16", "clap_complete", ] [[package]] name = "clap_derive" -version = "4.5.5" +version = "4.5.13" source = "registry+https://github.com/rust-lang/crates.io-index" -checksum = "c780290ccf4fb26629baa7a1081e68ced113f1d3ec302fa5948f1c381ebf06c6" +checksum = "501d359d5f3dcaf6ecdeee48833ae73ec6e42723a1e52419c79abf9507eec0a0" dependencies = [ "heck 0.5.0", "proc-macro2", @@ -1392,7 +1401,7 @@ dependencies = [ "anes", "cast", "ciborium", - "clap 4.5.7", + "clap 4.5.16", "criterion-plot", "is-terminal", "itertools 0.10.5", @@ -1640,16 +1649,15 @@ dependencies = [ [[package]] name = "curve25519-dalek" -version = "4.1.2" +version = "4.1.3" source = "registry+https://github.com/rust-lang/crates.io-index" -checksum = "0a677b8922c94e01bdbb12126b0bc852f00447528dee1782229af9c720c3f348" +checksum = "97fb8b7c4503de7d6ae7b42ab72a5a59857b4c937ec27a3d4539dba95b5ab2be" dependencies = [ "cfg-if", "cpufeatures", "curve25519-dalek-derive", "digest 0.10.7", "fiat-crypto", - "platforms", "rustc_version 0.4.0", "serde", "subtle 2.5.0", @@ -2034,17 +2042,6 @@ dependencies = [ "windows-sys 0.48.0", ] -[[package]] -name = "displaydoc" -version = "0.2.4" -source = "registry+https://github.com/rust-lang/crates.io-index" -checksum = "487585f4d0c6655fe74905e2504d8ad6908e4db67f744eb140876906c2f3175d" -dependencies = [ - "proc-macro2", - "quote", - "syn 2.0.66", -] - [[package]] name = "dkg-bypass-contract" version = "0.1.0" @@ -2120,7 +2117,7 @@ version = "2.1.1" source = "registry+https://github.com/rust-lang/crates.io-index" checksum = "4a3daa8e81a3963a60642bcc1f90a670680bd4a77535faa384e9d1c79d620871" dependencies = [ - "curve25519-dalek 4.1.2", + "curve25519-dalek 4.1.3", "ed25519", "rand_core 0.6.4", "serde", @@ -2244,7 +2241,7 @@ name = "explorer-api" version = "1.1.38" dependencies = [ "chrono", - "clap 4.5.7", + "clap 4.5.16", "dotenvy", "humantime-serde", "isocountry", @@ -2352,9 +2349,9 @@ dependencies = [ [[package]] name = "fastrand" -version = "2.1.0" +version = "2.1.1" source = "registry+https://github.com/rust-lang/crates.io-index" -checksum = "9fc0510504f03c51ada170672ac806f1f105a88aa97a5281117e1ddc3368e51a" +checksum = "e8c02a5121d4ea3eb16a80748c74f5549a5665e4c21333c6098f283870fbdea6" [[package]] name = "ff" @@ -2406,12 +2403,12 @@ checksum = "0ce7134b9999ecaf8bcd65542e436736ef32ddca1b3e06094cb6ec5755203b80" [[package]] name = "flate2" -version = "1.0.30" +version = "1.0.33" source = "registry+https://github.com/rust-lang/crates.io-index" -checksum = "5f54427cfd1c7829e2a139fcefea601bf088ebca651d2bf53ebc600eac295dae" +checksum = "324a1be68054ef05ad64b861cc9eaf1d623d2d8cb25b4bf2cb9cdd902b4bf253" dependencies = [ "crc32fast", - "miniz_oxide", + "miniz_oxide 0.8.0", ] [[package]] @@ -3074,9 +3071,9 @@ dependencies = [ [[package]] name = "hyper" -version = "1.3.1" +version = "1.4.1" source = "registry+https://github.com/rust-lang/crates.io-index" -checksum = "fe575dd17d0862a9a33781c8c4696a55c320909004a67a00fb286ba8b1bc496d" +checksum = "50dfd22e0e76d0f662d429a5f80fcaf3855009297eab6a0a9f8543834744ba05" dependencies = [ "bytes", "futures-channel", @@ -3114,7 +3111,7 @@ checksum = "a0bea761b46ae2b24eb4aef630d8d1c398157b6fc29e6350ecf090a0b70c952c" dependencies = [ "futures-util", "http 1.1.0", - "hyper 1.3.1", + "hyper 1.4.1", "hyper-util", "rustls 0.22.4", "rustls-pki-types", @@ -3137,16 +3134,16 @@ dependencies = [ [[package]] name = "hyper-util" -version = "0.1.5" +version = "0.1.7" source = "registry+https://github.com/rust-lang/crates.io-index" -checksum = "7b875924a60b96e5d7b9ae7b066540b1dd1cbd90d1828f54c92e02a283351c56" +checksum = "cde7055719c54e36e95e8719f95883f22072a48ede39db7fc17a4e1d5281e9b9" dependencies = [ "bytes", "futures-channel", "futures-util", "http 1.1.0", "http-body 1.0.0", - "hyper 1.3.1", + "hyper 1.4.1", "pin-project-lite", "socket2", "tokio", @@ -3178,124 +3175,6 @@ dependencies = [ "cc", ] -[[package]] -name = "icu_collections" -version = "1.5.0" -source = "registry+https://github.com/rust-lang/crates.io-index" -checksum = "db2fa452206ebee18c4b5c2274dbf1de17008e874b4dc4f0aea9d01ca79e4526" -dependencies = [ - "displaydoc", - "yoke", - "zerofrom", - "zerovec", -] - -[[package]] -name = "icu_locid" -version = "1.5.0" -source = "registry+https://github.com/rust-lang/crates.io-index" -checksum = "13acbb8371917fc971be86fc8057c41a64b521c184808a698c02acc242dbf637" -dependencies = [ - "displaydoc", - "litemap", - "tinystr", - "writeable", - "zerovec", -] - -[[package]] -name = "icu_locid_transform" -version = "1.5.0" -source = "registry+https://github.com/rust-lang/crates.io-index" -checksum = "01d11ac35de8e40fdeda00d9e1e9d92525f3f9d887cdd7aa81d727596788b54e" -dependencies = [ - "displaydoc", - "icu_locid", - "icu_locid_transform_data", - "icu_provider", - "tinystr", - "zerovec", -] - -[[package]] -name = "icu_locid_transform_data" -version = "1.5.0" -source = "registry+https://github.com/rust-lang/crates.io-index" -checksum = "fdc8ff3388f852bede6b579ad4e978ab004f139284d7b28715f773507b946f6e" - -[[package]] -name = "icu_normalizer" -version = "1.5.0" -source = "registry+https://github.com/rust-lang/crates.io-index" -checksum = "19ce3e0da2ec68599d193c93d088142efd7f9c5d6fc9b803774855747dc6a84f" -dependencies = [ - "displaydoc", - "icu_collections", - "icu_normalizer_data", - "icu_properties", - "icu_provider", - "smallvec", - "utf16_iter", - "utf8_iter", - "write16", - "zerovec", -] - -[[package]] -name = "icu_normalizer_data" -version = "1.5.0" -source = "registry+https://github.com/rust-lang/crates.io-index" -checksum = "f8cafbf7aa791e9b22bec55a167906f9e1215fd475cd22adfcf660e03e989516" - -[[package]] -name = "icu_properties" -version = "1.5.0" -source = "registry+https://github.com/rust-lang/crates.io-index" -checksum = "1f8ac670d7422d7f76b32e17a5db556510825b29ec9154f235977c9caba61036" -dependencies = [ - "displaydoc", - "icu_collections", - "icu_locid_transform", - "icu_properties_data", - "icu_provider", - "tinystr", - "zerovec", -] - -[[package]] -name = "icu_properties_data" -version = "1.5.0" -source = "registry+https://github.com/rust-lang/crates.io-index" -checksum = "67a8effbc3dd3e4ba1afa8ad918d5684b8868b3b26500753effea8d2eed19569" - -[[package]] -name = "icu_provider" -version = "1.5.0" -source = "registry+https://github.com/rust-lang/crates.io-index" -checksum = "6ed421c8a8ef78d3e2dbc98a973be2f3770cb42b606e3ab18d6237c4dfde68d9" -dependencies = [ - "displaydoc", - "icu_locid", - "icu_provider_macros", - "stable_deref_trait", - "tinystr", - "writeable", - "yoke", - "zerofrom", - "zerovec", -] - -[[package]] -name = "icu_provider_macros" -version = "1.5.0" -source = "registry+https://github.com/rust-lang/crates.io-index" -checksum = "1ec89e9337638ecdc08744df490b221a7399bf8d164eb52a665454e60e075ad6" -dependencies = [ - "proc-macro2", - "quote", - "syn 2.0.66", -] - [[package]] name = "ident_case" version = "1.0.1" @@ -3314,14 +3193,12 @@ dependencies = [ [[package]] name = "idna" -version = "1.0.0" +version = "0.5.0" source = "registry+https://github.com/rust-lang/crates.io-index" -checksum = "4716a3a0933a1d01c2f72450e89596eb51dd34ef3c211ccd875acdf1f8fe47ed" +checksum = "634d9b1461af396cad843f47fdba5597a4f9e6ddd4bfb6ff5d85028c25cb12f6" dependencies = [ - "icu_normalizer", - "icu_properties", - "smallvec", - "utf8_iter", + "unicode-bidi", + "unicode-normalization", ] [[package]] @@ -3755,12 +3632,6 @@ dependencies = [ "keystream", ] -[[package]] -name = "litemap" -version = "0.7.3" -source = "registry+https://github.com/rust-lang/crates.io-index" -checksum = "643cb0b8d4fcc284004d5fd0d67ccf61dfffadb7f75e1e71bc420f4688a3a704" - [[package]] name = "lock_api" version = "0.4.12" @@ -3773,9 +3644,9 @@ dependencies = [ [[package]] name = "log" -version = "0.4.21" +version = "0.4.22" source = "registry+https://github.com/rust-lang/crates.io-index" -checksum = "90ed8c1e510134f979dbc4f070f87d4313098b704861a105fe34231c70a3901c" +checksum = "a7a70ba024b9dc04c27ea2f0c0548feb474ec5c54bba33a7f72f873a39d07b24" [[package]] name = "loom" @@ -3928,6 +3799,15 @@ dependencies = [ "adler", ] +[[package]] +name = "miniz_oxide" +version = "0.8.0" +source = "registry+https://github.com/rust-lang/crates.io-index" +checksum = "e2d80299ef12ff69b16a84bb182e3b9df68b5a91574d3d4fa6e41b65deec4df1" +dependencies = [ + "adler2", +] + [[package]] name = "mio" version = "0.8.11" @@ -4220,7 +4100,7 @@ dependencies = [ "bloomfilter", "bs58 0.5.1", "cfg-if", - "clap 4.5.7", + "clap 4.5.16", "console-subscriber", "cosmwasm-std", "cw-utils", @@ -4332,9 +4212,9 @@ dependencies = [ "bincode", "bs58 0.5.1", "bytes", - "clap 4.5.7", + "clap 4.5.16", "defguard_wireguard_rs", - "fastrand 2.1.0", + "fastrand 2.1.1", "futures", "ipnetwork 0.16.0", "log", @@ -4397,7 +4277,7 @@ dependencies = [ name = "nym-bin-common" version = "0.6.0" dependencies = [ - "clap 4.5.7", + "clap 4.5.16", "clap_complete", "clap_complete_fig", "const-str", @@ -4439,7 +4319,7 @@ dependencies = [ "base64 0.13.1", "bip39", "bs58 0.5.1", - "clap 4.5.7", + "clap 4.5.16", "clap_complete", "clap_complete_fig", "dotenvy", @@ -4465,7 +4345,7 @@ dependencies = [ "bip39", "bs58 0.5.1", "cfg-if", - "clap 4.5.7", + "clap 4.5.16", "comfy-table 6.2.0", "cosmrs 0.17.0-pre", "cosmwasm-std", @@ -4515,7 +4395,7 @@ name = "nym-client" version = "1.1.39" dependencies = [ "bs58 0.5.1", - "clap 4.5.7", + "clap 4.5.16", "dirs 4.0.0", "futures", "log", @@ -4555,13 +4435,13 @@ dependencies = [ "base64 0.21.7", "bs58 0.5.1", "cfg-if", - "clap 4.5.7", + "clap 4.5.16", "comfy-table 7.1.1", "futures", "gloo-timers", "http-body-util", "humantime-serde", - "hyper 1.3.1", + "hyper 1.4.1", "hyper-util", "log", "nym-bandwidth-controller", @@ -5001,7 +4881,7 @@ dependencies = [ "bip39", "bloomfilter", "bs58 0.5.1", - "clap 4.5.7", + "clap 4.5.16", "colored", "cosmwasm-std", "cw-utils", @@ -5188,7 +5068,7 @@ version = "0.1.0" dependencies = [ "anyhow", "bs58 0.5.1", - "clap 4.5.7", + "clap 4.5.16", "nym-bin-common", "nym-credential-storage", "nym-id", @@ -5230,7 +5110,7 @@ dependencies = [ "bincode", "bs58 0.5.1", "bytes", - "clap 4.5.7", + "clap 4.5.16", "etherparse", "futures", "log", @@ -5325,7 +5205,7 @@ dependencies = [ "anyhow", "axum 0.7.5", "bs58 0.5.1", - "clap 4.5.7", + "clap 4.5.16", "colored", "cupid", "dirs 4.0.0", @@ -5425,7 +5305,7 @@ version = "0.1.0" dependencies = [ "anyhow", "axum 0.7.5", - "clap 4.5.7", + "clap 4.5.16", "dashmap", "futures", "log", @@ -5457,7 +5337,7 @@ dependencies = [ "anyhow", "async-trait", "bs58 0.5.1", - "clap 4.5.7", + "clap 4.5.16", "dirs 4.0.0", "futures", "humantime-serde", @@ -5509,7 +5389,7 @@ dependencies = [ "bs58 0.5.1", "cargo_metadata", "celes", - "clap 4.5.7", + "clap 4.5.16", "colored", "cupid", "humantime-serde", @@ -5553,10 +5433,10 @@ dependencies = [ "base64 0.21.7", "colored", "dashmap", - "fastrand 2.1.0", + "fastrand 2.1.1", "headers", "hmac", - "hyper 1.3.1", + "hyper 1.4.1", "ipnetwork 0.16.0", "nym-crypto", "nym-http-api-common", @@ -5657,7 +5537,7 @@ name = "nym-nr-query" version = "0.1.0" dependencies = [ "anyhow", - "clap 4.5.7", + "clap 4.5.16", "log", "nym-bin-common", "nym-network-defaults", @@ -5684,8 +5564,8 @@ dependencies = [ "chacha20", "chacha20poly1305", "criterion 0.4.0", - "curve25519-dalek 4.1.2", - "fastrand 2.1.0", + "curve25519-dalek 4.1.3", + "fastrand 2.1.1", "getrandom", "log", "rand 0.8.5", @@ -5780,7 +5660,7 @@ name = "nym-socks5-client" version = "1.1.39" dependencies = [ "bs58 0.5.1", - "clap 4.5.7", + "clap 4.5.16", "log", "nym-bin-common", "nym-client-core", @@ -6199,7 +6079,7 @@ version = "0.1.0" dependencies = [ "anyhow", "bip39", - "clap 4.5.7", + "clap 4.5.16", "cosmwasm-std", "futures", "humantime 2.1.0", @@ -6310,7 +6190,7 @@ version = "0.1.5" dependencies = [ "anyhow", "bytes", - "clap 4.5.7", + "clap 4.5.16", "dotenvy", "flate2", "futures", @@ -6788,12 +6668,6 @@ version = "0.3.30" source = "registry+https://github.com/rust-lang/crates.io-index" checksum = "d231b230927b5e4ad203db57bbcbee2802f6bce620b1e4a9024a07d94e2907ec" -[[package]] -name = "platforms" -version = "3.4.0" -source = "registry+https://github.com/rust-lang/crates.io-index" -checksum = "db23d408679286588f4d4644f965003d056e3dd5abcaaa938116871d7ce2fee7" - [[package]] name = "plotters" version = "0.3.6" @@ -6899,6 +6773,15 @@ dependencies = [ "syn 1.0.109", ] +[[package]] +name = "proc-macro-crate" +version = "3.1.0" +source = "registry+https://github.com/rust-lang/crates.io-index" +checksum = "6d37c51ca738a55da99dc0c4a34860fd675453b8b36209178c2249bb13651284" +dependencies = [ + "toml_edit 0.21.1", +] + [[package]] name = "proc-macro-error" version = "1.0.4" @@ -7069,9 +6952,9 @@ checksum = "a993555f31e5a609f617c12db6250dedcac1b0a85076912c436e6fc9b2c8e6a3" [[package]] name = "quote" -version = "1.0.36" +version = "1.0.37" source = "registry+https://github.com/rust-lang/crates.io-index" -checksum = "0fa76aaf39101c457836aec0ce2316dbdc3ab723cdda1c6bd4e6ad4208acaca7" +checksum = "b5b9d34b8991d19d98081b46eacdd8eb58c6f2b201139f7c5f643cc155a633af" dependencies = [ "proc-macro2", ] @@ -7341,9 +7224,9 @@ dependencies = [ [[package]] name = "regex" -version = "1.10.5" +version = "1.10.6" source = "registry+https://github.com/rust-lang/crates.io-index" -checksum = "b91213439dad192326a0d7c6ee3955910425f441d7038e0d6933b0aec5c4517f" +checksum = "4219d74c6b67a3654a9fbebc4b419e22126d13d2f3c4a07ee0cb61ff79a79619" dependencies = [ "aho-corasick", "memchr", @@ -7437,7 +7320,7 @@ dependencies = [ "http 1.1.0", "http-body 1.0.0", "http-body-util", - "hyper 1.3.1", + "hyper 1.4.1", "hyper-rustls 0.26.0", "hyper-util", "ipnet", @@ -7838,9 +7721,9 @@ checksum = "f3cb5ba0dc43242ce17de99c180e96db90b235b8a9fdc9543c96d2209116bd9f" [[package]] name = "safer-ffi" -version = "0.1.8" +version = "0.1.12" source = "registry+https://github.com/rust-lang/crates.io-index" -checksum = "44abae8773dc41fb96af52696b834b1f4c806006b456b22ee3602f7b061e3ad0" +checksum = "614978f55c6e885794b44afb2e2378fe61b104ec4391f310d879edf3df9d874c" dependencies = [ "inventory", "libc", @@ -7848,6 +7731,7 @@ dependencies = [ "paste", "safer_ffi-proc_macros", "scopeguard", + "stabby", "uninit", "unwind_safe", "with_builtin_macros", @@ -7855,9 +7739,9 @@ dependencies = [ [[package]] name = "safer_ffi-proc_macros" -version = "0.1.8" +version = "0.1.12" source = "registry+https://github.com/rust-lang/crates.io-index" -checksum = "6c9d4117a8a72f9b615169d4d720d79e74931f74003c73cc2f3927c700156ddf" +checksum = "7cdcb365894c49e42b5413def59ac644ea085bbbdee535d7c80b2b008a345686" dependencies = [ "macro_rules_attribute", "prettyplease", @@ -8013,9 +7897,9 @@ dependencies = [ [[package]] name = "serde" -version = "1.0.203" +version = "1.0.209" source = "registry+https://github.com/rust-lang/crates.io-index" -checksum = "7253ab4de971e72fb7be983802300c30b5a7f0c2e56fab8abfc6a214307c0094" +checksum = "99fce0ffe7310761ca6bf9faf5115afbc19688edd00171d81b1bb1b116c63e09" dependencies = [ "serde_derive", ] @@ -8053,18 +7937,18 @@ dependencies = [ [[package]] name = "serde_bytes" -version = "0.11.14" +version = "0.11.15" source = "registry+https://github.com/rust-lang/crates.io-index" -checksum = "8b8497c313fd43ab992087548117643f6fcd935cbf36f176ffda0aacf9591734" +checksum = "387cc504cb06bb40a96c8e04e951fe01854cf6bc921053c954e4a606d9675c6a" dependencies = [ "serde", ] [[package]] name = "serde_derive" -version = "1.0.203" +version = "1.0.209" source = "registry+https://github.com/rust-lang/crates.io-index" -checksum = "500cbc0ebeb6f46627f50f3f5811ccf6bf00643be300b4c3eabc0ef55dc5b5ba" +checksum = "a5831b979fd7b5439637af1752d535ff49f4860c0f341d1baeb6faf0f4242170" dependencies = [ "proc-macro2", "quote", @@ -8095,11 +7979,12 @@ dependencies = [ [[package]] name = "serde_json" -version = "1.0.117" +version = "1.0.127" source = "registry+https://github.com/rust-lang/crates.io-index" -checksum = "455182ea6142b14f93f4bc5320a2b31c1f266b66a4a5c858b013302a5d8cbfc3" +checksum = "8043c06d9f82bd7271361ed64f415fe5e12a77fdb52e573e7f06a516dea329ad" dependencies = [ "itoa", + "memchr", "ryu", "serde", ] @@ -8244,6 +8129,12 @@ dependencies = [ "digest 0.10.7", ] +[[package]] +name = "sha2-const-stable" +version = "0.1.0" +source = "registry+https://github.com/rust-lang/crates.io-index" +checksum = "5f179d4e11094a893b82fff208f74d448a7512f99f5a0acbd5c679b705f83ed9" + [[package]] name = "sharded-slab" version = "0.1.7" @@ -8254,10 +8145,16 @@ dependencies = [ ] [[package]] -name = "si-scale" -version = "0.2.2" +name = "shlex" +version = "1.3.0" source = "registry+https://github.com/rust-lang/crates.io-index" -checksum = "44beb68bf488343b13ddbd74d1d5d5e6559a58b6dfaee74eb8d5ed4f7ed7666f" +checksum = "0fda2ff0d084019ba4d7c6f371c95d8fd75ce3524c3cb8fb653a3023f6323e64" + +[[package]] +name = "si-scale" +version = "0.2.3" +source = "registry+https://github.com/rust-lang/crates.io-index" +checksum = "b72e7cd0744e007e382ba320435f1ed1ecd709409b4ebd5cfbc843d77b25a8aa" [[package]] name = "signal-hook" @@ -8376,7 +8273,7 @@ dependencies = [ "byteorder", "chacha", "ctr", - "curve25519-dalek 4.1.2", + "curve25519-dalek 4.1.3", "digest 0.10.7", "hkdf", "hmac", @@ -8516,11 +8413,45 @@ name = "ssl-inject" version = "0.1.0" dependencies = [ "anyhow", - "clap 4.5.7", + "clap 4.5.16", "hex", "tokio", ] +[[package]] +name = "stabby" +version = "36.1.1" +source = "registry+https://github.com/rust-lang/crates.io-index" +checksum = "311d6bcf0070c462ff626122ec2246f42bd2acd44b28908eedbfd07d500c7d99" +dependencies = [ + "rustversion", + "stabby-abi", +] + +[[package]] +name = "stabby-abi" +version = "36.1.1" +source = "registry+https://github.com/rust-lang/crates.io-index" +checksum = "e6daae1a0707399f56d27fce7f212e50e31d215112a447e1bbcd837ae1bf5f49" +dependencies = [ + "rustversion", + "sha2-const-stable", + "stabby-macros", +] + +[[package]] +name = "stabby-macros" +version = "36.1.1" +source = "registry+https://github.com/rust-lang/crates.io-index" +checksum = "43cf89a0cc9131279235baf8599b0e073fbcb096419204de0cc5d1a48ae73f74" +dependencies = [ + "proc-macro-crate", + "proc-macro2", + "quote", + "rand 0.8.5", + "syn 1.0.109", +] + [[package]] name = "stable-pattern" version = "0.1.0" @@ -8530,12 +8461,6 @@ dependencies = [ "memchr", ] -[[package]] -name = "stable_deref_trait" -version = "1.2.0" -source = "registry+https://github.com/rust-lang/crates.io-index" -checksum = "a8f112729512f8e442d81f95a8a7ddf2b7c6b8a1a6f509a95864142b30cab2d3" - [[package]] name = "state" version = "0.6.0" @@ -8711,17 +8636,6 @@ version = "1.0.1" source = "registry+https://github.com/rust-lang/crates.io-index" checksum = "a7065abeca94b6a8a577f9bd45aa0867a2238b74e8eb67cf10d492bc39351394" -[[package]] -name = "synstructure" -version = "0.13.1" -source = "registry+https://github.com/rust-lang/crates.io-index" -checksum = "c8af7666ab7b6390ab78131fb5b0fce11d6b7a6951602017c35fa82800708971" -dependencies = [ - "proc-macro2", - "quote", - "syn 2.0.66", -] - [[package]] name = "sysinfo" version = "0.27.8" @@ -8797,7 +8711,7 @@ source = "registry+https://github.com/rust-lang/crates.io-index" checksum = "85b77fafb263dd9d05cbeac119526425676db3784113aa9295c88498cbf8bff1" dependencies = [ "cfg-if", - "fastrand 2.1.0", + "fastrand 2.1.1", "rustix", "windows-sys 0.52.0", ] @@ -8962,7 +8876,7 @@ dependencies = [ "anyhow", "bip39", "bs58 0.5.1", - "clap 4.5.7", + "clap 4.5.16", "console", "cw-utils", "dkg-bypass-contract", @@ -9002,18 +8916,18 @@ checksum = "23d434d3f8967a09480fb04132ebe0a3e088c173e6d0ee7897abbdf4eab0f8b9" [[package]] name = "thiserror" -version = "1.0.61" +version = "1.0.63" source = "registry+https://github.com/rust-lang/crates.io-index" -checksum = "c546c80d6be4bc6a00c0f01730c08df82eaa7a7a61f11d656526506112cc1709" +checksum = "c0342370b38b6a11b6cc11d6a805569958d54cfa061a29969c3b5ce2ea405724" dependencies = [ "thiserror-impl", ] [[package]] name = "thiserror-impl" -version = "1.0.61" +version = "1.0.63" source = "registry+https://github.com/rust-lang/crates.io-index" -checksum = "46c3384250002a6d5af4d114f2845d37b57521033f30d5c3f46c4d70e1197533" +checksum = "a4558b58466b9ad7ca0f102865eccc95938dca1a74a856f2b57b6629050da261" dependencies = [ "proc-macro2", "quote", @@ -9086,16 +9000,6 @@ dependencies = [ "time-core", ] -[[package]] -name = "tinystr" -version = "0.7.6" -source = "registry+https://github.com/rust-lang/crates.io-index" -checksum = "9117f5d4db391c1cf6927e7bea3db74b9a1c1add8f7eda9ffd5364f40f57b82f" -dependencies = [ - "displaydoc", - "zerovec", -] - [[package]] name = "tinytemplate" version = "1.2.1" @@ -9123,9 +9027,9 @@ checksum = "1f3ccbac311fea05f86f61904b462b55fb3df8837a366dfc601a0161d0532f20" [[package]] name = "tokio" -version = "1.39.2" +version = "1.39.3" source = "registry+https://github.com/rust-lang/crates.io-index" -checksum = "daa4fb1bc778bd6f04cbfc4bb2d06a7396a8f299dc33ea1900cedaa316f467b1" +checksum = "9babc99b9923bfa4804bd74722ff02c0381021eafa4db9949217e3be8e84fff5" dependencies = [ "backtrace", "bytes", @@ -9328,6 +9232,17 @@ dependencies = [ "winnow 0.5.40", ] +[[package]] +name = "toml_edit" +version = "0.21.1" +source = "registry+https://github.com/rust-lang/crates.io-index" +checksum = "6a8534fd7f78b5405e860340ad6575217ce99f38d4d5c8f2442cb5ecb50090e1" +dependencies = [ + "indexmap 2.2.6", + "toml_datetime", + "winnow 0.5.40", +] + [[package]] name = "toml_edit" version = "0.22.14" @@ -9822,12 +9737,12 @@ checksum = "0976c77def3f1f75c4ef892a292c31c0bbe9e3d0702c63044d7c76db298171a3" [[package]] name = "url" -version = "2.5.1" +version = "2.5.2" source = "registry+https://github.com/rust-lang/crates.io-index" -checksum = "f7c25da092f0a868cdf09e8674cd3b7ef3a7d92a24253e663a2fb85e2496de56" +checksum = "22784dbdf76fdde8af1aeda5622b546b422b6fc585325248a2bf9f5e41e94d6c" dependencies = [ "form_urlencoded", - "idna 1.0.0", + "idna 0.5.0", "percent-encoding", "serde", ] @@ -9844,18 +9759,6 @@ version = "0.7.6" source = "registry+https://github.com/rust-lang/crates.io-index" checksum = "09cc8ee72d2a9becf2f2febe0205bbed8fc6615b7cb429ad062dc7b7ddd036a9" -[[package]] -name = "utf16_iter" -version = "1.0.5" -source = "registry+https://github.com/rust-lang/crates.io-index" -checksum = "c8232dd3cdaed5356e0f716d285e4b40b932ac434100fe9b7e0e8e935b9e6246" - -[[package]] -name = "utf8_iter" -version = "1.0.4" -source = "registry+https://github.com/rust-lang/crates.io-index" -checksum = "b6c140620e7ffbb22c2dee59cafe6084a59b5ffc27a8859a5f0d494b5d52b6be" - [[package]] name = "utf8parse" version = "0.2.2" @@ -9980,19 +9883,20 @@ checksum = "9c8d87e72b64a3b4db28d11ce29237c246188f4f51057d65a7eab63b7987e423" [[package]] name = "wasm-bindgen" -version = "0.2.92" +version = "0.2.93" source = "registry+https://github.com/rust-lang/crates.io-index" -checksum = "4be2531df63900aeb2bca0daaaddec08491ee64ceecbee5076636a3b026795a8" +checksum = "a82edfc16a6c469f5f44dc7b571814045d60404b55a0ee849f9bcfa2e63dd9b5" dependencies = [ "cfg-if", + "once_cell", "wasm-bindgen-macro", ] [[package]] name = "wasm-bindgen-backend" -version = "0.2.92" +version = "0.2.93" source = "registry+https://github.com/rust-lang/crates.io-index" -checksum = "614d787b966d3989fa7bb98a654e369c762374fd3213d212cfc0251257e747da" +checksum = "9de396da306523044d3302746f1208fa71d7532227f15e347e2d93e4145dd77b" dependencies = [ "bumpalo", "log", @@ -10017,9 +9921,9 @@ dependencies = [ [[package]] name = "wasm-bindgen-macro" -version = "0.2.92" +version = "0.2.93" source = "registry+https://github.com/rust-lang/crates.io-index" -checksum = "a1f8823de937b71b9460c0c34e25f3da88250760bec0ebac694b49997550d726" +checksum = "585c4c91a46b072c92e908d99cb1dcdf95c5218eeb6f3bf1efa991ee7a68cccf" dependencies = [ "quote", "wasm-bindgen-macro-support", @@ -10027,9 +9931,9 @@ dependencies = [ [[package]] name = "wasm-bindgen-macro-support" -version = "0.2.92" +version = "0.2.93" source = "registry+https://github.com/rust-lang/crates.io-index" -checksum = "e94f17b526d0a461a191c78ea52bbce64071ed5c04c9ffe424dcb38f74171bb7" +checksum = "afc340c74d9005395cf9dd098506f7f44e38f2b4a21c6aaacf9a105ea5e1e836" dependencies = [ "proc-macro2", "quote", @@ -10040,9 +9944,9 @@ dependencies = [ [[package]] name = "wasm-bindgen-shared" -version = "0.2.92" +version = "0.2.93" source = "registry+https://github.com/rust-lang/crates.io-index" -checksum = "af190c94f2773fdb3729c55b007a722abb5384da03bc0986df4c289bf5567e96" +checksum = "c62a0a307cb4a311d3a07867860911ca130c3494e8c2719593806c08bc5d0484" [[package]] name = "wasm-bindgen-test" @@ -10535,18 +10439,6 @@ dependencies = [ "syn 1.0.109", ] -[[package]] -name = "write16" -version = "1.0.0" -source = "registry+https://github.com/rust-lang/crates.io-index" -checksum = "d1890f4022759daae28ed4fe62859b1236caebfc61ede2f63ed4e695f3f6d936" - -[[package]] -name = "writeable" -version = "0.5.5" -source = "registry+https://github.com/rust-lang/crates.io-index" -checksum = "1e9df38ee2d2c3c5948ea468a8406ff0db0b29ae1ffde1bcf20ef305bcc95c51" - [[package]] name = "wyz" version = "0.5.1" @@ -10562,7 +10454,7 @@ version = "2.0.1" source = "registry+https://github.com/rust-lang/crates.io-index" checksum = "c7e468321c81fb07fa7f4c636c3972b9100f0346e5b6a9f2bd0603a52f7ed277" dependencies = [ - "curve25519-dalek 4.1.2", + "curve25519-dalek 4.1.3", "rand_core 0.6.4", "serde", "zeroize", @@ -10588,30 +10480,6 @@ dependencies = [ "is-terminal", ] -[[package]] -name = "yoke" -version = "0.7.4" -source = "registry+https://github.com/rust-lang/crates.io-index" -checksum = "6c5b1314b079b0930c31e3af543d8ee1757b1951ae1e1565ec704403a7240ca5" -dependencies = [ - "serde", - "stable_deref_trait", - "yoke-derive", - "zerofrom", -] - -[[package]] -name = "yoke-derive" -version = "0.7.4" -source = "registry+https://github.com/rust-lang/crates.io-index" -checksum = "28cc31741b18cb6f1d5ff12f5b7523e3d6eb0852bbbad19d73905511d9849b95" -dependencies = [ - "proc-macro2", - "quote", - "syn 2.0.66", - "synstructure", -] - [[package]] name = "zerocopy" version = "0.7.34" @@ -10632,27 +10500,6 @@ dependencies = [ "syn 2.0.66", ] -[[package]] -name = "zerofrom" -version = "0.1.4" -source = "registry+https://github.com/rust-lang/crates.io-index" -checksum = "91ec111ce797d0e0784a1116d0ddcdbea84322cd79e5d5ad173daeba4f93ab55" -dependencies = [ - "zerofrom-derive", -] - -[[package]] -name = "zerofrom-derive" -version = "0.1.4" -source = "registry+https://github.com/rust-lang/crates.io-index" -checksum = "0ea7b4a3637ea8669cedf0f1fd5c286a17f3de97b8dd5a70a6c167a1730e63a5" -dependencies = [ - "proc-macro2", - "quote", - "syn 2.0.66", - "synstructure", -] - [[package]] name = "zeroize" version = "1.6.0" @@ -10673,28 +10520,6 @@ dependencies = [ "syn 2.0.66", ] -[[package]] -name = "zerovec" -version = "0.10.2" -source = "registry+https://github.com/rust-lang/crates.io-index" -checksum = "bb2cc8827d6c0994478a15c53f374f46fbd41bea663d809b14744bc42e6b109c" -dependencies = [ - "yoke", - "zerofrom", - "zerovec-derive", -] - -[[package]] -name = "zerovec-derive" -version = "0.10.2" -source = "registry+https://github.com/rust-lang/crates.io-index" -checksum = "97cf56601ee5052b4417d90c8755c6683473c926039908196cf35d99f893ebe7" -dependencies = [ - "proc-macro2", - "quote", - "syn 2.0.66", -] - [[package]] name = "zip" version = "0.6.6" diff --git a/Cargo.toml b/Cargo.toml index 3a4af4b32d..b1c4a890de 100644 --- a/Cargo.toml +++ b/Cargo.toml @@ -168,7 +168,7 @@ aes = "0.8.1" aes-gcm = "0.10.1" anyhow = "1.0.71" argon2 = "0.5.0" -async-trait = "0.1.68" +async-trait = "0.1.81" axum = "0.7.5" axum-extra = "0.9.3" base64 = "0.21.4" @@ -179,7 +179,7 @@ bip39 = { version = "2.0.0", features = ["zeroize"] } bit-vec = "0.7.0" bitvec = "1.0.0" -blake3 = "1.3.1" +blake3 = "1.5.4" bloomfilter = "1.0.14" bs58 = "0.5.1" bytecodec = "0.4.15" @@ -191,9 +191,9 @@ chacha20 = "0.9.0" chacha20poly1305 = "0.10.1" chrono = "0.4.31" cipher = "0.4.3" -clap = "4.4.7" -clap_complete = "4.0" -clap_complete_fig = "4.0" +clap = "4.5.16" +clap_complete = "4.5" +clap_complete_fig = "4.5" colored = "2.0" comfy-table = "6.0.0" console-subscriber = "0.1.1" @@ -215,8 +215,8 @@ ecdsa = "0.16" ed25519-dalek = "2.1" etherparse = "0.13.0" eyre = "0.6.9" -fastrand = "2.1.0" -flate2 = "1.0.28" +fastrand = "2.1.1" +flate2 = "1.0.33" futures = "0.3.28" generic-array = "0.14.7" getrandom = "0.2.10" @@ -265,23 +265,23 @@ rand_distr = "0.4" rand_pcg = "0.3.1" rand_seeder = "0.2.3" rayon = "1.5.1" -regex = "1.8.4" +regex = "1.10.6" reqwest = { version = "0.12.4", default-features = false } rocket = "0.5.0" rocket_cors = "0.6.0" rocket_okapi = "0.8.0" -safer-ffi = "0.1.4" +safer-ffi = "0.1.12" schemars = "0.8.1" semver = "1.0.23" -serde = "1.0.152" -serde_bytes = "0.11.6" +serde = "1.0.209" +serde_bytes = "0.11.15" serde_derive = "1.0" -serde_json = "1.0.91" +serde_json = "1.0.127" serde_repr = "0.1" serde_with = "3.4.0" serde_yaml = "0.9.25" sha2 = "0.10.8" -si-scale = "0.2.2" +si-scale = "0.2.3" sphinx-packet = "0.1.1" sqlx = "0.6.3" strum = "0.25" @@ -291,7 +291,7 @@ sysinfo = "0.30.12" tap = "1.0.1" tar = "0.4.40" tempfile = "3.5.0" -thiserror = "1.0.48" +thiserror = "1.0.63" time = "0.3.30" tokio = "1.39" tokio-stream = "0.1.15" @@ -307,7 +307,7 @@ tracing-subscriber = "0.3.16" tracing-tree = "0.2.2" ts-rs = "7.0.0" tungstenite = { version = "0.20.1", default-features = false } -url = "2.4" +url = "2.5" utoipa = "4.2.0" utoipa-swagger-ui = "6.0.0" vergen = { version = "=8.3.1", default-features = false } @@ -343,7 +343,7 @@ cw4 = { version = "=1.1.2" } cw-controllers = { version = "=1.1.0" } # cosmrs-related -bip32 = { version = "0.5.1", default-features = false } +bip32 = { version = "0.5.2", default-features = false } # temporarily using a fork again (yay.) because we need staking and slashing support (which are already on main but not released) # plus response message parsing (which is, as of the time of writing this message, waiting to get merged) @@ -364,7 +364,7 @@ indexed_db_futures = { git = "https://github.com/TiemenSch/rust-indexed-db", bra js-sys = "0.3.69" serde-wasm-bindgen = "0.6.5" tsify = "0.4.5" -wasm-bindgen = "0.2.92" +wasm-bindgen = "0.2.93" wasm-bindgen-futures = "0.4.39" wasmtimer = "0.2.0" web-sys = "0.3.69" diff --git a/common/cosmwasm-smart-contracts/group-contract/Cargo.toml b/common/cosmwasm-smart-contracts/group-contract/Cargo.toml index 130fe163bc..0a6f33100b 100644 --- a/common/cosmwasm-smart-contracts/group-contract/Cargo.toml +++ b/common/cosmwasm-smart-contracts/group-contract/Cargo.toml @@ -11,4 +11,4 @@ cosmwasm-schema = { workspace = true } cw4 = { workspace = true } cw-controllers = { workspace = true } schemars = { workspace = true } -serde = { version = "1.0.103", default-features = false, features = ["derive"] } +serde = { version = "1.0.209", default-features = false, features = ["derive"] } diff --git a/common/cosmwasm-smart-contracts/multisig-contract/Cargo.toml b/common/cosmwasm-smart-contracts/multisig-contract/Cargo.toml index d328b1cdd3..5209cf8abf 100644 --- a/common/cosmwasm-smart-contracts/multisig-contract/Cargo.toml +++ b/common/cosmwasm-smart-contracts/multisig-contract/Cargo.toml @@ -14,5 +14,5 @@ cw-storage-plus = { workspace = true } cosmwasm-schema = { workspace = true } cosmwasm-std = { workspace = true } schemars = { workspace = true } -serde = { version = "1.0.103", default-features = false, features = ["derive"] } +serde = { version = "1.0.209", default-features = false, features = ["derive"] } thiserror = { workspace = true } diff --git a/common/crypto/Cargo.toml b/common/crypto/Cargo.toml index f66b5fba3c..2593c47b30 100644 --- a/common/crypto/Cargo.toml +++ b/common/crypto/Cargo.toml @@ -20,7 +20,7 @@ cipher = { workspace = true, optional = true } x25519-dalek = { workspace = true, features = ["static_secrets"], optional = true } ed25519-dalek = { workspace = true, features = ["rand_core"], optional = true } rand = { workspace = true, optional = true } -serde_bytes = { version = "0.11.6", optional = true } +serde_bytes = { version = "0.11.15", optional = true } serde_crate = { version = "1.0", optional = true, default-features = false, features = ["derive"], package = "serde" } subtle-encoding = { workspace = true, features = ["bech32-preview"] } thiserror = { workspace = true } diff --git a/common/nymsphinx/Cargo.toml b/common/nymsphinx/Cargo.toml index d377a8bdec..167b33a40a 100644 --- a/common/nymsphinx/Cargo.toml +++ b/common/nymsphinx/Cargo.toml @@ -42,7 +42,7 @@ nym-crypto = { path = "../crypto", version = "0.4.0", features = [ path = "framing" [target."cfg(not(target_arch = \"wasm32\"))".dependencies.tokio] -version = "1.24.1" +version = "1.39.3" features = ["sync"] [features] diff --git a/common/nymsphinx/anonymous-replies/Cargo.toml b/common/nymsphinx/anonymous-replies/Cargo.toml index 5366b90e3e..f8a1174d62 100644 --- a/common/nymsphinx/anonymous-replies/Cargo.toml +++ b/common/nymsphinx/anonymous-replies/Cargo.toml @@ -21,7 +21,7 @@ nym-sphinx-types = { path = "../types" } nym-topology = { path = "../../topology" } [target."cfg(target_arch = \"wasm32\")".dependencies.wasm-bindgen] -version = "0.2.83" +version = "0.2.93" [dev-dependencies] rand_chacha = { workspace = true } From 00aff01deb66b3669efc7e11b495359cd9aafa5e Mon Sep 17 00:00:00 2001 From: "dependabot[bot]" <49699333+dependabot[bot]@users.noreply.github.com> Date: Tue, 27 Aug 2024 13:22:10 +0200 Subject: [PATCH 30/93] build(deps): bump serde_with from 3.8.1 to 3.9.0 (#4792) Bumps [serde_with](https://github.com/jonasbb/serde_with) from 3.8.1 to 3.9.0. - [Release notes](https://github.com/jonasbb/serde_with/releases) - [Commits](https://github.com/jonasbb/serde_with/compare/v3.8.1...v3.9.0) --- updated-dependencies: - dependency-name: serde_with dependency-type: direct:production update-type: version-update:semver-minor ... Signed-off-by: dependabot[bot] Co-authored-by: dependabot[bot] <49699333+dependabot[bot]@users.noreply.github.com> --- Cargo.lock | 8 ++++---- Cargo.toml | 2 +- 2 files changed, 5 insertions(+), 5 deletions(-) diff --git a/Cargo.lock b/Cargo.lock index 936d174d81..121f7b5b36 100644 --- a/Cargo.lock +++ b/Cargo.lock @@ -8033,9 +8033,9 @@ dependencies = [ [[package]] name = "serde_with" -version = "3.8.1" +version = "3.9.0" source = "registry+https://github.com/rust-lang/crates.io-index" -checksum = "0ad483d2ab0149d5a5ebcd9972a3852711e0153d863bf5a5d0391d28883c4a20" +checksum = "69cecfa94848272156ea67b2b1a53f20fc7bc638c4a46d2f8abde08f05f4b857" dependencies = [ "base64 0.22.1", "chrono", @@ -8051,9 +8051,9 @@ dependencies = [ [[package]] name = "serde_with_macros" -version = "3.8.1" +version = "3.9.0" source = "registry+https://github.com/rust-lang/crates.io-index" -checksum = "65569b702f41443e8bc8bbb1c5779bd0450bbe723b56198980e80ec45780bce2" +checksum = "a8fee4991ef4f274617a51ad4af30519438dacb2f56ac773b08a1922ff743350" dependencies = [ "darling 0.20.9", "proc-macro2", diff --git a/Cargo.toml b/Cargo.toml index b1c4a890de..f0253bb1e8 100644 --- a/Cargo.toml +++ b/Cargo.toml @@ -278,7 +278,7 @@ serde_bytes = "0.11.15" serde_derive = "1.0" serde_json = "1.0.127" serde_repr = "0.1" -serde_with = "3.4.0" +serde_with = "3.9.0" serde_yaml = "0.9.25" sha2 = "0.10.8" si-scale = "0.2.3" From f1d97e55788bf4f27c0bd46bdead8f022d6eba3f Mon Sep 17 00:00:00 2001 From: "dependabot[bot]" <49699333+dependabot[bot]@users.noreply.github.com> Date: Tue, 27 Aug 2024 13:22:30 +0200 Subject: [PATCH 31/93] build(deps): bump acifani/setup-tinygo from 1 to 2 (#4785) Bumps [acifani/setup-tinygo](https://github.com/acifani/setup-tinygo) from 1 to 2. - [Release notes](https://github.com/acifani/setup-tinygo/releases) - [Commits](https://github.com/acifani/setup-tinygo/compare/v1...v2) --- updated-dependencies: - dependency-name: acifani/setup-tinygo dependency-type: direct:production update-type: version-update:semver-major ... Signed-off-by: dependabot[bot] Co-authored-by: dependabot[bot] <49699333+dependabot[bot]@users.noreply.github.com> --- .github/workflows/publish-sdk-npm.yml | 2 +- 1 file changed, 1 insertion(+), 1 deletion(-) diff --git a/.github/workflows/publish-sdk-npm.yml b/.github/workflows/publish-sdk-npm.yml index f6228b210a..12d9341472 100644 --- a/.github/workflows/publish-sdk-npm.yml +++ b/.github/workflows/publish-sdk-npm.yml @@ -34,7 +34,7 @@ jobs: go-version: "1.20" - name: Install TinyGo - uses: acifani/setup-tinygo@v1 + uses: acifani/setup-tinygo@v2 with: tinygo-version: "0.27.0" From dd695129ddade88da7bf8c957d97bd3125237ff4 Mon Sep 17 00:00:00 2001 From: "dependabot[bot]" <49699333+dependabot[bot]@users.noreply.github.com> Date: Tue, 27 Aug 2024 13:38:38 +0200 Subject: [PATCH 32/93] build(deps): bump actions/setup-go from 4 to 5 (#4799) Bumps [actions/setup-go](https://github.com/actions/setup-go) from 4 to 5. - [Release notes](https://github.com/actions/setup-go/releases) - [Commits](https://github.com/actions/setup-go/compare/v4...v5) --- updated-dependencies: - dependency-name: actions/setup-go dependency-type: direct:production update-type: version-update:semver-major ... Signed-off-by: dependabot[bot] Co-authored-by: dependabot[bot] <49699333+dependabot[bot]@users.noreply.github.com> --- .github/workflows/ci-lint-typescript.yml | 2 +- .github/workflows/ci-sdk-docs-typescript.yml | 2 +- .github/workflows/ci-sdk-wasm.yml | 2 +- .github/workflows/publish-sdk-npm.yml | 2 +- 4 files changed, 4 insertions(+), 4 deletions(-) diff --git a/.github/workflows/ci-lint-typescript.yml b/.github/workflows/ci-lint-typescript.yml index bd658b0a15..ab9ee4e8eb 100644 --- a/.github/workflows/ci-lint-typescript.yml +++ b/.github/workflows/ci-lint-typescript.yml @@ -38,7 +38,7 @@ jobs: version: '116' - name: Set up Go - uses: actions/setup-go@v4 + uses: actions/setup-go@v5 with: go-version: '1.20' diff --git a/.github/workflows/ci-sdk-docs-typescript.yml b/.github/workflows/ci-sdk-docs-typescript.yml index 937b07f2f3..382965f25a 100644 --- a/.github/workflows/ci-sdk-docs-typescript.yml +++ b/.github/workflows/ci-sdk-docs-typescript.yml @@ -26,7 +26,7 @@ jobs: run: npm install -g yarn - name: Set up Go - uses: actions/setup-go@v4 + uses: actions/setup-go@v5 with: go-version: '1.20' diff --git a/.github/workflows/ci-sdk-wasm.yml b/.github/workflows/ci-sdk-wasm.yml index 16e402ab6c..279defeb0e 100644 --- a/.github/workflows/ci-sdk-wasm.yml +++ b/.github/workflows/ci-sdk-wasm.yml @@ -28,7 +28,7 @@ jobs: components: rustfmt, clippy - name: Set up Go - uses: actions/setup-go@v4 + uses: actions/setup-go@v5 with: go-version: '1.20' diff --git a/.github/workflows/publish-sdk-npm.yml b/.github/workflows/publish-sdk-npm.yml index 12d9341472..7c29bbed34 100644 --- a/.github/workflows/publish-sdk-npm.yml +++ b/.github/workflows/publish-sdk-npm.yml @@ -29,7 +29,7 @@ jobs: run: cargo install wasm-opt - name: Set up Go - uses: actions/setup-go@v4 + uses: actions/setup-go@v5 with: go-version: "1.20" From 72306f12156e0aa515c83e5637dafb56d8cea89f Mon Sep 17 00:00:00 2001 From: "dependabot[bot]" <49699333+dependabot[bot]@users.noreply.github.com> Date: Tue, 27 Aug 2024 13:50:37 +0200 Subject: [PATCH 33/93] build(deps): bump actions/download-artifact from 3 to 4 (#4786) MIME-Version: 1.0 Content-Type: text/plain; charset=UTF-8 Content-Transfer-Encoding: 8bit * build(deps): bump actions/download-artifact from 3 to 4 Bumps [actions/download-artifact](https://github.com/actions/download-artifact) from 3 to 4. - [Release notes](https://github.com/actions/download-artifact/releases) - [Commits](https://github.com/actions/download-artifact/compare/v3...v4) --- updated-dependencies: - dependency-name: actions/download-artifact dependency-type: direct:production update-type: version-update:semver-major ... Signed-off-by: dependabot[bot] * Also upgrade corresponding upload-artifact actions --------- Signed-off-by: dependabot[bot] Co-authored-by: dependabot[bot] <49699333+dependabot[bot]@users.noreply.github.com> Co-authored-by: Jon Häggblad --- .github/workflows/nightly-security-audit.yml | 4 ++-- .github/workflows/publish-nyms5-android-apk.yml | 4 ++-- 2 files changed, 4 insertions(+), 4 deletions(-) diff --git a/.github/workflows/nightly-security-audit.yml b/.github/workflows/nightly-security-audit.yml index 8ccae9790d..be855f5776 100644 --- a/.github/workflows/nightly-security-audit.yml +++ b/.github/workflows/nightly-security-audit.yml @@ -20,7 +20,7 @@ jobs: find . -name Cargo.toml -exec cargo deny --manifest-path {} check \ advisories -A advisory-not-detected --hide-inclusion-graph \; &> \ >(uniq &> .github/workflows/support-files/notifications/deny.message ) - - uses: actions/upload-artifact@v3 + - uses: actions/upload-artifact@v4 with: name: report path: .github/workflows/support-files/notifications/deny.message @@ -31,7 +31,7 @@ jobs: - name: Check out repository code uses: actions/checkout@v4 - name: Download report from previous job - uses: actions/download-artifact@v3 + uses: actions/download-artifact@v4 with: name: report path: .github/workflows/support-files/notifications diff --git a/.github/workflows/publish-nyms5-android-apk.yml b/.github/workflows/publish-nyms5-android-apk.yml index da6db40ecb..0ac8c9ae49 100644 --- a/.github/workflows/publish-nyms5-android-apk.yml +++ b/.github/workflows/publish-nyms5-android-apk.yml @@ -84,7 +84,7 @@ jobs: apk/nyms5-arch64-release.apk - name: Upload APKs - uses: actions/upload-artifact@v3 + uses: actions/upload-artifact@v4 with: name: nyms5-apk-arch64 path: | @@ -99,7 +99,7 @@ jobs: - name: Checkout uses: actions/checkout@v4 - name: Download binary artifact - uses: actions/download-artifact@v3 + uses: actions/download-artifact@v4 with: name: nyms5-apk-arch64 path: apk From 8c250adcfd6cc8743816dd4825326b146571d375 Mon Sep 17 00:00:00 2001 From: "dependabot[bot]" <49699333+dependabot[bot]@users.noreply.github.com> Date: Tue, 27 Aug 2024 14:12:44 +0200 Subject: [PATCH 34/93] build(deps): bump bytes from 1.6.0 to 1.7.1 (#4794) Bumps [bytes](https://github.com/tokio-rs/bytes) from 1.6.0 to 1.7.1. - [Release notes](https://github.com/tokio-rs/bytes/releases) - [Changelog](https://github.com/tokio-rs/bytes/blob/master/CHANGELOG.md) - [Commits](https://github.com/tokio-rs/bytes/compare/v1.6.0...v1.7.1) --- updated-dependencies: - dependency-name: bytes dependency-type: direct:production update-type: version-update:semver-minor ... Signed-off-by: dependabot[bot] Co-authored-by: dependabot[bot] <49699333+dependabot[bot]@users.noreply.github.com> --- Cargo.lock | 4 ++-- Cargo.toml | 2 +- 2 files changed, 3 insertions(+), 3 deletions(-) diff --git a/Cargo.lock b/Cargo.lock index 121f7b5b36..b1b356fe44 100644 --- a/Cargo.lock +++ b/Cargo.lock @@ -749,9 +749,9 @@ checksum = "1fd0f2584146f6f2ef48085050886acf353beff7305ebd1ae69500e27c67f64b" [[package]] name = "bytes" -version = "1.6.0" +version = "1.7.1" source = "registry+https://github.com/rust-lang/crates.io-index" -checksum = "514de17de45fdb8dc022b1a7975556c53c86f9f0aa5f534b98977b171857c2c9" +checksum = "8318a53db07bb3f8dca91a600466bdb3f2eaadeedfdbcf02e1accbad9271ba50" dependencies = [ "serde", ] diff --git a/Cargo.toml b/Cargo.toml index f0253bb1e8..4efa1697a7 100644 --- a/Cargo.toml +++ b/Cargo.toml @@ -183,7 +183,7 @@ blake3 = "1.5.4" bloomfilter = "1.0.14" bs58 = "0.5.1" bytecodec = "0.4.15" -bytes = "1.5.0" +bytes = "1.7.1" cargo_metadata = "0.18.1" celes = "2.4.0" cfg-if = "1.0.0" From b6c15deae692f18f64da328bc4cc163531ca6735 Mon Sep 17 00:00:00 2001 From: "dependabot[bot]" <49699333+dependabot[bot]@users.noreply.github.com> Date: Tue, 27 Aug 2024 14:44:56 +0200 Subject: [PATCH 35/93] build(deps): bump sysinfo from 0.27.8 to 0.30.12 (#4795) MIME-Version: 1.0 Content-Type: text/plain; charset=UTF-8 Content-Transfer-Encoding: 8bit * build(deps): bump sysinfo from 0.27.8 to 0.30.12 Bumps [sysinfo](https://github.com/GuillaumeGomez/sysinfo) from 0.27.8 to 0.30.12. - [Changelog](https://github.com/GuillaumeGomez/sysinfo/blob/master/CHANGELOG.md) - [Commits](https://github.com/GuillaumeGomez/sysinfo/commits) --- updated-dependencies: - dependency-name: sysinfo dependency-type: direct:production update-type: version-update:semver-minor ... Signed-off-by: dependabot[bot] * Migrade to latest sysinfo in mixnode legacy hardware * Use workspace version --------- Signed-off-by: dependabot[bot] Co-authored-by: dependabot[bot] <49699333+dependabot[bot]@users.noreply.github.com> Co-authored-by: Jon Häggblad --- Cargo.lock | 19 ++----------------- mixnode/Cargo.toml | 2 +- mixnode/src/node/http/legacy/hardware.rs | 4 ++-- 3 files changed, 5 insertions(+), 20 deletions(-) diff --git a/Cargo.lock b/Cargo.lock index b1b356fe44..17814faec5 100644 --- a/Cargo.lock +++ b/Cargo.lock @@ -5234,7 +5234,7 @@ dependencies = [ "rand 0.8.5", "serde", "serde_json", - "sysinfo 0.27.8", + "sysinfo", "thiserror", "time", "tokio", @@ -5415,7 +5415,7 @@ dependencies = [ "semver 1.0.23", "serde", "serde_json", - "sysinfo 0.30.12", + "sysinfo", "thiserror", "tokio", "toml 0.8.14", @@ -8636,21 +8636,6 @@ version = "1.0.1" source = "registry+https://github.com/rust-lang/crates.io-index" checksum = "a7065abeca94b6a8a577f9bd45aa0867a2238b74e8eb67cf10d492bc39351394" -[[package]] -name = "sysinfo" -version = "0.27.8" -source = "registry+https://github.com/rust-lang/crates.io-index" -checksum = "a902e9050fca0a5d6877550b769abd2bd1ce8c04634b941dbe2809735e1a1e33" -dependencies = [ - "cfg-if", - "core-foundation-sys", - "libc", - "ntapi", - "once_cell", - "rayon", - "winapi", -] - [[package]] name = "sysinfo" version = "0.30.12" diff --git a/mixnode/Cargo.toml b/mixnode/Cargo.toml index db4473b530..6066817e0c 100644 --- a/mixnode/Cargo.toml +++ b/mixnode/Cargo.toml @@ -31,7 +31,7 @@ log = { workspace = true } rand = { workspace = true } serde = { workspace = true, features = ["derive"] } serde_json = { workspace = true } -sysinfo = "0.27.7" +sysinfo = { workspace = true } time.workspace = true tokio = { workspace = true, features = ["rt-multi-thread", "net", "signal"] } tokio-util = { workspace = true, features = ["codec"] } diff --git a/mixnode/src/node/http/legacy/hardware.rs b/mixnode/src/node/http/legacy/hardware.rs index a64ca3f5b5..b1ce61b6ff 100644 --- a/mixnode/src/node/http/legacy/hardware.rs +++ b/mixnode/src/node/http/legacy/hardware.rs @@ -5,7 +5,7 @@ use axum::extract::Query; use cupid::TopologyType; use nym_http_api_common::{FormattedResponse, OutputParams}; use serde::Serialize; -use sysinfo::{System, SystemExt}; +use sysinfo::System; #[derive(Serialize, Debug)] pub struct Hardware { @@ -43,7 +43,7 @@ fn hardware_info() -> Option { /// Sysinfo gives back basic stuff like number of CPU cores and available memory. If available, this includes the hardware encryption /// extensions report fn hardware_from_sysinfo(crypto_hardware: Option) -> Option { - if System::IS_SUPPORTED { + if sysinfo::IS_SUPPORTED_SYSTEM { let mut system = System::new_all(); system.refresh_all(); let ram = format!("{}KB", system.total_memory()); From 279de8a09b1d6b4f08dc190649b11225c4ca7c8e Mon Sep 17 00:00:00 2001 From: =?UTF-8?q?Jon=20H=C3=A4ggblad?= Date: Tue, 27 Aug 2024 15:06:17 +0200 Subject: [PATCH 36/93] Run cargo-autoinherit for a few new crates (#4801) * Run cargo-autoinherit for a few new crates * Sort crates list * sort --- Cargo.toml | 4 ++++ common/crypto/Cargo.toml | 2 +- common/nym_offline_compact_ecash/Cargo.toml | 2 +- nym-api/Cargo.toml | 2 +- nym-network-monitor/Cargo.toml | 2 +- tools/internal/testnet-manager/Cargo.toml | 4 ++-- wasm/zknym-lib/Cargo.toml | 4 ++-- 7 files changed, 12 insertions(+), 8 deletions(-) diff --git a/Cargo.toml b/Cargo.toml index 4efa1697a7..4e3529fee4 100644 --- a/Cargo.toml +++ b/Cargo.toml @@ -196,6 +196,7 @@ clap_complete = "4.5" clap_complete_fig = "4.5" colored = "2.0" comfy-table = "6.0.0" +console = "0.15.8" console-subscriber = "0.1.1" console_error_panic_hook = "0.1" const-str = "0.5.6" @@ -232,6 +233,7 @@ httpcodec = "0.2.3" humantime = "2.1.0" humantime-serde = "1.1.1" hyper = "1.3.1" +indicatif = "0.17.8" inquire = "0.6.2" ip_network = "0.4.1" ipnetwork = "0.16" @@ -252,6 +254,7 @@ opentelemetry = "0.19.0" opentelemetry-jaeger = "0.18.0" parking_lot = "0.12.1" pem = "0.8" +petgraph = "0.6.5" pin-project = "1.0" pretty_env_logger = "0.4.0" publicsuffix = "2.2.3" @@ -310,6 +313,7 @@ tungstenite = { version = "0.20.1", default-features = false } url = "2.5" utoipa = "4.2.0" utoipa-swagger-ui = "6.0.0" +uuid = "*" vergen = { version = "=8.3.1", default-features = false } walkdir = "2" wasm-bindgen-test = "0.3.36" diff --git a/common/crypto/Cargo.toml b/common/crypto/Cargo.toml index 2593c47b30..ff002afa0d 100644 --- a/common/crypto/Cargo.toml +++ b/common/crypto/Cargo.toml @@ -20,7 +20,7 @@ cipher = { workspace = true, optional = true } x25519-dalek = { workspace = true, features = ["static_secrets"], optional = true } ed25519-dalek = { workspace = true, features = ["rand_core"], optional = true } rand = { workspace = true, optional = true } -serde_bytes = { version = "0.11.15", optional = true } +serde_bytes = { workspace = true, optional = true } serde_crate = { version = "1.0", optional = true, default-features = false, features = ["derive"], package = "serde" } subtle-encoding = { workspace = true, features = ["bech32-preview"] } thiserror = { workspace = true } diff --git a/common/nym_offline_compact_ecash/Cargo.toml b/common/nym_offline_compact_ecash/Cargo.toml index 19bf70cf62..e9d2acbda5 100644 --- a/common/nym_offline_compact_ecash/Cargo.toml +++ b/common/nym_offline_compact_ecash/Cargo.toml @@ -21,7 +21,7 @@ thiserror = { workspace = true } sha2 = "0.9" bs58 = { workspace = true } serde = { workspace = true, features = ["derive"] } -rayon = { version = "1.5.0", optional = true } +rayon = { workspace = true, optional = true } zeroize = { workspace = true, features = ["zeroize_derive"] } ff = { workspace = true } group = { workspace = true } diff --git a/nym-api/Cargo.toml b/nym-api/Cargo.toml index 9e58b24f1c..d6906d0ce8 100644 --- a/nym-api/Cargo.toml +++ b/nym-api/Cargo.toml @@ -20,7 +20,7 @@ async-trait = { workspace = true } bs58 = { workspace = true } bip39 = { workspace = true } bincode.workspace = true -bloomfilter = "1.0.13" +bloomfilter = { workspace = true } cfg-if = { workspace = true } clap = { workspace = true, features = ["cargo", "derive"] } console-subscriber = { workspace = true, optional = true } # validator-api needs to be built with RUSTFLAGS="--cfg tokio_unstable" diff --git a/nym-network-monitor/Cargo.toml b/nym-network-monitor/Cargo.toml index 939a8b7146..5f608175f0 100644 --- a/nym-network-monitor/Cargo.toml +++ b/nym-network-monitor/Cargo.toml @@ -17,7 +17,7 @@ clap = { workspace = true, features = ["derive"] } dashmap = { workspace = true } futures = { workspace = true } log = { workspace = true } -petgraph = "0.6.5" +petgraph = { workspace = true } rand = { workspace = true } rand_chacha = { workspace = true } reqwest = { workspace = true, features = ["json"] } diff --git a/tools/internal/testnet-manager/Cargo.toml b/tools/internal/testnet-manager/Cargo.toml index 929ac555a6..bea1c68d4f 100644 --- a/tools/internal/testnet-manager/Cargo.toml +++ b/tools/internal/testnet-manager/Cargo.toml @@ -12,10 +12,10 @@ license.workspace = true anyhow.workspace = true bip39.workspace = true bs58.workspace = true -console = "0.15.8" +console = { workspace = true } cw-utils.workspace = true clap = { workspace = true, features = ["cargo", "derive"] } -indicatif = "0.17.8" +indicatif = { workspace = true } rand.workspace = true serde = { workspace = true, features = ["derive"] } serde_json.workspace = true diff --git a/wasm/zknym-lib/Cargo.toml b/wasm/zknym-lib/Cargo.toml index 5ef55b0314..75a203b727 100644 --- a/wasm/zknym-lib/Cargo.toml +++ b/wasm/zknym-lib/Cargo.toml @@ -16,13 +16,13 @@ crate-type = ["cdylib", "rlib"] [dependencies] async-trait.workspace = true bs58.workspace = true -getrandom = { version = "0.2", features = ["js"] } +getrandom = { workspace = true, features = ["js"] } js-sys.workspace = true wasm-bindgen.workspace = true serde = { workspace = true, features = ["derive"] } thiserror.workspace = true tsify = { workspace = true, features = ["js"] } -uuid = { version = "*", features = ["serde"] } +uuid = { workspace = true, features = ["serde"] } reqwest = { workspace = true } wasmtimer = { workspace = true } zeroize.workspace = true From 9378100957fe1a2fe53139fcd1fb14caa04782b9 Mon Sep 17 00:00:00 2001 From: "dependabot[bot]" <49699333+dependabot[bot]@users.noreply.github.com> Date: Tue, 27 Aug 2024 15:30:24 +0000 Subject: [PATCH 37/93] build(deps): bump base64 from 0.13.1 to 0.22.1 Bumps [base64](https://github.com/marshallpierce/rust-base64) from 0.13.1 to 0.22.1. - [Changelog](https://github.com/marshallpierce/rust-base64/blob/master/RELEASE-NOTES.md) - [Commits](https://github.com/marshallpierce/rust-base64/compare/v0.13.1...v0.22.1) --- updated-dependencies: - dependency-name: base64 dependency-type: direct:production update-type: version-update:semver-minor ... Signed-off-by: dependabot[bot] --- Cargo.lock | 20 +++++++++---------- Cargo.toml | 2 +- .../client-libs/validator-client/Cargo.toml | 2 +- common/commands/Cargo.toml | 2 +- tools/nym-cli/Cargo.toml | 2 +- 5 files changed, 14 insertions(+), 14 deletions(-) diff --git a/Cargo.lock b/Cargo.lock index 17814faec5..1070f7b681 100644 --- a/Cargo.lock +++ b/Cargo.lock @@ -4316,7 +4316,7 @@ name = "nym-cli" version = "1.1.40" dependencies = [ "anyhow", - "base64 0.13.1", + "base64 0.22.1", "bip39", "bs58 0.5.1", "clap 4.5.16", @@ -4341,7 +4341,7 @@ name = "nym-cli-commands" version = "1.0.0" dependencies = [ "anyhow", - "base64 0.13.1", + "base64 0.22.1", "bip39", "bs58 0.5.1", "cfg-if", @@ -4432,7 +4432,7 @@ name = "nym-client-core" version = "1.1.15" dependencies = [ "async-trait", - "base64 0.21.7", + "base64 0.22.1", "bs58 0.5.1", "cfg-if", "clap 4.5.16", @@ -5430,7 +5430,7 @@ version = "0.1.0" dependencies = [ "axum 0.7.5", "axum-extra", - "base64 0.21.7", + "base64 0.22.1", "colored", "dashmap", "fastrand 2.1.1", @@ -5463,7 +5463,7 @@ name = "nym-node-requests" version = "0.1.0" dependencies = [ "async-trait", - "base64 0.21.7", + "base64 0.22.1", "celes", "humantime 2.1.0", "humantime-serde", @@ -5633,7 +5633,7 @@ dependencies = [ name = "nym-serde-helpers" version = "0.1.0" dependencies = [ - "base64 0.21.7", + "base64 0.22.1", "bs58 0.5.1", "serde", ] @@ -5999,7 +5999,7 @@ dependencies = [ name = "nym-types" version = "1.0.0" dependencies = [ - "base64 0.21.7", + "base64 0.22.1", "cosmrs 0.17.0-pre", "cosmwasm-std", "eyre", @@ -6029,7 +6029,7 @@ name = "nym-validator-client" version = "0.1.0" dependencies = [ "async-trait", - "base64 0.13.1", + "base64 0.22.1", "bip32", "bip39", "colored", @@ -6147,7 +6147,7 @@ dependencies = [ name = "nym-wireguard" version = "0.1.0" dependencies = [ - "base64 0.21.7", + "base64 0.22.1", "bincode", "chrono", "dashmap", @@ -6169,7 +6169,7 @@ dependencies = [ name = "nym-wireguard-types" version = "0.1.0" dependencies = [ - "base64 0.21.7", + "base64 0.22.1", "hmac", "log", "nym-config", diff --git a/Cargo.toml b/Cargo.toml index 4e3529fee4..8c21c0ea61 100644 --- a/Cargo.toml +++ b/Cargo.toml @@ -171,7 +171,7 @@ argon2 = "0.5.0" async-trait = "0.1.81" axum = "0.7.5" axum-extra = "0.9.3" -base64 = "0.21.4" +base64 = "0.22.1" bincode = "1.3.3" bip39 = { version = "2.0.0", features = ["zeroize"] } diff --git a/common/client-libs/validator-client/Cargo.toml b/common/client-libs/validator-client/Cargo.toml index 2bf66895c0..dee9577516 100644 --- a/common/client-libs/validator-client/Cargo.toml +++ b/common/client-libs/validator-client/Cargo.toml @@ -9,7 +9,7 @@ license.workspace = true # See more keys and their definitions at https://doc.rust-lang.org/cargo/reference/manifest.html [dependencies] -base64 = "0.13" +base64 = "0.22" colored = { workspace = true } nym-coconut-dkg-common = { path = "../../cosmwasm-smart-contracts/coconut-dkg" } diff --git a/common/commands/Cargo.toml b/common/commands/Cargo.toml index 2045cf0d2a..bab9b86a6e 100644 --- a/common/commands/Cargo.toml +++ b/common/commands/Cargo.toml @@ -7,7 +7,7 @@ license.workspace = true [dependencies] anyhow = { workspace = true } -base64 = "0.13.0" +base64 = "0.22.1" bip39 = { workspace = true } bs58 = { workspace = true } comfy-table = { workspace = true } diff --git a/tools/nym-cli/Cargo.toml b/tools/nym-cli/Cargo.toml index e590e45141..dc8e8990f9 100644 --- a/tools/nym-cli/Cargo.toml +++ b/tools/nym-cli/Cargo.toml @@ -6,7 +6,7 @@ edition = "2021" license.workspace = true [dependencies] -base64 = "0.13.0" +base64 = "0.22.1" bs58 = { workspace = true } clap = { workspace = true, features = ["derive"] } clap_complete = { workspace = true } From 5f21f8334b4119f3fcb112fd7e13b6f3f65de0d4 Mon Sep 17 00:00:00 2001 From: "dependabot[bot]" <49699333+dependabot[bot]@users.noreply.github.com> Date: Tue, 27 Aug 2024 15:32:46 +0000 Subject: [PATCH 38/93] build(deps): bump android_logger from 0.13.3 to 0.14.1 Bumps [android_logger](https://github.com/rust-mobile/android_logger-rs) from 0.13.3 to 0.14.1. - [Release notes](https://github.com/rust-mobile/android_logger-rs/releases) - [Changelog](https://github.com/rust-mobile/android_logger-rs/blob/master/CHANGELOG.md) - [Commits](https://github.com/rust-mobile/android_logger-rs/commits/0.14.1) --- updated-dependencies: - dependency-name: android_logger dependency-type: direct:production update-type: version-update:semver-minor ... Signed-off-by: dependabot[bot] --- Cargo.lock | 29 ++++++++++++++--------------- sdk/lib/socks5-listener/Cargo.toml | 2 +- 2 files changed, 15 insertions(+), 16 deletions(-) diff --git a/Cargo.lock b/Cargo.lock index 17814faec5..1b936b46f0 100644 --- a/Cargo.lock +++ b/Cargo.lock @@ -138,14 +138,13 @@ checksum = "5ecc8056bf6ab9892dcd53216c83d1597487d7dacac16c8df6b877d127df9937" [[package]] name = "android_logger" -version = "0.13.3" +version = "0.14.1" source = "registry+https://github.com/rust-lang/crates.io-index" -checksum = "c494134f746c14dc653a35a4ea5aca24ac368529da5370ecf41fe0341c35772f" +checksum = "05b07e8e73d720a1f2e4b6014766e6039fd2e96a4fa44e2a78d0e1fa2ff49826" dependencies = [ "android_log-sys", - "env_logger 0.10.2", + "env_filter", "log", - "once_cell", ] [[package]] @@ -2182,6 +2181,16 @@ dependencies = [ "cfg-if", ] +[[package]] +name = "env_filter" +version = "0.1.2" +source = "registry+https://github.com/rust-lang/crates.io-index" +checksum = "4f2c92ceda6ceec50f43169f9ee8424fe2db276791afde7b2cd8bc084cb376ab" +dependencies = [ + "log", + "regex", +] + [[package]] name = "env_logger" version = "0.7.1" @@ -2195,16 +2204,6 @@ dependencies = [ "termcolor", ] -[[package]] -name = "env_logger" -version = "0.10.2" -source = "registry+https://github.com/rust-lang/crates.io-index" -checksum = "4cd405aab171cb85d6735e5c8d9db038c17d3ca007a4d2c25f337935c3d90580" -dependencies = [ - "log", - "regex", -] - [[package]] name = "equivalent" version = "1.0.1" @@ -6759,7 +6758,7 @@ version = "0.4.0" source = "registry+https://github.com/rust-lang/crates.io-index" checksum = "926d36b9553851b8b0005f1275891b392ee4d2d833852c417ed025477350fb9d" dependencies = [ - "env_logger 0.7.1", + "env_logger", "log", ] diff --git a/sdk/lib/socks5-listener/Cargo.toml b/sdk/lib/socks5-listener/Cargo.toml index 6463d4eb74..ac8c4d3e81 100644 --- a/sdk/lib/socks5-listener/Cargo.toml +++ b/sdk/lib/socks5-listener/Cargo.toml @@ -32,7 +32,7 @@ safer-ffi = { workspace = true } [target.'cfg(target_os="android")'.dependencies] jni = { version = "0.21", default-features = false } -android_logger = "0.13.1" +android_logger = "0.14.1" [features] From 37d9f919227cec148e0355404b4029c0949e4dea Mon Sep 17 00:00:00 2001 From: "dependabot[bot]" <49699333+dependabot[bot]@users.noreply.github.com> Date: Tue, 27 Aug 2024 17:45:24 +0200 Subject: [PATCH 39/93] build(deps): bump the patch-updates group with 4 updates (#4804) Bumps the patch-updates group with 4 updates: [clap_complete](https://github.com/clap-rs/clap), [js-sys](https://github.com/rustwasm/wasm-bindgen), [wasm-bindgen-futures](https://github.com/rustwasm/wasm-bindgen) and [web-sys](https://github.com/rustwasm/wasm-bindgen). Updates `clap_complete` from 4.5.23 to 4.5.24 - [Release notes](https://github.com/clap-rs/clap/releases) - [Changelog](https://github.com/clap-rs/clap/blob/master/CHANGELOG.md) - [Commits](https://github.com/clap-rs/clap/compare/clap_complete-v4.5.23...clap_complete-v4.5.24) Updates `js-sys` from 0.3.69 to 0.3.70 - [Release notes](https://github.com/rustwasm/wasm-bindgen/releases) - [Changelog](https://github.com/rustwasm/wasm-bindgen/blob/main/CHANGELOG.md) - [Commits](https://github.com/rustwasm/wasm-bindgen/commits) Updates `wasm-bindgen-futures` from 0.4.42 to 0.4.43 - [Release notes](https://github.com/rustwasm/wasm-bindgen/releases) - [Changelog](https://github.com/rustwasm/wasm-bindgen/blob/main/CHANGELOG.md) - [Commits](https://github.com/rustwasm/wasm-bindgen/commits) Updates `web-sys` from 0.3.69 to 0.3.70 - [Release notes](https://github.com/rustwasm/wasm-bindgen/releases) - [Changelog](https://github.com/rustwasm/wasm-bindgen/blob/main/CHANGELOG.md) - [Commits](https://github.com/rustwasm/wasm-bindgen/commits) --- updated-dependencies: - dependency-name: clap_complete dependency-type: direct:production update-type: version-update:semver-patch dependency-group: patch-updates - dependency-name: js-sys dependency-type: direct:production update-type: version-update:semver-patch dependency-group: patch-updates - dependency-name: wasm-bindgen-futures dependency-type: direct:production update-type: version-update:semver-patch dependency-group: patch-updates - dependency-name: web-sys dependency-type: direct:production update-type: version-update:semver-patch dependency-group: patch-updates ... Signed-off-by: dependabot[bot] Co-authored-by: dependabot[bot] <49699333+dependabot[bot]@users.noreply.github.com> --- Cargo.lock | 16 ++++++++-------- Cargo.toml | 6 +++--- 2 files changed, 11 insertions(+), 11 deletions(-) diff --git a/Cargo.lock b/Cargo.lock index 17814faec5..7408ab2ede 100644 --- a/Cargo.lock +++ b/Cargo.lock @@ -959,9 +959,9 @@ dependencies = [ [[package]] name = "clap_complete" -version = "4.5.23" +version = "4.5.24" source = "registry+https://github.com/rust-lang/crates.io-index" -checksum = "531d7959c5bbb6e266cecdd0f20213639c3a5c3e4d615f97db87661745f781ff" +checksum = "6d7db6eca8c205649e8d3ccd05aa5042b1800a784e56bc7c43524fde8abbfa9b" dependencies = [ "clap 4.5.16", ] @@ -3479,9 +3479,9 @@ checksum = "8eaf4bc02d17cbdd7ff4c7438cafcdf7fb9a4613313ad11b4f8fefe7d3fa0130" [[package]] name = "js-sys" -version = "0.3.69" +version = "0.3.70" source = "registry+https://github.com/rust-lang/crates.io-index" -checksum = "29c15563dc2726973df627357ce0c9ddddbea194836909d655df6a75d2cf296d" +checksum = "1868808506b929d7b0cfa8f75951347aa71bb21144b7791bae35d9bccfcfe37a" dependencies = [ "wasm-bindgen", ] @@ -9894,9 +9894,9 @@ dependencies = [ [[package]] name = "wasm-bindgen-futures" -version = "0.4.42" +version = "0.4.43" source = "registry+https://github.com/rust-lang/crates.io-index" -checksum = "76bc14366121efc8dbb487ab05bcc9d346b3b5ec0eaa76e46594cabbe51762c0" +checksum = "61e9300f63a621e96ed275155c108eb6f843b6a26d053f122ab69724559dc8ed" dependencies = [ "cfg-if", "js-sys", @@ -10051,9 +10051,9 @@ dependencies = [ [[package]] name = "web-sys" -version = "0.3.69" +version = "0.3.70" source = "registry+https://github.com/rust-lang/crates.io-index" -checksum = "77afa9a11836342370f4817622a2f0f418b134426d91a82dfb48f532d2ec13ef" +checksum = "26fdeaafd9bd129f65e7c031593c24d62186301e0c72c8978fa1678be7d532c0" dependencies = [ "js-sys", "wasm-bindgen", diff --git a/Cargo.toml b/Cargo.toml index 4e3529fee4..f448f088e4 100644 --- a/Cargo.toml +++ b/Cargo.toml @@ -365,13 +365,13 @@ gloo-net = "0.5.0" # this is blocked until the upstream removes outdates `wasm_bindgen` feature usage # indexed_db_futures = "0.4.1" indexed_db_futures = { git = "https://github.com/TiemenSch/rust-indexed-db", branch = "update-uuid" } -js-sys = "0.3.69" +js-sys = "0.3.70" serde-wasm-bindgen = "0.6.5" tsify = "0.4.5" wasm-bindgen = "0.2.93" -wasm-bindgen-futures = "0.4.39" +wasm-bindgen-futures = "0.4.43" wasmtimer = "0.2.0" -web-sys = "0.3.69" +web-sys = "0.3.70" # Profile settings for individual crates From ae7206e0c29172e605e5f1d33362d670dc24df2d Mon Sep 17 00:00:00 2001 From: import this <97586125+serinko@users.noreply.github.com> Date: Wed, 28 Aug 2024 13:10:36 +0000 Subject: [PATCH 40/93] [DOCs/dev-portal]: Update NymVPN & socks5 cli docs --- documentation/dev-portal/src/SUMMARY.md | 2 +- .../dev-portal/src/clients/socks5-client.md | 149 +----------------- .../dev-portal/src/clients/socks5/setup.md | 126 ++++++++++++++- documentation/dev-portal/src/nymvpn/cli.md | 6 +- documentation/dev-portal/src/nymvpn/intro.md | 19 +-- 5 files changed, 134 insertions(+), 168 deletions(-) diff --git a/documentation/dev-portal/src/SUMMARY.md b/documentation/dev-portal/src/SUMMARY.md index 355ed85568..70b789373e 100644 --- a/documentation/dev-portal/src/SUMMARY.md +++ b/documentation/dev-portal/src/SUMMARY.md @@ -52,7 +52,7 @@ - [Integrations](faq/integrations-faq.md) # User Manuals -- [NymVPN alpha](nymvpn/intro.md) +- [NymVPN beta](nymvpn/intro.md) - [CLI](nymvpn/cli.md) --- diff --git a/documentation/dev-portal/src/clients/socks5-client.md b/documentation/dev-portal/src/clients/socks5-client.md index 75159cc40d..b72298df75 100644 --- a/documentation/dev-portal/src/clients/socks5-client.md +++ b/documentation/dev-portal/src/clients/socks5-client.md @@ -2,12 +2,16 @@ > The Nym Socks5 Client was built in the [building nym](../binaries/building-nym.md) section. If you haven't yet built Nym and want to run the code on this page, go there first. +**To install and operate `nym-socks5-client`, visit [Setup & Run](socks5/setup.md) and [Using Your Client](socks5/usage.md) pages.** + ## Current version + ``` ``` ## What is this client for? + Many existing applications are able to use either the SOCKS4, SOCKS4A, or SOCKS5 proxy protocols. If you want to send such an application's traffic through the mixnet, you can use the `nym-socks5-client` to bounce network traffic through the Nym network, like this: ``` @@ -64,147 +68,4 @@ The `nym-socks5-client` allows you to do the following from your local machine: The `nym-network-requester` then reassembles the original TCP stream using the packets' sequence numbers, and make the intended request. It will then chop up the response into Sphinx packets and send them back through the mixnet to your `nym-socks5-client`. The application will then receive its data, without even noticing that it wasn't talking to a "normal" SOCKS5 proxy! -## Client setup -### Viewing command help - -You can check that your binaries are properly compiled with: - -``` -./nym-socks5-client --help -``` - -~~~admonish example collapsible=true title="Console output" -``` - -``` -~~~ - -You can check the necessary parameters for the available commands by running: - -``` -./nym-client --help -``` - -### Initialising a new client instance -Before you can use the client, you need to initalise a new instance of it, which can be done with the following command: - -``` -./nym-socks5-client init --id docs-example --use-reply-surbs true --provider Entztfv6Uaz2hpYHQJ6JKoaCTpDL5dja18SuQWVJAmmx.Cvhn9rBJw5Ay9wgHcbgCnVg89MPSV5s2muPV2YF1BXYu@Fo4f4SQLdoyoGkFae5TpVhRVoXCF8UiypLVGtGjujVPf -``` - -~~~admonish example collapsible=true title="Console output" -``` - -``` -~~~ - -The `--id` in the example above is a local identifier so that you can name your clients and keep track of them on your local system; it is **never** transmitted over the network. - -The `--use-reply-surbs` field denotes whether you wish to send [SURBs](https://nymtech.net/docs/architecture/traffic-flow.md#private-replies-using-surbs) along with your request. It defaults to `false`, we are explicitly setting it as `true`. It defaults to `false` for compatibility with older versions of the [Network Requester](https://nymtech.net/nodes/network-requester.md). - -The `--provider` field needs to be filled with the Nym address of a Network Requester that can make network requests on your behalf. If you don't want to [run your own](https://nymtech.net/operators/nodes/network-requester.md) you can select one from the [mixnet explorer](https://explorer.nymtech.net/network-components/service-providers) by copying its `Client ID` and using this as the value of the `--provider` flag. Alternatively, you could use [this list](https://harbourmaster.nymtech.net/). - -#### Choosing a Gateway -By default - as in the example above - your client will choose a random gateway to connect to. - -However, there are several options for choosing a gateway, if you do not want one that is randomly assigned to your client: -* If you wish to connect to a specific gateway, you can specify this with the `--gateway` flag when running `init`. -* You can also choose a gateway based on its location relative to your client. This can be done by appending the `--latency-based-selection` flag to your `init` command. This command means that to select a gateway, your client will: - * fetch a list of all availiable gateways - * send few ping messages to all of them, and measure response times. - * create a weighted distribution to randomly choose one, favouring ones with lower latency. - -> Note this doesn't mean that your client will pick the closest gateway to you, but it will be far more likely to connect to gateway with a 20ms ping rather than 200ms - -### Configuring your client -When you initalise a client instance, a configuration directory will be generated and stored in `$HOME_DIR/.nym/socks5-clients//`. - -``` -tree $HOME//.nym/socks5-clients/docs-example -├── config -│   └── config.toml -└── data - ├── ack_key.pem - ├── credentials_database.db - ├── gateway_shared.pem - ├── persistent_reply_store.sqlite - ├── private_encryption.pem - ├── private_identity.pem - ├── public_encryption.pem - └── public_identity.pem - -``` - -The `config.toml` file contains client configuration options, while the two `pem` files contain client key information. - -The generated files contain the client name, public/private keypairs, and gateway address. The name `` in the example above is just a local identifier so that you can name your clients. - -#### Configuring your client for Docker -By default, the native client listens to host `127.0.0.1`. However this can be an issue if you wish to run a client in a Dockerized environment, where it can be convenenient to listen on a different host such as `0.0.0.0`. - -You can set this via the `--host` flag during either the `init` or `run` commands. - -Alternatively, a custom host can be set in the `config.toml` file under the `socket` section. If you do this, remember to restart your client process. - -### Running the socks5 client - -You can run the initialised client by doing this: - -``` -./nym-socks5-client run --id docs-example -``` - -## Automating your socks5 client with systemd - -Create a service file for the socks5 client at `/etc/systemd/system/nym-socks5-client.service`: - -```ini -[Unit] -Description=Nym Socks5 Client -StartLimitInterval=350 -StartLimitBurst=10 - -[Service] -User=nym # replace this with whatever user you wish -LimitNOFILE=65536 -ExecStart=/home/nym/nym-socks5-client run --id -KillSignal=SIGINT -Restart=on-failure -RestartSec=30 - -[Install] -WantedBy=multi-user.target -``` - -Now enable and start your socks5 client: - -``` -systemctl enable nym-socks5-client.service -systemctl start nym-socks5-client.service -# you can always check your socks5 client has succesfully started with: -systemctl status nym-socks5-client.service -``` - -## Using your Socks5 Client - -After completing the steps above, your local Socks5 Client will be listening on `localhost:1080` ready to proxy traffic to the Network Requester set as the `--provider` when initialising. - -When trying to connect your app, generally the proxy settings are found in `settings->advanced` or `settings->connection`. - -Here is an example of setting the proxy connecting in Blockstream Green: - -![Blockstream Green settings](../images/wallet-proxy-settings/blockstream-green.gif) - -Most wallets and other applications will work basically the same way: find the network proxy settings, enter the proxy url (host: **localhost**, port: **1080**). - -In some other applications, this might be written as **localhost:1080** if there's only one proxy entry field. - -## Useful Commands - -**no-banner** - -Adding `--no-banner` startup flag will prevent Nym banner being printed even if run in tty environment. - -**build-info** - -A `build-info` command prints the build information like commit hash, rust version, binary version just like what command `--version` does. However, you can also specify an `--output=json` flag that will format the whole output as a json, making it an order of magnitude easier to parse. +Since the introduction of `nym-node` binary, `nym-network-requester` is incorporated in every node running in `exit-gateway` mode. The narrow whitelist was exchanged for a less restrictive Nym [exit policy](https://nymtech.net/.wellknown/network-requester/exit-policy.txt), where except the IPs and ports all internet access is permitted. `nym-socks5-client` users can find a full list of Network Requester addresses on [Nym Harbourmaster](https://harbourmaster.nymtech.net/) under tab called *SOCKS5 NETWORK REQUESTERS*. diff --git a/documentation/dev-portal/src/clients/socks5/setup.md b/documentation/dev-portal/src/clients/socks5/setup.md index a1fc1210a3..26dc0fda7a 100644 --- a/documentation/dev-portal/src/clients/socks5/setup.md +++ b/documentation/dev-portal/src/clients/socks5/setup.md @@ -1,4 +1,4 @@ -# Setup +# Setup & Run Nym Socks5 Client > `nym-socks5-client` now also supports SOCKS4 and SOCKS4A protocols as well as SOCKS5. @@ -9,7 +9,7 @@ Since the beginning of 2024 NymConnect is no longer maintained. Nym is developin If users want to route their traffic through socks5 we advice to use this client. If you want to run deprecated NymConnect, visit [NymConnect archive page](../../archive/nym-connect.md) with setup and application examples. ``` -## Setup and Run +## Setup ### Download or compile socks5 client @@ -17,11 +17,11 @@ If you are using OSX or a Debian-based operating system, you can download the `n If you are using a different operating system, head over to the [Building from Source](https://nymtech.net/docs/binaries/building-nym.html) page for instructions on how to build the repository from source. -### Initialise your socks5 client +### Initialise Socks5 Client -To initialise your `nym-socks5-client` you need to have an address of a Network Requester (NR). Nowadays NR is part of every Exit Gateway (`nym-node --mode exit-gateway`). The easiest way to get a NR address is to visit [harbourmaster.nymtech.net](https://harbourmaster.nymtech.net/) and scroll down to *SOCKS5 Network Requesters* table. There you can filter the NR by Gateways identity address, and other options. +To initialise your `nym-socks5-client` you need to have an address of a Network Requester (NR). Nowadays NR is part of every Exit Gateway (`nym-node --mode exit-gateway`). The easiest way to get a NR address is to visit [harbourmaster.nymtech.net](https://harbourmaster.nymtech.net/) and open the tab called *SOCKS5 NETWORK REQUESTERS*. There you can filter the NR by Gateways identity address, and other options. -Use the following command to initialise `nym-socs5-client` where `` can be anything you want (it's only for local config file storage) and `` is suplemented with a NR address: +Use the following command to initialise `nym-socs5-client` where `` can be anything you want (it's only for local config file storage identification and never shared on the network) and `` is suplemented with a NR address: ``` ./nym-socks5-client init --id --provider @@ -37,9 +37,123 @@ Another option to find a NR address associated with a Gateway is to query nodes ``` ~~~ -### Start your socks5 client +## Run + Now your client is initialised, start it with the following: ``` ./nym-socks5-client run --id ``` + +## Useful commands + +### Viewing Command `--help` + +You can check that your binaries are properly compiled with: + +``` +./nym-socks5-client --help +``` + +~~~admonish example collapsible=true title="Console output" +``` + +``` +~~~ + +You can check the necessary parameters for the available commands by running: + +``` +./nym-socks5-client --help +``` +For example `./nym-socks5-client run --help` will return all options associated with `run` command. + +~~~admonish example collapsible=true title="Console output" +``` + +``` +~~~ + +### `build-info` + +A `build-info` command prints the build information like commit hash, rust version, binary version just like what command `--version` does. However, you can also specify an `--output=json` flag that will format the whole output as a json, making it an order of magnitude easier to parse. + +### Flags & Arguments + +* `--id`: A local identifier so that you can name your clients and keep track of them on your local system; it is **never** transmitted over the network. + +* `--use-reply-surbs`: This field denotes whether you wish to send [SURBs](https://nymtech.net/docs/architecture/traffic-flow.md#private-replies-using-surbs) along with your request. It defaults to `false` and must be explicitly set to `true` to activate. + +* `--use-anonymous-replies `: Specifies whether this client is going to use an anonymous sender tag for communication with the service provider. While this is going to hide its actual address information, it will make the actual communication slower and consume nearly double the bandwidth as it will require sending reply SURBs. + +* `--gateway`: By default your client will choose a random gateway to connect to. However, there are several options for choosing a gateway, if you do not want one that is randomly assigned to your client: + +* `--latency-based-selection`: This flag will choose a gateway based on its location relative to your client. This argument means that to select a gateway, your client will: + * fetch a list of all availiable gateways + * send few ping messages to all of them, and measure response times. + * create a weighted distribution to randomly choose one, favouring ones with lower latency. + +> Note this doesn't mean that your client will pick the closest gateway to you, but it will be far more likely to connect to gateway with a 20ms ping rather than 200ms + +## Configuring `nym-socks5-client` + +When you initalise a client instance, a configuration directory will be generated and stored in `$HOME_DIR/.nym/socks5-clients//`. + +``` +tree $HOME/.nym/socks5-clients/ +├── config +│   └── config.toml +└── data + ├── ack_key.pem + ├── credentials_database.db + ├── gateways_registrations.sqlite + ├── persistent_reply_store.sqlite + ├── private_encryption.pem + ├── private_identity.pem + ├── public_encryption.pem + └── public_identity.pem +``` + +The `config.toml` file contains client configuration options, while the two `pem` files contain client key information. + +The generated files contain the client name, public/private keypairs, and gateway address. The name `` in the example above is just a local identifier so that you can name your clients. + +### Configuring your client for Docker + +By default, the native client listens to host `127.0.0.1`. However this can be an issue if you wish to run a client in a Dockerized environment, where it can be convenenient to listen on a different host such as `0.0.0.0`. + +You can set this via the `--host` flag during either the `init` or `run` commands. + +Alternatively, a custom host can be set in the `config.toml` file under the `socket` section. If you do this, remember to restart your client process. + +### Automating your socks5 client with systemd + +Create a service file for the socks5 client at `/etc/systemd/system/nym-socks5-client.service`: + +```ini +[Unit] +Description=Nym Socks5 Client +StartLimitInterval=350 +StartLimitBurst=10 + +[Service] +User=nym # replace this with whatever user you wish +LimitNOFILE=65536 +ExecStart=/home/nym/nym-socks5-client run --id +KillSignal=SIGINT +Restart=on-failure +RestartSec=30 + +[Install] +WantedBy=multi-user.target +``` + +Now enable and start your socks5 client: + +``` +systemctl enable nym-socks5-client.service +systemctl start nym-socks5-client.service + +# you can always check your socks5 client has succesfully started with: +systemctl status nym-socks5-client.service +``` diff --git a/documentation/dev-portal/src/nymvpn/cli.md b/documentation/dev-portal/src/nymvpn/cli.md index ae74274cf3..dc1c2f2238 100644 --- a/documentation/dev-portal/src/nymvpn/cli.md +++ b/documentation/dev-portal/src/nymvpn/cli.md @@ -1,7 +1,7 @@ # NymVPN CLI Guide -```admonish tip title="web3summit testing" -**If you testing NymVPN CLI on Web3 Summit Berlin, visit our event page with all info tailored for the event: [nym-vpn-cli.sandbox.nymtech.net](https://nym-vpn-cli.sandbox.nymtech.net/).** +```admonish tip title="NymVPN CLI Testnet" +If you testing NymVPN CLI and want to try our Sandbox testnet environment, you can visit an explicit guide at [nym-vpn-cli.sandbox.nymtech.net](https://nym-vpn-cli.sandbox.nymtech.net/). This page alco contains an auto generating access token button. ``` ```admonish info @@ -225,7 +225,7 @@ Options: ## Testnet environment -If you want to run NymVPN CLI in Nym Sandbox environment, there are a few adjustments to be done: +If you want to run NymVPN CLI in Nym Sandbox environment, there are a few adjustments to be done. You can follow the steps below or follow more explicit guide on [nym-vpn-cli.sandbox.nymtech.net](https://nym-vpn-cli.sandbox.nymtech.net), including the access token auto generation button. 1. Create Sandbox environment config file by saving [this](https://raw.githubusercontent.com/nymtech/nym/develop/envs/sandbox.env) as `sandbox.env` in the same directory as your NymVPN binaries: ```sh diff --git a/documentation/dev-portal/src/nymvpn/intro.md b/documentation/dev-portal/src/nymvpn/intro.md index 02150ffe5a..b559d22bd6 100644 --- a/documentation/dev-portal/src/nymvpn/intro.md +++ b/documentation/dev-portal/src/nymvpn/intro.md @@ -1,19 +1,13 @@ -# NymVPN alpha +# NymVPN beta -
- -```admonish tip title="web3summit testing" -**If you testing NymVPN CLI on Web3 Summit Berlin, visit our event page with all info tailored for the event: [nym-vpn-cli.sandbox.nymtech.net](https://nym-vpn-cli.sandbox.nymtech.net/).** -``` - -**NymVPN alpha** is a client that uses [Nym Mixnet](https://nymtech.net) to anonymise all of a user's internet traffic through either a 5-hop mixnet (for a full network privacy) or the faster 2-hop decentralised VPN (with some extra features). +**NymVPN** is a client that uses [Nym Mixnet](https://nymtech.net) to anonymise all of a user's internet traffic through either a 5-hop mixnet for a *full network privacy* or the *faster* 2-hop decentralised VPN (with some extra features). -**You are invited to take part in the alpha testing** of this new application. Register for private testing round at [nymvpn.com](https://nymvpn.com/en), that will grant you access to the [download page](https://nymvpn.com/download). Visit [NymVPN Support & FAQ](https://nymvpn.com/en/support) or join the [NymVPN matrix channel](https://matrix.to/#/#NymVPN:nymtech.chat) if you have any questions, comments or blockers. +**You are invited to take part in the beta testing** of this new application. Register for private testing round at [nymvpn.com](https://nymvpn.com/en), that will grant you access to the [download page](https://nymvpn.com/download). Visit [NymVPN Support & FAQ](https://nymvpn.com/en/support) or join the [NymVPN matrix channel](https://matrix.to/#/#NymVPN:nymtech.chat) if you have any questions, comments or blockers. Checkout the [release page](https://github.com/nymtech/nym-vpn-client/releases) for available binaries. -*NOTE: NymVPN alpha is experimental software for testing purposes only.* +*NOTE: NymVPN beta is experimental software for testing purposes only.* ## NymVPN Overview @@ -32,7 +26,4 @@ client ───► Gateway ──┘ mix │ mix ┌─►mix ───► mix └─►mix──┘ mix ``` -Users can switch to 2-hop only mode, which is a faster but less private option. In this mode traffic is only sent between the two Gateways, and is not passed between Mix Nodes. It uses Mixnet Sphinx packets with shorter, fixed routes, which improve latency, but doesn't offer the same level of protection as the 5 hop mode. - +Users can switch to 2-hop only mode, which is a faster but less private option. In this mode traffic is only sent between the two gateways, and is not passed through the mixnet. The client than use two wireguard tunnels with the Entry and Exit Gateway nodes, the Exit Gateway one being tunnelled itself through the Entry Gateway tunnel. NymVPN uses Mullvad libraries for wrapping `wireguard-go` and to setup local routing rules to route all traffic to the TUN virtual network device. From ff0ad976c610d6873c233e240d96e301f243ac3c Mon Sep 17 00:00:00 2001 From: =?UTF-8?q?Bogdan-=C8=98tefan=20Neac=C5=9Fu?= Date: Wed, 28 Aug 2024 19:47:51 +0200 Subject: [PATCH 41/93] Remove unused wireguard flag from SDK (#4823) * Remove unused wireguard flag from SDK * Remove from wasm and socks5 too --- .../20240828120000_remove_wg_address.sql | 17 ++++ .../src/backend/fs_backend/manager.rs | 5 +- .../client-core/gateways-storage/src/types.rs | 19 ----- .../src/cli_helpers/client_add_gateway.rs | 2 - .../src/cli_helpers/client_init.rs | 1 - .../src/cli_helpers/client_list_gateways.rs | 2 - common/client-core/src/cli_helpers/types.rs | 5 -- .../client-core/src/client/base_client/mod.rs | 77 ++++++------------- .../base_client/storage/migration_helpers.rs | 1 - common/client-core/src/init/mod.rs | 26 ++----- common/client-core/src/init/types.rs | 41 ---------- common/wasm/client-core/src/helpers.rs | 1 - common/wasm/client-core/src/storage/types.rs | 1 - sdk/lib/socks5-listener/src/lib.rs | 1 - sdk/rust/nym-sdk/src/mixnet/client.rs | 31 +------- 15 files changed, 51 insertions(+), 179 deletions(-) create mode 100644 common/client-core/gateways-storage/fs_gateways_migrations/20240828120000_remove_wg_address.sql diff --git a/common/client-core/gateways-storage/fs_gateways_migrations/20240828120000_remove_wg_address.sql b/common/client-core/gateways-storage/fs_gateways_migrations/20240828120000_remove_wg_address.sql new file mode 100644 index 0000000000..47f27ce889 --- /dev/null +++ b/common/client-core/gateways-storage/fs_gateways_migrations/20240828120000_remove_wg_address.sql @@ -0,0 +1,17 @@ +/* + * Copyright 2024 - Nym Technologies SA + * SPDX-License-Identifier: Apache-2.0 + */ + +CREATE TABLE remote_gateway_details_temp +( + gateway_id_bs58 TEXT NOT NULL UNIQUE PRIMARY KEY REFERENCES registered_gateway (gateway_id_bs58), + derived_aes128_ctr_blake3_hmac_keys_bs58 TEXT NOT NULL, + gateway_owner_address TEXT, + gateway_listener TEXT NOT NULL +); + +INSERT INTO remote_gateway_details_temp SELECT gateway_id_bs58, derived_aes128_ctr_blake3_hmac_keys_bs58, gateway_owner_address, gateway_listener FROM remote_gateway_details; + +DROP TABLE remote_gateway_details; +ALTER TABLE remote_gateway_details_temp RENAME TO remote_gateway_details; \ No newline at end of file diff --git a/common/client-core/gateways-storage/src/backend/fs_backend/manager.rs b/common/client-core/gateways-storage/src/backend/fs_backend/manager.rs index 4c3e3c48b5..daa342fe9b 100644 --- a/common/client-core/gateways-storage/src/backend/fs_backend/manager.rs +++ b/common/client-core/gateways-storage/src/backend/fs_backend/manager.rs @@ -155,14 +155,13 @@ impl StorageManager { ) -> Result<(), sqlx::Error> { sqlx::query!( r#" - INSERT INTO remote_gateway_details(gateway_id_bs58, derived_aes128_ctr_blake3_hmac_keys_bs58, gateway_owner_address, gateway_listener, wg_tun_address) - VALUES (?, ?, ?, ?, ?) + INSERT INTO remote_gateway_details(gateway_id_bs58, derived_aes128_ctr_blake3_hmac_keys_bs58, gateway_owner_address, gateway_listener) + VALUES (?, ?, ?, ?) "#, remote.gateway_id_bs58, remote.derived_aes128_ctr_blake3_hmac_keys_bs58, remote.gateway_owner_address, remote.gateway_listener, - remote.wg_tun_address, ) .execute(&self.connection_pool) .await?; diff --git a/common/client-core/gateways-storage/src/types.rs b/common/client-core/gateways-storage/src/types.rs index 58ce8f40a9..8daade3422 100644 --- a/common/client-core/gateways-storage/src/types.rs +++ b/common/client-core/gateways-storage/src/types.rs @@ -67,14 +67,12 @@ impl GatewayDetails { derived_aes128_ctr_blake3_hmac_keys: Arc, gateway_owner_address: Option, gateway_listener: Url, - wg_tun_address: Option, ) -> Self { GatewayDetails::Remote(RemoteGatewayDetails { gateway_id, derived_aes128_ctr_blake3_hmac_keys, gateway_owner_address, gateway_listener, - wg_tun_address, }) } @@ -172,7 +170,6 @@ pub struct RawRemoteGatewayDetails { pub derived_aes128_ctr_blake3_hmac_keys_bs58: String, pub gateway_owner_address: Option, pub gateway_listener: String, - pub wg_tun_address: Option, } impl TryFrom for RemoteGatewayDetails { @@ -217,24 +214,11 @@ impl TryFrom for RemoteGatewayDetails { } })?; - let wg_tun_address = value - .wg_tun_address - .as_ref() - .map(|addr| { - Url::parse(addr).map_err(|source| BadGateway::MalformedListener { - gateway_id: value.gateway_id_bs58.clone(), - raw_listener: addr.clone(), - source, - }) - }) - .transpose()?; - Ok(RemoteGatewayDetails { gateway_id, derived_aes128_ctr_blake3_hmac_keys, gateway_owner_address, gateway_listener, - wg_tun_address, }) } } @@ -248,7 +232,6 @@ impl<'a> From<&'a RemoteGatewayDetails> for RawRemoteGatewayDetails { .to_base58_string(), gateway_owner_address: value.gateway_owner_address.as_ref().map(|o| o.to_string()), gateway_listener: value.gateway_listener.to_string(), - wg_tun_address: value.wg_tun_address.as_ref().map(|addr| addr.to_string()), } } } @@ -264,8 +247,6 @@ pub struct RemoteGatewayDetails { pub gateway_owner_address: Option, pub gateway_listener: Url, - - pub wg_tun_address: Option, } #[derive(Debug, Clone, Serialize, Deserialize)] diff --git a/common/client-core/src/cli_helpers/client_add_gateway.rs b/common/client-core/src/cli_helpers/client_add_gateway.rs index 7b6448062f..022db8b9c3 100644 --- a/common/client-core/src/cli_helpers/client_add_gateway.rs +++ b/common/client-core/src/cli_helpers/client_add_gateway.rs @@ -133,7 +133,6 @@ where let gateway_setup = GatewaySetup::New { specification: selection_spec, available_gateways, - wg_tun_address: None, }; let init_details = @@ -162,6 +161,5 @@ where active: common_args.set_active, typ: gateway_registration.details.typ().to_string(), endpoint: Some(gateway_details.gateway_listener.clone()), - wg_tun_address: gateway_details.wg_tun_address.clone(), }) } diff --git a/common/client-core/src/cli_helpers/client_init.rs b/common/client-core/src/cli_helpers/client_init.rs index 646083ce5b..bac6de5c60 100644 --- a/common/client-core/src/cli_helpers/client_init.rs +++ b/common/client-core/src/cli_helpers/client_init.rs @@ -172,7 +172,6 @@ where let gateway_setup = GatewaySetup::New { specification: selection_spec, available_gateways, - wg_tun_address: None, }; let init_details = diff --git a/common/client-core/src/cli_helpers/client_list_gateways.rs b/common/client-core/src/cli_helpers/client_list_gateways.rs index 1bfcafb027..34259df02d 100644 --- a/common/client-core/src/cli_helpers/client_list_gateways.rs +++ b/common/client-core/src/cli_helpers/client_list_gateways.rs @@ -57,7 +57,6 @@ where active: active_gateway == Some(remote_details.gateway_id), typ: GatewayType::Remote.to_string(), endpoint: Some(remote_details.gateway_listener), - wg_tun_address: remote_details.wg_tun_address, }), GatewayDetails::Custom(_) => info.push(GatewayInfo { registration: gateway.registration_timestamp, @@ -65,7 +64,6 @@ where active: active_gateway == Some(gateway.details.gateway_id()), typ: gateway.details.typ().to_string(), endpoint: None, - wg_tun_address: None, }), }; } diff --git a/common/client-core/src/cli_helpers/types.rs b/common/client-core/src/cli_helpers/types.rs index 4a351f38ef..5cf2ebb012 100644 --- a/common/client-core/src/cli_helpers/types.rs +++ b/common/client-core/src/cli_helpers/types.rs @@ -15,7 +15,6 @@ pub struct GatewayInfo { pub typ: String, pub endpoint: Option, - pub wg_tun_address: Option, } impl Display for GatewayInfo { @@ -31,10 +30,6 @@ impl Display for GatewayInfo { if let Some(endpoint) = &self.endpoint { write!(f, " endpoint: {endpoint}")?; } - - if let Some(wg_tun_address) = &self.wg_tun_address { - write!(f, " wg tun address: {wg_tun_address}")?; - } Ok(()) } } diff --git a/common/client-core/src/client/base_client/mod.rs b/common/client-core/src/client/base_client/mod.rs index c91a7569fc..0579cc12a8 100644 --- a/common/client-core/src/client/base_client/mod.rs +++ b/common/client-core/src/client/base_client/mod.rs @@ -35,7 +35,7 @@ use crate::init::{ }; use crate::{config, spawn_future}; use futures::channel::mpsc; -use log::{debug, error, info, warn}; +use log::*; use nym_bandwidth_controller::BandwidthController; use nym_client_core_gateways_storage::{GatewayDetails, GatewaysDetailsStore}; use nym_credential_storage::storage::Storage as CredentialStorage; @@ -44,7 +44,6 @@ use nym_gateway_client::client::config::GatewayClientConfig; use nym_gateway_client::{ AcknowledgementReceiver, GatewayClient, GatewayConfig, MixnetMessageReceiver, PacketRouter, }; -use nym_network_defaults::{DEFAULT_CLIENT_LISTENING_PORT, WG_TUN_DEVICE_ADDRESS}; use nym_sphinx::acknowledgements::AckKey; use nym_sphinx::addressing::clients::Recipient; use nym_sphinx::addressing::nodes::NodeIdentity; @@ -181,7 +180,6 @@ pub struct BaseClientBuilder<'a, C, S: MixnetClientStorage> { dkg_query_client: Option, wait_for_gateway: bool, - wireguard_connection: bool, custom_topology_provider: Option>, custom_gateway_transceiver: Option>, shutdown: Option, @@ -205,7 +203,6 @@ where client_store, dkg_query_client, wait_for_gateway: false, - wireguard_connection: false, custom_topology_provider: None, custom_gateway_transceiver: None, shutdown: None, @@ -226,12 +223,6 @@ where self } - #[must_use] - pub fn with_wireguard_connection(mut self, wireguard_connection: bool) -> Self { - self.wireguard_connection = wireguard_connection; - self - } - #[must_use] pub fn with_topology_provider( mut self, @@ -361,7 +352,6 @@ where async fn start_gateway_client( config: &Config, - wireguard_connection: bool, initialisation_result: InitialisationResult, bandwidth_controller: Option>, packet_router: PacketRouter, @@ -377,47 +367,33 @@ where return Err(ClientCoreError::UnexpectedPersistedCustomGatewayDetails); }; - let mut gateway_client = if let Some(existing_client) = - initialisation_result.authenticated_ephemeral_client - { - existing_client.upgrade(packet_router, bandwidth_controller, shutdown) - } else { - let gateway_listener = if wireguard_connection { - if let Some(tun_address) = details.wg_tun_address { - tun_address.to_string() - } else { - let default = - format!("ws://{WG_TUN_DEVICE_ADDRESS}:{DEFAULT_CLIENT_LISTENING_PORT}"); - warn!("gateway {} does not have tun device address set. defaulting to '{default}'", details.gateway_id); - default - } + let mut gateway_client = + if let Some(existing_client) = initialisation_result.authenticated_ephemeral_client { + existing_client.upgrade(packet_router, bandwidth_controller, shutdown) } else { - details.gateway_listener.to_string() + let cfg = GatewayConfig::new( + details.gateway_id, + details + .gateway_owner_address + .as_ref() + .map(|o| o.to_string()), + details.gateway_listener.to_string(), + ); + GatewayClient::new( + GatewayClientConfig::new_default() + .with_disabled_credentials_mode(config.client.disabled_credentials_mode) + .with_response_timeout( + config.debug.gateway_connection.gateway_response_timeout, + ), + cfg, + managed_keys.identity_keypair(), + Some(details.derived_aes128_ctr_blake3_hmac_keys), + packet_router, + bandwidth_controller, + shutdown, + ) }; - let cfg = GatewayConfig::new( - details.gateway_id, - details - .gateway_owner_address - .as_ref() - .map(|o| o.to_string()), - gateway_listener, - ); - GatewayClient::new( - GatewayClientConfig::new_default() - .with_disabled_credentials_mode(config.client.disabled_credentials_mode) - .with_response_timeout( - config.debug.gateway_connection.gateway_response_timeout, - ), - cfg, - managed_keys.identity_keypair(), - Some(details.derived_aes128_ctr_blake3_hmac_keys), - packet_router, - bandwidth_controller, - shutdown, - ) - }; - gateway_client .authenticate_and_start() .await @@ -435,7 +411,6 @@ where async fn setup_gateway_transceiver( custom_gateway_transceiver: Option>, config: &Config, - wireguard_connection: bool, initialisation_result: InitialisationResult, bandwidth_controller: Option>, packet_router: PacketRouter, @@ -464,7 +439,6 @@ where // otherwise, setup normal gateway client, etc let gateway_client = Self::start_gateway_client( config, - wireguard_connection, initialisation_result, bandwidth_controller, packet_router, @@ -729,7 +703,6 @@ where let gateway_transceiver = Self::setup_gateway_transceiver( self.custom_gateway_transceiver, self.config, - self.wireguard_connection, init_res, bandwidth_controller, gateway_packet_router, diff --git a/common/client-core/src/client/base_client/storage/migration_helpers.rs b/common/client-core/src/client/base_client/storage/migration_helpers.rs index 81ea931085..b03b6d13c7 100644 --- a/common/client-core/src/client/base_client/storage/migration_helpers.rs +++ b/common/client-core/src/client/base_client/storage/migration_helpers.rs @@ -102,7 +102,6 @@ pub mod v1_1_33 { message: format!("the stored gateway listener address was malformed: {err}"), } })?, - wg_tun_address: None, })) } diff --git a/common/client-core/src/init/mod.rs b/common/client-core/src/init/mod.rs index 63f0a98e0c..479d73be1a 100644 --- a/common/client-core/src/init/mod.rs +++ b/common/client-core/src/init/mod.rs @@ -23,7 +23,6 @@ use nym_topology::gateway; use rand::rngs::OsRng; use rand::{CryptoRng, RngCore}; use serde::Serialize; -use std::net::IpAddr; pub mod helpers; pub mod types; @@ -52,7 +51,6 @@ async fn setup_new_gateway( details_store: &D, selection_specification: GatewaySelectionSpecification, available_gateways: Vec, - wg_tun_ip_address: Option, ) -> Result where K: KeyStore, @@ -70,19 +68,19 @@ where let selected_gateway = match selection_specification { GatewaySelectionSpecification::UniformRemote { must_use_tls } => { let gateway = uniformly_random_gateway(&mut rng, &available_gateways, must_use_tls)?; - SelectedGateway::from_topology_node(gateway, wg_tun_ip_address, must_use_tls)? + SelectedGateway::from_topology_node(gateway, must_use_tls)? } GatewaySelectionSpecification::RemoteByLatency { must_use_tls } => { let gateway = choose_gateway_by_latency(&mut rng, &available_gateways, must_use_tls).await?; - SelectedGateway::from_topology_node(gateway, wg_tun_ip_address, must_use_tls)? + SelectedGateway::from_topology_node(gateway, must_use_tls)? } GatewaySelectionSpecification::Specified { must_use_tls, identity, } => { let gateway = get_specified_gateway(&identity, &available_gateways, must_use_tls)?; - SelectedGateway::from_topology_node(gateway, wg_tun_ip_address, must_use_tls)? + SelectedGateway::from_topology_node(gateway, must_use_tls)? } GatewaySelectionSpecification::Custom { gateway_identity, @@ -104,23 +102,19 @@ where gateway_id, gateway_owner_address, gateway_listener, - wg_tun_address, } => { // if we're using a 'normal' gateway setup, do register let our_identity = client_keys.identity_keypair(); - // if wg address is set, use that one - let url = wg_tun_address.clone().unwrap_or(gateway_listener.clone()); - let registration = - helpers::register_with_gateway(gateway_id, url, our_identity).await?; + helpers::register_with_gateway(gateway_id, gateway_listener.clone(), our_identity) + .await?; ( GatewayDetails::new_remote( gateway_id, registration.shared_keys, gateway_owner_address, gateway_listener, - wg_tun_address, ), Some(registration.authenticated_ephemeral_client), ) @@ -207,17 +201,9 @@ where GatewaySetup::New { specification, available_gateways, - wg_tun_address, } => { log::debug!("GatewaySetup::New with spec: {specification:?}"); - setup_new_gateway( - key_store, - details_store, - specification, - available_gateways, - wg_tun_address, - ) - .await + setup_new_gateway(key_store, details_store, specification, available_gateways).await } GatewaySetup::ReuseConnection { authenticated_ephemeral_client, diff --git a/common/client-core/src/init/types.rs b/common/client-core/src/init/types.rs index c02509cf99..8f1daa84b4 100644 --- a/common/client-core/src/init/types.rs +++ b/common/client-core/src/init/types.rs @@ -6,7 +6,6 @@ use crate::client::key_manager::ClientKeys; use crate::config::Config; use crate::error::ClientCoreError; use crate::init::{setup_gateway, use_loaded_gateway_details}; -use log::info; use nym_client_core_gateways_storage::{ GatewayRegistration, GatewaysDetailsStore, RemoteGatewayDetails, }; @@ -19,7 +18,6 @@ use nym_validator_client::client::IdentityKey; use nym_validator_client::nyxd::AccountId; use serde::Serialize; use std::fmt::Display; -use std::net::IpAddr; use std::str::FromStr; use std::sync::Arc; use time::OffsetDateTime; @@ -32,8 +30,6 @@ pub enum SelectedGateway { gateway_owner_address: Option, gateway_listener: Url, - - wg_tun_address: Option, }, Custom { gateway_id: identity::PublicKey, @@ -41,36 +37,9 @@ pub enum SelectedGateway { }, } -fn wg_tun_address( - tun_ip: Option, - gateway: &gateway::Node, -) -> Result, ClientCoreError> { - let Some(tun_ip) = tun_ip else { - return Ok(None); - }; - - // log this so we'd remember about it if we ever decided to actually use that port - if gateway.clients_wss_port.is_some() { - info!( - "gateway {} exposes wss but for wireguard we're going to use ws", - gateway.identity_key - ); - } - - let raw_url = format!("ws://{tun_ip}:{}", gateway.clients_ws_port); - Ok(Some(raw_url.as_str().parse().map_err(|source| { - ClientCoreError::MalformedListener { - gateway_id: gateway.identity_key.to_base58_string(), - raw_listener: raw_url, - source, - } - })?)) -} - impl SelectedGateway { pub fn from_topology_node( node: gateway::Node, - wg_tun_ip_address: Option, must_use_tls: bool, ) -> Result { let gateway_listener = if must_use_tls { @@ -82,8 +51,6 @@ impl SelectedGateway { node.clients_address() }; - let wg_tun_address = wg_tun_address(wg_tun_ip_address, &node)?; - let gateway_owner_address = node .owner .as_ref() @@ -109,7 +76,6 @@ impl SelectedGateway { gateway_id: node.identity_key, gateway_owner_address, gateway_listener, - wg_tun_address, }) } @@ -250,12 +216,6 @@ pub enum GatewaySetup { // TODO: seems to be a bit inefficient to pass them by value available_gateways: Vec, - - /// Implicitly specify whether the chosen gateway must use wireguard mode by setting the tun address. - /// - /// Currently this is imperfect solution as I'd imagine this address could vary from gateway to gateway - /// so perhaps it should be part of gateway::Node struct - wg_tun_address: Option, }, ReuseConnection { @@ -290,7 +250,6 @@ impl GatewaySetup { additional_data: None, }, available_gateways: vec![], - wg_tun_address: None, } } diff --git a/common/wasm/client-core/src/helpers.rs b/common/wasm/client-core/src/helpers.rs index fb38508162..05caa7d88b 100644 --- a/common/wasm/client-core/src/helpers.rs +++ b/common/wasm/client-core/src/helpers.rs @@ -106,7 +106,6 @@ pub async fn setup_gateway_wasm( GatewaySetup::New { specification: selection_spec, available_gateways: gateways.to_vec(), - wg_tun_address: None, } }; diff --git a/common/wasm/client-core/src/storage/types.rs b/common/wasm/client-core/src/storage/types.rs index 499a0a0354..0973c837e8 100644 --- a/common/wasm/client-core/src/storage/types.rs +++ b/common/wasm/client-core/src/storage/types.rs @@ -32,7 +32,6 @@ impl TryFrom for GatewayRegistration { .derived_aes128_ctr_blake3_hmac_keys_bs58, gateway_owner_address: value.gateway_owner_address, gateway_listener: value.gateway_listener, - wg_tun_address: None, }; let remote: RemoteGatewayDetails = raw_remote.try_into()?; diff --git a/sdk/lib/socks5-listener/src/lib.rs b/sdk/lib/socks5-listener/src/lib.rs index 46afb57678..bc5350718c 100644 --- a/sdk/lib/socks5-listener/src/lib.rs +++ b/sdk/lib/socks5-listener/src/lib.rs @@ -276,7 +276,6 @@ where must_use_tls: false, }, available_gateways: current_gateways(&mut rng, &nym_apis, None).await?, - wg_tun_address: None, }); eprintln!("starting the socks5 client"); diff --git a/sdk/rust/nym-sdk/src/mixnet/client.rs b/sdk/rust/nym-sdk/src/mixnet/client.rs index 22cf485b33..72b14cbebc 100644 --- a/sdk/rust/nym-sdk/src/mixnet/client.rs +++ b/sdk/rust/nym-sdk/src/mixnet/client.rs @@ -29,14 +29,12 @@ use nym_client_core::init::helpers::current_gateways; use nym_client_core::init::setup_gateway; use nym_client_core::init::types::{GatewaySelectionSpecification, GatewaySetup}; use nym_credentials_interface::TicketType; -use nym_network_defaults::WG_TUN_DEVICE_IP_ADDRESS; use nym_socks5_client_core::config::Socks5; use nym_task::manager::TaskStatus; use nym_task::{TaskClient, TaskHandle}; use nym_topology::provider_trait::TopologyProvider; use nym_validator_client::{nyxd, QueryHttpRpcNyxdClient, UserAgent}; use rand::rngs::OsRng; -use std::net::IpAddr; use std::path::Path; use std::path::PathBuf; use url::Url; @@ -50,7 +48,6 @@ pub struct MixnetClientBuilder { storage_paths: Option, socks5_config: Option, - wireguard_mode: bool, wait_for_gateway: bool, custom_topology_provider: Option>, custom_gateway_transceiver: Option>, @@ -86,7 +83,6 @@ impl MixnetClientBuilder { config: Default::default(), storage_paths: None, socks5_config: None, - wireguard_mode: false, wait_for_gateway: false, custom_topology_provider: None, storage: storage_paths @@ -118,7 +114,6 @@ where config: Default::default(), storage_paths: None, socks5_config: None, - wireguard_mode: false, wait_for_gateway: false, custom_topology_provider: None, custom_gateway_transceiver: None, @@ -137,7 +132,6 @@ where config: self.config, storage_paths: self.storage_paths, socks5_config: self.socks5_config, - wireguard_mode: self.wireguard_mode, wait_for_gateway: self.wait_for_gateway, custom_topology_provider: self.custom_topology_provider, custom_gateway_transceiver: self.custom_gateway_transceiver, @@ -224,13 +218,6 @@ where self } - /// Attempt to wait for the selected gateway (if applicable) to come online if its currently not bonded. - #[must_use] - pub fn with_wireguard_mode(mut self, wireguard_mode: bool) -> Self { - self.wireguard_mode = wireguard_mode; - self - } - /// Attempt to wait for the selected gateway (if applicable) to come online if its currently not bonded. #[must_use] pub fn with_wait_for_gateway(mut self, wait_for_gateway: bool) -> Self { @@ -269,7 +256,6 @@ where client.custom_gateway_transceiver = self.custom_gateway_transceiver; client.custom_topology_provider = self.custom_topology_provider; client.custom_shutdown = self.custom_shutdown; - client.wireguard_mode = self.wireguard_mode; client.wait_for_gateway = self.wait_for_gateway; client.force_tls = self.force_tls; client.user_agent = self.user_agent; @@ -310,9 +296,6 @@ where /// advanced usage of custom gateways custom_gateway_transceiver: Option>, - /// If the client connects via Wireguard tunnel to the gateway. - wireguard_mode: bool, - /// Attempt to wait for the selected gateway (if applicable) to come online if its currently not bonded. wait_for_gateway: bool, @@ -368,7 +351,6 @@ where storage, custom_topology_provider: None, custom_gateway_transceiver: None, - wireguard_mode: false, wait_for_gateway: false, force_tls: false, custom_shutdown: None, @@ -396,15 +378,6 @@ where .collect() } - fn wireguard_tun_address(&self) -> Option { - // currently use a hardcoded value here, but perhaps we should change that later - if self.wireguard_mode { - Some(WG_TUN_DEVICE_IP_ADDRESS) - } else { - None - } - } - async fn setup_client_keys(&self) -> Result<()> { let mut rng = OsRng; let key_store = self.storage.key_store(); @@ -481,7 +454,6 @@ where Ok(GatewaySetup::New { specification: selection_spec, available_gateways, - wg_tun_address: self.wireguard_tun_address(), }) } @@ -594,8 +566,7 @@ where let mut base_builder: BaseClientBuilder<_, _> = BaseClientBuilder::new(&base_config, self.storage, self.dkg_query_client) - .with_wait_for_gateway(self.wait_for_gateway) - .with_wireguard_connection(self.wireguard_mode); + .with_wait_for_gateway(self.wait_for_gateway); if let Some(user_agent) = self.user_agent { base_builder = base_builder.with_user_agent(user_agent); From 3635cbdc8d919025d76c5fa057ab744f13971684 Mon Sep 17 00:00:00 2001 From: dynco-nym <173912580+dynco-nym@users.noreply.github.com> Date: Thu, 29 Aug 2024 01:22:51 +0200 Subject: [PATCH 42/93] Replace deprecated code --- .../validator-client/src/nyxd/cosmwasm_client/helpers.rs | 3 ++- common/client-libs/validator-client/src/rpc/reqwest.rs | 4 ++-- 2 files changed, 4 insertions(+), 3 deletions(-) diff --git a/common/client-libs/validator-client/src/nyxd/cosmwasm_client/helpers.rs b/common/client-libs/validator-client/src/nyxd/cosmwasm_client/helpers.rs index c437125b16..b60b4982cd 100644 --- a/common/client-libs/validator-client/src/nyxd/cosmwasm_client/helpers.rs +++ b/common/client-libs/validator-client/src/nyxd/cosmwasm_client/helpers.rs @@ -2,6 +2,7 @@ // SPDX-License-Identifier: Apache-2.0 use crate::nyxd::error::NyxdError; +use base64::Engine; use cosmrs::abci::TxMsgData; use cosmrs::cosmwasm::MsgExecuteContractResponse; use cosmrs::proto::cosmos::base::query::v1beta1::{PageRequest, PageResponse}; @@ -16,7 +17,7 @@ pub fn parse_msg_responses(data: Bytes) -> Vec { // it seems that currently, on wasmd 0.43 + tendermint-rs 0.37 + cosmrs 0.17.0-pre // the data is left in undecoded base64 form, but I'd imagine this might change so if the decoding fails, // use the bytes directly instead - let data = if let Ok(decoded) = base64::decode(&data) { + let data = if let Ok(decoded) = base64::prelude::BASE64_STANDARD.decode(&data) { decoded } else { error!("failed to base64-decode the 'data' field of the TxResponse - has the chain been upgraded and introduced some breaking changes?"); diff --git a/common/client-libs/validator-client/src/rpc/reqwest.rs b/common/client-libs/validator-client/src/rpc/reqwest.rs index 973fb63376..e20764d162 100644 --- a/common/client-libs/validator-client/src/rpc/reqwest.rs +++ b/common/client-libs/validator-client/src/rpc/reqwest.rs @@ -3,6 +3,7 @@ use crate::rpc::TendermintRpcClient; use async_trait::async_trait; +use base64::Engine; use cosmrs::tendermint::{block::Height, evidence::Evidence, Hash}; use reqwest::header::HeaderMap; use reqwest::{header, RequestBuilder}; @@ -13,7 +14,6 @@ use tendermint_rpc::{ query::Query, Error, Order, Response, SimpleRequest, }; - use url::Url; // copied macro from tendermint-rpc crate because that's exactly what we have to do here too @@ -206,7 +206,7 @@ pub fn extract_authorization(url: &Url) -> Option { let authority = url.authority(); if let Some((userpass, _)) = authority.split_once('@') { - Some(base64::encode(userpass)) + Some(base64::prelude::BASE64_STANDARD.encode(userpass)) } else { None } From 33b85a3ca188bccb393957b514d098f8ff547b50 Mon Sep 17 00:00:00 2001 From: dynco-nym <173912580+dynco-nym@users.noreply.github.com> Date: Thu, 29 Aug 2024 08:47:08 +0200 Subject: [PATCH 43/93] Fix additional one --- .../mixnet/operators/mixnode/keys/decode_mixnode_key.rs | 5 ++++- 1 file changed, 4 insertions(+), 1 deletion(-) diff --git a/common/commands/src/validator/mixnet/operators/mixnode/keys/decode_mixnode_key.rs b/common/commands/src/validator/mixnet/operators/mixnode/keys/decode_mixnode_key.rs index 21b026c85e..54d00010af 100644 --- a/common/commands/src/validator/mixnet/operators/mixnode/keys/decode_mixnode_key.rs +++ b/common/commands/src/validator/mixnet/operators/mixnode/keys/decode_mixnode_key.rs @@ -1,6 +1,7 @@ // Copyright 2021 - Nym Technologies SA // SPDX-License-Identifier: Apache-2.0 +use base64::Engine; use clap::Parser; #[derive(Debug, Parser)] @@ -10,7 +11,9 @@ pub struct Args { } pub fn decode_mixnode_key(args: Args) { - let b64_decoded = base64::decode(args.key).expect("failed to decode base64 string"); + let b64_decoded = base64::prelude::BASE64_STANDARD + .decode(args.key) + .expect("failed to decode base64 string"); let b58_encoded = bs58::encode(&b64_decoded).into_string(); println!("{b58_encoded}") From afc1b90b5719df8702229c634a2e7673726074a4 Mon Sep 17 00:00:00 2001 From: "dependabot[bot]" <49699333+dependabot[bot]@users.noreply.github.com> Date: Thu, 29 Aug 2024 13:44:50 +0200 Subject: [PATCH 44/93] build(deps): bump ipnetwork from 0.16.0 to 0.20.0 (#4812) Bumps [ipnetwork](https://github.com/achanda/ipnetwork) from 0.16.0 to 0.20.0. - [Release notes](https://github.com/achanda/ipnetwork/releases) - [Commits](https://github.com/achanda/ipnetwork/compare/v0.16.0...v0.20.0) --- updated-dependencies: - dependency-name: ipnetwork dependency-type: direct:production update-type: version-update:semver-minor ... Signed-off-by: dependabot[bot] Co-authored-by: dependabot[bot] <49699333+dependabot[bot]@users.noreply.github.com> --- Cargo.lock | 17 ++++------------- Cargo.toml | 2 +- 2 files changed, 5 insertions(+), 14 deletions(-) diff --git a/Cargo.lock b/Cargo.lock index 7408ab2ede..7f52622e81 100644 --- a/Cargo.lock +++ b/Cargo.lock @@ -3343,15 +3343,6 @@ version = "2.9.0" source = "registry+https://github.com/rust-lang/crates.io-index" checksum = "8f518f335dce6725a761382244631d86cf0ccb2863413590b31338feb467f9c3" -[[package]] -name = "ipnetwork" -version = "0.16.0" -source = "registry+https://github.com/rust-lang/crates.io-index" -checksum = "b8eca9f51da27bc908ef3dd85c21e1bbba794edaf94d7841e37356275b82d31e" -dependencies = [ - "serde", -] - [[package]] name = "ipnetwork" version = "0.18.0" @@ -4216,7 +4207,7 @@ dependencies = [ "defguard_wireguard_rs", "fastrand 2.1.1", "futures", - "ipnetwork 0.16.0", + "ipnetwork 0.20.0", "log", "nym-authenticator-requests", "nym-bin-common", @@ -4891,7 +4882,7 @@ dependencies = [ "dotenvy", "futures", "humantime-serde", - "ipnetwork 0.16.0", + "ipnetwork 0.20.0", "nym-api-requests", "nym-authenticator", "nym-bin-common", @@ -5393,7 +5384,7 @@ dependencies = [ "colored", "cupid", "humantime-serde", - "ipnetwork 0.16.0", + "ipnetwork 0.20.0", "nym-authenticator", "nym-bin-common", "nym-client-core-config-types", @@ -5437,7 +5428,7 @@ dependencies = [ "headers", "hmac", "hyper 1.4.1", - "ipnetwork 0.16.0", + "ipnetwork 0.20.0", "nym-crypto", "nym-http-api-common", "nym-metrics", diff --git a/Cargo.toml b/Cargo.toml index f448f088e4..4d5975a380 100644 --- a/Cargo.toml +++ b/Cargo.toml @@ -236,7 +236,7 @@ hyper = "1.3.1" indicatif = "0.17.8" inquire = "0.6.2" ip_network = "0.4.1" -ipnetwork = "0.16" +ipnetwork = "0.20" isocountry = "0.3.2" itertools = "0.13.0" k256 = "0.13" From a0fea6edb42eaa8b24ac55f0cb2e39415d478e97 Mon Sep 17 00:00:00 2001 From: Dinko Zdravac <173912580+dynco-nym@users.noreply.github.com> Date: Thu, 29 Aug 2024 15:31:01 +0200 Subject: [PATCH 45/93] Add `axum` server to `nym-api` (#4803) * Migrate nym-api HTTP server from rocket to axum (#4698) Migrate endpoints to Axum * Squashed after PR review Initial WIP - bootstrap axum server with same data as rocket - start axum server alongside rocket - add routes for circulating-supply, contract-cache, network - write simple bash validation that migrated APIs return 200 - mark rocket parts of code as deprecated - start more complicated routes: WIP Init storage always Add coconut routes Add api-status routes Expand tests WIP Migrate unstable APIs with query params Update bash tests Add node-status routes Redirect / to /swagger Update API tests Implement graceful shutdown rustfmt Fix clippy * Add ecash routes after rebase * PR feedback - add CORS layer - move logger to common crate - remove global log filters for nym-api and axum * Serve OpenAPI for all endpoints (#4761) * Playing around with swagger * Generate OpenAPI for /status routes * Phase out static_routes as strings - also nest routers in a clearer way * Generate OpenAPI for /network routes * Generate OpenAPI for /api-status routes * Generate OpenAPI for "nym nodes" routes * Fix some network-monitor routes * Generate OpenAPI for /ecash routes * Add utoipa feature to /common mods * Add OpenAPI for unstable routes * Fix MixNodeDetails field in models * Introduce axum feature flag (#4775) * Add Axum bind_address to config * Introduce axum feature flag * Add comment to template.rs * Add Github action to build wtih `axum` feature * Refactor server start & shutdown (#4777) * Clippy: don't forget axum feature * Refactor router so it's safer * Implement graceful shutdown * Nicer pattern matching * Better Result syntax --- .github/workflows/ci-build.yml | 10 +- Cargo.lock | 316 +++++++++----- Cargo.toml | 6 +- common/config/Cargo.toml | 3 +- .../mixnet-contract/Cargo.toml | 2 + .../mixnet-contract/src/gateway.rs | 4 + .../mixnet-contract/src/interval.rs | 4 + common/http-api-common/Cargo.toml | 7 +- common/http-api-common/src/lib.rs | 12 +- common/http-api-common/src/logging.rs | 63 +++ common/network-defaults/Cargo.toml | 4 +- common/network-defaults/src/network.rs | 5 + nym-api/Cargo.toml | 27 +- nym-api/nym-api-requests/Cargo.toml | 3 +- nym-api/nym-api-requests/src/ecash/models.rs | 31 +- nym-api/nym-api-requests/src/models.rs | 124 ++++-- nym-api/nym-api-requests/src/nym_nodes.rs | 16 +- nym-api/nym-api-requests/src/pagination.rs | 5 +- .../src/circulating_supply_api/cache/mod.rs | 3 +- .../src/circulating_supply_api/handlers.rs | 102 +++++ nym-api/src/circulating_supply_api/mod.rs | 2 + nym-api/src/circulating_supply_api/routes.rs | 14 +- .../src/ecash/api_routes/aggregation_axum.rs | 143 +++++++ nym-api/src/ecash/api_routes/handlers.rs | 19 + nym-api/src/ecash/api_routes/helpers.rs | 7 + nym-api/src/ecash/api_routes/issued_axum.rs | 147 +++++++ nym-api/src/ecash/api_routes/mod.rs | 10 + .../ecash/api_routes/partial_signing_axum.rs | 178 ++++++++ nym-api/src/ecash/api_routes/spending_axum.rs | 245 +++++++++++ nym-api/src/epoch_operations/mod.rs | 9 +- nym-api/src/main.rs | 24 +- nym-api/src/network/handlers.rs | 100 +++++ nym-api/src/network/mod.rs | 2 + nym-api/src/network/models.rs | 2 + nym-api/src/node_status_api/cache/mod.rs | 3 +- .../src/node_status_api/cache/node_sets.rs | 42 +- .../src/node_status_api/cache/refresher.rs | 4 +- nym-api/src/node_status_api/handlers/mod.rs | 32 ++ .../handlers/network_monitor.rs | 339 +++++++++++++++ .../src/node_status_api/handlers/unstable.rs | 279 ++++++++++++ .../handlers/without_monitor.rs | 176 ++++++++ nym-api/src/node_status_api/helpers.rs | 104 ++--- .../src/node_status_api/helpers_deprecated.rs | 405 ++++++++++++++++++ nym-api/src/node_status_api/mod.rs | 72 ++-- nym-api/src/node_status_api/models.rs | 110 ++++- .../{routes.rs => routes_deprecated.rs} | 62 +-- nym-api/src/node_status_api/uptime_updater.rs | 4 +- nym-api/src/nym_contract_cache/cache/mod.rs | 3 +- nym-api/src/nym_contract_cache/handlers.rs | 270 ++++++++++++ nym-api/src/nym_contract_cache/mod.rs | 2 + nym-api/src/nym_contract_cache/routes.rs | 4 +- nym-api/src/nym_nodes/handlers.rs | 95 ++++ nym-api/src/nym_nodes/handlers_unstable.rs | 377 ++++++++++++++++ nym-api/src/nym_nodes/mod.rs | 7 +- nym-api/src/nym_nodes/unstable_routes.rs | 59 ++- nym-api/src/status/handlers.rs | 92 ++++ nym-api/src/status/mod.rs | 2 + nym-api/src/status/routes.rs | 6 +- nym-api/src/support/cli/run.rs | 44 +- nym-api/src/support/config/mod.rs | 18 + nym-api/src/support/config/template.rs | 6 +- nym-api/src/support/http/mod.rs | 39 +- nym-api/src/support/storage/mod.rs | 1 + nym-api/src/v2/api_docs.rs | 85 ++++ nym-api/src/v2/mod.rs | 313 ++++++++++++++ nym-api/src/v2/router.rs | 136 ++++++ nym-node/tests/definitions.sh | 217 ++++++++++ nym-node/tests/test_apis.sh | 24 ++ 68 files changed, 4653 insertions(+), 428 deletions(-) create mode 100644 common/http-api-common/src/logging.rs create mode 100644 nym-api/src/circulating_supply_api/handlers.rs create mode 100644 nym-api/src/ecash/api_routes/aggregation_axum.rs create mode 100644 nym-api/src/ecash/api_routes/handlers.rs create mode 100644 nym-api/src/ecash/api_routes/issued_axum.rs create mode 100644 nym-api/src/ecash/api_routes/partial_signing_axum.rs create mode 100644 nym-api/src/ecash/api_routes/spending_axum.rs create mode 100644 nym-api/src/network/handlers.rs create mode 100644 nym-api/src/node_status_api/handlers/mod.rs create mode 100644 nym-api/src/node_status_api/handlers/network_monitor.rs create mode 100644 nym-api/src/node_status_api/handlers/unstable.rs create mode 100644 nym-api/src/node_status_api/handlers/without_monitor.rs create mode 100644 nym-api/src/node_status_api/helpers_deprecated.rs rename nym-api/src/node_status_api/{routes.rs => routes_deprecated.rs} (91%) create mode 100644 nym-api/src/nym_contract_cache/handlers.rs create mode 100644 nym-api/src/nym_nodes/handlers.rs create mode 100644 nym-api/src/nym_nodes/handlers_unstable.rs create mode 100644 nym-api/src/status/handlers.rs create mode 100644 nym-api/src/v2/api_docs.rs create mode 100644 nym-api/src/v2/mod.rs create mode 100644 nym-api/src/v2/router.rs create mode 100755 nym-node/tests/definitions.sh create mode 100755 nym-node/tests/test_apis.sh diff --git a/.github/workflows/ci-build.yml b/.github/workflows/ci-build.yml index 710b1e0d95..2c950f902a 100644 --- a/.github/workflows/ci-build.yml +++ b/.github/workflows/ci-build.yml @@ -76,6 +76,14 @@ jobs: # Enable wireguard by default on linux only args: --workspace --features wireguard + # while disabled by default, this build ensures nothing is broken within + # `axum` feature + - name: Build with `axum` feature + uses: actions-rs/cargo@v1 + with: + command: build + args: --features axum + - name: Build all examples if: matrix.os == 'custom-linux' uses: actions-rs/cargo@v1 @@ -109,4 +117,4 @@ jobs: uses: actions-rs/cargo@v1 with: command: clippy - args: --workspace --all-targets --features wireguard -- -D warnings + args: --workspace --all-targets --features wireguard,axum -- -D warnings diff --git a/Cargo.lock b/Cargo.lock index 7f52622e81..35cc541a87 100644 --- a/Cargo.lock +++ b/Cargo.lock @@ -83,7 +83,7 @@ dependencies = [ "cipher", "ctr", "ghash", - "subtle 2.5.0", + "subtle 2.6.1", ] [[package]] @@ -218,6 +218,15 @@ version = "1.0.86" source = "registry+https://github.com/rust-lang/crates.io-index" checksum = "b3d1d046238990b9cf5bcde22a3fb3584ee5cf65fb2765f454ed428c7a0063da" +[[package]] +name = "arbitrary" +version = "1.3.2" +source = "registry+https://github.com/rust-lang/crates.io-index" +checksum = "7d5a26814d8dcb93b0e5a0ff3c6d80a8843bafb21b39e8e18a6f05471870e110" +dependencies = [ + "derive_arbitrary", +] + [[package]] name = "argon2" version = "0.5.3" @@ -394,7 +403,7 @@ dependencies = [ "http 1.1.0", "http-body 1.0.0", "http-body-util", - "hyper 1.4.1", + "hyper 1.4.0", "hyper-util", "itoa", "matchit", @@ -548,7 +557,7 @@ dependencies = [ "rand_core 0.6.4", "ripemd", "sha2 0.10.8", - "subtle 2.5.0", + "subtle 2.6.1", "zeroize", ] @@ -586,9 +595,9 @@ checksum = "bef38d45163c2f1dde094a7dfd33ccf595c92905c8f8f4fdc18d06fb1037718a" [[package]] name = "bitflags" -version = "2.5.0" +version = "2.6.0" source = "registry+https://github.com/rust-lang/crates.io-index" -checksum = "cf4b9d6a944f767f8e5e0db018570623c85f3d925ac718db4e06d0187adb21c1" +checksum = "b048fb63fd8b5923fc5aa7b340d8e156aec7ec02f0c78fa8a6ddc2613f6f71de" [[package]] name = "bitvec" @@ -687,7 +696,7 @@ dependencies = [ "rand_core 0.6.4", "serde", "serdect 0.3.0-pre.0", - "subtle 2.5.0", + "subtle 2.6.1", "zeroize", ] @@ -737,9 +746,9 @@ dependencies = [ [[package]] name = "bytemuck" -version = "1.16.0" +version = "1.16.1" source = "registry+https://github.com/rust-lang/crates.io-index" -checksum = "78834c15cb5d5efe3452d58b1e8ba890dd62d21907f867f383358198e56ebca5" +checksum = "b236fc92302c97ed75b38da1f4917b5cdda4984745740f153a5d3059e48d725e" [[package]] name = "byteorder" @@ -882,7 +891,7 @@ dependencies = [ "num-traits", "serde", "wasm-bindgen", - "windows-targets 0.52.5", + "windows-targets 0.52.6", ] [[package]] @@ -1509,7 +1518,7 @@ version = "0.27.0" source = "registry+https://github.com/rust-lang/crates.io-index" checksum = "f476fe445d41c9e991fd07515a6f463074b782242ccf4a5b7b1d1012e70824df" dependencies = [ - "bitflags 2.5.0", + "bitflags 2.6.0", "crossterm_winapi", "libc", "parking_lot 0.12.3", @@ -1539,7 +1548,7 @@ checksum = "0dc92fb57ca44df6db8059111ab3af99a63d5d0f8375d9972e319a379c6bab76" dependencies = [ "generic-array 0.14.7", "rand_core 0.6.4", - "subtle 2.5.0", + "subtle 2.6.1", "zeroize", ] @@ -1621,9 +1630,9 @@ dependencies = [ [[package]] name = "curl-sys" -version = "0.4.72+curl-8.6.0" +version = "0.4.73+curl-8.8.0" source = "registry+https://github.com/rust-lang/crates.io-index" -checksum = "29cbdc8314c447d11e8fd156dcdd031d9e02a7a976163e396b548c03153bc9ea" +checksum = "450ab250ecf17227c39afb9a2dd9261dc0035cb80f2612472fc0c4aac2dcb84d" dependencies = [ "cc", "libc", @@ -1643,7 +1652,7 @@ dependencies = [ "byteorder", "digest 0.9.0", "rand_core 0.5.1", - "subtle 2.5.0", + "subtle 2.6.1", "zeroize", ] @@ -1660,7 +1669,7 @@ dependencies = [ "fiat-crypto", "rustc_version 0.4.0", "serde", - "subtle 2.5.0", + "subtle 2.6.1", "zeroize", ] @@ -1938,6 +1947,17 @@ dependencies = [ "syn 1.0.109", ] +[[package]] +name = "derive_arbitrary" +version = "1.3.2" +source = "registry+https://github.com/rust-lang/crates.io-index" +checksum = "67e77553c4162a157adbf834ebae5b415acbecbeafc7a74b0e886657506a7611" +dependencies = [ + "proc-macro2", + "quote", + "syn 2.0.66", +] + [[package]] name = "devise" version = "0.4.1" @@ -1964,7 +1984,7 @@ version = "0.4.1" source = "registry+https://github.com/rust-lang/crates.io-index" checksum = "35b50dba0afdca80b187392b24f2499a88c336d5a8493e4b4ccfb608708be56a" dependencies = [ - "bitflags 2.5.0", + "bitflags 2.6.0", "proc-macro2", "proc-macro2-diagnostics", "quote", @@ -1998,7 +2018,7 @@ dependencies = [ "block-buffer 0.10.4", "const-oid", "crypto-common", - "subtle 2.5.0", + "subtle 2.6.1", ] [[package]] @@ -2042,6 +2062,17 @@ dependencies = [ "windows-sys 0.48.0", ] +[[package]] +name = "displaydoc" +version = "0.2.5" +source = "registry+https://github.com/rust-lang/crates.io-index" +checksum = "97369cbbc041bc366949bc74d34658d6cda5621039731c6310521892a3a20ae0" +dependencies = [ + "proc-macro2", + "quote", + "syn 2.0.66", +] + [[package]] name = "dkg-bypass-contract" version = "0.1.0" @@ -2122,7 +2153,7 @@ dependencies = [ "rand_core 0.6.4", "serde", "sha2 0.10.8", - "subtle 2.5.0", + "subtle 2.6.1", "zeroize", ] @@ -2163,7 +2194,7 @@ dependencies = [ "rand_core 0.6.4", "sec1", "serdect 0.2.0", - "subtle 2.5.0", + "subtle 2.6.1", "zeroize", ] @@ -2360,7 +2391,7 @@ source = "registry+https://github.com/rust-lang/crates.io-index" checksum = "ded41244b729663b1e574f1b4fb731469f69f79c17667b5d776b16cda0479449" dependencies = [ "rand_core 0.6.4", - "subtle 2.5.0", + "subtle 2.6.1", ] [[package]] @@ -2744,7 +2775,7 @@ checksum = "f0f9ef7462f7c099f518d754361858f86d8a07af53ba9af0fe635bbccb151a63" dependencies = [ "ff", "rand_core 0.6.4", - "subtle 2.5.0", + "subtle 2.6.1", ] [[package]] @@ -3071,9 +3102,9 @@ dependencies = [ [[package]] name = "hyper" -version = "1.4.1" +version = "1.4.0" source = "registry+https://github.com/rust-lang/crates.io-index" -checksum = "50dfd22e0e76d0f662d429a5f80fcaf3855009297eab6a0a9f8543834744ba05" +checksum = "c4fe55fb7a772d59a5ff1dfbff4fe0258d19b89fec4b233e75d35d5d2316badc" dependencies = [ "bytes", "futures-channel", @@ -3111,7 +3142,7 @@ checksum = "a0bea761b46ae2b24eb4aef630d8d1c398157b6fc29e6350ecf090a0b70c952c" dependencies = [ "futures-util", "http 1.1.0", - "hyper 1.4.1", + "hyper 1.4.0", "hyper-util", "rustls 0.22.4", "rustls-pki-types", @@ -3143,7 +3174,7 @@ dependencies = [ "futures-util", "http 1.1.0", "http-body 1.0.0", - "hyper 1.4.1", + "hyper 1.4.0", "pin-project-lite", "socket2", "tokio", @@ -3519,9 +3550,9 @@ dependencies = [ [[package]] name = "lazy_static" -version = "1.4.0" +version = "1.5.0" source = "registry+https://github.com/rust-lang/crates.io-index" -checksum = "e2abad23fbc42b3700f2f279844dc832adb2b2eb069b2df918f455c4e18cc646" +checksum = "bbd2bcb4c963f2ddae06a2efc7e9f3591312473c50c6685e1f298068316e66fe" [[package]] name = "ledger-apdu" @@ -3578,7 +3609,7 @@ version = "0.1.3" source = "registry+https://github.com/rust-lang/crates.io-index" checksum = "c0ff37bd590ca25063e35af745c343cb7a0271906fb7b37e4813e8f79f00268d" dependencies = [ - "bitflags 2.5.0", + "bitflags 2.6.0", "libc", ] @@ -3746,9 +3777,9 @@ dependencies = [ [[package]] name = "memchr" -version = "2.7.2" +version = "2.7.4" source = "registry+https://github.com/rust-lang/crates.io-index" -checksum = "6c8640c5d730cb13ebd907d8d04b52f55ac9a2eec55b440c8892f40d56c76c1d" +checksum = "78ca9ab1a0babb1e7d5695e3530886289c18cf2f87ec19a575a0abdce112e3a3" [[package]] name = "memoffset" @@ -3767,9 +3798,9 @@ checksum = "6877bb514081ee2a7ff5ef9de3281f14a4dd4bceac4c09388074a6b5df8a139a" [[package]] name = "mime_guess" -version = "2.0.4" +version = "2.0.5" source = "registry+https://github.com/rust-lang/crates.io-index" -checksum = "4192263c238a5f0d0c6bfd21f336a313a4ce1c450542449ca191bb657b4642ef" +checksum = "f7c44f8e672c00fe5308fa235f821cb4198414e1c77935c1ab6948d3fd78550e" dependencies = [ "mime", "unicase", @@ -3957,7 +3988,7 @@ version = "0.27.1" source = "registry+https://github.com/rust-lang/crates.io-index" checksum = "2eb04e9c688eff1c89d72b407f168cf79bb9e867a9d3323ed6c01519eb9cc053" dependencies = [ - "bitflags 2.5.0", + "bitflags 2.6.0", "cfg-if", "libc", "memoffset", @@ -3969,7 +4000,7 @@ version = "0.29.0" source = "registry+https://github.com/rust-lang/crates.io-index" checksum = "71e2746dc3a24dd78b3cfcb7be93368c6de9963d30f43a6a73998a9cf4b17b46" dependencies = [ - "bitflags 2.5.0", + "bitflags 2.6.0", "cfg-if", "cfg_aliases", "libc", @@ -4065,6 +4096,27 @@ dependencies = [ "libc", ] +[[package]] +name = "num_enum" +version = "0.7.2" +source = "registry+https://github.com/rust-lang/crates.io-index" +checksum = "02339744ee7253741199f897151b38e72257d13802d4ee837285cc2990a90845" +dependencies = [ + "num_enum_derive", +] + +[[package]] +name = "num_enum_derive" +version = "0.7.2" +source = "registry+https://github.com/rust-lang/crates.io-index" +checksum = "681030a937600a36906c185595136d26abfebb4aa9c65701cefcaf8578bb982b" +dependencies = [ + "proc-macro-crate", + "proc-macro2", + "quote", + "syn 2.0.66", +] + [[package]] name = "num_threads" version = "0.1.7" @@ -4086,6 +4138,8 @@ version = "1.1.42" dependencies = [ "anyhow", "async-trait", + "axum 0.7.5", + "axum-extra", "bincode", "bip39", "bloomfilter", @@ -4122,6 +4176,7 @@ dependencies = [ "nym-ecash-double-spending", "nym-ecash-time", "nym-gateway-client", + "nym-http-api-common", "nym-inclusion-probability", "nym-mixnet-contract-common", "nym-multisig-contract-common", @@ -4153,8 +4208,15 @@ dependencies = [ "time", "tokio", "tokio-stream", + "tokio-util", + "tower-http", + "tracing", + "tracing-subscriber", "ts-rs", "url", + "utoipa", + "utoipa-swagger-ui", + "utoipauto", "zeroize", ] @@ -4183,6 +4245,7 @@ dependencies = [ "thiserror", "time", "ts-rs", + "utoipa", ] [[package]] @@ -4432,7 +4495,7 @@ dependencies = [ "gloo-timers", "http-body-util", "humantime-serde", - "hyper 1.4.1", + "hyper 1.4.0", "hyper-util", "log", "nym-bandwidth-controller", @@ -5034,10 +5097,12 @@ version = "0.1.0" dependencies = [ "axum 0.7.5", "bytes", + "colored", "mime", "serde", "serde_json", "serde_yaml", + "tracing", "utoipa", ] @@ -5187,6 +5252,7 @@ dependencies = [ "thiserror", "time", "ts-rs", + "utoipa", ] [[package]] @@ -5288,6 +5354,7 @@ dependencies = [ "schemars", "serde", "url", + "utoipa", ] [[package]] @@ -5427,7 +5494,7 @@ dependencies = [ "fastrand 2.1.1", "headers", "hmac", - "hyper 1.4.1", + "hyper 1.4.0", "ipnetwork 0.20.0", "nym-crypto", "nym-http-api-common", @@ -6258,9 +6325,9 @@ checksum = "3fdb12b2476b595f9358c5161aa467c2438859caa136dec86c26fdd2efe17b92" [[package]] name = "oorandom" -version = "11.1.3" +version = "11.1.4" source = "registry+https://github.com/rust-lang/crates.io-index" -checksum = "0ab1bc2a289d34bd04a330323ac98a1b4bc82c9d9fcb1e66b63caa84da26b575" +checksum = "b410bbe7e14ab526a0e86877eb47c6996a2bd7746f027ba551028c925390e4e9" [[package]] name = "opaque-debug" @@ -6467,9 +6534,9 @@ checksum = "1e401f977ab385c9e4e3ab30627d6f26d00e2c73eef317493c4ec6d468726cf8" dependencies = [ "cfg-if", "libc", - "redox_syscall 0.5.1", + "redox_syscall 0.5.2", "smallvec", - "windows-targets 0.52.5", + "windows-targets 0.52.6", ] [[package]] @@ -6480,7 +6547,7 @@ checksum = "346f04948ba92c43e8469c1ee6736c7563d71012b17d40745260fe106aac2166" dependencies = [ "base64ct", "rand_core 0.6.4", - "subtle 2.5.0", + "subtle 2.6.1", ] [[package]] @@ -6558,9 +6625,9 @@ checksum = "e3148f5046208a5d56bcfc03053e3ca6334e51da8dfb19b6cdc8b306fae3283e" [[package]] name = "pest" -version = "2.7.10" +version = "2.7.11" source = "registry+https://github.com/rust-lang/crates.io-index" -checksum = "560131c633294438da9f7c4b08189194b20946c8274c6b9e38881a7874dc8ee8" +checksum = "cd53dff83f26735fdc1ca837098ccf133605d794cdae66acfc2bfac3ec809d95" dependencies = [ "memchr", "thiserror", @@ -6569,9 +6636,9 @@ dependencies = [ [[package]] name = "pest_derive" -version = "2.7.10" +version = "2.7.11" source = "registry+https://github.com/rust-lang/crates.io-index" -checksum = "26293c9193fbca7b1a3bf9b79dc1e388e927e6cacaa78b4a3ab705a1d3d41459" +checksum = "2a548d2beca6773b1c244554d36fcf8548a8a58e74156968211567250e48e49a" dependencies = [ "pest", "pest_generator", @@ -6579,9 +6646,9 @@ dependencies = [ [[package]] name = "pest_generator" -version = "2.7.10" +version = "2.7.11" source = "registry+https://github.com/rust-lang/crates.io-index" -checksum = "3ec22af7d3fb470a85dd2ca96b7c577a1eb4ef6f1683a9fe9a8c16e136c04687" +checksum = "3c93a82e8d145725dcbaf44e5ea887c8a869efdcc28706df2d08c69e17077183" dependencies = [ "pest", "pest_meta", @@ -6592,9 +6659,9 @@ dependencies = [ [[package]] name = "pest_meta" -version = "2.7.10" +version = "2.7.11" source = "registry+https://github.com/rust-lang/crates.io-index" -checksum = "d7a240022f37c361ec1878d646fc5b7d7c4d28d5946e1a80ad5a7a4f4ca0bdcd" +checksum = "a941429fea7e08bedec25e4f6785b6ffaacc6b755da98df5ef3e7dcf4a124c4f" dependencies = [ "once_cell", "pest", @@ -7175,11 +7242,11 @@ dependencies = [ [[package]] name = "redox_syscall" -version = "0.5.1" +version = "0.5.2" source = "registry+https://github.com/rust-lang/crates.io-index" -checksum = "469052894dcb553421e483e4209ee581a45100d31b4018de03e5a7ad86374a7e" +checksum = "c82cf8cff14456045f55ec4241383baeff27af886adb72ffb2162f99911de0fd" dependencies = [ - "bitflags 2.5.0", + "bitflags 2.6.0", ] [[package]] @@ -7306,12 +7373,13 @@ checksum = "566cafdd92868e0939d3fb961bd0dc25fcfaaed179291093b3d43e6b3150ea10" dependencies = [ "base64 0.22.1", "bytes", + "futures-channel", "futures-core", "futures-util", "http 1.1.0", "http-body 1.0.0", "http-body-util", - "hyper 1.4.1", + "hyper 1.4.0", "hyper-rustls 0.26.0", "hyper-util", "ipnet", @@ -7349,7 +7417,7 @@ source = "registry+https://github.com/rust-lang/crates.io-index" checksum = "f8dd2a808d456c4a54e300a23e9f5a67e122c3024119acbfd73e3bf664491cb2" dependencies = [ "hmac", - "subtle 2.5.0", + "subtle 2.6.1", ] [[package]] @@ -7582,7 +7650,7 @@ version = "0.38.34" source = "registry+https://github.com/rust-lang/crates.io-index" checksum = "70dc5ec042f7a43c4a73241207cecc9873a06d45debb38b329f8541d85c2730f" dependencies = [ - "bitflags 2.5.0", + "bitflags 2.6.0", "errno", "libc", "linux-raw-sys", @@ -7623,7 +7691,7 @@ dependencies = [ "ring 0.17.8", "rustls-pki-types", "rustls-webpki 0.102.4", - "subtle 2.5.0", + "subtle 2.6.1", "zeroize", ] @@ -7817,7 +7885,7 @@ dependencies = [ "generic-array 0.14.7", "pkcs8", "serdect 0.2.0", - "subtle 2.5.0", + "subtle 2.6.1", "zeroize", ] @@ -7827,7 +7895,7 @@ version = "2.11.0" source = "registry+https://github.com/rust-lang/crates.io-index" checksum = "c627723fd09706bacdb5cf41499e95098555af3c3c29d014dc3c458ef6be11c0" dependencies = [ - "bitflags 2.5.0", + "bitflags 2.6.0", "core-foundation", "core-foundation-sys", "libc", @@ -8273,7 +8341,7 @@ dependencies = [ "rand 0.8.5", "rand_distr", "sha2 0.10.8", - "subtle 2.5.0", + "subtle 2.6.1", ] [[package]] @@ -8574,9 +8642,9 @@ checksum = "2d67a5a62ba6e01cb2192ff309324cb4875d0c451d55fe2319433abe7a05a8ee" [[package]] name = "subtle" -version = "2.5.0" +version = "2.6.1" source = "registry+https://github.com/rust-lang/crates.io-index" -checksum = "81cdd64d312baedb58e21336b31bc043b77e01cc99033ce76ef539f78e965ebc" +checksum = "13c2bddecc57b384dee18652358fb23172facb8a2c51ccc10d74c157bdea3292" [[package]] name = "subtle-encoding" @@ -8716,7 +8784,7 @@ dependencies = [ "serde_repr", "sha2 0.10.8", "signature", - "subtle 2.5.0", + "subtle 2.6.1", "subtle-encoding", "tendermint-proto 0.34.1", "time", @@ -8747,7 +8815,7 @@ dependencies = [ "serde_repr", "sha2 0.10.8", "signature", - "subtle 2.5.0", + "subtle 2.6.1", "subtle-encoding", "tendermint-proto 0.37.0", "time", @@ -8822,7 +8890,7 @@ dependencies = [ "serde", "serde_bytes", "serde_json", - "subtle 2.5.0", + "subtle 2.6.1", "subtle-encoding", "tendermint 0.37.0", "tendermint-config", @@ -8988,9 +9056,9 @@ dependencies = [ [[package]] name = "tinyvec" -version = "1.6.0" +version = "1.7.0" source = "registry+https://github.com/rust-lang/crates.io-index" -checksum = "87cc5ceb3875bb20c2890005a4e226a4651264a5c75edb2421b52861a0a0cb50" +checksum = "ce6b6a2fb3a985e99cebfaefa9faa3024743da73304ca1c683a36429613d3d22" dependencies = [ "tinyvec_macros", ] @@ -9286,7 +9354,7 @@ version = "0.5.2" source = "registry+https://github.com/rust-lang/crates.io-index" checksum = "1e9cd434a998747dd2c4276bc96ee2e0c7a2eadf3cae88e52be55a05fa9053f5" dependencies = [ - "bitflags 2.5.0", + "bitflags 2.6.0", "bytes", "futures-util", "http 1.1.0", @@ -9684,7 +9752,7 @@ source = "registry+https://github.com/rust-lang/crates.io-index" checksum = "fc1de2c688dc15305988b563c3854064043356019f97a4b46276fe734c4f07ea" dependencies = [ "crypto-common", - "subtle 2.5.0", + "subtle 2.6.1", ] [[package]] @@ -9768,20 +9836,54 @@ dependencies = [ [[package]] name = "utoipa-swagger-ui" -version = "6.0.0" +version = "7.1.0" source = "registry+https://github.com/rust-lang/crates.io-index" -checksum = "0b39868d43c011961e04b41623e050aedf2cc93652562ff7935ce0f819aaf2da" +checksum = "943e0ff606c6d57d410fd5663a4d7c074ab2c5f14ab903b9514565e59fa1189e" dependencies = [ "axum 0.7.5", "mime_guess", "regex", + "reqwest 0.12.4", "rust-embed", "serde", "serde_json", + "url", "utoipa", "zip", ] +[[package]] +name = "utoipauto" +version = "0.1.14" +source = "registry+https://github.com/rust-lang/crates.io-index" +checksum = "608b8f2279483be386261655b562e40877ea434eb92093c894a644fda2021860" +dependencies = [ + "utoipauto-macro", +] + +[[package]] +name = "utoipauto-core" +version = "0.1.12" +source = "registry+https://github.com/rust-lang/crates.io-index" +checksum = "17e82ab96c5a55263b5bed151b8426410d93aa909a453acdbd4b6792b5af7d64" +dependencies = [ + "proc-macro2", + "quote", + "syn 2.0.66", +] + +[[package]] +name = "utoipauto-macro" +version = "0.1.12" +source = "registry+https://github.com/rust-lang/crates.io-index" +checksum = "86b8338dc3c9526011ffaa2aa6bd60ddfda9d49d2123108690755c6e34844212" +dependencies = [ + "proc-macro2", + "quote", + "syn 2.0.66", + "utoipauto-core", +] + [[package]] name = "uuid" version = "1.8.0" @@ -10140,7 +10242,7 @@ source = "registry+https://github.com/rust-lang/crates.io-index" checksum = "e48a53791691ab099e5e2ad123536d0fff50652600abaf43bbf952894110d0be" dependencies = [ "windows-core", - "windows-targets 0.52.5", + "windows-targets 0.52.6", ] [[package]] @@ -10149,7 +10251,7 @@ version = "0.52.0" source = "registry+https://github.com/rust-lang/crates.io-index" checksum = "33ab640c8d7e35bf8ba19b884ba838ceb4fba93a4e8c65a9059d08afcfc683d9" dependencies = [ - "windows-targets 0.52.5", + "windows-targets 0.52.6", ] [[package]] @@ -10176,7 +10278,7 @@ version = "0.52.0" source = "registry+https://github.com/rust-lang/crates.io-index" checksum = "282be5f36a8ce781fad8c8ae18fa3f9beff57ec1b52cb3de0789201425d9a33d" dependencies = [ - "windows-targets 0.52.5", + "windows-targets 0.52.6", ] [[package]] @@ -10211,18 +10313,18 @@ dependencies = [ [[package]] name = "windows-targets" -version = "0.52.5" +version = "0.52.6" source = "registry+https://github.com/rust-lang/crates.io-index" -checksum = "6f0713a46559409d202e70e28227288446bf7841d3211583a4b53e3f6d96e7eb" +checksum = "9b724f72796e036ab90c1021d4780d4d3d648aca59e491e6b98e725b84e99973" dependencies = [ - "windows_aarch64_gnullvm 0.52.5", - "windows_aarch64_msvc 0.52.5", - "windows_i686_gnu 0.52.5", + "windows_aarch64_gnullvm 0.52.6", + "windows_aarch64_msvc 0.52.6", + "windows_i686_gnu 0.52.6", "windows_i686_gnullvm", - "windows_i686_msvc 0.52.5", - "windows_x86_64_gnu 0.52.5", - "windows_x86_64_gnullvm 0.52.5", - "windows_x86_64_msvc 0.52.5", + "windows_i686_msvc 0.52.6", + "windows_x86_64_gnu 0.52.6", + "windows_x86_64_gnullvm 0.52.6", + "windows_x86_64_msvc 0.52.6", ] [[package]] @@ -10239,9 +10341,9 @@ checksum = "2b38e32f0abccf9987a4e3079dfb67dcd799fb61361e53e2882c3cbaf0d905d8" [[package]] name = "windows_aarch64_gnullvm" -version = "0.52.5" +version = "0.52.6" source = "registry+https://github.com/rust-lang/crates.io-index" -checksum = "7088eed71e8b8dda258ecc8bac5fb1153c5cffaf2578fc8ff5d61e23578d3263" +checksum = "32a4622180e7a0ec044bb555404c800bc9fd9ec262ec147edd5989ccd0c02cd3" [[package]] name = "windows_aarch64_msvc" @@ -10257,9 +10359,9 @@ checksum = "dc35310971f3b2dbbf3f0690a219f40e2d9afcf64f9ab7cc1be722937c26b4bc" [[package]] name = "windows_aarch64_msvc" -version = "0.52.5" +version = "0.52.6" source = "registry+https://github.com/rust-lang/crates.io-index" -checksum = "9985fd1504e250c615ca5f281c3f7a6da76213ebd5ccc9561496568a2752afb6" +checksum = "09ec2a7bb152e2252b53fa7803150007879548bc709c039df7627cabbd05d469" [[package]] name = "windows_i686_gnu" @@ -10275,15 +10377,15 @@ checksum = "a75915e7def60c94dcef72200b9a8e58e5091744960da64ec734a6c6e9b3743e" [[package]] name = "windows_i686_gnu" -version = "0.52.5" +version = "0.52.6" source = "registry+https://github.com/rust-lang/crates.io-index" -checksum = "88ba073cf16d5372720ec942a8ccbf61626074c6d4dd2e745299726ce8b89670" +checksum = "8e9b5ad5ab802e97eb8e295ac6720e509ee4c243f69d781394014ebfe8bbfa0b" [[package]] name = "windows_i686_gnullvm" -version = "0.52.5" +version = "0.52.6" source = "registry+https://github.com/rust-lang/crates.io-index" -checksum = "87f4261229030a858f36b459e748ae97545d6f1ec60e5e0d6a3d32e0dc232ee9" +checksum = "0eee52d38c090b3caa76c563b86c3a4bd71ef1a819287c19d586d7334ae8ed66" [[package]] name = "windows_i686_msvc" @@ -10299,9 +10401,9 @@ checksum = "8f55c233f70c4b27f66c523580f78f1004e8b5a8b659e05a4eb49d4166cca406" [[package]] name = "windows_i686_msvc" -version = "0.52.5" +version = "0.52.6" source = "registry+https://github.com/rust-lang/crates.io-index" -checksum = "db3c2bf3d13d5b658be73463284eaf12830ac9a26a90c717b7f771dfe97487bf" +checksum = "240948bc05c5e7c6dabba28bf89d89ffce3e303022809e73deaefe4f6ec56c66" [[package]] name = "windows_x86_64_gnu" @@ -10317,9 +10419,9 @@ checksum = "53d40abd2583d23e4718fddf1ebec84dbff8381c07cae67ff7768bbf19c6718e" [[package]] name = "windows_x86_64_gnu" -version = "0.52.5" +version = "0.52.6" source = "registry+https://github.com/rust-lang/crates.io-index" -checksum = "4e4246f76bdeff09eb48875a0fd3e2af6aada79d409d33011886d3e1581517d9" +checksum = "147a5c80aabfbf0c7d901cb5895d1de30ef2907eb21fbbab29ca94c5b08b1a78" [[package]] name = "windows_x86_64_gnullvm" @@ -10335,9 +10437,9 @@ checksum = "0b7b52767868a23d5bab768e390dc5f5c55825b6d30b86c844ff2dc7414044cc" [[package]] name = "windows_x86_64_gnullvm" -version = "0.52.5" +version = "0.52.6" source = "registry+https://github.com/rust-lang/crates.io-index" -checksum = "852298e482cd67c356ddd9570386e2862b5673c85bd5f88df9ab6802b334c596" +checksum = "24d5b23dc417412679681396f2b49f3de8c1473deb516bd34410872eff51ed0d" [[package]] name = "windows_x86_64_msvc" @@ -10353,9 +10455,9 @@ checksum = "ed94fce61571a4006852b7389a063ab983c02eb1bb37b47f8272ce92d06d9538" [[package]] name = "windows_x86_64_msvc" -version = "0.52.5" +version = "0.52.6" source = "registry+https://github.com/rust-lang/crates.io-index" -checksum = "bec47e5bfd1bff0eeaf6d8b485cc1074891a197ab4225d504cb7a1ab88b02bf0" +checksum = "589f6da84c646204747d1270a2a5661ea66ed1cced2631d546fdfb155959f9ec" [[package]] name = "winnow" @@ -10458,18 +10560,18 @@ dependencies = [ [[package]] name = "zerocopy" -version = "0.7.34" +version = "0.7.35" source = "registry+https://github.com/rust-lang/crates.io-index" -checksum = "ae87e3fcd617500e5d106f0380cf7b77f3c6092aae37191433159dda23cfb087" +checksum = "1b9b4fd18abc82b8136838da5d50bae7bdea537c574d8dc1a34ed098d6c166f0" dependencies = [ "zerocopy-derive", ] [[package]] name = "zerocopy-derive" -version = "0.7.34" +version = "0.7.35" source = "registry+https://github.com/rust-lang/crates.io-index" -checksum = "15e934569e47891f7d9411f1a451d947a60e000ab3bd24fbb970f000387d1b3b" +checksum = "fa4f8080344d4671fb4e831a13ad1e68092748387dfc4f55e356242fae12ce3e" dependencies = [ "proc-macro2", "quote", @@ -10498,14 +10600,18 @@ dependencies = [ [[package]] name = "zip" -version = "0.6.6" +version = "1.1.4" source = "registry+https://github.com/rust-lang/crates.io-index" -checksum = "760394e246e4c28189f19d488c058bf16f564016aefac5d32bb1f3b51d5e9261" +checksum = "9cc23c04387f4da0374be4533ad1208cbb091d5c11d070dfef13676ad6497164" dependencies = [ - "byteorder", + "arbitrary", "crc32fast", "crossbeam-utils", + "displaydoc", "flate2", + "indexmap 2.2.6", + "num_enum", + "thiserror", ] [[package]] diff --git a/Cargo.toml b/Cargo.toml index 4d5975a380..15352251d5 100644 --- a/Cargo.toml +++ b/Cargo.toml @@ -311,8 +311,10 @@ tracing-tree = "0.2.2" ts-rs = "7.0.0" tungstenite = { version = "0.20.1", default-features = false } url = "2.5" -utoipa = "4.2.0" -utoipa-swagger-ui = "6.0.0" +utoipa = "4.2" +utoipa-rapidoc = "4.0" +utoipa-swagger-ui = "7.1" +utoipauto = "0.1" uuid = "*" vergen = { version = "=8.3.1", default-features = false } walkdir = "2" diff --git a/common/config/Cargo.toml b/common/config/Cargo.toml index 5ea13a45ce..6ff3efc432 100644 --- a/common/config/Cargo.toml +++ b/common/config/Cargo.toml @@ -15,7 +15,8 @@ serde = { workspace = true, features = ["derive"] } toml = "0.7.4" url = { workspace = true } -nym-network-defaults = { path = "../network-defaults" } +nym-network-defaults = { path = "../network-defaults", features = ["utoipa"] } [features] default = ["dirs"] +utoipa = [ "nym-network-defaults/utoipa" ] diff --git a/common/cosmwasm-smart-contracts/mixnet-contract/Cargo.toml b/common/cosmwasm-smart-contracts/mixnet-contract/Cargo.toml index 31e422a49c..86afc9d0c8 100644 --- a/common/cosmwasm-smart-contracts/mixnet-contract/Cargo.toml +++ b/common/cosmwasm-smart-contracts/mixnet-contract/Cargo.toml @@ -22,6 +22,7 @@ thiserror = { workspace = true } contracts-common = { path = "../contracts-common", package = "nym-contracts-common", version = "0.5.0" } serde-json-wasm = { workspace = true } humantime-serde = { workspace = true } +utoipa = { workspace = true, optional = true } # TO CHECK WHETHER STILL NEEDED: log = { workspace = true } @@ -35,5 +36,6 @@ time = { workspace = true, features = ["serde", "macros"] } [features] default = [] contract-testing = [] +utoipa = [ "dep:utoipa" ] schema = ["cw2"] generate-ts = ['ts-rs'] diff --git a/common/cosmwasm-smart-contracts/mixnet-contract/src/gateway.rs b/common/cosmwasm-smart-contracts/mixnet-contract/src/gateway.rs index ff991853fb..9d75b66c22 100644 --- a/common/cosmwasm-smart-contracts/mixnet-contract/src/gateway.rs +++ b/common/cosmwasm-smart-contracts/mixnet-contract/src/gateway.rs @@ -10,6 +10,7 @@ use std::fmt::Display; /// Information provided by the node operator during bonding that are used to allow other entities to use the services of this node. #[cw_serde] #[derive(PartialOrd)] +#[cfg_attr(feature = "utoipa", derive(utoipa::ToSchema))] pub struct Gateway { /// Network address of this gateway, for example 1.1.1.1 or foo.gateway.com pub host: String, @@ -25,9 +26,11 @@ pub struct Gateway { pub location: String, /// Base58-encoded x25519 public key used for sphinx key derivation. + #[cfg_attr(feature = "utoipa", schema(value_type = String))] pub sphinx_key: SphinxKey, /// Base58 encoded ed25519 EdDSA public key of the gateway used to derive shared keys with clients + #[cfg_attr(feature = "utoipa", schema(value_type = String))] pub identity_key: IdentityKey, /// The self-reported semver version of this gateway. @@ -36,6 +39,7 @@ pub struct Gateway { /// Basic gateway information provided by the node operator. #[cw_serde] +#[cfg_attr(feature = "utoipa", derive(utoipa::ToSchema))] pub struct GatewayBond { /// Original amount pledged by the operator of this node. pub pledge_amount: Coin, diff --git a/common/cosmwasm-smart-contracts/mixnet-contract/src/interval.rs b/common/cosmwasm-smart-contracts/mixnet-contract/src/interval.rs index 9301d92d29..d5382a29e6 100644 --- a/common/cosmwasm-smart-contracts/mixnet-contract/src/interval.rs +++ b/common/cosmwasm-smart-contracts/mixnet-contract/src/interval.rs @@ -209,8 +209,10 @@ impl Display for EpochState { ts(export_to = "ts-packages/types/src/types/rust/Interval.ts") )] #[derive(Clone, Copy, Debug, Deserialize, PartialEq, Eq, Serialize)] +#[cfg_attr(feature = "utoipa", derive(utoipa::ToSchema))] pub struct Interval { /// Monotonously increasing id of this interval. + #[cfg_attr(feature = "utoipa", schema(value_type = u32))] id: IntervalId, /// Number of epochs in this interval. @@ -226,6 +228,7 @@ pub struct Interval { current_epoch_start: OffsetDateTime, /// Monotonously increasing id of the current epoch in this interval. + #[cfg_attr(feature = "utoipa", schema(value_type = u32))] current_epoch_id: EpochId, /// The duration of all epochs in this interval. @@ -233,6 +236,7 @@ pub struct Interval { epoch_length: Duration, /// The total amount of elapsed epochs since the first epoch of the first interval. + #[cfg_attr(feature = "utoipa", schema(value_type = u32))] total_elapsed_epochs: EpochId, } diff --git a/common/http-api-common/Cargo.toml b/common/http-api-common/Cargo.toml index 0bd7767a05..b9252c2b05 100644 --- a/common/http-api-common/Cargo.toml +++ b/common/http-api-common/Cargo.toml @@ -13,8 +13,13 @@ license.workspace = true [dependencies] axum.workspace = true bytes = { workspace = true } +colored.workspace = true mime = { workspace = true } serde = { workspace = true, features = ["derive"] } serde_json.workspace = true serde_yaml = { workspace = true } -utoipa = { workspace = true } +tracing.workspace = true +utoipa = { workspace = true, optional = true } + +[features] +utoipa = ["dep:utoipa"] diff --git a/common/http-api-common/src/lib.rs b/common/http-api-common/src/lib.rs index 83b9c685d8..f84e6e2ecc 100644 --- a/common/http-api-common/src/lib.rs +++ b/common/http-api-common/src/lib.rs @@ -6,9 +6,11 @@ use axum::response::{IntoResponse, Response}; use axum::Json; use bytes::{BufMut, BytesMut}; use serde::{Deserialize, Serialize}; -use utoipa::{IntoParams, ToSchema}; -#[derive(Debug, Clone, ToSchema)] +pub mod logging; + +#[derive(Debug, Clone)] +#[cfg_attr(feature = "utoipa", derive(utoipa::ToSchema))] pub enum FormattedResponse { Json(Json), Yaml(Yaml), @@ -26,7 +28,8 @@ where } } -#[derive(Default, Debug, Serialize, Deserialize, Copy, Clone, ToSchema)] +#[derive(Default, Debug, Serialize, Deserialize, Copy, Clone)] +#[cfg_attr(feature = "utoipa", derive(utoipa::ToSchema))] #[serde(rename_all = "lowercase")] pub enum Output { #[default] @@ -34,7 +37,8 @@ pub enum Output { Yaml, } -#[derive(Default, Debug, Serialize, Deserialize, Copy, Clone, IntoParams, ToSchema)] +#[derive(Default, Debug, Serialize, Deserialize, Copy, Clone)] +#[cfg_attr(feature = "utoipa", derive(utoipa::IntoParams, utoipa::ToSchema))] #[serde(default)] pub struct OutputParams { pub output: Option, diff --git a/common/http-api-common/src/logging.rs b/common/http-api-common/src/logging.rs new file mode 100644 index 0000000000..ca2f5c63ce --- /dev/null +++ b/common/http-api-common/src/logging.rs @@ -0,0 +1,63 @@ +// Copyright 2024 - Nym Technologies SA +// SPDX-License-Identifier: GPL-3.0-only + +use axum::extract::{ConnectInfo, Request}; +use axum::http::header::{HOST, USER_AGENT}; +use axum::http::HeaderValue; +use axum::middleware::Next; +use axum::response::IntoResponse; +use colored::Colorize; +use std::net::SocketAddr; +use std::time::Instant; +use tracing::info; + +pub async fn logger( + ConnectInfo(addr): ConnectInfo, + request: Request, + next: Next, +) -> impl IntoResponse { + // TODO dz use `OriginalUri` extractor to get full URI even for nested + // routers if routes aren't logged correctly in handlers + fn header_map(header: Option<&HeaderValue>, msg: String) -> String { + header + .map(|x| x.to_str().unwrap_or(&msg).to_string()) + .unwrap_or(msg) + } + + let method = request.method().to_string().green(); + let uri = request.uri().to_string().blue(); + let agent = header_map( + request.headers().get(USER_AGENT), + "Unknown User Agent".to_string(), + ); + + let host = header_map(request.headers().get(HOST), "Unknown Host".to_string()); + + let start = Instant::now(); + // run request through all middleware, incl. extractors + let res = next.run(request).await; + let time_taken = start.elapsed(); + let status = res.status(); + let print_status = if status.is_client_error() || status.is_server_error() { + status.to_string().red() + } else if status.is_success() { + status.to_string().green() + } else { + status.to_string().yellow() + }; + + let taken = "time taken".bold(); + + let time_taken = match time_taken.as_millis() { + ms if ms > 500 => format!("{taken}: {}", format!("{ms}ms").red()), + ms if ms > 200 => format!("{taken}: {}", format!("{ms}ms").yellow()), + ms if ms > 50 => format!("{taken}: {}", format!("{ms}ms").bright_yellow()), + ms => format!("{taken}: {ms}ms"), + }; + + let agent_str = "agent".bold(); + + info!("[{addr} -> {host}] {method} '{uri}': {print_status} {time_taken} {agent_str}: {agent}"); + + res +} diff --git a/common/network-defaults/Cargo.toml b/common/network-defaults/Cargo.toml index 03d09cf159..2cd2d4c443 100644 --- a/common/network-defaults/Cargo.toml +++ b/common/network-defaults/Cargo.toml @@ -13,6 +13,7 @@ log = { workspace = true, optional = true } schemars = { workspace = true, features = ["preserve_order"], optional = true } serde = { workspace = true, features = ["derive"], optional = true } url = { workspace = true, optional = true } +utoipa = { workspace = true, optional = true } # please be extremely careful when adding new dependencies because this crate is imported by the ecash contract, # so if anything new is added, consider feature-locking it and then just adding it to default feature @@ -20,4 +21,5 @@ url = { workspace = true, optional = true } [features] default = ["env", "network"] env = ["dotenvy", "log"] -network = ["schemars", "serde", "url"] \ No newline at end of file +network = ["schemars", "serde", "url"] +utoipa = [ "dep:utoipa" ] diff --git a/common/network-defaults/src/network.rs b/common/network-defaults/src/network.rs index 9dbb5d9bc2..591f609ed9 100644 --- a/common/network-defaults/src/network.rs +++ b/common/network-defaults/src/network.rs @@ -8,6 +8,7 @@ use std::ops::Not; use url::Url; #[derive(Clone, Debug, Deserialize, Eq, Hash, PartialEq, Serialize, JsonSchema)] +#[cfg_attr(feature = "utoipa", derive(utoipa::ToSchema))] pub struct ChainDetails { pub bech32_account_prefix: String, pub mix_denom: DenomDetailsOwned, @@ -15,6 +16,7 @@ pub struct ChainDetails { } #[derive(Clone, Debug, Default, Deserialize, Eq, Hash, PartialEq, Serialize, JsonSchema)] +#[cfg_attr(feature = "utoipa", derive(utoipa::ToSchema))] pub struct NymContracts { pub mixnet_contract_address: Option, pub vesting_contract_address: Option, @@ -27,6 +29,7 @@ pub struct NymContracts { // I wanted to use the simpler `NetworkDetails` name, but there's a clash // with `NetworkDetails` defined in all.rs... #[derive(Clone, Debug, Deserialize, Eq, Hash, PartialEq, Serialize, JsonSchema)] +#[cfg_attr(feature = "utoipa", derive(utoipa::ToSchema))] pub struct NymNetworkDetails { pub network_name: String, pub chain_details: ChainDetails, @@ -293,6 +296,7 @@ impl DenomDetails { } #[derive(Debug, Serialize, Deserialize, Hash, Clone, PartialEq, Eq, JsonSchema)] +#[cfg_attr(feature = "utoipa", derive(utoipa::ToSchema))] pub struct DenomDetailsOwned { pub base: String, pub display: String, @@ -321,6 +325,7 @@ impl DenomDetailsOwned { } #[derive(Clone, Debug, Deserialize, Eq, Hash, PartialEq, Serialize, JsonSchema)] +#[cfg_attr(feature = "utoipa", derive(utoipa::ToSchema))] pub struct ValidatorDetails { // it is assumed those values are always valid since they're being provided in our defaults file pub nyxd_url: String, diff --git a/nym-api/Cargo.toml b/nym-api/Cargo.toml index d6906d0ce8..f776ca226f 100644 --- a/nym-api/Cargo.toml +++ b/nym-api/Cargo.toml @@ -50,6 +50,7 @@ tokio = { workspace = true, features = [ "time", ] } tokio-stream = { workspace = true } +tokio-util = { workspace = true } url = { workspace = true } ts-rs = { workspace = true, optional = true } @@ -70,6 +71,16 @@ rocket_okapi = { workspace = true, features = ["swagger"] } schemars = { workspace = true, features = ["preserve_order"] } zeroize = { workspace = true } +# for axum server +axum = { workspace = true, features = ["tokio"], optional = true } +axum-extra = { workspace = true, features = ["typed-header"], optional = true } +tower-http = { workspace = true, features = ["cors", "trace"], optional = true } +utoipa = { workspace = true, features = ["axum_extras", "time"], optional = true } +utoipa-swagger-ui = { workspace = true, features = ["axum"], optional = true} +utoipauto = { workspace = true, optional = true } +tracing-subscriber = { workspace = true, features = ["env-filter"], optional = true } +tracing = { workspace = true, optional = true } + ## ephemera-specific #actix-web = "4" #array-bytes = "6.0.0" @@ -101,7 +112,7 @@ cw4 = { workspace = true } nym-dkg = { path = "../common/dkg", features = ["cw-types"] } nym-gateway-client = { path = "../common/client-libs/gateway-client" } nym-inclusion-probability = { path = "../common/inclusion-probability" } -nym-mixnet-contract-common = { path = "../common/cosmwasm-smart-contracts/mixnet-contract" } +nym-mixnet-contract-common = { path = "../common/cosmwasm-smart-contracts/mixnet-contract", features = ["utoipa"]} nym-vesting-contract-common = { path = "../common/cosmwasm-smart-contracts/vesting-contract" } nym-contracts-common = { path = "../common/cosmwasm-smart-contracts/contracts-common" } nym-multisig-contract-common = { path = "../common/cosmwasm-smart-contracts/multisig-contract" } @@ -112,14 +123,26 @@ nym-task = { path = "../common/task" } nym-topology = { path = "../common/topology" } nym-api-requests = { path = "nym-api-requests", features = ["rocket-traits"] } nym-validator-client = { path = "../common/client-libs/validator-client" } -nym-bin-common = { path = "../common/bin-common", features = ["output_format"] } +nym-bin-common = { path = "../common/bin-common", features = ["output_format", "openapi"] } nym-node-tester-utils = { path = "../common/node-tester-utils" } nym-node-requests = { path = "../nym-node/nym-node-requests" } nym-types = { path = "../common/types" } +nym-http-api-common = { path = "../common/http-api-common", features = ["utoipa"] } [features] no-reward = [] generate-ts = ["ts-rs"] +axum = ["dep:axum", + "axum-extra", + "tower-http", + "utoipa", + "utoipauto", + "tracing-subscriber", + "tracing", + "utoipa-swagger-ui", + "nym-http-api-common/utoipa", + "nym-mixnet-contract-common/utoipa" +] [build-dependencies] tokio = { workspace = true, features = ["rt-multi-thread", "macros"] } diff --git a/nym-api/nym-api-requests/Cargo.toml b/nym-api/nym-api-requests/Cargo.toml index a4730db70e..ca647160e7 100644 --- a/nym-api/nym-api-requests/Cargo.toml +++ b/nym-api/nym-api-requests/Cargo.toml @@ -18,6 +18,7 @@ tendermint = { workspace = true } time = { workspace = true, features = ["serde", "parsing", "formatting"] } thiserror.workspace = true rocket = { workspace = true, optional = true } +utoipa.workspace = true sha2 = "0.10.8" @@ -31,7 +32,7 @@ nym-crypto = { path = "../../common/crypto", features = ["serde", "asymmetric"] nym-ecash-time = { path = "../../common/ecash-time" } nym-compact-ecash = { path = "../../common/nym_offline_compact_ecash" } nym-mixnet-contract-common = { path = "../../common/cosmwasm-smart-contracts/mixnet-contract" } -nym-node-requests = { path = "../../nym-node/nym-node-requests", default-features = false } +nym-node-requests = { path = "../../nym-node/nym-node-requests", default-features = false, features = ["openapi"] } [dev-dependencies] diff --git a/nym-api/nym-api-requests/src/ecash/models.rs b/nym-api/nym-api-requests/src/ecash/models.rs index bb3453463c..64c1a2dccb 100644 --- a/nym-api/nym-api-requests/src/ecash/models.rs +++ b/nym-api/nym-api-requests/src/ecash/models.rs @@ -20,6 +20,7 @@ use std::collections::BTreeMap; use std::ops::Deref; use thiserror::Error; use time::Date; +use utoipa::ToSchema; #[derive(Serialize, Deserialize, Clone, JsonSchema)] pub struct VerifyEcashTicketBody { @@ -60,7 +61,7 @@ impl VerifyEcashCredentialBody { } } -#[derive(Debug, Serialize, Deserialize, JsonSchema)] +#[derive(Debug, Serialize, Deserialize, JsonSchema, ToSchema)] pub struct EcashTicketVerificationResponse { pub verified: Result<(), EcashTicketVerificationRejection>, } @@ -73,7 +74,7 @@ impl EcashTicketVerificationResponse { } } -#[derive(Debug, Error, Serialize, Deserialize, JsonSchema)] +#[derive(Debug, Error, Serialize, Deserialize, JsonSchema, ToSchema)] pub enum EcashTicketVerificationRejection { #[error("invalid ticket spent date. expected either today's ({today}) or yesterday's* ({yesterday}) date but got {received} instead\n*assuming it's before 1AM UTC")] InvalidSpentDate { @@ -155,7 +156,7 @@ impl BlindSignRequestBody { } } -#[derive(Debug, Serialize, Deserialize, JsonSchema)] +#[derive(Debug, Serialize, Deserialize, JsonSchema, ToSchema)] pub struct BlindedSignatureResponse { #[schemars(with = "PlaceholderJsonSchemaImpl")] pub blinded_signature: BlindedSignature, @@ -198,7 +199,7 @@ impl MasterVerificationKeyResponse { } } -#[derive(Serialize, Deserialize, JsonSchema)] +#[derive(Serialize, Deserialize, JsonSchema, ToSchema)] pub struct VerificationKeyResponse { #[schemars(with = "PlaceholderJsonSchemaImpl")] pub key: VerificationKeyAuth, @@ -222,25 +223,26 @@ impl CosmosAddressResponse { } } -#[derive(Serialize, Deserialize, JsonSchema)] +#[derive(Serialize, Deserialize, JsonSchema, ToSchema)] pub struct PartialExpirationDateSignatureResponse { pub epoch_id: u64, #[schemars(with = "String")] #[serde(with = "crate::helpers::date_serde")] + #[schema(value_type = String)] pub expiration_date: Date, #[schemars(with = "PlaceholderJsonSchemaImpl")] pub signatures: Vec, } -#[derive(Serialize, Deserialize, JsonSchema)] +#[derive(Serialize, Deserialize, JsonSchema, ToSchema)] pub struct PartialCoinIndicesSignatureResponse { pub epoch_id: u64, #[schemars(with = "PlaceholderJsonSchemaImpl")] pub signatures: Vec, } -#[derive(Serialize, Deserialize, JsonSchema)] +#[derive(Serialize, Deserialize, JsonSchema, ToSchema)] pub struct AggregatedExpirationDateSignatureResponse { pub epoch_id: u64, @@ -252,7 +254,7 @@ pub struct AggregatedExpirationDateSignatureResponse { pub signatures: Vec, } -#[derive(Serialize, Deserialize, JsonSchema)] +#[derive(Serialize, Deserialize, JsonSchema, ToSchema)] pub struct AggregatedCoinIndicesSignatureResponse { pub epoch_id: u64, #[schemars(with = "PlaceholderJsonSchemaImpl")] @@ -350,16 +352,17 @@ impl BatchRedeemTicketsBody { } } -#[derive(Debug, Serialize, Deserialize, JsonSchema)] +#[derive(Debug, Serialize, Deserialize, JsonSchema, ToSchema)] pub struct EcashBatchTicketRedemptionResponse { pub proposal_accepted: bool, } -#[derive(Clone, Serialize, Deserialize, Debug, JsonSchema)] +#[derive(Clone, Serialize, Deserialize, Debug, JsonSchema, ToSchema)] #[serde(rename_all = "camelCase")] pub struct SpentCredentialsResponse { #[serde(with = "nym_serde_helpers::base64")] #[schemars(with = "String")] + #[schema(value_type = String)] pub bitmap: Vec, } @@ -369,7 +372,7 @@ impl SpentCredentialsResponse { } } -#[derive(Clone, Serialize, Deserialize, Debug, JsonSchema)] +#[derive(Clone, Serialize, Deserialize, Debug, JsonSchema, ToSchema)] #[serde(rename_all = "camelCase")] pub struct EpochCredentialsResponse { pub epoch_id: u64, @@ -377,20 +380,20 @@ pub struct EpochCredentialsResponse { pub total_issued: u32, } -#[derive(Clone, Serialize, Deserialize, Debug, JsonSchema)] +#[derive(Clone, Serialize, Deserialize, Debug, JsonSchema, ToSchema)] #[serde(rename_all = "camelCase")] pub struct IssuedCredentialsResponse { // note: BTreeMap returns ordered results so it's fine to use it with pagination pub credentials: BTreeMap, } -#[derive(Clone, Serialize, Deserialize, Debug, JsonSchema)] +#[derive(Clone, Serialize, Deserialize, Debug, JsonSchema, ToSchema)] #[serde(rename_all = "camelCase")] pub struct IssuedCredentialResponse { pub credential: Option, } -#[derive(Clone, Serialize, Deserialize, Debug, PartialEq, JsonSchema)] +#[derive(Clone, Serialize, Deserialize, Debug, PartialEq, JsonSchema, ToSchema)] #[serde(rename_all = "camelCase")] pub struct IssuedTicketbookBody { pub credential: IssuedTicketbook, diff --git a/nym-api/nym-api-requests/src/models.rs b/nym-api/nym-api-requests/src/models.rs index 8245d26d70..5889a33b83 100644 --- a/nym-api/nym-api-requests/src/models.rs +++ b/nym-api/nym-api-requests/src/models.rs @@ -1,10 +1,10 @@ -// Copyright 2022 - Nym Technologies SA +// Copyright 2022-2024 - Nym Technologies SA // SPDX-License-Identifier: Apache-2.0 use crate::helpers::unix_epoch; use crate::nym_nodes::NodeRole; use crate::pagination::PaginatedResponse; -use cosmwasm_std::{Addr, Coin, Decimal}; +use cosmwasm_std::{Addr, Coin, Decimal, Uint128}; use nym_mixnet_contract_common::families::FamilyHead; use nym_mixnet_contract_common::mixnode::MixNodeDetails; use nym_mixnet_contract_common::reward_params::{Performance, RewardingParams}; @@ -22,6 +22,7 @@ use std::net::IpAddr; use std::ops::{Deref, DerefMut}; use std::{fmt, time::Duration}; use time::OffsetDateTime; +use utoipa::{IntoParams, ToResponse, ToSchema}; #[derive(Clone, Debug, Serialize, Deserialize, PartialEq, Eq, JsonSchema)] pub struct RequestError { @@ -38,6 +39,12 @@ impl RequestError { pub fn message(&self) -> &str { &self.message } + + pub fn empty() -> Self { + Self { + message: String::new(), + } + } } impl Display for RequestError { @@ -77,7 +84,7 @@ impl MixnodeStatus { } } -#[derive(Clone, Debug, Serialize, Deserialize, JsonSchema)] +#[derive(Clone, Debug, Serialize, Deserialize, JsonSchema, ToSchema)] #[cfg_attr(feature = "generate-ts", derive(ts_rs::TS))] #[cfg_attr( feature = "generate-ts", @@ -88,7 +95,7 @@ pub struct MixnodeCoreStatusResponse { pub count: i32, } -#[derive(Clone, Debug, Serialize, Deserialize, JsonSchema)] +#[derive(Clone, Debug, Serialize, Deserialize, JsonSchema, ToSchema)] #[cfg_attr(feature = "generate-ts", derive(ts_rs::TS))] #[cfg_attr( feature = "generate-ts", @@ -99,7 +106,7 @@ pub struct GatewayCoreStatusResponse { pub count: i32, } -#[derive(Clone, Copy, Debug, Serialize, Deserialize, JsonSchema)] +#[derive(Clone, Copy, Debug, Serialize, Deserialize, JsonSchema, ToSchema)] #[cfg_attr(feature = "generate-ts", derive(ts_rs::TS))] #[cfg_attr( feature = "generate-ts", @@ -109,19 +116,39 @@ pub struct MixnodeStatusResponse { pub status: MixnodeStatus, } -#[derive(Clone, Debug, Default, Serialize, Deserialize, JsonSchema)] +#[derive(Clone, Debug, Default, Serialize, Deserialize, JsonSchema, ToSchema)] pub struct NodePerformance { + #[schema(value_type = String)] pub most_recent: Performance, + #[schema(value_type = String)] pub last_hour: Performance, + #[schema(value_type = String)] pub last_24h: Performance, } -#[derive(Clone, Debug, Serialize, Deserialize, JsonSchema)] +#[derive(ToSchema)] +#[schema(title = "MixNodeDetails")] +pub struct MixNodeDetailsSchema { + /// Basic bond information of this mixnode, such as owner address, original pledge, etc. + pub bond_information: String, + + /// Details used for computation of rewarding related data. + pub rewarding_details: String, + + /// Adjustments to the mixnode that are ought to happen during future epoch transitions. + pub pending_changes: String, +} + +#[derive(Clone, Debug, Serialize, Deserialize, JsonSchema, ToSchema)] pub struct MixNodeBondAnnotated { + #[schema(value_type = MixNodeDetailsSchema)] pub mixnode_details: MixNodeDetails, + #[schema(value_type = String)] pub stake_saturation: StakeSaturation, + #[schema(value_type = String)] pub uncapped_stake_saturation: StakeSaturation, // NOTE: the performance field is deprecated in favour of node_performance + #[schema(value_type = String)] pub performance: Performance, pub node_performance: NodePerformance, pub estimated_operator_apy: Decimal, @@ -152,7 +179,7 @@ impl MixNodeBondAnnotated { } } -#[derive(Clone, Debug, Serialize, Deserialize, JsonSchema)] +#[derive(Clone, Debug, Serialize, Deserialize, JsonSchema, ToSchema)] pub struct GatewayBondAnnotated { pub gateway_bond: GatewayBond, @@ -183,13 +210,16 @@ pub struct GatewayDescription { // for now only expose what we need. this struct will evolve in the future (or be incorporated into nym-node properly) } -#[derive(Debug, Serialize, Deserialize, JsonSchema)] +#[derive(Debug, Serialize, Deserialize, JsonSchema, ToSchema, IntoParams)] pub struct ComputeRewardEstParam { + #[schema(value_type = String)] pub performance: Option, pub active_in_rewarded_set: Option, pub pledge_amount: Option, pub total_delegation: Option, + #[schema(value_type = CoinSchema)] pub interval_operating_cost: Option, + #[schema(value_type = String)] pub profit_margin_percent: Option, } @@ -198,7 +228,7 @@ pub struct ComputeRewardEstParam { feature = "generate-ts", ts(export_to = "ts-packages/types/src/types/rust/RewardEstimationResponse.ts") )] -#[derive(Clone, Copy, Debug, Serialize, Deserialize, JsonSchema)] +#[derive(Clone, Copy, Debug, Serialize, Deserialize, JsonSchema, ToSchema)] pub struct RewardEstimationResponse { pub estimation: RewardEstimate, pub reward_params: RewardingParams, @@ -207,15 +237,16 @@ pub struct RewardEstimationResponse { pub as_at: i64, } -#[derive(Clone, Debug, Serialize, Deserialize, JsonSchema)] +#[derive(Clone, Debug, Serialize, Deserialize, JsonSchema, ToSchema)] pub struct UptimeResponse { + #[schema(value_type = u32)] pub mix_id: MixId, // The same as node_performance.last_24h. Legacy pub avg_uptime: u8, pub node_performance: NodePerformance, } -#[derive(Clone, Debug, Serialize, Deserialize, JsonSchema)] +#[derive(Clone, Debug, Serialize, Deserialize, JsonSchema, ToSchema)] pub struct GatewayUptimeResponse { pub identity: String, // The same as node_performance.last_24h. Legacy @@ -223,7 +254,7 @@ pub struct GatewayUptimeResponse { pub node_performance: NodePerformance, } -#[derive(Clone, Copy, Debug, Serialize, Deserialize, JsonSchema)] +#[derive(Clone, Copy, Debug, Serialize, Deserialize, JsonSchema, ToSchema)] #[cfg_attr(feature = "generate-ts", derive(ts_rs::TS))] #[cfg_attr( feature = "generate-ts", @@ -231,16 +262,18 @@ pub struct GatewayUptimeResponse { )] pub struct StakeSaturationResponse { #[cfg_attr(feature = "generate-ts", ts(type = "string"))] + #[schema(value_type = String)] pub saturation: StakeSaturation, #[cfg_attr(feature = "generate-ts", ts(type = "string"))] + #[schema(value_type = String)] pub uncapped_saturation: StakeSaturation, pub as_at: i64, } pub type StakeSaturation = Decimal; -#[derive(Clone, Debug, Serialize, Deserialize, JsonSchema)] +#[derive(Clone, Debug, Serialize, Deserialize, JsonSchema, ToSchema)] #[cfg_attr(feature = "generate-ts", derive(ts_rs::TS))] #[cfg_attr( feature = "generate-ts", @@ -282,7 +315,7 @@ impl fmt::Display for SelectionChance { } } -#[derive(Clone, Debug, Serialize, Deserialize, JsonSchema)] +#[derive(Clone, Debug, Serialize, Deserialize, JsonSchema, ToSchema)] #[cfg_attr(feature = "generate-ts", derive(ts_rs::TS))] #[cfg_attr( feature = "generate-ts", @@ -303,7 +336,7 @@ impl fmt::Display for InclusionProbabilityResponse { } } -#[derive(Clone, Serialize, schemars::JsonSchema)] +#[derive(Clone, Serialize, schemars::JsonSchema, ToSchema)] pub struct AllInclusionProbabilitiesResponse { pub inclusion_probabilities: Vec, pub samples: u64, @@ -313,8 +346,9 @@ pub struct AllInclusionProbabilitiesResponse { pub as_at: i64, } -#[derive(Clone, Serialize, schemars::JsonSchema)] +#[derive(Clone, Serialize, schemars::JsonSchema, ToSchema)] pub struct InclusionProbability { + #[schema(value_type = u32)] pub mix_id: MixId, pub in_active: f64, pub in_reserve: f64, @@ -322,7 +356,7 @@ pub struct InclusionProbability { type Uptime = u8; -#[derive(Clone, Serialize, Deserialize, schemars::JsonSchema)] +#[derive(Clone, Serialize, Deserialize, schemars::JsonSchema, ToSchema)] pub struct MixnodeStatusReportResponse { pub mix_id: MixId, pub identity: IdentityKey, @@ -332,22 +366,26 @@ pub struct MixnodeStatusReportResponse { pub last_day: Uptime, } -#[derive(Clone, Serialize, Deserialize, schemars::JsonSchema)] +#[derive(Clone, Serialize, Deserialize, schemars::JsonSchema, ToSchema)] pub struct GatewayStatusReportResponse { pub identity: String, pub owner: String, + #[schema(value_type = u8)] pub most_recent: Uptime, + #[schema(value_type = u8)] pub last_hour: Uptime, + #[schema(value_type = u8)] pub last_day: Uptime, } -#[derive(Clone, Serialize, Deserialize, schemars::JsonSchema)] +#[derive(Clone, Serialize, Deserialize, schemars::JsonSchema, ToSchema)] pub struct HistoricalUptimeResponse { pub date: String, + #[schema(value_type = u8)] pub uptime: Uptime, } -#[derive(Clone, Serialize, Deserialize, schemars::JsonSchema)] +#[derive(Clone, Serialize, Deserialize, schemars::JsonSchema, ToSchema)] pub struct MixnodeUptimeHistoryResponse { pub mix_id: MixId, pub identity: String, @@ -355,22 +393,34 @@ pub struct MixnodeUptimeHistoryResponse { pub history: Vec, } -#[derive(Clone, Serialize, Deserialize, schemars::JsonSchema)] +#[derive(Clone, Serialize, Deserialize, schemars::JsonSchema, ToSchema)] pub struct GatewayUptimeHistoryResponse { pub identity: String, pub owner: String, pub history: Vec, } -#[derive(Clone, Serialize, Deserialize, schemars::JsonSchema)] +#[derive(ToSchema)] +#[schema(title = "Coin")] +pub struct CoinSchema { + pub denom: String, + #[schema(value_type = String)] + pub amount: Uint128, +} + +#[derive(Clone, Serialize, Deserialize, schemars::JsonSchema, ToSchema, ToResponse)] pub struct CirculatingSupplyResponse { + #[schema(value_type = CoinSchema)] pub total_supply: Coin, + #[schema(value_type = CoinSchema)] pub mixmining_reserve: Coin, + #[schema(value_type = CoinSchema)] pub vesting_tokens: Coin, + #[schema(value_type = CoinSchema)] pub circulating_supply: Coin, } -#[derive(Clone, Debug, Serialize, Deserialize, schemars::JsonSchema)] +#[derive(Clone, Debug, Serialize, Deserialize, schemars::JsonSchema, ToSchema)] pub struct HostInformation { pub ip_address: Vec, pub hostname: Option, @@ -387,7 +437,7 @@ impl From for HostInf } } -#[derive(Clone, Debug, Serialize, Deserialize, schemars::JsonSchema)] +#[derive(Clone, Debug, Serialize, Deserialize, schemars::JsonSchema, ToSchema)] pub struct HostKeys { pub ed25519: String, pub x25519: String, @@ -402,7 +452,7 @@ impl From for HostKeys { } } -#[derive(Clone, Debug, Serialize, Deserialize, schemars::JsonSchema)] +#[derive(Clone, Debug, Serialize, Deserialize, schemars::JsonSchema, ToSchema)] pub struct WebSockets { pub ws_port: u16, @@ -426,7 +476,7 @@ where } // for all intents and purposes it's just OffsetDateTime, but we need JsonSchema... -#[derive(Clone, Copy, Debug, Serialize, Deserialize, PartialEq)] +#[derive(Clone, Copy, Debug, Serialize, Deserialize, PartialEq, ToSchema)] pub struct OffsetDateTimeJsonSchemaWrapper( #[serde( default = "unix_epoch", @@ -494,7 +544,7 @@ impl JsonSchema for OffsetDateTimeJsonSchemaWrapper { } // this struct is getting quite bloated... -#[derive(Clone, Debug, Serialize, Deserialize, schemars::JsonSchema)] +#[derive(Clone, Debug, Serialize, Deserialize, schemars::JsonSchema, ToSchema)] pub struct NymNodeDescription { #[serde(default)] pub last_polled: OffsetDateTimeJsonSchemaWrapper, @@ -528,7 +578,7 @@ fn default_node_role() -> NodeRole { NodeRole::Inactive } -#[derive(Clone, Debug, Serialize, Deserialize, schemars::JsonSchema)] +#[derive(Clone, Debug, Serialize, Deserialize, schemars::JsonSchema, ToSchema)] pub struct DescribedGateway { pub bond: GatewayBond, pub self_described: Option, @@ -543,7 +593,7 @@ impl From for DescribedGateway { } } -#[derive(Clone, Debug, Serialize, Deserialize, schemars::JsonSchema)] +#[derive(Clone, Debug, Serialize, Deserialize, schemars::JsonSchema, ToSchema)] pub struct DescribedMixNode { pub bond: MixNodeBond, pub self_described: Option, @@ -558,7 +608,7 @@ impl From for DescribedMixNode { } } -#[derive(Clone, Debug, Serialize, Deserialize, schemars::JsonSchema)] +#[derive(Clone, Debug, Serialize, Deserialize, schemars::JsonSchema, ToSchema)] pub struct NetworkRequesterDetails { /// address of the embedded network requester pub address: String, @@ -567,25 +617,25 @@ pub struct NetworkRequesterDetails { pub uses_exit_policy: bool, } -#[derive(Clone, Debug, Serialize, Deserialize, schemars::JsonSchema)] +#[derive(Clone, Debug, Serialize, Deserialize, schemars::JsonSchema, ToSchema)] pub struct IpPacketRouterDetails { /// address of the embedded ip packet router pub address: String, } -#[derive(Clone, Debug, Serialize, Deserialize, schemars::JsonSchema)] +#[derive(Clone, Debug, Serialize, Deserialize, schemars::JsonSchema, ToSchema)] pub struct AuthenticatorDetails { /// address of the embedded authenticator pub address: String, } -#[derive(Clone, Copy, Debug, Serialize, Deserialize, schemars::JsonSchema)] +#[derive(Clone, Copy, Debug, Serialize, Deserialize, schemars::JsonSchema, ToSchema)] pub struct ApiHealthResponse { pub status: ApiStatus, pub uptime: u64, } -#[derive(Clone, Copy, Debug, Serialize, Deserialize, schemars::JsonSchema)] +#[derive(Clone, Copy, Debug, Serialize, Deserialize, schemars::JsonSchema, ToSchema)] #[serde(rename_all = "lowercase")] pub enum ApiStatus { Up, @@ -606,7 +656,7 @@ impl ApiStatus { } } -#[derive(Clone, Debug, Serialize, Deserialize, schemars::JsonSchema)] +#[derive(Clone, Debug, Serialize, Deserialize, schemars::JsonSchema, ToSchema)] pub struct SignerInformationResponse { pub cosmos_address: String, @@ -631,7 +681,7 @@ pub struct TestRoute { pub layer3: TestNode, } -#[derive(Clone, Debug, Serialize, Deserialize, schemars::JsonSchema)] +#[derive(Clone, Debug, Serialize, Deserialize, schemars::JsonSchema, ToSchema)] pub struct PartialTestResult { pub monitor_run_id: i64, pub timestamp: i64, diff --git a/nym-api/nym-api-requests/src/nym_nodes.rs b/nym-api/nym-api-requests/src/nym_nodes.rs index 50b527070a..3a4ea40ca9 100644 --- a/nym-api/nym-api-requests/src/nym_nodes.rs +++ b/nym-api/nym-api-requests/src/nym_nodes.rs @@ -8,6 +8,7 @@ use nym_mixnet_contract_common::reward_params::Performance; use nym_mixnet_contract_common::MixId; use serde::{Deserialize, Serialize}; use std::net::IpAddr; +use utoipa::ToSchema; #[derive(Clone, Debug, Serialize, Deserialize, schemars::JsonSchema)] pub struct CachedNodesResponse { @@ -15,7 +16,7 @@ pub struct CachedNodesResponse { pub nodes: Vec, } -#[derive(Clone, Debug, Serialize, Deserialize, schemars::JsonSchema)] +#[derive(Clone, Debug, Serialize, Deserialize, schemars::JsonSchema, utoipa::ToSchema)] #[serde(rename_all = "kebab-case")] #[cfg_attr(feature = "rocket-traits", derive(rocket::form::FromFormField))] pub enum NodeRoleQueryParam { @@ -28,7 +29,7 @@ pub enum NodeRoleQueryParam { ExitGateway, } -#[derive(Clone, Debug, Serialize, Deserialize, schemars::JsonSchema)] +#[derive(Clone, Debug, Serialize, Deserialize, schemars::JsonSchema, ToSchema)] pub enum NodeRole { // a properly active mixnode Mixnode { @@ -47,7 +48,7 @@ pub enum NodeRole { Inactive, } -#[derive(Clone, Debug, Serialize, Deserialize, schemars::JsonSchema)] +#[derive(Clone, Debug, Serialize, Deserialize, schemars::JsonSchema, ToSchema)] pub struct BasicEntryInformation { pub hostname: Option, @@ -58,13 +59,15 @@ pub struct BasicEntryInformation { type NodeId = MixId; // the bare minimum information needed to construct sphinx packets -#[derive(Clone, Debug, Serialize, Deserialize, schemars::JsonSchema)] +#[derive(Clone, Debug, Serialize, Deserialize, schemars::JsonSchema, ToSchema)] pub struct SkimmedNode { // in directory v3 all nodes (mixnodes AND gateways) will have a unique id // but to keep structure consistent, introduce this field now + #[schema(value_type = u32)] pub node_id: NodeId, pub ed25519_identity_pubkey: String, + #[schema(value_type = Vec)] pub ip_addresses: Vec, // TODO: to be deprecated in favour of well-known hardcoded port for everyone @@ -74,6 +77,7 @@ pub struct SkimmedNode { pub entry: Option, /// Average node performance in last 24h period + #[schema(value_type = String)] pub performance: Performance, } @@ -143,14 +147,14 @@ impl<'a> From<&'a GatewayBondAnnotated> for SkimmedNode { // an intermediate variant that exposes additional data such as noise keys but without // the full fat of the self-described data -#[derive(Clone, Debug, Serialize, Deserialize, schemars::JsonSchema)] +#[derive(Clone, Debug, Serialize, Deserialize, schemars::JsonSchema, ToSchema)] pub struct SemiSkimmedNode { pub basic: SkimmedNode, pub x25519_noise_pubkey: String, // pub location: } -#[derive(Clone, Debug, Serialize, Deserialize, schemars::JsonSchema)] +#[derive(Clone, Debug, Serialize, Deserialize, schemars::JsonSchema, ToSchema)] pub struct FullFatNode { pub expanded: SemiSkimmedNode, diff --git a/nym-api/nym-api-requests/src/pagination.rs b/nym-api/nym-api-requests/src/pagination.rs index 20ab30e7a6..c17d5a7bee 100644 --- a/nym-api/nym-api-requests/src/pagination.rs +++ b/nym-api/nym-api-requests/src/pagination.rs @@ -3,15 +3,16 @@ use schemars::JsonSchema; use serde::{Deserialize, Serialize}; +use utoipa::ToSchema; -#[derive(Serialize, Deserialize, JsonSchema)] +#[derive(Serialize, Deserialize, JsonSchema, ToSchema)] pub struct Pagination { pub total: usize, pub page: u32, pub size: usize, } -#[derive(Serialize, Deserialize, JsonSchema)] +#[derive(Serialize, Deserialize, JsonSchema, ToSchema)] pub struct PaginatedResponse { pub pagination: Pagination, pub data: Vec, diff --git a/nym-api/src/circulating_supply_api/cache/mod.rs b/nym-api/src/circulating_supply_api/cache/mod.rs index af5568b158..7a2537ebee 100644 --- a/nym-api/src/circulating_supply_api/cache/mod.rs +++ b/nym-api/src/circulating_supply_api/cache/mod.rs @@ -50,7 +50,7 @@ pub(crate) struct CirculatingSupplyCache { } impl CirculatingSupplyCache { - fn new(mix_denom: String) -> CirculatingSupplyCache { + pub(crate) fn new(mix_denom: String) -> CirculatingSupplyCache { CirculatingSupplyCache { initialised: Arc::new(AtomicBool::new(false)), data: Arc::new(RwLock::new(CirculatingSupplyCacheData::new(mix_denom))), @@ -67,6 +67,7 @@ impl CirculatingSupplyCache { } } + #[deprecated(note = "TODO rocket: obsolete because it's used for Rocket")] pub(crate) fn stage(mix_denom: String) -> AdHoc { AdHoc::on_ignite("Circulating Supply Cache Stage", |rocket| async { rocket.manage(Self::new(mix_denom)) diff --git a/nym-api/src/circulating_supply_api/handlers.rs b/nym-api/src/circulating_supply_api/handlers.rs new file mode 100644 index 0000000000..973d1fc64e --- /dev/null +++ b/nym-api/src/circulating_supply_api/handlers.rs @@ -0,0 +1,102 @@ +// Copyright 2022-2023 - Nym Technologies SA +// SPDX-License-Identifier: GPL-3.0-only + +use crate::{ + node_status_api::models::{AxumErrorResponse, AxumResult}, + v2::AxumAppState, +}; +use axum::{extract, Router}; +use nym_api_requests::models::CirculatingSupplyResponse; +use nym_validator_client::nyxd::Coin; + +pub(crate) fn circulating_supply_routes() -> Router { + Router::new() + .route("/", axum::routing::get(get_full_circulating_supply)) + .route( + "/total-supply-value", + axum::routing::get(get_circulating_supply), + ) + .route( + "/circulating-supply-value", + axum::routing::get(get_total_supply), + ) +} + +#[utoipa::path( + tag = "circulating-supply", + get, + path = "/v1/circulating-supply", + responses( + (status = 200, body = CirculatingSupplyResponse) + ) +)] +async fn get_full_circulating_supply( + extract::State(state): extract::State, +) -> AxumResult> { + match state + .circulating_supply_cache() + .get_circulating_supply() + .await + { + Some(value) => Ok(value.into()), + None => Err(AxumErrorResponse::internal_msg("unavailable")), + } +} + +#[utoipa::path( + tag = "circulating-supply", + get, + path = "/v1/circulating-supply/total-supply-value", + responses( + (status = 200, body = [f64]) + ) +)] +async fn get_total_supply( + extract::State(state): extract::State, +) -> AxumResult> { + let full_circulating_supply = match state + .circulating_supply_cache() + .get_circulating_supply() + .await + { + Some(res) => res, + None => return Err(AxumErrorResponse::internal_msg("unavailable")), + }; + + Ok(unym_coin_to_float_unym(full_circulating_supply.total_supply.into()).into()) +} + +#[utoipa::path( + tag = "circulating-supply", + get, + path = "/v1/circulating-supply/circulating-supply-value", + responses( + (status = 200, body = [f64]) + ) +)] +async fn get_circulating_supply( + extract::State(state): extract::State, +) -> AxumResult> { + let full_circulating_supply = match state + .circulating_supply_cache() + .get_circulating_supply() + .await + { + Some(res) => res, + None => return Err(AxumErrorResponse::internal_msg("unavailable")), + }; + + Ok(unym_coin_to_float_unym(full_circulating_supply.circulating_supply.into()).into()) +} + +// TODO: this is not the best place to put it, it should be more centralised, +// but for a quick fix, that's good enough for now... +// (for proper solution we should be managing `NymNetworkDetails` via rocket and grabbing display exponent +// value from the mix denom here. +const UNYM_RATIO: f64 = 1000000.; + +fn unym_coin_to_float_unym(coin: Coin) -> f64 { + // our total supply can't exceed 1B so an overflow here is impossible + // (if it happened, then we SHOULD crash) + coin.amount as f64 / UNYM_RATIO +} diff --git a/nym-api/src/circulating_supply_api/mod.rs b/nym-api/src/circulating_supply_api/mod.rs index 0449e9f09f..2bfefcc35f 100644 --- a/nym-api/src/circulating_supply_api/mod.rs +++ b/nym-api/src/circulating_supply_api/mod.rs @@ -11,6 +11,8 @@ use crate::support::{config, nyxd}; use self::cache::refresher::CirculatingSupplyCacheRefresher; pub(crate) mod cache; +#[cfg(feature = "axum")] +pub(crate) mod handlers; pub(crate) mod routes; /// Merges the routes with http information and returns it to Rocket for serving diff --git a/nym-api/src/circulating_supply_api/routes.rs b/nym-api/src/circulating_supply_api/routes.rs index 5bc76ab8bb..b8b00cb82e 100644 --- a/nym-api/src/circulating_supply_api/routes.rs +++ b/nym-api/src/circulating_supply_api/routes.rs @@ -2,7 +2,7 @@ // SPDX-License-Identifier: GPL-3.0-only use crate::circulating_supply_api::cache::CirculatingSupplyCache; -use crate::node_status_api::models::ErrorResponse; +use crate::node_status_api::models::RocketErrorResponse; use nym_api_requests::models::CirculatingSupplyResponse; use nym_validator_client::nyxd::Coin; use rocket::http::Status; @@ -26,10 +26,10 @@ fn unym_coin_to_float_unym(coin: Coin) -> f64 { #[get("/circulating-supply")] pub(crate) async fn get_full_circulating_supply( cache: &State, -) -> Result, ErrorResponse> { +) -> Result, RocketErrorResponse> { match cache.get_circulating_supply().await { Some(value) => Ok(Json(value)), - None => Err(ErrorResponse::new( + None => Err(RocketErrorResponse::new( "unavailable", Status::InternalServerError, )), @@ -40,11 +40,11 @@ pub(crate) async fn get_full_circulating_supply( #[get("/circulating-supply/total-supply-value")] pub(crate) async fn get_total_supply( cache: &State, -) -> Result, ErrorResponse> { +) -> Result, RocketErrorResponse> { let full_circulating_supply = match cache.get_circulating_supply().await { Some(res) => res, None => { - return Err(ErrorResponse::new( + return Err(RocketErrorResponse::new( "unavailable", Status::InternalServerError, )) @@ -60,11 +60,11 @@ pub(crate) async fn get_total_supply( #[get("/circulating-supply/circulating-supply-value")] pub(crate) async fn get_circulating_supply( cache: &State, -) -> Result, ErrorResponse> { +) -> Result, RocketErrorResponse> { let full_circulating_supply = match cache.get_circulating_supply().await { Some(res) => res, None => { - return Err(ErrorResponse::new( + return Err(RocketErrorResponse::new( "unavailable", Status::InternalServerError, )) diff --git a/nym-api/src/ecash/api_routes/aggregation_axum.rs b/nym-api/src/ecash/api_routes/aggregation_axum.rs new file mode 100644 index 0000000000..4a03313580 --- /dev/null +++ b/nym-api/src/ecash/api_routes/aggregation_axum.rs @@ -0,0 +1,143 @@ +// Copyright 2024 - Nym Technologies SA +// SPDX-License-Identifier: GPL-3.0-only + +use crate::ecash::api_routes::helpers::EpochIdParam; +use crate::ecash::error::EcashError; +use crate::ecash::state::EcashState; +use crate::node_status_api::models::AxumResult; +use crate::v2::AxumAppState; +use axum::extract::Path; +use axum::{Json, Router}; +use log::trace; +use nym_api_requests::ecash::models::{ + AggregatedCoinIndicesSignatureResponse, AggregatedExpirationDateSignatureResponse, +}; +use nym_api_requests::ecash::VerificationKeyResponse; +use nym_ecash_time::{cred_exp_date, EcashTime}; +use nym_validator_client::nym_api::rfc_3339_date; +use serde::Deserialize; +use std::sync::Arc; +use time::Date; +use utoipa::IntoParams; + +/// routes with globally aggregated keys, signatures, etc. +pub(crate) fn aggregation_routes(ecash_state: Arc) -> Router { + Router::new() + .route( + "/master-verification-key:epoch_id", + axum::routing::get({ + let ecash_state = Arc::clone(&ecash_state); + |epoch_id| master_verification_key(epoch_id, ecash_state) + }), + ) + .route( + "/aggregated-expiration-date-signatures:expiration_date", + axum::routing::get({ + let ecash_state = Arc::clone(&ecash_state); + |expiration_date| expiration_date_signatures(expiration_date, ecash_state) + }), + ) + .route( + "/aggregated-coin-indices-signatures:epoch_id", + axum::routing::get({ + let ecash_state = Arc::clone(&ecash_state); + |epoch_id| coin_indices_signatures(epoch_id, ecash_state) + }), + ) +} + +#[utoipa::path( + tag = "Ecash Global Data", + get, + params( + EpochIdParam + ), + path = "/v1/ecash/master-verification-key/{epoch_id}", + responses( + (status = 200, body = VerificationKeyResponse) + ) +)] +async fn master_verification_key( + Path(EpochIdParam { epoch_id }): Path, + state: Arc, +) -> AxumResult> { + trace!("aggregated_verification_key request"); + + // see if we're not in the middle of new dkg + state.ensure_dkg_not_in_progress().await?; + + let key = state.master_verification_key(epoch_id).await?; + + Ok(Json(VerificationKeyResponse::new(key.clone()))) +} + +#[derive(Deserialize, IntoParams)] +#[into_params(parameter_in = Path)] +struct ExpirationDateParam { + expiration_date: Option, +} + +#[utoipa::path( + tag = "Ecash Global Data", + get, + params( + ExpirationDateParam + ), + path = "/v1/ecash/aggregated-expiration-date-signatures/{epoch_id}", + responses( + (status = 200, body = AggregatedExpirationDateSignatureResponse) + ) +)] +async fn expiration_date_signatures( + Path(ExpirationDateParam { expiration_date }): Path, + state: Arc, +) -> AxumResult> { + trace!("aggregated_expiration_date_signatures request"); + + let expiration_date = match expiration_date { + None => cred_exp_date().ecash_date(), + Some(raw) => Date::parse(&raw, &rfc_3339_date()) + .map_err(|_| EcashError::MalformedExpirationDate { raw })?, + }; + + // see if we're not in the middle of new dkg + state.ensure_dkg_not_in_progress().await?; + + let expiration_date_signatures = state + .master_expiration_date_signatures(expiration_date) + .await?; + + Ok(Json(AggregatedExpirationDateSignatureResponse { + epoch_id: expiration_date_signatures.epoch_id, + expiration_date, + signatures: expiration_date_signatures.signatures.clone(), + })) +} + +#[utoipa::path( + tag = "Ecash Global Data", + get, + params( + EpochIdParam + ), + path = "/v1/ecash/aggregated-coin-indices-signatures/{epoch_id}", + responses( + (status = 200, body = AggregatedCoinIndicesSignatureResponse) + ) +)] +async fn coin_indices_signatures( + Path(EpochIdParam { epoch_id }): Path, + state: Arc, +) -> AxumResult> { + trace!("aggregated_coin_indices_signatures request"); + + // see if we're not in the middle of new dkg + state.ensure_dkg_not_in_progress().await?; + + let coin_indices_signatures = state.master_coin_index_signatures(epoch_id).await?; + + Ok(Json(AggregatedCoinIndicesSignatureResponse { + epoch_id: coin_indices_signatures.epoch_id, + signatures: coin_indices_signatures.signatures.clone(), + })) +} diff --git a/nym-api/src/ecash/api_routes/handlers.rs b/nym-api/src/ecash/api_routes/handlers.rs new file mode 100644 index 0000000000..b40ccf9773 --- /dev/null +++ b/nym-api/src/ecash/api_routes/handlers.rs @@ -0,0 +1,19 @@ +// Copyright 2023-2024 - Nym Technologies SA +// SPDX-License-Identifier: GPL-3.0-only + +use crate::ecash::api_routes::aggregation_axum::aggregation_routes; +use crate::ecash::api_routes::issued_axum::issued_routes; +use crate::ecash::api_routes::partial_signing_axum::partial_signing_routes; +use crate::ecash::api_routes::spending_axum::spending_routes; +use crate::ecash::state::EcashState; +use crate::v2::AxumAppState; +use axum::Router; +use std::sync::Arc; + +pub(crate) fn ecash_routes(ecash_state: Arc) -> Router { + Router::new() + .merge(aggregation_routes(Arc::clone(&ecash_state))) + .merge(issued_routes(Arc::clone(&ecash_state))) + .merge(partial_signing_routes(Arc::clone(&ecash_state))) + .merge(spending_routes(Arc::clone(&ecash_state))) +} diff --git a/nym-api/src/ecash/api_routes/helpers.rs b/nym-api/src/ecash/api_routes/helpers.rs index 521f11067a..4469bf11d0 100644 --- a/nym-api/src/ecash/api_routes/helpers.rs +++ b/nym-api/src/ecash/api_routes/helpers.rs @@ -26,3 +26,10 @@ pub(crate) fn build_credentials_response( Ok(IssuedCredentialsResponse { credentials }) } + +#[cfg(feature = "axum")] +#[derive(serde::Deserialize, utoipa::IntoParams)] +#[into_params(parameter_in = Path)] +pub(super) struct EpochIdParam { + pub(super) epoch_id: Option, +} diff --git a/nym-api/src/ecash/api_routes/issued_axum.rs b/nym-api/src/ecash/api_routes/issued_axum.rs new file mode 100644 index 0000000000..72fa55e39f --- /dev/null +++ b/nym-api/src/ecash/api_routes/issued_axum.rs @@ -0,0 +1,147 @@ +// Copyright 2024 - Nym Technologies SA +// SPDX-License-Identifier: GPL-3.0-only + +use crate::ecash::api_routes::helpers::build_credentials_response; +use crate::ecash::error::EcashError; +use crate::ecash::state::EcashState; +use crate::ecash::storage::EcashStorageExt; +use crate::node_status_api::models::AxumResult; +use crate::v2::AxumAppState; +use axum::extract::Path; +use axum::{Json, Router}; +use nym_api_requests::ecash::models::{ + EpochCredentialsResponse, IssuedCredentialResponse, IssuedCredentialsResponse, +}; +use nym_api_requests::ecash::CredentialsRequestBody; +use serde::Deserialize; +use std::sync::Arc; +use utoipa::IntoParams; + +pub(crate) fn issued_routes(ecash_state: Arc) -> Router { + Router::new() + .route( + "/epoch-credentials/:epoch", + axum::routing::get({ + let ecash_state = Arc::clone(&ecash_state); + |epoch| epoch_credentials(epoch, ecash_state) + }), + ) + .route( + "/issued-credential/:id", + axum::routing::get({ + let ecash_state = Arc::clone(&ecash_state); + |id| issued_credential(id, ecash_state) + }), + ) + .route( + "/issued-credentials", + axum::routing::post({ + let ecash_state = Arc::clone(&ecash_state); + |body| issued_credentials(body, ecash_state) + }), + ) +} + +#[derive(Deserialize, IntoParams)] +#[into_params(parameter_in = Path)] +struct EpochParam { + epoch: u64, +} + +#[utoipa::path( + tag = "Ecash", + get, + params( + EpochParam + ), + path = "/v1/ecash/epoch-credentials/{epoch}", + responses( + (status = 200, body = EpochCredentialsResponse) + ) +)] +async fn epoch_credentials( + Path(EpochParam { epoch }): Path, + state: Arc, +) -> AxumResult> { + let issued = state.aux.storage.get_epoch_credentials(epoch).await?; + + let response = if let Some(issued) = issued { + issued.into() + } else { + EpochCredentialsResponse { + epoch_id: epoch, + first_epoch_credential_id: None, + total_issued: 0, + } + }; + + Ok(Json(response)) +} + +#[derive(Deserialize, IntoParams)] +#[into_params(parameter_in = Path)] +struct IdParam { + id: i64, +} + +#[utoipa::path( + tag = "Ecash", + get, + params( + IdParam + ), + path = "/v1/ecash/issued-credential/{id}", + responses( + (status = 200, body = IssuedCredentialResponse) + ) +)] +async fn issued_credential( + Path(IdParam { id }): Path, + state: Arc, +) -> AxumResult> { + let issued = state.aux.storage.get_issued_credential(id).await?; + + let credential = if let Some(issued) = issued { + Some(issued.try_into()?) + } else { + None + }; + + Ok(Json(IssuedCredentialResponse { credential })) +} + +#[utoipa::path( + tag = "Ecash", + post, + request_body = CredentialsRequestBody, + path = "/v1/ecash/issued-credentials", + responses( + (status = 200, body = IssuedCredentialsResponse) + ) +)] +async fn issued_credentials( + Json(params): Json, + state: Arc, +) -> AxumResult> { + if params.pagination.is_some() && !params.credential_ids.is_empty() { + return Err(EcashError::InvalidQueryArguments.into()); + } + + let credentials = if let Some(pagination) = params.pagination { + state + .aux + .storage + .get_issued_credentials_paged(pagination) + .await? + } else { + state + .aux + .storage + .get_issued_credentials(params.credential_ids) + .await? + }; + + build_credentials_response(credentials) + .map(Json) + .map_err(From::from) +} diff --git a/nym-api/src/ecash/api_routes/mod.rs b/nym-api/src/ecash/api_routes/mod.rs index 6037a8d18f..910e253288 100644 --- a/nym-api/src/ecash/api_routes/mod.rs +++ b/nym-api/src/ecash/api_routes/mod.rs @@ -6,3 +6,13 @@ mod helpers; pub(crate) mod issued; pub(crate) mod partial_signing; pub(crate) mod spending; + +cfg_if::cfg_if! { + if #[cfg(feature = "axum")] { + pub(crate) mod aggregation_axum; + pub(crate) mod handlers; + pub(crate) mod issued_axum; + pub(crate) mod partial_signing_axum; + pub(crate) mod spending_axum; + } +} diff --git a/nym-api/src/ecash/api_routes/partial_signing_axum.rs b/nym-api/src/ecash/api_routes/partial_signing_axum.rs new file mode 100644 index 0000000000..fe93ddc921 --- /dev/null +++ b/nym-api/src/ecash/api_routes/partial_signing_axum.rs @@ -0,0 +1,178 @@ +// Copyright 2024 - Nym Technologies SA +// SPDX-License-Identifier: GPL-3.0-only + +use crate::ecash::api_routes::helpers::EpochIdParam; +use crate::ecash::error::EcashError; +use crate::ecash::helpers::blind_sign; +use crate::ecash::state::EcashState; +use crate::node_status_api::models::AxumResult; +use crate::v2::AxumAppState; +use axum::extract::Path; +use axum::{Json, Router}; +use nym_api_requests::ecash::{ + BlindSignRequestBody, BlindedSignatureResponse, PartialCoinIndicesSignatureResponse, + PartialExpirationDateSignatureResponse, +}; +use nym_ecash_time::{cred_exp_date, EcashTime}; +use nym_validator_client::nym_api::rfc_3339_date; +use serde::Deserialize; +use std::ops::Deref; +use std::sync::Arc; +use time::Date; +use utoipa::IntoParams; + +pub(crate) fn partial_signing_routes(ecash_state: Arc) -> Router { + Router::new() + .route( + "/blind-sign", + axum::routing::post({ + let ecash_state = Arc::clone(&ecash_state); + |body| post_blind_sign(body, ecash_state) + }), + ) + .route( + "/partial-expiration-date-signatures:expiration_date", + axum::routing::get({ + let ecash_state = Arc::clone(&ecash_state); + |expiration_date| partial_expiration_date_signatures(expiration_date, ecash_state) + }), + ) + .route( + "/partial-coin-indices-signatures:epoch_id", + axum::routing::get({ + let ecash_state = Arc::clone(&ecash_state); + |epoch_id| partial_coin_indices_signatures(epoch_id, ecash_state) + }), + ) +} + +#[utoipa::path( + tag = "Ecash", + post, + request_body = BlindSignRequestBody, + path = "/v1/ecash/blind-sign", + responses( + (status = 200, body = BlindedSignatureResponse) + ) +)] +async fn post_blind_sign( + Json(blind_sign_request_body): Json, + state: Arc, +) -> AxumResult> { + debug!("Received blind sign request"); + trace!("body: {:?}", blind_sign_request_body); + + // check if we have the signing key available + debug!("checking if we actually have ecash keys derived..."); + let signing_key = state.ecash_signing_key().await?; + + // basic check of expiration date validity + if blind_sign_request_body.expiration_date > cred_exp_date().ecash_date() { + return Err(EcashError::ExpirationDateTooLate.into()); + } + + // see if we're not in the middle of new dkg + state.ensure_dkg_not_in_progress().await?; + + // check if we already issued a credential for this deposit + let deposit_id = blind_sign_request_body.deposit_id; + debug!( + "checking if we have already issued credential for this deposit (deposit_id: {deposit_id})", + ); + if let Some(blinded_signature) = state.already_issued(deposit_id).await? { + return Ok(Json(BlindedSignatureResponse { blinded_signature })); + } + + //check if account was blacklisted + let pub_key_bs58 = blind_sign_request_body.ecash_pubkey.to_base58_string(); + state.aux.ensure_not_blacklisted(&pub_key_bs58).await?; + + // get the deposit details of the claimed id + debug!("getting deposit details from the chain"); + let deposit = state.get_deposit(deposit_id).await?; + + // check validity of the request + debug!("fully validating received request"); + state + .validate_request(&blind_sign_request_body, deposit) + .await?; + + // produce the partial signature + debug!("producing the partial credential"); + let blinded_signature = blind_sign(&blind_sign_request_body, signing_key.deref())?; + + // store the information locally + debug!("storing the issued credential in the database"); + state + .store_issued_credential(blind_sign_request_body, &blinded_signature) + .await?; + + // finally return the credential to the client + Ok(Json(BlindedSignatureResponse { blinded_signature })) +} + +#[derive(Deserialize, IntoParams)] +struct ExpirationDateParam { + expiration_date: Option, +} + +#[utoipa::path( + tag = "Ecash", + get, + params( + ExpirationDateParam + ), + path = "/v1/ecash/partial-expiration-date-signatures/{expiration_date}", + responses( + (status = 200, body = PartialExpirationDateSignatureResponse) + ) +)] +async fn partial_expiration_date_signatures( + Path(ExpirationDateParam { expiration_date }): Path, + state: Arc, +) -> AxumResult> { + let expiration_date = match expiration_date { + None => cred_exp_date().ecash_date(), + Some(raw) => Date::parse(&raw, &rfc_3339_date()) + .map_err(|_| EcashError::MalformedExpirationDate { raw })?, + }; + + // see if we're not in the middle of new dkg + state.ensure_dkg_not_in_progress().await?; + + let expiration_date_signatures = state + .partial_expiration_date_signatures(expiration_date) + .await?; + + Ok(Json(PartialExpirationDateSignatureResponse { + epoch_id: expiration_date_signatures.epoch_id, + expiration_date, + signatures: expiration_date_signatures.signatures.clone(), + })) +} + +#[utoipa::path( + tag = "Ecash", + get, + params( + EpochIdParam + ), + path = "/v1/ecash/partial-coin-indices-signatures/{epoch_id}", + responses( + (status = 200, body = PartialExpirationDateSignatureResponse) + ) +)] +async fn partial_coin_indices_signatures( + Path(EpochIdParam { epoch_id }): Path, + state: Arc, +) -> AxumResult> { + // see if we're not in the middle of new dkg + state.ensure_dkg_not_in_progress().await?; + + let coin_indices_signatures = state.partial_coin_index_signatures(epoch_id).await?; + + Ok(Json(PartialCoinIndicesSignatureResponse { + epoch_id: coin_indices_signatures.epoch_id, + signatures: coin_indices_signatures.signatures.clone(), + })) +} diff --git a/nym-api/src/ecash/api_routes/spending_axum.rs b/nym-api/src/ecash/api_routes/spending_axum.rs new file mode 100644 index 0000000000..aca64b7f0c --- /dev/null +++ b/nym-api/src/ecash/api_routes/spending_axum.rs @@ -0,0 +1,245 @@ +// Copyright 2024 - Nym Technologies SA +// SPDX-License-Identifier: GPL-3.0-only + +use crate::ecash::error::EcashError; +use crate::ecash::state::EcashState; +use crate::node_status_api::models::AxumResult; +use crate::v2::AxumAppState; +use axum::{Json, Router}; +use nym_api_requests::constants::MIN_BATCH_REDEMPTION_DELAY; +use nym_api_requests::ecash::models::{ + BatchRedeemTicketsBody, EcashBatchTicketRedemptionResponse, EcashTicketVerificationRejection, + EcashTicketVerificationResponse, SpentCredentialsResponse, VerifyEcashTicketBody, +}; +use nym_compact_ecash::identify::IdentifyResult; +use nym_ecash_time::EcashTime; +use std::collections::HashSet; +use std::ops::Deref; +use std::sync::Arc; +use time::macros::time; +use time::{OffsetDateTime, Time}; + +pub(crate) fn spending_routes(ecash_state: Arc) -> Router { + Router::new() + .route( + "/verify-ecash-ticket", + axum::routing::post({ + let ecash_state = Arc::clone(&ecash_state); + |body| verify_ticket(body, ecash_state) + }), + ) + .route( + "/batch-redeem-ecash-tickets", + axum::routing::post({ + let ecash_state = Arc::clone(&ecash_state); + |body| batch_redeem_tickets(body, ecash_state) + }), + ) + .route( + "/double-spending-filter-v1", + axum::routing::get({ + let ecash_state = Arc::clone(&ecash_state); + || double_spending_filter_v1(ecash_state) + }), + ) +} + +const ONE_AM: Time = time!(1:00); + +fn reject_ticket( + reason: EcashTicketVerificationRejection, +) -> AxumResult> { + Ok(Json(EcashTicketVerificationResponse::reject(reason))) +} + +// TODO: optimise it; for now it's just dummy split of the original `verify_offline_credential` +// introduce bloomfilter checks without touching storage first, etc. +#[utoipa::path( + tag = "Ecash", + post, + request_body = VerifyEcashTicketBody, + path = "/v1/ecash/verify-ecash-ticket", + responses( + (status = 200, body = EcashTicketVerificationResponse) + ) +)] +async fn verify_ticket( + // TODO in the future: make it send binary data rather than json + Json(verify_ticket_body): Json, + state: Arc, +) -> AxumResult> { + let credential_data = &verify_ticket_body.credential; + let gateway_cosmos_addr = &verify_ticket_body.gateway_cosmos_addr; + + // easy check: is there only a single payment attached? + if credential_data.payment.spend_value != 1 { + return reject_ticket(EcashTicketVerificationRejection::MultipleTickets); + } + + let sn = &credential_data.encoded_serial_number(); + let spend_date = credential_data.spend_date; + let epoch_id = credential_data.epoch_id; + + let now = OffsetDateTime::now_utc(); + let today_ecash = now.ecash_date(); + + #[allow(clippy::unwrap_used)] + let yesterday_ecash = today_ecash.previous_day().unwrap(); + + // only accept yesterday date if we're near the day transition, i.e. before 1AM UTC + if spend_date != today_ecash && now.time() > ONE_AM && spend_date != yesterday_ecash { + return reject_ticket(EcashTicketVerificationRejection::InvalidSpentDate { + today: today_ecash, + yesterday: yesterday_ecash, + received: spend_date, + }); + } + + // check the bloomfilter for obvious double-spending so that we wouldn't need to waste time on crypto verification + // TODO: when blacklisting is implemented, this should get removed + if state.check_bloomfilter(sn).await { + return reject_ticket(EcashTicketVerificationRejection::ReplayedTicket); + } + + // actual double spend detection with storage + if let Some(previous_payment) = state.get_ticket_data_by_serial_number(sn).await? { + match nym_compact_ecash::identify::identify( + &credential_data.payment, + &previous_payment.payment, + credential_data.pay_info, + previous_payment.pay_info, + ) { + IdentifyResult::NotADuplicatePayment => {} //SW NOTE This should never happen, quick message? + IdentifyResult::DuplicatePayInfo(_) => { + log::warn!("Identical payInfo"); + return reject_ticket(EcashTicketVerificationRejection::ReplayedTicket); + } + IdentifyResult::DoubleSpendingPublicKeys(pub_key) => { + //Actual double spending + log::warn!( + "Double spending attempt for key {}", + pub_key.to_base58_string() + ); + log::error!("UNIMPLEMENTED: blacklisting the double spend key"); + return reject_ticket(EcashTicketVerificationRejection::DoubleSpend); + } + } + } + + let verification_key = state.master_verification_key(Some(epoch_id)).await?; + + // perform actual crypto verification + if credential_data.verify(&verification_key).is_err() { + return reject_ticket(EcashTicketVerificationRejection::InvalidTicket); + } + + // finally get EXCLUSIVE lock on the bloomfilter, check if for the final time and insert the SN + let was_present = state + .update_bloomfilter(sn, spend_date, today_ecash) + .await?; + if was_present { + return reject_ticket(EcashTicketVerificationRejection::ReplayedTicket); + } + + //store credential + state + .store_verified_ticket(credential_data, gateway_cosmos_addr) + .await?; + + Ok(Json(EcashTicketVerificationResponse { verified: Ok(()) })) +} + +// // for particular SN returns what gateway has submitted it and whether it has been verified correctly +// async fn credential_status() -> ! { +// todo!() +// } + +#[utoipa::path( + tag = "Ecash", + post, + request_body = BatchRedeemTicketsBody, + path = "/v1/ecash/batch-redeem-ecash-tickets", + responses( + (status = 200, body = EcashBatchTicketRedemptionResponse) + ) +)] +async fn batch_redeem_tickets( + // TODO in the future: make it send binary data rather than json + Json(batch_redeem_credentials_body): Json, + state: Arc, +) -> AxumResult> { + // 1. see if that gateway has even submitted any tickets + let Some(provider_info) = state + .get_ticket_provider(batch_redeem_credentials_body.gateway_cosmos_addr.as_ref()) + .await? + else { + return Err(EcashError::NotTicketsProvided.into()); + }; + + // 2. check if the gateway is not trying to spam the redemption requests + // (we have to protect our poor chain) + if let Some(last_redemption) = provider_info.last_batch_verification { + let now = OffsetDateTime::now_utc(); + let next_allowed = last_redemption + MIN_BATCH_REDEMPTION_DELAY; + + if next_allowed > now { + return Err(EcashError::TooFrequentRedemption { + last_redemption, + next_allowed, + } + .into()); + } + } + + // 3. verify the request digest + if !batch_redeem_credentials_body.verify_digest() { + return Err(EcashError::MismatchedRequestDigest.into()); + } + + // 4. verify the associated on-chain proposal (whether it's made by correct sender, has valid messages, etc.) + state + .validate_redemption_proposal(&batch_redeem_credentials_body) + .await?; + + let proposal_id = batch_redeem_credentials_body.proposal_id; + let received = batch_redeem_credentials_body.included_serial_numbers; + + // 5. check if **every** serial number included in the request has been verified by us + // if we have more than requested, tough luck, they're going to lose them + let verified = state.get_redeemable_tickets(provider_info).await?; + let verified_tickets: HashSet<_> = verified.iter().map(|sn| sn.deref()).collect(); + + for sn in &received { + if !verified_tickets.contains(sn.deref()) { + return Err(EcashError::TicketNotVerified { + serial_number_bs58: bs58::encode(sn).into_string(), + } + .into()); + } + } + + // TODO: offload it to separate task with work queue and batching (of tx messages) to vote for multiple proposals in the same tx + state.accept_proposal(proposal_id).await?; + Ok(Json(EcashBatchTicketRedemptionResponse { + proposal_accepted: true, + })) +} + +// explicitly mark it as v1 in the URL because the response type WILL change; +// it will probably be compressed bincode or something +#[utoipa::path( + tag = "Ecash", + get, + path = "/v1/ecash/double-spending-filter-v1", + responses( + (status = 200, body = SpentCredentialsResponse) + ) +)] +async fn double_spending_filter_v1( + state: Arc, +) -> AxumResult> { + let spent_credentials_export = state.get_bloomfilter_bytes().await; + Ok(Json(SpentCredentialsResponse::new( + spent_credentials_export, + ))) +} diff --git a/nym-api/src/epoch_operations/mod.rs b/nym-api/src/epoch_operations/mod.rs index d8e4365eee..952bb5ca1f 100644 --- a/nym-api/src/epoch_operations/mod.rs +++ b/nym-api/src/epoch_operations/mod.rs @@ -268,14 +268,11 @@ impl RewardedSetUpdater { pub(crate) fn start( nyxd_client: Client, nym_contract_cache: &NymContractCache, - storage: &NymApiStorage, + storage: NymApiStorage, shutdown: &TaskManager, ) { - let mut rewarded_set_updater = RewardedSetUpdater::new( - nyxd_client, - nym_contract_cache.to_owned(), - storage.to_owned(), - ); + let mut rewarded_set_updater = + RewardedSetUpdater::new(nyxd_client, nym_contract_cache.to_owned(), storage); let shutdown_listener = shutdown.subscribe(); tokio::spawn(async move { rewarded_set_updater.run(shutdown_listener).await }); } diff --git a/nym-api/src/main.rs b/nym-api/src/main.rs index 0bebd493ed..3121ce18f2 100644 --- a/nym-api/src/main.rs +++ b/nym-api/src/main.rs @@ -1,6 +1,9 @@ // Copyright 2020-2023 - Nym Technologies SA // SPDX-License-Identifier: GPL-3.0-only +// TODO rocket remove +#![allow(deprecated)] + #[macro_use] extern crate rocket; @@ -41,11 +44,15 @@ pub(crate) mod nym_nodes; mod status; pub(crate) mod support; +#[cfg(feature = "axum")] +mod v2; + struct ShutdownHandles { task_manager_handle: TaskManager, rocket_handle: rocket::Shutdown, } +// TODO rocket: remove all such Todos once rocket is phased out completely #[tokio::main] async fn main() -> Result<(), anyhow::Error> { cfg_if::cfg_if! {if #[cfg(feature = "console-subscriber")] { @@ -54,6 +61,7 @@ async fn main() -> Result<(), anyhow::Error> { }} setup_logging(); + // TODO rocket: replace with tracing logger once rocket is eliminated from code info!("Starting nym api..."); @@ -107,7 +115,11 @@ async fn start_nym_api_tasks(config: Config) -> anyhow::Result let nym_contract_cache_state = rocket.state::().unwrap(); let node_status_cache_state = rocket.state::().unwrap(); let circulating_supply_cache_state = rocket.state::().unwrap(); - let maybe_storage = rocket.state::(); + let storage = if let Some(storage) = rocket.state::() { + storage.to_owned() + } else { + storage::NymApiStorage::init(&config.node_status_api.storage_paths.database_path).await? + }; let described_nodes_state = rocket.state::>().unwrap(); // start note describe cache refresher @@ -134,7 +146,7 @@ async fn start_nym_api_tasks(config: Config) -> anyhow::Result &config.node_status_api, nym_contract_cache_state, node_status_cache_state, - maybe_storage, + storage.to_owned(), nym_contract_cache_listener, &shutdown, ); @@ -163,19 +175,16 @@ async fn start_nym_api_tasks(config: Config) -> anyhow::Result // and then only start the uptime updater (and the monitor itself, duh) // if the monitoring if it's enabled if config.network_monitor.enabled { - // if network monitor is enabled, the storage MUST BE available - let storage = maybe_storage.unwrap(); - network_monitor::start::( &config.network_monitor, nym_contract_cache_state, - storage, + &storage, nyxd_client.clone(), &shutdown, ) .await; - HistoricalUptimeUpdater::start(storage, &shutdown); + HistoricalUptimeUpdater::start(storage.to_owned(), &shutdown); // start 'rewarding' if its enabled if config.rewarding.enabled { @@ -183,7 +192,6 @@ async fn start_nym_api_tasks(config: Config) -> anyhow::Result RewardedSetUpdater::start(nyxd_client, nym_contract_cache_state, storage, &shutdown); } } - // Launch the rocket, serve http endpoints and finish the startup tokio::spawn(rocket.launch()); diff --git a/nym-api/src/network/handlers.rs b/nym-api/src/network/handlers.rs new file mode 100644 index 0000000000..0cb27ca92d --- /dev/null +++ b/nym-api/src/network/handlers.rs @@ -0,0 +1,100 @@ +// Copyright 2023 - Nym Technologies SA +// SPDX-License-Identifier: GPL-3.0-only + +use crate::network::models::{ContractInformation, NetworkDetails}; +use crate::v2::AxumAppState; +use axum::{extract, Router}; +use nym_contracts_common::ContractBuildInformation; +use std::collections::HashMap; +use utoipa::ToSchema; + +pub(crate) fn nym_network_routes() -> Router { + Router::new() + .route("/details", axum::routing::get(network_details)) + .route("/nym-contracts", axum::routing::get(nym_contracts)) + .route( + "/nym-contracts-detailed", + axum::routing::get(nym_contracts_detailed), + ) +} + +#[utoipa::path( + tag = "network", + get, + path = "/v1/network/details", + responses( + (status = 200, body = NetworkDetails) + ) +)] +async fn network_details( + extract::State(state): extract::State, +) -> axum::Json { + state.network_details().to_owned().into() +} + +// it's used for schema generation so dead_code is fine +#[allow(dead_code)] +#[derive(ToSchema)] +#[schema(title = "ContractVersion")] +pub(crate) struct ContractVersionSchemaResponse { + /// contract is the crate name of the implementing contract, eg. `crate:cw20-base` + /// we will use other prefixes for other languages, and their standard global namespacing + pub contract: String, + /// version is any string that this implementation knows. It may be simple counter "1", "2". + /// or semantic version on release tags "v0.7.0", or some custom feature flag list. + /// the only code that needs to understand the version parsing is code that knows how to + /// migrate from the given contract (and is tied to it's implementation somehow) + pub version: String, +} + +#[utoipa::path( + tag = "network", + get, + path = "/v1/network/nym-contracts", + responses( + (status = 200, body = HashMap>) + ) +)] +async fn nym_contracts( + extract::State(state): extract::State, +) -> axum::Json>> { + let info = state.nym_contract_cache().contract_details().await; + info.iter() + .map(|(contract, info)| { + ( + contract.to_owned(), + ContractInformation { + address: info.address.as_ref().map(|a| a.to_string()), + details: info.base.clone(), + }, + ) + }) + .collect::>() + .into() +} + +#[utoipa::path( + tag = "network", + get, + path = "/v1/network/nym-contracts-detailed", + responses( + (status = 200, body = HashMap>) + ) +)] +async fn nym_contracts_detailed( + extract::State(state): extract::State, +) -> axum::Json>> { + let info = state.nym_contract_cache().contract_details().await; + info.iter() + .map(|(contract, info)| { + ( + contract.to_owned(), + ContractInformation { + address: info.address.as_ref().map(|a| a.to_string()), + details: info.detailed.clone(), + }, + ) + }) + .collect::>() + .into() +} diff --git a/nym-api/src/network/mod.rs b/nym-api/src/network/mod.rs index ed60de4a39..1f91dea3fd 100644 --- a/nym-api/src/network/mod.rs +++ b/nym-api/src/network/mod.rs @@ -6,6 +6,8 @@ use rocket::Route; use rocket_okapi::openapi_get_routes_spec; use rocket_okapi::settings::OpenApiSettings; +#[cfg(feature = "axum")] +pub(crate) mod handlers; pub(crate) mod models; mod routes; diff --git a/nym-api/src/network/models.rs b/nym-api/src/network/models.rs index 5a86ea6401..7cdaa1d052 100644 --- a/nym-api/src/network/models.rs +++ b/nym-api/src/network/models.rs @@ -6,6 +6,7 @@ use schemars::JsonSchema; use serde::{Deserialize, Serialize}; #[derive(Clone, Serialize, Deserialize, JsonSchema)] +#[cfg_attr(feature = "axum", derive(utoipa::ToSchema))] pub struct NetworkDetails { pub(crate) connected_nyxd: String, pub(crate) network: NymNetworkDetails, @@ -20,6 +21,7 @@ impl NetworkDetails { } } +#[cfg_attr(feature = "axum", derive(utoipa::ToSchema))] #[derive(Serialize, Deserialize, Clone, JsonSchema)] #[serde(rename_all = "snake_case")] pub struct ContractInformation { diff --git a/nym-api/src/node_status_api/cache/mod.rs b/nym-api/src/node_status_api/cache/mod.rs index 022a56f156..99d4358802 100644 --- a/nym-api/src/node_status_api/cache/mod.rs +++ b/nym-api/src/node_status_api/cache/mod.rs @@ -41,12 +41,13 @@ pub struct NodeStatusCache { impl NodeStatusCache { /// Creates a new cache with no data. - fn new() -> NodeStatusCache { + pub(crate) fn new() -> NodeStatusCache { NodeStatusCache { inner: Arc::new(RwLock::new(NodeStatusCacheData::new())), } } + #[deprecated(note = "TODO rocket: obsolete because it's used for Rocket")] pub fn stage() -> AdHoc { AdHoc::on_ignite("Node Status Cache", |rocket| async { rocket.manage(Self::new()) diff --git a/nym-api/src/node_status_api/cache/node_sets.rs b/nym-api/src/node_status_api/cache/node_sets.rs index 05dfc8f777..d20f3329b4 100644 --- a/nym-api/src/node_status_api/cache/node_sets.rs +++ b/nym-api/src/node_status_api/cache/node_sets.rs @@ -52,12 +52,11 @@ pub(super) fn split_into_active_and_rewarded_set( } pub(super) async fn get_mixnode_performance_from_storage( - storage: &Option, + storage: &NymApiStorage, mix_id: MixId, epoch: Interval, ) -> Option { storage - .as_ref()? .get_average_mixnode_uptime_in_the_last_24hrs( mix_id, epoch.current_epoch_end_unix_timestamp(), @@ -68,12 +67,11 @@ pub(super) async fn get_mixnode_performance_from_storage( } pub(super) async fn get_gateway_performance_from_storage( - storage: &Option, + storage: &NymApiStorage, gateway_id: &str, epoch: Interval, ) -> Option { storage - .as_ref()? .get_average_gateway_uptime_in_the_last_24hrs( gateway_id, epoch.current_epoch_end_unix_timestamp(), @@ -84,7 +82,7 @@ pub(super) async fn get_gateway_performance_from_storage( } pub(super) async fn annotate_nodes_with_details( - storage: &Option, + storage: &NymApiStorage, mixnodes: Vec, interval_reward_params: RewardingParams, current_interval: Interval, @@ -123,16 +121,12 @@ pub(super) async fn annotate_nodes_with_details( current_interval, ); - let node_performance = if let Some(storage) = storage { - storage - .construct_mixnode_report(mixnode.mix_id()) - .await - .map(NodePerformance::from) - .ok() - } else { - None - } - .unwrap_or_default(); + let node_performance = storage + .construct_mixnode_report(mixnode.mix_id()) + .await + .map(NodePerformance::from) + .ok() + .unwrap_or_default(); // safety: this conversion is infallible let ip_addresses = @@ -177,7 +171,7 @@ pub(super) async fn annotate_nodes_with_details( } pub(crate) async fn annotate_gateways_with_details( - storage: &Option, + storage: &NymApiStorage, gateway_bonds: Vec, current_interval: Interval, blacklist: &HashSet, @@ -192,16 +186,12 @@ pub(crate) async fn annotate_gateways_with_details( .await .unwrap_or_default(); - let node_performance = if let Some(storage) = storage { - storage - .construct_gateway_report(gateway_bond.identity()) - .await - .map(NodePerformance::from) - .ok() - } else { - None - } - .unwrap_or_default(); + let node_performance = storage + .construct_gateway_report(gateway_bond.identity()) + .await + .map(NodePerformance::from) + .ok() + .unwrap_or_default(); // safety: this conversion is infallible let ip_addresses = match NetworkAddress::from_str(&gateway_bond.gateway.host).unwrap() { diff --git a/nym-api/src/node_status_api/cache/refresher.rs b/nym-api/src/node_status_api/cache/refresher.rs index e1dd3896f0..ad07919e62 100644 --- a/nym-api/src/node_status_api/cache/refresher.rs +++ b/nym-api/src/node_status_api/cache/refresher.rs @@ -29,7 +29,7 @@ pub struct NodeStatusCacheRefresher { // Sources for when refreshing data contract_cache: NymContractCache, contract_cache_listener: watch::Receiver, - storage: Option, + storage: NymApiStorage, } impl NodeStatusCacheRefresher { @@ -38,7 +38,7 @@ impl NodeStatusCacheRefresher { fallback_caching_interval: Duration, contract_cache: NymContractCache, contract_cache_listener: watch::Receiver, - storage: Option, + storage: NymApiStorage, ) -> Self { Self { cache, diff --git a/nym-api/src/node_status_api/handlers/mod.rs b/nym-api/src/node_status_api/handlers/mod.rs new file mode 100644 index 0000000000..2a385b2812 --- /dev/null +++ b/nym-api/src/node_status_api/handlers/mod.rs @@ -0,0 +1,32 @@ +// Copyright 2021-2024 - Nym Technologies SA +// SPDX-License-Identifier: GPL-3.0-only + +use crate::v2::AxumAppState; +use axum::Router; +use nym_mixnet_contract_common::MixId; +use serde::Deserialize; +use utoipa::IntoParams; + +pub(crate) mod network_monitor; +pub(crate) mod unstable; +pub(crate) mod without_monitor; + +pub(crate) fn node_status_routes(network_monitor: bool) -> Router { + // in the minimal variant we would not have access to endpoints relying on existence + // of the network monitor and the associated storage + let without_network_monitor = without_monitor::mandatory_routes(); + + if network_monitor { + let with_network_monitor = network_monitor::network_monitor_routes(); + + with_network_monitor.merge(without_network_monitor) + } else { + without_network_monitor + } +} + +#[derive(Deserialize, IntoParams)] +#[into_params(parameter_in = Path)] +struct MixIdParam { + mix_id: MixId, +} diff --git a/nym-api/src/node_status_api/handlers/network_monitor.rs b/nym-api/src/node_status_api/handlers/network_monitor.rs new file mode 100644 index 0000000000..ea38422c17 --- /dev/null +++ b/nym-api/src/node_status_api/handlers/network_monitor.rs @@ -0,0 +1,339 @@ +// Copyright 2021-2024 - Nym Technologies SA +// SPDX-License-Identifier: GPL-3.0-only + +use crate::node_status_api::handlers::MixIdParam; +use crate::node_status_api::helpers::{ + _compute_mixnode_reward_estimation, _gateway_core_status_count, _gateway_report, + _gateway_uptime_history, _get_gateway_avg_uptime, _get_gateways_detailed, + _get_gateways_detailed_unfiltered, _get_mixnode_avg_uptime, _get_mixnode_reward_estimation, + _get_mixnodes_detailed_unfiltered, _mixnode_core_status_count, _mixnode_report, + _mixnode_uptime_history, +}; +use crate::node_status_api::models::AxumResult; +use crate::v2::AxumAppState; +use axum::extract::{Path, Query, State}; +use axum::Json; +use axum::Router; +use nym_api_requests::models::{ + ComputeRewardEstParam, GatewayBondAnnotated, GatewayCoreStatusResponse, + GatewayStatusReportResponse, GatewayUptimeHistoryResponse, GatewayUptimeResponse, + MixNodeBondAnnotated, MixnodeCoreStatusResponse, MixnodeStatusReportResponse, + MixnodeUptimeHistoryResponse, RewardEstimationResponse, UptimeResponse, +}; +use serde::Deserialize; +use utoipa::IntoParams; + +use super::unstable; + +pub(super) fn network_monitor_routes() -> Router { + Router::new() + .nest( + "/gateway/:identity", + Router::new() + .route("/report", axum::routing::get(gateway_report)) + .route("/history", axum::routing::get(gateway_uptime_history)) + .route( + "/core-status-count", + axum::routing::get(gateway_core_status_count), + ) + .route("/avg_uptime", axum::routing::get(get_gateway_avg_uptime)), + ) + .nest( + "/mixnode/:mix_id", + Router::new() + .route("/report", axum::routing::get(mixnode_report)) + .route("/history", axum::routing::get(mixnode_uptime_history)) + .route( + "/core-status-count", + axum::routing::get(mixnode_core_status_count), + ) + .route( + "/reward-estimation", + axum::routing::get(get_mixnode_reward_estimation), + ) + .route( + "/compute-reward-estimation", + axum::routing::post(compute_mixnode_reward_estimation), + ) + .route("/avg_uptime", axum::routing::get(get_mixnode_avg_uptime)), + ) + .nest( + "/mixnodes", + Router::new() + .route( + "/detailed-unfiltered", + axum::routing::get(get_mixnodes_detailed_unfiltered), + ) + .route( + "/unstable/:mix_id/test-results", + axum::routing::get(unstable::mixnode_test_results), + ), + ) + .nest( + "/gateways", + Router::new() + .route("/detailed", axum::routing::get(get_gateways_detailed)) + .route( + "/detailed-unfiltered", + axum::routing::get(get_gateways_detailed_unfiltered), + ) + .route( + "/unstable/:gateway_identity/test-results", + axum::routing::get(unstable::gateway_test_results), + ), + ) +} + +#[utoipa::path( + tag = "network-monitor-status", + get, + path = "/v1/status/gateway/{identity}/report", + responses( + (status = 200, body = GatewayStatusReportResponse) + ) +)] +async fn gateway_report( + Path(identity): Path, + State(state): State, +) -> AxumResult> { + Ok(Json( + _gateway_report(state.node_status_cache(), &identity).await?, + )) +} + +#[utoipa::path( + tag = "network-monitor-status", + get, + path = "/v1/status/gateway/{identity}/history", + responses( + (status = 200, body = GatewayUptimeHistoryResponse) + ) +)] +async fn gateway_uptime_history( + Path(identity): Path, + State(state): State, +) -> AxumResult> { + Ok(Json( + _gateway_uptime_history(state.storage(), &identity).await?, + )) +} + +#[derive(Deserialize, IntoParams)] +#[into_params(parameter_in = Query)] +struct SinceQueryParams { + since: Option, +} + +#[utoipa::path( + tag = "network-monitor-status", + get, + params( + SinceQueryParams + ), + path = "/v1/status/gateway/{identity}/core-status-count", + responses( + (status = 200, body = GatewayCoreStatusResponse) + ) +)] +async fn gateway_core_status_count( + Path(identity): Path, + Query(SinceQueryParams { since }): Query, + State(state): State, +) -> AxumResult> { + Ok(Json( + _gateway_core_status_count(state.storage(), &identity, since).await?, + )) +} + +#[utoipa::path( + tag = "network-monitor-status", + get, + path = "/v1/status/gateway/{identity}/avg_uptime", + responses( + (status = 200, body = GatewayUptimeResponse) + ) +)] +async fn get_gateway_avg_uptime( + Path(identity): Path, + State(state): State, +) -> AxumResult> { + Ok(Json( + _get_gateway_avg_uptime(state.node_status_cache(), &identity).await?, + )) +} + +#[utoipa::path( + tag = "network-monitor-status", + get, + params( + MixIdParam + ), + path = "/v1/status/mixnode/{mix_id}/report", + responses( + (status = 200, body = MixnodeStatusReportResponse) + ) +)] +async fn mixnode_report( + Path(MixIdParam { mix_id }): Path, + State(state): State, +) -> AxumResult> { + Ok(Json( + _mixnode_report(state.node_status_cache(), mix_id).await?, + )) +} + +#[utoipa::path( + tag = "network-monitor-status", + get, + params( + MixIdParam + ), + path = "/v1/status/mixnode/{mix_id}/history", + responses( + (status = 200, body = MixnodeUptimeHistoryResponse) + ) +)] +async fn mixnode_uptime_history( + Path(MixIdParam { mix_id }): Path, + State(state): State, +) -> AxumResult> { + Ok(Json( + _mixnode_uptime_history(state.storage(), mix_id).await?, + )) +} + +#[utoipa::path( + tag = "network-monitor-status", + get, + params( + MixIdParam, SinceQueryParams + ), + path = "/v1/status/mixnode/{mix_id}/core-status-count", + responses( + (status = 200, body = MixnodeCoreStatusResponse) + ) +)] +async fn mixnode_core_status_count( + Path(MixIdParam { mix_id }): Path, + Query(SinceQueryParams { since }): Query, + State(state): State, +) -> AxumResult> { + Ok(Json( + _mixnode_core_status_count(state.storage(), mix_id, since).await?, + )) +} + +#[utoipa::path( + tag = "network-monitor-status", + get, + params( + MixIdParam + ), + path = "/v1/status/mixnode/{mix_id}/reward-estimation", + responses( + (status = 200, body = RewardEstimationResponse) + ) +)] +async fn get_mixnode_reward_estimation( + Path(MixIdParam { mix_id }): Path, + State(state): State, +) -> AxumResult> { + Ok(Json( + _get_mixnode_reward_estimation( + state.node_status_cache(), + state.nym_contract_cache(), + mix_id, + ) + .await?, + )) +} + +#[utoipa::path( + tag = "network-monitor-status", + post, + params( + ComputeRewardEstParam, MixIdParam + ), + path = "/v1/status/mixnode/{mix_id}/compute-reward-estimation", + request_body = ComputeRewardEstParam, + responses( + (status = 200, body = RewardEstimationResponse) + ) +)] +async fn compute_mixnode_reward_estimation( + Path(MixIdParam { mix_id }): Path, + State(state): State, + Json(user_reward_param): Json, +) -> AxumResult> { + Ok(Json( + _compute_mixnode_reward_estimation( + &user_reward_param, + state.node_status_cache(), + state.nym_contract_cache(), + mix_id, + ) + .await?, + )) +} + +#[utoipa::path( + tag = "network-monitor-status", + get, + params( + MixIdParam + ), + path = "/v1/status/mixnode/{mix_id}/avg_uptime", + responses( + (status = 200, body = UptimeResponse) + ) +)] +async fn get_mixnode_avg_uptime( + Path(MixIdParam { mix_id }): Path, + State(state): State, +) -> AxumResult> { + Ok(Json( + _get_mixnode_avg_uptime(state.node_status_cache(), mix_id).await?, + )) +} + +#[utoipa::path( + tag = "network-monitor-status", + get, + path = "/v1/status/mixnodes/detailed-unfiltered", + responses( + (status = 200, body = MixNodeBondAnnotated) + ) +)] +pub async fn get_mixnodes_detailed_unfiltered( + State(state): State, +) -> Json> { + Json(_get_mixnodes_detailed_unfiltered(state.node_status_cache()).await) +} + +#[utoipa::path( + tag = "network-monitor-status", + get, + path = "/v1/status/gateways/detailed", + responses( + (status = 200, body = GatewayBondAnnotated) + ) +)] +pub async fn get_gateways_detailed( + State(state): State, +) -> Json> { + Json(_get_gateways_detailed(state.node_status_cache()).await) +} + +#[utoipa::path( + tag = "network-monitor-status", + get, + path = "/v1/status/gateways/detailed-unfiltered", + responses( + (status = 200, body = GatewayBondAnnotated) + ) +)] +pub async fn get_gateways_detailed_unfiltered( + State(state): State, +) -> Json> { + Json(_get_gateways_detailed_unfiltered(state.node_status_cache()).await) +} diff --git a/nym-api/src/node_status_api/handlers/unstable.rs b/nym-api/src/node_status_api/handlers/unstable.rs new file mode 100644 index 0000000000..b8a30639b4 --- /dev/null +++ b/nym-api/src/node_status_api/handlers/unstable.rs @@ -0,0 +1,279 @@ +// Copyright 2021-2024 - Nym Technologies SA +// SPDX-License-Identifier: GPL-3.0-only + +use crate::node_status_api::models::{AxumErrorResponse, AxumResult}; +use crate::support::http::helpers::PaginationRequest; +use crate::support::storage::NymApiStorage; +use crate::v2::AxumAppState; +use axum::extract::{Path, Query, State}; +use axum::Json; +use nym_api_requests::models::{ + GatewayTestResultResponse, MixnodeTestResultResponse, PartialTestResult, TestNode, TestRoute, +}; +use nym_api_requests::pagination::Pagination; +use nym_mixnet_contract_common::MixId; +use std::cmp::min; +use std::collections::HashMap; +use std::sync::Arc; +use tokio::sync::RwLock; + +pub type DbId = i64; + +// a simply in-memory cache of node details +#[derive(Debug, Clone, Default)] +pub struct NodeInfoCache { + inner: Arc>, +} + +impl NodeInfoCache { + async fn get_mix_node_details(&self, db_id: DbId, storage: &NymApiStorage) -> TestNode { + { + let read_guard = self.inner.read().await; + if let Some(cached) = read_guard.mixnodes.get(&db_id) { + trace!("cache hit for mixnode {db_id}"); + return cached.clone(); + } + } + trace!("cache miss for mixnode {db_id}"); + + let mut write_guard = self.inner.write().await; + // double-check the cache in case somebody already updated it while we were waiting for the lock + if let Some(cached) = write_guard.mixnodes.get(&db_id) { + return cached.clone(); + } + + let details = match storage.get_mixnode_details_by_db_id(db_id).await { + Ok(Some(details)) => details.into(), + Ok(None) => { + error!("somebody has been messing with the database! details for mixnode with database id {db_id} have been removed!"); + TestNode::default() + } + Err(err) => { + // don't insert into the cache in case another request is successful + error!("failed to retrieve details for mixnode {db_id}: {err}"); + return TestNode::default(); + } + }; + + write_guard.mixnodes.insert(db_id, details.clone()); + details + } + + async fn get_gateway_details(&self, db_id: DbId, storage: &NymApiStorage) -> TestNode { + { + let read_guard = self.inner.read().await; + if let Some(cached) = read_guard.gateways.get(&db_id) { + trace!("cache hit for gateway {db_id}"); + return cached.clone(); + } + } + trace!("cache miss for gateway {db_id}"); + + let mut write_guard = self.inner.write().await; + // double-check the cache in case somebody already updated it while we were waiting for the lock + if let Some(cached) = write_guard.gateways.get(&db_id) { + return cached.clone(); + } + + let details = match storage.get_gateway_details_by_db_id(db_id).await { + Ok(Some(details)) => details.into(), + Ok(None) => { + error!("somebody has been messing with the database! details for gateway with database id {db_id} have been removed!"); + TestNode::default() + } + Err(err) => { + // don't insert into the cache in case another request is successful + error!("failed to retrieve details for gateway {db_id}: {err}"); + return TestNode::default(); + } + }; + + write_guard.gateways.insert(db_id, details.clone()); + details + } +} + +#[derive(Debug, Clone, Default)] +struct NodeInfoCacheInner { + mixnodes: HashMap, + gateways: HashMap, +} + +const MAX_TEST_RESULTS_PAGE_SIZE: u32 = 100; +const DEFAULT_TEST_RESULTS_PAGE_SIZE: u32 = 50; + +async fn _mixnode_test_results( + mix_id: MixId, + page: u32, + per_page: u32, + info_cache: &NodeInfoCache, + storage: &NymApiStorage, +) -> anyhow::Result { + // convert to db offset + // we're paging from page 0 like civilised people, + // so we have to skip (page * per_page) results + let offset = page * per_page; + let limit = per_page; + + let raw_results = storage + .get_mixnode_detailed_statuses(mix_id, limit, offset) + .await?; + let total = match raw_results.first() { + None => 0, + Some(r) => storage.get_mixnode_detailed_statuses_count(r.db_id).await?, + }; + + let mut partial_results = Vec::new(); + for result in raw_results { + let gateway = info_cache + .get_gateway_details(result.gateway_id, storage) + .await; + let layer1 = info_cache + .get_mix_node_details(result.layer1_mix_id, storage) + .await; + let layer2 = info_cache + .get_mix_node_details(result.layer2_mix_id, storage) + .await; + let layer3 = info_cache + .get_mix_node_details(result.layer3_mix_id, storage) + .await; + + partial_results.push(PartialTestResult { + monitor_run_id: result.monitor_run_id, + timestamp: result.timestamp, + overall_reliability_for_all_routes_in_monitor_run: result.reliability, + test_routes: TestRoute { + gateway, + layer1, + layer2, + layer3, + }, + }) + } + + Ok(MixnodeTestResultResponse { + pagination: Pagination { + total, + page, + size: partial_results.len(), + }, + data: partial_results, + }) +} + +pub async fn mixnode_test_results( + Path(mix_id): Path, + Query(pagination): Query, + State(state): State, +) -> AxumResult> { + let page = pagination.page.unwrap_or_default(); + let per_page = min( + pagination + .per_page + .unwrap_or(DEFAULT_TEST_RESULTS_PAGE_SIZE), + MAX_TEST_RESULTS_PAGE_SIZE, + ); + + match _mixnode_test_results( + mix_id, + page, + per_page, + state.node_info_cache(), + state.storage(), + ) + .await + { + Ok(res) => Ok(Json(res)), + Err(err) => Err(AxumErrorResponse::internal_msg(format!( + "failed to retrieve mixnode test results for node {mix_id}: {err}" + ))), + } +} + +async fn _gateway_test_results( + gateway_identity: &str, + page: u32, + per_page: u32, + info_cache: &NodeInfoCache, + storage: &NymApiStorage, +) -> anyhow::Result { + // convert to db offset + // we're paging from page 0 like civilised people, + // so we have to skip (page * per_page) results + let offset = page * per_page; + let limit = per_page; + + let raw_results = storage + .get_gateway_detailed_statuses(gateway_identity, limit, offset) + .await?; + let total = match raw_results.first() { + None => 0, + Some(r) => storage.get_gateway_detailed_statuses_count(r.db_id).await?, + }; + + let mut partial_results = Vec::new(); + for result in raw_results { + let gateway = info_cache + .get_gateway_details(result.gateway_id, storage) + .await; + let layer1 = info_cache + .get_mix_node_details(result.layer1_mix_id, storage) + .await; + let layer2 = info_cache + .get_mix_node_details(result.layer2_mix_id, storage) + .await; + let layer3 = info_cache + .get_mix_node_details(result.layer3_mix_id, storage) + .await; + + partial_results.push(PartialTestResult { + monitor_run_id: result.monitor_run_id, + timestamp: result.timestamp, + overall_reliability_for_all_routes_in_monitor_run: result.reliability, + test_routes: TestRoute { + gateway, + layer1, + layer2, + layer3, + }, + }) + } + + Ok(GatewayTestResultResponse { + pagination: Pagination { + total, + page, + size: partial_results.len(), + }, + data: partial_results, + }) +} + +pub async fn gateway_test_results( + Path(gateway_identity): Path, + Query(pagination): Query, + State(state): State, +) -> AxumResult> { + let page = pagination.page.unwrap_or_default(); + let per_page = min( + pagination + .per_page + .unwrap_or(DEFAULT_TEST_RESULTS_PAGE_SIZE), + MAX_TEST_RESULTS_PAGE_SIZE, + ); + + match _gateway_test_results( + &gateway_identity, + page, + per_page, + state.node_info_cache(), + state.storage(), + ) + .await + { + Ok(res) => Ok(Json(res)), + Err(err) => Err(AxumErrorResponse::internal_msg(format!( + "failed to retrieve mixnode test results for gateway {gateway_identity}: {err}" + ))), + } +} diff --git a/nym-api/src/node_status_api/handlers/without_monitor.rs b/nym-api/src/node_status_api/handlers/without_monitor.rs new file mode 100644 index 0000000000..b431d38913 --- /dev/null +++ b/nym-api/src/node_status_api/handlers/without_monitor.rs @@ -0,0 +1,176 @@ +// Copyright 2021-2024 - Nym Technologies SA +// SPDX-License-Identifier: GPL-3.0-only + +use crate::node_status_api::handlers::MixIdParam; +use crate::node_status_api::helpers::{ + _get_active_set_detailed, _get_mixnode_inclusion_probabilities, + _get_mixnode_inclusion_probability, _get_mixnode_stake_saturation, _get_mixnode_status, + _get_mixnodes_detailed, _get_rewarded_set_detailed, +}; +use crate::node_status_api::models::AxumResult; +use crate::v2::AxumAppState; +use axum::extract::{Path, State}; +use axum::Json; +use axum::Router; +use nym_api_requests::models::{ + AllInclusionProbabilitiesResponse, InclusionProbabilityResponse, MixNodeBondAnnotated, + MixnodeStatusResponse, StakeSaturationResponse, +}; +use nym_mixnet_contract_common::MixId; + +pub(super) fn mandatory_routes() -> Router { + Router::new() + .nest( + "/mixnode/:mix_id", + Router::new() + .route("/status", axum::routing::get(get_mixnode_status)) + .route( + "/stake-saturation", + axum::routing::get(get_mixnode_stake_saturation), + ) + .route( + "/inclusion-probability", + axum::routing::get(get_mixnode_inclusion_probability), + ), + ) + .merge( + Router::new().nest( + "/mixnodes", + Router::new() + .route( + "/inclusion-probability", + axum::routing::get(get_mixnode_inclusion_probabilities), + ) + .route("/detailed", axum::routing::get(get_mixnodes_detailed)) + .route( + "/rewarded/detailed", + axum::routing::get(get_rewarded_set_detailed), + ) + .route( + "/active/detailed", + axum::routing::get(get_active_set_detailed), + ), + ), + ) +} + +#[utoipa::path( + tag = "status", + get, + params( + MixIdParam + ), + path = "/v1/status/mixnode/{mix_id}/status", + responses( + (status = 200, body = MixnodeStatusResponse) + ) +)] +async fn get_mixnode_status( + Path(MixIdParam { mix_id }): Path, + State(state): State, +) -> Json { + Json(_get_mixnode_status(state.nym_contract_cache(), mix_id).await) +} + +#[utoipa::path( + tag = "status", + get, + params( + MixIdParam + ), + path = "/v1/status/mixnode/{mix_id}/stake-saturation", + responses( + (status = 200, body = StakeSaturationResponse) + ) +)] +async fn get_mixnode_stake_saturation( + Path(mix_id): Path, + State(state): State, +) -> AxumResult> { + Ok(Json( + _get_mixnode_stake_saturation( + state.node_status_cache(), + state.nym_contract_cache(), + mix_id, + ) + .await?, + )) +} + +#[utoipa::path( + tag = "status", + get, + params( + MixIdParam + ), + path = "/v1/status/mixnode/{mix_id}/inclusion-probability", + responses( + (status = 200, body = InclusionProbabilityResponse) + ) +)] +async fn get_mixnode_inclusion_probability( + Path(mix_id): Path, + State(state): State, +) -> AxumResult> { + Ok(Json( + _get_mixnode_inclusion_probability(state.node_status_cache(), mix_id).await?, + )) +} + +#[utoipa::path( + tag = "status", + get, + path = "/v1/status/mixnodes/inclusion-probability", + responses( + (status = 200, body = AllInclusionProbabilitiesResponse) + ) +)] +async fn get_mixnode_inclusion_probabilities( + State(state): State, +) -> AxumResult> { + Ok(Json( + _get_mixnode_inclusion_probabilities(state.node_status_cache()).await?, + )) +} + +#[utoipa::path( + tag = "status", + get, + path = "/v1/status/mixnodes/detailed", + responses( + (status = 200, body = MixNodeBondAnnotated) + ) +)] +pub async fn get_mixnodes_detailed( + State(state): State, +) -> Json> { + Json(_get_mixnodes_detailed(state.node_status_cache()).await) +} + +#[utoipa::path( + tag = "status", + get, + path = "/v1/status/mixnodes/rewarded/detailed", + responses( + (status = 200, body = MixNodeBondAnnotated) + ) +)] +pub async fn get_rewarded_set_detailed( + State(state): State, +) -> Json> { + Json(_get_rewarded_set_detailed(state.node_status_cache()).await) +} + +#[utoipa::path( + tag = "status", + get, + path = "/v1/status/mixnodes/active/detailed", + responses( + (status = 200, body = MixNodeBondAnnotated) + ) +)] +pub async fn get_active_set_detailed( + State(state): State, +) -> Json> { + Json(_get_active_set_detailed(state.node_status_cache()).await) +} diff --git a/nym-api/src/node_status_api/helpers.rs b/nym-api/src/node_status_api/helpers.rs index 9ac54bd363..0d706b1156 100644 --- a/nym-api/src/node_status_api/helpers.rs +++ b/nym-api/src/node_status_api/helpers.rs @@ -1,7 +1,8 @@ // Copyright 2021-2023 - Nym Technologies SA // SPDX-License-Identifier: GPL-3.0-only -use crate::node_status_api::models::ErrorResponse; +use super::reward_estimate::compute_reward_estimate; +use crate::node_status_api::models::{AxumErrorResponse, AxumResult}; use crate::storage::NymApiStorage; use crate::support::caching::Cache; use crate::{NodeStatusCache, NymContractCache}; @@ -15,41 +16,31 @@ use nym_api_requests::models::{ UptimeResponse, }; use nym_mixnet_contract_common::{MixId, RewardedSetNodeStatus}; -use rocket::http::Status; -use rocket::State; - -use super::reward_estimate::compute_reward_estimate; async fn get_gateway_bond_annotated( cache: &NodeStatusCache, identity: &str, -) -> Result { +) -> AxumResult { cache .gateway_annotated(identity) .await - .ok_or(ErrorResponse::new( - "gateway bond not found", - Status::NotFound, - )) + .ok_or(AxumErrorResponse::not_found("gateway bond not found")) } async fn get_mixnode_bond_annotated( cache: &NodeStatusCache, mix_id: MixId, -) -> Result { +) -> AxumResult { cache .mixnode_annotated(mix_id) .await - .ok_or(ErrorResponse::new( - "mixnode bond not found", - Status::NotFound, - )) + .ok_or(AxumErrorResponse::not_found("mixnode bond not found")) } pub(crate) async fn _gateway_report( cache: &NodeStatusCache, identity: &str, -) -> Result { +) -> AxumResult { let gateway = get_gateway_bond_annotated(cache, identity).await?; Ok(GatewayStatusReportResponse { @@ -64,23 +55,23 @@ pub(crate) async fn _gateway_report( pub(crate) async fn _gateway_uptime_history( storage: &NymApiStorage, identity: &str, -) -> Result { +) -> AxumResult { storage .get_gateway_uptime_history(identity) .await .map(GatewayUptimeHistoryResponse::from) - .map_err(|err| ErrorResponse::new(err.to_string(), Status::NotFound)) + .map_err(AxumErrorResponse::not_found) } pub(crate) async fn _gateway_core_status_count( - storage: &State, + storage: &NymApiStorage, identity: &str, since: Option, -) -> Result { +) -> AxumResult { let count = storage .get_core_gateway_status_count(identity, since) .await - .map_err(|err| ErrorResponse::new(err.to_string(), Status::NotFound))?; + .map_err(AxumErrorResponse::not_found)?; Ok(GatewayCoreStatusResponse { identity: identity.to_string(), @@ -91,7 +82,7 @@ pub(crate) async fn _gateway_core_status_count( pub(crate) async fn _mixnode_report( cache: &NodeStatusCache, mix_id: MixId, -) -> Result { +) -> AxumResult { let mixnode = get_mixnode_bond_annotated(cache, mix_id).await?; Ok(MixnodeStatusReportResponse { @@ -107,23 +98,23 @@ pub(crate) async fn _mixnode_report( pub(crate) async fn _mixnode_uptime_history( storage: &NymApiStorage, mix_id: MixId, -) -> Result { +) -> AxumResult { storage .get_mixnode_uptime_history(mix_id) .await .map(MixnodeUptimeHistoryResponse::from) - .map_err(|err| ErrorResponse::new(err.to_string(), Status::NotFound)) + .map_err(AxumErrorResponse::not_found) } pub(crate) async fn _mixnode_core_status_count( - storage: &State, + storage: &NymApiStorage, mix_id: MixId, since: Option, -) -> Result { +) -> AxumResult { let count = storage .get_core_mixnode_status_count(mix_id, since) .await - .map_err(|err| ErrorResponse::new(err.to_string(), Status::NotFound))?; + .map_err(AxumErrorResponse::not_found)?; Ok(MixnodeCoreStatusResponse { mix_id, count }) } @@ -138,22 +129,22 @@ pub(crate) async fn _get_mixnode_status( } pub(crate) async fn _get_mixnode_reward_estimation( - cache: &State, - validator_cache: &State, + cache: &NodeStatusCache, + validator_cache: &NymContractCache, mix_id: MixId, -) -> Result { +) -> AxumResult { let (mixnode, status) = cache.mixnode_details(mix_id).await; if let Some(mixnode) = mixnode { let reward_params = validator_cache.interval_reward_params().await; let as_at = reward_params.timestamp(); let reward_params = reward_params .into_inner() - .ok_or_else(|| ErrorResponse::new("server error", Status::InternalServerError))?; + .ok_or_else(AxumErrorResponse::internal)?; let current_interval = validator_cache .current_interval() .await .into_inner() - .ok_or_else(|| ErrorResponse::new("server error", Status::InternalServerError))?; + .ok_or_else(AxumErrorResponse::internal)?; let reward_estimation = compute_reward_estimate( &mixnode.mixnode_details, @@ -170,31 +161,28 @@ pub(crate) async fn _get_mixnode_reward_estimation( as_at: as_at.unix_timestamp(), }) } else { - Err(ErrorResponse::new( - "mixnode bond not found", - Status::NotFound, - )) + Err(AxumErrorResponse::not_found("mixnode bond not found")) } } pub(crate) async fn _compute_mixnode_reward_estimation( - user_reward_param: ComputeRewardEstParam, + user_reward_param: &ComputeRewardEstParam, cache: &NodeStatusCache, validator_cache: &NymContractCache, mix_id: MixId, -) -> Result { +) -> AxumResult { let (mixnode, actual_status) = cache.mixnode_details(mix_id).await; if let Some(mut mixnode) = mixnode { let reward_params = validator_cache.interval_reward_params().await; let as_at = reward_params.timestamp(); let reward_params = reward_params .into_inner() - .ok_or_else(|| ErrorResponse::new("server error", Status::InternalServerError))?; + .ok_or_else(AxumErrorResponse::internal)?; let current_interval = validator_cache .current_interval() .await .into_inner() - .ok_or_else(|| ErrorResponse::new("server error", Status::InternalServerError))?; + .ok_or_else(AxumErrorResponse::internal)?; // For these parameters we either use the provided ones, or fall back to the system ones let performance = user_reward_param.performance.unwrap_or(mixnode.performance); @@ -222,21 +210,20 @@ pub(crate) async fn _compute_mixnode_reward_estimation( .profit_margin_percent = profit_margin_percent; } - if let Some(interval_operating_cost) = user_reward_param.interval_operating_cost { + if let Some(interval_operating_cost) = &user_reward_param.interval_operating_cost { mixnode .mixnode_details .rewarding_details .cost_params - .interval_operating_cost = interval_operating_cost; + .interval_operating_cost = interval_operating_cost.clone(); } if mixnode.mixnode_details.rewarding_details.operator + mixnode.mixnode_details.rewarding_details.delegates > reward_params.interval.staking_supply { - return Err(ErrorResponse::new( + return Err(AxumErrorResponse::unprocessable_entity( "Pledge plus delegation too large", - Status::UnprocessableEntity, )); } @@ -255,10 +242,7 @@ pub(crate) async fn _compute_mixnode_reward_estimation( as_at: as_at.unix_timestamp(), }) } else { - Err(ErrorResponse::new( - "mixnode bond not found", - Status::NotFound, - )) + Err(AxumErrorResponse::not_found("mixnode bond not found")) } } @@ -266,7 +250,7 @@ pub(crate) async fn _get_mixnode_stake_saturation( cache: &NodeStatusCache, validator_cache: &NymContractCache, mix_id: MixId, -) -> Result { +) -> AxumResult { let (mixnode, _) = cache.mixnode_details(mix_id).await; if let Some(mixnode) = mixnode { // Recompute the stake saturation just so that we can confidently state that the `as_at` @@ -275,7 +259,7 @@ pub(crate) async fn _get_mixnode_stake_saturation( let as_at = reward_params.timestamp(); let rewarding_params = reward_params .into_inner() - .ok_or_else(|| ErrorResponse::new("server error", Status::InternalServerError))?; + .ok_or_else(AxumErrorResponse::internal)?; Ok(StakeSaturationResponse { saturation: mixnode @@ -289,17 +273,14 @@ pub(crate) async fn _get_mixnode_stake_saturation( as_at: as_at.unix_timestamp(), }) } else { - Err(ErrorResponse::new( - "mixnode bond not found", - Status::NotFound, - )) + Err(AxumErrorResponse::not_found("mixnode bond not found")) } } pub(crate) async fn _get_mixnode_inclusion_probability( cache: &NodeStatusCache, mix_id: MixId, -) -> Result { +) -> AxumResult { cache .inclusion_probabilities() .await @@ -309,13 +290,13 @@ pub(crate) async fn _get_mixnode_inclusion_probability( in_active: p.in_active.into(), in_reserve: p.in_reserve.into(), }) - .ok_or_else(|| ErrorResponse::new("mixnode bond not found", Status::NotFound)) + .ok_or_else(|| AxumErrorResponse::not_found("mixnode bond not found")) } pub(crate) async fn _get_mixnode_avg_uptime( cache: &NodeStatusCache, mix_id: MixId, -) -> Result { +) -> AxumResult { let mixnode = get_mixnode_bond_annotated(cache, mix_id).await?; Ok(UptimeResponse { @@ -328,7 +309,7 @@ pub(crate) async fn _get_mixnode_avg_uptime( pub(crate) async fn _get_gateway_avg_uptime( cache: &NodeStatusCache, identity: &str, -) -> Result { +) -> AxumResult { let gateway = get_gateway_bond_annotated(cache, identity).await?; Ok(GatewayUptimeResponse { @@ -340,7 +321,7 @@ pub(crate) async fn _get_gateway_avg_uptime( pub(crate) async fn _get_mixnode_inclusion_probabilities( cache: &NodeStatusCache, -) -> Result { +) -> AxumResult { if let Some(prob) = cache.inclusion_probabilities().await { let as_at = prob.timestamp(); let prob = prob.into_inner(); @@ -353,10 +334,7 @@ pub(crate) async fn _get_mixnode_inclusion_probabilities( as_at: as_at.unix_timestamp(), }) } else { - Err(ErrorResponse::new( - "No data available", - Status::ServiceUnavailable, - )) + Err(AxumErrorResponse::service_unavailable()) } } diff --git a/nym-api/src/node_status_api/helpers_deprecated.rs b/nym-api/src/node_status_api/helpers_deprecated.rs new file mode 100644 index 0000000000..0788cd2cb3 --- /dev/null +++ b/nym-api/src/node_status_api/helpers_deprecated.rs @@ -0,0 +1,405 @@ +// Copyright 2021-2023 - Nym Technologies SA +// SPDX-License-Identifier: GPL-3.0-only + +use crate::node_status_api::models::RocketErrorResponse; +use crate::storage::NymApiStorage; +use crate::support::caching::Cache; +use crate::{NodeStatusCache, NymContractCache}; +use cosmwasm_std::Decimal; +use nym_api_requests::models::{ + AllInclusionProbabilitiesResponse, ComputeRewardEstParam, GatewayBondAnnotated, + GatewayCoreStatusResponse, GatewayStatusReportResponse, GatewayUptimeHistoryResponse, + GatewayUptimeResponse, InclusionProbabilityResponse, MixNodeBondAnnotated, + MixnodeCoreStatusResponse, MixnodeStatusReportResponse, MixnodeStatusResponse, + MixnodeUptimeHistoryResponse, RewardEstimationResponse, StakeSaturationResponse, + UptimeResponse, +}; +use nym_mixnet_contract_common::{MixId, RewardedSetNodeStatus}; +use rocket::http::Status; +use rocket::State; + +use super::reward_estimate::compute_reward_estimate; + +async fn get_gateway_bond_annotated( + cache: &NodeStatusCache, + identity: &str, +) -> Result { + cache + .gateway_annotated(identity) + .await + .ok_or(RocketErrorResponse::new( + "gateway bond not found", + Status::NotFound, + )) +} + +async fn get_mixnode_bond_annotated( + cache: &NodeStatusCache, + mix_id: MixId, +) -> Result { + cache + .mixnode_annotated(mix_id) + .await + .ok_or(RocketErrorResponse::new( + "mixnode bond not found", + Status::NotFound, + )) +} + +pub(crate) async fn _gateway_report( + cache: &NodeStatusCache, + identity: &str, +) -> Result { + let gateway = get_gateway_bond_annotated(cache, identity).await?; + + Ok(GatewayStatusReportResponse { + identity: gateway.identity().to_owned(), + owner: gateway.owner().to_string(), + most_recent: gateway.node_performance.most_recent.round_to_integer(), + last_hour: gateway.node_performance.last_hour.round_to_integer(), + last_day: gateway.node_performance.last_24h.round_to_integer(), + }) +} + +pub(crate) async fn _gateway_uptime_history( + storage: &NymApiStorage, + identity: &str, +) -> Result { + storage + .get_gateway_uptime_history(identity) + .await + .map(GatewayUptimeHistoryResponse::from) + .map_err(|err| RocketErrorResponse::new(err.to_string(), Status::NotFound)) +} + +pub(crate) async fn _gateway_core_status_count( + storage: &State, + identity: &str, + since: Option, +) -> Result { + let count = storage + .get_core_gateway_status_count(identity, since) + .await + .map_err(|err| RocketErrorResponse::new(err.to_string(), Status::NotFound))?; + + Ok(GatewayCoreStatusResponse { + identity: identity.to_string(), + count, + }) +} + +pub(crate) async fn _mixnode_report( + cache: &NodeStatusCache, + mix_id: MixId, +) -> Result { + let mixnode = get_mixnode_bond_annotated(cache, mix_id).await?; + + Ok(MixnodeStatusReportResponse { + mix_id, + identity: mixnode.identity_key().to_owned(), + owner: mixnode.owner().to_string(), + most_recent: mixnode.node_performance.most_recent.round_to_integer(), + last_hour: mixnode.node_performance.last_hour.round_to_integer(), + last_day: mixnode.node_performance.last_24h.round_to_integer(), + }) +} + +pub(crate) async fn _mixnode_uptime_history( + storage: &NymApiStorage, + mix_id: MixId, +) -> Result { + storage + .get_mixnode_uptime_history(mix_id) + .await + .map(MixnodeUptimeHistoryResponse::from) + .map_err(|err| RocketErrorResponse::new(err.to_string(), Status::NotFound)) +} + +pub(crate) async fn _mixnode_core_status_count( + storage: &State, + mix_id: MixId, + since: Option, +) -> Result { + let count = storage + .get_core_mixnode_status_count(mix_id, since) + .await + .map_err(|err| RocketErrorResponse::new(err.to_string(), Status::NotFound))?; + + Ok(MixnodeCoreStatusResponse { mix_id, count }) +} + +pub(crate) async fn _get_mixnode_status( + cache: &NymContractCache, + mix_id: MixId, +) -> MixnodeStatusResponse { + MixnodeStatusResponse { + status: cache.mixnode_status(mix_id).await, + } +} + +pub(crate) async fn _get_mixnode_reward_estimation( + cache: &State, + validator_cache: &State, + mix_id: MixId, +) -> Result { + let (mixnode, status) = cache.mixnode_details(mix_id).await; + if let Some(mixnode) = mixnode { + let reward_params = validator_cache.interval_reward_params().await; + let as_at = reward_params.timestamp(); + let reward_params = reward_params + .into_inner() + .ok_or_else(|| RocketErrorResponse::new("server error", Status::InternalServerError))?; + let current_interval = validator_cache + .current_interval() + .await + .into_inner() + .ok_or_else(|| RocketErrorResponse::new("server error", Status::InternalServerError))?; + + let reward_estimation = compute_reward_estimate( + &mixnode.mixnode_details, + mixnode.performance, + status.into(), + reward_params, + current_interval, + ); + + Ok(RewardEstimationResponse { + estimation: reward_estimation, + reward_params, + epoch: current_interval, + as_at: as_at.unix_timestamp(), + }) + } else { + Err(RocketErrorResponse::new( + "mixnode bond not found", + Status::NotFound, + )) + } +} + +pub(crate) async fn _compute_mixnode_reward_estimation( + user_reward_param: ComputeRewardEstParam, + cache: &NodeStatusCache, + validator_cache: &NymContractCache, + mix_id: MixId, +) -> Result { + let (mixnode, actual_status) = cache.mixnode_details(mix_id).await; + if let Some(mut mixnode) = mixnode { + let reward_params = validator_cache.interval_reward_params().await; + let as_at = reward_params.timestamp(); + let reward_params = reward_params + .into_inner() + .ok_or_else(|| RocketErrorResponse::new("server error", Status::InternalServerError))?; + let current_interval = validator_cache + .current_interval() + .await + .into_inner() + .ok_or_else(|| RocketErrorResponse::new("server error", Status::InternalServerError))?; + + // For these parameters we either use the provided ones, or fall back to the system ones + let performance = user_reward_param.performance.unwrap_or(mixnode.performance); + + let status = match user_reward_param.active_in_rewarded_set { + Some(true) => Some(RewardedSetNodeStatus::Active), + Some(false) => Some(RewardedSetNodeStatus::Standby), + None => actual_status.into(), + }; + + if let Some(pledge_amount) = user_reward_param.pledge_amount { + mixnode.mixnode_details.rewarding_details.operator = + Decimal::from_ratio(pledge_amount, 1u64); + } + if let Some(total_delegation) = user_reward_param.total_delegation { + mixnode.mixnode_details.rewarding_details.delegates = + Decimal::from_ratio(total_delegation, 1u64); + } + + if let Some(profit_margin_percent) = user_reward_param.profit_margin_percent { + mixnode + .mixnode_details + .rewarding_details + .cost_params + .profit_margin_percent = profit_margin_percent; + } + + if let Some(interval_operating_cost) = user_reward_param.interval_operating_cost { + mixnode + .mixnode_details + .rewarding_details + .cost_params + .interval_operating_cost = interval_operating_cost; + } + + if mixnode.mixnode_details.rewarding_details.operator + + mixnode.mixnode_details.rewarding_details.delegates + > reward_params.interval.staking_supply + { + return Err(RocketErrorResponse::new( + "Pledge plus delegation too large", + Status::UnprocessableEntity, + )); + } + + let reward_estimation = compute_reward_estimate( + &mixnode.mixnode_details, + performance, + status, + reward_params, + current_interval, + ); + + Ok(RewardEstimationResponse { + estimation: reward_estimation, + reward_params, + epoch: current_interval, + as_at: as_at.unix_timestamp(), + }) + } else { + Err(RocketErrorResponse::new( + "mixnode bond not found", + Status::NotFound, + )) + } +} + +pub(crate) async fn _get_mixnode_stake_saturation( + cache: &NodeStatusCache, + validator_cache: &NymContractCache, + mix_id: MixId, +) -> Result { + let (mixnode, _) = cache.mixnode_details(mix_id).await; + if let Some(mixnode) = mixnode { + // Recompute the stake saturation just so that we can confidently state that the `as_at` + // field is consistent and correct. Luckily this is very cheap. + let reward_params = validator_cache.interval_reward_params().await; + let as_at = reward_params.timestamp(); + let rewarding_params = reward_params + .into_inner() + .ok_or_else(|| RocketErrorResponse::new("server error", Status::InternalServerError))?; + + Ok(StakeSaturationResponse { + saturation: mixnode + .mixnode_details + .rewarding_details + .bond_saturation(&rewarding_params), + uncapped_saturation: mixnode + .mixnode_details + .rewarding_details + .uncapped_bond_saturation(&rewarding_params), + as_at: as_at.unix_timestamp(), + }) + } else { + Err(RocketErrorResponse::new( + "mixnode bond not found", + Status::NotFound, + )) + } +} + +pub(crate) async fn _get_mixnode_inclusion_probability( + cache: &NodeStatusCache, + mix_id: MixId, +) -> Result { + cache + .inclusion_probabilities() + .await + .map(Cache::into_inner) + .and_then(|p| p.node(mix_id).cloned()) + .map(|p| InclusionProbabilityResponse { + in_active: p.in_active.into(), + in_reserve: p.in_reserve.into(), + }) + .ok_or_else(|| RocketErrorResponse::new("mixnode bond not found", Status::NotFound)) +} + +pub(crate) async fn _get_mixnode_avg_uptime( + cache: &NodeStatusCache, + mix_id: MixId, +) -> Result { + let mixnode = get_mixnode_bond_annotated(cache, mix_id).await?; + + Ok(UptimeResponse { + mix_id, + avg_uptime: mixnode.node_performance.last_24h.round_to_integer(), + node_performance: mixnode.node_performance, + }) +} + +pub(crate) async fn _get_gateway_avg_uptime( + cache: &NodeStatusCache, + identity: &str, +) -> Result { + let gateway = get_gateway_bond_annotated(cache, identity).await?; + + Ok(GatewayUptimeResponse { + identity: identity.to_string(), + avg_uptime: gateway.node_performance.last_24h.round_to_integer(), + node_performance: gateway.node_performance, + }) +} + +pub(crate) async fn _get_mixnode_inclusion_probabilities( + cache: &NodeStatusCache, +) -> Result { + if let Some(prob) = cache.inclusion_probabilities().await { + let as_at = prob.timestamp(); + let prob = prob.into_inner(); + Ok(AllInclusionProbabilitiesResponse { + inclusion_probabilities: prob.inclusion_probabilities, + samples: prob.samples, + elapsed: prob.elapsed, + delta_max: prob.delta_max, + delta_l2: prob.delta_l2, + as_at: as_at.unix_timestamp(), + }) + } else { + Err(RocketErrorResponse::new( + "No data available", + Status::ServiceUnavailable, + )) + } +} + +pub(crate) async fn _get_mixnodes_detailed(cache: &NodeStatusCache) -> Vec { + cache + .mixnodes_annotated_filtered() + .await + .unwrap_or_default() +} + +pub(crate) async fn _get_mixnodes_detailed_unfiltered( + cache: &NodeStatusCache, +) -> Vec { + cache.mixnodes_annotated_full().await.unwrap_or_default() +} + +pub(crate) async fn _get_rewarded_set_detailed( + cache: &NodeStatusCache, +) -> Vec { + cache + .rewarded_set_annotated() + .await + .unwrap_or_default() + .into_inner() +} + +pub(crate) async fn _get_active_set_detailed(cache: &NodeStatusCache) -> Vec { + cache + .active_set_annotated() + .await + .unwrap_or_default() + .into_inner() +} + +pub(crate) async fn _get_gateways_detailed(cache: &NodeStatusCache) -> Vec { + cache + .gateways_annotated_filtered() + .await + .unwrap_or_default() +} + +pub(crate) async fn _get_gateways_detailed_unfiltered( + cache: &NodeStatusCache, +) -> Vec { + cache.gateways_annotated_full().await.unwrap_or_default() +} diff --git a/nym-api/src/node_status_api/mod.rs b/nym-api/src/node_status_api/mod.rs index 4800b5957a..5f50e62964 100644 --- a/nym-api/src/node_status_api/mod.rs +++ b/nym-api/src/node_status_api/mod.rs @@ -15,10 +15,14 @@ use rocket_okapi::{openapi_get_routes_spec, settings::OpenApiSettings}; use std::time::Duration; pub(crate) mod cache; +#[cfg(feature = "axum")] +pub(crate) mod handlers; +#[cfg(feature = "axum")] pub(crate) mod helpers; +pub(crate) mod helpers_deprecated; pub(crate) mod models; pub(crate) mod reward_estimate; -pub(crate) mod routes; +pub(crate) mod routes_deprecated; pub(crate) mod uptime_updater; pub(crate) mod utils; @@ -32,42 +36,42 @@ pub(crate) fn node_status_routes( ) -> (Vec, OpenApi) { if enabled { openapi_get_routes_spec![ - settings: routes::gateway_report, - routes::gateway_uptime_history, - routes::gateway_core_status_count, - routes::mixnode_report, - routes::mixnode_uptime_history, - routes::mixnode_core_status_count, - routes::get_mixnode_status, - routes::get_mixnode_reward_estimation, - routes::compute_mixnode_reward_estimation, - routes::get_mixnode_stake_saturation, - routes::get_mixnode_inclusion_probability, - routes::get_mixnode_avg_uptime, - routes::get_gateway_avg_uptime, - routes::get_mixnode_inclusion_probabilities, - routes::get_mixnodes_detailed, - routes::get_mixnodes_detailed_unfiltered, - routes::get_rewarded_set_detailed, - routes::get_active_set_detailed, - routes::get_gateways_detailed, - routes::get_gateways_detailed_unfiltered, - routes::unstable::mixnode_test_results, - routes::unstable::gateway_test_results, - routes::submit_gateway_monitoring_results, - routes::submit_node_monitoring_results, + settings: routes_deprecated::gateway_report, + routes_deprecated::gateway_uptime_history, + routes_deprecated::gateway_core_status_count, + routes_deprecated::mixnode_report, + routes_deprecated::mixnode_uptime_history, + routes_deprecated::mixnode_core_status_count, + routes_deprecated::get_mixnode_status, + routes_deprecated::get_mixnode_reward_estimation, + routes_deprecated::compute_mixnode_reward_estimation, + routes_deprecated::get_mixnode_stake_saturation, + routes_deprecated::get_mixnode_inclusion_probability, + routes_deprecated::get_mixnode_avg_uptime, + routes_deprecated::get_gateway_avg_uptime, + routes_deprecated::get_mixnode_inclusion_probabilities, + routes_deprecated::get_mixnodes_detailed, + routes_deprecated::get_mixnodes_detailed_unfiltered, + routes_deprecated::get_rewarded_set_detailed, + routes_deprecated::get_active_set_detailed, + routes_deprecated::get_gateways_detailed, + routes_deprecated::get_gateways_detailed_unfiltered, + routes_deprecated::unstable::mixnode_test_results, + routes_deprecated::unstable::gateway_test_results, + routes_deprecated::submit_gateway_monitoring_results, + routes_deprecated::submit_node_monitoring_results, ] } else { // in the minimal variant we would not have access to endpoints relying on existence // of the network monitor and the associated storage openapi_get_routes_spec![ - settings: routes::get_mixnode_status, - routes::get_mixnode_stake_saturation, - routes::get_mixnode_inclusion_probability, - routes::get_mixnode_inclusion_probabilities, - routes::get_mixnodes_detailed, - routes::get_rewarded_set_detailed, - routes::get_active_set_detailed, + settings: routes_deprecated::get_mixnode_status, + routes_deprecated::get_mixnode_stake_saturation, + routes_deprecated::get_mixnode_inclusion_probability, + routes_deprecated::get_mixnode_inclusion_probabilities, + routes_deprecated::get_mixnodes_detailed, + routes_deprecated::get_rewarded_set_detailed, + routes_deprecated::get_active_set_detailed, ] } } @@ -80,7 +84,7 @@ pub(crate) fn start_cache_refresh( config: &config::NodeStatusAPI, nym_contract_cache_state: &NymContractCache, node_status_cache_state: &NodeStatusCache, - storage: Option<&storage::NymApiStorage>, + storage: storage::NymApiStorage, nym_contract_cache_listener: tokio::sync::watch::Receiver, shutdown: &TaskManager, ) { @@ -89,7 +93,7 @@ pub(crate) fn start_cache_refresh( config.debug.caching_interval, nym_contract_cache_state.to_owned(), nym_contract_cache_listener, - storage.cloned(), + storage, ); let shutdown_listener = shutdown.subscribe(); tokio::spawn(async move { nym_api_cache_refresher.run(shutdown_listener).await }); diff --git a/nym-api/src/node_status_api/models.rs b/nym-api/src/node_status_api/models.rs index d0c172d7a3..480fae65d2 100644 --- a/nym-api/src/node_status_api/models.rs +++ b/nym-api/src/node_status_api/models.rs @@ -330,21 +330,22 @@ impl From for HistoricalUptimeResponse { } } -pub(crate) struct ErrorResponse { +#[deprecated(note = "TODO rocket remove once Rocket is phased out")] +pub(crate) struct RocketErrorResponse { error_message: RequestError, status: Status, } -impl ErrorResponse { +impl RocketErrorResponse { pub(crate) fn new(error_message: impl Into, status: Status) -> Self { - ErrorResponse { + RocketErrorResponse { error_message: RequestError::new(error_message), status, } } } -impl<'r, 'o: 'r> Responder<'r, 'o> for ErrorResponse { +impl<'r, 'o: 'r> Responder<'r, 'o> for RocketErrorResponse { fn respond_to(self, req: &'r Request<'_>) -> response::Result<'o> { // piggyback on the existing implementation // also prefer json over plain for ease of use in frontend @@ -355,7 +356,7 @@ impl<'r, 'o: 'r> Responder<'r, 'o> for ErrorResponse { } } -impl JsonSchema for ErrorResponse { +impl JsonSchema for RocketErrorResponse { fn schema_name() -> String { "ErrorResponse".to_owned() } @@ -384,7 +385,7 @@ impl JsonSchema for ErrorResponse { } } -impl OpenApiResponderInner for ErrorResponse { +impl OpenApiResponderInner for RocketErrorResponse { fn responses(_gen: &mut OpenApiGenerator) -> rocket_okapi::Result { let mut responses = Responses::default(); ensure_status_code_exists(&mut responses, 404); @@ -392,6 +393,103 @@ impl OpenApiResponderInner for ErrorResponse { } } +#[cfg(feature = "axum")] +pub(crate) use axum_error::{AxumErrorResponse, AxumResult}; + +#[cfg(feature = "axum")] +/// TODO rocket: extract types from this module when axum becomes the only server in Nym API +mod axum_error { + pub use super::*; + use crate::ecash::error::{EcashError, RedemptionError}; + use std::fmt::Display; + + // TODO rocket remove smurf name after eliminating `rocket` + pub(crate) type AxumResult = Result; + pub(crate) struct AxumErrorResponse { + message: RequestError, + status: axum::http::StatusCode, + } + + impl AxumErrorResponse { + pub(crate) fn internal_msg(msg: impl Display) -> Self { + Self { + message: RequestError::new(msg.to_string()), + status: axum::http::StatusCode::INTERNAL_SERVER_ERROR, + } + } + + pub(crate) fn internal() -> Self { + Self { + message: RequestError::new("Internal server error"), + status: axum::http::StatusCode::INTERNAL_SERVER_ERROR, + } + } + + pub(crate) fn not_implemented() -> Self { + Self { + message: RequestError::empty(), + status: axum::http::StatusCode::NOT_IMPLEMENTED, + } + } + + pub(crate) fn not_found(msg: impl Display) -> Self { + Self { + message: RequestError::new(msg.to_string()), + status: axum::http::StatusCode::NOT_FOUND, + } + } + + pub(crate) fn service_unavailable() -> Self { + Self { + message: RequestError::empty(), + status: axum::http::StatusCode::SERVICE_UNAVAILABLE, + } + } + + pub(crate) fn unprocessable_entity(msg: impl Display) -> Self { + Self { + message: RequestError::new(msg.to_string()), + status: axum::http::StatusCode::UNPROCESSABLE_ENTITY, + } + } + } + + impl axum::response::IntoResponse for AxumErrorResponse { + fn into_response(self) -> axum::response::Response { + (self.status, self.message.message().to_string()).into_response() + } + } + + impl From for AxumErrorResponse { + fn from(value: NymApiStorageError) -> Self { + error!("{value}"); + Self { + message: RequestError::empty(), + status: axum::http::StatusCode::INTERNAL_SERVER_ERROR, + } + } + } + + impl From for AxumErrorResponse { + fn from(value: EcashError) -> Self { + Self { + message: RequestError::new(value.to_string()), + status: axum::http::StatusCode::BAD_REQUEST, + } + } + } + + #[cfg(feature = "axum")] + impl From for AxumErrorResponse { + fn from(value: RedemptionError) -> Self { + Self { + message: RequestError::new(value.to_string()), + status: axum::http::StatusCode::BAD_REQUEST, + } + } + } +} + #[derive(Debug, thiserror::Error)] pub enum NymApiStorageError { #[error("could not find status report associated with mixnode {mix_id}")] diff --git a/nym-api/src/node_status_api/routes.rs b/nym-api/src/node_status_api/routes_deprecated.rs similarity index 91% rename from nym-api/src/node_status_api/routes.rs rename to nym-api/src/node_status_api/routes_deprecated.rs index 19b6462d1d..29ab89fb4d 100644 --- a/nym-api/src/node_status_api/routes.rs +++ b/nym-api/src/node_status_api/routes_deprecated.rs @@ -15,9 +15,9 @@ use rocket::serde::json::Json; use rocket::State; use rocket_okapi::openapi; -use super::helpers::_get_gateways_detailed; +use super::helpers_deprecated::_get_gateways_detailed; use super::NodeStatusCache; -use crate::node_status_api::helpers::{ +use crate::node_status_api::helpers_deprecated::{ _compute_mixnode_reward_estimation, _gateway_core_status_count, _gateway_report, _gateway_uptime_history, _get_active_set_detailed, _get_gateway_avg_uptime, _get_gateways_detailed_unfiltered, _get_mixnode_avg_uptime, @@ -26,7 +26,7 @@ use crate::node_status_api::helpers::{ _get_mixnodes_detailed, _get_mixnodes_detailed_unfiltered, _get_rewarded_set_detailed, _mixnode_core_status_count, _mixnode_report, _mixnode_uptime_history, }; -use crate::node_status_api::models::ErrorResponse; +use crate::node_status_api::models::RocketErrorResponse; use crate::storage::NymApiStorage; use crate::NymContractCache; @@ -35,23 +35,23 @@ use crate::NymContractCache; pub(crate) async fn submit_gateway_monitoring_results( message: Json, storage: &State, -) -> Result<(), ErrorResponse> { +) -> Result<(), RocketErrorResponse> { if !message.from_allowed() { - return Err(ErrorResponse::new( + return Err(RocketErrorResponse::new( "Monitor not registered to submit results".to_string(), rocket::http::Status::Forbidden, )); } if !message.timely() { - return Err(ErrorResponse::new( + return Err(RocketErrorResponse::new( "Message is too old".to_string(), rocket::http::Status::BadRequest, )); } if !message.verify() { - return Err(ErrorResponse::new( + return Err(RocketErrorResponse::new( "Invalid signature".to_string(), rocket::http::Status::BadRequest, )); @@ -65,7 +65,7 @@ pub(crate) async fn submit_gateway_monitoring_results( Ok(_) => Ok(()), Err(err) => { error!("failed to submit gateway monitoring results: {}", err); - Err(ErrorResponse::new( + Err(RocketErrorResponse::new( "failed to submit gateway monitoring results".to_string(), rocket::http::Status::InternalServerError, )) @@ -78,23 +78,23 @@ pub(crate) async fn submit_gateway_monitoring_results( pub(crate) async fn submit_node_monitoring_results( message: Json, storage: &State, -) -> Result<(), ErrorResponse> { +) -> Result<(), RocketErrorResponse> { if !message.from_allowed() { - return Err(ErrorResponse::new( + return Err(RocketErrorResponse::new( "Monitor not registered to submit results".to_string(), rocket::http::Status::Forbidden, )); } if !message.timely() { - return Err(ErrorResponse::new( + return Err(RocketErrorResponse::new( "Message is too old".to_string(), rocket::http::Status::BadRequest, )); } if !message.verify() { - return Err(ErrorResponse::new( + return Err(RocketErrorResponse::new( "Invalid signature".to_string(), rocket::http::Status::BadRequest, )); @@ -108,7 +108,7 @@ pub(crate) async fn submit_node_monitoring_results( Ok(_) => Ok(()), Err(err) => { error!("failed to submit node monitoring results: {}", err); - Err(ErrorResponse::new( + Err(RocketErrorResponse::new( "failed to submit node monitoring results".to_string(), rocket::http::Status::InternalServerError, )) @@ -121,7 +121,7 @@ pub(crate) async fn submit_node_monitoring_results( pub(crate) async fn gateway_report( cache: &State, identity: &str, -) -> Result, ErrorResponse> { +) -> Result, RocketErrorResponse> { Ok(Json(_gateway_report(cache, identity).await?)) } @@ -130,7 +130,7 @@ pub(crate) async fn gateway_report( pub(crate) async fn gateway_uptime_history( storage: &State, identity: &str, -) -> Result, ErrorResponse> { +) -> Result, RocketErrorResponse> { Ok(Json(_gateway_uptime_history(storage, identity).await?)) } @@ -140,7 +140,7 @@ pub(crate) async fn gateway_core_status_count( storage: &State, identity: &str, since: Option, -) -> Result, ErrorResponse> { +) -> Result, RocketErrorResponse> { Ok(Json( _gateway_core_status_count(storage, identity, since).await?, )) @@ -151,7 +151,7 @@ pub(crate) async fn gateway_core_status_count( pub(crate) async fn mixnode_report( cache: &State, mix_id: MixId, -) -> Result, ErrorResponse> { +) -> Result, RocketErrorResponse> { Ok(Json(_mixnode_report(cache, mix_id).await?)) } @@ -160,7 +160,7 @@ pub(crate) async fn mixnode_report( pub(crate) async fn mixnode_uptime_history( storage: &State, mix_id: MixId, -) -> Result, ErrorResponse> { +) -> Result, RocketErrorResponse> { Ok(Json(_mixnode_uptime_history(storage, mix_id).await?)) } @@ -170,7 +170,7 @@ pub(crate) async fn mixnode_core_status_count( storage: &State, mix_id: MixId, since: Option, -) -> Result, ErrorResponse> { +) -> Result, RocketErrorResponse> { Ok(Json( _mixnode_core_status_count(storage, mix_id, since).await?, )) @@ -191,7 +191,7 @@ pub(crate) async fn get_mixnode_reward_estimation( cache: &State, validator_cache: &State, mix_id: MixId, -) -> Result, ErrorResponse> { +) -> Result, RocketErrorResponse> { Ok(Json( _get_mixnode_reward_estimation(cache, validator_cache, mix_id).await?, )) @@ -207,7 +207,7 @@ pub(crate) async fn compute_mixnode_reward_estimation( cache: &State, validator_cache: &State, mix_id: MixId, -) -> Result, ErrorResponse> { +) -> Result, RocketErrorResponse> { Ok(Json( _compute_mixnode_reward_estimation( user_reward_param.into_inner(), @@ -225,7 +225,7 @@ pub(crate) async fn get_mixnode_stake_saturation( cache: &State, validator_cache: &State, mix_id: MixId, -) -> Result, ErrorResponse> { +) -> Result, RocketErrorResponse> { Ok(Json( _get_mixnode_stake_saturation(cache, validator_cache, mix_id).await?, )) @@ -236,7 +236,7 @@ pub(crate) async fn get_mixnode_stake_saturation( pub(crate) async fn get_mixnode_inclusion_probability( cache: &State, mix_id: MixId, -) -> Result, ErrorResponse> { +) -> Result, RocketErrorResponse> { Ok(Json( _get_mixnode_inclusion_probability(cache, mix_id).await?, )) @@ -247,7 +247,7 @@ pub(crate) async fn get_mixnode_inclusion_probability( pub(crate) async fn get_mixnode_avg_uptime( cache: &State, mix_id: MixId, -) -> Result, ErrorResponse> { +) -> Result, RocketErrorResponse> { Ok(Json(_get_mixnode_avg_uptime(cache, mix_id).await?)) } @@ -256,7 +256,7 @@ pub(crate) async fn get_mixnode_avg_uptime( pub(crate) async fn get_gateway_avg_uptime( cache: &State, identity: &str, -) -> Result, ErrorResponse> { +) -> Result, RocketErrorResponse> { Ok(Json(_get_gateway_avg_uptime(cache, identity).await?)) } @@ -264,7 +264,7 @@ pub(crate) async fn get_gateway_avg_uptime( #[get("/mixnodes/inclusion_probability")] pub(crate) async fn get_mixnode_inclusion_probabilities( cache: &State, -) -> Result, ErrorResponse> { +) -> Result, RocketErrorResponse> { Ok(Json(_get_mixnode_inclusion_probabilities(cache).await?)) } @@ -317,7 +317,7 @@ pub async fn get_gateways_detailed_unfiltered( } pub mod unstable { - use crate::node_status_api::models::ErrorResponse; + use crate::node_status_api::models::RocketErrorResponse; use crate::support::http::helpers::PaginationRequest; use crate::support::storage::NymApiStorage; use nym_api_requests::models::{ @@ -486,7 +486,7 @@ pub mod unstable { pagination: PaginationRequest, info_cache: &State, storage: &State, - ) -> Result, ErrorResponse> { + ) -> Result, RocketErrorResponse> { let page = pagination.page.unwrap_or_default(); let per_page = min( pagination @@ -497,7 +497,7 @@ pub mod unstable { match _mixnode_test_results(mix_id, page, per_page, info_cache, storage).await { Ok(res) => Ok(Json(res)), - Err(err) => Err(ErrorResponse::new( + Err(err) => Err(RocketErrorResponse::new( format!("failed to retrieve mixnode test results for node {mix_id}: {err}"), Status::InternalServerError, )), @@ -570,7 +570,7 @@ pub mod unstable { pagination: PaginationRequest, info_cache: &State, storage: &State, - ) -> Result, ErrorResponse> { + ) -> Result, RocketErrorResponse> { let page = pagination.page.unwrap_or_default(); let per_page = min( pagination @@ -581,7 +581,7 @@ pub mod unstable { match _gateway_test_results(gateway_identity, page, per_page, info_cache, storage).await { Ok(res) => Ok(Json(res)), - Err(err) => Err(ErrorResponse::new( + Err(err) => Err(RocketErrorResponse::new( format!( "failed to retrieve mixnode test results for gateway {gateway_identity}: {err}" ), diff --git a/nym-api/src/node_status_api/uptime_updater.rs b/nym-api/src/node_status_api/uptime_updater.rs index fc09185b53..2a33a0118f 100644 --- a/nym-api/src/node_status_api/uptime_updater.rs +++ b/nym-api/src/node_status_api/uptime_updater.rs @@ -118,8 +118,8 @@ impl HistoricalUptimeUpdater { } } - pub(crate) fn start(storage: &NymApiStorage, shutdown: &TaskManager) { - let uptime_updater = HistoricalUptimeUpdater::new(storage.to_owned()); + pub(crate) fn start(storage: NymApiStorage, shutdown: &TaskManager) { + let uptime_updater = HistoricalUptimeUpdater::new(storage); let shutdown_listener = shutdown.subscribe(); tokio::spawn(async move { uptime_updater.run(shutdown_listener).await }); } diff --git a/nym-api/src/nym_contract_cache/cache/mod.rs b/nym-api/src/nym_contract_cache/cache/mod.rs index 811e44f347..efaeac74a6 100644 --- a/nym-api/src/nym_contract_cache/cache/mod.rs +++ b/nym-api/src/nym_contract_cache/cache/mod.rs @@ -31,13 +31,14 @@ pub struct NymContractCache { } impl NymContractCache { - fn new() -> Self { + pub(crate) fn new() -> Self { NymContractCache { initialised: Arc::new(AtomicBool::new(false)), inner: Arc::new(RwLock::new(ValidatorCacheData::new())), } } + #[deprecated(note = "TODO rocket: obsolete because it's used for Rocket")] pub fn stage() -> AdHoc { AdHoc::on_ignite("Validator Cache Stage", |rocket| async { rocket.manage(Self::new()) diff --git a/nym-api/src/nym_contract_cache/handlers.rs b/nym-api/src/nym_contract_cache/handlers.rs new file mode 100644 index 0000000000..84f2c70fd2 --- /dev/null +++ b/nym-api/src/nym_contract_cache/handlers.rs @@ -0,0 +1,270 @@ +// Copyright 2021-2023 - Nym Technologies SA +// SPDX-License-Identifier: GPL-3.0-only + +use crate::{ + node_status_api::helpers_deprecated::{ + _get_active_set_detailed, _get_mixnodes_detailed, _get_rewarded_set_detailed, + }, + v2::AxumAppState, +}; +use axum::{extract, Router}; +use nym_api_requests::models::MixNodeBondAnnotated; +use nym_mixnet_contract_common::{ + mixnode::MixNodeDetails, reward_params::RewardingParams, GatewayBond, Interval, MixId, +}; +use std::collections::HashSet; + +pub(crate) fn nym_contract_cache_routes() -> Router { + Router::new() + .route("/mixnodes", axum::routing::get(get_mixnodes)) + .route( + "/mixnodes/detailed", + axum::routing::get(get_mixnodes_detailed), + ) + .route("/gateways", axum::routing::get(get_gateways)) + .route("/mixnodes/rewarded", axum::routing::get(get_rewarded_set)) + .route( + "/mixnodes/rewarded/detailed", + axum::routing::get(get_rewarded_set_detailed), + ) + .route("/mixnodes/active", axum::routing::get(get_active_set)) + .route( + "/mixnodes/active/detailed", + axum::routing::get(get_active_set_detailed), + ) + .route( + "/mixnodes/blacklisted", + axum::routing::get(get_blacklisted_mixnodes), + ) + .route( + "/gateways/blacklisted", + axum::routing::get(get_blacklisted_gateways), + ) + .route( + "/epoch/reward_params", + axum::routing::get(get_interval_reward_params), + ) + .route("/epoch/current", axum::routing::get(get_current_epoch)) +} + +#[utoipa::path( + tag = "contract-cache", + get, + path = "/v1/mixnodes", + responses( + (status = 200, body = Vec) + ) +)] +async fn get_mixnodes( + extract::State(state): extract::State, +) -> axum::Json> { + state.nym_contract_cache().mixnodes_filtered().await.into() +} + +// DEPRECATED: this endpoint now lives in `node_status_api`. Once all consumers are updated, +// replace this with +// ``` +// pub fn get_mixnodes_detailed() -> Redirect { +// Redirect::to(uri!("/v1/status/mixnodes/detailed")) +// } +// ``` +#[utoipa::path( + tag = "contract-cache", + get, + path = "/v1/mixnodes/detailed", + responses( + (status = 200, body = Vec) + ) +)] +async fn get_mixnodes_detailed( + extract::State(state): extract::State, +) -> axum::Json> { + _get_mixnodes_detailed(state.node_status_cache()) + .await + .into() +} + +#[utoipa::path( + tag = "contract-cache", + get, + path = "/v1/gateways", + responses( + (status = 200, body = Vec) + ) +)] +async fn get_gateways( + extract::State(state): extract::State, +) -> axum::Json> { + state.nym_contract_cache().gateways_filtered().await.into() +} + +#[utoipa::path( + tag = "contract-cache", + get, + path = "/v1/mixnodes/rewarded", + responses( + (status = 200, body = Vec) + ) +)] +async fn get_rewarded_set( + extract::State(state): extract::State, +) -> axum::Json> { + state + .nym_contract_cache() + .rewarded_set() + .await + .to_owned() + .into() +} + +// DEPRECATED: this endpoint now lives in `node_status_api`. Once all consumers are updated, +// replace this with +// ``` +// pub fn get_mixnodes_set_detailed() -> Redirect { +// Redirect::to(uri!("/v1/status/mixnodes/rewarded/detailed")) +// } +// ``` +#[utoipa::path( + tag = "contract-cache", + get, + path = "/v1/mixnodes/rewarded/detailed", + responses( + (status = 200, body = Vec) + ) +)] +async fn get_rewarded_set_detailed( + extract::State(state): extract::State, +) -> axum::Json> { + _get_rewarded_set_detailed(state.node_status_cache()) + .await + .into() +} + +#[utoipa::path( + tag = "contract-cache", + get, + path = "/v1/mixnodes/active", + responses( + (status = 200, body = Vec) + ) +)] +async fn get_active_set( + extract::State(state): extract::State, +) -> axum::Json> { + state + .nym_contract_cache() + .active_set() + .await + .to_owned() + .into() +} + +// DEPRECATED: this endpoint now lives in `node_status_api`. Once all consumers are updated, +// replace this with +// ``` +// pub fn get_active_set_detailed() -> Redirect { +// Redirect::to(uri!("/status/mixnodes/active/detailed")) +// } +// ``` + +#[utoipa::path( + tag = "contract-cache", + get, + path = "/v1/mixnodes/active/detailed", + responses( + (status = 200, body = Vec) + ) +)] +async fn get_active_set_detailed( + extract::State(state): extract::State, +) -> axum::Json> { + _get_active_set_detailed(state.node_status_cache()) + .await + .into() +} + +#[utoipa::path( + tag = "contract-cache", + get, + path = "/v1/mixnodes/blacklisted", + responses( + (status = 200, body = Option>) + ) +)] +async fn get_blacklisted_mixnodes( + extract::State(state): extract::State, +) -> axum::Json>> { + let blacklist = state + .nym_contract_cache() + .mixnodes_blacklist() + .await + .to_owned(); + if blacklist.is_empty() { + None + } else { + Some(blacklist) + } + .into() +} + +#[utoipa::path( + tag = "contract-cache", + get, + path = "/v1/gateways/blacklisted", + responses( + (status = 200, body = Option>) + ) +)] +async fn get_blacklisted_gateways( + extract::State(state): extract::State, +) -> axum::Json>> { + let blacklist = state + .nym_contract_cache() + .gateways_blacklist() + .await + .to_owned(); + if blacklist.is_empty() { + None + } else { + Some(blacklist) + } + .into() +} + +#[utoipa::path( + tag = "contract-cache", + get, + path = "/v1/epoch/reward_params", + responses( + (status = 200, body = Option) + ) +)] +async fn get_interval_reward_params( + extract::State(state): extract::State, +) -> axum::Json> { + state + .nym_contract_cache() + .interval_reward_params() + .await + .to_owned() + .into() +} + +#[utoipa::path( + tag = "contract-cache", + get, + path = "/v1/epoch/current", + responses( + (status = 200, body = Option) + ) +)] +async fn get_current_epoch( + extract::State(state): extract::State, +) -> axum::Json> { + state + .nym_contract_cache() + .current_interval() + .await + .to_owned() + .into() +} diff --git a/nym-api/src/nym_contract_cache/mod.rs b/nym-api/src/nym_contract_cache/mod.rs index 15d861e51e..9b1f48d9ad 100644 --- a/nym-api/src/nym_contract_cache/mod.rs +++ b/nym-api/src/nym_contract_cache/mod.rs @@ -12,6 +12,8 @@ use rocket_okapi::settings::OpenApiSettings; use self::cache::refresher::NymContractCacheRefresher; pub(crate) mod cache; +#[cfg(feature = "axum")] +pub(crate) mod handlers; pub(crate) mod routes; pub(crate) fn nym_contract_cache_routes(settings: &OpenApiSettings) -> (Vec, OpenApi) { diff --git a/nym-api/src/nym_contract_cache/routes.rs b/nym-api/src/nym_contract_cache/routes.rs index ec2d61b2e4..cef7f04c9c 100644 --- a/nym-api/src/nym_contract_cache/routes.rs +++ b/nym-api/src/nym_contract_cache/routes.rs @@ -3,7 +3,9 @@ use crate::{ node_status_api::{ - helpers::{_get_active_set_detailed, _get_mixnodes_detailed, _get_rewarded_set_detailed}, + helpers_deprecated::{ + _get_active_set_detailed, _get_mixnodes_detailed, _get_rewarded_set_detailed, + }, NodeStatusCache, }, nym_contract_cache::cache::NymContractCache, diff --git a/nym-api/src/nym_nodes/handlers.rs b/nym-api/src/nym_nodes/handlers.rs new file mode 100644 index 0000000000..7f775d8de4 --- /dev/null +++ b/nym-api/src/nym_nodes/handlers.rs @@ -0,0 +1,95 @@ +// Copyright 2023 - Nym Technologies SA +// SPDX-License-Identifier: GPL-3.0-only + +use crate::v2::AxumAppState; +use axum::{extract::State, Json, Router}; +use nym_api_requests::models::{DescribedGateway, DescribedMixNode}; +use nym_mixnet_contract_common::MixNodeBond; +use std::ops::Deref; + +// obviously this should get refactored later on because gateways will go away. +// unless maybe this will be filtering based on which nodes got assigned gateway role? TBD + +pub(crate) fn nym_node_routes() -> axum::Router { + Router::new() + .route( + "/gateways/described", + axum::routing::get(get_gateways_described), + ) + .route( + "/mixnodes/described", + axum::routing::get(get_mixnodes_described), + ) +} + +#[utoipa::path( + tag = "Nym Nodes", + get, + path = "/v1/gateways/described", + responses( + (status = 200, body = Vec) + ) +)] +async fn get_gateways_described(State(state): State) -> Json> { + let gateways = state.nym_contract_cache().gateways_filtered().await; + if gateways.is_empty() { + return Json(Vec::new()); + } + + // if the self describe cache is unavailable, well, don't attach describe data + let Ok(self_descriptions) = state.described_nodes_state().get().await else { + return Json(gateways.into_iter().map(Into::into).collect()); + }; + + // TODO: this is extremely inefficient, but given we don't have many gateways, + // it shouldn't be too much of a problem until we go ahead with directory v3 / the smoosh 2: electric smoosharoo, + // but at that point (I hope) the whole caching situation should get refactored + Json( + gateways + .into_iter() + .map(|bond| DescribedGateway { + self_described: self_descriptions.deref().get(bond.identity()).cloned(), + bond, + }) + .collect(), + ) +} + +#[utoipa::path( + tag = "Nym Nodes", + get, + path = "/v1/mixnodes/described", + responses( + (status = 200, body = Vec) + ) +)] +async fn get_mixnodes_described(State(state): State) -> Json> { + let mixnodes = state + .nym_contract_cache() + .mixnodes_filtered() + .await + .into_iter() + .map(|m| m.bond_information) + .collect::>(); + if mixnodes.is_empty() { + return Json(Vec::new()); + } + + // if the self describe cache is unavailable, well, don't attach describe data + let Ok(self_descriptions) = state.described_nodes_state().get().await else { + return Json(mixnodes.into_iter().map(Into::into).collect()); + }; + + // TODO: this is extremely inefficient, but given we don't have many gateways, + // it shouldn't be too much of a problem until we go ahead with directory v3 / the smoosh 2: electric smoosharoo, + // but at that point (I hope) the whole caching situation should get refactored + Json( + mixnodes + .into_iter() + .map(|bond| DescribedMixNode { + self_described: self_descriptions.deref().get(bond.identity()).cloned(), + bond, + }) + .collect(), + ) +} diff --git a/nym-api/src/nym_nodes/handlers_unstable.rs b/nym-api/src/nym_nodes/handlers_unstable.rs new file mode 100644 index 0000000000..f0a7d8cc8b --- /dev/null +++ b/nym-api/src/nym_nodes/handlers_unstable.rs @@ -0,0 +1,377 @@ +// Copyright 2024 - Nym Technologies SA +// SPDX-License-Identifier: GPL-3.0-only + +//! All routes/nodes are split into three tiers: +//! +//! `/skimmed` +//! - used by clients +//! - returns the very basic information for routing purposes +//! +//! `/semi-skimmed` +//! - used by other nodes/VPN +//! - returns more additional information such noise keys +//! +//! `/full-fat` +//! - used by explorers, et al. +//! - returns almost everything there is about the nodes +//! +//! There's also additional split based on the role: +//! - `?role` => filters based on the specific role (mixnode/gateway/(in the future: entry/exit)) +//! - `/mixnodes/` => only returns mixnode role data +//! - `/gateway/` => only returns (entry) gateway role data + +use crate::node_status_api::models::{AxumErrorResponse, AxumResult}; +use crate::v2::AxumAppState; +use axum::extract::Query; +use axum::extract::State; +use axum::{Json, Router}; +use nym_api_requests::nym_nodes::{ + CachedNodesResponse, FullFatNode, NodeRoleQueryParam, SemiSkimmedNode, SkimmedNode, +}; +use nym_bin_common::version_checker; +use serde::Deserialize; +use std::cmp::min; +use std::ops::Deref; + +pub(crate) fn nym_node_routes_unstable() -> axum::Router { + Router::new() + .route("/skimmed", axum::routing::get(nodes_basic)) + .route("/semi-skimmed", axum::routing::get(nodes_expanded)) + .route("/full-fat", axum::routing::get(nodes_detailed)) + .nest( + "/gateways", + Router::new() + .route("/skimmed", axum::routing::get(gateways_basic)) + .route("/semi-skimmed", axum::routing::get(gateways_expanded)) + .route("/full-fat", axum::routing::get(gateways_detailed)), + ) + .nest( + "/mixnodes", + Router::new() + .route("/skimmed", axum::routing::get(mixnodes_basic)) + .route("/semi-skimmed", axum::routing::get(mixnodes_expanded)) + .route("/full-fat", axum::routing::get(mixnodes_detailed)), + ) +} + +#[derive(Debug, Deserialize, utoipa::IntoParams)] +struct NodesParams { + #[param(inline)] + role: Option, + semver_compatibility: Option, +} + +#[derive(Debug, Deserialize, utoipa::IntoParams)] +struct SemverCompatibilityQueryParam { + semver_compatibility: Option, +} + +impl SemverCompatibilityQueryParam { + pub fn new(semver_compatibility: Option) -> Self { + Self { + semver_compatibility, + } + } +} + +#[utoipa::path( + tag = "Unstable Nym Nodes", + get, + params(NodesParams), + path = "/v1/unstable/nym-nodes/skimmed", + responses( + (status = 200, body = CachedNodesResponse) + ) +)] +async fn nodes_basic( + state: State, + Query(NodesParams { + role, + semver_compatibility, + }): Query, +) -> AxumResult>> { + if let Some(role) = role { + match role { + NodeRoleQueryParam::ActiveMixnode => { + return mixnodes_basic( + state, + Query(SemverCompatibilityQueryParam::new(semver_compatibility)), + ) + .await + } + NodeRoleQueryParam::EntryGateway => { + return gateways_basic( + state, + Query(SemverCompatibilityQueryParam::new(semver_compatibility)), + ) + .await; + } + _ => {} + } + } + + Err(AxumErrorResponse::not_implemented()) +} + +#[utoipa::path( + tag = "Unstable Nym Nodes", + get, + params(NodesParams), + path = "/v1/unstable/nym-nodes/semi-skimmed", + responses( + (status = 200, body = CachedNodesResponse) + ) +)] +async fn nodes_expanded( + state: State, + Query(NodesParams { + role, + semver_compatibility, + }): Query, +) -> AxumResult>> { + if let Some(role) = role { + match role { + NodeRoleQueryParam::ActiveMixnode => { + return mixnodes_expanded( + state, + Query(SemverCompatibilityQueryParam::new(semver_compatibility)), + ) + .await + } + NodeRoleQueryParam::EntryGateway => { + return gateways_expanded( + state, + Query(SemverCompatibilityQueryParam::new(semver_compatibility)), + ) + .await + } + _ => {} + } + } + + Err(AxumErrorResponse::not_implemented()) +} + +#[utoipa::path( + tag = "Unstable Nym Nodes", + get, + params(NodesParams), + path = "/v1/unstable/nym-nodes/full-fat", + responses( + (status = 200, body = CachedNodesResponse) + ) +)] +async fn nodes_detailed( + state: State, + Query(NodesParams { + role, + semver_compatibility, + }): Query, +) -> AxumResult>> { + if let Some(role) = role { + match role { + NodeRoleQueryParam::ActiveMixnode => { + return mixnodes_detailed( + state, + Query(SemverCompatibilityQueryParam::new(semver_compatibility)), + ) + .await + } + NodeRoleQueryParam::EntryGateway => { + return gateways_detailed( + state, + Query(SemverCompatibilityQueryParam::new(semver_compatibility)), + ) + .await + } + _ => {} + } + } + + Err(AxumErrorResponse::not_implemented()) +} + +#[utoipa::path( + tag = "Unstable Nym Nodes", + get, + params(SemverCompatibilityQueryParam), + path = "/v1/unstable/nym-nodes/gateways/skimmed", + responses( + (status = 200, body = CachedNodesResponse) + ) +)] +async fn gateways_basic( + state: State, + Query(SemverCompatibilityQueryParam { + semver_compatibility, + }): Query, +) -> AxumResult>> { + let status_cache = state.node_status_cache(); + let describe_cache = state.described_nodes_state(); + let gateways_cache = + status_cache + .gateways_cache() + .await + .ok_or(AxumErrorResponse::internal_msg( + "could not obtain gateways cache", + ))?; + + if gateways_cache.is_empty() { + return Ok(Json(CachedNodesResponse { + refreshed_at: gateways_cache.timestamp().into(), + nodes: vec![], + })); + } + + // if the self describe cache is unavailable don't try to use self-describe data + let Ok(self_descriptions) = describe_cache.get().await else { + return Ok(Json(CachedNodesResponse { + refreshed_at: gateways_cache.timestamp().into(), + nodes: gateways_cache.values().map(Into::into).collect(), + })); + }; + + let refreshed_at = min(gateways_cache.timestamp(), self_descriptions.timestamp()); + + // the same comment holds as with `get_gateways_described`. + // this is inefficient and will have to get refactored with directory v3 + Ok(Json(CachedNodesResponse { + refreshed_at: refreshed_at.into(), + nodes: gateways_cache + .values() + .filter(|annotated_bond| { + if let Some(semver_compatibility) = semver_compatibility.as_ref() { + version_checker::is_minor_version_compatible( + &annotated_bond.gateway_bond.gateway.version, + semver_compatibility, + ) + } else { + true + } + }) + .map(|annotated_bond| { + SkimmedNode::from_described_gateway( + annotated_bond, + self_descriptions.deref().get(annotated_bond.identity()), + ) + }) + .collect(), + })) +} + +#[utoipa::path( + tag = "Unstable Nym Nodes", + get, + params(SemverCompatibilityQueryParam), + path = "/v1/unstable/nym-nodes/gateways/semi-skimmed", + responses( + (status = 200, body = CachedNodesResponse) + ) +)] +async fn gateways_expanded( + State(_state): State, + Query(SemverCompatibilityQueryParam { + semver_compatibility: _semver_compatibility, + }): Query, +) -> AxumResult>> { + Err(AxumErrorResponse::not_implemented()) +} + +#[utoipa::path( + tag = "Unstable Nym Nodes", + get, + params(SemverCompatibilityQueryParam), + path = "/v1/unstable/nym-nodes/gateways/full-fat", + responses( + (status = 200, body = CachedNodesResponse) + ) +)] +async fn gateways_detailed( + State(_state): State, + Query(SemverCompatibilityQueryParam { + semver_compatibility: _semver_compatibility, + }): Query, +) -> AxumResult>> { + Err(AxumErrorResponse::not_implemented()) +} + +#[utoipa::path( + tag = "Unstable Nym Nodes", + get, + params(SemverCompatibilityQueryParam), + path = "/v1/unstable/nym-nodes/mixnodes/skimmed", + responses( + (status = 200, body = CachedNodesResponse) + ) +)] +async fn mixnodes_basic( + state: State, + Query(SemverCompatibilityQueryParam { + semver_compatibility, + }): Query, +) -> AxumResult>> { + let mixnodes_cache = state + .node_status_cache() + .active_mixnodes_cache() + .await + .ok_or(AxumErrorResponse::internal_msg( + "could not obtain mixnodes cache", + ))?; + Ok(Json(CachedNodesResponse { + refreshed_at: mixnodes_cache.timestamp().into(), + nodes: mixnodes_cache + .iter() + .filter(|annotated_bond| { + if let Some(semver_compatibility) = semver_compatibility.as_ref() { + version_checker::is_minor_version_compatible( + &annotated_bond + .mixnode_details + .bond_information + .mix_node + .version, + semver_compatibility, + ) + } else { + true + } + }) + .map(Into::into) + .collect(), + })) +} + +#[utoipa::path( + tag = "Unstable Nym Nodes", + get, + params(SemverCompatibilityQueryParam), + path = "/v1/unstable/nym-nodes/mixnodes/semi-skimmed", + responses( + (status = 200, body = CachedNodesResponse) + ) +)] +async fn mixnodes_expanded( + State(_state): State, + Query(SemverCompatibilityQueryParam { + semver_compatibility: _semver_compatibility, + }): Query, +) -> AxumResult>> { + Err(AxumErrorResponse::not_implemented()) +} + +#[utoipa::path( + tag = "Unstable Nym Nodes", + get, + params(SemverCompatibilityQueryParam), + path = "/v1/unstable/nym-nodes/mixnodes/full-fat", + responses( + (status = 200, body = CachedNodesResponse) + ) +)] +async fn mixnodes_detailed( + State(_state): State, + Query(SemverCompatibilityQueryParam { + semver_compatibility: _semver_compatibility, + }): Query, +) -> AxumResult>> { + Err(AxumErrorResponse::not_implemented()) +} diff --git a/nym-api/src/nym_nodes/mod.rs b/nym-api/src/nym_nodes/mod.rs index 350fd320a3..d7d5b98a7e 100644 --- a/nym-api/src/nym_nodes/mod.rs +++ b/nym-api/src/nym_nodes/mod.rs @@ -6,11 +6,16 @@ use rocket::Route; use rocket_okapi::openapi_get_routes_spec; use rocket_okapi::settings::OpenApiSettings; +#[cfg(feature = "axum")] +pub(crate) mod handlers; +#[cfg(feature = "axum")] +pub(crate) mod handlers_unstable; + pub(crate) mod routes; mod unstable_routes; /// Merges the routes with http information and returns it to Rocket for serving -pub(crate) fn nym_node_routes(settings: &OpenApiSettings) -> (Vec, OpenApi) { +pub(crate) fn nym_node_routes_deprecated(settings: &OpenApiSettings) -> (Vec, OpenApi) { openapi_get_routes_spec![ settings: routes::get_gateways_described, routes::get_mixnodes_described ] diff --git a/nym-api/src/nym_nodes/unstable_routes.rs b/nym-api/src/nym_nodes/unstable_routes.rs index 93692b9c22..aa12e5b7f3 100644 --- a/nym-api/src/nym_nodes/unstable_routes.rs +++ b/nym-api/src/nym_nodes/unstable_routes.rs @@ -2,7 +2,7 @@ // SPDX-License-Identifier: GPL-3.0-only use crate::node_describe_cache::DescribedNodes; -use crate::node_status_api::models::ErrorResponse; +use crate::node_status_api::models::RocketErrorResponse; use crate::node_status_api::NodeStatusCache; use crate::support::caching::cache::SharedCache; use nym_api_requests::nym_nodes::{ @@ -39,7 +39,7 @@ pub async fn nodes_basic( describe_cache: &State>, role: Option, semver_compatibility: Option, -) -> Result>, ErrorResponse> { +) -> Result>, RocketErrorResponse> { if let Some(role) = role { match role { NodeRoleQueryParam::ActiveMixnode => { @@ -52,7 +52,10 @@ pub async fn nodes_basic( } } - Err(ErrorResponse::new("unimplemented", Status::NotImplemented)) + Err(RocketErrorResponse::new( + "unimplemented", + Status::NotImplemented, + )) } #[openapi(tag = "Unstable Nym Nodes")] @@ -61,7 +64,7 @@ pub async fn nodes_expanded( cache: &State, role: Option, semver_compatibility: Option, -) -> Result>, ErrorResponse> { +) -> Result>, RocketErrorResponse> { if let Some(role) = role { match role { NodeRoleQueryParam::ActiveMixnode => { @@ -74,7 +77,10 @@ pub async fn nodes_expanded( } } - Err(ErrorResponse::new("unimplemented", Status::NotImplemented)) + Err(RocketErrorResponse::new( + "unimplemented", + Status::NotImplemented, + )) } #[openapi(tag = "Unstable Nym Nodes")] @@ -83,7 +89,7 @@ pub async fn nodes_detailed( cache: &State, role: Option, semver_compatibility: Option, -) -> Result>, ErrorResponse> { +) -> Result>, RocketErrorResponse> { if let Some(role) = role { match role { NodeRoleQueryParam::ActiveMixnode => { @@ -96,7 +102,10 @@ pub async fn nodes_detailed( } } - Err(ErrorResponse::new("unimplemented", Status::NotImplemented)) + Err(RocketErrorResponse::new( + "unimplemented", + Status::NotImplemented, + )) } #[openapi(tag = "Unstable Nym Nodes")] @@ -105,11 +114,11 @@ pub async fn gateways_basic( status_cache: &State, describe_cache: &State>, semver_compatibility: Option, -) -> Result>, ErrorResponse> { +) -> Result>, RocketErrorResponse> { let gateways_cache = status_cache .gateways_cache() .await - .ok_or(ErrorResponse::new( + .ok_or(RocketErrorResponse::new( "could not obtain gateways cache", Status::InternalServerError, ))?; @@ -162,10 +171,13 @@ pub async fn gateways_basic( pub async fn gateways_expanded( cache: &State, semver_compatibility: Option, -) -> Result>, ErrorResponse> { +) -> Result>, RocketErrorResponse> { let _ = cache; let _ = semver_compatibility; - Err(ErrorResponse::new("unimplemented", Status::NotImplemented)) + Err(RocketErrorResponse::new( + "unimplemented", + Status::NotImplemented, + )) } #[openapi(tag = "Unstable Nym Nodes")] @@ -173,10 +185,13 @@ pub async fn gateways_expanded( pub async fn gateways_detailed( cache: &State, semver_compatibility: Option, -) -> Result>, ErrorResponse> { +) -> Result>, RocketErrorResponse> { let _ = cache; let _ = semver_compatibility; - Err(ErrorResponse::new("unimplemented", Status::NotImplemented)) + Err(RocketErrorResponse::new( + "unimplemented", + Status::NotImplemented, + )) } #[openapi(tag = "Unstable Nym Nodes")] @@ -184,11 +199,11 @@ pub async fn gateways_detailed( pub async fn mixnodes_basic( cache: &State, semver_compatibility: Option, -) -> Result>, ErrorResponse> { +) -> Result>, RocketErrorResponse> { let mixnodes_cache = cache .active_mixnodes_cache() .await - .ok_or(ErrorResponse::new( + .ok_or(RocketErrorResponse::new( "could not obtain mixnodes cache", Status::InternalServerError, ))?; @@ -220,10 +235,13 @@ pub async fn mixnodes_basic( pub async fn mixnodes_expanded( cache: &State, semver_compatibility: Option, -) -> Result>, ErrorResponse> { +) -> Result>, RocketErrorResponse> { let _ = cache; let _ = semver_compatibility; - Err(ErrorResponse::new("unimplemented", Status::NotImplemented)) + Err(RocketErrorResponse::new( + "unimplemented", + Status::NotImplemented, + )) } #[openapi(tag = "Unstable Nym Nodes")] @@ -231,8 +249,11 @@ pub async fn mixnodes_expanded( pub async fn mixnodes_detailed( cache: &State, semver_compatibility: Option, -) -> Result>, ErrorResponse> { +) -> Result>, RocketErrorResponse> { let _ = cache; let _ = semver_compatibility; - Err(ErrorResponse::new("unimplemented", Status::NotImplemented)) + Err(RocketErrorResponse::new( + "unimplemented", + Status::NotImplemented, + )) } diff --git a/nym-api/src/status/handlers.rs b/nym-api/src/status/handlers.rs new file mode 100644 index 0000000000..ea34727f9a --- /dev/null +++ b/nym-api/src/status/handlers.rs @@ -0,0 +1,92 @@ +// Copyright 2024 - Nym Technologies SA +// SPDX-License-Identifier: GPL-3.0-only + +use crate::node_status_api::models::{AxumErrorResponse, AxumResult}; +use crate::status::ApiStatusState; +use crate::v2::AxumAppState; +use axum::Json; +use axum::Router; +use nym_api_requests::models::{ApiHealthResponse, SignerInformationResponse}; +use nym_bin_common::build_information::BinaryBuildInformationOwned; +use nym_compact_ecash::Base58; +use std::sync::Arc; + +pub(crate) fn api_status_routes() -> Router { + let api_status_state = Arc::new(ApiStatusState::new()); + + Router::new() + .route( + "/health", + axum::routing::get({ + let state = Arc::clone(&api_status_state); + || health(state) + }), + ) + .route( + "/build-information", + axum::routing::get({ + let state = Arc::clone(&api_status_state); + || build_information(state) + }), + ) + .route( + "/signer-information", + axum::routing::get({ + let state = Arc::clone(&api_status_state); + || signer_information(state) + }), + ) +} + +#[utoipa::path( + tag = "API Status", + get, + path = "/v1/api-status/health", + responses( + (status = 200, body = ApiHealthResponse) + ) +)] +async fn health(state: Arc) -> Json { + let uptime = state.startup_time.elapsed(); + let health = ApiHealthResponse::new_healthy(uptime); + Json(health) +} + +#[utoipa::path( + tag = "API Status", + get, + path = "/v1/api-status/build-information", + responses( + (status = 200, body = BinaryBuildInformationOwned) + ) +)] +async fn build_information(state: Arc) -> Json { + Json(state.build_information.to_owned()) +} + +#[utoipa::path( + tag = "API Status", + get, + path = "/v1/api-status/signer-information", + responses( + (status = 200, body = SignerInformationResponse) + ) +)] +async fn signer_information( + state: Arc, +) -> AxumResult> { + let signer_state = state.signer_information.as_ref().ok_or_else(|| { + AxumErrorResponse::internal_msg("this api does not expose zk-nym signing functionalities") + })?; + + Ok(Json(SignerInformationResponse { + cosmos_address: signer_state.cosmos_address.clone(), + identity: signer_state.identity.clone(), + announce_address: signer_state.announce_address.clone(), + verification_key: signer_state + .coconut_keypair + .verification_key() + .await + .map(|maybe_vk| maybe_vk.to_bs58()), + })) +} diff --git a/nym-api/src/status/mod.rs b/nym-api/src/status/mod.rs index 053cb8ba88..1d09b341c8 100644 --- a/nym-api/src/status/mod.rs +++ b/nym-api/src/status/mod.rs @@ -10,6 +10,8 @@ use rocket_okapi::openapi_get_routes_spec; use rocket_okapi::settings::OpenApiSettings; use tokio::time::Instant; +#[cfg(feature = "axum")] +pub(crate) mod handlers; pub(crate) mod routes; pub(crate) struct ApiStatusState { diff --git a/nym-api/src/status/routes.rs b/nym-api/src/status/routes.rs index 560ac765d9..804744df18 100644 --- a/nym-api/src/status/routes.rs +++ b/nym-api/src/status/routes.rs @@ -1,7 +1,7 @@ // Copyright 2024 - Nym Technologies SA // SPDX-License-Identifier: GPL-3.0-only -use crate::node_status_api::models::ErrorResponse; +use crate::node_status_api::models::RocketErrorResponse; use crate::status::ApiStatusState; use nym_api_requests::models::{ApiHealthResponse, SignerInformationResponse}; use nym_bin_common::build_information::BinaryBuildInformationOwned; @@ -31,9 +31,9 @@ pub(crate) async fn build_information( #[get("/signer-information")] pub(crate) async fn signer_information( state: &State, -) -> Result, ErrorResponse> { +) -> Result, RocketErrorResponse> { let signer_state = state.signer_information.as_ref().ok_or_else(|| { - ErrorResponse::new( + RocketErrorResponse::new( "this api does not expose zk-nym signing functionalities", Status::InternalServerError, ) diff --git a/nym-api/src/support/cli/run.rs b/nym-api/src/support/cli/run.rs index 9bb58c585e..a19d2c1c29 100644 --- a/nym-api/src/support/cli/run.rs +++ b/nym-api/src/support/cli/run.rs @@ -3,7 +3,7 @@ use crate::start_nym_api_tasks; use crate::support::config::helpers::try_load_current_config; -use anyhow::bail; +use cfg_if::cfg_if; #[derive(clap::Args, Debug)] pub(crate) struct Args { @@ -43,7 +43,7 @@ pub(crate) struct Args { pub(crate) enable_zk_nym: Option, /// Announced address that is going to be put in the DKG contract where zk-nym clients will connect - /// to obtain their credentials + /// to obtain their credentials /// default: None - config value will be used instead #[clap(long)] pub(crate) announce_address: Option, @@ -62,18 +62,40 @@ pub(crate) async fn execute(args: Args) -> anyhow::Result<()> { config.validate()?; - let mut shutdown_handlers = start_nym_api_tasks(config).await?; + #[cfg(feature = "axum")] + let mut axum_shutdown = crate::v2::start_nym_api_tasks_v2(&config).await?; + let mut rocket_shutdown = start_nym_api_tasks(config).await?; + + // it doesn't matter which server catches the interrupt: it needs only be caught once + if let Err(err) = rocket_shutdown.task_manager_handle.catch_interrupt().await { + error!("Error stopping Rocket tasks: {err}"); + } - let res = shutdown_handlers - .task_manager_handle - .catch_interrupt() - .await; log::info!("Stopping nym API"); - shutdown_handlers.rocket_handle.notify(); + rocket_shutdown.rocket_handle.notify(); - if let Err(err) = res { - // that's a nasty workaround, but anyhow errors are generally nicer, especially on exit - bail!("{err}") + // because Rocket caught the interrupt, it had already signalled its + // background tasks to retire. Now do that for axum + cfg_if! { + if #[cfg(feature = "axum")] { + axum_shutdown.task_manager_mut().signal_shutdown().ok(); + axum_shutdown.task_manager_mut().wait_for_shutdown().await; + + let running_server = axum_shutdown.shutdown_axum(); + + match running_server.await { + Ok(Ok(_)) => { + info!("Axum HTTP server shut down without errors"); + }, + Ok(Err(err)) => { + error!("Axum HTTP server terminated with: {err}"); + anyhow::bail!(err) + }, + Err(err) => { + error!("Server task panicked: {err}"); + } + }; + } } Ok(()) diff --git a/nym-api/src/support/config/mod.rs b/nym-api/src/support/config/mod.rs index c5191b7960..a26384652f 100644 --- a/nym-api/src/support/config/mod.rs +++ b/nym-api/src/support/config/mod.rs @@ -16,6 +16,7 @@ use nym_config::{ }; use serde::{Deserialize, Serialize}; use std::io; +use std::net::{IpAddr, Ipv4Addr, SocketAddr}; use std::path::{Path, PathBuf}; use std::time::Duration; use url::Url; @@ -225,6 +226,17 @@ impl Config { } } +// TODO rocket: when axum becomes the main server, change its bind addr default here +fn default_http_socket_addr() -> SocketAddr { + cfg_if::cfg_if! { + if #[cfg(debug_assertions)] { + SocketAddr::new(IpAddr::V4(Ipv4Addr::LOCALHOST), 8081) + } else { + SocketAddr::new(IpAddr::V4(Ipv4Addr::UNSPECIFIED), 8081) + } + } +} + // we only really care about the mnemonic being zeroized #[derive(Debug, Deserialize, PartialEq, Eq, Serialize, Zeroize, ZeroizeOnDrop)] pub struct Base { @@ -234,6 +246,11 @@ pub struct Base { #[zeroize(skip)] pub local_validator: Url, + /// Socket address Axum will use for binding its HTTP API. + #[zeroize(skip)] + #[serde(default = "default_http_socket_addr")] + pub bind_address: SocketAddr, + /// Mnemonic used for rewarding and/or multisig operations // TODO: similarly to the note in gateway, this should get moved to a separate file #[serde(deserialize_with = "de_maybe_stringified")] @@ -256,6 +273,7 @@ impl Base { storage_paths: NymApiPaths::new_default(&id), id, local_validator: default_validator, + bind_address: default_http_socket_addr(), mnemonic: None, } } diff --git a/nym-api/src/support/config/template.rs b/nym-api/src/support/config/template.rs index 170cc73ba3..108cc0f426 100644 --- a/nym-api/src/support/config/template.rs +++ b/nym-api/src/support/config/template.rs @@ -15,6 +15,10 @@ id = '{{ base.id }}' # Validator server to which the API will be getting information about the network. local_validator = '{{ base.local_validator }}' +# Socket address this api will use for binding its http API. +# Note: only used if `axum` feature is enabled. +bind_address = '{{ base.bind_address }}' + # Mnemonic used for rewarding and validator interaction mnemonic = '{{ base.mnemonic }}' @@ -58,7 +62,7 @@ route_test_packets = {{ network_monitor.debug.route_test_packets }} # Number of test packets sent to each node during regular monitor test run. per_node_test_packets = {{ network_monitor.debug.per_node_test_packets }} - + ##### node status api config options ##### diff --git a/nym-api/src/support/http/mod.rs b/nym-api/src/support/http/mod.rs index a0696d4955..612dcb9333 100644 --- a/nym-api/src/support/http/mod.rs +++ b/nym-api/src/support/http/mod.rs @@ -8,19 +8,18 @@ use crate::ecash::{self, comm::QueryCommunicationChannel}; use crate::network::models::NetworkDetails; use crate::network::network_routes; use crate::node_describe_cache::DescribedNodes; -use crate::node_status_api::routes::unstable; +use crate::node_status_api::routes_deprecated::unstable; use crate::node_status_api::{self, NodeStatusCache}; use crate::nym_contract_cache::cache::NymContractCache; -use crate::nym_nodes::nym_node_routes_next; +use crate::nym_nodes::{nym_node_routes_deprecated, nym_node_routes_next}; use crate::status::{api_status_routes, ApiStatusState, SignerState}; use crate::support::caching::cache::SharedCache; use crate::support::config::Config; use crate::support::{nyxd, storage}; -use crate::{circulating_supply_api, nym_contract_cache, nym_nodes::nym_node_routes}; +use crate::{circulating_supply_api, nym_contract_cache}; use anyhow::{bail, Context, Result}; use nym_crypto::asymmetric::identity; use nym_validator_client::nyxd::Coin; -use rocket::http::Method; use rocket::{Ignite, Rocket}; use rocket_cors::{AllowedHeaders, AllowedOrigins, Cors}; use rocket_okapi::mount_endpoints_and_merged_docs; @@ -52,33 +51,26 @@ pub(crate) async fn setup_rocket( "/network" => network_routes(&openapi_settings), "/api-status" => api_status_routes(&openapi_settings), "/ecash" => ecash::routes_open_api(&openapi_settings, config.coconut_signer.enabled), - "" => nym_node_routes(&openapi_settings), + "" => nym_node_routes_deprecated(&openapi_settings), // => when we move those routes, we'll need to add a redirection for backwards compatibility "/unstable/nym-nodes" => nym_node_routes_next(&openapi_settings) } + let storage = + storage::NymApiStorage::init(&config.node_status_api.storage_paths.database_path).await?; + let rocket = rocket .manage(network_details) .manage(SharedCache::::new()) .mount("/swagger", make_swagger_ui(&openapi::get_docs())) - .attach(setup_cors()?) + .attach(setup_rocket_cors()?) .attach(NymContractCache::stage()) .attach(NodeStatusCache::stage()) .attach(CirculatingSupplyCache::stage(mix_denom.clone())) + .attach(storage::NymApiStorage::stage(storage.clone())) .manage(unstable::NodeInfoCache::default()); - // This is not a very nice approach. A lazy value would be more suitable, but that's still - // a nightly feature: https://github.com/rust-lang/rust/issues/74465 - let storage = if config.coconut_signer.enabled || config.network_monitor.enabled { - Some( - storage::NymApiStorage::init(&config.node_status_api.storage_paths.database_path) - .await?, - ) - } else { - None - }; - let mut status_state = ApiStatusState::new(); let rocket = if config.coconut_signer.enabled { @@ -117,7 +109,7 @@ pub(crate) async fn setup_rocket( identity_keypair, coconut_keypair, comm_channel, - storage.clone().unwrap(), + storage.clone(), ) .await?; @@ -126,23 +118,16 @@ pub(crate) async fn setup_rocket( rocket }; - // see if we should start up network monitor - let rocket = if config.network_monitor.enabled { - rocket.attach(storage::NymApiStorage::stage(storage.unwrap())) - } else { - rocket - }; - Ok(rocket.manage(status_state).ignite().await?) } -fn setup_cors() -> Result { +fn setup_rocket_cors() -> Result { let allowed_origins = AllowedOrigins::all(); // You can also deserialize this let cors = rocket_cors::CorsOptions { allowed_origins, - allowed_methods: vec![Method::Post, Method::Get] + allowed_methods: vec![rocket::http::Method::Post, rocket::http::Method::Get] .into_iter() .map(From::from) .collect(), diff --git a/nym-api/src/support/storage/mod.rs b/nym-api/src/support/storage/mod.rs index 32621aa619..d4cdc64c02 100644 --- a/nym-api/src/support/storage/mod.rs +++ b/nym-api/src/support/storage/mod.rs @@ -64,6 +64,7 @@ impl NymApiStorage { Ok(storage) } + #[deprecated(note = "TODO rocket: obsolete because it's used for Rocket")] pub(crate) fn stage(storage: NymApiStorage) -> AdHoc { AdHoc::try_on_ignite("SQLx Database", |rocket| async { Ok(rocket.manage(storage)) diff --git a/nym-api/src/v2/api_docs.rs b/nym-api/src/v2/api_docs.rs new file mode 100644 index 0000000000..9b248bb803 --- /dev/null +++ b/nym-api/src/v2/api_docs.rs @@ -0,0 +1,85 @@ +// Copyright 2023 - Nym Technologies SA +// SPDX-License-Identifier: GPL-3.0-only + +use crate::network::handlers::ContractVersionSchemaResponse; +use nym_api_requests::models; +use utoipa::OpenApi; +use utoipauto::utoipauto; + +// TODO once https://github.com/ProbablyClem/utoipauto/pull/38 is released: +// include ",./nym-api/nym-api-requests/src from nym-api-requests" (and other packages mentioned below) +// for automatic model discovery based on ToSchema / IntoParams implementation. +// Then you can remove `components(schemas)` manual imports below + +#[utoipauto(paths = "./nym-api/src")] +#[derive(OpenApi)] +#[openapi( + info(title = "Nym API"), + tags(), + components(schemas( + models::CirculatingSupplyResponse, + models::CoinSchema, + nym_mixnet_contract_common::Interval, + nym_api_requests::models::GatewayStatusReportResponse, + nym_api_requests::models::GatewayUptimeHistoryResponse, + nym_api_requests::models::HistoricalUptimeResponse, + nym_api_requests::models::GatewayCoreStatusResponse, + nym_api_requests::models::GatewayUptimeResponse, + nym_api_requests::models::RewardEstimationResponse, + nym_api_requests::models::UptimeResponse, + nym_api_requests::models::ComputeRewardEstParam, + nym_api_requests::models::MixNodeBondAnnotated, + nym_api_requests::models::GatewayBondAnnotated, + nym_api_requests::models::MixnodeTestResultResponse, + nym_api_requests::models::StakeSaturationResponse, + nym_api_requests::models::InclusionProbabilityResponse, + nym_api_requests::models::AllInclusionProbabilitiesResponse, + nym_api_requests::models::InclusionProbability, + nym_api_requests::models::SelectionChance, + crate::network::models::NetworkDetails, + nym_config::defaults::NymNetworkDetails, + nym_config::defaults::ChainDetails, + nym_config::defaults::DenomDetailsOwned, + nym_config::defaults::ValidatorDetails, + nym_config::defaults::NymContracts, + ContractVersionSchemaResponse, + crate::network::models::ContractInformation, + nym_api_requests::models::ApiHealthResponse, + nym_api_requests::models::ApiStatus, + nym_bin_common::build_information::BinaryBuildInformationOwned, + nym_api_requests::models::SignerInformationResponse, + nym_api_requests::models::DescribedGateway, + nym_api_requests::models::MixNodeDetailsSchema, + nym_mixnet_contract_common::Gateway, + nym_mixnet_contract_common::GatewayBond, + nym_api_requests::models::NymNodeDescription, + nym_api_requests::models::HostInformation, + nym_api_requests::models::HostKeys, + nym_node_requests::api::v1::node::models::AuxiliaryDetails, + nym_api_requests::models::NetworkRequesterDetails, + nym_api_requests::models::IpPacketRouterDetails, + nym_api_requests::models::AuthenticatorDetails, + nym_api_requests::models::WebSockets, + nym_api_requests::nym_nodes::NodeRole, + nym_api_requests::models::DescribedMixNode, + nym_api_requests::ecash::VerificationKeyResponse, + nym_api_requests::ecash::models::AggregatedExpirationDateSignatureResponse, + nym_api_requests::ecash::models::AggregatedCoinIndicesSignatureResponse, + nym_api_requests::ecash::models::EpochCredentialsResponse, + nym_api_requests::ecash::models::IssuedCredentialResponse, + nym_api_requests::ecash::models::IssuedTicketbookBody, + nym_api_requests::ecash::models::BlindedSignatureResponse, + nym_api_requests::ecash::models::PartialExpirationDateSignatureResponse, + nym_api_requests::ecash::models::PartialCoinIndicesSignatureResponse, + nym_api_requests::ecash::models::EcashTicketVerificationResponse, + nym_api_requests::ecash::models::EcashTicketVerificationRejection, + nym_api_requests::ecash::models::EcashBatchTicketRedemptionResponse, + nym_api_requests::ecash::models::SpentCredentialsResponse, + nym_api_requests::ecash::models::IssuedCredentialsResponse, + nym_api_requests::nym_nodes::SkimmedNode, + nym_api_requests::nym_nodes::BasicEntryInformation, + nym_api_requests::nym_nodes::SemiSkimmedNode, + nym_api_requests::nym_nodes::NodeRoleQueryParam, + )) +)] +pub(super) struct ApiDoc; diff --git a/nym-api/src/v2/mod.rs b/nym-api/src/v2/mod.rs new file mode 100644 index 0000000000..59109d16b7 --- /dev/null +++ b/nym-api/src/v2/mod.rs @@ -0,0 +1,313 @@ +// Copyright 2023 - Nym Technologies SA +// SPDX-License-Identifier: GPL-3.0-only + +use super::support::nyxd; +use crate::circulating_supply_api::cache::CirculatingSupplyCache; +use crate::ecash::api_routes::handlers::ecash_routes; +use crate::ecash::client::Client; +use crate::ecash::comm::QueryCommunicationChannel; +use crate::ecash::dkg::controller::keys::{ + can_validate_coconut_keys, load_bte_keypair, load_ecash_keypair_if_exists, +}; +use crate::ecash::dkg::controller::DkgController; +use crate::ecash::state::EcashState; +use crate::epoch_operations::{self, RewardedSetUpdater}; +use crate::network::models::NetworkDetails; +use crate::node_describe_cache::{self, DescribedNodes}; +use crate::node_status_api::handlers::unstable; +use crate::node_status_api::uptime_updater::HistoricalUptimeUpdater; +use crate::node_status_api::{self, NodeStatusCache}; +use crate::nym_contract_cache::cache::NymContractCache; +use crate::status::{ApiStatusState, SignerState}; +use crate::support::caching::cache::SharedCache; +use crate::support::config::Config; +use crate::support::storage; +use crate::{circulating_supply_api, ecash, network_monitor, nym_contract_cache}; +use anyhow::{bail, Context}; +use nym_config::defaults::NymNetworkDetails; +use nym_sphinx::receiver::SphinxMessageReceiver; +use nym_task::TaskManager; +use nym_validator_client::nyxd::Coin; +use router::RouterBuilder; +use std::sync::Arc; +use tokio::task::JoinHandle; +use tokio_util::sync::CancellationToken; + +pub(crate) mod api_docs; +pub(crate) mod router; + +const TASK_MANAGER_TIMEOUT_S: u64 = 10; + +/// Shutdown goes 2 directions: +/// 1. signal background tasks to gracefully finish +/// 2. signal server itself +/// +/// These are done through separate shutdown handles. Ofcourse, shut down server +/// AFTER you have shut down BG tasks (or past their grace period). +pub(crate) struct ShutdownHandles { + task_manager: TaskManager, + axum_shutdown_button: ShutdownAxum, + /// Tokio JoinHandle for axum server's task + axum_join_handle: AxumJoinHandle, +} + +impl ShutdownHandles { + /// Cancellation token is given to Axum server constructor. When the token + /// receives a shutdown signal, Axum server will shut down gracefully. + pub(crate) fn new( + task_manager: TaskManager, + axum_server_handle: AxumJoinHandle, + shutdown_button: CancellationToken, + ) -> Self { + Self { + task_manager, + axum_shutdown_button: ShutdownAxum(shutdown_button.clone()), + axum_join_handle: axum_server_handle, + } + } + + pub(crate) fn task_manager_mut(&mut self) -> &mut TaskManager { + &mut self.task_manager + } + + /// Signal server to shut down, then return join handle to its + /// `tokio` task + /// + /// https://tikv.github.io/doc/tokio/task/struct.JoinHandle.html + #[must_use] + pub(crate) fn shutdown_axum(self) -> AxumJoinHandle { + self.axum_shutdown_button.0.cancel(); + self.axum_join_handle + } +} + +struct ShutdownAxum(CancellationToken); + +type AxumJoinHandle = JoinHandle>; + +#[derive(Clone)] +// TODO rocket remove smurf name after eliminating rocket +pub(crate) struct AxumAppState { + nym_contract_cache: NymContractCache, + node_status_cache: NodeStatusCache, + circulating_supply_cache: CirculatingSupplyCache, + storage: storage::NymApiStorage, + described_nodes_state: SharedCache, + network_details: NetworkDetails, + node_info_cache: unstable::NodeInfoCache, +} + +impl AxumAppState { + pub(crate) fn nym_contract_cache(&self) -> &NymContractCache { + &self.nym_contract_cache + } + + pub(crate) fn node_status_cache(&self) -> &NodeStatusCache { + &self.node_status_cache + } + + pub(crate) fn circulating_supply_cache(&self) -> &CirculatingSupplyCache { + &self.circulating_supply_cache + } + + pub(crate) fn network_details(&self) -> &NetworkDetails { + &self.network_details + } + + pub(crate) fn described_nodes_state(&self) -> &SharedCache { + &self.described_nodes_state + } + + pub(crate) fn storage(&self) -> &storage::NymApiStorage { + &self.storage + } + + pub(crate) fn node_info_cache(&self) -> &unstable::NodeInfoCache { + &self.node_info_cache + } +} + +pub(crate) async fn start_nym_api_tasks_v2(config: &Config) -> anyhow::Result { + let nyxd_client = nyxd::Client::new(config); + let connected_nyxd = config.get_nyxd_url(); + let nym_network_details = NymNetworkDetails::new_from_env(); + let network_details = NetworkDetails::new(connected_nyxd.to_string(), nym_network_details); + + let coconut_keypair = ecash::keys::KeyPair::new(); + + // if the keypair doesnt exist (because say this API is running in the caching mode), nothing will happen + if let Some(loaded_keys) = load_ecash_keypair_if_exists(&config.coconut_signer)? { + let issued_for = loaded_keys.issued_for_epoch; + coconut_keypair.set(loaded_keys).await; + + if can_validate_coconut_keys(&nyxd_client, issued_for).await? { + coconut_keypair.validate() + } + } + + let identity_keypair = config.base.storage_paths.load_identity()?; + let identity_public_key = *identity_keypair.public_key(); + + let router = RouterBuilder::with_default_routes(config.network_monitor.enabled); + + let nym_contract_cache_state = NymContractCache::new(); + let node_status_cache_state = NodeStatusCache::new(); + let mix_denom = network_details.network.chain_details.mix_denom.base.clone(); + let circulating_supply_cache = CirculatingSupplyCache::new(mix_denom.to_owned()); + let described_nodes_state = SharedCache::::new(); + let storage = + storage::NymApiStorage::init(&config.node_status_api.storage_paths.database_path).await?; + let node_info_cache = unstable::NodeInfoCache::default(); + + let mut status_state = ApiStatusState::new(); + + // if coconut signer is enabled, add /coconut to server + let router = if config.coconut_signer.enabled { + // make sure we have some tokens to cover multisig fees + let balance = nyxd_client.balance(&mix_denom).await?; + if balance.amount < ecash::MINIMUM_BALANCE { + let address = nyxd_client.address().await; + let min = Coin::new(ecash::MINIMUM_BALANCE, mix_denom); + bail!("the account ({address}) doesn't have enough funds to cover verification fees. it has {balance} while it needs at least {min}") + } + + let cosmos_address = nyxd_client.address().await.to_string(); + let announce_address = config + .coconut_signer + .announce_address + .clone() + .map(|u| u.to_string()) + .unwrap_or_default(); + status_state.add_zk_nym_signer(SignerState { + cosmos_address, + identity: identity_keypair.public_key().to_base58_string(), + announce_address, + coconut_keypair: coconut_keypair.clone(), + }); + + let ecash_contract = nyxd_client + .get_ecash_contract_address() + .await + .context("e-cash contract address is required to setup the zk-nym signer")?; + + let comm_channel = QueryCommunicationChannel::new(nyxd_client.clone()); + + let ecash_state = EcashState::new( + ecash_contract, + nyxd_client.clone(), + identity_keypair, + coconut_keypair.clone(), + comm_channel, + storage.clone(), + ) + .await?; + + router.nest("/v1/ecash", ecash_routes(Arc::new(ecash_state))) + } else { + router + }; + + let router = router.with_state(AxumAppState { + nym_contract_cache: nym_contract_cache_state.clone(), + node_status_cache: node_status_cache_state.clone(), + circulating_supply_cache: circulating_supply_cache.clone(), + storage: storage.clone(), + described_nodes_state: described_nodes_state.clone(), + network_details, + node_info_cache, + }); + + let task_manager = TaskManager::new(TASK_MANAGER_TIMEOUT_S); + + // start note describe cache refresher + // we should be doing the below, but can't due to our current startup structure + // let refresher = node_describe_cache::new_refresher(&config.topology_cacher); + // let cache = refresher.get_shared_cache(); + node_describe_cache::new_refresher_with_initial_value( + &config.topology_cacher, + nym_contract_cache_state.clone(), + described_nodes_state, + ) + .named("node-self-described-data-refresher") + .start(task_manager.subscribe_named("node-self-described-data-refresher")); + + // start all the caches first + let nym_contract_cache_listener = nym_contract_cache::start_refresher( + &config.node_status_api, + &nym_contract_cache_state, + nyxd_client.clone(), + &task_manager, + ); + node_status_api::start_cache_refresh( + &config.node_status_api, + &nym_contract_cache_state, + &node_status_cache_state, + storage.clone(), + nym_contract_cache_listener, + &task_manager, + ); + circulating_supply_api::start_cache_refresh( + &config.circulating_supply_cacher, + nyxd_client.clone(), + &circulating_supply_cache, + &task_manager, + ); + + // start dkg task + if config.coconut_signer.enabled { + let dkg_bte_keypair = load_bte_keypair(&config.coconut_signer)?; + + DkgController::start( + &config.coconut_signer, + nyxd_client.clone(), + coconut_keypair, + dkg_bte_keypair, + identity_public_key, + rand::rngs::OsRng, + &task_manager, + )?; + } + + // and then only start the uptime updater (and the monitor itself, duh) + // if the monitoring is enabled + if config.network_monitor.enabled { + network_monitor::start::( + &config.network_monitor, + &nym_contract_cache_state, + &storage, + nyxd_client.clone(), + &task_manager, + ) + .await; + + HistoricalUptimeUpdater::start(storage.to_owned(), &task_manager); + + // start 'rewarding' if its enabled + if config.rewarding.enabled { + epoch_operations::ensure_rewarding_permission(&nyxd_client).await?; + RewardedSetUpdater::start( + nyxd_client, + &nym_contract_cache_state, + storage, + &task_manager, + ); + } + } + + let bind_address = config.base.bind_address.to_owned(); + let server = router.build_server(&bind_address).await?; + + let cancellation_token = CancellationToken::new(); + let shutdown_button = cancellation_token.clone(); + let axum_shutdown_receiver = cancellation_token.cancelled_owned(); + let server_handle = tokio::spawn(async move { + { + info!("Started Axum HTTP V2 server on {bind_address}"); + server.run(axum_shutdown_receiver).await + } + }); + + let shutdown = ShutdownHandles::new(task_manager, server_handle, shutdown_button); + + Ok(shutdown) +} diff --git a/nym-api/src/v2/router.rs b/nym-api/src/v2/router.rs new file mode 100644 index 0000000000..6ece0b7323 --- /dev/null +++ b/nym-api/src/v2/router.rs @@ -0,0 +1,136 @@ +// Copyright 2023 - Nym Technologies SA +// SPDX-License-Identifier: GPL-3.0-only + +use crate::circulating_supply_api::handlers::circulating_supply_routes; +use crate::network::handlers::nym_network_routes; +use crate::node_status_api::handlers::node_status_routes; +use crate::nym_contract_cache::handlers::nym_contract_cache_routes; +use crate::nym_nodes::handlers::nym_node_routes; +use crate::nym_nodes::handlers_unstable::nym_node_routes_unstable; +use crate::status; +use crate::v2::AxumAppState; +use anyhow::anyhow; +use axum::Router; +use core::net::SocketAddr; +use nym_http_api_common::logging::logger; +use tokio::net::TcpListener; +use tokio_util::sync::WaitForCancellationFutureOwned; +use tower_http::cors::CorsLayer; +use utoipa::OpenApi; +use utoipa_swagger_ui::SwaggerUi; + +/// Wrapper around `axum::Router` which ensures correct [order of layers][order]. +/// Add new routes as if you were working directly with `axum`. +/// +/// Why? Middleware like logger, CORS, TLS which need to handle request before other +/// layers should be added last. Using this builder pattern ensures that. +/// +/// [order]: https://docs.rs/axum/latest/axum/middleware/index.html#ordering +pub(crate) struct RouterBuilder { + unfinished_router: Router, +} + +impl RouterBuilder { + /// All routes should be, if possible, added here. Exceptions are e.g. + /// routes which are added conditionally in other places based on some `if`. + pub(crate) fn with_default_routes(network_monitor: bool) -> Self { + // https://docs.rs/tower-http/0.1.1/tower_http/trace/index.html + // TODO rocket use tracing instead of env_logger + // https://github.com/tokio-rs/axum/blob/main/examples/tracing-aka-logging/src/main.rs + // .layer( + // TraceLayer::new_for_http() + // .make_span_with(DefaultMakeSpan::new().include_headers(true)) + // .on_request(DefaultOnRequest::new()) + // .on_response(DefaultOnResponse::new().latency_unit(tower_http::LatencyUnit::Micros)), + // ) + // .route("/", axum::routing::get(|| async {axum::response::Redirect::permanent("/swagger")})) + // .route("/swagger", axum::routing::get(hello)) + let default_routes = Router::new() + .merge( + SwaggerUi::new("/swagger") + .url("/api-docs/openapi.json", super::api_docs::ApiDoc::openapi()), + ) + .nest( + "/v1", + Router::new() + .nest("/circulating-supply", circulating_supply_routes()) + .merge(nym_contract_cache_routes()) + .nest("/status", node_status_routes(network_monitor)) + .nest("/network", nym_network_routes()) + .nest("/api-status", status::handlers::api_status_routes()) + .merge(nym_node_routes()) + .nest("/unstable/nym-nodes", nym_node_routes_unstable()), // CORS layer needs to be "outside" of routes + ); + + Self { + unfinished_router: default_routes, + } + } + + pub(crate) fn nest(self, path: &str, router: Router) -> Self { + Self { + unfinished_router: self.unfinished_router.nest(path, router), + } + } + + /// Invoke this as late as possible before constructing HTTP server + /// (after all routes were added). + pub(crate) fn with_state(self, state: AxumAppState) -> RouterWithState { + RouterWithState { + router: self.finalize_routes().with_state(state), + } + } + + /// Middleware added here intercepts the request before it gets to other routes. + fn finalize_routes(self) -> Router { + self.unfinished_router + .layer(setup_cors()) + .layer(axum::middleware::from_fn(logger)) + } +} + +fn setup_cors() -> CorsLayer { + CorsLayer::new() + .allow_origin(tower_http::cors::Any) + .allow_methods([axum::http::Method::GET, axum::http::Method::POST]) + .allow_headers(tower_http::cors::Any) + .allow_credentials(false) +} + +pub(crate) struct RouterWithState { + router: Router, +} + +impl RouterWithState { + pub(crate) async fn build_server( + self, + bind_address: &SocketAddr, + ) -> anyhow::Result { + let listener = tokio::net::TcpListener::bind(bind_address) + .await + .map_err(|err| anyhow!("Couldn't bind to address {} due to {}", bind_address, err))?; + + Ok(ApiHttpServer { + router: self.router, + listener, + }) + } +} + +pub(crate) struct ApiHttpServer { + router: Router, + listener: TcpListener, +} + +impl ApiHttpServer { + pub async fn run(self, receiver: WaitForCancellationFutureOwned) -> Result<(), std::io::Error> { + // into_make_service_with_connect_info allows us to see client ip address + axum::serve( + self.listener, + self.router + .into_make_service_with_connect_info::(), + ) + .with_graceful_shutdown(receiver) + .await + } +} diff --git a/nym-node/tests/definitions.sh b/nym-node/tests/definitions.sh new file mode 100755 index 0000000000..80b6886aa4 --- /dev/null +++ b/nym-node/tests/definitions.sh @@ -0,0 +1,217 @@ +#!/bin/bash + +# color codes +GREEN='\033[0;32m' +RED='\033[0;31m' +BLUE='\033[0;34m' +DEFAULT='\033[0m' + +axum_server_addr="http://localhost:8081" +rocket_server_addr="http://localhost:8000" + +function compare_responses() { + local api="$1" + shift + local url_1="${axum_server_addr}${api}" + local url_2="${rocket_server_addr}${api}" + + local response_1=$(curl -s "${url_1}") + local normalized_resp_1=$(echo "${response_1}" | jq --sort-keys '.') + local response_2=$(curl -s "${url_2}") + local normalized_resp_2=$(echo "${response_2}" | jq --sort-keys '.') + + echo -e "Response: \n${response_1}" + # jq . "${response_1}" + + if [[ "${response_1}" == "${response_2}" ]]; then + # if cmp -s <(jq -S . "$response_1") <(jq -S ."$response_2"); then + echo -e "${GREEN}Responses are the same ${DEFAULT}" + else + echo -e "${RED}" + echo "${response_2}" + # jq . "${response_2}" + echo -e "Responses are different" + diff <(echo "${normalized_resp_1}") <(echo "${normalized_resp_2}") + echo -e "${DEFAULT}" + fi +} + +function validate_response() { + local expected_status="$1" + shift + local url=("$@") + local query=(curl -I -X 'GET' "${url[@]}" -H 'accept: application/json') + # execute given curl + echo -e "Executing\n${BLUE}\t${query[*]}${DEFAULT}" + local response=$("${query[@]}" -w "\n%{http_code}\n%{content_type}") + + # parse status code & content type + local http_code=$(echo "$response" | tail -n2 | head -n1) + local content_type=$(echo "$response" | tail -n1) + + # -e flag for coloured output + if [ "$http_code" -eq "$expected_status" ]; then + echo -e "${GREEN}HTTP code $http_code as expected, Content-Type is $content_type ${DEFAULT}" + return 0 + else + echo -e "${RED}Unexpected HTTP code: $http_code, Content-Type is $content_type ${DEFAULT}" + return 1 + fi +} + +function title() { + local title="$1" + echo -e "\n${BLUE}\t╔═══ ${title} ═══╗${DEFAULT}" +} + +function circulating_supply() { + title "/circulating-supply" + + local api="/v1/circulating-supply" + validate_response 200 "${target_address}${api}" + compare_responses ${api} + + local api="/v1/circulating-supply/total-supply-value" + validate_response 200 "${target_address}${api}" + compare_responses ${api} + + local api="/v1/circulating-supply/circulating-supply-value" + validate_response 200 "${target_address}${api}" + compare_responses ${api} +} + +function contract_cache() { + title "/contract-cache" + + local api="/v1/mixnodes" + validate_response 200 "${target_address}${api}" + compare_responses ${api} + + local api="/v1/mixnodes/detailed" + validate_response 200 "${target_address}${api}" + compare_responses ${api} + + local api="/v1/gateways" + validate_response 200 "${target_address}${api}" + compare_responses ${api} + + local api="/v1/mixnodes/active" + validate_response 200 "${target_address}${api}" + compare_responses ${api} + + local api="/v1/mixnodes/active/detailed" + validate_response 200 "${target_address}${api}" + compare_responses ${api} + + local api="/v1/mixnodes/rewarded" + validate_response 200 "${target_address}${api}" + compare_responses ${api} + + local api="/v1/mixnodes/rewarded/detailed" + validate_response 200 "${target_address}${api}" + compare_responses ${api} + + local api="/v1/mixnodes/blacklisted" + validate_response 200 "${target_address}${api}" + compare_responses ${api} + + local api="/v1/gateways/blacklisted" + validate_response 200 "${target_address}${api}" + compare_responses ${api} + + local api="/v1/epoch/reward_params" + validate_response 200 "${target_address}${api}" + compare_responses ${api} + + local api="/v1/epoch/current" + validate_response 200 "${target_address}${api}" + compare_responses ${api} +} + +function network() { + title "/network" + local api="/v1/network/details" + validate_response 200 "${target_address}${api}" + compare_responses ${api} + + local api="/v1/network/nym-contracts" + validate_response 200 "${target_address}${api}" + compare_responses ${api} + + local api="/v1/network/nym-contracts-detailed" + validate_response 200 "${target_address}${api}" + compare_responses ${api} +} + +function api_status() { + title "/api-status" + local api="/v1/api-status/health" + validate_response 200 "${target_address}${api}" + compare_responses ${api} + + local api="/v1/api-status/build-information" + validate_response 200 "${target_address}${api}" + compare_responses ${api} + + local api="/v1/api-status/signer-information" + validate_response 200 "${target_address}${api}" + compare_responses ${api} +} + +function unstable() { + title "/unstable" + + validate_response 501 "${target_address}/v1/unstable/nym-nodes/skimmed" + + validate_response 501 "${target_address}/v1/unstable/nym-nodes/semi-skimmed" + + validate_response 501 "${target_address}/v1/unstable/nym-nodes/full-fat" + + local api="/v1/unstable/nym-nodes/gateways/skimmed" + validate_response 200 "${target_address}${api}" + compare_responses ${api} + + local api="/v1/unstable/nym-nodes/gateways/skimmed?semver_compatibility" + validate_response 200 "${target_address}${api}" + compare_responses ${api} + + local api="/v1/unstable/nym-nodes/gateways/skimmed?semver_compatibility=2.0.0" + validate_response 200 "${target_address}${api}" + compare_responses ${api} + + validate_response 501 "${target_address}/v1/unstable/nym-nodes/gateways/semi-skimmed" + + validate_response 501 "${target_address}/v1/unstable/nym-nodes/gateways/semi-skimmed?semver_compatibility" + + validate_response 501 "${target_address}/v1/unstable/nym-nodes/gateways/semi-skimmed?semver_compatibility=2.0.0" + + validate_response 501 "${target_address}/v1/unstable/nym-nodes/gateways/full-fat" + + validate_response 501 "${target_address}/v1/unstable/nym-nodes/gateways/full-fat?semver_compatibility" + + validate_response 501 "${target_address}/v1/unstable/nym-nodes/gateways/full-fat?semver_compatibility=2.0.0" + + local api="/v1/unstable/nym-nodes/mixnodes/skimmed" + validate_response 200 "${target_address}${api}" + compare_responses ${api} + + local api="/v1/unstable/nym-nodes/mixnodes/skimmed?semver_compatibility" + validate_response 200 "${target_address}${api}" + compare_responses ${api} + + local api="/v1/unstable/nym-nodes/mixnodes/skimmed?semver_compatibility=2.0.0" + validate_response 200 "${target_address}${api}" + compare_responses ${api} + + validate_response 501 "${target_address}/v1/unstable/nym-nodes/mixnodes/semi-skimmed" + + validate_response 501 "${target_address}/v1/unstable/nym-nodes/mixnodes/semi-skimmed?semver_compatibility" + + validate_response 501 "${target_address}/v1/unstable/nym-nodes/mixnodes/semi-skimmed?semver_compatibility=2.0.0" + + validate_response 501 "${target_address}/v1/unstable/nym-nodes/mixnodes/full-fat" + + validate_response 501 "${target_address}/v1/unstable/nym-nodes/mixnodes/full-fat?semver_compatibility" + + validate_response 501 "${target_address}/v1/unstable/nym-nodes/mixnodes/full-fat?semver_compatibility=2.0.0" +} diff --git a/nym-node/tests/test_apis.sh b/nym-node/tests/test_apis.sh new file mode 100755 index 0000000000..31df14f48c --- /dev/null +++ b/nym-node/tests/test_apis.sh @@ -0,0 +1,24 @@ +#!/bin/bash + +# Very basic validation, only that endpoints are reachable +clear + +source $(dirname "$0")/definitions.sh + +function fire_on_all_apis() { + local target_address="$1" + + circulating_supply + + contract_cache + + network + + api_status + + unstable +} + +fire_on_all_apis "http://localhost:8081" + +fire_on_all_apis "http://localhost:8000" From 4d212f73fce89c3a1cf7e37bc6bf11075b0d87fa Mon Sep 17 00:00:00 2001 From: "dependabot[bot]" <49699333+dependabot[bot]@users.noreply.github.com> Date: Thu, 29 Aug 2024 16:16:07 +0000 Subject: [PATCH 46/93] build(deps): bump rand from 0.6.5 to 0.8.5 Bumps [rand](https://github.com/rust-random/rand) from 0.6.5 to 0.8.5. - [Release notes](https://github.com/rust-random/rand/releases) - [Changelog](https://github.com/rust-random/rand/blob/master/CHANGELOG.md) - [Commits](https://github.com/rust-random/rand/compare/0.6.5...0.8.5) --- updated-dependencies: - dependency-name: rand dependency-type: direct:production update-type: version-update:semver-minor ... Signed-off-by: dependabot[bot] --- Cargo.lock | 293 ++++++++++--------------------------- common/commands/Cargo.toml | 2 +- 2 files changed, 78 insertions(+), 217 deletions(-) diff --git a/Cargo.lock b/Cargo.lock index 7bf2a6c00e..d01833c041 100644 --- a/Cargo.lock +++ b/Cargo.lock @@ -346,15 +346,6 @@ dependencies = [ "winapi", ] -[[package]] -name = "autocfg" -version = "0.1.8" -source = "registry+https://github.com/rust-lang/crates.io-index" -checksum = "0dde43e75fd43e8a1bf86103336bc699aa8d17ad1be60c76c0bdfd4828e19b78" -dependencies = [ - "autocfg 1.3.0", -] - [[package]] name = "autocfg" version = "1.3.0" @@ -567,7 +558,7 @@ source = "registry+https://github.com/rust-lang/crates.io-index" checksum = "93f2635620bf0b9d4576eb7bb9a38a55df78bd1205d26fa994b25911a69f212f" dependencies = [ "bitcoin_hashes", - "rand 0.8.5", + "rand", "rand_core 0.6.4", "serde", "unicode-normalization", @@ -1011,15 +1002,6 @@ version = "0.7.1" source = "registry+https://github.com/rust-lang/crates.io-index" checksum = "4b82cf0babdbd58558212896d1a4272303a57bdb245c2bf1147185fb45640e70" -[[package]] -name = "cloudabi" -version = "0.0.3" -source = "registry+https://github.com/rust-lang/crates.io-index" -checksum = "ddfc5b9aa5d4507acaf872de71051dfd0e309860e88966e1051e462a077aac4f" -dependencies = [ - "bitflags 1.3.2", -] - [[package]] name = "colorchoice" version = "1.0.1" @@ -2287,8 +2269,8 @@ dependencies = [ "nym-validator-client", "okapi", "pretty_env_logger", - "rand 0.8.5", - "rand_pcg 0.3.1", + "rand", + "rand_pcg", "rand_seeder", "reqwest 0.12.4", "rocket", @@ -2493,12 +2475,6 @@ dependencies = [ "libc", ] -[[package]] -name = "fuchsia-cprng" -version = "0.1.1" -source = "registry+https://github.com/rust-lang/crates.io-index" -checksum = "a06f77d526c1a601b7c4cdd98f54b5eaabffc14d5f2f0296febdc7f357c6d3ba" - [[package]] name = "funty" version = "2.0.0" @@ -3259,7 +3235,7 @@ version = "1.9.3" source = "registry+https://github.com/rust-lang/crates.io-index" checksum = "bd070e393353796e801d209ad339e89596eb4c8d430d18ede6a1cced8fafbd99" dependencies = [ - "autocfg 1.3.0", + "autocfg", "hashbrown 0.12.3", "serde", ] @@ -3659,7 +3635,7 @@ version = "0.4.12" source = "registry+https://github.com/rust-lang/crates.io-index" checksum = "07af8b9cdd281b7915f413fa73f29ebd5d55d0d3f0155584dade1ff18cea1b17" dependencies = [ - "autocfg 1.3.0", + "autocfg", "scopeguard", ] @@ -3786,7 +3762,7 @@ version = "0.9.1" source = "registry+https://github.com/rust-lang/crates.io-index" checksum = "488016bfae457b036d996092f6cb448677611ce4449e970ceaf42695203f218a" dependencies = [ - "autocfg 1.3.0", + "autocfg", ] [[package]] @@ -3865,7 +3841,7 @@ dependencies = [ "nym-ordered-buffer", "nym-service-providers-common", "nym-socks5-requests", - "rand 0.8.5", + "rand", "serde", "serde-wasm-bindgen 0.6.5", "thiserror", @@ -4081,7 +4057,7 @@ version = "0.2.19" source = "registry+https://github.com/rust-lang/crates.io-index" checksum = "071dfc062690e90b734c0b2273ce72ad0ffa95f0c74596bc250dcfd960262841" dependencies = [ - "autocfg 1.3.0", + "autocfg", "libm", ] @@ -4190,8 +4166,8 @@ dependencies = [ "nym-vesting-contract-common", "okapi", "pin-project", - "rand 0.8.5", - "rand_chacha 0.3.1", + "rand", + "rand_chacha", "reqwest 0.12.4", "rocket", "rocket_cors", @@ -4285,7 +4261,7 @@ dependencies = [ "nym-types", "nym-wireguard", "nym-wireguard-types", - "rand 0.8.5", + "rand", "serde", "serde_json", "thiserror", @@ -4302,7 +4278,7 @@ dependencies = [ "bincode", "nym-sphinx", "nym-wireguard-types", - "rand 0.8.5", + "rand", "serde", ] @@ -4320,7 +4296,7 @@ dependencies = [ "nym-ecash-time", "nym-network-defaults", "nym-validator-client", - "rand 0.8.5", + "rand", "thiserror", "url", "zeroize", @@ -4431,7 +4407,7 @@ dependencies = [ "nym-types", "nym-validator-client", "nym-vesting-contract-common", - "rand 0.6.5", + "rand", "serde", "serde_json", "tap", @@ -4468,7 +4444,7 @@ dependencies = [ "nym-task", "nym-topology", "nym-validator-client", - "rand 0.8.5", + "rand", "serde", "serde_json", "tap", @@ -4519,8 +4495,8 @@ dependencies = [ "nym-task", "nym-topology", "nym-validator-client", - "rand 0.8.5", - "rand_chacha 0.3.1", + "rand", + "rand_chacha", "serde", "serde_json", "sha2 0.10.8", @@ -4600,7 +4576,7 @@ dependencies = [ "nym-bin-common", "nym-node-tester-utils", "nym-node-tester-wasm", - "rand 0.8.5", + "rand", "serde", "serde-wasm-bindgen 0.6.5", "serde_json", @@ -4637,8 +4613,8 @@ dependencies = [ "itertools 0.13.0", "nym-dkg", "nym-pemstore", - "rand 0.8.5", - "rand_chacha 0.3.1", + "rand", + "rand_chacha", "serde", "serde_derive", "sha2 0.9.9", @@ -4684,7 +4660,7 @@ dependencies = [ "itertools 0.12.1", "nym-network-defaults", "nym-pemstore", - "rand 0.8.5", + "rand", "rayon", "serde", "sha2 0.9.9", @@ -4778,7 +4754,7 @@ dependencies = [ "nym-ecash-time", "nym-network-defaults", "nym-validator-client", - "rand 0.8.5", + "rand", "serde", "thiserror", "time", @@ -4793,7 +4769,7 @@ dependencies = [ "nym-compact-ecash", "nym-ecash-time", "nym-network-defaults", - "rand 0.8.5", + "rand", "serde", "strum 0.25.0", "thiserror", @@ -4816,8 +4792,8 @@ dependencies = [ "hmac", "nym-pemstore", "nym-sphinx-types", - "rand 0.8.5", - "rand_chacha 0.3.1", + "rand", + "rand_chacha", "serde", "serde_bytes", "subtle-encoding", @@ -4839,8 +4815,8 @@ dependencies = [ "lazy_static", "nym-contracts-common", "nym-pemstore", - "rand 0.8.5", - "rand_chacha 0.3.1", + "rand", + "rand_chacha", "rand_core 0.6.4", "serde", "serde_derive", @@ -4970,7 +4946,7 @@ dependencies = [ "nym-wireguard", "nym-wireguard-types", "once_cell", - "rand 0.8.5", + "rand", "serde", "serde_json", "si-scale", @@ -5005,7 +4981,7 @@ dependencies = [ "nym-sphinx", "nym-task", "nym-validator-client", - "rand 0.8.5", + "rand", "serde", "si-scale", "thiserror", @@ -5034,7 +5010,7 @@ dependencies = [ "nym-crypto", "nym-pemstore", "nym-sphinx", - "rand 0.8.5", + "rand", "serde", "serde_json", "thiserror", @@ -5136,7 +5112,7 @@ name = "nym-inclusion-probability" version = "0.1.0" dependencies = [ "log", - "rand 0.8.5", + "rand", "thiserror", ] @@ -5149,7 +5125,7 @@ dependencies = [ "nym-bin-common", "nym-crypto", "nym-sphinx", - "rand 0.8.5", + "rand", "serde", "thiserror", "time", @@ -5186,7 +5162,7 @@ dependencies = [ "nym-types", "nym-wireguard", "nym-wireguard-types", - "rand 0.8.5", + "rand", "reqwest 0.12.4", "serde", "serde_json", @@ -5243,7 +5219,7 @@ dependencies = [ "humantime-serde", "log", "nym-contracts-common", - "rand_chacha 0.3.1", + "rand_chacha", "schemars", "serde", "serde-json-wasm", @@ -5287,7 +5263,7 @@ dependencies = [ "nym-topology", "nym-types", "nym-validator-client", - "rand 0.8.5", + "rand", "serde", "serde_json", "sysinfo", @@ -5320,7 +5296,7 @@ dependencies = [ "nym-sphinx-types", "nym-task", "nym-validator-client", - "rand 0.8.5", + "rand", "serde", "thiserror", "time", @@ -5375,8 +5351,8 @@ dependencies = [ "nym-types", "nym-validator-client", "petgraph", - "rand 0.8.5", - "rand_chacha 0.3.1", + "rand", + "rand_chacha", "reqwest 0.12.4", "serde", "serde_json", @@ -5421,7 +5397,7 @@ dependencies = [ "nym-types", "pretty_env_logger", "publicsuffix", - "rand 0.8.5", + "rand", "regex", "reqwest 0.12.4", "serde", @@ -5468,7 +5444,7 @@ dependencies = [ "nym-types", "nym-wireguard", "nym-wireguard-types", - "rand 0.8.5", + "rand", "semver 1.0.23", "serde", "serde_json", @@ -5502,7 +5478,7 @@ dependencies = [ "nym-task", "nym-wireguard", "nym-wireguard-types", - "rand 0.8.5", + "rand", "serde_json", "thiserror", "time", @@ -5529,7 +5505,7 @@ dependencies = [ "nym-exit-policy", "nym-http-api-client", "nym-wireguard-types", - "rand_chacha 0.3.1", + "rand_chacha", "schemars", "serde", "serde_json", @@ -5550,8 +5526,8 @@ dependencies = [ "nym-sphinx-params", "nym-task", "nym-topology", - "rand 0.8.5", - "rand_chacha 0.3.1", + "rand", + "rand_chacha", "serde", "serde_json", "thiserror", @@ -5566,7 +5542,7 @@ dependencies = [ "futures", "js-sys", "nym-node-tester-utils", - "rand 0.8.5", + "rand", "serde", "serde-wasm-bindgen 0.6.5", "thiserror", @@ -5625,7 +5601,7 @@ dependencies = [ "fastrand 2.1.1", "getrandom", "log", - "rand 0.8.5", + "rand", "rayon", "sphinx-packet", "thiserror", @@ -5674,7 +5650,7 @@ dependencies = [ "nym-validator-client", "parking_lot 0.12.3", "pretty_env_logger", - "rand 0.8.5", + "rand", "reqwest 0.12.4", "tap", "thiserror", @@ -5734,7 +5710,7 @@ dependencies = [ "nym-sphinx", "nym-topology", "nym-validator-client", - "rand 0.8.5", + "rand", "serde", "serde_json", "tap", @@ -5767,7 +5743,7 @@ dependencies = [ "nym-task", "nym-validator-client", "pin-project", - "rand 0.8.5", + "rand", "reqwest 0.12.4", "schemars", "serde", @@ -5793,7 +5769,7 @@ dependencies = [ "nym-credential-storage", "nym-crypto", "nym-socks5-client-core", - "rand 0.8.5", + "rand", "safer-ffi", "serde", "tokio", @@ -5848,8 +5824,8 @@ dependencies = [ "nym-sphinx-routing", "nym-sphinx-types", "nym-topology", - "rand 0.8.5", - "rand_chacha 0.3.1", + "rand", + "rand_chacha", "rand_distr", "thiserror", "tokio", @@ -5867,7 +5843,7 @@ dependencies = [ "nym-sphinx-routing", "nym-sphinx-types", "nym-topology", - "rand 0.8.5", + "rand", "serde", "thiserror", "zeroize", @@ -5879,7 +5855,7 @@ version = "0.1.0" dependencies = [ "nym-crypto", "nym-sphinx-types", - "rand 0.8.5", + "rand", "serde", "thiserror", ] @@ -5895,8 +5871,8 @@ dependencies = [ "nym-sphinx-routing", "nym-sphinx-types", "nym-topology", - "rand 0.8.5", - "rand_chacha 0.3.1", + "rand", + "rand_chacha", "serde", "thiserror", "wasm-bindgen", @@ -5913,7 +5889,7 @@ dependencies = [ "nym-sphinx-addressing", "nym-sphinx-params", "nym-sphinx-types", - "rand 0.8.5", + "rand", "serde", "thiserror", "utoipa", @@ -5932,7 +5908,7 @@ dependencies = [ "nym-sphinx-routing", "nym-sphinx-types", "nym-topology", - "rand 0.8.5", + "rand", "thiserror", ] @@ -5994,7 +5970,7 @@ dependencies = [ "argon2", "generic-array 0.14.7", "getrandom", - "rand 0.8.5", + "rand", "serde", "serde_json", "thiserror", @@ -6029,7 +6005,7 @@ dependencies = [ "nym-sphinx-addressing", "nym-sphinx-routing", "nym-sphinx-types", - "rand 0.8.5", + "rand", "reqwest 0.12.4", "semver 0.11.0", "serde", @@ -6154,7 +6130,7 @@ dependencies = [ "nym-task", "nym-validator-client", "nyxd-scraper", - "rand_chacha 0.3.1", + "rand_chacha", "serde", "serde_with", "sha2 0.10.8", @@ -6232,7 +6208,7 @@ dependencies = [ "nym-config", "nym-crypto", "nym-network-defaults", - "rand 0.8.5", + "rand", "serde", "serde_json", "sha2 0.10.8", @@ -6442,7 +6418,7 @@ dependencies = [ "once_cell", "opentelemetry_api", "percent-encoding", - "rand 0.8.5", + "rand", "thiserror", "tokio", "tokio-stream", @@ -6759,7 +6735,7 @@ version = "2.8.0" source = "registry+https://github.com/rust-lang/crates.io-index" checksum = "4b2d323e8ca7996b3e23126511a523f7e62924d93ecd5ae73b333815b0eb3dce" dependencies = [ - "autocfg 1.3.0", + "autocfg", "bitflags 1.3.2", "cfg-if", "concurrent-queue", @@ -7022,25 +6998,6 @@ version = "0.7.0" source = "registry+https://github.com/rust-lang/crates.io-index" checksum = "dc33ff2d4973d518d823d61aa239014831e521c75da58e3df4840d3f47749d09" -[[package]] -name = "rand" -version = "0.6.5" -source = "registry+https://github.com/rust-lang/crates.io-index" -checksum = "6d71dacdc3c88c1fde3885a3be3fbab9f35724e6ce99467f7d9c5026132184ca" -dependencies = [ - "autocfg 0.1.8", - "libc", - "rand_chacha 0.1.1", - "rand_core 0.4.2", - "rand_hc", - "rand_isaac", - "rand_jitter", - "rand_os", - "rand_pcg 0.1.2", - "rand_xorshift", - "winapi", -] - [[package]] name = "rand" version = "0.8.5" @@ -7048,20 +7005,10 @@ source = "registry+https://github.com/rust-lang/crates.io-index" checksum = "34af8d1a0e25924bc5b7c43c079c942339d8f0a8b57c39049bef581b46327404" dependencies = [ "libc", - "rand_chacha 0.3.1", + "rand_chacha", "rand_core 0.6.4", ] -[[package]] -name = "rand_chacha" -version = "0.1.1" -source = "registry+https://github.com/rust-lang/crates.io-index" -checksum = "556d3a1ca6600bfcbab7c7c91ccb085ac7fbbcd70e008a98742e7847f4f7bcef" -dependencies = [ - "autocfg 0.1.8", - "rand_core 0.3.1", -] - [[package]] name = "rand_chacha" version = "0.3.1" @@ -7072,21 +7019,6 @@ dependencies = [ "rand_core 0.6.4", ] -[[package]] -name = "rand_core" -version = "0.3.1" -source = "registry+https://github.com/rust-lang/crates.io-index" -checksum = "7a6fdeb83b075e8266dcc8762c22776f6877a63111121f5f8c7411e5be7eed4b" -dependencies = [ - "rand_core 0.4.2", -] - -[[package]] -name = "rand_core" -version = "0.4.2" -source = "registry+https://github.com/rust-lang/crates.io-index" -checksum = "9c33a3c44ca05fa6f1807d8e6743f3824e8509beca625669633be0acbdf509dc" - [[package]] name = "rand_core" version = "0.5.1" @@ -7109,60 +7041,7 @@ source = "registry+https://github.com/rust-lang/crates.io-index" checksum = "32cb0b9bc82b0a0876c2dd994a7e7a2683d3e7390ca40e6886785ef0c7e3ee31" dependencies = [ "num-traits", - "rand 0.8.5", -] - -[[package]] -name = "rand_hc" -version = "0.1.0" -source = "registry+https://github.com/rust-lang/crates.io-index" -checksum = "7b40677c7be09ae76218dc623efbf7b18e34bced3f38883af07bb75630a21bc4" -dependencies = [ - "rand_core 0.3.1", -] - -[[package]] -name = "rand_isaac" -version = "0.1.1" -source = "registry+https://github.com/rust-lang/crates.io-index" -checksum = "ded997c9d5f13925be2a6fd7e66bf1872597f759fd9dd93513dd7e92e5a5ee08" -dependencies = [ - "rand_core 0.3.1", -] - -[[package]] -name = "rand_jitter" -version = "0.1.4" -source = "registry+https://github.com/rust-lang/crates.io-index" -checksum = "1166d5c91dc97b88d1decc3285bb0a99ed84b05cfd0bc2341bdf2d43fc41e39b" -dependencies = [ - "libc", - "rand_core 0.4.2", - "winapi", -] - -[[package]] -name = "rand_os" -version = "0.1.3" -source = "registry+https://github.com/rust-lang/crates.io-index" -checksum = "7b75f676a1e053fc562eafbb47838d67c84801e38fc1ba459e8f180deabd5071" -dependencies = [ - "cloudabi", - "fuchsia-cprng", - "libc", - "rand_core 0.4.2", - "rdrand", - "winapi", -] - -[[package]] -name = "rand_pcg" -version = "0.1.2" -source = "registry+https://github.com/rust-lang/crates.io-index" -checksum = "abf9b09b01790cfe0364f52bf32995ea3c39f4d2dd011eac241d2914146d0b44" -dependencies = [ - "autocfg 0.1.8", - "rand_core 0.4.2", + "rand", ] [[package]] @@ -7183,15 +7062,6 @@ dependencies = [ "rand_core 0.6.4", ] -[[package]] -name = "rand_xorshift" -version = "0.1.1" -source = "registry+https://github.com/rust-lang/crates.io-index" -checksum = "cbf7e9e623549b0e21f6e97cf8ecf247c1a8fd2e8a992ae265314300b2455d5c" -dependencies = [ - "rand_core 0.3.1", -] - [[package]] name = "rayon" version = "1.10.0" @@ -7212,15 +7082,6 @@ dependencies = [ "crossbeam-utils", ] -[[package]] -name = "rdrand" -version = "0.4.0" -source = "registry+https://github.com/rust-lang/crates.io-index" -checksum = "678054eb77286b51581ba43620cc911abf02758c91f93f479767aed0f90458b2" -dependencies = [ - "rand_core 0.3.1", -] - [[package]] name = "redox_syscall" version = "0.2.16" @@ -7479,7 +7340,7 @@ dependencies = [ "num_cpus", "parking_lot 0.12.3", "pin-project-lite", - "rand 0.8.5", + "rand", "ref-cast", "rocket_codegen", "rocket_http", @@ -8266,7 +8127,7 @@ version = "0.4.9" source = "registry+https://github.com/rust-lang/crates.io-index" checksum = "8f92a496fb766b417c996b9c5e57daf2f7ad3b0bebe1ccfca4856390e3d3bb67" dependencies = [ - "autocfg 1.3.0", + "autocfg", ] [[package]] @@ -8337,7 +8198,7 @@ dependencies = [ "hmac", "lioness", "log", - "rand 0.8.5", + "rand", "rand_distr", "sha2 0.10.8", "subtle 2.6.1", @@ -8506,7 +8367,7 @@ dependencies = [ "proc-macro-crate", "proc-macro2", "quote", - "rand 0.8.5", + "rand", "syn 1.0.109", ] @@ -8883,7 +8744,7 @@ dependencies = [ "getrandom", "peg", "pin-project", - "rand 0.8.5", + "rand", "reqwest 0.11.27", "semver 1.0.23", "serde", @@ -8937,7 +8798,7 @@ dependencies = [ "nym-pemstore", "nym-validator-client", "nym-vesting-contract-common", - "rand 0.8.5", + "rand", "serde", "serde_json", "sqlx", @@ -9338,7 +9199,7 @@ dependencies = [ "indexmap 1.9.3", "pin-project", "pin-project-lite", - "rand 0.8.5", + "rand", "slab", "tokio", "tokio-util", @@ -9604,7 +9465,7 @@ dependencies = [ "http 0.2.12", "httparse", "log", - "rand 0.8.5", + "rand", "rustls 0.21.12", "sha1", "thiserror", @@ -9625,7 +9486,7 @@ dependencies = [ "http 1.1.0", "httparse", "log", - "rand 0.8.5", + "rand", "rustls 0.22.4", "rustls-pki-types", "sha1", @@ -10068,7 +9929,7 @@ dependencies = [ "nym-task", "nym-topology", "nym-validator-client", - "rand 0.8.5", + "rand", "serde", "serde-wasm-bindgen 0.6.5", "thiserror", @@ -10628,7 +10489,7 @@ dependencies = [ "nym-credentials", "nym-crypto", "nym-http-api-client", - "rand 0.8.5", + "rand", "reqwest 0.12.4", "serde", "thiserror", diff --git a/common/commands/Cargo.toml b/common/commands/Cargo.toml index bab9b86a6e..eb27029330 100644 --- a/common/commands/Cargo.toml +++ b/common/commands/Cargo.toml @@ -21,7 +21,7 @@ humantime-serde = { workspace = true } inquire = { workspace = true } k256 = { workspace = true, features = ["ecdsa", "sha256"] } log = { workspace = true } -rand = {version = "0.6", features = ["std"] } +rand = {version = "0.8", features = ["std"] } serde = { workspace = true, features = ["derive"] } serde_json = { workspace = true } thiserror = { workspace = true } From 6b933094829c44a8d044a7199fc6c6784bc867bf Mon Sep 17 00:00:00 2001 From: "dependabot[bot]" <49699333+dependabot[bot]@users.noreply.github.com> Date: Thu, 29 Aug 2024 16:17:17 +0000 Subject: [PATCH 47/93] build(deps): bump bs58 from 0.4.0 to 0.5.1 Bumps [bs58](https://github.com/Nullus157/bs58-rs) from 0.4.0 to 0.5.1. - [Changelog](https://github.com/Nullus157/bs58-rs/blob/main/CHANGELOG.md) - [Commits](https://github.com/Nullus157/bs58-rs/compare/0.4.0...0.5.1) --- updated-dependencies: - dependency-name: bs58 dependency-type: direct:production update-type: version-update:semver-minor ... Signed-off-by: dependabot[bot] --- Cargo.lock | 64 +++++++++---------- .../mixnet-contract/Cargo.toml | 2 +- 2 files changed, 30 insertions(+), 36 deletions(-) diff --git a/Cargo.lock b/Cargo.lock index 7bf2a6c00e..25b65b340a 100644 --- a/Cargo.lock +++ b/Cargo.lock @@ -550,7 +550,7 @@ version = "0.5.2" source = "registry+https://github.com/rust-lang/crates.io-index" checksum = "aa13fae8b6255872fd86f7faf4b41168661d7d78609f7bfe6771b85c6739a15b" dependencies = [ - "bs58 0.5.1", + "bs58", "hmac", "k256", "rand_core 0.6.4", @@ -705,12 +705,6 @@ version = "0.8.1" source = "registry+https://github.com/rust-lang/crates.io-index" checksum = "ab9008b6bb9fc80b5277f2fe481c09e828743d9151203e804583eb4c9e15b31d" -[[package]] -name = "bs58" -version = "0.4.0" -source = "registry+https://github.com/rust-lang/crates.io-index" -checksum = "771fe0050b883fcc3ea2359b1a96bcfbc090b7116eae7c3c512c7a083fdf23d3" - [[package]] name = "bs58" version = "0.5.1" @@ -4142,7 +4136,7 @@ dependencies = [ "bincode", "bip39", "bloomfilter", - "bs58 0.5.1", + "bs58", "cfg-if", "clap 4.5.16", "console-subscriber", @@ -4223,7 +4217,7 @@ dependencies = [ name = "nym-api-requests" version = "0.1.0" dependencies = [ - "bs58 0.5.1", + "bs58", "cosmrs 0.17.0-pre", "cosmwasm-std", "ecdsa", @@ -4263,7 +4257,7 @@ version = "0.1.0" dependencies = [ "anyhow", "bincode", - "bs58 0.5.1", + "bs58", "bytes", "clap 4.5.16", "defguard_wireguard_rs", @@ -4371,7 +4365,7 @@ dependencies = [ "anyhow", "base64 0.22.1", "bip39", - "bs58 0.5.1", + "bs58", "clap 4.5.16", "clap_complete", "clap_complete_fig", @@ -4396,7 +4390,7 @@ dependencies = [ "anyhow", "base64 0.22.1", "bip39", - "bs58 0.5.1", + "bs58", "cfg-if", "clap 4.5.16", "comfy-table 6.2.0", @@ -4447,7 +4441,7 @@ dependencies = [ name = "nym-client" version = "1.1.39" dependencies = [ - "bs58 0.5.1", + "bs58", "clap 4.5.16", "dirs 4.0.0", "futures", @@ -4486,7 +4480,7 @@ version = "1.1.15" dependencies = [ "async-trait", "base64 0.22.1", - "bs58 0.5.1", + "bs58", "cfg-if", "clap 4.5.16", "comfy-table 7.1.1", @@ -4627,7 +4621,7 @@ name = "nym-coconut" version = "0.5.0" dependencies = [ "bls12_381", - "bs58 0.5.1", + "bs58", "criterion 0.4.0", "digest 0.9.0", "doc-comment", @@ -4675,7 +4669,7 @@ version = "0.1.0" dependencies = [ "bincode", "bls12_381", - "bs58 0.5.1", + "bs58", "cfg-if", "criterion 0.5.1", "digest 0.9.0", @@ -4709,7 +4703,7 @@ dependencies = [ name = "nym-contracts-common" version = "0.5.0" dependencies = [ - "bs58 0.5.1", + "bs58", "cosmwasm-schema", "cosmwasm-std", "cw-storage-plus", @@ -4806,7 +4800,7 @@ version = "0.4.0" dependencies = [ "aes", "blake3", - "bs58 0.5.1", + "bs58", "cipher", "ctr", "digest 0.10.7", @@ -4832,7 +4826,7 @@ version = "0.1.0" dependencies = [ "bitvec", "bls12_381", - "bs58 0.5.1", + "bs58", "criterion 0.4.0", "ff", "group", @@ -4853,7 +4847,7 @@ dependencies = [ name = "nym-ecash-contract-common" version = "0.1.0" dependencies = [ - "bs58 0.5.1", + "bs58", "cosmwasm-schema", "cosmwasm-std", "cw-controllers", @@ -4933,7 +4927,7 @@ dependencies = [ "async-trait", "bip39", "bloomfilter", - "bs58 0.5.1", + "bs58", "clap 4.5.16", "colored", "cosmwasm-std", @@ -5025,7 +5019,7 @@ dependencies = [ name = "nym-gateway-requests" version = "0.1.0" dependencies = [ - "bs58 0.5.1", + "bs58", "futures", "generic-array 0.14.7", "nym-compact-ecash", @@ -5122,7 +5116,7 @@ name = "nym-id-cli" version = "0.1.0" dependencies = [ "anyhow", - "bs58 0.5.1", + "bs58", "clap 4.5.16", "nym-bin-common", "nym-credential-storage", @@ -5163,7 +5157,7 @@ version = "0.1.0" dependencies = [ "anyhow", "bincode", - "bs58 0.5.1", + "bs58", "bytes", "clap 4.5.16", "etherparse", @@ -5236,7 +5230,7 @@ dependencies = [ name = "nym-mixnet-contract-common" version = "0.6.0" dependencies = [ - "bs58 0.4.0", + "bs58", "cosmwasm-schema", "cosmwasm-std", "cw2", @@ -5260,7 +5254,7 @@ version = "1.1.37" dependencies = [ "anyhow", "axum 0.7.5", - "bs58 0.5.1", + "bs58", "clap 4.5.16", "colored", "cupid", @@ -5393,7 +5387,7 @@ dependencies = [ "addr", "anyhow", "async-trait", - "bs58 0.5.1", + "bs58", "clap 4.5.16", "dirs 4.0.0", "futures", @@ -5443,7 +5437,7 @@ version = "1.1.6" dependencies = [ "anyhow", "bip39", - "bs58 0.5.1", + "bs58", "cargo_metadata", "celes", "clap 4.5.16", @@ -5691,7 +5685,7 @@ name = "nym-serde-helpers" version = "0.1.0" dependencies = [ "base64 0.22.1", - "bs58 0.5.1", + "bs58", "serde", ] @@ -5716,7 +5710,7 @@ dependencies = [ name = "nym-socks5-client" version = "1.1.39" dependencies = [ - "bs58 0.5.1", + "bs58", "clap 4.5.16", "log", "nym-bin-common", @@ -5888,7 +5882,7 @@ dependencies = [ name = "nym-sphinx-anonymous-replies" version = "0.1.0" dependencies = [ - "bs58 0.5.1", + "bs58", "nym-crypto", "nym-sphinx-addressing", "nym-sphinx-params", @@ -6019,7 +6013,7 @@ name = "nym-topology" version = "0.1.0" dependencies = [ "async-trait", - "bs58 0.5.1", + "bs58", "log", "nym-api-requests", "nym-bin-common", @@ -8327,7 +8321,7 @@ dependencies = [ "aes", "arrayref", "blake2 0.8.1", - "bs58 0.5.1", + "bs58", "byteorder", "chacha", "ctr", @@ -8918,7 +8912,7 @@ version = "0.1.0" dependencies = [ "anyhow", "bip39", - "bs58 0.5.1", + "bs58", "clap 4.5.16", "console", "cw-utils", @@ -10619,7 +10613,7 @@ version = "0.1.0" dependencies = [ "anyhow", "async-trait", - "bs58 0.5.1", + "bs58", "getrandom", "js-sys", "nym-bin-common", diff --git a/common/cosmwasm-smart-contracts/mixnet-contract/Cargo.toml b/common/cosmwasm-smart-contracts/mixnet-contract/Cargo.toml index 86afc9d0c8..f75b1777f4 100644 --- a/common/cosmwasm-smart-contracts/mixnet-contract/Cargo.toml +++ b/common/cosmwasm-smart-contracts/mixnet-contract/Cargo.toml @@ -9,7 +9,7 @@ license = { workspace = true } repository = { workspace = true } [dependencies] -bs58 = "0.4.0" +bs58 = "0.5.1" cosmwasm-std = { workspace = true } cosmwasm-schema = { workspace = true } cw2 = { workspace = true, optional = true } From bdf45cafb5446bf17247b4b067f913dc1c710706 Mon Sep 17 00:00:00 2001 From: =?UTF-8?q?Bogdan-=C8=98tefan=20Neac=C5=9Fu?= Date: Mon, 2 Sep 2024 11:51:48 +0200 Subject: [PATCH 48/93] Expose wireguard details on self described endpoint (#4825) * Expose wireguard details on self described endpoint * Fill placeholder string --- nym-api/nym-api-requests/src/models.rs | 9 +++++ nym-api/src/node_describe_cache/mod.rs | 11 ++++++ .../api/v1/gateway/client_interfaces/mod.rs | 35 ++++++++++++++++++- nym-node/nym-node-requests/src/api/client.rs | 7 ++++ .../src/api/v1/gateway/models.rs | 2 +- nym-node/nym-node-requests/src/lib.rs | 10 ------ nym-node/src/node/mod.rs | 2 +- 7 files changed, 63 insertions(+), 13 deletions(-) diff --git a/nym-api/nym-api-requests/src/models.rs b/nym-api/nym-api-requests/src/models.rs index 5889a33b83..f42c8cb764 100644 --- a/nym-api/nym-api-requests/src/models.rs +++ b/nym-api/nym-api-requests/src/models.rs @@ -566,6 +566,9 @@ pub struct NymNodeDescription { #[serde(default)] pub authenticator: Option, + #[serde(default)] + pub wireguard: Option, + // for now we only care about their ws/wss situation, nothing more pub mixnet_websockets: WebSockets, @@ -629,6 +632,12 @@ pub struct AuthenticatorDetails { pub address: String, } +#[derive(Clone, Debug, Serialize, Deserialize, schemars::JsonSchema, ToSchema)] +pub struct WireguardDetails { + pub port: u16, + pub public_key: String, +} + #[derive(Clone, Copy, Debug, Serialize, Deserialize, schemars::JsonSchema, ToSchema)] pub struct ApiHealthResponse { pub status: ApiStatus, diff --git a/nym-api/src/node_describe_cache/mod.rs b/nym-api/src/node_describe_cache/mod.rs index 75fe3c6b82..f56646e6fc 100644 --- a/nym-api/src/node_describe_cache/mod.rs +++ b/nym-api/src/node_describe_cache/mod.rs @@ -9,6 +9,7 @@ use crate::support::config::DEFAULT_NODE_DESCRIBE_BATCH_SIZE; use futures::{stream, StreamExt}; use nym_api_requests::models::{ AuthenticatorDetails, IpPacketRouterDetails, NetworkRequesterDetails, NymNodeDescription, + WireguardDetails, }; use nym_api_requests::nym_nodes::NodeRole; use nym_config::defaults::{mainnet, DEFAULT_NYM_NODE_HTTP_PORT}; @@ -197,6 +198,15 @@ async fn try_get_description( None }; + let wireguard = if let Ok(wg) = client.get_wireguard().await { + Some(WireguardDetails { + port: wg.port, + public_key: wg.public_key, + }) + } else { + None + }; + let description = NymNodeDescription { host_information: host_info.data.into(), last_polled: OffsetDateTime::now_utc().into(), @@ -204,6 +214,7 @@ async fn try_get_description( network_requester, ip_packet_router, authenticator, + wireguard, mixnet_websockets: websockets.into(), auxiliary_details, role: data.role(), diff --git a/nym-node/nym-node-http-api/src/router/api/v1/gateway/client_interfaces/mod.rs b/nym-node/nym-node-http-api/src/router/api/v1/gateway/client_interfaces/mod.rs index 59e3d4ae04..809cc1fc9e 100644 --- a/nym-node/nym-node-http-api/src/router/api/v1/gateway/client_interfaces/mod.rs +++ b/nym-node/nym-node-http-api/src/router/api/v1/gateway/client_interfaces/mod.rs @@ -6,7 +6,7 @@ use axum::extract::Query; use axum::http::StatusCode; use axum::routing::get; use axum::Router; -use nym_node_requests::api::v1::gateway::models::{ClientInterfaces, WebSockets}; +use nym_node_requests::api::v1::gateway::models::{ClientInterfaces, WebSockets, Wireguard}; use nym_node_requests::routes::api::v1::gateway::client_interfaces; pub(crate) fn routes( @@ -27,6 +27,13 @@ pub(crate) fn routes( move |query| mixnet_websockets(websockets, query) }), ) + .route( + client_interfaces::WIREGUARD, + get({ + let wireguard = interfaces.as_ref().and_then(|i| i.wireguard.clone()); + move |query| wireguard_details(wireguard, query) + }), + ) } /// Returns client interfaces supported by this gateway. @@ -80,3 +87,29 @@ pub(crate) async fn mixnet_websockets( } pub type MixnetWebSocketsResponse = FormattedResponse; + +/// Returns wireguard information on this gateway. +#[utoipa::path( + get, + path = "/wireguard", + context_path = "/api/v1/gateway/client-interfaces", + tag = "Gateway", + responses( + (status = 501, description = "the endpoint hasn't been implemented yet"), + (status = 200, content( + ("application/json" = Wireguard), + ("application/yaml" = Wireguard) + )) + ), + params(OutputParams) +)] +pub(crate) async fn wireguard_details( + wireguard: Option, + Query(output): Query, +) -> Result { + let wireguard = wireguard.ok_or(StatusCode::NOT_IMPLEMENTED)?; + let output = output.output.unwrap_or_default(); + Ok(output.to_response(wireguard)) +} + +pub type WireguardResponse = FormattedResponse; diff --git a/nym-node/nym-node-requests/src/api/client.rs b/nym-node/nym-node-requests/src/api/client.rs index 7600886588..87257e2835 100644 --- a/nym-node/nym-node-requests/src/api/client.rs +++ b/nym-node/nym-node-requests/src/api/client.rs @@ -16,6 +16,8 @@ use crate::api::v1::network_requester::exit_policy::models::UsedExitPolicy; use crate::api::v1::network_requester::models::NetworkRequester; pub use nym_http_api_client::Client; +use super::v1::gateway::models::Wireguard; + pub type NymNodeApiClientError = HttpClientError; #[cfg_attr(target_arch = "wasm32", async_trait(?Send))] @@ -69,6 +71,11 @@ pub trait NymNodeApiClientExt: ApiClient { self.get_json_from(routes::api::v1::authenticator_absolute()) .await } + + async fn get_wireguard(&self) -> Result { + self.get_json_from(routes::api::v1::gateway::client_interfaces::wireguard_absolute()) + .await + } } #[cfg_attr(target_arch = "wasm32", async_trait(?Send))] diff --git a/nym-node/nym-node-requests/src/api/v1/gateway/models.rs b/nym-node/nym-node-requests/src/api/v1/gateway/models.rs index da3414ad45..24597847ca 100644 --- a/nym-node/nym-node-requests/src/api/v1/gateway/models.rs +++ b/nym-node/nym-node-requests/src/api/v1/gateway/models.rs @@ -16,7 +16,7 @@ pub struct Gateway { #[derive(Serialize, Deserialize, Debug, Clone, JsonSchema)] #[cfg_attr(feature = "openapi", derive(utoipa::ToSchema))] pub struct Wireguard { - #[cfg_attr(feature = "openapi", schema(example = 51820, default = 51820))] + #[cfg_attr(feature = "openapi", schema(example = 51822, default = 51822))] pub port: u16, pub public_key: String, diff --git a/nym-node/nym-node-requests/src/lib.rs b/nym-node/nym-node-requests/src/lib.rs index 30e2036343..7b4e0ee9b7 100644 --- a/nym-node/nym-node-requests/src/lib.rs +++ b/nym-node/nym-node-requests/src/lib.rs @@ -96,16 +96,6 @@ pub mod routes { client_interfaces_absolute(), WEBSOCKETS ); - - pub mod wireguard { - use super::*; - - pub const CLIENT: &str = "/client"; - pub const CLIENTS: &str = "/clients"; - - absolute_route!(client_absolute, wireguard_absolute(), CLIENT); - absolute_route!(clients_absolute, wireguard_absolute(), CLIENTS); - } } } diff --git a/nym-node/src/node/mod.rs b/nym-node/src/node/mod.rs index 19242eda04..e8347e2f62 100644 --- a/nym-node/src/node/mod.rs +++ b/nym-node/src/node/mod.rs @@ -639,7 +639,7 @@ impl NymNode { let wireguard = if self.config.wireguard.enabled { Some(api_requests::v1::gateway::models::Wireguard { port: self.config.wireguard.announced_port, - public_key: "placeholder key value".to_string(), + public_key: self.wireguard.inner.keypair().public_key().to_string(), }) } else { None From d094bb60c68a1a1976888acd6abc1197a7c4ebb4 Mon Sep 17 00:00:00 2001 From: "dependabot[bot]" <49699333+dependabot[bot]@users.noreply.github.com> Date: Mon, 2 Sep 2024 14:25:42 +0200 Subject: [PATCH 49/93] build(deps): bump actions/setup-java from 3 to 4 (#4815) Bumps [actions/setup-java](https://github.com/actions/setup-java) from 3 to 4. - [Release notes](https://github.com/actions/setup-java/releases) - [Commits](https://github.com/actions/setup-java/compare/v3...v4) --- updated-dependencies: - dependency-name: actions/setup-java dependency-type: direct:production update-type: version-update:semver-major ... Signed-off-by: dependabot[bot] Co-authored-by: dependabot[bot] <49699333+dependabot[bot]@users.noreply.github.com> --- .github/workflows/publish-nyms5-android-apk.yml | 2 +- 1 file changed, 1 insertion(+), 1 deletion(-) diff --git a/.github/workflows/publish-nyms5-android-apk.yml b/.github/workflows/publish-nyms5-android-apk.yml index 0ac8c9ae49..29b1cdc385 100644 --- a/.github/workflows/publish-nyms5-android-apk.yml +++ b/.github/workflows/publish-nyms5-android-apk.yml @@ -25,7 +25,7 @@ jobs: uses: actions/checkout@v4 - name: Install Java - uses: actions/setup-java@v3 + uses: actions/setup-java@v4 with: distribution: "temurin" java-version: "17" From abc6d61d845d16f528ba0f20111f055f69b86edb Mon Sep 17 00:00:00 2001 From: "dependabot[bot]" <49699333+dependabot[bot]@users.noreply.github.com> Date: Mon, 2 Sep 2024 14:27:01 +0200 Subject: [PATCH 50/93] build(deps): bump actions/deploy-pages from 2 to 4 (#4814) Bumps [actions/deploy-pages](https://github.com/actions/deploy-pages) from 2 to 4. - [Release notes](https://github.com/actions/deploy-pages/releases) - [Commits](https://github.com/actions/deploy-pages/compare/v2...v4) --- updated-dependencies: - dependency-name: actions/deploy-pages dependency-type: direct:production update-type: version-update:semver-major ... Signed-off-by: dependabot[bot] Co-authored-by: dependabot[bot] <49699333+dependabot[bot]@users.noreply.github.com> --- .github/workflows/deploy-github-pages.yml | 2 +- 1 file changed, 1 insertion(+), 1 deletion(-) diff --git a/.github/workflows/deploy-github-pages.yml b/.github/workflows/deploy-github-pages.yml index ee91090de6..f1e47a3ed8 100644 --- a/.github/workflows/deploy-github-pages.yml +++ b/.github/workflows/deploy-github-pages.yml @@ -40,4 +40,4 @@ jobs: path: './ppa' - name: Deploy to GitHub Pages id: deployment - uses: actions/deploy-pages@v2 + uses: actions/deploy-pages@v4 From 58c9a58a388968471e603c96a041fcb24d9013e8 Mon Sep 17 00:00:00 2001 From: "dependabot[bot]" <49699333+dependabot[bot]@users.noreply.github.com> Date: Mon, 2 Sep 2024 14:28:36 +0200 Subject: [PATCH 51/93] build(deps): bump actions/setup-node from 3 to 4 (#4816) Bumps [actions/setup-node](https://github.com/actions/setup-node) from 3 to 4. - [Release notes](https://github.com/actions/setup-node/releases) - [Commits](https://github.com/actions/setup-node/compare/v3...v4) --- updated-dependencies: - dependency-name: actions/setup-node dependency-type: direct:production update-type: version-update:semver-major ... Signed-off-by: dependabot[bot] Co-authored-by: dependabot[bot] <49699333+dependabot[bot]@users.noreply.github.com> --- .github/workflows/cd-docs.yml | 2 +- .github/workflows/ci-build-ts.yml | 2 +- .github/workflows/ci-docs.yml | 2 +- .github/workflows/ci-lint-typescript.yml | 2 +- .github/workflows/ci-nym-api-tests.yml | 2 +- .github/workflows/ci-nym-network-explorer.yml | 2 +- .github/workflows/ci-nym-wallet-storybook.yml | 2 +- .github/workflows/ci-sdk-docs-typescript.yml | 2 +- .github/workflows/ci-sdk-wasm.yml | 2 +- .github/workflows/nightly-build.yml | 2 +- .github/workflows/nightly-nym-wallet-build.yml | 2 +- .github/workflows/nightly-security-audit.yml | 2 +- .github/workflows/publish-nym-wallet-macos.yml | 2 +- .github/workflows/publish-nym-wallet-ubuntu.yml | 2 +- .github/workflows/publish-nym-wallet-win10.yml | 2 +- .github/workflows/publish-sdk-npm.yml | 2 +- .github/workflows/release-calculate-hash.yml | 2 +- 17 files changed, 17 insertions(+), 17 deletions(-) diff --git a/.github/workflows/cd-docs.yml b/.github/workflows/cd-docs.yml index 8d2ac55071..c3b4f6a7b2 100644 --- a/.github/workflows/cd-docs.yml +++ b/.github/workflows/cd-docs.yml @@ -17,7 +17,7 @@ jobs: - name: Install rsync run: sudo apt-get install rsync - uses: rlespinasse/github-slug-action@v3.x - - uses: actions/setup-node@v3 + - uses: actions/setup-node@v4 with: node-version: 18 - name: Install Rust stable diff --git a/.github/workflows/ci-build-ts.yml b/.github/workflows/ci-build-ts.yml index 9920f02540..624a52245d 100644 --- a/.github/workflows/ci-build-ts.yml +++ b/.github/workflows/ci-build-ts.yml @@ -15,7 +15,7 @@ jobs: run: sudo apt-get install rsync continue-on-error: true - uses: rlespinasse/github-slug-action@v3.x - - uses: actions/setup-node@v3 + - uses: actions/setup-node@v4 with: node-version: 18 - name: Setup yarn diff --git a/.github/workflows/ci-docs.yml b/.github/workflows/ci-docs.yml index 44bc46ee85..12fb22be4e 100644 --- a/.github/workflows/ci-docs.yml +++ b/.github/workflows/ci-docs.yml @@ -21,7 +21,7 @@ jobs: - name: Install rsync run: sudo apt-get install rsync - uses: rlespinasse/github-slug-action@v3.x - - uses: actions/setup-node@v3 + - uses: actions/setup-node@v4 with: node-version: 18 - name: Install Rust stable diff --git a/.github/workflows/ci-lint-typescript.yml b/.github/workflows/ci-lint-typescript.yml index ab9ee4e8eb..f14b713c45 100644 --- a/.github/workflows/ci-lint-typescript.yml +++ b/.github/workflows/ci-lint-typescript.yml @@ -18,7 +18,7 @@ jobs: - uses: actions/checkout@v4 - uses: rlespinasse/github-slug-action@v3.x - - uses: actions/setup-node@v3 + - uses: actions/setup-node@v4 with: node-version: 18 - name: Setup yarn diff --git a/.github/workflows/ci-nym-api-tests.yml b/.github/workflows/ci-nym-api-tests.yml index 508e2718fc..5e992f26f3 100644 --- a/.github/workflows/ci-nym-api-tests.yml +++ b/.github/workflows/ci-nym-api-tests.yml @@ -24,7 +24,7 @@ jobs: run: npm install - name: Node v18 - uses: actions/setup-node@v3 + uses: actions/setup-node@v4 with: node-version: 18.1.0 diff --git a/.github/workflows/ci-nym-network-explorer.yml b/.github/workflows/ci-nym-network-explorer.yml index 4b39cd565a..82516e6ddb 100644 --- a/.github/workflows/ci-nym-network-explorer.yml +++ b/.github/workflows/ci-nym-network-explorer.yml @@ -19,7 +19,7 @@ jobs: run: sudo apt-get install rsync continue-on-error: true - uses: rlespinasse/github-slug-action@v3.x - - uses: actions/setup-node@v3 + - uses: actions/setup-node@v4 with: node-version: 18 - name: Setup yarn diff --git a/.github/workflows/ci-nym-wallet-storybook.yml b/.github/workflows/ci-nym-wallet-storybook.yml index c830deed9e..91fbfcd4e5 100644 --- a/.github/workflows/ci-nym-wallet-storybook.yml +++ b/.github/workflows/ci-nym-wallet-storybook.yml @@ -17,7 +17,7 @@ jobs: - uses: rlespinasse/github-slug-action@v3.x - - uses: actions/setup-node@v3 + - uses: actions/setup-node@v4 with: node-version: 18 diff --git a/.github/workflows/ci-sdk-docs-typescript.yml b/.github/workflows/ci-sdk-docs-typescript.yml index 382965f25a..dac1612f8b 100644 --- a/.github/workflows/ci-sdk-docs-typescript.yml +++ b/.github/workflows/ci-sdk-docs-typescript.yml @@ -15,7 +15,7 @@ jobs: run: sudo apt-get install rsync continue-on-error: true - uses: rlespinasse/github-slug-action@v3.x - - uses: actions/setup-node@v3 + - uses: actions/setup-node@v4 with: node-version: 18.17 - name: Install Rust stable diff --git a/.github/workflows/ci-sdk-wasm.yml b/.github/workflows/ci-sdk-wasm.yml index 279defeb0e..39fd471b06 100644 --- a/.github/workflows/ci-sdk-wasm.yml +++ b/.github/workflows/ci-sdk-wasm.yml @@ -15,7 +15,7 @@ jobs: steps: - uses: actions/checkout@v4 - - uses: actions/setup-node@v3 + - uses: actions/setup-node@v4 with: node-version: 18 diff --git a/.github/workflows/nightly-build.yml b/.github/workflows/nightly-build.yml index 5049401781..a8fafc32cf 100644 --- a/.github/workflows/nightly-build.yml +++ b/.github/workflows/nightly-build.yml @@ -102,7 +102,7 @@ jobs: - name: Check out repository code uses: actions/checkout@v4 - name: install npm - uses: actions/setup-node@v3 + uses: actions/setup-node@v4 if: env.WORKFLOW_CONCLUSION == 'failure' with: node-version: 18 diff --git a/.github/workflows/nightly-nym-wallet-build.yml b/.github/workflows/nightly-nym-wallet-build.yml index c98eed2fbd..21e13d2c21 100644 --- a/.github/workflows/nightly-nym-wallet-build.yml +++ b/.github/workflows/nightly-nym-wallet-build.yml @@ -65,7 +65,7 @@ jobs: - name: Check out repository code uses: actions/checkout@v4 - name: install npm - uses: actions/setup-node@v3 + uses: actions/setup-node@v4 if: env.WORKFLOW_CONCLUSION == 'failure' with: node-version: 18 diff --git a/.github/workflows/nightly-security-audit.yml b/.github/workflows/nightly-security-audit.yml index be855f5776..76806575e0 100644 --- a/.github/workflows/nightly-security-audit.yml +++ b/.github/workflows/nightly-security-audit.yml @@ -36,7 +36,7 @@ jobs: name: report path: .github/workflows/support-files/notifications - name: install npm - uses: actions/setup-node@v3 + uses: actions/setup-node@v4 with: node-version: 18 - name: Matrix - Node Install diff --git a/.github/workflows/publish-nym-wallet-macos.yml b/.github/workflows/publish-nym-wallet-macos.yml index d8a7a04f0b..18c54d6b72 100644 --- a/.github/workflows/publish-nym-wallet-macos.yml +++ b/.github/workflows/publish-nym-wallet-macos.yml @@ -28,7 +28,7 @@ jobs: - uses: actions/checkout@v4 - name: Node - uses: actions/setup-node@v3 + uses: actions/setup-node@v4 with: node-version: 18 - name: Install Rust stable diff --git a/.github/workflows/publish-nym-wallet-ubuntu.yml b/.github/workflows/publish-nym-wallet-ubuntu.yml index 6f27780fac..12c3d3c823 100644 --- a/.github/workflows/publish-nym-wallet-ubuntu.yml +++ b/.github/workflows/publish-nym-wallet-ubuntu.yml @@ -34,7 +34,7 @@ jobs: continue-on-error: true - name: Node - uses: actions/setup-node@v3 + uses: actions/setup-node@v4 with: node-version: 18 diff --git a/.github/workflows/publish-nym-wallet-win10.yml b/.github/workflows/publish-nym-wallet-win10.yml index 0130d2b735..9deca2aec8 100644 --- a/.github/workflows/publish-nym-wallet-win10.yml +++ b/.github/workflows/publish-nym-wallet-win10.yml @@ -47,7 +47,7 @@ jobs: Import-PfxCertificate -FilePath certificate/certificate.pfx -CertStoreLocation Cert:\CurrentUser\My -Password (ConvertTo-SecureString -String $env:WINDOWS_CERTIFICATE_PASSWORD -Force -AsPlainText) - name: Node - uses: actions/setup-node@v3 + uses: actions/setup-node@v4 with: node-version: 18 diff --git a/.github/workflows/publish-sdk-npm.yml b/.github/workflows/publish-sdk-npm.yml index 7c29bbed34..583006b638 100644 --- a/.github/workflows/publish-sdk-npm.yml +++ b/.github/workflows/publish-sdk-npm.yml @@ -9,7 +9,7 @@ jobs: - uses: actions/checkout@v4 - name: Install Node - uses: actions/setup-node@v3 + uses: actions/setup-node@v4 with: node-version: 18 registry-url: "https://registry.npmjs.org" diff --git a/.github/workflows/release-calculate-hash.yml b/.github/workflows/release-calculate-hash.yml index 4b82bb3b98..9d27e2ba52 100644 --- a/.github/workflows/release-calculate-hash.yml +++ b/.github/workflows/release-calculate-hash.yml @@ -21,7 +21,7 @@ jobs: steps: - name: Check out repository code uses: actions/checkout@v4 - - uses: actions/setup-node@v3 + - uses: actions/setup-node@v4 with: node-version: 18 - uses: nymtech/nym/.github/actions/nym-hash-releases@develop From bf8d54b20181828d7daa1e56003d35188076c9f4 Mon Sep 17 00:00:00 2001 From: "dependabot[bot]" <49699333+dependabot[bot]@users.noreply.github.com> Date: Mon, 2 Sep 2024 14:36:44 +0200 Subject: [PATCH 52/93] build(deps): bump softprops/action-gh-release from 1 to 2 (#4818) Bumps [softprops/action-gh-release](https://github.com/softprops/action-gh-release) from 1 to 2. - [Release notes](https://github.com/softprops/action-gh-release/releases) - [Changelog](https://github.com/softprops/action-gh-release/blob/master/CHANGELOG.md) - [Commits](https://github.com/softprops/action-gh-release/compare/v1...v2) --- updated-dependencies: - dependency-name: softprops/action-gh-release dependency-type: direct:production update-type: version-update:semver-major ... Signed-off-by: dependabot[bot] Co-authored-by: dependabot[bot] <49699333+dependabot[bot]@users.noreply.github.com> --- .github/workflows/publish-nym-binaries.yml | 2 +- .github/workflows/publish-nym-contracts.yml | 2 +- .github/workflows/publish-nym-wallet-macos.yml | 2 +- .github/workflows/publish-nym-wallet-ubuntu.yml | 2 +- .github/workflows/publish-nym-wallet-win10.yml | 2 +- .github/workflows/publish-nyms5-android-apk.yml | 2 +- 6 files changed, 6 insertions(+), 6 deletions(-) diff --git a/.github/workflows/publish-nym-binaries.yml b/.github/workflows/publish-nym-binaries.yml index 422b09dcda..6c5794b228 100644 --- a/.github/workflows/publish-nym-binaries.yml +++ b/.github/workflows/publish-nym-binaries.yml @@ -83,7 +83,7 @@ jobs: - id: create-release name: Upload to release based on tag name - uses: softprops/action-gh-release@v1 + uses: softprops/action-gh-release@v2 if: github.event_name == 'release' with: files: | diff --git a/.github/workflows/publish-nym-contracts.yml b/.github/workflows/publish-nym-contracts.yml index de81793ad1..a9728b0371 100644 --- a/.github/workflows/publish-nym-contracts.yml +++ b/.github/workflows/publish-nym-contracts.yml @@ -40,7 +40,7 @@ jobs: retention-days: 5 - name: Upload to release based on tag name - uses: softprops/action-gh-release@v1 + uses: softprops/action-gh-release@v2 if: github.event_name == 'release' with: files: | diff --git a/.github/workflows/publish-nym-wallet-macos.yml b/.github/workflows/publish-nym-wallet-macos.yml index 18c54d6b72..c563b44acf 100644 --- a/.github/workflows/publish-nym-wallet-macos.yml +++ b/.github/workflows/publish-nym-wallet-macos.yml @@ -95,7 +95,7 @@ jobs: security delete-keychain $RUNNER_TEMP/app-signing.keychain-db - id: create-release name: Upload to release based on tag name - uses: softprops/action-gh-release@v1 + uses: softprops/action-gh-release@v2 if: github.event_name == 'release' with: files: | diff --git a/.github/workflows/publish-nym-wallet-ubuntu.yml b/.github/workflows/publish-nym-wallet-ubuntu.yml index 12c3d3c823..4004399297 100644 --- a/.github/workflows/publish-nym-wallet-ubuntu.yml +++ b/.github/workflows/publish-nym-wallet-ubuntu.yml @@ -70,7 +70,7 @@ jobs: - id: create-release name: Upload to release based on tag name - uses: softprops/action-gh-release@v1 + uses: softprops/action-gh-release@v2 if: github.event_name == 'release' with: files: | diff --git a/.github/workflows/publish-nym-wallet-win10.yml b/.github/workflows/publish-nym-wallet-win10.yml index 9deca2aec8..616ce99c8c 100644 --- a/.github/workflows/publish-nym-wallet-win10.yml +++ b/.github/workflows/publish-nym-wallet-win10.yml @@ -90,7 +90,7 @@ jobs: - id: create-release name: Upload to release based on tag name - uses: softprops/action-gh-release@v1 + uses: softprops/action-gh-release@v2 if: github.event_name == 'release' with: files: | diff --git a/.github/workflows/publish-nyms5-android-apk.yml b/.github/workflows/publish-nyms5-android-apk.yml index 29b1cdc385..ab665ea660 100644 --- a/.github/workflows/publish-nyms5-android-apk.yml +++ b/.github/workflows/publish-nyms5-android-apk.yml @@ -104,7 +104,7 @@ jobs: name: nyms5-apk-arch64 path: apk - name: Release - uses: softprops/action-gh-release@v1 + uses: softprops/action-gh-release@v2 with: files: | apk/nyms5-arch64-debug.apk From 3d8520dfc7d2f9b99e028f69733571aa2666d575 Mon Sep 17 00:00:00 2001 From: "dependabot[bot]" <49699333+dependabot[bot]@users.noreply.github.com> Date: Mon, 2 Sep 2024 14:37:10 +0200 Subject: [PATCH 53/93] build(deps): bump actions/upload-artifact from 2 to 4 (#4817) Bumps [actions/upload-artifact](https://github.com/actions/upload-artifact) from 2 to 4. - [Release notes](https://github.com/actions/upload-artifact/releases) - [Commits](https://github.com/actions/upload-artifact/compare/v2...v4) --- updated-dependencies: - dependency-name: actions/upload-artifact dependency-type: direct:production update-type: version-update:semver-major ... Signed-off-by: dependabot[bot] Co-authored-by: dependabot[bot] <49699333+dependabot[bot]@users.noreply.github.com> --- .github/workflows/ci-build-upload-binaries.yml | 2 +- .github/workflows/publish-nym-binaries.yml | 2 +- .github/workflows/publish-nym-contracts.yml | 4 ++-- .github/workflows/publish-nym-wallet-macos.yml | 2 +- .github/workflows/publish-nym-wallet-ubuntu.yml | 2 +- .github/workflows/publish-nym-wallet-win10.yml | 2 +- .github/workflows/release-calculate-hash.yml | 2 +- 7 files changed, 8 insertions(+), 8 deletions(-) diff --git a/.github/workflows/ci-build-upload-binaries.yml b/.github/workflows/ci-build-upload-binaries.yml index 5784398f07..c30f9c3528 100644 --- a/.github/workflows/ci-build-upload-binaries.yml +++ b/.github/workflows/ci-build-upload-binaries.yml @@ -91,7 +91,7 @@ jobs: - name: Upload Artifact if: github.event_name == 'workflow_dispatch' - uses: actions/upload-artifact@v3 + uses: actions/upload-artifact@v4 with: name: nym-binaries-artifacts path: | diff --git a/.github/workflows/publish-nym-binaries.yml b/.github/workflows/publish-nym-binaries.yml index 6c5794b228..0b87eb5380 100644 --- a/.github/workflows/publish-nym-binaries.yml +++ b/.github/workflows/publish-nym-binaries.yml @@ -67,7 +67,7 @@ jobs: args: --workspace --release ${{ env.CARGO_FEATURES }} - name: Upload Artifact - uses: actions/upload-artifact@v3 + uses: actions/upload-artifact@v4 with: name: my-artifact path: | diff --git a/.github/workflows/publish-nym-contracts.yml b/.github/workflows/publish-nym-contracts.yml index a9728b0371..85f1363b9b 100644 --- a/.github/workflows/publish-nym-contracts.yml +++ b/.github/workflows/publish-nym-contracts.yml @@ -26,14 +26,14 @@ jobs: run: make contracts - name: Upload Mixnet Contract Artifact - uses: actions/upload-artifact@v3 + uses: actions/upload-artifact@v4 with: name: mixnet_contract.wasm path: contracts/target/wasm32-unknown-unknown/release/mixnet_contract.wasm retention-days: 5 - name: Upload Vesting Contract Artifact - uses: actions/upload-artifact@v3 + uses: actions/upload-artifact@v4 with: name: vesting_contract.wasm path: contracts/target/wasm32-unknown-unknown/release/vesting_contract.wasm diff --git a/.github/workflows/publish-nym-wallet-macos.yml b/.github/workflows/publish-nym-wallet-macos.yml index c563b44acf..2f7d05a347 100644 --- a/.github/workflows/publish-nym-wallet-macos.yml +++ b/.github/workflows/publish-nym-wallet-macos.yml @@ -83,7 +83,7 @@ jobs: run: yarn && yarn build - name: Upload Artifact - uses: actions/upload-artifact@v3 + uses: actions/upload-artifact@v4 with: name: nym-wallet.app.tar.gz path: nym-wallet/target/release/bundle/macos/nym-wallet.app.tar.gz diff --git a/.github/workflows/publish-nym-wallet-ubuntu.yml b/.github/workflows/publish-nym-wallet-ubuntu.yml index 4004399297..25ed53db30 100644 --- a/.github/workflows/publish-nym-wallet-ubuntu.yml +++ b/.github/workflows/publish-nym-wallet-ubuntu.yml @@ -62,7 +62,7 @@ jobs: TAURI_KEY_PASSWORD: ${{ secrets.TAURI_KEY_PASSWORD }} - name: Upload Artifact - uses: actions/upload-artifact@v3 + uses: actions/upload-artifact@v4 with: name: nym-wallet_1.0.0_amd64.AppImage.tar.gz path: nym-wallet/target/release/bundle/appimage/nym-wallet*.AppImage.tar.gz diff --git a/.github/workflows/publish-nym-wallet-win10.yml b/.github/workflows/publish-nym-wallet-win10.yml index 616ce99c8c..86b2b2f275 100644 --- a/.github/workflows/publish-nym-wallet-win10.yml +++ b/.github/workflows/publish-nym-wallet-win10.yml @@ -82,7 +82,7 @@ jobs: run: yarn build - name: Upload Artifact - uses: actions/upload-artifact@v3 + uses: actions/upload-artifact@v4 with: name: nym-wallet_1.0.0_x64_en-US.msi path: nym-wallet/target/release/bundle/msi/nym-wallet_1.*.msi diff --git a/.github/workflows/release-calculate-hash.yml b/.github/workflows/release-calculate-hash.yml index 9d27e2ba52..f1a53c09c7 100644 --- a/.github/workflows/release-calculate-hash.yml +++ b/.github/workflows/release-calculate-hash.yml @@ -30,7 +30,7 @@ jobs: with: release-tag-or-name-or-id: ${{ inputs.release_tag }} - - uses: actions/upload-artifact@v2 + - uses: actions/upload-artifact@v4 with: name: Asset Hashes path: hashes.json From 51d1803ddde8e7e5fcfa847fabfffbc70d6f3809 Mon Sep 17 00:00:00 2001 From: =?UTF-8?q?Jon=20H=C3=A4ggblad?= Date: Mon, 2 Sep 2024 15:24:52 +0200 Subject: [PATCH 54/93] Run cargo autoinherit following last weeks dependabot updates (#4831) --- common/client-libs/validator-client/Cargo.toml | 2 +- common/commands/Cargo.toml | 4 ++-- common/credentials/Cargo.toml | 2 +- common/dkg/Cargo.toml | 2 +- common/mixnode-common/Cargo.toml | 2 +- common/nymcoconut/Cargo.toml | 2 +- common/nymsphinx/addressing/Cargo.toml | 2 +- common/store-cipher/Cargo.toml | 2 +- common/wireguard-types/Cargo.toml | 2 +- explorer-api/Cargo.toml | 2 +- service-providers/ip-packet-router/Cargo.toml | 2 +- service-providers/network-requester/Cargo.toml | 2 +- tools/nym-cli/Cargo.toml | 2 +- 13 files changed, 14 insertions(+), 14 deletions(-) diff --git a/common/client-libs/validator-client/Cargo.toml b/common/client-libs/validator-client/Cargo.toml index dee9577516..6e8dd55772 100644 --- a/common/client-libs/validator-client/Cargo.toml +++ b/common/client-libs/validator-client/Cargo.toml @@ -9,7 +9,7 @@ license.workspace = true # See more keys and their definitions at https://doc.rust-lang.org/cargo/reference/manifest.html [dependencies] -base64 = "0.22" +base64 = { workspace = true } colored = { workspace = true } nym-coconut-dkg-common = { path = "../../cosmwasm-smart-contracts/coconut-dkg" } diff --git a/common/commands/Cargo.toml b/common/commands/Cargo.toml index eb27029330..0754aa6f11 100644 --- a/common/commands/Cargo.toml +++ b/common/commands/Cargo.toml @@ -7,7 +7,7 @@ license.workspace = true [dependencies] anyhow = { workspace = true } -base64 = "0.22.1" +base64 = { workspace = true } bip39 = { workspace = true } bs58 = { workspace = true } comfy-table = { workspace = true } @@ -21,7 +21,7 @@ humantime-serde = { workspace = true } inquire = { workspace = true } k256 = { workspace = true, features = ["ecdsa", "sha256"] } log = { workspace = true } -rand = {version = "0.8", features = ["std"] } +rand = { workspace = true, features = ["std"] } serde = { workspace = true, features = ["derive"] } serde_json = { workspace = true } thiserror = { workspace = true } diff --git a/common/credentials/Cargo.toml b/common/credentials/Cargo.toml index 48159258fc..569c5736cb 100644 --- a/common/credentials/Cargo.toml +++ b/common/credentials/Cargo.toml @@ -27,5 +27,5 @@ nym-ecash-contract-common = { path = "../cosmwasm-smart-contracts/ecash-contract nym-network-defaults = { path = "../network-defaults" } [dev-dependencies] -rand = "0.8.5" +rand = { workspace = true } diff --git a/common/dkg/Cargo.toml b/common/dkg/Cargo.toml index f506d38e86..799e38a702 100644 --- a/common/dkg/Cargo.toml +++ b/common/dkg/Cargo.toml @@ -18,7 +18,7 @@ bs58 = { workspace = true } lazy_static = { workspace = true } -rand = { version = "0.8.5", default-features = false} +rand = { workspace = true } rand_chacha = { workspace = true } rand_core = { workspace = true } sha2 = "0.9" diff --git a/common/mixnode-common/Cargo.toml b/common/mixnode-common/Cargo.toml index 6c2aedff06..a955aba65d 100644 --- a/common/mixnode-common/Cargo.toml +++ b/common/mixnode-common/Cargo.toml @@ -12,7 +12,7 @@ bytes = { workspace = true } futures = { workspace = true } humantime-serde = { workspace = true } log = { workspace = true } -rand = "0.8" +rand = { workspace = true } serde = { workspace = true, features = ["derive"] } tokio = { workspace = true, features = [ "time", diff --git a/common/nymcoconut/Cargo.toml b/common/nymcoconut/Cargo.toml index bb4e924d30..c4266b3459 100644 --- a/common/nymcoconut/Cargo.toml +++ b/common/nymcoconut/Cargo.toml @@ -11,7 +11,7 @@ license.workspace = true bls12_381 = { workspace = true, default-features = false, features = ["pairings", "alloc", "experimental"] } itertools = { workspace = true } digest = "0.9" -rand = "0.8" +rand = { workspace = true } thiserror = { workspace = true } serde = { workspace = true } serde_derive = { workspace = true } diff --git a/common/nymsphinx/addressing/Cargo.toml b/common/nymsphinx/addressing/Cargo.toml index 049dcd9a49..4131dc751f 100644 --- a/common/nymsphinx/addressing/Cargo.toml +++ b/common/nymsphinx/addressing/Cargo.toml @@ -14,5 +14,5 @@ serde = { workspace = true } # implementing serialization/deserialization for so thiserror = { workspace = true } [dev-dependencies] -rand = "0.8.5" +rand = { workspace = true } nym-crypto = { path = "../../crypto", features = ["rand"] } diff --git a/common/store-cipher/Cargo.toml b/common/store-cipher/Cargo.toml index 7e391788ad..ca0a628635 100644 --- a/common/store-cipher/Cargo.toml +++ b/common/store-cipher/Cargo.toml @@ -10,7 +10,7 @@ license.workspace = true aes-gcm = { workspace = true } argon2 = { workspace = true } generic-array = { workspace = true, features = ["zeroize"] } -rand = "0.8.5" +rand = { workspace = true } serde = { workspace = true, features = ["derive"] } serde_json = { workspace = true, optional = true } thiserror = { workspace = true } diff --git a/common/wireguard-types/Cargo.toml b/common/wireguard-types/Cargo.toml index 27fe541f67..d0c387fe89 100644 --- a/common/wireguard-types/Cargo.toml +++ b/common/wireguard-types/Cargo.toml @@ -33,7 +33,7 @@ serde_json = { workspace = true, optional = true } x25519-dalek = { workspace = true, features = ["static_secrets"] } [dev-dependencies] -rand = "0.8.5" +rand = { workspace = true } nym-crypto = { path = "../crypto", features = ["rand"] } diff --git a/explorer-api/Cargo.toml b/explorer-api/Cargo.toml index 2a33ae5fc8..a7cf940f9c 100644 --- a/explorer-api/Cargo.toml +++ b/explorer-api/Cargo.toml @@ -17,7 +17,7 @@ log = { workspace = true } maxminddb = { workspace = true } okapi = { workspace = true, features = ["impl_json_schema"] } pretty_env_logger = { workspace = true } -rand = "0.8.5" +rand = { workspace = true } rand_pcg = { workspace = true } rand_seeder = { workspace = true } reqwest = { workspace = true } diff --git a/service-providers/ip-packet-router/Cargo.toml b/service-providers/ip-packet-router/Cargo.toml index d54239428f..50be33d829 100644 --- a/service-providers/ip-packet-router/Cargo.toml +++ b/service-providers/ip-packet-router/Cargo.toml @@ -34,7 +34,7 @@ nym-tun = { path = "../../common/tun" } nym-types = { path = "../../common/types" } nym-wireguard = { path = "../../common/wireguard" } nym-wireguard-types = { path = "../../common/wireguard-types" } -rand = "0.8.5" +rand = { workspace = true } reqwest.workspace = true serde = { workspace = true, features = ["derive"] } serde_json = { workspace = true } diff --git a/service-providers/network-requester/Cargo.toml b/service-providers/network-requester/Cargo.toml index 13b710e802..61d3e9cfdd 100644 --- a/service-providers/network-requester/Cargo.toml +++ b/service-providers/network-requester/Cargo.toml @@ -24,7 +24,7 @@ clap = { workspace = true, features = ["cargo", "derive"]} dirs = { workspace = true } futures = { workspace = true } humantime-serde = { workspace = true } -ipnetwork = "0.20.0" +ipnetwork = { workspace = true } log = { workspace = true } pretty_env_logger = { workspace = true } publicsuffix = { workspace = true } diff --git a/tools/nym-cli/Cargo.toml b/tools/nym-cli/Cargo.toml index dc8e8990f9..f7ac9b56f4 100644 --- a/tools/nym-cli/Cargo.toml +++ b/tools/nym-cli/Cargo.toml @@ -6,7 +6,7 @@ edition = "2021" license.workspace = true [dependencies] -base64 = "0.22.1" +base64 = { workspace = true } bs58 = { workspace = true } clap = { workspace = true, features = ["derive"] } clap_complete = { workspace = true } From d0b380cd99588d66e0d10c190a9c8aa21aa6c718 Mon Sep 17 00:00:00 2001 From: =?UTF-8?q?Jon=20H=C3=A4ggblad?= Date: Mon, 2 Sep 2024 15:51:56 +0200 Subject: [PATCH 55/93] Remove serde_crate named import (#4832) * Run cargo autoinherit following last weeks dependabot updates * Remove serde_crate named import --- common/crypto/Cargo.toml | 4 ++-- common/crypto/src/asymmetric/encryption/mod.rs | 1 - common/crypto/src/asymmetric/identity/mod.rs | 1 - common/crypto/src/asymmetric/identity/serde_helpers.rs | 2 +- common/crypto/src/lib.rs | 3 --- common/nymsphinx/acknowledgements/Cargo.toml | 4 ++-- common/nymsphinx/acknowledgements/src/key.rs | 3 +-- contracts/coconut-bandwidth/Cargo.toml | 2 +- 8 files changed, 7 insertions(+), 13 deletions(-) diff --git a/common/crypto/Cargo.toml b/common/crypto/Cargo.toml index ff002afa0d..ebd757518b 100644 --- a/common/crypto/Cargo.toml +++ b/common/crypto/Cargo.toml @@ -21,7 +21,7 @@ x25519-dalek = { workspace = true, features = ["static_secrets"], optional = tru ed25519-dalek = { workspace = true, features = ["rand_core"], optional = true } rand = { workspace = true, optional = true } serde_bytes = { workspace = true, optional = true } -serde_crate = { version = "1.0", optional = true, default-features = false, features = ["derive"], package = "serde" } +serde = { version = "1.0", optional = true, default-features = false, features = ["derive"] } subtle-encoding = { workspace = true, features = ["bech32-preview"] } thiserror = { workspace = true } zeroize = { workspace = true, optional = true, features = ["zeroize_derive"] } @@ -35,7 +35,7 @@ rand_chacha = { workspace = true } [features] default = ["sphinx"] -serde = ["serde_crate", "serde_bytes", "ed25519-dalek/serde", "x25519-dalek/serde"] +serde = ["dep:serde", "serde_bytes", "ed25519-dalek/serde", "x25519-dalek/serde"] asymmetric = ["x25519-dalek", "ed25519-dalek", "zeroize"] hashing = ["blake3", "digest", "hkdf", "hmac", "generic-array"] symmetric = ["aes", "ctr", "cipher", "generic-array"] diff --git a/common/crypto/src/asymmetric/encryption/mod.rs b/common/crypto/src/asymmetric/encryption/mod.rs index cadb5437e4..7f501445b9 100644 --- a/common/crypto/src/asymmetric/encryption/mod.rs +++ b/common/crypto/src/asymmetric/encryption/mod.rs @@ -44,7 +44,6 @@ pub enum KeyRecoveryError { #[derive(Zeroize, ZeroizeOnDrop)] #[cfg_attr(feature = "serde", derive(Serialize, Deserialize))] -#[cfg_attr(feature = "serde", serde(crate = "serde_crate"))] pub struct KeyPair { pub(crate) private_key: PrivateKey, diff --git a/common/crypto/src/asymmetric/identity/mod.rs b/common/crypto/src/asymmetric/identity/mod.rs index f65290f907..3536782e94 100644 --- a/common/crypto/src/asymmetric/identity/mod.rs +++ b/common/crypto/src/asymmetric/identity/mod.rs @@ -55,7 +55,6 @@ pub enum Ed25519RecoveryError { /// Keypair for usage in ed25519 EdDSA. #[derive(Debug, Zeroize, ZeroizeOnDrop)] #[cfg_attr(feature = "serde", derive(Serialize, Deserialize))] -#[cfg_attr(feature = "serde", serde(crate = "serde_crate"))] pub struct KeyPair { private_key: PrivateKey, diff --git a/common/crypto/src/asymmetric/identity/serde_helpers.rs b/common/crypto/src/asymmetric/identity/serde_helpers.rs index 67f9dece70..927ca77ec7 100644 --- a/common/crypto/src/asymmetric/identity/serde_helpers.rs +++ b/common/crypto/src/asymmetric/identity/serde_helpers.rs @@ -5,7 +5,7 @@ use super::PublicKey; pub mod bs58_pubkey { use super::*; - use serde_crate::{Deserialize, Deserializer, Serializer}; + use serde::{Deserialize, Deserializer, Serializer}; pub fn serialize(key: &PublicKey, serializer: S) -> Result { serializer.serialize_str(&key.to_base58_string()) diff --git a/common/crypto/src/lib.rs b/common/crypto/src/lib.rs index 19aab595d4..4ab59949f0 100644 --- a/common/crypto/src/lib.rs +++ b/common/crypto/src/lib.rs @@ -28,6 +28,3 @@ pub use aes; pub use blake3; #[cfg(feature = "symmetric")] pub use ctr; - -#[cfg(feature = "serde")] -extern crate serde_crate as serde; diff --git a/common/nymsphinx/acknowledgements/Cargo.toml b/common/nymsphinx/acknowledgements/Cargo.toml index 0392445c41..37b3b01519 100644 --- a/common/nymsphinx/acknowledgements/Cargo.toml +++ b/common/nymsphinx/acknowledgements/Cargo.toml @@ -9,7 +9,7 @@ repository = { workspace = true } [dependencies] rand = { workspace = true } -serde_crate = { version = "1.0", optional = true, default-features = false, features = ["derive"], package = "serde" } +serde = { version = "1.0", optional = true, default-features = false, features = ["derive"] } generic-array = { workspace = true, optional = true, features = ["serde"] } thiserror = { workspace = true } zeroize = { workspace = true } @@ -23,4 +23,4 @@ nym-sphinx-types = { path = "../types", features = ["sphinx"] } nym-topology = { path = "../../topology" } [features] -serde = ["serde_crate", "generic-array"] +serde = ["dep:serde", "generic-array"] diff --git a/common/nymsphinx/acknowledgements/src/key.rs b/common/nymsphinx/acknowledgements/src/key.rs index 869f713657..8ee996cd1d 100644 --- a/common/nymsphinx/acknowledgements/src/key.rs +++ b/common/nymsphinx/acknowledgements/src/key.rs @@ -9,10 +9,9 @@ use std::fmt::{self, Display, Formatter}; use zeroize::{Zeroize, ZeroizeOnDrop}; #[cfg(feature = "serde")] -use serde_crate::{Deserialize, Serialize}; +use serde::{Deserialize, Serialize}; #[cfg_attr(feature = "serde", derive(Serialize, Deserialize))] -#[cfg_attr(feature = "serde", serde(crate = "serde_crate"))] #[derive(Zeroize, ZeroizeOnDrop)] pub struct AckKey(CipherKey); diff --git a/contracts/coconut-bandwidth/Cargo.toml b/contracts/coconut-bandwidth/Cargo.toml index 86a6a1bbfb..b810e74105 100644 --- a/contracts/coconut-bandwidth/Cargo.toml +++ b/contracts/coconut-bandwidth/Cargo.toml @@ -26,4 +26,4 @@ serde = { version = "1.0.103", default-features = false, features = ["derive"] } thiserror = { workspace = true } [features] -schema-gen = ["nym-coconut-bandwidth-contract-common/schema", "cosmwasm-schema"] \ No newline at end of file +schema-gen = ["nym-coconut-bandwidth-contract-common/schema", "cosmwasm-schema"] From 4be5af0c40743c9a90620d0c49ffab153b9093a2 Mon Sep 17 00:00:00 2001 From: "dependabot[bot]" <49699333+dependabot[bot]@users.noreply.github.com> Date: Tue, 3 Sep 2024 09:55:23 +0200 Subject: [PATCH 56/93] build(deps): bump technote-space/workflow-conclusion-action from 2 to 3 (#4836) Bumps [technote-space/workflow-conclusion-action](https://github.com/technote-space/workflow-conclusion-action) from 2 to 3. - [Release notes](https://github.com/technote-space/workflow-conclusion-action/releases) - [Changelog](https://github.com/technote-space/workflow-conclusion-action/blob/main/.releasegarc) - [Commits](https://github.com/technote-space/workflow-conclusion-action/compare/v2...v3) --- updated-dependencies: - dependency-name: technote-space/workflow-conclusion-action dependency-type: direct:production update-type: version-update:semver-major ... Signed-off-by: dependabot[bot] Co-authored-by: dependabot[bot] <49699333+dependabot[bot]@users.noreply.github.com> --- .github/workflows/nightly-build.yml | 2 +- .github/workflows/nightly-nym-wallet-build.yml | 2 +- 2 files changed, 2 insertions(+), 2 deletions(-) diff --git a/.github/workflows/nightly-build.yml b/.github/workflows/nightly-build.yml index a8fafc32cf..d7b1c29563 100644 --- a/.github/workflows/nightly-build.yml +++ b/.github/workflows/nightly-build.yml @@ -98,7 +98,7 @@ jobs: runs-on: custom-linux steps: - name: Collect jobs status - uses: technote-space/workflow-conclusion-action@v2 + uses: technote-space/workflow-conclusion-action@v3 - name: Check out repository code uses: actions/checkout@v4 - name: install npm diff --git a/.github/workflows/nightly-nym-wallet-build.yml b/.github/workflows/nightly-nym-wallet-build.yml index 21e13d2c21..232a1273ef 100644 --- a/.github/workflows/nightly-nym-wallet-build.yml +++ b/.github/workflows/nightly-nym-wallet-build.yml @@ -61,7 +61,7 @@ jobs: runs-on: custom-linux steps: - name: Collect jobs status - uses: technote-space/workflow-conclusion-action@v2 + uses: technote-space/workflow-conclusion-action@v3 - name: Check out repository code uses: actions/checkout@v4 - name: install npm From 3300942529e80770300445e26f26fd8072ccf9e7 Mon Sep 17 00:00:00 2001 From: import this <97586125+serinko@users.noreply.github.com> Date: Tue, 3 Sep 2024 09:23:30 +0000 Subject: [PATCH 57/93] Update node_api_check.py & Documentation (#4835) * update API endpoints and node API check CLI * cleanup of commented code * update node_api_check guide --- .../operators/src/testing/node-api-check.md | 15 ++++++++++----- scripts/api_endpoints.json | 2 +- scripts/node_api_check.py | 19 ++++++++++++++++--- 3 files changed, 27 insertions(+), 9 deletions(-) diff --git a/documentation/operators/src/testing/node-api-check.md b/documentation/operators/src/testing/node-api-check.md index 1e11ddeed7..3c2e19d1c0 100644 --- a/documentation/operators/src/testing/node-api-check.md +++ b/documentation/operators/src/testing/node-api-check.md @@ -111,11 +111,12 @@ The most common usage may be `./node_api_check.py query_stats ` where `< **Optional arguments** -| Flag | Shortcut | Description | -| :--- | :--- | :--- | -| `--markdown` | `-m` | returns output in markdown format | -| `--no_routing_history` | `-n` | returns output without routing history which can be lengthy | -| `--output` | `-o` | exports output to a file, possible to add a target path | +| Flag | Shortcut | Description | +| :--- | :--- | :--- | +| `--markdown` | `-m` | returns output in markdown format | +| `--no_routing_history` | None | returns output without routing history which can be lengthy | +| `--no_verloc_metrics` | None | returns output without verloc measurement which can be lengthy | +| `--output` | `-o` | exports output to a file, possible to add a target path | #### `version_count` @@ -123,3 +124,7 @@ Another command is `version_count` where at least one `nym-node` version is requ ```sh ./node_api_check version_count 1.1.0 1.1.1 1.1.2 1.1.3 --markdown ``` + +```admonish tip +To see a quick overview of `nym-node` version distribution in numbers and graph, visit [Nym Harbourmaster](https://harbourmaster.nymtech.net). +``` diff --git a/scripts/api_endpoints.json b/scripts/api_endpoints.json index 32bde5647d..fb67859b79 100644 --- a/scripts/api_endpoints.json +++ b/scripts/api_endpoints.json @@ -5,7 +5,6 @@ "/status/mixnode/{mix_id}/core-status-count", "/status/mixnode/{mix_id}/status", "/status/mixnode/{mix_id}/reward-estimation", - "/status/mixnode/{mix_id}/compute-reward-estimation", "/status/mixnode/{mix_id}/stake-saturation", "/status/mixnode/{mix_id}/inclusion-probability", "/status/mixnode/{mix_id}/avg_uptime" @@ -23,6 +22,7 @@ "swagger":[ "/roles", + "/auxiliary-details", "/build-information", "/description", "/host-information", diff --git a/scripts/node_api_check.py b/scripts/node_api_check.py index 8fcfe52b72..ee9decea3d 100755 --- a/scripts/node_api_check.py +++ b/scripts/node_api_check.py @@ -35,21 +35,29 @@ class MainFunctions: print(f"Identity Key = {id_key}") print(f"Host = {host}") print(f"Version = {version}") + toc = "Swagger page is not accessible. T&Cs are unrecognized and treated as False!" + if swagger_data: + toc = swagger_data["/auxiliary-details"]["accepted_operator_terms_and_conditions"] + print(f"T&Cs = {toc}") + if mix_id: print(f"Mix ID = {mix_id}") print("\n\nNODE RESULTS FROM UNFILTERED QUERY\n") + if args.markdown: node_markdown = self._dataframe_to_markdown(node_df, ["RESULT"], ["API EDNPOINT"]) print(node_markdown, "\n") else: self.print_neat_dict(node_dict) print(f"\n\nNODE RESULTS FROM {self.api_url.upper()}\n") + if args.markdown: api_df = self._json_to_dataframe(api_data) node_markdown = self._dataframe_to_markdown(api_df, ["RESULT"], ["API EDNPOINT"]) print(node_markdown, "\n") else: self.print_neat_dict(api_data) + if swagger_data: print(f"\n\nNODE RESULTS FROM SWAGGER PAGE\n") if args.markdown: @@ -61,6 +69,7 @@ class MainFunctions: print(swagger_data) else: swagger_data = f"\nSwagger API endpoints of node {id_key} hosted on IP: {host} are not responding. Maybe you querying a deprecated version of nym-mixnode or the VPS ports are not open correctly.\n" + if routing_history: print(f"\n\nNODE UPTIME HISTORY\n") if args.markdown: @@ -71,13 +80,14 @@ class MainFunctions: routing_history = self._json_neat_format(routing_history) else: routing_history = " " + if args.output or args.output == "": node_dict = self._json_neat_format(node_dict) api_data = self._json_neat_format(api_data) if role: - data_list = [f"Id. Key = {id_key}", f"Host = {host}", f"Type = {mode}", f"Mode = {role}", node_dict, api_data, swagger_data, routing_history] + data_list = [f"Id. Key = {id_key}", f"Host = {host}", f"Type = {mode}", f"Mode = {role}", f"T&Cs = {toc}", node_dict, api_data, swagger_data, routing_history] else: - data_list = [f"Id. Key = {id_key}", f"Host = {host}", f"Type = {mode}", node_dict, api_data, swagger_data, routing_history] + data_list = [f"Id. Key = {id_key}", f"Host = {host}", f"Type = {mode}", f"T&Cs = {toc}", node_dict, api_data, swagger_data, routing_history] self.output.concat_to_file(args, data_list) def collect_all_results(self,args): @@ -118,6 +128,8 @@ class MainFunctions: dicts = json.load(f) endpoints = dicts[mode] swagger = dicts["swagger"] + if args.no_verloc_metrics: + swagger.remove("/metrics/verloc") api_data = {} swagger_data = {} routing_history = {} @@ -364,7 +376,8 @@ class ArgParser: # pull_stats arguments parser_pull_stats.add_argument("id", help="supply nym-node identity key") - parser_pull_stats.add_argument("-n","--no_routing_history", help="Display node stats without routing history", action="store_true") + parser_pull_stats.add_argument("--no_routing_history", help="Display node stats without routing history", action="store_true") + parser_pull_stats.add_argument("--no_verloc_metrics", help="Display node stats without verloc metrics", action="store_true") parser_pull_stats.add_argument("-m","--markdown",help="Display results in markdown format", action="store_true") parser_pull_stats.add_argument("-o","--output",help="Save results to file (in current dir or supply with path without filename)", nargs='?',const="", type=str) parser_pull_stats.set_defaults(func=self.functions.display_results) From 17bdb583b58ab4360caafd6da05ea5ab2d451557 Mon Sep 17 00:00:00 2001 From: Mark Sinclair <14054343+mmsinclair@users.noreply.github.com> Date: Tue, 3 Sep 2024 11:34:31 +0100 Subject: [PATCH 58/93] Add get_mixnodes_described to validator_client (#4725) * Add get_mixnodes_described to validator_client * Add methods to client to get blacklisted mixnodes and gateways --------- Co-authored-by: Mark Sinclair --- Cargo.lock | 694 +++++++++--------- .../validator-client/src/nym_api/mod.rs | 45 +- .../validator-client/src/nym_api/routes.rs | 1 + 3 files changed, 387 insertions(+), 353 deletions(-) diff --git a/Cargo.lock b/Cargo.lock index 96986ad666..4efaa347bd 100644 --- a/Cargo.lock +++ b/Cargo.lock @@ -17,7 +17,7 @@ dependencies = [ "macroific", "proc-macro2", "quote", - "syn 2.0.66", + "syn 2.0.63", ] [[package]] @@ -32,9 +32,9 @@ dependencies = [ [[package]] name = "addr2line" -version = "0.22.0" +version = "0.21.0" source = "registry+https://github.com/rust-lang/crates.io-index" -checksum = "6e4503c46a5c0c7844e948c9a4d6acd9f50cccb4de1c48eb9e291ea17470c678" +checksum = "8a30b2e23b9e17a9f90641c7ab1549cd9b44f296d3ccbf309d2863cfe398a0cb" dependencies = [ "gimli", ] @@ -83,7 +83,7 @@ dependencies = [ "cipher", "ctr", "ghash", - "subtle 2.6.1", + "subtle 2.5.0", ] [[package]] @@ -194,9 +194,9 @@ dependencies = [ [[package]] name = "anstyle-query" -version = "1.1.0" +version = "1.0.3" source = "registry+https://github.com/rust-lang/crates.io-index" -checksum = "ad186efb764318d35165f1758e7dcef3b10628e26d41a44bc5550652e6804391" +checksum = "a64c907d4e79225ac72e2a354c9ce84d50ebb4586dee56c82b3ee73004f537f5" dependencies = [ "windows-sys 0.52.0", ] @@ -213,9 +213,9 @@ dependencies = [ [[package]] name = "anyhow" -version = "1.0.86" +version = "1.0.83" source = "registry+https://github.com/rust-lang/crates.io-index" -checksum = "b3d1d046238990b9cf5bcde22a3fb3584ee5cf65fb2765f454ed428c7a0063da" +checksum = "25bdb32cbbdce2b519a9cd7df3a678443100e265d5e25ca763b7572a5104f5f3" [[package]] name = "arbitrary" @@ -280,7 +280,7 @@ checksum = "16e62a023e7c117e27523144c5d2459f4397fcc3cab0085af8e2224f643a0193" dependencies = [ "proc-macro2", "quote", - "syn 2.0.66", + "syn 2.0.63", ] [[package]] @@ -291,7 +291,7 @@ checksum = "6e0c28dcc82d7c8ead5cb13beb15405b57b8546e93215673ff8ca0349a028107" dependencies = [ "proc-macro2", "quote", - "syn 2.0.66", + "syn 2.0.63", ] [[package]] @@ -304,7 +304,7 @@ dependencies = [ "futures-util", "log", "pin-project-lite", - "rustls-native-certs 0.7.0", + "rustls-native-certs 0.7.3", "rustls-pki-types", "tokio", "tokio-rustls 0.25.0", @@ -365,7 +365,7 @@ dependencies = [ "futures-util", "http 0.2.12", "http-body 0.4.6", - "hyper 0.14.29", + "hyper 0.14.28", "itoa", "matchit", "memchr", @@ -393,7 +393,7 @@ dependencies = [ "http 1.1.0", "http-body 1.0.0", "http-body-util", - "hyper 1.4.0", + "hyper 1.3.1", "hyper-util", "itoa", "matchit", @@ -477,15 +477,15 @@ dependencies = [ [[package]] name = "backtrace" -version = "0.3.73" +version = "0.3.71" source = "registry+https://github.com/rust-lang/crates.io-index" -checksum = "5cc23269a4f8976d0a4d2e7109211a419fe30e8d88d677cd60b6bc79c5732e0a" +checksum = "26b05800d2e817c8b3b4b54abd461726265fa9789ae34330622f2db9ee696f9d" dependencies = [ "addr2line", "cc", "cfg-if", "libc", - "miniz_oxide 0.7.3", + "miniz_oxide 0.7.2", "object", "rustc-demangle", ] @@ -547,7 +547,7 @@ dependencies = [ "rand_core 0.6.4", "ripemd", "sha2 0.10.8", - "subtle 2.6.1", + "subtle 2.5.0", "zeroize", ] @@ -585,9 +585,9 @@ checksum = "bef38d45163c2f1dde094a7dfd33ccf595c92905c8f8f4fdc18d06fb1037718a" [[package]] name = "bitflags" -version = "2.6.0" +version = "2.5.0" source = "registry+https://github.com/rust-lang/crates.io-index" -checksum = "b048fb63fd8b5923fc5aa7b340d8e156aec7ec02f0c78fa8a6ddc2613f6f71de" +checksum = "cf4b9d6a944f767f8e5e0db018570623c85f3d925ac718db4e06d0187adb21c1" [[package]] name = "bitvec" @@ -686,7 +686,7 @@ dependencies = [ "rand_core 0.6.4", "serde", "serdect 0.3.0-pre.0", - "subtle 2.6.1", + "subtle 2.5.0", "zeroize", ] @@ -730,9 +730,9 @@ dependencies = [ [[package]] name = "bytemuck" -version = "1.16.1" +version = "1.16.0" source = "registry+https://github.com/rust-lang/crates.io-index" -checksum = "b236fc92302c97ed75b38da1f4917b5cdda4984745740f153a5d3059e48d725e" +checksum = "78834c15cb5d5efe3452d58b1e8ba890dd62d21907f867f383358198e56ebca5" [[package]] name = "byteorder" @@ -751,9 +751,9 @@ dependencies = [ [[package]] name = "camino" -version = "1.1.7" +version = "1.1.6" source = "registry+https://github.com/rust-lang/crates.io-index" -checksum = "e0ec6b951b160caa93cc0c7b209e5a3bff7aae9062213451ac99493cd844c239" +checksum = "c59e92b5a388f549b863a7bea62612c09f24c8393560709a54558a9abdfb3b9c" dependencies = [ "serde", ] @@ -795,9 +795,9 @@ checksum = "a2698f953def977c68f935bb0dfa959375ad4638570e969e2f1e9f433cbf1af6" [[package]] name = "cc" -version = "1.1.14" +version = "1.1.15" source = "registry+https://github.com/rust-lang/crates.io-index" -checksum = "50d2eb3cd3d1bf4529e31c215ee6f93ec5a3d536d9f578f93d9d33ee19562932" +checksum = "57b6a275aa2903740dc87da01c62040406b8812552e97129a63ea8850a17c6e6" dependencies = [ "shlex", ] @@ -825,9 +825,9 @@ checksum = "baf1de4339761588bc0619e3cbc0120ee582ebb74b53b4efbf79117bd2da40fd" [[package]] name = "cfg_aliases" -version = "0.2.1" +version = "0.1.1" source = "registry+https://github.com/rust-lang/crates.io-index" -checksum = "613afe47fcd5fac7ccf1db93babcb082c5994d996f20b8b159f2ad1658eb5724" +checksum = "fd16c4719339c4530435d38e511904438d07cce7950afa3718a84ac36c10e89e" [[package]] name = "chacha" @@ -875,7 +875,7 @@ dependencies = [ "num-traits", "serde", "wasm-bindgen", - "windows-targets 0.52.6", + "windows-targets 0.52.5", ] [[package]] @@ -946,24 +946,24 @@ checksum = "216aec2b177652e3846684cbfe25c9964d18ec45234f0f5da5157b207ed1aab6" dependencies = [ "anstream", "anstyle", - "clap_lex 0.7.1", + "clap_lex 0.7.0", "strsim 0.11.1", ] [[package]] name = "clap_complete" -version = "4.5.24" +version = "4.5.2" source = "registry+https://github.com/rust-lang/crates.io-index" -checksum = "6d7db6eca8c205649e8d3ccd05aa5042b1800a784e56bc7c43524fde8abbfa9b" +checksum = "dd79504325bf38b10165b02e89b4347300f855f273c4cb30c4a3209e6583275e" dependencies = [ "clap 4.5.16", ] [[package]] name = "clap_complete_fig" -version = "4.5.2" +version = "4.5.0" source = "registry+https://github.com/rust-lang/crates.io-index" -checksum = "d494102c8ff3951810c72baf96910b980fb065ca5d3101243e6a8dc19747c86b" +checksum = "54b3e65f91fabdd23cac3d57d39d5d938b4daabd070c335c006dccb866a61110" dependencies = [ "clap 4.5.16", "clap_complete", @@ -978,7 +978,7 @@ dependencies = [ "heck 0.5.0", "proc-macro2", "quote", - "syn 2.0.66", + "syn 2.0.63", ] [[package]] @@ -992,9 +992,9 @@ dependencies = [ [[package]] name = "clap_lex" -version = "0.7.1" +version = "0.7.0" source = "registry+https://github.com/rust-lang/crates.io-index" -checksum = "4b82cf0babdbd58558212896d1a4272303a57bdb245c2bf1147185fb45640e70" +checksum = "98cc8fbded0c607b7ba9dd60cd98df59af97e84d24e49c8557331cfc26d301ce" [[package]] name = "colorchoice" @@ -1185,8 +1185,8 @@ version = "0.20.0" source = "registry+https://github.com/rust-lang/crates.io-index" checksum = "32560304ab4c365791fd307282f76637213d8083c1a98490c35159cd67852237" dependencies = [ - "prost 0.12.6", - "prost-types 0.12.6", + "prost 0.12.4", + "prost-types 0.12.4", "tendermint-proto 0.34.1", ] @@ -1195,8 +1195,8 @@ name = "cosmos-sdk-proto" version = "0.22.0-pre" source = "git+https://github.com/cosmos/cosmos-rust?rev=4b1332e6d8258ac845cef71589c8d362a669675a#4b1332e6d8258ac845cef71589c8d362a669675a" dependencies = [ - "prost 0.12.6", - "prost-types 0.12.6", + "prost 0.12.4", + "prost-types 0.12.4", "tendermint-proto 0.37.0", ] @@ -1343,9 +1343,9 @@ checksum = "19d374276b40fb8bbdee95aef7c7fa6b5316ec764510eb64b8dd0e2ed0d7e7f5" [[package]] name = "crc32fast" -version = "1.4.2" +version = "1.4.0" source = "registry+https://github.com/rust-lang/crates.io-index" -checksum = "a97769d94ddab943e4510d138150169a2758b5ef3eb191a9ee688de3e23ef7b3" +checksum = "b3855a8a784b474f333699ef2bbca9db2c4a1f6d9088a90a2d25b1eb53111eaa" dependencies = [ "cfg-if", ] @@ -1414,9 +1414,9 @@ dependencies = [ [[package]] name = "crossbeam-channel" -version = "0.5.13" +version = "0.5.12" source = "registry+https://github.com/rust-lang/crates.io-index" -checksum = "33480d6946193aa8033910124896ca395333cae7e2d1113d1fef6c3272217df2" +checksum = "ab3db02a9c5b5121e1e42fbdb1aeb65f5e02624cc58c43f2884c6ccac0b82f95" dependencies = [ "crossbeam-utils", ] @@ -1451,9 +1451,9 @@ dependencies = [ [[package]] name = "crossbeam-utils" -version = "0.8.20" +version = "0.8.19" source = "registry+https://github.com/rust-lang/crates.io-index" -checksum = "22ec99545bb0ed0ea7bb9b8e1e9122ea386ff8a48c0922e43f36d45ab09e0e80" +checksum = "248e3bacc7dc6baa3b21e405ee045c3047101a49145e7e9eca583ab4c2ca5345" [[package]] name = "crossterm" @@ -1465,7 +1465,7 @@ dependencies = [ "crossterm_winapi", "libc", "mio 0.8.11", - "parking_lot 0.12.3", + "parking_lot 0.12.2", "signal-hook", "signal-hook-mio", "winapi", @@ -1481,7 +1481,7 @@ dependencies = [ "crossterm_winapi", "libc", "mio 0.8.11", - "parking_lot 0.12.3", + "parking_lot 0.12.2", "signal-hook", "signal-hook-mio", "winapi", @@ -1493,10 +1493,10 @@ version = "0.27.0" source = "registry+https://github.com/rust-lang/crates.io-index" checksum = "f476fe445d41c9e991fd07515a6f463074b782242ccf4a5b7b1d1012e70824df" dependencies = [ - "bitflags 2.6.0", + "bitflags 2.5.0", "crossterm_winapi", "libc", - "parking_lot 0.12.3", + "parking_lot 0.12.2", "winapi", ] @@ -1523,7 +1523,7 @@ checksum = "0dc92fb57ca44df6db8059111ab3af99a63d5d0f8375d9972e319a379c6bab76" dependencies = [ "generic-array 0.14.7", "rand_core 0.6.4", - "subtle 2.6.1", + "subtle 2.5.0", "zeroize", ] @@ -1605,9 +1605,9 @@ dependencies = [ [[package]] name = "curl-sys" -version = "0.4.73+curl-8.8.0" +version = "0.4.72+curl-8.6.0" source = "registry+https://github.com/rust-lang/crates.io-index" -checksum = "450ab250ecf17227c39afb9a2dd9261dc0035cb80f2612472fc0c4aac2dcb84d" +checksum = "29cbdc8314c447d11e8fd156dcdd031d9e02a7a976163e396b548c03153bc9ea" dependencies = [ "cc", "libc", @@ -1627,24 +1627,25 @@ dependencies = [ "byteorder", "digest 0.9.0", "rand_core 0.5.1", - "subtle 2.6.1", + "subtle 2.5.0", "zeroize", ] [[package]] name = "curve25519-dalek" -version = "4.1.3" +version = "4.1.2" source = "registry+https://github.com/rust-lang/crates.io-index" -checksum = "97fb8b7c4503de7d6ae7b42ab72a5a59857b4c937ec27a3d4539dba95b5ab2be" +checksum = "0a677b8922c94e01bdbb12126b0bc852f00447528dee1782229af9c720c3f348" dependencies = [ "cfg-if", "cpufeatures", "curve25519-dalek-derive", "digest 0.10.7", "fiat-crypto", + "platforms", "rustc_version 0.4.0", "serde", - "subtle 2.6.1", + "subtle 2.5.0", "zeroize", ] @@ -1656,7 +1657,7 @@ checksum = "f46882e17999c6cc590af592290432be3bce0428cb0d5f8b6715e4dc7b383eb3" dependencies = [ "proc-macro2", "quote", - "syn 2.0.66", + "syn 2.0.63", ] [[package]] @@ -1781,12 +1782,12 @@ dependencies = [ [[package]] name = "darling" -version = "0.20.9" +version = "0.20.8" source = "registry+https://github.com/rust-lang/crates.io-index" -checksum = "83b2eb4d90d12bdda5ed17de686c2acb4c57914f8f921b8da7e112b5a36f3fe1" +checksum = "54e36fcd13ed84ffdfda6f5be89b31287cbb80c439841fe69e04841435464391" dependencies = [ - "darling_core 0.20.9", - "darling_macro 0.20.9", + "darling_core 0.20.8", + "darling_macro 0.20.8", ] [[package]] @@ -1805,16 +1806,16 @@ dependencies = [ [[package]] name = "darling_core" -version = "0.20.9" +version = "0.20.8" source = "registry+https://github.com/rust-lang/crates.io-index" -checksum = "622687fe0bac72a04e5599029151f5796111b90f1baaa9b544d807a5e31cd120" +checksum = "9c2cf1c23a687a1feeb728783b993c4e1ad83d99f351801977dd809b48d0a70f" dependencies = [ "fnv", "ident_case", "proc-macro2", "quote", - "strsim 0.11.1", - "syn 2.0.66", + "strsim 0.10.0", + "syn 2.0.63", ] [[package]] @@ -1830,13 +1831,13 @@ dependencies = [ [[package]] name = "darling_macro" -version = "0.20.9" +version = "0.20.8" source = "registry+https://github.com/rust-lang/crates.io-index" -checksum = "733cabb43482b1a1b53eee8583c2b9e8684d592215ea83efd305dd31bc2f0178" +checksum = "a668eda54683121533a393014d8692171709ff57a7d61f187b6e782719f8933f" dependencies = [ - "darling_core 0.20.9", + "darling_core 0.20.8", "quote", - "syn 2.0.66", + "syn 2.0.63", ] [[package]] @@ -1888,7 +1889,7 @@ dependencies = [ "macroific", "proc-macro2", "quote", - "syn 2.0.66", + "syn 2.0.63", ] [[package]] @@ -1930,7 +1931,7 @@ checksum = "67e77553c4162a157adbf834ebae5b415acbecbeafc7a74b0e886657506a7611" dependencies = [ "proc-macro2", "quote", - "syn 2.0.66", + "syn 2.0.63", ] [[package]] @@ -1959,11 +1960,11 @@ version = "0.4.1" source = "registry+https://github.com/rust-lang/crates.io-index" checksum = "35b50dba0afdca80b187392b24f2499a88c336d5a8493e4b4ccfb608708be56a" dependencies = [ - "bitflags 2.6.0", + "bitflags 2.5.0", "proc-macro2", "proc-macro2-diagnostics", "quote", - "syn 2.0.66", + "syn 2.0.63", ] [[package]] @@ -1993,7 +1994,7 @@ dependencies = [ "block-buffer 0.10.4", "const-oid", "crypto-common", - "subtle 2.6.1", + "subtle 2.5.0", ] [[package]] @@ -2045,7 +2046,7 @@ checksum = "97369cbbc041bc366949bc74d34658d6cda5621039731c6310521892a3a20ae0" dependencies = [ "proc-macro2", "quote", - "syn 2.0.66", + "syn 2.0.63", ] [[package]] @@ -2123,12 +2124,12 @@ version = "2.1.1" source = "registry+https://github.com/rust-lang/crates.io-index" checksum = "4a3daa8e81a3963a60642bcc1f90a670680bd4a77535faa384e9d1c79d620871" dependencies = [ - "curve25519-dalek 4.1.3", + "curve25519-dalek 4.1.2", "ed25519", "rand_core 0.6.4", "serde", "sha2 0.10.8", - "subtle 2.6.1", + "subtle 2.5.0", "zeroize", ] @@ -2149,9 +2150,9 @@ dependencies = [ [[package]] name = "either" -version = "1.12.0" +version = "1.11.0" source = "registry+https://github.com/rust-lang/crates.io-index" -checksum = "3dca9240753cf90908d7e4aac30f630662b02aebaa1b58a3cadabdb23385b58b" +checksum = "a47c1c47d2f5964e29c61246e81db715514cd532db6b5116a25ea3c03d6780a2" [[package]] name = "elliptic-curve" @@ -2169,7 +2170,7 @@ dependencies = [ "rand_core 0.6.4", "sec1", "serdect 0.2.0", - "subtle 2.6.1", + "subtle 2.5.0", "zeroize", ] @@ -2334,14 +2335,14 @@ dependencies = [ [[package]] name = "fancy_constructor" -version = "1.2.2" +version = "1.3.0" source = "registry+https://github.com/rust-lang/crates.io-index" -checksum = "f71f317e4af73b2f8f608fac190c52eac4b1879d2145df1db2fe48881ca69435" +checksum = "07b19d0e43eae2bfbafe4931b5e79c73fb1a849ca15cd41a761a7b8587f9a1a2" dependencies = [ "macroific", "proc-macro2", "quote", - "syn 2.0.66", + "syn 2.0.63", ] [[package]] @@ -2366,7 +2367,7 @@ source = "registry+https://github.com/rust-lang/crates.io-index" checksum = "ded41244b729663b1e574f1b4fb731469f69f79c17667b5d776b16cda0479449" dependencies = [ "rand_core 0.6.4", - "subtle 2.6.1", + "subtle 2.5.0", ] [[package]] @@ -2377,9 +2378,9 @@ checksum = "28dea519a9695b9977216879a3ebfddf92f1c08c05d984f8996aecd6ecdc811d" [[package]] name = "figment" -version = "0.10.19" +version = "0.10.18" source = "registry+https://github.com/rust-lang/crates.io-index" -checksum = "8cb01cd46b0cf372153850f4c6c272d9cbea2da513e07538405148f95bd789f3" +checksum = "d032832d74006f99547004d49410a4b4218e4c33382d56ca3ff89df74f86b953" dependencies = [ "atomic 0.6.0", "pear", @@ -2401,6 +2402,12 @@ dependencies = [ "windows-sys 0.52.0", ] +[[package]] +name = "finl_unicode" +version = "1.2.0" +source = "registry+https://github.com/rust-lang/crates.io-index" +checksum = "8fcfdc7a0362c9f4444381a9e697c79d435fe65b52a37466fc2c1184cee9edc6" + [[package]] name = "fixedbitset" version = "0.4.2" @@ -2557,7 +2564,7 @@ checksum = "87750cf4b7a4c0625b1529e4c543c2182106e4dedc60a2a6455e00d212c489ac" dependencies = [ "proc-macro2", "quote", - "syn 2.0.66", + "syn 2.0.63", ] [[package]] @@ -2667,9 +2674,9 @@ dependencies = [ [[package]] name = "gimli" -version = "0.29.0" +version = "0.28.1" source = "registry+https://github.com/rust-lang/crates.io-index" -checksum = "40ecd4077b5ae9fd2e9e169b102c6c330d0605168eb0e8bf79952b256dbefffd" +checksum = "4271d37baee1b8c7e4b708028c57d816cf9d2434acb33a549475f78c181f6253" [[package]] name = "glob" @@ -2744,7 +2751,7 @@ checksum = "f0f9ef7462f7c099f518d754361858f86d8a07af53ba9af0fe635bbccb151a63" dependencies = [ "ff", "rand_core 0.6.4", - "subtle 2.6.1", + "subtle 2.5.0", ] [[package]] @@ -2981,12 +2988,12 @@ dependencies = [ [[package]] name = "http-body-util" -version = "0.1.2" +version = "0.1.1" source = "registry+https://github.com/rust-lang/crates.io-index" -checksum = "793429d76616a256bcb62c2a2ec2bed781c8307e797e2598c50010f2bee2544f" +checksum = "0475f8b2ac86659c21b64320d5d653f9efe42acd2a4e560073ec61a155a34f1d" dependencies = [ "bytes", - "futures-util", + "futures-core", "http 1.1.0", "http-body 1.0.0", "pin-project-lite", @@ -3000,9 +3007,9 @@ checksum = "08a397c49fec283e3d6211adbe480be95aae5f304cfb923e9970e08956d5168a" [[package]] name = "httparse" -version = "1.9.3" +version = "1.8.0" source = "registry+https://github.com/rust-lang/crates.io-index" -checksum = "d0e7a4dd27b9476dc40cb050d3632d3bba3a70ddbff012285f7f8559a1e7e545" +checksum = "d897f394bad6a705d5f4104762e116a75639e470d80901eed05a860a95cb1904" [[package]] name = "httpcodec" @@ -3047,9 +3054,9 @@ dependencies = [ [[package]] name = "hyper" -version = "0.14.29" +version = "0.14.28" source = "registry+https://github.com/rust-lang/crates.io-index" -checksum = "f361cde2f109281a220d4307746cdfd5ee3f410da58a70377762396775634b33" +checksum = "bf96e135eb83a2a8ddf766e426a841d8ddd7449d5f00d34ea02b41d2f19eef80" dependencies = [ "bytes", "futures-channel", @@ -3071,9 +3078,9 @@ dependencies = [ [[package]] name = "hyper" -version = "1.4.0" +version = "1.3.1" source = "registry+https://github.com/rust-lang/crates.io-index" -checksum = "c4fe55fb7a772d59a5ff1dfbff4fe0258d19b89fec4b233e75d35d5d2316badc" +checksum = "fe575dd17d0862a9a33781c8c4696a55c320909004a67a00fb286ba8b1bc496d" dependencies = [ "bytes", "futures-channel", @@ -3097,7 +3104,7 @@ checksum = "ec3efd23720e2049821a693cbc7e65ea87c72f1c58ff2f9522ff332b1491e590" dependencies = [ "futures-util", "http 0.2.12", - "hyper 0.14.29", + "hyper 0.14.28", "rustls 0.21.12", "tokio", "tokio-rustls 0.24.1", @@ -3111,7 +3118,7 @@ checksum = "a0bea761b46ae2b24eb4aef630d8d1c398157b6fc29e6350ecf090a0b70c952c" dependencies = [ "futures-util", "http 1.1.0", - "hyper 1.4.0", + "hyper 1.3.1", "hyper-util", "rustls 0.22.4", "rustls-pki-types", @@ -3126,7 +3133,7 @@ version = "0.4.1" source = "registry+https://github.com/rust-lang/crates.io-index" checksum = "bbb958482e8c7be4bc3cf272a766a2b0bf1a6755e7a6ae777f017a31d11b13b1" dependencies = [ - "hyper 0.14.29", + "hyper 0.14.28", "pin-project-lite", "tokio", "tokio-io-timeout", @@ -3134,16 +3141,16 @@ dependencies = [ [[package]] name = "hyper-util" -version = "0.1.7" +version = "0.1.3" source = "registry+https://github.com/rust-lang/crates.io-index" -checksum = "cde7055719c54e36e95e8719f95883f22072a48ede39db7fc17a4e1d5281e9b9" +checksum = "ca38ef113da30126bbff9cd1705f9273e15d45498615d138b0c20279ac7a76aa" dependencies = [ "bytes", "futures-channel", "futures-util", "http 1.1.0", "http-body 1.0.0", - "hyper 1.4.0", + "hyper 1.3.1", "pin-project-lite", "socket2", "tokio", @@ -3209,8 +3216,8 @@ checksum = "ce23b50ad8242c51a442f3ff322d56b02f08852c77e4c0b4d3fd684abc89c683" [[package]] name = "indexed_db_futures" -version = "0.4.2" -source = "git+https://github.com/TiemenSch/rust-indexed-db?branch=update-uuid#9745d015707008b0c410115d787014a6d1af2efb" +version = "0.4.1" +source = "git+https://github.com/TiemenSch/rust-indexed-db?branch=update-uuid#65ba1be4fec562e0cff55116e004ae081b460144" dependencies = [ "accessory", "cfg-if", @@ -3312,9 +3319,9 @@ dependencies = [ [[package]] name = "instant" -version = "0.1.13" +version = "0.1.12" source = "registry+https://github.com/rust-lang/crates.io-index" -checksum = "e0242819d153cba4b4b05a5a8f2a7e9bbf97b6055b2a002b395c96b5ff3c0222" +checksum = "7a5bbe824c507c5da5956355e86a746d82e0e1464f65d862cc5e71da70e94b2c" dependencies = [ "cfg-if", ] @@ -3519,9 +3526,9 @@ dependencies = [ [[package]] name = "lazy_static" -version = "1.5.0" +version = "1.4.0" source = "registry+https://github.com/rust-lang/crates.io-index" -checksum = "bbd2bcb4c963f2ddae06a2efc7e9f3591312473c50c6685e1f298068316e66fe" +checksum = "e2abad23fbc42b3700f2f279844dc832adb2b2eb069b2df918f455c4e18cc646" [[package]] name = "ledger-apdu" @@ -3562,9 +3569,9 @@ dependencies = [ [[package]] name = "libc" -version = "0.2.155" +version = "0.2.154" source = "registry+https://github.com/rust-lang/crates.io-index" -checksum = "97b3888a4aecf77e811145cadf6eef5901f4782c53886191b2f693f24761847c" +checksum = "ae743338b92ff9146ce83992f766a31066a91a8c84a45e0e9f21e7cf6de6d346" [[package]] name = "libm" @@ -3578,7 +3585,7 @@ version = "0.1.3" source = "registry+https://github.com/rust-lang/crates.io-index" checksum = "c0ff37bd590ca25063e35af745c343cb7a0271906fb7b37e4813e8f79f00268d" dependencies = [ - "bitflags 2.6.0", + "bitflags 2.5.0", "libc", ] @@ -3595,9 +3602,9 @@ dependencies = [ [[package]] name = "libz-sys" -version = "1.1.18" +version = "1.1.16" source = "registry+https://github.com/rust-lang/crates.io-index" -checksum = "c15da26e5af7e25c90b37a2d75cdbf940cf4a55316de9d84c679c9b8bfabf82e" +checksum = "5e143b5e666b2695d28f6bca6497720813f699c9602dd7f5cac91008b8ada7f9" dependencies = [ "cc", "libc", @@ -3607,9 +3614,9 @@ dependencies = [ [[package]] name = "linux-raw-sys" -version = "0.4.14" +version = "0.4.13" source = "registry+https://github.com/rust-lang/crates.io-index" -checksum = "78b3ae25bc7c8c38cec158d1f2757ee79e9b3740fbc7ccf0e59e4b08d793fa89" +checksum = "01cda141df6706de531b6c46c3a33ecca755538219bd484262fa09410c13539c" [[package]] name = "lioness" @@ -3635,9 +3642,9 @@ dependencies = [ [[package]] name = "log" -version = "0.4.22" +version = "0.4.21" source = "registry+https://github.com/rust-lang/crates.io-index" -checksum = "a7a70ba024b9dc04c27ea2f0c0548feb474ec5c54bba33a7f72f873a39d07b24" +checksum = "90ed8c1e510134f979dbc4f070f87d4313098b704861a105fe34231c70a3901c" [[package]] name = "loom" @@ -3690,7 +3697,7 @@ dependencies = [ "cfg-if", "proc-macro2", "quote", - "syn 2.0.66", + "syn 2.0.63", ] [[package]] @@ -3701,7 +3708,7 @@ checksum = "13198c120864097a565ccb3ff947672d969932b7975ebd4085732c9f09435e55" dependencies = [ "proc-macro2", "quote", - "syn 2.0.66", + "syn 2.0.63", ] [[package]] @@ -3714,7 +3721,7 @@ dependencies = [ "macroific_core", "proc-macro2", "quote", - "syn 2.0.66", + "syn 2.0.63", ] [[package]] @@ -3746,9 +3753,9 @@ dependencies = [ [[package]] name = "memchr" -version = "2.7.4" +version = "2.7.2" source = "registry+https://github.com/rust-lang/crates.io-index" -checksum = "78ca9ab1a0babb1e7d5695e3530886289c18cf2f87ec19a575a0abdce112e3a3" +checksum = "6c8640c5d730cb13ebd907d8d04b52f55ac9a2eec55b440c8892f40d56c76c1d" [[package]] name = "memoffset" @@ -3767,9 +3774,9 @@ checksum = "6877bb514081ee2a7ff5ef9de3281f14a4dd4bceac4c09388074a6b5df8a139a" [[package]] name = "mime_guess" -version = "2.0.5" +version = "2.0.4" source = "registry+https://github.com/rust-lang/crates.io-index" -checksum = "f7c44f8e672c00fe5308fa235f821cb4198414e1c77935c1ab6948d3fd78550e" +checksum = "4192263c238a5f0d0c6bfd21f336a313a4ce1c450542449ca191bb657b4642ef" dependencies = [ "mime", "unicase", @@ -3783,9 +3790,9 @@ checksum = "68354c5c6bd36d73ff3feceb05efa59b6acb7626617f4962be322a825e61f79a" [[package]] name = "miniz_oxide" -version = "0.7.3" +version = "0.7.2" source = "registry+https://github.com/rust-lang/crates.io-index" -checksum = "87dfd01fe195c66b572b37921ad8803d010623c0aca821bea2302239d155cdae" +checksum = "9d811f3e15f28568be3407c8e7fdb6514c1cda3cb30683f15b6a1a1dc4ea14a7" dependencies = [ "adler", ] @@ -3813,9 +3820,9 @@ dependencies = [ [[package]] name = "mio" -version = "1.0.1" +version = "1.0.2" source = "registry+https://github.com/rust-lang/crates.io-index" -checksum = "4569e456d394deccd22ce1c1913e6ea0e54519f577285001215d33557431afe4" +checksum = "80e04d1dcff3aae0704555fe5fee3bcfaf3d1fdf8a7e521d5b9d2b42acb52cec" dependencies = [ "hermit-abi 0.3.9", "libc", @@ -3957,7 +3964,7 @@ version = "0.27.1" source = "registry+https://github.com/rust-lang/crates.io-index" checksum = "2eb04e9c688eff1c89d72b407f168cf79bb9e867a9d3323ed6c01519eb9cc053" dependencies = [ - "bitflags 2.6.0", + "bitflags 2.5.0", "cfg-if", "libc", "memoffset", @@ -3965,11 +3972,11 @@ dependencies = [ [[package]] name = "nix" -version = "0.29.0" +version = "0.28.0" source = "registry+https://github.com/rust-lang/crates.io-index" -checksum = "71e2746dc3a24dd78b3cfcb7be93368c6de9963d30f43a6a73998a9cf4b17b46" +checksum = "ab2156c4fce2f8df6c499cc1c763e4394b7482525bf2a9701c9d79d215f519e4" dependencies = [ - "bitflags 2.6.0", + "bitflags 2.5.0", "cfg-if", "cfg_aliases", "libc", @@ -4067,23 +4074,23 @@ dependencies = [ [[package]] name = "num_enum" -version = "0.7.2" +version = "0.7.3" source = "registry+https://github.com/rust-lang/crates.io-index" -checksum = "02339744ee7253741199f897151b38e72257d13802d4ee837285cc2990a90845" +checksum = "4e613fc340b2220f734a8595782c551f1250e969d87d3be1ae0579e8d4065179" dependencies = [ "num_enum_derive", ] [[package]] name = "num_enum_derive" -version = "0.7.2" +version = "0.7.3" source = "registry+https://github.com/rust-lang/crates.io-index" -checksum = "681030a937600a36906c185595136d26abfebb4aa9c65701cefcaf8578bb982b" +checksum = "af1844ef2428cc3e1cb900be36181049ef3d3193c63e43026cfe202983b27a56" dependencies = [ "proc-macro-crate", "proc-macro2", "quote", - "syn 2.0.66", + "syn 2.0.63", ] [[package]] @@ -4464,7 +4471,7 @@ dependencies = [ "gloo-timers", "http-body-util", "humantime-serde", - "hyper 1.4.0", + "hyper 1.3.1", "hyper-util", "log", "nym-bandwidth-controller", @@ -5463,7 +5470,7 @@ dependencies = [ "fastrand 2.1.1", "headers", "hmac", - "hyper 1.4.0", + "hyper 1.3.1", "ipnetwork 0.20.0", "nym-crypto", "nym-http-api-common", @@ -5591,7 +5598,7 @@ dependencies = [ "chacha20", "chacha20poly1305", "criterion 0.4.0", - "curve25519-dalek 4.1.3", + "curve25519-dalek 4.1.2", "fastrand 2.1.1", "getrandom", "log", @@ -5642,7 +5649,7 @@ dependencies = [ "nym-task", "nym-topology", "nym-validator-client", - "parking_lot 0.12.3", + "parking_lot 0.12.2", "pretty_env_logger", "rand", "reqwest 0.12.4", @@ -6085,7 +6092,7 @@ dependencies = [ "nym-multisig-contract-common", "nym-network-defaults", "nym-vesting-contract-common", - "prost 0.12.6", + "prost 0.12.4", "reqwest 0.12.4", "serde", "serde_json", @@ -6267,9 +6274,9 @@ dependencies = [ [[package]] name = "object" -version = "0.36.0" +version = "0.32.2" source = "registry+https://github.com/rust-lang/crates.io-index" -checksum = "576dfe1fc8f9df304abb159d767a29d0476f7750fbf8aa7ad07816004a207434" +checksum = "a6a622008b6e321afc04970976f62ee297fdbaa6f95318ca343e3eebb9648441" dependencies = [ "memchr", ] @@ -6294,9 +6301,9 @@ checksum = "3fdb12b2476b595f9358c5161aa467c2438859caa136dec86c26fdd2efe17b92" [[package]] name = "oorandom" -version = "11.1.4" +version = "11.1.3" source = "registry+https://github.com/rust-lang/crates.io-index" -checksum = "b410bbe7e14ab526a0e86877eb47c6996a2bd7746f027ba551028c925390e4e9" +checksum = "0ab1bc2a289d34bd04a330323ac98a1b4bc82c9d9fcb1e66b63caa84da26b575" [[package]] name = "opaque-debug" @@ -6473,9 +6480,9 @@ dependencies = [ [[package]] name = "parking_lot" -version = "0.12.3" +version = "0.12.2" source = "registry+https://github.com/rust-lang/crates.io-index" -checksum = "f1bf18183cf54e8d6059647fc3063646a1801cf30896933ec2311622cc4b9a27" +checksum = "7e4af0ca4f6caed20e900d564c242b8e5d4903fdacf31d3daf527b66fe6f42fb" dependencies = [ "lock_api", "parking_lot_core 0.9.10", @@ -6503,9 +6510,9 @@ checksum = "1e401f977ab385c9e4e3ab30627d6f26d00e2c73eef317493c4ec6d468726cf8" dependencies = [ "cfg-if", "libc", - "redox_syscall 0.5.2", + "redox_syscall 0.5.1", "smallvec", - "windows-targets 0.52.6", + "windows-targets 0.52.5", ] [[package]] @@ -6516,7 +6523,7 @@ checksum = "346f04948ba92c43e8469c1ee6736c7563d71012b17d40745260fe106aac2166" dependencies = [ "base64ct", "rand_core 0.6.4", - "subtle 2.6.1", + "subtle 2.5.0", ] [[package]] @@ -6545,14 +6552,14 @@ dependencies = [ "proc-macro2", "proc-macro2-diagnostics", "quote", - "syn 2.0.66", + "syn 2.0.63", ] [[package]] name = "peg" -version = "0.8.3" +version = "0.8.4" source = "registry+https://github.com/rust-lang/crates.io-index" -checksum = "8a625d12ad770914cbf7eff6f9314c3ef803bfe364a1b20bc36ddf56673e71e5" +checksum = "295283b02df346d1ef66052a757869b2876ac29a6bb0ac3f5f7cd44aebe40e8f" dependencies = [ "peg-macros", "peg-runtime", @@ -6560,9 +6567,9 @@ dependencies = [ [[package]] name = "peg-macros" -version = "0.8.3" +version = "0.8.4" source = "registry+https://github.com/rust-lang/crates.io-index" -checksum = "f241d42067ed3ab6a4fece1db720838e1418f36d868585a27931f95d6bc03582" +checksum = "bdad6a1d9cf116a059582ce415d5f5566aabcd4008646779dab7fdc2a9a9d426" dependencies = [ "peg-runtime", "proc-macro2", @@ -6594,9 +6601,9 @@ checksum = "e3148f5046208a5d56bcfc03053e3ca6334e51da8dfb19b6cdc8b306fae3283e" [[package]] name = "pest" -version = "2.7.11" +version = "2.7.10" source = "registry+https://github.com/rust-lang/crates.io-index" -checksum = "cd53dff83f26735fdc1ca837098ccf133605d794cdae66acfc2bfac3ec809d95" +checksum = "560131c633294438da9f7c4b08189194b20946c8274c6b9e38881a7874dc8ee8" dependencies = [ "memchr", "thiserror", @@ -6605,9 +6612,9 @@ dependencies = [ [[package]] name = "pest_derive" -version = "2.7.11" +version = "2.7.10" source = "registry+https://github.com/rust-lang/crates.io-index" -checksum = "2a548d2beca6773b1c244554d36fcf8548a8a58e74156968211567250e48e49a" +checksum = "26293c9193fbca7b1a3bf9b79dc1e388e927e6cacaa78b4a3ab705a1d3d41459" dependencies = [ "pest", "pest_generator", @@ -6615,22 +6622,22 @@ dependencies = [ [[package]] name = "pest_generator" -version = "2.7.11" +version = "2.7.10" source = "registry+https://github.com/rust-lang/crates.io-index" -checksum = "3c93a82e8d145725dcbaf44e5ea887c8a869efdcc28706df2d08c69e17077183" +checksum = "3ec22af7d3fb470a85dd2ca96b7c577a1eb4ef6f1683a9fe9a8c16e136c04687" dependencies = [ "pest", "pest_meta", "proc-macro2", "quote", - "syn 2.0.66", + "syn 2.0.63", ] [[package]] name = "pest_meta" -version = "2.7.11" +version = "2.7.10" source = "registry+https://github.com/rust-lang/crates.io-index" -checksum = "a941429fea7e08bedec25e4f6785b6ffaacc6b755da98df5ef3e7dcf4a124c4f" +checksum = "d7a240022f37c361ec1878d646fc5b7d7c4d28d5946e1a80ad5a7a4f4ca0bdcd" dependencies = [ "once_cell", "pest", @@ -6664,7 +6671,7 @@ checksum = "2f38a4412a78282e09a2cf38d195ea5420d15ba0602cb375210efbc877243965" dependencies = [ "proc-macro2", "quote", - "syn 2.0.66", + "syn 2.0.63", ] [[package]] @@ -6696,10 +6703,16 @@ source = "registry+https://github.com/rust-lang/crates.io-index" checksum = "d231b230927b5e4ad203db57bbcbee2802f6bce620b1e4a9024a07d94e2907ec" [[package]] -name = "plotters" -version = "0.3.6" +name = "platforms" +version = "3.4.0" source = "registry+https://github.com/rust-lang/crates.io-index" -checksum = "a15b6eccb8484002195a3e44fe65a4ce8e93a625797a063735536fd59cb01cf3" +checksum = "db23d408679286588f4d4644f965003d056e3dd5abcaaa938116871d7ce2fee7" + +[[package]] +name = "plotters" +version = "0.3.5" +source = "registry+https://github.com/rust-lang/crates.io-index" +checksum = "d2c224ba00d7cadd4d5c660deaf2098e5e80e07846537c51f9cfa4be50c1fd45" dependencies = [ "num-traits", "plotters-backend", @@ -6710,15 +6723,15 @@ dependencies = [ [[package]] name = "plotters-backend" -version = "0.3.6" +version = "0.3.5" source = "registry+https://github.com/rust-lang/crates.io-index" -checksum = "414cec62c6634ae900ea1c56128dfe87cf63e7caece0852ec76aba307cebadb7" +checksum = "9e76628b4d3a7581389a35d5b6e2139607ad7c75b17aed325f210aa91f4a9609" [[package]] name = "plotters-svg" -version = "0.3.6" +version = "0.3.5" source = "registry+https://github.com/rust-lang/crates.io-index" -checksum = "81b30686a7d9c3e010b84284bdd26a29f2138574f52f5eb6f794fc0ad924e705" +checksum = "38f6d39893cca0701371e3c27294f09797214b86f1fb951b89ade8ec04e2abab" dependencies = [ "plotters-backend", ] @@ -6764,9 +6777,9 @@ dependencies = [ [[package]] name = "portable-atomic" -version = "1.6.0" +version = "1.7.0" source = "registry+https://github.com/rust-lang/crates.io-index" -checksum = "7170ef9988bc169ba16dd36a7fa041e5c4cbeb6a35b76d4c03daded371eae7c0" +checksum = "da544ee218f0d287a911e9c99a39a8c9bc8fcad3cb8db5959940044ecfc67265" [[package]] name = "powerfmt" @@ -6835,9 +6848,9 @@ dependencies = [ [[package]] name = "proc-macro2" -version = "1.0.85" +version = "1.0.82" source = "registry+https://github.com/rust-lang/crates.io-index" -checksum = "22244ce15aa966053a896d1accb3a6e68469b97c7f33f284b99f0d576879fc23" +checksum = "8ad3d49ab951a01fbaafe34f2ec74122942fe18a3f9814c3268f1bb72042131b" dependencies = [ "unicode-ident", ] @@ -6850,7 +6863,7 @@ checksum = "af066a9c399a26e020ada66a034357a868728e72cd426f3adcd35f80d88d88c8" dependencies = [ "proc-macro2", "quote", - "syn 2.0.66", + "syn 2.0.63", "version_check", "yansi", ] @@ -6865,7 +6878,7 @@ dependencies = [ "fnv", "lazy_static", "memchr", - "parking_lot 0.12.3", + "parking_lot 0.12.2", "protobuf", "thiserror", ] @@ -6882,12 +6895,12 @@ dependencies = [ [[package]] name = "prost" -version = "0.12.6" +version = "0.12.4" source = "registry+https://github.com/rust-lang/crates.io-index" -checksum = "deb1435c188b76130da55f17a466d252ff7b1418b2ad3e037d127b94e3411f29" +checksum = "d0f5d036824e4761737860779c906171497f6d55681139d8312388f8fe398922" dependencies = [ "bytes", - "prost-derive 0.12.6", + "prost-derive 0.12.5", ] [[package]] @@ -6905,15 +6918,15 @@ dependencies = [ [[package]] name = "prost-derive" -version = "0.12.6" +version = "0.12.5" source = "registry+https://github.com/rust-lang/crates.io-index" -checksum = "81bddcdb20abf9501610992b6759a4c888aef7d1a7247ef75e2404275ac24af1" +checksum = "9554e3ab233f0a932403704f1a1d08c30d5ccd931adfdfa1e8b5a19b52c1d55a" dependencies = [ "anyhow", "itertools 0.12.1", "proc-macro2", "quote", - "syn 2.0.66", + "syn 2.0.63", ] [[package]] @@ -6927,11 +6940,11 @@ dependencies = [ [[package]] name = "prost-types" -version = "0.12.6" +version = "0.12.4" source = "registry+https://github.com/rust-lang/crates.io-index" -checksum = "9091c90b0a32608e984ff2fa4091273cbdd755d54935c51d520887f4a1dbd5b0" +checksum = "3235c33eb02c1f1e212abdbe34c78b264b038fb58ca612664343271e36e55ffe" dependencies = [ - "prost 0.12.6", + "prost 0.12.4", ] [[package]] @@ -6942,9 +6955,9 @@ checksum = "106dd99e98437432fed6519dedecfade6a06a73bb7b2a1e019fdd2bee5778d94" [[package]] name = "psl" -version = "2.1.43" +version = "2.1.39" source = "registry+https://github.com/rust-lang/crates.io-index" -checksum = "ecec637c2e9d0c8c4bf78df069a53a103ebe3dbd0dc7eff1d60c1006a1c97254" +checksum = "7b320cda4ad7e8f4269fa415754418f83b38c666a5e2e99ea48825b274a373f3" dependencies = [ "psl-types", ] @@ -6979,9 +6992,9 @@ checksum = "a993555f31e5a609f617c12db6250dedcac1b0a85076912c436e6fc9b2c8e6a3" [[package]] name = "quote" -version = "1.0.37" +version = "1.0.36" source = "registry+https://github.com/rust-lang/crates.io-index" -checksum = "b5b9d34b8991d19d98081b46eacdd8eb58c6f2b201139f7c5f643cc155a633af" +checksum = "0fa76aaf39101c457836aec0ce2316dbdc3ab723cdda1c6bd4e6ad4208acaca7" dependencies = [ "proc-macro2", ] @@ -7096,11 +7109,11 @@ dependencies = [ [[package]] name = "redox_syscall" -version = "0.5.2" +version = "0.5.1" source = "registry+https://github.com/rust-lang/crates.io-index" -checksum = "c82cf8cff14456045f55ec4241383baeff27af886adb72ffb2162f99911de0fd" +checksum = "469052894dcb553421e483e4209ee581a45100d31b4018de03e5a7ad86374a7e" dependencies = [ - "bitflags 2.6.0", + "bitflags 2.5.0", ] [[package]] @@ -7131,7 +7144,7 @@ checksum = "bcc303e793d3734489387d205e9b186fac9c6cfacedd98cbb2e8a5943595f3e6" dependencies = [ "proc-macro2", "quote", - "syn 2.0.66", + "syn 2.0.63", ] [[package]] @@ -7142,8 +7155,8 @@ checksum = "4219d74c6b67a3654a9fbebc4b419e22126d13d2f3c4a07ee0cb61ff79a79619" dependencies = [ "aho-corasick", "memchr", - "regex-automata 0.4.7", - "regex-syntax 0.8.4", + "regex-automata 0.4.6", + "regex-syntax 0.8.3", ] [[package]] @@ -7157,13 +7170,13 @@ dependencies = [ [[package]] name = "regex-automata" -version = "0.4.7" +version = "0.4.6" source = "registry+https://github.com/rust-lang/crates.io-index" -checksum = "38caf58cc5ef2fed281f89292ef23f6365465ed9a41b7a7754eb4e26496c92df" +checksum = "86b83b8b9847f9bf95ef68afb0b8e6cdb80f498442f5179a29fad448fcc1eaea" dependencies = [ "aho-corasick", "memchr", - "regex-syntax 0.8.4", + "regex-syntax 0.8.3", ] [[package]] @@ -7174,9 +7187,9 @@ checksum = "f162c6dd7b008981e4d40210aca20b4bd0f9b60ca9271061b07f78537722f2e1" [[package]] name = "regex-syntax" -version = "0.8.4" +version = "0.8.3" source = "registry+https://github.com/rust-lang/crates.io-index" -checksum = "7a66a03ae7c801facd77a29370b4faec201768915ac14a721ba36f20bc9c209b" +checksum = "adad44e29e4c806119491a7f06f03de4d1af22c3a680dd47f1e6e179439d1f56" [[package]] name = "reqwest" @@ -7192,7 +7205,7 @@ dependencies = [ "h2", "http 0.2.12", "http-body 0.4.6", - "hyper 0.14.29", + "hyper 0.14.28", "hyper-rustls 0.24.2", "ipnet", "js-sys", @@ -7233,7 +7246,7 @@ dependencies = [ "http 1.1.0", "http-body 1.0.0", "http-body-util", - "hyper 1.4.0", + "hyper 1.3.1", "hyper-rustls 0.26.0", "hyper-util", "ipnet", @@ -7260,7 +7273,7 @@ dependencies = [ "wasm-bindgen-futures", "wasm-streams", "web-sys", - "webpki-roots 0.26.2", + "webpki-roots 0.26.1", "winreg 0.52.0", ] @@ -7271,7 +7284,7 @@ source = "registry+https://github.com/rust-lang/crates.io-index" checksum = "f8dd2a808d456c4a54e300a23e9f5a67e122c3024119acbfd73e3bf664491cb2" dependencies = [ "hmac", - "subtle 2.6.1", + "subtle 2.5.0", ] [[package]] @@ -7332,7 +7345,7 @@ dependencies = [ "memchr", "multer", "num_cpus", - "parking_lot 0.12.3", + "parking_lot 0.12.2", "pin-project-lite", "rand", "ref-cast", @@ -7363,7 +7376,7 @@ dependencies = [ "proc-macro2", "quote", "rocket_http", - "syn 2.0.66", + "syn 2.0.63", "unicode-xid", "version_check", ] @@ -7395,7 +7408,7 @@ dependencies = [ "either", "futures", "http 0.2.12", - "hyper 0.14.29", + "hyper 0.14.28", "indexmap 2.2.6", "log", "memchr", @@ -7460,7 +7473,7 @@ dependencies = [ "proc-macro2", "quote", "rust-embed-utils", - "syn 2.0.66", + "syn 2.0.63", "walkdir", ] @@ -7504,7 +7517,7 @@ version = "0.38.34" source = "registry+https://github.com/rust-lang/crates.io-index" checksum = "70dc5ec042f7a43c4a73241207cecc9873a06d45debb38b329f8541d85c2730f" dependencies = [ - "bitflags 2.6.0", + "bitflags 2.5.0", "errno", "libc", "linux-raw-sys", @@ -7544,8 +7557,8 @@ dependencies = [ "log", "ring 0.17.8", "rustls-pki-types", - "rustls-webpki 0.102.4", - "subtle 2.6.1", + "rustls-webpki 0.102.3", + "subtle 2.5.0", "zeroize", ] @@ -7563,9 +7576,9 @@ dependencies = [ [[package]] name = "rustls-native-certs" -version = "0.7.0" +version = "0.7.3" source = "registry+https://github.com/rust-lang/crates.io-index" -checksum = "8f1fb85efa936c42c6d5fc28d2629bb51e4b2f4b8a5211e297d599cc5a093792" +checksum = "e5bfb394eeed242e909609f56089eecfe5fda225042e8b171791b9c95f5931e5" dependencies = [ "openssl-probe", "rustls-pemfile 2.1.2", @@ -7611,9 +7624,9 @@ dependencies = [ [[package]] name = "rustls-webpki" -version = "0.102.4" +version = "0.102.3" source = "registry+https://github.com/rust-lang/crates.io-index" -checksum = "ff448f7e92e913c4b7d4c6d8e4540a1724b319b4152b8aef6d4cf8339712b33e" +checksum = "f3bce581c0dd41bce533ce695a1437fa16a7ab5ac3ccfa99fe1a620a7885eabf" dependencies = [ "ring 0.17.8", "rustls-pki-types", @@ -7622,9 +7635,9 @@ dependencies = [ [[package]] name = "rustversion" -version = "1.0.17" +version = "1.0.16" source = "registry+https://github.com/rust-lang/crates.io-index" -checksum = "955d28af4278de8121b7ebeb796b6a45735dc01436d898801014aced2773a3d6" +checksum = "092474d1a01ea8278f69e6a358998405fae5b8b963ddaeb2b0b04a128bf1dfb0" [[package]] name = "ryu" @@ -7683,9 +7696,9 @@ dependencies = [ [[package]] name = "schemars" -version = "0.8.21" +version = "0.8.19" source = "registry+https://github.com/rust-lang/crates.io-index" -checksum = "09c024468a378b7e36765cd36702b7a90cc3cba11654f6685c8f233408e89e92" +checksum = "fc6e7ed6919cb46507fb01ff1654309219f62b4d603822501b0b80d42f6f21ef" dependencies = [ "dyn-clone", "indexmap 1.9.3", @@ -7696,14 +7709,14 @@ dependencies = [ [[package]] name = "schemars_derive" -version = "0.8.21" +version = "0.8.19" source = "registry+https://github.com/rust-lang/crates.io-index" -checksum = "b1eee588578aff73f856ab961cd2f79e36bc45d7ded33a7562adba4667aecc0e" +checksum = "185f2b7aa7e02d418e453790dde16890256bbd2bcd04b7dc5348811052b53f49" dependencies = [ "proc-macro2", "quote", - "serde_derive_internals 0.29.1", - "syn 2.0.66", + "serde_derive_internals 0.29.0", + "syn 2.0.63", ] [[package]] @@ -7739,7 +7752,7 @@ dependencies = [ "generic-array 0.14.7", "pkcs8", "serdect 0.2.0", - "subtle 2.6.1", + "subtle 2.5.0", "zeroize", ] @@ -7749,7 +7762,7 @@ version = "2.11.0" source = "registry+https://github.com/rust-lang/crates.io-index" checksum = "c627723fd09706bacdb5cf41499e95098555af3c3c29d014dc3c458ef6be11c0" dependencies = [ - "bitflags 2.6.0", + "bitflags 2.5.0", "core-foundation", "core-foundation-sys", "libc", @@ -7865,7 +7878,7 @@ checksum = "a5831b979fd7b5439637af1752d535ff49f4860c0f341d1baeb6faf0f4242170" dependencies = [ "proc-macro2", "quote", - "syn 2.0.66", + "syn 2.0.63", ] [[package]] @@ -7876,18 +7889,18 @@ checksum = "e578a843d40b4189a4d66bba51d7684f57da5bd7c304c64e14bd63efbef49509" dependencies = [ "proc-macro2", "quote", - "syn 2.0.66", + "syn 2.0.63", ] [[package]] name = "serde_derive_internals" -version = "0.29.1" +version = "0.29.0" source = "registry+https://github.com/rust-lang/crates.io-index" -checksum = "18d26a20a969b9e3fdf2fc2d9f21eda6c40e2de84c9408bb5d3b05d499aae711" +checksum = "330f01ce65a3a5fe59a60c82f3c9a024b573b8a6e875bd233fe5f934e71d54e3" dependencies = [ "proc-macro2", "quote", - "syn 2.0.66", + "syn 2.0.63", ] [[package]] @@ -7920,7 +7933,7 @@ checksum = "6c64451ba24fc7a6a2d60fc75dd9c83c90903b19028d4eff35e88fc1e86564e9" dependencies = [ "proc-macro2", "quote", - "syn 2.0.66", + "syn 2.0.63", ] [[package]] @@ -7968,10 +7981,10 @@ version = "3.9.0" source = "registry+https://github.com/rust-lang/crates.io-index" checksum = "a8fee4991ef4f274617a51ad4af30519438dacb2f56ac773b08a1922ff743350" dependencies = [ - "darling 0.20.9", + "darling 0.20.8", "proc-macro2", "quote", - "syn 2.0.66", + "syn 2.0.63", ] [[package]] @@ -8186,7 +8199,7 @@ dependencies = [ "byteorder", "chacha", "ctr", - "curve25519-dalek 4.1.3", + "curve25519-dalek 4.1.2", "digest 0.10.7", "hkdf", "hmac", @@ -8195,7 +8208,7 @@ dependencies = [ "rand", "rand_distr", "sha2 0.10.8", - "subtle 2.6.1", + "subtle 2.5.0", ] [[package]] @@ -8225,10 +8238,11 @@ dependencies = [ [[package]] name = "sqlformat" -version = "0.2.4" +version = "0.2.3" source = "registry+https://github.com/rust-lang/crates.io-index" -checksum = "f895e3734318cc55f1fe66258926c9b910c124d47520339efecbb6c59cec7c1f" +checksum = "ce81b7bd7c4493975347ef60d8c7e8b742d4694f4c49f93e0a12ea263938176c" dependencies = [ + "itertools 0.12.1", "nom", "unicode_categories", ] @@ -8385,13 +8399,13 @@ dependencies = [ [[package]] name = "stringprep" -version = "0.1.5" +version = "0.1.4" source = "registry+https://github.com/rust-lang/crates.io-index" -checksum = "7b4df3d392d81bd458a8a621b8bffbd2302a12ffe288a9d931670948749463b1" +checksum = "bb41d74e231a107a1b4ee36bd1214b11285b77768d2e3824aedafa988fd36ee6" dependencies = [ + "finl_unicode", "unicode-bidi", "unicode-normalization", - "unicode-properties", ] [[package]] @@ -8472,7 +8486,7 @@ dependencies = [ "proc-macro2", "quote", "rustversion", - "syn 2.0.66", + "syn 2.0.63", ] [[package]] @@ -8485,7 +8499,7 @@ dependencies = [ "proc-macro2", "quote", "rustversion", - "syn 2.0.66", + "syn 2.0.63", ] [[package]] @@ -8496,9 +8510,9 @@ checksum = "2d67a5a62ba6e01cb2192ff309324cb4875d0c451d55fe2319433abe7a05a8ee" [[package]] name = "subtle" -version = "2.6.1" +version = "2.5.0" source = "registry+https://github.com/rust-lang/crates.io-index" -checksum = "13c2bddecc57b384dee18652358fb23172facb8a2c51ccc10d74c157bdea3292" +checksum = "81cdd64d312baedb58e21336b31bc043b77e01cc99033ce76ef539f78e965ebc" [[package]] name = "subtle-encoding" @@ -8528,9 +8542,9 @@ dependencies = [ [[package]] name = "syn" -version = "2.0.66" +version = "2.0.63" source = "registry+https://github.com/rust-lang/crates.io-index" -checksum = "c42f3f41a2de00b01c0aaad383c5a45241efc8b2d1eda5661812fda5f3cdcff5" +checksum = "bf5be731623ca1a1fb7d8be6f261a3be6d3e2337b8a1f97be944d020c8fcb704" dependencies = [ "proc-macro2", "quote", @@ -8593,9 +8607,9 @@ checksum = "55937e1799185b12863d447f42597ed69d9928686b8d88a1df17376a097d8369" [[package]] name = "tar" -version = "0.4.41" +version = "0.4.40" source = "registry+https://github.com/rust-lang/crates.io-index" -checksum = "cb797dad5fb5b76fcf519e702f4a589483b5ef06567f160c392832c1f5e44909" +checksum = "b16afcea1f22891c49a00c751c7b63b2233284064f11a200fc624137c51e2ddb" dependencies = [ "filetime", "libc", @@ -8629,8 +8643,8 @@ dependencies = [ "k256", "num-traits", "once_cell", - "prost 0.12.6", - "prost-types 0.12.6", + "prost 0.12.4", + "prost-types 0.12.4", "ripemd", "serde", "serde_bytes", @@ -8638,7 +8652,7 @@ dependencies = [ "serde_repr", "sha2 0.10.8", "signature", - "subtle 2.6.1", + "subtle 2.5.0", "subtle-encoding", "tendermint-proto 0.34.1", "time", @@ -8660,8 +8674,8 @@ dependencies = [ "k256", "num-traits", "once_cell", - "prost 0.12.6", - "prost-types 0.12.6", + "prost 0.12.4", + "prost-types 0.12.4", "ripemd", "serde", "serde_bytes", @@ -8669,7 +8683,7 @@ dependencies = [ "serde_repr", "sha2 0.10.8", "signature", - "subtle 2.6.1", + "subtle 2.5.0", "subtle-encoding", "tendermint-proto 0.37.0", "time", @@ -8700,8 +8714,8 @@ dependencies = [ "flex-error", "num-derive", "num-traits", - "prost 0.12.6", - "prost-types 0.12.6", + "prost 0.12.4", + "prost-types 0.12.4", "serde", "serde_bytes", "subtle-encoding", @@ -8716,8 +8730,8 @@ checksum = "dc87024548c7f3da479885201e3da20ef29e85a3b13d04606b380ac4c7120d87" dependencies = [ "bytes", "flex-error", - "prost 0.12.6", - "prost-types 0.12.6", + "prost 0.12.4", + "prost-types 0.12.4", "serde", "serde_bytes", "subtle-encoding", @@ -8744,7 +8758,7 @@ dependencies = [ "serde", "serde_bytes", "serde_json", - "subtle 2.6.1", + "subtle 2.5.0", "subtle-encoding", "tendermint 0.37.0", "tendermint-config", @@ -8829,7 +8843,7 @@ checksum = "a4558b58466b9ad7ca0f102865eccc95938dca1a74a856f2b57b6629050da261" dependencies = [ "proc-macro2", "quote", - "syn 2.0.66", + "syn 2.0.63", ] [[package]] @@ -8910,9 +8924,9 @@ dependencies = [ [[package]] name = "tinyvec" -version = "1.7.0" +version = "1.6.0" source = "registry+https://github.com/rust-lang/crates.io-index" -checksum = "ce6b6a2fb3a985e99cebfaefa9faa3024743da73304ca1c683a36429613d3d22" +checksum = "87cc5ceb3875bb20c2890005a4e226a4651264a5c75edb2421b52861a0a0cb50" dependencies = [ "tinyvec_macros", ] @@ -8932,8 +8946,8 @@ dependencies = [ "backtrace", "bytes", "libc", - "mio 1.0.1", - "parking_lot 0.12.3", + "mio 1.0.2", + "parking_lot 0.12.2", "pin-project-lite", "signal-hook-registry", "socket2", @@ -8960,7 +8974,7 @@ checksum = "693d596312e88961bc67d7f1f97af8a70227d9f90c31bba5806eec004978d752" dependencies = [ "proc-macro2", "quote", - "syn 2.0.66", + "syn 2.0.63", ] [[package]] @@ -9034,12 +9048,12 @@ dependencies = [ [[package]] name = "tokio-tun" -version = "0.11.5" +version = "0.11.4" source = "registry+https://github.com/rust-lang/crates.io-index" -checksum = "68f5381752d5832fc811f89d54fc334951aa435022f494190ba7151661f206df" +checksum = "65d79912ba514490b1f5a574b585e19082bd2a6b238970c87c57a66bd77206b5" dependencies = [ "libc", - "nix 0.29.0", + "nix 0.28.0", "thiserror", "tokio", ] @@ -9151,7 +9165,7 @@ dependencies = [ "serde", "serde_spanned", "toml_datetime", - "winnow 0.6.13", + "winnow 0.6.8", ] [[package]] @@ -9169,7 +9183,7 @@ dependencies = [ "h2", "http 0.2.12", "http-body 0.4.6", - "hyper 0.14.29", + "hyper 0.14.28", "hyper-timeout", "percent-encoding", "pin-project", @@ -9208,7 +9222,7 @@ version = "0.5.2" source = "registry+https://github.com/rust-lang/crates.io-index" checksum = "1e9cd434a998747dd2c4276bc96ee2e0c7a2eadf3cae88e52be55a05fa9053f5" dependencies = [ - "bitflags 2.6.0", + "bitflags 2.5.0", "bytes", "futures-util", "http 1.1.0", @@ -9259,7 +9273,7 @@ checksum = "34704c8d6ebcbc939824180af020566b01a7c01f80641264eba0999f6c2b6be7" dependencies = [ "proc-macro2", "quote", - "syn 2.0.66", + "syn 2.0.63", ] [[package]] @@ -9417,7 +9431,7 @@ dependencies = [ "Inflector", "proc-macro2", "quote", - "syn 2.0.66", + "syn 2.0.63", "termcolor", ] @@ -9444,7 +9458,7 @@ dependencies = [ "proc-macro2", "quote", "serde_derive_internals 0.28.0", - "syn 2.0.66", + "syn 2.0.63", ] [[package]] @@ -9560,12 +9574,6 @@ dependencies = [ "tinyvec", ] -[[package]] -name = "unicode-properties" -version = "0.1.1" -source = "registry+https://github.com/rust-lang/crates.io-index" -checksum = "e4259d9d4425d9f0661581b804cb85fe66a4c631cadd8f490d1c13a35d5d9291" - [[package]] name = "unicode-segmentation" version = "1.11.0" @@ -9574,9 +9582,9 @@ checksum = "d4c87d22b6e3f4a18d4d40ef354e97c90fcb14dd91d7dc0aa9d8a1172ebf7202" [[package]] name = "unicode-width" -version = "0.1.13" +version = "0.1.12" source = "registry+https://github.com/rust-lang/crates.io-index" -checksum = "0336d538f7abc86d282a4189614dfaa90810dfc2c6f6427eaf88e16311dd225d" +checksum = "68f5e5f3158ecfd4b8ff6fe086db7c8467a2dfdac97fe420f2b7c4aa97af66d6" [[package]] name = "unicode-xid" @@ -9606,7 +9614,7 @@ source = "registry+https://github.com/rust-lang/crates.io-index" checksum = "fc1de2c688dc15305988b563c3854064043356019f97a4b46276fe734c4f07ea" dependencies = [ "crypto-common", - "subtle 2.6.1", + "subtle 2.5.0", ] [[package]] @@ -9635,9 +9643,9 @@ checksum = "0976c77def3f1f75c4ef892a292c31c0bbe9e3d0702c63044d7c76db298171a3" [[package]] name = "url" -version = "2.5.2" +version = "2.5.0" source = "registry+https://github.com/rust-lang/crates.io-index" -checksum = "22784dbdf76fdde8af1aeda5622b546b422b6fc585325248a2bf9f5e41e94d6c" +checksum = "31e6302e3bb753d46e83516cae55ae196fc0c309407cf11ab35cc51a4c2a4633" dependencies = [ "form_urlencoded", "idna 0.5.0", @@ -9659,9 +9667,9 @@ checksum = "09cc8ee72d2a9becf2f2febe0205bbed8fc6615b7cb429ad062dc7b7ddd036a9" [[package]] name = "utf8parse" -version = "0.2.2" +version = "0.2.1" source = "registry+https://github.com/rust-lang/crates.io-index" -checksum = "06abde3611657adf66d383f00b093d7faecc7fa57071cce2578660c9f1010821" +checksum = "711b9620af191e0cdc7468a8d14e709c3dcdb115b36f838e601583af800a370a" [[package]] name = "utoipa" @@ -9685,7 +9693,7 @@ dependencies = [ "proc-macro2", "quote", "regex", - "syn 2.0.66", + "syn 2.0.63", ] [[package]] @@ -9723,7 +9731,7 @@ checksum = "17e82ab96c5a55263b5bed151b8426410d93aa909a453acdbd4b6792b5af7d64" dependencies = [ "proc-macro2", "quote", - "syn 2.0.66", + "syn 2.0.63", ] [[package]] @@ -9734,15 +9742,15 @@ checksum = "86b8338dc3c9526011ffaa2aa6bd60ddfda9d49d2123108690755c6e34844212" dependencies = [ "proc-macro2", "quote", - "syn 2.0.66", + "syn 2.0.63", "utoipauto-core", ] [[package]] name = "uuid" -version = "1.8.0" +version = "1.10.0" source = "registry+https://github.com/rust-lang/crates.io-index" -checksum = "a183cf7feeba97b4dd1c0d46788634f6221d87fa961b305bed08c851829efcc0" +checksum = "81dfa00651efa65069b0b6b651f4aaa31ba9e3c3ce0137aaad053604ee7e0314" dependencies = [ "getrandom", "serde", @@ -9835,7 +9843,7 @@ dependencies = [ "once_cell", "proc-macro2", "quote", - "syn 2.0.66", + "syn 2.0.63", "wasm-bindgen-shared", ] @@ -9869,7 +9877,7 @@ checksum = "afc340c74d9005395cf9dd098506f7f44e38f2b4a21c6aaacf9a105ea5e1e836" dependencies = [ "proc-macro2", "quote", - "syn 2.0.66", + "syn 2.0.63", "wasm-bindgen-backend", "wasm-bindgen-shared", ] @@ -9902,7 +9910,7 @@ checksum = "b7f89739351a2e03cb94beb799d47fb2cac01759b40ec441f7de39b00cbf7ef0" dependencies = [ "proc-macro2", "quote", - "syn 2.0.66", + "syn 2.0.63", ] [[package]] @@ -9990,7 +9998,7 @@ checksum = "5f656cd8858a5164932d8a90f936700860976ec21eb00e0fe2aa8cab13f6b4cf" dependencies = [ "futures", "js-sys", - "parking_lot 0.12.3", + "parking_lot 0.12.2", "pin-utils", "slab", "wasm-bindgen", @@ -10042,9 +10050,9 @@ checksum = "5f20c57d8d7db6d3b86154206ae5d8fba62dd39573114de97c2cb0578251f8e1" [[package]] name = "webpki-roots" -version = "0.26.2" +version = "0.26.1" source = "registry+https://github.com/rust-lang/crates.io-index" -checksum = "3c452ad30530b54a4d8e71952716a212b08efd0f3562baa66c29a618b07da7c3" +checksum = "b3de34ae270483955a94f4b21bdaaeb83d508bb84a01435f393818edb0012009" dependencies = [ "rustls-pki-types", ] @@ -10096,7 +10104,7 @@ source = "registry+https://github.com/rust-lang/crates.io-index" checksum = "e48a53791691ab099e5e2ad123536d0fff50652600abaf43bbf952894110d0be" dependencies = [ "windows-core", - "windows-targets 0.52.6", + "windows-targets 0.52.5", ] [[package]] @@ -10105,7 +10113,7 @@ version = "0.52.0" source = "registry+https://github.com/rust-lang/crates.io-index" checksum = "33ab640c8d7e35bf8ba19b884ba838ceb4fba93a4e8c65a9059d08afcfc683d9" dependencies = [ - "windows-targets 0.52.6", + "windows-targets 0.52.5", ] [[package]] @@ -10132,7 +10140,7 @@ version = "0.52.0" source = "registry+https://github.com/rust-lang/crates.io-index" checksum = "282be5f36a8ce781fad8c8ae18fa3f9beff57ec1b52cb3de0789201425d9a33d" dependencies = [ - "windows-targets 0.52.6", + "windows-targets 0.52.5", ] [[package]] @@ -10167,18 +10175,18 @@ dependencies = [ [[package]] name = "windows-targets" -version = "0.52.6" +version = "0.52.5" source = "registry+https://github.com/rust-lang/crates.io-index" -checksum = "9b724f72796e036ab90c1021d4780d4d3d648aca59e491e6b98e725b84e99973" +checksum = "6f0713a46559409d202e70e28227288446bf7841d3211583a4b53e3f6d96e7eb" dependencies = [ - "windows_aarch64_gnullvm 0.52.6", - "windows_aarch64_msvc 0.52.6", - "windows_i686_gnu 0.52.6", + "windows_aarch64_gnullvm 0.52.5", + "windows_aarch64_msvc 0.52.5", + "windows_i686_gnu 0.52.5", "windows_i686_gnullvm", - "windows_i686_msvc 0.52.6", - "windows_x86_64_gnu 0.52.6", - "windows_x86_64_gnullvm 0.52.6", - "windows_x86_64_msvc 0.52.6", + "windows_i686_msvc 0.52.5", + "windows_x86_64_gnu 0.52.5", + "windows_x86_64_gnullvm 0.52.5", + "windows_x86_64_msvc 0.52.5", ] [[package]] @@ -10195,9 +10203,9 @@ checksum = "2b38e32f0abccf9987a4e3079dfb67dcd799fb61361e53e2882c3cbaf0d905d8" [[package]] name = "windows_aarch64_gnullvm" -version = "0.52.6" +version = "0.52.5" source = "registry+https://github.com/rust-lang/crates.io-index" -checksum = "32a4622180e7a0ec044bb555404c800bc9fd9ec262ec147edd5989ccd0c02cd3" +checksum = "7088eed71e8b8dda258ecc8bac5fb1153c5cffaf2578fc8ff5d61e23578d3263" [[package]] name = "windows_aarch64_msvc" @@ -10213,9 +10221,9 @@ checksum = "dc35310971f3b2dbbf3f0690a219f40e2d9afcf64f9ab7cc1be722937c26b4bc" [[package]] name = "windows_aarch64_msvc" -version = "0.52.6" +version = "0.52.5" source = "registry+https://github.com/rust-lang/crates.io-index" -checksum = "09ec2a7bb152e2252b53fa7803150007879548bc709c039df7627cabbd05d469" +checksum = "9985fd1504e250c615ca5f281c3f7a6da76213ebd5ccc9561496568a2752afb6" [[package]] name = "windows_i686_gnu" @@ -10231,15 +10239,15 @@ checksum = "a75915e7def60c94dcef72200b9a8e58e5091744960da64ec734a6c6e9b3743e" [[package]] name = "windows_i686_gnu" -version = "0.52.6" +version = "0.52.5" source = "registry+https://github.com/rust-lang/crates.io-index" -checksum = "8e9b5ad5ab802e97eb8e295ac6720e509ee4c243f69d781394014ebfe8bbfa0b" +checksum = "88ba073cf16d5372720ec942a8ccbf61626074c6d4dd2e745299726ce8b89670" [[package]] name = "windows_i686_gnullvm" -version = "0.52.6" +version = "0.52.5" source = "registry+https://github.com/rust-lang/crates.io-index" -checksum = "0eee52d38c090b3caa76c563b86c3a4bd71ef1a819287c19d586d7334ae8ed66" +checksum = "87f4261229030a858f36b459e748ae97545d6f1ec60e5e0d6a3d32e0dc232ee9" [[package]] name = "windows_i686_msvc" @@ -10255,9 +10263,9 @@ checksum = "8f55c233f70c4b27f66c523580f78f1004e8b5a8b659e05a4eb49d4166cca406" [[package]] name = "windows_i686_msvc" -version = "0.52.6" +version = "0.52.5" source = "registry+https://github.com/rust-lang/crates.io-index" -checksum = "240948bc05c5e7c6dabba28bf89d89ffce3e303022809e73deaefe4f6ec56c66" +checksum = "db3c2bf3d13d5b658be73463284eaf12830ac9a26a90c717b7f771dfe97487bf" [[package]] name = "windows_x86_64_gnu" @@ -10273,9 +10281,9 @@ checksum = "53d40abd2583d23e4718fddf1ebec84dbff8381c07cae67ff7768bbf19c6718e" [[package]] name = "windows_x86_64_gnu" -version = "0.52.6" +version = "0.52.5" source = "registry+https://github.com/rust-lang/crates.io-index" -checksum = "147a5c80aabfbf0c7d901cb5895d1de30ef2907eb21fbbab29ca94c5b08b1a78" +checksum = "4e4246f76bdeff09eb48875a0fd3e2af6aada79d409d33011886d3e1581517d9" [[package]] name = "windows_x86_64_gnullvm" @@ -10291,9 +10299,9 @@ checksum = "0b7b52767868a23d5bab768e390dc5f5c55825b6d30b86c844ff2dc7414044cc" [[package]] name = "windows_x86_64_gnullvm" -version = "0.52.6" +version = "0.52.5" source = "registry+https://github.com/rust-lang/crates.io-index" -checksum = "24d5b23dc417412679681396f2b49f3de8c1473deb516bd34410872eff51ed0d" +checksum = "852298e482cd67c356ddd9570386e2862b5673c85bd5f88df9ab6802b334c596" [[package]] name = "windows_x86_64_msvc" @@ -10309,9 +10317,9 @@ checksum = "ed94fce61571a4006852b7389a063ab983c02eb1bb37b47f8272ce92d06d9538" [[package]] name = "windows_x86_64_msvc" -version = "0.52.6" +version = "0.52.5" source = "registry+https://github.com/rust-lang/crates.io-index" -checksum = "589f6da84c646204747d1270a2a5661ea66ed1cced2631d546fdfb155959f9ec" +checksum = "bec47e5bfd1bff0eeaf6d8b485cc1074891a197ab4225d504cb7a1ab88b02bf0" [[package]] name = "winnow" @@ -10324,9 +10332,9 @@ dependencies = [ [[package]] name = "winnow" -version = "0.6.13" +version = "0.6.8" source = "registry+https://github.com/rust-lang/crates.io-index" -checksum = "59b5e5f6c299a3c7890b876a2a587f3115162487e704907d9b6cd29473052ba1" +checksum = "c3c52e9c97a68071b23e836c9380edae937f17b9c4667bd021973efc689f618d" dependencies = [ "memchr", ] @@ -10386,7 +10394,7 @@ version = "2.0.1" source = "registry+https://github.com/rust-lang/crates.io-index" checksum = "c7e468321c81fb07fa7f4c636c3972b9100f0346e5b6a9f2bd0603a52f7ed277" dependencies = [ - "curve25519-dalek 4.1.3", + "curve25519-dalek 4.1.2", "rand_core 0.6.4", "serde", "zeroize", @@ -10414,22 +10422,22 @@ dependencies = [ [[package]] name = "zerocopy" -version = "0.7.35" +version = "0.7.34" source = "registry+https://github.com/rust-lang/crates.io-index" -checksum = "1b9b4fd18abc82b8136838da5d50bae7bdea537c574d8dc1a34ed098d6c166f0" +checksum = "ae87e3fcd617500e5d106f0380cf7b77f3c6092aae37191433159dda23cfb087" dependencies = [ "zerocopy-derive", ] [[package]] name = "zerocopy-derive" -version = "0.7.35" +version = "0.7.34" source = "registry+https://github.com/rust-lang/crates.io-index" -checksum = "fa4f8080344d4671fb4e831a13ad1e68092748387dfc4f55e356242fae12ce3e" +checksum = "15e934569e47891f7d9411f1a451d947a60e000ab3bd24fbb970f000387d1b3b" dependencies = [ "proc-macro2", "quote", - "syn 2.0.66", + "syn 2.0.63", ] [[package]] @@ -10449,7 +10457,7 @@ checksum = "ce36e65b0d2999d2aafac989fb249189a141aee1f53c612c1f37d72631959f69" dependencies = [ "proc-macro2", "quote", - "syn 2.0.66", + "syn 2.0.63", ] [[package]] diff --git a/common/client-libs/validator-client/src/nym_api/mod.rs b/common/client-libs/validator-client/src/nym_api/mod.rs index fa0bb2b7a9..1ebfea7284 100644 --- a/common/client-libs/validator-client/src/nym_api/mod.rs +++ b/common/client-libs/validator-client/src/nym_api/mod.rs @@ -9,17 +9,9 @@ use nym_api_requests::ecash::models::{ BatchRedeemTicketsBody, EcashBatchTicketRedemptionResponse, EcashTicketVerificationResponse, VerifyEcashTicketBody, }; -use nym_api_requests::nym_nodes::{CachedNodesResponse, SkimmedNode}; -use nym_http_api_client::{ApiClient, NO_PARAMS}; -use nym_mixnet_contract_common::mixnode::MixNodeDetails; -use nym_mixnet_contract_common::{GatewayBond, IdentityKeyRef, MixId}; -use time::format_description::BorrowedFormatItem; -use time::Date; - -pub mod error; -pub mod routes; - use nym_api_requests::ecash::VerificationKeyResponse; +use nym_api_requests::models::DescribedMixNode; +use nym_api_requests::nym_nodes::{CachedNodesResponse, SkimmedNode}; pub use nym_api_requests::{ ecash::{ models::{ @@ -39,7 +31,16 @@ pub use nym_api_requests::{ }, }; pub use nym_coconut_dkg_common::types::EpochId; +use nym_contracts_common::IdentityKey; pub use nym_http_api_client::Client; +use nym_http_api_client::{ApiClient, NO_PARAMS}; +use nym_mixnet_contract_common::mixnode::MixNodeDetails; +use nym_mixnet_contract_common::{GatewayBond, IdentityKeyRef, MixId}; +use time::format_description::BorrowedFormatItem; +use time::Date; + +pub mod error; +pub mod routes; pub fn rfc_3339_date() -> Vec> { time::format_description::parse("[year]-[month]-[day]").unwrap() @@ -107,6 +108,14 @@ pub trait NymApiClientExt: ApiClient { .await } + async fn get_mixnodes_described(&self) -> Result, NymAPIError> { + self.get_json( + &[routes::API_VERSION, routes::MIXNODES, routes::DESCRIBED], + NO_PARAMS, + ) + .await + } + async fn get_basic_mixnodes( &self, semver_compatibility: Option, @@ -431,6 +440,22 @@ pub trait NymApiClientExt: ApiClient { .await } + async fn get_mixnodes_blacklisted(&self) -> Result, NymAPIError> { + self.get_json( + &[routes::API_VERSION, routes::MIXNODES, routes::BLACKLISTED], + NO_PARAMS, + ) + .await + } + + async fn get_gateways_blacklisted(&self) -> Result, NymAPIError> { + self.get_json( + &[routes::API_VERSION, routes::GATEWAYS, routes::BLACKLISTED], + NO_PARAMS, + ) + .await + } + async fn blind_sign( &self, request_body: &BlindSignRequestBody, diff --git a/common/client-libs/validator-client/src/nym_api/routes.rs b/common/client-libs/validator-client/src/nym_api/routes.rs index b77d6438b5..dc87026701 100644 --- a/common/client-libs/validator-client/src/nym_api/routes.rs +++ b/common/client-libs/validator-client/src/nym_api/routes.rs @@ -7,6 +7,7 @@ pub const API_VERSION: &str = NYM_API_VERSION; pub const MIXNODES: &str = "mixnodes"; pub const GATEWAYS: &str = "gateways"; pub const DESCRIBED: &str = "described"; +pub const BLACKLISTED: &str = "blacklisted"; pub const DETAILED: &str = "detailed"; pub const DETAILED_UNFILTERED: &str = "detailed-unfiltered"; From e76bb0db12c782cba6127476e7772afc7314a895 Mon Sep 17 00:00:00 2001 From: =?UTF-8?q?Jon=20H=C3=A4ggblad?= Date: Tue, 3 Sep 2024 21:33:42 +0200 Subject: [PATCH 59/93] Add build-deb-meta.yml --- .github/workflows/build-deb-meta.yml | 0 1 file changed, 0 insertions(+), 0 deletions(-) create mode 100644 .github/workflows/build-deb-meta.yml diff --git a/.github/workflows/build-deb-meta.yml b/.github/workflows/build-deb-meta.yml new file mode 100644 index 0000000000..e69de29bb2 From 3c4bd13c2ad5ede506c0542859051f392dca6c20 Mon Sep 17 00:00:00 2001 From: =?UTF-8?q?Jon=20H=C3=A4ggblad?= Date: Tue, 3 Sep 2024 21:48:17 +0200 Subject: [PATCH 60/93] build-deb-meta.yml placeholder --- .github/workflows/build-deb-meta.yml | 9 +++++++++ 1 file changed, 9 insertions(+) diff --git a/.github/workflows/build-deb-meta.yml b/.github/workflows/build-deb-meta.yml index e69de29bb2..52618e57ce 100644 --- a/.github/workflows/build-deb-meta.yml +++ b/.github/workflows/build-deb-meta.yml @@ -0,0 +1,9 @@ +name: build-deb-meta + +on: + workflow_dispatch: + +jobs: + build: + steps: + run: "echo hello" From 18891e5f205c05c6cfda845b585808eb758fc421 Mon Sep 17 00:00:00 2001 From: =?UTF-8?q?Bogdan-=C8=98tefan=20Neac=C5=9Fu?= Date: Thu, 5 Sep 2024 13:19:19 +0200 Subject: [PATCH 61/93] Use ecash credential type for bandwidth value (#4840) * Use ecash credential type for bandwidth value * Fill explicit default value for args * Use up-to-date values for tickets * Fix sdk example default value * Another default * Fix sdk test * Fix TicketTypeRepr default --- common/commands/src/coconut/issue_ticket_book.rs | 2 +- common/credentials-interface/src/lib.rs | 11 +---------- common/network-defaults/src/ecash.rs | 13 +++++-------- .../benches/benchmarks_ecash_e2e.rs | 2 +- .../websocket/connection_handler/authenticated.rs | 8 ++++++-- .../connection_handler/ecash/credential_sender.rs | 14 ++++++++++---- .../websocket/connection_handler/ecash/error.rs | 3 +++ .../src/rewarder/credential_issuance/monitor.rs | 4 +++- sdk/rust/nym-sdk/examples/bandwidth.rs | 3 ++- sdk/rust/nym-sdk/src/bandwidth.rs | 3 ++- 10 files changed, 34 insertions(+), 29 deletions(-) diff --git a/common/commands/src/coconut/issue_ticket_book.rs b/common/commands/src/coconut/issue_ticket_book.rs index c6b0997ba5..79eb67ac0c 100644 --- a/common/commands/src/coconut/issue_ticket_book.rs +++ b/common/commands/src/coconut/issue_ticket_book.rs @@ -14,7 +14,7 @@ use std::path::PathBuf; #[derive(Debug, Parser)] pub struct Args { /// Specify which type of ticketbook should be issued - #[clap(long, default_value_t = TicketType::default())] + #[clap(long, default_value_t = TicketType::V1MixnetEntry)] pub(crate) ticketbook_type: TicketType, /// Config file of the client that is supposed to use the credential. diff --git a/common/credentials-interface/src/lib.rs b/common/credentials-interface/src/lib.rs index 85938c3c61..270cb5f658 100644 --- a/common/credentials-interface/src/lib.rs +++ b/common/credentials-interface/src/lib.rs @@ -221,20 +221,11 @@ impl From for NymPayInfo { } #[derive( - Default, - Copy, - Clone, - Debug, - PartialEq, - Serialize, - Deserialize, - strum::Display, - strum::EnumString, + Copy, Clone, Debug, PartialEq, Serialize, Deserialize, strum::Display, strum::EnumString, )] #[serde(rename_all = "kebab-case")] #[strum(serialize_all = "kebab-case")] pub enum TicketType { - #[default] V1MixnetEntry, V1MixnetExit, V1WireguardEntry, diff --git a/common/network-defaults/src/ecash.rs b/common/network-defaults/src/ecash.rs index 21d1ddfe85..ee5e7b5c61 100644 --- a/common/network-defaults/src/ecash.rs +++ b/common/network-defaults/src/ecash.rs @@ -9,10 +9,9 @@ pub const TICKETBOOK_SIZE: u64 = 50; /// This type is defined mostly for the purposes of having constants (like sizes) associated with given variants /// It's not meant to be serialised or have any fancy traits defined on it (in this crate) -#[derive(Default, Copy, Clone, Debug, PartialEq)] +#[derive(Copy, Clone, Debug, PartialEq)] #[repr(u8)] pub enum TicketTypeRepr { - #[default] V1MixnetEntry = 0, V1MixnetExit = 1, V1WireguardEntry = 2, @@ -20,12 +19,10 @@ pub enum TicketTypeRepr { } impl TicketTypeRepr { - pub const WIREGUARD_ENTRY_TICKET_SIZE: u64 = 500 * 1024 * 1024; // 500 MB - - // TBD: - pub const WIREGUARD_EXIT_TICKET_SIZE: u64 = Self::WIREGUARD_ENTRY_TICKET_SIZE; - pub const MIXNET_ENTRY_TICKET_SIZE: u64 = Self::WIREGUARD_ENTRY_TICKET_SIZE; - pub const MIXNET_EXIT_TICKET_SIZE: u64 = Self::WIREGUARD_ENTRY_TICKET_SIZE; + pub const WIREGUARD_ENTRY_TICKET_SIZE: u64 = 512 * 1024 * 1024; // 512 MB + pub const WIREGUARD_EXIT_TICKET_SIZE: u64 = 512 * 1024 * 1024; // 512 MB + pub const MIXNET_ENTRY_TICKET_SIZE: u64 = 128 * 1024 * 1024; // 128 MB + pub const MIXNET_EXIT_TICKET_SIZE: u64 = 128 * 1024 * 1024; // 128 MB /// How much bandwidth (in bytes) one ticket can grant pub const fn bandwidth_value(&self) -> u64 { diff --git a/common/nym_offline_compact_ecash/benches/benchmarks_ecash_e2e.rs b/common/nym_offline_compact_ecash/benches/benchmarks_ecash_e2e.rs index f7ea0cf9f3..e57eaafa03 100644 --- a/common/nym_offline_compact_ecash/benches/benchmarks_ecash_e2e.rs +++ b/common/nym_offline_compact_ecash/benches/benchmarks_ecash_e2e.rs @@ -32,7 +32,7 @@ fn bench_compact_ecash(c: &mut Criterion) { let spend_date = 1701907200; // Dec 07 2023 00:00:00 let expiration_date = 1702166400; // Dec 10 2023 00:00:00 - let encoded_ticket_type = TicketTypeRepr::default() as u8; + let encoded_ticket_type = TicketTypeRepr::V1MixnetEntry as u8; let case = BenchCase { num_authorities: 100, diff --git a/gateway/src/node/client_handling/websocket/connection_handler/authenticated.rs b/gateway/src/node/client_handling/websocket/connection_handler/authenticated.rs index 51117b2879..d0f039fcca 100644 --- a/gateway/src/node/client_handling/websocket/connection_handler/authenticated.rs +++ b/gateway/src/node/client_handling/websocket/connection_handler/authenticated.rs @@ -18,7 +18,7 @@ use futures::{ FutureExt, StreamExt, }; use nym_credentials::ecash::utils::{ecash_today, EcashTime}; -use nym_credentials_interface::{ClientTicket, CredentialSpendingData}; +use nym_credentials_interface::{ClientTicket, CredentialSpendingData, TicketType}; use nym_gateway_requests::models::CredentialSpendingRequest; use nym_gateway_requests::{ types::{BinaryRequest, ServerResponse}, @@ -104,6 +104,9 @@ pub enum RequestHandlingError { "the received payment contained more than a single ticket. that's currently not supported" )] MultipleTickets, + + #[error("{0}")] + UnknownTicketType(#[from] nym_credentials_interface::UnknownTicketType), } impl RequestHandlingError { @@ -414,6 +417,7 @@ where // check if the credential hasn't been spent before let serial_number = credential.data.encoded_serial_number(); + let credential_type = TicketType::try_from_encoded(credential.data.payment.t_type)?; if credential.data.payment.spend_value != 1 { return Err(RequestHandlingError::MultipleTickets); @@ -433,7 +437,7 @@ where // TODO: double storing? // self.store_spent_credential(serial_number_bs58).await?; - let bandwidth = Bandwidth::ticket_amount(Default::default()); + let bandwidth = Bandwidth::ticket_amount(credential_type.into()); self.increase_bandwidth(bandwidth, spend_date).await?; diff --git a/gateway/src/node/client_handling/websocket/connection_handler/ecash/credential_sender.rs b/gateway/src/node/client_handling/websocket/connection_handler/ecash/credential_sender.rs index 16670fe132..7cc478cc9a 100644 --- a/gateway/src/node/client_handling/websocket/connection_handler/ecash/credential_sender.rs +++ b/gateway/src/node/client_handling/websocket/connection_handler/ecash/credential_sender.rs @@ -12,7 +12,7 @@ use futures::channel::mpsc::UnboundedReceiver; use futures::{Stream, StreamExt}; use nym_api_requests::constants::MIN_BATCH_REDEMPTION_DELAY; use nym_api_requests::ecash::models::{BatchRedeemTicketsBody, VerifyEcashTicketBody}; -use nym_credentials_interface::ClientTicket; +use nym_credentials_interface::{ClientTicket, TicketType}; use nym_gateway_storage::Storage; use nym_validator_client::nym_api::EpochId; use nym_validator_client::nyxd::contract_traits::{ @@ -362,10 +362,14 @@ where } #[instrument(skip(self))] - async fn revoke_ticket_bandwidth(&self, ticket_id: i64) -> Result<(), EcashTicketError> { + async fn revoke_ticket_bandwidth( + &self, + ticket_id: i64, + ticket_type: TicketType, + ) -> Result<(), EcashTicketError> { warn!("revoking bandwidth associated with ticket {ticket_id} since it failed verification"); - let bytes_to_revoke = Bandwidth::ticket_amount(Default::default()).value() as f32 + let bytes_to_revoke = Bandwidth::ticket_amount(ticket_type.into()).value() as f32 * self.config.revocation_bandwidth_penalty; let to_revoke_bi2 = bibytes2(bytes_to_revoke as f64); @@ -385,6 +389,8 @@ where api_clients: Option>>, ) -> Result { let ticket_id = pending.ticket.ticket_id; + let ticket_type = + TicketType::try_from_encoded(pending.ticket.spending_data.payment.t_type)?; let api_clients = match api_clients { Some(clients) => clients, None => { @@ -444,7 +450,7 @@ where .storage .update_rejected_ticket(pending.ticket.ticket_id) .await?; - self.revoke_ticket_bandwidth(pending.ticket.ticket_id) + self.revoke_ticket_bandwidth(pending.ticket.ticket_id, ticket_type) .await?; } diff --git a/gateway/src/node/client_handling/websocket/connection_handler/ecash/error.rs b/gateway/src/node/client_handling/websocket/connection_handler/ecash/error.rs index c39ad89720..9e025316a7 100644 --- a/gateway/src/node/client_handling/websocket/connection_handler/ecash/error.rs +++ b/gateway/src/node/client_handling/websocket/connection_handler/ecash/error.rs @@ -28,6 +28,9 @@ pub enum EcashTicketError { #[error("provided payinfo's timestamp is invalid")] InvalidPayInfoTimestamp, + #[error("{0}")] + InvalidTicketType(#[from] nym_credentials_interface::UnknownTicketType), + #[error("received payinfo is a duplicate")] DuplicatePayInfo, diff --git a/nym-validator-rewarder/src/rewarder/credential_issuance/monitor.rs b/nym-validator-rewarder/src/rewarder/credential_issuance/monitor.rs index b4a2befa02..41bb39a6f8 100644 --- a/nym-validator-rewarder/src/rewarder/credential_issuance/monitor.rs +++ b/nym-validator-rewarder/src/rewarder/credential_issuance/monitor.rs @@ -331,6 +331,7 @@ mod tests { use super::*; use nym_compact_ecash::ttp_keygen; use nym_credentials::IssuanceTicketBook; + use nym_credentials_interface::TicketType; use nym_crypto::asymmetric::{ed25519, identity}; use rand_chacha::rand_core::{RngCore, SeedableRng}; @@ -349,7 +350,8 @@ mod tests { identity::PrivateKey::from_bytes(&identity_keypair.private_key().to_bytes()).unwrap(); let identifier = [44u8; 32]; - let issuance = IssuanceTicketBook::new(deposit_id, identifier, id_priv, Default::default()); + let issuance = + IssuanceTicketBook::new(deposit_id, identifier, id_priv, TicketType::V1MixnetEntry); let signing_data = issuance.prepare_for_signing(); let request = issuance.create_blind_sign_request_body(&signing_data); diff --git a/sdk/rust/nym-sdk/examples/bandwidth.rs b/sdk/rust/nym-sdk/examples/bandwidth.rs index b104ee51ea..bc30d1f65e 100644 --- a/sdk/rust/nym-sdk/examples/bandwidth.rs +++ b/sdk/rust/nym-sdk/examples/bandwidth.rs @@ -1,4 +1,5 @@ use futures::StreamExt; +use nym_credentials_interface::TicketType; use nym_network_defaults::setup_env; use nym_sdk::mixnet; use nym_sdk::mixnet::MixnetMessageSender; @@ -19,7 +20,7 @@ async fn main() -> anyhow::Result<()> { .build()?; let bandwidth_client = mixnet_client - .create_bandwidth_client(mnemonic, Default::default()) + .create_bandwidth_client(mnemonic, TicketType::V1MixnetEntry) .await?; // Get a bandwidth credential for the mixnet_client diff --git a/sdk/rust/nym-sdk/src/bandwidth.rs b/sdk/rust/nym-sdk/src/bandwidth.rs index 2152319f97..ef619429de 100644 --- a/sdk/rust/nym-sdk/src/bandwidth.rs +++ b/sdk/rust/nym-sdk/src/bandwidth.rs @@ -7,6 +7,7 @@ //! //! ```no_run //! use nym_sdk::mixnet::{self, MixnetMessageSender}; +//! use nym_credentials_interface::TicketType; //! //! #[tokio::main] //! async fn main() { @@ -15,7 +16,7 @@ //! .build() //! .unwrap(); //! -//! let bandwidth_client = mixnet_client.create_bandwidth_client(String::from("my super secret mnemonic"), Default::default()).await.unwrap(); +//! let bandwidth_client = mixnet_client.create_bandwidth_client(String::from("my super secret mnemonic"), TicketType::V1MixnetEntry).await.unwrap(); //! //! // Get a bandwidth credential for the mixnet_client //! bandwidth_client.acquire().await.unwrap(); From b7baff1a79d19ff8729531b1b8b10510b68cd8ca Mon Sep 17 00:00:00 2001 From: import this <97586125+serinko@users.noreply.github.com> Date: Fri, 6 Sep 2024 10:03:54 +0000 Subject: [PATCH 62/93] [DOCs:/dev-portal]: Add NymVPN hyper-link (#4842) --- documentation/dev-portal/src/nymvpn/intro.md | 2 +- 1 file changed, 1 insertion(+), 1 deletion(-) diff --git a/documentation/dev-portal/src/nymvpn/intro.md b/documentation/dev-portal/src/nymvpn/intro.md index b559d22bd6..738d9e801b 100644 --- a/documentation/dev-portal/src/nymvpn/intro.md +++ b/documentation/dev-portal/src/nymvpn/intro.md @@ -1,6 +1,6 @@ # NymVPN beta -**NymVPN** is a client that uses [Nym Mixnet](https://nymtech.net) to anonymise all of a user's internet traffic through either a 5-hop mixnet for a *full network privacy* or the *faster* 2-hop decentralised VPN (with some extra features). +[**NymVPN**](https://nymvpn.com/en) is a client that uses [Nym Mixnet](https://nymtech.net) to anonymise all of a user's internet traffic through either a 5-hop mixnet for a *full network privacy* or the *faster* 2-hop decentralised VPN (with some extra features). **You are invited to take part in the beta testing** of this new application. Register for private testing round at [nymvpn.com](https://nymvpn.com/en), that will grant you access to the [download page](https://nymvpn.com/download). Visit [NymVPN Support & FAQ](https://nymvpn.com/en/support) or join the [NymVPN matrix channel](https://matrix.to/#/#NymVPN:nymtech.chat) if you have any questions, comments or blockers. From 230e4393c5e7342630089eb8720c9638ce768b77 Mon Sep 17 00:00:00 2001 From: =?UTF-8?q?Jon=20H=C3=A4ggblad?= Date: Sun, 8 Sep 2024 19:14:05 +0200 Subject: [PATCH 63/93] Fix clippy for nym-wallet and latest rustc (#4845) --- nym-wallet/Cargo.lock | 155 +++++++++++------- .../src/operations/signatures/sign.rs | 5 +- 2 files changed, 93 insertions(+), 67 deletions(-) diff --git a/nym-wallet/Cargo.lock b/nym-wallet/Cargo.lock index 074ff08f97..7117b38868 100644 --- a/nym-wallet/Cargo.lock +++ b/nym-wallet/Cargo.lock @@ -23,6 +23,12 @@ version = "1.0.2" source = "registry+https://github.com/rust-lang/crates.io-index" checksum = "f26201604c87b1e01bd3d98f8d5d9a8fcbb815e8cedb41ffccbeb4bf593a35fe" +[[package]] +name = "adler2" +version = "2.0.0" +source = "registry+https://github.com/rust-lang/crates.io-index" +checksum = "512761e0bb2578dd7380c6baaa0f4ce03e84f95e960231d1dec8bf4d7d6e2627" + [[package]] name = "aead" version = "0.5.2" @@ -167,9 +173,9 @@ checksum = "6b4930d2cb77ce62f89ee5d5289b4ac049559b1c45539271f5ed4fdc7db34545" [[package]] name = "async-trait" -version = "0.1.73" +version = "0.1.82" source = "registry+https://github.com/rust-lang/crates.io-index" -checksum = "bc00ceb34980c03614e35a3a4e218276a0a824e911d07651cd0d858a51e8c0f0" +checksum = "a27b8a3a6e1a44fa4c8baf1f653e4172e81486d4941f2237e20dc2d0cf4ddff1" dependencies = [ "proc-macro2", "quote", @@ -249,7 +255,7 @@ dependencies = [ "cc", "cfg-if", "libc", - "miniz_oxide", + "miniz_oxide 0.7.1", "object", "rustc-demangle", ] @@ -295,11 +301,11 @@ dependencies = [ [[package]] name = "bip32" -version = "0.5.1" +version = "0.5.2" source = "registry+https://github.com/rust-lang/crates.io-index" -checksum = "7e141fb0f8be1c7b45887af94c88b182472b57c96b56773250ae00cd6a14a164" +checksum = "aa13fae8b6255872fd86f7faf4b41168661d7d78609f7bfe6771b85c6739a15b" dependencies = [ - "bs58 0.5.1", + "bs58", "hmac", "k256", "rand_core 0.6.4", @@ -429,12 +435,6 @@ dependencies = [ "alloc-stdlib", ] -[[package]] -name = "bs58" -version = "0.4.0" -source = "registry+https://github.com/rust-lang/crates.io-index" -checksum = "771fe0050b883fcc3ea2359b1a96bcfbc090b7116eae7c3c512c7a083fdf23d3" - [[package]] name = "bs58" version = "0.5.1" @@ -1237,19 +1237,6 @@ dependencies = [ "syn 1.0.109", ] -[[package]] -name = "dashmap" -version = "5.5.3" -source = "registry+https://github.com/rust-lang/crates.io-index" -checksum = "978747c1d849a7d2ee5e8adc0159961c48fb7e5db2f06af6723b80123bb53856" -dependencies = [ - "cfg-if", - "hashbrown 0.14.0", - "lock_api", - "once_cell", - "parking_lot_core", -] - [[package]] name = "der" version = "0.7.8" @@ -1650,12 +1637,12 @@ dependencies = [ [[package]] name = "flate2" -version = "1.0.30" +version = "1.0.33" source = "registry+https://github.com/rust-lang/crates.io-index" -checksum = "5f54427cfd1c7829e2a139fcefea601bf088ebca651d2bf53ebc600eac295dae" +checksum = "324a1be68054ef05ad64b861cc9eaf1d623d2d8cb25b4bf2cb9cdd902b4bf253" dependencies = [ "crc32fast", - "miniz_oxide", + "miniz_oxide 0.8.0", ] [[package]] @@ -1691,9 +1678,9 @@ checksum = "00b0228411908ca8685dba7fc2cdd70ec9990a6e753e89b6ac91a84c40fbaf4b" [[package]] name = "form_urlencoded" -version = "1.2.0" +version = "1.2.1" source = "registry+https://github.com/rust-lang/crates.io-index" -checksum = "a62bc1cf6f830c2ec14a513a9fb124d0a213a629668a4186f329db21fe045652" +checksum = "e13624c2627564efccf4934284bdd98cbaa14e79b0b5a141218e507b3a823456" dependencies = [ "percent-encoding", ] @@ -2509,9 +2496,9 @@ checksum = "b9e0384b61958566e926dc50660321d12159025e767c18e043daf26b70104c39" [[package]] name = "idna" -version = "0.4.0" +version = "0.5.0" source = "registry+https://github.com/rust-lang/crates.io-index" -checksum = "7d20d6b07bfbc108882d88ed8e37d39636dcc260e15e30c45e6ba089610b917c" +checksum = "634d9b1461af396cad843f47fdba5597a4f9e6ddd4bfb6ff5d85028c25cb12f6" dependencies = [ "unicode-bidi", "unicode-normalization", @@ -2572,6 +2559,7 @@ checksum = "d5477fe2230a79769d8dc68e0eabf5437907c0457a5614a9e8dddb67f65eb65d" dependencies = [ "equivalent", "hashbrown 0.14.0", + "serde", ] [[package]] @@ -2921,6 +2909,15 @@ dependencies = [ "simd-adler32", ] +[[package]] +name = "miniz_oxide" +version = "0.8.0" +source = "registry+https://github.com/rust-lang/crates.io-index" +checksum = "e2d80299ef12ff69b16a84bb182e3b9df68b5a91574d3d4fa6e41b65deec4df1" +dependencies = [ + "adler2", +] + [[package]] name = "mio" version = "1.0.1" @@ -3083,7 +3080,7 @@ dependencies = [ name = "nym-api-requests" version = "0.1.0" dependencies = [ - "bs58 0.5.1", + "bs58", "cosmrs 0.17.0-pre", "cosmwasm-std", "ecdsa", @@ -3101,6 +3098,7 @@ dependencies = [ "tendermint 0.37.0", "thiserror", "time", + "utoipa", ] [[package]] @@ -3113,6 +3111,7 @@ dependencies = [ "schemars", "semver 0.11.0", "serde", + "utoipa", "vergen", ] @@ -3144,7 +3143,7 @@ version = "0.1.0" dependencies = [ "bincode", "bls12_381", - "bs58 0.5.1", + "bs58", "cfg-if", "digest 0.9.0", "ff", @@ -3176,7 +3175,7 @@ dependencies = [ name = "nym-contracts-common" version = "0.5.0" dependencies = [ - "bs58 0.5.1", + "bs58", "cosmwasm-schema", "cosmwasm-std", "cw-storage-plus", @@ -3205,7 +3204,7 @@ dependencies = [ name = "nym-crypto" version = "0.4.0" dependencies = [ - "bs58 0.5.1", + "bs58", "ed25519-dalek", "nym-pemstore", "nym-sphinx-types", @@ -3222,7 +3221,7 @@ dependencies = [ name = "nym-ecash-contract-common" version = "0.1.0" dependencies = [ - "bs58 0.5.1", + "bs58", "cosmwasm-schema", "cosmwasm-std", "cw-controllers", @@ -3243,8 +3242,10 @@ name = "nym-exit-policy" version = "0.1.0" dependencies = [ "serde", + "serde_json", "thiserror", "tracing", + "utoipa", ] [[package]] @@ -3278,7 +3279,7 @@ dependencies = [ name = "nym-mixnet-contract-common" version = "0.6.0" dependencies = [ - "bs58 0.4.0", + "bs58", "cosmwasm-schema", "cosmwasm-std", "humantime-serde", @@ -3317,13 +3318,14 @@ dependencies = [ "schemars", "serde", "url", + "utoipa", ] [[package]] name = "nym-node-requests" version = "0.1.0" dependencies = [ - "base64 0.21.4", + "base64 0.22.1", "celes", "humantime 2.1.0", "humantime-serde", @@ -3336,6 +3338,7 @@ dependencies = [ "serde_json", "thiserror", "time", + "utoipa", ] [[package]] @@ -3349,8 +3352,8 @@ dependencies = [ name = "nym-serde-helpers" version = "0.1.0" dependencies = [ - "base64 0.21.4", - "bs58 0.5.1", + "base64 0.22.1", + "bs58", "serde", ] @@ -3381,7 +3384,7 @@ dependencies = [ name = "nym-types" version = "1.0.0" dependencies = [ - "base64 0.21.4", + "base64 0.22.1", "cosmrs 0.17.0-pre", "cosmwasm-std", "eyre", @@ -3410,7 +3413,7 @@ name = "nym-validator-client" version = "0.1.0" dependencies = [ "async-trait", - "base64 0.13.1", + "base64 0.22.1", "bip32", "bip39", "colored 2.0.4", @@ -3503,14 +3506,15 @@ dependencies = [ name = "nym-wireguard-types" version = "0.1.0" dependencies = [ - "base64 0.21.4", - "dashmap", + "base64 0.22.1", "log", "nym-config", "nym-crypto", "nym-network-defaults", "serde", + "serde_json", "thiserror", + "utoipa", "x25519-dalek", ] @@ -3817,9 +3821,9 @@ dependencies = [ [[package]] name = "percent-encoding" -version = "2.3.0" +version = "2.3.1" source = "registry+https://github.com/rust-lang/crates.io-index" -checksum = "9b2a4787296e9989611394c33f193f676704af1686e70b8f8033ab5ba9a35a94" +checksum = "e3148f5046208a5d56bcfc03053e3ca6334e51da8dfb19b6cdc8b306fae3283e" [[package]] name = "pest" @@ -4041,7 +4045,7 @@ dependencies = [ "crc32fast", "fdeflate", "flate2", - "miniz_oxide", + "miniz_oxide 0.7.1", ] [[package]] @@ -4791,9 +4795,9 @@ dependencies = [ [[package]] name = "serde" -version = "1.0.197" +version = "1.0.210" source = "registry+https://github.com/rust-lang/crates.io-index" -checksum = "3fb1c873e1b9b056a4dc4c0c198b24c3ffa059243875552b2bd0933b1aee4ce2" +checksum = "c8e3592472072e6e22e0a54d5904d9febf8508f65fb8552499a1abc7d1078c3a" dependencies = [ "serde_derive", ] @@ -4809,18 +4813,18 @@ dependencies = [ [[package]] name = "serde_bytes" -version = "0.11.12" +version = "0.11.15" source = "registry+https://github.com/rust-lang/crates.io-index" -checksum = "ab33ec92f677585af6d88c65593ae2375adde54efdbf16d597f2cbc7a6d368ff" +checksum = "387cc504cb06bb40a96c8e04e951fe01854cf6bc921053c954e4a606d9675c6a" dependencies = [ "serde", ] [[package]] name = "serde_derive" -version = "1.0.197" +version = "1.0.210" source = "registry+https://github.com/rust-lang/crates.io-index" -checksum = "7eb0b34b42edc17f6b7cac84a52a1c5f0e1bb2227e997ca9011ea3dd34e8610b" +checksum = "243902eda00fad750862fc144cea25caca5e20d615af0a81bee94ca738f1df1f" dependencies = [ "proc-macro2", "quote", @@ -4840,11 +4844,12 @@ dependencies = [ [[package]] name = "serde_json" -version = "1.0.108" +version = "1.0.128" source = "registry+https://github.com/rust-lang/crates.io-index" -checksum = "3d1c7e3eac408d115102c4c24ad393e0821bb3a5df4d506a80f85f7a742a526b" +checksum = "6ff5456707a1de34e7e37f2a6fd3d3f808c318259cbd01ab6377795054b483d8" dependencies = [ "itoa 1.0.9", + "memchr", "ryu", "serde", ] @@ -5091,7 +5096,7 @@ dependencies = [ "aes", "arrayref", "blake2 0.8.1", - "bs58 0.5.1", + "bs58", "byteorder", "chacha", "ctr", @@ -5746,18 +5751,18 @@ checksum = "8eaa81235c7058867fa8c0e7314f33dcce9c215f535d1913822a2b3f5e289f3c" [[package]] name = "thiserror" -version = "1.0.58" +version = "1.0.63" source = "registry+https://github.com/rust-lang/crates.io-index" -checksum = "03468839009160513471e86a034bb2c5c0e4baae3b43f79ffc55c4a5427b3297" +checksum = "c0342370b38b6a11b6cc11d6a805569958d54cfa061a29969c3b5ce2ea405724" dependencies = [ "thiserror-impl", ] [[package]] name = "thiserror-impl" -version = "1.0.58" +version = "1.0.63" source = "registry+https://github.com/rust-lang/crates.io-index" -checksum = "c61f3ba182994efc43764a46c018c347bc492c79f024e705f46567b418f6d4f7" +checksum = "a4558b58466b9ad7ca0f102865eccc95938dca1a74a856f2b57b6629050da261" dependencies = [ "proc-macro2", "quote", @@ -6150,9 +6155,9 @@ checksum = "8ecb6da28b8a351d773b68d5825ac39017e680750f980f3a1a85cd8dd28a47c1" [[package]] name = "url" -version = "2.4.1" +version = "2.5.2" source = "registry+https://github.com/rust-lang/crates.io-index" -checksum = "143b538f18257fac9cad154828a57c6bf5157e1aa604d4816b5995bf6de87ae5" +checksum = "22784dbdf76fdde8af1aeda5622b546b422b6fc585325248a2bf9f5e41e94d6c" dependencies = [ "form_urlencoded", "idna", @@ -6172,6 +6177,30 @@ version = "0.2.1" source = "registry+https://github.com/rust-lang/crates.io-index" checksum = "711b9620af191e0cdc7468a8d14e709c3dcdb115b36f838e601583af800a370a" +[[package]] +name = "utoipa" +version = "4.2.3" +source = "registry+https://github.com/rust-lang/crates.io-index" +checksum = "c5afb1a60e207dca502682537fefcfd9921e71d0b83e9576060f09abc6efab23" +dependencies = [ + "indexmap 2.0.0", + "serde", + "serde_json", + "utoipa-gen", +] + +[[package]] +name = "utoipa-gen" +version = "4.3.0" +source = "registry+https://github.com/rust-lang/crates.io-index" +checksum = "7bf0e16c02bc4bf5322ab65f10ab1149bdbcaa782cba66dc7057370a3f8190be" +dependencies = [ + "proc-macro-error", + "proc-macro2", + "quote", + "syn 2.0.55", +] + [[package]] name = "uuid" version = "0.8.2" diff --git a/nym-wallet/src-tauri/src/operations/signatures/sign.rs b/nym-wallet/src-tauri/src/operations/signatures/sign.rs index c494bc5b4f..59da5cae36 100644 --- a/nym-wallet/src-tauri/src/operations/signatures/sign.rs +++ b/nym-wallet/src-tauri/src/operations/signatures/sign.rs @@ -131,8 +131,5 @@ pub async fn verify( let message_as_bytes = message.into_bytes(); Ok(verifying_key .verify(&message_as_bytes, &signature) - .map_err(|e| { - log::error!(">>> Verification failed, wrong signature"); - e - })?) + .inspect_err(|_| log::error!(">>> Verification failed, wrong signature"))?) } From fb0b9da14fb3eca59799474db1c7cb49d8e1bc65 Mon Sep 17 00:00:00 2001 From: =?UTF-8?q?J=C4=99drzej=20Stuczy=C5=84ski?= Date: Fri, 30 Aug 2024 17:35:57 +0100 Subject: [PATCH 64/93] revamped ticketbook serialisation and exposed additional cli methods --- Cargo.lock | 3 + .../ecash/import_coin_index_signatures.rs | 16 ++ .../commands/{ => ecash}/import_credential.rs | 4 +- .../import_expiration_date_signatures.rs | 16 ++ .../ecash/import_master_verification_key.rs | 16 ++ clients/native/src/commands/ecash/mod.rs | 59 ++++++ .../commands/{ => ecash}/show_ticketbooks.rs | 0 clients/native/src/commands/mod.rs | 15 +- .../ecash/import_coin_index_signatures.rs | 16 ++ .../commands/{ => ecash}/import_credential.rs | 6 +- .../import_expiration_date_signatures.rs | 16 ++ .../ecash/import_master_verification_key.rs | 16 ++ clients/socks5/src/commands/ecash/mod.rs | 59 ++++++ .../commands/{ => ecash}/show_ticketbooks.rs | 4 +- clients/socks5/src/commands/mod.rs | 15 +- common/bandwidth-controller/src/utils.rs | 32 +++- .../client_import_coin_index_signatures.rs | 68 +++++++ .../cli_helpers/client_import_credential.rs | 35 +++- ...lient_import_expiration_date_signatures.rs | 68 +++++++ .../client_import_master_verification_key.rs | 68 +++++++ common/client-core/src/cli_helpers/mod.rs | 3 + common/commands/Cargo.toml | 3 +- .../commands/src/coconut/issue_ticket_book.rs | 56 ------ .../src/ecash/import_coin_index_signatures.rs | 76 ++++++++ .../import_expiration_date_signatures.rs | 76 ++++++++ .../ecash/import_master_verification_key.rs | 76 ++++++++ .../{coconut => ecash}/import_ticket_book.rs | 53 ++++-- .../commands/src/ecash/issue_ticket_book.rs | 170 ++++++++++++++++++ common/commands/src/{coconut => ecash}/mod.rs | 6 + .../{coconut => ecash}/recover_ticket_book.rs | 0 common/commands/src/lib.rs | 2 +- ...0002_signatures_serialisation_revision.sql | 13 ++ .../credential-storage/src/backends/memory.rs | 25 ++- .../credential-storage/src/backends/sqlite.rs | 49 +++-- .../src/ephemeral_storage.rs | 20 +-- common/credential-storage/src/models.rs | 15 ++ .../src/persistent_storage/helpers.rs | 54 ------ .../src/persistent_storage/legacy_helpers.rs | 44 +++++ .../src/persistent_storage/mod.rs | 75 +++++--- common/credential-storage/src/storage.rs | 14 +- common/credentials-interface/src/lib.rs | 2 +- common/credentials/Cargo.toml | 1 + .../src/ecash/bandwidth/importable.rs | 118 ++++++++++++ .../src/ecash/bandwidth/issuance.rs | 9 +- .../credentials/src/ecash/bandwidth/issued.rs | 5 + common/credentials/src/ecash/bandwidth/mod.rs | 1 + .../src/ecash/bandwidth/serialiser/keys.rs | 35 ++++ .../{serialiser.rs => serialiser/mod.rs} | 18 +- .../ecash/bandwidth/serialiser/signatures.rs | 66 +++++++ common/credentials/src/ecash/utils.rs | 2 +- common/credentials/src/error.rs | 5 +- common/credentials/src/lib.rs | 5 + common/nym-id/src/error.rs | 25 ++- common/nym-id/src/import_credential.rs | 49 ----- .../nym-id/src/import_credential/helpers.rs | 147 +++++++++++++++ common/nym-id/src/import_credential/mod.rs | 119 ++++++++++++ common/nym-id/src/lib.rs | 5 +- .../src/scheme/aggregation.rs | 5 +- .../src/scheme/keygen.rs | 15 ++ .../src/scheme/withdrawal.rs | 3 +- common/serde-helpers/Cargo.toml | 3 +- common/serde-helpers/src/lib.rs | 38 ++++ contracts/Cargo.lock | 18 +- envs/sandbox.env | 9 +- nym-api/nym-api-requests/Cargo.toml | 2 +- nym-api/nym-api-requests/src/helpers.rs | 41 +---- nym-api/src/ecash/comm.rs | 4 +- nym-wallet/Cargo.lock | 1 + .../cli/ecash/import_coin_index_signatures.rs | 16 ++ .../src/cli/{ => ecash}/import_credential.rs | 6 +- .../import_expiration_date_signatures.rs | 16 ++ .../ecash/import_master_verification_key.rs | 16 ++ .../authenticator/src/cli/ecash/mod.rs | 59 ++++++ .../src/cli/ecash/show_ticketbooks.rs | 32 ++++ .../authenticator/src/cli/mod.rs | 10 +- .../cli/ecash/import_coin_index_signatures.rs | 17 ++ .../src/cli/{ => ecash}/import_credential.rs | 6 +- .../import_expiration_date_signatures.rs | 16 ++ .../ecash/import_master_verification_key.rs | 16 ++ .../ip-packet-router/src/cli/ecash/mod.rs | 61 +++++++ .../src/cli/{ => ecash}/show_ticketbooks.rs | 4 +- .../ip-packet-router/src/cli/mod.rs | 13 +- .../cli/ecash/import_coin_index_signatures.rs | 16 ++ .../src/cli/{ => ecash}/import_credential.rs | 6 +- .../import_expiration_date_signatures.rs | 16 ++ .../ecash/import_master_verification_key.rs | 16 ++ .../network-requester/src/cli/ecash/mod.rs | 59 ++++++ .../src/cli/{ => ecash}/show_ticketbooks.rs | 0 .../network-requester/src/cli/mod.rs | 17 +- tools/nym-cli/src/coconut/mod.rs | 24 ++- tools/nym-cli/src/main.rs | 2 +- .../src/commands/import_credential.rs | 4 +- 92 files changed, 2158 insertions(+), 403 deletions(-) create mode 100644 clients/native/src/commands/ecash/import_coin_index_signatures.rs rename clients/native/src/commands/{ => ecash}/import_credential.rs (76%) create mode 100644 clients/native/src/commands/ecash/import_expiration_date_signatures.rs create mode 100644 clients/native/src/commands/ecash/import_master_verification_key.rs create mode 100644 clients/native/src/commands/ecash/mod.rs rename clients/native/src/commands/{ => ecash}/show_ticketbooks.rs (100%) create mode 100644 clients/socks5/src/commands/ecash/import_coin_index_signatures.rs rename clients/socks5/src/commands/{ => ecash}/import_credential.rs (68%) create mode 100644 clients/socks5/src/commands/ecash/import_expiration_date_signatures.rs create mode 100644 clients/socks5/src/commands/ecash/import_master_verification_key.rs create mode 100644 clients/socks5/src/commands/ecash/mod.rs rename clients/socks5/src/commands/{ => ecash}/show_ticketbooks.rs (89%) create mode 100644 common/client-core/src/cli_helpers/client_import_coin_index_signatures.rs create mode 100644 common/client-core/src/cli_helpers/client_import_expiration_date_signatures.rs create mode 100644 common/client-core/src/cli_helpers/client_import_master_verification_key.rs delete mode 100644 common/commands/src/coconut/issue_ticket_book.rs create mode 100644 common/commands/src/ecash/import_coin_index_signatures.rs create mode 100644 common/commands/src/ecash/import_expiration_date_signatures.rs create mode 100644 common/commands/src/ecash/import_master_verification_key.rs rename common/commands/src/{coconut => ecash}/import_ticket_book.rs (51%) create mode 100644 common/commands/src/ecash/issue_ticket_book.rs rename common/commands/src/{coconut => ecash}/mod.rs (63%) rename common/commands/src/{coconut => ecash}/recover_ticket_book.rs (100%) create mode 100644 common/credential-storage/migrations/20241104120002_signatures_serialisation_revision.sql delete mode 100644 common/credential-storage/src/persistent_storage/helpers.rs create mode 100644 common/credential-storage/src/persistent_storage/legacy_helpers.rs create mode 100644 common/credentials/src/ecash/bandwidth/importable.rs create mode 100644 common/credentials/src/ecash/bandwidth/serialiser/keys.rs rename common/credentials/src/ecash/bandwidth/{serialiser.rs => serialiser/mod.rs} (83%) create mode 100644 common/credentials/src/ecash/bandwidth/serialiser/signatures.rs delete mode 100644 common/nym-id/src/import_credential.rs create mode 100644 common/nym-id/src/import_credential/helpers.rs create mode 100644 common/nym-id/src/import_credential/mod.rs create mode 100644 service-providers/authenticator/src/cli/ecash/import_coin_index_signatures.rs rename service-providers/authenticator/src/cli/{ => ecash}/import_credential.rs (69%) create mode 100644 service-providers/authenticator/src/cli/ecash/import_expiration_date_signatures.rs create mode 100644 service-providers/authenticator/src/cli/ecash/import_master_verification_key.rs create mode 100644 service-providers/authenticator/src/cli/ecash/mod.rs create mode 100644 service-providers/authenticator/src/cli/ecash/show_ticketbooks.rs create mode 100644 service-providers/ip-packet-router/src/cli/ecash/import_coin_index_signatures.rs rename service-providers/ip-packet-router/src/cli/{ => ecash}/import_credential.rs (69%) create mode 100644 service-providers/ip-packet-router/src/cli/ecash/import_expiration_date_signatures.rs create mode 100644 service-providers/ip-packet-router/src/cli/ecash/import_master_verification_key.rs create mode 100644 service-providers/ip-packet-router/src/cli/ecash/mod.rs rename service-providers/ip-packet-router/src/cli/{ => ecash}/show_ticketbooks.rs (89%) create mode 100644 service-providers/network-requester/src/cli/ecash/import_coin_index_signatures.rs rename service-providers/network-requester/src/cli/{ => ecash}/import_credential.rs (69%) create mode 100644 service-providers/network-requester/src/cli/ecash/import_expiration_date_signatures.rs create mode 100644 service-providers/network-requester/src/cli/ecash/import_master_verification_key.rs create mode 100644 service-providers/network-requester/src/cli/ecash/mod.rs rename service-providers/network-requester/src/cli/{ => ecash}/show_ticketbooks.rs (100%) diff --git a/Cargo.lock b/Cargo.lock index 4efaa347bd..e8565e92f2 100644 --- a/Cargo.lock +++ b/Cargo.lock @@ -4412,6 +4412,7 @@ dependencies = [ "serde", "serde_json", "tap", + "tempfile", "thiserror", "time", "tokio", @@ -4754,6 +4755,7 @@ dependencies = [ "nym-ecash-contract-common", "nym-ecash-time", "nym-network-defaults", + "nym-serde-helpers", "nym-validator-client", "rand", "serde", @@ -5670,6 +5672,7 @@ dependencies = [ "base64 0.22.1", "bs58", "serde", + "time", ] [[package]] diff --git a/clients/native/src/commands/ecash/import_coin_index_signatures.rs b/clients/native/src/commands/ecash/import_coin_index_signatures.rs new file mode 100644 index 0000000000..bb232771b5 --- /dev/null +++ b/clients/native/src/commands/ecash/import_coin_index_signatures.rs @@ -0,0 +1,16 @@ +// Copyright 2024 - Nym Technologies SA +// SPDX-License-Identifier: Apache-2.0 + +use crate::commands::CliNativeClient; +use crate::error::ClientError; +use nym_client_core::cli_helpers::client_import_coin_index_signatures::{ + import_coin_index_signatures, CommonClientImportCoinIndexSignaturesArgs, +}; + +pub(crate) async fn execute( + args: CommonClientImportCoinIndexSignaturesArgs, +) -> Result<(), ClientError> { + import_coin_index_signatures::(args).await?; + println!("successfully imported coin index signatures!"); + Ok(()) +} diff --git a/clients/native/src/commands/import_credential.rs b/clients/native/src/commands/ecash/import_credential.rs similarity index 76% rename from clients/native/src/commands/import_credential.rs rename to clients/native/src/commands/ecash/import_credential.rs index 2e917ed226..a1951375cc 100644 --- a/clients/native/src/commands/import_credential.rs +++ b/clients/native/src/commands/ecash/import_credential.rs @@ -4,10 +4,10 @@ use crate::commands::CliNativeClient; use crate::error::ClientError; use nym_client_core::cli_helpers::client_import_credential::{ - import_credential, CommonClientImportCredentialArgs, + import_credential, CommonClientImportTicketBookArgs, }; -pub(crate) async fn execute(args: CommonClientImportCredentialArgs) -> Result<(), ClientError> { +pub(crate) async fn execute(args: CommonClientImportTicketBookArgs) -> Result<(), ClientError> { import_credential::(args).await?; println!("successfully imported credential!"); Ok(()) diff --git a/clients/native/src/commands/ecash/import_expiration_date_signatures.rs b/clients/native/src/commands/ecash/import_expiration_date_signatures.rs new file mode 100644 index 0000000000..dc562f664a --- /dev/null +++ b/clients/native/src/commands/ecash/import_expiration_date_signatures.rs @@ -0,0 +1,16 @@ +// Copyright 2024 - Nym Technologies SA +// SPDX-License-Identifier: Apache-2.0 + +use crate::commands::CliNativeClient; +use crate::error::ClientError; +use nym_client_core::cli_helpers::client_import_expiration_date_signatures::{ + import_expiration_date_signatures, CommonClientImportExpirationDateSignaturesArgs, +}; + +pub(crate) async fn execute( + args: CommonClientImportExpirationDateSignaturesArgs, +) -> Result<(), ClientError> { + import_expiration_date_signatures::(args).await?; + println!("successfully imported expiration date signatures!"); + Ok(()) +} diff --git a/clients/native/src/commands/ecash/import_master_verification_key.rs b/clients/native/src/commands/ecash/import_master_verification_key.rs new file mode 100644 index 0000000000..715efe00e0 --- /dev/null +++ b/clients/native/src/commands/ecash/import_master_verification_key.rs @@ -0,0 +1,16 @@ +// Copyright 2024 - Nym Technologies SA +// SPDX-License-Identifier: Apache-2.0 + +use crate::commands::CliNativeClient; +use crate::error::ClientError; +use nym_client_core::cli_helpers::client_import_master_verification_key::{ + import_master_verification_key, CommonClientImportMasterVerificationKeyArgs, +}; + +pub(crate) async fn execute( + args: CommonClientImportMasterVerificationKeyArgs, +) -> Result<(), ClientError> { + import_master_verification_key::(args).await?; + println!("successfully imported master verification key!"); + Ok(()) +} diff --git a/clients/native/src/commands/ecash/mod.rs b/clients/native/src/commands/ecash/mod.rs new file mode 100644 index 0000000000..c1bc47af1a --- /dev/null +++ b/clients/native/src/commands/ecash/mod.rs @@ -0,0 +1,59 @@ +// Copyright 2024 - Nym Technologies SA +// SPDX-License-Identifier: Apache-2.0 + +use clap::{Args, Subcommand}; +use nym_client_core::cli_helpers::client_import_coin_index_signatures::CommonClientImportCoinIndexSignaturesArgs; +use nym_client_core::cli_helpers::client_import_credential::CommonClientImportTicketBookArgs; +use nym_client_core::cli_helpers::client_import_expiration_date_signatures::CommonClientImportExpirationDateSignaturesArgs; +use nym_client_core::cli_helpers::client_import_master_verification_key::CommonClientImportMasterVerificationKeyArgs; +use std::error::Error; + +pub(crate) mod import_coin_index_signatures; +pub(crate) mod import_credential; +pub(crate) mod import_expiration_date_signatures; +pub(crate) mod import_master_verification_key; +pub(crate) mod show_ticketbooks; + +#[derive(Args)] +#[clap(args_conflicts_with_subcommands = true, subcommand_required = true)] +pub struct Ecash { + #[clap(subcommand)] + pub command: EcashCommands, +} + +impl Ecash { + pub async fn execute(self) -> Result<(), Box> { + match self.command { + EcashCommands::ShowTicketBooks(args) => show_ticketbooks::execute(args).await?, + EcashCommands::ImportTicketBook(args) => import_credential::execute(args).await?, + EcashCommands::ImportCoinIndexSignatures(args) => { + import_coin_index_signatures::execute(args).await? + } + EcashCommands::ImportExpirationDateSignatures(args) => { + import_expiration_date_signatures::execute(args).await? + } + EcashCommands::ImportMasterVerificationKey(args) => { + import_master_verification_key::execute(args).await? + } + } + Ok(()) + } +} + +#[derive(Subcommand)] +pub enum EcashCommands { + /// Display information associated with the imported ticketbooks, + ShowTicketBooks(show_ticketbooks::Args), + + /// Import a pre-generated ticketbook + ImportTicketBook(CommonClientImportTicketBookArgs), + + /// Import coin index signatures needed for ticketbooks + ImportCoinIndexSignatures(CommonClientImportCoinIndexSignaturesArgs), + + /// Import expiration date signatures needed for ticketbooks + ImportExpirationDateSignatures(CommonClientImportExpirationDateSignaturesArgs), + + /// Import master verification key needed for ticketbooks + ImportMasterVerificationKey(CommonClientImportMasterVerificationKeyArgs), +} diff --git a/clients/native/src/commands/show_ticketbooks.rs b/clients/native/src/commands/ecash/show_ticketbooks.rs similarity index 100% rename from clients/native/src/commands/show_ticketbooks.rs rename to clients/native/src/commands/ecash/show_ticketbooks.rs diff --git a/clients/native/src/commands/mod.rs b/clients/native/src/commands/mod.rs index 31aa4ae8ec..6c5e8a9497 100644 --- a/clients/native/src/commands/mod.rs +++ b/clients/native/src/commands/mod.rs @@ -6,13 +6,13 @@ use crate::client::config::old_config_v1_1_20::ConfigV1_1_20; use crate::client::config::old_config_v1_1_20_2::ConfigV1_1_20_2; use crate::client::config::old_config_v1_1_33::ConfigV1_1_33; use crate::client::config::{BaseClientConfig, Config}; +use crate::commands::ecash::Ecash; use crate::error::ClientError; use clap::CommandFactory; use clap::{Parser, Subcommand}; use log::{error, info}; use nym_bin_common::bin_info; use nym_bin_common::completions::{fig_generate, ArgShell}; -use nym_client_core::cli_helpers::client_import_credential::CommonClientImportCredentialArgs; use nym_client_core::cli_helpers::CliClient; use nym_client_core::client::base_client::storage::migration_helpers::v1_1_33; use nym_config::OptionalSet; @@ -22,11 +22,10 @@ use std::sync::OnceLock; mod add_gateway; pub(crate) mod build_info; -pub(crate) mod import_credential; +pub(crate) mod ecash; pub(crate) mod init; mod list_gateways; pub(crate) mod run; -mod show_ticketbooks; mod switch_gateway; pub(crate) struct CliNativeClient; @@ -73,8 +72,8 @@ pub(crate) enum Commands { /// Run the Nym client with provided configuration client optionally overriding set parameters Run(run::Run), - /// Import a pre-generated credential - ImportCredential(CommonClientImportCredentialArgs), + /// Ecash-related functionalities + Ecash(Ecash), /// List all registered with gateways ListGateways(list_gateways::Args), @@ -85,9 +84,6 @@ pub(crate) enum Commands { /// Change the currently active gateway. Note that you must have already registered with the new gateway! SwitchGateway(switch_gateway::Args), - /// Display information associated with the imported ticketbooks, - ShowTicketbooks(show_ticketbooks::Args), - /// Show build information of this binary BuildInfo(build_info::BuildInfo), @@ -116,11 +112,10 @@ pub(crate) async fn execute(args: Cli) -> Result<(), Box init::execute(m).await?, Commands::Run(m) => run::execute(m).await?, - Commands::ImportCredential(m) => import_credential::execute(m).await?, + Commands::Ecash(ecash) => ecash.execute().await?, Commands::ListGateways(args) => list_gateways::execute(args).await?, Commands::AddGateway(args) => add_gateway::execute(args).await?, Commands::SwitchGateway(args) => switch_gateway::execute(args).await?, - Commands::ShowTicketbooks(args) => show_ticketbooks::execute(args).await?, Commands::BuildInfo(m) => build_info::execute(m), Commands::Completions(s) => s.generate(&mut Cli::command(), bin_name), Commands::GenerateFigSpec => fig_generate(&mut Cli::command(), bin_name), diff --git a/clients/socks5/src/commands/ecash/import_coin_index_signatures.rs b/clients/socks5/src/commands/ecash/import_coin_index_signatures.rs new file mode 100644 index 0000000000..39cade10c7 --- /dev/null +++ b/clients/socks5/src/commands/ecash/import_coin_index_signatures.rs @@ -0,0 +1,16 @@ +// Copyright 2024 - Nym Technologies SA +// SPDX-License-Identifier: Apache-2.0 + +use crate::commands::CliSocks5Client; +use crate::error::Socks5ClientError; +use nym_client_core::cli_helpers::client_import_coin_index_signatures::{ + import_coin_index_signatures, CommonClientImportCoinIndexSignaturesArgs, +}; + +pub(crate) async fn execute( + args: CommonClientImportCoinIndexSignaturesArgs, +) -> Result<(), Socks5ClientError> { + import_coin_index_signatures::(args).await?; + println!("successfully imported coin index signatures!"); + Ok(()) +} diff --git a/clients/socks5/src/commands/import_credential.rs b/clients/socks5/src/commands/ecash/import_credential.rs similarity index 68% rename from clients/socks5/src/commands/import_credential.rs rename to clients/socks5/src/commands/ecash/import_credential.rs index d8f3d27bc9..e8f4508b83 100644 --- a/clients/socks5/src/commands/import_credential.rs +++ b/clients/socks5/src/commands/ecash/import_credential.rs @@ -4,12 +4,10 @@ use crate::commands::CliSocks5Client; use crate::error::Socks5ClientError; use nym_client_core::cli_helpers::client_import_credential::{ - import_credential, CommonClientImportCredentialArgs, + import_credential, CommonClientImportTicketBookArgs, }; -pub(crate) async fn execute( - args: CommonClientImportCredentialArgs, -) -> Result<(), Socks5ClientError> { +pub async fn execute(args: CommonClientImportTicketBookArgs) -> Result<(), Socks5ClientError> { import_credential::(args).await?; println!("successfully imported credential!"); Ok(()) diff --git a/clients/socks5/src/commands/ecash/import_expiration_date_signatures.rs b/clients/socks5/src/commands/ecash/import_expiration_date_signatures.rs new file mode 100644 index 0000000000..7cc9c1042f --- /dev/null +++ b/clients/socks5/src/commands/ecash/import_expiration_date_signatures.rs @@ -0,0 +1,16 @@ +// Copyright 2024 - Nym Technologies SA +// SPDX-License-Identifier: Apache-2.0 + +use crate::commands::CliSocks5Client; +use crate::error::Socks5ClientError; +use nym_client_core::cli_helpers::client_import_expiration_date_signatures::{ + import_expiration_date_signatures, CommonClientImportExpirationDateSignaturesArgs, +}; + +pub(crate) async fn execute( + args: CommonClientImportExpirationDateSignaturesArgs, +) -> Result<(), Socks5ClientError> { + import_expiration_date_signatures::(args).await?; + println!("successfully imported expiration date signatures!"); + Ok(()) +} diff --git a/clients/socks5/src/commands/ecash/import_master_verification_key.rs b/clients/socks5/src/commands/ecash/import_master_verification_key.rs new file mode 100644 index 0000000000..51dc108a59 --- /dev/null +++ b/clients/socks5/src/commands/ecash/import_master_verification_key.rs @@ -0,0 +1,16 @@ +// Copyright 2024 - Nym Technologies SA +// SPDX-License-Identifier: Apache-2.0 + +use crate::commands::CliSocks5Client; +use crate::error::Socks5ClientError; +use nym_client_core::cli_helpers::client_import_master_verification_key::{ + import_master_verification_key, CommonClientImportMasterVerificationKeyArgs, +}; + +pub(crate) async fn execute( + args: CommonClientImportMasterVerificationKeyArgs, +) -> Result<(), Socks5ClientError> { + import_master_verification_key::(args).await?; + println!("successfully imported master verification key!"); + Ok(()) +} diff --git a/clients/socks5/src/commands/ecash/mod.rs b/clients/socks5/src/commands/ecash/mod.rs new file mode 100644 index 0000000000..c1bc47af1a --- /dev/null +++ b/clients/socks5/src/commands/ecash/mod.rs @@ -0,0 +1,59 @@ +// Copyright 2024 - Nym Technologies SA +// SPDX-License-Identifier: Apache-2.0 + +use clap::{Args, Subcommand}; +use nym_client_core::cli_helpers::client_import_coin_index_signatures::CommonClientImportCoinIndexSignaturesArgs; +use nym_client_core::cli_helpers::client_import_credential::CommonClientImportTicketBookArgs; +use nym_client_core::cli_helpers::client_import_expiration_date_signatures::CommonClientImportExpirationDateSignaturesArgs; +use nym_client_core::cli_helpers::client_import_master_verification_key::CommonClientImportMasterVerificationKeyArgs; +use std::error::Error; + +pub(crate) mod import_coin_index_signatures; +pub(crate) mod import_credential; +pub(crate) mod import_expiration_date_signatures; +pub(crate) mod import_master_verification_key; +pub(crate) mod show_ticketbooks; + +#[derive(Args)] +#[clap(args_conflicts_with_subcommands = true, subcommand_required = true)] +pub struct Ecash { + #[clap(subcommand)] + pub command: EcashCommands, +} + +impl Ecash { + pub async fn execute(self) -> Result<(), Box> { + match self.command { + EcashCommands::ShowTicketBooks(args) => show_ticketbooks::execute(args).await?, + EcashCommands::ImportTicketBook(args) => import_credential::execute(args).await?, + EcashCommands::ImportCoinIndexSignatures(args) => { + import_coin_index_signatures::execute(args).await? + } + EcashCommands::ImportExpirationDateSignatures(args) => { + import_expiration_date_signatures::execute(args).await? + } + EcashCommands::ImportMasterVerificationKey(args) => { + import_master_verification_key::execute(args).await? + } + } + Ok(()) + } +} + +#[derive(Subcommand)] +pub enum EcashCommands { + /// Display information associated with the imported ticketbooks, + ShowTicketBooks(show_ticketbooks::Args), + + /// Import a pre-generated ticketbook + ImportTicketBook(CommonClientImportTicketBookArgs), + + /// Import coin index signatures needed for ticketbooks + ImportCoinIndexSignatures(CommonClientImportCoinIndexSignaturesArgs), + + /// Import expiration date signatures needed for ticketbooks + ImportExpirationDateSignatures(CommonClientImportExpirationDateSignaturesArgs), + + /// Import master verification key needed for ticketbooks + ImportMasterVerificationKey(CommonClientImportMasterVerificationKeyArgs), +} diff --git a/clients/socks5/src/commands/show_ticketbooks.rs b/clients/socks5/src/commands/ecash/show_ticketbooks.rs similarity index 89% rename from clients/socks5/src/commands/show_ticketbooks.rs rename to clients/socks5/src/commands/ecash/show_ticketbooks.rs index 41a37ef6eb..1271c0c01f 100644 --- a/clients/socks5/src/commands/show_ticketbooks.rs +++ b/clients/socks5/src/commands/ecash/show_ticketbooks.rs @@ -9,7 +9,7 @@ use nym_client_core::cli_helpers::client_show_ticketbooks::{ }; #[derive(clap::Args)] -pub(crate) struct Args { +pub struct Args { #[command(flatten)] common_args: CommonShowTicketbooksArgs, @@ -23,7 +23,7 @@ impl AsRef for Args { } } -pub(crate) async fn execute(args: Args) -> Result<(), Socks5ClientError> { +pub async fn execute(args: Args) -> Result<(), Socks5ClientError> { let output = args.output; let res = show_ticketbooks::(args).await?; diff --git a/clients/socks5/src/commands/mod.rs b/clients/socks5/src/commands/mod.rs index 34f0738a12..2c471ec3fa 100644 --- a/clients/socks5/src/commands/mod.rs +++ b/clients/socks5/src/commands/mod.rs @@ -1,6 +1,7 @@ // Copyright 2021-2023 - Nym Technologies SA // SPDX-License-Identifier: Apache-2.0 +use crate::commands::ecash::Ecash; use crate::config::old_config_v1_1_13::OldConfigV1_1_13; use crate::config::old_config_v1_1_20::ConfigV1_1_20; use crate::config::old_config_v1_1_20_2::ConfigV1_1_20_2; @@ -13,7 +14,6 @@ use clap::{Parser, Subcommand}; use log::{error, info}; use nym_bin_common::bin_info; use nym_bin_common::completions::{fig_generate, ArgShell}; -use nym_client_core::cli_helpers::client_import_credential::CommonClientImportCredentialArgs; use nym_client_core::cli_helpers::CliClient; use nym_client_core::client::base_client::storage::migration_helpers::v1_1_33; use nym_client_core::client::topology_control::geo_aware_provider::CountryGroup; @@ -26,11 +26,10 @@ use std::sync::OnceLock; mod add_gateway; pub(crate) mod build_info; -mod import_credential; +pub mod ecash; pub mod init; mod list_gateways; pub(crate) mod run; -mod show_ticketbooks; mod switch_gateway; pub(crate) struct CliSocks5Client; @@ -77,8 +76,8 @@ pub(crate) enum Commands { /// Run the Nym client with provided configuration client optionally overriding set parameters Run(run::Run), - /// Import a pre-generated credential - ImportCredential(CommonClientImportCredentialArgs), + /// Ecash-related functionalities + Ecash(Ecash), /// List all registered with gateways ListGateways(list_gateways::Args), @@ -89,9 +88,6 @@ pub(crate) enum Commands { /// Change the currently active gateway. Note that you must have already registered with the new gateway! SwitchGateway(switch_gateway::Args), - /// Display information associated with the imported ticketbooks, - ShowTicketbooks(show_ticketbooks::Args), - /// Show build information of this binary BuildInfo(build_info::BuildInfo), @@ -123,11 +119,10 @@ pub(crate) async fn execute(args: Cli) -> Result<(), Box init::execute(m).await?, Commands::Run(m) => run::execute(m).await?, - Commands::ImportCredential(m) => import_credential::execute(m).await?, + Commands::Ecash(ecash) => ecash.execute().await?, Commands::ListGateways(args) => list_gateways::execute(args).await?, Commands::AddGateway(args) => add_gateway::execute(args).await?, Commands::SwitchGateway(args) => switch_gateway::execute(args).await?, - Commands::ShowTicketbooks(args) => show_ticketbooks::execute(args).await?, Commands::BuildInfo(m) => build_info::execute(m), Commands::Completions(s) => s.generate(&mut Cli::command(), bin_name), Commands::GenerateFigSpec => fig_generate(&mut Cli::command(), bin_name), diff --git a/common/bandwidth-controller/src/utils.rs b/common/bandwidth-controller/src/utils.rs index 0d2427b2f8..9c15f5924b 100644 --- a/common/bandwidth-controller/src/utils.rs +++ b/common/bandwidth-controller/src/utils.rs @@ -4,6 +4,10 @@ use crate::error::BandwidthControllerError; use log::warn; use nym_credential_storage::storage::Storage; +use nym_credentials::ecash::bandwidth::serialiser::keys::EpochVerificationKey; +use nym_credentials::ecash::bandwidth::serialiser::signatures::{ + AggregatedCoinIndicesSignatures, AggregatedExpirationDateSignatures, +}; use nym_credentials_interface::{ AnnotatedCoinIndexSignature, AnnotatedExpirationDateSignature, VerificationKeyAuth, }; @@ -94,13 +98,18 @@ where .await? .key; + let full = EpochVerificationKey { + epoch_id, + key: master_vk, + }; + // store the retrieved key storage - .insert_master_verification_key(epoch_id, &master_vk) + .insert_master_verification_key(&full) .await .map_err(BandwidthControllerError::credential_storage_error)?; - Ok(master_vk) + Ok(full.key) } pub(crate) async fn get_coin_index_signatures( @@ -132,13 +141,18 @@ where .await? .signatures; + let aggregated = AggregatedCoinIndicesSignatures { + epoch_id, + signatures: index_sigs, + }; + // store the retrieved key storage - .insert_coin_index_signatures(epoch_id, &index_sigs) + .insert_coin_index_signatures(&aggregated) .await .map_err(BandwidthControllerError::credential_storage_error)?; - Ok(index_sigs) + Ok(aggregated.signatures) } pub(crate) async fn get_expiration_date_signatures( @@ -171,11 +185,17 @@ where .await? .signatures; + let aggregated = AggregatedExpirationDateSignatures { + epoch_id, + expiration_date, + signatures: expiration_sigs, + }; + // store the retrieved key storage - .insert_expiration_date_signatures(epoch_id, expiration_date, &expiration_sigs) + .insert_expiration_date_signatures(&aggregated) .await .map_err(BandwidthControllerError::credential_storage_error)?; - Ok(expiration_sigs) + Ok(aggregated.signatures) } diff --git a/common/client-core/src/cli_helpers/client_import_coin_index_signatures.rs b/common/client-core/src/cli_helpers/client_import_coin_index_signatures.rs new file mode 100644 index 0000000000..889c34ab4b --- /dev/null +++ b/common/client-core/src/cli_helpers/client_import_coin_index_signatures.rs @@ -0,0 +1,68 @@ +// Copyright 2024 - Nym Technologies SA +// SPDX-License-Identifier: Apache-2.0 + +use crate::cli_helpers::{CliClient, CliClientConfig}; +use std::fs; +use std::path::PathBuf; + +#[cfg(feature = "cli")] +fn parse_encoded_signatures_data(raw: &str) -> bs58::decode::Result> { + bs58::decode(raw).into_vec() +} + +#[cfg_attr(feature = "cli", derive(clap::Args))] +#[cfg_attr(feature = "cli", + clap( + group(clap::ArgGroup::new("signatures_data").required(true)), + )) +] +pub struct CommonClientImportCoinIndexSignaturesArgs { + /// Id of client that is going to import the signatures + #[cfg_attr(feature = "cli", clap(long))] + pub id: String, + + /// Config file of the client that is supposed to use the signatures. + #[cfg_attr(feature = "cli", clap(long))] + pub(crate) client_config: PathBuf, + + /// Explicitly provide the encoded signatures data (as base58) + #[cfg_attr(feature = "cli", clap(long, group = "signatures_data", value_parser = parse_encoded_signatures_data))] + pub(crate) signatures_data: Option>, + + /// Specifies the path to file containing binary signatures data + #[cfg_attr(feature = "cli", clap(long, group = "signatures_data"))] + pub(crate) signatures_path: Option, + + // currently hidden as there exists only a single serialization standard + #[cfg_attr(feature = "cli", clap(long, hide = true))] + pub(crate) version: Option, +} + +pub async fn import_coin_index_signatures(args: A) -> Result<(), C::Error> +where + A: Into, + C: CliClient, + C::Error: From + From, +{ + let common_args = args.into(); + let id = &common_args.id; + + let config = C::try_load_current_config(id).await?; + let paths = config.common_paths(); + + let credentials_store = + nym_credential_storage::initialise_persistent_storage(&paths.credentials_database).await; + + let version = common_args.version; + let raw_key = match common_args.signatures_data { + Some(data) => data, + None => { + // SAFETY: one of those arguments must have been set + fs::read(common_args.signatures_path.unwrap())? + } + }; + + nym_id::import_coin_index_signatures(credentials_store, raw_key, version).await?; + + Ok(()) +} diff --git a/common/client-core/src/cli_helpers/client_import_credential.rs b/common/client-core/src/cli_helpers/client_import_credential.rs index 48468771da..77c6dc16f4 100644 --- a/common/client-core/src/cli_helpers/client_import_credential.rs +++ b/common/client-core/src/cli_helpers/client_import_credential.rs @@ -11,9 +11,14 @@ fn parse_encoded_credential_data(raw: &str) -> bs58::decode::Result> { } #[cfg_attr(feature = "cli", derive(clap::Args))] -#[cfg_attr(feature = "cli", clap(group(clap::ArgGroup::new("cred_data").required(true))))] +#[cfg_attr(feature = "cli", + clap( + group(clap::ArgGroup::new("cred_data").required(true)), + group(clap::ArgGroup::new("type").required(true)), + )) +] #[derive(Debug, Clone)] -pub struct CommonClientImportCredentialArgs { +pub struct CommonClientImportTicketBookArgs { /// Id of client that is going to import the credential #[cfg_attr(feature = "cli", clap(long))] pub id: String, @@ -26,6 +31,15 @@ pub struct CommonClientImportCredentialArgs { #[cfg_attr(feature = "cli", clap(long, group = "cred_data"))] pub(crate) credential_path: Option, + /// Specifies whether we're attempting to import a standalone ticketbook (i.e. serialised `IssuedTicketBook`) + #[cfg_attr(feature = "cli", clap(long, group = "type"))] + pub(crate) standalone: bool, + + /// Specifies whether we're attempting to import full ticketboot + /// (i.e. one that **might** contain required global signatures; that is serialised `ImportableTicketBook`) + #[cfg_attr(feature = "cli", clap(long, group = "type"))] + pub(crate) full: bool, + // currently hidden as there exists only a single serialization standard #[cfg_attr(feature = "cli", clap(long, hide = true))] pub(crate) version: Option, @@ -33,7 +47,7 @@ pub struct CommonClientImportCredentialArgs { pub async fn import_credential(args: A) -> Result<(), C::Error> where - A: Into, + A: Into, C: CliClient, C::Error: From + From, { @@ -54,6 +68,19 @@ where } }; - nym_id::import_credential(credentials_store, raw_credential, common_args.version).await?; + if common_args.standalone { + nym_id::import_standalone_ticketbook( + credentials_store, + raw_credential, + common_args.version, + ) + .await?; + } else { + // sanity check; clap should have ensured it + assert!(common_args.full); + nym_id::import_full_ticketbook(credentials_store, raw_credential, common_args.version) + .await?; + } + Ok(()) } diff --git a/common/client-core/src/cli_helpers/client_import_expiration_date_signatures.rs b/common/client-core/src/cli_helpers/client_import_expiration_date_signatures.rs new file mode 100644 index 0000000000..7d0a14513a --- /dev/null +++ b/common/client-core/src/cli_helpers/client_import_expiration_date_signatures.rs @@ -0,0 +1,68 @@ +// Copyright 2024 - Nym Technologies SA +// SPDX-License-Identifier: Apache-2.0 + +use crate::cli_helpers::{CliClient, CliClientConfig}; +use std::fs; +use std::path::PathBuf; + +#[cfg(feature = "cli")] +fn parse_encoded_signatures_data(raw: &str) -> bs58::decode::Result> { + bs58::decode(raw).into_vec() +} + +#[cfg_attr(feature = "cli", derive(clap::Args))] +#[cfg_attr(feature = "cli", + clap( + group(clap::ArgGroup::new("signatures_data").required(true)), + )) +] +pub struct CommonClientImportExpirationDateSignaturesArgs { + /// Id of client that is going to import the signatures + #[cfg_attr(feature = "cli", clap(long))] + pub id: String, + + /// Config file of the client that is supposed to use the signatures. + #[cfg_attr(feature = "cli", clap(long))] + pub(crate) client_config: PathBuf, + + /// Explicitly provide the encoded signatures data (as base58) + #[cfg_attr(feature = "cli", clap(long, group = "signatures_data", value_parser = parse_encoded_signatures_data))] + pub(crate) signatures_data: Option>, + + /// Specifies the path to file containing binary signatures data + #[cfg_attr(feature = "cli", clap(long, group = "signatures_data"))] + pub(crate) signatures_path: Option, + + // currently hidden as there exists only a single serialization standard + #[cfg_attr(feature = "cli", clap(long, hide = true))] + pub(crate) version: Option, +} + +pub async fn import_expiration_date_signatures(args: A) -> Result<(), C::Error> +where + A: Into, + C: CliClient, + C::Error: From + From, +{ + let common_args = args.into(); + let id = &common_args.id; + + let config = C::try_load_current_config(id).await?; + let paths = config.common_paths(); + + let credentials_store = + nym_credential_storage::initialise_persistent_storage(&paths.credentials_database).await; + + let version = common_args.version; + let raw_key = match common_args.signatures_data { + Some(data) => data, + None => { + // SAFETY: one of those arguments must have been set + fs::read(common_args.signatures_path.unwrap())? + } + }; + + nym_id::import_expiration_date_signatures(credentials_store, raw_key, version).await?; + + Ok(()) +} diff --git a/common/client-core/src/cli_helpers/client_import_master_verification_key.rs b/common/client-core/src/cli_helpers/client_import_master_verification_key.rs new file mode 100644 index 0000000000..25a3c421f2 --- /dev/null +++ b/common/client-core/src/cli_helpers/client_import_master_verification_key.rs @@ -0,0 +1,68 @@ +// Copyright 2024 - Nym Technologies SA +// SPDX-License-Identifier: Apache-2.0 + +use crate::cli_helpers::{CliClient, CliClientConfig}; +use std::fs; +use std::path::PathBuf; + +#[cfg(feature = "cli")] +fn parse_encoded_key_data(raw: &str) -> bs58::decode::Result> { + bs58::decode(raw).into_vec() +} + +#[cfg_attr(feature = "cli", derive(clap::Args))] +#[cfg_attr(feature = "cli", + clap( + group(clap::ArgGroup::new("key_data").required(true)), + )) +] +pub struct CommonClientImportMasterVerificationKeyArgs { + /// Id of client that is going to import the key + #[cfg_attr(feature = "cli", clap(long))] + pub id: String, + + /// Config file of the client that is supposed to use the key. + #[cfg_attr(feature = "cli", clap(long))] + pub(crate) client_config: PathBuf, + + /// Explicitly provide the encoded key data (as base58) + #[cfg_attr(feature = "cli", clap(long, group = "key_data", value_parser = parse_encoded_key_data))] + pub(crate) key_data: Option>, + + /// Specifies the path to file containing binary key data + #[cfg_attr(feature = "cli", clap(long, group = "key_data"))] + pub(crate) key_path: Option, + + // currently hidden as there exists only a single serialization standard + #[cfg_attr(feature = "cli", clap(long, hide = true))] + pub(crate) version: Option, +} + +pub async fn import_master_verification_key(args: A) -> Result<(), C::Error> +where + A: Into, + C: CliClient, + C::Error: From + From, +{ + let common_args = args.into(); + let id = &common_args.id; + + let config = C::try_load_current_config(id).await?; + let paths = config.common_paths(); + + let credentials_store = + nym_credential_storage::initialise_persistent_storage(&paths.credentials_database).await; + + let version = common_args.version; + let raw_key = match common_args.key_data { + Some(data) => data, + None => { + // SAFETY: one of those arguments must have been set + fs::read(common_args.key_path.unwrap())? + } + }; + + nym_id::import_master_verification_key(credentials_store, raw_key, version).await?; + + Ok(()) +} diff --git a/common/client-core/src/cli_helpers/mod.rs b/common/client-core/src/cli_helpers/mod.rs index a3660a60e6..e1f2e23107 100644 --- a/common/client-core/src/cli_helpers/mod.rs +++ b/common/client-core/src/cli_helpers/mod.rs @@ -2,7 +2,10 @@ // SPDX-License-Identifier: Apache-2.0 pub mod client_add_gateway; +pub mod client_import_coin_index_signatures; pub mod client_import_credential; +pub mod client_import_expiration_date_signatures; +pub mod client_import_master_verification_key; pub mod client_init; pub mod client_list_gateways; pub mod client_run; diff --git a/common/commands/Cargo.toml b/common/commands/Cargo.toml index 0754aa6f11..b922baa10b 100644 --- a/common/commands/Cargo.toml +++ b/common/commands/Cargo.toml @@ -25,8 +25,9 @@ rand = { workspace = true, features = ["std"] } serde = { workspace = true, features = ["derive"] } serde_json = { workspace = true } thiserror = { workspace = true } +tempfile = { workspace = true } time = { workspace = true, features = ["parsing", "formatting"] } -tokio = { workspace = true, features = ["sync"]} +tokio = { workspace = true, features = ["sync"] } toml = "0.5.6" url = { workspace = true } tap = { workspace = true } diff --git a/common/commands/src/coconut/issue_ticket_book.rs b/common/commands/src/coconut/issue_ticket_book.rs deleted file mode 100644 index 79eb67ac0c..0000000000 --- a/common/commands/src/coconut/issue_ticket_book.rs +++ /dev/null @@ -1,56 +0,0 @@ -// Copyright 2022-2023 - Nym Technologies SA -// SPDX-License-Identifier: Apache-2.0 - -use crate::context::SigningClient; -use crate::utils::CommonConfigsWrapper; -use anyhow::bail; -use clap::Parser; -use nym_credential_storage::initialise_persistent_storage; -use nym_credential_utils::utils; -use nym_credentials_interface::TicketType; -use nym_crypto::asymmetric::identity; -use std::path::PathBuf; - -#[derive(Debug, Parser)] -pub struct Args { - /// Specify which type of ticketbook should be issued - #[clap(long, default_value_t = TicketType::V1MixnetEntry)] - pub(crate) ticketbook_type: TicketType, - - /// Config file of the client that is supposed to use the credential. - #[clap(long)] - pub(crate) client_config: PathBuf, -} - -pub async fn execute(args: Args, client: SigningClient) -> anyhow::Result<()> { - let loaded = CommonConfigsWrapper::try_load(args.client_config)?; - - if let Ok(id) = loaded.try_get_id() { - println!("loaded config file for client '{id}'"); - } - - let Ok(credentials_store) = loaded.try_get_credentials_store() else { - bail!("the loaded config does not have a credentials store information") - }; - - let Ok(private_id_key) = loaded.try_get_private_id_key() else { - bail!("the loaded config does not have a public id key information") - }; - - println!( - "using credentials store at '{}'", - credentials_store.display() - ); - - let persistent_storage = initialise_persistent_storage(credentials_store).await; - let private_id_key: identity::PrivateKey = nym_pemstore::load_key(private_id_key)?; - utils::issue_credential( - &client, - &persistent_storage, - &private_id_key.to_bytes(), - args.ticketbook_type, - ) - .await?; - - Ok(()) -} diff --git a/common/commands/src/ecash/import_coin_index_signatures.rs b/common/commands/src/ecash/import_coin_index_signatures.rs new file mode 100644 index 0000000000..91d12aafbb --- /dev/null +++ b/common/commands/src/ecash/import_coin_index_signatures.rs @@ -0,0 +1,76 @@ +// Copyright 2024 - Nym Technologies SA +// SPDX-License-Identifier: Apache-2.0 + +use crate::utils::CommonConfigsWrapper; +use anyhow::bail; +use clap::ArgGroup; +use clap::Parser; +use nym_credential_storage::initialise_persistent_storage; +use nym_id::import_credential::import_expiration_date_signatures; +use std::fs; +use std::path::PathBuf; + +fn parse_encoded_signatures_data(raw: &str) -> bs58::decode::Result> { + bs58::decode(raw).into_vec() +} + +#[derive(Debug, Parser)] +#[clap( + group(ArgGroup::new("signatures_data").required(true)), +)] +pub struct Args { + /// Config file of the client that is supposed to use the signatures. + #[clap(long)] + pub(crate) client_config: PathBuf, + + /// Explicitly provide the encoded signatures data (as base58) + #[clap(long, group = "signatures_data", value_parser = parse_encoded_signatures_data)] + pub(crate) signatures_data: Option>, + + /// Specifies the path to file containing binary signatures data + #[clap(long, group = "signatures_data")] + pub(crate) signatures_path: Option, + + // currently hidden as there exists only a single serialization standard + #[clap(long, hide = true)] + pub(crate) version: Option, +} + +impl Args { + fn signatures_data(self) -> anyhow::Result> { + let data = match self.signatures_data { + Some(data) => data, + None => { + // SAFETY: one of those arguments must have been set + #[allow(clippy::unwrap_used)] + fs::read(self.signatures_path.unwrap())? + } + }; + Ok(data) + } +} + +pub async fn execute(args: Args) -> anyhow::Result<()> { + let loaded = CommonConfigsWrapper::try_load(&args.client_config)?; + + if let Ok(id) = loaded.try_get_id() { + println!("loaded config file for client '{id}'"); + } + + let Ok(credentials_store) = loaded.try_get_credentials_store() else { + bail!("the loaded config does not have a credentials store information") + }; + + println!( + "using credentials store at '{}'", + credentials_store.display() + ); + let credentials_store = initialise_persistent_storage(credentials_store).await; + + let version = args.version; + let raw_signatures = args.signatures_data()?; + + import_expiration_date_signatures(credentials_store, raw_signatures, version).await?; + + Ok(()) +} diff --git a/common/commands/src/ecash/import_expiration_date_signatures.rs b/common/commands/src/ecash/import_expiration_date_signatures.rs new file mode 100644 index 0000000000..91d12aafbb --- /dev/null +++ b/common/commands/src/ecash/import_expiration_date_signatures.rs @@ -0,0 +1,76 @@ +// Copyright 2024 - Nym Technologies SA +// SPDX-License-Identifier: Apache-2.0 + +use crate::utils::CommonConfigsWrapper; +use anyhow::bail; +use clap::ArgGroup; +use clap::Parser; +use nym_credential_storage::initialise_persistent_storage; +use nym_id::import_credential::import_expiration_date_signatures; +use std::fs; +use std::path::PathBuf; + +fn parse_encoded_signatures_data(raw: &str) -> bs58::decode::Result> { + bs58::decode(raw).into_vec() +} + +#[derive(Debug, Parser)] +#[clap( + group(ArgGroup::new("signatures_data").required(true)), +)] +pub struct Args { + /// Config file of the client that is supposed to use the signatures. + #[clap(long)] + pub(crate) client_config: PathBuf, + + /// Explicitly provide the encoded signatures data (as base58) + #[clap(long, group = "signatures_data", value_parser = parse_encoded_signatures_data)] + pub(crate) signatures_data: Option>, + + /// Specifies the path to file containing binary signatures data + #[clap(long, group = "signatures_data")] + pub(crate) signatures_path: Option, + + // currently hidden as there exists only a single serialization standard + #[clap(long, hide = true)] + pub(crate) version: Option, +} + +impl Args { + fn signatures_data(self) -> anyhow::Result> { + let data = match self.signatures_data { + Some(data) => data, + None => { + // SAFETY: one of those arguments must have been set + #[allow(clippy::unwrap_used)] + fs::read(self.signatures_path.unwrap())? + } + }; + Ok(data) + } +} + +pub async fn execute(args: Args) -> anyhow::Result<()> { + let loaded = CommonConfigsWrapper::try_load(&args.client_config)?; + + if let Ok(id) = loaded.try_get_id() { + println!("loaded config file for client '{id}'"); + } + + let Ok(credentials_store) = loaded.try_get_credentials_store() else { + bail!("the loaded config does not have a credentials store information") + }; + + println!( + "using credentials store at '{}'", + credentials_store.display() + ); + let credentials_store = initialise_persistent_storage(credentials_store).await; + + let version = args.version; + let raw_signatures = args.signatures_data()?; + + import_expiration_date_signatures(credentials_store, raw_signatures, version).await?; + + Ok(()) +} diff --git a/common/commands/src/ecash/import_master_verification_key.rs b/common/commands/src/ecash/import_master_verification_key.rs new file mode 100644 index 0000000000..f194c00c8a --- /dev/null +++ b/common/commands/src/ecash/import_master_verification_key.rs @@ -0,0 +1,76 @@ +// Copyright 2024 - Nym Technologies SA +// SPDX-License-Identifier: Apache-2.0 + +use crate::utils::CommonConfigsWrapper; +use anyhow::bail; +use clap::ArgGroup; +use clap::Parser; +use nym_credential_storage::initialise_persistent_storage; +use nym_id::import_credential::import_master_verification_key; +use std::fs; +use std::path::PathBuf; + +fn parse_encoded_key_data(raw: &str) -> bs58::decode::Result> { + bs58::decode(raw).into_vec() +} + +#[derive(Debug, Parser)] +#[clap( + group(ArgGroup::new("key_data").required(true)), +)] +pub struct Args { + /// Config file of the client that is supposed to use the key. + #[clap(long)] + pub(crate) client_config: PathBuf, + + /// Explicitly provide the encoded key data (as base58) + #[clap(long, group = "key_data", value_parser = parse_encoded_key_data)] + pub(crate) key_data: Option>, + + /// Specifies the path to file containing binary key data + #[clap(long, group = "key_data")] + pub(crate) key_path: Option, + + // currently hidden as there exists only a single serialization standard + #[clap(long, hide = true)] + pub(crate) version: Option, +} + +impl Args { + fn key_data(self) -> anyhow::Result> { + let data = match self.key_data { + Some(data) => data, + None => { + // SAFETY: one of those arguments must have been set + #[allow(clippy::unwrap_used)] + fs::read(self.key_path.unwrap())? + } + }; + Ok(data) + } +} + +pub async fn execute(args: Args) -> anyhow::Result<()> { + let loaded = CommonConfigsWrapper::try_load(&args.client_config)?; + + if let Ok(id) = loaded.try_get_id() { + println!("loaded config file for client '{id}'"); + } + + let Ok(credentials_store) = loaded.try_get_credentials_store() else { + bail!("the loaded config does not have a credentials store information") + }; + + println!( + "using credentials store at '{}'", + credentials_store.display() + ); + let credentials_store = initialise_persistent_storage(credentials_store).await; + + let version = args.version; + let raw_key = args.key_data()?; + + import_master_verification_key(credentials_store, raw_key, version).await?; + + Ok(()) +} diff --git a/common/commands/src/coconut/import_ticket_book.rs b/common/commands/src/ecash/import_ticket_book.rs similarity index 51% rename from common/commands/src/coconut/import_ticket_book.rs rename to common/commands/src/ecash/import_ticket_book.rs index 852f94e34a..4900b37ef5 100644 --- a/common/commands/src/coconut/import_ticket_book.rs +++ b/common/commands/src/ecash/import_ticket_book.rs @@ -6,7 +6,8 @@ use anyhow::bail; use clap::ArgGroup; use clap::Parser; use nym_credential_storage::initialise_persistent_storage; -use nym_id::import_credential; +use nym_id::import_credential::import_full_ticketbook; +use nym_id::import_standalone_ticketbook; use std::fs; use std::path::PathBuf; @@ -15,7 +16,10 @@ fn parse_encoded_credential_data(raw: &str) -> bs58::decode::Result> { } #[derive(Debug, Parser)] -#[clap(group(ArgGroup::new("cred_data").required(true)))] +#[clap( + group(ArgGroup::new("cred_data").required(true)), + group(ArgGroup::new("type").required(true)), +)] pub struct Args { /// Config file of the client that is supposed to use the credential. #[clap(long)] @@ -29,13 +33,36 @@ pub struct Args { #[clap(long, group = "cred_data")] pub(crate) credential_path: Option, + /// Specifies whether we're attempting to import a standalone ticketbook (i.e. serialised `IssuedTicketBook`) + #[clap(long, group = "type")] + pub(crate) standalone: bool, + + /// Specifies whether we're attempting to import full ticketboot + /// (i.e. one that **might** contain required global signatures; that is serialised `ImportableTicketBook`) + #[clap(long, group = "type")] + pub(crate) full: bool, + // currently hidden as there exists only a single serialization standard #[clap(long, hide = true)] pub(crate) version: Option, } +impl Args { + fn credential_data(self) -> anyhow::Result> { + let data = match self.credential_data { + Some(data) => data, + None => { + // SAFETY: one of those arguments must have been set + #[allow(clippy::unwrap_used)] + fs::read(self.credential_path.unwrap())? + } + }; + Ok(data) + } +} + pub async fn execute(args: Args) -> anyhow::Result<()> { - let loaded = CommonConfigsWrapper::try_load(args.client_config)?; + let loaded = CommonConfigsWrapper::try_load(&args.client_config)?; if let Ok(id) = loaded.try_get_id() { println!("loaded config file for client '{id}'"); @@ -51,14 +78,18 @@ pub async fn execute(args: Args) -> anyhow::Result<()> { ); let credentials_store = initialise_persistent_storage(credentials_store).await; - let raw_credential = match args.credential_data { - Some(data) => data, - None => { - // SAFETY: one of those arguments must have been set - fs::read(args.credential_path.unwrap())? - } - }; + let version = args.version; + let standalone = args.standalone; + let full = args.full; + let raw_credential = args.credential_data()?; + + if standalone { + import_standalone_ticketbook(credentials_store, raw_credential, version).await?; + } else { + // sanity check; clap should have ensured it + assert!(full); + import_full_ticketbook(credentials_store, raw_credential, version).await?; + } - import_credential(credentials_store, raw_credential, args.version).await?; Ok(()) } diff --git a/common/commands/src/ecash/issue_ticket_book.rs b/common/commands/src/ecash/issue_ticket_book.rs new file mode 100644 index 0000000000..015522b016 --- /dev/null +++ b/common/commands/src/ecash/issue_ticket_book.rs @@ -0,0 +1,170 @@ +// Copyright 2022-2024 - Nym Technologies SA +// SPDX-License-Identifier: Apache-2.0 + +use crate::context::SigningClient; +use crate::utils::CommonConfigsWrapper; +use anyhow::{anyhow, bail}; +use clap::ArgGroup; +use clap::Parser; +use nym_credential_storage::initialise_persistent_storage; +use nym_credential_storage::storage::Storage; +use nym_credential_utils::utils; +use nym_credentials::ecash::bandwidth::serialiser::VersionedSerialise; +use nym_credentials::{ + AggregatedCoinIndicesSignatures, AggregatedExpirationDateSignatures, EpochVerificationKey, +}; +use nym_credentials_interface::TicketType; +use nym_crypto::asymmetric::identity; +use std::fs; +use std::path::PathBuf; +use tempfile::NamedTempFile; + +#[derive(Debug, Parser)] +#[clap( + group(ArgGroup::new("output").required(true)), +)] +pub struct Args { + /// Specify which type of ticketbook should be issued + #[clap(long, default_value_t = TicketType::V1MixnetEntry)] + pub(crate) ticketbook_type: TicketType, + + /// Config file of the client that is supposed to use the credential. + #[clap(long, group = "output")] + pub(crate) client_config: Option, + + /// Output file for the ticketbook + #[clap(long, group = "output", requires = "bs58_encoded_client_secret")] + pub(crate) output_file: Option, + + /// Specifies whether the output file should use binary or bs58 encoded data + #[clap(long, requires = "output_file")] + pub(crate) bs58_output: bool, + + /// Specifies whether the file output should contain expiration date signatures + #[clap(long, requires = "output_file")] + pub(crate) include_expiration_date_signatures: bool, + + /// Specifies whether the file output should contain coin index signatures + #[clap(long, requires = "output_file")] + pub(crate) include_coin_index_signatures: bool, + + /// Specifies whether the file output should contain master verification key + #[clap(long, requires = "output_file")] + pub(crate) include_master_verification_key: bool, + + /// Secret value that's used for deriving underlying ecash keypair + #[clap(long)] + pub(crate) bs58_encoded_client_secret: Option, +} + +async fn issue_client_ticketbook( + config_path: PathBuf, + ticketbook_type: TicketType, + client: SigningClient, +) -> anyhow::Result<()> { + let loaded = CommonConfigsWrapper::try_load(config_path)?; + + if let Ok(id) = loaded.try_get_id() { + println!("loaded config file for client '{id}'"); + } + + let Ok(credentials_store) = loaded.try_get_credentials_store() else { + bail!("the loaded config does not have a credentials store information") + }; + + let Ok(private_id_key) = loaded.try_get_private_id_key() else { + bail!("the loaded config does not have a public id key information") + }; + + println!( + "using credentials store at '{}'", + credentials_store.display() + ); + + let persistent_storage = initialise_persistent_storage(credentials_store).await; + let private_id_key: identity::PrivateKey = nym_pemstore::load_key(private_id_key)?; + utils::issue_credential( + &client, + &persistent_storage, + &private_id_key.to_bytes(), + ticketbook_type, + ) + .await?; + + Ok(()) +} + +async fn issue_to_file(args: Args, client: SigningClient) -> anyhow::Result<()> { + // those MUST HAVE been specified; clap ensures it + let output_file = args.output_file.unwrap(); + let secret = bs58::decode(&args.bs58_encoded_client_secret.unwrap()).into_vec()?; + + let temp_credential_store_file = NamedTempFile::new()?; + let credential_store_path = temp_credential_store_file.into_temp_path(); + + let credentials_store = initialise_persistent_storage(credential_store_path).await; + + utils::issue_credential(&client, &credentials_store, &secret, args.ticketbook_type).await?; + + let ticketbook = credentials_store + .get_next_unspent_usable_ticketbook(0) + .await? + .ok_or(anyhow!("we just issued a ticketbook, it must be present!"))? + .ticketbook; + + let expiration_date = ticketbook.expiration_date(); + let epoch_id = ticketbook.epoch_id(); + + let mut exported = ticketbook.begin_export(); + + if args.include_expiration_date_signatures { + let signatures = credentials_store + .get_expiration_date_signatures(expiration_date) + .await? + .ok_or(anyhow!("missing expiration date signatures!"))?; + + exported.with_expiration_date_signatures(&AggregatedExpirationDateSignatures { + epoch_id, + expiration_date, + signatures, + }); + } + + if args.include_coin_index_signatures { + let signatures = credentials_store + .get_coin_index_signatures(epoch_id) + .await? + .ok_or(anyhow!("missing coin index signatures!"))?; + exported.with_coin_index_signatures(&AggregatedCoinIndicesSignatures { + epoch_id, + signatures, + }); + } + + if args.include_master_verification_key { + let key = credentials_store + .get_master_verification_key(epoch_id) + .await? + .ok_or(anyhow!("missing master verification key!"))?; + + exported.with_master_verification_key(&EpochVerificationKey { epoch_id, key }); + } + + let data = exported.pack().data; + + if args.bs58_output { + fs::write(output_file, bs58::encode(&data).into_string())?; + } else { + fs::write(output_file, &data)?; + } + + Ok(()) +} + +pub async fn execute(args: Args, client: SigningClient) -> anyhow::Result<()> { + if let Some(client_config) = args.client_config { + return issue_client_ticketbook(client_config, args.ticketbook_type, client).await; + } + + issue_to_file(args, client).await +} diff --git a/common/commands/src/coconut/mod.rs b/common/commands/src/ecash/mod.rs similarity index 63% rename from common/commands/src/coconut/mod.rs rename to common/commands/src/ecash/mod.rs index 74421dd42b..b307e8dc8c 100644 --- a/common/commands/src/coconut/mod.rs +++ b/common/commands/src/ecash/mod.rs @@ -3,6 +3,9 @@ use clap::{Args, Subcommand}; +pub mod import_coin_index_signatures; +pub mod import_expiration_date_signatures; +pub mod import_master_verification_key; pub mod import_ticket_book; pub mod issue_ticket_book; pub mod recover_ticket_book; @@ -19,4 +22,7 @@ pub enum EcashCommands { IssueTicketBook(issue_ticket_book::Args), RecoverTicketBook(recover_ticket_book::Args), ImportTicketBook(import_ticket_book::Args), + ImportCoinIndexSignatures(import_coin_index_signatures::Args), + ImportExpirationDateSignatures(import_expiration_date_signatures::Args), + ImportMasterVerificationKey(import_master_verification_key::Args), } diff --git a/common/commands/src/coconut/recover_ticket_book.rs b/common/commands/src/ecash/recover_ticket_book.rs similarity index 100% rename from common/commands/src/coconut/recover_ticket_book.rs rename to common/commands/src/ecash/recover_ticket_book.rs diff --git a/common/commands/src/lib.rs b/common/commands/src/lib.rs index afca2be0f7..e3670ac572 100644 --- a/common/commands/src/lib.rs +++ b/common/commands/src/lib.rs @@ -1,7 +1,7 @@ // Copyright 2021 - Nym Technologies SA // SPDX-License-Identifier: Apache-2.0 -pub mod coconut; pub mod context; +pub mod ecash; pub mod utils; pub mod validator; diff --git a/common/credential-storage/migrations/20241104120002_signatures_serialisation_revision.sql b/common/credential-storage/migrations/20241104120002_signatures_serialisation_revision.sql new file mode 100644 index 0000000000..627ca3ae0f --- /dev/null +++ b/common/credential-storage/migrations/20241104120002_signatures_serialisation_revision.sql @@ -0,0 +1,13 @@ +/* + * Copyright 2024 - Nym Technologies SA + * SPDX-License-Identifier: Apache-2.0 + */ + +ALTER TABLE master_verification_key + ADD COLUMN serialization_revision INTEGER NOT NULL default 1; + +ALTER TABLE coin_indices_signatures + ADD COLUMN serialization_revision INTEGER NOT NULL default 1; + +ALTER TABLE expiration_date_signatures + ADD COLUMN serialization_revision INTEGER NOT NULL default 1; diff --git a/common/credential-storage/src/backends/memory.rs b/common/credential-storage/src/backends/memory.rs index 71aea890b0..d107677897 100644 --- a/common/credential-storage/src/backends/memory.rs +++ b/common/credential-storage/src/backends/memory.rs @@ -5,6 +5,10 @@ use crate::models::{BasicTicketbookInformation, RetrievedPendingTicketbook, Retr use nym_compact_ecash::scheme::coin_indices_signatures::AnnotatedCoinIndexSignature; use nym_compact_ecash::scheme::expiration_date_signatures::AnnotatedExpirationDateSignature; use nym_compact_ecash::VerificationKeyAuth; +use nym_credentials::ecash::bandwidth::serialiser::keys::EpochVerificationKey; +use nym_credentials::ecash::bandwidth::serialiser::signatures::{ + AggregatedCoinIndicesSignatures, AggregatedExpirationDateSignatures, +}; use nym_credentials::ecash::bandwidth::serialiser::VersionedSerialise; use nym_credentials::{IssuanceTicketBook, IssuedTicketBook}; use nym_ecash_time::Date; @@ -192,14 +196,10 @@ impl MemoryEcachTicketbookManager { guard.master_vk.get(&epoch_id).cloned() } - pub(crate) async fn insert_master_verification_key( - &self, - epoch_id: u64, - key: &VerificationKeyAuth, - ) { + pub(crate) async fn insert_master_verification_key(&self, key: &EpochVerificationKey) { let mut guard = self.inner.write().await; - guard.master_vk.insert(epoch_id, key.clone()); + guard.master_vk.insert(key.epoch_id, key.key.clone()); } pub(crate) async fn get_coin_index_signatures( @@ -213,12 +213,13 @@ impl MemoryEcachTicketbookManager { pub(crate) async fn insert_coin_index_signatures( &self, - epoch_id: u64, - sigs: &[AnnotatedCoinIndexSignature], + sigs: &AggregatedCoinIndicesSignatures, ) { let mut guard = self.inner.write().await; - guard.coin_indices_sigs.insert(epoch_id, sigs.to_vec()); + guard + .coin_indices_sigs + .insert(sigs.epoch_id, sigs.signatures.clone()); } pub(crate) async fn get_expiration_date_signatures( @@ -232,14 +233,12 @@ impl MemoryEcachTicketbookManager { pub(crate) async fn insert_expiration_date_signatures( &self, - _epoch_id: u64, - expiration_date: Date, - sigs: &[AnnotatedExpirationDateSignature], + sigs: &AggregatedExpirationDateSignatures, ) { let mut guard = self.inner.write().await; guard .expiration_date_sigs - .insert(expiration_date, sigs.to_vec()); + .insert(sigs.expiration_date, sigs.signatures.clone()); } } diff --git a/common/credential-storage/src/backends/sqlite.rs b/common/credential-storage/src/backends/sqlite.rs index 43f019afa3..39dbdc8702 100644 --- a/common/credential-storage/src/backends/sqlite.rs +++ b/common/credential-storage/src/backends/sqlite.rs @@ -2,8 +2,8 @@ // SPDX-License-Identifier: Apache-2.0 use crate::models::{ - BasicTicketbookInformation, RawExpirationDateSignatures, StoredIssuedTicketbook, - StoredPendingTicketbook, + BasicTicketbookInformation, RawCoinIndexSignatures, RawExpirationDateSignatures, + RawVerificationKey, StoredIssuedTicketbook, StoredPendingTicketbook, }; use nym_ecash_time::Date; use sqlx::{Executor, Sqlite, Transaction}; @@ -151,25 +151,30 @@ impl SqliteEcashTicketbookManager { pub(crate) async fn get_master_verification_key( &self, epoch_id: i64, - ) -> Result>, sqlx::Error> { - sqlx::query!( - "SELECT serialised_key FROM master_verification_key WHERE epoch_id = ?", + ) -> Result, sqlx::Error> { + sqlx::query_as!( + RawVerificationKey, + r#" + SELECT epoch_id as "epoch_id: u32", serialised_key, serialization_revision as "serialization_revision: u8" + FROM master_verification_key WHERE epoch_id = ? + "#, epoch_id ) .fetch_optional(&self.connection_pool) .await - .map(|maybe_record| maybe_record.map(|r| r.serialised_key)) } pub(crate) async fn insert_master_verification_key( &self, + serialisation_revision: u8, epoch_id: i64, data: &[u8], ) -> Result<(), sqlx::Error> { sqlx::query!( - "INSERT INTO master_verification_key(epoch_id, serialised_key) VALUES (?, ?)", + "INSERT INTO master_verification_key(epoch_id, serialised_key, serialization_revision) VALUES (?, ?, ?)", epoch_id, - data + data, + serialisation_revision ) .execute(&self.connection_pool) .await?; @@ -179,25 +184,30 @@ impl SqliteEcashTicketbookManager { pub(crate) async fn get_coin_index_signatures( &self, epoch_id: i64, - ) -> Result>, sqlx::Error> { - sqlx::query!( - "SELECT serialised_signatures FROM coin_indices_signatures WHERE epoch_id = ?", + ) -> Result, sqlx::Error> { + sqlx::query_as!( + RawCoinIndexSignatures, + r#" + SELECT epoch_id as "epoch_id: u32", serialised_signatures, serialization_revision as "serialization_revision: u8" + FROM coin_indices_signatures WHERE epoch_id = ? + "#, epoch_id ) .fetch_optional(&self.connection_pool) .await - .map(|maybe_record| maybe_record.map(|r| r.serialised_signatures)) } pub(crate) async fn insert_coin_index_signatures( &self, + serialisation_revision: u8, epoch_id: i64, data: &[u8], ) -> Result<(), sqlx::Error> { sqlx::query!( - "INSERT INTO coin_indices_signatures(epoch_id, serialised_signatures) VALUES (?, ?)", + "INSERT INTO coin_indices_signatures(epoch_id, serialised_signatures, serialization_revision) VALUES (?, ?, ?)", epoch_id, - data + data, + serialisation_revision ) .execute(&self.connection_pool) .await?; @@ -211,7 +221,7 @@ impl SqliteEcashTicketbookManager { sqlx::query_as!( RawExpirationDateSignatures, r#" - SELECT epoch_id as "epoch_id: u32", serialised_signatures + SELECT epoch_id as "epoch_id: u32", serialised_signatures, serialization_revision as "serialization_revision: u8" FROM expiration_date_signatures WHERE expiration_date = ? "#, @@ -223,15 +233,20 @@ impl SqliteEcashTicketbookManager { pub(crate) async fn insert_expiration_date_signatures( &self, + serialisation_revision: u8, epoch_id: i64, expiration_date: Date, data: &[u8], ) -> Result<(), sqlx::Error> { sqlx::query!( - "INSERT INTO expiration_date_signatures(expiration_date, epoch_id, serialised_signatures) VALUES (?, ?, ?)", + r#" + INSERT INTO expiration_date_signatures(expiration_date, epoch_id, serialised_signatures, serialization_revision) + VALUES (?, ?, ?, ?) + "#, expiration_date, epoch_id, - data + data, + serialisation_revision ) .execute(&self.connection_pool) .await?; diff --git a/common/credential-storage/src/ephemeral_storage.rs b/common/credential-storage/src/ephemeral_storage.rs index e1a18942c2..4b3ef93660 100644 --- a/common/credential-storage/src/ephemeral_storage.rs +++ b/common/credential-storage/src/ephemeral_storage.rs @@ -9,6 +9,10 @@ use async_trait::async_trait; use nym_compact_ecash::scheme::coin_indices_signatures::AnnotatedCoinIndexSignature; use nym_compact_ecash::scheme::expiration_date_signatures::AnnotatedExpirationDateSignature; use nym_compact_ecash::VerificationKeyAuth; +use nym_credentials::ecash::bandwidth::serialiser::keys::EpochVerificationKey; +use nym_credentials::ecash::bandwidth::serialiser::signatures::{ + AggregatedCoinIndicesSignatures, AggregatedExpirationDateSignatures, +}; use nym_credentials::{IssuanceTicketBook, IssuedTicketBook}; use nym_ecash_time::Date; use std::fmt::{self, Debug, Formatter}; @@ -119,11 +123,10 @@ impl Storage for EphemeralStorage { async fn insert_master_verification_key( &self, - epoch_id: u64, - key: &VerificationKeyAuth, + key: &EpochVerificationKey, ) -> Result<(), Self::StorageError> { self.storage_manager - .insert_master_verification_key(epoch_id, key) + .insert_master_verification_key(key) .await; Ok(()) } @@ -140,11 +143,10 @@ impl Storage for EphemeralStorage { async fn insert_coin_index_signatures( &self, - epoch_id: u64, - data: &[AnnotatedCoinIndexSignature], + signatures: &AggregatedCoinIndicesSignatures, ) -> Result<(), Self::StorageError> { self.storage_manager - .insert_coin_index_signatures(epoch_id, data) + .insert_coin_index_signatures(signatures) .await; Ok(()) } @@ -161,12 +163,10 @@ impl Storage for EphemeralStorage { async fn insert_expiration_date_signatures( &self, - epoch_id: u64, - expiration_date: Date, - data: &[AnnotatedExpirationDateSignature], + signatures: &AggregatedExpirationDateSignatures, ) -> Result<(), Self::StorageError> { self.storage_manager - .insert_expiration_date_signatures(epoch_id, expiration_date, data) + .insert_expiration_date_signatures(signatures) .await; Ok(()) } diff --git a/common/credential-storage/src/models.rs b/common/credential-storage/src/models.rs index 2a3faa2d70..2edf9df3cb 100644 --- a/common/credential-storage/src/models.rs +++ b/common/credential-storage/src/models.rs @@ -62,4 +62,19 @@ pub struct StoredPendingTicketbook { pub struct RawExpirationDateSignatures { pub epoch_id: u32, pub serialised_signatures: Vec, + pub serialization_revision: u8, +} + +#[cfg_attr(not(target_arch = "wasm32"), derive(sqlx::FromRow))] +pub struct RawCoinIndexSignatures { + pub epoch_id: u32, + pub serialised_signatures: Vec, + pub serialization_revision: u8, +} + +#[cfg_attr(not(target_arch = "wasm32"), derive(sqlx::FromRow))] +pub struct RawVerificationKey { + pub epoch_id: u32, + pub serialised_key: Vec, + pub serialization_revision: u8, } diff --git a/common/credential-storage/src/persistent_storage/helpers.rs b/common/credential-storage/src/persistent_storage/helpers.rs deleted file mode 100644 index 614800d609..0000000000 --- a/common/credential-storage/src/persistent_storage/helpers.rs +++ /dev/null @@ -1,54 +0,0 @@ -// Copyright 2024 - Nym Technologies SA -// SPDX-License-Identifier: Apache-2.0 - -use crate::error::StorageError; -use bincode::Options; -use nym_compact_ecash::scheme::coin_indices_signatures::AnnotatedCoinIndexSignature; -use nym_compact_ecash::scheme::expiration_date_signatures::AnnotatedExpirationDateSignature; -use serde::{Deserialize, Serialize}; - -#[derive(Serialize)] -struct StorageBorrowedSerdeWrapper<'a, T>(&'a T); - -#[derive(Serialize, Deserialize)] -struct StorageSerdeWrapper(T); - -pub(crate) fn serialise_coin_index_signatures(sigs: &[AnnotatedCoinIndexSignature]) -> Vec { - storage_serialiser() - .serialize(&StorageBorrowedSerdeWrapper(&sigs)) - .unwrap() -} - -pub(crate) fn deserialise_coin_index_signatures( - raw: &[u8], -) -> Result, StorageError> { - let de: StorageSerdeWrapper<_> = storage_serialiser().deserialize(raw).map_err(|_| { - StorageError::database_inconsistency("malformed stored coin index signatures") - })?; - Ok(de.0) -} - -pub(crate) fn serialise_expiration_date_signatures( - sigs: &[AnnotatedExpirationDateSignature], -) -> Vec { - storage_serialiser() - .serialize(&StorageBorrowedSerdeWrapper(&sigs)) - .unwrap() -} - -pub(crate) fn deserialise_expiration_date_signatures( - raw: &[u8], -) -> Result, StorageError> { - let de: StorageSerdeWrapper<_> = storage_serialiser().deserialize(raw).map_err(|_| { - StorageError::database_inconsistency("malformed expiration date signatures") - })?; - Ok(de.0) -} - -// storage serialiser used for non-critical data, such as global expiration signatures or master verification keys, -// i.e. data that could always be queried for again if malformed -fn storage_serialiser() -> impl bincode::Options { - bincode::DefaultOptions::new() - .with_big_endian() - .with_varint_encoding() -} diff --git a/common/credential-storage/src/persistent_storage/legacy_helpers.rs b/common/credential-storage/src/persistent_storage/legacy_helpers.rs new file mode 100644 index 0000000000..d1feb6ef1a --- /dev/null +++ b/common/credential-storage/src/persistent_storage/legacy_helpers.rs @@ -0,0 +1,44 @@ +// Copyright 2024 - Nym Technologies SA +// SPDX-License-Identifier: Apache-2.0 + +use crate::error::StorageError; +use bincode::Options; +use nym_compact_ecash::scheme::coin_indices_signatures::AnnotatedCoinIndexSignature; +use nym_compact_ecash::scheme::expiration_date_signatures::AnnotatedExpirationDateSignature; +use nym_compact_ecash::VerificationKeyAuth; +use serde::Deserialize; + +#[derive(Deserialize)] +struct StorageSerdeWrapper(T); + +pub(crate) fn deserialise_v1_expiration_date_signatures( + raw: &[u8], +) -> Result, StorageError> { + let de: StorageSerdeWrapper<_> = v1_signatures_serialiser().deserialize(raw).map_err(|_| { + StorageError::database_inconsistency("malformed expiration date signatures") + })?; + Ok(de.0) +} + +pub(crate) fn deserialise_v1_coin_index_signatures( + raw: &[u8], +) -> Result, StorageError> { + let de: StorageSerdeWrapper<_> = v1_signatures_serialiser().deserialize(raw).map_err(|_| { + StorageError::database_inconsistency("malformed stored coin index signatures") + })?; + Ok(de.0) +} + +pub(crate) fn deserialise_v1_master_verification_key( + raw: &[u8], +) -> Result { + VerificationKeyAuth::from_bytes(raw).map_err(|_| { + StorageError::database_inconsistency("malformed stored master verification key") + }) +} + +fn v1_signatures_serialiser() -> impl bincode::Options { + bincode::DefaultOptions::new() + .with_big_endian() + .with_varint_encoding() +} diff --git a/common/credential-storage/src/persistent_storage/mod.rs b/common/credential-storage/src/persistent_storage/mod.rs index 3940d82c3c..c5daceabd5 100644 --- a/common/credential-storage/src/persistent_storage/mod.rs +++ b/common/credential-storage/src/persistent_storage/mod.rs @@ -1,14 +1,16 @@ // Copyright 2023 - Nym Technologies SA // SPDX-License-Identifier: Apache-2.0 +mod legacy_helpers; + use crate::backends::sqlite::{ get_next_unspent_ticketbook, increase_used_ticketbook_tickets, SqliteEcashTicketbookManager, }; use crate::error::StorageError; use crate::models::{BasicTicketbookInformation, RetrievedPendingTicketbook, RetrievedTicketbook}; -use crate::persistent_storage::helpers::{ - deserialise_coin_index_signatures, deserialise_expiration_date_signatures, - serialise_coin_index_signatures, serialise_expiration_date_signatures, +use crate::persistent_storage::legacy_helpers::{ + deserialise_v1_coin_index_signatures, deserialise_v1_expiration_date_signatures, + deserialise_v1_master_verification_key, }; use crate::storage::Storage; use async_trait::async_trait; @@ -16,6 +18,10 @@ use log::{debug, error}; use nym_compact_ecash::scheme::coin_indices_signatures::AnnotatedCoinIndexSignature; use nym_compact_ecash::scheme::expiration_date_signatures::AnnotatedExpirationDateSignature; use nym_compact_ecash::VerificationKeyAuth; +use nym_credentials::ecash::bandwidth::serialiser::keys::EpochVerificationKey; +use nym_credentials::ecash::bandwidth::serialiser::signatures::{ + AggregatedCoinIndicesSignatures, AggregatedExpirationDateSignatures, +}; use nym_credentials::ecash::bandwidth::serialiser::VersionedSerialise; use nym_credentials::{IssuanceTicketBook, IssuedTicketBook}; use nym_ecash_time::{ecash_today, Date, EcashTime}; @@ -23,8 +29,6 @@ use sqlx::ConnectOptions; use std::path::Path; use zeroize::Zeroizing; -mod helpers; - // note that clone here is fine as upon cloning the same underlying pool will be used #[derive(Clone)] pub struct PersistentStorage { @@ -229,21 +233,24 @@ impl Storage for PersistentStorage { return Ok(None); }; - let master_vk = VerificationKeyAuth::from_bytes(&raw).map_err(|_| { - StorageError::database_inconsistency("malformed stored master verification key") - })?; - - Ok(Some(master_vk)) + match raw.serialization_revision { + 1 => deserialise_v1_master_verification_key(&raw.serialised_key).map(Some), + other => { + let deserialised = EpochVerificationKey::try_unpack(&raw.serialised_key, other) + .map_err(|err| StorageError::database_inconsistency(err.to_string()))?; + Ok(Some(deserialised.key)) + } + } } async fn insert_master_verification_key( &self, - epoch_id: u64, - key: &VerificationKeyAuth, + key: &EpochVerificationKey, ) -> Result<(), Self::StorageError> { + let packed = key.pack(); Ok(self .storage_manager - .insert_master_verification_key(epoch_id as i64, &key.to_bytes()) + .insert_master_verification_key(packed.revision, key.epoch_id as i64, &packed.data) .await?) } @@ -259,16 +266,24 @@ impl Storage for PersistentStorage { return Ok(None); }; - Ok(Some(deserialise_coin_index_signatures(&raw)?)) + match raw.serialization_revision { + 1 => deserialise_v1_coin_index_signatures(&raw.serialised_signatures).map(Some), + other => { + let deserialised = + AggregatedCoinIndicesSignatures::try_unpack(&raw.serialised_signatures, other) + .map_err(|err| StorageError::database_inconsistency(err.to_string()))?; + Ok(Some(deserialised.signatures)) + } + } } async fn insert_coin_index_signatures( &self, - epoch_id: u64, - sigs: &[AnnotatedCoinIndexSignature], + signatures: &AggregatedCoinIndicesSignatures, ) -> Result<(), Self::StorageError> { + let packed = signatures.pack(); self.storage_manager - .insert_coin_index_signatures(epoch_id as i64, &serialise_coin_index_signatures(sigs)) + .insert_coin_index_signatures(packed.revision, signatures.epoch_id as i64, &packed.data) .await?; Ok(()) } @@ -285,22 +300,30 @@ impl Storage for PersistentStorage { return Ok(None); }; - Ok(Some(deserialise_expiration_date_signatures( - &raw.serialised_signatures, - )?)) + match raw.serialization_revision { + 1 => deserialise_v1_expiration_date_signatures(&raw.serialised_signatures).map(Some), + other => { + let deserialised = AggregatedExpirationDateSignatures::try_unpack( + &raw.serialised_signatures, + other, + ) + .map_err(|err| StorageError::database_inconsistency(err.to_string()))?; + Ok(Some(deserialised.signatures)) + } + } } async fn insert_expiration_date_signatures( &self, - epoch_id: u64, - expiration_date: Date, - sigs: &[AnnotatedExpirationDateSignature], + signatures: &AggregatedExpirationDateSignatures, ) -> Result<(), Self::StorageError> { + let packed = signatures.pack(); self.storage_manager .insert_expiration_date_signatures( - epoch_id as i64, - expiration_date, - &serialise_expiration_date_signatures(sigs), + packed.revision, + signatures.epoch_id as i64, + signatures.expiration_date, + &packed.data, ) .await?; Ok(()) diff --git a/common/credential-storage/src/storage.rs b/common/credential-storage/src/storage.rs index 8b3ebc74ec..7033cd6e1f 100644 --- a/common/credential-storage/src/storage.rs +++ b/common/credential-storage/src/storage.rs @@ -6,6 +6,10 @@ use async_trait::async_trait; use nym_compact_ecash::scheme::coin_indices_signatures::AnnotatedCoinIndexSignature; use nym_compact_ecash::scheme::expiration_date_signatures::AnnotatedExpirationDateSignature; use nym_compact_ecash::VerificationKeyAuth; +use nym_credentials::ecash::bandwidth::serialiser::keys::EpochVerificationKey; +use nym_credentials::ecash::bandwidth::serialiser::signatures::{ + AggregatedCoinIndicesSignatures, AggregatedExpirationDateSignatures, +}; use nym_credentials::{IssuanceTicketBook, IssuedTicketBook}; use nym_ecash_time::Date; use std::error::Error; @@ -64,8 +68,7 @@ pub trait Storage: Send + Sync { async fn insert_master_verification_key( &self, - epoch_id: u64, - key: &VerificationKeyAuth, + key: &EpochVerificationKey, ) -> Result<(), Self::StorageError>; async fn get_coin_index_signatures( @@ -75,8 +78,7 @@ pub trait Storage: Send + Sync { async fn insert_coin_index_signatures( &self, - epoch_id: u64, - data: &[AnnotatedCoinIndexSignature], + signatures: &AggregatedCoinIndicesSignatures, ) -> Result<(), Self::StorageError>; async fn get_expiration_date_signatures( @@ -86,8 +88,6 @@ pub trait Storage: Send + Sync { async fn insert_expiration_date_signatures( &self, - epoch_id: u64, - expiration_date: Date, - data: &[AnnotatedExpirationDateSignature], + signatures: &AggregatedExpirationDateSignatures, ) -> Result<(), Self::StorageError>; } diff --git a/common/credentials-interface/src/lib.rs b/common/credentials-interface/src/lib.rs index 270cb5f658..fb0cd1a5df 100644 --- a/common/credentials-interface/src/lib.rs +++ b/common/credentials-interface/src/lib.rs @@ -28,7 +28,7 @@ pub use nym_compact_ecash::{ withdrawal_request, Base58, BlindedSignature, Bytable, EncodedDate, EncodedTicketType, PartialWallet, PayInfo, PublicKeyUser, SecretKeyUser, VerificationKeyAuth, WithdrawalRequest, }; -use nym_ecash_time::{ecash_today, EcashTime}; +pub use nym_ecash_time::{ecash_today, EcashTime}; #[derive(Debug, Clone)] pub struct CredentialSigningData { diff --git a/common/credentials/Cargo.toml b/common/credentials/Cargo.toml index 569c5736cb..4240718a37 100644 --- a/common/credentials/Cargo.toml +++ b/common/credentials/Cargo.toml @@ -25,6 +25,7 @@ nym-api-requests = { path = "../../nym-api/nym-api-requests" } nym-validator-client = { path = "../client-libs/validator-client", default-features = false } nym-ecash-contract-common = { path = "../cosmwasm-smart-contracts/ecash-contract" } nym-network-defaults = { path = "../network-defaults" } +nym-serde-helpers = { path = "../serde-helpers", features = ["date"] } [dev-dependencies] rand = { workspace = true } diff --git a/common/credentials/src/ecash/bandwidth/importable.rs b/common/credentials/src/ecash/bandwidth/importable.rs new file mode 100644 index 0000000000..a1f9ac099e --- /dev/null +++ b/common/credentials/src/ecash/bandwidth/importable.rs @@ -0,0 +1,118 @@ +// Copyright 2024 - Nym Technologies SA +// SPDX-License-Identifier: Apache-2.0 + +use crate::ecash::bandwidth::serialiser::keys::EpochVerificationKey; +use crate::ecash::bandwidth::serialiser::signatures::{ + AggregatedCoinIndicesSignatures, AggregatedExpirationDateSignatures, +}; +use crate::ecash::bandwidth::{ + issued::IssuedTicketBook, + serialiser::{VersionSerialised, VersionedSerialise}, +}; +use crate::Error; +use serde::de::DeserializeOwned; +use serde::{Deserialize, Serialize}; +use zeroize::{Zeroize, ZeroizeOnDrop}; + +pub struct DecodedImportableTicketBook { + pub ticketbook: IssuedTicketBook, + + pub expiration_date_signatures: Option, + + pub coin_index_signatures: Option, + + pub master_verification_key: Option, +} + +#[derive(Zeroize, ZeroizeOnDrop, Serialize, Deserialize)] +pub struct ImportableTicketBook { + pub serialised_ticketbook: VersionSerialised, + + #[zeroize(skip)] + pub serialised_expiration_date_signatures: + Option>, + + #[zeroize(skip)] + pub serialised_coin_index_signatures: + Option>, + + #[zeroize(skip)] + pub serialised_master_verification_key: Option>, +} + +impl From for ImportableTicketBook { + fn from(ticketbook: IssuedTicketBook) -> Self { + ImportableTicketBook { + serialised_ticketbook: ticketbook.pack(), + serialised_expiration_date_signatures: None, + serialised_coin_index_signatures: None, + serialised_master_verification_key: None, + } + } +} + +impl ImportableTicketBook { + pub fn with_expiration_date_signatures( + &mut self, + signatures: &AggregatedExpirationDateSignatures, + ) -> &mut Self { + self.serialised_expiration_date_signatures = Some(signatures.pack()); + self + } + + pub fn with_coin_index_signatures( + &mut self, + signatures: &AggregatedCoinIndicesSignatures, + ) -> &mut Self { + self.serialised_coin_index_signatures = Some(signatures.pack()); + self + } + + pub fn with_master_verification_key(&mut self, key: &EpochVerificationKey) -> &mut Self { + self.serialised_master_verification_key = Some(key.pack()); + self + } + + pub fn finalize_export(self) -> Vec { + self.pack().data + } + + pub fn try_unpack_full(&self) -> Result { + Ok(DecodedImportableTicketBook { + ticketbook: self.serialised_ticketbook.try_unpack()?, + expiration_date_signatures: self + .serialised_expiration_date_signatures + .as_ref() + .map(|sigs| sigs.try_unpack()) + .transpose()?, + coin_index_signatures: self + .serialised_coin_index_signatures + .as_ref() + .map(|sigs| sigs.try_unpack()) + .transpose()?, + master_verification_key: self + .serialised_master_verification_key + .as_ref() + .map(|key| key.try_unpack()) + .transpose()?, + }) + } +} + +impl VersionedSerialise for ImportableTicketBook { + const CURRENT_SERIALISATION_REVISION: u8 = 1; + + fn try_unpack(b: &[u8], revision: impl Into>) -> Result + where + Self: DeserializeOwned, + { + let revision = revision + .into() + .unwrap_or(::CURRENT_SERIALISATION_REVISION); + + match revision { + 1 => Self::try_unpack_current(b), + _ => Err(Error::UnknownSerializationRevision { revision }), + } + } +} diff --git a/common/credentials/src/ecash/bandwidth/issuance.rs b/common/credentials/src/ecash/bandwidth/issuance.rs index 72b1dd0a25..6e9e217f90 100644 --- a/common/credentials/src/ecash/bandwidth/issuance.rs +++ b/common/credentials/src/ecash/bandwidth/issuance.rs @@ -177,7 +177,7 @@ impl IssuanceTicketBook { } // ideally this would have been generic over credential type, but we really don't need secp256k1 keys for bandwidth vouchers - pub async fn obtain_partial_bandwidth_voucher_credential( + pub async fn obtain_partial_ticketbook_credential( &self, client: &nym_validator_client::client::NymApiClient, signer_index: u64, @@ -191,13 +191,6 @@ impl IssuanceTicketBook { self.unblind_signature(validator_vk, &signing_data, blinded_signature, signer_index) } - // pub fn unchecked_aggregate_signature_shares( - // &self, - // shares: &[SignatureShare], - // ) -> Result { - // aggregate_signature_shares(shares).map_err(Error::SignatureAggregationError) - // } - pub fn aggregate_signature_shares( &self, verification_key: &VerificationKeyAuth, diff --git a/common/credentials/src/ecash/bandwidth/issued.rs b/common/credentials/src/ecash/bandwidth/issued.rs index 8787528ae4..a471e7901d 100644 --- a/common/credentials/src/ecash/bandwidth/issued.rs +++ b/common/credentials/src/ecash/bandwidth/issued.rs @@ -1,6 +1,7 @@ // Copyright 2024 - Nym Technologies SA // SPDX-License-Identifier: Apache-2.0 +use crate::ecash::bandwidth::importable::ImportableTicketBook; use crate::ecash::bandwidth::serialiser::VersionedSerialise; use crate::ecash::bandwidth::CredentialSpendingData; use crate::ecash::utils::ecash_today; @@ -153,6 +154,10 @@ impl IssuedTicketBook { epoch_id: self.epoch_id, }) } + + pub fn begin_export(self) -> ImportableTicketBook { + self.into() + } } impl VersionedSerialise for IssuedTicketBook { diff --git a/common/credentials/src/ecash/bandwidth/mod.rs b/common/credentials/src/ecash/bandwidth/mod.rs index ce75507df6..5c66d80864 100644 --- a/common/credentials/src/ecash/bandwidth/mod.rs +++ b/common/credentials/src/ecash/bandwidth/mod.rs @@ -5,6 +5,7 @@ pub use issuance::IssuanceTicketBook; pub use issued::IssuedTicketBook; pub use nym_credentials_interface::{CredentialSigningData, CredentialSpendingData}; +pub mod importable; pub mod issuance; pub mod issued; pub mod serialiser; diff --git a/common/credentials/src/ecash/bandwidth/serialiser/keys.rs b/common/credentials/src/ecash/bandwidth/serialiser/keys.rs new file mode 100644 index 0000000000..ee2e1b0d24 --- /dev/null +++ b/common/credentials/src/ecash/bandwidth/serialiser/keys.rs @@ -0,0 +1,35 @@ +// Copyright 2024 - Nym Technologies SA +// SPDX-License-Identifier: Apache-2.0 + +use crate::ecash::bandwidth::serialiser::VersionedSerialise; +use crate::Error; +use nym_credentials_interface::VerificationKeyAuth; +use serde::de::DeserializeOwned; +use serde::{Deserialize, Serialize}; + +#[derive(Serialize, Deserialize, Debug, Clone)] +pub struct EpochVerificationKey { + pub epoch_id: u64, + + pub key: VerificationKeyAuth, +} + +impl VersionedSerialise for EpochVerificationKey { + // we start with revision 2 as the initial, 1, only contained the inner `key` field data + const CURRENT_SERIALISATION_REVISION: u8 = 2; + + fn try_unpack(b: &[u8], revision: impl Into>) -> Result + where + Self: DeserializeOwned, + { + let revision = revision + .into() + .unwrap_or(::CURRENT_SERIALISATION_REVISION); + + match revision { + 1 => Err(Error::UnsupportedSerializationRevision { revision }), + 2 => Self::try_unpack_current(b), + _ => Err(Error::UnknownSerializationRevision { revision }), + } + } +} diff --git a/common/credentials/src/ecash/bandwidth/serialiser.rs b/common/credentials/src/ecash/bandwidth/serialiser/mod.rs similarity index 83% rename from common/credentials/src/ecash/bandwidth/serialiser.rs rename to common/credentials/src/ecash/bandwidth/serialiser/mod.rs index acb7629002..518202187f 100644 --- a/common/credentials/src/ecash/bandwidth/serialiser.rs +++ b/common/credentials/src/ecash/bandwidth/serialiser/mod.rs @@ -5,17 +5,33 @@ use crate::ecash::bandwidth::issued::CURRENT_SERIALIZATION_REVISION; use crate::Error; use bincode::Options; use serde::de::DeserializeOwned; -use serde::Serialize; +use serde::{Deserialize, Serialize}; use std::marker::PhantomData; +use zeroize::Zeroize; +pub mod keys; +pub mod signatures; + +#[derive(Zeroize, Serialize, Deserialize)] pub struct VersionSerialised { pub data: Vec, pub revision: u8, // still wondering if there's any point in having the phantom in here + #[zeroize(skip)] + #[serde(skip)] _phantom: PhantomData, } +impl VersionSerialised { + pub fn try_unpack(&self) -> Result + where + T: VersionedSerialise + DeserializeOwned, + { + T::try_unpack(&self.data, self.revision) + } +} + pub trait VersionedSerialise { const CURRENT_SERIALISATION_REVISION: u8; diff --git a/common/credentials/src/ecash/bandwidth/serialiser/signatures.rs b/common/credentials/src/ecash/bandwidth/serialiser/signatures.rs new file mode 100644 index 0000000000..02095ca2c8 --- /dev/null +++ b/common/credentials/src/ecash/bandwidth/serialiser/signatures.rs @@ -0,0 +1,66 @@ +// Copyright 2024 - Nym Technologies SA +// SPDX-License-Identifier: Apache-2.0 + +use crate::ecash::bandwidth::serialiser::VersionedSerialise; +use crate::Error; +use nym_credentials_interface::{AnnotatedCoinIndexSignature, AnnotatedExpirationDateSignature}; +use serde::de::DeserializeOwned; +use serde::{Deserialize, Serialize}; +use time::Date; + +#[derive(Serialize, Deserialize, Debug, Clone)] +pub struct AggregatedExpirationDateSignatures { + pub epoch_id: u64, + + #[serde(with = "nym_serde_helpers::date")] + pub expiration_date: Date, + + pub signatures: Vec, +} + +impl VersionedSerialise for AggregatedExpirationDateSignatures { + // we start with revision 2 as the initial, 1, only contained the inner `signatures` field data + const CURRENT_SERIALISATION_REVISION: u8 = 2; + + fn try_unpack(b: &[u8], revision: impl Into>) -> Result + where + Self: DeserializeOwned, + { + let revision = revision + .into() + .unwrap_or(::CURRENT_SERIALISATION_REVISION); + + match revision { + 1 => Err(Error::UnsupportedSerializationRevision { revision }), + 2 => Self::try_unpack_current(b), + _ => Err(Error::UnknownSerializationRevision { revision }), + } + } +} + +#[derive(Serialize, Deserialize, Debug, Clone)] +pub struct AggregatedCoinIndicesSignatures { + pub epoch_id: u64, + + pub signatures: Vec, +} + +impl VersionedSerialise for AggregatedCoinIndicesSignatures { + // we start with revision 2 as the initial, 1, only contained the inner `signatures` field data + const CURRENT_SERIALISATION_REVISION: u8 = 2; + + fn try_unpack(b: &[u8], revision: impl Into>) -> Result + where + Self: DeserializeOwned, + { + let revision = revision + .into() + .unwrap_or(::CURRENT_SERIALISATION_REVISION); + + match revision { + 1 => Err(Error::UnsupportedSerializationRevision { revision }), + 2 => Self::try_unpack_current(b), + _ => Err(Error::UnknownSerializationRevision { revision }), + } + } +} diff --git a/common/credentials/src/ecash/utils.rs b/common/credentials/src/ecash/utils.rs index 970288b075..96d24ad018 100644 --- a/common/credentials/src/ecash/utils.rs +++ b/common/credentials/src/ecash/utils.rs @@ -151,7 +151,7 @@ pub async fn obtain_aggregate_wallet( ); match voucher - .obtain_partial_bandwidth_voucher_credential( + .obtain_partial_ticketbook_credential( &ecash_api_client.api_client, ecash_api_client.node_id, &ecash_api_client.verification_key, diff --git a/common/credentials/src/error.rs b/common/credentials/src/error.rs index c1f99608ee..8f69056de5 100644 --- a/common/credentials/src/error.rs +++ b/common/credentials/src/error.rs @@ -22,7 +22,10 @@ pub enum Error { revision: u8, }, - #[error("unknown credential serializatio revision {revision}. the current (and max supported) version is {CURRENT_SERIALIZATION_REVISION}")] + #[error("unsupported data serialization revision {revision}. the current (and max supported) version is {CURRENT_SERIALIZATION_REVISION}")] + UnsupportedSerializationRevision { revision: u8 }, + + #[error("unknown data serialization revision {revision}. the current (and max supported) version is {CURRENT_SERIALIZATION_REVISION}")] UnknownSerializationRevision { revision: u8 }, #[error("Could not contact any validator")] diff --git a/common/credentials/src/lib.rs b/common/credentials/src/lib.rs index 7f2c3ef2d4..71549ba59b 100644 --- a/common/credentials/src/lib.rs +++ b/common/credentials/src/lib.rs @@ -5,6 +5,11 @@ pub mod ecash; pub mod error; pub use ecash::bandwidth::{ + importable::{DecodedImportableTicketBook, ImportableTicketBook}, + serialiser::{ + keys::EpochVerificationKey, + signatures::{AggregatedCoinIndicesSignatures, AggregatedExpirationDateSignatures}, + }, CredentialSigningData, CredentialSpendingData, IssuanceTicketBook, IssuedTicketBook, }; pub use ecash::utils::{aggregate_verification_keys, obtain_aggregate_wallet}; diff --git a/common/nym-id/src/error.rs b/common/nym-id/src/error.rs index 780658944e..9ccf73267b 100644 --- a/common/nym-id/src/error.rs +++ b/common/nym-id/src/error.rs @@ -7,12 +7,33 @@ use time::Date; #[derive(Debug, Error)] pub enum NymIdError { - #[error("failed to deserialize provided credential: {source}")] - CredentialDeserializationFailure { source: nym_credentials::Error }, + #[error("failed to deserialize provided full ticketbook: {source}")] + FullTicketbookDeserializationFailure { source: nym_credentials::Error }, + + #[error("failed to deserialize provided ticketbook: {source}")] + TicketbookDeserializationFailure { source: nym_credentials::Error }, + + #[error("failed to deserialize provided expiration date signatures: {source}")] + ExpirationDateSignaturesDeserializationFailure { source: nym_credentials::Error }, + + #[error("failed to deserialize provided coin index signatures: {source}")] + CoinIndexSignaturesDeserializationFailure { source: nym_credentials::Error }, + + #[error("failed to deserialize provided verification key: {source}")] + VerificationKeyDeserializationFailure { source: nym_credentials::Error }, #[error("attempted to import an expired credential (it expired on {expiration})")] ExpiredCredentialImport { expiration: Date }, + #[error("could not import ticketbook expiring at {date} since we do not have corresponding expiration date signatures")] + MissingExpirationDateSignatures { date: Date }, + + #[error("could not import ticketbook for epoch {epoch_id} since we do not have corresponding coin index signatures")] + MissingCoinIndexSignatures { epoch_id: u64 }, + + #[error("could not import ticketbook for epoch {epoch_id} since we do not have corresponding master verification key")] + MissingMasterVerificationKey { epoch_id: u64 }, + #[error("failed to store credential in the provided store: {source}")] StorageError { source: Box, diff --git a/common/nym-id/src/import_credential.rs b/common/nym-id/src/import_credential.rs deleted file mode 100644 index 867db15749..0000000000 --- a/common/nym-id/src/import_credential.rs +++ /dev/null @@ -1,49 +0,0 @@ -// Copyright 2024 - Nym Technologies SA -// SPDX-License-Identifier: Apache-2.0 - -use crate::NymIdError; -use nym_credential_storage::storage::Storage; -use nym_credentials::ecash::bandwidth::serialiser::VersionedSerialise; -use nym_credentials::ecash::utils::EcashTime; -use nym_credentials::IssuedTicketBook; -use time::OffsetDateTime; -use tracing::{debug, warn}; -use zeroize::Zeroizing; - -pub async fn import_credential( - credentials_store: S, - raw_credential: Vec, - credential_version: impl Into>, -) -> Result -where - S: Storage, - ::StorageError: Send + Sync + 'static, -{ - let raw_credential = Zeroizing::new(raw_credential); - - // note: the type itself implements ZeroizeOnDrop - let ticketbook = IssuedTicketBook::try_unpack(&raw_credential, credential_version) - .map_err(|source| NymIdError::CredentialDeserializationFailure { source })?; - - debug!( - "attempting to import credential with expiration date at {}", - ticketbook.expiration_date() - ); - - if ticketbook.expired() { - warn!("the credential has already expired!"); - - // technically we can import it, but the gateway will just reject it so what's the point - return Err(NymIdError::ExpiredCredentialImport { - expiration: ticketbook.expiration_date(), - }); - } - - credentials_store - .insert_issued_ticketbook(&ticketbook) - .await - .map_err(|source| NymIdError::StorageError { - source: Box::new(source), - })?; - Ok(ticketbook.expiration_date().ecash_datetime()) -} diff --git a/common/nym-id/src/import_credential/helpers.rs b/common/nym-id/src/import_credential/helpers.rs new file mode 100644 index 0000000000..dec6228d79 --- /dev/null +++ b/common/nym-id/src/import_credential/helpers.rs @@ -0,0 +1,147 @@ +// Copyright 2024 - Nym Technologies SA +// SPDX-License-Identifier: Apache-2.0 + +use crate::NymIdError; +use nym_credential_storage::storage::Storage; +use nym_credentials::{ + AggregatedCoinIndicesSignatures, AggregatedExpirationDateSignatures, EpochVerificationKey, + IssuedTicketBook, +}; +use tracing::{debug, warn}; + +pub(crate) async fn import_master_verification_key( + credentials_store: &S, + key: &EpochVerificationKey, +) -> Result<(), NymIdError> +where + S: Storage, + ::StorageError: Send + Sync + 'static, +{ + debug!( + "attempting to import master verification key for epoch {}", + key.epoch_id + ); + + credentials_store + .insert_master_verification_key(key) + .await + .map_err(|source| NymIdError::StorageError { + source: Box::new(source), + })?; + Ok(()) +} + +pub(crate) async fn import_expiration_date_signatures( + credentials_store: &S, + signatures: &AggregatedExpirationDateSignatures, +) -> Result<(), NymIdError> +where + S: Storage, + ::StorageError: Send + Sync + 'static, +{ + debug!( + "attempting to import expiration date signatures with expiration date at {} (epoch: {})", + signatures.expiration_date, signatures.epoch_id + ); + + credentials_store + .insert_expiration_date_signatures(signatures) + .await + .map_err(|source| NymIdError::StorageError { + source: Box::new(source), + })?; + Ok(()) +} + +pub(crate) async fn import_coin_index_signatures( + credentials_store: &S, + signatures: &AggregatedCoinIndicesSignatures, +) -> Result<(), NymIdError> +where + S: Storage, + ::StorageError: Send + Sync + 'static, +{ + debug!( + "attempting to import coin index signatures for epoch {}", + signatures.epoch_id + ); + + credentials_store + .insert_coin_index_signatures(signatures) + .await + .map_err(|source| NymIdError::StorageError { + source: Box::new(source), + })?; + Ok(()) +} + +pub(crate) async fn import_ticketbook( + credentials_store: &S, + ticketbook: &IssuedTicketBook, +) -> Result<(), NymIdError> +where + S: Storage, + ::StorageError: Send + Sync + 'static, +{ + debug!( + "attempting to import ticketbook with expiration date at {}", + ticketbook.expiration_date() + ); + + if ticketbook.expired() { + warn!("the credential has already expired!"); + + // technically we can import it, but the gateway will just reject it so what's the point + return Err(NymIdError::ExpiredCredentialImport { + expiration: ticketbook.expiration_date(), + }); + } + + // in order to import the ticketbook we MUST have the appropriate signatures in the storage already + if credentials_store + .get_expiration_date_signatures(ticketbook.expiration_date()) + .await + .map_err(|source| NymIdError::StorageError { + source: Box::new(source), + })? + .is_none() + { + return Err(NymIdError::MissingExpirationDateSignatures { + date: ticketbook.expiration_date(), + }); + } + + if credentials_store + .get_coin_index_signatures(ticketbook.epoch_id()) + .await + .map_err(|source| NymIdError::StorageError { + source: Box::new(source), + })? + .is_none() + { + return Err(NymIdError::MissingCoinIndexSignatures { + epoch_id: ticketbook.epoch_id(), + }); + } + + if credentials_store + .get_master_verification_key(ticketbook.epoch_id()) + .await + .map_err(|source| NymIdError::StorageError { + source: Box::new(source), + })? + .is_none() + { + return Err(NymIdError::MissingMasterVerificationKey { + epoch_id: ticketbook.epoch_id(), + }); + } + + credentials_store + .insert_issued_ticketbook(ticketbook) + .await + .map_err(|source| NymIdError::StorageError { + source: Box::new(source), + })?; + Ok(()) +} diff --git a/common/nym-id/src/import_credential/mod.rs b/common/nym-id/src/import_credential/mod.rs new file mode 100644 index 0000000000..878b3bc5bc --- /dev/null +++ b/common/nym-id/src/import_credential/mod.rs @@ -0,0 +1,119 @@ +// Copyright 2024 - Nym Technologies SA +// SPDX-License-Identifier: Apache-2.0 + +use crate::NymIdError; +use nym_credential_storage::storage::Storage; +use nym_credentials::ecash::bandwidth::serialiser::keys::EpochVerificationKey; +use nym_credentials::ecash::bandwidth::serialiser::signatures::{ + AggregatedCoinIndicesSignatures, AggregatedExpirationDateSignatures, +}; +use nym_credentials::ecash::bandwidth::serialiser::VersionedSerialise; +use nym_credentials::ecash::utils::EcashTime; +use nym_credentials::{ImportableTicketBook, IssuedTicketBook}; +use time::OffsetDateTime; +use zeroize::Zeroizing; + +mod helpers; + +pub async fn import_master_verification_key( + credentials_store: S, + raw_key: Vec, + key_version: impl Into>, +) -> Result<(), NymIdError> +where + S: Storage, + ::StorageError: Send + Sync + 'static, +{ + let key = EpochVerificationKey::try_unpack(&raw_key, key_version) + .map_err(|source| NymIdError::VerificationKeyDeserializationFailure { source })?; + + helpers::import_master_verification_key(&credentials_store, &key).await +} + +pub async fn import_expiration_date_signatures( + credentials_store: S, + raw_signatures: Vec, + signatures_version: impl Into>, +) -> Result<(), NymIdError> +where + S: Storage, + ::StorageError: Send + Sync + 'static, +{ + let signatures = + AggregatedExpirationDateSignatures::try_unpack(&raw_signatures, signatures_version) + .map_err( + |source| NymIdError::ExpirationDateSignaturesDeserializationFailure { source }, + )?; + + helpers::import_expiration_date_signatures(&credentials_store, &signatures).await +} + +pub async fn import_coin_index_signatures( + credentials_store: S, + raw_signatures: Vec, + signatures_version: impl Into>, +) -> Result<(), NymIdError> +where + S: Storage, + ::StorageError: Send + Sync + 'static, +{ + let signatures = + AggregatedCoinIndicesSignatures::try_unpack(&raw_signatures, signatures_version) + .map_err(|source| NymIdError::CoinIndexSignaturesDeserializationFailure { source })?; + + helpers::import_coin_index_signatures(&credentials_store, &signatures).await +} + +pub async fn import_standalone_ticketbook( + credentials_store: S, + raw_credential: Vec, + credential_version: impl Into>, +) -> Result +where + S: Storage, + ::StorageError: Send + Sync + 'static, +{ + let raw_credential = Zeroizing::new(raw_credential); + + // note: the type itself implements ZeroizeOnDrop + let ticketbook = IssuedTicketBook::try_unpack(&raw_credential, credential_version) + .map_err(|source| NymIdError::TicketbookDeserializationFailure { source })?; + + helpers::import_ticketbook(&credentials_store, &ticketbook).await?; + Ok(ticketbook.expiration_date().ecash_datetime()) +} + +pub async fn import_full_ticketbook( + credentials_store: S, + raw_credential: Vec, + credential_version: impl Into>, +) -> Result +where + S: Storage, + ::StorageError: Send + Sync + 'static, +{ + let raw_credential = Zeroizing::new(raw_credential); + + let importable = ImportableTicketBook::try_unpack(&raw_credential, credential_version) + .map_err(|source| NymIdError::FullTicketbookDeserializationFailure { source })?; + + let decoded = importable + .try_unpack_full() + .map_err(|source| NymIdError::TicketbookDeserializationFailure { source })?; + + if let Some(key) = &decoded.master_verification_key { + helpers::import_master_verification_key(&credentials_store, key).await? + } + + if let Some(sigs) = &decoded.expiration_date_signatures { + helpers::import_expiration_date_signatures(&credentials_store, sigs).await? + } + + if let Some(sigs) = &decoded.coin_index_signatures { + helpers::import_coin_index_signatures(&credentials_store, sigs).await? + } + + helpers::import_ticketbook(&credentials_store, &decoded.ticketbook).await?; + + Ok(decoded.ticketbook.expiration_date().ecash_datetime()) +} diff --git a/common/nym-id/src/lib.rs b/common/nym-id/src/lib.rs index e2e3a74adc..e535bddd16 100644 --- a/common/nym-id/src/lib.rs +++ b/common/nym-id/src/lib.rs @@ -8,4 +8,7 @@ pub mod error; pub mod import_credential; pub use error::NymIdError; -pub use import_credential::import_credential; +pub use import_credential::{ + import_coin_index_signatures, import_expiration_date_signatures, import_full_ticketbook, + import_master_verification_key, import_standalone_ticketbook, +}; diff --git a/common/nym_offline_compact_ecash/src/scheme/aggregation.rs b/common/nym_offline_compact_ecash/src/scheme/aggregation.rs index 4d7c116121..b5ca003e22 100644 --- a/common/nym_offline_compact_ecash/src/scheme/aggregation.rs +++ b/common/nym_offline_compact_ecash/src/scheme/aggregation.rs @@ -14,6 +14,7 @@ use core::iter::Sum; use core::ops::Mul; use group::Curve; use itertools::Itertools; +use zeroize::Zeroizing; pub(crate) trait Aggregatable: Sized { fn aggregate(aggregatable: &[Self], indices: Option<&[SignerIndex]>) -> Result; @@ -138,12 +139,12 @@ pub fn aggregate_wallets( .map(|wallet| SignatureShare::new(*wallet.signature(), wallet.index())) .collect(); - let attributes = vec![ + let attributes = Zeroizing::new(vec![ sk_user.sk, *req_info.get_v(), *req_info.get_expiration_date(), *req_info.get_t_type(), - ]; + ]); let aggregated_signature = aggregate_signature_shares(verification_key, &attributes, &signature_shares)?; diff --git a/common/nym_offline_compact_ecash/src/scheme/keygen.rs b/common/nym_offline_compact_ecash/src/scheme/keygen.rs index ade891b01f..f5926d9cb6 100644 --- a/common/nym_offline_compact_ecash/src/scheme/keygen.rs +++ b/common/nym_offline_compact_ecash/src/scheme/keygen.rs @@ -524,7 +524,22 @@ pub struct KeyPairUser { public_key: PublicKeyUser, } +impl From for SecretKeyUser { + fn from(value: KeyPairUser) -> Self { + value.secret_key + } +} + impl KeyPairUser { + #[allow(clippy::new_without_default)] + pub fn new() -> Self { + generate_keypair_user() + } + + pub fn new_seeded>(seed: M) -> Self { + generate_keypair_user_from_seed(seed) + } + pub fn secret_key(&self) -> &SecretKeyUser { &self.secret_key } diff --git a/common/nym_offline_compact_ecash/src/scheme/withdrawal.rs b/common/nym_offline_compact_ecash/src/scheme/withdrawal.rs index 082f969508..77d780f589 100644 --- a/common/nym_offline_compact_ecash/src/scheme/withdrawal.rs +++ b/common/nym_offline_compact_ecash/src/scheme/withdrawal.rs @@ -16,6 +16,7 @@ use bls12_381::{multi_miller_loop, G1Projective, G2Prepared, G2Projective, Scala use group::{Curve, Group, GroupEncoding}; use serde::{Deserialize, Serialize}; use std::ops::Neg; +use zeroize::{Zeroize, ZeroizeOnDrop}; /// Represents a withdrawal request generate by the client who wants to obtain a zk-nym credential. /// @@ -51,7 +52,7 @@ impl WithdrawalRequest { /// /// This structure holds the commitment hash, commitment opening, private attributes openings, /// the wallet secret (scalar), and the expiration date related to a withdrawal request. -#[derive(Debug, Clone, Serialize, Deserialize)] +#[derive(Debug, Clone, Serialize, Deserialize, Zeroize, ZeroizeOnDrop)] pub struct RequestInfo { joined_commitment_hash: G1Projective, joined_commitment_opening: Scalar, diff --git a/common/serde-helpers/Cargo.toml b/common/serde-helpers/Cargo.toml index 1cb5c76fb7..a45ed0afbd 100644 --- a/common/serde-helpers/Cargo.toml +++ b/common/serde-helpers/Cargo.toml @@ -15,8 +15,9 @@ license.workspace = true serde = { workspace = true } bs58 = { workspace = true, optional = true } base64 = { workspace = true, optional = true } - +time = { workspace = true, features = ["formatting", "parsing"], optional = true } [features] bs58 = ["dep:bs58"] base64 = ["dep:base64"] +date = ["time"] \ No newline at end of file diff --git a/common/serde-helpers/src/lib.rs b/common/serde-helpers/src/lib.rs index f90a65a2f4..fd37be86b8 100644 --- a/common/serde-helpers/src/lib.rs +++ b/common/serde-helpers/src/lib.rs @@ -31,3 +31,41 @@ pub mod bs58 { .map_err(serde::de::Error::custom) } } + +#[cfg(feature = "date")] +pub mod date { + use serde::ser::Error; + use serde::{de, Deserialize, Deserializer, Serialize, Serializer}; + use time::format_description::{modifier, BorrowedFormatItem, Component}; + use time::Date; + + // simple YYYY-MM-DD + pub const DATE_FORMAT: &[BorrowedFormatItem<'_>] = &[ + BorrowedFormatItem::Component(Component::Year(modifier::Year::default())), + BorrowedFormatItem::Literal(b"-"), + BorrowedFormatItem::Component(Component::Month(modifier::Month::default())), + BorrowedFormatItem::Literal(b"-"), + BorrowedFormatItem::Component(Component::Day(modifier::Day::default())), + ]; + + pub fn deserialize<'de, D>(deserializer: D) -> Result + where + D: Deserializer<'de>, + { + let s = String::deserialize(deserializer)?; + + Date::parse(&s, DATE_FORMAT).map_err(de::Error::custom) + } + + pub fn serialize(datetime: &Date, serializer: S) -> Result + where + S: Serializer, + { + // serialize it with human-readable format for compatibility with eclipse and nutella clients + // in the future change it back to rfc3339 + datetime + .format(&DATE_FORMAT) + .map_err(S::Error::custom)? + .serialize(serializer) + } +} diff --git a/contracts/Cargo.lock b/contracts/Cargo.lock index 3bdbdb9022..aecf93c51e 100644 --- a/contracts/Cargo.lock +++ b/contracts/Cargo.lock @@ -1292,7 +1292,7 @@ dependencies = [ name = "nym-mixnet-contract-common" version = "0.6.0" dependencies = [ - "bs58 0.4.0", + "bs58 0.5.1", "cosmwasm-schema", "cosmwasm-std", "cw2", @@ -1697,9 +1697,9 @@ dependencies = [ [[package]] name = "serde" -version = "1.0.198" +version = "1.0.209" source = "registry+https://github.com/rust-lang/crates.io-index" -checksum = "9846a40c979031340571da2545a4e5b7c4163bdae79b301d5f86d03979451fcc" +checksum = "99fce0ffe7310761ca6bf9faf5115afbc19688edd00171d81b1bb1b116c63e09" dependencies = [ "serde_derive", ] @@ -1724,9 +1724,9 @@ dependencies = [ [[package]] name = "serde_derive" -version = "1.0.198" +version = "1.0.209" source = "registry+https://github.com/rust-lang/crates.io-index" -checksum = "e88edab869b01783ba905e7d0153f9fc1a6505a96e4ad3018011eedb838566d9" +checksum = "a5831b979fd7b5439637af1752d535ff49f4860c0f341d1baeb6faf0f4242170" dependencies = [ "proc-macro2", "quote", @@ -1933,18 +1933,18 @@ dependencies = [ [[package]] name = "thiserror" -version = "1.0.58" +version = "1.0.63" source = "registry+https://github.com/rust-lang/crates.io-index" -checksum = "03468839009160513471e86a034bb2c5c0e4baae3b43f79ffc55c4a5427b3297" +checksum = "c0342370b38b6a11b6cc11d6a805569958d54cfa061a29969c3b5ce2ea405724" dependencies = [ "thiserror-impl", ] [[package]] name = "thiserror-impl" -version = "1.0.58" +version = "1.0.63" source = "registry+https://github.com/rust-lang/crates.io-index" -checksum = "c61f3ba182994efc43764a46c018c347bc492c79f024e705f46567b418f6d4f7" +checksum = "a4558b58466b9ad7ca0f102865eccc95938dca1a74a856f2b57b6629050da261" dependencies = [ "proc-macro2", "quote", diff --git a/envs/sandbox.env b/envs/sandbox.env index 6deaafdfaa..4763269a6f 100644 --- a/envs/sandbox.env +++ b/envs/sandbox.env @@ -13,11 +13,10 @@ DENOMS_EXPONENT=6 REWARDING_VALIDATOR_ADDRESS=n1pefc2utwpy5w78p2kqdsfmpjxfwmn9d39k5mqa MIXNET_CONTRACT_ADDRESS=n1xr3rq8yvd7qplsw5yx90ftsr2zdhg4e9z60h5duusgxpv72hud3sjkxkav VESTING_CONTRACT_ADDRESS=n1unyuj8qnmygvzuex3dwmg9yzt9alhvyeat0uu0jedg2wj33efl5qackslz -ECASH_CONTRACT_ADDRESS=n1ljlwey4xdj0zs7zueepc48nkr033fca6fjgvurfvttqegm8dvsrswsul70 -GROUP_CONTRACT_ADDRESS=n10v3rjnq4cjyccfykyams68ztce337gksuu6f0lvtl4meuwvkewaqru4uav -MULTISIG_CONTRACT_ADDRESS=n1cemnu8as0ls45v3caunpesl8jlsfw2ff9rlwnltlecp7zrxct4dsqc2y42 -COCONUT_DKG_CONTRACT_ADDRESS=n1zx96qgd88vqlzcxkpwzks7kqs5ctrx36xtzfc58p7q6c4ng9anlqzc4nh8 - +GROUP_CONTRACT_ADDRESS=n1ewmwz97xm0h8rdk8sw7h9mwn866qkx9hl9zlmagqfkhuzvwk5hhq844ue9 +MULTISIG_CONTRACT_ADDRESS=n1tz0setr8vkh9udp8xyxgpqc89ns27k4d0jx2h942hr0ax63yjhmqz6xct8 +COCONUT_DKG_CONTRACT_ADDRESS=n1v3n2ly2dp3a9ng3ff6rh26yfkn0pc5hed7w2shc5u9ca5c865utqj5elvh +ECASH_CONTRACT_ADDRESS=n1v3vydvs2ued84yv3khqwtgldmgwn0elljsdh08dr5s2j9x4rc5fs9jlwz9 STATISTICS_SERVICE_DOMAIN_ADDRESS="http://0.0.0.0" EXPLORER_API=https://sandbox-explorer.nymtech.net/api diff --git a/nym-api/nym-api-requests/Cargo.toml b/nym-api/nym-api-requests/Cargo.toml index ca647160e7..8549c073eb 100644 --- a/nym-api/nym-api-requests/Cargo.toml +++ b/nym-api/nym-api-requests/Cargo.toml @@ -25,7 +25,7 @@ sha2 = "0.10.8" # for serde on secp256k1 signatures ecdsa = { workspace = true, features = ["serde"] } -nym-serde-helpers = { path = "../../common/serde-helpers", features = ["bs58", "base64"] } +nym-serde-helpers = { path = "../../common/serde-helpers", features = ["bs58", "base64", "date"] } nym-credentials-interface = { path = "../../common/credentials-interface" } nym-crypto = { path = "../../common/crypto", features = ["serde", "asymmetric"] } diff --git a/nym-api/nym-api-requests/src/helpers.rs b/nym-api/nym-api-requests/src/helpers.rs index dc2a28c1f5..651030fc74 100644 --- a/nym-api/nym-api-requests/src/helpers.rs +++ b/nym-api/nym-api-requests/src/helpers.rs @@ -2,27 +2,19 @@ // SPDX-License-Identifier: Apache-2.0 use schemars::JsonSchema; -use time::format_description::{modifier, BorrowedFormatItem, Component}; use time::OffsetDateTime; // just to have something, even if not accurate to generate the swagger docs #[derive(JsonSchema)] pub struct PlaceholderJsonSchemaImpl {} -const DATE_FORMAT: &[BorrowedFormatItem<'_>] = &[ - BorrowedFormatItem::Component(Component::Year(modifier::Year::default())), - BorrowedFormatItem::Literal(b"-"), - BorrowedFormatItem::Component(Component::Month(modifier::Month::default())), - BorrowedFormatItem::Literal(b"-"), - BorrowedFormatItem::Component(Component::Day(modifier::Day::default())), -]; - pub(crate) const fn unix_epoch() -> OffsetDateTime { OffsetDateTime::UNIX_EPOCH } pub(crate) mod overengineered_offset_date_time_serde { - use crate::helpers::{unix_epoch, DATE_FORMAT}; + use crate::helpers::unix_epoch; + use nym_serde_helpers::date::DATE_FORMAT; use serde::de::Visitor; use serde::ser::Error; use serde::{Deserializer, Serialize, Serializer}; @@ -112,30 +104,5 @@ pub(crate) mod overengineered_offset_date_time_serde { } } -pub(crate) mod date_serde { - use crate::helpers::DATE_FORMAT; - use serde::ser::Error; - use serde::{de, Deserialize, Deserializer, Serialize, Serializer}; - use time::Date; - - pub(crate) fn deserialize<'de, D>(deserializer: D) -> Result - where - D: Deserializer<'de>, - { - let s = String::deserialize(deserializer)?; - - Date::parse(&s, DATE_FORMAT).map_err(de::Error::custom) - } - - pub(crate) fn serialize(datetime: &Date, serializer: S) -> Result - where - S: Serializer, - { - // serialize it with human-readable format for compatibility with eclipse and nutella clients - // in the future change it back to rfc3339 - datetime - .format(&DATE_FORMAT) - .map_err(S::Error::custom)? - .serialize(serializer) - } -} +// reimport the module to not break existing imports +pub(crate) use nym_serde_helpers::date as date_serde; diff --git a/nym-api/src/ecash/comm.rs b/nym-api/src/ecash/comm.rs index 20941c484c..a539cb12c2 100644 --- a/nym-api/src/ecash/comm.rs +++ b/nym-api/src/ecash/comm.rs @@ -42,7 +42,7 @@ impl CachedEpoch { self.valid_until > OffsetDateTime::now_utc() } - async fn update(&mut self, epoch: Epoch) -> Result<()> { + fn update(&mut self, epoch: Epoch) -> Result<()> { let now = OffsetDateTime::now_utc(); let validity_duration = if let Some(epoch_finish) = epoch.deadline { @@ -85,7 +85,7 @@ impl QueryCommunicationChannel { let epoch = ecash::client::Client::get_current_epoch(&self.nyxd_client).await?; - guard.update(epoch).await?; + guard.update(epoch)?; Ok(guard) } } diff --git a/nym-wallet/Cargo.lock b/nym-wallet/Cargo.lock index 7117b38868..e905f79d5f 100644 --- a/nym-wallet/Cargo.lock +++ b/nym-wallet/Cargo.lock @@ -3355,6 +3355,7 @@ dependencies = [ "base64 0.22.1", "bs58", "serde", + "time", ] [[package]] diff --git a/service-providers/authenticator/src/cli/ecash/import_coin_index_signatures.rs b/service-providers/authenticator/src/cli/ecash/import_coin_index_signatures.rs new file mode 100644 index 0000000000..c3b1aa922e --- /dev/null +++ b/service-providers/authenticator/src/cli/ecash/import_coin_index_signatures.rs @@ -0,0 +1,16 @@ +// Copyright 2024 - Nym Technologies SA +// SPDX-License-Identifier: Apache-2.0 + +use crate::cli::CliAuthenticatorClient; +use nym_authenticator::error::AuthenticatorError; +use nym_client_core::cli_helpers::client_import_coin_index_signatures::{ + import_coin_index_signatures, CommonClientImportCoinIndexSignaturesArgs, +}; + +pub(crate) async fn execute( + args: CommonClientImportCoinIndexSignaturesArgs, +) -> Result<(), AuthenticatorError> { + import_coin_index_signatures::(args).await?; + println!("successfully imported coin index signatures!"); + Ok(()) +} diff --git a/service-providers/authenticator/src/cli/import_credential.rs b/service-providers/authenticator/src/cli/ecash/import_credential.rs similarity index 69% rename from service-providers/authenticator/src/cli/import_credential.rs rename to service-providers/authenticator/src/cli/ecash/import_credential.rs index 808a1c0363..e525eac518 100644 --- a/service-providers/authenticator/src/cli/import_credential.rs +++ b/service-providers/authenticator/src/cli/ecash/import_credential.rs @@ -4,12 +4,10 @@ use crate::cli::CliAuthenticatorClient; use nym_authenticator::error::AuthenticatorError; use nym_client_core::cli_helpers::client_import_credential::{ - import_credential, CommonClientImportCredentialArgs, + import_credential, CommonClientImportTicketBookArgs, }; -pub(crate) async fn execute( - args: CommonClientImportCredentialArgs, -) -> Result<(), AuthenticatorError> { +pub async fn execute(args: CommonClientImportTicketBookArgs) -> Result<(), AuthenticatorError> { import_credential::(args).await?; println!("successfully imported credential!"); Ok(()) diff --git a/service-providers/authenticator/src/cli/ecash/import_expiration_date_signatures.rs b/service-providers/authenticator/src/cli/ecash/import_expiration_date_signatures.rs new file mode 100644 index 0000000000..7db61d5238 --- /dev/null +++ b/service-providers/authenticator/src/cli/ecash/import_expiration_date_signatures.rs @@ -0,0 +1,16 @@ +// Copyright 2024 - Nym Technologies SA +// SPDX-License-Identifier: Apache-2.0 + +use crate::cli::CliAuthenticatorClient; +use nym_authenticator::error::AuthenticatorError; +use nym_client_core::cli_helpers::client_import_expiration_date_signatures::{ + import_expiration_date_signatures, CommonClientImportExpirationDateSignaturesArgs, +}; + +pub(crate) async fn execute( + args: CommonClientImportExpirationDateSignaturesArgs, +) -> Result<(), AuthenticatorError> { + import_expiration_date_signatures::(args).await?; + println!("successfully imported expiration date signatures!"); + Ok(()) +} diff --git a/service-providers/authenticator/src/cli/ecash/import_master_verification_key.rs b/service-providers/authenticator/src/cli/ecash/import_master_verification_key.rs new file mode 100644 index 0000000000..d53ddacf4c --- /dev/null +++ b/service-providers/authenticator/src/cli/ecash/import_master_verification_key.rs @@ -0,0 +1,16 @@ +// Copyright 2024 - Nym Technologies SA +// SPDX-License-Identifier: Apache-2.0 + +use crate::cli::CliAuthenticatorClient; +use nym_authenticator::error::AuthenticatorError; +use nym_client_core::cli_helpers::client_import_master_verification_key::{ + import_master_verification_key, CommonClientImportMasterVerificationKeyArgs, +}; + +pub(crate) async fn execute( + args: CommonClientImportMasterVerificationKeyArgs, +) -> Result<(), AuthenticatorError> { + import_master_verification_key::(args).await?; + println!("successfully imported master verification key!"); + Ok(()) +} diff --git a/service-providers/authenticator/src/cli/ecash/mod.rs b/service-providers/authenticator/src/cli/ecash/mod.rs new file mode 100644 index 0000000000..9272ed013c --- /dev/null +++ b/service-providers/authenticator/src/cli/ecash/mod.rs @@ -0,0 +1,59 @@ +// Copyright 2024 - Nym Technologies SA +// SPDX-License-Identifier: Apache-2.0 + +use clap::{Args, Subcommand}; +use nym_authenticator::error::AuthenticatorError; +use nym_client_core::cli_helpers::client_import_coin_index_signatures::CommonClientImportCoinIndexSignaturesArgs; +use nym_client_core::cli_helpers::client_import_credential::CommonClientImportTicketBookArgs; +use nym_client_core::cli_helpers::client_import_expiration_date_signatures::CommonClientImportExpirationDateSignaturesArgs; +use nym_client_core::cli_helpers::client_import_master_verification_key::CommonClientImportMasterVerificationKeyArgs; + +pub(crate) mod import_coin_index_signatures; +pub(crate) mod import_credential; +pub(crate) mod import_expiration_date_signatures; +pub(crate) mod import_master_verification_key; +pub(crate) mod show_ticketbooks; + +#[derive(Args)] +#[clap(args_conflicts_with_subcommands = true, subcommand_required = true)] +pub struct Ecash { + #[clap(subcommand)] + pub command: EcashCommands, +} + +impl Ecash { + pub async fn execute(self) -> Result<(), AuthenticatorError> { + match self.command { + EcashCommands::ShowTicketBooks(args) => show_ticketbooks::execute(args).await?, + EcashCommands::ImportTicketBook(args) => import_credential::execute(args).await?, + EcashCommands::ImportCoinIndexSignatures(args) => { + import_coin_index_signatures::execute(args).await? + } + EcashCommands::ImportExpirationDateSignatures(args) => { + import_expiration_date_signatures::execute(args).await? + } + EcashCommands::ImportMasterVerificationKey(args) => { + import_master_verification_key::execute(args).await? + } + } + Ok(()) + } +} + +#[derive(Subcommand)] +pub enum EcashCommands { + /// Display information associated with the imported ticketbooks, + ShowTicketBooks(show_ticketbooks::Args), + + /// Import a pre-generated ticketbook + ImportTicketBook(CommonClientImportTicketBookArgs), + + /// Import coin index signatures needed for ticketbooks + ImportCoinIndexSignatures(CommonClientImportCoinIndexSignaturesArgs), + + /// Import expiration date signatures needed for ticketbooks + ImportExpirationDateSignatures(CommonClientImportExpirationDateSignaturesArgs), + + /// Import master verification key needed for ticketbooks + ImportMasterVerificationKey(CommonClientImportMasterVerificationKeyArgs), +} diff --git a/service-providers/authenticator/src/cli/ecash/show_ticketbooks.rs b/service-providers/authenticator/src/cli/ecash/show_ticketbooks.rs new file mode 100644 index 0000000000..ca31d39802 --- /dev/null +++ b/service-providers/authenticator/src/cli/ecash/show_ticketbooks.rs @@ -0,0 +1,32 @@ +// Copyright 2024 - Nym Technologies SA +// SPDX-License-Identifier: Apache-2.0 + +use crate::cli::CliAuthenticatorClient; +use nym_authenticator::error::AuthenticatorError; +use nym_bin_common::output_format::OutputFormat; +use nym_client_core::cli_helpers::client_show_ticketbooks::{ + show_ticketbooks, CommonShowTicketbooksArgs, +}; + +#[derive(clap::Args)] +pub(crate) struct Args { + #[command(flatten)] + common_args: CommonShowTicketbooksArgs, + + #[arg(short, long, default_value_t = OutputFormat::default())] + output: OutputFormat, +} + +impl AsRef for Args { + fn as_ref(&self) -> &CommonShowTicketbooksArgs { + &self.common_args + } +} + +pub(crate) async fn execute(args: Args) -> Result<(), AuthenticatorError> { + let output = args.output; + let res = show_ticketbooks::(args).await?; + + println!("{}", output.format(&res)); + Ok(()) +} diff --git a/service-providers/authenticator/src/cli/mod.rs b/service-providers/authenticator/src/cli/mod.rs index 685ff62da3..22c88b2710 100644 --- a/service-providers/authenticator/src/cli/mod.rs +++ b/service-providers/authenticator/src/cli/mod.rs @@ -1,6 +1,7 @@ // Copyright 2024 - Nym Technologies SA // SPDX-License-Identifier: Apache-2.0 +use crate::cli::ecash::Ecash; use clap::{CommandFactory, Parser, Subcommand}; use log::error; use nym_authenticator::{ @@ -9,13 +10,12 @@ use nym_authenticator::{ }; use nym_bin_common::completions::{fig_generate, ArgShell}; use nym_bin_common::{bin_info, version_checker}; -use nym_client_core::cli_helpers::client_import_credential::CommonClientImportCredentialArgs; use nym_client_core::cli_helpers::CliClient; use std::sync::OnceLock; mod add_gateway; mod build_info; -mod import_credential; +pub mod ecash; mod init; mod list_gateways; mod peer_handler; @@ -69,8 +69,8 @@ pub(crate) enum Commands { /// parameters. Run(run::Run), - /// Import a pre-generated credential - ImportCredential(CommonClientImportCredentialArgs), + /// Ecash-related functionalities + Ecash(Ecash), /// List all registered with gateways ListGateways(list_gateways::Args), @@ -127,7 +127,7 @@ pub(crate) async fn execute(args: Cli) -> Result<(), AuthenticatorError> { match args.command { Commands::Init(m) => init::execute(m).await?, Commands::Run(m) => run::execute(&m).await?, - Commands::ImportCredential(m) => import_credential::execute(m).await?, + Commands::Ecash(ecash) => ecash.execute().await?, Commands::ListGateways(args) => list_gateways::execute(args).await?, Commands::AddGateway(args) => add_gateway::execute(args).await?, Commands::SwitchGateway(args) => switch_gateway::execute(args).await?, diff --git a/service-providers/ip-packet-router/src/cli/ecash/import_coin_index_signatures.rs b/service-providers/ip-packet-router/src/cli/ecash/import_coin_index_signatures.rs new file mode 100644 index 0000000000..9ffe5439fa --- /dev/null +++ b/service-providers/ip-packet-router/src/cli/ecash/import_coin_index_signatures.rs @@ -0,0 +1,17 @@ +// Copyright 2024 - Nym Technologies SA +// SPDX-License-Identifier: Apache-2.0 + +use crate::cli::CliIpPacketRouterClient; +use crate::error::ClientError; +use nym_client_core::cli_helpers::client_import_coin_index_signatures::{ + import_coin_index_signatures, CommonClientImportCoinIndexSignaturesArgs, +}; +use nym_ip_packet_router::error::IpPacketRouterError; + +pub(crate) async fn execute( + args: CommonClientImportCoinIndexSignaturesArgs, +) -> Result<(), IpPacketRouterError> { + import_coin_index_signatures::(args).await?; + println!("successfully imported coin index signatures!"); + Ok(()) +} diff --git a/service-providers/ip-packet-router/src/cli/import_credential.rs b/service-providers/ip-packet-router/src/cli/ecash/import_credential.rs similarity index 69% rename from service-providers/ip-packet-router/src/cli/import_credential.rs rename to service-providers/ip-packet-router/src/cli/ecash/import_credential.rs index 3c5fd47e56..d37a8fa066 100644 --- a/service-providers/ip-packet-router/src/cli/import_credential.rs +++ b/service-providers/ip-packet-router/src/cli/ecash/import_credential.rs @@ -3,13 +3,11 @@ use crate::cli::CliIpPacketRouterClient; use nym_client_core::cli_helpers::client_import_credential::{ - import_credential, CommonClientImportCredentialArgs, + import_credential, CommonClientImportTicketBookArgs, }; use nym_ip_packet_router::error::IpPacketRouterError; -pub(crate) async fn execute( - args: CommonClientImportCredentialArgs, -) -> Result<(), IpPacketRouterError> { +pub async fn execute(args: CommonClientImportTicketBookArgs) -> Result<(), IpPacketRouterError> { import_credential::(args).await?; println!("successfully imported credential!"); Ok(()) diff --git a/service-providers/ip-packet-router/src/cli/ecash/import_expiration_date_signatures.rs b/service-providers/ip-packet-router/src/cli/ecash/import_expiration_date_signatures.rs new file mode 100644 index 0000000000..7c338d05cb --- /dev/null +++ b/service-providers/ip-packet-router/src/cli/ecash/import_expiration_date_signatures.rs @@ -0,0 +1,16 @@ +// Copyright 2024 - Nym Technologies SA +// SPDX-License-Identifier: Apache-2.0 + +use crate::cli::CliIpPacketRouterClient; +use nym_client_core::cli_helpers::client_import_expiration_date_signatures::{ + import_expiration_date_signatures, CommonClientImportExpirationDateSignaturesArgs, +}; +use nym_ip_packet_router::error::IpPacketRouterError; + +pub(crate) async fn execute( + args: CommonClientImportExpirationDateSignaturesArgs, +) -> Result<(), IpPacketRouterError> { + import_expiration_date_signatures::(args).await?; + println!("successfully imported expiration date signatures!"); + Ok(()) +} diff --git a/service-providers/ip-packet-router/src/cli/ecash/import_master_verification_key.rs b/service-providers/ip-packet-router/src/cli/ecash/import_master_verification_key.rs new file mode 100644 index 0000000000..654be2ea18 --- /dev/null +++ b/service-providers/ip-packet-router/src/cli/ecash/import_master_verification_key.rs @@ -0,0 +1,16 @@ +// Copyright 2024 - Nym Technologies SA +// SPDX-License-Identifier: Apache-2.0 + +use crate::cli::CliIpPacketRouterClient; +use nym_client_core::cli_helpers::client_import_master_verification_key::{ + import_master_verification_key, CommonClientImportMasterVerificationKeyArgs, +}; +use nym_ip_packet_router::error::IpPacketRouterError; + +pub(crate) async fn execute( + args: CommonClientImportMasterVerificationKeyArgs, +) -> Result<(), IpPacketRouterError> { + import_master_verification_key::(args).await?; + println!("successfully imported master verification key!"); + Ok(()) +} diff --git a/service-providers/ip-packet-router/src/cli/ecash/mod.rs b/service-providers/ip-packet-router/src/cli/ecash/mod.rs new file mode 100644 index 0000000000..b0c7ca0ba9 --- /dev/null +++ b/service-providers/ip-packet-router/src/cli/ecash/mod.rs @@ -0,0 +1,61 @@ +// Copyright 2024 - Nym Technologies SA +// SPDX-License-Identifier: Apache-2.0 + +use clap::{Args, Subcommand}; +use nym_client_core::cli_helpers::client_import_coin_index_signatures::CommonClientImportCoinIndexSignaturesArgs; +use nym_client_core::cli_helpers::client_import_credential::CommonClientImportTicketBookArgs; +use nym_client_core::cli_helpers::client_import_expiration_date_signatures::CommonClientImportExpirationDateSignaturesArgs; +use nym_client_core::cli_helpers::client_import_master_verification_key::CommonClientImportMasterVerificationKeyArgs; +use std::error::Error; + +pub(crate) mod import_coin_index_signatures; +pub(crate) mod import_credential; +pub mod import_credential; +pub(crate) mod import_expiration_date_signatures; +pub(crate) mod import_master_verification_key; +pub(crate) mod show_ticketbooks; +pub mod show_ticketbooks; + +#[derive(Args)] +#[clap(args_conflicts_with_subcommands = true, subcommand_required = true)] +pub struct Ecash { + #[clap(subcommand)] + pub command: EcashCommands, +} + +impl Ecash { + pub async fn execute(self) -> Result<(), Box> { + match self.command { + EcashCommands::ShowTicketBooks(args) => show_ticketbooks::execute(args).await?, + EcashCommands::ImportTicketBook(args) => import_credential::execute(args).await?, + EcashCommands::ImportCoinIndexSignatures(args) => { + import_coin_index_signatures::execute(args).await? + } + EcashCommands::ImportExpirationDateSignatures(args) => { + import_expiration_date_signatures::execute(args).await? + } + EcashCommands::ImportMasterVerificationKey(args) => { + import_master_verification_key::execute(args).await? + } + } + Ok(()) + } +} + +#[derive(Subcommand)] +pub enum EcashCommands { + /// Display information associated with the imported ticketbooks, + ShowTicketBooks(show_ticketbooks::Args), + + /// Import a pre-generated ticketbook + ImportTicketBook(CommonClientImportTicketBookArgs), + + /// Import coin index signatures needed for ticketbooks + ImportCoinIndexSignatures(CommonClientImportCoinIndexSignaturesArgs), + + /// Import expiration date signatures needed for ticketbooks + ImportExpirationDateSignatures(CommonClientImportExpirationDateSignaturesArgs), + + /// Import master verification key needed for ticketbooks + ImportMasterVerificationKey(CommonClientImportMasterVerificationKeyArgs), +} diff --git a/service-providers/ip-packet-router/src/cli/show_ticketbooks.rs b/service-providers/ip-packet-router/src/cli/ecash/show_ticketbooks.rs similarity index 89% rename from service-providers/ip-packet-router/src/cli/show_ticketbooks.rs rename to service-providers/ip-packet-router/src/cli/ecash/show_ticketbooks.rs index 20c58a412c..b3abea30f7 100644 --- a/service-providers/ip-packet-router/src/cli/show_ticketbooks.rs +++ b/service-providers/ip-packet-router/src/cli/ecash/show_ticketbooks.rs @@ -9,7 +9,7 @@ use nym_client_core::cli_helpers::client_show_ticketbooks::{ use nym_ip_packet_router::error::IpPacketRouterError; #[derive(clap::Args)] -pub(crate) struct Args { +pub struct Args { #[command(flatten)] common_args: CommonShowTicketbooksArgs, @@ -23,7 +23,7 @@ impl AsRef for Args { } } -pub(crate) async fn execute(args: Args) -> Result<(), IpPacketRouterError> { +pub async fn execute(args: Args) -> Result<(), IpPacketRouterError> { let output = args.output; let res = show_ticketbooks::(args).await?; diff --git a/service-providers/ip-packet-router/src/cli/mod.rs b/service-providers/ip-packet-router/src/cli/mod.rs index d269d5045d..fb47e4c09f 100644 --- a/service-providers/ip-packet-router/src/cli/mod.rs +++ b/service-providers/ip-packet-router/src/cli/mod.rs @@ -1,8 +1,9 @@ +use crate::commands::ecash::Ecash; use clap::{CommandFactory, Parser, Subcommand}; use log::error; use nym_bin_common::completions::{fig_generate, ArgShell}; use nym_bin_common::{bin_info, version_checker}; -use nym_client_core::cli_helpers::client_import_credential::CommonClientImportCredentialArgs; +use nym_client_core::cli_helpers::client_import_credential::CommonClientImportTicketBookArgs; use nym_client_core::cli_helpers::CliClient; use nym_ip_packet_router::config::helpers::try_upgrade_config; use nym_ip_packet_router::config::{BaseClientConfig, Config}; @@ -11,11 +12,10 @@ use std::sync::OnceLock; mod add_gateway; mod build_info; -mod import_credential; +pub mod ecash; mod init; mod list_gateways; mod run; -mod show_ticketbooks; mod sign; mod switch_gateway; @@ -65,8 +65,8 @@ pub(crate) enum Commands { /// parameters. Run(run::Run), - /// Import a pre-generated credential - ImportCredential(CommonClientImportCredentialArgs), + /// Ecash-related functionalities + Ecash(Ecash), /// List all registered with gateways ListGateways(list_gateways::Args), @@ -132,11 +132,10 @@ pub(crate) async fn execute(args: Cli) -> Result<(), IpPacketRouterError> { match args.command { Commands::Init(m) => init::execute(m).await?, Commands::Run(m) => run::execute(&m).await?, - Commands::ImportCredential(m) => import_credential::execute(m).await?, + Commands::Ecash(ecash) => ecash.execute().await?, Commands::ListGateways(args) => list_gateways::execute(args).await?, Commands::AddGateway(args) => add_gateway::execute(args).await?, Commands::SwitchGateway(args) => switch_gateway::execute(args).await?, - Commands::ShowTicketbooks(args) => show_ticketbooks::execute(args).await?, Commands::Sign(m) => sign::execute(&m).await?, Commands::BuildInfo(m) => build_info::execute(m), Commands::Completions(s) => s.generate(&mut Cli::command(), bin_name), diff --git a/service-providers/network-requester/src/cli/ecash/import_coin_index_signatures.rs b/service-providers/network-requester/src/cli/ecash/import_coin_index_signatures.rs new file mode 100644 index 0000000000..d9fa9aad3c --- /dev/null +++ b/service-providers/network-requester/src/cli/ecash/import_coin_index_signatures.rs @@ -0,0 +1,16 @@ +// Copyright 2024 - Nym Technologies SA +// SPDX-License-Identifier: Apache-2.0 + +use crate::cli::CliNetworkRequesterClient; +use crate::error::NetworkRequesterError; +use nym_client_core::cli_helpers::client_import_coin_index_signatures::{ + import_coin_index_signatures, CommonClientImportCoinIndexSignaturesArgs, +}; + +pub(crate) async fn execute( + args: CommonClientImportCoinIndexSignaturesArgs, +) -> Result<(), NetworkRequesterError> { + import_coin_index_signatures::(args).await?; + println!("successfully imported coin index signatures!"); + Ok(()) +} diff --git a/service-providers/network-requester/src/cli/import_credential.rs b/service-providers/network-requester/src/cli/ecash/import_credential.rs similarity index 69% rename from service-providers/network-requester/src/cli/import_credential.rs rename to service-providers/network-requester/src/cli/ecash/import_credential.rs index 24b999ccd6..28b9e39545 100644 --- a/service-providers/network-requester/src/cli/import_credential.rs +++ b/service-providers/network-requester/src/cli/ecash/import_credential.rs @@ -4,12 +4,10 @@ use crate::cli::CliNetworkRequesterClient; use crate::error::NetworkRequesterError; use nym_client_core::cli_helpers::client_import_credential::{ - import_credential, CommonClientImportCredentialArgs, + import_credential, CommonClientImportTicketBookArgs, }; -pub(crate) async fn execute( - args: CommonClientImportCredentialArgs, -) -> Result<(), NetworkRequesterError> { +pub async fn execute(args: CommonClientImportTicketBookArgs) -> Result<(), NetworkRequesterError> { import_credential::(args).await?; println!("successfully imported credential!"); Ok(()) diff --git a/service-providers/network-requester/src/cli/ecash/import_expiration_date_signatures.rs b/service-providers/network-requester/src/cli/ecash/import_expiration_date_signatures.rs new file mode 100644 index 0000000000..059df07e76 --- /dev/null +++ b/service-providers/network-requester/src/cli/ecash/import_expiration_date_signatures.rs @@ -0,0 +1,16 @@ +// Copyright 2024 - Nym Technologies SA +// SPDX-License-Identifier: Apache-2.0 + +use crate::cli::CliNetworkRequesterClient; +use crate::error::NetworkRequesterError; +use nym_client_core::cli_helpers::client_import_expiration_date_signatures::{ + import_expiration_date_signatures, CommonClientImportExpirationDateSignaturesArgs, +}; + +pub(crate) async fn execute( + args: CommonClientImportExpirationDateSignaturesArgs, +) -> Result<(), NetworkRequesterError> { + import_expiration_date_signatures::(args).await?; + println!("successfully imported expiration date signatures!"); + Ok(()) +} diff --git a/service-providers/network-requester/src/cli/ecash/import_master_verification_key.rs b/service-providers/network-requester/src/cli/ecash/import_master_verification_key.rs new file mode 100644 index 0000000000..4283291b76 --- /dev/null +++ b/service-providers/network-requester/src/cli/ecash/import_master_verification_key.rs @@ -0,0 +1,16 @@ +// Copyright 2024 - Nym Technologies SA +// SPDX-License-Identifier: Apache-2.0 + +use crate::cli::CliNetworkRequesterClient; +use crate::error::NetworkRequesterError; +use nym_client_core::cli_helpers::client_import_master_verification_key::{ + import_master_verification_key, CommonClientImportMasterVerificationKeyArgs, +}; + +pub(crate) async fn execute( + args: CommonClientImportMasterVerificationKeyArgs, +) -> Result<(), NetworkRequesterError> { + import_master_verification_key::(args).await?; + println!("successfully imported master verification key!"); + Ok(()) +} diff --git a/service-providers/network-requester/src/cli/ecash/mod.rs b/service-providers/network-requester/src/cli/ecash/mod.rs new file mode 100644 index 0000000000..d660cb728f --- /dev/null +++ b/service-providers/network-requester/src/cli/ecash/mod.rs @@ -0,0 +1,59 @@ +// Copyright 2024 - Nym Technologies SA +// SPDX-License-Identifier: Apache-2.0 + +use crate::error::NetworkRequesterError; +use clap::{Args, Subcommand}; +use nym_client_core::cli_helpers::client_import_coin_index_signatures::CommonClientImportCoinIndexSignaturesArgs; +use nym_client_core::cli_helpers::client_import_credential::CommonClientImportTicketBookArgs; +use nym_client_core::cli_helpers::client_import_expiration_date_signatures::CommonClientImportExpirationDateSignaturesArgs; +use nym_client_core::cli_helpers::client_import_master_verification_key::CommonClientImportMasterVerificationKeyArgs; + +pub(crate) mod import_coin_index_signatures; +pub(crate) mod import_credential; +pub(crate) mod import_expiration_date_signatures; +pub(crate) mod import_master_verification_key; +pub(crate) mod show_ticketbooks; + +#[derive(Args)] +#[clap(args_conflicts_with_subcommands = true, subcommand_required = true)] +pub struct Ecash { + #[clap(subcommand)] + pub command: EcashCommands, +} + +impl Ecash { + pub async fn execute(self) -> Result<(), NetworkRequesterError> { + match self.command { + EcashCommands::ShowTicketBooks(args) => show_ticketbooks::execute(args).await?, + EcashCommands::ImportTicketBook(args) => import_credential::execute(args).await?, + EcashCommands::ImportCoinIndexSignatures(args) => { + import_coin_index_signatures::execute(args).await? + } + EcashCommands::ImportExpirationDateSignatures(args) => { + import_expiration_date_signatures::execute(args).await? + } + EcashCommands::ImportMasterVerificationKey(args) => { + import_master_verification_key::execute(args).await? + } + } + Ok(()) + } +} + +#[derive(Subcommand)] +pub enum EcashCommands { + /// Display information associated with the imported ticketbooks, + ShowTicketBooks(show_ticketbooks::Args), + + /// Import a pre-generated ticketbook + ImportTicketBook(CommonClientImportTicketBookArgs), + + /// Import coin index signatures needed for ticketbooks + ImportCoinIndexSignatures(CommonClientImportCoinIndexSignaturesArgs), + + /// Import expiration date signatures needed for ticketbooks + ImportExpirationDateSignatures(CommonClientImportExpirationDateSignaturesArgs), + + /// Import master verification key needed for ticketbooks + ImportMasterVerificationKey(CommonClientImportMasterVerificationKeyArgs), +} diff --git a/service-providers/network-requester/src/cli/show_ticketbooks.rs b/service-providers/network-requester/src/cli/ecash/show_ticketbooks.rs similarity index 100% rename from service-providers/network-requester/src/cli/show_ticketbooks.rs rename to service-providers/network-requester/src/cli/ecash/show_ticketbooks.rs diff --git a/service-providers/network-requester/src/cli/mod.rs b/service-providers/network-requester/src/cli/mod.rs index 11ef00cfd8..750575f2fb 100644 --- a/service-providers/network-requester/src/cli/mod.rs +++ b/service-providers/network-requester/src/cli/mod.rs @@ -1,6 +1,7 @@ // Copyright 2023 - Nym Technologies SA // SPDX-License-Identifier: GPL-3.0-only +use crate::cli::ecash::Ecash; use crate::config::helpers::try_upgrade_config_by_id; use crate::{ config::{BaseClientConfig, Config}, @@ -11,18 +12,16 @@ use log::error; use nym_bin_common::bin_info; use nym_bin_common::completions::{fig_generate, ArgShell}; use nym_bin_common::version_checker; -use nym_client_core::cli_helpers::client_import_credential::CommonClientImportCredentialArgs; use nym_client_core::cli_helpers::CliClient; use nym_config::OptionalSet; use std::sync::OnceLock; mod add_gateway; mod build_info; -mod import_credential; +pub mod ecash; mod init; mod list_gateways; mod run; -mod show_ticketbooks; mod sign; mod switch_gateway; @@ -72,12 +71,12 @@ pub(crate) enum Commands { /// parameters. Run(run::Run), + /// Ecash-related functionalities + Ecash(Ecash), + /// Sign to prove ownership of this network requester Sign(sign::Sign), - /// Import a pre-generated credential - ImportCredential(CommonClientImportCredentialArgs), - /// List all registered with gateways ListGateways(list_gateways::Args), @@ -87,9 +86,6 @@ pub(crate) enum Commands { /// Change the currently active gateway. Note that you must have already registered with the new gateway! SwitchGateway(switch_gateway::Args), - /// Display information associated with the imported ticketbooks, - ShowTicketbooks(show_ticketbooks::Args), - /// Show build information of this binary BuildInfo(build_info::BuildInfo), @@ -151,12 +147,11 @@ pub(crate) async fn execute(args: Cli) -> Result<(), NetworkRequesterError> { match args.command { Commands::Init(m) => init::execute(m).await?, Commands::Run(m) => run::execute(&m).await?, + Commands::Ecash(ecash) => ecash.execute().await?, Commands::Sign(m) => sign::execute(&m).await?, - Commands::ImportCredential(m) => import_credential::execute(m).await?, Commands::ListGateways(args) => list_gateways::execute(args).await?, Commands::AddGateway(args) => add_gateway::execute(args).await?, Commands::SwitchGateway(args) => switch_gateway::execute(args).await?, - Commands::ShowTicketbooks(args) => show_ticketbooks::execute(args).await?, Commands::BuildInfo(m) => build_info::execute(m), Commands::Completions(s) => s.generate(&mut Cli::command(), bin_name), Commands::GenerateFigSpec => fig_generate(&mut Cli::command(), bin_name), diff --git a/tools/nym-cli/src/coconut/mod.rs b/tools/nym-cli/src/coconut/mod.rs index 6fda72e6a0..ccf0836d05 100644 --- a/tools/nym-cli/src/coconut/mod.rs +++ b/tools/nym-cli/src/coconut/mod.rs @@ -1,28 +1,38 @@ use nym_cli_commands::context::{create_query_client, create_signing_client, ClientArgs}; +use nym_cli_commands::ecash::EcashCommands; use nym_network_defaults::NymNetworkDetails; pub(crate) async fn execute( global_args: ClientArgs, - coconut: nym_cli_commands::coconut::Ecash, + coconut: nym_cli_commands::ecash::Ecash, network_details: &NymNetworkDetails, ) -> anyhow::Result<()> { match coconut.command { - nym_cli_commands::coconut::EcashCommands::IssueTicketBook(args) => { - nym_cli_commands::coconut::issue_ticket_book::execute( + EcashCommands::IssueTicketBook(args) => { + nym_cli_commands::ecash::issue_ticket_book::execute( args, create_signing_client(global_args, network_details)?, ) .await? } - nym_cli_commands::coconut::EcashCommands::RecoverTicketBook(args) => { - nym_cli_commands::coconut::recover_ticket_book::execute( + EcashCommands::RecoverTicketBook(args) => { + nym_cli_commands::ecash::recover_ticket_book::execute( args, create_query_client(network_details)?, ) .await? } - nym_cli_commands::coconut::EcashCommands::ImportTicketBook(args) => { - nym_cli_commands::coconut::import_ticket_book::execute(args).await? + EcashCommands::ImportTicketBook(args) => { + nym_cli_commands::ecash::import_ticket_book::execute(args).await? + } + EcashCommands::ImportCoinIndexSignatures(args) => { + nym_cli_commands::ecash::import_coin_index_signatures::execute(args).await? + } + EcashCommands::ImportExpirationDateSignatures(args) => { + nym_cli_commands::ecash::import_expiration_date_signatures::execute(args).await? + } + EcashCommands::ImportMasterVerificationKey(args) => { + nym_cli_commands::ecash::import_master_verification_key::execute(args).await? } } Ok(()) diff --git a/tools/nym-cli/src/main.rs b/tools/nym-cli/src/main.rs index 12defe4817..a7255ab9a9 100644 --- a/tools/nym-cli/src/main.rs +++ b/tools/nym-cli/src/main.rs @@ -63,7 +63,7 @@ pub(crate) enum Commands { /// Sign and verify messages Signature(nym_cli_commands::validator::signature::Signature), /// Ecash related stuff - Ecash(nym_cli_commands::coconut::Ecash), + Ecash(nym_cli_commands::ecash::Ecash), /// Query chain blocks Block(nym_cli_commands::validator::block::Block), /// Manage and execute WASM smart contracts diff --git a/tools/nym-id-cli/src/commands/import_credential.rs b/tools/nym-id-cli/src/commands/import_credential.rs index e04bb89af5..340981006f 100644 --- a/tools/nym-id-cli/src/commands/import_credential.rs +++ b/tools/nym-id-cli/src/commands/import_credential.rs @@ -2,7 +2,7 @@ // SPDX-License-Identifier: Apache-2.0 use clap::ArgGroup; -use nym_id::import_credential; +use nym_id::import_standalone_ticketbook; use std::fs; use std::path::PathBuf; @@ -43,6 +43,6 @@ pub(crate) async fn execute(args: Args) -> anyhow::Result<()> { } }; - import_credential(credentials_store, raw_credential, args.version).await?; + import_standalone_ticketbook(credentials_store, raw_credential, args.version).await?; Ok(()) } From 052dbeaef8253d7321d82f24b2de7ff9480aaacc Mon Sep 17 00:00:00 2001 From: =?UTF-8?q?J=C4=99drzej=20Stuczy=C5=84ski?= Date: Fri, 30 Aug 2024 18:35:02 +0100 Subject: [PATCH 65/93] adjusting the API and fixing CI --- .../commands/src/ecash/issue_ticket_book.rs | 6 +-- .../src/ecash/bandwidth/importable.rs | 44 ++++++++++++++++--- .../cli/ecash/import_coin_index_signatures.rs | 1 - .../ip-packet-router/src/cli/ecash/mod.rs | 1 - .../ip-packet-router/src/cli/mod.rs | 5 +-- 5 files changed, 41 insertions(+), 16 deletions(-) diff --git a/common/commands/src/ecash/issue_ticket_book.rs b/common/commands/src/ecash/issue_ticket_book.rs index 015522b016..28e8c3eafc 100644 --- a/common/commands/src/ecash/issue_ticket_book.rs +++ b/common/commands/src/ecash/issue_ticket_book.rs @@ -123,7 +123,7 @@ async fn issue_to_file(args: Args, client: SigningClient) -> anyhow::Result<()> .await? .ok_or(anyhow!("missing expiration date signatures!"))?; - exported.with_expiration_date_signatures(&AggregatedExpirationDateSignatures { + exported = exported.with_expiration_date_signatures(&AggregatedExpirationDateSignatures { epoch_id, expiration_date, signatures, @@ -135,7 +135,7 @@ async fn issue_to_file(args: Args, client: SigningClient) -> anyhow::Result<()> .get_coin_index_signatures(epoch_id) .await? .ok_or(anyhow!("missing coin index signatures!"))?; - exported.with_coin_index_signatures(&AggregatedCoinIndicesSignatures { + exported = exported.with_coin_index_signatures(&AggregatedCoinIndicesSignatures { epoch_id, signatures, }); @@ -147,7 +147,7 @@ async fn issue_to_file(args: Args, client: SigningClient) -> anyhow::Result<()> .await? .ok_or(anyhow!("missing master verification key!"))?; - exported.with_master_verification_key(&EpochVerificationKey { epoch_id, key }); + exported = exported.with_master_verification_key(&EpochVerificationKey { epoch_id, key }); } let data = exported.pack().data; diff --git a/common/credentials/src/ecash/bandwidth/importable.rs b/common/credentials/src/ecash/bandwidth/importable.rs index a1f9ac099e..1765248faa 100644 --- a/common/credentials/src/ecash/bandwidth/importable.rs +++ b/common/credentials/src/ecash/bandwidth/importable.rs @@ -53,28 +53,58 @@ impl From for ImportableTicketBook { impl ImportableTicketBook { pub fn with_expiration_date_signatures( - &mut self, + mut self, signatures: &AggregatedExpirationDateSignatures, - ) -> &mut Self { + ) -> Self { self.serialised_expiration_date_signatures = Some(signatures.pack()); self } pub fn with_coin_index_signatures( - &mut self, + mut self, signatures: &AggregatedCoinIndicesSignatures, - ) -> &mut Self { + ) -> Self { self.serialised_coin_index_signatures = Some(signatures.pack()); self } - pub fn with_master_verification_key(&mut self, key: &EpochVerificationKey) -> &mut Self { + pub fn with_master_verification_key(mut self, key: &EpochVerificationKey) -> Self { self.serialised_master_verification_key = Some(key.pack()); self } - pub fn finalize_export(self) -> Vec { - self.pack().data + pub fn with_maybe_expiration_date_signatures( + self, + signatures: &Option, + ) -> Self { + if let Some(sigs) = signatures { + self.with_expiration_date_signatures(sigs) + } else { + self + } + } + + pub fn with_maybe_coin_index_signatures( + self, + signatures: &Option, + ) -> Self { + if let Some(sigs) = signatures { + self.with_coin_index_signatures(sigs) + } else { + self + } + } + + pub fn with_maybe_master_verification_key(self, key: &Option) -> Self { + if let Some(sigs) = key { + self.with_master_verification_key(sigs) + } else { + self + } + } + + pub fn finalize_export(self) -> VersionSerialised { + self.pack() } pub fn try_unpack_full(&self) -> Result { diff --git a/service-providers/ip-packet-router/src/cli/ecash/import_coin_index_signatures.rs b/service-providers/ip-packet-router/src/cli/ecash/import_coin_index_signatures.rs index 9ffe5439fa..a06f9e70b8 100644 --- a/service-providers/ip-packet-router/src/cli/ecash/import_coin_index_signatures.rs +++ b/service-providers/ip-packet-router/src/cli/ecash/import_coin_index_signatures.rs @@ -2,7 +2,6 @@ // SPDX-License-Identifier: Apache-2.0 use crate::cli::CliIpPacketRouterClient; -use crate::error::ClientError; use nym_client_core::cli_helpers::client_import_coin_index_signatures::{ import_coin_index_signatures, CommonClientImportCoinIndexSignaturesArgs, }; diff --git a/service-providers/ip-packet-router/src/cli/ecash/mod.rs b/service-providers/ip-packet-router/src/cli/ecash/mod.rs index b0c7ca0ba9..500f0666c5 100644 --- a/service-providers/ip-packet-router/src/cli/ecash/mod.rs +++ b/service-providers/ip-packet-router/src/cli/ecash/mod.rs @@ -10,7 +10,6 @@ use std::error::Error; pub(crate) mod import_coin_index_signatures; pub(crate) mod import_credential; -pub mod import_credential; pub(crate) mod import_expiration_date_signatures; pub(crate) mod import_master_verification_key; pub(crate) mod show_ticketbooks; diff --git a/service-providers/ip-packet-router/src/cli/mod.rs b/service-providers/ip-packet-router/src/cli/mod.rs index fb47e4c09f..6a0a9ed19b 100644 --- a/service-providers/ip-packet-router/src/cli/mod.rs +++ b/service-providers/ip-packet-router/src/cli/mod.rs @@ -1,4 +1,4 @@ -use crate::commands::ecash::Ecash; +use crate::cli::ecash::Ecash; use clap::{CommandFactory, Parser, Subcommand}; use log::error; use nym_bin_common::completions::{fig_generate, ArgShell}; @@ -77,9 +77,6 @@ pub(crate) enum Commands { /// Change the currently active gateway. Note that you must have already registered with the new gateway! SwitchGateway(switch_gateway::Args), - /// Display information associated with the imported ticketbooks, - ShowTicketbooks(show_ticketbooks::Args), - /// Sign to prove ownership of this network requester Sign(sign::Sign), From 27afe645c6e293636afbf1f1f7e3a932b1a8ce12 Mon Sep 17 00:00:00 2001 From: =?UTF-8?q?J=C4=99drzej=20Stuczy=C5=84ski?= Date: Fri, 30 Aug 2024 18:39:10 +0100 Subject: [PATCH 66/93] i hate the ipr build process --- service-providers/ip-packet-router/src/cli/ecash/mod.rs | 4 ++-- service-providers/ip-packet-router/src/cli/mod.rs | 1 - 2 files changed, 2 insertions(+), 3 deletions(-) diff --git a/service-providers/ip-packet-router/src/cli/ecash/mod.rs b/service-providers/ip-packet-router/src/cli/ecash/mod.rs index 500f0666c5..55db810257 100644 --- a/service-providers/ip-packet-router/src/cli/ecash/mod.rs +++ b/service-providers/ip-packet-router/src/cli/ecash/mod.rs @@ -7,13 +7,13 @@ use nym_client_core::cli_helpers::client_import_credential::CommonClientImportTi use nym_client_core::cli_helpers::client_import_expiration_date_signatures::CommonClientImportExpirationDateSignaturesArgs; use nym_client_core::cli_helpers::client_import_master_verification_key::CommonClientImportMasterVerificationKeyArgs; use std::error::Error; +use nym_ip_packet_router::error::IpPacketRouterError; pub(crate) mod import_coin_index_signatures; pub(crate) mod import_credential; pub(crate) mod import_expiration_date_signatures; pub(crate) mod import_master_verification_key; pub(crate) mod show_ticketbooks; -pub mod show_ticketbooks; #[derive(Args)] #[clap(args_conflicts_with_subcommands = true, subcommand_required = true)] @@ -23,7 +23,7 @@ pub struct Ecash { } impl Ecash { - pub async fn execute(self) -> Result<(), Box> { + pub async fn execute(self) -> Result<(), IpPacketRouterError> { match self.command { EcashCommands::ShowTicketBooks(args) => show_ticketbooks::execute(args).await?, EcashCommands::ImportTicketBook(args) => import_credential::execute(args).await?, diff --git a/service-providers/ip-packet-router/src/cli/mod.rs b/service-providers/ip-packet-router/src/cli/mod.rs index 6a0a9ed19b..ee746f48c9 100644 --- a/service-providers/ip-packet-router/src/cli/mod.rs +++ b/service-providers/ip-packet-router/src/cli/mod.rs @@ -3,7 +3,6 @@ use clap::{CommandFactory, Parser, Subcommand}; use log::error; use nym_bin_common::completions::{fig_generate, ArgShell}; use nym_bin_common::{bin_info, version_checker}; -use nym_client_core::cli_helpers::client_import_credential::CommonClientImportTicketBookArgs; use nym_client_core::cli_helpers::CliClient; use nym_ip_packet_router::config::helpers::try_upgrade_config; use nym_ip_packet_router::config::{BaseClientConfig, Config}; From 43b0b3eb375dfdb532cbad3daf8817b4af8b7687 Mon Sep 17 00:00:00 2001 From: =?UTF-8?q?J=C4=99drzej=20Stuczy=C5=84ski?= Date: Fri, 30 Aug 2024 18:42:46 +0100 Subject: [PATCH 67/93] i hate the ipr build process vol2 --- service-providers/ip-packet-router/src/cli/ecash/mod.rs | 2 +- 1 file changed, 1 insertion(+), 1 deletion(-) diff --git a/service-providers/ip-packet-router/src/cli/ecash/mod.rs b/service-providers/ip-packet-router/src/cli/ecash/mod.rs index 55db810257..4e3d0befcd 100644 --- a/service-providers/ip-packet-router/src/cli/ecash/mod.rs +++ b/service-providers/ip-packet-router/src/cli/ecash/mod.rs @@ -6,8 +6,8 @@ use nym_client_core::cli_helpers::client_import_coin_index_signatures::CommonCli use nym_client_core::cli_helpers::client_import_credential::CommonClientImportTicketBookArgs; use nym_client_core::cli_helpers::client_import_expiration_date_signatures::CommonClientImportExpirationDateSignaturesArgs; use nym_client_core::cli_helpers::client_import_master_verification_key::CommonClientImportMasterVerificationKeyArgs; -use std::error::Error; use nym_ip_packet_router::error::IpPacketRouterError; +use std::error::Error; pub(crate) mod import_coin_index_signatures; pub(crate) mod import_credential; From 04a2f59034f4749d76bdda4f26a416642f3bd9f7 Mon Sep 17 00:00:00 2001 From: =?UTF-8?q?J=C4=99drzej=20Stuczy=C5=84ski?= Date: Mon, 2 Sep 2024 09:59:21 +0100 Subject: [PATCH 68/93] fixed clap group names --- .../src/cli_helpers/client_import_coin_index_signatures.rs | 6 +++--- .../cli_helpers/client_import_expiration_date_signatures.rs | 6 +++--- .../cli_helpers/client_import_master_verification_key.rs | 6 +++--- common/commands/src/ecash/import_coin_index_signatures.rs | 6 +++--- .../commands/src/ecash/import_expiration_date_signatures.rs | 6 +++--- common/commands/src/ecash/import_master_verification_key.rs | 6 +++--- 6 files changed, 18 insertions(+), 18 deletions(-) diff --git a/common/client-core/src/cli_helpers/client_import_coin_index_signatures.rs b/common/client-core/src/cli_helpers/client_import_coin_index_signatures.rs index 889c34ab4b..5625250ce3 100644 --- a/common/client-core/src/cli_helpers/client_import_coin_index_signatures.rs +++ b/common/client-core/src/cli_helpers/client_import_coin_index_signatures.rs @@ -13,7 +13,7 @@ fn parse_encoded_signatures_data(raw: &str) -> bs58::decode::Result> { #[cfg_attr(feature = "cli", derive(clap::Args))] #[cfg_attr(feature = "cli", clap( - group(clap::ArgGroup::new("signatures_data").required(true)), + group(clap::ArgGroup::new("sig_data").required(true)), )) ] pub struct CommonClientImportCoinIndexSignaturesArgs { @@ -26,11 +26,11 @@ pub struct CommonClientImportCoinIndexSignaturesArgs { pub(crate) client_config: PathBuf, /// Explicitly provide the encoded signatures data (as base58) - #[cfg_attr(feature = "cli", clap(long, group = "signatures_data", value_parser = parse_encoded_signatures_data))] + #[cfg_attr(feature = "cli", clap(long, group = "sig_data", value_parser = parse_encoded_signatures_data))] pub(crate) signatures_data: Option>, /// Specifies the path to file containing binary signatures data - #[cfg_attr(feature = "cli", clap(long, group = "signatures_data"))] + #[cfg_attr(feature = "cli", clap(long, group = "sig_data"))] pub(crate) signatures_path: Option, // currently hidden as there exists only a single serialization standard diff --git a/common/client-core/src/cli_helpers/client_import_expiration_date_signatures.rs b/common/client-core/src/cli_helpers/client_import_expiration_date_signatures.rs index 7d0a14513a..4dc875e75c 100644 --- a/common/client-core/src/cli_helpers/client_import_expiration_date_signatures.rs +++ b/common/client-core/src/cli_helpers/client_import_expiration_date_signatures.rs @@ -13,7 +13,7 @@ fn parse_encoded_signatures_data(raw: &str) -> bs58::decode::Result> { #[cfg_attr(feature = "cli", derive(clap::Args))] #[cfg_attr(feature = "cli", clap( - group(clap::ArgGroup::new("signatures_data").required(true)), + group(clap::ArgGroup::new("sig_data").required(true)), )) ] pub struct CommonClientImportExpirationDateSignaturesArgs { @@ -26,11 +26,11 @@ pub struct CommonClientImportExpirationDateSignaturesArgs { pub(crate) client_config: PathBuf, /// Explicitly provide the encoded signatures data (as base58) - #[cfg_attr(feature = "cli", clap(long, group = "signatures_data", value_parser = parse_encoded_signatures_data))] + #[cfg_attr(feature = "cli", clap(long, group = "sig_data", value_parser = parse_encoded_signatures_data))] pub(crate) signatures_data: Option>, /// Specifies the path to file containing binary signatures data - #[cfg_attr(feature = "cli", clap(long, group = "signatures_data"))] + #[cfg_attr(feature = "cli", clap(long, group = "sig_data"))] pub(crate) signatures_path: Option, // currently hidden as there exists only a single serialization standard diff --git a/common/client-core/src/cli_helpers/client_import_master_verification_key.rs b/common/client-core/src/cli_helpers/client_import_master_verification_key.rs index 25a3c421f2..b44334b49e 100644 --- a/common/client-core/src/cli_helpers/client_import_master_verification_key.rs +++ b/common/client-core/src/cli_helpers/client_import_master_verification_key.rs @@ -13,7 +13,7 @@ fn parse_encoded_key_data(raw: &str) -> bs58::decode::Result> { #[cfg_attr(feature = "cli", derive(clap::Args))] #[cfg_attr(feature = "cli", clap( - group(clap::ArgGroup::new("key_data").required(true)), + group(clap::ArgGroup::new("key_data_group").required(true)), )) ] pub struct CommonClientImportMasterVerificationKeyArgs { @@ -26,11 +26,11 @@ pub struct CommonClientImportMasterVerificationKeyArgs { pub(crate) client_config: PathBuf, /// Explicitly provide the encoded key data (as base58) - #[cfg_attr(feature = "cli", clap(long, group = "key_data", value_parser = parse_encoded_key_data))] + #[cfg_attr(feature = "cli", clap(long, group = "key_data_group", value_parser = parse_encoded_key_data))] pub(crate) key_data: Option>, /// Specifies the path to file containing binary key data - #[cfg_attr(feature = "cli", clap(long, group = "key_data"))] + #[cfg_attr(feature = "cli", clap(long, group = "key_data_group"))] pub(crate) key_path: Option, // currently hidden as there exists only a single serialization standard diff --git a/common/commands/src/ecash/import_coin_index_signatures.rs b/common/commands/src/ecash/import_coin_index_signatures.rs index 91d12aafbb..8fb746937e 100644 --- a/common/commands/src/ecash/import_coin_index_signatures.rs +++ b/common/commands/src/ecash/import_coin_index_signatures.rs @@ -16,7 +16,7 @@ fn parse_encoded_signatures_data(raw: &str) -> bs58::decode::Result> { #[derive(Debug, Parser)] #[clap( - group(ArgGroup::new("signatures_data").required(true)), + group(ArgGroup::new("sig_data").required(true)), )] pub struct Args { /// Config file of the client that is supposed to use the signatures. @@ -24,11 +24,11 @@ pub struct Args { pub(crate) client_config: PathBuf, /// Explicitly provide the encoded signatures data (as base58) - #[clap(long, group = "signatures_data", value_parser = parse_encoded_signatures_data)] + #[clap(long, group = "sig_data", value_parser = parse_encoded_signatures_data)] pub(crate) signatures_data: Option>, /// Specifies the path to file containing binary signatures data - #[clap(long, group = "signatures_data")] + #[clap(long, group = "sig_data")] pub(crate) signatures_path: Option, // currently hidden as there exists only a single serialization standard diff --git a/common/commands/src/ecash/import_expiration_date_signatures.rs b/common/commands/src/ecash/import_expiration_date_signatures.rs index 91d12aafbb..8fb746937e 100644 --- a/common/commands/src/ecash/import_expiration_date_signatures.rs +++ b/common/commands/src/ecash/import_expiration_date_signatures.rs @@ -16,7 +16,7 @@ fn parse_encoded_signatures_data(raw: &str) -> bs58::decode::Result> { #[derive(Debug, Parser)] #[clap( - group(ArgGroup::new("signatures_data").required(true)), + group(ArgGroup::new("sig_data").required(true)), )] pub struct Args { /// Config file of the client that is supposed to use the signatures. @@ -24,11 +24,11 @@ pub struct Args { pub(crate) client_config: PathBuf, /// Explicitly provide the encoded signatures data (as base58) - #[clap(long, group = "signatures_data", value_parser = parse_encoded_signatures_data)] + #[clap(long, group = "sig_data", value_parser = parse_encoded_signatures_data)] pub(crate) signatures_data: Option>, /// Specifies the path to file containing binary signatures data - #[clap(long, group = "signatures_data")] + #[clap(long, group = "sig_data")] pub(crate) signatures_path: Option, // currently hidden as there exists only a single serialization standard diff --git a/common/commands/src/ecash/import_master_verification_key.rs b/common/commands/src/ecash/import_master_verification_key.rs index f194c00c8a..1e8118ca9d 100644 --- a/common/commands/src/ecash/import_master_verification_key.rs +++ b/common/commands/src/ecash/import_master_verification_key.rs @@ -16,7 +16,7 @@ fn parse_encoded_key_data(raw: &str) -> bs58::decode::Result> { #[derive(Debug, Parser)] #[clap( - group(ArgGroup::new("key_data").required(true)), + group(ArgGroup::new("key_data_group").required(true)), )] pub struct Args { /// Config file of the client that is supposed to use the key. @@ -24,11 +24,11 @@ pub struct Args { pub(crate) client_config: PathBuf, /// Explicitly provide the encoded key data (as base58) - #[clap(long, group = "key_data", value_parser = parse_encoded_key_data)] + #[clap(long, group = "key_data_group", value_parser = parse_encoded_key_data)] pub(crate) key_data: Option>, /// Specifies the path to file containing binary key data - #[clap(long, group = "key_data")] + #[clap(long, group = "key_data_group")] pub(crate) key_path: Option, // currently hidden as there exists only a single serialization standard From 45e60119619af7b66aa1fb5c24289027c2eec6d7 Mon Sep 17 00:00:00 2001 From: =?UTF-8?q?J=C4=99drzej=20Stuczy=C5=84ski?= Date: Mon, 2 Sep 2024 10:08:33 +0100 Subject: [PATCH 69/93] vol3 --- service-providers/ip-packet-router/src/cli/ecash/mod.rs | 1 - 1 file changed, 1 deletion(-) diff --git a/service-providers/ip-packet-router/src/cli/ecash/mod.rs b/service-providers/ip-packet-router/src/cli/ecash/mod.rs index 4e3d0befcd..33a4ddd667 100644 --- a/service-providers/ip-packet-router/src/cli/ecash/mod.rs +++ b/service-providers/ip-packet-router/src/cli/ecash/mod.rs @@ -7,7 +7,6 @@ use nym_client_core::cli_helpers::client_import_credential::CommonClientImportTi use nym_client_core::cli_helpers::client_import_expiration_date_signatures::CommonClientImportExpirationDateSignaturesArgs; use nym_client_core::cli_helpers::client_import_master_verification_key::CommonClientImportMasterVerificationKeyArgs; use nym_ip_packet_router::error::IpPacketRouterError; -use std::error::Error; pub(crate) mod import_coin_index_signatures; pub(crate) mod import_credential; From dd701925088536d7c536a823b99baf9ac35954c6 Mon Sep 17 00:00:00 2001 From: =?UTF-8?q?Jon=20H=C3=A4ggblad?= Date: Mon, 9 Sep 2024 11:21:57 +0200 Subject: [PATCH 70/93] Create nym-repo-setup debian package and nym-vpn meta package (#4837) * Create nym-repo-setup * update * Add postrm * Add README * Add Makefile * Move to subdir * Bundle the list file instead * Create nym-vpn metapackage * Rename top-level dir * Set version of meta package to 0.1 * Add dpkg-name * Create workflow for creating the debs * Restrict to amd64 only * Rename to build-deb-meta.yml * name to upload-artifact * Set names * typo * Extend version and set amd64 only * Bump to 1.0.1 --- .github/workflows/build-deb-meta.yml | 32 +++++++++++++++++- ppa/packages/Makefile | 22 ++++++++++++ ppa/packages/README.md | 13 +++++++ ppa/packages/nym-repo-setup/DEBIAN/control | 9 +++++ ppa/packages/nym-repo-setup/DEBIAN/postinst | 4 +++ ppa/packages/nym-repo-setup/DEBIAN/preinst | 18 ++++++++++ .../etc/apt/sources.list.d/nymtech.list | 3 ++ .../usr/share/keyrings/nymtech.gpg | Bin 0 -> 2272 bytes ppa/packages/nym-vpn/DEBIAN/control | 9 +++++ 9 files changed, 109 insertions(+), 1 deletion(-) create mode 100644 ppa/packages/Makefile create mode 100644 ppa/packages/README.md create mode 100644 ppa/packages/nym-repo-setup/DEBIAN/control create mode 100755 ppa/packages/nym-repo-setup/DEBIAN/postinst create mode 100755 ppa/packages/nym-repo-setup/DEBIAN/preinst create mode 100644 ppa/packages/nym-repo-setup/etc/apt/sources.list.d/nymtech.list create mode 100644 ppa/packages/nym-repo-setup/usr/share/keyrings/nymtech.gpg create mode 100644 ppa/packages/nym-vpn/DEBIAN/control diff --git a/.github/workflows/build-deb-meta.yml b/.github/workflows/build-deb-meta.yml index 52618e57ce..29fb29e631 100644 --- a/.github/workflows/build-deb-meta.yml +++ b/.github/workflows/build-deb-meta.yml @@ -5,5 +5,35 @@ on: jobs: build: + runs-on: arc-ubuntu-22.04 + steps: - run: "echo hello" + - name: Checkout Repository + uses: actions/checkout@v4 + + - name: Set up Build Environment + run: sudo apt-get update && sudo apt-get install -y make dpkg-dev + + - name: Build Debian Packages + working-directory: ppa/packages + run: make + + - name: Find .deb files + working-directory: ppa/packages + run: | + echo "file1=$(ls nym-repo-setup*.deb)" >> $GITHUB_ENV + echo "file2=$(ls nym-vpn*.deb)" >> $GITHUB_ENV + + - name: Upload nym-repo-setup + uses: actions/upload-artifact@v4 + with: + name: ${{ env.file1 }} + path: ppa/packages/nym-repo-setup*.deb + retention-days: 10 + + - name: Upload nym-vpn + uses: actions/upload-artifact@v4 + with: + name: ${{ env.file2 }} + path: ppa/packages/nym-vpn*.deb + retention-days: 10 diff --git a/ppa/packages/Makefile b/ppa/packages/Makefile new file mode 100644 index 0000000000..04ec2d0320 --- /dev/null +++ b/ppa/packages/Makefile @@ -0,0 +1,22 @@ +all: deb + +REPO_DEB=nym-repo-setup.deb +REPO_SRC=nym-repo-setup + +META_DEB=nym-vpn.deb +META_SRC=nym-vpn + +ALL_DEB=$(REPO_DEB) $(META_DEB) + +deb: $(ALL_DEB) + +$(REPO_DEB): + dpkg-deb --build $(REPO_SRC) $(REPO_DEB) + dpkg-name -o $(REPO_DEB) + +$(META_DEB): + dpkg-deb --build $(META_SRC) $(META_DEB) + dpkg-name -o $(META_DEB) + +clean: + rm $(ALL_DEB) diff --git a/ppa/packages/README.md b/ppa/packages/README.md new file mode 100644 index 0000000000..ba64922e7a --- /dev/null +++ b/ppa/packages/README.md @@ -0,0 +1,13 @@ +# Nym deb meta packages + +## Nymtech repo setup + +`nym-repo-setup.deb` is a debian package that sets up the nymtech debian repo by copying the keyring file and adding `nymtech.list` to `/etc/apt/sources.list.d`. + +## Nym VPN meta package + +A basic meta package which only purpose is to depend on the daemon and UI. + +# Build + +They can all be built by running `make`. diff --git a/ppa/packages/nym-repo-setup/DEBIAN/control b/ppa/packages/nym-repo-setup/DEBIAN/control new file mode 100644 index 0000000000..e098728bad --- /dev/null +++ b/ppa/packages/nym-repo-setup/DEBIAN/control @@ -0,0 +1,9 @@ +Package: nym-repo-setup +Version: 1.0.1 +Section: base +Priority: optional +Architecture: amd64 +Depends: apt (>= 1.0.0) +Maintainer: Nym Technologies SA +Description: Setup script to add the Nym repository + This package adds the Nym repository and installs the GPG key for verifying package signatures. diff --git a/ppa/packages/nym-repo-setup/DEBIAN/postinst b/ppa/packages/nym-repo-setup/DEBIAN/postinst new file mode 100755 index 0000000000..5eb21e1566 --- /dev/null +++ b/ppa/packages/nym-repo-setup/DEBIAN/postinst @@ -0,0 +1,4 @@ +#!/bin/bash + +# Updating package list +apt-get update diff --git a/ppa/packages/nym-repo-setup/DEBIAN/preinst b/ppa/packages/nym-repo-setup/DEBIAN/preinst new file mode 100755 index 0000000000..7755dd31be --- /dev/null +++ b/ppa/packages/nym-repo-setup/DEBIAN/preinst @@ -0,0 +1,18 @@ +#!/bin/bash + +# Path to the repository list file +REPO_LIST_FILE="/etc/apt/sources.list.d/nymtech.list" + +# Check if the repository list file already exists +if [ -f "$REPO_LIST_FILE" ]; then + # Generate a backup file name with a timestamp + TIMESTAMP=$(date +%Y%m%d%H%M%S) + BACKUP_FILE="/etc/apt/sources.list.d/nymtech.list.${TIMESTAMP}.bak" + + # Rename the existing list file to the backup file + echo "Backing up existing nymtech.list to $BACKUP_FILE" + mv "$REPO_LIST_FILE" "$BACKUP_FILE" +fi + +# Continue with the installation +exit 0 diff --git a/ppa/packages/nym-repo-setup/etc/apt/sources.list.d/nymtech.list b/ppa/packages/nym-repo-setup/etc/apt/sources.list.d/nymtech.list new file mode 100644 index 0000000000..7a9b95332a --- /dev/null +++ b/ppa/packages/nym-repo-setup/etc/apt/sources.list.d/nymtech.list @@ -0,0 +1,3 @@ +# This file is provided by the nym-repo-setup package + +deb [arch=amd64 signed-by=/usr/share/keyrings/nymtech.gpg] https://apt.nymtech.net/ jammy main diff --git a/ppa/packages/nym-repo-setup/usr/share/keyrings/nymtech.gpg b/ppa/packages/nym-repo-setup/usr/share/keyrings/nymtech.gpg new file mode 100644 index 0000000000000000000000000000000000000000..46d69640e5619fbb0adc40cc214302b9bab57ac8 GIT binary patch literal 2272 zcmV<62p{*E0u2OZTw+)O5CFA*vbIP?MO_`-PR=mK9-(H~uwR$HG(4Zf`(5E9pxYxi zheQX#aB!zYMk*;^a(fH$TcIJkhBSW!B59CYe9^rp;rjtF`P_wHNZN5=#PhmJN*22Y zXv;uTC`O!bNL2UFWdvwE8F24#1NkxB#(G)F0Fo5;E(sC&7>aI4)?G4@x-Uv$MXs32 z!*d}WDz*o@ck_RsV^b5_xBg)zV;v{r)X%QnO|U9ld4pd4+h}RYL}o0f@z+}vtMe#& zUT4R{n0FvcoZ>A~+>s&r&Fe8qcI^%z*47(#`b%If9>=(jI;+ai#JJa?dZrb*33kK4 zcwz}=!Eo|ADDoD48_+%S19=TudOS*&KD{m;^$kFb$d2zC1% zE~}MUJLQrPjX0W%Pm?>Wjqi8`itmy1#avgSZV8m#B?;?&a|!LX;vsG%oe3hSr(f1CP(dJbX=iR}Zf78CWqBze zJZ^byKyG<$bY){`E^cLXK8XTO1QP)Y05}#Q1kGaW0~q7hG^lS5S%D8k*I$Wd0tEtP zTw+)P8v_Lk2?z%Q1{Dek2nzxP76JnS0v-VZ7k~f?2@rt~MAu)5W&%f45B(BD=2XXv z9BpibO|8n{F44$R_*=cF6NWRietp9k=vR?MRz~iN#oo?!wytE#dU0TCr$|8qY(-?c z?cVj%tA8Rh3?$Ixr~Ie)kJ?MUR1im~hM6X<-ATpT3{1My53NU{spXHeQc20L5V=Ja zS(fmlif5tZ>zI?FquUgrJLjcJqu}muH#)9rlZxW4e^&+cTx;H|>Mjg?Ar4W~j)%c2 z3O`T}(of>EjK;+=RNWYCTMsJ4@@bO)O6Q6=#kAm0L4e#;o#jtT8Sb{e)IIpsWdfD4 zZ*%Zy^A>0XQ|Ax+r6gI|hHt&b{vLB@u4xU}OV1*`*-Ru^O#MZvIXf{nD%||&wiyM6 z30))rl}^RvN*iDKQ&(!B0!%rYJZMwWO zIkW}TN69o-(jXzt6T0NC{Z0J{fpS>-zz})!bcIeQ(LOw}gEASyqH^BU@=7 z1?<}jG8BP z4F1!erPB`@>GwQ$EhbFtq*r)X07uK5n&000Zlo5_M?;+757G{NQ<0e*z?9x*6Q#-Q z+kNN|0Z3o)TiB9Bna#J!jNi4e4+9xSI2mfZiebqv1n?Uvk-Z0*;t?)k@Q9tYNUW3d*C8O6Mge;1AYE$<3Y%4Z z%qhp!*IyuZcK{p(n)!h{ZuYZOIz@jwho|I5i_uTCpzG78EBq9!U`r2(LoxA_iKWE9 zZhbTb?YU`N*EDov^WKLzRO2m7E8D}*of=cA1m;fR-l-CvW4#R=-g}Hj60YkG7EMT% zJ-~wRA>b+CVvX|5;k1(t9?ZoqNA{FK=i23F07=LWt);l&lCWp5zTq?0EI{_2cat0E zcuwk5y{(C2#S#!M49w7D0UU-m>_y_sxo+ifm%UQXGAHV@ZsXjN0$)-m{SMGwj<87ieuNF;6^QPx7H)Cp6a5>ID`7}3`V560 z?*^iR<{?_97Q8b%t25nm>{c&b-krB5S4~?*d~t7#$rv^bc8*jCX;YIU<-2`k!p?~Z zze;iXDZm!*4vHCDl{esXmXN0{?R#XmSwCLhzL;GXVrUkog^o+42zYREBSKo5$piG& zz=eN-s=~^Bp>sS#=gH7N5=-(Qm^Zs_LF<^K}JF(AXmUz|lZ7b@4W*P5d zXN7oS3#7gp5}CWsxFmAGXrsV^XU*;=431N4HI@70+^Crq>SuGL`O$4m#m~?Fn?poH zd%3A$v9AUC&6ULsr|$ixxOp#AE%}^8-NRPI3}-=D6-_iH&16uwLTw)NQScrSXr0f{ z^x9LKRyt`BqM2cgSmI&DHgVM{37^Gn0GJdG-6UAWh)y5Z*{fQAio|%*1vxKx5NQP! zSljzlFxbzc_Mp&(h@%N4Z4v(g(Jwav0L{%H6ixf$vCxXcC=X1q>JvjL8bupi!H9BjyFyK literal 0 HcmV?d00001 diff --git a/ppa/packages/nym-vpn/DEBIAN/control b/ppa/packages/nym-vpn/DEBIAN/control new file mode 100644 index 0000000000..b51ba7d75f --- /dev/null +++ b/ppa/packages/nym-vpn/DEBIAN/control @@ -0,0 +1,9 @@ +Package: nym-vpn +Version: 0.1.0 +Section: metapackages +Priority: optional +Architecture: amd64 +Depends: nym-vpnd, nymvpn-x +Maintainer: Nym Technologies SA +Description: Nym Metapackage + This is a metapackage that depends on nym-vpnd and nymvpn-x. Installing this package will also install both nym-vpnd and nymvpn-x. From 85758be9ca805244b4fa4bb8677e7372b28f1152 Mon Sep 17 00:00:00 2001 From: =?UTF-8?q?Jon=20H=C3=A4ggblad?= Date: Mon, 9 Sep 2024 12:00:28 +0200 Subject: [PATCH 71/93] Start switching over jobs to arc-ubuntu-20.04 (#4843) * Switch ci-build to arc-ubuntu-20.04 * Trigger on wf file chanes * Add IPR and authenticator to default workspace * Move over a few more * and more * Revert two builds that require docker * typo in label * Revert two more * Fix go * update * update --- .github/workflows/ci-binary-config-checker.yml | 4 +++- .github/workflows/ci-build-ts.yml | 1 + .github/workflows/ci-build-upload-binaries.yml | 3 ++- .github/workflows/ci-build.yml | 4 +++- .github/workflows/ci-cargo-deny.yml | 6 +++++- .github/workflows/ci-contracts-schema.yml | 3 ++- .github/workflows/ci-contracts-upload-binaries.yml | 3 ++- .github/workflows/ci-contracts.yml | 3 ++- .github/workflows/ci-docs.yml | 3 ++- .github/workflows/ci-lint-typescript.yml | 1 + .github/workflows/ci-nym-network-explorer.yml | 1 + .github/workflows/ci-nym-wallet-rust.yml | 4 +++- .github/workflows/ci-nym-wallet-storybook.yml | 1 + .github/workflows/ci-sdk-docs-typescript.yml | 1 + .github/workflows/ci-sdk-wasm.yml | 13 ++++++++++++- Cargo.toml | 12 ++++++------ 16 files changed, 47 insertions(+), 16 deletions(-) diff --git a/.github/workflows/ci-binary-config-checker.yml b/.github/workflows/ci-binary-config-checker.yml index fc151c73dd..7f4717f883 100644 --- a/.github/workflows/ci-binary-config-checker.yml +++ b/.github/workflows/ci-binary-config-checker.yml @@ -13,6 +13,7 @@ on: - 'mixnode/**' - 'sdk/rust/nym-sdk/**' - 'service-providers/**' + - '.github/workflows/ci-binary-config-checker.yml' pull_request: paths: - 'clients/**' @@ -22,6 +23,7 @@ on: - 'mixnode/**' - 'sdk/rust/nym-sdk/**' - 'service-providers/**' + - '.github/workflows/ci-binary-config-checker.yml' env: NETWORK: mainnet @@ -31,7 +33,7 @@ jobs: strategy: fail-fast: false matrix: - platform: [custom-linux] + platform: [arc-ubuntu-20.04] runs-on: ${{ matrix.platform }} steps: diff --git a/.github/workflows/ci-build-ts.yml b/.github/workflows/ci-build-ts.yml index 624a52245d..4c8dbe6b7c 100644 --- a/.github/workflows/ci-build-ts.yml +++ b/.github/workflows/ci-build-ts.yml @@ -5,6 +5,7 @@ on: paths: - "ts-packages/**" - "sdk/typescript/**" + - ".github/workflows/ci-build-ts.yml" jobs: build: diff --git a/.github/workflows/ci-build-upload-binaries.yml b/.github/workflows/ci-build-upload-binaries.yml index c30f9c3528..778cf58050 100644 --- a/.github/workflows/ci-build-upload-binaries.yml +++ b/.github/workflows/ci-build-upload-binaries.yml @@ -31,13 +31,14 @@ on: - "service-providers/**" - "tools/**" - "nymvisor/**" + - ".github/workflows/ci-build-upload-binaries.yml" jobs: publish-nym: strategy: fail-fast: false matrix: - platform: [ ubuntu-20.04 ] + platform: [ arc-ubuntu-20.04 ] runs-on: ${{ matrix.platform }} env: diff --git a/.github/workflows/ci-build.yml b/.github/workflows/ci-build.yml index 2c950f902a..4293eba2ab 100644 --- a/.github/workflows/ci-build.yml +++ b/.github/workflows/ci-build.yml @@ -18,6 +18,7 @@ on: - 'tools/nym-nr-query/**' - 'tools/ts-rs-cli/**' - 'Cargo.toml' + - '.github/workflows/ci-build.yml' pull_request: paths: - 'clients/**' @@ -35,6 +36,7 @@ on: - 'tools/nym-nr-query/**' - 'tools/ts-rs-cli/**' - 'Cargo.toml' + - '.github/workflows/ci-build.yml' workflow_dispatch: jobs: @@ -42,7 +44,7 @@ jobs: strategy: fail-fast: false matrix: - os: [custom-linux, custom-runner-mac-m1] + os: [arc-ubuntu-20.04, custom-runner-mac-m1] runs-on: ${{ matrix.os }} env: CARGO_TERM_COLOR: always diff --git a/.github/workflows/ci-cargo-deny.yml b/.github/workflows/ci-cargo-deny.yml index e695c17e51..fc844695c1 100644 --- a/.github/workflows/ci-cargo-deny.yml +++ b/.github/workflows/ci-cargo-deny.yml @@ -2,10 +2,14 @@ name: ci-cargo-deny on: workflow_dispatch: pull_request: + paths: + - 'Cargo.toml' + - 'Cargo.lock' + - '.github/workflows/ci-cargo-deny.yml' jobs: cargo-deny: - runs-on: ubuntu-22.04 + runs-on: arc-ubuntu-22.04-dind strategy: matrix: checks: diff --git a/.github/workflows/ci-contracts-schema.yml b/.github/workflows/ci-contracts-schema.yml index 5f5ea4e538..054d68f9bc 100644 --- a/.github/workflows/ci-contracts-schema.yml +++ b/.github/workflows/ci-contracts-schema.yml @@ -6,11 +6,12 @@ on: paths: - 'contracts/**' - 'common/**' + - '.github/workflows/ci-contracts-schema.yml' jobs: check-schema: name: Generate and check schema - runs-on: custom-linux + runs-on: arc-ubuntu-20.04 env: CARGO_TERM_COLOR: always steps: diff --git a/.github/workflows/ci-contracts-upload-binaries.yml b/.github/workflows/ci-contracts-upload-binaries.yml index 77899f495a..4873d46885 100644 --- a/.github/workflows/ci-contracts-upload-binaries.yml +++ b/.github/workflows/ci-contracts-upload-binaries.yml @@ -6,6 +6,7 @@ on: paths: - 'common/**' - 'contracts/**' + - '.github/workflows/ci-contracts-upload-binaries.yml' env: NETWORK: mainnet @@ -15,7 +16,7 @@ jobs: strategy: fail-fast: false matrix: - platform: [ ubuntu-20.04 ] + platform: arc-ubuntu-20.04 runs-on: ${{ matrix.platform }} env: diff --git a/.github/workflows/ci-contracts.yml b/.github/workflows/ci-contracts.yml index cb88ca85f3..150ec5d6e9 100644 --- a/.github/workflows/ci-contracts.yml +++ b/.github/workflows/ci-contracts.yml @@ -9,10 +9,11 @@ on: paths: - 'contracts/**' - 'common/**' + - '.github/workflows/ci-contracts.yml' jobs: matrix_prep: - runs-on: ubuntu-20.04 + runs-on: arc-ubuntu-20.04 outputs: matrix: ${{ steps.set-matrix.outputs.matrix }} steps: diff --git a/.github/workflows/ci-docs.yml b/.github/workflows/ci-docs.yml index 12fb22be4e..877248d76e 100644 --- a/.github/workflows/ci-docs.yml +++ b/.github/workflows/ci-docs.yml @@ -6,10 +6,11 @@ on: branches-ignore: master paths: - 'documentation/docs/**' + - '.github/workflows/ci-docs.yml' jobs: build: - runs-on: ubuntu-20.04-16-core + runs-on: arc-ubuntu-20.04 steps: - uses: actions/checkout@v4 - name: Install Dependencies (Linux) diff --git a/.github/workflows/ci-lint-typescript.yml b/.github/workflows/ci-lint-typescript.yml index f14b713c45..165446bbd8 100644 --- a/.github/workflows/ci-lint-typescript.yml +++ b/.github/workflows/ci-lint-typescript.yml @@ -10,6 +10,7 @@ on: - "nym-wallet/src/**" - "nym-wallet/package.json" - "explorer/**" + - ".github/workflows/ci-lint-typescript.yml" jobs: build: diff --git a/.github/workflows/ci-nym-network-explorer.yml b/.github/workflows/ci-nym-network-explorer.yml index 82516e6ddb..b1cb2d9de3 100644 --- a/.github/workflows/ci-nym-network-explorer.yml +++ b/.github/workflows/ci-nym-network-explorer.yml @@ -5,6 +5,7 @@ on: push: paths: - 'explorer/**' + - '.github/workflows/ci-nym-network-explorer.yml' defaults: run: diff --git a/.github/workflows/ci-nym-wallet-rust.yml b/.github/workflows/ci-nym-wallet-rust.yml index d9001ff24d..62115b2738 100644 --- a/.github/workflows/ci-nym-wallet-rust.yml +++ b/.github/workflows/ci-nym-wallet-rust.yml @@ -7,16 +7,18 @@ on: - 'common/**' - 'contracts/vesting/**' - 'nym-api/nym-api-requests/**' + - '.github/workflows/ci-nym-wallet-rust.yml' pull_request: paths: - 'nym-wallet/**' - 'common/**' - 'contracts/vesting/**' - 'nym-api/nym-api-requests/**' + - '.github/workflows/ci-nym-wallet-rust.yml' jobs: build: - runs-on: [ self-hosted, custom-linux ] + runs-on: arc-ubuntu-20.04 env: CARGO_TERM_COLOR: always steps: diff --git a/.github/workflows/ci-nym-wallet-storybook.yml b/.github/workflows/ci-nym-wallet-storybook.yml index 91fbfcd4e5..a6b1fde221 100644 --- a/.github/workflows/ci-nym-wallet-storybook.yml +++ b/.github/workflows/ci-nym-wallet-storybook.yml @@ -4,6 +4,7 @@ on: pull_request: paths: - 'nym-wallet/**' + - '.github/workflows/ci-nym-wallet-storybook.yml' jobs: build: diff --git a/.github/workflows/ci-sdk-docs-typescript.yml b/.github/workflows/ci-sdk-docs-typescript.yml index dac1612f8b..836150ad23 100644 --- a/.github/workflows/ci-sdk-docs-typescript.yml +++ b/.github/workflows/ci-sdk-docs-typescript.yml @@ -5,6 +5,7 @@ on: paths: - "sdk/typescript/**" - "wasm/**" + - '.github/workflows/ci-sdk-docs-typescript.yml' jobs: build: diff --git a/.github/workflows/ci-sdk-wasm.yml b/.github/workflows/ci-sdk-wasm.yml index 39fd471b06..10fc1c70ff 100644 --- a/.github/workflows/ci-sdk-wasm.yml +++ b/.github/workflows/ci-sdk-wasm.yml @@ -6,10 +6,11 @@ on: - 'wasm/**' - 'clients/client-core/**' - 'common/**' + - '.github/workflows/ci-sdk-wasm.yml' jobs: wasm: - runs-on: [custom-linux] + runs-on: arc-ubuntu-20.04 env: CARGO_TERM_COLOR: always steps: @@ -32,6 +33,16 @@ jobs: with: go-version: '1.20' + - name: Override GOROOT and GOTOOLDIR + run: | + echo "Setting correct GOROOT and GOTOOLDIR" + unset GOROOT + unset GOTOOLDIR + export GOROOT=$(go env GOROOT) + export GOTOOLDIR=$(go env GOTOOLDIR) + echo "GOROOT=$GOROOT" >> $GITHUB_ENV + echo "GOTOOLDIR=$GOTOOLDIR" >> $GITHUB_ENV + - name: Install wasm-pack run: curl https://rustwasm.github.io/wasm-pack/installer/init.sh -sSf | sh diff --git a/Cargo.toml b/Cargo.toml index 2be451eb47..fa57151495 100644 --- a/Cargo.toml +++ b/Cargo.toml @@ -133,14 +133,16 @@ members = [ default-members = [ "clients/native", "clients/socks5", + "explorer-api", "gateway", - "service-providers/network-requester", "mixnode", "nym-api", - "tools/nymvisor", - "explorer-api", - "nym-validator-rewarder", "nym-node", + "nym-validator-rewarder", + "service-providers/authenticator", + "service-providers/ip-packet-router", + "service-providers/network-requester", + "tools/nymvisor", ] exclude = [ @@ -260,9 +262,7 @@ pretty_env_logger = "0.4.0" publicsuffix = "2.2.3" quote = "1" rand = "0.8.5" -rand-07 = "0.7.3" rand_chacha = "0.3" -rand_chacha_02 = "0.2" rand_core = "0.6.3" rand_distr = "0.4" rand_pcg = "0.3.1" From 7e40207d4691610fef14d903d36421ffff3d60e1 Mon Sep 17 00:00:00 2001 From: =?UTF-8?q?Jon=20H=C3=A4ggblad?= Date: Mon, 9 Sep 2024 12:01:24 +0200 Subject: [PATCH 72/93] Fix test failure in ipr request size (#4844) * Fix test failure in ipr request size that suddenly appeared * Use fixed date in unit test --- common/ip-packet-requests/src/v7/request.rs | 4 +++- 1 file changed, 3 insertions(+), 1 deletion(-) diff --git a/common/ip-packet-requests/src/v7/request.rs b/common/ip-packet-requests/src/v7/request.rs index 24f9819c2a..73266320e3 100644 --- a/common/ip-packet-requests/src/v7/request.rs +++ b/common/ip-packet-requests/src/v7/request.rs @@ -415,6 +415,8 @@ pub struct HealthRequest { #[cfg(test)] mod tests { + use time::macros::datetime; + use super::*; use std::net::{Ipv4Addr, Ipv6Addr}; use std::str::FromStr; @@ -432,7 +434,7 @@ mod tests { reply_to_hops: None, reply_to_avg_mix_delays: None, buffer_timeout: None, - timestamp: OffsetDateTime::now_utc(), + timestamp: datetime!(2024-01-01 12:59:59.5 UTC), }, signature: None, } From 55694f03419965640bd2548c51baa84b512cf968 Mon Sep 17 00:00:00 2001 From: =?UTF-8?q?Jon=20H=C3=A4ggblad?= Date: Mon, 9 Sep 2024 16:57:48 +0200 Subject: [PATCH 73/93] Revert runner for ci-docs (#4855) * Use arc-ubuntu-20.04-dind for ci-docs * Revert back to ubuntu 20.04-16-core for now --- .github/workflows/ci-docs.yml | 2 +- 1 file changed, 1 insertion(+), 1 deletion(-) diff --git a/.github/workflows/ci-docs.yml b/.github/workflows/ci-docs.yml index 877248d76e..74b599d26d 100644 --- a/.github/workflows/ci-docs.yml +++ b/.github/workflows/ci-docs.yml @@ -10,7 +10,7 @@ on: jobs: build: - runs-on: arc-ubuntu-20.04 + runs-on: ubuntu-20.04-16-core steps: - uses: actions/checkout@v4 - name: Install Dependencies (Linux) From 63d0ab49e12cb52f3bffb0fd23d88fac215c0132 Mon Sep 17 00:00:00 2001 From: =?UTF-8?q?Bogdan-=C8=98tefan=20Neac=C5=9Fu?= Date: Mon, 9 Sep 2024 19:13:10 +0200 Subject: [PATCH 74/93] Move credential verification into common crate (#4853) * Move cred verification to common crate * Put crate in toml file manually --- Cargo.lock | 32 +- Cargo.toml | 1 + common/credential-verification/Cargo.toml | 33 ++ .../src/bandwidth_storage_manager.rs | 148 ++++++++ .../src/client_bandwidth.rs | 57 +++ .../src}/ecash/credential_sender.rs | 26 +- .../src}/ecash/double_spending.rs | 6 +- .../src}/ecash/error.rs | 0 .../src}/ecash/helpers.rs | 0 .../credential-verification/src}/ecash/mod.rs | 15 +- .../src}/ecash/state.rs | 8 +- common/credential-verification/src/error.rs | 57 +++ common/credential-verification/src/lib.rs | 156 ++++++++ common/credentials-interface/src/lib.rs | 21 ++ gateway/Cargo.toml | 7 +- gateway/src/error.rs | 13 +- gateway/src/node/client_handling/bandwidth.rs | 30 -- gateway/src/node/client_handling/mod.rs | 5 - .../client_handling/websocket/common_state.rs | 3 +- .../connection_handler/authenticated.rs | 336 ++---------------- .../websocket/connection_handler/fresh.rs | 6 +- .../websocket/connection_handler/mod.rs | 54 +-- gateway/src/node/mod.rs | 23 +- 23 files changed, 577 insertions(+), 460 deletions(-) create mode 100644 common/credential-verification/Cargo.toml create mode 100644 common/credential-verification/src/bandwidth_storage_manager.rs create mode 100644 common/credential-verification/src/client_bandwidth.rs rename {gateway/src/node/client_handling/websocket/connection_handler => common/credential-verification/src}/ecash/credential_sender.rs (97%) rename {gateway/src/node/client_handling/websocket/connection_handler => common/credential-verification/src}/ecash/double_spending.rs (94%) rename {gateway/src/node/client_handling/websocket/connection_handler => common/credential-verification/src}/ecash/error.rs (100%) rename {gateway/src/node/client_handling/websocket/connection_handler => common/credential-verification/src}/ecash/helpers.rs (100%) rename {gateway/src/node/client_handling/websocket/connection_handler => common/credential-verification/src}/ecash/mod.rs (93%) rename {gateway/src/node/client_handling/websocket/connection_handler => common/credential-verification/src}/ecash/state.rs (97%) create mode 100644 common/credential-verification/src/error.rs create mode 100644 common/credential-verification/src/lib.rs diff --git a/Cargo.lock b/Cargo.lock index e8565e92f2..06140c6a8d 100644 --- a/Cargo.lock +++ b/Cargo.lock @@ -4741,6 +4741,31 @@ dependencies = [ "tokio", ] +[[package]] +name = "nym-credential-verification" +version = "0.1.0" +dependencies = [ + "bs58", + "cosmwasm-std", + "cw-utils", + "futures", + "nym-api-requests", + "nym-credentials", + "nym-credentials-interface", + "nym-ecash-contract-common", + "nym-ecash-double-spending", + "nym-gateway-requests", + "nym-gateway-storage", + "nym-task", + "nym-validator-client", + "rand", + "si-scale", + "thiserror", + "time", + "tokio", + "tracing", +] + [[package]] name = "nym-credentials" version = "0.1.0" @@ -4911,12 +4936,9 @@ dependencies = [ "anyhow", "async-trait", "bip39", - "bloomfilter", "bs58", "clap 4.5.16", "colored", - "cosmwasm-std", - "cw-utils", "dashmap", "defguard_wireguard_rs", "dirs 4.0.0", @@ -4928,11 +4950,10 @@ dependencies = [ "nym-authenticator", "nym-bin-common", "nym-config", + "nym-credential-verification", "nym-credentials", "nym-credentials-interface", "nym-crypto", - "nym-ecash-contract-common", - "nym-ecash-double-spending", "nym-gateway-requests", "nym-gateway-storage", "nym-ip-packet-router", @@ -4956,7 +4977,6 @@ dependencies = [ "sqlx", "subtle-encoding", "thiserror", - "time", "tokio", "tokio-stream", "tokio-tungstenite", diff --git a/Cargo.toml b/Cargo.toml index fa57151495..72035c969a 100644 --- a/Cargo.toml +++ b/Cargo.toml @@ -45,6 +45,7 @@ members = [ "common/credentials", "common/credential-utils", "common/credentials-interface", + "common/credential-verification", "common/crypto", "common/dkg", "common/ecash-double-spending", diff --git a/common/credential-verification/Cargo.toml b/common/credential-verification/Cargo.toml new file mode 100644 index 0000000000..8585ad2cfa --- /dev/null +++ b/common/credential-verification/Cargo.toml @@ -0,0 +1,33 @@ +[package] +name = "nym-credential-verification" +version = "0.1.0" +authors.workspace = true +repository.workspace = true +homepage.workspace = true +documentation.workspace = true +edition.workspace = true +license.workspace = true +rust-version.workspace = true +readme.workspace = true + +[dependencies] +bs58 = { workspace = true } +cosmwasm-std = { workspace = true } +cw-utils = { workspace = true } +futures = { workspace = true } +rand = { workspace = true } +si-scale = { workspace = true } +thiserror = { workspace = true } +tokio = { workspace = true, features = ["rt-multi-thread", "macros"] } +time = { workspace = true } +tracing = { workspace = true } + +nym-api-requests = { path = "../../nym-api/nym-api-requests" } +nym-credentials = { path = "../credentials" } +nym-credentials-interface = { path = "../credentials-interface" } +nym-ecash-contract-common = { path = "../cosmwasm-smart-contracts/ecash-contract" } +nym-ecash-double-spending = { path = "../ecash-double-spending" } +nym-gateway-requests = { path = "../gateway-requests" } +nym-gateway-storage = { path = "../gateway-storage" } +nym-task = { path = "../task" } +nym-validator-client = { path = "../client-libs/validator-client" } diff --git a/common/credential-verification/src/bandwidth_storage_manager.rs b/common/credential-verification/src/bandwidth_storage_manager.rs new file mode 100644 index 0000000000..3a67d43743 --- /dev/null +++ b/common/credential-verification/src/bandwidth_storage_manager.rs @@ -0,0 +1,148 @@ +// Copyright 2024 - Nym Technologies SA +// SPDX-License-Identifier: Apache-2.0 + +use nym_credentials::ecash::utils::ecash_today; +use nym_credentials_interface::Bandwidth; +use nym_gateway_requests::ServerResponse; +use nym_gateway_storage::Storage; +use si_scale::helpers::bibytes2; +use time::OffsetDateTime; +use tracing::*; + +use crate::error::*; +use crate::BandwidthFlushingBehaviourConfig; +use crate::ClientBandwidth; + +const FREE_TESTNET_BANDWIDTH_VALUE: Bandwidth = Bandwidth::new_unchecked(64 * 1024 * 1024 * 1024); // 64GB + +#[derive(Clone)] +pub struct BandwidthStorageManager { + pub(crate) storage: S, + pub(crate) client_bandwidth: ClientBandwidth, + pub(crate) client_id: i64, + pub(crate) bandwidth_cfg: BandwidthFlushingBehaviourConfig, + pub(crate) only_coconut_credentials: bool, +} + +impl BandwidthStorageManager { + pub fn new( + storage: S, + client_bandwidth: ClientBandwidth, + client_id: i64, + bandwidth_cfg: BandwidthFlushingBehaviourConfig, + only_coconut_credentials: bool, + ) -> Self { + BandwidthStorageManager { + storage, + client_bandwidth, + client_id, + bandwidth_cfg, + only_coconut_credentials, + } + } + + async fn sync_expiration(&mut self) -> Result<()> { + self.storage + .set_expiration(self.client_id, self.client_bandwidth.bandwidth.expiration) + .await?; + Ok(()) + } + + pub async fn handle_claim_testnet_bandwidth(&mut self) -> Result { + debug!("handling testnet bandwidth request"); + + if self.only_coconut_credentials { + return Err(Error::OnlyCoconutCredentials); + } + + self.increase_bandwidth(FREE_TESTNET_BANDWIDTH_VALUE, ecash_today()) + .await?; + let available_total = self.client_bandwidth.bandwidth.bytes; + + Ok(ServerResponse::Bandwidth { available_total }) + } + + #[instrument(skip_all)] + pub async fn try_use_bandwidth(&mut self, required_bandwidth: i64) -> Result { + if self.client_bandwidth.bandwidth.expired() { + self.expire_bandwidth().await?; + } + let available_bandwidth = self.client_bandwidth.bandwidth.bytes; + + if available_bandwidth < required_bandwidth { + return Err(Error::OutOfBandwidth { + required: required_bandwidth, + available: available_bandwidth, + }); + } + + let available_bi2 = bibytes2(available_bandwidth as f64); + let required_bi2 = bibytes2(required_bandwidth as f64); + debug!(available = available_bi2, required = required_bi2); + + self.consume_bandwidth(required_bandwidth).await?; + Ok(available_bandwidth) + } + + async fn expire_bandwidth(&mut self) -> Result<()> { + self.storage.reset_bandwidth(self.client_id).await?; + self.client_bandwidth.bandwidth = Default::default(); + self.client_bandwidth.update_sync_data(); + Ok(()) + } + + /// Decreases the amount of available bandwidth of the connected client by the specified value. + /// + /// # Arguments + /// + /// * `amount`: amount to decrease the available bandwidth by. + async fn consume_bandwidth(&mut self, amount: i64) -> Result<()> { + self.client_bandwidth.bandwidth.bytes -= amount; + self.client_bandwidth.bytes_delta_since_sync -= amount; + + // since we're going to be operating on a fair use policy anyway, even if we crash and let extra few packets + // through, that's completely fine + if self.client_bandwidth.should_sync(self.bandwidth_cfg) { + self.sync_bandwidth().await?; + } + + Ok(()) + } + + #[instrument(level = "trace", skip_all)] + async fn sync_bandwidth(&mut self) -> Result<()> { + trace!("syncing client bandwidth with the underlying storage"); + let updated = self + .storage + .increase_bandwidth(self.client_id, self.client_bandwidth.bytes_delta_since_sync) + .await?; + + trace!(updated); + + self.client_bandwidth.bandwidth.bytes = updated; + + self.client_bandwidth.update_sync_data(); + Ok(()) + } + + /// Increases the amount of available bandwidth of the connected client by the specified value. + /// + /// # Arguments + /// + /// * `amount`: amount to increase the available bandwidth by. + /// * `expiration` : the expiration date of that bandwidth + pub async fn increase_bandwidth( + &mut self, + bandwidth: Bandwidth, + expiration: OffsetDateTime, + ) -> Result<()> { + self.client_bandwidth.bandwidth.bytes += bandwidth.value() as i64; + self.client_bandwidth.bytes_delta_since_sync += bandwidth.value() as i64; + self.client_bandwidth.bandwidth.expiration = expiration; + + // any increases to bandwidth should get flushed immediately + // (we don't want to accidentally miss somebody claiming a gigabyte voucher) + self.sync_expiration().await?; + self.sync_bandwidth().await + } +} diff --git a/common/credential-verification/src/client_bandwidth.rs b/common/credential-verification/src/client_bandwidth.rs new file mode 100644 index 0000000000..610a198e88 --- /dev/null +++ b/common/credential-verification/src/client_bandwidth.rs @@ -0,0 +1,57 @@ +// Copyright 2024 - Nym Technologies SA +// SPDX-License-Identifier: Apache-2.0 + +use std::time::Duration; + +use nym_credentials_interface::AvailableBandwidth; +use time::OffsetDateTime; + +#[derive(Debug, Clone, Copy)] +pub struct BandwidthFlushingBehaviourConfig { + /// Defines maximum delay between client bandwidth information being flushed to the persistent storage. + pub client_bandwidth_max_flushing_rate: Duration, + + /// Defines a maximum change in client bandwidth before it gets flushed to the persistent storage. + pub client_bandwidth_max_delta_flushing_amount: i64, +} + +#[derive(Debug, Clone, Copy)] +pub struct ClientBandwidth { + pub(crate) bandwidth: AvailableBandwidth, + pub(crate) last_flushed: OffsetDateTime, + + /// the number of bytes the client had during the last sync. + /// it is used to determine whether the current value should be synced with the storage + /// by checking the delta with the known amount + pub(crate) bytes_at_last_sync: i64, + pub(crate) bytes_delta_since_sync: i64, +} + +impl ClientBandwidth { + pub fn new(bandwidth: AvailableBandwidth) -> ClientBandwidth { + ClientBandwidth { + bandwidth, + last_flushed: OffsetDateTime::now_utc(), + bytes_at_last_sync: bandwidth.bytes, + bytes_delta_since_sync: 0, + } + } + + pub(crate) fn should_sync(&self, cfg: BandwidthFlushingBehaviourConfig) -> bool { + if self.bytes_delta_since_sync.abs() >= cfg.client_bandwidth_max_delta_flushing_amount { + return true; + } + + if self.last_flushed + cfg.client_bandwidth_max_flushing_rate < OffsetDateTime::now_utc() { + return true; + } + + false + } + + pub(crate) fn update_sync_data(&mut self) { + self.last_flushed = OffsetDateTime::now_utc(); + self.bytes_at_last_sync = self.bandwidth.bytes; + self.bytes_delta_since_sync = 0; + } +} diff --git a/gateway/src/node/client_handling/websocket/connection_handler/ecash/credential_sender.rs b/common/credential-verification/src/ecash/credential_sender.rs similarity index 97% rename from gateway/src/node/client_handling/websocket/connection_handler/ecash/credential_sender.rs rename to common/credential-verification/src/ecash/credential_sender.rs index 7cc478cc9a..47653cf334 100644 --- a/gateway/src/node/client_handling/websocket/connection_handler/ecash/credential_sender.rs +++ b/common/credential-verification/src/ecash/credential_sender.rs @@ -1,17 +1,17 @@ // Copyright 2022-2024 - Nym Technologies SA // SPDX-License-Identifier: GPL-3.0-only -use crate::node::client_handling::bandwidth::Bandwidth; -use crate::node::client_handling::websocket::connection_handler::ecash::error::EcashTicketError; -use crate::node::client_handling::websocket::connection_handler::ecash::helpers::for_each_api_concurrent; -use crate::node::client_handling::websocket::connection_handler::ecash::state::SharedState; -use crate::GatewayError; +use crate::ecash::error::EcashTicketError; +use crate::ecash::helpers::for_each_api_concurrent; +use crate::ecash::state::SharedState; +use crate::Error; use cosmwasm_std::Fraction; use cw_utils::ThresholdResponse; use futures::channel::mpsc::UnboundedReceiver; use futures::{Stream, StreamExt}; use nym_api_requests::constants::MIN_BATCH_REDEMPTION_DELAY; use nym_api_requests::ecash::models::{BatchRedeemTicketsBody, VerifyEcashTicketBody}; +use nym_credentials_interface::Bandwidth; use nym_credentials_interface::{ClientTicket, TicketType}; use nym_gateway_storage::Storage; use nym_validator_client::nym_api::EpochId; @@ -105,25 +105,25 @@ impl PendingRedemptionVote { } } -pub(crate) struct CredentialHandlerConfig { +pub struct CredentialHandlerConfig { /// Specifies the multiplier for revoking a malformed/double-spent ticket /// (if it has to go all the way to the nym-api for verification) /// e.g. if one ticket grants 100Mb and `revocation_bandwidth_penalty` is set to 1.5, /// the client will lose 150Mb - pub(crate) revocation_bandwidth_penalty: f32, + pub revocation_bandwidth_penalty: f32, /// Specifies the interval for attempting to resolve any failed, pending operations, /// such as ticket verification or redemption. - pub(crate) pending_poller: Duration, + pub pending_poller: Duration, - pub(crate) minimum_api_quorum: f32, + pub minimum_api_quorum: f32, /// Specifies the minimum number of tickets this gateway will attempt to redeem. - pub(crate) minimum_redemption_tickets: usize, + pub minimum_redemption_tickets: usize, /// Specifies the maximum time between two subsequent tickets redemptions. /// That's required as nym-apis will purge all ticket information for tickets older than 30 days. - pub(crate) maximum_time_between_redemption: Duration, + pub maximum_time_between_redemption: Duration, } pub(crate) struct CredentialHandler { @@ -260,7 +260,7 @@ where config: CredentialHandlerConfig, ticket_receiver: UnboundedReceiver, shared_state: SharedState, - ) -> Result { + ) -> Result { let multisig_threshold = shared_state .nyxd_client .read() @@ -269,7 +269,7 @@ where .await?; let ThresholdResponse::AbsolutePercentage { percentage, .. } = multisig_threshold else { - return Err(GatewayError::InvalidMultisigThreshold); + return Err(Error::InvalidMultisigThreshold); }; // that's a nasty conversion, but it works : ) diff --git a/gateway/src/node/client_handling/websocket/connection_handler/ecash/double_spending.rs b/common/credential-verification/src/ecash/double_spending.rs similarity index 94% rename from gateway/src/node/client_handling/websocket/connection_handler/ecash/double_spending.rs rename to common/credential-verification/src/ecash/double_spending.rs index a8cebdaf7b..812eea1fc1 100644 --- a/gateway/src/node/client_handling/websocket/connection_handler/ecash/double_spending.rs +++ b/common/credential-verification/src/ecash/double_spending.rs @@ -1,10 +1,10 @@ // Copyright 2022-2024 - Nym Technologies SA // SPDX-License-Identifier: GPL-3.0-only -use crate::node::client_handling::websocket::connection_handler::ecash::error::EcashTicketError; -use crate::node::client_handling::websocket::connection_handler::ecash::state::SharedState; -use crate::node::Storage; +use crate::ecash::error::EcashTicketError; +use crate::ecash::state::SharedState; use nym_ecash_double_spending::DoubleSpendingFilter; +use nym_gateway_storage::Storage; use nym_task::TaskClient; use nym_validator_client::client::NymApiClientExt; use nym_validator_client::EcashApiClient; diff --git a/gateway/src/node/client_handling/websocket/connection_handler/ecash/error.rs b/common/credential-verification/src/ecash/error.rs similarity index 100% rename from gateway/src/node/client_handling/websocket/connection_handler/ecash/error.rs rename to common/credential-verification/src/ecash/error.rs diff --git a/gateway/src/node/client_handling/websocket/connection_handler/ecash/helpers.rs b/common/credential-verification/src/ecash/helpers.rs similarity index 100% rename from gateway/src/node/client_handling/websocket/connection_handler/ecash/helpers.rs rename to common/credential-verification/src/ecash/helpers.rs diff --git a/gateway/src/node/client_handling/websocket/connection_handler/ecash/mod.rs b/common/credential-verification/src/ecash/mod.rs similarity index 93% rename from gateway/src/node/client_handling/websocket/connection_handler/ecash/mod.rs rename to common/credential-verification/src/ecash/mod.rs index 69c3d46800..c024f37733 100644 --- a/gateway/src/node/client_handling/websocket/connection_handler/ecash/mod.rs +++ b/common/credential-verification/src/ecash/mod.rs @@ -1,26 +1,25 @@ // Copyright 2022-2024 - Nym Technologies SA // SPDX-License-Identifier: GPL-3.0-only -use crate::node::client_handling::websocket::connection_handler::ecash::state::SharedState; -use crate::GatewayError; +use crate::Error; use credential_sender::CredentialHandler; +use credential_sender::CredentialHandlerConfig; use double_spending::DoubleSpendingDetector; +use error::EcashTicketError; use futures::channel::mpsc::{self, UnboundedSender}; use nym_credentials::CredentialSpendingData; use nym_credentials_interface::{ClientTicket, CompactEcashError, NymPayInfo, VerificationKeyAuth}; use nym_gateway_storage::Storage; use nym_validator_client::nym_api::EpochId; use nym_validator_client::DirectSigningHttpRpcNyxdClient; +use state::SharedState; use time::OffsetDateTime; use tokio::sync::{Mutex, RwLockReadGuard}; use tracing::error; -use crate::node::client_handling::websocket::connection_handler::ecash::credential_sender::CredentialHandlerConfig; -use crate::node::client_handling::websocket::connection_handler::ecash::error::EcashTicketError; - -pub(crate) mod credential_sender; +pub mod credential_sender; pub(crate) mod double_spending; -pub(crate) mod error; +pub mod error; mod helpers; mod state; @@ -45,7 +44,7 @@ where pk_bytes: [u8; 32], shutdown: nym_task::TaskClient, storage: S, - ) -> Result { + ) -> Result { let shared_state = SharedState::new(nyxd_client, storage).await?; let double_spend_detector = DoubleSpendingDetector::new(shared_state.clone()); diff --git a/gateway/src/node/client_handling/websocket/connection_handler/ecash/state.rs b/common/credential-verification/src/ecash/state.rs similarity index 97% rename from gateway/src/node/client_handling/websocket/connection_handler/ecash/state.rs rename to common/credential-verification/src/ecash/state.rs index 57f39e95fd..7f5a718759 100644 --- a/gateway/src/node/client_handling/websocket/connection_handler/ecash/state.rs +++ b/common/credential-verification/src/ecash/state.rs @@ -1,12 +1,12 @@ // Copyright 2024 - Nym Technologies SA // SPDX-License-Identifier: Apache-2.0 -use crate::node::client_handling::websocket::connection_handler::ecash::error::EcashTicketError; -use crate::node::Storage; -use crate::GatewayError; +use crate::ecash::error::EcashTicketError; +use crate::Error; use cosmwasm_std::{from_binary, CosmosMsg, WasmMsg}; use nym_credentials_interface::VerificationKeyAuth; use nym_ecash_contract_common::msg::ExecuteMsg; +use nym_gateway_storage::Storage; use nym_validator_client::coconut::all_ecash_api_clients; use nym_validator_client::nym_api::EpochId; use nym_validator_client::nyxd::contract_traits::{ @@ -37,7 +37,7 @@ where pub(crate) async fn new( nyxd_client: DirectSigningHttpRpcNyxdClient, storage: S, - ) -> Result { + ) -> Result { let address = nyxd_client.address(); if nyxd_client.dkg_contract_address().is_none() { diff --git a/common/credential-verification/src/error.rs b/common/credential-verification/src/error.rs new file mode 100644 index 0000000000..0f6b0e27e5 --- /dev/null +++ b/common/credential-verification/src/error.rs @@ -0,0 +1,57 @@ +// Copyright 2024 - Nym Technologies SA +// SPDX-License-Identifier: Apache-2.0 + +use thiserror::Error; +use time::Date; + +use crate::ecash::error::EcashTicketError; + +pub type Result = std::result::Result; + +#[derive(Error, Debug)] +pub enum Error { + #[error("the provided bandwidth credential has already been spent before at this gateway")] + BandwidthCredentialAlreadySpent, + + #[error(transparent)] + EcashFailure(EcashTicketError), + + #[error( + "the provided credential has an invalid spending date. got {got} but expected {expected}" + )] + InvalidCredentialSpendingDate { got: Date, expected: Date }, + + #[error("the current multisig contract is not using 'AbsolutePercentage' threshold!")] + InvalidMultisigThreshold, + + #[error( + "the received payment contained more than a single ticket. that's currently not supported" + )] + MultipleTickets, + + #[error("Nyxd Error - {0}")] + NyxdError(#[from] nym_validator_client::nyxd::error::NyxdError), + + #[error("This gateway is only accepting coconut credentials for bandwidth")] + OnlyCoconutCredentials, + + #[error("insufficient bandwidth available to process the request. required: {required}B, available: {available}B")] + OutOfBandwidth { required: i64, available: i64 }, + + #[error("Internal gateway storage error")] + StorageError(#[from] nym_gateway_storage::error::StorageError), + + #[error("{0}")] + UnknownTicketType(#[from] nym_credentials_interface::UnknownTicketType), +} + +impl From for Error { + fn from(err: EcashTicketError) -> Self { + // don't expose storage issue details to the user + if let EcashTicketError::InternalStorageFailure { source } = err { + Error::StorageError(source) + } else { + Error::EcashFailure(err) + } + } +} diff --git a/common/credential-verification/src/lib.rs b/common/credential-verification/src/lib.rs new file mode 100644 index 0000000000..bb3a0cab8f --- /dev/null +++ b/common/credential-verification/src/lib.rs @@ -0,0 +1,156 @@ +// Copyright 2024 - Nym Technologies SA +// SPDX-License-Identifier: Apache-2.0 + +use bandwidth_storage_manager::BandwidthStorageManager; +use std::sync::Arc; +use time::{Date, OffsetDateTime}; +use tracing::*; + +use nym_credentials::ecash::utils::{ecash_today, EcashTime}; +use nym_credentials_interface::{Bandwidth, ClientTicket, TicketType}; +use nym_gateway_requests::models::CredentialSpendingRequest; +use nym_gateway_storage::Storage; + +pub use client_bandwidth::*; +use ecash::EcashManager; +pub use error::*; + +pub mod bandwidth_storage_manager; +mod client_bandwidth; +pub mod ecash; +pub mod error; + +pub struct CredentialVerifier { + credential: CredentialSpendingRequest, + ecash_verifier: Arc>, + bandwidth_storage_manager: BandwidthStorageManager, +} + +impl CredentialVerifier { + pub fn new( + credential: CredentialSpendingRequest, + ecash_verifier: Arc>, + bandwidth_storage_manager: BandwidthStorageManager, + ) -> Self { + CredentialVerifier { + credential, + ecash_verifier, + bandwidth_storage_manager, + } + } + + fn check_credential_spending_date(&self, today: Date) -> Result<()> { + let proposed = self.credential.data.spend_date; + trace!("checking ticket spending date..."); + + if today != proposed { + trace!("invalid credential spending date. received {proposed}"); + return Err(Error::InvalidCredentialSpendingDate { + got: proposed, + expected: today, + }); + } + Ok(()) + } + + async fn check_bloomfilter(&self, serial_number: &Vec) -> Result<()> { + trace!("checking the bloomfilter..."); + + let spent = self.ecash_verifier.check_double_spend(serial_number).await; + + if spent { + trace!("the credential has already been spent before at some gateway before (bloomfilter failure)"); + return Err(Error::BandwidthCredentialAlreadySpent); + } + Ok(()) + } + + async fn check_local_db_for_double_spending(&self, serial_number: &[u8]) -> Result<()> { + trace!("checking local db for double spending..."); + + let spent = self + .bandwidth_storage_manager + .storage + .contains_ticket(serial_number) + .await?; + if spent { + trace!("the credential has already been spent before at this gateway"); + return Err(Error::BandwidthCredentialAlreadySpent); + } + Ok(()) + } + + async fn cryptographically_verify_ticket(&self) -> Result<()> { + trace!("attempting to perform ticket verification..."); + + let aggregated_verification_key = self + .ecash_verifier + .verification_key(self.credential.data.epoch_id) + .await?; + + self.ecash_verifier + .check_payment(&self.credential.data, &aggregated_verification_key) + .await?; + Ok(()) + } + + async fn store_received_ticket(&self, received_at: OffsetDateTime) -> Result { + trace!("storing received ticket"); + let ticket_id = self + .bandwidth_storage_manager + .storage + .insert_received_ticket( + self.bandwidth_storage_manager.client_id, + received_at, + self.credential.encoded_serial_number(), + self.credential.to_bytes(), + ) + .await?; + Ok(ticket_id) + } + + fn async_verify_ticket(&self, ticket_id: i64) { + let client_ticket = ClientTicket::new(self.credential.data.clone(), ticket_id); + + self.ecash_verifier.async_verify(client_ticket); + } + + pub async fn verify(&mut self) -> Result { + let received_at = OffsetDateTime::now_utc(); + let spend_date = ecash_today(); + + // check if the credential hasn't been spent before + let serial_number = self.credential.data.encoded_serial_number(); + let credential_type = TicketType::try_from_encoded(self.credential.data.payment.t_type)?; + + if self.credential.data.payment.spend_value != 1 { + return Err(Error::MultipleTickets); + } + + self.check_credential_spending_date(spend_date.ecash_date())?; + self.check_bloomfilter(&serial_number).await?; + self.check_local_db_for_double_spending(&serial_number) + .await?; + + // TODO: do we HAVE TO do it? + self.cryptographically_verify_ticket().await?; + + let ticket_id = self.store_received_ticket(received_at).await?; + self.async_verify_ticket(ticket_id); + + // TODO: double storing? + // self.store_spent_credential(serial_number_bs58).await?; + + let bandwidth = Bandwidth::ticket_amount(credential_type.into()); + + self.bandwidth_storage_manager + .increase_bandwidth(bandwidth, spend_date) + .await?; + + Ok(self + .bandwidth_storage_manager + .client_bandwidth + .bandwidth + .bytes) + } +} diff --git a/common/credentials-interface/src/lib.rs b/common/credentials-interface/src/lib.rs index fb0cd1a5df..4121291b5a 100644 --- a/common/credentials-interface/src/lib.rs +++ b/common/credentials-interface/src/lib.rs @@ -319,3 +319,24 @@ impl Default for AvailableBandwidth { } } } + +#[derive(Debug, Copy, Clone)] +pub struct Bandwidth { + value: u64, +} + +impl Bandwidth { + pub const fn new_unchecked(value: u64) -> Bandwidth { + Bandwidth { value } + } + + pub fn ticket_amount(typ: TicketTypeRepr) -> Self { + Bandwidth { + value: typ.bandwidth_value(), + } + } + + pub fn value(&self) -> u64 { + self.value + } +} diff --git a/gateway/Cargo.toml b/gateway/Cargo.toml index e5f43bc54d..2a2e7ac51e 100644 --- a/gateway/Cargo.toml +++ b/gateway/Cargo.toml @@ -30,8 +30,6 @@ bip39 = { workspace = true } bs58 = { workspace = true } clap = { workspace = true, features = ["cargo", "derive"], optional = true } colored = { workspace = true } -cosmwasm-std = { workspace = true } -cw-utils = { workspace = true } dashmap = { workspace = true } dirs = { workspace = true } dotenvy = { workspace = true } @@ -64,9 +62,7 @@ tokio-tungstenite = { workspace = true } tokio-util = { workspace = true, features = ["codec"] } tracing = { workspace = true } url = { workspace = true, features = ["serde"] } -time = { workspace = true } zeroize = { workspace = true } -bloomfilter = { workspace = true } # internal @@ -76,9 +72,8 @@ nym-bin-common = { path = "../common/bin-common" } nym-config = { path = "../common/config" } nym-credentials = { path = "../common/credentials" } nym-credentials-interface = { path = "../common/credentials-interface" } +nym-credential-verification = { path = "../common/credential-verification" } nym-crypto = { path = "../common/crypto" } -nym-ecash-contract-common = { path = "../common/cosmwasm-smart-contracts/ecash-contract" } -nym-ecash-double-spending = { path = "../common/ecash-double-spending" } nym-gateway-storage = { path = "../common/gateway-storage" } nym-gateway-requests = { path = "../common/gateway-requests" } nym-mixnet-client = { path = "../common/client-libs/mixnet-client" } diff --git a/gateway/src/error.rs b/gateway/src/error.rs index 157f3f507e..e7786db443 100644 --- a/gateway/src/error.rs +++ b/gateway/src/error.rs @@ -14,7 +14,6 @@ use std::path::PathBuf; use thiserror::Error; pub use crate::node::client_handling::websocket::connection_handler::authenticated::RequestHandlingError; -use crate::node::client_handling::websocket::connection_handler::ecash::error::EcashTicketError; #[derive(Debug, Error)] pub enum GatewayError { @@ -170,12 +169,6 @@ pub enum GatewayError { source: RequestHandlingError, }, - #[error("ecash related failure: {source}")] - EcashFailure { - #[from] - source: EcashTicketError, - }, - #[error("failed to catch an interrupt: {source}")] ShutdownFailure { source: Box, @@ -196,9 +189,6 @@ pub enum GatewayError { source: ipnetwork::IpNetworkError, }, - #[error("the current multisig contract is not using 'AbsolutePercentage' threshold!")] - InvalidMultisigThreshold, - #[cfg(all(feature = "wireguard", target_os = "linux"))] #[error("failed to remove wireguard interface: {0}")] WireguardInterfaceError(#[from] defguard_wireguard_rs::error::WireguardInterfaceError), @@ -211,6 +201,9 @@ pub enum GatewayError { AuthenticatorStartError { source: Box, }, + + #[error("{0}")] + CredentialVefiricationError(#[from] nym_credential_verification::Error), } impl From for GatewayError { diff --git a/gateway/src/node/client_handling/bandwidth.rs b/gateway/src/node/client_handling/bandwidth.rs index ebfb91b0c1..0113be49b3 100644 --- a/gateway/src/node/client_handling/bandwidth.rs +++ b/gateway/src/node/client_handling/bandwidth.rs @@ -1,10 +1,8 @@ // Copyright 2021-2024 - Nym Technologies SA // SPDX-License-Identifier: GPL-3.0-only -use nym_network_defaults::TicketTypeRepr; use std::num::ParseIntError; use thiserror::Error; -use time::error::ComponentRange; use tracing::error; #[derive(Debug, Error)] @@ -23,32 +21,4 @@ pub enum BandwidthError { #[source] source: ParseIntError, }, - - #[error("failed to parse expiry timestamp into proper datetime: {source}")] - InvalidExpiryDate { - unix_timestamp: i64, - #[source] - source: ComponentRange, - }, -} - -#[derive(Debug, Copy, Clone)] -pub struct Bandwidth { - value: u64, -} - -impl Bandwidth { - pub const fn new_unchecked(value: u64) -> Bandwidth { - Bandwidth { value } - } - - pub fn ticket_amount(typ: TicketTypeRepr) -> Self { - Bandwidth { - value: typ.bandwidth_value(), - } - } - - pub fn value(&self) -> u64 { - self.value - } } diff --git a/gateway/src/node/client_handling/mod.rs b/gateway/src/node/client_handling/mod.rs index b195b8d693..eecb0735db 100644 --- a/gateway/src/node/client_handling/mod.rs +++ b/gateway/src/node/client_handling/mod.rs @@ -1,12 +1,7 @@ // Copyright 2020-2024 - Nym Technologies SA // SPDX-License-Identifier: GPL-3.0-only -use crate::node::client_handling::bandwidth::Bandwidth; - pub(crate) mod active_clients; mod bandwidth; pub(crate) mod embedded_clients; pub(crate) mod websocket; - -pub(crate) const FREE_TESTNET_BANDWIDTH_VALUE: Bandwidth = - Bandwidth::new_unchecked(64 * 1024 * 1024 * 1024); // 64GB diff --git a/gateway/src/node/client_handling/websocket/common_state.rs b/gateway/src/node/client_handling/websocket/common_state.rs index 3a2a206368..2120b33422 100644 --- a/gateway/src/node/client_handling/websocket/common_state.rs +++ b/gateway/src/node/client_handling/websocket/common_state.rs @@ -1,8 +1,7 @@ // Copyright 2024 - Nym Technologies SA // SPDX-License-Identifier: GPL-3.0-only -use crate::node::client_handling::websocket::connection_handler::ecash::EcashManager; -use crate::node::client_handling::websocket::connection_handler::BandwidthFlushingBehaviourConfig; +use nym_credential_verification::{ecash::EcashManager, BandwidthFlushingBehaviourConfig}; use nym_crypto::asymmetric::identity; use std::sync::Arc; diff --git a/gateway/src/node/client_handling/websocket/connection_handler/authenticated.rs b/gateway/src/node/client_handling/websocket/connection_handler/authenticated.rs index d0f039fcca..12bbb16b51 100644 --- a/gateway/src/node/client_handling/websocket/connection_handler/authenticated.rs +++ b/gateway/src/node/client_handling/websocket/connection_handler/authenticated.rs @@ -2,24 +2,22 @@ // SPDX-License-Identifier: GPL-3.0-only use crate::node::client_handling::{ - bandwidth::{Bandwidth, BandwidthError}, + bandwidth::BandwidthError, websocket::{ - connection_handler::{ - ecash::error::EcashTicketError, ClientBandwidth, ClientDetails, FreshHandler, - }, + connection_handler::{ClientDetails, FreshHandler}, message_receiver::{ IsActive, IsActiveRequestReceiver, IsActiveResultSender, MixMessageReceiver, }, }, - FREE_TESTNET_BANDWIDTH_VALUE, }; use futures::{ future::{FusedFuture, OptionFuture}, FutureExt, StreamExt, }; -use nym_credentials::ecash::utils::{ecash_today, EcashTime}; -use nym_credentials_interface::{ClientTicket, CredentialSpendingData, TicketType}; -use nym_gateway_requests::models::CredentialSpendingRequest; +use nym_credential_verification::CredentialVerifier; +use nym_credential_verification::{ + bandwidth_storage_manager::BandwidthStorageManager, ClientBandwidth, +}; use nym_gateway_requests::{ types::{BinaryRequest, ServerResponse}, ClientControlRequest, GatewayRequestsError, SimpleGatewayRequestsError, @@ -29,10 +27,8 @@ use nym_sphinx::forwarding::packet::MixPacket; use nym_task::TaskClient; use nym_validator_client::coconut::EcashApiError; use rand::{CryptoRng, Rng}; -use si_scale::helpers::bibytes2; use std::{process, time::Duration}; use thiserror::Error; -use time::{Date, OffsetDateTime}; use tokio::io::{AsyncRead, AsyncWrite}; use tokio_tungstenite::tungstenite::{protocol::Message, Error as WsError}; use tracing::*; @@ -59,20 +55,6 @@ pub enum RequestHandlingError { #[error("credential has been rejected by the validators")] RejectedProposal, - #[error( - "the provided credential has an invalid spending date. got {got} but expected {expected}" - )] - InvalidCredentialSpendingDate { got: Date, expected: Date }, - - #[error("the provided bandwidth credential has already been spent before at this gateway")] - BandwidthCredentialAlreadySpent, - - #[error("This gateway is only accepting coconut credentials for bandwidth")] - OnlyCoconutCredentials, - - #[error("Nyxd Error - {0}")] - NyxdError(#[from] nym_validator_client::nyxd::error::NyxdError), - #[error("Validator API error - {0}")] APIError(#[from] nym_validator_client::ValidatorClientError), @@ -94,28 +76,19 @@ pub enum RequestHandlingError { #[error("failed to recover bandwidth value: {0}")] BandwidthRecoveryFailure(#[from] BandwidthError), - #[error("insufficient bandwidth available to process the request. required: {required}B, available: {available}B")] - OutOfBandwidth { required: i64, available: i64 }, - - #[error(transparent)] - EcashFailure(EcashTicketError), - - #[error( - "the received payment contained more than a single ticket. that's currently not supported" - )] - MultipleTickets, - #[error("{0}")] - UnknownTicketType(#[from] nym_credentials_interface::UnknownTicketType), + CredentialVerification(#[from] nym_credential_verification::Error), } impl RequestHandlingError { fn into_error_message(self) -> Message { let server_response = match self { - RequestHandlingError::OutOfBandwidth { - required, - available, - } => ServerResponse::TypedError { + RequestHandlingError::CredentialVerification( + nym_credential_verification::Error::OutOfBandwidth { + required, + available, + }, + ) => ServerResponse::TypedError { error: SimpleGatewayRequestsError::OutOfBandwidth { required, available, @@ -127,17 +100,6 @@ impl RequestHandlingError { } } -impl From for RequestHandlingError { - fn from(err: EcashTicketError) -> Self { - // don't expose storage issue details to the user - if let EcashTicketError::InternalStorageFailure { source } = err { - RequestHandlingError::StorageError(source) - } else { - RequestHandlingError::EcashFailure(err) - } - } -} - /// Helper trait that allows converting result of handling client request into a websocket message // Note: I couldn't have implemented a normal "From" trait as both `Message` and `Result` are foreign types trait IntoWSMessage { @@ -155,8 +117,8 @@ impl IntoWSMessage for Result { pub(crate) struct AuthenticatedHandler { inner: FreshHandler, + bandwidth_storage_manager: BandwidthStorageManager, client: ClientDetails, - client_bandwidth: ClientBandwidth, mix_receiver: MixMessageReceiver, // Occasionally the handler is requested to ping the connected client for confirm that it's // active, such as when a duplicate connection is detected. This hashmap stores the oneshot @@ -209,9 +171,15 @@ where })?; Ok(AuthenticatedHandler { + bandwidth_storage_manager: BandwidthStorageManager::new( + fresh.shared_state.storage.clone(), + ClientBandwidth::new(bandwidth.into()), + client.id, + fresh.shared_state.bandwidth_cfg, + fresh.shared_state.only_coconut_credentials, + ), inner: fresh, client, - client_bandwidth: ClientBandwidth::new(bandwidth.into()), mix_receiver, is_active_request_receiver, is_active_ping_pending_reply: None, @@ -225,55 +193,6 @@ where .disconnect(self.client.address) } - async fn expire_bandwidth(&mut self) -> Result<(), RequestHandlingError> { - self.inner.expire_bandwidth(self.client.id).await?; - self.client_bandwidth.bandwidth = Default::default(); - self.client_bandwidth.update_sync_data(); - Ok(()) - } - - /// Increases the amount of available bandwidth of the connected client by the specified value. - /// - /// # Arguments - /// - /// * `amount`: amount to increase the available bandwidth by. - /// * `expiration` : the expiration date of that bandwidth - async fn increase_bandwidth( - &mut self, - bandwidth: Bandwidth, - expiration: OffsetDateTime, - ) -> Result<(), RequestHandlingError> { - self.client_bandwidth.bandwidth.bytes += bandwidth.value() as i64; - self.client_bandwidth.bytes_delta_since_sync += bandwidth.value() as i64; - self.client_bandwidth.bandwidth.expiration = expiration; - - // any increases to bandwidth should get flushed immediately - // (we don't want to accidentally miss somebody claiming a gigabyte voucher) - self.sync_expiration().await?; - self.sync_bandwidth().await - } - - /// Decreases the amount of available bandwidth of the connected client by the specified value. - /// - /// # Arguments - /// - /// * `amount`: amount to decrease the available bandwidth by. - async fn consume_bandwidth(&mut self, amount: i64) -> Result<(), RequestHandlingError> { - self.client_bandwidth.bandwidth.bytes -= amount; - self.client_bandwidth.bytes_delta_since_sync -= amount; - - // since we're going to be operating on a fair use policy anyway, even if we crash and let extra few packets - // through, that's completely fine - if self - .client_bandwidth - .should_sync(self.inner.shared_state.bandwidth_cfg) - { - self.sync_bandwidth().await?; - } - - Ok(()) - } - /// Forwards the received mix packet from the client into the mix network. /// /// # Arguments @@ -286,109 +205,6 @@ where } } - async fn check_local_db_for_double_spending( - &self, - serial_number: &[u8], - ) -> Result<(), RequestHandlingError> { - trace!("checking local db for double spending..."); - - let spent = self - .inner - .shared_state - .storage - .contains_ticket(serial_number) - .await?; - if spent { - trace!("the credential has already been spent before at this gateway"); - return Err(RequestHandlingError::BandwidthCredentialAlreadySpent); - } - Ok(()) - } - - async fn check_bloomfilter(&self, serial_number: &Vec) -> Result<(), RequestHandlingError> { - trace!("checking the bloomfilter..."); - - let spent = self - .inner - .shared_state - .ecash_verifier - .check_double_spend(serial_number) - .await; - - if spent { - trace!("the credential has already been spent before at some gateway before (bloomfilter failure)"); - return Err(RequestHandlingError::BandwidthCredentialAlreadySpent); - } - Ok(()) - } - - fn check_credential_spending_date( - &self, - proposed: Date, - today: Date, - ) -> Result<(), RequestHandlingError> { - trace!("checking ticket spending date..."); - - if today != proposed { - trace!("invalid credential spending date. received {proposed}"); - return Err(RequestHandlingError::InvalidCredentialSpendingDate { - got: proposed, - expected: today, - }); - } - Ok(()) - } - - async fn cryptographically_verify_ticket( - &self, - credential: &CredentialSpendingRequest, - ) -> Result<(), RequestHandlingError> { - trace!("attempting to perform ticket verification..."); - - let aggregated_verification_key = self - .inner - .shared_state - .ecash_verifier - .verification_key(credential.data.epoch_id) - .await?; - - self.inner - .shared_state - .ecash_verifier - .check_payment(&credential.data, &aggregated_verification_key) - .await?; - Ok(()) - } - - fn async_verify_ticket(&self, ticket: CredentialSpendingData, ticket_id: i64) { - let client_ticket = ClientTicket::new(ticket, ticket_id); - - self.inner - .shared_state - .ecash_verifier - .async_verify(client_ticket); - } - - async fn store_received_ticket( - &self, - ticket_data: &CredentialSpendingRequest, - received_at: OffsetDateTime, - ) -> Result { - trace!("storing received ticket"); - let ticket_id = self - .inner - .shared_state - .storage - .insert_received_ticket( - self.client.id, - received_at, - ticket_data.encoded_serial_number(), - ticket_data.to_bytes(), - ) - .await?; - Ok(ticket_id) - } - /// Tries to handle the received bandwidth request by checking correctness of the received data /// and if successful, increases client's bandwidth by an appropriate amount. /// @@ -401,7 +217,6 @@ where enc_credential: Vec, iv: Vec, ) -> Result { - let received_at = OffsetDateTime::now_utc(); // TODO: change it into a span field instead once we move to tracing debug!( "handling e-cash bandwidth request from {}", @@ -413,107 +228,17 @@ where &self.client.shared_keys, iv, )?; - let spend_date = ecash_today(); + let mut verifier = CredentialVerifier::new( + credential, + self.inner.shared_state.ecash_verifier.clone(), + self.bandwidth_storage_manager.clone(), + ); - // check if the credential hasn't been spent before - let serial_number = credential.data.encoded_serial_number(); - let credential_type = TicketType::try_from_encoded(credential.data.payment.t_type)?; - - if credential.data.payment.spend_value != 1 { - return Err(RequestHandlingError::MultipleTickets); - } - - self.check_credential_spending_date(credential.data.spend_date, spend_date.ecash_date())?; - self.check_bloomfilter(&serial_number).await?; - self.check_local_db_for_double_spending(&serial_number) - .await?; - - // TODO: do we HAVE TO do it? - self.cryptographically_verify_ticket(&credential).await?; - - let ticket_id = self.store_received_ticket(&credential, received_at).await?; - self.async_verify_ticket(credential.data, ticket_id); - - // TODO: double storing? - // self.store_spent_credential(serial_number_bs58).await?; - - let bandwidth = Bandwidth::ticket_amount(credential_type.into()); - - self.increase_bandwidth(bandwidth, spend_date).await?; - - let available_total = self.client_bandwidth.bandwidth.bytes; + let available_total = verifier.verify().await?; Ok(ServerResponse::Bandwidth { available_total }) } - async fn handle_claim_testnet_bandwidth( - &mut self, - ) -> Result { - debug!("handling testnet bandwidth request"); - - if self.inner.shared_state.only_coconut_credentials { - return Err(RequestHandlingError::OnlyCoconutCredentials); - } - - self.increase_bandwidth(FREE_TESTNET_BANDWIDTH_VALUE, ecash_today()) - .await?; - let available_total = self.client_bandwidth.bandwidth.bytes; - - Ok(ServerResponse::Bandwidth { available_total }) - } - - async fn sync_expiration(&mut self) -> Result<(), RequestHandlingError> { - self.inner - .shared_state - .storage - .set_expiration(self.client.id, self.client_bandwidth.bandwidth.expiration) - .await?; - Ok(()) - } - - #[instrument(level = "trace", skip_all)] - async fn sync_bandwidth(&mut self) -> Result<(), RequestHandlingError> { - trace!("syncing client bandwidth with the underlying storage"); - let updated = self - .inner - .shared_state - .storage - .increase_bandwidth(self.client.id, self.client_bandwidth.bytes_delta_since_sync) - .await?; - - trace!(updated); - - self.client_bandwidth.bandwidth.bytes = updated; - - self.client_bandwidth.update_sync_data(); - Ok(()) - } - - #[instrument(skip_all)] - async fn try_use_bandwidth( - &mut self, - required_bandwidth: i64, - ) -> Result { - if self.client_bandwidth.bandwidth.expired() { - self.expire_bandwidth().await?; - } - let available_bandwidth = self.client_bandwidth.bandwidth.bytes; - - if available_bandwidth < required_bandwidth { - return Err(RequestHandlingError::OutOfBandwidth { - required: required_bandwidth, - available: available_bandwidth, - }); - } - - let available_bi2 = bibytes2(available_bandwidth as f64); - let required_bi2 = bibytes2(required_bandwidth as f64); - debug!(available = available_bi2, required = required_bi2); - - self.consume_bandwidth(required_bandwidth).await?; - Ok(available_bandwidth) - } - /// Tries to handle request to forward sphinx packet into the network. The request can only succeed /// if the client has enough available bandwidth. /// @@ -529,7 +254,10 @@ where ) -> Result { let required_bandwidth = mix_packet.packet().len() as i64; - let remaining_bandwidth = self.try_use_bandwidth(required_bandwidth).await?; + let remaining_bandwidth = self + .bandwidth_storage_manager + .try_use_bandwidth(required_bandwidth) + .await?; self.forward_packet(mix_packet); Ok(ServerResponse::Send { @@ -589,8 +317,10 @@ where .into_error_message() } ClientControlRequest::ClaimFreeTestnetBandwidth => self + .bandwidth_storage_manager .handle_claim_testnet_bandwidth() .await + .map_err(|e| e.into()) .into_ws_message(), other => RequestHandlingError::IllegalRequest { additional_context: format!( diff --git a/gateway/src/node/client_handling/websocket/connection_handler/fresh.rs b/gateway/src/node/client_handling/websocket/connection_handler/fresh.rs index 0986532896..f56f14e0eb 100644 --- a/gateway/src/node/client_handling/websocket/connection_handler/fresh.rs +++ b/gateway/src/node/client_handling/websocket/connection_handler/fresh.rs @@ -566,7 +566,7 @@ where .unwrap_or_default(); let bandwidth_remaining = if available_bandwidth.expired() { - self.expire_bandwidth(client_id).await?; + self.shared_state.storage.reset_bandwidth(client_id).await?; 0 } else { available_bandwidth.bytes @@ -582,10 +582,6 @@ where )) } - pub(crate) async fn expire_bandwidth(&self, client_id: i64) -> Result<(), StorageError> { - self.shared_state.storage.reset_bandwidth(client_id).await - } - /// Attempts to finalize registration of the client by storing the derived shared keys in the /// persistent store as well as creating entry for its bandwidth allocation. /// diff --git a/gateway/src/node/client_handling/websocket/connection_handler/mod.rs b/gateway/src/node/client_handling/websocket/connection_handler/mod.rs index aeebdb02fa..0ffde8feed 100644 --- a/gateway/src/node/client_handling/websocket/connection_handler/mod.rs +++ b/gateway/src/node/client_handling/websocket/connection_handler/mod.rs @@ -2,15 +2,13 @@ // SPDX-License-Identifier: GPL-3.0-only use crate::config::Config; -use nym_credentials_interface::AvailableBandwidth; +use nym_credential_verification::BandwidthFlushingBehaviourConfig; use nym_gateway_requests::registration::handshake::SharedKeys; use nym_gateway_requests::ServerResponse; use nym_gateway_storage::Storage; use nym_sphinx::DestinationAddressBytes; use nym_task::TaskClient; use rand::{CryptoRng, Rng}; -use std::time::Duration; -use time::OffsetDateTime; use tokio::io::{AsyncRead, AsyncWrite}; use tokio_tungstenite::WebSocketStream; use tracing::{instrument, trace, warn}; @@ -20,7 +18,6 @@ pub(crate) use self::authenticated::AuthenticatedHandler; pub(crate) use self::fresh::FreshHandler; pub(crate) mod authenticated; -pub(crate) mod ecash; mod fresh; // TODO: note for my future self to consider the following idea: @@ -132,15 +129,6 @@ pub(crate) async fn handle_connection( trace!("The handler is done!"); } -#[derive(Debug, Clone, Copy)] -pub(crate) struct BandwidthFlushingBehaviourConfig { - /// Defines maximum delay between client bandwidth information being flushed to the persistent storage. - pub client_bandwidth_max_flushing_rate: Duration, - - /// Defines a maximum change in client bandwidth before it gets flushed to the persistent storage. - pub client_bandwidth_max_delta_flushing_amount: i64, -} - impl<'a> From<&'a Config> for BandwidthFlushingBehaviourConfig { fn from(value: &'a Config) -> Self { BandwidthFlushingBehaviourConfig { @@ -151,43 +139,3 @@ impl<'a> From<&'a Config> for BandwidthFlushingBehaviourConfig { } } } - -pub(crate) struct ClientBandwidth { - pub(crate) bandwidth: AvailableBandwidth, - pub(crate) last_flushed: OffsetDateTime, - - /// the number of bytes the client had during the last sync. - /// it is used to determine whether the current value should be synced with the storage - /// by checking the delta with the known amount - pub(crate) bytes_at_last_sync: i64, - pub(crate) bytes_delta_since_sync: i64, -} - -impl ClientBandwidth { - pub(crate) fn new(bandwidth: AvailableBandwidth) -> ClientBandwidth { - ClientBandwidth { - bandwidth, - last_flushed: OffsetDateTime::now_utc(), - bytes_at_last_sync: bandwidth.bytes, - bytes_delta_since_sync: 0, - } - } - - pub(crate) fn should_sync(&self, cfg: BandwidthFlushingBehaviourConfig) -> bool { - if self.bytes_delta_since_sync.abs() >= cfg.client_bandwidth_max_delta_flushing_amount { - return true; - } - - if self.last_flushed + cfg.client_bandwidth_max_flushing_rate < OffsetDateTime::now_utc() { - return true; - } - - false - } - - pub(crate) fn update_sync_data(&mut self) { - self.last_flushed = OffsetDateTime::now_utc(); - self.bytes_at_last_sync = self.bandwidth.bytes; - self.bytes_delta_since_sync = 0; - } -} diff --git a/gateway/src/node/mod.rs b/gateway/src/node/mod.rs index dc4ceec66f..94cdcf7776 100644 --- a/gateway/src/node/mod.rs +++ b/gateway/src/node/mod.rs @@ -12,10 +12,12 @@ use crate::http::HttpApiBuilder; use crate::node::client_handling::active_clients::ActiveClientsStore; use crate::node::client_handling::embedded_clients::{LocalEmbeddedClientHandle, MessageRouter}; use crate::node::client_handling::websocket; -use crate::node::client_handling::websocket::connection_handler::ecash::EcashManager; use crate::node::helpers::{initialise_main_storage, load_network_requester_config}; use crate::node::mixnet_handling::receiver::connection_handler::ConnectionHandler; use futures::channel::{mpsc, oneshot}; +use nym_credential_verification::ecash::{ + credential_sender::CredentialHandlerConfig, EcashManager, +}; use nym_crypto::asymmetric::{encryption, identity}; use nym_mixnet_client::forwarder::{MixForwardingSender, PacketForwarder}; use nym_network_defaults::NymNetworkDetails; @@ -35,7 +37,6 @@ pub(crate) mod client_handling; pub(crate) mod helpers; pub(crate) mod mixnet_handling; -use crate::node::client_handling::websocket::connection_handler::ecash::credential_sender::CredentialHandlerConfig; pub use nym_gateway_storage::{PersistentStorage, Storage}; // TODO: should this struct live here? @@ -620,16 +621,14 @@ impl Gateway { .maximum_time_between_redemption, }; - let ecash_manager = { - EcashManager::new( - handler_config, - nyxd_client, - self.identity_keypair.public_key().to_bytes(), - shutdown.fork("EcashVerifier"), - self.storage.clone(), - ) - .await - }?; + let ecash_manager = EcashManager::new( + handler_config, + nyxd_client, + self.identity_keypair.public_key().to_bytes(), + shutdown.fork("EcashVerifier"), + self.storage.clone(), + ) + .await?; let mix_forwarding_channel = self.start_packet_forwarder(shutdown.fork("PacketForwarder")); From 12e8d3468b601977557f8d3a8cb54e915eccb0ea Mon Sep 17 00:00:00 2001 From: import this <97586125+serinko@users.noreply.github.com> Date: Tue, 10 Sep 2024 13:05:19 +0000 Subject: [PATCH 75/93] [DOCs/operators]: Release notes v2024.10-caramello, nym-node simplier setup & wg troubleshooting configuration (#4860) * add icmp and dns configuration command * add parameters and vars table and make explicit steps * add features to changelog * add operators updates & tasks to changelog * syntax edits --- documentation/operators/src/changelog.md | 352 ++++++++++++++++++ .../operators/src/nodes/configuration.md | 23 +- documentation/operators/src/nodes/setup.md | 144 ++++--- 3 files changed, 454 insertions(+), 65 deletions(-) diff --git a/documentation/operators/src/changelog.md b/documentation/operators/src/changelog.md index 707adc484c..9a364f0441 100644 --- a/documentation/operators/src/changelog.md +++ b/documentation/operators/src/changelog.md @@ -2,6 +2,358 @@ This page displays a full list of all the changes during our release cycle from [`v2024.3-eclipse`](https://github.com/nymtech/nym/blob/nym-binaries-v2024.3-eclipse/CHANGELOG.md) onwards. Operators can find here the newest updates together with links to relevant documentation. The list is sorted so that the newest changes appear first. +## `v2024.10-caramello` + +- [Release binaries](https://github.com/nymtech/nym/releases/tag/nym-binaries-v2024.10-caramello) +- [Release CHANGELOG.md](https://github.com/nymtech/nym/blob/nym-binaries-v2024.10-caramello/CHANGELOG.md) +- [`nym-node`](nodes/nym-node.md) version `1.1.7` + +~~~admonish example collapsible=true title='CHANGELOG.md' +- Backport 4844 and 4845 ([#4857]) +- Bugfix/client registration vol2 ([#4856]) +- Remove wireguard feature flag and pass runtime enabled flag ([#4839]) +- Eliminate cancel unsafe sig awaiting ([#4834]) +- added explicit updateable admin to the mixnet contract ([#4822]) +- using legacy signing payload in CLI and verifying both variants in contract ([#4821]) +- adding ecash contract address ([#4819]) +- Check profit margin of node before defaulting to hardcoded value ([#4802]) +- Sync last_seen_bandwidth immediately ([#4774]) +- Feature/additional ecash nym cli utils ([#4773]) +- Better storage error logging ([#4772]) +- bugfix: make sure DKG parses data out of events if logs are empty ([#4764]) +- Fix clippy on rustc beta toolchain ([#4746]) +- Fix clippy for beta toolchain ([#4742]) +- Disable testnet-manager on non-unix ([#4741]) +- Don't set NYM_VPN_API to default ([#4740]) +- Update publish-nym-binaries.yml ([#4739]) +- Update ci-build-upload-binaries.yml ([#4738]) +- Add NYM_VPN_API to network config ([#4736]) +- Re-export RecipientFormattingError in nym sdk ([#4735]) +- Persist wireguard peers ([#4732]) +- Fix tokio error in 1.39 ([#4730]) +- Feature/vesting purge plus ranged cost params ([#4716]) +- Fix (some) feature unification build failures ([#4681]) +- Feature Compact Ecash : The One PR ([#4623]) + +[#4857]: https://github.com/nymtech/nym/pull/4857 +[#4856]: https://github.com/nymtech/nym/pull/4856 +[#4839]: https://github.com/nymtech/nym/pull/4839 +[#4834]: https://github.com/nymtech/nym/pull/4834 +[#4822]: https://github.com/nymtech/nym/pull/4822 +[#4821]: https://github.com/nymtech/nym/pull/4821 +[#4819]: https://github.com/nymtech/nym/pull/4819 +[#4802]: https://github.com/nymtech/nym/pull/4802 +[#4774]: https://github.com/nymtech/nym/pull/4774 +[#4773]: https://github.com/nymtech/nym/pull/4773 +[#4772]: https://github.com/nymtech/nym/pull/4772 +[#4764]: https://github.com/nymtech/nym/pull/4764 +[#4746]: https://github.com/nymtech/nym/pull/4746 +[#4742]: https://github.com/nymtech/nym/pull/4742 +[#4741]: https://github.com/nymtech/nym/pull/4741 +[#4740]: https://github.com/nymtech/nym/pull/4740 +[#4739]: https://github.com/nymtech/nym/pull/4739 +[#4738]: https://github.com/nymtech/nym/pull/4738 +[#4736]: https://github.com/nymtech/nym/pull/4736 +[#4735]: https://github.com/nymtech/nym/pull/4735 +[#4732]: https://github.com/nymtech/nym/pull/4732 +[#4730]: https://github.com/nymtech/nym/pull/4730 +[#4716]: https://github.com/nymtech/nym/pull/4716 +[#4681]: https://github.com/nymtech/nym/pull/4681 +[#4623]: https://github.com/nymtech/nym/pull/4623 +~~~ + +### Features + +- [Add 1GB/day/user bandwidth cap](https://github.com/nymtech/nym/pull/4717) + +~~~admonish example collapsible=true title='Testing steps performed' +**Scenario 1: Bandwidth Decreasing Continuously** + +1. Started the client and noted the initial bandwidth (e.g., 1GB). +2. Used the client and tracked bandwidth usage over time (e.g., decrease by 100MB every hour). +3. Restarted the client after some usage. +4. Verified the bandwidth continued from the last recorded value, not reset. + +The bandwidth continued decreasing without resetting upon restart. Logs and reports correctly reflected the decreasing bandwidth. + +**Scenario 2: Bandwidth Reset Next Day** + +1. Used the client normally until the end of the day. +2. Suspended some clients and kept others active. +3. Checked bandwidth at midnight. +4. Verified that bandwidth reset to 1GB for both suspended and active clients. + +Bandwidth reset to 1GB for all clients at midnight. Logs and reports correctly showed the reset. + +**Scenario 3: Bandwidth Reset at a Different Time (e.g., Midday)** + +1. Configured the system to reset bandwidth at midday. +2. Used the client and monitored bandwidth until midday. +3. Kept the client connected during the reset time. +4. Verified that bandwidth reset to 1GB live at midday. + +Bandwidth reset to 1GB at midday while the client was connected. Logs and reports correctly reflected the reset. + +**Scenario 4: Stale Check for 3 Days** + +1. Kept a client inactive for 3 days. +2. Verified removal from the peer list after 3 days. +3. Reconnected the client after 3 days and checked for a new private IP. +4. Restarted a client within 3 days and verified it retained the same private IP. + +The client was removed from the peer list after 3 days of inactivity. Upon re-connection after 3 days, the client received a new private IP. The client retained the same private IP when restarted within 3 days. +~~~ + +- [Feature/merge back](https://github.com/nymtech/nym/pull/4710): Merge back from the release branch the changes that fix the `nym-node` upgrades + +- [Removed mixnode/gateway config migration code and disabled cli without explicit flag](https://github.com/nymtech/nym/pull/4706): `nym-gateway` and `nym-mixnode` commands now won't do anything without explicit `--force-run` to bypass the deprecation. The next step, in say a month or so, is to completely remove all `cli` related things. + +~~~admonish example collapsible=true title='Testing steps performed' +- Verify that the `nym-gateway` binary and `nym-mixnode` binary commands return the _error message_ stating to update to nym-node +- Check that when adding the `--force-run` flag, it still allows the command to be run (aside from `init` which has been removed) and the message stating to update to nym-node is a _warning_ now +- Check `nym-node` is not affected +- Reviewed the changes in the PR +~~~ + +- [Handle clients with different versions in IPR](https://github.com/nymtech/nym/pull/4723): Allow the IPR to handle clients connecting both using `v6` and `v7`, independently. The motivation is that we want to be able to roll out a API version change gradually for VPN clients without breaking backwards compatibility. The main feature on the new `v7` format that is not yet used, is that it adds signatures for connect/disconnect. + +~~~admonish example collapsible=true title='Testing steps performed' +Run the same command (using same gateways deployed from this PR) on different versions of the `nym-vpn-cli`. + +Example: +```sh +~/nym-vpn-core-v0.1.10_macos_universal ❯ sudo -E ./nym-vpn-cli -c ../qa.env run --entry-gateway-id $entry_gateway --exit-gateway-id $exit_gateway --enable-two-hop + +~/nym-vpn-core-v0.1.11-dev_macos_universal ❯ sudo -E ./nym-vpn-cli -c ../qa.env run --entry-gateway-id $entry_gateway --exit-gateway-id $exit_gateway --enable-two-hop +``` +~~~ + +- [Backport `#4844` and `#4845`](https://github.com/nymtech/nym/pull/4857) + +- [Remove wireguard feature flag and pass runtime enabled flag](https://github.com/nymtech/nym/pull/4839) + +- [Eliminate cancel unsafe sig awaiting](https://github.com/nymtech/nym/pull/4834) + +- [Added explicit updateable admin to the mixnet contract](https://github.com/nymtech/nym/pull/4822) + +- [Using legacy signing payload in CLI and verifying both variants in contract](https://github.com/nymtech/nym/pull/4821) + +- [Adding ecash contract address](https://github.com/nymtech/nym/pull/4819) + +- [Check profit margin of node before defaulting to hardcoded value ](https://github.com/nymtech/nym/pull/4802) + +- [Sync `last_seen_bandwidth` immediately](https://github.com/nymtech/nym/pull/4774) + +- [Feature/additional ecash `nym-cli` utils](https://github.com/nymtech/nym/pull/4773) + +- [Better storage error logging](https://github.com/nymtech/nym/pull/4772) + +- [Disable testnet-manager on non-unix](https://github.com/nymtech/nym/pull/4741) + +- [Don't set NYM_VPN_API to default](https://github.com/nymtech/nym/pull/4740) + +- [Update publish-nym-binaries.yml](https://github.com/nymtech/nym/pull/4739): Adds wireguard to builds + +- [Update ci-build-upload-binaries.yml](https://github.com/nymtech/nym/pull/4738): Adds wireguard for ci-builds + +- [Add NYM_VPN_API to network config](https://github.com/nymtech/nym/pull/4736) + +- [Re-export RecipientFormattingError in nym sdk](https://github.com/nymtech/nym/pull/4735) + +- [Persist wireguard peers](https://github.com/nymtech/nym/pull/4732) + +- [Feature/vesting purge plus ranged cost params](https://github.com/nymtech/nym/pull/4716): Combines [\#4715](https://github.com/nymtech/nym/pull/4715) and [\#4711](https://github.com/nymtech/nym/pull/4711) into one. + - Disables all non-essential operations on the vesting contract => you can no longer bond mixnodes/make delegations/etc. (you can still, however, withdraw your vested tokens and so on) + - Introduces admin-controlled minimum (and maximum) profit margin and interval operating costs. + - both contracts have to be migrated **at the same time**. ideally within the same transaction + - mixnet contract migration is not allowed (and will fail) if there are any pending actions involving vesting tokens, like delegating, increasing pledge, etc + +- [Bump braces from `3.0.2` to `3.0.3` in `/nym-wallet/webdriver`](https://github.com/nymtech/nym/pull/4709): Bumps [braces](https://github.com/micromatch/braces) from `3.0.2` to `3.0.3`. + +### Bugfix + +- [chore: fix 1.80 lint issues](https://github.com/nymtech/nym/pull/4731) + +~~~admonish example collapsible=true title='Testing steps performed' +- Building all binaries is ok +- Running `cargo fmt` returns no issues +~~~ + +- [Fix version 1 not having template correspondent initially](https://github.com/nymtech/nym/pull/4733) + +~~~admonish example collapsible=true title='Testing steps performed' +Tested updating an old `nym-node` version and ensuring it did not throw any errors. +~~~ + +- [Bugfix/client registration vol2](https://github.com/nymtech/nym/pull/4856) + +- [Fix tokio error in `1.39`](https://github.com/nymtech/nym/pull/4730): + - Bump tokio to `1.39.2`, skipping the issue with `1.39.1` + + +- [Fix (some) feature unification build failures](https://github.com/nymtech/nym/pull/4681): Running a script in the root workspace that builds each crate independently + +~~~admonish example collapsible=true title='The script' + ```sh + #!/bin/bash + + packages=$(cargo metadata --format-version 1 --no-deps | jq -r '.packages[].name') + + # Loop through each package and build + for package in $packages; do + echo "Building $package" + cargo clean + cargo check -p "$package" + if [ $? -ne 0 ]; then + echo "Build failed for $package. Stopping." + exit 1 + fi + done + ``` +~~~ + +- [bugfix: make sure DKG parses data out of events if logs are empty](https://github.com/nymtech/nym/pull/4764): This will be the case on post `0.50` chains + +- [Fix clippy on rustc beta toolchain](https://github.com/nymtech/nym/pull/4746): Fix clippy warnings for rust beta toolchain + +- [Fix clippy for beta toolchain](https://github.com/nymtech/nym/pull/4742): Fix beta toolchain clippy by removing unused module + - Add `nym-` prefix to `serde-common` crate + - Remove ignored `default-features = false` attribute for workspace dependency + +### Crypto + +- [Feature Compact Ecash : The One PR](https://github.com/nymtech/nym/pull/4623) + +### Operators Guide, Tooling & Updates + +- More explicit [setup for `nym-node`](nodes/setup.md#initialise--run) with a new [option explanation](nodes/setup.md#essential-parameters--variables), including syntax examples + +- New [VPS networking configuration steps for Wireguard](nodes/configuration.md#routing-configuration) + +- Wireguard [builds from source](binaries/building-nym.md) together with `nym-node`, no need to specify with a feature flag anymore + +- Wireguard peers stay connected for longer time, re-connections are also faster + +- Profit margin and operating cost values will be set to the agreed values, the values can be changed in the future through [Nym Operators governance process](https://forum.nymtech.net/t/poll-proposal-for-on-chain-minimum-profit-margin-for-all-nym-nodes/253) +```admonish success title="" +- Minimum profit margin = 20% +- Maximum profit margin = 50% +- Minimum operating cost = 0 NYM +- Maximum operating cost = 1000 NYM +``` + +- [Nym Harbourmater](https://harbourmaster.nymtech.net) has several new functionalities: + - Version counting graph for Gateways and Mixnodes + - Several new columns with larger nodes performance and settings overview. + - Top routing score now includes: + - Wireguard registration and complete handshake test, to configure see [tasklist below](#operators-tasks) + - DNS resolution check, to configure see [tasklist below](#operators-tasks) + - Wireguard perfomance > 0.75, to configure see [tasklist below](#operators-tasks) + +- New wallet coming out soon! + - Vesting contract functionalities have been purged, users can only remove tokens from vesting + +- [Nym API Check CLI](testing/node-api-check.md) is upgraded according to the latest API endpoints, output is cleaner and more concise. + + +#### Operators Tasks + +```admonish warning title="" +**The steps below are highly recommended for all operators and mandatory for everyone who is a part of Nym Delegation or Grant program. Deadline is Friday, September 20th, 2024.** +``` + +Every `nym-node` should be upgraded to the latest version! Operators can test using [Sandbox env](sandbox.md) during the pre-release period, then upgrade on mainnet. During the upgrade, please follow the points below before you restart the node: + +**`nym-node`** + +- Make sure to fill in basic description info, into the file located at `.nym/nym-nodes//data/description.toml` (all nodes) +- Configure wireguard routing with new [`network_tunnel_manager.sh`](https://gist.github.com/tommyv1987/ccf6ca00ffb3d7e13192edda61bb2a77) following [these steps](nodes/configuration.md#routing-configuration) (Gateways only for the time being) +- Enable Wireguard with `--wireguard-enabled true` flag included in your run command (Gateways only for the time being) + - Note: On some VPS this setup may not be enough to get the correct results as some ISPs have their own security groups setup below the individual VPS. In that case a ticket to ISP will have to be issued to open the needed settings. We are working on a template for such ticket. +- Setup [reverse proxy and WSS](nodes/proxy-configuration.md) on `nym-node` (Gateways only for the time being) +- Don't forget to restart your node - or (preferably using [systemd automation](nodes/configuration.md#systemd)) reload daemon and restart the service +- Migrating from `mixnet` or `gateway` smart contracts to a new `nym-node` smart contract will be available soon with an upcoming version of Nym desktop wallet. After this migration all `nym-nodes` will be able to receive delegation. The operators will have to confirm the migration once it's deployed. +- Optional: Use [`nym-gateway-probe`](testing/gateway-probe.html) and [NymVPN CLI](https://nymtech.net/developers/nymvpn/cli.html) to test your own Gateway +- Optional: Run the script below to measure ping speed of your Gateway and share your results in [Nym Operators channel](https://matrix.to/#/#operators:nymtech.chat) + +~~~admonish example collapsible=true title='The script to measure Gateway ping results' +We made a script for pinging nymtech.net from your GWs. Can you please install it and then share the result together with your Gateway ID: + +1. Get the script onto your machine (soon on github for curl or wget): + +```sh +# paste all this block as one command +cat <<'EOL' > ping_with_curl_average_for_wg_check.sh +#!/bin/bash + +ping_with_curl_average_for_wg_check() { + total_connect_time=0 + total_total_time=0 + iterations=5 + timeout=2 + + for ((i=1; i<=iterations; i++)); do + echo "ping attempt $i..." + + echo "curling nymtech.net to check ping response times" + times=$(curl -I https://nymtech.net --max-time $timeout \ + -w "time_connect=%{time_connect}\ntime_total=%{time_total}" -o /dev/null -s) + + time_connect=$(echo "$times" | grep "time_connect" | cut -d"=" -f2) + time_total=$(echo "$times" | grep "time_total" | cut -d"=" -f2) + + total_connect_time=$(echo "$total_connect_time + $time_connect" | bc) + total_total_time=$(echo "$total_total_time + $time_total" | bc) + + echo "time to connect: $time_connect s" + echo "total time: $time_total s" + done + + average_connect_time=$(echo "scale=3; $total_connect_time / $iterations" | bc) + average_total_time=$(echo "scale=3; $total_total_time / $iterations" | bc) + + echo "-----------------------------------" + echo "average time to connect: $average_connect_time s" + echo "average total time: $average_total_time s" +} + +ping_with_curl_average_for_wg_check +EOL +``` + +2. Make executable: + +```sh +chmod +x ping_with_curl_average_for_wg_check.sh +``` + +3. In case you don't have `bc`, install it: + +```sh +sudo apt install bc +``` + +4. Run: + +```sh +./ping_with_curl_average_for_wg_check.sh +``` + +5. Share results and ID key in [Nym Operators channel](https://matrix.to/#/#operators:nymtech.chat) + +THANK YOU! +~~~ + +**validators** + +- Validators need to update and prepare for ecash implementation. + +### Known Bugs & Undone features + +- New `nym-nodes` without a performance 24h history above 50% don't show routing properly on `nym-gateway-probe`, on Nym Harbourmaster the page may appear blank - we are working on a fix. +- Wireguard works on IPv4 only for the time being, we are working on IPv6 implementation. +--- + ## `v2024.9-topdeck` - [Release binaries](https://github.com/nymtech/nym/releases/tag/nym-binaries-v2024.9-topdeck) diff --git a/documentation/operators/src/nodes/configuration.md b/documentation/operators/src/nodes/configuration.md index b933c4dede..b44f5bed23 100644 --- a/documentation/operators/src/nodes/configuration.md +++ b/documentation/operators/src/nodes/configuration.md @@ -103,7 +103,7 @@ To automate with `systemd` use this init service file by saving it as `/etc/syst nano /etc/systemd/system/nym-node.service ``` -2. Paste this config file +2. Paste this config file, substitute `` and `` with your correct values and add all flags to run your `nym-node` to `ExecStart` line: ```ini [Unit] Description=Nym Node @@ -199,7 +199,7 @@ In this (unusual) case your `mixnode` will not be able to route the packets. The ```admonish info We recommend operators to configure their `nym-node` with the full routing configuration. -However, most of the time the packets sent through the Mixnet are IPv4 based. The IPv6 packets are still pretty rare and therefore it's not mandatory from operational point of view to have this configuration implemented if you running only `mixnode` mode. +However, most of the time the packets sent through the Mixnet are IPv4 based. The IPv6 packets are still pretty rare and therefore it's not mandatory from operational point of view to have this configuration implemented if you running only `mixnode` mode. If you preparing to run a `nym-node` with all modes enabled in the future, this setup is required. ``` @@ -212,7 +212,7 @@ For everyone participating in Delegation Program or Service Grant program, this You can always check IPv6 address and connectivity by using some of these methods: -~~~admonish example collapsible=true +~~~admonish example collapsible=true title="Test IPv6 methods" ```sh # locally listed IPv6 addresses ip -6 addr @@ -241,19 +241,21 @@ Make sure to keep your IPv4 address enabled while setting up IPv6, as the majori While we're working on Rust implementation to have these settings as a part of the binary build, to solve these connectivity requirements in the meantime we wrote a script [`network_tunnel_manager.sh`](https://gist.github.com/tommyv1987/ccf6ca00ffb3d7e13192edda61bb2a77) to support the operators to configure their servers and address all the connectivity requirements. -Networking configuration across different ISPs and various operation systems does not have a generic solution. If the provided configuration setup doesn't solve your problem check out [IPv6 troubleshooting](../troubleshooting/vps-isp.md#ipv6-troubleshooting) page. Be aware that you may have to do more research and customised adjustments. +Networking configuration across different ISPs and various operation systems does not have a generic solution. If the provided configuration setup doesn't solve your problem check out [IPv6 troubleshooting](../troubleshooting/vps-isp.md#ipv6-troubleshooting) page. Be aware that you may have to do more research, customised adjustments or contact your ISP to change settings for your VPS. The `nymtun0` interface is dynamically managed by the `exit-gateway` service. When the service is stopped, `nymtun0` disappears, and when started, `nymtun0` is recreated. -The script should be used in a context where `nym-node`is running to fully utilise its capabilities, particularly for fetching IPv6 addresses or applying network rules that depend on the `nymtun0` interface and to establish a WireGuard tunnel. +The `nymwg` interface is used for creating a secure wireguard tunnel as part of the Nym Network configuration. Similar to `nymtun0`, the script manages iptables rules specific to `nymwg` to ensure proper routing and forwarding through the wireguard tunnel. The `nymwg` interface needs to be correctly configured and active for the related commands to function properly. This includes applying or removing iptables rules and running connectivity tests through the `nymwg` tunnel. -Before starting with the following, make sure you have the [latest `nym-node` binary](https://github.com/nymtech/nym/releases/) installed and your [VPS setup](vps-setup.md) finished properly! +The script should be used in a context where `nym-node` is running to fully utilise its capabilities, particularly for fetching IPv6 addresses or applying network rules that depend on the `nymtun0` and `nymwg` interfaces and to establish a WireGuard tunnel. + +**Before starting with the following configuration, make sure you have the [latest `nym-node` binary](https://github.com/nymtech/nym/releases/) installed and your [VPS setup](vps-setup.md) finished properly!** 1. Download `network_tunnel_manager.sh`, make executable and run: ```sh -curl -L -o network_tunnel_manager.sh https://gist.githubusercontent.com/tommyv1987/ccf6ca00ffb3d7e13192edda61bb2a77/raw/3c0a38c1416f8fdf22906c013299dd08d1497183/network_tunnel_manager.sh && \ +curl -L https://gist.githubusercontent.com/tommyv1987/ccf6ca00ffb3d7e13192edda61bb2a77/raw/74241cc06492b955e582052939090f57a285a65e/network_tunnel_manager.sh -o network_tunnel_manager.sh && \ chmod +x network_tunnel_manager.sh && \ ./network_tunnel_manager.sh ``` @@ -333,7 +335,10 @@ operation check_nymtun_iptables completed successfully. ./network_tunnel_manager.sh apply_iptables_rules_wg ``` -7. At this point your node needs to be [bonded](bonding.md) to the API for `nymtun0` to interact with the network. After bonding please follow up with the remaining steps below to ensure that your node is routing properly. +7. Apply rules to configure DNS routing and allow ICMP piung test for node probing (network testing): +```sh +./network_tunnel_manager.sh configure_dns_and_icmp_wg +``` 8. Check `nymtun0` interface: ```sh @@ -368,7 +373,7 @@ ip addr show nymtun0 11. Now you can run your node with the `--wireguard-enabled true` flag or add it to your [systemd service config](#systemd). Restart your `nym-node` or [systemd](#following-steps-for-nym-nodes-running-as-systemd-service) service (recommended): ```sh -systemctl daemon-reload && systemctl restart nym-node.service +systemctl daemon-reload && systemctl restart nym-node.service ``` - Optionally, you can check if the node is running correctly by monitoring the service logs: ```sh diff --git a/documentation/operators/src/nodes/setup.md b/documentation/operators/src/nodes/setup.md index 542dc7d883..8b6a53d84d 100644 --- a/documentation/operators/src/nodes/setup.md +++ b/documentation/operators/src/nodes/setup.md @@ -86,24 +86,6 @@ To list all available flags for each command, run `./nym-node --help` The Wireguard flags currently have limited functionality. From version `1.1.6` ([`v2024.9-topdeck`](https://github.com/nymtech/nym/releases/tag/nym-binaries-v2024.9-topdeck)) wireguard is available and recommended to be switched on for nodes running as Gateways. Keep in mind that this option needs a bit of a special [configuration](configuration.md#wireguard-setup). ``` -#### Flags Summary - -Some of the most useful flags and their explanation: - -~~~admonish example collapsible=true title="Flags explanation:" -- `--id `: Local identifier of your node. This `` determines your config path located at `~/.nym/nym-nodes//config/config.toml`, default value is `default-nym-node` -- `--accept-operator-terms-and-conditions`: Explicitly specify whether you agree with the terms and conditions of a nym node operator as defined at [nymtech.net/terms-and-conditions/operators/v1.0.0]({{toc_page}}) -- `--config-file `: Used for the migrate command to indicate the location of the existing node config file. Default path is `~/.nym/nym-nodes/default-nym-node/config/config.toml` -- `--deny-init`: Use this flag to prevent a new node from being initialized. It's recommended to use this after the first run to avoid accidental spinning up of a second node. -- `--init-only`: Use this flag if you want to set up a node without starting it. -- `--mode`: Determines the mode of the node and is always required. -- `--write-changes`: Used to change values within the `config.toml` file after the node has been run. -- `--mnemonic`: This is for when gateways are coconut-credentials-enforced, and this mnemonic is used as the `double_spend` prevention. This account needs credit in order for it to work. -- `--expose-system-info `: Sets your system info visibility on the network. -- `--expose-system-hardware `: Sets your system hardware info visibility on the network. -- `--expose-crypto-hardware `: Sets your crypto hardware info visibility on the network. -~~~ - ### Terms & Conditions ```admonish info @@ -150,72 +132,112 @@ When we use `run` command the node will do `init` as well, unless we specify wit Please keep in mind that currently you can run only one functionality (`--mode`) per a `nym-node` instance. We are yet to finalise implement the multi-functionality solution under one node bonded to one Nyx account. Every `exit-gateway` can function as `entry-gateway` by default, not vice versa. +There is a simple default command to initialise and run your node: `./nym-node run --mode `, however there quite a few parameters to be configured. When `nym-node` gets to be `run`, these parameters are read by the binary from the configuration file located at `.nym/nym-nodes//config/config.toml`. + +If an operator specifies any paramteres with optional flags alongside `run` command, these parameters passed in the option will take place over the ones in `config.toml` but they will not overwrite them by default. To overwrite them with the values passed with `run` command, a flag `-w` (`--write-changes`) must be added. + +Alternatively operators can just open a text editor and change these values manually. After saving the file,don't forget to restart the node or reload and restart the service. If all values are setup correctly in `config.toml`, then operator can use as simple command as `nym-node run --mode --accept-operators-terms-and-conditions`, or alternatively paste this command with a correct path to your binary to your `ExecStart` line into a [systemd `nym-node.service`](configuration.md#systemd) config file. + ```admonish success title="" -**We recommend operators to setup an [automation](configuration.md#systemd) flow for their nodes!** +**We recommend operators to setup an [automation](configuration.md#systemd) flow for their nodes, using systemd!** In such case, you can `run` a node to initalise it or try if everything works, but then stop the proces and paste your entire `run` command syntax (below) to the `ExecStart` line of your `/etc/systemd/system/nym-node.service` and start the node as a [service](configuration.md#following-steps-for-nym-nodes-running-as-systemd-service). ``` +#### Essential Parameters & Variables + +Running a `nym-node` in a `mixnode` mode requires less configuration than a full `exit-gateway` setup, we recommend operators to still follow through with all documented [configuration](configuration.md). Before you scroll down to syntax examples for the mode of your choice: [`mixnode`](#mode-miznode), [`exit-gateway`](#mode-exit-gateway), or [`entry-gateway](#mode-entry-gateway), please familiarise yourself with the essential paramters and variables convention we use in the guide. + +Substitute any variables in `<>` brackets your own value, without `<>` brackets. Here is a list of important options and variables. + +| Flag (Option) | Variable | Description | Syntax example | +| :-- | :--- | :--- | :--- | +| `--mode` | `` | A functionality of your `nym-node` in the mixnet - mandatory! Chose from `entry-gateway`, `mixnode` or `exit-gateway` | `--mode exit-gateway` | +| `--id` | `` | A local only `nym-node` identifier, specified by flag `--id`. Not mandatory as it defaults to `default-nym-node` if not specified. | `--id alice_super_node` | +| `-w` or `--write-changes` | *none* | Specify whether to write new changes - the values of other flags in the given command - to the config file | `--write-changes` | +| `--accept-operator-terms-and-conditions` | *none* | A flag added explicitly to `nym-node run` command every time, showing that the operator agreed with [T&Cs](#terms--conditions) | `--accept-operator-terms-and-conditions` | +| `--public-ips` | `` | IPv4 of the `nym-node` server - mandatory! Use this address as a `host` value for bonding.Use this address as a `host` value for bonding. | `--public-ips "$(curl -4 https://ifconfig.me)"` | +| `--mixnet-bind-address` | `` | Address to bind to for listening for mixnet packets - mandatory! Must be on port `1789`! | `--mixnet-bind-address 0.0.0.0:1789` | +| `--http-bind-address` | `` | Socket address this node will use for binding its http API - mandatory! Must be on port `8080`! | `--http-bind-address 0.0.0.0:8080` | +| `--hostname` | `` | Your registered DNS domain, asigned to the VPS with `nym-node`. Use without prefix like `http://` or `https://` | `exit-gateway1.squad.nsl` | +| `--location` | `` | Loacation of your node. Formats like 'Jamaica', or two-letter alpha2 (e.g. 'JM'), three-letter alpha3 (e.g. 'JAM') or three-digit numeric-3 (e.g. '388') can be provided. | `--location JAM` | +| `--wireguard-private-ip` | `` | Private IP address of the wireguard gateway. This mandatory field is set to a correct default: `10.1.0.1`, operators upgrading from older versions must overwrite it. | `--wireguard-private-ip 10.1.0.1` | +| `--wireguard-enabled` | `` | Specifies whether the wireguard service is enabled, possible values: `true` or `false` - `true` is recommended | `--wireguard-enabled true` | +| `--expose-system-info` | `` | Specify whether basic system information should be exposed. default: `true`, possible values: `true` or `false` | `--expose-system-info false` | +| `--expose-system-hardware` | `` | Specify whether basic system hardware information should be exposed. default: `true`, possible values: `true` or `false` | `--expose-system-hardware false` | +| *not a flag* | `` | Specify a full path to the given file, directory or binary behind this variable | `/root/src/nym/target/release/` | + ```admonish note To prevent over-flooding of our documentation we cannot provide with every single command syntax as there is a large combination of possibilities. Please use a common sense and the explanation in `--help` option. ``` #### Mode: `exit-gateway` +If you run a `nym-node` for the first time, you will need to specify a few parameters, please read the section [Essential Parameters & Variables](#essential-paramteters--varibles) before you start and make sure that your `nym-node` is up to date with the [latest version](https://github.com/nymtech/nym/releases/). + **Initialise and run** in one command: + +To initialise and test run your node, use this command: ```sh -# simple default -./nym-node run --mode exit-gateway - -# with other options -./nym-node run --id --mode exit-gateway --public-ips "$(curl -4 https://ifconfig.me)" --hostname "" --http-bind-address 0.0.0.0:8080 --mixnet-bind-address 0.0.0.0:1789 --location --accept-operator-terms-and-conditions --wireguard-enabled true - -# is in format without 'https://' prefix -# is format like 'Jamaica', or two-letter alpha2 (e.g. 'JM'), three-letter alpha3 (e.g. 'JAM') or three-digit numeric-3 (e.g. '388') can be provided. -# wireguard can be enabled from version 1.1.6 onwards +./nym-node run --id --mode exit-gateway --public-ips "$(curl -4 https://ifconfig.me)" --hostname "" --http-bind-address 0.0.0.0:8080 --mixnet-bind-address 0.0.0.0:1789 --location --accept-operator-terms-and-conditions --wireguard-enabled true ``` +If you prefer to have a generic local identifier set to `default-nym-node`, skip `--id` option. -**Initialise only** without running the node with `--init-only` command : +We highly recommend to setup [reverse proxy and WSS](proxy-configuration.md) for `nym-node`. If you haven't configured any of that, skip `--hostname` flag. + +In any case `--public-ips` is a necessity for your node to bond to API and communicate with the internet. + + +**Initialise only** without running the node with `--init-only` command: + +Adding `--init-only` option results in `nym-node` initialising a configuration file `config.toml` without running - a good option for an initial node setup. Remember that if you using this flag on a node which already has a config file, this will not over-write the values, unless used with a specified flag `--write-changes` (`-w`) - a good option for introducing changes to your `config.toml` file. ```sh -# simple default -./nym-node run --init-only --mode exit-gateway - -# with a custom `--id` and other options -./nym-node run --id --init-only --mode exit-gateway --public-ips "$(curl -4 https://ifconfig.me)" --hostname "" --http-bind-address 0.0.0.0:8080 --mixnet-bind-address 0.0.0.0:1789 --location --accept-operator-terms-and-conditions --wireguard-enabled true - -# is in format without 'https://' prefix -# is format like 'Jamaica', or two-letter alpha2 (e.g. 'JM'), three-letter alpha3 (e.g. 'JAM') or three-digit numeric-3 (e.g. '388') can be provided. -# wireguard can be enabled from version 1.1.6 onwards +./nym-node run --id --init-only --mode exit-gateway --public-ips "$(curl -4 https://ifconfig.me)" --hostname "" --http-bind-address 0.0.0.0:8080 --mixnet-bind-address 0.0.0.0:1789 --location --wireguard-enabled true ``` -Run the node with custom `--id` without initialising, using `--deny-init` command +In the example above we dropped `--accept-operator-terms-and-conditions` as the flag must be added to a running command explicitly and it is not stored in the config, `--init-only` will not run the node. + +**Deny init** + +`--deny-init` was introduced as an additional safety for migration from legacy binaries to `nym-node` to prevent operators initialise over existing nodes. For most of the operators, this flag is not needed. + +In this example we run the node with custom `--id` without initialising, using `--deny-init` command: ```sh ./nym-node run --id --deny-init --mode exit-gateway --accept-operator-terms-and-conditions ``` #### Mode: `entry-gateway` +If you run a `nym-node` for the first time, you will need to specify a few parameters, please read the section [Essential Parameters & Variables](#essential-paramteters--varibles) before you start and make sure that your `nym-node` is up to date with the [latest version](https://github.com/nymtech/nym/releases/). + **Initialise and run:** + +To initialise and test run with yur node with all needed options, use this command: ```sh -./nym-node run --mode entry-gateway +./nym-node run --id --mode entry-gateway --public-ips "$(curl -4 https://ifconfig.me)" --hostname "" --http-bind-address 0.0.0.0:8080 --mixnet-bind-address 0.0.0.0:1789 --location --accept-operator-terms-and-conditions --wireguard-enabled true +``` +If you prefer to have a generic local identifier set to `default-nym-node`, skip `--id` option. + +We highly recommend to setup [reverse proxy and WSS](proxy-configuration.md) for `nym-node`. If you haven't configured any of that, skip `--hostname` flag. + +In any case `--public-ips` is a necessity for your node to bond to API and communicate with the internet. + +**Initialise only** without running the node with `--init-only` command : + +Adding `--init-only` option results in `nym-node` initialising a configuration file `config.toml` without running - a good option for an initial node setup. Remember that if you using this flag on a node which already has a config file, this will not over-write the values, unless used with a specified flag `--write-changes` (`-w`) - a good option for introducing changes to your `config.toml` file. + +```sh +./nym-node run --id --init-only --mode entry-gateway --public-ips "$(curl -4 https://ifconfig.me)" --hostname "" --http-bind-address 0.0.0.0:8080 --mixnet-bind-address 0.0.0.0:1789 --location --wireguard-enabled true ``` -Initialise & run with all options -```sh -./nym-node run --id --mode entry-gateway --public-ips "$(curl -4 https://ifconfig.me)" --hostname "" --http-bind-address 0.0.0.0:8080 --mixnet-bind-address 0.0.0.0:1789 --accept-operator-terms-and-conditions --wireguard-enabled true +In the example above we dropped `--accept-operator-terms-and-conditions` as the flag must be added to a running command explicitly and it is not stored in the config, `--init-only` will not run the node. -# is in format without 'https://' prefix -# is format like 'Jamaica', or two-letter alpha2 (e.g. 'JM'), three-letter alpha3 (e.g. 'JAM') or three-digit numeric-3 (e.g. '388') can be provided. -# wireguard can be enabled from version 1.1.6 onwards -``` +**Deny init** -Initialise only, with an `--init-only` command (a custom `--id` used): -```sh -./nym-node run --id --init-only --mode entry-gateway --public-ips "$(curl -4 https://ifconfig.me)" --hostname "" --http-bind-address 0.0.0.0:8080 --mixnet-bind-address 0.0.0.0:1789 --accept-operator-terms-and-conditions -``` +`--deny-init` was introduced as an additional safety for migration from legacy binaries to `nym-node` to prevent operators initialise over existing nodes. For most of the operators, this flag is not needed. -Run the node with custom `--id` without initialising: +In this example we run the node with custom `--id` without initialising, using `--deny-init` command: ```sh ./nym-node run --id --deny-init --mode entry-gateway --accept-operator-terms-and-conditions ``` @@ -224,17 +246,27 @@ Run the node with custom `--id` without initialising: **Initialise and run:** ```sh -./nym-node run --mode mixnode +./nym-node run --mode mixnode --mixnet-bind-address 0.0.0.0:1789 --verloc-bind-address 0.0.0.0:1790 --http-bind-address 0.0.0.0:8080 --public-ips "$(curl -4 https://ifconfig.me)" --accept-operator-terms-and-conditions ``` +**Init only** + +Adding `--init-only` option results in `nym-node` initialising a configuration file `config.toml` without running - a good option for an initial node setup. Remember that if you using this flag on a node which already has a config file, this will not over-write the values, unless used with a specified flag `--write-changes` (`-w`) - a good option for introducing changes to your `config.toml` file. + Initialise only with a custom `--id` and `--init-only` command: ```sh -./nym-node run --id --init-only --mode mixnode --verloc-bind-address 0.0.0.0:1790 --public-ips "$(curl -4 https://ifconfig.me)" --accept-operator-terms-and-conditions +./nym-node run --mode mixnode --id --init-only --mixnet-bind-address 0.0.0.0:1789 --verloc-bind-address 0.0.0.0:1790 --http-bind-address 0.0.0.0:8080 --public-ips "$(curl -4 https://ifconfig.me)" --accept-operator-terms-and-conditions ``` -Run the node with custom `--id` without initialising: +If you prefer to have a generic local identifier set to `default-nym-node`, skip `--id` option. + +**Deny init** + +`--deny-init` was introduced as an additional safety for migration from legacy binaries to `nym-node` to prevent operators initialise over existing nodes. For most of the operators, this flag is not needed. + +In this example we run the node with custom `--id` without initialising, using `--deny-init` command: ```sh -./nym-node run --id --deny-init --mode mixnode --accept-operator-terms-and-conditions +./nym-node run --mode mixnode --id --deny-init --accept-operator-terms-and-conditions ``` ### Migrate From f70e8a3b9ed588255b3656187c4afac74aa504d9 Mon Sep 17 00:00:00 2001 From: "dependabot[bot]" <49699333+dependabot[bot]@users.noreply.github.com> Date: Wed, 11 Sep 2024 08:16:35 +0200 Subject: [PATCH 76/93] build(deps): bump dirs from 4.0.0 to 5.0.1 (#4849) Bumps [dirs](https://github.com/soc/dirs-rs) from 4.0.0 to 5.0.1. - [Commits](https://github.com/soc/dirs-rs/commits) --- updated-dependencies: - dependency-name: dirs dependency-type: direct:production update-type: version-update:semver-major ... Signed-off-by: dependabot[bot] Co-authored-by: dependabot[bot] <49699333+dependabot[bot]@users.noreply.github.com> --- Cargo.lock | 36 ++++++++---------------------------- Cargo.toml | 2 +- 2 files changed, 9 insertions(+), 29 deletions(-) diff --git a/Cargo.lock b/Cargo.lock index 06140c6a8d..b8248bd603 100644 --- a/Cargo.lock +++ b/Cargo.lock @@ -1997,33 +1997,13 @@ dependencies = [ "subtle 2.5.0", ] -[[package]] -name = "dirs" -version = "4.0.0" -source = "registry+https://github.com/rust-lang/crates.io-index" -checksum = "ca3aa72a6f96ea37bbc5aa912f6788242832f75369bdfdadcb0e38423f100059" -dependencies = [ - "dirs-sys 0.3.7", -] - [[package]] name = "dirs" version = "5.0.1" source = "registry+https://github.com/rust-lang/crates.io-index" checksum = "44c45a9d03d6676652bcb5e724c7e988de1acad23a711b5217ab9cbecbec2225" dependencies = [ - "dirs-sys 0.4.1", -] - -[[package]] -name = "dirs-sys" -version = "0.3.7" -source = "registry+https://github.com/rust-lang/crates.io-index" -checksum = "1b1d1d91c932ef41c0f2663aa8b0ca0342d444d842c06914aa0a7e352d0bada6" -dependencies = [ - "libc", - "redox_users", - "winapi", + "dirs-sys", ] [[package]] @@ -4128,7 +4108,7 @@ dependencies = [ "cw2", "cw3", "cw4", - "dirs 4.0.0", + "dirs", "futures", "getset", "humantime-serde", @@ -4427,7 +4407,7 @@ version = "1.1.39" dependencies = [ "bs58", "clap 4.5.16", - "dirs 4.0.0", + "dirs", "futures", "log", "nym-bandwidth-controller", @@ -4674,7 +4654,7 @@ dependencies = [ name = "nym-config" version = "0.1.0" dependencies = [ - "dirs 5.0.1", + "dirs", "handlebars", "log", "nym-network-defaults", @@ -4941,7 +4921,7 @@ dependencies = [ "colored", "dashmap", "defguard_wireguard_rs", - "dirs 4.0.0", + "dirs", "dotenvy", "futures", "humantime-serde", @@ -5263,7 +5243,7 @@ dependencies = [ "clap 4.5.16", "colored", "cupid", - "dirs 4.0.0", + "dirs", "futures", "humantime-serde", "lazy_static", @@ -5394,7 +5374,7 @@ dependencies = [ "async-trait", "bs58", "clap 4.5.16", - "dirs 4.0.0", + "dirs", "futures", "humantime-serde", "ipnetwork 0.20.0", @@ -5750,7 +5730,7 @@ name = "nym-socks5-client-core" version = "0.1.0" dependencies = [ "anyhow", - "dirs 4.0.0", + "dirs", "futures", "log", "nym-bandwidth-controller", diff --git a/Cargo.toml b/Cargo.toml index 72035c969a..a76bc4d0e6 100644 --- a/Cargo.toml +++ b/Cargo.toml @@ -212,7 +212,7 @@ curve25519-dalek = "4.1" dashmap = "5.5.3" defguard_wireguard_rs = "0.4.2" digest = "0.10.7" -dirs = "4.0" +dirs = "5.0" doc-comment = "0.3" dotenvy = "0.15.6" ecdsa = "0.16" From 4c5147390aaf2afbce5d6462a02d60f14d1c325b Mon Sep 17 00:00:00 2001 From: =?UTF-8?q?Jon=20H=C3=A4ggblad?= Date: Wed, 11 Sep 2024 09:39:08 +0200 Subject: [PATCH 77/93] Fix linux conditional in ci-build.yml (#4863) --- .github/workflows/ci-build.yml | 10 +++++----- 1 file changed, 5 insertions(+), 5 deletions(-) diff --git a/.github/workflows/ci-build.yml b/.github/workflows/ci-build.yml index 4293eba2ab..53932a6806 100644 --- a/.github/workflows/ci-build.yml +++ b/.github/workflows/ci-build.yml @@ -52,7 +52,7 @@ jobs: - name: Install Dependencies (Linux) run: sudo apt-get update && sudo apt-get -y install libwebkit2gtk-4.0-dev build-essential curl wget libssl-dev libgtk-3-dev libudev-dev squashfs-tools protobuf-compiler continue-on-error: true - if: matrix.os == 'custom-linux' + if: contains(matrix.os, 'ubuntu') - name: Check out repository code uses: actions/checkout@v4 @@ -87,28 +87,28 @@ jobs: args: --features axum - name: Build all examples - if: matrix.os == 'custom-linux' + if: contains(matrix.os, 'ubuntu') uses: actions-rs/cargo@v1 with: command: build args: --workspace --examples --features wireguard - name: Run all tests - if: matrix.os == 'custom-linux' + if: contains(matrix.os, 'ubuntu') uses: actions-rs/cargo@v1 with: command: test args: --workspace --features wireguard - name: Run expensive tests - if: (github.ref == 'refs/heads/develop' || github.event.pull_request.base.ref == 'develop' || github.event.pull_request.base.ref == 'master') && matrix.os == 'custom-linux' + if: (github.ref == 'refs/heads/develop' || github.event.pull_request.base.ref == 'develop' || github.event.pull_request.base.ref == 'master') && contains(matrix.os, 'ubuntu') uses: actions-rs/cargo@v1 with: command: test args: --workspace --features wireguard -- --ignored - name: Annotate with clippy checks - if: matrix.os == 'custom-linux' + if: contains(matrix.os, 'ubuntu') uses: actions-rs/clippy-check@v1 continue-on-error: true with: From c3eb433960398aaab92add79d5ae6876c8b3a279 Mon Sep 17 00:00:00 2001 From: =?UTF-8?q?Jon=20H=C3=A4ggblad?= Date: Wed, 11 Sep 2024 09:57:03 +0200 Subject: [PATCH 78/93] Remove golang workaround in ci-sdk-wasm (#4858) --- .github/workflows/ci-sdk-wasm.yml | 10 ---------- 1 file changed, 10 deletions(-) diff --git a/.github/workflows/ci-sdk-wasm.yml b/.github/workflows/ci-sdk-wasm.yml index 10fc1c70ff..40bb639501 100644 --- a/.github/workflows/ci-sdk-wasm.yml +++ b/.github/workflows/ci-sdk-wasm.yml @@ -33,16 +33,6 @@ jobs: with: go-version: '1.20' - - name: Override GOROOT and GOTOOLDIR - run: | - echo "Setting correct GOROOT and GOTOOLDIR" - unset GOROOT - unset GOTOOLDIR - export GOROOT=$(go env GOROOT) - export GOTOOLDIR=$(go env GOTOOLDIR) - echo "GOROOT=$GOROOT" >> $GITHUB_ENV - echo "GOTOOLDIR=$GOTOOLDIR" >> $GITHUB_ENV - - name: Install wasm-pack run: curl https://rustwasm.github.io/wasm-pack/installer/init.sh -sSf | sh From c08e7d2b115d7226c521d5a6d724e2edaa017ad5 Mon Sep 17 00:00:00 2001 From: "dependabot[bot]" <49699333+dependabot[bot]@users.noreply.github.com> Date: Wed, 11 Sep 2024 10:22:42 +0200 Subject: [PATCH 79/93] build(deps): bump the patch-updates group with 22 updates (#4846) Bumps the patch-updates group with 22 updates: | Package | From | To | | --- | --- | --- | | [anyhow](https://github.com/dtolnay/anyhow) | `1.0.83` | `1.0.87` | | [async-trait](https://github.com/dtolnay/async-trait) | `0.1.81` | `0.1.82` | | [clap](https://github.com/clap-rs/clap) | `4.5.16` | `4.5.17` | | [clap_complete](https://github.com/clap-rs/clap) | `4.5.2` | `4.5.26` | | [clap_complete_fig](https://github.com/clap-rs/clap) | `4.5.0` | `4.5.2` | | [const_format](https://github.com/rodrimati1992/const_format_crates) | `0.2.32` | `0.2.33` | | [curve25519-dalek](https://github.com/dalek-cryptography/curve25519-dalek) | `4.1.2` | `4.1.3` | | [log](https://github.com/rust-lang/log) | `0.4.21` | `0.4.22` | | [parking_lot](https://github.com/Amanieu/parking_lot) | `0.12.2` | `0.12.3` | | [quote](https://github.com/dtolnay/quote) | `1.0.36` | `1.0.37` | | [schemars](https://github.com/GREsau/schemars) | `0.8.19` | `0.8.21` | | [serde](https://github.com/serde-rs/serde) | `1.0.209` | `1.0.210` | | [serde_derive](https://github.com/serde-rs/serde) | `1.0.209` | `1.0.210` | | [serde_json](https://github.com/serde-rs/json) | `1.0.127` | `1.0.128` | | [tar](https://github.com/alexcrichton/tar-rs) | `0.4.40` | `0.4.41` | | [tokio-stream](https://github.com/tokio-rs/tokio) | `0.1.15` | `0.1.16` | | [tokio-util](https://github.com/tokio-rs/tokio) | `0.7.11` | `0.7.12` | | [url](https://github.com/servo/rust-url) | `2.5.0` | `2.5.2` | | [wasm-bindgen-test](https://github.com/rustwasm/wasm-bindgen) | `0.3.42` | `0.3.43` | | [http-body-util](https://github.com/hyperium/http-body) | `0.1.1` | `0.1.2` | | [hyper-util](https://github.com/hyperium/hyper-util) | `0.1.3` | `0.1.5` | | [tokio-tun](https://github.com/yaa110/tokio-tun) | `0.11.4` | `0.11.5` | Updates `anyhow` from 1.0.83 to 1.0.87 - [Release notes](https://github.com/dtolnay/anyhow/releases) - [Commits](https://github.com/dtolnay/anyhow/compare/1.0.83...1.0.87) Updates `async-trait` from 0.1.81 to 0.1.82 - [Release notes](https://github.com/dtolnay/async-trait/releases) - [Commits](https://github.com/dtolnay/async-trait/compare/0.1.81...0.1.82) Updates `clap` from 4.5.16 to 4.5.17 - [Release notes](https://github.com/clap-rs/clap/releases) - [Changelog](https://github.com/clap-rs/clap/blob/master/CHANGELOG.md) - [Commits](https://github.com/clap-rs/clap/compare/clap_complete-v4.5.16...clap_complete-v4.5.17) Updates `clap_complete` from 4.5.2 to 4.5.26 - [Release notes](https://github.com/clap-rs/clap/releases) - [Changelog](https://github.com/clap-rs/clap/blob/master/CHANGELOG.md) - [Commits](https://github.com/clap-rs/clap/compare/clap_complete-v4.5.2...clap_complete-v4.5.26) Updates `clap_complete_fig` from 4.5.0 to 4.5.2 - [Release notes](https://github.com/clap-rs/clap/releases) - [Changelog](https://github.com/clap-rs/clap/blob/master/CHANGELOG.md) - [Commits](https://github.com/clap-rs/clap/compare/clap_complete_fig-v4.5.0...clap_complete_fig-v4.5.2) Updates `const_format` from 0.2.32 to 0.2.33 - [Release notes](https://github.com/rodrimati1992/const_format_crates/releases) - [Changelog](https://github.com/rodrimati1992/const_format_crates/blob/master/Changelog.md) - [Commits](https://github.com/rodrimati1992/const_format_crates/commits) Updates `curve25519-dalek` from 4.1.2 to 4.1.3 - [Release notes](https://github.com/dalek-cryptography/curve25519-dalek/releases) - [Commits](https://github.com/dalek-cryptography/curve25519-dalek/compare/curve25519-4.1.2...curve25519-4.1.3) Updates `log` from 0.4.21 to 0.4.22 - [Release notes](https://github.com/rust-lang/log/releases) - [Changelog](https://github.com/rust-lang/log/blob/master/CHANGELOG.md) - [Commits](https://github.com/rust-lang/log/compare/0.4.21...0.4.22) Updates `parking_lot` from 0.12.2 to 0.12.3 - [Changelog](https://github.com/Amanieu/parking_lot/blob/master/CHANGELOG.md) - [Commits](https://github.com/Amanieu/parking_lot/compare/0.12.2...0.12.3) Updates `quote` from 1.0.36 to 1.0.37 - [Release notes](https://github.com/dtolnay/quote/releases) - [Commits](https://github.com/dtolnay/quote/compare/1.0.36...1.0.37) Updates `schemars` from 0.8.19 to 0.8.21 - [Release notes](https://github.com/GREsau/schemars/releases) - [Changelog](https://github.com/GREsau/schemars/blob/master/CHANGELOG.md) - [Commits](https://github.com/GREsau/schemars/compare/v0.8.19...v0.8.21) Updates `serde` from 1.0.209 to 1.0.210 - [Release notes](https://github.com/serde-rs/serde/releases) - [Commits](https://github.com/serde-rs/serde/compare/v1.0.209...v1.0.210) Updates `serde_derive` from 1.0.209 to 1.0.210 - [Release notes](https://github.com/serde-rs/serde/releases) - [Commits](https://github.com/serde-rs/serde/compare/v1.0.209...v1.0.210) Updates `serde_json` from 1.0.127 to 1.0.128 - [Release notes](https://github.com/serde-rs/json/releases) - [Commits](https://github.com/serde-rs/json/compare/1.0.127...1.0.128) Updates `tar` from 0.4.40 to 0.4.41 - [Commits](https://github.com/alexcrichton/tar-rs/compare/0.4.40...0.4.41) Updates `tokio-stream` from 0.1.15 to 0.1.16 - [Release notes](https://github.com/tokio-rs/tokio/releases) - [Commits](https://github.com/tokio-rs/tokio/compare/tokio-stream-0.1.15...tokio-stream-0.1.16) Updates `tokio-util` from 0.7.11 to 0.7.12 - [Release notes](https://github.com/tokio-rs/tokio/releases) - [Commits](https://github.com/tokio-rs/tokio/compare/tokio-util-0.7.11...tokio-util-0.7.12) Updates `url` from 2.5.0 to 2.5.2 - [Release notes](https://github.com/servo/rust-url/releases) - [Commits](https://github.com/servo/rust-url/compare/v2.5.0...v2.5.2) Updates `wasm-bindgen-test` from 0.3.42 to 0.3.43 - [Release notes](https://github.com/rustwasm/wasm-bindgen/releases) - [Changelog](https://github.com/rustwasm/wasm-bindgen/blob/main/CHANGELOG.md) - [Commits](https://github.com/rustwasm/wasm-bindgen/commits) Updates `http-body-util` from 0.1.1 to 0.1.2 - [Release notes](https://github.com/hyperium/http-body/releases) - [Commits](https://github.com/hyperium/http-body/compare/http-body-util-v0.1.1...http-body-util-v0.1.2) Updates `hyper-util` from 0.1.3 to 0.1.5 - [Release notes](https://github.com/hyperium/hyper-util/releases) - [Changelog](https://github.com/hyperium/hyper-util/blob/master/CHANGELOG.md) - [Commits](https://github.com/hyperium/hyper-util/compare/v0.1.3...v0.1.5) Updates `tokio-tun` from 0.11.4 to 0.11.5 - [Commits](https://github.com/yaa110/tokio-tun/compare/0.11.4...0.11.5) --- updated-dependencies: - dependency-name: anyhow dependency-type: direct:production update-type: version-update:semver-patch dependency-group: patch-updates - dependency-name: async-trait dependency-type: direct:production update-type: version-update:semver-patch dependency-group: patch-updates - dependency-name: clap dependency-type: direct:production update-type: version-update:semver-patch dependency-group: patch-updates - dependency-name: clap_complete dependency-type: direct:production update-type: version-update:semver-patch dependency-group: patch-updates - dependency-name: clap_complete_fig dependency-type: direct:production update-type: version-update:semver-patch dependency-group: patch-updates - dependency-name: const_format dependency-type: direct:production update-type: version-update:semver-patch dependency-group: patch-updates - dependency-name: curve25519-dalek dependency-type: direct:production update-type: version-update:semver-patch dependency-group: patch-updates - dependency-name: log dependency-type: direct:production update-type: version-update:semver-patch dependency-group: patch-updates - dependency-name: parking_lot dependency-type: direct:production update-type: version-update:semver-patch dependency-group: patch-updates - dependency-name: quote dependency-type: direct:production update-type: version-update:semver-patch dependency-group: patch-updates - dependency-name: schemars dependency-type: direct:production update-type: version-update:semver-patch dependency-group: patch-updates - dependency-name: serde dependency-type: direct:production update-type: version-update:semver-patch dependency-group: patch-updates - dependency-name: serde_derive dependency-type: direct:production update-type: version-update:semver-patch dependency-group: patch-updates - dependency-name: serde_json dependency-type: direct:production update-type: version-update:semver-patch dependency-group: patch-updates - dependency-name: tar dependency-type: direct:production update-type: version-update:semver-patch dependency-group: patch-updates - dependency-name: tokio-stream dependency-type: direct:production update-type: version-update:semver-patch dependency-group: patch-updates - dependency-name: tokio-util dependency-type: direct:production update-type: version-update:semver-patch dependency-group: patch-updates - dependency-name: url dependency-type: direct:production update-type: version-update:semver-patch dependency-group: patch-updates - dependency-name: wasm-bindgen-test dependency-type: direct:production update-type: version-update:semver-patch dependency-group: patch-updates - dependency-name: http-body-util dependency-type: direct:production update-type: version-update:semver-patch dependency-group: patch-updates - dependency-name: hyper-util dependency-type: direct:production update-type: version-update:semver-patch dependency-group: patch-updates - dependency-name: tokio-tun dependency-type: direct:production update-type: version-update:semver-patch dependency-group: patch-updates ... Signed-off-by: dependabot[bot] Co-authored-by: dependabot[bot] <49699333+dependabot[bot]@users.noreply.github.com> --- Cargo.lock | 210 +++++++++--------- Cargo.toml | 24 +- common/client-core/Cargo.toml | 2 +- common/client-libs/gateway-client/Cargo.toml | 2 +- .../group-contract/Cargo.toml | 2 +- .../multisig-contract/Cargo.toml | 2 +- common/nonexhaustive-delayqueue/Cargo.toml | 2 +- common/tun/Cargo.toml | 2 +- service-providers/ip-packet-router/Cargo.toml | 2 +- 9 files changed, 126 insertions(+), 122 deletions(-) diff --git a/Cargo.lock b/Cargo.lock index b8248bd603..b5602a891e 100644 --- a/Cargo.lock +++ b/Cargo.lock @@ -213,9 +213,9 @@ dependencies = [ [[package]] name = "anyhow" -version = "1.0.83" +version = "1.0.87" source = "registry+https://github.com/rust-lang/crates.io-index" -checksum = "25bdb32cbbdce2b519a9cd7df3a678443100e265d5e25ca763b7572a5104f5f3" +checksum = "10f00e1f6e58a40e807377c75c6a7f97bf9044fab57816f2414e6f5f4499d7b8" [[package]] name = "arbitrary" @@ -285,9 +285,9 @@ dependencies = [ [[package]] name = "async-trait" -version = "0.1.81" +version = "0.1.82" source = "registry+https://github.com/rust-lang/crates.io-index" -checksum = "6e0c28dcc82d7c8ead5cb13beb15405b57b8546e93215673ff8ca0349a028107" +checksum = "a27b8a3a6e1a44fa4c8baf1f653e4172e81486d4941f2237e20dc2d0cf4ddff1" dependencies = [ "proc-macro2", "quote", @@ -825,9 +825,9 @@ checksum = "baf1de4339761588bc0619e3cbc0120ee582ebb74b53b4efbf79117bd2da40fd" [[package]] name = "cfg_aliases" -version = "0.1.1" +version = "0.2.1" source = "registry+https://github.com/rust-lang/crates.io-index" -checksum = "fd16c4719339c4530435d38e511904438d07cce7950afa3718a84ac36c10e89e" +checksum = "613afe47fcd5fac7ccf1db93babcb082c5994d996f20b8b159f2ad1658eb5724" [[package]] name = "chacha" @@ -930,9 +930,9 @@ dependencies = [ [[package]] name = "clap" -version = "4.5.16" +version = "4.5.17" source = "registry+https://github.com/rust-lang/crates.io-index" -checksum = "ed6719fffa43d0d87e5fd8caeab59be1554fb028cd30edc88fc4369b17971019" +checksum = "3e5a21b8495e732f1b3c364c9949b201ca7bae518c502c80256c96ad79eaf6ac" dependencies = [ "clap_builder", "clap_derive", @@ -940,9 +940,9 @@ dependencies = [ [[package]] name = "clap_builder" -version = "4.5.15" +version = "4.5.17" source = "registry+https://github.com/rust-lang/crates.io-index" -checksum = "216aec2b177652e3846684cbfe25c9964d18ec45234f0f5da5157b207ed1aab6" +checksum = "8cf2dd12af7a047ad9d6da2b6b249759a22a7abc0f474c1dae1777afa4b21a73" dependencies = [ "anstream", "anstyle", @@ -952,20 +952,20 @@ dependencies = [ [[package]] name = "clap_complete" -version = "4.5.2" +version = "4.5.26" source = "registry+https://github.com/rust-lang/crates.io-index" -checksum = "dd79504325bf38b10165b02e89b4347300f855f273c4cb30c4a3209e6583275e" +checksum = "205d5ef6d485fa47606b98b0ddc4ead26eb850aaa86abfb562a94fb3280ecba0" dependencies = [ - "clap 4.5.16", + "clap 4.5.17", ] [[package]] name = "clap_complete_fig" -version = "4.5.0" +version = "4.5.2" source = "registry+https://github.com/rust-lang/crates.io-index" -checksum = "54b3e65f91fabdd23cac3d57d39d5d938b4daabd070c335c006dccb866a61110" +checksum = "d494102c8ff3951810c72baf96910b980fb065ca5d3101243e6a8dc19747c86b" dependencies = [ - "clap 4.5.16", + "clap 4.5.17", "clap_complete", ] @@ -1128,18 +1128,18 @@ checksum = "3618cccc083bb987a415d85c02ca6c9994ea5b44731ec28b9ecf09658655fba9" [[package]] name = "const_format" -version = "0.2.32" +version = "0.2.33" source = "registry+https://github.com/rust-lang/crates.io-index" -checksum = "e3a214c7af3d04997541b18d432afaff4c455e79e2029079647e72fc2bd27673" +checksum = "50c655d81ff1114fb0dcdea9225ea9f0cc712a6f8d189378e82bdf62a473a64b" dependencies = [ "const_format_proc_macros", ] [[package]] name = "const_format_proc_macros" -version = "0.2.32" +version = "0.2.33" source = "registry+https://github.com/rust-lang/crates.io-index" -checksum = "c7f6ff08fd20f4f299298a28e2dfa8a8ba1036e6cd2460ac1de7b425d76f2500" +checksum = "eff1a44b93f47b1bac19a27932f5c591e43d1ba357ee4f61526c8a25603f0eb1" dependencies = [ "proc-macro2", "quote", @@ -1385,7 +1385,7 @@ dependencies = [ "anes", "cast", "ciborium", - "clap 4.5.16", + "clap 4.5.17", "criterion-plot", "is-terminal", "itertools 0.10.5", @@ -1465,7 +1465,7 @@ dependencies = [ "crossterm_winapi", "libc", "mio 0.8.11", - "parking_lot 0.12.2", + "parking_lot 0.12.3", "signal-hook", "signal-hook-mio", "winapi", @@ -1481,7 +1481,7 @@ dependencies = [ "crossterm_winapi", "libc", "mio 0.8.11", - "parking_lot 0.12.2", + "parking_lot 0.12.3", "signal-hook", "signal-hook-mio", "winapi", @@ -1496,7 +1496,7 @@ dependencies = [ "bitflags 2.5.0", "crossterm_winapi", "libc", - "parking_lot 0.12.2", + "parking_lot 0.12.3", "winapi", ] @@ -1633,16 +1633,15 @@ dependencies = [ [[package]] name = "curve25519-dalek" -version = "4.1.2" +version = "4.1.3" source = "registry+https://github.com/rust-lang/crates.io-index" -checksum = "0a677b8922c94e01bdbb12126b0bc852f00447528dee1782229af9c720c3f348" +checksum = "97fb8b7c4503de7d6ae7b42ab72a5a59857b4c937ec27a3d4539dba95b5ab2be" dependencies = [ "cfg-if", "cpufeatures", "curve25519-dalek-derive", "digest 0.10.7", "fiat-crypto", - "platforms", "rustc_version 0.4.0", "serde", "subtle 2.5.0", @@ -2104,7 +2103,7 @@ version = "2.1.1" source = "registry+https://github.com/rust-lang/crates.io-index" checksum = "4a3daa8e81a3963a60642bcc1f90a670680bd4a77535faa384e9d1c79d620871" dependencies = [ - "curve25519-dalek 4.1.2", + "curve25519-dalek 4.1.3", "ed25519", "rand_core 0.6.4", "serde", @@ -2228,7 +2227,7 @@ name = "explorer-api" version = "1.1.38" dependencies = [ "chrono", - "clap 4.5.16", + "clap 4.5.17", "dotenvy", "humantime-serde", "isocountry", @@ -2968,12 +2967,12 @@ dependencies = [ [[package]] name = "http-body-util" -version = "0.1.1" +version = "0.1.2" source = "registry+https://github.com/rust-lang/crates.io-index" -checksum = "0475f8b2ac86659c21b64320d5d653f9efe42acd2a4e560073ec61a155a34f1d" +checksum = "793429d76616a256bcb62c2a2ec2bed781c8307e797e2598c50010f2bee2544f" dependencies = [ "bytes", - "futures-core", + "futures-util", "http 1.1.0", "http-body 1.0.0", "pin-project-lite", @@ -3121,9 +3120,9 @@ dependencies = [ [[package]] name = "hyper-util" -version = "0.1.3" +version = "0.1.5" source = "registry+https://github.com/rust-lang/crates.io-index" -checksum = "ca38ef113da30126bbff9cd1705f9273e15d45498615d138b0c20279ac7a76aa" +checksum = "7b875924a60b96e5d7b9ae7b066540b1dd1cbd90d1828f54c92e02a283351c56" dependencies = [ "bytes", "futures-channel", @@ -3549,9 +3548,9 @@ dependencies = [ [[package]] name = "libc" -version = "0.2.154" +version = "0.2.158" source = "registry+https://github.com/rust-lang/crates.io-index" -checksum = "ae743338b92ff9146ce83992f766a31066a91a8c84a45e0e9f21e7cf6de6d346" +checksum = "d8adc4bb1803a324070e64a98ae98f38934d91957a99cfb3a43dcbc01bc56439" [[package]] name = "libm" @@ -3622,9 +3621,9 @@ dependencies = [ [[package]] name = "log" -version = "0.4.21" +version = "0.4.22" source = "registry+https://github.com/rust-lang/crates.io-index" -checksum = "90ed8c1e510134f979dbc4f070f87d4313098b704861a105fe34231c70a3901c" +checksum = "a7a70ba024b9dc04c27ea2f0c0548feb474ec5c54bba33a7f72f873a39d07b24" [[package]] name = "loom" @@ -3762,6 +3761,16 @@ dependencies = [ "unicase", ] +[[package]] +name = "minicov" +version = "0.3.5" +source = "registry+https://github.com/rust-lang/crates.io-index" +checksum = "5c71e683cd655513b99affab7d317deb690528255a0d5f717f1024093c12b169" +dependencies = [ + "cc", + "walkdir", +] + [[package]] name = "minimal-lexical" version = "0.2.1" @@ -3952,9 +3961,9 @@ dependencies = [ [[package]] name = "nix" -version = "0.28.0" +version = "0.29.0" source = "registry+https://github.com/rust-lang/crates.io-index" -checksum = "ab2156c4fce2f8df6c499cc1c763e4394b7482525bf2a9701c9d79d215f519e4" +checksum = "71e2746dc3a24dd78b3cfcb7be93368c6de9963d30f43a6a73998a9cf4b17b46" dependencies = [ "bitflags 2.5.0", "cfg-if", @@ -4101,7 +4110,7 @@ dependencies = [ "bloomfilter", "bs58", "cfg-if", - "clap 4.5.16", + "clap 4.5.17", "console-subscriber", "cosmwasm-std", "cw-utils", @@ -4222,7 +4231,7 @@ dependencies = [ "bincode", "bs58", "bytes", - "clap 4.5.16", + "clap 4.5.17", "defguard_wireguard_rs", "fastrand 2.1.1", "futures", @@ -4287,7 +4296,7 @@ dependencies = [ name = "nym-bin-common" version = "0.6.0" dependencies = [ - "clap 4.5.16", + "clap 4.5.17", "clap_complete", "clap_complete_fig", "const-str", @@ -4329,7 +4338,7 @@ dependencies = [ "base64 0.22.1", "bip39", "bs58", - "clap 4.5.16", + "clap 4.5.17", "clap_complete", "clap_complete_fig", "dotenvy", @@ -4355,7 +4364,7 @@ dependencies = [ "bip39", "bs58", "cfg-if", - "clap 4.5.16", + "clap 4.5.17", "comfy-table 6.2.0", "cosmrs 0.17.0-pre", "cosmwasm-std", @@ -4406,7 +4415,7 @@ name = "nym-client" version = "1.1.39" dependencies = [ "bs58", - "clap 4.5.16", + "clap 4.5.17", "dirs", "futures", "log", @@ -4446,7 +4455,7 @@ dependencies = [ "base64 0.22.1", "bs58", "cfg-if", - "clap 4.5.16", + "clap 4.5.17", "comfy-table 7.1.1", "futures", "gloo-timers", @@ -4917,7 +4926,7 @@ dependencies = [ "async-trait", "bip39", "bs58", - "clap 4.5.16", + "clap 4.5.17", "colored", "dashmap", "defguard_wireguard_rs", @@ -5102,7 +5111,7 @@ version = "0.1.0" dependencies = [ "anyhow", "bs58", - "clap 4.5.16", + "clap 4.5.17", "nym-bin-common", "nym-credential-storage", "nym-id", @@ -5144,7 +5153,7 @@ dependencies = [ "bincode", "bs58", "bytes", - "clap 4.5.16", + "clap 4.5.17", "etherparse", "futures", "log", @@ -5240,7 +5249,7 @@ dependencies = [ "anyhow", "axum 0.7.5", "bs58", - "clap 4.5.16", + "clap 4.5.17", "colored", "cupid", "dirs", @@ -5341,7 +5350,7 @@ version = "0.1.0" dependencies = [ "anyhow", "axum 0.7.5", - "clap 4.5.16", + "clap 4.5.17", "dashmap", "futures", "log", @@ -5373,7 +5382,7 @@ dependencies = [ "anyhow", "async-trait", "bs58", - "clap 4.5.16", + "clap 4.5.17", "dirs", "futures", "humantime-serde", @@ -5425,7 +5434,7 @@ dependencies = [ "bs58", "cargo_metadata", "celes", - "clap 4.5.16", + "clap 4.5.17", "colored", "cupid", "humantime-serde", @@ -5573,7 +5582,7 @@ name = "nym-nr-query" version = "0.1.0" dependencies = [ "anyhow", - "clap 4.5.16", + "clap 4.5.17", "log", "nym-bin-common", "nym-network-defaults", @@ -5600,7 +5609,7 @@ dependencies = [ "chacha20", "chacha20poly1305", "criterion 0.4.0", - "curve25519-dalek 4.1.2", + "curve25519-dalek 4.1.3", "fastrand 2.1.1", "getrandom", "log", @@ -5651,7 +5660,7 @@ dependencies = [ "nym-task", "nym-topology", "nym-validator-client", - "parking_lot 0.12.2", + "parking_lot 0.12.3", "pretty_env_logger", "rand", "reqwest 0.12.4", @@ -5697,7 +5706,7 @@ name = "nym-socks5-client" version = "1.1.39" dependencies = [ "bs58", - "clap 4.5.16", + "clap 4.5.17", "log", "nym-bin-common", "nym-client-core", @@ -6116,7 +6125,7 @@ version = "0.1.0" dependencies = [ "anyhow", "bip39", - "clap 4.5.16", + "clap 4.5.17", "cosmwasm-std", "futures", "humantime 2.1.0", @@ -6227,7 +6236,7 @@ version = "0.1.5" dependencies = [ "anyhow", "bytes", - "clap 4.5.16", + "clap 4.5.17", "dotenvy", "flate2", "futures", @@ -6483,9 +6492,9 @@ dependencies = [ [[package]] name = "parking_lot" -version = "0.12.2" +version = "0.12.3" source = "registry+https://github.com/rust-lang/crates.io-index" -checksum = "7e4af0ca4f6caed20e900d564c242b8e5d4903fdacf31d3daf527b66fe6f42fb" +checksum = "f1bf18183cf54e8d6059647fc3063646a1801cf30896933ec2311622cc4b9a27" dependencies = [ "lock_api", "parking_lot_core 0.9.10", @@ -6705,12 +6714,6 @@ version = "0.3.30" source = "registry+https://github.com/rust-lang/crates.io-index" checksum = "d231b230927b5e4ad203db57bbcbee2802f6bce620b1e4a9024a07d94e2907ec" -[[package]] -name = "platforms" -version = "3.4.0" -source = "registry+https://github.com/rust-lang/crates.io-index" -checksum = "db23d408679286588f4d4644f965003d056e3dd5abcaaa938116871d7ce2fee7" - [[package]] name = "plotters" version = "0.3.5" @@ -6881,7 +6884,7 @@ dependencies = [ "fnv", "lazy_static", "memchr", - "parking_lot 0.12.2", + "parking_lot 0.12.3", "protobuf", "thiserror", ] @@ -6995,9 +6998,9 @@ checksum = "a993555f31e5a609f617c12db6250dedcac1b0a85076912c436e6fc9b2c8e6a3" [[package]] name = "quote" -version = "1.0.36" +version = "1.0.37" source = "registry+https://github.com/rust-lang/crates.io-index" -checksum = "0fa76aaf39101c457836aec0ce2316dbdc3ab723cdda1c6bd4e6ad4208acaca7" +checksum = "b5b9d34b8991d19d98081b46eacdd8eb58c6f2b201139f7c5f643cc155a633af" dependencies = [ "proc-macro2", ] @@ -7348,7 +7351,7 @@ dependencies = [ "memchr", "multer", "num_cpus", - "parking_lot 0.12.2", + "parking_lot 0.12.3", "pin-project-lite", "rand", "ref-cast", @@ -7699,9 +7702,9 @@ dependencies = [ [[package]] name = "schemars" -version = "0.8.19" +version = "0.8.21" source = "registry+https://github.com/rust-lang/crates.io-index" -checksum = "fc6e7ed6919cb46507fb01ff1654309219f62b4d603822501b0b80d42f6f21ef" +checksum = "09c024468a378b7e36765cd36702b7a90cc3cba11654f6685c8f233408e89e92" dependencies = [ "dyn-clone", "indexmap 1.9.3", @@ -7712,9 +7715,9 @@ dependencies = [ [[package]] name = "schemars_derive" -version = "0.8.19" +version = "0.8.21" source = "registry+https://github.com/rust-lang/crates.io-index" -checksum = "185f2b7aa7e02d418e453790dde16890256bbd2bcd04b7dc5348811052b53f49" +checksum = "b1eee588578aff73f856ab961cd2f79e36bc45d7ded33a7562adba4667aecc0e" dependencies = [ "proc-macro2", "quote", @@ -7826,9 +7829,9 @@ dependencies = [ [[package]] name = "serde" -version = "1.0.209" +version = "1.0.210" source = "registry+https://github.com/rust-lang/crates.io-index" -checksum = "99fce0ffe7310761ca6bf9faf5115afbc19688edd00171d81b1bb1b116c63e09" +checksum = "c8e3592472072e6e22e0a54d5904d9febf8508f65fb8552499a1abc7d1078c3a" dependencies = [ "serde_derive", ] @@ -7875,9 +7878,9 @@ dependencies = [ [[package]] name = "serde_derive" -version = "1.0.209" +version = "1.0.210" source = "registry+https://github.com/rust-lang/crates.io-index" -checksum = "a5831b979fd7b5439637af1752d535ff49f4860c0f341d1baeb6faf0f4242170" +checksum = "243902eda00fad750862fc144cea25caca5e20d615af0a81bee94ca738f1df1f" dependencies = [ "proc-macro2", "quote", @@ -7908,9 +7911,9 @@ dependencies = [ [[package]] name = "serde_json" -version = "1.0.127" +version = "1.0.128" source = "registry+https://github.com/rust-lang/crates.io-index" -checksum = "8043c06d9f82bd7271361ed64f415fe5e12a77fdb52e573e7f06a516dea329ad" +checksum = "6ff5456707a1de34e7e37f2a6fd3d3f808c318259cbd01ab6377795054b483d8" dependencies = [ "itoa", "memchr", @@ -8202,7 +8205,7 @@ dependencies = [ "byteorder", "chacha", "ctr", - "curve25519-dalek 4.1.2", + "curve25519-dalek 4.1.3", "digest 0.10.7", "hkdf", "hmac", @@ -8343,7 +8346,7 @@ name = "ssl-inject" version = "0.1.0" dependencies = [ "anyhow", - "clap 4.5.16", + "clap 4.5.17", "hex", "tokio", ] @@ -8610,9 +8613,9 @@ checksum = "55937e1799185b12863d447f42597ed69d9928686b8d88a1df17376a097d8369" [[package]] name = "tar" -version = "0.4.40" +version = "0.4.41" source = "registry+https://github.com/rust-lang/crates.io-index" -checksum = "b16afcea1f22891c49a00c751c7b63b2233284064f11a200fc624137c51e2ddb" +checksum = "cb797dad5fb5b76fcf519e702f4a589483b5ef06567f160c392832c1f5e44909" dependencies = [ "filetime", "libc", @@ -8791,7 +8794,7 @@ dependencies = [ "anyhow", "bip39", "bs58", - "clap 4.5.16", + "clap 4.5.17", "console", "cw-utils", "dkg-bypass-contract", @@ -8950,7 +8953,7 @@ dependencies = [ "bytes", "libc", "mio 1.0.2", - "parking_lot 0.12.2", + "parking_lot 0.12.3", "pin-project-lite", "signal-hook-registry", "socket2", @@ -9026,9 +9029,9 @@ dependencies = [ [[package]] name = "tokio-stream" -version = "0.1.15" +version = "0.1.16" source = "registry+https://github.com/rust-lang/crates.io-index" -checksum = "267ac89e0bec6e691e5813911606935d77c476ff49024f98abcea3e7b15e37af" +checksum = "4f4e6ce100d0eb49a2734f8c0812bcd324cf357d21810932c5df6b96ef2b86f1" dependencies = [ "futures-core", "pin-project-lite", @@ -9051,12 +9054,12 @@ dependencies = [ [[package]] name = "tokio-tun" -version = "0.11.4" +version = "0.11.5" source = "registry+https://github.com/rust-lang/crates.io-index" -checksum = "65d79912ba514490b1f5a574b585e19082bd2a6b238970c87c57a66bd77206b5" +checksum = "68f5381752d5832fc811f89d54fc334951aa435022f494190ba7151661f206df" dependencies = [ "libc", - "nix 0.28.0", + "nix 0.29.0", "thiserror", "tokio", ] @@ -9078,9 +9081,9 @@ dependencies = [ [[package]] name = "tokio-util" -version = "0.7.11" +version = "0.7.12" source = "registry+https://github.com/rust-lang/crates.io-index" -checksum = "9cf6b47b3771c49ac75ad09a6162f53ad4b8088b76ac60e8ec1455b31a189fe1" +checksum = "61e7c3654c13bcd040d4a03abee2c75b1d14a37b423cf5a813ceae1cc903ec6a" dependencies = [ "bytes", "futures-core", @@ -9646,9 +9649,9 @@ checksum = "0976c77def3f1f75c4ef892a292c31c0bbe9e3d0702c63044d7c76db298171a3" [[package]] name = "url" -version = "2.5.0" +version = "2.5.2" source = "registry+https://github.com/rust-lang/crates.io-index" -checksum = "31e6302e3bb753d46e83516cae55ae196fc0c309407cf11ab35cc51a4c2a4633" +checksum = "22784dbdf76fdde8af1aeda5622b546b422b6fc585325248a2bf9f5e41e94d6c" dependencies = [ "form_urlencoded", "idna 0.5.0", @@ -9893,12 +9896,13 @@ checksum = "c62a0a307cb4a311d3a07867860911ca130c3494e8c2719593806c08bc5d0484" [[package]] name = "wasm-bindgen-test" -version = "0.3.42" +version = "0.3.43" source = "registry+https://github.com/rust-lang/crates.io-index" -checksum = "d9bf62a58e0780af3e852044583deee40983e5886da43a271dd772379987667b" +checksum = "68497a05fb21143a08a7d24fc81763384a3072ee43c44e86aad1744d6adef9d9" dependencies = [ "console_error_panic_hook", "js-sys", + "minicov", "scoped-tls", "wasm-bindgen", "wasm-bindgen-futures", @@ -9907,9 +9911,9 @@ dependencies = [ [[package]] name = "wasm-bindgen-test-macro" -version = "0.3.42" +version = "0.3.43" source = "registry+https://github.com/rust-lang/crates.io-index" -checksum = "b7f89739351a2e03cb94beb799d47fb2cac01759b40ec441f7de39b00cbf7ef0" +checksum = "4b8220be1fa9e4c889b30fd207d4906657e7e90b12e0e6b0c8b8d8709f5de021" dependencies = [ "proc-macro2", "quote", @@ -10001,7 +10005,7 @@ checksum = "5f656cd8858a5164932d8a90f936700860976ec21eb00e0fe2aa8cab13f6b4cf" dependencies = [ "futures", "js-sys", - "parking_lot 0.12.2", + "parking_lot 0.12.3", "pin-utils", "slab", "wasm-bindgen", @@ -10397,7 +10401,7 @@ version = "2.0.1" source = "registry+https://github.com/rust-lang/crates.io-index" checksum = "c7e468321c81fb07fa7f4c636c3972b9100f0346e5b6a9f2bd0603a52f7ed277" dependencies = [ - "curve25519-dalek 4.1.2", + "curve25519-dalek 4.1.3", "rand_core 0.6.4", "serde", "zeroize", diff --git a/Cargo.toml b/Cargo.toml index a76bc4d0e6..38e9db4f02 100644 --- a/Cargo.toml +++ b/Cargo.toml @@ -169,9 +169,9 @@ readme = "README.md" addr = "0.15.6" aes = "0.8.1" aes-gcm = "0.10.1" -anyhow = "1.0.71" +anyhow = "1.0.87" argon2 = "0.5.0" -async-trait = "0.1.81" +async-trait = "0.1.82" axum = "0.7.5" axum-extra = "0.9.3" base64 = "0.22.1" @@ -194,7 +194,7 @@ chacha20 = "0.9.0" chacha20poly1305 = "0.10.1" chrono = "0.4.31" cipher = "0.4.3" -clap = "4.5.16" +clap = "4.5.17" clap_complete = "4.5" clap_complete_fig = "4.5" colored = "2.0" @@ -203,7 +203,7 @@ console = "0.15.8" console-subscriber = "0.1.1" console_error_panic_hook = "0.1" const-str = "0.5.6" -const_format = "0.2.32" +const_format = "0.2.33" criterion = "0.4" csv = "1.3.0" ctr = "0.9.1" @@ -255,7 +255,7 @@ okapi = "0.7.0" once_cell = "1.7.2" opentelemetry = "0.19.0" opentelemetry-jaeger = "0.18.0" -parking_lot = "0.12.1" +parking_lot = "0.12.3" pem = "0.8" petgraph = "0.6.5" pin-project = "1.0" @@ -275,12 +275,12 @@ rocket = "0.5.0" rocket_cors = "0.6.0" rocket_okapi = "0.8.0" safer-ffi = "0.1.12" -schemars = "0.8.1" +schemars = "0.8.21" semver = "1.0.23" -serde = "1.0.209" +serde = "1.0.210" serde_bytes = "0.11.15" serde_derive = "1.0" -serde_json = "1.0.127" +serde_json = "1.0.128" serde_repr = "0.1" serde_with = "3.9.0" serde_yaml = "0.9.25" @@ -293,15 +293,15 @@ subtle-encoding = "0.5" syn = "1" sysinfo = "0.30.12" tap = "1.0.1" -tar = "0.4.40" +tar = "0.4.41" tempfile = "3.5.0" thiserror = "1.0.63" time = "0.3.30" tokio = "1.39" -tokio-stream = "0.1.15" +tokio-stream = "0.1.16" tokio-test = "0.4.4" tokio-tungstenite = { version = "0.20.1" } -tokio-util = "0.7.11" +tokio-util = "0.7.12" toml = "0.8.14" tower = "0.4.13" tower-http = "0.5.2" @@ -319,7 +319,7 @@ utoipauto = "0.1" uuid = "*" vergen = { version = "=8.3.1", default-features = false } walkdir = "2" -wasm-bindgen-test = "0.3.36" +wasm-bindgen-test = "0.3.43" x25519-dalek = "2.0.0" zeroize = "1.6.0" diff --git a/common/client-core/Cargo.toml b/common/client-core/Cargo.toml index e23698259e..548592f0ae 100644 --- a/common/client-core/Cargo.toml +++ b/common/client-core/Cargo.toml @@ -71,7 +71,7 @@ features = ["tokio"] ### [target."cfg(not(target_arch = \"wasm32\"))".dependencies.tokio-stream] -version = "0.1.11" +version = "0.1.16" features = ["time"] [target."cfg(not(target_arch = \"wasm32\"))".dependencies.tokio] diff --git a/common/client-libs/gateway-client/Cargo.toml b/common/client-libs/gateway-client/Cargo.toml index 640d9694df..6390e3a844 100644 --- a/common/client-libs/gateway-client/Cargo.toml +++ b/common/client-libs/gateway-client/Cargo.toml @@ -43,7 +43,7 @@ workspace = true features = ["macros", "rt", "net", "sync", "time"] [target."cfg(not(target_arch = \"wasm32\"))".dependencies.tokio-stream] -version = "0.1.11" +version = "0.1.16" features = ["net", "sync", "time"] [target."cfg(not(target_arch = \"wasm32\"))".dependencies.tokio-tungstenite] diff --git a/common/cosmwasm-smart-contracts/group-contract/Cargo.toml b/common/cosmwasm-smart-contracts/group-contract/Cargo.toml index 0a6f33100b..bf053834cb 100644 --- a/common/cosmwasm-smart-contracts/group-contract/Cargo.toml +++ b/common/cosmwasm-smart-contracts/group-contract/Cargo.toml @@ -11,4 +11,4 @@ cosmwasm-schema = { workspace = true } cw4 = { workspace = true } cw-controllers = { workspace = true } schemars = { workspace = true } -serde = { version = "1.0.209", default-features = false, features = ["derive"] } +serde = { version = "1.0.210", default-features = false, features = ["derive"] } diff --git a/common/cosmwasm-smart-contracts/multisig-contract/Cargo.toml b/common/cosmwasm-smart-contracts/multisig-contract/Cargo.toml index 5209cf8abf..664bfa5845 100644 --- a/common/cosmwasm-smart-contracts/multisig-contract/Cargo.toml +++ b/common/cosmwasm-smart-contracts/multisig-contract/Cargo.toml @@ -14,5 +14,5 @@ cw-storage-plus = { workspace = true } cosmwasm-schema = { workspace = true } cosmwasm-std = { workspace = true } schemars = { workspace = true } -serde = { version = "1.0.209", default-features = false, features = ["derive"] } +serde = { version = "1.0.210", default-features = false, features = ["derive"] } thiserror = { workspace = true } diff --git a/common/nonexhaustive-delayqueue/Cargo.toml b/common/nonexhaustive-delayqueue/Cargo.toml index 0211edb62c..9afd584657 100644 --- a/common/nonexhaustive-delayqueue/Cargo.toml +++ b/common/nonexhaustive-delayqueue/Cargo.toml @@ -14,7 +14,7 @@ tokio-stream = { workspace = true } # this one seems to be a thing until `Stream workspace = true [target."cfg(not(target_arch = \"wasm32\"))".dependencies.tokio-util] -version = "0.7.4" +version = "0.7.12" features = ["time"] [target."cfg(target_arch = \"wasm32\")".dependencies.wasmtimer] diff --git a/common/tun/Cargo.toml b/common/tun/Cargo.toml index c141bf87a5..d00114594b 100644 --- a/common/tun/Cargo.toml +++ b/common/tun/Cargo.toml @@ -18,4 +18,4 @@ log.workspace = true nym-wireguard-types = { path = "../wireguard-types", optional = true } [target.'cfg(target_os = "linux")'.dependencies] -tokio-tun = "0.11.2" +tokio-tun = "0.11.5" diff --git a/service-providers/ip-packet-router/Cargo.toml b/service-providers/ip-packet-router/Cargo.toml index 50be33d829..257010c706 100644 --- a/service-providers/ip-packet-router/Cargo.toml +++ b/service-providers/ip-packet-router/Cargo.toml @@ -46,4 +46,4 @@ tokio-util = { workspace = true, features = ["codec"] } url.workspace = true [target.'cfg(target_os = "linux")'.dependencies] -tokio-tun = "0.11.2" +tokio-tun = "0.11.5" From cbea1d554ae6bd51d1daa4a833ed98a5decbecea Mon Sep 17 00:00:00 2001 From: =?UTF-8?q?J=C4=99drzej=20Stuczy=C5=84ski?= Date: Wed, 11 Sep 2024 11:19:30 +0100 Subject: [PATCH 80/93] chore: removed completed queued mixnet migration --- contracts/Cargo.lock | 24 +++++------ contracts/mixnet/src/contract.rs | 2 - contracts/mixnet/src/queued_migrations.rs | 49 ----------------------- 3 files changed, 12 insertions(+), 63 deletions(-) diff --git a/contracts/Cargo.lock b/contracts/Cargo.lock index aecf93c51e..d4b7aa57ae 100644 --- a/contracts/Cargo.lock +++ b/contracts/Cargo.lock @@ -1636,9 +1636,9 @@ checksum = "e86697c916019a8588c99b5fac3cead74ec0b4b819707a682fd4d23fa0ce1ba1" [[package]] name = "schemars" -version = "0.8.16" +version = "0.8.21" source = "registry+https://github.com/rust-lang/crates.io-index" -checksum = "45a28f4c49489add4ce10783f7911893516f15afe45d015608d41faca6bc4d29" +checksum = "09c024468a378b7e36765cd36702b7a90cc3cba11654f6685c8f233408e89e92" dependencies = [ "dyn-clone", "schemars_derive", @@ -1648,14 +1648,14 @@ dependencies = [ [[package]] name = "schemars_derive" -version = "0.8.16" +version = "0.8.21" source = "registry+https://github.com/rust-lang/crates.io-index" -checksum = "c767fd6fa65d9ccf9cf026122c1b555f2ef9a4f0cea69da4d7dbc3e258d30967" +checksum = "b1eee588578aff73f856ab961cd2f79e36bc45d7ded33a7562adba4667aecc0e" dependencies = [ "proc-macro2", "quote", "serde_derive_internals", - "syn 1.0.109", + "syn 2.0.59", ] [[package]] @@ -1697,9 +1697,9 @@ dependencies = [ [[package]] name = "serde" -version = "1.0.209" +version = "1.0.210" source = "registry+https://github.com/rust-lang/crates.io-index" -checksum = "99fce0ffe7310761ca6bf9faf5115afbc19688edd00171d81b1bb1b116c63e09" +checksum = "c8e3592472072e6e22e0a54d5904d9febf8508f65fb8552499a1abc7d1078c3a" dependencies = [ "serde_derive", ] @@ -1724,9 +1724,9 @@ dependencies = [ [[package]] name = "serde_derive" -version = "1.0.209" +version = "1.0.210" source = "registry+https://github.com/rust-lang/crates.io-index" -checksum = "a5831b979fd7b5439637af1752d535ff49f4860c0f341d1baeb6faf0f4242170" +checksum = "243902eda00fad750862fc144cea25caca5e20d615af0a81bee94ca738f1df1f" dependencies = [ "proc-macro2", "quote", @@ -1735,13 +1735,13 @@ dependencies = [ [[package]] name = "serde_derive_internals" -version = "0.26.0" +version = "0.29.1" source = "registry+https://github.com/rust-lang/crates.io-index" -checksum = "85bf8229e7920a9f636479437026331ce11aa132b4dde37d121944a44d6e5f3c" +checksum = "18d26a20a969b9e3fdf2fc2d9f21eda6c40e2de84c9408bb5d3b05d499aae711" dependencies = [ "proc-macro2", "quote", - "syn 1.0.109", + "syn 2.0.59", ] [[package]] diff --git a/contracts/mixnet/src/contract.rs b/contracts/mixnet/src/contract.rs index 884565d142..1d9336ca2b 100644 --- a/contracts/mixnet/src/contract.rs +++ b/contracts/mixnet/src/contract.rs @@ -535,8 +535,6 @@ pub fn migrate( set_build_information!(deps.storage)?; cw2::ensure_from_older_version(deps.storage, CONTRACT_NAME, CONTRACT_VERSION)?; - crate::queued_migrations::vesting_purge(deps.branch())?; - // due to circular dependency on contract addresses (i.e. mixnet contract requiring vesting contract address // and vesting contract requiring the mixnet contract address), if we ever want to deploy any new fresh // environment, one of the contracts will HAVE TO go through a migration diff --git a/contracts/mixnet/src/queued_migrations.rs b/contracts/mixnet/src/queued_migrations.rs index ab410897e9..8df3ef5d86 100644 --- a/contracts/mixnet/src/queued_migrations.rs +++ b/contracts/mixnet/src/queued_migrations.rs @@ -1,51 +1,2 @@ // Copyright 2022-2023 - Nym Technologies SA // SPDX-License-Identifier: Apache-2.0 - -use crate::interval::storage as interval_storage; -use cosmwasm_std::{DepsMut, Order, Storage}; -use mixnet_contract_common::error::MixnetContractError; -use mixnet_contract_common::PendingEpochEventKind; - -fn ensure_no_pending_proxy_events(storage: &dyn Storage) -> Result<(), MixnetContractError> { - let last_executed = interval_storage::LAST_PROCESSED_EPOCH_EVENT.load(storage)?; - let last_inserted = interval_storage::EPOCH_EVENT_ID_COUNTER.load(storage)?; - - // no pending events - if last_executed == last_inserted { - return Ok(()); - } - - for maybe_event in - interval_storage::PENDING_EPOCH_EVENTS.range(storage, None, None, Order::Ascending) - { - let (id, event_data) = maybe_event?; - match event_data.kind { - PendingEpochEventKind::Delegate { proxy, .. } => { - if proxy.is_some() { - return Err(MixnetContractError::FailedMigration { - comment: format!( - "there is a pending vesting contract delegation with id {id}" - ), - }); - } - } - PendingEpochEventKind::Undelegate { proxy, .. } => { - if proxy.is_some() { - return Err(MixnetContractError::FailedMigration { - comment: format!( - "there is a pending vesting contract undelegation with id {id}" - ), - }); - } - } - _ => continue, - } - } - Ok(()) -} - -pub(crate) fn vesting_purge(deps: DepsMut) -> Result<(), MixnetContractError> { - ensure_no_pending_proxy_events(deps.storage)?; - - Ok(()) -} From 86fa7024a29891e5ae2d4ca99da1ea601537a4a1 Mon Sep 17 00:00:00 2001 From: =?UTF-8?q?J=C4=99drzej=20Stuczy=C5=84ski?= Date: Wed, 11 Sep 2024 11:28:00 +0100 Subject: [PATCH 81/93] removed mutability of deps --- contracts/mixnet/src/contract.rs | 2 +- 1 file changed, 1 insertion(+), 1 deletion(-) diff --git a/contracts/mixnet/src/contract.rs b/contracts/mixnet/src/contract.rs index 1d9336ca2b..a2c85dd959 100644 --- a/contracts/mixnet/src/contract.rs +++ b/contracts/mixnet/src/contract.rs @@ -528,7 +528,7 @@ pub fn query( #[entry_point] pub fn migrate( - mut deps: DepsMut<'_>, + deps: DepsMut<'_>, _env: Env, msg: MigrateMsg, ) -> Result { From b67ad8c23ecac969959c96e5438f55329f9a6564 Mon Sep 17 00:00:00 2001 From: =?UTF-8?q?Jon=20H=C3=A4ggblad?= Date: Wed, 11 Sep 2024 13:39:07 +0200 Subject: [PATCH 82/93] Disable push trigger and add missing paths in ci-build (#4864) * Disable push trigger and add missing paths * Remove commented out --- .github/workflows/ci-build.yml | 31 ++++++++----------------------- Cargo.toml | 4 ++-- 2 files changed, 10 insertions(+), 25 deletions(-) diff --git a/.github/workflows/ci-build.yml b/.github/workflows/ci-build.yml index 53932a6806..c31f08ca37 100644 --- a/.github/workflows/ci-build.yml +++ b/.github/workflows/ci-build.yml @@ -1,24 +1,6 @@ name: ci-build on: - push: - paths: - - 'clients/**' - - 'common/**' - - 'explorer-api/**' - - 'gateway/**' - - 'integrations/**' - - 'mixnode/**' - - 'sdk/lib/socks5-listener/**' - - 'sdk/rust/nym-sdk/**' - - 'service-providers/**' - - 'nym-api/**' - - 'nym-outfox/**' - - 'tools/nym-cli/**' - - 'tools/nym-nr-query/**' - - 'tools/ts-rs-cli/**' - - 'Cargo.toml' - - '.github/workflows/ci-build.yml' pull_request: paths: - 'clients/**' @@ -27,15 +9,18 @@ on: - 'gateway/**' - 'integrations/**' - 'mixnode/**' - - 'sdk/lib/socks5-listener/**' - - 'sdk/rust/nym-sdk/**' + - 'sdk/rust/**' + - 'sdk/lib/**' - 'service-providers/**' + - 'nym-network-monitor/**' - 'nym-api/**' + - 'nym-node/**' - 'nym-outfox/**' - - 'tools/nym-cli/**' - - 'tools/nym-nr-query/**' - - 'tools/ts-rs-cli/**' + - 'nym-validator-rewarder/**' + - 'tools/**' + - 'wasm/**' - 'Cargo.toml' + - 'Cargo.lock' - '.github/workflows/ci-build.yml' workflow_dispatch: diff --git a/Cargo.toml b/Cargo.toml index 38e9db4f02..936b1f07e0 100644 --- a/Cargo.toml +++ b/Cargo.toml @@ -117,6 +117,8 @@ members = [ "nym-validator-rewarder", "tools/internal/ssl-inject", # "tools/internal/sdk-version-bump", + "tools/internal/testnet-manager", + "tools/internal/testnet-manager/dkg-bypass-contract", "tools/nym-cli", "tools/nym-id-cli", "tools/nym-nr-query", @@ -127,8 +129,6 @@ members = [ "wasm/mix-fetch", "wasm/node-tester", "wasm/zknym-lib", - "tools/internal/testnet-manager", - "tools/internal/testnet-manager/dkg-bypass-contract", ] default-members = [ From f6db1a87c63756899fdba1916286d87918a6e821 Mon Sep 17 00:00:00 2001 From: "dependabot[bot]" <49699333+dependabot[bot]@users.noreply.github.com> Date: Wed, 11 Sep 2024 15:23:15 +0200 Subject: [PATCH 83/93] build(deps): bump gloo-timers from 0.2.6 to 0.3.0 (#4852) Bumps [gloo-timers](https://github.com/rustwasm/gloo) from 0.2.6 to 0.3.0. - [Release notes](https://github.com/rustwasm/gloo/releases) - [Changelog](https://github.com/rustwasm/gloo/blob/master/CHANGELOG.md) - [Commits](https://github.com/rustwasm/gloo/compare/gloo-timers-v0.2.6...0.3.0) --- updated-dependencies: - dependency-name: gloo-timers dependency-type: direct:production update-type: version-update:semver-minor ... Signed-off-by: dependabot[bot] Co-authored-by: dependabot[bot] <49699333+dependabot[bot]@users.noreply.github.com> --- Cargo.lock | 4 ++-- common/client-core/Cargo.toml | 2 +- 2 files changed, 3 insertions(+), 3 deletions(-) diff --git a/Cargo.lock b/Cargo.lock index b5602a891e..37aa74f7a7 100644 --- a/Cargo.lock +++ b/Cargo.lock @@ -2686,9 +2686,9 @@ dependencies = [ [[package]] name = "gloo-timers" -version = "0.2.6" +version = "0.3.0" source = "registry+https://github.com/rust-lang/crates.io-index" -checksum = "9b995a66bb87bebce9a0f4a95aed01daca4872c050bfcb21653361c03bc35e5c" +checksum = "bbb143cf96099802033e0d4f4963b19fd2e0b728bcf076cd9cf7f6634f092994" dependencies = [ "futures-channel", "futures-core", diff --git a/common/client-core/Cargo.toml b/common/client-core/Cargo.toml index 548592f0ae..ab5d5fca4c 100644 --- a/common/client-core/Cargo.toml +++ b/common/client-core/Cargo.toml @@ -102,7 +102,7 @@ workspace = true features = ["tokio"] [target."cfg(target_arch = \"wasm32\")".dependencies.gloo-timers] -version = "0.2.4" +version = "0.3.0" features = ["futures"] [target."cfg(target_arch = \"wasm32\")".dependencies.wasm-utils] From 6db3b34bcb4f2044b664483d434c10273de7a881 Mon Sep 17 00:00:00 2001 From: =?UTF-8?q?Bogdan-=C8=98tefan=20Neac=C5=9Fu?= Date: Thu, 12 Sep 2024 13:49:33 +0200 Subject: [PATCH 84/93] Bump defguard to github latest version (#4872) * Bump defguard to github latest version * Fix comment location --- Cargo.lock | 18 +++++++++--------- Cargo.toml | 3 ++- common/wireguard/src/lib.rs | 1 + 3 files changed, 12 insertions(+), 10 deletions(-) diff --git a/Cargo.lock b/Cargo.lock index 825f1bf438..0d6b7e4ea6 100644 --- a/Cargo.lock +++ b/Cargo.lock @@ -1862,11 +1862,10 @@ checksum = "e8566979429cf69b49a5c740c60791108e86440e8be149bbea4fe54d2c32d6e2" [[package]] name = "defguard_wireguard_rs" -version = "0.4.2" -source = "registry+https://github.com/rust-lang/crates.io-index" -checksum = "6ba16f17698d4b389907310af018b0c3a80b025bba9c38d947cbc6dd70921743" +version = "0.4.7" +source = "git+https://github.com/DefGuard/wireguard-rs.git?rev=v0.4.7#ef1cf3714629bf5016fb38cbb7320451dc69fb09" dependencies = [ - "base64 0.21.7", + "base64 0.22.1", "libc", "log", "netlink-packet-core", @@ -1875,7 +1874,7 @@ dependencies = [ "netlink-packet-utils", "netlink-packet-wireguard", "netlink-sys", - "nix 0.27.1", + "nix 0.29.0", "serde", "thiserror", ] @@ -4010,14 +4009,15 @@ dependencies = [ [[package]] name = "netlink-packet-route" -version = "0.17.1" +version = "0.20.1" source = "registry+https://github.com/rust-lang/crates.io-index" -checksum = "053998cea5a306971f88580d0829e90f270f940befd7cf928da179d4187a5a66" +checksum = "55e5bda7ca0f9ac5e75b5debac3b75e29a8ac8e2171106a2c3bb466389a8dd83" dependencies = [ "anyhow", - "bitflags 1.3.2", + "bitflags 2.5.0", "byteorder", "libc", + "log", "netlink-packet-core", "netlink-packet-utils", ] @@ -4077,7 +4077,6 @@ dependencies = [ "bitflags 2.5.0", "cfg-if", "libc", - "memoffset", ] [[package]] @@ -4090,6 +4089,7 @@ dependencies = [ "cfg-if", "cfg_aliases", "libc", + "memoffset", ] [[package]] diff --git a/Cargo.toml b/Cargo.toml index 936b1f07e0..dcc3fbdd32 100644 --- a/Cargo.toml +++ b/Cargo.toml @@ -210,7 +210,8 @@ ctr = "0.9.1" cupid = "0.6.1" curve25519-dalek = "4.1" dashmap = "5.5.3" -defguard_wireguard_rs = "0.4.2" +# We want https://github.com/DefGuard/wireguard-rs/pull/64 , but there's no crates.io release being pushed out anymore +defguard_wireguard_rs = { git = "https://github.com/DefGuard/wireguard-rs.git", rev = "v0.4.7" } digest = "0.10.7" dirs = "5.0" doc-comment = "0.3" diff --git a/common/wireguard/src/lib.rs b/common/wireguard/src/lib.rs index cf6ce7e857..8125572bce 100644 --- a/common/wireguard/src/lib.rs +++ b/common/wireguard/src/lib.rs @@ -115,6 +115,7 @@ pub async fn start_wireguard( address: wireguard_data.inner.config().private_ip.to_string(), port: wireguard_data.inner.config().announced_port as u32, peers, + mtu: None, }; wg_api.configure_interface(&interface_config)?; From aad028be3f710010ba1d84d680c5a3446e322f16 Mon Sep 17 00:00:00 2001 From: benedettadavico Date: Fri, 13 Sep 2024 11:48:49 +0200 Subject: [PATCH 85/93] update qa env --- envs/qa.env | 11 ++++------- 1 file changed, 4 insertions(+), 7 deletions(-) diff --git a/envs/qa.env b/envs/qa.env index 781d4ef19f..e88f845416 100644 --- a/envs/qa.env +++ b/envs/qa.env @@ -11,16 +11,13 @@ STAKE_DENOM_DISPLAY=nyx DENOMS_EXPONENT=6 MIXNET_CONTRACT_ADDRESS=n1hm4y6fzgxgu688jgf7ek66px6xkrtmn3gyk8fax3eawhp68c2d5qujz296 -ECASH_CONTRACT_ADDRESS=n14y2x8a60knc5jjfeztt84kw8x8l5pwdgnqg256v0p9v4p7t2q6eswxyusw -GROUP_CONTRACT_ADDRESS=n1qp35fcj0v9u3trhaps5v9q0lc42t4m6aty2wryss75ee8zuqnsqqdcreyq -MULTISIG_CONTRACT_ADDRESS=n1qa4hswlcjmttulj0q9qa46jf64f93pecl6tydcsjldfe0hy5ju0sdmwzya -COCONUT_DKG_CONTRACT_ADDRESS=n1ayrk6wp6w5lf6njtnfjwljmtcc9vevv5sxwkz7uq24rp2pw67t0qhmmxdd +ECASH_CONTRACT_ADDRESS=n13xspq62y9gq6nueqmywxcdv2yep4p6nzv98w2889k25v3nhdy2dq2rkrk7 +GROUP_CONTRACT_ADDRESS=n13l7rwuwktklrwskc7m6lv70zws07en85uma28j7dxwsz9y5hvvhspl7a2t +MULTISIG_CONTRACT_ADDRESS=n138c9pyf7f3hyx0j3t6vmsz7ultnw2wj0lu6hzndep9z5grgq9haqlc25k0 +COCONUT_DKG_CONTRACT_ADDRESS=n1pk8jgr6y4c5k93gz7qf3xc0hvygmp7csk88c2tf8l39tkq6834wq2a6dtr VESTING_CONTRACT_ADDRESS=n1jlzdxnyces4hrhqz68dqk28mrw5jgwtcfq0c2funcwrmw0dx9l9s8nnnvj REWARDING_VALIDATOR_ADDRESS=n1rfvpsynktze6wvn6ldskj8xgwfzzk5v6pnff39 EXPLORER_API=https://qa-network-explorer.qa.nymte.ch/api NYXD="https://qa-validator.qa.nymte.ch" NYM_API="https://qa-nym-api.qa.nymte.ch/api" - -DKG_TIME_CONFIGURATION="600,300,300,60,60,1209600" -EXIT_POLICY="https://nymtech.net/.wellknown/network-requester/exit-policy.txt" From 48bcd7e80280e2e12d2e66b5715bf59cbdcb2fbb Mon Sep 17 00:00:00 2001 From: =?UTF-8?q?J=C4=99drzej=20Stuczy=C5=84ski?= Date: Tue, 17 Sep 2024 14:21:42 +0100 Subject: [PATCH 86/93] fix: allow updating globally stored signatures --- .../credential-storage/src/backends/sqlite.rs | 42 +++++++++++++++---- 1 file changed, 35 insertions(+), 7 deletions(-) diff --git a/common/credential-storage/src/backends/sqlite.rs b/common/credential-storage/src/backends/sqlite.rs index 39dbdc8702..8c5b20c7d8 100644 --- a/common/credential-storage/src/backends/sqlite.rs +++ b/common/credential-storage/src/backends/sqlite.rs @@ -171,10 +171,20 @@ impl SqliteEcashTicketbookManager { data: &[u8], ) -> Result<(), sqlx::Error> { sqlx::query!( - "INSERT INTO master_verification_key(epoch_id, serialised_key, serialization_revision) VALUES (?, ?, ?)", + r#" + INSERT OR IGNORE INTO master_verification_key(epoch_id, serialised_key, serialization_revision) VALUES (?, ?, ?); + UPDATE master_verification_key + SET + serialised_key = ?, + serialization_revision = ? + WHERE epoch_id = ? + "#, epoch_id, data, - serialisation_revision + serialisation_revision, + data, + serialisation_revision, + epoch_id ) .execute(&self.connection_pool) .await?; @@ -204,10 +214,20 @@ impl SqliteEcashTicketbookManager { data: &[u8], ) -> Result<(), sqlx::Error> { sqlx::query!( - "INSERT INTO coin_indices_signatures(epoch_id, serialised_signatures, serialization_revision) VALUES (?, ?, ?)", + r#" + INSERT OR IGNORE INTO coin_indices_signatures(epoch_id, serialised_signatures, serialization_revision) VALUES (?, ?, ?); + UPDATE coin_indices_signatures + SET + serialised_signatures = ?, + serialization_revision = ? + WHERE epoch_id = ? + "#, epoch_id, data, - serialisation_revision + serialisation_revision, + data, + serialisation_revision, + epoch_id, ) .execute(&self.connection_pool) .await?; @@ -240,13 +260,21 @@ impl SqliteEcashTicketbookManager { ) -> Result<(), sqlx::Error> { sqlx::query!( r#" - INSERT INTO expiration_date_signatures(expiration_date, epoch_id, serialised_signatures, serialization_revision) - VALUES (?, ?, ?, ?) + INSERT OR IGNORE INTO expiration_date_signatures(expiration_date, epoch_id, serialised_signatures, serialization_revision) + VALUES (?, ?, ?, ?); + UPDATE expiration_date_signatures + SET + serialised_signatures = ?, + serialization_revision = ? + WHERE expiration_date = ? "#, expiration_date, epoch_id, data, - serialisation_revision + serialisation_revision, + data, + serialisation_revision, + expiration_date ) .execute(&self.connection_pool) .await?; From 4548ef4d05f758ef5bbb015350d56d6ed9b2ad5a Mon Sep 17 00:00:00 2001 From: =?UTF-8?q?J=C4=99drzej=20Stuczy=C5=84ski?= Date: Tue, 17 Sep 2024 18:39:01 +0100 Subject: [PATCH 87/93] adding extra logs --- .../connection_handler/authenticated.rs | 98 ++++++++++--------- .../websocket/connection_handler/fresh.rs | 2 +- .../websocket/connection_handler/mod.rs | 2 +- 3 files changed, 53 insertions(+), 49 deletions(-) diff --git a/gateway/src/node/client_handling/websocket/connection_handler/authenticated.rs b/gateway/src/node/client_handling/websocket/connection_handler/authenticated.rs index 12bbb16b51..6bfd95478f 100644 --- a/gateway/src/node/client_handling/websocket/connection_handler/authenticated.rs +++ b/gateway/src/node/client_handling/websocket/connection_handler/authenticated.rs @@ -26,7 +26,7 @@ use nym_gateway_storage::{error::StorageError, Storage}; use nym_sphinx::forwarding::packet::MixPacket; use nym_task::TaskClient; use nym_validator_client::coconut::EcashApiError; -use rand::{CryptoRng, Rng}; +use rand::{random, CryptoRng, Rng}; use std::{process, time::Duration}; use thiserror::Error; use tokio::io::{AsyncRead, AsyncWrite}; @@ -217,11 +217,7 @@ where enc_credential: Vec, iv: Vec, ) -> Result { - // TODO: change it into a span field instead once we move to tracing - debug!( - "handling e-cash bandwidth request from {}", - self.client.address - ); + debug!("handling e-cash bandwidth request"); let credential = ClientControlRequest::try_from_enc_ecash_credential( enc_credential, @@ -234,7 +230,11 @@ where self.bandwidth_storage_manager.clone(), ); - let available_total = verifier.verify().await?; + let available_total = verifier + .verify() + .await + .inspect_err(|verification_failure| debug!("{verification_failure}"))?; + trace!("available total bandwidth: {available_total}"); Ok(ServerResponse::Bandwidth { available_total }) } @@ -297,40 +297,43 @@ where /// * `raw_request`: raw message to handle. async fn handle_text(&mut self, raw_request: String) -> Message { trace!("text request"); - match ClientControlRequest::try_from(raw_request) { - Err(e) => RequestHandlingError::InvalidTextRequest(e).into_error_message(), - Ok(request) => match request { - ClientControlRequest::EcashCredential { enc_credential, iv } => self - .handle_ecash_bandwidth(enc_credential, iv) - .await - .into_ws_message(), - ClientControlRequest::BandwidthCredential { .. } => { - RequestHandlingError::IllegalRequest { - additional_context: "coconut credential are not longer supported".into(), - } - .into_error_message() - } - ClientControlRequest::BandwidthCredentialV2 { .. } => { - RequestHandlingError::IllegalRequest { - additional_context: "coconut credential are not longer supported".into(), - } - .into_error_message() - } - ClientControlRequest::ClaimFreeTestnetBandwidth => self - .bandwidth_storage_manager - .handle_claim_testnet_bandwidth() - .await - .map_err(|e| e.into()) - .into_ws_message(), - other => RequestHandlingError::IllegalRequest { - additional_context: format!( - "received illegal message of type {} in an authenticated client", - other.name() - ), - } - .into_error_message(), - }, + + let request = match ClientControlRequest::try_from(raw_request) { + Ok(req) => { + debug!("received request of type {}", req.name()); + req + } + Err(err) => { + debug!("request was malformed: {err}"); + return RequestHandlingError::InvalidTextRequest(err).into_error_message(); + } + }; + + match request { + ClientControlRequest::EcashCredential { enc_credential, iv } => { + self.handle_ecash_bandwidth(enc_credential, iv).await + } + ClientControlRequest::BandwidthCredential { .. } + | ClientControlRequest::BandwidthCredentialV2 { .. } => { + Err(RequestHandlingError::IllegalRequest { + additional_context: "coconut credential are not longer supported".into(), + }) + } + ClientControlRequest::ClaimFreeTestnetBandwidth => self + .bandwidth_storage_manager + .handle_claim_testnet_bandwidth() + .await + .map_err(|e| e.into()), + other => Err(RequestHandlingError::IllegalRequest { + additional_context: format!( + "received illegal message of type {} in an authenticated client", + other.name() + ), + }), } + .inspect(|res| debug!(response = ?res, "success")) + .inspect_err(|err| debug!(error = %err, "failure")) + .into_ws_message() } /// Handles pong message received from the client. @@ -364,12 +367,13 @@ where /// # Arguments /// /// * `raw_request`: raw received websocket message. + #[instrument(level = "debug", skip_all, + fields( + client = %self.client.address.as_base58_string() + ) + )] async fn handle_request(&mut self, raw_request: Message) -> Option { - // TODO: this should be added via tracing - debug!( - "handling request from {}", - self.client.address.as_base58_string() - ); + trace!("new request"); // apparently tungstenite auto-handles ping/pong/close messages so for now let's ignore // them and let's test that claim. If that's not the case, just copy code from @@ -390,8 +394,8 @@ where where S: AsyncRead + AsyncWrite + Unpin, { - let tag: u64 = rand::thread_rng().gen(); - debug!("Got request to ping our connection: {}", tag); + let tag: u64 = random(); + debug!("got request to ping our connection: {tag}"); self.inner .send_websocket_message(Message::Ping(tag.to_be_bytes().to_vec())) .await?; diff --git a/gateway/src/node/client_handling/websocket/connection_handler/fresh.rs b/gateway/src/node/client_handling/websocket/connection_handler/fresh.rs index 289d7922bb..11f0ff2e34 100644 --- a/gateway/src/node/client_handling/websocket/connection_handler/fresh.rs +++ b/gateway/src/node/client_handling/websocket/connection_handler/fresh.rs @@ -419,7 +419,7 @@ where // we can't handle clients with higher protocol than ours // (perhaps we could try to negotiate downgrade on our end? sounds like a nice future improvement) if client_protocol_version <= CURRENT_PROTOCOL_VERSION { - info!("the client is using exactly the same (or older) protocol version as we are. We're good to continue!"); + debug!("the client is using exactly the same (or older) protocol version as we are. We're good to continue!"); Ok(CURRENT_PROTOCOL_VERSION) } else { let err = InitialAuthenticationError::IncompatibleProtocol { diff --git a/gateway/src/node/client_handling/websocket/connection_handler/mod.rs b/gateway/src/node/client_handling/websocket/connection_handler/mod.rs index 6e1d8a9b5a..bd33b25a9a 100644 --- a/gateway/src/node/client_handling/websocket/connection_handler/mod.rs +++ b/gateway/src/node/client_handling/websocket/connection_handler/mod.rs @@ -102,7 +102,7 @@ where .await { Err(timeout_err) => { - warn!("websocket handshake timedout: {timeout_err}"); + warn!("websocket handshake timed out: {timeout_err}"); return; } Ok(Err(err)) => { From 2fa8da811784f17b7c8632e7f61684935d1db30f Mon Sep 17 00:00:00 2001 From: =?UTF-8?q?J=C4=99drzej=20Stuczy=C5=84ski?= Date: Tue, 17 Sep 2024 18:39:49 +0100 Subject: [PATCH 88/93] making sure there can be only a single client task claiming more bandwidth --- .../gateway-client/src/bandwidth.rs | 39 +++++++++++++++++-- .../gateway-client/src/client/mod.rs | 5 +++ 2 files changed, 41 insertions(+), 3 deletions(-) diff --git a/common/client-libs/gateway-client/src/bandwidth.rs b/common/client-libs/gateway-client/src/bandwidth.rs index f232c004ec..1f45fdc8ea 100644 --- a/common/client-libs/gateway-client/src/bandwidth.rs +++ b/common/client-libs/gateway-client/src/bandwidth.rs @@ -2,21 +2,37 @@ // SPDX-License-Identifier: Apache-2.0 use si_scale::helpers::bibytes2; -use std::sync::atomic::{AtomicI64, Ordering}; +use std::sync::atomic::{AtomicBool, AtomicI64, Ordering}; use std::sync::Arc; use std::time::Duration; use time::OffsetDateTime; -#[derive(Clone, Default)] +pub(crate) struct BandwidthClaimGuard { + inner: Arc, +} + +impl Drop for BandwidthClaimGuard { + fn drop(&mut self) { + let old = self.inner.claiming_more.swap(false, Ordering::SeqCst); + assert!( + old, + "critical failure: there were multiple BandwidthClaimGuard existing" + ) + } +} + +#[derive(Clone)] pub struct ClientBandwidth { inner: Arc, } -#[derive(Default)] struct ClientBandwidthInner { /// the actual bandwidth amount (in bytes) available available: AtomicI64, + /// flag to indicate whether this client is currently in the process of claiming additional bandwidth + claiming_more: AtomicBool, + /// defines the timestamp when the bandwidth information has been logged to the logs stream last_logged_ts: AtomicI64, @@ -29,11 +45,28 @@ impl ClientBandwidth { ClientBandwidth { inner: Arc::new(ClientBandwidthInner { available: AtomicI64::new(0), + claiming_more: AtomicBool::new(false), last_logged_ts: AtomicI64::new(0), last_updated_ts: AtomicI64::new(0), }), } } + + pub(crate) fn begin_bandwidth_claim(&self) -> Option { + if self + .inner + .claiming_more + .compare_exchange(false, true, Ordering::SeqCst, Ordering::SeqCst) + .is_ok() + { + Some(BandwidthClaimGuard { + inner: self.inner.clone(), + }) + } else { + None + } + } + pub(crate) fn remaining(&self) -> i64 { self.inner.available.load(Ordering::Acquire) } diff --git a/common/client-libs/gateway-client/src/client/mod.rs b/common/client-libs/gateway-client/src/client/mod.rs index d899ec2928..ad30cc2c8e 100644 --- a/common/client-libs/gateway-client/src/client/mod.rs +++ b/common/client-libs/gateway-client/src/client/mod.rs @@ -598,6 +598,11 @@ impl GatewayClient { return Err(GatewayClientError::NoBandwidthControllerAvailable); } + let Some(_claim_guard) = self.bandwidth.begin_bandwidth_claim() else { + debug!("there's already an existing bandwidth claim ongoing"); + return Ok(()); + }; + warn!("Not enough bandwidth. Trying to get more bandwidth, this might take a while"); if !self.cfg.bandwidth.require_tickets { info!("The client is running in disabled credentials mode - attempting to claim bandwidth without a credential"); From c8c3928575a20c75484eac17374067af7b6e4860 Mon Sep 17 00:00:00 2001 From: =?UTF-8?q?J=C4=99drzej=20Stuczy=C5=84ski?= Date: Tue, 17 Sep 2024 18:40:24 +0100 Subject: [PATCH 89/93] put client bandwidth (gateway-side) behind shared pointer --- .../src/bandwidth_storage_manager.rs | 52 ++++++----- .../src/client_bandwidth.rs | 87 ++++++++++++++++--- common/credential-verification/src/lib.rs | 4 +- 3 files changed, 100 insertions(+), 43 deletions(-) diff --git a/common/credential-verification/src/bandwidth_storage_manager.rs b/common/credential-verification/src/bandwidth_storage_manager.rs index 3a67d43743..c36306def4 100644 --- a/common/credential-verification/src/bandwidth_storage_manager.rs +++ b/common/credential-verification/src/bandwidth_storage_manager.rs @@ -1,6 +1,9 @@ // Copyright 2024 - Nym Technologies SA // SPDX-License-Identifier: Apache-2.0 +use crate::error::*; +use crate::BandwidthFlushingBehaviourConfig; +use crate::ClientBandwidth; use nym_credentials::ecash::utils::ecash_today; use nym_credentials_interface::Bandwidth; use nym_gateway_requests::ServerResponse; @@ -9,10 +12,6 @@ use si_scale::helpers::bibytes2; use time::OffsetDateTime; use tracing::*; -use crate::error::*; -use crate::BandwidthFlushingBehaviourConfig; -use crate::ClientBandwidth; - const FREE_TESTNET_BANDWIDTH_VALUE: Bandwidth = Bandwidth::new_unchecked(64 * 1024 * 1024 * 1024); // 64GB #[derive(Clone)] @@ -43,7 +42,7 @@ impl BandwidthStorageManager { async fn sync_expiration(&mut self) -> Result<()> { self.storage - .set_expiration(self.client_id, self.client_bandwidth.bandwidth.expiration) + .set_expiration(self.client_id, self.client_bandwidth.expiration().await) .await?; Ok(()) } @@ -57,17 +56,17 @@ impl BandwidthStorageManager { self.increase_bandwidth(FREE_TESTNET_BANDWIDTH_VALUE, ecash_today()) .await?; - let available_total = self.client_bandwidth.bandwidth.bytes; + let available_total = self.client_bandwidth.available().await; Ok(ServerResponse::Bandwidth { available_total }) } #[instrument(skip_all)] pub async fn try_use_bandwidth(&mut self, required_bandwidth: i64) -> Result { - if self.client_bandwidth.bandwidth.expired() { + if self.client_bandwidth.expired().await { self.expire_bandwidth().await?; } - let available_bandwidth = self.client_bandwidth.bandwidth.bytes; + let available_bandwidth = self.client_bandwidth.available().await; if available_bandwidth < required_bandwidth { return Err(Error::OutOfBandwidth { @@ -86,8 +85,7 @@ impl BandwidthStorageManager { async fn expire_bandwidth(&mut self) -> Result<()> { self.storage.reset_bandwidth(self.client_id).await?; - self.client_bandwidth.bandwidth = Default::default(); - self.client_bandwidth.update_sync_data(); + self.client_bandwidth.expire_bandwidth().await; Ok(()) } @@ -97,32 +95,31 @@ impl BandwidthStorageManager { /// /// * `amount`: amount to decrease the available bandwidth by. async fn consume_bandwidth(&mut self, amount: i64) -> Result<()> { - self.client_bandwidth.bandwidth.bytes -= amount; - self.client_bandwidth.bytes_delta_since_sync -= amount; + self.client_bandwidth.decrease_bandwidth(amount).await; // since we're going to be operating on a fair use policy anyway, even if we crash and let extra few packets // through, that's completely fine - if self.client_bandwidth.should_sync(self.bandwidth_cfg) { - self.sync_bandwidth().await?; + if self.client_bandwidth.should_sync(self.bandwidth_cfg).await { + let synced_bandwidth = self.sync_storage_bandwidth().await?; + self.client_bandwidth + .update_and_sync_data(synced_bandwidth) + .await } Ok(()) } #[instrument(level = "trace", skip_all)] - async fn sync_bandwidth(&mut self) -> Result<()> { + async fn sync_storage_bandwidth(&mut self) -> Result { trace!("syncing client bandwidth with the underlying storage"); let updated = self .storage - .increase_bandwidth(self.client_id, self.client_bandwidth.bytes_delta_since_sync) + .increase_bandwidth( + self.client_id, + self.client_bandwidth.delta_since_sync().await, + ) .await?; - - trace!(updated); - - self.client_bandwidth.bandwidth.bytes = updated; - - self.client_bandwidth.update_sync_data(); - Ok(()) + Ok(updated) } /// Increases the amount of available bandwidth of the connected client by the specified value. @@ -136,13 +133,14 @@ impl BandwidthStorageManager { bandwidth: Bandwidth, expiration: OffsetDateTime, ) -> Result<()> { - self.client_bandwidth.bandwidth.bytes += bandwidth.value() as i64; - self.client_bandwidth.bytes_delta_since_sync += bandwidth.value() as i64; - self.client_bandwidth.bandwidth.expiration = expiration; + self.client_bandwidth + .increase_bandwidth_with_flushed(bandwidth.value() as i64, expiration) + .await; // any increases to bandwidth should get flushed immediately // (we don't want to accidentally miss somebody claiming a gigabyte voucher) self.sync_expiration().await?; - self.sync_bandwidth().await + self.sync_storage_bandwidth().await?; + Ok(()) } } diff --git a/common/credential-verification/src/client_bandwidth.rs b/common/credential-verification/src/client_bandwidth.rs index 610a198e88..de3026a9d0 100644 --- a/common/credential-verification/src/client_bandwidth.rs +++ b/common/credential-verification/src/client_bandwidth.rs @@ -1,10 +1,12 @@ // Copyright 2024 - Nym Technologies SA // SPDX-License-Identifier: Apache-2.0 -use std::time::Duration; - +use nym_credentials::ecash::utils::ecash_today; use nym_credentials_interface::AvailableBandwidth; +use std::sync::Arc; +use std::time::Duration; use time::OffsetDateTime; +use tokio::sync::RwLock; #[derive(Debug, Clone, Copy)] pub struct BandwidthFlushingBehaviourConfig { @@ -15,8 +17,13 @@ pub struct BandwidthFlushingBehaviourConfig { pub client_bandwidth_max_delta_flushing_amount: i64, } -#[derive(Debug, Clone, Copy)] +#[derive(Debug, Clone)] pub struct ClientBandwidth { + inner: Arc>, +} + +#[derive(Debug)] +struct ClientBandwidthInner { pub(crate) bandwidth: AvailableBandwidth, pub(crate) last_flushed: OffsetDateTime, @@ -30,28 +37,80 @@ pub struct ClientBandwidth { impl ClientBandwidth { pub fn new(bandwidth: AvailableBandwidth) -> ClientBandwidth { ClientBandwidth { - bandwidth, - last_flushed: OffsetDateTime::now_utc(), - bytes_at_last_sync: bandwidth.bytes, - bytes_delta_since_sync: 0, + inner: Arc::new(RwLock::new(ClientBandwidthInner { + bandwidth, + last_flushed: OffsetDateTime::now_utc(), + bytes_at_last_sync: bandwidth.bytes, + bytes_delta_since_sync: 0, + })), } } - pub(crate) fn should_sync(&self, cfg: BandwidthFlushingBehaviourConfig) -> bool { - if self.bytes_delta_since_sync.abs() >= cfg.client_bandwidth_max_delta_flushing_amount { + pub(crate) async fn should_sync(&self, cfg: BandwidthFlushingBehaviourConfig) -> bool { + let guard = self.inner.read().await; + + if guard.bytes_delta_since_sync.abs() >= cfg.client_bandwidth_max_delta_flushing_amount { return true; } - if self.last_flushed + cfg.client_bandwidth_max_flushing_rate < OffsetDateTime::now_utc() { + if guard.last_flushed + cfg.client_bandwidth_max_flushing_rate < OffsetDateTime::now_utc() { return true; } false } - pub(crate) fn update_sync_data(&mut self) { - self.last_flushed = OffsetDateTime::now_utc(); - self.bytes_at_last_sync = self.bandwidth.bytes; - self.bytes_delta_since_sync = 0; + pub(crate) async fn available(&self) -> i64 { + self.inner.read().await.bandwidth.bytes + } + + pub(crate) async fn delta_since_sync(&self) -> i64 { + self.inner.read().await.bytes_delta_since_sync + } + pub(crate) async fn expiration(&self) -> OffsetDateTime { + self.inner.read().await.bandwidth.expiration + } + + pub(crate) async fn expired(&self) -> bool { + self.expiration().await < ecash_today() + } + + pub(crate) async fn decrease_bandwidth(&self, decrease: i64) { + let mut guard = self.inner.write().await; + + guard.bandwidth.bytes -= decrease; + guard.bytes_at_last_sync -= decrease; + } + + pub(crate) async fn increase_bandwidth_with_flushed( + &self, + increase: i64, + expiration: OffsetDateTime, + ) { + let mut guard = self.inner.write().await; + + guard.bandwidth.bytes += increase; + guard.bandwidth.expiration = expiration; + guard.last_flushed = OffsetDateTime::now_utc(); + guard.bytes_at_last_sync = guard.bandwidth.bytes; + guard.bytes_delta_since_sync += increase; + } + + pub(crate) async fn expire_bandwidth(&self) { + let mut guard = self.inner.write().await; + + guard.bandwidth = AvailableBandwidth::default(); + guard.last_flushed = OffsetDateTime::now_utc(); + guard.bytes_at_last_sync = 0; + guard.bytes_delta_since_sync = 0; + } + + pub(crate) async fn update_and_sync_data(&self, updated_bandwidth: i64) { + let mut guard = self.inner.write().await; + + guard.bandwidth.bytes = updated_bandwidth; + guard.bytes_at_last_sync = updated_bandwidth; + guard.bytes_delta_since_sync = 0; + guard.last_flushed = OffsetDateTime::now_utc(); } } diff --git a/common/credential-verification/src/lib.rs b/common/credential-verification/src/lib.rs index bb3a0cab8f..4d2e7be2da 100644 --- a/common/credential-verification/src/lib.rs +++ b/common/credential-verification/src/lib.rs @@ -150,7 +150,7 @@ impl CredentialVerifier { Ok(self .bandwidth_storage_manager .client_bandwidth - .bandwidth - .bytes) + .available() + .await) } } From 87751894d94647ca65670a1142a8b022d4d4ccdb Mon Sep 17 00:00:00 2001 From: =?UTF-8?q?Jon=20H=C3=A4ggblad?= Date: Tue, 17 Sep 2024 23:29:36 +0200 Subject: [PATCH 90/93] Fix apt install in ci-build-upload-binaries.yml (#4894) --- .github/workflows/ci-build-upload-binaries.yml | 2 +- 1 file changed, 1 insertion(+), 1 deletion(-) diff --git a/.github/workflows/ci-build-upload-binaries.yml b/.github/workflows/ci-build-upload-binaries.yml index 04d9b9673c..3e615f7396 100644 --- a/.github/workflows/ci-build-upload-binaries.yml +++ b/.github/workflows/ci-build-upload-binaries.yml @@ -56,7 +56,7 @@ jobs: echo $OUTPUT_DIR - name: Install Dependencies (Linux) - run: sudo apt update && sudo apt install libudev-dev + run: sudo apt-get update && sudo apt-get -y install libudev-dev - name: Sets env vars for tokio if set in manual dispatch inputs run: | From 2a6aa13ecd7710824b3b92bf8f2595867a63ea05 Mon Sep 17 00:00:00 2001 From: =?UTF-8?q?J=C4=99drzej=20Stuczy=C5=84ski?= Date: Wed, 18 Sep 2024 11:12:24 +0100 Subject: [PATCH 91/93] fixed client bandwidth being not correctly deducted --- common/credential-verification/src/client_bandwidth.rs | 2 +- 1 file changed, 1 insertion(+), 1 deletion(-) diff --git a/common/credential-verification/src/client_bandwidth.rs b/common/credential-verification/src/client_bandwidth.rs index de3026a9d0..d015cbb4db 100644 --- a/common/credential-verification/src/client_bandwidth.rs +++ b/common/credential-verification/src/client_bandwidth.rs @@ -79,7 +79,7 @@ impl ClientBandwidth { let mut guard = self.inner.write().await; guard.bandwidth.bytes -= decrease; - guard.bytes_at_last_sync -= decrease; + guard.bytes_delta_since_sync -= decrease; } pub(crate) async fn increase_bandwidth_with_flushed( From 5753b799978c11f0fc3c11ccc737aa71ba018ea6 Mon Sep 17 00:00:00 2001 From: =?UTF-8?q?J=C4=99drzej=20Stuczy=C5=84ski?= Date: Wed, 18 Sep 2024 11:27:35 +0100 Subject: [PATCH 92/93] slightly refactored bandwidth tracking --- .../src/bandwidth_storage_manager.rs | 15 ++++++----- .../src/client_bandwidth.rs | 26 +++++++------------ 2 files changed, 18 insertions(+), 23 deletions(-) diff --git a/common/credential-verification/src/bandwidth_storage_manager.rs b/common/credential-verification/src/bandwidth_storage_manager.rs index c36306def4..b2f5cefb83 100644 --- a/common/credential-verification/src/bandwidth_storage_manager.rs +++ b/common/credential-verification/src/bandwidth_storage_manager.rs @@ -100,17 +100,14 @@ impl BandwidthStorageManager { // since we're going to be operating on a fair use policy anyway, even if we crash and let extra few packets // through, that's completely fine if self.client_bandwidth.should_sync(self.bandwidth_cfg).await { - let synced_bandwidth = self.sync_storage_bandwidth().await?; - self.client_bandwidth - .update_and_sync_data(synced_bandwidth) - .await + self.sync_storage_bandwidth().await?; } Ok(()) } #[instrument(level = "trace", skip_all)] - async fn sync_storage_bandwidth(&mut self) -> Result { + async fn sync_storage_bandwidth(&mut self) -> Result<()> { trace!("syncing client bandwidth with the underlying storage"); let updated = self .storage @@ -119,7 +116,11 @@ impl BandwidthStorageManager { self.client_bandwidth.delta_since_sync().await, ) .await?; - Ok(updated) + + self.client_bandwidth + .resync_bandwidth_with_storage(updated) + .await; + Ok(()) } /// Increases the amount of available bandwidth of the connected client by the specified value. @@ -134,7 +135,7 @@ impl BandwidthStorageManager { expiration: OffsetDateTime, ) -> Result<()> { self.client_bandwidth - .increase_bandwidth_with_flushed(bandwidth.value() as i64, expiration) + .increase_bandwidth(bandwidth.value() as i64, expiration) .await; // any increases to bandwidth should get flushed immediately diff --git a/common/credential-verification/src/client_bandwidth.rs b/common/credential-verification/src/client_bandwidth.rs index d015cbb4db..8b165d9353 100644 --- a/common/credential-verification/src/client_bandwidth.rs +++ b/common/credential-verification/src/client_bandwidth.rs @@ -25,7 +25,7 @@ pub struct ClientBandwidth { #[derive(Debug)] struct ClientBandwidthInner { pub(crate) bandwidth: AvailableBandwidth, - pub(crate) last_flushed: OffsetDateTime, + pub(crate) last_synced: OffsetDateTime, /// the number of bytes the client had during the last sync. /// it is used to determine whether the current value should be synced with the storage @@ -39,7 +39,7 @@ impl ClientBandwidth { ClientBandwidth { inner: Arc::new(RwLock::new(ClientBandwidthInner { bandwidth, - last_flushed: OffsetDateTime::now_utc(), + last_synced: OffsetDateTime::now_utc(), bytes_at_last_sync: bandwidth.bytes, bytes_delta_since_sync: 0, })), @@ -53,7 +53,7 @@ impl ClientBandwidth { return true; } - if guard.last_flushed + cfg.client_bandwidth_max_flushing_rate < OffsetDateTime::now_utc() { + if guard.last_synced + cfg.client_bandwidth_max_flushing_rate < OffsetDateTime::now_utc() { return true; } @@ -82,17 +82,11 @@ impl ClientBandwidth { guard.bytes_delta_since_sync -= decrease; } - pub(crate) async fn increase_bandwidth_with_flushed( - &self, - increase: i64, - expiration: OffsetDateTime, - ) { + pub(crate) async fn increase_bandwidth(&self, increase: i64, new_expiration: OffsetDateTime) { let mut guard = self.inner.write().await; guard.bandwidth.bytes += increase; - guard.bandwidth.expiration = expiration; - guard.last_flushed = OffsetDateTime::now_utc(); - guard.bytes_at_last_sync = guard.bandwidth.bytes; + guard.bandwidth.expiration = new_expiration; guard.bytes_delta_since_sync += increase; } @@ -100,17 +94,17 @@ impl ClientBandwidth { let mut guard = self.inner.write().await; guard.bandwidth = AvailableBandwidth::default(); - guard.last_flushed = OffsetDateTime::now_utc(); + guard.last_synced = OffsetDateTime::now_utc(); guard.bytes_at_last_sync = 0; guard.bytes_delta_since_sync = 0; } - pub(crate) async fn update_and_sync_data(&self, updated_bandwidth: i64) { + pub(crate) async fn resync_bandwidth_with_storage(&self, stored: i64) { let mut guard = self.inner.write().await; - guard.bandwidth.bytes = updated_bandwidth; - guard.bytes_at_last_sync = updated_bandwidth; + guard.bandwidth.bytes = stored; + guard.bytes_at_last_sync = stored; guard.bytes_delta_since_sync = 0; - guard.last_flushed = OffsetDateTime::now_utc(); + guard.last_synced = OffsetDateTime::now_utc(); } } From 803850be7453170d46867a8d60230ff990cedd6f Mon Sep 17 00:00:00 2001 From: benedettadavico Date: Mon, 23 Sep 2024 10:00:20 +0200 Subject: [PATCH 93/93] bump versions & update changelog --- CHANGELOG.md | 76 +++++++++++++++++++ Cargo.lock | 16 ++-- clients/native/Cargo.toml | 2 +- clients/socks5/Cargo.toml | 2 +- explorer-api/Cargo.toml | 2 +- nym-api/Cargo.toml | 2 +- nym-node/Cargo.toml | 2 +- .../network-requester/Cargo.toml | 2 +- tools/nym-cli/Cargo.toml | 2 +- tools/nymvisor/Cargo.toml | 2 +- 10 files changed, 92 insertions(+), 16 deletions(-) diff --git a/CHANGELOG.md b/CHANGELOG.md index fbed61bd54..209e993f51 100644 --- a/CHANGELOG.md +++ b/CHANGELOG.md @@ -4,6 +4,82 @@ Post 1.0.0 release, the changelog format is based on [Keep a Changelog](https:// ## [Unreleased] +## [2024.11-wedel] (2024-09-23) + +- Backport #4894 to fix ci ([#4899]) +- Bugfix/ticketbook false double spending ([#4892]) +- fix: allow updating globally stored signatures ([#4891]) +- [DOCs/operators]: Document changelog for patch/2024.10-caramello ([#4886]) +- [DOCs/operators]: Post release docs updates ([#4874]) +- Bump defguard to github latest version ([#4872]) +- chore: removed completed queued mixnet migration ([#4865]) +- Disable push trigger and add missing paths in ci-build ([#4864]) +- Fix linux conditional in ci-build.yml ([#4863]) +- Remove golang workaround in ci-sdk-wasm ([#4858]) +- Revert runner for ci-docs ([#4855]) +- Move credential verification into common crate ([#4853]) +- Fix test failure in ipr request size ([#4844]) +- Start switching over jobs to arc-ubuntu-20.04 ([#4843]) +- Use ecash credential type for bandwidth value ([#4840]) +- Create nym-repo-setup debian package and nym-vpn meta package ([#4837]) +- Remove serde_crate named import ([#4832]) +- Run cargo autoinherit following last weeks dependabot updates ([#4831]) +- revamped ticketbook serialisation and exposed additional cli methods ([#4827]) +- Expose wireguard details on self described endpoint ([#4825]) +- Remove unused wireguard flag from SDK ([#4823]) +- Add `axum` server to `nym-api` ([#4803]) +- Run cargo-autoinherit for a few new crates ([#4801]) +- Update dependabot ([#4796]) +- Fix clippy for unwrap_or_default ([#4783]) +- Enable dependabot version upgrades for root rust workspace ([#4778]) +- Persist used wireguard private IPs ([#4771]) +- Avoid race on ip and registration structures ([#4766]) +- docs/hotfix ([#4765]) +- chore: remove repetitive words ([#4763]) +- Make gateway latency check generic ([#4759]) +- Remove duplicate stat count for retransmissions ([#4756]) +- Update peer refresh value ([#4754]) +- Remove deprecated mark_as_success and use new disarm ([#4751]) +- Add get_mixnodes_described to validator_client ([#4725]) +- New Network Monitor ([#4610]) + +[#4899]: https://github.com/nymtech/nym/pull/4899 +[#4892]: https://github.com/nymtech/nym/pull/4892 +[#4891]: https://github.com/nymtech/nym/pull/4891 +[#4886]: https://github.com/nymtech/nym/pull/4886 +[#4874]: https://github.com/nymtech/nym/pull/4874 +[#4872]: https://github.com/nymtech/nym/pull/4872 +[#4865]: https://github.com/nymtech/nym/pull/4865 +[#4864]: https://github.com/nymtech/nym/pull/4864 +[#4863]: https://github.com/nymtech/nym/pull/4863 +[#4858]: https://github.com/nymtech/nym/pull/4858 +[#4855]: https://github.com/nymtech/nym/pull/4855 +[#4853]: https://github.com/nymtech/nym/pull/4853 +[#4844]: https://github.com/nymtech/nym/pull/4844 +[#4843]: https://github.com/nymtech/nym/pull/4843 +[#4840]: https://github.com/nymtech/nym/pull/4840 +[#4837]: https://github.com/nymtech/nym/pull/4837 +[#4832]: https://github.com/nymtech/nym/pull/4832 +[#4831]: https://github.com/nymtech/nym/pull/4831 +[#4827]: https://github.com/nymtech/nym/pull/4827 +[#4825]: https://github.com/nymtech/nym/pull/4825 +[#4823]: https://github.com/nymtech/nym/pull/4823 +[#4803]: https://github.com/nymtech/nym/pull/4803 +[#4801]: https://github.com/nymtech/nym/pull/4801 +[#4796]: https://github.com/nymtech/nym/pull/4796 +[#4783]: https://github.com/nymtech/nym/pull/4783 +[#4778]: https://github.com/nymtech/nym/pull/4778 +[#4771]: https://github.com/nymtech/nym/pull/4771 +[#4766]: https://github.com/nymtech/nym/pull/4766 +[#4765]: https://github.com/nymtech/nym/pull/4765 +[#4763]: https://github.com/nymtech/nym/pull/4763 +[#4759]: https://github.com/nymtech/nym/pull/4759 +[#4756]: https://github.com/nymtech/nym/pull/4756 +[#4754]: https://github.com/nymtech/nym/pull/4754 +[#4751]: https://github.com/nymtech/nym/pull/4751 +[#4725]: https://github.com/nymtech/nym/pull/4725 +[#4610]: https://github.com/nymtech/nym/pull/4610 + ## [2024.10-caramello] (2024-09-10) - Backport 4844 and 4845 ([#4857]) diff --git a/Cargo.lock b/Cargo.lock index 0d6b7e4ea6..3f0dae3857 100644 --- a/Cargo.lock +++ b/Cargo.lock @@ -2224,7 +2224,7 @@ checksum = "0206175f82b8d6bf6652ff7d71a1e27fd2e4efde587fd368662814d6ec1d9ce0" [[package]] name = "explorer-api" -version = "1.1.39" +version = "1.1.40" dependencies = [ "chrono", "clap 4.5.17", @@ -4220,7 +4220,7 @@ checksum = "830b246a0e5f20af87141b25c173cd1b609bd7779a4617d6ec582abaf90870f3" [[package]] name = "nym-api" -version = "1.1.43" +version = "1.1.44" dependencies = [ "anyhow", "async-trait", @@ -4453,7 +4453,7 @@ dependencies = [ [[package]] name = "nym-cli" -version = "1.1.41" +version = "1.1.42" dependencies = [ "anyhow", "base64 0.22.1", @@ -4534,7 +4534,7 @@ dependencies = [ [[package]] name = "nym-client" -version = "1.1.40" +version = "1.1.41" dependencies = [ "bs58", "clap 4.5.17", @@ -5500,7 +5500,7 @@ dependencies = [ [[package]] name = "nym-network-requester" -version = "1.1.41" +version = "1.1.42" dependencies = [ "addr", "anyhow", @@ -5551,7 +5551,7 @@ dependencies = [ [[package]] name = "nym-node" -version = "1.1.7" +version = "1.1.8" dependencies = [ "anyhow", "bip39", @@ -5827,7 +5827,7 @@ dependencies = [ [[package]] name = "nym-socks5-client" -version = "1.1.40" +version = "1.1.41" dependencies = [ "bs58", "clap 4.5.17", @@ -6356,7 +6356,7 @@ dependencies = [ [[package]] name = "nymvisor" -version = "0.1.6" +version = "0.1.7" dependencies = [ "anyhow", "bytes", diff --git a/clients/native/Cargo.toml b/clients/native/Cargo.toml index 7e253719c2..74de15b8a9 100644 --- a/clients/native/Cargo.toml +++ b/clients/native/Cargo.toml @@ -1,6 +1,6 @@ [package] name = "nym-client" -version = "1.1.40" +version = "1.1.41" authors = ["Dave Hrycyszyn ", "Jędrzej Stuczyński "] description = "Implementation of the Nym Client" edition = "2021" diff --git a/clients/socks5/Cargo.toml b/clients/socks5/Cargo.toml index ee15f6747c..7100923a87 100644 --- a/clients/socks5/Cargo.toml +++ b/clients/socks5/Cargo.toml @@ -1,6 +1,6 @@ [package] name = "nym-socks5-client" -version = "1.1.40" +version = "1.1.41" authors = ["Dave Hrycyszyn "] description = "A SOCKS5 localhost proxy that converts incoming messages to Sphinx and sends them to a Nym address" edition = "2021" diff --git a/explorer-api/Cargo.toml b/explorer-api/Cargo.toml index 0ab11f2859..62ff0ad277 100644 --- a/explorer-api/Cargo.toml +++ b/explorer-api/Cargo.toml @@ -1,6 +1,6 @@ [package] name = "explorer-api" -version = "1.1.39" +version = "1.1.40" edition = "2021" license.workspace = true diff --git a/nym-api/Cargo.toml b/nym-api/Cargo.toml index 4b2f7f776e..6f23a04747 100644 --- a/nym-api/Cargo.toml +++ b/nym-api/Cargo.toml @@ -4,7 +4,7 @@ [package] name = "nym-api" license = "GPL-3.0" -version = "1.1.43" +version = "1.1.44" authors = [ "Dave Hrycyszyn ", "Jędrzej Stuczyński ", diff --git a/nym-node/Cargo.toml b/nym-node/Cargo.toml index f33229d4bb..36af98832e 100644 --- a/nym-node/Cargo.toml +++ b/nym-node/Cargo.toml @@ -3,7 +3,7 @@ [package] name = "nym-node" -version = "1.1.7" +version = "1.1.8" authors.workspace = true repository.workspace = true homepage.workspace = true diff --git a/service-providers/network-requester/Cargo.toml b/service-providers/network-requester/Cargo.toml index e449911693..325debcc48 100644 --- a/service-providers/network-requester/Cargo.toml +++ b/service-providers/network-requester/Cargo.toml @@ -4,7 +4,7 @@ [package] name = "nym-network-requester" license = "GPL-3.0" -version = "1.1.41" +version = "1.1.42" authors.workspace = true edition.workspace = true rust-version = "1.70" diff --git a/tools/nym-cli/Cargo.toml b/tools/nym-cli/Cargo.toml index f930eba02b..8f272430d2 100644 --- a/tools/nym-cli/Cargo.toml +++ b/tools/nym-cli/Cargo.toml @@ -1,6 +1,6 @@ [package] name = "nym-cli" -version = "1.1.41" +version = "1.1.42" authors.workspace = true edition = "2021" license.workspace = true diff --git a/tools/nymvisor/Cargo.toml b/tools/nymvisor/Cargo.toml index 6fb6a36e5e..f82494c850 100644 --- a/tools/nymvisor/Cargo.toml +++ b/tools/nymvisor/Cargo.toml @@ -1,6 +1,6 @@ [package] name = "nymvisor" -version = "0.1.6" +version = "0.1.7" authors.workspace = true repository.workspace = true homepage.workspace = true