Skip to content

fix(batch): GetBatchSignerAccounts stops rewriting the batch it reports on - #162

Merged
Platonenkov merged 1 commit into
devfrom
claude/batch-signer-accounts-readonly-8fd79c
Sep 1, 2026
Merged

fix(batch): GetBatchSignerAccounts stops rewriting the batch it reports on#162
Platonenkov merged 1 commit into
devfrom
claude/batch-signer-accounts-readonly-8fd79c

Conversation

@Platonenkov

@Platonenkov Platonenkov commented Sep 1, 2026

Copy link
Copy Markdown
Collaborator

Closes #161.

What it does

GetBatchSignerAccounts returns the root account and the accounts required to sign a batch. It also replaced RawTransactions[i].RawTransaction in the caller's own dictionary with a converted copy — the IEnumerable branch does o as Dictionary<string, object>, which aliases an element that is already a dictionary, so the assignment landed in the caller's object. Being the gate every batch-signing path reaches through VerifyBatchSubmitter, it did this on every signature.

The conversion stays, for reading. Only the store-back is gone, with the reason written next to it so it does not come back.

How this was established, in the order the issue asked for

The issue said not to start by removing the assignment, because #157 began from exactly that assumption and it was wrong. So:

1. Removed it and ran the suite. All 1220 tests passed. That proved nothing — it is the same blindness that let #157's first proposal look safe.

2. Built the input where the assignment actually changes something — a wrapper holding a JsonObject rather than a Dictionary. Signed that batch and an equivalent dictionary-valued one, and compared blobs. Identical, with the assignment removed. So the store-back does not reach the signature.

3. Looked for a reader. There is none. Autofill (Autofill.cs:649) and Submit (Submit.cs:277) read RawTransaction from a JsonNode; SignAsBatchPart reads it from the tree it parsed itself; BatchNormalizer writes its own on a separate path. Nothing consumes the stored form from the caller's dictionary.

Tests

Two, answering different questions:

Test Detects this change? What it is for
the caller's wrapper still holds the object it was given yes — restoring the assignment fails it on AreSame pins the new contract
the same batch signs identically whether the wrapper holds a JsonObject or an equivalent Dictionary no — green either way pins the property that makes removing the store-back safe rather than merely tidy

The second is deliberate. It is not a detector for this diff; it would fail first if the two representations ever stopped serializing alike, which is the assumption step 2 rests on.

Verification

  • Unit suite: 1222 passed, 0 failed.
  • Integration tests for batch signing were not run locally (they need a rippled stand); the merge queue runs them against the merge result.
  • CHANGES.md entry added under the existing unreleased 11.2.0.0 section. No version bump: 11.2.0.0 is already the pending version and has not shipped.

Summary by CodeRabbit

  • Bug Fixes

    • Batch signing now preserves caller-provided transaction data without modifying it during signer account extraction.
    • Transactions represented as dictionaries or JSON objects now produce consistent signatures and serialized results.
  • Tests

    • Added coverage for equivalent transaction representations and verification that input batch data remains unchanged.

…ts on

The method returns the root account and the accounts required to sign a
batch. It also replaced RawTransactions[i].RawTransaction in the caller's
own dictionary with a converted copy: the IEnumerable branch aliases an
element that is already a Dictionary, so the assignment landed in the
caller's object. Being the gate every batch-signing path reaches through
VerifyBatchSubmitter, it did this on every signature.

The conversion stays, for reading; only the store-back is gone, and the
reason is written next to it so it does not come back. Nothing needed the
stored form: Autofill and Submit read RawTransaction from a JsonNode,
SignAsBatchPart reads it from the tree it parsed itself, and BatchNormalizer
writes its own on a separate path.

Two tests, because they answer different questions. One asserts the
caller's wrapper still holds the object it was given - restoring the
assignment fails it. The other signs the same batch twice, once with the
wrapper holding a JsonObject and once an equivalent Dictionary, and
requires the same blob; it passes either way, which is the point. It does
not detect this change, it pins the property that makes the change safe
instead of merely tidy, and it would fail first if the two representations
ever stopped serializing alike.

The unit suite does not otherwise notice: all 1220 tests pass with the
assignment removed, exactly as they did in #157 for the mutation there.
@Platonenkov

Copy link
Copy Markdown
Collaborator Author

@coderabbitai full review

@coderabbitai

coderabbitai Bot commented Sep 1, 2026

