Skip to content

improve Unroll method#46

Open
louisinger wants to merge 2 commits intomasterfrom
unroll-method
Open

improve Unroll method#46
louisinger wants to merge 2 commits intomasterfrom
unroll-method

Conversation

@louisinger
Copy link
Copy Markdown
Contributor

@louisinger louisinger commented Oct 24, 2025

This PR contains several improvements to Unroll method:

  • return RPC string outputs returning by submitpackage calls
  • all to specify outpointsFilter in order to select the branches to unroll
  • bump P2A: exclude unconfirmed coins from the coin selection (disallowed by current mempool policy).
  • improve error message in case of "PendingConfirmation" errors

@altafan please review

Summary by CodeRabbit

  • Refactor
    • Enhanced Unroll flow: supports filtering which outputs are processed and now returns a list of broadcast transaction IDs along with error status. Error and waiting-for-confirmation handling updated so empty work returns success (no transactions) and pending confirmations report which TXIDs are awaited.

✏️ Tip: You can customize this high-level summary in your review settings.

@louisinger louisinger requested a review from altafan October 24, 2025 09:52
@coderabbitai
Copy link
Copy Markdown

coderabbitai bot commented Oct 24, 2025

Walkthrough

The Unroll method on ArkClient was changed to accept an outpointsFilter []types.Outpoint and now returns ([]string, error) instead of error. Implementations and call sites were updated to apply filtering, collect package broadcast responses, and adjust confirmation/pending error paths.

Changes

Cohort / File(s) Summary
Interface and client implementation
ark_sdk.go, client.go
Changed Unroll(ctx context.Context) errorUnroll(ctx context.Context, outpointsFilter []types.Outpoint) ([]string, error). Updated implementation to pass outpointsFilter to vtxo selection, return collected package broadcast response IDs ([]string), convert prior return err sites to return nil, err, and handle pending confirmations by aggregating TXIDs.
Tests / call sites
test/e2e/exit_test.go
Updated call sites to pass nil for the new filter and to receive the additional return value: err = alice.Unroll(ctx)_, err = alice.Unroll(ctx, nil) (same error handling retained).

Estimated code review effort

🎯 3 (Moderate) | ⏱️ ~20 minutes

  • Review focus:
    • client.go — ensure all new return paths correctly propagate ([]string, error) and logging vs. error-return intent matches design.
    • ark_sdk.go — confirm interface change is build-safe for consumers.
    • Call sites (e.g., test/e2e/exit_test.go) — check other callers in repo for missing updates.

Pre-merge checks and finishing touches

❌ Failed checks (1 warning, 1 inconclusive)
Check name Status Explanation Resolution
Docstring Coverage ⚠️ Warning Docstring coverage is 0.00% which is insufficient. The required threshold is 80.00%. You can run @coderabbitai generate docstrings to improve docstring coverage.
Title check ❓ Inconclusive The title is vague and generic, using a non-descriptive term 'improve' that doesn't convey specific meaningful information about the changeset. Replace with a more specific title that reflects the main change, such as 'Enhance Unroll method to return package responses and support outpoints filtering' or 'Add outpoints filtering and package response returns to Unroll method'.
✅ Passed checks (1 passed)
Check name Status Explanation
Description Check ✅ Passed Check skipped - CodeRabbit’s high-level summary is enabled.
✨ Finishing touches
  • 📝 Generate docstrings
🧪 Generate unit tests (beta)
  • Create PR with unit tests
  • Post copyable unit tests in a comment
  • Commit unit tests in branch unroll-method

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.

Copy link
Copy Markdown

@coderabbitai coderabbitai bot left a comment

Choose a reason for hiding this comment

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

Actionable comments posted: 0

Caution

Some comments are outside the diff and can’t be posted inline due to platform limitations.

⚠️ Outside diff range comments (2)
client.go (2)

502-506: Fix build: remove unused totalVtxosAmount.

totalVtxosAmount is computed but never used; Go will not compile with an unused local.

Apply:

-    totalVtxosAmount := uint64(0)
-    for _, vtxo := range vtxos {
-        totalVtxosAmount += vtxo.Amount
-    }

1560-1590: Correct coin selection math and typos; stop selecting once sufficient.

  • amountToSelect should decrement by current utxo amount, not cumulative selectedAmount.
  • Break the outer address loop once amountToSelect <= 0 to avoid over-selection.
  • Typo: uncomfirmedBalance → unconfirmedBalance (also in error string).
