Skip to content

fix: mint UTXO auto-consolidation fails when margin exceeds balance#393

Open
JohnnyLawDGB wants to merge 1 commit intoDigiByte-Core:feature/digidollar-v1from
JohnnyLawDGB:fix/mint-utxo-consolidation
Open

fix: mint UTXO auto-consolidation fails when margin exceeds balance#393
JohnnyLawDGB wants to merge 1 commit intoDigiByte-Core:feature/digidollar-v1from
JohnnyLawDGB:fix/mint-utxo-consolidation

Conversation

@JohnnyLawDGB
Copy link

Problem

PR #391 introduced UTXO auto-consolidation for mintdigidollar to handle wallets with >400 UTXOs (the MAX_TX_INPUTS limit in txbuilder.cpp). However, the consolidation itself fails in a common scenario, leaving the bug effectively unfixed in RC25.

Reported by: @AussieEpic in DigiSwarm — confirmed the bug is still present in RC25 with >400 mining UTXOs.

Root Cause

The consolidation logic calculates a target amount:

CAmount consolidationTarget = result.collateralRequired +
    (result.collateralRequired / 10) + 10000000; // collateral + 10% + 0.1 DGB

When the wallet's total balance barely exceeds the collateral requirement, the 10% margin pushes the target above the available balance:

Collateral needed:  250,309 DGB
+ 10% margin:        25,030 DGB
+ 0.1 DGB buffer:         0.1 DGB
= Target:           275,339 DGB
Available balance:  274,686 DGB  ← LESS than target!

Result: "Insufficient funds for collateral. Need 250309.79 DGB, have 274686.74 DGB across 499 small UTXOs." — the wallet clearly has enough DGB, but the margin math rejects it.

Reproduction

On testnet19 (RC25), oracle wallet with 499 UTXOs:

$ digibyte-cli -rpcwallet=utxo-frag-test mintdigidollar 10000 0

error code: -6
error message:
Insufficient funds for collateral. Need 250309.79 DGB, have 274686.74 DGB across 499 small UTXOs.

The wallet has 274K DGB across 499 UTXOs. The top 400 UTXOs (the MAX_TX_INPUTS limit) sum to only 225K DGB — below the 250K collateral requirement. So SelectCoins correctly identifies this as a fragmentation issue and triggers the consolidation path. But the consolidation rejects because 275K target > 274K available.

Fix

Replace the fixed-margin target calculation with a sweep-to-self approach using subtractfeefromamount:

  1. Minimum check: Only verify that total balance > collateral + 0.2 DGB (the actual minimum needed)
  2. Consolidation: Send entire balance to self with subtractfeefromamount=true — the wallet's standard coin selection handles fee calculation, and the sweep always succeeds regardless of margin
  3. Retry: Re-gather UTXOs (now a single large output) and retry BuildMintTransaction

This approach:

  • Never fails due to margin math
  • Produces one clean UTXO for the retry (optimal for the mint builder)
  • Uses the wallet's battle-tested CreateTransaction for fee calculation

Tested

Built from source and tested on testnet19:

$ digibyte-cli -rpcwallet=utxo-frag-test mintdigidollar 10000 0

{
  "txid": "dfa98af4...",
  "dd_minted": 10000,
  "dgb_collateral": 250682.55150161,
  "lock_tier": 0,
  "unlock_height": 139025,
  "collateral_ratio": 150,
  "fee_paid": 0.11830000,
  "position_id": "dfa98af4...",
  "consolidation_txid": "a5bf0373...",
  "utxos_consolidated": true
}

Same wallet, same UTXOs that failed on RC25 — now auto-consolidates and mints successfully.

Test Methodology

  1. Sent 450 × 500 DGB to utxo-frag-test wallet (creating 499 UTXOs, 274K total)
  2. Verified top 400 UTXOs sum to 225K (below 250K collateral requirement)
  3. Confirmed RC25 binary fails with "Insufficient funds" error
  4. Built patched binary from this branch
  5. Confirmed patched binary auto-consolidates and mints successfully
  6. Restored RC25 binary, verified oracle still running

Files Changed

  • src/rpc/digidollar.cpp — consolidation block in mintdigidollar handler

Test plan

  • Reproduce failure on RC25 with >400 fragmented UTXOs
  • Verify patched binary auto-consolidates and mints successfully
  • Verify consolidation_txid and utxos_consolidated appear in response
  • Verify oracle continues running after swap back to RC25
  • Test edge case: wallet with barely enough balance (collateral + 0.3 DGB)
  • Test edge case: wallet with exactly 400 UTXOs (boundary condition)

🤖 Generated with Claude Code

The previous consolidation logic calculated a target of collateral + 10%
margin + 0.1 DGB, then checked if total balance exceeded that target.
When the margin pushed the target above the available balance (e.g.,
250K collateral + 10% = 275K > 274K available), the consolidation
rejected with "Insufficient funds" even though enough DGB existed.

Fix: sweep the entire wallet balance to self using subtractfeefromamount,
which always succeeds and consolidates all UTXOs into one output. The
fee check now only verifies that collateral + 0.2 DGB fees < total
balance (the actual minimum needed).

Tested: wallet with 500 UTXOs of 500 DGB each (250K total) where the
top 400 UTXOs sum to only 221K — below the 250K collateral requirement.
Previous code threw "Insufficient funds"; fix correctly consolidates
and retries.

Supersedes PR DigiByte-Core#391 consolidation logic.

Co-Authored-By: Claude Opus 4.6 <noreply@anthropic.com>
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.

1 participant