Skip to content
New issue

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

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

Already on GitHub? Sign in to your account

chore(drive): logs and metrics for withdrawal daily limit #2192

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

Filter by extension

Filter by extension

Conversations
Failed to load comments.
Loading
Jump to
Jump to file
Failed to load files.
Loading
Diff view
Diff view
Original file line number Diff line number Diff line change
Expand Up @@ -293,6 +293,8 @@ where
// required for signature verification (core height and quorum hash)
// Then we save unsigned transaction bytes to block execution context
// to be signed (on extend_vote), verified (on verify_vote) and broadcasted (on finalize_block)
// Also, the dequeued untiled transaction added to the broadcasted transaction queue to for further
// resigning in case of failures.
shumkov marked this conversation as resolved.
Show resolved Hide resolved
let unsigned_withdrawal_transaction_bytes = self
.dequeue_and_build_unsigned_withdrawal_transactions(
validator_set_quorum_hash,
Expand Down Expand Up @@ -329,12 +331,13 @@ where
// Corresponding withdrawal documents are changed from queued to pooled
self.pool_withdrawals_into_transactions_queue(
&block_info,
&last_committed_platform_state,
last_committed_platform_state,
Some(transaction),
platform_version,
)?;

// Cleans up the expired locks for withdrawal amounts
// to update daily withdrawal limit
// This is for example when we make a withdrawal for 30 Dash
// But we can only withdraw 1000 Dash a day
// after the withdrawal we should only be able to withdraw 970 Dash
Expand All @@ -350,7 +353,7 @@ where
let mut block_execution_context: BlockExecutionContext =
block_execution_context::v0::BlockExecutionContextV0 {
block_state_info: block_state_info.into(),
epoch_info: epoch_info.clone(),
epoch_info,
unsigned_withdrawal_transactions: unsigned_withdrawal_transaction_bytes,
block_platform_state,
proposer_results: None,
Expand Down
Original file line number Diff line number Diff line change
Expand Up @@ -19,18 +19,21 @@ where
platform_version: &PlatformVersion,
) -> Result<(), Error> {
// Currently Core only supports using the first 2 quorums (out of 24 for mainnet).
// For us, we just use the latest quorum to be extra safe.
// For extra safety, we use only the first quorum because our quorum info based
// on core chain locked height which is always late comparing with Core.
let Some(position_of_current_quorum) =
last_committed_platform_state.current_validator_set_position_in_list_by_most_recent()
else {
tracing::warn!("Current quorum not in current validator set, not making withdrawals");
tracing::warn!("Current quorum not in current validator set, do not pool withdrawals");

return Ok(());
};
if position_of_current_quorum != 0 {
tracing::debug!(
"Current quorum is not most recent, it is in position {}, not making withdrawals",
"Current quorum is not most recent, it is in position {}, do not pool withdrawals",
position_of_current_quorum
);

return Ok(());
}
// Just use the v1 as to not duplicate code
Expand Down
Original file line number Diff line number Diff line change
@@ -1,4 +1,5 @@
use dpp::block::block_info::BlockInfo;
use metrics::gauge;

use dpp::data_contract::accessors::v0::DataContractV0Getters;
use dpp::document::DocumentV0Getters;
Expand All @@ -9,6 +10,9 @@ use drive::grovedb::TransactionArg;
use dpp::system_data_contracts::withdrawals_contract;
use dpp::system_data_contracts::withdrawals_contract::v1::document_types::withdrawal;

use crate::metrics::{
GAUGE_CREDIT_WITHDRAWAL_LIMIT_AVAILABLE, GAUGE_CREDIT_WITHDRAWAL_LIMIT_TOTAL,
};
use crate::{
error::{execution::ExecutionError, Error},
platform_types::platform::Platform,
Expand Down Expand Up @@ -42,10 +46,16 @@ where
}

// Only take documents up to the withdrawal amount
let current_withdrawal_limit = self
let withdrawals_info = self
.drive
.calculate_current_withdrawal_limit(transaction, platform_version)?;

let current_withdrawal_limit = withdrawals_info.available();

// Store prometheus metrics
gauge!(GAUGE_CREDIT_WITHDRAWAL_LIMIT_AVAILABLE).set(current_withdrawal_limit as f64);
gauge!(GAUGE_CREDIT_WITHDRAWAL_LIMIT_TOTAL).set(withdrawals_info.daily_maximum as f64);

// Only process documents up to the current withdrawal limit.
let mut total_withdrawal_amount = 0u64;

Expand All @@ -65,8 +75,12 @@ where
))
})?;

// If adding this withdrawal would exceed the limit, stop processing further.
if potential_total_withdrawal_amount > current_withdrawal_limit {
// If adding this withdrawal would exceed the limit, stop processing further.
tracing::debug!(
"Pooling is limited due to daily withdrawals limit. {} credits left",
current_withdrawal_limit
);
break;
}

Expand Down
18 changes: 16 additions & 2 deletions packages/rs-drive-abci/src/metrics.rs
Original file line number Diff line number Diff line change
Expand Up @@ -6,7 +6,7 @@ use std::time::Duration;
use std::{sync::Once, time::Instant};