Copy link
Copy Markdown
✅ Action performed

Full review finished.

@coderabbitai

coderabbitai Bot commented Sep 1, 2026

Copy link
Copy Markdown

Review Change Stack

No actionable comments were generated in the recent review. 🎉

ℹ️ Recent review info
⚙️ Run configuration

Configuration used: Path: .coderabbit.yaml

Review profile: CHILL

Plan: Essentials

Run ID: ec02c072-b88f-4fea-bfdc-1c63271031da

📥 Commits

Reviewing files that changed from the base of the PR and between c84dc3b and 3455c5a.

📒 Files selected for processing (3)
  • CHANGES.md
  • Tests/Xrpl.Tests/Wallet/TestUBatchSigningV11.cs
  • Xrpl/Models/Utils/BatchUtils.cs

Included review availability: 3 reviews are currently available. Your included PR review attempts over the past 7 days set your current allowance at 4 reviews per hour.


📝 Walkthrough

Walkthrough

GetBatchSignerAccounts now processes normalized raw transactions without mutating caller-owned batch dictionaries. Tests verify unchanged inputs and identical signatures for JsonObject and dictionary representations.

Changes

Batch signing

Layer / File(s) Summary
Preserve input during signer extraction
Xrpl/Models/Utils/BatchUtils.cs, CHANGES.md
GetBatchSignerAccounts keeps converted raw transactions local instead of replacing values in caller dictionaries.
Validate representation equivalence and immutability
Tests/Xrpl.Tests/Wallet/TestUBatchSigningV11.cs
Tests verify identical signing blobs for equivalent representations and confirm that signer extraction preserves the input wrapper and inner transaction.

Estimated code review effort: 2 (Simple) | ~10 minutes

Merge Risk: ⚪ Minimal · up to 3455c

This change stops batch-signing account discovery from rewriting the caller’s transaction objects while preserving signing behavior; no actionable merge-blocking risk remains after normal checks and review.

🚥 Pre-merge checks | ✅ 4 | ❌ 1

❌ Failed checks (1 warning)

Check name Status Explanation Resolution
Docstring Coverage ⚠️ Warning Docstring coverage is 0.00% which is insufficient. The required threshold is 80.00%. Docstring coverage is scoped to functions touched by this diff. Analyzed 6 functions across 2 files. (1 skipped: 1 … Write docstrings for the functions missing them to satisfy the coverage threshold.
✅ Passed checks (4 passed)
Check name Status Explanation
Description Check ✅ Passed Check skipped - CodeRabbit’s high-level summary is enabled.
Title check ✅ Passed The title clearly and concisely describes the main change: GetBatchSignerAccounts no longer rewrites the caller’s batch dictionary.
Linked Issues check ✅ Passed The implementation removes the store-back mutation in GetBatchSignerAccounts. Added tests verify that the caller’s original object is preserved and that JsonObject and dictionary representations produ…
Out of Scope Changes check ✅ Passed The implementation, regression tests, and CHANGES.md entry directly support the linked issue and pull request objective. No unrelated code changes are identified.
Full details: Linked Issues check

Explanation

The implementation removes the store-back mutation in GetBatchSignerAccounts. Added tests verify that the caller’s original object is preserved and that JsonObject and dictionary representations produce identical batch-signing blobs, addressing issue #161 and validating downstream signing behavior.

Full details: Docstring Coverage

Explanation

Docstring coverage is 0.00% which is insufficient. The required threshold is 80.00%. Docstring coverage is scoped to functions touched by this diff. Analyzed 6 functions across 2 files. (1 skipped: 1 unsupported.)

  • Fix all pre-merge checks with AI
✨ Finishing Touches 💡 1
📝 Generate docstrings 💡
  • Create stacked PR
  • Commit on current branch
🧪 Generate unit tests (beta)
  • Create PR with unit tests
  • Commit unit tests in branch claude/batch-signer-accounts-readonly-8fd79c

Comment @coderabbitai help to get the list of available commands.

@Platonenkov
Platonenkov added this pull request to the merge queue Sep 1, 2026
Merged via the queue into dev with commit 3cd814e Sep 1, 2026
4 checks passed
@Platonenkov
Platonenkov deleted the claude/batch-signer-accounts-readonly-8fd79c branch September 1, 2026 14:51
@Platonenkov Platonenkov mentioned this pull request Sep 1, 2026
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.

GetBatchSignerAccounts rewrites the dictionary it is given

1 participant