From 765ee6a6868f495939ed12f99c72b944ad079f37 Mon Sep 17 00:00:00 2001 From: Akhil Repala Date: Mon, 2 Jun 2025 18:28:31 -0500 Subject: [PATCH 1/2] feat(ledger/babbage): Prevented uint underflow in UtxoValidateCollateralEqBalance when collateral UTxOs are missing Signed-off-by: Akhil Repala --- ledger/babbage/rules.go | 15 +++++++++++++-- ledger/babbage/rules_test.go | 21 +++++++++++++++++++++ 2 files changed, 34 insertions(+), 2 deletions(-) diff --git a/ledger/babbage/rules.go b/ledger/babbage/rules.go index bb1d9c7a..3d3a9857 100644 --- a/ledger/babbage/rules.go +++ b/ledger/babbage/rules.go @@ -184,10 +184,21 @@ func UtxoValidateCollateralEqBalance( } collBalance += utxo.Output.Amount() } - // Subtract collateral return amount + + // Skip validation if no valid collateral UTxOs were found + // This avoids subtracting from zero and prevents uint underflow + if collBalance == 0 { + return nil + } + + // Subtract collateral return amount with underflow protection collReturn := tx.CollateralReturn() if collReturn != nil { - collBalance -= collReturn.Amount() + returnAmt := collReturn.Amount() + if collBalance < returnAmt { + return errors.New("collateral return amount exceeds collateral input balance") + } + collBalance -= returnAmt } if totalCollateral == collBalance { return nil diff --git a/ledger/babbage/rules_test.go b/ledger/babbage/rules_test.go index 2e262075..6606ab18 100644 --- a/ledger/babbage/rules_test.go +++ b/ledger/babbage/rules_test.go @@ -1449,6 +1449,27 @@ func TestUtxoValidateCollateralEqBalance(t *testing.T) { } }, ) + // no valid collateral UTxO, should skip and not underflow + t.Run("no valid collateral UTxO, should skip and not underflow", func(t *testing.T) { + // Ledger state with NO matching UTxO + missingUtxoLedgerState := test.MockLedgerState{ + MockUtxos: []common.Utxo{}, // empty + } + testTx.Body.TxCollateralReturn = &babbage.BabbageTransactionOutput{ + OutputAmount: mary.MaryTransactionOutputValue{ + Amount: testCollateralReturnAmountBad, + }, + } + err := babbage.UtxoValidateCollateralEqBalance( + testTx, + testSlot, + missingUtxoLedgerState, + testProtocolParams, + ) + if err != nil { + t.Errorf("Should skip collateral return validation if collBalance == 0. Got error: %v", err) + } + }) } func TestUtxoValidateTooManyCollateralInputs(t *testing.T) { From 4b3f96e1a8149e655a5e5ce8fb5a4689768703ec Mon Sep 17 00:00:00 2001 From: Akhil Repala Date: Tue, 3 Jun 2025 00:27:45 -0500 Subject: [PATCH 2/2] feat(ledger/babbage): Refactored collateral validation to use only structured errors and return at function end Signed-off-by: Akhil Repala --- ledger/babbage/rules.go | 9 +++------ 1 file changed, 3 insertions(+), 6 deletions(-) diff --git a/ledger/babbage/rules.go b/ledger/babbage/rules.go index 3d3a9857..16c32bc1 100644 --- a/ledger/babbage/rules.go +++ b/ledger/babbage/rules.go @@ -193,13 +193,10 @@ func UtxoValidateCollateralEqBalance( // Subtract collateral return amount with underflow protection collReturn := tx.CollateralReturn() - if collReturn != nil { - returnAmt := collReturn.Amount() - if collBalance < returnAmt { - return errors.New("collateral return amount exceeds collateral input balance") - } - collBalance -= returnAmt + if collReturn != nil && collBalance >= collReturn.Amount() { + collBalance -= collReturn.Amount() } + if totalCollateral == collBalance { return nil }