This commit is contained in:
Jędrzej Stuczyński
2023-12-13 16:47:25 +00:00
committed by Jon Häggblad
parent e1c0638f1e
commit 2c2223947c
13 changed files with 915 additions and 723 deletions
Generated
+664 -611
View File
File diff suppressed because it is too large Load Diff
+1 -1
View File
@@ -206,7 +206,7 @@ bip32 = "0.5.1"
# temporarily using a fork again (yay.) because we need staking and slashing support
cosmrs = { git = "https://github.com/jstuczyn/cosmos-rust", branch ="nym-temp/all-validator-features" }
#cosmrs = "=0.15.0"
#cosmrs = { git = "https://github.com/jstuczyn/cosmos-rust", branch = "nym-temp/all-validator-features" } # unfortuntely we need a fork by yours truly to get the staking support
tendermint = "0.34" # same version as used by cosmrs
tendermint-rpc = "0.34" # same version as used by cosmrs
prost = "0.12"
@@ -1,79 +1,78 @@
// Copyright 2023 - Nym Technologies SA <contact@nymtech.net>
// SPDX-License-Identifier: Apache-2.0
// use crate::nyxd::error::NyxdError;
// use crate::nyxd::{CosmWasmClient, PageRequest};
use crate::nyxd::CosmWasmClient;
use crate::nyxd::error::NyxdError;
use crate::nyxd::{CosmWasmClient, PageRequest};
use async_trait::async_trait;
// use cosmrs::proto::cosmos::staking::v1beta1::{
// QueryHistoricalInfoRequest as ProtoQueryHistoricalInfoRequest,
// QueryHistoricalInfoResponse as ProtoQueryHistoricalInfoResponse,
// QueryValidatorRequest as ProtoQueryValidatorRequest,
// QueryValidatorResponse as ProtoQueryValidatorResponse,
// QueryValidatorsRequest as ProtoQueryValidatorsRequest,
// QueryValidatorsResponse as ProtoQueryValidatorsResponse,
// };
// use cosmrs::staking::{
// QueryHistoricalInfoRequest, QueryHistoricalInfoResponse, QueryValidatorRequest,
// QueryValidatorResponse, QueryValidatorsRequest, QueryValidatorsResponse,
// };
// use cosmrs::AccountId;
use cosmrs::proto::cosmos::staking::v1beta1::{
QueryHistoricalInfoRequest as ProtoQueryHistoricalInfoRequest,
QueryHistoricalInfoResponse as ProtoQueryHistoricalInfoResponse,
QueryValidatorRequest as ProtoQueryValidatorRequest,
QueryValidatorResponse as ProtoQueryValidatorResponse,
QueryValidatorsRequest as ProtoQueryValidatorsRequest,
QueryValidatorsResponse as ProtoQueryValidatorsResponse,
};
use cosmrs::staking::{
QueryHistoricalInfoRequest, QueryHistoricalInfoResponse, QueryValidatorRequest,
QueryValidatorResponse, QueryValidatorsRequest, QueryValidatorsResponse,
};
use cosmrs::AccountId;
// TODO: change trait restriction from `CosmWasmClient` to `TendermintRpcClient`
#[cfg_attr(target_arch = "wasm32", async_trait(?Send))]
#[cfg_attr(not(target_arch = "wasm32"), async_trait)]
pub trait StakingQueryClient: CosmWasmClient {
// async fn historical_info(&self, height: i64) -> Result<QueryHistoricalInfoResponse, NyxdError> {
// let path = Some("/cosmos.staking.v1beta1.Query/HistoricalInfo".to_owned());
//
// let req = QueryHistoricalInfoRequest { height };
//
// let res = self
// .make_abci_query::<ProtoQueryHistoricalInfoRequest, ProtoQueryHistoricalInfoResponse>(
// path,
// req.into(),
// )
// .await?;
//
// Ok(res.try_into()?)
// }
//
// async fn validator(
// &self,
// validator_addr: AccountId,
// ) -> Result<QueryValidatorResponse, NyxdError> {
// let path = Some("/cosmos.staking.v1beta1.Query/Validator".to_owned());
//
// let req = QueryValidatorRequest { validator_addr };
//
// let res = self
// .make_abci_query::<ProtoQueryValidatorRequest, ProtoQueryValidatorResponse>(
// path,
// req.into(),
// )
// .await?;
//
// Ok(res.try_into()?)
// }
//
// async fn validators(
// &self,
// status: String,
// pagination: Option<PageRequest>,
// ) -> Result<QueryValidatorsResponse, NyxdError> {
// let path = Some("/cosmos.staking.v1beta1.Query/Validators".to_owned());
//
// let req = QueryValidatorsRequest { status, pagination };
//
// let res = self
// .make_abci_query::<ProtoQueryValidatorsRequest, ProtoQueryValidatorsResponse>(
// path,
// req.into(),
// )
// .await?;
//
// Ok(res.try_into()?)
// }
async fn historical_info(&self, height: i64) -> Result<QueryHistoricalInfoResponse, NyxdError> {
let path = Some("/cosmos.staking.v1beta1.Query/HistoricalInfo".to_owned());
let req = QueryHistoricalInfoRequest { height };
let res = self
.make_abci_query::<ProtoQueryHistoricalInfoRequest, ProtoQueryHistoricalInfoResponse>(
path,
req.into(),
)
.await?;
Ok(res.try_into()?)
}
async fn validator(
&self,
validator_addr: AccountId,
) -> Result<QueryValidatorResponse, NyxdError> {
let path = Some("/cosmos.staking.v1beta1.Query/Validator".to_owned());
let req = QueryValidatorRequest { validator_addr };
let res = self
.make_abci_query::<ProtoQueryValidatorRequest, ProtoQueryValidatorResponse>(
path,
req.into(),
)
.await?;
Ok(res.try_into()?)
}
async fn validators(
&self,
status: String,
pagination: Option<PageRequest>,
) -> Result<QueryValidatorsResponse, NyxdError> {
let path = Some("/cosmos.staking.v1beta1.Query/Validators".to_owned());
let req = QueryValidatorsRequest { status, pagination };
let res = self
.make_abci_query::<ProtoQueryValidatorsRequest, ProtoQueryValidatorsResponse>(
path,
req.into(),
)
.await?;
Ok(res.try_into()?)
}
}
#[cfg_attr(target_arch = "wasm32", async_trait(?Send))]
@@ -41,7 +41,7 @@ pub use coin::Coin;
pub use cosmrs::{
bank::MsgSend,
bip32,
// query::{PageRequest, PageResponse},
query::{PageRequest, PageResponse},
tendermint::{
abci::{response::DeliverTx, types::ExecTxResult, Event, EventAttribute},
block::Height,
@@ -50,10 +50,7 @@ pub use cosmrs::{
Time as TendermintTime,
},
tx::{self, Msg},
AccountId,
Coin as CosmosCoin,
Denom,
Gas,
AccountId, Coin as CosmosCoin, Denom, Gas,
};
pub use cosmwasm_std::Coin as CosmWasmCoin;
pub use cw2;
+1
View File
@@ -16,3 +16,4 @@ pub mod storage;
pub use modules::{BlockModule, MsgModule, TxModule};
pub use scraper::{Config, NyxdScraper};
pub use storage::models;
+1 -1
View File
@@ -19,7 +19,7 @@ use tracing::{debug, error, info, instrument, trace, warn};
mod helpers;
mod manager;
mod models;
pub mod models;
pub type StorageTransaction = Transaction<'static, Sqlite>;
+1 -1
View File
@@ -4,7 +4,7 @@
use sqlx::types::time::OffsetDateTime;
use sqlx::FromRow;
#[derive(Debug, Clone, FromRow)]
#[derive(Debug, Clone, Eq, PartialEq, Hash, FromRow)]
pub struct Validator {
pub consensus_address: String,
pub consensus_pubkey: String,
+2 -4
View File
@@ -1014,8 +1014,7 @@ dependencies = [
[[package]]
name = "cosmos-sdk-proto"
version = "0.20.0"
source = "registry+https://github.com/rust-lang/crates.io-index"
checksum = "32560304ab4c365791fd307282f76637213d8083c1a98490c35159cd67852237"
source = "git+https://github.com/jstuczyn/cosmos-rust?branch=nym-temp/all-validator-features#67718aa27a96efb9881e927a8f998c94b885093c"
dependencies = [
"prost",
"prost-types",
@@ -1025,8 +1024,7 @@ dependencies = [
[[package]]
name = "cosmrs"
version = "0.15.0"
source = "registry+https://github.com/rust-lang/crates.io-index"
checksum = "47126f5364df9387b9d8559dcef62e99010e1d4098f39eb3f7ee4b5c254e40ea"
source = "git+https://github.com/jstuczyn/cosmos-rust?branch=nym-temp/all-validator-features#67718aa27a96efb9881e927a8f998c94b885093c"
dependencies = [
"bip32",
"cosmos-sdk-proto",
+4
View File
@@ -24,9 +24,13 @@ time.workspace = true
url.workspace = true
zeroize.workspace = true
sha2 = "0.10.8"
humantime-serde = "1.0"
reqwest = { workspace = true, features = ["json"] }
serde_json = "1.0.108"
# internal
nym-bin-common = { path = "../common/bin-common", features = ["output_format"] }
nym-config = { path = "../common/config" }
+6
View File
@@ -10,6 +10,7 @@ use nym_config::{
DEFAULT_CONFIG_DIR, DEFAULT_CONFIG_FILENAME, DEFAULT_DATA_DIR, NYM_DIR,
};
use nym_network_defaults::NymNetworkDetails;
use nym_validator_client::nyxd;
use nym_validator_client::nyxd::Coin;
use serde::{Deserialize, Serialize};
use std::io;
@@ -109,6 +110,11 @@ impl Config {
}
}
pub fn rpc_client_config(&self) -> nyxd::Config {
// TEMP
nyxd::Config::try_from_nym_network_details(&NymNetworkDetails::new_from_env()).unwrap()
}
pub fn ensure_is_valid(&self) -> Result<(), NymRewarderError> {
self.rewarding.ratios.ensure_is_valid()?;
Ok(())
@@ -3,11 +3,12 @@
use cosmwasm_std::{Decimal, Uint128};
use nym_validator_client::nyxd::Coin;
use nyxd_scraper::models;
use std::collections::HashMap;
#[derive(Debug)]
pub struct ValidatorSigning {
pub consensus_address: String,
pub validator: models::Validator,
pub voting_power_at_epoch_start: i64,
pub voting_power_ratio: Decimal,
@@ -28,7 +29,7 @@ impl EpochSigning {
pub fn construct(
blocks: i64,
total_vp: i64,
validator_results: HashMap<String, (i32, i64)>,
validator_results: HashMap<models::Validator, (i32, i64)>,
) -> Self {
assert!(total_vp >= 0, "negative voting power!");
assert!(blocks >= 0, "negative blocks!");
@@ -38,7 +39,7 @@ impl EpochSigning {
let validators = validator_results
.into_iter()
.map(
|(consensus_address, (signed_blocks, voting_power_at_epoch_start))| {
|(validator, (signed_blocks, voting_power_at_epoch_start))| {
let vp: u64 = voting_power_at_epoch_start.try_into().unwrap_or_default();
let signed: u64 = signed_blocks.try_into().unwrap_or_default();
@@ -46,7 +47,7 @@ impl EpochSigning {
let ratio_signed = Decimal::from_ratio(signed, blocks_u64);
ValidatorSigning {
consensus_address,
validator,
voting_power_at_epoch_start,
voting_power_ratio,
signed_blocks,
@@ -63,14 +64,14 @@ impl EpochSigning {
}
}
pub fn rewarding_amounts(&self, budget: &Coin) -> HashMap<String, Coin> {
pub fn rewarding_amounts(&self, budget: &Coin) -> HashMap<models::Validator, Coin> {
let denom = &budget.denom;
self.validators
.iter()
.map(|v| {
let amount = Uint128::new(budget.amount) * v.ratio_signed * v.voting_power_ratio;
(v.consensus_address.clone(), Coin::new(amount.u128(), denom))
(v.validator.clone(), Coin::new(amount.u128(), denom))
})
.collect()
}
+125 -21
View File
@@ -8,11 +8,14 @@ use crate::rewarder::epoch::Epoch;
use crate::rewarder::helpers::consensus_address_to_account;
use nym_network_defaults::NymNetworkDetails;
use nym_task::TaskManager;
use nym_validator_client::nyxd::{AccountId, Coin};
use nyxd_scraper::NyxdScraper;
use nym_validator_client::nyxd::{AccountId, Coin, StakingQueryClient};
use nym_validator_client::QueryHttpRpcNyxdClient;
use nyxd_scraper::{models, NyxdScraper};
use sha2::{Digest, Sha256};
use std::cmp::min;
use std::collections::HashMap;
use std::ops::{Add, Range};
use std::str::FromStr;
use std::time::Duration;
use time::format_description::well_known::Rfc3339;
use time::OffsetDateTime;
@@ -26,6 +29,7 @@ mod tasks;
pub struct Rewarder {
current_epoch: Epoch,
rpc_client: QueryHttpRpcNyxdClient,
config: Config,
nyxd_scraper: NyxdScraper,
@@ -34,9 +38,14 @@ pub struct Rewarder {
impl Rewarder {
pub async fn new(config: Config) -> Result<Self, NymRewarderError> {
let nyxd_scraper = NyxdScraper::new(config.scraper_config()).await?;
let rpc_client = QueryHttpRpcNyxdClient::connect(
config.rpc_client_config(),
config.base.upstream_nyxd.as_str(),
)?;
Ok(Rewarder {
current_epoch: Epoch::first()?,
rpc_client,
config,
nyxd_scraper,
})
@@ -105,7 +114,7 @@ impl Rewarder {
.storage
.get_signed_between_times(&validator.consensus_address, epoch_start, epoch_end)
.await?;
signed_in_epoch.insert(validator.consensus_address, (signed, vp));
signed_in_epoch.insert(validator, (signed, vp));
}
let total = self
@@ -122,7 +131,7 @@ impl Rewarder {
async fn calculate_block_signing_rewards(
&mut self,
budget: Coin,
) -> Result<HashMap<String, Coin>, NymRewarderError> {
) -> Result<HashMap<models::Validator, Coin>, NymRewarderError> {
info!("calculating reward shares");
let signed = self.get_signed_blocks().await?;
@@ -135,14 +144,14 @@ impl Rewarder {
async fn calculate_credential_rewards(
&mut self,
budget: Coin,
) -> Result<HashMap<String, Coin>, NymRewarderError> {
) -> Result<HashMap<models::Validator, Coin>, NymRewarderError> {
info!("calculating reward shares");
Ok(HashMap::new())
}
async fn determine_epoch_rewards(
&mut self,
) -> Result<HashMap<String, (AccountId, Coin)>, NymRewarderError> {
) -> Result<HashMap<models::Validator, (AccountId, Coin)>, NymRewarderError> {
let epoch_budget = &self.config.rewarding.epoch_budget;
let denom = &epoch_budget.denom;
let signing_budget = Coin::new(
@@ -157,23 +166,57 @@ impl Rewarder {
let signing_rewards = self.calculate_block_signing_rewards(signing_budget).await?;
let credential_rewards = self.calculate_credential_rewards(credential_budget).await?;
let mut rewards = HashMap::new();
for (validator, amount) in signing_rewards {
let account = consensus_address_to_account(&validator)?;
rewards.insert(validator, (account, amount));
let mut rewards: HashMap<models::Validator, (AccountId, Coin)> = HashMap::new();
let validators2 = self
.rpc_client
.validators("".to_string(), None)
.await
.unwrap();
let mut monikers = HashMap::new();
for v in validators2.validators {
let val = v.consensus_pubkey.unwrap();
// println!("{:?}", val);
let digest = Sha256::digest(&val.to_bytes()).to_vec();
// println!("{}", String::from_utf8_lossy(&val));
// assert_eq!(val.len(), 32);
let consensus_key = AccountId::new("nvalcons", &digest[..20])
.unwrap()
.to_string();
let moniker = v.description.unwrap().moniker;
let acc = v.operator_address;
let acc = AccountId::new("n", &acc.to_bytes()).unwrap();
monikers.insert(consensus_key, (moniker, acc));
}
for (validator, amount) in credential_rewards {
let account = consensus_address_to_account(&validator)?;
for (val, amount) in &signing_rewards {
// let oper = AccountId::new("nvaloper", &acc.to_bytes()).unwrap();
// let moniker = get_moniker(acc.clone()).await;
if let Some(existing) = rewards.get_mut(&validator) {
assert_eq!(existing.0, account);
existing.1.amount += amount.amount;
} else {
rewards.insert(validator, (account, amount));
}
let (moniker, acc) = monikers.get(&val.consensus_address).unwrap();
println!("{moniker}: {acc} signing: {amount} credentials: XXX")
//
}
// for (validator, amount) in signing_rewards {
// let account = consensus_address_to_account(&validator)?;
// rewards.insert(validator, (account, amount));
// }
//
// for (validator, amount) in credential_rewards {
// let account = consensus_address_to_account(&validator)?;
//
// if let Some(existing) = rewards.get_mut(&validator) {
// assert_eq!(existing.0, account);
// existing.1.amount += amount.amount;
// } else {
// rewards.insert(validator, (account, amount));
// }
// }
Ok(rewards)
}
@@ -195,6 +238,19 @@ impl Rewarder {
}
};
// for (_, (acc, amount)) in rewards {
// // let oper = AccountId::new("nvaloper", &acc.to_bytes()).unwrap();
// // let moniker = get_moniker(acc.clone()).await;
//
// let moniker = validators2.validators.iter().find(|v| {
// v.consensus_pubkey
//
// })
//
// println!("{moniker}: {acc} signing: {amount} credentials: XXX")
// //
// }
/*
let budget = Coin::new(667_000_000, "unym");
@@ -223,8 +279,8 @@ impl Rewarder {
self.current_epoch.end = OffsetDateTime::now_utc();
self.current_epoch.start = self.current_epoch.end - Duration::from_secs(60 * 60);
println!("sleepiing for 60");
tokio::time::sleep(Duration::from_secs(60)).await;
println!("sleepiing for 10");
tokio::time::sleep(Duration::from_secs(10)).await;
let until_end = self.current_epoch.until_end();
@@ -274,6 +330,37 @@ fn val_to_nym(addr: &str) -> String {
bar.to_string()
}
fn make_url(oper: &str) -> String {
format!("https://rpc.nymtech.net/api/cosmos/staking/v1beta1/validators/{oper}")
}
async fn get_moniker(addr: AccountId) -> String {
let oper = AccountId::new("nvaloper", &addr.to_bytes())
.unwrap()
.to_string();
let foo: serde_json::Value = reqwest::get(make_url(&oper))
.await
.unwrap()
.json()
.await
.unwrap();
println!("raw: {foo:?}");
let Some(a) = foo.as_object() else {
return "UNKNOWN".to_string();
};
let Some(b) = a.get("validator").and_then(|o| o.as_object()) else {
return "UNKNOWN".to_string();
};
let Some(c) = b.get("description").and_then(|o| o.as_object()) else {
return "UNKNOWN".to_string();
};
let moniker = c.get("moniker").unwrap().as_str().unwrap();
moniker.to_string()
}
#[cfg(test)]
mod tests {
use super::*;
@@ -281,7 +368,7 @@ mod tests {
#[test]
fn aaa() {
let addr = AccountId::from_str("nvaloper18xr68spwm96vvehuvwf6ay9er0gd7q7ae8w8ns").unwrap();
let addr = AccountId::from_str("nvalcons1yn8kzqna703x5a6wh449ylw70u5drjejx5t6dz").unwrap();
println!("{}", AccountId::new("n", &addr.to_bytes()).unwrap());
println!("{}", AccountId::new("nvaloper", &addr.to_bytes()).unwrap());
println!("{}", AccountId::new("nvalcons", &addr.to_bytes()).unwrap());
@@ -290,4 +377,21 @@ mod tests {
// let b = val_to_nym("nvaloper1q8cnx8s06q7ralnskqvj0acvqgacau6djqkm3z");
// println!("{b}");
}
#[tokio::test]
async fn bar() {
let oper = "nvaloper18xr68spwm96vvehuvwf6ay9er0gd7q7ae8w8ns";
let foo: serde_json::Value = reqwest::get(make_url(oper))
.await
.unwrap()
.json()
.await
.unwrap();
let a = foo.as_object().unwrap();
let b = a.get("validator").unwrap().as_object().unwrap();
let c = b.get("description").unwrap().as_object().unwrap();
let moniker = c.get("moniker").unwrap().as_str().unwrap();
println!("moniker: {moniker}")
}
}
+35 -6
View File
@@ -808,6 +808,16 @@ dependencies = [
"tendermint-proto",
]
[[package]]
name = "cosmos-sdk-proto"
version = "0.20.0"
source = "git+https://github.com/jstuczyn/cosmos-rust?branch=nym-temp/all-validator-features#67718aa27a96efb9881e927a8f998c94b885093c"
dependencies = [
"prost",
"prost-types",
"tendermint-proto",
]
[[package]]
name = "cosmrs"
version = "0.15.0"
@@ -815,7 +825,26 @@ source = "registry+https://github.com/rust-lang/crates.io-index"
checksum = "47126f5364df9387b9d8559dcef62e99010e1d4098f39eb3f7ee4b5c254e40ea"
dependencies = [
"bip32",
"cosmos-sdk-proto",
"cosmos-sdk-proto 0.20.0 (registry+https://github.com/rust-lang/crates.io-index)",
"ecdsa 0.16.8",
"eyre",
"k256 0.13.1",
"rand_core 0.6.4",
"serde",
"serde_json",
"signature 2.1.0",
"subtle-encoding",
"tendermint",
"thiserror",
]
[[package]]
name = "cosmrs"
version = "0.15.0"
source = "git+https://github.com/jstuczyn/cosmos-rust?branch=nym-temp/all-validator-features#67718aa27a96efb9881e927a8f998c94b885093c"
dependencies = [
"bip32",
"cosmos-sdk-proto 0.20.0 (git+https://github.com/jstuczyn/cosmos-rust?branch=nym-temp/all-validator-features)",
"ecdsa 0.16.8",
"eyre",
"k256 0.13.1",
@@ -3127,7 +3156,7 @@ name = "nym-api-requests"
version = "0.1.0"
dependencies = [
"bs58 0.4.0",
"cosmrs",
"cosmrs 0.15.0 (git+https://github.com/jstuczyn/cosmos-rust?branch=nym-temp/all-validator-features)",
"cosmwasm-std",
"getset",
"nym-coconut-interface",
@@ -3422,7 +3451,7 @@ name = "nym-types"
version = "1.0.0"
dependencies = [
"base64 0.21.4",
"cosmrs",
"cosmrs 0.15.0 (git+https://github.com/jstuczyn/cosmos-rust?branch=nym-temp/all-validator-features)",
"cosmwasm-std",
"eyre",
"hmac 0.12.1",
@@ -3455,7 +3484,7 @@ dependencies = [
"bip32",
"bip39",
"colored 2.0.4",
"cosmrs",
"cosmrs 0.15.0 (git+https://github.com/jstuczyn/cosmos-rust?branch=nym-temp/all-validator-features)",
"cosmwasm-std",
"cw-controllers",
"cw-utils",
@@ -3527,7 +3556,7 @@ dependencies = [
name = "nym-wallet-types"
version = "1.0.0"
dependencies = [
"cosmrs",
"cosmrs 0.15.0 (registry+https://github.com/rust-lang/crates.io-index)",
"cosmwasm-std",
"hex-literal",
"nym-config",
@@ -3564,7 +3593,7 @@ dependencies = [
"bip39",
"cfg-if",
"colored 2.0.4",
"cosmrs",
"cosmrs 0.15.0 (registry+https://github.com/rust-lang/crates.io-index)",
"cosmwasm-std",
"dirs 4.0.0",
"dotenvy",