Skip to content

feat: Batch (XLS-56) V1_1 signing support#1010

Open
ckeshava wants to merge 9 commits into
XRPLF:mainfrom
ckeshava:feat/batch-v1_1-signing
Open

feat: Batch (XLS-56) V1_1 signing support#1010
ckeshava wants to merge 9 commits into
XRPLF:mainfrom
ckeshava:feat/batch-v1_1-signing

Conversation

@ckeshava

@ckeshava ckeshava commented Jun 24, 2026

Copy link
Copy Markdown
Collaborator

Implements XLS-56 Batch V1_1 signing, matching rippled #6446.

  • binarycodecencode_for_signing_batch now binds the outer Account, Sequence (or TicketSequence), the BatchSigner account, and (for multi-signed signers) the inner signer account into the signed payload, preventing signature replay.
  • sign_multiaccount_batch — builds the V1_1 payload; adds batch_account and regular-key / string multisign support.
  • combine_batch_signers — validates the full payload (account, sequence, flags, tx IDs) and de-duplicates signers.
  • Tests — byte-level codec vectors, signing/combine unit tests (cross-checked against xrpl.js), and integration tests (all-or-nothing, independent, multi-account, combine, ticket sequence).

Breaking: batch signatures from older versions are no longer valid; re-sign against a BatchV1_1 network.

Depends on rippled#6446 (BatchV1_1). CI runs the integration suite against a rippled built from that PR;

🤖 Generated with Claude Code

@coderabbitai

coderabbitai Bot commented Jun 24, 2026

Copy link
Copy Markdown
Contributor

Review Change Stack

Walkthrough

Updates XLS-56 Batch signing to the V1_1 format by expanding the BatchSigningDict type and encode_for_signing_batch function to include outer account, sequence, batch_account, and optional signer_account. Reworks sign_multiaccount_batch and combine_batch_signers for stronger validation and deduplication, and extends unit/integration tests accordingly. CI config and xrpld config are updated to reference BatchV1_1.

Changes

BatchV1_1 signing payload and signer management

Layer / File(s) Summary
BatchSigningDict contract and encode_for_signing_batch V1_1 payload
xrpl/core/binarycodec/main.py
BatchSigningDict gains account, sequence, batch_account (required) and signer_account (optional via NotRequired). encode_for_signing_batch is rewritten to emit the full V1_1 bound payload: prefix, outer account/sequence, flags, transaction-id count and hashes, batch_account, and optional signer_account.
sign_multiaccount_batch rework and combine_batch_signers validation
xrpl/transaction/batch_signers.py
Adds _resolve_sequence helper for ticket/sequence fallback. sign_multiaccount_batch gains batch_account and multisign: Union[bool, str] parameters, enforces signing account membership in involved accounts (including counterparty), and passes the expanded payload fields. Equivalence key for combine_batch_signers now spans outer account, sequence, flags, and inner hashes; signer collection adds sorting and deduplication by account.
Unit tests for binarycodec and batch_signers
tests/unit/core/binarycodec/test_main.py, tests/unit/transaction/test_batch_signers.py
Replaces test_batch with test_batch_single_signed and test_batch_multi_signed asserting new V1_1 hex encodings. Updates batch_signer unit tests with revised sequence values, new expected signatures, multisign/batch_account scenarios, and new combine_batch_signers edge-case tests (dedup, empty input, fully-signed blob, mismatched flags/account/sequence).
Integration tests for batch signing flows
tests/integration/transactions/test_batch.py
Renames test_basic_functionalitytest_all_or_nothing and test_multisigntest_multi_account_single_sign. Adds test_independent, test_combine_batch_signers (multi-account sign+combine+submit), and test_ticket_sequence (ticket-based batch sequence).
CI config, amendment identifier, and changelog
.github/workflows/integration_test.yml, .ci-config/xrpld.cfg, CHANGELOG.md
CI Docker image updated to ghcr.io/ckeshava/xrpld-batch-v1_1:latest. Amendment identifier changed from Batch to BatchV1_1. Changelog documents new sign_multiaccount_batch arguments and two fixes to signing payload binding and combine validation.

Sequence Diagram(s)

sequenceDiagram
    participant Client
    participant sign_multiaccount_batch
    participant encode_for_signing_batch
    participant combine_batch_signers

    rect rgba(100, 149, 237, 0.5)
        note over Client,sign_multiaccount_batch: Per-account signing
        Client->>sign_multiaccount_batch: wallet, Batch tx, batch_account, multisign
        sign_multiaccount_batch->>sign_multiaccount_batch: resolve sequence (sequence or ticket_sequence)
        sign_multiaccount_batch->>sign_multiaccount_batch: validate signing_account in involved_accounts
        sign_multiaccount_batch->>encode_for_signing_batch: account, sequence, flags, tx_ids, batch_account, [signer_account]
        encode_for_signing_batch-->>sign_multiaccount_batch: V1_1 signing payload bytes
        sign_multiaccount_batch-->>Client: Batch with new BatchSigner appended
    end

    rect rgba(144, 238, 144, 0.5)
        note over Client,combine_batch_signers: Combining signer fragments
        Client->>combine_batch_signers: [Batch_signed_by_A, Batch_signed_by_B]
        combine_batch_signers->>combine_batch_signers: validate equivalence key (account, seq, flags, tx hashes)
        combine_batch_signers->>combine_batch_signers: sort + deduplicate BatchSigners by account
        combine_batch_signers-->>Client: combined Batch with merged BatchSigners
    end
