Compare commits

..

1 Commits

Author SHA1 Message Date
Bogdan-Ștefan Neacşu 3aa2d859a2 Gateway ipv6 separation of peers 2024-11-13 16:57:23 +00:00
380 changed files with 10148 additions and 12028 deletions
@@ -15,6 +15,24 @@ on:
type: boolean
schedule:
- cron: "14 0 * * *"
pull_request:
paths:
- "clients/**"
- "common/**"
- "explorer-api/**"
- "gateway/**"
- "integrations/**"
- "mixnode/**"
- "nym-api/**"
- "nym-node/**"
- "nym-outfox/**"
- 'nym-data-observatory/**'
- "nym-validator-rewarder/**"
- "sdk/rust/nym-sdk/**"
- "service-providers/**"
- "tools/**"
- "nymvisor/**"
- ".github/workflows/ci-build-upload-binaries.yml"
jobs:
publish-nym:
+1 -1
View File
@@ -9,7 +9,7 @@ on:
jobs:
cargo-deny:
runs-on: ubuntu-latest
runs-on: arc-ubuntu-22.04-dind
strategy:
matrix:
checks:
@@ -2,5 +2,9 @@
{
"rust":"stable",
"runOnEvent":"always"
},
{
"rust":"beta",
"runOnEvent":"pull_request"
}
]
+1 -1
View File
@@ -11,7 +11,7 @@ on:
jobs:
check-schema:
name: Generate and check schema
runs-on: ubuntu-20.04
runs-on: arc-ubuntu-20.04
env:
CARGO_TERM_COLOR: always
steps:
@@ -2,6 +2,11 @@ name: ci-contracts-upload-binaries
on:
workflow_dispatch:
pull_request:
paths:
- 'common/**'
- 'contracts/**'
- '.github/workflows/ci-contracts-upload-binaries.yml'
env:
NETWORK: mainnet
+1 -1
View File
@@ -13,7 +13,7 @@ on:
jobs:
matrix_prep:
runs-on: ubuntu-20.04
runs-on: arc-ubuntu-20.04
outputs:
matrix: ${{ steps.set-matrix.outputs.matrix }}
steps:
+39
View File
@@ -0,0 +1,39 @@
name: ci-nym-api-tests
on:
workflow_dispatch:
push:
paths:
- "nym-api/**"
defaults:
run:
working-directory: nym-api/tests
jobs:
test:
name: nym-api tests
runs-on: ubuntu-latest
steps:
- uses: actions/checkout@v4
- name: install yarn in root
run: cd ../.. && yarn install
- name: Install npm
run: npm install
- name: Node v18
uses: actions/setup-node@v4
with:
node-version: 18.1.0
- name: Install yarn
run: yarn install
- name: Run yarn
run: yarn
- name: Run tests
run: yarn test:sandbox
working-directory: nym-api/tests
@@ -55,7 +55,6 @@ jobs:
uses: actions-rs/toolchain@v1
with:
toolchain: stable
override: true
- name: Build all binaries
uses: actions-rs/cargo@v1
+3 -4
View File
@@ -14,14 +14,13 @@ jobs:
- name: Install Rust stable
uses: actions-rs/toolchain@v1
with:
toolchain: 1.77
toolchain: stable
target: wasm32-unknown-unknown
override: true
components: rustfmt, clippy
- name: Install wasm-opt
uses: ./.github/actions/install-wasm-opt
with:
version: '114'
run: cargo install --version 0.114.0 wasm-opt
- name: Build release contracts
run: make contracts
+1 -1
View File
@@ -26,7 +26,7 @@ jobs:
git config --global user.name "Lawrence Stalder"
- name: Get version from cargo.toml
uses: mikefarah/yq@v4.44.5
uses: mikefarah/yq@v4.44.3
id: get_version
with:
cmd: yq -oy '.package.version' ${{ env.WORKING_DIRECTORY }}/nym-credential-proxy/Cargo.toml
+1 -1
View File
@@ -26,7 +26,7 @@ jobs:
git config --global user.name "Lawrence Stalder"
- name: Get version from cargo.toml
uses: mikefarah/yq@v4.44.5
uses: mikefarah/yq@v4.44.3
id: get_version
with:
cmd: yq -oy '.package.version' ${{ env.WORKING_DIRECTORY }}/Cargo.toml
+18 -14
View File
@@ -25,27 +25,31 @@ jobs:
git config --global user.email "lawrence@nymtech.net"
git config --global user.name "Lawrence Stalder"
- name: Get version from cargo.toml
uses: mikefarah/yq@v4.44.5
- name: Get version from package.json
uses: sergeysova/jq-action@v2
id: get_version
with:
cmd: yq -oy '.package.version' ${{ env.WORKING_DIRECTORY }}/nym-network-monitor/Cargo.toml
cmd: jq -r '.version' ${{ env.WORKING_DIRECTORY }}/package.json
- name: Check if tag exists
run: |
if git rev-parse ${{ steps.get_version.outputs.value }} >/dev/null 2>&1; then
echo "Tag ${{ steps.get_version.outputs.value }} already exists"
fi
- name: Remove existing tag if exists
run: |
echo "Checking if tag ${{ env.CONTAINER_NAME }}-${{ steps.get_version.outputs.result }} exists..."
if git rev-parse ${{ env.CONTAINER_NAME }}-${{ steps.get_version.outputs.result }} >/dev/null 2>&1; then
echo "Tag ${{ env.CONTAINER_NAME }}-${{ steps.get_version.outputs.result }} already exists"
git push --delete origin ${{ env.CONTAINER_NAME }}-${{ steps.get_version.outputs.result }}
git tag -d ${{ env.CONTAINER_NAME }}-${{ steps.get_version.outputs.result }}
if git rev-parse ${{ steps.get_version.outputs.value }} >/dev/null 2>&1; then
git push --delete origin ${{ steps.get_version.outputs.value }}
git tag -d ${{ steps.get_version.outputs.value }}
fi
- name: Create tag
run: |
git tag -a ${{ env.CONTAINER_NAME }}-${{ steps.get_version.outputs.result }} -m "Version ${{ steps.get_version.outputs.result }}"
git push origin ${{ env.CONTAINER_NAME }}-${{ steps.get_version.outputs.result }}
git tag -a ${{ steps.get_version.outputs.value }} -m "Version ${{ steps.get_version.outputs.value }}"
git push origin ${{ steps.get_version.outputs.value }}
- name: BuildAndPushImageOnHarbor
run: |
docker build -f nym-network-monitor.dockerfile ${{ env.WORKING_DIRECTORY }} -t harbor.nymte.ch/nym/${{ env.CONTAINER_NAME }}:${{ steps.get_version.outputs.result }} -t harbor.nymte.ch/nym/${{ env.CONTAINER_NAME }}:latest
docker push harbor.nymte.ch/nym/${{ env.CONTAINER_NAME }} --all-tags
docker build -f nym-network-monitor.dockerfile ${{ env.WORKING_DIRECTORY }} -t harbor.nymte.ch/nym/${{ env.CONTAINER_NAME }}:${{ steps.get_version.outputs.value }} -t harbor.nymte.ch/nym/${{ env.CONTAINER_NAME }}:latest
docker push harbor.nymte.ch/nym/${{ env.CONTAINER_NAME }} --all-tags
@@ -31,7 +31,7 @@ jobs:
git config --global user.name "Lawrence Stalder"
- name: Get version from cargo.toml
uses: mikefarah/yq@v4.44.5
uses: mikefarah/yq@v4.44.3
id: get_version
with:
cmd: yq -oy '.package.version' ${{ env.WORKING_DIRECTORY }}/Cargo.toml
@@ -58,4 +58,4 @@ jobs:
- name: BuildAndPushImageOnHarbor
run: |
docker build --build-arg GIT_REF=${{ github.event.inputs.gateway_probe_git_ref }} -f ${{ env.WORKING_DIRECTORY }}/Dockerfile . -t harbor.nymte.ch/nym/${{ env.CONTAINER_NAME }}:${{ steps.get_version.outputs.result }}-${{ steps.cleanup_gateway_probe_ref.outputs.git_ref }}
docker push harbor.nymte.ch/nym/${{ env.CONTAINER_NAME }} --all-tags
docker push harbor.nymte.ch/nym/${{ env.CONTAINER_NAME }} --all-tags
+1 -1
View File
@@ -26,7 +26,7 @@ jobs:
git config --global user.name "Lawrence Stalder"
- name: Get version from cargo.toml
uses: mikefarah/yq@v4.44.5
uses: mikefarah/yq@v4.44.3
id: get_version
with:
cmd: yq -oy '.package.version' ${{ env.WORKING_DIRECTORY }}/Cargo.toml
+1 -1
View File
@@ -26,7 +26,7 @@ jobs:
git config --global user.name "Lawrence Stalder"
- name: Get version from cargo.toml
uses: mikefarah/yq@v4.44.5
uses: mikefarah/yq@v4.44.3
id: get_version
with:
cmd: yq -oy '.package.version' ${{ env.WORKING_DIRECTORY }}/Cargo.toml
@@ -26,7 +26,7 @@ jobs:
git config --global user.name "Lawrence Stalder"
- name: Get version from cargo.toml
uses: mikefarah/yq@v4.44.5
uses: mikefarah/yq@v4.44.3
id: get_version
with:
cmd: yq -oy '.package.version' ${{ env.WORKING_DIRECTORY }}/nym-credential-proxy/Cargo.toml
-198
View File
@@ -4,204 +4,6 @@ Post 1.0.0 release, the changelog format is based on [Keep a Changelog](https://
## [Unreleased]
## [2024.13-magura-patched] (2024-11-22)
- [experimental] allow clients to change between deterministic route selection based on packet headers and a pseudorandom distribution
- Introduced a configurable limit on retransmission frequency of packets if ACKs are not received
- Filtered out invalid IP addresses on nym-api
## [2024.13-magura] (2024-11-18)
- Limit race probability ([#5145])
- bugifx: assign 'node_id' when converting from 'GatewayDetails' to 'TestNode' ([#5143])
- bugfix: make sure to assign correct node_id and identity during 'gateway_details' table migration ([#5142])
- Respond to auth messages with same version ([#5140])
- Pain/polyfill deprecated endpoints ([#5131])
- change: dont select mixnodes bonded with vested tokens into the rewarded set ([#5129])
- nym-credential-proxy-requests: reqwest use rustls-tls ([#5116])
- bugfix: preserve as much as possible of the rewarded set during migration ([#5103])
- Feature/force refresh node ([#5101])
- Add NYM_VPN_API to env files ([#5099])
- bugfix: fixed historical uptimes for nodes ([#5097])
- Remove old use of 1GB constant ([#5096])
- Graceful agent 1.1.5 ([#5093])
- Add more translations from v2 to v3 authenticator ([#5091])
- Nym node - Fix claim delegator rewards ([#5090])
- Make 250 GB/30 days for free ride mode ([#5083])
- Don't increase bandwidth two times ([#5081])
- Fix expiration date as today + 7 days ([#5076])
- Fix gateway decreasing bandwidth ([#5075])
- Allow custom http port to be reset ([#5073])
- bugfix: additional checks inside credential proxy ([#5072])
- chore: deprecated old nym-api client methods and replaced them when possible ([#5069])
- NS API with directory v2 (#5058) ([#5068])
- bugfix: credential-proxy obtain-async ([#5067])
- Allow nym node config updates ([#5066])
- bugfix: use corrext axum extractors for ecash route arguments ([#5065])
- Merge2/release/2024.13 magura ([#5063])
- bugfix/feature: added NymApiClient method to get all skimmed nodes ([#5062])
- Merge1/release/2024.13 magura ([#5061])
- added hacky routes to return nymnodes alongside legacy nodes ([#5051])
- bugfix: mark migrated gateways as rewarded in the previous epoch in case theyre in the rewarded set ([#5049])
- bugfix: adjust runtime storage migration ([#5047])
- bugfix: supersede 'cb13be27f8f61d9ae74d924e85d2e6787895eb14' by using… ([#5046])
- bugfix: restore default http port for nym-api ([#5045])
- bugfix: fix ecash handlers routes ([#5043])
- bugfix: don't assign exit gateways to standby set ([#5041])
- bugfix: make sure nym-nodes are also tested by network monitor ([#5040])
- bugfix: use bonded nym-nodes for determining initial network monitor … ([#5039])
- bugfix: make gateways insert themselves into [local] topology ([#5038])
- Pass poisson flag ([#5037])
- bugfix: use human readable roles for annotations ([#5036])
- bugfix: use old name for 'epoch_role' in SkimmedNode ([#5034])
- bugfix: make sure to use correct highest node id when assigning role ([#5032])
- feature: use axum_client_ip for attempting to extract source ip ([#5031])
- bugfix: fixed backwards incompatibility for /gateways/described endpoint ([#5030])
- bugfix: verifying signed information of legacy nodes ([#5029])
- bugfix: introduce 'LegacyPendingMixNodeChanges' that does not contain 'cost_params_change' ([#5028])
- bugfix: missing #[serde(default)] for announce port ([#5024])
- bugfix: directory v2.1 `get_all_avg_gateway_reliability_in_interval` query ([#5023])
- added 'get_all_described_nodes' to NymApiClient and adjusted return t… ([#5016])
- Reapply fixes to new branch ([#5014])
- Consume only positive bandwidth ([#5013])
- feature: adjusted ticket sizes to the agreed amounts ([#5009])
- Push private ip before inserting ([#5008])
- chore: update itertools in compact ecash ([#4994])
- feature: make accepting t&c a hard requirement for rewarded set selection ([#4993])
- Fix rustfmt in nym-credential-proxy ([#4992])
- bugfix: client memory leak ([#4991])
- Eliminate 0 bandwidth race check ([#4988])
- [DOCs;/operators]: Release notes for v2024.12 aero ([#4984])
- Add topup req constructor ([#4983])
- Fix critical issues SI86 and SI87 from Cure53 ([#4982])
- Rename nym-vpn-api to nym-credential-proxy ([#4981])
- enable global ecash routes even if api is not a signer ([#4980])
- resolve beta clippy issues in contracts ([#4978])
- Re-enable vested delegation migration ([#4977])
- feature: require reporting using nym-node binary for rewarded set selection ([#4976])
- Top up bandwidth ([#4975])
- [Product Data] Add session type based on ecash ticket received ([#4974])
- Bugfix/additional directory fixes ([#4973])
- feat: add Dockerfile for nym node ([#4972])
- chore: remove unused rocket code ([#4968])
- Import nym-vpn-api crates ([#4967])
- feature: importer-cli to correctly handle mixnet/vesting import ([#4966])
- bugfix: fix expected return type on /v1/gateways endpoint ([#4965])
- [Product Data] First step in gateway usage data collection ([#4963])
- Bump sqlx to 0.7.4 ([#4959])
- Add env feature to clap and make clap parameters available as env variables ([#4957])
- Feature/contract state tools ([#4954])
- expose authenticator address along other address in node-details ([#4953])
- Extract packet processing from mixnode-common ([#4949])
- nym-api container ([#4948])
- Ticket type storage ([#4947])
- Add "utoipa" feature to nym-node ([#4945])
- build(deps): bump the patch-updates group across 1 directory with 9 updates ([#4944])
- V2 performance monitoring feature flag ([#4943])
- Bugfix/rewarder post pruning adjustments ([#4942])
- Switch over the last set of jobs to arc runners ([#4938])
- Fix broken build after merge ([#4937])
- bugfix: correctly paginate through 'search_tx' endpoint ([#4936])
- Add more conversions for responses of authenticator messages ([#4929])
- Directory Sevices v2.1 ([#4903])
- Migrate Legacy Node (Frontend) ([#4826])
- Fix critical issues SI84 and SI85 from Cure53 ([#4758])
[#5145]: https://github.com/nymtech/nym/pull/5145
[#5143]: https://github.com/nymtech/nym/pull/5143
[#5142]: https://github.com/nymtech/nym/pull/5142
[#5140]: https://github.com/nymtech/nym/pull/5140
[#5131]: https://github.com/nymtech/nym/pull/5131
[#5129]: https://github.com/nymtech/nym/pull/5129
[#5116]: https://github.com/nymtech/nym/pull/5116
[#5103]: https://github.com/nymtech/nym/pull/5103
[#5101]: https://github.com/nymtech/nym/pull/5101
[#5099]: https://github.com/nymtech/nym/pull/5099
[#5097]: https://github.com/nymtech/nym/pull/5097
[#5096]: https://github.com/nymtech/nym/pull/5096
[#5093]: https://github.com/nymtech/nym/pull/5093
[#5091]: https://github.com/nymtech/nym/pull/5091
[#5090]: https://github.com/nymtech/nym/pull/5090
[#5083]: https://github.com/nymtech/nym/pull/5083
[#5081]: https://github.com/nymtech/nym/pull/5081
[#5076]: https://github.com/nymtech/nym/pull/5076
[#5075]: https://github.com/nymtech/nym/pull/5075
[#5073]: https://github.com/nymtech/nym/pull/5073
[#5072]: https://github.com/nymtech/nym/pull/5072
[#5069]: https://github.com/nymtech/nym/pull/5069
[#5068]: https://github.com/nymtech/nym/pull/5068
[#5067]: https://github.com/nymtech/nym/pull/5067
[#5066]: https://github.com/nymtech/nym/pull/5066
[#5065]: https://github.com/nymtech/nym/pull/5065
[#5063]: https://github.com/nymtech/nym/pull/5063
[#5062]: https://github.com/nymtech/nym/pull/5062
[#5061]: https://github.com/nymtech/nym/pull/5061
[#5051]: https://github.com/nymtech/nym/pull/5051
[#5049]: https://github.com/nymtech/nym/pull/5049
[#5047]: https://github.com/nymtech/nym/pull/5047
[#5046]: https://github.com/nymtech/nym/pull/5046
[#5045]: https://github.com/nymtech/nym/pull/5045
[#5043]: https://github.com/nymtech/nym/pull/5043
[#5041]: https://github.com/nymtech/nym/pull/5041
[#5040]: https://github.com/nymtech/nym/pull/5040
[#5039]: https://github.com/nymtech/nym/pull/5039
[#5038]: https://github.com/nymtech/nym/pull/5038
[#5037]: https://github.com/nymtech/nym/pull/5037
[#5036]: https://github.com/nymtech/nym/pull/5036
[#5034]: https://github.com/nymtech/nym/pull/5034
[#5032]: https://github.com/nymtech/nym/pull/5032
[#5031]: https://github.com/nymtech/nym/pull/5031
[#5030]: https://github.com/nymtech/nym/pull/5030
[#5029]: https://github.com/nymtech/nym/pull/5029
[#5028]: https://github.com/nymtech/nym/pull/5028
[#5024]: https://github.com/nymtech/nym/pull/5024
[#5023]: https://github.com/nymtech/nym/pull/5023
[#5016]: https://github.com/nymtech/nym/pull/5016
[#5014]: https://github.com/nymtech/nym/pull/5014
[#5013]: https://github.com/nymtech/nym/pull/5013
[#5009]: https://github.com/nymtech/nym/pull/5009
[#5008]: https://github.com/nymtech/nym/pull/5008
[#4994]: https://github.com/nymtech/nym/pull/4994
[#4993]: https://github.com/nymtech/nym/pull/4993
[#4992]: https://github.com/nymtech/nym/pull/4992
[#4991]: https://github.com/nymtech/nym/pull/4991
[#4988]: https://github.com/nymtech/nym/pull/4988
[#4984]: https://github.com/nymtech/nym/pull/4984
[#4983]: https://github.com/nymtech/nym/pull/4983
[#4982]: https://github.com/nymtech/nym/pull/4982
[#4981]: https://github.com/nymtech/nym/pull/4981
[#4980]: https://github.com/nymtech/nym/pull/4980
[#4978]: https://github.com/nymtech/nym/pull/4978
[#4977]: https://github.com/nymtech/nym/pull/4977
[#4976]: https://github.com/nymtech/nym/pull/4976
[#4975]: https://github.com/nymtech/nym/pull/4975
[#4974]: https://github.com/nymtech/nym/pull/4974
[#4973]: https://github.com/nymtech/nym/pull/4973
[#4972]: https://github.com/nymtech/nym/pull/4972
[#4968]: https://github.com/nymtech/nym/pull/4968
[#4967]: https://github.com/nymtech/nym/pull/4967
[#4966]: https://github.com/nymtech/nym/pull/4966
[#4965]: https://github.com/nymtech/nym/pull/4965
[#4963]: https://github.com/nymtech/nym/pull/4963
[#4959]: https://github.com/nymtech/nym/pull/4959
[#4957]: https://github.com/nymtech/nym/pull/4957
[#4954]: https://github.com/nymtech/nym/pull/4954
[#4953]: https://github.com/nymtech/nym/pull/4953
[#4949]: https://github.com/nymtech/nym/pull/4949
[#4948]: https://github.com/nymtech/nym/pull/4948
[#4947]: https://github.com/nymtech/nym/pull/4947
[#4945]: https://github.com/nymtech/nym/pull/4945
[#4944]: https://github.com/nymtech/nym/pull/4944
[#4943]: https://github.com/nymtech/nym/pull/4943
[#4942]: https://github.com/nymtech/nym/pull/4942
[#4938]: https://github.com/nymtech/nym/pull/4938
[#4937]: https://github.com/nymtech/nym/pull/4937
[#4936]: https://github.com/nymtech/nym/pull/4936
[#4929]: https://github.com/nymtech/nym/pull/4929
[#4903]: https://github.com/nymtech/nym/pull/4903
[#4826]: https://github.com/nymtech/nym/pull/4826
[#4758]: https://github.com/nymtech/nym/pull/4758
## [2024.12-aero] (2024-10-17)
- nym-node: don't use bloomfilters for double spending checks ([#4960])
Generated
+136 -156
View File
@@ -11,7 +11,7 @@ dependencies = [
"macroific",
"proc-macro2",
"quote",
"syn 2.0.87",
"syn 2.0.82",
]
[[package]]
@@ -283,7 +283,7 @@ dependencies = [
"proc-macro2",
"quote",
"serde",
"syn 2.0.87",
"syn 2.0.82",
]
[[package]]
@@ -352,7 +352,7 @@ checksum = "16e62a023e7c117e27523144c5d2459f4397fcc3cab0085af8e2224f643a0193"
dependencies = [
"proc-macro2",
"quote",
"syn 2.0.87",
"syn 2.0.82",
]
[[package]]
@@ -363,7 +363,7 @@ checksum = "721cae7de5c34fbb2acd27e21e6d2cf7b886dce0c27388d46c4e6c47ea4318dd"
dependencies = [
"proc-macro2",
"quote",
"syn 2.0.87",
"syn 2.0.82",
]
[[package]]
@@ -573,7 +573,7 @@ checksum = "57d123550fa8d071b7255cb0cc04dc302baa6c8c4a79f55701552684d8399bce"
dependencies = [
"proc-macro2",
"quote",
"syn 2.0.87",
"syn 2.0.82",
]
[[package]]
@@ -1140,7 +1140,7 @@ dependencies = [
"heck 0.5.0",
"proc-macro2",
"quote",
"syn 2.0.87",
"syn 2.0.82",
]
[[package]]
@@ -1790,7 +1790,7 @@ checksum = "f46882e17999c6cc590af592290432be3bce0428cb0d5f8b6715e4dc7b383eb3"
dependencies = [
"proc-macro2",
"quote",
"syn 2.0.87",
"syn 2.0.82",
]
[[package]]
@@ -1948,7 +1948,7 @@ dependencies = [
"proc-macro2",
"quote",
"strsim 0.11.1",
"syn 2.0.87",
"syn 2.0.82",
]
[[package]]
@@ -1970,7 +1970,7 @@ checksum = "733cabb43482b1a1b53eee8583c2b9e8684d592215ea83efd305dd31bc2f0178"
dependencies = [
"darling_core 0.20.9",
"quote",
"syn 2.0.87",
"syn 2.0.82",
]
[[package]]
@@ -2021,7 +2021,7 @@ dependencies = [
"macroific",
"proc-macro2",
"quote",
"syn 2.0.87",
"syn 2.0.82",
]
[[package]]
@@ -2064,7 +2064,7 @@ checksum = "67e77553c4162a157adbf834ebae5b415acbecbeafc7a74b0e886657506a7611"
dependencies = [
"proc-macro2",
"quote",
"syn 2.0.87",
"syn 2.0.82",
]
[[package]]
@@ -2097,7 +2097,7 @@ dependencies = [
"proc-macro2",
"proc-macro2-diagnostics",
"quote",
"syn 2.0.87",
"syn 2.0.82",
]
[[package]]
@@ -2165,7 +2165,7 @@ checksum = "487585f4d0c6655fe74905e2504d8ad6908e4db67f744eb140876906c2f3175d"
dependencies = [
"proc-macro2",
"quote",
"syn 2.0.87",
"syn 2.0.82",
]
[[package]]
@@ -2428,7 +2428,7 @@ dependencies = [
[[package]]
name = "explorer-api"
version = "1.1.42"
version = "1.1.41"
dependencies = [
"chrono",
"clap 4.5.20",
@@ -2531,7 +2531,7 @@ dependencies = [
"macroific",
"proc-macro2",
"quote",
"syn 2.0.87",
"syn 2.0.82",
]
[[package]]
@@ -2765,7 +2765,7 @@ checksum = "87750cf4b7a4c0625b1529e4c543c2182106e4dedc60a2a6455e00d212c489ac"
dependencies = [
"proc-macro2",
"quote",
"syn 2.0.87",
"syn 2.0.82",
]
[[package]]
@@ -2860,7 +2860,7 @@ dependencies = [
"proc-macro-error2",
"proc-macro2",
"quote",
"syn 2.0.87",
"syn 2.0.82",
]
[[package]]
@@ -3822,9 +3822,9 @@ dependencies = [
[[package]]
name = "libc"
version = "0.2.162"
version = "0.2.155"
source = "registry+https://github.com/rust-lang/crates.io-index"
checksum = "18d287de67fe55fd7e1581fe933d965a5a9477b38e949cfa9f8574ef01506398"
checksum = "97b3888a4aecf77e811145cadf6eef5901f4782c53886191b2f693f24761847c"
[[package]]
name = "libm"
@@ -3950,7 +3950,7 @@ dependencies = [
"cfg-if",
"proc-macro2",
"quote",
"syn 2.0.87",
"syn 2.0.82",
]
[[package]]
@@ -3961,7 +3961,7 @@ checksum = "13198c120864097a565ccb3ff947672d969932b7975ebd4085732c9f09435e55"
dependencies = [
"proc-macro2",
"quote",
"syn 2.0.87",
"syn 2.0.82",
]
[[package]]
@@ -3974,7 +3974,7 @@ dependencies = [
"macroific_core",
"proc-macro2",
"quote",
"syn 2.0.87",
"syn 2.0.82",
]
[[package]]
@@ -4431,7 +4431,7 @@ dependencies = [
"proc-macro-crate",
"proc-macro2",
"quote",
"syn 2.0.87",
"syn 2.0.82",
]
[[package]]
@@ -4451,7 +4451,7 @@ checksum = "830b246a0e5f20af87141b25c173cd1b609bd7779a4617d6ec582abaf90870f3"
[[package]]
name = "nym-api"
version = "1.1.46"
version = "1.1.45"
dependencies = [
"anyhow",
"async-trait",
@@ -4470,7 +4470,6 @@ dependencies = [
"cw2",
"cw3",
"cw4",
"dashmap",
"dirs",
"futures",
"getset",
@@ -4503,9 +4502,7 @@ dependencies = [
"nym-pemstore",
"nym-serde-helpers",
"nym-sphinx",
"nym-statistics-common",
"nym-task",
"nym-ticketbooks-merkle",
"nym-topology",
"nym-types",
"nym-validator-client",
@@ -4515,7 +4512,6 @@ dependencies = [
"rand_chacha",
"reqwest 0.12.4",
"schemars",
"semver 1.0.23",
"serde",
"serde_json",
"sha2 0.9.9",
@@ -4546,7 +4542,6 @@ dependencies = [
"ecdsa",
"getset",
"nym-compact-ecash",
"nym-contracts-common",
"nym-credentials-interface",
"nym-crypto",
"nym-ecash-time",
@@ -4554,8 +4549,6 @@ dependencies = [
"nym-network-defaults",
"nym-node-requests",
"nym-serde-helpers",
"nym-ticketbooks-merkle",
"rand_chacha",
"schemars",
"serde",
"serde_json",
@@ -4701,7 +4694,7 @@ dependencies = [
[[package]]
name = "nym-cli"
version = "1.1.44"
version = "1.1.43"
dependencies = [
"anyhow",
"base64 0.22.1",
@@ -4782,7 +4775,7 @@ dependencies = [
[[package]]
name = "nym-client"
version = "1.1.44"
version = "1.1.42"
dependencies = [
"bs58",
"clap 4.5.20",
@@ -4890,6 +4883,7 @@ dependencies = [
"nym-sphinx-addressing",
"nym-sphinx-params",
"serde",
"serde_with",
"thiserror",
"url",
]
@@ -5011,9 +5005,6 @@ dependencies = [
name = "nym-common-models"
version = "0.1.0"
dependencies = [
"anyhow",
"bincode",
"nym-crypto",
"serde",
]
@@ -5433,12 +5424,19 @@ dependencies = [
"async-trait",
"bip39",
"bs58",
"clap 4.5.20",
"colored",
"dashmap",
"defguard_wireguard_rs",
"dirs",
"dotenvy",
"futures",
"humantime-serde",
"ipnetwork 0.20.0",
"nym-api-requests",
"nym-authenticator",
"nym-bin-common",
"nym-config",
"nym-credential-verification",
"nym-credentials",
"nym-credentials-interface",
@@ -5452,6 +5450,7 @@ dependencies = [
"nym-network-defaults",
"nym-network-requester",
"nym-node-http-api",
"nym-pemstore",
"nym-sdk",
"nym-sphinx",
"nym-statistics-common",
@@ -5461,9 +5460,14 @@ dependencies = [
"nym-validator-client",
"nym-wireguard",
"nym-wireguard-types",
"once_cell",
"rand",
"serde",
"serde_json",
"sha2 0.10.8",
"si-scale",
"sqlx",
"subtle-encoding",
"thiserror",
"time",
"tokio",
@@ -5491,7 +5495,6 @@ dependencies = [
"nym-network-defaults",
"nym-pemstore",
"nym-sphinx",
"nym-statistics-common",
"nym-task",
"nym-validator-client",
"rand",
@@ -5766,10 +5769,10 @@ dependencies = [
"cw-storage-plus",
"cw2",
"humantime-serde",
"log",
"nym-contracts-common",
"rand_chacha",
"schemars",
"semver 1.0.23",
"serde",
"serde-json-wasm",
"serde_repr",
@@ -5783,8 +5786,19 @@ dependencies = [
name = "nym-mixnode"
version = "1.1.37"
dependencies = [
"anyhow",
"axum 0.7.7",
"bs58",
"clap 4.5.20",
"colored",
"cupid",
"dirs",
"futures",
"humantime-serde",
"lazy_static",
"log",
"nym-bin-common",
"nym-config",
"nym-contracts-common",
"nym-crypto",
"nym-http-api-common",
@@ -5793,6 +5807,7 @@ dependencies = [
"nym-mixnode-common",
"nym-node-http-api",
"nym-nonexhaustive-delayqueue",
"nym-pemstore",
"nym-sphinx",
"nym-sphinx-params",
"nym-sphinx-types",
@@ -5800,11 +5815,15 @@ dependencies = [
"nym-topology",
"nym-types",
"nym-validator-client",
"rand",
"serde",
"serde_json",
"sysinfo",
"thiserror",
"time",
"tokio",
"tokio-util",
"tracing",
"toml 0.8.14",
"url",
]
@@ -5869,7 +5888,7 @@ dependencies = [
[[package]]
name = "nym-network-monitor"
version = "1.0.2"
version = "0.1.0"
dependencies = [
"anyhow",
"axum 0.7.7",
@@ -5899,7 +5918,7 @@ dependencies = [
[[package]]
name = "nym-network-requester"
version = "1.1.45"
version = "1.1.43"
dependencies = [
"addr",
"anyhow",
@@ -5950,7 +5969,7 @@ dependencies = [
[[package]]
name = "nym-node"
version = "1.1.11"
version = "1.1.9"
dependencies = [
"anyhow",
"bip39",
@@ -5977,7 +5996,6 @@ dependencies = [
"nym-sphinx-addressing",
"nym-task",
"nym-types",
"nym-validator-client",
"nym-wireguard",
"nym-wireguard-types",
"rand",
@@ -6053,20 +6071,14 @@ dependencies = [
[[package]]
name = "nym-node-status-agent"
version = "1.0.0-rc.1"
version = "0.1.4"
dependencies = [
"anyhow",
"bincode",
"chrono",
"clap 4.5.20",
"nym-bin-common",
"nym-common-models",
"nym-crypto",
"rand",
"reqwest 0.12.4",
"serde",
"serde_json",
"tempfile",
"tokio",
"tokio-util",
"tracing",
@@ -6075,11 +6087,10 @@ dependencies = [
[[package]]
name = "nym-node-status-api"
version = "1.0.0-rc.2"
version = "0.1.5"
dependencies = [
"anyhow",
"axum 0.7.7",
"bincode",
"chrono",
"clap 4.5.20",
"cosmwasm-std",
@@ -6088,7 +6099,6 @@ dependencies = [
"moka",
"nym-bin-common",
"nym-common-models",
"nym-crypto",
"nym-explorer-client",
"nym-network-defaults",
"nym-node-requests",
@@ -6306,7 +6316,7 @@ dependencies = [
[[package]]
name = "nym-socks5-client"
version = "1.1.44"
version = "1.1.42"
dependencies = [
"bs58",
"clap 4.5.20",
@@ -6591,13 +6601,11 @@ dependencies = [
"futures",
"log",
"nym-credentials-interface",
"nym-crypto",
"nym-metrics",
"nym-sphinx",
"nym-task",
"serde",
"serde_json",
"sha2 0.10.8",
"si-scale",
"sysinfo",
"thiserror",
@@ -6633,22 +6641,6 @@ dependencies = [
"wasmtimer",
]
[[package]]
name = "nym-ticketbooks-merkle"
version = "0.1.0"
dependencies = [
"nym-credentials-interface",
"nym-serde-helpers",
"rand",
"rand_chacha",
"rs_merkle",
"schemars",
"serde",
"serde_json",
"sha2 0.10.8",
"time",
]
[[package]]
name = "nym-topology"
version = "0.1.0"
@@ -6768,7 +6760,7 @@ dependencies = [
[[package]]
name = "nym-validator-rewarder"
version = "0.2.0"
version = "0.1.0"
dependencies = [
"anyhow",
"bip39",
@@ -6782,21 +6774,16 @@ dependencies = [
"nym-coconut-dkg-common",
"nym-compact-ecash",
"nym-config",
"nym-contracts-common",
"nym-credentials",
"nym-credentials-interface",
"nym-crypto",
"nym-ecash-time",
"nym-network-defaults",
"nym-serde-helpers",
"nym-task",
"nym-ticketbooks-merkle",
"nym-validator-client",
"nyxd-scraper",
"rand",
"rand_chacha",
"serde",
"serde_json",
"serde_with",
"sha2 0.10.8",
"sqlx",
@@ -6885,6 +6872,7 @@ dependencies = [
"nym-network-defaults",
"nym-task",
"nym-wireguard-types",
"serde",
"thiserror",
"tokio",
"tokio-stream",
@@ -6908,7 +6896,7 @@ dependencies = [
[[package]]
name = "nymvisor"
version = "0.1.9"
version = "0.1.8"
dependencies = [
"anyhow",
"bytes",
@@ -7221,7 +7209,7 @@ dependencies = [
"proc-macro2",
"proc-macro2-diagnostics",
"quote",
"syn 2.0.87",
"syn 2.0.82",
]
[[package]]
@@ -7308,7 +7296,7 @@ dependencies = [
"pest_meta",
"proc-macro2",
"quote",
"syn 2.0.87",
"syn 2.0.82",
]
[[package]]
@@ -7349,7 +7337,7 @@ checksum = "a4502d8515ca9f32f1fb543d987f63d95a14934883db45bdb48060b6b69257f8"
dependencies = [
"proc-macro2",
"quote",
"syn 2.0.87",
"syn 2.0.82",
]
[[package]]
@@ -7564,14 +7552,14 @@ dependencies = [
"proc-macro-error-attr2",
"proc-macro2",
"quote",
"syn 2.0.87",
"syn 2.0.82",
]
[[package]]
name = "proc-macro2"
version = "1.0.89"
version = "1.0.85"
source = "registry+https://github.com/rust-lang/crates.io-index"
checksum = "f139b0662de085916d1fb67d2b4169d1addddda1919e696f3252b740b629986e"
checksum = "22244ce15aa966053a896d1accb3a6e68469b97c7f33f284b99f0d576879fc23"
dependencies = [
"unicode-ident",
]
@@ -7584,7 +7572,7 @@ checksum = "af066a9c399a26e020ada66a034357a868728e72cd426f3adcd35f80d88d88c8"
dependencies = [
"proc-macro2",
"quote",
"syn 2.0.87",
"syn 2.0.82",
"version_check",
"yansi",
]
@@ -7647,7 +7635,7 @@ dependencies = [
"itertools 0.12.1",
"proc-macro2",
"quote",
"syn 2.0.87",
"syn 2.0.82",
]
[[package]]
@@ -7880,19 +7868,19 @@ checksum = "bcc303e793d3734489387d205e9b186fac9c6cfacedd98cbb2e8a5943595f3e6"
dependencies = [
"proc-macro2",
"quote",
"syn 2.0.87",
"syn 2.0.82",
]
[[package]]
name = "regex"
version = "1.11.1"
version = "1.10.6"
source = "registry+https://github.com/rust-lang/crates.io-index"
checksum = "b544ef1b4eac5dc2db33ea63606ae9ffcfac26c1416a2806ae0bf5f56b201191"
checksum = "4219d74c6b67a3654a9fbebc4b419e22126d13d2f3c4a07ee0cb61ff79a79619"
dependencies = [
"aho-corasick",
"memchr",
"regex-automata 0.4.9",
"regex-syntax 0.8.5",
"regex-automata 0.4.7",
"regex-syntax 0.8.4",
]
[[package]]
@@ -7906,13 +7894,13 @@ dependencies = [
[[package]]
name = "regex-automata"
version = "0.4.9"
version = "0.4.7"
source = "registry+https://github.com/rust-lang/crates.io-index"
checksum = "809e8dc61f6de73b46c85f4c96486310fe304c434cfa43669d7b40f711150908"
checksum = "38caf58cc5ef2fed281f89292ef23f6365465ed9a41b7a7754eb4e26496c92df"
dependencies = [
"aho-corasick",
"memchr",
"regex-syntax 0.8.5",
"regex-syntax 0.8.4",
]
[[package]]
@@ -7923,9 +7911,9 @@ checksum = "f162c6dd7b008981e4d40210aca20b4bd0f9b60ca9271061b07f78537722f2e1"
[[package]]
name = "regex-syntax"
version = "0.8.5"
version = "0.8.4"
source = "registry+https://github.com/rust-lang/crates.io-index"
checksum = "2b15c43186be67a4fd63bee50d0303afffcef381492ebe2c5d87f324e1b8815c"
checksum = "7a66a03ae7c801facd77a29370b4faec201768915ac14a721ba36f20bc9c209b"
[[package]]
name = "reqwest"
@@ -8107,7 +8095,7 @@ dependencies = [
"proc-macro2",
"quote",
"rocket_http",
"syn 2.0.87",
"syn 2.0.82",
"unicode-xid",
"version_check",
]
@@ -8184,15 +8172,6 @@ dependencies = [
"syn 1.0.109",
]
[[package]]
name = "rs_merkle"
version = "1.4.2"
source = "registry+https://github.com/rust-lang/crates.io-index"
checksum = "3b241d2e59b74ef9e98d94c78c47623d04c8392abaf82014dfd372a16041128f"
dependencies = [
"sha2 0.10.8",
]
[[package]]
name = "rsa"
version = "0.9.6"
@@ -8233,7 +8212,7 @@ dependencies = [
"proc-macro2",
"quote",
"rust-embed-utils",
"syn 2.0.87",
"syn 2.0.82",
"walkdir",
]
@@ -8289,9 +8268,9 @@ dependencies = [
[[package]]
name = "rustix"
version = "0.38.40"
version = "0.38.34"
source = "registry+https://github.com/rust-lang/crates.io-index"
checksum = "99e4ea3e1cdc4b559b8e5650f9c8e5998e3e5c1343b4eaf034565f32318d63c0"
checksum = "70dc5ec042f7a43c4a73241207cecc9873a06d45debb38b329f8541d85c2730f"
dependencies = [
"bitflags 2.5.0",
"errno",
@@ -8482,7 +8461,7 @@ dependencies = [
"proc-macro2",
"quote",
"serde_derive_internals 0.29.1",
"syn 2.0.87",
"syn 2.0.82",
]
[[package]]
@@ -8514,7 +8493,7 @@ checksum = "1db149f81d46d2deba7cd3c50772474707729550221e69588478ebf9ada425ae"
dependencies = [
"proc-macro2",
"quote",
"syn 2.0.87",
"syn 2.0.82",
]
[[package]]
@@ -8591,9 +8570,9 @@ checksum = "388a1df253eca08550bef6c72392cfe7c30914bf41df5269b68cbd6ff8f570a3"
[[package]]
name = "serde"
version = "1.0.215"
version = "1.0.211"
source = "registry+https://github.com/rust-lang/crates.io-index"
checksum = "6513c1ad0b11a9376da888e3e0baa0077f1aed55c17f50e7b2397136129fb88f"
checksum = "1ac55e59090389fb9f0dd9e0f3c09615afed1d19094284d0b200441f13550793"
dependencies = [
"serde_derive",
]
@@ -8640,13 +8619,13 @@ dependencies = [
[[package]]
name = "serde_derive"
version = "1.0.215"
version = "1.0.211"
source = "registry+https://github.com/rust-lang/crates.io-index"
checksum = "ad1e866f866923f252f05c889987993144fb74e722403468a4ebd70c3cd756c0"
checksum = "54be4f245ce16bc58d57ef2716271d0d4519e0f6defa147f6e081005bcb278ff"
dependencies = [
"proc-macro2",
"quote",
"syn 2.0.87",
"syn 2.0.82",
]
[[package]]
@@ -8657,7 +8636,7 @@ checksum = "e578a843d40b4189a4d66bba51d7684f57da5bd7c304c64e14bd63efbef49509"
dependencies = [
"proc-macro2",
"quote",
"syn 2.0.87",
"syn 2.0.82",
]
[[package]]
@@ -8668,7 +8647,7 @@ checksum = "18d26a20a969b9e3fdf2fc2d9f21eda6c40e2de84c9408bb5d3b05d499aae711"
dependencies = [
"proc-macro2",
"quote",
"syn 2.0.87",
"syn 2.0.82",
]
[[package]]
@@ -8685,12 +8664,13 @@ dependencies = [
[[package]]
name = "serde_json_path"
version = "0.7.1"
version = "0.6.7"
source = "registry+https://github.com/rust-lang/crates.io-index"
checksum = "e176fbf9bd62f75c2d8be33207fa13af2f800a506635e89759e46f934c520f4d"
checksum = "0bc0207b6351893eafa1e39aa9aea452abb6425ca7b02dd64faf29109e7a33ba"
dependencies = [
"inventory",
"nom",
"once_cell",
"regex",
"serde",
"serde_json",
@@ -8701,11 +8681,12 @@ dependencies = [
[[package]]
name = "serde_json_path_core"
version = "0.2.1"
version = "0.1.6"
source = "registry+https://github.com/rust-lang/crates.io-index"
checksum = "ea3bfd54a421bec8328aefede43ac9f18c8c7ded3b2afc8addd44b4813d99fd0"
checksum = "a3d64fe53ce1aaa31bea2b2b46d3b6ab6a37e61854bedcbd9f174e188f3f7d79"
dependencies = [
"inventory",
"once_cell",
"serde",
"serde_json",
"thiserror",
@@ -8713,24 +8694,25 @@ dependencies = [
[[package]]
name = "serde_json_path_macros"
version = "0.1.5"
version = "0.1.4"
source = "registry+https://github.com/rust-lang/crates.io-index"
checksum = "ee05bac728cc5232af5c23896b34fbdd17cf0bb0c113440588aeeb1b57c6ba1f"
checksum = "2a31e8177a443fd3e94917f12946ae7891dfb656e6d4c5e79b8c5d202fbcb723"
dependencies = [
"inventory",
"once_cell",
"serde_json_path_core",
"serde_json_path_macros_internal",
]
[[package]]
name = "serde_json_path_macros_internal"
version = "0.1.2"
version = "0.1.1"
source = "registry+https://github.com/rust-lang/crates.io-index"
checksum = "aafbefbe175fa9bf03ca83ef89beecff7d2a95aaacd5732325b90ac8c3bd7b90"
checksum = "75dde5a1d2ed78dfc411fc45592f72d3694436524d3353683ecb3d22009731dc"
dependencies = [
"proc-macro2",
"quote",
"syn 2.0.87",
"syn 2.0.82",
]
[[package]]
@@ -8751,7 +8733,7 @@ checksum = "6c64451ba24fc7a6a2d60fc75dd9c83c90903b19028d4eff35e88fc1e86564e9"
dependencies = [
"proc-macro2",
"quote",
"syn 2.0.87",
"syn 2.0.82",
]
[[package]]
@@ -8802,7 +8784,7 @@ dependencies = [
"darling 0.20.9",
"proc-macro2",
"quote",
"syn 2.0.87",
"syn 2.0.82",
]
[[package]]
@@ -9401,7 +9383,7 @@ dependencies = [
"proc-macro2",
"quote",
"rustversion",
"syn 2.0.87",
"syn 2.0.82",
]
[[package]]
@@ -9444,9 +9426,9 @@ dependencies = [
[[package]]
name = "syn"
version = "2.0.87"
version = "2.0.82"
source = "registry+https://github.com/rust-lang/crates.io-index"
checksum = "25aa4ce346d03a6dcd68dd8b4010bcb74e54e62c90c573f394c46eae99aba32d"
checksum = "83540f837a8afc019423a8edb95b52a8effe46957ee402287f4292fae35be021"
dependencies = [
"proc-macro2",
"quote",
@@ -9526,13 +9508,12 @@ dependencies = [
[[package]]
name = "tempfile"
version = "3.14.0"
version = "3.10.1"
source = "registry+https://github.com/rust-lang/crates.io-index"
checksum = "28cce251fcbc87fac86a866eeb0d6c2d536fc16d06f184bb61aeae11aa4cee0c"
checksum = "85b77fafb263dd9d05cbeac119526425676db3784113aa9295c88498cbf8bff1"
dependencies = [
"cfg-if",
"fastrand 2.1.1",
"once_cell",
"rustix",
"windows-sys 0.52.0",
]
@@ -9737,22 +9718,22 @@ checksum = "23d434d3f8967a09480fb04132ebe0a3e088c173e6d0ee7897abbdf4eab0f8b9"
[[package]]
name = "thiserror"
version = "1.0.69"
version = "1.0.64"
source = "registry+https://github.com/rust-lang/crates.io-index"
checksum = "b6aaf5339b578ea85b50e080feb250a3e8ae8cfcdff9a461c9ec2904bc923f52"
checksum = "d50af8abc119fb8bb6dbabcfa89656f46f84aa0ac7688088608076ad2b459a84"
dependencies = [
"thiserror-impl",
]
[[package]]
name = "thiserror-impl"
version = "1.0.69"
version = "1.0.64"
source = "registry+https://github.com/rust-lang/crates.io-index"
checksum = "4fee6c4efc90059e10f81e6d42c60a18f76588c3d74cb83a0b242a2b6c7504c1"
checksum = "08904e7672f5eb876eaaf87e0ce17857500934f4981c4a0ab2b4aa98baac7fc3"
dependencies = [
"proc-macro2",
"quote",
"syn 2.0.87",
"syn 2.0.82",
]
[[package]]
@@ -9883,7 +9864,7 @@ checksum = "693d596312e88961bc67d7f1f97af8a70227d9f90c31bba5806eec004978d752"
dependencies = [
"proc-macro2",
"quote",
"syn 2.0.87",
"syn 2.0.82",
]
[[package]]
@@ -10162,7 +10143,7 @@ checksum = "34704c8d6ebcbc939824180af020566b01a7c01f80641264eba0999f6c2b6be7"
dependencies = [
"proc-macro2",
"quote",
"syn 2.0.87",
"syn 2.0.82",
]
[[package]]
@@ -10326,7 +10307,7 @@ checksum = "0ea0b99e8ec44abd6f94a18f28f7934437809dd062820797c52401298116f70e"
dependencies = [
"proc-macro2",
"quote",
"syn 2.0.87",
"syn 2.0.82",
"termcolor",
]
@@ -10353,7 +10334,7 @@ dependencies = [
"proc-macro2",
"quote",
"serde_derive_internals 0.28.0",
"syn 2.0.87",
"syn 2.0.82",
]
[[package]]
@@ -10556,7 +10537,7 @@ source = "registry+https://github.com/rust-lang/crates.io-index"
checksum = "55137c122f712d9330fd985d66fa61bdc381752e89c35708c13ce63049a3002c"
dependencies = [
"quote",
"syn 2.0.87",
"syn 2.0.82",
]
[[package]]
@@ -10588,7 +10569,7 @@ dependencies = [
"proc-macro2",
"quote",
"serde",
"syn 2.0.87",
"syn 2.0.82",
"toml 0.5.11",
"uniffi_build",
"uniffi_meta",
@@ -10720,7 +10701,7 @@ dependencies = [
"proc-macro2",
"quote",
"regex",
"syn 2.0.87",
"syn 2.0.82",
"uuid",
]
@@ -10759,7 +10740,7 @@ checksum = "17e82ab96c5a55263b5bed151b8426410d93aa909a453acdbd4b6792b5af7d64"
dependencies = [
"proc-macro2",
"quote",
"syn 2.0.87",
"syn 2.0.82",
]
[[package]]
@@ -10770,7 +10751,7 @@ checksum = "86b8338dc3c9526011ffaa2aa6bd60ddfda9d49d2123108690755c6e34844212"
dependencies = [
"proc-macro2",
"quote",
"syn 2.0.87",
"syn 2.0.82",
"utoipauto-core",
]
@@ -10877,7 +10858,7 @@ dependencies = [
"once_cell",
"proc-macro2",
"quote",
"syn 2.0.87",
"syn 2.0.82",
"wasm-bindgen-shared",
]
@@ -10911,7 +10892,7 @@ checksum = "26c6ab57572f7a24a4985830b120de1594465e5d500f24afe89e16b4e833ef68"
dependencies = [
"proc-macro2",
"quote",
"syn 2.0.87",
"syn 2.0.82",
"wasm-bindgen-backend",
"wasm-bindgen-shared",
]
@@ -10945,7 +10926,7 @@ checksum = "4b8220be1fa9e4c889b30fd207d4906657e7e90b12e0e6b0c8b8d8709f5de021"
dependencies = [
"proc-macro2",
"quote",
"syn 2.0.87",
"syn 2.0.82",
]
[[package]]
@@ -10963,7 +10944,6 @@ dependencies = [
"nym-gateway-client",
"nym-sphinx",
"nym-sphinx-acknowledgements",
"nym-statistics-common",
"nym-task",
"nym-topology",
"nym-validator-client",
@@ -11473,7 +11453,7 @@ checksum = "15e934569e47891f7d9411f1a451d947a60e000ab3bd24fbb970f000387d1b3b"
dependencies = [
"proc-macro2",
"quote",
"syn 2.0.87",
"syn 2.0.82",
]
[[package]]
@@ -11493,7 +11473,7 @@ checksum = "ce36e65b0d2999d2aafac989fb249189a141aee1f53c612c1f37d72631959f69"
dependencies = [
"proc-macro2",
"quote",
"syn 2.0.87",
"syn 2.0.82",
]
[[package]]
+2 -4
View File
@@ -90,7 +90,6 @@ members = [
"common/statistics",
"common/store-cipher",
"common/task",
"common/ticketbooks-merkle",
"common/topology",
"common/tun",
"common/types",
@@ -278,7 +277,6 @@ ledger-transport = "0.10.0"
ledger-transport-hid = "0.10.0"
log = "0.4"
maxminddb = "0.23.0"
rs_merkle = "1.4.2"
mime = "0.3.17"
moka = { version = "0.12", features = ["future"] }
nix = "0.27.1"
@@ -314,7 +312,7 @@ serde = "1.0.211"
serde_bytes = "0.11.15"
serde_derive = "1.0"
serde_json = "1.0.132"
serde_json_path = "0.7.1"
serde_json_path = "0.6.7"
serde_repr = "0.1"
serde_with = "3.9.0"
serde_yaml = "0.9.25"
@@ -329,7 +327,7 @@ syn = "1"
sysinfo = "0.30.13"
tap = "1.0.1"
tar = "0.4.42"
tempfile = "3.14"
tempfile = "3.5.0"
thiserror = "1.0.64"
time = "0.3.30"
tokio = "1.39"
+1 -1
View File
@@ -1,6 +1,6 @@
[package]
name = "nym-client"
version = "1.1.44"
version = "1.1.42"
authors = ["Dave Hrycyszyn <futurechimp@users.noreply.github.com>", "Jędrzej Stuczyński <andrew@nymtech.net>"]
description = "Implementation of the Nym Client"
edition = "2021"
+1 -1
View File
@@ -1,6 +1,6 @@
[package]
name = "nym-socks5-client"
version = "1.1.44"
version = "1.1.42"
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"
edition = "2021"
@@ -22,7 +22,4 @@ pub enum Error {
#[error("conversion: {0}")]
Conversion(String),
#[error("failed to serialize response packet: {source}")]
FailedToSerializeResponsePacket { source: Box<bincode::ErrorKind> },
}
-1
View File
@@ -1,7 +1,6 @@
// Copyright 2024 - Nym Technologies SA <contact@nymtech.net>
// SPDX-License-Identifier: Apache-2.0
pub mod traits;
pub mod v1;
pub mod v2;
pub mod v3;
-343
View File
@@ -1,343 +0,0 @@
// Copyright 2024 - Nym Technologies SA <contact@nymtech.net>
// SPDX-License-Identifier: Apache-2.0
use nym_credentials_interface::CredentialSpendingData;
use nym_crypto::asymmetric::x25519::PrivateKey;
use nym_service_provider_requests_common::{Protocol, ServiceProviderType};
use nym_sphinx::addressing::clients::Recipient;
use nym_wireguard_types::PeerPublicKey;
use crate::{
v1, v2, v3,
v4::{self, registration::IpPair},
Error,
};
#[derive(Copy, Clone, Debug)]
pub enum AuthenticatorVersion {
V1,
V2,
V3,
V4,
UNKNOWN,
}
impl From<Protocol> for AuthenticatorVersion {
fn from(value: Protocol) -> Self {
if value.service_provider_type != ServiceProviderType::Authenticator {
AuthenticatorVersion::UNKNOWN
} else if value.version == v1::VERSION {
AuthenticatorVersion::V1
} else if value.version == v2::VERSION {
AuthenticatorVersion::V2
} else if value.version == v3::VERSION {
AuthenticatorVersion::V3
} else if value.version == v4::VERSION {
AuthenticatorVersion::V4
} else {
AuthenticatorVersion::UNKNOWN
}
}
}
pub trait InitMessage {
fn pub_key(&self) -> PeerPublicKey;
}
impl InitMessage for v1::registration::InitMessage {
fn pub_key(&self) -> PeerPublicKey {
self.pub_key
}
}
impl InitMessage for v2::registration::InitMessage {
fn pub_key(&self) -> PeerPublicKey {
self.pub_key
}
}
impl InitMessage for v3::registration::InitMessage {
fn pub_key(&self) -> PeerPublicKey {
self.pub_key
}
}
impl InitMessage for v4::registration::InitMessage {
fn pub_key(&self) -> PeerPublicKey {
self.pub_key
}
}
pub trait FinalMessage {
fn pub_key(&self) -> PeerPublicKey;
fn verify(&self, private_key: &PrivateKey, nonce: u64) -> Result<(), Error>;
fn private_ips(&self) -> IpPair;
fn credential(&self) -> Option<CredentialSpendingData>;
}
impl FinalMessage for v1::GatewayClient {
fn pub_key(&self) -> PeerPublicKey {
self.pub_key
}
fn verify(&self, private_key: &PrivateKey, nonce: u64) -> Result<(), Error> {
self.verify(private_key, nonce)
}
fn private_ips(&self) -> IpPair {
self.private_ip.into()
}
fn credential(&self) -> Option<CredentialSpendingData> {
None
}
}
impl FinalMessage for v2::registration::FinalMessage {
fn pub_key(&self) -> PeerPublicKey {
self.gateway_client.pub_key
}
fn verify(&self, private_key: &PrivateKey, nonce: u64) -> Result<(), Error> {
self.gateway_client.verify(private_key, nonce)
}
fn private_ips(&self) -> IpPair {
self.gateway_client.private_ip.into()
}
fn credential(&self) -> Option<CredentialSpendingData> {
self.credential.clone()
}
}
impl FinalMessage for v3::registration::FinalMessage {
fn pub_key(&self) -> PeerPublicKey {
self.gateway_client.pub_key
}
fn verify(&self, private_key: &PrivateKey, nonce: u64) -> Result<(), Error> {
self.gateway_client.verify(private_key, nonce)
}
fn private_ips(&self) -> IpPair {
self.gateway_client.private_ip.into()
}
fn credential(&self) -> Option<CredentialSpendingData> {
self.credential.clone()
}
}
impl FinalMessage for v4::registration::FinalMessage {
fn pub_key(&self) -> PeerPublicKey {
self.gateway_client.pub_key
}
fn verify(&self, private_key: &PrivateKey, nonce: u64) -> Result<(), Error> {
self.gateway_client.verify(private_key, nonce)
}
fn private_ips(&self) -> IpPair {
self.gateway_client.private_ips
}
fn credential(&self) -> Option<CredentialSpendingData> {
self.credential.clone()
}
}
pub trait QueryBandwidthMessage {
fn pub_key(&self) -> PeerPublicKey;
}
impl QueryBandwidthMessage for PeerPublicKey {
fn pub_key(&self) -> PeerPublicKey {
*self
}
}
pub trait TopUpMessage {
fn pub_key(&self) -> PeerPublicKey;
fn credential(&self) -> CredentialSpendingData;
}
impl TopUpMessage for v3::topup::TopUpMessage {
fn pub_key(&self) -> PeerPublicKey {
self.pub_key
}
fn credential(&self) -> CredentialSpendingData {
self.credential.clone()
}
}
impl TopUpMessage for v4::topup::TopUpMessage {
fn pub_key(&self) -> PeerPublicKey {
self.pub_key
}
fn credential(&self) -> CredentialSpendingData {
self.credential.clone()
}
}
pub enum AuthenticatorRequest {
Initial {
msg: Box<dyn InitMessage + Send + Sync + 'static>,
protocol: Protocol,
reply_to: Recipient,
request_id: u64,
},
Final {
msg: Box<dyn FinalMessage + Send + Sync + 'static>,
protocol: Protocol,
reply_to: Recipient,
request_id: u64,
},
QueryBandwidth {
msg: Box<dyn QueryBandwidthMessage + Send + Sync + 'static>,
protocol: Protocol,
reply_to: Recipient,
request_id: u64,
},
TopUpBandwidth {
msg: Box<dyn TopUpMessage + Send + Sync + 'static>,
protocol: Protocol,
reply_to: Recipient,
request_id: u64,
},
}
impl From<v1::request::AuthenticatorRequest> for AuthenticatorRequest {
fn from(value: v1::request::AuthenticatorRequest) -> Self {
match value.data {
v1::request::AuthenticatorRequestData::Initial(init_message) => Self::Initial {
msg: Box::new(init_message),
protocol: Protocol {
version: value.version,
service_provider_type: ServiceProviderType::Authenticator,
},
reply_to: value.reply_to,
request_id: value.request_id,
},
v1::request::AuthenticatorRequestData::Final(gateway_client) => Self::Final {
msg: Box::new(gateway_client),
protocol: Protocol {
version: value.version,
service_provider_type: ServiceProviderType::Authenticator,
},
reply_to: value.reply_to,
request_id: value.request_id,
},
v1::request::AuthenticatorRequestData::QueryBandwidth(peer_public_key) => {
Self::QueryBandwidth {
msg: Box::new(peer_public_key),
protocol: Protocol {
version: value.version,
service_provider_type: ServiceProviderType::Authenticator,
},
reply_to: value.reply_to,
request_id: value.request_id,
}
}
}
}
}
impl From<v2::request::AuthenticatorRequest> for AuthenticatorRequest {
fn from(value: v2::request::AuthenticatorRequest) -> Self {
match value.data {
v2::request::AuthenticatorRequestData::Initial(init_message) => Self::Initial {
msg: Box::new(init_message),
protocol: value.protocol,
reply_to: value.reply_to,
request_id: value.request_id,
},
v2::request::AuthenticatorRequestData::Final(final_message) => Self::Final {
msg: final_message,
protocol: value.protocol,
reply_to: value.reply_to,
request_id: value.request_id,
},
v2::request::AuthenticatorRequestData::QueryBandwidth(peer_public_key) => {
Self::QueryBandwidth {
msg: Box::new(peer_public_key),
protocol: value.protocol,
reply_to: value.reply_to,
request_id: value.request_id,
}
}
}
}
}
impl From<v3::request::AuthenticatorRequest> for AuthenticatorRequest {
fn from(value: v3::request::AuthenticatorRequest) -> Self {
match value.data {
v3::request::AuthenticatorRequestData::Initial(init_message) => Self::Initial {
msg: Box::new(init_message),
protocol: value.protocol,
reply_to: value.reply_to,
request_id: value.request_id,
},
v3::request::AuthenticatorRequestData::Final(final_message) => Self::Final {
msg: final_message,
protocol: value.protocol,
reply_to: value.reply_to,
request_id: value.request_id,
},
v3::request::AuthenticatorRequestData::QueryBandwidth(peer_public_key) => {
Self::QueryBandwidth {
msg: Box::new(peer_public_key),
protocol: value.protocol,
reply_to: value.reply_to,
request_id: value.request_id,
}
}
v3::request::AuthenticatorRequestData::TopUpBandwidth(top_up_message) => {
Self::TopUpBandwidth {
msg: top_up_message,
protocol: value.protocol,
reply_to: value.reply_to,
request_id: value.request_id,
}
}
}
}
}
impl From<v4::request::AuthenticatorRequest> for AuthenticatorRequest {
fn from(value: v4::request::AuthenticatorRequest) -> Self {
match value.data {
v4::request::AuthenticatorRequestData::Initial(init_message) => Self::Initial {
msg: Box::new(init_message),
protocol: value.protocol,
reply_to: value.reply_to,
request_id: value.request_id,
},
v4::request::AuthenticatorRequestData::Final(final_message) => Self::Final {
msg: final_message,
protocol: value.protocol,
reply_to: value.reply_to,
request_id: value.request_id,
},
v4::request::AuthenticatorRequestData::QueryBandwidth(peer_public_key) => {
Self::QueryBandwidth {
msg: Box::new(peer_public_key),
protocol: value.protocol,
reply_to: value.reply_to,
request_id: value.request_id,
}
}
v4::request::AuthenticatorRequestData::TopUpBandwidth(top_up_message) => {
Self::TopUpBandwidth {
msg: top_up_message,
protocol: value.protocol,
reply_to: value.reply_to,
request_id: value.request_id,
}
}
}
}
}
@@ -98,16 +98,6 @@ impl TryFrom<v3::response::AuthenticatorResponse> for v2::response::Authenticato
}
}
impl From<v2::response::AuthenticatorResponse> for v3::response::AuthenticatorResponse {
fn from(value: v2::response::AuthenticatorResponse) -> Self {
Self {
protocol: value.protocol,
data: value.data.into(),
reply_to: value.reply_to,
}
}
}
impl TryFrom<v3::response::AuthenticatorResponseData> for v2::response::AuthenticatorResponseData {
type Error = crate::Error;
@@ -139,22 +129,6 @@ impl TryFrom<v3::response::AuthenticatorResponseData> for v2::response::Authenti
}
}
impl From<v2::response::AuthenticatorResponseData> for v3::response::AuthenticatorResponseData {
fn from(value: v2::response::AuthenticatorResponseData) -> Self {
match value {
v2::response::AuthenticatorResponseData::PendingRegistration(
pending_registration_response,
) => Self::PendingRegistration(pending_registration_response.into()),
v2::response::AuthenticatorResponseData::Registered(registered_response) => {
Self::Registered(registered_response.into())
}
v2::response::AuthenticatorResponseData::RemainingBandwidth(
remaining_bandwidth_response,
) => Self::RemainingBandwidth(remaining_bandwidth_response.into()),
}
}
}
impl From<v3::response::PendingRegistrationResponse> for v2::response::PendingRegistrationResponse {
fn from(value: v3::response::PendingRegistrationResponse) -> Self {
Self {
@@ -165,16 +139,6 @@ impl From<v3::response::PendingRegistrationResponse> for v2::response::PendingRe
}
}
impl From<v2::response::PendingRegistrationResponse> for v3::response::PendingRegistrationResponse {
fn from(value: v2::response::PendingRegistrationResponse) -> Self {
Self {
request_id: value.request_id,
reply_to: value.reply_to,
reply: value.reply.into(),
}
}
}
impl From<v3::response::RegisteredResponse> for v2::response::RegisteredResponse {
fn from(value: v3::response::RegisteredResponse) -> Self {
Self {
@@ -185,16 +149,6 @@ impl From<v3::response::RegisteredResponse> for v2::response::RegisteredResponse
}
}
impl From<v2::response::RegisteredResponse> for v3::response::RegisteredResponse {
fn from(value: v2::response::RegisteredResponse) -> Self {
Self {
request_id: value.request_id,
reply_to: value.reply_to,
reply: value.reply.into(),
}
}
}
impl From<v3::response::RemainingBandwidthResponse> for v2::response::RemainingBandwidthResponse {
fn from(value: v3::response::RemainingBandwidthResponse) -> Self {
Self {
@@ -205,16 +159,6 @@ impl From<v3::response::RemainingBandwidthResponse> for v2::response::RemainingB
}
}
impl From<v2::response::RemainingBandwidthResponse> for v3::response::RemainingBandwidthResponse {
fn from(value: v2::response::RemainingBandwidthResponse) -> Self {
Self {
request_id: value.request_id,
reply_to: value.reply_to,
reply: value.reply.map(Into::into),
}
}
}
impl From<v3::registration::RegistrationData> for v2::registration::RegistrationData {
fn from(value: v3::registration::RegistrationData) -> Self {
Self {
@@ -225,16 +169,6 @@ impl From<v3::registration::RegistrationData> for v2::registration::Registration
}
}
impl From<v2::registration::RegistrationData> for v3::registration::RegistrationData {
fn from(value: v2::registration::RegistrationData) -> Self {
Self {
nonce: value.nonce,
gateway_data: value.gateway_data.into(),
wg_port: value.wg_port,
}
}
}
impl From<v3::registration::RegistredData> for v2::registration::RegistredData {
fn from(value: v3::registration::RegistredData) -> Self {
Self {
@@ -245,16 +179,6 @@ impl From<v3::registration::RegistredData> for v2::registration::RegistredData {
}
}
impl From<v2::registration::RegistredData> for v3::registration::RegistredData {
fn from(value: v2::registration::RegistredData) -> Self {
Self {
pub_key: value.pub_key,
private_ip: value.private_ip,
wg_port: value.wg_port,
}
}
}
impl From<v3::registration::RemainingBandwidthData> for v2::registration::RemainingBandwidthData {
fn from(value: v3::registration::RemainingBandwidthData) -> Self {
Self {
@@ -262,11 +186,3 @@ impl From<v3::registration::RemainingBandwidthData> for v2::registration::Remain
}
}
}
impl From<v2::registration::RemainingBandwidthData> for v3::registration::RemainingBandwidthData {
fn from(value: v2::registration::RemainingBandwidthData) -> Self {
Self {
available_bandwidth: value.available_bandwidth,
}
}
}
@@ -27,7 +27,7 @@ pub type HmacSha256 = Hmac<Sha256>;
pub type Nonce = u64;
pub type Taken = Option<SystemTime>;
pub const BANDWIDTH_CAP_PER_DAY: u64 = 250 * 1024 * 1024 * 1024; // 250 GB
pub const BANDWIDTH_CAP_PER_DAY: u64 = 1024 * 1024 * 1024; // 1 GB
#[derive(Serialize, Deserialize, Debug, Clone)]
pub struct InitMessage {
@@ -3,7 +3,7 @@
use nym_service_provider_requests_common::{Protocol, ServiceProviderType};
use crate::{v2, v3, v4};
use crate::{v3, v4};
impl From<v3::request::AuthenticatorRequest> for v4::request::AuthenticatorRequest {
fn from(authenticator_request: v3::request::AuthenticatorRequest) -> Self {
@@ -64,16 +64,6 @@ impl From<Box<v3::topup::TopUpMessage>> for Box<v4::topup::TopUpMessage> {
}
}
impl From<v2::registration::GatewayClient> for v4::registration::GatewayClient {
fn from(gw_client: v2::registration::GatewayClient) -> Self {
Self {
pub_key: gw_client.pub_key,
private_ips: gw_client.private_ip.into(),
mac: gw_client.mac.into(),
}
}
}
impl From<v3::registration::GatewayClient> for v4::registration::GatewayClient {
fn from(gw_client: v3::registration::GatewayClient) -> Self {
Self {
@@ -94,22 +84,6 @@ impl From<v4::registration::GatewayClient> for v3::registration::GatewayClient {
}
}
impl From<v4::registration::GatewayClient> for v2::registration::GatewayClient {
fn from(gw_client: v4::registration::GatewayClient) -> Self {
Self {
pub_key: gw_client.pub_key,
private_ip: gw_client.private_ips.ipv4.into(),
mac: gw_client.mac.into(),
}
}
}
impl From<v2::registration::ClientMac> for v4::registration::ClientMac {
fn from(mac: v2::registration::ClientMac) -> Self {
Self::new(mac.to_vec())
}
}
impl From<v3::registration::ClientMac> for v4::registration::ClientMac {
fn from(mac: v3::registration::ClientMac) -> Self {
Self::new(mac.to_vec())
@@ -122,12 +96,6 @@ impl From<v4::registration::ClientMac> for v3::registration::ClientMac {
}
}
impl From<v4::registration::ClientMac> for v2::registration::ClientMac {
fn from(mac: v4::registration::ClientMac) -> Self {
Self::new(mac.to_vec())
}
}
impl TryFrom<v4::response::AuthenticatorResponse> for v3::response::AuthenticatorResponse {
type Error = crate::Error;
@@ -42,12 +42,6 @@ impl IpPair {
}
}
impl From<(Ipv4Addr, Ipv6Addr)> for IpPair {
fn from((ipv4, ipv6): (Ipv4Addr, Ipv6Addr)) -> Self {
IpPair { ipv4, ipv6 }
}
}
impl fmt::Display for IpPair {
fn fmt(&self, f: &mut fmt::Formatter<'_>) -> fmt::Result {
write!(f, "({}, {})", self.ipv4, self.ipv6)
-1
View File
@@ -47,7 +47,6 @@ pub fn setup_logging() {
#[cfg(feature = "basic_tracing")]
pub fn setup_tracing_logger() {
let log_builder = tracing_subscriber::fmt()
.with_writer(std::io::stderr)
// Use a more compact, abbreviated log format
.compact()
// Display source code file paths
@@ -9,6 +9,7 @@ license.workspace = true
[dependencies]
humantime-serde = { workspace = true }
serde = { workspace = true, features = ["derive"] }
serde_with = { workspace = true, features = ["macros"] }
thiserror.workspace = true
url = { workspace = true, features = ["serde"] }
+4 -15
View File
@@ -2,10 +2,10 @@
// SPDX-License-Identifier: Apache-2.0
use nym_config::defaults::NymNetworkDetails;
use nym_config::serde_helpers::{de_maybe_stringified, ser_maybe_stringified};
use nym_sphinx_addressing::Recipient;
use nym_sphinx_params::{PacketSize, PacketType};
use serde::{Deserialize, Serialize};
use serde_with::{serde_as, DisplayFromStr};
use std::time::Duration;
use url::Url;
@@ -393,20 +393,13 @@ pub struct Traffic {
/// poisson distribution.
pub disable_main_poisson_packet_distribution: bool,
/// Specify whether route selection should be determined by the packet header.
pub deterministic_route_selection: bool,
/// Specify how many times particular packet can be retransmitted
/// None - no limit
pub maximum_number_of_retransmissions: Option<u32>,
/// Specifies the packet size used for sent messages.
/// Do not override it unless you understand the consequences of that change.
pub primary_packet_size: PacketSize,
/// Specifies the optional auxiliary packet size for optimizing message streams.
/// Note that its use decreases overall anonymity.
/// Do not set it unless you understand the consequences of that change.
/// Do not set it it unless you understand the consequences of that change.
pub secondary_packet_size: Option<PacketSize>,
pub packet_type: PacketType,
@@ -431,8 +424,6 @@ impl Default for Traffic {
average_packet_delay: DEFAULT_AVERAGE_PACKET_DELAY,
message_sending_average_delay: DEFAULT_MESSAGE_STREAM_AVERAGE_DELAY,
disable_main_poisson_packet_distribution: false,
deterministic_route_selection: false,
maximum_number_of_retransmissions: None,
primary_packet_size: PacketSize::RegularPacket,
secondary_packet_size: None,
packet_type: PacketType::Mix,
@@ -652,6 +643,7 @@ impl Default for ReplySurbs {
}
}
#[serde_as]
#[derive(Debug, Clone, Copy, Deserialize, PartialEq, Serialize)]
#[serde(default, deny_unknown_fields)]
pub struct StatsReporting {
@@ -659,10 +651,7 @@ pub struct StatsReporting {
pub enabled: bool,
/// Address of the stats collector. If this is none, no reporting will happen, regardless of `enabled`
#[serde(
serialize_with = "ser_maybe_stringified",
deserialize_with = "de_maybe_stringified"
)]
#[serde_as(as = "Option<DisplayFromStr>")]
pub provider_address: Option<Recipient>,
/// With what frequence will statistics be sent
@@ -111,7 +111,6 @@ impl From<ConfigV5> for Config {
primary_packet_size: value.debug.traffic.primary_packet_size,
secondary_packet_size: value.debug.traffic.secondary_packet_size,
packet_type: value.debug.traffic.packet_type,
..Default::default()
},
cover_traffic: CoverTraffic {
loop_cover_traffic_average_delay: value
@@ -49,13 +49,13 @@ use nym_sphinx::addressing::nodes::NodeIdentity;
use nym_sphinx::params::PacketType;
use nym_sphinx::receiver::{ReconstructedMessage, SphinxMessageReceiver};
use nym_statistics_common::clients::ClientStatsSender;
use nym_statistics_common::generate_client_stats_id;
use nym_task::connections::{ConnectionCommandReceiver, ConnectionCommandSender, LaneQueueLengths};
use nym_task::{TaskClient, TaskHandle};
use nym_topology::provider_trait::TopologyProvider;
use nym_topology::HardcodedTopologyProvider;
use nym_validator_client::{nyxd::contract_traits::DkgQueryClient, UserAgent};
use rand::rngs::OsRng;
use sha2::Digest;
use std::fmt::Debug;
use std::os::raw::c_int as RawFd;
use std::path::Path;
@@ -358,7 +358,6 @@ where
bandwidth_controller: Option<BandwidthController<C, S::CredentialStore>>,
details_store: &S::GatewaysDetailsStore,
packet_router: PacketRouter,
stats_reporter: ClientStatsSender,
shutdown: TaskClient,
) -> Result<GatewayClient<C, S::CredentialStore>, ClientCoreError>
where
@@ -374,12 +373,7 @@ where
let mut gateway_client =
if let Some(existing_client) = initialisation_result.authenticated_ephemeral_client {
existing_client.upgrade(
packet_router,
bandwidth_controller,
stats_reporter,
shutdown,
)
existing_client.upgrade(packet_router, bandwidth_controller, shutdown)
} else {
let cfg = GatewayConfig::new(
details.gateway_id,
@@ -400,7 +394,6 @@ where
Some(details.shared_key),
packet_router,
bandwidth_controller,
stats_reporter,
shutdown,
)
};
@@ -453,7 +446,6 @@ where
Ok(gateway_client)
}
#[allow(clippy::too_many_arguments)]
async fn setup_gateway_transceiver(
custom_gateway_transceiver: Option<Box<dyn GatewayTransceiver + Send>>,
config: &Config,
@@ -461,7 +453,6 @@ where
bandwidth_controller: Option<BandwidthController<C, S::CredentialStore>>,
details_store: &S::GatewaysDetailsStore,
packet_router: PacketRouter,
stats_reporter: ClientStatsSender,
mut shutdown: TaskClient,
) -> Result<Box<dyn GatewayTransceiver + Send>, ClientCoreError>
where
@@ -492,7 +483,6 @@ where
bandwidth_controller,
details_store,
packet_router,
stats_reporter,
shutdown,
)
.await?;
@@ -744,10 +734,15 @@ where
self.user_agent.clone(),
);
//make sure we don't accidentally get the same id as gateways are reporting
let client_stats_id = format!(
"stats_id_{:x}",
sha2::Sha256::digest(self_address.identity().to_bytes())
);
let stats_reporter = Self::start_statistics_control(
self.config,
self.user_agent.clone(),
generate_client_stats_id(*self_address.identity()),
client_stats_id,
input_sender.clone(),
shutdown.fork("statistics_control"),
);
@@ -776,7 +771,6 @@ where
bandwidth_controller,
&details_store,
gateway_packet_router,
stats_reporter.clone(),
shutdown.fork("gateway_transceiver"),
)
.await?;
@@ -30,8 +30,7 @@ pub(crate) enum Action {
InsertPending(Vec<PendingAcknowledgement>),
/// Removes given `PendingAcknowledgement` from the 'shared' state. Also cancels the retransmission timer.
/// Initiated by `AcknowledgementListener` upon receiving the acknowledgement. Also by `RetransmissionRequestListener`
/// upon deciding to abandon the data.
/// Initiated by `AcknowledgementListener`
RemovePending(FragmentIdentifier),
/// Starts the retransmission timer on given `PendingAcknowledgement` with the `Duration` based on
@@ -42,7 +41,7 @@ pub(crate) enum Action {
/// Updates the expected delay of given `PendingAcknowledgement` with the new provided `SphinxDelay`.
/// Initiated by `RetransmissionRequestListener`
UpdatePendingAck(FragmentIdentifier, SphinxDelay),
UpdateDelay(FragmentIdentifier, SphinxDelay),
}
impl Action {
@@ -58,8 +57,8 @@ impl Action {
Action::StartTimer(frag_id)
}
pub(crate) fn new_update_pending_ack(frag_id: FragmentIdentifier, delay: SphinxDelay) -> Self {
Action::UpdatePendingAck(frag_id, delay)
pub(crate) fn new_update_delay(frag_id: FragmentIdentifier, delay: SphinxDelay) -> Self {
Action::UpdateDelay(frag_id, delay)
}
}
@@ -136,7 +135,7 @@ impl ActionController {
}
fn handle_start_timer(&mut self, frag_id: FragmentIdentifier) {
trace!("{frag_id} is starting its timer");
trace!("{} is starting its timer", frag_id);
if let Some((pending_ack_data, queue_key)) = self.pending_acks_data.get_mut(&frag_id) {
// the fact that this branch is now POSSIBLE is a sign of a need to refactor this whole
@@ -194,7 +193,7 @@ impl ActionController {
// initiated basically as a first step of retransmission. At first data has its delay updated
// (as new sphinx packet was created with new expected delivery time)
fn handle_update_pending_ack(&mut self, frag_id: FragmentIdentifier, delay: SphinxDelay) {
fn handle_update_delay(&mut self, frag_id: FragmentIdentifier, delay: SphinxDelay) {
trace!("{} is updating its delay", frag_id);
// TODO: is it possible to solve this without either locking or temporarily removing the value?
if let Some((pending_ack_data, queue_key)) = self.pending_acks_data.remove(&frag_id) {
@@ -203,7 +202,7 @@ impl ActionController {
// reference to this Arc. HOWEVER, before the Action was pushed onto the queue, the reference
// was dropped hence this unwrap is safe.
let mut inner_data = Arc::try_unwrap(pending_ack_data).unwrap();
inner_data.update_retransmitted(delay);
inner_data.update_delay(delay);
self.pending_acks_data
.insert(frag_id, (Arc::new(inner_data), queue_key));
@@ -226,7 +225,7 @@ impl ActionController {
// about it. Perhaps just reschedule it at later point?
let frag_id = expired_ack.into_inner();
trace!("{frag_id} has expired");
trace!("{} has expired", frag_id);
if let Some((pending_ack_data, queue_key)) = self.pending_acks_data.get_mut(&frag_id) {
if queue_key.is_none() {
@@ -259,9 +258,7 @@ impl ActionController {
Action::InsertPending(pending_acks) => self.handle_insert(pending_acks),
Action::RemovePending(frag_id) => self.handle_remove(frag_id),
Action::StartTimer(frag_id) => self.handle_start_timer(frag_id),
Action::UpdatePendingAck(frag_id, delay) => {
self.handle_update_pending_ack(frag_id, delay)
}
Action::UpdateDelay(frag_id, delay) => self.handle_update_delay(frag_id, delay),
}
}
@@ -71,7 +71,6 @@ pub(crate) struct PendingAcknowledgement {
delay: SphinxDelay,
destination: PacketDestination,
mix_hops: Option<u8>,
retransmissions: u32,
}
impl PendingAcknowledgement {
@@ -87,7 +86,6 @@ impl PendingAcknowledgement {
delay,
destination: PacketDestination::KnownRecipient(recipient.into()),
mix_hops,
retransmissions: 0,
}
}
@@ -107,7 +105,6 @@ impl PendingAcknowledgement {
// Messages sent using SURBs are using the number of mix hops set by the recipient when
// they provided the SURBs, so it doesn't make sense to include it here.
mix_hops: None,
retransmissions: 0,
}
}
@@ -119,9 +116,8 @@ impl PendingAcknowledgement {
self.message_chunk.clone()
}
fn update_retransmitted(&mut self, new_delay: SphinxDelay) {
fn update_delay(&mut self, new_delay: SphinxDelay) {
self.delay = new_delay;
self.retransmissions += 1;
}
}
@@ -167,9 +163,6 @@ impl AcknowledgementControllerConnectors {
/// Configurable parameters of the `AcknowledgementController`
pub(super) struct Config {
/// Specify how many times particular packet can be retransmitted
maximum_retransmissions: Option<u32>,
/// Given ack timeout in the form a * BASE_DELAY + b, it specifies the additive part `b`
ack_wait_addition: Duration,
@@ -181,13 +174,8 @@ pub(super) struct Config {
}
impl Config {
pub(super) fn new(
maximum_retransmissions: Option<u32>,
ack_wait_addition: Duration,
ack_wait_multiplier: f64,
) -> Self {
pub(super) fn new(ack_wait_addition: Duration, ack_wait_multiplier: f64) -> Self {
Config {
maximum_retransmissions,
ack_wait_addition,
ack_wait_multiplier,
packet_size: Default::default(),
@@ -250,7 +238,6 @@ where
// will listen for any ack timeouts and trigger retransmission
let retransmission_request_listener = RetransmissionRequestListener::new(
config.maximum_retransmissions,
connectors.ack_action_sender.clone(),
message_handler,
retransmission_rx,
@@ -20,7 +20,6 @@ use std::sync::{Arc, Weak};
// responsible for packet retransmission upon fired timer
pub(super) struct RetransmissionRequestListener<R> {
maximum_retransmissions: Option<u32>,
action_sender: AckActionSender,
message_handler: MessageHandler<R>,
request_receiver: RetransmissionRequestReceiver,
@@ -32,14 +31,12 @@ where
R: CryptoRng + Rng,
{
pub(super) fn new(
maximum_retransmissions: Option<u32>,
action_sender: AckActionSender,
message_handler: MessageHandler<R>,
request_receiver: RetransmissionRequestReceiver,
reply_controller_sender: ReplyControllerSender,
) -> Self {
RetransmissionRequestListener {
maximum_retransmissions,
action_sender,
message_handler,
request_receiver,
@@ -80,18 +77,6 @@ where
}
};
let frag_id = timed_out_ack.message_chunk.fragment_identifier();
if let Some(limit) = self.maximum_retransmissions {
if timed_out_ack.retransmissions >= limit {
warn!("reached maximum number of allowed retransmissions for the packet");
self.action_sender
.unbounded_send(Action::new_remove(frag_id))
.unwrap();
return;
}
}
let maybe_prepared_fragment = match &timed_out_ack.destination {
PacketDestination::Anonymous {
recipient_tag,
@@ -116,6 +101,8 @@ where
}
};
let frag_id = timed_out_ack.message_chunk.fragment_identifier();
let prepared_fragment = match maybe_prepared_fragment {
Ok(prepared_fragment) => prepared_fragment,
Err(err) => {
@@ -149,7 +136,7 @@ where
// with the additional poisson delay.
// And since Actions are executed in order `UpdateTimer` will HAVE TO be executed before `StartTimer`
self.action_sender
.unbounded_send(Action::new_update_pending_ack(frag_id, new_delay))
.unbounded_send(Action::new_update_delay(frag_id, new_delay))
.unwrap();
// send to `OutQueueControl` to eventually send to the mix network
@@ -91,9 +91,6 @@ pub(crate) struct Config {
/// and surb-based are going to be sent.
sender_address: Recipient,
/// Specify whether route selection should be determined by the packet header.
deterministic_route_selection: bool,
/// Average delay a data packet is going to get delay at a single mixnode.
average_packet_delay: Duration,
@@ -117,12 +114,10 @@ impl Config {
sender_address: Recipient,
average_packet_delay: Duration,
average_ack_delay: Duration,
deterministic_route_selection: bool,
) -> Self {
Config {
ack_key,
sender_address,
deterministic_route_selection,
average_packet_delay,
average_ack_delay,
num_mix_hops: DEFAULT_NUM_MIX_HOPS,
@@ -181,7 +176,6 @@ where
{
let message_preparer = MessagePreparer::new(
rng,
config.deterministic_route_selection,
config.sender_address,
config.average_packet_delay,
config.average_ack_delay,
@@ -640,7 +634,7 @@ where
pub(crate) fn update_ack_delay(&self, id: FragmentIdentifier, new_delay: Delay) {
self.action_sender
.unbounded_send(Action::UpdatePendingAck(id, new_delay))
.unbounded_send(Action::UpdateDelay(id, new_delay))
.expect("action control task has died")
}
@@ -65,7 +65,6 @@ pub struct Config {
impl<'a> From<&'a Config> for acknowledgement_control::Config {
fn from(cfg: &'a Config) -> Self {
acknowledgement_control::Config::new(
cfg.traffic.maximum_number_of_retransmissions,
cfg.acks.ack_wait_addition,
cfg.acks.ack_wait_multiplier,
)
@@ -98,7 +97,6 @@ impl<'a> From<&'a Config> for message_handler::Config {
cfg.self_recipient,
cfg.traffic.average_packet_delay,
cfg.acks.average_ack_delay,
cfg.traffic.deterministic_route_selection,
)
.with_custom_primary_packet_size(cfg.traffic.primary_packet_size)
.with_custom_secondary_packet_size(cfg.traffic.secondary_packet_size)
@@ -29,7 +29,6 @@ nym-crypto = { path = "../../crypto" }
nym-gateway-requests = { path = "../../gateway-requests" }
nym-network-defaults = { path = "../../network-defaults" }
nym-sphinx = { path = "../../nymsphinx" }
nym-statistics-common = { path = "../../statistics" }
nym-pemstore = { path = "../../pemstore" }
nym-validator-client = { path = "../validator-client", default-features = false }
nym-task = { path = "../../task" }
@@ -25,8 +25,6 @@ use nym_gateway_requests::{
CREDENTIAL_UPDATE_V2_PROTOCOL_VERSION, CURRENT_PROTOCOL_VERSION,
};
use nym_sphinx::forwarding::packet::MixPacket;
use nym_statistics_common::clients::connection::ConnectionStatsEvent;
use nym_statistics_common::clients::ClientStatsSender;
use nym_task::TaskClient;
use nym_validator_client::nyxd::contract_traits::DkgQueryClient;
use rand::rngs::OsRng;
@@ -96,7 +94,6 @@ pub struct GatewayClient<C, St = EphemeralCredentialStorage> {
connection: SocketState,
packet_router: PacketRouter,
bandwidth_controller: Option<BandwidthController<C, St>>,
stats_reporter: ClientStatsSender,
// currently unused (but populated)
negotiated_protocol: Option<u8>,
@@ -106,7 +103,6 @@ pub struct GatewayClient<C, St = EphemeralCredentialStorage> {
}
impl<C, St> GatewayClient<C, St> {
#[allow(clippy::too_many_arguments)]
pub fn new(
cfg: GatewayClientConfig,
gateway_config: GatewayConfig,
@@ -115,7 +111,6 @@ impl<C, St> GatewayClient<C, St> {
shared_key: Option<Arc<SharedGatewayKey>>,
packet_router: PacketRouter,
bandwidth_controller: Option<BandwidthController<C, St>>,
stats_reporter: ClientStatsSender,
task_client: TaskClient,
) -> Self {
GatewayClient {
@@ -129,7 +124,6 @@ impl<C, St> GatewayClient<C, St> {
connection: SocketState::NotConnected,
packet_router,
bandwidth_controller,
stats_reporter,
negotiated_protocol: None,
task_client,
}
@@ -720,7 +714,6 @@ impl<C, St> GatewayClient<C, St> {
{
// TODO: make it configurable
const TICKETS_TO_SPEND: u32 = 1;
const MIXNET_TICKET: TicketType = TicketType::V1MixnetEntry;
if !self.authenticated {
return Err(GatewayClientError::NotAuthenticated);
@@ -757,23 +750,14 @@ impl<C, St> GatewayClient<C, St> {
let prepared_credential = self
.unchecked_bandwidth_controller()
.prepare_ecash_ticket(
MIXNET_TICKET,
TicketType::V1MixnetEntry,
self.gateway_identity.to_bytes(),
TICKETS_TO_SPEND,
)
.await?;
match self.claim_ecash_bandwidth(prepared_credential.data).await {
Ok(_) => {
self.stats_reporter.report(
ConnectionStatsEvent::TicketSpent {
typ: MIXNET_TICKET,
amount: TICKETS_TO_SPEND,
}
.into(),
);
Ok(())
}
Ok(_) => Ok(()),
Err(err) => {
error!("failed to claim ecash bandwidth with the gateway...: {err}");
if err.is_ticket_replay() {
@@ -1046,7 +1030,6 @@ impl GatewayClient<InitOnly, EphemeralCredentialStorage> {
connection: SocketState::NotConnected,
packet_router,
bandwidth_controller: None,
stats_reporter: ClientStatsSender::new(None),
negotiated_protocol: None,
task_client,
}
@@ -1056,7 +1039,6 @@ impl GatewayClient<InitOnly, EphemeralCredentialStorage> {
self,
packet_router: PacketRouter,
bandwidth_controller: Option<BandwidthController<C, St>>,
stats_reporter: ClientStatsSender,
task_client: TaskClient,
) -> GatewayClient<C, St> {
// invariants that can't be broken
@@ -1076,7 +1058,6 @@ impl GatewayClient<InitOnly, EphemeralCredentialStorage> {
connection: self.connection,
packet_router,
bandwidth_controller,
stats_reporter,
negotiated_protocol: self.negotiated_protocol,
task_client,
}
@@ -46,8 +46,7 @@ pub(crate) fn ws_fd(_conn: &WsConn) -> Option<RawFd> {
#[cfg(unix)]
match _conn.get_ref() {
MaybeTlsStream::Plain(stream) => Some(stream.as_raw_fd()),
MaybeTlsStream::Rustls(tls_stream) => Some(tls_stream.as_raw_fd()),
_ => None,
&_ => None,
}
#[cfg(not(unix))]
None
@@ -11,8 +11,7 @@ use crate::{
use nym_api_requests::ecash::models::{
AggregatedCoinIndicesSignatureResponse, AggregatedExpirationDateSignatureResponse,
BatchRedeemTicketsBody, EcashBatchTicketRedemptionResponse, EcashTicketVerificationResponse,
IssuedTicketbooksChallengeResponse, IssuedTicketbooksForResponse, SpentCredentialsResponse,
VerifyEcashTicketBody,
SpentCredentialsResponse, VerifyEcashTicketBody,
};
use nym_api_requests::ecash::{
BlindSignRequestBody, BlindedSignatureResponse, PartialCoinIndicesSignatureResponse,
@@ -25,17 +24,16 @@ use nym_api_requests::models::{
use nym_api_requests::models::{LegacyDescribedGateway, MixNodeBondAnnotated};
use nym_api_requests::nym_nodes::SkimmedNode;
use nym_coconut_dkg_common::types::EpochId;
use nym_ecash_contract_common::deposit::DepositId;
use nym_http_api_client::UserAgent;
use nym_network_defaults::NymNetworkDetails;
use time::Date;
use url::Url;
pub use crate::nym_api::NymApiClientExt;
use nym_mixnet_contract_common::NymNodeDetails;
pub use nym_mixnet_contract_common::{
mixnode::MixNodeDetails, GatewayBond, IdentityKey, IdentityKeyRef, NodeId, NymNodeDetails,
mixnode::MixNodeDetails, GatewayBond, IdentityKey, IdentityKeyRef, NodeId,
};
// re-export the type to not break existing imports
pub use crate::coconut::EcashApiClient;
@@ -332,10 +330,10 @@ impl NymApiClient {
NymApiClient { nym_api }
}
pub fn new_with_user_agent(api_url: Url, user_agent: impl Into<UserAgent>) -> Self {
pub fn new_with_user_agent(api_url: Url, user_agent: UserAgent) -> Self {
let nym_api = nym_api::Client::builder::<_, ValidatorClientError>(api_url)
.expect("invalid api url")
.with_user_agent(user_agent.into())
.with_user_agent(user_agent)
.build::<ValidatorClientError>()
.expect("failed to build nym api client");
@@ -698,22 +696,4 @@ impl NymApiClient {
) -> Result<VerificationKeyResponse, ValidatorClientError> {
Ok(self.nym_api.master_verification_key(epoch_id).await?)
}
pub async fn issued_ticketbooks_for(
&self,
expiration_date: Date,
) -> Result<IssuedTicketbooksForResponse, ValidatorClientError> {
Ok(self.nym_api.issued_ticketbooks_for(expiration_date).await?)
}
pub async fn issued_ticketbooks_challenge(
&self,
expiration_date: Date,
deposits: Vec<DepositId>,
) -> Result<IssuedTicketbooksChallengeResponse, ValidatorClientError> {
Ok(self
.nym_api
.issued_ticketbooks_challenge(expiration_date, deposits)
.await?)
}
}
@@ -7,34 +7,36 @@ use async_trait::async_trait;
use nym_api_requests::ecash::models::{
AggregatedCoinIndicesSignatureResponse, AggregatedExpirationDateSignatureResponse,
BatchRedeemTicketsBody, EcashBatchTicketRedemptionResponse, EcashTicketVerificationResponse,
IssuedTicketbooksChallengeRequest, IssuedTicketbooksChallengeResponse,
IssuedTicketbooksForResponse, VerifyEcashTicketBody,
VerifyEcashTicketBody,
};
use nym_api_requests::ecash::VerificationKeyResponse;
use nym_api_requests::models::{
AnnotationResponse, ApiHealthResponse, LegacyDescribedMixNode, NodePerformanceResponse,
NodeRefreshBody, NymNodeDescription,
NymNodeDescription,
};
use nym_api_requests::nym_nodes::PaginatedCachedNodesResponse;
use nym_api_requests::pagination::PaginatedResponse;
pub use nym_api_requests::{
ecash::{
models::SpentCredentialsResponse, BlindSignRequestBody, BlindedSignatureResponse,
models::{
EpochCredentialsResponse, IssuedCredentialResponse, IssuedCredentialsResponse,
IssuedTicketbook, IssuedTicketbookBody, SpentCredentialsResponse,
},
BlindSignRequestBody, BlindedSignatureResponse, CredentialsRequestBody,
PartialCoinIndicesSignatureResponse, PartialExpirationDateSignatureResponse,
VerifyEcashCredentialBody,
},
models::{
ComputeRewardEstParam, GatewayBondAnnotated, GatewayCoreStatusResponse,
GatewayStatusReportResponse, GatewayUptimeHistoryResponse, LegacyDescribedGateway,
MixNodeBondAnnotated, MixnodeCoreStatusResponse, MixnodeStatusReportResponse,
MixnodeStatusResponse, MixnodeUptimeHistoryResponse, RewardEstimationResponse,
StakeSaturationResponse, UptimeResponse,
GatewayStatusReportResponse, GatewayUptimeHistoryResponse, InclusionProbabilityResponse,
LegacyDescribedGateway, MixNodeBondAnnotated, MixnodeCoreStatusResponse,
MixnodeStatusReportResponse, MixnodeStatusResponse, MixnodeUptimeHistoryResponse,
RewardEstimationResponse, StakeSaturationResponse, UptimeResponse,
},
nym_nodes::{CachedNodesResponse, SkimmedNode},
};
pub use nym_coconut_dkg_common::types::EpochId;
use nym_contracts_common::IdentityKey;
use nym_ecash_contract_common::deposit::DepositId;
pub use nym_http_api_client::Client;
use nym_http_api_client::{ApiClient, NO_PARAMS};
use nym_mixnet_contract_common::mixnode::MixNodeDetails;
@@ -671,12 +673,11 @@ pub trait NymApiClientExt: ApiClient {
}
#[deprecated]
#[allow(deprecated)]
#[instrument(level = "debug", skip(self))]
async fn get_mixnode_inclusion_probability(
&self,
mix_id: NodeId,
) -> Result<nym_api_requests::models::InclusionProbabilityResponse, NymAPIError> {
) -> Result<InclusionProbabilityResponse, NymAPIError> {
self.get_json(
&[
routes::API_VERSION,
@@ -695,32 +696,16 @@ pub trait NymApiClientExt: ApiClient {
&self,
node_id: NodeId,
) -> Result<NodePerformanceResponse, NymAPIError> {
self.get_json(
&[
routes::API_VERSION,
"nym-nodes",
"performance",
&node_id.to_string(),
],
NO_PARAMS,
)
.await
self.get_json_from(format!("/v1/nym-nodes/performance/{node_id}"))
.await
}
async fn get_node_annotation(
&self,
node_id: NodeId,
) -> Result<AnnotationResponse, NymAPIError> {
self.get_json(
&[
routes::API_VERSION,
"nym-nodes",
"annotation",
&node_id.to_string(),
],
NO_PARAMS,
)
.await
self.get_json_from(format!("/v1/nym-nodes/annotation/{node_id}"))
.await
}
#[deprecated]
@@ -926,56 +911,62 @@ pub trait NymApiClientExt: ApiClient {
&[
routes::API_VERSION,
routes::ECASH_ROUTES,
ecash::MASTER_VERIFICATION_KEY,
routes::ecash::MASTER_VERIFICATION_KEY,
],
&params,
)
.await
}
async fn force_refresh_describe_cache(
#[instrument(level = "debug", skip(self))]
async fn epoch_credentials(
&self,
request: &NodeRefreshBody,
) -> Result<(), NymAPIError> {
self.post_json(
&[routes::API_VERSION, "nym-nodes", "refresh-described"],
NO_PARAMS,
request,
)
.await
}
async fn issued_ticketbooks_for(
&self,
expiration_date: Date,
) -> Result<IssuedTicketbooksForResponse, NymAPIError> {
dkg_epoch: EpochId,
) -> Result<EpochCredentialsResponse, NymAPIError> {
self.get_json(
&[
routes::API_VERSION,
routes::ECASH_ROUTES,
routes::ECASH_ISSUED_TICKETBOOKS_FOR,
&expiration_date.to_string(),
routes::ECASH_EPOCH_CREDENTIALS,
&dkg_epoch.to_string(),
],
NO_PARAMS,
)
.await
}
async fn issued_ticketbooks_challenge(
#[instrument(level = "debug", skip(self))]
async fn issued_credential(
&self,
expiration_date: Date,
deposits: Vec<DepositId>,
) -> Result<IssuedTicketbooksChallengeResponse, NymAPIError> {
credential_id: i64,
) -> Result<IssuedCredentialResponse, NymAPIError> {
self.get_json(
&[
routes::API_VERSION,
routes::ECASH_ROUTES,
routes::ECASH_ISSUED_CREDENTIAL,
&credential_id.to_string(),
],
NO_PARAMS,
)
.await
}
#[instrument(level = "debug", skip(self))]
async fn issued_credentials(
&self,
credential_ids: Vec<i64>,
) -> Result<IssuedCredentialsResponse, NymAPIError> {
self.post_json(
&[
routes::API_VERSION,
routes::ECASH_ROUTES,
routes::ECASH_ISSUED_TICKETBOOKS_CHALLENGE,
routes::ECASH_ISSUED_CREDENTIALS,
],
NO_PARAMS,
&IssuedTicketbooksChallengeRequest {
expiration_date,
deposits,
&CredentialsRequestBody {
credential_ids,
pagination: None,
},
)
.await
@@ -27,8 +27,9 @@ pub mod ecash {
pub const PARTIAL_COIN_INDICES_SIGNATURES: &str = "partial-coin-indices-signatures";
pub const GLOBAL_COIN_INDICES_SIGNATURES: &str = "aggregated-coin-indices-signatures";
pub const MASTER_VERIFICATION_KEY: &str = "master-verification-key";
pub const ECASH_ISSUED_TICKETBOOKS_FOR: &str = "issued-ticketbooks-for";
pub const ECASH_ISSUED_TICKETBOOKS_CHALLENGE: &str = "issued-ticketbooks-challenge";
pub const ECASH_EPOCH_CREDENTIALS: &str = "epoch-credentials";
pub const ECASH_ISSUED_CREDENTIAL: &str = "issued-credential";
pub const ECASH_ISSUED_CREDENTIALS: &str = "issued-credentials";
pub const EXPIRATION_DATE_PARAM: &str = "expiration_date";
pub const EPOCH_ID_PARAM: &str = "epoch_id";
@@ -7,7 +7,6 @@ use crate::nyxd::error::NyxdError;
use crate::nyxd::CosmWasmClient;
use async_trait::async_trait;
use cosmwasm_std::Coin;
use nym_ecash_contract_common::deposit::LatestDepositResponse;
use nym_ecash_contract_common::msg::QueryMsg as EcashQueryMsg;
use serde::Deserialize;
@@ -52,11 +51,6 @@ pub trait EcashQueryClient {
.await
}
async fn get_latest_deposit(&self) -> Result<LatestDepositResponse, NyxdError> {
self.query_ecash_contract(EcashQueryMsg::GetLatestDeposit {})
.await
}
async fn get_deposits_paged(
&self,
start_after: Option<u32>,
@@ -104,6 +98,7 @@ where
mod tests {
use super::*;
use crate::nyxd::contract_traits::tests::IgnoreValue;
use nym_ecash_contract_common::msg::QueryMsg;
// it's enough that this compiles and clippy is happy about it
#[allow(dead_code)]
@@ -115,17 +110,14 @@ mod tests {
EcashQueryMsg::GetBlacklistedAccount { public_key } => {
client.get_blacklisted_account(public_key).ignore()
}
EcashQueryMsg::GetBlacklistPaged { limit, start_after } => {
QueryMsg::GetBlacklistPaged { limit, start_after } => {
client.get_blacklist_paged(start_after, limit).ignore()
}
EcashQueryMsg::GetDeposit { deposit_id } => client.get_deposit(deposit_id).ignore(),
EcashQueryMsg::GetDepositsPaged { limit, start_after } => {
QueryMsg::GetDeposit { deposit_id } => client.get_deposit(deposit_id).ignore(),
QueryMsg::GetDepositsPaged { limit, start_after } => {
client.get_deposits_paged(start_after, limit).ignore()
}
EcashQueryMsg::GetRequiredDepositAmount {} => {
client.get_required_deposit_amount().ignore()
}
EcashQueryMsg::GetLatestDeposit {} => client.get_latest_deposit().ignore(),
QueryMsg::GetRequiredDepositAmount {} => client.get_required_deposit_amount().ignore(),
};
}
}
@@ -10,10 +10,10 @@ use cosmrs::AccountId;
use nym_contracts_common::signing::Nonce;
use nym_mixnet_contract_common::gateway::{PreassignedGatewayIdsResponse, PreassignedId};
use nym_mixnet_contract_common::nym_node::{
EpochAssignmentResponse, NodeDetailsByIdentityResponse, NodeDetailsResponse,
NodeOwnershipResponse, NodeRewardingDetailsResponse, PagedNymNodeBondsResponse,
PagedNymNodeDetailsResponse, PagedUnbondedNymNodesResponse, Role, RolesMetadataResponse,
StakeSaturationResponse, UnbondedNodeResponse, UnbondedNymNode,
EpochAssignmentResponse, NodeDetailsByIdentityResponse, NodeOwnershipResponse,
NodeRewardingDetailsResponse, PagedNymNodeBondsResponse, PagedNymNodeDetailsResponse,
PagedUnbondedNymNodesResponse, Role, RolesMetadataResponse, StakeSaturationResponse,
UnbondedNodeResponse, UnbondedNymNode,
};
use nym_mixnet_contract_common::reward_params::WorkFactor;
use nym_mixnet_contract_common::{
@@ -66,6 +66,11 @@ pub trait MixnetQueryClient {
.await
}
async fn get_mixnet_contract_settings(&self) -> Result<ContractStateParams, NyxdError> {
self.query_mixnet_contract(MixnetQueryMsg::GetStateParams {})
.await
}
async fn get_mixnet_contract_state_params(&self) -> Result<ContractStateParams, NyxdError> {
self.query_mixnet_contract(MixnetQueryMsg::GetStateParams {})
.await
@@ -311,7 +316,10 @@ pub trait MixnetQueryClient {
.await
}
async fn get_nymnode_details(&self, node_id: NodeId) -> Result<NodeDetailsResponse, NyxdError> {
async fn get_nymnode_details(
&self,
node_id: NodeId,
) -> Result<NodeOwnershipResponse, NyxdError> {
self.query_mixnet_contract(MixnetQueryMsg::GetNymNodeDetails { node_id })
.await
}
@@ -17,7 +17,7 @@ use nym_mixnet_contract_common::reward_params::{
ActiveSetUpdate, IntervalRewardingParamsUpdate, NodeRewardingParameters,
};
use nym_mixnet_contract_common::{
ContractStateParamsUpdate, ExecuteMsg as MixnetExecuteMsg, Gateway, MixNode, NodeId, NymNode,
ContractStateParams, ExecuteMsg as MixnetExecuteMsg, Gateway, MixNode, NodeId, NymNode,
RoleAssignment,
};
@@ -59,27 +59,12 @@ pub trait MixnetSigningClient {
async fn update_contract_state_params(
&self,
update: ContractStateParamsUpdate,
updated_parameters: ContractStateParams,
fee: Option<Fee>,
) -> Result<ExecuteResult, NyxdError> {
self.execute_mixnet_contract(
fee,
MixnetExecuteMsg::UpdateContractStateParams { update },
vec![],
)
.await
}
async fn update_current_nym_node_semver(
&self,
current_nym_node_semver: String,
fee: Option<Fee>,
) -> Result<ExecuteResult, NyxdError> {
self.execute_mixnet_contract(
fee,
MixnetExecuteMsg::UpdateCurrentNymNodeSemver {
current_version: current_nym_node_semver,
},
MixnetExecuteMsg::UpdateContractStateParams { updated_parameters },
vec![],
)
.await
@@ -697,11 +682,8 @@ mod tests {
MixnetExecuteMsg::UpdateRewardingValidatorAddress { address } => client
.update_rewarding_validator_address(address.parse().unwrap(), None)
.ignore(),
MixnetExecuteMsg::UpdateContractStateParams { update } => {
client.update_contract_state_params(update, None).ignore()
}
MixnetExecuteMsg::UpdateCurrentNymNodeSemver { current_version } => client
.update_current_nym_node_semver(current_version, None)
MixnetExecuteMsg::UpdateContractStateParams { updated_parameters } => client
.update_contract_state_params(updated_parameters, None)
.ignore(),
MixnetExecuteMsg::UpdateActiveSetDistribution {
update,
@@ -303,7 +303,7 @@ where
feature = "tendermint-rpc-http-client",
feature = "tendermint-rpc-websocket-client"
))]
async fn wait_until_healthy<T>(&self, timeout: T) -> Result<(), TendermintRpcError>
async fn wait_until_healthy<T>(&self, timeout: T) -> Result<(), Error>
where
T: Into<core::time::Duration> + Send,
{
@@ -823,7 +823,7 @@ where
feature = "tendermint-rpc-http-client",
feature = "tendermint-rpc-websocket-client"
))]
async fn wait_until_healthy<T>(&self, timeout: T) -> Result<(), TendermintRpcError>
async fn wait_until_healthy<T>(&self, timeout: T) -> Result<(), Error>
where
T: Into<core::time::Duration> + Send,
{
@@ -523,7 +523,7 @@ mod non_wasm {
))]
async fn wait_until_healthy<T>(&self, timeout: T) -> Result<(), Error>
where
T: Into<core::time::Duration> + Send,
T: Into<Duration> + Send,
{
self.wait_until_healthy(timeout).await
}
@@ -98,13 +98,6 @@ impl DirectSecp256k1HdWallet {
Ok((private_key, public_key))
}
pub fn derive_extended_private_key(
&self,
hd_path: &DerivationPath,
) -> Result<XPrv, DirectSecp256k1HdWalletError> {
Ok(XPrv::derive_from_path(self.seed, hd_path)?)
}
pub fn try_derive_accounts(&self) -> Result<Vec<AccountData>, DirectSecp256k1HdWalletError> {
let mut accounts = Vec::with_capacity(self.accounts.len());
for derivation_info in &self.accounts {
@@ -6,7 +6,6 @@ use crate::utils::CommonConfigsWrapper;
use anyhow::{anyhow, bail};
use clap::ArgGroup;
use clap::Parser;
use log::info;
use nym_credential_storage::initialise_persistent_storage;
use nym_credential_storage::storage::Storage;
use nym_credential_utils::utils;
@@ -151,7 +150,6 @@ async fn issue_to_file(args: Args, client: SigningClient) -> anyhow::Result<()>
exported = exported.with_master_verification_key(&EpochVerificationKey { epoch_id, key });
}
info!("the issued ticketbook has expiration of {expiration_date}");
let data = exported.pack().data;
if args.bs58_output {
@@ -33,9 +33,6 @@ pub struct Args {
#[clap(long)]
pub rewarding_denom: Option<String>,
#[clap(long)]
pub current_nym_node_version: String,
#[clap(long, default_value_t = 720)]
pub epochs_in_interval: u32,
@@ -146,9 +143,6 @@ pub async fn generate(args: Args) {
epochs_in_interval: args.epochs_in_interval,
epoch_duration: Duration::from_secs(args.epoch_duration),
initial_rewarding_params,
current_nym_node_version: args.current_nym_node_version,
version_score_weights: Default::default(),
version_score_params: Default::default(),
profit_margin: ProfitMarginRange {
minimum: args.minimum_profit_margin_percent,
maximum: args.maximum_profit_margin_percent,
+1 -12
View File
@@ -1,7 +1,7 @@
// Copyright 2023 - Nym Technologies SA <contact@nymtech.net>
// SPDX-License-Identifier: Apache-2.0
use serde::{Deserialize, Deserializer, Serializer};
use serde::{Deserialize, Deserializer};
use std::fmt::Display;
use std::path::PathBuf;
use std::str::FromStr;
@@ -20,17 +20,6 @@ where
}
}
pub fn ser_maybe_stringified<S, T>(field: &Option<T>, serializer: S) -> Result<S::Ok, S::Error>
where
S: Serializer,
T: Display,
{
match field {
Some(inner) => serializer.serialize_str(&inner.to_string()),
None => serializer.serialize_str(""),
}
}
pub fn de_maybe_string<'de, D>(deserializer: D) -> Result<Option<String>, D::Error>
where
D: Deserializer<'de>,
@@ -21,6 +21,3 @@ serde_json = { workspace = true }
[build-dependencies]
vergen = { workspace = true, features = ["build", "git", "gitcl", "rustc", "cargo"] }
[features]
naive_float = []
@@ -130,7 +130,7 @@ impl Deref for Percent {
}
// this is not implemented via From traits due to its naive nature and loss of precision
#[cfg(feature = "naive_float")]
#[cfg(not(target_arch = "wasm32"))]
pub trait NaiveFloat {
fn naive_to_f64(&self) -> f64;
@@ -139,8 +139,8 @@ pub trait NaiveFloat {
Self: Sized;
}
#[cfg(feature = "naive_float")]
impl NaiveFloat for Decimal {
#[cfg(not(target_arch = "wasm32"))]
impl NaiveFloat for Percent {
fn naive_to_f64(&self) -> f64 {
use cosmwasm_std::Fraction;
@@ -181,21 +181,7 @@ impl NaiveFloat for Decimal {
}
let (n, d) = to_rational(val);
Ok(Decimal::from_ratio(n, d))
}
}
#[cfg(feature = "naive_float")]
impl NaiveFloat for Percent {
fn naive_to_f64(&self) -> f64 {
self.0.naive_to_f64()
}
fn naive_try_from_f64(val: f64) -> Result<Self, ContractsCommonError>
where
Self: Sized,
{
Percent::new(Decimal::naive_try_from_f64(val)?)
Percent::new(Decimal::from_ratio(n, d))
}
}
@@ -47,12 +47,6 @@ impl Deposit {
}
}
#[cw_serde]
#[derive(Default)]
pub struct LatestDepositResponse {
pub deposit: Option<DepositData>,
}
#[cw_serde]
pub struct DepositResponse {
pub id: DepositId,
@@ -1,4 +1,4 @@
// Copyright 2024 - Nym Technologies SA <contact@nymtech.net>
// Copyright 2021 - Nym Technologies SA <contact@nymtech.net>
// SPDX-License-Identifier: Apache-2.0
use cosmwasm_schema::cw_serde;
@@ -7,7 +7,7 @@ use cosmwasm_std::Coin;
#[cfg(feature = "schema")]
use crate::blacklist::{BlacklistedAccountResponse, PagedBlacklistedAccountResponse};
#[cfg(feature = "schema")]
use crate::deposit::{DepositResponse, LatestDepositResponse, PagedDepositsResponse};
use crate::deposit::{DepositResponse, PagedDepositsResponse};
#[cfg(feature = "schema")]
use cosmwasm_schema::QueryResponses;
@@ -73,9 +73,6 @@ pub enum QueryMsg {
#[cfg_attr(feature = "schema", returns(DepositResponse))]
GetDeposit { deposit_id: u32 },
#[cfg_attr(feature = "schema", returns(LatestDepositResponse))]
GetLatestDeposit {},
#[cfg_attr(feature = "schema", returns(PagedDepositsResponse))]
GetDepositsPaged {
limit: Option<u32>,
@@ -17,7 +17,6 @@ cw-controllers = { workspace = true }
cw2 = { workspace = true, optional = true }
serde = { workspace = true, features = ["derive"] }
serde_repr = { workspace = true }
semver = { workspace = true, features = ["serde"] }
# we still have to preserve that import for `JsonSchema` for `Layer` type (since we can't use cw_serde macro due to custom serde impl)
schemars = { workspace = true }
@@ -27,6 +26,8 @@ serde-json-wasm = { workspace = true }
humantime-serde = { workspace = true }
utoipa = { workspace = true, optional = true }
# TO CHECK WHETHER STILL NEEDED:
log = { workspace = true }
time = { workspace = true, features = ["parsing", "formatting"] }
ts-rs = { workspace = true, optional = true }
@@ -37,6 +38,6 @@ time = { workspace = true, features = ["serde", "macros"] }
[features]
default = []
contract-testing = []
utoipa = ["dep:utoipa"]
utoipa = [ "dep:utoipa" ]
schema = ["cw2"]
generate-ts = ['ts-rs']
@@ -166,9 +166,6 @@ pub enum MixnetContractError {
#[error("Provided message to update rewarding params did not contain any updates")]
EmptyParamsChangeMsg,
#[error("provided message to update state parameters did not contain any updates")]
EmptyStateUpdateMsg,
#[error("one of the roles in the new active set is empty")]
EmptyRoleAssignment,
@@ -272,9 +269,6 @@ pub enum MixnetContractError {
#[error("the total work for this epoch seems to be bigger than 1.0!")]
TotalWorkAboveOne,
#[error("the provided nym-node version is not a valid semver. got: {provided}")]
InvalidNymNodeSemver { provided: String },
}
impl MixnetContractError {
@@ -7,9 +7,9 @@ use crate::mixnode::{MixNodeConfigUpdate, NodeCostParams};
use crate::nym_node::Role;
use crate::reward_params::{ActiveSetUpdate, IntervalRewardParams, IntervalRewardingParamsUpdate};
use crate::rewarding::RewardDistribution;
use crate::{BlockHeight, ContractStateParamsUpdate, EpochId, IdentityKeyRef, Interval, NodeId};
use crate::{BlockHeight, ContractStateParams, EpochId, IdentityKeyRef, Interval, NodeId};
pub use contracts_common::events::*;
use cosmwasm_std::{attr, Addr, Coin, Decimal, Event};
use cosmwasm_std::{Addr, Coin, Decimal, Event};
use std::fmt::Display;
pub const EVENT_VERSION_PREFIX: &str = "v2_";
@@ -45,7 +45,6 @@ pub enum MixnetEventType {
DelegationOnUnbonding,
Undelegation,
ContractSettingsUpdate,
NymNodeSemverUpdate,
RewardingValidatorUpdate,
BeginEpochTransition,
AdvanceEpoch,
@@ -98,7 +97,6 @@ impl Display for MixnetEventType {
MixnetEventType::Delegation => "delegation",
MixnetEventType::Undelegation => "undelegation",
MixnetEventType::ContractSettingsUpdate => "settings_update",
MixnetEventType::NymNodeSemverUpdate => "nym_node_semver_update",
MixnetEventType::RewardingValidatorUpdate => "rewarding_validator_address_update",
MixnetEventType::BeginEpochTransition => "beginning_epoch_transition",
MixnetEventType::AdvanceEpoch => "advance_epoch",
@@ -134,13 +132,11 @@ pub const NODE_ID_KEY: &str = "node_id";
pub const NODE_IDENTITY_KEY: &str = "identity";
// settings change
pub const OLD_MINIMUM_PLEDGE_KEY: &str = "old_minimum_pledge";
pub const OLD_MINIMUM_DELEGATION_KEY: &str = "old_minimum_delegation";
pub const NEW_MINIMUM_PLEDGE_KEY: &str = "new_minimum_pledge";
pub const NEW_MINIMUM_DELEGATION_KEY: &str = "new_minimum_delegation";
pub const NEW_PROFIT_MARGIN_RANGE_KEY: &str = "new_profit_margin_range";
pub const NEW_INTERVAL_OPERATING_COST_RANGE_KEY: &str = "new_interval_operating_cost_range";
pub const NEW_VERSION_WEIGHTS_RANGE_KEY: &str = "new_version_weights_range";
pub const NEW_VERSION_SCORE_FORMULA_PARAMS_KEY: &str = "new_version_score_formula_params";
pub const NYM_NODE_CURRENT_SEMVER_KEY: &str = "new_current_semver";
pub const OLD_REWARDING_VALIDATOR_ADDRESS_KEY: &str = "old_rewarding_validator_address";
pub const NEW_REWARDING_VALIDATOR_ADDRESS_KEY: &str = "new_rewarding_validator_address";
@@ -444,73 +440,40 @@ pub fn new_rewarding_validator_address_update_event(old: Addr, new: Addr) -> Eve
.add_attribute(NEW_REWARDING_VALIDATOR_ADDRESS_KEY, new)
}
pub fn new_settings_update_event(update: &ContractStateParamsUpdate) -> Event {
pub fn new_settings_update_event(
old_params: &ContractStateParams,
new_params: &ContractStateParams,
) -> Event {
let mut event = Event::new(MixnetEventType::ContractSettingsUpdate);
// check for delegations params updates
if let Some(delegations_update) = &update.delegations_params {
event.attributes.push(attr(
NEW_MINIMUM_DELEGATION_KEY,
delegations_update
.minimum_delegation
.as_ref()
.map(|d| d.to_string())
.unwrap_or("empty".to_string()),
));
if old_params.minimum_pledge != new_params.minimum_pledge {
event = event
.add_attribute(
OLD_MINIMUM_PLEDGE_KEY,
old_params.minimum_pledge.to_string(),
)
.add_attribute(
NEW_MINIMUM_PLEDGE_KEY,
new_params.minimum_pledge.to_string(),
)
}
// check for operators params updates
if let Some(operators_update) = &update.operators_params {
if let Some(minimum_pledge) = &operators_update.minimum_pledge {
event
.attributes
.push(attr(NEW_MINIMUM_PLEDGE_KEY, minimum_pledge.to_string()))
if old_params.minimum_delegation != new_params.minimum_delegation {
if let Some(ref old) = old_params.minimum_delegation {
event = event.add_attribute(OLD_MINIMUM_DELEGATION_KEY, old.to_string())
} else {
event = event.add_attribute(OLD_MINIMUM_DELEGATION_KEY, "None")
}
if let Some(profit_margin) = &operators_update.profit_margin {
event
.attributes
.push(attr(NEW_PROFIT_MARGIN_RANGE_KEY, profit_margin.to_string()))
}
if let Some(interval_operating_cost) = &operators_update.interval_operating_cost {
event.attributes.push(attr(
NEW_INTERVAL_OPERATING_COST_RANGE_KEY,
interval_operating_cost.to_string(),
))
}
}
// check for config score params updates
if let Some(config_score_update) = &update.config_score_params {
if let Some(current_nym_node_semver) = &config_score_update.current_nym_node_semver {
event.attributes.push(attr(
NYM_NODE_CURRENT_SEMVER_KEY,
current_nym_node_semver.to_string(),
))
}
if let Some(version_weights) = &config_score_update.version_weights {
event.attributes.push(attr(
NEW_VERSION_WEIGHTS_RANGE_KEY,
format!("{version_weights:?}"),
))
}
if let Some(version_score_formula_params) =
&config_score_update.version_score_formula_params
{
event.attributes.push(attr(
NEW_VERSION_SCORE_FORMULA_PARAMS_KEY,
format!("{version_score_formula_params:?}"),
))
if let Some(ref new) = new_params.minimum_delegation {
event = event.add_attribute(NEW_MINIMUM_DELEGATION_KEY, new.to_string())
} else {
event = event.add_attribute(NEW_MINIMUM_DELEGATION_KEY, "None")
}
}
event
}
pub fn new_update_nym_node_semver_event(new_version: &str) -> Event {
Event::new(MixnetEventType::NymNodeSemverUpdate)
.add_attribute(NYM_NODE_CURRENT_SEMVER_KEY, new_version)
}
pub fn new_not_found_node_operator_rewarding_event(interval: Interval, node_id: NodeId) -> Event {
Event::new(MixnetEventType::NodeRewarding)
.add_attribute(
@@ -12,11 +12,8 @@ use crate::reward_params::{
ActiveSetUpdate, IntervalRewardParams, IntervalRewardingParamsUpdate, NodeRewardingParameters,
Performance, RewardedSetParams, RewardingParams, WorkFactor,
};
use crate::types::NodeId;
use crate::{
ContractStateParamsUpdate, NymNode, OutdatedVersionWeights, RoleAssignment,
VersionScoreFormulaParams,
};
use crate::types::{ContractStateParams, NodeId};
use crate::{NymNode, RoleAssignment};
use crate::{OperatingCostRange, ProfitMarginRange};
use contracts_common::{signing::MessageSignature, IdentityKey, Percent};
use cosmwasm_schema::cw_serde;
@@ -50,7 +47,7 @@ use crate::{
PendingIntervalEventResponse, PendingIntervalEventsResponse,
},
rewarding::{EstimatedCurrentEpochRewardResponse, PendingRewardResponse},
types::{ContractState, ContractStateParams},
types::ContractState,
};
#[cfg(feature = "schema")]
use contracts_common::{signing::Nonce, ContractBuildInformation};
@@ -67,14 +64,6 @@ pub struct InstantiateMsg {
pub epoch_duration: Duration,
pub initial_rewarding_params: InitialRewardingParams,
pub current_nym_node_version: String,
#[serde(default)]
pub version_score_weights: OutdatedVersionWeights,
#[serde(default)]
pub version_score_params: VersionScoreFormulaParams,
#[serde(default)]
pub profit_margin: ProfitMarginRange,
@@ -137,10 +126,7 @@ pub enum ExecuteMsg {
address: String,
},
UpdateContractStateParams {
update: ContractStateParamsUpdate,
},
UpdateCurrentNymNodeSemver {
current_version: String,
updated_parameters: ContractStateParams,
},
UpdateActiveSetDistribution {
update: ActiveSetUpdate,
@@ -309,9 +295,6 @@ impl ExecuteMsg {
ExecuteMsg::UpdateContractStateParams { .. } => {
"updating mixnet state parameters".into()
}
ExecuteMsg::UpdateCurrentNymNodeSemver { current_version } => {
format!("updating current nym-node semver to {current_version}")
}
ExecuteMsg::UpdateActiveSetDistribution {
force_immediately, ..
} => format!("updating active set distribution. forced: {force_immediately}"),
@@ -846,13 +829,6 @@ pub enum QueryMsg {
#[cw_serde]
pub struct MigrateMsg {
pub unsafe_skip_state_updates: Option<bool>,
pub vesting_contract_address: Option<String>,
pub current_nym_node_semver: String,
#[serde(default)]
pub version_score_weights: OutdatedVersionWeights,
#[serde(default)]
pub version_score_params: VersionScoreFormulaParams,
pub unsafe_skip_state_updates: Option<bool>,
}
@@ -4,8 +4,8 @@
use crate::nym_node::Role;
use contracts_common::Percent;
use cosmwasm_schema::cw_serde;
use cosmwasm_std::Coin;
use cosmwasm_std::{Addr, Uint128};
use cosmwasm_std::{Coin, Decimal};
use std::fmt::{Display, Formatter};
// type aliases for better reasoning about available data
@@ -161,156 +161,19 @@ pub struct ContractState {
/// Contract parameters that could be adjusted in a transaction by the contract admin.
#[cw_serde]
pub struct ContractStateParams {
/// Parameters to do with delegations.
pub delegations_params: DelegationsParams,
/// Parameters to do with node operators.
pub operators_params: OperatorsParams,
/// Parameters to do with the config score
pub config_score_params: ConfigScoreParams,
}
#[cw_serde]
pub struct ContractStateParamsUpdate {
pub delegations_params: Option<DelegationsParams>,
pub operators_params: Option<OperatorsParamsUpdate>,
pub config_score_params: Option<ConfigScoreParamsUpdate>,
}
impl ContractStateParamsUpdate {
pub fn contains_updates(&self) -> bool {
self.delegations_params.is_some()
|| self.operators_params.is_some()
|| self.config_score_params.is_some()
}
}
#[cw_serde]
pub struct DelegationsParams {
/// Minimum amount a delegator must stake in orders for his delegation to get accepted.
pub minimum_delegation: Option<Coin>,
}
#[cw_serde]
pub struct OperatorsParams {
/// Minimum amount a node must pledge to get into the system.
pub minimum_pledge: Coin,
/// Defines the allowed profit margin range of operators.
/// default: 0% - 100%
#[serde(default)]
pub profit_margin: ProfitMarginRange,
/// Defines the allowed interval operating cost range of operators.
/// default: 0 - 1'000'000'000'000'000 (1 Billion native tokens - the total supply)
#[serde(default)]
pub interval_operating_cost: OperatingCostRange,
}
#[cw_serde]
pub struct OperatorsParamsUpdate {
pub minimum_pledge: Option<Coin>,
pub profit_margin: Option<ProfitMarginRange>,
pub interval_operating_cost: Option<OperatingCostRange>,
}
impl OperatorsParamsUpdate {
pub fn contains_updates(&self) -> bool {
self.minimum_pledge.is_some()
|| self.profit_margin.is_some()
|| self.interval_operating_cost.is_some()
}
}
#[cw_serde]
pub struct ConfigScoreParams {
/// Current version of the nym node that is going to be used for determining the version score of a node.
/// note: value stored here is pre-validated `semver::Version`
pub current_nym_node_semver: String,
/// Defines weights for calculating numbers of versions behind the current release.
pub version_weights: OutdatedVersionWeights,
/// Defines the parameters of the formula for calculating the version score
pub version_score_formula_params: VersionScoreFormulaParams,
}
impl ConfigScoreParams {
// SAFETY: the value stored in the contract is always valid
#[allow(clippy::unwrap_used)]
pub fn unchecked_nym_node_version(&self) -> semver::Version {
self.current_nym_node_semver.parse().unwrap()
}
pub fn versions_behind(&self, node_semver: &semver::Version) -> u32 {
let expected = self.unchecked_nym_node_version();
let major_diff = (node_semver.major as i64 - expected.major as i64).unsigned_abs() as u32;
let minor_diff = (node_semver.minor as i64 - expected.minor as i64).unsigned_abs() as u32;
let patch_diff = (node_semver.patch as i64 - expected.patch as i64).unsigned_abs() as u32;
let prerelease_diff = if node_semver.pre == expected.pre {
0
} else {
1
};
major_diff * self.version_weights.major
+ minor_diff * self.version_weights.minor
+ patch_diff * self.version_weights.patch
+ prerelease_diff * self.version_weights.prerelease
}
}
/// Defines weights for calculating numbers of versions behind the current release.
#[cw_serde]
#[derive(Copy)]
pub struct OutdatedVersionWeights {
pub major: u32,
pub minor: u32,
pub patch: u32,
pub prerelease: u32,
}
impl Default for OutdatedVersionWeights {
fn default() -> Self {
OutdatedVersionWeights {
major: 100,
minor: 10,
patch: 1,
prerelease: 1,
}
}
}
/// Given the formula of version_score = penalty ^ (num_versions_behind ^ penalty_scaling)
/// define the relevant parameters
#[cw_serde]
#[derive(Copy)]
pub struct VersionScoreFormulaParams {
pub penalty: Decimal,
pub penalty_scaling: Decimal,
}
impl Default for VersionScoreFormulaParams {
fn default() -> Self {
#[allow(clippy::unwrap_used)]
VersionScoreFormulaParams {
penalty: "0.8".parse().unwrap(),
penalty_scaling: "2.0".parse().unwrap(),
}
}
}
#[cw_serde]
pub struct ConfigScoreParamsUpdate {
pub current_nym_node_semver: Option<String>,
pub version_weights: Option<OutdatedVersionWeights>,
pub version_score_formula_params: Option<VersionScoreFormulaParams>,
}
impl ConfigScoreParamsUpdate {
pub fn contains_updates(&self) -> bool {
self.current_nym_node_semver.is_some()
|| self.version_weights.is_some()
|| self.version_score_formula_params.is_some()
}
}
@@ -15,9 +15,7 @@ mixnet-contract-common = { path = "../mixnet-contract", package = "nym-mixnet-co
contracts-common = { path = "../contracts-common", package = "nym-contracts-common", version = "0.5.0" }
serde = { workspace = true, features = ["derive"] }
thiserror = { workspace = true }
# without this feature, cargo clippy emits a ton of incompatibility warnings
# https://docs.rs/ts-rs/latest/ts_rs/#serde-compatability
ts-rs = { workspace = true, optional = true, features = ["no-serde-warnings"] }
ts-rs = { workspace = true, optional = true}
[features]
schema = ["cw2"]
+1 -9
View File
@@ -221,15 +221,7 @@ impl From<PayInfo> for NymPayInfo {
}
#[derive(
Copy,
Clone,
Debug,
PartialEq,
Serialize,
Deserialize,
strum::Display,
strum::EnumString,
strum::EnumIter,
Copy, Clone, Debug, PartialEq, Serialize, Deserialize, strum::Display, strum::EnumString,
)]
#[serde(rename_all = "kebab-case")]
#[strum(serialize_all = "kebab-case")]
-127
View File
@@ -282,48 +282,6 @@ impl Client {
}
}
pub async fn create_delete_request<K, V>(
&self,
path: PathSegments<'_>,
params: Params<'_, K, V>,
) -> RequestBuilder
where
K: AsRef<str>,
V: AsRef<str>,
{
let url = sanitize_url(&self.base_url, path, params);
self.reqwest_client.delete(url)
}
pub async fn send_delete_request<K, V, E>(
&self,
path: PathSegments<'_>,
params: Params<'_, K, V>,
) -> Result<Response, HttpClientError<E>>
where
K: AsRef<str>,
V: AsRef<str>,
E: Display,
{
tracing::trace!("Sending DELETE request");
let url = sanitize_url(&self.base_url, path, params);
#[cfg(target_arch = "wasm32")]
{
Ok(wasmtimer::tokio::timeout(
self.request_timeout,
self.reqwest_client.delete(url).send(),
)
.await
.map_err(|_timeout| HttpClientError::RequestTimeout)??)
}
#[cfg(not(target_arch = "wasm32"))]
{
Ok(self.reqwest_client.delete(url).send().await?)
}
}
#[instrument(level = "debug", skip_all)]
pub async fn get_json<T, K, V, E>(
&self,
@@ -357,22 +315,6 @@ impl Client {
parse_response(res, true).await
}
pub async fn delete_json<T, K, V, E>(
&self,
path: PathSegments<'_>,
params: Params<'_, K, V>,
) -> Result<T, HttpClientError<E>>
where
for<'a> T: Deserialize<'a>,
K: AsRef<str>,
V: AsRef<str>,
E: Display + DeserializeOwned,
{
let res = self.send_delete_request(path, params).await?;
parse_response(res, false).await
}
#[instrument(level = "debug", skip_all)]
pub async fn get_json_endpoint<T, S, E>(&self, endpoint: S) -> Result<T, HttpClientError<E>>
where
for<'a> T: Deserialize<'a>,
@@ -437,35 +379,6 @@ impl Client {
parse_response(res, true).await
}
pub async fn delete_json_endpoint<T, S, E>(&self, endpoint: S) -> Result<T, HttpClientError<E>>
where
for<'a> T: Deserialize<'a>,
E: Display + DeserializeOwned,
S: AsRef<str>,
{
#[cfg(target_arch = "wasm32")]
let res = {
wasmtimer::tokio::timeout(
self.request_timeout,
self.reqwest_client
.delete(self.base_url.join(endpoint.as_ref())?)
.send(),
)
.await
.map_err(|_timeout| HttpClientError::RequestTimeout)??
};
#[cfg(not(target_arch = "wasm32"))]
let res = {
self.reqwest_client
.delete(self.base_url.join(endpoint.as_ref())?)
.send()
.await?
};
parse_response(res, false).await
}
}
// define those methods on the trait for nicer extensions (and not having to type the thing twice)
@@ -498,17 +411,6 @@ pub trait ApiClient {
V: AsRef<str> + Sync,
E: Display + DeserializeOwned;
async fn delete_json<T, K, V, E>(
&self,
path: PathSegments<'_>,
params: Params<'_, K, V>,
) -> Result<T, HttpClientError<E>>
where
for<'a> T: Deserialize<'a>,
K: AsRef<str> + Sync,
V: AsRef<str> + Sync,
E: Display + DeserializeOwned;
/// `get` json data from the provided absolute endpoint, i.e. for example `"/api/v1/mixnodes?since=12345"`
async fn get_json_from<T, S, E>(&self, endpoint: S) -> Result<T, HttpClientError<E>>
where
@@ -526,12 +428,6 @@ pub trait ApiClient {
for<'a> T: Deserialize<'a>,
E: Display + DeserializeOwned,
S: AsRef<str> + Sync + Send;
async fn delete_json_from<T, S, E>(&self, endpoint: S) -> Result<T, HttpClientError<E>>
where
for<'a> T: Deserialize<'a>,
E: Display + DeserializeOwned,
S: AsRef<str> + Sync + Send;
}
#[cfg_attr(target_arch = "wasm32", async_trait(?Send))]
@@ -567,20 +463,6 @@ impl ApiClient for Client {
self.post_json(path, params, json_body).await
}
async fn delete_json<T, K, V, E>(
&self,
path: PathSegments<'_>,
params: Params<'_, K, V>,
) -> Result<T, HttpClientError<E>>
where
for<'a> T: Deserialize<'a>,
K: AsRef<str> + Sync,
V: AsRef<str> + Sync,
E: Display + DeserializeOwned,
{
self.delete_json(path, params).await
}
async fn get_json_from<T, S, E>(&self, endpoint: S) -> Result<T, HttpClientError<E>>
where
for<'a> T: Deserialize<'a>,
@@ -603,15 +485,6 @@ impl ApiClient for Client {
{
self.post_json_endpoint(endpoint, json_body).await
}
async fn delete_json_from<T, S, E>(&self, endpoint: S) -> Result<T, HttpClientError<E>>
where
for<'a> T: Deserialize<'a>,
E: Display + DeserializeOwned,
S: AsRef<str> + Sync + Send,
{
self.delete_json_endpoint(endpoint).await
}
}
// utility function that should solve the double slash problem in API urls forever.
-3
View File
@@ -11,7 +11,4 @@ rust-version.workspace = true
readme.workspace = true
[dependencies]
anyhow = { workspace = true }
bincode = { workspace = true }
nym-crypto = { path = "../crypto", features = ["asymmetric", "serde"] }
serde = { workspace = true, features = ["derive"] }
-94
View File
@@ -1,101 +1,7 @@
use nym_crypto::asymmetric::ed25519::{PublicKey, Signature, SignatureError};
use serde::{Deserialize, Serialize};
pub mod get_testrun {
use super::*;
#[derive(Debug, Clone, Deserialize, Serialize)]
pub struct Payload {
pub agent_public_key: PublicKey,
pub timestamp: i64,
}
#[derive(Debug, Clone, Deserialize, Serialize)]
pub struct GetTestrunRequest {
pub payload: Payload,
pub signature: Signature,
}
impl SignedRequest for GetTestrunRequest {
type Payload = Payload;
fn public_key(&self) -> &PublicKey {
&self.payload.agent_public_key
}
fn signature(&self) -> &Signature {
&self.signature
}
fn payload(&self) -> &Self::Payload {
&self.payload
}
}
}
#[derive(Debug, Clone, Deserialize, Serialize)]
pub struct TestrunAssignment {
pub testrun_id: i64,
pub assigned_at_utc: i64,
pub gateway_identity_key: String,
}
pub mod submit_results {
use super::*;
#[derive(Debug, Clone, Deserialize, Serialize)]
pub struct Payload {
pub probe_result: String,
pub agent_public_key: PublicKey,
pub assigned_at_utc: i64,
}
#[derive(Debug, Clone, Deserialize, Serialize)]
pub struct SubmitResults {
pub payload: Payload,
pub signature: Signature,
}
impl SignedRequest for SubmitResults {
type Payload = Payload;
fn public_key(&self) -> &PublicKey {
&self.payload.agent_public_key
}
fn signature(&self) -> &Signature {
&self.signature
}
fn payload(&self) -> &Self::Payload {
&self.payload
}
}
}
pub trait SignedRequest {
type Payload: serde::Serialize;
fn public_key(&self) -> &PublicKey;
fn signature(&self) -> &Signature;
fn payload(&self) -> &Self::Payload;
}
pub trait VerifiableRequest: SignedRequest {
type Error: From<bincode::Error> + From<SignatureError>;
fn verify_signature(&self) -> Result<(), Self::Error> {
bincode::serialize(self.payload())
.map_err(Self::Error::from)
.and_then(|serialized| {
self.public_key()
.verify(serialized, self.signature())
.map_err(Self::Error::from)
})
}
}
impl<T> VerifiableRequest for T
where
T: SignedRequest,
{
type Error = anyhow::Error;
}
+2 -1
View File
@@ -50,7 +50,8 @@ pub mod wireguard {
pub const WG_PORT: u16 = 51822;
// The interface used to route traffic
pub const WG_TUN_BASE_NAME: &str = "nymwg";
pub const WG_TUN_BASE_NAME_V4: &str = "nymwg";
pub const WG_TUN_BASE_NAME_V6: &str = "nymwgv6";
pub const WG_TUN_DEVICE_ADDRESS: &str = "10.1.0.1";
pub const WG_TUN_DEVICE_IP_ADDRESS_V4: Ipv4Addr = Ipv4Addr::new(10, 1, 0, 1);
pub const WG_TUN_DEVICE_NETMASK_V4: u8 = 16;
-40
View File
@@ -157,46 +157,6 @@ impl NymNetworkDetails {
}
}
#[rustfmt::skip]
#[cfg(feature = "env")]
pub fn export_to_env(self) {
use crate::var_names;
use std::env::set_var;
fn set_optional_var(var_name: &str, value: Option<String>) {
if let Some(value) = value {
set_var(var_name, value);
}
}
set_var(var_names::NETWORK_NAME, self.network_name);
set_var(var_names::BECH32_PREFIX, self.chain_details.bech32_account_prefix);
set_var(var_names::MIX_DENOM, self.chain_details.mix_denom.base);
set_var(var_names::MIX_DENOM_DISPLAY, self.chain_details.mix_denom.display);
set_var(var_names::STAKE_DENOM, self.chain_details.stake_denom.base);
set_var(var_names::STAKE_DENOM_DISPLAY, self.chain_details.stake_denom.display);
set_var(var_names::DENOMS_EXPONENT, self.chain_details.mix_denom.display_exponent.to_string());
if let Some(e) = self.endpoints.first() {
set_var(var_names::NYXD, e.nyxd_url.clone());
set_optional_var(var_names::NYM_API, e.api_url.clone());
set_optional_var(var_names::NYXD_WEBSOCKET, e.websocket_url.clone());
}
set_optional_var(var_names::MIXNET_CONTRACT_ADDRESS, self.contracts.mixnet_contract_address);
set_optional_var(var_names::VESTING_CONTRACT_ADDRESS, self.contracts.vesting_contract_address);
set_optional_var(var_names::ECASH_CONTRACT_ADDRESS, self.contracts.ecash_contract_address);
set_optional_var(var_names::GROUP_CONTRACT_ADDRESS, self.contracts.group_contract_address);
set_optional_var(var_names::MULTISIG_CONTRACT_ADDRESS, self.contracts.multisig_contract_address);
set_optional_var(var_names::COCONUT_DKG_CONTRACT_ADDRESS, self.contracts.coconut_dkg_contract_address);
set_optional_var(var_names::EXPLORER_API, self.explorer_api);
set_optional_var(var_names::NYM_VPN_API, self.nym_vpn_api_url);
}
pub fn default_gas_price_amount(&self) -> f64 {
GAS_PRICE_AMOUNT
}
+4 -14
View File
@@ -29,9 +29,6 @@ pub struct NodeTester<R> {
packet_size: PacketSize,
/// Specify whether route selection should be determined by the packet header.
deterministic_route_selection: bool,
/// Average delay a data packet is going to get delay at a single mixnode.
average_packet_delay: Duration,
@@ -51,13 +48,11 @@ impl<R> NodeTester<R>
where
R: Rng + CryptoRng,
{
#[allow(clippy::too_many_arguments)]
pub fn new(
rng: R,
base_topology: NymTopology,
self_address: Option<Recipient>,
packet_size: PacketSize,
deterministic_route_selection: bool,
average_packet_delay: Duration,
average_ack_delay: Duration,
ack_key: Arc<AckKey>,
@@ -67,7 +62,6 @@ where
base_topology,
self_address,
packet_size,
deterministic_route_selection,
average_packet_delay,
average_ack_delay,
num_mix_hops: DEFAULT_NUM_MIX_HOPS,
@@ -295,18 +289,10 @@ where
impl<R: CryptoRng + Rng> FragmentPreparer for NodeTester<R> {
type Rng = R;
fn deterministic_route_selection(&self) -> bool {
self.deterministic_route_selection
}
fn rng(&mut self) -> &mut Self::Rng {
&mut self.rng
}
fn nonce(&self) -> i32 {
1
}
fn num_mix_hops(&self) -> u8 {
self.num_mix_hops
}
@@ -318,4 +304,8 @@ impl<R: CryptoRng + Rng> FragmentPreparer for NodeTester<R> {
fn average_ack_delay(&self) -> Duration {
self.average_ack_delay
}
fn nonce(&self) -> i32 {
1
}
}
+10 -28
View File
@@ -18,7 +18,7 @@ use nym_sphinx_params::{PacketType, ReplySurbKeyDigestAlgorithm, DEFAULT_NUM_MIX
use nym_sphinx_types::{Delay, NymPacket};
use nym_topology::{NymTopology, NymTopologyError};
use rand::{CryptoRng, Rng, SeedableRng};
use rand_chacha::ChaCha8Rng;
use rand_chacha::ChaCha20Rng;
use nym_sphinx_chunking::monitoring;
use std::time::Duration;
@@ -51,7 +51,6 @@ impl From<PreparedFragment> for MixPacket {
pub trait FragmentPreparer {
type Rng: CryptoRng + Rng;
fn deterministic_route_selection(&self) -> bool;
fn rng(&mut self) -> &mut Self::Rng;
fn nonce(&self) -> i32;
fn num_mix_hops(&self) -> u8;
@@ -202,7 +201,9 @@ pub trait FragmentPreparer {
// could perform diffie-hellman with its own keys followed by a kdf to re-derive
// the packet encryption key
let fragment_header = fragment.header();
let seed = fragment.seed().wrapping_mul(self.nonce());
let mut rng = ChaCha20Rng::seed_from_u64(seed as u64);
let destination = packet_recipient.gateway();
let hops = mix_hops.unwrap_or(self.num_mix_hops());
monitoring::fragment_sent(&fragment, self.nonce(), *destination, hops);
@@ -240,18 +241,8 @@ pub trait FragmentPreparer {
};
// generate pseudorandom route for the packet
log::trace!("Preparing chunk for sending with {hops} mix hops");
let route = if self.deterministic_route_selection() {
log::trace!("using deterministic route selection");
let seed = fragment_header.seed().wrapping_mul(self.nonce());
let mut rng = ChaCha8Rng::seed_from_u64(seed as u64);
topology.random_route_to_gateway(&mut rng, hops, destination)?
} else {
log::trace!("using pseudorandom route selection");
let mut rng = self.rng();
topology.random_route_to_gateway(&mut rng, hops, destination)?
};
log::trace!("Preparing chunk for sending with {} mix hops", hops);
let route = topology.random_route_to_gateway(&mut rng, hops, destination)?;
let destination = packet_recipient.as_sphinx_destination();
// including set of delays
@@ -322,9 +313,6 @@ pub struct MessagePreparer<R> {
/// Instance of a cryptographically secure random number generator.
rng: R,
/// Specify whether route selection should be determined by the packet header.
deterministic_route_selection: bool,
/// Address of this client which also represent an address to which all acknowledgements
/// and surb-based are going to be sent.
sender_address: Recipient,
@@ -348,7 +336,6 @@ where
{
pub fn new(
rng: R,
deterministic_route_selection: bool,
sender_address: Recipient,
average_packet_delay: Duration,
average_ack_delay: Duration,
@@ -357,7 +344,6 @@ where
let nonce = rng.gen();
MessagePreparer {
rng,
deterministic_route_selection,
sender_address,
average_packet_delay,
average_ack_delay,
@@ -471,18 +457,10 @@ where
impl<R: CryptoRng + Rng> FragmentPreparer for MessagePreparer<R> {
type Rng = R;
fn deterministic_route_selection(&self) -> bool {
self.deterministic_route_selection
}
fn rng(&mut self) -> &mut Self::Rng {
&mut self.rng
}
fn nonce(&self) -> i32 {
self.nonce
}
fn num_mix_hops(&self) -> u8 {
self.num_mix_hops
}
@@ -494,6 +472,10 @@ impl<R: CryptoRng + Rng> FragmentPreparer for MessagePreparer<R> {
fn average_ack_delay(&self) -> Duration {
self.average_ack_delay
}
fn nonce(&self) -> i32 {
self.nonce
}
}
/*
@@ -3,7 +3,7 @@
use serde::{Deserialize, Serialize};
#[derive(Clone, Debug, PartialEq, Serialize, Deserialize)]
#[derive(Clone, Debug, Serialize, Deserialize)]
#[repr(u8)]
pub enum ServiceProviderType {
NetworkRequester = 0,
-2
View File
@@ -15,13 +15,11 @@ log = { workspace = true }
sysinfo = { workspace = true }
serde = { workspace = true }
serde_json = { workspace = true }
sha2 = { workspace = true }
thiserror = { workspace = true }
time = { workspace = true }
tokio = { workspace = true }
si-scale = { workspace = true }
nym-crypto = { path = "../crypto" }
nym-sphinx = { path = "../nymsphinx" }
nym-credentials-interface = { path = "../credentials-interface" }
nym-metrics = { path = "../nym-metrics" }
@@ -1,67 +0,0 @@
// Copyright 2024 - Nym Technologies SA <contact@nymtech.net>
// SPDX-License-Identifier: Apache-2.0
use super::ClientStatsEvents;
use nym_credentials_interface::TicketType;
use serde::{Deserialize, Serialize};
#[derive(Default, Debug, Clone, Serialize, Deserialize)]
pub(crate) struct ConnectionStats {
//tickets
mixnet_entry_spent: u32,
vpn_entry_spent: u32,
mixnet_exit_spent: u32,
vpn_exit_spent: u32,
//country_connection
wg_exit_country_code: String,
mix_exit_country_code: String,
}
/// Event space for Nym API statistics tracking
#[derive(Debug)]
pub enum ConnectionStatsEvent {
/// ecash ticket was spend
TicketSpent {
typ: TicketType,
amount: u32,
},
WgCountry(String),
MixCountry(String),
}
impl From<ConnectionStatsEvent> for ClientStatsEvents {
fn from(event: ConnectionStatsEvent) -> ClientStatsEvents {
ClientStatsEvents::Connection(event)
}
}
/// Nym API statistics tracking object
#[derive(Default)]
pub struct ConnectionStatsControl {
// Keep track of packet statistics over time
stats: ConnectionStats,
}
impl ConnectionStatsControl {
pub(crate) fn handle_event(&mut self, event: ConnectionStatsEvent) {
match event {
ConnectionStatsEvent::TicketSpent { typ, amount } => match typ {
TicketType::V1MixnetEntry => self.stats.mixnet_entry_spent += amount,
TicketType::V1MixnetExit => self.stats.mixnet_exit_spent += amount,
TicketType::V1WireguardEntry => self.stats.vpn_entry_spent += amount,
TicketType::V1WireguardExit => self.stats.vpn_exit_spent += amount,
},
ConnectionStatsEvent::WgCountry(cc) => {
self.stats.wg_exit_country_code = cc;
}
ConnectionStatsEvent::MixCountry(cc) => {
self.stats.mix_exit_country_code = cc;
}
}
}
pub(crate) fn report(&self) -> ConnectionStats {
self.stats.clone()
}
}
-10
View File
@@ -16,8 +16,6 @@ pub mod nym_api_statistics;
/// Packet count based statistics.
pub mod packet_statistics;
pub mod connection;
/// Channel receiving generic stats events to be used by a statistics aggregator.
pub type ClientStatsReceiver = tokio::sync::mpsc::UnboundedReceiver<ClientStatsEvents>;
@@ -51,8 +49,6 @@ pub enum ClientStatsEvents {
GatewayConn(gateway_conn_statistics::GatewayStatsEvent),
/// Nym API connection events
NymApi(nym_api_statistics::NymApiStatsEvent),
/// Credential events
Connection(connection::ConnectionStatsEvent),
}
/// Controls stats event handling and reporting
@@ -67,7 +63,6 @@ pub struct ClientStatsController {
packet_stats: packet_statistics::PacketStatisticsControl,
gateway_conn_stats: gateway_conn_statistics::GatewayStatsControl,
nym_api_stats: nym_api_statistics::NymApiStatsControl,
connection_stats: connection::ConnectionStatsControl,
}
impl ClientStatsController {
@@ -81,7 +76,6 @@ impl ClientStatsController {
packet_stats: Default::default(),
gateway_conn_stats: Default::default(),
nym_api_stats: Default::default(),
connection_stats: Default::default(),
}
}
/// Returns a static ClientStatsReport that can be sent somewhere
@@ -94,8 +88,6 @@ impl ClientStatsController {
packet_stats: self.packet_stats.report(),
gateway_conn_stats: self.gateway_conn_stats.report(),
nym_api_stats: self.nym_api_stats.report(),
connection_stats: self.connection_stats.report(),
..Default::default()
}
}
@@ -105,7 +97,6 @@ impl ClientStatsController {
ClientStatsEvents::PacketStatistics(event) => self.packet_stats.handle_event(event),
ClientStatsEvents::GatewayConn(event) => self.gateway_conn_stats.handle_event(event),
ClientStatsEvents::NymApi(event) => self.nym_api_stats.handle_event(event),
ClientStatsEvents::Connection(event) => self.connection_stats.handle_event(event),
}
}
@@ -115,7 +106,6 @@ impl ClientStatsController {
pub fn reset(&mut self) {
self.nym_api_stats = Default::default();
self.gateway_conn_stats = Default::default();
self.connection_stats = Default::default();
//no periodic reset for packet stats
self.last_update_time = ClientStatsController::get_update_time();
-17
View File
@@ -11,9 +11,6 @@
#![warn(clippy::todo)]
#![warn(clippy::dbg_macro)]
use nym_crypto::asymmetric::ed25519;
use sha2::Digest;
/// Client specific statistics interfaces and events.
pub mod clients;
/// Statistics related errors.
@@ -22,17 +19,3 @@ pub mod error;
pub mod gateways;
/// Statistics reporting abstractions and implementations.
pub mod report;
const CLIENT_ID_PREFIX: &str = "client_stats_id";
pub fn generate_client_stats_id(id_key: ed25519::PublicKey) -> String {
generate_stats_id(CLIENT_ID_PREFIX, id_key.to_base58_string())
}
fn generate_stats_id<M: AsRef<[u8]>>(prefix: &str, id_seed: M) -> String {
let mut hasher = sha2::Sha256::new();
hasher.update(prefix);
hasher.update(&id_seed);
let output = hasher.finalize();
format!("{:x}", output)
}
+2 -25
View File
@@ -2,8 +2,8 @@
// SPDX-License-Identifier: Apache-2.0
use crate::clients::{
connection::ConnectionStats, gateway_conn_statistics::GatewayStats,
nym_api_statistics::NymApiStats, packet_statistics::PacketStatistics,
gateway_conn_statistics::GatewayStats, nym_api_statistics::NymApiStats,
packet_statistics::PacketStatistics,
};
use super::error::StatsError;
@@ -12,14 +12,9 @@ use serde::{Deserialize, Serialize};
use sysinfo::System;
use time::OffsetDateTime;
const KIND: &str = "client_stats_report";
const VERSION: &str = "v1";
/// Report object containing both data to be reported and client / device context. We take extra care not to overcapture context information.
#[derive(Clone, Debug, Serialize, Deserialize)]
pub struct ClientStatsReport {
pub(crate) kind: String,
pub(crate) api_version: String,
pub(crate) last_update_time: OffsetDateTime,
pub(crate) client_id: String,
pub(crate) client_type: String,
@@ -27,7 +22,6 @@ pub struct ClientStatsReport {
pub(crate) packet_stats: PacketStatistics,
pub(crate) gateway_conn_stats: GatewayStats,
pub(crate) nym_api_stats: NymApiStats,
pub(crate) connection_stats: ConnectionStats,
}
impl From<ClientStatsReport> for Vec<u8> {
@@ -46,23 +40,6 @@ impl TryFrom<&[u8]> for ClientStatsReport {
}
}
impl Default for ClientStatsReport {
fn default() -> Self {
ClientStatsReport {
kind: KIND.to_string(),
api_version: VERSION.to_string(),
last_update_time: OffsetDateTime::now_utc(),
client_id: Default::default(),
client_type: Default::default(),
os_information: Default::default(),
packet_stats: Default::default(),
gateway_conn_stats: Default::default(),
nym_api_stats: Default::default(),
connection_stats: Default::default(),
}
}
}
#[derive(Clone, Debug, Serialize, Deserialize)]
pub struct OsInformation {
pub(crate) os_type: String,
-26
View File
@@ -1,26 +0,0 @@
[package]
name = "nym-ticketbooks-merkle"
version = "0.1.0"
authors.workspace = true
repository.workspace = true
homepage.workspace = true
documentation.workspace = true
edition.workspace = true
license.workspace = true
rust-version.workspace = true
readme.workspace = true
[dependencies]
sha2 = { workspace = true }
rs_merkle = { workspace = true }
schemars = { workspace = true }
serde = { workspace = true, features = ["derive"] }
time = { workspace = true }
nym-credentials-interface = { path = "../credentials-interface" }
nym-serde-helpers = { path = "../serde-helpers", features = ["date", "base64", "hex"] }
[dev-dependencies]
rand_chacha = { workspace = true }
rand = { workspace = true }
serde_json = { workspace = true }
-366
View File
@@ -1,366 +0,0 @@
// Copyright 2024 - Nym Technologies SA <contact@nymtech.net>
// SPDX-License-Identifier: Apache-2.0
#![warn(clippy::expect_used)]
#![warn(clippy::unwrap_used)]
#![warn(clippy::todo)]
#![warn(clippy::dbg_macro)]
use nym_credentials_interface::TicketType;
use rs_merkle::algorithms::Sha256;
use rs_merkle::{MerkleProof, MerkleTree};
use schemars::JsonSchema;
use serde::{Deserialize, Serialize};
use sha2::Digest;
use std::fmt::{Debug, Formatter};
use time::Date;
// no point in importing the entire contract commons just for this one type
pub type DepositId = u32;
pub type DKGEpochId = u64;
#[derive(Clone, Serialize, Deserialize, Debug, PartialEq, JsonSchema)]
#[serde(rename_all = "camelCase")]
pub struct IssuedTicketbook {
pub deposit_id: DepositId,
pub epoch_id: DKGEpochId,
// 96 bytes serialised 'BlindedSignature'
#[schemars(with = "String")]
#[serde(with = "nym_serde_helpers::base64")]
pub blinded_partial_credential: Vec<u8>,
// concatenated bytes for the commitments to the private attributes
#[schemars(with = "String")]
#[serde(with = "nym_serde_helpers::base64")]
pub joined_encoded_private_attributes_commitments: Vec<u8>,
#[schemars(with = "String")]
#[serde(with = "nym_serde_helpers::date")]
pub expiration_date: Date,
#[schemars(with = "String")]
pub ticketbook_type: TicketType,
}
impl IssuedTicketbook {
pub fn hash_to_merkle_leaf(&self) -> [u8; 32] {
let mut hasher = sha2::Sha256::new();
hasher.update(self.deposit_id.to_be_bytes());
hasher.update(self.epoch_id.to_be_bytes());
hasher.update(&self.blinded_partial_credential);
hasher.update(&self.joined_encoded_private_attributes_commitments);
hasher.update(self.expiration_date.to_julian_day().to_be_bytes());
hasher.update(self.ticketbook_type.encode().to_be_bytes());
hasher.finalize().into()
}
pub fn signable_plaintext(&self) -> Vec<u8> {
self.deposit_id
.to_be_bytes()
.into_iter()
.chain(self.epoch_id.to_be_bytes())
.chain(self.blinded_partial_credential.iter().copied())
.chain(
self.joined_encoded_private_attributes_commitments
.iter()
.copied(),
)
.chain(self.expiration_date.to_julian_day().to_be_bytes())
.chain(self.ticketbook_type.encode().to_be_bytes())
.collect()
}
}
#[derive(Debug, Clone, Serialize, Deserialize)]
pub struct InsertedMerkleLeaf {
#[serde(with = "nym_serde_helpers::hex")]
pub new_root: Vec<u8>,
pub leaf: MerkleLeaf,
}
#[derive(Debug, Clone, Serialize, Deserialize, JsonSchema, PartialOrd, PartialEq, Eq)]
pub struct MerkleLeaf {
#[schemars(with = "String")]
#[serde(with = "nym_serde_helpers::hex")]
pub hash: Vec<u8>,
pub index: usize,
}
#[derive(Default, Clone)]
pub struct IssuedTicketbooksMerkleTree {
inner: MerkleTree<Sha256>,
}
impl IssuedTicketbooksMerkleTree {
pub fn new() -> IssuedTicketbooksMerkleTree {
IssuedTicketbooksMerkleTree {
inner: MerkleTree::new(),
}
}
pub fn rebuild(leaves: &[[u8; 32]]) -> IssuedTicketbooksMerkleTree {
IssuedTicketbooksMerkleTree {
inner: MerkleTree::from_leaves(leaves),
}
}
pub fn all_leaves(&self) -> Option<Vec<[u8; 32]>> {
self.inner.leaves()
}
pub fn insert(&mut self, issued: &IssuedTicketbook) -> InsertedMerkleLeaf {
let hash = issued.hash_to_merkle_leaf();
self.insert_leaf(hash)
}
#[allow(clippy::unwrap_used)]
pub fn insert_leaf(&mut self, leaf_hash: [u8; 32]) -> InsertedMerkleLeaf {
let leaves = self.inner.leaves_len();
self.inner.insert(leaf_hash).commit();
InsertedMerkleLeaf {
// SAFETY: after inserting at least a single node, the root will always be available
new_root: self.inner.root().unwrap().to_vec(),
leaf: MerkleLeaf {
hash: leaf_hash.to_vec(),
index: leaves,
},
}
}
pub fn rollback(&mut self) {
self.inner.rollback();
}
pub fn root(&self) -> Option<[u8; 32]> {
self.inner.root()
}
pub fn generate_proof(
&self,
leaf_indices: &[usize],
) -> Option<IssuedTicketbooksFullMerkleProof> {
let leaves = self.inner.leaves()?;
let mut included_leaves = Vec::new();
for &index in leaf_indices {
let hash = *leaves.get(index)?;
included_leaves.push(MerkleLeaf {
hash: hash.to_vec(),
index,
})
}
Some(IssuedTicketbooksFullMerkleProof {
inner_proof: self.inner.proof(leaf_indices),
included_leaves,
total_leaves: self.inner.leaves_len(),
root: self.inner.root()?.to_vec(),
})
}
}
#[derive(Serialize, Deserialize, JsonSchema)]
pub struct IssuedTicketbooksFullMerkleProof {
#[schemars(with = "String")]
#[serde(with = "inner_proof_base64_serde")]
inner_proof: MerkleProof<Sha256>,
included_leaves: Vec<MerkleLeaf>,
total_leaves: usize,
#[schemars(with = "String")]
#[serde(with = "nym_serde_helpers::hex")]
root: Vec<u8>,
}
impl Debug for IssuedTicketbooksFullMerkleProof {
fn fmt(&self, f: &mut Formatter<'_>) -> std::fmt::Result {
f.debug_struct("IssuedTicketbooksFullMerkleProof")
.field("inner_proof", &self.inner_proof.proof_hashes_hex())
.field("included_leaves", &self.included_leaves)
.field("total_leaves", &self.total_leaves)
.field("root", &self.root)
.finish()
}
}
impl Clone for IssuedTicketbooksFullMerkleProof {
fn clone(&self) -> Self {
IssuedTicketbooksFullMerkleProof {
inner_proof: MerkleProof::new(self.inner_proof.proof_hashes().to_vec()),
included_leaves: self.included_leaves.clone(),
total_leaves: self.total_leaves,
root: self.root.clone(),
}
}
}
impl IssuedTicketbooksFullMerkleProof {
pub fn contains_leaf_hash(&self, hash: [u8; 32]) -> bool {
self.included_leaves.iter().any(|m| m.hash == hash)
}
pub fn contains_full_leaf(&self, leaf: &MerkleLeaf) -> bool {
self.included_leaves.iter().any(|m| m == leaf)
}
pub fn total_leaves(&self) -> usize {
self.total_leaves
}
pub fn verify(&self, expected_root: [u8; 32]) -> bool {
if self.root != expected_root {
return false;
}
let mut leaf_indices = Vec::with_capacity(self.included_leaves.len());
let mut leaf_hashes = Vec::with_capacity(self.included_leaves.len());
for leaf in &self.included_leaves {
leaf_indices.push(leaf.index);
let Ok(sha256_hash) = leaf.hash.clone().try_into() else {
return false;
};
leaf_hashes.push(sha256_hash);
}
self.inner_proof.verify(
expected_root,
&leaf_indices,
&leaf_hashes,
self.total_leaves,
)
}
}
mod inner_proof_base64_serde {
use rs_merkle::algorithms::Sha256;
use rs_merkle::proof_serializers::DirectHashesOrder;
use rs_merkle::MerkleProof;
use serde::{Deserializer, Serializer};
pub fn serialize<S: Serializer>(
proof: &MerkleProof<Sha256>,
serializer: S,
) -> Result<S::Ok, S::Error> {
let bytes = proof.serialize::<DirectHashesOrder>();
nym_serde_helpers::base64::serialize(&bytes, serializer)
}
pub fn deserialize<'de, D: Deserializer<'de>>(
deserializer: D,
) -> Result<MerkleProof<Sha256>, D::Error> {
let bytes = nym_serde_helpers::base64::deserialize(deserializer)?;
MerkleProof::<Sha256>::deserialize::<DirectHashesOrder>(&bytes)
.map_err(serde::de::Error::custom)
}
}
#[cfg(test)]
mod tests {
use super::*;
use nym_credentials_interface::ecash_today;
use rand::{RngCore, SeedableRng};
fn test_rng() -> rand_chacha::ChaChaRng {
let dummy_seed = [42u8; 32];
rand_chacha::ChaCha20Rng::from_seed(dummy_seed)
}
fn dummy_issued(rng: &mut rand_chacha::ChaCha20Rng) -> IssuedTicketbook {
let mut blinded_partial_credential = vec![0u8; 42];
rng.fill_bytes(&mut blinded_partial_credential);
let mut joined_encoded_private_attributes_commitments = vec![0u8; 48 * 3];
rng.fill_bytes(&mut joined_encoded_private_attributes_commitments);
IssuedTicketbook {
deposit_id: rng.next_u32(),
epoch_id: rng.next_u64(),
blinded_partial_credential,
joined_encoded_private_attributes_commitments,
expiration_date: ecash_today().date(),
ticketbook_type: TicketType::V1MixnetEntry,
}
}
#[test]
fn single_leaf() {
let mut rng = test_rng();
let issued = dummy_issued(&mut rng);
let expected_hash = issued.hash_to_merkle_leaf();
let mut tree = IssuedTicketbooksMerkleTree::new();
let inserted_node = tree.insert(&issued);
assert_eq!(inserted_node.leaf.index, 0);
assert_eq!(inserted_node.leaf.hash, expected_hash);
assert_eq!(inserted_node.new_root, expected_hash);
let proof = tree.generate_proof(&[0]).unwrap();
assert!(proof.verify(expected_hash));
assert_eq!(proof.total_leaves, 1);
assert_eq!(proof.included_leaves, vec![inserted_node.leaf]);
assert_eq!(proof.root, expected_hash);
}
#[test]
fn multiple_leaves() {
let mut rng = test_rng();
let mut tree = IssuedTicketbooksMerkleTree::new();
for i in 0..100 {
let issued = dummy_issued(&mut rng);
let expected_hash = issued.hash_to_merkle_leaf();
let inserted_node = tree.insert(&issued);
assert_eq!(inserted_node.leaf.index, i);
assert_eq!(inserted_node.leaf.hash, expected_hash);
// proof for this single node
let proof = tree.generate_proof(&[i]).unwrap();
assert!(proof.verify(tree.root().unwrap()));
assert_eq!(proof.total_leaves, i + 1);
assert!(proof.contains_leaf_hash(expected_hash));
}
// proof for multiple nodes
let indices = [0, 5, 42, 69, 74, 99];
let all_leaves = tree.inner.leaves().unwrap();
let big_proof = tree.generate_proof(&indices).unwrap();
for &index in &indices {
let leaf_hash = all_leaves.get(index).unwrap();
assert!(big_proof.contains_leaf_hash(*leaf_hash));
}
assert!(big_proof.verify(tree.root().unwrap()))
}
#[test]
fn merkle_proof_serialisation_roundtrip() {
let mut rng = test_rng();
let mut tree = IssuedTicketbooksMerkleTree::new();
for _ in 0..100 {
let issued = dummy_issued(&mut rng);
tree.insert(&issued);
}
let indices = [0, 5, 42, 69, 74, 99];
let big_proof = tree.generate_proof(&indices).unwrap();
let bytes = serde_json::to_vec(&big_proof).unwrap();
let recovered: IssuedTicketbooksFullMerkleProof = serde_json::from_slice(&bytes).unwrap();
assert_eq!(
big_proof.inner_proof.proof_hashes(),
recovered.inner_proof.proof_hashes()
);
assert_eq!(big_proof.included_leaves, recovered.included_leaves);
assert_eq!(big_proof.total_leaves, recovered.total_leaves);
assert_eq!(big_proof.root, recovered.root);
}
}
+1 -9
View File
@@ -3,7 +3,7 @@ use crate::deprecated::DelegationEvent;
use crate::error::TypesError;
use crate::mixnode::NodeCostParams;
use cosmwasm_std::Decimal;
use nym_mixnet_contract_common::{Delegation as MixnetContractDelegation, NodeId, NodeRewarding};
use nym_mixnet_contract_common::{Delegation as MixnetContractDelegation, NodeId};
use schemars::JsonSchema;
use serde::{Deserialize, Serialize};
@@ -70,14 +70,6 @@ pub struct DelegationWithEverything {
pub mixnode_is_unbonding: Option<bool>,
}
pub struct NodeInformation {
pub owner: String,
pub mix_id: NodeId,
pub node_identity: String,
pub rewarding_details: NodeRewarding,
pub is_unbonding: bool,
}
#[cfg_attr(feature = "generate-ts", derive(ts_rs::TS))]
#[cfg_attr(
feature = "generate-ts",
-1
View File
@@ -30,7 +30,6 @@ nym-crypto = { path = "../../crypto", features = ["asymmetric", "serde"] }
nym-gateway-client = { path = "../../client-libs/gateway-client", default-features = false, features = ["wasm"] }
nym-sphinx = { path = "../../nymsphinx" }
nym-sphinx-acknowledgements = { path = "../../nymsphinx/acknowledgements", features = ["serde"]}
nym-statistics-common = { path = "../../statistics" }
nym-task = { path = "../../task" }
nym-topology = { path = "../../topology", features = ["serializable", "wasm-serde-types"] }
nym-validator-client = { path = "../../client-libs/validator-client", default-features = false }
-11
View File
@@ -162,13 +162,6 @@ pub struct TrafficWasm {
/// a loop cover message is sent instead in order to preserve the rate.
pub message_sending_average_delay_ms: u32,
/// Specify how many times particular packet can be retransmitted
/// None - no limit
pub maximum_number_of_retransmissions: Option<u32>,
/// Specify whether route selection should be determined by the packet header.
pub deterministic_route_selection: bool,
/// Controls whether the main packet stream constantly produces packets according to the predefined
/// poisson distribution.
pub disable_main_poisson_packet_distribution: bool,
@@ -203,8 +196,6 @@ impl From<TrafficWasm> for ConfigTraffic {
message_sending_average_delay: Duration::from_millis(
traffic.message_sending_average_delay_ms as u64,
),
deterministic_route_selection: traffic.deterministic_route_selection,
maximum_number_of_retransmissions: traffic.maximum_number_of_retransmissions,
disable_main_poisson_packet_distribution: traffic
.disable_main_poisson_packet_distribution,
primary_packet_size: PacketSize::RegularPacket,
@@ -220,8 +211,6 @@ impl From<ConfigTraffic> for TrafficWasm {
average_packet_delay_ms: traffic.average_packet_delay.as_millis() as u32,
message_sending_average_delay_ms: traffic.message_sending_average_delay.as_millis()
as u32,
deterministic_route_selection: traffic.deterministic_route_selection,
maximum_number_of_retransmissions: traffic.maximum_number_of_retransmissions,
disable_main_poisson_packet_distribution: traffic
.disable_main_poisson_packet_distribution,
use_extended_packet_size: traffic.secondary_packet_size.is_some(),
@@ -88,14 +88,6 @@ pub struct TrafficWasmOverride {
#[tsify(optional)]
pub message_sending_average_delay_ms: Option<u32>,
/// Specify how many times particular packet can be retransmitted
#[tsify(optional)]
pub maximum_number_of_retransmissions: Option<u32>,
/// Specify whether route selection should be determined by the packet header.
#[tsify(optional)]
pub deterministic_route_selection: Option<bool>,
/// Controls whether the main packet stream constantly produces packets according to the predefined
/// poisson distribution.
#[tsify(optional)]
@@ -121,10 +113,6 @@ impl From<TrafficWasmOverride> for TrafficWasm {
message_sending_average_delay_ms: value
.message_sending_average_delay_ms
.unwrap_or(def.message_sending_average_delay_ms),
maximum_number_of_retransmissions: value.maximum_number_of_retransmissions,
deterministic_route_selection: value
.deterministic_route_selection
.unwrap_or(def.deterministic_route_selection),
disable_main_poisson_packet_distribution: value
.disable_main_poisson_packet_distribution
.unwrap_or(def.disable_main_poisson_packet_distribution),
-1
View File
@@ -26,7 +26,6 @@ pub use nym_sphinx::{
params::PacketType,
receiver::ReconstructedMessage,
};
pub use nym_statistics_common::clients::ClientStatsSender;
pub use nym_task;
pub use nym_topology::{HardcodedTopologyProvider, MixLayer, NymTopology, TopologyProvider};
pub use nym_validator_client::nym_api::Client as ApiClient;
+3
View File
@@ -23,6 +23,9 @@ futures = { workspace = true }
x25519-dalek = { workspace = true }
ip_network = { workspace = true }
log.workspace = true
serde = { workspace = true, features = [
"derive",
] } # for config serialization/deserialization
thiserror = { workspace = true }
tokio = { workspace = true, features = ["rt-multi-thread", "net", "io-util"] }
tokio-stream = { workspace = true }
+27
View File
@@ -0,0 +1,27 @@
// Copyright 2024 - Nym Technologies SA <contact@nymtech.net>
// SPDX-License-Identifier: Apache-2.0
use defguard_wireguard_rs::{host::Peer, key::Key};
use serde::{Deserialize, Serialize};
#[derive(Default, Clone, Serialize, Deserialize)]
pub struct Hosts {
host_v4: defguard_wireguard_rs::host::Host,
host_v6: defguard_wireguard_rs::host::Host,
}
impl Hosts {
pub fn new(
host_v4: defguard_wireguard_rs::host::Host,
host_v6: defguard_wireguard_rs::host::Host,
) -> Self {
Self { host_v4, host_v6 }
}
pub fn get(&self, key: &Key) -> Option<&Peer> {
self.host_v4
.peers
.get(key)
.or_else(|| self.host_v6.peers.get(key))
}
}
+63 -38
View File
@@ -6,34 +6,44 @@
// #![warn(clippy::expect_used)]
// #![warn(clippy::unwrap_used)]
use defguard_wireguard_rs::WGApi;
#[cfg(target_os = "linux")]
use defguard_wireguard_rs::{host::Peer, key::Key, net::IpAddrMask};
use defguard_wireguard_rs::{WGApi, WireguardInterfaceApi};
use hosts::Hosts;
use nym_crypto::asymmetric::encryption::KeyPair;
#[cfg(target_os = "linux")]
use nym_network_defaults::constants::WG_TUN_BASE_NAME;
use nym_network_defaults::constants::{WG_TUN_BASE_NAME_V4, WG_TUN_BASE_NAME_V6};
use nym_wireguard_types::Config;
use peer_controller::PeerControlRequest;
use std::sync::Arc;
use tokio::sync::mpsc::{self, Receiver, Sender};
pub(crate) mod error;
pub mod hosts;
pub mod peer_controller;
pub mod peer_handle;
pub struct WgApiWrapper {
inner: WGApi,
api_v4: WGApi,
api_v6: WGApi,
}
impl WgApiWrapper {
pub fn new(wg_api: WGApi) -> Self {
WgApiWrapper { inner: wg_api }
pub fn new(api_v4: WGApi, api_v6: WGApi) -> Self {
WgApiWrapper { api_v4, api_v6 }
}
pub fn get_hosts(&self) -> Result<Hosts, Box<dyn std::error::Error + Send + Sync + 'static>> {
let host_v4 = self.api_v4.read_interface_data()?;
let host_v6 = self.api_v6.read_interface_data()?;
let hosts = Hosts::new(host_v4, host_v6);
Ok(hosts)
}
}
impl Drop for WgApiWrapper {
fn drop(&mut self) {
if let Err(e) = defguard_wireguard_rs::WireguardInterfaceApi::remove_interface(&self.inner)
if let Err(e) = defguard_wireguard_rs::WireguardInterfaceApi::remove_interface(&self.api_v4)
{
log::error!("Could not remove the wireguard interface: {:?}", e);
}
@@ -93,9 +103,13 @@ pub async fn start_wireguard<St: nym_gateway_storage::Storage + Clone + 'static>
use std::collections::HashMap;
use tokio::sync::RwLock;
let ifname = String::from(WG_TUN_BASE_NAME);
let wg_api = defguard_wireguard_rs::WGApi::new(ifname.clone(), false)?;
let ifname_v4 = String::from(WG_TUN_BASE_NAME_V4);
let ifname_v6 = String::from(WG_TUN_BASE_NAME_V6);
let wg_api_v4 = defguard_wireguard_rs::WGApi::new(ifname_v4.clone(), false)?;
let wg_api_v6 = defguard_wireguard_rs::WGApi::new(ifname_v6.clone(), false)?;
let mut peer_bandwidth_managers = HashMap::with_capacity(all_peers.len());
let mut peers_v4 = vec![];
let mut peers_v6 = vec![];
let peers = all_peers
.into_iter()
.map(Peer::try_from)
@@ -108,7 +122,10 @@ pub async fn start_wireguard<St: nym_gateway_storage::Storage + Clone + 'static>
peer
})
.collect::<Vec<_>>();
for peer in peers.iter() {
for peer in peers.into_iter() {
let Some(ip_mask) = peer.allowed_ips.first() else {
continue;
};
let bandwidth_manager =
PeerController::generate_bandwidth_manager(storage.clone(), &peer.public_key)
.await?
@@ -116,34 +133,35 @@ pub async fn start_wireguard<St: nym_gateway_storage::Storage + Clone + 'static>
// Update storage with *x_bytes set to 0, as in kernel peers we can't set those values
// so we need to restart counting. Hopefully the bandwidth was counted in available_bandwidth
storage
.insert_wireguard_peer(peer, bandwidth_manager.is_some())
.insert_wireguard_peer(&peer, bandwidth_manager.is_some())
.await?;
peer_bandwidth_managers.insert(peer.public_key.clone(), bandwidth_manager);
if ip_mask.ip.is_ipv4() {
peers_v4.push(peer);
} else {
peers_v6.push(peer);
}
}
wg_api.create_interface()?;
let interface_config = InterfaceConfiguration {
name: ifname.clone(),
wg_api_v4.create_interface()?;
wg_api_v6.create_interface()?;
wg_api_v4.configure_interface(&InterfaceConfiguration {
name: ifname_v4.clone(),
prvkey: BASE64_STANDARD.encode(wireguard_data.inner.keypair().private_key().to_bytes()),
address: wireguard_data.inner.config().private_ipv4.to_string(),
port: wireguard_data.inner.config().announced_port as u32,
peers,
peers: peers_v4,
mtu: None,
};
wg_api.configure_interface(&interface_config)?;
std::process::Command::new("ip")
.args([
"-6",
"addr",
"add",
&format!(
"{}/{}",
wireguard_data.inner.config().private_ipv6,
wireguard_data.inner.config().private_network_prefix_v6
),
"dev",
(&ifname),
])
.output()?;
})?;
wg_api_v6.configure_interface(&InterfaceConfiguration {
name: ifname_v6.clone(),
prvkey: BASE64_STANDARD.encode(wireguard_data.inner.keypair().private_key().to_bytes()),
address: wireguard_data.inner.config().private_ipv6.to_string(),
port: wireguard_data.inner.config().announced_port as u32,
peers: peers_v6,
mtu: None,
})?;
// Use a dummy peer to create routing rule for the entire network space
let mut catch_all_peer = Peer::new(Key::new([0; 32]));
@@ -155,18 +173,25 @@ pub async fn start_wireguard<St: nym_gateway_storage::Storage + Clone + 'static>
wireguard_data.inner.config().private_ipv6,
wireguard_data.inner.config().private_network_prefix_v6,
)?;
catch_all_peer.set_allowed_ips(vec![
IpAddrMask::new(network_v4.network_address(), network_v4.netmask()),
IpAddrMask::new(network_v6.network_address(), network_v6.netmask()),
]);
wg_api.configure_peer_routing(&[catch_all_peer])?;
let host = wg_api.read_interface_data()?;
let wg_api = std::sync::Arc::new(WgApiWrapper::new(wg_api));
catch_all_peer.set_allowed_ips(vec![IpAddrMask::new(
network_v4.network_address(),
network_v4.netmask(),
)]);
wg_api_v4.configure_peer_routing(&[catch_all_peer.clone()])?;
catch_all_peer.set_allowed_ips(vec![IpAddrMask::new(
network_v6.network_address(),
network_v6.netmask(),
)]);
wg_api_v6.configure_peer_routing(&[catch_all_peer])?;
let wg_api = std::sync::Arc::new(WgApiWrapper::new(wg_api_v4, wg_api_v6));
let hosts = wg_api.get_hosts()?;
let mut controller = PeerController::new(
storage,
wg_api.clone(),
host,
hosts,
peer_bandwidth_managers,
wireguard_data.inner.peer_tx.clone(),
wireguard_data.peer_rx,
+16 -23
View File
@@ -1,14 +1,10 @@
// Copyright 2024 - Nym Technologies SA <contact@nymtech.net>
// SPDX-License-Identifier: Apache-2.0
use defguard_wireguard_rs::{
host::{Host, Peer},
key::Key,
WireguardInterfaceApi,
};
use defguard_wireguard_rs::{host::Peer, key::Key, WireguardInterfaceApi};
use futures::channel::oneshot;
use nym_authenticator_requests::latest::registration::{
RemainingBandwidthData, BANDWIDTH_CAP_PER_DAY,
use nym_authenticator_requests::{
latest::registration::RemainingBandwidthData, v1::registration::BANDWIDTH_CAP_PER_DAY,
};
use nym_credential_verification::{
bandwidth_storage_manager::BandwidthStorageManager, BandwidthFlushingBehaviourConfig,
@@ -20,6 +16,7 @@ use std::{collections::HashMap, sync::Arc};
use tokio::sync::{mpsc, RwLock};
use tokio_stream::{wrappers::IntervalStream, StreamExt};
use crate::hosts::Hosts;
use crate::peer_handle::PeerHandle;
use crate::WgApiWrapper;
use crate::{error::Error, peer_handle::SharedBandwidthStorageManager};
@@ -68,7 +65,7 @@ pub struct PeerController<St: Storage + Clone + 'static> {
request_tx: mpsc::Sender<PeerControlRequest>,
request_rx: mpsc::Receiver<PeerControlRequest>,
wg_api: Arc<WgApiWrapper>,
host_information: Arc<RwLock<Host>>,
hosts_information: Arc<RwLock<Hosts>>,
bw_storage_managers: HashMap<Key, Option<SharedBandwidthStorageManager<St>>>,
timeout_check_interval: IntervalStream,
task_client: nym_task::TaskClient,
@@ -78,7 +75,7 @@ impl<St: Storage + Clone + 'static> PeerController<St> {
pub fn new(
storage: St,
wg_api: Arc<WgApiWrapper>,
initial_host_information: Host,
initial_hosts_information: Hosts,
bw_storage_managers: HashMap<Key, Option<SharedBandwidthStorageManager<St>>>,
request_tx: mpsc::Sender<PeerControlRequest>,
request_rx: mpsc::Receiver<PeerControlRequest>,
@@ -87,12 +84,12 @@ impl<St: Storage + Clone + 'static> PeerController<St> {
let timeout_check_interval = tokio_stream::wrappers::IntervalStream::new(
tokio::time::interval(DEFAULT_PEER_TIMEOUT_CHECK),
);
let host_information = Arc::new(RwLock::new(initial_host_information));
let hosts_information = Arc::new(RwLock::new(initial_hosts_information));
for (public_key, bandwidth_storage_manager) in bw_storage_managers.iter() {
let mut handle = PeerHandle::new(
storage.clone(),
public_key.clone(),
host_information.clone(),
hosts_information.clone(),
bandwidth_storage_manager.clone(),
request_tx.clone(),
&task_client,
@@ -107,7 +104,7 @@ impl<St: Storage + Clone + 'static> PeerController<St> {
PeerController {
storage,
wg_api,
host_information,
hosts_information,
bw_storage_managers,
request_tx,
request_rx,
@@ -122,7 +119,7 @@ impl<St: Storage + Clone + 'static> PeerController<St> {
self.storage.insert_wireguard_peer(peer, false).await?;
}
let ret: Result<(), defguard_wireguard_rs::error::WireguardInterfaceError> =
self.wg_api.inner.configure_peer(peer);
self.wg_api.api_v4.configure_peer(peer);
if client_id.is_none() && ret.is_err() {
// Try to revert the insertion in storage
if self
@@ -141,7 +138,7 @@ impl<St: Storage + Clone + 'static> PeerController<St> {
pub async fn remove_peer(&mut self, key: &Key) -> Result<(), Error> {
self.storage.remove_wireguard_peer(&key.to_string()).await?;
self.bw_storage_managers.remove(key);
let ret = self.wg_api.inner.remove_peer(key);
let ret = self.wg_api.api_v4.remove_peer(key);
if ret.is_err() {
log::error!("Wireguard peer could not be removed from wireguard kernel module. Process should be restarted so that the interface is reset.");
}
@@ -187,17 +184,13 @@ impl<St: Storage + Clone + 'static> PeerController<St> {
let mut handle = PeerHandle::new(
self.storage.clone(),
peer.public_key.clone(),
self.host_information.clone(),
self.hosts_information.clone(),
bandwidth_storage_manager.clone(),
self.request_tx.clone(),
&self.task_client,
);
self.bw_storage_managers
.insert(peer.public_key.clone(), bandwidth_storage_manager);
// try to immediately update the host information, to eliminate races
if let Ok(host_information) = self.wg_api.inner.read_interface_data() {
*self.host_information.write().await = host_information;
}
tokio::spawn(async move {
if let Err(e) = handle.run().await {
log::error!("Peer handle shut down ungracefully - {e}");
@@ -230,11 +223,11 @@ impl<St: Storage + Clone + 'static> PeerController<St> {
.available_bandwidth()
.await
} else {
let Some(peer) = self.host_information.read().await.peers.get(key).cloned() else {
let Some(peer) = self.hosts_information.read().await.get(key).cloned() else {
// host information not updated yet
return Ok(None);
};
BANDWIDTH_CAP_PER_DAY.saturating_sub(peer.rx_bytes + peer.tx_bytes) as i64
BANDWIDTH_CAP_PER_DAY.saturating_sub((peer.rx_bytes + peer.tx_bytes) as i64)
};
Ok(Some(RemainingBandwidthData {
@@ -246,11 +239,11 @@ impl<St: Storage + Clone + 'static> PeerController<St> {
loop {
tokio::select! {
_ = self.timeout_check_interval.next() => {
let Ok(host) = self.wg_api.inner.read_interface_data() else {
let Ok(hosts) = self.wg_api.get_hosts() else {
log::error!("Can't read wireguard kernel data");
continue;
};
*self.host_information.write().await = host;
*self.hosts_information.write().await = hosts;
}
_ = self.task_client.recv() => {
log::trace!("PeerController handler: Received shutdown");
+9 -9
View File
@@ -2,11 +2,12 @@
// SPDX-License-Identifier: Apache-2.0
use crate::error::Error;
use crate::hosts::Hosts;
use crate::peer_controller::PeerControlRequest;
use defguard_wireguard_rs::host::Peer;
use defguard_wireguard_rs::{host::Host, key::Key};
use defguard_wireguard_rs::key::Key;
use futures::channel::oneshot;
use nym_authenticator_requests::latest::registration::BANDWIDTH_CAP_PER_DAY;
use nym_authenticator_requests::v2::registration::BANDWIDTH_CAP_PER_DAY;
use nym_credential_verification::bandwidth_storage_manager::BandwidthStorageManager;
use nym_gateway_storage::models::WireguardPeer;
use nym_gateway_storage::Storage;
@@ -18,12 +19,12 @@ use tokio::sync::{mpsc, RwLock};
use tokio_stream::{wrappers::IntervalStream, StreamExt};
pub(crate) type SharedBandwidthStorageManager<St> = Arc<RwLock<BandwidthStorageManager<St>>>;
const AUTO_REMOVE_AFTER: Duration = Duration::from_secs(60 * 60 * 24 * 30); // 30 days
const AUTO_REMOVE_AFTER: Duration = Duration::from_secs(60 * 60 * 24); // 24 hours
pub struct PeerHandle<St> {
storage: St,
public_key: Key,
host_information: Arc<RwLock<Host>>,
hosts_information: Arc<RwLock<Hosts>>,
bandwidth_storage_manager: Option<SharedBandwidthStorageManager<St>>,
request_tx: mpsc::Sender<PeerControlRequest>,
timeout_check_interval: IntervalStream,
@@ -35,7 +36,7 @@ impl<St: Storage + Clone + 'static> PeerHandle<St> {
pub fn new(
storage: St,
public_key: Key,
host_information: Arc<RwLock<Host>>,
hosts_information: Arc<RwLock<Hosts>>,
bandwidth_storage_manager: Option<SharedBandwidthStorageManager<St>>,
request_tx: mpsc::Sender<PeerControlRequest>,
task_client: &TaskClient,
@@ -48,7 +49,7 @@ impl<St: Storage + Clone + 'static> PeerHandle<St> {
PeerHandle {
storage,
public_key,
host_information,
hosts_information,
bandwidth_storage_manager,
request_tx,
timeout_check_interval,
@@ -98,7 +99,7 @@ impl<St: Storage + Clone + 'static> PeerHandle<St> {
} else {
if SystemTime::now().duration_since(self.startup_timestamp)? >= AUTO_REMOVE_AFTER {
log::debug!(
"Peer {} has been present for 30 days, removing it",
"Peer {} has been present for 24 hours, removing it",
self.public_key.to_string()
);
let success = self.remove_peer().await?;
@@ -123,10 +124,9 @@ impl<St: Storage + Clone + 'static> PeerHandle<St> {
tokio::select! {
_ = self.timeout_check_interval.next() => {
let Some(kernel_peer) = self
.host_information
.hosts_information
.read()
.await
.peers
.get(&self.public_key)
.cloned() else {
// the host information hasn't beed updated yet
+9 -15
View File
@@ -1219,7 +1219,6 @@ dependencies = [
name = "nym-ecash"
version = "0.1.0"
dependencies = [
"anyhow",
"bs58 0.4.0",
"cosmwasm-schema",
"cosmwasm-std",
@@ -1287,7 +1286,6 @@ dependencies = [
"nym-vesting-contract-common",
"rand",
"rand_chacha",
"semver",
"serde",
"thiserror",
"time",
@@ -1304,9 +1302,9 @@ dependencies = [
"cw-storage-plus",
"cw2",
"humantime-serde",
"log",
"nym-contracts-common",
"schemars",
"semver",
"serde",
"serde-json-wasm",
"serde_repr",
@@ -1332,10 +1330,6 @@ dependencies = [
[[package]]
name = "nym-network-defaults"
version = "0.1.0"
dependencies = [
"cargo_metadata",
"regex",
]
[[package]]
name = "nym-pemstore"
@@ -1576,9 +1570,9 @@ dependencies = [
[[package]]
name = "regex"
version = "1.11.1"
version = "1.10.4"
source = "registry+https://github.com/rust-lang/crates.io-index"
checksum = "b544ef1b4eac5dc2db33ea63606ae9ffcfac26c1416a2806ae0bf5f56b201191"
checksum = "c117dbdfde9c8308975b6a18d71f3f385c89461f7b3fb054288ecf2a2058ba4c"
dependencies = [
"aho-corasick",
"memchr",
@@ -1588,9 +1582,9 @@ dependencies = [
[[package]]
name = "regex-automata"
version = "0.4.9"
version = "0.4.6"
source = "registry+https://github.com/rust-lang/crates.io-index"
checksum = "809e8dc61f6de73b46c85f4c96486310fe304c434cfa43669d7b40f711150908"
checksum = "86b83b8b9847f9bf95ef68afb0b8e6cdb80f498442f5179a29fad448fcc1eaea"
dependencies = [
"aho-corasick",
"memchr",
@@ -1599,9 +1593,9 @@ dependencies = [
[[package]]
name = "regex-syntax"
version = "0.8.5"
version = "0.8.3"
source = "registry+https://github.com/rust-lang/crates.io-index"
checksum = "2b15c43186be67a4fd63bee50d0303afffcef381492ebe2c5d87f324e1b8815c"
checksum = "adad44e29e4c806119491a7f06f03de4d1af22c3a680dd47f1e6e179439d1f56"
[[package]]
name = "rfc6979"
@@ -1699,9 +1693,9 @@ dependencies = [
[[package]]
name = "semver"
version = "1.0.23"
version = "1.0.22"
source = "registry+https://github.com/rust-lang/crates.io-index"
checksum = "61697e0a1c7e512e84a621326239844a24d8207b4669b41bc18b32ea5cbf988b"
checksum = "92d43fe69e652f3df9bdc2b85b2854a0825b86e4fb76bc44d945137d053639ca"
dependencies = [
"serde",
]
-1
View File
@@ -36,7 +36,6 @@ nym-multisig-contract-common = { path = "../../common/cosmwasm-smart-contracts/m
nym-network-defaults = { path = "../../common/network-defaults", default-features = false }
[dev-dependencies]
anyhow = { workspace = true }
sylvia = { workspace = true, features = ["mt"] }
nym-crypto = { path = "../../common/crypto", features = ["rand", "asymmetric"] }
rand_chacha = "0.3"
-63
View File
@@ -328,19 +328,6 @@
},
"additionalProperties": false
},
{
"type": "object",
"required": [
"get_latest_deposit"
],
"properties": {
"get_latest_deposit": {
"type": "object",
"additionalProperties": false
}
},
"additionalProperties": false
},
{
"type": "object",
"required": [
@@ -592,56 +579,6 @@
}
}
},
"get_latest_deposit": {
"$schema": "http://json-schema.org/draft-07/schema#",
"title": "LatestDepositResponse",
"type": "object",
"properties": {
"deposit": {
"anyOf": [
{
"$ref": "#/definitions/DepositData"
},
{
"type": "null"
}
]
}
},
"additionalProperties": false,
"definitions": {
"Deposit": {
"type": "object",
"required": [
"bs58_encoded_ed25519_pubkey"
],
"properties": {
"bs58_encoded_ed25519_pubkey": {
"type": "string"
}
},
"additionalProperties": false
},
"DepositData": {
"type": "object",
"required": [
"deposit",
"id"
],
"properties": {
"deposit": {
"$ref": "#/definitions/Deposit"
},
"id": {
"type": "integer",
"format": "uint32",
"minimum": 0.0
}
},
"additionalProperties": false
}
}
},
"get_required_deposit_amount": {
"$schema": "http://json-schema.org/draft-07/schema#",
"title": "Coin",
-13
View File
@@ -88,19 +88,6 @@
},
"additionalProperties": false
},
{
"type": "object",
"required": [
"get_latest_deposit"
],
"properties": {
"get_latest_deposit": {
"type": "object",
"additionalProperties": false
}
},
"additionalProperties": false
},
{
"type": "object",
"required": [
@@ -1,50 +0,0 @@
{
"$schema": "http://json-schema.org/draft-07/schema#",
"title": "LatestDepositResponse",
"type": "object",
"properties": {
"deposit": {
"anyOf": [
{
"$ref": "#/definitions/DepositData"
},
{
"type": "null"
}
]
}
},
"additionalProperties": false,
"definitions": {
"Deposit": {
"type": "object",
"required": [
"bs58_encoded_ed25519_pubkey"
],
"properties": {
"bs58_encoded_ed25519_pubkey": {
"type": "string"
}
},
"additionalProperties": false
},
"DepositData": {
"type": "object",
"required": [
"deposit",
"id"
],
"properties": {
"deposit": {
"$ref": "#/definitions/Deposit"
},
"id": {
"type": "integer",
"format": "uint32",
"minimum": 0.0
}
},
"additionalProperties": false
}
}
}
+2 -195
View File
@@ -2,11 +2,9 @@
// SPDX-License-Identifier: Apache-2.0
use crate::contract::NymEcashContract;
use crate::helpers::{
create_batch_redemption_proposal, create_blacklist_proposal, Config, ProposalId,
};
use crate::helpers::{create_batch_redemption_proposal, create_blacklist_proposal, ProposalId};
use cosmwasm_schema::cw_serde;
use cosmwasm_std::{to_binary, Addr, Coin, Decimal, Deps, Storage, SubMsg, Uint128};
use cosmwasm_std::{to_binary, Addr, Deps, Storage, SubMsg};
use cw3::ProposalResponse;
use nym_ecash_contract_common::EcashContractError;
use nym_multisig_contract_common::msg::QueryMsg as MultisigQueryMsg;
@@ -33,28 +31,6 @@ impl NymEcashContract<'_> {
Ok(TICKETBOOK_SIZE)
}
pub(crate) fn tickets_redemption_amount(
&self,
storage: &dyn Storage,
config: &Config,
number_of_tickets: u16,
) -> Result<Coin, EcashContractError> {
let deposit_amount = config.deposit_amount.amount;
let ticketbook_size = Uint128::new(self.get_ticketbook_size(storage)? as u128);
let tickets = Uint128::new(number_of_tickets as u128);
// how many tickets from a ticketbook you redeemed
let book_ratio = Decimal::from_ratio(tickets, ticketbook_size);
// return = ticketbook_price * (tickets / ticketbook_size)
let return_amount = book_ratio * deposit_amount;
Ok(Coin {
denom: config.deposit_amount.denom.clone(),
amount: return_amount,
})
}
fn must_get_multisig_addr(&self, deps: Deps) -> Result<Addr, EcashContractError> {
// SAFETY: multisig admin MUST always be set on initialisation,
// if the call fails, we're in some weird UB land
@@ -117,172 +93,3 @@ impl NymEcashContract<'_> {
Ok(proposal_response)
}
}
#[cfg(test)]
mod tests {
use super::*;
use crate::support::tests::TestSetupSimple;
#[test]
fn ticket_redemption_amount() -> anyhow::Result<()> {
// make sure the ticketbook size hasn't changed so that our tests are still valid
assert_eq!(TICKETBOOK_SIZE, 50);
// ticketbook price of 100nym
let test = TestSetupSimple::new().with_deposit_amount(100_000_000);
let res =
test.contract()
.tickets_redemption_amount(test.deps().storage, &test.config(), 1)?;
assert_eq!(res.amount.u128(), 2_000_000);
let res =
test.contract()
.tickets_redemption_amount(test.deps().storage, &test.config(), 2)?;
assert_eq!(res.amount.u128(), 4_000_000);
let res =
test.contract()
.tickets_redemption_amount(test.deps().storage, &test.config(), 5)?;
assert_eq!(res.amount.u128(), 10_000_000);
let res =
test.contract()
.tickets_redemption_amount(test.deps().storage, &test.config(), 10)?;
assert_eq!(res.amount.u128(), 20_000_000);
let res =
test.contract()
.tickets_redemption_amount(test.deps().storage, &test.config(), 30)?;
assert_eq!(res.amount.u128(), 60_000_000);
let res =
test.contract()
.tickets_redemption_amount(test.deps().storage, &test.config(), 50)?;
assert_eq!(res.amount.u128(), 100_000_000);
let res =
test.contract()
.tickets_redemption_amount(test.deps().storage, &test.config(), 123)?;
assert_eq!(res.amount.u128(), 246_000_000);
// ticketbook price of 1.5unym per ticket
let test = TestSetupSimple::new().with_deposit_amount(75);
let res =
test.contract()
.tickets_redemption_amount(test.deps().storage, &test.config(), 1)?;
assert_eq!(res.amount.u128(), 1);
let res =
test.contract()
.tickets_redemption_amount(test.deps().storage, &test.config(), 2)?;
assert_eq!(res.amount.u128(), 3);
let res =
test.contract()
.tickets_redemption_amount(test.deps().storage, &test.config(), 5)?;
assert_eq!(res.amount.u128(), 7);
let res =
test.contract()
.tickets_redemption_amount(test.deps().storage, &test.config(), 10)?;
assert_eq!(res.amount.u128(), 15);
let res =
test.contract()
.tickets_redemption_amount(test.deps().storage, &test.config(), 30)?;
assert_eq!(res.amount.u128(), 45);
let res =
test.contract()
.tickets_redemption_amount(test.deps().storage, &test.config(), 50)?;
assert_eq!(res.amount.u128(), 75);
let res =
test.contract()
.tickets_redemption_amount(test.deps().storage, &test.config(), 123)?;
assert_eq!(res.amount.u128(), 184);
// ticketbook price of 1unym per ticket
let test = TestSetupSimple::new().with_deposit_amount(50);
let res =
test.contract()
.tickets_redemption_amount(test.deps().storage, &test.config(), 1)?;
assert_eq!(res.amount.u128(), 1);
let res =
test.contract()
.tickets_redemption_amount(test.deps().storage, &test.config(), 2)?;
assert_eq!(res.amount.u128(), 2);
let res =
test.contract()
.tickets_redemption_amount(test.deps().storage, &test.config(), 5)?;
assert_eq!(res.amount.u128(), 5);
let res =
test.contract()
.tickets_redemption_amount(test.deps().storage, &test.config(), 10)?;
assert_eq!(res.amount.u128(), 10);
let res =
test.contract()
.tickets_redemption_amount(test.deps().storage, &test.config(), 30)?;
assert_eq!(res.amount.u128(), 30);
let res =
test.contract()
.tickets_redemption_amount(test.deps().storage, &test.config(), 50)?;
assert_eq!(res.amount.u128(), 50);
let res =
test.contract()
.tickets_redemption_amount(test.deps().storage, &test.config(), 123)?;
assert_eq!(res.amount.u128(), 123);
// ticketbook price of 1unym in total
let test = TestSetupSimple::new().with_deposit_amount(1);
let res =
test.contract()
.tickets_redemption_amount(test.deps().storage, &test.config(), 1)?;
assert_eq!(res.amount.u128(), 0);
let res =
test.contract()
.tickets_redemption_amount(test.deps().storage, &test.config(), 2)?;
assert_eq!(res.amount.u128(), 0);
let res =
test.contract()
.tickets_redemption_amount(test.deps().storage, &test.config(), 5)?;
assert_eq!(res.amount.u128(), 0);
let res =
test.contract()
.tickets_redemption_amount(test.deps().storage, &test.config(), 10)?;
assert_eq!(res.amount.u128(), 0);
let res =
test.contract()
.tickets_redemption_amount(test.deps().storage, &test.config(), 30)?;
assert_eq!(res.amount.u128(), 0);
let res =
test.contract()
.tickets_redemption_amount(test.deps().storage, &test.config(), 50)?;
assert_eq!(res.amount.u128(), 1);
let res =
test.contract()
.tickets_redemption_amount(test.deps().storage, &test.config(), 123)?;
assert_eq!(res.amount.u128(), 2);
// ticketbook price of 0unym
let test = TestSetupSimple::new().with_deposit_amount(0);
let res =
test.contract()
.tickets_redemption_amount(test.deps().storage, &test.config(), 1)?;
assert_eq!(res.amount.u128(), 0);
let res =
test.contract()
.tickets_redemption_amount(test.deps().storage, &test.config(), 2)?;
assert_eq!(res.amount.u128(), 0);
let res =
test.contract()
.tickets_redemption_amount(test.deps().storage, &test.config(), 5)?;
assert_eq!(res.amount.u128(), 0);
let res =
test.contract()
.tickets_redemption_amount(test.deps().storage, &test.config(), 10)?;
assert_eq!(res.amount.u128(), 0);
let res =
test.contract()
.tickets_redemption_amount(test.deps().storage, &test.config(), 30)?;
assert_eq!(res.amount.u128(), 0);
let res =
test.contract()
.tickets_redemption_amount(test.deps().storage, &test.config(), 50)?;
assert_eq!(res.amount.u128(), 0);
let res =
test.contract()
.tickets_redemption_amount(test.deps().storage, &test.config(), 123)?;
assert_eq!(res.amount.u128(), 0);
Ok(())
}
}
+20 -29
View File
@@ -8,7 +8,9 @@ use crate::helpers::{
BlacklistKey, Config, MultisigReply, BLACKLIST_PAGE_DEFAULT_LIMIT, BLACKLIST_PAGE_MAX_LIMIT,
CONTRACT_NAME, CONTRACT_VERSION, DEPOSITS_PAGE_DEFAULT_LIMIT, DEPOSITS_PAGE_MAX_LIMIT,
};
use cosmwasm_std::{coin, BankMsg, Coin, Event, Order, Reply, Response, StdResult};
use cosmwasm_std::{
coin, BankMsg, Coin, Decimal, Event, Order, Reply, Response, StdResult, Uint128,
};
use cw4::Cw4Contract;
use cw_controllers::Admin;
use cw_storage_plus::{Bound, Item, Map};
@@ -17,9 +19,7 @@ use nym_ecash_contract_common::blacklist::{
BlacklistedAccount, BlacklistedAccountResponse, Blacklisting, PagedBlacklistedAccountResponse,
};
use nym_ecash_contract_common::counters::PoolCounters;
use nym_ecash_contract_common::deposit::{
DepositData, DepositResponse, LatestDepositResponse, PagedDepositsResponse,
};
use nym_ecash_contract_common::deposit::{DepositData, DepositResponse, PagedDepositsResponse};
use nym_ecash_contract_common::events::{
DEPOSITED_FUNDS_EVENT_TYPE, DEPOSIT_ID, PROPOSAL_ID_ATTRIBUTE_NAME,
};
@@ -179,25 +179,6 @@ impl NymEcashContract<'_> {
})
}
#[msg(query)]
pub fn get_latest_deposit(
&self,
ctx: QueryCtx,
) -> Result<LatestDepositResponse, EcashContractError> {
let Some(latest_id) = self.deposits.latest_deposit(ctx.deps.storage)? else {
return Ok(LatestDepositResponse::default());
};
let maybe_deposit = self.deposits.try_load_by_id(ctx.deps.storage, latest_id)?;
Ok(LatestDepositResponse {
deposit: maybe_deposit.map(|deposit| DepositData {
id: latest_id,
deposit,
}),
})
}
#[msg(query)]
pub fn get_deposits_paged(
&self,
@@ -302,20 +283,30 @@ impl NymEcashContract<'_> {
.assert_admin(ctx.deps.as_ref(), &ctx.info.sender)?;
let config = self.config.load(ctx.deps.storage)?;
let to_return = self.tickets_redemption_amount(ctx.deps.storage, &config, n)?;
if to_return.amount.is_zero() {
return Ok(Response::new());
}
// TODO: we need unit tests for this
let deposit_amount = config.deposit_amount.amount;
let ticketbook_size = Uint128::new(self.get_ticketbook_size(ctx.deps.storage)? as u128);
let tickets = Uint128::new(n as u128);
// how many tickets from a ticketbook you redeemed
let book_ratio = Decimal::from_ratio(tickets, ticketbook_size);
// return = ticketbook_price * (tickets / ticketbook_size)
let return_amount = book_ratio * deposit_amount;
self.pool_counters
.update(ctx.deps.storage, |mut counters| -> StdResult<_> {
counters.total_redeemed.amount += to_return.amount;
counters.total_redeemed.amount += return_amount;
Ok(counters)
})?;
Ok(Response::new().add_message(BankMsg::Send {
to_address: config.holding_account.to_string(),
amount: vec![to_return],
amount: vec![Coin {
denom: config.deposit_amount.denom,
amount: return_amount,
}],
}))
}
-32
View File
@@ -19,15 +19,6 @@ impl<'a> DepositStorage<'a> {
}
}
pub fn latest_deposit(
&self,
storage: &dyn Storage,
) -> Result<Option<DepositId>, EcashContractError> {
self.deposit_id_counter
.may_load(storage)
.map_err(Into::into)
}
fn next_id(&self, store: &mut dyn Storage) -> Result<DepositId, EcashContractError> {
let id: DepositId = self.deposit_id_counter.may_load(store)?.unwrap_or_default();
let next_id = id + 1;
@@ -116,29 +107,6 @@ mod tests {
use cosmwasm_std::testing::mock_dependencies;
use nym_crypto::asymmetric::ed25519;
#[test]
fn getting_latest_deposit() -> anyhow::Result<()> {
let mut deps = mock_dependencies();
let storage = DepositStorage::new();
// it's `None` for fresh storage
let first = storage.latest_deposit(deps.as_ref().storage)?;
assert!(first.is_none());
let _ = storage.next_id(deps.as_mut().storage)?;
// is correctly incremented for each subsequent id
let second = storage.latest_deposit(deps.as_ref().storage)?;
assert_eq!(second, Some(1));
let _ = storage.next_id(deps.as_mut().storage)?;
let third = storage.latest_deposit(deps.as_ref().storage)?;
assert_eq!(third, Some(2));
Ok(())
}
#[test]
fn iterating_over_deposits() {
let mut deps = mock_dependencies();
-103
View File
@@ -1,113 +1,10 @@
// Copyright 2024 - Nym Technologies SA <contact@nymtech.net>
// SPDX-License-Identifier: Apache-2.0
use crate::contract::NymEcashContract;
use crate::helpers::Config;
use cosmwasm_std::testing::{mock_dependencies, mock_env, mock_info, MockApi, MockQuerier};
use cosmwasm_std::{coin, Addr, Deps, Empty, Env, MemoryStorage, MessageInfo, OwnedDeps};
use rand_chacha::rand_core::SeedableRng;
use rand_chacha::ChaCha20Rng;
use sylvia::types::{ExecCtx, InstantiateCtx, QueryCtx};
pub fn test_rng() -> ChaCha20Rng {
let dummy_seed = [42u8; 32];
ChaCha20Rng::from_seed(dummy_seed)
}
const CONTRACT: NymEcashContract<'static> = NymEcashContract::new();
const DENOM: &str = "unym";
#[allow(dead_code)]
pub struct TestSetupSimple {
pub deps: OwnedDeps<MemoryStorage, MockApi, MockQuerier<Empty>>,
pub env: Env,
pub rng: ChaCha20Rng,
pub owner: Addr,
pub holding_account: Addr,
pub multisig_contract: Addr,
pub group_contract: Addr,
}
impl TestSetupSimple {
pub fn new() -> Self {
let mut deps = mock_dependencies();
let env = mock_env();
let owner = Addr::unchecked("owner");
let init_ctx = InstantiateCtx {
deps: deps.as_mut(),
env: env.clone(),
info: mock_info(owner.as_str(), &[]),
};
let rng = test_rng();
let holding_account = Addr::unchecked("holding_account");
let multisig_contract = Addr::unchecked("multisig_contract");
let group_contract = Addr::unchecked("group_contract");
CONTRACT
.instantiate(
init_ctx,
holding_account.to_string(),
multisig_contract.to_string(),
group_contract.to_string(),
coin(75_000_000, DENOM.to_string()),
)
.unwrap();
TestSetupSimple {
deps,
env,
rng,
owner,
holding_account,
multisig_contract,
group_contract,
}
}
pub fn admin(&self) -> MessageInfo {
let admin = CONTRACT
.contract_admin
.get(self.deps.as_ref())
.unwrap()
.unwrap();
mock_info(admin.as_str(), &[])
}
pub fn execute_ctx(&mut self, sender: MessageInfo) -> ExecCtx {
ExecCtx {
env: self.env.clone(),
deps: self.deps.as_mut(),
info: sender,
}
}
#[allow(dead_code)]
pub fn query_ctx(&self) -> QueryCtx {
QueryCtx {
env: self.env.clone(),
deps: self.deps.as_ref(),
}
}
pub fn contract(&self) -> NymEcashContract {
CONTRACT
}
pub fn deps(&self) -> Deps<'_> {
self.deps.as_ref()
}
pub fn config(&self) -> Config {
CONTRACT.config.load(self.deps().storage).unwrap()
}
pub fn with_deposit_amount(mut self, amount: u128) -> Self {
CONTRACT
.update_deposit_value(self.execute_ctx(self.admin()), coin(amount, DENOM))
.unwrap();
self
}
}
@@ -29,9 +29,6 @@ pub fn default_mixnet_init_msg() -> nym_mixnet_contract_common::InstantiateMsg {
standby: 0,
},
},
current_nym_node_version: "1.1.10".to_string(),
version_score_weights: Default::default(),
version_score_params: Default::default(),
profit_margin: Default::default(),
interval_operating_cost: Default::default(),
}

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