Skip to content

Transaction model, unit and integ tests for Delegate XLS-74d amendment #833

New issue

Have a question about this project? Sign up for a free GitHub account to open an issue and contact its maintainers and the community.

By clicking “Sign up for GitHub”, you agree to our terms of service and privacy statement. We’ll occasionally send you account related emails.

Already on GitHub? Sign in to your account

Open
wants to merge 5 commits into
base: main
Choose a base branch
from

Conversation

ckeshava
Copy link
Collaborator

High Level Overview of Change

This PR implements changes pertaining to the XLS-74d and XLS-75d amendments.

Here is the associated cpp implementation.

Note: This PR succeeds https://github.com/XRPLF/xrpl-py/pull/807/files. I chose to create a new PR owing to the major updates to the specification.

Context of Change

Type of Change

  • Bug fix (non-breaking change which fixes an issue)
  • New feature (non-breaking change which adds functionality)
  • Breaking change (fix or feature that would cause existing functionality to not work as expected)
  • Refactor (non-breaking change that only restructures code)
  • Tests (You added tests for code that already exists, or your new feature included in this PR)
  • Documentation Updates
  • Release

Did you update CHANGELOG.md?

  • Yes
  • No, this change does not impact library users

Test Plan

Appropriate unit and integration tests have been added to this PR. The integration tests are validated by running a local rippled executable compiled from the attached feature-branch. As of today, this executable is not available as a docker container because the cpp-implementation hasn't been merged into develop branch of rippled repository.

Copy link
Contributor

coderabbitai bot commented Apr 30, 2025

Walkthrough

This update introduces support for delegate-based account permissions in the XRPL Python SDK. It adds new transaction and ledger entry types for delegation, including the DelegateSet transaction and related permission structures. The binary codec definitions, models, and transaction type enumerations are extended to accommodate these features. Integration and unit tests are added to validate delegate set workflows, permission validation, and ledger entry queries. The configuration and changelog are updated to reflect the inclusion of the new features and amendments.

Changes

File(s) Change Summary
.ci-config/rippled.cfg Added the "PermissionDelegation" amendment to the enabled features list.
CHANGELOG.md Updated the "Unreleased" section to mention support for Account Permission and Account Permission Delegation (XLS-74d, XLS-75d).
xrpl/core/binarycodec/definitions/definitions.json Added new fields ("PermissionValue", "Delegate", "Permission", "Permissions"), a new ledger entry type ("Delegate"), and a new transaction type ("DelegateSet") to support permission delegation.
xrpl/models/transactions/types/transaction_type.py Added DELEGATE_SET = "DelegateSet" to the TransactionType enum.
xrpl/models/transactions/__init__.py Imported and exported the new DelegateSet transaction model.
xrpl/models/transactions/delegate_set.py Introduced the DelegateSet transaction model and nested Permission model, including validation logic for permissions and account addresses.
xrpl/models/transactions/transaction.py Added an optional delegate field to the Transaction class and enforced validation to prevent account and delegate from being the same.
xrpl/models/requests/ledger_entry.py Added a Delegate dataclass and extended the LedgerEntry model to support querying delegate ledger entries. Updated error validation to include the new field in exclusivity checks.
tests/unit/models/transactions/test_delegate_set.py Added unit tests for the DelegateSet transaction model, covering valid cases, permission limits, duplicate permissions, and account/authorize address validation.
tests/integration/transactions/test_delegate_set.py Added integration tests for delegate set transactions, including cases for missing permissions, successful delegation workflows, and ledger entry queries.

Sequence Diagram(s)

sequenceDiagram
    participant Client
    participant XRPL SDK
    participant Ledger

    Client->>XRPL SDK: Create DelegateSet transaction (authorize, permissions)
    XRPL SDK->>Ledger: Submit DelegateSet transaction
    Ledger-->>XRPL SDK: DelegateSet transaction result

    Client->>XRPL SDK: Submit Payment (signed by delegate)
    XRPL SDK->>Ledger: Process Payment (check delegate permissions)
    Ledger-->>XRPL SDK: Payment result (success/failure)