Loading

Estimated code review effort

🎯 4 (Complex) | ⏱️ ~45 minutes

Possibly related issues

Suggested reviewers

  • kuan121
  • pdp2121
  • cybele-ripple

Poem

🐇 Hop, hop, the batch is bound tight,
Account and sequence locked in right!
No replay tricks shall slip on through—
Deduplication keeps signers true.
Combined and sorted, off they go,
BatchV1_1 puts on quite a show! 🎉

🚥 Pre-merge checks | ✅ 4 | ❌ 1

❌ Failed checks (1 warning)

Check name Status Explanation Resolution
Docstring Coverage ⚠️ Warning Docstring coverage is 23.81% which is insufficient. The required threshold is 80.00%. Write docstrings for the functions missing them to satisfy the coverage threshold.
✅ Passed checks (4 passed)
Check name Status Explanation
Title check ✅ Passed The title is concise and accurately summarizes the main change: XLS-56 Batch V1_1 signing support.
Description check ✅ Passed It covers the overview, context, breaking change, and testing impact, with only some template sections left implicit.
Linked Issues check ✅ Passed Check skipped because no linked issues were found for this pull request.
Out of Scope Changes check ✅ Passed Check skipped because no linked issues were found for this pull request.

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

✨ Finishing Touches
🧪 Generate unit tests (beta)
  • Create PR with unit tests

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.

ckeshava and others added 6 commits June 24, 2026 09:49
…payload

Co-Authored-By: Claude Opus 4.8 (1M context) <noreply@anthropic.com>
…ar-key

Co-Authored-By: Claude Opus 4.8 (1M context) <noreply@anthropic.com>
…atch_signers

Co-Authored-By: Claude Opus 4.8 (1M context) <noreply@anthropic.com>
Co-Authored-By: Claude Opus 4.8 (1M context) <noreply@anthropic.com>
Co-Authored-By: Claude Opus 4.8 (1M context) <noreply@anthropic.com>
Co-Authored-By: Claude Opus 4.8 (1M context) <noreply@anthropic.com>
@ckeshava ckeshava force-pushed the feat/batch-v1_1-signing branch from 61ef7d1 to dbae6c8 Compare June 24, 2026 16:50
Comment thread CHANGELOG.md Outdated
Comment thread .github/workflows/integration_test.yml Outdated
Comment thread xrpl/core/binarycodec/main.py
ckeshava and others added 3 commits June 24, 2026 09:58
…strict

Co-Authored-By: Claude Opus 4.8 (1M context) <noreply@anthropic.com>
Co-Authored-By: Claude Opus 4.8 (1M context) <noreply@anthropic.com>
Co-Authored-By: Claude Opus 4.8 (1M context) <noreply@anthropic.com>
@ckeshava ckeshava marked this pull request as ready for review June 24, 2026 17:04

@coderabbitai coderabbitai Bot left a comment

Copy link
Copy Markdown
Contributor

Choose a reason for hiding this comment

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

Actionable comments posted: 2

🧹 Nitpick comments (1)
tests/unit/transaction/test_batch_signers.py (1)

27-34: 📐 Maintainability & Code Quality | 🔵 Trivial | 💤 Low value

Consider deriving REGKEY_PUBLIC_KEY instead of hardcoding.

REGKEY_PUBLIC_KEY duplicates regkey_wallet.public_key. Using REGKEY_PUBLIC_KEY = regkey_wallet.public_key removes the magic constant and keeps the fixture self-consistent if the seed ever changes; the txn_signature assertions still pin the cryptographic behavior.

🤖 Prompt for AI Agents
Verify each finding against current code. Fix only still-valid issues, skip the
rest with a brief reason, keep changes minimal, and validate.

In `@tests/unit/transaction/test_batch_signers.py` around lines 27 - 34, The test
fixture currently hardcodes REGKEY_PUBLIC_KEY even though it duplicates
regkey_wallet.public_key. Update the setup in test_batch_signers.py so
REGKEY_PUBLIC_KEY is derived from regkey_wallet.public_key, keeping the fixture
self-consistent and avoiding a magic constant while preserving the existing
txn_signature assertions.
🤖 Prompt for all review comments with AI agents
Verify each finding against current code. Fix only still-valid issues, skip the
rest with a brief reason, keep changes minimal, and validate.

Inline comments:
In @.github/workflows/integration_test.yml:
- Line 8: The XRPLD_DOCKER_IMAGE value is using a mutable latest tag, which
makes integration runs non-reproducible. Update the workflow variable in the
integration_test.yml configuration to reference a pinned image digest instead of
:latest, keeping the XRPLD_DOCKER_IMAGE identifier the same but replacing the
tag with an immutable digest so runs always use the same image.

