PHANTOM
🇮🇳 IN
Skip to content

Simplify cardano fee calc algo#32579

Merged
supermassive merged 6 commits intomasterfrom
simplify_cardano_fee_calc_algo
Dec 4, 2025
Merged

Simplify cardano fee calc algo#32579
supermassive merged 6 commits intomasterfrom
simplify_cardano_fee_calc_algo

Conversation

@supermassive
Copy link
Collaborator

@supermassive supermassive commented Nov 27, 2025

Resolves brave/brave-browser#51121

  • Do fee and output values estimation starting from 0 and increase fee iteratively until fee matches tx cost. That simplifies tx serialization code.
  • Extracted code above to be used by both Knapsack solver and MaxSend solver.
  • Fixed tx knapsack search algorithm so it does not try to increase fee to match 1-input == fee + 1-output tx. Wallets typically decline such possible transaction and proceed to next utxo.

@supermassive supermassive force-pushed the simplify_cardano_fee_calc_algo branch from 0c0306d to 88451a3 Compare November 29, 2025 14:46
@github-actions
Copy link
Contributor

github-actions bot commented Dec 1, 2025

[puLL-Merge] - brave/brave-core@32579

Description

This PR refactors the Cardano transaction fee and amount validation logic. The main changes include:

  • Moves fee and output amount calculation from CardanoCreateTransactionTask to CardanoTransactionSerializer
  • Replaces manual fee calculation loops with a centralized AdjustFeeAndOutputsForTx method
  • Adds explicit fee_ field to CardanoTransaction instead of calculating it implicitly
  • Introduces ValidateAmounts method to ensure transaction inputs equal outputs + fees
  • Updates validation to occur in the solver layer rather than at task level
  • Changes validation from runtime errors to CHECK assertions in critical paths

Possible Issues

  1. Breaking Change in Validation: The PR changes when and how validation occurs. Previously, ValidateMinValue on target output happened in CardanoCreateTransactionTask, now it happens in the solver. This could silently break if solvers aren't updated correctly.

  2. CHECK vs Error Handling: The code replaces error handling with CHECK assertions in CardanoCreateTransactionTask::RunSolverForTransaction(). If ValidateAmounts fails, the application will crash rather than returning an error to the user:

    CHECK(CardanoTransactionSerializer::ValidateAmounts(
        *solved_transaction, *latest_epoch_parameters_));
  3. Overflow Handling: The PR changes from ClampSub to CheckedNumeric, which is safer, but the error handling paths may not be complete. Several places return std::nullopt on overflow but callers may not handle this gracefully.

  4. Iteration Limit: The fee search loop has a fixed iteration limit (kFeeSearchMaxIterations = 10). If this is exceeded, the function returns nullopt without logging, making debugging difficult.

Security Hotspots

  1. Integer Overflow in Fee Calculation (Medium Risk): The AdjustFeeAndOutputsForTx method uses CheckedNumeric but doesn't validate all paths. If an attacker can craft inputs that cause overflow in unguarded paths, they might be able to create transactions with incorrect fees:

    if (!base::CheckSub(total_inputs_amount, result.fee())
             .AssignIfValid(&result.TargetOutput()->amount)) {
      return std::nullopt;
    }

    The nullopt return could be silently ignored by callers.

  2. CHECK-based Validation (Low-Medium Risk): Using CHECK for validation in production code means malformed transactions could crash the wallet rather than failing gracefully:

    CHECK(CardanoTransactionSerializer::ValidateAmounts(
        *solved_transaction, *latest_epoch_parameters_));

    This could be exploited for DoS if an attacker can trigger these conditions.

  3. Fee Manipulation Risk (Low Risk): The iterative fee calculation approach could potentially be exploited if the iteration limit is reached. An attacker might craft inputs that require more than 10 iterations, causing transaction creation to fail.

Privacy Hotspots

  1. Test Data Updates: The PR updates test UTXOs to use 969750 (minimum UTXO) and 2000000 instead of 54321 and 600000. While these are test values, they should not reflect real user patterns or be derived from production data.

  2. Transaction Serialization Changes: The serialization format has changed to include explicit fee values. This could affect transaction privacy if the fee calculation method reveals information about the wallet implementation version.

Changes

Changes

components/brave_wallet/browser/cardano/cardano_transaction_serializer.cc/h

  • Added AdjustFeeAndOutputsForTx static method to centralize fee and output amount calculation
  • Added ValidateAmounts static method to verify inputs = outputs + fees
  • Made ValidateMinValue a static method
  • Made CalcMinAdaRequired private
  • Removed serialization options for max_value_for_* flags (no longer needed)
  • Removed manual fee adjustment loop from serialization logic