Loading
sequenceDiagram
    participant Client
    participant XRPL SDK
    participant Ledger

    Client->>XRPL SDK: Query LedgerEntry (delegate)
    XRPL SDK->>Ledger: Fetch delegate ledger entry
    Ledger-->>XRPL SDK: Return delegate ledger entry details
    XRPL SDK-->>Client: Delegate ledger entry response
Loading

Suggested reviewers

  • achowdhry-ripple
  • khancode
  • mvadari

Poem

In the ledger’s warren, permissions now bloom,
Delegates hop in, dispelling old gloom.
With tests that ensure no rabbit’s astray,
And configs that guide us the delegate way.
New models and types, all neat in their bed—
A hop, skip, and jump for the code straight ahead!
🐇✨


📜 Recent review details

Configuration used: .coderabbit.yaml
Review profile: CHILL
Plan: Pro

📥 Commits

Reviewing files that changed from the base of the PR and between 4b1491b and 1d4b3d8.

📒 Files selected for processing (1)
  • xrpl/models/transactions/transaction.py (3 hunks)
🚧 Files skipped from review as they are similar to previous changes (1)
  • xrpl/models/transactions/transaction.py
⏰ Context from checks skipped due to timeout of 90000ms (6)
  • GitHub Check: Snippet test (3.12)
  • GitHub Check: Snippet test (3.10)
  • GitHub Check: Snippet test (3.13)
  • GitHub Check: Snippet test (3.8)
  • GitHub Check: Snippet test (3.11)
  • GitHub Check: Snippet test (3.9)
✨ Finishing Touches
  • 📝 Generate Docstrings

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
🪧 Tips

Chat

There are 3 ways to chat with CodeRabbit:

  • Review comments: Directly reply to a review comment made by CodeRabbit. Example:
    • I pushed a fix in commit <commit_id>, please review it.
    • Generate unit testing code for this file.
    • Open a follow-up GitHub issue for this discussion.
  • Files and specific lines of code (under the "Files changed" tab): Tag @coderabbitai in a new review comment at the desired location with your query. Examples:
    • @coderabbitai generate unit testing code for this file.
    • @coderabbitai modularize this function.
  • PR comments: Tag @coderabbitai in a new PR comment to ask questions about the PR branch. For the best results, please provide a very specific query, as very limited context is provided in this mode. Examples:
    • @coderabbitai gather interesting stats about this repository and render them as a table. Additionally, render a pie chart showing the language distribution in the codebase.
    • @coderabbitai read src/utils.ts and generate unit testing code.
    • @coderabbitai read the files in the src/scheduler package and generate a class diagram using mermaid and a README in the markdown format.
    • @coderabbitai help me debug CodeRabbit configuration file.

Support

Need help? Create a ticket on our support page for assistance with any issues or questions.

Note: Be mindful of the bot's finite context window. It's strongly recommended to break down tasks such as reading entire modules into smaller chunks. For a focused discussion, use review comments to chat about specific files and their changes, instead of using the PR comments.

CodeRabbit Commands (Invoked using PR comments)

  • @coderabbitai pause to pause the reviews on a PR.
  • @coderabbitai resume to resume the paused reviews.
  • @coderabbitai review to trigger an incremental review. This is useful when automatic reviews are disabled for the repository.
  • @coderabbitai full review to do a full review from scratch and review all the files again.
  • @coderabbitai summary to regenerate the summary of the PR.
  • @coderabbitai generate docstrings to generate docstrings for this PR.
  • @coderabbitai generate sequence diagram to generate a sequence diagram of the changes in this PR.
  • @coderabbitai resolve resolve all the CodeRabbit review comments.
  • @coderabbitai configuration to show the current CodeRabbit configuration for the repository.
  • @coderabbitai help to get help.

Other keywords and placeholders

  • Add @coderabbitai ignore anywhere in the PR description to prevent this PR from being reviewed.
  • Add @coderabbitai summary to generate the high-level summary at a specific location in the PR description.
  • Add @coderabbitai anywhere in the PR title to generate the title automatically.

Documentation and Community

  • Visit our Documentation for detailed information on how to use CodeRabbit.
  • Join our Discord Community to get help, request features, and share feedback.
  • Follow us on X/Twitter for updates and announcements.