-    selectedCoins := make([]explorer.Utxo, 0)
-    selectedAmount := uint64(0)
-    amountToSelect := int64(fees) - txutils.ANCHOR_VALUE
-    uncomfirmedBalance := uint64(0)
-    for _, addr := range addresses {
+    selectedCoins := make([]explorer.Utxo, 0)
+    selectedAmount := uint64(0)
+    amountToSelect := int64(fees) - txutils.ANCHOR_VALUE
+    unconfirmedBalance := uint64(0)
+    for _, addr := range addresses {
+        if amountToSelect <= 0 {
+            break
+        }
         utxos, err := a.explorer.GetUtxos(addr)
         if err != nil {
             return "", err
         }
 
         for _, utxo := range utxos {
-            if !utxo.Status.Confirmed {
-                uncomfirmedBalance += utxo.Amount
+            if !utxo.Status.Confirmed {
+                unconfirmedBalance += utxo.Amount
                 continue
             }
 
             selectedCoins = append(selectedCoins, utxo)
             selectedAmount += utxo.Amount
-            amountToSelect -= int64(selectedAmount)
+            amountToSelect -= int64(utxo.Amount)
             if amountToSelect <= 0 {
                 break
             }
         }
     }
 
     if amountToSelect > 0 {
-        return "", fmt.Errorf(
-            "not enough confirmed funds to select %d (uncomfirmed balance: %d)",
-            amountToSelect, uncomfirmedBalance,
-        )
+        return "", fmt.Errorf(
+            "not enough confirmed funds to select %d (unconfirmed balance: %d)",
+            amountToSelect, unconfirmedBalance,
+        )
     }
🧹 Nitpick comments (2)
client.go (2)

540-549: Preserve sentinel while improving message.

Wrap the detailed message with ErrWaitingForConfirmation so callers can use errors.Is(err, ErrWaitingForConfirmation).

-            return nil, fmt.Errorf(
-                "exit is running, waiting for confirmation(s): %s",
-                strings.Join(txids, ", "),
-            )
+            return nil, fmt.Errorf(
+                "%w: %s",
+                ErrWaitingForConfirmation,
+                strings.Join(txids, ", "),
+            )

555-579: Avoid UTXO selection races: lock around bumpAnchorTx/broadcast.

bumpAnchorTx selects/spends on-chain UTXOs; consider guarding this section with coinSelectionLock like other send/settle paths.

-    packageResponses := make([]string, 0, len(transactions))
-
-    for _, parent := range transactions {
+    packageResponses := make([]string, 0, len(transactions))
+
+    a.coinSelectionLock.Lock()
+    defer a.coinSelectionLock.Unlock()
+    for _, parent := range transactions {
         ...
     }
📜 Review details

Configuration used: CodeRabbit UI

Review profile: CHILL

Plan: Pro

📥 Commits

Reviewing files that changed from the base of the PR and between 2ede04a and 2545a97.

📒 Files selected for processing (2)
  • ark_sdk.go (1 hunks)
  • client.go (6 hunks)
🧰 Additional context used
🧬 Code graph analysis (2)
ark_sdk.go (1)
types/types.go (1)
  • Outpoint (71-74)
client.go (4)
types/types.go (1)
  • Outpoint (71-74)
api-spec/protobuf/gen/ark/v1/types.pb.go (3)
  • Outpoint (24-30)
  • Outpoint (43-43)
  • Outpoint (58-60)
types.go (1)
  • CoinSelectOptions (133-140)
redemption/redeem.go (1)
  • ErrPendingConfirmation (191-193)
⏰ Context from checks skipped due to timeout of 90000ms. You can increase the timeout in your CodeRabbit configuration to a maximum of 15 minutes (900000ms). (1)
  • GitHub Check: Sdk unit tests
🔇 Additional comments (2)
client.go (1)

491-494: Good: outpointsFilter is correctly threaded into getVtxos.

Passing OutpointsFilter via CoinSelectOptions here is the right place; aligns with the new signature.

ark_sdk.go (1)

41-41: Breaking API change: ArkClient.Unroll signature changed; document in release notes and consider version bump.

The signature change from Unroll(ctx context.Context) error to Unroll(ctx context.Context, outpointsFilter []types.Outpoint) ([]string, error) is confirmed. No internal call sites were found in the codebase. Since this is a public SDK interface, external consumers will need to adapt. Ensure the change is documented in release notes or CHANGELOG and consider a major version bump per semver.

Copy link
Copy Markdown

@coderabbitai coderabbitai bot left a comment

Choose a reason for hiding this comment

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

Actionable comments posted: 0

Caution

Some comments are outside the diff and can’t be posted inline due to platform limitations.

⚠️ Outside diff range comments (2)
client.go (1)

552-625: Unroll breaks test contract: missing "no vtxos to unroll" error and ErrWaitingForConfirmation wrapping

The implementation violates two existing test expectations in test/e2e/exit_test.go:

  1. Empty vtxos case returns (nil, nil) instead of error (line 570)
    The test loop expects Unroll to eventually return an error containing "no vtxos to unroll" to break. With nil error, the loop condition if err == nil { continue } will spin indefinitely since there are no vtxos to process.

  2. Pending-confirmation error loses ErrWaitingForConfirmation wrapping (lines 618–621)
    When vtxos are waiting for confirmation, the code builds a new error via fmt.Errorf("exit is running, waiting for confirmation(s): %s", ...) without wrapping ErrWaitingForConfirmation. Tests check if errors.Is(err, arksdk.ErrWaitingForConfirmation) to retry; this will always fail with the current implementation, breaking test flow.

Fix by:

  • Returning fmt.Errorf("no vtxos to unroll") on line 570 instead of nil
  • Wrapping with %w on line 618: fmt.Errorf("%w: exit is running, waiting for confirmation(s): %s", ErrWaitingForConfirmation, ...)
  • Returning fmt.Errorf("no vtxos to unroll") on line 623 for consistency (though currently unreachable)
test/e2e/exit_test.go (1)

206-221: Tests expect Unroll to return wrapped ErrWaitingForConfirmation and a "no vtxos to unroll" error, but implementation returns different values

The test logic is sound, but the current Unroll implementation doesn't match its expectations:

  • When len(vtxos) == 0, Unroll returns (nil, nil) (line 571), so the test assertion require.ErrorContains(t, err, "no vtxos to unroll") at lines 220 and 294 never triggers.
  • When confirmations are pending, Unroll returns a plain fmt.Errorf(...) without wrapping ErrWaitingForConfirmation (lines 608–614), so errors.Is(err, arksdk.ErrWaitingForConfirmation) at lines 215 and 289 will never match.

To align the implementation with test expectations, update Unroll to:

  1. Return fmt.Errorf("no vtxos to unroll") when len(vtxos) == 0.
  2. Return fmt.Errorf("%w: %s", arksdk.ErrWaitingForConfirmation, strings.Join(txids, ", ")) in the pending-confirmation branch.

Once these changes are made, the test loops will exercise the intended control flow without modification.

🧹 Nitpick comments (2)
client.go (2)

1801-1827: Minor typo and message clarity in bumpAnchorTx error for unconfirmed funds

The new unconfirmed-balance tracking is good, but there are a couple of small nits:

  • Variable and message typo: uncomfirmedBalance and "uncomfirmed balance" (Lines 1801, 1825–1827) should be unconfirmedBalance / "unconfirmed balance" for readability.
  • The message "not enough confirmed funds to select %d (uncomfirmed balance: %d)" uses amountToSelect (the remaining shortfall) as the first %d. Consider wording it explicitly as “shortfall” to avoid confusion with “total required funds”.

Example tweak:

-	uncomfirmedBalance := uint64(0)
+	unconfirmedBalance := uint64(0)
@@
-			if !utxo.Status.Confirmed {
-				uncomfirmedBalance += utxo.Amount
-				continue
-			}
+			if !utxo.Status.Confirmed {
+				unconfirmedBalance += utxo.Amount
+				continue
+			}
@@
-	if amountToSelect > 0 {
-		return "", fmt.Errorf(
-			"not enough confirmed funds to select %d (uncomfirmed balance: %d)",
-			amountToSelect, uncomfirmedBalance,
-		)
-	}
+	if amountToSelect > 0 {
+		return "", fmt.Errorf(
+			"not enough confirmed funds: shortfall %d (unconfirmed balance: %d)",
+			amountToSelect, unconfirmedBalance,
+		)
+	}

Purely cosmetic, but it makes logs and error messages clearer when diagnosing fee-bump funding issues.


2709-2735: OutpointsFilter behavior looks correct; consider deduping filter logic

The new OutpointsFilter handling in:

  • getClaimableBoardingUtxos (Lines 2709–2725),
  • getExpiredBoardingUtxos (Lines 2767–2783), and
  • getVtxos (Lines 2802–2804 via filterByOutpoints),

is consistent and does what it says: restricts to the provided outpoints before applying the rest of the logic.

Given you now filter vtxos via filterByOutpoints and inline essentially the same loop twice for boarding utxos, you might want to centralize that logic to avoid divergence over time (e.g., shared helper filterUtxosByOutpoints(utxos []explorer.Utxo, filter []types.Outpoint) that returns the sliced list), but this is non-blocking.

Also applies to: 2767-2789, 2802-2804

📜 Review details

Configuration used: CodeRabbit UI

Review profile: CHILL

Plan: Pro

📥 Commits

Reviewing files that changed from the base of the PR and between 2545a97 and 3036e0a.

📒 Files selected for processing (3)
  • ark_sdk.go (1 hunks)
  • client.go (8 hunks)
  • test/e2e/exit_test.go (2 hunks)
🚧 Files skipped from review as they are similar to previous changes (1)
  • ark_sdk.go
🧰 Additional context used
🧬 Code graph analysis (1)
client.go (4)
types/types.go (1)
  • Outpoint (71-74)
api-spec/protobuf/gen/ark/v1/types.pb.go (3)
  • Outpoint (24-30)
  • Outpoint (43-43)
  • Outpoint (58-60)
types.go (1)
  • CoinSelectOptions (134-145)
redemption/redeem.go (1)
  • ErrPendingConfirmation (191-193)
⏰ Context from checks skipped due to timeout of 90000ms. You can increase the timeout in your CodeRabbit configuration to a maximum of 15 minutes (900000ms). (2)
  • GitHub Check: Sdk unit tests
  • GitHub Check: Sdk integration tests

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.

2 participants