Skip to content

feat(dpp): add max_asset_lock_transaction_inputs limit to prevent stuck funds#3491

Open
lklimek wants to merge 1 commit intov3.1-devfrom
feat/max-asset-lock-inputs
Open

feat(dpp): add max_asset_lock_transaction_inputs limit to prevent stuck funds#3491
lklimek wants to merge 1 commit intov3.1-devfrom
feat/max-asset-lock-inputs

Conversation

@lklimek
Copy link
Copy Markdown
Contributor

@lklimek lklimek commented Apr 14, 2026

Issue being fixed or feature implemented

Fixes #3399

Imagine you are a user funding a Platform address with tDASH accumulated from many small mining rewards. You send 400 tDASH, the Core transaction succeeds — but Platform rejects the state transition with a cryptic "Tx too large" error. Your funds are stuck: gone from Core wallet, never credited to Platform. This change catches the problem before the Core broadcast, with a clear error message telling you to consolidate UTXOs first.

What was done?

Added a max_asset_lock_transaction_inputs limit (100) to prevent asset lock transactions from exceeding Platform's 20KB max_state_transition_size limit.

Size math: Each input adds ~184 bytes to the state transition (148 bytes for the transaction input + 36 bytes for the InstantLock outpoint). At 100 inputs the total is ~18,877 bytes — fits within the 20,480 byte limit with ~1,600 bytes (~8%) margin.

Changes across 3 packages:

rs-platform-version:

  • Added max_asset_lock_transaction_inputs: u16 to IdentityTransitionAssetLockVersions
  • Set to 100 in all version configs (v1, v2, v3)

rs-dpp:

  • New consensus error IdentityAssetLockTransactionTooManyInputsError (code 10534) with actionable message: "Consolidate UTXOs before creating the asset lock"
  • Added input count validation as the first check in validate_asset_lock_transaction_structure_v0
  • 3 unit tests: reject at 101, accept at 100, accept at 1

wasm-dpp:

  • WASM binding for the new error type with getMaxInputs(), getActualInputs(), getCode(), and message accessors

How Has This Been Tested?

  • cargo check -p dpp --features=validation — clean
  • cargo check -p dash-sdk — clean
  • cargo check -p drive-abci — clean
  • cargo test -p dpp --features=validation -- asset_lock_transaction — 5/5 pass (3 new + 2 existing)

Breaking Changes

None. The new limit (100 inputs) is well above typical transaction sizes. Only transactions that would have been rejected by Platform's existing 20KB state transition size limit are now caught earlier with a better error message.

Checklist:

  • I have performed a self-review of my own code
  • I have commented my code, particularly in hard-to-understand areas
  • I have added or updated relevant unit/integration/functional/e2e tests
  • I have added "!" to the title and described breaking changes in the corresponding section if my code contains any
  • I have made corresponding changes to the documentation if needed

For repository code-owners and collaborators only

  • I have assigned this pull request to a milestone

🤖 Co-authored by Claudius the Magnificent AI Agent

…ck funds

Asset lock transactions with too many inputs (from many small UTXOs) can exceed
Platform's 20KB state transition size limit. Core accepts the transaction but
Platform rejects it, leaving funds stuck. This adds a configurable input count
limit (default 100) that validates early with a clear error message advising
users to consolidate UTXOs first.

Closes #3399

Co-Authored-By: Claude Opus 4.6 (1M context) <noreply@anthropic.com>
@coderabbitai
Copy link
Copy Markdown
Contributor

coderabbitai bot commented Apr 14, 2026

Warning

Rate limit exceeded

@lklimek has exceeded the limit for the number of commits that can be reviewed per hour. Please wait 59 minutes and 57 seconds before requesting another review.

Your organization is not enrolled in usage-based pricing. Contact your admin to enable usage-based pricing to continue reviews beyond the rate limit, or try again in 59 minutes and 57 seconds.

⌛ How to resolve this issue?

After the wait time has elapsed, a review can be triggered using the @coderabbitai review command as a PR comment. Alternatively, push new commits to this PR.

We recommend that you space out your commits to avoid hitting the rate limit.

🚦 How do rate limits work?

CodeRabbit enforces hourly rate limits for each developer per organization.

Our paid plans have higher rate limits than the trial, open-source and free plans. In all cases, we re-allow further reviews after a brief timeout.

Please see our FAQ for further information.

ℹ️ Review info
⚙️ Run configuration

Configuration used: defaults

Review profile: CHILL

Plan: Pro

Run ID: 4cb8806e-0a22-49d1-971d-59ab344da235