@ckeshava ckeshava requested review from khancode and pdp2121 April 30, 2025 23:10
@ckeshava ckeshava mentioned this pull request Apr 30, 2025
9 tasks
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: 3

🧹 Nitpick comments (3)
xrpl/models/transactions/transaction.py (1)

27-29: Consider adding parentheses for multi-line function parameters.

Adding a trailing comma to the parameter list is good practice for future extensibility, but consider also enclosing the parameter in parentheses for better readability of multi-line function signatures.

- def transaction_json_to_binary_codec_form(
-     dictionary: Dict[str, XRPL_VALUE_TYPE],
- ) -> Dict[str, XRPL_VALUE_TYPE]:
+ def transaction_json_to_binary_codec_form(
+     (
+         dictionary: Dict[str, XRPL_VALUE_TYPE],
+     )
+ ) -> Dict[str, XRPL_VALUE_TYPE]:
tests/integration/transactions/test_delegate_set.py (1)

84-122: LGTM: Delegate ledger entry query test.

This test properly validates that delegate ledger entries can be queried using the LedgerEntry request with the new Delegate model, and checks that the returned data contains the expected fields.

Pipeline error note: The test failure appears to be unrelated to your code implementation and is likely due to connection issues with the test environment.

xrpl/models/transactions/delegate_set.py (1)

88-99: Consider validating permission values against known permissions.

The current implementation checks for duplicate permissions and enforces a maximum list length, which is good. However, it doesn't validate whether the permission_value values are known/valid according to the GRANULAR_PERMISSIONS dictionary.

Consider adding validation to ensure only recognized permission values are used, or document if arbitrary values are intentionally allowed.

def _get_permissions_error(self: Self) -> Optional[str]:
    if len(self.permissions) > PERMISSION_MAX_LENGTH:
        return (
            f"Length of `permissions` list is greater than {PERMISSION_MAX_LENGTH}."
        )

    permission_unique_values = set()
    for permission in self.permissions:
+       # Optional: Validate against known permissions
+       if permission.permission_value not in GRANULAR_PERMISSIONS.values():
+           return f"Unknown permission value: {permission.permission_value}"
+           
        if permission.permission_value in permission_unique_values:
            return "Duplicate permission value in `permissions` list."
        permission_unique_values.add(permission.permission_value)
    return None
📜 Review details

Configuration used: .coderabbit.yaml
Review profile: CHILL
Plan: Pro

📥 Commits

Reviewing files that changed from the base of the PR and between dd0e610 and d2ee762.

📒 Files selected for processing (10)
  • .ci-config/rippled.cfg (1 hunks)
  • CHANGELOG.md (1 hunks)
  • tests/integration/transactions/test_delegate_set.py (1 hunks)
  • tests/unit/models/transactions/test_delegate_set.py (1 hunks)
  • xrpl/core/binarycodec/definitions/definitions.json (6 hunks)
  • xrpl/models/requests/ledger_entry.py (3 hunks)
  • xrpl/models/transactions/__init__.py (2 hunks)
  • xrpl/models/transactions/delegate_set.py (1 hunks)
  • xrpl/models/transactions/transaction.py (3 hunks)
  • xrpl/models/transactions/types/transaction_type.py (1 hunks)
🧰 Additional context used
🧬 Code Graph Analysis (3)
xrpl/models/transactions/__init__.py (1)
xrpl/models/transactions/delegate_set.py (1)
  • DelegateSet (55-99)
tests/unit/models/transactions/test_delegate_set.py (3)
xrpl/models/exceptions.py (1)
  • XRPLModelException (6-9)
xrpl/models/transactions/delegate_set.py (2)
  • DelegateSet (55-99)
  • Permission (40-50)
xrpl/models/base_model.py (1)
  • is_valid (292-299)
tests/integration/transactions/test_delegate_set.py (8)
tests/integration/integration_test_case.py (1)
  • IntegrationTestCase (9-18)
tests/integration/it_utils.py (3)
  • fund_wallet_async (117-126)
  • sign_and_reliable_submission_async (188-220)
  • test_async_and_sync (265-360)
