diff --git a/.wellknown/wallet/connect/service-providers.json b/.wellknown/wallet/connect/service-providers.json
index c3749d6bd8..315b99d865 100644
--- a/.wellknown/wallet/connect/service-providers.json
+++ b/.wellknown/wallet/connect/service-providers.json
@@ -1,13 +1,13 @@
[
{
- "id": "nym-testing",
- "description": "coconuts",
+ "id": "Coconut",
+ "description": "Bandwidth Test",
"items": [
{
- "id": "nym-coconut",
- "description": "nym-credentials",
- "address": "",
- "gateway": ""
+ "id": "cocos",
+ "description": "testing",
+ "address": "51RhttA7LhKp573QWUU74uaFuoyb4Bg2cqNUaiuTRAMb.GW9e3T5TQvn5iyvdTVnhTWaZ9WLCaBvA8XVdnw4xL9DW@EVupP2tRUeZo5Y6RpBHAbm8kSntpgNyZNL6yCr7BDEoG",
+ "gateway": "EVupP2tRUeZo5Y6RpBHAbm8kSntpgNyZNL6yCr7BDEoG"
}
]
}
diff --git a/CHANGELOG.md b/CHANGELOG.md
index 7f3274b4e1..6a37e4e27a 100644
--- a/CHANGELOG.md
+++ b/CHANGELOG.md
@@ -2,6 +2,12 @@
Post 1.0.0 release, the changelog format is based on [Keep a Changelog](https://keepachangelog.com/en/1.0.0/), and this project adheres to [Semantic Versioning](https://semver.org/spec/v2.0.0.html).
+## [Unreleased]
+
+### Changed
+
+- gateway: Renamed flag from `enabled/disabled_credentials_mode` to `only-coconut-credentials`
+
## [v1.1.1](https://github.com/nymtech/nym/tree/v1.1.1) (2022-11-29)
### Added
diff --git a/Cargo.lock b/Cargo.lock
index 7dfcda47ff..e81281023f 100644
--- a/Cargo.lock
+++ b/Cargo.lock
@@ -923,7 +923,6 @@ dependencies = [
name = "credential"
version = "0.1.0"
dependencies = [
- "async-trait",
"bip39",
"cfg-if 0.1.10",
"clap 3.2.8",
@@ -935,7 +934,6 @@ dependencies = [
"crypto",
"network-defaults",
"pemstore",
- "pickledb",
"rand 0.7.3",
"serde",
"thiserror",
@@ -2745,12 +2743,6 @@ dependencies = [
"vcpkg",
]
-[[package]]
-name = "linked-hash-map"
-version = "0.5.4"
-source = "registry+https://github.com/rust-lang/crates.io-index"
-checksum = "7fb9b38af92608140b86b693604b9ffcc5824240a484d1ecd4795bacb2fe88f3"
-
[[package]]
name = "lioness"
version = "0.1.2"
@@ -3934,19 +3926,6 @@ dependencies = [
"indexmap",
]
-[[package]]
-name = "pickledb"
-version = "0.4.1"
-source = "registry+https://github.com/rust-lang/crates.io-index"
-checksum = "9161694d67f6c5163519d42be942ae36bbdb55f439460144f105bc4f9f7d1d61"
-dependencies = [
- "bincode",
- "serde",
- "serde_cbor",
- "serde_json",
- "serde_yaml",
-]
-
[[package]]
name = "pin-project"
version = "1.0.10"
@@ -5057,18 +5036,6 @@ dependencies = [
"serde",
]
-[[package]]
-name = "serde_yaml"
-version = "0.8.23"
-source = "registry+https://github.com/rust-lang/crates.io-index"
-checksum = "a4a521f2940385c165a24ee286aa8599633d162077a54bdcae2a6fd5a7bfa7a0"
-dependencies = [
- "indexmap",
- "ryu",
- "serde",
- "yaml-rust",
-]
-
[[package]]
name = "sha-1"
version = "0.8.2"
@@ -6938,15 +6905,6 @@ dependencies = [
"zeroize",
]
-[[package]]
-name = "yaml-rust"
-version = "0.4.5"
-source = "registry+https://github.com/rust-lang/crates.io-index"
-checksum = "56c1936c4cc7a1c9ab21a1ebb602eb942ba868cbd44a99cb7cdc5892335e1c85"
-dependencies = [
- "linked-hash-map",
-]
-
[[package]]
name = "yansi"
version = "0.5.1"
diff --git a/clients/client-core/src/client/topology_control.rs b/clients/client-core/src/client/topology_control.rs
index b685cfb8b4..9f35f6c3f1 100644
--- a/clients/client-core/src/client/topology_control.rs
+++ b/clients/client-core/src/client/topology_control.rs
@@ -186,13 +186,10 @@ impl TopologyRefresher {
/// # Arguments
///
/// * `topology`: active topology constructed from validator api data
- /// * `mixnodes_count`: total number of active mixnodes
- fn check_layer_distribution(
- &self,
- active_topology: &NymTopology,
- mixnodes_count: usize,
- ) -> bool {
+ fn check_layer_distribution(&self, active_topology: &NymTopology) -> bool {
let mixes = active_topology.mixes();
+ let mixnodes_count = active_topology.num_mixnodes();
+
if active_topology.gateways().is_empty() {
return false;
}
@@ -257,11 +254,10 @@ impl TopologyRefresher {
Ok(gateways) => gateways,
};
- let mixnodes_count = mixnodes.len();
let topology = nym_topology_from_detailed(mixnodes, gateways)
.filter_system_version(&self.client_version);
- if !self.check_layer_distribution(&topology, mixnodes_count) {
+ if !self.check_layer_distribution(&topology) {
warn!("The current filtered active topology has extremely skewed layer distribution. It cannot be used.");
None
} else {
diff --git a/clients/client-core/src/config/mod.rs b/clients/client-core/src/config/mod.rs
index 277fff30b9..b3dc70eb28 100644
--- a/clients/client-core/src/config/mod.rs
+++ b/clients/client-core/src/config/mod.rs
@@ -1,7 +1,7 @@
// Copyright 2021 - Nym Technologies SA
// SPDX-License-Identifier: Apache-2.0
-use config::NymConfig;
+use config::{NymConfig, DB_FILE_NAME};
use nymsphinx::params::PacketSize;
use serde::{Deserialize, Serialize};
use std::marker::PhantomData;
@@ -412,7 +412,7 @@ impl Client {
T::default_data_directory(Some(id)).join("reply_key_store")
}
fn default_database_path(id: &str) -> PathBuf {
- T::default_data_directory(Some(id)).join("db.sqlite")
+ T::default_data_directory(Some(id)).join(DB_FILE_NAME)
}
}
diff --git a/clients/credential/Cargo.toml b/clients/credential/Cargo.toml
index 81fe361ad0..ccf241b1cb 100644
--- a/clients/credential/Cargo.toml
+++ b/clients/credential/Cargo.toml
@@ -6,11 +6,9 @@ edition = "2021"
# See more keys and their definitions at https://doc.rust-lang.org/cargo/reference/manifest.html
[dependencies]
-async-trait = "0.1.52"
bip39 = "1.0.1"
cfg-if = "0.1"
clap = { version = "3.2", features = ["cargo", "derive"] }
-pickledb = "0.4.1"
rand = "0.7.3"
serde = { version = "1.0", features = ["derive"] }
thiserror = "1.0"
diff --git a/clients/credential/src/commands.rs b/clients/credential/src/commands.rs
index 7f9d3ae2e1..5ed4bd8dad 100644
--- a/clients/credential/src/commands.rs
+++ b/clients/credential/src/commands.rs
@@ -1,14 +1,12 @@
// Copyright 2022 - Nym Technologies SA
// SPDX-License-Identifier: Apache-2.0
-use async_trait::async_trait;
use clap::{Args, Subcommand};
use completions::ArgShell;
-use pickledb::PickleDb;
use rand::rngs::OsRng;
use std::str::FromStr;
-use coconut_interface::{Attribute, Base58, BlindSignRequest, Bytable, Parameters};
+use coconut_interface::{Base58, Parameters};
use credential_storage::storage::Storage;
use credential_storage::PersistentStorage;
use credentials::coconut::bandwidth::{BandwidthVoucher, TOTAL_ATTRIBUTES};
@@ -20,16 +18,12 @@ use validator_client::{CoconutApiClient, Config};
use crate::client::Client;
use crate::error::{CredentialClientError, Result};
-use crate::state::{KeyPair, RequestData, State};
+use crate::state::{KeyPair, State};
#[derive(Subcommand)]
-pub(crate) enum Commands {
- /// Deposit funds for buying coconut credential
- Deposit(Deposit),
- /// Lists the tx hashes of previous deposits
- ListDeposits(ListDeposits),
- /// Get a credential for a given deposit
- GetCredential(GetCredential),
+pub(crate) enum Command {
+ /// Run the binary
+ Run(Run),
/// Generate shell completions
Completions(ArgShell),
@@ -38,169 +32,81 @@ pub(crate) enum Commands {
GenerateFigSpec,
}
-#[async_trait]
-pub(crate) trait Execute {
- async fn execute(&self, db: &mut PickleDb, shared_storage: PersistentStorage) -> Result<()>;
-}
+#[derive(Args)]
+pub(crate) struct Run {
+ /// Home directory of the client that is supposed to use the credential.
+ #[clap(long)]
+ pub(crate) client_home_directory: std::path::PathBuf,
-#[derive(Args, Clone)]
-pub(crate) struct Deposit {
/// The nymd URL that should be used
#[clap(long)]
- nymd_url: String,
- /// A mnemonic for the account that does the deposit
+ pub(crate) nymd_url: String,
+
+ /// A mnemonic for the account that buys the credential
#[clap(long)]
- mnemonic: String,
- /// The amount that needs to be deposited
+ pub(crate) mnemonic: String,
+
+ /// The amount of utokens the credential will hold
#[clap(long)]
- amount: u64,
+ pub(crate) amount: u64,
}
-#[async_trait]
-impl Execute for Deposit {
- async fn execute(&self, db: &mut PickleDb, _shared_storage: PersistentStorage) -> Result<()> {
- let mut rng = OsRng;
- let signing_keypair = KeyPair::from(identity::KeyPair::new(&mut rng));
- let encryption_keypair = KeyPair::from(encryption::KeyPair::new(&mut rng));
+pub(crate) async fn deposit(nymd_url: &str, mnemonic: &str, amount: u64) -> Result {
+ let mut rng = OsRng;
+ let signing_keypair = KeyPair::from(identity::KeyPair::new(&mut rng));
+ let encryption_keypair = KeyPair::from(encryption::KeyPair::new(&mut rng));
- let client = Client::new(&self.nymd_url, &self.mnemonic);
- let tx_hash = client
- .deposit(
- self.amount,
- signing_keypair.public_key.clone(),
- encryption_keypair.public_key.clone(),
- None,
- )
- .await?;
-
- let state = State {
- amount: self.amount,
- tx_hash: tx_hash.clone(),
- signing_keypair,
- encryption_keypair,
- blind_request_data: None,
- signature: None,
- };
- db.set(&tx_hash, &state).unwrap();
-
- println!("{:?}", state);
-
- Ok(())
- }
-}
-
-#[derive(Args, Clone)]
-pub(crate) struct ListDeposits {}
-
-#[async_trait]
-impl Execute for ListDeposits {
- async fn execute(&self, db: &mut PickleDb, _shared_storage: PersistentStorage) -> Result<()> {
- for kv in db.iter() {
- println!("{:?}", kv.get_value::());
- }
-
- Ok(())
- }
-}
-
-#[derive(Args, Clone)]
-pub(crate) struct GetCredential {
- /// The hash of a successful deposit transaction
- #[clap(long)]
- tx_hash: String,
- /// The nymd URL that should be used
- #[clap(long)]
- nymd_url: String,
- /// If we want to get the signature without attaching a blind sign request; it is expected that
- /// there is already a signature stored on the signer
- #[clap(long, parse(from_flag))]
- __no_request: bool,
-}
-
-#[async_trait]
-impl Execute for GetCredential {
- async fn execute(&self, db: &mut PickleDb, shared_storage: PersistentStorage) -> Result<()> {
- let mut state = db
- .get::(&self.tx_hash)
- .ok_or(CredentialClientError::NoDeposit)?;
-
- let network_details = NymNetworkDetails::new_from_env();
- let config = Config::try_from_nym_network_details(&network_details)?;
- let client = validator_client::Client::new_query(config)?;
- let coconut_api_clients = CoconutApiClient::all_coconut_api_clients(&client).await?;
-
- let params = Parameters::new(TOTAL_ATTRIBUTES).unwrap();
- let bandwidth_credential_attributes = if self.__no_request {
- if let Some(blind_request_data) = state.blind_request_data {
- let serial_number =
- Attribute::try_from_byte_slice(&blind_request_data.serial_number)
- .map_err(|_| CredentialClientError::CorruptedBlindSignRequest)?;
- let binding_number =
- Attribute::try_from_byte_slice(&blind_request_data.binding_number)
- .map_err(|_| CredentialClientError::CorruptedBlindSignRequest)?;
- let pedersen_commitments_openings = vec![
- Attribute::try_from_byte_slice(&blind_request_data.first_attribute)
- .map_err(|_| CredentialClientError::CorruptedBlindSignRequest)?,
- Attribute::try_from_byte_slice(&blind_request_data.second_attribute)
- .map_err(|_| CredentialClientError::CorruptedBlindSignRequest)?,
- ];
- let blind_sign_request =
- BlindSignRequest::from_bytes(blind_request_data.blind_sign_req.as_slice())
- .map_err(|_| CredentialClientError::CorruptedBlindSignRequest)?;
- BandwidthVoucher::new_with_blind_sign_req(
- [serial_number, binding_number],
- [&state.amount.to_string(), VOUCHER_INFO],
- Hash::from_str(&self.tx_hash)
- .map_err(|_| CredentialClientError::InvalidTxHash)?,
- identity::PrivateKey::from_base58_string(&state.signing_keypair.private_key)?,
- encryption::PrivateKey::from_base58_string(
- &state.encryption_keypair.private_key,
- )?,
- pedersen_commitments_openings,
- blind_sign_request,
- )
- } else {
- return Err(CredentialClientError::NoLocalBlindSignRequest);
- }
- } else {
- BandwidthVoucher::new(
- ¶ms,
- state.amount.to_string(),
- VOUCHER_INFO.to_string(),
- Hash::from_str(&self.tx_hash).map_err(|_| CredentialClientError::InvalidTxHash)?,
- identity::PrivateKey::from_base58_string(&state.signing_keypair.private_key)?,
- encryption::PrivateKey::from_base58_string(&state.encryption_keypair.private_key)?,
- )
- };
-
- // Back up the blind sign req data, in case of sporadic failures
- state.blind_request_data = Some(RequestData::new(
- bandwidth_credential_attributes.get_private_attributes(),
- bandwidth_credential_attributes.pedersen_commitments_openings(),
- bandwidth_credential_attributes.blind_sign_request(),
- )?);
- db.set(&self.tx_hash, &state).unwrap();
-
- let signature = obtain_aggregate_signature(
- ¶ms,
- &bandwidth_credential_attributes,
- &coconut_api_clients,
+ let client = Client::new(nymd_url, mnemonic);
+ let tx_hash = client
+ .deposit(
+ amount,
+ signing_keypair.public_key.clone(),
+ encryption_keypair.public_key.clone(),
+ None,
)
.await?;
- shared_storage
- .insert_coconut_credential(
- state.amount.to_string(),
- VOUCHER_INFO.to_string(),
- bandwidth_credential_attributes.get_private_attributes()[0].to_bs58(),
- bandwidth_credential_attributes.get_private_attributes()[1].to_bs58(),
- signature.to_bs58(),
- )
- .await?;
- state.signature = Some(signature.to_bs58());
- db.set(&self.tx_hash, &state).unwrap();
- println!("Signature: {:?}", state.signature);
+ let state = State {
+ amount,
+ tx_hash: tx_hash.clone(),
+ signing_keypair,
+ encryption_keypair,
+ };
- Ok(())
- }
+ Ok(state)
+}
+
+pub(crate) async fn get_credential(state: &State, shared_storage: PersistentStorage) -> Result<()> {
+ let network_details = NymNetworkDetails::new_from_env();
+ let config = Config::try_from_nym_network_details(&network_details)?;
+ let client = validator_client::Client::new_query(config)?;
+ let coconut_api_clients = CoconutApiClient::all_coconut_api_clients(&client).await?;
+
+ let params = Parameters::new(TOTAL_ATTRIBUTES).unwrap();
+ let bandwidth_credential_attributes = BandwidthVoucher::new(
+ ¶ms,
+ state.amount.to_string(),
+ VOUCHER_INFO.to_string(),
+ Hash::from_str(&state.tx_hash).map_err(|_| CredentialClientError::InvalidTxHash)?,
+ identity::PrivateKey::from_base58_string(&state.signing_keypair.private_key)?,
+ encryption::PrivateKey::from_base58_string(&state.encryption_keypair.private_key)?,
+ );
+
+ let signature = obtain_aggregate_signature(
+ ¶ms,
+ &bandwidth_credential_attributes,
+ &coconut_api_clients,
+ )
+ .await?;
+ shared_storage
+ .insert_coconut_credential(
+ state.amount.to_string(),
+ VOUCHER_INFO.to_string(),
+ bandwidth_credential_attributes.get_private_attributes()[0].to_bs58(),
+ bandwidth_credential_attributes.get_private_attributes()[1].to_bs58(),
+ signature.to_bs58(),
+ )
+ .await?;
+
+ Ok(())
}
diff --git a/clients/credential/src/error.rs b/clients/credential/src/error.rs
index 08bd0001e9..5cbc636e58 100644
--- a/clients/credential/src/error.rs
+++ b/clients/credential/src/error.rs
@@ -23,18 +23,6 @@ pub enum CredentialClientError {
#[error("Credential error: {0}")]
Credential(#[from] CredentialError),
- #[error("No previous deposit with that tx hash")]
- NoDeposit,
-
- #[error("Wrong number of attributes")]
- WrongAttributeNumber,
-
- #[error("Could not find any backed up blind sign request data")]
- NoLocalBlindSignRequest,
-
- #[error("The local blind sign request data is corrupted")]
- CorruptedBlindSignRequest,
-
#[error("The tx hash provided is not valid")]
InvalidTxHash,
diff --git a/clients/credential/src/main.rs b/clients/credential/src/main.rs
index cc0263e048..f413673626 100644
--- a/clients/credential/src/main.rs
+++ b/clients/credential/src/main.rs
@@ -9,14 +9,13 @@ cfg_if::cfg_if! {
mod error;
mod state;
- use commands::{Commands, Execute};
use error::Result;
use network_defaults::setup_env;
- use clap::CommandFactory;
use completions::fig_generate;
+ use commands::*;
+ use config::{DATA_DIR, DB_FILE_NAME};
- use clap::Parser;
- use pickledb::{PickleDb, PickleDbDumpPolicy, SerializationMethod};
+ use clap::{CommandFactory, Parser};
#[derive(Parser)]
#[clap(author = "Nymtech", version, about)]
@@ -25,43 +24,26 @@ cfg_if::cfg_if! {
#[clap(short, long)]
pub(crate) config_env_file: Option,
- /// Path where the sqlite credental database will be located.
- /// It should point to a $HOME/$CLIENT_ID/data/db.sqlite file of
- /// the client that is supposed to use the credential.
- #[clap(long)]
- pub(crate) credential_db_path: std::path::PathBuf,
-
#[clap(subcommand)]
- command: Commands,
+ pub(crate) command: Command,
}
#[tokio::main]
async fn main() -> Result<()> {
let args = Cli::parse();
setup_env(args.config_env_file.clone());
-
- let shared_storage = credential_storage::initialise_storage(args.credential_db_path.clone()).await;
- let mut db = match PickleDb::load(
- "credential.db",
- PickleDbDumpPolicy::AutoDump,
- SerializationMethod::Json,
- ) {
- Ok(db) => db,
- Err(_) => PickleDb::new(
- "credential.db",
- PickleDbDumpPolicy::AutoDump,
- SerializationMethod::Json,
- ),
- };
-
let bin_name = "nym-credential-client";
- match &args.command {
- Commands::Deposit(m) => m.execute(&mut db, shared_storage).await?,
- Commands::ListDeposits(m) => m.execute(&mut db, shared_storage).await?,
- Commands::GetCredential(m) => m.execute(&mut db, shared_storage).await?,
- Commands::Completions(s) => s.generate(&mut crate::Cli::into_app(), bin_name),
- Commands::GenerateFigSpec => fig_generate(&mut crate::Cli::into_app(), bin_name)
+ match args.command {
+ Command::Run(r) => {
+ let db_path = r.client_home_directory.join(DATA_DIR).join(DB_FILE_NAME);
+ let shared_storage = credential_storage::initialise_storage(db_path).await;
+
+ let state = deposit(&r.nymd_url, &r.mnemonic, r.amount).await?;
+ get_credential(&state, shared_storage).await?;
+ }
+ Command::Completions(c) => c.generate(&mut crate::Cli::into_app(), bin_name),
+ Command::GenerateFigSpec => fig_generate(&mut crate::Cli::into_app(), bin_name)
}
Ok(())
diff --git a/clients/credential/src/state.rs b/clients/credential/src/state.rs
index 6da1ae6faa..98cbb307df 100644
--- a/clients/credential/src/state.rs
+++ b/clients/credential/src/state.rs
@@ -1,13 +1,10 @@
// Copyright 2022 - Nym Technologies SA
// SPDX-License-Identifier: Apache-2.0
-use coconut_interface::{Attribute, BlindSignRequest, Bytable, PrivateAttribute};
use serde::{Deserialize, Serialize};
use crypto::asymmetric::{encryption, identity};
-use crate::error::{CredentialClientError, Result};
-
#[derive(Clone, Debug, Deserialize, Serialize)]
pub(crate) struct KeyPair {
pub public_key: String,
@@ -38,35 +35,4 @@ pub(crate) struct State {
pub tx_hash: String,
pub signing_keypair: KeyPair,
pub encryption_keypair: KeyPair,
- pub blind_request_data: Option,
- pub signature: Option,
-}
-
-#[derive(Clone, Debug, Deserialize, Serialize)]
-pub(crate) struct RequestData {
- pub serial_number: Vec,
- pub binding_number: Vec,
- pub first_attribute: Vec,
- pub second_attribute: Vec,
- pub blind_sign_req: Vec,
-}
-
-impl RequestData {
- pub fn new(
- private_attributes: Vec,
- attributes: &[Attribute],
- blind_sign_request: &BlindSignRequest,
- ) -> Result {
- if private_attributes.len() != 2 || attributes.len() != 2 {
- Err(CredentialClientError::WrongAttributeNumber)
- } else {
- Ok(RequestData {
- serial_number: private_attributes[0].to_byte_vec(),
- binding_number: private_attributes[1].to_byte_vec(),
- first_attribute: attributes[0].to_byte_vec(),
- second_attribute: attributes[1].to_byte_vec(),
- blind_sign_req: blind_sign_request.to_bytes(),
- })
- }
- }
}
diff --git a/common/client-libs/validator-client/src/client.rs b/common/client-libs/validator-client/src/client.rs
index 8ddce33a4f..6a218f1fa2 100644
--- a/common/client-libs/validator-client/src/client.rs
+++ b/common/client-libs/validator-client/src/client.rs
@@ -1,6 +1,5 @@
// Copyright 2021 - Nym Technologies SA
// SPDX-License-Identifier: Apache-2.0
-
use crate::{validator_api, ValidatorClientError};
use coconut_dkg_common::types::NodeIndex;
#[cfg(feature = "nymd-client")]
@@ -10,9 +9,10 @@ use coconut_dkg_common::{
#[cfg(feature = "nymd-client")]
use coconut_interface::Base58;
use coconut_interface::VerificationKey;
+use mixnet_contract_common::families::{Family, FamilyHead};
use mixnet_contract_common::mixnode::MixNodeDetails;
-use mixnet_contract_common::MixId;
use mixnet_contract_common::{GatewayBond, IdentityKeyRef};
+use mixnet_contract_common::{IdentityKey, MixId};
#[cfg(feature = "nymd-client")]
use std::str::FromStr;
use validator_api_requests::coconut::{
@@ -220,6 +220,7 @@ impl Client {
impl Client {
// use case: somebody initialised client without a contract in order to upload and initialise one
// and now they want to actually use it without making new client
+
pub fn set_mixnet_contract_address(&mut self, mixnet_contract_address: cosmrs::AccountId) {
self.nymd
.set_mixnet_contract_address(mixnet_contract_address)
@@ -229,6 +230,56 @@ impl Client {
self.nymd.mixnet_contract_address().clone()
}
+ pub async fn get_all_node_families(&self) -> Result, ValidatorClientError>
+ where
+ C: CosmWasmClient + Sync + Send,
+ {
+ let mut families = Vec::new();
+ let mut start_after = None;
+
+ loop {
+ let paged_response = self
+ .nymd
+ .get_all_node_families_paged(start_after.take(), None)
+ .await?;
+ families.extend(paged_response.families);
+
+ if let Some(start_after_res) = paged_response.start_next_after {
+ start_after = Some(start_after_res)
+ } else {
+ break;
+ }
+ }
+
+ Ok(families)
+ }
+
+ pub async fn get_all_family_members(
+ &self,
+ ) -> Result, ValidatorClientError>
+ where
+ C: CosmWasmClient + Sync + Send,
+ {
+ let mut members = Vec::new();
+ let mut start_after = None;
+
+ loop {
+ let paged_response = self
+ .nymd
+ .get_all_family_members_paged(start_after.take(), None)
+ .await?;
+ members.extend(paged_response.members);
+
+ if let Some(start_after_res) = paged_response.start_next_after {
+ start_after = Some(start_after_res)
+ } else {
+ break;
+ }
+ }
+
+ Ok(members)
+ }
+
// basically handles paging for us
pub async fn get_all_nymd_rewarded_set_mixnodes(
&self,
diff --git a/common/client-libs/validator-client/src/nymd/traits/mixnet_query_client.rs b/common/client-libs/validator-client/src/nymd/traits/mixnet_query_client.rs
index 675c15c5d1..8c6c2e8d41 100644
--- a/common/client-libs/validator-client/src/nymd/traits/mixnet_query_client.rs
+++ b/common/client-libs/validator-client/src/nymd/traits/mixnet_query_client.rs
@@ -7,6 +7,7 @@ use crate::nymd::NymdClient;
use async_trait::async_trait;
use cosmrs::AccountId;
use mixnet_contract_common::delegation::{MixNodeDelegationResponse, OwnerProxySubKey};
+use mixnet_contract_common::families::Family;
use mixnet_contract_common::mixnode::{
MixNodeDetails, MixnodeRewardingDetailsResponse, PagedMixnodesDetailsResponse,
PagedUnbondedMixnodesResponse, StakeSaturationResponse, UnbondedMixnodeResponse,
@@ -20,9 +21,9 @@ use mixnet_contract_common::{
CurrentIntervalResponse, EpochEventId, GatewayBondResponse, GatewayOwnershipResponse,
IdentityKey, IntervalEventId, LayerDistribution, MixId, MixOwnershipResponse,
MixnodeDetailsResponse, PagedAllDelegationsResponse, PagedDelegatorDelegationsResponse,
- PagedGatewayResponse, PagedMixNodeDelegationsResponse, PagedMixnodeBondsResponse,
- PagedRewardedSetResponse, PendingEpochEventsResponse, PendingIntervalEventsResponse,
- QueryMsg as MixnetQueryMsg,
+ PagedFamiliesResponse, PagedGatewayResponse, PagedMembersResponse,
+ PagedMixNodeDelegationsResponse, PagedMixnodeBondsResponse, PagedRewardedSetResponse,
+ PendingEpochEventsResponse, PendingIntervalEventsResponse, QueryMsg as MixnetQueryMsg,
};
use serde::Deserialize;
@@ -73,6 +74,24 @@ pub trait MixnetQueryClient {
.await
}
+ async fn get_all_node_families_paged(
+ &self,
+ start_after: Option,
+ limit: Option,
+ ) -> Result {
+ self.query_mixnet_contract(MixnetQueryMsg::GetAllFamiliesPaged { limit, start_after })
+ .await
+ }
+
+ async fn get_all_family_members_paged(
+ &self,
+ start_after: Option,
+ limit: Option,
+ ) -> Result {
+ self.query_mixnet_contract(MixnetQueryMsg::GetAllMembersPaged { limit, start_after })
+ .await
+ }
+
// mixnode-related:
async fn get_mixnode_bonds_paged(
@@ -357,6 +376,20 @@ pub trait MixnetQueryClient {
})
.await
}
+
+ async fn get_node_family_by_label(&self, label: &str) -> Result