Skip to content

Limit the number of txs per address#1117

Merged
Klakurka merged 1 commit intoPayButton:masterfrom
Fabcien:limit_addresses
Feb 27, 2026
Merged

Limit the number of txs per address#1117
Klakurka merged 1 commit intoPayButton:masterfrom
Fabcien:limit_addresses

Conversation

@Fabcien
Copy link
Collaborator

@Fabcien Fabcien commented Feb 27, 2026

Avoid requiring too much memory by syncing very large history.

Summary by CodeRabbit

  • Bug Fixes
    • Added a safeguard that prevents processing addresses with more than 250,000 transactions. Such addresses will now return an error instead of attempting to process them.

Avoid requiring too much memory by syncing very large history.
@coderabbitai
Copy link
Contributor

coderabbitai bot commented Feb 27, 2026

📝 Walkthrough

Walkthrough

The changes introduce a new constant MAX_TXS_PER_ADDRESS set to 250,000 and add validation in the Chronik service's getPaginatedTxs method to throw an error when an address exceeds this transaction count limit.

Changes

Cohort / File(s) Summary
Transaction Limit Constant
constants/index.ts
Exported new constant MAX_TXS_PER_ADDRESS with value 250,000.
Chronik Service Validation
services/chronikService.ts
Imported MAX_TXS_PER_ADDRESS and added guard in getPaginatedTxs that throws an error when transaction page size exceeds the limit, replacing unconditional return behavior.

Estimated code review effort

🎯 2 (Simple) | ⏱️ ~10 minutes

Poem

🐰 A limit we set, two-fifty grand,
For txs per address, now firmly planned,
No overflow shall slip the gate,
A guard so swift, a threshold fate!

🚥 Pre-merge checks | ✅ 2 | ❌ 1

❌ Failed checks (1 warning)

Check name Status Explanation Resolution
Description check ⚠️ Warning The description is incomplete and does not follow the required template structure with sections for 'Related to', 'Description', and 'Test plan'. Expand the description to include the required template sections: add issue reference, provide detailed explanation of the change, and document the test plan used to verify the fix.
✅ Passed checks (2 passed)
Check name Status Explanation
Title check ✅ Passed The title 'Limit the number of txs per address' directly and accurately describes the main change: introducing a maximum transaction limit per address.
Docstring Coverage ✅ Passed No functions found in the changed files to evaluate docstring coverage. Skipping docstring coverage check.

✏️ Tip: You can configure your own custom pre-merge checks in the settings.

✨ Finishing Touches
🧪 Generate unit tests (beta)
  • Create PR with unit tests
  • Post copyable unit tests in a comment

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
Contributor

@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: 1

🤖 Prompt for all review comments with AI agents
Verify each finding against the current code and only fix it if needed.

Inline comments:
In `@services/chronikService.ts`:
- Around line 313-315: The new throw in the txsPage.numTxs check can bypass
cleanup in syncTransactionsForAddress; wrap the main loop/processing in a
try/finally so setSyncing(address.address, false) always runs and only call
updateLastSynced(address.address) when the sync actually completed successfully
(use a completed flag set after the loop). Ensure the thrown Error from the
MAX_TXS_PER_ADDRESS check is allowed to propagate but does not prevent the
syncing flag from being cleared.

ℹ️ Review info

Configuration used: defaults

Review profile: CHILL

Plan: Pro

📥 Commits

Reviewing files that changed from the base of the PR and between 3089793 and ab901f7.

📒 Files selected for processing (2)
  • constants/index.ts
  • services/chronikService.ts

Comment on lines +313 to +315
if (txsPage.numTxs > MAX_TXS_PER_ADDRESS) {
throw new Error(`Address ${addressString} has too many txs to sync (${txsPage.numTxs} > ${MAX_TXS_PER_ADDRESS}).`)
}
Copy link
Contributor

Choose a reason for hiding this comment

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

⚠️ Potential issue | 🟠 Major

Ensure thrown tx-limit errors cannot leave sync state dirty.

Line 313 introduces a predictable throw path, but syncTransactionsForAddress does cleanup outside a finally. If this error propagates there, setSyncing(false) may be skipped, leaving the address stuck in syncing state.

Proposed fix
+class AddressTxLimitExceededError extends Error {
+  constructor (
+    public readonly address: string,
+    public readonly numTxs: number,
+    public readonly limit: number
+  ) {
+    super(`Address ${address} has too many txs to sync (${numTxs} > ${limit}).`)
+    this.name = 'AddressTxLimitExceededError'
+  }
+}

   public async getPaginatedTxs (addressString: string, page: number, pageSize: number): Promise<Tx[]> {
     const { type, hash160 } = toHash160(addressString)
     const txsPage = (await this.chronik.script(type, hash160).history(page, pageSize))

     // If there are too many txs, this might be too expensive to sync. Raise an
     // error to skip this address.
     if (txsPage.numTxs > MAX_TXS_PER_ADDRESS) {
-      throw new Error(`Address ${addressString} has too many txs to sync (${txsPage.numTxs} > ${MAX_TXS_PER_ADDRESS}).`)
+      throw new AddressTxLimitExceededError(addressString, txsPage.numTxs, MAX_TXS_PER_ADDRESS)
     }

     return txsPage.txs
   }
// In syncTransactionsForAddress(), ensure state cleanup is always executed.
let completed = false
try {
  while (true) {
    // existing loop
  }
  completed = true
} finally {
  await setSyncing(address.address, false)
  if (completed) {
    await updateLastSynced(address.address)
  }
}
🤖 Prompt for AI Agents
Verify each finding against the current code and only fix it if needed.

In `@services/chronikService.ts` around lines 313 - 315, The new throw in the
txsPage.numTxs check can bypass cleanup in syncTransactionsForAddress; wrap the
main loop/processing in a try/finally so setSyncing(address.address, false)
always runs and only call updateLastSynced(address.address) when the sync
actually completed successfully (use a completed flag set after the loop).
Ensure the thrown Error from the MAX_TXS_PER_ADDRESS check is allowed to
propagate but does not prevent the syncing flag from being cleared.

@Klakurka Klakurka self-requested a review February 27, 2026 22:33
@Klakurka Klakurka added the enhancement (behind the scenes) Stuff that users won't see label Feb 27, 2026
Copy link
Member

@Klakurka Klakurka left a comment

Choose a reason for hiding this comment

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

Good idea putting an error throw on it.

@Klakurka Klakurka requested review from ScottMcDermid and removed request for ScottMcDermid February 27, 2026 22:44
@Klakurka Klakurka merged commit 4fb9f5f into PayButton:master Feb 27, 2026
3 of 4 checks passed
@Fabcien Fabcien deleted the limit_addresses branch March 2, 2026 09:41
Sign up for free to join this conversation on GitHub. Already have an account? Sign in to comment

Labels

enhancement (behind the scenes) Stuff that users won't see

Projects

None yet

Development

Successfully merging this pull request may close these issues.

2 participants