xrpl/models/requests/ledger_entry.py (2)
  • LedgerEntry (316-394)
  • Delegate (71-89)
xrpl/models/response.py (2)
  • ResponseStatus (23-27)
  • is_successful (74-82)
xrpl/models/transactions/delegate_set.py (2)
  • DelegateSet (55-99)
  • Permission (40-50)
xrpl/models/transactions/payment.py (1)
  • Payment (69-182)
xrpl/utils/xrp_conversions.py (1)
  • xrp_to_drops (25-70)
xrpl/wallet/main.py (3)
  • Wallet (16-290)
  • create (120-134)
  • address (24-29)
🪛 GitHub Actions: Unit test
tests/unit/models/transactions/test_delegate_set.py

[error] 77-77: flake8: line too long (90 > 88 characters) (E501)

xrpl/models/transactions/delegate_set.py

[error] 19-19: flake8: trailing whitespace (W291)

🪛 GitHub Actions: Integration test
tests/unit/models/transactions/test_delegate_set.py

[error] 1-20: Setup failure: ConnectionRefusedError: Connect call failed to 127.0.0.1:6006 during websocket client open.

tests/integration/transactions/test_delegate_set.py

[error] 12-12: ConnectionRefusedError: Connect call failed ('127.0.0.1', 6006) during WebSocket client open in setUpClass.

⏰ Context from checks skipped due to timeout of 90000ms (6)
  • GitHub Check: Snippet test (3.13)
  • GitHub Check: Snippet test (3.9)
  • GitHub Check: Snippet test (3.12)
  • GitHub Check: Snippet test (3.11)
  • GitHub Check: Snippet test (3.10)
  • GitHub Check: Snippet test (3.8)
🔇 Additional comments (21)
.ci-config/rippled.cfg (1)

199-199: LGTM: Added PermissionDelegation amendment

The configuration has been correctly updated to include the new PermissionDelegation amendment, which enables the account delegation features introduced in this PR.

xrpl/models/transactions/types/transaction_type.py (1)

25-25: LGTM: Added DELEGATE_SET transaction type

The TransactionType enum has been properly extended with the new DELEGATE_SET entry, allowing for DelegateSet transactions in the XRPL.

CHANGELOG.md (1)

17-17: LGTM: Added changelog entry for new features

The changelog has been properly updated to document the addition of Account Permission and Account Permission Delegation features with appropriate references to XLS-74d and XLS-75d.

xrpl/models/transactions/__init__.py (2)

35-35: LGTM: Added DelegateSet import

The DelegateSet class is now properly imported from its module.


145-145: LGTM: Added DelegateSet to exports

DelegateSet has been correctly added to the all list, making it publicly accessible when importing from the package.

tests/unit/models/transactions/test_delegate_set.py (2)

1-79: Comprehensive test coverage for DelegateSet transactions

The test suite thoroughly validates the DelegateSet transaction model's core functionality and constraints, including basic operations, granular permissions, and various validation scenarios.

🧰 Tools
🪛 GitHub Actions: Unit test

[error] 77-77: flake8: line too long (90 > 88 characters) (E501)

🪛 GitHub Actions: Integration test

[error] 1-20: Setup failure: ConnectionRefusedError: Connect call failed to 127.0.0.1:6006 during websocket client open.


1-20:

❓ Verification inconclusive

Note the integration test connection failure

There is a pipeline failure in the integration tests showing a connection error to the websocket client. This might be an infrastructure issue rather than a code problem.

Verify that the rippled server configured with the PermissionDelegation amendment is running and accessible during integration tests:


🏁 Script executed:

#!/bin/bash
# Check if the rippled server is running and accessible
curl -s http://127.0.0.1:5005 -X POST -H "Content-Type: application/json" \
  -d '{"method": "server_info", "params": [{}]}' | grep -i "error\|success"

# Check if PermissionDelegation amendment is enabled
curl -s http://127.0.0.1:5005 -X POST -H "Content-Type: application/json" \
  -d '{"method": "feature", "params": [{"feature": "PermissionDelegation"}]}' | grep -i "status\|enabled"

