Skip to content
New issue

Have a question about this project? Sign up for a free GitHub account to open an issue and contact its maintainers and the community.

By clicking “Sign up for GitHub”, you agree to our terms of service and privacy statement. We’ll occasionally send you account related emails.

Already on GitHub? Sign in to your account

Total mix stake accounting #794

Merged
merged 10 commits into from
Oct 4, 2021
Merged
Show file tree
Hide file tree
Changes from all commits
Commits
File filter

Filter by extension

Filter by extension


Conversations
Failed to load comments.
Loading
Jump to
Jump to file
Failed to load files.
Loading
Diff view
Diff view
3 changes: 2 additions & 1 deletion Cargo.lock

Some generated files are not rendered by default. Learn more about how customized files appear on GitHub.

4 changes: 2 additions & 2 deletions clients/client-core/src/client/mix_traffic.rs
Original file line number Diff line number Diff line change
Expand Up @@ -40,7 +40,7 @@ impl MixTrafficController {
async fn on_messages(&mut self, mut mix_packets: Vec<MixPacket>) {
debug_assert!(!mix_packets.is_empty());

let success = if mix_packets.len() == 1 {
let result = if mix_packets.len() == 1 {
let mix_packet = mix_packets.pop().unwrap();
self.gateway_client.send_mix_packet(mix_packet).await
} else {
Expand All @@ -49,7 +49,7 @@ impl MixTrafficController {
.await
};

match success {
match result {
Err(e) => {
error!("Failed to send sphinx packet(s) to the gateway! - {:?}", e);
self.consecutive_gateway_failure_count += 1;
Expand Down
24 changes: 15 additions & 9 deletions common/client-libs/gateway-client/src/client.rs
Original file line number Diff line number Diff line change
Expand Up @@ -36,8 +36,7 @@ const DEFAULT_RECONNECTION_BACKOFF: Duration = Duration::from_secs(5);

pub struct GatewayClient {
authenticated: bool,
// TODO: This should be replaced by an actual bandwidth value, with 0 meaning no bandwidth
has_bandwidth: bool,
bandwidth_remaining: i64,
gateway_address: String,
gateway_identity: identity::PublicKey,
local_identity: Arc<identity::KeyPair>,
Expand Down Expand Up @@ -72,7 +71,7 @@ impl GatewayClient {
) -> Self {
GatewayClient {
authenticated: false,
has_bandwidth: false,
bandwidth_remaining: 0,
gateway_address,
gateway_identity,
local_identity,
Expand Down Expand Up @@ -117,7 +116,7 @@ impl GatewayClient {

GatewayClient {
authenticated: false,
has_bandwidth: false,
bandwidth_remaining: 0,
gateway_address,
gateway_identity,
local_identity,
Expand Down Expand Up @@ -474,22 +473,29 @@ impl GatewayClient {
)
.ok_or(GatewayClientError::SerializeCredential)?
.into();
self.has_bandwidth = match self.send_websocket_message(msg).await? {
ServerResponse::Bandwidth { status } => Ok(status),
self.bandwidth_remaining = match self.send_websocket_message(msg).await? {
ServerResponse::Bandwidth { available_total } => Ok(available_total),
ServerResponse::Error { message } => Err(GatewayClientError::GatewayError(message)),
_ => Err(GatewayClientError::UnexpectedResponse),
}?;
Ok(())
}

fn estimate_required_bandwidth(&self, packets: &[MixPacket]) -> i64 {
packets
.iter()
.map(|packet| packet.sphinx_packet().len())
.sum::<usize>() as i64
}

pub async fn batch_send_mix_packets(
&mut self,
packets: Vec<MixPacket>,
) -> Result<(), GatewayClientError> {
if !self.authenticated {
return Err(GatewayClientError::NotAuthenticated);
}
if !self.has_bandwidth {
if self.estimate_required_bandwidth(&packets) < self.bandwidth_remaining {
return Err(GatewayClientError::NotEnoughBandwidth);
}
if !self.connection.is_established() {
Expand Down Expand Up @@ -550,7 +556,7 @@ impl GatewayClient {
if !self.authenticated {
return Err(GatewayClientError::NotAuthenticated);
}
if !self.has_bandwidth {
if (mix_packet.sphinx_packet().len() as i64) > self.bandwidth_remaining {
return Err(GatewayClientError::NotEnoughBandwidth);
}
if !self.connection.is_established() {
Expand Down Expand Up @@ -598,7 +604,7 @@ impl GatewayClient {
if !self.authenticated {
return Err(GatewayClientError::NotAuthenticated);
}
if !self.has_bandwidth {
if self.bandwidth_remaining <= 0 {
return Err(GatewayClientError::NotEnoughBandwidth);
}
if self.connection.is_partially_delegated() {
Expand Down
76 changes: 74 additions & 2 deletions common/client-libs/validator-client/src/client.rs
Original file line number Diff line number Diff line change
Expand Up @@ -10,6 +10,8 @@ use mixnet_contract::StateParams;

use crate::{validator_api, ValidatorClientError};
use coconut_interface::{BlindSignRequestBody, BlindedSignatureResponse, VerificationKeyResponse};
#[cfg(feature = "nymd-client")]
use mixnet_contract::RawDelegationData;
use mixnet_contract::{GatewayBond, MixNodeBond};
use url::Url;

Expand Down Expand Up @@ -180,6 +182,20 @@ impl<C> Client<C> {
Ok(self.nymd.get_state_params().await?)
}

pub async fn get_total_mix_stake(&self) -> Result<u128, ValidatorClientError>
where
C: CosmWasmClient + Sync,
{
Ok(self.nymd.get_total_mix_stake().await?.u128())
}

pub async fn get_total_gateway_stake(&self) -> Result<u128, ValidatorClientError>
where
C: CosmWasmClient + Sync,
{
Ok(self.nymd.get_total_gateway_stake().await?.u128())
}

// basically handles paging for us
pub async fn get_all_nymd_mixnodes(&self) -> Result<Vec<MixNodeBond>, ValidatorClientError>
where
Expand Down Expand Up @@ -227,7 +243,7 @@ impl<C> Client<C> {
Ok(gateways)
}

pub async fn get_all_nymd_mixnode_delegations(
pub async fn get_all_nymd_single_mixnode_delegations(
&self,
identity: mixnet_contract::IdentityKey,
) -> Result<Vec<mixnet_contract::Delegation>, ValidatorClientError>
Expand Down Expand Up @@ -257,6 +273,34 @@ impl<C> Client<C> {
Ok(delegations)
}

pub async fn get_all_nymd_mixnode_delegations(
&self,
) -> Result<Vec<mixnet_contract::UnpackedDelegation<RawDelegationData>>, ValidatorClientError>
where
C: CosmWasmClient + Sync,
{
let mut delegations = Vec::new();
let mut start_after = None;
loop {
let mut paged_response = self
.nymd
.get_all_mix_delegations_paged(
start_after.take(),
self.mixnode_delegations_page_limit,
)
.await?;
delegations.append(&mut paged_response.delegations);

if let Some(start_after_res) = paged_response.start_next_after {
start_after = Some(start_after_res)
} else {
break;
}
}

Ok(delegations)
}

pub async fn get_all_nymd_reverse_mixnode_delegations(
&self,
delegation_owner: &cosmrs::AccountId,
Expand Down Expand Up @@ -309,7 +353,7 @@ impl<C> Client<C> {
Ok(delegations)
}

pub async fn get_all_nymd_gateway_delegations(
pub async fn get_all_nymd_single_gateway_delegations(
&self,
identity: mixnet_contract::IdentityKey,
) -> Result<Vec<mixnet_contract::Delegation>, ValidatorClientError>
Expand Down Expand Up @@ -339,6 +383,34 @@ impl<C> Client<C> {
Ok(delegations)
}

pub async fn get_all_nymd_gateway_delegations(
&self,
) -> Result<Vec<mixnet_contract::UnpackedDelegation<RawDelegationData>>, ValidatorClientError>
where
C: CosmWasmClient + Sync,
{
let mut delegations = Vec::new();
let mut start_after = None;
loop {
let mut paged_response = self
.nymd
.get_all_gateway_delegations(
start_after.take(),
self.gateway_delegations_page_limit,
)
.await?;
delegations.append(&mut paged_response.delegations);

if let Some(start_after_res) = paged_response.start_next_after {
start_after = Some(start_after_res)
} else {
break;
}
}

Ok(delegations)
}

pub async fn get_all_nymd_reverse_gateway_delegations(
&self,
delegation_owner: &cosmrs::AccountId,
Expand Down
69 changes: 63 additions & 6 deletions common/client-libs/validator-client/src/nymd/mod.rs
Original file line number Diff line number Diff line change
Expand Up @@ -12,13 +12,13 @@ use crate::nymd::wallet::DirectSecp256k1HdWallet;
use cosmrs::rpc::endpoint::broadcast;
use cosmrs::rpc::{Error as TendermintRpcError, HttpClientUrl};

use cosmwasm_std::Coin;
use cosmwasm_std::{Coin, Uint128};
use mixnet_contract::{
Addr, Delegation, ExecuteMsg, Gateway, GatewayOwnershipResponse, IdentityKey,
LayerDistribution, MixNode, MixOwnershipResponse, PagedGatewayDelegationsResponse,
PagedGatewayResponse, PagedMixDelegationsResponse, PagedMixnodeResponse,
PagedReverseGatewayDelegationsResponse, PagedReverseMixDelegationsResponse, QueryMsg,
StateParams,
LayerDistribution, MixNode, MixOwnershipResponse, PagedAllDelegationsResponse,
PagedGatewayDelegationsResponse, PagedGatewayResponse, PagedMixDelegationsResponse,
PagedMixnodeResponse, PagedReverseGatewayDelegationsResponse,
PagedReverseMixDelegationsResponse, QueryMsg, RawDelegationData, StateParams,
};
use serde::Serialize;
use std::collections::HashMap;
Expand Down Expand Up @@ -198,6 +198,26 @@ impl<C> NymdClient<C> {
.await
}

pub async fn get_total_mix_stake(&self) -> Result<Uint128, NymdError>
where
C: CosmWasmClient + Sync,
{
let request = QueryMsg::GetTotalMixStake {};
self.client
.query_contract_smart(self.contract_address()?, &request)
.await
}

pub async fn get_total_gateway_stake(&self) -> Result<Uint128, NymdError>
where
C: CosmWasmClient + Sync,
{
let request = QueryMsg::GetTotalGatewayStake {};
self.client
.query_contract_smart(self.contract_address()?, &request)
.await
}

/// Checks whether there is a bonded mixnode associated with the provided client's address
pub async fn owns_mixnode(&self, address: &AccountId) -> Result<bool, NymdError>
where
Expand Down Expand Up @@ -283,6 +303,25 @@ impl<C> NymdClient<C> {
.await
}

/// Gets list of all mixnode delegations on particular page.
pub async fn get_all_mix_delegations_paged(
&self,
// I really hate mixing cosmwasm and cosmos-sdk types here...
start_after: Option<Vec<u8>>,
page_limit: Option<u32>,
) -> Result<PagedAllDelegationsResponse<RawDelegationData>, NymdError>
where
C: CosmWasmClient + Sync,
{
let request = QueryMsg::GetAllMixDelegations {
start_after,
limit: page_limit,
};
self.client
.query_contract_smart(self.contract_address()?, &request)
.await
}

/// Gets list of all the mixnodes on which a particular address delegated.
pub async fn get_reverse_mix_delegations_paged(
&self,
Expand Down Expand Up @@ -321,7 +360,7 @@ impl<C> NymdClient<C> {
.await
}

/// Gets list of all delegations towards particular mixnode on particular page.
/// Gets list of all delegations towards particular gateway on particular page.
pub async fn get_gateway_delegations(
&self,
gateway_identity: IdentityKey,
Expand All @@ -341,6 +380,24 @@ impl<C> NymdClient<C> {
.await
}

/// Gets list of all gateway delegations on particular page.
pub async fn get_all_gateway_delegations(
&self,
start_after: Option<Vec<u8>>,
page_limit: Option<u32>,
) -> Result<PagedAllDelegationsResponse<RawDelegationData>, NymdError>
where
C: CosmWasmClient + Sync,
{
let request = QueryMsg::GetAllGatewayDelegations {
start_after,
limit: page_limit,
};
self.client
.query_contract_smart(self.contract_address()?, &request)
.await
}

/// Gets list of all the gateways on which a particular address delegated.
pub async fn get_reverse_gateway_delegations_paged(
&self,
Expand Down
2 changes: 1 addition & 1 deletion common/credentials/src/bandwidth.rs
Original file line number Diff line number Diff line change
Expand Up @@ -12,7 +12,7 @@ use crate::error::Error;
use crate::utils::{obtain_aggregate_signature, prepare_credential_for_spending};
use coconut_interface::{hash_to_scalar, Credential, Parameters, Signature, VerificationKey};

const BANDWIDTH_VALUE: u64 = 1024 * 1024; // 1 MB
const BANDWIDTH_VALUE: u64 = 10 * 1024 * 1024 * 1024; // 10 GB

pub const PUBLIC_ATTRIBUTES: u32 = 1;
pub const PRIVATE_ATTRIBUTES: u32 = 1;
Expand Down
34 changes: 33 additions & 1 deletion common/mixnet-contract/src/delegation.rs
Original file line number Diff line number Diff line change
Expand Up @@ -7,7 +7,24 @@ use schemars::JsonSchema;
use serde::{Deserialize, Serialize};
use std::fmt::Display;

#[derive(Debug, Deserialize, PartialEq, Serialize)]
#[derive(Clone, Debug, Deserialize, PartialEq, Serialize, JsonSchema)]
pub struct UnpackedDelegation<T> {
pub owner: Addr,
pub node_identity: IdentityKey,
pub delegation_data: T,
}

impl<T> UnpackedDelegation<T> {
pub fn new(owner: Addr, node_identity: IdentityKey, delegation_data: T) -> Self {
UnpackedDelegation {
owner,
node_identity,
delegation_data,
}
}
}

#[derive(Clone, Debug, Deserialize, PartialEq, Serialize, JsonSchema)]
pub struct RawDelegationData {
pub amount: Uint128,
pub block_height: u64,
Expand Down Expand Up @@ -144,3 +161,18 @@ impl PagedReverseGatewayDelegationsResponse {
}
}
}

#[derive(Clone, Debug, Deserialize, PartialEq, Serialize, JsonSchema)]
pub struct PagedAllDelegationsResponse<T> {
pub delegations: Vec<UnpackedDelegation<T>>,
pub start_next_after: Option<Vec<u8>>,
}

impl<T> PagedAllDelegationsResponse<T> {
pub fn new(delegations: Vec<UnpackedDelegation<T>>, start_next_after: Option<Vec<u8>>) -> Self {
PagedAllDelegationsResponse {
delegations,
start_next_after,
}
}
}
4 changes: 4 additions & 0 deletions common/mixnet-contract/src/gateway.rs
Original file line number Diff line number Diff line change
Expand Up @@ -59,6 +59,10 @@ impl GatewayBond {
pub fn gateway(&self) -> &Gateway {
&self.gateway
}

pub fn total_delegation(&self) -> Coin {
self.total_delegation.clone()
}
}

impl PartialOrd for GatewayBond {
Expand Down
Loading