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:
committed by
GitHub
parent
ef88ce9252
commit
b19528d47e
Vendored
+1
-66
@@ -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(),
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
Vendored
-7
@@ -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))
|
||||
}
|
||||
|
||||
@@ -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())
|
||||
}
|
||||
}
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
@@ -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),
|
||||
|
||||
|
||||
@@ -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
|
||||
|
||||
@@ -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
|
||||
|
||||
@@ -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)
|
||||
}
|
||||
}
|
||||
|
||||
@@ -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,
|
||||
}
|
||||
|
||||
Reference in New Issue
Block a user