Length of output: 329


Ensure rippled node is running on port 5005 with PermissionDelegation enabled

The integration tests are failing with a connection error, and the previous curl checks produced no output. Please verify the following before rerunning the pipeline:

  • The rippled process is up and listening on 127.0.0.1:5005 (e.g. lsof -i:5005 or netstat -an | grep 5005).
  • You can reach the server via RPC:
    curl -s http://127.0.0.1:5005 \
      -X POST -H "Content-Type: application/json" \
      -d '{"method": "server_info","params":[{}]}' | jq
    Expect to see a "status":"success" response.
  • The PermissionDelegation amendment is enabled in your rippled.cfg:
    curl -s http://127.0.0.1:5005 \
      -X POST -H "Content-Type: application/json" \
      -d '{"method": "feature","params":[{"feature":"PermissionDelegation"}]}' | jq
    Look for "enabled":true.

Once confirmed, re-run the integration tests.

🧰 Tools
🪛 GitHub Actions: Integration test

[error] 1-20: Setup failure: ConnectionRefusedError: Connect call failed to 127.0.0.1:6006 during websocket client open.

xrpl/models/transactions/transaction.py (1)

256-258: LGTM: New delegate field added to support delegate transactions.

This new optional field properly supports the delegate functionality being added in the XLS-74d amendment, allowing transactions to be signed by a delegate account.

xrpl/core/binarycodec/definitions/definitions.json (6)

673-682: LGTM: New PermissionValue field definition added.

This properly defines the PermissionValue field as a UInt32 type with appropriate serialization and signing flags for the delegation feature.


1963-1972: LGTM: New Delegate field definition added.

This properly defines the Delegate field as an AccountID type with appropriate serialization and signing flags for the delegation feature.


2183-2192: LGTM: New Permission object definition added.

This properly defines the Permission field as an STObject type with appropriate serialization and signing flags for the delegation feature.


2582-2590: LGTM: New Permissions array definition added.

This properly defines the Permissions field as an STArray type with appropriate serialization and signing flags for the delegation feature.


2910-2910: LGTM: New Delegate ledger entry type definition added.

The Delegate ledger entry type is properly defined with a unique code (131) that doesn't conflict with existing ledger entry types.


3131-3131: LGTM: New DelegateSet transaction type definition added.

The DelegateSet transaction type is properly defined with a unique code (64) that doesn't conflict with existing transaction types.

xrpl/models/requests/ledger_entry.py (3)

69-90: LGTM: New Delegate model for ledger entry queries.

The Delegate class is properly implemented as a dataclass with required account and authorize fields, matching the structure of the delegate ledger entry. The documentation clearly explains its purpose.


330-330: LGTM: Added delegate field to LedgerEntry class.

This properly adds the optional delegate field to the LedgerEntry class, allowing for querying delegate ledger entries.


365-365: LGTM: Updated validation logic to include delegate field.

The _get_errors method is properly updated to include the delegate field in the list of mutually exclusive query parameters, maintaining the validation that exactly one ledger entry identifier is provided.

tests/integration/transactions/test_delegate_set.py (3)

1-14: LGTM: Appropriate imports for delegate feature tests.

All necessary imports are included for testing the delegate feature, including the new DelegateSet transaction type, Permission model, and Delegate ledger entry model.

🧰 Tools
🪛 GitHub Actions: Integration test

[error] 12-12: ConnectionRefusedError: Connect call failed ('127.0.0.1', 6006) during WebSocket client open in setUpClass.


16-41: LGTM: Test for unauthorized delegation.

This test correctly verifies that a delegate cannot execute a transaction without proper permission, validating the security aspect of the delegate feature.


42-83: LGTM: Complete delegate workflow test.

This test case properly validates the complete delegate flow:

  1. Setting permissions with DelegateSet transaction
  2. Executing a Payment transaction as a delegate
  3. Verifying the transaction was properly signed by the delegate

The permission value (1 + 0) corresponds to the Payment transaction type (0) with a permission bit (1).

xrpl/models/transactions/delegate_set.py (1)

1-100: Overall implementation looks solid.