📥 Commits

Reviewing files that changed from the base of the PR and between 127ad5e and 3656c69.

📒 Files selected for processing (13)
  • packages/rs-dpp/src/errors/consensus/basic/basic_error.rs
  • packages/rs-dpp/src/errors/consensus/basic/identity/identity_asset_lock_transaction_too_many_inputs_error.rs
  • packages/rs-dpp/src/errors/consensus/basic/identity/mod.rs
  • packages/rs-dpp/src/errors/consensus/codes.rs
  • packages/rs-dpp/src/identity/state_transition/asset_lock_proof/validate_asset_lock_transaction_structure/mod.rs
  • packages/rs-dpp/src/identity/state_transition/asset_lock_proof/validate_asset_lock_transaction_structure/v0/mod.rs
  • packages/rs-platform-version/src/version/dpp_versions/dpp_state_transition_versions/mod.rs
  • packages/rs-platform-version/src/version/dpp_versions/dpp_state_transition_versions/v1.rs
  • packages/rs-platform-version/src/version/dpp_versions/dpp_state_transition_versions/v2.rs
  • packages/rs-platform-version/src/version/dpp_versions/dpp_state_transition_versions/v3.rs
  • packages/wasm-dpp/src/errors/consensus/basic/identity/identity_asset_lock_transaction_too_many_inputs_error.rs
  • packages/wasm-dpp/src/errors/consensus/basic/identity/mod.rs
  • packages/wasm-dpp/src/errors/consensus/consensus_error.rs
✨ Finishing Touches
🧪 Generate unit tests (beta)
  • Create PR with unit tests
  • Commit unit tests in branch feat/max-asset-lock-inputs

Thanks for using CodeRabbit! It's free for OSS, and your support helps us grow. If you like it, consider giving us a shout-out.

❤️ Share

Comment @coderabbitai help to get the list of available commands and usage tips.

@github-actions github-actions bot added this to the v3.1.0 milestone Apr 14, 2026
@lklimek lklimek requested a review from Copilot April 15, 2026 06:44
@lklimek
Copy link
Copy Markdown
Contributor Author

lklimek commented Apr 15, 2026

Needs to be tested with dash-evo-tool

Copy link
Copy Markdown
Contributor

Copilot AI left a comment

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

Pull request overview

Adds a protocol-configured cap on Asset Lock transaction input count so oversized asset-lock state transitions are rejected before Core broadcast, avoiding “stuck funds” scenarios and providing a clearer, actionable consensus error.

Changes:

  • Introduces max_asset_lock_transaction_inputs (set to 100) in platform version configs (v1–v3).
  • Enforces the new limit during asset lock transaction structure validation and adds unit tests around the boundary.
  • Wires a new consensus error (code 10534) through Rust + WASM error surfaces.

Reviewed changes

Copilot reviewed 13 out of 13 changed files in this pull request and generated 3 comments.

Show a summary per file
File Description
packages/rs-platform-version/src/version/dpp_versions/dpp_state_transition_versions/mod.rs Adds max_asset_lock_transaction_inputs to identity asset-lock version config struct.
packages/rs-platform-version/src/version/dpp_versions/dpp_state_transition_versions/v1.rs Sets max asset-lock inputs to 100 for v1.
packages/rs-platform-version/src/version/dpp_versions/dpp_state_transition_versions/v2.rs Sets max asset-lock inputs to 100 for v2.
packages/rs-platform-version/src/version/dpp_versions/dpp_state_transition_versions/v3.rs Sets max asset-lock inputs to 100 for v3.
packages/rs-dpp/src/identity/state_transition/asset_lock_proof/validate_asset_lock_transaction_structure/mod.rs Threads platform-version limit into v0 validator call.
packages/rs-dpp/src/identity/state_transition/asset_lock_proof/validate_asset_lock_transaction_structure/v0/mod.rs Implements input-count guard and adds unit tests for 1/100/101 inputs.
packages/rs-dpp/src/errors/consensus/basic/identity/mod.rs Exposes the new identity consensus error type.
packages/rs-dpp/src/errors/consensus/basic/basic_error.rs Adds the new BasicError enum variant for the consensus error.
packages/rs-dpp/src/errors/consensus/codes.rs Assigns consensus error code 10534.
packages/rs-dpp/src/errors/consensus/basic/identity/identity_asset_lock_transaction_too_many_inputs_error.rs Defines the new consensus error type and message.
packages/wasm-dpp/src/errors/consensus/basic/identity/mod.rs Registers the new WASM error module + re-export.
packages/wasm-dpp/src/errors/consensus/basic/identity/identity_asset_lock_transaction_too_many_inputs_error.rs Adds WASM bindings/accessors for the new error type.
packages/wasm-dpp/src/errors/consensus/consensus_error.rs Maps the new BasicError variant into the WASM consensus error conversion.

