Compare commits

..

141 Commits

Author SHA1 Message Date
mfahampshire 589ee64516 refresh older imported text from archive 2024-08-30 09:33:53 +02:00
mfahampshire b20ab5dc50 tweak 2024-08-30 09:16:11 +02:00
mfahampshire 5bdff28a11 tweaked overall content 2024-08-29 18:02:52 +02:00
mfahampshire 4795a643a4 added more info from archive page 2024-08-29 18:02:38 +02:00
mfahampshire f7f6421415 first pass double spend doc 2024-08-29 18:02:22 +02:00
mfahampshire 891cfb80ea small tweak to archive coconut page 2024-08-29 18:02:06 +02:00
mfahampshire 9344296804 remove double spend stub from overview doc 2024-08-28 17:35:29 +02:00
mfahampshire 3538b5237e split out features into own pages 2024-08-28 17:33:33 +02:00
mfahampshire 5581f735d2 removed feature info from main overview doc 2024-08-28 17:33:19 +02:00
mfahampshire c0ede6a506 new structure 2024-08-28 17:33:04 +02:00
mfahampshire 5d6b84a94f added todo 2024-08-23 12:46:31 +02:00
mfahampshire 66fff0edf0 simplified subheading for zknyms 2024-08-23 12:16:37 +02:00
mfahampshire 2bdb623101 added high level examples to zknym overview page 2024-08-23 12:16:03 +02:00
mfahampshire 1f435880d7 restructure + reword + skeleton of incremental spend 2024-08-22 15:42:44 +02:00
mfahampshire 34579222c5 removed unnecessary file for moment 2024-08-22 15:42:23 +02:00
mfahampshire 2a43134327 made generic 2024-08-21 14:47:18 +02:00
mfahampshire 844bcba6e8 first pass ecash docs 2024-08-21 14:20:26 +02:00
import this f3ac17eb9d [DOCs/developers]: syntax fix (#4770)
* syntax-fix

* syntax-fix
2024-08-20 16:41:29 +02:00
import this 6296d09adf [DOCs/developers]: Update NymVPN CLI guide (#4769)
* creat guide to build nym-vpn-cli from source

* update nymvpn cli guide
2024-08-20 13:10:05 +00:00
Bogdan-Ștefan Neacşu 2ae81f6da0 Avoid race on ip and registration structures (#4766) 2024-08-20 14:51:59 +02:00
Tommy Verrall 1d5e8b62ac Merge pull request #4765 from nymtech/serinko-hotfix
docs/hotfix
2024-08-20 10:21:18 +02:00
import this 581cdd5bdf Update configuration.md 2024-08-18 11:56:56 +00:00
import this e2e49e7136 docs/hotfix 2024-08-18 11:55:28 +00:00
Jon Häggblad dff82f946f Make gateway latency check generic (#4759)
* Replace concrete gateway type with trait in latency check

* Rename to ConnectableGateway
2024-08-15 09:42:13 +02:00
Tommy Verrall ec61728654 Merge pull request #4762 from nymtech/serinko/wg_hotfix
[DOCs/operators]: serinko/hotfix
2024-08-13 17:48:36 +02:00
import this 61471e9058 add note about IPv6 2024-08-13 15:41:16 +00:00
import this ed4fd84503 serinko/hotfix 2024-08-13 15:39:31 +00:00
Jon Häggblad cb4b0403b5 Remove deprecated mark_as_success and use new disarm (#4751) 2024-08-13 15:09:48 +02:00
import this da8e513627 [DOCs/operators]: WireGuard guide & changelog update (#4760)
* wireguard documentation and changelog update

* add review comments

* add review comments
2024-08-13 13:05:52 +00:00
Jon Häggblad 3f6de8b10c Remove duplicate stat count for retransmissions (#4756) 2024-08-09 14:55:14 +02:00
import this 1e01a8e633 [DOCs/operators]: Release detailed changelog for v2024.9 topdeck (#4757)
* add changelog for new release

* add more URLs redirection for socks5 specific apps

* update exit policy page

* finish changelog - ready for review

* add tooling

* clarify tornul note comment
2024-08-07 13:20:17 +00:00
import this aaf3dca5b9 [DOCs]: Catching more broken URLs (#4755)
* urls edit

* finish PR - ready to merge
2024-08-06 18:49:46 +00:00
Bogdan-Ștefan Neacşu f939cae3d9 Update peer refresh value (#4754)
* Use a more proper timeout value

* Move const to wireguard types
2024-08-06 18:14:29 +02:00
import this 1db61f800c docs/hotfix (#4752) 2024-08-06 14:49:09 +00:00
import this 5096c1e60e [DOCs]: Create NymConnect archive page (#4750) 2024-08-06 13:22:30 +00:00
import this 7e36595d8f [DOCs/bugfix]: Fix broken URLs (#4745)
* create archive nym connect page & add redirections

* add info to socks5 page

* fix dev-portal links

* finish URL edits and redirection
2024-08-06 12:37:37 +00:00
benedetta davico 515aedac60 Merge pull request #4747 from nymtech/release/2024.9-topdeck
Release/2024.9 topdeck into develop
2024-08-06 11:05:19 +02:00
benedetta davico dca2b2c763 Merge branch 'develop' into release/2024.9-topdeck 2024-08-06 10:19:48 +02:00
Jon Häggblad c92f09543e Fix clippy on rustc beta toolchain (#4746)
* Fix clippy warnings for rust beta toolchain

* Cargo.lock nym-wallet
2024-08-05 17:59:49 +02:00
Tommy Verrall b45eb16783 Update ci-build-upload-binaries.yml 2024-08-05 11:48:07 +02:00
Tommy Verrall f8523dc7d1 Update publish-nym-binaries.yml 2024-08-05 11:47:00 +02:00
Jon Häggblad 996ce6a233 Fix clippy for beta toolchain (#4742)
* Fix clippy for beta toolchain

* Remove ignored default-features for workspace dependency

* Add nym- prefix to serde-helpers crate

* Remove unused local_guard mod
2024-08-02 11:05:34 +02:00
Jon Häggblad 1dcb0a0456 Disable testnet-manager on non-unix (#4741)
* Disable testnet-manager on non-unix

* Move mod behind cfg too
2024-08-01 11:24:33 +02:00
Jon Häggblad 55b99e4ce1 Don't set NYM_VPN_API to default (#4740) 2024-07-30 20:46:02 +02:00
Bogdan-Ștefan Neacşu bd94dd3055 Persist wireguard peers (#4732)
* Store wireguard peers in db

* Add update to nym-node

* Move gateway-requests and gateway-storage to common

* Carry storage to PeerController field

* Double kernel modifications with storage ones

* Take storage peers at boot

* Link storage query for registration flow

* Move authenticator peer comms in peer manager

* Modify template too

* Remove unused

* Fix clippy

* Fix clippy non-linux

* Keep storage data up-to-date on every check

* Check for staleness in storage timestamps

* Remove potential for panic in unwrap

* Fix clippy

* Fmt

* Clippy after rebase

* Remove in memory test structure
2024-07-30 18:26:40 +02:00
Jon Häggblad 0d19bb4ddc Fix (some) feature unification build failures (#4681)
* nym-crypto: use rand_core traits from rand crate instead of cipher

Make rand feature also use the rand_core traits from the rand crate to
fix compilation of nym-bandwidth-controller

* Add features to bip32 in nym-ledger crate

* Delete unused empty crate

* Add clag feature to socks5-client

* Add feature flags to authenticator

* Add clap feature to network-requester

* Handle rebase changes
2024-07-30 16:15:56 +02:00
Tommy Verrall dcd70155cd Merge pull request #4738 from nymtech/tommy/add-wireguard-to-builds
Update ci-build-upload-binaries.yml
2024-07-30 13:33:24 +02:00
Jędrzej Stuczyński a469aeff05 Merge pull request #4623 from nymtech/simon/ecash_reviewed
Feature Compact Ecash : The One PR
2024-07-30 12:30:50 +01:00
Jędrzej Stuczyński 107199bd9c clippy 2024-07-30 11:48:16 +01:00
Jędrzej Stuczyński 53524447c4 fixing build issues in testnet-manager post rebasing 2024-07-30 11:38:05 +01:00
Jędrzej Stuczyński bc832c97d8 make gateway query only single nym-api for BF (+ every 10min) 2024-07-30 11:31:50 +01:00
Jędrzej Stuczyński 4989d47ea2 nym-api exporting bloomfilter in separate task 2024-07-30 11:31:50 +01:00
Jędrzej Stuczyński 3cb69780a6 removed 95/5 reward split in favour of the holding account 2024-07-30 11:31:49 +01:00
Jędrzej Stuczyński 68b61bfa84 fix build issues 2024-07-30 11:31:49 +01:00
Jędrzej Stuczyński 06fca9bd1f reject tickets with more than a single payment 2024-07-30 11:31:49 +01:00
Jędrzej Stuczyński 4c10cebf1b propagated new ticket type through the whole stack 2024-07-30 11:31:49 +01:00
Jędrzej Stuczyński aea962b546 explicit aliases for ExpirationDate and TicketType 2024-07-30 11:31:49 +01:00
aniampio ab2a1c3fe5 Run fmt 2024-07-30 11:31:49 +01:00
aniampio 8d0c040015 Move functions around 2024-07-30 11:31:48 +01:00
aniampio 42efff83da Add type attribute 2024-07-30 11:31:48 +01:00
Jędrzej Stuczyński 86fe955592 fixed sdk-wasm build 2024-07-30 11:31:48 +01:00
Jędrzej Stuczyński c3ce0d0b5c post rebase fixes 2024-07-30 11:31:48 +01:00
Jędrzej Stuczyński 0e2cfa5be0 fixed incorrect naming of the ecash contract lib 2024-07-30 11:31:48 +01:00
Jędrzej Stuczyński 17a5872c6d chore: log info -> debug 2024-07-30 11:31:48 +01:00
Jędrzej Stuczyński 969155bf91 chore: fix unit tests 2024-07-30 11:31:48 +01:00
Jędrzej Stuczyński f4fafbfea5 updated ecash-contract parameters and generated schema 2024-07-30 11:31:47 +01:00
Jędrzej Stuczyński 5e97b1f79a updated all ecash-related parameters - bloomfilter, expiration, sizes, etc. 2024-07-30 11:31:47 +01:00
Jędrzej Stuczyński b52bf951a6 improve client errors 2024-07-30 11:27:25 +01:00
Jędrzej Stuczyński 98805a11e4 testnet manager: create client against specific nym-node 2024-07-30 11:27:25 +01:00
Jędrzej Stuczyński 0a2f28b0ec testnet manager: start multiple gateways 2024-07-30 11:27:25 +01:00
Jędrzej Stuczyński db1ad4dcab fixed client crashing upon having bandwidth revoked 2024-07-30 11:27:25 +01:00
Jędrzej Stuczyński 78ca539018 fixed incorrect bloomfilter cutoff date calculation 2024-07-30 11:27:24 +01:00
Jędrzej Stuczyński 04cafc72dc improved bandwidth information propagation within the client 2024-07-30 11:27:24 +01:00
Jędrzej Stuczyński 63812994a1 fixed nym-node zk-nym config debug settings not being applied 2024-07-30 11:27:24 +01:00
Jędrzej Stuczyński 19dee11539 changed the number of tickets to 100 2024-07-30 11:27:24 +01:00
Jędrzej Stuczyński 6f3a6b7855 Update README.md 2024-07-30 11:27:24 +01:00
Jędrzej Stuczyński 7c84ad4384 readme 2024-07-30 11:27:24 +01:00
Jędrzej Stuczyński bc647fc8e2 slightly less ghetto handling of .env files 2024-07-30 11:27:24 +01:00
Jędrzej Stuczyński 429ff6045d removed outdated error 2024-07-30 11:27:23 +01:00
Jędrzej Stuczyński 0de1deced4 fixed query for client bandwidth 2024-07-30 11:27:23 +01:00
Simon Wicky fc2eedfc66 Another Grand Ecash Squasheroo
add offline ecash library

minor changes in coconut benchmarks

add ecash smart contract

change contract traits from coconut to ecash

first wave of andrew's suggestion

first wave of andrew's suggestion

second wave of andrew's suggestion for ecash lib

andrew's suggestion for ecash contract

licensing commit

safety comments for most unwraps

more unwrap handling

change chrono crate for time

latest cargo lock

error revamp

small visibility fix

small fix

remove indexedmap from contract + some tweaks

add cw2 version in ecash contract

remove envryption key from contract

change types from coconut to ecash types

adapt api model for credential issuance

adapt issued credential storage on API

add signatures cache on API

change API routes for new blind signing

modify issued_credential table

add issuance logic client-side

credential and signature storage client side

utils for credential issuance

first wave of fix

some of andrew's suggestions

remove encryption key from deposit

freepass issuance client side

freepass issuance API side

andrew's suggested fixes

other suggested fix

adapt change from PR below

allow offline verification flag

credential spending models

credential spending models for client

credential preperation for the client

credential preperation for the client

credential storage for spending on client

bloom filter for API

spent credential storage on validators

API route for spending online and offline ecash

API routes in the client lib

credential storage on gateway

ecash verifier to replace coconut verifier

accept credentials on gateway

bandwidth expiration for gateways

client ask for more bandwidth if it runs out

credential import

adapt nym validator rewarder and sdk

fix tests api tests and add constants

cargo fmt and lock and small test fix

cargo fmt and lock and small test fix

cargo lock

move stuff where they belong in ecash and static parameters

move some constants, error handling and phase out time crate

error revamp part 2

secret key by ref instead of clone

change l in wallet and v visibility

rework payinfo

rework monster tuples

fix expiration date signature cloning

minor fixes

final bits and bobs fixes

final bits and bobs fixes

rename l accessor to tickets_spent

wave of fixes

second wave of fixes

change hash domain value

removed benchmark flag

remove useless stringification in storage

nuke Bandwidth voucher

change timestamps to offsetdatetime

key name change

post-rebase fixes

update nym-connect 'time' dep due to broken semver

upload ecash contract to the build server

make wasm zknym-lib compile

but it won't work properly just yet

make wasm zknym-lib compile

but it won't work properly just yet

fix typo in ecash contract deps

make sure to use 0.1.0 sphinx packet

optimise pairings in 'check_vk_pairing'

derive serde for ecash types

simplified g1 tuple byte conversion

further optimise the pairing

unified signature type + renamed nym-api coconut module to ecash

using bincode serialiser for more complex binary types

using multimiller loop instead of rayon for verifying coin indices signatures

batching signature verification wherever possible

feature-locked rayon

clippy

refactor ecash contract a bit + introduce deposit storage

reworked find_proposal_id

various minor fixed

add offline_zk_nyms to nym-node everywhere

add missing #query

change test value to fit new serialization

optimised deposits storage

removed duplicate decompression code

using deposit_id instead of transaction hash

removed freepasses

split up ecash handling

unified shared state

fixed deposit_id parsing

log recovered deposit id

removed online verification

add detailed build info to ecash contract

fixed deserialisation of deposit amount received from nyxd queries

changed deposit to only persist attached pubkey

first iteration of split of verification and redemption

basic tool for setting up new network

expanded the tool with the option to bypass DKG

rename + init network without DKG

setting up locally running apis

ecash key migration

more local functionalities

wip fixing sql schemas

gateway immediately submitting redemption proposal

and getting it passed if valid

most of the gateway logic for split redemption with error recovery

fixed gateway not persisting ecash signers

simplify creation of compatible client

create properly serialised ecash key from the beginning

rebuild missing tickets and proposals on startup

stop ticket issuance during DKG transition

fixing build issues

split out ecash storage on nym-api side

master-verification-key route

caching all the signatures and keys

implemented aggregated routes for nym-apis

swagger UI for ecash endpoints

added explicit annotation for index and expiration signatures

revamped client ticketbook storage

save all recovery information in the same underlying storage

wrapper for bloomfilter

being more aggressive with marking tickets as used

ensure client has correct signatures before making deposit

fix deserialisation of AggregatedExpirationDateSignatureResponse + add ticketbook table

split nym-api ecash routes handlers into multiple files

fixed deserialisation of encoded expiration date

add tt_gamma1 to challenge and change naming for paper consistency

rotating double spending bloomfilter

nym-api test fixes + make sure to insert initial BF params

fixed ecash benchmark code

updated contract schema

updated CI to not upload gateway/mixnode binaries

ticket bandwidth revocation

added default deserialisation for zk nym config

post-rebase fixes
2024-07-30 11:27:21 +01:00
Tommy Verrall 7ddd819ff3 Merge pull request #4739 from nymtech/tommy/add-wireguard-publish-binaries
Update publish-nym-binaries.yml
2024-07-30 11:41:43 +02:00
Tommy Verrall 83b416d12d amend build all binaries command 2024-07-30 11:38:07 +02:00
Tommy Verrall b9c775c3ae Update publish-nym-binaries.yml
add wireguard to builds
2024-07-30 11:27:50 +02:00
Tommy Verrall b613cf87c8 Update ci-build-upload-binaries.yml
add cargo features for all
2024-07-30 11:25:18 +02:00
mx 6f669866e9 Max/doc link fix (#4737)
* fix broken link in header dropdown

---------

Co-authored-by: serinko <97586125+serinko@users.noreply.github.com>
Co-authored-by: mfahampshire <mfahampshire@pm.me>
2024-07-30 08:48:14 +00:00
Tommy Verrall 4e61fefec8 Merge pull request #4736 from nymtech/jon/nym-vpn-api-env
Add NYM_VPN_API to network config
2024-07-30 10:04:55 +02:00
Jon Häggblad b4514ecd83 update for wallet 2024-07-29 23:50:52 +02:00
Jon Häggblad 4f6902525e restore explorer-api 2024-07-29 23:30:09 +02:00
Jon Häggblad 881139e36f Add nym_vpn_api_url 2024-07-29 23:30:09 +02:00
Jon Häggblad 32e2557456 Fix tokio error in 1.39 (#4730)
* Fix tokio error in 1.39

Fix the error generated by tokio 1.39

72 | /             tokio::select! {
173 | |                 daemon_res = &mut fused_runner => {
174 | |                     warn!("the daemon has terminated by itself - was it a short lived command?");
175 | |                     let exit_status = daemon_res?;
...   |
179 | |                 event = &mut self.upgrade_plan_watcher.next() => {
    | |                              ^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^ creates a temporary value which is freed while still in use
...   |
201 | |                 }
202 | |             }
    | |             -
    | |             |
    | |_____________temporary value is freed at the end of this statement
    |               borrow later used here

and

62 | /         select! {
63 | |             connection_message = &mut mix_receiver.next() => {
   | |                                       ^^^^^^^^^^^^^^^^^^^ creates a temporary value which is freed while still in use
64 | |                 if let Some(connection_message) = connection_message {
65 | |                     if deal_with_message(connection_message, &mut writer, &local_destination_address, &remote_source_address, connection_id).await {
...  |
86 | |             }
87 | |         }
   | |         -
   | |         |
   | |_________temporary value is freed at the end of this statement
   |           borrow later used here

* Upgrade to tokio 1.39.1

* Simpler attempt

* Revert fixes and instead bump to tokio 1.39.2

* update

* bump msrv for nym-node-tester-wasm
2024-07-29 20:45:26 +02:00
Jon Häggblad 8b44820e51 Re-export RecipientFormattingError in nym sdk (#4735) 2024-07-29 19:20:26 +02:00
import this 5e6417f837 clarify syntax - PR ready (#4734) 2024-07-29 13:51:31 +00:00
Bogdan-Ștefan Neacşu 3d5ac0b883 Fix version 1 not having template correspondent initially (#4733) 2024-07-29 12:38:27 +02:00
Jędrzej Stuczyński dfb2a2f380 Merge pull request #4716 from nymtech/feature/vesting-purge-plus-ranged-cost-params
Feature/vesting purge plus ranged cost params
2024-07-26 18:01:29 +01:00
fmtabbara d1de751850 fix ci 2024-07-26 17:28:24 +01:00
Jędrzej Stuczyński ecee6ca863 chore: cargo fmt 2024-07-26 15:08:38 +01:00
fmtabbara 31ea3f92e2 update bonding oc and pm validation 2024-07-26 15:08:38 +01:00
fmtabbara f19c934fae finish migrate vested bonded node work 2024-07-26 15:08:38 +01:00
Mark Sinclair 10d6f20de7 wip: add profit margin and cost params into validation from mixnet contract via MainContext 2024-07-26 15:08:38 +01:00
Mark Sinclair 96b33bfbe4 Regenerate TS types 2024-07-26 15:08:38 +01:00
Mark Sinclair 444c787d0a Add kind prop to vesting contract migration modal 2024-07-26 15:08:38 +01:00
Mark Sinclair 61fcd4ac69 Dialog and mock for migrating vesting contract delegations 2024-07-26 15:08:38 +01:00
Jędrzej Stuczyński b76802e6eb exposed tauri operations for vesting migrations 2024-07-26 15:08:38 +01:00
Mark Sinclair 7d351029a4 Fix dependency issue 2024-07-26 15:08:37 +01:00
Jędrzej Stuczyński 4ee445c119 cargo fmt 2024-07-26 15:05:47 +01:00
Jędrzej Stuczyński 61ddeea495 fixed post-rebasing imports 2024-07-26 15:05:47 +01:00
Jędrzej Stuczyński 7b802033b3 missing test fixture 2024-07-26 15:05:47 +01:00
Jędrzej Stuczyński b484f47369 fix nym-cli 2024-07-26 15:05:47 +01:00
Jędrzej Stuczyński 66979df10c update contract schema 2024-07-26 15:05:47 +01:00
Jędrzej Stuczyński 82f161fb91 added associated [hacky] wallet types 2024-07-26 15:05:47 +01:00
Jędrzej Stuczyński 9d0fd681d4 introducing allowed range of operator interval operating cost 2024-07-26 15:05:47 +01:00
Jędrzej Stuczyński c2ab47a102 profit margin range validation 2024-07-26 15:05:46 +01:00
Jędrzej Stuczyński 8704c21621 normalise node's profit margin during rewarding 2024-07-26 15:05:46 +01:00
Jędrzej Stuczyński 03ffb25bf9 introduced the concept of allowed profit margin ranges 2024-07-26 15:05:46 +01:00
Jędrzej Stuczyński 70db1ad062 fixed vesting contract tests 2024-07-26 15:05:46 +01:00
Jędrzej Stuczyński 952ed9b642 fixed wallet vesting-related tests 2024-07-26 15:05:46 +01:00
Jędrzej Stuczyński f57fe79686 updated contract schema 2024-07-26 15:05:46 +01:00
Jędrzej Stuczyński 9179f1c351 exposed migration commands to nym-cli + clippy 2024-07-26 15:05:46 +01:00
Jędrzej Stuczyński c4f7a1e09d implemented migration into non-vesting mixnodes/delegations 2024-07-26 15:05:46 +01:00
Jędrzej Stuczyński 701012a968 ensure no pending proxy events when migrating 2024-07-26 15:05:46 +01:00
Jędrzej Stuczyński 9767f72b8f removed all on_behalf mixnet contract methods 2024-07-26 15:05:46 +01:00
benedettadavico de0fb7459d update changelog 2024-07-26 15:28:06 +02:00
benedettadavico e2ead6dbe1 bumping binaries versions 2024-07-26 15:25:47 +02:00
Jędrzej Stuczyński 7b10d92ca4 Merge pull request #4731 from nymtech/chore/1.80-lints
chore: fix 1.80 lint issues
2024-07-26 11:51:23 +01:00
Jędrzej Stuczyński 2c6e5eb673 cherry-pick: fix build issues 2024-07-26 11:11:52 +01:00
Jon Häggblad 02fde4e530 Handle clients with different versions in IPR (#4723)
* Add signable_request function

* Export key type in function signature

* Cargo.lock

* Track client version and respond using it

* Internally use v7 and then down convert if needed

* Local response type

* Streamline

* Strong type for client version

* Remove commented out code

* rustfmt

* Ignore sign verification fail for v6
2024-07-24 15:35:59 +02:00
import this cc25fc1f32 [DOCs/operators]: Changelog for v2024.8 wispa & guide syntax edits (#4728)
* changelog for release v2024.8-wispa

* clarify syntax

* typo fix
2024-07-24 12:38:25 +00:00
benedetta davico c971e486b5 Merge pull request #4726 from nymtech/release/2024.8-wispa
Release/2024.8 wispa into develop
2024-07-24 12:48:57 +02:00
import this 96a9eb6f6a [DOCs/docs]: Commnet out extra stubs (#4727)
* commnet out stubs

* fix broken links - ready to merge
2024-07-24 11:58:14 +02:00
benedetta davico 9eeb61ea0a Merge branch 'develop' into release/2024.8-wispa 2024-07-24 10:56:03 +02:00
John Smith 08042c61ad [DOCs/operators]: Update troubleshooting/vps-isp.md with manual IPv6 configuration (#4651)
* Update vps-isp.md

Added an extra diagnostic step, which helped me to debug lack of routability.

* Update vps-isp.md

Implementing serinko's comments

* Update vps-isp.md

Changed possibly to possible and added how to find IPv6 Gateway.

* Update vps-isp.md

Fixed ifup/ifdown link
2024-07-24 08:53:49 +00:00
Stefano Piermatteo 36c74f30e5 [DOCs/operators]: Syntax fix in setup.md (#4682) 2024-07-24 08:37:33 +00:00
Tommy Verrall 4956d13bdc fix conflicts 2024-07-23 17:32:49 +02:00
benedettadavico d9f6c0723e updating versions 2024-07-23 15:37:04 +02:00
Tommy Verrall 52f5656190 Merge pull request #4721 from nymtech/jon/node-role-default
Default construct NodeRole
2024-07-22 15:09:27 +02:00
Jon Häggblad 21cd90f238 Default construct NodeRole for backwards compatibility 2024-07-22 14:59:18 +02:00
Bogdan-Ștefan Neacşu 72e243042e Add upgrades to nym-node for authenticator changes (#4703)
* Add iterative upgrades to nym-node

* Authenticator correct configuration

* Add info log

* Enable auth opts on entry gw

* Move ephemeral config from exit_gateway

* Fix fmt

* Fix clippy

* Pass custom transceiver for authenticator

* Fix non-linux build

* Feature gate wg_api

* Change naming from semver to simple incremental

* Move opts unwrap inside the mutable function

* Remove unneeded authenticator_description
2024-07-12 12:02:22 +02:00
benedettadavico c2ad4e5bb4 Update changelog and bump versions 2024-07-10 11:01:20 +02:00
Tommy Verrall 5f7f5ef92d Merge pull request #4699 from nymtech/release/2024.7-doubledecker
Release/2024.7 doubledecker
2024-07-10 10:46:03 +02:00
benedetta davico 008afe7a85 Merge pull request #4676 from nymtech/release/2024.6-chomp
Release/2024.6-chomp to master
2024-06-27 11:47:55 +02:00
358 changed files with 7403 additions and 5186 deletions
@@ -8,11 +8,6 @@ on:
required: true
default: false
type: boolean
enable_wireguard:
description: "Add --features wireguard"
required: true
default: false
type: boolean
enable_deb:
description: "True to enable cargo-deb installation and .deb package building"
required: false
@@ -70,9 +65,6 @@ jobs:
- name: Set CARGO_FEATURES
run: |
echo 'CARGO_FEATURES=--features wireguard' >> $GITHUB_ENV
if: >
github.event_name == 'schedule' ||
(github.event_name == 'workflow_dispatch' && inputs.enable_wireguard == true)
- name: Install Rust stable
uses: actions-rs/toolchain@v1
+6 -2
View File
@@ -51,6 +51,10 @@ jobs:
echo 'RUSTFLAGS="--cfg tokio_unstable"' >> $GITHUB_ENV
if: github.event_name == 'workflow_dispatch' && inputs.add_tokio_unstable == true
- name: Set CARGO_FEATURES
run: |
echo 'CARGO_FEATURES=--features wireguard' >> $GITHUB_ENV
- name: Install Rust stable
uses: actions-rs/toolchain@v1
with:
@@ -60,8 +64,8 @@ jobs:
uses: actions-rs/cargo@v1
with:
command: build
args: --workspace --release
args: --workspace --release ${{ env.CARGO_FEATURES }}
- name: Upload Artifact
uses: actions/upload-artifact@v3
with:
+38 -1
View File
@@ -4,6 +4,44 @@ Post 1.0.0 release, the changelog format is based on [Keep a Changelog](https://
## [Unreleased]
## [2024.9-topdeck] (2024-07-26)
- chore: fix 1.80 lint issues ([#4731])
- Handle clients with different versions in IPR ([#4723])
- Add 1GB/day/user bandwidth cap ([#4717])
- Feature/merge back ([#4710])
- removed mixnode/gateway config migration code and disabled cli without explicit flag ([#4706])
[#4731]: https://github.com/nymtech/nym/pull/4731
[#4723]: https://github.com/nymtech/nym/pull/4723
[#4717]: https://github.com/nymtech/nym/pull/4717
[#4710]: https://github.com/nymtech/nym/pull/4710
[#4706]: https://github.com/nymtech/nym/pull/4706
## [2024.8-wispa] (2024-07-10)
- add event parsing to support cosmos_sdk > 0.50 ([#4697])
- Fix NR config compatibility ([#4690])
- Remove UserAgent constructor since it's weakly typed ([#4689])
- [bugfix]: Node_api_check CLI looked over roles on blacklisted nodes ([#4687])
- Add mixnodes to self describing api cache ([#4684])
- Move and whole bump of crates to workspace and upgrade some ([#4680])
- Remove code that refers to removed nym-network-statistics ([#4679])
- Remove nym-network-statistics ([#4678])
- Create UserAgent that can be passed from the binary to the nym api client ([#4677])
- Add authenticator ([#4667])
[#4697]: https://github.com/nymtech/nym/pull/4697
[#4690]: https://github.com/nymtech/nym/pull/4690
[#4689]: https://github.com/nymtech/nym/pull/4689
[#4687]: https://github.com/nymtech/nym/pull/4687
[#4684]: https://github.com/nymtech/nym/pull/4684
[#4680]: https://github.com/nymtech/nym/pull/4680
[#4679]: https://github.com/nymtech/nym/pull/4679
[#4678]: https://github.com/nymtech/nym/pull/4678
[#4677]: https://github.com/nymtech/nym/pull/4677
[#4667]: https://github.com/nymtech/nym/pull/4667
## [2024.7-doubledecker] (2024-07-04)
- Add an early return in `parse_raw_str_logs` for empty raw log strings. ([#4686])
@@ -513,7 +551,6 @@ Post 1.0.0 release, the changelog format is based on [Keep a Changelog](https://
[#3187]: https://github.com/nymtech/nym/issues/3187
[#3203]: https://github.com/nymtech/nym/pull/3203
[#3199]: https://github.com/nymtech/nym/pull/3199
>>>>>>> master
## [v1.1.13] (2023-03-15)
Generated
+70 -31
View File
@@ -1471,7 +1471,7 @@ dependencies = [
"bitflags 1.3.2",
"crossterm_winapi",
"libc",
"mio",
"mio 0.8.11",
"parking_lot 0.12.3",
"signal-hook",
"signal-hook-mio",
@@ -1487,7 +1487,7 @@ dependencies = [
"bitflags 1.3.2",
"crossterm_winapi",
"libc",
"mio",
"mio 0.8.11",
"parking_lot 0.12.3",
"signal-hook",
"signal-hook-mio",
@@ -2240,7 +2240,7 @@ checksum = "0206175f82b8d6bf6652ff7d71a1e27fd2e4efde587fd368662814d6ec1d9ce0"
[[package]]
name = "explorer-api"
version = "1.1.36"
version = "1.1.38"
dependencies = [
"chrono",
"clap 4.5.7",
@@ -3933,6 +3933,18 @@ dependencies = [
"windows-sys 0.48.0",
]
[[package]]
name = "mio"
version = "1.0.1"
source = "registry+https://github.com/rust-lang/crates.io-index"
checksum = "4569e456d394deccd22ce1c1913e6ea0e54519f577285001215d33557431afe4"
dependencies = [
"hermit-abi 0.3.9",
"libc",
"wasi",
"windows-sys 0.52.0",
]
[[package]]
name = "mix-fetch-wasm"
version = "1.3.0-rc.0"
@@ -4114,7 +4126,7 @@ dependencies = [
"inotify",
"kqueue",
"libc",
"mio",
"mio 0.8.11",
"walkdir",
"windows-sys 0.45.0",
]
@@ -4192,7 +4204,7 @@ checksum = "830b246a0e5f20af87141b25c173cd1b609bd7779a4617d6ec582abaf90870f3"
[[package]]
name = "nym-api"
version = "1.1.40"
version = "1.1.42"
dependencies = [
"anyhow",
"async-trait",
@@ -4282,10 +4294,10 @@ dependencies = [
"nym-ecash-time",
"nym-mixnet-contract-common",
"nym-node-requests",
"nym-serde-helpers",
"rocket",
"schemars",
"serde",
"serde-helpers",
"serde_json",
"sha2 0.10.8",
"tendermint 0.37.0",
@@ -4313,6 +4325,7 @@ dependencies = [
"bs58 0.5.1",
"bytes",
"clap 4.5.7",
"defguard_wireguard_rs",
"fastrand 2.1.0",
"futures",
"ipnetwork 0.16.0",
@@ -4412,7 +4425,7 @@ dependencies = [
[[package]]
name = "nym-cli"
version = "1.1.38"
version = "1.1.40"
dependencies = [
"anyhow",
"base64 0.13.1",
@@ -4491,7 +4504,7 @@ dependencies = [
[[package]]
name = "nym-client"
version = "1.1.37"
version = "1.1.39"
dependencies = [
"bs58 0.5.1",
"clap 4.5.7",
@@ -4550,6 +4563,7 @@ dependencies = [
"nym-config",
"nym-country-group",
"nym-credential-storage",
"nym-credentials-interface",
"nym-crypto",
"nym-ecash-time",
"nym-explorer-client",
@@ -4796,10 +4810,10 @@ dependencies = [
"log",
"nym-bandwidth-controller",
"nym-client-core",
"nym-compact-ecash",
"nym-config",
"nym-credential-storage",
"nym-credentials",
"nym-credentials-interface",
"nym-ecash-time",
"nym-validator-client",
"thiserror",
@@ -4836,8 +4850,10 @@ dependencies = [
"bls12_381",
"nym-compact-ecash",
"nym-ecash-time",
"nym-network-defaults",
"rand 0.8.5",
"serde",
"strum 0.25.0",
"thiserror",
"time",
]
@@ -4997,6 +5013,7 @@ dependencies = [
"nym-ecash-contract-common",
"nym-ecash-double-spending",
"nym-gateway-requests",
"nym-gateway-storage",
"nym-ip-packet-router",
"nym-mixnet-client",
"nym-mixnode-common",
@@ -5086,6 +5103,24 @@ dependencies = [
"zeroize",
]
[[package]]
name = "nym-gateway-storage"
version = "0.1.0"
dependencies = [
"async-trait",
"bincode",
"defguard_wireguard_rs",
"log",
"nym-credentials-interface",
"nym-gateway-requests",
"nym-sphinx",
"sqlx",
"thiserror",
"time",
"tokio",
"tracing",
]
[[package]]
name = "nym-group-contract-common"
version = "0.1.0"
@@ -5377,7 +5412,7 @@ dependencies = [
[[package]]
name = "nym-network-requester"
version = "1.1.38"
version = "1.1.40"
dependencies = [
"addr",
"anyhow",
@@ -5428,7 +5463,7 @@ dependencies = [
[[package]]
name = "nym-node"
version = "1.1.4"
version = "1.1.6"
dependencies = [
"anyhow",
"bip39",
@@ -5648,6 +5683,7 @@ dependencies = [
"nym-credential-storage",
"nym-credential-utils",
"nym-credentials",
"nym-credentials-interface",
"nym-crypto",
"nym-gateway-requests",
"nym-network-defaults",
@@ -5673,6 +5709,15 @@ dependencies = [
"zeroize",
]
[[package]]
name = "nym-serde-helpers"
version = "0.1.0"
dependencies = [
"base64 0.21.7",
"bs58 0.5.1",
"serde",
]
[[package]]
name = "nym-service-providers-common"
version = "0.1.0"
@@ -5692,7 +5737,7 @@ dependencies = [
[[package]]
name = "nym-socks5-client"
version = "1.1.37"
version = "1.1.39"
dependencies = [
"bs58 0.5.1",
"clap 4.5.7",
@@ -6117,12 +6162,14 @@ dependencies = [
"nym-compact-ecash",
"nym-config",
"nym-credentials",
"nym-credentials-interface",
"nym-crypto",
"nym-ecash-time",
"nym-network-defaults",
"nym-task",
"nym-validator-client",
"nyxd-scraper",
"rand_chacha 0.3.1",
"serde",
"serde_with",
"sha2 0.10.8",
@@ -6173,12 +6220,14 @@ name = "nym-wireguard"
version = "0.1.0"
dependencies = [
"base64 0.21.7",
"bincode",
"chrono",
"dashmap",
"defguard_wireguard_rs",
"ip_network",
"log",
"nym-crypto",
"nym-gateway-storage",
"nym-network-defaults",
"nym-task",
"nym-wireguard-types",
@@ -6193,7 +6242,6 @@ name = "nym-wireguard-types"
version = "0.1.0"
dependencies = [
"base64 0.21.7",
"dashmap",
"hmac",
"log",
"nym-config",
@@ -6210,7 +6258,7 @@ dependencies = [
[[package]]
name = "nymvisor"
version = "0.1.3"
version = "0.1.5"
dependencies = [
"anyhow",
"bytes",
@@ -7914,15 +7962,6 @@ dependencies = [
"serde_derive",
]
[[package]]
name = "serde-helpers"
version = "0.1.0"
dependencies = [
"base64 0.21.7",
"bs58 0.5.1",
"serde",
]
[[package]]
name = "serde-json-wasm"
version = "0.5.0"
@@ -8179,7 +8218,7 @@ source = "registry+https://github.com/rust-lang/crates.io-index"
checksum = "29ad2e15f37ec9a6cc544097b78a1ec90001e9f71b81338ca39f430adaca99af"
dependencies = [
"libc",
"mio",
"mio 0.8.11",
"signal-hook",
]
@@ -9026,22 +9065,21 @@ checksum = "1f3ccbac311fea05f86f61904b462b55fb3df8837a366dfc601a0161d0532f20"
[[package]]
name = "tokio"
version = "1.38.0"
version = "1.39.2"
source = "registry+https://github.com/rust-lang/crates.io-index"
checksum = "ba4f4a02a7a80d6f274636f0aa95c7e383b912d41fe721a31f29e29698585a4a"
checksum = "daa4fb1bc778bd6f04cbfc4bb2d06a7396a8f299dc33ea1900cedaa316f467b1"
dependencies = [
"backtrace",
"bytes",
"libc",
"mio",
"num_cpus",
"mio 1.0.1",
"parking_lot 0.12.3",
"pin-project-lite",
"signal-hook-registry",
"socket2",
"tokio-macros",
"tracing",
"windows-sys 0.48.0",
"windows-sys 0.52.0",
]
[[package]]
@@ -9056,9 +9094,9 @@ dependencies = [
[[package]]
name = "tokio-macros"
version = "2.3.0"
version = "2.4.0"
source = "registry+https://github.com/rust-lang/crates.io-index"
checksum = "5f5ae998a069d4b5aba8ee9dad856af7d520c3699e6159b185c2acd48155d39a"
checksum = "693d596312e88961bc67d7f1f97af8a70227d9f90c31bba5806eec004978d752"
dependencies = [
"proc-macro2",
"quote",
@@ -10038,6 +10076,7 @@ dependencies = [
name = "wasm-utils"
version = "0.1.0"
dependencies = [
"console_error_panic_hook",
"futures",
"getrandom",
"gloo-net",
+9 -8
View File
@@ -52,6 +52,8 @@ members = [
"common/ecash-time",
"common/execute",
"common/exit-policy",
"common/gateway-requests",
"common/gateway-storage",
"common/http-api-client",
"common/http-api-common",
"common/inclusion-probability",
@@ -96,7 +98,6 @@ members = [
"explorer-api/explorer-api-requests",
"explorer-api/explorer-client",
"gateway",
"gateway/gateway-requests",
"integrations/bity",
"mixnode",
"sdk/lib/socks5-listener",
@@ -139,7 +140,7 @@ default-members = [
"tools/nymvisor",
"explorer-api",
"nym-validator-rewarder",
"nym-node"
"nym-node",
]
exclude = [
@@ -290,11 +291,11 @@ tar = "0.4.40"
tempfile = "3.5.0"
thiserror = "1.0.48"
time = "0.3.30"
tokio = "1.33.0"
tokio-stream = "0.1.14"
tokio-test = "0.4.2"
tokio = "1.39"
tokio-stream = "0.1.15"
tokio-test = "0.4.4"
tokio-tungstenite = { version = "0.20.1" }
tokio-util = "0.7.10"
tokio-util = "0.7.11"
toml = "0.8.14"
tower = "0.4.13"
tower-http = "0.5.2"
@@ -346,8 +347,8 @@ bip32 = { version = "0.5.1", default-features = false }
# plus response message parsing (which is, as of the time of writing this message, waiting to get merged)
#cosmrs = { path = "../cosmos-rust-fork/cosmos-rust/cosmrs" }
cosmrs = { git = "https://github.com/cosmos/cosmos-rust", rev = "4b1332e6d8258ac845cef71589c8d362a669675a" } # unfortuntely we need a fork by yours truly to get the staking support
tendermint = "0.37.0" # same version as used by cosmrs
tendermint-rpc = "0.37.0" # same version as used by cosmrs
tendermint = "0.37.0" # same version as used by cosmrs
tendermint-rpc = "0.37.0" # same version as used by cosmrs
prost = { version = "0.12", default-features = false }
# wasm-related dependencies
+23 -7
View File
@@ -1,6 +1,6 @@
[package]
name = "nym-client"
version = "1.1.37"
version = "1.1.39"
authors = ["Dave Hrycyszyn <futurechimp@users.noreply.github.com>", "Jędrzej Stuczyński <andrew@nymtech.net>"]
description = "Implementation of the Nym Client"
edition = "2021"
@@ -26,30 +26,46 @@ clap = { workspace = true, features = ["cargo", "derive"] }
dirs = { workspace = true }
log = { workspace = true } # self explanatory
rand = { workspace = true }
serde = { workspace = true, features = ["derive"] } # for config serialization/deserialization
serde = { workspace = true, features = [
"derive",
] } # for config serialization/deserialization
serde_json = { workspace = true }
thiserror = { workspace = true }
tap = { workspace = true }
time = { workspace = true }
tokio = { workspace = true, features = ["rt-multi-thread", "net", "signal"] } # async runtime
tokio = { workspace = true, features = [
"rt-multi-thread",
"net",
"signal",
] } # async runtime
tokio-tungstenite = { workspace = true }
zeroize = { workspace = true }
## internal
nym-bandwidth-controller = { path = "../../common/bandwidth-controller" }
nym-bin-common = { path = "../../common/bin-common", features = ["output_format", "clap"] }
nym-client-core = { path = "../../common/client-core", features = ["fs-surb-storage", "fs-gateways-storage", "cli"] }
nym-bin-common = { path = "../../common/bin-common", features = [
"output_format",
"clap",
] }
nym-client-core = { path = "../../common/client-core", features = [
"fs-credentials-storage",
"fs-surb-storage",
"fs-gateways-storage",
"cli",
] }
nym-config = { path = "../../common/config" }
nym-credential-storage = { path = "../../common/credential-storage" }
nym-credentials = { path = "../../common/credentials" }
nym-crypto = { path = "../../common/crypto" }
nym-gateway-requests = { path = "../../gateway/gateway-requests" }
nym-gateway-requests = { path = "../../common/gateway-requests" }
nym-network-defaults = { path = "../../common/network-defaults" }
nym-sphinx = { path = "../../common/nymsphinx" }
nym-pemstore = { path = "../../common/pemstore" }
nym-task = { path = "../../common/task" }
nym-topology = { path = "../../common/topology" }
nym-validator-client = { path = "../../common/client-libs/validator-client", features = ["http-client"] }
nym-validator-client = { path = "../../common/client-libs/validator-client", features = [
"http-client",
] }
nym-client-websocket-requests = { path = "websocket-requests" }
nym-id = { path = "../../common/nym-id" }
+1 -1
View File
@@ -422,7 +422,7 @@ impl Handler {
) {
// We don't want a crash in the connection handler to trigger a shutdown of the whole
// process.
task_client.mark_as_success();
task_client.disarm();
let ws_stream = match accept_async(socket).await {
Ok(ws_stream) => ws_stream,
+18 -6
View File
@@ -1,6 +1,6 @@
[package]
name = "nym-socks5-client"
version = "1.1.37"
version = "1.1.39"
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"
@@ -11,7 +11,9 @@ license.workspace = true
bs58 = { workspace = true }
clap = { workspace = true, features = ["cargo", "derive"] }
log = { workspace = true }
serde = { workspace = true, features = ["derive"] } # for config serialization/deserialization
serde = { workspace = true, features = [
"derive",
] } # for config serialization/deserialization
serde_json = { workspace = true }
tap = { workspace = true }
thiserror = { workspace = true }
@@ -22,13 +24,21 @@ url = { workspace = true }
zeroize = { workspace = true }
# internal
nym-bin-common = { path = "../../common/bin-common", features = ["output_format"] }
nym-client-core = { path = "../../common/client-core", features = ["fs-surb-storage", "fs-gateways-storage", "cli"] }
nym-bin-common = { path = "../../common/bin-common", features = [
"output_format",
"clap",
] }
nym-client-core = { path = "../../common/client-core", features = [
"fs-credentials-storage",
"fs-surb-storage",
"fs-gateways-storage",
"cli",
] }
nym-config = { path = "../../common/config" }
nym-credential-storage = { path = "../../common/credential-storage" }
nym-credentials = { path = "../../common/credentials" }
nym-crypto = { path = "../../common/crypto" }
nym-gateway-requests = { path = "../../gateway/gateway-requests" }
nym-gateway-requests = { path = "../../common/gateway-requests" }
nym-id = { path = "../../common/nym-id" }
nym-network-defaults = { path = "../../common/network-defaults" }
nym-ordered-buffer = { path = "../../common/socks5/ordered-buffer" }
@@ -36,7 +46,9 @@ nym-pemstore = { path = "../../common/pemstore" }
nym-socks5-client-core = { path = "../../common/socks5-client-core" }
nym-sphinx = { path = "../../common/nymsphinx" }
nym-topology = { path = "../../common/topology" }
nym-validator-client = { path = "../../common/client-libs/validator-client", features = ["http-client"] }
nym-validator-client = { path = "../../common/client-libs/validator-client", features = [
"http-client",
] }
[features]
default = []
@@ -8,6 +8,7 @@ use nym_credential_storage::storage::Storage;
use nym_credentials::ecash::bandwidth::IssuanceTicketBook;
use nym_credentials::ecash::utils::obtain_aggregate_wallet;
use nym_credentials::IssuedTicketBook;
use nym_credentials_interface::TicketType;
use nym_crypto::asymmetric::identity;
use nym_ecash_time::{ecash_default_expiration_date, Date};
use nym_validator_client::coconut::all_ecash_api_clients;
@@ -22,6 +23,7 @@ pub async fn make_deposit<C>(
client: &C,
client_id: &[u8],
expiration: Option<Date>,
ticketbook_type: TicketType,
) -> Result<IssuanceTicketBook, BandwidthControllerError>
where
C: EcashSigningClient + EcashQueryClient + Sync,
@@ -48,6 +50,7 @@ where
deposit_id,
client_id,
signing_key,
ticketbook_type,
expiration,
))
}
+6 -2
View File
@@ -38,7 +38,7 @@ nym-country-group = { path = "../country-group" }
nym-crypto = { path = "../crypto" }
nym-explorer-client = { path = "../../explorer-api/explorer-client" }
nym-gateway-client = { path = "../client-libs/gateway-client" }
nym-gateway-requests = { path = "../../gateway/gateway-requests" }
nym-gateway-requests = { path = "../gateway-requests" }
nym-metrics = { path = "../nym-metrics" }
nym-nonexhaustive-delayqueue = { path = "../nonexhaustive-delayqueue" }
nym-sphinx = { path = "../nymsphinx" }
@@ -46,9 +46,12 @@ nym-pemstore = { path = "../pemstore" }
nym-topology = { path = "../topology", features = ["serializable"] }
nym-validator-client = { path = "../client-libs/validator-client", default-features = false }
nym-task = { path = "../task" }
nym-credentials-interface = { path = "../credentials-interface" }
nym-credential-storage = { path = "../credential-storage" }
nym-network-defaults = { path = "../network-defaults" }
nym-client-core-config-types = { path = "./config-types", features = ["disk-persistence"] }
nym-client-core-config-types = { path = "./config-types", features = [
"disk-persistence",
] }
nym-client-core-surb-storage = { path = "./surb-storage" }
nym-client-core-gateways-storage = { path = "./gateways-storage" }
nym-ecash-time = { path = "../ecash-time" }
@@ -115,6 +118,7 @@ tempfile = { workspace = true }
[features]
default = []
cli = ["clap", "comfy-table"]
fs-credentials-storage = ["nym-credential-storage/persistent-storage"]
fs-surb-storage = ["nym-client-core-surb-storage/fs-surb-storage"]
fs-gateways-storage = ["nym-client-core-gateways-storage/fs-gateways-storage"]
wasm = ["nym-gateway-client/wasm"]
@@ -18,7 +18,7 @@ url.workspace = true
zeroize = { workspace = true, features = ["zeroize_derive"] }
nym-crypto = { path = "../../crypto", features = ["asymmetric"] }
nym-gateway-requests = { path = "../../../gateway/gateway-requests" }
nym-gateway-requests = { path = "../../gateway-requests" }
[target."cfg(not(target_arch = \"wasm32\"))".dependencies.sqlx]
workspace = true
@@ -27,7 +27,12 @@ optional = true
[build-dependencies]
tokio = { workspace = true, features = ["rt-multi-thread", "macros"] }
sqlx = { workspace = true, features = ["runtime-tokio-rustls", "sqlite", "macros", "migrate"] }
sqlx = { workspace = true, features = [
"runtime-tokio-rustls",
"sqlite",
"macros",
"migrate",
] }
[features]
fs-gateways-storage = ["sqlx"]
fs-gateways-storage = ["sqlx"]
@@ -5,14 +5,15 @@ use crate::cli_helpers::{CliClient, CliClientConfig};
use crate::error::ClientCoreError;
use nym_credential_storage::models::BasicTicketbookInformation;
use nym_credential_storage::storage::Storage;
use nym_credentials_interface::TicketType;
use nym_ecash_time::ecash_today;
use nym_network_defaults::TicketbookType::MixnetEntry;
use serde::{Deserialize, Serialize};
use time::Date;
#[derive(Serialize, Deserialize)]
pub struct AvailableTicketbook {
pub id: i64,
pub typ: TicketType,
pub expiration: Date,
pub issued_tickets: u32,
pub claimed_tickets: u32,
@@ -45,6 +46,7 @@ impl AvailableTicketbook {
vec![
comfy_table::Cell::new(self.id.to_string()),
comfy_table::Cell::new(self.typ),
expiration,
comfy_table::Cell::new(format!("{issued} ({si_issued})")),
comfy_table::Cell::new(format!("{claimed} ({si_claimed})")),
@@ -55,17 +57,22 @@ impl AvailableTicketbook {
}
}
impl From<BasicTicketbookInformation> for AvailableTicketbook {
fn from(value: BasicTicketbookInformation) -> Self {
AvailableTicketbook {
impl TryFrom<BasicTicketbookInformation> for AvailableTicketbook {
type Error = ClientCoreError;
fn try_from(value: BasicTicketbookInformation) -> Result<Self, Self::Error> {
let typ = value
.ticketbook_type
.parse()
.map_err(|_| ClientCoreError::UnknownTicketType)?;
Ok(AvailableTicketbook {
id: value.id,
typ,
expiration: value.expiration_date,
issued_tickets: value.total_tickets,
claimed_tickets: value.used_tickets,
// TODO: this will change when 'type' field is introduced; for now doesn't matter what we put there
ticket_size: MixnetEntry.bandwidth_value(),
}
ticket_size: typ.to_repr().bandwidth_value(),
})
}
}
@@ -79,6 +86,7 @@ impl std::fmt::Display for AvailableTicketbooks {
let mut table = comfy_table::Table::new();
table.set_header(vec![
"id",
"type",
"expiration",
"issued tickets (bandwidth)",
"claimed tickets (bandwidth)",
@@ -124,6 +132,9 @@ where
})?;
Ok(AvailableTicketbooks(
ticketbooks.into_iter().map(Into::into).collect(),
ticketbooks
.into_iter()
.map(TryInto::<AvailableTicketbook>::try_into)
.collect::<Result<_, _>>()?,
))
}
@@ -455,7 +455,7 @@ where
Err(ClientCoreError::CustomGatewaySelectionExpected)
} else {
// and make sure to invalidate the task client so we wouldn't cause premature shutdown
shutdown.mark_as_success();
shutdown.disarm();
custom_gateway_transceiver.set_packet_router(packet_router)?;
Ok(custom_gateway_transceiver)
};
@@ -562,7 +562,7 @@ where
if topology_config.disable_refreshing {
// if we're not spawning the refresher, don't cause shutdown immediately
info!("The topology refesher is not going to be started");
shutdown.mark_as_success();
shutdown.disarm();
} else {
// don't spawn the refresher if we don't want to be refreshing the topology.
// only use the initial values obtained
@@ -23,7 +23,7 @@ use crate::{
config::{self, disk_persistence::CommonClientPaths},
error::ClientCoreError,
};
#[cfg(all(not(target_arch = "wasm32"), feature = "fs-surb-storage"))]
#[cfg(all(not(target_arch = "wasm32"), feature = "fs-credentials-storage"))]
use nym_credential_storage::persistent_storage::PersistentStorage as PersistentCredentialStorage;
pub use nym_client_core_gateways_storage as gateways_storage;
@@ -474,13 +474,6 @@ where
Poll::Ready(Some((real_messages, conn_id))) => {
log::trace!("handling real_messages: size: {}", real_messages.len());
// This is the last step in the pipeline where we know the type of the message, so
// lets count the number of retransmissions here.
if conn_id == TransmissionLane::Retransmission {
self.stats_tx
.report(PacketStatisticsEvent::RetransmissionQueued);
}
// First store what we got for the given connection id
self.transmission_buffer.store(&conn_id, real_messages);
let real_next = self.pop_next_message().expect("we just added one");
+3
View File
@@ -68,6 +68,9 @@ pub enum ClientCoreError {
source: Box<dyn Error + Send + Sync>,
},
#[error("the provided ticket type is invalid")]
UnknownTicketType,
#[error("the gateway id is invalid - {0}")]
UnableToCreatePublicKeyFromGatewayId(Ed25519RecoveryError),
+40 -18
View File
@@ -46,13 +46,34 @@ const MEASUREMENTS: usize = 3;
const CONN_TIMEOUT: Duration = Duration::from_millis(1500);
const PING_TIMEOUT: Duration = Duration::from_millis(1000);
struct GatewayWithLatency<'a> {
gateway: &'a gateway::Node,
// The abstraction that some of these helpers use
pub trait ConnectableGateway {
fn identity(&self) -> &identity::PublicKey;
fn clients_address(&self) -> String;
fn is_wss(&self) -> bool;
}
impl ConnectableGateway for gateway::Node {
fn identity(&self) -> &identity::PublicKey {
self.identity()
}
fn clients_address(&self) -> String {
self.clients_address()
}
fn is_wss(&self) -> bool {
self.clients_wss_port.is_some()
}
}
struct GatewayWithLatency<'a, G: ConnectableGateway> {
gateway: &'a G,
latency: Duration,
}
impl<'a> GatewayWithLatency<'a> {
fn new(gateway: &'a gateway::Node, latency: Duration) -> Self {
impl<'a, G: ConnectableGateway> GatewayWithLatency<'a, G> {
fn new(gateway: &'a G, latency: Duration) -> Self {
GatewayWithLatency { gateway, latency }
}
}
@@ -130,11 +151,14 @@ async fn connect(endpoint: &str) -> Result<WsConn, ClientCoreError> {
JSWebsocket::new(endpoint).map_err(|_| ClientCoreError::GatewayJsConnectionFailure)
}
async fn measure_latency(gateway: &gateway::Node) -> Result<GatewayWithLatency, ClientCoreError> {
async fn measure_latency<G>(gateway: &G) -> Result<GatewayWithLatency<G>, ClientCoreError>
where
G: ConnectableGateway,
{
let addr = gateway.clients_address();
trace!(
"establishing connection to {} ({addr})...",
gateway.identity_key,
gateway.identity(),
);
let mut stream = connect(&addr).await?;
@@ -177,7 +201,7 @@ async fn measure_latency(gateway: &gateway::Node) -> Result<GatewayWithLatency,
let count = results.len() as u64;
if count == 0 {
return Err(ClientCoreError::NoGatewayMeasurements {
identity: gateway.identity_key.to_base58_string(),
identity: gateway.identity().to_base58_string(),
});
}
@@ -187,11 +211,11 @@ async fn measure_latency(gateway: &gateway::Node) -> Result<GatewayWithLatency,
Ok(GatewayWithLatency::new(gateway, avg))
}
pub async fn choose_gateway_by_latency<R: Rng>(
pub async fn choose_gateway_by_latency<'a, R: Rng, G: ConnectableGateway + Clone>(
rng: &mut R,
gateways: &[gateway::Node],
gateways: &[G],
must_use_tls: bool,
) -> Result<gateway::Node, ClientCoreError> {
) -> Result<G, ClientCoreError> {
let gateways = filter_by_tls(gateways, must_use_tls)?;
info!(
@@ -223,21 +247,19 @@ pub async fn choose_gateway_by_latency<R: Rng>(
info!(
"chose gateway {} with average latency of {:?}",
chosen.gateway.identity_key, chosen.latency
chosen.gateway.identity(),
chosen.latency
);
Ok(chosen.gateway.clone())
}
fn filter_by_tls(
gateways: &[gateway::Node],
fn filter_by_tls<G: ConnectableGateway>(
gateways: &[G],
must_use_tls: bool,
) -> Result<Vec<&gateway::Node>, ClientCoreError> {
) -> Result<Vec<&G>, ClientCoreError> {
if must_use_tls {
let filtered = gateways
.iter()
.filter(|g| g.clients_wss_port.is_some())
.collect::<Vec<_>>();
let filtered = gateways.iter().filter(|g| g.is_wss()).collect::<Vec<_>>();
if filtered.is_empty() {
return Err(ClientCoreError::NoWssGateways);
+2
View File
@@ -2,7 +2,9 @@ use std::future::Future;
#[cfg(all(
not(target_arch = "wasm32"),
feature = "cli",
feature = "fs-surb-storage",
feature = "fs-credentials-storage",
feature = "fs-gateways-storage"
))]
pub mod cli_helpers;
+1 -1
View File
@@ -24,7 +24,7 @@ nym-bandwidth-controller = { path = "../../bandwidth-controller" }
nym-credentials = { path = "../../credentials" }
nym-credential-storage = { path = "../../credential-storage" }
nym-crypto = { path = "../../crypto" }
nym-gateway-requests = { path = "../../../gateway/gateway-requests" }
nym-gateway-requests = { path = "../../gateway-requests" }
nym-network-defaults = { path = "../../network-defaults" }
nym-sphinx = { path = "../../nymsphinx" }
nym-pemstore = { path = "../../pemstore" }
@@ -2,7 +2,7 @@
// SPDX-License-Identifier: Apache-2.0
use crate::error::GatewayClientError;
use nym_network_defaults::TicketbookType::MixnetEntry;
use nym_network_defaults::TicketTypeRepr::V1MixnetEntry;
use si_scale::helpers::bibytes2;
use std::time::Duration;
@@ -103,7 +103,7 @@ impl BandwidthTickets {
// 20% of entry ticket value
pub const DEFAULT_REMAINING_BANDWIDTH_THRESHOLD: i64 =
(MixnetEntry.bandwidth_value() / 5) as i64;
(V1MixnetEntry.bandwidth_value() / 5) as i64;
pub const DEFAULT_CUTOFF_REMAINING_BANDWIDTH_THRESHOLD: Option<i64> = None;
@@ -70,8 +70,8 @@ impl PacketRouter {
Ok(())
}
pub fn mark_as_success(&mut self) {
self.shutdown.mark_as_success();
pub fn disarm(&mut self) {
self.shutdown.disarm();
}
}
@@ -113,8 +113,8 @@ impl PartiallyDelegatedRouter {
let return_res = match ret {
Err(err) => self.stream_return.send(Err(err)),
Ok(_) => {
self.packet_router.mark_as_success();
task_client.mark_as_success();
self.packet_router.disarm();
task_client.disarm();
self.stream_return.send(Ok(split_stream))
}
};
@@ -23,8 +23,8 @@ use nym_api_requests::ecash::VerificationKeyResponse;
pub use nym_api_requests::{
ecash::{
models::{
EpochCredentialsResponse, IssuedCredential, IssuedCredentialBody,
IssuedCredentialResponse, IssuedCredentialsResponse, SpentCredentialsResponse,
EpochCredentialsResponse, IssuedCredentialResponse, IssuedCredentialsResponse,
IssuedTicketbook, IssuedTicketbookBody, SpentCredentialsResponse,
},
BlindSignRequestBody, BlindedSignatureResponse, CredentialsRequestBody,
PartialCoinIndicesSignatureResponse, PartialExpirationDateSignatureResponse,
@@ -683,6 +683,24 @@ pub trait MixnetSigningClient {
.await
}
async fn migrate_vested_mixnode(&self, fee: Option<Fee>) -> Result<ExecuteResult, NyxdError> {
self.execute_mixnet_contract(fee, MixnetExecuteMsg::MigrateVestedMixNode {}, vec![])
.await
}
async fn migrate_vested_delegation(
&self,
mix_id: MixId,
fee: Option<Fee>,
) -> Result<ExecuteResult, NyxdError> {
self.execute_mixnet_contract(
fee,
MixnetExecuteMsg::MigrateVestedDelegation { mix_id },
vec![],
)
.await
}
#[cfg(feature = "contract-testing")]
async fn testing_resolve_all_pending_events(
&self,
@@ -928,6 +946,12 @@ mod tests {
MixnetExecuteMsg::WithdrawDelegatorRewardOnBehalf { mix_id, owner } => client
.withdraw_delegator_reward_on_behalf(owner.parse().unwrap(), mix_id, None)
.ignore(),
MixnetExecuteMsg::MigrateVestedMixNode { .. } => {
client.migrate_vested_mixnode(None).ignore()
}
MixnetExecuteMsg::MigrateVestedDelegation { mix_id } => {
client.migrate_vested_delegation(mix_id, None).ignore()
}
#[cfg(feature = "contract-testing")]
MixnetExecuteMsg::TestingResolveAllPendingEvents { .. } => {
@@ -437,6 +437,7 @@ where
mod tests {
use super::*;
use crate::nyxd::contract_traits::tests::{mock_coin, IgnoreValue};
use nym_vesting_contract_common::ExecuteMsg;
// it's enough that this compiles and clippy is happy about it
#[allow(dead_code)]
@@ -560,6 +561,9 @@ mod tests {
VestingExecuteMsg::UpdateLockedPledgeCap { address, cap } => client
.update_locked_pledge_cap(address.parse().unwrap(), cap, None)
.ignore(),
// those will never be manually called by clients
ExecuteMsg::TrackMigratedMixnode { .. } => "explicitly_ignored".ignore(),
ExecuteMsg::TrackMigratedDelegation { .. } => "explicitly_ignored".ignore(),
};
}
}
@@ -1,6 +1,11 @@
// Copyright 2021 - Nym Technologies SA <contact@nymtech.net>
// SPDX-License-Identifier: Apache-2.0
// TEMPORARY WORKAROUND:
// those features are expected as the below should only get activated whenever
// the corresponding features in tendermint-rpc are enabled transitively
#![allow(unexpected_cfgs)]
use crate::nyxd::cosmwasm_client::client_traits::SigningCosmWasmClient;
use crate::nyxd::error::NyxdError;
use crate::nyxd::{Config, GasPrice, Hash, Height};
@@ -1,6 +1,11 @@
// Copyright 2021 - Nym Technologies SA <contact@nymtech.net>
// SPDX-License-Identifier: Apache-2.0
// TEMPORARY WORKAROUND:
// those features are expected as the below should only get activated whenever
// the corresponding features in tendermint-rpc are enabled transitively
#![allow(unexpected_cfgs)]
use crate::nyxd::contract_traits::{NymContractsProvider, TypedNymContracts};
use crate::nyxd::cosmwasm_client::types::{
ChangeAdminResult, ContractCodeId, ExecuteResult, InstantiateOptions, InstantiateResult,
@@ -1,6 +1,11 @@
// Copyright 2023 - Nym Technologies SA <contact@nymtech.net>
// SPDX-License-Identifier: Apache-2.0
// TEMPORARY WORKAROUND:
// those features are expected as the below should only get activated whenever
// the corresponding features in tendermint-rpc are enabled transitively
#![allow(unexpected_cfgs)]
use async_trait::async_trait;
use cosmrs::tendermint::{self, abci, block::Height, evidence::Evidence, Genesis, Hash};
use serde::{de::DeserializeOwned, Serialize};
@@ -7,11 +7,16 @@ use anyhow::bail;
use clap::Parser;
use nym_credential_storage::initialise_persistent_storage;
use nym_credential_utils::utils;
use nym_credentials_interface::TicketType;
use nym_crypto::asymmetric::identity;
use std::path::PathBuf;
#[derive(Debug, Parser)]
pub struct Args {
/// Specify which type of ticketbook should be issued
#[clap(long, default_value_t = TicketType::default())]
pub(crate) ticketbook_type: TicketType,
/// Config file of the client that is supposed to use the credential.
#[clap(long)]
pub(crate) client_config: PathBuf,
@@ -39,7 +44,13 @@ pub async fn execute(args: Args, client: SigningClient) -> anyhow::Result<()> {
let persistent_storage = initialise_persistent_storage(credentials_store).await;
let private_id_key: identity::PrivateKey = nym_pemstore::load_key(private_id_key)?;
utils::issue_credential(&client, &persistent_storage, &private_id_key.to_bytes()).await?;
utils::issue_credential(
&client,
&persistent_storage,
&private_id_key.to_bytes(),
args.ticketbook_type,
)
.await?;
Ok(())
}
@@ -1,15 +1,26 @@
// Copyright 2022 - Nym Technologies SA <contact@nymtech.net>
// Copyright 2022-2024 - Nym Technologies SA <contact@nymtech.net>
// SPDX-License-Identifier: Apache-2.0
use clap::Parser;
use log::{debug, info};
use cosmwasm_std::Decimal;
use nym_mixnet_contract_common::{InitialRewardingParams, InstantiateMsg, Percent};
use nym_validator_client::nyxd::AccountId;
use log::{debug, info};
use nym_mixnet_contract_common::{
InitialRewardingParams, InstantiateMsg, OperatingCostRange, Percent, ProfitMarginRange,
};
use nym_network_defaults::mainnet::MIX_DENOM;
use nym_network_defaults::TOTAL_SUPPLY;
use nym_validator_client::nyxd::{AccountId, Coin};
use std::str::FromStr;
use std::time::Duration;
pub fn default_maximum_operating_cost() -> Coin {
Coin::new(TOTAL_SUPPLY, MIX_DENOM.base)
}
pub fn default_minimum_operating_cost() -> Coin {
Coin::new(0, MIX_DENOM.base)
}
#[derive(Debug, Parser)]
pub struct Args {
#[clap(long)]
@@ -50,6 +61,18 @@ pub struct Args {
#[clap(long, default_value_t = 240)]
pub active_set_size: u32,
#[clap(long, default_value_t = Percent::zero())]
pub minimum_profit_margin_percent: Percent,
#[clap(long, default_value_t = Percent::hundred())]
pub maximum_profit_margin_percent: Percent,
#[clap(long, default_value_t = default_minimum_operating_cost())]
pub minimum_interval_operating_cost: Coin,
#[clap(long, default_value_t = default_maximum_operating_cost())]
pub maximum_interval_operating_cost: Coin,
}
pub async fn generate(args: Args) {
@@ -97,6 +120,10 @@ pub async fn generate(args: Args) {
.expect("Rewarding (mix) denom has to be set")
});
if args.minimum_interval_operating_cost.denom != args.maximum_interval_operating_cost.denom {
panic!("different denoms for operating cost bounds")
}
let instantiate_msg = InstantiateMsg {
rewarding_validator_address: rewarding_validator_address.to_string(),
vesting_contract_address: vesting_contract_address.to_string(),
@@ -104,6 +131,14 @@ pub async fn generate(args: Args) {
epochs_in_interval: args.epochs_in_interval,
epoch_duration: Duration::from_secs(args.epoch_duration),
initial_rewarding_params,
profit_margin: ProfitMarginRange {
minimum: args.minimum_profit_margin_percent,
maximum: args.maximum_profit_margin_percent,
},
interval_operating_cost: OperatingCostRange {
minimum: args.minimum_interval_operating_cost.amount.into(),
maximum: args.maximum_interval_operating_cost.amount.into(),
},
};
debug!("instantiate_msg: {:?}", instantiate_msg);
@@ -0,0 +1,42 @@
// Copyright 2024 - Nym Technologies SA <contact@nymtech.net>
// SPDX-License-Identifier: Apache-2.0
use crate::context::SigningClient;
use clap::Parser;
use log::info;
use nym_mixnet_contract_common::MixId;
use nym_validator_client::nyxd::contract_traits::{MixnetQueryClient, MixnetSigningClient};
#[derive(Debug, Parser)]
pub struct Args {
#[clap(long)]
pub mix_id: Option<MixId>,
#[clap(long)]
pub identity_key: Option<String>,
}
pub async fn migrate_vested_delegation(args: Args, client: SigningClient) {
let mix_id = match args.mix_id {
Some(mix_id) => mix_id,
None => {
let identity_key = args
.identity_key
.expect("either mix_id or mix_identity has to be specified");
let node_details = client
.get_mixnode_details_by_identity(identity_key)
.await
.expect("contract query failed")
.mixnode_details
.expect("mixnode with the specified identity doesnt exist");
node_details.mix_id()
}
};
let res = client
.migrate_vested_delegation(mix_id, None)
.await
.expect("failed to migrate delegation!");
info!("migration result: {:?}", res)
}
@@ -7,6 +7,7 @@ pub mod rewards;
pub mod delegate_to_mixnode;
pub mod delegate_to_multiple_mixnodes;
pub mod migrate_vested_delegation;
pub mod query_for_delegations;
pub mod undelegate_from_mixnode;
pub mod vesting_delegate_to_mixnode;
@@ -35,4 +36,6 @@ pub enum MixnetDelegatorsCommands {
DelegateVesting(vesting_delegate_to_mixnode::Args),
/// Undelegate from a mixnode (when originally using locked tokens)
UndelegateVesting(vesting_undelegate_from_mixnode::Args),
/// Migrate the delegation to use liquid tokens
MigrateVestedDelegation(migrate_vested_delegation::Args),
}
@@ -96,6 +96,7 @@ async fn print_delegation_events(events: Vec<PendingEpochEvent>, client: &Signin
mix_id,
amount,
proxy,
..
} => {
if owner.as_str() == client.nyxd.address().as_ref() {
table.add_row(vec![
@@ -111,6 +112,7 @@ async fn print_delegation_events(events: Vec<PendingEpochEvent>, client: &Signin
owner,
mix_id,
proxy,
..
} => {
if owner.as_str() == client.nyxd.address().as_ref() {
table.add_row(vec![
@@ -8,7 +8,7 @@ use cosmwasm_std::Coin;
use nym_bin_common::output_format::OutputFormat;
use nym_mixnet_contract_common::construct_gateway_bonding_sign_payload;
use nym_network_defaults::{DEFAULT_CLIENT_LISTENING_PORT, DEFAULT_MIX_LISTENING_PORT};
use nym_validator_client::nyxd::contract_traits::{MixnetQueryClient, NymContractsProvider};
use nym_validator_client::nyxd::contract_traits::MixnetQueryClient;
#[derive(Debug, Parser)]
pub struct Args {
@@ -39,10 +39,6 @@ pub struct Args {
)]
pub amount: u128,
/// Indicates whether the gateway is going to get bonded via a vesting account
#[arg(long)]
pub with_vesting_account: bool,
#[clap(short, long, default_value_t = OutputFormat::default())]
output: OutputFormat,
}
@@ -74,15 +70,8 @@ pub async fn create_payload(args: Args, client: SigningClient) {
};
let address = account_id_to_cw_addr(&client.address());
let proxy = if args.with_vesting_account {
Some(account_id_to_cw_addr(
client.vesting_contract_address().unwrap(),
))
} else {
None
};
let payload = construct_gateway_bonding_sign_payload(nonce, address, proxy, coin, gateway);
let payload = construct_gateway_bonding_sign_payload(nonce, address, coin, gateway);
let wrapper = DataWrapper::new(payload.to_base58_string().unwrap());
println!("{}", args.output.format(&wrapper))
}
@@ -5,33 +5,21 @@ use crate::context::SigningClient;
use clap::Parser;
use log::info;
use nym_validator_client::nyxd::contract_traits::MixnetSigningClient;
use nym_validator_client::nyxd::contract_traits::VestingSigningClient;
#[derive(Debug, Parser)]
pub struct Args {
/// Label that is going to be used for creating the family
#[arg(long)]
pub family_label: String,
/// Indicates whether the family is going to get created via a vesting account
#[arg(long)]
pub with_vesting_account: bool,
}
pub async fn create_family(args: Args, client: SigningClient) {
info!("Create family");
let res = if args.with_vesting_account {
client
.vesting_create_family(args.family_label, None)
.await
.expect("failed to create family with vesting account")
} else {
client
.create_family(args.family_label, None)
.await
.expect("failed to create family")
};
let res = client
.create_family(args.family_label, None)
.await
.expect("failed to create family");
info!("Family creation result: {:?}", res);
}
@@ -2,7 +2,7 @@
// SPDX-License-Identifier: Apache-2.0
use crate::context::QueryClient;
use crate::utils::{account_id_to_cw_addr, DataWrapper};
use crate::utils::DataWrapper;
use clap::Parser;
use cosmrs::AccountId;
use log::info;
@@ -10,7 +10,7 @@ use nym_bin_common::output_format::OutputFormat;
use nym_crypto::asymmetric::identity;
use nym_mixnet_contract_common::construct_family_join_permit;
use nym_mixnet_contract_common::families::FamilyHead;
use nym_validator_client::nyxd::contract_traits::{MixnetQueryClient, NymContractsProvider};
use nym_validator_client::nyxd::contract_traits::MixnetQueryClient;
#[derive(Debug, Parser)]
pub struct Args {
@@ -18,10 +18,6 @@ pub struct Args {
#[arg(long)]
pub address: AccountId,
/// Indicates whether the member joining the family is going to use the vesting account for joining.
#[arg(long)]
pub with_vesting_account: bool,
// might as well validate the value when parsing the arguments
/// Identity of the member for whom we're issuing the permit
#[arg(long)]
@@ -68,18 +64,9 @@ pub async fn create_family_join_permit_sign_payload(args: Args, client: QueryCli
}
};
// let address = account_id_to_cw_addr(&args.address);
let proxy = if args.with_vesting_account {
Some(account_id_to_cw_addr(
client.vesting_contract_address().unwrap(),
))
} else {
None
};
let head = FamilyHead::new(mixnode.bond_information.identity());
let payload = construct_family_join_permit(nonce, head, proxy, args.member.to_base58_string());
let payload = construct_family_join_permit(nonce, head, args.member.to_base58_string());
let wrapper = DataWrapper::new(payload.to_base58_string().unwrap());
println!("{}", args.output.format(&wrapper))
}
@@ -8,7 +8,6 @@ use nym_contracts_common::signing::MessageSignature;
use nym_crypto::asymmetric::identity;
use nym_mixnet_contract_common::families::FamilyHead;
use nym_validator_client::nyxd::contract_traits::MixnetSigningClient;
use nym_validator_client::nyxd::contract_traits::VestingSigningClient;
#[derive(Debug, Parser)]
pub struct Args {
@@ -16,10 +15,6 @@ pub struct Args {
#[arg(long)]
pub family_head: identity::PublicKey,
/// Indicates whether the member joining the family is going to do so via the vesting contract
#[arg(long)]
pub with_vesting_account: bool,
/// Permission, as provided by the family head, for joining the family
#[arg(long)]
pub join_permit: MessageSignature,
@@ -30,17 +25,10 @@ pub async fn join_family(args: Args, client: SigningClient) {
let family_head = FamilyHead::new(args.family_head.to_base58_string());
let res = if args.with_vesting_account {
client
.vesting_join_family(args.join_permit, family_head, None)
.await
.expect("failed to join family with vesting account")
} else {
client
.join_family(args.join_permit, family_head, None)
.await
.expect("failed to join family")
};
let res = client
.join_family(args.join_permit, family_head, None)
.await
.expect("failed to join family");
info!("Family join result: {:?}", res);
}
@@ -7,17 +7,12 @@ use log::info;
use nym_crypto::asymmetric::identity;
use nym_mixnet_contract_common::families::FamilyHead;
use nym_validator_client::nyxd::contract_traits::MixnetSigningClient;
use nym_validator_client::nyxd::contract_traits::VestingSigningClient;
#[derive(Debug, Parser)]
pub struct Args {
/// The head of the family that we intend to leave
#[arg(long)]
pub family_head: identity::PublicKey,
/// Indicates whether we joined the family via the vesting contract
#[arg(long)]
pub with_vesting_account: bool,
}
pub async fn leave_family(args: Args, client: SigningClient) {
@@ -25,17 +20,10 @@ pub async fn leave_family(args: Args, client: SigningClient) {
let family_head = FamilyHead::new(args.family_head.to_base58_string());
let res = if args.with_vesting_account {
client
.vesting_leave_family(family_head, None)
.await
.expect("failed to leave family with vesting account")
} else {
client
.leave_family(family_head, None)
.await
.expect("failed to leave family")
};
let res = client
.leave_family(family_head, None)
.await
.expect("failed to leave family");
info!("Family leave result: {:?}", res);
}
@@ -0,0 +1,19 @@
// Copyright 2024 - Nym Technologies SA <contact@nymtech.net>
// SPDX-License-Identifier: Apache-2.0
use crate::context::SigningClient;
use clap::Parser;
use log::info;
use nym_validator_client::nyxd::contract_traits::MixnetSigningClient;
#[derive(Debug, Parser)]
pub struct Args {}
pub async fn migrate_vested_mixnode(_args: Args, client: SigningClient) {
let res = client
.migrate_vested_mixnode(None)
.await
.expect("failed to migrate mixnode!");
info!("migration result: {:?}", res)
}
@@ -11,7 +11,7 @@ use nym_mixnet_contract_common::{construct_mixnode_bonding_sign_payload, MixNode
use nym_network_defaults::{
DEFAULT_HTTP_API_LISTENING_PORT, DEFAULT_MIX_LISTENING_PORT, DEFAULT_VERLOC_LISTENING_PORT,
};
use nym_validator_client::nyxd::contract_traits::{MixnetQueryClient, NymContractsProvider};
use nym_validator_client::nyxd::contract_traits::MixnetQueryClient;
use nym_validator_client::nyxd::CosmWasmCoin;
#[derive(Debug, Parser)]
@@ -52,10 +52,6 @@ pub struct Args {
)]
pub amount: u128,
/// Indicates whether the mixnode is going to get bonded via a vesting account
#[arg(long)]
pub with_vesting_account: bool,
#[clap(short, long, default_value_t = OutputFormat::default())]
output: OutputFormat,
}
@@ -100,16 +96,9 @@ pub async fn create_payload(args: Args, client: SigningClient) {
};
let address = account_id_to_cw_addr(&client.address());
let proxy = if args.with_vesting_account {
Some(account_id_to_cw_addr(
client.vesting_contract_address().unwrap(),
))
} else {
None
};
let payload =
construct_mixnode_bonding_sign_payload(nonce, address, proxy, coin, mixnode, cost_params);
construct_mixnode_bonding_sign_payload(nonce, address, coin, mixnode, cost_params);
let wrapper = DataWrapper::new(payload.to_base58_string().unwrap());
println!("{}", args.output.format(&wrapper))
}
@@ -7,6 +7,7 @@ pub mod bond_mixnode;
pub mod decrease_pledge;
pub mod families;
pub mod keys;
pub mod migrate_vested_mixnode;
pub mod mixnode_bonding_sign_payload;
pub mod pledge_more;
pub mod rewards;
@@ -52,4 +53,6 @@ pub enum MixnetOperatorsMixnodeCommands {
DecreasePledge(decrease_pledge::Args),
/// Decrease pledge with locked tokens
DecreasePledgeVesting(vesting_decrease_pledge::Args),
/// Migrate the mixnode to use liquid tokens
MigrateVestedNode(migrate_vested_mixnode::Args),
}
@@ -218,7 +218,6 @@ where
#[derive(Serialize)]
pub struct ContractMessageContent<T> {
pub sender: Addr,
pub proxy: Option<Addr>,
pub funds: Vec<Coin>,
pub data: T,
}
@@ -233,25 +232,17 @@ where
}
impl<T> ContractMessageContent<T> {
pub fn new(sender: Addr, proxy: Option<Addr>, funds: Vec<Coin>, data: T) -> Self {
pub fn new(sender: Addr, funds: Vec<Coin>, data: T) -> Self {
ContractMessageContent {
sender,
proxy,
funds,
data,
}
}
pub fn new_with_info(info: MessageInfo, signer: Addr, data: T) -> Self {
let proxy = if info.sender == signer {
None
} else {
Some(info.sender)
};
ContractMessageContent {
sender: signer,
proxy,
funds: info.funds,
data,
}
@@ -7,6 +7,5 @@ use cosmwasm_std::Coin;
#[cw_serde]
pub struct PoolCounters {
pub total_deposited: Coin,
pub total_redeemed_gateways: Coin,
pub total_redeemed_holding: Coin,
pub total_redeemed: Coin,
}
@@ -65,7 +65,6 @@ impl Delegation {
cumulative_reward_ratio: Decimal,
amount: Coin,
height: u64,
proxy: Option<Addr>,
) -> Self {
assert!(
amount.amount <= TOKEN_SUPPLY,
@@ -78,7 +77,7 @@ impl Delegation {
cumulative_reward_ratio,
amount,
height,
proxy,
proxy: None,
}
}
@@ -1,8 +1,9 @@
// Copyright 2022-2023 - Nym Technologies SA <contact@nymtech.net>
// SPDX-License-Identifier: Apache-2.0
use crate::{EpochEventId, EpochState, IdentityKey, MixId};
use crate::{EpochEventId, EpochState, IdentityKey, MixId, OperatingCostRange, ProfitMarginRange};
use contracts_common::signing::verifier::ApiVerifierError;
use contracts_common::Percent;
use cosmwasm_std::{Addr, Coin, Decimal, Uint128};
use thiserror::Error;
@@ -76,21 +77,11 @@ pub enum MixnetContractError {
#[error("Received multiple coin types during staking")]
MultipleDenoms,
#[error("Proxy address mismatch, expected {existing}, got {incoming}")]
ProxyMismatch { existing: String, incoming: String },
#[error("Proxy address ({received}) is not set to the vesting contract ({vesting_contract})")]
ProxyIsNotVestingContract {
received: Addr,
vesting_contract: Addr,
},
#[error(
"Sender of this message ({received}) is not the vesting contract ({vesting_contract})"
)]
SenderIsNotVestingContract {
received: Addr,
vesting_contract: Addr,
},
#[error("Failed to recover ed25519 public key from its base58 representation - {0}")]
MalformedEd25519IdentityKey(String),
@@ -239,6 +230,30 @@ pub enum MixnetContractError {
#[from]
source: ApiVerifierError,
},
#[error("this operation is no longer allowed to be performed with vesting tokens. please move them to your liquid balance and try again")]
DisabledVestingOperation,
#[error(
"this mixnode has not been bonded with the vesting tokens or has already been migrated"
)]
NotAVestingMixnode,
#[error("this delegation has not been performed with the vesting tokens or has already been migrated")]
NotAVestingDelegation,
#[error("the provided profit margin ({provided}) is outside the allowed range: {range}")]
ProfitMarginOutsideRange {
provided: Percent,
range: ProfitMarginRange,
},
#[error("the provided interval operating cost ({provided}{denom}) is outside the allowed range: {range}")]
OperatingCostOutsideRange {
denom: String,
provided: Uint128,
range: OperatingCostRange,
},
}
impl MixnetContractError {
@@ -103,7 +103,6 @@ impl Display for MixnetEventType {
// attributes that are used in multiple places
pub const OWNER_KEY: &str = "owner";
pub const AMOUNT_KEY: &str = "amount";
pub const PROXY_KEY: &str = "proxy";
// event-specific attributes
@@ -163,7 +162,6 @@ pub const NEW_EPOCHS_IN_INTERVAL: &str = "new_epochs_in_interval";
pub fn new_delegation_event(
created_at: BlockHeight,
delegator: &Addr,
proxy: &Option<Addr>,
amount: &Coin,
mix_id: MixId,
unit_reward: Decimal,
@@ -171,58 +169,34 @@ pub fn new_delegation_event(
Event::new(MixnetEventType::Delegation)
.add_attribute(EVENT_CREATION_HEIGHT_KEY, created_at.to_string())
.add_attribute(DELEGATOR_KEY, delegator)
.add_optional_attribute(PROXY_KEY, proxy.as_ref())
.add_attribute(AMOUNT_KEY, amount.to_string())
.add_attribute(DELEGATION_TARGET_KEY, mix_id.to_string())
.add_attribute(UNIT_REWARD_KEY, unit_reward.to_string())
}
pub fn new_delegation_on_unbonded_node_event(
delegator: &Addr,
proxy: &Option<Addr>,
mix_id: MixId,
) -> Event {
pub fn new_delegation_on_unbonded_node_event(delegator: &Addr, mix_id: MixId) -> Event {
Event::new(MixnetEventType::Delegation)
.add_attribute(DELEGATOR_KEY, delegator)
.add_optional_attribute(PROXY_KEY, proxy.as_ref())
.add_attribute(DELEGATION_TARGET_KEY, mix_id.to_string())
}
pub fn new_pending_delegation_event(
delegator: &Addr,
proxy: &Option<Addr>,
amount: &Coin,
mix_id: MixId,
) -> Event {
pub fn new_pending_delegation_event(delegator: &Addr, amount: &Coin, mix_id: MixId) -> Event {
Event::new(MixnetEventType::PendingDelegation)
.add_attribute(DELEGATOR_KEY, delegator)
.add_optional_attribute(PROXY_KEY, proxy.as_ref())
.add_attribute(AMOUNT_KEY, amount.to_string())
.add_attribute(DELEGATION_TARGET_KEY, mix_id.to_string())
}
pub fn new_withdraw_operator_reward_event(
owner: &Addr,
proxy: &Option<Addr>,
amount: Coin,
mix_id: MixId,
) -> Event {
pub fn new_withdraw_operator_reward_event(owner: &Addr, amount: Coin, mix_id: MixId) -> Event {
Event::new(MixnetEventType::WithdrawOperatorReward)
.add_attribute(OWNER_KEY, owner.as_str())
.add_optional_attribute(PROXY_KEY, proxy.as_ref())
.add_attribute(AMOUNT_KEY, amount.to_string())
.add_attribute(MIX_ID_KEY, mix_id.to_string())
}
pub fn new_withdraw_delegator_reward_event(
delegator: &Addr,
proxy: &Option<Addr>,
amount: Coin,
mix_id: MixId,
) -> Event {
pub fn new_withdraw_delegator_reward_event(delegator: &Addr, amount: Coin, mix_id: MixId) -> Event {
Event::new(MixnetEventType::WithdrawDelegatorReward)
.add_attribute(DELEGATOR_KEY, delegator)
.add_optional_attribute(PROXY_KEY, proxy.as_ref())
.add_attribute(AMOUNT_KEY, amount.to_string())
.add_attribute(DELEGATION_TARGET_KEY, mix_id.to_string())
}
@@ -278,59 +252,43 @@ pub fn new_pending_rewarding_params_update_event(
)
}
pub fn new_undelegation_event(
created_at: BlockHeight,
delegator: &Addr,
proxy: &Option<Addr>,
mix_id: MixId,
) -> Event {
pub fn new_undelegation_event(created_at: BlockHeight, delegator: &Addr, mix_id: MixId) -> Event {
Event::new(MixnetEventType::Undelegation)
.add_attribute(EVENT_CREATION_HEIGHT_KEY, created_at.to_string())
.add_attribute(DELEGATOR_KEY, delegator)
.add_optional_attribute(PROXY_KEY, proxy.as_ref())
.add_attribute(MIX_ID_KEY, mix_id.to_string())
}
pub fn new_pending_undelegation_event(
delegator: &Addr,
proxy: &Option<Addr>,
mix_id: MixId,
) -> Event {
pub fn new_pending_undelegation_event(delegator: &Addr, mix_id: MixId) -> Event {
Event::new(MixnetEventType::PendingUndelegation)
.add_attribute(DELEGATOR_KEY, delegator)
.add_optional_attribute(PROXY_KEY, proxy.as_ref())
.add_attribute(MIX_ID_KEY, mix_id.to_string())
}
pub fn new_gateway_bonding_event(
owner: &Addr,
proxy: &Option<Addr>,
amount: &Coin,
identity: IdentityKeyRef<'_>,
) -> Event {
Event::new(MixnetEventType::GatewayBonding)
.add_attribute(OWNER_KEY, owner)
.add_attribute(NODE_IDENTITY_KEY, identity)
.add_optional_attribute(PROXY_KEY, proxy.as_ref())
.add_attribute(AMOUNT_KEY, amount.to_string())
}
pub fn new_gateway_unbonding_event(
owner: &Addr,
proxy: &Option<Addr>,
amount: &Coin,
identity: IdentityKeyRef<'_>,
) -> Event {
Event::new(MixnetEventType::GatewayUnbonding)
.add_attribute(OWNER_KEY, owner)
.add_attribute(NODE_IDENTITY_KEY, identity)
.add_optional_attribute(PROXY_KEY, proxy.as_ref())
.add_attribute(AMOUNT_KEY, amount.to_string())
}
pub fn new_mixnode_bonding_event(
owner: &Addr,
proxy: &Option<Addr>,
amount: &Coin,
identity: IdentityKeyRef<'_>,
mix_id: MixId,
@@ -341,7 +299,6 @@ pub fn new_mixnode_bonding_event(
.add_attribute(MIX_ID_KEY, mix_id.to_string())
.add_attribute(NODE_IDENTITY_KEY, identity)
.add_attribute(OWNER_KEY, owner)
.add_optional_attribute(PROXY_KEY, proxy.as_ref())
.add_attribute(ASSIGNED_LAYER_KEY, assigned_layer)
.add_attribute(AMOUNT_KEY, amount.to_string())
}
@@ -380,7 +337,6 @@ pub fn new_mixnode_unbonding_event(created_at: BlockHeight, mix_id: MixId) -> Ev
pub fn new_pending_mixnode_unbonding_event(
owner: &Addr,
proxy: &Option<Addr>,
identity: IdentityKeyRef<'_>,
mix_id: MixId,
) -> Event {
@@ -388,43 +344,33 @@ pub fn new_pending_mixnode_unbonding_event(
.add_attribute(MIX_ID_KEY, mix_id.to_string())
.add_attribute(NODE_IDENTITY_KEY, identity)
.add_attribute(OWNER_KEY, owner)
.add_optional_attribute(PROXY_KEY, proxy.as_ref())
}
pub fn new_mixnode_config_update_event(
mix_id: MixId,
owner: &Addr,
proxy: &Option<Addr>,
update: &MixNodeConfigUpdate,
) -> Event {
Event::new(MixnetEventType::MixnodeConfigUpdate)
.add_attribute(MIX_ID_KEY, mix_id.to_string())
.add_attribute(OWNER_KEY, owner)
.add_optional_attribute(PROXY_KEY, proxy.as_ref())
.add_attribute(UPDATED_MIXNODE_CONFIG_KEY, update.to_inline_json())
}
pub fn new_gateway_config_update_event(
owner: &Addr,
proxy: &Option<Addr>,
update: &GatewayConfigUpdate,
) -> Event {
pub fn new_gateway_config_update_event(owner: &Addr, update: &GatewayConfigUpdate) -> Event {
Event::new(MixnetEventType::GatewayConfigUpdate)
.add_attribute(OWNER_KEY, owner)
.add_optional_attribute(PROXY_KEY, proxy.as_ref())
.add_attribute(UPDATED_GATEWAY_CONFIG_KEY, update.to_inline_json())
}
pub fn new_mixnode_pending_cost_params_update_event(
mix_id: MixId,
owner: &Addr,
proxy: &Option<Addr>,
new_costs: &MixNodeCostParams,
) -> Event {
Event::new(MixnetEventType::PendingMixnodeCostParamsUpdate)
.add_attribute(MIX_ID_KEY, mix_id.to_string())
.add_attribute(OWNER_KEY, owner)
.add_optional_attribute(PROXY_KEY, proxy.as_ref())
.add_attribute(UPDATED_MIXNODE_COST_PARAMS_KEY, new_costs.to_inline_json())
}
@@ -3,7 +3,6 @@
use crate::{IdentityKey, IdentityKeyRef};
use cosmwasm_schema::cw_serde;
use cosmwasm_std::Addr;
use schemars::JsonSchema;
use serde::{Deserialize, Deserializer, Serialize, Serializer};
use std::fmt::{Display, Formatter};
@@ -84,10 +83,10 @@ impl FamilyHead {
}
impl Family {
pub fn new(head: FamilyHead, proxy: Option<Addr>, label: String) -> Self {
pub fn new(head: FamilyHead, label: String) -> Self {
Family {
head,
proxy: proxy.map(|p| p.to_string()),
proxy: None,
label,
}
}
@@ -55,19 +55,13 @@ pub struct GatewayBond {
}
impl GatewayBond {
pub fn new(
pledge_amount: Coin,
owner: Addr,
block_height: u64,
gateway: Gateway,
proxy: Option<Addr>,
) -> Self {
pub fn new(pledge_amount: Coin, owner: Addr, block_height: u64, gateway: Gateway) -> Self {
GatewayBond {
pledge_amount,
owner,
block_height,
gateway,
proxy,
proxy: None,
}
}
@@ -10,7 +10,10 @@ use crate::helpers::IntoBaseDecimal;
use crate::reward_params::{NodeRewardParams, RewardingParams};
use crate::rewarding::helpers::truncate_reward;
use crate::rewarding::RewardDistribution;
use crate::{Delegation, EpochEventId, EpochId, IdentityKey, MixId, Percent, SphinxKey};
use crate::{
Delegation, EpochEventId, EpochId, IdentityKey, MixId, OperatingCostRange, Percent,
ProfitMarginRange, SphinxKey,
};
use cosmwasm_schema::cw_serde;
use cosmwasm_std::{Addr, Coin, Decimal, StdResult, Uint128};
use schemars::JsonSchema;
@@ -152,6 +155,16 @@ impl MixNodeRewarding {
})
}
pub fn normalise_profit_margin(&mut self, allowed_range: ProfitMarginRange) {
self.cost_params.profit_margin_percent =
allowed_range.normalise(self.cost_params.profit_margin_percent)
}
pub fn normalise_operating_cost(&mut self, allowed_range: OperatingCostRange) {
self.cost_params.interval_operating_cost.amount =
allowed_range.normalise(self.cost_params.interval_operating_cost.amount)
}
/// Determines whether this node is still bonded. This is performed via a simple check,
/// if there are no tokens left associated with the operator, it means they have unbonded
/// and those params only exist for the purposes of calculating rewards for delegators that
@@ -518,7 +531,6 @@ impl MixNodeBond {
original_pledge: Coin,
layer: Layer,
mix_node: MixNode,
proxy: Option<Addr>,
bonding_height: u64,
) -> Self {
MixNodeBond {
@@ -527,7 +539,7 @@ impl MixNodeBond {
original_pledge,
layer,
mix_node,
proxy,
proxy: None,
bonding_height,
is_unbonding: false,
}
@@ -1,4 +1,4 @@
// Copyright 2021-2023 - Nym Technologies SA <contact@nymtech.net>
// Copyright 2021-2024 - Nym Technologies SA <contact@nymtech.net>
// SPDX-License-Identifier: Apache-2.0
use crate::delegation::{self, OwnerProxySubKey};
@@ -12,6 +12,7 @@ use crate::reward_params::{
IntervalRewardParams, IntervalRewardingParamsUpdate, Performance, RewardingParams,
};
use crate::types::{ContractStateParams, LayerAssignment, MixId};
use crate::{OperatingCostRange, ProfitMarginRange};
use contracts_common::{signing::MessageSignature, IdentityKey, Percent};
use cosmwasm_schema::cw_serde;
use cosmwasm_std::{Coin, Decimal};
@@ -57,6 +58,12 @@ pub struct InstantiateMsg {
pub epochs_in_interval: u32,
pub epoch_duration: Duration,
pub initial_rewarding_params: InitialRewardingParams,
#[serde(default)]
pub profit_margin: ProfitMarginRange,
#[serde(default)]
pub interval_operating_cost: OperatingCostRange,
}
#[cw_serde]
@@ -269,6 +276,12 @@ pub enum ExecuteMsg {
owner: String,
},
// vesting migration:
MigrateVestedMixNode {},
MigrateVestedDelegation {
mix_id: MixId,
},
// testing-only
#[cfg(feature = "contract-testing")]
TestingResolveAllPendingEvents {
@@ -381,6 +394,9 @@ impl ExecuteMsg {
ExecuteMsg::WithdrawDelegatorRewardOnBehalf { mix_id, .. } => {
format!("withdrawing delegator reward from mixnode {mix_id} on behalf")
}
ExecuteMsg::MigrateVestedMixNode { .. } => "migrate vested mixnode".into(),
ExecuteMsg::MigrateVestedDelegation { .. } => "migrate vested delegation".to_string(),
#[cfg(feature = "contract-testing")]
ExecuteMsg::TestingResolveAllPendingEvents { .. } => {
"resolving all pending events".into()
@@ -38,6 +38,7 @@ pub enum PendingEpochEventKind {
/// Request to create a delegation towards particular mixnode.
/// Note that if such delegation already exists, it will get updated with the provided token amount.
#[serde(alias = "Delegate")]
#[non_exhaustive]
Delegate {
/// The address of the owner of the delegation.
owner: Addr,
@@ -55,6 +56,7 @@ pub enum PendingEpochEventKind {
/// Request to remove delegation from particular mixnode.
#[serde(alias = "Undelegate")]
#[non_exhaustive]
Undelegate {
/// The address of the owner of the delegation.
owner: Addr,
@@ -109,6 +111,23 @@ impl PendingEpochEventKind {
kind: self,
}
}
pub fn new_delegate(owner: Addr, mix_id: MixId, amount: Coin) -> Self {
PendingEpochEventKind::Delegate {
owner,
mix_id,
amount,
proxy: None,
}
}
pub fn new_undelegate(owner: Addr, mix_id: MixId) -> Self {
PendingEpochEventKind::Undelegate {
owner,
mix_id,
proxy: None,
}
}
}
impl From<(EpochEventId, PendingEpochEventData)> for PendingEpochEvent {
@@ -47,7 +47,6 @@ impl SimulatedNode {
self.rewarding_details.total_unit_reward,
delegation,
42,
None,
);
self.delegations.insert(delegator, delegation);
@@ -37,13 +37,12 @@ impl SigningPurpose for MixnodeBondingPayload {
pub fn construct_mixnode_bonding_sign_payload(
nonce: Nonce,
sender: Addr,
proxy: Option<Addr>,
pledge: Coin,
mix_node: MixNode,
cost_params: MixNodeCostParams,
) -> SignableMixNodeBondingMsg {
let payload = MixnodeBondingPayload::new(mix_node, cost_params);
let content = ContractMessageContent::new(sender, proxy, vec![pledge], payload);
let content = ContractMessageContent::new(sender, vec![pledge], payload);
SignableMessage::new(nonce, content)
}
@@ -68,12 +67,11 @@ impl SigningPurpose for GatewayBondingPayload {
pub fn construct_gateway_bonding_sign_payload(
nonce: Nonce,
sender: Addr,
proxy: Option<Addr>,
pledge: Coin,
gateway: Gateway,
) -> SignableGatewayBondingMsg {
let payload = GatewayBondingPayload::new(gateway);
let content = ContractMessageContent::new(sender, proxy, vec![pledge], payload);
let content = ContractMessageContent::new(sender, vec![pledge], payload);
SignableMessage::new(nonce, content)
}
@@ -82,17 +80,14 @@ pub fn construct_gateway_bonding_sign_payload(
pub struct FamilyJoinPermit {
// the granter of this permit
family_head: FamilyHead,
// whether the **member** will want to join via the proxy (i.e. vesting contract)
proxy: Option<Addr>,
// the actual member we want to permit to join
member_node: IdentityKey,
}
impl FamilyJoinPermit {
pub fn new(family_head: FamilyHead, proxy: Option<Addr>, member_node: IdentityKey) -> Self {
pub fn new(family_head: FamilyHead, member_node: IdentityKey) -> Self {
Self {
family_head,
proxy,
member_node,
}
}
@@ -107,10 +102,9 @@ impl SigningPurpose for FamilyJoinPermit {
pub fn construct_family_join_permit(
nonce: Nonce,
family_head: FamilyHead,
proxy: Option<Addr>,
member_node: IdentityKey,
) -> SignableFamilyJoinPermitMsg {
let payload = FamilyJoinPermit::new(family_head, proxy, member_node);
let payload = FamilyJoinPermit::new(family_head, member_node);
// note: we're NOT wrapping it in `ContractMessageContent` because the family head is not going to be the one
// sending the message to the contract
@@ -3,9 +3,11 @@
use crate::error::MixnetContractError;
use crate::Layer;
use contracts_common::Percent;
use cosmwasm_schema::cw_serde;
use cosmwasm_std::Addr;
use cosmwasm_std::Coin;
use cosmwasm_std::{Addr, Uint128};
use std::fmt::{Display, Formatter};
use std::ops::Index;
// type aliases for better reasoning about available data
@@ -15,6 +17,65 @@ pub type SphinxKeyRef<'a> = &'a str;
pub type MixId = u32;
pub type BlockHeight = u64;
#[cw_serde]
pub struct RangedValue<T> {
pub minimum: T,
pub maximum: T,
}
impl<T> Copy for RangedValue<T> where T: Copy {}
pub type ProfitMarginRange = RangedValue<Percent>;
pub type OperatingCostRange = RangedValue<Uint128>;
impl<T> Display for RangedValue<T>
where
T: Display,
{
fn fmt(&self, f: &mut Formatter<'_>) -> std::fmt::Result {
write!(f, "{} - {}", self.minimum, self.maximum)
}
}
impl Default for ProfitMarginRange {
fn default() -> Self {
ProfitMarginRange {
minimum: Percent::zero(),
maximum: Percent::hundred(),
}
}
}
impl Default for OperatingCostRange {
fn default() -> Self {
OperatingCostRange {
minimum: Uint128::zero(),
// 1 billion (native tokens, i.e. 1 billion * 1'000'000 base tokens) - the total supply
maximum: Uint128::new(1_000_000_000_000_000),
}
}
}
impl<T> RangedValue<T>
where
T: Copy + PartialOrd + PartialEq,
{
pub fn normalise(&self, value: T) -> T {
if value < self.minimum {
self.minimum
} else if value > self.maximum {
self.maximum
} else {
value
}
}
pub fn within_range(&self, value: T) -> bool {
value >= self.minimum && value <= self.maximum
}
}
/// Specifies layer assignment for the given mixnode.
#[cw_serde]
pub struct LayerAssignment {
@@ -154,4 +215,14 @@ pub struct ContractStateParams {
/// Minimum amount a gateway must pledge to get into the system.
pub minimum_gateway_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,
}
@@ -167,3 +167,11 @@ pub fn new_track_undelegation_event() -> Event {
pub fn new_track_reward_event() -> Event {
Event::new(TRACK_REWARD_EVENT_TYPE)
}
pub fn new_track_migrate_mixnode_event() -> Event {
Event::new("track_migrate_vesting_mixnode")
}
pub fn new_track_migrate_delegation_event() -> Event {
Event::new("track_migrate_vesting_delegation")
}
@@ -136,6 +136,14 @@ pub enum ExecuteMsg {
address: String,
cap: PledgeCap,
},
TrackMigratedMixnode {
owner: String,
},
// no need to track migrated gateways as there are no vesting gateways on mainnet
TrackMigratedDelegation {
owner: String,
mix_id: MixId,
},
}
impl ExecuteMsg {
@@ -171,6 +179,10 @@ impl ExecuteMsg {
ExecuteMsg::TransferOwnership { .. } => "VestingExecuteMsg::TransferOwnership",
ExecuteMsg::UpdateStakingAddress { .. } => "VestingExecuteMsg::UpdateStakingAddress",
ExecuteMsg::UpdateLockedPledgeCap { .. } => "VestingExecuteMsg::UpdateLockedPledgeCap",
ExecuteMsg::TrackMigratedMixnode { .. } => "VestingExecuteMsg::TrackMigratedMixnode",
ExecuteMsg::TrackMigratedDelegation { .. } => {
"VestingExecuteMsg::TrackMigratedDelegation"
}
}
}
}
@@ -35,6 +35,9 @@ CREATE TABLE ecash_ticketbook
-- introduce a way for us to introduce breaking changes in serialization of data
serialization_revision INTEGER NOT NULL,
-- the type of the associated ticketbook
ticketbook_type TEXT NOT NULL,
-- the actual crypto data of the ticketbook (wallet, keys, etc.)
ticketbook_data BLOB NOT NULL UNIQUE,
@@ -175,6 +175,7 @@ impl MemoryEcachTicketbookManager {
.map(|t| BasicTicketbookInformation {
id: t.ticketbook_id,
expiration_date: t.ticketbook.expiration_date(),
ticketbook_type: t.ticketbook.ticketbook_type().to_string(),
epoch_id: t.ticketbook.epoch_id() as u32,
total_tickets: t.ticketbook.spent_tickets() as u32,
used_tickets: t.ticketbook.params_total_tickets() as u32,
@@ -61,11 +61,13 @@ impl SqliteEcashTicketbookManager {
Ok(())
}
#[allow(clippy::too_many_arguments)]
pub(crate) async fn insert_new_ticketbook(
&self,
serialisation_revision: u8,
data: &[u8],
expiration_date: Date,
typ: &str,
epoch_id: u32,
total_tickets: u32,
used_tickets: u32,
@@ -73,12 +75,13 @@ impl SqliteEcashTicketbookManager {
sqlx::query!(
r#"
INSERT INTO ecash_ticketbook
(serialization_revision, ticketbook_data, expiration_date, epoch_id, total_tickets, used_tickets)
VALUES (?, ?, ?, ?, ?, ?)
(serialization_revision, ticketbook_data, expiration_date, ticketbook_type, epoch_id, total_tickets, used_tickets)
VALUES (?, ?, ?, ?, ?, ?, ?)
"#,
serialisation_revision,
data,
expiration_date,
typ,
epoch_id,
total_tickets,
used_tickets,
@@ -92,7 +95,7 @@ impl SqliteEcashTicketbookManager {
) -> Result<Vec<BasicTicketbookInformation>, sqlx::Error> {
sqlx::query_as(
r#"
SELECT id, expiration_date, epoch_id, total_tickets, used_tickets
SELECT id, expiration_date, ticketbook_type, epoch_id, total_tickets, used_tickets
FROM ecash_ticketbook
"#,
)
+3
View File
@@ -19,6 +19,7 @@ pub struct RetrievedPendingTicketbook {
pub struct BasicTicketbookInformation {
pub id: i64,
pub expiration_date: Date,
pub ticketbook_type: String,
pub epoch_id: u32,
pub total_tickets: u32,
pub used_tickets: u32,
@@ -31,6 +32,8 @@ pub struct StoredIssuedTicketbook {
pub serialization_revision: u8,
pub ticketbook_type: String,
pub ticketbook_data: Vec<u8>,
#[zeroize(skip)]
@@ -114,6 +114,7 @@ impl Storage for PersistentStorage {
serialisation_revision,
&data,
ticketbook.expiration_date(),
&ticketbook.ticketbook_type().to_string(),
ticketbook.epoch_id() as u32,
ticketbook.params_total_tickets() as u32,
ticketbook.spent_tickets() as u32,
+1 -1
View File
@@ -14,9 +14,9 @@ time.workspace = true
nym-bandwidth-controller = { path = "../../common/bandwidth-controller" }
nym-credentials = { path = "../../common/credentials" }
nym-credentials-interface = { path = "../../common/credentials-interface" }
nym-credential-storage = { path = "../../common/credential-storage", features = ["persistent-storage"] }
nym-validator-client = { path = "../../common/client-libs/validator-client" }
nym-config = { path = "../../common/config" }
nym-client-core = { path = "../../common/client-core" }
nym-compact-ecash = { path = "../../common/nym_offline_compact_ecash" }
nym-ecash-time = { path = "../../common/ecash-time" }
+12 -2
View File
@@ -1,3 +1,6 @@
// Copyright 2023-2024 - Nym Technologies SA <contact@nymtech.net>
// SPDX-License-Identifier: Apache-2.0
use crate::errors::{Error, Result};
use log::*;
use nym_bandwidth_controller::acquire::{
@@ -7,6 +10,7 @@ use nym_client_core::config::disk_persistence::CommonClientPaths;
use nym_config::DEFAULT_DATA_DIR;
use nym_credential_storage::persistent_storage::PersistentStorage;
use nym_credential_storage::storage::Storage;
use nym_credentials_interface::TicketType;
use nym_ecash_time::ecash_default_expiration_date;
use nym_validator_client::coconut::all_ecash_api_clients;
use nym_validator_client::nyxd::contract_traits::{
@@ -16,7 +20,12 @@ use std::path::PathBuf;
use std::time::Duration;
use time::OffsetDateTime;
pub async fn issue_credential<C, S>(client: &C, storage: &S, client_id: &[u8]) -> Result<()>
pub async fn issue_credential<C, S>(
client: &C,
storage: &S,
client_id: &[u8],
typ: TicketType,
) -> Result<()>
where
C: DkgQueryClient + EcashSigningClient + EcashQueryClient + Send + Sync,
S: Storage,
@@ -49,6 +58,7 @@ where
client,
client_id,
Some(ticketbook_expiration),
typ,
)
.await?;
info!("Deposit done");
@@ -65,7 +75,7 @@ where
}).map_err(Error::storage_error)?
}
info!("Succeeded adding a ticketbook");
info!("Succeeded adding a ticketbook of type '{typ}'");
Ok(())
}
+3 -1
View File
@@ -14,8 +14,10 @@ license.workspace = true
bls12_381 = { workspace = true, default-features = false }
serde = { workspace = true, features = ["derive"] }
thiserror = { workspace = true }
strum = { workspace = true, features = ["derive"] }
time = { workspace = true, features = ["serde"] }
rand = { workspace = true }
nym-compact-ecash = { path = "../nym_offline_compact_ecash" }
nym-ecash-time = { path = "../ecash-time" }
nym-ecash-time = { path = "../ecash-time" }
nym-network-defaults = { path = "../network-defaults" }
+117 -5
View File
@@ -1,8 +1,10 @@
// Copyright 2024 - Nym Technologies SA <contact@nymtech.net>
// SPDX-License-Identifier: Apache-2.0
use nym_network_defaults::TicketTypeRepr;
use rand::Rng;
use serde::{Deserialize, Serialize};
use thiserror::Error;
use time::{Date, OffsetDateTime};
pub use nym_compact_ecash::{
@@ -15,7 +17,6 @@ pub use nym_compact_ecash::{
PartialCoinIndexSignature,
},
scheme::expiration_date_signatures::aggregate_expiration_signatures,
scheme::expiration_date_signatures::date_scalar,
scheme::expiration_date_signatures::{
AnnotatedExpirationDateSignature, ExpirationDateSignature, ExpirationDateSignatureShare,
PartialExpirationDateSignature,
@@ -24,10 +25,10 @@ pub use nym_compact_ecash::{
scheme::withdrawal::RequestInfo,
scheme::Payment,
scheme::{Wallet, WalletSignatures},
withdrawal_request, Base58, BlindedSignature, Bytable, PartialWallet, PayInfo, PublicKeyUser,
SecretKeyUser, VerificationKeyAuth, WithdrawalRequest,
withdrawal_request, Base58, BlindedSignature, Bytable, EncodedDate, EncodedTicketType,
PartialWallet, PayInfo, PublicKeyUser, SecretKeyUser, VerificationKeyAuth, WithdrawalRequest,
};
use nym_ecash_time::EcashTime;
use nym_ecash_time::{ecash_today, EcashTime};
#[derive(Debug, Clone)]
pub struct CredentialSigningData {
@@ -38,6 +39,8 @@ pub struct CredentialSigningData {
pub ecash_pub_key: PublicKeyUser,
pub expiration_date: Date,
pub ticketbook_type: TicketType,
}
#[derive(Debug, Serialize, Deserialize, PartialEq, Clone)]
@@ -58,7 +61,7 @@ impl CredentialSpendingData {
self.payment.spend_verify(
verification_key,
&self.pay_info,
date_scalar(self.spend_date.ecash_unix_timestamp()),
self.spend_date.ecash_unix_timestamp(),
)
}
@@ -216,3 +219,112 @@ impl From<PayInfo> for NymPayInfo {
}
}
}
#[derive(
Default,
Copy,
Clone,
Debug,
PartialEq,
Serialize,
Deserialize,
strum::Display,
strum::EnumString,
)]
#[serde(rename_all = "kebab-case")]
#[strum(serialize_all = "kebab-case")]
pub enum TicketType {
#[default]
V1MixnetEntry,
V1MixnetExit,
V1WireguardEntry,
V1WireguardExit,
}
#[derive(Debug, Copy, Clone, Error)]
#[error("provided unknown ticketbook type")]
pub struct UnknownTicketType;
impl TicketType {
pub fn to_repr(&self) -> TicketTypeRepr {
(*self).into()
}
pub fn encode(&self) -> EncodedTicketType {
self.to_repr() as EncodedTicketType
}
pub fn try_from_encoded(val: EncodedTicketType) -> Result<Self, UnknownTicketType> {
match val {
n if n == TicketTypeRepr::V1MixnetEntry as u8 => {
Ok(TicketTypeRepr::V1MixnetEntry.into())
}
n if n == TicketTypeRepr::V1MixnetExit as u8 => Ok(TicketTypeRepr::V1MixnetExit.into()),
n if n == TicketTypeRepr::V1WireguardEntry as u8 => {
Ok(TicketTypeRepr::V1WireguardEntry.into())
}
n if n == TicketTypeRepr::V1WireguardExit as u8 => {
Ok(TicketTypeRepr::V1WireguardExit.into())
}
_ => Err(UnknownTicketType),
}
}
}
impl From<TicketType> for TicketTypeRepr {
fn from(value: TicketType) -> Self {
match value {
TicketType::V1MixnetEntry => TicketTypeRepr::V1MixnetEntry,
TicketType::V1MixnetExit => TicketTypeRepr::V1MixnetExit,
TicketType::V1WireguardEntry => TicketTypeRepr::V1WireguardEntry,
TicketType::V1WireguardExit => TicketTypeRepr::V1WireguardExit,
}
}
}
impl From<TicketTypeRepr> for TicketType {
fn from(value: TicketTypeRepr) -> Self {
match value {
TicketTypeRepr::V1MixnetEntry => TicketType::V1MixnetEntry,
TicketTypeRepr::V1MixnetExit => TicketType::V1MixnetExit,
TicketTypeRepr::V1WireguardEntry => TicketType::V1WireguardEntry,
TicketTypeRepr::V1WireguardExit => TicketType::V1WireguardExit,
}
}
}
#[derive(Clone)]
pub struct ClientTicket {
pub spending_data: CredentialSpendingData,
pub ticket_id: i64,
}
impl ClientTicket {
pub fn new(spending_data: CredentialSpendingData, ticket_id: i64) -> Self {
ClientTicket {
spending_data,
ticket_id,
}
}
}
#[derive(Debug, Clone, Copy)]
pub struct AvailableBandwidth {
pub bytes: i64,
pub expiration: OffsetDateTime,
}
impl AvailableBandwidth {
pub fn expired(&self) -> bool {
self.expiration < ecash_today()
}
}
impl Default for AvailableBandwidth {
fn default() -> Self {
Self {
bytes: 0,
expiration: OffsetDateTime::UNIX_EPOCH,
}
}
}
@@ -2,14 +2,15 @@
// SPDX-License-Identifier: Apache-2.0
use crate::ecash::bandwidth::issued::IssuedTicketBook;
use crate::ecash::bandwidth::serialiser::VersionedSerialise;
use crate::ecash::bandwidth::CredentialSigningData;
use crate::ecash::utils::cred_exp_date;
use crate::error::Error;
use nym_api_requests::ecash::BlindSignRequestBody;
use nym_credentials_interface::{
aggregate_wallets, generate_keypair_user_from_seed, issue_verify, withdrawal_request,
BlindedSignature, KeyPairUser, PartialWallet, VerificationKeyAuth, WalletSignatures,
WithdrawalRequest,
BlindedSignature, KeyPairUser, PartialWallet, TicketType, VerificationKeyAuth,
WalletSignatures, WithdrawalRequest,
};
use nym_crypto::asymmetric::identity;
use nym_ecash_contract_common::deposit::DepositId;
@@ -18,7 +19,6 @@ use nym_validator_client::nym_api::EpochId;
use serde::{Deserialize, Serialize};
use time::Date;
use crate::ecash::bandwidth::serialiser::VersionedSerialise;
pub use nym_validator_client::nyxd::{Coin, Hash};
#[derive(Serialize, Deserialize)]
@@ -32,6 +32,9 @@ pub struct IssuanceTicketBook {
/// ecash keypair related to the credential
ecash_keypair: KeyPairUser,
/// the type of the ticketbook to be issued
ticketbook_type: TicketType,
/// expiration_date of that credential
expiration_date: Date,
}
@@ -41,12 +44,14 @@ impl IssuanceTicketBook {
deposit_id: DepositId,
identifier: M,
signing_key: identity::PrivateKey,
ticketbook_type: TicketType,
) -> Self {
//this expiration date will get fed to the ecash library, force midnight to be set
Self::new_with_expiration(
deposit_id,
identifier,
signing_key,
ticketbook_type,
ecash_default_expiration_date(),
)
}
@@ -55,6 +60,7 @@ impl IssuanceTicketBook {
deposit_id: DepositId,
identifier: M,
signing_key: identity::PrivateKey,
ticketbook_type: TicketType,
expiration_date: Date,
) -> Self {
let ecash_keypair = generate_keypair_user_from_seed(identifier);
@@ -62,6 +68,7 @@ impl IssuanceTicketBook {
deposit_id,
signing_key,
ecash_keypair,
ticketbook_type,
expiration_date,
}
}
@@ -76,6 +83,10 @@ impl IssuanceTicketBook {
self.expiration_date
}
pub fn ticketbook_type(&self) -> TicketType {
self.ticketbook_type
}
pub fn request_plaintext(request: &WithdrawalRequest, deposit_id: DepositId) -> Vec<u8> {
let mut message = request.to_bytes();
message.extend_from_slice(&deposit_id.to_be_bytes());
@@ -99,6 +110,7 @@ impl IssuanceTicketBook {
request_signature,
signing_request.ecash_pub_key.clone(),
signing_request.expiration_date,
signing_request.ticketbook_type,
)
}
@@ -133,6 +145,7 @@ impl IssuanceTicketBook {
let (withdrawal_request, request_info) = withdrawal_request(
self.ecash_keypair.secret_key(),
self.expiration_date.ecash_unix_timestamp(),
self.ticketbook_type.encode(),
)
.unwrap();
@@ -141,6 +154,7 @@ impl IssuanceTicketBook {
request_info,
ecash_pub_key: self.ecash_keypair.public_key(),
expiration_date: self.expiration_date,
ticketbook_type: self.ticketbook_type,
}
}
@@ -218,6 +232,7 @@ impl IssuanceTicketBook {
wallet,
epoch_id,
self.ecash_keypair.secret_key().clone(),
self.ticketbook_type,
self.expiration_date,
)
}
@@ -6,8 +6,8 @@ use crate::ecash::bandwidth::CredentialSpendingData;
use crate::ecash::utils::ecash_today;
use crate::error::Error;
use nym_credentials_interface::{
CoinIndexSignature, ExpirationDateSignature, PayInfo, SecretKeyUser, VerificationKeyAuth,
Wallet, WalletSignatures,
CoinIndexSignature, ExpirationDateSignature, PayInfo, SecretKeyUser, TicketType,
VerificationKeyAuth, Wallet, WalletSignatures,
};
use nym_ecash_time::EcashTime;
use nym_validator_client::nym_api::EpochId;
@@ -36,6 +36,10 @@ pub struct IssuedTicketBook {
/// expiration_date for easier discarding
#[zeroize(skip)]
expiration_date: Date,
/// the type of the ticketbook to got issued
#[zeroize(skip)]
ticketbook_type: TicketType,
}
impl IssuedTicketBook {
@@ -43,6 +47,7 @@ impl IssuedTicketBook {
wallet: WalletSignatures,
epoch_id: EpochId,
ecash_secret_key: SecretKeyUser,
ticketbook_type: TicketType,
expiration_date: Date,
) -> Self {
IssuedTicketBook {
@@ -51,6 +56,7 @@ impl IssuedTicketBook {
epoch_id,
ecash_secret_key,
expiration_date,
ticketbook_type,
}
}
@@ -58,6 +64,7 @@ impl IssuedTicketBook {
signatures_wallet: WalletSignatures,
epoch_id: EpochId,
ecash_secret_key: SecretKeyUser,
ticketbook_type: TicketType,
expiration_date: Date,
spent_tickets: u64,
) -> Self {
@@ -67,6 +74,7 @@ impl IssuedTicketBook {
epoch_id,
ecash_secret_key,
expiration_date,
ticketbook_type,
}
}
@@ -78,6 +86,10 @@ impl IssuedTicketBook {
self.epoch_id
}
pub fn ticketbook_type(&self) -> TicketType {
self.ticketbook_type
}
pub fn current_serialization_revision(&self) -> u8 {
CURRENT_SERIALIZATION_REVISION
}
+1 -17
View File
@@ -36,22 +36,6 @@ pub fn aggregate_verification_keys(
)?)
}
pub fn obtain_aggregated_verification_key(
_api_clients: &[EcashApiClient],
) -> Result<VerificationKeyAuth, Error> {
// TODO:
// let total = api_clients.len();
// let mut rng = thread_rng();
// let indices = sample(&mut rng, total, total);
// for index in indices {
// // randomly try apis until we succeed
// // if let Ok(res) = api_clients[index].api_client.get_aggregated_verification_key().await {
// // //
// // }
// }
todo!()
}
pub async fn obtain_expiration_date_signatures(
ecash_api_clients: &[EcashApiClient],
verification_key: &VerificationKeyAuth,
@@ -63,7 +47,7 @@ pub async fn obtain_expiration_date_signatures(
let mut signatures_shares: Vec<_> = Vec::with_capacity(ecash_api_clients.len());
let expiration_date = cred_exp_date().unix_timestamp() as u64;
let expiration_date = cred_exp_date().ecash_unix_timestamp();
for ecash_api_client in ecash_api_clients.iter() {
match ecash_api_client
.api_client
+5 -2
View File
@@ -6,13 +6,16 @@ use time::{Duration, PrimitiveDateTime, Time};
pub use time::{Date, OffsetDateTime};
pub trait EcashTime {
fn ecash_unix_timestamp(&self) -> u64 {
fn ecash_unix_timestamp(&self) -> u32 {
let ts = self.ecash_datetime().unix_timestamp();
// just panic on pre-1970 timestamps...
assert!(ts > 0);
ts as u64
// and on anything in 22nd century...
assert!(ts <= u32::MAX as i64);
ts as u32
}
fn ecash_date(&self) -> Date {
@@ -21,12 +21,12 @@ thiserror = { workspace = true }
tracing = { workspace = true, features = ["log"] }
zeroize = { workspace = true }
nym-crypto = { path = "../../common/crypto" }
nym-pemstore = { path = "../../common/pemstore" }
nym-sphinx = { path = "../../common/nymsphinx" }
nym-crypto = { path = "../crypto" }
nym-pemstore = { path = "../pemstore" }
nym-sphinx = { path = "../nymsphinx" }
nym-credentials = { path = "../../common/credentials" }
nym-credentials-interface = { path = "../../common/credentials-interface" }
nym-credentials = { path = "../credentials" }
nym-credentials-interface = { path = "../credentials-interface" }
[target."cfg(not(target_arch = \"wasm32\"))".dependencies.tokio]
workspace = true
@@ -41,6 +41,4 @@ workspace = true
default-features = false
[dev-dependencies]
nym-compact-ecash = { path = "../../common/nym_offline_compact_ecash" } # we need specific imports in tests
nym-compact-ecash = { path = "../nym_offline_compact_ecash" } # we need specific imports in tests
@@ -64,6 +64,7 @@ mod tests {
};
use nym_credentials::ecash::utils::EcashTime;
use nym_credentials::IssuanceTicketBook;
use nym_credentials_interface::TicketType;
use nym_crypto::asymmetric::ed25519;
use rand::rngs::OsRng;
@@ -75,7 +76,7 @@ mod tests {
let mut rng = OsRng;
let signing_key = ed25519::PrivateKey::new(&mut rng);
let issuance = IssuanceTicketBook::new(42, [], signing_key);
let issuance = IssuanceTicketBook::new(42, [], signing_key, TicketType::V1MixnetEntry);
let expiration_date = issuance.expiration_date();
let sig_req = issuance.prepare_for_signing();
let exp_date_sigs = generate_expiration_date_signatures(
@@ -91,6 +92,7 @@ mod tests {
sig_req.ecash_pub_key.clone(),
&sig_req.withdrawal_request,
expiration_date.ecash_unix_timestamp(),
issuance.ticketbook_type().encode(),
)
.unwrap();
+41
View File
@@ -0,0 +1,41 @@
[package]
name = "nym-gateway-storage"
version = "0.1.0"
authors.workspace = true
repository.workspace = true
homepage.workspace = true
documentation.workspace = true
edition.workspace = true
license.workspace = true
[dependencies]
async-trait = { workspace = true }
bincode = { workspace = true, optional = true }
defguard_wireguard_rs = { workspace = true, optional = true }
log = { workspace = true }
sqlx = { workspace = true, features = [
"runtime-tokio-rustls",
"sqlite",
"macros",
"migrate",
"time",
] }
time = { workspace = true }
thiserror = { workspace = true }
tracing = { workspace = true }
nym-credentials-interface = { path = "../credentials-interface" }
nym-gateway-requests = { path = "../gateway-requests" }
nym-sphinx = { path = "../nymsphinx" }
[build-dependencies]
tokio = { workspace = true, features = ["rt-multi-thread", "macros"] }
sqlx = { workspace = true, features = [
"runtime-tokio-rustls",
"sqlite",
"macros",
"migrate",
] }
[features]
wireguard = ["defguard_wireguard_rs", "bincode"]
@@ -0,0 +1,18 @@
/*
* Copyright 2024 - Nym Technologies SA <contact@nymtech.net>
* SPDX-License-Identifier: Apache-2.0
*/
CREATE TABLE wireguard_peer
(
public_key TEXT NOT NULL PRIMARY KEY UNIQUE,
preshared_key TEXT,
protocol_version INTEGER,
endpoint TEXT,
last_handshake TIMESTAMP,
tx_bytes BIGINT NOT NULL,
rx_bytes BIGINT NOT NULL,
persistent_keepalive_interval INTEGER,
allowed_ips BLOB NOT NULL,
suspended BOOLEAN NOT NULL
);
@@ -1,11 +1,28 @@
// Copyright 2021 - Nym Technologies SA <contact@nymtech.net>
// SPDX-License-Identifier: GPL-3.0-only
use crate::node::storage::models::PersistedBandwidth;
use crate::models::PersistedBandwidth;
use time::OffsetDateTime;
#[derive(Debug, Clone, Copy, Default)]
pub struct AvailableBandwidth {
pub bytes: i64,
pub freepass_expiration: Option<OffsetDateTime>,
}
impl AvailableBandwidth {
pub fn freepass_expired(&self) -> bool {
if let Some(expiration) = self.freepass_expiration {
if expiration < OffsetDateTime::now_utc() {
return true;
}
}
false
}
}
#[derive(Clone)]
pub(crate) struct BandwidthManager {
pub struct BandwidthManager {
connection_pool: sqlx::SqlitePool,
}
@@ -15,7 +32,7 @@ impl BandwidthManager {
/// # Arguments
///
/// * `connection_pool`: database connection pool to use.
pub(crate) fn new(connection_pool: sqlx::SqlitePool) -> Self {
pub fn new(connection_pool: sqlx::SqlitePool) -> Self {
BandwidthManager { connection_pool }
}
@@ -16,4 +16,7 @@ pub enum StorageError {
#[error("the stored data associated with ticket {ticket_id} is malformed!")]
MalformedStoredTicketData { ticket_id: i64 },
#[error("Failed to convert from type of database: {0}")]
TypeConversion(String),
}
@@ -1,7 +1,7 @@
// Copyright 2020 - Nym Technologies SA <contact@nymtech.net>
// SPDX-License-Identifier: GPL-3.0-only
use crate::node::storage::models::StoredMessage;
use crate::models::StoredMessage;
#[derive(Clone)]
pub(crate) struct InboxManager {
@@ -1,29 +1,32 @@
// Copyright 2020 - Nym Technologies SA <contact@nymtech.net>
// SPDX-License-Identifier: GPL-3.0-only
use crate::node::client_handling::websocket::connection_handler::ecash::ClientTicket;
use crate::node::storage::bandwidth::BandwidthManager;
use crate::node::storage::error::StorageError;
use crate::node::storage::inboxes::InboxManager;
use crate::node::storage::models::{
PersistedBandwidth, PersistedSharedKeys, RedemptionProposal, StoredMessage, VerifiedTicket,
};
use crate::node::storage::shared_keys::SharedKeysManager;
use crate::node::storage::tickets::TicketStorageManager;
use async_trait::async_trait;
use bandwidth::BandwidthManager;
use error::StorageError;
use inboxes::InboxManager;
use models::{
PersistedBandwidth, PersistedSharedKeys, RedemptionProposal, StoredMessage, VerifiedTicket,
WireguardPeer,
};
use nym_credentials_interface::ClientTicket;
use nym_gateway_requests::registration::handshake::SharedKeys;
use nym_sphinx::DestinationAddressBytes;
use shared_keys::SharedKeysManager;
use sqlx::ConnectOptions;
use std::path::Path;
use tickets::TicketStorageManager;
use time::OffsetDateTime;
use tracing::{debug, error};
mod bandwidth;
pub(crate) mod error;
pub mod bandwidth;
pub mod error;
mod inboxes;
pub(crate) mod models;
mod shared_keys;
mod tickets;
#[cfg(feature = "wireguard")]
mod wireguard_peers;
#[async_trait]
pub trait Storage: Send + Sync {
@@ -207,6 +210,42 @@ pub trait Storage: Send + Sync {
async fn get_votes(&self, ticket_id: i64) -> Result<Vec<i64>, StorageError>;
async fn get_signers(&self, epoch_id: i64) -> Result<Vec<i64>, StorageError>;
/// Insert a wireguard peer in the storage.
///
/// # Arguments
///
/// * `peer`: wireguard peer data to be stored
/// * `suspended`: if peer exists, but it's currently suspended
#[cfg(feature = "wireguard")]
async fn insert_wireguard_peer(
&self,
peer: &defguard_wireguard_rs::host::Peer,
suspended: bool,
) -> Result<(), StorageError>;
/// Tries to retrieve available bandwidth for the particular peer.
///
/// # Arguments
///
/// * `peer_public_key`: wireguard public key of the peer to be retrieved.
#[cfg(feature = "wireguard")]
async fn get_wireguard_peer(
&self,
peer_public_key: &str,
) -> Result<Option<WireguardPeer>, StorageError>;
/// Retrieves all wireguard peers.
#[cfg(feature = "wireguard")]
async fn get_all_wireguard_peers(&self) -> Result<Vec<WireguardPeer>, StorageError>;
/// Remove a wireguard peer from the storage.
///
/// # Arguments
///
/// * `peer_public_key`: wireguard public key of the peer to be removed.
#[cfg(feature = "wireguard")]
async fn remove_wireguard_peer(&self, peer_public_key: &str) -> Result<(), StorageError>;
}
// note that clone here is fine as upon cloning the same underlying pool will be used
@@ -216,6 +255,8 @@ pub struct PersistentStorage {
inbox_manager: InboxManager,
bandwidth_manager: BandwidthManager,
ticket_manager: TicketStorageManager,
#[cfg(feature = "wireguard")]
wireguard_peer_manager: wireguard_peers::WgPeerManager,
}
impl PersistentStorage {
@@ -259,6 +300,8 @@ impl PersistentStorage {
// the cloning here are cheap as connection pool is stored behind an Arc
Ok(PersistentStorage {
#[cfg(feature = "wireguard")]
wireguard_peer_manager: wireguard_peers::WgPeerManager::new(connection_pool.clone()),
shared_key_manager: SharedKeysManager::new(connection_pool.clone()),
inbox_manager: InboxManager::new(connection_pool.clone(), message_retrieval_limit),
bandwidth_manager: BandwidthManager::new(connection_pool.clone()),
@@ -576,4 +619,42 @@ impl Storage for PersistentStorage {
async fn get_signers(&self, epoch_id: i64) -> Result<Vec<i64>, StorageError> {
Ok(self.ticket_manager.get_epoch_signers(epoch_id).await?)
}
#[cfg(feature = "wireguard")]
async fn insert_wireguard_peer(
&self,
peer: &defguard_wireguard_rs::host::Peer,
suspended: bool,
) -> Result<(), StorageError> {
let mut peer = WireguardPeer::from(peer.clone());
peer.suspended = suspended;
self.wireguard_peer_manager.insert_peer(&peer).await?;
Ok(())
}
#[cfg(feature = "wireguard")]
async fn get_wireguard_peer(
&self,
peer_public_key: &str,
) -> Result<Option<WireguardPeer>, StorageError> {
let peer = self
.wireguard_peer_manager
.retrieve_peer(peer_public_key)
.await?;
Ok(peer)
}
#[cfg(feature = "wireguard")]
async fn get_all_wireguard_peers(&self) -> Result<Vec<WireguardPeer>, StorageError> {
let ret = self.wireguard_peer_manager.retrieve_all_peers().await?;
Ok(ret)
}
#[cfg(feature = "wireguard")]
async fn remove_wireguard_peer(&self, peer_public_key: &str) -> Result<(), StorageError> {
self.wireguard_peer_manager
.remove_peer(peer_public_key)
.await?;
Ok(())
}
}
+182
View File
@@ -0,0 +1,182 @@
// Copyright 2021-2024 - Nym Technologies SA <contact@nymtech.net>
// SPDX-License-Identifier: GPL-3.0-only
use crate::error::StorageError;
use nym_credentials_interface::{AvailableBandwidth, ClientTicket, CredentialSpendingData};
use sqlx::FromRow;
use time::OffsetDateTime;
pub struct PersistedSharedKeys {
#[allow(dead_code)]
pub id: i64,
#[allow(dead_code)]
pub client_address_bs58: String,
pub derived_aes128_ctr_blake3_hmac_keys_bs58: String,
}
pub struct StoredMessage {
pub id: i64,
#[allow(dead_code)]
pub client_address_bs58: String,
pub content: Vec<u8>,
}
#[derive(Debug, Clone, FromRow)]
pub struct PersistedBandwidth {
#[allow(dead_code)]
pub client_id: i64,
pub available: i64,
pub expiration: Option<OffsetDateTime>,
}
impl From<PersistedBandwidth> for AvailableBandwidth {
fn from(value: PersistedBandwidth) -> Self {
AvailableBandwidth {
bytes: value.available,
expiration: value.expiration.unwrap_or(OffsetDateTime::UNIX_EPOCH),
}
}
}
#[derive(FromRow)]
pub struct VerifiedTicket {
pub serial_number: Vec<u8>,
pub ticket_id: i64,
}
#[derive(FromRow)]
pub struct RedemptionProposal {
pub proposal_id: i64,
pub created_at: OffsetDateTime,
}
#[derive(FromRow)]
pub struct UnverifiedTicketData {
pub data: Vec<u8>,
pub ticket_id: i64,
}
impl TryFrom<UnverifiedTicketData> for ClientTicket {
type Error = StorageError;
fn try_from(value: UnverifiedTicketData) -> Result<Self, Self::Error> {
Ok(ClientTicket {
spending_data: CredentialSpendingData::try_from_bytes(&value.data).map_err(|_| {
StorageError::MalformedStoredTicketData {
ticket_id: value.ticket_id,
}
})?,
ticket_id: value.ticket_id,
})
}
}
#[cfg(feature = "wireguard")]
#[derive(Debug, Clone, FromRow)]
pub struct WireguardPeer {
pub public_key: String,
pub preshared_key: Option<String>,
pub protocol_version: Option<i64>,
pub endpoint: Option<String>,
pub last_handshake: Option<sqlx::types::chrono::NaiveDateTime>,
pub tx_bytes: i64,
pub rx_bytes: i64,
pub persistent_keepalive_interval: Option<i64>,
pub allowed_ips: Vec<u8>,
pub suspended: bool,
}
#[cfg(feature = "wireguard")]
impl From<defguard_wireguard_rs::host::Peer> for WireguardPeer {
fn from(value: defguard_wireguard_rs::host::Peer) -> Self {
WireguardPeer {
public_key: value.public_key.to_string(),
preshared_key: value.preshared_key.as_ref().map(|k| k.to_string()),
protocol_version: value.protocol_version.map(|v| v as i64),
endpoint: value.endpoint.map(|e| e.to_string()),
last_handshake: value.last_handshake.and_then(|t| {
if let Ok(d) = t.duration_since(std::time::UNIX_EPOCH) {
if let Ok(millis) = d.as_millis().try_into() {
sqlx::types::chrono::DateTime::from_timestamp_millis(millis)
.map(|d| d.naive_utc())
} else {
None
}
} else {
None
}
}),
tx_bytes: value.tx_bytes as i64,
rx_bytes: value.rx_bytes as i64,
persistent_keepalive_interval: value.persistent_keepalive_interval.map(|v| v as i64),
allowed_ips: bincode::Options::serialize(
bincode::DefaultOptions::new(),
&value.allowed_ips,
)
.unwrap_or_default(),
suspended: false,
}
}
}
#[cfg(feature = "wireguard")]
impl TryFrom<WireguardPeer> for defguard_wireguard_rs::host::Peer {
type Error = crate::error::StorageError;
fn try_from(value: WireguardPeer) -> Result<Self, Self::Error> {
Ok(Self {
public_key: value
.public_key
.as_str()
.try_into()
.map_err(|e| Self::Error::TypeConversion(format!("public key {e}")))?,
preshared_key: value
.preshared_key
.as_deref()
.map(TryFrom::try_from)
.transpose()
.map_err(|e| Self::Error::TypeConversion(format!("preshared key {e}")))?,
protocol_version: value
.protocol_version
.map(TryFrom::try_from)
.transpose()
.map_err(|e| Self::Error::TypeConversion(format!("protocol version {e}")))?,
endpoint: value
.endpoint
.as_deref()
.map(|e| e.parse())
.transpose()
.map_err(|e| Self::Error::TypeConversion(format!("endpoint {e}")))?,
last_handshake: value.last_handshake.and_then(|t| {
let unix_time = std::time::UNIX_EPOCH;
if let Ok(millis) = t.and_utc().timestamp_millis().try_into() {
let duration = std::time::Duration::from_millis(millis);
unix_time.checked_add(duration)
} else {
None
}
}),
tx_bytes: value
.tx_bytes
.try_into()
.map_err(|e| Self::Error::TypeConversion(format!("tx bytes {e}")))?,
rx_bytes: value
.rx_bytes
.try_into()
.map_err(|e| Self::Error::TypeConversion(format!("rx bytes {e}")))?,
persistent_keepalive_interval: value
.persistent_keepalive_interval
.map(TryFrom::try_from)
.transpose()
.map_err(|e| {
Self::Error::TypeConversion(format!("persistent keepalive interval {e}"))
})?,
allowed_ips: bincode::Options::deserialize(
bincode::DefaultOptions::new(),
&value.allowed_ips,
)
.map_err(|e| Self::Error::TypeConversion(format!("allowed ips {e}")))?,
})
}
}
@@ -1,7 +1,7 @@
// Copyright 2021 - Nym Technologies SA <contact@nymtech.net>
// SPDX-License-Identifier: GPL-3.0-only
use crate::node::storage::models::PersistedSharedKeys;
use crate::models::PersistedSharedKeys;
#[derive(Clone)]
pub(crate) struct SharedKeysManager {
@@ -1,7 +1,7 @@
// Copyright 2024 - Nym Technologies SA <contact@nymtech.net>
// SPDX-License-Identifier: GPL-3.0-only
use crate::node::storage::models::{RedemptionProposal, UnverifiedTicketData, VerifiedTicket};
use crate::models::{RedemptionProposal, UnverifiedTicketData, VerifiedTicket};
use time::OffsetDateTime;
#[derive(Clone)]
@@ -0,0 +1,89 @@
// Copyright 2024 - Nym Technologies SA <contact@nymtech.net>
// SPDX-License-Identifier: GPL-3.0-only
use crate::models::WireguardPeer;
#[derive(Clone)]
pub(crate) struct WgPeerManager {
connection_pool: sqlx::SqlitePool,
}
impl WgPeerManager {
/// Creates new instance of the `WgPeersManager` with the provided sqlite connection pool.
///
/// # Arguments
///
/// * `connection_pool`: database connection pool to use.
pub(crate) fn new(connection_pool: sqlx::SqlitePool) -> Self {
WgPeerManager { connection_pool }
}
/// Creates a new wireguard peer entry for its particular public key or
/// overwrittes the peer entry data if it already existed.
///
/// # Arguments
///
/// * `peer`: peer information needed by wireguard interface.
pub(crate) async fn insert_peer(&self, peer: &WireguardPeer) -> Result<(), sqlx::Error> {
sqlx::query!(
"INSERT OR REPLACE INTO wireguard_peer(public_key, preshared_key, protocol_version, endpoint, last_handshake, tx_bytes, rx_bytes, persistent_keepalive_interval, allowed_ips, suspended) VALUES (?, ?, ?, ?, ?, ?, ?, ?, ?, ?)",
peer.public_key, peer.preshared_key, peer.protocol_version, peer.endpoint, peer.last_handshake, peer.tx_bytes, peer.rx_bytes, peer.persistent_keepalive_interval, peer.allowed_ips, peer.suspended
)
.execute(&self.connection_pool)
.await?;
Ok(())
}
/// Retrieve the wireguard peer with the provided public key from the storage.
///
/// # Arguments
///
/// * `public_key`: the unique public key of the wireguard peer.
pub(crate) async fn retrieve_peer(
&self,
public_key: &str,
) -> Result<Option<WireguardPeer>, sqlx::Error> {
sqlx::query_as!(
WireguardPeer,
r#"
SELECT * FROM wireguard_peer
WHERE public_key = ?
LIMIT 1
"#,
public_key,
)
.fetch_optional(&self.connection_pool)
.await
}
/// Retrieve all wireguard peers.
pub(crate) async fn retrieve_all_peers(&self) -> Result<Vec<WireguardPeer>, sqlx::Error> {
sqlx::query_as!(
WireguardPeer,
r#"
SELECT *
FROM wireguard_peer;
"#,
)
.fetch_all(&self.connection_pool)
.await
}
/// Retrieve the wireguard peer with the provided public key from the storage.
///
/// # Arguments
///
/// * `public_key`: the unique public key of the wireguard peer.
pub(crate) async fn remove_peer(&self, public_key: &str) -> Result<(), sqlx::Error> {
sqlx::query!(
r#"
DELETE FROM wireguard_peer
WHERE public_key = ?
"#,
public_key,
)
.execute(&self.connection_pool)
.await?;
Ok(())
}
}
@@ -0,0 +1,69 @@
// Copyright 2024 - Nym Technologies SA <contact@nymtech.net>
// SPDX-License-Identifier: Apache-2.0
use crate::{v6, v7};
impl From<v7::response::StaticConnectFailureReason> for v6::response::StaticConnectFailureReason {
fn from(failure: v7::response::StaticConnectFailureReason) -> Self {
match failure {
v7::response::StaticConnectFailureReason::RequestedIpAlreadyInUse => {
v6::response::StaticConnectFailureReason::RequestedIpAlreadyInUse
}
v7::response::StaticConnectFailureReason::RequestedNymAddressAlreadyInUse => {
v6::response::StaticConnectFailureReason::RequestedNymAddressAlreadyInUse
}
v7::response::StaticConnectFailureReason::OutOfDateTimestamp => {
v6::response::StaticConnectFailureReason::Other("out of date timestamp".to_string())
}
v7::response::StaticConnectFailureReason::Other(reason) => {
v6::response::StaticConnectFailureReason::Other(reason)
}
}
}
}
impl From<v7::response::DynamicConnectFailureReason> for v6::response::DynamicConnectFailureReason {
fn from(failure: v7::response::DynamicConnectFailureReason) -> Self {
match failure {
v7::response::DynamicConnectFailureReason::RequestedNymAddressAlreadyInUse => {
v6::response::DynamicConnectFailureReason::RequestedNymAddressAlreadyInUse
}
v7::response::DynamicConnectFailureReason::NoAvailableIp => {
v6::response::DynamicConnectFailureReason::NoAvailableIp
}
v7::response::DynamicConnectFailureReason::Other(err) => {
v6::response::DynamicConnectFailureReason::Other(err)
}
}
}
}
impl From<v7::response::InfoResponseReply> for v6::response::InfoResponseReply {
fn from(reply: v7::response::InfoResponseReply) -> Self {
match reply {
v7::response::InfoResponseReply::Generic { msg } => {
v6::response::InfoResponseReply::Generic { msg }
}
v7::response::InfoResponseReply::VersionMismatch {
request_version,
response_version,
} => v6::response::InfoResponseReply::VersionMismatch {
request_version,
response_version,
},
v7::response::InfoResponseReply::ExitPolicyFilterCheckFailed { dst } => {
v6::response::InfoResponseReply::ExitPolicyFilterCheckFailed { dst }
}
}
}
}
impl From<v7::response::InfoLevel> for v6::response::InfoLevel {
fn from(level: v7::response::InfoLevel) -> Self {
match level {
v7::response::InfoLevel::Info => v6::response::InfoLevel::Info,
v7::response::InfoLevel::Warn => v6::response::InfoLevel::Warn,
v7::response::InfoLevel::Error => v6::response::InfoLevel::Error,
}
}
}
+1
View File
@@ -1,3 +1,4 @@
pub mod conversion;
pub mod request;
pub mod response;

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