components/brave_wallet/browser/cardano/cardano_transaction.cc/h

  • Added explicit fee_ member variable
  • Added set_fee() and fee() accessors
  • Changed TotalInputsAmount() and TotalOutputsAmount() to return CheckedNumeric<uint64_t> instead of uint64_t
  • Removed AmountsAreValid(), EffectiveFeeAmount(), and MoveSurplusFeeToChangeOutput() methods
  • Updated ToValue() to serialize fee field
  • Updated FromValue() to support legacy format without fee field (backwards compatibility)

components/brave_wallet/browser/cardano/cardano_create_transaction_task.cc

  • Removed manual ValidateMinValue check and error handling
  • Replaced with CHECK assertion on ValidateAmounts

components/brave_wallet/browser/cardano/cardano_knapsack_solver.cc

  • Moved validation back to solver initialization
  • Removed SetFeeAndChangeForTransaction helper function
  • Updated solver loop to use AdjustFeeAndOutputsForTx instead of manual calculation
  • Changed success criteria from AmountsAreValid() to successful AdjustFeeAndOutputsForTx() result

components/brave_wallet/browser/cardano/cardano_max_send_solver.cc

  • Simplified to use AdjustFeeAndOutputsForTx instead of manual calculation
  • Removed manual fee calculation and output adjustment

Test Files

  • Updated all test expectations to match new fee calculations
  • Added explicit fee validation using ValidateAmounts in tests
  • Updated mock UTXO values to minimum viable amounts
  • Added comprehensive tests for AdjustFeeAndOutputsForTx and ValidateAmounts
sequenceDiagram
    participant Task as CardanoCreateTransactionTask
    participant Solver as CardanoKnapsackSolver/MaxSendSolver
    participant Serializer as CardanoTransactionSerializer
    participant Tx as CardanoTransaction
    
    Task->>Solver: Create with base tx + inputs
    Note over Solver: Validate target output min value
    Solver->>Solver: RunSolver iteration loop
    loop For each input combination
        Solver->>Serializer: AdjustFeeAndOutputsForTx(tx, params)
        Serializer->>Serializer: Calculate initial fee
        loop Max 10 iterations
            Serializer->>Tx: Adjust output amounts based on fee
            Serializer->>Serializer: CalcMinTransactionFee(tx)
            alt Fee converged
                Serializer->>Serializer: ValidateAmounts(tx)
                Serializer-->>Solver: Return valid tx
            else Need larger fee
                Note over Serializer: Increase fee, retry
            end
        end
    end
    Solver-->>Task: Return best solution
    Task->>Serializer: CHECK ValidateAmounts(tx)
    Task->>Task: Store transaction
Loading

@github-actions
Copy link
Contributor

github-actions bot commented Dec 1, 2025

Copy link
Member

@kdenhartog kdenhartog left a comment

Choose a reason for hiding this comment

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

Are we changing how the fee structure works for smart contract execution transactions?

From what I can see, the calculation here operates a bit differently and I don't see anything about the way that Collateral requirements work or execution budget aspects.

The concern here would be that the fee structure isn't correct and lead to a phase 2 failure where a small fee (the collateral) is still collected even though the transaction didn't execute properly. Here's some docs I found that highlight how this works: https://www.essentialcardano.io/article/no-surprises-transaction-validation-part-2

Does that have an impact on this PR at all?

@supermassive
Copy link
Collaborator Author

Are we changing how the fee structure works for smart contract execution transactions?

From what I can see, the calculation here operates a bit differently and I don't see anything about the way that Collateral requirements work or execution budget aspects.

The concern here would be that the fee structure isn't correct and lead to a phase 2 failure where a small fee (the collateral) is still collected even though the transaction didn't execute properly. Here's some docs I found that highlight how this works: https://www.essentialcardano.io/article/no-surprises-transaction-validation-part-2

Does that have an impact on this PR at all?

Phase 2 failure fee is burned from collateral inputs which we don't(and didn't) add to transactions.

Copy link
Member

@kdenhartog kdenhartog left a comment

Choose a reason for hiding this comment

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

My question seems unrelated to the focus of this PR so we can address it in a follow up.

We discussed over DMs and it seems this is not an area we have implemented yet. I'm going to do some testing today and determine the best path forward to avoid the issue I highlighted above around smart contract execution fees and will open a follow up issue for it.

@supermassive supermassive enabled auto-merge (squash) December 4, 2025 06:58
@supermassive supermassive merged commit a7ae566 into master Dec 4, 2025
21 checks passed
@supermassive supermassive deleted the simplify_cardano_fee_calc_algo branch December 4, 2025 06:59
@github-actions github-actions bot added this to the 1.87.x - Nightly milestone Dec 4, 2025
@brave-builds
Copy link
Collaborator

Released in v1.87.47

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

Projects

None yet

Development

Successfully merging this pull request may close these issues.

Simplify Cardano fee calculation algorithm

4 participants