From 6557be37388cfa2090195f95fb4e5709d4e0dbda Mon Sep 17 00:00:00 2001 From: =?UTF-8?q?J=C4=99drzej=20Stuczy=C5=84ski?= Date: Tue, 30 Aug 2022 12:56:13 +0200 Subject: [PATCH 01/46] Delegator compoudning to bypass pending events (#1571) * Delegator compoudning to bypass pending events * Updated changelog --- contracts/CHANGELOG.md | 6 +++ contracts/mixnet/src/rewards/transactions.rs | 47 ++++++++++---------- 2 files changed, 30 insertions(+), 23 deletions(-) diff --git a/contracts/CHANGELOG.md b/contracts/CHANGELOG.md index c8d9d385a9..8685dc89d7 100644 --- a/contracts/CHANGELOG.md +++ b/contracts/CHANGELOG.md @@ -4,12 +4,18 @@ - vesting-contract: added queries for delegation timestamps and paged query for all vesting delegations in the contract ([#1569]) +### Changed + +- mixnet-contract: compounding delegator rewards now happens instantaneously as opposed to having to wait for the current epoch to finish ([#1571]) + ### Fixed - vesting-contract: the contract now correctly stores delegations with their timestamp as opposed to using block height ([#1544]) +- mixnet-contract: compounding delegator rewards is now possible even if the associated mixnode had already unbonded ([#1571]) [#1544]: https://github.com/nymtech/nym/pull/1544 [#1569]: https://github.com/nymtech/nym/pull/1569 +[#1569]: https://github.com/nymtech/nym/pull/1571 ## [nym-contracts-v1.0.1](https://github.com/nymtech/nym/tree/nym-contracts-v1.0.1) (2022-06-22) diff --git a/contracts/mixnet/src/rewards/transactions.rs b/contracts/mixnet/src/rewards/transactions.rs index e0f59de6e9..826c45f783 100644 --- a/contracts/mixnet/src/rewards/transactions.rs +++ b/contracts/mixnet/src/rewards/transactions.rs @@ -8,7 +8,6 @@ use super::storage::{ use crate::constants; use crate::contract::debug_with_visibility; use crate::delegations::storage as delegations_storage; -use crate::delegations::transactions::_try_delegate_to_mixnode; use crate::error::ContractError; use crate::mixnet_contract_settings::storage::mix_denom; use crate::mixnodes::storage::mixnodes; @@ -18,7 +17,7 @@ use crate::rewards::helpers; use crate::support::helpers::{is_authorized, operator_cost_at_epoch}; use cosmwasm_std::{ coins, wasm_execute, Addr, Api, BankMsg, Coin, DepsMut, Env, MessageInfo, Order, Response, - Storage, Uint128, + StdResult, Storage, Uint128, }; use cw_storage_plus::Bound; use mixnet_contract_common::events::{ @@ -450,18 +449,15 @@ pub fn try_compound_delegator_reward( pub fn _try_compound_delegator_reward( block_height: u64, - mut deps: DepsMut<'_>, + deps: DepsMut<'_>, owner_address: &str, mix_identity: &str, proxy: Option, ) -> Result { let delegation_map = crate::delegations::storage::delegations(); let mix_denom = mix_denom(deps.storage)?; - - let key = mixnet_contract_common::delegation::generate_storage_key( - &deps.api.addr_validate(owner_address)?, - proxy.as_ref(), - ); + let owner = deps.api.addr_validate(owner_address)?; + let key = mixnet_contract_common::delegation::generate_storage_key(&owner, proxy.as_ref()); let reward = calculate_delegator_reward(deps.storage, deps.api, key.clone(), mix_identity)?; let mut total_delegation_delegate = Uint128::zero(); @@ -469,8 +465,7 @@ pub fn _try_compound_delegator_reward( let delegation_heights = delegation_map .prefix((mix_identity.to_string(), key.clone())) .keys(deps.storage, None, None, cosmwasm_std::Order::Ascending) - .filter_map(|v| v.ok()) - .collect::>(); + .collect::>>()?; for h in delegation_heights { let delegation = @@ -494,30 +489,36 @@ pub fn _try_compound_delegator_reward( // since we know that the target node exists and because the total_delegation bucket // entry is created whenever the node itself is added, the unwrap here is fine // as the entry MUST exist - Ok(total_delegation - .unwrap() - .saturating_sub(total_delegation_delegate)) + Ok(total_delegation.unwrap() + reward) }, )?; - _try_delegate_to_mixnode( - deps.branch(), - block_height, - mix_identity, - owner_address, + // let's simplify the entire procedure. Rather than creating a fresh delegation on the mixnode + // via `_try_delegate_to_mixnode` and then waiting for reconcile to happen, + // just save it directly to the storage right now. + // my reasoning for that is simple: `_try_delegate_to_mixnode` could fail if the node the + // delegator has delegated to no longer exists. + let delegation = Delegation::new( + owner, + mix_identity.into(), Coin { amount: compounded_delegation, denom: mix_denom, }, + block_height, proxy, + ); + + delegation_map.save( + deps.storage, + (mix_identity.into(), key.clone(), block_height), + &delegation, )?; } - { - if let Some(mut bond) = mixnodes().may_load(deps.storage, mix_identity)? { - bond.accumulated_rewards = Some(bond.accumulated_rewards().saturating_sub(reward)); - mixnodes().save(deps.storage, mix_identity, &bond, block_height)?; - } + if let Some(mut bond) = mixnodes().may_load(deps.storage, mix_identity)? { + bond.accumulated_rewards = Some(bond.accumulated_rewards().saturating_sub(reward)); + mixnodes().save(deps.storage, mix_identity, &bond, block_height)?; } DELEGATOR_REWARD_CLAIMED_HEIGHT.save( From a6aba3defd2821e15fc23c9cb7f82c41427a9781 Mon Sep 17 00:00:00 2001 From: =?UTF-8?q?Bogdan-=C8=98tefan=20Neac=C5=9Fu?= Date: Tue, 30 Aug 2022 14:14:50 +0300 Subject: [PATCH 02/46] Feature/validator api shutdown (#1573) * Rewarded set updater shutdown (partial) handling * Shutdown handling in monitor * Remove shutdown from packet receiver * Configurable shutdown timeout * Select on test_run too * Remove unnecessary await/async * Add bias to shutdown select and concurrency for big tasks * Put cpu-bound packet prep on separate thread, to avoid blocking * Use a better fit timeout value * Fix clippy warnings * Update changelog * Fix wasm client --- CHANGELOG.md | 3 +- .../input_message_listener.rs | 1 - .../retransmission_request_listener.rs | 1 - clients/webassembly/src/client/mod.rs | 1 - common/nymsphinx/src/preparer/mod.rs | 10 +++---- common/task/src/shutdown.rs | 13 ++++++-- validator-api/src/contract_cache/mod.rs | 22 +++++++++----- validator-api/src/main.rs | 6 ++-- validator-api/src/network_monitor/chunker.rs | 8 ++--- .../monitor/gateways_pinger.rs | 21 ++++++++++--- .../src/network_monitor/monitor/mod.rs | 26 +++++++++++----- .../src/network_monitor/monitor/preparer.rs | 28 +++++++---------- .../src/network_monitor/monitor/processor.rs | 30 +++++++++++-------- .../src/network_monitor/monitor/receiver.rs | 7 +++-- .../src/network_monitor/monitor/sender.rs | 9 ++++-- validator-api/src/node_status_api/cache.rs | 21 +++++++++---- .../src/node_status_api/uptime_updater.rs | 22 +++++++++----- validator-api/src/rewarded_set_updater/mod.rs | 19 ++++++++++-- 18 files changed, 161 insertions(+), 87 deletions(-) diff --git a/CHANGELOG.md b/CHANGELOG.md index b6adc1c809..931457972f 100644 --- a/CHANGELOG.md +++ b/CHANGELOG.md @@ -53,7 +53,7 @@ Post 1.0.0 release, the changelog format is based on [Keep a Changelog](https:// - validator: fixed local docker-compose setup to work on Apple M1 ([#1329]) - explorer-api: listen out for SIGTERM and SIGQUIT too, making it play nicely as a system service ([#1482]). - network-requester: fix filter for suffix-only domains ([#1487]) -- validator-api: listen out for SIGTERM and SIGQUIT too, making it play nicely as a system service ([#1496]). +- validator-api: listen out for SIGTERM and SIGQUIT too, making it play nicely as a system service; cleaner shutdown, without panics ([#1496], [#1573]). ### Changed @@ -99,6 +99,7 @@ Post 1.0.0 release, the changelog format is based on [Keep a Changelog](https:// [#1496]: https://github.com/nymtech/nym/pull/1496 [#1503]: https://github.com/nymtech/nym/pull/1503 [#1520]: https://github.com/nymtech/nym/pull/1520 +[#1573]: https://github.com/nymtech/nym/pull/1573 ## [v1.0.1](https://github.com/nymtech/nym/tree/v1.0.1) (2022-05-04) diff --git a/clients/client-core/src/client/real_messages_control/acknowledgement_control/input_message_listener.rs b/clients/client-core/src/client/real_messages_control/acknowledgement_control/input_message_listener.rs index 2e34451de3..e44eef38c8 100644 --- a/clients/client-core/src/client/real_messages_control/acknowledgement_control/input_message_listener.rs +++ b/clients/client-core/src/client/real_messages_control/acknowledgement_control/input_message_listener.rs @@ -133,7 +133,6 @@ where let prepared_fragment = self .message_preparer .prepare_chunk_for_sending(chunk_clone, topology, &self.ack_key, &recipient) - .await .unwrap(); real_messages.push(RealMessage::new( diff --git a/clients/client-core/src/client/real_messages_control/acknowledgement_control/retransmission_request_listener.rs b/clients/client-core/src/client/real_messages_control/acknowledgement_control/retransmission_request_listener.rs index d0081f4d04..3e9e2ee65a 100644 --- a/clients/client-core/src/client/real_messages_control/acknowledgement_control/retransmission_request_listener.rs +++ b/clients/client-core/src/client/real_messages_control/acknowledgement_control/retransmission_request_listener.rs @@ -83,7 +83,6 @@ where let prepared_fragment = self .message_preparer .prepare_chunk_for_sending(chunk_clone, topology_ref, &self.ack_key, packet_recipient) - .await .unwrap(); // if we have the ONLY strong reference to the ack data, it means it was removed from the diff --git a/clients/webassembly/src/client/mod.rs b/clients/webassembly/src/client/mod.rs index 573ef60bc7..57e20931ca 100644 --- a/clients/webassembly/src/client/mod.rs +++ b/clients/webassembly/src/client/mod.rs @@ -197,7 +197,6 @@ impl NymClient { // don't bother with acks etc. for time being let prepared_fragment = message_preparer .prepare_chunk_for_sending(message_chunk, topology, &self.ack_key, &recipient) - .await .unwrap(); console_warn!("packet is going to have round trip time of {:?}, but we're not going to do anything for acks anyway ", prepared_fragment.total_delay); diff --git a/common/nymsphinx/src/preparer/mod.rs b/common/nymsphinx/src/preparer/mod.rs index 3f56f9bada..a51075290e 100644 --- a/common/nymsphinx/src/preparer/mod.rs +++ b/common/nymsphinx/src/preparer/mod.rs @@ -213,7 +213,7 @@ where /// - compute vk_b = g^x || v_b /// - compute sphinx_plaintext = SURB_ACK || g^x || v_b /// - compute sphinx_packet = Sphinx(recipient, sphinx_plaintext) - pub async fn prepare_chunk_for_sending( + pub fn prepare_chunk_for_sending( &mut self, fragment: Fragment, topology: &NymTopology, @@ -222,8 +222,7 @@ where ) -> Result { // create an ack let (ack_delay, surb_ack_bytes) = self - .generate_surb_ack(fragment.fragment_identifier(), topology, ack_key) - .await? + .generate_surb_ack(fragment.fragment_identifier(), topology, ack_key)? .prepare_for_sending(); // TODO: @@ -294,7 +293,7 @@ where } /// Construct an acknowledgement SURB for the given [`FragmentIdentifier`] - async fn generate_surb_ack( + fn generate_surb_ack( &mut self, fragment_id: FragmentIdentifier, topology: &NymTopology, @@ -357,8 +356,7 @@ where // gateways could not distinguish reply packets from normal messages due to lack of said acks // note: the ack delay is irrelevant since we do not know the delay of actual surb let (_, surb_ack_bytes) = self - .generate_surb_ack(reply_id, topology, ack_key) - .await? + .generate_surb_ack(reply_id, topology, ack_key)? .prepare_for_sending(); let zero_pad_len = self.packet_size.plaintext_size() diff --git a/common/task/src/shutdown.rs b/common/task/src/shutdown.rs index 8c8b472459..1fe873e9aa 100644 --- a/common/task/src/shutdown.rs +++ b/common/task/src/shutdown.rs @@ -5,13 +5,14 @@ use std::time::Duration; use tokio::sync::watch::{self, error::SendError}; -const SHUTDOWN_TIMER_SECS: u64 = 5; +const DEFAULT_SHUTDOWN_TIMER_SECS: u64 = 5; /// Used to notify other tasks to gracefully shutdown #[derive(Debug)] pub struct ShutdownNotifier { notify_tx: watch::Sender<()>, notify_rx: Option>, + shutdown_timer_secs: u64, } impl Default for ShutdownNotifier { @@ -20,11 +21,19 @@ impl Default for ShutdownNotifier { Self { notify_tx, notify_rx: Some(notify_rx), + shutdown_timer_secs: DEFAULT_SHUTDOWN_TIMER_SECS, } } } impl ShutdownNotifier { + pub fn new(shutdown_timer_secs: u64) -> Self { + Self { + shutdown_timer_secs, + ..Default::default() + } + } + pub fn subscribe(&self) -> ShutdownListener { ShutdownListener::new( self.notify_rx @@ -50,7 +59,7 @@ impl ShutdownNotifier { _ = tokio::signal::ctrl_c() => { log::info!("Forcing shutdown"); } - _ = tokio::time::sleep(Duration::from_secs(SHUTDOWN_TIMER_SECS)) => { + _ = tokio::time::sleep(Duration::from_secs(self.shutdown_timer_secs)) => { log::info!("Timout reached, forcing shutdown"); }, } diff --git a/validator-api/src/contract_cache/mod.rs b/validator-api/src/contract_cache/mod.rs index a7f2b91b0b..5a3d3d8978 100644 --- a/validator-api/src/contract_cache/mod.rs +++ b/validator-api/src/contract_cache/mod.rs @@ -281,13 +281,21 @@ impl ValidatorCacheRefresher { while !shutdown.is_shutdown() { tokio::select! { _ = interval.tick() => { - if let Err(err) = self.refresh_cache().await { - error!("Failed to refresh validator cache - {}", err); - } else { - // relaxed memory ordering is fine here. worst case scenario network monitor - // will just have to wait for an additional backoff to see the change. - // And so this will not really incur any performance penalties by setting it every loop iteration - self.cache.initialised.store(true, Ordering::Relaxed) + tokio::select! { + biased; + _ = shutdown.recv() => { + trace!("ValidatorCacheRefresher: Received shutdown"); + } + ret = self.refresh_cache() => { + if let Err(err) = ret { + error!("Failed to refresh validator cache - {}", err); + } else { + // relaxed memory ordering is fine here. worst case scenario network monitor + // will just have to wait for an additional backoff to see the change. + // And so this will not really incur any performance penalties by setting it every loop iteration + self.cache.initialised.store(true, Ordering::Relaxed) + } + } } } _ = shutdown.recv() => { diff --git a/validator-api/src/main.rs b/validator-api/src/main.rs index dd4ec49172..96abe8408a 100644 --- a/validator-api/src/main.rs +++ b/validator-api/src/main.rs @@ -568,7 +568,8 @@ async fn run_validator_api(matches: ArgMatches<'static>) -> Result<()> { let signing_nymd_client = Client::new_signing(&config); let liftoff_notify = Arc::new(Notify::new()); - let shutdown = ShutdownNotifier::default(); + // We need a bigger timeout + let shutdown = ShutdownNotifier::new(10); // let's build our rocket! let rocket = setup_rocket( @@ -609,7 +610,8 @@ async fn run_validator_api(matches: ArgMatches<'static>) -> Result<()> { // spawn rewarded set updater let mut rewarded_set_updater = RewardedSetUpdater::new(signing_nymd_client, validator_cache.clone(), storage).await?; - tokio::spawn(async move { rewarded_set_updater.run().await.unwrap() }); + let shutdown_listener = shutdown.subscribe(); + tokio::spawn(async move { rewarded_set_updater.run(shutdown_listener).await.unwrap() }); validator_cache_listener } else { diff --git a/validator-api/src/network_monitor/chunker.rs b/validator-api/src/network_monitor/chunker.rs index c95f8421f5..ec0da08871 100644 --- a/validator-api/src/network_monitor/chunker.rs +++ b/validator-api/src/network_monitor/chunker.rs @@ -12,6 +12,7 @@ use topology::NymTopology; const DEFAULT_AVERAGE_PACKET_DELAY: Duration = Duration::from_millis(200); const DEFAULT_AVERAGE_ACK_DELAY: Duration = Duration::from_millis(200); +#[derive(Clone)] pub(crate) struct Chunker { rng: OsRng, message_preparer: MessagePreparer, @@ -30,7 +31,7 @@ impl Chunker { } } - pub(crate) async fn prepare_packets_from( + pub(crate) fn prepare_packets_from( &mut self, message: Vec, topology: &NymTopology, @@ -40,10 +41,10 @@ impl Chunker { // but without some significant API changes in the `MessagePreparer` this was the easiest // way to being able to have variable sender address. self.message_preparer.set_sender_address(packet_sender); - self.prepare_packets(message, topology, packet_sender).await + self.prepare_packets(message, topology, packet_sender) } - async fn prepare_packets( + fn prepare_packets( &mut self, message: Vec, topology: &NymTopology, @@ -62,7 +63,6 @@ impl Chunker { let prepared_fragment = self .message_preparer .prepare_chunk_for_sending(message_chunk, topology, &ack_key, &packet_sender) - .await .unwrap(); mix_packets.push(prepared_fragment.mix_packet); diff --git a/validator-api/src/network_monitor/monitor/gateways_pinger.rs b/validator-api/src/network_monitor/monitor/gateways_pinger.rs index f7d47ca302..24cd581bf3 100644 --- a/validator-api/src/network_monitor/monitor/gateways_pinger.rs +++ b/validator-api/src/network_monitor/monitor/gateways_pinger.rs @@ -7,6 +7,7 @@ use crypto::asymmetric::identity; use crypto::asymmetric::identity::PUBLIC_KEY_LENGTH; use log::{debug, info, trace, warn}; use std::time::Duration; +use task::ShutdownListener; use tokio::time::{sleep, Instant}; // TODO: should it perhaps be moved to config along other timeout values? @@ -143,10 +144,22 @@ impl GatewayPinger { info!("Pinging all active gateways took {:?}", time_taken); } - pub(crate) async fn run(&self) { - loop { - sleep(self.pinging_interval).await; - self.ping_and_cleanup_all_gateways().await + pub(crate) async fn run(&self, mut shutdown: ShutdownListener) { + while !shutdown.is_shutdown() { + tokio::select! { + _ = sleep(self.pinging_interval) => { + tokio::select! { + biased; + _ = shutdown.recv() => { + trace!("GatewaysPinger: Received shutdown"); + } + _ = self.ping_and_cleanup_all_gateways() => (), + } + } + _ = shutdown.recv() => { + trace!("GatewaysPinger: Received shutdown"); + } + } } } } diff --git a/validator-api/src/network_monitor/monitor/mod.rs b/validator-api/src/network_monitor/monitor/mod.rs index 2cd1950f96..e2d1a07128 100644 --- a/validator-api/src/network_monitor/monitor/mod.rs +++ b/validator-api/src/network_monitor/monitor/mod.rs @@ -122,11 +122,15 @@ impl Monitor { let mut packets = Vec::with_capacity(routes.len()); for route in routes { - packets.push( - self.packet_preparer - .prepare_test_route_viability_packets(route, self.route_test_packets) - .await, - ); + let mut packet_preparer = self.packet_preparer.clone(); + let route = route.clone(); + let route_test_packets = self.route_test_packets; + let gateway_packets = tokio::spawn(async move { + packet_preparer.prepare_test_route_viability_packets(&route, route_test_packets) + }) + .await + .unwrap(); + packets.push(gateway_packets); } self.received_processor.set_route_test_nonce().await; @@ -306,12 +310,20 @@ impl Monitor { .await; self.packet_sender - .spawn_gateways_pinger(self.gateway_ping_interval); + .spawn_gateways_pinger(self.gateway_ping_interval, shutdown.clone()); let mut run_interval = tokio::time::interval(self.run_interval); while !shutdown.is_shutdown() { tokio::select! { - _ = run_interval.tick() => self.test_run().await, + _ = run_interval.tick() => { + tokio::select! { + biased; + _ = shutdown.recv() => { + trace!("UpdateHandler: Received shutdown"); + } + _ = self.test_run() => (), + } + } _ = shutdown.recv() => { trace!("UpdateHandler: Received shutdown"); } diff --git a/validator-api/src/network_monitor/monitor/preparer.rs b/validator-api/src/network_monitor/monitor/preparer.rs index d67eb59629..2173cc04da 100644 --- a/validator-api/src/network_monitor/monitor/preparer.rs +++ b/validator-api/src/network_monitor/monitor/preparer.rs @@ -117,6 +117,7 @@ pub(crate) struct PreparedPackets { pub(super) invalid_gateways: Vec, } +#[derive(Clone)] pub(crate) struct PacketPreparer { system_version: String, chunker: Option, @@ -151,7 +152,7 @@ impl PacketPreparer { } } - async fn wrap_test_packet( + fn wrap_test_packet( &mut self, packet: &TestPacket, topology: &NymTopology, @@ -162,12 +163,11 @@ impl PacketPreparer { if self.chunker.is_none() { self.chunker = Some(Chunker::new(packet_recipient)); } - let mut mix_packets = self - .chunker - .as_mut() - .unwrap() - .prepare_packets_from(packet.to_bytes(), topology, packet_recipient) - .await; + let mut mix_packets = self.chunker.as_mut().unwrap().prepare_packets_from( + packet.to_bytes(), + topology, + packet_recipient, + ); assert_eq!( mix_packets.len(), 1, @@ -351,7 +351,7 @@ impl PacketPreparer { ) } - pub(crate) async fn prepare_test_route_viability_packets( + pub(crate) fn prepare_test_route_viability_packets( &mut self, route: &TestRoute, num: usize, @@ -360,9 +360,7 @@ impl PacketPreparer { let test_packet = route.self_test_packet(); let recipient = self.create_packet_sender(route.gateway()); for _ in 0..num { - let mix_packet = self - .wrap_test_packet(&test_packet, route.topology(), recipient) - .await; + let mix_packet = self.wrap_test_packet(&test_packet, route.topology(), recipient); mix_packets.push(mix_packet) } @@ -451,9 +449,7 @@ impl PacketPreparer { let topology = test_route.substitute_mix(mixnode); // produce n mix packets for _ in 0..self.per_node_test_packets { - let mix_packet = self - .wrap_test_packet(&test_packet, &topology, recipient) - .await; + let mix_packet = self.wrap_test_packet(&test_packet, &topology, recipient); mix_packets.push(mix_packet); } } @@ -476,9 +472,7 @@ impl PacketPreparer { let topology = test_route.substitute_gateway(gateway); // produce n mix packets for _ in 0..self.per_node_test_packets { - let mix_packet = self - .wrap_test_packet(&test_packet, &topology, recipient) - .await; + let mix_packet = self.wrap_test_packet(&test_packet, &topology, recipient); gateway_mix_packets.push(mix_packet); } diff --git a/validator-api/src/network_monitor/monitor/processor.rs b/validator-api/src/network_monitor/monitor/processor.rs index 11d995f1c8..2d504c01c2 100644 --- a/validator-api/src/network_monitor/monitor/processor.rs +++ b/validator-api/src/network_monitor/monitor/processor.rs @@ -140,8 +140,7 @@ impl ReceivedProcessor { self.permit_changer = Some(permit_sender); tokio::spawn(async move { - loop { - let permit = wait_for_permit(&mut permit_receiver, &*inner).await; + while let Some(permit) = wait_for_permit(&mut permit_receiver, &*inner).await { receive_or_release_permit(&mut permit_receiver, permit).await; } @@ -151,16 +150,20 @@ impl ReceivedProcessor { ) { loop { tokio::select! { - permit_receiver = permit_receiver.next() => match permit_receiver.unwrap() { - LockPermit::Release => return, - LockPermit::Free => error!("somehow we got notification that the lock is free to take while we already hold it!"), + permit_receiver = permit_receiver.next() => match permit_receiver { + Some(LockPermit::Release) => return, + Some(LockPermit::Free) => error!("somehow we got notification that the lock is free to take while we already hold it!"), + None => return, }, - messages = inner.packets_receiver.next() => { - for message in messages.expect("packet receiver has died!") { - if let Err(err) = inner.on_message(message) { - warn!(target: "Monitor", "failed to process received gateway message - {}", err) + messages = inner.packets_receiver.next() => match messages { + Some(messages) => { + for message in messages { + if let Err(err) = inner.on_message(message) { + warn!(target: "Monitor", "failed to process received gateway message - {}", err) + } } } + None => return, }, } } @@ -172,14 +175,15 @@ impl ReceivedProcessor { async fn wait_for_permit<'a>( permit_receiver: &mut mpsc::Receiver, inner: &'a Mutex, - ) -> MutexGuard<'a, ReceivedProcessorInner> { + ) -> Option> { loop { - match permit_receiver.next().await.unwrap() { + match permit_receiver.next().await { // we should only ever get this on the very first run - LockPermit::Release => debug!( + Some(LockPermit::Release) => debug!( "somehow got request to drop our lock permit while we do not hold it!" ), - LockPermit::Free => return inner.lock().await, + Some(LockPermit::Free) => return Some(inner.lock().await), + None => return None, } } } diff --git a/validator-api/src/network_monitor/monitor/receiver.rs b/validator-api/src/network_monitor/monitor/receiver.rs index 36913241db..991da5fa05 100644 --- a/validator-api/src/network_monitor/monitor/receiver.rs +++ b/validator-api/src/network_monitor/monitor/receiver.rs @@ -59,6 +59,10 @@ impl PacketReceiver { pub(crate) async fn run(&mut self, mut shutdown: ShutdownListener) { while !shutdown.is_shutdown() { tokio::select! { + biased; + _ = shutdown.recv() => { + trace!("UpdateHandler: Received shutdown"); + } // unwrap here is fine as it can only return a `None` if the PacketSender has died // and if that was the case, then the entire monitor is already in an undefined state update = self.clients_updater.next() => self.process_gateway_update(update.unwrap()), @@ -68,9 +72,6 @@ impl PacketReceiver { Some((_gateway_id, message)) = self.gateways_reader.stream_map().next() => { self.process_gateway_messages(message) } - _ = shutdown.recv() => { - trace!("UpdateHandler: Received shutdown"); - } } } } diff --git a/validator-api/src/network_monitor/monitor/sender.rs b/validator-api/src/network_monitor/monitor/sender.rs index 48fea699dd..c11f38b826 100644 --- a/validator-api/src/network_monitor/monitor/sender.rs +++ b/validator-api/src/network_monitor/monitor/sender.rs @@ -24,6 +24,7 @@ use std::pin::Pin; use std::sync::Arc; use std::task::Poll; use std::time::Duration; +use task::ShutdownListener; use gateway_client::bandwidth::BandwidthController; @@ -176,7 +177,11 @@ impl PacketSender { } } - pub(crate) fn spawn_gateways_pinger(&self, pinging_interval: Duration) { + pub(crate) fn spawn_gateways_pinger( + &self, + pinging_interval: Duration, + shutdown: ShutdownListener, + ) { let gateway_pinger = GatewayPinger::new( self.active_gateway_clients.clone(), self.fresh_gateway_client_data @@ -185,7 +190,7 @@ impl PacketSender { pinging_interval, ); - tokio::spawn(async move { gateway_pinger.run().await }); + tokio::spawn(async move { gateway_pinger.run(shutdown).await }); } fn new_gateway_client_handle( diff --git a/validator-api/src/node_status_api/cache.rs b/validator-api/src/node_status_api/cache.rs index 8a7259679b..9d4b20067c 100644 --- a/validator-api/src/node_status_api/cache.rs +++ b/validator-api/src/node_status_api/cache.rs @@ -123,17 +123,28 @@ impl NodeStatusCacheRefresher { let mut fallback_interval = time::interval(self.fallback_caching_interval); while !shutdown.is_shutdown() { tokio::select! { + biased; + _ = shutdown.recv() => { + log::trace!("NodeStatusCacheRefresher: Received shutdown"); + } // Update node status cache when the contract cache / validator cache is updated Ok(_) = self.contract_cache_listener.changed() => { - self.update_on_notify(&mut fallback_interval).await; + tokio::select! { + _ = self.update_on_notify(&mut fallback_interval) => (), + _ = shutdown.recv() => { + log::trace!("NodeStatusCacheRefresher: Received shutdown"); + } + } } // ... however, if we don't receive any notifications we fall back to periodic // refreshes _ = fallback_interval.tick() => { - self.update_on_timer().await; - } - _ = shutdown.recv() => { - log::trace!("NodeStatusCacheRefresher: Received shutdown"); + tokio::select! { + _ = self.update_on_timer() => (), + _ = shutdown.recv() => { + log::trace!("NodeStatusCacheRefresher: Received shutdown"); + } + } } } } diff --git a/validator-api/src/node_status_api/uptime_updater.rs b/validator-api/src/node_status_api/uptime_updater.rs index 56e7655aae..0e60650f65 100644 --- a/validator-api/src/node_status_api/uptime_updater.rs +++ b/validator-api/src/node_status_api/uptime_updater.rs @@ -72,14 +72,20 @@ impl HistoricalUptimeUpdater { while !shutdown.is_shutdown() { tokio::select! { _ = sleep(ONE_DAY) => { - if let Err(err) = self.update_uptimes().await { - // normally that would have been a warning rather than an error, - // however, in this case it implies some underlying issues with our database - // that might affect the entire program - error!( - "We failed to update daily uptimes of active nodes - {}", - err - ) + tokio::select! { + biased; + _ = shutdown.recv() => { + trace!("UpdateHandler: Received shutdown"); + } + Err(err) = self.update_uptimes() => { + // normally that would have been a warning rather than an error, + // however, in this case it implies some underlying issues with our database + // that might affect the entire program + error!( + "We failed to update daily uptimes of active nodes - {}", + err + ); + } } } _ = shutdown.recv() => { diff --git a/validator-api/src/rewarded_set_updater/mod.rs b/validator-api/src/rewarded_set_updater/mod.rs index 627452d673..d7cef3e373 100644 --- a/validator-api/src/rewarded_set_updater/mod.rs +++ b/validator-api/src/rewarded_set_updater/mod.rs @@ -24,6 +24,7 @@ use rand::rngs::OsRng; use std::collections::HashSet; use std::ops::Deref; use std::time::Duration; +use task::ShutdownListener; use time::OffsetDateTime; use tokio::time::sleep; use validator_client::nymd::{Coin, SigningNymdClient}; @@ -328,11 +329,14 @@ impl RewardedSetUpdater { Ok(()) } - pub(crate) async fn run(&mut self) -> Result<(), RewardingError> { + pub(crate) async fn run( + &mut self, + mut shutdown: ShutdownListener, + ) -> Result<(), RewardingError> { self.validator_cache.wait_for_initial_values().await; let mut epoch = self.epoch().await?; - loop { + while !shutdown.is_shutdown() { // wait until the cache refresher determined its time to update the rewarded/active sets let time = OffsetDateTime::now_utc().unix_timestamp(); epoch.update_to_latest(self).await?; @@ -351,7 +355,16 @@ impl RewardedSetUpdater { ); // Sleep at most 300 before checking again, to keep logs busy let s = time_to_epoch_change.min(300).max(0) as u64; - sleep(Duration::from_secs(s)).await; + tokio::select! { + _ = sleep(Duration::from_secs(s)) => { + trace!("Checking again for updating rewarded/active sets"); + } + _ = shutdown.recv() => { + trace!("RewardedSetUpdater: Received shutdown"); + // This break should not be necessary, but there's a following sleep after this + break; + } + } } // allow some blocks to pass sleep(Duration::from_secs(10)).await; From d289c46e876cfc98764453271e78ce7e1788d505 Mon Sep 17 00:00:00 2001 From: =?UTF-8?q?Bogdan-=C8=98tefan=20Neac=C5=9Fu?= Date: Wed, 31 Aug 2022 16:27:02 +0300 Subject: [PATCH 03/46] Feature/nr err report (#1576) * common/socks5: Use thiserror and add copyright notice * Send allowlist failure msg back to socks5 client * Add some serde unit tests * Fix clippy after rustup update * Update changelog --- CHANGELOG.md | 2 + Cargo.lock | 1 + clients/socks5/src/socks/mixnet_responses.rs | 7 ++ common/socks5/requests/Cargo.toml | 1 + common/socks5/requests/src/lib.rs | 5 + common/socks5/requests/src/msg.rs | 43 ++++--- .../src/network_requester_response.rs | 112 ++++++++++++++++++ common/socks5/requests/src/request.rs | 42 +++---- common/socks5/requests/src/response.rs | 9 +- .../network-requester/src/core.rs | 17 ++- 10 files changed, 196 insertions(+), 43 deletions(-) create mode 100644 common/socks5/requests/src/network_requester_response.rs diff --git a/CHANGELOG.md b/CHANGELOG.md index 931457972f..709ae4b36d 100644 --- a/CHANGELOG.md +++ b/CHANGELOG.md @@ -70,6 +70,7 @@ Post 1.0.0 release, the changelog format is based on [Keep a Changelog](https:// - gateway, network-statistics: include gateway id in the sent statistical data ([#1478]) - network explorer: tweak how active set probability is shown ([#1503]) - validator-api: rewarder set update fails without panicking on possible nymd queries ([#1520]) +- network-requester, socks5 client (nym-connect): send and receive respectively a message error to be displayed about filter check failure ([#1576]) [#1249]: https://github.com/nymtech/nym/pull/1249 @@ -100,6 +101,7 @@ Post 1.0.0 release, the changelog format is based on [Keep a Changelog](https:// [#1503]: https://github.com/nymtech/nym/pull/1503 [#1520]: https://github.com/nymtech/nym/pull/1520 [#1573]: https://github.com/nymtech/nym/pull/1573 +[#1576]: https://github.com/nymtech/nym/pull/1576 ## [v1.0.1](https://github.com/nymtech/nym/tree/v1.0.1) (2022-05-04) diff --git a/Cargo.lock b/Cargo.lock index e7c7440bf6..36796c5ed8 100644 --- a/Cargo.lock +++ b/Cargo.lock @@ -5211,6 +5211,7 @@ version = "0.1.0" dependencies = [ "nymsphinx-addressing", "ordered-buffer", + "thiserror", ] [[package]] diff --git a/clients/socks5/src/socks/mixnet_responses.rs b/clients/socks5/src/socks/mixnet_responses.rs index 3146967711..cdc9ec3f4d 100644 --- a/clients/socks5/src/socks/mixnet_responses.rs +++ b/clients/socks5/src/socks/mixnet_responses.rs @@ -54,6 +54,13 @@ impl MixnetResponseListener { return; } Ok(Message::Response(data)) => data, + Ok(Message::NetworkRequesterResponse(r)) => { + error!( + "Network requester failed on connection id {} with error: {}", + r.connection_id, r.network_requester_error + ); + return; + } }; self.controller_sender diff --git a/common/socks5/requests/Cargo.toml b/common/socks5/requests/Cargo.toml index 39ccacb4b1..1b6b6266ad 100644 --- a/common/socks5/requests/Cargo.toml +++ b/common/socks5/requests/Cargo.toml @@ -9,3 +9,4 @@ edition = "2021" [dependencies] nymsphinx-addressing = { path = "../../../common/nymsphinx/addressing" } ordered-buffer = {path = "../ordered-buffer"} +thiserror = "1" diff --git a/common/socks5/requests/src/lib.rs b/common/socks5/requests/src/lib.rs index 434bf0df24..b7da4498fa 100644 --- a/common/socks5/requests/src/lib.rs +++ b/common/socks5/requests/src/lib.rs @@ -1,7 +1,12 @@ +// Copyright 2020-2022 - Nym Technologies SA +// SPDX-License-Identifier: Apache-2.0 + pub mod msg; +pub mod network_requester_response; pub mod request; pub mod response; pub use msg::*; +pub use network_requester_response::*; pub use request::*; pub use response::*; diff --git a/common/socks5/requests/src/msg.rs b/common/socks5/requests/src/msg.rs index 68d1160b4e..b13f346f35 100644 --- a/common/socks5/requests/src/msg.rs +++ b/common/socks5/requests/src/msg.rs @@ -1,36 +1,40 @@ -// Copyright 2022 - Nym Technologies SA +// Copyright 2020-2022 - Nym Technologies SA // SPDX-License-Identifier: Apache-2.0 +use thiserror::Error; + +use crate::network_requester_response::{Error as NrError, NetworkRequesterResponse}; use crate::request::{Request, RequestError}; use crate::response::{Response, ResponseError}; -#[derive(Debug)] +#[derive(Debug, Error)] pub enum MessageError { + #[error("{0}")] Request(RequestError), - Response(ResponseError), - NoData, - UnknownMessageType, -} -impl std::fmt::Display for MessageError { - fn fmt(&self, f: &mut std::fmt::Formatter<'_>) -> std::fmt::Result { - match self { - MessageError::Request(r) => write!(f, "{}", r), - MessageError::Response(r) => write!(f, "{:?}", r), - MessageError::NoData => write!(f, "no data provided"), - MessageError::UnknownMessageType => write!(f, "unknown message type received"), - } - } + #[error("{0:?}")] + Response(ResponseError), + + #[error("{0}")] + NetworkRequesterResponseError(NrError), + + #[error("no data")] + NoData, + + #[error("unknown message type received")] + UnknownMessageType, } pub enum Message { Request(Request), Response(Response), + NetworkRequesterResponse(NetworkRequesterResponse), } impl Message { const REQUEST_FLAG: u8 = 0; const RESPONSE_FLAG: u8 = 1; + const NR_RESPONSE_FLAG: u8 = 2; pub fn conn_id(&self) -> u64 { match self { @@ -39,6 +43,7 @@ impl Message { Request::Send(conn_id, _, _) => *conn_id, }, Message::Response(resp) => resp.connection_id, + Message::NetworkRequesterResponse(resp) => resp.connection_id, } } @@ -49,6 +54,7 @@ impl Message { Request::Send(_, data, _) => data.len(), }, Message::Response(resp) => resp.data.len(), + Message::NetworkRequesterResponse(_) => 0, } } @@ -65,6 +71,10 @@ impl Message { Response::try_from_bytes(&b[1..]) .map(Message::Response) .map_err(MessageError::Response) + } else if b[0] == Self::NR_RESPONSE_FLAG { + NetworkRequesterResponse::try_from_bytes(&b[1..]) + .map(Message::NetworkRequesterResponse) + .map_err(MessageError::NetworkRequesterResponseError) } else { Err(MessageError::UnknownMessageType) } @@ -78,6 +88,9 @@ impl Message { Self::Response(r) => std::iter::once(Self::RESPONSE_FLAG) .chain(r.into_bytes().iter().cloned()) .collect(), + Self::NetworkRequesterResponse(r) => std::iter::once(Self::NR_RESPONSE_FLAG) + .chain(r.into_bytes().iter().cloned()) + .collect(), } } } diff --git a/common/socks5/requests/src/network_requester_response.rs b/common/socks5/requests/src/network_requester_response.rs new file mode 100644 index 0000000000..64e459dfb0 --- /dev/null +++ b/common/socks5/requests/src/network_requester_response.rs @@ -0,0 +1,112 @@ +// Copyright 2022 - Nym Technologies SA +// SPDX-License-Identifier: Apache-2.0 + +use crate::ConnectionId; + +#[derive(Debug)] +pub struct NetworkRequesterResponse { + pub connection_id: ConnectionId, + pub network_requester_error: String, +} + +#[derive(Debug, thiserror::Error, PartialEq, Eq)] +pub enum Error { + #[error("no data provided")] + NoData, + + #[error("not enough bytes to recover the connection id")] + ConnectionIdTooShort, + + #[error("message is not utf8 encoded")] + MalformedErrorMessage(#[from] std::string::FromUtf8Error), +} + +impl NetworkRequesterResponse { + pub fn new(connection_id: ConnectionId, network_requester_error: String) -> Self { + NetworkRequesterResponse { + connection_id, + network_requester_error, + } + } + + pub fn try_from_bytes(b: &[u8]) -> Result { + if b.is_empty() { + return Err(Error::NoData); + } + + if b.len() < 8 { + return Err(Error::ConnectionIdTooShort); + } + + let mut connection_id_bytes = b.to_vec(); + let network_requester_error_bytes = connection_id_bytes.split_off(8); + + let connection_id = u64::from_be_bytes([ + connection_id_bytes[0], + connection_id_bytes[1], + connection_id_bytes[2], + connection_id_bytes[3], + connection_id_bytes[4], + connection_id_bytes[5], + connection_id_bytes[6], + connection_id_bytes[7], + ]); + let network_requester_error = String::from_utf8(network_requester_error_bytes)?; + + Ok(NetworkRequesterResponse { + connection_id, + network_requester_error, + }) + } + + pub fn into_bytes(self) -> Vec { + self.connection_id + .to_be_bytes() + .iter() + .cloned() + .chain(self.network_requester_error.into_bytes().into_iter()) + .collect() + } +} + +#[cfg(test)] +mod network_requester_response_serde_tests { + use super::*; + + #[test] + fn simple_serde() { + let conn_id = 42; + let network_requester_error = String::from("This is a test msg"); + let response = NetworkRequesterResponse::new(conn_id, network_requester_error.clone()); + let bytes = response.into_bytes(); + let deserialized_response = NetworkRequesterResponse::try_from_bytes(&bytes).unwrap(); + + assert_eq!(conn_id, deserialized_response.connection_id); + assert_eq!( + network_requester_error, + deserialized_response.network_requester_error + ); + } + + #[test] + fn deserialization_errors() { + let err = NetworkRequesterResponse::try_from_bytes(&[]).err().unwrap(); + assert_eq!(err, Error::NoData); + + let bytes: [u8; 5] = [1, 2, 3, 4, 5]; + let err = NetworkRequesterResponse::try_from_bytes(&bytes) + .err() + .unwrap(); + assert_eq!(err, Error::ConnectionIdTooShort); + + let bytes: Vec = 42u64 + .to_be_bytes() + .into_iter() + .chain([0, 159, 146, 150].into_iter()) + .collect(); + let err = NetworkRequesterResponse::try_from_bytes(&bytes) + .err() + .unwrap(); + assert!(matches!(err, Error::MalformedErrorMessage(_))); + } +} diff --git a/common/socks5/requests/src/request.rs b/common/socks5/requests/src/request.rs index b6551da1d4..f6921e362a 100644 --- a/common/socks5/requests/src/request.rs +++ b/common/socks5/requests/src/request.rs @@ -1,6 +1,9 @@ +// Copyright 2020-2022 - Nym Technologies SA +// SPDX-License-Identifier: Apache-2.0 + use nymsphinx_addressing::clients::{Recipient, RecipientFormattingError}; use std::convert::TryFrom; -use std::fmt::{self}; +use thiserror::Error; pub type ConnectionId = u64; pub type RemoteAddress = String; @@ -12,39 +15,30 @@ pub enum RequestFlag { Send = 1, } -#[derive(Debug)] +#[derive(Debug, Error)] pub enum RequestError { + #[error("not enough bytes to recover the length of the address")] AddressLengthTooShort, + + #[error("not enough bytes to recover the address")] AddressTooShort, + + #[error("not enough bytes to recover the connection id")] ConnectionIdTooShort, + + #[error("no data provided")] NoData, + + #[error("request of unknown type")] UnknownRequestFlag, + + #[error("too short return address")] ReturnAddressTooShort, + + #[error("malformed return address - {0}")] MalformedReturnAddress(RecipientFormattingError), } -impl fmt::Display for RequestError { - fn fmt(&self, f: &mut std::fmt::Formatter<'_>) -> fmt::Result { - match self { - RequestError::AddressLengthTooShort => { - write!(f, "not enough bytes to recover the length of the address") - } - RequestError::AddressTooShort => write!(f, "not enough bytes to recover the address"), - RequestError::ConnectionIdTooShort => { - write!(f, "not enough bytes to recover the connection id") - } - RequestError::NoData => write!(f, "no data provided"), - RequestError::UnknownRequestFlag => write!(f, "request of unknown type"), - RequestError::ReturnAddressTooShort => write!(f, "too short return address"), - RequestError::MalformedReturnAddress(recipient_err) => { - write!(f, "malformed return address - {}", recipient_err) - } - } - } -} - -impl std::error::Error for RequestError {} - impl RequestError { pub fn is_malformed_return(&self) -> bool { matches!(self, RequestError::MalformedReturnAddress(_)) diff --git a/common/socks5/requests/src/response.rs b/common/socks5/requests/src/response.rs index ab409eb03e..07d78be964 100644 --- a/common/socks5/requests/src/response.rs +++ b/common/socks5/requests/src/response.rs @@ -1,8 +1,15 @@ +// Copyright 2020-2022 - Nym Technologies SA +// SPDX-License-Identifier: Apache-2.0 + +use thiserror::Error; + use crate::ConnectionId; -#[derive(Debug, PartialEq, Eq)] +#[derive(Debug, Error, PartialEq, Eq)] pub enum ResponseError { + #[error("not enough bytes to recover the connection id")] ConnectionIdTooShort, + #[error("no data provided")] NoData, } /// A remote network response retrieved by the Socks5 service provider. This diff --git a/service-providers/network-requester/src/core.rs b/service-providers/network-requester/src/core.rs index b7d94a3b4f..c3bf589a65 100644 --- a/service-providers/network-requester/src/core.rs +++ b/service-providers/network-requester/src/core.rs @@ -13,7 +13,9 @@ use log::*; use nymsphinx::addressing::clients::Recipient; use nymsphinx::receiver::ReconstructedMessage; use proxy_helpers::connection_controller::{Controller, ControllerCommand, ControllerSender}; -use socks5_requests::{ConnectionId, Message as Socks5Message, Request, Response}; +use socks5_requests::{ + ConnectionId, Message as Socks5Message, NetworkRequesterResponse, Request, Response, +}; use statistics_common::collector::StatisticsSender; use std::path::PathBuf; use std::sync::atomic::{AtomicUsize, Ordering}; @@ -192,7 +194,16 @@ impl ServiceProvider { return_address: Recipient, ) { if !self.open_proxy && !self.outbound_request_filter.check(&remote_addr) { - log::info!("Domain {:?} failed filter check", remote_addr); + let log_msg = format!("Domain {:?} failed filter check", remote_addr); + log::info!("{}", log_msg); + mix_input_sender + .unbounded_send(( + Socks5Message::NetworkRequesterResponse(NetworkRequesterResponse::new( + conn_id, log_msg, + )), + return_address, + )) + .unwrap(); return; } @@ -275,7 +286,7 @@ impl ServiceProvider { self.handle_proxy_send(controller_sender, conn_id, data, closed) } }, - Socks5Message::Response(_) => {} + Socks5Message::Response(_) | Socks5Message::NetworkRequesterResponse(_) => {} } } From a2c6abd3dd1f536deb0613cf3777be5dee5af4ac Mon Sep 17 00:00:00 2001 From: =?UTF-8?q?J=C4=99drzej=20Stuczy=C5=84ski?= Date: Thu, 1 Sep 2022 17:10:17 +0100 Subject: [PATCH 04/46] Made nodes_to_remove field in mixnet MigrateMsg public --- common/cosmwasm-smart-contracts/mixnet-contract/src/msg.rs | 2 +- 1 file changed, 1 insertion(+), 1 deletion(-) diff --git a/common/cosmwasm-smart-contracts/mixnet-contract/src/msg.rs b/common/cosmwasm-smart-contracts/mixnet-contract/src/msg.rs index a9b3e8fbf3..8d9703e684 100644 --- a/common/cosmwasm-smart-contracts/mixnet-contract/src/msg.rs +++ b/common/cosmwasm-smart-contracts/mixnet-contract/src/msg.rs @@ -217,7 +217,7 @@ pub enum QueryMsg { #[serde(rename_all = "snake_case")] pub struct MigrateMsg { pub mixnet_denom: String, - nodes_to_remove: Option>, + pub nodes_to_remove: Option>, } impl MigrateMsg { From 10221a176741e139e7e842ef64fe66a7141b1066 Mon Sep 17 00:00:00 2001 From: =?UTF-8?q?Bogdan-=C8=98tefan=20Neac=C5=9Fu?= Date: Mon, 5 Sep 2022 12:25:57 +0300 Subject: [PATCH 05/46] Migrate heights to timestamps (#1584) * Migrate heights to timestamps * Improve test with a possible scenario * Use account id instead of address, as returned by the query --- .../vesting-contract/src/messages.rs | 5 + contracts/vesting/src/contract.rs | 68 ++++++++++++- contracts/vesting/src/errors.rs | 2 + contracts/vesting/src/vesting/mod.rs | 97 ++++++++++++++++++- 4 files changed, 168 insertions(+), 4 deletions(-) diff --git a/common/cosmwasm-smart-contracts/vesting-contract/src/messages.rs b/common/cosmwasm-smart-contracts/vesting-contract/src/messages.rs index a6e90c917c..868df6ac70 100644 --- a/common/cosmwasm-smart-contracts/vesting-contract/src/messages.rs +++ b/common/cosmwasm-smart-contracts/vesting-contract/src/messages.rs @@ -119,6 +119,11 @@ pub enum ExecuteMsg { UpdateLockedPledgeCap { amount: Uint128, }, + MigrateHeightsToTimestamps { + account_id: u32, + mix_identity: String, + height_timestamp_map: Vec<(u64, u64)>, + }, } #[derive(Serialize, Deserialize, Clone, Debug, PartialEq, Eq, JsonSchema)] diff --git a/contracts/vesting/src/contract.rs b/contracts/vesting/src/contract.rs index 4f9722fcd4..e6b5ce915e 100644 --- a/contracts/vesting/src/contract.rs +++ b/contracts/vesting/src/contract.rs @@ -1,8 +1,9 @@ use crate::errors::ContractError; use crate::queued_migrations::migrate_config_from_env; use crate::storage::{ - account_from_address, locked_pledge_cap, update_locked_pledge_cap, BlockTimestampSecs, ADMIN, - DELEGATIONS, MIXNET_CONTRACT_ADDRESS, MIX_DENOM, + account_from_address, locked_pledge_cap, remove_delegation, save_delegation, + update_locked_pledge_cap, BlockTimestampSecs, ADMIN, DELEGATIONS, MIXNET_CONTRACT_ADDRESS, + MIX_DENOM, }; use crate::traits::{ DelegatingAccount, GatewayBondingAccount, MixnodeBondingAccount, VestingAccount, @@ -129,6 +130,17 @@ pub fn execute( ExecuteMsg::UpdateStakingAddress { to_address } => { try_update_staking_address(to_address, info, deps) } + ExecuteMsg::MigrateHeightsToTimestamps { + account_id, + mix_identity, + height_timestamp_map, + } => try_migrate_heights_to_timestamps( + account_id, + mix_identity, + height_timestamp_map, + info, + deps, + ), } } @@ -240,6 +252,58 @@ fn try_update_staking_address( } } +pub fn try_migrate_heights_to_timestamps( + account_id: u32, + mix_identity: String, + mut height_timestamp_map: Vec<(u64, u64)>, + info: MessageInfo, + deps: DepsMut<'_>, +) -> Result { + if info.sender != ADMIN.load(deps.storage)? { + return Err(ContractError::NotAdmin(info.sender.as_str().to_string())); + } + let mut delegation_heights = DELEGATIONS + .prefix((account_id, mix_identity.clone())) + .range(deps.storage, None, None, Order::Ascending) + .collect::>>()?; + + if height_timestamp_map.len() != delegation_heights.len() { + return Err(ContractError::MigrateHeightsToTimestamp { + reason: format!( + "Received {} entries in height_timestamp_map, but {} entries are in storage", + height_timestamp_map.len(), + delegation_heights.len() + ), + }); + } + + height_timestamp_map.sort_by_key(|k| k.0); + delegation_heights.sort_by_key(|k| k.0); + + if height_timestamp_map + .iter() + .zip(delegation_heights.iter()) + .any(|(mapping, height)| mapping.0 != height.0) + { + return Err(ContractError::MigrateHeightsToTimestamp { + reason: String::from("height_timestamp_map heights mismatch with stored delegations"), + }); + } + + for ((old_key, new_key), (_, amount)) in + height_timestamp_map.iter().zip(delegation_heights.iter()) + { + remove_delegation((account_id, mix_identity.clone(), *old_key), deps.storage)?; + save_delegation( + (account_id, mix_identity.clone(), *new_key), + *amount, + deps.storage, + )?; + } + + Ok(Response::default()) +} + // Owner or staking pub fn try_bond_gateway( gateway: Gateway, diff --git a/contracts/vesting/src/errors.rs b/contracts/vesting/src/errors.rs index 867620ff8f..a265477dff 100644 --- a/contracts/vesting/src/errors.rs +++ b/contracts/vesting/src/errors.rs @@ -48,4 +48,6 @@ pub enum ContractError { MinVestingFunds { sent: u128, need: u128 }, #[error("VESTING ({}): Maximum amount of locked coins has already been pledged: {current}, cap is {cap}", line!())] LockedPledgeCapReached { current: Uint128, cap: Uint128 }, + #[error("{reason}")] + MigrateHeightsToTimestamp { reason: String }, } diff --git a/contracts/vesting/src/vesting/mod.rs b/contracts/vesting/src/vesting/mod.rs index 6fc9c56204..5289f978db 100644 --- a/contracts/vesting/src/vesting/mod.rs +++ b/contracts/vesting/src/vesting/mod.rs @@ -36,8 +36,8 @@ pub fn populate_vesting_periods( #[cfg(test)] mod tests { - use crate::contract::execute; - use crate::storage::load_account; + use crate::contract::*; + use crate::storage::*; use crate::support::tests::helpers::{ init_contract, vesting_account_mid_fixture, vesting_account_new_fixture, TEST_COIN_DENOM, }; @@ -925,4 +925,97 @@ mod tests { // the 50M delegation wasn't a thing here for VESTING tokens either assert_eq!(delegated_vesting.amount, Uint128::zero()); } + + #[test] + fn migrate_heights_to_timestamps() { + let mut deps = init_contract(); + let mut env = mock_env(); + + let account = vesting_account_new_fixture(&mut deps.storage, &env); + let mix_identity = String::from("identity"); + let mut curr_block = env.block.clone(); + let mut delegation_blocks = std::iter::from_fn(move || { + curr_block.height += 1; + curr_block.time = curr_block.time.plus_seconds(5); + Some(curr_block.clone()) + }) + .take(100) + .collect::>(); + + for block in delegation_blocks.iter() { + DELEGATIONS + .save( + &mut deps.storage, + (account.storage_key(), mix_identity.clone(), block.height), + &Uint128::new(90_000_000_000), + ) + .unwrap(); + } + + let delegations = try_get_delegation_times( + deps.as_ref(), + account.owner_address().as_str(), + mix_identity.clone(), + ) + .unwrap(); + assert_eq!( + delegations.delegation_timestamps.len(), + delegation_blocks.len() + ); + for (heights, delegation_block) in delegations + .delegation_timestamps + .iter() + .zip(delegation_blocks.iter()) + { + assert_eq!(*heights, delegation_block.height); + } + + let height_timestamp_map = delegation_blocks + .iter() + .map(|block| (block.height, block.time.seconds())) + .collect(); + let admin = ADMIN.load(&deps.storage).unwrap(); + try_migrate_heights_to_timestamps( + account.storage_key(), + mix_identity.clone(), + height_timestamp_map, + mock_info(&admin, &[]), + deps.as_mut(), + ) + .unwrap(); + + // Some new delegation appears during migration + env.block.height += 200; + env.block.time = env.block.time.plus_seconds(1000); + delegation_blocks.push(env.block.clone()); + account + .try_delegate_to_mixnode( + String::from("identity"), + Coin { + amount: Uint128::new(90_000_000_000), + denom: TEST_COIN_DENOM.to_string(), + }, + &env, + &mut deps.storage, + ) + .unwrap(); + + let delegations = try_get_delegation_times( + deps.as_ref(), + account.owner_address().as_str(), + mix_identity.clone(), + ) + .unwrap(); + assert_eq!( + delegations.delegation_timestamps.len(), + delegation_blocks.len() + ); + for (timestamp, delegation_block) in delegations + .delegation_timestamps + .iter() + .zip(delegation_blocks.iter()) + { + assert_eq!(*timestamp, delegation_block.time.seconds()); + } + } } From 7e7072258df79ccb07098d7d9c490b6ad3b9e075 Mon Sep 17 00:00:00 2001 From: Mark Sinclair Date: Mon, 5 Sep 2022 12:06:35 +0100 Subject: [PATCH 06/46] Add `nym-cli` tool (#1577) Co-authored-by: tommy --- CHANGELOG.md | 3 +- Cargo.lock | 153 +- Cargo.toml | 2 + Makefile | 3 + .../src/nymd/cosmwasm_client/types.rs | 10 +- .../validator-client/src/nymd/mod.rs | 44 +- .../validator-client/src/nymd/wallet/mod.rs | 13 +- common/commands/Cargo.toml | 32 + common/commands/README.md | 13 + common/commands/src/coconut/mod.rs | 4 + common/commands/src/context/errors.rs | 18 + common/commands/src/context/mod.rs | 138 + common/commands/src/lib.rs | 7 + common/commands/src/utils.rs | 44 + .../commands/src/validator/account/balance.rs | 72 + .../commands/src/validator/account/create.rs | 24 + common/commands/src/validator/account/mod.rs | 28 + .../commands/src/validator/account/pubkey.rs | 89 + common/commands/src/validator/account/send.rs | 66 + .../src/validator/block/block_time.rs | 23 + .../src/validator/block/current_height.rs | 19 + common/commands/src/validator/block/get.rs | 24 + common/commands/src/validator/block/mod.rs | 25 + .../validator/cosmwasm/execute_contract.rs | 60 + .../src/validator/cosmwasm/init_contract.rs | 78 + .../validator/cosmwasm/migrate_contract.rs | 51 + common/commands/src/validator/cosmwasm/mod.rs | 28 + .../src/validator/cosmwasm/upload_contract.rs | 37 + .../mixnet/delegators/delegate_to_mixnode.rs | 31 + .../src/validator/mixnet/delegators/mod.rs | 35 + .../delegators/query_for_delegations.rs | 129 + .../rewards/claim_delegator_reward.rs | 23 + .../mixnet/delegators/rewards/mod.rs | 22 + .../rewards/vesting_claim_delegator_reward.rs | 23 + .../delegators/undelegate_from_mixnode.rs | 23 + .../delegators/vesting_delegate_to_mixnode.rs | 34 + .../vesting_undelegate_from_mixnode.rs | 26 + common/commands/src/validator/mixnet/mod.rs | 25 + .../mixnet/operators/gateway/bond_gateway.rs | 77 + .../validator/mixnet/operators/gateway/mod.rs | 28 + .../operators/gateway/unbond_gateway.rs | 20 + .../operators/gateway/vesting_bond_gateway.rs | 76 + .../gateway/vesting_unbond_gateway.rs | 20 + .../mixnet/operators/mixnode/bond_mixnode.rs | 85 + .../mixnode/keys/decode_mixnode_key.rs | 17 + .../mixnet/operators/mixnode/keys/mod.rs | 19 + .../validator/mixnet/operators/mixnode/mod.rs | 37 + .../mixnode/rewards/claim_operator_reward.rs | 20 + .../mixnet/operators/mixnode/rewards/mod.rs | 22 + .../rewards/vesting_claim_operator_reward.rs | 23 + .../mixnet/operators/mixnode/settings/mod.rs | 22 + .../mixnode/settings/update_profit_percent.rs | 24 + .../settings/vesting_update_profit_percent.rs | 28 + .../operators/mixnode/unbond_mixnode.rs | 21 + .../operators/mixnode/vesting_bond_mixnode.rs | 86 + .../mixnode/vesting_unbond_mixnode.rs | 24 + .../src/validator/mixnet/operators/mod.rs | 22 + .../src/validator/mixnet/query/mod.rs | 22 + .../mixnet/query/query_all_gateways.rs | 52 + .../mixnet/query/query_all_mixnodes.rs | 60 + common/commands/src/validator/mod.rs | 10 + .../src/validator/signature/errors.rs | 13 + .../src/validator/signature/helpers.rs | 90 + .../commands/src/validator/signature/mod.rs | 24 + .../commands/src/validator/signature/sign.rs | 68 + .../src/validator/signature/verify.rs | 89 + .../validator/transactions/get_transaction.rs | 28 + .../src/validator/transactions/mod.rs | 22 + .../transactions/query_transactions.rs | 30 + .../commands/src/validator/vesting/balance.rs | 55 + .../vesting/create_vesting_schedule.rs | 83 + common/commands/src/validator/vesting/mod.rs | 28 + .../vesting/query_vesting_schedule.rs | 149 + .../src/validator/vesting/withdraw_vested.rs | 112 + common/network-defaults/envs/mainnet.env | 20 + common/network-defaults/envs/qa.env | 20 + examples/README.md | 9 + .../cli/commands/verify-signature}/Cargo.lock | 776 +-- .../cli/commands/verify-signature/Cargo.toml | 9 + .../cli/commands/verify-signature/README.md | 38 + .../cli/commands/verify-signature/src/main.rs | 43 + nym-connect/Cargo.lock | 1 + tools/nym-cli/Cargo.toml | 24 + tools/nym-cli/Makefile | 3 + tools/nym-cli/README.md | 139 + tools/nym-cli/src/completion.rs | 10 + tools/nym-cli/src/main.rs | 168 + tools/nym-cli/src/validator/account.rs | 79 + tools/nym-cli/src/validator/block.rs | 35 + tools/nym-cli/src/validator/cosmwasm.rs | 45 + .../src/validator/mixnet/delegators/mod.rs | 32 + .../mixnet/delegators/rewards/mod.rs | 19 + tools/nym-cli/src/validator/mixnet/mod.rs | 25 + .../mixnet/operators/gateways/mod.rs | 22 + .../mixnet/operators/mixnodes/keys/mod.rs | 13 + .../mixnet/operators/mixnodes/mod.rs | 35 + .../mixnet/operators/mixnodes/rewards/mod.rs | 19 + .../mixnet/operators/mixnodes/settings/mod.rs | 19 + .../src/validator/mixnet/operators/mod.rs | 24 + .../nym-cli/src/validator/mixnet/query/mod.rs | 28 + tools/nym-cli/src/validator/mod.rs | 10 + tools/nym-cli/src/validator/signature.rs | 30 + tools/nym-cli/src/validator/transactions.rs | 29 + tools/nym-cli/src/validator/vesting.rs | 49 + tools/nym-cli/user-docs/fig-spec.ts | 5048 +++++++++++++++++ tools/nym-cli/user-docs/tsconfig.json | 5 + 106 files changed, 9512 insertions(+), 399 deletions(-) create mode 100644 common/commands/Cargo.toml create mode 100644 common/commands/README.md create mode 100644 common/commands/src/coconut/mod.rs create mode 100644 common/commands/src/context/errors.rs create mode 100644 common/commands/src/context/mod.rs create mode 100644 common/commands/src/lib.rs create mode 100644 common/commands/src/utils.rs create mode 100644 common/commands/src/validator/account/balance.rs create mode 100644 common/commands/src/validator/account/create.rs create mode 100644 common/commands/src/validator/account/mod.rs create mode 100644 common/commands/src/validator/account/pubkey.rs create mode 100644 common/commands/src/validator/account/send.rs create mode 100644 common/commands/src/validator/block/block_time.rs create mode 100644 common/commands/src/validator/block/current_height.rs create mode 100644 common/commands/src/validator/block/get.rs create mode 100644 common/commands/src/validator/block/mod.rs create mode 100644 common/commands/src/validator/cosmwasm/execute_contract.rs create mode 100644 common/commands/src/validator/cosmwasm/init_contract.rs create mode 100644 common/commands/src/validator/cosmwasm/migrate_contract.rs create mode 100644 common/commands/src/validator/cosmwasm/mod.rs create mode 100644 common/commands/src/validator/cosmwasm/upload_contract.rs create mode 100644 common/commands/src/validator/mixnet/delegators/delegate_to_mixnode.rs create mode 100644 common/commands/src/validator/mixnet/delegators/mod.rs create mode 100644 common/commands/src/validator/mixnet/delegators/query_for_delegations.rs create mode 100644 common/commands/src/validator/mixnet/delegators/rewards/claim_delegator_reward.rs create mode 100644 common/commands/src/validator/mixnet/delegators/rewards/mod.rs create mode 100644 common/commands/src/validator/mixnet/delegators/rewards/vesting_claim_delegator_reward.rs create mode 100644 common/commands/src/validator/mixnet/delegators/undelegate_from_mixnode.rs create mode 100644 common/commands/src/validator/mixnet/delegators/vesting_delegate_to_mixnode.rs create mode 100644 common/commands/src/validator/mixnet/delegators/vesting_undelegate_from_mixnode.rs create mode 100644 common/commands/src/validator/mixnet/mod.rs create mode 100644 common/commands/src/validator/mixnet/operators/gateway/bond_gateway.rs create mode 100644 common/commands/src/validator/mixnet/operators/gateway/mod.rs create mode 100644 common/commands/src/validator/mixnet/operators/gateway/unbond_gateway.rs create mode 100644 common/commands/src/validator/mixnet/operators/gateway/vesting_bond_gateway.rs create mode 100644 common/commands/src/validator/mixnet/operators/gateway/vesting_unbond_gateway.rs create mode 100644 common/commands/src/validator/mixnet/operators/mixnode/bond_mixnode.rs create mode 100644 common/commands/src/validator/mixnet/operators/mixnode/keys/decode_mixnode_key.rs create mode 100644 common/commands/src/validator/mixnet/operators/mixnode/keys/mod.rs create mode 100644 common/commands/src/validator/mixnet/operators/mixnode/mod.rs create mode 100644 common/commands/src/validator/mixnet/operators/mixnode/rewards/claim_operator_reward.rs create mode 100644 common/commands/src/validator/mixnet/operators/mixnode/rewards/mod.rs create mode 100644 common/commands/src/validator/mixnet/operators/mixnode/rewards/vesting_claim_operator_reward.rs create mode 100644 common/commands/src/validator/mixnet/operators/mixnode/settings/mod.rs create mode 100644 common/commands/src/validator/mixnet/operators/mixnode/settings/update_profit_percent.rs create mode 100644 common/commands/src/validator/mixnet/operators/mixnode/settings/vesting_update_profit_percent.rs create mode 100644 common/commands/src/validator/mixnet/operators/mixnode/unbond_mixnode.rs create mode 100644 common/commands/src/validator/mixnet/operators/mixnode/vesting_bond_mixnode.rs create mode 100644 common/commands/src/validator/mixnet/operators/mixnode/vesting_unbond_mixnode.rs create mode 100644 common/commands/src/validator/mixnet/operators/mod.rs create mode 100644 common/commands/src/validator/mixnet/query/mod.rs create mode 100644 common/commands/src/validator/mixnet/query/query_all_gateways.rs create mode 100644 common/commands/src/validator/mixnet/query/query_all_mixnodes.rs create mode 100644 common/commands/src/validator/mod.rs create mode 100644 common/commands/src/validator/signature/errors.rs create mode 100644 common/commands/src/validator/signature/helpers.rs create mode 100644 common/commands/src/validator/signature/mod.rs create mode 100644 common/commands/src/validator/signature/sign.rs create mode 100644 common/commands/src/validator/signature/verify.rs create mode 100644 common/commands/src/validator/transactions/get_transaction.rs create mode 100644 common/commands/src/validator/transactions/mod.rs create mode 100644 common/commands/src/validator/transactions/query_transactions.rs create mode 100644 common/commands/src/validator/vesting/balance.rs create mode 100644 common/commands/src/validator/vesting/create_vesting_schedule.rs create mode 100644 common/commands/src/validator/vesting/mod.rs create mode 100644 common/commands/src/validator/vesting/query_vesting_schedule.rs create mode 100644 common/commands/src/validator/vesting/withdraw_vested.rs create mode 100644 common/network-defaults/envs/mainnet.env create mode 100644 common/network-defaults/envs/qa.env create mode 100644 examples/README.md rename {tools => examples/cli/commands/verify-signature}/Cargo.lock (82%) create mode 100644 examples/cli/commands/verify-signature/Cargo.toml create mode 100644 examples/cli/commands/verify-signature/README.md create mode 100644 examples/cli/commands/verify-signature/src/main.rs create mode 100644 tools/nym-cli/Cargo.toml create mode 100644 tools/nym-cli/Makefile create mode 100644 tools/nym-cli/README.md create mode 100644 tools/nym-cli/src/completion.rs create mode 100644 tools/nym-cli/src/main.rs create mode 100644 tools/nym-cli/src/validator/account.rs create mode 100644 tools/nym-cli/src/validator/block.rs create mode 100644 tools/nym-cli/src/validator/cosmwasm.rs create mode 100644 tools/nym-cli/src/validator/mixnet/delegators/mod.rs create mode 100644 tools/nym-cli/src/validator/mixnet/delegators/rewards/mod.rs create mode 100644 tools/nym-cli/src/validator/mixnet/mod.rs create mode 100644 tools/nym-cli/src/validator/mixnet/operators/gateways/mod.rs create mode 100644 tools/nym-cli/src/validator/mixnet/operators/mixnodes/keys/mod.rs create mode 100644 tools/nym-cli/src/validator/mixnet/operators/mixnodes/mod.rs create mode 100644 tools/nym-cli/src/validator/mixnet/operators/mixnodes/rewards/mod.rs create mode 100644 tools/nym-cli/src/validator/mixnet/operators/mixnodes/settings/mod.rs create mode 100644 tools/nym-cli/src/validator/mixnet/operators/mod.rs create mode 100644 tools/nym-cli/src/validator/mixnet/query/mod.rs create mode 100644 tools/nym-cli/src/validator/mod.rs create mode 100644 tools/nym-cli/src/validator/signature.rs create mode 100644 tools/nym-cli/src/validator/transactions.rs create mode 100644 tools/nym-cli/src/validator/vesting.rs create mode 100644 tools/nym-cli/user-docs/fig-spec.ts create mode 100644 tools/nym-cli/user-docs/tsconfig.json diff --git a/CHANGELOG.md b/CHANGELOG.md index 709ae4b36d..0b9a93a151 100644 --- a/CHANGELOG.md +++ b/CHANGELOG.md @@ -6,15 +6,16 @@ Post 1.0.0 release, the changelog format is based on [Keep a Changelog](https:// ### Added +- nym-cli: added CLI tool for interacting with the Nyx blockchain and Nym mixnet smart contracts ([#1577]) - validator-client: added `query_contract_smart` and `query_contract_raw` on `NymdClient` ([#1558]) - ### Changed - validator-client: made `fee` argument optional for `execute` and `execute_multiple` ([#1541]) [#1541]: https://github.com/nymtech/nym/pull/1541 [#1558]: https://github.com/nymtech/nym/pull/1558 +[#1577]: https://github.com/nymtech/nym/pull/1577 ## [nym-binaries-1.0.2](https://github.com/nymtech/nym/tree/nym-binaries-1.0.2) diff --git a/Cargo.lock b/Cargo.lock index 36796c5ed8..363c907a18 100644 --- a/Cargo.lock +++ b/Cargo.lock @@ -583,6 +583,25 @@ dependencies = [ "textwrap 0.15.0", ] +[[package]] +name = "clap_complete" +version = "3.2.4" +source = "registry+https://github.com/rust-lang/crates.io-index" +checksum = "e4179da71abd56c26b54dd0c248cc081c1f43b0a1a7e8448e28e57a29baa993d" +dependencies = [ + "clap 3.2.8", +] + +[[package]] +name = "clap_complete_fig" +version = "3.2.4" +source = "registry+https://github.com/rust-lang/crates.io-index" +checksum = "ed37b4c0c1214673eba6ad8ea31666626bf72be98ffb323067d973c48b4964b9" +dependencies = [ + "clap 3.2.8", + "clap_complete", +] + [[package]] name = "clap_derive" version = "3.2.7" @@ -671,6 +690,18 @@ dependencies = [ "winapi", ] +[[package]] +name = "comfy-table" +version = "6.0.0" +source = "registry+https://github.com/rust-lang/crates.io-index" +checksum = "121d8a5b0346092c18a4b2fd6f620d7a06f0eb7ac0a45860939a0884bc579c56" +dependencies = [ + "crossterm", + "strum 0.24.1", + "strum_macros 0.24.3", + "unicode-width", +] + [[package]] name = "config" version = "0.1.0" @@ -1027,6 +1058,31 @@ dependencies = [ "lazy_static", ] +[[package]] +name = "crossterm" +version = "0.23.2" +source = "registry+https://github.com/rust-lang/crates.io-index" +checksum = "a2102ea4f781910f8a5b98dd061f4c2023f479ce7bb1236330099ceb5a93cf17" +dependencies = [ + "bitflags", + "crossterm_winapi", + "libc", + "mio", + "parking_lot 0.12.0", + "signal-hook", + "signal-hook-mio", + "winapi", +] + +[[package]] +name = "crossterm_winapi" +version = "0.9.0" +source = "registry+https://github.com/rust-lang/crates.io-index" +checksum = "2ae1b35a484aa10e07fe0638d02301c5ad24de82d310ccbd2f3693da5f09bf1c" +dependencies = [ + "winapi", +] + [[package]] name = "crunchy" version = "0.2.2" @@ -3064,6 +3120,57 @@ dependencies = [ "libc", ] +[[package]] +name = "nym-cli" +version = "1.0.0" +dependencies = [ + "anyhow", + "base64", + "bip39", + "bs58", + "clap 3.2.8", + "clap_complete", + "clap_complete_fig", + "dotenv", + "log", + "network-defaults", + "nym-cli-commands", + "pretty_env_logger", + "serde", + "serde_json", + "tokio", + "validator-client", +] + +[[package]] +name = "nym-cli-commands" +version = "1.0.0" +dependencies = [ + "base64", + "bip39", + "bs58", + "cfg-if 1.0.0", + "clap 3.2.8", + "comfy-table", + "cosmrs", + "cosmwasm-std", + "handlebars", + "humantime-serde", + "k256", + "log", + "mixnet-contract-common", + "network-defaults", + "rand 0.6.5", + "serde", + "serde_json", + "thiserror", + "time 0.3.9", + "toml", + "url", + "validator-client", + "vesting-contract-common", +] + [[package]] name = "nym-client" version = "1.0.2" @@ -3281,7 +3388,7 @@ dependencies = [ "schemars", "serde", "serde_json", - "strum", + "strum 0.23.0", "tempfile", "thiserror", "ts-rs", @@ -3362,7 +3469,7 @@ dependencies = [ "nym-types", "serde", "serde_json", - "strum", + "strum 0.23.0", "ts-rs", "validator-client", "vesting-contract", @@ -5118,6 +5225,27 @@ dependencies = [ "lazy_static", ] +[[package]] +name = "signal-hook" +version = "0.3.14" +source = "registry+https://github.com/rust-lang/crates.io-index" +checksum = "a253b5e89e2698464fc26b545c9edceb338e18a89effeeecfea192c3025be29d" +dependencies = [ + "libc", + "signal-hook-registry", +] + +[[package]] +name = "signal-hook-mio" +version = "0.2.3" +source = "registry+https://github.com/rust-lang/crates.io-index" +checksum = "29ad2e15f37ec9a6cc544097b78a1ec90001e9f71b81338ca39f430adaca99af" +dependencies = [ + "libc", + "mio", + "signal-hook", +] + [[package]] name = "signal-hook-registry" version = "1.4.0" @@ -5439,9 +5567,15 @@ version = "0.23.0" source = "registry+https://github.com/rust-lang/crates.io-index" checksum = "cae14b91c7d11c9a851d3fbc80a963198998c2a64eec840477fa92d8ce9b70bb" dependencies = [ - "strum_macros", + "strum_macros 0.23.1", ] +[[package]] +name = "strum" +version = "0.24.1" +source = "registry+https://github.com/rust-lang/crates.io-index" +checksum = "063e6045c0e62079840579a7e47a355ae92f60eb74daaf156fb1e84ba164e63f" + [[package]] name = "strum_macros" version = "0.23.1" @@ -5455,6 +5589,19 @@ dependencies = [ "syn", ] +[[package]] +name = "strum_macros" +version = "0.24.3" +source = "registry+https://github.com/rust-lang/crates.io-index" +checksum = "1e385be0d24f186b4ce2f9982191e7101bb737312ad61c1f2f984f34bcf85d59" +dependencies = [ + "heck 0.4.0", + "proc-macro2", + "quote", + "rustversion", + "syn", +] + [[package]] name = "subtle" version = "1.0.0" diff --git a/Cargo.toml b/Cargo.toml index 6e3dc19265..a294283126 100644 --- a/Cargo.toml +++ b/Cargo.toml @@ -27,6 +27,7 @@ members = [ "common/client-libs/mixnet-client", "common/client-libs/validator-client", "common/coconut-interface", + "common/commands", "common/config", "common/cosmwasm-smart-contracts/coconut-bandwidth-contract", "common/cosmwasm-smart-contracts/contracts-common", @@ -69,6 +70,7 @@ members = [ "service-providers/network-statistics", "validator-api", "validator-api/validator-api-requests", + "tools/nym-cli", "tools/ts-rs-cli" ] diff --git a/Makefile b/Makefile index fb1393d11a..97f2d02abd 100644 --- a/Makefile +++ b/Makefile @@ -69,6 +69,9 @@ build-wallet: build-connect: cargo build --manifest-path nym-connect/Cargo.toml --workspace +build-nym-cli: + cargo build --release --manifest-path tools/nym-cli/Cargo.toml + fmt-main: cargo fmt --all diff --git a/common/client-libs/validator-client/src/nymd/cosmwasm_client/types.rs b/common/client-libs/validator-client/src/nymd/cosmwasm_client/types.rs index 3c28d8991f..b680a1a8f4 100644 --- a/common/client-libs/validator-client/src/nymd/cosmwasm_client/types.rs +++ b/common/client-libs/validator-client/src/nymd/cosmwasm_client/types.rs @@ -489,7 +489,7 @@ impl TryFrom for ContractCodeHistoryEntry { } } -#[derive(Copy, Clone, Debug, Default, Eq, PartialEq)] +#[derive(Copy, Clone, Debug, Default, Eq, PartialEq, Serialize)] pub struct GasInfo { /// GasWanted is the maximum units of work we allow this tx to perform. pub gas_wanted: Gas, @@ -645,7 +645,7 @@ impl InstantiateOptions { } } -#[derive(Debug)] +#[derive(Debug, Serialize)] pub struct InstantiateResult { /// The address of the newly instantiated contract pub contract_address: AccountId, @@ -658,7 +658,7 @@ pub struct InstantiateResult { pub gas_info: GasInfo, } -#[derive(Debug)] +#[derive(Debug, Serialize)] pub struct ChangeAdminResult { pub logs: Vec, @@ -668,7 +668,7 @@ pub struct ChangeAdminResult { pub gas_info: GasInfo, } -#[derive(Debug)] +#[derive(Debug, Serialize)] pub struct MigrateResult { pub logs: Vec, @@ -678,7 +678,7 @@ pub struct MigrateResult { pub gas_info: GasInfo, } -#[derive(Debug)] +#[derive(Debug, Serialize)] pub struct ExecuteResult { pub logs: Vec, diff --git a/common/client-libs/validator-client/src/nymd/mod.rs b/common/client-libs/validator-client/src/nymd/mod.rs index 1daf333456..d6c1d40c7f 100644 --- a/common/client-libs/validator-client/src/nymd/mod.rs +++ b/common/client-libs/validator-client/src/nymd/mod.rs @@ -10,6 +10,8 @@ use crate::nymd::error::NymdError; use crate::nymd::fee::DEFAULT_SIMULATED_GAS_MULTIPLIER; use crate::nymd::wallet::DirectSecp256k1HdWallet; use cosmrs::cosmwasm; +use cosmrs::rpc::endpoint::block::Response as BlockResponse; +use cosmrs::rpc::query::Query; use cosmrs::rpc::Error as TendermintRpcError; use cosmrs::rpc::HttpClientUrl; use cosmrs::tx::Msg; @@ -212,6 +214,10 @@ impl NymdClient { &self.config } + pub fn current_chain_details(&self) -> &ChainDetails { + &self.config.chain_details + } + pub fn set_mixnet_contract_address(&mut self, address: AccountId) { self.config.mixnet_contract_address = Some(address); } @@ -355,11 +361,26 @@ impl NymdClient { address: &AccountId, ) -> Result, NymdError> where - C: SigningCosmWasmClient + Sync, + C: CosmWasmClient + Sync, { self.client.get_account(address).await } + pub async fn get_account_public_key( + &self, + address: &AccountId, + ) -> Result, NymdError> + where + C: CosmWasmClient + Sync, + { + if let Some(account) = self.client.get_account(address).await? { + let base_account = account.try_get_base_account()?; + return Ok(base_account.pubkey); + } + + Ok(None) + } + pub async fn get_current_block_timestamp(&self) -> Result where C: CosmWasmClient + Sync, @@ -377,6 +398,13 @@ impl NymdClient { Ok(self.client.get_block(height).await?.block.header.time) } + pub async fn get_block(&self, height: Option) -> Result + where + C: CosmWasmClient + Sync, + { + self.client.get_block(height).await + } + pub async fn get_current_block_height(&self) -> Result where C: CosmWasmClient + Sync, @@ -421,6 +449,13 @@ impl NymdClient { self.client.get_balance(address, denom).await } + pub async fn get_all_balances(&self, address: &AccountId) -> Result, NymdError> + where + C: CosmWasmClient + Sync, + { + self.client.get_all_balances(address).await + } + pub async fn get_tx(&self, id: tx::Hash) -> Result where C: CosmWasmClient + Sync, @@ -428,6 +463,13 @@ impl NymdClient { self.client.get_tx(id).await } + pub async fn search_tx(&self, query: Query) -> Result, NymdError> + where + C: CosmWasmClient + Sync, + { + self.client.search_tx(query).await + } + pub async fn get_total_supply(&self) -> Result, NymdError> where C: CosmWasmClient + Sync, diff --git a/common/client-libs/validator-client/src/nymd/wallet/mod.rs b/common/client-libs/validator-client/src/nymd/wallet/mod.rs index 247ffcd743..e071d48853 100644 --- a/common/client-libs/validator-client/src/nymd/wallet/mod.rs +++ b/common/client-libs/validator-client/src/nymd/wallet/mod.rs @@ -4,7 +4,7 @@ use crate::nymd::error::NymdError; use config::defaults; use cosmrs::bip32::{DerivationPath, XPrv}; -use cosmrs::crypto::secp256k1::SigningKey; +use cosmrs::crypto::secp256k1::{Signature, SigningKey}; use cosmrs::crypto::PublicKey; use cosmrs::tx::SignDoc; use cosmrs::{tx, AccountId}; @@ -105,6 +105,17 @@ impl DirectSecp256k1HdWallet { self.secret.to_string() } + pub fn sign_raw_with_account( + &self, + signer: &AccountData, + message: &[u8], + ) -> Result { + signer + .private_key + .sign(message) + .map_err(|_| NymdError::SigningFailure) + } + pub fn sign_direct_with_account( &self, signer: &AccountData, diff --git a/common/commands/Cargo.toml b/common/commands/Cargo.toml new file mode 100644 index 0000000000..35b38512fa --- /dev/null +++ b/common/commands/Cargo.toml @@ -0,0 +1,32 @@ +[package] +name = "nym-cli-commands" +version = "1.0.0" +authors = ["Nym Technologies SA"] +edition = "2021" + +[dependencies] +base64 = "0.13.0" +bip39 = "1.0.1" +bs58 = "0.4" +comfy-table = "6.0.0" +cfg-if = "1.0.0" +clap = { version = "3.2", features = ["derive"] } +handlebars = "3.0.1" +humantime-serde = "1.0" +k256 = { version = "0.10", features = ["ecdsa", "sha256"] } +log = "0.4" +rand = {version = "0.6", features = ["std"] } +serde = { version = "1.0", features = ["derive"] } +serde_json = "1" +thiserror = "1" +time = { version = "0.3.6", features = ["parsing", "formatting"] } +toml = "0.5.6" +url = "2.2" + +cosmrs = { git = "https://github.com/neacsu/cosmos-rust", branch = "neacsu/feegrant_support" } +cosmwasm-std = { version = "1.0.0" } + +validator-client = { path = "../client-libs/validator-client", features = ["nymd-client"] } +network-defaults = { path = "../network-defaults" } +mixnet-contract-common = { path = "../cosmwasm-smart-contracts/mixnet-contract" } +vesting-contract-common = { path = "../cosmwasm-smart-contracts/vesting-contract" } diff --git a/common/commands/README.md b/common/commands/README.md new file mode 100644 index 0000000000..c545e13b1d --- /dev/null +++ b/common/commands/README.md @@ -0,0 +1,13 @@ +# Common `clap` Command Crate + +This crate contains `clap` commands for common operations: + +- account creation and queries +- block queries +- cosmwasm uploads, instantiate, execution, query, etc +- mixnet actions and queries +- sign and verify messages +- query for transactions +- create vesting schedules and query for them + +For how to use this crate, please see the [Nym CLI](../../tools/nym-cli). \ No newline at end of file diff --git a/common/commands/src/coconut/mod.rs b/common/commands/src/coconut/mod.rs new file mode 100644 index 0000000000..6cfc921228 --- /dev/null +++ b/common/commands/src/coconut/mod.rs @@ -0,0 +1,4 @@ +// Copyright 2022 - Nym Technologies SA +// SPDX-License-Identifier: Apache-2.0 + +// TODO: add coconut commands here diff --git a/common/commands/src/context/errors.rs b/common/commands/src/context/errors.rs new file mode 100644 index 0000000000..5c3d24a2bb --- /dev/null +++ b/common/commands/src/context/errors.rs @@ -0,0 +1,18 @@ +// Copyright 2021 - Nym Technologies SA +// SPDX-License-Identifier: Apache-2.0 + +use thiserror::Error; + +#[derive(Error, Debug)] +pub enum ContextError { + #[error("mnemonic was not provided, pass as an argument or an env var called MNEMONIC")] + MnemonicNotProvided, + + #[error("failed to parse mnemonic - {0}")] + Bip39Error(#[from] bip39::Error), + + // there are lots of error that can occur in the nymd client, so just pass through their display details + // TODO: improve this to return known errors + #[error("failed to create client - {0}")] + NymdError(String), +} diff --git a/common/commands/src/context/mod.rs b/common/commands/src/context/mod.rs new file mode 100644 index 0000000000..856a03e62a --- /dev/null +++ b/common/commands/src/context/mod.rs @@ -0,0 +1,138 @@ +// Copyright 2021 - Nym Technologies SA +// SPDX-License-Identifier: Apache-2.0 + +use network_defaults::{ + setup_env, + var_names::{API_VALIDATOR, MIXNET_CONTRACT_ADDRESS, NYMD_VALIDATOR, VESTING_CONTRACT_ADDRESS}, + NymNetworkDetails, +}; +use validator_client::nymd::{self, AccountId, NymdClient, QueryNymdClient, SigningNymdClient}; +pub use validator_client::validator_api::Client as ValidatorApiClient; + +use crate::context::errors::ContextError; + +pub mod errors; + +pub type SigningClient = validator_client::nymd::NymdClient; +pub type QueryClient = validator_client::nymd::NymdClient; +pub type SigningClientWithValidatorAPI = validator_client::Client; +pub type QueryClientWithValidatorAPI = validator_client::Client; + +#[derive(Debug)] +pub struct ClientArgs { + pub config_env_file: Option, + pub nymd_url: Option, + pub validator_api_url: Option, + pub mnemonic: Option, + pub mixnet_contract_address: Option, + pub vesting_contract_address: Option, +} + +pub fn get_network_details(args: &ClientArgs) -> Result { + // let the network defaults crate handle setting up the env vars if the file arg is set, otherwise + // it will default to what is already in env vars, falling back to mainnet + setup_env(args.config_env_file.clone()); + + // override the env vars with user supplied arguments, if set + if let Some(nymd_url) = args.nymd_url.as_ref() { + std::env::set_var(NYMD_VALIDATOR, nymd_url); + } + if let Some(validator_api_url) = args.validator_api_url.as_ref() { + std::env::set_var(API_VALIDATOR, validator_api_url); + } + if let Some(mixnet_contract_address) = args.mixnet_contract_address.as_ref() { + std::env::set_var(MIXNET_CONTRACT_ADDRESS, mixnet_contract_address.to_string()); + } + if let Some(vesting_contract_address) = args.vesting_contract_address.as_ref() { + std::env::set_var( + VESTING_CONTRACT_ADDRESS, + vesting_contract_address.to_string(), + ); + } + + Ok(NymNetworkDetails::new_from_env()) +} + +pub fn create_signing_client( + args: ClientArgs, + network_details: &NymNetworkDetails, +) -> Result { + let client_config = nymd::Config::try_from_nym_network_details(network_details) + .expect("failed to construct valid validator client config with the provided network"); + + // get mnemonic + let mnemonic = match std::env::var("MNEMONIC") { + Ok(value) => bip39::Mnemonic::parse(value)?, + // env var MNEMONIC is not present, so try to fall back to arg --mnemonic ... + Err(_) => match args.mnemonic { + Some(value) => value, + None => return Err(ContextError::MnemonicNotProvided), // no env var or arg provided + }, + }; + + let nymd_url = network_details + .endpoints + .first() + .expect("network details are not defined") + .nymd_url + .as_str(); + + match NymdClient::connect_with_mnemonic(client_config, nymd_url, mnemonic, None) { + Ok(client) => Ok(client), + Err(e) => Err(ContextError::NymdError(format!("{:?}", e))), + } +} + +pub fn create_query_client( + network_details: &NymNetworkDetails, +) -> Result { + let client_config = nymd::Config::try_from_nym_network_details(network_details) + .expect("failed to construct valid validator client config with the provided network"); + + let nymd_url = network_details + .endpoints + .first() + .expect("network details are not defined") + .nymd_url + .as_str(); + + match NymdClient::connect(client_config, nymd_url) { + Ok(client) => Ok(client), + Err(e) => Err(ContextError::NymdError(format!("{:?}", e))), + } +} + +pub fn create_signing_client_with_validator_api( + args: ClientArgs, + network_details: &NymNetworkDetails, +) -> Result { + let client_config = validator_client::Config::try_from_nym_network_details(network_details) + .expect("failed to construct valid validator client config with the provided network"); + + // get mnemonic + let mnemonic = match std::env::var("MNEMONIC") { + Ok(value) => bip39::Mnemonic::parse(value)?, + // env var MNEMONIC is not present, so try to fall back to arg --mnemonic ... + Err(_) => match args.mnemonic { + Some(value) => value, + None => return Err(ContextError::MnemonicNotProvided), // no env var or arg provided + }, + }; + + match validator_client::client::Client::new_signing(client_config, mnemonic) { + Ok(client) => Ok(client), + Err(e) => Err(ContextError::NymdError(format!("{:?}", e))), + } +} + +pub fn create_query_client_with_validator_api( + network_details: &NymNetworkDetails, +) -> Result { + let client_config = validator_client::Config::try_from_nym_network_details(network_details) + .expect("failed to construct valid validator client config with the provided network"); + + match validator_client::client::Client::new_query(client_config) { + Ok(client) => Ok(client), + Err(e) => Err(ContextError::NymdError(format!("{:?}", e))), + } +} diff --git a/common/commands/src/lib.rs b/common/commands/src/lib.rs new file mode 100644 index 0000000000..afca2be0f7 --- /dev/null +++ b/common/commands/src/lib.rs @@ -0,0 +1,7 @@ +// Copyright 2021 - Nym Technologies SA +// SPDX-License-Identifier: Apache-2.0 + +pub mod coconut; +pub mod context; +pub mod utils; +pub mod validator; diff --git a/common/commands/src/utils.rs b/common/commands/src/utils.rs new file mode 100644 index 0000000000..d6419fa20b --- /dev/null +++ b/common/commands/src/utils.rs @@ -0,0 +1,44 @@ +// Copyright 2022 - Nym Technologies SA +// SPDX-License-Identifier: Apache-2.0 + +use std::error::Error; +use std::fmt::Display; + +use cosmwasm_std::{Coin as CosmWasmCoin, Decimal}; +use log::error; +use validator_client::nymd::Coin; + +pub fn pretty_coin(coin: &Coin) -> String { + let amount = Decimal::from_ratio(coin.amount, 1_000_000u128); + let denom = if coin.denom.starts_with('u') { + &coin.denom[1..] + } else { + &coin.denom + }; + format!("{} {}", amount, denom) +} + +pub fn pretty_cosmwasm_coin(coin: &CosmWasmCoin) -> String { + let amount = Decimal::from_ratio(coin.amount, 1_000_000u128); + let denom = if coin.denom.starts_with('u') { + &coin.denom[1..] + } else { + &coin.denom + }; + format!("{} {}", amount, denom) +} + +pub fn show_error(e: E) +where + E: Display, +{ + error!("{}", e); +} + +pub fn show_error_passthrough(e: E) -> E +where + E: Error + Display, +{ + error!("{}", e); + e +} diff --git a/common/commands/src/validator/account/balance.rs b/common/commands/src/validator/account/balance.rs new file mode 100644 index 0000000000..8ac24b273f --- /dev/null +++ b/common/commands/src/validator/account/balance.rs @@ -0,0 +1,72 @@ +// Copyright 2021 - Nym Technologies SA +// SPDX-License-Identifier: Apache-2.0 + +use clap::Parser; +use log::{error, info}; + +use validator_client::nymd::AccountId; + +use crate::context::QueryClient; +use crate::utils::{pretty_coin, show_error}; + +#[derive(Debug, Parser)] +pub struct Args { + #[clap(value_parser)] + #[clap(help = "The account address to get the balance for")] + pub address: Option, + + #[clap(long)] + #[clap(help = "Optional currency to show balance for")] + pub denom: Option, + + #[clap(long, requires = "denom")] + #[clap(help = "Optionally hide the denom")] + pub hide_denom: bool, + + #[clap(long)] + #[clap(help = "Show as a raw value")] + pub raw: bool, +} + +pub async fn query_balance( + args: Args, + client: &QueryClient, + address_from_mnemonic: Option, +) { + if args.address.is_none() && address_from_mnemonic.is_none() { + error!("Please specify an account address or a mnemonic to get the balance for"); + return; + } + + let address = args + .address + .unwrap_or_else(|| address_from_mnemonic.expect("please provide a mnemonic")); + + info!("Getting balance for {}...", address); + + match client.get_all_balances(&address).await { + Ok(coins) => { + if coins.is_empty() { + println!("No balance"); + return; + } + + let denom = args.denom.unwrap_or_else(|| "".to_string()); + + for coin in coins { + if denom.is_empty() || denom.eq_ignore_ascii_case(&coin.denom) { + if args.raw { + if !args.hide_denom { + println!("{}", coin); + } else { + println!("{}", coin.amount); + } + } else { + println!("{}", pretty_coin(&coin)); + } + } + } + } + Err(e) => show_error(e), + } +} diff --git a/common/commands/src/validator/account/create.rs b/common/commands/src/validator/account/create.rs new file mode 100644 index 0000000000..3003b9a9d5 --- /dev/null +++ b/common/commands/src/validator/account/create.rs @@ -0,0 +1,24 @@ +// Copyright 2021 - Nym Technologies SA +// SPDX-License-Identifier: Apache-2.0 + +use clap::Parser; +use validator_client::nymd::wallet::DirectSecp256k1HdWallet; + +#[derive(Debug, Parser)] +pub struct Args { + #[clap(long)] + // allowed values are 12, 18 or 24 + pub word_count: Option, +} + +pub fn create_account(args: Args, prefix: &str) { + let word_count = args.word_count.unwrap_or(24); + let mnemonic = bip39::Mnemonic::generate(word_count).expect("failed to generate mnemonic!"); + + let wallet = + DirectSecp256k1HdWallet::from_mnemonic(prefix, mnemonic).expect("failed to build wallet!"); + + // Output address and mnemonics into separate lines for easier parsing + println!("{}", wallet.mnemonic()); + println!("{}", wallet.try_derive_accounts().unwrap()[0].address()); +} diff --git a/common/commands/src/validator/account/mod.rs b/common/commands/src/validator/account/mod.rs new file mode 100644 index 0000000000..b3cecc7c9a --- /dev/null +++ b/common/commands/src/validator/account/mod.rs @@ -0,0 +1,28 @@ +// Copyright 2021 - Nym Technologies SA +// SPDX-License-Identifier: Apache-2.0 + +use clap::{Args, Subcommand}; + +pub mod balance; +pub mod create; +pub mod pubkey; +pub mod send; + +#[derive(Debug, Args)] +#[clap(args_conflicts_with_subcommands = true, subcommand_required = true)] +pub struct Account { + #[clap(subcommand)] + pub command: Option, +} + +#[derive(Debug, Subcommand)] +pub enum AccountCommands { + /// Create a new mnemonic - note, this account does not appear on the chain until the account id is used in a transaction + Create(crate::validator::account::create::Args), + /// Gets the balance of an account + Balance(crate::validator::account::balance::Args), + /// Gets the public key of an account + PubKey(crate::validator::account::pubkey::Args), + /// Sends tokens to another account + Send(crate::validator::account::send::Args), +} diff --git a/common/commands/src/validator/account/pubkey.rs b/common/commands/src/validator/account/pubkey.rs new file mode 100644 index 0000000000..83d15f25e3 --- /dev/null +++ b/common/commands/src/validator/account/pubkey.rs @@ -0,0 +1,89 @@ +// Copyright 2021 - Nym Technologies SA +// SPDX-License-Identifier: Apache-2.0 + +use clap::Parser; +use log::{error, info}; + +use validator_client::nymd::wallet::DirectSecp256k1HdWallet; +use validator_client::nymd::AccountId; + +use crate::context::QueryClient; +use crate::utils::show_error; + +#[derive(Debug, Parser)] +pub struct Args { + #[clap(value_parser)] + #[clap( + help = "Optionally, show the public key for this account address, otherwise generate the account address from the mnemonic" + )] + pub address: Option, + + #[clap(long)] + #[clap(help = "If set, get the public key from the mnemonic, rather than querying for it")] + pub from_mnemonic: bool, +} + +pub async fn get_pubkey( + args: Args, + client: &QueryClient, + mnemonic: Option, + address_from_mnemonic: Option, +) { + if args.address.is_none() && address_from_mnemonic.is_none() { + error!("Please specify an account address or a mnemonic to get the balance for"); + return; + } + + let address = args + .address + .unwrap_or_else(|| address_from_mnemonic.expect("please provide a mnemonic")); + + if args.from_mnemonic { + let prefix = client + .current_chain_details() + .bech32_account_prefix + .as_str(); + get_pubkey_from_mnemonic(address, prefix, mnemonic.expect("mnemonic not set")); + return; + } + + get_pubkey_from_chain(address, client).await; +} + +pub fn get_pubkey_from_mnemonic(address: AccountId, prefix: &str, mnemonic: bip39::Mnemonic) { + match DirectSecp256k1HdWallet::from_mnemonic(prefix, mnemonic) { + Ok(wallet) => match wallet.try_derive_accounts() { + Ok(accounts) => match accounts.iter().find(|a| *a.address() == address) { + Some(account) => { + println!("{}", account.public_key().to_string()); + } + None => { + error!("Could not derive key that matches {}", address) + } + }, + Err(e) => { + error!("Failed to derive accounts. {}", e); + } + }, + Err(e) => show_error(e), + } +} + +pub async fn get_pubkey_from_chain(address: AccountId, client: &QueryClient) { + info!("Getting public key for address {} from chain...", address); + match client.get_account_details(&address).await { + Ok(Some(account)) => { + if let Ok(base_account) = account.try_get_base_account() { + if let Some(pubkey) = base_account.pubkey { + println!("{}", pubkey.to_string()); + } else { + println!("No account associated with address {}", address); + } + } + } + Ok(None) => { + println!("No account associated with address {}", address); + } + Err(e) => show_error(e), + } +} diff --git a/common/commands/src/validator/account/send.rs b/common/commands/src/validator/account/send.rs new file mode 100644 index 0000000000..90816258bd --- /dev/null +++ b/common/commands/src/validator/account/send.rs @@ -0,0 +1,66 @@ +// Copyright 2021 - Nym Technologies SA +// SPDX-License-Identifier: Apache-2.0 + +use clap::Parser; +use log::info; +use serde_json::json; + +use validator_client::nymd::{AccountId, Coin}; + +use crate::context::SigningClient; + +#[derive(Debug, Parser)] +pub struct Args { + #[clap(value_parser, help = "The recipient account address")] + pub recipient: AccountId, + + #[clap( + value_parser, + help = "Amount to transfer in micro denomination (e.g. unym or unyx)" + )] + pub amount: u128, + + #[clap(long, help = "Override the denomination")] + pub denom: Option, + + #[clap(long)] + pub memo: Option, +} + +pub async fn send(args: Args, client: &SigningClient) { + let memo = args + .memo + .unwrap_or_else(|| "Sending tokens with nym-cli".to_owned()); + let denom = args + .denom + .unwrap_or_else(|| client.current_chain_details().mix_denom.base.clone()); + + let coin = Coin { + denom, + amount: args.amount, + }; + + info!( + "Sending {} {} from {} to {}...", + coin.amount, + coin.denom, + client.address(), + args.recipient + ); + + let res = client + .send(&args.recipient, vec![coin], memo, None) + .await + .expect("failed to send tokens!"); + + info!("Sending result: {}", json!(res)); + + println!(); + println!( + "Nodesguru: https://nym.explorers.guru/transaction/{}", + &res.hash + ); + println!("Mintscan: https://www.mintscan.io/nyx/txs/{}", &res.hash); + println!("Transaction result code: {}", &res.tx_result.code.value()); + println!("Transaction hash: {}", &res.hash); +} diff --git a/common/commands/src/validator/block/block_time.rs b/common/commands/src/validator/block/block_time.rs new file mode 100644 index 0000000000..a35e7ca597 --- /dev/null +++ b/common/commands/src/validator/block/block_time.rs @@ -0,0 +1,23 @@ +// Copyright 2022 - Nym Technologies SA +// SPDX-License-Identifier: Apache-2.0 + +use clap::Parser; + +use crate::context::QueryClient; +use crate::utils::show_error; + +#[derive(Debug, Parser)] +pub struct Args { + #[clap(value_parser)] + #[clap(help = "The block height")] + pub height: u32, +} + +pub async fn query_for_block_time(args: Args, client: &QueryClient) { + match client.get_block_timestamp(Some(args.height)).await { + Ok(res) => { + println!("{}", res.to_rfc3339()) + } + Err(e) => show_error(e), + } +} diff --git a/common/commands/src/validator/block/current_height.rs b/common/commands/src/validator/block/current_height.rs new file mode 100644 index 0000000000..a7aa7fb743 --- /dev/null +++ b/common/commands/src/validator/block/current_height.rs @@ -0,0 +1,19 @@ +// Copyright 2022 - Nym Technologies SA +// SPDX-License-Identifier: Apache-2.0 + +use clap::Parser; + +use crate::context::QueryClient; +use crate::utils::show_error; + +#[derive(Debug, Parser)] +pub struct Args {} + +pub async fn query_current_block_height(client: &QueryClient) { + match client.get_current_block_height().await { + Ok(res) => { + println!("Current block height:\n{}", res.value()) + } + Err(e) => show_error(e), + } +} diff --git a/common/commands/src/validator/block/get.rs b/common/commands/src/validator/block/get.rs new file mode 100644 index 0000000000..12a612b0c8 --- /dev/null +++ b/common/commands/src/validator/block/get.rs @@ -0,0 +1,24 @@ +// Copyright 2022 - Nym Technologies SA +// SPDX-License-Identifier: Apache-2.0 + +use clap::Parser; + +use crate::context::QueryClient; +use crate::utils::show_error; +use serde_json::json; + +#[derive(Debug, Parser)] +pub struct Args { + #[clap(value_parser)] + #[clap(help = "The block height")] + pub height: u32, +} + +pub async fn query_for_block(args: Args, client: &QueryClient) { + match client.get_block(Some(args.height)).await { + Ok(res) => { + println!("{}", json!(res)) + } + Err(e) => show_error(e), + } +} diff --git a/common/commands/src/validator/block/mod.rs b/common/commands/src/validator/block/mod.rs new file mode 100644 index 0000000000..07798ced63 --- /dev/null +++ b/common/commands/src/validator/block/mod.rs @@ -0,0 +1,25 @@ +// Copyright 2021 - Nym Technologies SA +// SPDX-License-Identifier: Apache-2.0 + +use clap::{Args, Subcommand}; + +pub mod block_time; +pub mod current_height; +pub mod get; + +#[derive(Debug, Args)] +#[clap(args_conflicts_with_subcommands = true, subcommand_required = true)] +pub struct Block { + #[clap(subcommand)] + pub command: Option, +} + +#[derive(Debug, Subcommand)] +pub enum BlockCommands { + /// Gets a block's details and prints as JSON + Get(crate::validator::block::get::Args), + /// Gets the block time at a height + Time(crate::validator::block::block_time::Args), + /// Gets the current block height + CurrentHeight(crate::validator::block::current_height::Args), +} diff --git a/common/commands/src/validator/cosmwasm/execute_contract.rs b/common/commands/src/validator/cosmwasm/execute_contract.rs new file mode 100644 index 0000000000..f387b83903 --- /dev/null +++ b/common/commands/src/validator/cosmwasm/execute_contract.rs @@ -0,0 +1,60 @@ +// Copyright 2021 - Nym Technologies SA +// SPDX-License-Identifier: Apache-2.0 + +use crate::context::SigningClient; +use clap::Parser; +use cosmrs::AccountId; +use log::{error, info}; +use serde_json::{json, Value}; +use validator_client::nymd::Coin; + +#[derive(Debug, Parser)] +pub struct Args { + #[clap(value_parser)] + #[clap(help = "The address of contract to execute")] + pub contract_address: AccountId, + + #[clap(value_parser)] + #[clap(help = "JSON encoded method arguments")] + pub json_args: String, + + #[clap(long)] + pub memo: Option, + + #[clap( + value_parser, + requires = "fundsDenom", + help = "Amount to supply as funds in micro denomination (e.g. unym or unyx)" + )] + pub funds: Option, + + #[clap(long, requires = "funds", help = "Set the denomination for the funds")] + pub funds_denom: Option, +} + +pub async fn execute(args: Args, client: SigningClient) { + info!("Starting contract method execution!"); + + let json_args: Value = + serde_json::from_str(&args.json_args).expect("Unable to parse JSON args"); + + let memo = args + .memo + .unwrap_or_else(|| "nym-cli execute contract method".to_owned()); + + let funds = match args.funds { + Some(funds) => vec![Coin::new( + funds, + args.funds_denom.expect("denom for funds not set"), + )], + None => vec![], + }; + + match client + .execute(&args.contract_address, &json_args, None, memo, funds) + .await + { + Ok(res) => info!("SUCCESS ✅\n{}", json!(res)), + Err(e) => error!("FAILURE ❌\n{}", e), + } +} diff --git a/common/commands/src/validator/cosmwasm/init_contract.rs b/common/commands/src/validator/cosmwasm/init_contract.rs new file mode 100644 index 0000000000..c624a81a94 --- /dev/null +++ b/common/commands/src/validator/cosmwasm/init_contract.rs @@ -0,0 +1,78 @@ +// Copyright 2021 - Nym Technologies SA +// SPDX-License-Identifier: Apache-2.0 + +use crate::context::SigningClient; +use clap::Parser; +use cosmrs::{AccountId, Coin as CosmosCoin}; +use log::info; +use network_defaults::NymNetworkDetails; +use validator_client::nymd::cosmwasm_client::types::{ContractCodeId, InstantiateOptions}; +use validator_client::nymd::Coin; + +#[derive(Debug, Parser)] +pub struct Args { + #[clap(value_parser)] + pub code_id: ContractCodeId, + + #[clap(long)] + pub memo: Option, + + #[clap(long)] + pub label: Option, + + #[clap(long)] + pub init_message: String, + + #[clap(long)] + pub admin: Option, + + #[clap( + long, + requires = "fundsDenom", + help = "Amount to supply as funds in micro denomination (e.g. unym or unyx)" + )] + pub funds: Option, + + #[clap(long, requires = "funds", help = "Set the denomination for the funds")] + pub funds_denom: Option, +} + +pub async fn init(args: Args, client: SigningClient, network_details: &NymNetworkDetails) { + info!("Starting contract instantiation!"); + + let memo = args + .memo + .unwrap_or_else(|| "contract instantiation".to_owned()); + let label = args + .label + .unwrap_or_else(|| "Nym mixnet smart contract".to_owned()); + + let funds: Vec = match args.funds { + Some(funds) => vec![Coin::new( + funds, + args.funds_denom + .unwrap_or_else(|| network_details.chain_details.mix_denom.base.to_string()), + ) + .into()], + None => vec![], + }; + + // by default we make ourselves an admin, let me know if you don't like that behaviour + let opts = Some(InstantiateOptions { + funds, + admin: Some(args.admin.unwrap_or_else(|| client.address().clone())), + }); + + let msg: serde_json::Value = + serde_json::from_str(&args.init_message).expect("failed to parse init message"); + + // the EmptyMsg{} argument is equivalent to `--init-message='{}'` + let res = client + .instantiate(args.code_id, &msg, label, memo, opts, None) + .await + .expect("failed to instantiate the contract!"); + + info!("Init result: {:?}", res); + + println!("{}", res.contract_address) +} diff --git a/common/commands/src/validator/cosmwasm/migrate_contract.rs b/common/commands/src/validator/cosmwasm/migrate_contract.rs new file mode 100644 index 0000000000..fa21062ee7 --- /dev/null +++ b/common/commands/src/validator/cosmwasm/migrate_contract.rs @@ -0,0 +1,51 @@ +// Copyright 2021 - Nym Technologies SA +// SPDX-License-Identifier: Apache-2.0 + +use crate::context::SigningClient; +use crate::utils::show_error_passthrough; +use clap::Parser; +use cosmrs::AccountId; +use log::info; +use validator_client::nymd::cosmwasm_client::types::{ContractCodeId, EmptyMsg}; + +#[derive(Debug, Parser)] +pub struct Args { + #[clap(value_parser)] + pub contract_address: AccountId, + + #[clap(long)] + pub code_id: ContractCodeId, + + #[clap(long)] + pub memo: Option, + + #[clap(long)] + pub init_message: Option, +} + +pub async fn migrate(args: Args, client: SigningClient) { + println!("Starting contract migration!"); + + let memo = args.memo.unwrap_or_else(|| "contract migration".to_owned()); + let contract_address = args.contract_address; + + // the EmptyMsg{} argument is equivalent to `--init-message='{}'` + let res = if let Some(raw_msg) = args.init_message { + let msg: serde_json::Value = + serde_json::from_str(&raw_msg).expect("failed to parse init message"); + + client + .migrate(&contract_address, args.code_id, &msg, memo, None) + .await + .map_err(show_error_passthrough) + .expect("failed to migrate the contract!") + } else { + client + .migrate(&contract_address, args.code_id, &EmptyMsg {}, memo, None) + .await + .map_err(show_error_passthrough) + .expect("failed to migrate the contract!") + }; + + info!("Migrate result: {:?}", res); +} diff --git a/common/commands/src/validator/cosmwasm/mod.rs b/common/commands/src/validator/cosmwasm/mod.rs new file mode 100644 index 0000000000..9ee1fa182f --- /dev/null +++ b/common/commands/src/validator/cosmwasm/mod.rs @@ -0,0 +1,28 @@ +// Copyright 2021 - Nym Technologies SA +// SPDX-License-Identifier: Apache-2.0 + +use clap::{Args, Subcommand}; + +pub mod execute_contract; +pub mod init_contract; +pub mod migrate_contract; +pub mod upload_contract; + +#[derive(Debug, Args)] +#[clap(args_conflicts_with_subcommands = true, subcommand_required = true)] +pub struct Cosmwasm { + #[clap(subcommand)] + pub command: Option, +} + +#[derive(Debug, Subcommand)] +pub enum CosmwasmCommands { + /// Upload a smart contract WASM blob + Upload(crate::validator::cosmwasm::upload_contract::Args), + /// Init a WASM smart contract + Init(crate::validator::cosmwasm::init_contract::Args), + /// Migrate a WASM smart contract + Migrate(crate::validator::cosmwasm::migrate_contract::Args), + /// Execute a WASM smart contract method + Execute(crate::validator::cosmwasm::execute_contract::Args), +} diff --git a/common/commands/src/validator/cosmwasm/upload_contract.rs b/common/commands/src/validator/cosmwasm/upload_contract.rs new file mode 100644 index 0000000000..96d01741ee --- /dev/null +++ b/common/commands/src/validator/cosmwasm/upload_contract.rs @@ -0,0 +1,37 @@ +// Copyright 2021 - Nym Technologies SA +// SPDX-License-Identifier: Apache-2.0 + +use crate::context::SigningClient; +use clap::Parser; +use log::info; +use std::io::Read; +use std::path::PathBuf; + +#[derive(Debug, Parser)] +pub struct Args { + #[clap(long)] + pub wasm_path: PathBuf, + + #[clap(long)] + pub memo: Option, +} + +pub async fn upload(args: Args, client: SigningClient) { + info!("Starting contract upload!"); + + let mut file = std::fs::File::open(args.wasm_path).expect("failed to open the wasm blob"); + let mut data = Vec::new(); + + file.read_to_end(&mut data).unwrap(); + + let memo = args.memo.unwrap_or_else(|| "contract upload".to_owned()); + + let res = client + .upload(data, memo, None) + .await + .expect("failed to upload the contract!"); + + info!("Upload result: {:?}", res); + + println!("{}", res.code_id) +} diff --git a/common/commands/src/validator/mixnet/delegators/delegate_to_mixnode.rs b/common/commands/src/validator/mixnet/delegators/delegate_to_mixnode.rs new file mode 100644 index 0000000000..d69d5e0028 --- /dev/null +++ b/common/commands/src/validator/mixnet/delegators/delegate_to_mixnode.rs @@ -0,0 +1,31 @@ +// Copyright 2021 - Nym Technologies SA +// SPDX-License-Identifier: Apache-2.0 + +use crate::context::SigningClient; +use clap::Parser; +use log::info; +use mixnet_contract_common::Coin; + +#[derive(Debug, Parser)] +pub struct Args { + #[clap(long)] + pub identity_key: String, + + #[clap(long)] + pub amount: u128, +} + +pub async fn delegate_to_mixnode(args: Args, client: SigningClient) { + let denom = client.current_chain_details().mix_denom.base.as_str(); + + info!("Starting delegation to mixnode"); + + let coin = Coin::new(args.amount, denom); + + let res = client + .delegate_to_mixnode(&*args.identity_key, coin.into(), None) + .await + .expect("failed to delegate to mixnode!"); + + info!("delegating to mixnode: {:?}", res); +} diff --git a/common/commands/src/validator/mixnet/delegators/mod.rs b/common/commands/src/validator/mixnet/delegators/mod.rs new file mode 100644 index 0000000000..61e87f119d --- /dev/null +++ b/common/commands/src/validator/mixnet/delegators/mod.rs @@ -0,0 +1,35 @@ +// Copyright 2021 - Nym Technologies SA +// SPDX-License-Identifier: Apache-2.0 + +use clap::{Args, Subcommand}; + +pub mod rewards; + +pub mod delegate_to_mixnode; +pub mod query_for_delegations; +pub mod undelegate_from_mixnode; +pub mod vesting_delegate_to_mixnode; +pub mod vesting_undelegate_from_mixnode; + +#[derive(Debug, Args)] +#[clap(args_conflicts_with_subcommands = true, subcommand_required = true)] +pub struct MixnetDelegators { + #[clap(subcommand)] + pub command: MixnetDelegatorsCommands, +} + +#[derive(Debug, Subcommand)] +pub enum MixnetDelegatorsCommands { + /// Lists current delegations + List(query_for_delegations::Args), + /// Manage rewards from delegations + Rewards(rewards::MixnetDelegatorsReward), + /// Delegate to a mixnode + Delegate(delegate_to_mixnode::Args), + /// Undelegate from a mixnode + Undelegate(undelegate_from_mixnode::Args), + /// Delegate to a mixnode with locked tokens + DelegateVesting(vesting_delegate_to_mixnode::Args), + /// Undelegate from a mixnode (when originally using locked tokens) + UndelegateVesting(vesting_undelegate_from_mixnode::Args), +} diff --git a/common/commands/src/validator/mixnet/delegators/query_for_delegations.rs b/common/commands/src/validator/mixnet/delegators/query_for_delegations.rs new file mode 100644 index 0000000000..efb685e085 --- /dev/null +++ b/common/commands/src/validator/mixnet/delegators/query_for_delegations.rs @@ -0,0 +1,129 @@ +// Copyright 2021 - Nym Technologies SA +// SPDX-License-Identifier: Apache-2.0 + +use clap::Parser; +use log::info; + +use crate::context::SigningClientWithValidatorAPI; +use crate::utils::{pretty_cosmwasm_coin, show_error_passthrough}; + +use comfy_table::Table; +use mixnet_contract_common::mixnode::DelegationEvent; +use mixnet_contract_common::Delegation; + +#[derive(Debug, Parser)] +pub struct Args {} + +pub async fn execute(_args: Args, client: SigningClientWithValidatorAPI) { + info!( + "Getting delegations for account {}...", + client.nymd.address() + ); + + let delegations = client + .get_all_delegator_delegations(client.nymd.address()) + .await + .map_err(show_error_passthrough); + + let mixnet_contract_events = client + .nymd + .get_pending_delegation_events(client.nymd.address().to_string(), None) + .await + .map_err(show_error_passthrough); + + let vesting_contract = client.nymd.vesting_contract_address(); + + let vesting_contract_events = client + .nymd + .get_pending_delegation_events( + client.nymd.address().to_string(), + Some(vesting_contract.to_string()), + ) + .await + .map_err(show_error_passthrough); + + if let Ok(res) = delegations { + println!(); + if res.is_empty() { + println!("This account has not delegated any tokens to mixnodes"); + } else { + println!("Delegations:"); + print_delegations(res, &client).await; + } + } + if let Ok(res) = mixnet_contract_events { + if !res.is_empty() { + println!(); + println!("Pending delegations (liquid tokens):"); + print_delegation_events(res, &client).await; + } + } + if let Ok(res) = vesting_contract_events { + if !res.is_empty() { + println!(); + println!("Pending delegations (locked tokens):"); + print_delegation_events(res, &client).await; + } + } +} + +async fn to_iso_timestamp(block_height: u32, client: &SigningClientWithValidatorAPI) -> String { + match client.nymd.get_block_timestamp(Some(block_height)).await { + Ok(res) => res.to_rfc3339(), + Err(_e) => "-".to_string(), + } +} + +async fn print_delegations(delegations: Vec, client: &SigningClientWithValidatorAPI) { + let mut table = Table::new(); + + table.set_header(vec!["Timestamp", "Identity Key", "Delegation", "Proxy"]); + + for delegation in delegations { + table.add_row(vec![ + to_iso_timestamp(delegation.block_height as u32, client).await, + delegation.node_identity.to_string(), + pretty_cosmwasm_coin(&delegation.amount), + format!("{:?}", delegation.proxy), + ]); + } + + println!("{table}"); +} + +async fn print_delegation_events( + events: Vec, + client: &SigningClientWithValidatorAPI, +) { + let mut table = Table::new(); + + table.set_header(vec![ + "Timestamp", + "Identity Key", + "Delegation", + "Event Type", + ]); + + for event in events { + match event { + DelegationEvent::Delegate(delegation) => { + table.add_row(vec![ + to_iso_timestamp(delegation.block_height as u32, client).await, + delegation.node_identity.to_string(), + pretty_cosmwasm_coin(&delegation.amount), + "Delegate".to_string(), + ]); + } + DelegationEvent::Undelegate(undelegate) => { + table.add_row(vec![ + to_iso_timestamp(undelegate.block_height() as u32, client).await, + undelegate.mix_identity().to_string(), + "-".to_string(), + "Undelegate".to_string(), + ]); + } + } + } + + println!("{table}"); +} diff --git a/common/commands/src/validator/mixnet/delegators/rewards/claim_delegator_reward.rs b/common/commands/src/validator/mixnet/delegators/rewards/claim_delegator_reward.rs new file mode 100644 index 0000000000..850ac076d6 --- /dev/null +++ b/common/commands/src/validator/mixnet/delegators/rewards/claim_delegator_reward.rs @@ -0,0 +1,23 @@ +// Copyright 2021 - Nym Technologies SA +// SPDX-License-Identifier: Apache-2.0 + +use crate::context::SigningClient; +use clap::Parser; +use log::info; + +#[derive(Debug, Parser)] +pub struct Args { + #[clap(long)] + pub identity_key: String, +} + +pub async fn claim_delegator_reward(args: Args, client: SigningClient) { + info!("Claim delegator reward"); + + let res = client + .execute_claim_delegator_reward(args.identity_key, None) + .await + .expect("failed to claim delegator-reward"); + + info!("Claiming delegator reward: {:?}", res) +} diff --git a/common/commands/src/validator/mixnet/delegators/rewards/mod.rs b/common/commands/src/validator/mixnet/delegators/rewards/mod.rs new file mode 100644 index 0000000000..05fe7e98b5 --- /dev/null +++ b/common/commands/src/validator/mixnet/delegators/rewards/mod.rs @@ -0,0 +1,22 @@ +// Copyright 2021 - Nym Technologies SA +// SPDX-License-Identifier: Apache-2.0 + +use clap::{Args, Subcommand}; + +pub mod claim_delegator_reward; +pub mod vesting_claim_delegator_reward; + +#[derive(Debug, Args)] +#[clap(args_conflicts_with_subcommands = true, subcommand_required = true)] +pub struct MixnetDelegatorsReward { + #[clap(subcommand)] + pub command: MixnetDelegatorsRewardCommands, +} + +#[derive(Debug, Subcommand)] +pub enum MixnetDelegatorsRewardCommands { + /// Claim rewards accumulated during the delegation of unlocked tokens + Claim(claim_delegator_reward::Args), + /// Claim rewards accumulated during the delegation of locked tokens + VestingClaim(vesting_claim_delegator_reward::Args), +} diff --git a/common/commands/src/validator/mixnet/delegators/rewards/vesting_claim_delegator_reward.rs b/common/commands/src/validator/mixnet/delegators/rewards/vesting_claim_delegator_reward.rs new file mode 100644 index 0000000000..7e0e4d23ee --- /dev/null +++ b/common/commands/src/validator/mixnet/delegators/rewards/vesting_claim_delegator_reward.rs @@ -0,0 +1,23 @@ +// Copyright 2021 - Nym Technologies SA +// SPDX-License-Identifier: Apache-2.0 + +use crate::context::SigningClient; +use clap::Parser; +use log::info; + +#[derive(Debug, Parser)] +pub struct Args { + #[clap(long)] + pub identity: String, +} + +pub async fn vesting_claim_delegator_reward(args: Args, client: SigningClient) { + info!("Claim vesting delegator reward"); + + let res = client + .execute_vesting_claim_delegator_reward(args.identity, None) + .await + .expect("failed to claim vesting delegator-reward"); + + info!("Claiming vesting delegator reward: {:?}", res) +} diff --git a/common/commands/src/validator/mixnet/delegators/undelegate_from_mixnode.rs b/common/commands/src/validator/mixnet/delegators/undelegate_from_mixnode.rs new file mode 100644 index 0000000000..8cd28d0629 --- /dev/null +++ b/common/commands/src/validator/mixnet/delegators/undelegate_from_mixnode.rs @@ -0,0 +1,23 @@ +// Copyright 2021 - Nym Technologies SA +// SPDX-License-Identifier: Apache-2.0 + +use crate::context::SigningClient; +use clap::Parser; +use log::info; + +#[derive(Debug, Parser)] +pub struct Args { + #[clap(long)] + pub identity_key: String, +} + +pub async fn undelegate_from_mixnode(args: Args, client: SigningClient) { + info!("removing stake from mix-node"); + + let res = client + .remove_mixnode_delegation(&*args.identity_key, None) + .await + .expect("failed to remove stake from mixnode!"); + + info!("removing stake from mixnode: {:?}", res) +} diff --git a/common/commands/src/validator/mixnet/delegators/vesting_delegate_to_mixnode.rs b/common/commands/src/validator/mixnet/delegators/vesting_delegate_to_mixnode.rs new file mode 100644 index 0000000000..d87c334fa8 --- /dev/null +++ b/common/commands/src/validator/mixnet/delegators/vesting_delegate_to_mixnode.rs @@ -0,0 +1,34 @@ +// Copyright 2021 - Nym Technologies SA +// SPDX-License-Identifier: Apache-2.0 + +use clap::Parser; +use log::info; + +use mixnet_contract_common::Coin; +use validator_client::nymd::VestingSigningClient; + +use crate::context::SigningClient; + +#[derive(Debug, Parser)] +pub struct Args { + #[clap(long)] + pub identity_key: String, + + #[clap(long)] + pub amount: u128, +} + +pub async fn vesting_delegate_to_mixnode(args: Args, client: SigningClient) { + let denom = client.current_chain_details().mix_denom.base.as_str(); + + info!("Starting vesting delegation to mixnode"); + + let coin = Coin::new(args.amount, denom); + + let res = client + .vesting_delegate_to_mixnode(&*args.identity_key, coin.into(), None) + .await + .expect("failed to delegate to mixnode!"); + + info!("vesting delegating to mixnode: {:?}", res); +} diff --git a/common/commands/src/validator/mixnet/delegators/vesting_undelegate_from_mixnode.rs b/common/commands/src/validator/mixnet/delegators/vesting_undelegate_from_mixnode.rs new file mode 100644 index 0000000000..9dd802f1e0 --- /dev/null +++ b/common/commands/src/validator/mixnet/delegators/vesting_undelegate_from_mixnode.rs @@ -0,0 +1,26 @@ +// Copyright 2021 - Nym Technologies SA +// SPDX-License-Identifier: Apache-2.0 + +use clap::Parser; +use log::info; + +use validator_client::nymd::VestingSigningClient; + +use crate::context::SigningClient; + +#[derive(Debug, Parser)] +pub struct Args { + #[clap(long)] + pub identity_key: String, +} + +pub async fn vesting_undelegate_from_mixnode(args: Args, client: SigningClient) { + info!("removing stake from vesting mix-node"); + + let res = client + .vesting_undelegate_from_mixnode(&*args.identity_key, None) + .await + .expect("failed to remove stake from vesting account on mixnode!"); + + info!("removing stake from vesting mixnode: {:?}", res) +} diff --git a/common/commands/src/validator/mixnet/mod.rs b/common/commands/src/validator/mixnet/mod.rs new file mode 100644 index 0000000000..9429ea6118 --- /dev/null +++ b/common/commands/src/validator/mixnet/mod.rs @@ -0,0 +1,25 @@ +// Copyright 2021 - Nym Technologies SA +// SPDX-License-Identifier: Apache-2.0 + +use clap::{Args, Subcommand}; + +pub mod delegators; +pub mod operators; +pub mod query; + +#[derive(Debug, Args)] +#[clap(args_conflicts_with_subcommands = true, subcommand_required = true)] +pub struct Mixnet { + #[clap(subcommand)] + pub command: MixnetCommands, +} + +#[derive(Debug, Subcommand)] +pub enum MixnetCommands { + /// Query the mixnet directory + Query(query::MixnetQuery), + /// Manage your delegations + Delegators(delegators::MixnetDelegators), + /// Manage a mixnode or gateway you operate + Operators(operators::MixnetOperators), +} diff --git a/common/commands/src/validator/mixnet/operators/gateway/bond_gateway.rs b/common/commands/src/validator/mixnet/operators/gateway/bond_gateway.rs new file mode 100644 index 0000000000..254ae650da --- /dev/null +++ b/common/commands/src/validator/mixnet/operators/gateway/bond_gateway.rs @@ -0,0 +1,77 @@ +// Copyright 2021 - Nym Technologies SA +// SPDX-License-Identifier: Apache-2.0 + +use crate::context::SigningClient; +use clap::Parser; +use log::{info, warn}; +use mixnet_contract_common::Coin; +use network_defaults::{DEFAULT_CLIENT_LISTENING_PORT, DEFAULT_MIX_LISTENING_PORT}; + +#[derive(Debug, Parser)] +pub struct Args { + #[clap(long)] + pub host: String, + + #[clap(long)] + pub signature: String, + + #[clap(long)] + pub mix_port: Option, + + #[clap(long)] + pub clients_port: Option, + + #[clap(long)] + pub location: Option, + + #[clap(long)] + pub sphinx_key: String, + + #[clap(long)] + pub identity_key: String, + + #[clap(long)] + pub version: String, + + #[clap( + long, + help = "bonding amount in current DENOMINATION (so it would be 'unym', rather than 'nym')" + )] + pub amount: u128, + + #[clap(short, long)] + pub force: bool, +} + +pub async fn bond_gateway(args: Args, client: SigningClient) { + let denom = client.current_chain_details().mix_denom.base.as_str(); + + info!("Starting gateway bonding!"); + + // if we're trying to bond less than 1 token + if args.amount < 1_000_000 && !args.force { + warn!("You're trying to bond only {}{} which is less than 1 full token. Are you sure that's what you want? If so, run with `--force` or `-f` flag", args.amount, denom); + return; + } + + let gateway = mixnet_contract_common::Gateway { + host: args.host, + mix_port: args.mix_port.unwrap_or(DEFAULT_MIX_LISTENING_PORT), + clients_port: args.clients_port.unwrap_or(DEFAULT_CLIENT_LISTENING_PORT), + location: args + .location + .unwrap_or_else(|| "secret gateway location".to_owned()), + sphinx_key: args.sphinx_key, + identity_key: args.identity_key, + version: args.version, + }; + + let coin = Coin::new(args.amount, denom); + + let res = client + .bond_gateway(gateway, args.signature, coin.into(), None) + .await + .expect("failed to bond gateway!"); + + info!("Bonding result: {:?}", res) +} diff --git a/common/commands/src/validator/mixnet/operators/gateway/mod.rs b/common/commands/src/validator/mixnet/operators/gateway/mod.rs new file mode 100644 index 0000000000..af658a7876 --- /dev/null +++ b/common/commands/src/validator/mixnet/operators/gateway/mod.rs @@ -0,0 +1,28 @@ +// Copyright 2021 - Nym Technologies SA +// SPDX-License-Identifier: Apache-2.0 + +use clap::{Args, Subcommand}; + +pub mod bond_gateway; +pub mod unbond_gateway; +pub mod vesting_bond_gateway; +pub mod vesting_unbond_gateway; + +#[derive(Debug, Args)] +#[clap(args_conflicts_with_subcommands = true, subcommand_required = true)] +pub struct MixnetOperatorsGateway { + #[clap(subcommand)] + pub command: MixnetOperatorsGatewayCommands, +} + +#[derive(Debug, Subcommand)] +pub enum MixnetOperatorsGatewayCommands { + /// Bond to a gateway + Bond(bond_gateway::Args), + /// Unbound from a gateway + Unbound(unbond_gateway::Args), + /// Bond to a gateway with locked tokens + VestingBond(vesting_bond_gateway::Args), + /// Unbound from a gateway (when originally using locked tokens) + VestingUnbound(vesting_unbond_gateway::Args), +} diff --git a/common/commands/src/validator/mixnet/operators/gateway/unbond_gateway.rs b/common/commands/src/validator/mixnet/operators/gateway/unbond_gateway.rs new file mode 100644 index 0000000000..75a695dfa1 --- /dev/null +++ b/common/commands/src/validator/mixnet/operators/gateway/unbond_gateway.rs @@ -0,0 +1,20 @@ +// Copyright 2021 - Nym Technologies SA +// SPDX-License-Identifier: Apache-2.0 + +use crate::context::SigningClient; +use clap::Parser; +use log::info; + +#[derive(Debug, Parser)] +pub struct Args {} + +pub async fn unbond_gateway(client: SigningClient) { + info!("Starting gateway unbonding!"); + + let res = client + .unbond_gateway(None) + .await + .expect("failed to unbond gateway!"); + + info!("Unbonding result: {:?}", res) +} diff --git a/common/commands/src/validator/mixnet/operators/gateway/vesting_bond_gateway.rs b/common/commands/src/validator/mixnet/operators/gateway/vesting_bond_gateway.rs new file mode 100644 index 0000000000..d82a01c0c5 --- /dev/null +++ b/common/commands/src/validator/mixnet/operators/gateway/vesting_bond_gateway.rs @@ -0,0 +1,76 @@ +// Copyright 2021 - Nym Technologies SA +// SPDX-License-Identifier: Apache-2.0 + +use crate::context::SigningClient; +use clap::Parser; +use log::{info, warn}; +use mixnet_contract_common::{Coin, Gateway}; +use network_defaults::{DEFAULT_CLIENT_LISTENING_PORT, DEFAULT_MIX_LISTENING_PORT}; +use validator_client::nymd::VestingSigningClient; + +#[derive(Debug, Parser)] +pub struct Args { + #[clap(long)] + pub host: String, + + #[clap(long)] + pub signature: String, + + #[clap(long)] + pub mix_port: Option, + + #[clap(long)] + pub clients_port: Option, + + #[clap(long)] + pub location: Option, + + #[clap(long)] + pub sphinx_key: String, + + #[clap(long)] + pub identity_key: String, + + #[clap(long)] + pub version: String, + + #[clap( + long, + help = "bonding amount in current DENOMINATION (so it would be 'unym', rather than 'nym')" + )] + pub amount: u128, + + #[clap(short, long)] + pub force: bool, +} + +pub async fn vesting_bond_gateway(client: SigningClient, args: Args, denom: &str) { + info!("Starting vesting gateway bonding!"); + + // if we're trying to bond less than 1 token + if args.amount < 1_000_000 && !args.force { + warn!("You're trying to bond only {}{} which is less than 1 full token. Are you sure that's what you want? If so, run with `--force` or `-f` flag", args.amount, denom); + return; + } + + let gateway = Gateway { + host: args.host, + mix_port: args.mix_port.unwrap_or(DEFAULT_MIX_LISTENING_PORT), + clients_port: args.clients_port.unwrap_or(DEFAULT_CLIENT_LISTENING_PORT), + location: args + .location + .unwrap_or_else(|| "secret gateway location".to_owned()), + sphinx_key: args.sphinx_key, + identity_key: args.identity_key, + version: args.version, + }; + + let coin = Coin::new(args.amount, denom); + + let res = client + .vesting_bond_gateway(gateway, &*args.signature, coin.into(), None) + .await + .expect("failed to bond gateway!"); + + info!("Vesting bonding gateway result: {:?}", res) +} diff --git a/common/commands/src/validator/mixnet/operators/gateway/vesting_unbond_gateway.rs b/common/commands/src/validator/mixnet/operators/gateway/vesting_unbond_gateway.rs new file mode 100644 index 0000000000..563c4bdff6 --- /dev/null +++ b/common/commands/src/validator/mixnet/operators/gateway/vesting_unbond_gateway.rs @@ -0,0 +1,20 @@ +// Copyright 2021 - Nym Technologies SA +// SPDX-License-Identifier: Apache-2.0 + +use crate::context::SigningClient; +use clap::Parser; +use log::info; + +#[derive(Debug, Parser)] +pub struct Args {} + +pub async fn vesting_unbond_gateway(client: SigningClient) { + info!("Starting vesting gateway unbonding!"); + + let res = client + .unbond_gateway(None) + .await + .expect("failed to unbond vesting gateway!"); + + info!("Unbonding vesting result: {:?}", res) +} diff --git a/common/commands/src/validator/mixnet/operators/mixnode/bond_mixnode.rs b/common/commands/src/validator/mixnet/operators/mixnode/bond_mixnode.rs new file mode 100644 index 0000000000..26d95fe93f --- /dev/null +++ b/common/commands/src/validator/mixnet/operators/mixnode/bond_mixnode.rs @@ -0,0 +1,85 @@ +// Copyright 2021 - Nym Technologies SA +// SPDX-License-Identifier: Apache-2.0 + +use clap::Parser; +use log::{info, warn}; + +use mixnet_contract_common::Coin; +use network_defaults::{ + DEFAULT_HTTP_API_LISTENING_PORT, DEFAULT_MIX_LISTENING_PORT, DEFAULT_VERLOC_LISTENING_PORT, +}; + +use crate::context::SigningClient; + +#[derive(Debug, Parser)] +pub struct Args { + #[clap(long)] + pub host: String, + + #[clap(long)] + pub signature: String, + + #[clap(long)] + pub mix_port: Option, + + #[clap(long)] + pub verloc_port: Option, + + #[clap(long)] + pub http_api_port: Option, + + #[clap(long)] + pub sphinx_key: String, + + #[clap(long)] + pub identity_key: String, + + #[clap(long)] + pub version: String, + + #[clap(long)] + pub profit_margin_percent: Option, + + #[clap( + long, + help = "bonding amount in current DENOMINATION (so it would be 'unym', rather than 'nym')" + )] + pub amount: u128, + + #[clap(short, long)] + pub force: bool, +} + +pub async fn bond_mixnode(args: Args, client: SigningClient) { + let denom = client.current_chain_details().mix_denom.base.as_str(); + + info!("Starting mixnode bonding!"); + + // if we're trying to bond less than 1 token + if args.amount < 1_000_000 && !args.force { + warn!("You're trying to bond only {}{} which is less than 1 full token. Are you sure that's what you want? If so, run with `--force` or `-f` flag", args.amount, denom); + return; + } + + let mixnode = mixnet_contract_common::MixNode { + host: args.host, + mix_port: args.mix_port.unwrap_or(DEFAULT_MIX_LISTENING_PORT), + verloc_port: args.verloc_port.unwrap_or(DEFAULT_VERLOC_LISTENING_PORT), + http_api_port: args + .http_api_port + .unwrap_or(DEFAULT_HTTP_API_LISTENING_PORT), + sphinx_key: args.sphinx_key, + identity_key: args.identity_key, + version: args.version, + profit_margin_percent: args.profit_margin_percent.unwrap_or(10), + }; + + let coin = Coin::new(args.amount, denom); + + let res = client + .bond_mixnode(mixnode, args.signature, coin.into(), None) + .await + .expect("failed to bond mixnode!"); + + info!("Bonding result: {:?}", res) +} diff --git a/common/commands/src/validator/mixnet/operators/mixnode/keys/decode_mixnode_key.rs b/common/commands/src/validator/mixnet/operators/mixnode/keys/decode_mixnode_key.rs new file mode 100644 index 0000000000..5938a672c4 --- /dev/null +++ b/common/commands/src/validator/mixnet/operators/mixnode/keys/decode_mixnode_key.rs @@ -0,0 +1,17 @@ +// Copyright 2021 - Nym Technologies SA +// SPDX-License-Identifier: Apache-2.0 + +use clap::Parser; + +#[derive(Debug, Parser)] +pub struct Args { + #[clap(short, long)] + pub key: String, +} + +pub fn decode_mixnode_key(args: Args) { + let b64_decoded = base64::decode(args.key).expect("failed to decode base64 string"); + let b58_encoded = bs58::encode(&b64_decoded).into_string(); + + println!("{}", b58_encoded) +} diff --git a/common/commands/src/validator/mixnet/operators/mixnode/keys/mod.rs b/common/commands/src/validator/mixnet/operators/mixnode/keys/mod.rs new file mode 100644 index 0000000000..3f2b566a12 --- /dev/null +++ b/common/commands/src/validator/mixnet/operators/mixnode/keys/mod.rs @@ -0,0 +1,19 @@ +// Copyright 2021 - Nym Technologies SA +// SPDX-License-Identifier: Apache-2.0 + +use clap::{Args, Subcommand}; + +pub mod decode_mixnode_key; + +#[derive(Debug, Args)] +#[clap(args_conflicts_with_subcommands = true, subcommand_required = true)] +pub struct MixnetOperatorsMixnodeKeys { + #[clap(subcommand)] + pub command: MixnetOperatorsMixnodeKeysCommands, +} + +#[derive(Debug, Subcommand)] +pub enum MixnetOperatorsMixnodeKeysCommands { + /// Decode a mixnode key + DecodeMixnodeKey(decode_mixnode_key::Args), +} diff --git a/common/commands/src/validator/mixnet/operators/mixnode/mod.rs b/common/commands/src/validator/mixnet/operators/mixnode/mod.rs new file mode 100644 index 0000000000..e608c4c36f --- /dev/null +++ b/common/commands/src/validator/mixnet/operators/mixnode/mod.rs @@ -0,0 +1,37 @@ +// Copyright 2021 - Nym Technologies SA +// SPDX-License-Identifier: Apache-2.0 + +use clap::{Args, Subcommand}; + +pub mod bond_mixnode; +pub mod keys; +pub mod rewards; +pub mod settings; +pub mod unbond_mixnode; +pub mod vesting_bond_mixnode; +pub mod vesting_unbond_mixnode; + +#[derive(Debug, Args)] +#[clap(args_conflicts_with_subcommands = true, subcommand_required = true)] +pub struct MixnetOperatorsMixnode { + #[clap(subcommand)] + pub command: MixnetOperatorsMixnodeCommands, +} + +#[derive(Debug, Subcommand)] +pub enum MixnetOperatorsMixnodeCommands { + /// Operations for mixnode keys + Keys(keys::MixnetOperatorsMixnodeKeys), + /// Manage your mixnode operator rewards + Rewards(rewards::MixnetOperatorsMixnodeRewards), + /// Manage your mixnode settings stored in the directory + Settings(settings::MixnetOperatorsMixnodeSettings), + /// Bond to a mixnode + Bond(bond_mixnode::Args), + /// Unbound from a mixnode + Unbound(unbond_mixnode::Args), + /// Bond to a mixnode with locked tokens + BondVesting(vesting_bond_mixnode::Args), + /// Unbound from a mixnode (when originally using locked tokens) + UnboundVesting(vesting_unbond_mixnode::Args), +} diff --git a/common/commands/src/validator/mixnet/operators/mixnode/rewards/claim_operator_reward.rs b/common/commands/src/validator/mixnet/operators/mixnode/rewards/claim_operator_reward.rs new file mode 100644 index 0000000000..2f3f8dd3c4 --- /dev/null +++ b/common/commands/src/validator/mixnet/operators/mixnode/rewards/claim_operator_reward.rs @@ -0,0 +1,20 @@ +// Copyright 2021 - Nym Technologies SA +// SPDX-License-Identifier: Apache-2.0 + +use crate::context::SigningClient; +use clap::Parser; +use log::info; + +#[derive(Debug, Parser)] +pub struct Args {} + +pub async fn claim_operator_reward(_args: Args, client: SigningClient) { + info!("Claim operator reward"); + + let res = client + .execute_claim_operator_reward(None) + .await + .expect("failed to claim operator reward"); + + info!("Claiming operator reward: {:?}", res) +} diff --git a/common/commands/src/validator/mixnet/operators/mixnode/rewards/mod.rs b/common/commands/src/validator/mixnet/operators/mixnode/rewards/mod.rs new file mode 100644 index 0000000000..d3e4fc988c --- /dev/null +++ b/common/commands/src/validator/mixnet/operators/mixnode/rewards/mod.rs @@ -0,0 +1,22 @@ +// Copyright 2021 - Nym Technologies SA +// SPDX-License-Identifier: Apache-2.0 + +use clap::{Args, Subcommand}; + +pub mod claim_operator_reward; +pub mod vesting_claim_operator_reward; + +#[derive(Debug, Args)] +#[clap(args_conflicts_with_subcommands = true, subcommand_required = true)] +pub struct MixnetOperatorsMixnodeRewards { + #[clap(subcommand)] + pub command: MixnetOperatorsMixnodeRewardsCommands, +} + +#[derive(Debug, Subcommand)] +pub enum MixnetOperatorsMixnodeRewardsCommands { + /// Claim rewards + Claim(claim_operator_reward::Args), + /// Claim rewards for a mixnode bonded with locked tokens + VestingClaim(vesting_claim_operator_reward::Args), +} diff --git a/common/commands/src/validator/mixnet/operators/mixnode/rewards/vesting_claim_operator_reward.rs b/common/commands/src/validator/mixnet/operators/mixnode/rewards/vesting_claim_operator_reward.rs new file mode 100644 index 0000000000..ffcd4670e1 --- /dev/null +++ b/common/commands/src/validator/mixnet/operators/mixnode/rewards/vesting_claim_operator_reward.rs @@ -0,0 +1,23 @@ +// Copyright 2021 - Nym Technologies SA +// SPDX-License-Identifier: Apache-2.0 + +use crate::context::SigningClient; +use clap::Parser; +use log::info; + +#[derive(Debug, Parser)] +pub struct Args { + #[clap(long)] + pub gas: Option, +} + +pub async fn vesting_claim_operator_reward(client: SigningClient) { + info!("Claim vesting operator reward"); + + let res = client + .execute_vesting_claim_operator_reward(None) + .await + .expect("failed to claim vesting operator reward"); + + info!("Claiming vesting operator reward: {:?}", res) +} diff --git a/common/commands/src/validator/mixnet/operators/mixnode/settings/mod.rs b/common/commands/src/validator/mixnet/operators/mixnode/settings/mod.rs new file mode 100644 index 0000000000..10bbd6ba8b --- /dev/null +++ b/common/commands/src/validator/mixnet/operators/mixnode/settings/mod.rs @@ -0,0 +1,22 @@ +// Copyright 2021 - Nym Technologies SA +// SPDX-License-Identifier: Apache-2.0 + +use clap::{Args, Subcommand}; + +pub mod update_profit_percent; +pub mod vesting_update_profit_percent; + +#[derive(Debug, Args)] +#[clap(args_conflicts_with_subcommands = true, subcommand_required = true)] +pub struct MixnetOperatorsMixnodeSettings { + #[clap(subcommand)] + pub command: MixnetOperatorsMixnodeSettingsCommands, +} + +#[derive(Debug, Subcommand)] +pub enum MixnetOperatorsMixnodeSettingsCommands { + /// Update profit percentage + UpdateProfitPercentage(update_profit_percent::Args), + /// Update profit percentage for a mixnode bonded with locked tokens + VestingUpdateProfitPercentage(vesting_update_profit_percent::Args), +} diff --git a/common/commands/src/validator/mixnet/operators/mixnode/settings/update_profit_percent.rs b/common/commands/src/validator/mixnet/operators/mixnode/settings/update_profit_percent.rs new file mode 100644 index 0000000000..3c874c007c --- /dev/null +++ b/common/commands/src/validator/mixnet/operators/mixnode/settings/update_profit_percent.rs @@ -0,0 +1,24 @@ +// Copyright 2021 - Nym Technologies SA +// SPDX-License-Identifier: Apache-2.0 + +use crate::context::SigningClient; +use clap::Parser; +use log::info; + +#[derive(Debug, Parser)] +pub struct Args { + #[clap(long)] + pub profit_percent: u8, +} + +pub async fn update_profit_percent(args: Args, client: SigningClient) { + info!("Update mix node profit percent - get those rewards!"); + + //profit percent between 1-100 + let res = client + .update_mixnode_config(args.profit_percent, None) + .await + .expect("updating mix-node profit percent"); + + info!("profit percentage updated: {:?}", res) +} diff --git a/common/commands/src/validator/mixnet/operators/mixnode/settings/vesting_update_profit_percent.rs b/common/commands/src/validator/mixnet/operators/mixnode/settings/vesting_update_profit_percent.rs new file mode 100644 index 0000000000..cc47d99c1e --- /dev/null +++ b/common/commands/src/validator/mixnet/operators/mixnode/settings/vesting_update_profit_percent.rs @@ -0,0 +1,28 @@ +// Copyright 2021 - Nym Technologies SA +// SPDX-License-Identifier: Apache-2.0 + +use crate::context::SigningClient; +use clap::Parser; +use log::info; +use validator_client::nymd::VestingSigningClient; + +#[derive(Debug, Parser)] +pub struct Args { + #[clap(long)] + pub profit_percent: u8, + + #[clap(long)] + pub gas: Option, +} + +pub async fn vesting_update_profit_percent(client: SigningClient, args: Args) { + info!("Update vesting mix node profit percent - get those rewards!"); + + //profit percent between 1-100 + let res = client + .vesting_update_mixnode_config(args.profit_percent, None) + .await + .expect("updating vesting mix-node profit percent"); + + info!("profit percentage updated: {:?}", res) +} diff --git a/common/commands/src/validator/mixnet/operators/mixnode/unbond_mixnode.rs b/common/commands/src/validator/mixnet/operators/mixnode/unbond_mixnode.rs new file mode 100644 index 0000000000..d4f2bb478c --- /dev/null +++ b/common/commands/src/validator/mixnet/operators/mixnode/unbond_mixnode.rs @@ -0,0 +1,21 @@ +// Copyright 2021 - Nym Technologies SA +// SPDX-License-Identifier: Apache-2.0 + +use clap::Parser; +use log::info; + +use crate::context::SigningClient; + +#[derive(Debug, Parser)] +pub struct Args {} + +pub async fn unbond_mixnode(_args: Args, client: SigningClient) { + info!("Starting mixnode unbonding!"); + + let res = client + .unbond_mixnode(None) + .await + .expect("failed to unbond mixnode!"); + + info!("Unbonding result: {:?}", res) +} diff --git a/common/commands/src/validator/mixnet/operators/mixnode/vesting_bond_mixnode.rs b/common/commands/src/validator/mixnet/operators/mixnode/vesting_bond_mixnode.rs new file mode 100644 index 0000000000..2e90a83f7e --- /dev/null +++ b/common/commands/src/validator/mixnet/operators/mixnode/vesting_bond_mixnode.rs @@ -0,0 +1,86 @@ +// Copyright 2021 - Nym Technologies SA +// SPDX-License-Identifier: Apache-2.0 + +use crate::context::SigningClient; +use clap::Parser; +use log::{info, warn}; +use mixnet_contract_common::Coin; +use mixnet_contract_common::MixNode; +use network_defaults::{ + DEFAULT_HTTP_API_LISTENING_PORT, DEFAULT_MIX_LISTENING_PORT, DEFAULT_VERLOC_LISTENING_PORT, +}; +use validator_client::nymd::VestingSigningClient; + +#[derive(Debug, Parser)] +pub struct Args { + #[clap(long)] + pub host: String, + + #[clap(long)] + pub signature: String, + + #[clap(long)] + pub mix_port: Option, + + #[clap(long)] + pub verloc_port: Option, + + #[clap(long)] + pub http_api_port: Option, + + #[clap(long)] + pub sphinx_key: String, + + #[clap(long)] + pub identity_key: String, + + #[clap(long)] + pub version: String, + + #[clap(long)] + pub profit_margin_percent: Option, + + #[clap( + long, + help = "bonding amount in current DENOMINATION (so it would be 'unym', rather than 'nym')" + )] + pub amount: u128, + + #[clap(long)] + pub gas: Option, + + #[clap(short, long)] + pub force: bool, +} + +pub async fn vesting_bond_mixnode(client: SigningClient, args: Args, denom: &str) { + info!("Starting vesting mixnode bonding!"); + + // if we're trying to bond less than 1 token + if args.amount < 1_000_000 && !args.force { + warn!("You're trying to bond only {}{} which is less than 1 full token. Are you sure that's what you want? If so, run with `--force` or `-f` flag", args.amount, denom); + return; + } + + let mixnode = MixNode { + host: args.host, + mix_port: args.mix_port.unwrap_or(DEFAULT_MIX_LISTENING_PORT), + verloc_port: args.verloc_port.unwrap_or(DEFAULT_VERLOC_LISTENING_PORT), + http_api_port: args + .http_api_port + .unwrap_or(DEFAULT_HTTP_API_LISTENING_PORT), + sphinx_key: args.sphinx_key, + identity_key: args.identity_key, + version: args.version, + profit_margin_percent: args.profit_margin_percent.unwrap_or(10), + }; + + let coin = Coin::new(args.amount, denom); + + let res = client + .vesting_bond_mixnode(mixnode, &*args.signature, coin.into(), None) + .await + .expect("failed to bond vesting mixnode!"); + + info!("Bonding vesting result: {:?}", res) +} diff --git a/common/commands/src/validator/mixnet/operators/mixnode/vesting_unbond_mixnode.rs b/common/commands/src/validator/mixnet/operators/mixnode/vesting_unbond_mixnode.rs new file mode 100644 index 0000000000..0824cc9342 --- /dev/null +++ b/common/commands/src/validator/mixnet/operators/mixnode/vesting_unbond_mixnode.rs @@ -0,0 +1,24 @@ +// Copyright 2021 - Nym Technologies SA +// SPDX-License-Identifier: Apache-2.0 + +use crate::context::SigningClient; +use clap::Parser; +use log::info; +use validator_client::nymd::VestingSigningClient; + +#[derive(Debug, Parser)] +pub struct Args { + #[clap(long)] + pub gas: Option, +} + +pub async fn vesting_unbond_mixnode(client: SigningClient) { + info!("Starting vesting mixnode unbonding!"); + + let res = client + .vesting_unbond_mixnode(None) + .await + .expect("failed to unbond vesting mixnode!"); + + info!("Unbonding vesting result: {:?}", res) +} diff --git a/common/commands/src/validator/mixnet/operators/mod.rs b/common/commands/src/validator/mixnet/operators/mod.rs new file mode 100644 index 0000000000..a38479ba65 --- /dev/null +++ b/common/commands/src/validator/mixnet/operators/mod.rs @@ -0,0 +1,22 @@ +// Copyright 2021 - Nym Technologies SA +// SPDX-License-Identifier: Apache-2.0 + +use clap::{Args, Subcommand}; + +pub mod gateway; +pub mod mixnode; + +#[derive(Debug, Args)] +#[clap(args_conflicts_with_subcommands = true, subcommand_required = true)] +pub struct MixnetOperators { + #[clap(subcommand)] + pub command: MixnetOperatorsCommands, +} + +#[derive(Debug, Subcommand)] +pub enum MixnetOperatorsCommands { + /// Manage your mixnode + Mixnode(mixnode::MixnetOperatorsMixnode), + /// Manage your gateway + Gateway(gateway::MixnetOperatorsGateway), +} diff --git a/common/commands/src/validator/mixnet/query/mod.rs b/common/commands/src/validator/mixnet/query/mod.rs new file mode 100644 index 0000000000..6d86e6c7b9 --- /dev/null +++ b/common/commands/src/validator/mixnet/query/mod.rs @@ -0,0 +1,22 @@ +// Copyright 2021 - Nym Technologies SA +// SPDX-License-Identifier: Apache-2.0 + +use clap::{Args, Subcommand}; + +pub mod query_all_gateways; +pub mod query_all_mixnodes; + +#[derive(Debug, Args)] +#[clap(args_conflicts_with_subcommands = true, subcommand_required = true)] +pub struct MixnetQuery { + #[clap(subcommand)] + pub command: MixnetQueryCommands, +} + +#[derive(Debug, Subcommand)] +pub enum MixnetQueryCommands { + /// Query mixnodes + Mixnodes(query_all_mixnodes::Args), + /// Query gateways + Gateways(query_all_gateways::Args), +} diff --git a/common/commands/src/validator/mixnet/query/query_all_gateways.rs b/common/commands/src/validator/mixnet/query/query_all_gateways.rs new file mode 100644 index 0000000000..679ac08bcd --- /dev/null +++ b/common/commands/src/validator/mixnet/query/query_all_gateways.rs @@ -0,0 +1,52 @@ +// Copyright 2022 - Nym Technologies SA +// SPDX-License-Identifier: Apache-2.0 + +use clap::Parser; +use comfy_table::Table; + +use crate::context::QueryClientWithValidatorAPI; +use crate::utils::{pretty_cosmwasm_coin, show_error}; + +#[derive(Debug, Parser)] +pub struct Args { + #[clap(value_parser)] + #[clap(help = "Optionally, the gateway to display")] + pub identity_key: Option, +} + +pub async fn query(args: Args, client: &QueryClientWithValidatorAPI) { + match client.validator_api.get_gateways().await { + Ok(res) => match args.identity_key { + Some(identity_key) => { + let node = res.iter().find(|node| { + node.gateway + .identity_key + .to_string() + .eq_ignore_ascii_case(&identity_key) + }); + println!( + "{}", + ::serde_json::to_string_pretty(&node).expect("json formatting error") + ); + } + None => { + let mut table = Table::new(); + + table.set_header(vec!["Identity Key", "Owner", "Host", "Bond", "Version"]); + for node in res { + table.add_row(vec![ + node.gateway.identity_key.to_string(), + node.owner.to_string(), + node.gateway.host.to_string(), + pretty_cosmwasm_coin(&node.pledge_amount), + node.gateway.version, + ]); + } + + println!("The gateways in the directory are:"); + println!("{table}"); + } + }, + Err(e) => show_error(e), + } +} diff --git a/common/commands/src/validator/mixnet/query/query_all_mixnodes.rs b/common/commands/src/validator/mixnet/query/query_all_mixnodes.rs new file mode 100644 index 0000000000..91cc344806 --- /dev/null +++ b/common/commands/src/validator/mixnet/query/query_all_mixnodes.rs @@ -0,0 +1,60 @@ +// Copyright 2022 - Nym Technologies SA +// SPDX-License-Identifier: Apache-2.0 + +use clap::Parser; +use comfy_table::Table; + +use crate::context::QueryClientWithValidatorAPI; +use crate::utils::{pretty_cosmwasm_coin, show_error}; + +#[derive(Debug, Parser)] +pub struct Args { + #[clap(value_parser)] + #[clap(help = "Optionally, the mixnode to display")] + pub identity_key: Option, +} + +pub async fn query(args: Args, client: &QueryClientWithValidatorAPI) { + match client.validator_api.get_mixnodes().await { + Ok(res) => match args.identity_key { + Some(identity_key) => { + let node = res.iter().find(|node| { + node.mix_node + .identity_key + .to_string() + .eq_ignore_ascii_case(&identity_key) + }); + println!( + "{}", + ::serde_json::to_string_pretty(&node).expect("json formatting error") + ); + } + None => { + let mut table = Table::new(); + + table.set_header(vec![ + "Identity Key", + "Owner", + "Host", + "Bond", + "Total Delegations", + "Version", + ]); + for node in res { + table.add_row(vec![ + node.mix_node.identity_key.to_string(), + node.owner.to_string(), + node.mix_node.host.to_string(), + pretty_cosmwasm_coin(&node.pledge_amount), + pretty_cosmwasm_coin(&node.total_delegation()), + node.mix_node.version, + ]); + } + + println!("The mixnodes in the directory are:"); + println!("{table}"); + } + }, + Err(e) => show_error(e), + } +} diff --git a/common/commands/src/validator/mod.rs b/common/commands/src/validator/mod.rs new file mode 100644 index 0000000000..ebc295569f --- /dev/null +++ b/common/commands/src/validator/mod.rs @@ -0,0 +1,10 @@ +// Copyright 2021 - Nym Technologies SA +// SPDX-License-Identifier: Apache-2.0 + +pub mod account; +pub mod block; +pub mod cosmwasm; +pub mod mixnet; +pub mod signature; +pub mod transactions; +pub mod vesting; diff --git a/common/commands/src/validator/signature/errors.rs b/common/commands/src/validator/signature/errors.rs new file mode 100644 index 0000000000..82aae7e08c --- /dev/null +++ b/common/commands/src/validator/signature/errors.rs @@ -0,0 +1,13 @@ +// Copyright 2022 - Nym Technologies SA +// SPDX-License-Identifier: Apache-2.0 + +use thiserror::Error; + +#[derive(Error, Debug)] +pub enum Errors { + #[error("signature error - {0}")] + SignatureError(#[from] k256::ecdsa::signature::Error), + + #[error("{0}")] + CosmrsError(#[from] cosmrs::ErrorReport), +} diff --git a/common/commands/src/validator/signature/helpers.rs b/common/commands/src/validator/signature/helpers.rs new file mode 100644 index 0000000000..817a880b64 --- /dev/null +++ b/common/commands/src/validator/signature/helpers.rs @@ -0,0 +1,90 @@ +use std::str::FromStr; + +use cosmrs::crypto::secp256k1::{Signature, VerifyingKey}; +use cosmrs::crypto::PublicKey; +use k256::ecdsa::signature::Verifier; + +use crate::validator::signature::errors::Errors; + +pub fn secp256k1_verify_with_public_key( + public_key_as_bytes: &[u8], + signature_as_hex: String, + message: String, +) -> Result<(), k256::ecdsa::signature::Error> { + let verifying_key = VerifyingKey::from_sec1_bytes(public_key_as_bytes)?; + let signature = Signature::from_str(&signature_as_hex)?; + let message_as_bytes = message.into_bytes(); + verifying_key.verify(&message_as_bytes, &signature) +} + +pub fn secp256k1_verify_with_public_key_json( + public_key_as_json: String, + signature_as_hex: String, + message: String, +) -> Result<(), Errors> { + let public_key = PublicKey::from_json(&public_key_as_json)?; + let verifying_key = VerifyingKey::from_sec1_bytes(&public_key.to_bytes())?; + let signature = Signature::from_str(&signature_as_hex)?; + let message_as_bytes = message.into_bytes(); + Ok(verifying_key.verify(&message_as_bytes, &signature)?) +} + +#[cfg(test)] +mod test_secp256k1 { + use crate::validator::signature::helpers::{ + secp256k1_verify_with_public_key, secp256k1_verify_with_public_key_json, + }; + use cosmrs::crypto::PublicKey; + + #[test] + fn test_verify_with_json_public_key_with_valid_signature() { + let json_public_key = r#"{"@type":"/cosmos.crypto.secp256k1.PubKey","key":"A4FdhUMasPmNhRZjtpKlmjNbq7EEUgPxfdI+E3vSajvc"}"#; + let signature_as_hex = "E3AA5AC0DA1B7DEBB7808000F719D8ACB9A0BE10AFA2756A788516268EB246A1257EC1097C5E364EF916145B01641DEDFE955994CB340BDAFA99A65BCA3F6F28".to_string(); + let message = "test 1234".to_string(); + + let public_key = PublicKey::from_json(json_public_key).unwrap(); + let public_key_bytes = public_key.to_bytes(); + + let result = secp256k1_verify_with_public_key(&public_key_bytes, signature_as_hex, message); + + assert!(result.is_ok()); + } + + #[test] + fn test_verify_with_json_public_key_with_invalid_signature() { + let json_public_key = r#"{"@type":"/cosmos.crypto.secp256k1.PubKey","key":"A4FdhUMasPmNhRZjtpKlmjNbq7EEUgPxfdI+E3vSajvc"}"#; + let signature_as_hex = "E3AA5AC0DA1B7DEBB7808000F719D8ACB9A0BE10AFA2756A788516268EB246A1257EC1097C5E364EF916145B01641DEDFE955994CB340BDAFA99A65BCA3F6F28".to_string(); + let message = "abcdef".to_string(); + + let public_key = PublicKey::from_json(json_public_key).unwrap(); + let public_key_bytes = public_key.to_bytes(); + + let result = secp256k1_verify_with_public_key(&public_key_bytes, signature_as_hex, message); + + assert!(result.is_err()); + } + + #[test] + fn test_valid_json_public_key_succeeds() { + let json_public_key = r#"{"@type":"/cosmos.crypto.secp256k1.PubKey","key":"A4FdhUMasPmNhRZjtpKlmjNbq7EEUgPxfdI+E3vSajvc"}"#.to_string(); + let signature_as_hex = "E3AA5AC0DA1B7DEBB7808000F719D8ACB9A0BE10AFA2756A788516268EB246A1257EC1097C5E364EF916145B01641DEDFE955994CB340BDAFA99A65BCA3F6F28".to_string(); + let message = "test 1234".to_string(); + + let result = + secp256k1_verify_with_public_key_json(json_public_key, signature_as_hex, message); + + assert!(result.is_ok()); + } + + #[test] + fn test_json_public_key_fails_with_error() { + let bad_json_public_key = r#"This is not JSON ☠️"#.to_string(); + let signature_as_hex = "E3AA5AC0DA1B7DEBB7808000F719D8ACB9A0BE10AFA2756A788516268EB246A1257EC1097C5E364EF916145B01641DEDFE955994CB340BDAFA99A65BCA3F6F28".to_string(); + let message = "abcdef".to_string(); + + let result = + secp256k1_verify_with_public_key_json(bad_json_public_key, signature_as_hex, message); + + assert!(result.is_err()); + } +} diff --git a/common/commands/src/validator/signature/mod.rs b/common/commands/src/validator/signature/mod.rs new file mode 100644 index 0000000000..3782e977f4 --- /dev/null +++ b/common/commands/src/validator/signature/mod.rs @@ -0,0 +1,24 @@ +// Copyright 2022 - Nym Technologies SA +// SPDX-License-Identifier: Apache-2.0 + +use clap::{Args, Subcommand}; + +pub mod errors; +pub mod helpers; +pub mod sign; +pub mod verify; + +#[derive(Debug, Args)] +#[clap(args_conflicts_with_subcommands = true, subcommand_required = true)] +pub struct Signature { + #[clap(subcommand)] + pub command: Option, +} + +#[derive(Debug, Subcommand)] +pub enum SignatureCommands { + /// Sign a message + Sign(crate::validator::signature::sign::Args), + /// Verify a message + Verify(crate::validator::signature::verify::Args), +} diff --git a/common/commands/src/validator/signature/sign.rs b/common/commands/src/validator/signature/sign.rs new file mode 100644 index 0000000000..d26302aeba --- /dev/null +++ b/common/commands/src/validator/signature/sign.rs @@ -0,0 +1,68 @@ +// Copyright 2022 - Nym Technologies SA +// SPDX-License-Identifier: Apache-2.0 + +use crate::utils::show_error; +use clap::Parser; +use cosmrs::crypto::PublicKey; +use log::error; +use serde::Serialize; +use serde_json::json; +use validator_client::nymd::wallet::DirectSecp256k1HdWallet; + +#[derive(Debug, Serialize)] +pub struct SignatureOutputJson { + pub account_id: String, + pub public_key: PublicKey, + pub signature: String, +} + +#[derive(Debug, Parser)] +pub struct Args { + #[clap(value_parser)] + #[clap(help = "The message to sign")] + pub message: String, +} + +pub fn sign(args: Args, prefix: &str, mnemonic: Option) { + if args.message.trim().is_empty() { + error!("Message is empty or contains only whitespace"); + return; + } + + if mnemonic.is_none() { + error!( + "Please provide the mnemonic as an argument or using the MNEMONIC environment variable" + ); + return; + } + + match DirectSecp256k1HdWallet::from_mnemonic(prefix, mnemonic.expect("mnemonic not set")) { + Ok(wallet) => match wallet.try_derive_accounts() { + Ok(accounts) => match accounts.first() { + Some(account) => { + let msg = args.message.into_bytes(); + match wallet.sign_raw_with_account(account, &msg) { + Ok(signature) => { + let output = SignatureOutputJson { + account_id: account.address().to_string(), + public_key: account.public_key(), + signature: signature.to_string(), + }; + println!("{}", json!(output)); + } + Err(e) => { + error!("Failed to sign message. {}", e); + } + } + } + None => { + error!("Could not derive an account key from the mnemonic",) + } + }, + Err(e) => { + error!("Failed to derive accounts. {}", e); + } + }, + Err(e) => show_error(e), + } +} diff --git a/common/commands/src/validator/signature/verify.rs b/common/commands/src/validator/signature/verify.rs new file mode 100644 index 0000000000..b29f93ca9a --- /dev/null +++ b/common/commands/src/validator/signature/verify.rs @@ -0,0 +1,89 @@ +// Copyright 2022 - Nym Technologies SA +// SPDX-License-Identifier: Apache-2.0 + +use std::str::FromStr; + +use clap::Parser; +use cosmrs::crypto::PublicKey; +use log::{error, info}; +use serde_json::json; + +use validator_client::nymd::AccountId; + +use crate::context::QueryClient; +use crate::validator::signature::helpers::secp256k1_verify_with_public_key; + +#[derive(Debug, Parser)] +pub struct Args { + #[clap(value_parser)] + #[clap( + help = "The public key of the account, or the account id to query for a public key (NOTE: the account must have signed a message stored on the chain for the public key record to exist)" + )] + pub public_key_or_address: String, + + #[clap(value_parser)] + #[clap(help = "The signature to verify as hex")] + pub signature_as_hex: String, + + #[clap(value_parser)] + #[clap(help = "The message to verify as a string")] + pub message: String, +} + +pub async fn verify(args: Args, client: &QueryClient) { + if args.public_key_or_address.trim().is_empty() { + error!("Please ensure the public key or address is not empty or whitespace"); + return; + } + + let public_key = match AccountId::from_str(&args.public_key_or_address) { + Ok(address) => { + info!("Found account address instead of public key, so looking up public key for {} from chain", address); + match client.get_account_public_key(&address).await.ok() { + Some(public_key) => { + if let Some(k) = public_key { + info!("Found public key {}", json!(k)); + } + public_key + } + None => { + error!( + "Address {} does not have a public key recorded on the chain. This is probably because the account has never signed a transaction.", + address + ); + None + } + } + } + Err(_) => match PublicKey::from_json(&args.public_key_or_address) { + Ok(parsed) => Some(parsed), + Err(e) => { + error!("Public key should be JSON. Unable to parse: {}", e); + None + } + }, + }; + + match public_key { + Some(public_key) => { + if public_key.type_url() != PublicKey::SECP256K1_TYPE_URL { + error!("Sorry, we only support secp256k1 public keys at the moment"); + return; + } + + match secp256k1_verify_with_public_key( + &public_key.to_bytes(), + args.signature_as_hex, + args.message, + ) { + Ok(()) => println!("SUCCESS ✅ signature verified"), + Err(e) => { + error!("FAILURE ❌ Signature verification failed: {}", e); + } + } + } + None => { + error!("Unable to verify, as unable to get the public key"); + } + } +} diff --git a/common/commands/src/validator/transactions/get_transaction.rs b/common/commands/src/validator/transactions/get_transaction.rs new file mode 100644 index 0000000000..3d1b53e7b2 --- /dev/null +++ b/common/commands/src/validator/transactions/get_transaction.rs @@ -0,0 +1,28 @@ +// Copyright 2022 - Nym Technologies SA +// SPDX-License-Identifier: Apache-2.0 + +use clap::Parser; +use std::str::FromStr; + +use crate::context::QueryClient; +use crate::utils::show_error; +use cosmrs::tx::Hash; +use serde_json::json; + +#[derive(Debug, Parser)] +pub struct Args { + #[clap(value_parser)] + #[clap(help = "The transaction hash")] + pub tx_hash: String, +} + +pub async fn get(args: Args, client: &QueryClient) { + let hash = Hash::from_str(&args.tx_hash).expect("could not parse transaction hash"); + + match client.get_tx(hash).await { + Ok(res) => { + println!("{}", json!(res)) + } + Err(e) => show_error(e), + } +} diff --git a/common/commands/src/validator/transactions/mod.rs b/common/commands/src/validator/transactions/mod.rs new file mode 100644 index 0000000000..d78cdf07b0 --- /dev/null +++ b/common/commands/src/validator/transactions/mod.rs @@ -0,0 +1,22 @@ +// Copyright 2021 - Nym Technologies SA +// SPDX-License-Identifier: Apache-2.0 + +use clap::{Args, Subcommand}; + +pub mod get_transaction; +pub mod query_transactions; + +#[derive(Debug, Args)] +#[clap(args_conflicts_with_subcommands = true, subcommand_required = true)] +pub struct Transactions { + #[clap(subcommand)] + pub command: Option, +} + +#[derive(Debug, Subcommand)] +pub enum TransactionsCommands { + /// Get a transaction by hash or block height + Get(crate::validator::transactions::get_transaction::Args), + /// Query for transactions + Query(crate::validator::transactions::query_transactions::Args), +} diff --git a/common/commands/src/validator/transactions/query_transactions.rs b/common/commands/src/validator/transactions/query_transactions.rs new file mode 100644 index 0000000000..b8b341ec57 --- /dev/null +++ b/common/commands/src/validator/transactions/query_transactions.rs @@ -0,0 +1,30 @@ +// Copyright 2022 - Nym Technologies SA +// SPDX-License-Identifier: Apache-2.0 + +use std::str::FromStr; + +use clap::Parser; +use cosmrs::rpc::query::Query; +use serde_json::json; + +use crate::context::QueryClient; +use crate::utils::show_error; + +#[derive(Debug, Parser)] +pub struct Args { + #[clap(value_parser)] + #[clap(help = "The query to execute")] + pub query: String, +} + +pub async fn query(args: Args, client: &QueryClient) { + match Query::from_str(&args.query) { + Ok(query) => match client.search_tx(query).await { + Ok(res) => { + println!("{}", json!(res)) + } + Err(e) => show_error(e), + }, + Err(e) => show_error(e), + } +} diff --git a/common/commands/src/validator/vesting/balance.rs b/common/commands/src/validator/vesting/balance.rs new file mode 100644 index 0000000000..45b2f7866d --- /dev/null +++ b/common/commands/src/validator/vesting/balance.rs @@ -0,0 +1,55 @@ +// Copyright 2022 - Nym Technologies SA +// SPDX-License-Identifier: Apache-2.0 + +use clap::Parser; +use cosmrs::AccountId; +use log::info; + +use validator_client::nymd::{Coin, VestingQueryClient}; + +use crate::context::SigningClient; +use crate::utils::show_error; +use crate::utils::{pretty_coin, pretty_cosmwasm_coin}; + +#[derive(Debug, Parser)] +pub struct Args { + #[clap(value_parser)] + #[clap(help = "Optionally, the account address to get the balance for")] + pub address: Option, +} + +pub async fn balance(args: Args, client: SigningClient) { + let account_id = args.address.unwrap_or_else(|| client.address().clone()); + let vesting_address = account_id.to_string(); + let denom = client.current_chain_details().mix_denom.base.as_str(); + + info!( + "Getting vesting schedule information for {}...", + &vesting_address + ); + + let original_vesting = client.original_vesting(&vesting_address).await; + + match original_vesting { + Ok(res) => { + let spendable_coins = client + .spendable_coins(&vesting_address, None) + .await + .unwrap_or_else(|_| Coin::new(0u128, denom)); + let liquid_account_balance = client + .get_balance(&account_id, denom.to_string()) + .await + .unwrap_or(None) + .unwrap_or_else(|| Coin::new(0u128, denom)); + + println!( + "Account {} has\n{} vested with\n{} available to be withdrawn to the main account (balance {})", + &account_id, + pretty_cosmwasm_coin(&res.amount), + pretty_coin(&spendable_coins), + pretty_coin(&liquid_account_balance), + ); + } + Err(e) => show_error(e), + } +} diff --git a/common/commands/src/validator/vesting/create_vesting_schedule.rs b/common/commands/src/validator/vesting/create_vesting_schedule.rs new file mode 100644 index 0000000000..60f69e6f2b --- /dev/null +++ b/common/commands/src/validator/vesting/create_vesting_schedule.rs @@ -0,0 +1,83 @@ +// Copyright 2021 - Nym Technologies SA +// SPDX-License-Identifier: Apache-2.0 + +use std::str::FromStr; + +use clap::Parser; +use log::info; + +use mixnet_contract_common::Coin; +use network_defaults::NymNetworkDetails; +use validator_client::nymd::AccountId; +use validator_client::nymd::VestingSigningClient; +use validator_client::nymd::{CosmosCoin, Denom}; +use vesting_contract_common::messages::VestingSpecification; + +use crate::context::SigningClient; + +#[derive(Debug, Parser)] +pub struct Args { + #[clap(long)] + pub periods_seconds: Option, + + #[clap(long)] + pub number_of_periods: Option, + + #[clap(long)] + pub start_time: Option, + + #[clap(long)] + pub address: String, + + #[clap(long)] + pub amount: u64, + + #[clap(long)] + pub staking_address: Option, +} + +pub async fn create(args: Args, client: SigningClient, network_details: &NymNetworkDetails) { + info!("Creating vesting schedule!"); + + let vesting = VestingSpecification::new( + args.start_time, + args.periods_seconds, + args.number_of_periods, + ); + + let denom = network_details.chain_details.mix_denom.base.to_string(); + + let coin = Coin::new(args.amount.into(), &denom); + + let res = client + .create_periodic_vesting_account( + &*args.address, + args.staking_address, + Some(vesting), + coin.into(), + None, + ) + .await + .expect("creating vesting schedule for the user!"); + + //send 1 coin + let coin_amount: u64 = 1_000_000; + + let coin = CosmosCoin { + denom: Denom::from_str(&denom).unwrap(), + amount: coin_amount.into(), + }; + + let send_coin_response = client + .send( + &AccountId::from_str(&*args.address).unwrap(), + vec![coin.into()], + "payment made :)", + None, + ) + .await + .unwrap(); + + info!("Vesting result: {:?}", res); + info!("Coin send result: {:?}", send_coin_response); +} diff --git a/common/commands/src/validator/vesting/mod.rs b/common/commands/src/validator/vesting/mod.rs new file mode 100644 index 0000000000..807ba08438 --- /dev/null +++ b/common/commands/src/validator/vesting/mod.rs @@ -0,0 +1,28 @@ +// Copyright 2021 - Nym Technologies SA +// SPDX-License-Identifier: Apache-2.0 + +use clap::{Args, Subcommand}; + +pub mod balance; +pub mod create_vesting_schedule; +pub mod query_vesting_schedule; +pub mod withdraw_vested; + +#[derive(Debug, Args)] +#[clap(args_conflicts_with_subcommands = true, subcommand_required = true)] +pub struct VestingSchedule { + #[clap(subcommand)] + pub command: Option, +} + +#[derive(Debug, Subcommand)] +pub enum VestingScheduleCommands { + /// Creates a vesting schedule + Create(crate::validator::vesting::create_vesting_schedule::Args), + /// Query for vesting schedule + Query(crate::validator::vesting::query_vesting_schedule::Args), + /// Get the amount that has vested and is free for withdrawal, delegation or bonding + VestedBalance(crate::validator::vesting::balance::Args), + /// Withdraw vested tokens (note: the available amount excludes anything delegated or bonded before or after vesting) + WithdrawVested(crate::validator::vesting::withdraw_vested::Args), +} diff --git a/common/commands/src/validator/vesting/query_vesting_schedule.rs b/common/commands/src/validator/vesting/query_vesting_schedule.rs new file mode 100644 index 0000000000..23118c1bf5 --- /dev/null +++ b/common/commands/src/validator/vesting/query_vesting_schedule.rs @@ -0,0 +1,149 @@ +// Copyright 2022 - Nym Technologies SA +// SPDX-License-Identifier: Apache-2.0 + +use clap::Parser; +use cosmrs::AccountId; +use cosmwasm_std::Coin as CosmWasmCoin; +use log::info; + +use validator_client::nymd::{Coin, VestingQueryClient}; + +use crate::context::SigningClient; +use crate::utils::show_error; +use crate::utils::{pretty_coin, pretty_cosmwasm_coin}; + +#[derive(Debug, Parser)] +pub struct Args { + #[clap(value_parser)] + #[clap(help = "Optionally, the account address to get the balance for")] + pub address: Option, +} + +pub async fn query(args: Args, client: SigningClient) { + let account_id = args.address.unwrap_or_else(|| client.address().clone()); + let vesting_address = account_id.to_string(); + let denom = client.current_chain_details().mix_denom.base.as_str(); + + info!( + "Getting vesting schedule information for {}...", + &vesting_address + ); + + let liquid_account_balance = client + .get_balance(&account_id, denom.to_string()) + .await + .unwrap_or(None) + .unwrap_or_else(|| Coin::new(0u128, denom)); + let original_vesting = client.original_vesting(&vesting_address).await; + let start_time = client.vesting_start_time(&vesting_address).await; + let end_time = client.vesting_end_time(&vesting_address).await; + let vested_coins = client.vested_coins(&vesting_address, None).await; + let spendable_coins = client.spendable_coins(&vesting_address, None).await; + let locked_coins = client.locked_coins(&vesting_address, None).await; + + // TODO: get better copy text for what these are + let vesting_coins = client.vesting_coins(&vesting_address, None).await; + let delegated_vesting = client.delegated_vesting(&vesting_address, None).await; + let delegated_free = client.delegated_free(&vesting_address, None).await; + + original_vesting.as_ref().map_or_else(show_error, |res| { + println!( + "Amount: {} ({})", + pretty_cosmwasm_coin(&res.amount), + res.amount + ); + println!("No of periods: {}", res.number_of_periods); + println!( + "Duration each: {}", + time::Duration::seconds(res.period_duration as i64) + ); + }); + + start_time.as_ref().map_or_else(show_error, |res| { + println!( + "Start date: {}", + time::OffsetDateTime::from_unix_timestamp(res.seconds() as i64) + .expect("unable to parse vesting start timestamp") + .date() + ); + }); + + end_time.map_or_else(show_error, |res| { + println!( + "End date: {}", + time::OffsetDateTime::from_unix_timestamp(res.seconds() as i64) + .expect("unable to parse vesting end timestamp") + .date() + ); + }); + + vested_coins.map_or_else(show_error, |res| { + println!("Vested balance: {} ({})", pretty_coin(&res), res); + }); + + if let Ok(res) = original_vesting { + if let Ok(start) = start_time { + let amount_in_each_period = res.amount.amount.u128() / res.number_of_periods as u128; + let coin_in_each_period = CosmWasmCoin::new(amount_in_each_period, denom); + println!(); + println!("Vesting schedule:"); + for period in 1..(res.number_of_periods as u64 + 1) { + let date = time::OffsetDateTime::from_unix_timestamp( + (start.seconds() + period * res.period_duration) as i64, + ) + .expect("unable to parse vesting start timestamp") + .date(); + let amount_in_vested = + period as u128 * res.amount.amount.u128() / res.number_of_periods as u128; + let coin_in_vested = CosmWasmCoin::new(amount_in_vested, denom); + println!( + "{}. {} {} => {}", + period, + date, + pretty_cosmwasm_coin(&coin_in_each_period), + pretty_cosmwasm_coin(&coin_in_vested), + ); + } + } + } + + spendable_coins.map_or_else(show_error, |res| { + println!(); + println!("This account has the following vested tokens available either to be withdrawn to the main account, or to be delegated:"); + println!("Spendable coins: {} ({})", pretty_coin(&res), res); + }); + + locked_coins.map_or_else(show_error, |res| { + println!(); + if res.amount > 0 { + println!("This account has delegated more than the current cap, so the following balance is unavailable for bonding or delegation:"); + println!("Locked balance: {} ({})", pretty_coin(&res), res); + } else { + println!("This account is not capped and can use the spendable balance for bonding or delegations:"); + println!("Locked balance: {} ({})", pretty_coin(&res), res); + } + }); + + println!(); + println!("The following are shown for information (more help text will follow soon):"); + vesting_coins.map_or_else(show_error, |res| { + println!("Vesting coins: {} ({})", pretty_coin(&res), res); + }); + delegated_vesting.map_or_else(show_error, |res| { + println!("Delegated vesting: {} ({})", pretty_coin(&res), res); + }); + delegated_free.map_or_else(show_error, |res| { + println!("Delegation free: {} ({})", pretty_coin(&res), res); + }); + + println!(); + println!( + "The main account {} also has a regular balance of:", + &account_id + ); + println!( + "{} ({})", + pretty_coin(&liquid_account_balance), + &liquid_account_balance + ); +} diff --git a/common/commands/src/validator/vesting/withdraw_vested.rs b/common/commands/src/validator/vesting/withdraw_vested.rs new file mode 100644 index 0000000000..972c5290d9 --- /dev/null +++ b/common/commands/src/validator/vesting/withdraw_vested.rs @@ -0,0 +1,112 @@ +// Copyright 2022 - Nym Technologies SA +// SPDX-License-Identifier: Apache-2.0 + +use clap::Parser; +use log::info; + +use validator_client::nymd::{Coin, VestingQueryClient, VestingSigningClient}; + +use crate::context::SigningClient; +use crate::utils::show_error; +use crate::utils::{pretty_coin, pretty_cosmwasm_coin}; + +#[derive(Debug, Parser)] +pub struct Args { + #[clap(value_parser)] + #[clap(help = "Amount to transfer in micro denomination (e.g. unym or unyx)")] + pub amount: u128, +} + +pub async fn execute(args: Args, client: SigningClient) { + let account_id = client.address(); + let vesting_address = account_id.to_string(); + let denom = client.current_chain_details().mix_denom.base.as_str(); + + info!( + "Getting vesting schedule information for {}...", + &vesting_address + ); + + let original_vesting = client.original_vesting(&vesting_address).await; + + match original_vesting { + Ok(res) => { + let spendable_coins = client + .spendable_coins(&vesting_address, None) + .await + .unwrap_or_else(|_| Coin::new(0u128, denom)); + let liquid_account_balance = client + .get_balance(account_id, denom.to_string()) + .await + .unwrap_or(None) + .unwrap_or_else(|| Coin::new(0u128, denom)); + + println!( + "Account {} has\n{} vested with {} available to be withdrawn to the main account (balance {})", + &account_id, + pretty_cosmwasm_coin(&res.amount), + pretty_coin(&spendable_coins), + pretty_coin(&liquid_account_balance), + ); + println!(); + + // execute withdraw + + let amount = Coin { + amount: args.amount, + denom: denom.to_string(), + }; + + info!( + "Withdrawing {} ({}) from {}...", + pretty_coin(&amount), + &amount, + &account_id + ); + + match client.withdraw_vested_coins(amount, None).await { + Ok(res) => { + println!(); + println!("SUCCESS ✅"); + println!( + "Nodesguru: https://nym.explorers.guru/transaction/{}", + &res.transaction_hash + ); + println!( + "Mintscan: https://www.mintscan.io/nyx/txs/{}", + &res.transaction_hash + ); + println!("Transaction hash: {}", &res.transaction_hash); + println!("Gas used: {}", &res.gas_info.gas_used); + println!(); + } + Err(e) => show_error(e), + } + + // query for balances again + let res = client + .original_vesting(&vesting_address) + .await + .expect("vesting account does not exist"); + let spendable_coins = client + .spendable_coins(&vesting_address, None) + .await + .unwrap_or_else(|_| Coin::new(0u128, denom)); + + let liquid_account_balance = client + .get_balance(account_id, denom.to_string()) + .await + .unwrap_or(None) + .unwrap_or_else(|| Coin::new(0u128, denom)); + + println!( + "After withdrawal, account {} has\n{} vested with {} available to be withdrawn to the main account (balance {})", + &account_id, + pretty_cosmwasm_coin(&res.amount), + pretty_coin(&spendable_coins), + pretty_coin(&liquid_account_balance), + ); + } + Err(e) => show_error(e), + } +} diff --git a/common/network-defaults/envs/mainnet.env b/common/network-defaults/envs/mainnet.env new file mode 100644 index 0000000000..dce1c3c9c0 --- /dev/null +++ b/common/network-defaults/envs/mainnet.env @@ -0,0 +1,20 @@ +CONFIGURED=true + +RUST_LOG=info +RUST_BACKTRACE=1 + +BECH32_PREFIX=n +MIX_DENOM=unym +MIX_DENOM_DISPLAY=nym +STAKE_DENOM=unyx +STAKE_DENOM_DISPLAY=nyx +DENOMS_EXPONENT=6 +MIXNET_CONTRACT_ADDRESS=n14hj2tavq8fpesdwxxcu44rty3hh90vhujrvcmstl4zr3txmfvw9sjyvg3g +VESTING_CONTRACT_ADDRESS=n1nc5tatafv6eyq7llkr2gv50ff9e22mnf70qgjlv737ktmt4eswrq73f2nw +BANDWIDTH_CLAIM_CONTRACT_ADDRESS=n19lc9u84cz0yz3fww5283nucc9yvr8gsjmgeul0 +COCONUT_BANDWIDTH_CONTRACT_ADDRESS=n19lc9u84cz0yz3fww5283nucc9yvr8gsjmgeul0 +MULTISIG_CONTRACT_ADDRESS=n19lc9u84cz0yz3fww5283nucc9yvr8gsjmgeul0 +REWARDING_VALIDATOR_ADDRESS=n10yyd98e2tuwu0f7ypz9dy3hhjw7v772q6287gy +STATISTICS_SERVICE_DOMAIN_ADDRESS="http://127.0.0.1:8090" +NYMD_VALIDATOR="https://rpc.nyx.nodes.guru/" +API_VALIDATOR="https://validator.nymtech.net/api/" diff --git a/common/network-defaults/envs/qa.env b/common/network-defaults/envs/qa.env new file mode 100644 index 0000000000..842fb54c4d --- /dev/null +++ b/common/network-defaults/envs/qa.env @@ -0,0 +1,20 @@ +CONFIGURED=true + +RUST_LOG=info +RUST_BACKTRACE=1 + +BECH32_PREFIX=n +MIX_DENOM=unym +MIX_DENOM_DISPLAY=nym +STAKE_DENOM=unyx +STAKE_DENOM_DISPLAY=nyx +DENOMS_EXPONENT=6 +MIXNET_CONTRACT_ADDRESS=n1suhgf5svhu4usrurvxzlgn54ksxmn8gljarjtxqnapv8kjnp4nrsd3qaep +VESTING_CONTRACT_ADDRESS=n1xr3rq8yvd7qplsw5yx90ftsr2zdhg4e9z60h5duusgxpv72hud3sjkxkav +BANDWIDTH_CLAIM_CONTRACT_ADDRESS=n19lc9u84cz0yz3fww5283nucc9yvr8gsjmgeul0 +COCONUT_BANDWIDTH_CONTRACT_ADDRESS=n1ghd753shjuwexxywmgs4xz7x2q732vcn7ty4yw +MULTISIG_CONTRACT_ADDRESS=n17p9rzwnnfxcjp32un9ug7yhhzgtkhvl988qccs +REWARDING_VALIDATOR_ADDRESS=n1tfzd4qz3a45u8p4mr5zmzv66457uwjgcl05jdq +STATISTICS_SERVICE_DOMAIN_ADDRESS="http://0.0.0.0" +NYMD_VALIDATOR="https://qa-validator.nymtech.net" +API_VALIDATOR="https://qa-validator-api.nymtech.net/api" diff --git a/examples/README.md b/examples/README.md new file mode 100644 index 0000000000..00ba21ad4a --- /dev/null +++ b/examples/README.md @@ -0,0 +1,9 @@ +# Examples + +This directory contains examples of using the libraries in this repo: + +### CLI + +#### CLI Commands + +- [Use an account public key to verify a signature](./cli/commands/verify-signature) \ No newline at end of file diff --git a/tools/Cargo.lock b/examples/cli/commands/verify-signature/Cargo.lock similarity index 82% rename from tools/Cargo.lock rename to examples/cli/commands/verify-signature/Cargo.lock index d32be85ea2..176da87bee 100644 --- a/tools/Cargo.lock +++ b/examples/cli/commands/verify-signature/Cargo.lock @@ -16,15 +16,15 @@ checksum = "f26201604c87b1e01bd3d98f8d5d9a8fcbb815e8cedb41ffccbeb4bf593a35fe" [[package]] name = "anyhow" -version = "1.0.57" +version = "1.0.62" source = "registry+https://github.com/rust-lang/crates.io-index" -checksum = "08f9b8508dccb7687a1d6c4ce66b2b0ecef467c94667de27d8d7fe1f8d2a9cdc" +checksum = "1485d4d2cc45e7b201ee3767015c96faa5904387c9d87c6efdd0fb511f12d305" [[package]] name = "async-trait" -version = "0.1.53" +version = "0.1.57" source = "registry+https://github.com/rust-lang/crates.io-index" -checksum = "ed6aa3524a2dfcf9fe180c51eae2b58738348d819517ceadf95789c51fff7600" +checksum = "76464446b8bc32758d7e88ee1a804d9914cd9b1cb264c029899680b0be29826f" dependencies = [ "proc-macro2", "quote", @@ -59,9 +59,9 @@ checksum = "d468802bab17cbc0cc575e9b053f41e72aa36bfa6b7f55e3529ffa43161b97fa" [[package]] name = "az" -version = "1.2.0" +version = "1.2.1" source = "registry+https://github.com/rust-lang/crates.io-index" -checksum = "f771a5d1f5503f7f4279a30f3643d3421ba149848b89ecaaec0ea2acf04a5ac4" +checksum = "7b7e4c2464d97fe331d41de9d5db0def0a96f4d823b8b32a2efd503578988973" [[package]] name = "base16ct" @@ -77,9 +77,9 @@ checksum = "904dfeac50f3cdaba28fc6f57fdcddb75f49ed61346676a78c4ffe55877802fd" [[package]] name = "base64ct" -version = "1.5.0" +version = "1.5.2" source = "registry+https://github.com/rust-lang/crates.io-index" -checksum = "dea908e7347a8c64e378c17e30ef880ad73e3b4498346b055c2c00ea342f3179" +checksum = "ea2b2456fd614d856680dcd9fcc660a51a820fa09daef2e49772b56a193c8474" [[package]] name = "bip32" @@ -124,26 +124,14 @@ version = "1.3.2" source = "registry+https://github.com/rust-lang/crates.io-index" checksum = "bef38d45163c2f1dde094a7dfd33ccf595c92905c8f8f4fdc18d06fb1037718a" -[[package]] -name = "block-buffer" -version = "0.7.3" -source = "registry+https://github.com/rust-lang/crates.io-index" -checksum = "c0940dc441f31689269e10ac70eb1002a3a1d3ad1390e030043662eb7fe4688b" -dependencies = [ - "block-padding 0.1.5", - "byte-tools", - "byteorder", - "generic-array 0.12.4", -] - [[package]] name = "block-buffer" version = "0.9.0" source = "registry+https://github.com/rust-lang/crates.io-index" checksum = "4152116fd6e9dadb291ae18fc1ec3575ed6d84c29642d97890f4b4a3417297e4" dependencies = [ - "block-padding 0.2.1", - "generic-array 0.14.5", + "block-padding", + "generic-array", ] [[package]] @@ -152,16 +140,7 @@ version = "0.10.2" source = "registry+https://github.com/rust-lang/crates.io-index" checksum = "0bf7fe51849ea569fd452f37822f606a5cabb684dc918707a0193fd4664ff324" dependencies = [ - "generic-array 0.14.5", -] - -[[package]] -name = "block-padding" -version = "0.1.5" -source = "registry+https://github.com/rust-lang/crates.io-index" -checksum = "fa79dedbb091f449f1f39e53edf88d5dbe95f895dae6135a8d7b881fb5af73f5" -dependencies = [ - "byte-tools", + "generic-array", ] [[package]] @@ -195,21 +174,15 @@ dependencies = [ [[package]] name = "bumpalo" -version = "3.9.1" +version = "3.11.0" source = "registry+https://github.com/rust-lang/crates.io-index" -checksum = "a4a45a46ab1f2412e53d3a0ade76ffad2025804294569aae387231a0cd6e0899" - -[[package]] -name = "byte-tools" -version = "0.3.1" -source = "registry+https://github.com/rust-lang/crates.io-index" -checksum = "e3b5ca7a04898ad4bcd41c90c5285445ff5b791899bb1b0abdd2a2aa791211d7" +checksum = "c1ad822118d20d2c234f427000d5acc36eabe1e29a348c89b63dd60b13f28e5d" [[package]] name = "bytemuck" -version = "1.9.1" +version = "1.12.1" source = "registry+https://github.com/rust-lang/crates.io-index" -checksum = "cdead85bdec19c194affaeeb670c0e41fe23de31459efd1c174d049269cf02cc" +checksum = "2f5715e491b5a1598fc2bef5a606847b5dc1d48ea625bd3c02c00de8285591da" [[package]] name = "byteorder" @@ -219,9 +192,9 @@ checksum = "14c189c53d098945499cdfa7ecc63567cf3886b3332b312a5b4585d8d3a6a610" [[package]] name = "bytes" -version = "1.1.0" +version = "1.2.1" source = "registry+https://github.com/rust-lang/crates.io-index" -checksum = "c4872d67bab6358e59559027aa3b9157c53d9358c51423c17554809a8858e0f8" +checksum = "ec8a7b6a70fde80372154c65702f00a0f56f3e1c36abbc6c440484be248856db" [[package]] name = "cc" @@ -235,6 +208,45 @@ version = "1.0.0" source = "registry+https://github.com/rust-lang/crates.io-index" checksum = "baf1de4339761588bc0619e3cbc0120ee582ebb74b53b4efbf79117bd2da40fd" +[[package]] +name = "clap" +version = "3.2.17" +source = "registry+https://github.com/rust-lang/crates.io-index" +checksum = "29e724a68d9319343bb3328c9cc2dfde263f4b3142ee1059a9980580171c954b" +dependencies = [ + "atty", + "bitflags", + "clap_derive", + "clap_lex", + "indexmap", + "once_cell", + "strsim", + "termcolor", + "textwrap", +] + +[[package]] +name = "clap_derive" +version = "3.2.17" +source = "registry+https://github.com/rust-lang/crates.io-index" +checksum = "13547f7012c01ab4a0e8f8967730ada8f9fdf419e8b6c792788f39cf4e46eefa" +dependencies = [ + "heck", + "proc-macro-error", + "proc-macro2", + "quote", + "syn", +] + +[[package]] +name = "clap_lex" +version = "0.2.4" +source = "registry+https://github.com/rust-lang/crates.io-index" +checksum = "2850f2f5a82cbf437dd5af4d49848fbdfc27c157c3d010345776f952765261c5" +dependencies = [ + "os_str_bytes", +] + [[package]] name = "cloudabi" version = "0.0.3" @@ -244,9 +256,21 @@ dependencies = [ "bitflags", ] +[[package]] +name = "coconut-bandwidth-contract-common" +version = "0.1.0" +source = "git+https://github.com/nymtech/nym?branch=feature/nym-cli#4045541e461898c37872a9b75822d3ba84b9f98c" +dependencies = [ + "cosmwasm-std", + "multisig-contract-common", + "schemars", + "serde", +] + [[package]] name = "coconut-interface" version = "0.1.0" +source = "git+https://github.com/nymtech/nym?branch=feature/nym-cli#4045541e461898c37872a9b75822d3ba84b9f98c" dependencies = [ "bs58", "getset", @@ -269,6 +293,7 @@ dependencies = [ [[package]] name = "config" version = "0.1.0" +source = "git+https://github.com/nymtech/nym?branch=feature/nym-cli#4045541e461898c37872a9b75822d3ba84b9f98c" dependencies = [ "cfg-if", "handlebars", @@ -289,6 +314,7 @@ checksum = "e4c78c047431fee22c1a7bb92e00ad095a02a983affe4d8a72e2a2c62c1b94f3" [[package]] name = "contracts-common" version = "0.1.0" +source = "git+https://github.com/nymtech/nym?branch=feature/nym-cli#4045541e461898c37872a9b75822d3ba84b9f98c" dependencies = [ "cosmwasm-std", ] @@ -311,8 +337,8 @@ checksum = "5827cebf4670468b8772dd191856768aedcb1b0278a04f989f7766351917b9dc" [[package]] name = "cosmos-sdk-proto" -version = "0.9.0" -source = "git+https://github.com/nymtech/cosmos-rust?branch=bugfix/account-id-length-validation#911fbe1236cfed591783ccef01018f7ccc97c496" +version = "0.12.3" +source = "git+https://github.com/neacsu/cosmos-rust?branch=neacsu/feegrant_support#f63ded63ec13e753ebe8bdafe9dc503df265d67d" dependencies = [ "prost", "prost-types", @@ -321,14 +347,14 @@ dependencies = [ [[package]] name = "cosmrs" -version = "0.4.1" -source = "git+https://github.com/nymtech/cosmos-rust?branch=bugfix/account-id-length-validation#911fbe1236cfed591783ccef01018f7ccc97c496" +version = "0.7.1" +source = "git+https://github.com/neacsu/cosmos-rust?branch=neacsu/feegrant_support#f63ded63ec13e753ebe8bdafe9dc503df265d67d" dependencies = [ "bip32", "cosmos-sdk-proto", "ecdsa", "eyre", - "getrandom 0.2.6", + "getrandom 0.2.7", "k256", "prost", "prost-types", @@ -382,9 +408,9 @@ dependencies = [ [[package]] name = "cpufeatures" -version = "0.2.2" +version = "0.2.4" source = "registry+https://github.com/rust-lang/crates.io-index" -checksum = "59a6001667ab124aebae2a495118e11d30984c3a653e99d86d58971708cf5e4b" +checksum = "dc948ebb96241bb40ab73effeb80d9f93afaad49359d159a5e61be51619fe813" dependencies = [ "libc", ] @@ -410,7 +436,7 @@ version = "0.3.2" source = "registry+https://github.com/rust-lang/crates.io-index" checksum = "03c6a1d5fa1de37e071642dfa44ec552ca5b299adb128fab16138e24b548fd21" dependencies = [ - "generic-array 0.14.5", + "generic-array", "rand_core 0.6.3", "subtle", "zeroize", @@ -418,11 +444,11 @@ dependencies = [ [[package]] name = "crypto-common" -version = "0.1.3" +version = "0.1.6" source = "registry+https://github.com/rust-lang/crates.io-index" -checksum = "57952ca27b5e3606ff4dd79b0020231aaf9d6aa76dc05fd30137538c50bd3ce8" +checksum = "1bfb12502f3fc46cca1bb51ac28df9d618d813cdc3d2f25b9fe775a34af26bb3" dependencies = [ - "generic-array 0.14.5", + "generic-array", "typenum", ] @@ -432,7 +458,7 @@ version = "0.11.1" source = "registry+https://github.com/rust-lang/crates.io-index" checksum = "b1d1a86f49236c215f271d40892d5fc950490551400b02ef360692c29815c714" dependencies = [ - "generic-array 0.14.5", + "generic-array", "subtle", ] @@ -447,9 +473,9 @@ dependencies = [ [[package]] name = "curve25519-dalek" -version = "3.2.0" +version = "3.2.1" source = "registry+https://github.com/rust-lang/crates.io-index" -checksum = "0b9fdf9972b2bd6af2d913799d9ebc165ea4d2e65878e329d9c6b372c4491b61" +checksum = "90f9d052967f590a76e62eb387bd0bbb1b000182c3cefe5364db6b7211651bc0" dependencies = [ "byteorder", "digest 0.9.0", @@ -460,15 +486,51 @@ dependencies = [ [[package]] name = "cw-storage-plus" -version = "0.13.2" +version = "0.13.4" source = "registry+https://github.com/rust-lang/crates.io-index" -checksum = "9336ecef1e19d56cf6e3e932475fc6a3dee35eec5a386e07917a1d1ba6bb0e35" +checksum = "648b1507290bbc03a8d88463d7cd9b04b1fa0155e5eef366c4fa052b9caaac7a" dependencies = [ "cosmwasm-std", "schemars", "serde", ] +[[package]] +name = "cw-utils" +version = "0.13.4" +source = "registry+https://github.com/rust-lang/crates.io-index" +checksum = "9dbaecb78c8e8abfd6b4258c7f4fbeb5c49a5e45ee4d910d3240ee8e1d714e1b" +dependencies = [ + "cosmwasm-std", + "schemars", + "serde", + "thiserror", +] + +[[package]] +name = "cw3" +version = "0.13.4" +source = "registry+https://github.com/rust-lang/crates.io-index" +checksum = "fe19462a7f644ba60c19d3443cb90d00c50d9b6b3b0a3a7fca93df8261af979b" +dependencies = [ + "cosmwasm-std", + "cw-utils", + "schemars", + "serde", +] + +[[package]] +name = "cw4" +version = "0.13.4" +source = "registry+https://github.com/rust-lang/crates.io-index" +checksum = "0acc3549d5ce11c6901b3a676f2e2628684722197054d97cd0101ea174ed5cbd" +dependencies = [ + "cosmwasm-std", + "cw-storage-plus", + "schemars", + "serde", +] + [[package]] name = "der" version = "0.5.1" @@ -478,22 +540,13 @@ dependencies = [ "const-oid", ] -[[package]] -name = "digest" -version = "0.8.1" -source = "registry+https://github.com/rust-lang/crates.io-index" -checksum = "f3d0c8c8752312f9713efd397ff63acb9f85585afbf179282e720e7704954dd5" -dependencies = [ - "generic-array 0.12.4", -] - [[package]] name = "digest" version = "0.9.0" source = "registry+https://github.com/rust-lang/crates.io-index" checksum = "d3dd60d1080a57a05ab032377049e0591415d2b31afd7028356dbf3cc6dcb066" dependencies = [ - "generic-array 0.14.5", + "generic-array", ] [[package]] @@ -507,10 +560,16 @@ dependencies = [ ] [[package]] -name = "dyn-clone" -version = "1.0.5" +name = "dotenv" +version = "0.15.0" source = "registry+https://github.com/rust-lang/crates.io-index" -checksum = "21e50f3adc76d6a43f5ed73b698a87d0760ca74617f60f7c3b879003536fdd28" +checksum = "77c90badedccf4105eca100756a0b1289e191f6fcbdadd3cee1d2f614f97da8f" + +[[package]] +name = "dyn-clone" +version = "1.0.9" +source = "registry+https://github.com/rust-lang/crates.io-index" +checksum = "4f94fa09c2aeea5b8839e414b7b841bf429fd25b9c522116ac97ee87856d88b2" [[package]] name = "ecdsa" @@ -562,9 +621,9 @@ dependencies = [ [[package]] name = "either" -version = "1.6.1" +version = "1.8.0" source = "registry+https://github.com/rust-lang/crates.io-index" -checksum = "e78d4f1cc4ae33bbfc157ed5d5a5ef3bc29227303d595861deb238fcec4e9457" +checksum = "90e5c1c8368803113bf0c9584fc495a58b86dc8a29edbf8fe877d21d9507e797" [[package]] name = "elliptic-curve" @@ -576,7 +635,7 @@ dependencies = [ "crypto-bigint", "der", "ff 0.11.1", - "generic-array 0.14.5", + "generic-array", "group 0.11.0", "rand_core 0.6.3", "sec1", @@ -593,6 +652,22 @@ dependencies = [ "cfg-if", ] +[[package]] +name = "example-verify-signature" +version = "0.1.0" +dependencies = [ + "nym-cli-commands", +] + +[[package]] +name = "execute" +version = "0.1.0" +source = "git+https://github.com/nymtech/nym?branch=feature/nym-cli#4045541e461898c37872a9b75822d3ba84b9f98c" +dependencies = [ + "quote", + "syn", +] + [[package]] name = "eyre" version = "0.6.8" @@ -603,17 +678,11 @@ dependencies = [ "once_cell", ] -[[package]] -name = "fake-simd" -version = "0.1.2" -source = "registry+https://github.com/rust-lang/crates.io-index" -checksum = "e88a8acf291dafb59c2d96e8f59828f3838bb1a70398823ade51a84de6a6deed" - [[package]] name = "fastrand" -version = "1.7.0" +version = "1.8.0" source = "registry+https://github.com/rust-lang/crates.io-index" -checksum = "c3fcf0cee53519c866c09b5de1f6c56ff9d647101f81c1964fa632e148896cdf" +checksum = "a7a407cfaa3385c4ae6b23e84623d48c2798d06e3e6a1878f7f59f17b3f86499" dependencies = [ "instant", ] @@ -640,9 +709,9 @@ dependencies = [ [[package]] name = "fixed" -version = "1.15.0" +version = "1.18.0" source = "registry+https://github.com/rust-lang/crates.io-index" -checksum = "36a65312835c1097a0c926ff3702df965285fadc33d948b87397ff8961bad881" +checksum = "ec8c4fbf8cd36f2a96740c31320902abbf0acbd733049b758707d842490c98c4" dependencies = [ "az", "bytemuck", @@ -653,13 +722,11 @@ dependencies = [ [[package]] name = "flate2" -version = "1.0.23" +version = "1.0.24" source = "registry+https://github.com/rust-lang/crates.io-index" -checksum = "b39522e96686d38f4bc984b9198e3a0613264abaebaff2c5c918bfa6b6da09af" +checksum = "f82b0f4c27ad9f8bfd1f3208d882da2b09c301bc1c828fd3a00d0216d2fbbff6" dependencies = [ - "cfg-if", "crc32fast", - "libc", "miniz_oxide", ] @@ -718,9 +785,9 @@ checksum = "a06f77d526c1a601b7c4cdd98f54b5eaabffc14d5f2f0296febdc7f357c6d3ba" [[package]] name = "futures" -version = "0.3.21" +version = "0.3.23" source = "registry+https://github.com/rust-lang/crates.io-index" -checksum = "f73fe65f54d1e12b726f517d3e2135ca3125a437b6d998caf1962961f7172d9e" +checksum = "ab30e97ab6aacfe635fad58f22c2bb06c8b685f7421eb1e064a729e2a5f481fa" dependencies = [ "futures-channel", "futures-core", @@ -733,9 +800,9 @@ dependencies = [ [[package]] name = "futures-channel" -version = "0.3.21" +version = "0.3.23" source = "registry+https://github.com/rust-lang/crates.io-index" -checksum = "c3083ce4b914124575708913bca19bfe887522d6e2e6d0952943f5eac4a74010" +checksum = "2bfc52cbddcfd745bf1740338492bb0bd83d76c67b445f91c5fb29fae29ecaa1" dependencies = [ "futures-core", "futures-sink", @@ -743,15 +810,15 @@ dependencies = [ [[package]] name = "futures-core" -version = "0.3.21" +version = "0.3.23" source = "registry+https://github.com/rust-lang/crates.io-index" -checksum = "0c09fd04b7e4073ac7156a9539b57a484a8ea920f79c7c675d05d289ab6110d3" +checksum = "d2acedae88d38235936c3922476b10fced7b2b68136f5e3c03c2d5be348a1115" [[package]] name = "futures-executor" -version = "0.3.21" +version = "0.3.23" source = "registry+https://github.com/rust-lang/crates.io-index" -checksum = "9420b90cfa29e327d0429f19be13e7ddb68fa1cccb09d65e5706b8c7a749b8a6" +checksum = "1d11aa21b5b587a64682c0094c2bdd4df0076c5324961a40cc3abd7f37930528" dependencies = [ "futures-core", "futures-task", @@ -760,15 +827,15 @@ dependencies = [ [[package]] name = "futures-io" -version = "0.3.21" +version = "0.3.23" source = "registry+https://github.com/rust-lang/crates.io-index" -checksum = "fc4045962a5a5e935ee2fdedaa4e08284547402885ab326734432bed5d12966b" +checksum = "93a66fc6d035a26a3ae255a6d2bca35eda63ae4c5512bef54449113f7a1228e5" [[package]] name = "futures-macro" -version = "0.3.21" +version = "0.3.23" source = "registry+https://github.com/rust-lang/crates.io-index" -checksum = "33c1e13800337f4d4d7a316bf45a567dbcb6ffe087f16424852d97e97a91f512" +checksum = "0db9cce532b0eae2ccf2766ab246f114b56b9cf6d445e00c2549fbc100ca045d" dependencies = [ "proc-macro2", "quote", @@ -777,21 +844,21 @@ dependencies = [ [[package]] name = "futures-sink" -version = "0.3.21" +version = "0.3.23" source = "registry+https://github.com/rust-lang/crates.io-index" -checksum = "21163e139fa306126e6eedaf49ecdb4588f939600f0b1e770f4205ee4b7fa868" +checksum = "ca0bae1fe9752cf7fd9b0064c674ae63f97b37bc714d745cbde0afb7ec4e6765" [[package]] name = "futures-task" -version = "0.3.21" +version = "0.3.23" source = "registry+https://github.com/rust-lang/crates.io-index" -checksum = "57c66a976bf5909d801bbef33416c41372779507e7a6b3a5e25e4749c58f776a" +checksum = "842fc63b931f4056a24d59de13fb1272134ce261816e063e634ad0c15cdc5306" [[package]] name = "futures-util" -version = "0.3.21" +version = "0.3.23" source = "registry+https://github.com/rust-lang/crates.io-index" -checksum = "d8b7abd5d659d9b90c8cba917f6ec750a74e2dc23902ef9cd4cc8c8b22e6036a" +checksum = "f0828a5471e340229c11c77ca80017937ce3c58cb788a17e5f1c2d5c485a9577" dependencies = [ "futures-channel", "futures-core", @@ -807,18 +874,9 @@ dependencies = [ [[package]] name = "generic-array" -version = "0.12.4" +version = "0.14.6" source = "registry+https://github.com/rust-lang/crates.io-index" -checksum = "ffdf9f34f1447443d37393cc6c2b8313aebddcd96906caf34e54c68d8e57d7bd" -dependencies = [ - "typenum", -] - -[[package]] -name = "generic-array" -version = "0.14.5" -source = "registry+https://github.com/rust-lang/crates.io-index" -checksum = "fd48d33ec7f05fbfa152300fdad764757cbded343c1aa1cff2fbaf4134851803" +checksum = "bff49e947297f3312447abdca79f45f4738097cc82b06e72054d2223f601f1b9" dependencies = [ "typenum", "version_check", @@ -837,14 +895,14 @@ dependencies = [ [[package]] name = "getrandom" -version = "0.2.6" +version = "0.2.7" source = "registry+https://github.com/rust-lang/crates.io-index" -checksum = "9be70c98951c83b8d2f8f60d7065fa6d5146873094452a1008da8c2f1e4205ad" +checksum = "4eb1a864a501629691edf6c15a593b7a51eebaa1e8468e9ddc623de7c9b58ec6" dependencies = [ "cfg-if", "js-sys", "libc", - "wasi 0.10.2+wasi-snapshot-preview1", + "wasi 0.11.0+wasi-snapshot-preview1", "wasm-bindgen", ] @@ -885,9 +943,9 @@ dependencies = [ [[package]] name = "h2" -version = "0.3.13" +version = "0.3.14" source = "registry+https://github.com/rust-lang/crates.io-index" -checksum = "37a82c6d637fc9515a4694bbf1cb2457b79d81ce52b3108bdeea58b07dd34a57" +checksum = "5ca32592cf21ac7ccab1825cd87f6c9b3d9022c44d086172ed0966bec8af30be" dependencies = [ "bytes", "fnv", @@ -904,9 +962,12 @@ dependencies = [ [[package]] name = "half" -version = "1.8.2" +version = "2.1.0" source = "registry+https://github.com/rust-lang/crates.io-index" -checksum = "eabb4a44450da02c90444cf74558da904edde8fb4e9035a9a6a4e15445af0bd7" +checksum = "ad6a9459c9c30b177b925162351f97e7d967c7ea8bab3b8352805327daf45554" +dependencies = [ + "crunchy", +] [[package]] name = "handlebars" @@ -924,9 +985,9 @@ dependencies = [ [[package]] name = "hashbrown" -version = "0.11.2" +version = "0.12.3" source = "registry+https://github.com/rust-lang/crates.io-index" -checksum = "ab5ef0d4909ef3724cc8cce6ccc8572c5c817592e9285f5464f8e86f8bd3726e" +checksum = "8a9ee70c43aaf417c914396645a0fa852624801b24ebb7ae78fe8272889ac888" [[package]] name = "headers" @@ -941,7 +1002,7 @@ dependencies = [ "http", "httpdate", "mime", - "sha-1 0.10.0", + "sha-1", ] [[package]] @@ -955,12 +1016,9 @@ dependencies = [ [[package]] name = "heck" -version = "0.3.3" +version = "0.4.0" source = "registry+https://github.com/rust-lang/crates.io-index" -checksum = "6d621efb26863f0e9924c6ac577e8275e5e6b77455db64ffa6c65c904e9e132c" -dependencies = [ - "unicode-segmentation", -] +checksum = "2540771e65fc8cb83cd6e8a237f70c319bd5c29f78ed1084ba5d50eeac86f7f9" [[package]] name = "hermit-abi" @@ -995,9 +1053,9 @@ dependencies = [ [[package]] name = "http" -version = "0.2.7" +version = "0.2.8" source = "registry+https://github.com/rust-lang/crates.io-index" -checksum = "ff8670570af52249509a86f5e3e18a08c60b177071826898fde8997cf5f6bfbb" +checksum = "75f43d41e26995c17e71ee126451dd3941010b0514a81a9d11f3b341debc2399" dependencies = [ "bytes", "fnv", @@ -1045,9 +1103,9 @@ dependencies = [ [[package]] name = "hyper" -version = "0.14.18" +version = "0.14.20" source = "registry+https://github.com/rust-lang/crates.io-index" -checksum = "b26ae0a80afebe130861d90abf98e3814a4f28a4c6ffeb5ab8ebb2be311e0ef2" +checksum = "02c929dc5c39e335a03c405292728118860721b10190d98c2a0f0efd5baafbac" dependencies = [ "bytes", "futures-channel", @@ -1078,11 +1136,12 @@ dependencies = [ "headers", "http", "hyper", - "hyper-tls", - "native-tls", + "hyper-rustls", + "rustls-native-certs", "tokio", - "tokio-native-tls", + "tokio-rustls", "tower-service", + "webpki", ] [[package]] @@ -1135,9 +1194,9 @@ checksum = "ce23b50ad8242c51a442f3ff322d56b02f08852c77e4c0b4d3fd684abc89c683" [[package]] name = "indexmap" -version = "1.8.1" +version = "1.9.1" source = "registry+https://github.com/rust-lang/crates.io-index" -checksum = "0f647032dfaa1f8b6dc29bd3edb7bbef4861b8b8007ebb118d6db284fd59f6ee" +checksum = "10a35a97730320ffe8e2d410b5d3b69279b98d2c14bdb8b70ea89ecf7888d41e" dependencies = [ "autocfg 1.1.0", "hashbrown", @@ -1170,15 +1229,15 @@ dependencies = [ [[package]] name = "itoa" -version = "1.0.2" +version = "1.0.3" source = "registry+https://github.com/rust-lang/crates.io-index" -checksum = "112c678d4050afce233f4f2852bb2eb519230b3cf12f33585275537d7e41578d" +checksum = "6c8af84674fe1f223a982c933a0ee1086ac4d4052aa0fb8060c12c6ad838e754" [[package]] name = "js-sys" -version = "0.3.57" +version = "0.3.59" source = "registry+https://github.com/rust-lang/crates.io-index" -checksum = "671a26f820db17c2a2750743f1dd03bafd15b98c9f30c7c2628c024c05d73397" +checksum = "258451ab10b34f8af53416d1fdab72c22e805f0c92a1136d59470ec0b11138b2" dependencies = [ "wasm-bindgen", ] @@ -1211,9 +1270,9 @@ checksum = "e2abad23fbc42b3700f2f279844dc832adb2b2eb069b2df918f455c4e18cc646" [[package]] name = "libc" -version = "0.2.126" +version = "0.2.132" source = "registry+https://github.com/rust-lang/crates.io-index" -checksum = "349d5a591cd28b49e1d1037471617a32ddcda5731b99419008085f72d5a53836" +checksum = "8371e4e5341c3a96db127eb2465ac681ced4c433e01dd0e938adbef26ba93ba5" [[package]] name = "log" @@ -1224,12 +1283,6 @@ dependencies = [ "cfg-if", ] -[[package]] -name = "maplit" -version = "1.0.2" -source = "registry+https://github.com/rust-lang/crates.io-index" -checksum = "3e2e65a1a2e43cfcb47a895c4c8b10d1f4a61097f9f254f183aee60cad9c651d" - [[package]] name = "matches" version = "0.1.9" @@ -1256,18 +1309,18 @@ checksum = "2a60c7ce501c71e03a9c9c0d35b861413ae925bd979cc7a4e30d060069aaac8d" [[package]] name = "miniz_oxide" -version = "0.5.1" +version = "0.5.3" source = "registry+https://github.com/rust-lang/crates.io-index" -checksum = "d2b29bd4bc3f33391105ebee3589c19197c4271e3e5a9ec9bfe8127eeff8f082" +checksum = "6f5c75688da582b8ffc1f1799e9db273f32133c49e048f614d22ec3256773ccc" dependencies = [ "adler", ] [[package]] name = "mio" -version = "0.8.3" +version = "0.8.4" source = "registry+https://github.com/rust-lang/crates.io-index" -checksum = "713d550d9b44d89174e066b7a6217ae06234c10cb47819a88290d2b353c31799" +checksum = "57ee1c23c7c63b0c9250c339ffdc69255f110b298b901b9f6c82547b7b87caaf" dependencies = [ "libc", "log", @@ -1278,13 +1331,13 @@ dependencies = [ [[package]] name = "mixnet-contract-common" version = "0.1.0" +source = "git+https://github.com/nymtech/nym?branch=feature/nym-cli#4045541e461898c37872a9b75822d3ba84b9f98c" dependencies = [ "az", "contracts-common", "cosmwasm-std", "fixed", "log", - "network-defaults", "schemars", "serde", "serde_repr", @@ -1293,6 +1346,19 @@ dependencies = [ "ts-rs", ] +[[package]] +name = "multisig-contract-common" +version = "0.1.0" +source = "git+https://github.com/nymtech/nym?branch=feature/nym-cli#4045541e461898c37872a9b75822d3ba84b9f98c" +dependencies = [ + "cosmwasm-std", + "cw-utils", + "cw3", + "cw4", + "schemars", + "serde", +] + [[package]] name = "native-tls" version = "0.2.10" @@ -1314,8 +1380,10 @@ dependencies = [ [[package]] name = "network-defaults" version = "0.1.0" +source = "git+https://github.com/nymtech/nym?branch=feature/nym-cli#4045541e461898c37872a9b75822d3ba84b9f98c" dependencies = [ "cfg-if", + "dotenv", "hex-literal", "once_cell", "serde", @@ -1363,57 +1431,40 @@ dependencies = [ ] [[package]] -name = "nym-types" +name = "nym-cli-commands" version = "1.0.0" +source = "git+https://github.com/nymtech/nym?branch=feature/nym-cli#4045541e461898c37872a9b75822d3ba84b9f98c" dependencies = [ - "coconut-interface", - "config", + "bip39", + "cfg-if", + "clap", "cosmrs", - "cosmwasm-std", - "eyre", - "itertools", + "handlebars", + "humantime-serde", + "k256", "log", "mixnet-contract-common", - "reqwest", - "schemars", + "network-defaults", + "rand 0.6.5", "serde", "serde_json", - "strum", "thiserror", - "ts-rs", + "toml", "url", "validator-client", - "vesting-contract", - "vesting-contract-common", -] - -[[package]] -name = "nym-wallet-types" -version = "1.0.0" -dependencies = [ - "config", - "cosmrs", - "cosmwasm-std", - "mixnet-contract-common", - "nym-types", - "serde", - "serde_json", - "strum", - "ts-rs", - "validator-client", - "vesting-contract", "vesting-contract-common", ] [[package]] name = "nymcoconut" version = "0.5.0" +source = "git+https://github.com/nymtech/nym?branch=feature/nym-cli#4045541e461898c37872a9b75822d3ba84b9f98c" dependencies = [ "bls12_381", "bs58", "digest 0.9.0", "ff 0.10.1", - "getrandom 0.2.6", + "getrandom 0.2.7", "group 0.10.0", "itertools", "rand 0.8.5", @@ -1425,15 +1476,9 @@ dependencies = [ [[package]] name = "once_cell" -version = "1.12.0" +version = "1.13.1" source = "registry+https://github.com/rust-lang/crates.io-index" -checksum = "7709cef83f0c1f58f666e746a08b21e0085f7440fa6a29cc194d68aac97a4225" - -[[package]] -name = "opaque-debug" -version = "0.2.3" -source = "registry+https://github.com/rust-lang/crates.io-index" -checksum = "2839e79665f131bdb5782e51f2c6c9599c133c6098982a54c794358bf432529c" +checksum = "074864da206b4973b84eb91683020dbefd6a8c3f0f38e054d93954e891935e4e" [[package]] name = "opaque-debug" @@ -1443,9 +1488,9 @@ checksum = "624a8340c38c1b80fd549087862da4ba43e08858af025b236e509b6649fc13d5" [[package]] name = "openssl" -version = "0.10.40" +version = "0.10.41" source = "registry+https://github.com/rust-lang/crates.io-index" -checksum = "fb81a6430ac911acb25fe5ac8f1d2af1b4ea8a4fdfda0f1ee4292af2e2d8eb0e" +checksum = "618febf65336490dfcf20b73f885f5651a0c89c64c2d4a8c3662585a70bf5bd0" dependencies = [ "bitflags", "cfg-if", @@ -1475,9 +1520,9 @@ checksum = "ff011a302c396a5197692431fc1948019154afc178baf7d8e37367442a4601cf" [[package]] name = "openssl-sys" -version = "0.9.73" +version = "0.9.75" source = "registry+https://github.com/rust-lang/crates.io-index" -checksum = "9d5fd19fb3e0a8191c1e34935718976a3e70c112ab9a24af6d7cadccd9d90bc0" +checksum = "e5f9bd0c2710541a3cda73d6f9ac4f1b240de4ae261065d309dbe73d9dceb42f" dependencies = [ "autocfg 1.1.0", "cc", @@ -1486,6 +1531,12 @@ dependencies = [ "vcpkg", ] +[[package]] +name = "os_str_bytes" +version = "6.3.0" +source = "registry+https://github.com/rust-lang/crates.io-index" +checksum = "9ff7415e9ae3fff1225851df9e0d9e4e5479f947619774677a63572e55e80eff" + [[package]] name = "pairing" version = "0.20.0" @@ -1497,9 +1548,9 @@ dependencies = [ [[package]] name = "paste" -version = "1.0.7" +version = "1.0.8" source = "registry+https://github.com/rust-lang/crates.io-index" -checksum = "0c520e05135d6e763148b6426a837e239041653ba7becd2e538c076c738025fc" +checksum = "9423e2b32f7a043629287a536f21951e8c6a82482d0acb1eeebfc90bc2225b22" [[package]] name = "pbkdf2" @@ -1545,18 +1596,19 @@ checksum = "d4fd5641d01c8f18a23da7b6fe29298ff4b55afcccdf78973b24cf3175fee32e" [[package]] name = "pest" -version = "2.1.3" +version = "2.3.0" source = "registry+https://github.com/rust-lang/crates.io-index" -checksum = "10f4872ae94d7b90ae48754df22fd42ad52ce740b8f370b03da4835417403e53" +checksum = "4b0560d531d1febc25a3c9398a62a71256c0178f2e3443baedd9ad4bb8c9deb4" dependencies = [ + "thiserror", "ucd-trie", ] [[package]] name = "pest_derive" -version = "2.1.0" +version = "2.3.0" source = "registry+https://github.com/rust-lang/crates.io-index" -checksum = "833d1ae558dc601e9a60366421196a8d94bc0ac980476d0b67e1d0988d72b2d0" +checksum = "905708f7f674518498c1f8d644481440f476d39ca6ecae83319bba7c6c12da91" dependencies = [ "pest", "pest_generator", @@ -1564,9 +1616,9 @@ dependencies = [ [[package]] name = "pest_generator" -version = "2.1.3" +version = "2.3.0" source = "registry+https://github.com/rust-lang/crates.io-index" -checksum = "99b8db626e31e5b81787b9783425769681b347011cc59471e33ea46d2ea0cf55" +checksum = "5803d8284a629cc999094ecd630f55e91b561a1d1ba75e233b00ae13b91a69ad" dependencies = [ "pest", "pest_meta", @@ -1577,29 +1629,29 @@ dependencies = [ [[package]] name = "pest_meta" -version = "2.1.3" +version = "2.3.0" source = "registry+https://github.com/rust-lang/crates.io-index" -checksum = "54be6e404f5317079812fc8f9f5279de376d8856929e21c184ecf6bbd692a11d" +checksum = "1538eb784f07615c6d9a8ab061089c6c54a344c5b4301db51990ca1c241e8c04" dependencies = [ - "maplit", + "once_cell", "pest", - "sha-1 0.8.2", + "sha-1", ] [[package]] name = "pin-project" -version = "1.0.10" +version = "1.0.12" source = "registry+https://github.com/rust-lang/crates.io-index" -checksum = "58ad3879ad3baf4e44784bc6a718a8698867bb991f8ce24d1bcbe2cfb4c3a75e" +checksum = "ad29a609b6bcd67fee905812e544992d216af9d755757c05ed2d0e15a74c6ecc" dependencies = [ "pin-project-internal", ] [[package]] name = "pin-project-internal" -version = "1.0.10" +version = "1.0.12" source = "registry+https://github.com/rust-lang/crates.io-index" -checksum = "744b6f092ba29c3650faf274db506afd39944f48420f6c86b17cfe0ee1cb36bb" +checksum = "069bdb1e05adc7a8990dce9cc75370895fbe4e3d58b9b73bf1aee56359344a55" dependencies = [ "proc-macro2", "quote", @@ -1667,18 +1719,18 @@ dependencies = [ [[package]] name = "proc-macro2" -version = "1.0.39" +version = "1.0.43" source = "registry+https://github.com/rust-lang/crates.io-index" -checksum = "c54b25569025b7fc9651de43004ae593a75ad88543b17178aa5e1b9c4f15f56f" +checksum = "0a2ca2c61bc9f3d74d2886294ab7b9853abd9c1ad903a3ac7815c58989bb7bab" dependencies = [ "unicode-ident", ] [[package]] name = "prost" -version = "0.9.0" +version = "0.10.4" source = "registry+https://github.com/rust-lang/crates.io-index" -checksum = "444879275cb4fd84958b1a1d5420d15e6fcf7c235fe47f053c9c2a80aceb6001" +checksum = "71adf41db68aa0daaefc69bb30bcd68ded9b9abaad5d1fbb6304c4fb390e083e" dependencies = [ "bytes", "prost-derive", @@ -1686,9 +1738,9 @@ dependencies = [ [[package]] name = "prost-derive" -version = "0.9.0" +version = "0.10.1" source = "registry+https://github.com/rust-lang/crates.io-index" -checksum = "f9cc1a3263e07e0bf68e96268f37665207b49560d98739662cdfaae215c720fe" +checksum = "7b670f45da57fb8542ebdbb6105a925fe571b67f9e7ed9f47a06a84e72b4e7cc" dependencies = [ "anyhow", "itertools", @@ -1699,9 +1751,9 @@ dependencies = [ [[package]] name = "prost-types" -version = "0.9.0" +version = "0.10.1" source = "registry+https://github.com/rust-lang/crates.io-index" -checksum = "534b7a0e836e3c482d2693070f982e39e7611da9695d4d1f5a4b186b51faef0a" +checksum = "2d0a014229361011dc8e69c8a1ec6c2e8d0f2af7c91e3ea3f5b2170298461e68" dependencies = [ "bytes", "prost", @@ -1715,9 +1767,9 @@ checksum = "a993555f31e5a609f617c12db6250dedcac1b0a85076912c436e6fc9b2c8e6a3" [[package]] name = "quote" -version = "1.0.18" +version = "1.0.21" source = "registry+https://github.com/rust-lang/crates.io-index" -checksum = "a1feb54ed693b93a84e14094943b84b7c4eae204c512b7ccb95ab0c66d278ad1" +checksum = "bbe448f377a7d6961e30f5955f9b8d106c3f5e449d493ee1b125c1d43c2b5179" dependencies = [ "proc-macro2", ] @@ -1802,7 +1854,7 @@ version = "0.6.3" source = "registry+https://github.com/rust-lang/crates.io-index" checksum = "d34f1408f55294453790c48b2f1ebbb1c5b4b7563eb1f418bcfcfdbb06ebb4e7" dependencies = [ - "getrandom 0.2.6", + "getrandom 0.2.7", ] [[package]] @@ -1878,9 +1930,9 @@ dependencies = [ [[package]] name = "redox_syscall" -version = "0.2.13" +version = "0.2.16" source = "registry+https://github.com/rust-lang/crates.io-index" -checksum = "62f25bc4c7e55e0b0b7a1d43fb893f4fa1361d0abe38b9ce4f323c2adfe6ef42" +checksum = "fb5a58c1855b4b6819d59012155603f0b22ad30cad752600aadfcb695265519a" dependencies = [ "bitflags", ] @@ -1896,9 +1948,9 @@ dependencies = [ [[package]] name = "reqwest" -version = "0.11.10" +version = "0.11.11" source = "registry+https://github.com/rust-lang/crates.io-index" -checksum = "46a1f7aa4f35e5e8b4160449f51afc758f0ce6454315a9fa7d0d113e958c41eb" +checksum = "b75aa69a3f06bbcc66ede33af2af253c6f7a86b1ca0033f60c580a27074fbf92" dependencies = [ "base64", "bytes", @@ -1923,6 +1975,7 @@ dependencies = [ "serde_urlencoded", "tokio", "tokio-native-tls", + "tower-service", "url", "wasm-bindgen", "wasm-bindgen-futures", @@ -1964,7 +2017,7 @@ checksum = "2eca4ecc81b7f313189bf73ce724400a07da2a6dac19588b03c8bd76a2dcc251" dependencies = [ "block-buffer 0.9.0", "digest 0.9.0", - "opaque-debug 0.3.0", + "opaque-debug", ] [[package]] @@ -1992,17 +2045,11 @@ dependencies = [ "security-framework", ] -[[package]] -name = "rustversion" -version = "1.0.6" -source = "registry+https://github.com/rust-lang/crates.io-index" -checksum = "f2cc38e8fa666e2de3c4aba7edeb5ffc5246c1c2ed0e3d17e560aeeba736b23f" - [[package]] name = "ryu" -version = "1.0.10" +version = "1.0.11" source = "registry+https://github.com/rust-lang/crates.io-index" -checksum = "f3f6f92acf49d1b98f7a81226834412ada05458b7364277387724a237f062695" +checksum = "4501abdff3ae82a1c1b477a17252eb69cee9e66eb915c1abaa4f44d873df9f09" [[package]] name = "same-file" @@ -2065,7 +2112,7 @@ source = "registry+https://github.com/rust-lang/crates.io-index" checksum = "08da66b8b0965a5555b6bd6639e68ccba85e1e2506f5fbb089e93f8a04e1a2d1" dependencies = [ "der", - "generic-array 0.14.5", + "generic-array", "pkcs8", "subtle", "zeroize", @@ -2073,9 +2120,9 @@ dependencies = [ [[package]] name = "security-framework" -version = "2.6.1" +version = "2.7.0" source = "registry+https://github.com/rust-lang/crates.io-index" -checksum = "2dc14f172faf8a0194a3aded622712b0de276821addc574fa54fc0a1167e10dc" +checksum = "2bc1bb97804af6631813c55739f771071e0f2ed33ee20b68c86ec505d906356c" dependencies = [ "bitflags", "core-foundation", @@ -2096,9 +2143,9 @@ dependencies = [ [[package]] name = "serde" -version = "1.0.137" +version = "1.0.144" source = "registry+https://github.com/rust-lang/crates.io-index" -checksum = "61ea8d54c77f8315140a05f4c7237403bf38b72704d031543aa1d16abbf517d1" +checksum = "0f747710de3dcd43b88c9168773254e809d8ddbdf9653b84e2554ab219f17860" dependencies = [ "serde_derive", ] @@ -2114,18 +2161,18 @@ dependencies = [ [[package]] name = "serde_bytes" -version = "0.11.6" +version = "0.11.7" source = "registry+https://github.com/rust-lang/crates.io-index" -checksum = "212e73464ebcde48d723aa02eb270ba62eff38a9b732df31f33f1b4e145f3a54" +checksum = "cfc50e8183eeeb6178dcb167ae34a8051d63535023ae38b5d8d12beae193d37b" dependencies = [ "serde", ] [[package]] name = "serde_derive" -version = "1.0.137" +version = "1.0.144" source = "registry+https://github.com/rust-lang/crates.io-index" -checksum = "1f26faba0c3959972377d3b2d306ee9f71faee9714294e41bb777f83f88578be" +checksum = "94ed3a816fb1d101812f83e789f888322c34e291f894f19590dc310963e87a00" dependencies = [ "proc-macro2", "quote", @@ -2145,9 +2192,9 @@ dependencies = [ [[package]] name = "serde_json" -version = "1.0.81" +version = "1.0.85" source = "registry+https://github.com/rust-lang/crates.io-index" -checksum = "9b7ce2b32a1aed03c558dc61a5cd328f15aff2dbc17daad8fb8af04d2100e15c" +checksum = "e55a28e3aaef9d5ce0506d0a14dbba8054ddc7e499ef522dd8b26859ec9d4a44" dependencies = [ "itoa", "ryu", @@ -2156,9 +2203,9 @@ dependencies = [ [[package]] name = "serde_repr" -version = "0.1.8" +version = "0.1.9" source = "registry+https://github.com/rust-lang/crates.io-index" -checksum = "a2ad84e47328a31223de7fed7a4f5087f2d6ddfe586cf3ca25b7a165bc0a5aed" +checksum = "1fe39d9fbb0ebf5eb2c7cb7e2a47e4f462fad1379f1166b8ae49ad9eae89a7ca" dependencies = [ "proc-macro2", "quote", @@ -2177,18 +2224,6 @@ dependencies = [ "serde", ] -[[package]] -name = "sha-1" -version = "0.8.2" -source = "registry+https://github.com/rust-lang/crates.io-index" -checksum = "f7d94d0bede923b3cea61f3f1ff57ff8cdfd77b400fb8f9998949e0cf04163df" -dependencies = [ - "block-buffer 0.7.3", - "digest 0.8.1", - "fake-simd", - "opaque-debug 0.2.3", -] - [[package]] name = "sha-1" version = "0.10.0" @@ -2210,7 +2245,7 @@ dependencies = [ "cfg-if", "cpufeatures", "digest 0.9.0", - "opaque-debug 0.3.0", + "opaque-debug", ] [[package]] @@ -2222,7 +2257,7 @@ dependencies = [ "block-buffer 0.9.0", "digest 0.9.0", "keccak", - "opaque-debug 0.3.0", + "opaque-debug", ] [[package]] @@ -2237,9 +2272,12 @@ dependencies = [ [[package]] name = "slab" -version = "0.4.6" +version = "0.4.7" source = "registry+https://github.com/rust-lang/crates.io-index" -checksum = "eb703cfe953bccee95685111adeedb76fabe4e97549a58d16f03ea7b9367bb32" +checksum = "4614a76b2a8be0058caa9dbbaf66d988527d86d003c11a94fbd335d7661edcef" +dependencies = [ + "autocfg 1.1.0", +] [[package]] name = "smallvec" @@ -2283,26 +2321,10 @@ source = "registry+https://github.com/rust-lang/crates.io-index" checksum = "a2eb9349b6444b326872e140eb1cf5e7c522154d69e7a0ffb0fb81c06b37543f" [[package]] -name = "strum" -version = "0.23.0" +name = "strsim" +version = "0.10.0" source = "registry+https://github.com/rust-lang/crates.io-index" -checksum = "cae14b91c7d11c9a851d3fbc80a963198998c2a64eec840477fa92d8ce9b70bb" -dependencies = [ - "strum_macros", -] - -[[package]] -name = "strum_macros" -version = "0.23.1" -source = "registry+https://github.com/rust-lang/crates.io-index" -checksum = "5bb0dc7ee9c15cea6199cde9a127fa16a4c5819af85395457ad72d68edc85a38" -dependencies = [ - "heck", - "proc-macro2", - "quote", - "rustversion", - "syn", -] +checksum = "73473c0e59e6d5812c5dfe2a064a6444949f089e20eec9a2e5506596494e4623" [[package]] name = "subtle" @@ -2321,9 +2343,9 @@ dependencies = [ [[package]] name = "syn" -version = "1.0.95" +version = "1.0.99" source = "registry+https://github.com/rust-lang/crates.io-index" -checksum = "fbaf6116ab8924f39d52792136fb74fd60a80194cf1b1c6ffa6453eef1c3f942" +checksum = "58dbef6ec655055e20b86b15a8cc6d439cca19b667537ac6a1369572d151ab13" dependencies = [ "proc-macro2", "quote", @@ -2358,9 +2380,9 @@ dependencies = [ [[package]] name = "tendermint" -version = "0.23.3" +version = "0.23.7" source = "registry+https://github.com/rust-lang/crates.io-index" -checksum = "a9ef686b8ecd36550d0581f0989c9d8607090b23005df479d8e6ba348b5800b9" +checksum = "3ca881fa4dedd2b46334f13be7fbc8cc1549ba4be5a833fe4e73d1a1baaf7949" dependencies = [ "async-trait", "bytes", @@ -2389,9 +2411,9 @@ dependencies = [ [[package]] name = "tendermint-config" -version = "0.23.3" +version = "0.23.7" source = "registry+https://github.com/rust-lang/crates.io-index" -checksum = "ecc127f82e7a8c7337c1f293d65a821380d3407c4c44bc979ef4da0ebc3b31ed" +checksum = "f6c56ee93f4e9b7e7daba86d171f44572e91b741084384d0ae00df7991873dfd" dependencies = [ "flex-error", "serde", @@ -2403,9 +2425,9 @@ dependencies = [ [[package]] name = "tendermint-proto" -version = "0.23.3" +version = "0.23.7" source = "registry+https://github.com/rust-lang/crates.io-index" -checksum = "a9e0a0251fd81bed7420bea0f4d91c2a58f6c9fa34d5b2f70bed0ba8890de5aa" +checksum = "b71f925d74903f4abbdc4af0110635a307b3cb05b175fdff4a7247c14a4d0874" dependencies = [ "bytes", "flex-error", @@ -2421,15 +2443,15 @@ dependencies = [ [[package]] name = "tendermint-rpc" -version = "0.23.3" +version = "0.23.7" source = "registry+https://github.com/rust-lang/crates.io-index" -checksum = "626c493e9ced3a9de37583bbd929f4b6dbd49aa513ab9b4776aa44a9332ce9b5" +checksum = "a13e63f57ee05a1e927887191c76d1b139de9fa40c180b9f8727ee44377242a6" dependencies = [ "async-trait", "bytes", "flex-error", "futures", - "getrandom 0.2.6", + "getrandom 0.2.7", "http", "hyper", "hyper-proxy", @@ -2462,19 +2484,25 @@ dependencies = [ ] [[package]] -name = "thiserror" -version = "1.0.31" +name = "textwrap" +version = "0.15.0" source = "registry+https://github.com/rust-lang/crates.io-index" -checksum = "bd829fe32373d27f76265620b5309d0340cb8550f523c1dda251d6298069069a" +checksum = "b1141d4d61095b28419e22cb0bbf02755f5e54e0526f97f1e3d1d160e60885fb" + +[[package]] +name = "thiserror" +version = "1.0.32" +source = "registry+https://github.com/rust-lang/crates.io-index" +checksum = "f5f6586b7f764adc0231f4c79be7b920e766bb2f3e51b3661cdb263828f19994" dependencies = [ "thiserror-impl", ] [[package]] name = "thiserror-impl" -version = "1.0.31" +version = "1.0.32" source = "registry+https://github.com/rust-lang/crates.io-index" -checksum = "0396bc89e626244658bef819e22d0cc459e795a5ebe878e6ec336d1674a8d79a" +checksum = "12bafc5b54507e0149cdf1b145a5d80ab80a90bcd9275df43d4fff68460f6c21" dependencies = [ "proc-macro2", "quote", @@ -2483,9 +2511,9 @@ dependencies = [ [[package]] name = "time" -version = "0.3.9" +version = "0.3.13" source = "registry+https://github.com/rust-lang/crates.io-index" -checksum = "c2702e08a7a860f005826c6815dcac101b19b5eb330c27fe4a5928fec1d20ddd" +checksum = "db76ff9fa4b1458b3c7f077f3ff9887394058460d21e634355b273aaf11eea45" dependencies = [ "itoa", "libc", @@ -2501,10 +2529,11 @@ checksum = "42657b1a6f4d817cda8e7a0ace261fe0cc946cf3a80314390b22cc61ae080792" [[package]] name = "tokio" -version = "1.18.2" +version = "1.20.1" source = "registry+https://github.com/rust-lang/crates.io-index" -checksum = "4903bf0427cf68dddd5aa6a93220756f8be0c34fcfa9f5e6191e103e15a31395" +checksum = "7a8325f63a7d4774dd041e363b2409ed1c5cbbd0f867795e661df066b2b0a581" dependencies = [ + "autocfg 1.1.0", "bytes", "libc", "memchr", @@ -2519,9 +2548,9 @@ dependencies = [ [[package]] name = "tokio-macros" -version = "1.7.0" +version = "1.8.0" source = "registry+https://github.com/rust-lang/crates.io-index" -checksum = "b557f72f448c511a979e2564e55d74e6c4432fc96ff4f6241bc6bded342643b7" +checksum = "9724f9a975fb987ef7a3cd9be0350edcbe130698af5b8f7a631e23d42d052484" dependencies = [ "proc-macro2", "quote", @@ -2551,9 +2580,9 @@ dependencies = [ [[package]] name = "tokio-util" -version = "0.7.2" +version = "0.7.3" source = "registry+https://github.com/rust-lang/crates.io-index" -checksum = "f988a1a1adc2fb21f9c12aa96441da33a1728193ae0b95d2be22dbd17fcb4e5c" +checksum = "cc463cd8deddc3770d20f9852143d50bf6094e640b485cb2e189a2099085ff45" dependencies = [ "bytes", "futures-core", @@ -2574,40 +2603,28 @@ dependencies = [ [[package]] name = "tower-service" -version = "0.3.1" +version = "0.3.2" source = "registry+https://github.com/rust-lang/crates.io-index" -checksum = "360dfd1d6d30e05fda32ace2c8c70e9c0a9da713275777f5a4dbb8a1893930c6" +checksum = "b6bc1c9ce2b5135ac7f93c72918fc37feb872bdc6a5533a8b85eb4b86bfdae52" [[package]] name = "tracing" -version = "0.1.34" +version = "0.1.36" source = "registry+https://github.com/rust-lang/crates.io-index" -checksum = "5d0ecdcb44a79f0fe9844f0c4f33a342cbcbb5117de8001e6ba0dc2351327d09" +checksum = "2fce9567bd60a67d08a16488756721ba392f24f29006402881e43b19aac64307" dependencies = [ "cfg-if", "pin-project-lite", - "tracing-attributes", "tracing-core", ] -[[package]] -name = "tracing-attributes" -version = "0.1.21" -source = "registry+https://github.com/rust-lang/crates.io-index" -checksum = "cc6b8ad3567499f98a1db7a752b07a7c8c7c7c34c332ec00effb2b0027974b7c" -dependencies = [ - "proc-macro2", - "quote", - "syn", -] - [[package]] name = "tracing-core" -version = "0.1.26" +version = "0.1.29" source = "registry+https://github.com/rust-lang/crates.io-index" -checksum = "f54c8ca710e81886d498c2fd3331b56c93aa248d49de2222ad2742247c60072f" +checksum = "5aeea4303076558a00714b823f9ad67d58a3bbda1df83d8827d21193156e22f7" dependencies = [ - "lazy_static", + "once_cell", ] [[package]] @@ -2618,34 +2635,19 @@ checksum = "59547bce71d9c38b83d9c0e92b6066c4253371f15005def0c30d9657f50c7642" [[package]] name = "ts-rs" -version = "6.1.2" +version = "6.2.0" source = "registry+https://github.com/rust-lang/crates.io-index" -checksum = "3d26cba30c9b3a2f537f765cf754126f11c983b7426d280ae0b4cef2374cab98" +checksum = "dc59f479df54269b400dd95bc3b7e81623b3e4b9c70c8ca7125ab8341eafa64e" dependencies = [ "thiserror", "ts-rs-macros", ] -[[package]] -name = "ts-rs-cli" -version = "0.1.0" -dependencies = [ - "anyhow", - "mixnet-contract-common", - "nym-types", - "nym-wallet-types", - "ts-rs", - "validator-api-requests", - "validator-client", - "vesting-contract-common", - "walkdir", -] - [[package]] name = "ts-rs-macros" -version = "6.1.2" +version = "6.2.0" source = "registry+https://github.com/rust-lang/crates.io-index" -checksum = "fd8e302fbcf5b60dfa1df443535967511442c5ce4eac8b4c9fa811f2274280a4" +checksum = "9f807fdb3151fee75df7485b901a89624358cd07a67a8fb1a5831bf5a07681ff" dependencies = [ "Inflector", "proc-macro2", @@ -2662,9 +2664,9 @@ checksum = "dcf81ac59edc17cc8697ff311e8f5ef2d99fcbd9817b34cec66f90b6c3dfd987" [[package]] name = "ucd-trie" -version = "0.1.3" +version = "0.1.4" source = "registry+https://github.com/rust-lang/crates.io-index" -checksum = "56dee185309b50d1f11bfedef0fe6d036842e3fb77413abef29f8f8d1c5d4c1c" +checksum = "89570599c4fe5585de2b388aab47e99f7fa4e9238a1399f707a02e356058141c" [[package]] name = "uint" @@ -2686,9 +2688,9 @@ checksum = "099b7128301d285f79ddd55b9a83d5e6b9e97c92e0ea0daebee7263e932de992" [[package]] name = "unicode-ident" -version = "1.0.0" +version = "1.0.3" source = "registry+https://github.com/rust-lang/crates.io-index" -checksum = "d22af068fba1eb5edcb4aea19d382b2a3deb4c8f9d475c589b6ada9e0fd493ee" +checksum = "c4f5b37a154999a8f3f98cc23a628d850e154479cd94decf3414696e12e31aaf" [[package]] name = "unicode-normalization" @@ -2699,12 +2701,6 @@ dependencies = [ "smallvec", ] -[[package]] -name = "unicode-segmentation" -version = "1.9.0" -source = "registry+https://github.com/rust-lang/crates.io-index" -checksum = "7e8820f5d777f6224dc4be3632222971ac30164d4a258d595640799554ebfd99" - [[package]] name = "unicode-xid" version = "0.2.3" @@ -2739,7 +2735,12 @@ checksum = "bc5cf98d8186244414c848017f0e2676b3fcb46807f6668a97dfe67359a3c4b7" [[package]] name = "validator-api-requests" version = "0.1.0" +source = "git+https://github.com/nymtech/nym?branch=feature/nym-cli#4045541e461898c37872a9b75822d3ba84b9f98c" dependencies = [ + "bs58", + "coconut-interface", + "cosmrs", + "getset", "mixnet-contract-common", "schemars", "serde", @@ -2749,20 +2750,25 @@ dependencies = [ [[package]] name = "validator-client" version = "0.1.0" +source = "git+https://github.com/nymtech/nym?branch=feature/nym-cli#4045541e461898c37872a9b75822d3ba84b9f98c" dependencies = [ "async-trait", "base64", "bip39", + "coconut-bandwidth-contract-common", "coconut-interface", "colored", "config", "cosmrs", "cosmwasm-std", + "cw3", + "execute", "flate2", "futures", "itertools", "log", "mixnet-contract-common", + "multisig-contract-common", "network-defaults", "prost", "reqwest", @@ -2771,7 +2777,6 @@ dependencies = [ "sha2", "thiserror", "tokio", - "ts-rs", "url", "validator-api-requests", "vesting-contract", @@ -2792,9 +2797,9 @@ checksum = "49874b5167b65d7193b8aba1567f5c7d93d001cafc34600cee003eda787e483f" [[package]] name = "vesting-contract" -version = "1.0.0" +version = "1.0.1" +source = "git+https://github.com/nymtech/nym?branch=feature/nym-cli#4045541e461898c37872a9b75822d3ba84b9f98c" dependencies = [ - "config", "cosmwasm-std", "cw-storage-plus", "mixnet-contract-common", @@ -2807,6 +2812,7 @@ dependencies = [ [[package]] name = "vesting-contract-common" version = "0.1.0" +source = "git+https://github.com/nymtech/nym?branch=feature/nym-cli#4045541e461898c37872a9b75822d3ba84b9f98c" dependencies = [ "config", "cosmwasm-std", @@ -2844,12 +2850,6 @@ version = "0.9.0+wasi-snapshot-preview1" source = "registry+https://github.com/rust-lang/crates.io-index" checksum = "cccddf32554fecc6acb585f82a32a72e28b48f8c4c1883ddfeeeaa96f7d8e519" -[[package]] -name = "wasi" -version = "0.10.2+wasi-snapshot-preview1" -source = "registry+https://github.com/rust-lang/crates.io-index" -checksum = "fd6fbd9a79829dd1ad0cc20627bf1ed606756a7f77edff7b66b7064f9cb327c6" - [[package]] name = "wasi" version = "0.11.0+wasi-snapshot-preview1" @@ -2858,9 +2858,9 @@ checksum = "9c8d87e72b64a3b4db28d11ce29237c246188f4f51057d65a7eab63b7987e423" [[package]] name = "wasm-bindgen" -version = "0.2.80" +version = "0.2.82" source = "registry+https://github.com/rust-lang/crates.io-index" -checksum = "27370197c907c55e3f1a9fbe26f44e937fe6451368324e009cba39e139dc08ad" +checksum = "fc7652e3f6c4706c8d9cd54832c4a4ccb9b5336e2c3bd154d5cccfbf1c1f5f7d" dependencies = [ "cfg-if", "wasm-bindgen-macro", @@ -2868,13 +2868,13 @@ dependencies = [ [[package]] name = "wasm-bindgen-backend" -version = "0.2.80" +version = "0.2.82" source = "registry+https://github.com/rust-lang/crates.io-index" -checksum = "53e04185bfa3a779273da532f5025e33398409573f348985af9a1cbf3774d3f4" +checksum = "662cd44805586bd52971b9586b1df85cdbbd9112e4ef4d8f41559c334dc6ac3f" dependencies = [ "bumpalo", - "lazy_static", "log", + "once_cell", "proc-macro2", "quote", "syn", @@ -2883,9 +2883,9 @@ dependencies = [ [[package]] name = "wasm-bindgen-futures" -version = "0.4.30" +version = "0.4.32" source = "registry+https://github.com/rust-lang/crates.io-index" -checksum = "6f741de44b75e14c35df886aff5f1eb73aa114fa5d4d00dcd37b5e01259bf3b2" +checksum = "fa76fb221a1f8acddf5b54ace85912606980ad661ac7a503b4570ffd3a624dad" dependencies = [ "cfg-if", "js-sys", @@ -2895,9 +2895,9 @@ dependencies = [ [[package]] name = "wasm-bindgen-macro" -version = "0.2.80" +version = "0.2.82" source = "registry+https://github.com/rust-lang/crates.io-index" -checksum = "17cae7ff784d7e83a2fe7611cfe766ecf034111b49deb850a3dc7699c08251f5" +checksum = "b260f13d3012071dfb1512849c033b1925038373aea48ced3012c09df952c602" dependencies = [ "quote", "wasm-bindgen-macro-support", @@ -2905,9 +2905,9 @@ dependencies = [ [[package]] name = "wasm-bindgen-macro-support" -version = "0.2.80" +version = "0.2.82" source = "registry+https://github.com/rust-lang/crates.io-index" -checksum = "99ec0dc7a4756fffc231aab1b9f2f578d23cd391390ab27f952ae0c9b3ece20b" +checksum = "5be8e654bdd9b79216c2929ab90721aa82faf65c48cdf08bdc4e7f51357b80da" dependencies = [ "proc-macro2", "quote", @@ -2918,15 +2918,15 @@ dependencies = [ [[package]] name = "wasm-bindgen-shared" -version = "0.2.80" +version = "0.2.82" source = "registry+https://github.com/rust-lang/crates.io-index" -checksum = "d554b7f530dee5964d9a9468d95c1f8b8acae4f282807e7d27d4b03099a46744" +checksum = "6598dd0bd3c7d51095ff6531a5b23e02acdc81804e30d8f07afb77b7215a140a" [[package]] name = "web-sys" -version = "0.3.57" +version = "0.3.59" source = "registry+https://github.com/rust-lang/crates.io-index" -checksum = "7b17e741662c70c8bd24ac5c5b18de314a2c26c32bf8346ee1e6f53de919c283" +checksum = "ed055ab27f941423197eb86b2035720b1a3ce40504df082cac2ecc6ed73335a1" dependencies = [ "js-sys", "wasm-bindgen", @@ -3036,9 +3036,9 @@ dependencies = [ [[package]] name = "zeroize" -version = "1.5.5" +version = "1.3.0" source = "registry+https://github.com/rust-lang/crates.io-index" -checksum = "94693807d016b2f2d2e14420eb3bfcca689311ff775dcf113d74ea624b7cdf07" +checksum = "4756f7db3f7b5574938c3eb1c117038b8e07f95ee6718c0efad4ac21508f1efd" dependencies = [ "zeroize_derive", ] diff --git a/examples/cli/commands/verify-signature/Cargo.toml b/examples/cli/commands/verify-signature/Cargo.toml new file mode 100644 index 0000000000..5ad0673115 --- /dev/null +++ b/examples/cli/commands/verify-signature/Cargo.toml @@ -0,0 +1,9 @@ +[package] +name = "example-verify-signature" +version = "0.1.0" +edition = "2021" + +[workspace] + +[dependencies] +nym-cli-commands = { git = "https://github.com/nymtech/nym", branch = "develop" } \ No newline at end of file diff --git a/examples/cli/commands/verify-signature/README.md b/examples/cli/commands/verify-signature/README.md new file mode 100644 index 0000000000..e32c0b558c --- /dev/null +++ b/examples/cli/commands/verify-signature/README.md @@ -0,0 +1,38 @@ +# Example code to verify a signature + +This is an example app that shows how to verify a signature signed by an account key. + +Inputs to the app are: + +- **signature** - bytes represented as a hex string +- **public key** - in JSON format (you can query any Cosmos chain for account's public key as JSON, however it will need to have sent a signed transaction to the chain for this to be present) +- **message** - the string message to verify + +## Running locally + +Run the example by changning to this directory and running: + +``` +cargo run +``` + +And you should see the output: + +``` +Nym signature verification example + + +public key: {"@type":"/cosmos.crypto.secp256k1.PubKey","key":"A4FdhUMasPmNhRZjtpKlmjNbq7EEUgPxfdI+E3vSajvc"} +signature: E3AA5AC0DA1B7DEBB7808000F719D8ACB9A0BE10AFA2756A788516268EB246A1257EC1097C5E364EF916145B01641DEDFE955994CB340BDAFA99A65BCA3F6F28 +message: test 1234 + + +Verify the correct message: + +SUCCESS ✅ signature is valid + + +Verify another message: + +FAILURE ❌ signature is not valid: signature error +``` \ No newline at end of file diff --git a/examples/cli/commands/verify-signature/src/main.rs b/examples/cli/commands/verify-signature/src/main.rs new file mode 100644 index 0000000000..28f47ca4a4 --- /dev/null +++ b/examples/cli/commands/verify-signature/src/main.rs @@ -0,0 +1,43 @@ +use nym_cli_commands::validator::signature::helpers::secp256k1_verify_with_public_key_json; + +fn main() { + println!("\nNym signature verification example\n\n"); + + // the public key in JSON format (because Cosmos supports secp256k1 and ed25519 - NB: the helper only supports secp256k1) + let public_key_as_json = r#"{"@type":"/cosmos.crypto.secp256k1.PubKey","key":"A4FdhUMasPmNhRZjtpKlmjNbq7EEUgPxfdI+E3vSajvc"}"#; + + // the signature as a string of hex characters to represent the bytes in the signature + let signature_as_hex = "E3AA5AC0DA1B7DEBB7808000F719D8ACB9A0BE10AFA2756A788516268EB246A1257EC1097C5E364EF916145B01641DEDFE955994CB340BDAFA99A65BCA3F6F28"; + + // the original message as a string to verify + let message = "test 1234".to_string(); + + println!("public key: {}", &public_key_as_json); + println!("signature: {}", &signature_as_hex); + println!("message: {}", &message); + + println!(); + + // this will pass, because the signature was signed for this message + println!("\nVerify the correct message:\n"); + do_verify( + public_key_as_json.to_string(), + signature_as_hex.to_string(), + message, + ); + + // this will fail, because the signature is for another message + println!("\n\nVerify another message:\n"); + do_verify( + public_key_as_json.to_string(), + signature_as_hex.to_string(), + "another message that will fail".to_string(), + ); +} + +fn do_verify(public_key_as_json: String, signature_as_hex: String, message: String) { + match secp256k1_verify_with_public_key_json(public_key_as_json, signature_as_hex, message) { + Ok(()) => println!("SUCCESS ✅ signature is valid"), + Err(e) => println!("FAILURE ❌ signature is not valid: {}", e), + } +} diff --git a/nym-connect/Cargo.lock b/nym-connect/Cargo.lock index 1e808758c8..d6bf186f83 100644 --- a/nym-connect/Cargo.lock +++ b/nym-connect/Cargo.lock @@ -5227,6 +5227,7 @@ version = "0.1.0" dependencies = [ "nymsphinx-addressing", "ordered-buffer", + "thiserror", ] [[package]] diff --git a/tools/nym-cli/Cargo.toml b/tools/nym-cli/Cargo.toml new file mode 100644 index 0000000000..fe7a243f85 --- /dev/null +++ b/tools/nym-cli/Cargo.toml @@ -0,0 +1,24 @@ +[package] +name = "nym-cli" +version = "1.0.0" +authors = ["Nym Technologies SA"] +edition = "2021" + +[dependencies] +base64 = "0.13.0" +bs58 = "0.4" +clap = { version = "3.2.8", features = ["derive"] } +clap_complete = "3.2.4" +clap_complete_fig = "3.2.4" +dotenv = "0.15.0" +log = "0.4" +pretty_env_logger = "0.4" +serde = { version = "1", features = ["derive"] } +serde_json = "1" +tokio = { version = "1.11", features = [ "net", "rt-multi-thread", "macros", "signal"] } +bip39 = "1.0.1" +anyhow = "1" + +nym-cli-commands = { path = "../../common/commands" } +validator-client = { path = "../../common/client-libs/validator-client", features = ["nymd-client"] } +network-defaults = { path = "../../common/network-defaults" } diff --git a/tools/nym-cli/Makefile b/tools/nym-cli/Makefile new file mode 100644 index 0000000000..1d79365de9 --- /dev/null +++ b/tools/nym-cli/Makefile @@ -0,0 +1,3 @@ +generate-user-docs: + cargo build --release + ../../target/release/nym-cli generate-fig > user-docs/fig-spec.ts diff --git a/tools/nym-cli/README.md b/tools/nym-cli/README.md new file mode 100644 index 0000000000..415e500564 --- /dev/null +++ b/tools/nym-cli/README.md @@ -0,0 +1,139 @@ +# Nym CLI + +This is a CLI tool for interacting with: + +- the Nyx blockchain +- the smart contracts for the Mixnet + +It provides a convenient wrapper around the [`nymd client`](../../common/client-libs) with similar functionality to the`nyxd` binary for querying the chain or executing smart contract methods. + +And in the future it will provide an easy way to interact with Coconut, to issue and verify Coconut credenitals. + +### It DOES NOT do these things: + +The infrastructure components that run a [`gateway`](../../gateway), [`mixnode`](../../mixnode) or Service Provider have their own binaries. + +The [`socks5`](../../common/socks5) client also has its own binary, or use [NymConnect](../../nym-connect). + +# Installing + +Download the CLI binary for your platform from https://nymtech.net/downloads or get a specific version from [GitHub releases](https://github.com/nymtech/nym/releases?q=nym-cli&expanded=true). + +# Configuration + +The Nym CLI runs against mainnet by default. + +If you want to use another environment, you can do this by: +- providing a `.env` file +- setting environment variables ([see here for options](../../common/network-defaults/envs/mainnet.env)) +- passing named arguments + +### `.env` File + +There are two ways to provide this: + +1. A file called `.env` in the same directory as the binary +2. Pass the `--config-env-file` along with a command + +### Passing named arguments + +You will need to pass the following with every command as an argument: + +``` +--mnemonic +--nymd-url +--mixnet-contract +--vesting-contract +``` + +# How do I use it? + +The simplest way to find out how to use the CLI is to explore the built-in help: + +``` +nym-cli --help +``` + +# Features + +### 🏦 Account + +- create a new account with a random mnemonic +- query the account balance +- query the account public key (needed to verify signatures) +- query for transactions originating from the account +- send tokens to another account + +### ⛓ Block + +- query for the current block height +- query for a block at a height +- query for a block at a timestamp + +### 🪐 `cosmwasm` + +- upload a smart contract +- instantiate a smart contract +- upgrade a smart contract +- execute a smart contract method + +### 𐄳 Mixnet + +#### 📒 Directory + +- query for mixnodes +- query for gateways + +#### 🧑‍🔧 Operators + +- bond/unbond a mixnode or gateway +- query for waiting rewards +- withdraw rewards +- manage mixnode settings + +#### 🥩 Delegators + +- delegate/undelegate to a mixnode +- query for waiting rewards +- withdraw rewards + +### ✍ Sign + +- create a signature for string data (UTF-8) +- verify a signature for an account + +### 🕓 Vesting +- create a vesting schedule +- query for a vesting schedule + +### 🥥 Coconut + +Coming soon, including: + +- issue credential +- verify credential + +# Building + +Build the tool locally by running the following in this directory: + +``` +cargo build --release +``` + +# Generating user docs + +There is a [Makefile](./Makefile) with a target to build the user docs: + +``` +make generate-user-docs +``` + +Build the tool and run the `generate` command: + +``` +cargo build --release +../../target/release/nym-cli generate-fig > user-docs/fig-spec.ts +``` + +See https://github.com/withfig/autocomplete-tools/tree/main/types. \ No newline at end of file diff --git a/tools/nym-cli/src/completion.rs b/tools/nym-cli/src/completion.rs new file mode 100644 index 0000000000..27dedb0318 --- /dev/null +++ b/tools/nym-cli/src/completion.rs @@ -0,0 +1,10 @@ +use clap::Command; +use clap_complete::generate; +use clap_complete_fig::Fig; + +use std::io; + +/// Generates a file with a Typescript export of type Fig.Spec (use https://www.npmjs.com/package/@withfig/autocomplete-tools for typings) +pub(crate) fn print_fig(cmd: &mut Command) { + generate(Fig, cmd, cmd.get_name().to_string(), &mut io::stdout()); +} diff --git a/tools/nym-cli/src/main.rs b/tools/nym-cli/src/main.rs new file mode 100644 index 0000000000..842229b15e --- /dev/null +++ b/tools/nym-cli/src/main.rs @@ -0,0 +1,168 @@ +// Copyright 2022 - Nym Technologies SA +// SPDX-License-Identifier: Apache-2.0 + +use clap::{CommandFactory, Parser, Subcommand}; +use log::{error, warn}; + +use nym_cli_commands::context::{get_network_details, ClientArgs}; +use validator_client::nymd::AccountId; + +mod completion; +mod validator; + +#[derive(Debug, Parser)] +#[clap(name = "nym-cli")] +#[clap(about = "A client for interacting with Nym smart contracts and the Nyx blockchain", long_about = None)] +pub(crate) struct Cli { + #[clap(long, global = true)] + #[clap( + help = "Provide the mnemonic for your account. You can also provide this is an env var called MNEMONIC." + )] + pub(crate) mnemonic: Option, + + #[clap(long, global = true)] + #[clap( + help = "Overrides configuration as a file of environment variables. Note: individual env vars take precedence over this file." + )] + pub(crate) config_env_file: Option, + + #[clap(long, global = true)] + #[clap( + help = "Overrides the nymd URL provided either as an environment variable NYMD_VALIDATOR or in a config file" + )] + pub(crate) nymd_url: Option, + + #[clap(long, global = true)] + #[clap( + help = "Overrides the validator API URL provided either as an environment variable API_VALIDATOR or in a config file" + )] + pub(crate) validator_api_url: Option, + + #[clap(long, global = true)] + #[clap( + help = "Overrides the mixnet contract address provided either as an environment variable or in a config file" + )] + pub(crate) mixnet_contract_address: Option, + + #[clap(long, global = true)] + #[clap( + help = "Overrides the vesting contract address provided either as an environment variable or in a config file" + )] + pub(crate) vesting_contract_address: Option, + + #[clap(subcommand)] + command: Commands, +} + +#[derive(Debug, Subcommand)] +pub(crate) enum Commands { + /// Query and manage Nyx blockchain accounts + Account(nym_cli_commands::validator::account::Account), + /// Sign and verify messages + Signature(nym_cli_commands::validator::signature::Signature), + /// Query chain blocks + Block(nym_cli_commands::validator::block::Block), + /// Manage and execute WASM smart contracts + Cosmwasm(nym_cli_commands::validator::cosmwasm::Cosmwasm), + /// Query for transactions + Tx(nym_cli_commands::validator::transactions::Transactions), + /// Create and query for a vesting schedule + VestingSchedule(nym_cli_commands::validator::vesting::VestingSchedule), + /// Manage your mixnet infrastructure, delegate stake or query the directory + Mixnet(nym_cli_commands::validator::mixnet::Mixnet), + /// Generates shell completion + GenerateFig, +} + +async fn execute(cli: Cli) -> anyhow::Result<()> { + let args = ClientArgs { + nymd_url: cli.nymd_url, + validator_api_url: cli.validator_api_url, + mnemonic: cli.mnemonic, + mixnet_contract_address: cli.mixnet_contract_address, + vesting_contract_address: cli.vesting_contract_address, + config_env_file: cli.config_env_file, + }; + + let network_details = get_network_details(&args)?; + + // use the --mnemonic option if set, then try fall back to the MNEMONIC env var + let mnemonic = args.mnemonic.clone().or_else(|| { + std::env::var("MNEMONIC") + .ok() + .and_then(|m| bip39::Mnemonic::parse(m).ok()) + }); + + match cli.command { + Commands::Account(account) => { + validator::account::execute(args, account, &network_details, mnemonic).await? + } + Commands::Signature(signature) => { + validator::signature::execute(signature, &network_details, mnemonic).await? + } + Commands::Block(block) => validator::block::execute(block, &network_details).await?, + Commands::Cosmwasm(cosmwasm) => { + validator::cosmwasm::execute(args, cosmwasm, &network_details).await? + } + Commands::Tx(transactions) => { + validator::transactions::execute(transactions, &network_details).await? + } + Commands::VestingSchedule(vesting) => { + validator::vesting::execute(args, vesting, &network_details).await? + } + Commands::Mixnet(mixnet) => { + validator::mixnet::execute(args, mixnet, &network_details).await? + } + Commands::GenerateFig => { + let mut cmd = Cli::command(); + completion::print_fig(&mut cmd); + } + } + + Ok(()) +} + +fn setup_logging() { + let mut log_builder = pretty_env_logger::formatted_timed_builder(); + if let Ok(s) = ::std::env::var("RUST_LOG") { + log_builder.parse_filters(&s); + } else { + // default to 'Info' + log_builder.filter(None, log::LevelFilter::Info); + } + + log_builder + .filter_module("hyper", log::LevelFilter::Warn) + .filter_module("tokio_reactor", log::LevelFilter::Warn) + .filter_module("reqwest", log::LevelFilter::Warn) + .filter_module("mio", log::LevelFilter::Warn) + .filter_module("want", log::LevelFilter::Warn) + .filter_module("sled", log::LevelFilter::Warn) + .filter_module("tungstenite", log::LevelFilter::Warn) + .filter_module("tokio_tungstenite", log::LevelFilter::Warn) + .init(); +} + +async fn wait_for_interrupt() { + if let Err(e) = tokio::signal::ctrl_c().await { + error!( + "There was an error while capturing SIGINT - {:?}. We will terminate regardless", + e + ); + } + println!( + "Received SIGINT - the process will terminate now (threads are not yet nicely stopped, if you see stack traces that's alright)." + ); +} + +#[tokio::main] +async fn main() { + setup_logging(); + + let cli = Cli::parse(); + + tokio::select! { + _ = wait_for_interrupt() => warn!("Received interrupt - the specified command might have not completed!"), + _ = execute(cli) => (), + } +} diff --git a/tools/nym-cli/src/validator/account.rs b/tools/nym-cli/src/validator/account.rs new file mode 100644 index 0000000000..36fc3460ba --- /dev/null +++ b/tools/nym-cli/src/validator/account.rs @@ -0,0 +1,79 @@ +// Copyright 2022 - Nym Technologies SA +// SPDX-License-Identifier: Apache-2.0 + +use network_defaults::NymNetworkDetails; +use nym_cli_commands::context::{create_query_client, create_signing_client, ClientArgs}; +use validator_client::nymd::AccountId; + +pub(crate) async fn execute( + global_args: ClientArgs, + account: nym_cli_commands::validator::account::Account, + network_details: &NymNetworkDetails, + mnemonic: Option, +) -> anyhow::Result<()> { + match account.command { + Some(nym_cli_commands::validator::account::AccountCommands::Create(args)) => { + nym_cli_commands::validator::account::create::create_account( + args, + &network_details.chain_details.bech32_account_prefix, + ) + } + Some(nym_cli_commands::validator::account::AccountCommands::Balance(args)) => { + let address_from_args = args.address.clone(); + nym_cli_commands::validator::account::balance::query_balance( + args, + &create_query_client(network_details)?, + get_account_from_mnemonic_as_option( + global_args, + network_details, + address_from_args, + ), + ) + .await + } + Some(nym_cli_commands::validator::account::AccountCommands::PubKey(args)) => { + let address_from_args = args.address.clone(); + nym_cli_commands::validator::account::pubkey::get_pubkey( + args, + &create_query_client(network_details)?, + mnemonic, + get_account_from_mnemonic_as_option( + global_args, + network_details, + address_from_args, + ), + ) + .await; + } + Some(nym_cli_commands::validator::account::AccountCommands::Send(args)) => { + nym_cli_commands::validator::account::send::send( + args, + &create_signing_client(global_args, network_details)?, + ) + .await; + } + _ => unreachable!(), + } + + Ok(()) +} + +fn get_account_from_mnemonic( + global_args: ClientArgs, + network_details: &NymNetworkDetails, + address: Option, +) -> anyhow::Result> { + Ok(address.or(Some( + create_signing_client(global_args, network_details)? + .address() + .clone(), + ))) +} + +fn get_account_from_mnemonic_as_option( + global_args: ClientArgs, + network_details: &NymNetworkDetails, + address: Option, +) -> Option { + get_account_from_mnemonic(global_args, network_details, address).unwrap_or(None) +} diff --git a/tools/nym-cli/src/validator/block.rs b/tools/nym-cli/src/validator/block.rs new file mode 100644 index 0000000000..104680a1d1 --- /dev/null +++ b/tools/nym-cli/src/validator/block.rs @@ -0,0 +1,35 @@ +// Copyright 2022 - Nym Technologies SA +// SPDX-License-Identifier: Apache-2.0 + +use network_defaults::NymNetworkDetails; +use nym_cli_commands::context::create_query_client; + +pub(crate) async fn execute( + block: nym_cli_commands::validator::block::Block, + network_details: &NymNetworkDetails, +) -> anyhow::Result<()> { + match block.command { + Some(nym_cli_commands::validator::block::BlockCommands::Get(args)) => { + nym_cli_commands::validator::block::get::query_for_block( + args, + &create_query_client(network_details)?, + ) + .await + } + Some(nym_cli_commands::validator::block::BlockCommands::Time(args)) => { + nym_cli_commands::validator::block::block_time::query_for_block_time( + args, + &create_query_client(network_details)?, + ) + .await + } + Some(nym_cli_commands::validator::block::BlockCommands::CurrentHeight(_args)) => { + nym_cli_commands::validator::block::current_height::query_current_block_height( + &create_query_client(network_details)?, + ) + .await + } + _ => unreachable!(), + } + Ok(()) +} diff --git a/tools/nym-cli/src/validator/cosmwasm.rs b/tools/nym-cli/src/validator/cosmwasm.rs new file mode 100644 index 0000000000..4a77b3896f --- /dev/null +++ b/tools/nym-cli/src/validator/cosmwasm.rs @@ -0,0 +1,45 @@ +// Copyright 2022 - Nym Technologies SA +// SPDX-License-Identifier: Apache-2.0 + +use network_defaults::NymNetworkDetails; +use nym_cli_commands::context::{create_signing_client, ClientArgs}; + +pub(crate) async fn execute( + global_args: ClientArgs, + cosmwasm: nym_cli_commands::validator::cosmwasm::Cosmwasm, + network_details: &NymNetworkDetails, +) -> anyhow::Result<()> { + match cosmwasm.command { + Some(nym_cli_commands::validator::cosmwasm::CosmwasmCommands::Upload(args)) => { + nym_cli_commands::validator::cosmwasm::upload_contract::upload( + args, + create_signing_client(global_args, network_details)?, + ) + .await + } + Some(nym_cli_commands::validator::cosmwasm::CosmwasmCommands::Init(args)) => { + nym_cli_commands::validator::cosmwasm::init_contract::init( + args, + create_signing_client(global_args, network_details)?, + network_details, + ) + .await + } + Some(nym_cli_commands::validator::cosmwasm::CosmwasmCommands::Migrate(args)) => { + nym_cli_commands::validator::cosmwasm::migrate_contract::migrate( + args, + create_signing_client(global_args, network_details)?, + ) + .await + } + Some(nym_cli_commands::validator::cosmwasm::CosmwasmCommands::Execute(args)) => { + nym_cli_commands::validator::cosmwasm::execute_contract::execute( + args, + create_signing_client(global_args, network_details)?, + ) + .await + } + _ => unreachable!(), + } + Ok(()) +} diff --git a/tools/nym-cli/src/validator/mixnet/delegators/mod.rs b/tools/nym-cli/src/validator/mixnet/delegators/mod.rs new file mode 100644 index 0000000000..ed1ac2f211 --- /dev/null +++ b/tools/nym-cli/src/validator/mixnet/delegators/mod.rs @@ -0,0 +1,32 @@ +// Copyright 2022 - Nym Technologies SA +// SPDX-License-Identifier: Apache-2.0 + +use network_defaults::NymNetworkDetails; +use nym_cli_commands::context::{ + create_signing_client, create_signing_client_with_validator_api, ClientArgs, +}; + +pub(crate) mod rewards; + +pub(crate) async fn execute( + global_args: ClientArgs, + delegators: nym_cli_commands::validator::mixnet::delegators::MixnetDelegators, + network_details: &NymNetworkDetails, +) -> anyhow::Result<()> { + match delegators.command { + nym_cli_commands::validator::mixnet::delegators::MixnetDelegatorsCommands::Rewards(rewards) => { + rewards::execute(global_args, rewards, network_details).await? + } + nym_cli_commands::validator::mixnet::delegators::MixnetDelegatorsCommands::Delegate(args) => { + nym_cli_commands::validator::mixnet::delegators::delegate_to_mixnode::delegate_to_mixnode(args, create_signing_client(global_args, network_details)?).await + } + nym_cli_commands::validator::mixnet::delegators::MixnetDelegatorsCommands::Undelegate(args) => { + nym_cli_commands::validator::mixnet::delegators::undelegate_from_mixnode::undelegate_from_mixnode(args, create_signing_client(global_args, network_details)?).await + } + nym_cli_commands::validator::mixnet::delegators::MixnetDelegatorsCommands::List(args) => { + nym_cli_commands::validator::mixnet::delegators::query_for_delegations::execute(args, create_signing_client_with_validator_api(global_args, network_details)?).await + } + _ => unreachable!(), + } + Ok(()) +} diff --git a/tools/nym-cli/src/validator/mixnet/delegators/rewards/mod.rs b/tools/nym-cli/src/validator/mixnet/delegators/rewards/mod.rs new file mode 100644 index 0000000000..39ca3f673c --- /dev/null +++ b/tools/nym-cli/src/validator/mixnet/delegators/rewards/mod.rs @@ -0,0 +1,19 @@ +// Copyright 2022 - Nym Technologies SA +// SPDX-License-Identifier: Apache-2.0 + +use network_defaults::NymNetworkDetails; +use nym_cli_commands::context::{create_signing_client, ClientArgs}; + +pub(crate) async fn execute( + global_args: ClientArgs, + rewards: nym_cli_commands::validator::mixnet::delegators::rewards::MixnetDelegatorsReward, + network_details: &NymNetworkDetails, +) -> anyhow::Result<()> { + match rewards.command { + nym_cli_commands::validator::mixnet::delegators::rewards::MixnetDelegatorsRewardCommands::Claim(args) => { + nym_cli_commands::validator::mixnet::delegators::rewards::claim_delegator_reward::claim_delegator_reward(args, create_signing_client(global_args, network_details)?).await + } + _ => unreachable!(), + } + Ok(()) +} diff --git a/tools/nym-cli/src/validator/mixnet/mod.rs b/tools/nym-cli/src/validator/mixnet/mod.rs new file mode 100644 index 0000000000..366b922b16 --- /dev/null +++ b/tools/nym-cli/src/validator/mixnet/mod.rs @@ -0,0 +1,25 @@ +use network_defaults::NymNetworkDetails; +use nym_cli_commands::context::ClientArgs; + +pub(crate) mod delegators; +pub(crate) mod operators; +pub(crate) mod query; + +pub(crate) async fn execute( + global_args: ClientArgs, + mixnet: nym_cli_commands::validator::mixnet::Mixnet, + network_details: &NymNetworkDetails, +) -> anyhow::Result<()> { + match mixnet.command { + nym_cli_commands::validator::mixnet::MixnetCommands::Delegators(delegators) => { + delegators::execute(global_args, delegators, network_details).await? + } + nym_cli_commands::validator::mixnet::MixnetCommands::Operators(operators) => { + operators::execute(global_args, operators, network_details).await? + } + nym_cli_commands::validator::mixnet::MixnetCommands::Query(query) => { + query::execute(query, network_details).await? + } + } + Ok(()) +} diff --git a/tools/nym-cli/src/validator/mixnet/operators/gateways/mod.rs b/tools/nym-cli/src/validator/mixnet/operators/gateways/mod.rs new file mode 100644 index 0000000000..f54ac43bca --- /dev/null +++ b/tools/nym-cli/src/validator/mixnet/operators/gateways/mod.rs @@ -0,0 +1,22 @@ +// Copyright 2022 - Nym Technologies SA +// SPDX-License-Identifier: Apache-2.0 + +use network_defaults::NymNetworkDetails; +use nym_cli_commands::context::{create_signing_client, ClientArgs}; + +pub(crate) async fn execute( + global_args: ClientArgs, + gateway: nym_cli_commands::validator::mixnet::operators::gateway::MixnetOperatorsGateway, + network_details: &NymNetworkDetails, +) -> anyhow::Result<()> { + match gateway.command { + nym_cli_commands::validator::mixnet::operators::gateway::MixnetOperatorsGatewayCommands::Bond(args) => { + nym_cli_commands::validator::mixnet::operators::gateway::bond_gateway::bond_gateway(args, create_signing_client(global_args, network_details)?).await + }, + nym_cli_commands::validator::mixnet::operators::gateway::MixnetOperatorsGatewayCommands::Unbound(_args) => { + nym_cli_commands::validator::mixnet::operators::gateway::unbond_gateway::unbond_gateway(create_signing_client(global_args, network_details)?).await + }, + _ => unreachable!(), + } + Ok(()) +} diff --git a/tools/nym-cli/src/validator/mixnet/operators/mixnodes/keys/mod.rs b/tools/nym-cli/src/validator/mixnet/operators/mixnodes/keys/mod.rs new file mode 100644 index 0000000000..3923093dbb --- /dev/null +++ b/tools/nym-cli/src/validator/mixnet/operators/mixnodes/keys/mod.rs @@ -0,0 +1,13 @@ +// Copyright 2022 - Nym Technologies SA +// SPDX-License-Identifier: Apache-2.0 + +pub(crate) async fn execute( + keys: nym_cli_commands::validator::mixnet::operators::mixnode::keys::MixnetOperatorsMixnodeKeys, +) -> anyhow::Result<()> { + match keys.command { + nym_cli_commands::validator::mixnet::operators::mixnode::keys::MixnetOperatorsMixnodeKeysCommands::DecodeMixnodeKey(args) => { + nym_cli_commands::validator::mixnet::operators::mixnode::keys::decode_mixnode_key::decode_mixnode_key(args) + } + } + Ok(()) +} diff --git a/tools/nym-cli/src/validator/mixnet/operators/mixnodes/mod.rs b/tools/nym-cli/src/validator/mixnet/operators/mixnodes/mod.rs new file mode 100644 index 0000000000..2a6a3d0477 --- /dev/null +++ b/tools/nym-cli/src/validator/mixnet/operators/mixnodes/mod.rs @@ -0,0 +1,35 @@ +// Copyright 2022 - Nym Technologies SA +// SPDX-License-Identifier: Apache-2.0 + +use network_defaults::NymNetworkDetails; +use nym_cli_commands::context::{create_signing_client, ClientArgs}; + +pub(crate) mod keys; +pub(crate) mod rewards; +pub(crate) mod settings; + +pub(crate) async fn execute( + global_args: ClientArgs, + mixnode: nym_cli_commands::validator::mixnet::operators::mixnode::MixnetOperatorsMixnode, + network_details: &NymNetworkDetails, +) -> anyhow::Result<()> { + match mixnode.command { + nym_cli_commands::validator::mixnet::operators::mixnode::MixnetOperatorsMixnodeCommands::Keys(keys) => { + keys::execute(keys).await? + } + nym_cli_commands::validator::mixnet::operators::mixnode::MixnetOperatorsMixnodeCommands::Rewards(rewards) => { + rewards::execute(global_args, rewards, network_details).await? + } + nym_cli_commands::validator::mixnet::operators::mixnode::MixnetOperatorsMixnodeCommands::Settings(settings) => { + settings::execute(global_args, settings, network_details).await? + } + nym_cli_commands::validator::mixnet::operators::mixnode::MixnetOperatorsMixnodeCommands::Bond(args) => { + nym_cli_commands::validator::mixnet::operators::mixnode::bond_mixnode::bond_mixnode(args, create_signing_client(global_args, network_details)?).await + } + nym_cli_commands::validator::mixnet::operators::mixnode::MixnetOperatorsMixnodeCommands::Unbound(args) => { + nym_cli_commands::validator::mixnet::operators::mixnode::unbond_mixnode::unbond_mixnode(args, create_signing_client(global_args, network_details)?).await + } + _ => unreachable!(), + } + Ok(()) +} diff --git a/tools/nym-cli/src/validator/mixnet/operators/mixnodes/rewards/mod.rs b/tools/nym-cli/src/validator/mixnet/operators/mixnodes/rewards/mod.rs new file mode 100644 index 0000000000..fb2d241b74 --- /dev/null +++ b/tools/nym-cli/src/validator/mixnet/operators/mixnodes/rewards/mod.rs @@ -0,0 +1,19 @@ +// Copyright 2022 - Nym Technologies SA +// SPDX-License-Identifier: Apache-2.0 + +use network_defaults::NymNetworkDetails; +use nym_cli_commands::context::{create_signing_client, ClientArgs}; + +pub(crate) async fn execute( + global_args: ClientArgs, + rewards: nym_cli_commands::validator::mixnet::operators::mixnode::rewards::MixnetOperatorsMixnodeRewards, + network_details: &NymNetworkDetails, +) -> anyhow::Result<()> { + match rewards.command { + nym_cli_commands::validator::mixnet::operators::mixnode::rewards::MixnetOperatorsMixnodeRewardsCommands::Claim(args) => { + nym_cli_commands::validator::mixnet::operators::mixnode::rewards::claim_operator_reward::claim_operator_reward(args, create_signing_client(global_args, network_details)?).await + } + _ => unreachable!(), + } + Ok(()) +} diff --git a/tools/nym-cli/src/validator/mixnet/operators/mixnodes/settings/mod.rs b/tools/nym-cli/src/validator/mixnet/operators/mixnodes/settings/mod.rs new file mode 100644 index 0000000000..43a579b17b --- /dev/null +++ b/tools/nym-cli/src/validator/mixnet/operators/mixnodes/settings/mod.rs @@ -0,0 +1,19 @@ +// Copyright 2022 - Nym Technologies SA +// SPDX-License-Identifier: Apache-2.0 + +use network_defaults::NymNetworkDetails; +use nym_cli_commands::context::{create_signing_client, ClientArgs}; + +pub(crate) async fn execute( + global_args: ClientArgs, + settings: nym_cli_commands::validator::mixnet::operators::mixnode::settings::MixnetOperatorsMixnodeSettings, + network_details: &NymNetworkDetails, +) -> anyhow::Result<()> { + match settings.command { + nym_cli_commands::validator::mixnet::operators::mixnode::settings::MixnetOperatorsMixnodeSettingsCommands::UpdateProfitPercentage(args) => { + nym_cli_commands::validator::mixnet::operators::mixnode::settings::update_profit_percent::update_profit_percent(args, create_signing_client(global_args, network_details)?).await + } + _ => unreachable!(), + } + Ok(()) +} diff --git a/tools/nym-cli/src/validator/mixnet/operators/mod.rs b/tools/nym-cli/src/validator/mixnet/operators/mod.rs new file mode 100644 index 0000000000..b1706fb6c8 --- /dev/null +++ b/tools/nym-cli/src/validator/mixnet/operators/mod.rs @@ -0,0 +1,24 @@ +// Copyright 2022 - Nym Technologies SA +// SPDX-License-Identifier: Apache-2.0 + +use network_defaults::NymNetworkDetails; +use nym_cli_commands::context::ClientArgs; + +pub(crate) mod gateways; +pub(crate) mod mixnodes; + +pub(crate) async fn execute( + global_args: ClientArgs, + operators: nym_cli_commands::validator::mixnet::operators::MixnetOperators, + network_details: &NymNetworkDetails, +) -> anyhow::Result<()> { + match operators.command { + nym_cli_commands::validator::mixnet::operators::MixnetOperatorsCommands::Gateway( + gateway, + ) => gateways::execute(global_args, gateway, network_details).await?, + nym_cli_commands::validator::mixnet::operators::MixnetOperatorsCommands::Mixnode( + mixnode, + ) => mixnodes::execute(global_args, mixnode, network_details).await?, + } + Ok(()) +} diff --git a/tools/nym-cli/src/validator/mixnet/query/mod.rs b/tools/nym-cli/src/validator/mixnet/query/mod.rs new file mode 100644 index 0000000000..21afb8c833 --- /dev/null +++ b/tools/nym-cli/src/validator/mixnet/query/mod.rs @@ -0,0 +1,28 @@ +// Copyright 2022 - Nym Technologies SA +// SPDX-License-Identifier: Apache-2.0 + +use network_defaults::NymNetworkDetails; +use nym_cli_commands::context::create_query_client_with_validator_api; + +pub(crate) async fn execute( + query: nym_cli_commands::validator::mixnet::query::MixnetQuery, + network_details: &NymNetworkDetails, +) -> anyhow::Result<()> { + match query.command { + nym_cli_commands::validator::mixnet::query::MixnetQueryCommands::Mixnodes(args) => { + nym_cli_commands::validator::mixnet::query::query_all_mixnodes::query( + args, + &create_query_client_with_validator_api(network_details)?, + ) + .await + } + nym_cli_commands::validator::mixnet::query::MixnetQueryCommands::Gateways(args) => { + nym_cli_commands::validator::mixnet::query::query_all_gateways::query( + args, + &create_query_client_with_validator_api(network_details)?, + ) + .await + } + } + Ok(()) +} diff --git a/tools/nym-cli/src/validator/mod.rs b/tools/nym-cli/src/validator/mod.rs new file mode 100644 index 0000000000..0f1ddb6122 --- /dev/null +++ b/tools/nym-cli/src/validator/mod.rs @@ -0,0 +1,10 @@ +// Copyright 2022 - Nym Technologies SA +// SPDX-License-Identifier: Apache-2.0 + +pub(crate) mod account; +pub(crate) mod block; +pub(crate) mod cosmwasm; +pub(crate) mod mixnet; +pub(crate) mod signature; +pub(crate) mod transactions; +pub(crate) mod vesting; diff --git a/tools/nym-cli/src/validator/signature.rs b/tools/nym-cli/src/validator/signature.rs new file mode 100644 index 0000000000..edc237753f --- /dev/null +++ b/tools/nym-cli/src/validator/signature.rs @@ -0,0 +1,30 @@ +// Copyright 2022 - Nym Technologies SA +// SPDX-License-Identifier: Apache-2.0 + +use network_defaults::NymNetworkDetails; +use nym_cli_commands::context::create_query_client; + +pub(crate) async fn execute( + signature: nym_cli_commands::validator::signature::Signature, + network_details: &NymNetworkDetails, + mnemonic: Option, +) -> anyhow::Result<()> { + match signature.command { + Some(nym_cli_commands::validator::signature::SignatureCommands::Sign(args)) => { + nym_cli_commands::validator::signature::sign::sign( + args, + &network_details.chain_details.bech32_account_prefix, + mnemonic, + ) + } + Some(nym_cli_commands::validator::signature::SignatureCommands::Verify(args)) => { + nym_cli_commands::validator::signature::verify::verify( + args, + &create_query_client(network_details)?, + ) + .await + } + _ => unreachable!(), + } + Ok(()) +} diff --git a/tools/nym-cli/src/validator/transactions.rs b/tools/nym-cli/src/validator/transactions.rs new file mode 100644 index 0000000000..05455a3502 --- /dev/null +++ b/tools/nym-cli/src/validator/transactions.rs @@ -0,0 +1,29 @@ +// Copyright 2022 - Nym Technologies SA +// SPDX-License-Identifier: Apache-2.0 + +use network_defaults::NymNetworkDetails; +use nym_cli_commands::context::create_query_client; + +pub(crate) async fn execute( + transactions: nym_cli_commands::validator::transactions::Transactions, + network_details: &NymNetworkDetails, +) -> anyhow::Result<()> { + match transactions.command { + Some(nym_cli_commands::validator::transactions::TransactionsCommands::Get(args)) => { + nym_cli_commands::validator::transactions::get_transaction::get( + args, + &create_query_client(network_details)?, + ) + .await + } + Some(nym_cli_commands::validator::transactions::TransactionsCommands::Query(args)) => { + nym_cli_commands::validator::transactions::query_transactions::query( + args, + &create_query_client(network_details)?, + ) + .await + } + _ => unreachable!(), + } + Ok(()) +} diff --git a/tools/nym-cli/src/validator/vesting.rs b/tools/nym-cli/src/validator/vesting.rs new file mode 100644 index 0000000000..d87ca2c9ff --- /dev/null +++ b/tools/nym-cli/src/validator/vesting.rs @@ -0,0 +1,49 @@ +// Copyright 2022 - Nym Technologies SA +// SPDX-License-Identifier: Apache-2.0 + +use network_defaults::NymNetworkDetails; +use nym_cli_commands::context::{create_signing_client, ClientArgs}; + +pub(crate) async fn execute( + global_args: ClientArgs, + vesting: nym_cli_commands::validator::vesting::VestingSchedule, + network_details: &NymNetworkDetails, +) -> anyhow::Result<()> { + match vesting.command { + Some(nym_cli_commands::validator::vesting::VestingScheduleCommands::Create(args)) => { + nym_cli_commands::validator::vesting::create_vesting_schedule::create( + args, + create_signing_client(global_args, network_details)?, + network_details, + ) + .await + } + Some(nym_cli_commands::validator::vesting::VestingScheduleCommands::Query(args)) => { + nym_cli_commands::validator::vesting::query_vesting_schedule::query( + args, + create_signing_client(global_args, network_details)?, + ) + .await + } + Some(nym_cli_commands::validator::vesting::VestingScheduleCommands::VestedBalance( + args, + )) => { + nym_cli_commands::validator::vesting::balance::balance( + args, + create_signing_client(global_args, network_details)?, + ) + .await + } + Some(nym_cli_commands::validator::vesting::VestingScheduleCommands::WithdrawVested( + args, + )) => { + nym_cli_commands::validator::vesting::withdraw_vested::execute( + args, + create_signing_client(global_args, network_details)?, + ) + .await + } + _ => unreachable!(), + } + Ok(()) +} diff --git a/tools/nym-cli/user-docs/fig-spec.ts b/tools/nym-cli/user-docs/fig-spec.ts new file mode 100644 index 0000000000..95825de55d --- /dev/null +++ b/tools/nym-cli/user-docs/fig-spec.ts @@ -0,0 +1,5048 @@ +const completion: Fig.Spec = { + name: "nym-cli", + description: "A client for interacting with Nym smart contracts and the Nyx blockchain", + subcommands: [ + { + name: "account", + description: "Query and manage Nyx blockchain accounts", + subcommands: [ + { + name: "create", + description: "Create a new mnemonic - note, this account does not appear on the chain until the account id is used in a transaction", + options: [ + { + name: "--word-count", + args: { + name: "word-count", + isOptional: true, + }, + }, + { + name: "--mnemonic", + description: "Provide the mnemonic for your account. You can also provide this is an env var called MNEMONIC.", + args: { + name: "mnemonic", + isOptional: true, + }, + }, + { + name: "--config-env-file", + description: "Overrides configuration as a file of environment variables. Note: individual env vars take precedence over this file.", + args: { + name: "config-env-file", + isOptional: true, + }, + }, + { + name: "--nymd-url", + description: "Overrides the nymd URL provided either as an environment variable NYMD_VALIDATOR or in a config file", + args: { + name: "nymd-url", + isOptional: true, + }, + }, + { + name: "--validator-api-url", + description: "Overrides the validator API URL provided either as an environment variable API_VALIDATOR or in a config file", + args: { + name: "validator-api-url", + isOptional: true, + }, + }, + { + name: "--mixnet-contract-address", + description: "Overrides the mixnet contract address provided either as an environment variable or in a config file", + args: { + name: "mixnet-contract-address", + isOptional: true, + }, + }, + { + name: "--vesting-contract-address", + description: "Overrides the vesting contract address provided either as an environment variable or in a config file", + args: { + name: "vesting-contract-address", + isOptional: true, + }, + }, + { + name: ["-h", "--help"], + description: "Print help information", + }, + ], + }, + { + name: "balance", + description: "Gets the balance of an account", + options: [ + { + name: "--denom", + description: "Optional currency to show balance for", + args: { + name: "denom", + isOptional: true, + }, + }, + { + name: "--mnemonic", + description: "Provide the mnemonic for your account. You can also provide this is an env var called MNEMONIC.", + args: { + name: "mnemonic", + isOptional: true, + }, + }, + { + name: "--config-env-file", + description: "Overrides configuration as a file of environment variables. Note: individual env vars take precedence over this file.", + args: { + name: "config-env-file", + isOptional: true, + }, + }, + { + name: "--nymd-url", + description: "Overrides the nymd URL provided either as an environment variable NYMD_VALIDATOR or in a config file", + args: { + name: "nymd-url", + isOptional: true, + }, + }, + { + name: "--validator-api-url", + description: "Overrides the validator API URL provided either as an environment variable API_VALIDATOR or in a config file", + args: { + name: "validator-api-url", + isOptional: true, + }, + }, + { + name: "--mixnet-contract-address", + description: "Overrides the mixnet contract address provided either as an environment variable or in a config file", + args: { + name: "mixnet-contract-address", + isOptional: true, + }, + }, + { + name: "--vesting-contract-address", + description: "Overrides the vesting contract address provided either as an environment variable or in a config file", + args: { + name: "vesting-contract-address", + isOptional: true, + }, + }, + { + name: "--hide-denom", + description: "Optionally hide the denom", + }, + { + name: "--raw", + description: "Show as a raw value", + }, + { + name: ["-h", "--help"], + description: "Print help information", + }, + ], + args: { + name: "address", + isOptional: true, + }, + }, + { + name: "pub-key", + description: "Gets the public key of an account", + options: [ + { + name: "--mnemonic", + description: "Provide the mnemonic for your account. You can also provide this is an env var called MNEMONIC.", + args: { + name: "mnemonic", + isOptional: true, + }, + }, + { + name: "--config-env-file", + description: "Overrides configuration as a file of environment variables. Note: individual env vars take precedence over this file.", + args: { + name: "config-env-file", + isOptional: true, + }, + }, + { + name: "--nymd-url", + description: "Overrides the nymd URL provided either as an environment variable NYMD_VALIDATOR or in a config file", + args: { + name: "nymd-url", + isOptional: true, + }, + }, + { + name: "--validator-api-url", + description: "Overrides the validator API URL provided either as an environment variable API_VALIDATOR or in a config file", + args: { + name: "validator-api-url", + isOptional: true, + }, + }, + { + name: "--mixnet-contract-address", + description: "Overrides the mixnet contract address provided either as an environment variable or in a config file", + args: { + name: "mixnet-contract-address", + isOptional: true, + }, + }, + { + name: "--vesting-contract-address", + description: "Overrides the vesting contract address provided either as an environment variable or in a config file", + args: { + name: "vesting-contract-address", + isOptional: true, + }, + }, + { + name: "--from-mnemonic", + description: "If set, get the public key from the mnemonic, rather than querying for it", + }, + { + name: ["-h", "--help"], + description: "Print help information", + }, + ], + args: { + name: "address", + isOptional: true, + }, + }, + { + name: "send", + description: "Sends tokens to another account", + options: [ + { + name: "--denom", + description: "Override the denomination", + args: { + name: "denom", + isOptional: true, + }, + }, + { + name: "--memo", + args: { + name: "memo", + isOptional: true, + }, + }, + { + name: "--mnemonic", + description: "Provide the mnemonic for your account. You can also provide this is an env var called MNEMONIC.", + args: { + name: "mnemonic", + isOptional: true, + }, + }, + { + name: "--config-env-file", + description: "Overrides configuration as a file of environment variables. Note: individual env vars take precedence over this file.", + args: { + name: "config-env-file", + isOptional: true, + }, + }, + { + name: "--nymd-url", + description: "Overrides the nymd URL provided either as an environment variable NYMD_VALIDATOR or in a config file", + args: { + name: "nymd-url", + isOptional: true, + }, + }, + { + name: "--validator-api-url", + description: "Overrides the validator API URL provided either as an environment variable API_VALIDATOR or in a config file", + args: { + name: "validator-api-url", + isOptional: true, + }, + }, + { + name: "--mixnet-contract-address", + description: "Overrides the mixnet contract address provided either as an environment variable or in a config file", + args: { + name: "mixnet-contract-address", + isOptional: true, + }, + }, + { + name: "--vesting-contract-address", + description: "Overrides the vesting contract address provided either as an environment variable or in a config file", + args: { + name: "vesting-contract-address", + isOptional: true, + }, + }, + { + name: ["-h", "--help"], + description: "Print help information", + }, + ], + args: [ + { + name: "recipient", + }, + { + name: "amount", + }, + ] + }, + { + name: "help", + description: "Print this message or the help of the given subcommand(s)", + options: [ + { + name: "--mnemonic", + description: "Provide the mnemonic for your account. You can also provide this is an env var called MNEMONIC.", + args: { + name: "mnemonic", + isOptional: true, + }, + }, + { + name: "--config-env-file", + description: "Overrides configuration as a file of environment variables. Note: individual env vars take precedence over this file.", + args: { + name: "config-env-file", + isOptional: true, + }, + }, + { + name: "--nymd-url", + description: "Overrides the nymd URL provided either as an environment variable NYMD_VALIDATOR or in a config file", + args: { + name: "nymd-url", + isOptional: true, + }, + }, + { + name: "--validator-api-url", + description: "Overrides the validator API URL provided either as an environment variable API_VALIDATOR or in a config file", + args: { + name: "validator-api-url", + isOptional: true, + }, + }, + { + name: "--mixnet-contract-address", + description: "Overrides the mixnet contract address provided either as an environment variable or in a config file", + args: { + name: "mixnet-contract-address", + isOptional: true, + }, + }, + { + name: "--vesting-contract-address", + description: "Overrides the vesting contract address provided either as an environment variable or in a config file", + args: { + name: "vesting-contract-address", + isOptional: true, + }, + }, + ], + args: { + name: "subcommand", + isOptional: true, + }, + }, + ], + options: [ + { + name: "--mnemonic", + description: "Provide the mnemonic for your account. You can also provide this is an env var called MNEMONIC.", + args: { + name: "mnemonic", + isOptional: true, + }, + }, + { + name: "--config-env-file", + description: "Overrides configuration as a file of environment variables. Note: individual env vars take precedence over this file.", + args: { + name: "config-env-file", + isOptional: true, + }, + }, + { + name: "--nymd-url", + description: "Overrides the nymd URL provided either as an environment variable NYMD_VALIDATOR or in a config file", + args: { + name: "nymd-url", + isOptional: true, + }, + }, + { + name: "--validator-api-url", + description: "Overrides the validator API URL provided either as an environment variable API_VALIDATOR or in a config file", + args: { + name: "validator-api-url", + isOptional: true, + }, + }, + { + name: "--mixnet-contract-address", + description: "Overrides the mixnet contract address provided either as an environment variable or in a config file", + args: { + name: "mixnet-contract-address", + isOptional: true, + }, + }, + { + name: "--vesting-contract-address", + description: "Overrides the vesting contract address provided either as an environment variable or in a config file", + args: { + name: "vesting-contract-address", + isOptional: true, + }, + }, + { + name: ["-h", "--help"], + description: "Print help information", + }, + ], + }, + { + name: "signature", + description: "Sign and verify messages", + subcommands: [ + { + name: "sign", + description: "Sign a message", + options: [ + { + name: "--mnemonic", + description: "Provide the mnemonic for your account. You can also provide this is an env var called MNEMONIC.", + args: { + name: "mnemonic", + isOptional: true, + }, + }, + { + name: "--config-env-file", + description: "Overrides configuration as a file of environment variables. Note: individual env vars take precedence over this file.", + args: { + name: "config-env-file", + isOptional: true, + }, + }, + { + name: "--nymd-url", + description: "Overrides the nymd URL provided either as an environment variable NYMD_VALIDATOR or in a config file", + args: { + name: "nymd-url", + isOptional: true, + }, + }, + { + name: "--validator-api-url", + description: "Overrides the validator API URL provided either as an environment variable API_VALIDATOR or in a config file", + args: { + name: "validator-api-url", + isOptional: true, + }, + }, + { + name: "--mixnet-contract-address", + description: "Overrides the mixnet contract address provided either as an environment variable or in a config file", + args: { + name: "mixnet-contract-address", + isOptional: true, + }, + }, + { + name: "--vesting-contract-address", + description: "Overrides the vesting contract address provided either as an environment variable or in a config file", + args: { + name: "vesting-contract-address", + isOptional: true, + }, + }, + { + name: ["-h", "--help"], + description: "Print help information", + }, + ], + args: { + name: "message", + }, + }, + { + name: "verify", + description: "Verify a message", + options: [ + { + name: "--mnemonic", + description: "Provide the mnemonic for your account. You can also provide this is an env var called MNEMONIC.", + args: { + name: "mnemonic", + isOptional: true, + }, + }, + { + name: "--config-env-file", + description: "Overrides configuration as a file of environment variables. Note: individual env vars take precedence over this file.", + args: { + name: "config-env-file", + isOptional: true, + }, + }, + { + name: "--nymd-url", + description: "Overrides the nymd URL provided either as an environment variable NYMD_VALIDATOR or in a config file", + args: { + name: "nymd-url", + isOptional: true, + }, + }, + { + name: "--validator-api-url", + description: "Overrides the validator API URL provided either as an environment variable API_VALIDATOR or in a config file", + args: { + name: "validator-api-url", + isOptional: true, + }, + }, + { + name: "--mixnet-contract-address", + description: "Overrides the mixnet contract address provided either as an environment variable or in a config file", + args: { + name: "mixnet-contract-address", + isOptional: true, + }, + }, + { + name: "--vesting-contract-address", + description: "Overrides the vesting contract address provided either as an environment variable or in a config file", + args: { + name: "vesting-contract-address", + isOptional: true, + }, + }, + { + name: ["-h", "--help"], + description: "Print help information", + }, + ], + args: [ + { + name: "public-key-or-address", + }, + { + name: "signature-as-hex", + }, + { + name: "message", + }, + ] + }, + { + name: "help", + description: "Print this message or the help of the given subcommand(s)", + options: [ + { + name: "--mnemonic", + description: "Provide the mnemonic for your account. You can also provide this is an env var called MNEMONIC.", + args: { + name: "mnemonic", + isOptional: true, + }, + }, + { + name: "--config-env-file", + description: "Overrides configuration as a file of environment variables. Note: individual env vars take precedence over this file.", + args: { + name: "config-env-file", + isOptional: true, + }, + }, + { + name: "--nymd-url", + description: "Overrides the nymd URL provided either as an environment variable NYMD_VALIDATOR or in a config file", + args: { + name: "nymd-url", + isOptional: true, + }, + }, + { + name: "--validator-api-url", + description: "Overrides the validator API URL provided either as an environment variable API_VALIDATOR or in a config file", + args: { + name: "validator-api-url", + isOptional: true, + }, + }, + { + name: "--mixnet-contract-address", + description: "Overrides the mixnet contract address provided either as an environment variable or in a config file", + args: { + name: "mixnet-contract-address", + isOptional: true, + }, + }, + { + name: "--vesting-contract-address", + description: "Overrides the vesting contract address provided either as an environment variable or in a config file", + args: { + name: "vesting-contract-address", + isOptional: true, + }, + }, + ], + args: { + name: "subcommand", + isOptional: true, + }, + }, + ], + options: [ + { + name: "--mnemonic", + description: "Provide the mnemonic for your account. You can also provide this is an env var called MNEMONIC.", + args: { + name: "mnemonic", + isOptional: true, + }, + }, + { + name: "--config-env-file", + description: "Overrides configuration as a file of environment variables. Note: individual env vars take precedence over this file.", + args: { + name: "config-env-file", + isOptional: true, + }, + }, + { + name: "--nymd-url", + description: "Overrides the nymd URL provided either as an environment variable NYMD_VALIDATOR or in a config file", + args: { + name: "nymd-url", + isOptional: true, + }, + }, + { + name: "--validator-api-url", + description: "Overrides the validator API URL provided either as an environment variable API_VALIDATOR or in a config file", + args: { + name: "validator-api-url", + isOptional: true, + }, + }, + { + name: "--mixnet-contract-address", + description: "Overrides the mixnet contract address provided either as an environment variable or in a config file", + args: { + name: "mixnet-contract-address", + isOptional: true, + }, + }, + { + name: "--vesting-contract-address", + description: "Overrides the vesting contract address provided either as an environment variable or in a config file", + args: { + name: "vesting-contract-address", + isOptional: true, + }, + }, + { + name: ["-h", "--help"], + description: "Print help information", + }, + ], + }, + { + name: "block", + description: "Query chain blocks", + subcommands: [ + { + name: "get", + description: "Gets a block's details and prints as JSON", + options: [ + { + name: "--mnemonic", + description: "Provide the mnemonic for your account. You can also provide this is an env var called MNEMONIC.", + args: { + name: "mnemonic", + isOptional: true, + }, + }, + { + name: "--config-env-file", + description: "Overrides configuration as a file of environment variables. Note: individual env vars take precedence over this file.", + args: { + name: "config-env-file", + isOptional: true, + }, + }, + { + name: "--nymd-url", + description: "Overrides the nymd URL provided either as an environment variable NYMD_VALIDATOR or in a config file", + args: { + name: "nymd-url", + isOptional: true, + }, + }, + { + name: "--validator-api-url", + description: "Overrides the validator API URL provided either as an environment variable API_VALIDATOR or in a config file", + args: { + name: "validator-api-url", + isOptional: true, + }, + }, + { + name: "--mixnet-contract-address", + description: "Overrides the mixnet contract address provided either as an environment variable or in a config file", + args: { + name: "mixnet-contract-address", + isOptional: true, + }, + }, + { + name: "--vesting-contract-address", + description: "Overrides the vesting contract address provided either as an environment variable or in a config file", + args: { + name: "vesting-contract-address", + isOptional: true, + }, + }, + { + name: ["-h", "--help"], + description: "Print help information", + }, + ], + args: { + name: "height", + }, + }, + { + name: "time", + description: "Gets the block time at a height", + options: [ + { + name: "--mnemonic", + description: "Provide the mnemonic for your account. You can also provide this is an env var called MNEMONIC.", + args: { + name: "mnemonic", + isOptional: true, + }, + }, + { + name: "--config-env-file", + description: "Overrides configuration as a file of environment variables. Note: individual env vars take precedence over this file.", + args: { + name: "config-env-file", + isOptional: true, + }, + }, + { + name: "--nymd-url", + description: "Overrides the nymd URL provided either as an environment variable NYMD_VALIDATOR or in a config file", + args: { + name: "nymd-url", + isOptional: true, + }, + }, + { + name: "--validator-api-url", + description: "Overrides the validator API URL provided either as an environment variable API_VALIDATOR or in a config file", + args: { + name: "validator-api-url", + isOptional: true, + }, + }, + { + name: "--mixnet-contract-address", + description: "Overrides the mixnet contract address provided either as an environment variable or in a config file", + args: { + name: "mixnet-contract-address", + isOptional: true, + }, + }, + { + name: "--vesting-contract-address", + description: "Overrides the vesting contract address provided either as an environment variable or in a config file", + args: { + name: "vesting-contract-address", + isOptional: true, + }, + }, + { + name: ["-h", "--help"], + description: "Print help information", + }, + ], + args: { + name: "height", + }, + }, + { + name: "current-height", + description: "Gets the current block height", + options: [ + { + name: "--mnemonic", + description: "Provide the mnemonic for your account. You can also provide this is an env var called MNEMONIC.", + args: { + name: "mnemonic", + isOptional: true, + }, + }, + { + name: "--config-env-file", + description: "Overrides configuration as a file of environment variables. Note: individual env vars take precedence over this file.", + args: { + name: "config-env-file", + isOptional: true, + }, + }, + { + name: "--nymd-url", + description: "Overrides the nymd URL provided either as an environment variable NYMD_VALIDATOR or in a config file", + args: { + name: "nymd-url", + isOptional: true, + }, + }, + { + name: "--validator-api-url", + description: "Overrides the validator API URL provided either as an environment variable API_VALIDATOR or in a config file", + args: { + name: "validator-api-url", + isOptional: true, + }, + }, + { + name: "--mixnet-contract-address", + description: "Overrides the mixnet contract address provided either as an environment variable or in a config file", + args: { + name: "mixnet-contract-address", + isOptional: true, + }, + }, + { + name: "--vesting-contract-address", + description: "Overrides the vesting contract address provided either as an environment variable or in a config file", + args: { + name: "vesting-contract-address", + isOptional: true, + }, + }, + { + name: ["-h", "--help"], + description: "Print help information", + }, + ], + }, + { + name: "help", + description: "Print this message or the help of the given subcommand(s)", + options: [ + { + name: "--mnemonic", + description: "Provide the mnemonic for your account. You can also provide this is an env var called MNEMONIC.", + args: { + name: "mnemonic", + isOptional: true, + }, + }, + { + name: "--config-env-file", + description: "Overrides configuration as a file of environment variables. Note: individual env vars take precedence over this file.", + args: { + name: "config-env-file", + isOptional: true, + }, + }, + { + name: "--nymd-url", + description: "Overrides the nymd URL provided either as an environment variable NYMD_VALIDATOR or in a config file", + args: { + name: "nymd-url", + isOptional: true, + }, + }, + { + name: "--validator-api-url", + description: "Overrides the validator API URL provided either as an environment variable API_VALIDATOR or in a config file", + args: { + name: "validator-api-url", + isOptional: true, + }, + }, + { + name: "--mixnet-contract-address", + description: "Overrides the mixnet contract address provided either as an environment variable or in a config file", + args: { + name: "mixnet-contract-address", + isOptional: true, + }, + }, + { + name: "--vesting-contract-address", + description: "Overrides the vesting contract address provided either as an environment variable or in a config file", + args: { + name: "vesting-contract-address", + isOptional: true, + }, + }, + ], + args: { + name: "subcommand", + isOptional: true, + }, + }, + ], + options: [ + { + name: "--mnemonic", + description: "Provide the mnemonic for your account. You can also provide this is an env var called MNEMONIC.", + args: { + name: "mnemonic", + isOptional: true, + }, + }, + { + name: "--config-env-file", + description: "Overrides configuration as a file of environment variables. Note: individual env vars take precedence over this file.", + args: { + name: "config-env-file", + isOptional: true, + }, + }, + { + name: "--nymd-url", + description: "Overrides the nymd URL provided either as an environment variable NYMD_VALIDATOR or in a config file", + args: { + name: "nymd-url", + isOptional: true, + }, + }, + { + name: "--validator-api-url", + description: "Overrides the validator API URL provided either as an environment variable API_VALIDATOR or in a config file", + args: { + name: "validator-api-url", + isOptional: true, + }, + }, + { + name: "--mixnet-contract-address", + description: "Overrides the mixnet contract address provided either as an environment variable or in a config file", + args: { + name: "mixnet-contract-address", + isOptional: true, + }, + }, + { + name: "--vesting-contract-address", + description: "Overrides the vesting contract address provided either as an environment variable or in a config file", + args: { + name: "vesting-contract-address", + isOptional: true, + }, + }, + { + name: ["-h", "--help"], + description: "Print help information", + }, + ], + }, + { + name: "cosmwasm", + description: "Manage and execute WASM smart contracts", + subcommands: [ + { + name: "upload", + description: "Upload a smart contract WASM blob", + options: [ + { + name: "--wasm-path", + args: { + name: "wasm-path", + }, + }, + { + name: "--memo", + args: { + name: "memo", + isOptional: true, + }, + }, + { + name: "--mnemonic", + description: "Provide the mnemonic for your account. You can also provide this is an env var called MNEMONIC.", + args: { + name: "mnemonic", + isOptional: true, + }, + }, + { + name: "--config-env-file", + description: "Overrides configuration as a file of environment variables. Note: individual env vars take precedence over this file.", + args: { + name: "config-env-file", + isOptional: true, + }, + }, + { + name: "--nymd-url", + description: "Overrides the nymd URL provided either as an environment variable NYMD_VALIDATOR or in a config file", + args: { + name: "nymd-url", + isOptional: true, + }, + }, + { + name: "--validator-api-url", + description: "Overrides the validator API URL provided either as an environment variable API_VALIDATOR or in a config file", + args: { + name: "validator-api-url", + isOptional: true, + }, + }, + { + name: "--mixnet-contract-address", + description: "Overrides the mixnet contract address provided either as an environment variable or in a config file", + args: { + name: "mixnet-contract-address", + isOptional: true, + }, + }, + { + name: "--vesting-contract-address", + description: "Overrides the vesting contract address provided either as an environment variable or in a config file", + args: { + name: "vesting-contract-address", + isOptional: true, + }, + }, + { + name: ["-h", "--help"], + description: "Print help information", + }, + ], + }, + { + name: "init", + description: "Init a WASM smart contract", + options: [ + { + name: "--memo", + args: { + name: "memo", + isOptional: true, + }, + }, + { + name: "--label", + args: { + name: "label", + isOptional: true, + }, + }, + { + name: "--init-message", + args: { + name: "init-message", + }, + }, + { + name: "--admin", + args: { + name: "admin", + isOptional: true, + }, + }, + { + name: "--funds", + description: "Amount to supply as funds in micro denomination (e.g. unym or unyx)", + args: { + name: "funds", + isOptional: true, + }, + }, + { + name: "--funds-denom", + description: "Set the denomination for the funds", + args: { + name: "funds-denom", + isOptional: true, + }, + }, + { + name: "--mnemonic", + description: "Provide the mnemonic for your account. You can also provide this is an env var called MNEMONIC.", + args: { + name: "mnemonic", + isOptional: true, + }, + }, + { + name: "--config-env-file", + description: "Overrides configuration as a file of environment variables. Note: individual env vars take precedence over this file.", + args: { + name: "config-env-file", + isOptional: true, + }, + }, + { + name: "--nymd-url", + description: "Overrides the nymd URL provided either as an environment variable NYMD_VALIDATOR or in a config file", + args: { + name: "nymd-url", + isOptional: true, + }, + }, + { + name: "--validator-api-url", + description: "Overrides the validator API URL provided either as an environment variable API_VALIDATOR or in a config file", + args: { + name: "validator-api-url", + isOptional: true, + }, + }, + { + name: "--mixnet-contract-address", + description: "Overrides the mixnet contract address provided either as an environment variable or in a config file", + args: { + name: "mixnet-contract-address", + isOptional: true, + }, + }, + { + name: "--vesting-contract-address", + description: "Overrides the vesting contract address provided either as an environment variable or in a config file", + args: { + name: "vesting-contract-address", + isOptional: true, + }, + }, + { + name: ["-h", "--help"], + description: "Print help information", + }, + ], + args: { + name: "code-id", + }, + }, + { + name: "migrate", + description: "Migrate a WASM smart contract", + options: [ + { + name: "--code-id", + args: { + name: "code-id", + }, + }, + { + name: "--memo", + args: { + name: "memo", + isOptional: true, + }, + }, + { + name: "--init-message", + args: { + name: "init-message", + isOptional: true, + }, + }, + { + name: "--mnemonic", + description: "Provide the mnemonic for your account. You can also provide this is an env var called MNEMONIC.", + args: { + name: "mnemonic", + isOptional: true, + }, + }, + { + name: "--config-env-file", + description: "Overrides configuration as a file of environment variables. Note: individual env vars take precedence over this file.", + args: { + name: "config-env-file", + isOptional: true, + }, + }, + { + name: "--nymd-url", + description: "Overrides the nymd URL provided either as an environment variable NYMD_VALIDATOR or in a config file", + args: { + name: "nymd-url", + isOptional: true, + }, + }, + { + name: "--validator-api-url", + description: "Overrides the validator API URL provided either as an environment variable API_VALIDATOR or in a config file", + args: { + name: "validator-api-url", + isOptional: true, + }, + }, + { + name: "--mixnet-contract-address", + description: "Overrides the mixnet contract address provided either as an environment variable or in a config file", + args: { + name: "mixnet-contract-address", + isOptional: true, + }, + }, + { + name: "--vesting-contract-address", + description: "Overrides the vesting contract address provided either as an environment variable or in a config file", + args: { + name: "vesting-contract-address", + isOptional: true, + }, + }, + { + name: ["-h", "--help"], + description: "Print help information", + }, + ], + args: { + name: "contract-address", + }, + }, + { + name: "execute", + description: "Execute a WASM smart contract method", + options: [ + { + name: "--memo", + args: { + name: "memo", + isOptional: true, + }, + }, + { + name: "--funds-denom", + description: "Set the denomination for the funds", + args: { + name: "funds-denom", + isOptional: true, + }, + }, + { + name: "--mnemonic", + description: "Provide the mnemonic for your account. You can also provide this is an env var called MNEMONIC.", + args: { + name: "mnemonic", + isOptional: true, + }, + }, + { + name: "--config-env-file", + description: "Overrides configuration as a file of environment variables. Note: individual env vars take precedence over this file.", + args: { + name: "config-env-file", + isOptional: true, + }, + }, + { + name: "--nymd-url", + description: "Overrides the nymd URL provided either as an environment variable NYMD_VALIDATOR or in a config file", + args: { + name: "nymd-url", + isOptional: true, + }, + }, + { + name: "--validator-api-url", + description: "Overrides the validator API URL provided either as an environment variable API_VALIDATOR or in a config file", + args: { + name: "validator-api-url", + isOptional: true, + }, + }, + { + name: "--mixnet-contract-address", + description: "Overrides the mixnet contract address provided either as an environment variable or in a config file", + args: { + name: "mixnet-contract-address", + isOptional: true, + }, + }, + { + name: "--vesting-contract-address", + description: "Overrides the vesting contract address provided either as an environment variable or in a config file", + args: { + name: "vesting-contract-address", + isOptional: true, + }, + }, + { + name: ["-h", "--help"], + description: "Print help information", + }, + ], + args: [ + { + name: "contract-address", + }, + { + name: "json-args", + }, + { + name: "funds", + isOptional: true, + }, + ] + }, + { + name: "help", + description: "Print this message or the help of the given subcommand(s)", + options: [ + { + name: "--mnemonic", + description: "Provide the mnemonic for your account. You can also provide this is an env var called MNEMONIC.", + args: { + name: "mnemonic", + isOptional: true, + }, + }, + { + name: "--config-env-file", + description: "Overrides configuration as a file of environment variables. Note: individual env vars take precedence over this file.", + args: { + name: "config-env-file", + isOptional: true, + }, + }, + { + name: "--nymd-url", + description: "Overrides the nymd URL provided either as an environment variable NYMD_VALIDATOR or in a config file", + args: { + name: "nymd-url", + isOptional: true, + }, + }, + { + name: "--validator-api-url", + description: "Overrides the validator API URL provided either as an environment variable API_VALIDATOR or in a config file", + args: { + name: "validator-api-url", + isOptional: true, + }, + }, + { + name: "--mixnet-contract-address", + description: "Overrides the mixnet contract address provided either as an environment variable or in a config file", + args: { + name: "mixnet-contract-address", + isOptional: true, + }, + }, + { + name: "--vesting-contract-address", + description: "Overrides the vesting contract address provided either as an environment variable or in a config file", + args: { + name: "vesting-contract-address", + isOptional: true, + }, + }, + ], + args: { + name: "subcommand", + isOptional: true, + }, + }, + ], + options: [ + { + name: "--mnemonic", + description: "Provide the mnemonic for your account. You can also provide this is an env var called MNEMONIC.", + args: { + name: "mnemonic", + isOptional: true, + }, + }, + { + name: "--config-env-file", + description: "Overrides configuration as a file of environment variables. Note: individual env vars take precedence over this file.", + args: { + name: "config-env-file", + isOptional: true, + }, + }, + { + name: "--nymd-url", + description: "Overrides the nymd URL provided either as an environment variable NYMD_VALIDATOR or in a config file", + args: { + name: "nymd-url", + isOptional: true, + }, + }, + { + name: "--validator-api-url", + description: "Overrides the validator API URL provided either as an environment variable API_VALIDATOR or in a config file", + args: { + name: "validator-api-url", + isOptional: true, + }, + }, + { + name: "--mixnet-contract-address", + description: "Overrides the mixnet contract address provided either as an environment variable or in a config file", + args: { + name: "mixnet-contract-address", + isOptional: true, + }, + }, + { + name: "--vesting-contract-address", + description: "Overrides the vesting contract address provided either as an environment variable or in a config file", + args: { + name: "vesting-contract-address", + isOptional: true, + }, + }, + { + name: ["-h", "--help"], + description: "Print help information", + }, + ], + }, + { + name: "tx", + description: "Query for transactions", + subcommands: [ + { + name: "get", + description: "Get a transaction by hash or block height", + options: [ + { + name: "--mnemonic", + description: "Provide the mnemonic for your account. You can also provide this is an env var called MNEMONIC.", + args: { + name: "mnemonic", + isOptional: true, + }, + }, + { + name: "--config-env-file", + description: "Overrides configuration as a file of environment variables. Note: individual env vars take precedence over this file.", + args: { + name: "config-env-file", + isOptional: true, + }, + }, + { + name: "--nymd-url", + description: "Overrides the nymd URL provided either as an environment variable NYMD_VALIDATOR or in a config file", + args: { + name: "nymd-url", + isOptional: true, + }, + }, + { + name: "--validator-api-url", + description: "Overrides the validator API URL provided either as an environment variable API_VALIDATOR or in a config file", + args: { + name: "validator-api-url", + isOptional: true, + }, + }, + { + name: "--mixnet-contract-address", + description: "Overrides the mixnet contract address provided either as an environment variable or in a config file", + args: { + name: "mixnet-contract-address", + isOptional: true, + }, + }, + { + name: "--vesting-contract-address", + description: "Overrides the vesting contract address provided either as an environment variable or in a config file", + args: { + name: "vesting-contract-address", + isOptional: true, + }, + }, + { + name: ["-h", "--help"], + description: "Print help information", + }, + ], + args: { + name: "tx-hash", + }, + }, + { + name: "query", + description: "Query for transactions", + options: [ + { + name: "--mnemonic", + description: "Provide the mnemonic for your account. You can also provide this is an env var called MNEMONIC.", + args: { + name: "mnemonic", + isOptional: true, + }, + }, + { + name: "--config-env-file", + description: "Overrides configuration as a file of environment variables. Note: individual env vars take precedence over this file.", + args: { + name: "config-env-file", + isOptional: true, + }, + }, + { + name: "--nymd-url", + description: "Overrides the nymd URL provided either as an environment variable NYMD_VALIDATOR or in a config file", + args: { + name: "nymd-url", + isOptional: true, + }, + }, + { + name: "--validator-api-url", + description: "Overrides the validator API URL provided either as an environment variable API_VALIDATOR or in a config file", + args: { + name: "validator-api-url", + isOptional: true, + }, + }, + { + name: "--mixnet-contract-address", + description: "Overrides the mixnet contract address provided either as an environment variable or in a config file", + args: { + name: "mixnet-contract-address", + isOptional: true, + }, + }, + { + name: "--vesting-contract-address", + description: "Overrides the vesting contract address provided either as an environment variable or in a config file", + args: { + name: "vesting-contract-address", + isOptional: true, + }, + }, + { + name: ["-h", "--help"], + description: "Print help information", + }, + ], + args: { + name: "query", + }, + }, + { + name: "help", + description: "Print this message or the help of the given subcommand(s)", + options: [ + { + name: "--mnemonic", + description: "Provide the mnemonic for your account. You can also provide this is an env var called MNEMONIC.", + args: { + name: "mnemonic", + isOptional: true, + }, + }, + { + name: "--config-env-file", + description: "Overrides configuration as a file of environment variables. Note: individual env vars take precedence over this file.", + args: { + name: "config-env-file", + isOptional: true, + }, + }, + { + name: "--nymd-url", + description: "Overrides the nymd URL provided either as an environment variable NYMD_VALIDATOR or in a config file", + args: { + name: "nymd-url", + isOptional: true, + }, + }, + { + name: "--validator-api-url", + description: "Overrides the validator API URL provided either as an environment variable API_VALIDATOR or in a config file", + args: { + name: "validator-api-url", + isOptional: true, + }, + }, + { + name: "--mixnet-contract-address", + description: "Overrides the mixnet contract address provided either as an environment variable or in a config file", + args: { + name: "mixnet-contract-address", + isOptional: true, + }, + }, + { + name: "--vesting-contract-address", + description: "Overrides the vesting contract address provided either as an environment variable or in a config file", + args: { + name: "vesting-contract-address", + isOptional: true, + }, + }, + ], + args: { + name: "subcommand", + isOptional: true, + }, + }, + ], + options: [ + { + name: "--mnemonic", + description: "Provide the mnemonic for your account. You can also provide this is an env var called MNEMONIC.", + args: { + name: "mnemonic", + isOptional: true, + }, + }, + { + name: "--config-env-file", + description: "Overrides configuration as a file of environment variables. Note: individual env vars take precedence over this file.", + args: { + name: "config-env-file", + isOptional: true, + }, + }, + { + name: "--nymd-url", + description: "Overrides the nymd URL provided either as an environment variable NYMD_VALIDATOR or in a config file", + args: { + name: "nymd-url", + isOptional: true, + }, + }, + { + name: "--validator-api-url", + description: "Overrides the validator API URL provided either as an environment variable API_VALIDATOR or in a config file", + args: { + name: "validator-api-url", + isOptional: true, + }, + }, + { + name: "--mixnet-contract-address", + description: "Overrides the mixnet contract address provided either as an environment variable or in a config file", + args: { + name: "mixnet-contract-address", + isOptional: true, + }, + }, + { + name: "--vesting-contract-address", + description: "Overrides the vesting contract address provided either as an environment variable or in a config file", + args: { + name: "vesting-contract-address", + isOptional: true, + }, + }, + { + name: ["-h", "--help"], + description: "Print help information", + }, + ], + }, + { + name: "vesting-schedule", + description: "Create and query for a vesting schedule", + subcommands: [ + { + name: "create", + description: "Creates a vesting schedule", + options: [ + { + name: "--periods-seconds", + args: { + name: "periods-seconds", + isOptional: true, + }, + }, + { + name: "--number-of-periods", + args: { + name: "number-of-periods", + isOptional: true, + }, + }, + { + name: "--start-time", + args: { + name: "start-time", + isOptional: true, + }, + }, + { + name: "--address", + args: { + name: "address", + }, + }, + { + name: "--amount", + args: { + name: "amount", + }, + }, + { + name: "--staking-address", + args: { + name: "staking-address", + isOptional: true, + }, + }, + { + name: "--mnemonic", + description: "Provide the mnemonic for your account. You can also provide this is an env var called MNEMONIC.", + args: { + name: "mnemonic", + isOptional: true, + }, + }, + { + name: "--config-env-file", + description: "Overrides configuration as a file of environment variables. Note: individual env vars take precedence over this file.", + args: { + name: "config-env-file", + isOptional: true, + }, + }, + { + name: "--nymd-url", + description: "Overrides the nymd URL provided either as an environment variable NYMD_VALIDATOR or in a config file", + args: { + name: "nymd-url", + isOptional: true, + }, + }, + { + name: "--validator-api-url", + description: "Overrides the validator API URL provided either as an environment variable API_VALIDATOR or in a config file", + args: { + name: "validator-api-url", + isOptional: true, + }, + }, + { + name: "--mixnet-contract-address", + description: "Overrides the mixnet contract address provided either as an environment variable or in a config file", + args: { + name: "mixnet-contract-address", + isOptional: true, + }, + }, + { + name: "--vesting-contract-address", + description: "Overrides the vesting contract address provided either as an environment variable or in a config file", + args: { + name: "vesting-contract-address", + isOptional: true, + }, + }, + { + name: ["-h", "--help"], + description: "Print help information", + }, + ], + }, + { + name: "query", + description: "Query for vesting schedule", + options: [ + { + name: "--mnemonic", + description: "Provide the mnemonic for your account. You can also provide this is an env var called MNEMONIC.", + args: { + name: "mnemonic", + isOptional: true, + }, + }, + { + name: "--config-env-file", + description: "Overrides configuration as a file of environment variables. Note: individual env vars take precedence over this file.", + args: { + name: "config-env-file", + isOptional: true, + }, + }, + { + name: "--nymd-url", + description: "Overrides the nymd URL provided either as an environment variable NYMD_VALIDATOR or in a config file", + args: { + name: "nymd-url", + isOptional: true, + }, + }, + { + name: "--validator-api-url", + description: "Overrides the validator API URL provided either as an environment variable API_VALIDATOR or in a config file", + args: { + name: "validator-api-url", + isOptional: true, + }, + }, + { + name: "--mixnet-contract-address", + description: "Overrides the mixnet contract address provided either as an environment variable or in a config file", + args: { + name: "mixnet-contract-address", + isOptional: true, + }, + }, + { + name: "--vesting-contract-address", + description: "Overrides the vesting contract address provided either as an environment variable or in a config file", + args: { + name: "vesting-contract-address", + isOptional: true, + }, + }, + { + name: ["-h", "--help"], + description: "Print help information", + }, + ], + args: { + name: "address", + isOptional: true, + }, + }, + { + name: "vested-balance", + description: "Get the amount that has vested and is free for withdrawal, delegation or bonding", + options: [ + { + name: "--mnemonic", + description: "Provide the mnemonic for your account. You can also provide this is an env var called MNEMONIC.", + args: { + name: "mnemonic", + isOptional: true, + }, + }, + { + name: "--config-env-file", + description: "Overrides configuration as a file of environment variables. Note: individual env vars take precedence over this file.", + args: { + name: "config-env-file", + isOptional: true, + }, + }, + { + name: "--nymd-url", + description: "Overrides the nymd URL provided either as an environment variable NYMD_VALIDATOR or in a config file", + args: { + name: "nymd-url", + isOptional: true, + }, + }, + { + name: "--validator-api-url", + description: "Overrides the validator API URL provided either as an environment variable API_VALIDATOR or in a config file", + args: { + name: "validator-api-url", + isOptional: true, + }, + }, + { + name: "--mixnet-contract-address", + description: "Overrides the mixnet contract address provided either as an environment variable or in a config file", + args: { + name: "mixnet-contract-address", + isOptional: true, + }, + }, + { + name: "--vesting-contract-address", + description: "Overrides the vesting contract address provided either as an environment variable or in a config file", + args: { + name: "vesting-contract-address", + isOptional: true, + }, + }, + { + name: ["-h", "--help"], + description: "Print help information", + }, + ], + args: { + name: "address", + isOptional: true, + }, + }, + { + name: "withdraw-vested", + description: "Withdraw vested tokens (note: the available amount excludes anything delegated or bonded before or after vesting)", + options: [ + { + name: "--mnemonic", + description: "Provide the mnemonic for your account. You can also provide this is an env var called MNEMONIC.", + args: { + name: "mnemonic", + isOptional: true, + }, + }, + { + name: "--config-env-file", + description: "Overrides configuration as a file of environment variables. Note: individual env vars take precedence over this file.", + args: { + name: "config-env-file", + isOptional: true, + }, + }, + { + name: "--nymd-url", + description: "Overrides the nymd URL provided either as an environment variable NYMD_VALIDATOR or in a config file", + args: { + name: "nymd-url", + isOptional: true, + }, + }, + { + name: "--validator-api-url", + description: "Overrides the validator API URL provided either as an environment variable API_VALIDATOR or in a config file", + args: { + name: "validator-api-url", + isOptional: true, + }, + }, + { + name: "--mixnet-contract-address", + description: "Overrides the mixnet contract address provided either as an environment variable or in a config file", + args: { + name: "mixnet-contract-address", + isOptional: true, + }, + }, + { + name: "--vesting-contract-address", + description: "Overrides the vesting contract address provided either as an environment variable or in a config file", + args: { + name: "vesting-contract-address", + isOptional: true, + }, + }, + { + name: ["-h", "--help"], + description: "Print help information", + }, + ], + args: { + name: "amount", + }, + }, + { + name: "help", + description: "Print this message or the help of the given subcommand(s)", + options: [ + { + name: "--mnemonic", + description: "Provide the mnemonic for your account. You can also provide this is an env var called MNEMONIC.", + args: { + name: "mnemonic", + isOptional: true, + }, + }, + { + name: "--config-env-file", + description: "Overrides configuration as a file of environment variables. Note: individual env vars take precedence over this file.", + args: { + name: "config-env-file", + isOptional: true, + }, + }, + { + name: "--nymd-url", + description: "Overrides the nymd URL provided either as an environment variable NYMD_VALIDATOR or in a config file", + args: { + name: "nymd-url", + isOptional: true, + }, + }, + { + name: "--validator-api-url", + description: "Overrides the validator API URL provided either as an environment variable API_VALIDATOR or in a config file", + args: { + name: "validator-api-url", + isOptional: true, + }, + }, + { + name: "--mixnet-contract-address", + description: "Overrides the mixnet contract address provided either as an environment variable or in a config file", + args: { + name: "mixnet-contract-address", + isOptional: true, + }, + }, + { + name: "--vesting-contract-address", + description: "Overrides the vesting contract address provided either as an environment variable or in a config file", + args: { + name: "vesting-contract-address", + isOptional: true, + }, + }, + ], + args: { + name: "subcommand", + isOptional: true, + }, + }, + ], + options: [ + { + name: "--mnemonic", + description: "Provide the mnemonic for your account. You can also provide this is an env var called MNEMONIC.", + args: { + name: "mnemonic", + isOptional: true, + }, + }, + { + name: "--config-env-file", + description: "Overrides configuration as a file of environment variables. Note: individual env vars take precedence over this file.", + args: { + name: "config-env-file", + isOptional: true, + }, + }, + { + name: "--nymd-url", + description: "Overrides the nymd URL provided either as an environment variable NYMD_VALIDATOR or in a config file", + args: { + name: "nymd-url", + isOptional: true, + }, + }, + { + name: "--validator-api-url", + description: "Overrides the validator API URL provided either as an environment variable API_VALIDATOR or in a config file", + args: { + name: "validator-api-url", + isOptional: true, + }, + }, + { + name: "--mixnet-contract-address", + description: "Overrides the mixnet contract address provided either as an environment variable or in a config file", + args: { + name: "mixnet-contract-address", + isOptional: true, + }, + }, + { + name: "--vesting-contract-address", + description: "Overrides the vesting contract address provided either as an environment variable or in a config file", + args: { + name: "vesting-contract-address", + isOptional: true, + }, + }, + { + name: ["-h", "--help"], + description: "Print help information", + }, + ], + }, + { + name: "mixnet", + description: "Manage your mixnet infrastructure, delegate stake or query the directory", + subcommands: [ + { + name: "query", + description: "Query the mixnet directory", + subcommands: [ + { + name: "mixnodes", + description: "Query mixnodes", + options: [ + { + name: "--mnemonic", + description: "Provide the mnemonic for your account. You can also provide this is an env var called MNEMONIC.", + args: { + name: "mnemonic", + isOptional: true, + }, + }, + { + name: "--config-env-file", + description: "Overrides configuration as a file of environment variables. Note: individual env vars take precedence over this file.", + args: { + name: "config-env-file", + isOptional: true, + }, + }, + { + name: "--nymd-url", + description: "Overrides the nymd URL provided either as an environment variable NYMD_VALIDATOR or in a config file", + args: { + name: "nymd-url", + isOptional: true, + }, + }, + { + name: "--validator-api-url", + description: "Overrides the validator API URL provided either as an environment variable API_VALIDATOR or in a config file", + args: { + name: "validator-api-url", + isOptional: true, + }, + }, + { + name: "--mixnet-contract-address", + description: "Overrides the mixnet contract address provided either as an environment variable or in a config file", + args: { + name: "mixnet-contract-address", + isOptional: true, + }, + }, + { + name: "--vesting-contract-address", + description: "Overrides the vesting contract address provided either as an environment variable or in a config file", + args: { + name: "vesting-contract-address", + isOptional: true, + }, + }, + { + name: ["-h", "--help"], + description: "Print help information", + }, + ], + args: { + name: "identity-key", + isOptional: true, + }, + }, + { + name: "gateways", + description: "Query gateways", + options: [ + { + name: "--mnemonic", + description: "Provide the mnemonic for your account. You can also provide this is an env var called MNEMONIC.", + args: { + name: "mnemonic", + isOptional: true, + }, + }, + { + name: "--config-env-file", + description: "Overrides configuration as a file of environment variables. Note: individual env vars take precedence over this file.", + args: { + name: "config-env-file", + isOptional: true, + }, + }, + { + name: "--nymd-url", + description: "Overrides the nymd URL provided either as an environment variable NYMD_VALIDATOR or in a config file", + args: { + name: "nymd-url", + isOptional: true, + }, + }, + { + name: "--validator-api-url", + description: "Overrides the validator API URL provided either as an environment variable API_VALIDATOR or in a config file", + args: { + name: "validator-api-url", + isOptional: true, + }, + }, + { + name: "--mixnet-contract-address", + description: "Overrides the mixnet contract address provided either as an environment variable or in a config file", + args: { + name: "mixnet-contract-address", + isOptional: true, + }, + }, + { + name: "--vesting-contract-address", + description: "Overrides the vesting contract address provided either as an environment variable or in a config file", + args: { + name: "vesting-contract-address", + isOptional: true, + }, + }, + { + name: ["-h", "--help"], + description: "Print help information", + }, + ], + args: { + name: "identity-key", + isOptional: true, + }, + }, + { + name: "help", + description: "Print this message or the help of the given subcommand(s)", + options: [ + { + name: "--mnemonic", + description: "Provide the mnemonic for your account. You can also provide this is an env var called MNEMONIC.", + args: { + name: "mnemonic", + isOptional: true, + }, + }, + { + name: "--config-env-file", + description: "Overrides configuration as a file of environment variables. Note: individual env vars take precedence over this file.", + args: { + name: "config-env-file", + isOptional: true, + }, + }, + { + name: "--nymd-url", + description: "Overrides the nymd URL provided either as an environment variable NYMD_VALIDATOR or in a config file", + args: { + name: "nymd-url", + isOptional: true, + }, + }, + { + name: "--validator-api-url", + description: "Overrides the validator API URL provided either as an environment variable API_VALIDATOR or in a config file", + args: { + name: "validator-api-url", + isOptional: true, + }, + }, + { + name: "--mixnet-contract-address", + description: "Overrides the mixnet contract address provided either as an environment variable or in a config file", + args: { + name: "mixnet-contract-address", + isOptional: true, + }, + }, + { + name: "--vesting-contract-address", + description: "Overrides the vesting contract address provided either as an environment variable or in a config file", + args: { + name: "vesting-contract-address", + isOptional: true, + }, + }, + ], + args: { + name: "subcommand", + isOptional: true, + }, + }, + ], + options: [ + { + name: "--mnemonic", + description: "Provide the mnemonic for your account. You can also provide this is an env var called MNEMONIC.", + args: { + name: "mnemonic", + isOptional: true, + }, + }, + { + name: "--config-env-file", + description: "Overrides configuration as a file of environment variables. Note: individual env vars take precedence over this file.", + args: { + name: "config-env-file", + isOptional: true, + }, + }, + { + name: "--nymd-url", + description: "Overrides the nymd URL provided either as an environment variable NYMD_VALIDATOR or in a config file", + args: { + name: "nymd-url", + isOptional: true, + }, + }, + { + name: "--validator-api-url", + description: "Overrides the validator API URL provided either as an environment variable API_VALIDATOR or in a config file", + args: { + name: "validator-api-url", + isOptional: true, + }, + }, + { + name: "--mixnet-contract-address", + description: "Overrides the mixnet contract address provided either as an environment variable or in a config file", + args: { + name: "mixnet-contract-address", + isOptional: true, + }, + }, + { + name: "--vesting-contract-address", + description: "Overrides the vesting contract address provided either as an environment variable or in a config file", + args: { + name: "vesting-contract-address", + isOptional: true, + }, + }, + { + name: ["-h", "--help"], + description: "Print help information", + }, + ], + }, + { + name: "delegators", + description: "Manage your delegations", + subcommands: [ + { + name: "list", + description: "Lists current delegations", + options: [ + { + name: "--mnemonic", + description: "Provide the mnemonic for your account. You can also provide this is an env var called MNEMONIC.", + args: { + name: "mnemonic", + isOptional: true, + }, + }, + { + name: "--config-env-file", + description: "Overrides configuration as a file of environment variables. Note: individual env vars take precedence over this file.", + args: { + name: "config-env-file", + isOptional: true, + }, + }, + { + name: "--nymd-url", + description: "Overrides the nymd URL provided either as an environment variable NYMD_VALIDATOR or in a config file", + args: { + name: "nymd-url", + isOptional: true, + }, + }, + { + name: "--validator-api-url", + description: "Overrides the validator API URL provided either as an environment variable API_VALIDATOR or in a config file", + args: { + name: "validator-api-url", + isOptional: true, + }, + }, + { + name: "--mixnet-contract-address", + description: "Overrides the mixnet contract address provided either as an environment variable or in a config file", + args: { + name: "mixnet-contract-address", + isOptional: true, + }, + }, + { + name: "--vesting-contract-address", + description: "Overrides the vesting contract address provided either as an environment variable or in a config file", + args: { + name: "vesting-contract-address", + isOptional: true, + }, + }, + { + name: ["-h", "--help"], + description: "Print help information", + }, + ], + }, + { + name: "rewards", + description: "Manage rewards from delegations", + subcommands: [ + { + name: "claim", + description: "Claim rewards accumulated during the delegation of unlocked tokens", + options: [ + { + name: "--identity-key", + args: { + name: "identity-key", + }, + }, + { + name: "--mnemonic", + description: "Provide the mnemonic for your account. You can also provide this is an env var called MNEMONIC.", + args: { + name: "mnemonic", + isOptional: true, + }, + }, + { + name: "--config-env-file", + description: "Overrides configuration as a file of environment variables. Note: individual env vars take precedence over this file.", + args: { + name: "config-env-file", + isOptional: true, + }, + }, + { + name: "--nymd-url", + description: "Overrides the nymd URL provided either as an environment variable NYMD_VALIDATOR or in a config file", + args: { + name: "nymd-url", + isOptional: true, + }, + }, + { + name: "--validator-api-url", + description: "Overrides the validator API URL provided either as an environment variable API_VALIDATOR or in a config file", + args: { + name: "validator-api-url", + isOptional: true, + }, + }, + { + name: "--mixnet-contract-address", + description: "Overrides the mixnet contract address provided either as an environment variable or in a config file", + args: { + name: "mixnet-contract-address", + isOptional: true, + }, + }, + { + name: "--vesting-contract-address", + description: "Overrides the vesting contract address provided either as an environment variable or in a config file", + args: { + name: "vesting-contract-address", + isOptional: true, + }, + }, + { + name: ["-h", "--help"], + description: "Print help information", + }, + ], + }, + { + name: "vesting-claim", + description: "Claim rewards accumulated during the delegation of locked tokens", + options: [ + { + name: "--identity", + args: { + name: "identity", + }, + }, + { + name: "--mnemonic", + description: "Provide the mnemonic for your account. You can also provide this is an env var called MNEMONIC.", + args: { + name: "mnemonic", + isOptional: true, + }, + }, + { + name: "--config-env-file", + description: "Overrides configuration as a file of environment variables. Note: individual env vars take precedence over this file.", + args: { + name: "config-env-file", + isOptional: true, + }, + }, + { + name: "--nymd-url", + description: "Overrides the nymd URL provided either as an environment variable NYMD_VALIDATOR or in a config file", + args: { + name: "nymd-url", + isOptional: true, + }, + }, + { + name: "--validator-api-url", + description: "Overrides the validator API URL provided either as an environment variable API_VALIDATOR or in a config file", + args: { + name: "validator-api-url", + isOptional: true, + }, + }, + { + name: "--mixnet-contract-address", + description: "Overrides the mixnet contract address provided either as an environment variable or in a config file", + args: { + name: "mixnet-contract-address", + isOptional: true, + }, + }, + { + name: "--vesting-contract-address", + description: "Overrides the vesting contract address provided either as an environment variable or in a config file", + args: { + name: "vesting-contract-address", + isOptional: true, + }, + }, + { + name: ["-h", "--help"], + description: "Print help information", + }, + ], + }, + { + name: "help", + description: "Print this message or the help of the given subcommand(s)", + options: [ + { + name: "--mnemonic", + description: "Provide the mnemonic for your account. You can also provide this is an env var called MNEMONIC.", + args: { + name: "mnemonic", + isOptional: true, + }, + }, + { + name: "--config-env-file", + description: "Overrides configuration as a file of environment variables. Note: individual env vars take precedence over this file.", + args: { + name: "config-env-file", + isOptional: true, + }, + }, + { + name: "--nymd-url", + description: "Overrides the nymd URL provided either as an environment variable NYMD_VALIDATOR or in a config file", + args: { + name: "nymd-url", + isOptional: true, + }, + }, + { + name: "--validator-api-url", + description: "Overrides the validator API URL provided either as an environment variable API_VALIDATOR or in a config file", + args: { + name: "validator-api-url", + isOptional: true, + }, + }, + { + name: "--mixnet-contract-address", + description: "Overrides the mixnet contract address provided either as an environment variable or in a config file", + args: { + name: "mixnet-contract-address", + isOptional: true, + }, + }, + { + name: "--vesting-contract-address", + description: "Overrides the vesting contract address provided either as an environment variable or in a config file", + args: { + name: "vesting-contract-address", + isOptional: true, + }, + }, + ], + args: { + name: "subcommand", + isOptional: true, + }, + }, + ], + options: [ + { + name: "--mnemonic", + description: "Provide the mnemonic for your account. You can also provide this is an env var called MNEMONIC.", + args: { + name: "mnemonic", + isOptional: true, + }, + }, + { + name: "--config-env-file", + description: "Overrides configuration as a file of environment variables. Note: individual env vars take precedence over this file.", + args: { + name: "config-env-file", + isOptional: true, + }, + }, + { + name: "--nymd-url", + description: "Overrides the nymd URL provided either as an environment variable NYMD_VALIDATOR or in a config file", + args: { + name: "nymd-url", + isOptional: true, + }, + }, + { + name: "--validator-api-url", + description: "Overrides the validator API URL provided either as an environment variable API_VALIDATOR or in a config file", + args: { + name: "validator-api-url", + isOptional: true, + }, + }, + { + name: "--mixnet-contract-address", + description: "Overrides the mixnet contract address provided either as an environment variable or in a config file", + args: { + name: "mixnet-contract-address", + isOptional: true, + }, + }, + { + name: "--vesting-contract-address", + description: "Overrides the vesting contract address provided either as an environment variable or in a config file", + args: { + name: "vesting-contract-address", + isOptional: true, + }, + }, + { + name: ["-h", "--help"], + description: "Print help information", + }, + ], + }, + { + name: "delegate", + description: "Delegate to a mixnode", + options: [ + { + name: "--identity-key", + args: { + name: "identity-key", + }, + }, + { + name: "--amount", + args: { + name: "amount", + }, + }, + { + name: "--mnemonic", + description: "Provide the mnemonic for your account. You can also provide this is an env var called MNEMONIC.", + args: { + name: "mnemonic", + isOptional: true, + }, + }, + { + name: "--config-env-file", + description: "Overrides configuration as a file of environment variables. Note: individual env vars take precedence over this file.", + args: { + name: "config-env-file", + isOptional: true, + }, + }, + { + name: "--nymd-url", + description: "Overrides the nymd URL provided either as an environment variable NYMD_VALIDATOR or in a config file", + args: { + name: "nymd-url", + isOptional: true, + }, + }, + { + name: "--validator-api-url", + description: "Overrides the validator API URL provided either as an environment variable API_VALIDATOR or in a config file", + args: { + name: "validator-api-url", + isOptional: true, + }, + }, + { + name: "--mixnet-contract-address", + description: "Overrides the mixnet contract address provided either as an environment variable or in a config file", + args: { + name: "mixnet-contract-address", + isOptional: true, + }, + }, + { + name: "--vesting-contract-address", + description: "Overrides the vesting contract address provided either as an environment variable or in a config file", + args: { + name: "vesting-contract-address", + isOptional: true, + }, + }, + { + name: ["-h", "--help"], + description: "Print help information", + }, + ], + }, + { + name: "undelegate", + description: "Undelegate from a mixnode", + options: [ + { + name: "--identity-key", + args: { + name: "identity-key", + }, + }, + { + name: "--mnemonic", + description: "Provide the mnemonic for your account. You can also provide this is an env var called MNEMONIC.", + args: { + name: "mnemonic", + isOptional: true, + }, + }, + { + name: "--config-env-file", + description: "Overrides configuration as a file of environment variables. Note: individual env vars take precedence over this file.", + args: { + name: "config-env-file", + isOptional: true, + }, + }, + { + name: "--nymd-url", + description: "Overrides the nymd URL provided either as an environment variable NYMD_VALIDATOR or in a config file", + args: { + name: "nymd-url", + isOptional: true, + }, + }, + { + name: "--validator-api-url", + description: "Overrides the validator API URL provided either as an environment variable API_VALIDATOR or in a config file", + args: { + name: "validator-api-url", + isOptional: true, + }, + }, + { + name: "--mixnet-contract-address", + description: "Overrides the mixnet contract address provided either as an environment variable or in a config file", + args: { + name: "mixnet-contract-address", + isOptional: true, + }, + }, + { + name: "--vesting-contract-address", + description: "Overrides the vesting contract address provided either as an environment variable or in a config file", + args: { + name: "vesting-contract-address", + isOptional: true, + }, + }, + { + name: ["-h", "--help"], + description: "Print help information", + }, + ], + }, + { + name: "delegate-vesting", + description: "Delegate to a mixnode with locked tokens", + options: [ + { + name: "--identity-key", + args: { + name: "identity-key", + }, + }, + { + name: "--amount", + args: { + name: "amount", + }, + }, + { + name: "--mnemonic", + description: "Provide the mnemonic for your account. You can also provide this is an env var called MNEMONIC.", + args: { + name: "mnemonic", + isOptional: true, + }, + }, + { + name: "--config-env-file", + description: "Overrides configuration as a file of environment variables. Note: individual env vars take precedence over this file.", + args: { + name: "config-env-file", + isOptional: true, + }, + }, + { + name: "--nymd-url", + description: "Overrides the nymd URL provided either as an environment variable NYMD_VALIDATOR or in a config file", + args: { + name: "nymd-url", + isOptional: true, + }, + }, + { + name: "--validator-api-url", + description: "Overrides the validator API URL provided either as an environment variable API_VALIDATOR or in a config file", + args: { + name: "validator-api-url", + isOptional: true, + }, + }, + { + name: "--mixnet-contract-address", + description: "Overrides the mixnet contract address provided either as an environment variable or in a config file", + args: { + name: "mixnet-contract-address", + isOptional: true, + }, + }, + { + name: "--vesting-contract-address", + description: "Overrides the vesting contract address provided either as an environment variable or in a config file", + args: { + name: "vesting-contract-address", + isOptional: true, + }, + }, + { + name: ["-h", "--help"], + description: "Print help information", + }, + ], + }, + { + name: "undelegate-vesting", + description: "Undelegate from a mixnode (when originally using locked tokens)", + options: [ + { + name: "--identity-key", + args: { + name: "identity-key", + }, + }, + { + name: "--mnemonic", + description: "Provide the mnemonic for your account. You can also provide this is an env var called MNEMONIC.", + args: { + name: "mnemonic", + isOptional: true, + }, + }, + { + name: "--config-env-file", + description: "Overrides configuration as a file of environment variables. Note: individual env vars take precedence over this file.", + args: { + name: "config-env-file", + isOptional: true, + }, + }, + { + name: "--nymd-url", + description: "Overrides the nymd URL provided either as an environment variable NYMD_VALIDATOR or in a config file", + args: { + name: "nymd-url", + isOptional: true, + }, + }, + { + name: "--validator-api-url", + description: "Overrides the validator API URL provided either as an environment variable API_VALIDATOR or in a config file", + args: { + name: "validator-api-url", + isOptional: true, + }, + }, + { + name: "--mixnet-contract-address", + description: "Overrides the mixnet contract address provided either as an environment variable or in a config file", + args: { + name: "mixnet-contract-address", + isOptional: true, + }, + }, + { + name: "--vesting-contract-address", + description: "Overrides the vesting contract address provided either as an environment variable or in a config file", + args: { + name: "vesting-contract-address", + isOptional: true, + }, + }, + { + name: ["-h", "--help"], + description: "Print help information", + }, + ], + }, + { + name: "help", + description: "Print this message or the help of the given subcommand(s)", + options: [ + { + name: "--mnemonic", + description: "Provide the mnemonic for your account. You can also provide this is an env var called MNEMONIC.", + args: { + name: "mnemonic", + isOptional: true, + }, + }, + { + name: "--config-env-file", + description: "Overrides configuration as a file of environment variables. Note: individual env vars take precedence over this file.", + args: { + name: "config-env-file", + isOptional: true, + }, + }, + { + name: "--nymd-url", + description: "Overrides the nymd URL provided either as an environment variable NYMD_VALIDATOR or in a config file", + args: { + name: "nymd-url", + isOptional: true, + }, + }, + { + name: "--validator-api-url", + description: "Overrides the validator API URL provided either as an environment variable API_VALIDATOR or in a config file", + args: { + name: "validator-api-url", + isOptional: true, + }, + }, + { + name: "--mixnet-contract-address", + description: "Overrides the mixnet contract address provided either as an environment variable or in a config file", + args: { + name: "mixnet-contract-address", + isOptional: true, + }, + }, + { + name: "--vesting-contract-address", + description: "Overrides the vesting contract address provided either as an environment variable or in a config file", + args: { + name: "vesting-contract-address", + isOptional: true, + }, + }, + ], + args: { + name: "subcommand", + isOptional: true, + }, + }, + ], + options: [ + { + name: "--mnemonic", + description: "Provide the mnemonic for your account. You can also provide this is an env var called MNEMONIC.", + args: { + name: "mnemonic", + isOptional: true, + }, + }, + { + name: "--config-env-file", + description: "Overrides configuration as a file of environment variables. Note: individual env vars take precedence over this file.", + args: { + name: "config-env-file", + isOptional: true, + }, + }, + { + name: "--nymd-url", + description: "Overrides the nymd URL provided either as an environment variable NYMD_VALIDATOR or in a config file", + args: { + name: "nymd-url", + isOptional: true, + }, + }, + { + name: "--validator-api-url", + description: "Overrides the validator API URL provided either as an environment variable API_VALIDATOR or in a config file", + args: { + name: "validator-api-url", + isOptional: true, + }, + }, + { + name: "--mixnet-contract-address", + description: "Overrides the mixnet contract address provided either as an environment variable or in a config file", + args: { + name: "mixnet-contract-address", + isOptional: true, + }, + }, + { + name: "--vesting-contract-address", + description: "Overrides the vesting contract address provided either as an environment variable or in a config file", + args: { + name: "vesting-contract-address", + isOptional: true, + }, + }, + { + name: ["-h", "--help"], + description: "Print help information", + }, + ], + }, + { + name: "operators", + description: "Manage a mixnode or gateway you operate", + subcommands: [ + { + name: "mixnode", + description: "Manage your mixnode", + subcommands: [ + { + name: "keys", + description: "Operations for mixnode keys", + subcommands: [ + { + name: "decode-mixnode-key", + description: "Decode a mixnode key", + options: [ + { + name: ["-k", "--key"], + args: { + name: "key", + }, + }, + { + name: "--mnemonic", + description: "Provide the mnemonic for your account. You can also provide this is an env var called MNEMONIC.", + args: { + name: "mnemonic", + isOptional: true, + }, + }, + { + name: "--config-env-file", + description: "Overrides configuration as a file of environment variables. Note: individual env vars take precedence over this file.", + args: { + name: "config-env-file", + isOptional: true, + }, + }, + { + name: "--nymd-url", + description: "Overrides the nymd URL provided either as an environment variable NYMD_VALIDATOR or in a config file", + args: { + name: "nymd-url", + isOptional: true, + }, + }, + { + name: "--validator-api-url", + description: "Overrides the validator API URL provided either as an environment variable API_VALIDATOR or in a config file", + args: { + name: "validator-api-url", + isOptional: true, + }, + }, + { + name: "--mixnet-contract-address", + description: "Overrides the mixnet contract address provided either as an environment variable or in a config file", + args: { + name: "mixnet-contract-address", + isOptional: true, + }, + }, + { + name: "--vesting-contract-address", + description: "Overrides the vesting contract address provided either as an environment variable or in a config file", + args: { + name: "vesting-contract-address", + isOptional: true, + }, + }, + { + name: ["-h", "--help"], + description: "Print help information", + }, + ], + }, + { + name: "help", + description: "Print this message or the help of the given subcommand(s)", + options: [ + { + name: "--mnemonic", + description: "Provide the mnemonic for your account. You can also provide this is an env var called MNEMONIC.", + args: { + name: "mnemonic", + isOptional: true, + }, + }, + { + name: "--config-env-file", + description: "Overrides configuration as a file of environment variables. Note: individual env vars take precedence over this file.", + args: { + name: "config-env-file", + isOptional: true, + }, + }, + { + name: "--nymd-url", + description: "Overrides the nymd URL provided either as an environment variable NYMD_VALIDATOR or in a config file", + args: { + name: "nymd-url", + isOptional: true, + }, + }, + { + name: "--validator-api-url", + description: "Overrides the validator API URL provided either as an environment variable API_VALIDATOR or in a config file", + args: { + name: "validator-api-url", + isOptional: true, + }, + }, + { + name: "--mixnet-contract-address", + description: "Overrides the mixnet contract address provided either as an environment variable or in a config file", + args: { + name: "mixnet-contract-address", + isOptional: true, + }, + }, + { + name: "--vesting-contract-address", + description: "Overrides the vesting contract address provided either as an environment variable or in a config file", + args: { + name: "vesting-contract-address", + isOptional: true, + }, + }, + ], + args: { + name: "subcommand", + isOptional: true, + }, + }, + ], + options: [ + { + name: "--mnemonic", + description: "Provide the mnemonic for your account. You can also provide this is an env var called MNEMONIC.", + args: { + name: "mnemonic", + isOptional: true, + }, + }, + { + name: "--config-env-file", + description: "Overrides configuration as a file of environment variables. Note: individual env vars take precedence over this file.", + args: { + name: "config-env-file", + isOptional: true, + }, + }, + { + name: "--nymd-url", + description: "Overrides the nymd URL provided either as an environment variable NYMD_VALIDATOR or in a config file", + args: { + name: "nymd-url", + isOptional: true, + }, + }, + { + name: "--validator-api-url", + description: "Overrides the validator API URL provided either as an environment variable API_VALIDATOR or in a config file", + args: { + name: "validator-api-url", + isOptional: true, + }, + }, + { + name: "--mixnet-contract-address", + description: "Overrides the mixnet contract address provided either as an environment variable or in a config file", + args: { + name: "mixnet-contract-address", + isOptional: true, + }, + }, + { + name: "--vesting-contract-address", + description: "Overrides the vesting contract address provided either as an environment variable or in a config file", + args: { + name: "vesting-contract-address", + isOptional: true, + }, + }, + { + name: ["-h", "--help"], + description: "Print help information", + }, + ], + }, + { + name: "rewards", + description: "Manage your mixnode operator rewards", + subcommands: [ + { + name: "claim", + description: "Claim rewards", + options: [ + { + name: "--mnemonic", + description: "Provide the mnemonic for your account. You can also provide this is an env var called MNEMONIC.", + args: { + name: "mnemonic", + isOptional: true, + }, + }, + { + name: "--config-env-file", + description: "Overrides configuration as a file of environment variables. Note: individual env vars take precedence over this file.", + args: { + name: "config-env-file", + isOptional: true, + }, + }, + { + name: "--nymd-url", + description: "Overrides the nymd URL provided either as an environment variable NYMD_VALIDATOR or in a config file", + args: { + name: "nymd-url", + isOptional: true, + }, + }, + { + name: "--validator-api-url", + description: "Overrides the validator API URL provided either as an environment variable API_VALIDATOR or in a config file", + args: { + name: "validator-api-url", + isOptional: true, + }, + }, + { + name: "--mixnet-contract-address", + description: "Overrides the mixnet contract address provided either as an environment variable or in a config file", + args: { + name: "mixnet-contract-address", + isOptional: true, + }, + }, + { + name: "--vesting-contract-address", + description: "Overrides the vesting contract address provided either as an environment variable or in a config file", + args: { + name: "vesting-contract-address", + isOptional: true, + }, + }, + { + name: ["-h", "--help"], + description: "Print help information", + }, + ], + }, + { + name: "vesting-claim", + description: "Claim rewards for a mixnode bonded with locked tokens", + options: [ + { + name: "--gas", + args: { + name: "gas", + isOptional: true, + }, + }, + { + name: "--mnemonic", + description: "Provide the mnemonic for your account. You can also provide this is an env var called MNEMONIC.", + args: { + name: "mnemonic", + isOptional: true, + }, + }, + { + name: "--config-env-file", + description: "Overrides configuration as a file of environment variables. Note: individual env vars take precedence over this file.", + args: { + name: "config-env-file", + isOptional: true, + }, + }, + { + name: "--nymd-url", + description: "Overrides the nymd URL provided either as an environment variable NYMD_VALIDATOR or in a config file", + args: { + name: "nymd-url", + isOptional: true, + }, + }, + { + name: "--validator-api-url", + description: "Overrides the validator API URL provided either as an environment variable API_VALIDATOR or in a config file", + args: { + name: "validator-api-url", + isOptional: true, + }, + }, + { + name: "--mixnet-contract-address", + description: "Overrides the mixnet contract address provided either as an environment variable or in a config file", + args: { + name: "mixnet-contract-address", + isOptional: true, + }, + }, + { + name: "--vesting-contract-address", + description: "Overrides the vesting contract address provided either as an environment variable or in a config file", + args: { + name: "vesting-contract-address", + isOptional: true, + }, + }, + { + name: ["-h", "--help"], + description: "Print help information", + }, + ], + }, + { + name: "help", + description: "Print this message or the help of the given subcommand(s)", + options: [ + { + name: "--mnemonic", + description: "Provide the mnemonic for your account. You can also provide this is an env var called MNEMONIC.", + args: { + name: "mnemonic", + isOptional: true, + }, + }, + { + name: "--config-env-file", + description: "Overrides configuration as a file of environment variables. Note: individual env vars take precedence over this file.", + args: { + name: "config-env-file", + isOptional: true, + }, + }, + { + name: "--nymd-url", + description: "Overrides the nymd URL provided either as an environment variable NYMD_VALIDATOR or in a config file", + args: { + name: "nymd-url", + isOptional: true, + }, + }, + { + name: "--validator-api-url", + description: "Overrides the validator API URL provided either as an environment variable API_VALIDATOR or in a config file", + args: { + name: "validator-api-url", + isOptional: true, + }, + }, + { + name: "--mixnet-contract-address", + description: "Overrides the mixnet contract address provided either as an environment variable or in a config file", + args: { + name: "mixnet-contract-address", + isOptional: true, + }, + }, + { + name: "--vesting-contract-address", + description: "Overrides the vesting contract address provided either as an environment variable or in a config file", + args: { + name: "vesting-contract-address", + isOptional: true, + }, + }, + ], + args: { + name: "subcommand", + isOptional: true, + }, + }, + ], + options: [ + { + name: "--mnemonic", + description: "Provide the mnemonic for your account. You can also provide this is an env var called MNEMONIC.", + args: { + name: "mnemonic", + isOptional: true, + }, + }, + { + name: "--config-env-file", + description: "Overrides configuration as a file of environment variables. Note: individual env vars take precedence over this file.", + args: { + name: "config-env-file", + isOptional: true, + }, + }, + { + name: "--nymd-url", + description: "Overrides the nymd URL provided either as an environment variable NYMD_VALIDATOR or in a config file", + args: { + name: "nymd-url", + isOptional: true, + }, + }, + { + name: "--validator-api-url", + description: "Overrides the validator API URL provided either as an environment variable API_VALIDATOR or in a config file", + args: { + name: "validator-api-url", + isOptional: true, + }, + }, + { + name: "--mixnet-contract-address", + description: "Overrides the mixnet contract address provided either as an environment variable or in a config file", + args: { + name: "mixnet-contract-address", + isOptional: true, + }, + }, + { + name: "--vesting-contract-address", + description: "Overrides the vesting contract address provided either as an environment variable or in a config file", + args: { + name: "vesting-contract-address", + isOptional: true, + }, + }, + { + name: ["-h", "--help"], + description: "Print help information", + }, + ], + }, + { + name: "settings", + description: "Manage your mixnode settings stored in the directory", + subcommands: [ + { + name: "update-profit-percentage", + description: "Update profit percentage", + options: [ + { + name: "--profit-percent", + args: { + name: "profit-percent", + }, + }, + { + name: "--mnemonic", + description: "Provide the mnemonic for your account. You can also provide this is an env var called MNEMONIC.", + args: { + name: "mnemonic", + isOptional: true, + }, + }, + { + name: "--config-env-file", + description: "Overrides configuration as a file of environment variables. Note: individual env vars take precedence over this file.", + args: { + name: "config-env-file", + isOptional: true, + }, + }, + { + name: "--nymd-url", + description: "Overrides the nymd URL provided either as an environment variable NYMD_VALIDATOR or in a config file", + args: { + name: "nymd-url", + isOptional: true, + }, + }, + { + name: "--validator-api-url", + description: "Overrides the validator API URL provided either as an environment variable API_VALIDATOR or in a config file", + args: { + name: "validator-api-url", + isOptional: true, + }, + }, + { + name: "--mixnet-contract-address", + description: "Overrides the mixnet contract address provided either as an environment variable or in a config file", + args: { + name: "mixnet-contract-address", + isOptional: true, + }, + }, + { + name: "--vesting-contract-address", + description: "Overrides the vesting contract address provided either as an environment variable or in a config file", + args: { + name: "vesting-contract-address", + isOptional: true, + }, + }, + { + name: ["-h", "--help"], + description: "Print help information", + }, + ], + }, + { + name: "vesting-update-profit-percentage", + description: "Update profit percentage for a mixnode bonded with locked tokens", + options: [ + { + name: "--profit-percent", + args: { + name: "profit-percent", + }, + }, + { + name: "--gas", + args: { + name: "gas", + isOptional: true, + }, + }, + { + name: "--mnemonic", + description: "Provide the mnemonic for your account. You can also provide this is an env var called MNEMONIC.", + args: { + name: "mnemonic", + isOptional: true, + }, + }, + { + name: "--config-env-file", + description: "Overrides configuration as a file of environment variables. Note: individual env vars take precedence over this file.", + args: { + name: "config-env-file", + isOptional: true, + }, + }, + { + name: "--nymd-url", + description: "Overrides the nymd URL provided either as an environment variable NYMD_VALIDATOR or in a config file", + args: { + name: "nymd-url", + isOptional: true, + }, + }, + { + name: "--validator-api-url", + description: "Overrides the validator API URL provided either as an environment variable API_VALIDATOR or in a config file", + args: { + name: "validator-api-url", + isOptional: true, + }, + }, + { + name: "--mixnet-contract-address", + description: "Overrides the mixnet contract address provided either as an environment variable or in a config file", + args: { + name: "mixnet-contract-address", + isOptional: true, + }, + }, + { + name: "--vesting-contract-address", + description: "Overrides the vesting contract address provided either as an environment variable or in a config file", + args: { + name: "vesting-contract-address", + isOptional: true, + }, + }, + { + name: ["-h", "--help"], + description: "Print help information", + }, + ], + }, + { + name: "help", + description: "Print this message or the help of the given subcommand(s)", + options: [ + { + name: "--mnemonic", + description: "Provide the mnemonic for your account. You can also provide this is an env var called MNEMONIC.", + args: { + name: "mnemonic", + isOptional: true, + }, + }, + { + name: "--config-env-file", + description: "Overrides configuration as a file of environment variables. Note: individual env vars take precedence over this file.", + args: { + name: "config-env-file", + isOptional: true, + }, + }, + { + name: "--nymd-url", + description: "Overrides the nymd URL provided either as an environment variable NYMD_VALIDATOR or in a config file", + args: { + name: "nymd-url", + isOptional: true, + }, + }, + { + name: "--validator-api-url", + description: "Overrides the validator API URL provided either as an environment variable API_VALIDATOR or in a config file", + args: { + name: "validator-api-url", + isOptional: true, + }, + }, + { + name: "--mixnet-contract-address", + description: "Overrides the mixnet contract address provided either as an environment variable or in a config file", + args: { + name: "mixnet-contract-address", + isOptional: true, + }, + }, + { + name: "--vesting-contract-address", + description: "Overrides the vesting contract address provided either as an environment variable or in a config file", + args: { + name: "vesting-contract-address", + isOptional: true, + }, + }, + ], + args: { + name: "subcommand", + isOptional: true, + }, + }, + ], + options: [ + { + name: "--mnemonic", + description: "Provide the mnemonic for your account. You can also provide this is an env var called MNEMONIC.", + args: { + name: "mnemonic", + isOptional: true, + }, + }, + { + name: "--config-env-file", + description: "Overrides configuration as a file of environment variables. Note: individual env vars take precedence over this file.", + args: { + name: "config-env-file", + isOptional: true, + }, + }, + { + name: "--nymd-url", + description: "Overrides the nymd URL provided either as an environment variable NYMD_VALIDATOR or in a config file", + args: { + name: "nymd-url", + isOptional: true, + }, + }, + { + name: "--validator-api-url", + description: "Overrides the validator API URL provided either as an environment variable API_VALIDATOR or in a config file", + args: { + name: "validator-api-url", + isOptional: true, + }, + }, + { + name: "--mixnet-contract-address", + description: "Overrides the mixnet contract address provided either as an environment variable or in a config file", + args: { + name: "mixnet-contract-address", + isOptional: true, + }, + }, + { + name: "--vesting-contract-address", + description: "Overrides the vesting contract address provided either as an environment variable or in a config file", + args: { + name: "vesting-contract-address", + isOptional: true, + }, + }, + { + name: ["-h", "--help"], + description: "Print help information", + }, + ], + }, + { + name: "bond", + description: "Bond to a mixnode", + options: [ + { + name: "--host", + args: { + name: "host", + }, + }, + { + name: "--signature", + args: { + name: "signature", + }, + }, + { + name: "--mix-port", + args: { + name: "mix-port", + isOptional: true, + }, + }, + { + name: "--verloc-port", + args: { + name: "verloc-port", + isOptional: true, + }, + }, + { + name: "--http-api-port", + args: { + name: "http-api-port", + isOptional: true, + }, + }, + { + name: "--sphinx-key", + args: { + name: "sphinx-key", + }, + }, + { + name: "--identity-key", + args: { + name: "identity-key", + }, + }, + { + name: "--version", + args: { + name: "version", + }, + }, + { + name: "--profit-margin-percent", + args: { + name: "profit-margin-percent", + isOptional: true, + }, + }, + { + name: "--amount", + description: "bonding amount in current DENOMINATION (so it would be 'unym', rather than 'nym')", + args: { + name: "amount", + }, + }, + { + name: "--mnemonic", + description: "Provide the mnemonic for your account. You can also provide this is an env var called MNEMONIC.", + args: { + name: "mnemonic", + isOptional: true, + }, + }, + { + name: "--config-env-file", + description: "Overrides configuration as a file of environment variables. Note: individual env vars take precedence over this file.", + args: { + name: "config-env-file", + isOptional: true, + }, + }, + { + name: "--nymd-url", + description: "Overrides the nymd URL provided either as an environment variable NYMD_VALIDATOR or in a config file", + args: { + name: "nymd-url", + isOptional: true, + }, + }, + { + name: "--validator-api-url", + description: "Overrides the validator API URL provided either as an environment variable API_VALIDATOR or in a config file", + args: { + name: "validator-api-url", + isOptional: true, + }, + }, + { + name: "--mixnet-contract-address", + description: "Overrides the mixnet contract address provided either as an environment variable or in a config file", + args: { + name: "mixnet-contract-address", + isOptional: true, + }, + }, + { + name: "--vesting-contract-address", + description: "Overrides the vesting contract address provided either as an environment variable or in a config file", + args: { + name: "vesting-contract-address", + isOptional: true, + }, + }, + { + name: ["-f", "--force"], + }, + { + name: ["-h", "--help"], + description: "Print help information", + }, + ], + }, + { + name: "unbound", + description: "Unbound from a mixnode", + options: [ + { + name: "--mnemonic", + description: "Provide the mnemonic for your account. You can also provide this is an env var called MNEMONIC.", + args: { + name: "mnemonic", + isOptional: true, + }, + }, + { + name: "--config-env-file", + description: "Overrides configuration as a file of environment variables. Note: individual env vars take precedence over this file.", + args: { + name: "config-env-file", + isOptional: true, + }, + }, + { + name: "--nymd-url", + description: "Overrides the nymd URL provided either as an environment variable NYMD_VALIDATOR or in a config file", + args: { + name: "nymd-url", + isOptional: true, + }, + }, + { + name: "--validator-api-url", + description: "Overrides the validator API URL provided either as an environment variable API_VALIDATOR or in a config file", + args: { + name: "validator-api-url", + isOptional: true, + }, + }, + { + name: "--mixnet-contract-address", + description: "Overrides the mixnet contract address provided either as an environment variable or in a config file", + args: { + name: "mixnet-contract-address", + isOptional: true, + }, + }, + { + name: "--vesting-contract-address", + description: "Overrides the vesting contract address provided either as an environment variable or in a config file", + args: { + name: "vesting-contract-address", + isOptional: true, + }, + }, + { + name: ["-h", "--help"], + description: "Print help information", + }, + ], + }, + { + name: "bond-vesting", + description: "Bond to a mixnode with locked tokens", + options: [ + { + name: "--host", + args: { + name: "host", + }, + }, + { + name: "--signature", + args: { + name: "signature", + }, + }, + { + name: "--mix-port", + args: { + name: "mix-port", + isOptional: true, + }, + }, + { + name: "--verloc-port", + args: { + name: "verloc-port", + isOptional: true, + }, + }, + { + name: "--http-api-port", + args: { + name: "http-api-port", + isOptional: true, + }, + }, + { + name: "--sphinx-key", + args: { + name: "sphinx-key", + }, + }, + { + name: "--identity-key", + args: { + name: "identity-key", + }, + }, + { + name: "--version", + args: { + name: "version", + }, + }, + { + name: "--profit-margin-percent", + args: { + name: "profit-margin-percent", + isOptional: true, + }, + }, + { + name: "--amount", + description: "bonding amount in current DENOMINATION (so it would be 'unym', rather than 'nym')", + args: { + name: "amount", + }, + }, + { + name: "--gas", + args: { + name: "gas", + isOptional: true, + }, + }, + { + name: "--mnemonic", + description: "Provide the mnemonic for your account. You can also provide this is an env var called MNEMONIC.", + args: { + name: "mnemonic", + isOptional: true, + }, + }, + { + name: "--config-env-file", + description: "Overrides configuration as a file of environment variables. Note: individual env vars take precedence over this file.", + args: { + name: "config-env-file", + isOptional: true, + }, + }, + { + name: "--nymd-url", + description: "Overrides the nymd URL provided either as an environment variable NYMD_VALIDATOR or in a config file", + args: { + name: "nymd-url", + isOptional: true, + }, + }, + { + name: "--validator-api-url", + description: "Overrides the validator API URL provided either as an environment variable API_VALIDATOR or in a config file", + args: { + name: "validator-api-url", + isOptional: true, + }, + }, + { + name: "--mixnet-contract-address", + description: "Overrides the mixnet contract address provided either as an environment variable or in a config file", + args: { + name: "mixnet-contract-address", + isOptional: true, + }, + }, + { + name: "--vesting-contract-address", + description: "Overrides the vesting contract address provided either as an environment variable or in a config file", + args: { + name: "vesting-contract-address", + isOptional: true, + }, + }, + { + name: ["-f", "--force"], + }, + { + name: ["-h", "--help"], + description: "Print help information", + }, + ], + }, + { + name: "unbound-vesting", + description: "Unbound from a mixnode (when originally using locked tokens)", + options: [ + { + name: "--gas", + args: { + name: "gas", + isOptional: true, + }, + }, + { + name: "--mnemonic", + description: "Provide the mnemonic for your account. You can also provide this is an env var called MNEMONIC.", + args: { + name: "mnemonic", + isOptional: true, + }, + }, + { + name: "--config-env-file", + description: "Overrides configuration as a file of environment variables. Note: individual env vars take precedence over this file.", + args: { + name: "config-env-file", + isOptional: true, + }, + }, + { + name: "--nymd-url", + description: "Overrides the nymd URL provided either as an environment variable NYMD_VALIDATOR or in a config file", + args: { + name: "nymd-url", + isOptional: true, + }, + }, + { + name: "--validator-api-url", + description: "Overrides the validator API URL provided either as an environment variable API_VALIDATOR or in a config file", + args: { + name: "validator-api-url", + isOptional: true, + }, + }, + { + name: "--mixnet-contract-address", + description: "Overrides the mixnet contract address provided either as an environment variable or in a config file", + args: { + name: "mixnet-contract-address", + isOptional: true, + }, + }, + { + name: "--vesting-contract-address", + description: "Overrides the vesting contract address provided either as an environment variable or in a config file", + args: { + name: "vesting-contract-address", + isOptional: true, + }, + }, + { + name: ["-h", "--help"], + description: "Print help information", + }, + ], + }, + { + name: "help", + description: "Print this message or the help of the given subcommand(s)", + options: [ + { + name: "--mnemonic", + description: "Provide the mnemonic for your account. You can also provide this is an env var called MNEMONIC.", + args: { + name: "mnemonic", + isOptional: true, + }, + }, + { + name: "--config-env-file", + description: "Overrides configuration as a file of environment variables. Note: individual env vars take precedence over this file.", + args: { + name: "config-env-file", + isOptional: true, + }, + }, + { + name: "--nymd-url", + description: "Overrides the nymd URL provided either as an environment variable NYMD_VALIDATOR or in a config file", + args: { + name: "nymd-url", + isOptional: true, + }, + }, + { + name: "--validator-api-url", + description: "Overrides the validator API URL provided either as an environment variable API_VALIDATOR or in a config file", + args: { + name: "validator-api-url", + isOptional: true, + }, + }, + { + name: "--mixnet-contract-address", + description: "Overrides the mixnet contract address provided either as an environment variable or in a config file", + args: { + name: "mixnet-contract-address", + isOptional: true, + }, + }, + { + name: "--vesting-contract-address", + description: "Overrides the vesting contract address provided either as an environment variable or in a config file", + args: { + name: "vesting-contract-address", + isOptional: true, + }, + }, + ], + args: { + name: "subcommand", + isOptional: true, + }, + }, + ], + options: [ + { + name: "--mnemonic", + description: "Provide the mnemonic for your account. You can also provide this is an env var called MNEMONIC.", + args: { + name: "mnemonic", + isOptional: true, + }, + }, + { + name: "--config-env-file", + description: "Overrides configuration as a file of environment variables. Note: individual env vars take precedence over this file.", + args: { + name: "config-env-file", + isOptional: true, + }, + }, + { + name: "--nymd-url", + description: "Overrides the nymd URL provided either as an environment variable NYMD_VALIDATOR or in a config file", + args: { + name: "nymd-url", + isOptional: true, + }, + }, + { + name: "--validator-api-url", + description: "Overrides the validator API URL provided either as an environment variable API_VALIDATOR or in a config file", + args: { + name: "validator-api-url", + isOptional: true, + }, + }, + { + name: "--mixnet-contract-address", + description: "Overrides the mixnet contract address provided either as an environment variable or in a config file", + args: { + name: "mixnet-contract-address", + isOptional: true, + }, + }, + { + name: "--vesting-contract-address", + description: "Overrides the vesting contract address provided either as an environment variable or in a config file", + args: { + name: "vesting-contract-address", + isOptional: true, + }, + }, + { + name: ["-h", "--help"], + description: "Print help information", + }, + ], + }, + { + name: "gateway", + description: "Manage your gateway", + subcommands: [ + { + name: "bond", + description: "Bond to a gateway", + options: [ + { + name: "--host", + args: { + name: "host", + }, + }, + { + name: "--signature", + args: { + name: "signature", + }, + }, + { + name: "--mix-port", + args: { + name: "mix-port", + isOptional: true, + }, + }, + { + name: "--clients-port", + args: { + name: "clients-port", + isOptional: true, + }, + }, + { + name: "--location", + args: { + name: "location", + isOptional: true, + }, + }, + { + name: "--sphinx-key", + args: { + name: "sphinx-key", + }, + }, + { + name: "--identity-key", + args: { + name: "identity-key", + }, + }, + { + name: "--version", + args: { + name: "version", + }, + }, + { + name: "--amount", + description: "bonding amount in current DENOMINATION (so it would be 'unym', rather than 'nym')", + args: { + name: "amount", + }, + }, + { + name: "--mnemonic", + description: "Provide the mnemonic for your account. You can also provide this is an env var called MNEMONIC.", + args: { + name: "mnemonic", + isOptional: true, + }, + }, + { + name: "--config-env-file", + description: "Overrides configuration as a file of environment variables. Note: individual env vars take precedence over this file.", + args: { + name: "config-env-file", + isOptional: true, + }, + }, + { + name: "--nymd-url", + description: "Overrides the nymd URL provided either as an environment variable NYMD_VALIDATOR or in a config file", + args: { + name: "nymd-url", + isOptional: true, + }, + }, + { + name: "--validator-api-url", + description: "Overrides the validator API URL provided either as an environment variable API_VALIDATOR or in a config file", + args: { + name: "validator-api-url", + isOptional: true, + }, + }, + { + name: "--mixnet-contract-address", + description: "Overrides the mixnet contract address provided either as an environment variable or in a config file", + args: { + name: "mixnet-contract-address", + isOptional: true, + }, + }, + { + name: "--vesting-contract-address", + description: "Overrides the vesting contract address provided either as an environment variable or in a config file", + args: { + name: "vesting-contract-address", + isOptional: true, + }, + }, + { + name: ["-f", "--force"], + }, + { + name: ["-h", "--help"], + description: "Print help information", + }, + ], + }, + { + name: "unbound", + description: "Unbound from a gateway", + options: [ + { + name: "--mnemonic", + description: "Provide the mnemonic for your account. You can also provide this is an env var called MNEMONIC.", + args: { + name: "mnemonic", + isOptional: true, + }, + }, + { + name: "--config-env-file", + description: "Overrides configuration as a file of environment variables. Note: individual env vars take precedence over this file.", + args: { + name: "config-env-file", + isOptional: true, + }, + }, + { + name: "--nymd-url", + description: "Overrides the nymd URL provided either as an environment variable NYMD_VALIDATOR or in a config file", + args: { + name: "nymd-url", + isOptional: true, + }, + }, + { + name: "--validator-api-url", + description: "Overrides the validator API URL provided either as an environment variable API_VALIDATOR or in a config file", + args: { + name: "validator-api-url", + isOptional: true, + }, + }, + { + name: "--mixnet-contract-address", + description: "Overrides the mixnet contract address provided either as an environment variable or in a config file", + args: { + name: "mixnet-contract-address", + isOptional: true, + }, + }, + { + name: "--vesting-contract-address", + description: "Overrides the vesting contract address provided either as an environment variable or in a config file", + args: { + name: "vesting-contract-address", + isOptional: true, + }, + }, + { + name: ["-h", "--help"], + description: "Print help information", + }, + ], + }, + { + name: "vesting-bond", + description: "Bond to a gateway with locked tokens", + options: [ + { + name: "--host", + args: { + name: "host", + }, + }, + { + name: "--signature", + args: { + name: "signature", + }, + }, + { + name: "--mix-port", + args: { + name: "mix-port", + isOptional: true, + }, + }, + { + name: "--clients-port", + args: { + name: "clients-port", + isOptional: true, + }, + }, + { + name: "--location", + args: { + name: "location", + isOptional: true, + }, + }, + { + name: "--sphinx-key", + args: { + name: "sphinx-key", + }, + }, + { + name: "--identity-key", + args: { + name: "identity-key", + }, + }, + { + name: "--version", + args: { + name: "version", + }, + }, + { + name: "--amount", + description: "bonding amount in current DENOMINATION (so it would be 'unym', rather than 'nym')", + args: { + name: "amount", + }, + }, + { + name: "--mnemonic", + description: "Provide the mnemonic for your account. You can also provide this is an env var called MNEMONIC.", + args: { + name: "mnemonic", + isOptional: true, + }, + }, + { + name: "--config-env-file", + description: "Overrides configuration as a file of environment variables. Note: individual env vars take precedence over this file.", + args: { + name: "config-env-file", + isOptional: true, + }, + }, + { + name: "--nymd-url", + description: "Overrides the nymd URL provided either as an environment variable NYMD_VALIDATOR or in a config file", + args: { + name: "nymd-url", + isOptional: true, + }, + }, + { + name: "--validator-api-url", + description: "Overrides the validator API URL provided either as an environment variable API_VALIDATOR or in a config file", + args: { + name: "validator-api-url", + isOptional: true, + }, + }, + { + name: "--mixnet-contract-address", + description: "Overrides the mixnet contract address provided either as an environment variable or in a config file", + args: { + name: "mixnet-contract-address", + isOptional: true, + }, + }, + { + name: "--vesting-contract-address", + description: "Overrides the vesting contract address provided either as an environment variable or in a config file", + args: { + name: "vesting-contract-address", + isOptional: true, + }, + }, + { + name: ["-f", "--force"], + }, + { + name: ["-h", "--help"], + description: "Print help information", + }, + ], + }, + { + name: "vesting-unbound", + description: "Unbound from a gateway (when originally using locked tokens)", + options: [ + { + name: "--mnemonic", + description: "Provide the mnemonic for your account. You can also provide this is an env var called MNEMONIC.", + args: { + name: "mnemonic", + isOptional: true, + }, + }, + { + name: "--config-env-file", + description: "Overrides configuration as a file of environment variables. Note: individual env vars take precedence over this file.", + args: { + name: "config-env-file", + isOptional: true, + }, + }, + { + name: "--nymd-url", + description: "Overrides the nymd URL provided either as an environment variable NYMD_VALIDATOR or in a config file", + args: { + name: "nymd-url", + isOptional: true, + }, + }, + { + name: "--validator-api-url", + description: "Overrides the validator API URL provided either as an environment variable API_VALIDATOR or in a config file", + args: { + name: "validator-api-url", + isOptional: true, + }, + }, + { + name: "--mixnet-contract-address", + description: "Overrides the mixnet contract address provided either as an environment variable or in a config file", + args: { + name: "mixnet-contract-address", + isOptional: true, + }, + }, + { + name: "--vesting-contract-address", + description: "Overrides the vesting contract address provided either as an environment variable or in a config file", + args: { + name: "vesting-contract-address", + isOptional: true, + }, + }, + { + name: ["-h", "--help"], + description: "Print help information", + }, + ], + }, + { + name: "help", + description: "Print this message or the help of the given subcommand(s)", + options: [ + { + name: "--mnemonic", + description: "Provide the mnemonic for your account. You can also provide this is an env var called MNEMONIC.", + args: { + name: "mnemonic", + isOptional: true, + }, + }, + { + name: "--config-env-file", + description: "Overrides configuration as a file of environment variables. Note: individual env vars take precedence over this file.", + args: { + name: "config-env-file", + isOptional: true, + }, + }, + { + name: "--nymd-url", + description: "Overrides the nymd URL provided either as an environment variable NYMD_VALIDATOR or in a config file", + args: { + name: "nymd-url", + isOptional: true, + }, + }, + { + name: "--validator-api-url", + description: "Overrides the validator API URL provided either as an environment variable API_VALIDATOR or in a config file", + args: { + name: "validator-api-url", + isOptional: true, + }, + }, + { + name: "--mixnet-contract-address", + description: "Overrides the mixnet contract address provided either as an environment variable or in a config file", + args: { + name: "mixnet-contract-address", + isOptional: true, + }, + }, + { + name: "--vesting-contract-address", + description: "Overrides the vesting contract address provided either as an environment variable or in a config file", + args: { + name: "vesting-contract-address", + isOptional: true, + }, + }, + ], + args: { + name: "subcommand", + isOptional: true, + }, + }, + ], + options: [ + { + name: "--mnemonic", + description: "Provide the mnemonic for your account. You can also provide this is an env var called MNEMONIC.", + args: { + name: "mnemonic", + isOptional: true, + }, + }, + { + name: "--config-env-file", + description: "Overrides configuration as a file of environment variables. Note: individual env vars take precedence over this file.", + args: { + name: "config-env-file", + isOptional: true, + }, + }, + { + name: "--nymd-url", + description: "Overrides the nymd URL provided either as an environment variable NYMD_VALIDATOR or in a config file", + args: { + name: "nymd-url", + isOptional: true, + }, + }, + { + name: "--validator-api-url", + description: "Overrides the validator API URL provided either as an environment variable API_VALIDATOR or in a config file", + args: { + name: "validator-api-url", + isOptional: true, + }, + }, + { + name: "--mixnet-contract-address", + description: "Overrides the mixnet contract address provided either as an environment variable or in a config file", + args: { + name: "mixnet-contract-address", + isOptional: true, + }, + }, + { + name: "--vesting-contract-address", + description: "Overrides the vesting contract address provided either as an environment variable or in a config file", + args: { + name: "vesting-contract-address", + isOptional: true, + }, + }, + { + name: ["-h", "--help"], + description: "Print help information", + }, + ], + }, + { + name: "help", + description: "Print this message or the help of the given subcommand(s)", + options: [ + { + name: "--mnemonic", + description: "Provide the mnemonic for your account. You can also provide this is an env var called MNEMONIC.", + args: { + name: "mnemonic", + isOptional: true, + }, + }, + { + name: "--config-env-file", + description: "Overrides configuration as a file of environment variables. Note: individual env vars take precedence over this file.", + args: { + name: "config-env-file", + isOptional: true, + }, + }, + { + name: "--nymd-url", + description: "Overrides the nymd URL provided either as an environment variable NYMD_VALIDATOR or in a config file", + args: { + name: "nymd-url", + isOptional: true, + }, + }, + { + name: "--validator-api-url", + description: "Overrides the validator API URL provided either as an environment variable API_VALIDATOR or in a config file", + args: { + name: "validator-api-url", + isOptional: true, + }, + }, + { + name: "--mixnet-contract-address", + description: "Overrides the mixnet contract address provided either as an environment variable or in a config file", + args: { + name: "mixnet-contract-address", + isOptional: true, + }, + }, + { + name: "--vesting-contract-address", + description: "Overrides the vesting contract address provided either as an environment variable or in a config file", + args: { + name: "vesting-contract-address", + isOptional: true, + }, + }, + ], + args: { + name: "subcommand", + isOptional: true, + }, + }, + ], + options: [ + { + name: "--mnemonic", + description: "Provide the mnemonic for your account. You can also provide this is an env var called MNEMONIC.", + args: { + name: "mnemonic", + isOptional: true, + }, + }, + { + name: "--config-env-file", + description: "Overrides configuration as a file of environment variables. Note: individual env vars take precedence over this file.", + args: { + name: "config-env-file", + isOptional: true, + }, + }, + { + name: "--nymd-url", + description: "Overrides the nymd URL provided either as an environment variable NYMD_VALIDATOR or in a config file", + args: { + name: "nymd-url", + isOptional: true, + }, + }, + { + name: "--validator-api-url", + description: "Overrides the validator API URL provided either as an environment variable API_VALIDATOR or in a config file", + args: { + name: "validator-api-url", + isOptional: true, + }, + }, + { + name: "--mixnet-contract-address", + description: "Overrides the mixnet contract address provided either as an environment variable or in a config file", + args: { + name: "mixnet-contract-address", + isOptional: true, + }, + }, + { + name: "--vesting-contract-address", + description: "Overrides the vesting contract address provided either as an environment variable or in a config file", + args: { + name: "vesting-contract-address", + isOptional: true, + }, + }, + { + name: ["-h", "--help"], + description: "Print help information", + }, + ], + }, + { + name: "help", + description: "Print this message or the help of the given subcommand(s)", + options: [ + { + name: "--mnemonic", + description: "Provide the mnemonic for your account. You can also provide this is an env var called MNEMONIC.", + args: { + name: "mnemonic", + isOptional: true, + }, + }, + { + name: "--config-env-file", + description: "Overrides configuration as a file of environment variables. Note: individual env vars take precedence over this file.", + args: { + name: "config-env-file", + isOptional: true, + }, + }, + { + name: "--nymd-url", + description: "Overrides the nymd URL provided either as an environment variable NYMD_VALIDATOR or in a config file", + args: { + name: "nymd-url", + isOptional: true, + }, + }, + { + name: "--validator-api-url", + description: "Overrides the validator API URL provided either as an environment variable API_VALIDATOR or in a config file", + args: { + name: "validator-api-url", + isOptional: true, + }, + }, + { + name: "--mixnet-contract-address", + description: "Overrides the mixnet contract address provided either as an environment variable or in a config file", + args: { + name: "mixnet-contract-address", + isOptional: true, + }, + }, + { + name: "--vesting-contract-address", + description: "Overrides the vesting contract address provided either as an environment variable or in a config file", + args: { + name: "vesting-contract-address", + isOptional: true, + }, + }, + ], + args: { + name: "subcommand", + isOptional: true, + }, + }, + ], + options: [ + { + name: "--mnemonic", + description: "Provide the mnemonic for your account. You can also provide this is an env var called MNEMONIC.", + args: { + name: "mnemonic", + isOptional: true, + }, + }, + { + name: "--config-env-file", + description: "Overrides configuration as a file of environment variables. Note: individual env vars take precedence over this file.", + args: { + name: "config-env-file", + isOptional: true, + }, + }, + { + name: "--nymd-url", + description: "Overrides the nymd URL provided either as an environment variable NYMD_VALIDATOR or in a config file", + args: { + name: "nymd-url", + isOptional: true, + }, + }, + { + name: "--validator-api-url", + description: "Overrides the validator API URL provided either as an environment variable API_VALIDATOR or in a config file", + args: { + name: "validator-api-url", + isOptional: true, + }, + }, + { + name: "--mixnet-contract-address", + description: "Overrides the mixnet contract address provided either as an environment variable or in a config file", + args: { + name: "mixnet-contract-address", + isOptional: true, + }, + }, + { + name: "--vesting-contract-address", + description: "Overrides the vesting contract address provided either as an environment variable or in a config file", + args: { + name: "vesting-contract-address", + isOptional: true, + }, + }, + { + name: ["-h", "--help"], + description: "Print help information", + }, + ], + }, + { + name: "generate-fig", + description: "Generates shell completion", + options: [ + { + name: "--mnemonic", + description: "Provide the mnemonic for your account. You can also provide this is an env var called MNEMONIC.", + args: { + name: "mnemonic", + isOptional: true, + }, + }, + { + name: "--config-env-file", + description: "Overrides configuration as a file of environment variables. Note: individual env vars take precedence over this file.", + args: { + name: "config-env-file", + isOptional: true, + }, + }, + { + name: "--nymd-url", + description: "Overrides the nymd URL provided either as an environment variable NYMD_VALIDATOR or in a config file", + args: { + name: "nymd-url", + isOptional: true, + }, + }, + { + name: "--validator-api-url", + description: "Overrides the validator API URL provided either as an environment variable API_VALIDATOR or in a config file", + args: { + name: "validator-api-url", + isOptional: true, + }, + }, + { + name: "--mixnet-contract-address", + description: "Overrides the mixnet contract address provided either as an environment variable or in a config file", + args: { + name: "mixnet-contract-address", + isOptional: true, + }, + }, + { + name: "--vesting-contract-address", + description: "Overrides the vesting contract address provided either as an environment variable or in a config file", + args: { + name: "vesting-contract-address", + isOptional: true, + }, + }, + { + name: ["-h", "--help"], + description: "Print help information", + }, + ], + }, + { + name: "help", + description: "Print this message or the help of the given subcommand(s)", + options: [ + { + name: "--mnemonic", + description: "Provide the mnemonic for your account. You can also provide this is an env var called MNEMONIC.", + args: { + name: "mnemonic", + isOptional: true, + }, + }, + { + name: "--config-env-file", + description: "Overrides configuration as a file of environment variables. Note: individual env vars take precedence over this file.", + args: { + name: "config-env-file", + isOptional: true, + }, + }, + { + name: "--nymd-url", + description: "Overrides the nymd URL provided either as an environment variable NYMD_VALIDATOR or in a config file", + args: { + name: "nymd-url", + isOptional: true, + }, + }, + { + name: "--validator-api-url", + description: "Overrides the validator API URL provided either as an environment variable API_VALIDATOR or in a config file", + args: { + name: "validator-api-url", + isOptional: true, + }, + }, + { + name: "--mixnet-contract-address", + description: "Overrides the mixnet contract address provided either as an environment variable or in a config file", + args: { + name: "mixnet-contract-address", + isOptional: true, + }, + }, + { + name: "--vesting-contract-address", + description: "Overrides the vesting contract address provided either as an environment variable or in a config file", + args: { + name: "vesting-contract-address", + isOptional: true, + }, + }, + ], + args: { + name: "subcommand", + isOptional: true, + }, + }, + ], + options: [ + { + name: "--mnemonic", + description: "Provide the mnemonic for your account. You can also provide this is an env var called MNEMONIC.", + args: { + name: "mnemonic", + isOptional: true, + }, + }, + { + name: "--config-env-file", + description: "Overrides configuration as a file of environment variables. Note: individual env vars take precedence over this file.", + args: { + name: "config-env-file", + isOptional: true, + }, + }, + { + name: "--nymd-url", + description: "Overrides the nymd URL provided either as an environment variable NYMD_VALIDATOR or in a config file", + args: { + name: "nymd-url", + isOptional: true, + }, + }, + { + name: "--validator-api-url", + description: "Overrides the validator API URL provided either as an environment variable API_VALIDATOR or in a config file", + args: { + name: "validator-api-url", + isOptional: true, + }, + }, + { + name: "--mixnet-contract-address", + description: "Overrides the mixnet contract address provided either as an environment variable or in a config file", + args: { + name: "mixnet-contract-address", + isOptional: true, + }, + }, + { + name: "--vesting-contract-address", + description: "Overrides the vesting contract address provided either as an environment variable or in a config file", + args: { + name: "vesting-contract-address", + isOptional: true, + }, + }, + { + name: ["-h", "--help"], + description: "Print help information", + }, + ], +}; + +export default completion; diff --git a/tools/nym-cli/user-docs/tsconfig.json b/tools/nym-cli/user-docs/tsconfig.json new file mode 100644 index 0000000000..b810c4f5c9 --- /dev/null +++ b/tools/nym-cli/user-docs/tsconfig.json @@ -0,0 +1,5 @@ +{ + "compilerOptions": { + "types": ["@withfig/autocomplete-types"] + }, +} \ No newline at end of file From 30dfa09e183686c95a81865753671c723dd720a7 Mon Sep 17 00:00:00 2001 From: =?UTF-8?q?Bogdan-=C8=98tefan=20Neac=C5=9Fu?= Date: Mon, 5 Sep 2022 17:31:06 +0300 Subject: [PATCH 07/46] Simplify the migration to trust the owner more (#1593) --- contracts/vesting/src/contract.rs | 40 +++++-------------------------- contracts/vesting/src/errors.rs | 2 -- 2 files changed, 6 insertions(+), 36 deletions(-) diff --git a/contracts/vesting/src/contract.rs b/contracts/vesting/src/contract.rs index e6b5ce915e..d478c686ae 100644 --- a/contracts/vesting/src/contract.rs +++ b/contracts/vesting/src/contract.rs @@ -255,48 +255,20 @@ fn try_update_staking_address( pub fn try_migrate_heights_to_timestamps( account_id: u32, mix_identity: String, - mut height_timestamp_map: Vec<(u64, u64)>, + height_timestamp_map: Vec<(u64, u64)>, info: MessageInfo, deps: DepsMut<'_>, ) -> Result { if info.sender != ADMIN.load(deps.storage)? { return Err(ContractError::NotAdmin(info.sender.as_str().to_string())); } - let mut delegation_heights = DELEGATIONS - .prefix((account_id, mix_identity.clone())) - .range(deps.storage, None, None, Order::Ascending) - .collect::>>()?; - if height_timestamp_map.len() != delegation_heights.len() { - return Err(ContractError::MigrateHeightsToTimestamp { - reason: format!( - "Received {} entries in height_timestamp_map, but {} entries are in storage", - height_timestamp_map.len(), - delegation_heights.len() - ), - }); - } - - height_timestamp_map.sort_by_key(|k| k.0); - delegation_heights.sort_by_key(|k| k.0); - - if height_timestamp_map - .iter() - .zip(delegation_heights.iter()) - .any(|(mapping, height)| mapping.0 != height.0) - { - return Err(ContractError::MigrateHeightsToTimestamp { - reason: String::from("height_timestamp_map heights mismatch with stored delegations"), - }); - } - - for ((old_key, new_key), (_, amount)) in - height_timestamp_map.iter().zip(delegation_heights.iter()) - { - remove_delegation((account_id, mix_identity.clone(), *old_key), deps.storage)?; + for (height, timestamp) in height_timestamp_map { + let amount = DELEGATIONS.load(deps.storage, (account_id, mix_identity.clone(), height))?; + remove_delegation((account_id, mix_identity.clone(), height), deps.storage)?; save_delegation( - (account_id, mix_identity.clone(), *new_key), - *amount, + (account_id, mix_identity.clone(), timestamp), + amount, deps.storage, )?; } diff --git a/contracts/vesting/src/errors.rs b/contracts/vesting/src/errors.rs index a265477dff..867620ff8f 100644 --- a/contracts/vesting/src/errors.rs +++ b/contracts/vesting/src/errors.rs @@ -48,6 +48,4 @@ pub enum ContractError { MinVestingFunds { sent: u128, need: u128 }, #[error("VESTING ({}): Maximum amount of locked coins has already been pledged: {current}, cap is {cap}", line!())] LockedPledgeCapReached { current: Uint128, cap: Uint128 }, - #[error("{reason}")] - MigrateHeightsToTimestamp { reason: String }, } From 8a6f8185db2d763dcd4aab7bda16f5571aab8d3f Mon Sep 17 00:00:00 2001 From: Fouad Date: Tue, 6 Sep 2022 09:56:12 +0100 Subject: [PATCH 08/46] Update/update modal background color (#1594) * update receive bg color + all other modals --- .../components/Accounts/MultiAccountHowTo.tsx | 58 +++--- .../Accounts/modals/AccountsModal.tsx | 88 ++++----- .../Accounts/modals/AddAccountModal.tsx | 126 ++++++------- .../Accounts/modals/ConfirmPasswordModal.tsx | 36 ++-- .../Accounts/modals/EditAccountModal.tsx | 86 ++++----- .../Accounts/modals/MnemonicModal.tsx | 116 ++++++------ .../components/Modals/ConfirmationModal.tsx | 10 +- .../src/components/Receive/ReceiveModal.tsx | 20 ++- nym-wallet/src/pages/terminal/index.tsx | 169 +++++++++--------- 9 files changed, 371 insertions(+), 338 deletions(-) diff --git a/nym-wallet/src/components/Accounts/MultiAccountHowTo.tsx b/nym-wallet/src/components/Accounts/MultiAccountHowTo.tsx index aca5552b2e..fa7ae1659c 100644 --- a/nym-wallet/src/components/Accounts/MultiAccountHowTo.tsx +++ b/nym-wallet/src/components/Accounts/MultiAccountHowTo.tsx @@ -11,35 +11,33 @@ const passwordCreationSteps = [ ]; export const MultiAccountHowTo = ({ show, handleClose }: { show: boolean; handleClose: () => void }) => ( - - - - - Multi accounts - - - - - theme.palette.nym.text.muted }}> - How to set up multiple accounts - - - - - (t.palette.mode === 'dark' ? { bgcolor: (theme) => theme.palette.background.paper } : {})} - > - In order to create multiple accounts your wallet needs a password. - Follow steps below to create password. - - How to create a password for your account - {passwordCreationSteps.map((step, index) => ( - {`${index + 1}. ${step}`} - ))} - - - + + + + Multi accounts + + + + + theme.palette.nym.text.muted }}> + How to set up multiple accounts + + + + + (t.palette.mode === 'dark' ? { bgcolor: (theme) => theme.palette.background.paper } : {})} + > + In order to create multiple accounts your wallet needs a password. + Follow steps below to create password. + + How to create a password for your account + {passwordCreationSteps.map((step, index) => ( + {`${index + 1}. ${step}`} + ))} + + ); diff --git a/nym-wallet/src/components/Accounts/modals/AccountsModal.tsx b/nym-wallet/src/components/Accounts/modals/AccountsModal.tsx index cb1fe51c1d..efe5a5428c 100644 --- a/nym-wallet/src/components/Accounts/modals/AccountsModal.tsx +++ b/nym-wallet/src/components/Accounts/modals/AccountsModal.tsx @@ -43,48 +43,52 @@ export const AccountsModal = () => { ); return ( - - - - - Accounts - - - - - - Switch between accounts - - - - {accounts?.map(({ id, address }) => ( - { - if (selectedAccount?.id !== id) { - setAccountToSwitchTo(id); - } - }} - /> - ))} - - - - - - - + + + + Accounts + + + + + + Switch between accounts + + + + {accounts?.map(({ id, address }) => ( + { + if (selectedAccount?.id !== id) { + setAccountToSwitchTo(id); + } + }} + /> + ))} + + + + + + ); }; diff --git a/nym-wallet/src/components/Accounts/modals/AddAccountModal.tsx b/nym-wallet/src/components/Accounts/modals/AddAccountModal.tsx index 097f6d7ad0..9c03cb164a 100644 --- a/nym-wallet/src/components/Accounts/modals/AddAccountModal.tsx +++ b/nym-wallet/src/components/Accounts/modals/AddAccountModal.tsx @@ -177,68 +177,72 @@ export const AddAccountModal = () => { }, [step]); return ( - - - - - {`${dialogToDisplay} new account`} - - - {dialogToDisplay === 'Add' ? createAccountSteps[step] : importAccountSteps[step]} - - - {(() => { - switch (step) { - case 0: - return dialogToDisplay === 'Add' ? ( - setStep((s) => s + 1)} - onBack={() => (step === 0 ? handleClose() : setStep((s) => s - 1))} - /> - ) : ( - setData((d) => ({ ...d, mnemonic: value }))} - onNext={() => setStep((s) => s + 1)} - onBack={() => (step === 0 ? handleClose() : setStep((s) => s - 1))} - /> - ); - case 1: - return ( - { - setData((d) => ({ ...d, accountName })); - setStep((s) => s + 1); - }} - onBack={() => setStep((s) => s - 1)} - /> - ); - case 2: - return ( - { - if (data.accountName && data.mnemonic) { - try { - await handleAddAccount({ accountName: data.accountName, mnemonic: data.mnemonic, password }); - setStep(0); - setDialogToDisplay('Accounts'); - } catch (e) { - Console.error(e as string); - } + + + + {`${dialogToDisplay} new account`} + + + {dialogToDisplay === 'Add' ? createAccountSteps[step] : importAccountSteps[step]} + + + {(() => { + switch (step) { + case 0: + return dialogToDisplay === 'Add' ? ( + setStep((s) => s + 1)} + onBack={() => (step === 0 ? handleClose() : setStep((s) => s - 1))} + /> + ) : ( + setData((d) => ({ ...d, mnemonic: value }))} + onNext={() => setStep((s) => s + 1)} + onBack={() => (step === 0 ? handleClose() : setStep((s) => s - 1))} + /> + ); + case 1: + return ( + { + setData((d) => ({ ...d, accountName })); + setStep((s) => s + 1); + }} + onBack={() => setStep((s) => s - 1)} + /> + ); + case 2: + return ( + { + if (data.accountName && data.mnemonic) { + try { + await handleAddAccount({ accountName: data.accountName, mnemonic: data.mnemonic, password }); + setStep(0); + setDialogToDisplay('Accounts'); + } catch (e) { + Console.error(e as string); } - }} - onCancel={() => setStep((s) => s - 1)} - isLoading={isLoading} - error={error} - /> - ); - default: - return null; - } - })()} - + } + }} + onCancel={() => setStep((s) => s - 1)} + isLoading={isLoading} + error={error} + /> + ); + default: + return null; + } + })()} ); }; diff --git a/nym-wallet/src/components/Accounts/modals/ConfirmPasswordModal.tsx b/nym-wallet/src/components/Accounts/modals/ConfirmPasswordModal.tsx index 5f9307bcdf..29694fcda8 100644 --- a/nym-wallet/src/components/Accounts/modals/ConfirmPasswordModal.tsx +++ b/nym-wallet/src/components/Accounts/modals/ConfirmPasswordModal.tsx @@ -16,22 +16,26 @@ export const ConfirmPasswordModal = ({ const { isLoading, error } = useContext(AccountsContext); return ( - - - - Switch account - - Confirm password - - - - + + + Switch account + + Confirm password + + + ); }; diff --git a/nym-wallet/src/components/Accounts/modals/EditAccountModal.tsx b/nym-wallet/src/components/Accounts/modals/EditAccountModal.tsx index c9d495a329..91a0a65e9d 100644 --- a/nym-wallet/src/components/Accounts/modals/EditAccountModal.tsx +++ b/nym-wallet/src/components/Accounts/modals/EditAccountModal.tsx @@ -24,48 +24,52 @@ export const EditAccountModal = () => { }, [accountToEdit]); return ( - setDialogToDisplay('Accounts')} fullWidth> - - - - Edit account name - setDialogToDisplay('Accounts')}> - - - - - New wallet address - - - - - setAccountName(e.target.value)} - autoFocus - /> - - - - - - + value={accountName} + onChange={(e) => setAccountName(e.target.value)} + autoFocus + /> + + + + + ); }; diff --git a/nym-wallet/src/components/Accounts/modals/MnemonicModal.tsx b/nym-wallet/src/components/Accounts/modals/MnemonicModal.tsx index 713a321f25..cffdeea213 100644 --- a/nym-wallet/src/components/Accounts/modals/MnemonicModal.tsx +++ b/nym-wallet/src/components/Accounts/modals/MnemonicModal.tsx @@ -40,63 +40,67 @@ export const MnemonicModal = () => { }; return ( - - - - - Display mnemonic - - - - - theme.palette.text.disabled }}> - {`Display mnemonic for: ${accountMnemonic?.accountName}`} - - - - - {error && ( - - {error} - - )} - {!accountMnemonic.value ? ( - <> - Enter the password used to login to your wallet - setPassword(pswrd)} - autoFocus - /> - - ) : ( - - )} - - - - {!accountMnemonic.value && ( - + + + + Display mnemonic + + + + + theme.palette.text.disabled }}> + {`Display mnemonic for: ${accountMnemonic?.accountName}`} + + + + + {error && ( + + {error} + )} - - + {!accountMnemonic.value ? ( + <> + Enter the password used to login to your wallet + setPassword(pswrd)} + autoFocus + /> + + ) : ( + + )} + + + + {!accountMnemonic.value && ( + + )} + ); }; diff --git a/nym-wallet/src/components/Modals/ConfirmationModal.tsx b/nym-wallet/src/components/Modals/ConfirmationModal.tsx index f02202afd6..cc7107ae66 100644 --- a/nym-wallet/src/components/Modals/ConfirmationModal.tsx +++ b/nym-wallet/src/components/Modals/ConfirmationModal.tsx @@ -72,12 +72,12 @@ export const ConfirmationModal = ({ sx={{ textAlign: 'center', ...sx }} fullWidth={fullWidth} BackdropProps={backdropProps} + PaperComponent={Paper} + PaperProps={{ elevation: 0 }} > - - {Title} - {children} - {ConfirmButton} - + {Title} + {children} + {ConfirmButton} ); }; diff --git a/nym-wallet/src/components/Receive/ReceiveModal.tsx b/nym-wallet/src/components/Receive/ReceiveModal.tsx index 0b13cf87dd..181e93c0c7 100644 --- a/nym-wallet/src/components/Receive/ReceiveModal.tsx +++ b/nym-wallet/src/components/Receive/ReceiveModal.tsx @@ -1,15 +1,15 @@ import React, { useContext } from 'react'; import { AppContext } from 'src/context'; -import { Box, Stack, Typography, SxProps, Dialog, DialogTitle, DialogContent } from '@mui/material'; +import { Box, Stack, Typography, SxProps, Dialog, DialogTitle, DialogContent, Paper } from '@mui/material'; import QRCode from 'qrcode.react'; import { ClientAddress } from '../ClientAddress'; import { ModalListItem } from '../Modals/ModalListItem'; import { Close as CloseIcon } from '@mui/icons-material'; export const ReceiveModal = ({ onClose }: { onClose: () => void; sx?: SxProps; backdropProps?: object }) => { - const { clientDetails } = useContext(AppContext); + const { clientDetails, mode } = useContext(AppContext); return ( - + @@ -22,8 +22,18 @@ export const ReceiveModal = ({ onClose }: { onClose: () => void; sx?: SxProps; b } /> - - `1px solid ${t.palette.nym.highlight}`, bgcolor: 'white', borderRadius: 2, p: 3 }}> + + `1px solid ${mode === 'light' ? t.palette.nym.highlight : t.palette.nym.text.grey} `, + bgcolor: mode === 'light' ? 'white' : 'nym.background.main', + borderRadius: 2, + p: 3, + }} + > {clientDetails && } diff --git a/nym-wallet/src/pages/terminal/index.tsx b/nym-wallet/src/pages/terminal/index.tsx index 13e3cc2dce..a5dce4167d 100644 --- a/nym-wallet/src/pages/terminal/index.tsx +++ b/nym-wallet/src/pages/terminal/index.tsx @@ -92,98 +92,103 @@ const TerminalInner: React.FC = () => { }, [network]); return ( - - - - - - Terminal - {!isBusy && } - - + + + + + Terminal + {!isBusy && } + + + } + dataTestid="terminal-page" + > +

State Viewer

+ + {error && {error}} + + {status ? ( + } sx={{ mb: 2 }}> + {status} + + ) : ( + + Data loading complete + + )} + + +
{JSON.stringify(appEnv, null, 2)}
+
+ + +
{JSON.stringify(clientDetails, null, 2)}
+
+ + +
{JSON.stringify(userBalance, null, 2)}
+
+ + + useGetBalance Balance + } - dataTestid="terminal-page" > -

State Viewer

+
{JSON.stringify(userBalance.balance, null, 2)}
+
- {error && {error}} + + useGetBalance Vesting Account Info + + } + > +
{JSON.stringify(userBalance.vestingAccountInfo, null, 2)}
+
- {status ? ( - } sx={{ mb: 2 }}> - {status} - - ) : ( - - Data loading complete - - )} + + useGetBalance Current Vest Period + + } + > +
{JSON.stringify(userBalance.currentVestingPeriod, null, 2)}
+
- -
{JSON.stringify(appEnv, null, 2)}
-
+ +
{JSON.stringify(userBalance.originalVesting, null, 2)}
+
- -
{JSON.stringify(clientDetails, null, 2)}
-
+ +
{JSON.stringify(mixnodeDelegations, null, 2)}
+
- -
{JSON.stringify(userBalance, null, 2)}
-
+ +
{JSON.stringify(pendingEvents, null, 2)}
+
- - useGetBalance Balance - - } - > -
{JSON.stringify(userBalance.balance, null, 2)}
-
+ +
{JSON.stringify(pendingVestingEvents, null, 2)}
+
- - useGetBalance Vesting Account Info - - } - > -
{JSON.stringify(userBalance.vestingAccountInfo, null, 2)}
-
- - - useGetBalance Current Vest Period - - } - > -
{JSON.stringify(userBalance.currentVestingPeriod, null, 2)}
-
- - -
{JSON.stringify(userBalance.originalVesting, null, 2)}
-
- - -
{JSON.stringify(mixnodeDelegations, null, 2)}
-
- - -
{JSON.stringify(pendingEvents, null, 2)}
-
- - -
{JSON.stringify(pendingVestingEvents, null, 2)}
-
- - -
{JSON.stringify(epoch, null, 2)}
-
- - + +
{JSON.stringify(epoch, null, 2)}
+
+
); }; From 5a7f29632875e33a3e1f1132f82c708e17e36330 Mon Sep 17 00:00:00 2001 From: Drazen Urch Date: Tue, 6 Sep 2022 14:15:22 +0200 Subject: [PATCH 09/46] Update validator-api dependencies (#1589) --- Cargo.lock | 1480 ++++++++++------- .../mixnet-contract/src/mixnode.rs | 1 - validator-api/Cargo.toml | 83 +- validator-api/src/main.rs | 12 +- 4 files changed, 927 insertions(+), 649 deletions(-) diff --git a/Cargo.lock b/Cargo.lock index 363c907a18..6d495b6a06 100644 --- a/Cargo.lock +++ b/Cargo.lock @@ -20,7 +20,7 @@ version = "0.4.3" source = "registry+https://github.com/rust-lang/crates.io-index" checksum = "0b613b8e1e3cf911a086f53f03bf286f52fd7a7258e4fa606f0ef220d39d8877" dependencies = [ - "generic-array 0.14.5", + "generic-array 0.14.6", ] [[package]] @@ -67,16 +67,16 @@ version = "0.7.6" source = "registry+https://github.com/rust-lang/crates.io-index" checksum = "fcb51a0695d8f838b1ee009b3fbf66bda078cd64590202a864a8f3e8c4315c47" dependencies = [ - "getrandom 0.2.6", + "getrandom 0.2.7", "once_cell", "version_check", ] [[package]] name = "aho-corasick" -version = "0.7.18" +version = "0.7.19" source = "registry+https://github.com/rust-lang/crates.io-index" -checksum = "1e37cfd5e7657ada45f742d6e99ca5788580b5c529dc78faf11ece6dc702656f" +checksum = "b4f55bd91a0978cbfd91c457a164bab8b4001c833b7f323132c0a4e1922dd44e" dependencies = [ "memchr", ] @@ -92,9 +92,9 @@ dependencies = [ [[package]] name = "anyhow" -version = "1.0.56" +version = "1.0.64" source = "registry+https://github.com/rust-lang/crates.io-index" -checksum = "4361135be9122e0870de935d7c439aef945b9f9ddd4199a553b5270b49c82a27" +checksum = "b9a8f622bcf6ff3df478e9deba3e03e4e04b300f8e6a139e192c05fa3490afc7" [[package]] name = "arrayref" @@ -137,9 +137,9 @@ dependencies = [ [[package]] name = "async-trait" -version = "0.1.53" +version = "0.1.57" source = "registry+https://github.com/rust-lang/crates.io-index" -checksum = "ed6aa3524a2dfcf9fe180c51eae2b58738348d819517ceadf95789c51fff7600" +checksum = "76464446b8bc32758d7e88ee1a804d9914cd9b1cb264c029899680b0be29826f" dependencies = [ "proc-macro2", "quote", @@ -155,6 +155,15 @@ dependencies = [ "num-traits", ] +[[package]] +name = "atoi" +version = "1.0.0" +source = "registry+https://github.com/rust-lang/crates.io-index" +checksum = "d7c57d12312ff59c811c0643f4d80830505833c9ffaebd193d819392b265be8e" +dependencies = [ + "num-traits", +] + [[package]] name = "atomic" version = "0.5.1" @@ -208,10 +217,53 @@ source = "registry+https://github.com/rust-lang/crates.io-index" checksum = "d468802bab17cbc0cc575e9b053f41e72aa36bfa6b7f55e3529ffa43161b97fa" [[package]] -name = "az" -version = "1.2.0" +name = "axum" +version = "0.5.15" source = "registry+https://github.com/rust-lang/crates.io-index" -checksum = "f771a5d1f5503f7f4279a30f3643d3421ba149848b89ecaaec0ea2acf04a5ac4" +checksum = "9de18bc5f2e9df8f52da03856bf40e29b747de5a84e43aefff90e3dc4a21529b" +dependencies = [ + "async-trait", + "axum-core", + "bitflags", + "bytes", + "futures-util", + "http", + "http-body", + "hyper", + "itoa 1.0.3", + "matchit", + "memchr", + "mime", + "percent-encoding", + "pin-project-lite", + "serde", + "sync_wrapper", + "tokio", + "tower", + "tower-http", + "tower-layer", + "tower-service", +] + +[[package]] +name = "axum-core" +version = "0.2.7" +source = "registry+https://github.com/rust-lang/crates.io-index" +checksum = "e4f44a0e6200e9d11a1cdc989e4b358f6e3d354fbf48478f345a17f4e43f8635" +dependencies = [ + "async-trait", + "bytes", + "futures-util", + "http", + "http-body", + "mime", +] + +[[package]] +name = "az" +version = "1.2.1" +source = "registry+https://github.com/rust-lang/crates.io-index" +checksum = "7b7e4c2464d97fe331d41de9d5db0def0a96f4d823b8b32a2efd503578988973" [[package]] name = "bandwidth-claim-contract" @@ -235,9 +287,9 @@ checksum = "904dfeac50f3cdaba28fc6f57fdcddb75f49ed61346676a78c4ffe55877802fd" [[package]] name = "base64ct" -version = "1.0.1" +version = "1.5.2" source = "registry+https://github.com/rust-lang/crates.io-index" -checksum = "8a32fd6af2b5827bce66c29053ba0e7c42b9dcab01835835058558c10851a46b" +checksum = "ea2b2456fd614d856680dcd9fcc660a51a820fa09daef2e49772b56a193c8474" [[package]] name = "binascii" @@ -311,9 +363,9 @@ dependencies = [ [[package]] name = "bitvec" -version = "1.0.0" +version = "1.0.1" source = "registry+https://github.com/rust-lang/crates.io-index" -checksum = "1489fcb93a5bb47da0462ca93ad252ad6af2145cce58d10d46a83931ba9f016b" +checksum = "1bc2832c24239b0141d5674bb9174f9d68a8b5b3f2753311927c172ca46f7e9c" dependencies = [ "funty 2.0.0", "radium 0.7.0", @@ -347,44 +399,23 @@ dependencies = [ "digest 0.10.3", ] -[[package]] -name = "block-buffer" -version = "0.7.3" -source = "registry+https://github.com/rust-lang/crates.io-index" -checksum = "c0940dc441f31689269e10ac70eb1002a3a1d3ad1390e030043662eb7fe4688b" -dependencies = [ - "block-padding 0.1.5", - "byte-tools", - "byteorder", - "generic-array 0.12.4", -] - [[package]] name = "block-buffer" version = "0.9.0" source = "registry+https://github.com/rust-lang/crates.io-index" checksum = "4152116fd6e9dadb291ae18fc1ec3575ed6d84c29642d97890f4b4a3417297e4" dependencies = [ - "block-padding 0.2.1", - "generic-array 0.14.5", + "block-padding", + "generic-array 0.14.6", ] [[package]] name = "block-buffer" -version = "0.10.2" +version = "0.10.3" source = "registry+https://github.com/rust-lang/crates.io-index" -checksum = "0bf7fe51849ea569fd452f37822f606a5cabb684dc918707a0193fd4664ff324" +checksum = "69cce20737498f97b993470a6e536b8523f0af7892a4f928cceb1ac5e52ebe7e" dependencies = [ - "generic-array 0.14.5", -] - -[[package]] -name = "block-padding" -version = "0.1.5" -source = "registry+https://github.com/rust-lang/crates.io-index" -checksum = "fa79dedbb091f449f1f39e53edf88d5dbe95f895dae6135a8d7b881fb5af73f5" -dependencies = [ - "byte-tools", + "generic-array 0.14.6", ] [[package]] @@ -413,7 +444,7 @@ version = "0.6.0" source = "git+https://github.com/jstuczyn/bls12_381?branch=gt-serialisation#10fb6f700bfda17c8475af3bfd31e3fec15f2278" dependencies = [ "digest 0.9.0", - "ff 0.11.0", + "ff 0.11.1", "group 0.11.0", "pairing 0.21.0", "rand_core 0.6.3", @@ -444,9 +475,9 @@ dependencies = [ [[package]] name = "bumpalo" -version = "3.9.1" +version = "3.11.0" source = "registry+https://github.com/rust-lang/crates.io-index" -checksum = "a4a45a46ab1f2412e53d3a0ade76ffad2025804294569aae387231a0cd6e0899" +checksum = "c1ad822118d20d2c234f427000d5acc36eabe1e29a348c89b63dd60b13f28e5d" [[package]] name = "byte-slice-cast" @@ -462,9 +493,9 @@ checksum = "e3b5ca7a04898ad4bcd41c90c5285445ff5b791899bb1b0abdd2a2aa791211d7" [[package]] name = "bytemuck" -version = "1.9.1" +version = "1.12.1" source = "registry+https://github.com/rust-lang/crates.io-index" -checksum = "cdead85bdec19c194affaeeb670c0e41fe23de31459efd1c174d049269cf02cc" +checksum = "2f5715e491b5a1598fc2bef5a606847b5dc1d48ea625bd3c02c00de8285591da" [[package]] name = "byteorder" @@ -474,18 +505,15 @@ checksum = "14c189c53d098945499cdfa7ecc63567cf3886b3332b312a5b4585d8d3a6a610" [[package]] name = "bytes" -version = "1.1.0" +version = "1.2.1" source = "registry+https://github.com/rust-lang/crates.io-index" -checksum = "c4872d67bab6358e59559027aa3b9157c53d9358c51423c17554809a8858e0f8" +checksum = "ec8a7b6a70fde80372154c65702f00a0f56f3e1c36abbc6c440484be248856db" [[package]] name = "cast" -version = "0.2.7" +version = "0.3.0" source = "registry+https://github.com/rust-lang/crates.io-index" -checksum = "4c24dab4283a142afa2fdca129b80ad2c6284e073930f964c3a1293c225ee39a" -dependencies = [ - "rustc_version 0.4.0", -] +checksum = "37b2a672a2cb129a2e41c10b1224bb368f9f37a2b16b612598138befd7b37eb5" [[package]] name = "cc" @@ -520,15 +548,16 @@ dependencies = [ [[package]] name = "chrono" -version = "0.4.19" +version = "0.4.20" source = "registry+https://github.com/rust-lang/crates.io-index" -checksum = "670ad68c9088c2a963aaa298cb369688cf3f9465ce5e2d4ca10e6e0098a1ce73" +checksum = "6127248204b9aba09a362f6c930ef6a78f2c1b2215f8a7b398c06e1083f17af0" dependencies = [ - "libc", + "js-sys", "num-integer", "num-traits", "serde", "time 0.1.44", + "wasm-bindgen", "winapi", ] @@ -538,7 +567,7 @@ version = "0.3.0" source = "registry+https://github.com/rust-lang/crates.io-index" checksum = "7ee52072ec15386f770805afd189a01c8841be8696bed250fa2f13c4c0d6dfb7" dependencies = [ - "generic-array 0.14.5", + "generic-array 0.14.6", ] [[package]] @@ -568,9 +597,9 @@ dependencies = [ [[package]] name = "clap" -version = "3.2.8" +version = "3.2.20" source = "registry+https://github.com/rust-lang/crates.io-index" -checksum = "190814073e85d238f31ff738fcb0bf6910cedeb73376c87cd69291028966fd83" +checksum = "23b71c3ce99b7611011217b366d923f1d0a7e07a92bb2dbf1e84508c673ca3bd" dependencies = [ "atty", "bitflags", @@ -604,9 +633,9 @@ dependencies = [ [[package]] name = "clap_derive" -version = "3.2.7" +version = "3.2.18" source = "registry+https://github.com/rust-lang/crates.io-index" -checksum = "759bf187376e1afa7b85b959e6a664a3e7a95203415dba952ad19139e798f902" +checksum = "ea0c8bce528c4be4da13ea6fead8965e95b6073585a2f05204bd8f4119f82a65" dependencies = [ "heck 0.4.0", "proc-macro-error", @@ -718,22 +747,21 @@ dependencies = [ [[package]] name = "console-api" -version = "0.1.2" +version = "0.4.0" source = "registry+https://github.com/rust-lang/crates.io-index" -checksum = "cc347c19eb5b940f396ac155822caee6662f850d97306890ac3773ed76c90c5a" +checksum = "e57ff02e8ad8e06ab9731d5dc72dc23bef9200778eae1a89d555d8c42e5d4a86" dependencies = [ - "prost 0.9.0", - "prost-types 0.9.0", + "prost 0.11.0", + "prost-types 0.11.1", "tonic", - "tonic-build", "tracing-core", ] [[package]] name = "console-subscriber" -version = "0.1.3" +version = "0.1.8" source = "registry+https://github.com/rust-lang/crates.io-index" -checksum = "565a7dfea2d10dd0e5c57cc394d5d441b1910960d8c9211ed14135e0e6ec3a20" +checksum = "22a3a81dfaf6b66bce5d159eddae701e3a002f194d378cbf7be5f053c281d9be" dependencies = [ "console-api", "crossbeam-channel", @@ -741,7 +769,7 @@ dependencies = [ "futures", "hdrhistogram", "humantime 2.1.0", - "prost-types 0.9.0", + "prost-types 0.11.1", "serde", "serde_json", "thread_local", @@ -790,9 +818,9 @@ dependencies = [ "hmac 0.12.1", "percent-encoding", "rand 0.8.5", - "sha2 0.10.2", + "sha2 0.10.5", "subtle 2.4.1", - "time 0.3.9", + "time 0.3.14", "version_check", ] @@ -817,7 +845,7 @@ name = "cosmos-sdk-proto" version = "0.12.3" source = "git+https://github.com/neacsu/cosmos-rust?branch=neacsu/feegrant_support#f63ded63ec13e753ebe8bdafe9dc503df265d67d" dependencies = [ - "prost 0.10.3", + "prost 0.10.4", "prost-types 0.10.1", "tendermint-proto", ] @@ -831,9 +859,9 @@ dependencies = [ "cosmos-sdk-proto", "ecdsa", "eyre", - "getrandom 0.2.6", + "getrandom 0.2.7", "k256", - "prost 0.10.3", + "prost 0.10.4", "prost-types 0.10.1", "rand_core 0.6.3", "serde", @@ -885,9 +913,9 @@ dependencies = [ [[package]] name = "cpufeatures" -version = "0.2.2" +version = "0.2.5" source = "registry+https://github.com/rust-lang/crates.io-index" -checksum = "59a6001667ab124aebae2a495118e11d30984c3a653e99d86d58971708cf5e4b" +checksum = "28d997bd5e24a5928dd43e46dc529867e207907fe0b239c3477d924f7f2ca320" dependencies = [ "libc", ] @@ -898,7 +926,16 @@ version = "2.1.0" source = "registry+https://github.com/rust-lang/crates.io-index" checksum = "49fc9a695bca7f35f5f4c15cddc84415f66a74ea78eef08e90c5024f2b540e23" dependencies = [ - "crc-catalog", + "crc-catalog 1.1.1", +] + +[[package]] +name = "crc" +version = "3.0.0" +source = "registry+https://github.com/rust-lang/crates.io-index" +checksum = "53757d12b596c16c78b83458d732a5d1a17ab3f53f2f7412f6fb57cc8a140ab3" +dependencies = [ + "crc-catalog 2.1.0", ] [[package]] @@ -907,6 +944,12 @@ version = "1.1.1" source = "registry+https://github.com/rust-lang/crates.io-index" checksum = "ccaeedb56da03b09f598226e25e80088cb4cd25f316e6e4df7d695f0feeb1403" +[[package]] +name = "crc-catalog" +version = "2.1.0" +source = "registry+https://github.com/rust-lang/crates.io-index" +checksum = "2d0165d2900ae6778e36e80bbc4da3b5eefccee9ba939761f9c2882a5d9af3ff" + [[package]] name = "crc32fast" version = "1.3.2" @@ -923,7 +966,7 @@ dependencies = [ "async-trait", "bip39", "cfg-if 0.1.10", - "clap 3.2.8", + "clap 3.2.20", "coconut-interface", "config", "credential-storage", @@ -947,7 +990,7 @@ dependencies = [ "async-trait", "log", "nymcoconut", - "sqlx", + "sqlx 0.5.13", "thiserror", "tokio", ] @@ -969,9 +1012,9 @@ dependencies = [ [[package]] name = "criterion" -version = "0.3.5" +version = "0.3.6" source = "registry+https://github.com/rust-lang/crates.io-index" -checksum = "1604dafd25fba2fe2d5895a9da139f8dc9b319a5fe5354ca137cbbce4e178d10" +checksum = "b01d6de93b2b6c65e17c634a26653a29d107b3c98c607c765bf38d041531cd8f" dependencies = [ "atty", "cast", @@ -995,9 +1038,9 @@ dependencies = [ [[package]] name = "criterion-plot" -version = "0.4.4" +version = "0.4.5" source = "registry+https://github.com/rust-lang/crates.io-index" -checksum = "d00996de9f2f7559f7f4dc286073197f83e92256a59ed395f9aac01fe717da57" +checksum = "2673cc8207403546f45f5fd319a974b1e6983ad1a3ee7e6041650013be041876" dependencies = [ "cast", "itertools", @@ -1005,9 +1048,9 @@ dependencies = [ [[package]] name = "crossbeam-channel" -version = "0.5.4" +version = "0.5.6" source = "registry+https://github.com/rust-lang/crates.io-index" -checksum = "5aaa7bd5fb665c6864b5f963dd9097905c54125909c7aa94c9e18507cdbe6c53" +checksum = "c2dd04ddaf88237dc3b8d8f9a3c1004b506b54b3313403944054d23c0870c521" dependencies = [ "cfg-if 1.0.0", "crossbeam-utils", @@ -1015,9 +1058,9 @@ dependencies = [ [[package]] name = "crossbeam-deque" -version = "0.8.1" +version = "0.8.2" source = "registry+https://github.com/rust-lang/crates.io-index" -checksum = "6455c0ca19f0d2fbf751b908d5c55c1f5cbc65e03c4225427254b46890bdde1e" +checksum = "715e8152b692bba2d374b53d4875445368fdf21a94751410af607a5ac677d1fc" dependencies = [ "cfg-if 1.0.0", "crossbeam-epoch", @@ -1026,23 +1069,23 @@ dependencies = [ [[package]] name = "crossbeam-epoch" -version = "0.9.8" +version = "0.9.10" source = "registry+https://github.com/rust-lang/crates.io-index" -checksum = "1145cf131a2c6ba0615079ab6a638f7e1973ac9c2634fcbeaaad6114246efe8c" +checksum = "045ebe27666471bb549370b4b0b3e51b07f56325befa4284db65fc89c02511b1" dependencies = [ "autocfg 1.1.0", "cfg-if 1.0.0", "crossbeam-utils", - "lazy_static", "memoffset", + "once_cell", "scopeguard", ] [[package]] name = "crossbeam-queue" -version = "0.3.5" +version = "0.3.6" source = "registry+https://github.com/rust-lang/crates.io-index" -checksum = "1f25d8400f4a7a5778f0e4e52384a48cbd9b5c495d110786187fc750075277a2" +checksum = "1cd42583b04998a5363558e5f9291ee5a5ff6b49944332103f251e7479a82aa7" dependencies = [ "cfg-if 1.0.0", "crossbeam-utils", @@ -1050,12 +1093,12 @@ dependencies = [ [[package]] name = "crossbeam-utils" -version = "0.8.8" +version = "0.8.11" source = "registry+https://github.com/rust-lang/crates.io-index" -checksum = "0bf124c720b7686e3c2663cf54062ab0f68a88af2fb6a030e87e30bf721fcb38" +checksum = "51887d4adc7b564537b15adcfb307936f8075dfcd5f00dde9a9f1d29383682bc" dependencies = [ "cfg-if 1.0.0", - "lazy_static", + "once_cell", ] [[package]] @@ -1101,7 +1144,7 @@ dependencies = [ "ctr 0.9.1", "digest 0.10.3", "ed25519-dalek", - "generic-array 0.14.5", + "generic-array 0.14.6", "hkdf 0.12.3", "hmac 0.12.1", "nymsphinx-types", @@ -1120,7 +1163,7 @@ version = "0.3.2" source = "registry+https://github.com/rust-lang/crates.io-index" checksum = "03c6a1d5fa1de37e071642dfa44ec552ca5b299adb128fab16138e24b548fd21" dependencies = [ - "generic-array 0.14.5", + "generic-array 0.14.6", "rand_core 0.6.3", "subtle 2.4.1", "zeroize", @@ -1128,11 +1171,11 @@ dependencies = [ [[package]] name = "crypto-common" -version = "0.1.3" +version = "0.1.6" source = "registry+https://github.com/rust-lang/crates.io-index" -checksum = "57952ca27b5e3606ff4dd79b0020231aaf9d6aa76dc05fd30137538c50bd3ce8" +checksum = "1bfb12502f3fc46cca1bb51ac28df9d618d813cdc3d2f25b9fe775a34af26bb3" dependencies = [ - "generic-array 0.14.5", + "generic-array 0.14.6", "typenum", ] @@ -1152,7 +1195,7 @@ version = "0.11.1" source = "registry+https://github.com/rust-lang/crates.io-index" checksum = "b1d1a86f49236c215f271d40892d5fc950490551400b02ef360692c29815c714" dependencies = [ - "generic-array 0.14.5", + "generic-array 0.14.6", "subtle 2.4.1", ] @@ -1184,7 +1227,7 @@ version = "0.8.0" source = "registry+https://github.com/rust-lang/crates.io-index" checksum = "c1a816186fa68d9e426e3cb4ae4dff1fcd8e4a2c34b781bf7a822574a0d0aac8" dependencies = [ - "sct", + "sct 0.6.1", ] [[package]] @@ -1242,9 +1285,9 @@ dependencies = [ [[package]] name = "cw-utils" -version = "0.13.2" +version = "0.13.4" source = "registry+https://github.com/rust-lang/crates.io-index" -checksum = "babd2c090f39d07ce5bf2556962305e795daa048ce20a93709eb591476e4a29e" +checksum = "9dbaecb78c8e8abfd6b4258c7f4fbeb5c49a5e45ee4d910d3240ee8e1d714e1b" dependencies = [ "cosmwasm-std", "schemars", @@ -1254,9 +1297,9 @@ dependencies = [ [[package]] name = "cw3" -version = "0.13.2" +version = "0.13.4" source = "registry+https://github.com/rust-lang/crates.io-index" -checksum = "f871854338a54c7bb094d16ffe17212b93b146d9659dbce4c9402a9b77e240ef" +checksum = "fe19462a7f644ba60c19d3443cb90d00c50d9b6b3b0a3a7fca93df8261af979b" dependencies = [ "cosmwasm-std", "cw-utils", @@ -1266,9 +1309,9 @@ dependencies = [ [[package]] name = "cw4" -version = "0.13.2" +version = "0.13.4" source = "registry+https://github.com/rust-lang/crates.io-index" -checksum = "c4476d6a7c13c46ed9ff260bd0e1cf648dc37b13f483822e1ff2a431f0f6ee52" +checksum = "0acc3549d5ce11c6901b3a676f2e2628684722197054d97cd0101ea174ed5cbd" dependencies = [ "cosmwasm-std", "cw-storage-plus", @@ -1391,7 +1434,7 @@ version = "0.9.0" source = "registry+https://github.com/rust-lang/crates.io-index" checksum = "d3dd60d1080a57a05ab032377049e0591415d2b31afd7028356dbf3cc6dcb066" dependencies = [ - "generic-array 0.14.5", + "generic-array 0.14.6", ] [[package]] @@ -1400,7 +1443,7 @@ version = "0.10.3" source = "registry+https://github.com/rust-lang/crates.io-index" checksum = "f2fb860ca6fafa5552fb6d0e816a69c8e49f0908bf524e30a90d97c85892d506" dependencies = [ - "block-buffer 0.10.2", + "block-buffer 0.10.3", "crypto-common", "subtle 2.4.1", ] @@ -1429,11 +1472,11 @@ dependencies = [ name = "dkg" version = "0.1.0" dependencies = [ - "bitvec 1.0.0", + "bitvec 1.0.1", "bls12_381 0.6.0", "bs58", "criterion", - "ff 0.11.0", + "ff 0.11.1", "group 0.11.0", "lazy_static", "rand 0.8.5", @@ -1459,10 +1502,19 @@ source = "registry+https://github.com/rust-lang/crates.io-index" checksum = "77c90badedccf4105eca100756a0b1289e191f6fcbdadd3cee1d2f614f97da8f" [[package]] -name = "dyn-clone" -version = "1.0.5" +name = "dotenvy" +version = "0.15.3" source = "registry+https://github.com/rust-lang/crates.io-index" -checksum = "21e50f3adc76d6a43f5ed73b698a87d0760ca74617f60f7c3b879003536fdd28" +checksum = "da3db6fcad7c1fc4abdd99bf5276a4db30d6a819127903a709ed41e5ff016e84" +dependencies = [ + "dirs", +] + +[[package]] +name = "dyn-clone" +version = "1.0.9" +source = "registry+https://github.com/rust-lang/crates.io-index" +checksum = "4f94fa09c2aeea5b8839e414b7b841bf429fd25b9c522116ac97ee87856d88b2" [[package]] name = "ecdsa" @@ -1478,9 +1530,9 @@ dependencies = [ [[package]] name = "ed25519" -version = "1.4.1" +version = "1.5.2" source = "registry+https://github.com/rust-lang/crates.io-index" -checksum = "3d5c4b5e5959dc2c2b89918d8e2cc40fcdd623cef026ed09d2f0ee05199dc8e4" +checksum = "1e9c280362032ea4203659fc489832d0204ef09f247a0506f170dafcac08c369" dependencies = [ "serde", "signature", @@ -1518,9 +1570,9 @@ dependencies = [ [[package]] name = "either" -version = "1.6.1" +version = "1.8.0" source = "registry+https://github.com/rust-lang/crates.io-index" -checksum = "e78d4f1cc4ae33bbfc157ed5d5a5ef3bc29227303d595861deb238fcec4e9457" +checksum = "90e5c1c8368803113bf0c9584fc495a58b86dc8a29edbf8fe877d21d9507e797" [[package]] name = "elliptic-curve" @@ -1531,8 +1583,8 @@ dependencies = [ "base16ct", "crypto-bigint", "der", - "ff 0.11.0", - "generic-array 0.14.5", + "ff 0.11.1", + "generic-array 0.14.6", "group 0.11.0", "rand_core 0.6.3", "sec1", @@ -1551,18 +1603,18 @@ dependencies = [ [[package]] name = "enum-iterator" -version = "0.7.0" +version = "0.8.1" source = "registry+https://github.com/rust-lang/crates.io-index" -checksum = "4eeac5c5edb79e4e39fe8439ef35207780a11f69c52cbe424ce3dfad4cb78de6" +checksum = "2953d1df47ac0eb70086ccabf0275aa8da8591a28bd358ee2b52bd9f9e3ff9e9" dependencies = [ "enum-iterator-derive", ] [[package]] name = "enum-iterator-derive" -version = "0.7.0" +version = "0.8.1" source = "registry+https://github.com/rust-lang/crates.io-index" -checksum = "c134c37760b27a871ba422106eedbb8247da973a09e82558bf26d619c882b159" +checksum = "8958699f9359f0b04e691a13850d48b7de329138023876d07cbd024c2c820598" dependencies = [ "proc-macro2", "quote", @@ -1634,6 +1686,12 @@ dependencies = [ "uint", ] +[[package]] +name = "event-listener" +version = "2.5.3" +source = "registry+https://github.com/rust-lang/crates.io-index" +checksum = "0206175f82b8d6bf6652ff7d71a1e27fd2e4efde587fd368662814d6ec1d9ce0" + [[package]] name = "execute" version = "0.1.0" @@ -1647,7 +1705,7 @@ name = "explorer-api" version = "1.0.1" dependencies = [ "chrono", - "clap 3.2.8", + "clap 3.2.20", "humantime-serde", "isocountry", "itertools", @@ -1679,17 +1737,11 @@ dependencies = [ "once_cell", ] -[[package]] -name = "fake-simd" -version = "0.1.2" -source = "registry+https://github.com/rust-lang/crates.io-index" -checksum = "e88a8acf291dafb59c2d96e8f59828f3838bb1a70398823ade51a84de6a6deed" - [[package]] name = "fastrand" -version = "1.7.0" +version = "1.8.0" source = "registry+https://github.com/rust-lang/crates.io-index" -checksum = "c3fcf0cee53519c866c09b5de1f6c56ff9d647101f81c1964fa632e148896cdf" +checksum = "a7a407cfaa3385c4ae6b23e84623d48c2798d06e3e6a1878f7f59f17b3f86499" dependencies = [ "instant", ] @@ -1706,9 +1758,9 @@ dependencies = [ [[package]] name = "ff" -version = "0.11.0" +version = "0.11.1" source = "registry+https://github.com/rust-lang/crates.io-index" -checksum = "b2958d04124b9f27f175eaeb9a9f383d026098aa837eadd8ba22c11f13a05b9e" +checksum = "131655483be284720a17d74ff97592b8e76576dc25563148601df2d7c9080924" dependencies = [ "rand_core 0.6.3", "subtle 2.4.1", @@ -1730,13 +1782,13 @@ dependencies = [ [[package]] name = "fixed" -version = "1.15.0" +version = "1.19.0" source = "registry+https://github.com/rust-lang/crates.io-index" -checksum = "36a65312835c1097a0c926ff3702df965285fadc33d948b87397ff8961bad881" +checksum = "e0371cd413fb63f8ec1b9eb4dff47fa2c88b21abc681771234c84808b9920991" dependencies = [ "az", "bytemuck", - "half", + "half 2.1.0", "serde", "typenum", ] @@ -1753,21 +1805,13 @@ dependencies = [ "static_assertions", ] -[[package]] -name = "fixedbitset" -version = "0.4.1" -source = "registry+https://github.com/rust-lang/crates.io-index" -checksum = "279fb028e20b3c4c320317955b77c5e0c9701f05a1d309905d6fc702cdc5053e" - [[package]] name = "flate2" -version = "1.0.22" +version = "1.0.24" source = "registry+https://github.com/rust-lang/crates.io-index" -checksum = "1e6988e897c1c9c485f43b47a529cef42fde0547f9d8d41a7062518f1d8fc53f" +checksum = "f82b0f4c27ad9f8bfd1f3208d882da2b09c301bc1c828fd3a00d0216d2fbbff6" dependencies = [ - "cfg-if 1.0.0", "crc32fast", - "libc", "miniz_oxide", ] @@ -1783,14 +1827,14 @@ dependencies = [ [[package]] name = "flume" -version = "0.10.12" +version = "0.10.14" source = "registry+https://github.com/rust-lang/crates.io-index" -checksum = "843c03199d0c0ca54bc1ea90ac0d507274c28abcc4f691ae8b4eaa375087c76a" +checksum = "1657b4441c3403d9f7b3409e47575237dac27b1b5726df654a6ecbf92f0f7577" dependencies = [ "futures-core", "futures-sink", "pin-project", - "spin 0.9.2", + "spin 0.9.4", ] [[package]] @@ -1875,9 +1919,9 @@ checksum = "e6d5a32815ae3f33302d95fdcb2ce17862f8c65363dcfd29360480ba1001fc9c" [[package]] name = "futures" -version = "0.3.21" +version = "0.3.24" source = "registry+https://github.com/rust-lang/crates.io-index" -checksum = "f73fe65f54d1e12b726f517d3e2135ca3125a437b6d998caf1962961f7172d9e" +checksum = "7f21eda599937fba36daeb58a22e8f5cee2d14c4a17b5b7739c7c8e5e3b8230c" dependencies = [ "futures-channel", "futures-core", @@ -1890,9 +1934,9 @@ dependencies = [ [[package]] name = "futures-channel" -version = "0.3.21" +version = "0.3.24" source = "registry+https://github.com/rust-lang/crates.io-index" -checksum = "c3083ce4b914124575708913bca19bfe887522d6e2e6d0952943f5eac4a74010" +checksum = "30bdd20c28fadd505d0fd6712cdfcb0d4b5648baf45faef7f852afb2399bb050" dependencies = [ "futures-core", "futures-sink", @@ -1900,15 +1944,15 @@ dependencies = [ [[package]] name = "futures-core" -version = "0.3.21" +version = "0.3.24" source = "registry+https://github.com/rust-lang/crates.io-index" -checksum = "0c09fd04b7e4073ac7156a9539b57a484a8ea920f79c7c675d05d289ab6110d3" +checksum = "4e5aa3de05362c3fb88de6531e6296e85cde7739cccad4b9dfeeb7f6ebce56bf" [[package]] name = "futures-executor" -version = "0.3.21" +version = "0.3.24" source = "registry+https://github.com/rust-lang/crates.io-index" -checksum = "9420b90cfa29e327d0429f19be13e7ddb68fa1cccb09d65e5706b8c7a749b8a6" +checksum = "9ff63c23854bee61b6e9cd331d523909f238fc7636290b96826e9cfa5faa00ab" dependencies = [ "futures-core", "futures-task", @@ -1928,15 +1972,15 @@ dependencies = [ [[package]] name = "futures-io" -version = "0.3.21" +version = "0.3.24" source = "registry+https://github.com/rust-lang/crates.io-index" -checksum = "fc4045962a5a5e935ee2fdedaa4e08284547402885ab326734432bed5d12966b" +checksum = "bbf4d2a7a308fd4578637c0b17c7e1c7ba127b8f6ba00b29f717e9655d85eb68" [[package]] name = "futures-macro" -version = "0.3.21" +version = "0.3.24" source = "registry+https://github.com/rust-lang/crates.io-index" -checksum = "33c1e13800337f4d4d7a316bf45a567dbcb6ffe087f16424852d97e97a91f512" +checksum = "42cd15d1c7456c04dbdf7e88bcd69760d74f3a798d6444e16974b505b0e62f17" dependencies = [ "proc-macro2", "quote", @@ -1945,15 +1989,15 @@ dependencies = [ [[package]] name = "futures-sink" -version = "0.3.21" +version = "0.3.24" source = "registry+https://github.com/rust-lang/crates.io-index" -checksum = "21163e139fa306126e6eedaf49ecdb4588f939600f0b1e770f4205ee4b7fa868" +checksum = "21b20ba5a92e727ba30e72834706623d94ac93a725410b6a6b6fbc1b07f7ba56" [[package]] name = "futures-task" -version = "0.3.21" +version = "0.3.24" source = "registry+https://github.com/rust-lang/crates.io-index" -checksum = "57c66a976bf5909d801bbef33416c41372779507e7a6b3a5e25e4749c58f776a" +checksum = "a6508c467c73851293f390476d4491cf4d227dbabcd4170f3bb6044959b294f1" [[package]] name = "futures-timer" @@ -1967,9 +2011,9 @@ dependencies = [ [[package]] name = "futures-util" -version = "0.3.21" +version = "0.3.24" source = "registry+https://github.com/rust-lang/crates.io-index" -checksum = "d8b7abd5d659d9b90c8cba917f6ec750a74e2dc23902ef9cd4cc8c8b22e6036a" +checksum = "44fb6cb1be61cc1d2e43b262516aafcf63b241cffdb1d3fa115f91d9c7b09c90" dependencies = [ "futures-channel", "futures-core", @@ -2004,7 +2048,7 @@ dependencies = [ "fluvio-wasm-timer", "futures", "gateway-requests", - "getrandom 0.2.6", + "getrandom 0.2.7", "json", "log", "network-defaults", @@ -2051,15 +2095,15 @@ checksum = "8f5f3913fa0bfe7ee1fd8248b6b9f42a5af4b9d65ec2dd2c3c26132b950ecfc2" [[package]] name = "generator" -version = "0.7.0" +version = "0.7.1" source = "registry+https://github.com/rust-lang/crates.io-index" -checksum = "c1d9279ca822891c1a4dae06d185612cf8fc6acfe5dff37781b41297811b12ee" +checksum = "cc184cace1cea8335047a471cc1da80f18acf8a76f3bab2028d499e328948ec7" dependencies = [ "cc", "libc", "log", "rustversion", - "winapi", + "windows", ] [[package]] @@ -2073,9 +2117,9 @@ dependencies = [ [[package]] name = "generic-array" -version = "0.14.5" +version = "0.14.6" source = "registry+https://github.com/rust-lang/crates.io-index" -checksum = "fd48d33ec7f05fbfa152300fdad764757cbded343c1aa1cff2fbaf4134851803" +checksum = "bff49e947297f3312447abdca79f45f4738097cc82b06e72054d2223f601f1b9" dependencies = [ "typenum", "version_check", @@ -2096,14 +2140,14 @@ dependencies = [ [[package]] name = "getrandom" -version = "0.2.6" +version = "0.2.7" source = "registry+https://github.com/rust-lang/crates.io-index" -checksum = "9be70c98951c83b8d2f8f60d7065fa6d5146873094452a1008da8c2f1e4205ad" +checksum = "4eb1a864a501629691edf6c15a593b7a51eebaa1e8468e9ddc623de7c9b58ec6" dependencies = [ "cfg-if 1.0.0", "js-sys", "libc", - "wasi 0.10.0+wasi-snapshot-preview1", + "wasi 0.11.0+wasi-snapshot-preview1", "wasm-bindgen", ] @@ -2131,9 +2175,9 @@ dependencies = [ [[package]] name = "git2" -version = "0.14.2" +version = "0.15.0" source = "registry+https://github.com/rust-lang/crates.io-index" -checksum = "3826a6e0e2215d7a41c2bfc7c9244123969273f3476b939a226aac0ab56e9e3c" +checksum = "2994bee4a3a6a51eb90c218523be382fd7ea09b16380b9312e9dbe955ff7c7d1" dependencies = [ "bitflags", "libc", @@ -2150,9 +2194,9 @@ checksum = "9b919933a397b79c37e33b77bb2aa3dc8eb6e165ad809e58ff75bc7db2e34574" [[package]] name = "gloo-timers" -version = "0.2.3" +version = "0.2.4" source = "registry+https://github.com/rust-lang/crates.io-index" -checksum = "4d12a7f4e95cfe710f1d624fb1210b7d961a5fb05c4fd942f4feab06e61f590e" +checksum = "5fb7d06c1c8cc2a29bee7ec961009a0b2caa0793ee4900c2ffb348734ba1c8f9" dependencies = [ "futures-channel", "futures-core", @@ -2179,16 +2223,16 @@ source = "registry+https://github.com/rust-lang/crates.io-index" checksum = "bc5ac374b108929de78460075f3dc439fa66df9d8fc77e8f12caa5165fcf0c89" dependencies = [ "byteorder", - "ff 0.11.0", + "ff 0.11.1", "rand_core 0.6.3", "subtle 2.4.1", ] [[package]] name = "h2" -version = "0.3.13" +version = "0.3.14" source = "registry+https://github.com/rust-lang/crates.io-index" -checksum = "37a82c6d637fc9515a4694bbf1cb2457b79d81ce52b3108bdeea58b07dd34a57" +checksum = "5ca32592cf21ac7ccab1825cd87f6c9b3d9022c44d086172ed0966bec8af30be" dependencies = [ "bytes", "fnv", @@ -2209,6 +2253,15 @@ version = "1.8.2" source = "registry+https://github.com/rust-lang/crates.io-index" checksum = "eabb4a44450da02c90444cf74558da904edde8fb4e9035a9a6a4e15445af0bd7" +[[package]] +name = "half" +version = "2.1.0" +source = "registry+https://github.com/rust-lang/crates.io-index" +checksum = "ad6a9459c9c30b177b925162351f97e7d967c7ea8bab3b8352805327daf45554" +dependencies = [ + "crunchy", +] + [[package]] name = "handlebars" version = "3.5.5" @@ -2232,20 +2285,38 @@ dependencies = [ "ahash", ] +[[package]] +name = "hashbrown" +version = "0.12.3" +source = "registry+https://github.com/rust-lang/crates.io-index" +checksum = "8a9ee70c43aaf417c914396645a0fa852624801b24ebb7ae78fe8272889ac888" +dependencies = [ + "ahash", +] + [[package]] name = "hashlink" version = "0.7.0" source = "registry+https://github.com/rust-lang/crates.io-index" checksum = "7249a3129cbc1ffccd74857f81464a323a152173cdb134e0fd81bc803b29facf" dependencies = [ - "hashbrown", + "hashbrown 0.11.2", +] + +[[package]] +name = "hashlink" +version = "0.8.0" +source = "registry+https://github.com/rust-lang/crates.io-index" +checksum = "d452c155cb93fecdfb02a73dd57b5d8e442c2063bd7aac72f1bc5e4263a43086" +dependencies = [ + "hashbrown 0.12.3", ] [[package]] name = "hdrhistogram" -version = "7.5.0" +version = "7.5.1" source = "registry+https://github.com/rust-lang/crates.io-index" -checksum = "31672b7011be2c4f7456c4ddbcb40e7e9a4a9fad8efe49a6ebaf5f307d0109c0" +checksum = "6ea9fe3952d32674a14e0975009a3547af9ea364995b5ec1add2e23c2ae523ab" dependencies = [ "base64", "byteorder", @@ -2256,9 +2327,9 @@ dependencies = [ [[package]] name = "headers" -version = "0.3.7" +version = "0.3.8" source = "registry+https://github.com/rust-lang/crates.io-index" -checksum = "4cff78e5788be1e0ab65b04d306b2ed5092c815ec97ec70f4ebd5aee158aa55d" +checksum = "f3e372db8e5c0d213e0cd0b9be18be2aca3d44cf2fe30a9d46a65581cd454584" dependencies = [ "base64", "bitflags", @@ -2267,7 +2338,7 @@ dependencies = [ "http", "httpdate", "mime", - "sha-1 0.10.0", + "sha1", ] [[package]] @@ -2293,6 +2364,9 @@ name = "heck" version = "0.4.0" source = "registry+https://github.com/rust-lang/crates.io-index" checksum = "2540771e65fc8cb83cd6e8a237f70c319bd5c29f78ed1084ba5d50eeac86f7f9" +dependencies = [ + "unicode-segmentation", +] [[package]] name = "hermit-abi" @@ -2355,20 +2429,20 @@ dependencies = [ [[package]] name = "http" -version = "0.2.6" +version = "0.2.8" source = "registry+https://github.com/rust-lang/crates.io-index" -checksum = "31f4c6746584866f0feabcc69893c5b51beef3831656a968ed7ae254cdc4fd03" +checksum = "75f43d41e26995c17e71ee126451dd3941010b0514a81a9d11f3b341debc2399" dependencies = [ "bytes", "fnv", - "itoa 1.0.1", + "itoa 1.0.3", ] [[package]] name = "http-body" -version = "0.4.4" +version = "0.4.5" source = "registry+https://github.com/rust-lang/crates.io-index" -checksum = "1ff4f84919677303da5f147645dbea6b1881f368d03ac84e1dc09031ebd7b2c6" +checksum = "d5f38f16d184e36f2408a55281cd658ecbd3ca05cce6d6510a176eca393e26d1" dependencies = [ "bytes", "http", @@ -2376,10 +2450,16 @@ dependencies = [ ] [[package]] -name = "httparse" -version = "1.6.0" +name = "http-range-header" +version = "0.3.0" source = "registry+https://github.com/rust-lang/crates.io-index" -checksum = "9100414882e15fb7feccb4897e5f0ff0ff1ca7d1a86a23208ada4d7a18e6c6c4" +checksum = "0bfe8eed0a9285ef776bb792479ea3834e8b94e13d615c2f66d03dd50a435a29" + +[[package]] +name = "httparse" +version = "1.8.0" +source = "registry+https://github.com/rust-lang/crates.io-index" +checksum = "d897f394bad6a705d5f4104762e116a75639e470d80901eed05a860a95cb1904" [[package]] name = "httpdate" @@ -2414,9 +2494,9 @@ dependencies = [ [[package]] name = "hyper" -version = "0.14.18" +version = "0.14.20" source = "registry+https://github.com/rust-lang/crates.io-index" -checksum = "b26ae0a80afebe130861d90abf98e3814a4f28a4c6ffeb5ab8ebb2be311e0ef2" +checksum = "02c929dc5c39e335a03c405292728118860721b10190d98c2a0f0efd5baafbac" dependencies = [ "bytes", "futures-channel", @@ -2427,7 +2507,7 @@ dependencies = [ "http-body", "httparse", "httpdate", - "itoa 1.0.1", + "itoa 1.0.3", "pin-project-lite", "socket2", "tokio", @@ -2450,9 +2530,9 @@ dependencies = [ "hyper-rustls", "rustls-native-certs", "tokio", - "tokio-rustls", + "tokio-rustls 0.22.0", "tower-service", - "webpki", + "webpki 0.21.4", ] [[package]] @@ -2465,12 +2545,12 @@ dependencies = [ "futures-util", "hyper", "log", - "rustls", + "rustls 0.19.1", "rustls-native-certs", "tokio", - "tokio-rustls", - "webpki", - "webpki-roots", + "tokio-rustls 0.22.0", + "webpki 0.21.4", + "webpki-roots 0.21.1", ] [[package]] @@ -2570,12 +2650,12 @@ checksum = "ce23b50ad8242c51a442f3ff322d56b02f08852c77e4c0b4d3fd684abc89c683" [[package]] name = "indexmap" -version = "1.8.1" +version = "1.9.1" source = "registry+https://github.com/rust-lang/crates.io-index" -checksum = "0f647032dfaa1f8b6dc29bd3edb7bbef4861b8b8007ebb118d6db284fd59f6ee" +checksum = "10a35a97730320ffe8e2d410b5d3b69279b98d2c14bdb8b70ea89ecf7888d41e" dependencies = [ "autocfg 1.1.0", - "hashbrown", + "hashbrown 0.12.3", "serde", ] @@ -2591,7 +2671,7 @@ version = "0.1.3" source = "registry+https://github.com/rust-lang/crates.io-index" checksum = "a0c10553d664a4d0bcff9f4215d0aac67a639cc68ef660840afe309b807bc9f5" dependencies = [ - "generic-array 0.14.5", + "generic-array 0.14.6", ] [[package]] @@ -2617,9 +2697,9 @@ dependencies = [ [[package]] name = "ipnet" -version = "2.4.0" +version = "2.5.0" source = "registry+https://github.com/rust-lang/crates.io-index" -checksum = "35e70ee094dc02fd9c13fdad4940090f22dbd6ac7c9e7094a46cf0232a50bc7c" +checksum = "879d54834c8c76457ef4293a689b2a8c59b076067ad77b15efafbb05f92a592b" [[package]] name = "ipnetwork" @@ -2657,9 +2737,9 @@ checksum = "b71991ff56294aa922b450139ee08b3bfc70982c6b2c7562771375cf73542dd4" [[package]] name = "itoa" -version = "1.0.1" +version = "1.0.3" source = "registry+https://github.com/rust-lang/crates.io-index" -checksum = "1aab8fc367588b89dcee83ab0fd66b72b50b72fa1904d7095045ace2b0c81c35" +checksum = "6c8af84674fe1f223a982c933a0ee1086ac4d4052aa0fb8060c12c6ad838e754" [[package]] name = "jobserver" @@ -2716,9 +2796,9 @@ dependencies = [ [[package]] name = "keccak" -version = "0.1.0" +version = "0.1.2" source = "registry+https://github.com/rust-lang/crates.io-index" -checksum = "67c21572b4949434e4fc1e1978b99c5f77064153c59d998bf13ecd96fb5ecba7" +checksum = "f9b7d56ba4a8344d6be9729995e6b06f928af29998cdf79fe390cbf6b1fee838" [[package]] name = "keystream" @@ -2734,15 +2814,15 @@ checksum = "e2abad23fbc42b3700f2f279844dc832adb2b2eb069b2df918f455c4e18cc646" [[package]] name = "libc" -version = "0.2.122" +version = "0.2.132" source = "registry+https://github.com/rust-lang/crates.io-index" -checksum = "ec647867e2bf0772e28c8bcde4f0d19a9216916e890543b5a03ed8ef27b8f259" +checksum = "8371e4e5341c3a96db127eb2465ac681ced4c433e01dd0e938adbef26ba93ba5" [[package]] name = "libgit2-sys" -version = "0.13.2+1.4.2" +version = "0.14.0+1.5.0" source = "registry+https://github.com/rust-lang/crates.io-index" -checksum = "3a42de9a51a5c12e00fc0e4ca6bc2ea43582fc6418488e8f615e905d886f258b" +checksum = "47a00859c70c8a4f7218e6d1cc32875c4b55f6799445b842b0d8ed5e4c3d959b" dependencies = [ "cc", "libc", @@ -2752,15 +2832,15 @@ dependencies = [ [[package]] name = "libm" -version = "0.2.2" +version = "0.2.5" source = "registry+https://github.com/rust-lang/crates.io-index" -checksum = "33a33a362ce288760ec6a508b94caaec573ae7d3bbbd91b87aa0bad4456839db" +checksum = "292a948cd991e376cf75541fe5b97a1081d713c618b4f1b9500f8844e49eb565" [[package]] name = "libsqlite3-sys" -version = "0.23.2" +version = "0.24.2" source = "registry+https://github.com/rust-lang/crates.io-index" -checksum = "d2cafc7c74096c336d9d27145f7ebd4f4b6f95ba16aa5a282387267e6925cb58" +checksum = "898745e570c7d0453cc1fbc4a701eb6c662ed54e8fec8b7d14be137ebeeb9d14" dependencies = [ "cc", "pkg-config", @@ -2769,9 +2849,9 @@ dependencies = [ [[package]] name = "libz-sys" -version = "1.1.5" +version = "1.1.8" source = "registry+https://github.com/rust-lang/crates.io-index" -checksum = "6f35facd4a5673cb5a48822be2be1d4236c1c99cb4113cab7061ac720d5bf859" +checksum = "9702761c3935f8cc2f101793272e202c72b99da8f4224a19ddcf1279a6450bbf" dependencies = [ "cc", "libc", @@ -2781,9 +2861,9 @@ dependencies = [ [[package]] name = "linked-hash-map" -version = "0.5.4" +version = "0.5.6" source = "registry+https://github.com/rust-lang/crates.io-index" -checksum = "7fb9b38af92608140b86b693604b9ffcc5824240a484d1ecd4795bacb2fe88f3" +checksum = "0717cef1bc8b636c6e1c1bbdefc09e6322da8a9321966e8928ef80d20f7f770f" [[package]] name = "lioness" @@ -2799,9 +2879,9 @@ dependencies = [ [[package]] name = "lock_api" -version = "0.4.7" +version = "0.4.8" source = "registry+https://github.com/rust-lang/crates.io-index" -checksum = "327fa5b6a6940e4699ec49a9beae1ea4845c6bab9314e4f84ac68742139d8c53" +checksum = "9f80bf5aacaf25cbfc8210d1cfb718f2bf3b11c4c54e5afe36c236853a8ec390" dependencies = [ "autocfg 1.1.0", "scopeguard", @@ -2818,9 +2898,9 @@ dependencies = [ [[package]] name = "loom" -version = "0.5.4" +version = "0.5.6" source = "registry+https://github.com/rust-lang/crates.io-index" -checksum = "edc5c7d328e32cc4954e8e01193d7f0ef5ab257b5090b70a964e099a36034309" +checksum = "ff50ecb28bb86013e935fb6683ab1f6d3a20016f123c76fd4c27470076ac30f5" dependencies = [ "cfg-if 1.0.0", "generator", @@ -2831,12 +2911,6 @@ dependencies = [ "tracing-subscriber", ] -[[package]] -name = "maplit" -version = "1.0.2" -source = "registry+https://github.com/rust-lang/crates.io-index" -checksum = "3e2e65a1a2e43cfcb47a895c4c8b10d1f4a61097f9f254f183aee60cad9c651d" - [[package]] name = "matchers" version = "0.1.0" @@ -2852,6 +2926,12 @@ version = "0.1.9" source = "registry+https://github.com/rust-lang/crates.io-index" checksum = "a3e378b66a060d48947b590737b30a1be76706c8dd7b8ba0f2fe3989c68a853f" +[[package]] +name = "matchit" +version = "0.5.0" +source = "registry+https://github.com/rust-lang/crates.io-index" +checksum = "73cbba799671b762df5a175adf59ce145165747bb891505c43d09aefbbf38beb" + [[package]] name = "maybe-uninit" version = "2.0.0" @@ -2860,9 +2940,9 @@ checksum = "60302e4db3a61da70c0cb7991976248362f30319e88850c487b9b95bbf059e00" [[package]] name = "memchr" -version = "2.4.1" +version = "2.5.0" source = "registry+https://github.com/rust-lang/crates.io-index" -checksum = "308cc39be01b73d0d18f82a0e7b2a3df85245f84af96fdddc5d202d27e47b86a" +checksum = "2dffe52ecf27772e601905b7522cb4ef790d2cc203488bbd0e2fe85fcb74566d" [[package]] name = "memoffset" @@ -2887,35 +2967,23 @@ checksum = "68354c5c6bd36d73ff3feceb05efa59b6acb7626617f4962be322a825e61f79a" [[package]] name = "miniz_oxide" -version = "0.4.4" +version = "0.5.4" source = "registry+https://github.com/rust-lang/crates.io-index" -checksum = "a92518e98c078586bc6c934028adcca4c92a53d6a958196de835170a01d84e4b" +checksum = "96590ba8f175222643a85693f33d26e9c8a015f599c216509b1a6894af675d34" dependencies = [ "adler", - "autocfg 1.1.0", ] [[package]] name = "mio" -version = "0.8.2" +version = "0.8.4" source = "registry+https://github.com/rust-lang/crates.io-index" -checksum = "52da4364ffb0e4fe33a9841a98a3f3014fb964045ce4f7a45a398243c8d6b0c9" +checksum = "57ee1c23c7c63b0c9250c339ffdc69255f110b298b901b9f6c82547b7b87caaf" dependencies = [ "libc", "log", - "miow", - "ntapi", "wasi 0.11.0+wasi-snapshot-preview1", - "winapi", -] - -[[package]] -name = "miow" -version = "0.3.7" -source = "registry+https://github.com/rust-lang/crates.io-index" -checksum = "b9f1c5b025cda876f66ef43a113f91ebc9f4ccef34843000e0adf6ebbab84e21" -dependencies = [ - "winapi", + "windows-sys", ] [[package]] @@ -2942,7 +3010,7 @@ dependencies = [ "serde", "serde_repr", "thiserror", - "time 0.3.9", + "time 0.3.14", "ts-rs", ] @@ -2975,9 +3043,9 @@ dependencies = [ [[package]] name = "multer" -version = "2.0.2" +version = "2.0.3" source = "registry+https://github.com/rust-lang/crates.io-index" -checksum = "5f8f35e687561d5c1667590911e6698a8cb714a134a7505718a182e7bc9d3836" +checksum = "a30ba6d97eb198c5e8a35d67d5779d6680cca35652a60ee90fc23dc431d4fde8" dependencies = [ "bytes", "encoding_rs", @@ -2987,18 +3055,12 @@ dependencies = [ "log", "memchr", "mime", - "spin 0.9.2", + "spin 0.9.4", "tokio", - "tokio-util 0.6.9", + "tokio-util 0.7.3", "version_check", ] -[[package]] -name = "multimap" -version = "0.8.3" -source = "registry+https://github.com/rust-lang/crates.io-index" -checksum = "e5ce46fe64a9d73be07dcbe690a38ce1b293be448fd8ce1e6c1b8062c9f72c6a" - [[package]] name = "multisig-contract-common" version = "0.1.0" @@ -3083,9 +3145,9 @@ dependencies = [ [[package]] name = "num-integer" -version = "0.1.44" +version = "0.1.45" source = "registry+https://github.com/rust-lang/crates.io-index" -checksum = "d2cc698a63b549a70bc047073d2949cce27cd1c7b0a4a862d08a8031bc2801db" +checksum = "225d3389fb3509a24c93f5c29eb6bde2586b98d9f016636dff58d7c6f7569cd9" dependencies = [ "autocfg 1.1.0", "num-traits", @@ -3093,9 +3155,9 @@ dependencies = [ [[package]] name = "num-traits" -version = "0.2.14" +version = "0.2.15" source = "registry+https://github.com/rust-lang/crates.io-index" -checksum = "9a64b1ec5cda2586e284722486d802acf1f7dbdc623e2bfc57e65ca1cd099290" +checksum = "578ede34cf02f8924ab9447f50c28075b4d3e5b269972345e7e0372b38c6cdcd" dependencies = [ "autocfg 1.1.0", "libm", @@ -3113,9 +3175,9 @@ dependencies = [ [[package]] name = "num_threads" -version = "0.1.5" +version = "0.1.6" source = "registry+https://github.com/rust-lang/crates.io-index" -checksum = "aba1801fb138d8e85e11d0fc70baf4fe1cdfffda7c6cd34a854905df588e5ed0" +checksum = "2819ce041d2ee131036f4fc9d6ae7ae125a3a40e97ba64d04fe799ad9dabbb44" dependencies = [ "libc", ] @@ -3175,7 +3237,7 @@ dependencies = [ name = "nym-client" version = "1.0.2" dependencies = [ - "clap 3.2.8", + "clap 3.2.20", "client-core", "coconut-interface", "config", @@ -3214,7 +3276,7 @@ dependencies = [ "bandwidth-claim-contract", "bip39", "bs58", - "clap 3.2.8", + "clap 3.2.20", "coconut-interface", "colored", "config", @@ -3237,7 +3299,7 @@ dependencies = [ "pretty_env_logger", "rand 0.7.3", "serde", - "sqlx", + "sqlx 0.5.13", "statistics-common", "subtle-encoding", "thiserror", @@ -3259,7 +3321,7 @@ version = "1.0.2" dependencies = [ "anyhow", "bs58", - "clap 3.2.8", + "clap 3.2.20", "colored", "config", "crypto", @@ -3313,7 +3375,7 @@ dependencies = [ "reqwest", "serde", "socks5-requests", - "sqlx", + "sqlx 0.5.13", "statistics-common", "thiserror", "tokio", @@ -3330,7 +3392,7 @@ dependencies = [ "pretty_env_logger", "rocket", "serde", - "sqlx", + "sqlx 0.5.13", "statistics-common", "thiserror", "tokio", @@ -3341,7 +3403,7 @@ dependencies = [ name = "nym-socks5-client" version = "1.0.2" dependencies = [ - "clap 3.2.8", + "clap 3.2.20", "client-core", "coconut-interface", "config", @@ -3406,7 +3468,7 @@ dependencies = [ "async-trait", "attohttpc", "cfg-if 1.0.0", - "clap 2.34.0", + "clap 3.2.20", "coconut-bandwidth-contract-common", "coconut-interface", "config", @@ -3442,11 +3504,12 @@ dependencies = [ "schemars", "serde", "serde_json", - "sqlx", + "sqlx 0.5.13", + "sqlx 0.6.1", "tap", "task", "thiserror", - "time 0.3.9", + "time 0.3.14", "tokio", "tokio-stream", "topology", @@ -3487,7 +3550,7 @@ dependencies = [ "digest 0.9.0", "doc-comment", "ff 0.10.1", - "getrandom 0.2.6", + "getrandom 0.2.7", "group 0.10.0", "itertools", "rand 0.8.5", @@ -3629,9 +3692,9 @@ dependencies = [ [[package]] name = "once_cell" -version = "1.13.0" +version = "1.14.0" source = "registry+https://github.com/rust-lang/crates.io-index" -checksum = "18a6dbe30758c9f83eb00cbea4ac95966305f5a7772f3f42ebfc7fc7eddbd8e1" +checksum = "2f7254b99e31cad77da24b08ebf628882739a608578bb1bcdfc1f9c21260d7c0" [[package]] name = "oorandom" @@ -3653,18 +3716,30 @@ checksum = "624a8340c38c1b80fd549087862da4ba43e08858af025b236e509b6649fc13d5" [[package]] name = "openssl" -version = "0.10.38" +version = "0.10.41" source = "registry+https://github.com/rust-lang/crates.io-index" -checksum = "0c7ae222234c30df141154f159066c5093ff73b63204dcda7121eb082fc56a95" +checksum = "618febf65336490dfcf20b73f885f5651a0c89c64c2d4a8c3662585a70bf5bd0" dependencies = [ "bitflags", "cfg-if 1.0.0", "foreign-types", "libc", "once_cell", + "openssl-macros", "openssl-sys", ] +[[package]] +name = "openssl-macros" +version = "0.1.0" +source = "registry+https://github.com/rust-lang/crates.io-index" +checksum = "b501e44f11665960c7e7fcf062c7d96a14ade4aa98116c004b2e37b5be7d736c" +dependencies = [ + "proc-macro2", + "quote", + "syn", +] + [[package]] name = "openssl-probe" version = "0.1.5" @@ -3673,9 +3748,9 @@ checksum = "ff011a302c396a5197692431fc1948019154afc178baf7d8e37367442a4601cf" [[package]] name = "openssl-sys" -version = "0.9.72" +version = "0.9.75" source = "registry+https://github.com/rust-lang/crates.io-index" -checksum = "7e46109c383602735fa0a2e48dd2b7c892b048e1bf69e5c3b1d804b7d9c203cb" +checksum = "e5f9bd0c2710541a3cda73d6f9ac4f1b240de4ae261065d309dbe73d9dceb42f" dependencies = [ "autocfg 1.1.0", "cc", @@ -3693,9 +3768,9 @@ dependencies = [ [[package]] name = "os_str_bytes" -version = "6.0.0" +version = "6.3.0" source = "registry+https://github.com/rust-lang/crates.io-index" -checksum = "8e22443d1643a904602595ba1cd8f7d896afe56d26712531c5ff73a15b2fbf64" +checksum = "9ff7415e9ae3fff1225851df9e0d9e4e5479f947619774677a63572e55e80eff" [[package]] name = "pairing" @@ -3754,12 +3829,12 @@ dependencies = [ [[package]] name = "parking_lot" -version = "0.12.0" +version = "0.12.1" source = "registry+https://github.com/rust-lang/crates.io-index" -checksum = "87f5ec2493a61ac0506c0f4199f99070cbe83857b0337006a30f3e6719b8ef58" +checksum = "3742b2c103b9f06bc9fff0a37ff4912935851bee6d36f3c02bcc755bcfec228f" dependencies = [ "lock_api", - "parking_lot_core 0.9.2", + "parking_lot_core 0.9.3", ] [[package]] @@ -3772,28 +3847,28 @@ dependencies = [ "instant", "libc", "redox_syscall", - "smallvec 1.8.0", + "smallvec 1.9.0", "winapi", ] [[package]] name = "parking_lot_core" -version = "0.9.2" +version = "0.9.3" source = "registry+https://github.com/rust-lang/crates.io-index" -checksum = "995f667a6c822200b0433ac218e05582f0e2efa1b922a3fd2fbaadc5f87bab37" +checksum = "09a279cbf25cb0757810394fbc1e359949b59e348145c643a939a525692e6929" dependencies = [ "cfg-if 1.0.0", "libc", "redox_syscall", - "smallvec 1.8.0", + "smallvec 1.9.0", "windows-sys", ] [[package]] name = "paste" -version = "1.0.7" +version = "1.0.9" source = "registry+https://github.com/rust-lang/crates.io-index" -checksum = "0c520e05135d6e763148b6426a837e239041653ba7becd2e538c076c738025fc" +checksum = "b1de2e551fb905ac83f73f7aedf2f0cb4a0da7e35efa24a202a936269f1f18e1" [[package]] name = "pbkdf2" @@ -3880,18 +3955,19 @@ checksum = "d4fd5641d01c8f18a23da7b6fe29298ff4b55afcccdf78973b24cf3175fee32e" [[package]] name = "pest" -version = "2.1.3" +version = "2.3.0" source = "registry+https://github.com/rust-lang/crates.io-index" -checksum = "10f4872ae94d7b90ae48754df22fd42ad52ce740b8f370b03da4835417403e53" +checksum = "4b0560d531d1febc25a3c9398a62a71256c0178f2e3443baedd9ad4bb8c9deb4" dependencies = [ + "thiserror", "ucd-trie", ] [[package]] name = "pest_derive" -version = "2.1.0" +version = "2.3.0" source = "registry+https://github.com/rust-lang/crates.io-index" -checksum = "833d1ae558dc601e9a60366421196a8d94bc0ac980476d0b67e1d0988d72b2d0" +checksum = "905708f7f674518498c1f8d644481440f476d39ca6ecae83319bba7c6c12da91" dependencies = [ "pest", "pest_generator", @@ -3899,9 +3975,9 @@ dependencies = [ [[package]] name = "pest_generator" -version = "2.1.3" +version = "2.3.0" source = "registry+https://github.com/rust-lang/crates.io-index" -checksum = "99b8db626e31e5b81787b9783425769681b347011cc59471e33ea46d2ea0cf55" +checksum = "5803d8284a629cc999094ecd630f55e91b561a1d1ba75e233b00ae13b91a69ad" dependencies = [ "pest", "pest_meta", @@ -3912,23 +3988,13 @@ dependencies = [ [[package]] name = "pest_meta" -version = "2.1.3" +version = "2.3.0" source = "registry+https://github.com/rust-lang/crates.io-index" -checksum = "54be6e404f5317079812fc8f9f5279de376d8856929e21c184ecf6bbd692a11d" +checksum = "1538eb784f07615c6d9a8ab061089c6c54a344c5b4301db51990ca1c241e8c04" dependencies = [ - "maplit", + "once_cell", "pest", - "sha-1 0.8.2", -] - -[[package]] -name = "petgraph" -version = "0.6.0" -source = "registry+https://github.com/rust-lang/crates.io-index" -checksum = "4a13a2fa9d0b63e5f22328828741e523766fff0ee9e779316902290dff3f824f" -dependencies = [ - "fixedbitset", - "indexmap", + "sha-1 0.10.0", ] [[package]] @@ -3946,18 +4012,18 @@ dependencies = [ [[package]] name = "pin-project" -version = "1.0.10" +version = "1.0.12" source = "registry+https://github.com/rust-lang/crates.io-index" -checksum = "58ad3879ad3baf4e44784bc6a718a8698867bb991f8ce24d1bcbe2cfb4c3a75e" +checksum = "ad29a609b6bcd67fee905812e544992d216af9d755757c05ed2d0e15a74c6ecc" dependencies = [ "pin-project-internal", ] [[package]] name = "pin-project-internal" -version = "1.0.10" +version = "1.0.12" source = "registry+https://github.com/rust-lang/crates.io-index" -checksum = "744b6f092ba29c3650faf274db506afd39944f48420f6c86b17cfe0ee1cb36bb" +checksum = "069bdb1e05adc7a8990dce9cc75370895fbe4e3d58b9b73bf1aee56359344a55" dependencies = [ "proc-macro2", "quote", @@ -3966,9 +4032,9 @@ dependencies = [ [[package]] name = "pin-project-lite" -version = "0.2.8" +version = "0.2.9" source = "registry+https://github.com/rust-lang/crates.io-index" -checksum = "e280fbe77cc62c91527259e9442153f4688736748d24660126286329742b4c6c" +checksum = "e0a7ae3ac2f1173085d398531c705756c94a4c56843785df85a60c1a0afac116" [[package]] name = "pin-utils" @@ -3995,9 +4061,9 @@ checksum = "1df8c4ec4b0627e53bdf214615ad287367e482558cf84b109250b37464dc03ae" [[package]] name = "plotters" -version = "0.3.1" +version = "0.3.3" source = "registry+https://github.com/rust-lang/crates.io-index" -checksum = "32a3fd9ec30b9749ce28cd91f255d569591cdf937fe280c312143e3c4bad6f2a" +checksum = "716b4eeb6c4a1d3ecc956f75b43ec2e8e8ba80026413e70a3f41fd3313d3492b" dependencies = [ "num-traits", "plotters-backend", @@ -4008,15 +4074,15 @@ dependencies = [ [[package]] name = "plotters-backend" -version = "0.3.2" +version = "0.3.4" source = "registry+https://github.com/rust-lang/crates.io-index" -checksum = "d88417318da0eaf0fdcdb51a0ee6c3bed624333bff8f946733049380be67ac1c" +checksum = "193228616381fecdc1224c62e96946dfbc73ff4384fba576e052ff8c1bea8142" [[package]] name = "plotters-svg" -version = "0.3.1" +version = "0.3.3" source = "registry+https://github.com/rust-lang/crates.io-index" -checksum = "521fa9638fa597e1dc53e9412a4f9cefb01187ee1f7413076f9e6749e2885ba9" +checksum = "f9a81d2759aae1dae668f783c308bc5c8ebd191ff4184aaa1b37f65a6ae5a56f" dependencies = [ "plotters-backend", ] @@ -4064,10 +4130,11 @@ dependencies = [ [[package]] name = "proc-macro-crate" -version = "1.1.3" +version = "1.2.1" source = "registry+https://github.com/rust-lang/crates.io-index" -checksum = "e17d47ce914bf4de440332250b0edd23ce48c005f59fab39d3335866b114f11a" +checksum = "eda0fc3b0fb7c975631757e14d9049da17374063edb6ebbcbc54d880d4fe94e9" dependencies = [ + "once_cell", "thiserror", "toml", ] @@ -4098,11 +4165,11 @@ dependencies = [ [[package]] name = "proc-macro2" -version = "1.0.37" +version = "1.0.43" source = "registry+https://github.com/rust-lang/crates.io-index" -checksum = "ec757218438d5fda206afc041538b2f6d889286160d649a86a24d37e1235afd1" +checksum = "0a2ca2c61bc9f3d74d2886294ab7b9853abd9c1ad903a3ac7815c58989bb7bab" dependencies = [ - "unicode-xid", + "unicode-ident", ] [[package]] @@ -4120,55 +4187,22 @@ dependencies = [ [[package]] name = "prost" -version = "0.9.0" +version = "0.10.4" source = "registry+https://github.com/rust-lang/crates.io-index" -checksum = "444879275cb4fd84958b1a1d5420d15e6fcf7c235fe47f053c9c2a80aceb6001" -dependencies = [ - "bytes", - "prost-derive 0.9.0", -] - -[[package]] -name = "prost" -version = "0.10.3" -source = "registry+https://github.com/rust-lang/crates.io-index" -checksum = "bc03e116981ff7d8da8e5c220e374587b98d294af7ba7dd7fda761158f00086f" +checksum = "71adf41db68aa0daaefc69bb30bcd68ded9b9abaad5d1fbb6304c4fb390e083e" dependencies = [ "bytes", "prost-derive 0.10.1", ] [[package]] -name = "prost-build" -version = "0.9.0" +name = "prost" +version = "0.11.0" source = "registry+https://github.com/rust-lang/crates.io-index" -checksum = "62941722fb675d463659e49c4f3fe1fe792ff24fe5bbaa9c08cd3b98a1c354f5" +checksum = "399c3c31cdec40583bb68f0b18403400d01ec4289c383aa047560439952c4dd7" dependencies = [ "bytes", - "heck 0.3.3", - "itertools", - "lazy_static", - "log", - "multimap", - "petgraph", - "prost 0.9.0", - "prost-types 0.9.0", - "regex", - "tempfile", - "which", -] - -[[package]] -name = "prost-derive" -version = "0.9.0" -source = "registry+https://github.com/rust-lang/crates.io-index" -checksum = "f9cc1a3263e07e0bf68e96268f37665207b49560d98739662cdfaae215c720fe" -dependencies = [ - "anyhow", - "itertools", - "proc-macro2", - "quote", - "syn", + "prost-derive 0.11.0", ] [[package]] @@ -4185,13 +4219,16 @@ dependencies = [ ] [[package]] -name = "prost-types" -version = "0.9.0" +name = "prost-derive" +version = "0.11.0" source = "registry+https://github.com/rust-lang/crates.io-index" -checksum = "534b7a0e836e3c482d2693070f982e39e7611da9695d4d1f5a4b186b51faef0a" +checksum = "7345d5f0e08c0536d7ac7229952590239e77abf0a0100a1b1d890add6ea96364" dependencies = [ - "bytes", - "prost 0.9.0", + "anyhow", + "itertools", + "proc-macro2", + "quote", + "syn", ] [[package]] @@ -4201,7 +4238,17 @@ source = "registry+https://github.com/rust-lang/crates.io-index" checksum = "2d0a014229361011dc8e69c8a1ec6c2e8d0f2af7c91e3ea3f5b2170298461e68" dependencies = [ "bytes", - "prost 0.10.3", + "prost 0.10.4", +] + +[[package]] +name = "prost-types" +version = "0.11.1" +source = "registry+https://github.com/rust-lang/crates.io-index" +checksum = "4dfaa718ad76a44b3415e6c4d53b17c8f99160dcb3a99b10470fce8ad43f6e3e" +dependencies = [ + "bytes", + "prost 0.11.0", ] [[package]] @@ -4246,21 +4293,21 @@ checksum = "a993555f31e5a609f617c12db6250dedcac1b0a85076912c436e6fc9b2c8e6a3" [[package]] name = "quote" -version = "1.0.18" +version = "1.0.21" source = "registry+https://github.com/rust-lang/crates.io-index" -checksum = "a1feb54ed693b93a84e14094943b84b7c4eae204c512b7ccb95ab0c66d278ad1" +checksum = "bbe448f377a7d6961e30f5955f9b8d106c3f5e449d493ee1b125c1d43c2b5179" dependencies = [ "proc-macro2", ] [[package]] name = "r2d2" -version = "0.8.9" +version = "0.8.10" source = "registry+https://github.com/rust-lang/crates.io-index" -checksum = "545c5bc2b880973c9c10e4067418407a0ccaa3091781d1671d46eb35107cb26f" +checksum = "51de85fb3fb6524929c8a2eb85e6b6d363de4e8c48f9e2c2eac4944abc181c93" dependencies = [ "log", - "parking_lot 0.11.2", + "parking_lot 0.12.1", "scheduled-thread-pool", ] @@ -4379,7 +4426,7 @@ version = "0.6.3" source = "registry+https://github.com/rust-lang/crates.io-index" checksum = "d34f1408f55294453790c48b2f1ebbb1c5b4b7563eb1f418bcfcfdbb06ebb4e7" dependencies = [ - "getrandom 0.2.6", + "getrandom 0.2.7", ] [[package]] @@ -4465,9 +4512,9 @@ dependencies = [ [[package]] name = "rayon" -version = "1.5.1" +version = "1.5.3" source = "registry+https://github.com/rust-lang/crates.io-index" -checksum = "c06aca804d41dbc8ba42dfd964f0d01334eceb64314b9ecf7c5fad5188a06d90" +checksum = "bd99e5772ead8baa5215278c9b15bf92087709e9c1b2d1f97cdb5a183c933a7d" dependencies = [ "autocfg 1.1.0", "crossbeam-deque", @@ -4477,14 +4524,13 @@ dependencies = [ [[package]] name = "rayon-core" -version = "1.9.1" +version = "1.9.3" source = "registry+https://github.com/rust-lang/crates.io-index" -checksum = "d78120e2c850279833f1dd3582f730c4ab53ed95aeaaaa862a2a5c71b1656d8e" +checksum = "258bcdb5ac6dad48491bb2992db6b7cf74878b0384908af124823d118c99683f" dependencies = [ "crossbeam-channel", "crossbeam-deque", "crossbeam-utils", - "lazy_static", "num_cpus", ] @@ -4499,9 +4545,9 @@ dependencies = [ [[package]] name = "redox_syscall" -version = "0.2.13" +version = "0.2.16" source = "registry+https://github.com/rust-lang/crates.io-index" -checksum = "62f25bc4c7e55e0b0b7a1d43fb893f4fa1361d0abe38b9ce4f323c2adfe6ef42" +checksum = "fb5a58c1855b4b6819d59012155603f0b22ad30cad752600aadfcb695265519a" dependencies = [ "bitflags", ] @@ -4512,25 +4558,25 @@ version = "0.4.3" source = "registry+https://github.com/rust-lang/crates.io-index" checksum = "b033d837a7cf162d7993aded9304e30a83213c648b6e389db233191f891e5c2b" dependencies = [ - "getrandom 0.2.6", + "getrandom 0.2.7", "redox_syscall", "thiserror", ] [[package]] name = "ref-cast" -version = "1.0.6" +version = "1.0.9" source = "registry+https://github.com/rust-lang/crates.io-index" -checksum = "300f2a835d808734ee295d45007adacb9ebb29dd3ae2424acfa17930cae541da" +checksum = "ed13bcd201494ab44900a96490291651d200730904221832b9547d24a87d332b" dependencies = [ "ref-cast-impl", ] [[package]] name = "ref-cast-impl" -version = "1.0.6" +version = "1.0.9" source = "registry+https://github.com/rust-lang/crates.io-index" -checksum = "4c38e3aecd2b21cb3959637b883bb3714bc7e43f0268b9a29d3743ee3e55cdd2" +checksum = "5234cd6063258a5e32903b53b1b6ac043a0541c8adc1f610f67b0326c7a578fa" dependencies = [ "proc-macro2", "quote", @@ -4539,9 +4585,9 @@ dependencies = [ [[package]] name = "regex" -version = "1.5.5" +version = "1.6.0" source = "registry+https://github.com/rust-lang/crates.io-index" -checksum = "1a11647b6b25ff05a515cb92c365cec08801e83423a235b51e231e1808747286" +checksum = "4c4eb3267174b8c6c2f654116623910a0fef09c4753f8dd83db29c48a0df988b" dependencies = [ "aho-corasick", "memchr", @@ -4559,9 +4605,9 @@ dependencies = [ [[package]] name = "regex-syntax" -version = "0.6.25" +version = "0.6.27" source = "registry+https://github.com/rust-lang/crates.io-index" -checksum = "f497285884f3fcff424ffc933e56d7cbca511def0c9831a7f9b5f6153e3cc89b" +checksum = "a3f87b73ce11b1619a3c6332f45341e0047173771e8b8b73f87bfeefb7b56244" [[package]] name = "remove_dir_all" @@ -4574,9 +4620,9 @@ dependencies = [ [[package]] name = "reqwest" -version = "0.11.10" +version = "0.11.11" source = "registry+https://github.com/rust-lang/crates.io-index" -checksum = "46a1f7aa4f35e5e8b4160449f51afc758f0ce6454315a9fa7d0d113e958c41eb" +checksum = "b75aa69a3f06bbcc66ede33af2af253c6f7a86b1ca0033f60c580a27074fbf92" dependencies = [ "base64", "bytes", @@ -4601,6 +4647,7 @@ dependencies = [ "serde_urlencoded", "tokio", "tokio-native-tls", + "tower-service", "url", "wasm-bindgen", "wasm-bindgen-futures", @@ -4675,7 +4722,7 @@ dependencies = [ "memchr", "multer", "num_cpus", - "parking_lot 0.12.0", + "parking_lot 0.12.1", "pin-project-lite", "rand 0.8.5", "ref-cast", @@ -4685,7 +4732,7 @@ dependencies = [ "serde_json", "state", "tempfile", - "time 0.3.9", + "time 0.3.14", "tokio", "tokio-stream", "tokio-util 0.7.3", @@ -4744,10 +4791,10 @@ dependencies = [ "pin-project-lite", "ref-cast", "serde", - "smallvec 1.8.0", + "smallvec 1.9.0", "stable-pattern", "state", - "time 0.3.9", + "time 0.3.14", "tokio", "uncased", ] @@ -4825,7 +4872,7 @@ version = "0.4.0" source = "registry+https://github.com/rust-lang/crates.io-index" checksum = "bfa0f585226d2e68097d4f95d113b15b83a82e819ab25717ec0590d9584ef366" dependencies = [ - "semver 1.0.7", + "semver 1.0.13", ] [[package]] @@ -4837,8 +4884,20 @@ dependencies = [ "base64", "log", "ring", - "sct", - "webpki", + "sct 0.6.1", + "webpki 0.21.4", +] + +[[package]] +name = "rustls" +version = "0.20.6" +source = "registry+https://github.com/rust-lang/crates.io-index" +checksum = "5aab8ee6c7097ed6057f43c187a62418d0c05a4bd5f18b3571db50ee0f9ce033" +dependencies = [ + "log", + "ring", + "sct 0.7.0", + "webpki 0.22.0", ] [[package]] @@ -4848,22 +4907,31 @@ source = "registry+https://github.com/rust-lang/crates.io-index" checksum = "5a07b7c1885bd8ed3831c289b7870b13ef46fe0e856d288c30d9cc17d75a2092" dependencies = [ "openssl-probe", - "rustls", + "rustls 0.19.1", "schannel", "security-framework", ] [[package]] -name = "rustversion" -version = "1.0.6" +name = "rustls-pemfile" +version = "1.0.1" source = "registry+https://github.com/rust-lang/crates.io-index" -checksum = "f2cc38e8fa666e2de3c4aba7edeb5ffc5246c1c2ed0e3d17e560aeeba736b23f" +checksum = "0864aeff53f8c05aa08d86e5ef839d3dfcf07aeba2db32f12db0ef716e87bd55" +dependencies = [ + "base64", +] + +[[package]] +name = "rustversion" +version = "1.0.9" +source = "registry+https://github.com/rust-lang/crates.io-index" +checksum = "97477e48b4cf8603ad5f7aaf897467cf42ab4218a38ef76fb14c2d6773a6d6a8" [[package]] name = "ryu" -version = "1.0.9" +version = "1.0.11" source = "registry+https://github.com/rust-lang/crates.io-index" -checksum = "73b4b750c782965c211b42f022f59af1fbceabdd026623714f104152f1ec149f" +checksum = "4501abdff3ae82a1c1b477a17252eb69cee9e66eb915c1abaa4f44d873df9f09" [[package]] name = "same-file" @@ -4876,21 +4944,21 @@ dependencies = [ [[package]] name = "schannel" -version = "0.1.19" +version = "0.1.20" source = "registry+https://github.com/rust-lang/crates.io-index" -checksum = "8f05ba609c234e60bee0d547fe94a4c7e9da733d1c962cf6e59efa4cd9c8bc75" +checksum = "88d6731146462ea25d9244b2ed5fd1d716d25c52e4d54aa4fb0f3c4e9854dbe2" dependencies = [ "lazy_static", - "winapi", + "windows-sys", ] [[package]] name = "scheduled-thread-pool" -version = "0.2.5" +version = "0.2.6" source = "registry+https://github.com/rust-lang/crates.io-index" -checksum = "dc6f74fd1204073fa02d5d5d68bec8021be4c38690b61264b2fdb48083d0e7d7" +checksum = "977a7519bff143a44f842fd07e80ad1329295bd71686457f18e496736f4bf9bf" dependencies = [ - "parking_lot 0.11.2", + "parking_lot 0.12.1", ] [[package]] @@ -4940,6 +5008,16 @@ dependencies = [ "untrusted", ] +[[package]] +name = "sct" +version = "0.7.0" +source = "registry+https://github.com/rust-lang/crates.io-index" +checksum = "d53dcdb7c9f8158937a7981b48accfd39a43af418591a5d008c7b22b5e1b7ca4" +dependencies = [ + "ring", + "untrusted", +] + [[package]] name = "sec1" version = "0.2.1" @@ -4947,7 +5025,7 @@ source = "registry+https://github.com/rust-lang/crates.io-index" checksum = "08da66b8b0965a5555b6bd6639e68ccba85e1e2506f5fbb089e93f8a04e1a2d1" dependencies = [ "der", - "generic-array 0.14.5", + "generic-array 0.14.6", "pkcs8", "subtle 2.4.1", "zeroize", @@ -4973,9 +5051,9 @@ dependencies = [ [[package]] name = "security-framework" -version = "2.6.1" +version = "2.7.0" source = "registry+https://github.com/rust-lang/crates.io-index" -checksum = "2dc14f172faf8a0194a3aded622712b0de276821addc574fa54fc0a1167e10dc" +checksum = "2bc1bb97804af6631813c55739f771071e0f2ed33ee20b68c86ec505d906356c" dependencies = [ "bitflags", "core-foundation", @@ -5014,9 +5092,9 @@ dependencies = [ [[package]] name = "semver" -version = "1.0.7" +version = "1.0.13" source = "registry+https://github.com/rust-lang/crates.io-index" -checksum = "d65bd28f48be7196d222d95b9243287f48d27aca604e08497513019ff0502cc4" +checksum = "93f6841e709003d68bb2deee8c343572bf446003ec20a583e76f7b15cebf3711" [[package]] name = "semver-parser" @@ -5041,9 +5119,9 @@ checksum = "f638d531eccd6e23b980caf34876660d38e265409d8e99b397ab71eb3612fad0" [[package]] name = "serde" -version = "1.0.136" +version = "1.0.144" source = "registry+https://github.com/rust-lang/crates.io-index" -checksum = "ce31e24b01e1e524df96f1c2fdd054405f8d7376249a5110886fb4b658484789" +checksum = "0f747710de3dcd43b88c9168773254e809d8ddbdf9653b84e2554ab219f17860" dependencies = [ "serde_derive", ] @@ -5059,9 +5137,9 @@ dependencies = [ [[package]] name = "serde_bytes" -version = "0.11.6" +version = "0.11.7" source = "registry+https://github.com/rust-lang/crates.io-index" -checksum = "212e73464ebcde48d723aa02eb270ba62eff38a9b732df31f33f1b4e145f3a54" +checksum = "cfc50e8183eeeb6178dcb167ae34a8051d63535023ae38b5d8d12beae193d37b" dependencies = [ "serde", ] @@ -5072,15 +5150,15 @@ version = "0.11.2" source = "registry+https://github.com/rust-lang/crates.io-index" checksum = "2bef2ebfde456fb76bbcf9f59315333decc4fda0b2b44b420243c11e0f5ec1f5" dependencies = [ - "half", + "half 1.8.2", "serde", ] [[package]] name = "serde_derive" -version = "1.0.136" +version = "1.0.144" source = "registry+https://github.com/rust-lang/crates.io-index" -checksum = "08597e7152fcd306f41838ed3e37be9eaeed2b61c42e2117266a554fab4662f9" +checksum = "94ed3a816fb1d101812f83e789f888322c34e291f894f19590dc310963e87a00" dependencies = [ "proc-macro2", "quote", @@ -5100,20 +5178,20 @@ dependencies = [ [[package]] name = "serde_json" -version = "1.0.83" +version = "1.0.85" source = "registry+https://github.com/rust-lang/crates.io-index" -checksum = "38dd04e3c8279e75b31ef29dbdceebfe5ad89f4d0937213c53f7d49d01b3d5a7" +checksum = "e55a28e3aaef9d5ce0506d0a14dbba8054ddc7e499ef522dd8b26859ec9d4a44" dependencies = [ - "itoa 1.0.1", + "itoa 1.0.3", "ryu", "serde", ] [[package]] name = "serde_repr" -version = "0.1.7" +version = "0.1.9" source = "registry+https://github.com/rust-lang/crates.io-index" -checksum = "98d0516900518c29efa217c298fa1f4e6c6ffc85ae29fd7f4ee48f176e1a9ed5" +checksum = "1fe39d9fbb0ebf5eb2c7cb7e2a47e4f462fad1379f1166b8ae49ad9eae89a7ca" dependencies = [ "proc-macro2", "quote", @@ -5127,16 +5205,16 @@ source = "registry+https://github.com/rust-lang/crates.io-index" checksum = "d3491c14715ca2294c4d6a88f15e84739788c1d030eed8c110436aafdaa2f3fd" dependencies = [ "form_urlencoded", - "itoa 1.0.1", + "itoa 1.0.3", "ryu", "serde", ] [[package]] name = "serde_yaml" -version = "0.8.23" +version = "0.8.26" source = "registry+https://github.com/rust-lang/crates.io-index" -checksum = "a4a521f2940385c165a24ee286aa8599633d162077a54bdcae2a6fd5a7bfa7a0" +checksum = "578a7433b776b56a35785ed5ce9a7e777ac0598aac5a6dd1b4b18a307c7fc71b" dependencies = [ "indexmap", "ryu", @@ -5144,18 +5222,6 @@ dependencies = [ "yaml-rust", ] -[[package]] -name = "sha-1" -version = "0.8.2" -source = "registry+https://github.com/rust-lang/crates.io-index" -checksum = "f7d94d0bede923b3cea61f3f1ff57ff8cdfd77b400fb8f9998949e0cf04163df" -dependencies = [ - "block-buffer 0.7.3", - "digest 0.8.1", - "fake-simd", - "opaque-debug 0.2.3", -] - [[package]] name = "sha-1" version = "0.9.8" @@ -5180,6 +5246,17 @@ dependencies = [ "digest 0.10.3", ] +[[package]] +name = "sha1" +version = "0.10.4" +source = "registry+https://github.com/rust-lang/crates.io-index" +checksum = "006769ba83e921b3085caa8334186b00cf92b4cb1a6cf4632fbccc8eff5c7549" +dependencies = [ + "cfg-if 1.0.0", + "cpufeatures", + "digest 0.10.3", +] + [[package]] name = "sha2" version = "0.9.9" @@ -5195,9 +5272,9 @@ dependencies = [ [[package]] name = "sha2" -version = "0.10.2" +version = "0.10.5" source = "registry+https://github.com/rust-lang/crates.io-index" -checksum = "55deaec60f81eefe3cce0dc50bda92d6d8e88f2a27df7c5033b42afeb1ed2676" +checksum = "cf9db03534dff993187064c4e0c05a5708d2a9728ace9a8959b77bedf415dac5" dependencies = [ "cfg-if 1.0.0", "cpufeatures", @@ -5257,9 +5334,9 @@ dependencies = [ [[package]] name = "signature" -version = "1.3.2" +version = "1.4.0" source = "registry+https://github.com/rust-lang/crates.io-index" -checksum = "f2807892cfa58e081aa1f1111391c7a0649d4fa127a4ffbe34bcbfb35a1171a4" +checksum = "02658e48d89f2bec991f9a78e69cfa4c316f8d6a6c4ec12fae1aeb263d486788" dependencies = [ "digest 0.9.0", "rand_core 0.6.3", @@ -5267,9 +5344,12 @@ dependencies = [ [[package]] name = "slab" -version = "0.4.6" +version = "0.4.7" source = "registry+https://github.com/rust-lang/crates.io-index" -checksum = "eb703cfe953bccee95685111adeedb76fabe4e97549a58d16f03ea7b9367bb32" +checksum = "4614a76b2a8be0058caa9dbbaf66d988527d86d003c11a94fbd335d7661edcef" +dependencies = [ + "autocfg 1.1.0", +] [[package]] name = "sled" @@ -5298,9 +5378,9 @@ dependencies = [ [[package]] name = "smallvec" -version = "1.8.0" +version = "1.9.0" source = "registry+https://github.com/rust-lang/crates.io-index" -checksum = "f2dd574626839106c320a323308629dcb1acfc96e32a8cba364ddc61ac23ee83" +checksum = "2fd0db749597d91ff862fd1d55ea87f7855a744a8425a64695b6fca237d1dad1" [[package]] name = "snafu" @@ -5325,9 +5405,9 @@ dependencies = [ [[package]] name = "socket2" -version = "0.4.4" +version = "0.4.7" source = "registry+https://github.com/rust-lang/crates.io-index" -checksum = "66d72b759436ae32898a2af0a14218dbf55efde3feeb170eb623637db85ee1e0" +checksum = "02e2d2db9033d13a1567121ddd7a095ee144db4e1ca1b1bda3419bc0da294ebd" dependencies = [ "libc", "winapi", @@ -5388,9 +5468,9 @@ checksum = "6e63cff320ae2c57904679ba7cb63280a3dc4613885beafb148ee7bf9aa9042d" [[package]] name = "spin" -version = "0.9.2" +version = "0.9.4" source = "registry+https://github.com/rust-lang/crates.io-index" -checksum = "511254be0c5bcf062b019a6c89c01a664aa359ded62f78aa72c6fc137c0590e5" +checksum = "7f6002a767bff9e83f8eeecf883ecb8011875a21ae8da43bffb817a57e78cc09" dependencies = [ "lock_api", ] @@ -5418,39 +5498,50 @@ dependencies = [ [[package]] name = "sqlx" -version = "0.5.11" +version = "0.5.13" source = "registry+https://github.com/rust-lang/crates.io-index" -checksum = "fc15591eb44ffb5816a4a70a7efd5dd87bfd3aa84c4c200401c4396140525826" +checksum = "551873805652ba0d912fec5bbb0f8b4cdd96baf8e2ebf5970e5671092966019b" dependencies = [ - "sqlx-core", - "sqlx-macros", + "sqlx-core 0.5.13", + "sqlx-macros 0.5.13", +] + +[[package]] +name = "sqlx" +version = "0.6.1" +source = "registry+https://github.com/rust-lang/crates.io-index" +checksum = "788841def501aabde58d3666fcea11351ec3962e6ea75dbcd05c84a71d68bcd1" +dependencies = [ + "sqlx-core 0.6.1", + "sqlx-macros 0.6.1", ] [[package]] name = "sqlx-core" -version = "0.5.11" +version = "0.5.13" source = "registry+https://github.com/rust-lang/crates.io-index" -checksum = "195183bf6ff8328bb82c0511a83faf60aacf75840103388851db61d7a9854ae3" +checksum = "e48c61941ccf5ddcada342cd59e3e5173b007c509e1e8e990dafc830294d9dc5" dependencies = [ "ahash", - "atoi", + "atoi 0.4.0", "bitflags", "byteorder", "bytes", "chrono", - "crc", + "crc 2.1.0", "crossbeam-queue", "either", + "event-listener", "flume", "futures-channel", "futures-core", "futures-executor", "futures-intrusive", "futures-util", - "hashlink", + "hashlink 0.7.0", "hex", "indexmap", - "itoa 1.0.1", + "itoa 1.0.3", "libc", "libsqlite3-sys", "log", @@ -5458,47 +5549,123 @@ dependencies = [ "once_cell", "paste", "percent-encoding", - "rustls", - "sha2 0.9.9", - "smallvec 1.8.0", + "rustls 0.19.1", + "sha2 0.10.5", + "smallvec 1.9.0", "sqlformat", - "sqlx-rt", + "sqlx-rt 0.5.13", "stringprep", "thiserror", "tokio-stream", "url", - "webpki", - "webpki-roots", + "webpki 0.21.4", + "webpki-roots 0.21.1", +] + +[[package]] +name = "sqlx-core" +version = "0.6.1" +source = "registry+https://github.com/rust-lang/crates.io-index" +checksum = "8c21d3b5e7cadfe9ba7cdc1295f72cc556c750b4419c27c219c0693198901f8e" +dependencies = [ + "ahash", + "atoi 1.0.0", + "bitflags", + "byteorder", + "bytes", + "crc 3.0.0", + "crossbeam-queue", + "dotenvy", + "either", + "event-listener", + "flume", + "futures-channel", + "futures-core", + "futures-executor", + "futures-intrusive", + "futures-util", + "hashlink 0.8.0", + "hex", + "indexmap", + "itoa 1.0.3", + "libc", + "libsqlite3-sys", + "log", + "memchr", + "once_cell", + "paste", + "percent-encoding", + "rustls 0.20.6", + "rustls-pemfile", + "sha2 0.10.5", + "smallvec 1.9.0", + "sqlformat", + "sqlx-rt 0.6.1", + "stringprep", + "thiserror", + "tokio-stream", + "url", + "webpki-roots 0.22.4", ] [[package]] name = "sqlx-macros" -version = "0.5.11" +version = "0.5.13" source = "registry+https://github.com/rust-lang/crates.io-index" -checksum = "eee35713129561f5e55c554bba1c378e2a7e67f81257b7311183de98c50e6f94" +checksum = "bc0fba2b0cae21fc00fe6046f8baa4c7fcb49e379f0f592b04696607f69ed2e1" dependencies = [ "dotenv", "either", - "heck 0.3.3", + "heck 0.4.0", "once_cell", "proc-macro2", "quote", - "sha2 0.9.9", - "sqlx-core", - "sqlx-rt", + "sha2 0.10.5", + "sqlx-core 0.5.13", + "sqlx-rt 0.5.13", + "syn", + "url", +] + +[[package]] +name = "sqlx-macros" +version = "0.6.1" +source = "registry+https://github.com/rust-lang/crates.io-index" +checksum = "4adfd2df3557bddd3b91377fc7893e8fa899e9b4061737cbade4e1bb85f1b45c" +dependencies = [ + "dotenvy", + "either", + "heck 0.4.0", + "once_cell", + "proc-macro2", + "quote", + "sha2 0.10.5", + "sqlx-core 0.6.1", + "sqlx-rt 0.6.1", "syn", "url", ] [[package]] name = "sqlx-rt" -version = "0.5.11" +version = "0.5.13" source = "registry+https://github.com/rust-lang/crates.io-index" -checksum = "b555e70fbbf84e269ec3858b7a6515bcfe7a166a7cc9c636dd6efd20431678b6" +checksum = "4db708cd3e459078f85f39f96a00960bd841f66ee2a669e90bf36907f5a79aae" dependencies = [ "once_cell", "tokio", - "tokio-rustls", + "tokio-rustls 0.22.0", +] + +[[package]] +name = "sqlx-rt" +version = "0.6.1" +source = "registry+https://github.com/rust-lang/crates.io-index" +checksum = "7be52fc7c96c136cedea840ed54f7d446ff31ad670c9dea95ebcb998530971a3" +dependencies = [ + "once_cell", + "tokio", + "tokio-rustls 0.23.4", ] [[package]] @@ -5534,7 +5701,7 @@ dependencies = [ "reqwest", "serde", "serde_json", - "sqlx", + "sqlx 0.5.13", "thiserror", "tokio", ] @@ -5625,15 +5792,21 @@ dependencies = [ [[package]] name = "syn" -version = "1.0.91" +version = "1.0.99" source = "registry+https://github.com/rust-lang/crates.io-index" -checksum = "b683b2b825c8eef438b77c36a06dc262294da3d5a5813fac20da149241dcd44d" +checksum = "58dbef6ec655055e20b86b15a8cc6d439cca19b667537ac6a1369572d151ab13" dependencies = [ "proc-macro2", "quote", - "unicode-xid", + "unicode-ident", ] +[[package]] +name = "sync_wrapper" +version = "0.1.1" +source = "registry+https://github.com/rust-lang/crates.io-index" +checksum = "20518fe4a4c9acf048008599e464deb21beeae3d3578418951a189c235a7a9a8" + [[package]] name = "synstructure" version = "0.12.6" @@ -5648,9 +5821,9 @@ dependencies = [ [[package]] name = "sysinfo" -version = "0.24.1" +version = "0.24.7" source = "registry+https://github.com/rust-lang/crates.io-index" -checksum = "a6a8e71535da31837213ac114531d31def75d7aebd133264e420a3451fa7f703" +checksum = "54cb4ebf3d49308b99e6e9dc95e989e2fdbdc210e4f67c39db0bb89ba927001c" dependencies = [ "cfg-if 1.0.0", "core-foundation-sys", @@ -5705,7 +5878,7 @@ dependencies = [ "k256", "num-traits", "once_cell", - "prost 0.10.3", + "prost 0.10.4", "prost-types 0.10.1", "ripemd160", "serde", @@ -5717,7 +5890,7 @@ dependencies = [ "subtle 2.4.1", "subtle-encoding", "tendermint-proto", - "time 0.3.9", + "time 0.3.14", "zeroize", ] @@ -5745,12 +5918,12 @@ dependencies = [ "flex-error", "num-derive", "num-traits", - "prost 0.10.3", + "prost 0.10.4", "prost-types 0.10.1", "serde", "serde_bytes", "subtle-encoding", - "time 0.3.9", + "time 0.3.14", ] [[package]] @@ -5763,7 +5936,7 @@ dependencies = [ "bytes", "flex-error", "futures", - "getrandom 0.2.6", + "getrandom 0.2.7", "http", "hyper", "hyper-proxy", @@ -5778,7 +5951,7 @@ dependencies = [ "tendermint-config", "tendermint-proto", "thiserror", - "time 0.3.9", + "time 0.3.14", "tokio", "tracing", "url", @@ -5812,18 +5985,18 @@ checksum = "b1141d4d61095b28419e22cb0bbf02755f5e54e0526f97f1e3d1d160e60885fb" [[package]] name = "thiserror" -version = "1.0.32" +version = "1.0.34" source = "registry+https://github.com/rust-lang/crates.io-index" -checksum = "f5f6586b7f764adc0231f4c79be7b920e766bb2f3e51b3661cdb263828f19994" +checksum = "8c1b05ca9d106ba7d2e31a9dab4a64e7be2cce415321966ea3132c49a656e252" dependencies = [ "thiserror-impl", ] [[package]] name = "thiserror-impl" -version = "1.0.32" +version = "1.0.34" source = "registry+https://github.com/rust-lang/crates.io-index" -checksum = "12bafc5b54507e0149cdf1b145a5d80ab80a90bcd9275df43d4fff68460f6c21" +checksum = "e8f2591983642de85c921015f3f070c665a197ed69e417af436115e3a1407487" dependencies = [ "proc-macro2", "quote", @@ -5852,11 +6025,11 @@ dependencies = [ [[package]] name = "time" -version = "0.3.9" +version = "0.3.14" source = "registry+https://github.com/rust-lang/crates.io-index" -checksum = "c2702e08a7a860f005826c6815dcac101b19b5eb330c27fe4a5928fec1d20ddd" +checksum = "3c3f9a28b618c3a6b9251b6908e9c99e04b9e5c02e6581ccbb67d59c34ef7f9b" dependencies = [ - "itoa 1.0.1", + "itoa 1.0.3", "libc", "num_threads", "serde", @@ -5890,17 +6063,18 @@ dependencies = [ [[package]] name = "tokio" -version = "1.19.1" +version = "1.21.0" source = "registry+https://github.com/rust-lang/crates.io-index" -checksum = "95eec79ea28c00a365f539f1961e9278fbcaf81c0ff6aaf0e93c181352446948" +checksum = "89797afd69d206ccd11fb0ea560a44bbb87731d020670e79416d442919257d42" dependencies = [ + "autocfg 1.1.0", "bytes", "libc", "memchr", "mio", "num_cpus", "once_cell", - "parking_lot 0.12.0", + "parking_lot 0.12.1", "pin-project-lite", "signal-hook-registry", "socket2", @@ -5921,9 +6095,9 @@ dependencies = [ [[package]] name = "tokio-macros" -version = "1.7.0" +version = "1.8.0" source = "registry+https://github.com/rust-lang/crates.io-index" -checksum = "b557f72f448c511a979e2564e55d74e6c4432fc96ff4f6241bc6bded342643b7" +checksum = "9724f9a975fb987ef7a3cd9be0350edcbe130698af5b8f7a631e23d42d052484" dependencies = [ "proc-macro2", "quote", @@ -5946,9 +6120,20 @@ version = "0.22.0" source = "registry+https://github.com/rust-lang/crates.io-index" checksum = "bc6844de72e57df1980054b38be3a9f4702aba4858be64dd700181a8a6d0e1b6" dependencies = [ - "rustls", + "rustls 0.19.1", "tokio", - "webpki", + "webpki 0.21.4", +] + +[[package]] +name = "tokio-rustls" +version = "0.23.4" +source = "registry+https://github.com/rust-lang/crates.io-index" +checksum = "c43ee83903113e03984cb9e5cebe6c04a5116269e900e3ddba8f068a62adda59" +dependencies = [ + "rustls 0.20.6", + "tokio", + "webpki 0.22.0", ] [[package]] @@ -5990,9 +6175,9 @@ dependencies = [ [[package]] name = "tokio-util" -version = "0.6.9" +version = "0.6.10" source = "registry+https://github.com/rust-lang/crates.io-index" -checksum = "9e99e1983e5d376cd8eb4b66604d2e99e79f5bd988c3055891dcd8c9e2604cc0" +checksum = "36943ee01a6d67977dd3f84a5a1d2efeb4ada3a1ae771cadfaa535d9d9fc6507" dependencies = [ "bytes", "futures-core", @@ -6020,21 +6205,22 @@ dependencies = [ [[package]] name = "toml" -version = "0.5.8" +version = "0.5.9" source = "registry+https://github.com/rust-lang/crates.io-index" -checksum = "a31142970826733df8241ef35dc040ef98c679ab14d7c3e54d827099b3acecaa" +checksum = "8d82e1a7758622a465f8cee077614c73484dac5b836c02ff6a40d5d1010324d7" dependencies = [ "serde", ] [[package]] name = "tonic" -version = "0.6.2" +version = "0.8.0" source = "registry+https://github.com/rust-lang/crates.io-index" -checksum = "ff08f4649d10a70ffa3522ca559031285d8e421d727ac85c60825761818f5d0a" +checksum = "498f271adc46acce75d66f639e4d35b31b2394c295c82496727dafa16d465dd2" dependencies = [ "async-stream", "async-trait", + "axum", "base64", "bytes", "futures-core", @@ -6046,11 +6232,11 @@ dependencies = [ "hyper-timeout", "percent-encoding", "pin-project", - "prost 0.9.0", - "prost-derive 0.9.0", + "prost 0.11.0", + "prost-derive 0.11.0", "tokio", "tokio-stream", - "tokio-util 0.6.9", + "tokio-util 0.7.3", "tower", "tower-layer", "tower-service", @@ -6058,18 +6244,6 @@ dependencies = [ "tracing-futures", ] -[[package]] -name = "tonic-build" -version = "0.6.2" -source = "registry+https://github.com/rust-lang/crates.io-index" -checksum = "9403f1bafde247186684b230dc6f38b5cd514584e8bec1dd32514be4745fa757" -dependencies = [ - "proc-macro2", - "prost-build", - "quote", - "syn", -] - [[package]] name = "topology" version = "0.1.0" @@ -6086,9 +6260,9 @@ dependencies = [ [[package]] name = "tower" -version = "0.4.12" +version = "0.4.13" source = "registry+https://github.com/rust-lang/crates.io-index" -checksum = "9a89fd63ad6adf737582df5db40d286574513c69a11dac5214dc3b5603d6713e" +checksum = "b8fa9be0de6cf49e536ce1851f987bd21a43b771b09473c3549a6c853db37c1c" dependencies = [ "futures-core", "futures-util", @@ -6104,6 +6278,25 @@ dependencies = [ "tracing", ] +[[package]] +name = "tower-http" +version = "0.3.4" +source = "registry+https://github.com/rust-lang/crates.io-index" +checksum = "3c530c8675c1dbf98facee631536fa116b5fb6382d7dd6dc1b118d970eafe3ba" +dependencies = [ + "bitflags", + "bytes", + "futures-core", + "futures-util", + "http", + "http-body", + "http-range-header", + "pin-project-lite", + "tower", + "tower-layer", + "tower-service", +] + [[package]] name = "tower-layer" version = "0.3.1" @@ -6112,15 +6305,15 @@ checksum = "343bc9466d3fe6b0f960ef45960509f84480bf4fd96f92901afe7ff3df9d3a62" [[package]] name = "tower-service" -version = "0.3.1" +version = "0.3.2" source = "registry+https://github.com/rust-lang/crates.io-index" -checksum = "360dfd1d6d30e05fda32ace2c8c70e9c0a9da713275777f5a4dbb8a1893930c6" +checksum = "b6bc1c9ce2b5135ac7f93c72918fc37feb872bdc6a5533a8b85eb4b86bfdae52" [[package]] name = "tracing" -version = "0.1.33" +version = "0.1.36" source = "registry+https://github.com/rust-lang/crates.io-index" -checksum = "80b9fa4360528139bc96100c160b7ae879f5567f49f1782b0b02035b0358ebf3" +checksum = "2fce9567bd60a67d08a16488756721ba392f24f29006402881e43b19aac64307" dependencies = [ "cfg-if 1.0.0", "log", @@ -6131,9 +6324,9 @@ dependencies = [ [[package]] name = "tracing-attributes" -version = "0.1.20" +version = "0.1.22" source = "registry+https://github.com/rust-lang/crates.io-index" -checksum = "2e65ce065b4b5c53e73bb28912318cb8c9e9ad3921f1d669eb0e68b4c8143a2b" +checksum = "11c75893af559bc8e10716548bdef5cb2b983f8e637db9d0e15126b61b484ee2" dependencies = [ "proc-macro2", "quote", @@ -6142,11 +6335,11 @@ dependencies = [ [[package]] name = "tracing-core" -version = "0.1.24" +version = "0.1.29" source = "registry+https://github.com/rust-lang/crates.io-index" -checksum = "90442985ee2f57c9e1b548ee72ae842f4a9a20e3f417cc38dbc5dc684d9bb4ee" +checksum = "5aeea4303076558a00714b823f9ad67d58a3bbda1df83d8827d21193156e22f7" dependencies = [ - "lazy_static", + "once_cell", "valuable", ] @@ -6162,9 +6355,9 @@ dependencies = [ [[package]] name = "tracing-log" -version = "0.1.2" +version = "0.1.3" source = "registry+https://github.com/rust-lang/crates.io-index" -checksum = "a6923477a48e41c1951f1999ef8bb5a3023eb723ceadafe78ffb65dc366761e3" +checksum = "78ddad33d2d10b1ed7eb9d1f518a5674713876e97e5bb9b7345a7984fbb4f922" dependencies = [ "lazy_static", "log", @@ -6173,16 +6366,16 @@ dependencies = [ [[package]] name = "tracing-subscriber" -version = "0.3.11" +version = "0.3.15" source = "registry+https://github.com/rust-lang/crates.io-index" -checksum = "4bc28f93baff38037f64e6f43d34cfa1605f27a49c34e8a04c5e78b0babf2596" +checksum = "60db860322da191b40952ad9affe65ea23e7dd6a5c442c2c42865810c6ab8e6b" dependencies = [ "ansi_term", - "lazy_static", "matchers", + "once_cell", "regex", "sharded-slab", - "smallvec 1.8.0", + "smallvec 1.9.0", "thread_local", "tracing", "tracing-core", @@ -6197,9 +6390,9 @@ checksum = "59547bce71d9c38b83d9c0e92b6066c4253371f15005def0c30d9657f50c7642" [[package]] name = "ts-rs" -version = "6.1.2" +version = "6.2.0" source = "registry+https://github.com/rust-lang/crates.io-index" -checksum = "3d26cba30c9b3a2f537f765cf754126f11c983b7426d280ae0b4cef2374cab98" +checksum = "dc59f479df54269b400dd95bc3b7e81623b3e4b9c70c8ca7125ab8341eafa64e" dependencies = [ "thiserror", "ts-rs-macros", @@ -6222,9 +6415,9 @@ dependencies = [ [[package]] name = "ts-rs-macros" -version = "6.1.2" +version = "6.2.0" source = "registry+https://github.com/rust-lang/crates.io-index" -checksum = "fd8e302fbcf5b60dfa1df443535967511442c5ce4eac8b4c9fa811f2274280a4" +checksum = "9f807fdb3151fee75df7485b901a89624358cd07a67a8fb1a5831bf5a07681ff" dependencies = [ "Inflector", "proc-macro2", @@ -6261,18 +6454,18 @@ checksum = "dcf81ac59edc17cc8697ff311e8f5ef2d99fcbd9817b34cec66f90b6c3dfd987" [[package]] name = "ubyte" -version = "0.10.1" +version = "0.10.3" source = "registry+https://github.com/rust-lang/crates.io-index" -checksum = "42756bb9e708855de2f8a98195643dff31a97f0485d90d8467b39dc24be9e8fe" +checksum = "c81f0dae7d286ad0d9366d7679a77934cfc3cf3a8d67e82669794412b2368fe6" dependencies = [ "serde", ] [[package]] name = "ucd-trie" -version = "0.1.3" +version = "0.1.5" source = "registry+https://github.com/rust-lang/crates.io-index" -checksum = "56dee185309b50d1f11bfedef0fe6d036842e3fb77413abef29f8f8d1c5d4c1c" +checksum = "9e79c4d996edb816c91e4308506774452e55e95c3c9de07b6729e17e15a5ef81" [[package]] name = "uint" @@ -6288,9 +6481,9 @@ dependencies = [ [[package]] name = "uncased" -version = "0.9.6" +version = "0.9.7" source = "registry+https://github.com/rust-lang/crates.io-index" -checksum = "5baeed7327e25054889b9bd4f975f32e5f4c5d434042d59ab6cd4142c0a76ed0" +checksum = "09b01702b0fd0b3fadcf98e098780badda8742d4f4a7676615cad90e8ac73622" dependencies = [ "serde", "version_check", @@ -6317,9 +6510,15 @@ dependencies = [ [[package]] name = "unicode-bidi" -version = "0.3.7" +version = "0.3.8" source = "registry+https://github.com/rust-lang/crates.io-index" -checksum = "1a01404663e3db436ed2746d9fefef640d868edae3cceb81c3b8d5732fda678f" +checksum = "099b7128301d285f79ddd55b9a83d5e6b9e97c92e0ea0daebee7263e932de992" + +[[package]] +name = "unicode-ident" +version = "1.0.3" +source = "registry+https://github.com/rust-lang/crates.io-index" +checksum = "c4f5b37a154999a8f3f98cc23a628d850e154479cd94decf3414696e12e31aaf" [[package]] name = "unicode-normalization" @@ -6344,9 +6543,9 @@ checksum = "3ed742d4ea2bd1176e236172c8429aaf54486e7ac098db29ffe6529e0ce50973" [[package]] name = "unicode-xid" -version = "0.2.2" +version = "0.2.3" source = "registry+https://github.com/rust-lang/crates.io-index" -checksum = "8ccb82d61f80a663efe1f787a51b16b5a51e3314d6ac365b08639f52387b33f3" +checksum = "957e51f3646910546462e67d5f7599b9e4fb8acdd304b087a6494730f9eebf04" [[package]] name = "unicode_categories" @@ -6360,7 +6559,7 @@ version = "0.4.1" source = "registry+https://github.com/rust-lang/crates.io-index" checksum = "9f214e8f697e925001e66ec2c6e37a4ef93f0f78c2eed7814394e10c62025b05" dependencies = [ - "generic-array 0.14.5", + "generic-array 0.14.6", "subtle 2.4.1", ] @@ -6431,7 +6630,7 @@ dependencies = [ "mixnet-contract-common", "multisig-contract-common", "network-defaults", - "prost 0.10.3", + "prost 0.10.4", "reqwest", "serde", "serde_json", @@ -6662,7 +6861,7 @@ dependencies = [ "ethereum-types", "futures", "futures-timer", - "getrandom 0.2.6", + "getrandom 0.2.7", "headers", "hex", "js-sys", @@ -6680,7 +6879,7 @@ dependencies = [ "tiny-keccak", "tokio", "tokio-stream", - "tokio-util 0.6.9", + "tokio-util 0.6.10", "url", "wasm-bindgen", "wasm-bindgen-futures", @@ -6709,13 +6908,32 @@ dependencies = [ "untrusted", ] +[[package]] +name = "webpki" +version = "0.22.0" +source = "registry+https://github.com/rust-lang/crates.io-index" +checksum = "f095d78192e208183081cc07bc5515ef55216397af48b873e5edcd72637fa1bd" +dependencies = [ + "ring", + "untrusted", +] + [[package]] name = "webpki-roots" version = "0.21.1" source = "registry+https://github.com/rust-lang/crates.io-index" checksum = "aabe153544e473b775453675851ecc86863d2a81d786d741f6b76778f2a48940" dependencies = [ - "webpki", + "webpki 0.21.4", +] + +[[package]] +name = "webpki-roots" +version = "0.22.4" +source = "registry+https://github.com/rust-lang/crates.io-index" +checksum = "f1c760f0d366a6c24a02ed7816e23e691f5d92291f94d15e836006fd11b04daf" +dependencies = [ + "webpki 0.22.0", ] [[package]] @@ -6727,22 +6945,11 @@ dependencies = [ "serde_json", ] -[[package]] -name = "which" -version = "4.2.5" -source = "registry+https://github.com/rust-lang/crates.io-index" -checksum = "5c4fb54e6113b6a8772ee41c3404fb0301ac79604489467e0a9ce1f3e97c24ae" -dependencies = [ - "either", - "lazy_static", - "libc", -] - [[package]] name = "wildmatch" -version = "2.1.0" +version = "2.1.1" source = "registry+https://github.com/rust-lang/crates.io-index" -checksum = "d6c48bd20df7e4ced539c12f570f937c6b4884928a87fee70a479d72f031d4e0" +checksum = "ee583bdc5ff1cf9db20e9db5bb3ff4c3089a8f6b8b31aff265c9aba85812db86" [[package]] name = "winapi" @@ -6776,47 +6983,90 @@ source = "registry+https://github.com/rust-lang/crates.io-index" checksum = "712e227841d057c1ee1cd2fb22fa7e5a5461ae8e48fa2ca79ec42cfc1931183f" [[package]] -name = "windows-sys" -version = "0.34.0" +name = "windows" +version = "0.32.0" source = "registry+https://github.com/rust-lang/crates.io-index" -checksum = "5acdd78cb4ba54c0045ac14f62d8f94a03d10047904ae2a40afa1e99d8f70825" +checksum = "fbedf6db9096bc2364adce0ae0aa636dcd89f3c3f2cd67947062aaf0ca2a10ec" dependencies = [ - "windows_aarch64_msvc", - "windows_i686_gnu", - "windows_i686_msvc", - "windows_x86_64_gnu", - "windows_x86_64_msvc", + "windows_aarch64_msvc 0.32.0", + "windows_i686_gnu 0.32.0", + "windows_i686_msvc 0.32.0", + "windows_x86_64_gnu 0.32.0", + "windows_x86_64_msvc 0.32.0", +] + +[[package]] +name = "windows-sys" +version = "0.36.1" +source = "registry+https://github.com/rust-lang/crates.io-index" +checksum = "ea04155a16a59f9eab786fe12a4a450e75cdb175f9e0d80da1e17db09f55b8d2" +dependencies = [ + "windows_aarch64_msvc 0.36.1", + "windows_i686_gnu 0.36.1", + "windows_i686_msvc 0.36.1", + "windows_x86_64_gnu 0.36.1", + "windows_x86_64_msvc 0.36.1", ] [[package]] name = "windows_aarch64_msvc" -version = "0.34.0" +version = "0.32.0" source = "registry+https://github.com/rust-lang/crates.io-index" -checksum = "17cffbe740121affb56fad0fc0e421804adf0ae00891205213b5cecd30db881d" +checksum = "d8e92753b1c443191654ec532f14c199742964a061be25d77d7a96f09db20bf5" + +[[package]] +name = "windows_aarch64_msvc" +version = "0.36.1" +source = "registry+https://github.com/rust-lang/crates.io-index" +checksum = "9bb8c3fd39ade2d67e9874ac4f3db21f0d710bee00fe7cab16949ec184eeaa47" [[package]] name = "windows_i686_gnu" -version = "0.34.0" +version = "0.32.0" source = "registry+https://github.com/rust-lang/crates.io-index" -checksum = "2564fde759adb79129d9b4f54be42b32c89970c18ebf93124ca8870a498688ed" +checksum = "6a711c68811799e017b6038e0922cb27a5e2f43a2ddb609fe0b6f3eeda9de615" + +[[package]] +name = "windows_i686_gnu" +version = "0.36.1" +source = "registry+https://github.com/rust-lang/crates.io-index" +checksum = "180e6ccf01daf4c426b846dfc66db1fc518f074baa793aa7d9b9aaeffad6a3b6" [[package]] name = "windows_i686_msvc" -version = "0.34.0" +version = "0.32.0" source = "registry+https://github.com/rust-lang/crates.io-index" -checksum = "9cd9d32ba70453522332c14d38814bceeb747d80b3958676007acadd7e166956" +checksum = "146c11bb1a02615db74680b32a68e2d61f553cc24c4eb5b4ca10311740e44172" + +[[package]] +name = "windows_i686_msvc" +version = "0.36.1" +source = "registry+https://github.com/rust-lang/crates.io-index" +checksum = "e2e7917148b2812d1eeafaeb22a97e4813dfa60a3f8f78ebe204bcc88f12f024" [[package]] name = "windows_x86_64_gnu" -version = "0.34.0" +version = "0.32.0" source = "registry+https://github.com/rust-lang/crates.io-index" -checksum = "cfce6deae227ee8d356d19effc141a509cc503dfd1f850622ec4b0f84428e1f4" +checksum = "c912b12f7454c6620635bbff3450962753834be2a594819bd5e945af18ec64bc" + +[[package]] +name = "windows_x86_64_gnu" +version = "0.36.1" +source = "registry+https://github.com/rust-lang/crates.io-index" +checksum = "4dcd171b8776c41b97521e5da127a2d86ad280114807d0b2ab1e462bc764d9e1" [[package]] name = "windows_x86_64_msvc" -version = "0.34.0" +version = "0.32.0" source = "registry+https://github.com/rust-lang/crates.io-index" -checksum = "d19538ccc21819d01deaf88d6a17eae6596a12e9aafdbb97916fb49896d89de9" +checksum = "504a2476202769977a040c6364301a3f65d0cc9e3fb08600b2bda150a0488316" + +[[package]] +name = "windows_x86_64_msvc" +version = "0.36.1" +source = "registry+https://github.com/rust-lang/crates.io-index" +checksum = "c811ca4a8c853ef420abd8592ba53ddbbac90410fab6903b3e79972a631f7680" [[package]] name = "winreg" @@ -6871,9 +7121,9 @@ checksum = "09041cd90cf85f7f8b2df60c646f853b7f535ce68f85244eb6731cf89fa498ec" [[package]] name = "zeroize" -version = "1.4.3" +version = "1.5.7" source = "registry+https://github.com/rust-lang/crates.io-index" -checksum = "d68d9dcec5f9b43a30d38c49f91dfedfaac384cb8f085faca366c26207dd1619" +checksum = "c394b5bd0c6f669e7275d9c20aa90ae064cb22e75a1cad54e1b34088034b149f" dependencies = [ "zeroize_derive", ] diff --git a/common/cosmwasm-smart-contracts/mixnet-contract/src/mixnode.rs b/common/cosmwasm-smart-contracts/mixnet-contract/src/mixnode.rs index 752719e9c9..e124853074 100644 --- a/common/cosmwasm-smart-contracts/mixnet-contract/src/mixnode.rs +++ b/common/cosmwasm-smart-contracts/mixnet-contract/src/mixnode.rs @@ -166,7 +166,6 @@ pub mod fixed_U128_as_string { use super::U128; use serde::de::Error; use serde::Deserialize; - use std::str::FromStr; pub fn serialize(val: &U128, serializer: S) -> Result where diff --git a/validator-api/Cargo.toml b/validator-api/Cargo.toml index 6c5faecb82..43c7ea30e1 100644 --- a/validator-api/Cargo.toml +++ b/validator-api/Cargo.toml @@ -17,36 +17,46 @@ rust-version = "1.56" [dependencies] async-trait = "0.1.52" cfg-if = "1.0" -clap = "2.33.0" -console-subscriber = { version = "0.1.1", optional = true} # validator-api needs to be built with RUSTFLAGS="--cfg tokio_unstable" +clap = { version = "3.2", features = ["cargo"] } +console-subscriber = { version = "0.1.1", optional = true } # validator-api needs to be built with RUSTFLAGS="--cfg tokio_unstable" dirs = "4.0" dotenv = "0.15.0" -futures = "0.3" +futures = "0.3.24" humantime-serde = "1.0" -log = "0.4" +log = "0.4.17" pin-project = "1.0" -pretty_env_logger = "0.4" -rand = "0.8" -rand-07 = { package = "rand", version = "0.7" } # required for compatibility -reqwest = { version = "0.11", features = ["json"] } +pretty_env_logger = "0.4.0" +rand = "0.8.5" +rand-07 = { package = "rand", version = "0.7.3" } # required for compatibility +reqwest = { version = "0.11.11", features = ["json"] } rocket = { version = "0.5.0-rc.2", features = ["json"] } -rocket_cors = { git="https://github.com/lawliet89/rocket_cors", rev="dfd3662c49e2f6fc37df35091cb94d82f7fb5915" } +rocket_cors = { git = "https://github.com/lawliet89/rocket_cors", rev = "dfd3662c49e2f6fc37df35091cb94d82f7fb5915" } serde = "1.0" serde_json = "1.0" -tap = "1.0.1" -thiserror = "1" -time = { version = "0.3", features = ["serde-human-readable", "parsing"]} -tokio = { version = "1.19.1", features = ["rt-multi-thread", "macros", "signal", "time"] } +tap = "1.0" +thiserror = "1.0" +time = { version = "0.3.14", features = ["serde-human-readable", "parsing"] } +tokio = { version = "1.19", features = [ + "rt-multi-thread", + "macros", + "signal", + "time", +] } tokio-stream = "0.1.9" url = "2.2" -ts-rs = "6.1.2" +ts-rs = "6.1" -anyhow = "1" +anyhow = "1.0" getset = "0.1.1" rocket_sync_db_pools = { version = "0.1.0-rc.2", default-features = false } -sqlx = { version = "0.5", features = ["runtime-tokio-rustls", "sqlite", "macros", "migrate"]} +sqlx = { version = "0.6.1", features = [ + "runtime-tokio-rustls", + "sqlite", + "macros", + "migrate", +] } okapi = { version = "0.7.0-rc.1", features = ["impl_json_schema"] } rocket_okapi = { version = "0.8.0-rc.2", features = ["swagger"] } @@ -59,30 +69,49 @@ config = { path = "../common/config" } cosmwasm-std = "1.0.0" credential-storage = { path = "../common/credential-storage" } credentials = { path = "../common/credentials", optional = true } -crypto = { path="../common/crypto" } -gateway-client = { path="../common/client-libs/gateway-client" } +crypto = { path = "../common/crypto" } +gateway-client = { path = "../common/client-libs/gateway-client" } inclusion-probability = { path = "../common/inclusion-probability" } -mixnet-contract-common = { path= "../common/cosmwasm-smart-contracts/mixnet-contract" } +mixnet-contract-common = { path = "../common/cosmwasm-smart-contracts/mixnet-contract" } multisig-contract-common = { path = "../common/cosmwasm-smart-contracts/multisig-contract" } nymcoconut = { path = "../common/nymcoconut", optional = true } -nymsphinx = { path="../common/nymsphinx" } +nymsphinx = { path = "../common/nymsphinx" } task = { path = "../common/task" } -topology = { path="../common/topology" } +topology = { path = "../common/topology" } validator-api-requests = { path = "validator-api-requests" } -validator-client = { path="../common/client-libs/validator-client", features = ["nymd-client"] } -version-checker = { path="../common/version-checker" } +validator-client = { path = "../common/client-libs/validator-client", features = [ + "nymd-client", +] } +version-checker = { path = "../common/version-checker" } [features] -coconut = ["coconut-interface", "credentials", "gateway-client/coconut", "credentials/coconut", "validator-api-requests/coconut", "nymcoconut"] +coconut = [ + "coconut-interface", + "credentials", + "gateway-client/coconut", + "credentials/coconut", + "validator-api-requests/coconut", + "nymcoconut", +] no-reward = [] generate-ts = [] [build-dependencies] tokio = { version = "1.19.1", features = ["rt-multi-thread", "macros"] } -sqlx = { version = "0.5", features = ["runtime-tokio-rustls", "sqlite", "macros", "migrate"] } -vergen = { version = "5", default-features = false, features = ["build", "git", "rustc", "cargo"] } +sqlx = { version = "0.5", features = [ + "runtime-tokio-rustls", + "sqlite", + "macros", + "migrate", +] } +vergen = { version = "5", default-features = false, features = [ + "build", + "git", + "rustc", + "cargo", +] } [dev-dependencies] -attohttpc = {version = "0.18.0", features = ["json"]} +attohttpc = { version = "0.18.0", features = ["json"] } cw3 = "0.13.2" cw-utils = "0.13.2" diff --git a/validator-api/src/main.rs b/validator-api/src/main.rs index 96abe8408a..09537181a3 100644 --- a/validator-api/src/main.rs +++ b/validator-api/src/main.rs @@ -114,7 +114,7 @@ fn long_version() -> String { ) } -fn parse_args<'a>() -> ArgMatches<'a> { +fn parse_args() -> ArgMatches { let build_details = long_version(); let base_app = App::new("Nym Validator API") .version(crate_version!()) @@ -136,13 +136,13 @@ fn parse_args<'a>() -> ArgMatches<'a> { Arg::with_name(MONITORING_ENABLED) .help("specifies whether a network monitoring is enabled on this API") .long(MONITORING_ENABLED) - .short("m") + .short('m') ) .arg( Arg::with_name(REWARDING_ENABLED) .help("specifies whether a network rewarding is enabled on this API") .long(REWARDING_ENABLED) - .short("r") + .short('r') .requires_all(&[MONITORING_ENABLED, MNEMONIC_ARG]) ) .arg( @@ -165,7 +165,7 @@ fn parse_args<'a>() -> ArgMatches<'a> { Arg::with_name(WRITE_CONFIG_ARG) .help("specifies whether a config file based on provided arguments should be saved to a file") .long(WRITE_CONFIG_ARG) - .short("w") + .short('w') ) .arg( Arg::with_name(REWARDING_MONITOR_THRESHOLD_ARG) @@ -277,7 +277,7 @@ fn setup_logging() { .init(); } -fn override_config(mut config: Config, matches: &ArgMatches<'_>) -> Config { +fn override_config(mut config: Config, matches: &ArgMatches) -> Config { if let Some(id) = matches.value_of(ID) { fs::create_dir_all(Config::default_config_directory(Some(id))) .expect("Could not create config directory"); @@ -538,7 +538,7 @@ fn get_servers() -> Vec { }] } -async fn run_validator_api(matches: ArgMatches<'static>) -> Result<()> { +async fn run_validator_api(matches: ArgMatches) -> Result<()> { let system_version = env!("CARGO_PKG_VERSION"); // try to load config from the file, if it doesn't exist, use default values From 49d8424e30d714e304d2a212a6cd1f58fec9fe94 Mon Sep 17 00:00:00 2001 From: Drazen Urch Date: Tue, 6 Sep 2022 14:24:17 +0200 Subject: [PATCH 10/46] Update network-requester dependencies (#1588) --- Cargo.lock | 106 ++++++++++-------- .../network-requester/Cargo.toml | 24 ++-- .../network-requester/src/main.rs | 6 +- 3 files changed, 76 insertions(+), 60 deletions(-) diff --git a/Cargo.lock b/Cargo.lock index 6d495b6a06..6419e1e296 100644 --- a/Cargo.lock +++ b/Cargo.lock @@ -586,13 +586,9 @@ version = "2.34.0" source = "registry+https://github.com/rust-lang/crates.io-index" checksum = "a0610544180c38b88101fecf2dd634b174a62eef6946f84dfc6a7127512b381c" dependencies = [ - "ansi_term", - "atty", "bitflags", - "strsim 0.8.0", "textwrap 0.11.0", "unicode-width", - "vec_map", ] [[package]] @@ -607,7 +603,7 @@ dependencies = [ "clap_lex", "indexmap", "once_cell", - "strsim 0.10.0", + "strsim", "termcolor", "textwrap 0.15.0", ] @@ -618,7 +614,7 @@ version = "3.2.4" source = "registry+https://github.com/rust-lang/crates.io-index" checksum = "e4179da71abd56c26b54dd0c248cc081c1f43b0a1a7e8448e28e57a29baa993d" dependencies = [ - "clap 3.2.8", + "clap 3.2.20", ] [[package]] @@ -627,7 +623,7 @@ version = "3.2.4" source = "registry+https://github.com/rust-lang/crates.io-index" checksum = "ed37b4c0c1214673eba6ad8ea31666626bf72be98ffb323067d973c48b4964b9" dependencies = [ - "clap 3.2.8", + "clap 3.2.20", "clap_complete", ] @@ -721,9 +717,9 @@ dependencies = [ [[package]] name = "comfy-table" -version = "6.0.0" +version = "6.1.0" source = "registry+https://github.com/rust-lang/crates.io-index" -checksum = "121d8a5b0346092c18a4b2fd6f620d7a06f0eb7ac0a45860939a0884bc579c56" +checksum = "85914173c2f558d61613bfbbf1911f14e630895087a7ed2fafc0f5319e1536e7" dependencies = [ "crossterm", "strum 0.24.1", @@ -887,9 +883,9 @@ dependencies = [ [[package]] name = "cosmwasm-derive" -version = "1.0.0" +version = "1.1.0" source = "registry+https://github.com/rust-lang/crates.io-index" -checksum = "4b36e527620a2a3e00e46b6e731ab6c9b68d11069c986f7d7be8eba79ef081a4" +checksum = "9053ebe2ad85831e9f9e2124fa2b22807528a78b25cc447483ce2a4aadfba394" dependencies = [ "syn", ] @@ -1103,15 +1099,15 @@ dependencies = [ [[package]] name = "crossterm" -version = "0.23.2" +version = "0.25.0" source = "registry+https://github.com/rust-lang/crates.io-index" -checksum = "a2102ea4f781910f8a5b98dd061f4c2023f479ce7bb1236330099ceb5a93cf17" +checksum = "e64e6c0fbe2c17357405f7c758c1ef960fce08bdfb2c03d88d2a18d7e09c4b67" dependencies = [ "bitflags", "crossterm_winapi", "libc", "mio", - "parking_lot 0.12.0", + "parking_lot 0.12.1", "signal-hook", "signal-hook-mio", "winapi", @@ -1339,7 +1335,7 @@ dependencies = [ "ident_case", "proc-macro2", "quote", - "strsim 0.10.0", + "strsim", "syn", ] @@ -1768,9 +1764,9 @@ dependencies = [ [[package]] name = "figment" -version = "0.10.6" +version = "0.10.7" source = "registry+https://github.com/rust-lang/crates.io-index" -checksum = "790b4292c72618abbab50f787a477014fe15634f96291de45672ce46afe122df" +checksum = "6e3bd154d9ae2f1bb0ada5b7eebd56529513efa5de7d2fc8c6adf33bc43260cf" dependencies = [ "atomic", "pear", @@ -2058,8 +2054,8 @@ dependencies = [ "secp256k1", "thiserror", "tokio", - "tokio-tungstenite", - "tungstenite", + "tokio-tungstenite 0.14.0", + "tungstenite 0.13.0", "url", "validator-client", "wasm-bindgen", @@ -2084,7 +2080,7 @@ dependencies = [ "serde", "serde_json", "thiserror", - "tungstenite", + "tungstenite 0.13.0", ] [[package]] @@ -2703,9 +2699,9 @@ checksum = "879d54834c8c76457ef4293a689b2a8c59b076067ad77b15efafbb05f92a592b" [[package]] name = "ipnetwork" -version = "0.17.0" +version = "0.20.0" source = "registry+https://github.com/rust-lang/crates.io-index" -checksum = "02c3eaab3ac0ede60ffa41add21970a7df7d91772c03383aac6c2c3d53cc716b" +checksum = "bf466541e9d546596ee94f9f69590f89473455f88372423e0008fc1a7daf100e" dependencies = [ "serde", ] @@ -3190,7 +3186,7 @@ dependencies = [ "base64", "bip39", "bs58", - "clap 3.2.8", + "clap 3.2.20", "clap_complete", "clap_complete_fig", "dotenv", @@ -3212,7 +3208,7 @@ dependencies = [ "bip39", "bs58", "cfg-if 1.0.0", - "clap 3.2.8", + "clap 3.2.20", "comfy-table", "cosmrs", "cosmwasm-std", @@ -3226,7 +3222,7 @@ dependencies = [ "serde", "serde_json", "thiserror", - "time 0.3.9", + "time 0.3.14", "toml", "url", "validator-client", @@ -3258,7 +3254,7 @@ dependencies = [ "serde_json", "sled", "tokio", - "tokio-tungstenite", + "tokio-tungstenite 0.14.0", "topology", "url", "validator-client", @@ -3305,7 +3301,7 @@ dependencies = [ "thiserror", "tokio", "tokio-stream", - "tokio-tungstenite", + "tokio-tungstenite 0.14.0", "tokio-util 0.7.3", "url", "validator-api-requests", @@ -3360,7 +3356,7 @@ name = "nym-network-requester" version = "1.0.2" dependencies = [ "async-trait", - "clap 2.34.0", + "clap 3.2.20", "dirs", "futures", "ipnetwork", @@ -3375,11 +3371,11 @@ dependencies = [ "reqwest", "serde", "socks5-requests", - "sqlx 0.5.13", + "sqlx 0.6.1", "statistics-common", "thiserror", "tokio", - "tokio-tungstenite", + "tokio-tungstenite 0.17.2", "websocket-requests", ] @@ -3396,7 +3392,7 @@ dependencies = [ "statistics-common", "thiserror", "tokio", - "tokio-tungstenite", + "tokio-tungstenite 0.14.0", ] [[package]] @@ -5573,6 +5569,7 @@ dependencies = [ "bitflags", "byteorder", "bytes", + "chrono", "crc 3.0.0", "crossbeam-queue", "dotenvy", @@ -5716,12 +5713,6 @@ dependencies = [ "unicode-normalization", ] -[[package]] -name = "strsim" -version = "0.8.0" -source = "registry+https://github.com/rust-lang/crates.io-index" -checksum = "8ea5119cdb4c55b55d432abb513a0429384878c15dde60cc77b1c99de1a95a6a" - [[package]] name = "strsim" version = "0.10.0" @@ -6170,7 +6161,19 @@ dependencies = [ "log", "pin-project", "tokio", - "tungstenite", + "tungstenite 0.13.0", +] + +[[package]] +name = "tokio-tungstenite" +version = "0.17.2" +source = "registry+https://github.com/rust-lang/crates.io-index" +checksum = "f714dd15bead90401d77e04243611caec13726c2408afd5b31901dfcdcb3b181" +dependencies = [ + "futures-util", + "log", + "tokio", + "tungstenite 0.17.3", ] [[package]] @@ -6446,6 +6449,25 @@ dependencies = [ "utf-8", ] +[[package]] +name = "tungstenite" +version = "0.17.3" +source = "registry+https://github.com/rust-lang/crates.io-index" +checksum = "e27992fd6a8c29ee7eef28fc78349aa244134e10ad447ce3b9f0ac0ed0fa4ce0" +dependencies = [ + "base64", + "byteorder", + "bytes", + "http", + "httparse", + "log", + "rand 0.8.5", + "sha-1 0.10.0", + "thiserror", + "url", + "utf-8", +] + [[package]] name = "typenum" version = "1.15.0" @@ -6656,12 +6678,6 @@ version = "0.2.15" source = "registry+https://github.com/rust-lang/crates.io-index" checksum = "accd4ea62f7bb7a82fe23066fb0957d48ef677f6eeb8215f372f52e48bb32426" -[[package]] -name = "vec_map" -version = "0.8.2" -source = "registry+https://github.com/rust-lang/crates.io-index" -checksum = "f1bddf1187be692e79c5ffeab891132dfb0f236ed36a43c7ed39f1165ee20191" - [[package]] name = "vergen" version = "5.1.17" @@ -6831,7 +6847,7 @@ version = "0.1.0" dependencies = [ "futures", "js-sys", - "tungstenite", + "tungstenite 0.13.0", "wasm-bindgen", "wasm-bindgen-futures", "web-sys", diff --git a/service-providers/network-requester/Cargo.toml b/service-providers/network-requester/Cargo.toml index 4d30d20755..0c5a5d6b12 100644 --- a/service-providers/network-requester/Cargo.toml +++ b/service-providers/network-requester/Cargo.toml @@ -11,20 +11,20 @@ edition = "2021" [dependencies] async-trait = { version = "0.1.51" } -clap = "2.33.0" +clap = "3.2" dirs = "4.0" -futures = "0.3" -ipnetwork = "0.17" -log = "0.4" -pretty_env_logger = "0.4" -publicsuffix = "1.5" -rand = "0.7" -reqwest = { version = "0.11", features = ["json"] } +futures = "0.3.24" +ipnetwork = "0.20.0" +log = "0.4.17" +pretty_env_logger = "0.4.0" +publicsuffix = "1.5" # Can't update this until bip updates to support newer idna version +rand = "0.7.3" +reqwest = { version = "0.11.11", features = ["json"] } serde = { version = "1.0", features = ["derive"] } -sqlx = { version = "0.5", features = ["runtime-tokio-rustls", "chrono"]} -thiserror = "1" -tokio = { version = "1.19.1", features = [ "net", "rt-multi-thread", "macros" ] } -tokio-tungstenite = "0.14" +sqlx = { version = "0.6.1", features = ["runtime-tokio-rustls", "chrono"]} +thiserror = "1.0" +tokio = { version = "1.19", features = [ "net", "rt-multi-thread", "macros" ] } +tokio-tungstenite = "0.17.2" # internal diff --git a/service-providers/network-requester/src/main.rs b/service-providers/network-requester/src/main.rs index 60f57bc745..4f30fb77e8 100644 --- a/service-providers/network-requester/src/main.rs +++ b/service-providers/network-requester/src/main.rs @@ -17,7 +17,7 @@ const WS_PORT: &str = "websocket-port"; const ENABLE_STATISTICS: &str = "enable-statistics"; const STATISTICS_RECIPIENT: &str = "statistics-recipient"; -fn parse_args<'a>() -> ArgMatches<'a> { +fn parse_args() -> ArgMatches { App::new("Nym Network Requester") .version(env!("CARGO_PKG_VERSION")) .author("Nymtech") @@ -25,13 +25,13 @@ fn parse_args<'a>() -> ArgMatches<'a> { Arg::with_name(OPEN_PROXY_ARG) .help("specifies whether this network requester should run in 'open-proxy' mode") .long(OPEN_PROXY_ARG) - .short("o"), + .short('o'), ) .arg( Arg::with_name(WS_PORT) .help("websocket port to bind to") .long(WS_PORT) - .short("p") + .short('p') .takes_value(true), ) .arg( From c74ea43b94978ed235663905661eafb4b1b27af1 Mon Sep 17 00:00:00 2001 From: =?UTF-8?q?J=C4=99drzej=20Stuczy=C5=84ski?= Date: Tue, 6 Sep 2022 16:20:16 +0100 Subject: [PATCH 11/46] Removed migration artifacts from mixnet and vesting contracts (#1598) * Removed migration artifacts from mixnet and vesting contracts * Workaround for CI build * unused imports --- .../mixnet-contract/src/mixnode.rs | 2 ++ .../mixnet-contract/src/msg.rs | 1 - contracts/mixnet/src/contract.rs | 2 -- contracts/mixnet/src/queued_migrations.rs | 35 ------------------- contracts/vesting/src/contract.rs | 2 -- contracts/vesting/src/queued_migrations.rs | 15 -------- 6 files changed, 2 insertions(+), 55 deletions(-) diff --git a/common/cosmwasm-smart-contracts/mixnet-contract/src/mixnode.rs b/common/cosmwasm-smart-contracts/mixnet-contract/src/mixnode.rs index e124853074..d951ec4db2 100644 --- a/common/cosmwasm-smart-contracts/mixnet-contract/src/mixnode.rs +++ b/common/cosmwasm-smart-contracts/mixnet-contract/src/mixnode.rs @@ -166,6 +166,8 @@ pub mod fixed_U128_as_string { use super::U128; use serde::de::Error; use serde::Deserialize; + #[allow(unused_imports)] + use std::str::FromStr; pub fn serialize(val: &U128, serializer: S) -> Result where diff --git a/common/cosmwasm-smart-contracts/mixnet-contract/src/msg.rs b/common/cosmwasm-smart-contracts/mixnet-contract/src/msg.rs index 8d9703e684..bf1d0d5916 100644 --- a/common/cosmwasm-smart-contracts/mixnet-contract/src/msg.rs +++ b/common/cosmwasm-smart-contracts/mixnet-contract/src/msg.rs @@ -216,7 +216,6 @@ pub enum QueryMsg { #[derive(Serialize, Deserialize, Clone, Debug, PartialEq, Eq, JsonSchema)] #[serde(rename_all = "snake_case")] pub struct MigrateMsg { - pub mixnet_denom: String, pub nodes_to_remove: Option>, } diff --git a/contracts/mixnet/src/contract.rs b/contracts/mixnet/src/contract.rs index 3eaa1f6035..2f039a2695 100644 --- a/contracts/mixnet/src/contract.rs +++ b/contracts/mixnet/src/contract.rs @@ -28,7 +28,6 @@ use crate::mixnodes::bonding_queries::{ }; use crate::mixnodes::layer_queries::query_layer_distribution; use crate::mixnodes::transactions::_try_remove_mixnode; -use crate::queued_migrations::migrate_config_from_env; use crate::rewards::queries::{ query_circulating_supply, query_reward_pool, query_rewarding_status, query_staking_supply, }; @@ -509,7 +508,6 @@ fn remove_malicious_node( #[entry_point] pub fn migrate(deps: DepsMut<'_>, env: Env, msg: MigrateMsg) -> Result { - migrate_config_from_env(deps.storage, &msg)?; let mut response = Response::new(); for node in msg.nodes_to_remove().iter() { let mut sub_response = remove_malicious_node(deps.storage, deps.api, &env, node) diff --git a/contracts/mixnet/src/queued_migrations.rs b/contracts/mixnet/src/queued_migrations.rs index 56e4a9f890..87d5c392c8 100644 --- a/contracts/mixnet/src/queued_migrations.rs +++ b/contracts/mixnet/src/queued_migrations.rs @@ -1,37 +1,2 @@ // Copyright 2022 - Nym Technologies SA // SPDX-License-Identifier: Apache-2.0 - -use cosmwasm_std::{Addr, Response, Storage}; -use cw_storage_plus::Item; -use mixnet_contract_common::{ContractStateParams, MigrateMsg}; -use schemars::JsonSchema; -use serde::{Deserialize, Serialize}; - -use crate::error::ContractError; -use crate::mixnet_contract_settings::models::ContractState; -use crate::mixnet_contract_settings::storage::CONTRACT_STATE; - -pub fn migrate_config_from_env( - storage: &mut dyn Storage, - msg: &MigrateMsg, -) -> Result { - #[derive(Serialize, Deserialize, Clone, Debug, PartialEq, Eq, JsonSchema)] - pub struct OldContractState { - pub owner: Addr, - pub rewarding_validator_address: Addr, - pub params: ContractStateParams, - } - const OLD_CONTRACT_STATE: Item<'_, OldContractState> = Item::new("config"); - - let old_state = OLD_CONTRACT_STATE.load(storage)?; - let new_state = ContractState { - owner: old_state.owner, - mix_denom: msg.mixnet_denom.clone(), - rewarding_validator_address: old_state.rewarding_validator_address, - params: old_state.params, - }; - - CONTRACT_STATE.save(storage, &new_state)?; - - Ok(Default::default()) -} diff --git a/contracts/vesting/src/contract.rs b/contracts/vesting/src/contract.rs index d478c686ae..32104c66fb 100644 --- a/contracts/vesting/src/contract.rs +++ b/contracts/vesting/src/contract.rs @@ -1,5 +1,4 @@ use crate::errors::ContractError; -use crate::queued_migrations::migrate_config_from_env; use crate::storage::{ account_from_address, locked_pledge_cap, remove_delegation, save_delegation, update_locked_pledge_cap, BlockTimestampSecs, ADMIN, DELEGATIONS, MIXNET_CONTRACT_ADDRESS, @@ -47,7 +46,6 @@ pub fn instantiate( #[entry_point] pub fn migrate(_deps: DepsMut<'_>, _env: Env, _msg: MigrateMsg) -> Result { - migrate_config_from_env(_deps, _env, _msg)?; Ok(Response::default()) } diff --git a/contracts/vesting/src/queued_migrations.rs b/contracts/vesting/src/queued_migrations.rs index 75d63ba648..87d5c392c8 100644 --- a/contracts/vesting/src/queued_migrations.rs +++ b/contracts/vesting/src/queued_migrations.rs @@ -1,17 +1,2 @@ // Copyright 2022 - Nym Technologies SA // SPDX-License-Identifier: Apache-2.0 - -use cosmwasm_std::{DepsMut, Env, Response}; -use vesting_contract_common::MigrateMsg; - -use crate::{errors::ContractError, storage::MIX_DENOM}; - -pub fn migrate_config_from_env( - deps: DepsMut<'_>, - _env: Env, - msg: MigrateMsg, -) -> Result { - MIX_DENOM.save(deps.storage, &msg.mix_denom)?; - - Ok(Default::default()) -} From 6d3e5f22d49ca8aee24d5b14bd1f4244f9b4532d Mon Sep 17 00:00:00 2001 From: =?UTF-8?q?J=C4=99drzej=20Stuczy=C5=84ski?= Date: Tue, 6 Sep 2022 16:45:32 +0100 Subject: [PATCH 12/46] Removed mix_denom from vesting MigrateMsg --- .../cosmwasm-smart-contracts/vesting-contract/src/messages.rs | 4 +--- 1 file changed, 1 insertion(+), 3 deletions(-) diff --git a/common/cosmwasm-smart-contracts/vesting-contract/src/messages.rs b/common/cosmwasm-smart-contracts/vesting-contract/src/messages.rs index 868df6ac70..ceeaef6a0e 100644 --- a/common/cosmwasm-smart-contracts/vesting-contract/src/messages.rs +++ b/common/cosmwasm-smart-contracts/vesting-contract/src/messages.rs @@ -12,9 +12,7 @@ pub struct InitMsg { #[derive(Serialize, Deserialize, Clone, Debug, PartialEq, Eq, JsonSchema)] #[serde(rename_all = "snake_case")] -pub struct MigrateMsg { - pub mix_denom: String, -} +pub struct MigrateMsg {} #[derive(Serialize, Deserialize, Clone, Debug, PartialEq, Eq, JsonSchema, Default)] pub struct VestingSpecification { From 2363f3ad0a1d9e1f70942c2f8f470848f8828765 Mon Sep 17 00:00:00 2001 From: Drazen Urch Date: Wed, 7 Sep 2022 01:41:51 +0200 Subject: [PATCH 13/46] Initial docs pass (#1582) --- contracts/vesting/Cargo.toml | 2 +- contracts/vesting/src/contract.rs | 47 +++++++++++++++++-- contracts/vesting/src/lib.rs | 3 ++ .../vesting/src/traits/vesting_account.rs | 32 ++++++++++--- .../src/vesting/account/vesting_account.rs | 3 +- 5 files changed, 74 insertions(+), 13 deletions(-) diff --git a/contracts/vesting/Cargo.toml b/contracts/vesting/Cargo.toml index 3f29aa7e94..d7e9ea49d9 100644 --- a/contracts/vesting/Cargo.toml +++ b/contracts/vesting/Cargo.toml @@ -22,4 +22,4 @@ cw-storage-plus = { version = "0.13.4", features = ["iterator"] } schemars = "0.8" serde = { version = "1.0", default-features = false, features = ["derive"] } -thiserror = { version = "1.0" } +thiserror = { version = "1.0" } \ No newline at end of file diff --git a/contracts/vesting/src/contract.rs b/contracts/vesting/src/contract.rs index 32104c66fb..1270461520 100644 --- a/contracts/vesting/src/contract.rs +++ b/contracts/vesting/src/contract.rs @@ -30,6 +30,7 @@ use vesting_contract_common::{ pub const INITIAL_LOCKED_PLEDGE_CAP: Uint128 = Uint128::new(100_000_000_000); +/// Instantiate the contract #[entry_point] pub fn instantiate( deps: DepsMut<'_>, @@ -37,7 +38,7 @@ pub fn instantiate( info: MessageInfo, msg: InitMsg, ) -> Result { - // ADMIN is set to the address that instantiated the contract, TODO: make this updatable + //! ADMIN is set to the address that instantiated the contract ADMIN.save(deps.storage, &info.sender.to_string())?; MIXNET_CONTRACT_ADDRESS.save(deps.storage, &msg.mixnet_contract_address)?; MIX_DENOM.save(deps.storage, &msg.mix_denom)?; @@ -142,6 +143,9 @@ pub fn execute( } } +/// Update locked_pledge_cap, the hard cap for staking/bonding with unvested tokens. +/// +/// Callable by ADMIN only, see [instantiate]. pub fn try_update_locked_pledge_cap( amount: Uint128, info: MessageInfo, @@ -154,6 +158,7 @@ pub fn try_update_locked_pledge_cap( Ok(Response::default()) } +/// Update config for a mixnode bonded with vesting account, sends [mixnet_contract_common::ExecuteMsg::UpdateMixnodeConfig] to [crate::storage::MIXNET_CONTRACT_ADDRESS]. pub fn try_update_mixnode_config( profit_margin_percent: u8, info: MessageInfo, @@ -163,7 +168,9 @@ pub fn try_update_mixnode_config( account.try_update_mixnode_config(profit_margin_percent, deps.storage) } -// Only contract admin, set at init +/// Updates mixnet contract address, for cases when a new mixnet contract is deployed. +/// +/// Callable by ADMIN only, see [instantiate]. pub fn try_update_mixnet_address( address: String, info: MessageInfo, @@ -176,7 +183,7 @@ pub fn try_update_mixnet_address( Ok(Response::default()) } -// Only contract owner of vesting account +/// Withdraw already vested coins. pub fn try_withdraw_vested_coins( amount: Coin, env: Env, @@ -217,6 +224,7 @@ pub fn try_withdraw_vested_coins( } } +/// Transfer ownership of the entire vesting account. fn try_transfer_ownership( to_address: String, info: MessageInfo, @@ -233,6 +241,7 @@ fn try_transfer_ownership( } } +/// Set or update staking address for a vesting account. fn try_update_staking_address( to_address: Option, info: MessageInfo, @@ -274,7 +283,7 @@ pub fn try_migrate_heights_to_timestamps( Ok(Response::default()) } -// Owner or staking +/// Bond a gateway, sends [mixnet_contract_common::ExecuteMsg::BondGatewayOnBehalf] to [crate::storage::MIXNET_CONTRACT_ADDRESS]. pub fn try_bond_gateway( gateway: Gateway, owner_signature: String, @@ -289,11 +298,13 @@ pub fn try_bond_gateway( account.try_bond_gateway(gateway, owner_signature, pledge, &env, deps.storage) } +/// Unbond a gateway, sends [mixnet_contract_common::ExecuteMsg::UnbondGatewayOnBehalf] to [crate::storage::MIXNET_CONTRACT_ADDRESS]. pub fn try_unbond_gateway(info: MessageInfo, deps: DepsMut<'_>) -> Result { let account = account_from_address(info.sender.as_str(), deps.storage, deps.api)?; account.try_unbond_gateway(deps.storage) } +/// Track gateway unbonding, invoked by the mixnet contract after succesful unbonding, message containes coins returned including any accrued rewards. pub fn try_track_unbond_gateway( owner: &str, amount: Coin, @@ -308,6 +319,7 @@ pub fn try_track_unbond_gateway( Ok(Response::new().add_event(new_track_gateway_unbond_event())) } +/// Compound operator reward, sends [mixnet_contract_common::ExecuteMsg::CompoundOperatorRewardOnBehalf] to [crate::storage::MIXNET_CONTRACT_ADDRESS], adds available rewards to the existing bond pub fn try_compound_operator_reward( info: MessageInfo, deps: DepsMut<'_>, @@ -316,6 +328,7 @@ pub fn try_compound_operator_reward( account.try_compound_operator_reward(deps.storage) } +/// Bond a mixnode, sends [mixnet_contract_common::ExecuteMsg::BondMixnodeOnBehalf] to [crate::storage::MIXNET_CONTRACT_ADDRESS]. pub fn try_bond_mixnode( mix_node: MixNode, owner_signature: String, @@ -330,11 +343,13 @@ pub fn try_bond_mixnode( account.try_bond_mixnode(mix_node, owner_signature, pledge, &env, deps.storage) } +/// Unbond a mixnode, sends [mixnet_contract_common::ExecuteMsg::UnbondMixnodeOnBehalf] to [crate::storage::MIXNET_CONTRACT_ADDRESS]. pub fn try_unbond_mixnode(info: MessageInfo, deps: DepsMut<'_>) -> Result { let account = account_from_address(info.sender.as_str(), deps.storage, deps.api)?; account.try_unbond_mixnode(deps.storage) } +/// Track mixnode unbonding, invoked by the mixnet contract after succesful unbonding, message containes coins returned including any accrued rewards. pub fn try_track_unbond_mixnode( owner: &str, amount: Coin, @@ -349,6 +364,7 @@ pub fn try_track_unbond_mixnode( Ok(Response::new().add_event(new_track_mixnode_unbond_event())) } +/// Track reward collection, invoked by the mixnert contract after sucessful reward compounding or claiming fn try_track_reward( deps: DepsMut<'_>, info: MessageInfo, @@ -363,6 +379,7 @@ fn try_track_reward( Ok(Response::new().add_event(new_track_reward_event())) } +/// Track undelegation, invoked by the mixnet contract after sucessful undelegation, message contains coins returned with any accrued rewards. fn try_track_undelegation( address: &str, mix_identity: IdentityKey, @@ -378,6 +395,7 @@ fn try_track_undelegation( Ok(Response::new().add_event(new_track_undelegation_event())) } +/// Delegate to mixnode, sends [mixnet_contract_common::ExecuteMsg::DelegateToMixnodeOnBehalf] to [crate::storage::MIXNET_CONTRACT_ADDRESS].. fn try_delegate_to_mixnode( mix_identity: IdentityKey, amount: Coin, @@ -391,6 +409,7 @@ fn try_delegate_to_mixnode( account.try_delegate_to_mixnode(mix_identity, amount, &env, deps.storage) } +/// Compounds deleagtor reward, ie adds it to the existing delegations for a node, sends [mixnet_contract_common::ExecuteMsg::CompoundDelegatorRewardOnBehalf] to [crate::storage::MIXNET_CONTRACT_ADDRESS]. fn try_compound_delegator_reward( mix_identity: IdentityKey, info: MessageInfo, @@ -400,6 +419,7 @@ fn try_compound_delegator_reward( account.try_compound_delegator_reward(mix_identity, deps.storage) } +/// Claims operator reward, sends [mixnet_contract_common::ExecuteMsg::ClaimOperatorRewardOnBehalf] to [crate::storage::MIXNET_CONTRACT_ADDRESS]. fn try_claim_operator_reward( deps: DepsMut<'_>, info: MessageInfo, @@ -408,6 +428,7 @@ fn try_claim_operator_reward( account.try_claim_operator_reward(deps.storage) } +/// Claims delegator reward, sends [mixnet_contract_common::ExecuteMsg::ClaimDelegatorRewardOnBehalf] to [crate::storage::MIXNET_CONTRACT_ADDRESS]. fn try_claim_delegator_reward( deps: DepsMut<'_>, info: MessageInfo, @@ -417,6 +438,7 @@ fn try_claim_delegator_reward( account.try_claim_delegator_reward(mix_identity, deps.storage) } +/// Undelegates from a mixnode, sends [mixnet_contract_common::ExecuteMsg::UndelegateFromMixnodeOnBehalf] to [crate::storage::MIXNET_CONTRACT_ADDRESS]. fn try_undelegate_from_mixnode( mix_identity: IdentityKey, info: MessageInfo, @@ -426,6 +448,9 @@ fn try_undelegate_from_mixnode( account.try_undelegate_from_mixnode(mix_identity, deps.storage) } +/// Creates a new periodic vesting account, and deposits funds to vest into the contract. +/// +/// Callable by ADMIN only, see [instantiate]. fn try_create_periodic_vesting_account( owner_address: &str, staking_address: Option, @@ -568,10 +593,12 @@ pub fn query(deps: Deps<'_>, env: Env, msg: QueryMsg) -> Result) -> Uint128 { locked_pledge_cap(deps.storage) } +/// Get current vesting period for a given [crate::vesting::Account]. pub fn try_get_current_vesting_period( address: &str, deps: Deps<'_>, @@ -581,11 +608,13 @@ pub fn try_get_current_vesting_period( Ok(account.get_current_vesting_period(env.block.time)) } +/// Loads mixnode bond from vesting contract storage. pub fn try_get_mixnode(address: &str, deps: Deps<'_>) -> Result, ContractError> { let account = account_from_address(address, deps.storage, deps.api)?; account.load_mixnode_pledge(deps.storage) } +/// Loads gateway bond from vesting contract storage. pub fn try_get_gateway(address: &str, deps: Deps<'_>) -> Result, ContractError> { let account = account_from_address(address, deps.storage, deps.api)?; account.load_gateway_pledge(deps.storage) @@ -595,6 +624,7 @@ pub fn try_get_account(address: &str, deps: Deps<'_>) -> Result, @@ -605,6 +635,7 @@ pub fn try_get_locked_coins( account.locked_coins(block_time, &env, deps.storage) } +/// Returns currently locked coins, see [crate::traits::VestingAccount::spendable_coins] pub fn try_get_spendable_coins( vesting_account_address: &str, block_time: Option, @@ -615,6 +646,7 @@ pub fn try_get_spendable_coins( account.spendable_coins(block_time, &env, deps.storage) } +/// Returns coins that have vested, see [crate::traits::VestingAccount::get_vested_coins] pub fn try_get_vested_coins( vesting_account_address: &str, block_time: Option, @@ -625,6 +657,7 @@ pub fn try_get_vested_coins( account.get_vested_coins(block_time, &env, deps.storage) } +/// Returns coins that are vesting, see [crate::traits::VestingAccount::get_vesting_coins] pub fn try_get_vesting_coins( vesting_account_address: &str, block_time: Option, @@ -635,6 +668,7 @@ pub fn try_get_vesting_coins( account.get_vesting_coins(block_time, &env, deps.storage) } +/// See [crate::traits::VestingAccount::get_start_time] pub fn try_get_start_time( vesting_account_address: &str, deps: Deps<'_>, @@ -643,6 +677,7 @@ pub fn try_get_start_time( Ok(account.get_start_time()) } +/// See [crate::traits::VestingAccount::get_end_time] pub fn try_get_end_time( vesting_account_address: &str, deps: Deps<'_>, @@ -651,6 +686,7 @@ pub fn try_get_end_time( Ok(account.get_end_time()) } +/// See [crate::traits::VestingAccount::get_original_vesting] pub fn try_get_original_vesting( vesting_account_address: &str, deps: Deps<'_>, @@ -659,6 +695,7 @@ pub fn try_get_original_vesting( Ok(account.get_original_vesting()) } +/// See [crate::traits::VestingAccount::get_delegated_free] pub fn try_get_delegated_free( block_time: Option, vesting_account_address: &str, @@ -669,6 +706,7 @@ pub fn try_get_delegated_free( account.get_delegated_free(block_time, &env, deps.storage) } +/// See [crate::traits::VestingAccount::get_delegated_vesting] pub fn try_get_delegated_vesting( block_time: Option, vesting_account_address: &str, @@ -679,6 +717,7 @@ pub fn try_get_delegated_vesting( account.get_delegated_vesting(block_time, &env, deps.storage) } +/// Returns timestamps at which delegations were made pub fn try_get_delegation_times( deps: Deps<'_>, vesting_account_address: &str, diff --git a/contracts/vesting/src/lib.rs b/contracts/vesting/src/lib.rs index 4e44a69be8..8da47f12a6 100644 --- a/contracts/vesting/src/lib.rs +++ b/contracts/vesting/src/lib.rs @@ -1,3 +1,6 @@ +#![allow(rustdoc::private_intra_doc_links)] +//! Nym vesting contract, providing vesting accounts with ability to stake unvested tokens + pub mod contract; mod errors; mod queued_migrations; diff --git a/contracts/vesting/src/traits/vesting_account.rs b/contracts/vesting/src/traits/vesting_account.rs index 95f445114e..04173a56c6 100644 --- a/contracts/vesting/src/traits/vesting_account.rs +++ b/contracts/vesting/src/traits/vesting_account.rs @@ -9,12 +9,13 @@ pub trait VestingAccount { env: &Env, ) -> Result; - // locked_coins returns the set of coins that are not spendable (can still be delegated tough) (i.e. locked), - // defined as the vesting coins that are not delegated or pledged. - // - // To get spendable coins of a vesting account, first the total balance must - // be retrieved and the locked tokens can be subtracted from the total balance. - // Note, the spendable balance can be negative. + /// Returns the set of coins that are not spendable (can still be delegated tough) (i.e. locked), + /// defined as the vesting coins that are not delegated or pledged. + /// + /// To get spendable coins of a vesting account, first the total balance must + /// be retrieved and the locked tokens can be subtracted from the total balance. + /// Note, the spendable balance can be negative. + /// See [/vesting-contract/struct.Account.html/method.locked_coins] for impl fn locked_coins( &self, block_time: Option, @@ -22,7 +23,8 @@ pub trait VestingAccount { storage: &dyn Storage, ) -> Result; - // Calculates the total spendable balance that can be sent to other accounts. + /// Calculated as current_balance minus [crate::traits::VestingAccount::locked_coins] + /// See [/vesting-contract/struct.Account.html/method.spendable_coins] for impl fn spendable_coins( &self, block_time: Option, @@ -30,12 +32,15 @@ pub trait VestingAccount { storage: &dyn Storage, ) -> Result; + /// See [/vesting-contract/struct.Account.html/method.get_vested_coins] for impl fn get_vested_coins( &self, block_time: Option, env: &Env, storage: &dyn Storage, ) -> Result; + + /// See [/vesting-contract/struct.Account.html/method.get_vesting_coins] for impl fn get_vesting_coins( &self, block_time: Option, @@ -43,39 +48,52 @@ pub trait VestingAccount { storage: &dyn Storage, ) -> Result; + /// See [/vesting-contract/struct.Account.html/method.get_start_time] for impl fn get_start_time(&self) -> Timestamp; + /// See [/vesting-contract/struct.Account.html/method.get_end_time] for impl fn get_end_time(&self) -> Timestamp; + /// Returns amount of coins set at account creation + /// See [/vesting-contract/struct.Account.html/method.get_original_vesting] for impl fn get_original_vesting(&self) -> OriginalVestingResponse; + + /// See [/vesting-contract/struct.Account.html/method.get_delegated_free] for impl fn get_delegated_free( &self, block_time: Option, env: &Env, storage: &dyn Storage, ) -> Result; + + /// See [/vesting-contract/struct.Account.html/method.get_delegated_vesting] for impl fn get_delegated_vesting( &self, block_time: Option, env: &Env, storage: &dyn Storage, ) -> Result; + + /// See [/vesting-contract/struct.Account.html/method.get_pledged_free] for impl fn get_pledged_free( &self, block_time: Option, env: &Env, storage: &dyn Storage, ) -> Result; + /// See [/vesting-contract/struct.Account.html/method.get_pledged_vesting] for impl fn get_pledged_vesting( &self, block_time: Option, env: &Env, storage: &dyn Storage, ) -> Result; + /// See [/vesting-contract/struct.Account.html/method.transfer_ownership] for impl fn transfer_ownership( &mut self, to_address: &Addr, storage: &mut dyn Storage, ) -> Result<(), ContractError>; + /// See [/vesting-contract/struct.Account.html/method.update_staking_address] for impl fn update_staking_address( &mut self, to_address: Option, diff --git a/contracts/vesting/src/vesting/account/vesting_account.rs b/contracts/vesting/src/vesting/account/vesting_account.rs index 060ea95973..d7eeeb0946 100644 --- a/contracts/vesting/src/vesting/account/vesting_account.rs +++ b/contracts/vesting/src/vesting/account/vesting_account.rs @@ -16,13 +16,14 @@ impl VestingAccount for Account { + self.get_pledged_vesting(None, env, storage)?.amount) } + /// See [VestingAccount::locked_coins] for documentation. + /// Returns 0 in case of underflow. Which is fine, as the amount of pledged and delegated tokens can be larger then vesting_coins due to rewards and vesting periods expiring fn locked_coins( &self, block_time: Option, env: &Env, storage: &dyn Storage, ) -> Result { - // Returns 0 in case of underflow. Which is fine, as the amount of pledged and delegated tokens can be larger then vesting_coins due to rewards and vesting periods expiring Ok(Coin { amount: Uint128::new( self.get_vesting_coins(block_time, env, storage)? From f172a23ef804ca360cd66e384e99adef454638aa Mon Sep 17 00:00:00 2001 From: =?UTF-8?q?Jon=20H=C3=A4ggblad?= Date: Wed, 7 Sep 2022 15:35:26 +0200 Subject: [PATCH 14/46] clients: remove cluster of unwrap and expects for gateway handling (#1599) * clients: remove cluster of unwraps and expects for gateway handling * rustfmt --- Cargo.lock | 2 + clients/client-core/Cargo.toml | 2 + clients/client-core/src/error.rs | 27 +++++++++++ clients/client-core/src/init.rs | 60 ++++++++++++++----------- clients/client-core/src/lib.rs | 1 + clients/native/src/commands/init.rs | 50 ++++++++++++--------- clients/socks5/src/commands/init.rs | 49 +++++++++++--------- contracts/vesting/src/contract.rs | 6 +-- nym-connect/Cargo.lock | 10 +++-- nym-connect/src-tauri/src/config/mod.rs | 32 +++++++------ nym-connect/src-tauri/src/error.rs | 6 +++ 11 files changed, 154 insertions(+), 91 deletions(-) create mode 100644 clients/client-core/src/error.rs diff --git a/Cargo.lock b/Cargo.lock index 6419e1e296..3494de31af 100644 --- a/Cargo.lock +++ b/Cargo.lock @@ -667,7 +667,9 @@ dependencies = [ "rand 0.7.3", "serde", "sled", + "tap", "tempfile", + "thiserror", "tokio", "topology", "url", diff --git a/clients/client-core/Cargo.toml b/clients/client-core/Cargo.toml index c628d8bd44..ca11dfd240 100644 --- a/clients/client-core/Cargo.toml +++ b/clients/client-core/Cargo.toml @@ -14,6 +14,7 @@ log = "0.4" rand = { version = "0.7.3", features = ["wasm-bindgen"] } serde = { version = "1.0", features = ["derive"] } sled = "0.34" +thiserror = "1.0.34" tokio = { version = "1.19.1", features = ["macros"] } url = { version ="2.2", features = ["serde"] } @@ -27,6 +28,7 @@ nymsphinx = { path = "../../common/nymsphinx" } pemstore = { path = "../../common/pemstore" } topology = { path = "../../common/topology" } validator-client = { path = "../../common/client-libs/validator-client" } +tap = "1.0.1" [dev-dependencies] tempfile = "3.1.0" diff --git a/clients/client-core/src/error.rs b/clients/client-core/src/error.rs new file mode 100644 index 0000000000..12e27fdd58 --- /dev/null +++ b/clients/client-core/src/error.rs @@ -0,0 +1,27 @@ +// Copyright 2022 - Nym Technologies SA +// SPDX-License-Identifier: Apache-2.0 + +use crypto::asymmetric::identity::Ed25519RecoveryError; +use gateway_client::error::GatewayClientError; +use validator_client::ValidatorClientError; + +#[derive(thiserror::Error, Debug)] +pub enum ClientCoreError { + #[error("I/O error: {0}")] + IoError(#[from] std::io::Error), + #[error("Gateway client error: {0}")] + GatewayClientError(#[from] GatewayClientError), + #[error("Ed25519 error: {0}")] + Ed25519RecoveryError(#[from] Ed25519RecoveryError), + #[error("Validator client error: {0}")] + ValidatorClientError(#[from] ValidatorClientError), + + #[error("No gateway with id: {0}")] + NoGatewayWithId(String), + #[error("No gateways on network")] + NoGatewaysOnNetwork, + #[error("List of validator apis is empty")] + ListOfValidatorApisIsEmpty, + #[error("Could not load existing gateway configuration: {0}")] + CouldNotLoadExistingGatewayConfiguration(std::io::Error), +} diff --git a/clients/client-core/src/init.rs b/clients/client-core/src/init.rs index 16921cd3f5..66ae845b04 100644 --- a/clients/client-core/src/init.rs +++ b/clients/client-core/src/init.rs @@ -14,25 +14,27 @@ use nymsphinx::addressing::nodes::NodeIdentity; use rand::rngs::OsRng; use rand::seq::SliceRandom; use rand::thread_rng; +use tap::TapFallible; use topology::{filter::VersionFilterable, gateway}; use url::Url; use crate::{ client::key_manager::KeyManager, config::{persistence::key_pathfinder::ClientKeyPathfinder, Config}, + error::ClientCoreError, }; pub async fn query_gateway_details( validator_servers: Vec, chosen_gateway_id: Option<&str>, -) -> gateway::Node { +) -> Result { let validator_api = validator_servers .choose(&mut thread_rng()) - .expect("The list of validator apis is empty"); + .ok_or(ClientCoreError::ListOfValidatorApisIsEmpty)?; let validator_client = validator_client::ApiClient::new(validator_api.clone()); log::trace!("Fetching list of gateways from: {}", validator_api); - let gateways = validator_client.get_cached_gateways().await.unwrap(); + let gateways = validator_client.get_cached_gateways().await?; let valid_gateways = gateways .into_iter() .filter_map(|gateway| gateway.try_into().ok()) @@ -47,38 +49,40 @@ pub async fn query_gateway_details( filtered_gateways .iter() .find(|gateway| gateway.identity_key.to_base58_string() == gateway_id) - .expect(&*format!("no gateway with id {} exists!", gateway_id)) - .clone() + .ok_or_else(|| ClientCoreError::NoGatewayWithId(gateway_id.to_string())) + .cloned() } else { filtered_gateways .choose(&mut rand::thread_rng()) - .expect("there are no gateways on the network!") - .clone() + .ok_or(ClientCoreError::NoGatewaysOnNetwork) + .cloned() } } pub async fn register_with_gateway_and_store_keys( gateway_details: gateway::Node, config: &Config, -) where +) -> Result<(), ClientCoreError> +where T: NymConfig, { let mut rng = OsRng; let mut key_manager = KeyManager::new(&mut rng); - let shared_keys = register_with_gateway(&gateway_details, key_manager.identity_keypair()).await; + let shared_keys = + register_with_gateway(&gateway_details, key_manager.identity_keypair()).await?; key_manager.insert_gateway_shared_key(shared_keys); let pathfinder = ClientKeyPathfinder::new_from_config(config); - key_manager + Ok(key_manager .store_keys(&pathfinder) - .expect("Failed to generated keys"); + .tap_err(|err| log::error!("Failed to generate keys: {err}"))?) } async fn register_with_gateway( gateway: &gateway::Node, our_identity: Arc, -) -> Arc { +) -> Result, ClientCoreError> { let timeout = Duration::from_millis(1500); let mut gateway_client = GatewayClient::new_init( gateway.clients_address(), @@ -90,48 +94,54 @@ async fn register_with_gateway( gateway_client .establish_connection() .await - .expect("failed to establish connection with the gateway!"); - gateway_client + .tap_err(|_| log::warn!("Failed to establish connection with gateway!"))?; + let shared_keys = gateway_client .perform_initial_authentication() .await - .expect("failed to register with the gateway!") + .tap_err(|_| log::warn!("Failed to register with the gateway!"))?; + Ok(shared_keys) } -pub fn show_address(config: &Config) +pub fn show_address(config: &Config) -> Result<(), ClientCoreError> where T: config::NymConfig, { - fn load_identity_keys(pathfinder: &ClientKeyPathfinder) -> identity::KeyPair { + fn load_identity_keys( + pathfinder: &ClientKeyPathfinder, + ) -> Result { let identity_keypair: identity::KeyPair = pemstore::load_keypair(&pemstore::KeyPairPath::new( pathfinder.private_identity_key().to_owned(), pathfinder.public_identity_key().to_owned(), )) - .expect("Failed to read stored identity key files"); - identity_keypair + .tap_err(|_| log::error!("Failed to read stored identity key files"))?; + Ok(identity_keypair) } - fn load_sphinx_keys(pathfinder: &ClientKeyPathfinder) -> encryption::KeyPair { + fn load_sphinx_keys( + pathfinder: &ClientKeyPathfinder, + ) -> Result { let sphinx_keypair: encryption::KeyPair = pemstore::load_keypair(&pemstore::KeyPairPath::new( pathfinder.private_encryption_key().to_owned(), pathfinder.public_encryption_key().to_owned(), )) - .expect("Failed to read stored sphinx key files"); - sphinx_keypair + .tap_err(|_| log::error!("Failed to read stored sphinx key files"))?; + Ok(sphinx_keypair) } let pathfinder = ClientKeyPathfinder::new_from_config(config); - let identity_keypair = load_identity_keys(&pathfinder); - let sphinx_keypair = load_sphinx_keys(&pathfinder); + let identity_keypair = load_identity_keys(&pathfinder)?; + let sphinx_keypair = load_sphinx_keys(&pathfinder)?; let client_recipient = Recipient::new( *identity_keypair.public_key(), *sphinx_keypair.public_key(), // TODO: below only works under assumption that gateway address == gateway id // (which currently is true) - NodeIdentity::from_base58_string(config.get_gateway_id()).unwrap(), + NodeIdentity::from_base58_string(config.get_gateway_id())?, ); println!("\nThe address of this client is: {}", client_recipient); + Ok(()) } diff --git a/clients/client-core/src/lib.rs b/clients/client-core/src/lib.rs index 6bbed6b087..e36cea9276 100644 --- a/clients/client-core/src/lib.rs +++ b/clients/client-core/src/lib.rs @@ -1,3 +1,4 @@ pub mod client; pub mod config; +pub mod error; pub mod init; diff --git a/clients/native/src/commands/init.rs b/clients/native/src/commands/init.rs index 55a57a935b..8052ceeac7 100644 --- a/clients/native/src/commands/init.rs +++ b/clients/native/src/commands/init.rs @@ -2,7 +2,7 @@ // SPDX-License-Identifier: Apache-2.0 use clap::Args; -use client_core::config::GatewayEndpoint; +use client_core::{config::GatewayEndpoint, error::ClientCoreError}; use config::NymConfig; use crate::{ @@ -120,7 +120,12 @@ pub(crate) async fn execute(args: &Init) { let override_config_fields = OverrideConfig::from(args.clone()); config = override_config(config, override_config_fields); - let gateway = setup_gateway(id, register_gateway, user_chosen_gateway_id, &config).await; + let gateway = setup_gateway(id, register_gateway, user_chosen_gateway_id, &config) + .await + .unwrap_or_else(|err| { + eprintln!("Failed to setup gateway\nError: {err}"); + std::process::exit(1) + }); config.get_base_mut().with_gateway_endpoint(gateway); let config_save_location = config.get_config_file_save_location(); @@ -138,7 +143,10 @@ pub(crate) async fn execute(args: &Init) { ); println!("Client configuration completed."); - client_core::init::show_address(config.get_base()); + client_core::init::show_address(config.get_base()).unwrap_or_else(|err| { + eprintln!("Failed to show address\nError: {err}"); + std::process::exit(1) + }); } async fn setup_gateway( @@ -146,7 +154,7 @@ async fn setup_gateway( register: bool, user_chosen_gateway_id: Option<&str>, config: &Config, -) -> GatewayEndpoint { +) -> Result { if register { // Get the gateway details by querying the validator-api. Either pick one at random or use // the chosen one if it's among the available ones. @@ -155,16 +163,16 @@ async fn setup_gateway( config.get_base().get_validator_api_endpoints(), user_chosen_gateway_id, ) - .await; + .await?; log::debug!("Querying gateway gives: {}", gateway); // Registering with gateway by setting up and writing shared keys to disk log::trace!("Registering gateway"); client_core::init::register_with_gateway_and_store_keys(gateway.clone(), config.get_base()) - .await; + .await?; println!("Saved all generated keys"); - gateway.into() + Ok(gateway.into()) } else if user_chosen_gateway_id.is_some() { // Just set the config, don't register or create any keys // This assumes that the user knows what they are doing, and that the existing keys are @@ -174,22 +182,22 @@ async fn setup_gateway( config.get_base().get_validator_api_endpoints(), user_chosen_gateway_id, ) - .await; + .await?; log::debug!("Querying gateway gives: {}", gateway); - gateway.into() + Ok(gateway.into()) } else { println!("Not registering gateway, will reuse existing config and keys"); - match Config::load_from_file(Some(id)) { - Ok(existing_config) => existing_config.get_base().get_gateway_endpoint().clone(), - Err(err) => { - panic!( - "Unable to configure gateway: {err}. \n - Seems like the client was already initialized but it was not possible to read \ - the existing configuration file. \n - CAUTION: Consider backing up your gateway keys and try force gateway registration, or \ - removing the existing configuration and starting over." - ) - } - } + let existing_config = Config::load_from_file(Some(id)).map_err(|err| { + log::error!( + "Unable to configure gateway: {err}. \n + Seems like the client was already initialized but it was not possible to read \ + the existing configuration file. \n + CAUTION: Consider backing up your gateway keys and try force gateway registration, or \ + removing the existing configuration and starting over." + ); + ClientCoreError::CouldNotLoadExistingGatewayConfiguration(err) + })?; + + Ok(existing_config.get_base().get_gateway_endpoint().clone()) } } diff --git a/clients/socks5/src/commands/init.rs b/clients/socks5/src/commands/init.rs index 7d4f731d0d..bb2135fa9f 100644 --- a/clients/socks5/src/commands/init.rs +++ b/clients/socks5/src/commands/init.rs @@ -2,7 +2,7 @@ // SPDX-License-Identifier: Apache-2.0 use clap::Args; -use client_core::config::GatewayEndpoint; +use client_core::{config::GatewayEndpoint, error::ClientCoreError}; use config::NymConfig; use crate::{ @@ -120,7 +120,12 @@ pub(crate) async fn execute(args: &Init) { let override_config_fields = OverrideConfig::from(args.clone()); config = override_config(config, override_config_fields); - let gateway = setup_gateway(id, register_gateway, user_chosen_gateway_id, &config).await; + let gateway = setup_gateway(id, register_gateway, user_chosen_gateway_id, &config) + .await + .unwrap_or_else(|err| { + eprintln!("Failed to setup gateway\nError: {err}"); + std::process::exit(1) + }); config.get_base_mut().with_gateway_endpoint(gateway); let config_save_location = config.get_config_file_save_location(); @@ -138,7 +143,10 @@ pub(crate) async fn execute(args: &Init) { ); println!("Client configuration completed."); - client_core::init::show_address(config.get_base()); + client_core::init::show_address(config.get_base()).unwrap_or_else(|err| { + eprintln!("Failed to show address\nError: {err}"); + std::process::exit(1) + }); } async fn setup_gateway( @@ -146,7 +154,7 @@ async fn setup_gateway( register: bool, user_chosen_gateway_id: Option<&str>, config: &Config, -) -> GatewayEndpoint { +) -> Result { if register { // Get the gateway details by querying the validator-api. Either pick one at random or use // the chosen one if it's among the available ones. @@ -155,16 +163,16 @@ async fn setup_gateway( config.get_base().get_validator_api_endpoints(), user_chosen_gateway_id, ) - .await; + .await?; log::debug!("Querying gateway gives: {}", gateway); // Registering with gateway by setting up and writing shared keys to disk log::trace!("Registering gateway"); client_core::init::register_with_gateway_and_store_keys(gateway.clone(), config.get_base()) - .await; + .await?; println!("Saved all generated keys"); - gateway.into() + Ok(gateway.into()) } else if user_chosen_gateway_id.is_some() { // Just set the config, don't register or create any keys // This assumes that the user knows what they are doing, and that the existing keys are @@ -174,22 +182,21 @@ async fn setup_gateway( config.get_base().get_validator_api_endpoints(), user_chosen_gateway_id, ) - .await; + .await?; log::debug!("Querying gateway gives: {}", gateway); - gateway.into() + Ok(gateway.into()) } else { println!("Not registering gateway, will reuse existing config and keys"); - match Config::load_from_file(Some(id)) { - Ok(existing_config) => existing_config.get_base().get_gateway_endpoint().clone(), - Err(err) => { - panic!( - "Unable to configure gateway: {err}. \n - Seems like the client was already initialized but it was not possible to read \ - the existing configuration file. \n - CAUTION: Consider backing up your gateway keys and try force gateway registration, or \ - removing the existing configuration and starting over." - ) - } - } + let existing_config = Config::load_from_file(Some(id)).map_err(|err| { + log::error!( + "Unable to configure gateway: {err}. \n + Seems like the client was already initialized but it was not possible to read \ + the existing configuration file. \n + CAUTION: Consider backing up your gateway keys and try force gateway registration, or \ + removing the existing configuration and starting over." + ); + ClientCoreError::CouldNotLoadExistingGatewayConfiguration(err) + })?; + Ok(existing_config.get_base().get_gateway_endpoint().clone()) } } diff --git a/contracts/vesting/src/contract.rs b/contracts/vesting/src/contract.rs index 1270461520..30857c6fd8 100644 --- a/contracts/vesting/src/contract.rs +++ b/contracts/vesting/src/contract.rs @@ -144,7 +144,7 @@ pub fn execute( } /// Update locked_pledge_cap, the hard cap for staking/bonding with unvested tokens. -/// +/// /// Callable by ADMIN only, see [instantiate]. pub fn try_update_locked_pledge_cap( amount: Uint128, @@ -169,7 +169,7 @@ pub fn try_update_mixnode_config( } /// Updates mixnet contract address, for cases when a new mixnet contract is deployed. -/// +/// /// Callable by ADMIN only, see [instantiate]. pub fn try_update_mixnet_address( address: String, @@ -449,7 +449,7 @@ fn try_undelegate_from_mixnode( } /// Creates a new periodic vesting account, and deposits funds to vest into the contract. -/// +/// /// Callable by ADMIN only, see [instantiate]. fn try_create_periodic_vesting_account( owner_address: &str, diff --git a/nym-connect/Cargo.lock b/nym-connect/Cargo.lock index d6bf186f83..008d909765 100644 --- a/nym-connect/Cargo.lock +++ b/nym-connect/Cargo.lock @@ -629,6 +629,8 @@ dependencies = [ "rand 0.7.3", "serde", "sled", + "tap", + "thiserror", "tokio", "topology", "url", @@ -5944,18 +5946,18 @@ checksum = "8eaa81235c7058867fa8c0e7314f33dcce9c215f535d1913822a2b3f5e289f3c" [[package]] name = "thiserror" -version = "1.0.31" +version = "1.0.34" source = "registry+https://github.com/rust-lang/crates.io-index" -checksum = "bd829fe32373d27f76265620b5309d0340cb8550f523c1dda251d6298069069a" +checksum = "8c1b05ca9d106ba7d2e31a9dab4a64e7be2cce415321966ea3132c49a656e252" dependencies = [ "thiserror-impl", ] [[package]] name = "thiserror-impl" -version = "1.0.31" +version = "1.0.34" source = "registry+https://github.com/rust-lang/crates.io-index" -checksum = "0396bc89e626244658bef819e22d0cc459e795a5ebe878e6ec336d1674a8d79a" +checksum = "e8f2591983642de85c921015f3f070c665a197ed69e417af436115e3a1407487" dependencies = [ "proc-macro2", "quote", diff --git a/nym-connect/src-tauri/src/config/mod.rs b/nym-connect/src-tauri/src/config/mod.rs index 92556c29e0..ee4cb690fb 100644 --- a/nym-connect/src-tauri/src/config/mod.rs +++ b/nym-connect/src-tauri/src/config/mod.rs @@ -172,7 +172,7 @@ pub async fn init_socks5_config(provider_address: String, chosen_gateway_id: Str ); log::info!("Client configuration completed."); - client_core::init::show_address(config.get_base()); + client_core::init::show_address(config.get_base())?; Ok(()) } @@ -191,13 +191,13 @@ async fn setup_gateway( config.get_base().get_validator_api_endpoints(), user_chosen_gateway_id, ) - .await; + .await?; log::debug!("Querying gateway gives: {}", gateway); // Registering with gateway by setting up and writing shared keys to disk log::trace!("Registering gateway"); client_core::init::register_with_gateway_and_store_keys(gateway.clone(), config.get_base()) - .await; + .await?; println!("Saved all generated keys"); Ok(gateway.into()) @@ -210,23 +210,21 @@ async fn setup_gateway( config.get_base().get_validator_api_endpoints(), user_chosen_gateway_id, ) - .await; + .await?; log::debug!("Querying gateway gives: {}", gateway); Ok(gateway.into()) } else { println!("Not registering gateway, will reuse existing config and keys"); - match Socks5Config::load_from_file(Some(id)) { - Ok(existing_config) => Ok(existing_config.get_base().get_gateway_endpoint().clone()), - Err(err) => { - log::error!( - "Unable to configure gateway: {err}. \n - Seems like the client was already initialized but it was not possible to read \ - the existing configuration file. \n - CAUTION: Consider backing up your gateway keys and try force gateway registration, or \ - removing the existing configuration and starting over." - ); - Err(BackendError::CouldNotLoadExistingGatewayConfiguration(err)) - } - } + let existing_config = Socks5Config::load_from_file(Some(id)).map_err(|err| { + log::error!( + "Unable to configure gateway: {err}. \n + Seems like the client was already initialized but it was not possible to read \ + the existing configuration file. \n + CAUTION: Consider backing up your gateway keys and try force gateway registration, or \ + removing the existing configuration and starting over." + ); + BackendError::CouldNotLoadExistingGatewayConfiguration(err) + })?; + Ok(existing_config.get_base().get_gateway_endpoint().clone()) } } diff --git a/nym-connect/src-tauri/src/error.rs b/nym-connect/src-tauri/src/error.rs index 27a10d58e3..9ffaba93a6 100644 --- a/nym-connect/src-tauri/src/error.rs +++ b/nym-connect/src-tauri/src/error.rs @@ -1,3 +1,4 @@ +use client_core::error::ClientCoreError; use serde::{Serialize, Serializer}; use thiserror::Error; @@ -29,6 +30,11 @@ pub enum BackendError { #[from] source: serde_json::Error, }, + #[error("{source}")] + ClientCoreError { + #[from] + source: ClientCoreError, + }, #[error("State error")] StateError, From 4d5565d8b649f563420416f664dd5f2336500d72 Mon Sep 17 00:00:00 2001 From: =?UTF-8?q?Bogdan-=C8=98tefan=20Neac=C5=9Fu?= Date: Thu, 8 Sep 2022 18:41:56 +0300 Subject: [PATCH 15/46] Remove migration code (#1604) * Remove migration code * Leave blacklist functionality, just in case --- .../vesting-contract/src/messages.rs | 5 - contracts/mixnet/src/contract.rs | 15 +-- contracts/vesting/src/contract.rs | 40 +------- contracts/vesting/src/vesting/mod.rs | 93 ------------------- 4 files changed, 6 insertions(+), 147 deletions(-) diff --git a/common/cosmwasm-smart-contracts/vesting-contract/src/messages.rs b/common/cosmwasm-smart-contracts/vesting-contract/src/messages.rs index ceeaef6a0e..660c4a5dc8 100644 --- a/common/cosmwasm-smart-contracts/vesting-contract/src/messages.rs +++ b/common/cosmwasm-smart-contracts/vesting-contract/src/messages.rs @@ -117,11 +117,6 @@ pub enum ExecuteMsg { UpdateLockedPledgeCap { amount: Uint128, }, - MigrateHeightsToTimestamps { - account_id: u32, - mix_identity: String, - height_timestamp_map: Vec<(u64, u64)>, - }, } #[derive(Serialize, Deserialize, Clone, Debug, PartialEq, Eq, JsonSchema)] diff --git a/contracts/mixnet/src/contract.rs b/contracts/mixnet/src/contract.rs index 2f039a2695..bf99614939 100644 --- a/contracts/mixnet/src/contract.rs +++ b/contracts/mixnet/src/contract.rs @@ -471,6 +471,7 @@ pub fn query(deps: Deps<'_>, env: Env, msg: QueryMsg) -> Result Result<(), ContractError> { let mixnode_bond = match crate::mixnodes::storage::mixnodes() .idx @@ -491,6 +492,7 @@ fn blacklist_malicious_node(storage: &mut dyn Storage, owner: &Addr) -> Result<( } // Removes nodes we've deemed malicious, returns the pledge to the owners, but does not send any rewards +#[allow(unused)] fn remove_malicious_node( storage: &mut dyn Storage, api: &dyn Api, @@ -507,17 +509,8 @@ fn remove_malicious_node( } #[entry_point] -pub fn migrate(deps: DepsMut<'_>, env: Env, msg: MigrateMsg) -> Result { - let mut response = Response::new(); - for node in msg.nodes_to_remove().iter() { - let mut sub_response = remove_malicious_node(deps.storage, deps.api, &env, node) - .unwrap_or_else(|_| panic!("Could not remove node: {:?}", node)); - response.messages.append(&mut sub_response.messages); - response.attributes.append(&mut sub_response.attributes); - response.events.append(&mut sub_response.events); - } - - Ok(response) +pub fn migrate(_deps: DepsMut<'_>, _env: Env, _msg: MigrateMsg) -> Result { + Ok(Response::default()) } #[cfg(test)] diff --git a/contracts/vesting/src/contract.rs b/contracts/vesting/src/contract.rs index 30857c6fd8..236ff12b65 100644 --- a/contracts/vesting/src/contract.rs +++ b/contracts/vesting/src/contract.rs @@ -1,8 +1,7 @@ use crate::errors::ContractError; use crate::storage::{ - account_from_address, locked_pledge_cap, remove_delegation, save_delegation, - update_locked_pledge_cap, BlockTimestampSecs, ADMIN, DELEGATIONS, MIXNET_CONTRACT_ADDRESS, - MIX_DENOM, + account_from_address, locked_pledge_cap, update_locked_pledge_cap, BlockTimestampSecs, ADMIN, + DELEGATIONS, MIXNET_CONTRACT_ADDRESS, MIX_DENOM, }; use crate::traits::{ DelegatingAccount, GatewayBondingAccount, MixnodeBondingAccount, VestingAccount, @@ -129,17 +128,6 @@ pub fn execute( ExecuteMsg::UpdateStakingAddress { to_address } => { try_update_staking_address(to_address, info, deps) } - ExecuteMsg::MigrateHeightsToTimestamps { - account_id, - mix_identity, - height_timestamp_map, - } => try_migrate_heights_to_timestamps( - account_id, - mix_identity, - height_timestamp_map, - info, - deps, - ), } } @@ -259,30 +247,6 @@ fn try_update_staking_address( } } -pub fn try_migrate_heights_to_timestamps( - account_id: u32, - mix_identity: String, - height_timestamp_map: Vec<(u64, u64)>, - info: MessageInfo, - deps: DepsMut<'_>, -) -> Result { - if info.sender != ADMIN.load(deps.storage)? { - return Err(ContractError::NotAdmin(info.sender.as_str().to_string())); - } - - for (height, timestamp) in height_timestamp_map { - let amount = DELEGATIONS.load(deps.storage, (account_id, mix_identity.clone(), height))?; - remove_delegation((account_id, mix_identity.clone(), height), deps.storage)?; - save_delegation( - (account_id, mix_identity.clone(), timestamp), - amount, - deps.storage, - )?; - } - - Ok(Response::default()) -} - /// Bond a gateway, sends [mixnet_contract_common::ExecuteMsg::BondGatewayOnBehalf] to [crate::storage::MIXNET_CONTRACT_ADDRESS]. pub fn try_bond_gateway( gateway: Gateway, diff --git a/contracts/vesting/src/vesting/mod.rs b/contracts/vesting/src/vesting/mod.rs index 5289f978db..45d8b9bfa2 100644 --- a/contracts/vesting/src/vesting/mod.rs +++ b/contracts/vesting/src/vesting/mod.rs @@ -925,97 +925,4 @@ mod tests { // the 50M delegation wasn't a thing here for VESTING tokens either assert_eq!(delegated_vesting.amount, Uint128::zero()); } - - #[test] - fn migrate_heights_to_timestamps() { - let mut deps = init_contract(); - let mut env = mock_env(); - - let account = vesting_account_new_fixture(&mut deps.storage, &env); - let mix_identity = String::from("identity"); - let mut curr_block = env.block.clone(); - let mut delegation_blocks = std::iter::from_fn(move || { - curr_block.height += 1; - curr_block.time = curr_block.time.plus_seconds(5); - Some(curr_block.clone()) - }) - .take(100) - .collect::>(); - - for block in delegation_blocks.iter() { - DELEGATIONS - .save( - &mut deps.storage, - (account.storage_key(), mix_identity.clone(), block.height), - &Uint128::new(90_000_000_000), - ) - .unwrap(); - } - - let delegations = try_get_delegation_times( - deps.as_ref(), - account.owner_address().as_str(), - mix_identity.clone(), - ) - .unwrap(); - assert_eq!( - delegations.delegation_timestamps.len(), - delegation_blocks.len() - ); - for (heights, delegation_block) in delegations - .delegation_timestamps - .iter() - .zip(delegation_blocks.iter()) - { - assert_eq!(*heights, delegation_block.height); - } - - let height_timestamp_map = delegation_blocks - .iter() - .map(|block| (block.height, block.time.seconds())) - .collect(); - let admin = ADMIN.load(&deps.storage).unwrap(); - try_migrate_heights_to_timestamps( - account.storage_key(), - mix_identity.clone(), - height_timestamp_map, - mock_info(&admin, &[]), - deps.as_mut(), - ) - .unwrap(); - - // Some new delegation appears during migration - env.block.height += 200; - env.block.time = env.block.time.plus_seconds(1000); - delegation_blocks.push(env.block.clone()); - account - .try_delegate_to_mixnode( - String::from("identity"), - Coin { - amount: Uint128::new(90_000_000_000), - denom: TEST_COIN_DENOM.to_string(), - }, - &env, - &mut deps.storage, - ) - .unwrap(); - - let delegations = try_get_delegation_times( - deps.as_ref(), - account.owner_address().as_str(), - mix_identity.clone(), - ) - .unwrap(); - assert_eq!( - delegations.delegation_timestamps.len(), - delegation_blocks.len() - ); - for (timestamp, delegation_block) in delegations - .delegation_timestamps - .iter() - .zip(delegation_blocks.iter()) - { - assert_eq!(*timestamp, delegation_block.time.seconds()); - } - } } From 5cb80f76486dcb40aea931b40a780923d21c2210 Mon Sep 17 00:00:00 2001 From: =?UTF-8?q?Rapha=C3=ABl=20Walther?= Date: Fri, 9 Sep 2022 11:36:49 +0200 Subject: [PATCH 16/46] Revert "Added audit workflow" This reverts commit a7afd2a1c7ee1ab472a5c7a6dbb2b73601996e4f. --- .github/workflows/nightly_build_on_dispatch.yml | 4 ++-- 1 file changed, 2 insertions(+), 2 deletions(-) diff --git a/.github/workflows/nightly_build_on_dispatch.yml b/.github/workflows/nightly_build_on_dispatch.yml index 76e141efed..d45808b3fd 100644 --- a/.github/workflows/nightly_build_on_dispatch.yml +++ b/.github/workflows/nightly_build_on_dispatch.yml @@ -166,8 +166,8 @@ jobs: GIT_BRANCH: "${GITHUB_REF##*/}" KEYBASE_NYMBOT_USERNAME: "${{ secrets.KEYBASE_NYMBOT_USERNAME }}" KEYBASE_NYMBOT_PAPERKEY: "${{ secrets.KEYBASE_NYMBOT_PAPERKEY }}" - KEYBASE_NYMBOT_TEAM: "${{ secrets.KEYBASE_NYMTECH_TEAM }}" - KEYBASE_NYM_CHANNEL: "test" + KEYBASE_NYMBOT_TEAM: "${{ secrets.KEYBASE_NYMBOT_TEAM }}" + KEYBASE_NYM_CHANNEL: "ci-nightly" IS_SUCCESS: "${{ env.WORKFLOW_CONCLUSION == 'success' }}" uses: docker://keybaseio/client:stable-node with: From 634818a98872cd37d20bb3e8d3d1cb83684cab94 Mon Sep 17 00:00:00 2001 From: =?UTF-8?q?Rapha=C3=ABl=20Walther?= Date: Fri, 9 Sep 2022 11:41:44 +0200 Subject: [PATCH 17/46] Added notification workflow --- .../workflows/notification_on_dispatch.yml | 26 +++++++++++++++++++ 1 file changed, 26 insertions(+) create mode 100644 .github/workflows/notification_on_dispatch.yml diff --git a/.github/workflows/notification_on_dispatch.yml b/.github/workflows/notification_on_dispatch.yml new file mode 100644 index 0000000000..4222a71ae3 --- /dev/null +++ b/.github/workflows/notification_on_dispatch.yml @@ -0,0 +1,26 @@ +name: Nightly builds on dispatch + +on: workflow_dispatch +jobs: + notification: + runs-on: ubuntu-latest + steps: + - name: Check out repository code + uses: actions/checkout@v2 + - name: Keybase - Node Install + run: npm install + working-directory: .github/workflows/support-files + - name: Keybase - Send Notification + env: + NYM_NOTIFICATION_KIND: nightly + NYM_PROJECT_NAME: "Notification test" + GITHUB_TOKEN: "${{ secrets.GITHUB_TOKEN }}" + GIT_COMMIT_MESSAGE: "${{ github.event.head_commit.message }}" + GIT_BRANCH: "${GITHUB_REF##*/}" + KEYBASE_NYMBOT_USERNAME: "${{ secrets.KEYBASE_NYMBOT_USERNAME }}" + KEYBASE_NYMBOT_PAPERKEY: "${{ secrets.KEYBASE_NYMBOT_PAPERKEY }}" + KEYBASE_NYMBOT_TEAM: "${{ secrets.KEYBASE_NYMBOT_TEAM }}" + KEYBASE_NYM_CHANNEL: "ci-nightly" + uses: docker://keybaseio/client:stable-node + with: + args: .github/workflows/support-files/notifications/entry_point.sh From 10be112279839ddcd4e653fa08c594b502e94e96 Mon Sep 17 00:00:00 2001 From: =?UTF-8?q?Jon=20H=C3=A4ggblad?= Date: Tue, 6 Sep 2022 12:46:24 +0200 Subject: [PATCH 18/46] socks5-client: graceful shutdown --- Cargo.lock | 12 ++- clients/client-core/Cargo.toml | 1 + .../src/client/cover_traffic_stream.rs | 22 ++++- clients/client-core/src/client/mix_traffic.rs | 22 ++++- .../acknowledgement_listener.rs | 21 +++- .../action_controller.rs | 16 +++- .../input_message_listener.rs | 17 +++- .../acknowledgement_control/mod.rs | 24 +++-- .../retransmission_request_listener.rs | 18 +++- .../sent_notification_listener.rs | 17 +++- .../src/client/real_messages_control/mod.rs | 8 +- .../real_traffic_stream.rs | 30 +++++- .../client-core/src/client/received_buffer.rs | 52 +++++++--- .../src/client/topology_control.rs | 16 +++- clients/native/Cargo.toml | 9 +- clients/native/src/client/mod.rs | 67 +++++++++---- clients/socks5/Cargo.toml | 11 ++- clients/socks5/src/client/mod.rs | 88 ++++++++++++----- clients/socks5/src/socks/client.rs | 5 + clients/socks5/src/socks/mixnet_responses.rs | 19 +++- clients/socks5/src/socks/server.rs | 96 +++++++++++-------- common/client-libs/gateway-client/Cargo.toml | 9 +- .../client-libs/gateway-client/src/client.rs | 11 ++- .../gateway-client/src/socket_state.rs | 17 +++- common/socks5/proxy-helpers/Cargo.toml | 1 + .../src/connection_controller.rs | 23 +++-- .../proxy-helpers/src/proxy_runner/inbound.rs | 7 ++ .../proxy-helpers/src/proxy_runner/mod.rs | 8 ++ .../src/proxy_runner/outbound.rs | 6 ++ common/task/src/lib.rs | 2 + common/task/src/shutdown.rs | 19 ++++ common/task/src/signal.rs | 27 ++++++ mixnode/src/node/mod.rs | 30 +----- nym-connect/Cargo.lock | 15 +++ .../network-requester/Cargo.toml | 1 + .../network-requester/src/connection.rs | 3 + .../network-requester/src/core.rs | 15 ++- .../src/network_monitor/monitor/sender.rs | 2 + 38 files changed, 580 insertions(+), 187 deletions(-) create mode 100644 common/task/src/signal.rs diff --git a/Cargo.lock b/Cargo.lock index 3494de31af..d3b3155c34 100644 --- a/Cargo.lock +++ b/Cargo.lock @@ -668,6 +668,7 @@ dependencies = [ "serde", "sled", "tap", + "task", "tempfile", "thiserror", "tokio", @@ -2054,10 +2055,12 @@ dependencies = [ "pemstore", "rand 0.7.3", "secp256k1", + "task", "thiserror", "tokio", - "tokio-tungstenite 0.14.0", - "tungstenite 0.13.0", + "tokio-stream", + "tokio-tungstenite", + "tungstenite", "url", "validator-client", "wasm-bindgen", @@ -3255,6 +3258,7 @@ dependencies = [ "serde", "serde_json", "sled", + "task", "tokio", "tokio-tungstenite 0.14.0", "topology", @@ -3375,6 +3379,7 @@ dependencies = [ "socks5-requests", "sqlx 0.6.1", "statistics-common", + "task", "thiserror", "tokio", "tokio-tungstenite 0.17.2", @@ -3424,6 +3429,7 @@ dependencies = [ "serde", "snafu", "socks5-requests", + "task", "tokio", "topology", "url", @@ -4258,6 +4264,7 @@ dependencies = [ "log", "ordered-buffer", "socks5-requests", + "task", "tokio", "tokio-test", "tokio-util 0.7.3", @@ -6138,6 +6145,7 @@ dependencies = [ "futures-core", "pin-project-lite", "tokio", + "tokio-util 0.7.3", ] [[package]] diff --git a/clients/client-core/Cargo.toml b/clients/client-core/Cargo.toml index ca11dfd240..9cd7d16e4b 100644 --- a/clients/client-core/Cargo.toml +++ b/clients/client-core/Cargo.toml @@ -26,6 +26,7 @@ gateway-requests = { path = "../../gateway/gateway-requests" } nonexhaustive-delayqueue = { path = "../../common/nonexhaustive-delayqueue" } nymsphinx = { path = "../../common/nymsphinx" } pemstore = { path = "../../common/pemstore" } +task = { path = "../../common/task" } topology = { path = "../../common/topology" } validator-client = { path = "../../common/client-libs/validator-client" } tap = "1.0.1" diff --git a/clients/client-core/src/client/cover_traffic_stream.rs b/clients/client-core/src/client/cover_traffic_stream.rs index 8c47b197c8..9370b5c6ce 100644 --- a/clients/client-core/src/client/cover_traffic_stream.rs +++ b/clients/client-core/src/client/cover_traffic_stream.rs @@ -13,6 +13,7 @@ use nymsphinx::utils::sample_poisson_duration; use rand::{rngs::OsRng, CryptoRng, Rng}; use std::pin::Pin; use std::sync::Arc; +use task::ShutdownListener; use tokio::task::JoinHandle; use tokio::time; @@ -48,6 +49,9 @@ where /// Accessor to the common instance of network topology. topology_access: TopologyAccessor, + + /// Listen to shutdown signals. + shutdown: ShutdownListener, } impl Stream for LoopCoverTrafficStream @@ -92,6 +96,7 @@ impl LoopCoverTrafficStream { mix_tx: BatchMixMessageSender, our_full_destination: Recipient, topology_access: TopologyAccessor, + shutdown: ShutdownListener, ) -> Self { let rng = OsRng; @@ -105,6 +110,7 @@ impl LoopCoverTrafficStream { our_full_destination, rng, topology_access, + shutdown, } } @@ -159,9 +165,21 @@ impl LoopCoverTrafficStream { self.average_cover_message_sending_delay, ))); - while self.next().await.is_some() { - self.on_new_message().await; + let mut shutdown = self.shutdown.clone(); + while !shutdown.is_shutdown() { + tokio::select! { + biased; + _ = shutdown.recv() => { + log::trace!("LoopCoverTrafficStream: Received shutdown"); + } + next = self.next() => { + if next.is_some() { + self.on_new_message().await; + } + } + } } + log::debug!("LoopCoverTrafficStream: Exiting"); } pub fn start(mut self) -> JoinHandle<()> { diff --git a/clients/client-core/src/client/mix_traffic.rs b/clients/client-core/src/client/mix_traffic.rs index 86312f1aa8..cbd1d413cb 100644 --- a/clients/client-core/src/client/mix_traffic.rs +++ b/clients/client-core/src/client/mix_traffic.rs @@ -6,6 +6,7 @@ use futures::StreamExt; use gateway_client::GatewayClient; use log::*; use nymsphinx::forwarding::packet::MixPacket; +use task::ShutdownListener; use tokio::task::JoinHandle; pub type BatchMixMessageSender = mpsc::UnboundedSender>; @@ -18,6 +19,7 @@ pub struct MixTrafficController { // later on gateway_client will need to be accessible by other entities gateway_client: GatewayClient, mix_rx: BatchMixMessageReceiver, + shutdown: ShutdownListener, // TODO: this is temporary work-around. // in long run `gateway_client` will be moved away from `MixTrafficController` anyway. @@ -28,10 +30,12 @@ impl MixTrafficController { pub fn new( mix_rx: BatchMixMessageReceiver, gateway_client: GatewayClient, + shutdown: ShutdownListener, ) -> MixTrafficController { MixTrafficController { gateway_client, mix_rx, + shutdown, consecutive_gateway_failure_count: 0, } } @@ -66,9 +70,23 @@ impl MixTrafficController { } pub async fn run(&mut self) { - while let Some(mix_packets) = self.mix_rx.next().await { - self.on_messages(mix_packets).await; + while !self.shutdown.is_shutdown() { + tokio::select! { + mix_packets = self.mix_rx.next() => match mix_packets { + Some(mix_packets) => { + self.on_messages(mix_packets).await; + }, + None => { + log::trace!("MixTrafficController: Stopping since channel closed"); + break; + } + }, + _ = self.shutdown.recv() => { + log::trace!("MixTrafficController: Received shutdown"); + } + } } + log::debug!("MixTrafficController: Exiting"); } pub fn start(mut self) -> JoinHandle<()> { diff --git a/clients/client-core/src/client/real_messages_control/acknowledgement_control/acknowledgement_listener.rs b/clients/client-core/src/client/real_messages_control/acknowledgement_control/acknowledgement_listener.rs index 77294b8cd6..964617c5b0 100644 --- a/clients/client-core/src/client/real_messages_control/acknowledgement_control/acknowledgement_listener.rs +++ b/clients/client-core/src/client/real_messages_control/acknowledgement_control/acknowledgement_listener.rs @@ -10,6 +10,7 @@ use nymsphinx::{ chunking::fragment::{FragmentIdentifier, COVER_FRAG_ID}, }; use std::sync::Arc; +use task::ShutdownListener; /// Module responsible for listening for any data resembling acknowledgements from the network /// and firing actions to remove them from the 'Pending' state. @@ -17,6 +18,7 @@ pub(super) struct AcknowledgementListener { ack_key: Arc, ack_receiver: AcknowledgementReceiver, action_sender: ActionSender, + shutdown: ShutdownListener, } impl AcknowledgementListener { @@ -24,11 +26,13 @@ impl AcknowledgementListener { ack_key: Arc, ack_receiver: AcknowledgementReceiver, action_sender: ActionSender, + shutdown: ShutdownListener, ) -> Self { AcknowledgementListener { ack_key, ack_receiver, action_sender, + shutdown, } } @@ -65,12 +69,19 @@ impl AcknowledgementListener { pub(super) async fn run(&mut self) { debug!("Started AcknowledgementListener"); - while let Some(acks) = self.ack_receiver.next().await { - // realistically we would only be getting one ack at the time - for ack in acks { - self.on_ack(ack).await; + while !self.shutdown.is_shutdown() { + tokio::select! { + Some(acks) = self.ack_receiver.next() => { + // realistically we would only be getting one ack at the time + for ack in acks { + self.on_ack(ack).await; + } + }, + _ = self.shutdown.recv() => { + log::trace!("AcknowledgementListener: Received shutdown"); + } } } - error!("TODO: error msg. Or maybe panic?") + log::debug!("AcknowledgementListener: Exiting"); } } diff --git a/clients/client-core/src/client/real_messages_control/acknowledgement_control/action_controller.rs b/clients/client-core/src/client/real_messages_control/acknowledgement_control/action_controller.rs index f8417b0285..a11fe49f5d 100644 --- a/clients/client-core/src/client/real_messages_control/acknowledgement_control/action_controller.rs +++ b/clients/client-core/src/client/real_messages_control/acknowledgement_control/action_controller.rs @@ -12,6 +12,7 @@ use nymsphinx::Delay as SphinxDelay; use std::collections::HashMap; use std::sync::Arc; use std::time::Duration; +use task::ShutdownListener; pub(crate) type ActionSender = UnboundedSender; @@ -99,12 +100,16 @@ pub(super) struct ActionController { /// Channel for notifying `RetransmissionRequestListener` about expired acknowledgements. retransmission_sender: RetransmissionRequestSender, + + /// Listen for shutdown notifications + shutdown: ShutdownListener, } impl ActionController { pub(super) fn new( config: Config, retransmission_sender: RetransmissionRequestSender, + shutdown: ShutdownListener, ) -> (Self, ActionSender) { let (sender, receiver) = mpsc::unbounded(); ( @@ -114,6 +119,7 @@ impl ActionController { pending_acks_timers: NonExhaustiveDelayQueue::new(), incoming_actions: receiver, retransmission_sender, + shutdown, }, sender, ) @@ -246,14 +252,18 @@ impl ActionController { } pub(super) async fn run(&mut self) { - loop { - // at some point there will be a global shutdown signal here as the third option + while !self.shutdown.is_shutdown() { tokio::select! { // we NEVER expect for ANY sender to get dropped so unwrap here is fine action = self.incoming_actions.next() => self.process_action(action.unwrap()), // pending ack queue Stream CANNOT return a `None` so unwrap here is fine - expired_ack = self.pending_acks_timers.next() => self.handle_expired_ack_timer(expired_ack.unwrap()) + expired_ack = self.pending_acks_timers.next() => self.handle_expired_ack_timer(expired_ack.unwrap()), + // listen for shutdown notifications + _ = self.shutdown.recv() => { + log::trace!("ActionController: Received shutdown"); + } } } + log::debug!("ActionController: Exiting"); } } diff --git a/clients/client-core/src/client/real_messages_control/acknowledgement_control/input_message_listener.rs b/clients/client-core/src/client/real_messages_control/acknowledgement_control/input_message_listener.rs index e44eef38c8..35d5ccdcf6 100644 --- a/clients/client-core/src/client/real_messages_control/acknowledgement_control/input_message_listener.rs +++ b/clients/client-core/src/client/real_messages_control/acknowledgement_control/input_message_listener.rs @@ -16,6 +16,7 @@ use nymsphinx::preparer::MessagePreparer; use nymsphinx::{acknowledgements::AckKey, addressing::clients::Recipient}; use rand::{CryptoRng, Rng}; use std::sync::Arc; +use task::ShutdownListener; /// Module responsible for dealing with the received messages: splitting them, creating acknowledgements, /// putting everything into sphinx packets, etc. @@ -32,6 +33,7 @@ where real_message_sender: BatchRealMessageSender, topology_access: TopologyAccessor, reply_key_storage: ReplyKeyStorage, + shutdown: ShutdownListener, } impl InputMessageListener @@ -50,6 +52,7 @@ where real_message_sender: BatchRealMessageSender, topology_access: TopologyAccessor, reply_key_storage: ReplyKeyStorage, + shutdown: ShutdownListener, ) -> Self { InputMessageListener { ack_key, @@ -60,6 +63,7 @@ where real_message_sender, topology_access, reply_key_storage, + shutdown, } } @@ -182,9 +186,16 @@ where pub(super) async fn run(&mut self) { debug!("Started InputMessageListener"); - while let Some(input_msg) = self.input_receiver.next().await { - self.on_input_message(input_msg).await; + while !self.shutdown.is_shutdown() { + tokio::select! { + Some(input_msg) = self.input_receiver.next() => { + self.on_input_message(input_msg).await; + }, + _ = self.shutdown.recv() => { + log::trace!("InputMessageListener: Received shutdown"); + } + } } - error!("TODO: error msg. Or maybe panic?") + log::debug!("InputMessageListener: Exiting"); } } diff --git a/clients/client-core/src/client/real_messages_control/acknowledgement_control/mod.rs b/clients/client-core/src/client/real_messages_control/acknowledgement_control/mod.rs index a987497af1..17b406cd07 100644 --- a/clients/client-core/src/client/real_messages_control/acknowledgement_control/mod.rs +++ b/clients/client-core/src/client/real_messages_control/acknowledgement_control/mod.rs @@ -25,6 +25,7 @@ use std::{ sync::{Arc, Weak}, time::Duration, }; +use task::ShutdownListener; use tokio::task::JoinHandle; mod acknowledgement_listener; @@ -160,13 +161,14 @@ where ack_recipient: Recipient, reply_key_storage: ReplyKeyStorage, connectors: AcknowledgementControllerConnectors, + shutdown: ShutdownListener, ) -> Self { let (retransmission_tx, retransmission_rx) = mpsc::unbounded(); let action_config = action_controller::Config::new(config.ack_wait_addition, config.ack_wait_multiplier); let (action_controller, action_sender) = - ActionController::new(action_config, retransmission_tx); + ActionController::new(action_config, retransmission_tx, shutdown.clone()); let message_preparer = MessagePreparer::new( rng, @@ -180,6 +182,7 @@ where Arc::clone(&ack_key), connectors.ack_receiver, action_sender.clone(), + shutdown.clone(), ); // will listen for any new messages from the client @@ -192,6 +195,7 @@ where connectors.real_message_sender.clone(), topology_access.clone(), reply_key_storage, + shutdown.clone(), ); // will listen for any ack timeouts and trigger retransmission @@ -203,12 +207,16 @@ where connectors.real_message_sender, retransmission_rx, topology_access, + shutdown.clone(), ); // will listen for events indicating the packet was sent through the network so that // the retransmission timer should be started. - let sent_notification_listener = - SentNotificationListener::new(connectors.sent_notifier, action_sender); + let sent_notification_listener = SentNotificationListener::new( + connectors.sent_notifier, + action_sender, + shutdown.clone(), + ); AcknowledgementController { acknowledgement_listener: Some(acknowledgement_listener), @@ -232,27 +240,27 @@ where // graceful shutdowns. let ack_listener_fut = tokio::spawn(async move { acknowledgement_listener.run().await; - error!("The acknowledgement listener has finished execution!"); + debug!("The acknowledgement listener has finished execution!"); acknowledgement_listener }); let input_listener_fut = tokio::spawn(async move { input_message_listener.run().await; - error!("The input listener has finished execution!"); + debug!("The input listener has finished execution!"); input_message_listener }); let retransmission_req_fut = tokio::spawn(async move { retransmission_request_listener.run().await; - error!("The retransmission request listener has finished execution!"); + debug!("The retransmission request listener has finished execution!"); retransmission_request_listener }); let sent_notification_fut = tokio::spawn(async move { sent_notification_listener.run().await; - error!("The sent notification listener has finished execution!"); + debug!("The sent notification listener has finished execution!"); sent_notification_listener }); let action_controller_fut = tokio::spawn(async move { action_controller.run().await; - error!("The controller has finished execution!"); + debug!("The controller has finished execution!"); action_controller }); diff --git a/clients/client-core/src/client/real_messages_control/acknowledgement_control/retransmission_request_listener.rs b/clients/client-core/src/client/real_messages_control/acknowledgement_control/retransmission_request_listener.rs index 3e9e2ee65a..650f21c0fd 100644 --- a/clients/client-core/src/client/real_messages_control/acknowledgement_control/retransmission_request_listener.rs +++ b/clients/client-core/src/client/real_messages_control/acknowledgement_control/retransmission_request_listener.rs @@ -14,6 +14,7 @@ use nymsphinx::preparer::MessagePreparer; use nymsphinx::{acknowledgements::AckKey, addressing::clients::Recipient}; use rand::{CryptoRng, Rng}; use std::sync::{Arc, Weak}; +use task::ShutdownListener; // responsible for packet retransmission upon fired timer pub(super) struct RetransmissionRequestListener @@ -27,6 +28,7 @@ where real_message_sender: BatchRealMessageSender, request_receiver: RetransmissionRequestReceiver, topology_access: TopologyAccessor, + shutdown: ShutdownListener, } impl RetransmissionRequestListener @@ -41,6 +43,7 @@ where real_message_sender: BatchRealMessageSender, request_receiver: RetransmissionRequestReceiver, topology_access: TopologyAccessor, + shutdown: ShutdownListener, ) -> Self { RetransmissionRequestListener { ack_key, @@ -50,6 +53,7 @@ where real_message_sender, request_receiver, topology_access, + shutdown, } } @@ -121,9 +125,17 @@ where pub(super) async fn run(&mut self) { debug!("Started RetransmissionRequestListener"); - while let Some(timed_out_ack) = self.request_receiver.next().await { - self.on_retransmission_request(timed_out_ack).await; + + while !self.shutdown.is_shutdown() { + tokio::select! { + Some(timed_out_ack) = self.request_receiver.next() => { + self.on_retransmission_request(timed_out_ack).await; + }, + _ = self.shutdown.recv() => { + log::trace!("RetransmissionRequestListener: Received shutdown"); + } + } } - error!("TODO: error msg. Or maybe panic?") + log::debug!("RetransmissionRequestListener: Exiting"); } } diff --git a/clients/client-core/src/client/real_messages_control/acknowledgement_control/sent_notification_listener.rs b/clients/client-core/src/client/real_messages_control/acknowledgement_control/sent_notification_listener.rs index 2bd2eac933..4c33d1b609 100644 --- a/clients/client-core/src/client/real_messages_control/acknowledgement_control/sent_notification_listener.rs +++ b/clients/client-core/src/client/real_messages_control/acknowledgement_control/sent_notification_listener.rs @@ -6,6 +6,7 @@ use super::SentPacketNotificationReceiver; use futures::StreamExt; use log::*; use nymsphinx::chunking::fragment::{FragmentIdentifier, COVER_FRAG_ID}; +use task::ShutdownListener; /// Module responsible for starting up retransmission timers. /// It is required because when we send our packet to the `real traffic stream` controlled @@ -14,16 +15,19 @@ use nymsphinx::chunking::fragment::{FragmentIdentifier, COVER_FRAG_ID}; pub(super) struct SentNotificationListener { sent_notifier: SentPacketNotificationReceiver, action_sender: ActionSender, + shutdown: ShutdownListener, } impl SentNotificationListener { pub(super) fn new( sent_notifier: SentPacketNotificationReceiver, action_sender: ActionSender, + shutdown: ShutdownListener, ) -> Self { SentNotificationListener { sent_notifier, action_sender, + shutdown, } } @@ -44,9 +48,16 @@ impl SentNotificationListener { pub(super) async fn run(&mut self) { debug!("Started SentNotificationListener"); - while let Some(frag_id) = self.sent_notifier.next().await { - self.on_sent_message(frag_id).await; + while !self.shutdown.is_shutdown() { + tokio::select! { + Some(frag_id) = self.sent_notifier.next() => { + self.on_sent_message(frag_id).await; + }, + _ = self.shutdown.recv() => { + log::trace!("SentNotificationListener: Received shutdown"); + } + } } - error!("TODO: error msg. Or maybe panic?") + log::debug!("SentNotificationListener: Exiting"); } } diff --git a/clients/client-core/src/client/real_messages_control/mod.rs b/clients/client-core/src/client/real_messages_control/mod.rs index 610f1b586e..9068b51e06 100644 --- a/clients/client-core/src/client/real_messages_control/mod.rs +++ b/clients/client-core/src/client/real_messages_control/mod.rs @@ -22,6 +22,7 @@ use nymsphinx::addressing::clients::Recipient; use rand::{rngs::OsRng, CryptoRng, Rng}; use std::sync::Arc; use std::time::Duration; +use task::ShutdownListener; use tokio::task::JoinHandle; mod acknowledgement_control; @@ -91,6 +92,7 @@ impl RealMessagesController { mix_sender: BatchMixMessageSender, topology_access: TopologyAccessor, reply_key_storage: ReplyKeyStorage, + shutdown: ShutdownListener, ) -> Self { let rng = OsRng; @@ -119,6 +121,7 @@ impl RealMessagesController { config.self_recipient, reply_key_storage, ack_controller_connectors, + shutdown.clone(), ); let out_queue_config = real_traffic_stream::Config::new( @@ -136,6 +139,7 @@ impl RealMessagesController { rng, config.self_recipient, topology_access, + shutdown, ); RealMessagesController { @@ -153,12 +157,12 @@ impl RealMessagesController { // graceful shutdowns. let out_queue_control_fut = tokio::spawn(async move { out_queue_control.run_out_queue_control().await; - error!("The out queue controller has finished execution!"); + debug!("The out queue controller has finished execution!"); out_queue_control }); let ack_control_fut = tokio::spawn(async move { ack_control.run().await; - error!("The acknowledgement controller has finished execution!"); + debug!("The acknowledgement controller has finished execution!"); ack_control }); diff --git a/clients/client-core/src/client/real_messages_control/real_traffic_stream.rs b/clients/client-core/src/client/real_messages_control/real_traffic_stream.rs index 47d95d0d26..cb27cc2779 100644 --- a/clients/client-core/src/client/real_messages_control/real_traffic_stream.rs +++ b/clients/client-core/src/client/real_messages_control/real_traffic_stream.rs @@ -19,6 +19,7 @@ use std::collections::VecDeque; use std::pin::Pin; use std::sync::Arc; use std::time::Duration; +use task::ShutdownListener; use tokio::time; /// Configurable parameters of the `OutQueueControl` @@ -83,6 +84,9 @@ where /// Buffer containing all real messages received. It is first exhausted before more are pulled. received_buffer: VecDeque, + + /// Listens for shutdown signals + shutdown: ShutdownListener, } pub(crate) struct RealMessage { @@ -174,6 +178,7 @@ where rng: R, our_full_destination: Recipient, topology_access: TopologyAccessor, + shutdown: ShutdownListener, ) -> Self { OutQueueControl { config, @@ -186,6 +191,7 @@ where rng, topology_access, received_buffer: VecDeque::with_capacity(0), // we won't be putting any data into this guy directly + shutdown, } } @@ -239,7 +245,15 @@ where // - we run out of memory // - the receiver channel is closed // in either case there's no recovery and we can only panic - self.mix_tx.unbounded_send(vec![next_message]).unwrap(); + if let Err(err) = self.mix_tx.unbounded_send(vec![next_message]) { + if self.shutdown.is_shutdown_poll() { + log::info!("Failed to send (shutdown detected)"); + } else { + // We don't try to limp along, panic to avoid continuing in a potentially + // inconsistent state + panic!("{err}"); + } + } // JS: Not entirely sure why or how it fixes stuff, but without the yield call, // the UnboundedReceiver [of mix_rx] will not get a chance to read anything @@ -257,9 +271,19 @@ where self.config.average_message_sending_delay, ))); - while let Some(next_message) = self.next().await { - self.on_message(next_message).await; + let mut shutdown = self.shutdown.clone(); + while !shutdown.is_shutdown() { + tokio::select! { + biased; + _ = shutdown.recv() => { + log::trace!("OutQueueControl: Received shutdown"); + } + Some(next_message) = self.next() => { + self.on_message(next_message).await; + }, + } } + log::debug!("OutQueueControl: Exiting"); } pub(crate) async fn run_out_queue_control(&mut self) { diff --git a/clients/client-core/src/client/received_buffer.rs b/clients/client-core/src/client/received_buffer.rs index ad77b82e1a..fb51c9a703 100644 --- a/clients/client-core/src/client/received_buffer.rs +++ b/clients/client-core/src/client/received_buffer.rs @@ -15,6 +15,7 @@ use nymsphinx::params::{ReplySurbEncryptionAlgorithm, ReplySurbKeyDigestAlgorith use nymsphinx::receiver::{MessageReceiver, MessageRecoveryError, ReconstructedMessage}; use std::collections::HashSet; use std::sync::Arc; +use task::ShutdownListener; use tokio::task::JoinHandle; // Buffer Requests to say "hey, send any reconstructed messages to this channel" @@ -292,16 +293,26 @@ impl RequestReceiver { fn start(mut self) -> JoinHandle<()> { tokio::spawn(async move { - while let Some(request) = self.query_receiver.next().await { - match request { - ReceivedBufferMessage::ReceiverAnnounce(sender) => { - self.received_buffer.connect_sender(sender).await; - } - ReceivedBufferMessage::ReceiverDisconnect => { - self.received_buffer.disconnect_sender().await - } - } + loop { + tokio::select! { + request = self.query_receiver.next() => { + match request { + Some(ReceivedBufferMessage::ReceiverAnnounce(sender)) => { + self.received_buffer.connect_sender(sender).await; + } + Some(ReceivedBufferMessage::ReceiverDisconnect) => { + self.received_buffer.disconnect_sender().await + } + None => { + log::trace!("RequestReceiver: Stopping since channel closed"); + break; + }, + } + }, + }; } + + log::debug!("RequestReceiver: Exiting"); }) } } @@ -309,23 +320,40 @@ impl RequestReceiver { struct FragmentedMessageReceiver { received_buffer: ReceivedMessagesBuffer, mixnet_packet_receiver: MixnetMessageReceiver, + shutdown: ShutdownListener, } impl FragmentedMessageReceiver { fn new( received_buffer: ReceivedMessagesBuffer, mixnet_packet_receiver: MixnetMessageReceiver, + shutdown: ShutdownListener, ) -> Self { FragmentedMessageReceiver { received_buffer, mixnet_packet_receiver, + shutdown, } } fn start(mut self) -> JoinHandle<()> { tokio::spawn(async move { - while let Some(new_messages) = self.mixnet_packet_receiver.next().await { - self.received_buffer.handle_new_received(new_messages).await; + while !self.shutdown.is_shutdown() { + tokio::select! { + new_messages = self.mixnet_packet_receiver.next() => match new_messages { + Some(new_messages) => { + self.received_buffer.handle_new_received(new_messages).await; + } + None => { + log::trace!("FragmentedMessageReceiver: Stopping since channel closed"); + break; + } + }, + _ = self.shutdown.recv() => { + log::trace!("FragmentedMessageReceiver: Received shutdown"); + } + } } + log::debug!("FragmentedMessageReceiver: Exiting"); }) } } @@ -341,6 +369,7 @@ impl ReceivedMessagesBufferController { query_receiver: ReceivedBufferRequestReceiver, mixnet_packet_receiver: MixnetMessageReceiver, reply_key_storage: ReplyKeyStorage, + shutdown: ShutdownListener, ) -> Self { let received_buffer = ReceivedMessagesBuffer::new(local_encryption_keypair, reply_key_storage); @@ -349,6 +378,7 @@ impl ReceivedMessagesBufferController { fragmented_message_receiver: FragmentedMessageReceiver::new( received_buffer.clone(), mixnet_packet_receiver, + shutdown, ), request_receiver: RequestReceiver::new(received_buffer, query_receiver), } diff --git a/clients/client-core/src/client/topology_control.rs b/clients/client-core/src/client/topology_control.rs index 7f38bdc680..089b3bd0d2 100644 --- a/clients/client-core/src/client/topology_control.rs +++ b/clients/client-core/src/client/topology_control.rs @@ -10,6 +10,7 @@ use std::ops::Deref; use std::sync::Arc; use std::time; use std::time::Duration; +use task::ShutdownListener; use tokio::sync::{RwLock, RwLockReadGuard}; use tokio::task::JoinHandle; use topology::{nym_topology_from_bonds, NymTopology}; @@ -303,12 +304,19 @@ impl TopologyRefresher { self.topology_accessor.is_routable().await } - pub fn start(mut self) -> JoinHandle<()> { + pub fn start(mut self, mut shutdown: ShutdownListener) -> JoinHandle<()> { tokio::spawn(async move { - loop { - tokio::time::sleep(self.refresh_rate).await; - self.refresh().await; + while !shutdown.is_shutdown() { + tokio::select! { + _ = tokio::time::sleep(self.refresh_rate) => { + self.refresh().await; + }, + _ = shutdown.recv() => { + log::trace!("TopologyRefresher: Received shutdown"); + }, + } } + log::debug!("TopologyRefresher: Exiting"); }) } } diff --git a/clients/native/Cargo.toml b/clients/native/Cargo.toml index 4d712233b2..f59909534e 100644 --- a/clients/native/Cargo.toml +++ b/clients/native/Cargo.toml @@ -33,19 +33,20 @@ tokio-tungstenite = "0.14" # websocket ## internal client-core = { path = "../client-core" } coconut-interface = { path = "../../common/coconut-interface", optional = true } -credentials = { path = "../../common/credentials", optional = true } -credential-storage = { path = "../../common/credential-storage" } config = { path = "../../common/config" } +credential-storage = { path = "../../common/credential-storage" } +credentials = { path = "../../common/credentials", optional = true } crypto = { path = "../../common/crypto" } gateway-client = { path = "../../common/client-libs/gateway-client" } gateway-requests = { path = "../../gateway/gateway-requests" } +network-defaults = { path = "../../common/network-defaults" } nymsphinx = { path = "../../common/nymsphinx" } pemstore = { path = "../../common/pemstore" } +task = { path = "../../common/task" } topology = { path = "../../common/topology" } -websocket-requests = { path = "websocket-requests" } validator-client = { path = "../../common/client-libs/validator-client", features = ["nymd-client"] } version-checker = { path = "../../common/version-checker" } -network-defaults = { path = "../../common/network-defaults" } +websocket-requests = { path = "websocket-requests" } [features] coconut = ["coconut-interface", "credentials", "credentials/coconut", "gateway-requests/coconut", "gateway-client/coconut", "client-core/coconut"] diff --git a/clients/native/src/client/mod.rs b/clients/native/src/client/mod.rs index 8066cfde2e..854cebc0dc 100644 --- a/clients/native/src/client/mod.rs +++ b/clients/native/src/client/mod.rs @@ -32,6 +32,7 @@ use nymsphinx::addressing::clients::Recipient; use nymsphinx::addressing::nodes::NodeIdentity; use nymsphinx::anonymous_replies::ReplySurb; use nymsphinx::receiver::ReconstructedMessage; +use task::{wait_for_signal, ShutdownListener, ShutdownNotifier}; use crate::client::config::{Config, SocketType}; use crate::websocket; @@ -85,6 +86,7 @@ impl NymClient { &self, topology_accessor: TopologyAccessor, mix_tx: BatchMixMessageSender, + shutdown: ShutdownListener, ) { info!("Starting loop cover traffic stream..."); @@ -98,6 +100,7 @@ impl NymClient { mix_tx, self.as_mix_recipient(), topology_accessor, + shutdown, ) .start(); } @@ -109,6 +112,7 @@ impl NymClient { ack_receiver: AcknowledgementReceiver, input_receiver: InputMessageReceiver, mix_sender: BatchMixMessageSender, + shutdown: ShutdownListener, ) { let controller_config = real_messages_control::Config::new( self.key_manager.ack_key(), @@ -129,6 +133,7 @@ impl NymClient { mix_sender, topology_accessor, reply_key_storage, + shutdown, ) .start(); } @@ -140,6 +145,7 @@ impl NymClient { query_receiver: ReceivedBufferRequestReceiver, mixnet_receiver: MixnetMessageReceiver, reply_key_storage: ReplyKeyStorage, + shutdown: ShutdownListener, ) { info!("Starting received messages buffer controller..."); ReceivedMessagesBufferController::new( @@ -147,6 +153,7 @@ impl NymClient { query_receiver, mixnet_receiver, reply_key_storage, + shutdown, ) .start() } @@ -155,6 +162,7 @@ impl NymClient { &mut self, mixnet_message_sender: MixnetMessageSender, ack_sender: AcknowledgementSender, + shutdown: ShutdownListener, ) -> GatewayClient { let gateway_id = self.config.get_base().get_gateway_id(); if gateway_id.is_empty() { @@ -197,6 +205,7 @@ impl NymClient { ack_sender, self.config.get_base().get_gateway_response_timeout(), Some(bandwidth_controller), + Some(shutdown), ); gateway_client @@ -212,7 +221,11 @@ impl NymClient { // future responsible for periodically polling directory server and updating // the current global view of topology - async fn start_topology_refresher(&mut self, topology_accessor: TopologyAccessor) { + async fn start_topology_refresher( + &mut self, + topology_accessor: TopologyAccessor, + shutdown: ShutdownListener, + ) { let topology_refresher_config = TopologyRefresherConfig::new( self.config.get_base().get_validator_api_endpoints(), self.config.get_base().get_topology_refresh_rate(), @@ -234,7 +247,7 @@ impl NymClient { } info!("Starting topology refresher..."); - topology_refresher.start(); + topology_refresher.start(shutdown); } // controller for sending sphinx packets to mixnet (either real traffic or cover traffic) @@ -245,9 +258,10 @@ impl NymClient { &mut self, mix_rx: BatchMixMessageReceiver, gateway_client: GatewayClient, + shutdown: ShutdownListener, ) { info!("Starting mix traffic controller..."); - MixTrafficController::new(mix_rx, gateway_client).start(); + MixTrafficController::new(mix_rx, gateway_client, shutdown).start(); } fn start_websocket_listener( @@ -308,20 +322,26 @@ impl NymClient { /// blocking version of `start` method. Will run forever (or until SIGINT is sent) pub async fn run_forever(&mut self) { - self.start().await; - if let Err(e) = tokio::signal::ctrl_c().await { - error!( - "There was an error while capturing SIGINT - {:?}. We will terminate regardless", - e - ); - } + let shutdown = self.start().await; + wait_for_signal().await; println!( - "Received SIGINT - the client will terminate now (threads are not yet nicely stopped, if you see stack traces that's alright)." + "Received signal - the client will terminate now (threads are not yet nicely stopped, if you see stack traces that's alright)." ); + + log::info!("Sending shutdown"); + shutdown.signal_shutdown().ok(); + + // Some of these components have shutdown signalling implemented as part of socks5 work, + // but since it's not fully implemented (yet) for all the components of the native client, + // we don't try to wait and instead just stop immediately. + //log::info!("Waiting for tasks to finish... (Press ctrl-c to force)"); + //shutdown.wait_for_shutdown().await; + + log::info!("Stopping nym-client"); } - pub async fn start(&mut self) { + pub async fn start(&mut self) -> ShutdownNotifier { info!("Starting nym client"); // channels for inter-component communication // TODO: make the channels be internally created by the relevant components @@ -351,30 +371,43 @@ impl NymClient { ReplyKeyStorage::load(self.config.get_base().get_reply_encryption_key_store_path()) .expect("Failed to load reply key storage!"); + // Shutdown notifier for signalling tasks to stop + let shutdown = ShutdownNotifier::default(); + // the components are started in very specific order. Unless you know what you are doing, // do not change that. - self.start_topology_refresher(shared_topology_accessor.clone()) + self.start_topology_refresher(shared_topology_accessor.clone(), shutdown.subscribe()) .await; self.start_received_messages_buffer_controller( received_buffer_request_receiver, mixnet_messages_receiver, reply_key_storage.clone(), + shutdown.subscribe(), ); let gateway_client = self - .start_gateway_client(mixnet_messages_sender, ack_sender) + .start_gateway_client(mixnet_messages_sender, ack_sender, shutdown.subscribe()) .await; - self.start_mix_traffic_controller(sphinx_message_receiver, gateway_client); + self.start_mix_traffic_controller( + sphinx_message_receiver, + gateway_client, + shutdown.subscribe(), + ); self.start_real_traffic_controller( shared_topology_accessor.clone(), reply_key_storage, ack_receiver, input_receiver, sphinx_message_sender.clone(), + shutdown.subscribe(), ); - self.start_cover_traffic_stream(shared_topology_accessor, sphinx_message_sender); + self.start_cover_traffic_stream( + shared_topology_accessor, + sphinx_message_sender, + shutdown.subscribe(), + ); match self.config.get_socket_type() { SocketType::WebSocket => { @@ -399,5 +432,7 @@ impl NymClient { info!("Client startup finished!"); info!("The address of this client is: {}", self.as_mix_recipient()); + + shutdown } } diff --git a/clients/socks5/Cargo.toml b/clients/socks5/Cargo.toml index 008db6fe85..e9091ea4e8 100644 --- a/clients/socks5/Cargo.toml +++ b/clients/socks5/Cargo.toml @@ -26,21 +26,22 @@ url = "2.2" # internal client-core = { path = "../client-core" } coconut-interface = { path = "../../common/coconut-interface", optional = true } -credentials = { path = "../../common/credentials", optional = true } -credential-storage = { path = "../../common/credential-storage" } config = { path = "../../common/config" } +credential-storage = { path = "../../common/credential-storage" } +credentials = { path = "../../common/credentials", optional = true } crypto = { path = "../../common/crypto" } gateway-client = { path = "../../common/client-libs/gateway-client" } gateway-requests = { path = "../../gateway/gateway-requests" } +network-defaults = { path = "../../common/network-defaults" } nymsphinx = { path = "../../common/nymsphinx" } ordered-buffer = { path = "../../common/socks5/ordered-buffer" } -socks5-requests = { path = "../../common/socks5/requests" } -topology = { path = "../../common/topology" } pemstore = { path = "../../common/pemstore" } proxy-helpers = { path = "../../common/socks5/proxy-helpers" } +socks5-requests = { path = "../../common/socks5/requests" } +task = { path = "../../common/task" } +topology = { path = "../../common/topology" } validator-client = { path = "../../common/client-libs/validator-client", features = ["nymd-client"] } version-checker = { path = "../../common/version-checker" } -network-defaults = { path = "../../common/network-defaults" } [features] coconut = ["coconut-interface", "credentials", "gateway-requests/coconut", "gateway-client/coconut", "credentials/coconut", "client-core/coconut"] diff --git a/clients/socks5/src/client/mod.rs b/clients/socks5/src/client/mod.rs index a37fd92b80..bd8b60cf27 100644 --- a/clients/socks5/src/client/mod.rs +++ b/clients/socks5/src/client/mod.rs @@ -29,6 +29,7 @@ use gateway_client::{ use log::*; use nymsphinx::addressing::clients::Recipient; use nymsphinx::addressing::nodes::NodeIdentity; +use task::{wait_for_signal, ShutdownListener, ShutdownNotifier}; use crate::client::config::Config; use crate::socks::{ @@ -84,6 +85,7 @@ impl NymClient { &self, topology_accessor: TopologyAccessor, mix_tx: BatchMixMessageSender, + shutdown: ShutdownListener, ) { info!("Starting loop cover traffic stream..."); @@ -97,6 +99,7 @@ impl NymClient { mix_tx, self.as_mix_recipient(), topology_accessor, + shutdown, ) .start(); } @@ -108,6 +111,7 @@ impl NymClient { ack_receiver: AcknowledgementReceiver, input_receiver: InputMessageReceiver, mix_sender: BatchMixMessageSender, + shutdown: ShutdownListener, ) { let controller_config = client_core::client::real_messages_control::Config::new( self.key_manager.ack_key(), @@ -128,6 +132,7 @@ impl NymClient { mix_sender, topology_accessor, reply_key_storage, + shutdown, ) .start(); } @@ -139,6 +144,7 @@ impl NymClient { query_receiver: ReceivedBufferRequestReceiver, mixnet_receiver: MixnetMessageReceiver, reply_key_storage: ReplyKeyStorage, + shutdown: ShutdownListener, ) { info!("Starting received messages buffer controller..."); ReceivedMessagesBufferController::new( @@ -146,6 +152,7 @@ impl NymClient { query_receiver, mixnet_receiver, reply_key_storage, + shutdown, ) .start() } @@ -154,6 +161,7 @@ impl NymClient { &mut self, mixnet_message_sender: MixnetMessageSender, ack_sender: AcknowledgementSender, + shutdown: ShutdownListener, ) -> GatewayClient { let gateway_id = self.config.get_base().get_gateway_id(); if gateway_id.is_empty() { @@ -196,6 +204,7 @@ impl NymClient { ack_sender, self.config.get_base().get_gateway_response_timeout(), Some(bandwidth_controller), + Some(shutdown), ); gateway_client @@ -211,7 +220,11 @@ impl NymClient { // future responsible for periodically polling directory server and updating // the current global view of topology - async fn start_topology_refresher(&mut self, topology_accessor: TopologyAccessor) { + async fn start_topology_refresher( + &mut self, + topology_accessor: TopologyAccessor, + shutdown: ShutdownListener, + ) { let topology_refresher_config = TopologyRefresherConfig::new( self.config.get_base().get_validator_api_endpoints(), self.config.get_base().get_topology_refresh_rate(), @@ -233,7 +246,7 @@ impl NymClient { } info!("Starting topology refresher..."); - topology_refresher.start(); + topology_refresher.start(shutdown); } // controller for sending sphinx packets to mixnet (either real traffic or cover traffic) @@ -244,15 +257,17 @@ impl NymClient { &mut self, mix_rx: BatchMixMessageReceiver, gateway_client: GatewayClient, + shutdown: ShutdownListener, ) { info!("Starting mix traffic controller..."); - MixTrafficController::new(mix_rx, gateway_client).start(); + MixTrafficController::new(mix_rx, gateway_client, shutdown).start(); } fn start_socks5_listener( &self, buffer_requester: ReceivedBufferRequestSender, msg_input: InputMessageSender, + shutdown: ShutdownListener, ) { info!("Starting socks5 listener..."); let auth_methods = vec![AuthenticationMethods::NoAuth as u8]; @@ -264,43 +279,53 @@ impl NymClient { authenticator, self.config.get_provider_mix_address(), self.as_mix_recipient(), + shutdown, ); tokio::spawn(async move { sphinx_socks.serve(msg_input, buffer_requester).await }); } /// blocking version of `start` method. Will run forever (or until SIGINT is sent) pub async fn run_forever(&mut self) { - self.start().await; - if let Err(e) = tokio::signal::ctrl_c().await { - error!( - "There was an error while capturing SIGINT - {:?}. We will terminate regardless", - e - ); - } + let mut shutdown = self.start().await; + wait_for_signal().await; - println!( - "Received SIGINT - the client will terminate now (threads are not yet nicely stopped, if you see stack traces that's alright)." - ); + log::info!("Sending shutdown"); + shutdown.signal_shutdown().ok(); + + log::info!("Waiting for tasks to finish... (Press ctrl-c to force)"); + shutdown.wait_for_shutdown().await; + + log::info!("Stopping nym-socks5-client"); } // Variant of `run_forever` that listends for remote control messages pub async fn run_and_listen(&mut self, mut receiver: Socks5ControlMessageReceiver) { - self.start().await; + let mut shutdown = self.start().await; tokio::select! { message = receiver.next() => { log::debug!("Received message: {:?}", message); match message { Some(Socks5ControlMessage::Stop) => { - log::info!("Shutting down"); - log::info!("Graceful shutdown of tasks not yet implemented, you might see (harmless) panics until then"); + log::info!("Received stop message"); } None => log::debug!("None"), } } + _ = tokio::signal::ctrl_c() => { + log::info!("Received SIGINT"); + }, } + + log::info!("Sending shutdown"); + shutdown.signal_shutdown().ok(); + + log::info!("Waiting for tasks to finish... (Press ctrl-c to force)"); + shutdown.wait_for_shutdown().await; + + log::info!("Stopping nym-socks5-client"); } - pub async fn start(&mut self) { + pub async fn start(&mut self) -> ShutdownNotifier { info!("Starting nym client"); // channels for inter-component communication // TODO: make the channels be internally created by the relevant components @@ -330,33 +355,52 @@ impl NymClient { ReplyKeyStorage::load(self.config.get_base().get_reply_encryption_key_store_path()) .expect("Failed to load reply key storage!"); + // Shutdown notifier for signalling tasks to stop + let shutdown = ShutdownNotifier::default(); + // the components are started in very specific order. Unless you know what you are doing, // do not change that. - self.start_topology_refresher(shared_topology_accessor.clone()) + self.start_topology_refresher(shared_topology_accessor.clone(), shutdown.subscribe()) .await; self.start_received_messages_buffer_controller( received_buffer_request_receiver, mixnet_messages_receiver, reply_key_storage.clone(), + shutdown.subscribe(), ); let gateway_client = self - .start_gateway_client(mixnet_messages_sender, ack_sender) + .start_gateway_client(mixnet_messages_sender, ack_sender, shutdown.subscribe()) .await; - self.start_mix_traffic_controller(sphinx_message_receiver, gateway_client); + self.start_mix_traffic_controller( + sphinx_message_receiver, + gateway_client, + shutdown.subscribe(), + ); self.start_real_traffic_controller( shared_topology_accessor.clone(), reply_key_storage, ack_receiver, input_receiver, sphinx_message_sender.clone(), + shutdown.subscribe(), ); - self.start_cover_traffic_stream(shared_topology_accessor, sphinx_message_sender); - self.start_socks5_listener(received_buffer_request_sender, input_sender); + self.start_cover_traffic_stream( + shared_topology_accessor, + sphinx_message_sender, + shutdown.subscribe(), + ); + self.start_socks5_listener( + received_buffer_request_sender, + input_sender, + shutdown.subscribe(), + ); info!("Client startup finished!"); info!("The address of this client is: {}", self.as_mix_recipient()); + + shutdown } } diff --git a/clients/socks5/src/socks/client.rs b/clients/socks5/src/socks/client.rs index 2c3dc578f2..71ad3514ec 100644 --- a/clients/socks5/src/socks/client.rs +++ b/clients/socks5/src/socks/client.rs @@ -20,6 +20,7 @@ use socks5_requests::{ConnectionId, Message, RemoteAddress, Request}; use std::io; use std::net::SocketAddr; use std::pin::Pin; +use task::ShutdownListener; use tokio::io::{AsyncRead, AsyncReadExt, AsyncWrite, AsyncWriteExt, ReadBuf}; use tokio::{self, net::TcpStream}; @@ -140,6 +141,7 @@ pub(crate) struct SocksClient { service_provider: Recipient, self_address: Recipient, started_proxy: bool, + shutdown_listener: ShutdownListener, } impl Drop for SocksClient { @@ -163,6 +165,7 @@ impl SocksClient { service_provider: Recipient, controller_sender: ControllerSender, self_address: Recipient, + shutdown_listener: ShutdownListener, ) -> Self { let connection_id = Self::generate_random(); SocksClient { @@ -176,6 +179,7 @@ impl SocksClient { service_provider, self_address, started_proxy: false, + shutdown_listener, } } @@ -250,6 +254,7 @@ impl SocksClient { conn_receiver, input_sender, connection_id, + self.shutdown_listener.clone(), ) .run(move |conn_id, read_data, socket_closed| { let provider_request = Request::new_send(conn_id, read_data, socket_closed); diff --git a/clients/socks5/src/socks/mixnet_responses.rs b/clients/socks5/src/socks/mixnet_responses.rs index cdc9ec3f4d..29f9186448 100644 --- a/clients/socks5/src/socks/mixnet_responses.rs +++ b/clients/socks5/src/socks/mixnet_responses.rs @@ -6,11 +6,13 @@ use log::*; use nymsphinx::receiver::ReconstructedMessage; use proxy_helpers::connection_controller::{ControllerCommand, ControllerSender}; use socks5_requests::Message; +use task::ShutdownListener; pub(crate) struct MixnetResponseListener { buffer_requester: ReceivedBufferRequestSender, mix_response_receiver: ReconstructedMessagesReceiver, controller_sender: ControllerSender, + shutdown: ShutdownListener, } impl Drop for MixnetResponseListener { @@ -25,6 +27,7 @@ impl MixnetResponseListener { pub(crate) fn new( buffer_requester: ReceivedBufferRequestSender, controller_sender: ControllerSender, + shutdown: ShutdownListener, ) -> Self { let (mix_response_sender, mix_response_receiver) = mpsc::unbounded(); buffer_requester @@ -35,6 +38,7 @@ impl MixnetResponseListener { buffer_requester, mix_response_receiver, controller_sender, + shutdown, } } @@ -73,11 +77,18 @@ impl MixnetResponseListener { } pub(crate) async fn run(&mut self) { - while let Some(received_responses) = self.mix_response_receiver.next().await { - for reconstructed_message in received_responses { - self.on_message(reconstructed_message).await; + while !self.shutdown.is_shutdown() { + tokio::select! { + Some(received_responses) = self.mix_response_receiver.next() => { + for reconstructed_message in received_responses { + self.on_message(reconstructed_message).await; + } + }, + _ = self.shutdown.recv() => { + log::trace!("MixnetResponseListener: Received shutdown"); + } } } - error!("We should never see this message"); + log::debug!("MixnetResponseListener: Exiting"); } } diff --git a/clients/socks5/src/socks/server.rs b/clients/socks5/src/socks/server.rs index afa6f88e02..4282b72207 100644 --- a/clients/socks5/src/socks/server.rs +++ b/clients/socks5/src/socks/server.rs @@ -11,6 +11,7 @@ use log::*; use nymsphinx::addressing::clients::Recipient; use proxy_helpers::connection_controller::Controller; use std::net::SocketAddr; +use task::ShutdownListener; use tokio::net::TcpListener; /// A Socks5 server that listens for connections. @@ -19,6 +20,7 @@ pub struct SphinxSocksServer { listening_address: SocketAddr, service_provider: Recipient, self_address: Recipient, + shutdown: ShutdownListener, } impl SphinxSocksServer { @@ -28,6 +30,7 @@ impl SphinxSocksServer { authenticator: Authenticator, service_provider: Recipient, self_address: Recipient, + shutdown: ShutdownListener, ) -> Self { // hardcode ip as we (presumably) ONLY want to listen locally. If we change it, we can // just modify the config @@ -38,6 +41,7 @@ impl SphinxSocksServer { listening_address: format!("{}:{}", ip, port).parse().unwrap(), service_provider, self_address, + shutdown, } } @@ -58,56 +62,66 @@ impl SphinxSocksServer { }); // listener for mix messages - let mut mixnet_response_listener = - MixnetResponseListener::new(buffer_requester, controller_sender.clone()); - + let mut mixnet_response_listener = MixnetResponseListener::new( + buffer_requester, + controller_sender.clone(), + self.shutdown.clone(), + ); tokio::spawn(async move { mixnet_response_listener.run().await; }); loop { - if let Ok((stream, _remote)) = listener.accept().await { - // TODO Optimize this - let mut client = SocksClient::new( - stream, - self.authenticator.clone(), - input_sender.clone(), - self.service_provider, - controller_sender.clone(), - self.self_address, - ); + tokio::select! { + Ok((stream, _remote)) = listener.accept() => { + // TODO Optimize this + let mut client = SocksClient::new( + stream, + self.authenticator.clone(), + input_sender.clone(), + self.service_provider, + controller_sender.clone(), + self.self_address, + self.shutdown.clone(), + ); - tokio::spawn(async move { - { - match client.run().await { - Ok(_) => {} - Err(error) => { - error!("Error! {}", error); - let error_text = format!("{}", error); + tokio::spawn(async move { + { + match client.run().await { + Ok(_) => {} + Err(error) => { + error!("Error! {}", error); + let error_text = format!("{}", error); - let response: ResponseCode; + let response: ResponseCode; - if error_text.contains("Host") { - response = ResponseCode::HostUnreachable; - } else if error_text.contains("Network") { - response = ResponseCode::NetworkUnreachable; - } else if error_text.contains("ttl") { - response = ResponseCode::TtlExpired - } else { - response = ResponseCode::Failure + if error_text.contains("Host") { + response = ResponseCode::HostUnreachable; + } else if error_text.contains("Network") { + response = ResponseCode::NetworkUnreachable; + } else if error_text.contains("ttl") { + response = ResponseCode::TtlExpired + } else { + response = ResponseCode::Failure + } + + if client.error(response).await.is_err() { + warn!("Failed to send error code"); + }; + if client.shutdown().await.is_err() { + warn!("Failed to shutdown TcpStream"); + }; } - - if client.error(response).await.is_err() { - warn!("Failed to send error code"); - }; - if client.shutdown().await.is_err() { - warn!("Failed to shutdown TcpStream"); - }; - } - }; - // client gets dropped here - } - }); + }; + // client gets dropped here + } + }); + }, + _ = self.shutdown.recv() => { + log::trace!("SphinxSocksServer: Received shutdown"); + log::debug!("SphinxSocksServer: Exiting"); + return Ok(()); + } } } } diff --git a/common/client-libs/gateway-client/Cargo.toml b/common/client-libs/gateway-client/Cargo.toml index 2cd7388139..d4688e9428 100644 --- a/common/client-libs/gateway-client/Cargo.toml +++ b/common/client-libs/gateway-client/Cargo.toml @@ -20,13 +20,14 @@ web3 = { version = "0.17.0", default-features = false } async-trait = { version = "0.1.51" } # internal +coconut-interface = { path = "../../coconut-interface", optional = true } credentials = { path = "../../credentials" } crypto = { path = "../../crypto" } gateway-requests = { path = "../../../gateway/gateway-requests" } +network-defaults = { path = "../../network-defaults" } nymsphinx = { path = "../../nymsphinx" } pemstore = { path = "../../pemstore" } -coconut-interface = { path = "../../coconut-interface", optional = true } -network-defaults = { path = "../../network-defaults" } +task = { path = "../../task" } validator-client = { path = "../validator-client", optional = true } [dependencies.tungstenite] @@ -38,6 +39,10 @@ default-features = false version = "1.19.1" features = ["macros", "rt", "net", "sync", "time"] +[target."cfg(not(target_arch = \"wasm32\"))".dependencies.tokio-stream] +version = "0.1.9" +features = ["net", "sync", "time"] + [target."cfg(not(target_arch = \"wasm32\"))".dependencies.tokio-tungstenite] version = "0.14" diff --git a/common/client-libs/gateway-client/src/client.rs b/common/client-libs/gateway-client/src/client.rs index c29a65b080..658a314535 100644 --- a/common/client-libs/gateway-client/src/client.rs +++ b/common/client-libs/gateway-client/src/client.rs @@ -30,6 +30,7 @@ use rand::rngs::OsRng; use std::convert::TryFrom; use std::sync::Arc; use std::time::Duration; +use task::ShutdownListener; use tungstenite::protocol::Message; #[cfg(not(target_arch = "wasm32"))] @@ -65,6 +66,10 @@ pub struct GatewayClient { reconnection_attempts: usize, /// Delay between each subsequent reconnection attempt. reconnection_backoff: Duration, + + /// Listen to shutdown messages. This is an option since we don't require it when for example + /// when doing initial authentication. + shutdown: Option, } impl GatewayClient { @@ -80,6 +85,7 @@ impl GatewayClient { ack_sender: AcknowledgementSender, response_timeout_duration: Duration, bandwidth_controller: Option>, + shutdown: Option, ) -> Self { GatewayClient { authenticated: false, @@ -97,6 +103,7 @@ impl GatewayClient { should_reconnect_on_failure: true, reconnection_attempts: DEFAULT_RECONNECTION_ATTEMPTS, reconnection_backoff: DEFAULT_RECONNECTION_BACKOFF, + shutdown, } } @@ -148,6 +155,7 @@ impl GatewayClient { should_reconnect_on_failure: false, reconnection_attempts: DEFAULT_RECONNECTION_ATTEMPTS, reconnection_backoff: DEFAULT_RECONNECTION_BACKOFF, + shutdown: None, } } @@ -298,7 +306,7 @@ impl GatewayClient { } _ => (), } - } + } } } } @@ -723,6 +731,7 @@ impl GatewayClient { .as_ref() .expect("no shared key present even though we're authenticated!"), ), + self.shutdown.clone(), ) } _ => unreachable!(), diff --git a/common/client-libs/gateway-client/src/socket_state.rs b/common/client-libs/gateway-client/src/socket_state.rs index b4e1aef8f2..3326d17c45 100644 --- a/common/client-libs/gateway-client/src/socket_state.rs +++ b/common/client-libs/gateway-client/src/socket_state.rs @@ -11,6 +11,7 @@ use gateway_requests::registration::handshake::SharedKeys; use gateway_requests::BinaryResponse; use log::*; use std::sync::Arc; +use task::ShutdownListener; use tungstenite::Message; #[cfg(not(target_arch = "wasm32"))] @@ -86,6 +87,7 @@ impl PartiallyDelegated { conn: WsConn, packet_router: PacketRouter, shared_key: Arc, + shutdown: Option, ) -> Self { // when called for, it NEEDS TO yield back the stream so that we could merge it and // read control request responses. @@ -98,9 +100,15 @@ impl PartiallyDelegated { let mut fused_receiver = notify_receiver.fuse(); let mut fused_stream = (&mut stream).fuse(); + // Bit of an ugly workaround for selecting on an `Option`. The unwrap is lazy so we use + // this bool inside the `select` to guard against unwrapping in the `None` case. + let shutdown_is_some = shutdown.is_some(); + let shutdown_recv_lazy = async { shutdown.unwrap().recv().await }; + tokio::pin!(shutdown_recv_lazy); + let ret_err = loop { - futures::select! { - _ = fused_receiver => { + tokio::select! { + _ = &mut fused_receiver => { break Ok(()); } msg = fused_stream.next() => { @@ -110,6 +118,11 @@ impl PartiallyDelegated { }; Self::route_socket_message(ws_msg, &packet_router, shared_key.as_ref()); } + _ = &mut shutdown_recv_lazy, if shutdown_is_some => { + log::trace!("GatewayClient listener: Received shutdown"); + log::debug!("GatewayClient listener: Exiting"); + return; + } }; }; diff --git a/common/socks5/proxy-helpers/Cargo.toml b/common/socks5/proxy-helpers/Cargo.toml index 92ac6a2bae..99ce5f3559 100644 --- a/common/socks5/proxy-helpers/Cargo.toml +++ b/common/socks5/proxy-helpers/Cargo.toml @@ -16,6 +16,7 @@ futures = "0.3" log = "0.4" socks5-requests = { path = "../requests" } ordered-buffer = { path = "../ordered-buffer" } +task = { path = "../../task" } [dev-dependencies] tokio-test = "0.4.2" diff --git a/common/socks5/proxy-helpers/src/connection_controller.rs b/common/socks5/proxy-helpers/src/connection_controller.rs index 03f3d4b5cc..32b44b674e 100644 --- a/common/socks5/proxy-helpers/src/connection_controller.rs +++ b/common/socks5/proxy-helpers/src/connection_controller.rs @@ -170,16 +170,23 @@ impl Controller { } pub async fn run(&mut self) { - while let Some(command) = self.receiver.next().await { - match command { - ControllerCommand::Send(conn_id, data, is_closed) => { - self.send_to_connection(conn_id, data, is_closed) + loop { + tokio::select! { + command = self.receiver.next() => match command { + Some(ControllerCommand::Send(conn_id, data, is_closed)) => { + self.send_to_connection(conn_id, data, is_closed) + } + Some(ControllerCommand::Insert(conn_id, sender)) => { + self.insert_connection(conn_id, sender) + } + Some(ControllerCommand::Remove(conn_id)) => self.remove_connection(conn_id), + None => { + log::trace!("SOCKS5 Controller: Stopping since channel closed"); + break; + } } - ControllerCommand::Insert(conn_id, sender) => { - self.insert_connection(conn_id, sender) - } - ControllerCommand::Remove(conn_id) => self.remove_connection(conn_id), } } + log::debug!("SOCKS5 Controller: Exiting"); } } diff --git a/common/socks5/proxy-helpers/src/proxy_runner/inbound.rs b/common/socks5/proxy-helpers/src/proxy_runner/inbound.rs index 979ae918c4..5efc297ce7 100644 --- a/common/socks5/proxy-helpers/src/proxy_runner/inbound.rs +++ b/common/socks5/proxy-helpers/src/proxy_runner/inbound.rs @@ -11,6 +11,7 @@ use log::*; use ordered_buffer::OrderedMessageSender; use socks5_requests::ConnectionId; use std::{io, sync::Arc}; +use task::ShutdownListener; use tokio::select; use tokio::{net::tcp::OwnedReadHalf, sync::Notify, time::sleep}; @@ -74,6 +75,7 @@ where is_finished } +#[allow(clippy::too_many_arguments)] pub(super) async fn run_inbound( mut reader: OwnedReadHalf, local_destination_address: String, // addresses are provided for better logging @@ -82,6 +84,7 @@ pub(super) async fn run_inbound( mix_sender: MixProxySender, adapter_fn: F, shutdown_notify: Arc, + mut shutdown_listener: ShutdownListener, ) -> OwnedReadHalf where F: Fn(ConnectionId, Vec, bool) -> S + Send + 'static, @@ -106,6 +109,10 @@ where send_empty_close(connection_id, &mut message_sender, &mix_sender, &adapter_fn); break; } + _ = shutdown_listener.recv() => { + log::trace!("ProxyRunner inbound: Received shutdown"); + break; + } } } trace!("{} - inbound closed", connection_id); diff --git a/common/socks5/proxy-helpers/src/proxy_runner/mod.rs b/common/socks5/proxy-helpers/src/proxy_runner/mod.rs index d31ef8ced7..1d5b493ced 100644 --- a/common/socks5/proxy-helpers/src/proxy_runner/mod.rs +++ b/common/socks5/proxy-helpers/src/proxy_runner/mod.rs @@ -5,6 +5,7 @@ use crate::connection_controller::ConnectionReceiver; use futures::channel::mpsc; use socks5_requests::ConnectionId; use std::{sync::Arc, time::Duration}; +use task::ShutdownListener; use tokio::{net::TcpStream, sync::Notify}; mod inbound; @@ -44,6 +45,9 @@ pub struct ProxyRunner { local_destination_address: String, remote_source_address: String, connection_id: ConnectionId, + + // Listens to shutdown commands from higher up + shutdown_listener: ShutdownListener, } impl ProxyRunner @@ -57,6 +61,7 @@ where mix_receiver: ConnectionReceiver, mix_sender: MixProxySender, connection_id: ConnectionId, + shutdown_listener: ShutdownListener, ) -> Self { ProxyRunner { mix_receiver: Some(mix_receiver), @@ -65,6 +70,7 @@ where local_destination_address, remote_source_address, connection_id, + shutdown_listener, } } @@ -86,6 +92,7 @@ where self.mix_sender.clone(), adapter_fn, Arc::clone(&shutdown_notify), + self.shutdown_listener.clone(), ); let outbound_future = outbound::run_outbound( @@ -95,6 +102,7 @@ where self.mix_receiver.take().unwrap(), self.connection_id, shutdown_notify, + self.shutdown_listener.clone(), ); // TODO: this shouldn't really have to spawn tasks inside "library" code, but diff --git a/common/socks5/proxy-helpers/src/proxy_runner/outbound.rs b/common/socks5/proxy-helpers/src/proxy_runner/outbound.rs index 111bc6bf9e..8fad665785 100644 --- a/common/socks5/proxy-helpers/src/proxy_runner/outbound.rs +++ b/common/socks5/proxy-helpers/src/proxy_runner/outbound.rs @@ -8,6 +8,7 @@ use futures::StreamExt; use log::*; use socks5_requests::ConnectionId; use std::{sync::Arc, time::Duration}; +use task::ShutdownListener; use tokio::io::AsyncWriteExt; use tokio::select; use tokio::{net::tcp::OwnedWriteHalf, sync::Notify, time::sleep, time::Instant}; @@ -50,6 +51,7 @@ pub(super) async fn run_outbound( mut mix_receiver: ConnectionReceiver, connection_id: ConnectionId, shutdown_notify: Arc, + mut shutdown_listener: ShutdownListener, ) -> (OwnedWriteHalf, ConnectionReceiver) { let shutdown_future = shutdown_notify.notified().then(|_| sleep(SHUTDOWN_TIMEOUT)); tokio::pin!(shutdown_future); @@ -78,6 +80,10 @@ pub(super) async fn run_outbound( debug!("closing outbound proxy after inbound was closed {:?} ago", SHUTDOWN_TIMEOUT); break; } + _ = shutdown_listener.recv() => { + log::trace!("ProxyRunner outbound: Received shutdown"); + break; + } } } diff --git a/common/task/src/lib.rs b/common/task/src/lib.rs index b983af29db..b8ddb7076a 100644 --- a/common/task/src/lib.rs +++ b/common/task/src/lib.rs @@ -2,5 +2,7 @@ // SPDX-License-Identifier: Apache-2.0 pub mod shutdown; +pub mod signal; pub use shutdown::{ShutdownListener, ShutdownNotifier}; +pub use signal::wait_for_signal; diff --git a/common/task/src/shutdown.rs b/common/task/src/shutdown.rs index 1fe873e9aa..92696e8a23 100644 --- a/common/task/src/shutdown.rs +++ b/common/task/src/shutdown.rs @@ -92,6 +92,25 @@ impl ShutdownListener { let _ = self.notify.changed().await; self.shutdown = true; } + + pub fn is_shutdown_poll(&mut self) -> bool { + if self.shutdown { + return true; + } + match self.notify.has_changed() { + Ok(has_changed) => { + if has_changed { + self.shutdown = true; + } + has_changed + } + Err(err) => { + log::debug!("Polling shutdown failed: {err}"); + log::debug!("Assuming this means we should shutdown..."); + true + } + } + } } #[cfg(test)] diff --git a/common/task/src/signal.rs b/common/task/src/signal.rs new file mode 100644 index 0000000000..40ca122848 --- /dev/null +++ b/common/task/src/signal.rs @@ -0,0 +1,27 @@ +#[cfg(unix)] +pub async fn wait_for_signal() { + use tokio::signal::unix::{signal, SignalKind}; + let mut sigterm = signal(SignalKind::terminate()).expect("Failed to setup SIGTERM channel"); + let mut sigquit = signal(SignalKind::quit()).expect("Failed to setup SIGQUIT channel"); + + tokio::select! { + _ = tokio::signal::ctrl_c() => { + log::info!("Received SIGINT"); + }, + _ = sigterm.recv() => { + log::info!("Received SIGTERM"); + } + _ = sigquit.recv() => { + log::info!("Received SIGQUIT"); + } + } +} + +#[cfg(not(unix))] +pub async fn wait_for_signal() { + tokio::select! { + _ = tokio::signal::ctrl_c() => { + log::info!("Received SIGINT"); + }, + } +} diff --git a/mixnode/src/node/mod.rs b/mixnode/src/node/mod.rs index f2d3635139..c27fd93037 100644 --- a/mixnode/src/node/mod.rs +++ b/mixnode/src/node/mod.rs @@ -26,7 +26,7 @@ use rand::thread_rng; use std::net::SocketAddr; use std::process; use std::sync::Arc; -use task::{ShutdownListener, ShutdownNotifier}; +use task::{wait_for_signal, ShutdownListener, ShutdownNotifier}; use version_checker::parse_version; mod http; @@ -334,31 +334,3 @@ impl MixNode { self.wait_for_interrupt(shutdown).await } } - -#[cfg(unix)] -async fn wait_for_signal() { - use tokio::signal::unix::{signal, SignalKind}; - let mut sigterm = signal(SignalKind::terminate()).expect("Failed to setup SIGTERM channel"); - let mut sigquit = signal(SignalKind::quit()).expect("Failed to setup SIGQUIT channel"); - - tokio::select! { - _ = tokio::signal::ctrl_c() => { - log::info!("Received SIGINT"); - }, - _ = sigterm.recv() => { - log::info!("Received SIGTERM"); - } - _ = sigquit.recv() => { - log::info!("Received SIGQUIT"); - } - } -} - -#[cfg(not(unix))] -async fn wait_for_signal() { - tokio::select! { - _ = tokio::signal::ctrl_c() => { - log::info!("Received SIGINT"); - }, - } -} diff --git a/nym-connect/Cargo.lock b/nym-connect/Cargo.lock index 008d909765..2944a49719 100644 --- a/nym-connect/Cargo.lock +++ b/nym-connect/Cargo.lock @@ -630,6 +630,7 @@ dependencies = [ "serde", "sled", "tap", + "task", "thiserror", "tokio", "topology", @@ -1921,8 +1922,10 @@ dependencies = [ "pemstore", "rand 0.7.3", "secp256k1", + "task", "thiserror", "tokio", + "tokio-stream", "tokio-tungstenite", "tungstenite", "url", @@ -3461,6 +3464,7 @@ dependencies = [ "serde", "snafu", "socks5-requests", + "task", "tokio", "topology", "url", @@ -4268,6 +4272,7 @@ dependencies = [ "log", "ordered-buffer", "socks5-requests", + "task", "tokio", "tokio-util 0.7.3", ] @@ -5626,6 +5631,15 @@ dependencies = [ "xattr", ] +[[package]] +name = "task" +version = "0.1.0" +dependencies = [ + "log", + "tokio", + "tokio-util 0.7.3", +] + [[package]] name = "tauri" version = "1.0.3" @@ -6072,6 +6086,7 @@ dependencies = [ "futures-core", "pin-project-lite", "tokio", + "tokio-util 0.7.3", ] [[package]] diff --git a/service-providers/network-requester/Cargo.toml b/service-providers/network-requester/Cargo.toml index 0c5a5d6b12..1806a75ac4 100644 --- a/service-providers/network-requester/Cargo.toml +++ b/service-providers/network-requester/Cargo.toml @@ -34,4 +34,5 @@ ordered-buffer = {path = "../../common/socks5/ordered-buffer"} proxy-helpers = { path = "../../common/socks5/proxy-helpers" } socks5-requests = { path = "../../common/socks5/requests" } statistics-common = { path = "../../common/statistics" } +task = { path = "../../common/task" } websocket-requests = { path = "../../clients/native/websocket-requests" } diff --git a/service-providers/network-requester/src/connection.rs b/service-providers/network-requester/src/connection.rs index 9d4374f76e..5c5fea04b4 100644 --- a/service-providers/network-requester/src/connection.rs +++ b/service-providers/network-requester/src/connection.rs @@ -7,6 +7,7 @@ use proxy_helpers::connection_controller::ConnectionReceiver; use proxy_helpers::proxy_runner::ProxyRunner; use socks5_requests::{ConnectionId, Message as Socks5Message, RemoteAddress, Response}; use std::io; +use task::ShutdownListener; use tokio::net::TcpStream; /// A TCP connection between the Socks5 service provider, which makes @@ -40,6 +41,7 @@ impl Connection { &mut self, mix_receiver: ConnectionReceiver, mix_sender: mpsc::UnboundedSender<(Socks5Message, Recipient)>, + shutdown: ShutdownListener, ) { let stream = self.conn.take().unwrap(); let remote_source_address = "???".to_string(); // we don't know ip address of requester @@ -52,6 +54,7 @@ impl Connection { mix_receiver, mix_sender, connection_id, + shutdown, ) .run(move |conn_id, read_data, socket_closed| { ( diff --git a/service-providers/network-requester/src/core.rs b/service-providers/network-requester/src/core.rs index c3bf589a65..ee2c064443 100644 --- a/service-providers/network-requester/src/core.rs +++ b/service-providers/network-requester/src/core.rs @@ -19,6 +19,7 @@ use socks5_requests::{ use statistics_common::collector::StatisticsSender; use std::path::PathBuf; use std::sync::atomic::{AtomicUsize, Ordering}; +use task::ShutdownListener; use tokio_tungstenite::tungstenite::protocol::Message; use websocket::WebsocketConnectionError; use websocket_requests::{requests::ClientRequest, responses::ServerResponse}; @@ -134,6 +135,7 @@ impl ServiceProvider { return_address: Recipient, controller_sender: ControllerSender, mix_input_sender: mpsc::UnboundedSender<(Socks5Message, Recipient)>, + shutdown: ShutdownListener, ) { let mut conn = match Connection::new(conn_id, remote_addr.clone(), return_address).await { Ok(conn) => conn, @@ -170,7 +172,8 @@ impl ServiceProvider { ); // run the proxy on the connection - conn.run_proxy(mix_receiver, mix_input_sender).await; + conn.run_proxy(mix_receiver, mix_input_sender, shutdown) + .await; // proxy is done - remove the access channel from the controller controller_sender @@ -192,6 +195,7 @@ impl ServiceProvider { conn_id: ConnectionId, remote_addr: String, return_address: Recipient, + shutdown: ShutdownListener, ) { if !self.open_proxy && !self.outbound_request_filter.check(&remote_addr) { let log_msg = format!("Domain {:?} failed filter check", remote_addr); @@ -218,6 +222,7 @@ impl ServiceProvider { return_address, controller_sender_clone, mix_input_sender_clone, + shutdown, ) .await }); @@ -241,6 +246,7 @@ impl ServiceProvider { controller_sender: &mut ControllerSender, mix_input_sender: &mpsc::UnboundedSender<(Socks5Message, Recipient)>, stats_collector: Option, + shutdown: ShutdownListener, ) { let deserialized_msg = match Socks5Message::try_from_bytes(raw_request) { Ok(msg) => msg, @@ -265,6 +271,7 @@ impl ServiceProvider { req.conn_id, req.remote_addr, req.return_address, + shutdown, ) } @@ -302,7 +309,10 @@ impl ServiceProvider { let (mix_input_sender, mix_input_receiver) = mpsc::unbounded::<(Socks5Message, Recipient)>(); - // controller for managing all active connections + // Controller for managing all active connections. + // We provide it with a ShutdownListener since it requires it, even though for the network + // requester shutdown signalling is not yet fully implemented. + let shutdown = task::ShutdownNotifier::default(); let (mut active_connections_controller, mut controller_sender) = Controller::new(); tokio::spawn(async move { active_connections_controller.run().await; @@ -353,6 +363,7 @@ impl ServiceProvider { &mut controller_sender, &mix_input_sender, stats_collector.clone(), + shutdown.subscribe(), ) .await; } diff --git a/validator-api/src/network_monitor/monitor/sender.rs b/validator-api/src/network_monitor/monitor/sender.rs index c11f38b826..3689a4b6db 100644 --- a/validator-api/src/network_monitor/monitor/sender.rs +++ b/validator-api/src/network_monitor/monitor/sender.rs @@ -209,6 +209,7 @@ impl PacketSender { // currently we do not care about acks at all, but we must keep the channel alive // so that the gateway client would not crash let (ack_sender, ack_receiver) = mpsc::unbounded(); + let mut gateway_client = GatewayClient::new( address, Arc::clone(&fresh_gateway_client_data.local_identity), @@ -219,6 +220,7 @@ impl PacketSender { ack_sender, fresh_gateway_client_data.gateway_response_timeout, Some(fresh_gateway_client_data.bandwidth_controller.clone()), + None, ); gateway_client From 04e5cfabb8f582a8b903760d454699ffdfa05715 Mon Sep 17 00:00:00 2001 From: =?UTF-8?q?Jon=20H=C3=A4ggblad?= Date: Tue, 6 Sep 2022 12:49:59 +0200 Subject: [PATCH 19/46] changelog: add note --- CHANGELOG.md | 2 ++ 1 file changed, 2 insertions(+) diff --git a/CHANGELOG.md b/CHANGELOG.md index 0b9a93a151..197d79ada8 100644 --- a/CHANGELOG.md +++ b/CHANGELOG.md @@ -12,10 +12,12 @@ Post 1.0.0 release, the changelog format is based on [Keep a Changelog](https:// ### Changed - validator-client: made `fee` argument optional for `execute` and `execute_multiple` ([#1541]) +- socks5 client: graceful shutdown should fix error on disconnect in nym-connect ([#1591]) [#1541]: https://github.com/nymtech/nym/pull/1541 [#1558]: https://github.com/nymtech/nym/pull/1558 [#1577]: https://github.com/nymtech/nym/pull/1577 +[#1591]: https://github.com/nymtech/nym/pull/1591 ## [nym-binaries-1.0.2](https://github.com/nymtech/nym/tree/nym-binaries-1.0.2) From 46135146eaddf8d20b7f1db7805dd123fbbb7f23 Mon Sep 17 00:00:00 2001 From: =?UTF-8?q?Jon=20H=C3=A4ggblad?= Date: Tue, 6 Sep 2022 13:00:41 +0200 Subject: [PATCH 20/46] clippy --- clients/client-core/src/client/cover_traffic_stream.rs | 1 + 1 file changed, 1 insertion(+) diff --git a/clients/client-core/src/client/cover_traffic_stream.rs b/clients/client-core/src/client/cover_traffic_stream.rs index 9370b5c6ce..3aaf6da053 100644 --- a/clients/client-core/src/client/cover_traffic_stream.rs +++ b/clients/client-core/src/client/cover_traffic_stream.rs @@ -88,6 +88,7 @@ where // obviously when we finally make shared rng that is on 'higher' level, this should become // generic `R` impl LoopCoverTrafficStream { + #[allow(clippy::too_many_arguments)] pub fn new( ack_key: Arc, average_ack_delay: time::Duration, From 106491ef01756e33b74351c029815e4aa6db2461 Mon Sep 17 00:00:00 2001 From: =?UTF-8?q?Jon=20H=C3=A4ggblad?= Date: Tue, 6 Sep 2022 13:57:18 +0200 Subject: [PATCH 21/46] more clippy --- .../real_messages_control/acknowledgement_control/mod.rs | 8 +++----- .../retransmission_request_listener.rs | 1 + 2 files changed, 4 insertions(+), 5 deletions(-) diff --git a/clients/client-core/src/client/real_messages_control/acknowledgement_control/mod.rs b/clients/client-core/src/client/real_messages_control/acknowledgement_control/mod.rs index 17b406cd07..9314519a8a 100644 --- a/clients/client-core/src/client/real_messages_control/acknowledgement_control/mod.rs +++ b/clients/client-core/src/client/real_messages_control/acknowledgement_control/mod.rs @@ -153,6 +153,7 @@ impl AcknowledgementController where R: 'static + CryptoRng + Rng + Clone + Send, { + #[allow(clippy::too_many_arguments)] pub(super) fn new( config: Config, rng: R, @@ -212,11 +213,8 @@ where // will listen for events indicating the packet was sent through the network so that // the retransmission timer should be started. - let sent_notification_listener = SentNotificationListener::new( - connectors.sent_notifier, - action_sender, - shutdown.clone(), - ); + let sent_notification_listener = + SentNotificationListener::new(connectors.sent_notifier, action_sender, shutdown); AcknowledgementController { acknowledgement_listener: Some(acknowledgement_listener), diff --git a/clients/client-core/src/client/real_messages_control/acknowledgement_control/retransmission_request_listener.rs b/clients/client-core/src/client/real_messages_control/acknowledgement_control/retransmission_request_listener.rs index 650f21c0fd..840ea09c2e 100644 --- a/clients/client-core/src/client/real_messages_control/acknowledgement_control/retransmission_request_listener.rs +++ b/clients/client-core/src/client/real_messages_control/acknowledgement_control/retransmission_request_listener.rs @@ -35,6 +35,7 @@ impl RetransmissionRequestListener where R: CryptoRng + Rng, { + #[allow(clippy::too_many_arguments)] pub(super) fn new( ack_key: Arc, ack_recipient: Recipient, From baed6c89fccad7eec3bb6cc1e42726b8e44f83a8 Mon Sep 17 00:00:00 2001 From: =?UTF-8?q?Jon=20H=C3=A4ggblad?= Date: Wed, 7 Sep 2022 17:01:52 +0200 Subject: [PATCH 22/46] socks5: assert that tasks are not exiting when not shutdown --- Cargo.lock | 4 ++-- clients/client-core/src/client/cover_traffic_stream.rs | 1 + clients/client-core/src/client/mix_traffic.rs | 1 + clients/client-core/src/client/mod.rs | 7 +++++++ .../acknowledgement_control/acknowledgement_listener.rs | 1 + .../acknowledgement_control/action_controller.rs | 1 + .../acknowledgement_control/input_message_listener.rs | 1 + .../retransmission_request_listener.rs | 1 + .../acknowledgement_control/sent_notification_listener.rs | 1 + .../client/real_messages_control/real_traffic_stream.rs | 1 + clients/client-core/src/client/received_buffer.rs | 4 ++++ clients/client-core/src/client/topology_control.rs | 1 + clients/socks5/src/client/mod.rs | 3 +++ clients/socks5/src/socks/mixnet_responses.rs | 6 ++++-- clients/socks5/src/socks/server.rs | 3 ++- common/socks5/proxy-helpers/src/connection_controller.rs | 7 ++++++- service-providers/network-requester/src/core.rs | 3 ++- 17 files changed, 39 insertions(+), 7 deletions(-) diff --git a/Cargo.lock b/Cargo.lock index d3b3155c34..dbfc5b52ad 100644 --- a/Cargo.lock +++ b/Cargo.lock @@ -2059,8 +2059,8 @@ dependencies = [ "thiserror", "tokio", "tokio-stream", - "tokio-tungstenite", - "tungstenite", + "tokio-tungstenite 0.14.0", + "tungstenite 0.13.0", "url", "validator-client", "wasm-bindgen", diff --git a/clients/client-core/src/client/cover_traffic_stream.rs b/clients/client-core/src/client/cover_traffic_stream.rs index 3aaf6da053..1b3f5fec3a 100644 --- a/clients/client-core/src/client/cover_traffic_stream.rs +++ b/clients/client-core/src/client/cover_traffic_stream.rs @@ -180,6 +180,7 @@ impl LoopCoverTrafficStream { } } } + assert!(self.shutdown.is_shutdown_poll()); log::debug!("LoopCoverTrafficStream: Exiting"); } diff --git a/clients/client-core/src/client/mix_traffic.rs b/clients/client-core/src/client/mix_traffic.rs index cbd1d413cb..9a3e70a0d6 100644 --- a/clients/client-core/src/client/mix_traffic.rs +++ b/clients/client-core/src/client/mix_traffic.rs @@ -86,6 +86,7 @@ impl MixTrafficController { } } } + assert!(self.shutdown.is_shutdown_poll()); log::debug!("MixTrafficController: Exiting"); } diff --git a/clients/client-core/src/client/mod.rs b/clients/client-core/src/client/mod.rs index 510c072073..fdbe732826 100644 --- a/clients/client-core/src/client/mod.rs +++ b/clients/client-core/src/client/mod.rs @@ -1,3 +1,5 @@ +use std::sync::atomic::AtomicBool; + pub mod cover_traffic_stream; pub mod inbound_messages; pub mod key_manager; @@ -6,3 +8,8 @@ pub mod real_messages_control; pub mod received_buffer; pub mod reply_key_storage; pub mod topology_control; + +// This is *NOT* used to signal shutdown, it's used to assert that tasks finishing are doing so +// because shutdown has been signalled. +// In particular for tasks that rely on their associated channel being closed to signal shutdown. +pub static SHUTDOWN_HAS_BEEN_SIGNALLED: AtomicBool = AtomicBool::new(false); diff --git a/clients/client-core/src/client/real_messages_control/acknowledgement_control/acknowledgement_listener.rs b/clients/client-core/src/client/real_messages_control/acknowledgement_control/acknowledgement_listener.rs index 964617c5b0..9df98afaf0 100644 --- a/clients/client-core/src/client/real_messages_control/acknowledgement_control/acknowledgement_listener.rs +++ b/clients/client-core/src/client/real_messages_control/acknowledgement_control/acknowledgement_listener.rs @@ -82,6 +82,7 @@ impl AcknowledgementListener { } } } + assert!(self.shutdown.is_shutdown_poll()); log::debug!("AcknowledgementListener: Exiting"); } } diff --git a/clients/client-core/src/client/real_messages_control/acknowledgement_control/action_controller.rs b/clients/client-core/src/client/real_messages_control/acknowledgement_control/action_controller.rs index a11fe49f5d..3bbf978c1a 100644 --- a/clients/client-core/src/client/real_messages_control/acknowledgement_control/action_controller.rs +++ b/clients/client-core/src/client/real_messages_control/acknowledgement_control/action_controller.rs @@ -264,6 +264,7 @@ impl ActionController { } } } + assert!(self.shutdown.is_shutdown_poll()); log::debug!("ActionController: Exiting"); } } diff --git a/clients/client-core/src/client/real_messages_control/acknowledgement_control/input_message_listener.rs b/clients/client-core/src/client/real_messages_control/acknowledgement_control/input_message_listener.rs index 35d5ccdcf6..5311b515af 100644 --- a/clients/client-core/src/client/real_messages_control/acknowledgement_control/input_message_listener.rs +++ b/clients/client-core/src/client/real_messages_control/acknowledgement_control/input_message_listener.rs @@ -196,6 +196,7 @@ where } } } + assert!(self.shutdown.is_shutdown_poll()); log::debug!("InputMessageListener: Exiting"); } } diff --git a/clients/client-core/src/client/real_messages_control/acknowledgement_control/retransmission_request_listener.rs b/clients/client-core/src/client/real_messages_control/acknowledgement_control/retransmission_request_listener.rs index 840ea09c2e..ee62f1e2b0 100644 --- a/clients/client-core/src/client/real_messages_control/acknowledgement_control/retransmission_request_listener.rs +++ b/clients/client-core/src/client/real_messages_control/acknowledgement_control/retransmission_request_listener.rs @@ -137,6 +137,7 @@ where } } } + assert!(self.shutdown.is_shutdown_poll()); log::debug!("RetransmissionRequestListener: Exiting"); } } diff --git a/clients/client-core/src/client/real_messages_control/acknowledgement_control/sent_notification_listener.rs b/clients/client-core/src/client/real_messages_control/acknowledgement_control/sent_notification_listener.rs index 4c33d1b609..a4247be245 100644 --- a/clients/client-core/src/client/real_messages_control/acknowledgement_control/sent_notification_listener.rs +++ b/clients/client-core/src/client/real_messages_control/acknowledgement_control/sent_notification_listener.rs @@ -58,6 +58,7 @@ impl SentNotificationListener { } } } + assert!(self.shutdown.is_shutdown_poll()); log::debug!("SentNotificationListener: Exiting"); } } diff --git a/clients/client-core/src/client/real_messages_control/real_traffic_stream.rs b/clients/client-core/src/client/real_messages_control/real_traffic_stream.rs index cb27cc2779..6ca4f04aea 100644 --- a/clients/client-core/src/client/real_messages_control/real_traffic_stream.rs +++ b/clients/client-core/src/client/real_messages_control/real_traffic_stream.rs @@ -283,6 +283,7 @@ where }, } } + assert!(shutdown.is_shutdown_poll()); log::debug!("OutQueueControl: Exiting"); } diff --git a/clients/client-core/src/client/received_buffer.rs b/clients/client-core/src/client/received_buffer.rs index fb51c9a703..b116617f4e 100644 --- a/clients/client-core/src/client/received_buffer.rs +++ b/clients/client-core/src/client/received_buffer.rs @@ -1,6 +1,7 @@ // Copyright 2021 - Nym Technologies SA // SPDX-License-Identifier: Apache-2.0 +use crate::client::SHUTDOWN_HAS_BEEN_SIGNALLED; use crate::client::reply_key_storage::ReplyKeyStorage; use crypto::asymmetric::encryption; use crypto::symmetric::stream_cipher; @@ -15,6 +16,7 @@ use nymsphinx::params::{ReplySurbEncryptionAlgorithm, ReplySurbKeyDigestAlgorith use nymsphinx::receiver::{MessageReceiver, MessageRecoveryError, ReconstructedMessage}; use std::collections::HashSet; use std::sync::Arc; +use std::sync::atomic::Ordering; use task::ShutdownListener; use tokio::task::JoinHandle; @@ -312,6 +314,7 @@ impl RequestReceiver { }; } + assert!(SHUTDOWN_HAS_BEEN_SIGNALLED.load(Ordering::Relaxed)); log::debug!("RequestReceiver: Exiting"); }) } @@ -353,6 +356,7 @@ impl FragmentedMessageReceiver { } } } + assert!(self.shutdown.is_shutdown_poll()); log::debug!("FragmentedMessageReceiver: Exiting"); }) } diff --git a/clients/client-core/src/client/topology_control.rs b/clients/client-core/src/client/topology_control.rs index 089b3bd0d2..b7bc7325fb 100644 --- a/clients/client-core/src/client/topology_control.rs +++ b/clients/client-core/src/client/topology_control.rs @@ -316,6 +316,7 @@ impl TopologyRefresher { }, } } + assert!(shutdown.is_shutdown_poll()); log::debug!("TopologyRefresher: Exiting"); }) } diff --git a/clients/socks5/src/client/mod.rs b/clients/socks5/src/client/mod.rs index bd8b60cf27..2ecec048b9 100644 --- a/clients/socks5/src/client/mod.rs +++ b/clients/socks5/src/client/mod.rs @@ -1,6 +1,8 @@ // Copyright 2021 - Nym Technologies SA // SPDX-License-Identifier: Apache-2.0 +use std::sync::atomic::{AtomicBool, Ordering}; + use client_core::client::cover_traffic_stream::LoopCoverTrafficStream; use client_core::client::inbound_messages::{ InputMessage, InputMessageReceiver, InputMessageSender, @@ -290,6 +292,7 @@ impl NymClient { wait_for_signal().await; log::info!("Sending shutdown"); + client_core::client::SHUTDOWN_HAS_BEEN_SIGNALLED.store(true, Ordering::Relaxed); shutdown.signal_shutdown().ok(); log::info!("Waiting for tasks to finish... (Press ctrl-c to force)"); diff --git a/clients/socks5/src/socks/mixnet_responses.rs b/clients/socks5/src/socks/mixnet_responses.rs index 29f9186448..2bef34c152 100644 --- a/clients/socks5/src/socks/mixnet_responses.rs +++ b/clients/socks5/src/socks/mixnet_responses.rs @@ -1,8 +1,9 @@ -use client_core::client::received_buffer::ReconstructedMessagesReceiver; -use client_core::client::received_buffer::{ReceivedBufferMessage, ReceivedBufferRequestSender}; use futures::channel::mpsc; use futures::StreamExt; use log::*; + +use client_core::client::received_buffer::ReconstructedMessagesReceiver; +use client_core::client::received_buffer::{ReceivedBufferMessage, ReceivedBufferRequestSender}; use nymsphinx::receiver::ReconstructedMessage; use proxy_helpers::connection_controller::{ControllerCommand, ControllerSender}; use socks5_requests::Message; @@ -89,6 +90,7 @@ impl MixnetResponseListener { } } } + assert!(self.shutdown.is_shutdown_poll()); log::debug!("MixnetResponseListener: Exiting"); } } diff --git a/clients/socks5/src/socks/server.rs b/clients/socks5/src/socks/server.rs index 4282b72207..c8feebbfb1 100644 --- a/clients/socks5/src/socks/server.rs +++ b/clients/socks5/src/socks/server.rs @@ -56,7 +56,8 @@ impl SphinxSocksServer { info!("Serving Connections..."); // controller for managing all active connections - let (mut active_streams_controller, controller_sender) = Controller::new(); + let (mut active_streams_controller, controller_sender) = + Controller::new(self.shutdown.clone()); tokio::spawn(async move { active_streams_controller.run().await; }); diff --git a/common/socks5/proxy-helpers/src/connection_controller.rs b/common/socks5/proxy-helpers/src/connection_controller.rs index 32b44b674e..0eebf8d994 100644 --- a/common/socks5/proxy-helpers/src/connection_controller.rs +++ b/common/socks5/proxy-helpers/src/connection_controller.rs @@ -7,6 +7,7 @@ use log::*; use ordered_buffer::{OrderedMessage, OrderedMessageBuffer}; use socks5_requests::ConnectionId; use std::collections::{HashMap, HashSet}; +use task::ShutdownListener; /// A generic message produced after reading from a socket/connection. It includes data that was /// actually read alongside boolean indicating whether the connection got closed so that @@ -74,10 +75,12 @@ pub struct Controller { // buffer for messages received before connection was established due to mixnet being able to // un-order messages. Note we don't ever expect to have more than 1-2 messages per connection here pending_messages: HashMap, bool)>>, + + shutdown: ShutdownListener, } impl Controller { - pub fn new() -> (Self, ControllerSender) { + pub fn new(shutdown: ShutdownListener) -> (Self, ControllerSender) { let (sender, receiver) = mpsc::unbounded(); ( Controller { @@ -85,6 +88,7 @@ impl Controller { receiver, recently_closed: HashSet::new(), pending_messages: HashMap::new(), + shutdown, }, sender, ) @@ -187,6 +191,7 @@ impl Controller { } } } + assert!(self.shutdown.is_shutdown_poll()); log::debug!("SOCKS5 Controller: Exiting"); } } diff --git a/service-providers/network-requester/src/core.rs b/service-providers/network-requester/src/core.rs index ee2c064443..3431e61c03 100644 --- a/service-providers/network-requester/src/core.rs +++ b/service-providers/network-requester/src/core.rs @@ -313,7 +313,8 @@ impl ServiceProvider { // We provide it with a ShutdownListener since it requires it, even though for the network // requester shutdown signalling is not yet fully implemented. let shutdown = task::ShutdownNotifier::default(); - let (mut active_connections_controller, mut controller_sender) = Controller::new(); + let (mut active_connections_controller, mut controller_sender) = + Controller::new(shutdown.subscribe()); tokio::spawn(async move { active_connections_controller.run().await; }); From d109c53370e9f10759a3899263102807d1e8ed37 Mon Sep 17 00:00:00 2001 From: =?UTF-8?q?Jon=20H=C3=A4ggblad?= Date: Thu, 8 Sep 2022 15:08:15 +0200 Subject: [PATCH 23/46] socks5: tasks with closed channels should all exit --- .../src/client/cover_traffic_stream.rs | 3 +++ clients/client-core/src/client/mod.rs | 8 ++++--- .../acknowledgement_listener.rs | 14 +++++++++---- .../action_controller.rs | 21 ++++++++++++++----- .../input_message_listener.rs | 10 +++++++-- .../retransmission_request_listener.rs | 8 +++++-- .../sent_notification_listener.rs | 10 +++++++-- .../real_traffic_stream.rs | 12 ++++++++--- clients/socks5/src/client/mod.rs | 6 ++++-- clients/socks5/src/socks/mixnet_responses.rs | 12 ++++++++--- 10 files changed, 78 insertions(+), 26 deletions(-) diff --git a/clients/client-core/src/client/cover_traffic_stream.rs b/clients/client-core/src/client/cover_traffic_stream.rs index 1b3f5fec3a..8e25357e00 100644 --- a/clients/client-core/src/client/cover_traffic_stream.rs +++ b/clients/client-core/src/client/cover_traffic_stream.rs @@ -176,6 +176,9 @@ impl LoopCoverTrafficStream { next = self.next() => { if next.is_some() { self.on_new_message().await; + } else { + log::trace!("LoopCoverTrafficStream: Stopping since channel closed"); + break; } } } diff --git a/clients/client-core/src/client/mod.rs b/clients/client-core/src/client/mod.rs index fdbe732826..6edb810bc8 100644 --- a/clients/client-core/src/client/mod.rs +++ b/clients/client-core/src/client/mod.rs @@ -9,7 +9,9 @@ pub mod received_buffer; pub mod reply_key_storage; pub mod topology_control; -// This is *NOT* used to signal shutdown, it's used to assert that tasks finishing are doing so -// because shutdown has been signalled. -// In particular for tasks that rely on their associated channel being closed to signal shutdown. +// This is *NOT* used to signal shutdown. +// It's critical that we don't have any tasks finishing early, this is an additional safety check +// that tasks exiting are doing so because shutdown has been signalled, and no other reason. +// In particular for tasks that rely on their associated channel being closed to signal shutdown, +// and don't have access to a shutdown listener channel. pub static SHUTDOWN_HAS_BEEN_SIGNALLED: AtomicBool = AtomicBool::new(false); diff --git a/clients/client-core/src/client/real_messages_control/acknowledgement_control/acknowledgement_listener.rs b/clients/client-core/src/client/real_messages_control/acknowledgement_control/acknowledgement_listener.rs index 9df98afaf0..97f80474bb 100644 --- a/clients/client-core/src/client/real_messages_control/acknowledgement_control/acknowledgement_listener.rs +++ b/clients/client-core/src/client/real_messages_control/acknowledgement_control/acknowledgement_listener.rs @@ -71,10 +71,16 @@ impl AcknowledgementListener { debug!("Started AcknowledgementListener"); while !self.shutdown.is_shutdown() { tokio::select! { - Some(acks) = self.ack_receiver.next() => { - // realistically we would only be getting one ack at the time - for ack in acks { - self.on_ack(ack).await; + acks = self.ack_receiver.next() => match acks { + Some(acks) => { + // realistically we would only be getting one ack at the time + for ack in acks { + self.on_ack(ack).await; + } + }, + None => { + log::trace!("AcknowledgementListener: Stopping since channel closed"); + break; } }, _ = self.shutdown.recv() => { diff --git a/clients/client-core/src/client/real_messages_control/acknowledgement_control/action_controller.rs b/clients/client-core/src/client/real_messages_control/acknowledgement_control/action_controller.rs index 3bbf978c1a..ca22780d92 100644 --- a/clients/client-core/src/client/real_messages_control/acknowledgement_control/action_controller.rs +++ b/clients/client-core/src/client/real_messages_control/acknowledgement_control/action_controller.rs @@ -254,11 +254,22 @@ impl ActionController { pub(super) async fn run(&mut self) { while !self.shutdown.is_shutdown() { tokio::select! { - // we NEVER expect for ANY sender to get dropped so unwrap here is fine - action = self.incoming_actions.next() => self.process_action(action.unwrap()), - // pending ack queue Stream CANNOT return a `None` so unwrap here is fine - expired_ack = self.pending_acks_timers.next() => self.handle_expired_ack_timer(expired_ack.unwrap()), - // listen for shutdown notifications + action = self.incoming_actions.next() => match action { + Some(action) => self.process_action(action), + None => { + log::trace!( + "ActionController: Stopping since incoming actions channel closed" + ); + break; + } + }, + expired_ack = self.pending_acks_timers.next() => match expired_ack { + Some(expired_ack) => self.handle_expired_ack_timer(expired_ack), + None => { + log::trace!("ActionController: Stopping since ack channel closed"); + break; + } + }, _ = self.shutdown.recv() => { log::trace!("ActionController: Received shutdown"); } diff --git a/clients/client-core/src/client/real_messages_control/acknowledgement_control/input_message_listener.rs b/clients/client-core/src/client/real_messages_control/acknowledgement_control/input_message_listener.rs index 5311b515af..611b43d02b 100644 --- a/clients/client-core/src/client/real_messages_control/acknowledgement_control/input_message_listener.rs +++ b/clients/client-core/src/client/real_messages_control/acknowledgement_control/input_message_listener.rs @@ -188,8 +188,14 @@ where debug!("Started InputMessageListener"); while !self.shutdown.is_shutdown() { tokio::select! { - Some(input_msg) = self.input_receiver.next() => { - self.on_input_message(input_msg).await; + input_msg = self.input_receiver.next() => match input_msg { + Some(input_msg) => { + self.on_input_message(input_msg).await; + }, + None => { + log::trace!("InputMessageListener: Stopping since channel closed"); + break; + } }, _ = self.shutdown.recv() => { log::trace!("InputMessageListener: Received shutdown"); diff --git a/clients/client-core/src/client/real_messages_control/acknowledgement_control/retransmission_request_listener.rs b/clients/client-core/src/client/real_messages_control/acknowledgement_control/retransmission_request_listener.rs index ee62f1e2b0..d5d433fa9f 100644 --- a/clients/client-core/src/client/real_messages_control/acknowledgement_control/retransmission_request_listener.rs +++ b/clients/client-core/src/client/real_messages_control/acknowledgement_control/retransmission_request_listener.rs @@ -129,8 +129,12 @@ where while !self.shutdown.is_shutdown() { tokio::select! { - Some(timed_out_ack) = self.request_receiver.next() => { - self.on_retransmission_request(timed_out_ack).await; + timed_out_ack = self.request_receiver.next() => match timed_out_ack { + Some(timed_out_ack) => self.on_retransmission_request(timed_out_ack).await, + None => { + log::trace!("RetransmissionRequestListener: Stopping since channel closed"); + break; + } }, _ = self.shutdown.recv() => { log::trace!("RetransmissionRequestListener: Received shutdown"); diff --git a/clients/client-core/src/client/real_messages_control/acknowledgement_control/sent_notification_listener.rs b/clients/client-core/src/client/real_messages_control/acknowledgement_control/sent_notification_listener.rs index a4247be245..692a28a6ab 100644 --- a/clients/client-core/src/client/real_messages_control/acknowledgement_control/sent_notification_listener.rs +++ b/clients/client-core/src/client/real_messages_control/acknowledgement_control/sent_notification_listener.rs @@ -50,8 +50,14 @@ impl SentNotificationListener { debug!("Started SentNotificationListener"); while !self.shutdown.is_shutdown() { tokio::select! { - Some(frag_id) = self.sent_notifier.next() => { - self.on_sent_message(frag_id).await; + frag_id = self.sent_notifier.next() => match frag_id { + Some(frag_id) => { + self.on_sent_message(frag_id).await; + } + None => { + log::trace!("SentNotificationListener: Stopping since channel closed"); + break; + } }, _ = self.shutdown.recv() => { log::trace!("SentNotificationListener: Received shutdown"); diff --git a/clients/client-core/src/client/real_messages_control/real_traffic_stream.rs b/clients/client-core/src/client/real_messages_control/real_traffic_stream.rs index 6ca4f04aea..5585044654 100644 --- a/clients/client-core/src/client/real_messages_control/real_traffic_stream.rs +++ b/clients/client-core/src/client/real_messages_control/real_traffic_stream.rs @@ -278,9 +278,15 @@ where _ = shutdown.recv() => { log::trace!("OutQueueControl: Received shutdown"); } - Some(next_message) = self.next() => { - self.on_message(next_message).await; - }, + next_message = self.next() => match next_message { + Some(next_message) => { + self.on_message(next_message).await; + }, + None => { + log::trace!("OutQueueControl: Stopping since channel closed"); + break; + } + } } } assert!(shutdown.is_shutdown_poll()); diff --git a/clients/socks5/src/client/mod.rs b/clients/socks5/src/client/mod.rs index 2ecec048b9..c121b82734 100644 --- a/clients/socks5/src/client/mod.rs +++ b/clients/socks5/src/client/mod.rs @@ -1,7 +1,7 @@ // Copyright 2021 - Nym Technologies SA // SPDX-License-Identifier: Apache-2.0 -use std::sync::atomic::{AtomicBool, Ordering}; +use std::sync::atomic::Ordering; use client_core::client::cover_traffic_stream::LoopCoverTrafficStream; use client_core::client::inbound_messages::{ @@ -311,7 +311,9 @@ impl NymClient { Some(Socks5ControlMessage::Stop) => { log::info!("Received stop message"); } - None => log::debug!("None"), + None => { + log::info!("Channel closed, stopping"); + } } } _ = tokio::signal::ctrl_c() => { diff --git a/clients/socks5/src/socks/mixnet_responses.rs b/clients/socks5/src/socks/mixnet_responses.rs index 2bef34c152..5bd83bee85 100644 --- a/clients/socks5/src/socks/mixnet_responses.rs +++ b/clients/socks5/src/socks/mixnet_responses.rs @@ -80,9 +80,15 @@ impl MixnetResponseListener { pub(crate) async fn run(&mut self) { while !self.shutdown.is_shutdown() { tokio::select! { - Some(received_responses) = self.mix_response_receiver.next() => { - for reconstructed_message in received_responses { - self.on_message(reconstructed_message).await; + received_responses = self.mix_response_receiver.next() => match received_responses { + Some(received_responses) => { + for reconstructed_message in received_responses { + self.on_message(reconstructed_message).await; + } + }, + None => { + log::trace!("MixnetResponseListener: Stopping since channel closed"); + break; } }, _ = self.shutdown.recv() => { From e0567dddf2fc425fc2497f8e5ffdb85abb2e72c6 Mon Sep 17 00:00:00 2001 From: =?UTF-8?q?Jon=20H=C3=A4ggblad?= Date: Thu, 8 Sep 2022 15:42:21 +0200 Subject: [PATCH 24/46] gateway-client: additional shutdown handling --- .../client-core/src/client/received_buffer.rs | 4 +- clients/client-core/src/init.rs | 1 + .../client-libs/gateway-client/src/client.rs | 28 ++++++++++---- .../client-libs/gateway-client/src/error.rs | 6 +++ .../gateway-client/src/packet_router.rs | 37 +++++++++++++------ .../gateway-client/src/socket_state.rs | 37 +++++++++++-------- common/task/src/shutdown.rs | 2 +- 7 files changed, 78 insertions(+), 37 deletions(-) diff --git a/clients/client-core/src/client/received_buffer.rs b/clients/client-core/src/client/received_buffer.rs index b116617f4e..567302121f 100644 --- a/clients/client-core/src/client/received_buffer.rs +++ b/clients/client-core/src/client/received_buffer.rs @@ -1,8 +1,8 @@ // Copyright 2021 - Nym Technologies SA // SPDX-License-Identifier: Apache-2.0 -use crate::client::SHUTDOWN_HAS_BEEN_SIGNALLED; use crate::client::reply_key_storage::ReplyKeyStorage; +use crate::client::SHUTDOWN_HAS_BEEN_SIGNALLED; use crypto::asymmetric::encryption; use crypto::symmetric::stream_cipher; use crypto::Digest; @@ -15,8 +15,8 @@ use nymsphinx::anonymous_replies::{encryption_key::EncryptionKeyDigest, SurbEncr use nymsphinx::params::{ReplySurbEncryptionAlgorithm, ReplySurbKeyDigestAlgorithm}; use nymsphinx::receiver::{MessageReceiver, MessageRecoveryError, ReconstructedMessage}; use std::collections::HashSet; -use std::sync::Arc; use std::sync::atomic::Ordering; +use std::sync::Arc; use task::ShutdownListener; use tokio::task::JoinHandle; diff --git a/clients/client-core/src/init.rs b/clients/client-core/src/init.rs index 66ae845b04..a2e3ed22f7 100644 --- a/clients/client-core/src/init.rs +++ b/clients/client-core/src/init.rs @@ -90,6 +90,7 @@ async fn register_with_gateway( gateway.owner.clone(), our_identity.clone(), timeout, + None, ); gateway_client .establish_connection() diff --git a/common/client-libs/gateway-client/src/client.rs b/common/client-libs/gateway-client/src/client.rs index 658a314535..71eb795e65 100644 --- a/common/client-libs/gateway-client/src/client.rs +++ b/common/client-libs/gateway-client/src/client.rs @@ -67,8 +67,7 @@ pub struct GatewayClient { /// Delay between each subsequent reconnection attempt. reconnection_backoff: Duration, - /// Listen to shutdown messages. This is an option since we don't require it when for example - /// when doing initial authentication. + /// Listen to shutdown messages. shutdown: Option, } @@ -97,7 +96,7 @@ impl GatewayClient { local_identity, shared_key, connection: SocketState::NotConnected, - packet_router: PacketRouter::new(ack_sender, mixnet_message_sender), + packet_router: PacketRouter::new(ack_sender, mixnet_message_sender, shutdown.clone()), response_timeout_duration, bandwidth_controller, should_reconnect_on_failure: true, @@ -130,6 +129,7 @@ impl GatewayClient { gateway_owner: String, local_identity: Arc, response_timeout_duration: Duration, + shutdown: Option, ) -> Self { use futures::channel::mpsc; @@ -137,7 +137,7 @@ impl GatewayClient { // perfectly fine here, because it's not meant to be used let (ack_tx, _) = mpsc::unbounded(); let (mix_tx, _) = mpsc::unbounded(); - let packet_router = PacketRouter::new(ack_tx, mix_tx); + let packet_router = PacketRouter::new(ack_tx, mix_tx, shutdown.clone()); GatewayClient { authenticated: false, @@ -155,7 +155,7 @@ impl GatewayClient { should_reconnect_on_failure: false, reconnection_attempts: DEFAULT_RECONNECTION_ATTEMPTS, reconnection_backoff: DEFAULT_RECONNECTION_BACKOFF, - shutdown: None, + shutdown, } } @@ -287,8 +287,20 @@ impl GatewayClient { let mut fused_timeout = timeout.fuse(); let mut fused_stream = conn.fuse(); + // Bit of an ugly workaround for selecting on an `Option`. The unwrap is lazy so we use + // this bool inside the `select` to guard against unwrapping in the `None` case. + let shutdown_is_some = self.shutdown.is_some(); + let shutdown_recv_lazy = async { self.shutdown.clone().unwrap().recv().await }; + tokio::pin!(shutdown_recv_lazy); + loop { - futures::select! { + tokio::select! { + biased; + _ = &mut shutdown_recv_lazy, if shutdown_is_some => { + log::trace!("GatewayClient control response: Received shutdown"); + log::debug!("GatewayClient control response: Exiting"); + break Err(GatewayClientError::ConnectionClosedGatewayShutdown); + } _ = &mut fused_timeout => { break Err(GatewayClientError::Timeout); } @@ -299,7 +311,9 @@ impl GatewayClient { }; match ws_msg { Message::Binary(bin_msg) => { - self.packet_router.route_received(vec![bin_msg]); + if let Err(err) = self.packet_router.route_received(vec![bin_msg]) { + log::warn!("Route received failed: {:?}", err); + } } Message::Text(txt_msg) => { break ServerResponse::try_from(txt_msg).map_err(|_| GatewayClientError::MalformedResponse); diff --git a/common/client-libs/gateway-client/src/error.rs b/common/client-libs/gateway-client/src/error.rs index 0890dcd12a..bda9352a3b 100644 --- a/common/client-libs/gateway-client/src/error.rs +++ b/common/client-libs/gateway-client/src/error.rs @@ -64,6 +64,9 @@ pub enum GatewayClientError { #[error("Connection was abruptly closed")] ConnectionAbruptlyClosed, + #[error("Connection was abruptly closed as gateway was stopped")] + ConnectionClosedGatewayShutdown, + #[error("Received response was malformed")] MalformedResponse, @@ -93,6 +96,9 @@ pub enum GatewayClientError { #[error("Timed out")] Timeout, + + #[error("Failed to send mixnet message")] + MixnetMsgSenderFailedToSend, } impl GatewayClientError { diff --git a/common/client-libs/gateway-client/src/packet_router.rs b/common/client-libs/gateway-client/src/packet_router.rs index 7d650ad695..2605b291fb 100644 --- a/common/client-libs/gateway-client/src/packet_router.rs +++ b/common/client-libs/gateway-client/src/packet_router.rs @@ -8,6 +8,9 @@ use futures::channel::mpsc; use log::*; use nymsphinx::addressing::nodes::MAX_NODE_ADDRESS_UNPADDED_LEN; use nymsphinx::params::packet_sizes::PacketSize; +use task::ShutdownListener; + +use crate::error::GatewayClientError; pub type MixnetMessageSender = mpsc::UnboundedSender>>; pub type MixnetMessageReceiver = mpsc::UnboundedReceiver>>; @@ -19,20 +22,26 @@ pub type AcknowledgementReceiver = mpsc::UnboundedReceiver>>; pub struct PacketRouter { ack_sender: AcknowledgementSender, mixnet_message_sender: MixnetMessageSender, + shutdown: Option, } impl PacketRouter { pub fn new( ack_sender: AcknowledgementSender, mixnet_message_sender: MixnetMessageSender, + shutdown: Option, ) -> Self { PacketRouter { ack_sender, mixnet_message_sender, + shutdown, } } - pub fn route_received(&self, unwrapped_packets: Vec>) { + pub fn route_received( + &mut self, + unwrapped_packets: Vec>, + ) -> Result<(), GatewayClientError> { let mut received_messages = Vec::new(); let mut received_acks = Vec::new(); @@ -60,24 +69,28 @@ impl PacketRouter { } } - // due to how we are currently using it, those unwraps can't fail, but if we ever - // wanted to make `gateway-client` into some more generic library, we would probably need - // to catch that error or something. if !received_messages.is_empty() { trace!("routing 'real'"); - self.mixnet_message_sender - .unbounded_send(received_messages) - .unwrap(); + if let Err(err) = self.mixnet_message_sender.unbounded_send(received_messages) { + if let Some(shutdown) = &mut self.shutdown { + if shutdown.is_shutdown_poll() { + // This should ideally not happen, but it's ok + log::warn!("Failed to send mixnet message due to receiver task shutdown"); + return Err(GatewayClientError::MixnetMsgSenderFailedToSend); + } + } + // This should never happen during ordinary operation the way it's currently used. + // Abort to be on the safe side + panic!("Failed to send mixnet message: {:?}", err); + } } if !received_acks.is_empty() { trace!("routing acks"); - match self.ack_sender.unbounded_send(received_acks) { - Ok(_) => {} - Err(e) => { - error!("failed to send ack: {:?}", e); - } + if let Err(e) = self.ack_sender.unbounded_send(received_acks) { + error!("failed to send ack: {:?}", e); }; } + Ok(()) } } diff --git a/common/client-libs/gateway-client/src/socket_state.rs b/common/client-libs/gateway-client/src/socket_state.rs index 3326d17c45..e828f7dbbf 100644 --- a/common/client-libs/gateway-client/src/socket_state.rs +++ b/common/client-libs/gateway-client/src/socket_state.rs @@ -45,9 +45,9 @@ pub(crate) struct PartiallyDelegated { impl PartiallyDelegated { fn route_socket_message( ws_msg: Message, - packet_router: &PacketRouter, + packet_router: &mut PacketRouter, shared_key: &SharedKeys, - ) { + ) -> Result<(), GatewayClientError> { match ws_msg { Message::Binary(bin_msg) => { // this function decrypts the request and checks the MAC @@ -61,7 +61,7 @@ impl PartiallyDelegated { "message received from the gateway was malformed! - {:?}", err ); - return; + return Ok(()); } }; @@ -75,12 +75,15 @@ impl PartiallyDelegated { // This would also require NOT discarding any text responses here. // TODO: those can return the "send confirmations" - perhaps it should be somehow worked around? - Message::Text(text) => trace!( - "received a text message - probably a response to some previous query! - {}", - text - ), - _ => (), - }; + Message::Text(text) => { + trace!( + "received a text message - probably a response to some previous query! - {}", + text + ); + Ok(()) + } + _ => Ok(()), + } } pub(crate) fn split_and_listen_for_mixnet_messages( @@ -99,6 +102,7 @@ impl PartiallyDelegated { let mixnet_receiver_future = async move { let mut fused_receiver = notify_receiver.fuse(); let mut fused_stream = (&mut stream).fuse(); + let mut packet_router = packet_router; // Bit of an ugly workaround for selecting on an `Option`. The unwrap is lazy so we use // this bool inside the `select` to guard against unwrapping in the `None` case. @@ -108,6 +112,12 @@ impl PartiallyDelegated { let ret_err = loop { tokio::select! { + biased; + _ = &mut shutdown_recv_lazy, if shutdown_is_some => { + log::trace!("GatewayClient listener: Received shutdown"); + log::debug!("GatewayClient listener: Exiting"); + return; + } _ = &mut fused_receiver => { break Ok(()); } @@ -116,12 +126,9 @@ impl PartiallyDelegated { Err(err) => break Err(err), Ok(msg) => msg }; - Self::route_socket_message(ws_msg, &packet_router, shared_key.as_ref()); - } - _ = &mut shutdown_recv_lazy, if shutdown_is_some => { - log::trace!("GatewayClient listener: Received shutdown"); - log::debug!("GatewayClient listener: Exiting"); - return; + if let Err(err) = Self::route_socket_message(ws_msg, &mut packet_router, shared_key.as_ref()) { + log::warn!("Route socket message failed: {:?}", err); + } } }; }; diff --git a/common/task/src/shutdown.rs b/common/task/src/shutdown.rs index 92696e8a23..21ea12569d 100644 --- a/common/task/src/shutdown.rs +++ b/common/task/src/shutdown.rs @@ -74,7 +74,7 @@ pub struct ShutdownListener { } impl ShutdownListener { - pub fn new(notify: watch::Receiver<()>) -> ShutdownListener { + fn new(notify: watch::Receiver<()>) -> ShutdownListener { ShutdownListener { shutdown: false, notify, From 351adb7f7b10591bf7b47a44a83d8ea1f1f67d22 Mon Sep 17 00:00:00 2001 From: =?UTF-8?q?Jon=20H=C3=A4ggblad?= Date: Fri, 9 Sep 2022 13:02:53 +0200 Subject: [PATCH 25/46] socks5: add missing SHUTDOWN_HAS_BEEN_SIGNALLED.store --- clients/socks5/src/client/mod.rs | 1 + 1 file changed, 1 insertion(+) diff --git a/clients/socks5/src/client/mod.rs b/clients/socks5/src/client/mod.rs index c121b82734..12c38c8401 100644 --- a/clients/socks5/src/client/mod.rs +++ b/clients/socks5/src/client/mod.rs @@ -322,6 +322,7 @@ impl NymClient { } log::info!("Sending shutdown"); + client_core::client::SHUTDOWN_HAS_BEEN_SIGNALLED.store(true, Ordering::Relaxed); shutdown.signal_shutdown().ok(); log::info!("Waiting for tasks to finish... (Press ctrl-c to force)"); From f3ed0bb11f6412821d64340bf1f6d289d59d2274 Mon Sep 17 00:00:00 2001 From: =?UTF-8?q?Jon=20H=C3=A4ggblad?= Date: Fri, 9 Sep 2022 15:00:13 +0200 Subject: [PATCH 26/46] gateway-client: disable shutdown signalling for wasm --- common/client-libs/gateway-client/Cargo.toml | 4 +- .../client-libs/gateway-client/src/client.rs | 50 ++++++++++++++----- .../gateway-client/src/packet_router.rs | 6 ++- .../gateway-client/src/socket_state.rs | 30 +++++++---- 4 files changed, 67 insertions(+), 23 deletions(-) diff --git a/common/client-libs/gateway-client/Cargo.toml b/common/client-libs/gateway-client/Cargo.toml index d4688e9428..fa651db447 100644 --- a/common/client-libs/gateway-client/Cargo.toml +++ b/common/client-libs/gateway-client/Cargo.toml @@ -27,7 +27,6 @@ gateway-requests = { path = "../../../gateway/gateway-requests" } network-defaults = { path = "../../network-defaults" } nymsphinx = { path = "../../nymsphinx" } pemstore = { path = "../../pemstore" } -task = { path = "../../task" } validator-client = { path = "../validator-client", optional = true } [dependencies.tungstenite] @@ -49,6 +48,9 @@ version = "0.14" [target."cfg(not(target_arch = \"wasm32\"))".dependencies.credential-storage] path = "../../credential-storage" +[target."cfg(not(target_arch = \"wasm32\"))".dependencies.task] +path = "../../task" + # wasm-only dependencies [target."cfg(target_arch = \"wasm32\")".dependencies.wasm-bindgen] version = "0.2" diff --git a/common/client-libs/gateway-client/src/client.rs b/common/client-libs/gateway-client/src/client.rs index 71eb795e65..2c6226a013 100644 --- a/common/client-libs/gateway-client/src/client.rs +++ b/common/client-libs/gateway-client/src/client.rs @@ -30,6 +30,7 @@ use rand::rngs::OsRng; use std::convert::TryFrom; use std::sync::Arc; use std::time::Duration; +#[cfg(not(target_arch = "wasm32"))] use task::ShutdownListener; use tungstenite::protocol::Message; @@ -67,6 +68,7 @@ pub struct GatewayClient { /// Delay between each subsequent reconnection attempt. reconnection_backoff: Duration, + #[cfg(not(target_arch = "wasm32"))] /// Listen to shutdown messages. shutdown: Option, } @@ -84,7 +86,7 @@ impl GatewayClient { ack_sender: AcknowledgementSender, response_timeout_duration: Duration, bandwidth_controller: Option>, - shutdown: Option, + #[cfg(not(target_arch = "wasm32"))] shutdown: Option, ) -> Self { GatewayClient { authenticated: false, @@ -96,12 +98,18 @@ impl GatewayClient { local_identity, shared_key, connection: SocketState::NotConnected, - packet_router: PacketRouter::new(ack_sender, mixnet_message_sender, shutdown.clone()), + packet_router: PacketRouter::new( + ack_sender, + mixnet_message_sender, + #[cfg(not(target_arch = "wasm32"))] + shutdown.clone(), + ), response_timeout_duration, bandwidth_controller, should_reconnect_on_failure: true, reconnection_attempts: DEFAULT_RECONNECTION_ATTEMPTS, reconnection_backoff: DEFAULT_RECONNECTION_BACKOFF, + #[cfg(not(target_arch = "wasm32"))] shutdown, } } @@ -129,7 +137,7 @@ impl GatewayClient { gateway_owner: String, local_identity: Arc, response_timeout_duration: Duration, - shutdown: Option, + #[cfg(not(target_arch = "wasm32"))] shutdown: Option, ) -> Self { use futures::channel::mpsc; @@ -137,7 +145,12 @@ impl GatewayClient { // perfectly fine here, because it's not meant to be used let (ack_tx, _) = mpsc::unbounded(); let (mix_tx, _) = mpsc::unbounded(); - let packet_router = PacketRouter::new(ack_tx, mix_tx, shutdown.clone()); + let packet_router = PacketRouter::new( + ack_tx, + mix_tx, + #[cfg(not(target_arch = "wasm32"))] + shutdown.clone(), + ); GatewayClient { authenticated: false, @@ -155,6 +168,7 @@ impl GatewayClient { should_reconnect_on_failure: false, reconnection_attempts: DEFAULT_RECONNECTION_ATTEMPTS, reconnection_backoff: DEFAULT_RECONNECTION_BACKOFF, + #[cfg(not(target_arch = "wasm32"))] shutdown, } } @@ -287,16 +301,27 @@ impl GatewayClient { let mut fused_timeout = timeout.fuse(); let mut fused_stream = conn.fuse(); - // Bit of an ugly workaround for selecting on an `Option`. The unwrap is lazy so we use - // this bool inside the `select` to guard against unwrapping in the `None` case. - let shutdown_is_some = self.shutdown.is_some(); - let shutdown_recv_lazy = async { self.shutdown.clone().unwrap().recv().await }; - tokio::pin!(shutdown_recv_lazy); + // Bit of an ugly workaround for selecting on an `Option` without having access to + // `tokio::select` + #[cfg(not(target_arch = "wasm32"))] + let shutdown = { + let m_shutdown = self.shutdown.clone(); + async { + if let Some(mut s) = m_shutdown { + s.recv().await + } + } + .fuse() + }; + #[cfg(not(target_arch = "wasm32"))] + tokio::pin!(shutdown); + + #[cfg(target_arch = "wasm32")] + let mut shutdown = Box::pin(async {}.fuse()); loop { - tokio::select! { - biased; - _ = &mut shutdown_recv_lazy, if shutdown_is_some => { + futures::select! { + _ = shutdown => { log::trace!("GatewayClient control response: Received shutdown"); log::debug!("GatewayClient control response: Exiting"); break Err(GatewayClientError::ConnectionClosedGatewayShutdown); @@ -745,6 +770,7 @@ impl GatewayClient { .as_ref() .expect("no shared key present even though we're authenticated!"), ), + #[cfg(not(target_arch = "wasm32"))] self.shutdown.clone(), ) } diff --git a/common/client-libs/gateway-client/src/packet_router.rs b/common/client-libs/gateway-client/src/packet_router.rs index 2605b291fb..13977efdc7 100644 --- a/common/client-libs/gateway-client/src/packet_router.rs +++ b/common/client-libs/gateway-client/src/packet_router.rs @@ -8,6 +8,7 @@ use futures::channel::mpsc; use log::*; use nymsphinx::addressing::nodes::MAX_NODE_ADDRESS_UNPADDED_LEN; use nymsphinx::params::packet_sizes::PacketSize; +#[cfg(not(target_arch = "wasm32"))] use task::ShutdownListener; use crate::error::GatewayClientError; @@ -22,6 +23,7 @@ pub type AcknowledgementReceiver = mpsc::UnboundedReceiver>>; pub struct PacketRouter { ack_sender: AcknowledgementSender, mixnet_message_sender: MixnetMessageSender, + #[cfg(not(target_arch = "wasm32"))] shutdown: Option, } @@ -29,11 +31,12 @@ impl PacketRouter { pub fn new( ack_sender: AcknowledgementSender, mixnet_message_sender: MixnetMessageSender, - shutdown: Option, + #[cfg(not(target_arch = "wasm32"))] shutdown: Option, ) -> Self { PacketRouter { ack_sender, mixnet_message_sender, + #[cfg(not(target_arch = "wasm32"))] shutdown, } } @@ -72,6 +75,7 @@ impl PacketRouter { if !received_messages.is_empty() { trace!("routing 'real'"); if let Err(err) = self.mixnet_message_sender.unbounded_send(received_messages) { + #[cfg(not(target_arch = "wasm32"))] if let Some(shutdown) = &mut self.shutdown { if shutdown.is_shutdown_poll() { // This should ideally not happen, but it's ok diff --git a/common/client-libs/gateway-client/src/socket_state.rs b/common/client-libs/gateway-client/src/socket_state.rs index e828f7dbbf..8194f7c8c7 100644 --- a/common/client-libs/gateway-client/src/socket_state.rs +++ b/common/client-libs/gateway-client/src/socket_state.rs @@ -11,6 +11,7 @@ use gateway_requests::registration::handshake::SharedKeys; use gateway_requests::BinaryResponse; use log::*; use std::sync::Arc; +#[cfg(not(target_arch = "wasm32"))] use task::ShutdownListener; use tungstenite::Message; @@ -90,7 +91,7 @@ impl PartiallyDelegated { conn: WsConn, packet_router: PacketRouter, shared_key: Arc, - shutdown: Option, + #[cfg(not(target_arch = "wasm32"))] shutdown: Option, ) -> Self { // when called for, it NEEDS TO yield back the stream so that we could merge it and // read control request responses. @@ -104,16 +105,27 @@ impl PartiallyDelegated { let mut fused_stream = (&mut stream).fuse(); let mut packet_router = packet_router; - // Bit of an ugly workaround for selecting on an `Option`. The unwrap is lazy so we use - // this bool inside the `select` to guard against unwrapping in the `None` case. - let shutdown_is_some = shutdown.is_some(); - let shutdown_recv_lazy = async { shutdown.unwrap().recv().await }; - tokio::pin!(shutdown_recv_lazy); + // Bit of an ugly workaround for selecting on an `Option` without having access to + // `tokio::select` + #[cfg(not(target_arch = "wasm32"))] + let shutdown = { + let m_shutdown = shutdown.clone(); + async { + if let Some(mut s) = m_shutdown { + s.recv().await + } + } + .fuse() + }; + #[cfg(not(target_arch = "wasm32"))] + tokio::pin!(shutdown); + + #[cfg(target_arch = "wasm32")] + let mut shutdown = Box::pin(async {}.fuse()); let ret_err = loop { - tokio::select! { - biased; - _ = &mut shutdown_recv_lazy, if shutdown_is_some => { + futures::select! { + _ = shutdown => { log::trace!("GatewayClient listener: Received shutdown"); log::debug!("GatewayClient listener: Exiting"); return; From fdff4bf1b7a75747c0484db5ce48db5f23f54418 Mon Sep 17 00:00:00 2001 From: Mark Sinclair Date: Fri, 9 Sep 2022 14:47:17 +0100 Subject: [PATCH 27/46] Nym Wallet v1.0.9 (#1605) MIME-Version: 1.0 Content-Type: text/plain; charset=UTF-8 Content-Transfer-Encoding: 8bit * network-defaults: update mainnet default nymd_url * update tests * Bump nym-wallet version to 1.0.9 and update CHANGELOG Co-authored-by: Jon Häggblad --- clients/validator/tests/query/balance.test.ts | 4 ++-- common/network-defaults/src/mainnet.rs | 2 +- nym-wallet/CHANGELOG.md | 4 ++++ nym-wallet/Cargo.lock | 2 +- nym-wallet/src-tauri/Cargo.toml | 2 +- nym-wallet/src-tauri/src/config/mod.rs | 2 +- nym-wallet/src-tauri/src/state.rs | 4 ++-- nym-wallet/src-tauri/tauri.conf.json | 2 +- 8 files changed, 13 insertions(+), 9 deletions(-) diff --git a/clients/validator/tests/query/balance.test.ts b/clients/validator/tests/query/balance.test.ts index b9ed9e8737..254e54a745 100644 --- a/clients/validator/tests/query/balance.test.ts +++ b/clients/validator/tests/query/balance.test.ts @@ -4,8 +4,8 @@ import expect from 'expect'; describe('Query: balances', () => { it('can query for an account balance', async () => { const client = await ValidatorClient.connectForQuery( - 'https://rpc.nyx.nodes.guru/', 'https://validator.nymtech.net/api/', 'n', 'n14hj2tavq8fpesdwxxcu44rty3hh90vhujrvcmstl4zr3txmfvw9sjyvg3g', 'n1nc5tatafv6eyq7llkr2gv50ff9e22mnf70qgjlv737ktmt4eswrq73f2nw', 'nym'); + 'https://rpc.nymtech.net/', 'https://validator.nymtech.net/api/', 'n', 'n14hj2tavq8fpesdwxxcu44rty3hh90vhujrvcmstl4zr3txmfvw9sjyvg3g', 'n1nc5tatafv6eyq7llkr2gv50ff9e22mnf70qgjlv737ktmt4eswrq73f2nw', 'nym'); const balance = await client.getBalance('n10yyd98e2tuwu0f7ypz9dy3hhjw7v772q6287gy'); expect(Number.parseFloat(balance.amount)).toBeGreaterThan(0); }).timeout(5000); -}) \ No newline at end of file +}) diff --git a/common/network-defaults/src/mainnet.rs b/common/network-defaults/src/mainnet.rs index 4a59806183..53e85d8d89 100644 --- a/common/network-defaults/src/mainnet.rs +++ b/common/network-defaults/src/mainnet.rs @@ -25,7 +25,7 @@ pub(crate) const _ETH_ERC20_CONTRACT_ADDRESS: [u8; 20] = pub(crate) const REWARDING_VALIDATOR_ADDRESS: &str = "n10yyd98e2tuwu0f7ypz9dy3hhjw7v772q6287gy"; pub(crate) const STATISTICS_SERVICE_DOMAIN_ADDRESS: &str = "https://mainnet-stats.nymte.ch:8090/"; -pub const NYMD_VALIDATOR: &str = "https://rpc.nyx.nodes.guru/"; +pub const NYMD_VALIDATOR: &str = "https://rpc.nymtech.net"; pub const API_VALIDATOR: &str = "https://validator.nymtech.net/api/"; pub(crate) fn validators() -> Vec { vec![ValidatorDetails::new(NYMD_VALIDATOR, Some(API_VALIDATOR))] diff --git a/nym-wallet/CHANGELOG.md b/nym-wallet/CHANGELOG.md index b630e83b02..e3426d7d70 100644 --- a/nym-wallet/CHANGELOG.md +++ b/nym-wallet/CHANGELOG.md @@ -1,3 +1,7 @@ +## [nym-wallet-v1.0.9](https://github.com/nymtech/nym/releases/tag/nym-wallet-v1.0.8) (2022-09-08) + +- wallet: change default `nymd` URL to https://rpc.nymtech.net + ## [nym-wallet-v1.0.8](https://github.com/nymtech/nym/releases/tag/nym-wallet-v1.0.8) (2022-08-11) - wallet: new bonding flow and screen for bonded node diff --git a/nym-wallet/Cargo.lock b/nym-wallet/Cargo.lock index 1a48fd35b5..2eacccf667 100644 --- a/nym-wallet/Cargo.lock +++ b/nym-wallet/Cargo.lock @@ -3055,7 +3055,7 @@ dependencies = [ [[package]] name = "nym_wallet" -version = "1.0.8" +version = "1.0.9" dependencies = [ "aes-gcm", "argon2 0.3.4", diff --git a/nym-wallet/src-tauri/Cargo.toml b/nym-wallet/src-tauri/Cargo.toml index 1ecea8e852..86eccfc437 100644 --- a/nym-wallet/src-tauri/Cargo.toml +++ b/nym-wallet/src-tauri/Cargo.toml @@ -1,6 +1,6 @@ [package] name = "nym_wallet" -version = "1.0.8" +version = "1.0.9" description = "Nym Native Wallet" authors = ["Nym Technologies SA"] license = "" diff --git a/nym-wallet/src-tauri/src/config/mod.rs b/nym-wallet/src-tauri/src/config/mod.rs index 6ac65f3b45..8fcfc95a6c 100644 --- a/nym-wallet/src-tauri/src/config/mod.rs +++ b/nym-wallet/src-tauri/src/config/mod.rs @@ -552,7 +552,7 @@ api_url = 'https://baz/api' .next() .map(|v| v.nymd_url) .unwrap(); - assert_eq!(nymd_url.as_ref(), "https://rpc.nyx.nodes.guru/"); + assert_eq!(nymd_url.as_ref(), "https://rpc.nymtech.net/"); let api_url = config .get_base_validators(WalletNetwork::MAINNET) diff --git a/nym-wallet/src-tauri/src/state.rs b/nym-wallet/src-tauri/src/state.rs index 3abcb29324..458aa3e418 100644 --- a/nym-wallet/src-tauri/src/state.rs +++ b/nym-wallet/src-tauri/src/state.rs @@ -516,7 +516,7 @@ mod tests { "http://nymd_url.com/".parse().unwrap(), "http://foo.com".parse().unwrap(), "http://bar.com".parse().unwrap(), - "https://rpc.nyx.nodes.guru".parse().unwrap(), + "https://rpc.nymtech.net".parse().unwrap(), ], ); assert_eq!( @@ -538,7 +538,7 @@ mod tests { "http://nymd_url.com/".parse().unwrap(), "http://foo.com".parse().unwrap(), "http://bar.com".parse().unwrap(), - "https://rpc.nyx.nodes.guru".parse().unwrap(), + "https://rpc.nymtech.net".parse().unwrap(), ], ) } diff --git a/nym-wallet/src-tauri/tauri.conf.json b/nym-wallet/src-tauri/tauri.conf.json index 238f534a1a..035117f5d8 100644 --- a/nym-wallet/src-tauri/tauri.conf.json +++ b/nym-wallet/src-tauri/tauri.conf.json @@ -1,7 +1,7 @@ { "package": { "productName": "nym-wallet", - "version": "1.0.8" + "version": "1.0.9" }, "build": { "distDir": "../dist", From 20624243c0955db395505324e17843eb225f602f Mon Sep 17 00:00:00 2001 From: =?UTF-8?q?Jon=20H=C3=A4ggblad?= Date: Mon, 12 Sep 2022 10:38:30 +0200 Subject: [PATCH 28/46] ci: another ugly fix for windows low disk space Crazy. I hope we can get runners with more disk space soon --- .github/workflows/nightly_build.yml | 6 ++++++ 1 file changed, 6 insertions(+) diff --git a/.github/workflows/nightly_build.yml b/.github/workflows/nightly_build.yml index e03a57bbb5..8937d964bd 100644 --- a/.github/workflows/nightly_build.yml +++ b/.github/workflows/nightly_build.yml @@ -44,6 +44,12 @@ jobs: command: build args: --workspace + - name: Reclaim some disk space (because Windows is being annoying) + uses: actions-rs/cargo@v1 + if: ${{ matrix.os == 'windows-latest' }} + with: + command: clean + - name: Run all tests uses: actions-rs/cargo@v1 with: From b43657f42d402b4861221fa17303bd578c20259f Mon Sep 17 00:00:00 2001 From: Pierre Dommerc Date: Mon, 12 Sep 2022 12:32:10 +0200 Subject: [PATCH 29/46] feat(wallet): add tauri ops to sign and verify (#1606) MIME-Version: 1.0 Content-Type: text/plain; charset=UTF-8 Content-Transfer-Encoding: 8bit * Fix compile error * Expose signing wallet for signing client * Add stub tauri operation to sign a message with the current account * feat(wallet): add a request to verify a signature * feat(wallet): add support to verify from account address * feat(wallet): add support to verify from account address * fix(wallet): verify tauri request signature * wallet-recovery-cli: upgrade clap to 3.2 * Fix compile error * Expose signing wallet for signing client * Add stub tauri operation to sign a message with the current account * feat(wallet): add a request to verify a signature * feat(wallet): add support to verify from account address * feat(wallet): add support to verify from account address * fix(wallet): verify tauri request signature * Fix deserializtion of U128 * feat(wallet): avoid unwrap * refactor(wallet):suggested feedbacks Co-authored-by: Mark Sinclair Co-authored-by: Jon Häggblad Co-authored-by: durch --- .../validator-client/src/nymd/mod.rs | 7 + nym-wallet/Cargo.lock | 36 ++--- nym-wallet/src-tauri/Cargo.toml | 1 + nym-wallet/src-tauri/src/error.rs | 7 + nym-wallet/src-tauri/src/main.rs | 3 + nym-wallet/src-tauri/src/operations/mod.rs | 1 + .../src/operations/signatures/mod.rs | 1 + .../src/operations/signatures/sign.rs | 140 ++++++++++++++++++ nym-wallet/src/requests/index.ts | 1 + nym-wallet/src/requests/signature.ts | 9 ++ nym-wallet/wallet-recovery-cli/Cargo.toml | 2 +- nym-wallet/wallet-recovery-cli/src/main.rs | 6 +- 12 files changed, 193 insertions(+), 21 deletions(-) create mode 100644 nym-wallet/src-tauri/src/operations/signatures/mod.rs create mode 100644 nym-wallet/src-tauri/src/operations/signatures/sign.rs create mode 100644 nym-wallet/src/requests/signature.ts diff --git a/common/client-libs/validator-client/src/nymd/mod.rs b/common/client-libs/validator-client/src/nymd/mod.rs index d6c1d40c7f..e43db6a6a2 100644 --- a/common/client-libs/validator-client/src/nymd/mod.rs +++ b/common/client-libs/validator-client/src/nymd/mod.rs @@ -338,6 +338,13 @@ impl NymdClient { &self.client_address.as_ref().unwrap()[0] } + pub fn signer(&self) -> &DirectSecp256k1HdWallet + where + C: SigningCosmWasmClient, + { + self.client.signer() + } + pub fn gas_price(&self) -> &GasPrice where C: SigningCosmWasmClient, diff --git a/nym-wallet/Cargo.lock b/nym-wallet/Cargo.lock index 2eacccf667..36307fd9ed 100644 --- a/nym-wallet/Cargo.lock +++ b/nym-wallet/Cargo.lock @@ -645,16 +645,16 @@ dependencies = [ [[package]] name = "clap" -version = "3.1.18" +version = "3.2.20" source = "registry+https://github.com/rust-lang/crates.io-index" -checksum = "d2dbdf4bdacb33466e854ce889eee8dfd5729abf7ccd7664d0a2d60cd384440b" +checksum = "23b71c3ce99b7611011217b366d923f1d0a7e07a92bb2dbf1e84508c673ca3bd" dependencies = [ "atty", "bitflags", "clap_derive", "clap_lex", "indexmap", - "lazy_static", + "once_cell", "strsim 0.10.0", "termcolor", "textwrap", @@ -662,9 +662,9 @@ dependencies = [ [[package]] name = "clap_derive" -version = "3.1.18" +version = "3.2.18" source = "registry+https://github.com/rust-lang/crates.io-index" -checksum = "25320346e922cffe59c0bbc5410c8d8784509efb321488971081313cb1e1a33c" +checksum = "ea0c8bce528c4be4da13ea6fead8965e95b6073585a2f05204bd8f4119f82a65" dependencies = [ "heck 0.4.0", "proc-macro-error", @@ -675,9 +675,9 @@ dependencies = [ [[package]] name = "clap_lex" -version = "0.2.0" +version = "0.2.4" source = "registry+https://github.com/rust-lang/crates.io-index" -checksum = "a37c35f1112dad5e6e0b1adaff798507497a18fceeb30cceb3bae7d1427b9213" +checksum = "2850f2f5a82cbf437dd5af4d49848fbdfc27c157c3d010345776f952765261c5" dependencies = [ "os_str_bytes", ] @@ -756,9 +756,9 @@ dependencies = [ [[package]] name = "concurrent-queue" -version = "1.2.2" +version = "1.2.4" source = "registry+https://github.com/rust-lang/crates.io-index" -checksum = "30ed07550be01594c6026cff2a1d7fe9c8f683caa798e12b68694ac9e88286a3" +checksum = "af4780a44ab5696ea9e28294517f1fffb421a83a25af521333c838635509db9c" dependencies = [ "cache-padded", ] @@ -1456,9 +1456,9 @@ dependencies = [ [[package]] name = "enumflags2" -version = "0.7.4" +version = "0.7.5" source = "registry+https://github.com/rust-lang/crates.io-index" -checksum = "1b3ab37dc79652c9d85f1f7b6070d77d321d2467f5fe7b00d6b7a86c57b092ae" +checksum = "e75d4cd21b95383444831539909fbb14b9dc3fdceb2a6f5d36577329a1f55ccb" dependencies = [ "enumflags2_derive", "serde", @@ -1490,9 +1490,9 @@ dependencies = [ [[package]] name = "event-listener" -version = "2.5.2" +version = "2.5.3" source = "registry+https://github.com/rust-lang/crates.io-index" -checksum = "77f3309417938f28bf8228fcff79a4a37103981e3e186d2ccd19c74b38f4eb71" +checksum = "0206175f82b8d6bf6652ff7d71a1e27fd2e4efde587fd368662814d6ec1d9ce0" [[package]] name = "execute" @@ -3073,6 +3073,7 @@ dependencies = [ "eyre", "futures", "itertools", + "k256", "log", "mixnet-contract-common", "nym-types", @@ -3150,9 +3151,9 @@ dependencies = [ [[package]] name = "once_cell" -version = "1.9.0" +version = "1.14.0" source = "registry+https://github.com/rust-lang/crates.io-index" -checksum = "da32515d9f6e6e489d7bc9d84c71b060db7247dc035bbe44eac88cf87486d8d5" +checksum = "2f7254b99e31cad77da24b08ebf628882739a608578bb1bcdfc1f9c21260d7c0" [[package]] name = "opaque-debug" @@ -3605,10 +3606,11 @@ dependencies = [ [[package]] name = "polling" -version = "2.2.0" +version = "2.3.0" source = "registry+https://github.com/rust-lang/crates.io-index" -checksum = "685404d509889fade3e86fe3a5803bca2ec09b0c0778d5ada6ec8bf7a8de5259" +checksum = "899b00b9c8ab553c743b3e11e87c5c7d423b2a2de229ba95b24a756344748011" dependencies = [ + "autocfg 1.1.0", "cfg-if", "libc", "log", diff --git a/nym-wallet/src-tauri/Cargo.toml b/nym-wallet/src-tauri/Cargo.toml index 86eccfc437..451f5d0b9e 100644 --- a/nym-wallet/src-tauri/Cargo.toml +++ b/nym-wallet/src-tauri/Cargo.toml @@ -42,6 +42,7 @@ thiserror = "1.0" tokio = { version = "1.10", features = ["full"] } toml = "0.5.8" url = "2.2" +k256 = { version = "0.10", features = ["ecdsa", "sha256"] } aes-gcm = "0.9.4" argon2 = { version = "0.3.2", features = ["std"] } diff --git a/nym-wallet/src-tauri/src/error.rs b/nym-wallet/src-tauri/src/error.rs index 64a9bd7fe1..8232d6f5c0 100644 --- a/nym-wallet/src-tauri/src/error.rs +++ b/nym-wallet/src-tauri/src/error.rs @@ -69,6 +69,11 @@ pub enum BackendError { #[from] source: reqwest::Error, }, + #[error("{source}")] + K256Error { + #[from] + source: k256::ecdsa::Error, + }, #[error("failed to encrypt the given data with the provided password")] EncryptionError, #[error("failed to decrypt the given data with the provided password")] @@ -111,6 +116,8 @@ pub enum BackendError { UnknownCoinDenom(String), #[error("Network {network} doesn't have any associated registered coin denoms")] NoCoinsRegistered { network: Network }, + #[error("Signature error {0}")] + SignatureError(String), } impl Serialize for BackendError { diff --git a/nym-wallet/src-tauri/src/main.rs b/nym-wallet/src-tauri/src/main.rs index 488b26e7a9..59b215f890 100644 --- a/nym-wallet/src-tauri/src/main.rs +++ b/nym-wallet/src-tauri/src/main.rs @@ -18,6 +18,7 @@ mod wallet_storage; use crate::menu::AddDefaultSubmenus; use crate::operations::mixnet; +use crate::operations::signatures; use crate::operations::simulate; use crate::operations::validator_api; use crate::operations::vesting; @@ -146,6 +147,8 @@ fn main() { simulate::mixnet::simulate_claim_operator_reward, simulate::mixnet::simulate_compound_operator_reward, simulate::mixnet::simulate_compound_delegator_reward, + signatures::sign::sign, + signatures::sign::verify, ]) .menu(Menu::new().add_default_app_submenu_if_macos()) .run(tauri::generate_context!()) diff --git a/nym-wallet/src-tauri/src/operations/mod.rs b/nym-wallet/src-tauri/src/operations/mod.rs index a0720b85b0..795a431a9a 100644 --- a/nym-wallet/src-tauri/src/operations/mod.rs +++ b/nym-wallet/src-tauri/src/operations/mod.rs @@ -1,4 +1,5 @@ pub mod mixnet; +pub mod signatures; pub mod simulate; pub mod validator_api; pub mod vesting; diff --git a/nym-wallet/src-tauri/src/operations/signatures/mod.rs b/nym-wallet/src-tauri/src/operations/signatures/mod.rs new file mode 100644 index 0000000000..66ccbc9eb6 --- /dev/null +++ b/nym-wallet/src-tauri/src/operations/signatures/mod.rs @@ -0,0 +1 @@ +pub mod sign; diff --git a/nym-wallet/src-tauri/src/operations/signatures/sign.rs b/nym-wallet/src-tauri/src/operations/signatures/sign.rs new file mode 100644 index 0000000000..4ebca7aa56 --- /dev/null +++ b/nym-wallet/src-tauri/src/operations/signatures/sign.rs @@ -0,0 +1,140 @@ +use std::str::FromStr; + +use crate::error::BackendError; +use crate::state::WalletState; +use cosmrs::crypto::secp256k1::{Signature, VerifyingKey}; +use cosmrs::crypto::PublicKey; +use cosmrs::AccountId; +use k256::ecdsa::signature::Verifier; +use serde::Serialize; +use serde_json::json; + +#[derive(Debug, Serialize)] +pub struct SignatureOutputJson { + pub account_id: String, + pub public_key: PublicKey, + pub signature: String, +} + +#[tauri::command] +pub async fn sign( + message: String, + state: tauri::State<'_, WalletState>, +) -> Result { + let guard = state.read().await; + let client = guard.current_client()?; + let wallet = client.nymd.signer(); + let derived_accounts = wallet.try_derive_accounts()?; + let account = derived_accounts.first().ok_or_else(|| { + log::error!(">>> Unable to derive account"); + BackendError::SignatureError("unable to derive account".to_string()) + })?; + + log::info!("<<< Signing message"); + let signature = wallet.sign_raw_with_account(account, message.as_bytes())?; + let signature_as_hex_string = signature.to_string(); + let output = SignatureOutputJson { + account_id: account.address().to_string(), + public_key: account.public_key(), + signature: signature_as_hex_string.to_string(), + }; + log::info!(">>> Signing data {}", json!(output),); + Ok(signature_as_hex_string) +} + +async fn get_pubkey_from_account_address( + address: &AccountId, + state: &tauri::State<'_, WalletState>, +) -> Result { + log::info!("Getting public key for address {} from chain...", address); + let guard = state.read().await; + let client = guard.current_client()?; + let account = client + .nymd + .get_account_details(address) + .await? + .ok_or_else(|| { + log::error!("No account associated with address {}", address); + BackendError::SignatureError(format!("No account associated with address {}", address)) + })?; + let base_account = account.try_get_base_account()?; + + base_account.pubkey.ok_or_else(|| { + log::error!("No pubkey found for address {}", address); + BackendError::SignatureError(format!("No pubkey found for address {}", address)) + }) +} + +enum VerifyInputKind { + PublicKey(PublicKey), + AccountAddress(String), + CurrentAccountAddress, +} + +impl TryFrom> for VerifyInputKind { + type Error = BackendError; + + fn try_from(value: Option) -> Result { + let key = match value { + Some(key) => key, + None => return Ok(VerifyInputKind::CurrentAccountAddress), + }; + if key.trim().is_empty() { + return Err(BackendError::SignatureError( + "Please ensure the public key or address is not empty or whitespace".to_string(), + )); + } + let account_id = AccountId::from_str(&key); + let key_from_json = PublicKey::from_json(&key); + if account_id.is_err() && key_from_json.is_err() { + return Err(BackendError::SignatureError( + "Please ensure the public key or address is valid".to_string(), + )); + } + if let Ok(k) = key_from_json { + Ok(VerifyInputKind::PublicKey(k)) + } else { + Ok(VerifyInputKind::AccountAddress(key)) + } + } +} + +#[tauri::command] +pub async fn verify( + public_key_as_json_or_account_address: Option, + signature_as_hex: String, + message: String, + state: tauri::State<'_, WalletState>, +) -> Result<(), BackendError> { + let public_key = match VerifyInputKind::try_from(public_key_as_json_or_account_address)? { + VerifyInputKind::PublicKey(key) => key, + VerifyInputKind::AccountAddress(address) => { + // get public key from the given account address + get_pubkey_from_account_address(&AccountId::from_str(&address)?, &state).await? + } + VerifyInputKind::CurrentAccountAddress => { + // get public key from current account address + let guard = state.read().await; + let client = guard.current_client()?; + let address = client.nymd.address(); + get_pubkey_from_account_address(address, &state).await? + } + }; + + if public_key.type_url() != PublicKey::SECP256K1_TYPE_URL { + return Err(BackendError::SignatureError( + "Sorry, we only support secp256k1 public keys at the moment".to_string(), + )); + } + + log::info!("<<< Verifying signature [{}]", signature_as_hex); + let verifying_key = VerifyingKey::from_sec1_bytes(&public_key.to_bytes())?; + let signature = Signature::from_str(&signature_as_hex)?; + let message_as_bytes = message.into_bytes(); + Ok(verifying_key + .verify(&message_as_bytes, &signature) + .map_err(|e| { + log::error!(">>> Verification failed, wrong signature"); + e + })?) +} diff --git a/nym-wallet/src/requests/index.ts b/nym-wallet/src/requests/index.ts index aec40a78b4..d808caf4da 100644 --- a/nym-wallet/src/requests/index.ts +++ b/nym-wallet/src/requests/index.ts @@ -8,3 +8,4 @@ export * from './utils'; export * from './delegation'; export * from './rewards'; export * from './simulate'; +export * from './signature'; diff --git a/nym-wallet/src/requests/signature.ts b/nym-wallet/src/requests/signature.ts new file mode 100644 index 0000000000..cf36289088 --- /dev/null +++ b/nym-wallet/src/requests/signature.ts @@ -0,0 +1,9 @@ +import { invokeWrapper } from './wrapper'; + +export const sign = async (message: string): Promise => invokeWrapper('sign', { message }); + +export const verify = async ( + signatureAsHex: string, + message: string, + publicKeyAsJsonOrAccountAddress?: string | null, +): Promise => invokeWrapper('verify', { publicKeyAsJsonOrAccountAddress, signatureAsHex, message }); diff --git a/nym-wallet/wallet-recovery-cli/Cargo.toml b/nym-wallet/wallet-recovery-cli/Cargo.toml index c56f9a6068..45d17723b3 100644 --- a/nym-wallet/wallet-recovery-cli/Cargo.toml +++ b/nym-wallet/wallet-recovery-cli/Cargo.toml @@ -11,7 +11,7 @@ anyhow = "1.0" argon2 = "0.4" base64 = "0.13" bip39 = "1.0" -clap = { version = "3.0", features = ["derive"] } +clap = { version = "3.2.20", features = ["derive"] } log = "0.4" pretty_env_logger = "0.4" serde_json = "1.0.0" diff --git a/nym-wallet/wallet-recovery-cli/src/main.rs b/nym-wallet/wallet-recovery-cli/src/main.rs index e60253ecf9..068745fcdd 100644 --- a/nym-wallet/wallet-recovery-cli/src/main.rs +++ b/nym-wallet/wallet-recovery-cli/src/main.rs @@ -32,15 +32,15 @@ enum DecryptedAccount { struct Args { /// Password used to attempt to decrypt the logins found in the file. The option can be /// provided multiple times for files that require multiple passwords. - #[clap(short, long, min_values(1), required = true)] + #[clap(short, long, value_parser, required = true)] password: Vec, /// Path to the wallet file that will be decrypted. - #[clap(short, long)] + #[clap(short, long, value_parser)] file: String, /// Raw mode. Skips trying to parse the decrypted content. - #[clap(short, long)] + #[clap(short, long, action)] raw: bool, } From 6154b0c24c216abc9bc7f5a32e80339674f11531 Mon Sep 17 00:00:00 2001 From: Drazen Urch Date: Tue, 13 Sep 2022 10:38:23 +0200 Subject: [PATCH 30/46] Fix claim -> undelegate (#1613) * Fix claim -> undelegate * Fix ordering * Changelog --- contracts/CHANGELOG.md | 2 ++ contracts/mixnet/src/rewards/transactions.rs | 9 +-------- 2 files changed, 3 insertions(+), 8 deletions(-) diff --git a/contracts/CHANGELOG.md b/contracts/CHANGELOG.md index 8685dc89d7..a8844de3c8 100644 --- a/contracts/CHANGELOG.md +++ b/contracts/CHANGELOG.md @@ -12,10 +12,12 @@ - vesting-contract: the contract now correctly stores delegations with their timestamp as opposed to using block height ([#1544]) - mixnet-contract: compounding delegator rewards is now possible even if the associated mixnode had already unbonded ([#1571]) +- mixnet-contract: fixed reward accumulation after claiming rewards ([#1613]) [#1544]: https://github.com/nymtech/nym/pull/1544 [#1569]: https://github.com/nymtech/nym/pull/1569 [#1569]: https://github.com/nymtech/nym/pull/1571 +[#1613]: https://github.com/nymtech/nym/pull/1613 ## [nym-contracts-v1.0.1](https://github.com/nymtech/nym/tree/nym-contracts-v1.0.1) (2022-06-22) diff --git a/contracts/mixnet/src/rewards/transactions.rs b/contracts/mixnet/src/rewards/transactions.rs index 826c45f783..7ccf9989a1 100644 --- a/contracts/mixnet/src/rewards/transactions.rs +++ b/contracts/mixnet/src/rewards/transactions.rs @@ -547,16 +547,9 @@ pub fn calculate_delegator_reward( .load(storage, (key.clone(), mix_identity.to_string())) .unwrap_or(0); - // Get delegations newer then last_claimed_height, it would be nice to also fold this into the iteration bellow but it should be ok for now, as - // I doubt folks refresh their delegations often let mut delegations = delegations_storage::delegations() .prefix((mix_identity.to_string(), key)) - .range( - storage, - Some(Bound::inclusive(last_claimed_height)), - None, - Order::Descending, - ) + .range(storage, None, None, Order::Ascending) .filter_map(|record| record.ok()) .map(|(_, delegation)| delegation) .collect::>(); From 124103d51b8fdd66552c27575234d810e80ec6c8 Mon Sep 17 00:00:00 2001 From: Mark Sinclair Date: Tue, 13 Sep 2022 09:47:18 +0100 Subject: [PATCH 31/46] Mixnet and vesting contracts v1.0.2 (#1616) --- contracts/CHANGELOG.md | 2 +- contracts/mixnet/Cargo.toml | 2 +- contracts/vesting/Cargo.toml | 2 +- 3 files changed, 3 insertions(+), 3 deletions(-) diff --git a/contracts/CHANGELOG.md b/contracts/CHANGELOG.md index a8844de3c8..38fbe32341 100644 --- a/contracts/CHANGELOG.md +++ b/contracts/CHANGELOG.md @@ -1,4 +1,4 @@ -## Unreleased +## [nym-contracts-v1.0.2](https://github.com/nymtech/nym/tree/nym-contracts-v1.0.2) (2022-09-13) ### Added diff --git a/contracts/mixnet/Cargo.toml b/contracts/mixnet/Cargo.toml index 24df80eb65..8a6f83b8c4 100644 --- a/contracts/mixnet/Cargo.toml +++ b/contracts/mixnet/Cargo.toml @@ -1,6 +1,6 @@ [package] name = "mixnet-contract" -version = "1.0.1" +version = "1.0.2" authors = ["Dave Hrycyszyn "] edition = "2021" diff --git a/contracts/vesting/Cargo.toml b/contracts/vesting/Cargo.toml index d7e9ea49d9..4ffc353a6a 100644 --- a/contracts/vesting/Cargo.toml +++ b/contracts/vesting/Cargo.toml @@ -1,6 +1,6 @@ [package] name = "vesting-contract" -version = "1.0.1" +version = "1.0.2" authors = ["Drazen Urch "] edition = "2021" From 627d12239e23e76a3b140539fe31b56f14668958 Mon Sep 17 00:00:00 2001 From: =?UTF-8?q?Rapha=C3=ABl=20Walther?= <48209673+raphael-walther@users.noreply.github.com> Date: Tue, 13 Sep 2022 19:13:18 +0200 Subject: [PATCH 32/46] Added keybase team variable (#1537) * Added keybase team variable * Amended notification --- .github/workflows/support-files/notifications/send_message.js | 2 +- 1 file changed, 1 insertion(+), 1 deletion(-) diff --git a/.github/workflows/support-files/notifications/send_message.js b/.github/workflows/support-files/notifications/send_message.js index 1563f53e6d..fbc256d011 100644 --- a/.github/workflows/support-files/notifications/send_message.js +++ b/.github/workflows/support-files/notifications/send_message.js @@ -89,7 +89,7 @@ async function sendKeybaseMessage(messageBody) { }); const channel = { - name: 'nymtech_bot', + name: context.env.KEYBASE_NYMBOT_TEAM || 'nymtech_bot', membersType: 'team', topicName: context.keybase.channel, topic_type: 'CHAT', From d38614b15ca6eb8c9090a795a195845fadd4f8f6 Mon Sep 17 00:00:00 2001 From: =?UTF-8?q?Rapha=C3=ABl=20Walther?= Date: Tue, 13 Sep 2022 19:22:09 +0200 Subject: [PATCH 33/46] Test for notification --- .github/workflows/notification_on_dispatch.yml | 1 + 1 file changed, 1 insertion(+) diff --git a/.github/workflows/notification_on_dispatch.yml b/.github/workflows/notification_on_dispatch.yml index 4222a71ae3..6a80d4fd62 100644 --- a/.github/workflows/notification_on_dispatch.yml +++ b/.github/workflows/notification_on_dispatch.yml @@ -21,6 +21,7 @@ jobs: KEYBASE_NYMBOT_PAPERKEY: "${{ secrets.KEYBASE_NYMBOT_PAPERKEY }}" KEYBASE_NYMBOT_TEAM: "${{ secrets.KEYBASE_NYMBOT_TEAM }}" KEYBASE_NYM_CHANNEL: "ci-nightly" + WORKFLOW_CONCLUSION: "failure" uses: docker://keybaseio/client:stable-node with: args: .github/workflows/support-files/notifications/entry_point.sh From e12b69e58fa761fa3d135a9729ea487e0bc81f2a Mon Sep 17 00:00:00 2001 From: =?UTF-8?q?Rapha=C3=ABl=20Walther?= Date: Tue, 13 Sep 2022 19:28:46 +0200 Subject: [PATCH 34/46] Test for notification --- .github/workflows/notification_on_dispatch.yml | 2 +- 1 file changed, 1 insertion(+), 1 deletion(-) diff --git a/.github/workflows/notification_on_dispatch.yml b/.github/workflows/notification_on_dispatch.yml index 6a80d4fd62..3596df481f 100644 --- a/.github/workflows/notification_on_dispatch.yml +++ b/.github/workflows/notification_on_dispatch.yml @@ -19,7 +19,7 @@ jobs: GIT_BRANCH: "${GITHUB_REF##*/}" KEYBASE_NYMBOT_USERNAME: "${{ secrets.KEYBASE_NYMBOT_USERNAME }}" KEYBASE_NYMBOT_PAPERKEY: "${{ secrets.KEYBASE_NYMBOT_PAPERKEY }}" - KEYBASE_NYMBOT_TEAM: "${{ secrets.KEYBASE_NYMBOT_TEAM }}" + KEYBASE_NYMBOT_TEAM: "${{ secrets.KEYBASE_NYMTECH_TEAM }}" KEYBASE_NYM_CHANNEL: "ci-nightly" WORKFLOW_CONCLUSION: "failure" uses: docker://keybaseio/client:stable-node From af1a83fe8370ac3c150e18b5d0ddc6dff22267a1 Mon Sep 17 00:00:00 2001 From: =?UTF-8?q?Rapha=C3=ABl=20Walther?= Date: Tue, 13 Sep 2022 19:35:22 +0200 Subject: [PATCH 35/46] Test for notification --- .github/workflows/notification_on_dispatch.yml | 4 ++-- 1 file changed, 2 insertions(+), 2 deletions(-) diff --git a/.github/workflows/notification_on_dispatch.yml b/.github/workflows/notification_on_dispatch.yml index 3596df481f..1b8a99b213 100644 --- a/.github/workflows/notification_on_dispatch.yml +++ b/.github/workflows/notification_on_dispatch.yml @@ -1,4 +1,4 @@ -name: Nightly builds on dispatch +name: Notification on dispatch on: workflow_dispatch jobs: @@ -20,7 +20,7 @@ jobs: KEYBASE_NYMBOT_USERNAME: "${{ secrets.KEYBASE_NYMBOT_USERNAME }}" KEYBASE_NYMBOT_PAPERKEY: "${{ secrets.KEYBASE_NYMBOT_PAPERKEY }}" KEYBASE_NYMBOT_TEAM: "${{ secrets.KEYBASE_NYMTECH_TEAM }}" - KEYBASE_NYM_CHANNEL: "ci-nightly" + KEYBASE_NYM_CHANNEL: "test" WORKFLOW_CONCLUSION: "failure" uses: docker://keybaseio/client:stable-node with: From fc90d5a3899e01391067b6844c0c940eb8fa4a53 Mon Sep 17 00:00:00 2001 From: =?UTF-8?q?Jon=20H=C3=A4ggblad?= Date: Wed, 14 Sep 2022 08:31:01 +0200 Subject: [PATCH 36/46] ci: more cargo clean for windows Not ideal, we need runners with more disk space --- .github/workflows/nightly_build.yml | 6 ++++++ 1 file changed, 6 insertions(+) diff --git a/.github/workflows/nightly_build.yml b/.github/workflows/nightly_build.yml index 8937d964bd..087f379984 100644 --- a/.github/workflows/nightly_build.yml +++ b/.github/workflows/nightly_build.yml @@ -107,6 +107,12 @@ jobs: command: build args: --workspace --features=coconut + - name: Reclaim some disk space (because Windows is being annoying) + uses: actions-rs/cargo@v1 + if: ${{ matrix.os == 'windows-latest' }} + with: + command: clean + - name: Run all tests with coconut enabled uses: actions-rs/cargo@v1 with: From db2417075245eac7203bd16854c2457a7a8bc789 Mon Sep 17 00:00:00 2001 From: Dave Hrycyszyn Date: Wed, 14 Sep 2022 10:32:39 +0100 Subject: [PATCH 37/46] Fixing npm audit in js example code --- .../webassembly/js-example/package-lock.json | 140 ++++++++++++++---- 1 file changed, 115 insertions(+), 25 deletions(-) diff --git a/clients/webassembly/js-example/package-lock.json b/clients/webassembly/js-example/package-lock.json index 9b7ff01b7d..fe566e6f19 100644 --- a/clients/webassembly/js-example/package-lock.json +++ b/clients/webassembly/js-example/package-lock.json @@ -36,6 +36,64 @@ "node": ">=10.0.0" } }, + "node_modules/@jridgewell/gen-mapping": { + "version": "0.3.2", + "resolved": "https://registry.npmjs.org/@jridgewell/gen-mapping/-/gen-mapping-0.3.2.tgz", + "integrity": "sha512-mh65xKQAzI6iBcFzwv28KVWSmCkdRBWoOh+bYQGW3+6OZvbbN3TqMGo5hqYxQniRcH9F2VZIoJCm4pa3BPDK/A==", + "dev": true, + "dependencies": { + "@jridgewell/set-array": "^1.0.1", + "@jridgewell/sourcemap-codec": "^1.4.10", + "@jridgewell/trace-mapping": "^0.3.9" + }, + "engines": { + "node": ">=6.0.0" + } + }, + "node_modules/@jridgewell/resolve-uri": { + "version": "3.1.0", + "resolved": "https://registry.npmjs.org/@jridgewell/resolve-uri/-/resolve-uri-3.1.0.tgz", + "integrity": "sha512-F2msla3tad+Mfht5cJq7LSXcdudKTWCVYUgw6pLFOOHSTtZlj6SWNYAp+AhuqLmWdBO2X5hPrLcu8cVP8fy28w==", + "dev": true, + "engines": { + "node": ">=6.0.0" + } + }, + "node_modules/@jridgewell/set-array": { + "version": "1.1.2", + "resolved": "https://registry.npmjs.org/@jridgewell/set-array/-/set-array-1.1.2.tgz", + "integrity": "sha512-xnkseuNADM0gt2bs+BvhO0p78Mk762YnZdsuzFV018NoG1Sj1SCQvpSqa7XUaTam5vAGasABV9qXASMKnFMwMw==", + "dev": true, + "engines": { + "node": ">=6.0.0" + } + }, + "node_modules/@jridgewell/source-map": { + "version": "0.3.2", + "resolved": "https://registry.npmjs.org/@jridgewell/source-map/-/source-map-0.3.2.tgz", + "integrity": "sha512-m7O9o2uR8k2ObDysZYzdfhb08VuEml5oWGiosa1VdaPZ/A6QyPkAJuwN0Q1lhULOf6B7MtQmHENS743hWtCrgw==", + "dev": true, + "dependencies": { + "@jridgewell/gen-mapping": "^0.3.0", + "@jridgewell/trace-mapping": "^0.3.9" + } + }, + "node_modules/@jridgewell/sourcemap-codec": { + "version": "1.4.14", + "resolved": "https://registry.npmjs.org/@jridgewell/sourcemap-codec/-/sourcemap-codec-1.4.14.tgz", + "integrity": "sha512-XPSJHWmi394fuUuzDnGz1wiKqWfo1yXecHQMRf2l6hztTO+nPru658AyDngaBe7isIxEkRsPR3FZh+s7iVa4Uw==", + "dev": true + }, + "node_modules/@jridgewell/trace-mapping": { + "version": "0.3.15", + "resolved": "https://registry.npmjs.org/@jridgewell/trace-mapping/-/trace-mapping-0.3.15.tgz", + "integrity": "sha512-oWZNOULl+UbhsgB51uuZzglikfIKSUBO/M9W2OfEjn7cmqoAiCgmv9lyACTUacZwBz0ITnJ2NqjU8Tx0DHL88g==", + "dev": true, + "dependencies": { + "@jridgewell/resolve-uri": "^3.0.3", + "@jridgewell/sourcemap-codec": "^1.4.10" + } + }, "node_modules/@nodelib/fs.scandir": { "version": "2.1.5", "resolved": "https://registry.npmjs.org/@nodelib/fs.scandir/-/fs.scandir-2.1.5.tgz", @@ -3272,14 +3330,14 @@ } }, "node_modules/terser": { - "version": "5.12.1", - "resolved": "https://registry.npmjs.org/terser/-/terser-5.12.1.tgz", - "integrity": "sha512-NXbs+7nisos5E+yXwAD+y7zrcTkMqb0dEJxIGtSKPdCBzopf7ni4odPul2aechpV7EXNvOudYOX2bb5tln1jbQ==", + "version": "5.15.0", + "resolved": "https://registry.npmjs.org/terser/-/terser-5.15.0.tgz", + "integrity": "sha512-L1BJiXVmheAQQy+as0oF3Pwtlo4s3Wi1X2zNZ2NxOB4wx9bdS9Vk67XQENLFdLYGCK/Z2di53mTj/hBafR+dTA==", "dev": true, "dependencies": { + "@jridgewell/source-map": "^0.3.2", "acorn": "^8.5.0", "commander": "^2.20.0", - "source-map": "~0.7.2", "source-map-support": "~0.5.20" }, "bin": { @@ -3372,15 +3430,6 @@ "url": "https://opencollective.com/webpack" } }, - "node_modules/terser/node_modules/source-map": { - "version": "0.7.3", - "resolved": "https://registry.npmjs.org/source-map/-/source-map-0.7.3.tgz", - "integrity": "sha512-CkCj6giN3S+n9qrYiBTX5gystlENnRW5jZeNLHpe6aue+SrHcG5VYwujhW9s4dY31mEGsxBDrHR6oI69fTXsaQ==", - "dev": true, - "engines": { - "node": ">= 8" - } - }, "node_modules/thunky": { "version": "1.1.0", "resolved": "https://registry.npmjs.org/thunky/-/thunky-1.1.0.tgz", @@ -3828,6 +3877,55 @@ "integrity": "sha512-dBVuXR082gk3jsFp7Rd/JI4kytwGHecnCoTtXFb7DB6CNHp4rg5k1bhg0nWdLGLnOV71lmDzGQaLMy8iPLY0pw==", "dev": true }, + "@jridgewell/gen-mapping": { + "version": "0.3.2", + "resolved": "https://registry.npmjs.org/@jridgewell/gen-mapping/-/gen-mapping-0.3.2.tgz", + "integrity": "sha512-mh65xKQAzI6iBcFzwv28KVWSmCkdRBWoOh+bYQGW3+6OZvbbN3TqMGo5hqYxQniRcH9F2VZIoJCm4pa3BPDK/A==", + "dev": true, + "requires": { + "@jridgewell/set-array": "^1.0.1", + "@jridgewell/sourcemap-codec": "^1.4.10", + "@jridgewell/trace-mapping": "^0.3.9" + } + }, + "@jridgewell/resolve-uri": { + "version": "3.1.0", + "resolved": "https://registry.npmjs.org/@jridgewell/resolve-uri/-/resolve-uri-3.1.0.tgz", + "integrity": "sha512-F2msla3tad+Mfht5cJq7LSXcdudKTWCVYUgw6pLFOOHSTtZlj6SWNYAp+AhuqLmWdBO2X5hPrLcu8cVP8fy28w==", + "dev": true + }, + "@jridgewell/set-array": { + "version": "1.1.2", + "resolved": "https://registry.npmjs.org/@jridgewell/set-array/-/set-array-1.1.2.tgz", + "integrity": "sha512-xnkseuNADM0gt2bs+BvhO0p78Mk762YnZdsuzFV018NoG1Sj1SCQvpSqa7XUaTam5vAGasABV9qXASMKnFMwMw==", + "dev": true + }, + "@jridgewell/source-map": { + "version": "0.3.2", + "resolved": "https://registry.npmjs.org/@jridgewell/source-map/-/source-map-0.3.2.tgz", + "integrity": "sha512-m7O9o2uR8k2ObDysZYzdfhb08VuEml5oWGiosa1VdaPZ/A6QyPkAJuwN0Q1lhULOf6B7MtQmHENS743hWtCrgw==", + "dev": true, + "requires": { + "@jridgewell/gen-mapping": "^0.3.0", + "@jridgewell/trace-mapping": "^0.3.9" + } + }, + "@jridgewell/sourcemap-codec": { + "version": "1.4.14", + "resolved": "https://registry.npmjs.org/@jridgewell/sourcemap-codec/-/sourcemap-codec-1.4.14.tgz", + "integrity": "sha512-XPSJHWmi394fuUuzDnGz1wiKqWfo1yXecHQMRf2l6hztTO+nPru658AyDngaBe7isIxEkRsPR3FZh+s7iVa4Uw==", + "dev": true + }, + "@jridgewell/trace-mapping": { + "version": "0.3.15", + "resolved": "https://registry.npmjs.org/@jridgewell/trace-mapping/-/trace-mapping-0.3.15.tgz", + "integrity": "sha512-oWZNOULl+UbhsgB51uuZzglikfIKSUBO/M9W2OfEjn7cmqoAiCgmv9lyACTUacZwBz0ITnJ2NqjU8Tx0DHL88g==", + "dev": true, + "requires": { + "@jridgewell/resolve-uri": "^3.0.3", + "@jridgewell/sourcemap-codec": "^1.4.10" + } + }, "@nodelib/fs.scandir": { "version": "2.1.5", "resolved": "https://registry.npmjs.org/@nodelib/fs.scandir/-/fs.scandir-2.1.5.tgz", @@ -6334,23 +6432,15 @@ "dev": true }, "terser": { - "version": "5.12.1", - "resolved": "https://registry.npmjs.org/terser/-/terser-5.12.1.tgz", - "integrity": "sha512-NXbs+7nisos5E+yXwAD+y7zrcTkMqb0dEJxIGtSKPdCBzopf7ni4odPul2aechpV7EXNvOudYOX2bb5tln1jbQ==", + "version": "5.15.0", + "resolved": "https://registry.npmjs.org/terser/-/terser-5.15.0.tgz", + "integrity": "sha512-L1BJiXVmheAQQy+as0oF3Pwtlo4s3Wi1X2zNZ2NxOB4wx9bdS9Vk67XQENLFdLYGCK/Z2di53mTj/hBafR+dTA==", "dev": true, "requires": { + "@jridgewell/source-map": "^0.3.2", "acorn": "^8.5.0", "commander": "^2.20.0", - "source-map": "~0.7.2", "source-map-support": "~0.5.20" - }, - "dependencies": { - "source-map": { - "version": "0.7.3", - "resolved": "https://registry.npmjs.org/source-map/-/source-map-0.7.3.tgz", - "integrity": "sha512-CkCj6giN3S+n9qrYiBTX5gystlENnRW5jZeNLHpe6aue+SrHcG5VYwujhW9s4dY31mEGsxBDrHR6oI69fTXsaQ==", - "dev": true - } } }, "terser-webpack-plugin": { From 29166c1d6aa57bfff6b0f33d83c7c09eeff91e42 Mon Sep 17 00:00:00 2001 From: "dependabot[bot]" <49699333+dependabot[bot]@users.noreply.github.com> Date: Wed, 14 Sep 2022 11:03:56 +0100 Subject: [PATCH 38/46] Bump terser from 5.10.0 to 5.15.0 in /testnet-faucet (#1621) Bumps [terser](https://github.com/terser/terser) from 5.10.0 to 5.15.0. - [Release notes](https://github.com/terser/terser/releases) - [Changelog](https://github.com/terser/terser/blob/master/CHANGELOG.md) - [Commits](https://github.com/terser/terser/compare/v5.10.0...v5.15.0) --- updated-dependencies: - dependency-name: terser dependency-type: indirect ... Signed-off-by: dependabot[bot] Signed-off-by: dependabot[bot] Co-authored-by: dependabot[bot] <49699333+dependabot[bot]@users.noreply.github.com> --- testnet-faucet/yarn.lock | 62 +++++++++++++++++++++++++++++++--------- 1 file changed, 49 insertions(+), 13 deletions(-) diff --git a/testnet-faucet/yarn.lock b/testnet-faucet/yarn.lock index 2ef7df43be..b867973f6a 100644 --- a/testnet-faucet/yarn.lock +++ b/testnet-faucet/yarn.lock @@ -357,6 +357,46 @@ resolved "https://registry.yarnpkg.com/@humanwhocodes/object-schema/-/object-schema-1.2.1.tgz#b520529ec21d8e5945a1851dfd1c32e94e39ff45" integrity sha512-ZnQMnLV4e7hDlUvw8H+U8ASL02SS2Gn6+9Ac3wGGLIe7+je2AeAOxPY+izIPJDfFDb7eDjev0Us8MO1iFRN8hA== +"@jridgewell/gen-mapping@^0.3.0": + version "0.3.2" + resolved "https://registry.yarnpkg.com/@jridgewell/gen-mapping/-/gen-mapping-0.3.2.tgz#c1aedc61e853f2bb9f5dfe6d4442d3b565b253b9" + integrity sha512-mh65xKQAzI6iBcFzwv28KVWSmCkdRBWoOh+bYQGW3+6OZvbbN3TqMGo5hqYxQniRcH9F2VZIoJCm4pa3BPDK/A== + dependencies: + "@jridgewell/set-array" "^1.0.1" + "@jridgewell/sourcemap-codec" "^1.4.10" + "@jridgewell/trace-mapping" "^0.3.9" + +"@jridgewell/resolve-uri@^3.0.3": + version "3.1.0" + resolved "https://registry.yarnpkg.com/@jridgewell/resolve-uri/-/resolve-uri-3.1.0.tgz#2203b118c157721addfe69d47b70465463066d78" + integrity sha512-F2msla3tad+Mfht5cJq7LSXcdudKTWCVYUgw6pLFOOHSTtZlj6SWNYAp+AhuqLmWdBO2X5hPrLcu8cVP8fy28w== + +"@jridgewell/set-array@^1.0.1": + version "1.1.2" + resolved "https://registry.yarnpkg.com/@jridgewell/set-array/-/set-array-1.1.2.tgz#7c6cf998d6d20b914c0a55a91ae928ff25965e72" + integrity sha512-xnkseuNADM0gt2bs+BvhO0p78Mk762YnZdsuzFV018NoG1Sj1SCQvpSqa7XUaTam5vAGasABV9qXASMKnFMwMw== + +"@jridgewell/source-map@^0.3.2": + version "0.3.2" + resolved "https://registry.yarnpkg.com/@jridgewell/source-map/-/source-map-0.3.2.tgz#f45351aaed4527a298512ec72f81040c998580fb" + integrity sha512-m7O9o2uR8k2ObDysZYzdfhb08VuEml5oWGiosa1VdaPZ/A6QyPkAJuwN0Q1lhULOf6B7MtQmHENS743hWtCrgw== + dependencies: + "@jridgewell/gen-mapping" "^0.3.0" + "@jridgewell/trace-mapping" "^0.3.9" + +"@jridgewell/sourcemap-codec@^1.4.10": + version "1.4.14" + resolved "https://registry.yarnpkg.com/@jridgewell/sourcemap-codec/-/sourcemap-codec-1.4.14.tgz#add4c98d341472a289190b424efbdb096991bb24" + integrity sha512-XPSJHWmi394fuUuzDnGz1wiKqWfo1yXecHQMRf2l6hztTO+nPru658AyDngaBe7isIxEkRsPR3FZh+s7iVa4Uw== + +"@jridgewell/trace-mapping@^0.3.9": + version "0.3.15" + resolved "https://registry.yarnpkg.com/@jridgewell/trace-mapping/-/trace-mapping-0.3.15.tgz#aba35c48a38d3fd84b37e66c9c0423f9744f9774" + integrity sha512-oWZNOULl+UbhsgB51uuZzglikfIKSUBO/M9W2OfEjn7cmqoAiCgmv9lyACTUacZwBz0ITnJ2NqjU8Tx0DHL88g== + dependencies: + "@jridgewell/resolve-uri" "^3.0.3" + "@jridgewell/sourcemap-codec" "^1.4.10" + "@mui/base@5.0.0-alpha.55": version "5.0.0-alpha.55" resolved "https://registry.yarnpkg.com/@mui/base/-/base-5.0.0-alpha.55.tgz#564d6c9374b4cfe86a4493512356047636076d4f" @@ -1321,10 +1361,10 @@ acorn-jsx@^5.3.1: resolved "https://registry.yarnpkg.com/acorn-jsx/-/acorn-jsx-5.3.2.tgz#7ed5bb55908b3b2f1bc55c6af1653bada7f07937" integrity sha512-rq9s+JNhf0IChjtDXxllJ7g41oZk5SlXtp0LHwyA5cejwn7vKmKp4pPri6YEePv2PU65sAsegbXtIinmDFDXgQ== -acorn@^8.7.0: - version "8.7.0" - resolved "https://registry.yarnpkg.com/acorn/-/acorn-8.7.0.tgz#90951fde0f8f09df93549481e5fc141445b791cf" - integrity sha512-V/LGr1APy+PXIwKebEWrkZPwoeoF+w1jiOBUmuxuiUIaOHtob8Qc9BTrYo7VuI5fR8tqsy+buA2WFooR5olqvQ== +acorn@^8.5.0, acorn@^8.7.0: + version "8.8.0" + resolved "https://registry.yarnpkg.com/acorn/-/acorn-8.8.0.tgz#88c0187620435c7f6015803f5539dae05a9dbea8" + integrity sha512-QOxyigPVrpZ2GXT+PFyZTl6TtOFc5egxHIP9IlQ+RbupQuX4RkT/Bee4/kQuC02Xkzg84JcT7oLYtDIQxp+v7w== ajv@^6.10.0, ajv@^6.12.4: version "6.12.6" @@ -3339,11 +3379,6 @@ source-map@^0.6.0, source-map@^0.6.1: resolved "https://registry.yarnpkg.com/source-map/-/source-map-0.6.1.tgz#74722af32e9614e9c287a8d0bbde48b5e2f1a263" integrity sha512-UjgapumWlbMhkBgzT7Ykc5YXUT46F0iKu8SGXq0bcwP5dz/h0Plj6enJqjz1Zbq2l5WaqYnrVbwWOWMyF3F47g== -source-map@~0.7.2: - version "0.7.3" - resolved "https://registry.yarnpkg.com/source-map/-/source-map-0.7.3.tgz#5302f8169031735226544092e64981f751750383" - integrity sha512-CkCj6giN3S+n9qrYiBTX5gystlENnRW5jZeNLHpe6aue+SrHcG5VYwujhW9s4dY31mEGsxBDrHR6oI69fTXsaQ== - stable@^0.1.8: version "0.1.8" resolved "https://registry.yarnpkg.com/stable/-/stable-0.1.8.tgz#836eb3c8382fe2936feaf544631017ce7d47a3cf" @@ -3449,12 +3484,13 @@ term-size@^2.2.1: integrity sha512-wK0Ri4fOGjv/XPy8SBHZChl8CM7uMc5VML7SqiQ0zG7+J5Vr+RMQDoHa2CNT6KHUnTGIXH34UDMkPzAUyapBZg== terser@^5.2.0: - version "5.10.0" - resolved "https://registry.yarnpkg.com/terser/-/terser-5.10.0.tgz#b86390809c0389105eb0a0b62397563096ddafcc" - integrity sha512-AMmF99DMfEDiRJfxfY5jj5wNH/bYO09cniSqhfoyxc8sFoYIgkJy86G04UoZU5VjlpnplVu0K6Tx6E9b5+DlHA== + version "5.15.0" + resolved "https://registry.yarnpkg.com/terser/-/terser-5.15.0.tgz#e16967894eeba6e1091509ec83f0c60e179f2425" + integrity sha512-L1BJiXVmheAQQy+as0oF3Pwtlo4s3Wi1X2zNZ2NxOB4wx9bdS9Vk67XQENLFdLYGCK/Z2di53mTj/hBafR+dTA== dependencies: + "@jridgewell/source-map" "^0.3.2" + acorn "^8.5.0" commander "^2.20.0" - source-map "~0.7.2" source-map-support "~0.5.20" text-table@^0.2.0: From 67900956f88310e85ca0a573aa1756d05a244f8a Mon Sep 17 00:00:00 2001 From: "dependabot[bot]" <49699333+dependabot[bot]@users.noreply.github.com> Date: Wed, 14 Sep 2022 11:04:14 +0100 Subject: [PATCH 39/46] Bump terser in /clients/native/examples/js-examples/websocket (#1620) Bumps [terser](https://github.com/terser/terser) from 5.12.1 to 5.15.0. - [Release notes](https://github.com/terser/terser/releases) - [Changelog](https://github.com/terser/terser/blob/master/CHANGELOG.md) - [Commits](https://github.com/terser/terser/compare/v5.12.1...v5.15.0) --- updated-dependencies: - dependency-name: terser dependency-type: indirect ... Signed-off-by: dependabot[bot] Signed-off-by: dependabot[bot] Co-authored-by: dependabot[bot] <49699333+dependabot[bot]@users.noreply.github.com> --- .../js-examples/websocket/package-lock.json | 124 +++++++++++++++--- 1 file changed, 103 insertions(+), 21 deletions(-) diff --git a/clients/native/examples/js-examples/websocket/package-lock.json b/clients/native/examples/js-examples/websocket/package-lock.json index 36c731306a..4fc3fbbd83 100644 --- a/clients/native/examples/js-examples/websocket/package-lock.json +++ b/clients/native/examples/js-examples/websocket/package-lock.json @@ -27,6 +27,58 @@ "node": ">=10.0.0" } }, + "node_modules/@jridgewell/gen-mapping": { + "version": "0.3.2", + "resolved": "https://registry.npmjs.org/@jridgewell/gen-mapping/-/gen-mapping-0.3.2.tgz", + "integrity": "sha512-mh65xKQAzI6iBcFzwv28KVWSmCkdRBWoOh+bYQGW3+6OZvbbN3TqMGo5hqYxQniRcH9F2VZIoJCm4pa3BPDK/A==", + "dependencies": { + "@jridgewell/set-array": "^1.0.1", + "@jridgewell/sourcemap-codec": "^1.4.10", + "@jridgewell/trace-mapping": "^0.3.9" + }, + "engines": { + "node": ">=6.0.0" + } + }, + "node_modules/@jridgewell/resolve-uri": { + "version": "3.1.0", + "resolved": "https://registry.npmjs.org/@jridgewell/resolve-uri/-/resolve-uri-3.1.0.tgz", + "integrity": "sha512-F2msla3tad+Mfht5cJq7LSXcdudKTWCVYUgw6pLFOOHSTtZlj6SWNYAp+AhuqLmWdBO2X5hPrLcu8cVP8fy28w==", + "engines": { + "node": ">=6.0.0" + } + }, + "node_modules/@jridgewell/set-array": { + "version": "1.1.2", + "resolved": "https://registry.npmjs.org/@jridgewell/set-array/-/set-array-1.1.2.tgz", + "integrity": "sha512-xnkseuNADM0gt2bs+BvhO0p78Mk762YnZdsuzFV018NoG1Sj1SCQvpSqa7XUaTam5vAGasABV9qXASMKnFMwMw==", + "engines": { + "node": ">=6.0.0" + } + }, + "node_modules/@jridgewell/source-map": { + "version": "0.3.2", + "resolved": "https://registry.npmjs.org/@jridgewell/source-map/-/source-map-0.3.2.tgz", + "integrity": "sha512-m7O9o2uR8k2ObDysZYzdfhb08VuEml5oWGiosa1VdaPZ/A6QyPkAJuwN0Q1lhULOf6B7MtQmHENS743hWtCrgw==", + "dependencies": { + "@jridgewell/gen-mapping": "^0.3.0", + "@jridgewell/trace-mapping": "^0.3.9" + } + }, + "node_modules/@jridgewell/sourcemap-codec": { + "version": "1.4.14", + "resolved": "https://registry.npmjs.org/@jridgewell/sourcemap-codec/-/sourcemap-codec-1.4.14.tgz", + "integrity": "sha512-XPSJHWmi394fuUuzDnGz1wiKqWfo1yXecHQMRf2l6hztTO+nPru658AyDngaBe7isIxEkRsPR3FZh+s7iVa4Uw==" + }, + "node_modules/@jridgewell/trace-mapping": { + "version": "0.3.15", + "resolved": "https://registry.npmjs.org/@jridgewell/trace-mapping/-/trace-mapping-0.3.15.tgz", + "integrity": "sha512-oWZNOULl+UbhsgB51uuZzglikfIKSUBO/M9W2OfEjn7cmqoAiCgmv9lyACTUacZwBz0ITnJ2NqjU8Tx0DHL88g==", + "dependencies": { + "@jridgewell/resolve-uri": "^3.0.3", + "@jridgewell/sourcemap-codec": "^1.4.10" + } + }, "node_modules/@nodelib/fs.scandir": { "version": "2.1.5", "resolved": "https://registry.npmjs.org/@nodelib/fs.scandir/-/fs.scandir-2.1.5.tgz", @@ -3529,13 +3581,13 @@ } }, "node_modules/terser": { - "version": "5.12.1", - "resolved": "https://registry.npmjs.org/terser/-/terser-5.12.1.tgz", - "integrity": "sha512-NXbs+7nisos5E+yXwAD+y7zrcTkMqb0dEJxIGtSKPdCBzopf7ni4odPul2aechpV7EXNvOudYOX2bb5tln1jbQ==", + "version": "5.15.0", + "resolved": "https://registry.npmjs.org/terser/-/terser-5.15.0.tgz", + "integrity": "sha512-L1BJiXVmheAQQy+as0oF3Pwtlo4s3Wi1X2zNZ2NxOB4wx9bdS9Vk67XQENLFdLYGCK/Z2di53mTj/hBafR+dTA==", "dependencies": { + "@jridgewell/source-map": "^0.3.2", "acorn": "^8.5.0", "commander": "^2.20.0", - "source-map": "~0.7.2", "source-map-support": "~0.5.20" }, "bin": { @@ -3583,14 +3635,6 @@ "resolved": "https://registry.npmjs.org/commander/-/commander-2.20.3.tgz", "integrity": "sha512-GpVkmM8vF2vQUkj2LvZmD35JxeJOLCwJ9cUkugyk2nuhbv3+mJvpLYYt+0+USMxE+oj+ey/lJEnhZw75x/OMcQ==" }, - "node_modules/terser/node_modules/source-map": { - "version": "0.7.3", - "resolved": "https://registry.npmjs.org/source-map/-/source-map-0.7.3.tgz", - "integrity": "sha512-CkCj6giN3S+n9qrYiBTX5gystlENnRW5jZeNLHpe6aue+SrHcG5VYwujhW9s4dY31mEGsxBDrHR6oI69fTXsaQ==", - "engines": { - "node": ">= 8" - } - }, "node_modules/thunky": { "version": "1.1.0", "resolved": "https://registry.npmjs.org/thunky/-/thunky-1.1.0.tgz", @@ -4330,6 +4374,49 @@ "integrity": "sha512-dBVuXR082gk3jsFp7Rd/JI4kytwGHecnCoTtXFb7DB6CNHp4rg5k1bhg0nWdLGLnOV71lmDzGQaLMy8iPLY0pw==", "dev": true }, + "@jridgewell/gen-mapping": { + "version": "0.3.2", + "resolved": "https://registry.npmjs.org/@jridgewell/gen-mapping/-/gen-mapping-0.3.2.tgz", + "integrity": "sha512-mh65xKQAzI6iBcFzwv28KVWSmCkdRBWoOh+bYQGW3+6OZvbbN3TqMGo5hqYxQniRcH9F2VZIoJCm4pa3BPDK/A==", + "requires": { + "@jridgewell/set-array": "^1.0.1", + "@jridgewell/sourcemap-codec": "^1.4.10", + "@jridgewell/trace-mapping": "^0.3.9" + } + }, + "@jridgewell/resolve-uri": { + "version": "3.1.0", + "resolved": "https://registry.npmjs.org/@jridgewell/resolve-uri/-/resolve-uri-3.1.0.tgz", + "integrity": "sha512-F2msla3tad+Mfht5cJq7LSXcdudKTWCVYUgw6pLFOOHSTtZlj6SWNYAp+AhuqLmWdBO2X5hPrLcu8cVP8fy28w==" + }, + "@jridgewell/set-array": { + "version": "1.1.2", + "resolved": "https://registry.npmjs.org/@jridgewell/set-array/-/set-array-1.1.2.tgz", + "integrity": "sha512-xnkseuNADM0gt2bs+BvhO0p78Mk762YnZdsuzFV018NoG1Sj1SCQvpSqa7XUaTam5vAGasABV9qXASMKnFMwMw==" + }, + "@jridgewell/source-map": { + "version": "0.3.2", + "resolved": "https://registry.npmjs.org/@jridgewell/source-map/-/source-map-0.3.2.tgz", + "integrity": "sha512-m7O9o2uR8k2ObDysZYzdfhb08VuEml5oWGiosa1VdaPZ/A6QyPkAJuwN0Q1lhULOf6B7MtQmHENS743hWtCrgw==", + "requires": { + "@jridgewell/gen-mapping": "^0.3.0", + "@jridgewell/trace-mapping": "^0.3.9" + } + }, + "@jridgewell/sourcemap-codec": { + "version": "1.4.14", + "resolved": "https://registry.npmjs.org/@jridgewell/sourcemap-codec/-/sourcemap-codec-1.4.14.tgz", + "integrity": "sha512-XPSJHWmi394fuUuzDnGz1wiKqWfo1yXecHQMRf2l6hztTO+nPru658AyDngaBe7isIxEkRsPR3FZh+s7iVa4Uw==" + }, + "@jridgewell/trace-mapping": { + "version": "0.3.15", + "resolved": "https://registry.npmjs.org/@jridgewell/trace-mapping/-/trace-mapping-0.3.15.tgz", + "integrity": "sha512-oWZNOULl+UbhsgB51uuZzglikfIKSUBO/M9W2OfEjn7cmqoAiCgmv9lyACTUacZwBz0ITnJ2NqjU8Tx0DHL88g==", + "requires": { + "@jridgewell/resolve-uri": "^3.0.3", + "@jridgewell/sourcemap-codec": "^1.4.10" + } + }, "@nodelib/fs.scandir": { "version": "2.1.5", "resolved": "https://registry.npmjs.org/@nodelib/fs.scandir/-/fs.scandir-2.1.5.tgz", @@ -7058,13 +7145,13 @@ "integrity": "sha512-GNzQvQTOIP6RyTfE2Qxb8ZVlNmw0n88vp1szwWRimP02mnTsx3Wtn5qRdqY9w2XduFNUgvOwhNnQsjwCp+kqaQ==" }, "terser": { - "version": "5.12.1", - "resolved": "https://registry.npmjs.org/terser/-/terser-5.12.1.tgz", - "integrity": "sha512-NXbs+7nisos5E+yXwAD+y7zrcTkMqb0dEJxIGtSKPdCBzopf7ni4odPul2aechpV7EXNvOudYOX2bb5tln1jbQ==", + "version": "5.15.0", + "resolved": "https://registry.npmjs.org/terser/-/terser-5.15.0.tgz", + "integrity": "sha512-L1BJiXVmheAQQy+as0oF3Pwtlo4s3Wi1X2zNZ2NxOB4wx9bdS9Vk67XQENLFdLYGCK/Z2di53mTj/hBafR+dTA==", "requires": { + "@jridgewell/source-map": "^0.3.2", "acorn": "^8.5.0", "commander": "^2.20.0", - "source-map": "~0.7.2", "source-map-support": "~0.5.20" }, "dependencies": { @@ -7072,11 +7159,6 @@ "version": "2.20.3", "resolved": "https://registry.npmjs.org/commander/-/commander-2.20.3.tgz", "integrity": "sha512-GpVkmM8vF2vQUkj2LvZmD35JxeJOLCwJ9cUkugyk2nuhbv3+mJvpLYYt+0+USMxE+oj+ey/lJEnhZw75x/OMcQ==" - }, - "source-map": { - "version": "0.7.3", - "resolved": "https://registry.npmjs.org/source-map/-/source-map-0.7.3.tgz", - "integrity": "sha512-CkCj6giN3S+n9qrYiBTX5gystlENnRW5jZeNLHpe6aue+SrHcG5VYwujhW9s4dY31mEGsxBDrHR6oI69fTXsaQ==" } } }, From 2ee4b8fec669709d81159e5d76c58f2c0563a3e5 Mon Sep 17 00:00:00 2001 From: "dependabot[bot]" <49699333+dependabot[bot]@users.noreply.github.com> Date: Wed, 14 Sep 2022 11:05:07 +0100 Subject: [PATCH 40/46] Bump @openzeppelin/contracts in /contracts/basic-bandwidth-generation (#1545) Bumps [@openzeppelin/contracts](https://github.com/OpenZeppelin/openzeppelin-contracts) from 4.5.0 to 4.7.3. - [Release notes](https://github.com/OpenZeppelin/openzeppelin-contracts/releases) - [Changelog](https://github.com/OpenZeppelin/openzeppelin-contracts/blob/master/CHANGELOG.md) - [Commits](https://github.com/OpenZeppelin/openzeppelin-contracts/compare/v4.5.0...v4.7.3) --- updated-dependencies: - dependency-name: "@openzeppelin/contracts" dependency-type: direct:production ... Signed-off-by: dependabot[bot] Signed-off-by: dependabot[bot] Co-authored-by: dependabot[bot] <49699333+dependabot[bot]@users.noreply.github.com> --- .../basic-bandwidth-generation/package-lock.json | 14 +++++++------- contracts/basic-bandwidth-generation/package.json | 2 +- 2 files changed, 8 insertions(+), 8 deletions(-) diff --git a/contracts/basic-bandwidth-generation/package-lock.json b/contracts/basic-bandwidth-generation/package-lock.json index 934096cf6e..c954a7d488 100644 --- a/contracts/basic-bandwidth-generation/package-lock.json +++ b/contracts/basic-bandwidth-generation/package-lock.json @@ -7,7 +7,7 @@ "dependencies": { "@nomiclabs/hardhat-truffle5": "^2.0.5", "@nomiclabs/hardhat-web3": "^2.0.0", - "@openzeppelin/contracts": "4.5.0", + "@openzeppelin/contracts": "4.7.3", "@openzeppelin/test-helpers": "^0.5.15", "dotenv": "^16.0.0", "file-system": "^2.2.2", @@ -1920,9 +1920,9 @@ } }, "node_modules/@openzeppelin/contracts": { - "version": "4.5.0", - "resolved": "https://registry.npmjs.org/@openzeppelin/contracts/-/contracts-4.5.0.tgz", - "integrity": "sha512-fdkzKPYMjrRiPK6K4y64e6GzULR7R7RwxSigHS8DDp7aWDeoReqsQI+cxHV1UuhAqX69L1lAaWDxenfP+xiqzA==" + "version": "4.7.3", + "resolved": "https://registry.npmjs.org/@openzeppelin/contracts/-/contracts-4.7.3.tgz", + "integrity": "sha512-dGRS0agJzu8ybo44pCIf3xBaPQN/65AIXNgK8+4gzKd5kbvlqyxryUYVLJv7fK98Seyd2hDZzVEHSWAh0Bt1Yw==" }, "node_modules/@openzeppelin/test-helpers": { "version": "0.5.15", @@ -21190,9 +21190,9 @@ } }, "@openzeppelin/contracts": { - "version": "4.5.0", - "resolved": "https://registry.npmjs.org/@openzeppelin/contracts/-/contracts-4.5.0.tgz", - "integrity": "sha512-fdkzKPYMjrRiPK6K4y64e6GzULR7R7RwxSigHS8DDp7aWDeoReqsQI+cxHV1UuhAqX69L1lAaWDxenfP+xiqzA==" + "version": "4.7.3", + "resolved": "https://registry.npmjs.org/@openzeppelin/contracts/-/contracts-4.7.3.tgz", + "integrity": "sha512-dGRS0agJzu8ybo44pCIf3xBaPQN/65AIXNgK8+4gzKd5kbvlqyxryUYVLJv7fK98Seyd2hDZzVEHSWAh0Bt1Yw==" }, "@openzeppelin/test-helpers": { "version": "0.5.15", diff --git a/contracts/basic-bandwidth-generation/package.json b/contracts/basic-bandwidth-generation/package.json index 020625ad2d..0fee523d6c 100644 --- a/contracts/basic-bandwidth-generation/package.json +++ b/contracts/basic-bandwidth-generation/package.json @@ -12,7 +12,7 @@ "dependencies": { "@nomiclabs/hardhat-truffle5": "^2.0.5", "@nomiclabs/hardhat-web3": "^2.0.0", - "@openzeppelin/contracts": "4.5.0", + "@openzeppelin/contracts": "4.7.3", "@openzeppelin/test-helpers": "^0.5.15", "dotenv": "^16.0.0", "file-system": "^2.2.2", From 55bdcecffb631f2c1a1ece3cfc83937c169b316f Mon Sep 17 00:00:00 2001 From: "dependabot[bot]" <49699333+dependabot[bot]@users.noreply.github.com> Date: Wed, 14 Sep 2022 11:05:39 +0100 Subject: [PATCH 41/46] Bump parse-url from 6.0.0 to 6.0.5 (#1497) Bumps [parse-url](https://github.com/IonicaBizau/parse-url) from 6.0.0 to 6.0.5. - [Release notes](https://github.com/IonicaBizau/parse-url/releases) - [Commits](https://github.com/IonicaBizau/parse-url/compare/6.0.0...6.0.5) --- updated-dependencies: - dependency-name: parse-url dependency-type: indirect ... Signed-off-by: dependabot[bot] Signed-off-by: dependabot[bot] Co-authored-by: dependabot[bot] <49699333+dependabot[bot]@users.noreply.github.com> --- yarn.lock | 62 +++++++++++++++++++++++++++++++++++++++---------------- 1 file changed, 44 insertions(+), 18 deletions(-) diff --git a/yarn.lock b/yarn.lock index 95fbba22ec..8954561d19 100644 --- a/yarn.lock +++ b/yarn.lock @@ -8752,7 +8752,7 @@ decimal.js@^10.2.1: decode-uri-component@^0.2.0: version "0.2.0" resolved "https://registry.yarnpkg.com/decode-uri-component/-/decode-uri-component-0.2.0.tgz#eb3913333458775cb84cd1a1fae062106bb87545" - integrity sha1-6zkTMzRYd1y4TNGh+uBiEGu4dUU= + integrity sha512-hjf+xovcEn31w/EUYdTXQh/8smFL/dzYjohQGEIgjyNavaJfBY2p5F527Bo1VPATxv0VYTUC2bOcXvqFwk78Og== decompress-response@^4.2.0: version "4.2.1" @@ -10218,7 +10218,7 @@ fill-range@^7.0.1: filter-obj@^1.1.0: version "1.1.0" resolved "https://registry.yarnpkg.com/filter-obj/-/filter-obj-1.1.0.tgz#9b311112bc6c6127a16e016c6c5d7f19e0805c5b" - integrity sha1-mzERErxsYSehbgFsbF1/GeCAXFs= + integrity sha512-8rXg1ZnX7xzy2NGDVkBVaAy+lSlPNwad13BtgSlLuxfIslyt5Vg64U7tFcCt4WS1R0hvtnQybT/IyCkGZ3DpXQ== finalhandler@~1.1.2: version "1.1.2" @@ -10598,7 +10598,16 @@ get-caller-file@^2.0.5: resolved "https://registry.yarnpkg.com/get-caller-file/-/get-caller-file-2.0.5.tgz#4f94412a82db32f36e3b0b9741f8a97feb031f7e" integrity sha512-DyFP3BM/3YHTQOCUL/w0OZHR0lpKeGrxotcHWcqNEdnltqFwXVfhEBQ94eIo34AfQpo0rGki4cyIiftY06h2Fg== -get-intrinsic@^1.0.2, get-intrinsic@^1.1.0, get-intrinsic@^1.1.1: +get-intrinsic@^1.0.2: + version "1.1.2" + resolved "https://registry.yarnpkg.com/get-intrinsic/-/get-intrinsic-1.1.2.tgz#336975123e05ad0b7ba41f152ee4aadbea6cf598" + integrity sha512-Jfm3OyCxHh9DJyc28qGk+JmfkpO41A4XkneDSujN9MDXrm4oDKdHvndhZ2dN94+ERNfkYJWDclW6k2L/ZGHjXA== + dependencies: + function-bind "^1.1.1" + has "^1.0.3" + has-symbols "^1.0.3" + +get-intrinsic@^1.1.0, get-intrinsic@^1.1.1: version "1.1.1" resolved "https://registry.yarnpkg.com/get-intrinsic/-/get-intrinsic-1.1.1.tgz#15f59f376f855c446963948f0d24cd3637b4abc6" integrity sha512-kWZrnVM42QCiEA2Ig1bG8zjoIMOgxWwYCEeNdwY6Tv/cOSeGpcoX4pXHfKUxNKVoArnrEr2e9srnAxxGIraS9Q== @@ -10927,7 +10936,7 @@ has-glob@^1.0.0: dependencies: is-glob "^3.0.0" -has-symbols@^1.0.1, has-symbols@^1.0.2: +has-symbols@^1.0.1, has-symbols@^1.0.2, has-symbols@^1.0.3: version "1.0.3" resolved "https://registry.yarnpkg.com/has-symbols/-/has-symbols-1.0.3.tgz#bb7b2c4349251dce87b125f7bdf874aa7c8b39f8" integrity sha512-l3LCuF6MgDNwTDKkdYGEihYjt5pRPbEg46rtlmnSPlUbgmB8LOIrKJbYYFBSbnPaJexMKtiPO8hmeRjRz2Td+A== @@ -11925,11 +11934,11 @@ is-shared-array-buffer@^1.0.1: integrity sha512-IU0NmyknYZN0rChcKhRO1X8LYz5Isj/Fsqh8NJOSf+N/hCOTwy29F32Ik7a+QszE63IdvmwdTPDd6cZ5pg4cwA== is-ssh@^1.3.0: - version "1.3.3" - resolved "https://registry.yarnpkg.com/is-ssh/-/is-ssh-1.3.3.tgz#7f133285ccd7f2c2c7fc897b771b53d95a2b2c7e" - integrity sha512-NKzJmQzJfEEma3w5cJNcUMxoXfDjz0Zj0eyCalHn2E6VOwlzjZo0yuO2fcBSf8zhFuVCL/82/r5gRcoi6aEPVQ== + version "1.4.0" + resolved "https://registry.yarnpkg.com/is-ssh/-/is-ssh-1.4.0.tgz#4f8220601d2839d8fa624b3106f8e8884f01b8b2" + integrity sha512-x7+VxdxOdlV3CYpjvRLBv5Lo9OJerlYanjwFrPR9fuGPjCiNiCzFgAWpiLAohSbsnH4ZAys3SBh+hq5rJosxUQ== dependencies: - protocols "^1.1.0" + protocols "^2.0.1" is-stream@^1.1.0: version "1.1.0" @@ -14450,11 +14459,16 @@ object-copy@^0.1.0: define-property "^0.2.5" kind-of "^3.0.3" -object-inspect@^1.11.0, object-inspect@^1.9.0: +object-inspect@^1.11.0: version "1.12.0" resolved "https://registry.yarnpkg.com/object-inspect/-/object-inspect-1.12.0.tgz#6e2c120e868fd1fd18cb4f18c31741d0d6e776f0" integrity sha512-Ho2z80bVIvJloH+YzRmpZVQe87+qASmBUKZDWgx9cu+KDrX2ZDH/3tMy+gXbZETVGs2M8YdxObOh7XAtim9Y0g== +object-inspect@^1.9.0: + version "1.12.2" + resolved "https://registry.yarnpkg.com/object-inspect/-/object-inspect-1.12.2.tgz#c0641f26394532f28ab8d796ab954e43c009a8ea" + integrity sha512-z+cPxW0QGUp0mcqcsgQyLVRDoXFQbXOwBaqyF7VIgI4TWNQsDHrBpUQslRmIfAoYWdYzs6UlKJtB2XJpTaNSpQ== + object-is@^1.0.1: version "1.1.5" resolved "https://registry.yarnpkg.com/object-is/-/object-is-1.1.5.tgz#b9deeaa5fc7f1846a0faecdceec138e5778f53ac" @@ -14933,9 +14947,9 @@ parse-json@^5.0.0, parse-json@^5.2.0: lines-and-columns "^1.1.6" parse-path@^4.0.0: - version "4.0.3" - resolved "https://registry.yarnpkg.com/parse-path/-/parse-path-4.0.3.tgz#82d81ec3e071dcc4ab49aa9f2c9c0b8966bb22bf" - integrity sha512-9Cepbp2asKnWTJ9x2kpw6Fe8y9JDbqwahGCTvklzd/cEq5C5JC59x2Xb0Kx+x0QZ8bvNquGO8/BWP0cwBHzSAA== + version "4.0.4" + resolved "https://registry.yarnpkg.com/parse-path/-/parse-path-4.0.4.tgz#4bf424e6b743fb080831f03b536af9fc43f0ffea" + integrity sha512-Z2lWUis7jlmXC1jeOG9giRO2+FsuyNipeQ43HAjqAZjwSe3SEf+q/84FGPHoso3kyntbxa4c4i77t3m6fGf8cw== dependencies: is-ssh "^1.3.0" protocols "^1.4.0" @@ -14950,9 +14964,9 @@ parse-png@^1.0.0, parse-png@^1.1.1: pngjs "^3.2.0" parse-url@^6.0.0: - version "6.0.0" - resolved "https://registry.yarnpkg.com/parse-url/-/parse-url-6.0.0.tgz#f5dd262a7de9ec00914939220410b66cff09107d" - integrity sha512-cYyojeX7yIIwuJzledIHeLUBVJ6COVLeT4eF+2P6aKVzwvgKQPndCBv3+yQ7pcWjqToYwaligxzSYNNmGoMAvw== + version "6.0.5" + resolved "https://registry.yarnpkg.com/parse-url/-/parse-url-6.0.5.tgz#4acab8982cef1846a0f8675fa686cef24b2f6f9b" + integrity sha512-e35AeLTSIlkw/5GFq70IN7po8fmDUjpDPY1rIK+VubRfsUvBonjQ+PBZG+vWMACnQSmNlvl524IucoDmcioMxA== dependencies: is-ssh "^1.3.0" normalize-url "^6.1.0" @@ -15804,11 +15818,16 @@ protobufjs@~6.11.2, protobufjs@~6.11.3: "@types/node" ">=13.7.0" long "^4.0.0" -protocols@^1.1.0, protocols@^1.4.0: +protocols@^1.4.0: version "1.4.8" resolved "https://registry.yarnpkg.com/protocols/-/protocols-1.4.8.tgz#48eea2d8f58d9644a4a32caae5d5db290a075ce8" integrity sha512-IgjKyaUSjsROSO8/D49Ab7hP8mJgTYcqApOqdPhLoPxAplXmkp+zRvsrSQjFn5by0rhm4VH0GAUELIPpx7B1yg== +protocols@^2.0.1: + version "2.0.1" + resolved "https://registry.yarnpkg.com/protocols/-/protocols-2.0.1.tgz#8f155da3fc0f32644e83c5782c8e8212ccf70a86" + integrity sha512-/XJ368cyBJ7fzLMwLKv1e4vLxOju2MNAIokcr7meSaNcVbWz/CPcW22cP04mwxOErdA5mwjA8Q6w/cdAQxVn7Q== + proxy-addr@~2.0.7: version "2.0.7" resolved "https://registry.yarnpkg.com/proxy-addr/-/proxy-addr-2.0.7.tgz#f19fe69ceab311eeb94b42e70e8c2070f9ba1025" @@ -15903,13 +15922,20 @@ qs@6.9.7: resolved "https://registry.yarnpkg.com/qs/-/qs-6.9.7.tgz#4610846871485e1e048f44ae3b94033f0e675afe" integrity sha512-IhMFgUmuNpyRfxA90umL7ByLlgRXu6tIfKPpF5TmcfRLlLCckfP/g3IQmju6jjpu+Hh8rA+2p6A27ZSPOOHdKw== -qs@^6.10.0, qs@^6.9.4: +qs@^6.10.0: version "6.10.3" resolved "https://registry.yarnpkg.com/qs/-/qs-6.10.3.tgz#d6cde1b2ffca87b5aa57889816c5f81535e22e8e" integrity sha512-wr7M2E0OFRfIfJZjKGieI8lBKb7fRCH4Fv5KNPEs7gJ8jadvotdsS08PzOKR7opXhZ/Xkjtt3WF9g38drmyRqQ== dependencies: side-channel "^1.0.4" +qs@^6.9.4: + version "6.11.0" + resolved "https://registry.yarnpkg.com/qs/-/qs-6.11.0.tgz#fd0d963446f7a65e1367e01abd85429453f0c37a" + integrity sha512-MvjoMCJwEarSbUYk5O+nmoSzSutSsTwF85zcHPQ9OrlFoZOYIjaqBAJIqIXjptyD5vThxGq52Xu/MaJzRkIk4Q== + dependencies: + side-channel "^1.0.4" + qs@~6.5.2: version "6.5.3" resolved "https://registry.yarnpkg.com/qs/-/qs-6.5.3.tgz#3aeeffc91967ef6e35c0e488ef46fb296ab76aad" @@ -17588,7 +17614,7 @@ stream-to@~0.2.0: strict-uri-encode@^2.0.0: version "2.0.0" resolved "https://registry.yarnpkg.com/strict-uri-encode/-/strict-uri-encode-2.0.0.tgz#b9c7330c7042862f6b142dc274bbcc5866ce3546" - integrity sha1-ucczDHBChi9rFC3CdLvMWGbONUY= + integrity sha512-QwiXZgpRcKkhTj2Scnn++4PKtWsH0kpzZ62L2R6c/LUVYv7hVnZqcg2+sMuT6R7Jusu1vviK/MFsu6kNJfWlEQ== string-length@^4.0.1: version "4.0.2" From 46e206e8f06c2c88e3105f3d327cde3135c9e0e8 Mon Sep 17 00:00:00 2001 From: "dependabot[bot]" <49699333+dependabot[bot]@users.noreply.github.com> Date: Wed, 14 Sep 2022 11:07:05 +0100 Subject: [PATCH 42/46] build(deps): bump terser from 4.8.0 to 4.8.1 (#1468) Bumps [terser](https://github.com/terser/terser) from 4.8.0 to 4.8.1. - [Release notes](https://github.com/terser/terser/releases) - [Changelog](https://github.com/terser/terser/blob/master/CHANGELOG.md) - [Commits](https://github.com/terser/terser/commits) --- updated-dependencies: - dependency-name: terser dependency-type: indirect ... Signed-off-by: dependabot[bot] Signed-off-by: dependabot[bot] Co-authored-by: dependabot[bot] <49699333+dependabot[bot]@users.noreply.github.com> --- yarn.lock | 6 +++--- 1 file changed, 3 insertions(+), 3 deletions(-) diff --git a/yarn.lock b/yarn.lock index 8954561d19..44978bd435 100644 --- a/yarn.lock +++ b/yarn.lock @@ -18076,9 +18076,9 @@ terser-webpack-plugin@^5.0.3, terser-webpack-plugin@^5.1.3: terser "^5.7.2" terser@^4.1.2, terser@^4.6.3: - version "4.8.0" - resolved "https://registry.yarnpkg.com/terser/-/terser-4.8.0.tgz#63056343d7c70bb29f3af665865a46fe03a0df17" - integrity sha512-EAPipTNeWsb/3wLPeup1tVPaXfIaU68xMnVdPafIL1TV05OhASArYyIfFvnvJCNrR2NIOvDVNNTFRa+Re2MWyw== + version "4.8.1" + resolved "https://registry.yarnpkg.com/terser/-/terser-4.8.1.tgz#a00e5634562de2239fd404c649051bf6fc21144f" + integrity sha512-4GnLC0x667eJG0ewJTa6z/yXrbLGv80D9Ru6HIpCQmO+Q4PfEtBFi0ObSckqwL6VyQv/7ENJieXHo2ANmdQwgw== dependencies: commander "^2.20.0" source-map "~0.6.1" From fbe02fa7fbfe06e7b27dcf2bafb9763f02efca2c Mon Sep 17 00:00:00 2001 From: mx <33262279+mfahampshire@users.noreply.github.com> Date: Wed, 14 Sep 2022 12:07:19 +0200 Subject: [PATCH 43/46] added new blockstream endpoint to example allowed.list (#1611) * added new blockstream endpoint to example allowed.list * updated changelog --- CHANGELOG.md | 1 + service-providers/network-requester/allowed.list.sample | 1 + 2 files changed, 2 insertions(+) diff --git a/CHANGELOG.md b/CHANGELOG.md index 197d79ada8..d86757828b 100644 --- a/CHANGELOG.md +++ b/CHANGELOG.md @@ -8,6 +8,7 @@ Post 1.0.0 release, the changelog format is based on [Keep a Changelog](https:// - nym-cli: added CLI tool for interacting with the Nyx blockchain and Nym mixnet smart contracts ([#1577]) - validator-client: added `query_contract_smart` and `query_contract_raw` on `NymdClient` ([#1558]) +- network-requester: added additional Blockstream Green wallet endpoint to `example.allowed.list` ([#1611](https://github.com/nymtech/nym/pull/1611)) ### Changed diff --git a/service-providers/network-requester/allowed.list.sample b/service-providers/network-requester/allowed.list.sample index 614bf0a08b..81eda2959b 100644 --- a/service-providers/network-requester/allowed.list.sample +++ b/service-providers/network-requester/allowed.list.sample @@ -2,6 +2,7 @@ // SPDX-License-Identifier: Apache-2.0 blockstream.info +blockstream.com greenaddress.it electrum.org qtornado.com From 95d0afdeb6a76e192ba59ce73753f0d29b36e921 Mon Sep 17 00:00:00 2001 From: Dave Hrycyszyn Date: Wed, 14 Sep 2022 11:47:54 +0100 Subject: [PATCH 44/46] Whitespace fix --- clients/webassembly/js-example/webpack.config.js | 2 +- 1 file changed, 1 insertion(+), 1 deletion(-) diff --git a/clients/webassembly/js-example/webpack.config.js b/clients/webassembly/js-example/webpack.config.js index 6086e52425..8f75bb7d57 100644 --- a/clients/webassembly/js-example/webpack.config.js +++ b/clients/webassembly/js-example/webpack.config.js @@ -9,7 +9,7 @@ module.exports = { }, mode: "development", plugins: [ - new CopyWebpackPlugin({patterns: ['index.html']}) + new CopyWebpackPlugin({ patterns: ['index.html'] }) ], experiments: { asyncWebAssembly: true } }; From bb9753cda67f89a324e4b06f4c04353440d9feba Mon Sep 17 00:00:00 2001 From: Dave Hrycyszyn Date: Wed, 14 Sep 2022 11:48:25 +0100 Subject: [PATCH 45/46] Switching webassembly client to sync web assembly (async loading doens't work) --- clients/webassembly/js-example/webpack.config.js | 2 +- 1 file changed, 1 insertion(+), 1 deletion(-) diff --git a/clients/webassembly/js-example/webpack.config.js b/clients/webassembly/js-example/webpack.config.js index 8f75bb7d57..e70c197a25 100644 --- a/clients/webassembly/js-example/webpack.config.js +++ b/clients/webassembly/js-example/webpack.config.js @@ -11,5 +11,5 @@ module.exports = { plugins: [ new CopyWebpackPlugin({ patterns: ['index.html'] }) ], - experiments: { asyncWebAssembly: true } + experiments: { syncWebAssembly: true } }; From 2f53e40355327664677a9d1bd8b9538ca08a1f25 Mon Sep 17 00:00:00 2001 From: Dave Hrycyszyn Date: Wed, 14 Sep 2022 11:48:55 +0100 Subject: [PATCH 46/46] Switching to mainnet validator API --- clients/webassembly/js-example/index.js | 6 +++--- 1 file changed, 3 insertions(+), 3 deletions(-) diff --git a/clients/webassembly/js-example/index.js b/clients/webassembly/js-example/index.js index e8d76eff17..7c2d3151d5 100644 --- a/clients/webassembly/js-example/index.js +++ b/clients/webassembly/js-example/index.js @@ -13,8 +13,8 @@ // limitations under the License. import { - NymClient, - set_panic_hook + NymClient, + set_panic_hook } from "@nymproject/nym-client-wasm" // current limitation of rust-wasm for async stuff : ( @@ -25,7 +25,7 @@ async function main() { set_panic_hook(); // validator server we will use to get topology from - const validator = "https://sandbox-validator.nymtech.net/api"; //"http://localhost:8081"; + const validator = "https://validator.nymtech.net/api"; //"http://localhost:8081"; client = new NymClient(validator);