-
Notifications
You must be signed in to change notification settings - Fork 86
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
XLS-80d Permissioned Domains #773
base: cred
Are you sure you want to change the base?
Conversation
update definitions.json integration test framework merge common models from Verifiable Credentials amendment Unit tests for PDSet transaction Update rippled.cfg with latest fixes, features
Important Review skippedAuto reviews are disabled on base/target branches other than the default branch. Please check the settings in the CodeRabbit UI or the You can disable this status message by setting the WalkthroughThe pull request introduces significant enhancements across various files, primarily focusing on the addition of credential and permissioned domain functionalities. Key changes include updates to configuration files, the introduction of new transaction types and models for credentials, and enhancements to existing transaction handling, particularly in validation and error management. The integration tests have also been expanded to cover new features, ensuring comprehensive testing of the newly introduced functionalities. Changes
Possibly related PRs
Suggested reviewers
Thank you for using CodeRabbit. We offer it for free to the OSS community and would appreciate your support in helping us grow. If you find it useful, would you consider giving us a shout-out on your favorite social media? 🪧 TipsChatThere are 3 ways to chat with CodeRabbit:
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)
Other keywords and placeholders
Documentation and Community
|
There was a problem hiding this comment.
Choose a reason for hiding this comment
The reason will be displayed to describe this comment to others. Learn more.
Actionable comments posted: 23
🧹 Outside diff range and nitpick comments (61)
tests/unit/models/requests/test_deposit_authorized.py (1)
9-10
: Use realistic test data for account addressesThe current test uses placeholder values "srcAccount" and "dstAccount" which don't match the format of actual XRPL addresses. Consider using valid XRPL address formats to ensure proper validation.
Example:
- source_account="srcAccount", - destination_account="dstAccount", + source_account="rHb9CJAWyB4rj91VRWn96DkukG4bwdtyTh", + destination_account="rPT1Sjq2YGrBMTttX4GZHjKu9dyfzbpAYe",xrpl/models/transactions/permissioned_domain_delete.py (1)
14-14
: Enhance class documentation with more details.The current docstring could be more helpful by including:
- Purpose and use cases of PermissionedDomainDelete
- Format and requirements for the domain_id field
- Example usage
- Link to the XRPL documentation about PermissionedDomains
- """Represents a PermissionedDomainDelete transaction""" + """ + Represents a PermissionedDomainDelete transaction, which removes a domain from the + permissioned domains list. + + The domain_id must be a valid HASH256 value obtained from the rippled RPC. + + Example: + PermissionedDomainDelete( + account="rMail...", + domain_id="ABCD...", + fee="10", + sequence=4, + ) + + See Also: + https://xrpl.org/permissioneddomaindelete.html + """xrpl/models/requests/deposit_authorized.py (1)
42-46
: Consider enhancing the credentials field documentationThe implementation looks good, but the documentation could be more helpful by including:
- An example of valid credential IDs format
- Any constraints or validation rules for the credential IDs
Consider adding to the docstring:
"""The object IDs of Credential objects. If this field is included, then the credential will be taken into account when analyzing whether the sender can send funds to the destination. + + Example: + credentials=["0123456789ABCDEF0123456789ABCDEF0123456789ABCDEF0123456789ABCDEF"] """.github/workflows/integration_test.yml (1)
35-36
: Docker configuration improvements look good with one suggestionThe changes improve the container configuration:
- More standard volume mount path
- Better health check using
rippled server_info
- Explicit service startup
- More descriptive container name
However, the 2-second health check timeout might be too aggressive for initial startup.
Consider increasing the health check timeout:
- --health-timeout=2s + --health-timeout=5sxrpl/models/transactions/permissioned_domain_set.py (2)
31-52
: Enhance error validation implementationWhile the validation logic is correct, consider these improvements:
- Use more specific error dictionary keys (e.g., "EmptyCredentials", "MaxCredentialsExceeded", "DuplicateCredentials")
- Split validation into separate methods for better testability
- Use set operation for duplicate detection
def _get_errors(self: Self) -> Dict[str, str]: errors = super()._get_errors() - - def _validate_credentials_length( - credentials: List[Credential], field_name: str - ) -> None: - if len(credentials) == 0: - errors["PermissionedDomainSet"] = f"{field_name} list cannot be empty." - elif len(credentials) > _MAX_ACCEPTED_CREDENTIALS_LENGTH: - errors["PermissionedDomainSet"] = ( - f"{field_name} list cannot have more than " - + f"{_MAX_ACCEPTED_CREDENTIALS_LENGTH} elements." - ) - - if len(credentials) != len(set(credentials)): - errors["PermissionedDomainSet"] = ( - f"{field_name} list cannot contain duplicate credentials." - ) - - _validate_credentials_length(self.accepted_credentials, "AcceptedCredentials") + if len(self.accepted_credentials) == 0: + errors["EmptyCredentials"] = "AcceptedCredentials list cannot be empty." + elif len(self.accepted_credentials) > _MAX_ACCEPTED_CREDENTIALS_LENGTH: + errors["MaxCredentialsExceeded"] = ( + f"AcceptedCredentials list cannot have more than " + f"{_MAX_ACCEPTED_CREDENTIALS_LENGTH} elements." + ) + + unique_credentials = set(self.accepted_credentials) + if len(self.accepted_credentials) != len(unique_credentials): + errors["DuplicateCredentials"] = ( + "AcceptedCredentials list cannot contain duplicate credentials." + ) return errors
1-52
: Add missing unit testsThe PR objectives mention that no unit tests were created for the
PermissionedDomainDelete
transaction. While this file implementsPermissionedDomainSet
, it's important to maintain consistent test coverage across related features.Would you like me to help create unit tests for both transaction types to ensure comprehensive coverage?
tests/unit/models/transactions/test_permissioned_domain_set.py (3)
4-4
: Consider relocating theCredential
class to a more appropriate module.The
Credential
class is currently imported fromdeposit_preauth
, which seems architecturally misplaced. Consider moving it to a dedicated credentials-related module for better separation of concerns.
21-22
: Document the hardcoded domain_id value.The
domain_id
value appears to be hardcoded without explanation. Consider adding a comment explaining its significance or moving it to a named constant with documentation.
42-44
: Use f-strings for better readability.Consider using an f-string instead of string concatenation for the error message assertion:
- "{'PermissionedDomainSet': 'AcceptedCredentials list cannot have more than " - + "10 elements.'}", + "{'PermissionedDomainSet': 'AcceptedCredentials list cannot have more than 10 elements.'}"tests/unit/models/transactions/test_account_delete.py (2)
52-60
: Consider adding more test casesThe test suite would benefit from additional test cases:
- Test with invalid credential ID format
- Test with null/None credential_ids
- Test with mixed-case credential IDs to verify case sensitivity
Example test case:
def test_invalid_credential_id_format(self): """Test that AccountDelete raises exception for invalid credential ID format.""" with self.assertRaises(XRPLModelException) as err: AccountDelete( account=_ACCOUNT, destination=_DESTINATION, credential_ids=["invalid_hash_format"], ) self.assertEqual( err.exception.args[0], "{'credential_ids': 'Invalid credential ID format.'}" )
23-24
: Improve string concatenation in error messagesInstead of using string concatenation with
+
, consider using multi-line strings or f-strings for better readability.- "{'credential_ids': 'CredentialIDs list cannot have more than 8 elements." - + "'}", + "{'credential_ids': 'CredentialIDs list cannot have more than 8 elements.'}", - "{'credential_ids_duplicates': 'CredentialIDs list cannot contain duplicate" - + " values.'}", + "{'credential_ids_duplicates': 'CredentialIDs list cannot contain duplicate values.'}",Also applies to: 48-49
tests/unit/models/transactions/test_credential_accept.py (2)
7-9
: Add docstrings to explain test constantsConsider adding docstrings to explain the purpose and significance of these test accounts (issuer and subject) to improve test maintainability.
+# Test accounts representing credential issuer and subject _ACCOUNT_ISSUER = "r9LqNeG6qHxjeUocjvVki2XR35weJ9mZgQ" _ACCOUNT_SUBJECT = "rNdY9XDnQ4Dr1EgefwU3CBRuAjt3sAutGg"
13-23
: Enhance test coverage for the valid caseWhile the basic functionality is tested, consider adding tests for:
- Optional fields if any
- Edge cases for field values (e.g., minimum/maximum lengths for credential_type)
- Different types of valid credentials
xrpl/models/transactions/escrow_finish.py (1)
Line range hint
62-77
: Consider adding integration tests for credential validation scenariosSince this is part of the PermissionedDomains feature and involves credential validation, consider adding integration tests that cover:
- Successful escrow finish with valid credentials
- Failed attempts with expired credentials
- Edge cases with maximum number of credentials
- Interaction with existing escrow conditions
This will ensure the feature works correctly in real-world scenarios.
xrpl/models/transactions/did_set.py (2)
Line range hint
19-40
: Consider standardizing docstring format.While the documentation is comprehensive, consider adopting Google-style docstrings for consistency:
- """ - The DID document associated with the DID. - - To delete the Data, DIDDocument, or URI field from an existing DID ledger - entry, add the field as an empty string. - """ + """The DID document associated with the DID. + + Args: + None + + Notes: + To delete the Data, DIDDocument, or URI field from an existing DID ledger + entry, add the field as an empty string. + """
Line range hint
65-67
: Consider extracting magic numbers as constants.The maximum length of 256 characters should be defined as a class or module-level constant for better maintainability.
+# At module level +MAX_FIELD_LENGTH = 256 class DIDSet(Transaction): # ... other code ... def _process_field(name: str, value: Optional[str]) -> None: if value is not None: error_strs = [] if not bool(HEX_REGEX.fullmatch(value)): error_strs.append("must be hex") - if len(value) > 256: + if len(value) > MAX_FIELD_LENGTH: error_strs.append("must be <= 256 characters")tests/integration/transactions/test_deposit_preauth.py (1)
17-37
: Consider adding state validation.While the test correctly verifies the transaction success, it would be more robust to validate the actual state changes after each operation. Consider adding checks to verify:
- After authorization: The address is actually authorized
- After un-authorization: The address is no longer authorized
Example addition:
# After authorization account_info = await client.request(AccountInfo(account=ACCOUNT)) # Verify DESTINATION.address is in the authorized list # After un-authorization account_info = await client.request(AccountInfo(account=ACCOUNT)) # Verify DESTINATION.address is not in the authorized listtests/unit/models/transactions/test_credential_delete.py (2)
12-28
: Add documentation and strengthen assertions.While the test cases cover valid transaction creation paths, consider these improvements:
- Add a class docstring explaining the purpose of these tests.
- Document why there are two different ways to specify the transaction.
- Add assertions to verify the actual field values in the created transactions.
Example implementation:
class TestCredentialDelete(TestCase): + """ + Test cases for the CredentialDelete transaction model. + + The transaction can be specified in two ways: + 1. Using issuer + account combination + 2. Using account + subject combination (alternative specification) + """ def test_valid(self): + """Test both valid ways to create a CredentialDelete transaction.""" tx = CredentialDelete( issuer=_ACCOUNT_ISSUER, account=_ACCOUNT_SUBJECT, credential_type=_VALID_CREDENTIAL_TYPE, ) self.assertTrue(tx.is_valid()) + self.assertEqual(tx.issuer, _ACCOUNT_ISSUER) + self.assertEqual(tx.account, _ACCOUNT_SUBJECT) + self.assertEqual(tx.credential_type, _VALID_CREDENTIAL_TYPE) # alternative specification of the CredentialDelete transaction tx = CredentialDelete( account=_ACCOUNT_ISSUER, subject=_ACCOUNT_SUBJECT, credential_type=_VALID_CREDENTIAL_TYPE, ) self.assertTrue(tx.is_valid()) + self.assertEqual(tx.account, _ACCOUNT_ISSUER) + self.assertEqual(tx.subject, _ACCOUNT_SUBJECT) + self.assertEqual(tx.credential_type, _VALID_CREDENTIAL_TYPE)
29-76
: Add tests for additional edge cases.The current error handling tests are good, but consider adding these test cases for better coverage:
- Test when both
issuer
andsubject
are provided (should raise an error)- Test the maximum valid length of
credential_type
(just under 128 characters)- Test hex strings containing valid special characters
Example implementation:
def test_both_issuer_and_subject(self): """Test that providing both issuer and subject raises an error.""" with self.assertRaises(XRPLModelException) as error: CredentialDelete( issuer=_ACCOUNT_ISSUER, subject=_ACCOUNT_SUBJECT, account=_ACCOUNT_SUBJECT, credential_type=_VALID_CREDENTIAL_TYPE, ) self.assertEqual( error.exception.args[0], "{'invalid_params': 'Cannot specify both `issuer` and `subject`.'}" ) def test_cred_type_max_valid_length(self): """Test credential_type with maximum valid length.""" tx = CredentialDelete( issuer=_ACCOUNT_ISSUER, account=_ACCOUNT_SUBJECT, credential_type=str_to_hex("A" * 63), # Results in 126 hex chars ) self.assertTrue(tx.is_valid()) def test_cred_type_special_hex_chars(self): """Test credential_type with valid special hex characters.""" tx = CredentialDelete( issuer=_ACCOUNT_ISSUER, account=_ACCOUNT_SUBJECT, credential_type="0123456789abcdefABCDEF", ) self.assertTrue(tx.is_valid())tests/unit/models/transactions/test_escrow_finish.py (4)
40-53
: Consider improving test readability and maintainability.The test logic is correct, but could be enhanced:
- Extract the magic number 9 into a constant like
MAX_CREDENTIALS_PLUS_ONE
- Consider using a triple-quoted string for the error message to avoid string concatenation
+MAX_CREDENTIALS_PLUS_ONE = 9 +CREDS_MAX_LENGTH_ERROR = """{'credential_ids': 'CredentialIDs list cannot have more than 8 elements.'}""" def test_creds_list_too_long(self): with self.assertRaises(XRPLModelException) as err: EscrowFinish( account=_ACCOUNT, owner=_ACCOUNT, offer_sequence=1, - credential_ids=["credential_index_" + str(i) for i in range(9)], + credential_ids=["credential_index_" + str(i) for i in range(MAX_CREDENTIALS_PLUS_ONE)], ) self.assertEqual( err.exception.args[0], - "{'credential_ids': 'CredentialIDs list cannot have more than 8 " - + "elements.'}", + CREDS_MAX_LENGTH_ERROR, )
55-68
: Make duplicate test data more explicit.While the test is functional, the duplicate values could be more clearly demonstrated:
+CREDS_DUPLICATES_ERROR = """{'credential_ids_duplicates': 'CredentialIDs list cannot contain duplicate values.'}""" def test_creds_list_duplicates(self): with self.assertRaises(XRPLModelException) as err: EscrowFinish( account=_ACCOUNT, owner=_ACCOUNT, offer_sequence=1, - credential_ids=["credential_index" for _ in range(5)], + credential_ids=["cred1", "cred2", "cred1"], # Explicit duplicate ) self.assertEqual( err.exception.args[0], - "{'credential_ids_duplicates': 'CredentialIDs list cannot contain duplicate" - + " values.'}", + CREDS_DUPLICATES_ERROR, )
70-81
: Maintain consistency with error message constants.For consistency with the previous tests, consider extracting the error message:
+CREDS_EMPTY_ERROR = """{'credential_ids': 'CredentialIDs list cannot be empty.'}""" def test_creds_list_empty(self): with self.assertRaises(XRPLModelException) as err: EscrowFinish( account=_ACCOUNT, owner=_ACCOUNT, offer_sequence=1, credential_ids=[], ) self.assertEqual( err.exception.args[0], - "{'credential_ids': 'CredentialIDs list cannot be empty.'}", + CREDS_EMPTY_ERROR, )
83-92
: Consider expanding valid credential tests.While the test covers a valid case, consider adding:
- Test with multiple valid credentials (2-8 range)
- Document the HASH256 format requirement in the test
+ def test_valid_multiple_credentials(self): + """Test EscrowFinish with multiple valid credential IDs (HASH256 format).""" + tx = EscrowFinish( + account=_ACCOUNT, + owner=_ACCOUNT, + offer_sequence=1, + credential_ids=[ + "EA85602C1B41F6F1F5E83C0E6B87142FB8957BD209469E4CC347BA2D0C26F66A", + "DFB5602C1B41F6F1F5E83C0E6B87142FB8957BD209469E4CC347BA2D0C26F66B" + ], + ) + self.assertTrue(tx.is_valid())tests/unit/models/transactions/test_payment_channel_claim.py (3)
10-24
: Consider enhancing test coverage with additional assertions.While the basic validation is good, consider adding assertions to verify:
- The actual values of the fields after instantiation
- The serialized format of the transaction
Example enhancement:
def test_valid(self): tx = PaymentChannelClaim( # ... existing parameters ... ) self.assertTrue(tx.is_valid()) self.assertEqual(tx.account, _ACCOUNT) self.assertEqual(len(tx.credential_ids), 1) self.assertEqual( tx.credential_ids[0], "EA85602C1B41F6F1F5E83C0E6B87142FB8957BD209469E4CC347BA2D0C26F66A" )🧰 Tools
🪛 Gitleaks
18-18: Detected a Generic API Key, potentially exposing access to various services and sensitive operations.
(generic-api-key)
41-45
: Improve string assertion readability.Instead of using string concatenation with '+', consider using a single string:
- self.assertEqual( - err.exception.args[0], - "{'credential_ids': 'CredentialIDs list cannot have more than 8 elements." - + "'}", - ) + self.assertEqual( + err.exception.args[0], + "{'credential_ids': 'CredentialIDs list cannot have more than 8 elements.'}" + )
26-85
: Consider adding boundary test cases.The error cases are well covered, but consider adding these scenarios:
- Test with exactly 8 credentials (boundary case)
- Test with invalid credential format
- Test with null/None in credential list
Would you like me to help generate these additional test cases?
🧰 Tools
🪛 Gitleaks
36-36: Detected a Generic API Key, potentially exposing access to various services and sensitive operations.
(generic-api-key)
57-57: Detected a Generic API Key, potentially exposing access to various services and sensitive operations.
(generic-api-key)
78-78: Detected a Generic API Key, potentially exposing access to various services and sensitive operations.
(generic-api-key)
tests/integration/transactions/test_permissioned_domain.py (2)
10-10
: Remove or uncomment the import statement.The commented import statement
from xrpl.models.requests.ledger_entry import Credential as CredentialLedgerEntry
should either be removed if unused or uncommented if needed.
22-22
: Add test cases for error scenarios.The current test only covers the happy path. Consider adding test cases for:
- Invalid credential types
- Non-existent domain_id in deletion
- Unauthorized account access
- Duplicate PermissionedDomain creation
tests/unit/models/transactions/test_credential_create.py (4)
14-21
: Add test case with all fields including optional ones.While the basic valid case is tested, consider adding another test case that includes the optional
uri
field to ensure complete field coverage for this new feature.def test_valid_with_all_fields(self): tx = CredentialCreate( account=_ACCOUNT_ISSUER, subject=_ACCOUNT_SUBJECT, credential_type=_VALID_CREDENTIAL_TYPE, uri=_VALID_URI, ) self.assertTrue(tx.is_valid())
22-61
: Simplify URI field validation tests.Based on previous learnings, specific error message assertions can increase maintenance overhead. Consider simplifying the tests to only assert that the expected exception is raised.
Example refactor for one test:
def test_uri_field_too_long(self): with self.assertRaises(XRPLModelException) as error: CredentialCreate( account=_ACCOUNT_ISSUER, subject=_ACCOUNT_SUBJECT, credential_type=_VALID_CREDENTIAL_TYPE, uri=str_to_hex("A" * 257), ) - self.assertEqual( - error.exception.args[0], - "{'uri': 'Length must be < 256.'}" - )
73-73
: Fix grammatical error in error message.The error message has a grammatical error: "Length must less than 128" should be "Length must be less than 128".
102-109
: Add clarifying comment for empty fields test.Consider adding a comment to clarify that this test verifies that the transaction fails validation when both optional fields are empty strings, regardless of which validation fails first.
def test_create_cred_type_object_all_empty_fields(self): + # Verify that empty strings are rejected for both optional fields, + # regardless of validation order with self.assertRaises(XRPLModelException): CredentialCreate( account=_ACCOUNT_ISSUER,xrpl/models/transactions/payment_channel_claim.py (2)
115-117
: Enhance credential_ids documentationWhile the docstring explains the basic purpose, consider adding more details about:
- Format requirements for credential IDs
- Maximum number of credentials allowed (if any)
- Impact on transaction processing
Example enhancement:
- """Credentials associated with sender of this transaction. The credentials included - must not be expired.""" + """Credentials associated with sender of this transaction. The credentials included + must not be expired. + + :type: Optional[List[str]] + :param credential_ids: List of credential identifiers in HASH256 format + :raises: ValidationError if any credential is expired or invalid + """
114-122
: Consider caching credential validation resultsSince credential validation will be performed for multiple transaction types, consider implementing a caching mechanism for credential validation results to improve performance, especially in scenarios where the same credentials are used across multiple transactions.
Key considerations:
- Cache invalidation strategy for expired credentials
- Cache scope (per-transaction vs global)
- Memory usage implications
tests/integration/reusable_values.py (1)
101-102
: Consider moving credential type to a constant.The hardcoded credential type
"IdentityDocument"
should be moved to a module-level constant for better maintainability and reuse.+ IDENTITY_DOCUMENT_CREDENTIAL_TYPE = str_to_hex("IdentityDocument")
xrpl/models/utils.py (1)
11-11
: Strengthen the hex validation patternThe current regex pattern could allow partial matches. Consider anchoring it with
^
and$
to ensure the entire string matches the hex pattern.-HEX_REGEX: Final[Pattern[str]] = re.compile("[a-fA-F0-9]*") +HEX_REGEX: Final[Pattern[str]] = re.compile("^[a-fA-F0-9]*$")tests/unit/models/transactions/test_deposit_preauth.py (2)
32-34
: Consider moving sample_credentials to a test method or setup.The
sample_credentials
is defined as a class variable but used as an instance variable withself.sample_credentials
. This could lead to shared state between tests if modified.Consider moving it to either:
- A setup method:
def setUp(self): self.sample_credentials = [ Credential(issuer="SampleIssuer", credential_type="SampleCredType") ]
- Or make it a static fixture:
@staticmethod def get_sample_credentials(): return [ Credential(issuer="SampleIssuer", credential_type="SampleCredType") ]
36-54
: Enhance test documentation and assertions.While the test cases cover important scenarios, they could be improved:
- Add docstrings explaining the test purpose
- Add more specific assertions for error messages
- Validate more properties in the success case
Example improvements:
def test_invalid_input_with_authorize_credentials(self): """Test that combining authorize with authorize_credentials raises an exception.""" with self.assertRaises(XRPLModelException) as error: DepositPreauth( account=_ACCOUNT, fee=_FEE, sequence=_SEQUENCE, authorize="authorize", authorize_credentials=self.sample_credentials, ) self.assertIn("Cannot set both authorize and authorize_credentials", str(error.exception)) def test_valid_input_unauthorize_credentials(self): """Test successful creation with unauthorize_credentials.""" tx = DepositPreauth( account=_ACCOUNT, fee=_FEE, sequence=_SEQUENCE, unauthorize_credentials=self.sample_credentials, ) self.assertTrue(tx.is_valid()) self.assertEqual(tx.unauthorize_credentials, self.sample_credentials) self.assertIsNone(tx.authorize_credentials)tests/unit/models/requests/test_ledger_entry.py (1)
Unit tests needed for PermissionedDomainDelete transaction
The integration tests cover PermissionedDomainDelete functionality, but there are no corresponding unit tests. Unit tests for transactions are typically placed in
tests/unit/models/transactions/
. Consider adding unit tests to validate:
- Required fields validation
- Field type validation
- Transaction serialization
- Invalid input handling
🔗 Analysis chain
Line range hint
26-188
: Consider adding tests for PermissionedDomainDelete transactionAccording to the PR objectives, no unit tests were created for the
PermissionedDomainDelete
transaction. Consider adding these tests to ensure complete coverage of the PermissionedDomains amendment implementation.Let's verify if there are any existing tests for
PermissionedDomainDelete
:Would you like me to help create the test cases for the
PermissionedDomainDelete
transaction?🏁 Scripts executed
The following scripts were executed for the analysis:
Script:
#!/bin/bash # Search for any existing PermissionedDomainDelete tests rg -l "PermissionedDomainDelete" "tests/"Length of output: 98
Script:
#!/bin/bash # Let's check the content of the test file to see if it covers PermissionedDomainDelete rg -A 5 "PermissionedDomainDelete" "tests/integration/transactions/test_permissioned_domain.py"Length of output: 492
Script:
#!/bin/bash # Let's check if there are any unit tests for PermissionedDomainDelete rg -l "test.*PermissionedDomainDelete" "tests/unit/" # Also check the structure of unit test directory for transaction tests fd "test_.*transaction" "tests/unit/"Length of output: 264
tests/unit/models/transactions/test_payment.py (3)
137-148
: Add docstring to explain test purposeConsider adding a docstring to explain the test's purpose and expectations. This helps maintain consistency with Python best practices and improves test documentation.
def test_credentials_array_empty(self): + """ + Test that an XRPLModelException is raised when an empty credential_ids list + is provided to a Payment transaction. + """ with self.assertRaises(XRPLModelException) as err:
150-163
: Improve test readability and maintainabilityA few suggestions to enhance this test:
- Define MAX_CREDENTIALS constant to avoid magic number
- Use triple quotes for multi-line error message instead of string concatenation
+MAX_CREDENTIALS = 8 + def test_credentials_array_too_long(self): + """ + Test that an XRPLModelException is raised when credential_ids list + exceeds the maximum allowed length. + """ with self.assertRaises(XRPLModelException) as err: Payment( account=_ACCOUNT, amount=_XRP_AMOUNT, destination=_DESTINATION, - credential_ids=["credential_index_" + str(i) for i in range(9)], + credential_ids=["credential_index_" + str(i) for i in range(MAX_CREDENTIALS + 1)], ) self.assertEqual( err.exception.args[0], - "{'credential_ids': 'CredentialIDs list cannot have more than 8 " - + "elements.'}" + "{'credential_ids': 'CredentialIDs list cannot have more than 8 elements.'}" )
165-178
: Enhance test clarity and data realismConsider these improvements:
- Use explicit duplicate values instead of generating them
- Use triple quotes for multi-line error message
- Use more realistic credential IDs that match the expected format
def test_credentials_array_duplicates(self): + """ + Test that an XRPLModelException is raised when credential_ids list + contains duplicate values. + """ with self.assertRaises(XRPLModelException) as err: Payment( account=_ACCOUNT, amount=_XRP_AMOUNT, destination=_DESTINATION, - credential_ids=["credential_index" for _ in range(5)], + credential_ids=[ + "0123456789ABCDEF0123456789ABCDEF0123456789ABCDEF0123456789ABCDEF", + "1123456789ABCDEF0123456789ABCDEF0123456789ABCDEF0123456789ABCDEF", + "0123456789ABCDEF0123456789ABCDEF0123456789ABCDEF0123456789ABCDEF", # duplicate + ], ) self.assertEqual( err.exception.args[0], - "{'credential_ids_duplicates': 'CredentialIDs list cannot contain duplicate" - + " values.'}" + "{'credential_ids_duplicates': 'CredentialIDs list cannot contain duplicate values.'}" )xrpl/models/transactions/payment.py (2)
136-139
: Enhance credential_ids documentation.While the docstring explains the expiry requirement, it would be helpful to add:
- Expected format of credential IDs
- Example usage
- Link to relevant documentation about credentials
Example enhancement:
credential_ids: Optional[List[str]] = None """Credentials associated with sender of this transaction. The credentials included - must not be expired.""" + must not be expired. + + Example: + credential_ids=["F...A", "B...C"] # Replace with actual format + + See: <link-to-credential-documentation> + """
136-144
: Consider future extensibility of credential validation.The current implementation provides a good foundation for credential support. For future extensibility, consider:
- Adding credential validation hooks for custom validation logic
- Supporting credential metadata or attributes
- Implementing credential caching if validation becomes a performance bottleneck
This would make the system more adaptable to future credential-related features.
xrpl/models/requests/ledger_entry.py (1)
48-64
: Enhance docstrings for better clarityThe
Credential
class implementation looks good, following the established patterns. Consider enhancing the docstrings to include:
- Format requirements or constraints for each field
- Example values
- Any validation rules that apply
Example enhancement for the credential_type field:
- """The type of the credential, as issued.""" + """ + The type of the credential, as issued. + This should match one of the credential types defined in the XRPL standards. + Example: "KYC" or "AML" + """CHANGELOG.md (1)
12-12
: Enhance the changelog entry with more specific details.While the entry correctly documents the addition of PermissionedDomains support, it would be more helpful to users if it included specific details about:
- The new transaction types added (e.g., PermissionedDomainSet, PermissionedDomainDelete)
- Any new models or utilities introduced
- Breaking changes or dependencies (e.g., requirement for domain_id from rippled RPCs)
Consider expanding the entry to something like:
-Add support for the `PermissionedDomains` feature in xrpl-py +Add support for the `PermissionedDomains` feature in xrpl-py: + - New transaction types: PermissionedDomainSet, PermissionedDomainDelete + - Support for domain_id field (HASH256 type) from rippled RPCs + - New models and validation for permissioned domain operationsxrpl/core/binarycodec/definitions/definitions.json (1)
2814-2842
: Consider grouping credential-related arrays togetherThe credential-related arrays (AuthorizeCredentials, UnauthorizeCredentials, AcceptedCredentials) could be grouped with sequential nth values for better organization and maintenance.
Consider reordering to use sequential nth values:
- "nth": 26, + "nth": 26, // AuthorizeCredentials - "nth": 27, + "nth": 27, // UnauthorizeCredentials - "nth": 28, + "nth": 28, // AcceptedCredentialsxrpl/models/transactions/credential_accept.py (1)
54-57
: Clarify error messages in credential_type validationConsider refining the error messages in
_get_credential_type_error
for clarity. For instance, if the maximum length is inclusive, you might change "Length must be <_MAX_CREDENTIAL_LENGTH
." to "Length must be ≤_MAX_CREDENTIAL_LENGTH
."xrpl/models/transactions/credential_delete.py (6)
31-32
: Consider Updatingaccount
Field to Avoid# type: ignore
The
account
field uses# type: ignore
to bypass type checking due to assigningREQUIRED
. To enhance type safety and avoid suppressing type errors, consider usingfield
withdefault=REQUIRED
.Apply this diff:
- account: str = REQUIRED # type: ignore + account: str = field(default=REQUIRED)
41-42
: Refactorcredential_type
Field to Improve Type CheckingSimilar to the
account
field, thecredential_type
field uses# type: ignore
. To maintain consistency and improve type checking, usefield
withdefault=REQUIRED
.Apply this diff:
- credential_type: str = REQUIRED # type: ignore + credential_type: str = field(default=REQUIRED)
64-69
: Enhance Clarity of Validation Error MessagesThe error messages in
_get_credential_type_error
can be made clearer:
- Line 65: Replace "Length must be > 0." with "credential_type must not be empty."
- Line 67: Adjust "Length must be < ..." to "Length must be ≤ ..."
This provides more precise guidance to the user.
Apply this diff:
- errors.append("Length must be > 0.") + errors.append("credential_type must not be empty.") - errors.append(f"Length must be < {_MAX_CREDENTIAL_LENGTH}.") + errors.append(f"Length must be ≤ {_MAX_CREDENTIAL_LENGTH}.")
44-61
: Simplify Method Signatures by Removing Redundant Type AnnotationsThe methods
_get_errors
and_get_credential_type_error
specifyself: Self
, which may be unnecessary. Sinceself
is inherently the instance of the class, you can simplify the method signatures by omittingSelf
.Apply this diff:
- def _get_errors(self: Self) -> Dict[str, str]: + def _get_errors(self) -> Dict[str, str]: ... - def _get_credential_type_error(self: Self) -> Optional[str]: + def _get_credential_type_error(self) -> Optional[str]:
54-57
: Ensure at Least One ofissuer
orsubject
is ProvidedThe validation correctly checks that at least one of
issuer
orsubject
is provided. However, consider explicitly documenting this requirement in the class docstring or field descriptions to guide users.Suggestion:
- Update the class docstring or field docstrings to indicate that one of
issuer
orsubject
must be specified.
34-40
: Clarify Field Descriptions forsubject
andissuer
For better understanding, consider rephrasing the docstrings:
- For
subject
: "The address of the subject for whom the credential is issued. Defaults toaccount
if omitted."- For
issuer
: "The address of the issuer of the credential. Defaults toaccount
if omitted."Apply this diff:
- """The person that the credential is for. If omitted, Account is assumed to be the - subject.""" + """The address of the subject for whom the credential is issued. Defaults to `account` if omitted.""" ... - """The issuer of the credential. If omitted, Account is assumed to be the issuer.""" + """The address of the issuer of the credential. Defaults to `account` if omitted."""xrpl/models/transactions/credential_create.py (4)
84-84
: Typo in error messageThere's a minor typo in the error message at line 84:
errors.append(f"Length must less than {_MAX_CREDENTIAL_LENGTH}.")It should be:
errors.append(f"Length must be less than {_MAX_CREDENTIAL_LENGTH}.")
73-73
: Clarify length constraint in error messageIn line 73, the error message:
errors.append(f"Length must be < {_MAX_URI_LENGTH}.")Consider updating it for clarity and consistency:
errors.append(f"Length must be less than {_MAX_URI_LENGTH}.")
65-77
: Standardize error messages for consistencyTo improve clarity, consider standardizing the error messages in
_get_uri_error
:
"Length must be > 0."
➔"URI length must be greater than 0."
"Length must be less than {_MAX_URI_LENGTH}."
➔"URI length must be less than {_MAX_URI_LENGTH}."
"Must be encoded in hex."
➔"URI must be encoded in hex."
78-87
: Standardize error messages for consistencySimilarly, in
_get_credential_type_error
, you can enhance the error messages:
"Length must be > 0."
➔"Credential type length must be greater than 0."
"Length must be less than {_MAX_CREDENTIAL_LENGTH}."
➔"Credential type length must be less than {_MAX_CREDENTIAL_LENGTH}."
"credential_type field must be encoded in hex."
➔"Credential type must be encoded in hex."
Ensure these changes align with existing patterns in the
xrpl/models/transactions/
directory to maintain overall consistency.xrpl/models/transactions/deposit_preauth.py (1)
99-99
: Remove unnecessary comment at line 99The comment
# Then replace the checks with:
appears outdated or unnecessary. Removing it will improve code clarity and prevent potential confusion.Apply this diff to remove the comment:
- # Then replace the checks with:
tests/integration/transactions/test_credential.py (2)
47-48
: Rename local variables to lowercasePython style conventions recommend using lowercase for variable names. Rename
_ISSUER
and_SUBJECT
to_issuer
and_subject
to adhere to PEP 8 guidelines.
18-41
: Inline theis_cred_object_present
function or simplify testPer the project's conventions, avoid abstracting checks into separate utility functions in integration tests. Consider inlining the logic of
is_cred_object_present
or simplifying the test to eliminate the need for this function.
📜 Review details
Configuration used: .coderabbit.yaml
Review profile: CHILL
📒 Files selected for processing (37)
.ci-config/rippled.cfg
(1 hunks).github/workflows/integration_test.yml
(3 hunks)CHANGELOG.md
(2 hunks)CONTRIBUTING.md
(1 hunks)tests/integration/reusable_values.py
(5 hunks)tests/integration/transactions/test_credential.py
(1 hunks)tests/integration/transactions/test_deposit_preauth.py
(1 hunks)tests/integration/transactions/test_permissioned_domain.py
(1 hunks)tests/unit/models/requests/test_deposit_authorized.py
(1 hunks)tests/unit/models/requests/test_ledger_entry.py
(3 hunks)tests/unit/models/transactions/test_account_delete.py
(1 hunks)tests/unit/models/transactions/test_credential_accept.py
(1 hunks)tests/unit/models/transactions/test_credential_create.py
(1 hunks)tests/unit/models/transactions/test_credential_delete.py
(1 hunks)tests/unit/models/transactions/test_deposit_preauth.py
(2 hunks)tests/unit/models/transactions/test_escrow_finish.py
(1 hunks)tests/unit/models/transactions/test_payment.py
(1 hunks)tests/unit/models/transactions/test_payment_channel_claim.py
(1 hunks)tests/unit/models/transactions/test_permissioned_domain_set.py
(1 hunks)xrpl/core/binarycodec/definitions/definitions.json
(10 hunks)xrpl/models/requests/account_objects.py
(1 hunks)xrpl/models/requests/deposit_authorized.py
(2 hunks)xrpl/models/requests/ledger_entry.py
(5 hunks)xrpl/models/transactions/__init__.py
(4 hunks)xrpl/models/transactions/account_delete.py
(2 hunks)xrpl/models/transactions/credential_accept.py
(1 hunks)xrpl/models/transactions/credential_create.py
(1 hunks)xrpl/models/transactions/credential_delete.py
(1 hunks)xrpl/models/transactions/deposit_preauth.py
(2 hunks)xrpl/models/transactions/did_set.py
(1 hunks)xrpl/models/transactions/escrow_finish.py
(3 hunks)xrpl/models/transactions/payment.py
(2 hunks)xrpl/models/transactions/payment_channel_claim.py
(2 hunks)xrpl/models/transactions/permissioned_domain_delete.py
(1 hunks)xrpl/models/transactions/permissioned_domain_set.py
(1 hunks)xrpl/models/transactions/types/transaction_type.py
(2 hunks)xrpl/models/utils.py
(1 hunks)
🧰 Additional context used
📓 Learnings (8)
tests/integration/transactions/test_credential.py (3)
Learnt from: mvadari
PR: XRPLF/xrpl-py#759
File: tests/integration/transactions/test_credential.py:61-63
Timestamp: 2024-11-12T12:37:49.114Z
Learning: In integration tests for xrpl-py, tests should only be testing the library, not rippled functionalities.
Learnt from: mvadari
PR: XRPLF/xrpl-py#759
File: tests/integration/transactions/test_credential.py:42-44
Timestamp: 2024-11-12T12:37:49.114Z
Learning: In this codebase, extensive unit tests are located in `rippled`, and additional tests are not required in this library.
Learnt from: ckeshava
PR: XRPLF/xrpl-py#759
File: tests/integration/transactions/test_credential.py:37-108
Timestamp: 2024-11-12T12:37:49.114Z
Learning: In integration tests, setup and teardown are performed using the `CredentialCreate` and `CredentialDelete` transactions, and we prefer not to abstract these transactions into separate utility functions.
tests/unit/models/transactions/test_credential_create.py (2)
Learnt from: mvadari
PR: XRPLF/xrpl-py#759
File: tests/unit/models/transactions/test_credential_create.py:13-22
Timestamp: 2024-11-12T12:37:49.114Z
Learning: In Python test files in the xrpl-py codebase (e.g., `tests/unit/models/transactions/test_credential_create.py`), docstrings are not required for test classes and methods if their names are self-explanatory enough.
Learnt from: ckeshava
PR: XRPLF/xrpl-py#759
File: tests/unit/models/transactions/test_credential_create.py:107-114
Timestamp: 2024-11-12T12:37:49.114Z
Learning: In `tests/unit/models/transactions/test_credential_create.py`, when testing invalid inputs, avoid adding assertions on specific error messages if it increases the complexity and maintenance overhead of the tests.
tests/unit/models/transactions/test_credential_delete.py (1)
Learnt from: ckeshava
PR: XRPLF/xrpl-py#759
File: xrpl/models/transactions/credential_delete.py:57-68
Timestamp: 2024-11-12T12:37:49.114Z
Learning: Consistent implementation patterns are preferred in the `xrpl-py` codebase, especially in transaction models under `xrpl/models/transactions/`. When suggesting refactoring that affects multiple transactions, consider the impact on overall consistency and propose comprehensive changes when appropriate.
tests/unit/models/transactions/test_deposit_preauth.py (2)
Learnt from: mvadari
PR: XRPLF/xrpl-py#759
File: tests/integration/transactions/test_deposit_preauth.py:40-67
Timestamp: 2024-11-12T12:37:49.114Z
Learning: Negative test cases for credential validation should be included in unit tests rather than integration tests.
Learnt from: ckeshava
PR: XRPLF/xrpl-py#759
File: xrpl/models/transactions/deposit_preauth.py:54-64
Timestamp: 2024-11-12T12:37:49.114Z
Learning: In the `DepositPreauth` class in `xrpl/models/transactions/deposit_preauth.py`, when validating that exactly one of the parameters `authorize`, `unauthorize`, `authorize_credentials`, or `unauthorize_credentials` is set, ensure that any refactoring maintains logical equivalence with the original condition to prevent altering the intended functionality.
xrpl/models/transactions/credential_accept.py (1)
Learnt from: ckeshava
PR: XRPLF/xrpl-py#759
File: xrpl/models/transactions/credential_accept.py:27-39
Timestamp: 2024-11-12T12:37:49.114Z
Learning: In the `xrpl` codebase, when defining required fields in dataclasses (e.g., `account: str = REQUIRED`), it's necessary to include `# type: ignore` to prevent `mypy` errors.
xrpl/models/transactions/credential_create.py (1)
Learnt from: ckeshava
PR: XRPLF/xrpl-py#759
File: xrpl/models/transactions/credential_delete.py:57-68
Timestamp: 2024-11-12T12:37:49.114Z
Learning: Consistent implementation patterns are preferred in the `xrpl-py` codebase, especially in transaction models under `xrpl/models/transactions/`. When suggesting refactoring that affects multiple transactions, consider the impact on overall consistency and propose comprehensive changes when appropriate.
xrpl/models/transactions/credential_delete.py (1)
Learnt from: ckeshava
PR: XRPLF/xrpl-py#759
File: xrpl/models/transactions/credential_delete.py:57-68
Timestamp: 2024-11-12T12:37:49.114Z
Learning: Consistent implementation patterns are preferred in the `xrpl-py` codebase, especially in transaction models under `xrpl/models/transactions/`. When suggesting refactoring that affects multiple transactions, consider the impact on overall consistency and propose comprehensive changes when appropriate.
xrpl/models/transactions/deposit_preauth.py (2)
Learnt from: ckeshava
PR: XRPLF/xrpl-py#759
File: xrpl/models/transactions/deposit_preauth.py:54-64
Timestamp: 2024-11-12T12:37:49.114Z
Learning: In the `DepositPreauth` class in `xrpl/models/transactions/deposit_preauth.py`, when validating that exactly one of the parameters `authorize`, `unauthorize`, `authorize_credentials`, or `unauthorize_credentials` is set, ensure that any refactoring maintains logical equivalence with the original condition to prevent altering the intended functionality.
Learnt from: ckeshava
PR: XRPLF/xrpl-py#759
File: xrpl/models/transactions/deposit_preauth.py:89-93
Timestamp: 2024-11-12T12:37:49.114Z
Learning: In the Python file `xrpl/models/transactions/deposit_preauth.py`, within the `_validate_credentials_length` function, when validating `authorize_credentials` and `unauthorize_credentials`, it's acceptable to assign error messages to the same key in the `errors` dictionary if the conditions are mutually exclusive, as the error messages won't overwrite each other.
🪛 LanguageTool
CONTRIBUTING.md
[uncategorized] ~104-~104: A comma may be missing after the conjunctive/linking adverb ‘Hence’.
Context: ...default behavior) for the config files. Hence there is no need to explicitly specify ...
(SENT_START_CONJUNCTIVE_LINKING_ADVERB_COMMA)
🪛 Markdownlint
CONTRIBUTING.md
100-100: Expected: dash; Actual: asterisk
Unordered list style
(MD004, ul-style)
101-101: Expected: dash; Actual: asterisk
Unordered list style
(MD004, ul-style)
102-102: Expected: dash; Actual: asterisk
Unordered list style
(MD004, ul-style)
103-103: Expected: dash; Actual: asterisk
Unordered list style
(MD004, ul-style)
104-104: Expected: dash; Actual: asterisk
Unordered list style
(MD004, ul-style)
105-105: Expected: dash; Actual: asterisk
Unordered list style
(MD004, ul-style)
🪛 Gitleaks
tests/unit/models/transactions/test_payment_channel_claim.py
18-18: Detected a Generic API Key, potentially exposing access to various services and sensitive operations.
(generic-api-key)
36-36: Detected a Generic API Key, potentially exposing access to various services and sensitive operations.
(generic-api-key)
57-57: Detected a Generic API Key, potentially exposing access to various services and sensitive operations.
(generic-api-key)
78-78: Detected a Generic API Key, potentially exposing access to various services and sensitive operations.
(generic-api-key)
🔇 Additional comments (65)
tests/unit/models/requests/test_deposit_authorized.py (1)
1-6
: LGTM: Clean imports and proper class structure
The imports are minimal and appropriate, and the class structure follows unittest conventions.
xrpl/models/transactions/permissioned_domain_delete.py (3)
1-9
: LGTM! Well-structured imports and module documentation.
The imports are organized logically and include all necessary dependencies for the transaction model.
11-13
: Verify consistency with other transaction models.
The class definition follows best practices with appropriate decorators. Let's verify it matches other transaction implementations.
✅ Verification successful
Based on the ast-grep results, I can see that all transaction model classes in the codebase consistently follow the same pattern:
- Use
@require_kwargs_on_init
decorator - Use
@dataclass(frozen=True, **KW_ONLY_DATACLASS)
decorator - Inherit from
Transaction
base class
The PermissionedDomainDelete
class follows this exact pattern, matching the consistent implementation across all transaction models in the codebase.
Class definition follows standard transaction model pattern.
The decorators and inheritance are correctly implemented, matching the established pattern used across all transaction classes in the XRPL SDK.
🏁 Scripts executed
The following scripts were executed for the analysis:
Script:
#!/bin/bash
# Description: Verify consistent class structure across transaction models
# Expected: All transaction models should use similar decorators and inherit from Transaction
# Check other transaction models for consistent patterns
ast-grep --pattern $'@require_kwargs_on_init
@dataclass(frozen=True, **KW_ONLY_DATACLASS)
class $_(Transaction):
$$$'
Length of output: 220735
16-21
:
Add validation for domain_id HASH256 format.
The domain_id
field should be validated to ensure it's a valid HASH256 value as mentioned in the PR objectives.
Consider adding a validator or using a more specific type:
- domain_id: str = REQUIRED # type: ignore
+ domain_id: str = field(
+ default=REQUIRED,
+ metadata={"length": 64, "hex_only": True},
+ validator=lambda x: len(x) == 64 and all(c in '0123456789ABCDEFabcdef' for c in x),
+ )
xrpl/models/requests/deposit_authorized.py (2)
9-9
: LGTM: Import addition is appropriate
The addition of List
to the typing imports is necessary for the new credentials
field type annotation.
42-46
: Verify integration with rippled RPC responses
Let's ensure the credential IDs format matches what's returned by rippled RPCs.
✅ Verification successful
Credential ID format and validation is properly integrated with rippled RPC
Based on the codebase analysis:
- The credential ID format is consistently implemented as a hex string with a maximum length of 128 characters (64 bytes) across all transaction types.
- The validation logic in
validate_credential_ids
enforces:- Non-empty list when specified
- Maximum of 8 credentials
- No duplicate values
- The format matches the rippled implementation as evidenced by integration tests using valid credential IDs like
EA85602C1B41F6F1F5E83C0E6B87142FB8957BD209469E4CC347BA2D0C26F66A
.
🏁 Scripts executed
The following scripts were executed for the analysis:
Script:
#!/bin/bash
# Search for credential ID handling in tests and other files
rg -t python "credential.*id" -A 5 -B 5
# Look for similar credential list handling in other request models
ast-grep --pattern 'class $_ {
$$$
credentials: Optional[List[str]] = $_
$$$
}'
Length of output: 160
Script:
#!/bin/bash
# Search for credential ID handling in tests and other files
rg "credential.*id" -A 5 -B 5
# Look for credential-related test cases
fd "test.*credential" --type f
# Check for similar request models
rg "class.*Request.*credentials:" -A 5 -B 5
Length of output: 31165
xrpl/models/transactions/account_delete.py (4)
4-15
: LGTM! Import statements are properly organized
The new imports are necessary for type hints and credential validation functionality.
57-61
: LGTM! Error handling implementation is robust
The error handling properly combines parent class validation with credential-specific validation.
Let's examine the validation utility implementation:
#!/bin/bash
# Check the implementation of validate_credential_ids
rg -A 10 'def validate_credential_ids'
# Look for related test coverage
rg -g '*test*.py' 'validate_credential_ids|credential_ids'
Line range hint 1-61
: Consider version handling for the PermissionedDomains amendment
Since this adds amendment-dependent functionality, consider implementing version checking to ensure these fields are only used when the PermissionedDomains amendment is enabled on the network.
Let's check how other amendments handle versioning:
#!/bin/bash
# Search for amendment version handling patterns
rg -g '*.py' -B 2 -A 2 'amendment.*enabled|require.*amendment'
52-55
: Consider enhancing credential_ids implementation
While the field addition and documentation are good, consider these improvements:
- Extract the maximum credentials limit (8) into a named constant
- Add format validation for credential IDs if specified by XRPL standards
Let's verify the credential implementation against XRPL specs:
.github/workflows/integration_test.yml (2)
64-64
: LGTM: Container cleanup is properly handled
The container stop command is correctly updated to match the new container name and will run even if previous steps fail.
5-5
: Verify rippled version compatibility with PermissionedDomains
The upgrade from 2.2.0-b3
to 2.3.0-rc1
is significant. Since this PR implements the PermissionedDomains amendment, we should verify that this RC version fully supports this feature.
✅ Verification successful
Based on the search results, I can now provide a final response:
Version 2.3.0-rc1 is appropriate for PermissionedDomains implementation
The CHANGELOG.md shows that PermissionedDomains support was recently added to the codebase, and the code includes proper implementation of PermissionedDomains-related models and transactions. The version upgrade from 2.2.0-b3 to 2.3.0-rc1 is appropriate as it aligns with the feature implementation timeline.
🏁 Scripts executed
The following scripts were executed for the analysis:
Script:
#!/bin/bash
# Description: Verify if the rippled version supports PermissionedDomains
# Pull and check the rippled container
docker pull rippleci/rippled:2.3.0-rc1
docker run --rm rippleci/rippled:2.3.0-rc1 rippled --version
# Check if PermissionedDomains is listed in supported amendments
docker run --rm rippleci/rippled:2.3.0-rc1 rippled feature 2>&1 | grep -i "permissioneddomains"
Length of output: 342
Script:
#!/bin/bash
# Let's check the repository for information about PermissionedDomains and version requirements
# Search for PermissionedDomains in the codebase
rg -i "permissioneddomains" -A 5 -B 5
# Check for version-related changes in the PR
fd -t f "CHANGELOG|README" --exec cat {}
# Look for amendment documentation
fd -t f -e md -e txt --exec grep -l -i "permissioneddomains" {} \; -exec cat {}
Length of output: 46473
xrpl/models/transactions/permissioned_domain_set.py (2)
14-14
: Verify the maximum credentials limit
Please verify that the _MAX_ACCEPTED_CREDENTIALS_LENGTH = 10
constant aligns with the XRPL specification for the PermissionedDomains amendment.
9-9
: Verify the Credential import location
The Credential
class is imported from deposit_preauth
, which seems incorrect for a permissioned domains feature. Consider moving the Credential
class to a more appropriate location or verify if this is the intended design.
✅ Verification successful
Let me gather more information about the Credential class and its usage in both deposit_preauth and permissioned_domain_set to better understand if this is indeed a misplaced import.
Let me check the credential-related transaction files to understand if there's a more appropriate location for the Credential class.
Let me check the common types file to see if it would be a more appropriate location for the Credential class.
Let me check the nested_model.py since Credential inherits from NestedModel.
Based on the comprehensive analysis of the codebase, I can now provide the final response:
The Credential import location is correct
The Credential
class is appropriately placed in deposit_preauth.py
as it's a shared nested model used by both DepositPreauth and PermissionedDomainSet transactions. This follows the same pattern as other nested models in the codebase (like SignerEntry, Memo, PriceData) which are defined in their primary transaction file and reused where needed. The implementation is consistent with XRPL's model architecture where:
- It inherits from NestedModel like other similar shared components
- It's defined in a transaction file that first introduced it
- Other transaction types import and reuse it
🏁 Scripts executed
The following scripts were executed for the analysis:
Script:
#!/bin/bash
# Search for Credential class definition and its usages
ast-grep --pattern 'class Credential {
$$$
}'
# Search for other files importing Credential
rg "from.*import.*Credential"
Length of output: 1905
Script:
#!/bin/bash
# Check the Credential class definition in deposit_preauth
cat xrpl/models/transactions/deposit_preauth.py
# Check how Credential is used in permissioned_domain_set
cat xrpl/models/transactions/permissioned_domain_set.py
# Look for credential-related files to see if there's a better location
fd "credential.*\.py" xrpl/models/
Length of output: 6841
Script:
#!/bin/bash
# Check credential transaction files to see if they define or use a similar Credential class
cat xrpl/models/transactions/credential_create.py
cat xrpl/models/transactions/credential_accept.py
cat xrpl/models/transactions/credential_delete.py
# Also check if there's a common models location for shared types
fd "types\.py" xrpl/models/
Length of output: 7373
Script:
#!/bin/bash
# Check the common types file
cat xrpl/models/types.py
# Also check if there's a common nested models location
fd "nested.*\.py" xrpl/models/
Length of output: 837
Script:
#!/bin/bash
# Check the nested model file
cat xrpl/models/nested_model.py
# Also check if there are other similar nested models
rg "class.*\(NestedModel\)" --type py
Length of output: 2909
xrpl/models/transactions/types/transaction_type.py (1)
21-23
: LGTM! Credential transaction types are well-defined.
The new credential transaction types follow the existing naming conventions and provide a complete set of operations.
xrpl/models/requests/account_objects.py (1)
25-25
: LGTM! Verify integration with related transaction types.
The new enum values CREDENTIAL
and PERMISSIONED_DOMAIN
follow the existing naming conventions and align with the PR objectives for implementing the PermissionedDomains amendment.
Let's verify the integration with related transaction types and models:
Also applies to: 33-33
✅ Verification successful
Integration verified - new account object types are properly supported
The verification shows comprehensive integration:
- Transaction models implemented:
- Credential: Create, Accept, Delete operations
- PermissionedDomain: Set, Delete operations
- Test coverage exists for all transaction types:
- Unit tests for each transaction model
- Integration tests for both Credential and PermissionedDomain features
🏁 Scripts executed
The following scripts were executed for the analysis:
Script:
#!/bin/bash
# Description: Verify that the new account object types are properly integrated with their corresponding transaction types and models
# Check for credential-related transaction models
echo "Checking for credential transaction models..."
rg -l "class.*Credential.*\(Transaction\)"
# Check for permissioned domain transaction models
echo "Checking for permissioned domain transaction models..."
rg -l "class.*PermissionedDomain.*\(Transaction\)"
# Check for references to these new object types in tests
echo "Checking test coverage..."
rg -l "CREDENTIAL|PERMISSIONED_DOMAIN" --glob "test_*.py"
Length of output: 1026
tests/unit/models/transactions/test_account_delete.py (3)
10-60
: Well-structured test implementation
The test suite provides good coverage of the credential_ids parameter constraints with clear test cases and assertions. The implementation follows testing best practices with proper setup of test fixtures and clear error message validation.
6-7
: Verify test fixture XRP addresses
The test fixture addresses should be valid and preferably use well-known test accounts.
✅ Verification successful
Test fixture addresses are valid and commonly used
The address r9LqNeG6qHxjeUocjvVki2XR35weJ9mZgQ
is extensively used as a test account across many test files in the codebase (30+ files), making it a standard test fixture. While rf7HPydP4ihkFkSRHWFq34b4SXRc7GvPCR
is less common, it follows the correct XRP address format and is appropriate for testing the AccountDelete transaction's destination parameter.
🏁 Scripts executed
The following scripts were executed for the analysis:
Script:
#!/bin/bash
# Description: Search for these addresses in test files to verify if they are commonly used test accounts
rg -l "r9LqNeG6qHxjeUocjvVki2XR35weJ9mZgQ|rf7HPydP4ihkFkSRHWFq34b4SXRc7GvPCR" --type py
Length of output: 727
Script:
#!/bin/bash
# Search for these addresses in all test files to verify their usage
rg -l "r9LqNeG6qHxjeUocjvVki2XR35weJ9mZgQ" tests/
rg -l "rf7HPydP4ihkFkSRHWFq34b4SXRc7GvPCR" tests/
# Search for common test account patterns in test files
rg "^_ACCOUNT\s*=|^_DESTINATION\s*=" tests/unit/models/transactions/
Length of output: 5551
57-57
: Verify the credential ID hash format
The credential ID appears to be a HASH256 value. Let's verify if this is a commonly used test hash or if we should document its significance.
✅ Verification successful
The credential ID hash is consistently used across test files
The hash value EA85602C1B41F6F1F5E83C0E6B87142FB8957BD209469E4CC347BA2D0C26F66A
appears to be a standard test credential ID used consistently across multiple test files for valid test cases. It's used in similar contexts for testing credential-related functionality in account deletion, escrow finish, payment channel claims, and deposit authorization. The format follows the expected 64-character hexadecimal pattern for credential IDs, and its reuse across test files suggests it's a deliberate test fixture value.
🏁 Scripts executed
The following scripts were executed for the analysis:
Script:
#!/bin/bash
# Description: Search for this hash in test files to verify if it's a commonly used test value
rg "EA85602C1B41F6F1F5E83C0E6B87142FB8957BD209469E4CC347BA2D0C26F66A" --type py
Length of output: 727
Script:
#!/bin/bash
# Let's check the context of how this hash is used in these test files
for file in tests/unit/models/transactions/test_escrow_finish.py tests/unit/models/transactions/test_account_delete.py tests/unit/models/transactions/test_payment_channel_claim.py tests/unit/models/requests/test_deposit_authorized.py; do
echo "=== $file ==="
rg -B 2 -A 2 "EA85602C1B41F6F1F5E83C0E6B87142FB8957BD209469E4CC347BA2D0C26F66A" "$file"
done
Length of output: 2708
Script:
#!/bin/bash
# Let's check if there's any documentation or constant definition for this hash value
rg -i "credential.*id|hash.*format" --type py tests/
Length of output: 4687
tests/unit/models/transactions/test_credential_accept.py (1)
1-60
: Verify integration with PermissionedDomains feature
The PR objectives mention this is part of the PermissionedDomains amendment, but these tests focus on credential acceptance. Let's verify how credentials relate to permissioned domains.
✅ Verification successful
CredentialAccept is correctly integrated with PermissionedDomains feature
The verification shows that credentials are an integral part of the PermissionedDomains feature:
PermissionedDomainSet
transaction requires a list of accepted credentials (accepted_credentials
)- Each credential in the list must specify a credential type and issuer, matching the fields validated in
CredentialAccept
- The
CredentialAccept
transaction allows subjects to accept credentials that can then be used in permissioned domains
The test implementation is appropriate as it verifies the core functionality needed for the credential acceptance flow that's used by the permissioned domains feature.
🏁 Scripts executed
The following scripts were executed for the analysis:
Script:
#!/bin/bash
# Search for relationships between credentials and permissioned domains
echo "Searching for credential usage in domain-related files..."
rg -l "credential" | rg "domain"
echo "Searching for domain-related models..."
fd "domain.*\.py" "xrpl/models"
echo "Checking if CredentialAccept is used in domain transactions..."
rg -A 5 "CredentialAccept" "xrpl/models/transactions/domain"
Length of output: 821
Script:
#!/bin/bash
# Let's check the content of permissioned domain files to understand the relationship
echo "Checking PermissionedDomainSet implementation..."
cat xrpl/models/transactions/permissioned_domain_set.py
echo -e "\nChecking test implementation..."
cat tests/unit/models/transactions/test_permissioned_domain_set.py
echo -e "\nLet's also check credential model implementation..."
cat xrpl/models/transactions/credential_accept.py
Length of output: 6350
xrpl/models/transactions/escrow_finish.py (3)
6-6
: LGTM: Import changes are clean and well-organized
The new imports are properly organized and all are utilized within the code.
Also applies to: 13-17
77-77
: LGTM: Error validation properly integrated
The credential validation is correctly integrated into the existing error handling flow, maintaining consistency with the codebase's error handling patterns.
62-64
: Verify credential expiry validation implementation
The documentation states that credentials must not be expired, but there's no explicit expiry validation in this class. Let's verify where this validation occurs.
xrpl/models/transactions/did_set.py (3)
6-12
: LGTM! Clean imports and proper class setup.
The import organization and class setup follow best practices with proper type hints and immutable dataclass usage.
Line range hint 42-78
: LGTM! Robust validation logic.
The error validation is thorough and well-structured:
- Proper validation of required fields
- Clear error messages
- Good use of helper method for field validation
- Appropriate hex format checking
Line range hint 65-67
: Verify hex validation against XRPL specification.
Let's ensure the hex validation aligns with the XRPL specification for the PermissionedDomains amendment.
✅ Verification successful
Let me gather more context about the hex validation implementation and specification.
Let me gather more specific information about the hex validation in DIDSet and related specifications.
Based on the gathered information, I can now generate the final response:
Hex validation implementation is correct and consistent with XRPL standards.
The hex validation in DIDSet uses the standard HEX_REGEX = re.compile("[a-fA-F0-9]*")
pattern from xrpl/models/utils.py, which:
- Correctly validates hexadecimal characters (0-9, a-f, A-F)
- Is consistent with other hex validations in the codebase (as seen in credential fields)
- Has proper test coverage (test_not_hex, test_too_long_and_not_hex in test_did_set.py)
🏁 Scripts executed
The following scripts were executed for the analysis:
Script:
#!/bin/bash
# Search for related validation patterns in the codebase
rg -l "HEX_REGEX" | xargs rg "must be hex"
# Look for similar transaction types to compare validation
ast-grep --pattern 'class $_ extends Transaction {
$$$
_get_errors($$$) {
$$$
}
}'
Length of output: 226
Script:
#!/bin/bash
# Check the HEX_REGEX pattern definition
rg -A 2 "HEX_REGEX\s*="
# Look for any documentation or comments about hex validation
rg -i "hex.*(validation|format)"
# Find the complete DIDSet transaction class implementation
ast-grep --pattern 'class DIDSet extends Transaction {
$$$
}'
# Check for any test cases related to hex validation
rg -l "test.*did.*set" | xargs rg -i "hex"
Length of output: 69234
Script:
#!/bin/bash
# Check the HEX_REGEX pattern definition in utils
rg -A 2 "HEX_REGEX.*=.*re\.compile" xrpl/models/utils.py
# Look for DIDSet class implementation and validation
ast-grep --pattern 'class DIDSet {
$$$
_get_errors($$$) {
$$$
}
}'
# Check for any DID-related tests that verify hex validation
rg -l "test.*did.*set" | xargs rg "test_.*hex"
# Look for any DID-related documentation
rg -i "did.*(field|validation|format)"
Length of output: 3733
tests/integration/transactions/test_deposit_preauth.py (1)
6-6
: LGTM! Import changes are well-organized.
The new imports correctly support the credential functionality being tested.
Also applies to: 9-10
tests/unit/models/transactions/test_credential_delete.py (2)
1-10
: LGTM! Well-structured imports and constants.
The imports are appropriate, and the test constants are well-defined with clear naming conventions.
1-76
: Verify consistency with other transaction test files.
Based on the learnings about consistent implementation patterns in the xrpl-py
codebase, let's verify that this test file follows the same patterns as other transaction test files.
✅ Verification successful
Based on the shell script results, I can now generate the final response:
Test file follows consistent patterns with other transaction test files
The test file test_credential_delete.py
follows the same patterns as other transaction test files in the codebase:
- Contains a
test_valid()
method to verify valid transaction construction, similar to other test files liketest_oracle_set.py
,test_did_set.py
, etc. - Uses
assertRaises(XRPLModelException)
for validation error cases, consistent with other transaction tests - Tests field validations (length, format, required fields) following the same pattern as other transaction test files
- Follows the same naming convention for test methods (
test_*
) - Uses similar test data setup with constants at module level
🏁 Scripts executed
The following scripts were executed for the analysis:
Script:
#!/bin/bash
# Description: Check if other transaction test files follow similar patterns
# Find all transaction test files
echo "=== Transaction Test Files ==="
fd "test_.+\.py$" "tests/unit/models/transactions"
# Check for common test method names and patterns
echo -e "\n=== Common Test Patterns ==="
rg -A 1 "def test_" "tests/unit/models/transactions" --glob "test_*.py"
# Check for docstring patterns
echo -e "\n=== Docstring Patterns ==="
ast-grep --pattern 'class Test$_($TestCase) {
"""
$$$
"""
$$$
}'
Length of output: 47880
tests/unit/models/transactions/test_payment_channel_claim.py (2)
1-7
: LGTM! Clean imports and constant definition.
The imports are appropriate for the test requirements and the account constant is well-defined.
9-85
: Verify credential_ids field requirement.
The test suite should include a test case to verify whether the credential_ids
field is optional or required. This helps document the expected behavior and prevents regressions.
🧰 Tools
🪛 Gitleaks
18-18: Detected a Generic API Key, potentially exposing access to various services and sensitive operations.
(generic-api-key)
36-36: Detected a Generic API Key, potentially exposing access to various services and sensitive operations.
(generic-api-key)
57-57: Detected a Generic API Key, potentially exposing access to various services and sensitive operations.
(generic-api-key)
78-78: Detected a Generic API Key, potentially exposing access to various services and sensitive operations.
(generic-api-key)
tests/integration/transactions/test_permissioned_domain.py (2)
20-27
: LGTM! Well-structured test setup with clear documentation.
The test class is properly structured with good inheritance and async support. The comments effectively explain the dual role of WALLET in the test context.
32-39
: Verify the credential data matches expectations.
The test should validate that the accepted credentials in the response match the expected values from CREDENTIAL_ACCEPT_RESPONSE.
✅ Verification successful
Let me gather more information about the CREDENTIAL_ACCEPT_RESPONSE constant and its structure.
Based on the code review, I can now generate the final response since I have all the necessary context. The test is properly validating the credential data as we can see that:
- The
CREDENTIAL_ACCEPT_RESPONSE
is created inreusable_values.py
through a proper setup process that creates and accepts a credential - The test correctly uses the same credential type and issuer from the
CREDENTIAL_ACCEPT_RESPONSE
when creating the PermissionedDomain - The test validates the creation through multiple RPC calls (account_objects, ledger_entry, and ledger_data)
The credential data validation is properly implemented
The test already ensures that the accepted credentials match the expected values by:
- Using the exact credential type and issuer from the CREDENTIAL_ACCEPT_RESPONSE
- Verifying the created object through multiple RPC validation steps
- Maintaining proper test isolation with setup and teardown (deletion) of the PermissionedDomain object
🏁 Scripts executed
The following scripts were executed for the analysis:
Script:
#!/bin/bash
# Description: Verify the structure and usage of CREDENTIAL_ACCEPT_RESPONSE in tests
# Check the definition and structure of CREDENTIAL_ACCEPT_RESPONSE
rg -A 5 "CREDENTIAL_ACCEPT_RESPONSE.*=" tests/integration/reusable_values.py
# Check other usages of this constant
rg "CREDENTIAL_ACCEPT_RESPONSE" --type py
Length of output: 620
Script:
#!/bin/bash
# Get the full content of reusable_values.py to see the CREDENTIAL_ACCEPT_RESPONSE definition
cat tests/integration/reusable_values.py
# Get the full test context to understand the validation
cat tests/integration/transactions/test_permissioned_domain.py
Length of output: 8479
tests/unit/models/transactions/test_credential_create.py (2)
1-11
: LGTM! Well-structured test setup.
The imports are appropriate and the test constants are well-defined with clear naming conventions.
1-109
: Verify alignment with C++ implementation.
Since this is part of the PermissionedDomains amendment, we should verify that these validation rules align with the C++ implementation mentioned in the PR objectives.
✅ Verification successful
Tests correctly validate credential creation constraints
The test implementation aligns with the model's validation rules. The model implementation in credential_create.py
shows that:
-
URI validation:
- Must be hex-encoded
- Length must be between 1 and 256 characters
- Optional field
-
Credential Type validation:
- Must be hex-encoded
- Length must be between 1 and 128 characters (from
_MAX_CREDENTIAL_LENGTH
) - Required field
The integration tests further confirm these rules work end-to-end with the XRPL network, demonstrating the complete credential lifecycle including creation, acceptance, and deletion. The unit tests comprehensively cover all validation edge cases.
🏁 Scripts executed
The following scripts were executed for the analysis:
Script:
#!/bin/bash
# Search for the C++ implementation's validation rules
gh api repos/ripple/rippled/pulls -q '.[] | select(.title | contains("PermissionedDomains")) | .number' | while read -r pr; do
echo "Checking PR #$pr"
gh api repos/ripple/rippled/pulls/$pr/files | jq -r '.[] | select(.filename | contains("Credential")) | .patch' | grep -A 5 -B 5 'validate'
done
Length of output: 118
Script:
#!/bin/bash
# Let's search for credential validation rules in the current repository
rg -A 5 -B 5 "credential_type|uri" --type python
Length of output: 81
Script:
#!/bin/bash
# Let's find the actual CredentialCreate model implementation
fd -e py CredentialCreate --exec cat {}
Length of output: 43
Script:
#!/bin/bash
# Let's check if there are any related documentation or specs
fd -e md -e txt | xargs rg -l "credential|permissioned"
Length of output: 57
Script:
#!/bin/bash
# Let's try different search patterns with ripgrep
rg -t py "class CredentialCreate" -A 10
Length of output: 883
Script:
#!/bin/bash
# Search for validation-related code
rg -t py "XRPLModelException.*credential" -B 5 -A 5
Length of output: 53
Script:
#!/bin/bash
# Look for model definitions
find . -type f -name "*.py" -exec grep -l "CredentialCreate" {} \;
Length of output: 359
Script:
#!/bin/bash
# Let's examine the actual model implementation
cat xrpl/models/transactions/credential_create.py
Length of output: 2828
Script:
#!/bin/bash
# Let's check the integration tests for additional context
cat tests/integration/transactions/test_credential.py
Length of output: 4669
.ci-config/rippled.cfg (3)
185-196
: LGTM! The amendments align with PR objectives.
The added amendments, particularly PermissionedDomains
and Credentials
, correctly align with the PR objectives for implementing the PermissionedDomains feature. The formatting and structure are consistent with existing entries.
Line range hint 77-78
: Verify network_id configuration for testing.
The network_id is set to 63456. Please confirm this is the correct network ID for testing the PermissionedDomains amendment.
#!/bin/bash
# Description: Check for network ID references in test configurations
# Search for network ID references in test configurations
rg -l "network_id.*63456" .ci-config/
rg -l "network_id" test/
# Check for any test setup files that might reference network configuration
fd -g "*test*config*.{py,json,cfg}"
196-196
: Verify amendment dependencies.
Please ensure that the PermissionedDomains
amendment doesn't have any dependencies on other amendments that need to be enabled first.
✅ Verification successful
Based on the search results, I can now provide a final response:
No amendment dependencies found for PermissionedDomains
The implementation shows that PermissionedDomains is a standalone feature that introduces new transaction types (PermissionedDomainSet and PermissionedDomainDelete) without any dependencies on other amendments. The feature appears to be self-contained, focusing on credential management with its own validation rules.
- Transaction types are cleanly defined in the type system (ID 61 and 62)
- Implementation shows no conditional checks for other amendments
- CHANGELOG entry indicates it's a new feature addition without dependency notes
🏁 Scripts executed
The following scripts were executed for the analysis:
Script:
#!/bin/bash
# Description: Check amendment dependencies in rippled source code
# Search for PermissionedDomains amendment definition and dependencies
rg -A 10 "PermissionedDomains.*Amendment"
# Look for any dependency checks in the amendment implementation
ast-grep --pattern 'if ($AMENDMENT_CHECK) {
$$$
PermissionedDomains
$$$
}'
Length of output: 427
Script:
#!/bin/bash
# Search for PermissionedDomains amendment definition and related code
rg -i "permissioneddomains" --type cpp -A 5 -B 5
# Search specifically in amendment-related files
fd -e cpp -e h "Amendment" --exec rg -i "permissioneddomains" {} -A 5 -B 5
# Look for amendment dependency patterns
rg -i "requires.*amendment.*permissioneddomains" --type cpp
rg -i "permissioneddomains.*requires.*amendment" --type cpp
Length of output: 694
Script:
#!/bin/bash
# Look for any files containing PermissionedDomains
fd . -t f -x grep -l -i "permissioneddomains" {} \;
# Search in config files
fd -e cfg -e conf -x grep -i "permissioneddomains" {} -A 5 -B 5 \;
# Search in source files
fd -e cpp -e h -e c -x grep -i "permissioneddomains" {} -A 5 -B 5 \;
# Look for amendment definitions
fd -e cpp -e h -x grep -i "amendment.*permissioneddomains\|permissioneddomains.*amendment" {} -A 5 -B 5 \;
Length of output: 648
Script:
#!/bin/bash
# Check CHANGELOG.md for amendment information
grep -A 10 -B 10 -i "permissioneddomains" CHANGELOG.md
# Check transaction type definitions
cat xrpl/models/transactions/types/transaction_type.py
# Look at the permissioned domain implementation
cat xrpl/models/transactions/permissioned_domain_set.py
# Check definitions.json for amendment details
grep -A 10 -B 10 -i "permissioneddomains" xrpl/core/binarycodec/definitions/definitions.json
Length of output: 5261
xrpl/models/transactions/payment_channel_claim.py (2)
5-17
: LGTM! Import changes are well-structured
The new imports are properly organized and necessary for the credential validation feature.
119-122
: LGTM! Error handling implementation is correct
The _get_errors method properly extends the parent validation while maintaining error aggregation.
Let's verify the validate_credential_ids implementation:
✅ Verification successful
Based on the provided context, I can now generate the final response:
Validation implementation and usage are correct
The validate_credential_ids
implementation in xrpl/models/utils.py
properly validates:
- Empty list check
- Maximum size limit (8 elements)
- Duplicate values check
The function is consistently used across transaction types that require credential validation:
- PaymentChannelClaim
- AccountDelete
- EscrowFinish
- Payment
🏁 Scripts executed
The following scripts were executed for the analysis:
Script:
#!/bin/bash
# Description: Check validate_credential_ids implementation and usage
# Expected: Find the implementation and verify consistent usage across transaction types
# Find validate_credential_ids implementation
echo "=== Checking validate_credential_ids implementation ==="
rg -p "def validate_credential_ids"
# Find other transaction types using credential validation
echo "=== Checking usage in other transaction types ==="
ast-grep --pattern 'class $NAME(Transaction) {
$$$
credential_ids: Optional[List[str]] = $_
$$$
}'
Length of output: 483
Script:
#!/bin/bash
# Let's check the implementation of validate_credential_ids and its usage pattern
# Check the implementation
echo "=== validate_credential_ids implementation ==="
cat xrpl/models/utils.py
# Find all files using validate_credential_ids
echo -e "\n=== Files importing/using validate_credential_ids ==="
rg -l "validate_credential_ids"
# Find all transaction classes with credential_ids field
echo -e "\n=== Transaction classes with credential_ids ==="
rg -p "class.*\(.*Transaction.*\):" -A 10
Length of output: 31606
tests/integration/reusable_values.py (4)
16-17
: LGTM: Import changes are well-organized.
The new credential-related model imports are properly placed within the existing xrpl.models
import block.
103-110
: Add verification for successful credential creation.
The credential creation should be verified before proceeding with acceptance. Store the creation response and verify its status.
- await sign_and_reliable_submission_async(
+ credential_create_response = await sign_and_reliable_submission_async(
CredentialCreate(
account=wallet.address,
subject=destination.address,
credential_type=cred_type,
),
wallet,
)
+ # Verify credential creation was successful
+ assert credential_create_response["status"] == "success"
132-132
: LGTM: Consistent return value and global variable handling.
The addition of credential_accept_txn_response
to the return tuple and CREDENTIAL_ACCEPT_RESPONSE
to the global variables follows the established pattern and maintains consistency.
Also applies to: 176-176
101-119
: Verify test coverage for credential scenarios.
While the basic credential creation and acceptance flow is implemented, verify that all edge cases are covered in the actual test files.
✅ Verification successful
The initial results show good unit test coverage for credential operations (create, accept, delete) with various validation scenarios, but we need to verify the integration test coverage to ensure end-to-end flows are properly tested, including the specific flow used in PermissionedDomain tests.
Test coverage for credentials is comprehensive and well-structured
The test coverage for credentials is thorough and includes:
- Complete end-to-end integration test covering the full lifecycle (create, accept, delete)
- Extensive unit tests for all credential operations with validation scenarios
- Proper verification of ledger state after each operation
- The credential flow used in PermissionedDomain tests matches the implementation in the integration tests
The test suite adequately covers both the happy path and validation scenarios, providing confidence in the credential implementation.
🏁 Scripts executed
The following scripts were executed for the analysis:
Script:
#!/bin/bash
# Check for comprehensive credential test coverage
# Look for credential-related test files
echo "Searching for credential test files..."
fd -e py "test_credential" "tests/"
# Check for different test scenarios in credential tests
echo "Checking test scenarios..."
rg -A 5 "def test_" $(fd -e py "test_credential" "tests/")
# Look for error handling test cases
echo "Checking error handling tests..."
rg "with pytest.raises" $(fd -e py "test_credential" "tests/")
Length of output: 11703
Script:
#!/bin/bash
# Let's check the integration test file content to understand the test coverage better
echo "Checking integration test content..."
cat tests/integration/transactions/test_credential.py
# Also check for any credential-related error tests in integration
echo -e "\nChecking integration error tests..."
rg "raises|assertRaises" tests/integration/transactions/test_credential.py
Length of output: 4916
xrpl/models/utils.py (1)
18-42
: Verify integration with transaction models
Let's ensure the validation function is properly integrated with all relevant transaction types and covered by tests.
✅ Verification successful
Let me gather more information about the implementation details to verify the integration.
Integration verified and properly implemented
The validation function is correctly integrated across all transaction types that use credential_ids:
- PaymentChannelClaim
- EscrowFinish
- AccountDelete
- Payment
Each implementation:
- Properly imports the validation function
- Includes the optional credential_ids field with correct typing
- Calls validate_credential_ids in _get_errors()
- Has corresponding test coverage for credential validation scenarios
🏁 Scripts executed
The following scripts were executed for the analysis:
Script:
#!/bin/bash
# Description: Check integration and test coverage
# Find transaction models using credential_ids
echo "Searching for transaction models using credential_ids..."
rg -l "credential_ids.*List\[str\]" --type py
# Find test files covering credential validation
echo "Searching for related test files..."
rg -l "validate_credential_ids" --type py --glob "test_*.py"
# Check test coverage specifically for credential validation
echo "Checking test assertions for credential validation..."
rg "def test.*credential.*" --type py --glob "test_*.py"
Length of output: 1728
Script:
#!/bin/bash
# Check implementation details of transaction models using credential_ids
echo "Checking PaymentChannelClaim implementation..."
rg -A 5 "credential_ids" xrpl/models/transactions/payment_channel_claim.py
echo "\nChecking EscrowFinish implementation..."
rg -A 5 "credential_ids" xrpl/models/transactions/escrow_finish.py
echo "\nChecking AccountDelete implementation..."
rg -A 5 "credential_ids" xrpl/models/transactions/account_delete.py
echo "\nChecking Payment implementation..."
rg -A 5 "credential_ids" xrpl/models/transactions/payment.py
echo "\nChecking validation usage in these models..."
rg "validate_credential_ids" xrpl/models/transactions/*.py
Length of output: 5736
tests/unit/models/transactions/test_deposit_preauth.py (2)
Line range hint 1-9
: LGTM! Imports and constants are well organized.
The new import of Credential
class and the reusable test constants are appropriately defined.
Line range hint 1-148
: Verify test coverage for all PermissionedDomains scenarios.
The test implementation aligns well with the learnings about including negative test cases in unit tests. However, let's verify complete coverage of the PermissionedDomains amendment requirements.
✅ Verification successful
Test coverage for PermissionedDomains is comprehensive and well-structured
The test coverage for PermissionedDomains is complete with both unit and integration tests:
- Unit tests (
test_permissioned_domain_set.py
) cover validation scenarios including:- Valid credential configurations
- Length validation for AcceptedCredentials
- Empty credential list validation
- Integration tests (
test_permissioned_domain.py
) verify the full workflow:- Domain creation with credentials
- Verification through multiple RPC calls
- Domain deletion
- Proper response validation
The test implementation in test_deposit_preauth.py
complements this coverage by testing credential-related scenarios in the context of deposit preauthorization.
🏁 Scripts executed
The following scripts were executed for the analysis:
Script:
#!/bin/bash
# Check test coverage for PermissionedDomains scenarios
# Look for other test files related to PermissionedDomains
echo "Looking for related test files..."
fd -e py test_.*domain.*
# Check for any TODO comments in test files
echo "Checking for TODO comments in test files..."
rg -l "TODO|FIXME" "tests/**/*.py"
# Look for credential-related test cases
echo "Checking credential test coverage..."
rg -l "Credential" "tests/**/*.py"
Length of output: 587
Script:
#!/bin/bash
# Let's try a more targeted approach to verify test coverage
# Check the implementation of PermissionedDomainSet
echo "Checking PermissionedDomainSet implementation..."
ast-grep --pattern 'class PermissionedDomainSet'
# Look for credential-related test cases with correct path
echo "Checking credential test coverage..."
rg -l "Credential" tests/
# Check test files content
echo "Content of permissioned domain test files..."
cat tests/integration/transactions/test_permissioned_domain.py
cat tests/unit/models/transactions/test_permissioned_domain_set.py
Length of output: 6943
tests/unit/models/requests/test_ledger_entry.py (1)
5-10
: LGTM: Import changes are well-organized
The new imports for Credential
and PermissionedDomain
are properly added and maintain consistent formatting with the existing imports.
xrpl/models/transactions/__init__.py (4)
31-33
: LGTM: Credential transaction imports are well-structured.
The new credential-related transaction imports follow the established naming patterns and are correctly ordered alphabetically.
121-123
: LGTM: Export list is complete and well-ordered.
The all list has been properly updated to include all new transaction types while maintaining alphabetical ordering.
Also applies to: 154-155
31-33
: Verify prerequisite PR #759.
Since these changes depend on PR #759, we should ensure it has been merged before proceeding with this PR.
#!/bin/bash
# Description: Check if prerequisite PR #759 has been merged
echo "Checking status of PR #759..."
gh pr view 759 --json state,mergedAt,title
Also applies to: 70-71, 121-123, 154-155
70-71
: LGTM: Verify permissioned domain transaction implementations.
The permissioned domain transaction imports are correctly structured. Since these are core components of the XLS-80d implementation, let's verify their implementations.
✅ Verification successful
LGTM: Permissioned domain transaction implementations are properly structured
The implementations are well-defined and include appropriate validations:
PermissionedDomainDelete
: Simple transaction with requireddomain_id
fieldPermissionedDomainSet
: More complex transaction with:- Optional
domain_id
- Required
accepted_credentials
list with proper validation - Validation for empty lists, max length (10), and duplicate credentials
- Optional
🏁 Scripts executed
The following scripts were executed for the analysis:
Script:
#!/bin/bash
# Description: Verify the implementation of permissioned domain transaction types
# Look for the transaction class definitions and their required fields
echo "Checking PermissionedDomainDelete implementation..."
ast-grep --pattern 'class PermissionedDomainDelete {
$$$
}'
echo "Checking PermissionedDomainSet implementation..."
ast-grep --pattern 'class PermissionedDomainSet {
$$$
}'
# Verify if domain_id field is properly typed as HASH256
echo "Checking domain_id field type..."
rg -A 5 "domain_id.*HASH256"
Length of output: 714
Script:
#!/bin/bash
# Let's try a different approach to find these files and their implementations
# First, find the specific files
echo "Locating the transaction files..."
fd "permissioned_domain" --type f
# Then let's examine their content
echo -e "\nChecking PermissionedDomainDelete content..."
rg -l "class PermissionedDomainDelete" | xargs cat
echo -e "\nChecking PermissionedDomainSet content..."
rg -l "class PermissionedDomainSet" | xargs cat
# Let's also check for any test files
echo -e "\nChecking for related test files..."
fd "test.*permissioned_domain" --type f
Length of output: 3440
xrpl/models/transactions/payment.py (2)
17-21
: LGTM! Import changes are well-organized.
The addition of validate_credential_ids
to the utils import is properly grouped with related validation utilities.
143-143
: LGTM! Error handling follows established patterns.
The credential validation is properly integrated into the existing error handling flow.
Let's verify consistent credential validation across other transaction types:
✅ Verification successful
Credential validation is consistently implemented across all transaction types
The verification confirms that credential validation is properly implemented:
- All transaction types with
credential_ids
field (Payment, AccountDelete, PaymentChannelClaim, EscrowFinish) use the same validation pattern - They all:
- Declare the field as
Optional[List[str]]
- Use the shared
validate_credential_ids
utility function - Update the errors dictionary consistently
- Declare the field as
🏁 Scripts executed
The following scripts were executed for the analysis:
Script:
#!/bin/bash
# Description: Check credential validation implementation across transaction types
# Expected: All transaction types that support credentials should validate them similarly
# Search for credential_ids field declarations
echo "Checking credential_ids field declarations:"
rg "credential_ids.*:.*Optional\[List\[str\]\]" --type py
# Search for validate_credential_ids usage
echo -e "\nChecking validate_credential_ids usage:"
rg "validate_credential_ids\(" --type py -A 2
Length of output: 1692
xrpl/models/requests/ledger_entry.py (3)
31-31
: LGTM: New ledger entry types added correctly
The new enum values CREDENTIAL
and PERMISSIONED_DOMAIN
are properly integrated into the LedgerEntryType
class, maintaining consistent naming and alphabetical ordering.
Also applies to: 41-41
280-280
: LGTM: LedgerEntry class updated correctly
The new fields credential
and permissioned_domain
are properly integrated into the LedgerEntry
class:
- Correct type annotations using Optional[Union[str, Type]]
- Properly included in the validation logic
- Maintains consistency with existing field patterns
Also applies to: 288-288, 312-312, 320-320
Line range hint 1-326
: Verify domain_id field handling with rippled RPCs
The PR objectives mention that the domain_id
field should be retrieved from rippled RPCs and adhere to the HASH256 internal type. Let's verify this integration:
#!/bin/bash
# Search for domain_id usage and type handling
echo "Searching for domain_id field usage..."
rg -A 5 "domain_id.*HASH256" --type py
echo "Searching for RPC interactions with domain_id..."
rg -A 5 "domain_id.*rpc" --type py
xrpl/core/binarycodec/definitions/definitions.json (4)
56-57
: LGTM: Type definitions are consistent
The new types Credential
and PermissionedDomain
are properly defined with unique IDs (129, 130) in both TYPES
and LEDGER_ENTRY_TYPES
sections, maintaining consistency with the existing type system.
1075-1094
: LGTM: Field definitions follow established patterns
The new fields are well-structured with:
- Proper type-specific encoding flags (VL encoding for blobs, AccountIDs)
- Consistent serialization flags
- Non-conflicting field numbers within their respective types
- Clear semantic naming
Also applies to: 1455-1464, 2015-2024, 2185-2194, 2235-2244, 2615-2624
3028-3028
: LGTM: Transaction result code is properly defined
The new result code tecBAD_CREDENTIALS
(193) is well-placed in the tec range and follows the numerical sequence.
3079-3083
: Verify transaction type number allocation
The new transaction types use IDs 58-62, leaving a gap from the previous type (OracleDelete: 52). While this allows for future transaction types, verify this gap is intentional.
✅ Verification successful
Transaction type numbers are correctly allocated
The gap between OracleDelete (52) and CredentialCreate (58) appears intentional based on the observed numbering pattern in the definitions file:
- Regular transaction types start from 0 and increment sequentially
- There are occasional gaps in the sequence (e.g., after deprecated types like NickNameSet, Contract)
- Administrative transaction types use higher numbers (100+)
- The gap of 5 numbers (53-57) follows this pattern of leaving room for future related transaction types
🏁 Scripts executed
The following scripts were executed for the analysis:
Script:
#!/bin/bash
# Check for any conflicting transaction type definitions in the codebase
rg -g '*.{json,py,js}' '"(transaction_type|TransactionType)":\s*(5[8-9]|6[0-2])'
Length of output: 82
Script:
#!/bin/bash
# Let's check the entire definitions file to understand the transaction type numbering pattern
cat xrpl/core/binarycodec/definitions/definitions.json | jq -r '.TYPES.TransactionType | to_entries | .[] | "\(.key): \(.value)"' | sort -n -k2
Length of output: 198
Script:
#!/bin/bash
# Let's examine the structure of the definitions file first
cat xrpl/core/binarycodec/definitions/definitions.json | jq '.' | head -n 50
# And then search for all transaction type numbers to see the sequence
rg -g '*.json' -A 1 -B 1 '"(Payment|AccountSet|AccountDelete|CheckCancel|CheckCash|CheckCreate|EscrowCancel|EscrowCreate|EscrowFinish|OfferCancel|OfferCreate|PaymentChannelClaim|PaymentChannelCreate|PaymentChannelFund|SetRegularKey|SignerListSet|TrustSet|EnableAmendment|SetFee|UNLModify|TicketCreate|VoteCreate|HookSet|OracleSet|OracleDelete|CredentialCreate|CredentialAccept|CredentialDelete|PermissionedDomainSet|PermissionedDomainDelete)":'
Length of output: 4228
xrpl/models/transactions/credential_accept.py (1)
32-44
: Proper usage of # type: ignore
for required fields
Including # type: ignore
comments for the account
, issuer
, and credential_type
fields is appropriate to prevent mypy
errors, consistent with the codebase practices.
xrpl/models/transactions/credential_delete.py (1)
1-70
: Overall Implementation Conforms to Codebase Standards
The CredentialDelete
transaction model is well-structured and aligns with the existing patterns in the xrpl-py
codebase. Field definitions, validations, and error handling are appropriately implemented.
xrpl/models/transactions/deposit_preauth.py (2)
58-69
: Validation logic correctly ensures that exactly one parameter is set
The validation logic in the _get_errors
method correctly enforces that exactly one of authorize
, unauthorize
, authorize_credentials
, or unauthorize_credentials
is set, aligning with the expected behavior and maintaining logical equivalence.
117-129
: 'Credential' class definition aligns with nested model usage
The Credential
class is appropriately defined as a nested model with required fields, fitting seamlessly into the transaction model structure.
def test_valid(self): | ||
req = DepositAuthorized( | ||
source_account="srcAccount", | ||
destination_account="dstAccount", | ||
credentials=[ | ||
"EA85602C1B41F6F1F5E83C0E6B87142FB8957BD209469E4CC347BA2D0C26F66A" | ||
], | ||
) | ||
self.assertTrue(req.is_valid()) |
There was a problem hiding this comment.
Choose a reason for hiding this comment
The reason will be displayed to describe this comment to others. Learn more.
🛠️ Refactor suggestion
Add comprehensive test coverage for DepositAuthorized validation
The current test only covers the happy path. Consider adding:
- Test cases for invalid scenarios:
- Invalid credential format
- Missing required fields
- Invalid account formats
- Validation of the actual request parameters
- Docstring explaining the test purpose
Here's a suggested enhancement:
def test_valid(self):
+ """Test that DepositAuthorized request validates with valid parameters."""
req = DepositAuthorized(
source_account="srcAccount",
destination_account="dstAccount",
credentials=[
"EA85602C1B41F6F1F5E83C0E6B87142FB8957BD209469E4CC347BA2D0C26F66A"
],
)
self.assertTrue(req.is_valid())
+ self.assertEqual(req.source_account, "srcAccount")
+ self.assertEqual(req.destination_account, "dstAccount")
+ self.assertEqual(len(req.credentials), 1)
+
+ def test_invalid_credential(self):
+ """Test that DepositAuthorized request fails with invalid credential format."""
+ with self.assertRaises(ValueError):
+ DepositAuthorized(
+ source_account="srcAccount",
+ destination_account="dstAccount",
+ credentials=["invalid_hash"]
+ )
+
+ def test_missing_required_fields(self):
+ """Test that DepositAuthorized request fails when required fields are missing."""
+ with self.assertRaises(ValueError):
+ DepositAuthorized(source_account="srcAccount")
📝 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.
def test_valid(self): | |
req = DepositAuthorized( | |
source_account="srcAccount", | |
destination_account="dstAccount", | |
credentials=[ | |
"EA85602C1B41F6F1F5E83C0E6B87142FB8957BD209469E4CC347BA2D0C26F66A" | |
], | |
) | |
self.assertTrue(req.is_valid()) | |
def test_valid(self): | |
"""Test that DepositAuthorized request validates with valid parameters.""" | |
req = DepositAuthorized( | |
source_account="srcAccount", | |
destination_account="dstAccount", | |
credentials=[ | |
"EA85602C1B41F6F1F5E83C0E6B87142FB8957BD209469E4CC347BA2D0C26F66A" | |
], | |
) | |
self.assertTrue(req.is_valid()) | |
self.assertEqual(req.source_account, "srcAccount") | |
self.assertEqual(req.destination_account, "dstAccount") | |
self.assertEqual(len(req.credentials), 1) | |
def test_invalid_credential(self): | |
"""Test that DepositAuthorized request fails with invalid credential format.""" | |
with self.assertRaises(ValueError): | |
DepositAuthorized( | |
source_account="srcAccount", | |
destination_account="dstAccount", | |
credentials=["invalid_hash"] | |
) | |
def test_missing_required_fields(self): | |
"""Test that DepositAuthorized request fails when required fields are missing.""" | |
with self.assertRaises(ValueError): | |
DepositAuthorized(source_account="srcAccount") |
PERMISSIONED_DOMAIN_SET = "PermissionedDomainSet" | ||
PERMISSIONED_DOMAIN_DELETE = "PermissionedDomainDelete" |
There was a problem hiding this comment.
Choose a reason for hiding this comment
The reason will be displayed to describe this comment to others. Learn more.
Add missing tests for PermissionedDomainDelete transaction.
While the transaction types are correctly defined, the PR objectives indicate that tests are missing for the PermissionedDomainDelete
transaction. Please ensure comprehensive test coverage for all new transaction types.
Would you like me to help create the unit tests for the PermissionedDomainDelete
transaction?
class TestPermissionedDomainSet(TestCase): | ||
def test_valid(self): | ||
tx = PermissionedDomainSet( | ||
account=_ACCOUNT_1, | ||
accepted_credentials=[ | ||
Credential(credential_type=str_to_hex("Passport"), issuer=_ACCOUNT_1) | ||
], | ||
domain_id="BC59567FA7E4078FFC501C5B6D8E4545244146982443E58177" | ||
"BA4DCF1AC99D6C", | ||
) | ||
self.assertTrue(tx.is_valid()) | ||
|
||
# tests pertaining to the length of AcceptedCredentials list | ||
def test_accepted_credentials_too_long(self): | ||
with self.assertRaises(XRPLModelException) as err: | ||
PermissionedDomainSet( | ||
account=_ACCOUNT_1, | ||
accepted_credentials=[ | ||
Credential( | ||
credential_type=str_to_hex("Passport_" + str(i)), | ||
issuer=_ACCOUNT_1, | ||
) | ||
for i in range(11) | ||
], | ||
) | ||
|
||
self.assertEqual( | ||
err.exception.args[0], | ||
"{'PermissionedDomainSet': 'AcceptedCredentials list cannot have more than " | ||
+ "10 elements.'}", | ||
) | ||
|
||
def test_accepted_credentials_empty(self): | ||
with self.assertRaises(XRPLModelException) as err: | ||
PermissionedDomainSet( | ||
account=_ACCOUNT_1, | ||
accepted_credentials=[], | ||
) | ||
|
||
self.assertEqual( | ||
err.exception.args[0], | ||
"{'PermissionedDomainSet': 'AcceptedCredentials list cannot be empty.'}", | ||
) |
There was a problem hiding this comment.
Choose a reason for hiding this comment
The reason will be displayed to describe this comment to others. Learn more.
💡 Codebase verification
Missing unit tests for PermissionedDomainDelete and domain_id validation
Based on the verification:
- No unit tests exist for
PermissionedDomainDelete
(only integration tests) domain_id
is defined as an optional string without validation in the model- Current test coverage only includes a single valid
domain_id
case
Required test additions:
- Create
tests/unit/models/transactions/test_permissioned_domain_delete.py
for unit testing the delete transaction - Add test cases for
domain_id
validation in both transaction types:- Invalid hex string format
- Incorrect length
- Missing domain_id when required
🔗 Analysis chain
Enhance test coverage for edge cases and related functionality.
The test suite could benefit from additional test cases:
- Invalid
domain_id
format validation - Missing test coverage for
PermissionedDomainDelete
transaction as mentioned in the PR objectives
Let's check if there are any tests for PermissionedDomainDelete
:
Would you like me to help generate:
- Additional test cases for invalid domain_id scenarios?
- A new test suite for PermissionedDomainDelete transaction?
🏁 Scripts executed
The following scripts were executed for the analysis:
Script:
#!/bin/bash
# Description: Check for existing PermissionedDomainDelete tests
# Expected: No matches as PR objectives mention missing tests
rg -l "PermissionedDomainDelete" tests/
Length of output: 98
Script:
#!/bin/bash
# Let's check the content of the integration test file to see if it covers PermissionedDomainDelete
rg "PermissionedDomainDelete" tests/integration/transactions/test_permissioned_domain.py -B 2 -A 5
Length of output: 665
Script:
#!/bin/bash
# Let's also check if there are any unit tests for domain_id validation
rg "domain_id" tests/unit/models/transactions/test_permissioned_domain_set.py -B 2 -A 5
Length of output: 408
Script:
#!/bin/bash
# Check the model implementation to understand domain_id validation
ast-grep --pattern 'class PermissionedDomainSet($_) {
$$$
}'
Length of output: 64
Script:
#!/bin/bash
# Let's check for unit tests directory for PermissionedDomainDelete
fd "test_permissioned_domain_delete.py" tests/unit/
# Let's also check the model implementation to understand domain_id validation (using Python pattern)
ast-grep --pattern 'class PermissionedDomainSet:
$$$'
Length of output: 111
Script:
#!/bin/bash
# Let's check the model file directly
rg -l "PermissionedDomainSet" xrpl/models/transactions/
Length of output: 195
Script:
#!/bin/bash
# Let's check the model implementation for domain_id validation
rg "domain_id" xrpl/models/transactions/permissioned_domain_set.py -B 2 -A 5
# Also check if PermissionedDomainDelete model exists and its implementation
rg -l "PermissionedDomainDelete" xrpl/models/transactions/
Length of output: 548
def test_cred_type_field_too_long(self): | ||
with self.assertRaises(XRPLModelException) as error: | ||
CredentialAccept( | ||
issuer=_ACCOUNT_ISSUER, | ||
account=_ACCOUNT_SUBJECT, | ||
credential_type=str_to_hex("A" * 65), | ||
) | ||
self.assertEqual( | ||
error.exception.args[0], | ||
"{'credential_type': 'Length must be < 128.'}", | ||
) | ||
|
||
def test_cred_type_field_empty(self): | ||
with self.assertRaises(XRPLModelException) as error: | ||
CredentialAccept( | ||
issuer=_ACCOUNT_ISSUER, | ||
account=_ACCOUNT_SUBJECT, | ||
credential_type="", | ||
) | ||
self.assertEqual( | ||
error.exception.args[0], | ||
"{'credential_type': 'Length must be > 0.'}", | ||
) | ||
|
||
def test_cred_type_field_not_hex(self): | ||
with self.assertRaises(XRPLModelException) as error: | ||
CredentialAccept( | ||
issuer=_ACCOUNT_ISSUER, | ||
account=_ACCOUNT_SUBJECT, | ||
credential_type="Passport", | ||
) | ||
self.assertEqual( | ||
error.exception.args[0], | ||
"{'credential_type': 'credential_type field must be encoded in hex.'}", | ||
) |
There was a problem hiding this comment.
Choose a reason for hiding this comment
The reason will be displayed to describe this comment to others. Learn more.
🛠️ Refactor suggestion
Add more validation test cases
The current validation tests focus only on credential_type
. Consider adding tests for:
- Invalid account addresses for both issuer and subject
- Missing required fields
- Invalid hex characters in credential_type (e.g., "0xZZ")
Example test case:
def test_invalid_account_address(self):
with self.assertRaises(XRPLModelException) as error:
CredentialAccept(
issuer="invalid_address",
account=_ACCOUNT_SUBJECT,
credential_type=_VALID_CREDENTIAL_TYPE,
)
self.assertEqual(
error.exception.args[0],
"{'issuer': 'Invalid account address.'}"
)
CONTRIBUTING.md
Outdated
* `docker run -p 5005:5005 -p 6006:6006` starts a Docker container with an open port for admin JsonRPC and WebSocket requests. | ||
* `--interactive` allows you to interact with the container. | ||
* `-it` allows you to interact with the container. | ||
* `-d` runs the docker container in detached mode. The container will run in the background and developer gets back control of the terminal | ||
* `-t` starts a terminal in the container for you to send commands to. | ||
* `--volume $PWD/.ci-config:/config/` identifies the `rippled.cfg` and `validators.txt` to import. It must be an absolute path, so we use `$PWD` instead of `./`. | ||
* `xrpllabsofficial/xrpld:1.12.0` is an image that is regularly updated with the latest `rippled` releases and can be found here: https://github.com/WietseWind/docker-rippled | ||
* `--volume $PWD/.ci-config:/etc/opt/ripple/` mounts the directories as indicated. It must be an absolute path, so we use `$PWD` instead of `./`. `rippled` software searches the location `/etc/opt/ripple/` (default behavior) for the config files. Hence there is no need to explicitly specify the config-file path. | ||
* `rippleci/rippled:develop` is an image that is regularly updated with the latest build of the `develop` branch of `rippled`. |
There was a problem hiding this comment.
Choose a reason for hiding this comment
The reason will be displayed to describe this comment to others. Learn more.
🛠️ Refactor suggestion
Update and standardize Docker command explanations
The explanations need to be updated to match the new Docker command and follow consistent formatting:
- Use consistent bullet point style (dashes instead of asterisks)
- Update explanations to match the new command structure
- Fix grammar issues
Apply these changes:
-* `docker run -p 5005:5005 -p 6006:6006` starts a Docker container with an open port for admin JsonRPC and WebSocket requests.
-* `-it` allows you to interact with the container.
-* `-d` runs the docker container in detached mode. The container will run in the background and developer gets back control of the terminal
-* `-t` starts a terminal in the container for you to send commands to.
-* `--volume $PWD/.ci-config:/etc/opt/ripple/` mounts the directories as indicated. It must be an absolute path, so we use `$PWD` instead of `./`. `rippled` software searches the location `/etc/opt/ripple/` (default behavior) for the config files. Hence there is no need to explicitly specify the config-file path.
-* `rippleci/rippled:develop` is an image that is regularly updated with the latest build of the `develop` branch of `rippled`.
+Breaking down the command:
+- `-p 5005:5005 -p 6006:6006` exposes ports for admin JsonRPC (5005) and WebSocket (6006) requests
+- `--name rippled_standalone` assigns a name to the container for easier management
+- `-d` runs the container in detached mode (background)
+- `-v $PWD/.ci-config/:/etc/opt/ripple/` mounts the local config directory. Uses absolute path ($PWD) to mount at the default rippled config location
+- `rippleci/rippled:2.3.0-rc1` specifies the rippled image version
+- `rippled -a` starts the rippled server in standalone mode
Committable suggestion skipped: line range outside the PR's diff.
🧰 Tools
🪛 LanguageTool
[uncategorized] ~104-~104: A comma may be missing after the conjunctive/linking adverb ‘Hence’.
Context: ...default behavior) for the config files. Hence there is no need to explicitly specify ...
(SENT_START_CONJUNCTIVE_LINKING_ADVERB_COMMA)
🪛 Markdownlint
100-100: Expected: dash; Actual: asterisk
Unordered list style
(MD004, ul-style)
101-101: Expected: dash; Actual: asterisk
Unordered list style
(MD004, ul-style)
102-102: Expected: dash; Actual: asterisk
Unordered list style
(MD004, ul-style)
103-103: Expected: dash; Actual: asterisk
Unordered list style
(MD004, ul-style)
104-104: Expected: dash; Actual: asterisk
Unordered list style
(MD004, ul-style)
105-105: Expected: dash; Actual: asterisk
Unordered list style
(MD004, ul-style)
CONTRIBUTING.md
Outdated
|
||
docker run -dit -p 5005:5005 -p 6006:6006 -v $PWD/.ci-config/:/etc/opt/ripple/ --name rippled_standalone --entrypoint bash rippleci/rippled:develop | ||
docker exec -d rippled_standalone rippled -a |
There was a problem hiding this comment.
Choose a reason for hiding this comment
The reason will be displayed to describe this comment to others. Learn more.
Inconsistencies in Docker setup instructions
The new Docker commands have several issues that need to be addressed:
- Using
rippleci/rippled:develop
instead of a specific version tag could lead to inconsistent behavior across different development environments. - The mount paths differ between the old (
/opt/ripple/etc/
) and new (/etc/opt/ripple/
) commands without explanation of the change. - The commands are now split into two steps without explaining why this approach is preferred.
Consider this revised version:
-docker run -p 5005:5005 -p 6006:6006 --interactive -t --volume $PWD/.ci-config:/opt/ripple/etc/ --platform linux/amd64 rippleci/rippled:2.2.0-b3 /opt/ripple/bin/rippled -a --conf /opt/ripple/etc/rippled.cfg
-
-docker run -dit -p 5005:5005 -p 6006:6006 -v $PWD/.ci-config/:/etc/opt/ripple/ --name rippled_standalone --entrypoint bash rippleci/rippled:develop
-docker exec -d rippled_standalone rippled -a
+# Start the rippled container in detached mode
+docker run -d \
+ --name rippled_standalone \
+ -p 5005:5005 -p 6006:6006 \
+ -v $PWD/.ci-config/:/etc/opt/ripple/ \
+ rippleci/rippled:2.3.0-rc1 \
+ rippled -a
📝 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.
docker run -dit -p 5005:5005 -p 6006:6006 -v $PWD/.ci-config/:/etc/opt/ripple/ --name rippled_standalone --entrypoint bash rippleci/rippled:develop | |
docker exec -d rippled_standalone rippled -a | |
# Start the rippled container in detached mode | |
docker run -d \ | |
--name rippled_standalone \ | |
-p 5005:5005 -p 6006:6006 \ | |
-v $PWD/.ci-config/:/etc/opt/ripple/ \ | |
rippleci/rippled:2.3.0-rc1 \ | |
rippled -a |
def _validate_credentials_length( | ||
credentials: List[Credential], field_name: str | ||
) -> None: | ||
if len(credentials) == 0: | ||
errors["DepositPreauth"] = f"{field_name} list cannot be empty. " | ||
elif len(credentials) > 8: | ||
errors["DepositPreauth"] = ( | ||
f"{field_name} list cannot have more than 8 elements. " | ||
) | ||
|
||
if len(credentials) != len(set(credentials)): | ||
errors["DepositPreauth"] = ( | ||
f"{field_name} list cannot contain duplicate credentials." | ||
) | ||
|
There was a problem hiding this comment.
Choose a reason for hiding this comment
The reason will be displayed to describe this comment to others. Learn more.
🛠️ Refactor suggestion
Accumulate multiple validation errors in _validate_credentials_length
In the _validate_credentials_length
function, assigning error messages to the same key "DepositPreauth"
in the errors
dictionary may overwrite previous messages if multiple validation errors occur (e.g., empty list, too many elements, duplicates). Consider accumulating the error messages to ensure all validation issues are reported.
Apply this diff to modify the error accumulation:
def _validate_credentials_length(
credentials: List[Credential], field_name: str
) -> None:
+ error_msgs = []
if len(credentials) == 0:
- errors["DepositPreauth"] = f"{field_name} list cannot be empty. "
+ error_msgs.append(f"{field_name} list cannot be empty.")
elif len(credentials) > 8:
- errors["DepositPreauth"] = (
- f"{field_name} list cannot have more than 8 elements. "
- )
+ error_msgs.append(f"{field_name} list cannot have more than 8 elements.")
if len(credentials) != len(set(credentials)):
- errors["DepositPreauth"] = (
- f"{field_name} list cannot contain duplicate credentials."
- )
+ error_msgs.append(f"{field_name} list cannot contain duplicate credentials.")
+ if error_msgs:
+ errors["DepositPreauth"] = " ".join(error_msgs)
📝 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.
def _validate_credentials_length( | |
credentials: List[Credential], field_name: str | |
) -> None: | |
if len(credentials) == 0: | |
errors["DepositPreauth"] = f"{field_name} list cannot be empty. " | |
elif len(credentials) > 8: | |
errors["DepositPreauth"] = ( | |
f"{field_name} list cannot have more than 8 elements. " | |
) | |
if len(credentials) != len(set(credentials)): | |
errors["DepositPreauth"] = ( | |
f"{field_name} list cannot contain duplicate credentials." | |
) | |
def _validate_credentials_length( | |
credentials: List[Credential], field_name: str | |
) -> None: | |
error_msgs = [] | |
if len(credentials) == 0: | |
error_msgs.append(f"{field_name} list cannot be empty.") | |
elif len(credentials) > 8: | |
error_msgs.append(f"{field_name} list cannot have more than 8 elements.") | |
if len(credentials) != len(set(credentials)): | |
error_msgs.append(f"{field_name} list cannot contain duplicate credentials.") | |
if error_msgs: | |
errors["DepositPreauth"] = " ".join(error_msgs) |
account_objects_response = await client.request( | ||
AccountObjects(account=_ISSUER, type=AccountObjectType.CREDENTIAL) | ||
) | ||
self.assertFalse( | ||
is_cred_object_present( | ||
account_objects_response.result, | ||
issuer=_ISSUER, | ||
subject=_SUBJECT, | ||
cred_type=cred_type, | ||
) | ||
) | ||
|
||
# Verify that the Credential object has been deleted from the Subject's | ||
# directory page as well | ||
account_objects_response = await client.request( | ||
AccountObjects(account=_SUBJECT, type=AccountObjectType.CREDENTIAL) | ||
) | ||
self.assertFalse( | ||
is_cred_object_present( | ||
account_objects_response.result, | ||
issuer=_ISSUER, | ||
subject=_SUBJECT, | ||
cred_type=cred_type, | ||
) | ||
) |
There was a problem hiding this comment.
Choose a reason for hiding this comment
The reason will be displayed to describe this comment to others. Learn more.
Avoid direct ledger queries using AccountObjects
in tests
Directly querying ledger data with AccountObjects
RPC calls tests rippled
internals rather than the library. Simplify the test by relying on transaction responses (tesSUCCESS
) to confirm the deletion of credential objects.
# Use the LedgerEntry RPC to validate the creation of the credential object | ||
ledger_entry_response = await client.request( | ||
LedgerEntry( | ||
credential=Credential( | ||
subject=_SUBJECT, issuer=_ISSUER, credential_type=cred_type | ||
) | ||
) | ||
) | ||
|
||
self.assertEqual(ledger_entry_response.status, ResponseStatus.SUCCESS) | ||
|
There was a problem hiding this comment.
Choose a reason for hiding this comment
The reason will be displayed to describe this comment to others. Learn more.
Remove direct LedgerEntry
RPC call in integration test
Integration tests should focus on testing xrpl-py
library functionalities rather than underlying rippled
behaviors. Remove the direct LedgerEntry
RPC call used to validate the creation of the credential object to align with testing guidelines.
This PR should be based on top of the #759 branch, so it's easier to review. |
@mvadari Do you mean the target branch of the current PR should be |
yes. Otherwise, the diff of this PR contains both. |
Okay, I have changed the base to the Github doesn't allow me to change the base-repository, I had to resort to this idea. |
If this is too messy, I can close this PR and re-open a new one |
Hello, I'm going on a vacation next week. If possible, I'd appreciate if I can get a review this week. |
This PR is very unlikely to be merged before then, as rippled code is unlikely to be merged by then and this PR can't be merged until the rippled PR is merged. |
Co-authored-by: Mayukha Vadari <mvadari@gmail.com>
|
||
### BREAKING CHANGE: | ||
- Remove Python 3.7 support to fix dependency installation and use 3.8 as new default. | ||
- Remove the AccountObjectType enum. Instead, use the LedgerEntryType enum, this reduces redundancy in the codebase. |
There was a problem hiding this comment.
Choose a reason for hiding this comment
The reason will be displayed to describe this comment to others. Learn more.
Not all valid LedgerEntryType
s are valid AccountObjectType
s.
There was a problem hiding this comment.
Choose a reason for hiding this comment
The reason will be displayed to describe this comment to others. Learn more.
This is also a breaking change and shouldn't be done in a random update.
There was a problem hiding this comment.
Choose a reason for hiding this comment
The reason will be displayed to describe this comment to others. Learn more.
Not to mention, it's also confusing.
There was a problem hiding this comment.
Choose a reason for hiding this comment
The reason will be displayed to describe this comment to others. Learn more.
the xrpl.js library does not have separate filters for LedgerEntryType and AccountObjectType
There was a problem hiding this comment.
Choose a reason for hiding this comment
The reason will be displayed to describe this comment to others. Learn more.
I think its a good opportunity to refactor and clean up the code. Its slow to wait for approvals of multiple small PRs
There was a problem hiding this comment.
Choose a reason for hiding this comment
The reason will be displayed to describe this comment to others. Learn more.
the xrpl.js library does not have separate filters for LedgerEntryType and AccountObjectType
It may depend on the LedgerEntryType
equivalent, but it's still separate.
There was a problem hiding this comment.
Choose a reason for hiding this comment
The reason will be displayed to describe this comment to others. Learn more.
I agree that some ledger-entries are excluded from AccountObjectType. In fact, the xrpl.js implementation is faulty. rippled
does not allow five ledger_entry_type
's in the account_objects
RPC: https://github.com/XRPLF/rippled/blob/0ec17b6026298dc150099b66a2cecad0fe561d1b/src/xrpld/rpc/detail/RPCHelpers.cpp#L994
I didn't narrow the type because rippled
will raise an error if incompatible types are used in the filter.
Having said that, I still believe its useful to unify the AccountObjectType
and LedgerEntryType
in xrpl-py codebase.
There was a problem hiding this comment.
Choose a reason for hiding this comment
The reason will be displayed to describe this comment to others. Learn more.
If you feel strongly that this refactor shouldn't be mixed in with PD amendment, I can roll the commit back
@@ -95,6 +98,26 @@ async def _set_up_reusable_values(): | |||
amm_asset2 = setup_amm_pool_res["asset2"] | |||
amm_issuer_wallet = setup_amm_pool_res["issuer_wallet"] | |||
|
|||
# Create and accept one credential; This is used in the PermissionedDomain tests |
There was a problem hiding this comment.
Choose a reason for hiding this comment
The reason will be displayed to describe this comment to others. Learn more.
This is not necessary. You can create a Permissioned Domain without any credentials existing for it.
There was a problem hiding this comment.
Choose a reason for hiding this comment
The reason will be displayed to describe this comment to others. Learn more.
that is true, but I'd like to test for a tesSUCCESS
code at the end. If the credential-object doesn't exist, I wasn't sure if rippled throws an error.
Besides, this displays the general workflow with PD
There was a problem hiding this comment.
Choose a reason for hiding this comment
The reason will be displayed to describe this comment to others. Learn more.
The credential object does not need to exist. In fact, there's no way for rippled to check for it, since the subject could be anybody.
There was a problem hiding this comment.
Choose a reason for hiding this comment
The reason will be displayed to describe this comment to others. Learn more.
Nonetheless, a re-usable credential in the integration test cases would be useful for upcoming amendments. I prefer to retain this piece of code.
High Level Overview of Change
This PR implements the PermissionedDomains amendment in the xrpl-py library.
Specification: XRPLF/XRPL-Standards#228
C++ Implementation: XRPLF/rippled#5161
#759 is a prerequisite for this PR.
For the readers who are only interested in the
PermissionedDomain
changes only, (but not theVerifiableCredentials
changes) please read from this commit onwards: 8abf7b7Context of Change
Type of Change
Did you update CHANGELOG.md?
Test Plan
I've included Unit and integration tests for the newly added transactions. No new unit tests have been attributed to the
PermissionedDomainDelete
transaction. Thedomain_id
field must be retrieved from one of the rippled RPCs which conforms to the HASH256 internal type.