The DelegateSet transaction model and supporting Permission class are well-structured and follow the design patterns of the XRPL SDK. The implementation includes appropriate validation logic to ensure:

  1. The authorizing account is different from the transaction account
  2. No more than 10 permissions are included
  3. No duplicate permissions exist

The utility dictionary of granular permissions provides good documentation for developers implementing this feature.

🧰 Tools
🪛 GitHub Actions: Unit test

[error] 19-19: flake8: trailing whitespace (W291)

)
self.assertEqual(
error.exception.args[0],
"{'account_addresses': 'Field `authorize` and `account` must be different.'}",
Copy link
Contributor

@coderabbitai coderabbitai bot Apr 30, 2025

Choose a reason for hiding this comment

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

⚠️ Potential issue

Fix line length to comply with flake8

The line exceeds the maximum length limit (90 > 88 characters).

-            "{'account_addresses': 'Field `authorize` and `account` must be different.'}",
+            "{'account_addresses': 'Field `authorize` and `account` must be different.'}",

Consider either:

  1. Breaking this line into multiple lines, or
  2. Using a shorter error message in the test
-            "{'account_addresses': 'Field `authorize` and `account` must be different.'}",
+            "{'account_addresses': 'Field `authorize` and `account` must be "
+            "different.'}",
📝 Committable suggestion

‼️ IMPORTANT
Carefully review the code before committing. Ensure that it accurately replaces the highlighted code, contains no missing lines, and has no issues with indentation. Thoroughly test & benchmark the code to ensure it meets the requirements.

Suggested change
"{'account_addresses': 'Field `authorize` and `account` must be different.'}",
"{'account_addresses': 'Field `authorize` and `account` must be "
"different.'}",
🧰 Tools
🪛 GitHub Actions: Unit test

[error] 77-77: flake8: line too long (90 > 88 characters) (E501)

Copy link
Collaborator Author

Choose a reason for hiding this comment

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

The linter (and flake8) haven't thrown any errors over this line. This is not a necessary update.

Copy link
Contributor

Choose a reason for hiding this comment

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

@ckeshava I understand you're not seeing this error locally, but the GitHub Actions CI shows a flake8 error for this line: "flake8: line too long (90 > 88 characters) (E501)".

This discrepancy might be due to different flake8 configurations between your local environment and the CI pipeline. The CI is enforcing an 88-character limit, which this line exceeds at 90 characters.

Would you like me to help investigate the flake8 configuration in the project to resolve this inconsistency?

Copy link
Collaborator Author

Choose a reason for hiding this comment

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

updated in 1d4b3d8

Copy link
Contributor

Choose a reason for hiding this comment

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

@ckeshava Thank you for confirming that you've addressed the line length issue in commit 1d4b3d8. Great work on resolving this flake8 warning!


If you found this review helpful, would you consider giving us a shout-out on X?

Thank you for using CodeRabbit!

f"Length of `permissions` list is greater than {PERMISSION_MAX_LENGTH}."
)

permission_unique_values = set()
Copy link
Collaborator

Choose a reason for hiding this comment

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

Probably can just use if self.permissions != set(self.permissions)

Copy link
Collaborator Author

Choose a reason for hiding this comment

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

thanks. updated in 4b1491b


authorize: str = REQUIRED # type: ignore
"""
This field is required.
Copy link
Collaborator

Choose a reason for hiding this comment

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

Could you add description for this field?

Copy link
Collaborator Author

Choose a reason for hiding this comment

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

added description in 4b1491b

ckeshava and others added 3 commits May 2, 2025 11:37
Co-authored-by: coderabbitai[bot] <136622811+coderabbitai[bot]@users.noreply.github.com>
@ckeshava ckeshava requested a review from pdp2121 May 2, 2025 18:48
@Patel-Raj11
Copy link
Collaborator

Patel-Raj11 commented May 6, 2025

@pdp2121 @khancode Please hold for some time reviewing this PR as I am going to raise a new PR with a few changes with respect to permission_value field of class Permission as it's a string as opposed to int as per the spec. So unit test cases, and integration test cases will change.

I'll raise a PR once the cpp PR is merged in develop and we have a docker image to write 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.

3 participants