merge develop
This commit is contained in:
@@ -22,6 +22,8 @@ jobs:
|
||||
node-version: '14'
|
||||
- run: npm install
|
||||
continue-on-error: true
|
||||
- name: Set environment from the example
|
||||
run: cp .env.prod .env
|
||||
- run: npm run test
|
||||
continue-on-error: true
|
||||
- run: npm run build
|
||||
|
||||
@@ -0,0 +1,31 @@
|
||||
all: clippy test fmt
|
||||
clippy: clippy-main clippy-contracts clippy-wallet
|
||||
test: test-main test-contracts test-wallet
|
||||
fmt: fmt-main fmt-contracts fmt-wallet
|
||||
|
||||
clippy-main:
|
||||
cargo clippy
|
||||
|
||||
clippy-contracts:
|
||||
cargo clippy --manifest-path contracts/Cargo.toml
|
||||
|
||||
clippy-wallet:
|
||||
cargo clippy --manifest-path nym-wallet/Cargo.toml
|
||||
|
||||
test-main:
|
||||
cargo test
|
||||
|
||||
test-contracts:
|
||||
cargo test --manifest-path contracts/Cargo.toml
|
||||
|
||||
test-wallet:
|
||||
cargo test --manifest-path nym-wallet/Cargo.toml
|
||||
|
||||
fmt-main:
|
||||
cargo fmt --all
|
||||
|
||||
fmt-contracts:
|
||||
cargo fmt --manifest-path contracts/Cargo.toml --all
|
||||
|
||||
fmt-wallet:
|
||||
cargo fmt --manifest-path nym-wallet/Cargo.toml --all
|
||||
@@ -94,6 +94,7 @@ impl Client<SigningNymdClient> {
|
||||
config.mixnet_contract_address.clone(),
|
||||
config.vesting_contract_address.clone(),
|
||||
mnemonic.clone(),
|
||||
None,
|
||||
)?;
|
||||
|
||||
Ok(Client {
|
||||
@@ -114,6 +115,7 @@ impl Client<SigningNymdClient> {
|
||||
self.mixnet_contract_address.clone(),
|
||||
self.vesting_contract_address.clone(),
|
||||
self.mnemonic.clone().unwrap(),
|
||||
None,
|
||||
)?;
|
||||
Ok(())
|
||||
}
|
||||
|
||||
@@ -4,7 +4,7 @@
|
||||
use crate::nymd::cosmwasm_client::helpers::create_pagination;
|
||||
use crate::nymd::cosmwasm_client::types::{
|
||||
Account, Code, CodeDetails, Contract, ContractCodeHistoryEntry, ContractCodeId,
|
||||
SequenceResponse,
|
||||
SequenceResponse, SimulateResponse,
|
||||
};
|
||||
use crate::nymd::error::NymdError;
|
||||
use async_trait::async_trait;
|
||||
@@ -14,15 +14,19 @@ use cosmrs::proto::cosmos::auth::v1beta1::{
|
||||
use cosmrs::proto::cosmos::bank::v1beta1::{
|
||||
QueryAllBalancesRequest, QueryAllBalancesResponse, QueryBalanceRequest, QueryBalanceResponse,
|
||||
};
|
||||
use cosmrs::proto::cosmos::tx::v1beta1::{
|
||||
SimulateRequest, SimulateResponse as ProtoSimulateResponse,
|
||||
};
|
||||
use cosmrs::proto::cosmwasm::wasm::v1::*;
|
||||
use cosmrs::rpc::endpoint::block::Response as BlockResponse;
|
||||
use cosmrs::rpc::endpoint::broadcast;
|
||||
use cosmrs::rpc::endpoint::tx::Response as TxResponse;
|
||||
use cosmrs::rpc::query::Query;
|
||||
use cosmrs::rpc::{self, HttpClient, Order};
|
||||
use cosmrs::tendermint::abci::Code as AbciCode;
|
||||
use cosmrs::tendermint::abci::Transaction;
|
||||
use cosmrs::tendermint::{abci, block, chain};
|
||||
use cosmrs::{tx, AccountId, Coin, Denom};
|
||||
use cosmrs::{tx, AccountId, Coin, Denom, Tx};
|
||||
use prost::Message;
|
||||
use serde::{Deserialize, Serialize};
|
||||
use std::convert::{TryFrom, TryInto};
|
||||
@@ -49,6 +53,11 @@ pub trait CosmWasmClient: rpc::Client {
|
||||
|
||||
let res = self.abci_query(path, buf, None, false).await?;
|
||||
|
||||
match res.code {
|
||||
AbciCode::Err(code) => return Err(NymdError::AbciError(code, res.log)),
|
||||
AbciCode::Ok => (),
|
||||
}
|
||||
|
||||
Ok(Res::decode(res.value.as_ref())?)
|
||||
}
|
||||
|
||||
@@ -388,4 +397,27 @@ pub trait CosmWasmClient: rpc::Client {
|
||||
|
||||
Ok(serde_json::from_slice(&res.data)?)
|
||||
}
|
||||
|
||||
// deprecation warning is due to the fact the protobuf files built were based on cosmos-sdk 0.44,
|
||||
// where they prefer using tx_bytes directly. However, in 0.42, which we are using at the time
|
||||
// of writing this, the option does not work
|
||||
#[allow(deprecated)]
|
||||
async fn query_simulate(
|
||||
&self,
|
||||
tx: Option<Tx>,
|
||||
tx_bytes: Vec<u8>,
|
||||
) -> Result<SimulateResponse, NymdError> {
|
||||
let path = Some("/cosmos.tx.v1beta1.Service/Simulate".parse().unwrap());
|
||||
|
||||
let req = SimulateRequest {
|
||||
tx: tx.map(Into::into),
|
||||
tx_bytes,
|
||||
};
|
||||
|
||||
let res = self
|
||||
.make_abci_query::<_, ProtoSimulateResponse>(path, req)
|
||||
.await?;
|
||||
|
||||
res.try_into()
|
||||
}
|
||||
}
|
||||
|
||||
@@ -3,6 +3,7 @@
|
||||
|
||||
use crate::nymd::error::NymdError;
|
||||
use crate::nymd::wallet::DirectSecp256k1HdWallet;
|
||||
use crate::nymd::GasPrice;
|
||||
use cosmrs::rpc::{Error as TendermintRpcError, HttpClient, HttpClientUrl};
|
||||
use std::convert::TryInto;
|
||||
|
||||
@@ -23,9 +24,10 @@ where
|
||||
pub fn connect_with_signer<U>(
|
||||
endpoint: U,
|
||||
signer: DirectSecp256k1HdWallet,
|
||||
gas_price: Option<GasPrice>,
|
||||
) -> Result<signing_client::Client, NymdError>
|
||||
where
|
||||
U: TryInto<HttpClientUrl, Error = TendermintRpcError>,
|
||||
{
|
||||
signing_client::Client::connect_with_signer(endpoint, signer)
|
||||
signing_client::Client::connect_with_signer(endpoint, signer, gas_price)
|
||||
}
|
||||
|
||||
@@ -1,30 +1,94 @@
|
||||
// Copyright 2021 - Nym Technologies SA <contact@nymtech.net>
|
||||
// SPDX-License-Identifier: Apache-2.0
|
||||
|
||||
use std::convert::TryInto;
|
||||
|
||||
use async_trait::async_trait;
|
||||
use cosmrs::bank::MsgSend;
|
||||
use cosmrs::distribution::MsgWithdrawDelegatorReward;
|
||||
use cosmrs::proto::cosmos::tx::signing::v1beta1::SignMode;
|
||||
use cosmrs::rpc::endpoint::broadcast;
|
||||
use cosmrs::rpc::{Error as TendermintRpcError, HttpClient, HttpClientUrl, SimpleRequest};
|
||||
use cosmrs::staking::{MsgDelegate, MsgUndelegate};
|
||||
use cosmrs::tx::{self, Msg, SignDoc, SignerInfo};
|
||||
use cosmrs::{cosmwasm, rpc, AccountId, Any, Coin, Tx};
|
||||
use log::debug;
|
||||
use serde::Serialize;
|
||||
use sha2::Digest;
|
||||
use sha2::Sha256;
|
||||
|
||||
use crate::nymd::cosmwasm_client::client::CosmWasmClient;
|
||||
use crate::nymd::cosmwasm_client::helpers::{compress_wasm_code, CheckResponse};
|
||||
use crate::nymd::cosmwasm_client::logs::{self, parse_raw_logs};
|
||||
use crate::nymd::cosmwasm_client::types::*;
|
||||
use crate::nymd::error::NymdError;
|
||||
use crate::nymd::fee::{Fee, DEFAULT_SIMULATED_GAS_MULTIPLIER};
|
||||
use crate::nymd::wallet::DirectSecp256k1HdWallet;
|
||||
use async_trait::async_trait;
|
||||
use cosmrs::bank::MsgSend;
|
||||
use cosmrs::distribution::MsgWithdrawDelegatorReward;
|
||||
use cosmrs::rpc::endpoint::broadcast;
|
||||
use cosmrs::rpc::{Error as TendermintRpcError, HttpClient, HttpClientUrl, SimpleRequest};
|
||||
use cosmrs::staking::{MsgDelegate, MsgUndelegate};
|
||||
use cosmrs::tx::{Fee, Msg, SignDoc, SignerInfo};
|
||||
use cosmrs::{cosmwasm, rpc, tx, AccountId, Any, Coin};
|
||||
use log::debug;
|
||||
use serde::Serialize;
|
||||
use sha2::Digest;
|
||||
use sha2::Sha256;
|
||||
use std::convert::TryInto;
|
||||
use crate::nymd::{CosmosCoin, GasPrice};
|
||||
|
||||
// we need to have **a** valid secp256k1 signature for simulation purposes.
|
||||
// it doesn't matter what it is as long as it parses correctly
|
||||
const DUMMY_SECP256K1_SIGNATURE: &[u8] = &[
|
||||
54, 167, 169, 61, 100, 173, 231, 87, 1, 113, 179, 49, 102, 141, 67, 22, 170, 153, 52, 88, 178,
|
||||
159, 200, 11, 37, 138, 76, 221, 187, 70, 104, 123, 98, 216, 190, 249, 149, 81, 1, 158, 0, 220,
|
||||
32, 147, 101, 60, 64, 77, 44, 83, 221, 119, 170, 124, 109, 177, 73, 116, 46, 57, 102, 181, 98,
|
||||
91,
|
||||
];
|
||||
|
||||
#[async_trait]
|
||||
pub trait SigningCosmWasmClient: CosmWasmClient {
|
||||
fn signer(&self) -> &DirectSecp256k1HdWallet;
|
||||
|
||||
fn gas_price(&self) -> &GasPrice;
|
||||
|
||||
fn signer_public_key(&self, signer_address: &AccountId) -> Option<tx::SignerPublicKey> {
|
||||
let signer_accounts = self.signer().try_derive_accounts().ok()?;
|
||||
let account_from_signer = signer_accounts
|
||||
.iter()
|
||||
.find(|account| &account.address == signer_address)?;
|
||||
let public_key = account_from_signer.public_key;
|
||||
Some(public_key.into())
|
||||
}
|
||||
|
||||
async fn simulate(
|
||||
&self,
|
||||
signer_address: &AccountId,
|
||||
messages: Vec<Any>,
|
||||
memo: impl Into<String> + Send + 'static,
|
||||
) -> Result<SimulateResponse, NymdError> {
|
||||
let public_key = self.signer_public_key(signer_address);
|
||||
let sequence_response = self.get_sequence(signer_address).await?;
|
||||
|
||||
let partial_tx = Tx {
|
||||
body: tx::Body {
|
||||
messages,
|
||||
memo: memo.into(),
|
||||
timeout_height: 0u32.into(),
|
||||
extension_options: vec![],
|
||||
non_critical_extension_options: vec![],
|
||||
},
|
||||
auth_info: tx::AuthInfo {
|
||||
signer_infos: vec![tx::SignerInfo {
|
||||
public_key,
|
||||
mode_info: tx::ModeInfo::Single(tx::mode_info::Single {
|
||||
mode: SignMode::Unspecified,
|
||||
}),
|
||||
sequence: sequence_response.sequence,
|
||||
}],
|
||||
fee: tx::Fee::from_amount_and_gas(
|
||||
CosmosCoin {
|
||||
denom: "".parse().unwrap(),
|
||||
amount: 0u64.into(),
|
||||
},
|
||||
0,
|
||||
),
|
||||
},
|
||||
signatures: vec![DUMMY_SECP256K1_SIGNATURE.try_into().unwrap()],
|
||||
};
|
||||
|
||||
self.query_simulate(Some(partial_tx), Vec::new()).await
|
||||
}
|
||||
|
||||
async fn upload(
|
||||
&self,
|
||||
sender_address: &AccountId,
|
||||
@@ -52,6 +116,7 @@ pub trait SigningCosmWasmClient: CosmWasmClient {
|
||||
.check_response()?;
|
||||
|
||||
let logs = parse_raw_logs(tx_res.deliver_tx.log)?;
|
||||
let gas_info = GasInfo::new(tx_res.deliver_tx.gas_wanted, tx_res.deliver_tx.gas_used);
|
||||
|
||||
// TODO: should those strings be extracted into some constants?
|
||||
// the reason I think unwrap here is fine is that if the transaction succeeded and those
|
||||
@@ -71,6 +136,7 @@ pub trait SigningCosmWasmClient: CosmWasmClient {
|
||||
code_id,
|
||||
logs,
|
||||
transaction_hash: tx_res.hash,
|
||||
gas_info,
|
||||
})
|
||||
}
|
||||
|
||||
@@ -114,6 +180,7 @@ pub trait SigningCosmWasmClient: CosmWasmClient {
|
||||
.check_response()?;
|
||||
|
||||
let logs = parse_raw_logs(tx_res.deliver_tx.log)?;
|
||||
let gas_info = GasInfo::new(tx_res.deliver_tx.gas_wanted, tx_res.deliver_tx.gas_used);
|
||||
|
||||
// TODO: should those strings be extracted into some constants?
|
||||
// the reason I think unwrap here is fine is that if the transaction succeeded and those
|
||||
@@ -129,6 +196,7 @@ pub trait SigningCosmWasmClient: CosmWasmClient {
|
||||
contract_address,
|
||||
logs,
|
||||
transaction_hash: tx_res.hash,
|
||||
gas_info,
|
||||
})
|
||||
}
|
||||
|
||||
@@ -153,9 +221,12 @@ pub trait SigningCosmWasmClient: CosmWasmClient {
|
||||
.await?
|
||||
.check_response()?;
|
||||
|
||||
let gas_info = GasInfo::new(tx_res.deliver_tx.gas_wanted, tx_res.deliver_tx.gas_used);
|
||||
|
||||
Ok(ChangeAdminResult {
|
||||
logs: parse_raw_logs(tx_res.deliver_tx.log)?,
|
||||
transaction_hash: tx_res.hash,
|
||||
gas_info,
|
||||
})
|
||||
}
|
||||
|
||||
@@ -178,9 +249,12 @@ pub trait SigningCosmWasmClient: CosmWasmClient {
|
||||
.await?
|
||||
.check_response()?;
|
||||
|
||||
let gas_info = GasInfo::new(tx_res.deliver_tx.gas_wanted, tx_res.deliver_tx.gas_used);
|
||||
|
||||
Ok(ChangeAdminResult {
|
||||
logs: parse_raw_logs(tx_res.deliver_tx.log)?,
|
||||
transaction_hash: tx_res.hash,
|
||||
gas_info,
|
||||
})
|
||||
}
|
||||
|
||||
@@ -210,9 +284,12 @@ pub trait SigningCosmWasmClient: CosmWasmClient {
|
||||
.await?
|
||||
.check_response()?;
|
||||
|
||||
let gas_info = GasInfo::new(tx_res.deliver_tx.gas_wanted, tx_res.deliver_tx.gas_used);
|
||||
|
||||
Ok(MigrateResult {
|
||||
logs: parse_raw_logs(tx_res.deliver_tx.log)?,
|
||||
transaction_hash: tx_res.hash,
|
||||
gas_info,
|
||||
})
|
||||
}
|
||||
|
||||
@@ -242,9 +319,12 @@ pub trait SigningCosmWasmClient: CosmWasmClient {
|
||||
.await?
|
||||
.check_response()?;
|
||||
|
||||
let gas_info = GasInfo::new(tx_res.deliver_tx.gas_wanted, tx_res.deliver_tx.gas_used);
|
||||
|
||||
Ok(ExecuteResult {
|
||||
logs: parse_raw_logs(tx_res.deliver_tx.log)?,
|
||||
transaction_hash: tx_res.hash,
|
||||
gas_info,
|
||||
})
|
||||
}
|
||||
|
||||
@@ -279,14 +359,12 @@ pub trait SigningCosmWasmClient: CosmWasmClient {
|
||||
.await?
|
||||
.check_response()?;
|
||||
|
||||
debug!(
|
||||
"gas wanted: {:?}, gas used: {:?}",
|
||||
tx_res.deliver_tx.gas_wanted, tx_res.deliver_tx.gas_used
|
||||
);
|
||||
let gas_info = GasInfo::new(tx_res.deliver_tx.gas_wanted, tx_res.deliver_tx.gas_used);
|
||||
|
||||
Ok(ExecuteResult {
|
||||
logs: parse_raw_logs(tx_res.deliver_tx.log)?,
|
||||
transaction_hash: tx_res.hash,
|
||||
gas_info,
|
||||
})
|
||||
}
|
||||
|
||||
@@ -400,6 +478,43 @@ pub trait SigningCosmWasmClient: CosmWasmClient {
|
||||
.check_response()
|
||||
}
|
||||
|
||||
// in this particular case we cannot generalise the argument to `&str` due to lifetime constraints
|
||||
#[allow(clippy::ptr_arg)]
|
||||
async fn determine_transaction_fee(
|
||||
&self,
|
||||
signer_address: &AccountId,
|
||||
messages: &[Any],
|
||||
fee: Fee,
|
||||
memo: &String,
|
||||
) -> Result<tx::Fee, NymdError> {
|
||||
let fee = match fee {
|
||||
Fee::Manual(fee) => fee,
|
||||
Fee::Auto(multiplier) => {
|
||||
debug!("Trying to simulate gas costs...");
|
||||
// from what I've seen in manual testing, gas estimation does not exist if transaction
|
||||
// fails to get executed (for example if you send 'BondMixnode" with invalid signature)
|
||||
let gas_estimation = self
|
||||
.simulate(signer_address, messages.to_vec(), memo.clone())
|
||||
.await?
|
||||
.gas_info
|
||||
.ok_or(NymdError::GasEstimationFailure)?
|
||||
.gas_used;
|
||||
|
||||
let multiplier = multiplier.unwrap_or(DEFAULT_SIMULATED_GAS_MULTIPLIER);
|
||||
let gas = ((gas_estimation.value() as f32 * multiplier) as u64).into();
|
||||
|
||||
debug!("Gas estimation: {}", gas_estimation);
|
||||
debug!("Multiplying the estimation by {}", multiplier);
|
||||
debug!("Final gas limit used: {}", gas);
|
||||
|
||||
let fee = self.gas_price() * gas;
|
||||
tx::Fee::from_amount_and_gas(fee, gas)
|
||||
}
|
||||
};
|
||||
debug!("Fee used for the transaction: {:?}", fee);
|
||||
Ok(fee)
|
||||
}
|
||||
|
||||
/// Broadcast a transaction, returning immediately.
|
||||
async fn sign_and_broadcast_async(
|
||||
&self,
|
||||
@@ -408,6 +523,10 @@ pub trait SigningCosmWasmClient: CosmWasmClient {
|
||||
fee: Fee,
|
||||
memo: impl Into<String> + Send + 'static,
|
||||
) -> Result<broadcast::tx_async::Response, NymdError> {
|
||||
let memo = memo.into();
|
||||
let fee = self
|
||||
.determine_transaction_fee(signer_address, &messages, fee, &memo)
|
||||
.await?;
|
||||
let tx_raw = self.sign(signer_address, messages, fee, memo).await?;
|
||||
let tx_bytes = tx_raw
|
||||
.to_bytes()
|
||||
@@ -424,6 +543,10 @@ pub trait SigningCosmWasmClient: CosmWasmClient {
|
||||
fee: Fee,
|
||||
memo: impl Into<String> + Send + 'static,
|
||||
) -> Result<broadcast::tx_sync::Response, NymdError> {
|
||||
let memo = memo.into();
|
||||
let fee = self
|
||||
.determine_transaction_fee(signer_address, &messages, fee, &memo)
|
||||
.await?;
|
||||
let tx_raw = self.sign(signer_address, messages, fee, memo).await?;
|
||||
let tx_bytes = tx_raw
|
||||
.to_bytes()
|
||||
@@ -440,6 +563,11 @@ pub trait SigningCosmWasmClient: CosmWasmClient {
|
||||
fee: Fee,
|
||||
memo: impl Into<String> + Send + 'static,
|
||||
) -> Result<broadcast::tx_commit::Response, NymdError> {
|
||||
let memo = memo.into();
|
||||
let fee = self
|
||||
.determine_transaction_fee(signer_address, &messages, fee, &memo)
|
||||
.await?;
|
||||
|
||||
let tx_raw = self.sign(signer_address, messages, fee, memo).await?;
|
||||
let tx_bytes = tx_raw
|
||||
.to_bytes()
|
||||
@@ -452,7 +580,7 @@ pub trait SigningCosmWasmClient: CosmWasmClient {
|
||||
&self,
|
||||
signer_address: &AccountId,
|
||||
messages: Vec<Any>,
|
||||
fee: Fee,
|
||||
fee: tx::Fee,
|
||||
memo: impl Into<String> + Send + 'static,
|
||||
signer_data: SignerData,
|
||||
) -> Result<tx::Raw, NymdError> {
|
||||
@@ -490,7 +618,7 @@ pub trait SigningCosmWasmClient: CosmWasmClient {
|
||||
&self,
|
||||
signer_address: &AccountId,
|
||||
messages: Vec<Any>,
|
||||
fee: Fee,
|
||||
fee: tx::Fee,
|
||||
memo: impl Into<String> + Send + 'static,
|
||||
) -> Result<tx::Raw, NymdError> {
|
||||
// TODO: Future optimisation: rather than grabbing current account_number and sequence
|
||||
@@ -508,22 +636,28 @@ pub trait SigningCosmWasmClient: CosmWasmClient {
|
||||
}
|
||||
}
|
||||
|
||||
#[derive(Debug)]
|
||||
#[derive(Debug, Clone)]
|
||||
pub struct Client {
|
||||
rpc_client: HttpClient,
|
||||
signer: DirectSecp256k1HdWallet,
|
||||
gas_price: GasPrice,
|
||||
}
|
||||
|
||||
impl Client {
|
||||
pub fn connect_with_signer<U>(
|
||||
endpoint: U,
|
||||
signer: DirectSecp256k1HdWallet,
|
||||
gas_price: Option<GasPrice>,
|
||||
) -> Result<Self, NymdError>
|
||||
where
|
||||
U: TryInto<HttpClientUrl, Error = TendermintRpcError>,
|
||||
{
|
||||
let rpc_client = HttpClient::new(endpoint)?;
|
||||
Ok(Client { rpc_client, signer })
|
||||
Ok(Client {
|
||||
rpc_client,
|
||||
signer,
|
||||
gas_price: gas_price.unwrap_or_default(),
|
||||
})
|
||||
}
|
||||
}
|
||||
|
||||
@@ -545,4 +679,8 @@ impl SigningCosmWasmClient for Client {
|
||||
fn signer(&self) -> &DirectSecp256k1HdWallet {
|
||||
&self.signer
|
||||
}
|
||||
|
||||
fn gas_price(&self) -> &GasPrice {
|
||||
&self.gas_price
|
||||
}
|
||||
}
|
||||
|
||||
@@ -7,15 +7,19 @@ use crate::nymd::cosmwasm_client::logs::Log;
|
||||
use crate::nymd::error::NymdError;
|
||||
use cosmrs::crypto::PublicKey;
|
||||
use cosmrs::proto::cosmos::auth::v1beta1::BaseAccount;
|
||||
use cosmrs::proto::cosmos::base::abci::v1beta1::{
|
||||
GasInfo as ProtoGasInfo, Result as ProtoAbciResult,
|
||||
};
|
||||
use cosmrs::proto::cosmos::tx::v1beta1::SimulateResponse as ProtoSimulateResponse;
|
||||
use cosmrs::proto::cosmwasm::wasm::v1::{
|
||||
CodeInfoResponse, ContractCodeHistoryEntry as ProtoContractCodeHistoryEntry,
|
||||
ContractCodeHistoryOperationType, ContractInfo as ProtoContractInfo,
|
||||
};
|
||||
use cosmrs::tendermint::chain;
|
||||
use cosmrs::tx::{AccountNumber, SequenceNumber};
|
||||
use cosmrs::tendermint::{abci, chain};
|
||||
use cosmrs::tx::{AccountNumber, Gas, SequenceNumber};
|
||||
use cosmrs::{tx, AccountId, Coin};
|
||||
use serde::Serialize;
|
||||
use std::convert::TryFrom;
|
||||
use std::convert::{TryFrom, TryInto};
|
||||
|
||||
pub type ContractCodeId = u64;
|
||||
|
||||
@@ -215,6 +219,101 @@ impl TryFrom<ProtoContractCodeHistoryEntry> for ContractCodeHistoryEntry {
|
||||
}
|
||||
}
|
||||
|
||||
#[derive(Debug)]
|
||||
pub struct GasInfo {
|
||||
/// GasWanted is the maximum units of work we allow this tx to perform.
|
||||
pub gas_wanted: Gas,
|
||||
|
||||
/// GasUsed is the amount of gas actually consumed.
|
||||
pub gas_used: Gas,
|
||||
}
|
||||
|
||||
impl From<ProtoGasInfo> for GasInfo {
|
||||
fn from(value: ProtoGasInfo) -> Self {
|
||||
GasInfo {
|
||||
gas_wanted: value.gas_wanted.into(),
|
||||
gas_used: value.gas_used.into(),
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
impl GasInfo {
|
||||
pub fn new(gas_wanted: Gas, gas_used: Gas) -> Self {
|
||||
GasInfo {
|
||||
gas_wanted,
|
||||
gas_used,
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
#[derive(Debug)]
|
||||
pub struct AbciResult {
|
||||
/// Data is any data returned from message or handler execution. It MUST be
|
||||
/// length prefixed in order to separate data from multiple message executions.
|
||||
pub data: Vec<u8>,
|
||||
|
||||
/// Log contains the log information from message or handler execution.
|
||||
// todo: try to parse into Log?
|
||||
pub log: String,
|
||||
|
||||
/// Events contains a slice of Event objects that were emitted during message
|
||||
/// or handler execution.
|
||||
pub events: Vec<abci::Event>,
|
||||
}
|
||||
|
||||
impl TryFrom<ProtoAbciResult> for AbciResult {
|
||||
type Error = NymdError;
|
||||
|
||||
fn try_from(value: ProtoAbciResult) -> Result<Self, Self::Error> {
|
||||
let mut events = Vec::with_capacity(value.events.len());
|
||||
|
||||
for proto_event in value.events.into_iter() {
|
||||
let type_str = proto_event.r#type;
|
||||
|
||||
let mut attributes = Vec::with_capacity(proto_event.attributes.len());
|
||||
for proto_attribute in proto_event.attributes.into_iter() {
|
||||
let stringified_ked = String::from_utf8(proto_attribute.key)
|
||||
.map_err(|_| NymdError::DeserializationError("EventAttributeKey".to_owned()))?;
|
||||
let stringified_value = String::from_utf8(proto_attribute.value)
|
||||
.map_err(|_| NymdError::DeserializationError("EventAttributeKey".to_owned()))?;
|
||||
|
||||
attributes.push(abci::tag::Tag {
|
||||
key: stringified_ked.parse().unwrap(),
|
||||
value: stringified_value.parse().unwrap(),
|
||||
})
|
||||
}
|
||||
|
||||
events.push(abci::Event {
|
||||
type_str,
|
||||
attributes,
|
||||
})
|
||||
}
|
||||
|
||||
Ok(AbciResult {
|
||||
data: value.data,
|
||||
log: value.log,
|
||||
events,
|
||||
})
|
||||
}
|
||||
}
|
||||
|
||||
#[derive(Debug)]
|
||||
pub struct SimulateResponse {
|
||||
pub gas_info: Option<GasInfo>,
|
||||
pub result: Option<AbciResult>,
|
||||
}
|
||||
|
||||
impl TryFrom<ProtoSimulateResponse> for SimulateResponse {
|
||||
type Error = NymdError;
|
||||
|
||||
fn try_from(value: ProtoSimulateResponse) -> Result<Self, Self::Error> {
|
||||
Ok(SimulateResponse {
|
||||
gas_info: value.gas_info.map(|gas_info| gas_info.into()),
|
||||
result: value.result.map(|result| result.try_into()).transpose()?,
|
||||
})
|
||||
}
|
||||
}
|
||||
|
||||
// ##############################################################################
|
||||
// types specific to the signing client (perhaps they should go to separate file)
|
||||
// ##############################################################################
|
||||
@@ -248,6 +347,8 @@ pub struct UploadResult {
|
||||
|
||||
/// Transaction hash (might be used as transaction ID)
|
||||
pub transaction_hash: tx::Hash,
|
||||
|
||||
pub gas_info: GasInfo,
|
||||
}
|
||||
|
||||
#[derive(Debug)]
|
||||
@@ -274,6 +375,8 @@ pub struct InstantiateResult {
|
||||
|
||||
/// Transaction hash (might be used as transaction ID)
|
||||
pub transaction_hash: tx::Hash,
|
||||
|
||||
pub gas_info: GasInfo,
|
||||
}
|
||||
|
||||
#[derive(Debug)]
|
||||
@@ -282,6 +385,8 @@ pub struct ChangeAdminResult {
|
||||
|
||||
/// Transaction hash (might be used as transaction ID)
|
||||
pub transaction_hash: tx::Hash,
|
||||
|
||||
pub gas_info: GasInfo,
|
||||
}
|
||||
|
||||
#[derive(Debug)]
|
||||
@@ -290,6 +395,8 @@ pub struct MigrateResult {
|
||||
|
||||
/// Transaction hash (might be used as transaction ID)
|
||||
pub transaction_hash: tx::Hash,
|
||||
|
||||
pub gas_info: GasInfo,
|
||||
}
|
||||
|
||||
#[derive(Debug)]
|
||||
@@ -298,4 +405,6 @@ pub struct ExecuteResult {
|
||||
|
||||
/// Transaction hash (might be used as transaction ID)
|
||||
pub transaction_hash: tx::Hash,
|
||||
|
||||
pub gas_info: GasInfo,
|
||||
}
|
||||
|
||||
@@ -2,7 +2,7 @@
|
||||
// SPDX-License-Identifier: Apache-2.0
|
||||
|
||||
use crate::nymd::cosmwasm_client::types::ContractCodeId;
|
||||
use cosmrs::tendermint::block;
|
||||
use cosmrs::tendermint::{abci, block};
|
||||
use cosmrs::{bip32, tx, AccountId};
|
||||
use std::io;
|
||||
use thiserror::Error;
|
||||
@@ -102,6 +102,12 @@ pub enum NymdError {
|
||||
|
||||
#[error("The provided gas price is malformed")]
|
||||
MalformedGasPrice,
|
||||
|
||||
#[error("Failed to estimate gas price for the transaction")]
|
||||
GasEstimationFailure,
|
||||
|
||||
#[error("Abci query failed with code {0} - {1}")]
|
||||
AbciError(u32, abci::Log),
|
||||
}
|
||||
|
||||
impl NymdError {
|
||||
|
||||
+5
-6
@@ -30,7 +30,7 @@ pub enum Operation {
|
||||
UnbondGateway,
|
||||
UnbondGatewayOnBehalf,
|
||||
|
||||
UpdateStateParams,
|
||||
UpdateContractSettings,
|
||||
|
||||
BeginMixnodeRewarding,
|
||||
FinishMixnodeRewarding,
|
||||
@@ -68,7 +68,7 @@ impl fmt::Display for Operation {
|
||||
Operation::UndelegateFromMixnodeOnBehalf => {
|
||||
f.write_str("UndelegateFromMixnodeOnBehalf")
|
||||
}
|
||||
Operation::UpdateStateParams => f.write_str("UpdateStateParams"),
|
||||
Operation::UpdateContractSettings => f.write_str("UpdateContractSettings"),
|
||||
Operation::BeginMixnodeRewarding => f.write_str("BeginMixnodeRewarding"),
|
||||
Operation::FinishMixnodeRewarding => f.write_str("FinishMixnodeRewarding"),
|
||||
Operation::TrackUnbondGateway => f.write_str("TrackUnbondGateway"),
|
||||
@@ -104,7 +104,7 @@ impl Operation {
|
||||
Operation::UnbondGateway => 175_000u64.into(),
|
||||
Operation::UnbondGatewayOnBehalf => 200_000u64.into(),
|
||||
|
||||
Operation::UpdateStateParams => 175_000u64.into(),
|
||||
Operation::UpdateContractSettings => 175_000u64.into(),
|
||||
Operation::BeginMixnodeRewarding => 175_000u64.into(),
|
||||
Operation::FinishMixnodeRewarding => 175_000u64.into(),
|
||||
Operation::TrackUnbondGateway => 175_000u64.into(),
|
||||
@@ -125,9 +125,8 @@ impl Operation {
|
||||
Fee::from_amount_and_gas(fee, gas_limit)
|
||||
}
|
||||
|
||||
pub(crate) fn determine_fee(&self, gas_price: &GasPrice, gas_limit: Option<Gas>) -> Fee {
|
||||
let gas_limit = gas_limit.unwrap_or_else(|| self.default_gas_limit());
|
||||
Self::determine_custom_fee(gas_price, gas_limit)
|
||||
pub fn default_fee(&self, gas_price: &GasPrice) -> Fee {
|
||||
Self::determine_custom_fee(gas_price, self.default_gas_limit())
|
||||
}
|
||||
}
|
||||
|
||||
@@ -0,0 +1,33 @@
|
||||
// Copyright 2021 - Nym Technologies SA <contact@nymtech.net>
|
||||
// SPDX-License-Identifier: Apache-2.0
|
||||
|
||||
use cosmrs::tx;
|
||||
|
||||
pub mod gas_price;
|
||||
pub mod helpers;
|
||||
|
||||
pub const DEFAULT_SIMULATED_GAS_MULTIPLIER: f32 = 1.3;
|
||||
|
||||
#[derive(Debug, Clone)]
|
||||
pub enum Fee {
|
||||
Manual(tx::Fee),
|
||||
Auto(Option<f32>),
|
||||
}
|
||||
|
||||
impl From<tx::Fee> for Fee {
|
||||
fn from(fee: tx::Fee) -> Self {
|
||||
Fee::Manual(fee)
|
||||
}
|
||||
}
|
||||
|
||||
impl From<f32> for Fee {
|
||||
fn from(multiplier: f32) -> Self {
|
||||
Fee::Auto(Some(multiplier))
|
||||
}
|
||||
}
|
||||
|
||||
impl Default for Fee {
|
||||
fn default() -> Self {
|
||||
Fee::Auto(Some(DEFAULT_SIMULATED_GAS_MULTIPLIER))
|
||||
}
|
||||
}
|
||||
@@ -7,11 +7,12 @@ use crate::nymd::cosmwasm_client::types::{
|
||||
MigrateResult, SequenceResponse, UploadResult,
|
||||
};
|
||||
use crate::nymd::error::NymdError;
|
||||
use crate::nymd::fee_helpers::Operation;
|
||||
use crate::nymd::wallet::DirectSecp256k1HdWallet;
|
||||
use cosmrs::rpc::endpoint::broadcast;
|
||||
use cosmrs::rpc::{Error as TendermintRpcError, HttpClientUrl};
|
||||
use cosmwasm_std::{Coin, Uint128};
|
||||
pub use fee::gas_price::GasPrice;
|
||||
use fee::helpers::Operation;
|
||||
use mixnet_contract::{
|
||||
ContractStateParams, Delegation, ExecuteMsg, Gateway, GatewayBond, GatewayOwnershipResponse,
|
||||
IdentityKey, LayerDistribution, MixNode, MixNodeBond, MixOwnershipResponse,
|
||||
@@ -20,38 +21,37 @@ use mixnet_contract::{
|
||||
PagedMixnodeResponse, QueryMsg, RewardingIntervalResponse,
|
||||
};
|
||||
use serde::Serialize;
|
||||
use std::collections::HashMap;
|
||||
use std::convert::TryInto;
|
||||
|
||||
pub use crate::nymd::cosmwasm_client::client::CosmWasmClient;
|
||||
pub use crate::nymd::cosmwasm_client::signing_client::SigningCosmWasmClient;
|
||||
pub use crate::nymd::gas_price::GasPrice;
|
||||
pub use crate::nymd::fee::Fee;
|
||||
use crate::nymd::fee::DEFAULT_SIMULATED_GAS_MULTIPLIER;
|
||||
pub use cosmrs::rpc::HttpClient as QueryNymdClient;
|
||||
pub use cosmrs::tendermint::block::Height;
|
||||
pub use cosmrs::tendermint::hash;
|
||||
pub use cosmrs::tendermint::Time as TendermintTime;
|
||||
pub use cosmrs::tx::{Fee, Gas};
|
||||
pub use cosmrs::tx::{self, Gas};
|
||||
pub use cosmrs::Coin as CosmosCoin;
|
||||
pub use cosmrs::{AccountId, Decimal, Denom};
|
||||
pub use signing_client::Client as SigningNymdClient;
|
||||
use std::collections::HashMap;
|
||||
pub use traits::{VestingQueryClient, VestingSigningClient};
|
||||
|
||||
pub mod cosmwasm_client;
|
||||
pub mod error;
|
||||
pub mod fee_helpers;
|
||||
pub mod gas_price;
|
||||
pub mod fee;
|
||||
pub mod traits;
|
||||
pub mod wallet;
|
||||
|
||||
pub use traits::{VestingQueryClient, VestingSigningClient};
|
||||
|
||||
#[derive(Debug)]
|
||||
pub struct NymdClient<C> {
|
||||
client: C,
|
||||
mixnet_contract_address: Option<AccountId>,
|
||||
vesting_contract_address: Option<AccountId>,
|
||||
client_address: Option<Vec<AccountId>>,
|
||||
gas_price: GasPrice,
|
||||
custom_gas_limits: HashMap<Operation, Gas>,
|
||||
simulated_gas_multiplier: f32,
|
||||
}
|
||||
|
||||
impl NymdClient<QueryNymdClient> {
|
||||
@@ -68,8 +68,8 @@ impl NymdClient<QueryNymdClient> {
|
||||
mixnet_contract_address: Some(mixnet_contract_address),
|
||||
vesting_contract_address: Some(vesting_contract_address),
|
||||
client_address: None,
|
||||
gas_price: Default::default(),
|
||||
custom_gas_limits: Default::default(),
|
||||
simulated_gas_multiplier: DEFAULT_SIMULATED_GAS_MULTIPLIER,
|
||||
})
|
||||
}
|
||||
}
|
||||
@@ -81,6 +81,7 @@ impl NymdClient<SigningNymdClient> {
|
||||
mixnet_contract_address: Option<AccountId>,
|
||||
vesting_contract_address: Option<AccountId>,
|
||||
signer: DirectSecp256k1HdWallet,
|
||||
gas_price: Option<GasPrice>,
|
||||
) -> Result<NymdClient<SigningNymdClient>, NymdError>
|
||||
where
|
||||
U: TryInto<HttpClientUrl, Error = TendermintRpcError>,
|
||||
@@ -92,12 +93,12 @@ impl NymdClient<SigningNymdClient> {
|
||||
.collect();
|
||||
|
||||
Ok(NymdClient {
|
||||
client: SigningNymdClient::connect_with_signer(endpoint, signer)?,
|
||||
client: SigningNymdClient::connect_with_signer(endpoint, signer, gas_price)?,
|
||||
mixnet_contract_address,
|
||||
vesting_contract_address,
|
||||
client_address: Some(client_address),
|
||||
gas_price: Default::default(),
|
||||
custom_gas_limits: Default::default(),
|
||||
simulated_gas_multiplier: DEFAULT_SIMULATED_GAS_MULTIPLIER,
|
||||
})
|
||||
}
|
||||
|
||||
@@ -106,6 +107,7 @@ impl NymdClient<SigningNymdClient> {
|
||||
mixnet_contract_address: Option<AccountId>,
|
||||
vesting_contract_address: Option<AccountId>,
|
||||
mnemonic: bip39::Mnemonic,
|
||||
gas_price: Option<GasPrice>,
|
||||
) -> Result<NymdClient<SigningNymdClient>, NymdError>
|
||||
where
|
||||
U: TryInto<HttpClientUrl, Error = TendermintRpcError>,
|
||||
@@ -118,33 +120,17 @@ impl NymdClient<SigningNymdClient> {
|
||||
.collect();
|
||||
|
||||
Ok(NymdClient {
|
||||
client: SigningNymdClient::connect_with_signer(endpoint, wallet)?,
|
||||
client: SigningNymdClient::connect_with_signer(endpoint, wallet, gas_price)?,
|
||||
mixnet_contract_address,
|
||||
vesting_contract_address,
|
||||
client_address: Some(client_address),
|
||||
gas_price: Default::default(),
|
||||
custom_gas_limits: Default::default(),
|
||||
simulated_gas_multiplier: DEFAULT_SIMULATED_GAS_MULTIPLIER,
|
||||
})
|
||||
}
|
||||
}
|
||||
|
||||
impl<C> NymdClient<C> {
|
||||
pub fn set_gas_price(&mut self, gas_price: GasPrice) {
|
||||
self.gas_price = gas_price
|
||||
}
|
||||
|
||||
pub fn set_custom_gas_limit(&mut self, operation: Operation, limit: Gas) {
|
||||
self.custom_gas_limits.insert(operation, limit);
|
||||
}
|
||||
|
||||
pub fn get_gas_price(&self) -> GasPrice {
|
||||
self.gas_price.clone()
|
||||
}
|
||||
|
||||
pub fn get_custom_gas_limits(&self) -> HashMap<Operation, Gas> {
|
||||
self.custom_gas_limits.clone()
|
||||
}
|
||||
|
||||
pub fn mixnet_contract_address(&self) -> Result<&AccountId, NymdError> {
|
||||
self.mixnet_contract_address
|
||||
.as_ref()
|
||||
@@ -172,6 +158,46 @@ impl<C> NymdClient<C> {
|
||||
&self.client_address.as_ref().unwrap()[0]
|
||||
}
|
||||
|
||||
pub fn gas_price(&self) -> &GasPrice
|
||||
where
|
||||
C: SigningCosmWasmClient,
|
||||
{
|
||||
self.client.gas_price()
|
||||
}
|
||||
|
||||
pub fn set_custom_gas_limit(&mut self, operation: Operation, limit: Gas)
|
||||
where
|
||||
C: SigningCosmWasmClient + Sync,
|
||||
{
|
||||
self.custom_gas_limits.insert(operation, limit);
|
||||
}
|
||||
|
||||
pub fn operation_fee(&self, operation: Operation) -> Fee
|
||||
where
|
||||
C: SigningCosmWasmClient + Sync,
|
||||
{
|
||||
if let Some(&gas_limit) = self.custom_gas_limits.get(&operation) {
|
||||
Operation::determine_custom_fee(self.client.gas_price(), gas_limit).into()
|
||||
} else {
|
||||
Fee::Auto(Some(self.simulated_gas_multiplier))
|
||||
}
|
||||
}
|
||||
|
||||
pub fn repeated_operation_fee(&self, operation: Operation, count: u64) -> Fee
|
||||
where
|
||||
C: SigningCosmWasmClient + Sync,
|
||||
{
|
||||
if let Some(&gas_limit) = self.custom_gas_limits.get(&operation) {
|
||||
Operation::determine_custom_fee(
|
||||
self.client.gas_price(),
|
||||
(gas_limit.value() * count).into(),
|
||||
)
|
||||
.into()
|
||||
} else {
|
||||
Fee::Auto(Some(self.simulated_gas_multiplier))
|
||||
}
|
||||
}
|
||||
|
||||
pub async fn account_sequence(&self) -> Result<SequenceResponse, NymdError>
|
||||
where
|
||||
C: SigningCosmWasmClient + Sync,
|
||||
@@ -179,25 +205,6 @@ impl<C> NymdClient<C> {
|
||||
self.client.get_sequence(self.address()).await
|
||||
}
|
||||
|
||||
pub fn get_fee(&self, operation: Operation) -> Fee {
|
||||
let gas_limit = self.custom_gas_limits.get(&operation).cloned();
|
||||
operation.determine_fee(&self.gas_price, gas_limit)
|
||||
}
|
||||
|
||||
pub fn get_fee_multiple(&self, operation: Operation, times: u64) -> Fee {
|
||||
let default_gas_limit = operation.default_gas_limit();
|
||||
let gas_limit_unit = self
|
||||
.custom_gas_limits
|
||||
.get(&operation)
|
||||
.unwrap_or(&default_gas_limit);
|
||||
let gas_limit = Gas::from(gas_limit_unit.value() * times);
|
||||
Operation::determine_custom_fee(&self.gas_price, gas_limit)
|
||||
}
|
||||
|
||||
pub fn calculate_custom_fee(&self, gas_limit: impl Into<Gas>) -> Fee {
|
||||
Operation::determine_custom_fee(&self.gas_price, gas_limit.into())
|
||||
}
|
||||
|
||||
pub async fn get_current_block_timestamp(&self) -> Result<TendermintTime, NymdError>
|
||||
where
|
||||
C: CosmWasmClient + Sync,
|
||||
@@ -483,7 +490,7 @@ impl<C> NymdClient<C> {
|
||||
where
|
||||
C: SigningCosmWasmClient + Sync,
|
||||
{
|
||||
let fee = self.get_fee(Operation::Send);
|
||||
let fee = self.operation_fee(Operation::Send);
|
||||
self.client
|
||||
.send_tokens(self.address(), recipient, amount, fee, memo)
|
||||
.await
|
||||
@@ -498,7 +505,7 @@ impl<C> NymdClient<C> {
|
||||
where
|
||||
C: SigningCosmWasmClient + Sync,
|
||||
{
|
||||
let fee = self.get_fee_multiple(Operation::Send, msgs.len() as u64);
|
||||
let fee = self.repeated_operation_fee(Operation::Send, msgs.len() as u64);
|
||||
self.client
|
||||
.send_tokens_multiple(self.address(), msgs, fee, memo)
|
||||
.await
|
||||
@@ -546,7 +553,7 @@ impl<C> NymdClient<C> {
|
||||
where
|
||||
C: SigningCosmWasmClient + Sync,
|
||||
{
|
||||
let fee = self.get_fee(Operation::Upload);
|
||||
let fee = self.operation_fee(Operation::Upload);
|
||||
self.client
|
||||
.upload(self.address(), wasm_code, fee, memo)
|
||||
.await
|
||||
@@ -564,7 +571,7 @@ impl<C> NymdClient<C> {
|
||||
C: SigningCosmWasmClient + Sync,
|
||||
M: ?Sized + Serialize + Sync,
|
||||
{
|
||||
let fee = self.get_fee(Operation::Init);
|
||||
let fee = self.operation_fee(Operation::Init);
|
||||
self.client
|
||||
.instantiate(self.address(), code_id, msg, label, fee, memo, options)
|
||||
.await
|
||||
@@ -579,7 +586,7 @@ impl<C> NymdClient<C> {
|
||||
where
|
||||
C: SigningCosmWasmClient + Sync,
|
||||
{
|
||||
let fee = self.get_fee(Operation::ChangeAdmin);
|
||||
let fee = self.operation_fee(Operation::ChangeAdmin);
|
||||
self.client
|
||||
.update_admin(self.address(), contract_address, new_admin, fee, memo)
|
||||
.await
|
||||
@@ -593,7 +600,7 @@ impl<C> NymdClient<C> {
|
||||
where
|
||||
C: SigningCosmWasmClient + Sync,
|
||||
{
|
||||
let fee = self.get_fee(Operation::ChangeAdmin);
|
||||
let fee = self.operation_fee(Operation::ChangeAdmin);
|
||||
self.client
|
||||
.clear_admin(self.address(), contract_address, fee, memo)
|
||||
.await
|
||||
@@ -610,7 +617,7 @@ impl<C> NymdClient<C> {
|
||||
C: SigningCosmWasmClient + Sync,
|
||||
M: ?Sized + Serialize + Sync,
|
||||
{
|
||||
let fee = self.get_fee(Operation::Migrate);
|
||||
let fee = self.operation_fee(Operation::Migrate);
|
||||
self.client
|
||||
.migrate(self.address(), contract_address, code_id, fee, msg, memo)
|
||||
.await
|
||||
@@ -626,7 +633,7 @@ impl<C> NymdClient<C> {
|
||||
where
|
||||
C: SigningCosmWasmClient + Sync,
|
||||
{
|
||||
let fee = self.get_fee(Operation::BondMixnode);
|
||||
let fee = self.operation_fee(Operation::BondMixnode);
|
||||
|
||||
let req = ExecuteMsg::BondMixnode {
|
||||
mix_node: mixnode,
|
||||
@@ -655,7 +662,7 @@ impl<C> NymdClient<C> {
|
||||
where
|
||||
C: SigningCosmWasmClient + Sync,
|
||||
{
|
||||
let fee = self.get_fee(Operation::BondMixnodeOnBehalf);
|
||||
let fee = self.operation_fee(Operation::BondMixnodeOnBehalf);
|
||||
|
||||
let req = ExecuteMsg::BondMixnodeOnBehalf {
|
||||
mix_node: mixnode,
|
||||
@@ -682,7 +689,7 @@ impl<C> NymdClient<C> {
|
||||
where
|
||||
C: SigningCosmWasmClient + Sync,
|
||||
{
|
||||
let fee = self.get_fee_multiple(
|
||||
let fee = self.repeated_operation_fee(
|
||||
Operation::BondMixnodeOnBehalf,
|
||||
mixnode_bonds_with_sigs.len() as u64,
|
||||
);
|
||||
@@ -717,7 +724,7 @@ impl<C> NymdClient<C> {
|
||||
where
|
||||
C: SigningCosmWasmClient + Sync,
|
||||
{
|
||||
let fee = self.get_fee(Operation::UnbondMixnode);
|
||||
let fee = self.operation_fee(Operation::UnbondMixnode);
|
||||
|
||||
let req = ExecuteMsg::UnbondMixnode {};
|
||||
self.client
|
||||
@@ -737,7 +744,7 @@ impl<C> NymdClient<C> {
|
||||
where
|
||||
C: SigningCosmWasmClient + Sync,
|
||||
{
|
||||
let fee = self.get_fee(Operation::UnbondMixnodeOnBehalf);
|
||||
let fee = self.operation_fee(Operation::UnbondMixnodeOnBehalf);
|
||||
|
||||
let req = ExecuteMsg::UnbondMixnodeOnBehalf { owner };
|
||||
self.client
|
||||
@@ -761,7 +768,7 @@ impl<C> NymdClient<C> {
|
||||
where
|
||||
C: SigningCosmWasmClient + Sync,
|
||||
{
|
||||
let fee = self.get_fee(Operation::DelegateToMixnode);
|
||||
let fee = self.operation_fee(Operation::DelegateToMixnode);
|
||||
|
||||
let req = ExecuteMsg::DelegateToMixnode {
|
||||
mix_identity: mix_identity.to_string(),
|
||||
@@ -789,7 +796,7 @@ impl<C> NymdClient<C> {
|
||||
where
|
||||
C: SigningCosmWasmClient + Sync,
|
||||
{
|
||||
let fee = self.get_fee(Operation::DelegateToMixnodeOnBehalf);
|
||||
let fee = self.operation_fee(Operation::DelegateToMixnodeOnBehalf);
|
||||
|
||||
let req = ExecuteMsg::DelegateToMixnodeOnBehalf {
|
||||
mix_identity: mix_identity.to_string(),
|
||||
@@ -815,7 +822,7 @@ impl<C> NymdClient<C> {
|
||||
where
|
||||
C: SigningCosmWasmClient + Sync,
|
||||
{
|
||||
let fee = self.get_fee_multiple(
|
||||
let fee = self.repeated_operation_fee(
|
||||
Operation::DelegateToMixnodeOnBehalf,
|
||||
mixnode_delegations.len() as u64,
|
||||
);
|
||||
@@ -852,7 +859,7 @@ impl<C> NymdClient<C> {
|
||||
where
|
||||
C: SigningCosmWasmClient + Sync,
|
||||
{
|
||||
let fee = self.get_fee(Operation::UndelegateFromMixnode);
|
||||
let fee = self.operation_fee(Operation::UndelegateFromMixnode);
|
||||
|
||||
let req = ExecuteMsg::UndelegateFromMixnode {
|
||||
mix_identity: mix_identity.to_string(),
|
||||
@@ -878,7 +885,7 @@ impl<C> NymdClient<C> {
|
||||
where
|
||||
C: SigningCosmWasmClient + Sync,
|
||||
{
|
||||
let fee = self.get_fee(Operation::UndelegateFromMixnodeOnBehalf);
|
||||
let fee = self.operation_fee(Operation::UndelegateFromMixnodeOnBehalf);
|
||||
|
||||
let req = ExecuteMsg::UndelegateFromMixnodeOnBehalf {
|
||||
mix_identity: mix_identity.to_string(),
|
||||
@@ -906,7 +913,7 @@ impl<C> NymdClient<C> {
|
||||
where
|
||||
C: SigningCosmWasmClient + Sync,
|
||||
{
|
||||
let fee = self.get_fee(Operation::BondGateway);
|
||||
let fee = self.operation_fee(Operation::BondGateway);
|
||||
|
||||
let req = ExecuteMsg::BondGateway {
|
||||
gateway,
|
||||
@@ -935,7 +942,7 @@ impl<C> NymdClient<C> {
|
||||
where
|
||||
C: SigningCosmWasmClient + Sync,
|
||||
{
|
||||
let fee = self.get_fee(Operation::BondGatewayOnBehalf);
|
||||
let fee = self.operation_fee(Operation::BondGatewayOnBehalf);
|
||||
|
||||
let req = ExecuteMsg::BondGatewayOnBehalf {
|
||||
gateway,
|
||||
@@ -962,7 +969,7 @@ impl<C> NymdClient<C> {
|
||||
where
|
||||
C: SigningCosmWasmClient + Sync,
|
||||
{
|
||||
let fee = self.get_fee_multiple(
|
||||
let fee = self.repeated_operation_fee(
|
||||
Operation::BondGatewayOnBehalf,
|
||||
gateway_bonds_with_sigs.len() as u64,
|
||||
);
|
||||
@@ -997,7 +1004,7 @@ impl<C> NymdClient<C> {
|
||||
where
|
||||
C: SigningCosmWasmClient + Sync,
|
||||
{
|
||||
let fee = self.get_fee(Operation::UnbondGateway);
|
||||
let fee = self.operation_fee(Operation::UnbondGateway);
|
||||
|
||||
let req = ExecuteMsg::UnbondGateway {};
|
||||
self.client
|
||||
@@ -1018,7 +1025,7 @@ impl<C> NymdClient<C> {
|
||||
where
|
||||
C: SigningCosmWasmClient + Sync,
|
||||
{
|
||||
let fee = self.get_fee(Operation::UnbondGatewayOnBehalf);
|
||||
let fee = self.operation_fee(Operation::UnbondGatewayOnBehalf);
|
||||
|
||||
let req = ExecuteMsg::UnbondGatewayOnBehalf { owner };
|
||||
self.client
|
||||
@@ -1040,7 +1047,7 @@ impl<C> NymdClient<C> {
|
||||
where
|
||||
C: SigningCosmWasmClient + Sync,
|
||||
{
|
||||
let fee = self.get_fee(Operation::UpdateStateParams);
|
||||
let fee = self.operation_fee(Operation::UpdateContractSettings);
|
||||
|
||||
let req = ExecuteMsg::UpdateContractStateParams(new_params);
|
||||
self.client
|
||||
@@ -1062,7 +1069,7 @@ impl<C> NymdClient<C> {
|
||||
where
|
||||
C: SigningCosmWasmClient + Sync,
|
||||
{
|
||||
let fee = self.get_fee(Operation::BeginMixnodeRewarding);
|
||||
let fee = self.operation_fee(Operation::BeginMixnodeRewarding);
|
||||
|
||||
let req = ExecuteMsg::BeginMixnodeRewarding {
|
||||
rewarding_interval_nonce,
|
||||
@@ -1086,7 +1093,7 @@ impl<C> NymdClient<C> {
|
||||
where
|
||||
C: SigningCosmWasmClient + Sync,
|
||||
{
|
||||
let fee = self.get_fee(Operation::FinishMixnodeRewarding);
|
||||
let fee = self.operation_fee(Operation::FinishMixnodeRewarding);
|
||||
|
||||
let req = ExecuteMsg::FinishMixnodeRewarding {
|
||||
rewarding_interval_nonce,
|
||||
|
||||
@@ -52,8 +52,8 @@ pub trait VestingQueryClient {
|
||||
|
||||
async fn delegated_vesting(
|
||||
&self,
|
||||
block_time: Option<Timestamp>,
|
||||
vesting_account_address: &str,
|
||||
block_time: Option<Timestamp>,
|
||||
) -> Result<Coin, NymdError>;
|
||||
}
|
||||
|
||||
@@ -162,8 +162,8 @@ impl<C: CosmWasmClient + Sync + Send> VestingQueryClient for NymdClient<C> {
|
||||
|
||||
async fn delegated_vesting(
|
||||
&self,
|
||||
block_time: Option<Timestamp>,
|
||||
vesting_account_address: &str,
|
||||
block_time: Option<Timestamp>,
|
||||
) -> Result<Coin, NymdError> {
|
||||
let request = VestingQueryMsg::GetDelegatedVesting {
|
||||
vesting_account_address: vesting_account_address.to_string(),
|
||||
|
||||
@@ -4,11 +4,11 @@
|
||||
pub use crate::nymd::cosmwasm_client::signing_client::SigningCosmWasmClient;
|
||||
use crate::nymd::cosmwasm_client::types::ExecuteResult;
|
||||
use crate::nymd::error::NymdError;
|
||||
use crate::nymd::fee_helpers::Operation;
|
||||
use crate::nymd::fee::helpers::Operation;
|
||||
use crate::nymd::{cosmwasm_coin_to_cosmos_coin, NymdClient};
|
||||
use async_trait::async_trait;
|
||||
use cosmwasm_std::Coin;
|
||||
use mixnet_contract::{Gateway, IdentityKey, MixNode};
|
||||
use mixnet_contract::{Gateway, IdentityKey, IdentityKeyRef, MixNode};
|
||||
use vesting_contract::messages::ExecuteMsg as VestingExecuteMsg;
|
||||
|
||||
#[async_trait]
|
||||
@@ -16,9 +16,10 @@ pub trait VestingSigningClient {
|
||||
async fn vesting_bond_gateway(
|
||||
&self,
|
||||
gateway: Gateway,
|
||||
pledge: Coin,
|
||||
owner_signature: &str,
|
||||
pledge: Coin,
|
||||
) -> Result<ExecuteResult, NymdError>;
|
||||
|
||||
async fn vesting_unbond_gateway(&self) -> Result<ExecuteResult, NymdError>;
|
||||
|
||||
async fn vesting_track_unbond_gateway(
|
||||
@@ -30,8 +31,8 @@ pub trait VestingSigningClient {
|
||||
async fn vesting_bond_mixnode(
|
||||
&self,
|
||||
mix_node: MixNode,
|
||||
pledge: Coin,
|
||||
owner_signature: &str,
|
||||
pledge: Coin,
|
||||
) -> Result<ExecuteResult, NymdError>;
|
||||
async fn vesting_unbond_mixnode(&self) -> Result<ExecuteResult, NymdError>;
|
||||
|
||||
@@ -40,6 +41,7 @@ pub trait VestingSigningClient {
|
||||
owner: &str,
|
||||
amount: Coin,
|
||||
) -> Result<ExecuteResult, NymdError>;
|
||||
|
||||
async fn withdraw_vested_coins(&self, amount: Coin) -> Result<ExecuteResult, NymdError>;
|
||||
|
||||
async fn vesting_track_undelegation(
|
||||
@@ -49,15 +51,15 @@ pub trait VestingSigningClient {
|
||||
amount: Coin,
|
||||
) -> Result<ExecuteResult, NymdError>;
|
||||
|
||||
async fn vesting_delegate_to_mixnode(
|
||||
async fn vesting_delegate_to_mixnode<'a>(
|
||||
&self,
|
||||
mix_identity: IdentityKey,
|
||||
amount: Coin,
|
||||
mix_identity: IdentityKeyRef<'a>,
|
||||
amount: &Coin,
|
||||
) -> Result<ExecuteResult, NymdError>;
|
||||
|
||||
async fn vesting_undelegate_from_mixnode(
|
||||
async fn vesting_undelegate_from_mixnode<'a>(
|
||||
&self,
|
||||
mix_identity: IdentityKey,
|
||||
mix_identity: IdentityKeyRef<'a>,
|
||||
) -> Result<ExecuteResult, NymdError>;
|
||||
|
||||
async fn create_periodic_vesting_account(
|
||||
@@ -73,10 +75,10 @@ impl<C: SigningCosmWasmClient + Sync + Send> VestingSigningClient for NymdClient
|
||||
async fn vesting_bond_gateway(
|
||||
&self,
|
||||
gateway: Gateway,
|
||||
pledge: Coin,
|
||||
owner_signature: &str,
|
||||
pledge: Coin,
|
||||
) -> Result<ExecuteResult, NymdError> {
|
||||
let fee = self.get_fee(Operation::BondGateway);
|
||||
let fee = self.operation_fee(Operation::BondGateway);
|
||||
let req = VestingExecuteMsg::BondGateway {
|
||||
gateway,
|
||||
owner_signature: owner_signature.to_string(),
|
||||
@@ -94,7 +96,7 @@ impl<C: SigningCosmWasmClient + Sync + Send> VestingSigningClient for NymdClient
|
||||
}
|
||||
|
||||
async fn vesting_unbond_gateway(&self) -> Result<ExecuteResult, NymdError> {
|
||||
let fee = self.get_fee(Operation::UnbondGateway);
|
||||
let fee = self.operation_fee(Operation::UnbondGateway);
|
||||
let req = VestingExecuteMsg::UnbondGateway {};
|
||||
self.client
|
||||
.execute(
|
||||
@@ -113,7 +115,7 @@ impl<C: SigningCosmWasmClient + Sync + Send> VestingSigningClient for NymdClient
|
||||
owner: &str,
|
||||
amount: Coin,
|
||||
) -> Result<ExecuteResult, NymdError> {
|
||||
let fee = self.get_fee(Operation::TrackUnbondGateway);
|
||||
let fee = self.operation_fee(Operation::TrackUnbondGateway);
|
||||
let req = VestingExecuteMsg::TrackUnbondGateway {
|
||||
owner: owner.to_string(),
|
||||
amount,
|
||||
@@ -133,10 +135,10 @@ impl<C: SigningCosmWasmClient + Sync + Send> VestingSigningClient for NymdClient
|
||||
async fn vesting_bond_mixnode(
|
||||
&self,
|
||||
mix_node: MixNode,
|
||||
pledge: Coin,
|
||||
owner_signature: &str,
|
||||
pledge: Coin,
|
||||
) -> Result<ExecuteResult, NymdError> {
|
||||
let fee = self.get_fee(Operation::BondMixnode);
|
||||
let fee = self.operation_fee(Operation::BondMixnode);
|
||||
let req = VestingExecuteMsg::BondMixnode {
|
||||
mix_node,
|
||||
owner_signature: owner_signature.to_string(),
|
||||
@@ -154,7 +156,7 @@ impl<C: SigningCosmWasmClient + Sync + Send> VestingSigningClient for NymdClient
|
||||
}
|
||||
|
||||
async fn vesting_unbond_mixnode(&self) -> Result<ExecuteResult, NymdError> {
|
||||
let fee = self.get_fee(Operation::UnbondMixnode);
|
||||
let fee = self.operation_fee(Operation::UnbondMixnode);
|
||||
let req = VestingExecuteMsg::UnbondMixnode {};
|
||||
self.client
|
||||
.execute(
|
||||
@@ -173,7 +175,7 @@ impl<C: SigningCosmWasmClient + Sync + Send> VestingSigningClient for NymdClient
|
||||
owner: &str,
|
||||
amount: Coin,
|
||||
) -> Result<ExecuteResult, NymdError> {
|
||||
let fee = self.get_fee(Operation::TrackUnbondMixnode);
|
||||
let fee = self.operation_fee(Operation::TrackUnbondMixnode);
|
||||
let req = VestingExecuteMsg::TrackUnbondMixnode {
|
||||
owner: owner.to_string(),
|
||||
amount,
|
||||
@@ -191,7 +193,7 @@ impl<C: SigningCosmWasmClient + Sync + Send> VestingSigningClient for NymdClient
|
||||
}
|
||||
|
||||
async fn withdraw_vested_coins(&self, amount: Coin) -> Result<ExecuteResult, NymdError> {
|
||||
let fee = self.get_fee(Operation::WithdrawVestedCoins);
|
||||
let fee = self.operation_fee(Operation::WithdrawVestedCoins);
|
||||
let req = VestingExecuteMsg::WithdrawVestedCoins { amount };
|
||||
self.client
|
||||
.execute(
|
||||
@@ -211,7 +213,7 @@ impl<C: SigningCosmWasmClient + Sync + Send> VestingSigningClient for NymdClient
|
||||
mix_identity: IdentityKey,
|
||||
amount: Coin,
|
||||
) -> Result<ExecuteResult, NymdError> {
|
||||
let fee = self.get_fee(Operation::TrackUndelegation);
|
||||
let fee = self.operation_fee(Operation::TrackUndelegation);
|
||||
let req = VestingExecuteMsg::TrackUndelegation {
|
||||
owner: address.to_string(),
|
||||
mix_identity,
|
||||
@@ -228,13 +230,15 @@ impl<C: SigningCosmWasmClient + Sync + Send> VestingSigningClient for NymdClient
|
||||
)
|
||||
.await
|
||||
}
|
||||
async fn vesting_delegate_to_mixnode(
|
||||
async fn vesting_delegate_to_mixnode<'a>(
|
||||
&self,
|
||||
mix_identity: IdentityKey,
|
||||
amount: Coin,
|
||||
mix_identity: IdentityKeyRef<'a>,
|
||||
amount: &Coin,
|
||||
) -> Result<ExecuteResult, NymdError> {
|
||||
let fee = self.get_fee(Operation::DelegateToMixnode);
|
||||
let req = VestingExecuteMsg::DelegateToMixnode { mix_identity };
|
||||
let fee = self.operation_fee(Operation::DelegateToMixnode);
|
||||
let req = VestingExecuteMsg::DelegateToMixnode {
|
||||
mix_identity: mix_identity.into(),
|
||||
};
|
||||
self.client
|
||||
.execute(
|
||||
self.address(),
|
||||
@@ -242,16 +246,18 @@ impl<C: SigningCosmWasmClient + Sync + Send> VestingSigningClient for NymdClient
|
||||
&req,
|
||||
fee,
|
||||
"VestingContract::DeledateToMixnode",
|
||||
vec![cosmwasm_coin_to_cosmos_coin(amount)],
|
||||
vec![cosmwasm_coin_to_cosmos_coin(amount.to_owned())],
|
||||
)
|
||||
.await
|
||||
}
|
||||
async fn vesting_undelegate_from_mixnode(
|
||||
async fn vesting_undelegate_from_mixnode<'a>(
|
||||
&self,
|
||||
mix_identity: IdentityKey,
|
||||
mix_identity: IdentityKeyRef<'a>,
|
||||
) -> Result<ExecuteResult, NymdError> {
|
||||
let fee = self.get_fee(Operation::UndelegateFromMixnode);
|
||||
let req = VestingExecuteMsg::UndelegateFromMixnode { mix_identity };
|
||||
let fee = self.operation_fee(Operation::UndelegateFromMixnode);
|
||||
let req = VestingExecuteMsg::UndelegateFromMixnode {
|
||||
mix_identity: mix_identity.into(),
|
||||
};
|
||||
self.client
|
||||
.execute(
|
||||
self.address(),
|
||||
@@ -269,7 +275,7 @@ impl<C: SigningCosmWasmClient + Sync + Send> VestingSigningClient for NymdClient
|
||||
start_time: Option<u64>,
|
||||
amount: Coin,
|
||||
) -> Result<ExecuteResult, NymdError> {
|
||||
let fee = self.get_fee(Operation::CreatePeriodicVestingAccount);
|
||||
let fee = self.operation_fee(Operation::CreatePeriodicVestingAccount);
|
||||
let req = VestingExecuteMsg::CreateAccount {
|
||||
address: address.to_string(),
|
||||
start_time,
|
||||
|
||||
@@ -10,7 +10,7 @@ use cosmrs::tx::SignDoc;
|
||||
use cosmrs::{tx, AccountId};
|
||||
|
||||
/// Derivation information required to derive a keypair and an address from a mnemonic.
|
||||
#[derive(Debug)]
|
||||
#[derive(Debug, Clone)]
|
||||
struct Secp256k1Derivation {
|
||||
hd_path: DerivationPath,
|
||||
prefix: String,
|
||||
@@ -40,7 +40,7 @@ impl AccountData {
|
||||
|
||||
type Secp256k1Keypair = (SigningKey, PublicKey);
|
||||
|
||||
#[derive(Debug)]
|
||||
#[derive(Debug, Clone)]
|
||||
pub struct DirectSecp256k1HdWallet {
|
||||
/// Base secret
|
||||
secret: bip39::Mnemonic,
|
||||
|
||||
@@ -1,7 +1,7 @@
|
||||
// Copyright 2021 - Nym Technologies SA <contact@nymtech.net>
|
||||
// SPDX-License-Identifier: Apache-2.0
|
||||
|
||||
use ed25519_dalek::ed25519::signature::Signature as SignatureTrait;
|
||||
pub use ed25519_dalek::ed25519::signature::Signature as SignatureTrait;
|
||||
pub use ed25519_dalek::SignatureError;
|
||||
pub use ed25519_dalek::{Verifier, PUBLIC_KEY_LENGTH, SECRET_KEY_LENGTH, SIGNATURE_LENGTH};
|
||||
use nymsphinx_types::{DestinationAddressBytes, DESTINATION_ADDRESS_LENGTH};
|
||||
|
||||
@@ -56,32 +56,68 @@ pub enum Layer {
|
||||
#[derive(Debug, Clone, JsonSchema, PartialEq, Serialize, Deserialize, Copy)]
|
||||
pub struct NodeRewardParams {
|
||||
period_reward_pool: Uint128,
|
||||
k: Uint128,
|
||||
rewarded_set_size: Uint128,
|
||||
active_set_size: Uint128,
|
||||
reward_blockstamp: u64,
|
||||
circulating_supply: Uint128,
|
||||
uptime: Uint128,
|
||||
sybil_resistance_percent: u8,
|
||||
in_active_set: bool,
|
||||
active_set_work_factor: u8,
|
||||
}
|
||||
|
||||
impl NodeRewardParams {
|
||||
#[allow(clippy::too_many_arguments)]
|
||||
pub fn new(
|
||||
period_reward_pool: u128,
|
||||
k: u128,
|
||||
rewarded_set_size: u128,
|
||||
active_set_size: u128,
|
||||
reward_blockstamp: u64,
|
||||
circulating_supply: u128,
|
||||
uptime: u128,
|
||||
sybil_resistance_percent: u8,
|
||||
in_active_set: bool,
|
||||
active_set_work_factor: u8,
|
||||
) -> NodeRewardParams {
|
||||
NodeRewardParams {
|
||||
period_reward_pool: Uint128::new(period_reward_pool),
|
||||
k: Uint128::new(k),
|
||||
rewarded_set_size: Uint128::new(rewarded_set_size),
|
||||
active_set_size: Uint128::new(active_set_size),
|
||||
reward_blockstamp,
|
||||
circulating_supply: Uint128::new(circulating_supply),
|
||||
uptime: Uint128::new(uptime),
|
||||
sybil_resistance_percent,
|
||||
in_active_set,
|
||||
active_set_work_factor,
|
||||
}
|
||||
}
|
||||
|
||||
pub fn omega(&self) -> U128 {
|
||||
// As per keybase://chat/nymtech#tokeneconomics/1179
|
||||
let denom = self.active_set_work_factor() * U128::from_num(self.rewarded_set_size())
|
||||
- (self.active_set_work_factor() - ONE) * U128::from_num(self.idle_nodes().u128());
|
||||
|
||||
if self.in_active_set() {
|
||||
// work_active = factor / (factor * self.network.k[month] - (factor - 1) * idle_nodes)
|
||||
self.active_set_work_factor() / denom * self.rewarded_set_size()
|
||||
} else {
|
||||
// work_idle = 1 / (factor * self.network.k[month] - (factor - 1) * idle_nodes)
|
||||
ONE / denom * self.rewarded_set_size()
|
||||
}
|
||||
}
|
||||
|
||||
pub fn idle_nodes(&self) -> Uint128 {
|
||||
self.rewarded_set_size - self.active_set_size
|
||||
}
|
||||
|
||||
pub fn active_set_work_factor(&self) -> U128 {
|
||||
U128::from_num(self.active_set_work_factor)
|
||||
}
|
||||
|
||||
pub fn in_active_set(&self) -> bool {
|
||||
self.in_active_set
|
||||
}
|
||||
|
||||
pub fn performance(&self) -> U128 {
|
||||
U128::from_num(self.uptime.u128()) / U128::from_num(100)
|
||||
}
|
||||
@@ -98,8 +134,8 @@ impl NodeRewardParams {
|
||||
self.period_reward_pool.u128()
|
||||
}
|
||||
|
||||
pub fn k(&self) -> u128 {
|
||||
self.k.u128()
|
||||
pub fn rewarded_set_size(&self) -> u128 {
|
||||
self.rewarded_set_size.u128()
|
||||
}
|
||||
|
||||
pub fn circulating_supply(&self) -> u128 {
|
||||
@@ -115,7 +151,7 @@ impl NodeRewardParams {
|
||||
}
|
||||
|
||||
pub fn one_over_k(&self) -> U128 {
|
||||
ONE / U128::from_num(self.k.u128())
|
||||
ONE / U128::from_num(self.rewarded_set_size.u128())
|
||||
}
|
||||
|
||||
pub fn alpha(&self) -> U128 {
|
||||
@@ -315,14 +351,13 @@ impl MixNodeBond {
|
||||
}
|
||||
|
||||
pub fn reward(&self, params: &NodeRewardParams) -> NodeRewardResult {
|
||||
// Assuming uniform work distribution across the network this is one_over_k * k
|
||||
let omega_k = ONE;
|
||||
let lambda = self.lambda(params);
|
||||
let sigma = self.sigma(params);
|
||||
|
||||
let reward = params.performance()
|
||||
* params.period_reward_pool()
|
||||
* (sigma * omega_k + params.alpha() * lambda * sigma * params.k())
|
||||
* (sigma * params.omega()
|
||||
+ params.alpha() * lambda * sigma * params.rewarded_set_size())
|
||||
/ (ONE + params.alpha());
|
||||
|
||||
NodeRewardResult {
|
||||
|
||||
@@ -50,6 +50,7 @@ pub struct ContractStateParams {
|
||||
// subset of rewarded mixnodes that are actively receiving mix traffic
|
||||
// used to handle shorter-term (e.g. hourly) fluctuations of demand
|
||||
pub mixnode_active_set_size: u32,
|
||||
pub active_set_work_factor: u8,
|
||||
}
|
||||
|
||||
impl Display for ContractStateParams {
|
||||
@@ -74,6 +75,11 @@ impl Display for ContractStateParams {
|
||||
f,
|
||||
"mixnode active set size: {}",
|
||||
self.mixnode_active_set_size
|
||||
)?;
|
||||
write!(
|
||||
f,
|
||||
"mixnode active set work factor: {}",
|
||||
self.active_set_work_factor
|
||||
)
|
||||
}
|
||||
}
|
||||
|
||||
@@ -37,11 +37,7 @@ pub const INITIAL_MIXNODE_ACTIVE_SET_SIZE: u32 = 100;
|
||||
pub const INITIAL_REWARD_POOL: u128 = 250_000_000_000_000;
|
||||
pub const EPOCH_REWARD_PERCENT: u8 = 2; // Used to calculate epoch reward pool
|
||||
pub const DEFAULT_SYBIL_RESISTANCE_PERCENT: u8 = 30;
|
||||
|
||||
// We'll be assuming a few more things, profit margin and cost function. Since we don't have reliable package measurement, we'll be using uptime. We'll also set the value of 1 Nym to 1 $, to be able to translate epoch costs to Nyms. We'll also assume a cost of 40$ per epoch(month), converting that to Nym at our 1$ rate translates to 40_000_000 uNyms
|
||||
// question to @durch: where do we need it (if at all)?
|
||||
#[allow(dead_code)]
|
||||
pub const DEFAULT_COST_PER_EPOCH: u32 = 40_000_000;
|
||||
pub const DEFAULT_ACTIVE_SET_WORK_FACTOR: u8 = 10;
|
||||
|
||||
fn default_initial_state(
|
||||
owner: Addr,
|
||||
@@ -56,6 +52,7 @@ fn default_initial_state(
|
||||
minimum_gateway_pledge: INITIAL_GATEWAY_PLEDGE,
|
||||
mixnode_rewarded_set_size: INITIAL_MIXNODE_REWARDED_SET_SIZE,
|
||||
mixnode_active_set_size: INITIAL_MIXNODE_ACTIVE_SET_SIZE,
|
||||
active_set_work_factor: DEFAULT_ACTIVE_SET_WORK_FACTOR,
|
||||
},
|
||||
rewarding_interval_starting_block: env.block.height,
|
||||
latest_rewarding_interval_nonce: 0,
|
||||
@@ -285,7 +282,8 @@ pub fn query(deps: Deps, _env: Env, msg: QueryMsg) -> Result<QueryResponse, Cont
|
||||
}
|
||||
#[entry_point]
|
||||
pub fn migrate(_deps: DepsMut, _env: Env, _msg: MigrateMsg) -> Result<Response, ContractError> {
|
||||
Ok(Default::default())
|
||||
todo!("ACTIVE_STATE_WORK_FACTOR to State");
|
||||
// Ok(Default::default())
|
||||
}
|
||||
|
||||
#[cfg(test)]
|
||||
|
||||
@@ -55,6 +55,7 @@ pub(crate) mod tests {
|
||||
minimum_gateway_pledge: 456u128.into(),
|
||||
mixnode_rewarded_set_size: 1000,
|
||||
mixnode_active_set_size: 500,
|
||||
active_set_work_factor: 10,
|
||||
},
|
||||
rewarding_interval_starting_block: 123,
|
||||
latest_rewarding_interval_nonce: 0,
|
||||
|
||||
@@ -60,6 +60,7 @@ pub mod tests {
|
||||
minimum_gateway_pledge: INITIAL_GATEWAY_PLEDGE,
|
||||
mixnode_rewarded_set_size: 100,
|
||||
mixnode_active_set_size: 50,
|
||||
active_set_work_factor: 10,
|
||||
};
|
||||
|
||||
// sanity check to ensure new_params are different than the default ones
|
||||
|
||||
@@ -251,10 +251,6 @@ pub(crate) fn try_reward_next_mixnode_delegators(
|
||||
}
|
||||
}
|
||||
|
||||
// Note: if any changes are made to this function or anything it is calling down the stack,
|
||||
// for example delegation reward distribution, the gas limits must be retested and both
|
||||
// validator-api/src/rewarding/mod.rs::{MIXNODE_REWARD_OP_BASE_GAS_LIMIT, PER_MIXNODE_DELEGATION_GAS_INCREASE}
|
||||
// must be updated appropriately.
|
||||
pub(crate) fn try_reward_mixnode(
|
||||
deps: DepsMut,
|
||||
env: Env,
|
||||
@@ -1088,12 +1084,11 @@ pub mod tests {
|
||||
let rewarding_validator_address = current_state.rewarding_validator_address;
|
||||
let period_reward_pool = (INITIAL_REWARD_POOL / 100) * EPOCH_REWARD_PERCENT as u128;
|
||||
assert_eq!(period_reward_pool, 5_000_000_000_000);
|
||||
let k = 200; // Imagining our active set size is 200
|
||||
let rewarded_set_size = 200; // Imagining our reward set size is 200
|
||||
let active_set_size = 100;
|
||||
let active_set_work_factor = 10;
|
||||
let circulating_supply = storage::circulating_supply(&deps.storage).unwrap().u128();
|
||||
assert_eq!(circulating_supply, 750_000_000_000_000u128);
|
||||
// mut_reward_pool(deps.as_mut().storage)
|
||||
// .save(&Uint128::new(period_reward_pool))
|
||||
// .unwrap();
|
||||
|
||||
let node_owner: Addr = Addr::unchecked("alice");
|
||||
let node_identity = test_helpers::add_mixnode(
|
||||
@@ -1136,11 +1131,14 @@ pub mod tests {
|
||||
|
||||
let mut params = NodeRewardParams::new(
|
||||
period_reward_pool,
|
||||
k,
|
||||
rewarded_set_size,
|
||||
active_set_size,
|
||||
0,
|
||||
circulating_supply,
|
||||
mix_1_uptime,
|
||||
DEFAULT_SYBIL_RESISTANCE_PERCENT,
|
||||
true,
|
||||
active_set_work_factor,
|
||||
);
|
||||
|
||||
params.set_reward_blockstamp(env.block.height);
|
||||
@@ -1157,7 +1155,7 @@ pub mod tests {
|
||||
mix_1_reward_result.lambda(),
|
||||
U128::from_num(0.0000133333333333)
|
||||
);
|
||||
assert_eq!(mix_1_reward_result.reward().int(), 102646153);
|
||||
assert_eq!(mix_1_reward_result.reward().int(), 186562237);
|
||||
|
||||
let mix1_operator_profit = mix_1.operator_reward(¶ms);
|
||||
|
||||
@@ -1165,9 +1163,9 @@ pub mod tests {
|
||||
|
||||
let mix1_delegator2_reward = mix_1.reward_delegation(Uint128::new(2000_000000), ¶ms);
|
||||
|
||||
assert_eq!(mix1_operator_profit, U128::from_num(74455384));
|
||||
assert_eq!(mix1_delegator1_reward, U128::from_num(22552615));
|
||||
assert_eq!(mix1_delegator2_reward, U128::from_num(5638153));
|
||||
assert_eq!(mix1_operator_profit, U128::from_num(120609230));
|
||||
assert_eq!(mix1_delegator1_reward, U128::from_num(52762405));
|
||||
assert_eq!(mix1_delegator2_reward, U128::from_num(13190601));
|
||||
|
||||
let pre_reward_bond =
|
||||
test_helpers::read_mixnode_pledge_amount(&deps.storage, &node_identity)
|
||||
|
||||
@@ -247,10 +247,13 @@ pub mod test_helpers {
|
||||
NodeRewardParams::new(
|
||||
(INITIAL_REWARD_POOL / 100) * EPOCH_REWARD_PERCENT as u128,
|
||||
50 as u128,
|
||||
25 as u128,
|
||||
0,
|
||||
TOTAL_SUPPLY - INITIAL_REWARD_POOL,
|
||||
uptime,
|
||||
DEFAULT_SYBIL_RESISTANCE_PERCENT,
|
||||
true,
|
||||
10,
|
||||
)
|
||||
}
|
||||
|
||||
|
||||
@@ -0,0 +1,3 @@
|
||||
EXPLORER_API_URL=https://testnet-milhon-explorer.nymtech.net
|
||||
VALIDATOR_API_URL=https://testnet-milhon-validator1.nymtech.net
|
||||
BIG_DIPPER_URL=https://testnet-milhon-blocks.nymtech.net
|
||||
@@ -0,0 +1,3 @@
|
||||
EXPLORER_API_URL=https://testnet-milhon-explorer.nymtech.net
|
||||
VALIDATOR_API_URL=https://testnet-milhon-validator1.nymtech.net
|
||||
BIG_DIPPER_URL=https://testnet-milhon-blocks.nymtech.net
|
||||
Generated
+60
@@ -50,6 +50,7 @@
|
||||
"clean-webpack-plugin": "^4.0.0",
|
||||
"css-loader": "^6.2.0",
|
||||
"css-minimizer-webpack-plugin": "^3.0.2",
|
||||
"dotenv-webpack": "^7.0.3",
|
||||
"eslint": "7.32.0",
|
||||
"eslint-config-airbnb": "18.2.1",
|
||||
"eslint-config-prettier": "8.3.0",
|
||||
@@ -6198,6 +6199,39 @@
|
||||
"tslib": "^2.0.3"
|
||||
}
|
||||
},
|
||||
"node_modules/dotenv-defaults": {
|
||||
"version": "2.0.2",
|
||||
"resolved": "https://registry.npmjs.org/dotenv-defaults/-/dotenv-defaults-2.0.2.tgz",
|
||||
"integrity": "sha512-iOIzovWfsUHU91L5i8bJce3NYK5JXeAwH50Jh6+ARUdLiiGlYWfGw6UkzsYqaXZH/hjE/eCd/PlfM/qqyK0AMg==",
|
||||
"dev": true,
|
||||
"dependencies": {
|
||||
"dotenv": "^8.2.0"
|
||||
}
|
||||
},
|
||||
"node_modules/dotenv-defaults/node_modules/dotenv": {
|
||||
"version": "8.6.0",
|
||||
"resolved": "https://registry.npmjs.org/dotenv/-/dotenv-8.6.0.tgz",
|
||||
"integrity": "sha512-IrPdXQsk2BbzvCBGBOTmmSH5SodmqZNt4ERAZDmW4CT+tL8VtvinqywuANaFu4bOMWki16nqf0e4oC0QIaDr/g==",
|
||||
"dev": true,
|
||||
"engines": {
|
||||
"node": ">=10"
|
||||
}
|
||||
},
|
||||
"node_modules/dotenv-webpack": {
|
||||
"version": "7.0.3",
|
||||
"resolved": "https://registry.npmjs.org/dotenv-webpack/-/dotenv-webpack-7.0.3.tgz",
|
||||
"integrity": "sha512-O0O9pOEwrk+n1zzR3T2uuXRlw64QxHSPeNN1GaiNBloQFNaCUL9V8jxSVz4jlXXFP/CIqK8YecWf8BAvsSgMjw==",
|
||||
"dev": true,
|
||||
"dependencies": {
|
||||
"dotenv-defaults": "^2.0.2"
|
||||
},
|
||||
"engines": {
|
||||
"node": ">=10"
|
||||
},
|
||||
"peerDependencies": {
|
||||
"webpack": "^4 || ^5"
|
||||
}
|
||||
},
|
||||
"node_modules/ecc-jsbn": {
|
||||
"version": "0.1.2",
|
||||
"resolved": "https://registry.npmjs.org/ecc-jsbn/-/ecc-jsbn-0.1.2.tgz",
|
||||
@@ -21882,6 +21916,32 @@
|
||||
"tslib": "^2.0.3"
|
||||
}
|
||||
},
|
||||
"dotenv-defaults": {
|
||||
"version": "2.0.2",
|
||||
"resolved": "https://registry.npmjs.org/dotenv-defaults/-/dotenv-defaults-2.0.2.tgz",
|
||||
"integrity": "sha512-iOIzovWfsUHU91L5i8bJce3NYK5JXeAwH50Jh6+ARUdLiiGlYWfGw6UkzsYqaXZH/hjE/eCd/PlfM/qqyK0AMg==",
|
||||
"dev": true,
|
||||
"requires": {
|
||||
"dotenv": "^8.2.0"
|
||||
},
|
||||
"dependencies": {
|
||||
"dotenv": {
|
||||
"version": "8.6.0",
|
||||
"resolved": "https://registry.npmjs.org/dotenv/-/dotenv-8.6.0.tgz",
|
||||
"integrity": "sha512-IrPdXQsk2BbzvCBGBOTmmSH5SodmqZNt4ERAZDmW4CT+tL8VtvinqywuANaFu4bOMWki16nqf0e4oC0QIaDr/g==",
|
||||
"dev": true
|
||||
}
|
||||
}
|
||||
},
|
||||
"dotenv-webpack": {
|
||||
"version": "7.0.3",
|
||||
"resolved": "https://registry.npmjs.org/dotenv-webpack/-/dotenv-webpack-7.0.3.tgz",
|
||||
"integrity": "sha512-O0O9pOEwrk+n1zzR3T2uuXRlw64QxHSPeNN1GaiNBloQFNaCUL9V8jxSVz4jlXXFP/CIqK8YecWf8BAvsSgMjw==",
|
||||
"dev": true,
|
||||
"requires": {
|
||||
"dotenv-defaults": "^2.0.2"
|
||||
}
|
||||
},
|
||||
"ecc-jsbn": {
|
||||
"version": "0.1.2",
|
||||
"resolved": "https://registry.npmjs.org/ecc-jsbn/-/ecc-jsbn-0.1.2.tgz",
|
||||
|
||||
@@ -45,6 +45,7 @@
|
||||
"clean-webpack-plugin": "^4.0.0",
|
||||
"css-loader": "^6.2.0",
|
||||
"css-minimizer-webpack-plugin": "^3.0.2",
|
||||
"dotenv-webpack": "^7.0.3",
|
||||
"eslint": "7.32.0",
|
||||
"eslint-config-airbnb": "18.2.1",
|
||||
"eslint-config-prettier": "8.3.0",
|
||||
|
||||
@@ -1,8 +1,7 @@
|
||||
// master APIs
|
||||
export const MASTER_URL = 'https://testnet-milhon-explorer.nymtech.net';
|
||||
export const MASTER_VALIDATOR_URL =
|
||||
'https://testnet-milhon-validator1.nymtech.net';
|
||||
export const BIG_DIPPER = 'https://testnet-milhon-blocks.nymtech.net';
|
||||
export const MASTER_URL = process.env.EXPLORER_API_URL;
|
||||
export const MASTER_VALIDATOR_URL = process.env.VALIDATOR_API_URL;
|
||||
export const BIG_DIPPER = process.env.BIG_DIPPER_URL;
|
||||
|
||||
// specific API routes
|
||||
export const MIXNODE_PING = `${MASTER_URL}/api/ping`;
|
||||
|
||||
@@ -5,6 +5,7 @@ const TsconfigPathsPlugin = require('tsconfig-paths-webpack-plugin');
|
||||
const { CleanWebpackPlugin } = require('clean-webpack-plugin');
|
||||
const ForkTsCheckerWebpackPlugin = require('fork-ts-checker-webpack-plugin');
|
||||
const WebpackFavicons = require('webpack-favicons');
|
||||
const Dotenv = require('dotenv-webpack');
|
||||
|
||||
module.exports = {
|
||||
entry: './src/index.tsx',
|
||||
@@ -78,6 +79,8 @@ module.exports = {
|
||||
new WebpackFavicons({
|
||||
src: 'src/logo.svg',
|
||||
}),
|
||||
|
||||
new Dotenv(),
|
||||
],
|
||||
output: {
|
||||
path: path.resolve(__dirname, 'dist'),
|
||||
|
||||
@@ -21,7 +21,7 @@ use erc20_bridge_contract::payment::LinkPaymentData;
|
||||
use gateway_client::bandwidth::eth_contract;
|
||||
use network_defaults::{COSMOS_CONTRACT_ADDRESS, DENOM, ETH_EVENT_NAME, ETH_MIN_BLOCK_DEPTH};
|
||||
use validator_client::nymd::{
|
||||
AccountId, CosmosCoin, Decimal, Denom, Fee, Gas, NymdClient, SigningNymdClient,
|
||||
AccountId, CosmosCoin, Decimal, Denom, NymdClient, SigningNymdClient,
|
||||
};
|
||||
|
||||
pub(crate) struct ERC20Bridge {
|
||||
@@ -45,6 +45,7 @@ impl ERC20Bridge {
|
||||
AccountId::from_str(COSMOS_CONTRACT_ADDRESS).ok(),
|
||||
None,
|
||||
mnemonic,
|
||||
None,
|
||||
)
|
||||
.expect("Could not create nymd client");
|
||||
|
||||
@@ -106,7 +107,6 @@ impl ERC20Bridge {
|
||||
denom: Denom::from_str(DENOM).unwrap(),
|
||||
amount: Decimal::from(100000u64),
|
||||
};
|
||||
let fee = Fee::from_amount_and_gas(coin.clone(), Gas::from(500000));
|
||||
let req = ExecuteMsg::LinkPayment {
|
||||
data: LinkPaymentData::new(
|
||||
credential.verification_key().to_bytes(),
|
||||
@@ -120,7 +120,7 @@ impl ERC20Bridge {
|
||||
// it's ok to unwrap here, as the address is
|
||||
contract_address,
|
||||
&req,
|
||||
fee,
|
||||
Default::default(),
|
||||
"Linking payment",
|
||||
vec![coin],
|
||||
)
|
||||
|
||||
Generated
+148
-144
@@ -57,9 +57,9 @@ dependencies = [
|
||||
|
||||
[[package]]
|
||||
name = "anyhow"
|
||||
version = "1.0.45"
|
||||
version = "1.0.51"
|
||||
source = "registry+https://github.com/rust-lang/crates.io-index"
|
||||
checksum = "ee10e43ae4a853c0a3591d4e2ada1719e553be18199d9da9d4a83f5927c2f5c7"
|
||||
checksum = "8b26702f315f53b6071259e15dd9d64528213b44d61de1ec926eca7715d62203"
|
||||
|
||||
[[package]]
|
||||
name = "arrayref"
|
||||
@@ -89,9 +89,9 @@ dependencies = [
|
||||
|
||||
[[package]]
|
||||
name = "async-trait"
|
||||
version = "0.1.51"
|
||||
version = "0.1.52"
|
||||
source = "registry+https://github.com/rust-lang/crates.io-index"
|
||||
checksum = "44318e776df68115a881de9a8fd1b9e53368d7a4a5ce4cc48517da3393233a5e"
|
||||
checksum = "061a7acccaa286c011ddc30970520b98fa40e00c9d644633fb26b5fc63a265e3"
|
||||
dependencies = [
|
||||
"proc-macro2",
|
||||
"quote",
|
||||
@@ -154,9 +154,9 @@ checksum = "cdb031dd78e28731d87d56cc8ffef4a8f36ca26c38fe2de700543e627f8a464a"
|
||||
|
||||
[[package]]
|
||||
name = "az"
|
||||
version = "1.1.2"
|
||||
version = "1.2.0"
|
||||
source = "registry+https://github.com/rust-lang/crates.io-index"
|
||||
checksum = "9d6dff4a1892b54d70af377bf7a17064192e822865791d812957f21e3108c325"
|
||||
checksum = "f771a5d1f5503f7f4279a30f3643d3421ba149848b89ecaaec0ea2acf04a5ac4"
|
||||
|
||||
[[package]]
|
||||
name = "base64"
|
||||
@@ -331,9 +331,9 @@ checksum = "e3b5ca7a04898ad4bcd41c90c5285445ff5b791899bb1b0abdd2a2aa791211d7"
|
||||
|
||||
[[package]]
|
||||
name = "bytemuck"
|
||||
version = "1.7.2"
|
||||
version = "1.7.3"
|
||||
source = "registry+https://github.com/rust-lang/crates.io-index"
|
||||
checksum = "72957246c41db82b8ef88a5486143830adeb8227ef9837740bdec67724cf2c5b"
|
||||
checksum = "439989e6b8c38d1b6570a384ef1e49c8848128f5a97f3914baef02920842712f"
|
||||
|
||||
[[package]]
|
||||
name = "byteorder"
|
||||
@@ -394,9 +394,9 @@ dependencies = [
|
||||
|
||||
[[package]]
|
||||
name = "cc"
|
||||
version = "1.0.71"
|
||||
version = "1.0.72"
|
||||
source = "registry+https://github.com/rust-lang/crates.io-index"
|
||||
checksum = "79c2681d6594606957bbb8631c4b90a7fcaaa72cdb714743a437b156d6a7eedd"
|
||||
checksum = "22a9137b95ea06864e018375b72adfb7db6e6f68cfc8df5a04d00288050485ee"
|
||||
dependencies = [
|
||||
"jobserver",
|
||||
]
|
||||
@@ -448,19 +448,6 @@ dependencies = [
|
||||
"keystream",
|
||||
]
|
||||
|
||||
[[package]]
|
||||
name = "chrono"
|
||||
version = "0.4.19"
|
||||
source = "registry+https://github.com/rust-lang/crates.io-index"
|
||||
checksum = "670ad68c9088c2a963aaa298cb369688cf3f9465ce5e2d4ca10e6e0098a1ce73"
|
||||
dependencies = [
|
||||
"libc",
|
||||
"num-integer",
|
||||
"num-traits",
|
||||
"serde",
|
||||
"winapi",
|
||||
]
|
||||
|
||||
[[package]]
|
||||
name = "cipher"
|
||||
version = "0.3.0"
|
||||
@@ -696,9 +683,9 @@ dependencies = [
|
||||
|
||||
[[package]]
|
||||
name = "cosmwasm-crypto"
|
||||
version = "1.0.0-beta2"
|
||||
version = "1.0.0-beta3"
|
||||
source = "registry+https://github.com/rust-lang/crates.io-index"
|
||||
checksum = "c16b255449b3f5cd7fa4b79acd5225b5185655261087a3d8aaac44f88a0e23e9"
|
||||
checksum = "a380b87642204557629c9b72988c47b55fbfe6d474960adba56b22331504956a"
|
||||
dependencies = [
|
||||
"digest 0.9.0",
|
||||
"ed25519-zebra",
|
||||
@@ -709,18 +696,18 @@ dependencies = [
|
||||
|
||||
[[package]]
|
||||
name = "cosmwasm-derive"
|
||||
version = "1.0.0-beta2"
|
||||
version = "1.0.0-beta3"
|
||||
source = "registry+https://github.com/rust-lang/crates.io-index"
|
||||
checksum = "abad1a6ff427a2f66890a4dce6354b4563cd07cee91a942300e011c921c09ed2"
|
||||
checksum = "866713b2fe13f23038c7d8824c3059d1f28dd94685fb406d1533c4eeeefeefae"
|
||||
dependencies = [
|
||||
"syn",
|
||||
]
|
||||
|
||||
[[package]]
|
||||
name = "cosmwasm-std"
|
||||
version = "1.0.0-beta2"
|
||||
version = "1.0.0-beta3"
|
||||
source = "registry+https://github.com/rust-lang/crates.io-index"
|
||||
checksum = "1660ee3d5734672e1eb4f0ceda403e2d83345e15143a48845f340f3252ce99a6"
|
||||
checksum = "8dbb9939b31441dfa9af3ec9740c8a24d585688401eff1b6b386abb7ad0d10a8"
|
||||
dependencies = [
|
||||
"base64",
|
||||
"cosmwasm-crypto",
|
||||
@@ -743,9 +730,9 @@ dependencies = [
|
||||
|
||||
[[package]]
|
||||
name = "crc32fast"
|
||||
version = "1.2.1"
|
||||
version = "1.3.0"
|
||||
source = "registry+https://github.com/rust-lang/crates.io-index"
|
||||
checksum = "81156fece84ab6a9f2afdb109ce3ae577e42b1228441eded99bd77f627953b1a"
|
||||
checksum = "738c290dfaea84fc1ca15ad9c168d083b05a714e1efddd8edaab678dc28d2836"
|
||||
dependencies = [
|
||||
"cfg-if 1.0.0",
|
||||
]
|
||||
@@ -872,7 +859,7 @@ checksum = "754b69d351cdc2d8ee09ae203db831e005560fc6030da058f86ad60c92a9cb0a"
|
||||
dependencies = [
|
||||
"cssparser-macros",
|
||||
"dtoa-short",
|
||||
"itoa",
|
||||
"itoa 0.4.8",
|
||||
"matches",
|
||||
"phf 0.8.0",
|
||||
"proc-macro2",
|
||||
@@ -909,6 +896,12 @@ dependencies = [
|
||||
"cipher",
|
||||
]
|
||||
|
||||
[[package]]
|
||||
name = "cty"
|
||||
version = "0.2.2"
|
||||
source = "registry+https://github.com/rust-lang/crates.io-index"
|
||||
checksum = "b365fabc795046672053e29c954733ec3b05e4be654ab130fe8f1f94d7051f35"
|
||||
|
||||
[[package]]
|
||||
name = "curve25519-dalek"
|
||||
version = "3.2.0"
|
||||
@@ -990,9 +983,9 @@ dependencies = [
|
||||
|
||||
[[package]]
|
||||
name = "der"
|
||||
version = "0.4.4"
|
||||
version = "0.4.5"
|
||||
source = "registry+https://github.com/rust-lang/crates.io-index"
|
||||
checksum = "28e98c534e9c8a0483aa01d6f6913bc063de254311bd267c9cf535e9b70e15b2"
|
||||
checksum = "79b71cca7d95d7681a4b3b9cdf63c8dbc3730d0584c2c74e31416d64a90493f4"
|
||||
dependencies = [
|
||||
"const-oid",
|
||||
]
|
||||
@@ -1010,14 +1003,14 @@ dependencies = [
|
||||
|
||||
[[package]]
|
||||
name = "derive_more"
|
||||
version = "0.99.16"
|
||||
version = "0.99.17"
|
||||
source = "registry+https://github.com/rust-lang/crates.io-index"
|
||||
checksum = "40eebddd2156ce1bb37b20bbe5151340a31828b1f2d22ba4141f3531710e38df"
|
||||
checksum = "4fb810d30a7c1953f91334de7244731fc3f3c10d7fe163338a35b9f640960321"
|
||||
dependencies = [
|
||||
"convert_case",
|
||||
"proc-macro2",
|
||||
"quote",
|
||||
"rustc_version",
|
||||
"rustc_version 0.4.0",
|
||||
"syn",
|
||||
]
|
||||
|
||||
@@ -1160,9 +1153,9 @@ dependencies = [
|
||||
|
||||
[[package]]
|
||||
name = "ed25519"
|
||||
version = "1.2.0"
|
||||
version = "1.3.0"
|
||||
source = "registry+https://github.com/rust-lang/crates.io-index"
|
||||
checksum = "4620d40f6d2601794401d6dd95a5cf69b6c157852539470eeda433a99b3c0efc"
|
||||
checksum = "74e1069e39f1454367eb2de793ed062fac4c35c2934b76a81d90dd9abcd28816"
|
||||
dependencies = [
|
||||
"signature",
|
||||
]
|
||||
@@ -1225,9 +1218,9 @@ checksum = "53dd2e43a7d32952a6054141ee0d75183958620e84e5eab045de362dff13dc99"
|
||||
|
||||
[[package]]
|
||||
name = "encoding_rs"
|
||||
version = "0.8.29"
|
||||
version = "0.8.30"
|
||||
source = "registry+https://github.com/rust-lang/crates.io-index"
|
||||
checksum = "a74ea89a0a1b98f6332de42c95baff457ada66d1cb4030f9ff151b2041a1c746"
|
||||
checksum = "7896dc8abb250ffdda33912550faa54c88ec8b998dec0b2c55ab224921ce11df"
|
||||
dependencies = [
|
||||
"cfg-if 1.0.0",
|
||||
]
|
||||
@@ -1286,7 +1279,7 @@ source = "registry+https://github.com/rust-lang/crates.io-index"
|
||||
checksum = "1e1c54951450cbd39f3dbcf1005ac413b49487dabf18a720ad2383eccfeffb92"
|
||||
dependencies = [
|
||||
"memoffset",
|
||||
"rustc_version",
|
||||
"rustc_version 0.3.3",
|
||||
]
|
||||
|
||||
[[package]]
|
||||
@@ -1303,9 +1296,9 @@ dependencies = [
|
||||
|
||||
[[package]]
|
||||
name = "fixed"
|
||||
version = "1.10.0"
|
||||
version = "1.11.0"
|
||||
source = "registry+https://github.com/rust-lang/crates.io-index"
|
||||
checksum = "6d333a26ec13a023c6dff4b7584de4d323cfee2e508f5dd2bbee6669e4f7efdf"
|
||||
checksum = "80a9a8cb2e34880a498f09367089339bda5e12d6f871640f947850f7113058c0"
|
||||
dependencies = [
|
||||
"az",
|
||||
"bytemuck",
|
||||
@@ -1631,9 +1624,9 @@ dependencies = [
|
||||
|
||||
[[package]]
|
||||
name = "getset"
|
||||
version = "0.1.1"
|
||||
version = "0.1.2"
|
||||
source = "registry+https://github.com/rust-lang/crates.io-index"
|
||||
checksum = "24b328c01a4d71d2d8173daa93562a73ab0fe85616876f02500f53d82948c504"
|
||||
checksum = "e45727250e75cc04ff2846a66397da8ef2b3db8e40e0cef4df67950a07621eb9"
|
||||
dependencies = [
|
||||
"proc-macro-error",
|
||||
"proc-macro2",
|
||||
@@ -1843,9 +1836,9 @@ dependencies = [
|
||||
|
||||
[[package]]
|
||||
name = "h2"
|
||||
version = "0.3.7"
|
||||
version = "0.3.9"
|
||||
source = "registry+https://github.com/rust-lang/crates.io-index"
|
||||
checksum = "7fd819562fcebdac5afc5c113c3ec36f902840b70fd4fc458799c8ce4607ae55"
|
||||
checksum = "8f072413d126e57991455e0a922b31e4c8ba7c2ffbebf6b78b4f8521397d65cd"
|
||||
dependencies = [
|
||||
"bytes",
|
||||
"fnv",
|
||||
@@ -1937,9 +1930,9 @@ checksum = "7f24254aa9a54b5c858eaee2f5bccdb46aaf0e486a595ed5fd8f86ba55232a70"
|
||||
|
||||
[[package]]
|
||||
name = "hex-literal"
|
||||
version = "0.3.3"
|
||||
version = "0.3.4"
|
||||
source = "registry+https://github.com/rust-lang/crates.io-index"
|
||||
checksum = "21e4590e13640f19f249fe3e4eca5113bc4289f2497710378190e7f4bd96f45b"
|
||||
checksum = "7ebdb29d2ea9ed0083cd8cece49bbd968021bd99b0849edb4a9a7ee0fdf6a4e0"
|
||||
|
||||
[[package]]
|
||||
name = "hkd32"
|
||||
@@ -1997,7 +1990,7 @@ checksum = "1323096b05d41827dadeaee54c9981958c0f94e670bc94ed80037d1a7b8b186b"
|
||||
dependencies = [
|
||||
"bytes",
|
||||
"fnv",
|
||||
"itoa",
|
||||
"itoa 0.4.8",
|
||||
]
|
||||
|
||||
[[package]]
|
||||
@@ -2025,9 +2018,9 @@ checksum = "acd94fdbe1d4ff688b67b04eee2e17bd50995534a61539e45adfefb45e5e5503"
|
||||
|
||||
[[package]]
|
||||
name = "httpdate"
|
||||
version = "1.0.1"
|
||||
version = "1.0.2"
|
||||
source = "registry+https://github.com/rust-lang/crates.io-index"
|
||||
checksum = "6456b8a6c8f33fee7d958fcd1b60d55b11940a79e63ae87013e6d22e26034440"
|
||||
checksum = "c4a1e36c821dbe04574f602848a19f742f4fb3c98d40449f11bcad18d6b17421"
|
||||
|
||||
[[package]]
|
||||
name = "humantime"
|
||||
@@ -2047,9 +2040,9 @@ dependencies = [
|
||||
|
||||
[[package]]
|
||||
name = "hyper"
|
||||
version = "0.14.14"
|
||||
version = "0.14.16"
|
||||
source = "registry+https://github.com/rust-lang/crates.io-index"
|
||||
checksum = "2b91bb1f221b6ea1f1e4371216b70f40748774c2fb5971b450c07773fb92d26b"
|
||||
checksum = "b7ec3e62bdc98a2f0393a5048e4c30ef659440ea6e0e572965103e72bd836f55"
|
||||
dependencies = [
|
||||
"bytes",
|
||||
"futures-channel",
|
||||
@@ -2060,7 +2053,7 @@ dependencies = [
|
||||
"http-body",
|
||||
"httparse",
|
||||
"httpdate",
|
||||
"itoa",
|
||||
"itoa 0.4.8",
|
||||
"pin-project-lite",
|
||||
"socket2",
|
||||
"tokio",
|
||||
@@ -2227,9 +2220,9 @@ dependencies = [
|
||||
|
||||
[[package]]
|
||||
name = "itertools"
|
||||
version = "0.10.1"
|
||||
version = "0.10.3"
|
||||
source = "registry+https://github.com/rust-lang/crates.io-index"
|
||||
checksum = "69ddb889f9d0d08a67338271fa9b62996bc788c7796a5c18cf057420aaed5eaf"
|
||||
checksum = "a9a9d19fa1e79b6215ff29b9d6880b706147f16e9b1dbb1e4e5947b5b02bc5e3"
|
||||
dependencies = [
|
||||
"either",
|
||||
]
|
||||
@@ -2240,6 +2233,12 @@ version = "0.4.8"
|
||||
source = "registry+https://github.com/rust-lang/crates.io-index"
|
||||
checksum = "b71991ff56294aa922b450139ee08b3bfc70982c6b2c7562771375cf73542dd4"
|
||||
|
||||
[[package]]
|
||||
name = "itoa"
|
||||
version = "1.0.1"
|
||||
source = "registry+https://github.com/rust-lang/crates.io-index"
|
||||
checksum = "1aab8fc367588b89dcee83ab0fd66b72b50b72fa1904d7095045ace2b0c81c35"
|
||||
|
||||
[[package]]
|
||||
name = "javascriptcore-rs"
|
||||
version = "0.14.0"
|
||||
@@ -2328,9 +2327,9 @@ checksum = "e2abad23fbc42b3700f2f279844dc832adb2b2eb069b2df918f455c4e18cc646"
|
||||
|
||||
[[package]]
|
||||
name = "libc"
|
||||
version = "0.2.107"
|
||||
version = "0.2.112"
|
||||
source = "registry+https://github.com/rust-lang/crates.io-index"
|
||||
checksum = "fbe5e23404da5b4f555ef85ebed98fb4083e55a00c317800bc2a50ede9f3d219"
|
||||
checksum = "1b03d17f364a3a042d5e5d46b053bbbf82c92c9430c592dd4c064dc6ee997125"
|
||||
|
||||
[[package]]
|
||||
name = "libm"
|
||||
@@ -2370,9 +2369,9 @@ dependencies = [
|
||||
|
||||
[[package]]
|
||||
name = "loom"
|
||||
version = "0.5.2"
|
||||
version = "0.5.4"
|
||||
source = "registry+https://github.com/rust-lang/crates.io-index"
|
||||
checksum = "b2b9df80a3804094bf49bb29881d18f6f05048db72127e84e09c26fc7c2324f5"
|
||||
checksum = "edc5c7d328e32cc4954e8e01193d7f0ef5ab257b5090b70a964e099a36034309"
|
||||
dependencies = [
|
||||
"cfg-if 1.0.0",
|
||||
"generator",
|
||||
@@ -2420,9 +2419,9 @@ dependencies = [
|
||||
|
||||
[[package]]
|
||||
name = "matchers"
|
||||
version = "0.0.1"
|
||||
version = "0.1.0"
|
||||
source = "registry+https://github.com/rust-lang/crates.io-index"
|
||||
checksum = "f099785f7595cc4b4553a174ce30dd7589ef93391ff414dbb67f62392b9e0ce1"
|
||||
checksum = "8263075bb86c5a1b1427b5ae862e8889656f126e9f77c484496e8b47cf5c5558"
|
||||
dependencies = [
|
||||
"regex-automata",
|
||||
]
|
||||
@@ -2447,9 +2446,9 @@ checksum = "308cc39be01b73d0d18f82a0e7b2a3df85245f84af96fdddc5d202d27e47b86a"
|
||||
|
||||
[[package]]
|
||||
name = "memoffset"
|
||||
version = "0.6.4"
|
||||
version = "0.6.5"
|
||||
source = "registry+https://github.com/rust-lang/crates.io-index"
|
||||
checksum = "59accc507f1338036a0477ef61afdae33cde60840f4dfe481319ce3ad116ddf9"
|
||||
checksum = "5aa361d4faea93603064a027415f07bd8e1d5c88c9fbf68bf56a285428fd79ce"
|
||||
dependencies = [
|
||||
"autocfg 1.0.1",
|
||||
]
|
||||
@@ -2577,9 +2576,9 @@ dependencies = [
|
||||
|
||||
[[package]]
|
||||
name = "ndk-sys"
|
||||
version = "0.2.1"
|
||||
version = "0.2.2"
|
||||
source = "registry+https://github.com/rust-lang/crates.io-index"
|
||||
checksum = "c44922cb3dbb1c70b5e5f443d63b64363a898564d739ba5198e3a9138442868d"
|
||||
checksum = "e1bcdd74c20ad5d95aacd60ef9ba40fdf77f767051040541df557b7a9b2a2121"
|
||||
|
||||
[[package]]
|
||||
name = "network-defaults"
|
||||
@@ -2587,7 +2586,7 @@ version = "0.1.0"
|
||||
dependencies = [
|
||||
"hex-literal",
|
||||
"serde",
|
||||
"time 0.3.4",
|
||||
"time 0.3.5",
|
||||
"url",
|
||||
]
|
||||
|
||||
@@ -2709,6 +2708,7 @@ dependencies = [
|
||||
"cosmwasm-std",
|
||||
"credentials",
|
||||
"dirs",
|
||||
"eyre",
|
||||
"mixnet-contract",
|
||||
"rand 0.6.5",
|
||||
"serde",
|
||||
@@ -2779,9 +2779,9 @@ dependencies = [
|
||||
|
||||
[[package]]
|
||||
name = "once_cell"
|
||||
version = "1.8.0"
|
||||
version = "1.9.0"
|
||||
source = "registry+https://github.com/rust-lang/crates.io-index"
|
||||
checksum = "692fcb63b64b1758029e0a96ee63e049ce8c5948587f2f7208df04625e5f6b56"
|
||||
checksum = "da32515d9f6e6e489d7bc9d84c71b060db7247dc035bbe44eac88cf87486d8d5"
|
||||
|
||||
[[package]]
|
||||
name = "opaque-debug"
|
||||
@@ -2797,9 +2797,9 @@ checksum = "624a8340c38c1b80fd549087862da4ba43e08858af025b236e509b6649fc13d5"
|
||||
|
||||
[[package]]
|
||||
name = "open"
|
||||
version = "2.0.1"
|
||||
version = "2.0.2"
|
||||
source = "registry+https://github.com/rust-lang/crates.io-index"
|
||||
checksum = "b46b233de7d83bc167fe43ae2dda3b5b84e80e09cceba581e4decb958a4896bf"
|
||||
checksum = "176ee4b630d174d2da8241336763bb459281dddc0f4d87f72c3b1efc9a6109b7"
|
||||
dependencies = [
|
||||
"pathdiff",
|
||||
"winapi",
|
||||
@@ -2827,9 +2827,9 @@ checksum = "28988d872ab76095a6e6ac88d99b54fd267702734fd7ffe610ca27f533ddb95a"
|
||||
|
||||
[[package]]
|
||||
name = "openssl-sys"
|
||||
version = "0.9.70"
|
||||
version = "0.9.72"
|
||||
source = "registry+https://github.com/rust-lang/crates.io-index"
|
||||
checksum = "c6517987b3f8226b5da3661dad65ff7f300cc59fb5ea8333ca191fc65fde3edf"
|
||||
checksum = "7e46109c383602735fa0a2e48dd2b7c892b048e1bf69e5c3b1d804b7d9c203cb"
|
||||
dependencies = [
|
||||
"autocfg 1.0.1",
|
||||
"cc",
|
||||
@@ -3040,9 +3040,9 @@ dependencies = [
|
||||
|
||||
[[package]]
|
||||
name = "phf"
|
||||
version = "0.10.0"
|
||||
version = "0.10.1"
|
||||
source = "registry+https://github.com/rust-lang/crates.io-index"
|
||||
checksum = "b9fc3db1018c4b59d7d582a739436478b6035138b6aecbce989fc91c3e98409f"
|
||||
checksum = "fabbf1ead8a5bcbc20f5f8b939ee3f5b0f6f281b6ad3468b84656b658b455259"
|
||||
dependencies = [
|
||||
"phf_macros 0.10.0",
|
||||
"phf_shared 0.10.0",
|
||||
@@ -3169,9 +3169,9 @@ dependencies = [
|
||||
|
||||
[[package]]
|
||||
name = "pkg-config"
|
||||
version = "0.3.22"
|
||||
version = "0.3.24"
|
||||
source = "registry+https://github.com/rust-lang/crates.io-index"
|
||||
checksum = "12295df4f294471248581bc09bef3c38a5e46f1e36d6a37353621a0c6c357e1f"
|
||||
checksum = "58893f751c9b0412871a09abd62ecd2a00298c6c83befa223ef98c52aef40cbe"
|
||||
|
||||
[[package]]
|
||||
name = "pmutil"
|
||||
@@ -3277,9 +3277,9 @@ checksum = "bc881b2c22681370c6a780e47af9840ef841837bc98118431d4e1868bd0c1086"
|
||||
|
||||
[[package]]
|
||||
name = "proc-macro2"
|
||||
version = "1.0.32"
|
||||
version = "1.0.34"
|
||||
source = "registry+https://github.com/rust-lang/crates.io-index"
|
||||
checksum = "ba508cc11742c0dc5c1659771673afbab7a0efab23aa17e854cbab0837ed0b43"
|
||||
checksum = "2f84e92c0f7c9d58328b85a78557813e4bd845130db68d7184635344399423b1"
|
||||
dependencies = [
|
||||
"unicode-xid",
|
||||
]
|
||||
@@ -3541,11 +3541,21 @@ dependencies = [
|
||||
|
||||
[[package]]
|
||||
name = "raw-window-handle"
|
||||
version = "0.3.3"
|
||||
version = "0.3.4"
|
||||
source = "registry+https://github.com/rust-lang/crates.io-index"
|
||||
checksum = "0a441a7a6c80ad6473bd4b74ec1c9a4c951794285bf941c2126f607c72e48211"
|
||||
checksum = "e28f55143d0548dad60bb4fbdc835a3d7ac6acc3324506450c5fdd6e42903a76"
|
||||
dependencies = [
|
||||
"libc",
|
||||
"raw-window-handle 0.4.2",
|
||||
]
|
||||
|
||||
[[package]]
|
||||
name = "raw-window-handle"
|
||||
version = "0.4.2"
|
||||
source = "registry+https://github.com/rust-lang/crates.io-index"
|
||||
checksum = "fba75eee94a9d5273a68c9e1e105d9cffe1ef700532325788389e5a83e2522b7"
|
||||
dependencies = [
|
||||
"cty",
|
||||
]
|
||||
|
||||
[[package]]
|
||||
@@ -3638,9 +3648,9 @@ dependencies = [
|
||||
|
||||
[[package]]
|
||||
name = "reqwest"
|
||||
version = "0.11.6"
|
||||
version = "0.11.7"
|
||||
source = "registry+https://github.com/rust-lang/crates.io-index"
|
||||
checksum = "66d2927ca2f685faf0fc620ac4834690d29e7abb153add10f5812eef20b5e280"
|
||||
checksum = "07bea77bc708afa10e59905c3d4af7c8fd43c9214251673095ff8b14345fcbc5"
|
||||
dependencies = [
|
||||
"base64",
|
||||
"bytes",
|
||||
@@ -3687,7 +3697,7 @@ dependencies = [
|
||||
"objc",
|
||||
"objc-foundation",
|
||||
"objc_id",
|
||||
"raw-window-handle",
|
||||
"raw-window-handle 0.3.4",
|
||||
"wasm-bindgen",
|
||||
"wasm-bindgen-futures",
|
||||
"web-sys",
|
||||
@@ -3729,6 +3739,15 @@ dependencies = [
|
||||
"semver 0.11.0",
|
||||
]
|
||||
|
||||
[[package]]
|
||||
name = "rustc_version"
|
||||
version = "0.4.0"
|
||||
source = "registry+https://github.com/rust-lang/crates.io-index"
|
||||
checksum = "bfa0f585226d2e68097d4f95d113b15b83a82e819ab25717ec0590d9584ef366"
|
||||
dependencies = [
|
||||
"semver 1.0.4",
|
||||
]
|
||||
|
||||
[[package]]
|
||||
name = "rustls"
|
||||
version = "0.19.1"
|
||||
@@ -3756,15 +3775,15 @@ dependencies = [
|
||||
|
||||
[[package]]
|
||||
name = "rustversion"
|
||||
version = "1.0.5"
|
||||
version = "1.0.6"
|
||||
source = "registry+https://github.com/rust-lang/crates.io-index"
|
||||
checksum = "61b3909d758bb75c79f23d4736fac9433868679d3ad2ea7a61e3c25cfda9a088"
|
||||
checksum = "f2cc38e8fa666e2de3c4aba7edeb5ffc5246c1c2ed0e3d17e560aeeba736b23f"
|
||||
|
||||
[[package]]
|
||||
name = "ryu"
|
||||
version = "1.0.5"
|
||||
version = "1.0.9"
|
||||
source = "registry+https://github.com/rust-lang/crates.io-index"
|
||||
checksum = "71d301d4193d031abdd79ff7e3dd721168a9572ef3fe51a1517aba235bd8f86e"
|
||||
checksum = "73b4b750c782965c211b42f022f59af1fbceabdd026623714f104152f1ec149f"
|
||||
|
||||
[[package]]
|
||||
name = "same-file"
|
||||
@@ -3787,9 +3806,9 @@ dependencies = [
|
||||
|
||||
[[package]]
|
||||
name = "schemars"
|
||||
version = "0.8.6"
|
||||
version = "0.8.8"
|
||||
source = "registry+https://github.com/rust-lang/crates.io-index"
|
||||
checksum = "d7a48d098c2a7fdf5740b19deb1181b4fb8a9e68e03ae517c14cde04b5725409"
|
||||
checksum = "c6b5a3c80cea1ab61f4260238409510e814e38b4b563c06044edf91e7dc070e3"
|
||||
dependencies = [
|
||||
"dyn-clone",
|
||||
"schemars_derive",
|
||||
@@ -3799,9 +3818,9 @@ dependencies = [
|
||||
|
||||
[[package]]
|
||||
name = "schemars_derive"
|
||||
version = "0.8.6"
|
||||
version = "0.8.8"
|
||||
source = "registry+https://github.com/rust-lang/crates.io-index"
|
||||
checksum = "4a9ea2a613fe4cd7118b2bb101a25d8ae6192e1975179b67b2f17afd11e70ac8"
|
||||
checksum = "41ae4dce13e8614c46ac3c38ef1c0d668b101df6ac39817aebdaa26642ddae9b"
|
||||
dependencies = [
|
||||
"proc-macro2",
|
||||
"quote",
|
||||
@@ -3900,18 +3919,18 @@ dependencies = [
|
||||
|
||||
[[package]]
|
||||
name = "serde"
|
||||
version = "1.0.130"
|
||||
version = "1.0.131"
|
||||
source = "registry+https://github.com/rust-lang/crates.io-index"
|
||||
checksum = "f12d06de37cf59146fbdecab66aa99f9fe4f78722e3607577a5375d66bd0c913"
|
||||
checksum = "b4ad69dfbd3e45369132cc64e6748c2d65cdfb001a2b1c232d128b4ad60561c1"
|
||||
dependencies = [
|
||||
"serde_derive",
|
||||
]
|
||||
|
||||
[[package]]
|
||||
name = "serde-json-wasm"
|
||||
version = "0.3.1"
|
||||
version = "0.3.2"
|
||||
source = "registry+https://github.com/rust-lang/crates.io-index"
|
||||
checksum = "50eef3672ec8fa45f3457fd423ba131117786784a895548021976117c1ded449"
|
||||
checksum = "042ac496d97e5885149d34139bad1d617192770d7eb8f1866da2317ff4501853"
|
||||
dependencies = [
|
||||
"serde",
|
||||
]
|
||||
@@ -3927,9 +3946,9 @@ dependencies = [
|
||||
|
||||
[[package]]
|
||||
name = "serde_derive"
|
||||
version = "1.0.130"
|
||||
version = "1.0.131"
|
||||
source = "registry+https://github.com/rust-lang/crates.io-index"
|
||||
checksum = "d7bc1a1ab1961464eae040d96713baa5a724a8152c1222492465b54322ec508b"
|
||||
checksum = "b710a83c4e0dff6a3d511946b95274ad9ca9e5d3ae497b63fda866ac955358d2"
|
||||
dependencies = [
|
||||
"proc-macro2",
|
||||
"quote",
|
||||
@@ -3949,11 +3968,11 @@ dependencies = [
|
||||
|
||||
[[package]]
|
||||
name = "serde_json"
|
||||
version = "1.0.69"
|
||||
version = "1.0.73"
|
||||
source = "registry+https://github.com/rust-lang/crates.io-index"
|
||||
checksum = "e466864e431129c7e0d3476b92f20458e5879919a0596c6472738d9fa2d342f8"
|
||||
checksum = "bcbd0344bc6533bc7ec56df11d42fb70f1b912351c0825ccb7211b59d8af7cf5"
|
||||
dependencies = [
|
||||
"itoa",
|
||||
"itoa 1.0.1",
|
||||
"ryu",
|
||||
"serde",
|
||||
]
|
||||
@@ -3976,7 +3995,7 @@ source = "registry+https://github.com/rust-lang/crates.io-index"
|
||||
checksum = "9ec5d77e2d4c73717816afac02670d5c4f534ea95ed430442cad02e7a6e32c97"
|
||||
dependencies = [
|
||||
"dtoa",
|
||||
"itoa",
|
||||
"itoa 0.4.8",
|
||||
"serde",
|
||||
"url",
|
||||
]
|
||||
@@ -3988,7 +4007,7 @@ source = "registry+https://github.com/rust-lang/crates.io-index"
|
||||
checksum = "edfa57a7f8d9c1d260a549e7224100f6c43d43f9103e06dd8b4095a9b2b43ce9"
|
||||
dependencies = [
|
||||
"form_urlencoded",
|
||||
"itoa",
|
||||
"itoa 0.4.8",
|
||||
"ryu",
|
||||
"serde",
|
||||
]
|
||||
@@ -4510,7 +4529,7 @@ dependencies = [
|
||||
"ndk-sys",
|
||||
"objc",
|
||||
"parking_lot",
|
||||
"raw-window-handle",
|
||||
"raw-window-handle 0.3.4",
|
||||
"scopeguard",
|
||||
"serde",
|
||||
"unicode-segmentation",
|
||||
@@ -4520,9 +4539,9 @@ dependencies = [
|
||||
|
||||
[[package]]
|
||||
name = "tar"
|
||||
version = "0.4.37"
|
||||
version = "0.4.38"
|
||||
source = "registry+https://github.com/rust-lang/crates.io-index"
|
||||
checksum = "d6f5515d3add52e0bbdcad7b83c388bb36ba7b754dda3b5f5bc2d38640cdba5c"
|
||||
checksum = "4b55807c0344e1e6c04d7c965f5289c39a8d94ae23ed5c0b57aabac549f871c6"
|
||||
dependencies = [
|
||||
"filetime",
|
||||
"libc",
|
||||
@@ -4552,7 +4571,7 @@ dependencies = [
|
||||
"open",
|
||||
"percent-encoding",
|
||||
"rand 0.8.4",
|
||||
"raw-window-handle",
|
||||
"raw-window-handle 0.3.4",
|
||||
"rfd",
|
||||
"semver 1.0.4",
|
||||
"serde",
|
||||
@@ -4660,7 +4679,7 @@ checksum = "fcb9b79594f22b6ed0cc8362e0dfde5b7969962de3cd8ca683de702e59e8221b"
|
||||
dependencies = [
|
||||
"html5ever",
|
||||
"kuchiki",
|
||||
"phf 0.10.0",
|
||||
"phf 0.10.1",
|
||||
"proc-macro2",
|
||||
"quote",
|
||||
"serde",
|
||||
@@ -4686,13 +4705,12 @@ dependencies = [
|
||||
|
||||
[[package]]
|
||||
name = "tendermint"
|
||||
version = "0.23.0"
|
||||
version = "0.23.2"
|
||||
source = "registry+https://github.com/rust-lang/crates.io-index"
|
||||
checksum = "50d1cdb0236becb17ab35a2ed1566503e412fd910944dc940239857bb7663652"
|
||||
checksum = "9015fdeab074f9b8f97dcb89c2bb2ec8537c89423e95551e8d7ecdfbab58a329"
|
||||
dependencies = [
|
||||
"async-trait",
|
||||
"bytes",
|
||||
"chrono",
|
||||
"ed25519",
|
||||
"ed25519-dalek",
|
||||
"flex-error",
|
||||
@@ -4712,14 +4730,15 @@ dependencies = [
|
||||
"subtle 2.4.1",
|
||||
"subtle-encoding",
|
||||
"tendermint-proto",
|
||||
"time 0.3.5",
|
||||
"zeroize",
|
||||
]
|
||||
|
||||
[[package]]
|
||||
name = "tendermint-config"
|
||||
version = "0.23.0"
|
||||
version = "0.23.2"
|
||||
source = "registry+https://github.com/rust-lang/crates.io-index"
|
||||
checksum = "2a1f94250d30e3011130a09756b05985d8dbfbd562cf261b5a17e36d89a37992"
|
||||
checksum = "a2b2e6d4442bab49319dbacdfd79c5929bc6e0b35d1e0d959ff5b79fddf3f018"
|
||||
dependencies = [
|
||||
"flex-error",
|
||||
"serde",
|
||||
@@ -4731,12 +4750,11 @@ dependencies = [
|
||||
|
||||
[[package]]
|
||||
name = "tendermint-proto"
|
||||
version = "0.23.0"
|
||||
version = "0.23.2"
|
||||
source = "registry+https://github.com/rust-lang/crates.io-index"
|
||||
checksum = "ff16a7b42bdbcf31c8cd10a4cffc7631f2a301360ba3a3f71dde48eabfa5bced"
|
||||
checksum = "da86f6e52ced9c2f24c4ae57662ce8a44dd90ee7bc47bae27a710b02d48e193c"
|
||||
dependencies = [
|
||||
"bytes",
|
||||
"chrono",
|
||||
"flex-error",
|
||||
"num-derive",
|
||||
"num-traits",
|
||||
@@ -4745,17 +4763,17 @@ dependencies = [
|
||||
"serde",
|
||||
"serde_bytes",
|
||||
"subtle-encoding",
|
||||
"time 0.3.5",
|
||||
]
|
||||
|
||||
[[package]]
|
||||
name = "tendermint-rpc"
|
||||
version = "0.23.0"
|
||||
version = "0.23.2"
|
||||
source = "registry+https://github.com/rust-lang/crates.io-index"
|
||||
checksum = "c7842dcd5edb60b077572aa92ff8b29fc810b9b463310f9810a2607474130db4"
|
||||
checksum = "50f5f4875c36798e5590894a5176cf8d75e4bc81ec34ced1b9a87609e7d56861"
|
||||
dependencies = [
|
||||
"async-trait",
|
||||
"bytes",
|
||||
"chrono",
|
||||
"flex-error",
|
||||
"futures",
|
||||
"getrandom 0.1.16",
|
||||
@@ -4773,6 +4791,7 @@ dependencies = [
|
||||
"tendermint-config",
|
||||
"tendermint-proto",
|
||||
"thiserror",
|
||||
"time 0.3.5",
|
||||
"tokio",
|
||||
"tracing",
|
||||
"url",
|
||||
@@ -4838,9 +4857,9 @@ dependencies = [
|
||||
|
||||
[[package]]
|
||||
name = "time"
|
||||
version = "0.3.4"
|
||||
version = "0.3.5"
|
||||
source = "registry+https://github.com/rust-lang/crates.io-index"
|
||||
checksum = "99beeb0daeac2bd1e86ac2c21caddecb244b39a093594da1a661ec2060c7aedd"
|
||||
checksum = "41effe7cfa8af36f439fac33861b66b049edc6f9a32331e2312660529c1c24ad"
|
||||
dependencies = [
|
||||
"libc",
|
||||
"time-macros",
|
||||
@@ -4854,11 +4873,10 @@ checksum = "25eb0ca3468fc0acc11828786797f6ef9aa1555e4a211a60d64cc8e4d1be47d6"
|
||||
|
||||
[[package]]
|
||||
name = "tokio"
|
||||
version = "1.13.0"
|
||||
version = "1.15.0"
|
||||
source = "registry+https://github.com/rust-lang/crates.io-index"
|
||||
checksum = "588b2d10a336da58d877567cd8fb8a14b463e2104910f8132cd054b4b96e29ee"
|
||||
checksum = "fbbf1c778ec206785635ce8ad57fe52b3009ae9e0c9f574a728f3049d3e55838"
|
||||
dependencies = [
|
||||
"autocfg 1.0.1",
|
||||
"bytes",
|
||||
"libc",
|
||||
"memchr",
|
||||
@@ -4871,9 +4889,9 @@ dependencies = [
|
||||
|
||||
[[package]]
|
||||
name = "tokio-macros"
|
||||
version = "1.5.1"
|
||||
version = "1.7.0"
|
||||
source = "registry+https://github.com/rust-lang/crates.io-index"
|
||||
checksum = "114383b041aa6212c579467afa0075fbbdd0718de036100bc0ba7961d8cb9095"
|
||||
checksum = "b557f72f448c511a979e2564e55d74e6c4432fc96ff4f6241bc6bded342643b7"
|
||||
dependencies = [
|
||||
"proc-macro2",
|
||||
"quote",
|
||||
@@ -4973,36 +4991,22 @@ dependencies = [
|
||||
"tracing-core",
|
||||
]
|
||||
|
||||
[[package]]
|
||||
name = "tracing-serde"
|
||||
version = "0.1.2"
|
||||
source = "registry+https://github.com/rust-lang/crates.io-index"
|
||||
checksum = "fb65ea441fbb84f9f6748fd496cf7f63ec9af5bca94dd86456978d055e8eb28b"
|
||||
dependencies = [
|
||||
"serde",
|
||||
"tracing-core",
|
||||
]
|
||||
|
||||
[[package]]
|
||||
name = "tracing-subscriber"
|
||||
version = "0.2.25"
|
||||
version = "0.3.3"
|
||||
source = "registry+https://github.com/rust-lang/crates.io-index"
|
||||
checksum = "0e0d2eaa99c3c2e41547cfa109e910a68ea03823cccad4a0525dcbc9b01e8c71"
|
||||
checksum = "245da694cc7fc4729f3f418b304cb57789f1bed2a78c575407ab8a23f53cb4d3"
|
||||
dependencies = [
|
||||
"ansi_term",
|
||||
"chrono",
|
||||
"lazy_static",
|
||||
"matchers",
|
||||
"regex",
|
||||
"serde",
|
||||
"serde_json",
|
||||
"sharded-slab",
|
||||
"smallvec 1.7.0",
|
||||
"thread_local",
|
||||
"tracing",
|
||||
"tracing-core",
|
||||
"tracing-log",
|
||||
"tracing-serde",
|
||||
]
|
||||
|
||||
[[package]]
|
||||
|
||||
@@ -26,6 +26,7 @@ thiserror = "1.0"
|
||||
tendermint-rpc = "0.23.0"
|
||||
url = "2.0"
|
||||
rand = "0.6.5"
|
||||
eyre = "0.6.5"
|
||||
|
||||
|
||||
cosmrs = { git = "https://github.com/cosmos/cosmos-rust", rev="e5a1872083abb3d88fa62dda966e7f5408deba58", features = ["rpc", "bip32", "cosmwasm"] }
|
||||
|
||||
@@ -1,5 +1,6 @@
|
||||
// This should be moved out of the wallet, and used as a primary coin type throughout the codebase
|
||||
|
||||
use crate::error::BackendError;
|
||||
use ::config::defaults::DENOM;
|
||||
use cosmrs::Decimal;
|
||||
use cosmrs::Denom as CosmosDenom;
|
||||
@@ -12,8 +13,6 @@ use std::ops::{Add, Sub};
|
||||
use std::str::FromStr;
|
||||
use validator_client::nymd::{CosmosCoin, GasPrice};
|
||||
|
||||
use crate::format_err;
|
||||
|
||||
#[cfg_attr(test, derive(ts_rs::TS))]
|
||||
#[derive(Serialize, Deserialize, Clone, PartialEq, Debug)]
|
||||
pub enum Denom {
|
||||
@@ -33,19 +32,16 @@ impl fmt::Display for Denom {
|
||||
}
|
||||
|
||||
impl FromStr for Denom {
|
||||
type Err = String;
|
||||
type Err = BackendError;
|
||||
|
||||
fn from_str(s: &str) -> Result<Denom, String> {
|
||||
fn from_str(s: &str) -> Result<Denom, BackendError> {
|
||||
let s = s.to_lowercase();
|
||||
if s == DENOM.to_lowercase() || s == "minor" {
|
||||
Ok(Denom::Minor)
|
||||
} else if s == DENOM[1..].to_lowercase() || s == "major" {
|
||||
Ok(Denom::Major)
|
||||
} else {
|
||||
Err(format_err!(format!(
|
||||
"{} is not a valid denomination string",
|
||||
s
|
||||
)))
|
||||
Err(BackendError::InvalidDenom(s))
|
||||
}
|
||||
}
|
||||
}
|
||||
@@ -169,9 +165,9 @@ impl Coin {
|
||||
}
|
||||
|
||||
impl TryFrom<Coin> for CosmWasmCoin {
|
||||
type Error = String;
|
||||
type Error = BackendError;
|
||||
|
||||
fn try_from(coin: Coin) -> Result<CosmWasmCoin, String> {
|
||||
fn try_from(coin: Coin) -> Result<CosmWasmCoin, Self::Error> {
|
||||
Ok(CosmWasmCoin::new(
|
||||
Uint128::try_from(coin.amount.as_str()).unwrap().u128(),
|
||||
coin.denom.to_string(),
|
||||
@@ -180,15 +176,15 @@ impl TryFrom<Coin> for CosmWasmCoin {
|
||||
}
|
||||
|
||||
impl TryFrom<Coin> for CosmosCoin {
|
||||
type Error = String;
|
||||
type Error = BackendError;
|
||||
|
||||
fn try_from(coin: Coin) -> Result<CosmosCoin, String> {
|
||||
fn try_from(coin: Coin) -> Result<CosmosCoin, BackendError> {
|
||||
match Decimal::from_str(&coin.amount) {
|
||||
Ok(d) => Ok(CosmosCoin {
|
||||
amount: d,
|
||||
denom: CosmosDenom::from_str(&coin.denom.to_string()).unwrap(),
|
||||
denom: CosmosDenom::from_str(&coin.denom.to_string())?,
|
||||
}),
|
||||
Err(e) => Err(format_err!(e)),
|
||||
Err(e) => Err(e.into()),
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
@@ -1,21 +1,47 @@
|
||||
use serde::{Serialize, Serializer};
|
||||
use thiserror::Error;
|
||||
use validator_client::nymd::error::NymdError;
|
||||
|
||||
#[derive(Error, Debug)]
|
||||
pub enum BackendError {
|
||||
#[error("Error parsing bip39 mnemonic")]
|
||||
#[error("{source}")]
|
||||
Bip39Error {
|
||||
#[from]
|
||||
source: bip39::Error,
|
||||
},
|
||||
#[error("Error parsing into tendermint Url")]
|
||||
#[error("{source}")]
|
||||
TendermintError {
|
||||
#[from]
|
||||
source: tendermint_rpc::Error,
|
||||
},
|
||||
#[error("Error getting balances")]
|
||||
#[error("{source}")]
|
||||
NymdError {
|
||||
#[from]
|
||||
source: NymdError,
|
||||
},
|
||||
#[error("{source}")]
|
||||
CosmwasmStd {
|
||||
#[from]
|
||||
source: cosmwasm_std::StdError,
|
||||
},
|
||||
#[error("{source}")]
|
||||
ErrorReport {
|
||||
#[from]
|
||||
source: eyre::Report,
|
||||
},
|
||||
#[error("Client has not been initialized yet, connect with mnemonic to initialize")]
|
||||
ClientNotInitialized,
|
||||
#[error("No balance available for address {0}")]
|
||||
NoBalance(String),
|
||||
#[error("{0} is not a valid denomination string")]
|
||||
InvalidDenom(String),
|
||||
}
|
||||
|
||||
impl Serialize for BackendError {
|
||||
fn serialize<S>(&self, serializer: S) -> Result<S::Ok, S::Error>
|
||||
where
|
||||
S: Serializer,
|
||||
{
|
||||
serializer.serialize_str(&self.to_string())
|
||||
}
|
||||
}
|
||||
|
||||
@@ -7,7 +7,7 @@ use mixnet_contract::{Gateway, MixNode};
|
||||
use std::sync::Arc;
|
||||
use tauri::Menu;
|
||||
use tokio::sync::RwLock;
|
||||
use validator_client::nymd::fee_helpers::Operation;
|
||||
use validator_client::nymd::fee::helpers::Operation;
|
||||
|
||||
mod coin;
|
||||
mod config;
|
||||
@@ -18,47 +18,50 @@ mod state;
|
||||
mod utils;
|
||||
|
||||
use crate::menu::AddDefaultSubmenus;
|
||||
use crate::operations::account::*;
|
||||
use crate::operations::admin::*;
|
||||
use crate::operations::bond::*;
|
||||
use crate::operations::delegate::*;
|
||||
use crate::operations::send::*;
|
||||
use crate::utils::*;
|
||||
use crate::operations::mixnet;
|
||||
use crate::operations::vesting;
|
||||
|
||||
use crate::state::State;
|
||||
|
||||
#[cfg(test)]
|
||||
use crate::coin::{Coin, Denom};
|
||||
|
||||
#[macro_export]
|
||||
macro_rules! format_err {
|
||||
($e:expr) => {
|
||||
format!("line {}: {}", line!(), $e)
|
||||
};
|
||||
}
|
||||
|
||||
fn main() {
|
||||
tauri::Builder::default()
|
||||
.manage(Arc::new(RwLock::new(State::default())))
|
||||
.invoke_handler(tauri::generate_handler![
|
||||
connect_with_mnemonic,
|
||||
get_balance,
|
||||
minor_to_major,
|
||||
major_to_minor,
|
||||
owns_gateway,
|
||||
owns_mixnode,
|
||||
bond_mixnode,
|
||||
unbond_mixnode,
|
||||
bond_gateway,
|
||||
unbond_gateway,
|
||||
delegate_to_mixnode,
|
||||
undelegate_from_mixnode,
|
||||
send,
|
||||
create_new_account,
|
||||
get_fee,
|
||||
get_contract_settings,
|
||||
update_contract_settings,
|
||||
get_reverse_mix_delegations_paged,
|
||||
mixnet::account::connect_with_mnemonic,
|
||||
mixnet::account::create_new_account,
|
||||
mixnet::account::get_balance,
|
||||
mixnet::admin::get_contract_settings,
|
||||
mixnet::admin::update_contract_settings,
|
||||
mixnet::bond::bond_gateway,
|
||||
mixnet::bond::bond_mixnode,
|
||||
mixnet::bond::unbond_gateway,
|
||||
mixnet::bond::unbond_mixnode,
|
||||
mixnet::bond::mixnode_bond_details,
|
||||
mixnet::bond::gateway_bond_details,
|
||||
mixnet::delegate::delegate_to_mixnode,
|
||||
mixnet::delegate::get_reverse_mix_delegations_paged,
|
||||
mixnet::delegate::undelegate_from_mixnode,
|
||||
mixnet::send::send,
|
||||
utils::get_approximate_fee,
|
||||
utils::major_to_minor,
|
||||
utils::minor_to_major,
|
||||
utils::owns_gateway,
|
||||
utils::owns_mixnode,
|
||||
vesting::bond::vesting_bond_gateway,
|
||||
vesting::bond::vesting_bond_mixnode,
|
||||
vesting::bond::vesting_unbond_gateway,
|
||||
vesting::bond::vesting_unbond_mixnode,
|
||||
vesting::delegate::vesting_delegate_to_mixnode,
|
||||
vesting::delegate::vesting_undelegate_from_mixnode,
|
||||
vesting::queries::locked_coins,
|
||||
vesting::queries::spendable_coins,
|
||||
vesting::queries::vesting_coins,
|
||||
vesting::queries::vested_coins,
|
||||
vesting::queries::vesting_start_time,
|
||||
vesting::queries::vesting_end_time,
|
||||
vesting::queries::original_vesting,
|
||||
vesting::queries::delegated_free,
|
||||
vesting::queries::delegated_vesting,
|
||||
])
|
||||
.menu(Menu::new().add_default_app_submenu_if_macos())
|
||||
.run(tauri::generate_context!())
|
||||
@@ -69,15 +72,15 @@ fn main() {
|
||||
mod test {
|
||||
ts_rs::export! {
|
||||
mixnet_contract::MixNode => "../src/types/rust/mixnode.ts",
|
||||
crate::Coin => "../src/types/rust/coin.ts",
|
||||
crate::Balance => "../src/types/rust/balance.ts",
|
||||
crate::coin::Coin => "../src/types/rust/coin.ts",
|
||||
crate::mixnet::account::Balance => "../src/types/rust/balance.ts",
|
||||
mixnet_contract::Gateway => "../src/types/rust/gateway.ts",
|
||||
crate::TauriTxResult => "../src/types/rust/tauritxresult.ts",
|
||||
crate::TransactionDetails => "../src/types/rust/transactiondetails.ts",
|
||||
validator_client::nymd::fee_helpers::Operation => "../src/types/rust/operation.ts",
|
||||
crate::Denom => "../src/types/rust/denom.ts",
|
||||
crate::DelegationResult => "../src/types/rust/delegationresult.ts",
|
||||
crate::Account => "../src/types/rust/account.ts",
|
||||
crate::TauriContractStateParams => "../src/types/rust/stateparams.ts"
|
||||
crate::mixnet::send::TauriTxResult => "../src/types/rust/tauritxresult.ts",
|
||||
crate::mixnet::send::TransactionDetails => "../src/types/rust/transactiondetails.ts",
|
||||
validator_client::nymd::fee::helpers::Operation => "../src/types/rust/operation.ts",
|
||||
crate::coin::Denom => "../src/types/rust/denom.ts",
|
||||
crate::utils::DelegationResult => "../src/types/rust/delegationresult.ts",
|
||||
crate::mixnet::account::Account => "../src/types/rust/account.ts",
|
||||
crate::mixnet::admin::TauriContractStateParams => "../src/types/rust/stateparams.ts"
|
||||
}
|
||||
}
|
||||
|
||||
@@ -1,66 +0,0 @@
|
||||
use crate::coin::Coin;
|
||||
use crate::format_err;
|
||||
use crate::state::State;
|
||||
use crate::{Gateway, MixNode};
|
||||
use cosmwasm_std::Coin as CosmWasmCoin;
|
||||
use std::convert::TryInto;
|
||||
use std::sync::Arc;
|
||||
use tokio::sync::RwLock;
|
||||
|
||||
#[tauri::command]
|
||||
pub async fn bond_gateway(
|
||||
gateway: Gateway,
|
||||
pledge: Coin,
|
||||
owner_signature: String,
|
||||
state: tauri::State<'_, Arc<RwLock<State>>>,
|
||||
) -> Result<(), String> {
|
||||
let r_state = state.read().await;
|
||||
let pledge: CosmWasmCoin = match pledge.try_into() {
|
||||
Ok(b) => b,
|
||||
Err(e) => return Err(format_err!(e)),
|
||||
};
|
||||
let client = r_state.client()?;
|
||||
match client.bond_gateway(gateway, owner_signature, pledge).await {
|
||||
Ok(_result) => Ok(()),
|
||||
Err(e) => Err(format_err!(e)),
|
||||
}
|
||||
}
|
||||
|
||||
#[tauri::command]
|
||||
pub async fn unbond_gateway(state: tauri::State<'_, Arc<RwLock<State>>>) -> Result<(), String> {
|
||||
let r_state = state.read().await;
|
||||
let client = r_state.client()?;
|
||||
match client.unbond_gateway().await {
|
||||
Ok(_result) => Ok(()),
|
||||
Err(e) => Err(format_err!(e)),
|
||||
}
|
||||
}
|
||||
|
||||
#[tauri::command]
|
||||
pub async fn unbond_mixnode(state: tauri::State<'_, Arc<RwLock<State>>>) -> Result<(), String> {
|
||||
let r_state = state.read().await;
|
||||
let client = r_state.client()?;
|
||||
match client.unbond_mixnode().await {
|
||||
Ok(_result) => Ok(()),
|
||||
Err(e) => Err(format_err!(e)),
|
||||
}
|
||||
}
|
||||
|
||||
#[tauri::command]
|
||||
pub async fn bond_mixnode(
|
||||
mixnode: MixNode,
|
||||
owner_signature: String,
|
||||
pledge: Coin,
|
||||
state: tauri::State<'_, Arc<RwLock<State>>>,
|
||||
) -> Result<(), String> {
|
||||
let r_state = state.read().await;
|
||||
let pledge: CosmWasmCoin = match pledge.try_into() {
|
||||
Ok(b) => b,
|
||||
Err(e) => return Err(format_err!(e)),
|
||||
};
|
||||
let client = r_state.client()?;
|
||||
match client.bond_mixnode(mixnode, owner_signature, pledge).await {
|
||||
Ok(_result) => Ok(()),
|
||||
Err(e) => Err(format_err!(e)),
|
||||
}
|
||||
}
|
||||
@@ -1,68 +0,0 @@
|
||||
use crate::coin::Coin;
|
||||
use crate::format_err;
|
||||
use crate::state::State;
|
||||
use cosmwasm_std::Coin as CosmWasmCoin;
|
||||
use mixnet_contract::PagedDelegatorDelegationsResponse;
|
||||
use serde::{Deserialize, Serialize};
|
||||
use std::convert::TryInto;
|
||||
use std::sync::Arc;
|
||||
use tokio::sync::RwLock;
|
||||
|
||||
#[cfg_attr(test, derive(ts_rs::TS))]
|
||||
#[derive(Serialize, Deserialize)]
|
||||
pub struct DelegationResult {
|
||||
source_address: String,
|
||||
target_address: String,
|
||||
amount: Option<Coin>,
|
||||
}
|
||||
|
||||
#[tauri::command]
|
||||
pub async fn delegate_to_mixnode(
|
||||
identity: &str,
|
||||
amount: Coin,
|
||||
state: tauri::State<'_, Arc<RwLock<State>>>,
|
||||
) -> Result<DelegationResult, String> {
|
||||
let r_state = state.read().await;
|
||||
let delegation: CosmWasmCoin = match amount.try_into() {
|
||||
Ok(b) => b,
|
||||
Err(e) => return Err(format_err!(e)),
|
||||
};
|
||||
let client = r_state.client()?;
|
||||
match client.delegate_to_mixnode(identity, &delegation).await {
|
||||
Ok(_result) => Ok(DelegationResult {
|
||||
source_address: client.address().to_string(),
|
||||
target_address: identity.to_string(),
|
||||
amount: Some(delegation.into()),
|
||||
}),
|
||||
Err(e) => Err(format_err!(e)),
|
||||
}
|
||||
}
|
||||
|
||||
#[tauri::command]
|
||||
pub async fn undelegate_from_mixnode(
|
||||
identity: &str,
|
||||
state: tauri::State<'_, Arc<RwLock<State>>>,
|
||||
) -> Result<DelegationResult, String> {
|
||||
let r_state = state.read().await;
|
||||
let client = r_state.client()?;
|
||||
match client.remove_mixnode_delegation(identity).await {
|
||||
Ok(_result) => Ok(DelegationResult {
|
||||
source_address: client.address().to_string(),
|
||||
target_address: identity.to_string(),
|
||||
amount: None,
|
||||
}),
|
||||
Err(e) => Err(format_err!(e)),
|
||||
}
|
||||
}
|
||||
|
||||
#[tauri::command]
|
||||
pub async fn get_reverse_mix_delegations_paged(
|
||||
state: tauri::State<'_, Arc<RwLock<State>>>,
|
||||
) -> Result<PagedDelegatorDelegationsResponse, String> {
|
||||
let r_state = state.read().await;
|
||||
let client = r_state.client()?;
|
||||
client
|
||||
.get_delegator_delegations_paged(client.address().to_string(), None, None)
|
||||
.await
|
||||
.map_err(|err| format_err!(err))
|
||||
}
|
||||
+17
-27
@@ -1,7 +1,7 @@
|
||||
use crate::client;
|
||||
use crate::coin::{Coin, Denom};
|
||||
use crate::config::Config;
|
||||
use crate::error::BackendError;
|
||||
use crate::format_err;
|
||||
use crate::state::State;
|
||||
use bip39::{Language, Mnemonic};
|
||||
use serde::{Deserialize, Serialize};
|
||||
@@ -30,26 +30,16 @@ pub struct Balance {
|
||||
pub async fn connect_with_mnemonic(
|
||||
mnemonic: String,
|
||||
state: tauri::State<'_, Arc<RwLock<State>>>,
|
||||
) -> Result<Account, String> {
|
||||
let mnemonic = match Mnemonic::from_str(&mnemonic) {
|
||||
Ok(mnemonic) => mnemonic,
|
||||
Err(e) => return Err(BackendError::from(e).to_string()),
|
||||
};
|
||||
let client;
|
||||
{
|
||||
) -> Result<Account, BackendError> {
|
||||
let mnemonic = Mnemonic::from_str(&mnemonic)?;
|
||||
let client = {
|
||||
let r_state = state.read().await;
|
||||
client = _connect_with_mnemonic(mnemonic, &r_state.config());
|
||||
}
|
||||
_connect_with_mnemonic(mnemonic, &r_state.config())
|
||||
};
|
||||
|
||||
let contract_address = match client.mixnet_contract_address() {
|
||||
Ok(address) => address.to_string(),
|
||||
Err(e) => return Err(format_err!(e)),
|
||||
};
|
||||
let contract_address = client.mixnet_contract_address()?.to_string();
|
||||
let client_address = client.address().to_string();
|
||||
let denom = match client.denom() {
|
||||
Ok(denom) => denom,
|
||||
Err(e) => return Err(format_err!(e)),
|
||||
};
|
||||
let denom = client.denom()?;
|
||||
|
||||
let account = Account {
|
||||
contract_address,
|
||||
@@ -65,10 +55,10 @@ pub async fn connect_with_mnemonic(
|
||||
}
|
||||
|
||||
#[tauri::command]
|
||||
pub async fn get_balance(state: tauri::State<'_, Arc<RwLock<State>>>) -> Result<Balance, String> {
|
||||
let r_state = state.read().await;
|
||||
let client = r_state.client()?;
|
||||
match client.get_balance(client.address()).await {
|
||||
pub async fn get_balance(
|
||||
state: tauri::State<'_, Arc<RwLock<State>>>,
|
||||
) -> Result<Balance, BackendError> {
|
||||
match client!(state).get_balance(client!(state).address()).await {
|
||||
Ok(Some(coin)) => {
|
||||
let coin = Coin::new(
|
||||
&coin.amount.to_string(),
|
||||
@@ -79,18 +69,17 @@ pub async fn get_balance(state: tauri::State<'_, Arc<RwLock<State>>>) -> Result<
|
||||
printable_balance: coin.to_major().to_string(),
|
||||
})
|
||||
}
|
||||
Ok(None) => Err(format!(
|
||||
"No balance available for address {}",
|
||||
client.address()
|
||||
Ok(None) => Err(BackendError::NoBalance(
|
||||
client!(state).address().to_string(),
|
||||
)),
|
||||
Err(e) => Err(BackendError::from(e).to_string()),
|
||||
Err(e) => Err(BackendError::from(e)),
|
||||
}
|
||||
}
|
||||
|
||||
#[tauri::command]
|
||||
pub async fn create_new_account(
|
||||
state: tauri::State<'_, Arc<RwLock<State>>>,
|
||||
) -> Result<Account, String> {
|
||||
) -> Result<Account, BackendError> {
|
||||
let rand_mnemonic = random_mnemonic();
|
||||
let mut client = connect_with_mnemonic(rand_mnemonic.to_string(), state).await?;
|
||||
client.mnemonic = Some(rand_mnemonic.to_string());
|
||||
@@ -108,6 +97,7 @@ fn _connect_with_mnemonic(mnemonic: Mnemonic, config: &Config) -> NymdClient<Sig
|
||||
Some(AccountId::from_str(&config.get_mixnet_contract_address()).unwrap()),
|
||||
None,
|
||||
mnemonic,
|
||||
None,
|
||||
) {
|
||||
Ok(client) => client,
|
||||
Err(e) => panic!("{}", e),
|
||||
+13
-22
@@ -1,4 +1,5 @@
|
||||
use crate::format_err;
|
||||
use crate::client;
|
||||
use crate::error::BackendError;
|
||||
use crate::state::State;
|
||||
use cosmwasm_std::Uint128;
|
||||
use mixnet_contract::ContractStateParams;
|
||||
@@ -14,6 +15,7 @@ pub struct TauriContractStateParams {
|
||||
minimum_gateway_pledge: String,
|
||||
mixnode_rewarded_set_size: u32,
|
||||
mixnode_active_set_size: u32,
|
||||
active_set_work_factor: u8,
|
||||
}
|
||||
|
||||
impl From<ContractStateParams> for TauriContractStateParams {
|
||||
@@ -23,12 +25,13 @@ impl From<ContractStateParams> for TauriContractStateParams {
|
||||
minimum_gateway_pledge: p.minimum_gateway_pledge.to_string(),
|
||||
mixnode_rewarded_set_size: p.mixnode_rewarded_set_size,
|
||||
mixnode_active_set_size: p.mixnode_active_set_size,
|
||||
active_set_work_factor: p.active_set_work_factor,
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
impl TryFrom<TauriContractStateParams> for ContractStateParams {
|
||||
type Error = Box<dyn std::error::Error>;
|
||||
type Error = BackendError;
|
||||
|
||||
fn try_from(p: TauriContractStateParams) -> Result<ContractStateParams, Self::Error> {
|
||||
Ok(ContractStateParams {
|
||||
@@ -36,6 +39,7 @@ impl TryFrom<TauriContractStateParams> for ContractStateParams {
|
||||
minimum_gateway_pledge: Uint128::try_from(p.minimum_gateway_pledge.as_str())?,
|
||||
mixnode_rewarded_set_size: p.mixnode_rewarded_set_size,
|
||||
mixnode_active_set_size: p.mixnode_active_set_size,
|
||||
active_set_work_factor: p.active_set_work_factor,
|
||||
})
|
||||
}
|
||||
}
|
||||
@@ -43,31 +47,18 @@ impl TryFrom<TauriContractStateParams> for ContractStateParams {
|
||||
#[tauri::command]
|
||||
pub async fn get_contract_settings(
|
||||
state: tauri::State<'_, Arc<RwLock<State>>>,
|
||||
) -> Result<TauriContractStateParams, String> {
|
||||
let r_state = state.read().await;
|
||||
let client = r_state.client()?;
|
||||
match client.get_contract_settings().await {
|
||||
Ok(params) => Ok(params.into()),
|
||||
Err(e) => Err(format_err!(e)),
|
||||
}
|
||||
) -> Result<TauriContractStateParams, BackendError> {
|
||||
Ok(client!(state).get_contract_settings().await?.into())
|
||||
}
|
||||
|
||||
#[tauri::command]
|
||||
pub async fn update_contract_settings(
|
||||
params: TauriContractStateParams,
|
||||
state: tauri::State<'_, Arc<RwLock<State>>>,
|
||||
) -> Result<TauriContractStateParams, String> {
|
||||
let r_state = state.read().await;
|
||||
let client = r_state.client()?;
|
||||
let mixnet_contract_settings_params: ContractStateParams = match params.try_into() {
|
||||
Ok(mixnet_contract_settings_params) => mixnet_contract_settings_params,
|
||||
Err(e) => return Err(format_err!(e)),
|
||||
};
|
||||
match client
|
||||
) -> Result<TauriContractStateParams, BackendError> {
|
||||
let mixnet_contract_settings_params: ContractStateParams = params.try_into()?;
|
||||
client!(state)
|
||||
.update_contract_settings(mixnet_contract_settings_params.clone())
|
||||
.await
|
||||
{
|
||||
Ok(_) => Ok(mixnet_contract_settings_params.into()),
|
||||
Err(e) => Err(format_err!(e)),
|
||||
}
|
||||
.await?;
|
||||
Ok(mixnet_contract_settings_params.into())
|
||||
}
|
||||
@@ -0,0 +1,71 @@
|
||||
use crate::client;
|
||||
use crate::coin::Coin;
|
||||
use crate::error::BackendError;
|
||||
use crate::state::State;
|
||||
use crate::{Gateway, MixNode};
|
||||
use mixnet_contract::{GatewayBond, MixNodeBond};
|
||||
use std::convert::TryInto;
|
||||
use std::sync::Arc;
|
||||
use tokio::sync::RwLock;
|
||||
|
||||
#[tauri::command]
|
||||
pub async fn bond_gateway(
|
||||
gateway: Gateway,
|
||||
pledge: Coin,
|
||||
owner_signature: String,
|
||||
state: tauri::State<'_, Arc<RwLock<State>>>,
|
||||
) -> Result<(), BackendError> {
|
||||
client!(state)
|
||||
.bond_gateway(gateway, owner_signature, pledge.try_into()?)
|
||||
.await?;
|
||||
Ok(())
|
||||
}
|
||||
|
||||
#[tauri::command]
|
||||
pub async fn unbond_gateway(
|
||||
state: tauri::State<'_, Arc<RwLock<State>>>,
|
||||
) -> Result<(), BackendError> {
|
||||
client!(state).unbond_gateway().await?;
|
||||
Ok(())
|
||||
}
|
||||
|
||||
#[tauri::command]
|
||||
pub async fn unbond_mixnode(
|
||||
state: tauri::State<'_, Arc<RwLock<State>>>,
|
||||
) -> Result<(), BackendError> {
|
||||
client!(state).unbond_mixnode().await?;
|
||||
Ok(())
|
||||
}
|
||||
|
||||
#[tauri::command]
|
||||
pub async fn bond_mixnode(
|
||||
mixnode: MixNode,
|
||||
owner_signature: String,
|
||||
pledge: Coin,
|
||||
state: tauri::State<'_, Arc<RwLock<State>>>,
|
||||
) -> Result<(), BackendError> {
|
||||
client!(state)
|
||||
.bond_mixnode(mixnode, owner_signature, pledge.try_into()?)
|
||||
.await?;
|
||||
Ok(())
|
||||
}
|
||||
|
||||
#[tauri::command]
|
||||
pub async fn mixnode_bond_details(
|
||||
state: tauri::State<'_, Arc<RwLock<State>>>,
|
||||
) -> Result<Option<MixNodeBond>, BackendError> {
|
||||
let guard = state.read().await;
|
||||
let client = guard.client()?;
|
||||
let bond = client.owns_mixnode(client.address()).await?;
|
||||
Ok(bond)
|
||||
}
|
||||
|
||||
#[tauri::command]
|
||||
pub async fn gateway_bond_details(
|
||||
state: tauri::State<'_, Arc<RwLock<State>>>,
|
||||
) -> Result<Option<GatewayBond>, BackendError> {
|
||||
let guard = state.read().await;
|
||||
let client = guard.client()?;
|
||||
let bond = client.owns_gateway(client.address()).await?;
|
||||
Ok(bond)
|
||||
}
|
||||
@@ -0,0 +1,51 @@
|
||||
use crate::client;
|
||||
use crate::coin::Coin;
|
||||
use crate::error::BackendError;
|
||||
use crate::state::State;
|
||||
use crate::utils::DelegationResult;
|
||||
use cosmwasm_std::Coin as CosmWasmCoin;
|
||||
use mixnet_contract::PagedDelegatorDelegationsResponse;
|
||||
use std::convert::TryInto;
|
||||
use std::sync::Arc;
|
||||
use tokio::sync::RwLock;
|
||||
|
||||
#[tauri::command]
|
||||
pub async fn delegate_to_mixnode(
|
||||
identity: &str,
|
||||
amount: Coin,
|
||||
state: tauri::State<'_, Arc<RwLock<State>>>,
|
||||
) -> Result<DelegationResult, BackendError> {
|
||||
let delegation: CosmWasmCoin = amount.try_into()?;
|
||||
client!(state)
|
||||
.delegate_to_mixnode(identity, &delegation)
|
||||
.await?;
|
||||
Ok(DelegationResult::new(
|
||||
&client!(state).address().to_string(),
|
||||
identity,
|
||||
Some(delegation.into()),
|
||||
))
|
||||
}
|
||||
|
||||
#[tauri::command]
|
||||
pub async fn undelegate_from_mixnode(
|
||||
identity: &str,
|
||||
state: tauri::State<'_, Arc<RwLock<State>>>,
|
||||
) -> Result<DelegationResult, BackendError> {
|
||||
client!(state).remove_mixnode_delegation(identity).await?;
|
||||
Ok(DelegationResult::new(
|
||||
&client!(state).address().to_string(),
|
||||
identity,
|
||||
None,
|
||||
))
|
||||
}
|
||||
|
||||
#[tauri::command]
|
||||
pub async fn get_reverse_mix_delegations_paged(
|
||||
state: tauri::State<'_, Arc<RwLock<State>>>,
|
||||
) -> Result<PagedDelegatorDelegationsResponse, BackendError> {
|
||||
Ok(
|
||||
client!(state)
|
||||
.get_delegator_delegations_paged(client!(state).address().to_string(), None, None)
|
||||
.await?,
|
||||
)
|
||||
}
|
||||
@@ -0,0 +1,5 @@
|
||||
pub mod account;
|
||||
pub mod admin;
|
||||
pub mod bond;
|
||||
pub mod delegate;
|
||||
pub mod send;
|
||||
+16
-23
@@ -1,5 +1,6 @@
|
||||
use crate::client;
|
||||
use crate::coin::Coin;
|
||||
use crate::format_err;
|
||||
use crate::error::BackendError;
|
||||
use crate::state::State;
|
||||
use serde::{Deserialize, Serialize};
|
||||
use std::convert::TryInto;
|
||||
@@ -47,26 +48,18 @@ pub async fn send(
|
||||
amount: Coin,
|
||||
memo: String,
|
||||
state: tauri::State<'_, Arc<RwLock<State>>>,
|
||||
) -> Result<TauriTxResult, String> {
|
||||
let address = match AccountId::from_str(address) {
|
||||
Ok(addy) => addy,
|
||||
Err(e) => return Err(format_err!(e)),
|
||||
};
|
||||
let cosmos_amount: CosmosCoin = match amount.clone().try_into() {
|
||||
Ok(b) => b,
|
||||
Err(e) => return Err(format_err!(e)),
|
||||
};
|
||||
let r_state = state.read().await;
|
||||
let client = r_state.client()?;
|
||||
match client.send(&address, vec![cosmos_amount], memo).await {
|
||||
Ok(result) => Ok(TauriTxResult::new(
|
||||
result,
|
||||
TransactionDetails {
|
||||
from_address: client.address().to_string(),
|
||||
to_address: address.to_string(),
|
||||
amount,
|
||||
},
|
||||
)),
|
||||
Err(e) => Err(format_err!(e)),
|
||||
}
|
||||
) -> Result<TauriTxResult, BackendError> {
|
||||
let address = AccountId::from_str(address)?;
|
||||
let cosmos_amount: CosmosCoin = amount.clone().try_into()?;
|
||||
let result = client!(state)
|
||||
.send(&address, vec![cosmos_amount], memo)
|
||||
.await?;
|
||||
Ok(TauriTxResult::new(
|
||||
result,
|
||||
TransactionDetails {
|
||||
from_address: client!(state).address().to_string(),
|
||||
to_address: address.to_string(),
|
||||
amount,
|
||||
},
|
||||
))
|
||||
}
|
||||
@@ -1,5 +1,2 @@
|
||||
pub mod account;
|
||||
pub mod admin;
|
||||
pub mod bond;
|
||||
pub mod delegate;
|
||||
pub mod send;
|
||||
pub mod mixnet;
|
||||
pub mod vesting;
|
||||
|
||||
@@ -0,0 +1,51 @@
|
||||
use crate::client;
|
||||
use crate::coin::Coin;
|
||||
use crate::error::BackendError;
|
||||
use crate::state::State;
|
||||
use crate::{Gateway, MixNode};
|
||||
use std::convert::TryInto;
|
||||
use std::sync::Arc;
|
||||
use tokio::sync::RwLock;
|
||||
use validator_client::nymd::VestingSigningClient;
|
||||
|
||||
#[tauri::command]
|
||||
pub async fn vesting_bond_gateway(
|
||||
gateway: Gateway,
|
||||
pledge: Coin,
|
||||
owner_signature: String,
|
||||
state: tauri::State<'_, Arc<RwLock<State>>>,
|
||||
) -> Result<(), BackendError> {
|
||||
client!(state)
|
||||
.vesting_bond_gateway(gateway, &owner_signature, pledge.try_into()?)
|
||||
.await?;
|
||||
Ok(())
|
||||
}
|
||||
|
||||
#[tauri::command]
|
||||
pub async fn vesting_unbond_gateway(
|
||||
state: tauri::State<'_, Arc<RwLock<State>>>,
|
||||
) -> Result<(), BackendError> {
|
||||
client!(state).vesting_unbond_gateway().await?;
|
||||
Ok(())
|
||||
}
|
||||
|
||||
#[tauri::command]
|
||||
pub async fn vesting_unbond_mixnode(
|
||||
state: tauri::State<'_, Arc<RwLock<State>>>,
|
||||
) -> Result<(), BackendError> {
|
||||
client!(state).vesting_unbond_mixnode().await?;
|
||||
Ok(())
|
||||
}
|
||||
|
||||
#[tauri::command]
|
||||
pub async fn vesting_bond_mixnode(
|
||||
mixnode: MixNode,
|
||||
owner_signature: String,
|
||||
pledge: Coin,
|
||||
state: tauri::State<'_, Arc<RwLock<State>>>,
|
||||
) -> Result<(), BackendError> {
|
||||
client!(state)
|
||||
.vesting_bond_mixnode(mixnode, &owner_signature, pledge.try_into()?)
|
||||
.await?;
|
||||
Ok(())
|
||||
}
|
||||
@@ -0,0 +1,42 @@
|
||||
use crate::client;
|
||||
use crate::coin::Coin;
|
||||
use crate::error::BackendError;
|
||||
use crate::state::State;
|
||||
use crate::utils::DelegationResult;
|
||||
use cosmwasm_std::Coin as CosmWasmCoin;
|
||||
use std::convert::TryInto;
|
||||
use std::sync::Arc;
|
||||
use tokio::sync::RwLock;
|
||||
use validator_client::nymd::VestingSigningClient;
|
||||
|
||||
#[tauri::command]
|
||||
pub async fn vesting_delegate_to_mixnode(
|
||||
identity: &str,
|
||||
amount: Coin,
|
||||
state: tauri::State<'_, Arc<RwLock<State>>>,
|
||||
) -> Result<DelegationResult, BackendError> {
|
||||
let delegation: CosmWasmCoin = amount.try_into()?;
|
||||
client!(state)
|
||||
.vesting_delegate_to_mixnode(identity, &delegation)
|
||||
.await?;
|
||||
Ok(DelegationResult::new(
|
||||
&client!(state).address().to_string(),
|
||||
identity,
|
||||
Some(delegation.into()),
|
||||
))
|
||||
}
|
||||
|
||||
#[tauri::command]
|
||||
pub async fn vesting_undelegate_from_mixnode(
|
||||
identity: &str,
|
||||
state: tauri::State<'_, Arc<RwLock<State>>>,
|
||||
) -> Result<DelegationResult, BackendError> {
|
||||
client!(state)
|
||||
.vesting_undelegate_from_mixnode(identity)
|
||||
.await?;
|
||||
Ok(DelegationResult::new(
|
||||
&client!(state).address().to_string(),
|
||||
identity,
|
||||
None,
|
||||
))
|
||||
}
|
||||
@@ -0,0 +1,3 @@
|
||||
pub mod bond;
|
||||
pub mod delegate;
|
||||
pub mod queries;
|
||||
@@ -0,0 +1,146 @@
|
||||
use crate::client;
|
||||
use crate::coin::Coin;
|
||||
use crate::error::BackendError;
|
||||
use crate::state::State;
|
||||
use cosmwasm_std::Timestamp;
|
||||
use std::sync::Arc;
|
||||
use tokio::sync::RwLock;
|
||||
use validator_client::nymd::VestingQueryClient;
|
||||
|
||||
#[tauri::command]
|
||||
pub async fn locked_coins(
|
||||
address: &str,
|
||||
block_time: Option<u64>,
|
||||
state: tauri::State<'_, Arc<RwLock<State>>>,
|
||||
) -> Result<Coin, BackendError> {
|
||||
Ok(
|
||||
client!(state)
|
||||
.locked_coins(address, block_time.map(Timestamp::from_seconds))
|
||||
.await?
|
||||
.into(),
|
||||
)
|
||||
}
|
||||
|
||||
#[tauri::command]
|
||||
pub async fn spendable_coins(
|
||||
vesting_account_address: &str,
|
||||
block_time: Option<u64>,
|
||||
state: tauri::State<'_, Arc<RwLock<State>>>,
|
||||
) -> Result<Coin, BackendError> {
|
||||
Ok(
|
||||
client!(state)
|
||||
.spendable_coins(
|
||||
vesting_account_address,
|
||||
block_time.map(Timestamp::from_seconds),
|
||||
)
|
||||
.await?
|
||||
.into(),
|
||||
)
|
||||
}
|
||||
|
||||
#[tauri::command]
|
||||
pub async fn vested_coins(
|
||||
vesting_account_address: &str,
|
||||
block_time: Option<u64>,
|
||||
state: tauri::State<'_, Arc<RwLock<State>>>,
|
||||
) -> Result<Coin, BackendError> {
|
||||
Ok(
|
||||
client!(state)
|
||||
.vested_coins(
|
||||
vesting_account_address,
|
||||
block_time.map(Timestamp::from_seconds),
|
||||
)
|
||||
.await?
|
||||
.into(),
|
||||
)
|
||||
}
|
||||
|
||||
#[tauri::command]
|
||||
pub async fn vesting_coins(
|
||||
vesting_account_address: &str,
|
||||
block_time: Option<u64>,
|
||||
state: tauri::State<'_, Arc<RwLock<State>>>,
|
||||
) -> Result<Coin, BackendError> {
|
||||
Ok(
|
||||
client!(state)
|
||||
.vesting_coins(
|
||||
vesting_account_address,
|
||||
block_time.map(Timestamp::from_seconds),
|
||||
)
|
||||
.await?
|
||||
.into(),
|
||||
)
|
||||
}
|
||||
|
||||
#[tauri::command]
|
||||
pub async fn vesting_start_time(
|
||||
vesting_account_address: &str,
|
||||
state: tauri::State<'_, Arc<RwLock<State>>>,
|
||||
) -> Result<u64, BackendError> {
|
||||
Ok(
|
||||
client!(state)
|
||||
.vesting_start_time(vesting_account_address)
|
||||
.await?
|
||||
.seconds(),
|
||||
)
|
||||
}
|
||||
|
||||
#[tauri::command]
|
||||
pub async fn vesting_end_time(
|
||||
vesting_account_address: &str,
|
||||
state: tauri::State<'_, Arc<RwLock<State>>>,
|
||||
) -> Result<u64, BackendError> {
|
||||
Ok(
|
||||
client!(state)
|
||||
.vesting_end_time(vesting_account_address)
|
||||
.await?
|
||||
.seconds(),
|
||||
)
|
||||
}
|
||||
|
||||
#[tauri::command]
|
||||
pub async fn original_vesting(
|
||||
vesting_account_address: &str,
|
||||
state: tauri::State<'_, Arc<RwLock<State>>>,
|
||||
) -> Result<Coin, BackendError> {
|
||||
Ok(
|
||||
client!(state)
|
||||
.original_vesting(vesting_account_address)
|
||||
.await?
|
||||
.into(),
|
||||
)
|
||||
}
|
||||
|
||||
#[tauri::command]
|
||||
pub async fn delegated_free(
|
||||
vesting_account_address: &str,
|
||||
block_time: Option<u64>,
|
||||
state: tauri::State<'_, Arc<RwLock<State>>>,
|
||||
) -> Result<Coin, BackendError> {
|
||||
Ok(
|
||||
client!(state)
|
||||
.delegated_free(
|
||||
vesting_account_address,
|
||||
block_time.map(Timestamp::from_seconds),
|
||||
)
|
||||
.await?
|
||||
.into(),
|
||||
)
|
||||
}
|
||||
|
||||
#[tauri::command]
|
||||
pub async fn delegated_vesting(
|
||||
block_time: Option<u64>,
|
||||
vesting_account_address: &str,
|
||||
state: tauri::State<'_, Arc<RwLock<State>>>,
|
||||
) -> Result<Coin, BackendError> {
|
||||
Ok(
|
||||
client!(state)
|
||||
.delegated_vesting(
|
||||
vesting_account_address,
|
||||
block_time.map(Timestamp::from_seconds),
|
||||
)
|
||||
.await?
|
||||
.into(),
|
||||
)
|
||||
}
|
||||
@@ -1,4 +1,5 @@
|
||||
use crate::config::Config;
|
||||
use crate::error::BackendError;
|
||||
use validator_client::nymd::{NymdClient, SigningNymdClient};
|
||||
|
||||
#[derive(Default)]
|
||||
@@ -8,10 +9,11 @@ pub struct State {
|
||||
}
|
||||
|
||||
impl State {
|
||||
pub fn client(&self) -> Result<&NymdClient<SigningNymdClient>, String> {
|
||||
self.signing_client.as_ref().ok_or_else(|| {
|
||||
"Client has not been initialized yet, connect with mnemonic to initialize".to_string()
|
||||
})
|
||||
pub fn client(&self) -> Result<&NymdClient<SigningNymdClient>, BackendError> {
|
||||
self
|
||||
.signing_client
|
||||
.as_ref()
|
||||
.ok_or(BackendError::ClientNotInitialized)
|
||||
}
|
||||
|
||||
pub fn config(&self) -> Config {
|
||||
@@ -22,3 +24,10 @@ impl State {
|
||||
self.signing_client = Some(signing_client)
|
||||
}
|
||||
}
|
||||
|
||||
#[macro_export]
|
||||
macro_rules! client {
|
||||
($state:ident) => {
|
||||
$state.read().await.client()?
|
||||
};
|
||||
}
|
||||
|
||||
@@ -1,54 +1,77 @@
|
||||
use crate::client;
|
||||
use crate::coin::{Coin, Denom};
|
||||
use crate::format_err;
|
||||
use crate::error::BackendError;
|
||||
use crate::state::State;
|
||||
use crate::Operation;
|
||||
use serde::{Deserialize, Serialize};
|
||||
use std::sync::Arc;
|
||||
use tokio::sync::RwLock;
|
||||
|
||||
#[tauri::command]
|
||||
pub fn major_to_minor(amount: &str) -> Result<Coin, String> {
|
||||
pub fn major_to_minor(amount: &str) -> Coin {
|
||||
let coin = Coin::new(amount, &Denom::Major);
|
||||
Ok(coin.to_minor())
|
||||
coin.to_minor()
|
||||
}
|
||||
|
||||
#[tauri::command]
|
||||
pub fn minor_to_major(amount: &str) -> Result<Coin, String> {
|
||||
pub fn minor_to_major(amount: &str) -> Coin {
|
||||
let coin = Coin::new(amount, &Denom::Minor);
|
||||
Ok(coin.to_major())
|
||||
coin.to_major()
|
||||
}
|
||||
|
||||
#[tauri::command]
|
||||
pub async fn owns_mixnode(state: tauri::State<'_, Arc<RwLock<State>>>) -> Result<bool, String> {
|
||||
let r_state = state.read().await;
|
||||
let client = r_state.client()?;
|
||||
match client.owns_mixnode(client.address()).await {
|
||||
Ok(o) => Ok(o.is_some()),
|
||||
Err(e) => Err(format_err!(e)),
|
||||
}
|
||||
pub async fn owns_mixnode(
|
||||
state: tauri::State<'_, Arc<RwLock<State>>>,
|
||||
) -> Result<bool, BackendError> {
|
||||
Ok(
|
||||
client!(state)
|
||||
.owns_mixnode(client!(state).address())
|
||||
.await?
|
||||
.is_some(),
|
||||
)
|
||||
}
|
||||
|
||||
#[tauri::command]
|
||||
pub async fn owns_gateway(state: tauri::State<'_, Arc<RwLock<State>>>) -> Result<bool, String> {
|
||||
let r_state = state.read().await;
|
||||
let client = r_state.client()?;
|
||||
match client.owns_gateway(client.address()).await {
|
||||
Ok(o) => Ok(o.is_some()),
|
||||
Err(e) => Err(format_err!(e)),
|
||||
}
|
||||
pub async fn owns_gateway(
|
||||
state: tauri::State<'_, Arc<RwLock<State>>>,
|
||||
) -> Result<bool, BackendError> {
|
||||
Ok(
|
||||
client!(state)
|
||||
.owns_gateway(client!(state).address())
|
||||
.await?
|
||||
.is_some(),
|
||||
)
|
||||
}
|
||||
|
||||
// NOTE: this uses OUTDATED defaults that might have no resemblance with the reality
|
||||
// as for the actual transaction, the gas cost is being simulated beforehand
|
||||
#[tauri::command]
|
||||
pub async fn get_fee(
|
||||
pub async fn get_approximate_fee(
|
||||
operation: Operation,
|
||||
state: tauri::State<'_, Arc<RwLock<State>>>,
|
||||
) -> Result<Coin, String> {
|
||||
let r_state = state.read().await;
|
||||
let client = r_state.client()?;
|
||||
let fee = client.get_fee(operation);
|
||||
) -> Result<Coin, BackendError> {
|
||||
let approximate_fee = operation.default_fee(client!(state).gas_price());
|
||||
let mut coin = Coin::new("0", &Denom::Major);
|
||||
for f in fee.amount {
|
||||
for f in approximate_fee.amount {
|
||||
coin = coin + f.into();
|
||||
}
|
||||
|
||||
Ok(coin)
|
||||
}
|
||||
|
||||
#[cfg_attr(test, derive(ts_rs::TS))]
|
||||
#[derive(Serialize, Deserialize)]
|
||||
pub struct DelegationResult {
|
||||
source_address: String,
|
||||
target_address: String,
|
||||
amount: Option<Coin>,
|
||||
}
|
||||
|
||||
impl DelegationResult {
|
||||
pub fn new(source_address: &str, target_address: &str, amount: Option<Coin>) -> DelegationResult {
|
||||
DelegationResult {
|
||||
source_address: source_address.to_string(),
|
||||
target_address: target_address.to_string(),
|
||||
amount,
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
@@ -23,7 +23,10 @@ export const minorToMajor = async (amount: string): Promise<Coin> => await invok
|
||||
|
||||
export const majorToMinor = async (amount: string): Promise<Coin> => await invoke('major_to_minor', { amount })
|
||||
|
||||
export const getGasFee = async (operation: Operation): Promise<Coin> => await invoke('get_fee', { operation })
|
||||
// NOTE: this uses OUTDATED defaults that might have no resemblance with the reality
|
||||
// as for the actual transaction, the gas cost is being simulated beforehand
|
||||
export const getGasFee = async (operation: Operation): Promise<Coin> =>
|
||||
await invoke('get_approximate_fee', { operation })
|
||||
|
||||
export const delegate = async ({
|
||||
type,
|
||||
|
||||
@@ -139,7 +139,7 @@ export const ApiList = () => {
|
||||
<ListItem>
|
||||
<DocEntry
|
||||
function={{
|
||||
name: 'get_fee',
|
||||
name: 'get_approximate_fee',
|
||||
args: [{ name: 'operation', type: 'str' }],
|
||||
}}
|
||||
/>
|
||||
|
||||
@@ -16,7 +16,7 @@ export type Operation =
|
||||
| "BondGatewayOnBehalf"
|
||||
| "UnbondGateway"
|
||||
| "UnbondGatewayOnBehalf"
|
||||
| "UpdateStateParams"
|
||||
| "UpdateContractSettings"
|
||||
| "BeginMixnodeRewarding"
|
||||
| "FinishMixnodeRewarding"
|
||||
| "TrackUnbondGateway"
|
||||
|
||||
@@ -3,4 +3,5 @@ export interface TauriContractStateParams {
|
||||
minimum_gateway_pledge: string;
|
||||
mixnode_rewarded_set_size: number;
|
||||
mixnode_active_set_size: number;
|
||||
active_set_work_factor: number;
|
||||
}
|
||||
@@ -189,7 +189,7 @@ impl PacketPreparer {
|
||||
|
||||
if gateways.into_inner().len() < minimum_full_routes {
|
||||
info!(
|
||||
"Minimal topology is still not offline. Going to check again in {:?}",
|
||||
"Minimal topology is still not online. Going to check again in {:?}",
|
||||
initialisation_backoff
|
||||
);
|
||||
tokio::time::sleep(initialisation_backoff).await;
|
||||
@@ -217,7 +217,7 @@ impl PacketPreparer {
|
||||
}
|
||||
|
||||
info!(
|
||||
"Minimal topology is still not offline. Going to check again in {:?}",
|
||||
"Minimal topology is still not online. Going to check again in {:?}",
|
||||
initialisation_backoff
|
||||
);
|
||||
tokio::time::sleep(initialisation_backoff).await;
|
||||
|
||||
@@ -2,10 +2,7 @@
|
||||
// SPDX-License-Identifier: Apache-2.0
|
||||
|
||||
use crate::config::Config;
|
||||
use crate::rewarding::{
|
||||
error::RewardingError, MixnodeToReward, MIXNODE_REWARD_OP_BASE_GAS_LIMIT,
|
||||
PER_MIXNODE_DELEGATION_GAS_INCREASE, REWARDING_GAS_LIMIT_MULTIPLIER,
|
||||
};
|
||||
use crate::rewarding::{error::RewardingError, MixnodeToReward};
|
||||
use config::defaults::DEFAULT_VALIDATOR_API_PORT;
|
||||
use mixnet_contract::{
|
||||
ContractStateParams, Delegation, ExecuteMsg, GatewayBond, IdentityKey, MixNodeBond,
|
||||
@@ -211,19 +208,6 @@ impl<C> Client<C> {
|
||||
.await
|
||||
}
|
||||
|
||||
async fn estimate_mixnode_reward_fees(&self, nodes: usize, total_delegations: usize) -> Fee {
|
||||
let base_gas_limit = MIXNODE_REWARD_OP_BASE_GAS_LIMIT * nodes as u64
|
||||
+ PER_MIXNODE_DELEGATION_GAS_INCREASE * total_delegations as u64;
|
||||
|
||||
let total_gas_limit = (base_gas_limit as f64 * REWARDING_GAS_LIMIT_MULTIPLIER) as u64;
|
||||
|
||||
self.0
|
||||
.read()
|
||||
.await
|
||||
.nymd
|
||||
.calculate_custom_fee(total_gas_limit)
|
||||
}
|
||||
|
||||
pub(crate) async fn begin_mixnode_rewarding(
|
||||
&self,
|
||||
rewarding_interval_nonce: u32,
|
||||
@@ -269,15 +253,13 @@ impl<C> Client<C> {
|
||||
let further_calls = node.total_delegations / MIXNODE_DELEGATORS_PAGE_LIMIT;
|
||||
|
||||
// start with the base call to reward operator and first page of delegators
|
||||
let fee = self
|
||||
.estimate_mixnode_reward_fees(1, MIXNODE_DELEGATORS_PAGE_LIMIT)
|
||||
.await;
|
||||
let msgs = vec![(node.to_reward_execute_msg(rewarding_interval_nonce), vec![])];
|
||||
let memo = format!(
|
||||
"operator + {} delegators rewarding",
|
||||
MIXNODE_DELEGATORS_PAGE_LIMIT
|
||||
);
|
||||
self.execute_multiple_with_retry(msgs, fee, memo).await?;
|
||||
self.execute_multiple_with_retry(msgs, Default::default(), memo)
|
||||
.await?;
|
||||
|
||||
// reward rest of delegators
|
||||
let mut remaining_delegators = node.total_delegations - MIXNODE_DELEGATORS_PAGE_LIMIT;
|
||||
@@ -287,12 +269,10 @@ impl<C> Client<C> {
|
||||
);
|
||||
for _ in 0..further_calls {
|
||||
let delegators_in_call = remaining_delegators.min(MIXNODE_DELEGATORS_PAGE_LIMIT);
|
||||
let fee = self
|
||||
.estimate_mixnode_reward_fees(1, delegators_in_call)
|
||||
.await;
|
||||
let msgs = vec![delegator_rewarding_msg.clone()];
|
||||
let memo = format!("rewarding another {} delegators", delegators_in_call);
|
||||
self.execute_multiple_with_retry(msgs, fee, memo).await?;
|
||||
self.execute_multiple_with_retry(msgs, Default::default(), memo)
|
||||
.await?;
|
||||
|
||||
remaining_delegators -= MIXNODE_DELEGATORS_PAGE_LIMIT;
|
||||
}
|
||||
@@ -310,16 +290,13 @@ impl<C> Client<C> {
|
||||
{
|
||||
// the fee is a tricky subject here because we don't know exactly how many delegators we missed,
|
||||
// let's aim for the worst case scenario and assume it was the entire page
|
||||
let fee = self
|
||||
.estimate_mixnode_reward_fees(1, MIXNODE_DELEGATORS_PAGE_LIMIT)
|
||||
.await;
|
||||
let delegator_rewarding_msg = (
|
||||
node.to_next_delegator_reward_execute_msg(rewarding_interval_nonce),
|
||||
vec![],
|
||||
);
|
||||
|
||||
let memo = "rewarding delegators".to_string();
|
||||
self.execute_multiple_with_retry(vec![delegator_rewarding_msg], fee, memo)
|
||||
self.execute_multiple_with_retry(vec![delegator_rewarding_msg], Default::default(), memo)
|
||||
.await
|
||||
}
|
||||
|
||||
@@ -331,10 +308,6 @@ impl<C> Client<C> {
|
||||
where
|
||||
C: SigningCosmWasmClient + Sync,
|
||||
{
|
||||
let total_delegations = nodes.iter().map(|node| node.total_delegations).sum();
|
||||
let fee = self
|
||||
.estimate_mixnode_reward_fees(nodes.len(), total_delegations)
|
||||
.await;
|
||||
let msgs: Vec<(ExecuteMsg, _)> = nodes
|
||||
.iter()
|
||||
.map(|node| node.to_reward_execute_msg(rewarding_interval_nonce))
|
||||
@@ -343,7 +316,8 @@ impl<C> Client<C> {
|
||||
|
||||
let memo = format!("rewarding {} mixnodes", msgs.len());
|
||||
|
||||
self.execute_multiple_with_retry(msgs, fee, memo).await
|
||||
self.execute_multiple_with_retry(msgs, Default::default(), memo)
|
||||
.await
|
||||
}
|
||||
|
||||
async fn execute_multiple_with_retry<M>(
|
||||
|
||||
@@ -10,6 +10,7 @@ use crate::storage::models::{
|
||||
FailedMixnodeRewardChunk, PossiblyUnrewardedMixnode, RewardingReport,
|
||||
};
|
||||
use crate::storage::ValidatorApiStorage;
|
||||
use config::defaults::DENOM;
|
||||
use log::{error, info};
|
||||
use mixnet_contract::mixnode::NodeRewardParams;
|
||||
use mixnet_contract::{ExecuteMsg, IdentityKey, RewardingStatus, MIXNODE_DELEGATORS_PAGE_LIMIT};
|
||||
@@ -22,21 +23,15 @@ use validator_client::nymd::SigningNymdClient;
|
||||
pub(crate) mod epoch;
|
||||
pub(crate) mod error;
|
||||
|
||||
// the actual base cost is around 125_000, but let's give ourselves a bit of safety net in case
|
||||
// we introduce some tiny contract changes that would bump that value up
|
||||
pub(crate) const MIXNODE_REWARD_OP_BASE_GAS_LIMIT: u64 = 150_000;
|
||||
|
||||
// For each delegation reward we perform a read and a write is being executed,
|
||||
// which are the most costly parts involved in process. Both of them are ~1000 sdk gas in cost.
|
||||
// However, experimentally it looks like first delegation adds total of additional ~3000 of sdk gas
|
||||
// cost and each subsequent about ~2500.
|
||||
// Therefore, since base cost is not tuned to the bare minimum, let's treat all of delegations as extra
|
||||
// 2750 of sdk gas.
|
||||
pub(crate) const PER_MIXNODE_DELEGATION_GAS_INCREASE: u64 = 2750;
|
||||
|
||||
// Another safety net in case of contract changes,
|
||||
// the calculated total gas limit is going to get multiplied by that value.
|
||||
pub(crate) const REWARDING_GAS_LIMIT_MULTIPLIER: f64 = 1.05;
|
||||
struct EpochRewardParams {
|
||||
reward_pool: u128,
|
||||
circulating_supply: u128,
|
||||
sybil_resistance_percent: u8,
|
||||
rewarded_set_size: u32,
|
||||
active_set_size: u32,
|
||||
period_reward_pool: u128,
|
||||
active_set_work_factor: u8,
|
||||
}
|
||||
|
||||
#[derive(Debug, Clone)]
|
||||
pub(crate) struct MixnodeToReward {
|
||||
@@ -50,7 +45,6 @@ pub(crate) struct MixnodeToReward {
|
||||
}
|
||||
|
||||
impl MixnodeToReward {
|
||||
/// Somewhat clumsy way of feature gatting tokenomics payments. In a tokenomics scenario this will never be None at reward time. We leverage that to Into a different ExecuteMsg variant
|
||||
fn params(&self) -> NodeRewardParams {
|
||||
self.params
|
||||
}
|
||||
@@ -123,6 +117,24 @@ impl Rewarder {
|
||||
}
|
||||
}
|
||||
|
||||
async fn epoch_reward_params(&self) -> Result<EpochRewardParams, RewardingError> {
|
||||
let state = self.nymd_client.get_contract_settings().await?;
|
||||
let reward_pool = self.nymd_client.get_reward_pool().await?;
|
||||
let epoch_reward_percent = self.nymd_client.get_epoch_reward_percent().await?;
|
||||
|
||||
let epoch_reward_params = EpochRewardParams {
|
||||
reward_pool,
|
||||
circulating_supply: self.nymd_client.get_circulating_supply().await?,
|
||||
sybil_resistance_percent: self.nymd_client.get_sybil_resistance_percent().await?,
|
||||
rewarded_set_size: state.mixnode_rewarded_set_size,
|
||||
active_set_size: state.mixnode_active_set_size,
|
||||
period_reward_pool: (reward_pool / 100) * epoch_reward_percent as u128,
|
||||
active_set_work_factor: state.active_set_work_factor,
|
||||
};
|
||||
|
||||
Ok(epoch_reward_params)
|
||||
}
|
||||
|
||||
/// Obtains the current number of delegators that have delegated their stake towards this particular mixnode.
|
||||
///
|
||||
/// # Arguments
|
||||
@@ -158,21 +170,21 @@ impl Rewarder {
|
||||
// and the lack of port data / verloc data will eventually be balanced out anyway
|
||||
// by people hesitating to delegate to nodes without them and thus those nodes disappearing
|
||||
// from the active set (once introduced)
|
||||
let state = self.nymd_client.get_contract_settings().await?;
|
||||
|
||||
let reward_pool = self.nymd_client.get_reward_pool().await?;
|
||||
let circulating_supply = self.nymd_client.get_circulating_supply().await?;
|
||||
let sybil_resistance_percent = self.nymd_client.get_sybil_resistance_percent().await?;
|
||||
let epoch_reward_percent = self.nymd_client.get_epoch_reward_percent().await?;
|
||||
|
||||
// TODO: question to @durch: is k active set or 'rewarded' set?
|
||||
let k = state.mixnode_active_set_size;
|
||||
let period_reward_pool = (reward_pool / 100) * epoch_reward_percent as u128;
|
||||
let epoch_reward_params = self.epoch_reward_params().await?;
|
||||
|
||||
info!("Rewarding pool stats");
|
||||
info!("-- Reward pool: {} unym", reward_pool);
|
||||
info!("---- Epoch reward pool: {} unym", period_reward_pool);
|
||||
info!("-- Circulating supply: {} unym", circulating_supply);
|
||||
info!(
|
||||
"-- Reward pool: {} {}",
|
||||
epoch_reward_params.reward_pool, DENOM
|
||||
);
|
||||
info!(
|
||||
"---- Epoch reward pool: {} {}",
|
||||
epoch_reward_params.period_reward_pool, DENOM
|
||||
);
|
||||
info!(
|
||||
"-- Circulating supply: {} {}",
|
||||
epoch_reward_params.circulating_supply, DENOM
|
||||
);
|
||||
|
||||
// 1. get list of 'rewarded' nodes
|
||||
// 2. for each of them determine their delegator count
|
||||
@@ -187,7 +199,9 @@ impl Rewarder {
|
||||
}
|
||||
|
||||
let mut eligible_nodes = Vec::with_capacity(nodes_with_delegations.len());
|
||||
for (rewarded_node, total_delegations) in nodes_with_delegations {
|
||||
for (i, (rewarded_node, total_delegations)) in
|
||||
nodes_with_delegations.into_iter().enumerate()
|
||||
{
|
||||
let uptime = self
|
||||
.storage
|
||||
.get_average_mixnode_uptime_in_interval(
|
||||
@@ -201,12 +215,16 @@ impl Rewarder {
|
||||
identity: rewarded_node.mix_node.identity_key,
|
||||
total_delegations,
|
||||
params: NodeRewardParams::new(
|
||||
period_reward_pool,
|
||||
k.into(),
|
||||
epoch_reward_params.period_reward_pool,
|
||||
epoch_reward_params.rewarded_set_size.into(),
|
||||
epoch_reward_params.active_set_size.into(),
|
||||
// Reward blockstamp gets set in the contract call
|
||||
0,
|
||||
circulating_supply,
|
||||
epoch_reward_params.circulating_supply,
|
||||
uptime.u8().into(),
|
||||
sybil_resistance_percent,
|
||||
epoch_reward_params.sybil_resistance_percent,
|
||||
i < epoch_reward_params.active_set_size as usize,
|
||||
epoch_reward_params.active_set_work_factor,
|
||||
),
|
||||
})
|
||||
}
|
||||
@@ -257,6 +275,23 @@ impl Rewarder {
|
||||
(unrewarded, further_delegators_present)
|
||||
}
|
||||
|
||||
// Utility function to print to the stdout rewarding progress
|
||||
fn print_rewarding_progress(&self, total_rewarded: usize, out_of: usize, is_retry: bool) {
|
||||
let percentage = total_rewarded as f32 * 100.0 / out_of as f32;
|
||||
|
||||
if is_retry {
|
||||
info!(
|
||||
"Resent rewarding transaction for {} / {} mixnodes\t{:.2}%",
|
||||
total_rewarded, out_of, percentage
|
||||
);
|
||||
} else {
|
||||
info!(
|
||||
"Sent rewarding transaction for {} / {} mixnodes\t{:.2}%",
|
||||
total_rewarded, out_of, percentage
|
||||
);
|
||||
}
|
||||
}
|
||||
|
||||
/// Using the list of mixnodes eligible for rewards, chunks it into pre-defined sized-chunks
|
||||
/// and gives out the rewards by calling the smart contract.
|
||||
///
|
||||
@@ -271,12 +306,26 @@ impl Rewarder {
|
||||
/// # Arguments
|
||||
///
|
||||
/// * `eligible_mixnodes`: list of the nodes that are eligible to receive rewards.
|
||||
/// * `rewarding_interval_nonce`: nonce associated with the current rewarding interval
|
||||
/// * `rewarding_interval_nonce`: nonce associated with the current rewarding interval.
|
||||
/// * `retry`: flag to indicate whether this is a retry attempt for rewarding particular nodes.
|
||||
async fn distribute_rewards_to_mixnodes(
|
||||
&self,
|
||||
eligible_mixnodes: &[MixnodeToReward],
|
||||
rewarding_interval_nonce: u32,
|
||||
retry: bool,
|
||||
) -> Option<Vec<FailedMixnodeRewardChunkDetails>> {
|
||||
if retry {
|
||||
info!(
|
||||
"Attempting to retry rewarding {} mixnodes...",
|
||||
eligible_mixnodes.len()
|
||||
)
|
||||
} else {
|
||||
info!(
|
||||
"Attempting to reward {} mixnodes...",
|
||||
eligible_mixnodes.len()
|
||||
)
|
||||
}
|
||||
|
||||
let mut failed_chunks = Vec::new();
|
||||
|
||||
// construct chunks such that we reward at most MIXNODE_DELEGATORS_PAGE_LIMIT delegators per block
|
||||
@@ -336,17 +385,14 @@ impl Rewarder {
|
||||
}
|
||||
|
||||
total_rewarded += 1;
|
||||
let percentage = total_rewarded as f32 * 100.0 / eligible_mixnodes.len() as f32;
|
||||
info!(
|
||||
"Rewarded {} / {} mixnodes\t{:.2}%",
|
||||
total_rewarded,
|
||||
eligible_mixnodes.len(),
|
||||
percentage
|
||||
);
|
||||
self.print_rewarding_progress(total_rewarded, eligible_mixnodes.len(), retry);
|
||||
}
|
||||
|
||||
// then we move onto the chunks
|
||||
for mix_chunk in batch_rewarded {
|
||||
if mix_chunk.is_empty() {
|
||||
continue;
|
||||
}
|
||||
if let Err(err) = self
|
||||
.nymd_client
|
||||
.reward_mixnodes_with_single_page_of_delegators(
|
||||
@@ -369,13 +415,7 @@ impl Rewarder {
|
||||
}
|
||||
|
||||
total_rewarded += mix_chunk.len();
|
||||
let percentage = total_rewarded as f32 * 100.0 / eligible_mixnodes.len() as f32;
|
||||
info!(
|
||||
"Rewarded {} / {} mixnodes\t{:.2}%",
|
||||
total_rewarded,
|
||||
eligible_mixnodes.len(),
|
||||
percentage
|
||||
);
|
||||
self.print_rewarding_progress(total_rewarded, eligible_mixnodes.len(), retry);
|
||||
}
|
||||
|
||||
if failed_chunks.is_empty() {
|
||||
@@ -399,7 +439,15 @@ impl Rewarder {
|
||||
nodes: &[MixnodeToReward],
|
||||
rewarding_interval_nonce: u32,
|
||||
) {
|
||||
let mut total_resent = 0;
|
||||
for missed_node in nodes {
|
||||
total_resent += 1;
|
||||
info!(
|
||||
"Sending rewarding transaction for missed delegators ({} / {} mixnodes re-checked)",
|
||||
total_resent,
|
||||
nodes.len()
|
||||
);
|
||||
|
||||
if let Err(err) = self
|
||||
.nymd_client
|
||||
.reward_mix_delegators(missed_node, rewarding_interval_nonce)
|
||||
@@ -442,7 +490,7 @@ impl Rewarder {
|
||||
.begin_mixnode_rewarding(current_rewarding_nonce + 1)
|
||||
.await?;
|
||||
failure_data.mixnodes = self
|
||||
.distribute_rewards_to_mixnodes(&eligible_mixnodes, current_rewarding_nonce + 1)
|
||||
.distribute_rewards_to_mixnodes(&eligible_mixnodes, current_rewarding_nonce + 1, false)
|
||||
.await;
|
||||
|
||||
let mut nodes_to_verify = eligible_mixnodes;
|
||||
@@ -463,7 +511,7 @@ impl Rewarder {
|
||||
|
||||
if !unrewarded.is_empty() {
|
||||
// no need to save failure data as we already know about those from the very first run
|
||||
self.distribute_rewards_to_mixnodes(&unrewarded, current_rewarding_nonce + 1)
|
||||
self.distribute_rewards_to_mixnodes(&unrewarded, current_rewarding_nonce + 1, true)
|
||||
.await;
|
||||
}
|
||||
|
||||
|
||||
Reference in New Issue
Block a user