From ddd84295c410cbbbf6ad472b253fff5410eb86d9 Mon Sep 17 00:00:00 2001 From: gala1234 Date: Wed, 25 May 2022 10:11:36 +0200 Subject: [PATCH 01/25] remove layer column --- explorer/src/pages/Mixnodes/index.tsx | 17 ----------------- 1 file changed, 17 deletions(-) diff --git a/explorer/src/pages/Mixnodes/index.tsx b/explorer/src/pages/Mixnodes/index.tsx index 49919b00d0..4611f9d688 100644 --- a/explorer/src/pages/Mixnodes/index.tsx +++ b/explorer/src/pages/Mixnodes/index.tsx @@ -197,23 +197,6 @@ export const PageMixnodes: React.FC = () => { ), }, - { - field: 'layer', - headerName: 'Layer', - renderHeader: () => , - headerClassName: 'MuiDataGrid-header-override', - width: 110, - headerAlign: 'left', - renderCell: (params: GridRenderCellParams) => ( - - {params.value} - - ), - }, { field: 'profit_percentage', headerName: 'Profit Margin', From e9280f2c17ebf8fc1708f281865eb6bd4bf06ddd Mon Sep 17 00:00:00 2001 From: gala1234 Date: Wed, 25 May 2022 10:45:08 +0200 Subject: [PATCH 02/25] swap bond to stake and pledge to bond --- explorer/src/components/MixNodes/BondBreakdown.tsx | 6 +++--- explorer/src/pages/MixnodeDetail/index.tsx | 4 ++-- 2 files changed, 5 insertions(+), 5 deletions(-) diff --git a/explorer/src/components/MixNodes/BondBreakdown.tsx b/explorer/src/components/MixNodes/BondBreakdown.tsx index 7ebcea0f5f..0dd13d96fd 100644 --- a/explorer/src/components/MixNodes/BondBreakdown.tsx +++ b/explorer/src/components/MixNodes/BondBreakdown.tsx @@ -91,14 +91,14 @@ export const BondBreakdownTable: React.FC = () => { }} align="left" > - Bond total + Stake total {bonds.bondsTotal} - Self + Bond Total {bonds.pledges} @@ -187,7 +187,7 @@ export const BondBreakdownTable: React.FC = () => { }} align="left" > - Share from bond + Share from stake diff --git a/explorer/src/pages/MixnodeDetail/index.tsx b/explorer/src/pages/MixnodeDetail/index.tsx index 50cba3c790..e933cb6adb 100644 --- a/explorer/src/pages/MixnodeDetail/index.tsx +++ b/explorer/src/pages/MixnodeDetail/index.tsx @@ -29,7 +29,7 @@ const columns: ColumnsType[] = [ { field: 'bond', - title: 'Bond', + title: 'Stake', flex: 1, headerAlign: 'left', }, @@ -95,7 +95,7 @@ const PageMixnodeDetailWithState: React.FC = () => { - + From 780c6041efa9090c89c0dbeb53ddef7de9ce5e0c Mon Sep 17 00:00:00 2001 From: gala1234 Date: Wed, 25 May 2022 14:09:09 +0200 Subject: [PATCH 03/25] bond, stake and pledge re-wording --- explorer/src/components/MixNodes/BondBreakdown.tsx | 6 +++--- explorer/src/pages/Mixnodes/index.tsx | 4 ++-- 2 files changed, 5 insertions(+), 5 deletions(-) diff --git a/explorer/src/components/MixNodes/BondBreakdown.tsx b/explorer/src/components/MixNodes/BondBreakdown.tsx index 0dd13d96fd..0152db5745 100644 --- a/explorer/src/components/MixNodes/BondBreakdown.tsx +++ b/explorer/src/components/MixNodes/BondBreakdown.tsx @@ -98,7 +98,7 @@ export const BondBreakdownTable: React.FC = () => { - Bond Total + Bond {bonds.pledges} @@ -177,7 +177,7 @@ export const BondBreakdownTable: React.FC = () => { }} align="left" > - Stake + Amount { }} align="left" > - Share from stake + Share of stake diff --git a/explorer/src/pages/Mixnodes/index.tsx b/explorer/src/pages/Mixnodes/index.tsx index 4611f9d688..e051af98ed 100644 --- a/explorer/src/pages/Mixnodes/index.tsx +++ b/explorer/src/pages/Mixnodes/index.tsx @@ -127,8 +127,8 @@ export const PageMixnodes: React.FC = () => { }, { field: 'bond', - headerName: 'Bond', - renderHeader: () => , + headerName: 'Stake', + renderHeader: () => , type: 'number', headerClassName: 'MuiDataGrid-header-override', width: 200, From 1ee1d4ebf7cb417ce40623defeea197fbd655498 Mon Sep 17 00:00:00 2001 From: gala1234 Date: Thu, 26 May 2022 11:32:57 +0200 Subject: [PATCH 04/25] explorer: altering api response to make ui work --- explorer/src/api/index.ts | 21 +++++++++++++++++---- explorer/src/components/MixNodes/index.ts | 2 ++ explorer/src/pages/Mixnodes/index.tsx | 17 +++++++++++++++++ explorer/src/typeDefs/explorer-api.ts | 1 + 4 files changed, 37 insertions(+), 4 deletions(-) diff --git a/explorer/src/api/index.ts b/explorer/src/api/index.ts index 8c0c087f46..49490d1d25 100644 --- a/explorer/src/api/index.ts +++ b/explorer/src/api/index.ts @@ -60,8 +60,15 @@ export class Api { } const res = await fetch(MIXNODES_API); const json = await res.json(); - storeInCache('mixnodes', JSON.stringify(json)); - return json; + // TODO remove hard coded API response + const nodeArr = json.map((element: MixNodeResponseItem) => { + const node = element; + node.delegators_number = 2; + return node; + }); + + storeInCache('mixnodes', JSON.stringify(nodeArr)); + return nodeArr; }; static fetchMixnodesActiveSetByStatus = async (status: MixnodeStatus): Promise => { @@ -71,8 +78,14 @@ export class Api { } const res = await fetch(`${MIXNODES_API}/active-set/${status}`); const json = await res.json(); - storeInCache(`mixnodes-${status}`, JSON.stringify(json)); - return json; + // TODO remove hard coded API response + const nodeArr = json.map((element: MixNodeResponseItem) => { + const node = element; + node.delegators_number = 2; + return node; + }); + storeInCache(`mixnodes-${status}`, JSON.stringify(nodeArr)); + return nodeArr; }; static fetchMixnodeByID = async (id: string): Promise => { diff --git a/explorer/src/components/MixNodes/index.ts b/explorer/src/components/MixNodes/index.ts index b9e696e785..26413c6fbc 100644 --- a/explorer/src/components/MixNodes/index.ts +++ b/explorer/src/components/MixNodes/index.ts @@ -13,6 +13,7 @@ export type MixnodeRowType = { layer: string; profit_percentage: string; avg_uptime: string; + delegators_number: number; }; export function mixnodeToGridRow(arrayOfMixnodes?: MixNodeResponse): MixnodeRowType[] { @@ -37,5 +38,6 @@ export function mixNodeResponseItemToMixnodeRowType(item: MixNodeResponseItem): layer: item?.layer || '', profit_percentage: `${profitPercentage}%`, avg_uptime: `${item.avg_uptime}%` || '-', + delegators_number: Number(item.delegators_number) || 0, }; } diff --git a/explorer/src/pages/Mixnodes/index.tsx b/explorer/src/pages/Mixnodes/index.tsx index e051af98ed..d9e48db259 100644 --- a/explorer/src/pages/Mixnodes/index.tsx +++ b/explorer/src/pages/Mixnodes/index.tsx @@ -231,6 +231,23 @@ export const PageMixnodes: React.FC = () => { ), }, + { + field: 'delegators_number', + headerName: 'Delegators Number', + renderHeader: () => , + headerClassName: 'MuiDataGrid-header-override', + width: 185, + headerAlign: 'left', + renderCell: (params: GridRenderCellParams) => ( + + {params.value} + + ), + }, ]; const handlePageSize = (event: SelectChangeEvent) => { diff --git a/explorer/src/typeDefs/explorer-api.ts b/explorer/src/typeDefs/explorer-api.ts index 36dd210181..9bc05c5988 100644 --- a/explorer/src/typeDefs/explorer-api.ts +++ b/explorer/src/typeDefs/explorer-api.ts @@ -84,6 +84,7 @@ export interface MixNodeResponseItem { }; mix_node: MixNode; avg_uptime: number; + delegators_number: number; } export type MixNodeResponse = MixNodeResponseItem[]; From c65c1ef7cbe622b809c6e9f8dfa9acfc51cd8f99 Mon Sep 17 00:00:00 2001 From: gala1234 Date: Mon, 30 May 2022 13:03:25 +0200 Subject: [PATCH 05/25] re-organising node list columns and validators column name change --- explorer/src/pages/Mixnodes/index.tsx | 80 +++++++++++++-------------- 1 file changed, 40 insertions(+), 40 deletions(-) diff --git a/explorer/src/pages/Mixnodes/index.tsx b/explorer/src/pages/Mixnodes/index.tsx index d9e48db259..a888275ff2 100644 --- a/explorer/src/pages/Mixnodes/index.tsx +++ b/explorer/src/pages/Mixnodes/index.tsx @@ -125,24 +125,6 @@ export const PageMixnodes: React.FC = () => { ), }, - { - field: 'bond', - headerName: 'Stake', - renderHeader: () => , - type: 'number', - headerClassName: 'MuiDataGrid-header-override', - width: 200, - headerAlign: 'left', - renderCell: (params: GridRenderCellParams) => ( - - {currencyToString(params.value)} - - ), - }, { field: 'location', headerName: 'Location', @@ -162,6 +144,41 @@ export const PageMixnodes: React.FC = () => { ), }, + { + field: 'host', + headerName: 'Host', + renderHeader: () => , + headerClassName: 'MuiDataGrid-header-override', + width: 130, + headerAlign: 'left', + renderCell: (params: GridRenderCellParams) => ( + + {params.value} + + ), + }, + { + field: 'bond', + headerName: 'Stake', + renderHeader: () => , + type: 'number', + headerClassName: 'MuiDataGrid-header-override', + width: 200, + headerAlign: 'left', + renderCell: (params: GridRenderCellParams) => ( + + {currencyToString(params.value)} + + ), + }, { field: 'self_percentage', headerName: 'Self %', @@ -181,15 +198,15 @@ export const PageMixnodes: React.FC = () => { ), }, { - field: 'host', - headerName: 'Host', - renderHeader: () => , + field: 'delegators_number', + headerName: 'Delegators', + renderHeader: () => , headerClassName: 'MuiDataGrid-header-override', - width: 130, + width: 185, headerAlign: 'left', renderCell: (params: GridRenderCellParams) => ( @@ -231,23 +248,6 @@ export const PageMixnodes: React.FC = () => { ), }, - { - field: 'delegators_number', - headerName: 'Delegators Number', - renderHeader: () => , - headerClassName: 'MuiDataGrid-header-override', - width: 185, - headerAlign: 'left', - renderCell: (params: GridRenderCellParams) => ( - - {params.value} - - ), - }, ]; const handlePageSize = (event: SelectChangeEvent) => { From a6a5ffce68193dfcf4595b6c2a008b4a3318a497 Mon Sep 17 00:00:00 2001 From: gala1234 Date: Wed, 1 Jun 2022 14:18:20 +0200 Subject: [PATCH 06/25] explorer: implement SummedDelegations endpoint and display value on frontend --- explorer/src/api/index.ts | 4 ++++ explorer/src/components/MixNodes/BondBreakdown.tsx | 6 +++--- explorer/src/context/mixnode.tsx | 12 ++++++++++++ explorer/src/typeDefs/explorer-api.ts | 7 +++++++ 4 files changed, 26 insertions(+), 3 deletions(-) diff --git a/explorer/src/api/index.ts b/explorer/src/api/index.ts index 8c0c087f46..5a9b40ef9a 100644 --- a/explorer/src/api/index.ts +++ b/explorer/src/api/index.ts @@ -13,6 +13,7 @@ import { import { CountryDataResponse, DelegationsResponse, + UniqDelegationsResponse, GatewayResponse, MixNodeDescriptionResponse, MixNodeResponse, @@ -117,6 +118,9 @@ export class Api { static fetchDelegationsById = async (id: string): Promise => (await fetch(`${MIXNODE_API}/${id}/delegations`)).json(); + static fetchUniqDelegationsById = async (id: string): Promise => + (await fetch(`${MIXNODE_API}/${id}/delegations/summed`)).json(); + static fetchStatsById = async (id: string): Promise => (await fetch(`${MIXNODE_API}/${id}/stats`)).json(); diff --git a/explorer/src/components/MixNodes/BondBreakdown.tsx b/explorer/src/components/MixNodes/BondBreakdown.tsx index 7ebcea0f5f..a8fb791e8d 100644 --- a/explorer/src/components/MixNodes/BondBreakdown.tsx +++ b/explorer/src/components/MixNodes/BondBreakdown.tsx @@ -13,7 +13,7 @@ import { currencyToString } from '../../utils/currency'; import { useMixnodeContext } from '../../context/mixnode'; export const BondBreakdownTable: React.FC = () => { - const { mixNode, delegations } = useMixnodeContext(); + const { mixNode, delegations, uniqDelegations } = useMixnodeContext(); const [showDelegations, toggleShowDelegations] = React.useState(false); const [bonds, setBonds] = React.useState({ @@ -155,7 +155,7 @@ export const BondBreakdownTable: React.FC = () => { fontWeight: 400, }} > - {`(${delegations?.data?.length} delegators)`} + {`(${uniqDelegations?.data?.length} delegators)`} @@ -193,7 +193,7 @@ export const BondBreakdownTable: React.FC = () => { - {delegations?.data?.map(({ owner, amount: { amount, denom } }) => ( + {uniqDelegations?.data?.map(({ owner, amount: { amount, denom } }) => ( {owner} diff --git a/explorer/src/context/mixnode.tsx b/explorer/src/context/mixnode.tsx index c84ee60517..6259b8c00d 100644 --- a/explorer/src/context/mixnode.tsx +++ b/explorer/src/context/mixnode.tsx @@ -2,6 +2,7 @@ import * as React from 'react'; import { ApiState, DelegationsResponse, + UniqDelegationsResponse, MixNodeDescriptionResponse, MixNodeEconomicDynamicsStatsResponse, MixNodeResponseItem, @@ -18,6 +19,7 @@ import { mixNodeResponseItemToMixnodeRowType, MixnodeRowType } from '../componen interface MixnodeState { delegations?: ApiState; + uniqDelegations?: ApiState; description?: ApiState; economicDynamicsStats?: ApiState; mixNode?: ApiState; @@ -55,6 +57,12 @@ export const MixnodeContextProvider: React.FC = ({ 'Failed to fetch delegations for mixnode', ); + const [uniqDelegations, fetchUniqDelegations, clearUniqDelegations] = useApiState( + mixNodeIdentityKey, + Api.fetchUniqDelegationsById, + 'Failed to fetch delegations for mixnode', + ); + const [status, fetchStatus, clearStatus] = useApiState( mixNodeIdentityKey, Api.fetchStatusById, @@ -90,6 +98,7 @@ export const MixnodeContextProvider: React.FC = ({ // when the identity key changes, remove all previous data clearMixnodeById(); clearDelegations(); + clearUniqDelegations(); clearStatus(); clearStats(); clearDescription(); @@ -105,6 +114,7 @@ export const MixnodeContextProvider: React.FC = ({ setMixnodeRow(mixNodeResponseItemToMixnodeRowType(value.data)); Promise.all([ fetchDelegations(), + fetchUniqDelegations(), fetchStatus(), fetchStats(), fetchDescription(), @@ -117,6 +127,7 @@ export const MixnodeContextProvider: React.FC = ({ const state = React.useMemo( () => ({ delegations, + uniqDelegations, mixNode, mixNodeRow, description, @@ -128,6 +139,7 @@ export const MixnodeContextProvider: React.FC = ({ [ { delegations, + uniqDelegations, mixNode, mixNodeRow, description, diff --git a/explorer/src/typeDefs/explorer-api.ts b/explorer/src/typeDefs/explorer-api.ts index 36dd210181..944e04fc89 100644 --- a/explorer/src/typeDefs/explorer-api.ts +++ b/explorer/src/typeDefs/explorer-api.ts @@ -170,8 +170,15 @@ export type Delegation = { block_height: number; }; +export type DelegationUniq = { + owner: string; + amount: Amount; +}; + export type DelegationsResponse = Delegation[]; +export type UniqDelegationsResponse = DelegationUniq[]; + export interface CountryDataResponse { [threeLetterCountryCode: string]: CountryData; } From 1bdaab6c9713eba67ce712ca3efccc4152253372 Mon Sep 17 00:00:00 2001 From: durch Date: Mon, 6 Jun 2022 14:17:59 +0200 Subject: [PATCH 07/25] Fix underflow in rewards estimation --- common/cosmwasm-smart-contracts/mixnet-contract/src/mixnode.rs | 2 +- 1 file changed, 1 insertion(+), 1 deletion(-) diff --git a/common/cosmwasm-smart-contracts/mixnet-contract/src/mixnode.rs b/common/cosmwasm-smart-contracts/mixnet-contract/src/mixnode.rs index 4325727195..b8622e0f11 100644 --- a/common/cosmwasm-smart-contracts/mixnet-contract/src/mixnode.rs +++ b/common/cosmwasm-smart-contracts/mixnet-contract/src/mixnode.rs @@ -458,7 +458,7 @@ impl MixNodeBond { .unwrap_or_default(); let operator_reward = self.operator_reward(params); // Total reward has to be the sum of operator and delegator rewards - let delegators_reward = node_profit - operator_reward; + let delegators_reward = node_profit.saturating_sub(operator_reward); Ok(RewardEstimate { total_node_reward: total_node_reward.try_into()?, From 459db5718ec2cccf6d60de6a9cbbc78975d7e3a9 Mon Sep 17 00:00:00 2001 From: Drazen Urch Date: Mon, 6 Jun 2022 14:19:24 +0200 Subject: [PATCH 08/25] Set probability to 1 if less nodes then the limit (#1306) * Set probability to 1 if less nodes then the limit * Check both sets independantly --- validator-api/src/node_status_api/routes.rs | 15 +++++++++++---- 1 file changed, 11 insertions(+), 4 deletions(-) diff --git a/validator-api/src/node_status_api/routes.rs b/validator-api/src/node_status_api/routes.rs index 22ccbee404..f82206e32b 100644 --- a/validator-api/src/node_status_api/routes.rs +++ b/validator-api/src/node_status_api/routes.rs @@ -211,6 +211,7 @@ pub(crate) async fn get_mixnode_inclusion_probability( identity: String, ) -> Json> { let mixnodes = cache.mixnodes().await; + let rewarding_params = cache.epoch_reward_params().await.into_inner(); if let Some(target_mixnode) = mixnodes.iter().find(|x| x.identity() == &identity) { let total_bonded_tokens = mixnodes @@ -218,17 +219,23 @@ pub(crate) async fn get_mixnode_inclusion_probability( .fold(0u128, |acc, x| acc + x.total_bond().unwrap_or_default()) as f64; - let rewarding_params = cache.epoch_reward_params().await.into_inner(); let rewarded_set_size = rewarding_params.rewarded_set_size() as f64; let active_set_size = rewarding_params.active_set_size() as f64; let prob_one_draw = target_mixnode.total_bond().unwrap_or_default() as f64 / total_bonded_tokens; // Chance to be selected in any draw for active set - let prob_active_set = active_set_size * prob_one_draw; + let prob_active_set = if mixnodes.len() <= active_set_size as usize { + 1.0 + } else { + active_set_size * prob_one_draw + }; // This is likely slightly too high, as we're not correcting form them not being selected in active, should be chance to be selected, minus the chance for being not selected in reserve - let prob_reserve_set = (rewarded_set_size - active_set_size) * prob_one_draw; - // (rewarded_set_size - active_set_size) * prob_one_draw * (1. - prob_active_set); + let prob_reserve_set = if mixnodes.len() <= rewarded_set_size as usize { + 1.0 + } else { + (rewarded_set_size - active_set_size) * prob_one_draw + }; Json(Some(InclusionProbabilityResponse { in_active: prob_active_set.into(), From 27a4a447175e3aa2f7885d857866f177e50b2b44 Mon Sep 17 00:00:00 2001 From: Drazen Urch Date: Mon, 6 Jun 2022 14:19:36 +0200 Subject: [PATCH 09/25] Claim and compound reward wallet endpoints (#1302) * Add claim and compound wallet endpoints, proc_macro to generate execute and simulate * CHANGELOG * Sort CHANGELOG lines * PR comments --- CHANGELOG.md | 30 +++-- Cargo.lock | 9 ++ Cargo.toml | 1 + .../client-libs/validator-client/Cargo.toml | 1 + .../validator-client/src/nymd/mod.rs | 122 ++++++++++-------- .../src/nymd/traits/vesting_signing_client.rs | 96 -------------- common/execute/Cargo.toml | 11 ++ common/execute/src/lib.rs | 110 ++++++++++++++++ nym-wallet/Cargo.lock | 9 ++ nym-wallet/src-tauri/src/main.rs | 16 +++ .../src-tauri/src/operations/mixnet/mod.rs | 1 + .../src/operations/mixnet/rewards.rs | 53 ++++++++ .../src/operations/simulate/mixnet.rs | 48 +++++++ .../src/operations/simulate/vesting.rs | 48 +++++++ .../src-tauri/src/operations/vesting/mod.rs | 1 + .../src/operations/vesting/rewards.rs | 52 ++++++++ 16 files changed, 441 insertions(+), 167 deletions(-) create mode 100644 common/execute/Cargo.toml create mode 100644 common/execute/src/lib.rs create mode 100644 nym-wallet/src-tauri/src/operations/mixnet/rewards.rs create mode 100644 nym-wallet/src-tauri/src/operations/vesting/rewards.rs diff --git a/CHANGELOG.md b/CHANGELOG.md index 50dc0d6fdb..f9c3f58406 100644 --- a/CHANGELOG.md +++ b/CHANGELOG.md @@ -4,40 +4,41 @@ ### Added +- all: added network compilation target to `--help` (or `--version`) commands ([#1256]). - explorer-api: learned how to sum the delegations by owner in a new endpoint. +- gateway: Added gateway coconut verifications and validator-api communication for double spending protection ([#1261]) +- mixnet-contract: Added ClaimOperatorReward and ClaimDelegatorReward messages ([#1292]) +- mixnet-contract: Replace all naked `-` with `saturating_sub`. +- network-requester: send traffic statistics from all network requesters and receive it in a special network-requester that aggregates the data and exposes it via a rest API ([#1267], [#1278]). +- validator-api: add `estimated_node_profit` and `estimated_operator_cost` to `reward-estimate` endpoint ([#1284]) - validator-api: add detailed mixnode bond endpoints, and explorer-api makes use of that data to append stake saturation. -- wallet: require password to switch accounts +- validator-api: add Swagger to document the REST API ([#1249]). +- validator-api: Added new endpoints for coconut spending flow and communications with coconut & multisig contracts ([#1261]) +- vesting-contract: Added ClaimOperatorReward and ClaimDelegatorReward messages ([#1292]) - wallet: add simple CLI tool for decrypting and recovering the wallet file. - wallet: added support for multiple accounts ([#1265]) +- wallet: compound and claim reward endpoints for operators and delegators ([#1302]) +- wallet: require password to switch accounts - wallet: the wallet backend learned how to keep track of validator name, either hardcoded or by querying the status endpoint. -- mixnet-contract: Replace all naked `-` with `saturating_sub`. -- mixnet-contract: Added ClaimOperatorReward and ClaimDelegatorReward messages ([#1292]) -- vesting-contract: Added ClaimOperatorReward and ClaimDelegatorReward messages ([#1292]) -- validator-api: add Swagger to document the REST API ([#1249]). -- validator-api: add `estimated_node_profit` and `estimated_operator_cost` to `reward-estimate` endpoint ([#1284]) -- all: added network compilation target to `--help` (or `--version`) commands ([#1256]). -- network-requester: send traffic statistics from all network requesters and receive it in a special network-requester that aggregates the data and exposes it via a rest API ([#1267], [#1278]). -- gateway: Added gateway coconut verifications and validator-api communication for double spending protection ([#1261]) -- validator-api: Added new endpoints for coconut spending flow and communications with coconut & multisig contracts ([#1261]) ### Fixed -- mixnet-contract: replaced integer division with fixed for performance calculations ([#1284]) -- mixnet-contract: delegator and operator rewards use lambda and sigma instead of lambda_ticked and sigma_ticked ([#1284]) - mixnet-contract: `estimated_delegator_reward` calculation ([#1284]) -- vesting-contract: replaced `checked_sub` with `saturating_sub` to fix the underflow in `get_vesting_tokens` ([#1275]) +- mixnet-contract: delegator and operator rewards use lambda and sigma instead of lambda_ticked and sigma_ticked ([#1284]) - mixnet-contract: removed `expect` in `query_delegator_reward` and queries containing invalid proxy address should now return a more human-readable error ([#1257]) +- mixnet-contract: replaced integer division with fixed for performance calculations ([#1284]) - mixnet-contract: Under certain circumstances nodes could not be unbonded ([#1255](https://github.com/nymtech/nym/issues/1255)) ([#1258]) - mixnode, gateway: attempting to determine reconnection backoff to persistently failing mixnode could result in a crash ([#1260]) +- vesting-contract: replaced `checked_sub` with `saturating_sub` to fix the underflow in `get_vesting_tokens` ([#1275]) ### Changed - validator-client: created internal `Coin` type that replaces coins from `cosmrs` and `cosmwasm` for API entrypoints [[#1295]] -[#1258]: https://github.com/nymtech/nym/pull/1258 [#1249]: https://github.com/nymtech/nym/pull/1249 [#1256]: https://github.com/nymtech/nym/pull/1256 [#1257]: https://github.com/nymtech/nym/pull/1257 +[#1258]: https://github.com/nymtech/nym/pull/1258 [#1260]: https://github.com/nymtech/nym/pull/1260 [#1261]: https://github.com/nymtech/nym/pull/1261 [#1265]: https://github.com/nymtech/nym/pull/1265 @@ -47,6 +48,7 @@ [#1284]: https://github.com/nymtech/nym/pull/1284 [#1292]: https://github.com/nymtech/nym/pull/1292 [#1295]: https://github.com/nymtech/nym/pull/1295 +[#1302]: https://github.com/nymtech/nym/pull/1302 ## [nym-wallet-v1.0.4](https://github.com/nymtech/nym/tree/nym-wallet-v1.0.4) (2022-05-04) diff --git a/Cargo.lock b/Cargo.lock index 5df601a7b7..26e5c5b3f9 100644 --- a/Cargo.lock +++ b/Cargo.lock @@ -1602,6 +1602,14 @@ dependencies = [ "uint", ] +[[package]] +name = "execute" +version = "0.1.0" +dependencies = [ + "quote", + "syn", +] + [[package]] name = "explorer-api" version = "1.0.1" @@ -6257,6 +6265,7 @@ dependencies = [ "cosmrs", "cosmwasm-std", "cw3", + "execute", "flate2", "futures", "itertools", diff --git a/Cargo.toml b/Cargo.toml index 131fd2dbb4..1f36d4b26e 100644 --- a/Cargo.toml +++ b/Cargo.toml @@ -31,6 +31,7 @@ members = [ "common/credentials", "common/crypto", "common/crypto/dkg", + "common/execute", "common/bandwidth-claim-contract", "common/cosmwasm-smart-contracts/coconut-bandwidth-contract", "common/cosmwasm-smart-contracts/contracts-common", diff --git a/common/client-libs/validator-client/Cargo.toml b/common/client-libs/validator-client/Cargo.toml index 560dcb4788..6c9fa9faf5 100644 --- a/common/client-libs/validator-client/Cargo.toml +++ b/common/client-libs/validator-client/Cargo.toml @@ -41,6 +41,7 @@ flate2 = { version = "1.0.20", optional = true } sha2 = { version = "0.9.5", optional = true } itertools = { version = "0.10", optional = true } cosmwasm-std = { version = "1.0.0-beta8", optional = true } +execute = { path = "../../execute" } [dev-dependencies] ts-rs = "6.1.2" diff --git a/common/client-libs/validator-client/src/nymd/mod.rs b/common/client-libs/validator-client/src/nymd/mod.rs index 1851ce155d..e680a57e6a 100644 --- a/common/client-libs/validator-client/src/nymd/mod.rs +++ b/common/client-libs/validator-client/src/nymd/mod.rs @@ -14,6 +14,7 @@ use cosmrs::rpc::Error as TendermintRpcError; use cosmrs::rpc::HttpClientUrl; use cosmrs::tx::Msg; use cosmwasm_std::Uint128; +use execute::execute; pub use fee::gas_price::GasPrice; use mixnet_contract_common::mixnode::DelegationEvent; use mixnet_contract_common::{ @@ -26,6 +27,7 @@ use mixnet_contract_common::{ use network_defaults::DEFAULT_NETWORK; use serde::Serialize; use std::convert::TryInto; +use vesting_contract_common::ExecuteMsg as VestingExecuteMsg; pub use crate::nymd::cosmwasm_client::client::CosmWasmClient; pub use crate::nymd::cosmwasm_client::signing_client::SigningCosmWasmClient; @@ -848,87 +850,93 @@ impl NymdClient { .await } - pub async fn compound_operator_reward( - &self, - fee: Option, - ) -> Result + #[execute("mixnet")] + fn _compound_operator_reward(&self, fee: Option) -> (ExecuteMsg, Option) where C: SigningCosmWasmClient + Sync, { - let fee = fee.unwrap_or(Fee::Auto(Some(self.simulated_gas_multiplier))); - let req = ExecuteMsg::CompoundOperatorReward {}; - self.client - .execute( - self.address(), - self.mixnet_contract_address(), - &req, - fee, - "MixnetContract::CompoundOperatorReward", - vec![], - ) - .await + (ExecuteMsg::CompoundOperatorReward {}, fee) } - pub async fn claim_operator_reward(&self, fee: Option) -> Result + #[execute("mixnet")] + fn _claim_operator_reward(&self, fee: Option) -> (ExecuteMsg, Option) where C: SigningCosmWasmClient + Sync, { - let fee = fee.unwrap_or(Fee::Auto(Some(self.simulated_gas_multiplier))); - let req = ExecuteMsg::ClaimOperatorReward {}; - self.client - .execute( - self.address(), - self.mixnet_contract_address(), - &req, - fee, - "MixnetContract::ClaimOperatorReward", - vec![], - ) - .await + (ExecuteMsg::ClaimOperatorReward {}, fee) } - pub async fn compound_delegator_reward( + #[execute("mixnet")] + fn _compound_delegator_reward( &self, mix_identity: IdentityKey, fee: Option, - ) -> Result + ) -> (ExecuteMsg, Option) where C: SigningCosmWasmClient + Sync, { - let fee = fee.unwrap_or(Fee::Auto(Some(self.simulated_gas_multiplier))); - let req = ExecuteMsg::CompoundDelegatorReward { mix_identity }; - self.client - .execute( - self.address(), - self.mixnet_contract_address(), - &req, - fee, - "MixnetContract::CompoundDelegatorReward", - vec![], - ) - .await + (ExecuteMsg::CompoundDelegatorReward { mix_identity }, fee) } - pub async fn claim_delegator_reward( + #[execute("mixnet")] + fn _claim_delegator_reward( &self, mix_identity: IdentityKey, fee: Option, - ) -> Result + ) -> (ExecuteMsg, Option) where C: SigningCosmWasmClient + Sync, { - let fee = fee.unwrap_or(Fee::Auto(Some(self.simulated_gas_multiplier))); - let req = ExecuteMsg::ClaimDelegatorReward { mix_identity }; - self.client - .execute( - self.address(), - self.mixnet_contract_address(), - &req, - fee, - "MixnetContract::ClaimDelegatorReward", - vec![], - ) - .await + (ExecuteMsg::ClaimDelegatorReward { mix_identity }, fee) + } + + #[execute("vesting")] + fn _vesting_compound_delegator_reward( + &self, + mix_identity: IdentityKey, + fee: Option, + ) -> (VestingExecuteMsg, Option) + where + C: SigningCosmWasmClient + Sync, + { + ( + VestingExecuteMsg::CompoundDelegatorReward { mix_identity }, + fee, + ) + } + + #[execute("vesting")] + fn _vesting_claim_operator_reward(&self, fee: Option) -> (VestingExecuteMsg, Option) + where + C: SigningCosmWasmClient + Sync, + { + (VestingExecuteMsg::ClaimOperatorReward {}, fee) + } + + #[execute("vesting")] + fn _vesting_compound_operator_reward( + &self, + fee: Option, + ) -> (VestingExecuteMsg, Option) + where + C: SigningCosmWasmClient + Sync, + { + (VestingExecuteMsg::CompoundOperatorReward {}, fee) + } + + #[execute("vesting")] + fn _vesting_claim_delegator_reward( + &self, + mix_identity: IdentityKey, + fee: Option, + ) -> (VestingExecuteMsg, Option) + where + C: SigningCosmWasmClient + Sync, + { + ( + VestingExecuteMsg::ClaimDelegatorReward { mix_identity }, + fee, + ) } /// Announce a mixnode, paying a fee. diff --git a/common/client-libs/validator-client/src/nymd/traits/vesting_signing_client.rs b/common/client-libs/validator-client/src/nymd/traits/vesting_signing_client.rs index e24473e81d..957a02e3e1 100644 --- a/common/client-libs/validator-client/src/nymd/traits/vesting_signing_client.rs +++ b/common/client-libs/validator-client/src/nymd/traits/vesting_signing_client.rs @@ -11,28 +11,6 @@ use vesting_contract_common::messages::{ExecuteMsg as VestingExecuteMsg, Vesting #[async_trait] pub trait VestingSigningClient { - async fn vesting_claim_operator_reward( - &self, - fee: Option, - ) -> Result; - - async fn vesting_claim_delegator_reward( - &self, - mix_identity: IdentityKey, - fee: Option, - ) -> Result; - - async fn vesting_compound_operator_reward( - &self, - fee: Option, - ) -> Result; - - async fn vesting_compound_delegator_reward( - &self, - mix_identity: IdentityKey, - fee: Option, - ) -> Result; - async fn vesting_update_mixnode_config( &self, profix_margin_percent: u8, @@ -397,78 +375,4 @@ impl VestingSigningClient for NymdClient ) .await } - - async fn vesting_claim_operator_reward( - &self, - fee: Option, - ) -> Result { - let fee = fee.unwrap_or(Fee::Auto(Some(self.simulated_gas_multiplier))); - let req = VestingExecuteMsg::ClaimOperatorReward {}; - self.client - .execute( - self.address(), - self.vesting_contract_address(), - &req, - fee, - "VestingContract::ClaimOperatorReward", - vec![], - ) - .await - } - - async fn vesting_compound_operator_reward( - &self, - fee: Option, - ) -> Result { - let fee = fee.unwrap_or(Fee::Auto(Some(self.simulated_gas_multiplier))); - let req = VestingExecuteMsg::CompoundOperatorReward {}; - self.client - .execute( - self.address(), - self.vesting_contract_address(), - &req, - fee, - "VestingContract::CompoundOperatorReward", - vec![], - ) - .await - } - - async fn vesting_claim_delegator_reward( - &self, - mix_identity: IdentityKey, - fee: Option, - ) -> Result { - let fee = fee.unwrap_or(Fee::Auto(Some(self.simulated_gas_multiplier))); - let req = VestingExecuteMsg::ClaimDelegatorReward { mix_identity }; - self.client - .execute( - self.address(), - self.vesting_contract_address(), - &req, - fee, - "VestingContract::ClaimDelegatorReward", - vec![], - ) - .await - } - - async fn vesting_compound_delegator_reward( - &self, - mix_identity: IdentityKey, - fee: Option, - ) -> Result { - let fee = fee.unwrap_or(Fee::Auto(Some(self.simulated_gas_multiplier))); - let req = VestingExecuteMsg::CompoundDelegatorReward { mix_identity }; - self.client - .execute( - self.address(), - self.vesting_contract_address(), - &req, - fee, - "VestingContract::CompoundDelegatorReward", - vec![], - ) - .await - } } diff --git a/common/execute/Cargo.toml b/common/execute/Cargo.toml new file mode 100644 index 0000000000..551f1728fb --- /dev/null +++ b/common/execute/Cargo.toml @@ -0,0 +1,11 @@ +[package] +name = "execute" +version = "0.1.0" +edition = "2021" + +[lib] +proc-macro = true + +[dependencies] +syn = { version = "1", features = ["full"] } +quote = "1" diff --git a/common/execute/src/lib.rs b/common/execute/src/lib.rs new file mode 100644 index 0000000000..795a72822d --- /dev/null +++ b/common/execute/src/lib.rs @@ -0,0 +1,110 @@ +use proc_macro::TokenStream; +use quote::quote; +use syn::{ + parse_macro_input, Block, ExprMethodCall, FnArg, Ident, ItemFn, LitStr, ReturnType, Token, + VisPublic, Visibility, +}; + +#[proc_macro_attribute] +pub fn execute(attr: TokenStream, item: TokenStream) -> TokenStream { + let f = parse_macro_input!(item as ItemFn); + let target = parse_macro_input!(attr as LitStr).value(); + + let cl = if target == "mixnet" { + quote! {self.mixnet_contract_address()} + } else if target == "vesting" { + quote! {self.vesting_contract_address()} + } else { + panic!("Only `mixnet` and `vesting` targets are supported!") + }; + let cl = proc_macro::TokenStream::from(cl); + let cl = parse_macro_input!(cl as ExprMethodCall); + + let orig_f = f.clone(); + let mut execute_f = f.clone(); + let mut simulate_f = f.clone(); + let name = f.sig.ident; + let name_str = name.to_string(); + let call_args = f.sig.inputs.into_iter().filter_map(|arg| match arg { + FnArg::Receiver(_) => None, + FnArg::Typed(arg) => Some(arg.pat), + }); + let execute_args = call_args.clone(); + let simulate_args = call_args; + + execute_f.sig.asyncness = Some(Token![async](execute_f.sig.ident.span())); + simulate_f.sig.asyncness = Some(Token![async](simulate_f.sig.ident.span())); + + execute_f.vis = Visibility::Public(VisPublic { + pub_token: Token![pub](execute_f.sig.ident.span()), + }); + simulate_f.vis = Visibility::Public(VisPublic { + pub_token: Token![pub](simulate_f.sig.ident.span()), + }); + + execute_f.sig.ident = Ident::new( + &format!("execute{}", execute_f.sig.ident), + execute_f.sig.ident.span(), + ); + + simulate_f.sig.ident = Ident::new( + &format!("simulate{}", simulate_f.sig.ident), + simulate_f.sig.ident.span(), + ); + + let execute_output = quote! { + -> Result + }; + let o_ts = proc_macro::TokenStream::from(execute_output); + execute_f.sig.output = parse_macro_input!(o_ts as ReturnType); + + let simulate_output = quote! { + -> Result + }; + let o_ts = proc_macro::TokenStream::from(simulate_output); + simulate_f.sig.output = parse_macro_input!(o_ts as ReturnType); + + let simulate_block = quote! { + { + let (msg, _fee) = self.#name(#(#simulate_args),*); + let msg = self.wrap_contract_execute_message( + #cl, + &msg, + vec![], + )?; + + self.simulate(vec![msg]).await + } + }; + + let ts = proc_macro::TokenStream::from(simulate_block); + simulate_f.block = Box::new(parse_macro_input!(ts as Block)); + + let execute_block = quote! { + { + let (req, fee) = self.#name(#(#execute_args),*); + let fee = fee.unwrap_or(Fee::Auto(Some(self.simulated_gas_multiplier))); + self.client + .execute( + self.address(), + #cl, + &req, + fee, + #name_str, + vec![], + ) + .await + } + }; + + let ts = proc_macro::TokenStream::from(execute_block); + execute_f.block = Box::new(parse_macro_input!(ts as Block)); + + let out = quote! { + #orig_f + #execute_f + #simulate_f + }; + + out.into() +} diff --git a/nym-wallet/Cargo.lock b/nym-wallet/Cargo.lock index 72377c7237..074df1422e 100644 --- a/nym-wallet/Cargo.lock +++ b/nym-wallet/Cargo.lock @@ -1537,6 +1537,14 @@ version = "2.5.2" source = "registry+https://github.com/rust-lang/crates.io-index" checksum = "77f3309417938f28bf8228fcff79a4a37103981e3e186d2ccd19c74b38f4eb71" +[[package]] +name = "execute" +version = "0.1.0" +dependencies = [ + "quote", + "syn", +] + [[package]] name = "eyre" version = "0.6.7" @@ -5542,6 +5550,7 @@ dependencies = [ "cosmrs", "cosmwasm-std", "cw3", + "execute", "flate2", "futures", "itertools", diff --git a/nym-wallet/src-tauri/src/main.rs b/nym-wallet/src-tauri/src/main.rs index 9f78cef22b..ddb43f08fc 100644 --- a/nym-wallet/src-tauri/src/main.rs +++ b/nym-wallet/src-tauri/src/main.rs @@ -62,6 +62,10 @@ fn main() { mixnet::delegate::get_reverse_mix_delegations_paged, mixnet::delegate::undelegate_from_mixnode, mixnet::epoch::get_current_epoch, + mixnet::rewards::claim_delegator_reward, + mixnet::rewards::claim_operator_reward, + mixnet::rewards::compound_operator_reward, + mixnet::rewards::compound_delegator_reward, mixnet::send::send, network_config::add_validator, network_config::get_validator_api_urls, @@ -84,6 +88,10 @@ fn main() { validator_api::status::mixnode_reward_estimation, validator_api::status::mixnode_stake_saturation, validator_api::status::mixnode_status, + vesting::rewards::vesting_claim_delegator_reward, + vesting::rewards::vesting_claim_operator_reward, + vesting::rewards::vesting_compound_operator_reward, + vesting::rewards::vesting_compound_delegator_reward, vesting::bond::vesting_bond_gateway, vesting::bond::vesting_bond_mixnode, vesting::bond::vesting_unbond_gateway, @@ -122,6 +130,14 @@ fn main() { simulate::vesting::simulate_vesting_unbond_mixnode, simulate::vesting::simulate_vesting_update_mixnode, simulate::vesting::simulate_withdraw_vested_coins, + simulate::vesting::simulate_vesting_claim_delegator_reward, + simulate::vesting::simulate_vesting_claim_operator_reward, + simulate::vesting::simulate_vesting_compound_operator_reward, + simulate::vesting::simulate_vesting_compound_delegator_reward, + simulate::mixnet::simulate_claim_delegator_reward, + simulate::mixnet::simulate_claim_operator_reward, + simulate::mixnet::simulate_compound_operator_reward, + simulate::mixnet::simulate_compound_delegator_reward, ]) .menu(Menu::new().add_default_app_submenu_if_macos()) .run(tauri::generate_context!()) diff --git a/nym-wallet/src-tauri/src/operations/mixnet/mod.rs b/nym-wallet/src-tauri/src/operations/mixnet/mod.rs index e59890f38e..40ebc405d8 100644 --- a/nym-wallet/src-tauri/src/operations/mixnet/mod.rs +++ b/nym-wallet/src-tauri/src/operations/mixnet/mod.rs @@ -3,4 +3,5 @@ pub mod admin; pub mod bond; pub mod delegate; pub mod epoch; +pub mod rewards; pub mod send; diff --git a/nym-wallet/src-tauri/src/operations/mixnet/rewards.rs b/nym-wallet/src-tauri/src/operations/mixnet/rewards.rs new file mode 100644 index 0000000000..adc4612a34 --- /dev/null +++ b/nym-wallet/src-tauri/src/operations/mixnet/rewards.rs @@ -0,0 +1,53 @@ +use crate::error::BackendError; +use crate::nymd_client; +use crate::state::State; +use mixnet_contract_common::IdentityKey; +use std::sync::Arc; +use tokio::sync::RwLock; +use validator_client::nymd::Fee; + +#[tauri::command] +pub async fn claim_operator_reward( + fee: Option, + state: tauri::State<'_, Arc>>, +) -> Result<(), BackendError> { + nymd_client!(state) + .execute_claim_operator_reward(fee) + .await?; + Ok(()) +} + +#[tauri::command] +pub async fn compound_operator_reward( + fee: Option, + state: tauri::State<'_, Arc>>, +) -> Result<(), BackendError> { + nymd_client!(state) + .execute_compound_operator_reward(fee) + .await?; + Ok(()) +} + +#[tauri::command] +pub async fn claim_delegator_reward( + mix_identity: IdentityKey, + fee: Option, + state: tauri::State<'_, Arc>>, +) -> Result<(), BackendError> { + nymd_client!(state) + .execute_claim_delegator_reward(mix_identity, fee) + .await?; + Ok(()) +} + +#[tauri::command] +pub async fn compound_delegator_reward( + mix_identity: IdentityKey, + fee: Option, + state: tauri::State<'_, Arc>>, +) -> Result<(), BackendError> { + nymd_client!(state) + .execute_compound_delegator_reward(mix_identity, fee) + .await?; + Ok(()) +} diff --git a/nym-wallet/src-tauri/src/operations/simulate/mixnet.rs b/nym-wallet/src-tauri/src/operations/simulate/mixnet.rs index a833f934b1..1e443cd709 100644 --- a/nym-wallet/src-tauri/src/operations/simulate/mixnet.rs +++ b/nym-wallet/src-tauri/src/operations/simulate/mixnet.rs @@ -3,8 +3,10 @@ use crate::coin::Coin; use crate::error::BackendError; +use crate::nymd_client; use crate::simulate::{FeeDetails, SimulateResult}; use crate::State; +use mixnet_contract_common::IdentityKey; use mixnet_contract_common::{ExecuteMsg, Gateway, MixNode}; use std::sync::Arc; use tokio::sync::RwLock; @@ -174,3 +176,49 @@ pub async fn simulate_undelegate_from_mixnode( let result = client.nymd.simulate(vec![msg]).await?; Ok(SimulateResult::new(result.gas_info, gas_price).detailed_fee()) } + +#[tauri::command] +pub async fn simulate_claim_operator_reward( + state: tauri::State<'_, Arc>>, +) -> Result { + let result = nymd_client!(state) + .simulate_claim_operator_reward(None) + .await?; + let gas_price = nymd_client!(state).gas_price().clone(); + Ok(SimulateResult::new(result.gas_info, gas_price).detailed_fee()) +} + +#[tauri::command] +pub async fn simulate_compound_operator_reward( + state: tauri::State<'_, Arc>>, +) -> Result { + let result = nymd_client!(state) + .simulate_compound_operator_reward(None) + .await?; + let gas_price = nymd_client!(state).gas_price().clone(); + Ok(SimulateResult::new(result.gas_info, gas_price).detailed_fee()) +} + +#[tauri::command] +pub async fn simulate_claim_delegator_reward( + mix_identity: IdentityKey, + state: tauri::State<'_, Arc>>, +) -> Result { + let result = nymd_client!(state) + .simulate_claim_delegator_reward(mix_identity, None) + .await?; + let gas_price = nymd_client!(state).gas_price().clone(); + Ok(SimulateResult::new(result.gas_info, gas_price).detailed_fee()) +} + +#[tauri::command] +pub async fn simulate_compound_delegator_reward( + mix_identity: IdentityKey, + state: tauri::State<'_, Arc>>, +) -> Result { + let result = nymd_client!(state) + .simulate_compound_delegator_reward(mix_identity, None) + .await?; + let gas_price = nymd_client!(state).gas_price().clone(); + Ok(SimulateResult::new(result.gas_info, gas_price).detailed_fee()) +} diff --git a/nym-wallet/src-tauri/src/operations/simulate/vesting.rs b/nym-wallet/src-tauri/src/operations/simulate/vesting.rs index fe095c5717..616d58f1e5 100644 --- a/nym-wallet/src-tauri/src/operations/simulate/vesting.rs +++ b/nym-wallet/src-tauri/src/operations/simulate/vesting.rs @@ -3,8 +3,10 @@ use crate::coin::Coin; use crate::error::BackendError; +use crate::nymd_client; use crate::simulate::{FeeDetails, SimulateResult}; use crate::State; +use mixnet_contract_common::IdentityKey; use mixnet_contract_common::{Gateway, MixNode}; use std::sync::Arc; use tokio::sync::RwLock; @@ -152,3 +154,49 @@ pub async fn simulate_withdraw_vested_coins( let result = client.nymd.simulate(vec![msg]).await?; Ok(SimulateResult::new(result.gas_info, gas_price).detailed_fee()) } + +#[tauri::command] +pub async fn simulate_vesting_claim_operator_reward( + state: tauri::State<'_, Arc>>, +) -> Result { + let result = nymd_client!(state) + .simulate_vesting_claim_operator_reward(None) + .await?; + let gas_price = nymd_client!(state).gas_price().clone(); + Ok(SimulateResult::new(result.gas_info, gas_price).detailed_fee()) +} + +#[tauri::command] +pub async fn simulate_vesting_compound_operator_reward( + state: tauri::State<'_, Arc>>, +) -> Result { + let result = nymd_client!(state) + .simulate_vesting_compound_operator_reward(None) + .await?; + let gas_price = nymd_client!(state).gas_price().clone(); + Ok(SimulateResult::new(result.gas_info, gas_price).detailed_fee()) +} + +#[tauri::command] +pub async fn simulate_vesting_claim_delegator_reward( + mix_identity: IdentityKey, + state: tauri::State<'_, Arc>>, +) -> Result { + let result = nymd_client!(state) + .simulate_vesting_claim_delegator_reward(mix_identity, None) + .await?; + let gas_price = nymd_client!(state).gas_price().clone(); + Ok(SimulateResult::new(result.gas_info, gas_price).detailed_fee()) +} + +#[tauri::command] +pub async fn simulate_vesting_compound_delegator_reward( + mix_identity: IdentityKey, + state: tauri::State<'_, Arc>>, +) -> Result { + let result = nymd_client!(state) + .simulate_vesting_compound_delegator_reward(mix_identity, None) + .await?; + let gas_price = nymd_client!(state).gas_price().clone(); + Ok(SimulateResult::new(result.gas_info, gas_price).detailed_fee()) +} diff --git a/nym-wallet/src-tauri/src/operations/vesting/mod.rs b/nym-wallet/src-tauri/src/operations/vesting/mod.rs index 3542fd8d5c..f680e5ec6d 100644 --- a/nym-wallet/src-tauri/src/operations/vesting/mod.rs +++ b/nym-wallet/src-tauri/src/operations/vesting/mod.rs @@ -8,6 +8,7 @@ use vesting_contract_common::PledgeData as VestingPledgeData; pub mod bond; pub mod delegate; pub mod queries; +pub mod rewards; #[cfg_attr(test, derive(ts_rs::TS))] #[cfg_attr(test, ts(export, export_to = "../src/types/rust/pledgedata.ts"))] diff --git a/nym-wallet/src-tauri/src/operations/vesting/rewards.rs b/nym-wallet/src-tauri/src/operations/vesting/rewards.rs new file mode 100644 index 0000000000..e6b27fa78f --- /dev/null +++ b/nym-wallet/src-tauri/src/operations/vesting/rewards.rs @@ -0,0 +1,52 @@ +use crate::error::BackendError; +use crate::nymd_client; +use crate::state::State; +use mixnet_contract_common::IdentityKey; +use std::sync::Arc; +use tokio::sync::RwLock; +use validator_client::nymd::Fee; + +#[tauri::command] +pub async fn vesting_claim_operator_reward( + state: tauri::State<'_, Arc>>, +) -> Result<(), BackendError> { + nymd_client!(state) + .execute_vesting_claim_operator_reward(None) + .await?; + Ok(()) +} + +#[tauri::command] +pub async fn vesting_compound_operator_reward( + fee: Option, + state: tauri::State<'_, Arc>>, +) -> Result<(), BackendError> { + nymd_client!(state) + .execute_vesting_compound_operator_reward(fee) + .await?; + Ok(()) +} + +#[tauri::command] +pub async fn vesting_claim_delegator_reward( + mix_identity: IdentityKey, + fee: Option, + state: tauri::State<'_, Arc>>, +) -> Result<(), BackendError> { + nymd_client!(state) + .execute_vesting_claim_delegator_reward(mix_identity, fee) + .await?; + Ok(()) +} + +#[tauri::command] +pub async fn vesting_compound_delegator_reward( + mix_identity: IdentityKey, + fee: Option, + state: tauri::State<'_, Arc>>, +) -> Result<(), BackendError> { + nymd_client!(state) + .execute_vesting_compound_delegator_reward(mix_identity, fee) + .await?; + Ok(()) +} From d8fed178aa7af9bb89516b608df1d547afc94f4e Mon Sep 17 00:00:00 2001 From: vnpmid Date: Mon, 6 Jun 2022 20:38:01 +0700 Subject: [PATCH 10/25] Upgrade to tokio 1.19.1, tokio-util 0.7.3, tokio-stream 0.1.9, tokio-test 0.4.2 (#1305) * Upgrade to tokio 1.19.1, tokio-util 0.7.3, tokio-stream 0.1.9, tokio-test 0.4.2 * Tokio-util 0.7.3 handle_done_delaying, handle_expired_ack_timer * Upgrade to tokio 1.19.1, tokio-util 0.7.3, tokio-stream 0.1.9, tokio-test 0.4.2 --- Cargo.lock | 32 +++++++++---------- clients/client-core/Cargo.toml | 2 +- .../action_controller.rs | 11 ++----- clients/credential/Cargo.toml | 2 +- clients/native/Cargo.toml | 2 +- clients/socks5/Cargo.toml | 2 +- common/client-libs/gateway-client/Cargo.toml | 2 +- common/client-libs/mixnet-client/Cargo.toml | 4 +-- .../client-libs/validator-client/Cargo.toml | 2 +- common/credential-storage/Cargo.toml | 4 +-- common/mixnode-common/Cargo.toml | 4 +-- common/nonexhaustive-delayqueue/Cargo.toml | 6 ++-- common/nymsphinx/Cargo.toml | 2 +- common/nymsphinx/framing/Cargo.toml | 2 +- common/socks5/proxy-helpers/Cargo.toml | 6 ++-- explorer-api/Cargo.toml | 2 +- gateway/Cargo.toml | 8 ++--- mixnode/Cargo.toml | 6 ++-- mixnode/src/node/packet_delayforwarder.rs | 13 +++----- nym-wallet/src-tauri/Cargo.toml | 2 +- .../network-requester/Cargo.toml | 4 +-- validator-api/Cargo.toml | 6 ++-- 22 files changed, 57 insertions(+), 67 deletions(-) diff --git a/Cargo.lock b/Cargo.lock index 26e5c5b3f9..108ec33301 100644 --- a/Cargo.lock +++ b/Cargo.lock @@ -2149,7 +2149,7 @@ dependencies = [ "indexmap", "slab", "tokio", - "tokio-util 0.7.1", + "tokio-util 0.7.3", "tracing", ] @@ -2879,7 +2879,7 @@ dependencies = [ "log", "nymsphinx", "tokio", - "tokio-util 0.6.9", + "tokio-util 0.7.3", ] [[package]] @@ -2920,7 +2920,7 @@ dependencies = [ "rand 0.8.5", "serde", "tokio", - "tokio-util 0.6.9", + "tokio-util 0.7.3", "url", "validator-client", "version-checker", @@ -3010,7 +3010,7 @@ version = "0.1.0" dependencies = [ "tokio", "tokio-stream", - "tokio-util 0.6.9", + "tokio-util 0.7.3", ] [[package]] @@ -3145,7 +3145,7 @@ dependencies = [ "tokio", "tokio-stream", "tokio-tungstenite", - "tokio-util 0.6.9", + "tokio-util 0.7.3", "url", "validator-client", "vergen", @@ -3182,7 +3182,7 @@ dependencies = [ "serde", "serial_test", "tokio", - "tokio-util 0.6.9", + "tokio-util 0.7.3", "toml", "topology", "url", @@ -3430,7 +3430,7 @@ dependencies = [ "bytes", "nymsphinx-params", "nymsphinx-types", - "tokio-util 0.6.9", + "tokio-util 0.7.3", ] [[package]] @@ -4055,7 +4055,7 @@ dependencies = [ "socks5-requests", "tokio", "tokio-test", - "tokio-util 0.6.9", + "tokio-util 0.7.3", ] [[package]] @@ -5761,9 +5761,9 @@ dependencies = [ [[package]] name = "tokio" -version = "1.17.0" +version = "1.19.1" source = "registry+https://github.com/rust-lang/crates.io-index" -checksum = "2af73ac49756f3f7c01172e34a23e5d0216f6c32333757c2c61feb2bbff5a5ee" +checksum = "95eec79ea28c00a365f539f1961e9278fbcaf81c0ff6aaf0e93c181352446948" dependencies = [ "bytes", "libc", @@ -5824,9 +5824,9 @@ dependencies = [ [[package]] name = "tokio-stream" -version = "0.1.8" +version = "0.1.9" source = "registry+https://github.com/rust-lang/crates.io-index" -checksum = "50145484efff8818b5ccd256697f36863f587da82cf8b409c53adf1e840798e3" +checksum = "df54d54117d6fdc4e4fea40fe1e4e566b3505700e148a6827e59b34b0d2600d9" dependencies = [ "futures-core", "pin-project-lite", @@ -5871,20 +5871,20 @@ dependencies = [ "futures-sink", "log", "pin-project-lite", - "slab", "tokio", ] [[package]] name = "tokio-util" -version = "0.7.1" +version = "0.7.3" source = "registry+https://github.com/rust-lang/crates.io-index" -checksum = "0edfdeb067411dba2044da6d1cb2df793dd35add7888d73c16e3381ded401764" +checksum = "cc463cd8deddc3770d20f9852143d50bf6094e640b485cb2e189a2099085ff45" dependencies = [ "bytes", "futures-core", "futures-sink", "pin-project-lite", + "slab", "tokio", "tracing", ] @@ -5969,7 +5969,7 @@ dependencies = [ "rand 0.8.5", "slab", "tokio", - "tokio-util 0.7.1", + "tokio-util 0.7.3", "tower-layer", "tower-service", "tracing", diff --git a/clients/client-core/Cargo.toml b/clients/client-core/Cargo.toml index 30f88d4c5e..ddd6d14ef9 100644 --- a/clients/client-core/Cargo.toml +++ b/clients/client-core/Cargo.toml @@ -14,7 +14,7 @@ log = "0.4" rand = { version = "0.7.3", features = ["wasm-bindgen"] } serde = { version = "1.0", features = ["derive"] } sled = "0.34" -tokio = { version = "1.4", features = ["macros"] } +tokio = { version = "1.19.1", features = ["macros"] } url = { version ="2.2", features = ["serde"] } # internal diff --git a/clients/client-core/src/client/real_messages_control/acknowledgement_control/action_controller.rs b/clients/client-core/src/client/real_messages_control/acknowledgement_control/action_controller.rs index d619cf3f35..f8417b0285 100644 --- a/clients/client-core/src/client/real_messages_control/acknowledgement_control/action_controller.rs +++ b/clients/client-core/src/client/real_messages_control/acknowledgement_control/action_controller.rs @@ -6,7 +6,7 @@ use crate::client::real_messages_control::acknowledgement_control::Retransmissio use futures::channel::mpsc::{self, UnboundedReceiver, UnboundedSender}; use futures::StreamExt; use log::*; -use nonexhaustive_delayqueue::{Expired, NonExhaustiveDelayQueue, QueueKey, TimerError}; +use nonexhaustive_delayqueue::{Expired, NonExhaustiveDelayQueue, QueueKey}; use nymsphinx::chunking::fragment::FragmentIdentifier; use nymsphinx::Delay as SphinxDelay; use std::collections::HashMap; @@ -209,16 +209,11 @@ impl ActionController { } // note: when the entry expires it's automatically removed from pending_acks_timers - fn handle_expired_ack_timer( - &mut self, - expired_ack: Result, TimerError>, - ) { + fn handle_expired_ack_timer(&mut self, expired_ack: Expired) { // I'm honestly not sure how to handle it, because getting it means other things in our // system are already misbehaving. If we ever see this panic, then I guess we should worry // about it. Perhaps just reschedule it at later point? - let frag_id = expired_ack - .expect("Tokio timer returned an error!") - .into_inner(); + let frag_id = expired_ack.into_inner(); trace!("{} has expired", frag_id); diff --git a/clients/credential/Cargo.toml b/clients/credential/Cargo.toml index 54fdb0ee21..5d2d4d8142 100644 --- a/clients/credential/Cargo.toml +++ b/clients/credential/Cargo.toml @@ -15,7 +15,7 @@ rand = "0.7.3" serde = { version = "1.0", features = ["derive"] } thiserror = "1.0" url = "2.2" -tokio = { version = "1.4", features = ["rt-multi-thread", "net", "signal", "macros"] } # async runtime +tokio = { version = "1.19.1", features = ["rt-multi-thread", "net", "signal", "macros"] } # async runtime coconut-interface = { path = "../../common/coconut-interface" } credentials = { path = "../../common/credentials" } diff --git a/clients/native/Cargo.toml b/clients/native/Cargo.toml index 5c4d0dd6e1..661af318c9 100644 --- a/clients/native/Cargo.toml +++ b/clients/native/Cargo.toml @@ -27,7 +27,7 @@ pretty_env_logger = "0.4" # for formatting log messages rand = { version = "0.7.3", features = ["wasm-bindgen"] } # rng-related traits + some rng implementation to use serde = { version = "1.0.104", features = ["derive"] } # for config serialization/deserialization sled = "0.34" # for storage of replySURB decryption keys -tokio = { version = "1.4", features = ["rt-multi-thread", "net", "signal"] } # async runtime +tokio = { version = "1.19.1", features = ["rt-multi-thread", "net", "signal"] } # async runtime tokio-tungstenite = "0.14" # websocket ## internal diff --git a/clients/socks5/Cargo.toml b/clients/socks5/Cargo.toml index b5316cc6cd..1ac917a7cf 100644 --- a/clients/socks5/Cargo.toml +++ b/clients/socks5/Cargo.toml @@ -20,7 +20,7 @@ pretty_env_logger = "0.4" rand = { version = "0.7.3", features = ["wasm-bindgen"] } serde = { version = "1.0", features = ["derive"] } # for config serialization/deserialization snafu = "0.6" -tokio = { version = "1.4", features = ["rt-multi-thread", "net", "signal"] } +tokio = { version = "1.19.1", features = ["rt-multi-thread", "net", "signal"] } url = "2.2" # internal diff --git a/common/client-libs/gateway-client/Cargo.toml b/common/client-libs/gateway-client/Cargo.toml index 004619e4d3..8e22cd012e 100644 --- a/common/client-libs/gateway-client/Cargo.toml +++ b/common/client-libs/gateway-client/Cargo.toml @@ -35,7 +35,7 @@ default-features = false # non-wasm-only dependencies [target."cfg(not(target_arch = \"wasm32\"))".dependencies.tokio] -version = "1.4" +version = "1.19.1" features = ["macros", "rt", "net", "sync", "time"] [target."cfg(not(target_arch = \"wasm32\"))".dependencies.tokio-tungstenite] diff --git a/common/client-libs/mixnet-client/Cargo.toml b/common/client-libs/mixnet-client/Cargo.toml index 2585440542..c99ddabbbb 100644 --- a/common/client-libs/mixnet-client/Cargo.toml +++ b/common/client-libs/mixnet-client/Cargo.toml @@ -9,8 +9,8 @@ edition = "2021" [dependencies] futures = "0.3" log = "0.4.8" -tokio = { version = "1.4", features = ["time", "net", "rt"] } -tokio-util = { version = "0.6", features = ["codec"] } +tokio = { version = "1.19.1", features = ["time", "net", "rt"] } +tokio-util = { version = "0.7.3", features = ["codec"] } # internal nymsphinx = {path = "../../nymsphinx" } diff --git a/common/client-libs/validator-client/Cargo.toml b/common/client-libs/validator-client/Cargo.toml index 6c9fa9faf5..e69699d36b 100644 --- a/common/client-libs/validator-client/Cargo.toml +++ b/common/client-libs/validator-client/Cargo.toml @@ -22,7 +22,7 @@ reqwest = { version = "0.11", features = ["json"] } thiserror = "1" log = "0.4" url = { version = "2.2", features = ["serde"] } -tokio = { version = "1.10", features = ["sync", "time"] } +tokio = { version = "1.19.1", features = ["sync", "time"] } futures = "0.3" coconut-interface = { path = "../../coconut-interface" } diff --git a/common/credential-storage/Cargo.toml b/common/credential-storage/Cargo.toml index fe05fb4bd3..70d18c4716 100644 --- a/common/credential-storage/Cargo.toml +++ b/common/credential-storage/Cargo.toml @@ -12,9 +12,9 @@ nymcoconut = { path = "../nymcoconut" } log = "0.4" sqlx = { version = "0.5", features = ["runtime-tokio-rustls", "sqlite", "macros", "migrate"]} thiserror = "1.0" -tokio = { version = "1.4", features = [ "rt-multi-thread", "net", "signal", "fs" ] } +tokio = { version = "1.19.1", features = [ "rt-multi-thread", "net", "signal", "fs" ] } [build-dependencies] sqlx = { version = "0.5", features = ["runtime-tokio-rustls", "sqlite", "macros", "migrate"] } -tokio = { version = "1.4", features = ["rt-multi-thread", "macros"] } \ No newline at end of file +tokio = { version = "1.19.1", features = ["rt-multi-thread", "macros"] } \ No newline at end of file diff --git a/common/mixnode-common/Cargo.toml b/common/mixnode-common/Cargo.toml index f5b70e1612..77c25d0455 100644 --- a/common/mixnode-common/Cargo.toml +++ b/common/mixnode-common/Cargo.toml @@ -14,8 +14,8 @@ humantime-serde = "1.0" log = "0.4" rand = "0.8" serde = { version = "1.0", features = ["derive"] } -tokio = { version = "1.4", features = ["time", "macros", "rt", "net", "io-util"] } -tokio-util = { version = "0.6", features = ["codec"] } +tokio = { version = "1.19.1", features = ["time", "macros", "rt", "net", "io-util"] } +tokio-util = { version = "0.7.3", features = ["codec"] } url = "2.2" crypto = { path = "../crypto" } diff --git a/common/nonexhaustive-delayqueue/Cargo.toml b/common/nonexhaustive-delayqueue/Cargo.toml index ea64ddf6c6..778342e578 100644 --- a/common/nonexhaustive-delayqueue/Cargo.toml +++ b/common/nonexhaustive-delayqueue/Cargo.toml @@ -7,6 +7,6 @@ edition = "2021" # See more keys and their definitions at https://doc.rust-lang.org/cargo/reference/manifest.html [dependencies] -tokio = { version = "1.4", features = [] } -tokio-stream = "0.1" # this one seems to be a thing until `Stream` trait is stabilised in stdlib -tokio-util = { version = "0.6", features = ["time"] } +tokio = { version = "1.19.1", features = [] } +tokio-stream = "0.1.9" # this one seems to be a thing until `Stream` trait is stabilised in stdlib +tokio-util = { version = "0.7.3", features = ["time"] } diff --git a/common/nymsphinx/Cargo.toml b/common/nymsphinx/Cargo.toml index 460fd11390..b697700ec1 100644 --- a/common/nymsphinx/Cargo.toml +++ b/common/nymsphinx/Cargo.toml @@ -33,5 +33,5 @@ mixnet-contract-common = { path = "../cosmwasm-smart-contracts/mixnet-contract" path = "framing" [target."cfg(not(target_arch = \"wasm32\"))".dependencies.tokio] -version = "1.4" +version = "1.19.1" features = ["sync"] diff --git a/common/nymsphinx/framing/Cargo.toml b/common/nymsphinx/framing/Cargo.toml index 0cddb5bf22..6921a8cf69 100644 --- a/common/nymsphinx/framing/Cargo.toml +++ b/common/nymsphinx/framing/Cargo.toml @@ -8,7 +8,7 @@ edition = "2021" [dependencies] bytes = "1.0" -tokio-util = { version = "0.6", features = ["codec"] } +tokio-util = { version = "0.7.3", features = ["codec"] } nymsphinx-types = { path = "../types" } nymsphinx-params = { path = "../params" } diff --git a/common/socks5/proxy-helpers/Cargo.toml b/common/socks5/proxy-helpers/Cargo.toml index 77c9e4cf7e..71a4cebb23 100644 --- a/common/socks5/proxy-helpers/Cargo.toml +++ b/common/socks5/proxy-helpers/Cargo.toml @@ -8,8 +8,8 @@ edition = "2021" [dependencies] bytes = "1.0" -tokio = { version = "1.4", features = [ "net", "io-util", "sync", "macros", "time", "rt-multi-thread" ] } -tokio-util = { version = "0.6", features = [ "io" ] } # reason for getting this guy is to to able to port to tokio 1.X more quickly by being able to use +tokio = { version = "1.19.1", features = [ "net", "io-util", "sync", "macros", "time", "rt-multi-thread" ] } +tokio-util = { version = "0.7.3", features = [ "io" ] } # reason for getting this guy is to to able to port to tokio 1.X more quickly by being able to use # their `read_buf` [from the util crate] replacement rather than having to rethink/reimplement `AvailableReader` with the new AsyncRead trait definition. # In the long run, the dependency should probably get removed in favour of pure-tokio implementation, but for time being it's fine. futures = "0.3" @@ -18,4 +18,4 @@ socks5-requests = { path = "../requests" } ordered-buffer = { path = "../ordered-buffer" } [dev-dependencies] -tokio-test = "0.4" \ No newline at end of file +tokio-test = "0.4.2" \ No newline at end of file diff --git a/explorer-api/Cargo.toml b/explorer-api/Cargo.toml index a4787ecebc..58096adee4 100644 --- a/explorer-api/Cargo.toml +++ b/explorer-api/Cargo.toml @@ -21,7 +21,7 @@ schemars = { version = "0.8", features = ["preserve_order"] } serde = "1.0.126" serde_json = "1.0.66" thiserror = "1.0.29" -tokio = {version = "1.9.0", features = ["full"] } +tokio = {version = "1.19.1", features = ["full"] } mixnet-contract-common = { path = "../common/cosmwasm-smart-contracts/mixnet-contract" } network-defaults = { path = "../common/network-defaults" } diff --git a/gateway/Cargo.toml b/gateway/Cargo.toml index e25a803d14..e3ab0f4722 100644 --- a/gateway/Cargo.toml +++ b/gateway/Cargo.toml @@ -31,10 +31,10 @@ serde = { version = "1.0.104", features = ["derive"] } sqlx = { version = "0.5", features = ["runtime-tokio-rustls", "sqlite", "macros", "migrate"] } subtle-encoding = { version = "0.5", features = ["bech32-preview"]} thiserror = "1" -tokio = { version = "1.4", features = [ "rt-multi-thread", "net", "signal", "fs" ] } -tokio-stream = { version = "0.1", features = [ "fs" ] } +tokio = { version = "1.19.1", features = [ "rt-multi-thread", "net", "signal", "fs" ] } +tokio-stream = { version = "0.1.9", features = [ "fs" ] } tokio-tungstenite = "0.14" -tokio-util = { version = "0.6", features = [ "codec" ] } +tokio-util = { version = "0.7.3", features = [ "codec" ] } url = { version = "2.2", features = [ "serde" ] } web3 = "0.17.0" @@ -59,6 +59,6 @@ coconut = ["coconut-interface", "gateway-requests/coconut", "gateway-client/coco eth = [] [build-dependencies] -tokio = { version = "1.4", features = ["rt-multi-thread", "macros"] } +tokio = { version = "1.19.1", features = ["rt-multi-thread", "macros"] } sqlx = { version = "0.5", features = ["runtime-tokio-rustls", "sqlite", "macros", "migrate"] } vergen = { version = "5", default-features = false, features = ["build", "git", "rustc", "cargo"] } diff --git a/mixnode/Cargo.toml b/mixnode/Cargo.toml index 9dac6d1953..e7157683a6 100644 --- a/mixnode/Cargo.toml +++ b/mixnode/Cargo.toml @@ -28,8 +28,8 @@ pretty_env_logger = "0.4.0" rand = "0.7.3" rocket = { version="0.5.0-rc.1", features = ["json"] } serde = { version="1.0", features = ["derive"] } -tokio = { version="1.8", features = ["rt-multi-thread", "net", "signal"] } -tokio-util = { version="0.6.7", features = ["codec"] } +tokio = { version="1.19.1", features = ["rt-multi-thread", "net", "signal"] } +tokio-util = { version="0.7.3", features = ["codec"] } toml = "0.5.8" url = { version = "2.2", features = ["serde"] } lazy_static = "1.4.0" @@ -49,7 +49,7 @@ version-checker = { path="../common/version-checker" } [dev-dependencies] serial_test = "0.5" -tokio = { version="1.8", features = ["rt-multi-thread", "net", "signal", "test-util"] } +tokio = { version="1.19.1", features = ["rt-multi-thread", "net", "signal", "test-util"] } nymsphinx-types = { path = "../common/nymsphinx/types" } nymsphinx-params = { path = "../common/nymsphinx/params" } diff --git a/mixnode/src/node/packet_delayforwarder.rs b/mixnode/src/node/packet_delayforwarder.rs index d2f1ced206..e0aece8fcb 100644 --- a/mixnode/src/node/packet_delayforwarder.rs +++ b/mixnode/src/node/packet_delayforwarder.rs @@ -4,7 +4,7 @@ use crate::node::node_statistics::UpdateSender; use futures::channel::mpsc; use futures::StreamExt; -use nonexhaustive_delayqueue::{Expired, NonExhaustiveDelayQueue, TimerError}; +use nonexhaustive_delayqueue::{Expired, NonExhaustiveDelayQueue}; use nymsphinx::forwarding::packet::MixPacket; use std::io; use tokio::time::Instant; @@ -75,13 +75,8 @@ where } /// Upon packet being finished getting delayed, forward it to the mixnet. - fn handle_done_delaying(&mut self, packet: Option, TimerError>>) { - // those are critical errors that I don't think can be recovered from. - let delayed = packet.expect("the queue has unexpectedly terminated!"); - let delayed_packet = delayed - .expect("Encountered timer issue within the runtime!") - .into_inner(); - + fn handle_done_delaying(&mut self, packet: Expired) { + let delayed_packet = packet.into_inner(); self.forward_packet(delayed_packet) } @@ -105,7 +100,7 @@ where loop { tokio::select! { delayed = self.delay_queue.next() => { - self.handle_done_delaying(delayed); + self.handle_done_delaying(delayed.unwrap()); } new_packet = self.packet_receiver.next() => { // this one is impossible to ever panic - the object itself contains a sender diff --git a/nym-wallet/src-tauri/Cargo.toml b/nym-wallet/src-tauri/Cargo.toml index 82f6e2d89b..03a23fe886 100644 --- a/nym-wallet/src-tauri/Cargo.toml +++ b/nym-wallet/src-tauri/Cargo.toml @@ -38,7 +38,7 @@ strum = { version = "0.23", features = ["derive"] } tauri = { version = "=1.0.0-rc.2", features = ["clipboard-all", "shell-open", "updater", "window-maximize"] } tendermint-rpc = "0.23.0" thiserror = "1.0" -tokio = { version = "1.10", features = ["sync", "time"] } +tokio = { version = "1.19.1", features = ["sync", "time"] } toml = "0.5.8" url = "2.2" diff --git a/service-providers/network-requester/Cargo.toml b/service-providers/network-requester/Cargo.toml index bd266ecd9a..ba83a25179 100644 --- a/service-providers/network-requester/Cargo.toml +++ b/service-providers/network-requester/Cargo.toml @@ -23,7 +23,7 @@ rocket = { version = "0.5.0-rc.1", features = ["json"], optional = true } serde = { version = "1.0", features = ["derive"] } sqlx = { version = "0.5", features = ["runtime-tokio-rustls", "sqlite", "macros", "migrate", "chrono"]} thiserror = "1" -tokio = { version = "1.4", features = [ "net", "rt-multi-thread", "macros", "time" ] } +tokio = { version = "1.19.1", features = [ "net", "rt-multi-thread", "macros", "time" ] } tokio-tungstenite = "0.14" @@ -40,7 +40,7 @@ rand = "0.7" [build-dependencies] sqlx = { version = "0.5", features = ["runtime-tokio-rustls", "sqlite", "macros", "migrate"] } -tokio = { version = "1.4", features = ["rt-multi-thread", "macros"] } +tokio = { version = "1.19.1", features = ["rt-multi-thread", "macros"] } [features] stats-service = ["rocket"] \ No newline at end of file diff --git a/validator-api/Cargo.toml b/validator-api/Cargo.toml index c33e43b55d..a75534348a 100644 --- a/validator-api/Cargo.toml +++ b/validator-api/Cargo.toml @@ -33,8 +33,8 @@ serde = "1.0" serde_json = "1.0" thiserror = "1" time = { version = "0.3", features = ["serde-human-readable", "parsing"]} -tokio = { version = "1.4", features = ["rt-multi-thread", "macros", "signal", "time"] } -tokio-stream = "0.1.8" +tokio = { version = "1.19.1", features = ["rt-multi-thread", "macros", "signal", "time"] } +tokio-stream = "0.1.9" url = "2.2" anyhow = "1" @@ -72,7 +72,7 @@ coconut = ["coconut-interface", "credentials", "gateway-client/coconut", "creden no-reward = [] [build-dependencies] -tokio = { version = "1.4", features = ["rt-multi-thread", "macros"] } +tokio = { version = "1.19.1", features = ["rt-multi-thread", "macros"] } sqlx = { version = "0.5", features = ["runtime-tokio-rustls", "sqlite", "macros", "migrate"] } vergen = { version = "5", default-features = false, features = ["build", "git", "rustc", "cargo"] } From c7dd48edbb1a15e5f5b33e58704652d6fac6f5e3 Mon Sep 17 00:00:00 2001 From: gala1234 Date: Mon, 6 Jun 2022 16:47:30 +0200 Subject: [PATCH 11/25] remove delegators number column on node list and hardcode --- explorer/src/api/index.ts | 21 ++++----------------- explorer/src/components/MixNodes/index.ts | 2 -- explorer/src/pages/Mixnodes/index.tsx | 17 ----------------- 3 files changed, 4 insertions(+), 36 deletions(-) diff --git a/explorer/src/api/index.ts b/explorer/src/api/index.ts index ba24855a70..5a9b40ef9a 100644 --- a/explorer/src/api/index.ts +++ b/explorer/src/api/index.ts @@ -61,15 +61,8 @@ export class Api { } const res = await fetch(MIXNODES_API); const json = await res.json(); - // TODO remove hard coded API response - const nodeArr = json.map((element: MixNodeResponseItem) => { - const node = element; - node.delegators_number = 2; - return node; - }); - - storeInCache('mixnodes', JSON.stringify(nodeArr)); - return nodeArr; + storeInCache('mixnodes', JSON.stringify(json)); + return json; }; static fetchMixnodesActiveSetByStatus = async (status: MixnodeStatus): Promise => { @@ -79,14 +72,8 @@ export class Api { } const res = await fetch(`${MIXNODES_API}/active-set/${status}`); const json = await res.json(); - // TODO remove hard coded API response - const nodeArr = json.map((element: MixNodeResponseItem) => { - const node = element; - node.delegators_number = 2; - return node; - }); - storeInCache(`mixnodes-${status}`, JSON.stringify(nodeArr)); - return nodeArr; + storeInCache(`mixnodes-${status}`, JSON.stringify(json)); + return json; }; static fetchMixnodeByID = async (id: string): Promise => { diff --git a/explorer/src/components/MixNodes/index.ts b/explorer/src/components/MixNodes/index.ts index 4ef6518ef3..55a6b7c080 100644 --- a/explorer/src/components/MixNodes/index.ts +++ b/explorer/src/components/MixNodes/index.ts @@ -13,7 +13,6 @@ export type MixnodeRowType = { layer: string; profit_percentage: string; avg_uptime: string; - delegators_number: number; stake_saturation: number; }; @@ -40,7 +39,6 @@ export function mixNodeResponseItemToMixnodeRowType(item: MixNodeResponseItem): layer: item?.layer || '', profit_percentage: `${profitPercentage}%`, avg_uptime: `${item.avg_uptime}%` || '-', - delegators_number: Number(item.delegators_number) || 0, stake_saturation: stakeSaturation, }; } diff --git a/explorer/src/pages/Mixnodes/index.tsx b/explorer/src/pages/Mixnodes/index.tsx index 64a7c69e01..ce55f257ee 100644 --- a/explorer/src/pages/Mixnodes/index.tsx +++ b/explorer/src/pages/Mixnodes/index.tsx @@ -197,23 +197,6 @@ export const PageMixnodes: React.FC = () => { ), }, - { - field: 'delegators_number', - headerName: 'Delegators', - renderHeader: () => , - headerClassName: 'MuiDataGrid-header-override', - width: 185, - headerAlign: 'left', - renderCell: (params: GridRenderCellParams) => ( - - {params.value} - - ), - }, { field: 'profit_percentage', headerName: 'Profit Margin', From 858ef7b3f99a6caaeda070492da16eff25a1b994 Mon Sep 17 00:00:00 2001 From: gala1234 Date: Mon, 6 Jun 2022 16:49:04 +0200 Subject: [PATCH 12/25] cleaning --- explorer/src/typeDefs/explorer-api.ts | 1 - 1 file changed, 1 deletion(-) diff --git a/explorer/src/typeDefs/explorer-api.ts b/explorer/src/typeDefs/explorer-api.ts index ab1d9b7d00..3463f55d98 100644 --- a/explorer/src/typeDefs/explorer-api.ts +++ b/explorer/src/typeDefs/explorer-api.ts @@ -84,7 +84,6 @@ export interface MixNodeResponseItem { }; mix_node: MixNode; avg_uptime: number; - delegators_number: number; stake_saturation: number; } From 67625fe76811f02dda65334cc5994d98dbd1a249 Mon Sep 17 00:00:00 2001 From: gala1234 Date: Tue, 7 Jun 2022 09:40:55 +0200 Subject: [PATCH 13/25] explorer: move stake-sat column in node list --- explorer/src/pages/Mixnodes/index.tsx | 42 +++++++++++++-------------- 1 file changed, 21 insertions(+), 21 deletions(-) diff --git a/explorer/src/pages/Mixnodes/index.tsx b/explorer/src/pages/Mixnodes/index.tsx index ce55f257ee..bcdccd2c9c 100644 --- a/explorer/src/pages/Mixnodes/index.tsx +++ b/explorer/src/pages/Mixnodes/index.tsx @@ -179,6 +179,27 @@ export const PageMixnodes: React.FC = () => { ), }, + { + field: 'stake_saturation', + headerName: 'Stake Saturation', + renderHeader: () => , + headerClassName: 'MuiDataGrid-header-override', + width: 175, + headerAlign: 'left', + renderCell: (params: GridRenderCellParams) => ( + 100 ? theme.palette.warning.main : 'inherit', + ...getCellStyles(theme, params.row), + }} + component={RRDLink} + to={`/network-components/mixnode/${params.row.identity_key}`} + > + {`${params.value.toFixed(2)} %`} + + ), + }, { field: 'self_percentage', headerName: 'Self %', @@ -231,27 +252,6 @@ export const PageMixnodes: React.FC = () => { ), }, - { - field: 'stake_saturation', - headerName: 'Stake Saturation', - renderHeader: () => , - headerClassName: 'MuiDataGrid-header-override', - width: 175, - headerAlign: 'left', - renderCell: (params: GridRenderCellParams) => ( - 100 ? theme.palette.warning.main : 'inherit', - ...getCellStyles(theme, params.row), - }} - component={RRDLink} - to={`/network-components/mixnode/${params.row.identity_key}`} - > - {`${params.value.toFixed(2)} %`} - - ), - }, ]; const handlePageSize = (event: SelectChangeEvent) => { From 7a74bb9ad5234e049f5bf00108104a3b10810e0a Mon Sep 17 00:00:00 2001 From: =?UTF-8?q?Rapha=C3=ABl=20Walther?= <48209673+raphael-walther@users.noreply.github.com> Date: Tue, 7 Jun 2022 10:47:59 +0200 Subject: [PATCH 14/25] Fixed unused variables in test (#1311) --- validator-api/src/coconut/tests.rs | 4 ++-- 1 file changed, 2 insertions(+), 2 deletions(-) diff --git a/validator-api/src/coconut/tests.rs b/validator-api/src/coconut/tests.rs index 5e34f3962c..021902e32d 100644 --- a/validator-api/src/coconut/tests.rs +++ b/validator-api/src/coconut/tests.rs @@ -83,8 +83,8 @@ impl super::client::Client for DummyClient { async fn execute_proposal( &self, - proposal_id: u64, - fee: Option, + _proposal_id: u64, + _fee: Option, ) -> crate::coconut::error::Result<()> { todo!() } From f15ecdda06d719f7ed916da71c74e0730d5f1da2 Mon Sep 17 00:00:00 2001 From: =?UTF-8?q?Jon=20H=C3=A4ggblad?= Date: Tue, 7 Jun 2022 11:41:58 +0200 Subject: [PATCH 15/25] mixnode: graceful shutdown on ctrl-c (#1304) * mixnode: add graceful notification to most tasks * Add note about remaining work * task/shutdown: add shutdown timer * changelog: add entry for shutdown * mixnode: revert some temp changes * common/task: make sure to use latest tokio --- CHANGELOG.md | 1 + Cargo.lock | 10 ++ Cargo.toml | 1 + common/task/Cargo.toml | 14 +++ common/task/src/lib.rs | 6 + common/task/src/shutdown.rs | 106 ++++++++++++++++++ mixnode/Cargo.toml | 1 + .../node/listener/connection_handler/mod.rs | 52 +++++---- mixnode/src/node/listener/mod.rs | 30 +++-- mixnode/src/node/mod.rs | 51 +++++++-- mixnode/src/node/node_statistics.rs | 93 +++++++++++---- mixnode/src/node/packet_delayforwarder.rs | 22 +++- 12 files changed, 325 insertions(+), 62 deletions(-) create mode 100644 common/task/Cargo.toml create mode 100644 common/task/src/lib.rs create mode 100644 common/task/src/shutdown.rs diff --git a/CHANGELOG.md b/CHANGELOG.md index f9c3f58406..29771fda42 100644 --- a/CHANGELOG.md +++ b/CHANGELOG.md @@ -29,6 +29,7 @@ - mixnet-contract: replaced integer division with fixed for performance calculations ([#1284]) - mixnet-contract: Under certain circumstances nodes could not be unbonded ([#1255](https://github.com/nymtech/nym/issues/1255)) ([#1258]) - mixnode, gateway: attempting to determine reconnection backoff to persistently failing mixnode could result in a crash ([#1260]) +- mixnode: the mixnode learned how to shutdown gracefully. - vesting-contract: replaced `checked_sub` with `saturating_sub` to fix the underflow in `get_vesting_tokens` ([#1275]) ### Changed diff --git a/Cargo.lock b/Cargo.lock index 108ec33301..5542e148d0 100644 --- a/Cargo.lock +++ b/Cargo.lock @@ -3181,6 +3181,7 @@ dependencies = [ "rocket", "serde", "serial_test", + "task", "tokio", "tokio-util 0.7.3", "toml", @@ -5509,6 +5510,15 @@ version = "1.0.1" source = "registry+https://github.com/rust-lang/crates.io-index" checksum = "55937e1799185b12863d447f42597ed69d9928686b8d88a1df17376a097d8369" +[[package]] +name = "task" +version = "0.1.0" +dependencies = [ + "log", + "tokio", + "tokio-util 0.6.9", +] + [[package]] name = "tempfile" version = "3.3.0" diff --git a/Cargo.toml b/Cargo.toml index 1f36d4b26e..d1acbb02a1 100644 --- a/Cargo.toml +++ b/Cargo.toml @@ -55,6 +55,7 @@ members = [ "common/pemstore", "common/socks5/proxy-helpers", "common/socks5/requests", + "common/task", "common/topology", "common/wasm-utils", "explorer-api", diff --git a/common/task/Cargo.toml b/common/task/Cargo.toml new file mode 100644 index 0000000000..0e8df18f3a --- /dev/null +++ b/common/task/Cargo.toml @@ -0,0 +1,14 @@ +[package] +name = "task" +version = "0.1.0" +edition = "2021" + +# See more keys and their definitions at https://doc.rust-lang.org/cargo/reference/manifest.html + +[dependencies] +log = "0.4" +tokio = { version = "1.19.1", features = ["rt-multi-thread", "net", "signal"] } +tokio-util = { version = "0.7.3", features = ["codec"] } + +[dev-dependencies] +tokio = { version = "1.19.1", features = ["rt-multi-thread", "net", "signal", "test-util", "macros"] } diff --git a/common/task/src/lib.rs b/common/task/src/lib.rs new file mode 100644 index 0000000000..b983af29db --- /dev/null +++ b/common/task/src/lib.rs @@ -0,0 +1,6 @@ +// Copyright 2022 - Nym Technologies SA +// SPDX-License-Identifier: Apache-2.0 + +pub mod shutdown; + +pub use shutdown::{ShutdownListener, ShutdownNotifier}; diff --git a/common/task/src/shutdown.rs b/common/task/src/shutdown.rs new file mode 100644 index 0000000000..8c8b472459 --- /dev/null +++ b/common/task/src/shutdown.rs @@ -0,0 +1,106 @@ +// Copyright 2022 - Nym Technologies SA +// SPDX-License-Identifier: Apache-2.0 + +use std::time::Duration; + +use tokio::sync::watch::{self, error::SendError}; + +const SHUTDOWN_TIMER_SECS: u64 = 5; + +/// Used to notify other tasks to gracefully shutdown +#[derive(Debug)] +pub struct ShutdownNotifier { + notify_tx: watch::Sender<()>, + notify_rx: Option>, +} + +impl Default for ShutdownNotifier { + fn default() -> Self { + let (notify_tx, notify_rx) = watch::channel(()); + Self { + notify_tx, + notify_rx: Some(notify_rx), + } + } +} + +impl ShutdownNotifier { + pub fn subscribe(&self) -> ShutdownListener { + ShutdownListener::new( + self.notify_rx + .as_ref() + .expect("Unable to subscribe to shutdown notifier that is already shutdown") + .clone(), + ) + } + + pub fn signal_shutdown(&self) -> Result<(), SendError<()>> { + self.notify_tx.send(()) + } + + pub async fn wait_for_shutdown(&mut self) { + if let Some(notify_rx) = self.notify_rx.take() { + drop(notify_rx); + } + + tokio::select! { + _ = self.notify_tx.closed() => { + log::info!("All registered tasks succesfully shutdown"); + }, + _ = tokio::signal::ctrl_c() => { + log::info!("Forcing shutdown"); + } + _ = tokio::time::sleep(Duration::from_secs(SHUTDOWN_TIMER_SECS)) => { + log::info!("Timout reached, forcing shutdown"); + }, + } + } +} + +/// Listen for shutdown notifications +#[derive(Clone, Debug)] +pub struct ShutdownListener { + shutdown: bool, + notify: watch::Receiver<()>, +} + +impl ShutdownListener { + pub fn new(notify: watch::Receiver<()>) -> ShutdownListener { + ShutdownListener { + shutdown: false, + notify, + } + } + + pub fn is_shutdown(&self) -> bool { + self.shutdown + } + + pub async fn recv(&mut self) { + if self.shutdown { + return; + } + let _ = self.notify.changed().await; + self.shutdown = true; + } +} + +#[cfg(test)] +mod tests { + use super::*; + + #[tokio::test] + async fn signal_shutdown() { + let shutdown = ShutdownNotifier::default(); + let mut listener = shutdown.subscribe(); + + let task = tokio::spawn(async move { + tokio::select! { + _ = listener.recv() => 42, + } + }); + + shutdown.signal_shutdown().unwrap(); + assert_eq!(task.await.unwrap(), 42); + } +} diff --git a/mixnode/Cargo.toml b/mixnode/Cargo.toml index e7157683a6..3c99624cb5 100644 --- a/mixnode/Cargo.toml +++ b/mixnode/Cargo.toml @@ -43,6 +43,7 @@ mixnode-common = { path="../common/mixnode-common" } nonexhaustive-delayqueue = { path="../common/nonexhaustive-delayqueue" } nymsphinx = { path="../common/nymsphinx" } pemstore = { path="../common/pemstore" } +task = { path = "../common/task" } topology = { path="../common/topology" } validator-client = { path="../common/client-libs/validator-client" } version-checker = { path="../common/version-checker" } diff --git a/mixnode/src/node/listener/connection_handler/mod.rs b/mixnode/src/node/listener/connection_handler/mod.rs index 3aff6ad3a8..c9baaecacf 100644 --- a/mixnode/src/node/listener/connection_handler/mod.rs +++ b/mixnode/src/node/listener/connection_handler/mod.rs @@ -5,6 +5,7 @@ use crate::node::listener::connection_handler::packet_processing::{ MixProcessingResult, PacketProcessor, }; use crate::node::packet_delayforwarder::PacketDelayForwardSender; +use crate::node::ShutdownListener; use futures::StreamExt; use log::{error, info}; use nymsphinx::forwarding::packet::MixPacket; @@ -69,28 +70,40 @@ impl ConnectionHandler { } } - pub(crate) async fn handle_connection(self, conn: TcpStream, remote: SocketAddr) { + pub(crate) async fn handle_connection( + self, + conn: TcpStream, + remote: SocketAddr, + mut shutdown: ShutdownListener, + ) { debug!("Starting connection handler for {:?}", remote); let mut framed_conn = Framed::new(conn, SphinxCodec); - while let Some(framed_sphinx_packet) = framed_conn.next().await { - match framed_sphinx_packet { - Ok(framed_sphinx_packet) => { - // TODO: benchmark spawning tokio task with full processing vs just processing it - // synchronously (without delaying inside of course, - // delay is moved to a global DelayQueue) - // under higher load in single and multi-threaded situation. + while !shutdown.is_shutdown() { + tokio::select! { + Some(framed_sphinx_packet) = framed_conn.next() => { + match framed_sphinx_packet { + Ok(framed_sphinx_packet) => { + // TODO: benchmark spawning tokio task with full processing vs just processing it + // synchronously (without delaying inside of course, + // delay is moved to a global DelayQueue) + // under higher load in single and multi-threaded situation. - // in theory we could process multiple sphinx packet from the same connection in parallel, - // but we already handle multiple concurrent connections so if anything, making - // that change would only slow things down - self.handle_received_packet(framed_sphinx_packet); - } - Err(err) => { - error!( - "The socket connection got corrupted with error: {:?}. Closing the socket", - err - ); - return; + // in theory we could process multiple sphinx packet from the same connection in parallel, + // but we already handle multiple concurrent connections so if anything, making + // that change would only slow things down + self.handle_received_packet(framed_sphinx_packet); + } + Err(err) => { + error!( + "The socket connection got corrupted with error: {:?}. Closing the socket", + err + ); + return; + } + } + }, + _ = shutdown.recv() => { + log::trace!("ConnectionHandler: received shutdown"); } } } @@ -99,5 +112,6 @@ impl ConnectionHandler { "Closing connection from {:?}", framed_conn.into_inner().peer_addr() ); + log::trace!("ConnectionHandler: Exiting"); } } diff --git a/mixnode/src/node/listener/mod.rs b/mixnode/src/node/listener/mod.rs index e24e951838..a1542fba79 100644 --- a/mixnode/src/node/listener/mod.rs +++ b/mixnode/src/node/listener/mod.rs @@ -8,18 +8,22 @@ use std::process; use tokio::net::TcpListener; use tokio::task::JoinHandle; +use super::ShutdownListener; + pub(crate) mod connection_handler; pub(crate) struct Listener { address: SocketAddr, + shutdown: ShutdownListener, } impl Listener { - pub(crate) fn new(address: SocketAddr) -> Self { - Listener { address } + pub(crate) fn new(address: SocketAddr, shutdown: ShutdownListener) -> Self { + Listener { address, shutdown } } async fn run(&mut self, connection_handler: ConnectionHandler) { + log::trace!("Starting Listener"); let listener = match TcpListener::bind(self.address).await { Ok(listener) => listener, Err(err) => { @@ -28,15 +32,23 @@ impl Listener { } }; - loop { - match listener.accept().await { - Ok((socket, remote_addr)) => { - let handler = connection_handler.clone(); - tokio::spawn(handler.handle_connection(socket, remote_addr)); + while !self.shutdown.is_shutdown() { + tokio::select! { + connection = listener.accept() => { + match connection { + Ok((socket, remote_addr)) => { + let handler = connection_handler.clone(); + tokio::spawn(handler.handle_connection(socket, remote_addr, self.shutdown.clone())); + } + Err(err) => warn!("Failed to accept incoming connection - {:?}", err), + } + }, + _ = self.shutdown.recv() => { + log::trace!("Listener: Received shutdown"); } - Err(err) => warn!("Failed to accept incoming connection - {:?}", err), - } + }; } + log::trace!("Listener: Exiting"); } pub(crate) fn start(mut self, connection_handler: ConnectionHandler) -> JoinHandle<()> { diff --git a/mixnode/src/node/mod.rs b/mixnode/src/node/mod.rs index 27851e34bf..b107e698a3 100644 --- a/mixnode/src/node/mod.rs +++ b/mixnode/src/node/mod.rs @@ -25,6 +25,7 @@ use rand::thread_rng; use std::net::SocketAddr; use std::process; use std::sync::Arc; +use task::{ShutdownListener, ShutdownNotifier}; use version_checker::parse_version; mod http; @@ -149,11 +150,15 @@ impl MixNode { }); } - fn start_node_stats_controller(&self) -> (SharedNodeStats, node_statistics::UpdateSender) { + fn start_node_stats_controller( + &self, + shutdown: ShutdownListener, + ) -> (SharedNodeStats, node_statistics::UpdateSender) { info!("Starting node stats controller..."); let controller = node_statistics::Controller::new( self.config.get_node_stats_logging_delay(), self.config.get_node_stats_updating_delay(), + shutdown, ); let node_stats_pointer = controller.get_node_stats_data_pointer(); let update_sender = controller.start(); @@ -165,6 +170,7 @@ impl MixNode { &self, node_stats_update_sender: node_statistics::UpdateSender, delay_forwarding_channel: PacketDelayForwardSender, + shutdown: ShutdownListener, ) { info!("Starting socket listener..."); @@ -178,12 +184,13 @@ impl MixNode { self.config.get_mix_port(), ); - Listener::new(listening_address).start(connection_handler); + Listener::new(listening_address, shutdown).start(connection_handler); } fn start_packet_delay_forwarder( &mut self, node_stats_update_sender: node_statistics::UpdateSender, + shutdown: ShutdownListener, ) -> PacketDelayForwardSender { info!("Starting packet delay-forwarder..."); @@ -197,6 +204,7 @@ impl MixNode { let mut packet_forwarder = DelayForwarder::new( mixnet_client::Client::new(client_config), node_stats_update_sender, + shutdown, ); let packet_sender = packet_forwarder.sender(); @@ -259,7 +267,10 @@ impl MixNode { let existing_nodes = match validator_client.get_cached_mixnodes().await { Ok(nodes) => nodes, Err(err) => { - error!("failed to grab initial network mixnodes - {}\n Please try to startup again in few minutes", err); + error!( + "failed to grab initial network mixnodes - {err}\n \ + Please try to startup again in few minutes", + ); process::exit(1); } }; @@ -272,16 +283,26 @@ impl MixNode { .map(|node| node.mix_node.identity_key.clone()) } - async fn wait_for_interrupt(&self) { + async fn wait_for_interrupt(&self, mut shutdown: ShutdownNotifier) { if let Err(e) = tokio::signal::ctrl_c().await { error!( - "There was an error while capturing SIGINT - {:?}. We will terminate regardless", + "There was an error while capturing SIGINT - {:?}. \ + We will terminate regardless", e ); } println!( - "Received SIGINT - the mixnode will terminate now (threads are not yet nicely stopped, if you see stack traces that's alright)." + "Received SIGINT - the mixnode will terminate now \ + (threads are not yet nicely stopped, if you see stack traces that's alright)." ); + + log::info!("Sending shutdown"); + shutdown.signal_shutdown().ok(); + + log::info!("Waiting for tasks to finish... (Press ctrl-c to force)"); + shutdown.wait_for_shutdown().await; + + log::info!("Stopping nym mixnode"); } pub async fn run(&mut self) { @@ -299,15 +320,23 @@ impl MixNode { } } - let (node_stats_pointer, node_stats_update_sender) = self.start_node_stats_controller(); - let delay_forwarding_channel = - self.start_packet_delay_forwarder(node_stats_update_sender.clone()); - self.start_socket_listener(node_stats_update_sender, delay_forwarding_channel); + let shutdown = ShutdownNotifier::default(); + let (node_stats_pointer, node_stats_update_sender) = + self.start_node_stats_controller(shutdown.subscribe()); + let delay_forwarding_channel = self + .start_packet_delay_forwarder(node_stats_update_sender.clone(), shutdown.subscribe()); + self.start_socket_listener( + node_stats_update_sender, + delay_forwarding_channel, + shutdown.subscribe(), + ); + + // TODO: these two also needs to be shutdown let atomic_verloc_results = self.start_verloc_measurements(); self.start_http_api(atomic_verloc_results, node_stats_pointer); info!("Finished nym mixnode startup procedure - it should now be able to receive mix traffic!"); - self.wait_for_interrupt().await + self.wait_for_interrupt(shutdown).await } } diff --git a/mixnode/src/node/node_statistics.rs b/mixnode/src/node/node_statistics.rs index 4dc2b3a9a1..21cba5ef96 100644 --- a/mixnode/src/node/node_statistics.rs +++ b/mixnode/src/node/node_statistics.rs @@ -9,6 +9,8 @@ use std::sync::Arc; use std::time::{Duration, SystemTime}; use tokio::sync::{RwLock, RwLockReadGuard}; +use super::ShutdownListener; + // convenience aliases type PacketsMap = HashMap; type PacketDataReceiver = mpsc::UnboundedReceiver; @@ -209,28 +211,45 @@ impl CurrentPacketData { struct UpdateHandler { current_data: CurrentPacketData, update_receiver: PacketDataReceiver, + shutdown: ShutdownListener, } impl UpdateHandler { - fn new(current_data: CurrentPacketData, update_receiver: PacketDataReceiver) -> Self { + fn new( + current_data: CurrentPacketData, + update_receiver: PacketDataReceiver, + shutdown: ShutdownListener, + ) -> Self { UpdateHandler { current_data, update_receiver, + shutdown, } } async fn run(&mut self) { - while let Some(packet_data) = self.update_receiver.next().await { - match packet_data { - PacketEvent::Received => self.current_data.increment_received(), - PacketEvent::Sent(destination) => { - self.current_data.increment_sent(destination).await + log::trace!("Starting UpdateHandler"); + while !self.shutdown.is_shutdown() { + tokio::select! { + Some(packet_data) = self.update_receiver.next() => { + match packet_data { + PacketEvent::Received => self.current_data.increment_received(), + PacketEvent::Sent(destination) => { + self.current_data.increment_sent(destination).await + } + PacketEvent::Dropped(destination) => { + self.current_data.increment_dropped(destination).await + } + } } - PacketEvent::Dropped(destination) => { - self.current_data.increment_dropped(destination).await + _ = self.shutdown.recv() => { + log::trace!("UpdateHandler: Received shutdown"); + break; } } } + + log::trace!("UpdateHandler: Exiting"); } } @@ -274,6 +293,7 @@ struct StatsUpdater { updating_delay: Duration, current_packet_data: CurrentPacketData, current_stats: SharedNodeStats, + shutdown: ShutdownListener, } impl StatsUpdater { @@ -281,11 +301,13 @@ impl StatsUpdater { updating_delay: Duration, current_packet_data: CurrentPacketData, current_stats: SharedNodeStats, + shutdown: ShutdownListener, ) -> Self { StatsUpdater { updating_delay, current_packet_data, current_stats, + shutdown, } } @@ -295,11 +317,16 @@ impl StatsUpdater { self.current_stats.update(received, sent, dropped).await; } - async fn run(&self) { - loop { - tokio::time::sleep(self.updating_delay).await; - self.update_stats().await + async fn run(&mut self) { + while !self.shutdown.is_shutdown() { + tokio::select! { + _ = tokio::time::sleep(self.updating_delay) => self.update_stats().await, + _ = self.shutdown.recv() => { + log::trace!("StatsUpdater: Received shutdown"); + } + } } + log::trace!("StatsUpdater: Exiting"); } } @@ -308,13 +335,15 @@ impl StatsUpdater { struct PacketStatsConsoleLogger { logging_delay: Duration, stats: SharedNodeStats, + shutdown: ShutdownListener, } impl PacketStatsConsoleLogger { - fn new(logging_delay: Duration, stats: SharedNodeStats) -> Self { + fn new(logging_delay: Duration, stats: SharedNodeStats, shutdown: ShutdownListener) -> Self { PacketStatsConsoleLogger { logging_delay, stats, + shutdown, } } @@ -387,10 +416,16 @@ impl PacketStatsConsoleLogger { } async fn run(&mut self) { - loop { - tokio::time::sleep(self.logging_delay).await; - self.log_running_stats().await; + log::trace!("Starting PacketStatsConsoleLogger"); + while !self.shutdown.is_shutdown() { + tokio::select! { + _ = tokio::time::sleep(self.logging_delay) => self.log_running_stats().await, + _ = self.shutdown.recv() => { + log::trace!("PacketStatsConsoleLogger: Received shutdown"); + } + }; } + log::trace!("PacketStatsConsoleLogger: Exiting"); } } @@ -413,19 +448,32 @@ pub struct Controller { } impl Controller { - pub(crate) fn new(logging_delay: Duration, stats_updating_delay: Duration) -> Self { + pub(crate) fn new( + logging_delay: Duration, + stats_updating_delay: Duration, + shutdown: ShutdownListener, + ) -> Self { let (sender, receiver) = mpsc::unbounded(); let shared_packet_data = CurrentPacketData::new(); let shared_node_stats = SharedNodeStats::new(); Controller { - update_handler: UpdateHandler::new(shared_packet_data.clone(), receiver), + update_handler: UpdateHandler::new( + shared_packet_data.clone(), + receiver, + shutdown.clone(), + ), update_sender: UpdateSender::new(sender), - console_logger: PacketStatsConsoleLogger::new(logging_delay, shared_node_stats.clone()), + console_logger: PacketStatsConsoleLogger::new( + logging_delay, + shared_node_stats.clone(), + shutdown.clone(), + ), stats_updater: StatsUpdater::new( stats_updating_delay, shared_packet_data, shared_node_stats.clone(), + shutdown, ), node_stats: shared_node_stats, } @@ -441,7 +489,7 @@ impl Controller { pub(crate) fn start(self) -> UpdateSender { // move out of self let mut update_handler = self.update_handler; - let stats_updater = self.stats_updater; + let mut stats_updater = self.stats_updater; let mut console_logger = self.console_logger; tokio::spawn(async move { update_handler.run().await }); @@ -455,12 +503,15 @@ impl Controller { #[cfg(test)] mod tests { use super::*; + use task::ShutdownNotifier; #[tokio::test] async fn node_stats_reported_are_received() { let logging_delay = Duration::from_millis(20); let stats_updating_delay = Duration::from_millis(10); - let node_stats_controller = Controller::new(logging_delay, stats_updating_delay); + let shutdown = ShutdownNotifier::default(); + let node_stats_controller = + Controller::new(logging_delay, stats_updating_delay, shutdown.subscribe()); let node_stats_pointer = node_stats_controller.get_node_stats_data_pointer(); let update_sender = node_stats_controller.start(); diff --git a/mixnode/src/node/packet_delayforwarder.rs b/mixnode/src/node/packet_delayforwarder.rs index e0aece8fcb..9be8175bed 100644 --- a/mixnode/src/node/packet_delayforwarder.rs +++ b/mixnode/src/node/packet_delayforwarder.rs @@ -9,6 +9,8 @@ use nymsphinx::forwarding::packet::MixPacket; use std::io; use tokio::time::Instant; +use super::ShutdownListener; + // Delay + MixPacket vs Instant + MixPacket // rather than using Duration directly, we use an Instant, this way we minimise skew due to @@ -26,13 +28,18 @@ where packet_sender: PacketDelayForwardSender, packet_receiver: PacketDelayForwardReceiver, node_stats_update_sender: UpdateSender, + shutdown: ShutdownListener, } impl DelayForwarder where C: mixnet_client::SendWithoutResponse, { - pub(crate) fn new(client: C, node_stats_update_sender: UpdateSender) -> DelayForwarder { + pub(crate) fn new( + client: C, + node_stats_update_sender: UpdateSender, + shutdown: ShutdownListener, + ) -> DelayForwarder { let (packet_sender, packet_receiver) = mpsc::unbounded(); DelayForwarder:: { @@ -41,6 +48,7 @@ where packet_sender, packet_receiver, node_stats_update_sender, + shutdown, } } @@ -97,6 +105,7 @@ where } pub(crate) async fn run(&mut self) { + log::trace!("Starting DelayForwarder"); loop { tokio::select! { delayed = self.delay_queue.next() => { @@ -107,8 +116,13 @@ where // and hence it can't happen that ALL senders are dropped self.handle_new_packet(new_packet.unwrap()) } + _ = self.shutdown.recv() => { + log::trace!("DelayForwarder: Received shutdown"); + break; + } } } + log::trace!("DelayForwarder: Exiting"); } } @@ -120,6 +134,8 @@ mod tests { use std::sync::{Arc, Mutex}; use std::time::Duration; + use task::ShutdownNotifier; + use nymsphinx::addressing::nodes::NymNodeRoutingAddress; use nymsphinx_params::packet_sizes::PacketSize; use nymsphinx_params::PacketMode; @@ -189,7 +205,9 @@ mod tests { let node_stats_update_sender = UpdateSender::new(stats_sender); let client = TestClient::default(); let client_packets_sent = client.packets_sent.clone(); - let mut delay_forwarder = DelayForwarder::new(client, node_stats_update_sender); + let shutdown = ShutdownNotifier::default(); + let mut delay_forwarder = + DelayForwarder::new(client, node_stats_update_sender, shutdown.subscribe()); let packet_sender = delay_forwarder.sender(); // Spawn the worker, listening on packet_sender channel From 24d3089458465d50d5c81fbcdce857ae91faf9cc Mon Sep 17 00:00:00 2001 From: gala1234 Date: Tue, 7 Jun 2022 13:14:16 +0200 Subject: [PATCH 16/25] Adding discord icon --- explorer/src/components/Socials.tsx | 11 ++++------- 1 file changed, 4 insertions(+), 7 deletions(-) diff --git a/explorer/src/components/Socials.tsx b/explorer/src/components/Socials.tsx index ded74ffe98..f359a24ac1 100644 --- a/explorer/src/components/Socials.tsx +++ b/explorer/src/components/Socials.tsx @@ -10,7 +10,7 @@ import { DiscordIcon } from '../icons/socials/DiscordIcon'; export const TELEGRAM_LINK = 'https://t.me/nymchan'; export const TWITTER_LINK = 'https://twitter.com/nymproject'; export const GITHUB_LINK = 'https://github.com/nymtech'; -export const DISCORD_LINK = 'https://discord.gg/ggxrUpbNnn'; +export const DISCORD_LINK = 'https://discord.gg/nym'; export const Socials: React.FC<{ isFooter?: boolean }> = ({ isFooter }) => { const theme = useTheme(); @@ -22,12 +22,9 @@ export const Socials: React.FC<{ isFooter?: boolean }> = ({ isFooter }) => { - {false && ( - - - - )} - + + + From d5c456a3708f5d8a335c73ba62f2e16fc4c359ec Mon Sep 17 00:00:00 2001 From: =?UTF-8?q?Jon=20H=C3=A4ggblad?= Date: Tue, 7 Jun 2022 13:16:00 +0200 Subject: [PATCH 17/25] wallet: additional wallet test (#1312) --- .../src/operations/mixnet/account.rs | 45 ++++++++++++++++++- 1 file changed, 44 insertions(+), 1 deletion(-) diff --git a/nym-wallet/src-tauri/src/operations/mixnet/account.rs b/nym-wallet/src-tauri/src/operations/mixnet/account.rs index 5e0215cf71..31c45f21c6 100644 --- a/nym-wallet/src-tauri/src/operations/mixnet/account.rs +++ b/nym-wallet/src-tauri/src/operations/mixnet/account.rs @@ -679,8 +679,51 @@ mod tests { ); } + // This decryptes a stored wallet file using the same procedure as when signing in. Most tests + // related to the encryped wallet storage is in `wallet_storage`. #[test] fn decrypt_stored_wallet_multiple_for_sign_in() { - // WIP(JON): same as above but with file containing multiple accounts + const SAVED_WALLET: &str = "src/wallet_storage/test-data/saved-wallet-1.0.5.json"; + let wallet_file = PathBuf::from(env!("CARGO_MANIFEST_DIR")).join(SAVED_WALLET); + let login_id = wallet_storage::LoginId::new(DEFAULT_LOGIN_ID.to_string()); + let account_id = wallet_storage::AccountId::new("default".to_string()); + let password = wallet_storage::UserPassword::new("password11!".to_string()); + let hd_path: DerivationPath = COSMOS_DERIVATION_PATH.parse().unwrap(); + + let stored_login = + wallet_storage::load_existing_login_at_file(&wallet_file, &login_id, &password) + .unwrap(); + let mnemonic = extract_first_mnemonic(&stored_login).unwrap(); + + let expected_mnemonic = bip39::Mnemonic::from_str("arrow capable abstract industry elevator nominee december piece hotel feed lounge web faint sword veteran bundle hour page actual laptop horror gold test warrior").unwrap(); + assert_eq!(mnemonic, expected_mnemonic); + + let all_accounts: Vec<_> = stored_login + .unwrap_into_multiple_accounts(account_id.clone()) + .into_accounts() + .collect(); + + let expected_mn2 = bip39::Mnemonic::from_str("border hurt skull lunar goddess second danger game dismiss exhaust oven thumb dog drama onion false orchard spice tent next predict invite cherry green").unwrap(); + let expected_mn3 = bip39::Mnemonic::from_str("gentle crowd rule snap girl urge flat jump winner cluster night sand museum stock grunt quick tree acquire traffic major awake tag rack peasant").unwrap(); + let expected_mn4 = bip39::Mnemonic::from_str("debris blue skin annual inhale text border rigid spatial lesson coconut yard horn crystal control survey version vote hawk neck frame arrive oblige width").unwrap(); + + assert_eq!( + all_accounts, + vec![ + WalletAccount::new( + "default".into(), + MnemonicAccount::new(expected_mnemonic, hd_path.clone()) + ), + WalletAccount::new( + "account2".into(), + MnemonicAccount::new(expected_mn2, hd_path.clone()), + ), + WalletAccount::new( + "foobar".into(), + MnemonicAccount::new(expected_mn3, hd_path.clone()), + ), + WalletAccount::new("42".into(), MnemonicAccount::new(expected_mn4, hd_path)), + ] + ); } } From ca16dc6d66aa0a2ea78ee689f0649a3bbfcbed60 Mon Sep 17 00:00:00 2001 From: gala1234 Date: Tue, 7 Jun 2022 13:17:15 +0200 Subject: [PATCH 18/25] Revert "Adding discord icon" This reverts commit 24d3089458465d50d5c81fbcdce857ae91faf9cc. --- explorer/src/components/Socials.tsx | 11 +++++++---- 1 file changed, 7 insertions(+), 4 deletions(-) diff --git a/explorer/src/components/Socials.tsx b/explorer/src/components/Socials.tsx index f359a24ac1..ded74ffe98 100644 --- a/explorer/src/components/Socials.tsx +++ b/explorer/src/components/Socials.tsx @@ -10,7 +10,7 @@ import { DiscordIcon } from '../icons/socials/DiscordIcon'; export const TELEGRAM_LINK = 'https://t.me/nymchan'; export const TWITTER_LINK = 'https://twitter.com/nymproject'; export const GITHUB_LINK = 'https://github.com/nymtech'; -export const DISCORD_LINK = 'https://discord.gg/nym'; +export const DISCORD_LINK = 'https://discord.gg/ggxrUpbNnn'; export const Socials: React.FC<{ isFooter?: boolean }> = ({ isFooter }) => { const theme = useTheme(); @@ -22,9 +22,12 @@ export const Socials: React.FC<{ isFooter?: boolean }> = ({ isFooter }) => { - - - + {false && ( + + + + )} + From f655a9d8c640befaa025dbb960745f5ba9bf504c Mon Sep 17 00:00:00 2001 From: =?UTF-8?q?Bogdan-=C8=98tefan=20Neac=C5=9Fu?= Date: Tue, 7 Jun 2022 14:44:48 +0300 Subject: [PATCH 19/25] Replace default network with provided network (#1317) --- common/client-libs/validator-client/src/nymd/mod.rs | 10 +++++----- 1 file changed, 5 insertions(+), 5 deletions(-) diff --git a/common/client-libs/validator-client/src/nymd/mod.rs b/common/client-libs/validator-client/src/nymd/mod.rs index e680a57e6a..3c79bf1f6c 100644 --- a/common/client-libs/validator-client/src/nymd/mod.rs +++ b/common/client-libs/validator-client/src/nymd/mod.rs @@ -189,23 +189,23 @@ impl NymdClient { client: SigningNymdClient::connect_with_signer(endpoint, wallet, gas_price)?, client_address: Some(client_address), simulated_gas_multiplier: DEFAULT_SIMULATED_GAS_MULTIPLIER, - mixnet_contract_address: DEFAULT_NETWORK + mixnet_contract_address: network .mixnet_contract_address() .parse() .expect("Error parsing mixnet contract address"), - vesting_contract_address: DEFAULT_NETWORK + vesting_contract_address: network .vesting_contract_address() .parse() .expect("Error parsing vesting contract address"), - bandwidth_claim_contract_address: DEFAULT_NETWORK + bandwidth_claim_contract_address: network .bandwidth_claim_contract_address() .parse() .expect("Error parsing bandwidth claim contract address"), - coconut_bandwidth_contract_address: DEFAULT_NETWORK + coconut_bandwidth_contract_address: network .coconut_bandwidth_contract_address() .parse() .unwrap(), - multisig_contract_address: DEFAULT_NETWORK.multisig_contract_address().parse().unwrap(), + multisig_contract_address: network.multisig_contract_address().parse().unwrap(), }) } } From c13d3ab15d027756b22709a52e4b080e2749630a Mon Sep 17 00:00:00 2001 From: =?UTF-8?q?J=C4=99drzej=20Stuczy=C5=84ski?= Date: Tue, 7 Jun 2022 12:55:10 +0100 Subject: [PATCH 20/25] Updated cosmwasm dependencies to 1.0.0 (#1318) * Updated cosmwasm dependencies to 1.0.0 * changelog --- CHANGELOG.md | 4 + Cargo.lock | 144 ++++------------ .../client-libs/validator-client/Cargo.toml | 2 +- .../coconut-bandwidth-contract/Cargo.toml | 2 +- .../contracts-common/Cargo.toml | 2 +- .../mixnet-contract/Cargo.toml | 2 +- .../multisig-contract/Cargo.toml | 2 +- .../vesting-contract/Cargo.toml | 4 +- contracts/Cargo.lock | 121 ++++++++----- contracts/bandwidth-claim/Cargo.toml | 4 +- contracts/coconut-bandwidth/Cargo.toml | 8 +- contracts/mixnet/Cargo.toml | 8 +- .../multisig/cw3-flex-multisig/Cargo.toml | 4 +- contracts/multisig/cw4-group/Cargo.toml | 4 +- contracts/vesting/Cargo.toml | 4 +- nym-wallet/Cargo.lock | 162 +++++------------- nym-wallet/src-tauri/Cargo.toml | 2 +- validator-api/Cargo.toml | 2 +- 18 files changed, 181 insertions(+), 300 deletions(-) diff --git a/CHANGELOG.md b/CHANGELOG.md index 29771fda42..5082f33fad 100644 --- a/CHANGELOG.md +++ b/CHANGELOG.md @@ -1,5 +1,7 @@ # Changelog +Post 1.0.0 release, the changelog format is based on [Keep a Changelog](https://keepachangelog.com/en/1.0.0/), and this project adheres to [Semantic Versioning](https://semver.org/spec/v2.0.0.html). + ## [Unreleased] ### Added @@ -35,6 +37,7 @@ ### Changed - validator-client: created internal `Coin` type that replaces coins from `cosmrs` and `cosmwasm` for API entrypoints [[#1295]] +- all: updated all `cosmwasm`-related dependencies to `1.0.0` and `cw-storage-plus` to `0.13.4` [[#1318]] [#1249]: https://github.com/nymtech/nym/pull/1249 [#1256]: https://github.com/nymtech/nym/pull/1256 @@ -50,6 +53,7 @@ [#1292]: https://github.com/nymtech/nym/pull/1292 [#1295]: https://github.com/nymtech/nym/pull/1295 [#1302]: https://github.com/nymtech/nym/pull/1302 +[#1318]: https://github.com/nymtech/nym/pull/1318 ## [nym-wallet-v1.0.4](https://github.com/nymtech/nym/tree/nym-wallet-v1.0.4) (2022-05-04) diff --git a/Cargo.lock b/Cargo.lock index 5542e148d0..363273a699 100644 --- a/Cargo.lock +++ b/Cargo.lock @@ -245,7 +245,7 @@ checksum = "873faa4363bfc54c36a48321da034c92a0645a363eed34d948683ffc1706e37f" dependencies = [ "bs58", "hmac 0.11.0", - "k256 0.10.4", + "k256", "once_cell", "pbkdf2", "rand_core 0.6.3", @@ -695,12 +695,6 @@ dependencies = [ "tracing-subscriber", ] -[[package]] -name = "const-oid" -version = "0.6.2" -source = "registry+https://github.com/rust-lang/crates.io-index" -checksum = "9d6f2aa4d0537bcc1c74df8755072bd31c1ef1a3a1b85a68e8404a8c353b7b8b" - [[package]] name = "const-oid" version = "0.7.1" @@ -778,10 +772,10 @@ checksum = "8413275b23cb5a0734d9d1e3e33f0b5b94547c1e94776dbc3149dbf46588a533" dependencies = [ "bip32", "cosmos-sdk-proto", - "ecdsa 0.13.4", + "ecdsa", "eyre", "getrandom 0.2.6", - "k256 0.10.4", + "k256", "prost 0.10.3", "prost-types 0.10.1", "rand_core 0.6.3", @@ -795,31 +789,31 @@ dependencies = [ [[package]] name = "cosmwasm-crypto" -version = "1.0.0-beta8" +version = "1.0.0" source = "registry+https://github.com/rust-lang/crates.io-index" -checksum = "37e70111e9701c3ec43bfbff0e523cd4cb115876b4d3433813436dd0934ee962" +checksum = "5eb0afef2325df81aadbf9be1233f522ed8f6e91df870c764bc44cca2b1415bd" dependencies = [ "digest 0.9.0", "ed25519-zebra", - "k256 0.9.6", + "k256", "rand_core 0.6.3", "thiserror", ] [[package]] name = "cosmwasm-derive" -version = "1.0.0-beta8" +version = "1.0.0" source = "registry+https://github.com/rust-lang/crates.io-index" -checksum = "58bc2ad5d86be5f6068833f63e20786768db6890019c095dd7775232184fb7b3" +checksum = "4b36e527620a2a3e00e46b6e731ab6c9b68d11069c986f7d7be8eba79ef081a4" dependencies = [ "syn", ] [[package]] name = "cosmwasm-std" -version = "1.0.0-beta8" +version = "1.0.0" source = "registry+https://github.com/rust-lang/crates.io-index" -checksum = "915ca82bd944f116f3a9717481f3fa657e4a73f28c4887288761ebb24e6fbe10" +checksum = "875994993c2082a6fcd406937bf0fca21c349e4a624f3810253a14fa83a3a195" dependencies = [ "base64", "cosmwasm-crypto", @@ -1037,18 +1031,6 @@ dependencies = [ "x25519-dalek", ] -[[package]] -name = "crypto-bigint" -version = "0.2.11" -source = "registry+https://github.com/rust-lang/crates.io-index" -checksum = "f83bd3bb4314701c568e340cd8cf78c975aa0ca79e03d3f6d1677d5b0c9c0c03" -dependencies = [ - "generic-array 0.14.5", - "rand_core 0.6.3", - "subtle 2.4.1", - "zeroize", -] - [[package]] name = "crypto-bigint" version = "0.3.2" @@ -1156,9 +1138,9 @@ dependencies = [ [[package]] name = "cw-storage-plus" -version = "0.13.2" +version = "0.13.4" source = "registry+https://github.com/rust-lang/crates.io-index" -checksum = "9336ecef1e19d56cf6e3e932475fc6a3dee35eec5a386e07917a1d1ba6bb0e35" +checksum = "648b1507290bbc03a8d88463d7cd9b04b1fa0155e5eef366c4fa052b9caaac7a" dependencies = [ "cosmwasm-std", "schemars", @@ -1246,22 +1228,13 @@ dependencies = [ "num_cpus", ] -[[package]] -name = "der" -version = "0.4.5" -source = "registry+https://github.com/rust-lang/crates.io-index" -checksum = "79b71cca7d95d7681a4b3b9cdf63c8dbc3730d0584c2c74e31416d64a90493f4" -dependencies = [ - "const-oid 0.6.2", -] - [[package]] name = "der" version = "0.5.1" source = "registry+https://github.com/rust-lang/crates.io-index" checksum = "6919815d73839e7ad218de758883aae3a257ba6759ce7a9992501efbb53d705c" dependencies = [ - "const-oid 0.7.1", + "const-oid", ] [[package]] @@ -1404,26 +1377,14 @@ version = "1.0.5" source = "registry+https://github.com/rust-lang/crates.io-index" checksum = "21e50f3adc76d6a43f5ed73b698a87d0760ca74617f60f7c3b879003536fdd28" -[[package]] -name = "ecdsa" -version = "0.12.4" -source = "registry+https://github.com/rust-lang/crates.io-index" -checksum = "43ee23aa5b4f68c7a092b5c3beb25f50c406adc75e2363634f242f28ab255372" -dependencies = [ - "der 0.4.5", - "elliptic-curve 0.10.6", - "hmac 0.11.0", - "signature", -] - [[package]] name = "ecdsa" version = "0.13.4" source = "registry+https://github.com/rust-lang/crates.io-index" checksum = "d0d69ae62e0ce582d56380743515fefaf1a8c70cec685d9677636d7e30ae9dc9" dependencies = [ - "der 0.5.1", - "elliptic-curve 0.11.12", + "der", + "elliptic-curve", "rfc6979", "signature", ] @@ -1474,22 +1435,6 @@ version = "1.6.1" source = "registry+https://github.com/rust-lang/crates.io-index" checksum = "e78d4f1cc4ae33bbfc157ed5d5a5ef3bc29227303d595861deb238fcec4e9457" -[[package]] -name = "elliptic-curve" -version = "0.10.6" -source = "registry+https://github.com/rust-lang/crates.io-index" -checksum = "beca177dcb8eb540133e7680baff45e7cc4d93bf22002676cec549f82343721b" -dependencies = [ - "crypto-bigint 0.2.11", - "ff 0.10.1", - "generic-array 0.14.5", - "group 0.10.0", - "pkcs8 0.7.6", - "rand_core 0.6.3", - "subtle 2.4.1", - "zeroize", -] - [[package]] name = "elliptic-curve" version = "0.11.12" @@ -1497,8 +1442,8 @@ source = "registry+https://github.com/rust-lang/crates.io-index" checksum = "25b477563c2bfed38a3b7a60964c49e058b2510ad3f12ba3483fd8f62c2306d6" dependencies = [ "base16ct", - "crypto-bigint 0.3.2", - "der 0.5.1", + "crypto-bigint", + "der", "ff 0.11.0", "generic-array 0.14.5", "group 0.11.0", @@ -2641,18 +2586,6 @@ dependencies = [ "serde_json", ] -[[package]] -name = "k256" -version = "0.9.6" -source = "registry+https://github.com/rust-lang/crates.io-index" -checksum = "903ae2481bcdfdb7b68e0a9baa4b7c9aff600b9ae2e8e5bb5833b8c91ab851ea" -dependencies = [ - "cfg-if 1.0.0", - "ecdsa 0.12.4", - "elliptic-curve 0.10.6", - "sha2", -] - [[package]] name = "k256" version = "0.10.4" @@ -2660,8 +2593,8 @@ source = "registry+https://github.com/rust-lang/crates.io-index" checksum = "19c3a5e0a0b8450278feda242592512e09f61c72e018b8cd5c859482802daf2d" dependencies = [ "cfg-if 1.0.0", - "ecdsa 0.13.4", - "elliptic-curve 0.11.12", + "ecdsa", + "elliptic-curve", "sec1", "sha2", "sha3", @@ -3813,24 +3746,14 @@ version = "0.1.0" source = "registry+https://github.com/rust-lang/crates.io-index" checksum = "8b870d8c151b6f2fb93e84a13146138f05d02ed11c7e7c54f8826aaaf7c9f184" -[[package]] -name = "pkcs8" -version = "0.7.6" -source = "registry+https://github.com/rust-lang/crates.io-index" -checksum = "ee3ef9b64d26bad0536099c816c6734379e45bbd5f14798def6809e5cc350447" -dependencies = [ - "der 0.4.5", - "spki 0.4.1", -] - [[package]] name = "pkcs8" version = "0.8.0" source = "registry+https://github.com/rust-lang/crates.io-index" checksum = "7cabda3fb821068a9a4fab19a683eac3af12edf0f34b94a8be53c4972b8149d0" dependencies = [ - "der 0.5.1", - "spki 0.5.4", + "der", + "spki", "zeroize", ] @@ -4455,7 +4378,7 @@ version = "0.1.0" source = "registry+https://github.com/rust-lang/crates.io-index" checksum = "96ef608575f6392792f9ecf7890c00086591d29a83910939d430753f7c050525" dependencies = [ - "crypto-bigint 0.3.2", + "crypto-bigint", "hmac 0.11.0", "zeroize", ] @@ -4788,9 +4711,9 @@ version = "0.2.1" source = "registry+https://github.com/rust-lang/crates.io-index" checksum = "08da66b8b0965a5555b6bd6639e68ccba85e1e2506f5fbb089e93f8a04e1a2d1" dependencies = [ - "der 0.5.1", + "der", "generic-array 0.14.5", - "pkcs8 0.8.0", + "pkcs8", "subtle 2.4.1", "zeroize", ] @@ -4892,9 +4815,9 @@ dependencies = [ [[package]] name = "serde-json-wasm" -version = "0.3.2" +version = "0.4.1" source = "registry+https://github.com/rust-lang/crates.io-index" -checksum = "042ac496d97e5885149d34139bad1d617192770d7eb8f1866da2317ff4501853" +checksum = "479b4dbc401ca13ee8ce902851b834893251404c4f3c65370a49e047a6be09a5" dependencies = [ "serde", ] @@ -5241,15 +5164,6 @@ dependencies = [ "lock_api", ] -[[package]] -name = "spki" -version = "0.4.1" -source = "registry+https://github.com/rust-lang/crates.io-index" -checksum = "5c01a0c15da1b0b0e1494112e7af814a678fec9bd157881b49beac661e9b6f32" -dependencies = [ - "der 0.4.5", -] - [[package]] name = "spki" version = "0.5.4" @@ -5257,7 +5171,7 @@ source = "registry+https://github.com/rust-lang/crates.io-index" checksum = "44d01ac02a6ccf3e07db148d2be087da624fea0221a16152ed01f0496a6b0a27" dependencies = [ "base64ct", - "der 0.5.1", + "der", ] [[package]] @@ -5516,7 +5430,7 @@ version = "0.1.0" dependencies = [ "log", "tokio", - "tokio-util 0.6.9", + "tokio-util 0.7.3", ] [[package]] @@ -5545,7 +5459,7 @@ dependencies = [ "ed25519-dalek", "flex-error", "futures", - "k256 0.10.4", + "k256", "num-traits", "once_cell", "prost 0.10.3", diff --git a/common/client-libs/validator-client/Cargo.toml b/common/client-libs/validator-client/Cargo.toml index e69699d36b..10322feda7 100644 --- a/common/client-libs/validator-client/Cargo.toml +++ b/common/client-libs/validator-client/Cargo.toml @@ -40,7 +40,7 @@ prost = { version = "0.10", default-features = false, optional = true } flate2 = { version = "1.0.20", optional = true } sha2 = { version = "0.9.5", optional = true } itertools = { version = "0.10", optional = true } -cosmwasm-std = { version = "1.0.0-beta8", optional = true } +cosmwasm-std = { version = "1.0.0", optional = true } execute = { path = "../../execute" } [dev-dependencies] diff --git a/common/cosmwasm-smart-contracts/coconut-bandwidth-contract/Cargo.toml b/common/cosmwasm-smart-contracts/coconut-bandwidth-contract/Cargo.toml index 5baf73bff6..12b802d3b8 100644 --- a/common/cosmwasm-smart-contracts/coconut-bandwidth-contract/Cargo.toml +++ b/common/cosmwasm-smart-contracts/coconut-bandwidth-contract/Cargo.toml @@ -6,6 +6,6 @@ edition = "2021" # See more keys and their definitions at https://doc.rust-lang.org/cargo/reference/manifest.html [dependencies] -cosmwasm-std = "1.0.0-beta6" +cosmwasm-std = "1.0.0" schemars = "0.8" serde = { version = "1.0.103", default-features = false, features = ["derive"] } diff --git a/common/cosmwasm-smart-contracts/contracts-common/Cargo.toml b/common/cosmwasm-smart-contracts/contracts-common/Cargo.toml index 03b05b438a..a7e383db64 100644 --- a/common/cosmwasm-smart-contracts/contracts-common/Cargo.toml +++ b/common/cosmwasm-smart-contracts/contracts-common/Cargo.toml @@ -7,4 +7,4 @@ edition = "2021" # See more keys and their definitions at https://doc.rust-lang.org/cargo/reference/manifest.html [dependencies] -cosmwasm-std = "1.0.0-beta8" +cosmwasm-std = "1.0.0" diff --git a/common/cosmwasm-smart-contracts/mixnet-contract/Cargo.toml b/common/cosmwasm-smart-contracts/mixnet-contract/Cargo.toml index d4171283f3..3cc065da7e 100644 --- a/common/cosmwasm-smart-contracts/mixnet-contract/Cargo.toml +++ b/common/cosmwasm-smart-contracts/mixnet-contract/Cargo.toml @@ -7,7 +7,7 @@ edition = "2021" # See more keys and their definitions at https://doc.rust-lang.org/cargo/reference/manifest.html [dependencies] -cosmwasm-std = "1.0.0-beta8" +cosmwasm-std = "1.0.0" serde = { version = "1.0", features = ["derive"] } serde_repr = "0.1" diff --git a/common/cosmwasm-smart-contracts/multisig-contract/Cargo.toml b/common/cosmwasm-smart-contracts/multisig-contract/Cargo.toml index c7437e4a6d..2a063367ba 100644 --- a/common/cosmwasm-smart-contracts/multisig-contract/Cargo.toml +++ b/common/cosmwasm-smart-contracts/multisig-contract/Cargo.toml @@ -9,6 +9,6 @@ edition = "2021" cw-utils = { version = "0.13.1" } cw3 = { version = "0.13.1" } cw4 = { version = "0.13.1" } -cosmwasm-std = "1.0.0-beta6" +cosmwasm-std = "1.0.0" schemars = "0.8" serde = { version = "1.0.103", default-features = false, features = ["derive"] } \ No newline at end of file diff --git a/common/cosmwasm-smart-contracts/vesting-contract/Cargo.toml b/common/cosmwasm-smart-contracts/vesting-contract/Cargo.toml index 3f1c40dfa1..ede76f5998 100644 --- a/common/cosmwasm-smart-contracts/vesting-contract/Cargo.toml +++ b/common/cosmwasm-smart-contracts/vesting-contract/Cargo.toml @@ -6,11 +6,11 @@ edition = "2021" # See more keys and their definitions at https://doc.rust-lang.org/cargo/reference/manifest.html [dependencies] -cosmwasm-std = "1.0.0-beta8" +cosmwasm-std = "1.0.0" mixnet-contract-common = { path = "../mixnet-contract" } serde = { version = "1.0", features = ["derive"] } schemars = "0.8" -cw-storage-plus = "0.13.2" +cw-storage-plus = "0.13.4" config = { path = "../../config" } [dev-dependencies] diff --git a/contracts/Cargo.lock b/contracts/Cargo.lock index 055efa78b3..1fca87b909 100644 --- a/contracts/Cargo.lock +++ b/contracts/Cargo.lock @@ -60,12 +60,24 @@ dependencies = [ "serde", ] +[[package]] +name = "base16ct" +version = "0.1.1" +source = "registry+https://github.com/rust-lang/crates.io-index" +checksum = "349a06037c7bf932dd7e7d1f653678b2038b9ad46a74102f1fc7bd7872678cce" + [[package]] name = "base64" version = "0.13.0" source = "registry+https://github.com/rust-lang/crates.io-index" checksum = "904dfeac50f3cdaba28fc6f57fdcddb75f49ed61346676a78c4ffe55877802fd" +[[package]] +name = "base64ct" +version = "1.5.0" +source = "registry+https://github.com/rust-lang/crates.io-index" +checksum = "dea908e7347a8c64e378c17e30ef880ad73e3b4498346b055c2c00ea342f3179" + [[package]] name = "bitflags" version = "1.3.2" @@ -239,9 +251,9 @@ dependencies = [ [[package]] name = "const-oid" -version = "0.6.2" +version = "0.7.1" source = "registry+https://github.com/rust-lang/crates.io-index" -checksum = "9d6f2aa4d0537bcc1c74df8755072bd31c1ef1a3a1b85a68e8404a8c353b7b8b" +checksum = "e4c78c047431fee22c1a7bb92e00ad095a02a983affe4d8a72e2a2c62c1b94f3" [[package]] name = "contracts-common" @@ -252,9 +264,9 @@ dependencies = [ [[package]] name = "cosmwasm-crypto" -version = "1.0.0-beta8" +version = "1.0.0" source = "registry+https://github.com/rust-lang/crates.io-index" -checksum = "37e70111e9701c3ec43bfbff0e523cd4cb115876b4d3433813436dd0934ee962" +checksum = "5eb0afef2325df81aadbf9be1233f522ed8f6e91df870c764bc44cca2b1415bd" dependencies = [ "digest 0.9.0", "ed25519-zebra", @@ -265,18 +277,18 @@ dependencies = [ [[package]] name = "cosmwasm-derive" -version = "1.0.0-beta8" +version = "1.0.0" source = "registry+https://github.com/rust-lang/crates.io-index" -checksum = "58bc2ad5d86be5f6068833f63e20786768db6890019c095dd7775232184fb7b3" +checksum = "4b36e527620a2a3e00e46b6e731ab6c9b68d11069c986f7d7be8eba79ef081a4" dependencies = [ "syn", ] [[package]] name = "cosmwasm-schema" -version = "1.0.0-beta7" +version = "1.0.0" source = "registry+https://github.com/rust-lang/crates.io-index" -checksum = "63f79866e7b2190b6b6cb06959e308183c8d9511a8530f7292073f3cddc963db" +checksum = "772e80bbad231a47a2068812b723a1ff81dd4a0d56c9391ac748177bea3a61da" dependencies = [ "schemars", "serde_json", @@ -284,9 +296,9 @@ dependencies = [ [[package]] name = "cosmwasm-std" -version = "1.0.0-beta8" +version = "1.0.0" source = "registry+https://github.com/rust-lang/crates.io-index" -checksum = "915ca82bd944f116f3a9717481f3fa657e4a73f28c4887288761ebb24e6fbe10" +checksum = "875994993c2082a6fcd406937bf0fca21c349e4a624f3810253a14fa83a3a195" dependencies = [ "base64", "cosmwasm-crypto", @@ -301,9 +313,9 @@ dependencies = [ [[package]] name = "cosmwasm-storage" -version = "1.0.0-beta8" +version = "1.0.0" source = "registry+https://github.com/rust-lang/crates.io-index" -checksum = "1c4be9fd8c9d3ae7d0c32a925ecbc20707007ce0cba1f7538c0d78b7a2d3729b" +checksum = "d18403b07304d15d304dad11040d45bbcaf78d603b4be3fb5e2685c16f9229b5" dependencies = [ "cosmwasm-std", "serde", @@ -340,9 +352,9 @@ dependencies = [ [[package]] name = "crypto-bigint" -version = "0.2.11" +version = "0.3.2" source = "registry+https://github.com/rust-lang/crates.io-index" -checksum = "f83bd3bb4314701c568e340cd8cf78c975aa0ca79e03d3f6d1677d5b0c9c0c03" +checksum = "03c6a1d5fa1de37e071642dfa44ec552ca5b299adb128fab16138e24b548fd21" dependencies = [ "generic-array 0.14.5", "rand_core 0.6.3", @@ -394,9 +406,9 @@ dependencies = [ [[package]] name = "cw-controllers" -version = "0.13.2" +version = "0.13.4" source = "registry+https://github.com/rust-lang/crates.io-index" -checksum = "1bc6d042b14823b0e9f33f5cdd67a1eb9b16a7d79f7547b1a73c8870b518b97b" +checksum = "4f0bc6019b4d3d81e11f5c384bcce7173e2210bd654d75c6c9668e12cca05dfa" dependencies = [ "cosmwasm-std", "cw-storage-plus", @@ -427,9 +439,9 @@ dependencies = [ [[package]] name = "cw-storage-plus" -version = "0.13.2" +version = "0.13.4" source = "registry+https://github.com/rust-lang/crates.io-index" -checksum = "9336ecef1e19d56cf6e3e932475fc6a3dee35eec5a386e07917a1d1ba6bb0e35" +checksum = "648b1507290bbc03a8d88463d7cd9b04b1fa0155e5eef366c4fa052b9caaac7a" dependencies = [ "cosmwasm-std", "schemars", @@ -438,9 +450,9 @@ dependencies = [ [[package]] name = "cw-utils" -version = "0.13.2" +version = "0.13.4" source = "registry+https://github.com/rust-lang/crates.io-index" -checksum = "babd2c090f39d07ce5bf2556962305e795daa048ce20a93709eb591476e4a29e" +checksum = "9dbaecb78c8e8abfd6b4258c7f4fbeb5c49a5e45ee4d910d3240ee8e1d714e1b" dependencies = [ "cosmwasm-std", "schemars", @@ -538,9 +550,9 @@ dependencies = [ [[package]] name = "der" -version = "0.4.5" +version = "0.5.1" source = "registry+https://github.com/rust-lang/crates.io-index" -checksum = "79b71cca7d95d7681a4b3b9cdf63c8dbc3730d0584c2c74e31416d64a90493f4" +checksum = "6919815d73839e7ad218de758883aae3a257ba6759ce7a9992501efbb53d705c" dependencies = [ "const-oid", ] @@ -582,13 +594,13 @@ checksum = "ee2626afccd7561a06cf1367e2950c4718ea04565e20fb5029b6c7d8ad09abcf" [[package]] name = "ecdsa" -version = "0.12.4" +version = "0.13.4" source = "registry+https://github.com/rust-lang/crates.io-index" -checksum = "43ee23aa5b4f68c7a092b5c3beb25f50c406adc75e2363634f242f28ab255372" +checksum = "d0d69ae62e0ce582d56380743515fefaf1a8c70cec685d9677636d7e30ae9dc9" dependencies = [ "der", "elliptic-curve", - "hmac", + "rfc6979", "signature", ] @@ -638,16 +650,18 @@ checksum = "e78d4f1cc4ae33bbfc157ed5d5a5ef3bc29227303d595861deb238fcec4e9457" [[package]] name = "elliptic-curve" -version = "0.10.6" +version = "0.11.12" source = "registry+https://github.com/rust-lang/crates.io-index" -checksum = "beca177dcb8eb540133e7680baff45e7cc4d93bf22002676cec549f82343721b" +checksum = "25b477563c2bfed38a3b7a60964c49e058b2510ad3f12ba3483fd8f62c2306d6" dependencies = [ + "base16ct", "crypto-bigint", + "der", "ff", "generic-array 0.14.5", "group", - "pkcs8", "rand_core 0.6.3", + "sec1", "subtle 2.4.1", "zeroize", ] @@ -680,9 +694,9 @@ checksum = "e88a8acf291dafb59c2d96e8f59828f3838bb1a70398823ade51a84de6a6deed" [[package]] name = "ff" -version = "0.10.1" +version = "0.11.1" source = "registry+https://github.com/rust-lang/crates.io-index" -checksum = "d0f40b2dcd8bc322217a5f6559ae5f9e9d1de202a2ecee2e9eafcbece7562a4f" +checksum = "131655483be284720a17d74ff97592b8e76576dc25563148601df2d7c9080924" dependencies = [ "rand_core 0.6.3", "subtle 2.4.1", @@ -787,9 +801,9 @@ dependencies = [ [[package]] name = "group" -version = "0.10.0" +version = "0.11.0" source = "registry+https://github.com/rust-lang/crates.io-index" -checksum = "1c363a5301b8f153d80747126a04b3c82073b9fe3130571a9d170cacdeaf7912" +checksum = "bc5ac374b108929de78460075f3dc439fa66df9d8fc77e8f12caa5165fcf0c89" dependencies = [ "ff", "rand_core 0.6.3", @@ -910,13 +924,14 @@ dependencies = [ [[package]] name = "k256" -version = "0.9.6" +version = "0.10.4" source = "registry+https://github.com/rust-lang/crates.io-index" -checksum = "903ae2481bcdfdb7b68e0a9baa4b7c9aff600b9ae2e8e5bb5833b8c91ab851ea" +checksum = "19c3a5e0a0b8450278feda242592512e09f61c72e018b8cd5c859482802daf2d" dependencies = [ "cfg-if", "ecdsa", "elliptic-curve", + "sec1", "sha2", ] @@ -1190,12 +1205,13 @@ dependencies = [ [[package]] name = "pkcs8" -version = "0.7.6" +version = "0.8.0" source = "registry+https://github.com/rust-lang/crates.io-index" -checksum = "ee3ef9b64d26bad0536099c816c6734379e45bbd5f14798def6809e5cc350447" +checksum = "7cabda3fb821068a9a4fab19a683eac3af12edf0f34b94a8be53c4972b8149d0" dependencies = [ "der", "spki", + "zeroize", ] [[package]] @@ -1356,6 +1372,17 @@ version = "0.6.25" source = "registry+https://github.com/rust-lang/crates.io-index" checksum = "f497285884f3fcff424ffc933e56d7cbca511def0c9831a7f9b5f6153e3cc89b" +[[package]] +name = "rfc6979" +version = "0.1.0" +source = "registry+https://github.com/rust-lang/crates.io-index" +checksum = "96ef608575f6392792f9ecf7890c00086591d29a83910939d430753f7c050525" +dependencies = [ + "crypto-bigint", + "hmac", + "zeroize", +] + [[package]] name = "rustc_version" version = "0.4.0" @@ -1401,6 +1428,19 @@ dependencies = [ "syn", ] +[[package]] +name = "sec1" +version = "0.2.1" +source = "registry+https://github.com/rust-lang/crates.io-index" +checksum = "08da66b8b0965a5555b6bd6639e68ccba85e1e2506f5fbb089e93f8a04e1a2d1" +dependencies = [ + "der", + "generic-array 0.14.5", + "pkcs8", + "subtle 2.4.1", + "zeroize", +] + [[package]] name = "semver" version = "1.0.4" @@ -1418,9 +1458,9 @@ dependencies = [ [[package]] name = "serde-json-wasm" -version = "0.3.2" +version = "0.4.1" source = "registry+https://github.com/rust-lang/crates.io-index" -checksum = "042ac496d97e5885149d34139bad1d617192770d7eb8f1866da2317ff4501853" +checksum = "479b4dbc401ca13ee8ce902851b834893251404c4f3c65370a49e047a6be09a5" dependencies = [ "serde", ] @@ -1529,10 +1569,11 @@ dependencies = [ [[package]] name = "spki" -version = "0.4.1" +version = "0.5.4" source = "registry+https://github.com/rust-lang/crates.io-index" -checksum = "5c01a0c15da1b0b0e1494112e7af814a678fec9bd157881b49beac661e9b6f32" +checksum = "44d01ac02a6ccf3e07db148d2be087da624fea0221a16152ed01f0496a6b0a27" dependencies = [ + "base64ct", "der", ] diff --git a/contracts/bandwidth-claim/Cargo.toml b/contracts/bandwidth-claim/Cargo.toml index cd8136c8f9..5d530a5452 100644 --- a/contracts/bandwidth-claim/Cargo.toml +++ b/contracts/bandwidth-claim/Cargo.toml @@ -14,8 +14,8 @@ config = { path = "../../common/config"} [dependencies] bandwidth-claim-contract = { path = "../../common/bandwidth-claim-contract" } -cosmwasm-std = "1.0.0-beta8" -cosmwasm-storage = "1.0.0-beta8" +cosmwasm-std = "1.0.0" +cosmwasm-storage = "1.0.0" schemars = "0.8" serde = { version = "1.0.103", default-features = false, features = ["derive"] } diff --git a/contracts/coconut-bandwidth/Cargo.toml b/contracts/coconut-bandwidth/Cargo.toml index 74466d70d1..56ae373c2b 100644 --- a/contracts/coconut-bandwidth/Cargo.toml +++ b/contracts/coconut-bandwidth/Cargo.toml @@ -13,10 +13,10 @@ bandwidth-claim-contract = { path = "../../common/bandwidth-claim-contract" } coconut-bandwidth-contract-common = { path = "../../common/cosmwasm-smart-contracts/coconut-bandwidth-contract" } config = { path = "../../common/config"} -cosmwasm-std = "1.0.0-beta8" -cosmwasm-storage = "1.0.0-beta8" -cw-storage-plus = "0.13.2" -cw-controllers = "0.13.2" +cosmwasm-std = "1.0.0" +cosmwasm-storage = "1.0.0" +cw-storage-plus = "0.13.4" +cw-controllers = "0.13.4" schemars = "0.8" serde = { version = "1.0.103", default-features = false, features = ["derive"] } diff --git a/contracts/mixnet/Cargo.toml b/contracts/mixnet/Cargo.toml index 6b9e553914..ec28cd953c 100644 --- a/contracts/mixnet/Cargo.toml +++ b/contracts/mixnet/Cargo.toml @@ -20,9 +20,9 @@ mixnet-contract-common = { path = "../../common/cosmwasm-smart-contracts/mixnet- vesting-contract-common = { path = "../../common/cosmwasm-smart-contracts/vesting-contract" } config = { path = "../../common/config"} -cosmwasm-std = "1.0.0-beta8" -cosmwasm-storage = "1.0.0-beta8" -cw-storage-plus = "0.13.2" +cosmwasm-std = "1.0.0" +cosmwasm-storage = "1.0.0" +cw-storage-plus = "0.13.4" az = "1.2.0" bs58 = "0.4.0" @@ -33,7 +33,7 @@ time = { version = "0.3", features = ["macros"] } hex = "0.4.3" [dev-dependencies] -cosmwasm-schema = "1.0.0-beta3" +cosmwasm-schema = "1.0.0" fixed = "1.1" rand_chacha = "0.2" rand = "0.7" diff --git a/contracts/multisig/cw3-flex-multisig/Cargo.toml b/contracts/multisig/cw3-flex-multisig/Cargo.toml index 9c83f0fc21..c1c1d63620 100644 --- a/contracts/multisig/cw3-flex-multisig/Cargo.toml +++ b/contracts/multisig/cw3-flex-multisig/Cargo.toml @@ -23,7 +23,7 @@ cw3 = { version = "0.13.1" } cw3-fixed-multisig = { version = "0.13.1", features = ["library"] } cw4 = { version = "0.13.1" } cw-storage-plus = { version = "0.13.1" } -cosmwasm-std = { version = "1.0.0-beta6" } +cosmwasm-std = { version = "1.0.0" } schemars = "0.8.1" serde = { version = "1.0.103", default-features = false, features = ["derive"] } thiserror = { version = "1.0.23" } @@ -31,6 +31,6 @@ thiserror = { version = "1.0.23" } multisig-contract-common = { path= "../../../common/cosmwasm-smart-contracts/multisig-contract" } [dev-dependencies] -cosmwasm-schema = { version = "1.0.0-beta6" } +cosmwasm-schema = { version = "1.0.0" } cw4-group = { path = "../cw4-group", version = "0.13.1" } cw-multi-test = { version = "0.13.1" } diff --git a/contracts/multisig/cw4-group/Cargo.toml b/contracts/multisig/cw4-group/Cargo.toml index bdce839d85..949612ba77 100644 --- a/contracts/multisig/cw4-group/Cargo.toml +++ b/contracts/multisig/cw4-group/Cargo.toml @@ -29,10 +29,10 @@ cw2 = { version = "0.13.1" } cw4 = { version = "0.13.1" } cw-controllers = { version = "0.13.1" } cw-storage-plus = { version = "0.13.1" } -cosmwasm-std = { version = "1.0.0-beta6" } +cosmwasm-std = { version = "1.0.0" } schemars = "0.8.1" serde = { version = "1.0.103", default-features = false, features = ["derive"] } thiserror = { version = "1.0.23" } [dev-dependencies] -cosmwasm-schema = { version = "1.0.0-beta6" } +cosmwasm-schema = { version = "1.0.0" } diff --git a/contracts/vesting/Cargo.toml b/contracts/vesting/Cargo.toml index 56a4cf3e56..6cc29de4fb 100644 --- a/contracts/vesting/Cargo.toml +++ b/contracts/vesting/Cargo.toml @@ -18,8 +18,8 @@ mixnet-contract-common = { path = "../../common/cosmwasm-smart-contracts/mixnet- vesting-contract-common = { path = "../../common/cosmwasm-smart-contracts/vesting-contract" } config = { path = "../../common/config" } -cosmwasm-std = { version = "1.0.0-beta8"} -cw-storage-plus = { version = "0.13.1", features = ["iterator"] } +cosmwasm-std = { version = "1.0.0 "} +cw-storage-plus = { version = "0.13.4", features = ["iterator"] } schemars = "0.8" serde = { version = "1.0", default-features = false, features = ["derive"] } diff --git a/nym-wallet/Cargo.lock b/nym-wallet/Cargo.lock index 074df1422e..98b497e2da 100644 --- a/nym-wallet/Cargo.lock +++ b/nym-wallet/Cargo.lock @@ -328,7 +328,7 @@ checksum = "873faa4363bfc54c36a48321da034c92a0645a363eed34d948683ffc1706e37f" dependencies = [ "bs58", "hmac", - "k256 0.10.2", + "k256", "once_cell", "pbkdf2", "rand_core 0.6.3", @@ -763,12 +763,6 @@ dependencies = [ "url", ] -[[package]] -name = "const-oid" -version = "0.6.2" -source = "registry+https://github.com/rust-lang/crates.io-index" -checksum = "9d6f2aa4d0537bcc1c74df8755072bd31c1ef1a3a1b85a68e8404a8c353b7b8b" - [[package]] name = "const-oid" version = "0.7.1" @@ -854,10 +848,10 @@ checksum = "8413275b23cb5a0734d9d1e3e33f0b5b94547c1e94776dbc3149dbf46588a533" dependencies = [ "bip32", "cosmos-sdk-proto", - "ecdsa 0.13.4", + "ecdsa", "eyre", "getrandom 0.2.5", - "k256 0.10.2", + "k256", "prost", "prost-types", "rand_core 0.6.3", @@ -871,31 +865,31 @@ dependencies = [ [[package]] name = "cosmwasm-crypto" -version = "1.0.0-beta8" +version = "1.0.0" source = "registry+https://github.com/rust-lang/crates.io-index" -checksum = "37e70111e9701c3ec43bfbff0e523cd4cb115876b4d3433813436dd0934ee962" +checksum = "5eb0afef2325df81aadbf9be1233f522ed8f6e91df870c764bc44cca2b1415bd" dependencies = [ "digest 0.9.0", "ed25519-zebra", - "k256 0.9.6", + "k256", "rand_core 0.6.3", "thiserror", ] [[package]] name = "cosmwasm-derive" -version = "1.0.0-beta8" +version = "1.0.0" source = "registry+https://github.com/rust-lang/crates.io-index" -checksum = "58bc2ad5d86be5f6068833f63e20786768db6890019c095dd7775232184fb7b3" +checksum = "4b36e527620a2a3e00e46b6e731ab6c9b68d11069c986f7d7be8eba79ef081a4" dependencies = [ "syn", ] [[package]] name = "cosmwasm-std" -version = "1.0.0-beta8" +version = "1.0.0" source = "registry+https://github.com/rust-lang/crates.io-index" -checksum = "915ca82bd944f116f3a9717481f3fa657e4a73f28c4887288761ebb24e6fbe10" +checksum = "875994993c2082a6fcd406937bf0fca21c349e4a624f3810253a14fa83a3a195" dependencies = [ "base64", "cosmwasm-crypto", @@ -976,18 +970,6 @@ version = "0.2.2" source = "registry+https://github.com/rust-lang/crates.io-index" checksum = "7a81dae078cea95a014a339291cec439d2f232ebe854a9d672b796c6afafa9b7" -[[package]] -name = "crypto-bigint" -version = "0.2.11" -source = "registry+https://github.com/rust-lang/crates.io-index" -checksum = "f83bd3bb4314701c568e340cd8cf78c975aa0ca79e03d3f6d1677d5b0c9c0c03" -dependencies = [ - "generic-array 0.14.5", - "rand_core 0.6.3", - "subtle", - "zeroize", -] - [[package]] name = "crypto-bigint" version = "0.3.2" @@ -1096,9 +1078,9 @@ dependencies = [ [[package]] name = "cw-storage-plus" -version = "0.13.2" +version = "0.13.4" source = "registry+https://github.com/rust-lang/crates.io-index" -checksum = "9336ecef1e19d56cf6e3e932475fc6a3dee35eec5a386e07917a1d1ba6bb0e35" +checksum = "648b1507290bbc03a8d88463d7cd9b04b1fa0155e5eef366c4fa052b9caaac7a" dependencies = [ "cosmwasm-std", "schemars", @@ -1231,22 +1213,13 @@ dependencies = [ "byteorder", ] -[[package]] -name = "der" -version = "0.4.5" -source = "registry+https://github.com/rust-lang/crates.io-index" -checksum = "79b71cca7d95d7681a4b3b9cdf63c8dbc3730d0584c2c74e31416d64a90493f4" -dependencies = [ - "const-oid 0.6.2", -] - [[package]] name = "der" version = "0.5.1" source = "registry+https://github.com/rust-lang/crates.io-index" checksum = "6919815d73839e7ad218de758883aae3a257ba6759ce7a9992501efbb53d705c" dependencies = [ - "const-oid 0.7.1", + "const-oid", ] [[package]] @@ -1382,26 +1355,14 @@ version = "3.2.0" source = "registry+https://github.com/rust-lang/crates.io-index" checksum = "6907e25393cdcc1f4f3f513d9aac1e840eb1cc341a0fccb01171f7d14d10b946" -[[package]] -name = "ecdsa" -version = "0.12.4" -source = "registry+https://github.com/rust-lang/crates.io-index" -checksum = "43ee23aa5b4f68c7a092b5c3beb25f50c406adc75e2363634f242f28ab255372" -dependencies = [ - "der 0.4.5", - "elliptic-curve 0.10.6", - "hmac", - "signature", -] - [[package]] name = "ecdsa" version = "0.13.4" source = "registry+https://github.com/rust-lang/crates.io-index" checksum = "d0d69ae62e0ce582d56380743515fefaf1a8c70cec685d9677636d7e30ae9dc9" dependencies = [ - "der 0.5.1", - "elliptic-curve 0.11.12", + "der", + "elliptic-curve", "rfc6979", "signature", ] @@ -1448,22 +1409,6 @@ version = "1.6.1" source = "registry+https://github.com/rust-lang/crates.io-index" checksum = "e78d4f1cc4ae33bbfc157ed5d5a5ef3bc29227303d595861deb238fcec4e9457" -[[package]] -name = "elliptic-curve" -version = "0.10.6" -source = "registry+https://github.com/rust-lang/crates.io-index" -checksum = "beca177dcb8eb540133e7680baff45e7cc4d93bf22002676cec549f82343721b" -dependencies = [ - "crypto-bigint 0.2.11", - "ff 0.10.1", - "generic-array 0.14.5", - "group 0.10.0", - "pkcs8 0.7.6", - "rand_core 0.6.3", - "subtle", - "zeroize", -] - [[package]] name = "elliptic-curve" version = "0.11.12" @@ -1471,8 +1416,8 @@ source = "registry+https://github.com/rust-lang/crates.io-index" checksum = "25b477563c2bfed38a3b7a60964c49e058b2510ad3f12ba3483fd8f62c2306d6" dependencies = [ "base16ct", - "crypto-bigint 0.3.2", - "der 0.5.1", + "crypto-bigint", + "der", "ff 0.11.0", "generic-array 0.14.5", "group 0.11.0", @@ -2625,25 +2570,13 @@ dependencies = [ [[package]] name = "k256" -version = "0.9.6" +version = "0.10.4" source = "registry+https://github.com/rust-lang/crates.io-index" -checksum = "903ae2481bcdfdb7b68e0a9baa4b7c9aff600b9ae2e8e5bb5833b8c91ab851ea" +checksum = "19c3a5e0a0b8450278feda242592512e09f61c72e018b8cd5c859482802daf2d" dependencies = [ "cfg-if", - "ecdsa 0.12.4", - "elliptic-curve 0.10.6", - "sha2 0.9.9", -] - -[[package]] -name = "k256" -version = "0.10.2" -source = "registry+https://github.com/rust-lang/crates.io-index" -checksum = "1cc5937366afd3b38071f400d1ce5bd8b1d40b5083cc14e6f8dbcc4032a7f5bb" -dependencies = [ - "cfg-if", - "ecdsa 0.13.4", - "elliptic-curve 0.11.12", + "ecdsa", + "elliptic-curve", "sec1", "sha2 0.9.9", "sha3", @@ -2816,14 +2749,15 @@ dependencies = [ [[package]] name = "mio" -version = "0.8.0" +version = "0.8.2" source = "registry+https://github.com/rust-lang/crates.io-index" -checksum = "ba272f85fa0b41fc91872be579b3bbe0f56b792aa361a380eb669469f68dafb2" +checksum = "52da4364ffb0e4fe33a9841a98a3f3014fb964045ce4f7a45a398243c8d6b0c9" dependencies = [ "libc", "log", "miow", "ntapi", + "wasi 0.11.0+wasi-snapshot-preview1", "winapi", ] @@ -3545,24 +3479,14 @@ version = "0.1.0" source = "registry+https://github.com/rust-lang/crates.io-index" checksum = "8b870d8c151b6f2fb93e84a13146138f05d02ed11c7e7c54f8826aaaf7c9f184" -[[package]] -name = "pkcs8" -version = "0.7.6" -source = "registry+https://github.com/rust-lang/crates.io-index" -checksum = "ee3ef9b64d26bad0536099c816c6734379e45bbd5f14798def6809e5cc350447" -dependencies = [ - "der 0.4.5", - "spki 0.4.1", -] - [[package]] name = "pkcs8" version = "0.8.0" source = "registry+https://github.com/rust-lang/crates.io-index" checksum = "7cabda3fb821068a9a4fab19a683eac3af12edf0f34b94a8be53c4972b8149d0" dependencies = [ - "der 0.5.1", - "spki 0.5.4", + "der", + "spki", "zeroize", ] @@ -4087,7 +4011,7 @@ version = "0.1.0" source = "registry+https://github.com/rust-lang/crates.io-index" checksum = "96ef608575f6392792f9ecf7890c00086591d29a83910939d430753f7c050525" dependencies = [ - "crypto-bigint 0.3.2", + "crypto-bigint", "hmac", "zeroize", ] @@ -4271,9 +4195,9 @@ version = "0.2.1" source = "registry+https://github.com/rust-lang/crates.io-index" checksum = "08da66b8b0965a5555b6bd6639e68ccba85e1e2506f5fbb089e93f8a04e1a2d1" dependencies = [ - "der 0.5.1", + "der", "generic-array 0.14.5", - "pkcs8 0.8.0", + "pkcs8", "subtle", "zeroize", ] @@ -4356,9 +4280,9 @@ dependencies = [ [[package]] name = "serde-json-wasm" -version = "0.3.2" +version = "0.4.1" source = "registry+https://github.com/rust-lang/crates.io-index" -checksum = "042ac496d97e5885149d34139bad1d617192770d7eb8f1866da2317ff4501853" +checksum = "479b4dbc401ca13ee8ce902851b834893251404c4f3c65370a49e047a6be09a5" dependencies = [ "serde", ] @@ -4633,15 +4557,6 @@ version = "0.5.2" source = "registry+https://github.com/rust-lang/crates.io-index" checksum = "6e63cff320ae2c57904679ba7cb63280a3dc4613885beafb148ee7bf9aa9042d" -[[package]] -name = "spki" -version = "0.4.1" -source = "registry+https://github.com/rust-lang/crates.io-index" -checksum = "5c01a0c15da1b0b0e1494112e7af814a678fec9bd157881b49beac661e9b6f32" -dependencies = [ - "der 0.4.5", -] - [[package]] name = "spki" version = "0.5.4" @@ -4649,7 +4564,7 @@ source = "registry+https://github.com/rust-lang/crates.io-index" checksum = "44d01ac02a6ccf3e07db148d2be087da624fea0221a16152ed01f0496a6b0a27" dependencies = [ "base64ct", - "der 0.5.1", + "der", ] [[package]] @@ -5081,7 +4996,7 @@ dependencies = [ "ed25519-dalek", "flex-error", "futures", - "k256 0.10.2", + "k256", "num-traits", "once_cell", "prost", @@ -5256,15 +5171,16 @@ checksum = "25eb0ca3468fc0acc11828786797f6ef9aa1555e4a211a60d64cc8e4d1be47d6" [[package]] name = "tokio" -version = "1.17.0" +version = "1.19.2" source = "registry+https://github.com/rust-lang/crates.io-index" -checksum = "2af73ac49756f3f7c01172e34a23e5d0216f6c32333757c2c61feb2bbff5a5ee" +checksum = "c51a52ed6686dd62c320f9b89299e9dfb46f730c7a48e635c19f21d116cb1439" dependencies = [ "bytes", "libc", "memchr", "mio", "num_cpus", + "once_cell", "pin-project-lite", "socket2", "tokio-macros", @@ -5681,6 +5597,12 @@ version = "0.10.2+wasi-snapshot-preview1" source = "registry+https://github.com/rust-lang/crates.io-index" checksum = "fd6fbd9a79829dd1ad0cc20627bf1ed606756a7f77edff7b66b7064f9cb327c6" +[[package]] +name = "wasi" +version = "0.11.0+wasi-snapshot-preview1" +source = "registry+https://github.com/rust-lang/crates.io-index" +checksum = "9c8d87e72b64a3b4db28d11ce29237c246188f4f51057d65a7eab63b7987e423" + [[package]] name = "wasm-bindgen" version = "0.2.79" diff --git a/nym-wallet/src-tauri/Cargo.toml b/nym-wallet/src-tauri/Cargo.toml index 03a23fe886..2c28fcdc1e 100644 --- a/nym-wallet/src-tauri/Cargo.toml +++ b/nym-wallet/src-tauri/Cargo.toml @@ -47,7 +47,7 @@ argon2 = { version = "0.3.2", features = ["std"] } base64 = "0.13" zeroize = "1.4.3" -cosmwasm-std = "1.0.0-beta8" +cosmwasm-std = "1.0.0" validator-client = { path = "../../common/client-libs/validator-client", features = [ "nymd-client", diff --git a/validator-api/Cargo.toml b/validator-api/Cargo.toml index a75534348a..5b2597876a 100644 --- a/validator-api/Cargo.toml +++ b/validator-api/Cargo.toml @@ -50,7 +50,7 @@ schemars = { version = "0.8", features = ["preserve_order"] } ## internal coconut-bandwidth-contract-common = { path = "../common/cosmwasm-smart-contracts/coconut-bandwidth-contract" } config = { path = "../common/config" } -cosmwasm-std = "1.0.0-beta8" +cosmwasm-std = "1.0.0" crypto = { path="../common/crypto" } gateway-client = { path="../common/client-libs/gateway-client" } mixnet-contract-common = { path= "../common/cosmwasm-smart-contracts/mixnet-contract" } From fb5193163ead00248b088c69c35b3caf7532ca57 Mon Sep 17 00:00:00 2001 From: =?UTF-8?q?Bogdan-=C8=98tefan=20Neac=C5=9Fu?= Date: Wed, 8 Jun 2022 12:08:12 +0300 Subject: [PATCH 21/25] Remove coconut debugging code (#1321) --- common/client-libs/gateway-client/src/client.rs | 6 +++--- 1 file changed, 3 insertions(+), 3 deletions(-) diff --git a/common/client-libs/gateway-client/src/client.rs b/common/client-libs/gateway-client/src/client.rs index 4ead7b4597..c29a65b080 100644 --- a/common/client-libs/gateway-client/src/client.rs +++ b/common/client-libs/gateway-client/src/client.rs @@ -83,7 +83,7 @@ impl GatewayClient { ) -> Self { GatewayClient { authenticated: false, - disabled_credentials_mode: false, + disabled_credentials_mode: true, bandwidth_remaining: 0, gateway_address, gateway_identity, @@ -100,8 +100,8 @@ impl GatewayClient { } } - pub fn set_disabled_credentials_mode(&mut self, _disabled_credentials_mode: bool) { - self.disabled_credentials_mode = false; + pub fn set_disabled_credentials_mode(&mut self, disabled_credentials_mode: bool) { + self.disabled_credentials_mode = disabled_credentials_mode; } // TODO: later convert into proper builder methods From 12412d32e601e0af0d17eabbd4ccd32a70a50a8e Mon Sep 17 00:00:00 2001 From: =?UTF-8?q?Bogdan-=C8=98tefan=20Neac=C5=9Fu?= Date: Wed, 8 Jun 2022 14:07:17 +0300 Subject: [PATCH 22/25] Panic early if re-init with new gateway (#1322) * Panic early if re-init with new gateway * Update CHANGELOG --- CHANGELOG.md | 2 ++ clients/native/src/commands/init.rs | 3 +++ clients/native/src/commands/mod.rs | 4 ---- clients/socks5/src/commands/init.rs | 3 +++ clients/socks5/src/commands/mod.rs | 4 ---- 5 files changed, 8 insertions(+), 8 deletions(-) diff --git a/CHANGELOG.md b/CHANGELOG.md index 5082f33fad..1dd00a5c89 100644 --- a/CHANGELOG.md +++ b/CHANGELOG.md @@ -33,6 +33,7 @@ Post 1.0.0 release, the changelog format is based on [Keep a Changelog](https:// - mixnode, gateway: attempting to determine reconnection backoff to persistently failing mixnode could result in a crash ([#1260]) - mixnode: the mixnode learned how to shutdown gracefully. - vesting-contract: replaced `checked_sub` with `saturating_sub` to fix the underflow in `get_vesting_tokens` ([#1275]) +- native & socks5 clients: fail early when clients try to re-init with a different gateway, which is not supported yet ([#1322]) ### Changed @@ -54,6 +55,7 @@ Post 1.0.0 release, the changelog format is based on [Keep a Changelog](https:// [#1295]: https://github.com/nymtech/nym/pull/1295 [#1302]: https://github.com/nymtech/nym/pull/1302 [#1318]: https://github.com/nymtech/nym/pull/1318 +[#1322]: https://github.com/nymtech/nym/pull/1322 ## [nym-wallet-v1.0.4](https://github.com/nymtech/nym/tree/nym-wallet-v1.0.4) (2022-05-04) diff --git a/clients/native/src/commands/init.rs b/clients/native/src/commands/init.rs index 2ef90debf1..63ac522634 100644 --- a/clients/native/src/commands/init.rs +++ b/clients/native/src/commands/init.rs @@ -186,6 +186,9 @@ pub async fn execute(matches: ArgMatches<'static>) { let id = matches.value_of("id").unwrap(); // required for now let already_init = if Config::default_config_file_path(Some(id)).exists() { + if matches.is_present("gateway") { + panic!("At the moment, gateway information can't be overwritten. If you want to point to a different gateway, client {}'s directory will need to be manually removed", id); + } println!("Client \"{}\" was already initialised before! Config information will be overwritten (but keys will be kept)!", id); true } else { diff --git a/clients/native/src/commands/mod.rs b/clients/native/src/commands/mod.rs index f3a1d408f0..79e8f0e00d 100644 --- a/clients/native/src/commands/mod.rs +++ b/clients/native/src/commands/mod.rs @@ -39,10 +39,6 @@ pub(crate) fn override_config(mut config: Config, matches: &ArgMatches<'_>) -> C .set_custom_validator_apis(parse_validators(raw_validators)); } - if let Some(gateway_id) = matches.value_of("gateway") { - config.get_base_mut().with_gateway_id(gateway_id); - } - if matches.is_present("disable-socket") { config = config.with_socket(SocketType::None); } diff --git a/clients/socks5/src/commands/init.rs b/clients/socks5/src/commands/init.rs index 4ada9a6296..c7bf48b051 100644 --- a/clients/socks5/src/commands/init.rs +++ b/clients/socks5/src/commands/init.rs @@ -187,6 +187,9 @@ pub async fn execute(matches: ArgMatches<'static>) { let provider_address = matches.value_of("provider").unwrap(); let already_init = if Config::default_config_file_path(Some(id)).exists() { + if matches.is_present("gateway") { + panic!("At the moment, gateway information can't be overwritten. If you want to point to a different gateway, client {}'s directory will need to be manually removed", id); + } println!("Socks5 client \"{}\" was already initialised before! Config information will be overwritten (but keys will be kept)!", id); true } else { diff --git a/clients/socks5/src/commands/mod.rs b/clients/socks5/src/commands/mod.rs index 3aa1131a24..4573244eb0 100644 --- a/clients/socks5/src/commands/mod.rs +++ b/clients/socks5/src/commands/mod.rs @@ -39,10 +39,6 @@ pub(crate) fn override_config(mut config: Config, matches: &ArgMatches<'_>) -> C .set_custom_validator_apis(parse_validators(raw_validators)); } - if let Some(gateway_id) = matches.value_of("gateway") { - config.get_base_mut().with_gateway_id(gateway_id); - } - if let Some(port) = matches.value_of("port").map(|port| port.parse::()) { if let Err(err) = port { // if port was overridden, it must be parsable From be938cf4f06a41602a8f56bbde99307c76796c0f Mon Sep 17 00:00:00 2001 From: =?UTF-8?q?Jon=20H=C3=A4ggblad?= Date: Wed, 8 Jun 2022 21:51:00 +0200 Subject: [PATCH 23/25] client/native: tidy some logging (#1320) * client/native: some logging refinement * client/native: fix pedantic clippy warn * client/native: another pedantic clippy warn * rustfmt --- clients/native/src/commands/init.rs | 13 +++++++++++-- clients/native/src/commands/mod.rs | 2 +- clients/native/src/commands/run.rs | 6 +++--- clients/native/src/commands/upgrade.rs | 14 +++++++------- clients/native/src/main.rs | 2 ++ common/config/src/lib.rs | 4 ---- common/topology/src/gateway.rs | 10 ++++++++++ 7 files changed, 34 insertions(+), 17 deletions(-) diff --git a/clients/native/src/commands/init.rs b/clients/native/src/commands/init.rs index 63ac522634..4810365526 100644 --- a/clients/native/src/commands/init.rs +++ b/clients/native/src/commands/init.rs @@ -119,6 +119,7 @@ async fn gateway_details( .expect("The list of validator apis is empty"); let validator_client = validator_client::ApiClient::new(validator_api.clone()); + log::trace!("Fetching list of gateways from: {}", validator_api); let gateways = validator_client.get_cached_gateways().await.unwrap(); let valid_gateways = gateways .into_iter() @@ -213,12 +214,14 @@ pub async fn execute(matches: ArgMatches<'static>) { let mut key_manager = KeyManager::new(&mut rng); let chosen_gateway_id = matches.value_of("gateway"); + log::trace!("Chosen gateway: {:?}", chosen_gateway_id); let gateway_details = gateway_details( config.get_base().get_validator_api_endpoints(), chosen_gateway_id, ) .await; + log::trace!("Used gateway: {}", gateway_details); let shared_keys = register_with_gateway(&gateway_details, key_manager.identity_keypair()).await; @@ -241,8 +244,14 @@ pub async fn execute(matches: ArgMatches<'static>) { .save_to_file(None) .expect("Failed to save the config file"); println!("Saved configuration file to {:?}", config_save_location); - println!("Using gateway: {}", config.get_base().get_gateway_id(),); - println!("Client configuration completed.\n\n\n"); + println!("Using gateway: {}", config.get_base().get_gateway_id()); + log::debug!("Gateway id: {}", config.get_base().get_gateway_id()); + log::debug!("Gateway owner: {}", config.get_base().get_gateway_owner()); + log::debug!( + "Gateway listener: {}", + config.get_base().get_gateway_listener() + ); + println!("Client configuration completed."); show_address(&config); } diff --git a/clients/native/src/commands/mod.rs b/clients/native/src/commands/mod.rs index 79e8f0e00d..f48e9fb9d7 100644 --- a/clients/native/src/commands/mod.rs +++ b/clients/native/src/commands/mod.rs @@ -43,7 +43,7 @@ pub(crate) fn override_config(mut config: Config, matches: &ArgMatches<'_>) -> C config = config.with_socket(SocketType::None); } - if let Some(port) = matches.value_of("port").map(|port| port.parse::()) { + if let Some(port) = matches.value_of("port").map(str::parse) { if let Err(err) = port { // if port was overridden, it must be parsable panic!("Invalid port value provided - {:?}", err); diff --git a/clients/native/src/commands/run.rs b/clients/native/src/commands/run.rs index 1ccbcc9ed9..14c3fe14a2 100644 --- a/clients/native/src/commands/run.rs +++ b/clients/native/src/commands/run.rs @@ -70,7 +70,9 @@ pub fn command_args<'a, 'b>() -> clap::App<'a, 'b> { fn version_check(cfg: &Config) -> bool { let binary_version = env!("CARGO_PKG_VERSION"); let config_version = cfg.get_base().get_version(); - if binary_version != config_version { + if binary_version == config_version { + true + } else { warn!("The mixnode binary has different version than what is specified in config file! {} and {}", binary_version, config_version); if is_minor_version_compatible(binary_version, config_version) { info!("but they are still semver compatible. However, consider running the `upgrade` command"); @@ -79,8 +81,6 @@ fn version_check(cfg: &Config) -> bool { error!("and they are semver incompatible! - please run the `upgrade` command before attempting `run` again"); false } - } else { - true } } diff --git a/clients/native/src/commands/upgrade.rs b/clients/native/src/commands/upgrade.rs index 2c90840f31..446f110d47 100644 --- a/clients/native/src/commands/upgrade.rs +++ b/clients/native/src/commands/upgrade.rs @@ -131,22 +131,22 @@ fn minor_0_12_upgrade( config } -fn do_upgrade(mut config: Config, matches: &ArgMatches<'_>, package_version: Version) { +fn do_upgrade(mut config: Config, matches: &ArgMatches<'_>, package_version: &Version) { loop { let config_version = parse_config_version(&config); - if config_version == package_version { + if &config_version == package_version { println!("You're using the most recent version!"); return; } config = match config_version.major { 0 => match config_version.minor { - 9 | 10 => outdated_upgrade(&config_version, &package_version), - 11 => minor_0_12_upgrade(config, matches, &config_version, &package_version), - _ => unsupported_upgrade(&config_version, &package_version), + 9 | 10 => outdated_upgrade(&config_version, package_version), + 11 => minor_0_12_upgrade(config, matches, &config_version, package_version), + _ => unsupported_upgrade(&config_version, package_version), }, - _ => unsupported_upgrade(&config_version, &package_version), + _ => unsupported_upgrade(&config_version, package_version), } } } @@ -167,5 +167,5 @@ pub fn execute(matches: &ArgMatches<'_>) { } // here be upgrade path to 0.9.X and beyond based on version number from config - do_upgrade(existing_config, matches, package_version) + do_upgrade(existing_config, matches, &package_version) } diff --git a/clients/native/src/main.rs b/clients/native/src/main.rs index fc9a475b9b..7b3af045f5 100644 --- a/clients/native/src/main.rs +++ b/clients/native/src/main.rs @@ -108,5 +108,7 @@ fn setup_logging() { .filter_module("want", log::LevelFilter::Warn) .filter_module("tungstenite", log::LevelFilter::Warn) .filter_module("tokio_tungstenite", log::LevelFilter::Warn) + .filter_module("handlebars", log::LevelFilter::Warn) + .filter_module("sled", log::LevelFilter::Warn) .init(); } diff --git a/common/config/src/lib.rs b/common/config/src/lib.rs index 39427d5a85..10cff06548 100644 --- a/common/config/src/lib.rs +++ b/common/config/src/lib.rs @@ -15,7 +15,6 @@ pub trait NymConfig: Default + Serialize + DeserializeOwned { fn template() -> &'static str; fn config_file_name() -> String { - log::trace!("NymdConfig::config_file_name"); "config.toml".to_string() } @@ -23,7 +22,6 @@ pub trait NymConfig: Default + Serialize + DeserializeOwned { // default, most probable, implementations; can be easily overridden where required fn default_config_directory(id: Option<&str>) -> PathBuf { - log::trace!("NymdConfig::default_config_directory"); if let Some(id) = id { Self::default_root_directory().join(id).join("config") } else { @@ -32,7 +30,6 @@ pub trait NymConfig: Default + Serialize + DeserializeOwned { } fn default_data_directory(id: Option<&str>) -> PathBuf { - log::trace!("NymdConfig::default_data_path"); if let Some(id) = id { Self::default_root_directory().join(id).join("data") } else { @@ -41,7 +38,6 @@ pub trait NymConfig: Default + Serialize + DeserializeOwned { } fn default_config_file_path(id: Option<&str>) -> PathBuf { - log::trace!("NymdConfig::default_config_file_path"); Self::default_config_directory(id).join(Self::config_file_name()) } diff --git a/common/topology/src/gateway.rs b/common/topology/src/gateway.rs index bc9a569df8..57b34146e6 100644 --- a/common/topology/src/gateway.rs +++ b/common/topology/src/gateway.rs @@ -93,6 +93,16 @@ impl Node { } } +impl fmt::Display for Node { + fn fmt(&self, f: &mut fmt::Formatter<'_>) -> fmt::Result { + write!( + f, + "Node(id: {}, owner: {}, stake: {}, location: {}, host: {})", + self.identity_key, self.owner, self.stake, self.location, self.host, + ) + } +} + impl filter::Versioned for Node { fn version(&self) -> String { self.version.clone() From e9aa75ccac44eb97f49e6cbbca70d18af092bb13 Mon Sep 17 00:00:00 2001 From: =?UTF-8?q?Jon=20H=C3=A4ggblad?= Date: Thu, 9 Jun 2022 14:35:44 +0200 Subject: [PATCH 24/25] wallet: fix clippy (#1334) --- nym-wallet/src-tauri/src/coin.rs | 4 ++-- nym-wallet/src-tauri/src/operations/mixnet/account.rs | 2 +- 2 files changed, 3 insertions(+), 3 deletions(-) diff --git a/nym-wallet/src-tauri/src/coin.rs b/nym-wallet/src-tauri/src/coin.rs index 9f4c1d7f3a..79b19171d9 100644 --- a/nym-wallet/src-tauri/src/coin.rs +++ b/nym-wallet/src-tauri/src/coin.rs @@ -239,7 +239,7 @@ mod test { let network_denom = "unym"; let coin = Coin::minor("42"); - let backend_coin = coin.clone().into_backend_coin(&network_denom).unwrap(); + let backend_coin = coin.into_backend_coin(network_denom).unwrap(); assert_eq!(backend_coin, BackendCoin::new(42, "unym")); } @@ -248,7 +248,7 @@ mod test { let network_denom = "unym"; let coin = Coin::major("52"); - let backend_coin = coin.clone().into_backend_coin(network_denom).unwrap(); + let backend_coin = coin.into_backend_coin(network_denom).unwrap(); assert_eq!(backend_coin, BackendCoin::new(52, "nym")); } diff --git a/nym-wallet/src-tauri/src/operations/mixnet/account.rs b/nym-wallet/src-tauri/src/operations/mixnet/account.rs index 31c45f21c6..4d535a01f1 100644 --- a/nym-wallet/src-tauri/src/operations/mixnet/account.rs +++ b/nym-wallet/src-tauri/src/operations/mixnet/account.rs @@ -699,7 +699,7 @@ mod tests { assert_eq!(mnemonic, expected_mnemonic); let all_accounts: Vec<_> = stored_login - .unwrap_into_multiple_accounts(account_id.clone()) + .unwrap_into_multiple_accounts(account_id) .into_accounts() .collect(); From fbdf31b8794643dde2f78d02eaed7235fa108584 Mon Sep 17 00:00:00 2001 From: =?UTF-8?q?Bogdan-=C8=98tefan=20Neac=C5=9Fu?= Date: Thu, 9 Jun 2022 16:58:51 +0300 Subject: [PATCH 25/25] Feature/split stats service (#1328) * Replace client address with service address * Copy over the server parts of the statistics server * Separate API in module * Rename struct * Add insertion endpoint * Remove unused code from network requester * Box big rocket error * Remove the feature-specific code * Construct http req * Clippy + Cargo.lock update * Re-added needed sqlx feature * Wrap http req in ordered msg * Add http headers * Move common api functionality into the separate crate * Make stats server address configurable, especially for testing * Update changelog * Fix clippy * Help command update --- CHANGELOG.md | 4 +- Cargo.lock | 29 +++- Cargo.toml | 2 + common/socks5/requests/src/msg.rs | 20 +++ common/statistics/Cargo.toml | 15 ++ common/statistics/src/api.rs | 40 +++++ common/statistics/src/error.rs | 10 ++ common/statistics/src/lib.rs | 43 +++++ .../network-requester/Cargo.toml | 16 +- service-providers/network-requester/README.md | 9 +- .../network-requester/src/connection.rs | 9 +- .../network-requester/src/core.rs | 149 ++++++++--------- .../network-requester/src/main.rs | 33 ++-- .../network-requester/src/statistics/comm.rs | 150 +++++++++--------- .../network-requester/src/statistics/error.rs | 3 - .../network-requester/src/statistics/mod.rs | 2 +- .../network-requester/src/storage/routes.rs | 52 ------ .../network-statistics/Cargo.toml | 23 +++ .../network-statistics/Rocket.toml | 7 + .../build.rs | 2 +- .../20220512120000_mixnet_statistics.sql | 5 +- .../network-statistics/src/api/error.rs | 31 ++++ .../network-statistics/src/api/mod.rs | 48 ++++++ .../network-statistics/src/api/routes.rs | 61 +++++++ .../network-statistics/src/main.rs | 53 +++++++ .../src/storage/error.rs | 5 +- .../src/storage/manager.rs | 19 +-- .../src/storage/mod.rs | 42 ++--- .../src/storage/models.rs | 5 +- 29 files changed, 590 insertions(+), 297 deletions(-) create mode 100644 common/statistics/Cargo.toml create mode 100644 common/statistics/src/api.rs create mode 100644 common/statistics/src/error.rs create mode 100644 common/statistics/src/lib.rs delete mode 100644 service-providers/network-requester/src/storage/routes.rs create mode 100644 service-providers/network-statistics/Cargo.toml create mode 100644 service-providers/network-statistics/Rocket.toml rename service-providers/{network-requester => network-statistics}/build.rs (91%) rename service-providers/{network-requester => network-statistics}/migrations/20220512120000_mixnet_statistics.sql (74%) create mode 100644 service-providers/network-statistics/src/api/error.rs create mode 100644 service-providers/network-statistics/src/api/mod.rs create mode 100644 service-providers/network-statistics/src/api/routes.rs create mode 100644 service-providers/network-statistics/src/main.rs rename service-providers/{network-requester => network-statistics}/src/storage/error.rs (76%) rename service-providers/{network-requester => network-statistics}/src/storage/manager.rs (70%) rename service-providers/{network-requester => network-statistics}/src/storage/mod.rs (66%) rename service-providers/{network-requester => network-statistics}/src/storage/models.rs (78%) diff --git a/CHANGELOG.md b/CHANGELOG.md index 1dd00a5c89..7d5127b964 100644 --- a/CHANGELOG.md +++ b/CHANGELOG.md @@ -11,7 +11,6 @@ Post 1.0.0 release, the changelog format is based on [Keep a Changelog](https:// - gateway: Added gateway coconut verifications and validator-api communication for double spending protection ([#1261]) - mixnet-contract: Added ClaimOperatorReward and ClaimDelegatorReward messages ([#1292]) - mixnet-contract: Replace all naked `-` with `saturating_sub`. -- network-requester: send traffic statistics from all network requesters and receive it in a special network-requester that aggregates the data and exposes it via a rest API ([#1267], [#1278]). - validator-api: add `estimated_node_profit` and `estimated_operator_cost` to `reward-estimate` endpoint ([#1284]) - validator-api: add detailed mixnode bond endpoints, and explorer-api makes use of that data to append stake saturation. - validator-api: add Swagger to document the REST API ([#1249]). @@ -22,6 +21,7 @@ Post 1.0.0 release, the changelog format is based on [Keep a Changelog](https:// - wallet: compound and claim reward endpoints for operators and delegators ([#1302]) - wallet: require password to switch accounts - wallet: the wallet backend learned how to keep track of validator name, either hardcoded or by querying the status endpoint. +- network-statistics: a new mixnet service that aggregates and exposes anonymized data about mixnet services ([#1328]) ### Fixed @@ -39,6 +39,7 @@ Post 1.0.0 release, the changelog format is based on [Keep a Changelog](https:// - validator-client: created internal `Coin` type that replaces coins from `cosmrs` and `cosmwasm` for API entrypoints [[#1295]] - all: updated all `cosmwasm`-related dependencies to `1.0.0` and `cw-storage-plus` to `0.13.4` [[#1318]] +- network-requester: allow to voluntarily store and send statistical data about the number of bytes the proxied server serves ([#1328]) [#1249]: https://github.com/nymtech/nym/pull/1249 [#1256]: https://github.com/nymtech/nym/pull/1256 @@ -56,6 +57,7 @@ Post 1.0.0 release, the changelog format is based on [Keep a Changelog](https:// [#1302]: https://github.com/nymtech/nym/pull/1302 [#1318]: https://github.com/nymtech/nym/pull/1318 [#1322]: https://github.com/nymtech/nym/pull/1322 +[#1328]: https://github.com/nymtech/nym/pull/1328 ## [nym-wallet-v1.0.4](https://github.com/nymtech/nym/tree/nym-wallet-v1.0.4) (2022-05-04) diff --git a/Cargo.lock b/Cargo.lock index 363273a699..d800d74f15 100644 --- a/Cargo.lock +++ b/Cargo.lock @@ -3129,7 +3129,6 @@ dependencies = [ name = "nym-network-requester" version = "1.0.1" dependencies = [ - "bincode", "clap 2.34.0", "dirs", "futures", @@ -3143,16 +3142,32 @@ dependencies = [ "publicsuffix", "rand 0.7.3", "reqwest", - "rocket", "serde", "socks5-requests", "sqlx", + "statistics", "thiserror", "tokio", "tokio-tungstenite", "websocket-requests", ] +[[package]] +name = "nym-network-statistics" +version = "0.1.0" +dependencies = [ + "dirs", + "log", + "pretty_env_logger", + "rocket", + "serde", + "sqlx", + "statistics", + "thiserror", + "tokio", + "tokio-tungstenite", +] + [[package]] name = "nym-socks5-client" version = "1.0.1" @@ -5303,6 +5318,16 @@ version = "1.1.0" source = "registry+https://github.com/rust-lang/crates.io-index" checksum = "a2eb9349b6444b326872e140eb1cf5e7c522154d69e7a0ffb0fb81c06b37543f" +[[package]] +name = "statistics" +version = "1.0.1" +dependencies = [ + "reqwest", + "serde", + "serde_json", + "thiserror", +] + [[package]] name = "stdweb" version = "0.4.20" diff --git a/Cargo.toml b/Cargo.toml index d1acbb02a1..4ffc4cbdd2 100644 --- a/Cargo.toml +++ b/Cargo.toml @@ -53,6 +53,7 @@ members = [ "common/nymsphinx/params", "common/nymsphinx/types", "common/pemstore", + "common/statistics", "common/socks5/proxy-helpers", "common/socks5/requests", "common/task", @@ -63,6 +64,7 @@ members = [ "gateway/gateway-requests", "mixnode", "service-providers/network-requester", + "service-providers/network-statistics", "validator-api", "validator-api/validator-api-requests", ] diff --git a/common/socks5/requests/src/msg.rs b/common/socks5/requests/src/msg.rs index 21a37b1190..68d1160b4e 100644 --- a/common/socks5/requests/src/msg.rs +++ b/common/socks5/requests/src/msg.rs @@ -32,6 +32,26 @@ impl Message { const REQUEST_FLAG: u8 = 0; const RESPONSE_FLAG: u8 = 1; + pub fn conn_id(&self) -> u64 { + match self { + Message::Request(req) => match req { + Request::Connect(c) => c.conn_id, + Request::Send(conn_id, _, _) => *conn_id, + }, + Message::Response(resp) => resp.connection_id, + } + } + + pub fn size(&self) -> usize { + match self { + Message::Request(req) => match req { + Request::Connect(_) => 0, + Request::Send(_, data, _) => data.len(), + }, + Message::Response(resp) => resp.data.len(), + } + } + pub fn try_from_bytes(b: &[u8]) -> Result { if b.is_empty() { return Err(MessageError::NoData); diff --git a/common/statistics/Cargo.toml b/common/statistics/Cargo.toml new file mode 100644 index 0000000000..efed3428a5 --- /dev/null +++ b/common/statistics/Cargo.toml @@ -0,0 +1,15 @@ +# Copyright 2022 - Nym Technologies SA +# SPDX-License-Identifier: Apache-2.0 + +[package] +name = "statistics" +version = "1.0.1" +edition = "2021" + +# See more keys and their definitions at https://doc.rust-lang.org/cargo/reference/manifest.html + +[dependencies] +reqwest = "0.11" +serde = { version = "1.0", features = ["derive"] } +serde_json = "1" +thiserror = "1" \ No newline at end of file diff --git a/common/statistics/src/api.rs b/common/statistics/src/api.rs new file mode 100644 index 0000000000..6b9139adba --- /dev/null +++ b/common/statistics/src/api.rs @@ -0,0 +1,40 @@ +// Copyright 2022 - Nym Technologies SA +// SPDX-License-Identifier: Apache-2.0 + +use crate::error::StatsError; +use crate::StatsMessage; + +pub const DEFAULT_STATISTICS_SERVICE_ADDRESS: &str = "127.0.0.1"; +pub const DEFAULT_STATISTICS_SERVICE_PORT: u16 = 8090; + +pub const STATISTICS_SERVICE_VERSION: &str = "/v1"; +pub const STATISTICS_SERVICE_API_STATISTICS: &str = "statistic"; + +pub fn build_statistics_request_bytes(msg: StatsMessage) -> Result, StatsError> { + let json_msg = msg.to_json()?; + + let req = reqwest::Request::new( + reqwest::Method::POST, + reqwest::Url::parse(&format!( + "http://{}:{}/{}/{}", + DEFAULT_STATISTICS_SERVICE_ADDRESS, + DEFAULT_STATISTICS_SERVICE_PORT, + STATISTICS_SERVICE_VERSION, + STATISTICS_SERVICE_API_STATISTICS + )) + .unwrap(), + ); + let data = format!( + "{} {} {:?}\n\ + Content-Type: application/json\n\ + Content-Length: {}\n\n\ + {}\n", + req.method().as_str(), + req.url().as_str(), + req.version(), + json_msg.len(), + json_msg + ); + + Ok(data.into_bytes()) +} diff --git a/common/statistics/src/error.rs b/common/statistics/src/error.rs new file mode 100644 index 0000000000..1c25807d98 --- /dev/null +++ b/common/statistics/src/error.rs @@ -0,0 +1,10 @@ +// Copyright 2022 - Nym Technologies SA +// SPDX-License-Identifier: Apache-2.0 + +use thiserror::Error; + +#[derive(Debug, Error)] +pub enum StatsError { + #[error("Serde JSON error: {0}")] + SerdeJsonError(#[from] serde_json::Error), +} diff --git a/common/statistics/src/lib.rs b/common/statistics/src/lib.rs new file mode 100644 index 0000000000..267ccafb83 --- /dev/null +++ b/common/statistics/src/lib.rs @@ -0,0 +1,43 @@ +// Copyright 2022 - Nym Technologies SA +// SPDX-License-Identifier: Apache-2.0 + +use serde::{Deserialize, Serialize}; + +use error::StatsError; + +pub mod api; +pub mod error; + +#[derive(Clone, Debug, Deserialize, Serialize)] +pub struct StatsMessage { + pub stats_data: Vec, + pub interval_seconds: u32, + pub timestamp: String, +} + +impl StatsMessage { + pub fn to_json(&self) -> Result { + Ok(serde_json::to_string(self)?) + } + + pub fn from_json(s: &str) -> Result { + Ok(serde_json::from_str(s)?) + } +} + +#[derive(Clone, Debug, Deserialize, Serialize)] +pub struct StatsServiceData { + pub requested_service: String, + pub request_bytes: u32, + pub response_bytes: u32, +} + +impl StatsServiceData { + pub fn new(requested_service: String, request_bytes: u32, response_bytes: u32) -> Self { + StatsServiceData { + requested_service, + request_bytes, + response_bytes, + } + } +} diff --git a/service-providers/network-requester/Cargo.toml b/service-providers/network-requester/Cargo.toml index ba83a25179..b4825bb782 100644 --- a/service-providers/network-requester/Cargo.toml +++ b/service-providers/network-requester/Cargo.toml @@ -10,7 +10,6 @@ edition = "2021" # See more keys and their definitions at https://doc.rust-lang.org/cargo/reference/manifest.html [dependencies] -bincode = "1.3" clap = "2.33.0" dirs = "3.0" futures = "0.3" @@ -18,10 +17,10 @@ ipnetwork = "0.17" log = "0.4" pretty_env_logger = "0.4" publicsuffix = "1.5" +rand = "0.7" reqwest = { version = "0.11", features = ["json"] } -rocket = { version = "0.5.0-rc.1", features = ["json"], optional = true } serde = { version = "1.0", features = ["derive"] } -sqlx = { version = "0.5", features = ["runtime-tokio-rustls", "sqlite", "macros", "migrate", "chrono"]} +sqlx = { version = "0.5", features = ["runtime-tokio-rustls", "chrono"]} thiserror = "1" tokio = { version = "1.19.1", features = [ "net", "rt-multi-thread", "macros", "time" ] } tokio-tungstenite = "0.14" @@ -33,14 +32,5 @@ nymsphinx = { path = "../../common/nymsphinx" } ordered-buffer = {path = "../../common/socks5/ordered-buffer"} proxy-helpers = { path = "../../common/socks5/proxy-helpers" } socks5-requests = { path = "../../common/socks5/requests" } +statistics = { path = "../../common/statistics" } websocket-requests = { path = "../../clients/native/websocket-requests" } - -[dev-dependencies] -rand = "0.7" - -[build-dependencies] -sqlx = { version = "0.5", features = ["runtime-tokio-rustls", "sqlite", "macros", "migrate"] } -tokio = { version = "1.19.1", features = ["rt-multi-thread", "macros"] } - -[features] -stats-service = ["rocket"] \ No newline at end of file diff --git a/service-providers/network-requester/README.md b/service-providers/network-requester/README.md index a5006561ef..fb414d7e75 100644 --- a/service-providers/network-requester/README.md +++ b/service-providers/network-requester/README.md @@ -19,8 +19,7 @@ Running in `open-proxy` mode allows any traffic to be proxied by the network requester. ### Statistics service -The network requester can be build and ran as a gatherer of statistics from all -the other network requesters on the mixnet. For that, build the binary with the -`stats-service` feature enabled. The native client address that corresponds to -this network requester would have to be built into the constants of all the -other network requesters that are sending the data. \ No newline at end of file +The network requester can be ran as a gatherer of statistics for all +the services it proxies. For that, run the binary with the +`enable-statistics` flag enabled. Anonymized statistics are then sent to +a central server, through the mixnet. \ No newline at end of file diff --git a/service-providers/network-requester/src/connection.rs b/service-providers/network-requester/src/connection.rs index ee3aff024e..9d4374f76e 100644 --- a/service-providers/network-requester/src/connection.rs +++ b/service-providers/network-requester/src/connection.rs @@ -5,7 +5,7 @@ use futures::channel::mpsc; use nymsphinx::addressing::clients::Recipient; use proxy_helpers::connection_controller::ConnectionReceiver; use proxy_helpers::proxy_runner::ProxyRunner; -use socks5_requests::{ConnectionId, RemoteAddress, Response}; +use socks5_requests::{ConnectionId, Message as Socks5Message, RemoteAddress, Response}; use std::io; use tokio::net::TcpStream; @@ -39,7 +39,7 @@ impl Connection { pub(crate) async fn run_proxy( &mut self, mix_receiver: ConnectionReceiver, - mix_sender: mpsc::UnboundedSender<(Response, Recipient)>, + mix_sender: mpsc::UnboundedSender<(Socks5Message, Recipient)>, ) { let stream = self.conn.take().unwrap(); let remote_source_address = "???".to_string(); // we don't know ip address of requester @@ -54,7 +54,10 @@ impl Connection { connection_id, ) .run(move |conn_id, read_data, socket_closed| { - (Response::new(conn_id, read_data, socket_closed), recipient) + ( + Socks5Message::Response(Response::new(conn_id, read_data, socket_closed)), + recipient, + ) }) .await .into_inner(); diff --git a/service-providers/network-requester/src/core.rs b/service-providers/network-requester/src/core.rs index 315854a9da..74fd2fb509 100644 --- a/service-providers/network-requester/src/core.rs +++ b/service-providers/network-requester/src/core.rs @@ -3,22 +3,19 @@ use crate::allowed_hosts::{HostsStore, OutboundRequestFilter}; use crate::connection::Connection; -use crate::statistics::{Statistics, StatsData, Timer}; +use crate::statistics::{StatisticsCollector, StatisticsSender, Timer}; use crate::websocket; use crate::websocket::TSWebsocketStream; use futures::channel::mpsc; use futures::stream::{SplitSink, SplitStream}; use futures::{SinkExt, StreamExt}; use log::*; -use nymsphinx::addressing::clients::{ClientIdentity, Recipient}; +use nymsphinx::addressing::clients::Recipient; use nymsphinx::receiver::ReconstructedMessage; use proxy_helpers::connection_controller::{Controller, ControllerCommand, ControllerSender}; use socks5_requests::{ConnectionId, Message as Socks5Message, Request, Response}; -use std::collections::HashMap; use std::path::PathBuf; use std::sync::atomic::{AtomicUsize, Ordering}; -use std::sync::Arc; -use tokio::sync::RwLock; use tokio_tungstenite::tungstenite::protocol::Message; use websocket::WebsocketConnectionError; use websocket_requests::{requests::ClientRequest, responses::ServerResponse}; @@ -28,20 +25,18 @@ static ACTIVE_PROXIES: AtomicUsize = AtomicUsize::new(0); pub struct ServiceProvider { listening_address: String, - description: String, - #[cfg(feature = "stats-service")] - db_path: PathBuf, outbound_request_filter: OutboundRequestFilter, open_proxy: bool, enable_statistics: bool, + stats_provider_addr: Option, } impl ServiceProvider { pub fn new( listening_address: String, - description: String, open_proxy: bool, enable_statistics: bool, + stats_provider_addr: Option, ) -> ServiceProvider { let allowed_hosts = HostsStore::new( HostsStore::default_base_dir(), @@ -53,21 +48,13 @@ impl ServiceProvider { PathBuf::from("unknown.list"), ); - #[cfg(feature = "stats-service")] - let db_path = HostsStore::default_base_dir() - .join("service-providers") - .join("network-requester") - .join("db.sqlite"); - let outbound_request_filter = OutboundRequestFilter::new(allowed_hosts, unknown_hosts); ServiceProvider { listening_address, - description, - #[cfg(feature = "stats-service")] - db_path, outbound_request_filter, open_proxy, enable_statistics, + stats_provider_addr, } } @@ -75,21 +62,29 @@ impl ServiceProvider { /// via the `websocket_writer`. async fn mixnet_response_listener( mut websocket_writer: SplitSink, - mut mix_reader: mpsc::UnboundedReceiver<(Response, Recipient)>, - response_stats_data: &Option>>, + mut mix_reader: mpsc::UnboundedReceiver<(Socks5Message, Recipient)>, + stats_collector: Option, ) { // TODO: wire SURBs in here once they're available - while let Some((response, return_address)) = mix_reader.next().await { - if let Some(response_stats_data) = response_stats_data { - response_stats_data - .write() + while let Some((msg, return_address)) = mix_reader.next().await { + if let Some(stats_collector) = stats_collector.as_ref() { + if let Some(remote_addr) = stats_collector + .connected_services + .read() .await - .processed(return_address.identity(), response.data.len() as u32); + .get(&msg.conn_id()) + { + stats_collector + .response_stats_data + .write() + .await + .processed(remote_addr, msg.size() as u32); + } } // make 'request' to native-websocket client let response_message = ClientRequest::Send { recipient: return_address, - message: Socks5Message::Response(response).into_bytes(), + message: msg.into_bytes(), with_reply_surb: false, }; @@ -135,7 +130,7 @@ impl ServiceProvider { remote_addr: String, return_address: Recipient, controller_sender: ControllerSender, - mix_input_sender: mpsc::UnboundedSender<(Response, Recipient)>, + mix_input_sender: mpsc::UnboundedSender<(Socks5Message, Recipient)>, ) { let mut conn = match Connection::new(conn_id, remote_addr.clone(), return_address).await { Ok(conn) => conn, @@ -148,7 +143,10 @@ impl ServiceProvider { // inform the remote that the connection is closed before it even was established mix_input_sender - .unbounded_send((Response::new(conn_id, Vec::new(), true), return_address)) + .unbounded_send(( + Socks5Message::Response(Response::new(conn_id, Vec::new(), true)), + return_address, + )) .unwrap(); return; @@ -187,7 +185,7 @@ impl ServiceProvider { fn handle_proxy_connect( &mut self, controller_sender: &mut ControllerSender, - mix_input_sender: &mpsc::UnboundedSender<(Response, Recipient)>, + mix_input_sender: &mpsc::UnboundedSender<(Socks5Message, Recipient)>, conn_id: ConnectionId, remote_addr: String, return_address: Recipient, @@ -227,12 +225,10 @@ impl ServiceProvider { async fn handle_proxy_message( &mut self, - #[cfg(feature = "stats-service")] storage: &crate::storage::NetworkRequesterStorage, raw_request: &[u8], controller_sender: &mut ControllerSender, - mix_input_sender: &mpsc::UnboundedSender<(Response, Recipient)>, - request_stats_data: &Option>>, - connected_clients: &mut HashMap, + mix_input_sender: &mpsc::UnboundedSender<(Socks5Message, Recipient)>, + stats_collector: Option, ) { let deserialized_msg = match Socks5Message::try_from_bytes(raw_request) { Ok(msg) => msg, @@ -244,8 +240,12 @@ impl ServiceProvider { match deserialized_msg { Socks5Message::Request(deserialized_request) => match deserialized_request { Request::Connect(req) => { - if self.enable_statistics { - connected_clients.insert(req.conn_id, *req.return_address.identity()); + if let Some(stats_collector) = stats_collector { + stats_collector + .connected_services + .write() + .await + .insert(req.conn_id, req.remote_addr.clone()); } self.handle_proxy_connect( controller_sender, @@ -257,29 +257,24 @@ impl ServiceProvider { } Request::Send(conn_id, data, closed) => { - if let Some(request_stats_data) = request_stats_data { - if let Some(client_identity) = connected_clients.get(&conn_id) { - request_stats_data + if let Some(stats_collector) = stats_collector { + if let Some(remote_addr) = stats_collector + .connected_services + .read() + .await + .get(&conn_id) + { + stats_collector + .request_stats_data .write() .await - .processed(client_identity, data.len() as u32); + .processed(remote_addr, data.len() as u32); } } self.handle_proxy_send(controller_sender, conn_id, data, closed) } }, - Socks5Message::Response(_deserialized_response) => - { - #[cfg(feature = "stats-service")] - match crate::statistics::StatsMessage::from_bytes(&_deserialized_response.data) { - Ok(data) => { - if let Err(e) = storage.insert_service_statistics(data).await { - error!("Could not store received statistics: {}", e); - } - } - Err(e) => error!("Malformed statistics received: {}", e), - } - } + Socks5Message::Response(_) => {} } } @@ -292,7 +287,8 @@ impl ServiceProvider { // channels responsible for managing messages that are to be sent to the mix network. The receiver is // going to be used by `mixnet_response_listener` - let (mix_input_sender, mix_input_receiver) = mpsc::unbounded::<(Response, Recipient)>(); + let (mix_input_sender, mix_input_receiver) = + mpsc::unbounded::<(Socks5Message, Recipient)>(); let (mut timer_sender, timer_receiver) = Timer::new(); let interval = timer_sender.interval(); @@ -306,53 +302,35 @@ impl ServiceProvider { active_connections_controller.run().await; }); - let mut request_stats_data = None; - let mut response_stats_data = None; + let stats_collector = if self.enable_statistics { + let mut stats_sender = + StatisticsSender::new(interval, timer_receiver, self.stats_provider_addr) + .await + .expect("Statistics controller could not be bootstrapped"); + let stats_collector = StatisticsCollector::from(&stats_sender); - if self.enable_statistics { - let mut stats = Statistics::new(self.description.clone(), interval, timer_receiver) - .await - .expect("Statistics controller could not be bootstrapped"); - request_stats_data = Some(Arc::clone(stats.request_data())); - response_stats_data = Some(Arc::clone(stats.response_data())); let mix_input_sender_clone = mix_input_sender.clone(); tokio::spawn(async move { - stats.run(&mix_input_sender_clone).await; + stats_sender.run(&mix_input_sender_clone).await; }); - } - - #[cfg(feature = "stats-service")] - let storage = crate::storage::NetworkRequesterStorage::init(self.db_path.as_path()) - .await - .expect("Could not create network requester storage"); - - #[cfg(feature = "stats-service")] - tokio::spawn( - rocket::build() - .mount( - "/v1", - rocket::routes![crate::storage::post_mixnet_statistics], - ) - .manage(storage.clone()) - .ignite() - .await - .expect("Could not ignite stats api service") - .launch(), - ); + Some(stats_collector) + } else { + None + }; + let stats_collector_clone = stats_collector.clone(); // start the listener for mix messages tokio::spawn(async move { Self::mixnet_response_listener( websocket_writer, mix_input_receiver, - &response_stats_data, + stats_collector_clone, ) .await; }); println!("\nAll systems go. Press CTRL-C to stop the server."); // for each incoming message from the websocket... (which in 99.99% cases is going to be a mix message) - let mut connected_clients = HashMap::new(); loop { let received = match Self::read_websocket_message(&mut websocket_reader).await { Some(msg) => msg, @@ -366,13 +344,10 @@ impl ServiceProvider { // TODO: here be potential SURB (i.e. received.reply_SURB) self.handle_proxy_message( - #[cfg(feature = "stats-service")] - &storage, &raw_message, &mut controller_sender, &mix_input_sender, - &request_stats_data, - &mut connected_clients, + stats_collector.clone(), ) .await; } diff --git a/service-providers/network-requester/src/main.rs b/service-providers/network-requester/src/main.rs index a7a988ebc2..8b6d8d5834 100644 --- a/service-providers/network-requester/src/main.rs +++ b/service-providers/network-requester/src/main.rs @@ -4,19 +4,18 @@ use clap::{App, Arg, ArgMatches}; use network_defaults::DEFAULT_WEBSOCKET_LISTENING_PORT; +use nymsphinx::addressing::clients::Recipient; mod allowed_hosts; mod connection; mod core; mod statistics; -#[cfg(feature = "stats-service")] -mod storage; mod websocket; const OPEN_PROXY_ARG: &str = "open-proxy"; const WS_PORT: &str = "websocket-port"; -const DESCRIPTION: &str = "description"; const ENABLE_STATISTICS: &str = "enable-statistics"; +const STATISTICS_RECIPIENT: &str = "statistics-recipient"; fn parse_args<'a>() -> ArgMatches<'a> { App::new("Nym Network Requester") @@ -37,15 +36,14 @@ fn parse_args<'a>() -> ArgMatches<'a> { ) .arg( Arg::with_name(ENABLE_STATISTICS) - .help("enable mixnet statistics that get sent to a Nym server") - .long(ENABLE_STATISTICS) - .requires(DESCRIPTION), + .help("enable service statistics that get sent to a statistics aggregator server") + .long(ENABLE_STATISTICS), ) .arg( - Arg::with_name(DESCRIPTION) - .help("service description") - .long(DESCRIPTION) - .short("d") + Arg::with_name(STATISTICS_RECIPIENT) + .help("mixnet client address where a statistics aggregator is running. The default value is a Nym aggregator client") + .long(STATISTICS_RECIPIENT) + .requires(ENABLE_STATISTICS) .takes_value(true), ) .get_matches() @@ -63,9 +61,15 @@ async fn main() { let enable_statistics = matches.is_present(ENABLE_STATISTICS); if enable_statistics { - println!("\n\nTHE NETWORK REQUESTER STATISTICS ARE ENABLED. IT WILL COLLECT AND SEND STATISTICS TO A NYM SERVER. PLEASE QUIT IF YOU DON'T WANT THIS TO HAPPEN AND START WITHOUT THE {} FLAG .\n\n", ENABLE_STATISTICS); + println!("\n\nTHE NETWORK REQUESTER STATISTICS ARE ENABLED. IT WILL COLLECT AND SEND ANONYMIZED STATISTICS TO A CENTRAL SERVER. PLEASE QUIT IF YOU DON'T WANT THIS TO HAPPEN AND START WITHOUT THE {} FLAG .\n\n", ENABLE_STATISTICS); } + let stats_provider_addr = matches + .value_of(STATISTICS_RECIPIENT) + .map(Recipient::try_from_base58_string) + .transpose() + .unwrap_or(None); + let uri = format!( "ws://localhost:{}", matches @@ -73,12 +77,9 @@ async fn main() { .unwrap_or(&DEFAULT_WEBSOCKET_LISTENING_PORT.to_string()) ); - let description = matches - .value_of(DESCRIPTION) - .unwrap_or("undefined") - .to_string(); println!("Starting socks5 service provider:"); - let mut server = core::ServiceProvider::new(uri, description, open_proxy, enable_statistics); + let mut server = + core::ServiceProvider::new(uri, open_proxy, enable_statistics, stats_provider_addr); server.run().await; } diff --git a/service-providers/network-requester/src/statistics/comm.rs b/service-providers/network-requester/src/statistics/comm.rs index d92ac44d99..79f619b0db 100644 --- a/service-providers/network-requester/src/statistics/comm.rs +++ b/service-providers/network-requester/src/statistics/comm.rs @@ -4,7 +4,8 @@ use futures::channel::mpsc; use futures::StreamExt; use log::*; -use serde::{Deserialize, Serialize}; +use rand::RngCore; +use serde::Deserialize; use sqlx::types::chrono::{DateTime, Utc}; use std::collections::{HashMap, HashSet}; use std::sync::Arc; @@ -12,50 +13,20 @@ use std::time::Duration; use tokio::sync::RwLock; use network_defaults::DEFAULT_NETWORK; -use nymsphinx::addressing::clients::{ClientIdentity, Recipient}; -use socks5_requests::Response; +use nymsphinx::addressing::clients::Recipient; +use ordered_buffer::OrderedMessageSender; +use socks5_requests::{ConnectionId, Message as Socks5Message, RemoteAddress, Request}; +use statistics::api::{ + build_statistics_request_bytes, DEFAULT_STATISTICS_SERVICE_ADDRESS, + DEFAULT_STATISTICS_SERVICE_PORT, +}; +use statistics::{StatsMessage, StatsServiceData}; use super::error::StatsError; const REMOTE_SOURCE_OF_STATS_PROVIDER_CONFIG: &str = "https://nymtech.net/.wellknown/network-requester/stats-provider.json"; -#[derive(Clone, Debug, Deserialize, Serialize)] -pub struct StatsMessage { - pub description: String, - pub stats_data: Vec, - pub interval_seconds: u32, - pub timestamp: String, -} - -impl StatsMessage { - pub fn to_bytes(&self) -> Result, StatsError> { - Ok(bincode::serialize(self)?) - } - - #[cfg(feature = "stats-service")] - pub fn from_bytes(b: &[u8]) -> Result { - Ok(bincode::deserialize(b)?) - } -} - -#[derive(Clone, Debug, Deserialize, Serialize)] -pub struct StatsClientData { - pub client_identity: String, - pub request_bytes: u32, - pub response_bytes: u32, -} - -impl StatsClientData { - pub fn new(client_identity: String, request_bytes: u32, response_bytes: u32) -> Self { - StatsClientData { - client_identity, - request_bytes, - response_bytes, - } - } -} - #[derive(Clone, Debug)] pub struct StatsData { client_processed_bytes: HashMap, @@ -68,13 +39,12 @@ impl StatsData { } } - pub fn processed(&mut self, client_identity: &ClientIdentity, bytes: u32) { - let client_identity_bs58 = client_identity.to_base58_string(); - if let Some(curr_bytes) = self.client_processed_bytes.get_mut(&client_identity_bs58) { + pub fn processed(&mut self, remote_addr: &str, bytes: u32) { + if let Some(curr_bytes) = self.client_processed_bytes.get_mut(remote_addr) { *curr_bytes += bytes; } else { self.client_processed_bytes - .insert(client_identity_bs58, bytes); + .insert(remote_addr.to_string(), bytes); } } } @@ -103,8 +73,24 @@ impl OptionalStatsProviderConfig { } } -pub struct Statistics { - description: String, +#[derive(Clone)] +pub struct StatisticsCollector { + pub(crate) request_stats_data: Arc>, + pub(crate) response_stats_data: Arc>, + pub(crate) connected_services: Arc>>, +} + +impl StatisticsCollector { + pub fn from(stats: &StatisticsSender) -> Self { + Self { + request_stats_data: Arc::clone(&stats.request_data), + response_stats_data: Arc::clone(&stats.response_data), + connected_services: Arc::new(RwLock::new(HashMap::new())), + } + } +} + +pub struct StatisticsSender { request_data: Arc>, response_data: Arc>, interval_seconds: u32, @@ -113,11 +99,11 @@ pub struct Statistics { stats_provider_addr: Recipient, } -impl Statistics { +impl StatisticsSender { pub async fn new( - description: String, interval_seconds: Duration, timer_receiver: mpsc::Receiver<()>, + stats_provider_addr: Option, ) -> Result { let client = reqwest::Client::builder() .timeout(Duration::from_secs(3)) @@ -128,15 +114,16 @@ impl Statistics { .await? .json() .await?; - let stats_provider_addr = Recipient::try_from_base58_string( - stats_provider_config - .stats_client_address() - .ok_or(StatsError::InvalidClientAddress)?, - ) - .map_err(|_| StatsError::InvalidClientAddress)?; + let stats_provider_addr = stats_provider_addr.unwrap_or( + Recipient::try_from_base58_string( + stats_provider_config + .stats_client_address() + .ok_or(StatsError::InvalidClientAddress)?, + ) + .map_err(|_| StatsError::InvalidClientAddress)?, + ); - Ok(Statistics { - description, + Ok(StatisticsSender { request_data: Arc::new(RwLock::new(StatsData::new())), response_data: Arc::new(RwLock::new(StatsData::new())), timestamp: Utc::now(), @@ -146,15 +133,10 @@ impl Statistics { }) } - pub fn request_data(&self) -> &Arc> { - &self.request_data - } - - pub fn response_data(&self) -> &Arc> { - &self.response_data - } - - pub async fn run(&mut self, mix_input_sender: &mpsc::UnboundedSender<(Response, Recipient)>) { + pub async fn run( + &mut self, + mix_input_sender: &mpsc::UnboundedSender<(Socks5Message, Recipient)>, + ) { loop { if self.timer_receiver.next().await == None { error!("Timer thread has died. No more statistics will be sent"); @@ -162,42 +144,62 @@ impl Statistics { let stats_data = { let request_data_bytes = self.request_data.read().await; let response_data_bytes = self.response_data.read().await; - let clients: HashSet = request_data_bytes + let services: HashSet = request_data_bytes .client_processed_bytes .keys() .chain(response_data_bytes.client_processed_bytes.keys()) .cloned() .collect(); - clients + services .into_iter() - .map(|client_identity| { + .map(|requested_service| { let request_bytes = request_data_bytes .client_processed_bytes - .get(&client_identity) + .get(&requested_service) .copied() .unwrap_or(0); let response_bytes = response_data_bytes .client_processed_bytes - .get(&client_identity) + .get(&requested_service) .copied() .unwrap_or(0); - StatsClientData::new(client_identity, request_bytes, response_bytes) + StatsServiceData::new(requested_service, request_bytes, response_bytes) }) .collect() }; let stats_message = StatsMessage { - description: self.description.clone(), stats_data, interval_seconds: self.interval_seconds, timestamp: self.timestamp.to_rfc3339(), }; - match stats_message.to_bytes() { + match build_statistics_request_bytes(stats_message) { Ok(data) => { - trace!("Sending data to statistics service"); + trace!("Connecting to statistics service"); + let mut rng = rand::rngs::OsRng; + let conn_id = rng.next_u64(); + let connect_req = Request::new_connect( + conn_id, + format!( + "{}:{}", + DEFAULT_STATISTICS_SERVICE_ADDRESS, DEFAULT_STATISTICS_SERVICE_PORT + ), + self.stats_provider_addr, + ); mix_input_sender .unbounded_send(( - Response::new(0, data, false), + Socks5Message::Request(connect_req), + self.stats_provider_addr, + )) + .unwrap(); + + trace!("Sending data to statistics service"); + let mut message_sender = OrderedMessageSender::new(); + let ordered_msg = message_sender.wrap_message(data).into_bytes(); + let send_req = Request::new_send(conn_id, ordered_msg, true); + mix_input_sender + .unbounded_send(( + Socks5Message::Request(send_req), self.stats_provider_addr, )) .unwrap(); diff --git a/service-providers/network-requester/src/statistics/error.rs b/service-providers/network-requester/src/statistics/error.rs index 7ca0d1f22b..eadc188c5a 100644 --- a/service-providers/network-requester/src/statistics/error.rs +++ b/service-providers/network-requester/src/statistics/error.rs @@ -5,9 +5,6 @@ use thiserror::Error; #[derive(Debug, Error)] pub enum StatsError { - #[error("Bincode error: {0}")] - BincodeError(#[from] bincode::Error), - #[error("Reqwuest error {0}")] ReqwestError(#[from] reqwest::Error), diff --git a/service-providers/network-requester/src/statistics/mod.rs b/service-providers/network-requester/src/statistics/mod.rs index 257c405915..8284283801 100644 --- a/service-providers/network-requester/src/statistics/mod.rs +++ b/service-providers/network-requester/src/statistics/mod.rs @@ -5,5 +5,5 @@ mod comm; mod error; mod timer; -pub use comm::{Statistics, StatsClientData, StatsData, StatsMessage}; +pub use comm::{StatisticsCollector, StatisticsSender, StatsData}; pub use timer::Timer; diff --git a/service-providers/network-requester/src/storage/routes.rs b/service-providers/network-requester/src/storage/routes.rs deleted file mode 100644 index 2c76e24c38..0000000000 --- a/service-providers/network-requester/src/storage/routes.rs +++ /dev/null @@ -1,52 +0,0 @@ -// Copyright 2022 - Nym Technologies SA -// SPDX-License-Identifier: Apache-2.0 - -use rocket::serde::json::Json; -use rocket::State; -use serde::{Deserialize, Serialize}; - -use crate::storage::NetworkRequesterStorage; - -#[derive(Clone, Serialize, Deserialize, Debug)] -pub struct MixnetStatisticsRequest { - // date, RFC 3339 format - since: String, - // date, RFC 3339 format - until: String, -} - -#[derive(Clone, Serialize, Deserialize, Debug)] -pub struct MixnetStatisticsResponse { - pub service_description: String, - pub client_identity: String, - pub request_processed_bytes: u32, - pub response_processed_bytes: u32, - pub interval_seconds: u32, - pub timestamp: String, -} - -#[rocket::post("/mixnet-statistics", data = "")] -pub(crate) async fn post_mixnet_statistics( - mixnet_statistics_request: Json, - storage: &State, -) -> Json> { - let mixnet_statistics = storage - .get_service_statistics_in_interval( - &mixnet_statistics_request.since, - &mixnet_statistics_request.until, - ) - .await - .unwrap() - .into_iter() - .map(|data| MixnetStatisticsResponse { - service_description: data.service_description, - client_identity: data.client_identity, - request_processed_bytes: data.request_processed_bytes as u32, - response_processed_bytes: data.response_processed_bytes as u32, - interval_seconds: data.interval_seconds as u32, - timestamp: data.timestamp.to_string(), - }) - .collect(); - - Json(mixnet_statistics) -} diff --git a/service-providers/network-statistics/Cargo.toml b/service-providers/network-statistics/Cargo.toml new file mode 100644 index 0000000000..de08cf0785 --- /dev/null +++ b/service-providers/network-statistics/Cargo.toml @@ -0,0 +1,23 @@ +[package] +name = "nym-network-statistics" +version = "0.1.0" +edition = "2021" + +# See more keys and their definitions at https://doc.rust-lang.org/cargo/reference/manifest.html + +[dependencies] +dirs = "3.0" +log = "0.4" +pretty_env_logger = "0.4" +rocket = { version = "0.5.0-rc.1", features = ["json"] } +serde = { version = "1.0", features = ["derive"] } +sqlx = { version = "0.5", features = ["runtime-tokio-rustls", "sqlite", "macros", "migrate", "chrono"]} +thiserror = "1" +tokio = { version = "1.4", features = [ "net", "rt-multi-thread", "macros", "time" ] } +tokio-tungstenite = "0.14" + +statistics = { path = "../../common/statistics" } + +[build-dependencies] +sqlx = { version = "0.5", features = ["runtime-tokio-rustls", "sqlite", "macros", "migrate"] } +tokio = { version = "1.4", features = ["rt-multi-thread", "macros"] } diff --git a/service-providers/network-statistics/Rocket.toml b/service-providers/network-statistics/Rocket.toml new file mode 100644 index 0000000000..5828739b6f --- /dev/null +++ b/service-providers/network-statistics/Rocket.toml @@ -0,0 +1,7 @@ +[default] +limits = { forms = "64 kB", json = "1 MiB" } +port = 8090 +address = "127.0.0.1" + +[release] +address = "0.0.0.0" \ No newline at end of file diff --git a/service-providers/network-requester/build.rs b/service-providers/network-statistics/build.rs similarity index 91% rename from service-providers/network-requester/build.rs rename to service-providers/network-statistics/build.rs index 73e5fdf775..b8baded838 100644 --- a/service-providers/network-requester/build.rs +++ b/service-providers/network-statistics/build.rs @@ -7,7 +7,7 @@ use std::env; #[tokio::main] async fn main() { let out_dir = env::var("OUT_DIR").unwrap(); - let database_path = format!("{}/network-requester-example.sqlite", out_dir); + let database_path = format!("{}/network-statistics-example.sqlite", out_dir); let mut conn = SqliteConnection::connect(&*format!("sqlite://{}?mode=rwc", database_path)) .await diff --git a/service-providers/network-requester/migrations/20220512120000_mixnet_statistics.sql b/service-providers/network-statistics/migrations/20220512120000_mixnet_statistics.sql similarity index 74% rename from service-providers/network-requester/migrations/20220512120000_mixnet_statistics.sql rename to service-providers/network-statistics/migrations/20220512120000_mixnet_statistics.sql index 5370884e27..51514df755 100644 --- a/service-providers/network-requester/migrations/20220512120000_mixnet_statistics.sql +++ b/service-providers/network-statistics/migrations/20220512120000_mixnet_statistics.sql @@ -3,11 +3,10 @@ * SPDX-License-Identifier: Apache-2.0 */ -CREATE TABLE mixnet_statistics +CREATE TABLE service_statistics ( id INTEGER NOT NULL PRIMARY KEY AUTOINCREMENT, - service_description VARCHAR NOT NULL, - client_identity VARCHAR NOT NULL, + requested_service VARCHAR NOT NULL, request_processed_bytes INTEGER NOT NULL, response_processed_bytes INTEGER NOT NULL, interval_seconds INTEGER NOT NULL, diff --git a/service-providers/network-statistics/src/api/error.rs b/service-providers/network-statistics/src/api/error.rs new file mode 100644 index 0000000000..d2b190840e --- /dev/null +++ b/service-providers/network-statistics/src/api/error.rs @@ -0,0 +1,31 @@ +// Copyright 2022 - Nym Technologies SA +// SPDX-License-Identifier: Apache-2.0 + +use rocket::http::{ContentType, Status}; +use rocket::response::Responder; +use rocket::{response, Request, Response}; +use std::io::Cursor; + +use crate::storage::error::NetworkStatisticsStorageError; + +pub type Result = std::result::Result; + +#[derive(Debug, thiserror::Error)] +pub enum NetworkStatisticsAPIError { + #[error("{0}")] + RocketError(#[from] Box), + + #[error("{0}")] + StorageError(#[from] NetworkStatisticsStorageError), +} + +impl<'r, 'o: 'r> Responder<'r, 'o> for NetworkStatisticsAPIError { + fn respond_to(self, _: &'r Request<'_>) -> response::Result<'o> { + let err_msg = self.to_string(); + Response::build() + .header(ContentType::Plain) + .sized_body(err_msg.len(), Cursor::new(err_msg)) + .status(Status::BadRequest) + .ok() + } +} diff --git a/service-providers/network-statistics/src/api/mod.rs b/service-providers/network-statistics/src/api/mod.rs new file mode 100644 index 0000000000..3a30d8ebb8 --- /dev/null +++ b/service-providers/network-statistics/src/api/mod.rs @@ -0,0 +1,48 @@ +// Copyright 2022 - Nym Technologies SA +// SPDX-License-Identifier: Apache-2.0 + +use log::*; +use rocket::{Ignite, Rocket}; + +use crate::storage::NetworkStatisticsStorage; +use error::Result; +use routes::{post_all_statistics, post_statistic}; + +use statistics::api::STATISTICS_SERVICE_VERSION; + +mod error; +mod routes; + +pub(crate) struct NetworkStatisticsAPI { + rocket: Rocket, +} + +impl NetworkStatisticsAPI { + pub async fn init(storage: NetworkStatisticsStorage) -> Result { + let rocket = rocket::build() + .mount( + STATISTICS_SERVICE_VERSION, + rocket::routes![post_all_statistics, post_statistic], + ) + .manage(storage.clone()) + .ignite() + .await + .map_err(Box::new)?; + + Ok(NetworkStatisticsAPI { rocket }) + } + + pub async fn run(self) { + let shutdown_handle = self.rocket.shutdown(); + tokio::spawn(self.rocket.launch()); + + if let Err(e) = tokio::signal::ctrl_c().await { + error!( + "There was an error while capturing SIGINT - {:?}. We will terminate regardless", + e + ); + } + info!("Received SIGINT - the network statistics API will terminate now"); + shutdown_handle.notify(); + } +} diff --git a/service-providers/network-statistics/src/api/routes.rs b/service-providers/network-statistics/src/api/routes.rs new file mode 100644 index 0000000000..5f5c9bb3b1 --- /dev/null +++ b/service-providers/network-statistics/src/api/routes.rs @@ -0,0 +1,61 @@ +// Copyright 2022 - Nym Technologies SA +// SPDX-License-Identifier: Apache-2.0 + +use rocket::serde::json::Json; +use rocket::State; +use serde::{Deserialize, Serialize}; + +use statistics::StatsMessage; + +use crate::api::error::Result; +use crate::storage::NetworkStatisticsStorage; + +#[derive(Clone, Serialize, Deserialize, Debug)] +pub struct ServiceStatisticsRequest { + // date, RFC 3339 format + since: String, + // date, RFC 3339 format + until: String, +} + +#[derive(Clone, Serialize, Deserialize, Debug)] +pub struct ServiceStatistic { + pub requested_service: String, + pub request_processed_bytes: u32, + pub response_processed_bytes: u32, + pub interval_seconds: u32, + pub timestamp: String, +} + +#[rocket::post("/all-statistics", data = "")] +pub(crate) async fn post_all_statistics( + all_statistics_request: Json, + storage: &State, +) -> Result>> { + let service_statistics = storage + .get_service_statistics_in_interval( + &all_statistics_request.since, + &all_statistics_request.until, + ) + .await? + .into_iter() + .map(|data| ServiceStatistic { + requested_service: data.requested_service, + request_processed_bytes: data.request_processed_bytes as u32, + response_processed_bytes: data.response_processed_bytes as u32, + interval_seconds: data.interval_seconds as u32, + timestamp: data.timestamp.to_string(), + }) + .collect(); + + Ok(Json(service_statistics)) +} + +#[rocket::post("/statistic", data = "")] +pub(crate) async fn post_statistic( + statistic: Json, + storage: &State, +) -> Result> { + storage.insert_service_statistics(statistic.0).await?; + Ok(Json(())) +} diff --git a/service-providers/network-statistics/src/main.rs b/service-providers/network-statistics/src/main.rs new file mode 100644 index 0000000000..0a32438a80 --- /dev/null +++ b/service-providers/network-statistics/src/main.rs @@ -0,0 +1,53 @@ +// Copyright 2022 - Nym Technologies SA +// SPDX-License-Identifier: Apache-2.0 + +use std::path::PathBuf; + +use api::NetworkStatisticsAPI; + +mod api; +mod storage; + +#[tokio::main] +async fn main() { + setup_logging(); + + let base_dir = default_base_dir(); + let storage = storage::NetworkStatisticsStorage::init(&base_dir) + .await + .expect("Could not create network statistics storage"); + + let api = NetworkStatisticsAPI::init(storage) + .await + .expect("Could not ignite stats api service"); + api.run().await; +} + +fn setup_logging() { + let mut log_builder = pretty_env_logger::formatted_timed_builder(); + if let Ok(s) = ::std::env::var("RUST_LOG") { + log_builder.parse_filters(&s); + } else { + // default to 'Info' + log_builder.filter(None, log::LevelFilter::Info); + } + + log_builder + .filter_module("hyper", log::LevelFilter::Warn) + .filter_module("tokio_reactor", log::LevelFilter::Warn) + .filter_module("reqwest", log::LevelFilter::Warn) + .filter_module("mio", log::LevelFilter::Warn) + .filter_module("want", log::LevelFilter::Warn) + .init(); +} + +/// Returns the default base directory for the storefile. +/// +/// This is split out so we can easily inject our own base_dir for unit tests. +fn default_base_dir() -> PathBuf { + dirs::home_dir() + .expect("no home directory known for this OS") + .join(".nym") + .join("service-providers") + .join("network-statistics") +} diff --git a/service-providers/network-requester/src/storage/error.rs b/service-providers/network-statistics/src/storage/error.rs similarity index 76% rename from service-providers/network-requester/src/storage/error.rs rename to service-providers/network-statistics/src/storage/error.rs index 1df83a46fd..48253a261b 100644 --- a/service-providers/network-requester/src/storage/error.rs +++ b/service-providers/network-statistics/src/storage/error.rs @@ -2,7 +2,10 @@ // SPDX-License-Identifier: Apache-2.0 #[derive(Debug, thiserror::Error)] -pub enum NetworkRequesterStorageError { +pub enum NetworkStatisticsStorageError { + #[error("File system error - {0}")] + FSError(#[from] std::io::Error), + #[error("SQL error - {0}")] InternalDatabaseError(#[from] sqlx::Error), diff --git a/service-providers/network-requester/src/storage/manager.rs b/service-providers/network-statistics/src/storage/manager.rs similarity index 70% rename from service-providers/network-requester/src/storage/manager.rs rename to service-providers/network-statistics/src/storage/manager.rs index a60712de11..4fda9d7bd0 100644 --- a/service-providers/network-requester/src/storage/manager.rs +++ b/service-providers/network-statistics/src/storage/manager.rs @@ -3,7 +3,7 @@ use sqlx::types::chrono::{DateTime, Utc}; -use crate::storage::models::MixnetStatistics; +use crate::storage::models::ServiceStatistics; #[derive(Clone)] pub(crate) struct StorageManager { @@ -16,24 +16,21 @@ impl StorageManager { /// /// # Arguments /// - /// * `service_description`: Description of the service that gathered the data. - /// * `client_identity`: Client that connected to the service. + /// * `requested_service`: Address of the service requested. /// * `request_processed_bytes`: Number of bytes for socks5 requests. /// * `response_processed_bytes`: Number of bytes for socks5 responses. /// * `interval_seconds`: Duration in seconds in which the data was gathered. pub(super) async fn insert_service_statistics( &self, - service_description: String, - client_identity: String, + requested_service: String, request_processed_bytes: u32, response_processed_bytes: u32, interval_seconds: u32, timestamp: DateTime, ) -> Result<(), sqlx::Error> { sqlx::query!( - "INSERT INTO mixnet_statistics(service_description, client_identity, request_processed_bytes, response_processed_bytes, interval_seconds, timestamp) VALUES (?, ?, ?, ?, ?, ?)", - service_description, - client_identity, + "INSERT INTO service_statistics(requested_service, request_processed_bytes, response_processed_bytes, interval_seconds, timestamp) VALUES (?, ?, ?, ?, ?)", + requested_service, request_processed_bytes, response_processed_bytes, interval_seconds, @@ -55,10 +52,10 @@ impl StorageManager { &self, since: DateTime, until: DateTime, - ) -> Result, sqlx::Error> { + ) -> Result, sqlx::Error> { sqlx::query_as!( - MixnetStatistics, - "SELECT * FROM mixnet_statistics WHERE timestamp BETWEEN ? AND ?", + ServiceStatistics, + "SELECT * FROM service_statistics WHERE timestamp BETWEEN ? AND ?", since, until ) diff --git a/service-providers/network-requester/src/storage/mod.rs b/service-providers/network-statistics/src/storage/mod.rs similarity index 66% rename from service-providers/network-requester/src/storage/mod.rs rename to service-providers/network-statistics/src/storage/mod.rs index 2e35565d24..ac7cdb8bdd 100644 --- a/service-providers/network-requester/src/storage/mod.rs +++ b/service-providers/network-statistics/src/storage/mod.rs @@ -4,27 +4,28 @@ use log::*; use sqlx::types::chrono::{DateTime, Utc}; use sqlx::ConnectOptions; -use std::path::Path; +use std::path::PathBuf; -use crate::statistics::StatsMessage; -use crate::storage::error::NetworkRequesterStorageError; +use statistics::StatsMessage; + +use crate::storage::error::NetworkStatisticsStorageError; use crate::storage::manager::StorageManager; -use crate::storage::models::MixnetStatistics; -pub(crate) use crate::storage::routes::post_mixnet_statistics; +use crate::storage::models::ServiceStatistics; -mod error; +pub(crate) mod error; mod manager; mod models; -mod routes; // note that clone here is fine as upon cloning the same underlying pool will be used #[derive(Clone)] -pub(crate) struct NetworkRequesterStorage { +pub(crate) struct NetworkStatisticsStorage { manager: StorageManager, } -impl NetworkRequesterStorage { - pub async fn init(database_path: &Path) -> Result { +impl NetworkStatisticsStorage { + pub async fn init(base_dir: &PathBuf) -> Result { + std::fs::create_dir_all(base_dir)?; + let database_path = base_dir.join("db.sqlite"); let mut opts = sqlx::sqlite::SqliteConnectOptions::new() .filename(database_path) .create_if_missing(true); @@ -36,7 +37,7 @@ impl NetworkRequesterStorage { sqlx::migrate!("./migrations").run(&connection_pool).await?; info!("Database migration finished!"); - let storage = NetworkRequesterStorage { + let storage = NetworkStatisticsStorage { manager: StorageManager { connection_pool }, }; @@ -51,17 +52,16 @@ impl NetworkRequesterStorage { pub(super) async fn insert_service_statistics( &self, msg: StatsMessage, - ) -> Result<(), NetworkRequesterStorageError> { + ) -> Result<(), NetworkStatisticsStorageError> { let timestamp: DateTime = DateTime::parse_from_rfc3339(&msg.timestamp) - .map_err(|_| NetworkRequesterStorageError::TimestampParse)? + .map_err(|_| NetworkStatisticsStorageError::TimestampParse)? .into(); - for client_data in msg.stats_data { + for service_data in msg.stats_data { self.manager .insert_service_statistics( - msg.description.clone(), - client_data.client_identity.clone(), - client_data.request_bytes, - client_data.response_bytes, + service_data.requested_service.clone(), + service_data.request_bytes, + service_data.response_bytes, msg.interval_seconds, timestamp, ) @@ -81,12 +81,12 @@ impl NetworkRequesterStorage { &self, since: &str, until: &str, - ) -> Result, NetworkRequesterStorageError> { + ) -> Result, NetworkStatisticsStorageError> { let since = DateTime::parse_from_rfc3339(since) - .map_err(|_| NetworkRequesterStorageError::TimestampParse)? + .map_err(|_| NetworkStatisticsStorageError::TimestampParse)? .into(); let until = DateTime::parse_from_rfc3339(until) - .map_err(|_| NetworkRequesterStorageError::TimestampParse)? + .map_err(|_| NetworkStatisticsStorageError::TimestampParse)? .into(); Ok(self .manager diff --git a/service-providers/network-requester/src/storage/models.rs b/service-providers/network-statistics/src/storage/models.rs similarity index 78% rename from service-providers/network-requester/src/storage/models.rs rename to service-providers/network-statistics/src/storage/models.rs index 7c08292a2c..1f3ee3e1de 100644 --- a/service-providers/network-requester/src/storage/models.rs +++ b/service-providers/network-statistics/src/storage/models.rs @@ -4,11 +4,10 @@ use sqlx::types::chrono::NaiveDateTime; // Internally used struct to catch results from the database to get mixnet statistics -pub(crate) struct MixnetStatistics { +pub(crate) struct ServiceStatistics { #[allow(dead_code)] pub(crate) id: i64, - pub(crate) service_description: String, - pub(crate) client_identity: String, + pub(crate) requested_service: String, pub(crate) request_processed_bytes: i64, pub(crate) response_processed_bytes: i64, pub(crate) interval_seconds: i64,