diff --git a/packages/rs-dpp/src/withdrawal/daily_withdrawal_limit/mod.rs b/packages/rs-dpp/src/withdrawal/daily_withdrawal_limit/mod.rs index 997bd422621..3f964db0e41 100644 --- a/packages/rs-dpp/src/withdrawal/daily_withdrawal_limit/mod.rs +++ b/packages/rs-dpp/src/withdrawal/daily_withdrawal_limit/mod.rs @@ -12,9 +12,37 @@ pub fn daily_withdrawal_limit( ) -> Result { match platform_version.dpp.methods.daily_withdrawal_limit { 0 => Ok(daily_withdrawal_limit_v0(total_credits_in_platform)), - 1 => Ok(v1::daily_withdrawal_limit_v1()), + 1 => Ok(v1::daily_withdrawal_limit_v1(platform_version)), v => Err(ProtocolError::UnknownVersionError(format!( "Unknown daily_withdrawal_limit version {v}" ))), } } + +#[cfg(test)] +mod tests { + use super::*; + use crate::dash_to_credits; + + #[test] + fn should_double_flat_daily_withdrawal_limit_at_protocol_version_14() { + let v13 = PlatformVersion::get(13).expect("expected protocol version 13"); + let v14 = PlatformVersion::get(14).expect("expected protocol version 14"); + + // Both flat limits are independent of the credits held in Platform. + for total_credits in [ + dash_to_credits!(50), + dash_to_credits!(5000), + dash_to_credits!(1000000), + ] { + assert_eq!( + daily_withdrawal_limit(total_credits, v13).expect("expected v13 limit"), + dash_to_credits!(2000) + ); + assert_eq!( + daily_withdrawal_limit(total_credits, v14).expect("expected v14 limit"), + dash_to_credits!(4000) + ); + } + } +} diff --git a/packages/rs-dpp/src/withdrawal/daily_withdrawal_limit/v1/mod.rs b/packages/rs-dpp/src/withdrawal/daily_withdrawal_limit/v1/mod.rs index 56112338a6d..5f2e4537573 100644 --- a/packages/rs-dpp/src/withdrawal/daily_withdrawal_limit/v1/mod.rs +++ b/packages/rs-dpp/src/withdrawal/daily_withdrawal_limit/v1/mod.rs @@ -1,8 +1,9 @@ use crate::fee::Credits; +use platform_version::version::PlatformVersion; -/// Set constant withdrawal daily limit to 2000 Dash -/// that corresponds to the limit in Core v22. -pub const fn daily_withdrawal_limit_v1() -> Credits { - // 2000 Dash - 200_000_000_000_000 +/// Flat daily withdrawal limit, read from the protocol version's system limits +/// (`SystemLimits::daily_withdrawal_limit`): 2000 Dash up to protocol version 13 +/// (the limit in Core v22), 4000 Dash from protocol version 14 (Core v24). +pub fn daily_withdrawal_limit_v1(platform_version: &PlatformVersion) -> Credits { + platform_version.system_limits.daily_withdrawal_limit } diff --git a/packages/rs-platform-version/src/version/mocks/v2_test.rs b/packages/rs-platform-version/src/version/mocks/v2_test.rs index 4286f9fb97d..5e8cce5f0d1 100644 --- a/packages/rs-platform-version/src/version/mocks/v2_test.rs +++ b/packages/rs-platform-version/src/version/mocks/v2_test.rs @@ -509,6 +509,7 @@ pub const TEST_PLATFORM_V2: PlatformVersion = PlatformVersion { withdrawal_transactions_per_block_limit: 4, retry_signing_expired_withdrawal_documents_per_block_limit: 1, max_withdrawal_amount: 50_000_000_000_000, + daily_withdrawal_limit: 200_000_000_000_000, //2000 Dash min_withdrawal_amount: 190_000, max_contract_group_size: 256, max_token_redemption_cycles: 128, diff --git a/packages/rs-platform-version/src/version/system_limits/mod.rs b/packages/rs-platform-version/src/version/system_limits/mod.rs index 5ceb6fceaf9..87ce1718742 100644 --- a/packages/rs-platform-version/src/version/system_limits/mod.rs +++ b/packages/rs-platform-version/src/version/system_limits/mod.rs @@ -1,6 +1,7 @@ pub mod v1; pub mod v2; pub mod v3; +pub mod v4; #[derive(Clone, Debug, Default)] pub struct SystemLimits { @@ -57,6 +58,12 @@ pub struct SystemLimits { pub withdrawal_transactions_per_block_limit: u16, pub retry_signing_expired_withdrawal_documents_per_block_limit: u16, pub max_withdrawal_amount: u64, + /// Flat cap (in credits) on the total amount Platform pools into asset unlock transactions + /// per 24 hours. Read by `daily_withdrawal_limit` method version 1 (protocol version 8 and + /// later); method version 0 (protocol versions 1–7) derived the limit from the total credits + /// in Platform instead and ignores this field. Versioned: see `daily_withdrawal_limit` in + /// each `SYSTEM_LIMITS_V*`. + pub daily_withdrawal_limit: u64, /// Minimum net amount (in credits) a withdrawal may send to Core, shared by the /// transparent (identity + address) and shielded withdrawal paths. The dust floor that /// keeps Core from rejecting the resulting `TxOut`. Versioned: see `min_withdrawal_amount` diff --git a/packages/rs-platform-version/src/version/system_limits/v1.rs b/packages/rs-platform-version/src/version/system_limits/v1.rs index f36f5dd05f8..39516e2f0f8 100644 --- a/packages/rs-platform-version/src/version/system_limits/v1.rs +++ b/packages/rs-platform-version/src/version/system_limits/v1.rs @@ -26,7 +26,8 @@ pub const SYSTEM_LIMITS_V1: SystemLimits = SystemLimits { max_transitions_in_documents_batch: 1, withdrawal_transactions_per_block_limit: 4, retry_signing_expired_withdrawal_documents_per_block_limit: 1, - max_withdrawal_amount: 50_000_000_000_000, //500 Dash + max_withdrawal_amount: 50_000_000_000_000, //500 Dash + daily_withdrawal_limit: 200_000_000_000_000, //2000 Dash (Core v22 limit; unused before protocol version 8) // = dpp MIN_WITHDRAWAL_AMOUNT: ASSET_UNLOCK_TX_SIZE(190) * MIN_CORE_FEE_PER_BYTE(1) // * CREDITS_PER_DUFF(1000) = 190_000 credits = 190 duffs. min_withdrawal_amount: 190_000, diff --git a/packages/rs-platform-version/src/version/system_limits/v2.rs b/packages/rs-platform-version/src/version/system_limits/v2.rs index 1fcb2205aa0..3c1b74aa944 100644 --- a/packages/rs-platform-version/src/version/system_limits/v2.rs +++ b/packages/rs-platform-version/src/version/system_limits/v2.rs @@ -16,8 +16,9 @@ pub const SYSTEM_LIMITS_V2: SystemLimits = SystemLimits { max_transitions_in_documents_batch: 1, withdrawal_transactions_per_block_limit: 4, retry_signing_expired_withdrawal_documents_per_block_limit: 1, - max_withdrawal_amount: 50_000_000_000_000, //500 Dash - min_withdrawal_amount: 1_000_000, //1000 duffs (raised from 190 in v12) + max_withdrawal_amount: 50_000_000_000_000, //500 Dash + daily_withdrawal_limit: 200_000_000_000_000, //2000 Dash (Core v22 limit) + min_withdrawal_amount: 1_000_000, //1000 duffs (raised from 190 in v12) max_contract_group_size: 256, max_token_redemption_cycles: 128, // NOTE: the Halo 2 proof grows with the action count (~2,273 B/action on diff --git a/packages/rs-platform-version/src/version/system_limits/v3.rs b/packages/rs-platform-version/src/version/system_limits/v3.rs index 99472f10562..7002be075e8 100644 --- a/packages/rs-platform-version/src/version/system_limits/v3.rs +++ b/packages/rs-platform-version/src/version/system_limits/v3.rs @@ -1,6 +1,6 @@ use crate::version::system_limits::SystemLimits; -/// System limits for protocol version 13 and above. +/// System limits for protocol version 13. /// /// Identical to [`super::v2::SYSTEM_LIMITS_V2`] except that `max_document_value_depth` is set: /// document property values are bounded to 256 nested containers, enforced by the wire decoder @@ -18,8 +18,9 @@ pub const SYSTEM_LIMITS_V3: SystemLimits = SystemLimits { max_transitions_in_documents_batch: 1, withdrawal_transactions_per_block_limit: 4, retry_signing_expired_withdrawal_documents_per_block_limit: 1, - max_withdrawal_amount: 50_000_000_000_000, //500 Dash - min_withdrawal_amount: 1_000_000, //1000 duffs (raised from 190 in v12) + max_withdrawal_amount: 50_000_000_000_000, //500 Dash + daily_withdrawal_limit: 200_000_000_000_000, //2000 Dash (Core v22 limit) + min_withdrawal_amount: 1_000_000, //1000 duffs (raised from 190 in v12) max_contract_group_size: 256, max_token_redemption_cycles: 128, // NOTE: the Halo 2 proof grows with the action count (~2,273 B/action on diff --git a/packages/rs-platform-version/src/version/system_limits/v4.rs b/packages/rs-platform-version/src/version/system_limits/v4.rs new file mode 100644 index 00000000000..485753e458c --- /dev/null +++ b/packages/rs-platform-version/src/version/system_limits/v4.rs @@ -0,0 +1,34 @@ +use crate::version::system_limits::SystemLimits; + +/// System limits for protocol version 14 and above. +/// +/// Identical to [`super::v3::SYSTEM_LIMITS_V3`] except that `daily_withdrawal_limit` is raised +/// from 2000 Dash to 4000 Dash, matching Core's doubled credit-pool unlock limit +/// (`LimitAmountV24`, DIP-0165, dashpay/dash#6662). v13 is already live on networks with the +/// 2000 Dash limit, so the change gates here. +pub const SYSTEM_LIMITS_V4: SystemLimits = SystemLimits { + estimated_contract_max_serialized_size: 16384, + max_field_value_size: 5120, //5 KiB + // Use the protocol's existing data-contract schema-depth ceiling as the conservative + // instance budget, bounding pre-schema work well above known document requirements. + max_document_value_depth: Some(256), + max_state_transition_size: 20480, //20 KiB + // Load-bearing for state correctness, not just for throughput — see + // SystemLimits::max_transitions_in_documents_batch and SYSTEM_LIMITS_V1. + max_transitions_in_documents_batch: 1, + withdrawal_transactions_per_block_limit: 4, + retry_signing_expired_withdrawal_documents_per_block_limit: 1, + max_withdrawal_amount: 50_000_000_000_000, //500 Dash + daily_withdrawal_limit: 400_000_000_000_000, //4000 Dash (Core v24 limit; raised from 2000 in v14) + min_withdrawal_amount: 1_000_000, //1000 duffs (raised from 190 in v12) + max_contract_group_size: 256, + max_token_redemption_cycles: 128, + // NOTE: the Halo 2 proof grows with the action count (~2,273 B/action on + // top of the 408 B serialized action), so a transition's on-wire size is + // ~2,681 B per action + ~2,930 B fixed (measured: 2 actions → 8,294 B, + // 6 → 19,018 B). The effective per-transition action bound under the + // 20 KiB `max_state_transition_size` is therefore 6, NOT this cap — 16 + // only becomes reachable if the size limit is raised. Pinned by dpp's + // `seed_pool_batch_fits_max_state_transition_size` signing test. + max_shielded_transition_actions: 16, +}; diff --git a/packages/rs-platform-version/src/version/v14.rs b/packages/rs-platform-version/src/version/v14.rs index cfa1f2a0efc..84f2bd3d306 100644 --- a/packages/rs-platform-version/src/version/v14.rs +++ b/packages/rs-platform-version/src/version/v14.rs @@ -25,12 +25,12 @@ use crate::version::drive_versions::v9::DRIVE_VERSION_V9; use crate::version::fee::v2::FEE_VERSION2; use crate::version::protocol_version::PlatformVersion; use crate::version::system_data_contract_versions::v3::SYSTEM_DATA_CONTRACT_VERSIONS_V3; -use crate::version::system_limits::v3::SYSTEM_LIMITS_V3; +use crate::version::system_limits::v4::SYSTEM_LIMITS_V4; use crate::version::ProtocolVersion; pub const PROTOCOL_VERSION_14: ProtocolVersion = 14; -/// v14 hosts three consensus changes: +/// v14 hosts four consensus changes: /// /// 1. **Contract-level ranked aggregates** (this branch): an index can /// declare that its groups are rankable by an aggregate, so a query like @@ -66,6 +66,19 @@ pub const PROTOCOL_VERSION_14: ProtocolVersion = 14; /// the contest was created on — which halts the chain when that poll /// ends — or open a contest for a document that is not a contested /// resource at all. +/// 4. **Daily withdrawal limit 2000 → 4000 Dash**: `SYSTEM_LIMITS_V4` raises +/// `daily_withdrawal_limit`, doubling the amount of credits Platform pools +/// into asset unlock transactions per 24 hours (the `daily_withdrawal_limit` +/// method stays at v1, which reads that system limit). This +/// mirrors Core's doubled credit-pool unlock limit (`LimitAmountV24`, +/// DIP-0165, dashpay/dash#6662), which Core gates on its own +/// `DEPLOYMENT_V24` hard fork. v14 does not have to wait for that fork: +/// pre-V24 Core caps unlocks at `LimitAmountV22` (2000 Dash) per *block* +/// (no sliding window — the window only arrives with V24), and its mempool +/// does not check the amount at all, so a day's 4000 Dash is still fully +/// minable; unlocks above 2000 in one Core block simply wait for the next +/// one. After V24, Core enforces 4000 Dash per 576-block window, which +/// matches this limit. /// /// The first two are orthogonal by construction: the ranked upgrade decides the /// *property-name* tree type, the demotion decides the *value* tree type @@ -75,8 +88,9 @@ pub const PROTOCOL_VERSION_14: ProtocolVersion = 14; /// shared-prefix shapes. /// /// Until a contract uses the ranked grammar, the only v14 behavior changes -/// are the shared-prefix fix, the contested-index cross-check and the -/// index-reorder schema-compatibility fix; everything else matches v13: +/// are the shared-prefix fix, the contested-index cross-check, the +/// index-reorder schema-compatibility fix and the doubled daily withdrawal +/// limit; everything else matches v13: /// /// * `CONTRACT_VERSIONS_V6` points `document_type_schema` at the v3 document /// meta-schema, which hosts the ranked index keywords @@ -150,7 +164,7 @@ pub const PLATFORM_V14: PlatformVersion = PlatformVersion { }, system_data_contracts: SYSTEM_DATA_CONTRACT_VERSIONS_V3, // changed: DashPay v2 adds profile payment address fields (DIP-33) fee_version: FEE_VERSION2, - system_limits: SYSTEM_LIMITS_V3, + system_limits: SYSTEM_LIMITS_V4, // changed: daily_withdrawal_limit 2000 → 4000 Dash, matching Core's LimitAmountV24 consensus: ConsensusVersions { tenderdash_consensus_version: 1, },