Compare commits

..

12 Commits

Author SHA1 Message Date
fmtabbara 43d6908d22 display loading modal for initial loading of values
run cargo fmt

fix clippy error

minor fixes
2022-12-19 09:38:00 +00:00
fmtabbara e10f291ee9 set active set to be always true 2022-12-19 09:38:00 +00:00
Jon Häggblad ecc89ced08 Make ComputeRewardEstParam derive Debug 2022-12-19 09:38:00 +00:00
fmtabbara 1e10c247bc calculate saturation
tidy

Use NodeId in compute_mixnode_reward_estimation

only call handleCalculation on button click

fix validation tests

tweak calculations

calculate stake saturation

pick up and display errors

pass profit margin and operator cost as args

rebase develop

rebase develop

fix profit margin validation

tidy up

refactor requests for rewards playground

wip
2022-12-19 09:38:00 +00:00
fmtabbara 4584f35a2a get mixnode reward estimation
separarte handleCalculate function into own file

add mix-id to bondedNode state

remove unused imports
2022-12-19 09:38:00 +00:00
fmtabbara 41fa03862e get node uptime 2022-12-19 09:38:00 +00:00
fmtabbara 66303d7ca4 init playground with default values
add more default values

env updates
2022-12-19 09:38:00 +00:00
fmtabbara 480f8a0a53 update validation for rewards playground 2022-12-19 09:38:00 +00:00
fmtabbara ecb0f11bbb add initial rewards calculation
run make file
2022-12-19 09:38:00 +00:00
fmtabbara fe223b5a60 apy playground ui
update calc button style

validator-api-client and wallet: compute mixnode reward estimation
2022-12-19 09:37:45 +00:00
fmtabbara b9e52d22d1 add print to pdf package 2022-12-19 09:36:56 +00:00
fmtabbara ecdf192b47 initial ui for test my node
use svg for node path

adjust layout for overiew page

add stories for test my node

remove placeholder nav item

add top margin to app bar

add print to pdf functionality for node test results
2022-12-19 09:36:56 +00:00
490 changed files with 22600 additions and 15490 deletions
+1 -1
View File
@@ -14,7 +14,7 @@ GEOIPUPDATE_LICENSE_KEY=xxx
# List of space-separated database edition IDs. Edition IDs may # List of space-separated database edition IDs. Edition IDs may
# consist of letters, digits, and dashes. For example, GeoIP2-City # consist of letters, digits, and dashes. For example, GeoIP2-City
# would download the GeoIP2 City database (GeoIP2-City). # would download the GeoIP2 City database (GeoIP2-City).
GEOIPUPDATE_EDITION_IDS=GeoLite2-City GEOIPUPDATE_EDITION_IDS=GeoLite2-Country
# The number of hours between geoipupdate runs. If this is not set # The number of hours between geoipupdate runs. If this is not set
# or is set to 0, geoipupdate will run once and exit. # or is set to 0, geoipupdate will run once and exit.
GEOIPUPDATE_FREQUENCY=72 GEOIPUPDATE_FREQUENCY=72
-5
View File
@@ -47,11 +47,6 @@ jobs:
KEYBASE_NYMBOT_PAPERKEY: "${{ secrets.KEYBASE_NYMBOT_PAPERKEY }}" KEYBASE_NYMBOT_PAPERKEY: "${{ secrets.KEYBASE_NYMBOT_PAPERKEY }}"
KEYBASE_NYMBOT_TEAM: "${{ secrets.KEYBASE_NYMBOT_TEAM }}" KEYBASE_NYMBOT_TEAM: "${{ secrets.KEYBASE_NYMBOT_TEAM }}"
KEYBASE_NYM_CHANNEL: "security" KEYBASE_NYM_CHANNEL: "security"
MATRIX_SERVER: "${{ secrets.MATRIX_SERVER }}"
MATRIX_ROOM: "${{ secrets.MATRIX_ROOM }}"
MATRIX_USER_ID: "${{ secrets.MATRIX_USER_ID }}"
MATRIX_TOKEN: "${{ secrets.MATRIX_TOKEN }}"
MATRIX_DEVICE_ID: "${{ secrets.MATRIX_DEVICE_ID }}"
uses: docker://keybaseio/client:stable-node uses: docker://keybaseio/client:stable-node
with: with:
args: .github/workflows/support-files/notifications/entry_point.sh args: .github/workflows/support-files/notifications/entry_point.sh
-5
View File
@@ -58,11 +58,6 @@ jobs:
KEYBASE_NYMBOT_TEAM: "${{ secrets.KEYBASE_NYMBOT_TEAM }}" KEYBASE_NYMBOT_TEAM: "${{ secrets.KEYBASE_NYMBOT_TEAM }}"
KEYBASE_NYM_CHANNEL: "ci-ts-packages" KEYBASE_NYM_CHANNEL: "ci-ts-packages"
IS_SUCCESS: "${{ job.status == 'success' }}" IS_SUCCESS: "${{ job.status == 'success' }}"
MATRIX_SERVER: "${{ secrets.MATRIX_SERVER }}"
MATRIX_ROOM: "${{ secrets.MATRIX_ROOM }}"
MATRIX_USER_ID: "${{ secrets.MATRIX_USER_ID }}"
MATRIX_TOKEN: "${{ secrets.MATRIX_TOKEN }}"
MATRIX_DEVICE_ID: "${{ secrets.MATRIX_DEVICE_ID }}"
uses: docker://keybaseio/client:stable-node uses: docker://keybaseio/client:stable-node
with: with:
args: .github/workflows/support-files/notifications/entry_point.sh args: .github/workflows/support-files/notifications/entry_point.sh
+1 -1
View File
@@ -11,7 +11,7 @@ on:
jobs: jobs:
build: build:
runs-on: [ self-hosted, custom-linux ] runs-on: [ self-hosted, custom-linux ]
# Enable sccache via environment variable # Enable sccache via environment variable
env: env:
RUSTC_WRAPPER: /home/ubuntu/.cargo/bin/sccache RUSTC_WRAPPER: /home/ubuntu/.cargo/bin/sccache
steps: steps:
-5
View File
@@ -73,11 +73,6 @@ jobs:
KEYBASE_NYMBOT_TEAM: "${{ secrets.KEYBASE_NYMBOT_TEAM }}" KEYBASE_NYMBOT_TEAM: "${{ secrets.KEYBASE_NYMBOT_TEAM }}"
KEYBASE_NYM_CHANNEL: "ci-network-explorer" KEYBASE_NYM_CHANNEL: "ci-network-explorer"
IS_SUCCESS: "${{ job.status == 'success' }}" IS_SUCCESS: "${{ job.status == 'success' }}"
MATRIX_SERVER: "${{ secrets.MATRIX_SERVER }}"
MATRIX_ROOM: "${{ secrets.MATRIX_ROOM }}"
MATRIX_USER_ID: "${{ secrets.MATRIX_USER_ID }}"
MATRIX_TOKEN: "${{ secrets.MATRIX_TOKEN }}"
MATRIX_DEVICE_ID: "${{ secrets.MATRIX_DEVICE_ID }}"
uses: docker://keybaseio/client:stable-node uses: docker://keybaseio/client:stable-node
with: with:
args: .github/workflows/support-files/notifications/entry_point.sh args: .github/workflows/support-files/notifications/entry_point.sh
-5
View File
@@ -183,11 +183,6 @@ jobs:
KEYBASE_NYMBOT_TEAM: "${{ secrets.KEYBASE_NYMBOT_TEAM }}" KEYBASE_NYMBOT_TEAM: "${{ secrets.KEYBASE_NYMBOT_TEAM }}"
KEYBASE_NYM_CHANNEL: "ci-nightly" KEYBASE_NYM_CHANNEL: "ci-nightly"
IS_SUCCESS: "${{ env.WORKFLOW_CONCLUSION == 'success' }}" IS_SUCCESS: "${{ env.WORKFLOW_CONCLUSION == 'success' }}"
MATRIX_SERVER: "${{ secrets.MATRIX_SERVER }}"
MATRIX_ROOM: "${{ secrets.MATRIX_ROOM }}"
MATRIX_USER_ID: "${{ secrets.MATRIX_USER_ID }}"
MATRIX_TOKEN: "${{ secrets.MATRIX_TOKEN }}"
MATRIX_DEVICE_ID: "${{ secrets.MATRIX_DEVICE_ID }}"
uses: docker://keybaseio/client:stable-node uses: docker://keybaseio/client:stable-node
with: with:
args: .github/workflows/support-files/notifications/entry_point.sh args: .github/workflows/support-files/notifications/entry_point.sh
@@ -198,11 +198,6 @@ jobs:
KEYBASE_NYMBOT_TEAM: "${{ secrets.KEYBASE_NYMBOT_TEAM }}" KEYBASE_NYMBOT_TEAM: "${{ secrets.KEYBASE_NYMBOT_TEAM }}"
KEYBASE_NYM_CHANNEL: "ci-nightly-release" KEYBASE_NYM_CHANNEL: "ci-nightly-release"
IS_SUCCESS: "${{ env.WORKFLOW_CONCLUSION == 'success' }}" IS_SUCCESS: "${{ env.WORKFLOW_CONCLUSION == 'success' }}"
MATRIX_SERVER: "${{ secrets.MATRIX_SERVER }}"
MATRIX_ROOM: "${{ secrets.MATRIX_ROOM }}"
MATRIX_USER_ID: "${{ secrets.MATRIX_USER_ID }}"
MATRIX_TOKEN: "${{ secrets.MATRIX_TOKEN }}"
MATRIX_DEVICE_ID: "${{ secrets.MATRIX_DEVICE_ID }}"
uses: docker://keybaseio/client:stable-node uses: docker://keybaseio/client:stable-node
with: with:
args: .github/workflows/support-files/notifications/entry_point.sh args: .github/workflows/support-files/notifications/entry_point.sh
@@ -198,11 +198,6 @@ jobs:
KEYBASE_NYMBOT_TEAM: "${{ secrets.KEYBASE_NYMBOT_TEAM }}" KEYBASE_NYMBOT_TEAM: "${{ secrets.KEYBASE_NYMBOT_TEAM }}"
KEYBASE_NYM_CHANNEL: "ci-nightly-release" KEYBASE_NYM_CHANNEL: "ci-nightly-release"
IS_SUCCESS: "${{ env.WORKFLOW_CONCLUSION == 'success' }}" IS_SUCCESS: "${{ env.WORKFLOW_CONCLUSION == 'success' }}"
MATRIX_SERVER: "${{ secrets.MATRIX_SERVER }}"
MATRIX_ROOM: "${{ secrets.MATRIX_ROOM }}"
MATRIX_USER_ID: "${{ secrets.MATRIX_USER_ID }}"
MATRIX_TOKEN: "${{ secrets.MATRIX_TOKEN }}"
MATRIX_DEVICE_ID: "${{ secrets.MATRIX_DEVICE_ID }}"
uses: docker://keybaseio/client:stable-node uses: docker://keybaseio/client:stable-node
with: with:
args: .github/workflows/support-files/notifications/entry_point.sh args: .github/workflows/support-files/notifications/entry_point.sh
-5
View File
@@ -54,11 +54,6 @@ jobs:
KEYBASE_NYMBOT_TEAM: "${{ secrets.KEYBASE_NYMBOT_TEAM }}" KEYBASE_NYMBOT_TEAM: "${{ secrets.KEYBASE_NYMBOT_TEAM }}"
KEYBASE_NYM_CHANNEL: "ci-nym-connect" KEYBASE_NYM_CHANNEL: "ci-nym-connect"
IS_SUCCESS: "${{ job.status == 'success' }}" IS_SUCCESS: "${{ job.status == 'success' }}"
MATRIX_SERVER: "${{ secrets.MATRIX_SERVER }}"
MATRIX_ROOM: "${{ secrets.MATRIX_ROOM }}"
MATRIX_USER_ID: "${{ secrets.MATRIX_USER_ID }}"
MATRIX_TOKEN: "${{ secrets.MATRIX_TOKEN }}"
MATRIX_DEVICE_ID: "${{ secrets.MATRIX_DEVICE_ID }}"
uses: docker://keybaseio/client:stable-node uses: docker://keybaseio/client:stable-node
with: with:
args: .github/workflows/support-files/notifications/entry_point.sh args: .github/workflows/support-files/notifications/entry_point.sh
@@ -50,11 +50,6 @@ jobs:
KEYBASE_NYMBOT_TEAM: "${{ secrets.KEYBASE_NYMBOT_TEAM }}" KEYBASE_NYMBOT_TEAM: "${{ secrets.KEYBASE_NYMBOT_TEAM }}"
KEYBASE_NYM_CHANNEL: "ci-nym-wallet" KEYBASE_NYM_CHANNEL: "ci-nym-wallet"
IS_SUCCESS: "${{ job.status == 'success' }}" IS_SUCCESS: "${{ job.status == 'success' }}"
MATRIX_SERVER: "${{ secrets.MATRIX_SERVER }}"
MATRIX_ROOM: "${{ secrets.MATRIX_ROOM }}"
MATRIX_USER_ID: "${{ secrets.MATRIX_USER_ID }}"
MATRIX_TOKEN: "${{ secrets.MATRIX_TOKEN }}"
MATRIX_DEVICE_ID: "${{ secrets.MATRIX_DEVICE_ID }}"
uses: docker://keybaseio/client:stable-node uses: docker://keybaseio/client:stable-node
with: with:
args: .github/workflows/support-files/notifications/entry_point.sh args: .github/workflows/support-files/notifications/entry_point.sh
@@ -2,13 +2,6 @@ KEYBASE_NYM_CHANNEL=
KEYBASE_NYMBOT_USERNAME= KEYBASE_NYMBOT_USERNAME=
KEYBASE_NYMBOT_PAPERKEY= KEYBASE_NYMBOT_PAPERKEY=
MATRIX_SERVER=
MATRIX_ROOM=
MATRIX_ROOM_OF_SHAME=
MATRIX_USER_ID=
MATRIX_TOKEN=
MATRIX_DEVICE_ID=
NYM_NOTIFICATION_KIND=nightly NYM_NOTIFICATION_KIND=nightly
NYM_PROJECT_NAME=Nightly Build NYM_PROJECT_NAME=Nightly Build
+1 -3
View File
@@ -2,6 +2,4 @@ node_modules
.idea .idea
# don't commit the lock file to avoid cross-platform issues # don't commit the lock file to avoid cross-platform issues
package-lock.json package-lock.json
scratch
@@ -1,7 +1,6 @@
require('dotenv').config(); require('dotenv').config();
const Bot = require('keybase-bot'); const Bot = require('keybase-bot');
const { sendMatrixMessage } = require('./send_message_to_matrix');
let context = { let context = {
kinds: ['nym-wallet', 'ts-packages', 'network-explorer', 'nightly', 'nym-connect','security'], kinds: ['nym-wallet', 'ts-packages', 'network-explorer', 'nightly', 'nym-connect','security'],
@@ -39,28 +38,6 @@ function validateContext() {
'Paperkey is not defined. Please set env var KEYBASE_NYMBOT_PAPERKEY', 'Paperkey is not defined. Please set env var KEYBASE_NYMBOT_PAPERKEY',
); );
} }
if (context.env.MATRIX_ROOM) {
if (!context.env.MATRIX_SERVER) {
throw new Error(
'Matrix server is not defined. Please set env var MATRIX_SERVER',
);
}
if (!context.env.MATRIX_USER_ID) {
throw new Error(
'Matrix user id is not defined. Please set env var MATRIX_USER_ID',
);
}
if (!context.env.MATRIX_TOKEN) {
throw new Error(
'Matrix token is not defined. Please set env var MATRIX_TOKEN',
);
}
if (!context.env.MATRIX_DEVICE_ID) {
throw new Error(
'Matrix device id is not defined. Please set env var MATRIX_DEVICE_ID',
);
}
}
} }
/** /**
@@ -170,13 +147,6 @@ async function main() {
console.log('-----------------------------------------'); console.log('-----------------------------------------');
} }
await sendKeybaseMessage(messageBody); await sendKeybaseMessage(messageBody);
if(context.env.MATRIX_ROOM) {
await sendMatrixMessage(context, messageBody, context.env.MATRIX_ROOM)
}
if(context.env.MATRIX_ROOM_OF_SHAME && context.env.IS_SUCCESS !== 'true') {
// when a job fails
await sendMatrixMessage(context, messageBody, context.env.MATRIX_ROOM_OF_SHAME)
}
} }
// call main function and let NodeJS handle the promise // call main function and let NodeJS handle the promise
@@ -1,80 +0,0 @@
const sdk = require('matrix-js-sdk');
global.Olm = require('olm');
const { LocalStorage } = require('node-localstorage');
const localStorage = new LocalStorage('./scratch');
const {
LocalStorageCryptoStore,
} = require('matrix-js-sdk/lib/crypto/store/localStorage-crypto-store');
const vfile = require('to-vfile');
const unified = require('unified');
const remarkParse = require('remark-parse');
const remarkHtml = require('remark-html');
const emoji = require('remark-emoji');
// hide all matrix client output
console.error = (error) => console.log('❌ error: ', error);
process.stderr.write = () => {};
process.stdout.write = () => {};
function createClient(context, room, message) {
const server = context.env.MATRIX_SERVER;
const token = context.env.MATRIX_TOKEN;
const deviceId = context.env.MATRIX_DEVICE_ID;
const userId = context.env.MATRIX_USER_ID;
const client = sdk.createClient({
baseUrl: server,
accessToken: token,
userId,
deviceId,
sessionStore: new sdk.WebStorageSessionStore(localStorage),
cryptoStore: new LocalStorageCryptoStore(localStorage),
});
client.on('sync', async function(state, prevState, res) {
if (state !== 'PREPARED') return;
client.setGlobalErrorOnUnknownDevices(false);
try {
await client.joinRoom(room);
await client.sendEvent(
room,
'm.room.message',
{
msgtype: 'm.text',
format: 'org.matrix.custom.html',
body: message,
formatted_body: message,
},
'',
);
} catch (error) {
console.error('Job failed: ' + error.message);
}
client.stopClient();
process.exit(0);
});
return client;
}
async function markdownToHtml(messageAsMarkdown) {
const file = await unified()
.use(emoji)
.use(remarkParse)
.use(remarkHtml)
.process(await vfile({ path: 'test.md', contents: messageAsMarkdown}));
return String(file);
}
async function sendMatrixMessage(contextArg, messageAsMarkdown, roomId) {
const messageAsHtml = await markdownToHtml(messageAsMarkdown);
const client = createClient(contextArg, roomId, messageAsHtml);
await client.initCrypto();
await client.startClient({ initialSyncLimit: 1 });
}
module.exports = {
sendMatrixMessage,
};
+1 -9
View File
@@ -11,15 +11,7 @@
"dotenv": "^16.0.0", "dotenv": "^16.0.0",
"handlebars": "^4.7.7", "handlebars": "^4.7.7",
"keybase-bot": "^3.6.1", "keybase-bot": "^3.6.1",
"matrix-js-sdk": "^9.3.0", "octokit": "^1.7.1"
"node-localstorage": "^2.1.6",
"octokit": "^1.7.1",
"olm": "https://packages.matrix.org/npm/olm/olm-3.2.1.tgz",
"remark-emoji": "^2.2.0",
"remark-html": "^13.0.2",
"remark-parse": "^9.0.0",
"to-vfile": "^6.1.0",
"unified": "^9.2.2"
}, },
"devDependencies": { "devDependencies": {
"prettier": "2.3.2" "prettier": "2.3.2"
+1 -3
View File
@@ -38,6 +38,4 @@ validator-config
validator-api-config.toml validator-api-config.toml
dist dist
storybook-static storybook-static
envs/qwerty.env envs/qwerty.env
Cargo.lock
nym-connect/Cargo.lock
+5 -7
View File
@@ -1,8 +1,6 @@
{ {
"mainnet": [ "mainnet":[{
{ "nymd_url":"https://rpc.nyx.nodes.guru/",
"nyxd_url": "https://rpc.nyx.nodes.guru/", "api_url":"https://api.nyx.nodes.guru/"
"api_url": "https://api.nyx.nodes.guru/" }]
} }
]
}
+42 -73
View File
@@ -6,61 +6,24 @@ Post 1.0.0 release, the changelog format is based on [Keep a Changelog](https://
### Added ### Added
- nym-sdk: added initial version of a Rust client sdk - socks5: send status message for service ready, and network-requester error response
### Changed ### Changed
- renamed all references to validator_api to nym_api - all-binaries: improved error logging ([#2686])
- renamed all references to nymd to nyxd - native client: bring shutdown logic up to the same level as socks5-client
- all-binaries: standarised argument names (note: old names should still be accepted) ([#2762] - nym-api, coconut-dkg contract: automatic, time-based dkg epoch state advancement ([#2670])
### Fixed [#2686]: https://github.com/nymtech/nym/pull/2686
[#2670]: https://github.com/nymtech/nym/pull/2670
- nym-api: should now correctly use `rewarding.enabled` config flag ([#2753])
[#2753]: https://github.com/nymtech/nym/pull/2753
[#2762]: https://github.com/nymtech/nym/pull/2762
## [v1.1.5] (2022-01-10)
### Added
- socks5: send status message for service ready, and network-requester error response in https://github.com/nymtech/nym/pull/2715
### Changed
- all-binaries: improved error logging in https://github.com/nymtech/nym/pull/2686
- native client: bring shutdown logic up to the same level as socks5-client in https://github.com/nymtech/nym/pull/2695
- nym-api, coconut-dkg contract: automatic, time-based dkg epoch state advancement in https://github.com/nymtech/nym/pull/2670
- DKG resharing unit test by @neacsu in https://github.com/nymtech/nym/pull/2668
- Renaming validator-api to nym-api by @futurechimp in https://github.com/nymtech/nym/pull/1863
- Modify wasm specific make targets by @neacsu in https://github.com/nymtech/nym/pull/2693
- client: create websocket handler builder by @octol in https://github.com/nymtech/nym/pull/2700
- Outfox and Lion by @durch in https://github.com/nymtech/nym/pull/2730
- Feature/multi surb transmission lanes by @jstuczyn in https://github.com/nymtech/nym/pull/2723
## [v1.1.4] (2022-12-20)
This release adds multiple Single Use Reply Blocks (SURBs) to allow arbitrarily-sized anonymized replies.
At the moment this is turned off by default, but available for use by application developers.
We will need to wait for network-requesters to upgrade to this new release, after which multi-SURB anonymization will become the default setting for the SOCKS proxy clients.
The release also include some additional work for distributed key generation in the Coconut signing authority nodes.
### Changed
- Feature/dkg contract threshold by @neacsu in https://github.com/nymtech/nym/pull/1885
- Multi-surbs by @jstuczyn in https://github.com/nymtech/nym/pull/2667
- Fix multi-surb backwards compatibility in pre 1.1.4 client config files by @jstuczyn in https://github.com/nymtech/nym/pull/2703
- fix: ignore corrupted surb storage and instead create fresh one by @jstuczyn in https://github.com/nymtech/nym/pull/2711
- socks5: rework waiting in inbound.rs by @octol in https://github.com/nymtech/nym/pull/1880
## [v1.1.3] (2022-12-13) ## [v1.1.3] (2022-12-13)
### Changed ### Changed
- validator-api: can recover from shutdown during DKG process ([#1872]) - validator-api: can recover from shutdown during DKG process ([#1872])
- clients: deduplicate gateway initialization, part of work towards a rust-sdk - clients: deduplicate gateway inititialization, part of work towards a rust-sdk
- clients: keep all transmission lanes going at all times by making priority probabilistic - clients: keep all transmission lanes going at all times by making priority probabilistic
- clients: ability to use multi-reply SURBs to send arbitrarily long messages fully anonymously whilst requesting additional reply blocks whenever they're about to run out ([#1796], [#1801], [#1804], [#1835], [#1858], [#1883])) - clients: ability to use multi-reply SURBs to send arbitrarily long messages fully anonymously whilst requesting additional reply blocks whenever they're about to run out ([#1796], [#1801], [#1804], [#1835], [#1858], [#1883]))
@@ -68,7 +31,7 @@ The release also include some additional work for distributed key generation in
- network-requester: fix bug where websocket connection disconnect resulted in success error code - network-requester: fix bug where websocket connection disconnect resulted in success error code
- clients: fix a few panics handling the gateway-client - clients: fix a few panics handling the gateway-client
- mixnode, gateway, validator-api: Use mainnet values as defaults for URLs and mixnet contract ([#1884]) - mixnode, gateway, validator-api: Use mainnet values as defaults for URLs and mixnet contract ([#1884])
- socks5: fixed bug where connections sometimes where closed too early - socks5: fixed bug where connections sometimes where closed too early
- clients: improve message logging when received message fails to get reconstructed ([#1803]) - clients: improve message logging when received message fails to get reconstructed ([#1803])
@@ -88,7 +51,7 @@ The release also include some additional work for distributed key generation in
- gateway: Renamed flag from `enabled/disabled_credentials_mode` to `only-coconut-credentials` - gateway: Renamed flag from `enabled/disabled_credentials_mode` to `only-coconut-credentials`
- "Family" feature for node families + layers - "Family" feature for node families + layers
- Initial coconut functionality including credentials and distributed key generation - Initial coconut functionality including credentials and distributed key generation
## [v1.1.1](https://github.com/nymtech/nym/tree/v1.1.1) (2022-11-29) ## [v1.1.1](https://github.com/nymtech/nym/tree/v1.1.1) (2022-11-29)
@@ -124,6 +87,7 @@ The release also include some additional work for distributed key generation in
[#1786]: https://github.com/nymtech/nym/pull/1786 [#1786]: https://github.com/nymtech/nym/pull/1786
[#1805]: https://github.com/nymtech/nym/pull/1805 [#1805]: https://github.com/nymtech/nym/pull/1805
## [v1.1.0](https://github.com/nymtech/nym/tree/v1.1.0) (2022-11-09) ## [v1.1.0](https://github.com/nymtech/nym/tree/v1.1.0) (2022-11-09)
### Added ### Added
@@ -135,7 +99,7 @@ The release also include some additional work for distributed key generation in
- native-client/socks5-client/wasm-client: `use_extended_packet_size` Debug config option to make the client use 'ExtendedPacketSize' for its traffic (32kB as opposed to 2kB in 1.0.2) ([#1671]) - native-client/socks5-client/wasm-client: `use_extended_packet_size` Debug config option to make the client use 'ExtendedPacketSize' for its traffic (32kB as opposed to 2kB in 1.0.2) ([#1671])
- network-requester: added additional Blockstream Green wallet endpoint to `example.allowed.list` ([#1611]) - network-requester: added additional Blockstream Green wallet endpoint to `example.allowed.list` ([#1611])
- validator-api: add `interval_operating_cost` and `profit_margin_percent` to compute reward estimation endpoint - validator-api: add `interval_operating_cost` and `profit_margin_percent` to compute reward estimation endpoint
- validator-client: added `query_contract_smart` and `query_contract_raw` on `NyxdClient` ([#1558]) - validator-client: added `query_contract_smart` and `query_contract_raw` on `NymdClient` ([#1558])
- wasm-client: uses updated wasm-compatible `client-core` so that it's now capable of packet retransmission, cover traffic and poisson delay (among other things!) ([#1673]) - wasm-client: uses updated wasm-compatible `client-core` so that it's now capable of packet retransmission, cover traffic and poisson delay (among other things!) ([#1673])
### Fixed ### Fixed
@@ -150,7 +114,7 @@ The release also include some additional work for distributed key generation in
- gateway-client: will attempt to read now as many as 8 websocket messages at once, assuming they're already available on the socket ([#1669]) - gateway-client: will attempt to read now as many as 8 websocket messages at once, assuming they're already available on the socket ([#1669])
- moved `Percent` struct to `contracts-common`, change affects explorer-api - moved `Percent` struct to `contracts-common`, change affects explorer-api
- socks5 client: graceful shutdown should fix error on disconnect in nym-connect ([#1591]) - socks5 client: graceful shutdown should fix error on disconnect in nym-connect ([#1591])
- validator-api: changed error serialization on `inclusion_probability`, `stake-saturation` and `reward-estimation` endpoints to provide more accurate information ([#1681]) - validator-api: changed error serialization on `inclusion_probability`, `stake-saturation` and `reward-estimation` endpoints to provide more accurate information ([#1681])
- validator-client: made `fee` argument optional for `execute` and `execute_multiple` ([#1541]) - validator-client: made `fee` argument optional for `execute` and `execute_multiple` ([#1541])
- wasm-client: fixed build errors on MacOS and changed example JS code to use mainnet ([#1585]) - wasm-client: fixed build errors on MacOS and changed example JS code to use mainnet ([#1585])
- validator-api: changes to internal SQL schema due to the mixnet contract revamp ([#1472]) - validator-api: changes to internal SQL schema due to the mixnet contract revamp ([#1472])
@@ -178,6 +142,7 @@ The release also include some additional work for distributed key generation in
[#1724]: https://github.com/nymtech/nym/pull/1724 [#1724]: https://github.com/nymtech/nym/pull/1724
[#1725]: https://github.com/nymtech/nym/pull/1725 [#1725]: https://github.com/nymtech/nym/pull/1725
## [nym-binaries-1.0.2](https://github.com/nymtech/nym/tree/nym-binaries-1.0.2) ## [nym-binaries-1.0.2](https://github.com/nymtech/nym/tree/nym-binaries-1.0.2)
### Added ### Added
@@ -230,8 +195,9 @@ The release also include some additional work for distributed key generation in
- All binaries and cosmwasm blobs are configured at runtime now; binaries are configured using environment variables or .env files and contracts keep the configuration parameters in storage ([#1463]) - All binaries and cosmwasm blobs are configured at runtime now; binaries are configured using environment variables or .env files and contracts keep the configuration parameters in storage ([#1463])
- gateway, network-statistics: include gateway id in the sent statistical data ([#1478]) - gateway, network-statistics: include gateway id in the sent statistical data ([#1478])
- network explorer: tweak how active set probability is shown ([#1503]) - network explorer: tweak how active set probability is shown ([#1503])
- validator-api: rewarder set update fails without panicking on possible nyxd queries ([#1520]) - validator-api: rewarder set update fails without panicking on possible nymd queries ([#1520])
- network-requester, socks5 client (nym-connect): send and receive respectively a message error to be displayed about filter check failure ([#1576]) - network-requester, socks5 client (nym-connect): send and receive respectively a message error to be displayed about filter check failure ([#1576])
[#1249]: https://github.com/nymtech/nym/pull/1249 [#1249]: https://github.com/nymtech/nym/pull/1249
[#1256]: https://github.com/nymtech/nym/pull/1256 [#1256]: https://github.com/nymtech/nym/pull/1256
@@ -325,9 +291,9 @@ The release also include some additional work for distributed key generation in
- Bump minimist from 1.2.5 to 1.2.6 in /clients/tauri-client [\#1163](https://github.com/nymtech/nym/pull/1163) ([dependabot[bot]](https://github.com/apps/dependabot)) - Bump minimist from 1.2.5 to 1.2.6 in /clients/tauri-client [\#1163](https://github.com/nymtech/nym/pull/1163) ([dependabot[bot]](https://github.com/apps/dependabot))
- Bump minimist from 1.2.5 to 1.2.6 in /clients/webassembly/js-example [\#1162](https://github.com/nymtech/nym/pull/1162) ([dependabot[bot]](https://github.com/apps/dependabot)) - Bump minimist from 1.2.5 to 1.2.6 in /clients/webassembly/js-example [\#1162](https://github.com/nymtech/nym/pull/1162) ([dependabot[bot]](https://github.com/apps/dependabot))
- Bump minimist from 1.2.5 to 1.2.6 in /clients/native/examples/js-examples/websocket [\#1160](https://github.com/nymtech/nym/pull/1160) ([dependabot[bot]](https://github.com/apps/dependabot)) - Bump minimist from 1.2.5 to 1.2.6 in /clients/native/examples/js-examples/websocket [\#1160](https://github.com/nymtech/nym/pull/1160) ([dependabot[bot]](https://github.com/apps/dependabot))
- Bump minimist from 1.2.5 to 1.2.6 in /docker/typescript_client/upload_contract [\#1159](https://github.com/nymtech/nym/pull/1159) ([dependabot[bot]](https://github.com/apps/dependabot)) - Bump minimist from 1.2.5 to 1.2.6 in /docker/typescript\_client/upload\_contract [\#1159](https://github.com/nymtech/nym/pull/1159) ([dependabot[bot]](https://github.com/apps/dependabot))
- Feature/vesting full [\#1158](https://github.com/nymtech/nym/pull/1158) ([fmtabbara](https://github.com/fmtabbara)) - Feature/vesting full [\#1158](https://github.com/nymtech/nym/pull/1158) ([fmtabbara](https://github.com/fmtabbara))
- get_current_epoch tauri [\#1156](https://github.com/nymtech/nym/pull/1156) ([durch](https://github.com/durch)) - get\_current\_epoch tauri [\#1156](https://github.com/nymtech/nym/pull/1156) ([durch](https://github.com/durch))
- Cleanup [\#1155](https://github.com/nymtech/nym/pull/1155) ([durch](https://github.com/durch)) - Cleanup [\#1155](https://github.com/nymtech/nym/pull/1155) ([durch](https://github.com/durch))
- Feature flag reward payments [\#1154](https://github.com/nymtech/nym/pull/1154) ([durch](https://github.com/durch)) - Feature flag reward payments [\#1154](https://github.com/nymtech/nym/pull/1154) ([durch](https://github.com/durch))
- Add Query endpoints for calculating rewards [\#1152](https://github.com/nymtech/nym/pull/1152) ([durch](https://github.com/durch)) - Add Query endpoints for calculating rewards [\#1152](https://github.com/nymtech/nym/pull/1152) ([durch](https://github.com/durch))
@@ -336,7 +302,7 @@ The release also include some additional work for distributed key generation in
- wallet: use Urls rather than Strings for validator urls [\#1148](https://github.com/nymtech/nym/pull/1148) ([octol](https://github.com/octol)) - wallet: use Urls rather than Strings for validator urls [\#1148](https://github.com/nymtech/nym/pull/1148) ([octol](https://github.com/octol))
- Change accumulated reward to Option, migrate delegations [\#1147](https://github.com/nymtech/nym/pull/1147) ([durch](https://github.com/durch)) - Change accumulated reward to Option, migrate delegations [\#1147](https://github.com/nymtech/nym/pull/1147) ([durch](https://github.com/durch))
- wallet: fetch validators url remotely if available [\#1146](https://github.com/nymtech/nym/pull/1146) ([octol](https://github.com/octol)) - wallet: fetch validators url remotely if available [\#1146](https://github.com/nymtech/nym/pull/1146) ([octol](https://github.com/octol))
- Fix delegated_free calculation [\#1145](https://github.com/nymtech/nym/pull/1145) ([durch](https://github.com/durch)) - Fix delegated\_free calculation [\#1145](https://github.com/nymtech/nym/pull/1145) ([durch](https://github.com/durch))
- Update Nym wallet dependencies to use `ts-packages` [\#1144](https://github.com/nymtech/nym/pull/1144) ([mmsinclair](https://github.com/mmsinclair)) - Update Nym wallet dependencies to use `ts-packages` [\#1144](https://github.com/nymtech/nym/pull/1144) ([mmsinclair](https://github.com/mmsinclair))
- wallet: try validators one by one if available [\#1143](https://github.com/nymtech/nym/pull/1143) ([octol](https://github.com/octol)) - wallet: try validators one by one if available [\#1143](https://github.com/nymtech/nym/pull/1143) ([octol](https://github.com/octol))
- Update Network Explorer Packages and add mix node identity key copy [\#1142](https://github.com/nymtech/nym/pull/1142) ([mmsinclair](https://github.com/mmsinclair)) - Update Network Explorer Packages and add mix node identity key copy [\#1142](https://github.com/nymtech/nym/pull/1142) ([mmsinclair](https://github.com/mmsinclair))
@@ -376,13 +342,14 @@ The release also include some additional work for distributed key generation in
- feature/pedersen-commitments [\#1048](https://github.com/nymtech/nym/pull/1048) ([danielementary](https://github.com/danielementary)) - feature/pedersen-commitments [\#1048](https://github.com/nymtech/nym/pull/1048) ([danielementary](https://github.com/danielementary))
- Feature/reuse init owner [\#970](https://github.com/nymtech/nym/pull/970) ([neacsu](https://github.com/neacsu)) - Feature/reuse init owner [\#970](https://github.com/nymtech/nym/pull/970) ([neacsu](https://github.com/neacsu))
## [v0.12.1](https://github.com/nymtech/nym/tree/v0.12.1) (2021-12-23) ## [v0.12.1](https://github.com/nymtech/nym/tree/v0.12.1) (2021-12-23)
[Full Changelog](https://github.com/nymtech/nym/compare/v0.12.0...v0.12.1) [Full Changelog](https://github.com/nymtech/nym/compare/v0.12.0...v0.12.1)
**Implemented enhancements:** **Implemented enhancements:**
- Add version check to binaries [\#967](https://github.com/nymtech/nym/issues/967) - Add version check to binaries [\#967](https://github.com/nymtech/nym/issues/967)
**Fixed bugs:** **Fixed bugs:**
@@ -412,7 +379,7 @@ The release also include some additional work for distributed key generation in
- Bugfix/remove mixnode bonding overwrite [\#917](https://github.com/nymtech/nym/pull/917) ([jstuczyn](https://github.com/jstuczyn)) - Bugfix/remove mixnode bonding overwrite [\#917](https://github.com/nymtech/nym/pull/917) ([jstuczyn](https://github.com/jstuczyn))
- Fixes crash condition in validator API when calculating last day uptime [\#909](https://github.com/nymtech/nym/pull/909) ([jstuczyn](https://github.com/jstuczyn)) - Fixes crash condition in validator API when calculating last day uptime [\#909](https://github.com/nymtech/nym/pull/909) ([jstuczyn](https://github.com/jstuczyn))
- Bugfix/monitor initial values wait [\#907](https://github.com/nymtech/nym/pull/907) ([jstuczyn](https://github.com/jstuczyn)) - Bugfix/monitor initial values wait [\#907](https://github.com/nymtech/nym/pull/907) ([jstuczyn](https://github.com/jstuczyn))
- Bug fix: Network Explorer: Add freegeoip API key and split out tasks for country distributions [\#806](https://github.com/nymtech/nym/pull/806) ([mmsinclair](https://github.com/mmsinclair)) - Bug fix: Network Explorer: Add freegeoip API key and split out tasks for country distributions [\#806](https://github.com/nymtech/nym/pull/806) ([mmsinclair](https://github.com/mmsinclair))
- Explorer API: port test now split out address resolution and add units tests [\#755](https://github.com/nymtech/nym/pull/755) ([mmsinclair](https://github.com/mmsinclair)) - Explorer API: port test now split out address resolution and add units tests [\#755](https://github.com/nymtech/nym/pull/755) ([mmsinclair](https://github.com/mmsinclair))
**Closed issues:** **Closed issues:**
@@ -427,7 +394,7 @@ The release also include some additional work for distributed key generation in
- help!!! [\#712](https://github.com/nymtech/nym/issues/712) - help!!! [\#712](https://github.com/nymtech/nym/issues/712)
- UX feature request: show all delegated nodes in wallet [\#711](https://github.com/nymtech/nym/issues/711) - UX feature request: show all delegated nodes in wallet [\#711](https://github.com/nymtech/nym/issues/711)
- UX feature request: add current balance on wallet pages [\#710](https://github.com/nymtech/nym/issues/710) - UX feature request: add current balance on wallet pages [\#710](https://github.com/nymtech/nym/issues/710)
- got sign issue from bot [\#709](https://github.com/nymtech/nym/issues/709) - got sign issue from bot [\#709](https://github.com/nymtech/nym/issues/709)
- As a wallet user, I would like to be able to log out of the wallet [\#706](https://github.com/nymtech/nym/issues/706) - As a wallet user, I would like to be able to log out of the wallet [\#706](https://github.com/nymtech/nym/issues/706)
- As a wallet user, I would like to have a "receive" page where I can see my own wallet address [\#705](https://github.com/nymtech/nym/issues/705) - As a wallet user, I would like to have a "receive" page where I can see my own wallet address [\#705](https://github.com/nymtech/nym/issues/705)
- Update native client/socks client/mixnode/gateway `upgrade` command [\#689](https://github.com/nymtech/nym/issues/689) - Update native client/socks client/mixnode/gateway `upgrade` command [\#689](https://github.com/nymtech/nym/issues/689)
@@ -437,7 +404,7 @@ The release also include some additional work for distributed key generation in
- nym-socks5-client crash after opening Keybase team "Browse all channels" [\#494](https://github.com/nymtech/nym/issues/494) - nym-socks5-client crash after opening Keybase team "Browse all channels" [\#494](https://github.com/nymtech/nym/issues/494)
- Mixed Content problem [\#400](https://github.com/nymtech/nym/issues/400) - Mixed Content problem [\#400](https://github.com/nymtech/nym/issues/400)
- Gateway disk quota [\#137](https://github.com/nymtech/nym/issues/137) - Gateway disk quota [\#137](https://github.com/nymtech/nym/issues/137)
- Simplify message encapsulation with regards to topology [\#127](https://github.com/nymtech/nym/issues/127) - Simplify message encapsulation with regards to topology [\#127](https://github.com/nymtech/nym/issues/127)
- Create constants for cli argument names [\#115](https://github.com/nymtech/nym/issues/115) - Create constants for cli argument names [\#115](https://github.com/nymtech/nym/issues/115)
- Using Blake3 as a hash function [\#103](https://github.com/nymtech/nym/issues/103) - Using Blake3 as a hash function [\#103](https://github.com/nymtech/nym/issues/103)
- Validator should decide which layer a node is in [\#86](https://github.com/nymtech/nym/issues/86) - Validator should decide which layer a node is in [\#86](https://github.com/nymtech/nym/issues/86)
@@ -493,10 +460,10 @@ The release also include some additional work for distributed key generation in
- Feature/pre cosmrs updates [\#935](https://github.com/nymtech/nym/pull/935) ([jstuczyn](https://github.com/jstuczyn)) - Feature/pre cosmrs updates [\#935](https://github.com/nymtech/nym/pull/935) ([jstuczyn](https://github.com/jstuczyn))
- Feature/client on behalf [\#934](https://github.com/nymtech/nym/pull/934) ([neacsu](https://github.com/neacsu)) - Feature/client on behalf [\#934](https://github.com/nymtech/nym/pull/934) ([neacsu](https://github.com/neacsu))
- Webpack wallet prod configuration [\#933](https://github.com/nymtech/nym/pull/933) ([tommyv1987](https://github.com/tommyv1987)) - Webpack wallet prod configuration [\#933](https://github.com/nymtech/nym/pull/933) ([tommyv1987](https://github.com/tommyv1987))
- Adding tx_hash to wallet response [\#932](https://github.com/nymtech/nym/pull/932) ([futurechimp](https://github.com/futurechimp)) - Adding tx\_hash to wallet response [\#932](https://github.com/nymtech/nym/pull/932) ([futurechimp](https://github.com/futurechimp))
- Release/1.0.0 pre1 [\#931](https://github.com/nymtech/nym/pull/931) ([durch](https://github.com/durch)) - Release/1.0.0 pre1 [\#931](https://github.com/nymtech/nym/pull/931) ([durch](https://github.com/durch))
- Feature/identity verification [\#930](https://github.com/nymtech/nym/pull/930) ([jstuczyn](https://github.com/jstuczyn)) - Feature/identity verification [\#930](https://github.com/nymtech/nym/pull/930) ([jstuczyn](https://github.com/jstuczyn))
- Move cleaned up smart contracts to main code repo [\#929](https://github.com/nymtech/nym/pull/929) ([mfahampshire](https://github.com/mfahampshire)) - Move cleaned up smart contracts to main code repo [\#929](https://github.com/nymtech/nym/pull/929) ([mfahampshire](https://github.com/mfahampshire))
- Feature/mixnet contract further adjustments [\#928](https://github.com/nymtech/nym/pull/928) ([jstuczyn](https://github.com/jstuczyn)) - Feature/mixnet contract further adjustments [\#928](https://github.com/nymtech/nym/pull/928) ([jstuczyn](https://github.com/jstuczyn))
- typo copy change for nodemap [\#926](https://github.com/nymtech/nym/pull/926) ([Aid19801](https://github.com/Aid19801)) - typo copy change for nodemap [\#926](https://github.com/nymtech/nym/pull/926) ([Aid19801](https://github.com/Aid19801))
- Feature/UI enhancements for Desktop Wallet [\#925](https://github.com/nymtech/nym/pull/925) ([fmtabbara](https://github.com/fmtabbara)) - Feature/UI enhancements for Desktop Wallet [\#925](https://github.com/nymtech/nym/pull/925) ([fmtabbara](https://github.com/fmtabbara))
@@ -509,7 +476,7 @@ The release also include some additional work for distributed key generation in
- Feature/faucet page react [\#911](https://github.com/nymtech/nym/pull/911) ([fmtabbara](https://github.com/fmtabbara)) - Feature/faucet page react [\#911](https://github.com/nymtech/nym/pull/911) ([fmtabbara](https://github.com/fmtabbara))
- Feature/mixnet contract refactor [\#910](https://github.com/nymtech/nym/pull/910) ([futurechimp](https://github.com/futurechimp)) - Feature/mixnet contract refactor [\#910](https://github.com/nymtech/nym/pull/910) ([futurechimp](https://github.com/futurechimp))
- Update README.md [\#905](https://github.com/nymtech/nym/pull/905) ([tommyv1987](https://github.com/tommyv1987)) - Update README.md [\#905](https://github.com/nymtech/nym/pull/905) ([tommyv1987](https://github.com/tommyv1987))
- BUG: Bond cell denom [\#904](https://github.com/nymtech/nym/pull/904) ([Aid19801](https://github.com/Aid19801)) - BUG: Bond cell denom [\#904](https://github.com/nymtech/nym/pull/904) ([Aid19801](https://github.com/Aid19801))
- Explorer UI tests missing data-testid [\#903](https://github.com/nymtech/nym/pull/903) ([tommyv1987](https://github.com/tommyv1987)) - Explorer UI tests missing data-testid [\#903](https://github.com/nymtech/nym/pull/903) ([tommyv1987](https://github.com/tommyv1987))
- Fix up Nym-Wallet README.md [\#899](https://github.com/nymtech/nym/pull/899) ([tommyv1987](https://github.com/tommyv1987)) - Fix up Nym-Wallet README.md [\#899](https://github.com/nymtech/nym/pull/899) ([tommyv1987](https://github.com/tommyv1987))
- Feature/batch delegator rewarding [\#898](https://github.com/nymtech/nym/pull/898) ([jstuczyn](https://github.com/jstuczyn)) - Feature/batch delegator rewarding [\#898](https://github.com/nymtech/nym/pull/898) ([jstuczyn](https://github.com/jstuczyn))
@@ -527,7 +494,7 @@ The release also include some additional work for distributed key generation in
- Reverted gateway registration handshake to its 0.11.0 version [\#882](https://github.com/nymtech/nym/pull/882) ([jstuczyn](https://github.com/jstuczyn)) - Reverted gateway registration handshake to its 0.11.0 version [\#882](https://github.com/nymtech/nym/pull/882) ([jstuczyn](https://github.com/jstuczyn))
- Network Explorer [\#881](https://github.com/nymtech/nym/pull/881) ([mmsinclair](https://github.com/mmsinclair)) - Network Explorer [\#881](https://github.com/nymtech/nym/pull/881) ([mmsinclair](https://github.com/mmsinclair))
- Feature/rewarding interval updates [\#880](https://github.com/nymtech/nym/pull/880) ([jstuczyn](https://github.com/jstuczyn)) - Feature/rewarding interval updates [\#880](https://github.com/nymtech/nym/pull/880) ([jstuczyn](https://github.com/jstuczyn))
- Put client_address and id in the correct order [\#875](https://github.com/nymtech/nym/pull/875) ([neacsu](https://github.com/neacsu)) - Put client\_address and id in the correct order [\#875](https://github.com/nymtech/nym/pull/875) ([neacsu](https://github.com/neacsu))
- remove gateway selection on delegation and undelegation pages [\#873](https://github.com/nymtech/nym/pull/873) ([fmtabbara](https://github.com/fmtabbara)) - remove gateway selection on delegation and undelegation pages [\#873](https://github.com/nymtech/nym/pull/873) ([fmtabbara](https://github.com/fmtabbara))
- Set MSRV on all binaries to 1.56 [\#872](https://github.com/nymtech/nym/pull/872) ([jstuczyn](https://github.com/jstuczyn)) - Set MSRV on all binaries to 1.56 [\#872](https://github.com/nymtech/nym/pull/872) ([jstuczyn](https://github.com/jstuczyn))
- add native window items \(copy/paste\) via tauri [\#871](https://github.com/nymtech/nym/pull/871) ([fmtabbara](https://github.com/fmtabbara)) - add native window items \(copy/paste\) via tauri [\#871](https://github.com/nymtech/nym/pull/871) ([fmtabbara](https://github.com/fmtabbara))
@@ -543,7 +510,7 @@ The release also include some additional work for distributed key generation in
- Overflow checks in release [\#846](https://github.com/nymtech/nym/pull/846) ([jstuczyn](https://github.com/jstuczyn)) - Overflow checks in release [\#846](https://github.com/nymtech/nym/pull/846) ([jstuczyn](https://github.com/jstuczyn))
- fix delegate success overflow [\#842](https://github.com/nymtech/nym/pull/842) ([fmtabbara](https://github.com/fmtabbara)) - fix delegate success overflow [\#842](https://github.com/nymtech/nym/pull/842) ([fmtabbara](https://github.com/fmtabbara))
- Feature NYM wallet webdriverio test [\#841](https://github.com/nymtech/nym/pull/841) ([tommyv1987](https://github.com/tommyv1987)) - Feature NYM wallet webdriverio test [\#841](https://github.com/nymtech/nym/pull/841) ([tommyv1987](https://github.com/tommyv1987))
- Update nym_wallet.yml [\#840](https://github.com/nymtech/nym/pull/840) ([tommyv1987](https://github.com/tommyv1987)) - Update nym\_wallet.yml [\#840](https://github.com/nymtech/nym/pull/840) ([tommyv1987](https://github.com/tommyv1987))
- Feature/vouchers [\#837](https://github.com/nymtech/nym/pull/837) ([aniampio](https://github.com/aniampio)) - Feature/vouchers [\#837](https://github.com/nymtech/nym/pull/837) ([aniampio](https://github.com/aniampio))
- Apply readable ids to elements on Nym Wallet [\#836](https://github.com/nymtech/nym/pull/836) ([tommyv1987](https://github.com/tommyv1987)) - Apply readable ids to elements on Nym Wallet [\#836](https://github.com/nymtech/nym/pull/836) ([tommyv1987](https://github.com/tommyv1987))
- Feature/removal of monitor good nodes [\#833](https://github.com/nymtech/nym/pull/833) ([jstuczyn](https://github.com/jstuczyn)) - Feature/removal of monitor good nodes [\#833](https://github.com/nymtech/nym/pull/833) ([jstuczyn](https://github.com/jstuczyn))
@@ -567,8 +534,8 @@ The release also include some additional work for distributed key generation in
- Created getters for AccountData [\#787](https://github.com/nymtech/nym/pull/787) ([jstuczyn](https://github.com/jstuczyn)) - Created getters for AccountData [\#787](https://github.com/nymtech/nym/pull/787) ([jstuczyn](https://github.com/jstuczyn))
- Feature/migrate hidden delegations [\#786](https://github.com/nymtech/nym/pull/786) ([neacsu](https://github.com/neacsu)) - Feature/migrate hidden delegations [\#786](https://github.com/nymtech/nym/pull/786) ([neacsu](https://github.com/neacsu))
- Feature/persistent gateway storage [\#784](https://github.com/nymtech/nym/pull/784) ([jstuczyn](https://github.com/jstuczyn)) - Feature/persistent gateway storage [\#784](https://github.com/nymtech/nym/pull/784) ([jstuczyn](https://github.com/jstuczyn))
- Replaced unwrap_or_else with unwrap_or_default [\#780](https://github.com/nymtech/nym/pull/780) ([jstuczyn](https://github.com/jstuczyn)) - Replaced unwrap\_or\_else with unwrap\_or\_default [\#780](https://github.com/nymtech/nym/pull/780) ([jstuczyn](https://github.com/jstuczyn))
- Add block_height method to Delegation [\#778](https://github.com/nymtech/nym/pull/778) ([durch](https://github.com/durch)) - Add block\_height method to Delegation [\#778](https://github.com/nymtech/nym/pull/778) ([durch](https://github.com/durch))
- Make fee helpers public [\#777](https://github.com/nymtech/nym/pull/777) ([durch](https://github.com/durch)) - Make fee helpers public [\#777](https://github.com/nymtech/nym/pull/777) ([durch](https://github.com/durch))
- re-enable bonding [\#776](https://github.com/nymtech/nym/pull/776) ([fmtabbara](https://github.com/fmtabbara)) - re-enable bonding [\#776](https://github.com/nymtech/nym/pull/776) ([fmtabbara](https://github.com/fmtabbara))
- Explorer-api: add API resource to show the delegations for each mix node [\#774](https://github.com/nymtech/nym/pull/774) ([mmsinclair](https://github.com/mmsinclair)) - Explorer-api: add API resource to show the delegations for each mix node [\#774](https://github.com/nymtech/nym/pull/774) ([mmsinclair](https://github.com/mmsinclair))
@@ -577,14 +544,14 @@ The release also include some additional work for distributed key generation in
- Adding deps for building the Tauri wallet under Ubuntu [\#770](https://github.com/nymtech/nym/pull/770) ([futurechimp](https://github.com/futurechimp)) - Adding deps for building the Tauri wallet under Ubuntu [\#770](https://github.com/nymtech/nym/pull/770) ([futurechimp](https://github.com/futurechimp))
- remove alert [\#767](https://github.com/nymtech/nym/pull/767) ([fmtabbara](https://github.com/fmtabbara)) - remove alert [\#767](https://github.com/nymtech/nym/pull/767) ([fmtabbara](https://github.com/fmtabbara))
- Feature/consumable bandwidth [\#766](https://github.com/nymtech/nym/pull/766) ([neacsu](https://github.com/neacsu)) - Feature/consumable bandwidth [\#766](https://github.com/nymtech/nym/pull/766) ([neacsu](https://github.com/neacsu))
- Update coconut-rs and use hash_to_scalar from there [\#765](https://github.com/nymtech/nym/pull/765) ([neacsu](https://github.com/neacsu)) - Update coconut-rs and use hash\_to\_scalar from there [\#765](https://github.com/nymtech/nym/pull/765) ([neacsu](https://github.com/neacsu))
- Feature/active sets [\#764](https://github.com/nymtech/nym/pull/764) ([jstuczyn](https://github.com/jstuczyn)) - Feature/active sets [\#764](https://github.com/nymtech/nym/pull/764) ([jstuczyn](https://github.com/jstuczyn))
- add app alert banner [\#762](https://github.com/nymtech/nym/pull/762) ([fmtabbara](https://github.com/fmtabbara)) - add app alert banner [\#762](https://github.com/nymtech/nym/pull/762) ([fmtabbara](https://github.com/fmtabbara))
- Updated cosmos-sdk [\#761](https://github.com/nymtech/nym/pull/761) ([jstuczyn](https://github.com/jstuczyn)) - Updated cosmos-sdk [\#761](https://github.com/nymtech/nym/pull/761) ([jstuczyn](https://github.com/jstuczyn))
- Feature/bond blockstamp [\#760](https://github.com/nymtech/nym/pull/760) ([neacsu](https://github.com/neacsu)) - Feature/bond blockstamp [\#760](https://github.com/nymtech/nym/pull/760) ([neacsu](https://github.com/neacsu))
- Feature/revert migration code [\#759](https://github.com/nymtech/nym/pull/759) ([neacsu](https://github.com/neacsu)) - Feature/revert migration code [\#759](https://github.com/nymtech/nym/pull/759) ([neacsu](https://github.com/neacsu))
- Bump next from 11.1.0 to 11.1.1 in /wallet-web [\#758](https://github.com/nymtech/nym/pull/758) ([dependabot[bot]](https://github.com/apps/dependabot)) - Bump next from 11.1.0 to 11.1.1 in /wallet-web [\#758](https://github.com/nymtech/nym/pull/758) ([dependabot[bot]](https://github.com/apps/dependabot))
- Add block_height in the Delegation structure as well [\#757](https://github.com/nymtech/nym/pull/757) ([neacsu](https://github.com/neacsu)) - Add block\_height in the Delegation structure as well [\#757](https://github.com/nymtech/nym/pull/757) ([neacsu](https://github.com/neacsu))
- Feature/add blockstamp [\#756](https://github.com/nymtech/nym/pull/756) ([neacsu](https://github.com/neacsu)) - Feature/add blockstamp [\#756](https://github.com/nymtech/nym/pull/756) ([neacsu](https://github.com/neacsu))
- NetworkMonitorBuilder - starting the monitor after rocket has launched [\#754](https://github.com/nymtech/nym/pull/754) ([jstuczyn](https://github.com/jstuczyn)) - NetworkMonitorBuilder - starting the monitor after rocket has launched [\#754](https://github.com/nymtech/nym/pull/754) ([jstuczyn](https://github.com/jstuczyn))
- Enabled validators api argument [\#753](https://github.com/nymtech/nym/pull/753) ([jstuczyn](https://github.com/jstuczyn)) - Enabled validators api argument [\#753](https://github.com/nymtech/nym/pull/753) ([jstuczyn](https://github.com/jstuczyn))
@@ -596,21 +563,21 @@ The release also include some additional work for distributed key generation in
- Feature/more reliable uptime calculation [\#747](https://github.com/nymtech/nym/pull/747) ([jstuczyn](https://github.com/jstuczyn)) - Feature/more reliable uptime calculation [\#747](https://github.com/nymtech/nym/pull/747) ([jstuczyn](https://github.com/jstuczyn))
- Update template toml key [\#746](https://github.com/nymtech/nym/pull/746) ([neacsu](https://github.com/neacsu)) - Update template toml key [\#746](https://github.com/nymtech/nym/pull/746) ([neacsu](https://github.com/neacsu))
- Feature/cred after handshake [\#745](https://github.com/nymtech/nym/pull/745) ([neacsu](https://github.com/neacsu)) - Feature/cred after handshake [\#745](https://github.com/nymtech/nym/pull/745) ([neacsu](https://github.com/neacsu))
- Reinstate the POST method blind_sign [\#744](https://github.com/nymtech/nym/pull/744) ([neacsu](https://github.com/neacsu)) - Reinstate the POST method blind\_sign [\#744](https://github.com/nymtech/nym/pull/744) ([neacsu](https://github.com/neacsu))
- explorer-api: add pending field to port check response [\#742](https://github.com/nymtech/nym/pull/742) ([mmsinclair](https://github.com/mmsinclair)) - explorer-api: add pending field to port check response [\#742](https://github.com/nymtech/nym/pull/742) ([mmsinclair](https://github.com/mmsinclair))
- Feature/use delegation rates [\#741](https://github.com/nymtech/nym/pull/741) ([neacsu](https://github.com/neacsu)) - Feature/use delegation rates [\#741](https://github.com/nymtech/nym/pull/741) ([neacsu](https://github.com/neacsu))
- Feature/copy to clipboard [\#740](https://github.com/nymtech/nym/pull/740) ([fmtabbara](https://github.com/fmtabbara)) - Feature/copy to clipboard [\#740](https://github.com/nymtech/nym/pull/740) ([fmtabbara](https://github.com/fmtabbara))
- Feature/update wallet with stake rates [\#739](https://github.com/nymtech/nym/pull/739) ([neacsu](https://github.com/neacsu)) - Feature/update wallet with stake rates [\#739](https://github.com/nymtech/nym/pull/739) ([neacsu](https://github.com/neacsu))
- Add stake reward rates and bump version of client [\#738](https://github.com/nymtech/nym/pull/738) ([neacsu](https://github.com/neacsu)) - Add stake reward rates and bump version of client [\#738](https://github.com/nymtech/nym/pull/738) ([neacsu](https://github.com/neacsu))
- Bump next from 10.1.3 to 11.1.0 in /wallet-web [\#737](https://github.com/nymtech/nym/pull/737) ([dependabot[bot]](https://github.com/apps/dependabot)) - Bump next from 10.1.3 to 11.1.0 in /wallet-web [\#737](https://github.com/nymtech/nym/pull/737) ([dependabot[bot]](https://github.com/apps/dependabot))
- Feature/nyxd client integration [\#736](https://github.com/nymtech/nym/pull/736) ([jstuczyn](https://github.com/jstuczyn)) - Feature/nymd client integration [\#736](https://github.com/nymtech/nym/pull/736) ([jstuczyn](https://github.com/jstuczyn))
- Bug/fix parking lot on wasm [\#735](https://github.com/nymtech/nym/pull/735) ([neacsu](https://github.com/neacsu)) - Bug/fix parking lot on wasm [\#735](https://github.com/nymtech/nym/pull/735) ([neacsu](https://github.com/neacsu))
- Explorer API: add new HTTP resource to decorate mix nodes with geoip locations [\#734](https://github.com/nymtech/nym/pull/734) ([mmsinclair](https://github.com/mmsinclair)) - Explorer API: add new HTTP resource to decorate mix nodes with geoip locations [\#734](https://github.com/nymtech/nym/pull/734) ([mmsinclair](https://github.com/mmsinclair))
- Feature/completing nyxd client api [\#732](https://github.com/nymtech/nym/pull/732) ([jstuczyn](https://github.com/jstuczyn)) - Feature/completing nymd client api [\#732](https://github.com/nymtech/nym/pull/732) ([jstuczyn](https://github.com/jstuczyn))
- Explorer API - add port check and node description/stats proxy [\#731](https://github.com/nymtech/nym/pull/731) ([mmsinclair](https://github.com/mmsinclair)) - Explorer API - add port check and node description/stats proxy [\#731](https://github.com/nymtech/nym/pull/731) ([mmsinclair](https://github.com/mmsinclair))
- Feature/nyxd client fee handling [\#730](https://github.com/nymtech/nym/pull/730) ([jstuczyn](https://github.com/jstuczyn)) - Feature/nymd client fee handling [\#730](https://github.com/nymtech/nym/pull/730) ([jstuczyn](https://github.com/jstuczyn))
- Update DelegationCheck.tsx [\#725](https://github.com/nymtech/nym/pull/725) ([jessgess](https://github.com/jessgess)) - Update DelegationCheck.tsx [\#725](https://github.com/nymtech/nym/pull/725) ([jessgess](https://github.com/jessgess))
- Rust nyxd/cosmwasm client [\#724](https://github.com/nymtech/nym/pull/724) ([jstuczyn](https://github.com/jstuczyn)) - Rust nymd/cosmwasm client [\#724](https://github.com/nymtech/nym/pull/724) ([jstuczyn](https://github.com/jstuczyn))
- Removed wasm feature bypassing cyclic dependencies [\#723](https://github.com/nymtech/nym/pull/723) ([jstuczyn](https://github.com/jstuczyn)) - Removed wasm feature bypassing cyclic dependencies [\#723](https://github.com/nymtech/nym/pull/723) ([jstuczyn](https://github.com/jstuczyn))
- Updated used sphinx dependency to the most recent revision [\#722](https://github.com/nymtech/nym/pull/722) ([jstuczyn](https://github.com/jstuczyn)) - Updated used sphinx dependency to the most recent revision [\#722](https://github.com/nymtech/nym/pull/722) ([jstuczyn](https://github.com/jstuczyn))
- update state management and validation [\#721](https://github.com/nymtech/nym/pull/721) ([fmtabbara](https://github.com/fmtabbara)) - update state management and validation [\#721](https://github.com/nymtech/nym/pull/721) ([fmtabbara](https://github.com/fmtabbara))
@@ -629,8 +596,10 @@ The release also include some additional work for distributed key generation in
- Bond and delegation alerts [\#698](https://github.com/nymtech/nym/pull/698) ([fmtabbara](https://github.com/fmtabbara)) - Bond and delegation alerts [\#698](https://github.com/nymtech/nym/pull/698) ([fmtabbara](https://github.com/fmtabbara))
- Bugfix/network monitor version check [\#697](https://github.com/nymtech/nym/pull/697) ([jstuczyn](https://github.com/jstuczyn)) - Bugfix/network monitor version check [\#697](https://github.com/nymtech/nym/pull/697) ([jstuczyn](https://github.com/jstuczyn))
- Feature/other containers [\#692](https://github.com/nymtech/nym/pull/692) ([neacsu](https://github.com/neacsu)) - Feature/other containers [\#692](https://github.com/nymtech/nym/pull/692) ([neacsu](https://github.com/neacsu))
- Using validator API instead of nyxd [\#690](https://github.com/nymtech/nym/pull/690) ([futurechimp](https://github.com/futurechimp)) - Using validator API instead of nymd [\#690](https://github.com/nymtech/nym/pull/690) ([futurechimp](https://github.com/futurechimp))
- Hang coconut issuance off the validator-api [\#679](https://github.com/nymtech/nym/pull/679) ([durch](https://github.com/durch)) - Hang coconut issuance off the validator-api [\#679](https://github.com/nymtech/nym/pull/679) ([durch](https://github.com/durch))
- Update hmac and blake3 [\#673](https://github.com/nymtech/nym/pull/673) ([durch](https://github.com/durch)) - Update hmac and blake3 [\#673](https://github.com/nymtech/nym/pull/673) ([durch](https://github.com/durch))
\* _This Changelog was automatically generated by [github_changelog_generator](https://github.com/github-changelog-generator/github-changelog-generator)_
\* *This Changelog was automatically generated by [github_changelog_generator](https://github.com/github-changelog-generator/github-changelog-generator)*
Generated
+139 -374
View File
@@ -23,16 +23,6 @@ dependencies = [
"generic-array 0.14.5", "generic-array 0.14.5",
] ]
[[package]]
name = "aead"
version = "0.5.1"
source = "registry+https://github.com/rust-lang/crates.io-index"
checksum = "5c192eb8f11fc081b0fe4259ba5af04217d4e0faddd02417310a927911abd7c8"
dependencies = [
"crypto-common",
"generic-array 0.14.5",
]
[[package]] [[package]]
name = "aes" name = "aes"
version = "0.7.5" version = "0.7.5"
@@ -63,7 +53,7 @@ version = "0.9.4"
source = "registry+https://github.com/rust-lang/crates.io-index" source = "registry+https://github.com/rust-lang/crates.io-index"
checksum = "df5f85a83a7d8b0442b6aa7b504b8212c1733da07b98aae43d4bc21b2cb3cdf6" checksum = "df5f85a83a7d8b0442b6aa7b504b8212c1733da07b98aae43d4bc21b2cb3cdf6"
dependencies = [ dependencies = [
"aead 0.4.3", "aead",
"aes 0.7.5", "aes 0.7.5",
"cipher 0.3.0", "cipher 0.3.0",
"ctr 0.8.0", "ctr 0.8.0",
@@ -91,12 +81,6 @@ dependencies = [
"memchr", "memchr",
] ]
[[package]]
name = "anes"
version = "0.1.6"
source = "registry+https://github.com/rust-lang/crates.io-index"
checksum = "4b46cbb362ab8752921c97e041f5e366ee6297bd428a31275b9fcf1e380f7299"
[[package]] [[package]]
name = "ansi_term" name = "ansi_term"
version = "0.12.1" version = "0.12.1"
@@ -426,13 +410,6 @@ dependencies = [
"serde", "serde",
] ]
[[package]]
name = "build-information"
version = "0.1.0"
dependencies = [
"vergen 7.2.1",
]
[[package]] [[package]]
name = "bumpalo" name = "bumpalo"
version = "3.9.1" version = "3.9.1"
@@ -466,12 +443,6 @@ dependencies = [
"rustc_version 0.4.0", "rustc_version 0.4.0",
] ]
[[package]]
name = "cast"
version = "0.3.0"
source = "registry+https://github.com/rust-lang/crates.io-index"
checksum = "37b2a672a2cb129a2e41c10b1224bb368f9f37a2b16b612598138befd7b37eb5"
[[package]] [[package]]
name = "cc" name = "cc"
version = "1.0.73" version = "1.0.73"
@@ -503,30 +474,6 @@ dependencies = [
"keystream", "keystream",
] ]
[[package]]
name = "chacha20"
version = "0.9.0"
source = "registry+https://github.com/rust-lang/crates.io-index"
checksum = "c7fc89c7c5b9e7a02dfe45cd2367bae382f9ed31c61ca8debe5f827c420a2f08"
dependencies = [
"cfg-if 1.0.0",
"cipher 0.4.3",
"cpufeatures",
]
[[package]]
name = "chacha20poly1305"
version = "0.10.1"
source = "registry+https://github.com/rust-lang/crates.io-index"
checksum = "10cd79432192d1c0f4e1a0fef9527696cc039165d729fb41b3f4f4f354c2dc35"
dependencies = [
"aead 0.5.1",
"chacha20",
"cipher 0.4.3",
"poly1305",
"zeroize",
]
[[package]] [[package]]
name = "chrono" name = "chrono"
version = "0.4.19" version = "0.4.19"
@@ -541,33 +488,6 @@ dependencies = [
"winapi", "winapi",
] ]
[[package]]
name = "ciborium"
version = "0.2.0"
source = "registry+https://github.com/rust-lang/crates.io-index"
checksum = "b0c137568cc60b904a7724001b35ce2630fd00d5d84805fbb608ab89509d788f"
dependencies = [
"ciborium-io",
"ciborium-ll",
"serde",
]
[[package]]
name = "ciborium-io"
version = "0.2.0"
source = "registry+https://github.com/rust-lang/crates.io-index"
checksum = "346de753af073cc87b52b2083a506b38ac176a44cfb05497b622e27be899b369"
[[package]]
name = "ciborium-ll"
version = "0.2.0"
source = "registry+https://github.com/rust-lang/crates.io-index"
checksum = "213030a2b5a4e0c0892b6652260cf6ccac84827b83a85a534e178e3906c4cf1b"
dependencies = [
"ciborium-io",
"half",
]
[[package]] [[package]]
name = "cipher" name = "cipher"
version = "0.3.0" version = "0.3.0"
@@ -585,7 +505,6 @@ checksum = "d1873270f8f7942c191139cb8a40fd228da6c3fd2fc376d7e92d47aa14aeb59e"
dependencies = [ dependencies = [
"crypto-common", "crypto-common",
"inout", "inout",
"zeroize",
] ]
[[package]] [[package]]
@@ -605,51 +524,41 @@ version = "3.2.8"
source = "registry+https://github.com/rust-lang/crates.io-index" source = "registry+https://github.com/rust-lang/crates.io-index"
checksum = "190814073e85d238f31ff738fcb0bf6910cedeb73376c87cd69291028966fd83" checksum = "190814073e85d238f31ff738fcb0bf6910cedeb73376c87cd69291028966fd83"
dependencies = [ dependencies = [
"atty",
"bitflags", "bitflags",
"clap_lex 0.2.4", "clap_derive",
"clap_lex",
"indexmap", "indexmap",
"once_cell",
"strsim",
"termcolor",
"textwrap 0.15.0", "textwrap 0.15.0",
] ]
[[package]]
name = "clap"
version = "4.0.26"
source = "registry+https://github.com/rust-lang/crates.io-index"
checksum = "2148adefda54e14492fb9bddcc600b4344c5d1a3123bd666dcb939c6f0e0e57e"
dependencies = [
"atty",
"bitflags",
"clap_derive",
"clap_lex 0.3.0",
"once_cell",
"strsim",
"termcolor",
]
[[package]] [[package]]
name = "clap_complete" name = "clap_complete"
version = "4.0.7" version = "3.2.4"
source = "registry+https://github.com/rust-lang/crates.io-index" source = "registry+https://github.com/rust-lang/crates.io-index"
checksum = "10861370d2ba66b0f5989f83ebf35db6421713fd92351790e7fdd6c36774c56b" checksum = "e4179da71abd56c26b54dd0c248cc081c1f43b0a1a7e8448e28e57a29baa993d"
dependencies = [ dependencies = [
"clap 4.0.26", "clap 3.2.8",
] ]
[[package]] [[package]]
name = "clap_complete_fig" name = "clap_complete_fig"
version = "4.0.2" version = "3.2.4"
source = "registry+https://github.com/rust-lang/crates.io-index" source = "registry+https://github.com/rust-lang/crates.io-index"
checksum = "46b30e010e669cd021e5004f3be26cff6b7c08d2a8a0d65b48d43a8cc0efd6c3" checksum = "ed37b4c0c1214673eba6ad8ea31666626bf72be98ffb323067d973c48b4964b9"
dependencies = [ dependencies = [
"clap 4.0.26", "clap 3.2.8",
"clap_complete", "clap_complete",
] ]
[[package]] [[package]]
name = "clap_derive" name = "clap_derive"
version = "4.0.21" version = "3.2.7"
source = "registry+https://github.com/rust-lang/crates.io-index" source = "registry+https://github.com/rust-lang/crates.io-index"
checksum = "0177313f9f02afc995627906bbd8967e2be069f5261954222dac78290c2b9014" checksum = "759bf187376e1afa7b85b959e6a664a3e7a95203415dba952ad19139e798f902"
dependencies = [ dependencies = [
"heck 0.4.0", "heck 0.4.0",
"proc-macro-error", "proc-macro-error",
@@ -667,15 +576,6 @@ dependencies = [
"os_str_bytes", "os_str_bytes",
] ]
[[package]]
name = "clap_lex"
version = "0.3.0"
source = "registry+https://github.com/rust-lang/crates.io-index"
checksum = "0d4198f73e42b4936b35b5bb248d81d2b595ecb170da0bac7655c54eedfa8da8"
dependencies = [
"os_str_bytes",
]
[[package]] [[package]]
name = "client-connections" name = "client-connections"
version = "0.1.0" version = "0.1.0"
@@ -686,7 +586,7 @@ dependencies = [
[[package]] [[package]]
name = "client-core" name = "client-core"
version = "1.1.5" version = "1.1.3"
dependencies = [ dependencies = [
"async-trait", "async-trait",
"client-connections", "client-connections",
@@ -792,7 +692,7 @@ dependencies = [
name = "completions" name = "completions"
version = "0.1.0" version = "0.1.0"
dependencies = [ dependencies = [
"clap 4.0.26", "clap 3.2.8",
"clap_complete", "clap_complete",
"clap_complete_fig", "clap_complete_fig",
] ]
@@ -1031,7 +931,7 @@ version = "0.1.0"
dependencies = [ dependencies = [
"bip39", "bip39",
"cfg-if 0.1.10", "cfg-if 0.1.10",
"clap 4.0.26", "clap 3.2.8",
"coconut-interface", "coconut-interface",
"completions", "completions",
"config", "config",
@@ -1080,9 +980,9 @@ source = "registry+https://github.com/rust-lang/crates.io-index"
checksum = "1604dafd25fba2fe2d5895a9da139f8dc9b319a5fe5354ca137cbbce4e178d10" checksum = "1604dafd25fba2fe2d5895a9da139f8dc9b319a5fe5354ca137cbbce4e178d10"
dependencies = [ dependencies = [
"atty", "atty",
"cast 0.2.7", "cast",
"clap 2.34.0", "clap 2.34.0",
"criterion-plot 0.4.4", "criterion-plot",
"csv", "csv",
"itertools", "itertools",
"lazy_static", "lazy_static",
@@ -1099,49 +999,13 @@ dependencies = [
"walkdir", "walkdir",
] ]
[[package]]
name = "criterion"
version = "0.4.0"
source = "registry+https://github.com/rust-lang/crates.io-index"
checksum = "e7c76e09c1aae2bc52b3d2f29e13c6572553b30c4aa1b8a49fd70de6412654cb"
dependencies = [
"anes",
"atty",
"cast 0.3.0",
"ciborium",
"clap 3.2.8",
"criterion-plot 0.5.0",
"itertools",
"lazy_static",
"num-traits",
"oorandom",
"plotters",
"rayon",
"regex",
"serde",
"serde_derive",
"serde_json",
"tinytemplate",
"walkdir",
]
[[package]] [[package]]
name = "criterion-plot" name = "criterion-plot"
version = "0.4.4" version = "0.4.4"
source = "registry+https://github.com/rust-lang/crates.io-index" source = "registry+https://github.com/rust-lang/crates.io-index"
checksum = "d00996de9f2f7559f7f4dc286073197f83e92256a59ed395f9aac01fe717da57" checksum = "d00996de9f2f7559f7f4dc286073197f83e92256a59ed395f9aac01fe717da57"
dependencies = [ dependencies = [
"cast 0.2.7", "cast",
"itertools",
]
[[package]]
name = "criterion-plot"
version = "0.5.0"
source = "registry+https://github.com/rust-lang/crates.io-index"
checksum = "6b50826342786a51a89e2da3a28f1c32b06e387201bc2d19791f622c673706b1"
dependencies = [
"cast 0.3.0",
"itertools", "itertools",
] ]
@@ -1270,12 +1134,11 @@ dependencies = [
[[package]] [[package]]
name = "crypto-common" name = "crypto-common"
version = "0.1.6" version = "0.1.3"
source = "registry+https://github.com/rust-lang/crates.io-index" source = "registry+https://github.com/rust-lang/crates.io-index"
checksum = "1bfb12502f3fc46cca1bb51ac28df9d618d813cdc3d2f25b9fe775a34af26bb3" checksum = "57952ca27b5e3606ff4dd79b0020231aaf9d6aa76dc05fd30137538c50bd3ce8"
dependencies = [ dependencies = [
"generic-array 0.14.5", "generic-array 0.14.5",
"rand_core 0.6.3",
"typenum", "typenum",
] ]
@@ -1603,7 +1466,7 @@ dependencies = [
"bitvec", "bitvec",
"bls12_381 0.6.0", "bls12_381 0.6.0",
"bs58", "bs58",
"criterion 0.3.5", "criterion",
"ff 0.11.0", "ff 0.11.0",
"group 0.11.0", "group 0.11.0",
"lazy_static", "lazy_static",
@@ -1788,10 +1651,10 @@ dependencies = [
[[package]] [[package]]
name = "explorer-api" name = "explorer-api"
version = "1.1.2" version = "1.1.1"
dependencies = [ dependencies = [
"chrono", "chrono",
"clap 4.0.26", "clap 3.2.8",
"contracts-common", "contracts-common",
"dotenv", "dotenv",
"humantime-serde", "humantime-serde",
@@ -1804,9 +1667,6 @@ dependencies = [
"network-defaults", "network-defaults",
"okapi", "okapi",
"pretty_env_logger", "pretty_env_logger",
"rand 0.8.5",
"rand_pcg 0.3.1",
"rand_seeder",
"reqwest", "reqwest",
"rocket", "rocket",
"rocket_cors", "rocket_cors",
@@ -1838,9 +1698,9 @@ checksum = "e88a8acf291dafb59c2d96e8f59828f3838bb1a70398823ade51a84de6a6deed"
[[package]] [[package]]
name = "fastrand" name = "fastrand"
version = "1.8.0" version = "1.7.0"
source = "registry+https://github.com/rust-lang/crates.io-index" source = "registry+https://github.com/rust-lang/crates.io-index"
checksum = "a7a407cfaa3385c4ae6b23e84623d48c2798d06e3e6a1878f7f59f17b3f86499" checksum = "c3fcf0cee53519c866c09b5de1f6c56ff9d647101f81c1964fa632e148896cdf"
dependencies = [ dependencies = [
"instant", "instant",
] ]
@@ -1970,9 +1830,9 @@ checksum = "e6d5a32815ae3f33302d95fdcb2ce17862f8c65363dcfd29360480ba1001fc9c"
[[package]] [[package]]
name = "futures" name = "futures"
version = "0.3.25" version = "0.3.24"
source = "registry+https://github.com/rust-lang/crates.io-index" source = "registry+https://github.com/rust-lang/crates.io-index"
checksum = "38390104763dc37a5145a53c29c63c1290b5d316d6086ec32c293f6736051bb0" checksum = "7f21eda599937fba36daeb58a22e8f5cee2d14c4a17b5b7739c7c8e5e3b8230c"
dependencies = [ dependencies = [
"futures-channel", "futures-channel",
"futures-core", "futures-core",
@@ -1985,9 +1845,9 @@ dependencies = [
[[package]] [[package]]
name = "futures-channel" name = "futures-channel"
version = "0.3.25" version = "0.3.24"
source = "registry+https://github.com/rust-lang/crates.io-index" source = "registry+https://github.com/rust-lang/crates.io-index"
checksum = "52ba265a92256105f45b719605a571ffe2d1f0fea3807304b522c1d778f79eed" checksum = "30bdd20c28fadd505d0fd6712cdfcb0d4b5648baf45faef7f852afb2399bb050"
dependencies = [ dependencies = [
"futures-core", "futures-core",
"futures-sink", "futures-sink",
@@ -1995,15 +1855,15 @@ dependencies = [
[[package]] [[package]]
name = "futures-core" name = "futures-core"
version = "0.3.25" version = "0.3.24"
source = "registry+https://github.com/rust-lang/crates.io-index" source = "registry+https://github.com/rust-lang/crates.io-index"
checksum = "04909a7a7e4633ae6c4a9ab280aeb86da1236243a77b694a49eacd659a4bd3ac" checksum = "4e5aa3de05362c3fb88de6531e6296e85cde7739cccad4b9dfeeb7f6ebce56bf"
[[package]] [[package]]
name = "futures-executor" name = "futures-executor"
version = "0.3.25" version = "0.3.24"
source = "registry+https://github.com/rust-lang/crates.io-index" source = "registry+https://github.com/rust-lang/crates.io-index"
checksum = "7acc85df6714c176ab5edf386123fafe217be88c0840ec11f199441134a074e2" checksum = "9ff63c23854bee61b6e9cd331d523909f238fc7636290b96826e9cfa5faa00ab"
dependencies = [ dependencies = [
"futures-core", "futures-core",
"futures-task", "futures-task",
@@ -2023,15 +1883,15 @@ dependencies = [
[[package]] [[package]]
name = "futures-io" name = "futures-io"
version = "0.3.25" version = "0.3.24"
source = "registry+https://github.com/rust-lang/crates.io-index" source = "registry+https://github.com/rust-lang/crates.io-index"
checksum = "00f5fb52a06bdcadeb54e8d3671f8888a39697dcb0b81b23b55174030427f4eb" checksum = "bbf4d2a7a308fd4578637c0b17c7e1c7ba127b8f6ba00b29f717e9655d85eb68"
[[package]] [[package]]
name = "futures-macro" name = "futures-macro"
version = "0.3.25" version = "0.3.24"
source = "registry+https://github.com/rust-lang/crates.io-index" source = "registry+https://github.com/rust-lang/crates.io-index"
checksum = "bdfb8ce053d86b91919aad980c220b1fb8401a9394410e1c289ed7e66b61835d" checksum = "42cd15d1c7456c04dbdf7e88bcd69760d74f3a798d6444e16974b505b0e62f17"
dependencies = [ dependencies = [
"proc-macro2", "proc-macro2",
"quote", "quote",
@@ -2040,21 +1900,21 @@ dependencies = [
[[package]] [[package]]
name = "futures-sink" name = "futures-sink"
version = "0.3.25" version = "0.3.24"
source = "registry+https://github.com/rust-lang/crates.io-index" source = "registry+https://github.com/rust-lang/crates.io-index"
checksum = "39c15cf1a4aa79df40f1bb462fb39676d0ad9e366c2a33b590d7c66f4f81fcf9" checksum = "21b20ba5a92e727ba30e72834706623d94ac93a725410b6a6b6fbc1b07f7ba56"
[[package]] [[package]]
name = "futures-task" name = "futures-task"
version = "0.3.25" version = "0.3.24"
source = "registry+https://github.com/rust-lang/crates.io-index" source = "registry+https://github.com/rust-lang/crates.io-index"
checksum = "2ffb393ac5d9a6eaa9d3fdf37ae2776656b706e200c8e16b1bdb227f5198e6ea" checksum = "a6508c467c73851293f390476d4491cf4d227dbabcd4170f3bb6044959b294f1"
[[package]] [[package]]
name = "futures-util" name = "futures-util"
version = "0.3.25" version = "0.3.24"
source = "registry+https://github.com/rust-lang/crates.io-index" source = "registry+https://github.com/rust-lang/crates.io-index"
checksum = "197676987abd2f9cadff84926f410af1c183608d36641465df73ae8211dc65d6" checksum = "44fb6cb1be61cc1d2e43b262516aafcf63b241cffdb1d3fa115f91d9c7b09c90"
dependencies = [ dependencies = [
"futures-channel", "futures-channel",
"futures-core", "futures-core",
@@ -2085,7 +1945,6 @@ dependencies = [
"nymsphinx", "nymsphinx",
"pemstore", "pemstore",
"rand 0.7.3", "rand 0.7.3",
"serde",
"task", "task",
"thiserror", "thiserror",
"tokio", "tokio",
@@ -3232,72 +3091,6 @@ dependencies = [
"libc", "libc",
] ]
[[package]]
name = "nym-api"
version = "1.1.5"
dependencies = [
"anyhow",
"async-trait",
"bip39",
"bs58",
"build-information",
"cfg-if 1.0.0",
"clap 4.0.26",
"coconut-bandwidth-contract-common",
"coconut-dkg-common",
"coconut-interface",
"config",
"console-subscriber",
"contracts-common",
"cosmwasm-std",
"credential-storage",
"credentials",
"crypto",
"cw-utils",
"cw3",
"dirs",
"dkg",
"dotenv",
"futures",
"gateway-client",
"getset",
"humantime-serde",
"inclusion-probability",
"lazy_static",
"log",
"logging",
"mixnet-contract-common",
"multisig-contract-common",
"nym-api-requests",
"nymcoconut",
"nymsphinx",
"okapi",
"pemstore",
"pin-project",
"pretty_env_logger",
"rand 0.7.3",
"rand 0.8.5",
"reqwest",
"rocket",
"rocket_cors",
"rocket_okapi",
"schemars",
"serde",
"serde_json",
"sqlx 0.6.2",
"tap",
"task",
"thiserror",
"time 0.3.17",
"tokio",
"tokio-stream",
"topology",
"ts-rs",
"url",
"validator-client",
"version-checker",
]
[[package]] [[package]]
name = "nym-api-requests" name = "nym-api-requests"
version = "0.1.0" version = "0.1.0"
@@ -3330,13 +3123,13 @@ dependencies = [
[[package]] [[package]]
name = "nym-cli" name = "nym-cli"
version = "1.1.5" version = "1.1.3"
dependencies = [ dependencies = [
"anyhow", "anyhow",
"base64", "base64",
"bip39", "bip39",
"bs58", "bs58",
"clap 4.0.26", "clap 3.2.8",
"clap_complete", "clap_complete",
"clap_complete_fig", "clap_complete_fig",
"dotenv", "dotenv",
@@ -3360,19 +3153,15 @@ dependencies = [
"bip39", "bip39",
"bs58", "bs58",
"cfg-if 1.0.0", "cfg-if 1.0.0",
"clap 4.0.26", "clap 3.2.8",
"coconut-bandwidth-contract-common",
"coconut-dkg-common",
"comfy-table", "comfy-table",
"cosmrs", "cosmrs",
"cosmwasm-std", "cosmwasm-std",
"cw-utils",
"handlebars", "handlebars",
"humantime-serde", "humantime-serde",
"k256", "k256",
"log", "log",
"mixnet-contract-common", "mixnet-contract-common",
"multisig-contract-common",
"network-defaults", "network-defaults",
"rand 0.6.5", "rand 0.6.5",
"serde", "serde",
@@ -3388,10 +3177,9 @@ dependencies = [
[[package]] [[package]]
name = "nym-client" name = "nym-client"
version = "1.1.5" version = "1.1.3"
dependencies = [ dependencies = [
"build-information", "clap 3.2.8",
"clap 4.0.26",
"client-connections", "client-connections",
"client-core", "client-core",
"coconut-interface", "coconut-interface",
@@ -3404,7 +3192,6 @@ dependencies = [
"futures", "futures",
"gateway-client", "gateway-client",
"gateway-requests", "gateway-requests",
"lazy_static",
"log", "log",
"logging", "logging",
"network-defaults", "network-defaults",
@@ -3422,21 +3209,20 @@ dependencies = [
"topology", "topology",
"url", "url",
"validator-client", "validator-client",
"vergen 5.1.17",
"version-checker", "version-checker",
"websocket-requests", "websocket-requests",
] ]
[[package]] [[package]]
name = "nym-gateway" name = "nym-gateway"
version = "1.1.5" version = "1.1.3"
dependencies = [ dependencies = [
"anyhow", "anyhow",
"async-trait", "async-trait",
"atty",
"bip39", "bip39",
"bs58", "bs58",
"build-information", "clap 3.2.8",
"clap 4.0.26",
"coconut-interface", "coconut-interface",
"colored", "colored",
"completions", "completions",
@@ -3449,21 +3235,18 @@ dependencies = [
"futures", "futures",
"gateway-requests", "gateway-requests",
"humantime-serde", "humantime-serde",
"lazy_static",
"log", "log",
"logging", "logging",
"mixnet-client", "mixnet-client",
"mixnode-common", "mixnode-common",
"network-defaults", "network-defaults",
"nym-api-requests", "nym-api-requests",
"nym-types",
"nymsphinx", "nymsphinx",
"once_cell", "once_cell",
"pemstore", "pemstore",
"pretty_env_logger", "pretty_env_logger",
"rand 0.7.3", "rand 0.7.3",
"serde", "serde",
"serde_json",
"sqlx 0.5.11", "sqlx 0.5.11",
"statistics-common", "statistics-common",
"subtle-encoding", "subtle-encoding",
@@ -3474,18 +3257,17 @@ dependencies = [
"tokio-util 0.7.3", "tokio-util 0.7.3",
"url", "url",
"validator-client", "validator-client",
"vergen 5.1.17",
"version-checker", "version-checker",
] ]
[[package]] [[package]]
name = "nym-mixnode" name = "nym-mixnode"
version = "1.1.5" version = "1.1.3"
dependencies = [ dependencies = [
"anyhow", "anyhow",
"atty",
"bs58", "bs58",
"build-information", "clap 3.2.8",
"clap 4.0.26",
"colored", "colored",
"completions", "completions",
"config", "config",
@@ -3501,7 +3283,6 @@ dependencies = [
"mixnet-client", "mixnet-client",
"mixnode-common", "mixnode-common",
"nonexhaustive-delayqueue", "nonexhaustive-delayqueue",
"nym-types",
"nymsphinx", "nymsphinx",
"nymsphinx-params", "nymsphinx-params",
"nymsphinx-types", "nymsphinx-types",
@@ -3510,7 +3291,6 @@ dependencies = [
"rand 0.7.3", "rand 0.7.3",
"rocket", "rocket",
"serde", "serde",
"serde_json",
"sysinfo", "sysinfo",
"task", "task",
"tokio", "tokio",
@@ -3519,15 +3299,16 @@ dependencies = [
"topology", "topology",
"url", "url",
"validator-client", "validator-client",
"vergen 5.1.17",
"version-checker", "version-checker",
] ]
[[package]] [[package]]
name = "nym-network-requester" name = "nym-network-requester"
version = "1.1.5" version = "1.1.3"
dependencies = [ dependencies = [
"async-trait", "async-trait",
"clap 4.0.26", "clap 3.2.8",
"client-connections", "client-connections",
"completions", "completions",
"dirs", "dirs",
@@ -3556,7 +3337,7 @@ dependencies = [
[[package]] [[package]]
name = "nym-network-statistics" name = "nym-network-statistics"
version = "1.1.5" version = "1.1.3"
dependencies = [ dependencies = [
"dirs", "dirs",
"log", "log",
@@ -3570,52 +3351,11 @@ dependencies = [
"tokio", "tokio",
] ]
[[package]]
name = "nym-outfox"
version = "0.1.0"
dependencies = [
"blake3",
"chacha20",
"chacha20poly1305",
"criterion 0.4.0",
"curve25519-dalek",
"fastrand",
"getrandom 0.2.6",
"rayon",
"thiserror",
"zeroize",
]
[[package]]
name = "nym-sdk"
version = "0.1.0"
dependencies = [
"client-connections",
"client-core",
"crypto",
"futures",
"gateway-client",
"gateway-requests",
"log",
"logging",
"network-defaults",
"nymsphinx",
"pretty_env_logger",
"rand 0.7.3",
"tap",
"task",
"thiserror",
"tokio",
"toml",
"url",
]
[[package]] [[package]]
name = "nym-socks5-client" name = "nym-socks5-client"
version = "1.1.5" version = "1.1.3"
dependencies = [ dependencies = [
"build-information", "clap 3.2.8",
"clap 4.0.26",
"client-connections", "client-connections",
"client-core", "client-core",
"coconut-interface", "coconut-interface",
@@ -3628,7 +3368,6 @@ dependencies = [
"futures", "futures",
"gateway-client", "gateway-client",
"gateway-requests", "gateway-requests",
"lazy_static",
"log", "log",
"logging", "logging",
"network-defaults", "network-defaults",
@@ -3649,6 +3388,7 @@ dependencies = [
"topology", "topology",
"url", "url",
"validator-client", "validator-client",
"vergen 5.1.17",
"version-checker", "version-checker",
] ]
@@ -3678,6 +3418,70 @@ dependencies = [
"vesting-contract-common", "vesting-contract-common",
] ]
[[package]]
name = "nym-validator-api"
version = "1.1.3"
dependencies = [
"anyhow",
"async-trait",
"bs58",
"cfg-if 1.0.0",
"clap 3.2.8",
"coconut-bandwidth-contract-common",
"coconut-dkg-common",
"coconut-interface",
"config",
"console-subscriber",
"contracts-common",
"cosmwasm-std",
"credential-storage",
"credentials",
"crypto",
"cw-utils",
"cw3",
"dirs",
"dkg",
"dotenv",
"futures",
"gateway-client",
"getset",
"humantime-serde",
"inclusion-probability",
"log",
"logging",
"mixnet-contract-common",
"multisig-contract-common",
"nym-api-requests",
"nymcoconut",
"nymsphinx",
"okapi",
"pemstore",
"pin-project",
"pretty_env_logger",
"rand 0.7.3",
"rand 0.8.5",
"reqwest",
"rocket",
"rocket_cors",
"rocket_okapi",
"schemars",
"serde",
"serde_json",
"sqlx 0.6.2",
"tap",
"task",
"thiserror",
"time 0.3.17",
"tokio",
"tokio-stream",
"topology",
"ts-rs",
"url",
"validator-client",
"vergen 7.2.1",
"version-checker",
]
[[package]] [[package]]
name = "nym-wallet-types" name = "nym-wallet-types"
version = "1.0.0" version = "1.0.0"
@@ -3705,7 +3509,7 @@ dependencies = [
"bincode", "bincode",
"bls12_381 0.6.0", "bls12_381 0.6.0",
"bs58", "bs58",
"criterion 0.3.5", "criterion",
"digest 0.9.0", "digest 0.9.0",
"dkg", "dkg",
"doc-comment", "doc-comment",
@@ -4217,17 +4021,6 @@ dependencies = [
"plotters-backend", "plotters-backend",
] ]
[[package]]
name = "poly1305"
version = "0.8.0"
source = "registry+https://github.com/rust-lang/crates.io-index"
checksum = "8159bd90725d2df49889a078b54f4f79e87f1f8a8444194cdca81d38f5393abf"
dependencies = [
"cpufeatures",
"opaque-debug 0.3.0",
"universal-hash 0.5.0",
]
[[package]] [[package]]
name = "polyval" name = "polyval"
version = "0.5.3" version = "0.5.3"
@@ -4237,7 +4030,7 @@ dependencies = [
"cfg-if 1.0.0", "cfg-if 1.0.0",
"cpufeatures", "cpufeatures",
"opaque-debug 0.3.0", "opaque-debug 0.3.0",
"universal-hash 0.4.1", "universal-hash",
] ]
[[package]] [[package]]
@@ -4459,7 +4252,7 @@ dependencies = [
"rand_isaac", "rand_isaac",
"rand_jitter", "rand_jitter",
"rand_os", "rand_os",
"rand_pcg 0.1.2", "rand_pcg",
"rand_xorshift", "rand_xorshift",
"winapi", "winapi",
] ]
@@ -4623,24 +4416,6 @@ dependencies = [
"rand_core 0.4.2", "rand_core 0.4.2",
] ]
[[package]]
name = "rand_pcg"
version = "0.3.1"
source = "registry+https://github.com/rust-lang/crates.io-index"
checksum = "59cad018caf63deb318e5a4586d99a24424a364f40f1e5778c29aca23f4fc73e"
dependencies = [
"rand_core 0.6.3",
]
[[package]]
name = "rand_seeder"
version = "0.2.3"
source = "registry+https://github.com/rust-lang/crates.io-index"
checksum = "cf2890aaef0aa82719a50e808de264f9484b74b442e1a3a0e5ee38243ac40bdb"
dependencies = [
"rand_core 0.6.3",
]
[[package]] [[package]]
name = "rand_xorshift" name = "rand_xorshift"
version = "0.1.1" version = "0.1.1"
@@ -6012,18 +5787,18 @@ checksum = "b1141d4d61095b28419e22cb0bbf02755f5e54e0526f97f1e3d1d160e60885fb"
[[package]] [[package]]
name = "thiserror" name = "thiserror"
version = "1.0.38" version = "1.0.37"
source = "registry+https://github.com/rust-lang/crates.io-index" source = "registry+https://github.com/rust-lang/crates.io-index"
checksum = "6a9cd18aa97d5c45c6603caea1da6628790b37f7a34b6ca89522331c5180fed0" checksum = "10deb33631e3c9018b9baf9dcbbc4f737320d2b576bac10f6aefa048fa407e3e"
dependencies = [ dependencies = [
"thiserror-impl", "thiserror-impl",
] ]
[[package]] [[package]]
name = "thiserror-impl" name = "thiserror-impl"
version = "1.0.38" version = "1.0.37"
source = "registry+https://github.com/rust-lang/crates.io-index" source = "registry+https://github.com/rust-lang/crates.io-index"
checksum = "1fb327af4685e4d03fa8cbcf1716380da910eeb2bb8be417e7f9fd3fb164f36f" checksum = "982d17546b47146b28f7c22e3d08465f6b8903d0ea13c1660d9d84a6e7adcdbb"
dependencies = [ dependencies = [
"proc-macro2", "proc-macro2",
"quote", "quote",
@@ -6243,9 +6018,9 @@ dependencies = [
[[package]] [[package]]
name = "toml" name = "toml"
version = "0.5.10" version = "0.5.8"
source = "registry+https://github.com/rust-lang/crates.io-index" source = "registry+https://github.com/rust-lang/crates.io-index"
checksum = "1333c76748e868a4d9d1017b5ab53171dfd095f70c712fdb4653a406547f598f" checksum = "a31142970826733df8241ef35dc040ef98c679ab14d7c3e54d827099b3acecaa"
dependencies = [ dependencies = [
"serde", "serde",
] ]
@@ -6613,16 +6388,6 @@ dependencies = [
"subtle 2.4.1", "subtle 2.4.1",
] ]
[[package]]
name = "universal-hash"
version = "0.5.0"
source = "registry+https://github.com/rust-lang/crates.io-index"
checksum = "7d3160b73c9a19f7e2939a2fdad446c57c1bbbbf4d919d3213ff1267a580d8b5"
dependencies = [
"crypto-common",
"subtle 2.4.1",
]
[[package]] [[package]]
name = "untrusted" name = "untrusted"
version = "0.7.1" version = "0.7.1"
@@ -7146,9 +6911,9 @@ checksum = "09041cd90cf85f7f8b2df60c646f853b7f535ce68f85244eb6731cf89fa498ec"
[[package]] [[package]]
name = "zeroize" name = "zeroize"
version = "1.5.7" version = "1.4.3"
source = "registry+https://github.com/rust-lang/crates.io-index" source = "registry+https://github.com/rust-lang/crates.io-index"
checksum = "c394b5bd0c6f669e7275d9c20aa90ae064cb22e75a1cad54e1b34088034b149f" checksum = "d68d9dcec5f9b43a30d38c49f91dfedfaac384cb8f085faca366c26207dd1619"
dependencies = [ dependencies = [
"zeroize_derive", "zeroize_derive",
] ]
-3
View File
@@ -30,7 +30,6 @@ members = [
"common/coconut-interface", "common/coconut-interface",
"common/commands", "common/commands",
"common/config", "common/config",
"common/build-information",
"common/cosmwasm-smart-contracts/coconut-bandwidth-contract", "common/cosmwasm-smart-contracts/coconut-bandwidth-contract",
"common/cosmwasm-smart-contracts/coconut-dkg", "common/cosmwasm-smart-contracts/coconut-dkg",
"common/cosmwasm-smart-contracts/contracts-common", "common/cosmwasm-smart-contracts/contracts-common",
@@ -73,12 +72,10 @@ members = [
"gateway/gateway-requests", "gateway/gateway-requests",
"integrations/bity", "integrations/bity",
"mixnode", "mixnode",
"sdk/rust/nym-sdk",
"service-providers/network-requester", "service-providers/network-requester",
"service-providers/network-statistics", "service-providers/network-statistics",
"nym-api", "nym-api",
"nym-api/nym-api-requests", "nym-api/nym-api-requests",
"nym-outfox",
"tools/nym-cli", "tools/nym-cli",
"tools/ts-rs-cli" "tools/ts-rs-cli"
] ]
+1 -2
View File
@@ -1,9 +1,8 @@
[package] [package]
name = "client-core" name = "client-core"
version = "1.1.5" version = "1.1.3"
authors = ["Dave Hrycyszyn <futurechimp@users.noreply.github.com>"] authors = ["Dave Hrycyszyn <futurechimp@users.noreply.github.com>"]
edition = "2021" edition = "2021"
rust-version = "1.66"
# See more keys and their definitions at https://doc.rust-lang.org/cargo/reference/manifest.html # See more keys and their definitions at https://doc.rust-lang.org/cargo/reference/manifest.html
@@ -33,15 +33,12 @@ use log::{debug, info};
use nymsphinx::acknowledgements::AckKey; use nymsphinx::acknowledgements::AckKey;
use nymsphinx::addressing::clients::Recipient; use nymsphinx::addressing::clients::Recipient;
use nymsphinx::addressing::nodes::NodeIdentity; use nymsphinx::addressing::nodes::NodeIdentity;
use nymsphinx::receiver::ReconstructedMessage;
use std::sync::Arc; use std::sync::Arc;
use std::time::Duration; use std::time::Duration;
use tap::TapFallible; use tap::TapFallible;
use task::{TaskClient, TaskManager}; use task::{TaskClient, TaskManager};
use url::Url; use url::Url;
use super::received_buffer::ReceivedBufferMessage;
#[cfg(all(not(target_arch = "wasm32"), feature = "fs-surb-storage"))] #[cfg(all(not(target_arch = "wasm32"), feature = "fs-surb-storage"))]
pub mod non_wasm_helpers; pub mod non_wasm_helpers;
@@ -51,28 +48,8 @@ pub struct ClientInput {
} }
pub struct ClientOutput { pub struct ClientOutput {
pub received_buffer_request_sender: ReceivedBufferRequestSender,
}
impl ClientOutput {
pub fn register_receiver(
&mut self,
) -> Result<mpsc::UnboundedReceiver<Vec<ReconstructedMessage>>, ClientCoreError> {
let (reconstructed_sender, reconstructed_receiver) = mpsc::unbounded();
self.received_buffer_request_sender
.unbounded_send(ReceivedBufferMessage::ReceiverAnnounce(
reconstructed_sender,
))
.map_err(|_| ClientCoreError::FailedToRegisterReceiver)?;
Ok(reconstructed_receiver)
}
}
pub struct ClientState {
pub shared_lane_queue_lengths: LaneQueueLengths, pub shared_lane_queue_lengths: LaneQueueLengths,
pub reply_controller_sender: ReplyControllerSender, pub received_buffer_request_sender: ReceivedBufferRequestSender,
} }
pub enum ClientInputStatus { pub enum ClientInputStatus {
@@ -103,32 +80,6 @@ impl ClientOutputStatus {
} }
} }
#[derive(Copy, Clone, PartialEq, Eq)]
pub enum CredentialsToggle {
Enabled,
Disabled,
}
impl CredentialsToggle {
pub fn is_enabled(&self) -> bool {
self == &CredentialsToggle::Enabled
}
pub fn is_disabled(&self) -> bool {
self == &CredentialsToggle::Disabled
}
}
impl From<bool> for CredentialsToggle {
fn from(value: bool) -> Self {
if value {
CredentialsToggle::Enabled
} else {
CredentialsToggle::Disabled
}
}
}
pub struct BaseClientBuilder<'a, B> { pub struct BaseClientBuilder<'a, B> {
// due to wasm limitations I had to split it like this : ( // due to wasm limitations I had to split it like this : (
gateway_config: &'a GatewayEndpointConfig, gateway_config: &'a GatewayEndpointConfig,
@@ -168,13 +119,13 @@ where
key_manager: KeyManager, key_manager: KeyManager,
bandwidth_controller: Option<BandwidthController>, bandwidth_controller: Option<BandwidthController>,
reply_storage_backend: B, reply_storage_backend: B,
credentials_toggle: CredentialsToggle, disabled_credentials: bool,
nym_api_endpoints: Vec<Url>, nym_api_endpoints: Vec<Url>,
) -> BaseClientBuilder<'a, B> { ) -> BaseClientBuilder<'a, B> {
BaseClientBuilder { BaseClientBuilder {
gateway_config, gateway_config,
debug_config, debug_config,
disabled_credentials: credentials_toggle.is_disabled(), disabled_credentials,
nym_api_endpoints, nym_api_endpoints,
reply_storage_backend, reply_storage_backend,
bandwidth_controller, bandwidth_controller,
@@ -279,7 +230,7 @@ where
mixnet_message_sender: MixnetMessageSender, mixnet_message_sender: MixnetMessageSender,
ack_sender: AcknowledgementSender, ack_sender: AcknowledgementSender,
shutdown: TaskClient, shutdown: TaskClient,
) -> Result<GatewayClient, ClientCoreError> { ) -> Result<GatewayClient, ClientCoreError<B>> {
let gateway_id = self.gateway_config.gateway_id.clone(); let gateway_id = self.gateway_config.gateway_id.clone();
if gateway_id.is_empty() { if gateway_id.is_empty() {
return Err(ClientCoreError::GatewayIdUnknown); return Err(ClientCoreError::GatewayIdUnknown);
@@ -297,7 +248,7 @@ where
.map_err(ClientCoreError::UnableToCreatePublicKeyFromGatewayId)?; .map_err(ClientCoreError::UnableToCreatePublicKeyFromGatewayId)?;
// disgusting wasm workaround since there's no key persistence there (nor `client init`) // disgusting wasm workaround since there's no key persistence there (nor `client init`)
let shared_key = if self.key_manager.is_gateway_key_set() { let shared_key = if self.key_manager.gateway_key_set() {
Some(self.key_manager.gateway_shared_key()) Some(self.key_manager.gateway_shared_key())
} else { } else {
None None
@@ -334,7 +285,7 @@ where
refresh_rate: Duration, refresh_rate: Duration,
topology_accessor: TopologyAccessor, topology_accessor: TopologyAccessor,
shutdown: TaskClient, shutdown: TaskClient,
) -> Result<(), ClientCoreError> { ) -> Result<(), ClientCoreError<B>> {
let topology_refresher_config = TopologyRefresherConfig::new( let topology_refresher_config = TopologyRefresherConfig::new(
nym_api_urls, nym_api_urls,
refresh_rate, refresh_rate,
@@ -377,17 +328,12 @@ where
async fn setup_persistent_reply_storage( async fn setup_persistent_reply_storage(
backend: B, backend: B,
shutdown: TaskClient, shutdown: TaskClient,
) -> Result<CombinedReplyStorage, ClientCoreError> ) -> Result<CombinedReplyStorage, ClientCoreError<B>> {
where
<B as ReplyStorageBackend>::StorageError: Sync + Send,
{
let persistent_storage = PersistentReplyStorage::new(backend); let persistent_storage = PersistentReplyStorage::new(backend);
let mem_store = persistent_storage let mem_store = persistent_storage
.load_state_from_backend() .load_state_from_backend()
.await .await
.map_err(|err| ClientCoreError::SurbStorageError { .map_err(|err| ClientCoreError::SurbStorageError { source: err })?;
source: Box::new(err),
})?;
let store_clone = mem_store.clone(); let store_clone = mem_store.clone();
spawn_future(async move { spawn_future(async move {
@@ -399,10 +345,7 @@ where
Ok(mem_store) Ok(mem_store)
} }
pub async fn start_base(mut self) -> Result<BaseClient, ClientCoreError> pub async fn start_base(mut self) -> Result<BaseClient, ClientCoreError<B>> {
where
<B as ReplyStorageBackend>::StorageError: Sync + Send,
{
info!("Starting nym client"); info!("Starting nym client");
// channels for inter-component communication // channels for inter-component communication
// TODO: make the channels be internally created by the relevant components // TODO: make the channels be internally created by the relevant components
@@ -428,7 +371,7 @@ where
// channels responsible for dealing with reply-related fun // channels responsible for dealing with reply-related fun
let (reply_controller_sender, reply_controller_receiver) = let (reply_controller_sender, reply_controller_receiver) =
reply_controller::requests::new_control_channels(); reply_controller::new_control_channels();
let self_address = self.as_mix_recipient(); let self_address = self.as_mix_recipient();
@@ -494,7 +437,7 @@ where
input_receiver, input_receiver,
sphinx_message_sender.clone(), sphinx_message_sender.clone(),
reply_storage, reply_storage,
reply_controller_sender.clone(), reply_controller_sender,
reply_controller_receiver, reply_controller_receiver,
shared_lane_queue_lengths.clone(), shared_lane_queue_lengths.clone(),
client_connection_rx, client_connection_rx,
@@ -524,13 +467,10 @@ where
}, },
client_output: ClientOutputStatus::AwaitingConsumer { client_output: ClientOutputStatus::AwaitingConsumer {
client_output: ClientOutput { client_output: ClientOutput {
shared_lane_queue_lengths,
received_buffer_request_sender, received_buffer_request_sender,
}, },
}, },
client_state: ClientState {
shared_lane_queue_lengths,
reply_controller_sender,
},
task_manager, task_manager,
}) })
} }
@@ -539,7 +479,6 @@ where
pub struct BaseClient { pub struct BaseClient {
pub client_input: ClientInputStatus, pub client_input: ClientInputStatus,
pub client_output: ClientOutputStatus, pub client_output: ClientOutputStatus,
pub client_state: ClientState,
pub task_manager: TaskManager, pub task_manager: TaskManager,
} }
@@ -2,7 +2,7 @@
// SPDX-License-Identifier: Apache-2.0 // SPDX-License-Identifier: Apache-2.0
use crate::client::replies::reply_storage::{ use crate::client::replies::reply_storage::{
self, fs_backend, CombinedReplyStorage, ReplyStorageBackend, fs_backend, CombinedReplyStorage, ReplyStorageBackend,
}; };
use crate::config::DebugConfig; use crate::config::DebugConfig;
use crate::error::ClientCoreError; use crate::error::ClientCoreError;
@@ -14,15 +14,13 @@ use time::OffsetDateTime;
async fn setup_fresh_backend<P: AsRef<Path>>( async fn setup_fresh_backend<P: AsRef<Path>>(
db_path: P, db_path: P,
debug_config: &DebugConfig, debug_config: &DebugConfig,
) -> Result<fs_backend::Backend, ClientCoreError> { ) -> Result<fs_backend::Backend, ClientCoreError<fs_backend::Backend>> {
info!("creating fresh surb database"); info!("creating fresh surb database");
let mut storage_backend = match fs_backend::Backend::init(db_path).await { let mut storage_backend = match fs_backend::Backend::init(db_path).await {
Ok(backend) => backend, Ok(backend) => backend,
Err(err) => { Err(err) => {
error!("failed to setup persistent storage backend for our reply needs: {err}"); error!("failed to setup persistent storage backend for our reply needs: {err}");
return Err(ClientCoreError::SurbStorageError { return Err(ClientCoreError::SurbStorageError { source: err });
source: Box::new(err),
});
} }
}; };
@@ -36,9 +34,7 @@ async fn setup_fresh_backend<P: AsRef<Path>>(
storage_backend storage_backend
.init_fresh(&mem_store) .init_fresh(&mem_store)
.await .await
.map_err(|err| ClientCoreError::SurbStorageError { .map_err(|err| ClientCoreError::SurbStorageError { source: err })?;
source: Box::new(err),
})?;
Ok(storage_backend) Ok(storage_backend)
} }
@@ -67,7 +63,7 @@ fn archive_corrupted_database<P: AsRef<Path>>(db_path: P) -> io::Result<()> {
pub async fn setup_fs_reply_surb_backend<P: AsRef<Path>>( pub async fn setup_fs_reply_surb_backend<P: AsRef<Path>>(
db_path: P, db_path: P,
debug_config: &DebugConfig, debug_config: &DebugConfig,
) -> Result<fs_backend::Backend, ClientCoreError> { ) -> Result<fs_backend::Backend, ClientCoreError<fs_backend::Backend>> {
// if the database file doesnt exist, initialise fresh storage, otherwise attempt to load the existing one // if the database file doesnt exist, initialise fresh storage, otherwise attempt to load the existing one
let db_path = db_path.as_ref(); let db_path = db_path.as_ref();
if db_path.exists() { if db_path.exists() {
@@ -85,10 +81,3 @@ pub async fn setup_fs_reply_surb_backend<P: AsRef<Path>>(
setup_fresh_backend(db_path, debug_config).await setup_fresh_backend(db_path, debug_config).await
} }
} }
pub fn setup_empty_reply_surb_backend(debug_config: &DebugConfig) -> reply_storage::Empty {
reply_storage::Empty {
min_surb_threshold: debug_config.minimum_reply_surb_storage_threshold,
max_surb_threshold: debug_config.maximum_reply_surb_storage_threshold,
}
}
@@ -1,14 +0,0 @@
// Copyright 2022 - Nym Technologies SA <contact@nymtech.net>
// SPDX-License-Identifier: Apache-2.0
#[cfg(not(target_arch = "wasm32"))]
mod non_wasm;
#[cfg(target_arch = "wasm32")]
mod wasm;
#[cfg(not(target_arch = "wasm32"))]
pub use non_wasm::*;
#[cfg(target_arch = "wasm32")]
pub use wasm::*;
@@ -1,13 +0,0 @@
// Copyright 2022 - Nym Technologies SA <contact@nymtech.net>
// SPDX-License-Identifier: Apache-2.0
pub use tokio::time::*;
pub type IntervalStream = tokio_stream::wrappers::IntervalStream;
pub(crate) fn get_time_now() -> Instant {
Instant::now()
}
pub(crate) fn new_interval_stream(polling_rate: Duration) -> IntervalStream {
tokio_stream::wrappers::IntervalStream::new(tokio::time::interval(polling_rate))
}
@@ -1,16 +0,0 @@
// Copyright 2022 - Nym Technologies SA <contact@nymtech.net>
// SPDX-License-Identifier: Apache-2.0
use std::time::Duration;
use wasm_timer;
pub use wasm_timer::*;
pub type IntervalStream = gloo_timers::future::IntervalStream;
pub(crate) fn get_time_now() -> Instant {
wasm_timer::Instant::now()
}
pub(crate) fn new_interval_stream(polling_rate: Duration) -> IntervalStream {
gloo_timers::future::IntervalStream::new(polling_rate.as_millis() as u32)
}
+24 -100
View File
@@ -17,7 +17,6 @@ use std::sync::Arc;
// use the old key after new one was issued. // use the old key after new one was issued.
// Remember that Arc<T> has Deref implementation for T // Remember that Arc<T> has Deref implementation for T
#[derive(Clone)]
pub struct KeyManager { pub struct KeyManager {
/// identity key associated with the client instance. /// identity key associated with the client instance.
identity_keypair: Arc<identity::KeyPair>, identity_keypair: Arc<identity::KeyPair>,
@@ -58,22 +57,16 @@ impl KeyManager {
} }
} }
pub fn from_keys( // this is actually **NOT** dead code
id_keypair: identity::KeyPair, // I have absolutely no idea why the compiler insists it's unused. The call happens during client::init::execute
enc_keypair: encryption::KeyPair, #[allow(dead_code)]
gateway_shared_key: SharedKeys, /// After shared key with the gateway is derived, puts its ownership to this instance of a [`KeyManager`].
ack_key: AckKey, pub fn insert_gateway_shared_key(&mut self, gateway_shared_key: Arc<SharedKeys>) {
) -> Self { self.gateway_shared_key = Some(gateway_shared_key)
Self {
identity_keypair: Arc::new(id_keypair),
encryption_keypair: Arc::new(enc_keypair),
gateway_shared_key: Some(Arc::new(gateway_shared_key)),
ack_key: Arc::new(ack_key),
}
} }
/// Loads previously stored client keys from the disk. /// Loads previously stored keys from the disk.
fn load_client_keys(client_pathfinder: &ClientKeyPathfinder) -> io::Result<Self> { pub fn load_keys(client_pathfinder: &ClientKeyPathfinder) -> io::Result<Self> {
let identity_keypair: identity::KeyPair = let identity_keypair: identity::KeyPair =
pemstore::load_keypair(&pemstore::KeyPairPath::new( pemstore::load_keypair(&pemstore::KeyPairPath::new(
client_pathfinder.private_identity_key().to_owned(), client_pathfinder.private_identity_key().to_owned(),
@@ -85,49 +78,19 @@ impl KeyManager {
client_pathfinder.public_encryption_key().to_owned(), client_pathfinder.public_encryption_key().to_owned(),
))?; ))?;
let ack_key: AckKey = pemstore::load_key(client_pathfinder.ack_key())?;
Ok(KeyManager {
identity_keypair: Arc::new(identity_keypair),
encryption_keypair: Arc::new(encryption_keypair),
gateway_shared_key: None,
ack_key: Arc::new(ack_key),
})
}
/// Loads previously stored keys from the disk. Fails if not all, including the shared gateway
/// key, is available.
pub fn load_keys(client_pathfinder: &ClientKeyPathfinder) -> io::Result<Self> {
let mut key_manager = Self::load_client_keys(client_pathfinder)?;
let gateway_shared_key: SharedKeys = let gateway_shared_key: SharedKeys =
pemstore::load_key(client_pathfinder.gateway_shared_key())?; pemstore::load_key(client_pathfinder.gateway_shared_key())?;
key_manager.gateway_shared_key = Some(Arc::new(gateway_shared_key)); let ack_key: AckKey = pemstore::load_key(client_pathfinder.ack_key())?;
Ok(key_manager) // TODO: ack key is never stored so it is generated now. But perhaps it should be stored
} // after all for consistency sake?
Ok(KeyManager {
/// Loads previously stored keys from the disk. Fails if client keys are not availabe, but the identity_keypair: Arc::new(identity_keypair),
/// shared gateway key is optional. encryption_keypair: Arc::new(encryption_keypair),
pub fn load_keys_but_gateway_is_optional( gateway_shared_key: Some(Arc::new(gateway_shared_key)),
client_pathfinder: &ClientKeyPathfinder, ack_key: Arc::new(ack_key),
) -> io::Result<Self> { })
let mut key_manager = Self::load_client_keys(client_pathfinder)?;
let gateway_shared_key: Result<SharedKeys, io::Error> =
pemstore::load_key(client_pathfinder.gateway_shared_key());
// It's ok if the gateway key was not found
let gateway_shared_key = match gateway_shared_key {
Err(err) if err.kind() == io::ErrorKind::NotFound => Ok(None),
Err(err) => Err(err),
Ok(key) => Ok(Some(key)),
}?;
key_manager.gateway_shared_key = gateway_shared_key.map(Arc::new);
Ok(key_manager)
} }
// this is actually **NOT** dead code // this is actually **NOT** dead code
@@ -156,7 +119,7 @@ impl KeyManager {
pemstore::store_key(self.ack_key.as_ref(), client_pathfinder.ack_key())?; pemstore::store_key(self.ack_key.as_ref(), client_pathfinder.ack_key())?;
match self.gateway_shared_key.as_ref() { match self.gateway_shared_key.as_ref() {
None => debug!("No gateway shared key available to store!"), None => warn!("No gateway shared key available to store!"),
Some(gate_key) => { Some(gate_key) => {
pemstore::store_key(gate_key.as_ref(), client_pathfinder.gateway_shared_key())? pemstore::store_key(gate_key.as_ref(), client_pathfinder.gateway_shared_key())?
} }
@@ -165,60 +128,16 @@ impl KeyManager {
Ok(()) Ok(())
} }
pub fn store_gateway_key(&self, client_pathfinder: &ClientKeyPathfinder) -> io::Result<()> {
match self.gateway_shared_key.as_ref() {
None => {
return Err(io::Error::new(
io::ErrorKind::Other,
"trying to store a non-existing key",
))
}
Some(gate_key) => {
pemstore::store_key(gate_key.as_ref(), client_pathfinder.gateway_shared_key())?
}
}
Ok(())
}
/// Overwrite the existing identity keypair
pub fn set_identity_keypair(&mut self, id_keypair: identity::KeyPair) {
self.identity_keypair = Arc::new(id_keypair);
}
/// Gets an atomically reference counted pointer to [`identity::KeyPair`]. /// Gets an atomically reference counted pointer to [`identity::KeyPair`].
pub fn identity_keypair(&self) -> Arc<identity::KeyPair> { pub fn identity_keypair(&self) -> Arc<identity::KeyPair> {
Arc::clone(&self.identity_keypair) Arc::clone(&self.identity_keypair)
} }
/// Overwrite the existing encryption keypair
pub fn set_encryption_keypair(&mut self, enc_keypair: encryption::KeyPair) {
self.encryption_keypair = Arc::new(enc_keypair);
}
/// Gets an atomically reference counted pointer to [`encryption::KeyPair`]. /// Gets an atomically reference counted pointer to [`encryption::KeyPair`].
pub fn encryption_keypair(&self) -> Arc<encryption::KeyPair> { pub fn encryption_keypair(&self) -> Arc<encryption::KeyPair> {
Arc::clone(&self.encryption_keypair) Arc::clone(&self.encryption_keypair)
} }
/// Overwrite the existing ack key
pub fn set_ack_key(&mut self, ack_key: AckKey) {
self.ack_key = Arc::new(ack_key);
}
/// Gets an atomically reference counted pointer to [`AckKey`].
pub fn ack_key(&self) -> Arc<AckKey> {
Arc::clone(&self.ack_key)
}
// this is actually **NOT** dead code
// I have absolutely no idea why the compiler insists it's unused. The call happens during client::init::execute
#[allow(dead_code)]
/// After shared key with the gateway is derived, puts its ownership to this instance of a [`KeyManager`].
pub fn insert_gateway_shared_key(&mut self, gateway_shared_key: Arc<SharedKeys>) {
self.gateway_shared_key = Some(gateway_shared_key)
}
/// Gets an atomically reference counted pointer to [`SharedKey`]. /// Gets an atomically reference counted pointer to [`SharedKey`].
// since this function is not fully public, it is not expected to be used externally and // since this function is not fully public, it is not expected to be used externally and
// hence it's up to us to ensure it's called in correct context // hence it's up to us to ensure it's called in correct context
@@ -230,7 +149,12 @@ impl KeyManager {
) )
} }
pub fn is_gateway_key_set(&self) -> bool { pub fn gateway_key_set(&self) -> bool {
self.gateway_shared_key.is_some() self.gateway_shared_key.is_some()
} }
/// Gets an atomically reference counted pointer to [`AckKey`].
pub fn ack_key(&self) -> Arc<AckKey> {
Arc::clone(&self.ack_key)
}
} }
-2
View File
@@ -3,7 +3,6 @@
pub mod base_client; pub mod base_client;
pub mod cover_traffic_stream; pub mod cover_traffic_stream;
pub(crate) mod helpers;
pub mod inbound_messages; pub mod inbound_messages;
pub mod key_manager; pub mod key_manager;
pub mod mix_traffic; pub mod mix_traffic;
@@ -11,4 +10,3 @@ pub mod real_messages_control;
pub mod received_buffer; pub mod received_buffer;
pub mod replies; pub mod replies;
pub mod topology_control; pub mod topology_control;
pub(crate) mod transmission_buffer;
@@ -213,11 +213,7 @@ impl ActionController {
} }
// note: when the entry expires it's automatically removed from pending_acks_timers // note: when the entry expires it's automatically removed from pending_acks_timers
fn handle_expired_ack_timer( fn handle_expired_ack_timer(&mut self, expired_ack: Expired<FragmentIdentifier>) {
&mut self,
expired_ack: Expired<FragmentIdentifier>,
task_client: &mut task::TaskClient,
) {
// I'm honestly not sure how to handle it, because getting it means other things in our // 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 // 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? // about it. Perhaps just reschedule it at later point?
@@ -235,16 +231,9 @@ impl ActionController {
// downgrading an arc and then upgrading vs cloning is difference of 30ns vs 15ns // downgrading an arc and then upgrading vs cloning is difference of 30ns vs 15ns
// so it's literally a NO difference while it might prevent us from unnecessarily // so it's literally a NO difference while it might prevent us from unnecessarily
// resending data (in maybe 1 in 1 million cases, but it's something) // resending data (in maybe 1 in 1 million cases, but it's something)
if self self.retransmission_sender
.retransmission_sender
.unbounded_send(Arc::downgrade(pending_ack_data)) .unbounded_send(Arc::downgrade(pending_ack_data))
.is_err() .unwrap()
{
assert!(
task_client.is_shutdown_poll(),
"Failed to send pending ack for retransmission"
);
}
} else { } else {
// this shouldn't cause any issues but shouldn't have happened to begin with! // this shouldn't cause any issues but shouldn't have happened to begin with!
error!("An already removed pending ack has expired") error!("An already removed pending ack has expired")
@@ -275,7 +264,7 @@ impl ActionController {
} }
}, },
expired_ack = self.pending_acks_timers.next() => match expired_ack { expired_ack = self.pending_acks_timers.next() => match expired_ack {
Some(expired_ack) => self.handle_expired_ack_timer(expired_ack, &mut shutdown), Some(expired_ack) => self.handle_expired_ack_timer(expired_ack),
None => { None => {
log::trace!("ActionController: Stopping since ack channel closed"); log::trace!("ActionController: Stopping since ack channel closed");
break; break;
@@ -286,7 +275,10 @@ impl ActionController {
} }
} }
} }
shutdown.recv_timeout().await; #[cfg(not(target_arch = "wasm32"))]
tokio::time::timeout(Duration::from_secs(5), shutdown.recv())
.await
.expect("Task stopped without shutdown called");
log::debug!("ActionController: Exiting"); log::debug!("ActionController: Exiting");
} }
} }
@@ -20,7 +20,6 @@ use nymsphinx::params::{PacketSize, DEFAULT_NUM_MIX_HOPS};
use nymsphinx::preparer::{MessagePreparer, PreparedFragment}; use nymsphinx::preparer::{MessagePreparer, PreparedFragment};
use nymsphinx::Delay; use nymsphinx::Delay;
use rand::{CryptoRng, Rng}; use rand::{CryptoRng, Rng};
use std::collections::HashMap;
use std::sync::Arc; use std::sync::Arc;
use std::time::Duration; use std::time::Duration;
use thiserror::Error; use thiserror::Error;
@@ -279,7 +278,7 @@ where
reply_surb: ReplySurb, reply_surb: ReplySurb,
amount: u32, amount: u32,
) -> Result<(), SurbWrappedPreparationError> { ) -> Result<(), SurbWrappedPreparationError> {
debug!("requesting {amount} reply SURBs from {from}"); debug!("requesting {amount} reply SURBs from {from:?}");
let surbs_request = let surbs_request =
ReplyMessage::new_surb_request_message(self.config.sender_address, amount); ReplyMessage::new_surb_request_message(self.config.sender_address, amount);
@@ -295,11 +294,19 @@ where
))) )))
} }
pub(crate) async fn send_retransmission_reply_chunks( // the only difference between this method and `try_send_reply_chunks` is that
// here we are not creating acks as acks are already in memory waiting to get cleared.
// we are only updating their existing delays
pub(crate) async fn try_send_retransmission_reply_chunks(
&mut self, &mut self,
prepared_fragments: Vec<PreparedFragment>, fragments: Vec<Fragment>,
reply_surbs: Vec<ReplySurb>,
lane: TransmissionLane, lane: TransmissionLane,
) { ) -> Result<(), SurbWrappedPreparationError> {
let prepared_fragments = self
.prepare_reply_chunks_for_sending(fragments.clone(), reply_surbs)
.await?;
let mut real_messages = Vec::with_capacity(prepared_fragments.len()); let mut real_messages = Vec::with_capacity(prepared_fragments.len());
for prepared in prepared_fragments { for prepared in prepared_fragments {
@@ -308,58 +315,33 @@ where
} }
self.forward_messages(real_messages, lane).await; self.forward_messages(real_messages, lane).await;
Ok(())
} }
pub(crate) async fn try_send_reply_chunks_on_lane( pub(crate) async fn try_send_reply_chunks(
&mut self, &mut self,
target: AnonymousSenderTag, target: AnonymousSenderTag,
fragments: Vec<Fragment>, fragments: Vec<Fragment>,
reply_surbs: Vec<ReplySurb>, reply_surbs: Vec<ReplySurb>,
lane: TransmissionLane, lane: TransmissionLane,
) -> Result<(), SurbWrappedPreparationError> {
// TODO: technically this is performing an unnecessary cloning, but in the grand scheme of things
// is it really that bad?
self.try_send_reply_chunks(
target,
fragments.into_iter().map(|f| (lane, f)).collect(),
reply_surbs,
)
.await
}
pub(crate) async fn try_send_reply_chunks(
&mut self,
target: AnonymousSenderTag,
fragments: Vec<(TransmissionLane, Fragment)>,
reply_surbs: Vec<ReplySurb>,
) -> Result<(), SurbWrappedPreparationError> { ) -> Result<(), SurbWrappedPreparationError> {
let prepared_fragments = self let prepared_fragments = self
.prepare_reply_chunks_for_sending( .prepare_reply_chunks_for_sending(fragments.clone(), reply_surbs)
fragments.iter().map(|(_, f)| f.clone()).collect(),
reply_surbs,
)
.await?; .await?;
let mut pending_acks = Vec::with_capacity(fragments.len()); let mut pending_acks = Vec::with_capacity(fragments.len());
let mut to_forward: HashMap<_, Vec<_>> = HashMap::new(); let mut real_messages = Vec::with_capacity(fragments.len());
for (raw, prepared) in fragments.into_iter().zip(prepared_fragments.into_iter()) { for (raw, prepared) in fragments.into_iter().zip(prepared_fragments.into_iter()) {
let lane = raw.0;
let fragment = raw.1;
let real_message = RealMessage::new(prepared.mix_packet, prepared.fragment_identifier); let real_message = RealMessage::new(prepared.mix_packet, prepared.fragment_identifier);
let delay = prepared.total_delay; let delay = prepared.total_delay;
let pending_ack = PendingAcknowledgement::new_anonymous(fragment, delay, target, false); let pending_ack = PendingAcknowledgement::new_anonymous(raw, delay, target, false);
let entry = to_forward.entry(lane).or_default(); real_messages.push(real_message);
entry.push(real_message);
pending_acks.push(pending_ack); pending_acks.push(pending_ack);
} }
for (lane, real_messages) in to_forward { self.forward_messages(real_messages, lane).await;
self.forward_messages(real_messages, lane).await;
}
self.insert_pending_acks(pending_acks); self.insert_pending_acks(pending_acks);
Ok(()) Ok(())
} }
@@ -485,7 +467,7 @@ where
Ok(prepared_fragment) Ok(prepared_fragment)
} }
pub(crate) async fn prepare_reply_chunks_for_sending( async fn prepare_reply_chunks_for_sending(
&mut self, &mut self,
fragments: Vec<Fragment>, fragments: Vec<Fragment>,
reply_surbs: Vec<ReplySurb>, reply_surbs: Vec<ReplySurb>,
@@ -1,11 +1,9 @@
// Copyright 2021 - Nym Technologies SA <contact@nymtech.net> // Copyright 2021 - Nym Technologies SA <contact@nymtech.net>
// SPDX-License-Identifier: Apache-2.0 // SPDX-License-Identifier: Apache-2.0
use self::sending_delay_controller::SendingDelayController;
use crate::client::mix_traffic::BatchMixMessageSender; use crate::client::mix_traffic::BatchMixMessageSender;
use crate::client::real_messages_control::acknowledgement_control::SentPacketNotificationSender; use crate::client::real_messages_control::acknowledgement_control::SentPacketNotificationSender;
use crate::client::topology_control::TopologyAccessor; use crate::client::topology_control::TopologyAccessor;
use crate::client::transmission_buffer::TransmissionBuffer;
use client_connections::{ use client_connections::{
ConnectionCommand, ConnectionCommandReceiver, ConnectionId, LaneQueueLengths, TransmissionLane, ConnectionCommand, ConnectionCommandReceiver, ConnectionId, LaneQueueLengths, TransmissionLane,
}; };
@@ -31,7 +29,22 @@ use tokio::time;
#[cfg(target_arch = "wasm32")] #[cfg(target_arch = "wasm32")]
use wasm_timer; use wasm_timer;
use self::{
sending_delay_controller::SendingDelayController, transmission_buffer::TransmissionBuffer,
};
mod sending_delay_controller; mod sending_delay_controller;
mod transmission_buffer;
#[cfg(not(target_arch = "wasm32"))]
fn get_time_now() -> time::Instant {
time::Instant::now()
}
#[cfg(target_arch = "wasm32")]
fn get_time_now() -> wasm_timer::Instant {
wasm_timer::Instant::now()
}
/// Configurable parameters of the `OutQueueControl` /// Configurable parameters of the `OutQueueControl`
pub(crate) struct Config { pub(crate) struct Config {
@@ -122,7 +135,7 @@ where
/// Buffer containing all incoming real messages keyed by transmission lane, that we will send /// Buffer containing all incoming real messages keyed by transmission lane, that we will send
/// out to the mixnet. /// out to the mixnet.
transmission_buffer: TransmissionBuffer<RealMessage>, transmission_buffer: TransmissionBuffer,
/// Incoming channel for being notified of closed connections, so that we can close lanes /// Incoming channel for being notified of closed connections, so that we can close lanes
/// corresponding to connections. To avoid sending traffic unnecessary /// corresponding to connections. To avoid sending traffic unnecessary
@@ -149,10 +162,6 @@ impl From<PreparedFragment> for RealMessage {
} }
impl RealMessage { impl RealMessage {
pub(crate) fn packet_size(&self) -> usize {
self.mix_packet.sphinx_packet().len()
}
pub(crate) fn new(mix_packet: MixPacket, fragment_id: FragmentIdentifier) -> Self { pub(crate) fn new(mix_packet: MixPacket, fragment_id: FragmentIdentifier) -> Self {
RealMessage { RealMessage {
mix_packet, mix_packet,
@@ -198,7 +207,7 @@ where
real_receiver, real_receiver,
rng, rng,
topology_access, topology_access,
transmission_buffer: TransmissionBuffer::new(), transmission_buffer: Default::default(),
client_connection_rx, client_connection_rx,
lane_queue_lengths, lane_queue_lengths,
} }
@@ -319,9 +328,7 @@ where
fn pop_next_message(&mut self) -> Option<RealMessage> { fn pop_next_message(&mut self) -> Option<RealMessage> {
// Pop the next message from the transmission buffer // Pop the next message from the transmission buffer
let (lane, real_next) = self let (lane, real_next) = self.transmission_buffer.pop_next_message_at_random()?;
.transmission_buffer
.pop_next_message_at_random(&mut self.rng)?;
// Update the published queue length // Update the published queue length
let lane_length = self.transmission_buffer.lane_length(&lane); let lane_length = self.transmission_buffer.lane_length(&lane);
@@ -535,7 +542,9 @@ where
} }
} }
} }
shutdown.recv_timeout().await; tokio::time::timeout(Duration::from_secs(5), shutdown.recv())
.await
.expect("Task stopped without shutdown called");
} }
#[cfg(target_arch = "wasm32")] #[cfg(target_arch = "wasm32")]
@@ -1,9 +1,14 @@
// Copyright 2021 - Nym Technologies SA <contact@nymtech.net> // Copyright 2021 - Nym Technologies SA <contact@nymtech.net>
// SPDX-License-Identifier: Apache-2.0 // SPDX-License-Identifier: Apache-2.0
use crate::client::helpers::{get_time_now, Instant}; use super::get_time_now;
use std::time::Duration; use std::time::Duration;
#[cfg(not(target_arch = "wasm32"))]
use tokio::time;
#[cfg(target_arch = "wasm32")]
use wasm_timer;
// The minimum time between increasing the average delay between packets. If we hit the ceiling in // The minimum time between increasing the average delay between packets. If we hit the ceiling in
// the available buffer space we want to take somewhat swift action, but we still need to give a // the available buffer space we want to take somewhat swift action, but we still need to give a
// short time to give the channel a chance reduce pressure. // short time to give the channel a chance reduce pressure.
@@ -34,11 +39,19 @@ pub(crate) struct SendingDelayController {
lower_bound: u32, lower_bound: u32,
/// To make sure we don't change the multiplier to fast, we limit a change to some duration /// To make sure we don't change the multiplier to fast, we limit a change to some duration
time_when_changed: Instant, #[cfg(not(target_arch = "wasm32"))]
time_when_changed: time::Instant,
#[cfg(target_arch = "wasm32")]
time_when_changed: wasm_timer::Instant,
/// If we have a long enough time without any backpressure detected we try reducing the sending /// If we have a long enough time without any backpressure detected we try reducing the sending
/// delay multiplier /// delay multiplier
time_when_backpressure_detected: Instant, #[cfg(not(target_arch = "wasm32"))]
time_when_backpressure_detected: time::Instant,
#[cfg(target_arch = "wasm32")]
time_when_backpressure_detected: wasm_timer::Instant,
} }
impl Default for SendingDelayController { impl Default for SendingDelayController {
@@ -1,57 +1,38 @@
// Copyright 2022 - Nym Technologies SA <contact@nymtech.net> // Copyright 2022 - Nym Technologies SA <contact@nymtech.net>
// SPDX-License-Identifier: Apache-2.0 // SPDX-License-Identifier: Apache-2.0
use crate::client::helpers::{get_time_now, Instant};
use crate::client::real_messages_control::real_traffic_stream::RealMessage;
use client_connections::TransmissionLane; use client_connections::TransmissionLane;
use nymsphinx::chunking::fragment::Fragment;
use rand::{seq::SliceRandom, Rng}; use rand::{seq::SliceRandom, Rng};
use std::{ use std::{
collections::{HashMap, HashSet, VecDeque}, collections::{HashMap, HashSet, VecDeque},
time::Duration, time::Duration,
}; };
#[cfg(not(target_arch = "wasm32"))]
use tokio::time;
#[cfg(target_arch = "wasm32")]
use wasm_timer;
use super::{get_time_now, RealMessage};
// The number of lanes included in the oldest set. Used when we need to prioritize traffic. // The number of lanes included in the oldest set. Used when we need to prioritize traffic.
const OLDEST_LANE_SET_SIZE: usize = 4; const OLDEST_LANE_SET_SIZE: usize = 4;
// As a way of prune connections we also check for timeouts. // As a way of prune connections we also check for timeouts.
const MSG_CONSIDERED_STALE_AFTER_SECS: u64 = 10 * 60; const MSG_CONSIDERED_STALE_AFTER_SECS: u64 = 10 * 60;
pub(crate) trait SizedData {
fn data_size(&self) -> usize;
}
impl SizedData for RealMessage {
fn data_size(&self) -> usize {
self.packet_size()
}
}
impl SizedData for Fragment {
fn data_size(&self) -> usize {
// note that raw `Fragment` is smaller than sphinx packet payload
// as it doesn't include surb-ack or the [shared] key materials
self.payload_size()
}
}
#[derive(Default)] #[derive(Default)]
pub(crate) struct TransmissionBuffer<T> { pub(crate) struct TransmissionBuffer {
buffer: HashMap<TransmissionLane, LaneBufferEntry<T>>, buffer: HashMap<TransmissionLane, LaneBufferEntry>,
} }
impl<T> TransmissionBuffer<T> { impl TransmissionBuffer {
pub(crate) fn new() -> Self {
TransmissionBuffer {
buffer: HashMap::new(),
}
}
#[allow(unused)] #[allow(unused)]
pub(crate) fn is_empty(&self) -> bool { pub(crate) fn is_empty(&self) -> bool {
self.buffer.is_empty() self.buffer.is_empty()
} }
pub(crate) fn remove(&mut self, lane: &TransmissionLane) -> Option<LaneBufferEntry<T>> { pub(crate) fn remove(&mut self, lane: &TransmissionLane) -> Option<LaneBufferEntry> {
self.buffer.remove(lane) self.buffer.remove(lane)
} }
@@ -76,22 +57,20 @@ impl<T> TransmissionBuffer<T> {
.collect() .collect()
} }
#[cfg(not(target_arch = "wasm32"))]
pub(crate) fn total_size(&self) -> usize { pub(crate) fn total_size(&self) -> usize {
self.buffer.values().map(LaneBufferEntry::len).sum() self.buffer.values().map(LaneBufferEntry::len).sum()
} }
#[cfg(not(target_arch = "wasm32"))] #[cfg(not(target_arch = "wasm32"))]
pub(crate) fn total_size_in_bytes(&self) -> usize pub(crate) fn total_size_in_bytes(&self) -> usize {
where
T: SizedData,
{
self.buffer self.buffer
.values() .values()
.map(|lane_buffer_entry| { .map(|lane_buffer_entry| {
lane_buffer_entry lane_buffer_entry
.items .real_messages
.iter() .iter()
.map(|item| item.data_size()) .map(|real_message| real_message.mix_packet.sphinx_packet().len())
.sum::<usize>() .sum::<usize>()
}) })
.sum() .sum()
@@ -113,51 +92,42 @@ impl<T> TransmissionBuffer<T> {
.collect() .collect()
} }
pub(crate) fn store<I: IntoIterator<Item = T>>(&mut self, lane: &TransmissionLane, items: I) { pub(crate) fn store(&mut self, lane: &TransmissionLane, real_messages: Vec<RealMessage>) {
if let Some(lane_buffer_entry) = self.buffer.get_mut(lane) { if let Some(lane_buffer_entry) = self.buffer.get_mut(lane) {
lane_buffer_entry.extend(items); lane_buffer_entry.append(real_messages);
} else { } else {
self.buffer self.buffer
.insert(*lane, LaneBufferEntry::new(items.into_iter().collect())); .insert(*lane, LaneBufferEntry::new(real_messages));
} }
} }
pub(crate) fn store_multiple(&mut self, items: Vec<(TransmissionLane, T)>) { fn pick_random_lane(&self) -> Option<&TransmissionLane> {
for (lane, item) in items {
self.buffer
.entry(lane)
.or_insert_with(LaneBufferEntry::new_empty)
.push_item(item)
}
}
fn pick_random_lane<R: Rng + ?Sized>(&self, rng: &mut R) -> Option<&TransmissionLane> {
let lanes: Vec<&TransmissionLane> = self.buffer.keys().collect(); let lanes: Vec<&TransmissionLane> = self.buffer.keys().collect();
lanes.choose(rng).copied() lanes.choose(&mut rand::thread_rng()).copied()
} }
fn pick_random_small_lane<R: Rng + ?Sized>(&self, rng: &mut R) -> Option<&TransmissionLane> { fn pick_random_small_lane(&self) -> Option<&TransmissionLane> {
let lanes: Vec<&TransmissionLane> = self let lanes: Vec<&TransmissionLane> = self
.buffer .buffer
.iter() .iter()
.filter(|(_, v)| v.is_small()) .filter(|(_, v)| v.is_small())
.map(|(k, _)| k) .map(|(k, _)| k)
.collect(); .collect();
lanes.choose(rng).copied() lanes.choose(&mut rand::thread_rng()).copied()
} }
// 2/3 chance to pick from the old lanes // 2/3 chance to pick from the old lanes
fn pick_random_old_lane<R: Rng + ?Sized>(&self, rng: &mut R) -> Option<TransmissionLane> { fn pick_random_old_lane(&self) -> Option<TransmissionLane> {
let rand = &mut rand::thread_rng(); let rand = &mut rand::thread_rng();
if rand.gen_ratio(2, 3) { if rand.gen_ratio(2, 3) {
let lanes = self.get_oldest_set(); let lanes = self.get_oldest_set();
lanes.choose(rand).copied() lanes.choose(rand).copied()
} else { } else {
self.pick_random_lane(rng).copied() self.pick_random_lane().copied()
} }
} }
fn pop_front_from_lane(&mut self, lane: &TransmissionLane) -> Option<T> { fn pop_front_from_lane(&mut self, lane: &TransmissionLane) -> Option<RealMessage> {
let real_msgs_queued = self.buffer.get_mut(lane)?; let real_msgs_queued = self.buffer.get_mut(lane)?;
let real_next = real_msgs_queued.pop_front()?; let real_next = real_msgs_queued.pop_front()?;
real_msgs_queued.messages_transmitted += 1; real_msgs_queued.messages_transmitted += 1;
@@ -167,48 +137,19 @@ impl<T> TransmissionBuffer<T> {
Some(real_next) Some(real_next)
} }
pub(crate) fn pop_at_most_n_next_messages_at_random( pub(crate) fn pop_next_message_at_random(&mut self) -> Option<(TransmissionLane, RealMessage)> {
&mut self,
n: usize,
) -> Option<Vec<(TransmissionLane, T)>> {
// let start = Instant::now();
if self.buffer.is_empty() {
return None;
}
let rng = &mut rand::thread_rng();
let mut items = Vec::with_capacity(n);
while items.len() < n {
let Some(next) = self.pop_next_message_at_random(rng) else {
break
};
items.push(next)
}
// todo!("time time taken");
Some(items)
}
pub(crate) fn pop_next_message_at_random<R: Rng + ?Sized>(
&mut self,
// turns out the caller always have access to some rng, so no point in instantiating new one
rng: &mut R,
) -> Option<(TransmissionLane, T)> {
if self.buffer.is_empty() { if self.buffer.is_empty() {
return None; return None;
} }
// Very basic heuristic where we prioritize according to small lanes first, the older lanes // Very basic heuristic where we prioritize according to small lanes first, the older lanes
// to try to finish lanes when possible, then the rest. // to try to finish lanes when possible, then the rest.
let lane = if let Some(small_lane) = self.pick_random_small_lane(rng) { let lane = if let Some(small_lane) = self.pick_random_small_lane() {
*small_lane *small_lane
} else if let Some(old_lane) = self.pick_random_old_lane(rng) { } else if let Some(old_lane) = self.pick_random_old_lane() {
old_lane old_lane
} else { } else {
*self.pick_random_lane(rng)? *self.pick_random_lane()?
}; };
let msg = self.pop_front_from_lane(&lane)?; let msg = self.pop_front_from_lane(&lane)?;
@@ -230,46 +171,35 @@ impl<T> TransmissionBuffer<T> {
} }
} }
pub(crate) struct LaneBufferEntry<T> { pub(crate) struct LaneBufferEntry {
pub items: VecDeque<T>, pub real_messages: VecDeque<RealMessage>,
pub messages_transmitted: usize, pub messages_transmitted: usize,
pub time_for_last_activity: Instant, #[cfg(not(target_arch = "wasm32"))]
pub time_for_last_activity: time::Instant,
#[cfg(target_arch = "wasm32")]
pub time_for_last_activity: wasm_timer::Instant,
} }
impl<T> LaneBufferEntry<T> { impl LaneBufferEntry {
fn new_empty() -> Self { fn new(real_messages: Vec<RealMessage>) -> Self {
LaneBufferEntry { LaneBufferEntry {
items: VecDeque::new(), real_messages: real_messages.into(),
messages_transmitted: 0, messages_transmitted: 0,
time_for_last_activity: get_time_now(), time_for_last_activity: get_time_now(),
} }
} }
fn new(items: VecDeque<T>) -> Self { fn append(&mut self, real_messages: Vec<RealMessage>) {
LaneBufferEntry { self.real_messages.append(&mut real_messages.into());
items,
messages_transmitted: 0,
time_for_last_activity: get_time_now(),
}
}
fn push_item(&mut self, item: T) {
self.items.push_back(item);
// I'm not updating time here on purpose. This method is called just after `new_empty`,
// where the time is already set. Furthermore, this method is called there multiple times at once
}
fn extend<I: IntoIterator<Item = T>>(&mut self, items: I) {
self.items.extend(items);
self.time_for_last_activity = get_time_now(); self.time_for_last_activity = get_time_now();
} }
fn pop_front(&mut self) -> Option<T> { fn pop_front(&mut self) -> Option<RealMessage> {
self.items.pop_front() self.real_messages.pop_front()
} }
fn is_small(&self) -> bool { fn is_small(&self) -> bool {
self.items.len() < 100 self.real_messages.len() < 100
} }
fn is_stale(&self) -> bool { fn is_stale(&self) -> bool {
@@ -278,10 +208,10 @@ impl<T> LaneBufferEntry<T> {
} }
fn len(&self) -> usize { fn len(&self) -> usize {
self.items.len() self.real_messages.len()
} }
fn is_empty(&self) -> bool { fn is_empty(&self) -> bool {
self.items.is_empty() self.real_messages.is_empty()
} }
} }
@@ -4,8 +4,8 @@
use crate::client::real_messages_control::acknowledgement_control::PendingAcknowledgement; use crate::client::real_messages_control::acknowledgement_control::PendingAcknowledgement;
use crate::client::real_messages_control::message_handler::{MessageHandler, PreparationError}; use crate::client::real_messages_control::message_handler::{MessageHandler, PreparationError};
use crate::client::replies::reply_storage::CombinedReplyStorage; use crate::client::replies::reply_storage::CombinedReplyStorage;
use client_connections::{ConnectionId, TransmissionLane}; use client_connections::TransmissionLane;
use futures::channel::oneshot; use futures::channel::mpsc;
use futures::StreamExt; use futures::StreamExt;
use log::{debug, error, info, trace, warn}; use log::{debug, error, info, trace, warn};
use nymsphinx::addressing::clients::Recipient; use nymsphinx::addressing::clients::Recipient;
@@ -15,16 +15,116 @@ use nymsphinx::chunking::fragment::{Fragment, FragmentIdentifier};
use rand::{CryptoRng, Rng}; use rand::{CryptoRng, Rng};
use std::cmp::{max, min}; use std::cmp::{max, min};
use std::collections::btree_map::Entry; use std::collections::btree_map::Entry;
use std::collections::{BTreeMap, HashMap}; use std::collections::{BTreeMap, HashMap, VecDeque};
use std::sync::{Arc, Weak}; use std::sync::{Arc, Weak};
use std::time::Duration; use std::time::Duration;
use time::OffsetDateTime; use time::OffsetDateTime;
use crate::client::helpers::new_interval_stream; #[cfg(not(target_arch = "wasm32"))]
use crate::client::transmission_buffer::TransmissionBuffer; type IntervalStream = tokio_stream::wrappers::IntervalStream;
pub(crate) use requests::{ReplyControllerMessage, ReplyControllerReceiver, ReplyControllerSender};
pub mod requests; #[cfg(target_arch = "wasm32")]
type IntervalStream = gloo_timers::future::IntervalStream;
pub(crate) fn new_control_channels() -> (ReplyControllerSender, ReplyControllerReceiver) {
let (tx, rx) = mpsc::unbounded();
(tx.into(), rx)
}
#[derive(Debug, Clone)]
pub(crate) struct ReplyControllerSender(mpsc::UnboundedSender<ReplyControllerMessage>);
impl From<mpsc::UnboundedSender<ReplyControllerMessage>> for ReplyControllerSender {
fn from(inner: mpsc::UnboundedSender<ReplyControllerMessage>) -> Self {
ReplyControllerSender(inner)
}
}
impl ReplyControllerSender {
pub(crate) fn send_retransmission_data(
&self,
recipient: AnonymousSenderTag,
timed_out_ack: Weak<PendingAcknowledgement>,
extra_surb_request: bool,
) {
self.0
.unbounded_send(ReplyControllerMessage::RetransmitReply {
recipient,
timed_out_ack,
extra_surb_request,
})
.expect("ReplyControllerReceiver has died!")
}
pub(crate) fn send_reply(
&self,
recipient: AnonymousSenderTag,
message: Vec<u8>,
lane: TransmissionLane,
) {
self.0
.unbounded_send(ReplyControllerMessage::SendReply {
recipient,
message,
lane,
})
.expect("ReplyControllerReceiver has died!")
}
pub(crate) fn send_additional_surbs(
&self,
sender_tag: AnonymousSenderTag,
reply_surbs: Vec<ReplySurb>,
from_surb_request: bool,
) {
self.0
.unbounded_send(ReplyControllerMessage::AdditionalSurbs {
sender_tag,
reply_surbs,
from_surb_request,
})
.expect("ReplyControllerReceiver has died!")
}
pub(crate) fn send_additional_surbs_request(&self, recipient: Recipient, amount: u32) {
self.0
.unbounded_send(ReplyControllerMessage::AdditionalSurbsRequest {
recipient: Box::new(recipient),
amount,
})
.expect("ReplyControllerReceiver has died!")
}
}
pub(crate) type ReplyControllerReceiver = mpsc::UnboundedReceiver<ReplyControllerMessage>;
#[derive(Debug)]
pub(crate) enum ReplyControllerMessage {
RetransmitReply {
recipient: AnonymousSenderTag,
timed_out_ack: Weak<PendingAcknowledgement>,
extra_surb_request: bool,
},
SendReply {
recipient: AnonymousSenderTag,
message: Vec<u8>,
lane: TransmissionLane,
},
AdditionalSurbs {
sender_tag: AnonymousSenderTag,
reply_surbs: Vec<ReplySurb>,
from_surb_request: bool,
},
// Should this also be handled in here? it's technically a completely different side of the pipe
// let's see how it works when combined, might split it before creating PR
AdditionalSurbsRequest {
recipient: Box<Recipient>,
amount: u32,
},
}
pub struct Config { pub struct Config {
min_surb_request_size: u32, min_surb_request_size: u32,
@@ -72,7 +172,7 @@ pub struct ReplyController<R> {
// of surbs required to send the message through // of surbs required to send the message through
// expected_reliability: f32, // expected_reliability: f32,
request_receiver: ReplyControllerReceiver, request_receiver: ReplyControllerReceiver,
pending_replies: HashMap<AnonymousSenderTag, TransmissionBuffer<Fragment>>, pending_replies: HashMap<AnonymousSenderTag, VecDeque<Fragment>>,
/// Retransmission packets that have already timed out and are waiting for additional reply SURBs /// Retransmission packets that have already timed out and are waiting for additional reply SURBs
/// so that they could be sent back to the network. Once we receive more SURBs, we should send them ASAP. /// so that they could be sent back to the network. Once we receive more SURBs, we should send them ASAP.
@@ -104,28 +204,17 @@ where
} }
} }
fn insert_pending_replies<I: IntoIterator<Item = Fragment>>( /// Inserts the pending replies into the BACK of the queue fn insert_pending_replies<V: Into<VecDeque<Fragment>>>(
fn insert_pending_replies<V: Into<VecDeque<Fragment>>>(
&mut self, &mut self,
recipient: &AnonymousSenderTag, recipient: &AnonymousSenderTag,
fragments: I, fragments: V,
lane: TransmissionLane,
) { ) {
self.pending_replies if let Some(existing) = self.pending_replies.get_mut(recipient) {
.entry(*recipient) existing.append(&mut fragments.into())
.or_insert_with(TransmissionBuffer::new) } else {
.store(&lane, fragments) self.pending_replies.insert(*recipient, fragments.into());
} }
fn re_insert_pending_replies(
&mut self,
recipient: &AnonymousSenderTag,
fragments: Vec<(TransmissionLane, Fragment)>,
) {
// the buffer should ALWAYS exist at this point, if it doesn't, it's a bug...
self.pending_replies
.entry(*recipient)
.or_insert_with(TransmissionBuffer::new)
.store_multiple(fragments)
} }
fn re_insert_pending_retransmission( fn re_insert_pending_retransmission(
@@ -155,7 +244,7 @@ where
let pending_queue_size = self let pending_queue_size = self
.pending_replies .pending_replies
.get(target) .get(target)
.map(|pending_queue| pending_queue.total_size()) .map(|pending_queue| pending_queue.len())
.unwrap_or_default(); .unwrap_or_default();
let retransmission_queue = self let retransmission_queue = self
@@ -210,61 +299,42 @@ where
} }
trace!("handling reply to {:?}", recipient_tag); trace!("handling reply to {:?}", recipient_tag);
let mut fragments = self.message_handler.split_reply_message(data); let fragments = self.message_handler.split_reply_message(data);
let total_size = fragments.len();
trace!("This reply requires {:?} SURBs", total_size);
let available_surbs = self let required_surbs = fragments.len();
trace!("This reply requires {:?} SURBs", required_surbs);
// TODO: edge case:
// we're making a lot of requests and have to request a lot of surbs
// (but at some point we run out of surbs for surb requests)
let (surbs, _surbs_left) = self
.full_reply_storage .full_reply_storage
.surbs_storage_ref() .surbs_storage_ref()
.available_surbs(&recipient_tag); .get_reply_surbs(&recipient_tag, required_surbs);
let min_surbs_threshold = self
.full_reply_storage
.surbs_storage_ref()
.min_surb_threshold();
let max_to_send = if available_surbs > min_surbs_threshold { if let Some(reply_surbs) = surbs {
min(fragments.len(), available_surbs - min_surbs_threshold) if let Err(err) = self
} else { .message_handler
0 .try_send_reply_chunks(recipient_tag, fragments, reply_surbs, lane)
}; .await
{
let err = err.return_unused_surbs(
self.full_reply_storage.surbs_storage_ref(),
&recipient_tag,
);
warn!("failed to send reply to {:?} - {err}", recipient_tag);
if max_to_send > 0 { // TODO: should we buffer that data to try again?
let (surbs, _surbs_left) = self
.full_reply_storage
.surbs_storage_ref()
.get_reply_surbs(&recipient_tag, max_to_send);
if let Some(reply_surbs) = surbs {
let to_send = fragments.drain(..max_to_send).collect::<Vec<_>>();
if let Err(err) = self
.message_handler
.try_send_reply_chunks_on_lane(
recipient_tag,
to_send.clone(),
reply_surbs,
lane,
)
.await
{
let err = err.return_unused_surbs(
self.full_reply_storage.surbs_storage_ref(),
&recipient_tag,
);
warn!("failed to send reply to {recipient_tag}: {err}");
self.insert_pending_replies(&recipient_tag, to_send, lane);
}
} }
} } else {
// we don't have enough surbs for this reply
self.insert_pending_replies(&recipient_tag, fragments);
// if there's leftover data we didn't send because we didn't have enough (or any) surbs - buffer it if self.should_request_more_surbs(&recipient_tag) {
if !fragments.is_empty() { self.request_reply_surbs_for_queue_clearing(recipient_tag)
self.insert_pending_replies(&recipient_tag, fragments, lane); .await;
} }
if self.should_request_more_surbs(&recipient_tag) {
self.request_reply_surbs_for_queue_clearing(recipient_tag)
.await;
} }
} }
@@ -328,18 +398,35 @@ where
}; };
let mut to_take = Vec::new(); let mut to_take = Vec::new();
let mut to_remove = Vec::new();
while to_take.len() < max_to_clear { // TODO: once rust 1.66.0 is stabilised on 15.12.22, just change it to
if let Some((_, data)) = pending.pop_first() { // `.pop_front()` to directly take ownership
// no need to do anything if we failed to upgrade the reference, for (k, data) in pending.iter() {
// it means we got the ack while the data was waiting in the queue let upgraded = match data.upgrade() {
if let Some(upgraded) = data.upgrade() { Some(upgraded) => upgraded,
to_take.push(upgraded) None => {
// we got the ack while the data was waiting in the queue
to_remove.push(*k);
continue;
} }
} else { };
// our map is empty!
to_take.push(upgraded);
// we have taken as many entries as we could have
if to_take.len() >= max_to_clear {
break; break;
} }
// TODO: use if upgraded.is_extra_surb_request() to bypass the limit
}
for ack in &to_take {
pending.remove(&ack.inner_fragment_identifier());
}
for id in to_remove {
pending.remove(&id);
} }
if to_take.is_empty() { if to_take.is_empty() {
@@ -360,47 +447,46 @@ where
let to_send_vec = to_take.iter().map(|ack| ack.fragment_data()).collect(); let to_send_vec = to_take.iter().map(|ack| ack.fragment_data()).collect();
let prepared_fragments = match self if let Err(err) = self
.message_handler .message_handler
.prepare_reply_chunks_for_sending(to_send_vec, surbs_for_reply) .try_send_retransmission_reply_chunks(
to_send_vec,
surbs_for_reply,
TransmissionLane::Retransmission,
)
.await .await
{ {
Ok(prepared) => prepared, let err = err.return_unused_surbs(self.full_reply_storage.surbs_storage_ref(), &target);
Err(err) => { self.re_insert_pending_retransmission(&target, to_take);
let err =
err.return_unused_surbs(self.full_reply_storage.surbs_storage_ref(), &target);
self.re_insert_pending_retransmission(&target, to_take);
warn!( warn!(
"failed to clear pending retransmission queue for {:?} - {err}", "failed to clear pending retransmission queue for {:?} - {err}",
target target
); );
return; }
}
};
// we can't fail at this point, so drop all references to acks so that timer updates wouldn't blow up
drop(to_take);
self.message_handler
.send_retransmission_reply_chunks(prepared_fragments, TransmissionLane::Retransmission)
.await;
} }
fn pop_at_most_pending_replies( fn pop_at_most_pending_replies(
&mut self, &mut self,
from: &AnonymousSenderTag, from: &AnonymousSenderTag,
amount: usize, amount: usize,
) -> Option<Vec<(TransmissionLane, Fragment)>> { ) -> Option<VecDeque<Fragment>> {
// if possible, pop all pending replies, if not, pop only entries for which we'd have a reply surb // if possible, pop all pending replies, if not, pop only entries for which we'd have a reply surb
let total = self.pending_replies.get(from)?.total_size(); let total = self.pending_replies.get(from)?.len();
trace!("pending queue has {total} elements"); trace!("pending queue has {total} elements");
if total == 0 { if total == 0 {
return None; return None;
} }
self.pending_replies if total < amount {
.get_mut(from)? self.pending_replies.remove(from)
.pop_at_most_n_next_messages_at_random(amount) } else {
Some(
self.pending_replies
.get_mut(from)?
.drain(..amount)
.collect(),
)
}
} }
async fn try_clear_pending_queue(&mut self, target: AnonymousSenderTag) { async fn try_clear_pending_queue(&mut self, target: AnonymousSenderTag) {
@@ -424,9 +510,9 @@ where
// we're guaranteed to not get more entries than we have reply surbs for // we're guaranteed to not get more entries than we have reply surbs for
if let Some(to_send) = self.pop_at_most_pending_replies(&target, max_to_clear) { if let Some(to_send) = self.pop_at_most_pending_replies(&target, max_to_clear) {
let to_send_clone = to_send.clone(); let to_send_vec = to_send.iter().cloned().collect::<Vec<_>>();
if to_send_clone.is_empty() { if to_send_vec.is_empty() {
panic!( panic!(
"please let the devs know if you ever see this message (reply_controller.rs)" "please let the devs know if you ever see this message (reply_controller.rs)"
); );
@@ -435,22 +521,27 @@ where
let (surbs_for_reply, _) = self let (surbs_for_reply, _) = self
.full_reply_storage .full_reply_storage
.surbs_storage_ref() .surbs_storage_ref()
.get_reply_surbs(&target, to_send_clone.len()); .get_reply_surbs(&target, to_send_vec.len());
let Some(surbs_for_reply) = surbs_for_reply else { let Some(surbs_for_reply) = surbs_for_reply else {
error!("somehow different task has stolen our reply surbs! - this should have been impossible"); error!("somehow different task has stolen our reply surbs! - this should have been impossible");
self.re_insert_pending_replies(&target, to_send); self.insert_pending_replies(&target, to_send);
return; return;
}; };
if let Err(err) = self if let Err(err) = self
.message_handler .message_handler
.try_send_reply_chunks(target, to_send_clone, surbs_for_reply) .try_send_reply_chunks(
target,
to_send_vec,
surbs_for_reply,
TransmissionLane::General,
)
.await .await
{ {
let err = let err =
err.return_unused_surbs(self.full_reply_storage.surbs_storage_ref(), &target); err.return_unused_surbs(self.full_reply_storage.surbs_storage_ref(), &target);
self.re_insert_pending_replies(&target, to_send); self.insert_pending_replies(&target, to_send);
warn!("failed to clear pending queue for {:?} - {err}", target); warn!("failed to clear pending queue for {:?} - {err}", target);
} }
} else { } else {
@@ -621,30 +712,6 @@ where
} }
} }
// to be honest this doesn't make a lot of sense in the context of `connection_id`,
// it should really be asked per tag
fn handle_lane_queue_length(
&self,
connection_id: ConnectionId,
response_channel: oneshot::Sender<usize>,
) {
// TODO: if we ever have duplicate ids for different senders, it means our rng is super weak
// thus I don't think we have to worry about it?
let lane = TransmissionLane::ConnectionId(connection_id);
for buf in self.pending_replies.values() {
if let Some(length) = buf.lane_length(&lane) {
if response_channel.send(length).is_err() {
error!("the requester for lane queue length has dropped the response channel!")
}
return;
}
}
// make sure that if we didn't find that lane, we reply with 0
if response_channel.send(0).is_err() {
error!("the requester for lane queue length has dropped the response channel!")
}
}
async fn handle_request(&mut self, request: ReplyControllerMessage) { async fn handle_request(&mut self, request: ReplyControllerMessage) {
match request { match request {
ReplyControllerMessage::RetransmitReply { ReplyControllerMessage::RetransmitReply {
@@ -668,26 +735,19 @@ where
self.handle_received_surbs(sender_tag, reply_surbs, from_surb_request) self.handle_received_surbs(sender_tag, reply_surbs, from_surb_request)
.await .await
} }
ReplyControllerMessage::LaneQueueLength {
connection_id,
response_channel,
} => self.handle_lane_queue_length(connection_id, response_channel),
ReplyControllerMessage::AdditionalSurbsRequest { recipient, amount } => { ReplyControllerMessage::AdditionalSurbsRequest { recipient, amount } => {
self.handle_surb_request(*recipient, amount).await self.handle_surb_request(*recipient, amount).await
} }
} }
} }
// TODO: modify this method to more accurately determine the amount of surbs it needs to request
// it should take into consideration the average latency, sending rate and queue size.
// it should request as many surbs as it takes to saturate its sending rate before next batch arrives
async fn request_reply_surbs_for_queue_clearing(&mut self, target: AnonymousSenderTag) { async fn request_reply_surbs_for_queue_clearing(&mut self, target: AnonymousSenderTag) {
trace!("requesting surbs for queues clearing"); trace!("requesting surbs for queues clearing");
let pending_queue_size = self let pending_queue_size = self
.pending_replies .pending_replies
.get(&target) .get(&target)
.map(|pending_queue| pending_queue.total_size()) .map(|pending_queue| pending_queue.len())
.unwrap_or_default(); .unwrap_or_default();
let retransmission_queue = self let retransmission_queue = self
@@ -727,7 +787,7 @@ where
} }
let Some(last_received) = self.full_reply_storage.surbs_storage_ref().surbs_last_received_at(pending_reply_target) else { let Some(last_received) = self.full_reply_storage.surbs_storage_ref().surbs_last_received_at(pending_reply_target) else {
error!("we have {} pending replies for {pending_reply_target}, but we somehow never received any reply surbs from them!", vals.total_size()); error!("we have {} pending replies for {pending_reply_target}, but we somehow never received any reply surbs from them!", vals.len());
to_remove.push(*pending_reply_target); to_remove.push(*pending_reply_target);
continue; continue;
}; };
@@ -823,20 +883,23 @@ where
} }
} }
// #[cfg(not(target_arch = "wasm32"))] fn create_interval_stream(polling_rate: Duration) -> IntervalStream {
// async fn log_status(&self) { #[cfg(not(target_arch = "wasm32"))]
// todo!() return tokio_stream::wrappers::IntervalStream::new(tokio::time::interval(polling_rate));
// }
#[cfg(target_arch = "wasm32")]
return gloo_timers::future::IntervalStream::new(polling_rate.as_millis() as u32);
}
pub(crate) async fn run_with_shutdown(&mut self, mut shutdown: task::TaskClient) { pub(crate) async fn run_with_shutdown(&mut self, mut shutdown: task::TaskClient) {
debug!("Started ReplyController with graceful shutdown support"); debug!("Started ReplyController with graceful shutdown support");
let polling_rate = Duration::from_secs(5); let polling_rate = Duration::from_secs(5);
let mut stale_inspection = new_interval_stream(polling_rate); let mut stale_inspection = Self::create_interval_stream(polling_rate);
// this is in the order of hours/days so we don't have to poll it that often // this is in the order of hours/days so we don't have to poll it that often
let polling_rate = Duration::from_secs(self.config.max_reply_surb_age.as_secs() / 10); let polling_rate = Duration::from_secs(self.config.max_reply_surb_age.as_secs() / 10);
let mut invalidation_inspection = new_interval_stream(polling_rate); let mut invalidation_inspection = Self::create_interval_stream(polling_rate);
while !shutdown.is_shutdown() { while !shutdown.is_shutdown() {
tokio::select! { tokio::select! {
@@ -1,154 +0,0 @@
// Copyright 2022 - Nym Technologies SA <contact@nymtech.net>
// SPDX-License-Identifier: Apache-2.0
use crate::client::real_messages_control::acknowledgement_control::PendingAcknowledgement;
use client_connections::{ConnectionId, TransmissionLane};
use futures::channel::{mpsc, oneshot};
use log::error;
use nymsphinx::addressing::clients::Recipient;
use nymsphinx::anonymous_replies::requests::AnonymousSenderTag;
use nymsphinx::anonymous_replies::ReplySurb;
use std::sync::Weak;
pub(crate) fn new_control_channels() -> (ReplyControllerSender, ReplyControllerReceiver) {
let (tx, rx) = mpsc::unbounded();
(tx.into(), rx)
}
#[derive(Debug, Clone)]
pub struct ReplyControllerSender(mpsc::UnboundedSender<ReplyControllerMessage>);
impl From<mpsc::UnboundedSender<ReplyControllerMessage>> for ReplyControllerSender {
fn from(inner: mpsc::UnboundedSender<ReplyControllerMessage>) -> Self {
ReplyControllerSender(inner)
}
}
impl ReplyControllerSender {
pub(crate) fn send_retransmission_data(
&self,
recipient: AnonymousSenderTag,
timed_out_ack: Weak<PendingAcknowledgement>,
extra_surb_request: bool,
) {
self.0
.unbounded_send(ReplyControllerMessage::RetransmitReply {
recipient,
timed_out_ack,
extra_surb_request,
})
.expect("ReplyControllerReceiver has died!")
}
pub(crate) fn send_reply(
&self,
recipient: AnonymousSenderTag,
message: Vec<u8>,
lane: TransmissionLane,
) {
self.0
.unbounded_send(ReplyControllerMessage::SendReply {
recipient,
message,
lane,
})
.expect("ReplyControllerReceiver has died!")
}
pub(crate) fn send_additional_surbs(
&self,
sender_tag: AnonymousSenderTag,
reply_surbs: Vec<ReplySurb>,
from_surb_request: bool,
) {
self.0
.unbounded_send(ReplyControllerMessage::AdditionalSurbs {
sender_tag,
reply_surbs,
from_surb_request,
})
.expect("ReplyControllerReceiver has died!")
}
pub(crate) fn send_additional_surbs_request(&self, recipient: Recipient, amount: u32) {
self.0
.unbounded_send(ReplyControllerMessage::AdditionalSurbsRequest {
recipient: Box::new(recipient),
amount,
})
.expect("ReplyControllerReceiver has died!")
}
pub async fn get_lane_queue_length(&self, connection_id: ConnectionId) -> usize {
let (response_tx, response_rx) = oneshot::channel();
self.0
.unbounded_send(ReplyControllerMessage::LaneQueueLength {
connection_id,
response_channel: response_tx,
})
.expect("ReplyControllerReceiver has died!");
match response_rx.await {
Ok(length) => length,
Err(_) => {
error!("The reply controller has dropped our response channel!");
// TODO: should we panic here instead? this message implies something weird and unrecoverable has happened
0
}
}
}
}
pub struct ReplyQueueLengths {
reply_controller_sender: ReplyControllerSender,
}
impl ReplyQueueLengths {
pub fn new(reply_controller_sender: ReplyControllerSender) -> Self {
Self {
reply_controller_sender,
}
}
pub async fn get_lane_queue_length(&self, connection_id: ConnectionId) -> usize {
self.reply_controller_sender
.get_lane_queue_length(connection_id)
.await
}
}
pub(crate) type ReplyControllerReceiver = mpsc::UnboundedReceiver<ReplyControllerMessage>;
#[derive(Debug)]
pub(crate) enum ReplyControllerMessage {
RetransmitReply {
recipient: AnonymousSenderTag,
timed_out_ack: Weak<PendingAcknowledgement>,
extra_surb_request: bool,
},
SendReply {
recipient: AnonymousSenderTag,
message: Vec<u8>,
lane: TransmissionLane,
},
AdditionalSurbs {
sender_tag: AnonymousSenderTag,
reply_surbs: Vec<ReplySurb>,
from_surb_request: bool,
},
// this one doesn't belong here either...
LaneQueueLength {
connection_id: ConnectionId,
response_channel: oneshot::Sender<usize>,
},
// Should this also be handled in here? it's technically a completely different side of the pipe
// let's see how it works when combined, might split it before creating PR
AdditionalSurbsRequest {
recipient: Box<Recipient>,
amount: u32,
},
}
@@ -7,7 +7,6 @@ use async_trait::async_trait;
// well, right now we don't have the browser storage : ( // well, right now we don't have the browser storage : (
// so we keep everything in memory // so we keep everything in memory
#[derive(Debug)]
pub struct Backend { pub struct Backend {
empty: Empty, empty: Empty,
} }
@@ -19,11 +19,10 @@ pub mod fs_backend;
#[error("no information provided")] #[error("no information provided")]
pub struct UndefinedError; pub struct UndefinedError;
#[derive(Debug)]
pub struct Empty { pub struct Empty {
// we need to keep 'basic' metadata here to "load" the CombinedReplyStorage // we need to keep 'basic' metadata here to "load" the CombinedReplyStorage
pub min_surb_threshold: usize, min_surb_threshold: usize,
pub max_surb_threshold: usize, max_surb_threshold: usize,
} }
#[async_trait] #[async_trait]
@@ -152,7 +152,7 @@ impl TopologyRefresherConfig {
} }
pub struct TopologyRefresher { pub struct TopologyRefresher {
validator_client: validator_client::client::NymApiClient, validator_client: validator_client::client::ApiClient,
client_version: String, client_version: String,
nym_api_urls: Vec<Url>, nym_api_urls: Vec<Url>,
@@ -168,9 +168,7 @@ impl TopologyRefresher {
cfg.nym_api_urls.shuffle(&mut thread_rng()); cfg.nym_api_urls.shuffle(&mut thread_rng());
TopologyRefresher { TopologyRefresher {
validator_client: validator_client::client::NymApiClient::new( validator_client: validator_client::client::ApiClient::new(cfg.nym_api_urls[0].clone()),
cfg.nym_api_urls[0].clone(),
),
client_version: cfg.client_version, client_version: cfg.client_version,
nym_api_urls: cfg.nym_api_urls, nym_api_urls: cfg.nym_api_urls,
topology_accessor, topology_accessor,
+9 -37
View File
@@ -1,7 +1,7 @@
// Copyright 2021 - Nym Technologies SA <contact@nymtech.net> // Copyright 2021 - Nym Technologies SA <contact@nymtech.net>
// SPDX-License-Identifier: Apache-2.0 // SPDX-License-Identifier: Apache-2.0
use config::{NymConfig, OptionalSet, DB_FILE_NAME}; use config::{NymConfig, DB_FILE_NAME};
use nymsphinx::params::PacketSize; use nymsphinx::params::PacketSize;
use serde::{Deserialize, Serialize}; use serde::{Deserialize, Serialize};
use std::marker::PhantomData; use std::marker::PhantomData;
@@ -70,15 +70,12 @@ pub struct Config<T> {
#[serde(default)] #[serde(default)]
debug: DebugConfig, debug: DebugConfig,
} }
impl<T> ClientCoreConfigTrait for Config<T> { impl<T> ClientCoreConfigTrait for Config<T> {
fn get_gateway_endpoint(&self) -> &GatewayEndpointConfig { fn get_gateway_endpoint(&self) -> &GatewayEndpointConfig {
&self.client.gateway_endpoint &self.client.gateway_endpoint
} }
} }
impl<T> OptionalSet for Config<T> where T: NymConfig {}
impl<T> Config<T> { impl<T> Config<T> {
pub fn new<S: Into<String>>(id: S) -> Self pub fn new<S: Into<String>>(id: S) -> Self
where where
@@ -163,9 +160,8 @@ impl<T> Config<T> {
changes_made changes_made
} }
pub fn with_disabled_credentials(mut self, disabled_credentials_mode: bool) -> Self { pub fn with_disabled_credentials(&mut self, disabled_credentials_mode: bool) {
self.client.disabled_credentials_mode = disabled_credentials_mode; self.client.disabled_credentials_mode = disabled_credentials_mode;
self
} }
pub fn with_gateway_endpoint(&mut self, gateway_endpoint: GatewayEndpointConfig) { pub fn with_gateway_endpoint(&mut self, gateway_endpoint: GatewayEndpointConfig) {
@@ -176,31 +172,14 @@ impl<T> Config<T> {
self.client.gateway_endpoint.gateway_id = id.into(); self.client.gateway_endpoint.gateway_id = id.into();
} }
pub fn with_custom_nyxd(mut self, urls: Vec<Url>) -> Self { pub fn set_custom_validators(&mut self, validator_urls: Vec<Url>) {
self.client.nyxd_urls = urls; self.client.validator_urls = validator_urls;
self
}
pub fn set_custom_nyxd(&mut self, nyxd_urls: Vec<Url>) {
self.client.nyxd_urls = nyxd_urls;
}
pub fn with_custom_nym_apis(mut self, nym_api_urls: Vec<Url>) -> Self {
self.client.nym_api_urls = nym_api_urls;
self
} }
pub fn set_custom_nym_apis(&mut self, nym_api_urls: Vec<Url>) { pub fn set_custom_nym_apis(&mut self, nym_api_urls: Vec<Url>) {
self.client.nym_api_urls = nym_api_urls; self.client.nym_api_urls = nym_api_urls;
} }
pub fn with_high_default_traffic_volume(mut self, enabled: bool) -> Self {
if enabled {
self.set_high_default_traffic_volume();
}
self
}
pub fn set_high_default_traffic_volume(&mut self) { pub fn set_high_default_traffic_volume(&mut self) {
self.debug.average_packet_delay = Duration::from_millis(10); self.debug.average_packet_delay = Duration::from_millis(10);
// basically don't really send cover messages // basically don't really send cover messages
@@ -209,13 +188,6 @@ impl<T> Config<T> {
self.debug.message_sending_average_delay = Duration::from_millis(4); self.debug.message_sending_average_delay = Duration::from_millis(4);
} }
pub fn with_disabled_cover_traffic(mut self, disabled: bool) -> Self {
if disabled {
self.set_no_cover_traffic()
}
self
}
pub fn set_no_cover_traffic(&mut self) { pub fn set_no_cover_traffic(&mut self) {
self.debug.disable_loop_cover_traffic_stream = true; self.debug.disable_loop_cover_traffic_stream = true;
self.debug.disable_main_poisson_packet_distribution = true; self.debug.disable_main_poisson_packet_distribution = true;
@@ -262,7 +234,7 @@ impl<T> Config<T> {
} }
pub fn get_validator_endpoints(&self) -> Vec<Url> { pub fn get_validator_endpoints(&self) -> Vec<Url> {
self.client.nyxd_urls.clone() self.client.validator_urls.clone()
} }
pub fn get_nym_api_endpoints(&self) -> Vec<Url> { pub fn get_nym_api_endpoints(&self) -> Vec<Url> {
@@ -448,9 +420,9 @@ pub struct Client<T> {
#[serde(default)] #[serde(default)]
disabled_credentials_mode: bool, disabled_credentials_mode: bool,
/// Addresses to nyxd validators via which the client can communicate with the chain. /// Addresses to nymd validators via which the client can communicate with the chain.
#[serde(alias = "validator_urls")] #[serde(default)]
nyxd_urls: Vec<Url>, validator_urls: Vec<Url>,
/// Addresses to APIs running on validator from which the client gets the view of the network. /// Addresses to APIs running on validator from which the client gets the view of the network.
#[serde(alias = "validator_api_urls")] #[serde(alias = "validator_api_urls")]
@@ -504,7 +476,7 @@ impl<T: NymConfig> Default for Client<T> {
version: env!("CARGO_PKG_VERSION").to_string(), version: env!("CARGO_PKG_VERSION").to_string(),
id: "".to_string(), id: "".to_string(),
disabled_credentials_mode: true, disabled_credentials_mode: true,
nyxd_urls: vec![], validator_urls: vec![],
nym_api_urls: vec![], nym_api_urls: vec![],
private_identity_key_file: Default::default(), private_identity_key_file: Default::default(),
public_identity_key_file: Default::default(), public_identity_key_file: Default::default(),
@@ -7,12 +7,12 @@ use std::path::{Path, PathBuf};
#[derive(Debug)] #[derive(Debug)]
pub struct ClientKeyPathfinder { pub struct ClientKeyPathfinder {
pub identity_private_key: PathBuf, identity_private_key: PathBuf,
pub identity_public_key: PathBuf, identity_public_key: PathBuf,
pub encryption_private_key: PathBuf, encryption_private_key: PathBuf,
pub encryption_public_key: PathBuf, encryption_public_key: PathBuf,
pub gateway_shared_key: PathBuf, gateway_shared_key: PathBuf,
pub ack_key: PathBuf, ack_key: PathBuf,
} }
impl ClientKeyPathfinder { impl ClientKeyPathfinder {
@@ -22,8 +22,8 @@ impl ClientKeyPathfinder {
ClientKeyPathfinder { ClientKeyPathfinder {
identity_private_key: config_dir.join("private_identity.pem"), identity_private_key: config_dir.join("private_identity.pem"),
identity_public_key: config_dir.join("public_identity.pem"), identity_public_key: config_dir.join("public_identity.pem"),
encryption_private_key: config_dir.join("private_encryption.pem"), encryption_private_key: config_dir.join("public_encryption.pem"),
encryption_public_key: config_dir.join("public_encryption.pem"), encryption_public_key: config_dir.join("private_encryption.pem"),
gateway_shared_key: config_dir.join("gateway_shared.pem"), gateway_shared_key: config_dir.join("gateway_shared.pem"),
ack_key: config_dir.join("ack_key.pem"), ack_key: config_dir.join("ack_key.pem"),
} }
@@ -40,28 +40,6 @@ impl ClientKeyPathfinder {
} }
} }
pub fn any_file_exists(&self) -> bool {
matches!(self.identity_public_key.try_exists(), Ok(true))
|| matches!(self.identity_private_key.try_exists(), Ok(true))
|| matches!(self.encryption_public_key.try_exists(), Ok(true))
|| matches!(self.encryption_private_key.try_exists(), Ok(true))
|| matches!(self.gateway_shared_key.try_exists(), Ok(true))
|| matches!(self.ack_key.try_exists(), Ok(true))
}
pub fn any_file_exists_and_return(&self) -> Option<PathBuf> {
file_exists(&self.identity_public_key)
.or_else(|| file_exists(&self.identity_private_key))
.or_else(|| file_exists(&self.encryption_public_key))
.or_else(|| file_exists(&self.encryption_private_key))
.or_else(|| file_exists(&self.gateway_shared_key))
.or_else(|| file_exists(&self.ack_key))
}
pub fn gateway_key_file_exists(&self) -> bool {
matches!(self.gateway_shared_key.try_exists(), Ok(true))
}
pub fn private_identity_key(&self) -> &Path { pub fn private_identity_key(&self) -> &Path {
&self.identity_private_key &self.identity_private_key
} }
@@ -86,10 +64,3 @@ impl ClientKeyPathfinder {
&self.ack_key &self.ack_key
} }
} }
fn file_exists(path: &Path) -> Option<PathBuf> {
if matches!(path.try_exists(), Ok(true)) {
return Some(path.to_path_buf());
}
None
}
+3 -7
View File
@@ -1,13 +1,14 @@
// Copyright 2022 - Nym Technologies SA <contact@nymtech.net> // Copyright 2022 - Nym Technologies SA <contact@nymtech.net>
// SPDX-License-Identifier: Apache-2.0 // SPDX-License-Identifier: Apache-2.0
use crate::client::replies::reply_storage::ReplyStorageBackend;
use crypto::asymmetric::identity::Ed25519RecoveryError; use crypto::asymmetric::identity::Ed25519RecoveryError;
use gateway_client::error::GatewayClientError; use gateway_client::error::GatewayClientError;
use topology::NymTopologyError; use topology::NymTopologyError;
use validator_client::ValidatorClientError; use validator_client::ValidatorClientError;
#[derive(thiserror::Error, Debug)] #[derive(thiserror::Error, Debug)]
pub enum ClientCoreError { pub enum ClientCoreError<B: ReplyStorageBackend> {
#[error("I/O error: {0}")] #[error("I/O error: {0}")]
IoError(#[from] std::io::Error), IoError(#[from] std::io::Error),
@@ -39,9 +40,7 @@ pub enum ClientCoreError {
InsufficientNetworkTopology(#[from] NymTopologyError), InsufficientNetworkTopology(#[from] NymTopologyError),
#[error("experienced a failure with our reply surb persistent storage: {source}")] #[error("experienced a failure with our reply surb persistent storage: {source}")]
SurbStorageError { SurbStorageError { source: B::StorageError },
source: Box<dyn std::error::Error + Send + Sync>,
},
#[error("The gateway id is invalid - {0}")] #[error("The gateway id is invalid - {0}")]
UnableToCreatePublicKeyFromGatewayId(Ed25519RecoveryError), UnableToCreatePublicKeyFromGatewayId(Ed25519RecoveryError),
@@ -55,9 +54,6 @@ pub enum ClientCoreError {
#[error("The address of the gateway is unknown - did you run init?")] #[error("The address of the gateway is unknown - did you run init?")]
GatwayAddressUnknown, GatwayAddressUnknown,
#[error("failed to register receiver for reconstructed mixnet messages")]
FailedToRegisterReceiver,
#[error("Unexpected exit")] #[error("Unexpected exit")]
UnexpectedExit, UnexpectedExit,
} }
+24 -9
View File
@@ -1,6 +1,7 @@
// Copyright 2022 - Nym Technologies SA <contact@nymtech.net> // Copyright 2022 - Nym Technologies SA <contact@nymtech.net>
// SPDX-License-Identifier: Apache-2.0 // SPDX-License-Identifier: Apache-2.0
use crate::client::replies::reply_storage::ReplyStorageBackend;
use crate::{ use crate::{
client::key_manager::KeyManager, client::key_manager::KeyManager,
config::{persistence::key_pathfinder::ClientKeyPathfinder, Config}, config::{persistence::key_pathfinder::ClientKeyPathfinder, Config},
@@ -10,20 +11,23 @@ use config::NymConfig;
use crypto::asymmetric::identity; use crypto::asymmetric::identity;
use gateway_client::GatewayClient; use gateway_client::GatewayClient;
use gateway_requests::registration::handshake::SharedKeys; use gateway_requests::registration::handshake::SharedKeys;
use rand::{seq::SliceRandom, thread_rng}; use rand::{rngs::OsRng, seq::SliceRandom, thread_rng};
use std::{sync::Arc, time::Duration}; use std::{sync::Arc, time::Duration};
use tap::TapFallible; use tap::TapFallible;
use topology::{filter::VersionFilterable, gateway}; use topology::{filter::VersionFilterable, gateway};
use url::Url; use url::Url;
pub(super) async fn query_gateway_details( pub(super) async fn query_gateway_details<B>(
validator_servers: Vec<Url>, validator_servers: Vec<Url>,
chosen_gateway_id: Option<String>, chosen_gateway_id: Option<String>,
) -> Result<gateway::Node, ClientCoreError> { ) -> Result<gateway::Node, ClientCoreError<B>>
where
B: ReplyStorageBackend,
{
let nym_api = validator_servers let nym_api = validator_servers
.choose(&mut thread_rng()) .choose(&mut thread_rng())
.ok_or(ClientCoreError::ListOfNymApisIsEmpty)?; .ok_or(ClientCoreError::ListOfNymApisIsEmpty)?;
let validator_client = validator_client::client::NymApiClient::new(nym_api.clone()); let validator_client = validator_client::client::ApiClient::new(nym_api.clone());
log::trace!("Fetching list of gateways from: {}", nym_api); log::trace!("Fetching list of gateways from: {}", nym_api);
let gateways = validator_client.get_cached_gateways().await?; let gateways = validator_client.get_cached_gateways().await?;
@@ -51,10 +55,13 @@ pub(super) async fn query_gateway_details(
} }
} }
pub(super) async fn register_with_gateway( async fn register_with_gateway<B>(
gateway: &gateway::Node, gateway: &gateway::Node,
our_identity: Arc<identity::KeyPair>, our_identity: Arc<identity::KeyPair>,
) -> Result<Arc<SharedKeys>, ClientCoreError> { ) -> Result<Arc<SharedKeys>, ClientCoreError<B>>
where
B: ReplyStorageBackend,
{
let timeout = Duration::from_millis(1500); let timeout = Duration::from_millis(1500);
let mut gateway_client = GatewayClient::new_init( let mut gateway_client = GatewayClient::new_init(
gateway.clients_address(), gateway.clients_address(),
@@ -74,13 +81,21 @@ pub(super) async fn register_with_gateway(
Ok(shared_keys) Ok(shared_keys)
} }
pub(super) fn store_keys<T>( pub(super) async fn register_with_gateway_and_store_keys<T, B>(
key_manager: &KeyManager, gateway_details: gateway::Node,
config: &Config<T>, config: &Config<T>,
) -> Result<(), ClientCoreError> ) -> Result<(), ClientCoreError<B>>
where where
T: NymConfig, T: NymConfig,
B: ReplyStorageBackend,
{ {
let mut rng = OsRng;
let mut key_manager = KeyManager::new(&mut rng);
let shared_keys =
register_with_gateway(&gateway_details, key_manager.identity_keypair()).await?;
key_manager.insert_gateway_shared_key(shared_keys);
let pathfinder = ClientKeyPathfinder::new_from_config(config); let pathfinder = ClientKeyPathfinder::new_from_config(config);
Ok(key_manager Ok(key_manager
.store_keys(&pathfinder) .store_keys(&pathfinder)
+40 -77
View File
@@ -6,26 +6,24 @@
use std::fmt::Display; use std::fmt::Display;
use nymsphinx::addressing::{clients::Recipient, nodes::NodeIdentity}; use nymsphinx::addressing::{clients::Recipient, nodes::NodeIdentity};
use rand::rngs::OsRng;
use serde::Serialize; use serde::Serialize;
use tap::TapFallible; use tap::TapFallible;
use config::NymConfig; use config::NymConfig;
use crypto::asymmetric::{encryption, identity}; use crypto::asymmetric::{encryption, identity};
use url::Url;
use crate::client::key_manager::KeyManager; use crate::client::replies::reply_storage::ReplyStorageBackend;
use crate::{ use crate::{
config::{ config::{
persistence::key_pathfinder::ClientKeyPathfinder, ClientCoreConfigTrait, Config, persistence::key_pathfinder::ClientKeyPathfinder, ClientCoreConfigTrait, Config,
GatewayEndpointConfig, GatewayEndpointConfig,
}, },
error::ClientCoreError, error::ClientCoreError,
init::helpers::{query_gateway_details, register_with_gateway_and_store_keys},
}; };
mod helpers; mod helpers;
/// Struct describing the results of the client initialization procedure.
#[derive(Debug, Serialize)] #[derive(Debug, Serialize)]
pub struct InitResults { pub struct InitResults {
version: String, version: String,
@@ -63,105 +61,77 @@ impl Display for InitResults {
} }
} }
/// Create a new set of client keys.
pub fn new_client_keys() -> KeyManager {
let mut rng = OsRng;
KeyManager::new(&mut rng)
}
/// Convenience function for setting up the gateway for a client. Depending on the arguments given /// Convenience function for setting up the gateway for a client. Depending on the arguments given
/// it will do the sensible thing. /// it will do the sensible thing.
pub async fn setup_gateway<C, T>( pub async fn setup_gateway<B, C, T>(
register_gateway: bool, register_gateway: bool,
// TODO: this should get refactored to instead take Option<identity::PublicKey>
user_chosen_gateway_id: Option<String>, user_chosen_gateway_id: Option<String>,
config: &Config<T>, config: &Config<T>,
) -> Result<GatewayEndpointConfig, ClientCoreError> ) -> Result<GatewayEndpointConfig, ClientCoreError<B>>
where where
B: ReplyStorageBackend,
C: NymConfig + ClientCoreConfigTrait, C: NymConfig + ClientCoreConfigTrait,
T: NymConfig, T: NymConfig,
{ {
let id = config.get_id(); let id = config.get_id();
if register_gateway { if register_gateway {
register_with_gateway_and_store(user_chosen_gateway_id, config).await register_with_gateway(user_chosen_gateway_id, config).await
} else if let Some(user_chosen_gateway_id) = user_chosen_gateway_id { } else if let Some(user_chosen_gateway_id) = user_chosen_gateway_id {
config_gateway_with_existing_keys(user_chosen_gateway_id, config).await config_gateway_with_existing_keys(user_chosen_gateway_id, config).await
} else { } else {
reuse_existing_gateway_config::<C>(&id) reuse_existing_gateway_config::<B, C>(&id)
} }
} }
/// Get the gateway details by querying the validator-api. Either pick one at random or use
/// the chosen one if it's among the available ones.
pub async fn register_with_gateway(
key_manager: &mut KeyManager,
nym_api_endpoints: Vec<Url>,
chosen_gateway_id: Option<String>,
) -> Result<GatewayEndpointConfig, ClientCoreError> {
// Our identity is derived from our key
let our_identity = key_manager.identity_keypair();
// Get the gateway details of the gateway we will use
let gateway = helpers::query_gateway_details(nym_api_endpoints, chosen_gateway_id).await?;
log::debug!("Querying gateway gives: {}", gateway);
// Establish connection, authenticate and generate keys for talking with the gateway
let shared_keys = helpers::register_with_gateway(&gateway, our_identity).await?;
key_manager.insert_gateway_shared_key(shared_keys);
Ok(gateway.into())
}
/// Get the gateway details by querying the validator-api. Either pick one at random or use /// Get the gateway details by querying the validator-api. Either pick one at random or use
/// the chosen one if it's among the available ones. /// the chosen one if it's among the available ones.
/// Saves keys to disk, specified by the paths in `config`. /// Saves keys to disk, specified by the paths in `config`.
pub async fn register_with_gateway_and_store<T>( pub async fn register_with_gateway<B, T>(
chosen_gateway_id: Option<String>, user_chosen_gateway_id: Option<String>,
config: &Config<T>, config: &Config<T>,
) -> Result<GatewayEndpointConfig, ClientCoreError> ) -> Result<GatewayEndpointConfig, ClientCoreError<B>>
where where
B: ReplyStorageBackend,
T: NymConfig, T: NymConfig,
{ {
println!("Configuring gateway"); println!("Configuring gateway");
let mut key_manager = new_client_keys(); let gateway =
query_gateway_details(config.get_nym_api_endpoints(), user_chosen_gateway_id).await?;
log::debug!("Querying gateway gives: {}", gateway);
let gateway = register_with_gateway( // Registering with gateway by setting up and writing shared keys to disk
&mut key_manager, log::trace!("Registering gateway");
config.get_nym_api_endpoints(), register_with_gateway_and_store_keys(gateway.clone(), config).await?;
chosen_gateway_id,
)
.await?;
helpers::store_keys(&key_manager, config)?;
println!("Saved all generated keys"); println!("Saved all generated keys");
Ok(gateway) Ok(gateway.into())
} }
/// Set the gateway using the usual procedue of querying the validator-api, but don't register or /// Set the gateway using the usual procedue of querying the validator-api, but don't register or
/// create any keys. /// create any keys.
/// This assumes that the user knows what they are doing, and that the existing keys are valid for /// This assumes that the user knows what they are doing, and that the existing keys are valid for
/// the gateway being used /// the gateway being used
pub async fn config_gateway_with_existing_keys<T>( pub async fn config_gateway_with_existing_keys<B, T>(
user_chosen_gateway_id: String, user_chosen_gateway_id: String,
config: &Config<T>, config: &Config<T>,
) -> Result<GatewayEndpointConfig, ClientCoreError> ) -> Result<GatewayEndpointConfig, ClientCoreError<B>>
where where
B: ReplyStorageBackend,
T: NymConfig, T: NymConfig,
{ {
println!("Using gateway provided by user, keeping existing keys"); println!("Using gateway provided by user, keeping existing keys");
let gateway = helpers::query_gateway_details( let gateway =
config.get_nym_api_endpoints(), query_gateway_details(config.get_nym_api_endpoints(), Some(user_chosen_gateway_id)).await?;
Some(user_chosen_gateway_id),
)
.await?;
log::debug!("Querying gateway gives: {}", gateway); log::debug!("Querying gateway gives: {}", gateway);
Ok(gateway.into()) Ok(gateway.into())
} }
/// Read and reuse the existing gateway configuration from a file that was generate earlier. /// Read and reuse the existing gateway configuration from a file that was generate earlier.
pub fn reuse_existing_gateway_config<T>(id: &str) -> Result<GatewayEndpointConfig, ClientCoreError> pub fn reuse_existing_gateway_config<B, T>(
id: &str,
) -> Result<GatewayEndpointConfig, ClientCoreError<B>>
where where
B: ReplyStorageBackend,
T: NymConfig + ClientCoreConfigTrait, T: NymConfig + ClientCoreConfigTrait,
{ {
println!("Not registering gateway, will reuse existing config and keys"); println!("Not registering gateway, will reuse existing config and keys");
@@ -179,30 +149,20 @@ where
}) })
} }
/// Get the full client address from the client keys and the gateway identity
pub fn get_client_address(
key_manager: &KeyManager,
gateway_config: &GatewayEndpointConfig,
) -> Recipient {
Recipient::new(
*key_manager.identity_keypair().public_key(),
*key_manager.encryption_keypair().public_key(),
// TODO: below only works under assumption that gateway address == gateway id
// (which currently is true)
NodeIdentity::from_base58_string(&gateway_config.gateway_id).unwrap(),
)
}
/// Get the client address by loading the keys from stored files. /// Get the client address by loading the keys from stored files.
pub fn get_client_address_from_stored_keys<T>( pub fn get_client_address_from_stored_keys<B, T>(
config: &Config<T>, config: &Config<T>,
) -> Result<Recipient, ClientCoreError> ) -> Result<Recipient, ClientCoreError<B>>
where where
T: config::NymConfig, T: config::NymConfig,
B: ReplyStorageBackend,
{ {
fn load_identity_keys( fn load_identity_keys<B>(
pathfinder: &ClientKeyPathfinder, pathfinder: &ClientKeyPathfinder,
) -> Result<identity::KeyPair, ClientCoreError> { ) -> Result<identity::KeyPair, ClientCoreError<B>>
where
B: ReplyStorageBackend,
{
let identity_keypair: identity::KeyPair = let identity_keypair: identity::KeyPair =
pemstore::load_keypair(&pemstore::KeyPairPath::new( pemstore::load_keypair(&pemstore::KeyPairPath::new(
pathfinder.private_identity_key().to_owned(), pathfinder.private_identity_key().to_owned(),
@@ -212,9 +172,12 @@ where
Ok(identity_keypair) Ok(identity_keypair)
} }
fn load_sphinx_keys( fn load_sphinx_keys<B>(
pathfinder: &ClientKeyPathfinder, pathfinder: &ClientKeyPathfinder,
) -> Result<encryption::KeyPair, ClientCoreError> { ) -> Result<encryption::KeyPair, ClientCoreError<B>>
where
B: ReplyStorageBackend,
{
let sphinx_keypair: encryption::KeyPair = let sphinx_keypair: encryption::KeyPair =
pemstore::load_keypair(&pemstore::KeyPairPath::new( pemstore::load_keypair(&pemstore::KeyPairPath::new(
pathfinder.private_encryption_key().to_owned(), pathfinder.private_encryption_key().to_owned(),
+2 -2
View File
@@ -8,7 +8,7 @@ edition = "2021"
[dependencies] [dependencies]
bip39 = "1.0.1" bip39 = "1.0.1"
cfg-if = "0.1" cfg-if = "0.1"
clap = { version = "4.0", features = ["cargo", "derive"] } clap = { version = "3.2", features = ["cargo", "derive"] }
rand = "0.7.3" rand = "0.7.3"
serde = { version = "1.0", features = ["derive"] } serde = { version = "1.0", features = ["derive"] }
thiserror = "1.0" thiserror = "1.0"
@@ -23,7 +23,7 @@ credential-storage = { path = "../../common/credential-storage" }
crypto = { path = "../../common/crypto", features = ["rand", "asymmetric", "symmetric", "aes", "hashing"] } crypto = { path = "../../common/crypto", features = ["rand", "asymmetric", "symmetric", "aes", "hashing"] }
network-defaults = { path = "../../common/network-defaults" } network-defaults = { path = "../../common/network-defaults" }
pemstore = { path = "../../common/pemstore" } pemstore = { path = "../../common/pemstore" }
validator-client = { path = "../../common/client-libs/validator-client", features = ["nyxd-client"] } validator-client = { path = "../../common/client-libs/validator-client", features = ["nymd-client"] }
[features] [features]
coconut = ["credentials/coconut"] coconut = ["credentials/coconut"]
+11 -11
View File
@@ -6,27 +6,27 @@ use bip39::Mnemonic;
use network_defaults::{NymNetworkDetails, VOUCHER_INFO}; use network_defaults::{NymNetworkDetails, VOUCHER_INFO};
use std::str::FromStr; use std::str::FromStr;
use url::Url; use url::Url;
use validator_client::nyxd; use validator_client::nymd;
use validator_client::nyxd::traits::CoconutBandwidthSigningClient; use validator_client::nymd::traits::CoconutBandwidthSigningClient;
use validator_client::nyxd::{Coin, Fee, NyxdClient, SigningNyxdClient}; use validator_client::nymd::{Coin, Fee, NymdClient, SigningNymdClient};
pub(crate) struct Client { pub(crate) struct Client {
nyxd_client: NyxdClient<SigningNyxdClient>, nymd_client: NymdClient<SigningNymdClient>,
mix_denom_base: String, mix_denom_base: String,
} }
impl Client { impl Client {
pub fn new(nyxd_url: &str, mnemonic: &str) -> Self { pub fn new(nymd_url: &str, mnemonic: &str) -> Self {
let nyxd_url = Url::from_str(nyxd_url).unwrap(); let nymd_url = Url::from_str(nymd_url).unwrap();
let mnemonic = Mnemonic::from_str(mnemonic).unwrap(); let mnemonic = Mnemonic::from_str(mnemonic).unwrap();
let network_details = NymNetworkDetails::new_from_env(); let network_details = NymNetworkDetails::new_from_env();
let config = nyxd::Config::try_from_nym_network_details(&network_details) let config = nymd::Config::try_from_nym_network_details(&network_details)
.expect("failed to construct valid validator client config with the provided network"); .expect("failed to construct valid validator client config with the provided network");
let nyxd_client = let nymd_client =
NyxdClient::connect_with_mnemonic(config, nyxd_url.as_ref(), mnemonic, None).unwrap(); NymdClient::connect_with_mnemonic(config, nymd_url.as_ref(), mnemonic, None).unwrap();
Client { Client {
nyxd_client, nymd_client,
mix_denom_base: network_details.chain_details.mix_denom.base, mix_denom_base: network_details.chain_details.mix_denom.base,
} }
} }
@@ -40,7 +40,7 @@ impl Client {
) -> Result<String> { ) -> Result<String> {
let amount = Coin::new(amount as u128, self.mix_denom_base.clone()); let amount = Coin::new(amount as u128, self.mix_denom_base.clone());
Ok(self Ok(self
.nyxd_client .nymd_client
.deposit( .deposit(
amount, amount,
String::from(VOUCHER_INFO), String::from(VOUCHER_INFO),
+5 -5
View File
@@ -13,7 +13,7 @@ use credentials::coconut::bandwidth::{BandwidthVoucher, TOTAL_ATTRIBUTES};
use credentials::coconut::utils::obtain_aggregate_signature; use credentials::coconut::utils::obtain_aggregate_signature;
use crypto::asymmetric::{encryption, identity}; use crypto::asymmetric::{encryption, identity};
use network_defaults::{NymNetworkDetails, VOUCHER_INFO}; use network_defaults::{NymNetworkDetails, VOUCHER_INFO};
use validator_client::nyxd::tx::Hash; use validator_client::nymd::tx::Hash;
use validator_client::{CoconutApiClient, Config}; use validator_client::{CoconutApiClient, Config};
use crate::client::Client; use crate::client::Client;
@@ -38,9 +38,9 @@ pub(crate) struct Run {
#[clap(long)] #[clap(long)]
pub(crate) client_home_directory: std::path::PathBuf, pub(crate) client_home_directory: std::path::PathBuf,
/// The nyxd URL that should be used /// The nymd URL that should be used
#[clap(long)] #[clap(long)]
pub(crate) nyxd_url: String, pub(crate) nymd_url: String,
/// A mnemonic for the account that buys the credential /// A mnemonic for the account that buys the credential
#[clap(long)] #[clap(long)]
@@ -51,12 +51,12 @@ pub(crate) struct Run {
pub(crate) amount: u64, pub(crate) amount: u64,
} }
pub(crate) async fn deposit(nyxd_url: &str, mnemonic: &str, amount: u64) -> Result<State> { pub(crate) async fn deposit(nymd_url: &str, mnemonic: &str, amount: u64) -> Result<State> {
let mut rng = OsRng; let mut rng = OsRng;
let signing_keypair = KeyPair::from(identity::KeyPair::new(&mut rng)); let signing_keypair = KeyPair::from(identity::KeyPair::new(&mut rng));
let encryption_keypair = KeyPair::from(encryption::KeyPair::new(&mut rng)); let encryption_keypair = KeyPair::from(encryption::KeyPair::new(&mut rng));
let client = Client::new(nyxd_url, mnemonic); let client = Client::new(nymd_url, mnemonic);
let tx_hash = client let tx_hash = client
.deposit( .deposit(
amount, amount,
+3 -3
View File
@@ -7,15 +7,15 @@ use credential_storage::error::StorageError;
use credentials::error::Error as CredentialError; use credentials::error::Error as CredentialError;
use crypto::asymmetric::encryption::KeyRecoveryError; use crypto::asymmetric::encryption::KeyRecoveryError;
use crypto::asymmetric::identity::Ed25519RecoveryError; use crypto::asymmetric::identity::Ed25519RecoveryError;
use validator_client::nyxd::error::NyxdError; use validator_client::nymd::error::NymdError;
use validator_client::ValidatorClientError; use validator_client::ValidatorClientError;
pub type Result<T> = std::result::Result<T, CredentialClientError>; pub type Result<T> = std::result::Result<T, CredentialClientError>;
#[derive(Error, Debug)] #[derive(Error, Debug)]
pub enum CredentialClientError { pub enum CredentialClientError {
#[error("Nyxd error: {0}")] #[error("Nymd error: {0}")]
Nyxd(#[from] NyxdError), Nymd(#[from] NymdError),
#[error("Validator client error: {0}")] #[error("Validator client error: {0}")]
ValidatorClientError(#[from] ValidatorClientError), ValidatorClientError(#[from] ValidatorClientError),
+4 -4
View File
@@ -31,7 +31,7 @@ cfg_if::cfg_if! {
#[tokio::main] #[tokio::main]
async fn main() -> Result<()> { async fn main() -> Result<()> {
let args = Cli::parse(); let args = Cli::parse();
setup_env(args.config_env_file.as_ref()); setup_env(args.config_env_file.clone());
let bin_name = "nym-credential-client"; let bin_name = "nym-credential-client";
match args.command { match args.command {
@@ -39,11 +39,11 @@ cfg_if::cfg_if! {
let db_path = r.client_home_directory.join(DATA_DIR).join(DB_FILE_NAME); let db_path = r.client_home_directory.join(DATA_DIR).join(DB_FILE_NAME);
let shared_storage = credential_storage::initialise_storage(db_path).await; let shared_storage = credential_storage::initialise_storage(db_path).await;
let state = deposit(&r.nyxd_url, &r.mnemonic, r.amount).await?; let state = deposit(&r.nymd_url, &r.mnemonic, r.amount).await?;
get_credential(&state, shared_storage).await?; get_credential(&state, shared_storage).await?;
} }
Command::Completions(c) => c.generate(&mut crate::Cli::command(), bin_name), Command::Completions(c) => c.generate(&mut crate::Cli::into_app(), bin_name),
Command::GenerateFigSpec => fig_generate(&mut crate::Cli::command(), bin_name) Command::GenerateFigSpec => fig_generate(&mut crate::Cli::into_app(), bin_name)
} }
Ok(()) Ok(())
+6 -5
View File
@@ -1,6 +1,6 @@
[package] [package]
name = "nym-client" name = "nym-client"
version = "1.1.5" version = "1.1.3"
authors = ["Dave Hrycyszyn <futurechimp@users.noreply.github.com>", "Jędrzej Stuczyński <andrew@nymtech.net>"] authors = ["Dave Hrycyszyn <futurechimp@users.noreply.github.com>", "Jędrzej Stuczyński <andrew@nymtech.net>"]
description = "Implementation of the Nym Client" description = "Implementation of the Nym Client"
edition = "2021" edition = "2021"
@@ -20,9 +20,8 @@ futures = "0.3" # bunch of futures stuff, however, now that I think about it, it
# and the single instance of abortable we have should really be refactored anyway # and the single instance of abortable we have should really be refactored anyway
url = "2.2" url = "2.2"
clap = { version = "4.0", features = ["cargo", "derive"] } clap = { version = "3.2", features = ["cargo", "derive"] }
dirs = "4.0" dirs = "4.0"
lazy_static = "1.4.0"
log = "0.4" # self explanatory log = "0.4" # self explanatory
pretty_env_logger = "0.4" # for formatting log messages 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 rand = { version = "0.7.3", features = ["wasm-bindgen"] } # rng-related traits + some rng implementation to use
@@ -34,7 +33,6 @@ tokio = { version = "1.21.2", features = ["rt-multi-thread", "net", "signal"] }
tokio-tungstenite = "0.14" # websocket tokio-tungstenite = "0.14" # websocket
## internal ## internal
build-information = { path = "../../common/build-information" }
client-core = { path = "../client-core", features = ["fs-surb-storage"] } client-core = { path = "../client-core", features = ["fs-surb-storage"] }
client-connections = { path = "../../common/client-connections" } client-connections = { path = "../../common/client-connections" }
coconut-interface = { path = "../../common/coconut-interface", optional = true } coconut-interface = { path = "../../common/coconut-interface", optional = true }
@@ -51,7 +49,7 @@ nymsphinx = { path = "../../common/nymsphinx" }
pemstore = { path = "../../common/pemstore" } pemstore = { path = "../../common/pemstore" }
task = { path = "../../common/task" } task = { path = "../../common/task" }
topology = { path = "../../common/topology" } topology = { path = "../../common/topology" }
validator-client = { path = "../../common/client-libs/validator-client", features = ["nyxd-client"] } validator-client = { path = "../../common/client-libs/validator-client", features = ["nymd-client"] }
version-checker = { path = "../../common/version-checker" } version-checker = { path = "../../common/version-checker" }
websocket-requests = { path = "websocket-requests" } websocket-requests = { path = "websocket-requests" }
@@ -60,3 +58,6 @@ coconut = ["coconut-interface", "credentials", "credentials/coconut", "gateway-r
[dev-dependencies] [dev-dependencies]
serde_json = "1.0" # for the "textsend" example serde_json = "1.0" # for the "textsend" example
[build-dependencies]
vergen = { version = "5", default-features = false, features = ["build", "git", "rustc", "cargo"] }
@@ -1,4 +1,4 @@
// Copyright 2023 - Nym Technologies SA <contact@nymtech.net> // Copyright 2021 - Nym Technologies SA <contact@nymtech.net>
// SPDX-License-Identifier: Apache-2.0 // SPDX-License-Identifier: Apache-2.0
use vergen::{vergen, Config}; use vergen::{vergen, Config};
File diff suppressed because it is too large Load Diff
+2 -58
View File
@@ -2,15 +2,12 @@
// SPDX-License-Identifier: Apache-2.0 // SPDX-License-Identifier: Apache-2.0
use crate::client::config::template::config_template; use crate::client::config::template::config_template;
pub use client_core::config::Config as BaseConfig;
pub use client_core::config::MISSING_VALUE; pub use client_core::config::MISSING_VALUE;
use client_core::config::{ClientCoreConfigTrait, DebugConfig}; use client_core::config::{ClientCoreConfigTrait, Config as BaseConfig, DebugConfig};
use config::defaults::DEFAULT_WEBSOCKET_LISTENING_PORT; use config::defaults::DEFAULT_WEBSOCKET_LISTENING_PORT;
use config::{NymConfig, OptionalSet}; use config::NymConfig;
use serde::{Deserialize, Serialize}; use serde::{Deserialize, Serialize};
use std::fmt::Debug;
use std::path::PathBuf; use std::path::PathBuf;
use std::str::FromStr;
mod template; mod template;
@@ -95,15 +92,6 @@ impl Config {
self self
} }
pub fn with_disabled_socket(mut self, disabled: bool) -> Self {
if disabled {
self.socket.socket_type = SocketType::None;
} else {
self.socket.socket_type = SocketType::WebSocket;
}
self
}
pub fn with_port(mut self, port: u16) -> Self { pub fn with_port(mut self, port: u16) -> Self {
self.socket.listening_port = port; self.socket.listening_port = port;
self self
@@ -133,50 +121,6 @@ impl Config {
pub fn get_listening_port(&self) -> u16 { pub fn get_listening_port(&self) -> u16 {
self.socket.listening_port self.socket.listening_port
} }
// poor man's 'builder' method
pub fn with_base<F, T>(mut self, f: F, val: T) -> Self
where
F: Fn(BaseConfig<Self>, T) -> BaseConfig<Self>,
{
self.base = f(self.base, val);
self
}
// helper methods to use `OptionalSet` trait. Those are defined due to very... ehm. 'specific' structure of this config
// (plz, lets refactor it)
pub fn with_optional_ext<F, T>(mut self, f: F, val: Option<T>) -> Self
where
F: Fn(BaseConfig<Self>, T) -> BaseConfig<Self>,
{
self.base = self.base.with_optional(f, val);
self
}
pub fn with_optional_env_ext<F, T>(mut self, f: F, val: Option<T>, env_var: &str) -> Self
where
F: Fn(BaseConfig<Self>, T) -> BaseConfig<Self>,
T: FromStr,
<T as FromStr>::Err: Debug,
{
self.base = self.base.with_optional_env(f, val, env_var);
self
}
pub fn with_optional_custom_env_ext<F, T, G>(
mut self,
f: F,
val: Option<T>,
env_var: &str,
parser: G,
) -> Self
where
F: Fn(BaseConfig<Self>, T) -> BaseConfig<Self>,
G: Fn(&str) -> T,
{
self.base = self.base.with_optional_custom_env(f, val, env_var, parser);
self
}
} }
#[derive(Debug, Deserialize, PartialEq, Eq, Serialize)] #[derive(Debug, Deserialize, PartialEq, Eq, Serialize)]
+3 -3
View File
@@ -23,9 +23,9 @@ id = '{{ client.id }}'
# to claim bandwidth without presenting bandwidth credentials. # to claim bandwidth without presenting bandwidth credentials.
disabled_credentials_mode = {{ client.disabled_credentials_mode }} disabled_credentials_mode = {{ client.disabled_credentials_mode }}
# Addresses to nyxd validators via which the client can communicate with the chain. # Addresses to nymd validators via which the client can communicate with the chain.
nyxd_urls = [ validator_urls = [
{{#each client.nyxd_urls }} {{#each client.validator_urls }}
'{{this}}', '{{this}}',
{{/each}} {{/each}}
] ]
+5 -13
View File
@@ -8,7 +8,7 @@ use crate::error::ClientError;
use crate::websocket; use crate::websocket;
use client_connections::TransmissionLane; use client_connections::TransmissionLane;
use client_core::client::base_client::{ use client_core::client::base_client::{
non_wasm_helpers, BaseClientBuilder, ClientInput, ClientOutput, ClientState, non_wasm_helpers, BaseClientBuilder, ClientInput, ClientOutput,
}; };
use client_core::client::inbound_messages::InputMessage; use client_core::client::inbound_messages::InputMessage;
use client_core::client::key_manager::KeyManager; use client_core::client::key_manager::KeyManager;
@@ -51,18 +51,18 @@ impl SocketClient {
let mut client_config = let mut client_config =
validator_client::Config::try_from_nym_network_details(&details) validator_client::Config::try_from_nym_network_details(&details)
.expect("failed to construct validator client config"); .expect("failed to construct validator client config");
let nyxd_url = config let nymd_url = config
.get_base() .get_base()
.get_validator_endpoints() .get_validator_endpoints()
.pop() .pop()
.expect("No nyxd validator endpoint provided"); .expect("No nymd validator endpoint provided");
let api_url = config let api_url = config
.get_base() .get_base()
.get_nym_api_endpoints() .get_nym_api_endpoints()
.pop() .pop()
.expect("No validator api endpoint provided"); .expect("No validator api endpoint provided");
// overwrite env configuration with config URLs // overwrite env configuration with config URLs
client_config = client_config.with_urls(nyxd_url, api_url); client_config = client_config.with_urls(nymd_url, api_url);
let client = validator_client::Client::new_query(client_config) let client = validator_client::Client::new_query(client_config)
.expect("Could not construct query client"); .expect("Could not construct query client");
let coconut_api_clients = let coconut_api_clients =
@@ -86,7 +86,6 @@ impl SocketClient {
config: &Config, config: &Config,
client_input: ClientInput, client_input: ClientInput,
client_output: ClientOutput, client_output: ClientOutput,
client_state: ClientState,
self_address: &Recipient, self_address: &Recipient,
shutdown: task::TaskClient, shutdown: task::TaskClient,
) { ) {
@@ -98,21 +97,16 @@ impl SocketClient {
} = client_input; } = client_input;
let ClientOutput { let ClientOutput {
shared_lane_queue_lengths,
received_buffer_request_sender, received_buffer_request_sender,
} = client_output; } = client_output;
let ClientState {
shared_lane_queue_lengths,
reply_controller_sender,
} = client_state;
let websocket_handler = websocket::HandlerBuilder::new( let websocket_handler = websocket::HandlerBuilder::new(
input_sender, input_sender,
connection_command_sender, connection_command_sender,
received_buffer_request_sender, received_buffer_request_sender,
self_address, self_address,
shared_lane_queue_lengths, shared_lane_queue_lengths,
reply_controller_sender,
); );
websocket::Listener::new(config.get_listening_port()).start(websocket_handler, shutdown); websocket::Listener::new(config.get_listening_port()).start(websocket_handler, shutdown);
@@ -154,13 +148,11 @@ impl SocketClient {
let mut started_client = base_builder.start_base().await?; let mut started_client = base_builder.start_base().await?;
let client_input = started_client.client_input.register_producer(); let client_input = started_client.client_input.register_producer();
let client_output = started_client.client_output.register_consumer(); let client_output = started_client.client_output.register_consumer();
let client_state = started_client.client_state;
Self::start_websocket_listener( Self::start_websocket_listener(
&self.config, &self.config,
client_input, client_input,
client_output, client_output,
client_state,
&self_address, &self_address,
started_client.task_manager.subscribe(), started_client.task_manager.subscribe(),
); );
+15 -19
View File
@@ -8,7 +8,6 @@ use crate::{
}; };
use clap::Args; use clap::Args;
use config::NymConfig; use config::NymConfig;
use crypto::asymmetric::identity;
use nymsphinx::addressing::clients::Recipient; use nymsphinx::addressing::clients::Recipient;
use serde::Serialize; use serde::Serialize;
use std::fmt::Display; use std::fmt::Display;
@@ -22,22 +21,20 @@ pub(crate) struct Init {
/// Id of the gateway we are going to connect to. /// Id of the gateway we are going to connect to.
#[clap(long)] #[clap(long)]
gateway: Option<identity::PublicKey>, gateway: Option<String>,
/// Force register gateway. WARNING: this will overwrite any existing keys for the given id, /// Force register gateway. WARNING: this will overwrite any existing keys for the given id,
/// potentially causing loss of access. /// potentially causing loss of access.
#[clap(long)] #[clap(long)]
force_register_gateway: bool, force_register_gateway: bool,
/// Comma separated list of rest endpoints of the nyxd validators /// Comma separated list of rest endpoints of the nymd validators
#[cfg(feature = "coconut")] #[clap(long)]
#[clap(long, alias = "nymd_validators", value_delimiter = ',')] nymd_validators: Option<String>,
nyxd_urls: Option<Vec<url::Url>>,
/// Comma separated list of rest endpoints of the API validators /// Comma separated list of rest endpoints of the API validators
#[clap(long, alias = "api_validators", value_delimiter = ',')] #[clap(long)]
// the alias here is included for backwards compatibility (1.1.4 and before) api_validators: Option<String>,
nym_apis: Option<Vec<url::Url>>,
/// Whether to not start the websocket /// Whether to not start the websocket
#[clap(long)] #[clap(long)]
@@ -49,11 +46,11 @@ pub(crate) struct Init {
/// Mostly debug-related option to increase default traffic rate so that you would not need to /// Mostly debug-related option to increase default traffic rate so that you would not need to
/// modify config post init /// modify config post init
#[clap(long, hide = true)] #[clap(long, hidden = true)]
fastmode: bool, fastmode: bool,
/// Disable loop cover traffic and the Poisson rate limiter (for debugging only) /// Disable loop cover traffic and the Poisson rate limiter (for debugging only)
#[clap(long, hide = true)] #[clap(long, hidden = true)]
no_cover: bool, no_cover: bool,
/// Set this client to work in a enabled credentials mode that would attempt to use gateway /// Set this client to work in a enabled credentials mode that would attempt to use gateway
@@ -70,14 +67,13 @@ pub(crate) struct Init {
impl From<Init> for OverrideConfig { impl From<Init> for OverrideConfig {
fn from(init_config: Init) -> Self { fn from(init_config: Init) -> Self {
OverrideConfig { OverrideConfig {
nym_apis: init_config.nym_apis, nymd_validators: init_config.nymd_validators,
api_validators: init_config.api_validators,
disable_socket: init_config.disable_socket, disable_socket: init_config.disable_socket,
port: init_config.port, port: init_config.port,
fastmode: init_config.fastmode, fastmode: init_config.fastmode,
no_cover: init_config.no_cover, no_cover: init_config.no_cover,
#[cfg(feature = "coconut")]
nyxd_urls: init_config.nyxd_urls,
#[cfg(feature = "coconut")] #[cfg(feature = "coconut")]
enabled_credentials_mode: init_config.enabled_credentials_mode, enabled_credentials_mode: init_config.enabled_credentials_mode,
} }
@@ -131,16 +127,16 @@ pub(crate) async fn execute(args: &Init) -> Result<(), ClientError> {
let register_gateway = !already_init || user_wants_force_register; let register_gateway = !already_init || user_wants_force_register;
// Attempt to use a user-provided gateway, if possible // Attempt to use a user-provided gateway, if possible
let user_chosen_gateway_id = args.gateway; let user_chosen_gateway_id = args.gateway.clone();
// Load and potentially override config // Load and potentially override config
let mut config = override_config(Config::new(id), OverrideConfig::from(args.clone())); let mut config = override_config(Config::new(id), OverrideConfig::from(args.clone()));
// Setup gateway by either registering a new one, or creating a new config from the selected // Setup gateway by either registering a new one, or creating a new config from the selected
// one but with keys kept, or reusing the gateway configuration. // one but with keys kept, or reusing the gateway configuration.
let gateway = client_core::init::setup_gateway::<Config, _>( let gateway = client_core::init::setup_gateway::<_, Config, _>(
register_gateway, register_gateway,
user_chosen_gateway_id.map(|id| id.to_base58_string()), user_chosen_gateway_id,
config.get_base(), config.get_base(),
) )
.await .await
@@ -156,14 +152,14 @@ pub(crate) async fn execute(args: &Init) -> Result<(), ClientError> {
let address = client_core::init::get_client_address_from_stored_keys(config.get_base())?; let address = client_core::init::get_client_address_from_stored_keys(config.get_base())?;
let init_results = InitResults::new(&config, &address); let init_results = InitResults::new(&config, &address);
println!("{init_results}"); println!("{}", init_results);
// Output summary to a json file, if specified // Output summary to a json file, if specified
if args.output_json { if args.output_json {
client_core::init::output_to_json(&init_results, "client_init_results.json"); client_core::init::output_to_json(&init_results, "client_init_results.json");
} }
println!("\nThe address of this client is: {address}\n"); println!("\nThe address of this client is: {}\n", address);
Ok(()) Ok(())
} }
+81 -40
View File
@@ -1,31 +1,54 @@
// Copyright 2021-2023 - Nym Technologies SA <contact@nymtech.net> // Copyright 2021 - Nym Technologies SA <contact@nymtech.net>
// SPDX-License-Identifier: Apache-2.0 // SPDX-License-Identifier: Apache-2.0
use crate::client::config::{BaseConfig, Config}; use std::error::Error;
use build_information::BinaryBuildInformation;
use crate::client::config::{Config, SocketType};
use clap::CommandFactory; use clap::CommandFactory;
use clap::{Parser, Subcommand}; use clap::{Parser, Subcommand};
use completions::{fig_generate, ArgShell}; use completions::{fig_generate, ArgShell};
use config::OptionalSet;
use lazy_static::lazy_static;
use std::error::Error;
pub(crate) mod init; pub(crate) mod init;
pub(crate) mod run; pub(crate) mod run;
pub(crate) mod upgrade; pub(crate) mod upgrade;
lazy_static! { fn long_version() -> String {
pub static ref PRETTY_BUILD_INFORMATION: String = format!(
BinaryBuildInformation::new(env!("CARGO_PKG_VERSION")).pretty_print(); r#"
{:<20}{}
{:<20}{}
{:<20}{}
{:<20}{}
{:<20}{}
{:<20}{}
{:<20}{}
{:<20}{}
"#,
"Build Timestamp:",
env!("VERGEN_BUILD_TIMESTAMP"),
"Build Version:",
env!("VERGEN_BUILD_SEMVER"),
"Commit SHA:",
env!("VERGEN_GIT_SHA"),
"Commit Date:",
env!("VERGEN_GIT_COMMIT_TIMESTAMP"),
"Commit Branch:",
env!("VERGEN_GIT_BRANCH"),
"rustc Version:",
env!("VERGEN_RUSTC_SEMVER"),
"rustc Channel:",
env!("VERGEN_RUSTC_CHANNEL"),
"cargo Profile:",
env!("VERGEN_CARGO_PROFILE"),
)
} }
// Helper for passing LONG_VERSION to clap fn long_version_static() -> &'static str {
fn pretty_build_info_static() -> &'static str { Box::leak(long_version().into_boxed_str())
&PRETTY_BUILD_INFORMATION
} }
#[derive(Parser)] #[derive(Parser)]
#[clap(author = "Nymtech", version, long_version = pretty_build_info_static(), about)] #[clap(author = "Nymtech", version, long_version = long_version_static(), about)]
pub(crate) struct Cli { pub(crate) struct Cli {
/// Path pointing to an env file that configures the client. /// Path pointing to an env file that configures the client.
#[clap(short, long)] #[clap(short, long)]
@@ -53,14 +76,13 @@ pub(crate) enum Commands {
// Configuration that can be overridden. // Configuration that can be overridden.
pub(crate) struct OverrideConfig { pub(crate) struct OverrideConfig {
nym_apis: Option<Vec<url::Url>>, nymd_validators: Option<String>,
api_validators: Option<String>,
disable_socket: bool, disable_socket: bool,
port: Option<u16>, port: Option<u16>,
fastmode: bool, fastmode: bool,
no_cover: bool, no_cover: bool,
#[cfg(feature = "coconut")]
nyxd_urls: Option<Vec<url::Url>>,
#[cfg(feature = "coconut")] #[cfg(feature = "coconut")]
enabled_credentials_mode: bool, enabled_credentials_mode: bool,
} }
@@ -72,38 +94,57 @@ pub(crate) async fn execute(args: &Cli) -> Result<(), Box<dyn Error + Send + Syn
Commands::Init(m) => init::execute(m).await?, Commands::Init(m) => init::execute(m).await?,
Commands::Run(m) => run::execute(m).await?, Commands::Run(m) => run::execute(m).await?,
Commands::Upgrade(m) => upgrade::execute(m), Commands::Upgrade(m) => upgrade::execute(m),
Commands::Completions(s) => s.generate(&mut Cli::command(), bin_name), Commands::Completions(s) => s.generate(&mut Cli::into_app(), bin_name),
Commands::GenerateFigSpec => fig_generate(&mut Cli::command(), bin_name), Commands::GenerateFigSpec => fig_generate(&mut Cli::into_app(), bin_name),
} }
Ok(()) Ok(())
} }
pub(crate) fn override_config(mut config: Config, args: OverrideConfig) -> Config { pub(crate) fn override_config(mut config: Config, args: OverrideConfig) -> Config {
config = config if let Some(raw_validators) = args.nymd_validators {
.with_disabled_socket(args.disable_socket) config
.with_base(BaseConfig::with_high_default_traffic_volume, args.fastmode) .get_base_mut()
.with_base(BaseConfig::with_disabled_cover_traffic, args.no_cover) .set_custom_validators(config::parse_validators(&raw_validators));
.with_optional(Config::with_port, args.port) } else if std::env::var(network_defaults::var_names::CONFIGURED).is_ok() {
.with_optional_custom_env_ext( let raw_validators = std::env::var(network_defaults::var_names::NYMD_VALIDATOR)
BaseConfig::with_custom_nym_apis, .expect("nymd validator not set");
args.nym_apis, config
network_defaults::var_names::NYM_API, .get_base_mut()
config::parse_urls, .set_custom_validators(config::parse_validators(&raw_validators));
); }
if let Some(raw_validators) = args.api_validators {
config
.get_base_mut()
.set_custom_nym_apis(config::parse_validators(&raw_validators));
} else if std::env::var(network_defaults::var_names::CONFIGURED).is_ok() {
let raw_validators = std::env::var(network_defaults::var_names::API_VALIDATOR)
.expect("api validator not set");
config
.get_base_mut()
.set_custom_nym_apis(config::parse_validators(&raw_validators));
}
if args.disable_socket {
config = config.with_socket(SocketType::None);
}
if let Some(port) = args.port {
config = config.with_port(port);
}
#[cfg(feature = "coconut")] #[cfg(feature = "coconut")]
{ {
config = config if args.enabled_credentials_mode {
.with_optional_custom_env_ext( config.get_base_mut().with_disabled_credentials(false)
BaseConfig::with_custom_nyxd, }
args.nyxd_urls, }
network_defaults::var_names::NYXD,
config::parse_urls, if args.fastmode {
) config.get_base_mut().set_high_default_traffic_volume();
.with_base( }
BaseConfig::with_disabled_credentials,
!args.enabled_credentials_mode, if args.no_cover {
); config.get_base_mut().set_no_cover_traffic();
} }
config config
+11 -16
View File
@@ -1,4 +1,4 @@
// Copyright 2021-2023 - Nym Technologies SA <contact@nymtech.net> // Copyright 2021 - Nym Technologies SA <contact@nymtech.net>
// SPDX-License-Identifier: Apache-2.0 // SPDX-License-Identifier: Apache-2.0
use std::error::Error; use std::error::Error;
@@ -11,7 +11,6 @@ use crate::{
use clap::Args; use clap::Args;
use config::NymConfig; use config::NymConfig;
use crypto::asymmetric::identity;
use log::*; use log::*;
use version_checker::is_minor_version_compatible; use version_checker::is_minor_version_compatible;
@@ -21,20 +20,18 @@ pub(crate) struct Run {
#[clap(long)] #[clap(long)]
id: String, id: String,
/// Comma separated list of rest endpoints of the nyxd validators /// Comma separated list of rest endpoints of the nymd validators
#[cfg(feature = "coconut")] #[clap(long)]
#[clap(long, alias = "nymd_validators", value_delimiter = ',')] nymd_validators: Option<String>,
nyxd_urls: Option<Vec<url::Url>>,
/// Comma separated list of rest endpoints of the API validators /// Comma separated list of rest endpoints of the API validators
#[clap(long, alias = "api_validators", value_delimiter = ',')] #[clap(long)]
// the alias here is included for backwards compatibility (1.1.4 and before) api_validators: Option<String>,
nym_apis: Option<Vec<url::Url>>,
/// Id of the gateway we want to connect to. If overridden, it is user's responsibility to /// Id of the gateway we want to connect to. If overridden, it is user's responsibility to
/// ensure prior registration happened /// ensure prior registration happened
#[clap(long)] #[clap(long)]
gateway: Option<identity::PublicKey>, gateway: Option<String>,
/// Whether to not start the websocket /// Whether to not start the websocket
#[clap(long)] #[clap(long)]
@@ -46,11 +43,11 @@ pub(crate) struct Run {
/// Mostly debug-related option to increase default traffic rate so that you would not need to /// Mostly debug-related option to increase default traffic rate so that you would not need to
/// modify config post init /// modify config post init
#[clap(long, hide = true)] #[clap(long, hidden = true)]
fastmode: bool, fastmode: bool,
/// Disable loop cover traffic and the Poisson rate limiter (for debugging only) /// Disable loop cover traffic and the Poisson rate limiter (for debugging only)
#[clap(long, hide = true)] #[clap(long, hidden = true)]
no_cover: bool, no_cover: bool,
/// Set this client to work in a enabled credentials mode that would attempt to use gateway /// Set this client to work in a enabled credentials mode that would attempt to use gateway
@@ -63,14 +60,12 @@ pub(crate) struct Run {
impl From<Run> for OverrideConfig { impl From<Run> for OverrideConfig {
fn from(run_config: Run) -> Self { fn from(run_config: Run) -> Self {
OverrideConfig { OverrideConfig {
nym_apis: run_config.nym_apis, nymd_validators: run_config.nymd_validators,
api_validators: run_config.api_validators,
disable_socket: run_config.disable_socket, disable_socket: run_config.disable_socket,
port: run_config.port, port: run_config.port,
fastmode: run_config.fastmode, fastmode: run_config.fastmode,
no_cover: run_config.no_cover, no_cover: run_config.no_cover,
#[cfg(feature = "coconut")]
nyxd_urls: run_config.nyxd_urls,
#[cfg(feature = "coconut")] #[cfg(feature = "coconut")]
enabled_credentials_mode: run_config.enabled_credentials_mode, enabled_credentials_mode: run_config.enabled_credentials_mode,
} }
+2 -1
View File
@@ -1,3 +1,4 @@
use client_core::client::replies::reply_storage::fs_backend;
use client_core::error::ClientCoreError; use client_core::error::ClientCoreError;
#[derive(thiserror::Error, Debug)] #[derive(thiserror::Error, Debug)]
@@ -6,7 +7,7 @@ pub enum ClientError {
IoError(#[from] std::io::Error), IoError(#[from] std::io::Error),
#[error("client-core error: {0}")] #[error("client-core error: {0}")]
ClientCoreError(#[from] ClientCoreError), ClientCoreError(#[from] ClientCoreError<fs_backend::Backend>),
#[error("Failed to load config for: {0}")] #[error("Failed to load config for: {0}")]
FailedToLoadConfig(String), FailedToLoadConfig(String),
+1 -1
View File
@@ -18,7 +18,7 @@ async fn main() -> Result<(), Box<dyn Error + Send + Sync>> {
println!("{}", banner()); println!("{}", banner());
let args = commands::Cli::parse(); let args = commands::Cli::parse();
setup_env(args.config_env_file.as_ref()); setup_env(args.config_env_file.clone());
commands::execute(&args).await commands::execute(&args).await
} }
+73 -63
View File
@@ -2,9 +2,8 @@
// SPDX-License-Identifier: Apache-2.0 // SPDX-License-Identifier: Apache-2.0
use client_connections::{ use client_connections::{
ConnectionCommand, ConnectionCommandSender, ConnectionId, LaneQueueLengths, TransmissionLane, ConnectionCommand, ConnectionCommandSender, LaneQueueLengths, TransmissionLane,
}; };
use client_core::client::replies::reply_controller::requests::ReplyControllerSender;
use client_core::client::{ use client_core::client::{
inbound_messages::{InputMessage, InputMessageSender}, inbound_messages::{InputMessage, InputMessageSender},
received_buffer::{ received_buffer::{
@@ -17,9 +16,7 @@ use log::*;
use nymsphinx::addressing::clients::Recipient; use nymsphinx::addressing::clients::Recipient;
use nymsphinx::anonymous_replies::requests::AnonymousSenderTag; use nymsphinx::anonymous_replies::requests::AnonymousSenderTag;
use nymsphinx::receiver::ReconstructedMessage; use nymsphinx::receiver::ReconstructedMessage;
use std::time::Duration;
use tokio::net::TcpStream; use tokio::net::TcpStream;
use tokio::time::Instant;
use tokio_tungstenite::{ use tokio_tungstenite::{
accept_async, accept_async,
tungstenite::{protocol::Message as WsMessage, Error as WsError}, tungstenite::{protocol::Message as WsMessage, Error as WsError},
@@ -44,7 +41,6 @@ pub(crate) struct HandlerBuilder {
buffer_requester: ReceivedBufferRequestSender, buffer_requester: ReceivedBufferRequestSender,
self_full_address: Recipient, self_full_address: Recipient,
lane_queue_lengths: LaneQueueLengths, lane_queue_lengths: LaneQueueLengths,
reply_controller_sender: ReplyControllerSender,
} }
impl HandlerBuilder { impl HandlerBuilder {
@@ -54,7 +50,6 @@ impl HandlerBuilder {
buffer_requester: ReceivedBufferRequestSender, buffer_requester: ReceivedBufferRequestSender,
self_full_address: &Recipient, self_full_address: &Recipient,
lane_queue_lengths: LaneQueueLengths, lane_queue_lengths: LaneQueueLengths,
reply_controller_sender: ReplyControllerSender,
) -> Self { ) -> Self {
Self { Self {
msg_input, msg_input,
@@ -62,7 +57,6 @@ impl HandlerBuilder {
buffer_requester, buffer_requester,
self_full_address: *self_full_address, self_full_address: *self_full_address,
lane_queue_lengths, lane_queue_lengths,
reply_controller_sender,
} }
} }
@@ -76,7 +70,6 @@ impl HandlerBuilder {
socket: None, socket: None,
received_response_type: Default::default(), received_response_type: Default::default(),
lane_queue_lengths: self.lane_queue_lengths.clone(), lane_queue_lengths: self.lane_queue_lengths.clone(),
reply_controller_sender: self.reply_controller_sender.clone(),
} }
} }
} }
@@ -89,7 +82,6 @@ pub(crate) struct Handler {
socket: Option<WebSocketStream<TcpStream>>, socket: Option<WebSocketStream<TcpStream>>,
received_response_type: ReceivedResponseType, received_response_type: ReceivedResponseType,
lane_queue_lengths: LaneQueueLengths, lane_queue_lengths: LaneQueueLengths,
reply_controller_sender: ReplyControllerSender,
} }
impl Drop for Handler { impl Drop for Handler {
@@ -105,48 +97,6 @@ impl Drop for Handler {
} }
impl Handler { impl Handler {
async fn get_lane_queue_length(&self, connection_id: ConnectionId) -> Option<ServerResponse> {
let req_start = Instant::now();
// get the base queue length
// Note that this does _NOT_ take into account the packets that have been received but not
// yet reach `OutQueueControl`, so it might be a tad low.
let conn_lane = TransmissionLane::ConnectionId(connection_id);
let Ok(base_length) = self
.lane_queue_lengths
.lock()
.map(|guard| guard.get(&conn_lane).unwrap_or_default()) else {
// I'd argue we should panic here as this error it not recoverable
error!("The lane queue length lock is poisoned!!");
return None
};
// get the number of pending replies waiting for reply surbs
let reply_queue_length = self
.reply_controller_sender
.get_lane_queue_length(connection_id)
.await;
let queue_length = base_length + reply_queue_length;
let time_taken = req_start.elapsed();
let msg =
format!("it took {time_taken:?} to get lane length for connection {connection_id}. The length is: {queue_length} = {base_length} (already queued up) + {reply_queue_length} (waiting for reply SURBs)");
if time_taken > Duration::from_millis(1) {
info!("{msg}");
} else if time_taken > Duration::from_millis(10) {
warn!("{msg}");
} else if time_taken > Duration::from_millis(50) {
error!("{msg}");
}
Some(ServerResponse::LaneQueueLength {
lane: connection_id,
queue_length,
})
}
async fn handle_send( async fn handle_send(
&mut self, &mut self,
recipient: Recipient, recipient: Recipient,
@@ -171,11 +121,27 @@ impl Handler {
.expect("InputMessageReceiver has stopped receiving!"); .expect("InputMessageReceiver has stopped receiving!");
// Only reply back with a `LaneQueueLength` if the sender providided a connection id // Only reply back with a `LaneQueueLength` if the sender providided a connection id
let TransmissionLane::ConnectionId(connection_id) = lane else { let connection_id = match lane {
return None TransmissionLane::General
| TransmissionLane::ReplySurbRequest
| TransmissionLane::Retransmission
| TransmissionLane::AdditionalReplySurbs => return None,
TransmissionLane::ConnectionId(id) => id,
}; };
self.get_lane_queue_length(connection_id).await // on receiving a send, we reply back the current lane queue length for that connection id.
// Note that this does _NOT_ take into account the packets that have been received but not
// yet reach `OutQueueControl`, so it might be a tad low.
if let Ok(lane_queue_lengths) = self.lane_queue_lengths.lock() {
let queue_length = lane_queue_lengths.get(&lane).unwrap_or(0);
return Some(ServerResponse::LaneQueueLength {
lane: connection_id,
queue_length,
});
}
log::warn!("Failed to get the lane queue length lock, not responding back with the current queue length");
None
} }
async fn handle_send_anonymous( async fn handle_send_anonymous(
@@ -202,11 +168,27 @@ impl Handler {
.expect("InputMessageReceiver has stopped receiving!"); .expect("InputMessageReceiver has stopped receiving!");
// Only reply back with a `LaneQueueLength` if the sender providided a connection id // Only reply back with a `LaneQueueLength` if the sender providided a connection id
let TransmissionLane::ConnectionId(connection_id) = lane else { let connection_id = match lane {
return None TransmissionLane::General
| TransmissionLane::ReplySurbRequest
| TransmissionLane::Retransmission
| TransmissionLane::AdditionalReplySurbs => return None,
TransmissionLane::ConnectionId(id) => id,
}; };
self.get_lane_queue_length(connection_id).await // on receiving a send, we reply back the current lane queue length for that connection id.
// Note that this does _NOT_ take into account the packets that have been received but not
// yet reach `OutQueueControl`, so it might be a tad low.
if let Ok(lane_queue_lengths) = self.lane_queue_lengths.lock() {
let queue_length = lane_queue_lengths.get(&lane).unwrap_or(0);
return Some(ServerResponse::LaneQueueLength {
lane: connection_id,
queue_length,
});
}
log::warn!("Failed to get the lane queue length lock, not responding back with the current queue length");
None
} }
async fn handle_reply( async fn handle_reply(
@@ -229,11 +211,27 @@ impl Handler {
.expect("InputMessageReceiver has stopped receiving!"); .expect("InputMessageReceiver has stopped receiving!");
// Only reply back with a `LaneQueueLength` if the sender providided a connection id // Only reply back with a `LaneQueueLength` if the sender providided a connection id
let TransmissionLane::ConnectionId(connection_id) = lane else { let connection_id = match lane {
return None TransmissionLane::General
| TransmissionLane::ReplySurbRequest
| TransmissionLane::Retransmission
| TransmissionLane::AdditionalReplySurbs => return None,
TransmissionLane::ConnectionId(id) => id,
}; };
self.get_lane_queue_length(connection_id).await // on receiving a send, we reply back the current lane queue length for that connection id.
// Note that this does _NOT_ take into account the packets that have been received but not
// yet reach `OutQueueControl`, so it might be a tad low.
if let Ok(lane_queue_lengths) = self.lane_queue_lengths.lock() {
let queue_length = lane_queue_lengths.get(&lane).unwrap_or(0);
return Some(ServerResponse::LaneQueueLength {
lane: connection_id,
queue_length,
});
}
log::warn!("Failed to get the lane queue length lock, not responding back with the current queue length");
None
} }
fn handle_self_address(&self) -> ServerResponse { fn handle_self_address(&self) -> ServerResponse {
@@ -247,8 +245,20 @@ impl Handler {
None None
} }
async fn handle_get_lane_queue_length(&self, connection_id: u64) -> Option<ServerResponse> { fn handle_get_lane_queue_length(&self, connection_id: u64) -> Option<ServerResponse> {
self.get_lane_queue_length(connection_id).await let Ok(lane_queue_lengths) = self.lane_queue_lengths.lock() else {
log::warn!(
"Failed to get the lane queue length lock, not responding back with the current queue length"
);
return None;
};
let lane = TransmissionLane::ConnectionId(connection_id);
let queue_length = lane_queue_lengths.get(&lane).unwrap_or(0);
Some(ServerResponse::LaneQueueLength {
lane: connection_id,
queue_length,
})
} }
async fn handle_request(&mut self, request: ClientRequest) -> Option<ServerResponse> { async fn handle_request(&mut self, request: ClientRequest) -> Option<ServerResponse> {
@@ -277,7 +287,7 @@ impl Handler {
ClientRequest::SelfAddress => Some(self.handle_self_address()), ClientRequest::SelfAddress => Some(self.handle_self_address()),
ClientRequest::ClosedConnection(id) => self.handle_closed_connection(id), ClientRequest::ClosedConnection(id) => self.handle_closed_connection(id),
ClientRequest::GetLaneQueueLength(id) => self.handle_get_lane_queue_length(id).await, ClientRequest::GetLaneQueueLength(id) => self.handle_get_lane_queue_length(id),
} }
} }
+6 -5
View File
@@ -1,6 +1,6 @@
[package] [package]
name = "nym-socks5-client" name = "nym-socks5-client"
version = "1.1.5" version = "1.1.3"
authors = ["Dave Hrycyszyn <futurechimp@users.noreply.github.com>"] authors = ["Dave Hrycyszyn <futurechimp@users.noreply.github.com>"]
description = "A SOCKS5 localhost proxy that converts incoming messages to Sphinx and sends them to a Nym address" description = "A SOCKS5 localhost proxy that converts incoming messages to Sphinx and sends them to a Nym address"
edition = "2021" edition = "2021"
@@ -11,10 +11,9 @@ name = "nym_socks5"
path = "src/lib.rs" path = "src/lib.rs"
[dependencies] [dependencies]
clap = { version = "4.0", features = ["cargo", "derive"] } clap = { version = "3.2", features = ["cargo", "derive"] }
dirs = "4.0" dirs = "4.0"
futures = "0.3" futures = "0.3"
lazy_static = "1.4.0"
log = "0.4" log = "0.4"
pin-project = "1.0" pin-project = "1.0"
pretty_env_logger = "0.4" pretty_env_logger = "0.4"
@@ -27,7 +26,6 @@ tokio = { version = "1.21.2", features = ["rt-multi-thread", "net", "signal"] }
url = "2.2" url = "2.2"
# internal # internal
build-information = { path = "../../common/build-information" }
client-core = { path = "../client-core", features = ["fs-surb-storage"] } client-core = { path = "../client-core", features = ["fs-surb-storage"] }
client-connections = { path = "../../common/client-connections" } client-connections = { path = "../../common/client-connections" }
coconut-interface = { path = "../../common/coconut-interface", optional = true } coconut-interface = { path = "../../common/coconut-interface", optional = true }
@@ -47,9 +45,12 @@ proxy-helpers = { path = "../../common/socks5/proxy-helpers" }
socks5-requests = { path = "../../common/socks5/requests" } socks5-requests = { path = "../../common/socks5/requests" }
task = { path = "../../common/task" } task = { path = "../../common/task" }
topology = { path = "../../common/topology" } topology = { path = "../../common/topology" }
validator-client = { path = "../../common/client-libs/validator-client", features = ["nyxd-client"] } validator-client = { path = "../../common/client-libs/validator-client", features = ["nymd-client"] }
version-checker = { path = "../../common/version-checker" } version-checker = { path = "../../common/version-checker" }
[features] [features]
coconut = ["coconut-interface", "credentials", "gateway-requests/coconut", "gateway-client/coconut", "credentials/coconut", "client-core/coconut"] coconut = ["coconut-interface", "credentials", "gateway-requests/coconut", "gateway-client/coconut", "credentials/coconut", "client-core/coconut"]
eth = [] eth = []
[build-dependencies]
vergen = { version = "5", default-features = false, features = ["build", "git", "rustc", "cargo"] }
+8
View File
@@ -0,0 +1,8 @@
// Copyright 2021 - Nym Technologies SA <contact@nymtech.net>
// SPDX-License-Identifier: Apache-2.0
use vergen::{vergen, Config};
fn main() {
vergen(Config::default()).expect("failed to extract build metadata")
}
+2 -49
View File
@@ -2,16 +2,13 @@
// SPDX-License-Identifier: Apache-2.0 // SPDX-License-Identifier: Apache-2.0
use crate::client::config::template::config_template; use crate::client::config::template::config_template;
pub use client_core::config::Config as BaseConfig;
pub use client_core::config::MISSING_VALUE; pub use client_core::config::MISSING_VALUE;
use client_core::config::{ClientCoreConfigTrait, DebugConfig}; use client_core::config::{ClientCoreConfigTrait, Config as BaseConfig, DebugConfig};
use config::defaults::DEFAULT_SOCKS5_LISTENING_PORT; use config::defaults::DEFAULT_SOCKS5_LISTENING_PORT;
use config::{NymConfig, OptionalSet}; use config::NymConfig;
use nymsphinx::addressing::clients::Recipient; use nymsphinx::addressing::clients::Recipient;
use serde::{Deserialize, Serialize}; use serde::{Deserialize, Serialize};
use std::fmt::Debug;
use std::path::PathBuf; use std::path::PathBuf;
use std::str::FromStr;
mod template; mod template;
@@ -130,50 +127,6 @@ impl Config {
pub fn get_per_request_surbs(&self) -> u32 { pub fn get_per_request_surbs(&self) -> u32 {
self.socks5_debug.per_request_surbs self.socks5_debug.per_request_surbs
} }
// poor man's 'builder' method
pub fn with_base<F, T>(mut self, f: F, val: T) -> Self
where
F: Fn(BaseConfig<Self>, T) -> BaseConfig<Self>,
{
self.base = f(self.base, val);
self
}
// helper methods to use `OptionalSet` trait. Those are defined due to very... ehm. 'specific' structure of this config
// (plz, lets refactor it)
pub fn with_optional_ext<F, T>(mut self, f: F, val: Option<T>) -> Self
where
F: Fn(BaseConfig<Self>, T) -> BaseConfig<Self>,
{
self.base = self.base.with_optional(f, val);
self
}
pub fn with_optional_env_ext<F, T>(mut self, f: F, val: Option<T>, env_var: &str) -> Self
where
F: Fn(BaseConfig<Self>, T) -> BaseConfig<Self>,
T: FromStr,
<T as FromStr>::Err: Debug,
{
self.base = self.base.with_optional_env(f, val, env_var);
self
}
pub fn with_optional_custom_env_ext<F, T, G>(
mut self,
f: F,
val: Option<T>,
env_var: &str,
parser: G,
) -> Self
where
F: Fn(BaseConfig<Self>, T) -> BaseConfig<Self>,
G: Fn(&str) -> T,
{
self.base = self.base.with_optional_custom_env(f, val, env_var, parser);
self
}
} }
#[derive(Debug, Deserialize, PartialEq, Eq, Serialize)] #[derive(Debug, Deserialize, PartialEq, Eq, Serialize)]
+3 -3
View File
@@ -23,9 +23,9 @@ id = '{{ client.id }}'
# to claim bandwidth without presenting bandwidth credentials. # to claim bandwidth without presenting bandwidth credentials.
disabled_credentials_mode = {{ client.disabled_credentials_mode }} disabled_credentials_mode = {{ client.disabled_credentials_mode }}
# Addresses to nyxd validators via which the client can communicate with the chain. # Addresses to nymd validators via which the client can communicate with the chain.
nyxd_urls = [ validator_urls = [
{{#each client.nyxd_urls }} {{#each client.validator_urls }}
'{{this}}', '{{this}}',
{{/each}} {{/each}}
] ]
+5 -12
View File
@@ -9,7 +9,7 @@ use crate::socks::{
server::SphinxSocksServer, server::SphinxSocksServer,
}; };
use client_core::client::base_client::{ use client_core::client::base_client::{
non_wasm_helpers, BaseClientBuilder, ClientInput, ClientOutput, ClientState, non_wasm_helpers, BaseClientBuilder, ClientInput, ClientOutput,
}; };
use client_core::client::key_manager::KeyManager; use client_core::client::key_manager::KeyManager;
use client_core::config::persistence::key_pathfinder::ClientKeyPathfinder; use client_core::config::persistence::key_pathfinder::ClientKeyPathfinder;
@@ -60,18 +60,18 @@ impl NymClient {
let mut client_config = let mut client_config =
validator_client::Config::try_from_nym_network_details(&details) validator_client::Config::try_from_nym_network_details(&details)
.expect("failed to construct validator client config"); .expect("failed to construct validator client config");
let nyxd_url = config let nymd_url = config
.get_base() .get_base()
.get_validator_endpoints() .get_validator_endpoints()
.pop() .pop()
.expect("No nyxd validator endpoint provided"); .expect("No nymd validator endpoint provided");
let api_url = config let api_url = config
.get_base() .get_base()
.get_nym_api_endpoints() .get_nym_api_endpoints()
.pop() .pop()
.expect("No validator api endpoint provided"); .expect("No validator api endpoint provided");
// overwrite env configuration with config URLs // overwrite env configuration with config URLs
client_config = client_config.with_urls(nyxd_url, api_url); client_config = client_config.with_urls(nymd_url, api_url);
let client = validator_client::Client::new_query(client_config) let client = validator_client::Client::new_query(client_config)
.expect("Could not construct query client"); .expect("Could not construct query client");
let coconut_api_clients = let coconut_api_clients =
@@ -95,7 +95,6 @@ impl NymClient {
config: &Config, config: &Config,
client_input: ClientInput, client_input: ClientInput,
client_output: ClientOutput, client_output: ClientOutput,
client_status: ClientState,
self_address: Recipient, self_address: Recipient,
shutdown: TaskClient, shutdown: TaskClient,
) { ) {
@@ -109,14 +108,10 @@ impl NymClient {
} = client_input; } = client_input;
let ClientOutput { let ClientOutput {
shared_lane_queue_lengths,
received_buffer_request_sender, received_buffer_request_sender,
} = client_output; } = client_output;
let ClientState {
shared_lane_queue_lengths,
reply_controller_sender: _,
} = client_status;
let authenticator = Authenticator::new(auth_methods, allowed_users); let authenticator = Authenticator::new(auth_methods, allowed_users);
let mut sphinx_socks = SphinxSocksServer::new( let mut sphinx_socks = SphinxSocksServer::new(
config.get_listening_port(), config.get_listening_port(),
@@ -223,13 +218,11 @@ impl NymClient {
let mut started_client = base_builder.start_base().await?; let mut started_client = base_builder.start_base().await?;
let client_input = started_client.client_input.register_producer(); let client_input = started_client.client_input.register_producer();
let client_output = started_client.client_output.register_consumer(); let client_output = started_client.client_output.register_consumer();
let client_state = started_client.client_state;
Self::start_socks5_listener( Self::start_socks5_listener(
&self.config, &self.config,
client_input, client_input,
client_output, client_output,
client_state,
self_address, self_address,
started_client.task_manager.subscribe(), started_client.task_manager.subscribe(),
); );
+18 -24
View File
@@ -8,7 +8,6 @@ use crate::{
}; };
use clap::Args; use clap::Args;
use config::NymConfig; use config::NymConfig;
use crypto::asymmetric::identity;
use nymsphinx::addressing::clients::Recipient; use nymsphinx::addressing::clients::Recipient;
use serde::Serialize; use serde::Serialize;
use std::fmt::Display; use std::fmt::Display;
@@ -22,35 +21,32 @@ pub(crate) struct Init {
/// Address of the socks5 provider to send messages to. /// Address of the socks5 provider to send messages to.
#[clap(long)] #[clap(long)]
provider: Recipient, provider: String,
/// Specifies whether this client is going to use an anonymous sender tag for communication with the service provider. /// Specifies whether this client is going to use an anonymous sender tag for communication with the service provider.
/// While this is going to hide its actual address information, it will make the actual communication /// While this is going to hide its actual address information, it will make the actual communication
/// slower and consume nearly double the bandwidth as it will require sending reply SURBs. /// slower and consume nearly double the bandwidth as it will require sending reply SURBs.
/// ///
/// Note that some service providers might not support this. /// Note that some service providers might not support this.
// the alias here is included for backwards compatibility (1.1.4 and before) #[clap(long)]
#[clap(long, alias = "use_anonymous_sender_tag")] use_anonymous_sender_tag: bool,
use_reply_surbs: bool,
/// Id of the gateway we are going to connect to. /// Id of the gateway we are going to connect to.
#[clap(long)] #[clap(long)]
gateway: Option<identity::PublicKey>, gateway: Option<String>,
/// Force register gateway. WARNING: this will overwrite any existing keys for the given id, /// Force register gateway. WARNING: this will overwrite any existing keys for the given id,
/// potentially causing loss of access. /// potentially causing loss of access.
#[clap(long)] #[clap(long)]
force_register_gateway: bool, force_register_gateway: bool,
/// Comma separated list of rest endpoints of the nyxd validators /// Comma separated list of rest endpoints of the nymd validators
#[cfg(feature = "coconut")] #[clap(long)]
#[clap(long, alias = "nymd_validators", value_delimiter = ',')] nymd_validators: Option<String>,
nyxd_urls: Option<Vec<url::Url>>,
/// Comma separated list of rest endpoints of the API validators /// Comma separated list of rest endpoints of the API validators
#[clap(long, alias = "api_validators", value_delimiter = ',')] #[clap(long)]
// the alias here is included for backwards compatibility (1.1.4 and before) api_validators: Option<String>,
nym_apis: Option<Vec<url::Url>>,
/// Port for the socket to listen on in all subsequent runs /// Port for the socket to listen on in all subsequent runs
#[clap(short, long)] #[clap(short, long)]
@@ -58,11 +54,11 @@ pub(crate) struct Init {
/// Mostly debug-related option to increase default traffic rate so that you would not need to /// Mostly debug-related option to increase default traffic rate so that you would not need to
/// modify config post init /// modify config post init
#[clap(long, hide = true)] #[clap(long, hidden = true)]
fastmode: bool, fastmode: bool,
/// Disable loop cover traffic and the Poisson rate limiter (for debugging only) /// Disable loop cover traffic and the Poisson rate limiter (for debugging only)
#[clap(long, hide = true)] #[clap(long, hidden = true)]
no_cover: bool, no_cover: bool,
/// Set this client to work in a enabled credentials mode that would attempt to use gateway /// Set this client to work in a enabled credentials mode that would attempt to use gateway
@@ -79,14 +75,12 @@ pub(crate) struct Init {
impl From<Init> for OverrideConfig { impl From<Init> for OverrideConfig {
fn from(init_config: Init) -> Self { fn from(init_config: Init) -> Self {
OverrideConfig { OverrideConfig {
nym_apis: init_config.nym_apis, nymd_validators: init_config.nymd_validators,
api_validators: init_config.api_validators,
port: init_config.port, port: init_config.port,
use_anonymous_replies: init_config.use_reply_surbs, use_anonymous_sender_tag: init_config.use_anonymous_sender_tag,
fastmode: init_config.fastmode, fastmode: init_config.fastmode,
no_cover: init_config.no_cover, no_cover: init_config.no_cover,
#[cfg(feature = "coconut")]
nyxd_urls: init_config.nyxd_urls,
#[cfg(feature = "coconut")] #[cfg(feature = "coconut")]
enabled_credentials_mode: init_config.enabled_credentials_mode, enabled_credentials_mode: init_config.enabled_credentials_mode,
} }
@@ -141,19 +135,19 @@ pub(crate) async fn execute(args: &Init) -> Result<(), Socks5ClientError> {
let register_gateway = !already_init || user_wants_force_register; let register_gateway = !already_init || user_wants_force_register;
// Attempt to use a user-provided gateway, if possible // Attempt to use a user-provided gateway, if possible
let user_chosen_gateway_id = args.gateway; let user_chosen_gateway_id = args.gateway.clone();
// Load and potentially override config // Load and potentially override config
let mut config = override_config( let mut config = override_config(
Config::new(id, &provider_address.to_string()), Config::new(id, provider_address),
OverrideConfig::from(args.clone()), OverrideConfig::from(args.clone()),
); );
// Setup gateway by either registering a new one, or creating a new config from the selected // Setup gateway by either registering a new one, or creating a new config from the selected
// one but with keys kept, or reusing the gateway configuration. // one but with keys kept, or reusing the gateway configuration.
let gateway = client_core::init::setup_gateway::<Config, _>( let gateway = client_core::init::setup_gateway::<_, Config, _>(
register_gateway, register_gateway,
user_chosen_gateway_id.map(|id| id.to_base58_string()), user_chosen_gateway_id,
config.get_base(), config.get_base(),
) )
.await .await
+79 -41
View File
@@ -1,31 +1,55 @@
// Copyright 2021-2023 - Nym Technologies SA <contact@nymtech.net> // Copyright 2021 - Nym Technologies SA <contact@nymtech.net>
// SPDX-License-Identifier: Apache-2.0 // SPDX-License-Identifier: Apache-2.0
use crate::client::config::{BaseConfig, Config}; use std::error::Error;
use build_information::BinaryBuildInformation;
use crate::client::config::Config;
use clap::CommandFactory; use clap::CommandFactory;
use clap::{Parser, Subcommand}; use clap::{Parser, Subcommand};
use completions::{fig_generate, ArgShell}; use completions::{fig_generate, ArgShell};
use config::OptionalSet; use config::parse_validators;
use lazy_static::lazy_static;
use std::error::Error;
pub mod init; pub mod init;
pub(crate) mod run; pub(crate) mod run;
pub(crate) mod upgrade; pub(crate) mod upgrade;
lazy_static! { fn long_version() -> String {
pub static ref PRETTY_BUILD_INFORMATION: String = format!(
BinaryBuildInformation::new(env!("CARGO_PKG_VERSION")).pretty_print(); r#"
{:<20}{}
{:<20}{}
{:<20}{}
{:<20}{}
{:<20}{}
{:<20}{}
{:<20}{}
{:<20}{}
"#,
"Build Timestamp:",
env!("VERGEN_BUILD_TIMESTAMP"),
"Build Version:",
env!("VERGEN_BUILD_SEMVER"),
"Commit SHA:",
env!("VERGEN_GIT_SHA"),
"Commit Date:",
env!("VERGEN_GIT_COMMIT_TIMESTAMP"),
"Commit Branch:",
env!("VERGEN_GIT_BRANCH"),
"rustc Version:",
env!("VERGEN_RUSTC_SEMVER"),
"rustc Channel:",
env!("VERGEN_RUSTC_CHANNEL"),
"cargo Profile:",
env!("VERGEN_CARGO_PROFILE"),
)
} }
// Helper for passing LONG_VERSION to clap fn long_version_static() -> &'static str {
fn pretty_build_info_static() -> &'static str { Box::leak(long_version().into_boxed_str())
&PRETTY_BUILD_INFORMATION
} }
#[derive(Parser)] #[derive(Parser)]
#[clap(author = "Nymtech", version, long_version = pretty_build_info_static(), about)] #[clap(author = "Nymtech", version, long_version = long_version_static(), about)]
pub(crate) struct Cli { pub(crate) struct Cli {
/// Path pointing to an env file that configures the client. /// Path pointing to an env file that configures the client.
#[clap(short, long)] #[clap(short, long)]
@@ -55,14 +79,13 @@ pub(crate) enum Commands {
// Configuration that can be overridden. // Configuration that can be overridden.
pub(crate) struct OverrideConfig { pub(crate) struct OverrideConfig {
nym_apis: Option<Vec<url::Url>>, nymd_validators: Option<String>,
api_validators: Option<String>,
port: Option<u16>, port: Option<u16>,
use_anonymous_replies: bool, use_anonymous_sender_tag: bool,
fastmode: bool, fastmode: bool,
no_cover: bool, no_cover: bool,
#[cfg(feature = "coconut")]
nyxd_urls: Option<Vec<url::Url>>,
#[cfg(feature = "coconut")] #[cfg(feature = "coconut")]
enabled_credentials_mode: bool, enabled_credentials_mode: bool,
} }
@@ -74,38 +97,53 @@ pub(crate) async fn execute(args: &Cli) -> Result<(), Box<dyn Error + Send + Syn
Commands::Init(m) => init::execute(m).await?, Commands::Init(m) => init::execute(m).await?,
Commands::Run(m) => run::execute(m).await?, Commands::Run(m) => run::execute(m).await?,
Commands::Upgrade(m) => upgrade::execute(m), Commands::Upgrade(m) => upgrade::execute(m),
Commands::Completions(s) => s.generate(&mut Cli::command(), bin_name), Commands::Completions(s) => s.generate(&mut Cli::into_app(), bin_name),
Commands::GenerateFigSpec => fig_generate(&mut Cli::command(), bin_name), Commands::GenerateFigSpec => fig_generate(&mut Cli::into_app(), bin_name),
} }
Ok(()) Ok(())
} }
pub(crate) fn override_config(mut config: Config, args: OverrideConfig) -> Config { pub(crate) fn override_config(mut config: Config, args: OverrideConfig) -> Config {
config = config if let Some(raw_validators) = args.nymd_validators {
.with_base(BaseConfig::with_high_default_traffic_volume, args.fastmode) config
.with_base(BaseConfig::with_disabled_cover_traffic, args.no_cover) .get_base_mut()
.with_anonymous_replies(args.use_anonymous_replies) .set_custom_validators(parse_validators(&raw_validators));
.with_optional(Config::with_port, args.port) } else if let Ok(raw_validators) = std::env::var(network_defaults::var_names::NYMD_VALIDATOR) {
.with_optional_custom_env_ext( config
BaseConfig::with_custom_nym_apis, .get_base_mut()
args.nym_apis, .set_custom_validators(parse_validators(&raw_validators));
network_defaults::var_names::NYM_API, }
config::parse_urls, if let Some(raw_validators) = args.api_validators {
); config
.get_base_mut()
.set_custom_nym_apis(parse_validators(&raw_validators));
} else if let Ok(raw_validators) = std::env::var(network_defaults::var_names::API_VALIDATOR) {
config
.get_base_mut()
.set_custom_nym_apis(parse_validators(&raw_validators));
}
if args.use_anonymous_sender_tag {
config = config.with_anonymous_replies(true)
}
if let Some(port) = args.port {
config = config.with_port(port);
}
#[cfg(feature = "coconut")] #[cfg(feature = "coconut")]
{ {
config = config if args.enabled_credentials_mode {
.with_optional_custom_env_ext( config.get_base_mut().with_disabled_credentials(false)
BaseConfig::with_custom_nyxd, }
args.nyxd_urls, }
network_defaults::var_names::NYXD,
config::parse_urls, if args.fastmode {
) config.get_base_mut().set_high_default_traffic_volume();
.with_base( }
BaseConfig::with_disabled_credentials,
!args.enabled_credentials_mode, if args.no_cover {
); config.get_base_mut().set_no_cover_traffic();
} }
config config
+14 -20
View File
@@ -9,9 +9,7 @@ use crate::{
use clap::Args; use clap::Args;
use config::NymConfig; use config::NymConfig;
use crypto::asymmetric::identity;
use log::*; use log::*;
use nymsphinx::addressing::clients::Recipient;
use version_checker::is_minor_version_compatible; use version_checker::is_minor_version_compatible;
#[derive(Args, Clone)] #[derive(Args, Clone)]
@@ -29,27 +27,25 @@ pub(crate) struct Run {
/// slower and consume nearly double the bandwidth as it will require sending reply SURBs. /// slower and consume nearly double the bandwidth as it will require sending reply SURBs.
/// ///
/// Note that some service providers might not support this. /// Note that some service providers might not support this.
// the alias here is included for backwards compatibility (1.1.4 and before) #[clap(long)]
#[clap(long, alias = "use_anonymous_sender_tag")] use_anonymous_sender_tag: bool,
use_anonymous_replies: bool,
/// Address of the socks5 provider to send messages to. /// Address of the socks5 provider to send messages to.
#[clap(long)] #[clap(long)]
provider: Option<Recipient>, provider: Option<String>,
/// Id of the gateway we want to connect to. If overridden, it is user's responsibility to /// Id of the gateway we want to connect to. If overridden, it is user's responsibility to
/// ensure prior registration happened /// ensure prior registration happened
#[clap(long)] #[clap(long)]
gateway: Option<identity::PublicKey>, gateway: Option<String>,
/// Comma separated list of rest endpoints of the nyxd validators /// Comma separated list of rest endpoints of the nymd validators
#[cfg(feature = "coconut")] #[clap(long)]
#[clap(long, alias = "nymd_validators", value_delimiter = ',')] nymd_validators: Option<String>,
nyxd_urls: Option<Vec<url::Url>>,
/// Comma separated list of rest endpoints of the Nym APIs /// Comma separated list of rest endpoints of the Nym APIs
#[clap(long, value_delimiter = ',')] #[clap(long)]
nym_apis: Option<Vec<url::Url>>, nym_apis: Option<String>,
/// Port for the socket to listen on /// Port for the socket to listen on
#[clap(short, long)] #[clap(short, long)]
@@ -57,11 +53,11 @@ pub(crate) struct Run {
/// Mostly debug-related option to increase default traffic rate so that you would not need to /// Mostly debug-related option to increase default traffic rate so that you would not need to
/// modify config post init /// modify config post init
#[clap(long, hide = true)] #[clap(long, hidden = true)]
fastmode: bool, fastmode: bool,
/// Disable loop cover traffic and the Poisson rate limiter (for debugging only) /// Disable loop cover traffic and the Poisson rate limiter (for debugging only)
#[clap(long, hide = true)] #[clap(long, hidden = true)]
no_cover: bool, no_cover: bool,
/// Set this client to work in a enabled credentials mode that would attempt to use gateway /// Set this client to work in a enabled credentials mode that would attempt to use gateway
@@ -74,14 +70,12 @@ pub(crate) struct Run {
impl From<Run> for OverrideConfig { impl From<Run> for OverrideConfig {
fn from(run_config: Run) -> Self { fn from(run_config: Run) -> Self {
OverrideConfig { OverrideConfig {
nym_apis: run_config.nym_apis, nymd_validators: run_config.nymd_validators,
api_validators: run_config.nym_apis,
port: run_config.port, port: run_config.port,
use_anonymous_replies: run_config.use_anonymous_replies, use_anonymous_sender_tag: run_config.use_anonymous_sender_tag,
fastmode: run_config.fastmode, fastmode: run_config.fastmode,
no_cover: run_config.no_cover, no_cover: run_config.no_cover,
#[cfg(feature = "coconut")]
nyxd_urls: run_config.nyxd_urls,
#[cfg(feature = "coconut")] #[cfg(feature = "coconut")]
enabled_credentials_mode: run_config.enabled_credentials_mode, enabled_credentials_mode: run_config.enabled_credentials_mode,
} }
+2 -1
View File
@@ -1,4 +1,5 @@
use crate::socks::types::SocksProxyError; use crate::socks::types::SocksProxyError;
use client_core::client::replies::reply_storage::fs_backend;
use client_core::error::ClientCoreError; use client_core::error::ClientCoreError;
use socks5_requests::ConnectionId; use socks5_requests::ConnectionId;
@@ -8,7 +9,7 @@ pub enum Socks5ClientError {
IoError(#[from] std::io::Error), IoError(#[from] std::io::Error),
#[error("client-core error: {0}")] #[error("client-core error: {0}")]
ClientCoreError(#[from] ClientCoreError), ClientCoreError(#[from] ClientCoreError<fs_backend::Backend>),
#[error("SOCKS proxy error")] #[error("SOCKS proxy error")]
SocksProxyError(SocksProxyError), SocksProxyError(SocksProxyError),
+1 -1
View File
@@ -18,7 +18,7 @@ async fn main() -> Result<(), Box<dyn Error + Send + Sync>> {
println!("{}", banner()); println!("{}", banner());
let args = commands::Cli::parse(); let args = commands::Cli::parse();
setup_env(args.config_env_file.as_ref()); setup_env(args.config_env_file.clone());
commands::execute(&args).await commands::execute(&args).await
} }
+6 -1
View File
@@ -1,3 +1,5 @@
use std::time::Duration;
use futures::channel::mpsc; use futures::channel::mpsc;
use futures::StreamExt; use futures::StreamExt;
use log::*; use log::*;
@@ -114,7 +116,10 @@ impl MixnetResponseListener {
} }
} }
} }
self.shutdown.recv_timeout().await; #[cfg(not(target_arch = "wasm32"))]
tokio::time::timeout(Duration::from_secs(5), self.shutdown.recv())
.await
.expect("Task stopped without shutdown called");
log::debug!("MixnetResponseListener: Exiting"); log::debug!("MixnetResponseListener: Exiting");
} }
} }
+14 -14
View File
@@ -85,7 +85,7 @@ export default class ValidatorClient implements INymClient {
static async connect( static async connect(
mnemonic: string, mnemonic: string,
nyxdUrl: string, nymdUrl: string,
nymApiUrl: string, nymApiUrl: string,
prefix: string, prefix: string,
mixnetContract: string, mixnetContract: string,
@@ -94,19 +94,19 @@ export default class ValidatorClient implements INymClient {
): Promise<ValidatorClient> { ): Promise<ValidatorClient> {
const wallet = await ValidatorClient.buildWallet(mnemonic, prefix); const wallet = await ValidatorClient.buildWallet(mnemonic, prefix);
const signingClient = await SigningClient.connectWithNymSigner(wallet, nyxdUrl, nymApiUrl, prefix, denom); const signingClient = await SigningClient.connectWithNymSigner(wallet, nymdUrl, nymApiUrl, prefix, denom);
return new ValidatorClient(signingClient, prefix, mixnetContract, vestingContract, denom); return new ValidatorClient(signingClient, prefix, mixnetContract, vestingContract, denom);
} }
static async connectForQuery( static async connectForQuery(
nyxdUrl: string, nymdUrl: string,
nymApiUrl: string, nymApiUrl: string,
prefix: string, prefix: string,
mixnetContract: string, mixnetContract: string,
vestingContract: string, vestingContract: string,
denom: string, denom: string,
): Promise<ValidatorClient> { ): Promise<ValidatorClient> {
const queryClient = await QueryClient.connectWithNym(nyxdUrl, nymApiUrl); const queryClient = await QueryClient.connectWithNym(nymdUrl, nymApiUrl);
return new ValidatorClient(queryClient, prefix, mixnetContract, vestingContract, denom); return new ValidatorClient(queryClient, prefix, mixnetContract, vestingContract, denom);
} }
@@ -191,11 +191,11 @@ export default class ValidatorClient implements INymClient {
return this.client.getIntervalRewardPercent(this.mixnetContract); return this.client.getIntervalRewardPercent(this.mixnetContract);
} }
public async getAllNyxdMixnodes(): Promise<MixNodeBond[]> { public async getAllNymdMixnodes(): Promise<MixNodeBond[]> {
let mixNodes: MixNodeBond[] = []; let mixNodes: MixNodeBond[] = [];
const limit = 50; const limit = 50;
let startAfter; let startAfter;
for (; ;) { for (;;) {
// eslint-disable-next-line no-await-in-loop // eslint-disable-next-line no-await-in-loop
const pagedResponse: PagedMixnodeResponse = await this.client.getMixNodesPaged(this.mixnetContract, limit); const pagedResponse: PagedMixnodeResponse = await this.client.getMixNodesPaged(this.mixnetContract, limit);
mixNodes = mixNodes.concat(pagedResponse.nodes); mixNodes = mixNodes.concat(pagedResponse.nodes);
@@ -209,11 +209,11 @@ export default class ValidatorClient implements INymClient {
return mixNodes; return mixNodes;
} }
public async getAllNyxdGateways(): Promise<GatewayBond[]> { public async getAllNymdGateways(): Promise<GatewayBond[]> {
let gateways: GatewayBond[] = []; let gateways: GatewayBond[] = [];
const limit = 50; const limit = 50;
let startAfter; let startAfter;
for (; ;) { for (;;) {
// eslint-disable-next-line no-await-in-loop // eslint-disable-next-line no-await-in-loop
const pagedResponse: PagedGatewayResponse = await this.client.getGatewaysPaged(this.mixnetContract, limit); const pagedResponse: PagedGatewayResponse = await this.client.getGatewaysPaged(this.mixnetContract, limit);
gateways = gateways.concat(pagedResponse.nodes); gateways = gateways.concat(pagedResponse.nodes);
@@ -232,11 +232,11 @@ export default class ValidatorClient implements INymClient {
* *
* @param mixIdentity identity of the node to which the delegation was sent * @param mixIdentity identity of the node to which the delegation was sent
*/ */
public async getAllNyxdSingleMixnodeDelegations(mixIdentity: string): Promise<Delegation[]> { public async getAllNymdSingleMixnodeDelegations(mixIdentity: string): Promise<Delegation[]> {
let delegations: Delegation[] = []; let delegations: Delegation[] = [];
const limit = 250; const limit = 250;
let startAfter; let startAfter;
for (; ;) { for (;;) {
// eslint-disable-next-line no-await-in-loop // eslint-disable-next-line no-await-in-loop
const pagedResponse: PagedMixDelegationsResponse = await this.client.getMixNodeDelegationsPaged( const pagedResponse: PagedMixDelegationsResponse = await this.client.getMixNodeDelegationsPaged(
this.mixnetContract, this.mixnetContract,
@@ -255,11 +255,11 @@ export default class ValidatorClient implements INymClient {
return delegations; return delegations;
} }
public async getAllNyxdDelegatorDelegations(delegator: string): Promise<Delegation[]> { public async getAllNymdDelegatorDelegations(delegator: string): Promise<Delegation[]> {
let delegations: Delegation[] = []; let delegations: Delegation[] = [];
const limit = 250; const limit = 250;
let startAfter; let startAfter;
for (; ;) { for (;;) {
// eslint-disable-next-line no-await-in-loop // eslint-disable-next-line no-await-in-loop
const pagedResponse: PagedDelegatorDelegationsResponse = await this.client.getDelegatorDelegationsPaged( const pagedResponse: PagedDelegatorDelegationsResponse = await this.client.getDelegatorDelegationsPaged(
this.mixnetContract, this.mixnetContract,
@@ -278,11 +278,11 @@ export default class ValidatorClient implements INymClient {
return delegations; return delegations;
} }
public async getAllNyxdNetworkDelegations(): Promise<Delegation[]> { public async getAllNymdNetworkDelegations(): Promise<Delegation[]> {
let delegations: Delegation[] = []; let delegations: Delegation[] = [];
const limit = 250; const limit = 250;
let startAfter; let startAfter;
for (; ;) { for (;;) {
// eslint-disable-next-line no-await-in-loop // eslint-disable-next-line no-await-in-loop
const pagedResponse: PagedAllDelegationsResponse = await this.client.getAllNetworkDelegationsPaged( const pagedResponse: PagedAllDelegationsResponse = await this.client.getAllNetworkDelegationsPaged(
this.mixnetContract, this.mixnetContract,
@@ -5,7 +5,7 @@
import { JsonObject } from '@cosmjs/cosmwasm-stargate'; import { JsonObject } from '@cosmjs/cosmwasm-stargate';
// eslint-disable-next-line import/no-cycle // eslint-disable-next-line import/no-cycle
import { INyxdQuery } from './query-client'; import { INymdQuery } from './query-client';
import { import {
ContractStateParams, ContractStateParams,
Delegation, Delegation,
@@ -25,7 +25,7 @@ interface SmartContractQuery {
queryContractSmart(address: string, queryMsg: Record<string, unknown>): Promise<JsonObject>; queryContractSmart(address: string, queryMsg: Record<string, unknown>): Promise<JsonObject>;
} }
export default class NyxdQuerier implements INyxdQuery { export default class NymdQuerier implements INymdQuery {
client: SmartContractQuery; client: SmartContractQuery;
constructor(client: SmartContractQuery) { constructor(client: SmartContractQuery) {
+23 -23
View File
@@ -12,7 +12,7 @@ import {
} from '@cosmjs/stargate'; } from '@cosmjs/stargate';
import { Code, CodeDetails, Contract, ContractCodeHistoryEntry } from '@cosmjs/cosmwasm-stargate/build/cosmwasmclient'; import { Code, CodeDetails, Contract, ContractCodeHistoryEntry } from '@cosmjs/cosmwasm-stargate/build/cosmwasmclient';
// eslint-disable-next-line import/no-cycle // eslint-disable-next-line import/no-cycle
import NyxdQuerier from './nyxd-querier'; import NymdQuerier from './nymd-querier';
import { import {
ContractStateParams, ContractStateParams,
Delegation, Delegation,
@@ -52,7 +52,7 @@ export interface ICosmWasmQuery {
queryContractSmart(address: string, queryMsg: Record<string, unknown>): Promise<JsonObject>; queryContractSmart(address: string, queryMsg: Record<string, unknown>): Promise<JsonObject>;
} }
export interface INyxdQuery { export interface INymdQuery {
// nym-specific implemented inside NymQuerier // nym-specific implemented inside NymQuerier
getContractVersion(mixnetContractAddress: string): Promise<MixnetContractVersion>; getContractVersion(mixnetContractAddress: string): Promise<MixnetContractVersion>;
@@ -93,46 +93,46 @@ export interface INyxdQuery {
): Promise<RewardingStatus>; ): Promise<RewardingStatus>;
} }
export interface IQueryClient extends ICosmWasmQuery, INyxdQuery, INymApiQuery { } export interface IQueryClient extends ICosmWasmQuery, INymdQuery, INymApiQuery { }
export default class QueryClient extends CosmWasmClient implements IQueryClient { export default class QueryClient extends CosmWasmClient implements IQueryClient {
private nyxdQuerier: NyxdQuerier; private nymdQuerier: NymdQuerier;
private nymApiQuerier: NymApiQuerier; private nymApiQuerier: NymApiQuerier;
private constructor(tmClient: Tendermint34Client, nymApiUrl: string) { private constructor(tmClient: Tendermint34Client, nymApiUrl: string) {
super(tmClient); super(tmClient);
this.nyxdQuerier = new NyxdQuerier(this); this.nymdQuerier = new NymdQuerier(this);
this.nymApiQuerier = new NymApiQuerier(nymApiUrl); this.nymApiQuerier = new NymApiQuerier(nymApiUrl);
} }
public static async connectWithNym(nyxdUrl: string, nymApiUrl: string): Promise<QueryClient> { public static async connectWithNym(nymdUrl: string, nymApiUrl: string): Promise<QueryClient> {
const tmClient = await Tendermint34Client.connect(nyxdUrl); const tmClient = await Tendermint34Client.connect(nymdUrl);
return new QueryClient(tmClient, nymApiUrl); return new QueryClient(tmClient, nymApiUrl);
} }
getContractVersion(mixnetContractAddress: string): Promise<MixnetContractVersion> { getContractVersion(mixnetContractAddress: string): Promise<MixnetContractVersion> {
return this.nyxdQuerier.getContractVersion(mixnetContractAddress); return this.nymdQuerier.getContractVersion(mixnetContractAddress);
} }
getMixNodesPaged(mixnetContractAddress: string, limit?: number, startAfter?: string): Promise<PagedMixnodeResponse> { getMixNodesPaged(mixnetContractAddress: string, limit?: number, startAfter?: string): Promise<PagedMixnodeResponse> {
return this.nyxdQuerier.getMixNodesPaged(mixnetContractAddress, limit, startAfter); return this.nymdQuerier.getMixNodesPaged(mixnetContractAddress, limit, startAfter);
} }
getGatewaysPaged(mixnetContractAddress: string, limit?: number, startAfter?: string): Promise<PagedGatewayResponse> { getGatewaysPaged(mixnetContractAddress: string, limit?: number, startAfter?: string): Promise<PagedGatewayResponse> {
return this.nyxdQuerier.getGatewaysPaged(mixnetContractAddress, limit, startAfter); return this.nymdQuerier.getGatewaysPaged(mixnetContractAddress, limit, startAfter);
} }
ownsMixNode(mixnetContractAddress: string, address: string): Promise<MixOwnershipResponse> { ownsMixNode(mixnetContractAddress: string, address: string): Promise<MixOwnershipResponse> {
return this.nyxdQuerier.ownsMixNode(mixnetContractAddress, address); return this.nymdQuerier.ownsMixNode(mixnetContractAddress, address);
} }
ownsGateway(mixnetContractAddress: string, address: string): Promise<GatewayOwnershipResponse> { ownsGateway(mixnetContractAddress: string, address: string): Promise<GatewayOwnershipResponse> {
return this.nyxdQuerier.ownsGateway(mixnetContractAddress, address); return this.nymdQuerier.ownsGateway(mixnetContractAddress, address);
} }
getStateParams(mixnetContractAddress: string): Promise<ContractStateParams> { getStateParams(mixnetContractAddress: string): Promise<ContractStateParams> {
return this.nyxdQuerier.getStateParams(mixnetContractAddress); return this.nymdQuerier.getStateParams(mixnetContractAddress);
} }
getAllNetworkDelegationsPaged( getAllNetworkDelegationsPaged(
@@ -140,7 +140,7 @@ export default class QueryClient extends CosmWasmClient implements IQueryClient
limit?: number, limit?: number,
startAfter?: [string, string], startAfter?: [string, string],
): Promise<PagedAllDelegationsResponse> { ): Promise<PagedAllDelegationsResponse> {
return this.nyxdQuerier.getAllNetworkDelegationsPaged(mixnetContractAddress, limit, startAfter); return this.nymdQuerier.getAllNetworkDelegationsPaged(mixnetContractAddress, limit, startAfter);
} }
getMixNodeDelegationsPaged( getMixNodeDelegationsPaged(
@@ -149,7 +149,7 @@ export default class QueryClient extends CosmWasmClient implements IQueryClient
limit?: number, limit?: number,
startAfter?: string, startAfter?: string,
): Promise<PagedMixDelegationsResponse> { ): Promise<PagedMixDelegationsResponse> {
return this.nyxdQuerier.getMixNodeDelegationsPaged(mixnetContractAddress, mixIdentity, limit, startAfter); return this.nymdQuerier.getMixNodeDelegationsPaged(mixnetContractAddress, mixIdentity, limit, startAfter);
} }
getDelegatorDelegationsPaged( getDelegatorDelegationsPaged(
@@ -158,31 +158,31 @@ export default class QueryClient extends CosmWasmClient implements IQueryClient
limit?: number, limit?: number,
startAfter?: string, startAfter?: string,
): Promise<PagedDelegatorDelegationsResponse> { ): Promise<PagedDelegatorDelegationsResponse> {
return this.nyxdQuerier.getDelegatorDelegationsPaged(mixnetContractAddress, delegator, limit, startAfter); return this.nymdQuerier.getDelegatorDelegationsPaged(mixnetContractAddress, delegator, limit, startAfter);
} }
getDelegationDetails(mixnetContractAddress: string, mixIdentity: string, delegator: string): Promise<Delegation> { getDelegationDetails(mixnetContractAddress: string, mixIdentity: string, delegator: string): Promise<Delegation> {
return this.nyxdQuerier.getDelegationDetails(mixnetContractAddress, mixIdentity, delegator); return this.nymdQuerier.getDelegationDetails(mixnetContractAddress, mixIdentity, delegator);
} }
getLayerDistribution(mixnetContractAddress: string): Promise<LayerDistribution> { getLayerDistribution(mixnetContractAddress: string): Promise<LayerDistribution> {
return this.nyxdQuerier.getLayerDistribution(mixnetContractAddress); return this.nymdQuerier.getLayerDistribution(mixnetContractAddress);
} }
getRewardPool(mixnetContractAddress: string): Promise<string> { getRewardPool(mixnetContractAddress: string): Promise<string> {
return this.nyxdQuerier.getRewardPool(mixnetContractAddress); return this.nymdQuerier.getRewardPool(mixnetContractAddress);
} }
getCirculatingSupply(mixnetContractAddress: string): Promise<string> { getCirculatingSupply(mixnetContractAddress: string): Promise<string> {
return this.nyxdQuerier.getCirculatingSupply(mixnetContractAddress); return this.nymdQuerier.getCirculatingSupply(mixnetContractAddress);
} }
getIntervalRewardPercent(mixnetContractAddress: string): Promise<number> { getIntervalRewardPercent(mixnetContractAddress: string): Promise<number> {
return this.nyxdQuerier.getIntervalRewardPercent(mixnetContractAddress); return this.nymdQuerier.getIntervalRewardPercent(mixnetContractAddress);
} }
getSybilResistancePercent(mixnetContractAddress: string): Promise<number> { getSybilResistancePercent(mixnetContractAddress: string): Promise<number> {
return this.nyxdQuerier.getSybilResistancePercent(mixnetContractAddress); return this.nymdQuerier.getSybilResistancePercent(mixnetContractAddress);
} }
getRewardingStatus( getRewardingStatus(
@@ -190,7 +190,7 @@ export default class QueryClient extends CosmWasmClient implements IQueryClient
mixIdentity: string, mixIdentity: string,
rewardingIntervalNonce: number, rewardingIntervalNonce: number,
): Promise<RewardingStatus> { ): Promise<RewardingStatus> {
return this.nyxdQuerier.getRewardingStatus(mixnetContractAddress, mixIdentity, rewardingIntervalNonce); return this.nymdQuerier.getRewardingStatus(mixnetContractAddress, mixIdentity, rewardingIntervalNonce);
} }
getCachedGateways(): Promise<GatewayBond[]> { getCachedGateways(): Promise<GatewayBond[]> {
+21 -21
View File
@@ -14,7 +14,7 @@ import { ChangeAdminResult } from '@cosmjs/cosmwasm-stargate/build/signingcosmwa
import { TxRaw } from 'cosmjs-types/cosmos/tx/v1beta1/tx'; import { TxRaw } from 'cosmjs-types/cosmos/tx/v1beta1/tx';
import { nymGasPrice } from './stargate-helper'; import { nymGasPrice } from './stargate-helper';
import { IQueryClient } from './query-client'; import { IQueryClient } from './query-client';
import NyxdQuerier from './nyxd-querier'; import NymdQuerier from './nymd-querier';
import { import {
ContractStateParams, ContractStateParams,
Delegation, Delegation,
@@ -197,7 +197,7 @@ export interface ISigningClient extends IQueryClient, ICosmWasmSigning, INymSign
} }
export default class SigningClient extends SigningCosmWasmClient implements ISigningClient { export default class SigningClient extends SigningCosmWasmClient implements ISigningClient {
private nyxdQuerier: NyxdQuerier; private nymdQuerier: NymdQuerier;
private nymApiQuerier: NymApiQuerier; private nymApiQuerier: NymApiQuerier;
@@ -212,13 +212,13 @@ export default class SigningClient extends SigningCosmWasmClient implements ISig
) { ) {
super(tmClient, wallet, signerOptions); super(tmClient, wallet, signerOptions);
this.clientAddress = clientAddress; this.clientAddress = clientAddress;
this.nyxdQuerier = new NyxdQuerier(this); this.nymdQuerier = new NymdQuerier(this);
this.nymApiQuerier = new NymApiQuerier(nymApiUrl); this.nymApiQuerier = new NymApiQuerier(nymApiUrl);
} }
public static async connectWithNymSigner( public static async connectWithNymSigner(
wallet: DirectSecp256k1HdWallet, wallet: DirectSecp256k1HdWallet,
nyxdUrl: string, nymdUrl: string,
nymApiUrl: string, nymApiUrl: string,
prefix: string, prefix: string,
denom: string, denom: string,
@@ -228,34 +228,34 @@ export default class SigningClient extends SigningCosmWasmClient implements ISig
prefix, prefix,
gasPrice: nymGasPrice(denom), gasPrice: nymGasPrice(denom),
}; };
const tmClient = await Tendermint34Client.connect(nyxdUrl); const tmClient = await Tendermint34Client.connect(nymdUrl);
return new SigningClient(address, nymApiUrl, tmClient, wallet, signerOptions); return new SigningClient(address, nymApiUrl, tmClient, wallet, signerOptions);
} }
// query related: // query related:
getContractVersion(mixnetContractAddress: string): Promise<MixnetContractVersion> { getContractVersion(mixnetContractAddress: string): Promise<MixnetContractVersion> {
return this.nyxdQuerier.getContractVersion(mixnetContractAddress); return this.nymdQuerier.getContractVersion(mixnetContractAddress);
} }
getMixNodesPaged(mixnetContractAddress: string, limit?: number, startAfter?: string): Promise<PagedMixnodeResponse> { getMixNodesPaged(mixnetContractAddress: string, limit?: number, startAfter?: string): Promise<PagedMixnodeResponse> {
return this.nyxdQuerier.getMixNodesPaged(mixnetContractAddress, limit, startAfter); return this.nymdQuerier.getMixNodesPaged(mixnetContractAddress, limit, startAfter);
} }
getGatewaysPaged(mixnetContractAddress: string, limit?: number, startAfter?: string): Promise<PagedGatewayResponse> { getGatewaysPaged(mixnetContractAddress: string, limit?: number, startAfter?: string): Promise<PagedGatewayResponse> {
return this.nyxdQuerier.getGatewaysPaged(mixnetContractAddress, limit, startAfter); return this.nymdQuerier.getGatewaysPaged(mixnetContractAddress, limit, startAfter);
} }
ownsMixNode(mixnetContractAddress: string, address: string): Promise<MixOwnershipResponse> { ownsMixNode(mixnetContractAddress: string, address: string): Promise<MixOwnershipResponse> {
return this.nyxdQuerier.ownsMixNode(mixnetContractAddress, address); return this.nymdQuerier.ownsMixNode(mixnetContractAddress, address);
} }
ownsGateway(mixnetContractAddress: string, address: string): Promise<GatewayOwnershipResponse> { ownsGateway(mixnetContractAddress: string, address: string): Promise<GatewayOwnershipResponse> {
return this.nyxdQuerier.ownsGateway(mixnetContractAddress, address); return this.nymdQuerier.ownsGateway(mixnetContractAddress, address);
} }
getStateParams(mixnetContractAddress: string): Promise<ContractStateParams> { getStateParams(mixnetContractAddress: string): Promise<ContractStateParams> {
return this.nyxdQuerier.getStateParams(mixnetContractAddress); return this.nymdQuerier.getStateParams(mixnetContractAddress);
} }
getAllNetworkDelegationsPaged( getAllNetworkDelegationsPaged(
@@ -263,7 +263,7 @@ export default class SigningClient extends SigningCosmWasmClient implements ISig
limit?: number, limit?: number,
startAfter?: [string, string], startAfter?: [string, string],
): Promise<PagedAllDelegationsResponse> { ): Promise<PagedAllDelegationsResponse> {
return this.nyxdQuerier.getAllNetworkDelegationsPaged(mixnetContractAddress, limit, startAfter); return this.nymdQuerier.getAllNetworkDelegationsPaged(mixnetContractAddress, limit, startAfter);
} }
getMixNodeDelegationsPaged( getMixNodeDelegationsPaged(
@@ -272,7 +272,7 @@ export default class SigningClient extends SigningCosmWasmClient implements ISig
limit?: number, limit?: number,
startAfter?: string, startAfter?: string,
): Promise<PagedMixDelegationsResponse> { ): Promise<PagedMixDelegationsResponse> {
return this.nyxdQuerier.getMixNodeDelegationsPaged(mixnetContractAddress, mixIdentity, limit, startAfter); return this.nymdQuerier.getMixNodeDelegationsPaged(mixnetContractAddress, mixIdentity, limit, startAfter);
} }
getDelegatorDelegationsPaged( getDelegatorDelegationsPaged(
@@ -281,31 +281,31 @@ export default class SigningClient extends SigningCosmWasmClient implements ISig
limit?: number, limit?: number,
startAfter?: string, startAfter?: string,
): Promise<PagedDelegatorDelegationsResponse> { ): Promise<PagedDelegatorDelegationsResponse> {
return this.nyxdQuerier.getDelegatorDelegationsPaged(mixnetContractAddress, delegator, limit, startAfter); return this.nymdQuerier.getDelegatorDelegationsPaged(mixnetContractAddress, delegator, limit, startAfter);
} }
getDelegationDetails(mixnetContractAddress: string, mixIdentity: string, delegator: string): Promise<Delegation> { getDelegationDetails(mixnetContractAddress: string, mixIdentity: string, delegator: string): Promise<Delegation> {
return this.nyxdQuerier.getDelegationDetails(mixnetContractAddress, mixIdentity, delegator); return this.nymdQuerier.getDelegationDetails(mixnetContractAddress, mixIdentity, delegator);
} }
getLayerDistribution(mixnetContractAddress: string): Promise<LayerDistribution> { getLayerDistribution(mixnetContractAddress: string): Promise<LayerDistribution> {
return this.nyxdQuerier.getLayerDistribution(mixnetContractAddress); return this.nymdQuerier.getLayerDistribution(mixnetContractAddress);
} }
getRewardPool(mixnetContractAddress: string): Promise<string> { getRewardPool(mixnetContractAddress: string): Promise<string> {
return this.nyxdQuerier.getRewardPool(mixnetContractAddress); return this.nymdQuerier.getRewardPool(mixnetContractAddress);
} }
getCirculatingSupply(mixnetContractAddress: string): Promise<string> { getCirculatingSupply(mixnetContractAddress: string): Promise<string> {
return this.nyxdQuerier.getCirculatingSupply(mixnetContractAddress); return this.nymdQuerier.getCirculatingSupply(mixnetContractAddress);
} }
getIntervalRewardPercent(mixnetContractAddress: string): Promise<number> { getIntervalRewardPercent(mixnetContractAddress: string): Promise<number> {
return this.nyxdQuerier.getIntervalRewardPercent(mixnetContractAddress); return this.nymdQuerier.getIntervalRewardPercent(mixnetContractAddress);
} }
getSybilResistancePercent(mixnetContractAddress: string): Promise<number> { getSybilResistancePercent(mixnetContractAddress: string): Promise<number> {
return this.nyxdQuerier.getSybilResistancePercent(mixnetContractAddress); return this.nymdQuerier.getSybilResistancePercent(mixnetContractAddress);
} }
getRewardingStatus( getRewardingStatus(
@@ -313,7 +313,7 @@ export default class SigningClient extends SigningCosmWasmClient implements ISig
mixIdentity: string, mixIdentity: string,
rewardingIntervalNonce: number, rewardingIntervalNonce: number,
): Promise<RewardingStatus> { ): Promise<RewardingStatus> {
return this.nyxdQuerier.getRewardingStatus(mixnetContractAddress, mixIdentity, rewardingIntervalNonce); return this.nymdQuerier.getRewardingStatus(mixnetContractAddress, mixIdentity, rewardingIntervalNonce);
} }
getCachedGateways(): Promise<GatewayBond[]> { getCachedGateways(): Promise<GatewayBond[]> {
@@ -0,0 +1,24 @@
#!/usr/bin/env node
const { spawn } = require("child_process");
const fs = require("fs");
let folderName = '.';
if (process.argv.length >= 3) {
folderName = process.argv[2];
if (!fs.existsSync(folderName)) {
fs.mkdirSync(folderName);
}
}
const clone = spawn("git", ["clone", "https://github.com/rustwasm/create-wasm-app.git", folderName]);
clone.on("close", code => {
if (code !== 0) {
console.error("cloning the template failed!")
process.exit(code);
} else {
console.log("🦀 Rust + 🕸 Wasm = ❤");
}
});
@@ -0,0 +1,2 @@
node_modules
dist
@@ -0,0 +1,5 @@
language: node_js
node_js: "10"
script:
- ./node_modules/.bin/webpack
@@ -0,0 +1,201 @@
Apache License
Version 2.0, January 2004
http://www.apache.org/licenses/
TERMS AND CONDITIONS FOR USE, REPRODUCTION, AND DISTRIBUTION
1. Definitions.
"License" shall mean the terms and conditions for use, reproduction,
and distribution as defined by Sections 1 through 9 of this document.
"Licensor" shall mean the copyright owner or entity authorized by
the copyright owner that is granting the License.
"Legal Entity" shall mean the union of the acting entity and all
other entities that control, are controlled by, or are under common
control with that entity. For the purposes of this definition,
"control" means (i) the power, direct or indirect, to cause the
direction or management of such entity, whether by contract or
otherwise, or (ii) ownership of fifty percent (50%) or more of the
outstanding shares, or (iii) beneficial ownership of such entity.
"You" (or "Your") shall mean an individual or Legal Entity
exercising permissions granted by this License.
"Source" form shall mean the preferred form for making modifications,
including but not limited to software source code, documentation
source, and configuration files.
"Object" form shall mean any form resulting from mechanical
transformation or translation of a Source form, including but
not limited to compiled object code, generated documentation,
and conversions to other media types.
"Work" shall mean the work of authorship, whether in Source or
Object form, made available under the License, as indicated by a
copyright notice that is included in or attached to the work
(an example is provided in the Appendix below).
"Derivative Works" shall mean any work, whether in Source or Object
form, that is based on (or derived from) the Work and for which the
editorial revisions, annotations, elaborations, or other modifications
represent, as a whole, an original work of authorship. For the purposes
of this License, Derivative Works shall not include works that remain
separable from, or merely link (or bind by name) to the interfaces of,
the Work and Derivative Works thereof.
"Contribution" shall mean any work of authorship, including
the original version of the Work and any modifications or additions
to that Work or Derivative Works thereof, that is intentionally
submitted to Licensor for inclusion in the Work by the copyright owner
or by an individual or Legal Entity authorized to submit on behalf of
the copyright owner. For the purposes of this definition, "submitted"
means any form of electronic, verbal, or written communication sent
to the Licensor or its representatives, including but not limited to
communication on electronic mailing lists, source code control systems,
and issue tracking systems that are managed by, or on behalf of, the
Licensor for the purpose of discussing and improving the Work, but
excluding communication that is conspicuously marked or otherwise
designated in writing by the copyright owner as "Not a Contribution."
"Contributor" shall mean Licensor and any individual or Legal Entity
on behalf of whom a Contribution has been received by Licensor and
subsequently incorporated within the Work.
2. Grant of Copyright License. Subject to the terms and conditions of
this License, each Contributor hereby grants to You a perpetual,
worldwide, non-exclusive, no-charge, royalty-free, irrevocable
copyright license to reproduce, prepare Derivative Works of,
publicly display, publicly perform, sublicense, and distribute the
Work and such Derivative Works in Source or Object form.
3. Grant of Patent License. Subject to the terms and conditions of
this License, each Contributor hereby grants to You a perpetual,
worldwide, non-exclusive, no-charge, royalty-free, irrevocable
(except as stated in this section) patent license to make, have made,
use, offer to sell, sell, import, and otherwise transfer the Work,
where such license applies only to those patent claims licensable
by such Contributor that are necessarily infringed by their
Contribution(s) alone or by combination of their Contribution(s)
with the Work to which such Contribution(s) was submitted. If You
institute patent litigation against any entity (including a
cross-claim or counterclaim in a lawsuit) alleging that the Work
or a Contribution incorporated within the Work constitutes direct
or contributory patent infringement, then any patent licenses
granted to You under this License for that Work shall terminate
as of the date such litigation is filed.
4. Redistribution. You may reproduce and distribute copies of the
Work or Derivative Works thereof in any medium, with or without
modifications, and in Source or Object form, provided that You
meet the following conditions:
(a) You must give any other recipients of the Work or
Derivative Works a copy of this License; and
(b) You must cause any modified files to carry prominent notices
stating that You changed the files; and
(c) You must retain, in the Source form of any Derivative Works
that You distribute, all copyright, patent, trademark, and
attribution notices from the Source form of the Work,
excluding those notices that do not pertain to any part of
the Derivative Works; and
(d) If the Work includes a "NOTICE" text file as part of its
distribution, then any Derivative Works that You distribute must
include a readable copy of the attribution notices contained
within such NOTICE file, excluding those notices that do not
pertain to any part of the Derivative Works, in at least one
of the following places: within a NOTICE text file distributed
as part of the Derivative Works; within the Source form or
documentation, if provided along with the Derivative Works; or,
within a display generated by the Derivative Works, if and
wherever such third-party notices normally appear. The contents
of the NOTICE file are for informational purposes only and
do not modify the License. You may add Your own attribution
notices within Derivative Works that You distribute, alongside
or as an addendum to the NOTICE text from the Work, provided
that such additional attribution notices cannot be construed
as modifying the License.
You may add Your own copyright statement to Your modifications and
may provide additional or different license terms and conditions
for use, reproduction, or distribution of Your modifications, or
for any such Derivative Works as a whole, provided Your use,
reproduction, and distribution of the Work otherwise complies with
the conditions stated in this License.
5. Submission of Contributions. Unless You explicitly state otherwise,
any Contribution intentionally submitted for inclusion in the Work
by You to the Licensor shall be under the terms and conditions of
this License, without any additional terms or conditions.
Notwithstanding the above, nothing herein shall supersede or modify
the terms of any separate license agreement you may have executed
with Licensor regarding such Contributions.
6. Trademarks. This License does not grant permission to use the trade
names, trademarks, service marks, or product names of the Licensor,
except as required for reasonable and customary use in describing the
origin of the Work and reproducing the content of the NOTICE file.
7. Disclaimer of Warranty. Unless required by applicable law or
agreed to in writing, Licensor provides the Work (and each
Contributor provides its Contributions) on an "AS IS" BASIS,
WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or
implied, including, without limitation, any warranties or conditions
of TITLE, NON-INFRINGEMENT, MERCHANTABILITY, or FITNESS FOR A
PARTICULAR PURPOSE. You are solely responsible for determining the
appropriateness of using or redistributing the Work and assume any
risks associated with Your exercise of permissions under this License.
8. Limitation of Liability. In no event and under no legal theory,
whether in tort (including negligence), contract, or otherwise,
unless required by applicable law (such as deliberate and grossly
negligent acts) or agreed to in writing, shall any Contributor be
liable to You for damages, including any direct, indirect, special,
incidental, or consequential damages of any character arising as a
result of this License or out of the use or inability to use the
Work (including but not limited to damages for loss of goodwill,
work stoppage, computer failure or malfunction, or any and all
other commercial damages or losses), even if such Contributor
has been advised of the possibility of such damages.
9. Accepting Warranty or Additional Liability. While redistributing
the Work or Derivative Works thereof, You may choose to offer,
and charge a fee for, acceptance of support, warranty, indemnity,
or other liability obligations and/or rights consistent with this
License. However, in accepting such obligations, You may act only
on Your own behalf and on Your sole responsibility, not on behalf
of any other Contributor, and only if You agree to indemnify,
defend, and hold each Contributor harmless for any liability
incurred by, or claims asserted against, such Contributor by reason
of your accepting any such warranty or additional liability.
END OF TERMS AND CONDITIONS
APPENDIX: How to apply the Apache License to your work.
To apply the Apache License to your work, attach the following
boilerplate notice, with the fields enclosed by brackets "[]"
replaced with your own identifying information. (Don't include
the brackets!) The text should be enclosed in the appropriate
comment syntax for the file format. We also recommend that a
file or class name and description of purpose be included on the
same "printed page" as the copyright notice for easier
identification within third-party archives.
Copyright [yyyy] [name of copyright owner]
Licensed under the Apache License, Version 2.0 (the "License");
you may not use this file except in compliance with the License.
You may obtain a copy of the License at
http://www.apache.org/licenses/LICENSE-2.0
Unless required by applicable law or agreed to in writing, software
distributed under the License is distributed on an "AS IS" BASIS,
WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
See the License for the specific language governing permissions and
limitations under the License.
+28
View File
@@ -0,0 +1,28 @@
# Nym Sphinx Wasm Demo
This example application demonstrates how to use WebAssembly to create Sphinx packets, in the browser, and forward them to a Nym gateway.
## 🚴 Usage
Build the WASM package for bundling:
```
wasm-pack build --scope nymproject --target no-modules
```
in the `clients/webassembly` directory (one up).
Start the webpack dev server:
```
npm install # set up dependencies
npm run start # starts a web server at http://localhost:8001
```
Check your dev console for output.
### Rebuild after Rust source changes
Install `wasm-pack`. Instruction are at the [Rust WASM tutorial](https://rustwasm.github.io/docs/book/game-of-life/hello-world.html).
`wasm-pack build --scope nymproject --target no-modules` in the `clients/webassembly` directory (one up) will rebuild the wasm package if you make changes to the Rust source. That will be automatically picked up (and reloaded, if need be) by the npm dev server.
+5
View File
@@ -0,0 +1,5 @@
// A dependency graph that contains any wasm must all be imported
// asynchronously. This `bootstrap.js` file does the single async import, so
// that no one else needs to worry about it again.
import('./index.js')
.catch(e => console.error('Error importing `index.js`:', e));
+36
View File
@@ -0,0 +1,36 @@
<!DOCTYPE html>
<html lang="en">
<head>
<meta charset="UTF-8">
<meta name="viewport" content="width=device-width, initial-scale=1.0">
<title>Nym WebAssembly Demo</title>
</head>
<body>
<p>
<label>Sender: </label><input disabled="true" size="85" type="text" id="sender" value="">
</p>
<p>
<label>Recipient: </label><input size="85" type="text" id="recipient" value="">
</p>
<p>
<label>Message: </label><input type="text" id="message" value="Hello mixnet!">
</p>
<p>
<button id="send-button">Send</button>
</p>
<p>Send messages from your browser, through the mixnet, and to the recipient using the "send" button.</p>
<p><span style='color: blue;'>Sent</span> messages show in blue, <span style='color: green;'>received</span>
messages show in green.</p>
<hr>
<p>
<span id="output"></div>
</p>
<script src="./bootstrap.js"></script>
</body>
</html>
+128
View File
@@ -0,0 +1,128 @@
// Copyright 2020-2022 Nym Technologies SA
//
// Licensed under the Apache License, Version 2.0 (the "License");
// you may not use this file except in compliance with the License.
// You may obtain a copy of the License at
//
// http://www.apache.org/licenses/LICENSE-2.0
//
// Unless required by applicable law or agreed to in writing, software
// distributed under the License is distributed on an "AS IS" BASIS,
// WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
// See the License for the specific language governing permissions and
// limitations under the License.
class WebWorkerClient {
worker = null;
constructor() {
this.worker = new Worker('./worker.js');
this.worker.onmessage = (ev) => {
if (ev.data && ev.data.kind) {
switch (ev.data.kind) {
case 'Ready':
const { selfAddress } = ev.data.args;
displaySenderAddress(selfAddress);
break;
case 'ReceiveMessage':
const { message } = ev.data.args;
displayReceived(message);
break;
}
}
};
}
sendMessage = (message, recipient) => {
if (!this.worker) {
console.error('Could not send message because worker does not exist');
return;
}
this.worker.postMessage({
kind: 'SendMessage',
args: {
message, recipient,
},
});
};
}
let client = null;
async function main() {
client = new WebWorkerClient();
const sendButton = document.querySelector('#send-button');
sendButton.onclick = function() {
sendMessageTo();
};
}
/**
* Create a Sphinx packet and send it to the mixnet through the gateway node.
*
* Message and recipient are taken from the values in the user interface.
*
*/
async function sendMessageTo() {
const message = document.getElementById('message').value;
const recipient = document.getElementById('recipient').value;
await client.sendMessage(message, recipient);
displaySend(message);
}
/**
* Display messages that have been sent up the websocket. Colours them blue.
*
* @param {string} message
*/
function displaySend(message) {
let timestamp = new Date().toISOString().substr(11, 12);
let sendDiv = document.createElement('div');
let paragraph = document.createElement('p');
paragraph.setAttribute('style', 'color: blue');
let paragraphContent = document.createTextNode(timestamp + ' sent >>> ' + message);
paragraph.appendChild(paragraphContent);
sendDiv.appendChild(paragraph);
document.getElementById('output').appendChild(sendDiv);
}
/**
* Display received text messages in the browser. Colour them green.
*
* @param {Uint8Array} raw
*/
function displayReceived(raw, sender_tag) {
const content = new TextDecoder().decode(raw);
if (sender_tag !== undefined) {
console.log("this message also contained some surbs from", sender_tag)
}
let timestamp = new Date().toISOString().substr(11, 12);
let receivedDiv = document.createElement('div');
let paragraph = document.createElement('p');
paragraph.setAttribute('style', 'color: green');
let paragraphContent = document.createTextNode(timestamp + ' received >>> ' + content);
// let paragraphContent = document.createTextNode(timestamp + " received >>> " + content + ((replySurb != null) ? "Reply SURB was attached here (but we can't do anything with it yet" : " (NO REPLY-SURB AVAILABLE)"))
paragraph.appendChild(paragraphContent);
receivedDiv.appendChild(paragraph);
document.getElementById('output').appendChild(receivedDiv);
}
/**
* Display the nymClient's sender address in the user interface
*
* @param {String} address
*/
function displaySenderAddress(address) {
document.getElementById('sender').value = address;
}
// Let's get started!
main();
File diff suppressed because it is too large Load Diff
@@ -0,0 +1,39 @@
{
"name": "create-wasm-app",
"version": "0.1.0",
"description": "create an app to consume rust-generated wasm packages",
"main": "index.js",
"bin": {
"create-wasm-app": ".bin/create-wasm-app.js"
},
"scripts": {
"build": "webpack --config webpack.config.js",
"start": "webpack-dev-server --port 8001"
},
"repository": {
"type": "git",
"url": "git+https://github.com/rustwasm/create-wasm-app.git"
},
"keywords": [
"webassembly",
"wasm",
"rust",
"webpack"
],
"author": "Dave Hrycyszyn <futurechimp@users.noreply.github.com>",
"license": "Apache-2.0",
"bugs": {
"url": "https://github.com/nymtech/nym/issues"
},
"homepage": "https://nymtech.net/docs",
"devDependencies": {
"copy-webpack-plugin": "^10.2.4",
"hello-wasm-pack": "^0.1.0",
"webpack": "^5.70.0",
"webpack-cli": "^4.9.2",
"webpack-dev-server": "^4.7.4"
},
"dependencies": {
"@nymproject/nym-client-wasm": "file:../pkg"
}
}
@@ -0,0 +1,33 @@
const CopyWebpackPlugin = require('copy-webpack-plugin');
const path = require('path');
module.exports = {
performance: {
hints: false,
maxEntrypointSize: 512000,
maxAssetSize: 512000
},
entry: {
bootstrap: './bootstrap.js',
worker: './worker.js',
},
output: {
path: path.resolve(__dirname, 'dist'),
filename: '[name].js',
},
// mode: 'development',
mode: 'production',
plugins: [
new CopyWebpackPlugin({
patterns: [
'index.html',
{
from: 'node_modules/@nymproject/nym-client-wasm/*.(js|wasm)',
to: '[name][ext]',
},
],
}),
],
experiments: { syncWebAssembly: true },
};
+101
View File
@@ -0,0 +1,101 @@
// Copyright 2020-2022 Nym Technologies SA
//
// Licensed under the Apache License, Version 2.0 (the "License");
// you may not use this file except in compliance with the License.
// You may obtain a copy of the License at
//
// http://www.apache.org/licenses/LICENSE-2.0
//
// Unless required by applicable law or agreed to in writing, software
// distributed under the License is distributed on an "AS IS" BASIS,
// WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
// See the License for the specific language governing permissions and
// limitations under the License.
importScripts('nym_client_wasm.js');
console.log('Initializing worker');
// wasm_bindgen creates a global variable (with the exports attached) that is in scope after `importScripts`
const { default_debug, NymClientBuilder, set_panic_hook, Config, GatewayEndpointConfig } = wasm_bindgen;
let client = null;
async function main() {
// load WASM package
await wasm_bindgen('nym_client_wasm_bg.wasm');
console.log('Loaded WASM');
// sets up better stack traces in case of in-rust panics
set_panic_hook();
// validator server we will use to get topology from
const validator = 'https://qwerty-validator-api.qa.nymte.ch/api';
const gatewayId = 'EVupP2tRUeZo5Y6RpBHAbm8kSntpgNyZNL6yCr7BDEoG';
const gatewayOwner = 'n1rmlew3euapuq7rs4s4j9apv00whrsazr764kl7';
const gatewayListener = 'ws://176.58.120.72:9000';
const gatewayEndpoint = new GatewayEndpointConfig(gatewayId, gatewayOwner, gatewayListener)
// only really useful if you want to adjust some settings like traffic rate
// (if not needed you can just pass a null)
const debug = default_debug();
debug.disable_main_poisson_packet_distribution = true;
debug.disable_loop_cover_traffic_stream = true;
debug.use_extended_packet_size = true;
// debug.average_packet_delay_ms = BigInt(10);
// debug.average_ack_delay_ms = BigInt(10);
// debug.ack_wait_addition_ms = BigInt(3000);
// debug.ack_wait_multiplier = 10;
debug.topology_refresh_rate_ms = BigInt(60000)
const config = new Config('my-awesome-wasm-client', validator, gatewayEndpoint, debug);
const onMessageHandler = (message) => {
self.postMessage({
kind: 'ReceiveMessage',
args: {
message,
},
});
};
console.log('Instantiating WASM client...');
let clientBuilder = new NymClientBuilder(config, onMessageHandler)
console.log('Web worker creating WASM client...');
let local_client = await clientBuilder.start_client();
console.log('WASM client running!');
const selfAddress = local_client.self_address();
// set the global (I guess we don't have to anymore?)
client = local_client;
console.log(`Client address is ${selfAddress}`);
self.postMessage({
kind: 'Ready',
args: {
selfAddress,
},
});
// Set callback to handle messages passed to the worker.
self.onmessage = async event => {
if (event.data && event.data.kind) {
switch (event.data.kind) {
case 'SendMessage': {
const { message, recipient } = event.data.args;
let uint8Array = new TextEncoder().encode(message);
await client.send_regular_message(uint8Array, recipient);
}
}
}
};
}
// Let's get started!
main();
+2 -10
View File
@@ -5,9 +5,7 @@ use self::config::Config;
use crate::client::helpers::InputSender; use crate::client::helpers::InputSender;
use crate::client::response_pusher::ResponsePusher; use crate::client::response_pusher::ResponsePusher;
use client_connections::TransmissionLane; use client_connections::TransmissionLane;
use client_core::client::base_client::{ use client_core::client::base_client::{BaseClientBuilder, ClientInput, ClientOutput};
BaseClientBuilder, ClientInput, ClientOutput, CredentialsToggle,
};
use client_core::client::replies::reply_storage::browser_backend; use client_core::client::replies::reply_storage::browser_backend;
use client_core::client::{inbound_messages::InputMessage, key_manager::KeyManager}; use client_core::client::{inbound_messages::InputMessage, key_manager::KeyManager};
use gateway_client::bandwidth::BandwidthController; use gateway_client::bandwidth::BandwidthController;
@@ -94,19 +92,13 @@ impl NymClientBuilder {
future_to_promise(async move { future_to_promise(async move {
console_log!("Starting the wasm client"); console_log!("Starting the wasm client");
let disabled_credentials = if self.disabled_credentials {
CredentialsToggle::Disabled
} else {
CredentialsToggle::Enabled
};
let base_builder = BaseClientBuilder::new( let base_builder = BaseClientBuilder::new(
&self.config.gateway_endpoint, &self.config.gateway_endpoint,
&self.config.debug, &self.config.debug,
self.key_manager, self.key_manager,
self.bandwidth_controller, self.bandwidth_controller,
self.reply_surb_storage_backend, self.reply_surb_storage_backend,
disabled_credentials, self.disabled_credentials,
vec![self.config.nym_api_url.clone()], vec![self.config.nym_api_url.clone()],
); );
+1 -1
View File
@@ -6,7 +6,7 @@ use wasm_bindgen::prelude::*;
#[wasm_bindgen] #[wasm_bindgen]
pub async fn get_gateway(api_server: String, preferred: Option<String>) -> GatewayEndpointConfig { pub async fn get_gateway(api_server: String, preferred: Option<String>) -> GatewayEndpointConfig {
let validator_client = validator_client::client::NymApiClient::new(api_server.parse().unwrap()); let validator_client = validator_client::client::ApiClient::new(api_server.parse().unwrap());
let gateways = match validator_client.get_cached_gateways().await { let gateways = match validator_client.get_cached_gateways().await {
Err(err) => panic!("failed to obtain list of all gateways - {err}"), Err(err) => panic!("failed to obtain list of all gateways - {err}"),
-11
View File
@@ -1,11 +0,0 @@
[package]
name = "build-information"
version = "0.1.0"
edition = "2021"
# See more keys and their definitions at https://doc.rust-lang.org/cargo/reference/manifest.html
[dependencies]
[build-dependencies]
vergen = { version = "7", default-features = false, features = ["build", "git", "rustc", "cargo"] }
-86
View File
@@ -1,86 +0,0 @@
// Copyright 2023 - Nym Technologies SA <contact@nymtech.net>
// SPDX-License-Identifier: Apache-2.0
// TODO: at a later date this crate should probably also expose `ContractBuildInformation`
// and be used by our smart contracts
pub struct BinaryBuildInformation {
// VERGEN_BUILD_TIMESTAMP
/// Provides the build timestamp, for example `2021-02-23T20:14:46.558472672+00:00`.
pub build_timestamp: &'static str,
// VERGEN_BUILD_SEMVER
/// Provides the build version, for example `0.1.0-9-g46f83e1`.
pub build_version: &'static str,
// VERGEN_GIT_SHA
/// Provides the hash of the commit that was used for the build, for example `46f83e112520533338245862d366f6a02cef07d4`.
pub commit_sha: &'static str,
// VERGEN_GIT_COMMIT_TIMESTAMP
/// Provides the timestamp of the commit that was used for the build, for example `2021-02-23T08:08:02-05:00`.
pub commit_timestamp: &'static str,
// VERGEN_GIT_BRANCH
/// Provides the name of the git branch that was used for the build, for example `master`.
pub commit_branch: &'static str,
// VERGEN_RUSTC_SEMVER
/// Provides the rustc version that was used for the build, for example `1.52.0-nightly`.
pub rustc_version: &'static str,
// VERGEN_RUSTC_CHANNEL
/// Provides the rustc channel that was used for the build, for example `nightly`.
pub rustc_channel: &'static str,
// VERGEN_CARGO_PROFILE
/// Provides the cargo profile that was used for the build, for example `debug`.
pub cargo_profile: &'static str,
}
impl BinaryBuildInformation {
// explicitly require the build_version to be passed as it's binary specific
pub const fn new(build_version: &'static str) -> Self {
BinaryBuildInformation {
build_timestamp: env!("VERGEN_BUILD_TIMESTAMP"),
build_version,
commit_sha: env!("VERGEN_GIT_SHA"),
commit_timestamp: env!("VERGEN_GIT_COMMIT_TIMESTAMP"),
commit_branch: env!("VERGEN_GIT_BRANCH"),
rustc_version: env!("VERGEN_RUSTC_SEMVER"),
rustc_channel: env!("VERGEN_RUSTC_CHANNEL"),
cargo_profile: env!("VERGEN_CARGO_PROFILE"),
}
}
pub fn pretty_print(&self) -> String {
format!(
r#"
{:<20}{}
{:<20}{}
{:<20}{}
{:<20}{}
{:<20}{}
{:<20}{}
{:<20}{}
{:<20}{}
"#,
"Build Timestamp:",
self.build_timestamp,
"Build Version:",
self.build_version,
"Commit SHA:",
self.commit_sha,
"Commit Date:",
self.commit_timestamp,
"Commit Branch:",
self.commit_branch,
"rustc Version:",
self.rustc_version,
"rustc Channel:",
self.rustc_channel,
"cargo Profile:",
self.cargo_profile,
)
}
}
+2 -1
View File
@@ -1,9 +1,10 @@
// Copyright 2022 - Nym Technologies SA <contact@nymtech.net> // Copyright 2022 - Nym Technologies SA <contact@nymtech.net>
// SPDX-License-Identifier: Apache-2.0 // SPDX-License-Identifier: Apache-2.0
use futures::channel::mpsc;
use std::collections::HashMap; use std::collections::HashMap;
use futures::channel::mpsc;
pub type ConnectionId = u64; pub type ConnectionId = u64;
#[derive(Copy, Clone, Debug, Hash, PartialEq, Eq)] #[derive(Copy, Clone, Debug, Hash, PartialEq, Eq)]
@@ -27,7 +27,6 @@ nymsphinx = { path = "../../nymsphinx" }
pemstore = { path = "../../pemstore" } pemstore = { path = "../../pemstore" }
validator-client = { path = "../validator-client", optional = true } validator-client = { path = "../validator-client", optional = true }
task = { path = "../../task" } task = { path = "../../task" }
serde = { version = "1.0", features = ["derive"]}
[dependencies.tungstenite] [dependencies.tungstenite]
@@ -31,7 +31,7 @@ coconut-interface = { path = "../../coconut-interface" }
network-defaults = { path = "../../network-defaults" } network-defaults = { path = "../../network-defaults" }
nym-api-requests = { path = "../../../nym-api/nym-api-requests", features = ["coconut"] } nym-api-requests = { path = "../../../nym-api/nym-api-requests", features = ["coconut"] }
# required for nyxd-client # required for nymd-client
# at some point it might be possible to make it wasm-compatible # at some point it might be possible to make it wasm-compatible
# perhaps after https://github.com/cosmos/cosmos-rust/pull/97 is resolved (and tendermint-rs is updated) # perhaps after https://github.com/cosmos/cosmos-rust/pull/97 is resolved (and tendermint-rs is updated)
async-trait = { version = "0.1.51", optional = true } async-trait = { version = "0.1.51", optional = true }
@@ -50,7 +50,7 @@ execute = { path = "../../execute" }
ts-rs = "6.1.2" ts-rs = "6.1.2"
[features] [features]
nyxd-client = [ nymd-client = [
"async-trait", "async-trait",
"bip39", "bip39",
"config", "config",
@@ -15,41 +15,41 @@ use nym_api_requests::models::{
RewardEstimationResponse, StakeSaturationResponse, RewardEstimationResponse, StakeSaturationResponse,
}; };
#[cfg(feature = "nyxd-client")] #[cfg(feature = "nymd-client")]
use crate::nyxd::traits::{DkgQueryClient, MixnetQueryClient, MultisigQueryClient}; use crate::nymd::traits::{DkgQueryClient, MixnetQueryClient, MultisigQueryClient};
#[cfg(feature = "nyxd-client")] #[cfg(feature = "nymd-client")]
use crate::nyxd::{self, CosmWasmClient, NyxdClient, QueryNyxdClient, SigningNyxdClient}; use crate::nymd::{self, CosmWasmClient, NymdClient, QueryNymdClient, SigningNymdClient};
#[cfg(feature = "nyxd-client")] #[cfg(feature = "nymd-client")]
use coconut_dkg_common::{ use coconut_dkg_common::{
dealer::ContractDealing, types::DealerDetails, verification_key::ContractVKShare, dealer::ContractDealing, types::DealerDetails, verification_key::ContractVKShare,
}; };
#[cfg(feature = "nyxd-client")] #[cfg(feature = "nymd-client")]
use coconut_interface::Base58; use coconut_interface::Base58;
#[cfg(feature = "nyxd-client")] #[cfg(feature = "nymd-client")]
use cw3::ProposalResponse; use cw3::ProposalResponse;
#[cfg(feature = "nyxd-client")] #[cfg(feature = "nymd-client")]
use mixnet_contract_common::{ use mixnet_contract_common::{
families::{Family, FamilyHead}, families::{Family, FamilyHead},
mixnode::MixNodeBond, mixnode::MixNodeBond,
pending_events::{PendingEpochEvent, PendingIntervalEvent}, pending_events::{PendingEpochEvent, PendingIntervalEvent},
Delegation, IdentityKey, RewardedSetNodeStatus, UnbondedMixnode, Delegation, IdentityKey, RewardedSetNodeStatus, UnbondedMixnode,
}; };
#[cfg(feature = "nyxd-client")] #[cfg(feature = "nymd-client")]
use network_defaults::NymNetworkDetails; use network_defaults::NymNetworkDetails;
#[cfg(feature = "nyxd-client")] #[cfg(feature = "nymd-client")]
use nym_api_requests::models::MixNodeBondAnnotated; use nym_api_requests::models::MixNodeBondAnnotated;
#[cfg(feature = "nyxd-client")] #[cfg(feature = "nymd-client")]
use std::str::FromStr; use std::str::FromStr;
use url::Url; use url::Url;
#[cfg(feature = "nyxd-client")] #[cfg(feature = "nymd-client")]
#[must_use] #[must_use]
#[derive(Debug, Clone)] #[derive(Debug, Clone)]
pub struct Config { pub struct Config {
api_url: Url, api_url: Url,
nyxd_url: Url, nymd_url: Url,
nyxd_config: nyxd::Config, nymd_config: nymd::Config,
mixnode_page_limit: Option<u32>, mixnode_page_limit: Option<u32>,
gateway_page_limit: Option<u32>, gateway_page_limit: Option<u32>,
@@ -60,7 +60,7 @@ pub struct Config {
proposals_page_limit: Option<u32>, proposals_page_limit: Option<u32>,
} }
#[cfg(feature = "nyxd-client")] #[cfg(feature = "nymd-client")]
impl Config { impl Config {
pub fn try_from_nym_network_details( pub fn try_from_nym_network_details(
details: &NymNetworkDetails, details: &NymNetworkDetails,
@@ -78,11 +78,11 @@ impl Config {
Ok(Config { Ok(Config {
api_url: api_url.pop().unwrap(), api_url: api_url.pop().unwrap(),
nyxd_url: details.endpoints[0] nymd_url: details.endpoints[0]
.nyxd_url .nymd_url
.parse() .parse()
.map_err(ValidatorClientError::MalformedUrlProvided)?, .map_err(ValidatorClientError::MalformedUrlProvided)?,
nyxd_config: nyxd::Config::try_from_nym_network_details(details)?, nymd_config: nymd::Config::try_from_nym_network_details(details)?,
mixnode_page_limit: None, mixnode_page_limit: None,
gateway_page_limit: None, gateway_page_limit: None,
mixnode_delegations_page_limit: None, mixnode_delegations_page_limit: None,
@@ -95,14 +95,14 @@ impl Config {
// TODO: this method shouldn't really exist as all information should be included immediately // TODO: this method shouldn't really exist as all information should be included immediately
// via `from_nym_network_details`, but it's here for, you guessed it, legacy compatibility // via `from_nym_network_details`, but it's here for, you guessed it, legacy compatibility
pub fn with_urls(mut self, nyxd_url: Url, api_url: Url) -> Self { pub fn with_urls(mut self, nymd_url: Url, api_url: Url) -> Self {
self.nyxd_url = nyxd_url; self.nymd_url = nymd_url;
self.api_url = api_url; self.api_url = api_url;
self self
} }
pub fn with_nyxd_url(mut self, nyxd_url: Url) -> Self { pub fn with_nymd_url(mut self, nymd_url: Url) -> Self {
self.nyxd_url = nyxd_url; self.nymd_url = nymd_url;
self self
} }
@@ -127,7 +127,7 @@ impl Config {
} }
} }
#[cfg(feature = "nyxd-client")] #[cfg(feature = "nymd-client")]
pub struct Client<C> { pub struct Client<C> {
// TODO: we really shouldn't be storing a mnemonic here, but removing it would be // TODO: we really shouldn't be storing a mnemonic here, but removing it would be
// non-trivial amount of work and it's out of scope of the current branch // non-trivial amount of work and it's out of scope of the current branch
@@ -143,19 +143,19 @@ pub struct Client<C> {
// ideally they would have been read-only, but unfortunately rust doesn't have such features // ideally they would have been read-only, but unfortunately rust doesn't have such features
pub nym_api: nym_api::Client, pub nym_api: nym_api::Client,
pub nyxd: NyxdClient<C>, pub nymd: NymdClient<C>,
} }
#[cfg(feature = "nyxd-client")] #[cfg(feature = "nymd-client")]
impl Client<SigningNyxdClient> { impl Client<SigningNymdClient> {
pub fn new_signing( pub fn new_signing(
config: Config, config: Config,
mnemonic: bip39::Mnemonic, mnemonic: bip39::Mnemonic,
) -> Result<Client<SigningNyxdClient>, ValidatorClientError> { ) -> Result<Client<SigningNymdClient>, ValidatorClientError> {
let nym_api_client = nym_api::Client::new(config.api_url.clone()); let nym_api_client = nym_api::Client::new(config.api_url.clone());
let nyxd_client = NyxdClient::connect_with_mnemonic( let nymd_client = NymdClient::connect_with_mnemonic(
config.nyxd_config.clone(), config.nymd_config.clone(),
config.nyxd_url.as_str(), config.nymd_url.as_str(),
mnemonic.clone(), mnemonic.clone(),
None, None,
)?; )?;
@@ -170,13 +170,13 @@ impl Client<SigningNyxdClient> {
verification_key_page_limit: config.verification_key_page_limit, verification_key_page_limit: config.verification_key_page_limit,
proposals_page_limit: config.proposals_page_limit, proposals_page_limit: config.proposals_page_limit,
nym_api: nym_api_client, nym_api: nym_api_client,
nyxd: nyxd_client, nymd: nymd_client,
}) })
} }
pub fn change_nyxd(&mut self, new_endpoint: Url) -> Result<(), ValidatorClientError> { pub fn change_nymd(&mut self, new_endpoint: Url) -> Result<(), ValidatorClientError> {
self.nyxd = NyxdClient::connect_with_mnemonic( self.nymd = NymdClient::connect_with_mnemonic(
self.nyxd.current_config().clone(), self.nymd.current_config().clone(),
new_endpoint.as_ref(), new_endpoint.as_ref(),
self.mnemonic.clone().unwrap(), self.mnemonic.clone().unwrap(),
None, None,
@@ -184,17 +184,17 @@ impl Client<SigningNyxdClient> {
Ok(()) Ok(())
} }
pub fn set_nyxd_simulated_gas_multiplier(&mut self, multiplier: f32) { pub fn set_nymd_simulated_gas_multiplier(&mut self, multiplier: f32) {
self.nyxd.set_simulated_gas_multiplier(multiplier) self.nymd.set_simulated_gas_multiplier(multiplier)
} }
} }
#[cfg(feature = "nyxd-client")] #[cfg(feature = "nymd-client")]
impl Client<QueryNyxdClient> { impl Client<QueryNymdClient> {
pub fn new_query(config: Config) -> Result<Client<QueryNyxdClient>, ValidatorClientError> { pub fn new_query(config: Config) -> Result<Client<QueryNymdClient>, ValidatorClientError> {
let nym_api_client = nym_api::Client::new(config.api_url.clone()); let nym_api_client = nym_api::Client::new(config.api_url.clone());
let nyxd_client = let nymd_client =
NyxdClient::connect(config.nyxd_config.clone(), config.nyxd_url.as_str())?; NymdClient::connect(config.nymd_config.clone(), config.nymd_url.as_str())?;
Ok(Client { Ok(Client {
mnemonic: None, mnemonic: None,
@@ -206,29 +206,29 @@ impl Client<QueryNyxdClient> {
verification_key_page_limit: config.verification_key_page_limit, verification_key_page_limit: config.verification_key_page_limit,
proposals_page_limit: config.proposals_page_limit, proposals_page_limit: config.proposals_page_limit,
nym_api: nym_api_client, nym_api: nym_api_client,
nyxd: nyxd_client, nymd: nymd_client,
}) })
} }
pub fn change_nyxd(&mut self, new_endpoint: Url) -> Result<(), ValidatorClientError> { pub fn change_nymd(&mut self, new_endpoint: Url) -> Result<(), ValidatorClientError> {
self.nyxd = NyxdClient::connect(self.nyxd.current_config().clone(), new_endpoint.as_ref())?; self.nymd = NymdClient::connect(self.nymd.current_config().clone(), new_endpoint.as_ref())?;
Ok(()) Ok(())
} }
} }
// nyxd wrappers // nymd wrappers
#[cfg(feature = "nyxd-client")] #[cfg(feature = "nymd-client")]
impl<C> Client<C> { impl<C> Client<C> {
// use case: somebody initialised client without a contract in order to upload and initialise one // use case: somebody initialised client without a contract in order to upload and initialise one
// and now they want to actually use it without making new client // and now they want to actually use it without making new client
pub fn set_mixnet_contract_address(&mut self, mixnet_contract_address: cosmrs::AccountId) { pub fn set_mixnet_contract_address(&mut self, mixnet_contract_address: cosmrs::AccountId) {
self.nyxd self.nymd
.set_mixnet_contract_address(mixnet_contract_address) .set_mixnet_contract_address(mixnet_contract_address)
} }
pub fn get_mixnet_contract_address(&self) -> cosmrs::AccountId { pub fn get_mixnet_contract_address(&self) -> cosmrs::AccountId {
self.nyxd.mixnet_contract_address().clone() self.nymd.mixnet_contract_address().clone()
} }
pub async fn get_all_node_families(&self) -> Result<Vec<Family>, ValidatorClientError> pub async fn get_all_node_families(&self) -> Result<Vec<Family>, ValidatorClientError>
@@ -240,7 +240,7 @@ impl<C> Client<C> {
loop { loop {
let paged_response = self let paged_response = self
.nyxd .nymd
.get_all_node_families_paged(start_after.take(), None) .get_all_node_families_paged(start_after.take(), None)
.await?; .await?;
families.extend(paged_response.families); families.extend(paged_response.families);
@@ -266,7 +266,7 @@ impl<C> Client<C> {
loop { loop {
let paged_response = self let paged_response = self
.nyxd .nymd
.get_all_family_members_paged(start_after.take(), None) .get_all_family_members_paged(start_after.take(), None)
.await?; .await?;
members.extend(paged_response.members); members.extend(paged_response.members);
@@ -282,7 +282,7 @@ impl<C> Client<C> {
} }
// basically handles paging for us // basically handles paging for us
pub async fn get_all_nyxd_rewarded_set_mixnodes( pub async fn get_all_nymd_rewarded_set_mixnodes(
&self, &self,
) -> Result<Vec<(MixId, RewardedSetNodeStatus)>, ValidatorClientError> ) -> Result<Vec<(MixId, RewardedSetNodeStatus)>, ValidatorClientError>
where where
@@ -293,7 +293,7 @@ impl<C> Client<C> {
loop { loop {
let mut paged_response = self let mut paged_response = self
.nyxd .nymd
.get_rewarded_set_paged(start_after.take(), self.rewarded_set_page_limit) .get_rewarded_set_paged(start_after.take(), self.rewarded_set_page_limit)
.await?; .await?;
identities.append(&mut paged_response.nodes); identities.append(&mut paged_response.nodes);
@@ -308,7 +308,7 @@ impl<C> Client<C> {
Ok(identities) Ok(identities)
} }
pub async fn get_all_nyxd_mixnode_bonds(&self) -> Result<Vec<MixNodeBond>, ValidatorClientError> pub async fn get_all_nymd_mixnode_bonds(&self) -> Result<Vec<MixNodeBond>, ValidatorClientError>
where where
C: CosmWasmClient + Sync + Send, C: CosmWasmClient + Sync + Send,
{ {
@@ -316,7 +316,7 @@ impl<C> Client<C> {
let mut start_after = None; let mut start_after = None;
loop { loop {
let mut paged_response = self let mut paged_response = self
.nyxd .nymd
.get_mixnode_bonds_paged(self.mixnode_page_limit, start_after.take()) .get_mixnode_bonds_paged(self.mixnode_page_limit, start_after.take())
.await?; .await?;
mixnodes.append(&mut paged_response.nodes); mixnodes.append(&mut paged_response.nodes);
@@ -331,7 +331,7 @@ impl<C> Client<C> {
Ok(mixnodes) Ok(mixnodes)
} }
pub async fn get_all_nyxd_mixnodes_detailed( pub async fn get_all_nymd_mixnodes_detailed(
&self, &self,
) -> Result<Vec<MixNodeDetails>, ValidatorClientError> ) -> Result<Vec<MixNodeDetails>, ValidatorClientError>
where where
@@ -341,7 +341,7 @@ impl<C> Client<C> {
let mut start_after = None; let mut start_after = None;
loop { loop {
let mut paged_response = self let mut paged_response = self
.nyxd .nymd
.get_mixnodes_detailed_paged(self.mixnode_page_limit, start_after.take()) .get_mixnodes_detailed_paged(self.mixnode_page_limit, start_after.take())
.await?; .await?;
mixnodes.append(&mut paged_response.nodes); mixnodes.append(&mut paged_response.nodes);
@@ -356,7 +356,7 @@ impl<C> Client<C> {
Ok(mixnodes) Ok(mixnodes)
} }
pub async fn get_all_nyxd_unbonded_mixnodes( pub async fn get_all_nymd_unbonded_mixnodes(
&self, &self,
) -> Result<Vec<(MixId, UnbondedMixnode)>, ValidatorClientError> ) -> Result<Vec<(MixId, UnbondedMixnode)>, ValidatorClientError>
where where
@@ -366,7 +366,7 @@ impl<C> Client<C> {
let mut start_after = None; let mut start_after = None;
loop { loop {
let mut paged_response = self let mut paged_response = self
.nyxd .nymd
.get_unbonded_paged(self.mixnode_page_limit, start_after.take()) .get_unbonded_paged(self.mixnode_page_limit, start_after.take())
.await?; .await?;
mixnodes.append(&mut paged_response.nodes); mixnodes.append(&mut paged_response.nodes);
@@ -381,7 +381,7 @@ impl<C> Client<C> {
Ok(mixnodes) Ok(mixnodes)
} }
pub async fn get_all_nyxd_unbonded_mixnodes_by_owner( pub async fn get_all_nymd_unbonded_mixnodes_by_owner(
&self, &self,
owner: &cosmrs::AccountId, owner: &cosmrs::AccountId,
) -> Result<Vec<(MixId, UnbondedMixnode)>, ValidatorClientError> ) -> Result<Vec<(MixId, UnbondedMixnode)>, ValidatorClientError>
@@ -392,7 +392,7 @@ impl<C> Client<C> {
let mut start_after = None; let mut start_after = None;
loop { loop {
let mut paged_response = self let mut paged_response = self
.nyxd .nymd
.get_unbonded_by_owner_paged(owner, self.mixnode_page_limit, start_after.take()) .get_unbonded_by_owner_paged(owner, self.mixnode_page_limit, start_after.take())
.await?; .await?;
mixnodes.append(&mut paged_response.nodes); mixnodes.append(&mut paged_response.nodes);
@@ -407,7 +407,7 @@ impl<C> Client<C> {
Ok(mixnodes) Ok(mixnodes)
} }
pub async fn get_all_nyxd_unbonded_mixnodes_by_identity( pub async fn get_all_nymd_unbonded_mixnodes_by_identity(
&self, &self,
identity_key: String, identity_key: String,
) -> Result<Vec<(MixId, UnbondedMixnode)>, ValidatorClientError> ) -> Result<Vec<(MixId, UnbondedMixnode)>, ValidatorClientError>
@@ -418,7 +418,7 @@ impl<C> Client<C> {
let mut start_after = None; let mut start_after = None;
loop { loop {
let mut paged_response = self let mut paged_response = self
.nyxd .nymd
.get_unbonded_by_identity_paged( .get_unbonded_by_identity_paged(
identity_key.clone(), identity_key.clone(),
self.mixnode_page_limit, self.mixnode_page_limit,
@@ -437,7 +437,7 @@ impl<C> Client<C> {
Ok(mixnodes) Ok(mixnodes)
} }
pub async fn get_all_nyxd_gateways(&self) -> Result<Vec<GatewayBond>, ValidatorClientError> pub async fn get_all_nymd_gateways(&self) -> Result<Vec<GatewayBond>, ValidatorClientError>
where where
C: CosmWasmClient + Sync + Send, C: CosmWasmClient + Sync + Send,
{ {
@@ -445,7 +445,7 @@ impl<C> Client<C> {
let mut start_after = None; let mut start_after = None;
loop { loop {
let mut paged_response = self let mut paged_response = self
.nyxd .nymd
.get_gateways_paged(start_after.take(), self.gateway_page_limit) .get_gateways_paged(start_after.take(), self.gateway_page_limit)
.await?; .await?;
gateways.append(&mut paged_response.nodes); gateways.append(&mut paged_response.nodes);
@@ -460,7 +460,7 @@ impl<C> Client<C> {
Ok(gateways) Ok(gateways)
} }
pub async fn get_all_nyxd_single_mixnode_delegations( pub async fn get_all_nymd_single_mixnode_delegations(
&self, &self,
mix_id: MixId, mix_id: MixId,
) -> Result<Vec<Delegation>, ValidatorClientError> ) -> Result<Vec<Delegation>, ValidatorClientError>
@@ -471,7 +471,7 @@ impl<C> Client<C> {
let mut start_after = None; let mut start_after = None;
loop { loop {
let mut paged_response = self let mut paged_response = self
.nyxd .nymd
.get_mixnode_delegations_paged( .get_mixnode_delegations_paged(
mix_id, mix_id,
start_after.take(), start_after.take(),
@@ -501,7 +501,7 @@ impl<C> Client<C> {
let mut start_after = None; let mut start_after = None;
loop { loop {
let mut paged_response = self let mut paged_response = self
.nyxd .nymd
.get_delegator_delegations_paged( .get_delegator_delegations_paged(
delegation_owner.to_string(), delegation_owner.to_string(),
start_after.take(), start_after.take(),
@@ -528,7 +528,7 @@ impl<C> Client<C> {
let mut start_after = None; let mut start_after = None;
loop { loop {
let mut paged_response = self let mut paged_response = self
.nyxd .nymd
.get_all_network_delegations_paged( .get_all_network_delegations_paged(
start_after.take(), start_after.take(),
self.mixnode_delegations_page_limit, self.mixnode_delegations_page_limit,
@@ -546,7 +546,7 @@ impl<C> Client<C> {
Ok(delegations) Ok(delegations)
} }
pub async fn get_all_nyxd_pending_epoch_events( pub async fn get_all_nymd_pending_epoch_events(
&self, &self,
) -> Result<Vec<PendingEpochEvent>, ValidatorClientError> ) -> Result<Vec<PendingEpochEvent>, ValidatorClientError>
where where
@@ -557,7 +557,7 @@ impl<C> Client<C> {
loop { loop {
let mut paged_response = self let mut paged_response = self
.nyxd .nymd
.get_pending_epoch_events_paged(start_after.take(), self.rewarded_set_page_limit) .get_pending_epoch_events_paged(start_after.take(), self.rewarded_set_page_limit)
.await?; .await?;
events.append(&mut paged_response.events); events.append(&mut paged_response.events);
@@ -572,7 +572,7 @@ impl<C> Client<C> {
Ok(events) Ok(events)
} }
pub async fn get_all_nyxd_pending_interval_events( pub async fn get_all_nymd_pending_interval_events(
&self, &self,
) -> Result<Vec<PendingIntervalEvent>, ValidatorClientError> ) -> Result<Vec<PendingIntervalEvent>, ValidatorClientError>
where where
@@ -583,7 +583,7 @@ impl<C> Client<C> {
loop { loop {
let mut paged_response = self let mut paged_response = self
.nyxd .nymd
.get_pending_interval_events_paged(start_after.take(), self.rewarded_set_page_limit) .get_pending_interval_events_paged(start_after.take(), self.rewarded_set_page_limit)
.await?; .await?;
events.append(&mut paged_response.events); events.append(&mut paged_response.events);
@@ -598,7 +598,7 @@ impl<C> Client<C> {
Ok(events) Ok(events)
} }
pub async fn get_all_nyxd_current_dealers( pub async fn get_all_nymd_current_dealers(
&self, &self,
) -> Result<Vec<DealerDetails>, ValidatorClientError> ) -> Result<Vec<DealerDetails>, ValidatorClientError>
where where
@@ -608,7 +608,7 @@ impl<C> Client<C> {
let mut start_after = None; let mut start_after = None;
loop { loop {
let mut paged_response = self let mut paged_response = self
.nyxd .nymd
.get_current_dealers_paged(start_after.take(), self.dealers_page_limit) .get_current_dealers_paged(start_after.take(), self.dealers_page_limit)
.await?; .await?;
dealers.append(&mut paged_response.dealers); dealers.append(&mut paged_response.dealers);
@@ -623,7 +623,7 @@ impl<C> Client<C> {
Ok(dealers) Ok(dealers)
} }
pub async fn get_all_nyxd_past_dealers( pub async fn get_all_nymd_past_dealers(
&self, &self,
) -> Result<Vec<DealerDetails>, ValidatorClientError> ) -> Result<Vec<DealerDetails>, ValidatorClientError>
where where
@@ -633,7 +633,7 @@ impl<C> Client<C> {
let mut start_after = None; let mut start_after = None;
loop { loop {
let mut paged_response = self let mut paged_response = self
.nyxd .nymd
.get_past_dealers_paged(start_after.take(), self.dealers_page_limit) .get_past_dealers_paged(start_after.take(), self.dealers_page_limit)
.await?; .await?;
dealers.append(&mut paged_response.dealers); dealers.append(&mut paged_response.dealers);
@@ -648,7 +648,7 @@ impl<C> Client<C> {
Ok(dealers) Ok(dealers)
} }
pub async fn get_all_nyxd_epoch_dealings( pub async fn get_all_nymd_epoch_dealings(
&self, &self,
idx: usize, idx: usize,
) -> Result<Vec<ContractDealing>, ValidatorClientError> ) -> Result<Vec<ContractDealing>, ValidatorClientError>
@@ -659,7 +659,7 @@ impl<C> Client<C> {
let mut start_after = None; let mut start_after = None;
loop { loop {
let mut paged_response = self let mut paged_response = self
.nyxd .nymd
.get_dealings_paged(idx, start_after.take(), self.dealers_page_limit) .get_dealings_paged(idx, start_after.take(), self.dealers_page_limit)
.await?; .await?;
dealings.append(&mut paged_response.dealings); dealings.append(&mut paged_response.dealings);
@@ -674,7 +674,7 @@ impl<C> Client<C> {
Ok(dealings) Ok(dealings)
} }
pub async fn get_all_nyxd_verification_key_shares( pub async fn get_all_nymd_verification_key_shares(
&self, &self,
) -> Result<Vec<ContractVKShare>, ValidatorClientError> ) -> Result<Vec<ContractVKShare>, ValidatorClientError>
where where
@@ -684,7 +684,7 @@ impl<C> Client<C> {
let mut start_after = None; let mut start_after = None;
loop { loop {
let mut paged_response = self let mut paged_response = self
.nyxd .nymd
.get_vk_shares_paged(start_after.take(), self.verification_key_page_limit) .get_vk_shares_paged(start_after.take(), self.verification_key_page_limit)
.await?; .await?;
shares.append(&mut paged_response.shares); shares.append(&mut paged_response.shares);
@@ -699,7 +699,7 @@ impl<C> Client<C> {
Ok(shares) Ok(shares)
} }
pub async fn get_all_nyxd_proposals( pub async fn get_all_nymd_proposals(
&self, &self,
) -> Result<Vec<ProposalResponse>, ValidatorClientError> ) -> Result<Vec<ProposalResponse>, ValidatorClientError>
where where
@@ -710,7 +710,7 @@ impl<C> Client<C> {
loop { loop {
let mut paged_response = self let mut paged_response = self
.nyxd .nymd
.list_proposals(start_after.take(), self.proposals_page_limit) .list_proposals(start_after.take(), self.proposals_page_limit)
.await?; .await?;
@@ -729,7 +729,7 @@ impl<C> Client<C> {
} }
// validator-api wrappers // validator-api wrappers
#[cfg(feature = "nyxd-client")] #[cfg(feature = "nymd-client")]
impl<C> Client<C> { impl<C> Client<C> {
pub fn change_nym_api(&mut self, new_endpoint: Url) { pub fn change_nym_api(&mut self, new_endpoint: Url) {
self.nym_api.change_url(new_endpoint) self.nym_api.change_url(new_endpoint)
@@ -783,23 +783,23 @@ impl<C> Client<C> {
#[derive(Clone)] #[derive(Clone)]
pub struct CoconutApiClient { pub struct CoconutApiClient {
pub api_client: NymApiClient, pub api_client: ApiClient,
pub verification_key: VerificationKey, pub verification_key: VerificationKey,
pub node_id: NodeIndex, pub node_id: NodeIndex,
#[cfg(feature = "nyxd-client")] #[cfg(feature = "nymd-client")]
pub cosmos_address: cosmrs::AccountId, pub cosmos_address: cosmrs::AccountId,
} }
#[cfg(feature = "nyxd-client")] #[cfg(feature = "nymd-client")]
impl CoconutApiClient { impl CoconutApiClient {
pub async fn all_coconut_api_clients<C>( pub async fn all_coconut_api_clients<C>(
nyxd_client: &Client<C>, nymd_client: &Client<C>,
) -> Result<Vec<Self>, ValidatorClientError> ) -> Result<Vec<Self>, ValidatorClientError>
where where
C: CosmWasmClient + Sync + Send, C: CosmWasmClient + Sync + Send,
{ {
Ok(nyxd_client Ok(nymd_client
.get_all_nyxd_verification_key_shares() .get_all_nymd_verification_key_shares()
.await? .await?
.into_iter() .into_iter()
.filter_map(Self::try_from) .filter_map(Self::try_from)
@@ -812,7 +812,7 @@ impl CoconutApiClient {
if let Ok(verification_key) = VerificationKey::try_from_bs58(&share.share) { if let Ok(verification_key) = VerificationKey::try_from_bs58(&share.share) {
if let Ok(cosmos_address) = cosmrs::AccountId::from_str(share.owner.as_str()) { if let Ok(cosmos_address) = cosmrs::AccountId::from_str(share.owner.as_str()) {
return Some(CoconutApiClient { return Some(CoconutApiClient {
api_client: NymApiClient::new(url_address), api_client: ApiClient::new(url_address),
verification_key, verification_key,
node_id: share.node_index, node_id: share.node_index,
cosmos_address, cosmos_address,
@@ -826,17 +826,17 @@ impl CoconutApiClient {
} }
#[derive(Clone)] #[derive(Clone)]
pub struct NymApiClient { pub struct ApiClient {
pub nym_api_client: nym_api::Client, pub nym_api_client: nym_api::Client,
// TODO: perhaps if we really need it at some (currently I don't see any reasons for it) // TODO: perhaps if we really need it at some (currently I don't see any reasons for it)
// we could re-implement the communication with the REST API on port 1317 // we could re-implement the communication with the REST API on port 1317
} }
impl NymApiClient { impl ApiClient {
pub fn new(api_url: Url) -> Self { pub fn new(api_url: Url) -> Self {
let nym_api_client = nym_api::Client::new(api_url); let nym_api_client = nym_api::Client::new(api_url);
NymApiClient { nym_api_client } ApiClient { nym_api_client }
} }
pub fn change_nym_api(&mut self, new_endpoint: Url) { pub fn change_nym_api(&mut self, new_endpoint: Url) {
@@ -1,8 +1,8 @@
use crate::nyxd::error::NyxdError; use crate::nymd::error::NymdError;
use crate::nyxd::{Config as ClientConfig, NyxdClient, QueryNyxdClient}; use crate::nymd::{Config as ClientConfig, NymdClient, QueryNymdClient};
use crate::NymApiClient; use crate::ApiClient;
use crate::nyxd::traits::MixnetQueryClient; use crate::nymd::traits::MixnetQueryClient;
use colored::Colorize; use colored::Colorize;
use core::fmt; use core::fmt;
use itertools::Itertools; use itertools::Itertools;
@@ -16,9 +16,9 @@ use url::Url;
const MAX_URLS_TESTED: usize = 200; const MAX_URLS_TESTED: usize = 200;
const CONNECTION_TEST_TIMEOUT_SEC: u64 = 2; const CONNECTION_TEST_TIMEOUT_SEC: u64 = 2;
/// Run connection tests for all specified nyxd and api urls. These are all run concurrently. // Run connection tests for all specified nymd and api urls. These are all run concurrently.
pub async fn run_validator_connection_test<H: BuildHasher + 'static>( pub async fn run_validator_connection_test<H: BuildHasher + 'static>(
nyxd_urls: impl Iterator<Item = (NymNetworkDetails, Url)>, nymd_urls: impl Iterator<Item = (NymNetworkDetails, Url)>,
api_urls: impl Iterator<Item = (NymNetworkDetails, Url)>, api_urls: impl Iterator<Item = (NymNetworkDetails, Url)>,
mixnet_contract_address: HashMap<NymNetworkDetails, cosmrs::AccountId, H>, mixnet_contract_address: HashMap<NymNetworkDetails, cosmrs::AccountId, H>,
) -> ( ) -> (
@@ -27,7 +27,7 @@ pub async fn run_validator_connection_test<H: BuildHasher + 'static>(
) { ) {
// Setup all the clients for the connection tests // Setup all the clients for the connection tests
let connection_test_clients = let connection_test_clients =
setup_connection_tests(nyxd_urls, api_urls, mixnet_contract_address); setup_connection_tests(nymd_urls, api_urls, mixnet_contract_address);
// Run all tests concurrently // Run all tests concurrently
let connection_results = futures::future::join_all( let connection_results = futures::future::join_all(
@@ -40,28 +40,28 @@ pub async fn run_validator_connection_test<H: BuildHasher + 'static>(
// Seperate and collect results into HashMaps // Seperate and collect results into HashMaps
( (
extract_and_collect_results_into_map(&connection_results, &UrlType::Nyxd), extract_and_collect_results_into_map(&connection_results, &UrlType::Nymd),
extract_and_collect_results_into_map(&connection_results, &UrlType::NymApi), extract_and_collect_results_into_map(&connection_results, &UrlType::Api),
) )
} }
fn setup_connection_tests<H: BuildHasher + 'static>( fn setup_connection_tests<H: BuildHasher + 'static>(
nyxd_urls: impl Iterator<Item = (NymNetworkDetails, Url)>, nymd_urls: impl Iterator<Item = (NymNetworkDetails, Url)>,
api_urls: impl Iterator<Item = (NymNetworkDetails, Url)>, api_urls: impl Iterator<Item = (NymNetworkDetails, Url)>,
mixnet_contract_address: HashMap<NymNetworkDetails, cosmrs::AccountId, H>, mixnet_contract_address: HashMap<NymNetworkDetails, cosmrs::AccountId, H>,
) -> impl Iterator<Item = ClientForConnectionTest> { ) -> impl Iterator<Item = ClientForConnectionTest> {
let nyxd_connection_test_clients = nyxd_urls.filter_map(move |(network, url)| { let nymd_connection_test_clients = nymd_urls.filter_map(move |(network, url)| {
let address = mixnet_contract_address let address = mixnet_contract_address
.get(&network) .get(&network)
.expect("No configured contract address") .expect("No configured contract address")
.clone(); .clone();
let config = ClientConfig::try_from_nym_network_details(&network) let config = ClientConfig::try_from_nym_network_details(&network)
.expect("failed to create valid nyxd client config"); .expect("failed to create valid nymd client config");
if let Ok(mut client) = NyxdClient::<QueryNyxdClient>::connect(config, url.as_str()) { if let Ok(mut client) = NymdClient::<QueryNymdClient>::connect(config, url.as_str()) {
// possibly redundant, but lets just leave it here // possibly redundant, but lets just leave it here
client.set_mixnet_contract_address(address); client.set_mixnet_contract_address(address);
Some(ClientForConnectionTest::Nyxd( Some(ClientForConnectionTest::Nymd(
network, network,
url, url,
Box::new(client), Box::new(client),
@@ -72,10 +72,10 @@ fn setup_connection_tests<H: BuildHasher + 'static>(
}); });
let api_connection_test_clients = api_urls.map(|(network, url)| { let api_connection_test_clients = api_urls.map(|(network, url)| {
ClientForConnectionTest::Api(network, url.clone(), NymApiClient::new(url)) ClientForConnectionTest::Api(network, url.clone(), ApiClient::new(url))
}); });
nyxd_connection_test_clients.chain(api_connection_test_clients) nymd_connection_test_clients.chain(api_connection_test_clients)
} }
fn extract_and_collect_results_into_map( fn extract_and_collect_results_into_map(
@@ -92,10 +92,10 @@ fn extract_and_collect_results_into_map(
.into_group_map() .into_group_map()
} }
async fn test_nyxd_connection( async fn test_nymd_connection(
network: NymNetworkDetails, network: NymNetworkDetails,
url: &Url, url: &Url,
client: &NyxdClient<QueryNyxdClient>, client: &NymdClient<QueryNymdClient>,
) -> ConnectionResult { ) -> ConnectionResult {
let result = match timeout( let result = match timeout(
Duration::from_secs(CONNECTION_TEST_TIMEOUT_SEC), Duration::from_secs(CONNECTION_TEST_TIMEOUT_SEC),
@@ -103,48 +103,48 @@ async fn test_nyxd_connection(
) )
.await .await
{ {
Ok(Err(NyxdError::TendermintError(e))) => { Ok(Err(NymdError::TendermintError(e))) => {
// If we get a tendermint-rpc error, we classify the node as not contactable // If we get a tendermint-rpc error, we classify the node as not contactable
log::debug!("Checking: nyxd url: {url}: {}: {}", "failed".red(), e); log::debug!("Checking: nymd_url: {url}: {}: {}", "failed".red(), e);
false false
} }
Ok(Err(NyxdError::AbciError { code, log, .. })) => { Ok(Err(NymdError::AbciError { code, log, .. })) => {
// We accept the mixnet contract not found as ok from a connection standpoint. This happens // We accept the mixnet contract not found as ok from a connection standpoint. This happens
// for example on a pre-launch network. // for example on a pre-launch network.
log::debug!( log::debug!(
"Checking: nyxd url: {url}: {}, but with abci error: {code}: {log}", "Checking: nymd_url: {url}: {}, but with abci error: {code}: {log}",
"success".green() "success".green()
); );
code == 18 code == 18
} }
Ok(Err(error @ NyxdError::NoContractAddressAvailable)) => { Ok(Err(error @ NymdError::NoContractAddressAvailable)) => {
log::debug!("Checking: nyxd url: {url}: {}: {error}", "failed".red()); log::debug!("Checking: nymd_url: {url}: {}: {error}", "failed".red());
false false
} }
Ok(Err(e)) => { Ok(Err(e)) => {
// For any other error, we're optimistic and just try anyway. // For any other error, we're optimistic and just try anyway.
log::debug!( log::debug!(
"Checking: nyxd_url: {url}: {}, but with error: {e}", "Checking: nymd_url: {url}: {}, but with error: {e}",
"success".green() "success".green()
); );
true true
} }
Ok(Ok(_)) => { Ok(Ok(_)) => {
log::debug!("Checking: nyxd_url: {url}: {}", "success".green()); log::debug!("Checking: nymd_url: {url}: {}", "success".green());
true true
} }
Err(e) => { Err(e) => {
log::debug!("Checking: nyxd_url: {url}: {}: {e}", "failed".red()); log::debug!("Checking: nymd_url: {url}: {}: {e}", "failed".red());
false false
} }
}; };
ConnectionResult::Nyxd(network, url.clone(), result) ConnectionResult::Nymd(network, url.clone(), result)
} }
async fn test_nym_api_connection( async fn test_api_connection(
network: NymNetworkDetails, network: NymNetworkDetails,
url: &Url, url: &Url,
client: &NymApiClient, client: &ApiClient,
) -> ConnectionResult { ) -> ConnectionResult {
let result = match timeout( let result = match timeout(
Duration::from_secs(CONNECTION_TEST_TIMEOUT_SEC), Duration::from_secs(CONNECTION_TEST_TIMEOUT_SEC),
@@ -169,18 +169,18 @@ async fn test_nym_api_connection(
} }
enum ClientForConnectionTest { enum ClientForConnectionTest {
Nyxd(NymNetworkDetails, Url, Box<NyxdClient<QueryNyxdClient>>), Nymd(NymNetworkDetails, Url, Box<NymdClient<QueryNymdClient>>),
Api(NymNetworkDetails, Url, NymApiClient), Api(NymNetworkDetails, Url, ApiClient),
} }
impl ClientForConnectionTest { impl ClientForConnectionTest {
async fn run_connection_check(self) -> ConnectionResult { async fn run_connection_check(self) -> ConnectionResult {
match self { match self {
ClientForConnectionTest::Nyxd(network, ref url, ref client) => { ClientForConnectionTest::Nymd(network, ref url, ref client) => {
test_nyxd_connection(network, url, client).await test_nymd_connection(network, url, client).await
} }
ClientForConnectionTest::Api(network, ref url, ref client) => { ClientForConnectionTest::Api(network, ref url, ref client) => {
test_nym_api_connection(network, url, client).await test_api_connection(network, url, client).await
} }
} }
} }
@@ -188,37 +188,37 @@ impl ClientForConnectionTest {
#[derive(Debug, PartialEq, Eq)] #[derive(Debug, PartialEq, Eq)]
enum UrlType { enum UrlType {
Nyxd, Nymd,
NymApi, Api,
} }
impl fmt::Display for UrlType { impl fmt::Display for UrlType {
fn fmt(&self, f: &mut fmt::Formatter<'_>) -> fmt::Result { fn fmt(&self, f: &mut fmt::Formatter<'_>) -> fmt::Result {
match self { match self {
UrlType::Nyxd => write!(f, "nyxd"), UrlType::Nymd => write!(f, "nymd"),
UrlType::NymApi => write!(f, "api"), UrlType::Api => write!(f, "api"),
} }
} }
} }
#[derive(Debug)] #[derive(Debug)]
enum ConnectionResult { enum ConnectionResult {
Nyxd(NymNetworkDetails, Url, bool), Nymd(NymNetworkDetails, Url, bool),
Api(NymNetworkDetails, Url, bool), Api(NymNetworkDetails, Url, bool),
} }
impl ConnectionResult { impl ConnectionResult {
fn result(&self) -> (&NymNetworkDetails, &Url, &bool) { fn result(&self) -> (&NymNetworkDetails, &Url, &bool) {
match self { match self {
ConnectionResult::Nyxd(network, url, result) ConnectionResult::Nymd(network, url, result)
| ConnectionResult::Api(network, url, result) => (network, url, result), | ConnectionResult::Api(network, url, result) => (network, url, result),
} }
} }
fn url_type(&self) -> UrlType { fn url_type(&self) -> UrlType {
match self { match self {
ConnectionResult::Nyxd(..) => UrlType::Nyxd, ConnectionResult::Nymd(..) => UrlType::Nymd,
ConnectionResult::Api(..) => UrlType::NymApi, ConnectionResult::Api(..) => UrlType::Api,
} }
} }
} }
@@ -15,9 +15,9 @@ pub enum ValidatorClientError {
#[error("One of the provided URLs was malformed - {0}")] #[error("One of the provided URLs was malformed - {0}")]
MalformedUrlProvided(#[from] url::ParseError), MalformedUrlProvided(#[from] url::ParseError),
#[cfg(feature = "nyxd-client")] #[cfg(feature = "nymd-client")]
#[error("There was an issue with the Nyxd client - {0}")] #[error("There was an issue with the Nymd client - {0}")]
NyxdError(#[from] crate::nyxd::error::NyxdError), NymdError(#[from] crate::nymd::error::NymdError),
#[error("No validator API url has been provided")] #[error("No validator API url has been provided")]
NoAPIUrlAvailable, NoAPIUrlAvailable,
@@ -2,17 +2,17 @@
// SPDX-License-Identifier: Apache-2.0 // SPDX-License-Identifier: Apache-2.0
pub mod client; pub mod client;
#[cfg(feature = "nyxd-client")] #[cfg(feature = "nymd-client")]
pub mod connection_tester; pub mod connection_tester;
mod error; mod error;
pub mod nym_api; pub mod nym_api;
#[cfg(feature = "nyxd-client")] #[cfg(feature = "nymd-client")]
pub mod nyxd; pub mod nymd;
#[cfg(feature = "nyxd-client")] #[cfg(feature = "nymd-client")]
pub use crate::client::{CoconutApiClient, NymApiClient}; pub use crate::client::{ApiClient, CoconutApiClient};
pub use crate::error::ValidatorClientError; pub use crate::error::ValidatorClientError;
pub use nym_api_requests::*; pub use nym_api_requests::*;
#[cfg(feature = "nyxd-client")] #[cfg(feature = "nymd-client")]
pub use client::{Client, Config}; pub use client::{Client, Config};
@@ -366,8 +366,8 @@ impl Client {
&self, &self,
mix_id: MixId, mix_id: MixId,
request_body: &ComputeRewardEstParam, request_body: &ComputeRewardEstParam,
) -> Result<RewardEstimationResponse, NymAPIError> { ) -> Result<RewardEstimationResponse, ValidatorAPIError> {
self.post_nym_api( self.post_validator_api(
&[ &[
routes::API_VERSION, routes::API_VERSION,
routes::STATUS_ROUTES, routes::STATUS_ROUTES,

Some files were not shown because too many files have changed in this diff Show More