💡 Add Copilot custom instructions for smarter, more guided reviews. Learn how to get started.

@@ -0,0 +1,47 @@
use crate::consensus::basic::BasicError;
use crate::consensus::ConsensusError;
use crate::errors::ProtocolError;
Copy link

Copilot AI Apr 15, 2026

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

ProtocolError is imported but never used in this error type, which will generate an unused-import warning. Please remove the import (or use it if it was intended).

Suggested change
use crate::errors::ProtocolError;

Copilot uses AI. Check for mistakes.
Comment on lines +19 to +21
return ConsensusValidationResult::new_with_error(
IdentityAssetLockTransactionTooManyInputsError::new(input_count as u16, max_inputs)
.into(),
Copy link

Copilot AI Apr 15, 2026

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

input_count is a usize but is cast to u16 when constructing the error. If a transaction ever has more than u16::MAX inputs, actual_inputs will wrap/truncate and the error will report the wrong count. Consider using a fallible conversion (u16::try_from) and clamping, or store actual_inputs as a wider type (e.g. u32) in the error.

Suggested change
return ConsensusValidationResult::new_with_error(
IdentityAssetLockTransactionTooManyInputsError::new(input_count as u16, max_inputs)
.into(),
let actual_inputs = u16::try_from(input_count).unwrap_or(u16::MAX);
return ConsensusValidationResult::new_with_error(
IdentityAssetLockTransactionTooManyInputsError::new(actual_inputs, max_inputs).into(),

Copilot uses AI. Check for mistakes.
Comment on lines +138 to +142
fn should_accept_transaction_at_max_inputs() {
let tx = make_asset_lock_transaction(100);
let result = validate_asset_lock_transaction_structure_v0(&tx, 0, 100);

let has_too_many_inputs_error = result.errors.iter().any(|e| {
Copy link

Copilot AI Apr 15, 2026

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

should_accept_transaction_at_max_inputs only asserts that the "too many inputs" error is absent; it would still pass if other validation errors were returned. To make the test actually verify acceptance, assert result.is_valid() (similar to should_accept_transaction_with_one_input).

Copilot uses AI. Check for mistakes.
@lklimek lklimek marked this pull request as ready for review April 15, 2026 14:41
@thepastaclaw
Copy link
Copy Markdown
Collaborator

thepastaclaw commented Apr 15, 2026

⏳ Review in progress (commit 3656c69)

@codecov
Copy link
Copy Markdown

codecov bot commented Apr 15, 2026

Codecov Report

❌ Patch coverage is 88.76404% with 10 lines in your changes missing coverage. Please review.
✅ Project coverage is 84.83%. Comparing base (127ad5e) to head (3656c69).
⚠️ Report is 2 commits behind head on v3.1-dev.

Files with missing lines Patch % Lines
...alidate_asset_lock_transaction_structure/v0/mod.rs 87.95% 10 Missing ⚠️
Additional details and impacted files
@@            Coverage Diff            @@
##           v3.1-dev    #3491   +/-   ##
=========================================
  Coverage     84.83%   84.83%           
=========================================
  Files          2476     2476           
  Lines        267733   267822   +89     
=========================================
+ Hits         227123   227202   +79     
- Misses        40610    40620   +10     
Components Coverage Δ
dpp 82.00% <88.76%> (+0.01%) ⬆️
drive 84.21% <ø> (ø)
drive-abci 87.46% <ø> (ø)
sdk ∅ <ø> (∅)
dapi-client ∅ <ø> (∅)
platform-version ∅ <ø> (∅)
platform-value 92.10% <ø> (ø)
platform-wallet ∅ <ø> (∅)
drive-proof-verifier 55.66% <ø> (ø)
🚀 New features to boost your workflow:
  • ❄️ Test Analytics: Detect flaky tests, report on failures, and find test suite problems.
  • 📦 JS Bundle Analysis: Save yourself from yourself by tracking and limiting bundle sizes in JS merges.

Sign up for free to join this conversation on GitHub. Already have an account? Sign in to comment

Labels

None yet

Projects

None yet

Development

Successfully merging this pull request may close these issues.

Asset lock state transition rejected as "Tx too large" after Core broadcast — funds stuck

3 participants