From ab6aeea515ee643c7cc01c46119fb5a8620668b8 Mon Sep 17 00:00:00 2001 From: Lukasz Klimek <842586+lklimek@users.noreply.github.com> Date: Wed, 15 Apr 2026 15:39:58 +0200 Subject: [PATCH 1/2] fix(dpp): reduce max_shielded_transition_actions from 100 to 16 (#3411) The previous limit of 100 actions allowed state transitions up to ~46 KB, far exceeding the 20 KiB max_state_transition_size. Each SerializedAction is 408 bytes; at 16 actions the total is ~12 KB with comfortable margin. Co-Authored-By: Claude Opus 4.6 (1M context) --- .../state_transitions/shield/tests.rs | 10 +++++----- .../state_transitions/shield_from_asset_lock/tests.rs | 10 +++++----- .../state_transitions/shielded_transfer/tests.rs | 10 +++++----- .../state_transitions/shielded_withdrawal/tests.rs | 11 +++++------ .../state_transitions/unshield/tests.rs | 11 +++++------ .../rs-platform-version/src/version/mocks/v2_test.rs | 2 +- .../src/version/system_limits/v1.rs | 3 ++- 7 files changed, 28 insertions(+), 29 deletions(-) diff --git a/packages/rs-drive-abci/src/execution/validation/state_transition/state_transitions/shield/tests.rs b/packages/rs-drive-abci/src/execution/validation/state_transition/state_transitions/shield/tests.rs index c1c68667c4c..8ca7e84b407 100644 --- a/packages/rs-drive-abci/src/execution/validation/state_transition/state_transitions/shield/tests.rs +++ b/packages/rs-drive-abci/src/execution/validation/state_transition/state_transitions/shield/tests.rs @@ -273,18 +273,18 @@ mod tests { ); } - /// Tests validate_structure directly because 101 actions exceed the - /// max_state_transition_size (20KB) before reaching the actions count check - /// in the full pipeline. + /// Tests validate_structure directly because 17 actions could exceed + /// max_state_transition_size (20KB) with real proofs before reaching + /// the actions count check in the full pipeline. #[test] fn test_too_many_actions_returns_error() { use dpp::state_transition::StateTransitionStructureValidation; let platform_version = PlatformVersion::latest(); - // 101 actions exceeds max_shielded_transition_actions (100) + // 17 actions exceeds max_shielded_transition_actions (16) let actions: Vec = - (0..101).map(|_| create_dummy_serialized_action()).collect(); + (0..17).map(|_| create_dummy_serialized_action()).collect(); let transition = ShieldTransitionV0 { inputs: BTreeMap::new(), diff --git a/packages/rs-drive-abci/src/execution/validation/state_transition/state_transitions/shield_from_asset_lock/tests.rs b/packages/rs-drive-abci/src/execution/validation/state_transition/state_transitions/shield_from_asset_lock/tests.rs index ac182357636..1465f111083 100644 --- a/packages/rs-drive-abci/src/execution/validation/state_transition/state_transitions/shield_from_asset_lock/tests.rs +++ b/packages/rs-drive-abci/src/execution/validation/state_transition/state_transitions/shield_from_asset_lock/tests.rs @@ -158,18 +158,18 @@ mod tests { ); } - /// Tests validate_structure directly because 101 actions exceed the - /// max_state_transition_size (20KB) before reaching the actions count check - /// in the full pipeline. + /// Tests validate_structure directly because 17 actions could exceed + /// max_state_transition_size (20KB) with real proofs before reaching + /// the actions count check in the full pipeline. #[test] fn test_too_many_actions_returns_error() { use dpp::state_transition::StateTransitionStructureValidation; let platform_version = PlatformVersion::latest(); - // 101 actions exceeds max_shielded_transition_actions (100) + // 17 actions exceeds max_shielded_transition_actions (16) let actions: Vec = - (0..101).map(|_| create_dummy_serialized_action()).collect(); + (0..17).map(|_| create_dummy_serialized_action()).collect(); let transition = ShieldFromAssetLockTransitionV0 { asset_lock_proof: instant_asset_lock_proof_fixture(None, None), diff --git a/packages/rs-drive-abci/src/execution/validation/state_transition/state_transitions/shielded_transfer/tests.rs b/packages/rs-drive-abci/src/execution/validation/state_transition/state_transitions/shielded_transfer/tests.rs index d700debd995..030fd84b321 100644 --- a/packages/rs-drive-abci/src/execution/validation/state_transition/state_transitions/shielded_transfer/tests.rs +++ b/packages/rs-drive-abci/src/execution/validation/state_transition/state_transitions/shielded_transfer/tests.rs @@ -84,18 +84,18 @@ mod tests { ); } - /// Tests validate_structure directly because 101 actions exceed the - /// max_state_transition_size (20KB) before reaching the actions count check - /// in the full pipeline. + /// Tests validate_structure directly because 17 actions could exceed + /// max_state_transition_size (20KB) with real proofs before reaching + /// the actions count check in the full pipeline. #[test] fn test_too_many_actions_returns_error() { use dpp::state_transition::StateTransitionStructureValidation; let platform_version = PlatformVersion::latest(); - // 101 actions exceeds max_shielded_transition_actions (100) + // 17 actions exceeds max_shielded_transition_actions (16) let actions: Vec = - (0..101).map(|_| create_dummy_serialized_action()).collect(); + (0..17).map(|_| create_dummy_serialized_action()).collect(); let transition = ShieldedTransferTransitionV0 { actions, diff --git a/packages/rs-drive-abci/src/execution/validation/state_transition/state_transitions/shielded_withdrawal/tests.rs b/packages/rs-drive-abci/src/execution/validation/state_transition/state_transitions/shielded_withdrawal/tests.rs index 328bcc774bc..bab788125c9 100644 --- a/packages/rs-drive-abci/src/execution/validation/state_transition/state_transitions/shielded_withdrawal/tests.rs +++ b/packages/rs-drive-abci/src/execution/validation/state_transition/state_transitions/shielded_withdrawal/tests.rs @@ -105,17 +105,16 @@ mod tests { #[test] fn test_too_many_actions_returns_error() { - // NOTE: We call validate_structure directly because 101 actions (~41KB) - // exceeds max_state_transition_size (20KB) before the actions count check - // can trigger. This means ShieldedTooManyActionsError is effectively - // unreachable through the normal pipeline. + // NOTE: We call validate_structure directly because 17 actions (~7KB) + // could exceed max_state_transition_size (20KB) with real proofs before + // the actions count check can trigger. use dpp::state_transition::StateTransitionStructureValidation; let platform_version = PlatformVersion::latest(); - // 101 actions exceeds max_shielded_transition_actions (100) + // 17 actions exceeds max_shielded_transition_actions (16) let actions: Vec = - (0..101).map(|_| create_dummy_serialized_action()).collect(); + (0..17).map(|_| create_dummy_serialized_action()).collect(); let transition = ShieldedWithdrawalTransitionV0 { actions, diff --git a/packages/rs-drive-abci/src/execution/validation/state_transition/state_transitions/unshield/tests.rs b/packages/rs-drive-abci/src/execution/validation/state_transition/state_transitions/unshield/tests.rs index 733cfe6df01..06dd1cd6278 100644 --- a/packages/rs-drive-abci/src/execution/validation/state_transition/state_transitions/unshield/tests.rs +++ b/packages/rs-drive-abci/src/execution/validation/state_transition/state_transitions/unshield/tests.rs @@ -96,17 +96,16 @@ mod tests { #[test] fn test_too_many_actions_returns_error() { - // NOTE: We call validate_structure directly because 101 actions (~41KB) - // exceeds max_state_transition_size (20KB) before the actions count check - // can trigger. This means ShieldedTooManyActionsError is effectively - // unreachable through the normal pipeline. + // NOTE: We call validate_structure directly because 17 actions (~7KB) + // could exceed max_state_transition_size (20KB) with real proofs before + // the actions count check can trigger. use dpp::state_transition::StateTransitionStructureValidation; let platform_version = PlatformVersion::latest(); - // 101 actions exceeds max_shielded_transition_actions (100) + // 17 actions exceeds max_shielded_transition_actions (16) let actions: Vec = - (0..101).map(|_| create_dummy_serialized_action()).collect(); + (0..17).map(|_| create_dummy_serialized_action()).collect(); let transition = UnshieldTransitionV0 { output_address: create_output_address(), 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 d7eca7f5318..2871e55c336 100644 --- a/packages/rs-platform-version/src/version/mocks/v2_test.rs +++ b/packages/rs-platform-version/src/version/mocks/v2_test.rs @@ -518,7 +518,7 @@ pub const TEST_PLATFORM_V2: PlatformVersion = PlatformVersion { max_withdrawal_amount: 50_000_000_000_000, max_contract_group_size: 256, max_token_redemption_cycles: 128, - max_shielded_transition_actions: 100, + max_shielded_transition_actions: 16, }, consensus: ConsensusVersions { tenderdash_consensus_version: 0, 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 9b11657710c..3421ba58076 100644 --- a/packages/rs-platform-version/src/version/system_limits/v1.rs +++ b/packages/rs-platform-version/src/version/system_limits/v1.rs @@ -10,5 +10,6 @@ pub const SYSTEM_LIMITS_V1: SystemLimits = SystemLimits { max_withdrawal_amount: 50_000_000_000_000, //500 Dash max_contract_group_size: 256, max_token_redemption_cycles: 128, - max_shielded_transition_actions: 100, + // 16 actions x 408 bytes + ~5,305 bytes overhead = ~11,833 bytes (within 20 KiB max_state_transition_size) + max_shielded_transition_actions: 16, }; From 5de5f7a2aa8234b809f57aab4613f3e8998c7535 Mon Sep 17 00:00:00 2001 From: Lukasz Klimek <842586+lklimek@users.noreply.github.com> Date: Mon, 20 Apr 2026 13:42:49 +0200 Subject: [PATCH 2/2] docs(drive-abci): fix stale size rationale in shielded action-count tests MIME-Version: 1.0 Content-Type: text/plain; charset=UTF-8 Content-Transfer-Encoding: 8bit Replace the outdated "17 actions could exceed 20KB" explanation — per the sizing math documented alongside max_shielded_transition_actions=16, 17 actions is ~12KB, well under the 20 KiB state transition size cap. The real reason for calling validate_structure directly is to exercise the action-count check in isolation from the full processing pipeline. Addresses Copilot PR review on #3498. --- .../state_transition/state_transitions/shield/tests.rs | 6 +++--- .../state_transitions/shield_from_asset_lock/tests.rs | 6 +++--- .../state_transitions/shielded_transfer/tests.rs | 6 +++--- .../state_transitions/shielded_withdrawal/tests.rs | 6 +++--- .../state_transition/state_transitions/unshield/tests.rs | 6 +++--- 5 files changed, 15 insertions(+), 15 deletions(-) diff --git a/packages/rs-drive-abci/src/execution/validation/state_transition/state_transitions/shield/tests.rs b/packages/rs-drive-abci/src/execution/validation/state_transition/state_transitions/shield/tests.rs index 8ca7e84b407..82eb063d306 100644 --- a/packages/rs-drive-abci/src/execution/validation/state_transition/state_transitions/shield/tests.rs +++ b/packages/rs-drive-abci/src/execution/validation/state_transition/state_transitions/shield/tests.rs @@ -273,9 +273,9 @@ mod tests { ); } - /// Tests validate_structure directly because 17 actions could exceed - /// max_state_transition_size (20KB) with real proofs before reaching - /// the actions count check in the full pipeline. + /// Tests `validate_structure` directly to exercise the + /// `max_shielded_transition_actions` check in isolation, without + /// depending on the full transition-processing pipeline. #[test] fn test_too_many_actions_returns_error() { use dpp::state_transition::StateTransitionStructureValidation; diff --git a/packages/rs-drive-abci/src/execution/validation/state_transition/state_transitions/shield_from_asset_lock/tests.rs b/packages/rs-drive-abci/src/execution/validation/state_transition/state_transitions/shield_from_asset_lock/tests.rs index 1465f111083..ae914d32fd1 100644 --- a/packages/rs-drive-abci/src/execution/validation/state_transition/state_transitions/shield_from_asset_lock/tests.rs +++ b/packages/rs-drive-abci/src/execution/validation/state_transition/state_transitions/shield_from_asset_lock/tests.rs @@ -158,9 +158,9 @@ mod tests { ); } - /// Tests validate_structure directly because 17 actions could exceed - /// max_state_transition_size (20KB) with real proofs before reaching - /// the actions count check in the full pipeline. + /// Tests `validate_structure` directly to exercise the + /// `max_shielded_transition_actions` check in isolation, without + /// depending on the full transition-processing pipeline. #[test] fn test_too_many_actions_returns_error() { use dpp::state_transition::StateTransitionStructureValidation; diff --git a/packages/rs-drive-abci/src/execution/validation/state_transition/state_transitions/shielded_transfer/tests.rs b/packages/rs-drive-abci/src/execution/validation/state_transition/state_transitions/shielded_transfer/tests.rs index 030fd84b321..f6f1039f491 100644 --- a/packages/rs-drive-abci/src/execution/validation/state_transition/state_transitions/shielded_transfer/tests.rs +++ b/packages/rs-drive-abci/src/execution/validation/state_transition/state_transitions/shielded_transfer/tests.rs @@ -84,9 +84,9 @@ mod tests { ); } - /// Tests validate_structure directly because 17 actions could exceed - /// max_state_transition_size (20KB) with real proofs before reaching - /// the actions count check in the full pipeline. + /// Tests `validate_structure` directly to exercise the + /// `max_shielded_transition_actions` check in isolation, without + /// depending on the full transition-processing pipeline. #[test] fn test_too_many_actions_returns_error() { use dpp::state_transition::StateTransitionStructureValidation; diff --git a/packages/rs-drive-abci/src/execution/validation/state_transition/state_transitions/shielded_withdrawal/tests.rs b/packages/rs-drive-abci/src/execution/validation/state_transition/state_transitions/shielded_withdrawal/tests.rs index bab788125c9..52600811fab 100644 --- a/packages/rs-drive-abci/src/execution/validation/state_transition/state_transitions/shielded_withdrawal/tests.rs +++ b/packages/rs-drive-abci/src/execution/validation/state_transition/state_transitions/shielded_withdrawal/tests.rs @@ -105,9 +105,9 @@ mod tests { #[test] fn test_too_many_actions_returns_error() { - // NOTE: We call validate_structure directly because 17 actions (~7KB) - // could exceed max_state_transition_size (20KB) with real proofs before - // the actions count check can trigger. + // NOTE: We call validate_structure directly to exercise the + // max_shielded_transition_actions check in isolation, without + // depending on the full transition-processing pipeline. use dpp::state_transition::StateTransitionStructureValidation; let platform_version = PlatformVersion::latest(); diff --git a/packages/rs-drive-abci/src/execution/validation/state_transition/state_transitions/unshield/tests.rs b/packages/rs-drive-abci/src/execution/validation/state_transition/state_transitions/unshield/tests.rs index 06dd1cd6278..fd990009e5d 100644 --- a/packages/rs-drive-abci/src/execution/validation/state_transition/state_transitions/unshield/tests.rs +++ b/packages/rs-drive-abci/src/execution/validation/state_transition/state_transitions/unshield/tests.rs @@ -96,9 +96,9 @@ mod tests { #[test] fn test_too_many_actions_returns_error() { - // NOTE: We call validate_structure directly because 17 actions (~7KB) - // could exceed max_state_transition_size (20KB) with real proofs before - // the actions count check can trigger. + // NOTE: We call validate_structure directly to exercise the + // max_shielded_transition_actions check in isolation, without + // depending on the full transition-processing pipeline. use dpp::state_transition::StateTransitionStructureValidation; let platform_version = PlatformVersion::latest();