In `@xrpl/transaction/batch_signers.py`:
- Around line 191-198: The deduping logic in the BatchSigners combination path
is too aggressive because it drops later entries with the same
BatchSigner.account even when they contain distinct nested multisigners. Update
the merge logic in the BatchSigner accumulation code to detect duplicate account
entries, then either combine and sort their nested signers by Signer.account
when they are compatible or explicitly reject incompatible direct-vs-multisigned
duplicates. Make the fix in the deduping block that builds deduped_signers so
valid signatures are preserved instead of silently keeping only the first
fragment.

---

Nitpick comments:
In `@tests/unit/transaction/test_batch_signers.py`:
- Around line 27-34: The test fixture currently hardcodes REGKEY_PUBLIC_KEY even
though it duplicates regkey_wallet.public_key. Update the setup in
test_batch_signers.py so REGKEY_PUBLIC_KEY is derived from
regkey_wallet.public_key, keeping the fixture self-consistent and avoiding a
magic constant while preserving the existing txn_signature assertions.
🪄 Autofix (Beta)

Fix all unresolved CodeRabbit comments on this PR:

  • Push a commit to this branch (recommended)
  • Create a new PR with the fixes

ℹ️ Review info
⚙️ Run configuration

Configuration used: Path: .coderabbit.yaml

Review profile: CHILL

Plan: Pro

Run ID: 22f7cf05-e520-456a-9714-f80cf3337af7

📥 Commits

Reviewing files that changed from the base of the PR and between 9f9281e and 06ad478.

📒 Files selected for processing (8)
  • .ci-config/xrpld.cfg
  • .github/workflows/integration_test.yml
  • CHANGELOG.md
  • tests/integration/transactions/test_batch.py
  • tests/unit/core/binarycodec/test_main.py
  • tests/unit/transaction/test_batch_signers.py
  • xrpl/core/binarycodec/main.py
  • xrpl/transaction/batch_signers.py

# Standalone rippled with the XLS-56 BatchV1_1 amendment, built from the amd64
# binary artifact of https://github.com/XRPLF/rippled/pull/6446 and pushed to
# GHCR. Revert to rippleci/xrpld:develop once BatchV1_1 lands in develop.
XRPLD_DOCKER_IMAGE: ghcr.io/ckeshava/xrpld-batch-v1_1:latest

Copy link
Copy Markdown
Contributor

Choose a reason for hiding this comment

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

🩺 Stability & Availability | 🟠 Major | ⚡ Quick win

Pin the XRPLD image by digest instead of :latest.

Line 8 currently uses a mutable tag, so integration runs are not reproducible and can fail unexpectedly when the tag moves.

Suggested change
-  XRPLD_DOCKER_IMAGE: ghcr.io/ckeshava/xrpld-batch-v1_1:latest
+  XRPLD_DOCKER_IMAGE: ghcr.io/ckeshava/xrpld-batch-v1_1@sha256:<pinned_digest>
🤖 Prompt for AI Agents
Verify each finding against current code. Fix only still-valid issues, skip the
rest with a brief reason, keep changes minimal, and validate.

In @.github/workflows/integration_test.yml at line 8, The XRPLD_DOCKER_IMAGE
value is using a mutable latest tag, which makes integration runs
non-reproducible. Update the workflow variable in the integration_test.yml
configuration to reference a pinned image digest instead of :latest, keeping the
XRPLD_DOCKER_IMAGE identifier the same but replacing the tag with an immutable
digest so runs always use the same image.

Comment on lines +191 to +198
# BatchSigners must be strictly ascending and unique by account, so
# de-duplicate when combining fragments that share a signer.
deduped_signers: List[BatchSigner] = []
last_account: Optional[str] = None
for signer in batch_signers:
if signer.account != last_account:
deduped_signers.append(signer)
last_account = signer.account

Copy link
Copy Markdown
Contributor

Choose a reason for hiding this comment

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

🗄️ Data Integrity & Integration | 🟠 Major | 🏗️ Heavy lift

Merge nested multisigners before deduping BatchSigner.account.

Line 196 drops every later BatchSigner with the same account. With the new multisign path, two fragments can validly share BatchSigner.account while carrying different nested Signer.account entries, so the combined transaction loses required signatures. Merge and sort nested signers for equal accounts, or reject incompatible direct-vs-multisigned duplicates instead of silently keeping the first one.

🤖 Prompt for AI Agents
Verify each finding against current code. Fix only still-valid issues, skip the
rest with a brief reason, keep changes minimal, and validate.

In `@xrpl/transaction/batch_signers.py` around lines 191 - 198, The deduping logic
in the BatchSigners combination path is too aggressive because it drops later
entries with the same BatchSigner.account even when they contain distinct nested
multisigners. Update the merge logic in the BatchSigner accumulation code to
detect duplicate account entries, then either combine and sort their nested
signers by Signer.account when they are compatible or explicitly reject
incompatible direct-vs-multisigned duplicates. Make the fix in the deduping
block that builds deduped_signers so valid signatures are preserved instead of
silently keeping only the first fragment.

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.

1 participant