Removed gateway rewarding and delegation (#856)

* Removed gateway rewarding and delegation

* Removed redundant error variants

* [ci skip] Generate TS types

* Test fixes

Co-authored-by: jstuczyn <jstuczyn@users.noreply.github.com>
This commit is contained in:
Jędrzej Stuczyński
2021-11-03 15:01:59 +00:00
committed by GitHub
parent ef88ce9252
commit b19528d47e
32 changed files with 73 additions and 3520 deletions
+1 -66
View File
@@ -33,10 +33,7 @@ struct ValidatorCacheInner {
gateways: RwLock<Cache<Vec<GatewayBond>>>,
active_mixnodes_available: AtomicBool,
active_gateways_available: AtomicBool,
current_mixnode_active_set_size: AtomicUsize,
current_gateway_active_set_size: AtomicUsize,
}
#[derive(Default, Serialize, Clone)]
@@ -131,7 +128,6 @@ impl ValidatorCache {
routes::get_mixnodes,
routes::get_gateways,
routes::get_active_mixnodes,
routes::get_active_gateways
],
)
})
@@ -155,28 +151,10 @@ impl ValidatorCache {
true
}
// TODO: check if all nodes can be compared together,
// i.e. they all have the same denom for bonds and delegations
fn verify_gateways(&self, gateways: &[GatewayBond]) -> bool {
if gateways.is_empty() {
return true;
}
let expected_denom = &gateways[0].bond_amount.denom;
for gateway in gateways {
if &gateway.bond_amount.denom != expected_denom
|| &gateway.total_delegation.denom != expected_denom
{
return false;
}
}
true
}
async fn update_cache(
&self,
mut mixnodes: Vec<MixNodeBond>,
mut gateways: Vec<GatewayBond>,
gateways: Vec<GatewayBond>,
state: StateParams,
) {
// if our data is valid, it means the active sets are available,
@@ -199,23 +177,6 @@ impl ValidatorCache {
.store(false, Ordering::SeqCst);
}
if self.verify_gateways(&gateways) {
// partial_cmp can only fail if the nodes have different denomination,
// but we just checked for that hence the unwraps are fine here
// Note the reverse order of comparison so that the "highest" node would be first
gateways.sort_by(|a, b| b.partial_cmp(a).unwrap());
self.inner
.active_gateways_available
.store(true, Ordering::SeqCst);
self.inner
.current_gateway_active_set_size
.store(state.gateway_active_set_size as usize, Ordering::SeqCst);
} else {
self.inner
.active_gateways_available
.store(false, Ordering::SeqCst);
}
self.inner.mixnodes.write().await.set(mixnodes);
self.inner.gateways.write().await.set(gateways);
}
@@ -252,30 +213,6 @@ impl ValidatorCache {
}
}
pub async fn active_gateways(&self) -> Option<Cache<Vec<GatewayBond>>> {
// if active set is available, it means it is already sorted
if self.inner.active_gateways_available.load(Ordering::SeqCst) {
let cache = self.inner.gateways.read().await;
let timestamp = cache.as_at;
let nodes = cache
.value
.iter()
.take(
self.inner
.current_gateway_active_set_size
.load(Ordering::SeqCst),
)
.cloned()
.collect();
Some(Cache {
value: nodes,
as_at: timestamp,
})
} else {
None
}
}
pub fn initialised(&self) -> bool {
self.inner.initialised.load(Ordering::Relaxed)
}
@@ -300,9 +237,7 @@ impl ValidatorCacheInner {
mixnodes: RwLock::new(Cache::default()),
gateways: RwLock::new(Cache::default()),
active_mixnodes_available: AtomicBool::new(false),
active_gateways_available: AtomicBool::new(false),
current_mixnode_active_set_size: Default::default(),
current_gateway_active_set_size: Default::default(),
}
}
}
-7
View File
@@ -22,10 +22,3 @@ pub(crate) async fn get_active_mixnodes(
) -> Option<Json<Vec<MixNodeBond>>> {
cache.active_mixnodes().await.map(|cache| Json(cache.value))
}
#[get("/gateways/active")]
pub(crate) async fn get_active_gateways(
cache: &State<ValidatorCache>,
) -> Option<Json<Vec<GatewayBond>>> {
cache.active_gateways().await.map(|cache| Json(cache.value))
}
+1 -97
View File
@@ -3,8 +3,7 @@
use crate::config::Config;
use crate::rewarding::{
error::RewardingError, GatewayToReward, MixnodeToReward, GATEWAY_REWARD_OP_BASE_GAS_LIMIT,
MIXNODE_REWARD_OP_BASE_GAS_LIMIT, PER_GATEWAY_DELEGATION_GAS_INCREASE,
error::RewardingError, MixnodeToReward, MIXNODE_REWARD_OP_BASE_GAS_LIMIT,
PER_MIXNODE_DELEGATION_GAS_INCREASE, REWARDING_GAS_LIMIT_MULTIPLIER,
};
use config::defaults::DEFAULT_VALIDATOR_API_PORT;
@@ -129,20 +128,6 @@ impl<C> Client<C> {
.await
}
pub(crate) async fn get_gateway_delegations(
&self,
identity: IdentityKey,
) -> Result<Vec<Delegation>, ValidatorClientError>
where
C: CosmWasmClient + Sync,
{
self.0
.read()
.await
.get_all_nymd_single_gateway_delegations(identity)
.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;
@@ -156,19 +141,6 @@ impl<C> Client<C> {
.calculate_custom_fee(total_gas_limit)
}
async fn estimate_gateway_reward_fees(&self, nodes: usize, total_delegations: usize) -> Fee {
let base_gas_limit = GATEWAY_REWARD_OP_BASE_GAS_LIMIT * nodes as u64
+ PER_GATEWAY_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 reward_mixnodes(
&self,
nodes: &[MixnodeToReward],
@@ -236,72 +208,4 @@ impl<C> Client<C> {
}
}
}
pub(crate) async fn reward_gateways(
&self,
nodes: &[GatewayToReward],
) -> Result<(), RewardingError>
where
C: SigningCosmWasmClient + Sync,
{
let total_delegations = nodes.iter().map(|node| node.total_delegations).sum();
let fee = self
.estimate_gateway_reward_fees(nodes.len(), total_delegations)
.await;
let msgs: Vec<(ExecuteMsg, _)> = nodes
.iter()
.map(Into::into)
.zip(std::iter::repeat(Vec::new()))
.collect();
let memo = format!("rewarding {} gateways", msgs.len());
let contract = self
.0
.read()
.await
.get_mixnet_contract_address()
.ok_or(RewardingError::UnspecifiedContractAddress)?;
// grab the write lock here so we're sure nothing else is executing anything on the contract
// in the meantime
// however, we're not 100% guarded against everything
// for example somebody might have taken the mnemonic used by the validator
// and sent a transaction manually using the same account. The sequence number
// would have gotten incremented, yet the rewarding transaction might have actually not
// been included in the block. sadly we can't do much about that.
let client_guard = self.0.write().await;
let pre_sequence = client_guard.nymd.account_sequence().await?;
let res = client_guard
.nymd
.execute_multiple(&contract, msgs.clone(), fee.clone(), memo.clone())
.await;
match res {
Ok(_) => Ok(()),
Err(err) => {
if err.is_tendermint_response_timeout() {
// wait until we're sure we're into the next block (remember we're holding the lock)
sleep(Duration::from_secs(11)).await;
let curr_sequence = client_guard.nymd.account_sequence().await?;
if curr_sequence.sequence > pre_sequence.sequence {
// unless somebody was messing around doing stuff manually in that tiny time interval
// we're good. It was a false negative.
Ok(())
} else {
// the sequence number has not increased, meaning the transaction was not executed
// so attempt to send it again
client_guard
.nymd
.execute_multiple(&contract, msgs, fee, memo)
.await?;
Ok(())
}
} else {
Err(err.into())
}
}
}
}
}
-3
View File
@@ -14,9 +14,6 @@ pub(crate) enum RewardingError {
#[error("There were no mixnodes to reward (network is dead)")]
NoMixnodesToReward,
#[error("There were no gateways to reward (network is dead)")]
NoGatewaysToReward,
#[error("Failed to execute the smart contract - {0}")]
ContractExecutionFailure(NymdError),
+3 -216
View File
@@ -8,8 +8,7 @@ use crate::nymd_client::Client;
use crate::rewarding::epoch::Epoch;
use crate::rewarding::error::RewardingError;
use crate::storage::models::{
FailedGatewayRewardChunk, FailedMixnodeRewardChunk, PossiblyUnrewardedGateway,
PossiblyUnrewardedMixnode, RewardingReport,
FailedMixnodeRewardChunk, PossiblyUnrewardedMixnode, RewardingReport,
};
use crate::storage::NodeStatusStorage;
use log::{error, info};
@@ -27,7 +26,6 @@ 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;
pub(crate) const GATEWAY_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.
@@ -36,7 +34,6 @@ pub(crate) const GATEWAY_REWARD_OP_BASE_GAS_LIMIT: u64 = 150_000;
// 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;
pub(crate) const PER_GATEWAY_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.
@@ -53,29 +50,14 @@ pub(crate) struct MixnodeToReward {
pub(crate) total_delegations: usize,
}
#[derive(Debug, Clone)]
pub(crate) struct GatewayToReward {
pub(crate) identity: IdentityKey,
pub(crate) uptime: Uptime,
/// Total number of individual addresses that have delegated to this particular gateway
pub(crate) total_delegations: usize,
}
pub(crate) struct FailedMixnodeRewardChunkDetails {
possibly_unrewarded: Vec<MixnodeToReward>,
error_message: String,
}
pub(crate) struct FailedGatewayRewardChunkDetails {
possibly_unrewarded: Vec<GatewayToReward>,
error_message: String,
}
#[derive(Default)]
pub(crate) struct FailureData {
mixnodes: Option<Vec<FailedMixnodeRewardChunkDetails>>,
gateways: Option<Vec<FailedGatewayRewardChunkDetails>>,
}
impl<'a> From<&'a MixnodeToReward> for ExecuteMsg {
@@ -87,15 +69,6 @@ impl<'a> From<&'a MixnodeToReward> for ExecuteMsg {
}
}
impl<'a> From<&'a GatewayToReward> for ExecuteMsg {
fn from(node: &GatewayToReward) -> Self {
ExecuteMsg::RewardGateway {
identity: node.identity.clone(),
uptime: node.uptime.u8() as u32,
}
}
}
pub(crate) struct Rewarder {
nymd_client: Client<SigningNymdClient>,
validator_cache: ValidatorCache,
@@ -149,22 +122,6 @@ impl Rewarder {
.len())
}
/// Obtains the current number of delegators that have delegated their stake towards this particular gateway.
///
/// # Arguments
///
/// * `identity`: identity key of the gateway
async fn get_gateway_delegators_count(
&self,
identity: IdentityKey,
) -> Result<usize, RewardingError> {
Ok(self
.nymd_client
.get_gateway_delegations(identity)
.await?
.len())
}
/// Queries the smart contract in order to obtain the current list of bonded mixnodes and then
/// for each mixnode determines how many delegators it has.
async fn produce_active_mixnode_delegators_map(
@@ -202,30 +159,6 @@ impl Rewarder {
Ok(map)
}
/// Queries the smart contract in order to obtain the current list of bonded gateways and then
/// for each gateway determines how many delegators it has.
async fn produce_active_gateway_delegators_map(
&self,
) -> Result<HashMap<IdentityKey, usize>, RewardingError> {
// look at comments in `produce_mixnode_delegators_map` for some optimisation elaboration
let mut map = HashMap::new();
let active_bonded_gateways = self
.validator_cache
.active_gateways()
.await
.ok_or(RewardingError::NoGatewaysToReward)?
.into_inner();
for gateway in active_bonded_gateways.into_iter() {
let delegator_count = self
.get_gateway_delegators_count(gateway.gateway.identity_key.clone())
.await?;
map.insert(gateway.gateway.identity_key, delegator_count);
}
Ok(map)
}
/// Calculates the absolute uptime of given node that is then passed as one of the arguments
/// in the smart contract to determine the actual reward value.
///
@@ -290,46 +223,6 @@ impl Rewarder {
Ok(eligible_nodes)
}
/// Given the list of gateways that were tested in the last epoch, tries to determine the
/// subset that are eligible for any rewards.
///
/// As of right now, it is a rather straightforward process. It is checked whether the node
/// is currently bonded, has uptime > 0 and is part of the "active" set.
/// Unlike the typescript rewards script, it currently does not look at the non-mixing ports are open.
///
/// The method also obtains the number of delegators towards the node in order to more accurately
/// approximate the required gas fees when distributing the rewards.
///
/// # Arguments
///
/// * `active_gateways`: list of the nodes that were tested at least once by the network monitor
/// in the last epoch.
async fn determine_eligible_gateways(
&self,
active_gateways: &[GatewayStatusReport],
) -> Result<Vec<GatewayToReward>, RewardingError> {
let gateway_delegators = self.produce_active_gateway_delegators_map().await?;
let eligible_nodes = active_gateways
.iter()
.filter_map(|gateway| {
gateway_delegators
.get(&gateway.identity)
.map(|&total_delegations| GatewayToReward {
identity: gateway.identity.clone(),
uptime: self.calculate_absolute_uptime(
gateway.last_day_ipv4,
gateway.last_day_ipv6,
),
total_delegations,
})
})
.filter(|node| node.uptime.u8() > 0)
.collect();
Ok(eligible_nodes)
}
/// Obtains the lists of all mixnodes and gateways that were tested at least a single time
/// by the network monitor in the specified epoch.
///
@@ -410,58 +303,6 @@ impl Rewarder {
}
}
/// Using the list of gateways eligible for rewards, chunks it into pre-defined sized-chunks
/// and gives out the rewards by calling the smart contract.
///
/// Returns an optional vector containing list of chunks that experienced a smart contract
/// execution error during reward distribution. However, it does not necessarily imply they
/// were not rewarded. There are some edge cases where we time out waiting for block to be included
/// yet the transactions went through.
///
/// Only returns errors for problems originating from before smart contract was called, i.e.
/// we know for sure not a single node has been rewarded.
///
/// # Arguments
///
/// * `eligible_gateways`: list of the nodes that are eligible to receive non-zero rewards.
async fn distribute_rewards_to_gateways(
&self,
eligible_gateways: &[GatewayToReward],
) -> Option<Vec<FailedGatewayRewardChunkDetails>> {
let mut failed_chunks = Vec::new();
for (i, gateway_chunk) in eligible_gateways.chunks(MAX_TO_REWARD_AT_ONCE).enumerate() {
if let Err(err) = self.nymd_client.reward_gateways(gateway_chunk).await {
// this is a super weird edge case that we didn't catch change to sequence and
// resent rewards unnecessarily, but the mempool saved us from executing it again
// however, still we want to wait until we're sure we're into the next block
if !err.is_tendermint_duplicate() {
error!("failed to reward gateways... - {}", err);
failed_chunks.push(FailedGatewayRewardChunkDetails {
possibly_unrewarded: gateway_chunk.to_vec(),
error_message: err.to_string(),
});
}
sleep(Duration::from_secs(11)).await;
}
let rewarded = i * MAX_TO_REWARD_AT_ONCE + gateway_chunk.len();
let percentage = rewarded as f32 * 100.0 / eligible_gateways.len() as f32;
info!(
"Rewarded {} / {} gateways\t{:.2}%",
rewarded,
eligible_gateways.len(),
percentage
);
}
if failed_chunks.is_empty() {
None
} else {
Some(failed_chunks)
}
}
/// Using the list of active mixnode and gateways, determine which of them are eligible for
/// rewarding and distribute the rewards.
///
@@ -471,14 +312,10 @@ impl Rewarder {
///
/// * `active_monitor_mixnodes`: list of the nodes that were tested at least once by the network monitor
/// in the last epoch.
///
/// * `active_monitor_gateways`: list of the nodes that were tested at least once by the network monitor
/// in the last epoch.
async fn distribute_rewards(
&self,
epoch_rewarding_id: i64,
active_monitor_mixnodes: &[MixnodeStatusReport],
active_monitor_gateways: &[GatewayStatusReport],
) -> Result<(RewardingReport, Option<FailureData>), RewardingError> {
let mut failure_data = FailureData::default();
@@ -489,25 +326,13 @@ impl Rewarder {
return Err(RewardingError::NoMixnodesToReward);
}
let eligible_gateways = self
.determine_eligible_gateways(active_monitor_gateways)
.await?;
if eligible_gateways.is_empty() {
return Err(RewardingError::NoGatewaysToReward);
}
failure_data.mixnodes = self
.distribute_rewards_to_mixnodes(&eligible_mixnodes)
.await;
failure_data.gateways = self
.distribute_rewards_to_gateways(&eligible_gateways)
.await;
let report = RewardingReport {
epoch_rewarding_id,
eligible_mixnodes: eligible_mixnodes.len() as i64,
eligible_gateways: eligible_gateways.len() as i64,
possibly_unrewarded_mixnodes: failure_data
.mixnodes
.as_ref()
@@ -518,19 +343,9 @@ impl Rewarder {
.sum::<usize>() as i64
})
.unwrap_or_default(),
possibly_unrewarded_gateways: failure_data
.gateways
.as_ref()
.map(|chunks| {
chunks
.iter()
.map(|chunk| chunk.possibly_unrewarded.len())
.sum::<usize>() as i64
})
.unwrap_or_default(),
};
if failure_data.mixnodes.is_none() && failure_data.gateways.is_none() {
if failure_data.mixnodes.is_none() {
Ok((report, None))
} else {
Ok((report, Some(failure_data)))
@@ -575,30 +390,6 @@ impl Rewarder {
}
}
if let Some(failed_gateway_chunks) = failure_data.gateways {
for failed_chunk in failed_gateway_chunks.into_iter() {
// save the chunk
let chunk_id = self
.storage
.insert_failed_gateway_reward_chunk(FailedGatewayRewardChunk {
epoch_rewarding_id,
error_message: failed_chunk.error_message,
})
.await?;
// and then all associated nodes
for node in failed_chunk.possibly_unrewarded.into_iter() {
self.storage
.insert_possibly_unrewarded_gateway(PossiblyUnrewardedGateway {
chunk_id,
identity: node.identity,
uptime: node.uptime.u8(),
})
.await?;
}
}
}
Ok(())
}
@@ -731,11 +522,7 @@ impl Rewarder {
.await?;
let (report, failure_data) = self
.distribute_rewards(
epoch_rewarding_id,
&active_monitor_mixnodes,
&active_monitor_gateways,
)
.distribute_rewards(epoch_rewarding_id, &active_monitor_mixnodes)
.await?;
self.storage
+6 -49
View File
@@ -5,8 +5,8 @@ use crate::network_monitor::monitor::summary_producer::NodeResult;
use crate::node_status_api::models::{HistoricalUptime, Uptime};
use crate::node_status_api::utils::ActiveNodeDayStatuses;
use crate::storage::models::{
ActiveNode, EpochRewarding, FailedGatewayRewardChunk, FailedMixnodeRewardChunk, NodeStatus,
PossiblyUnrewardedGateway, PossiblyUnrewardedMixnode, RewardingReport,
ActiveNode, EpochRewarding, FailedMixnodeRewardChunk, NodeStatus, PossiblyUnrewardedMixnode,
RewardingReport,
};
use crate::storage::UnixTimestamp;
use std::convert::TryFrom;
@@ -791,17 +791,15 @@ impl StorageManager {
sqlx::query!(
r#"
INSERT INTO rewarding_report
(epoch_rewarding_id, eligible_mixnodes, eligible_gateways, possibly_unrewarded_mixnodes, possibly_unrewarded_gateways)
VALUES (?, ?, ?, ?, ?);
(epoch_rewarding_id, eligible_mixnodes, possibly_unrewarded_mixnodes)
VALUES (?, ?, ?);
"#,
report.epoch_rewarding_id,
report.eligible_mixnodes,
report.eligible_gateways,
report.possibly_unrewarded_mixnodes,
report.possibly_unrewarded_gateways,
)
.execute(&self.connection_pool)
.await?;
.execute(&self.connection_pool)
.await?;
Ok(())
}
@@ -826,27 +824,6 @@ impl StorageManager {
Ok(res.last_insert_rowid())
}
/// Inserts new failed gateway reward chunk information into the database.
/// Returns id of the newly created entry.
///
/// # Arguments
///
/// * `failed_chunk`: chunk information to insert.
pub(super) async fn insert_failed_gateway_reward_chunk(
&self,
failed_chunk: FailedGatewayRewardChunk,
) -> Result<i64, sqlx::Error> {
let res = sqlx::query!(
r#"
INSERT INTO failed_gateway_reward_chunk (error_message, reward_summary_id) VALUES (?, ?)
"#,
failed_chunk.error_message,
failed_chunk.epoch_rewarding_id,
).execute(&self.connection_pool).await?;
Ok(res.last_insert_rowid())
}
/// Inserts information into the database about a mixnode that might have been unfairly unrewarded this epoch.
///
/// # Arguments
@@ -867,26 +844,6 @@ impl StorageManager {
Ok(())
}
/// Inserts information into the database about a gateway that might have been unfairly unrewarded this epoch.
///
/// # Arguments
///
/// * `gateway`: mixnode information to insert.
pub(super) async fn insert_possibly_unrewarded_gateway(
&self,
gateway: PossiblyUnrewardedGateway,
) -> Result<(), sqlx::Error> {
sqlx::query!(
r#"
INSERT INTO possibly_unrewarded_gateway (identity, uptime, failed_gateway_reward_chunk_id) VALUES (?, ?, ?)
"#,
gateway.identity,
gateway.uptime,
gateway.chunk_id
).execute(&self.connection_pool).await?;
Ok(())
}
/// Obtains all statuses of active mixnodes from the specified time interval.
///
/// # Arguments
+2 -33
View File
@@ -9,8 +9,8 @@ use crate::node_status_api::models::{
use crate::node_status_api::{ONE_DAY, ONE_HOUR};
use crate::storage::manager::StorageManager;
use crate::storage::models::{
EpochRewarding, FailedGatewayRewardChunk, FailedMixnodeRewardChunk, NodeStatus,
PossiblyUnrewardedGateway, PossiblyUnrewardedMixnode, RewardingReport,
EpochRewarding, FailedMixnodeRewardChunk, NodeStatus, PossiblyUnrewardedMixnode,
RewardingReport,
};
use rocket::fairing::{self, AdHoc};
use rocket::{Build, Rocket};
@@ -648,22 +648,6 @@ impl NodeStatusStorage {
.map_err(|_| NodeStatusApiError::InternalDatabaseError)
}
/// Inserts new failed gateway reward chunk information into the database.
/// Returns id of the newly created entry.
///
/// # Arguments
///
/// * `failed_chunk`: chunk information to insert.
pub(crate) async fn insert_failed_gateway_reward_chunk(
&self,
failed_chunk: FailedGatewayRewardChunk,
) -> Result<i64, NodeStatusApiError> {
self.manager
.insert_failed_gateway_reward_chunk(failed_chunk)
.await
.map_err(|_| NodeStatusApiError::InternalDatabaseError)
}
/// Inserts information into the database about a mixnode that might have been unfairly unrewarded this epoch.
///
/// # Arguments
@@ -678,19 +662,4 @@ impl NodeStatusStorage {
.await
.map_err(|_| NodeStatusApiError::InternalDatabaseError)
}
/// Inserts information into the database about a gateway that might have been unfairly unrewarded this epoch.
///
/// # Arguments
///
/// * `gateway`: mixnode information to insert.
pub(crate) async fn insert_possibly_unrewarded_gateway(
&self,
gateway: PossiblyUnrewardedGateway,
) -> Result<(), NodeStatusApiError> {
self.manager
.insert_possibly_unrewarded_gateway(gateway)
.await
.map_err(|_| NodeStatusApiError::InternalDatabaseError)
}
}
-15
View File
@@ -29,10 +29,8 @@ pub(crate) struct RewardingReport {
pub(crate) epoch_rewarding_id: i64,
pub(crate) eligible_mixnodes: i64,
pub(crate) eligible_gateways: i64,
pub(crate) possibly_unrewarded_mixnodes: i64,
pub(crate) possibly_unrewarded_gateways: i64,
}
pub(crate) struct FailedMixnodeRewardChunk {
@@ -47,16 +45,3 @@ pub(crate) struct PossiblyUnrewardedMixnode {
pub(crate) identity: String,
pub(crate) uptime: u8,
}
pub(crate) struct FailedGatewayRewardChunk {
// references particular epoch_rewarding (there can be multiple chunks in a rewarding epoch)
pub(crate) epoch_rewarding_id: i64,
pub(crate) error_message: String,
}
pub(crate) struct PossiblyUnrewardedGateway {
// references particular FailedGatewayRewardChunk (there can be multiple nodes in a chunk)
pub(crate) chunk_id: i64,
pub(crate) identity: String,
pub(crate) uptime: u8,
}