diff --git a/packages/rs-drive-abci/src/execution/engine/run_block_proposal/v0/mod.rs b/packages/rs-drive-abci/src/execution/engine/run_block_proposal/v0/mod.rs index 1ae4a1e6392..9c45694f6c4 100644 --- a/packages/rs-drive-abci/src/execution/engine/run_block_proposal/v0/mod.rs +++ b/packages/rs-drive-abci/src/execution/engine/run_block_proposal/v0/mod.rs @@ -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. let unsigned_withdrawal_transaction_bytes = self .dequeue_and_build_unsigned_withdrawal_transactions( validator_set_quorum_hash, @@ -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 @@ -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, diff --git a/packages/rs-drive-abci/src/execution/platform_events/withdrawals/pool_withdrawals_into_transactions_queue/v0/mod.rs b/packages/rs-drive-abci/src/execution/platform_events/withdrawals/pool_withdrawals_into_transactions_queue/v0/mod.rs index 01c84035f65..610d8e3fcca 100644 --- a/packages/rs-drive-abci/src/execution/platform_events/withdrawals/pool_withdrawals_into_transactions_queue/v0/mod.rs +++ b/packages/rs-drive-abci/src/execution/platform_events/withdrawals/pool_withdrawals_into_transactions_queue/v0/mod.rs @@ -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 diff --git a/packages/rs-drive-abci/src/execution/platform_events/withdrawals/pool_withdrawals_into_transactions_queue/v1/mod.rs b/packages/rs-drive-abci/src/execution/platform_events/withdrawals/pool_withdrawals_into_transactions_queue/v1/mod.rs index cf7c3cec299..b0b0f99e658 100644 --- a/packages/rs-drive-abci/src/execution/platform_events/withdrawals/pool_withdrawals_into_transactions_queue/v1/mod.rs +++ b/packages/rs-drive-abci/src/execution/platform_events/withdrawals/pool_withdrawals_into_transactions_queue/v1/mod.rs @@ -1,4 +1,5 @@ use dpp::block::block_info::BlockInfo; +use metrics::gauge; use dpp::data_contract::accessors::v0::DataContractV0Getters; use dpp::document::DocumentV0Getters; @@ -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, @@ -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; @@ -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; } diff --git a/packages/rs-drive-abci/src/metrics.rs b/packages/rs-drive-abci/src/metrics.rs index 5c90ec25019..943f0d5aaed 100644 --- a/packages/rs-drive-abci/src/metrics.rs +++ b/packages/rs-drive-abci/src/metrics.rs @@ -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) @@ -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)] @@ -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" + ); }); } } diff --git a/packages/rs-drive/src/drive/identity/withdrawals/calculate_current_withdrawal_limit/mod.rs b/packages/rs-drive/src/drive/identity/withdrawals/calculate_current_withdrawal_limit/mod.rs index 172eda82c97..1d31584f69b 100644 --- a/packages/rs-drive/src/drive/identity/withdrawals/calculate_current_withdrawal_limit/mod.rs +++ b/packages/rs-drive/src/drive/identity/withdrawals/calculate_current_withdrawal_limit/mod.rs @@ -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. @@ -34,7 +50,7 @@ impl Drive { &self, transaction: TransactionArg, platform_version: &PlatformVersion, - ) -> Result { + ) -> Result { match platform_version .drive .methods diff --git a/packages/rs-drive/src/drive/identity/withdrawals/calculate_current_withdrawal_limit/v0/mod.rs b/packages/rs-drive/src/drive/identity/withdrawals/calculate_current_withdrawal_limit/v0/mod.rs index f7610ec941c..c4f2316d3fe 100644 --- a/packages/rs-drive/src/drive/identity/withdrawals/calculate_current_withdrawal_limit/v0/mod.rs +++ b/packages/rs-drive/src/drive/identity/withdrawals/calculate_current_withdrawal_limit/v0/mod.rs @@ -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, }; @@ -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; @@ -42,7 +42,7 @@ impl Drive { &self, transaction: TransactionArg, platform_version: &PlatformVersion, - ) -> Result { + ) -> Result { // 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 @@ -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, + }) } } diff --git a/packages/rs-drive/src/drive/identity/withdrawals/transaction/queue/dequeue_untied_withdrawal_transactions/mod.rs b/packages/rs-drive/src/drive/identity/withdrawals/transaction/queue/dequeue_untied_withdrawal_transactions/mod.rs index 3423114aaf4..cdc4672759d 100644 --- a/packages/rs-drive/src/drive/identity/withdrawals/transaction/queue/dequeue_untied_withdrawal_transactions/mod.rs +++ b/packages/rs-drive/src/drive/identity/withdrawals/transaction/queue/dequeue_untied_withdrawal_transactions/mod.rs @@ -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,