use dapi_grpc::tonic::Code;
use metrics::{counter, describe_counter, describe_histogram, histogram, Label};
use metrics::{counter, describe_counter, describe_gauge, describe_histogram, histogram, Label};
use metrics_exporter_prometheus::PrometheusBuilder;

/// Default Prometheus port (29090)
Expand All @@ -29,6 +29,10 @@ pub const LABEL_STATE_TRANSITION_NAME: &str = "st_name";
const LABEL_STATE_TRANSITION_EXECUTION_CODE: &str = "st_exec_code";
/// Metrics label to specify check tx mode: 0 - first time check, 1 - recheck
pub const LABEL_CHECK_TX_MODE: &str = "check_tx_mode";
/// Withdrawal daily limit available credits
pub const GAUGE_CREDIT_WITHDRAWAL_LIMIT_AVAILABLE: &str = "credit_withdrawal_limit_available";
/// Total withdrawal daily limit in credits
pub const GAUGE_CREDIT_WITHDRAWAL_LIMIT_TOTAL: &str = "credit_withdrawal_limit_total";

/// Error returned by metrics subsystem
#[derive(thiserror::Error, Debug)]
Expand Down Expand Up @@ -210,7 +214,17 @@ impl Prometheus {
HISTOGRAM_QUERY_DURATION,
metrics::Unit::Seconds,
"Duration of query request execution inside Drive per endpoint, in seconds"
)
);

describe_gauge!(
GAUGE_CREDIT_WITHDRAWAL_LIMIT_AVAILABLE,
"Available withdrawal limit for last 24 hours in credits"
);

describe_gauge!(
GAUGE_CREDIT_WITHDRAWAL_LIMIT_TOTAL,
"Total withdrawal limit for last 24 hours in credits"
);
});
}
}
Expand Down
Original file line number Diff line number Diff line change
Expand Up @@ -7,6 +7,22 @@ use platform_version::version::PlatformVersion;

mod v0;

/// Daily withdrawal limit information
#[derive(Debug, Clone, Copy, PartialEq, Eq)]
pub struct WithdrawalLimitInfo {
/// The total maximum withdrawal amount allowed in a 24-hour period.
pub daily_maximum: Credits,
/// The amount already withdrawn in the last 24 hours.
pub withdrawals_amount: Credits,
}

impl WithdrawalLimitInfo {
/// Calculates the available credits to withdraw
pub fn available(&self) -> Credits {
self.daily_maximum.saturating_sub(self.withdrawals_amount)
}
}

impl Drive {
/// Calculates the current withdrawal limit based on the total credits available in the platform
/// and the amount already withdrawn in the last 24 hours, using the appropriate version-specific logic.
Expand Down Expand Up @@ -34,7 +50,7 @@ impl Drive {
&self,
transaction: TransactionArg,
platform_version: &PlatformVersion,
) -> Result<Credits, Error> {
) -> Result<WithdrawalLimitInfo, Error> {
match platform_version
.drive
.methods
Expand Down
Original file line number Diff line number Diff line change
@@ -1,4 +1,5 @@
use crate::drive::balances::TOTAL_SYSTEM_CREDITS_STORAGE_KEY;
use crate::drive::identity::withdrawals::calculate_current_withdrawal_limit::WithdrawalLimitInfo;
use crate::drive::identity::withdrawals::paths::{
get_withdrawal_root_path, WITHDRAWAL_TRANSACTIONS_SUM_AMOUNT_TREE_KEY,
};
Expand All @@ -7,7 +8,6 @@ use crate::drive::Drive;
use crate::error::drive::DriveError;
use crate::error::Error;
use crate::util::grove_operations::DirectQueryType;
use dpp::fee::Credits;
use dpp::withdrawal::daily_withdrawal_limit::daily_withdrawal_limit;
use grovedb::TransactionArg;
use platform_version::version::PlatformVersion;
Expand Down Expand Up @@ -42,7 +42,7 @@ impl Drive {
&self,
transaction: TransactionArg,
platform_version: &PlatformVersion,
) -> Result<Credits, Error> {
) -> Result<WithdrawalLimitInfo, Error> {
// The current withdrawal limit has two components
// 1. The total maximum that we are allowed to do in 24 hours
// 2. The amount that we have already withdrawn in the last 24 hours
Expand Down Expand Up @@ -81,6 +81,9 @@ impl Drive {
))
})?;

Ok(daily_maximum.saturating_sub(withdrawal_amount_in_last_day))
Ok(WithdrawalLimitInfo {
daily_maximum,
withdrawals_amount: withdrawal_amount_in_last_day,
})
}
}
Original file line number Diff line number Diff line change
Expand Up @@ -9,7 +9,8 @@ use grovedb::TransactionArg;
use platform_version::version::PlatformVersion;

impl Drive {
/// Get specified amount of withdrawal transactions from the DB
/// Deque specified amount of untiled withdrawal transactions
/// and move them to broadcasted queue
pub fn dequeue_untied_withdrawal_transactions(
&self,
limit: u16,
Expand Down
Loading