-
Notifications
You must be signed in to change notification settings - Fork 102
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
[Fix #354] Introduce decode_ledger_data utility method #785
base: main
Are you sure you want to change the base?
Changes from all commits
File filter
Filter by extension
Conversations
Jump to
Diff view
Diff view
There are no files selected for viewing
Original file line number | Diff line number | Diff line change | ||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||
---|---|---|---|---|---|---|---|---|---|---|---|---|---|---|---|---|---|---|---|---|---|---|---|---|---|---|---|---|---|---|---|---|---|---|---|---|---|---|---|---|---|---|---|---|---|---|---|---|---|---|---|---|---|---|---|---|---|---|---|---|---|---|---|---|---|---|---|---|---|---|---|---|---|---|---|---|
|
@@ -2,6 +2,7 @@ | |||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||
|
||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||
import xrpl.core.binarycodec.field_id_codec as field_id_codec | ||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||
from tests.unit.core.binarycodec.fixtures import data_driven_fixtures | ||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||
from xrpl.core.binarycodec.field_id_codec import decode_ledger_header | ||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||
There was a problem hiding this comment. Choose a reason for hiding this commentThe reason will be displayed to describe this comment to others. Learn more. 🛠️ Refactor suggestion Add missing import for exception handling. For the new test cases, we need to import XRPLBinaryCodecException. Add this import: from unittest import TestCase
import xrpl.core.binarycodec.field_id_codec as field_id_codec
+from xrpl.core.binarycodec.exceptions import XRPLBinaryCodecException
from tests.unit.core.binarycodec.fixtures import data_driven_fixtures
from xrpl.core.binarycodec.field_id_codec import decode_ledger_header 📝 Committable suggestion
Suggested change
|
||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||
|
||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||
|
||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||
class TestFieldIDCodec(TestCase): | ||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||
|
@@ -21,3 +22,11 @@ def test_encode(self): | |||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||
def test_decode(self): | ||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||
for test in self.field_tests: | ||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||
self.assertEqual(test.name, field_id_codec.decode(test.expected_hex)) | ||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||
|
||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||
|
||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||
class TestDecodeLedgerHeader(TestCase): | ||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||
def test_decode_ledger_header_valid(self): | ||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||
for test in data_driven_fixtures.get_ledger_data_codec_test(): | ||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||
self.assertEqual( | ||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||
test["json"], decode_ledger_header(test["serialized_data"]) | ||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||
) | ||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||
Comment on lines
+27
to
+32
There was a problem hiding this comment. Choose a reason for hiding this commentThe reason will be displayed to describe this comment to others. Learn more. 🛠️ Refactor suggestion Enhance test coverage with additional test cases. The current test implementation only covers the happy path. Consider adding tests for:
Add these test methods to improve coverage: class TestDecodeLedgerHeader(TestCase):
def test_decode_ledger_header_valid(self):
for test in data_driven_fixtures.get_ledger_data_codec_test():
self.assertEqual(
test["json"], decode_ledger_header(test["serialized_data"])
)
+
+ def test_decode_ledger_header_invalid_input(self):
+ """Test that invalid inputs raise appropriate exceptions."""
+ invalid_inputs = [
+ None,
+ 123,
+ "",
+ "invalid hex",
+ "0x1234", # incomplete data
+ ]
+ for invalid_input in invalid_inputs:
+ with self.assertRaises(XRPLBinaryCodecException):
+ decode_ledger_header(invalid_input)
+
+ def test_decode_ledger_header_field_validation(self):
+ """Test specific field values and types."""
+ test_data = data_driven_fixtures.get_ledger_data_codec_test()[0]
+ result = decode_ledger_header(test_data["serialized_data"])
+
+ # Validate field types
+ self.assertIsInstance(result["ledger_index"], int)
+ self.assertIsInstance(result["total_coins"], str)
+ self.assertIsInstance(result["parent_hash"], str)
+ self.assertTrue(result["parent_hash"].isalnum())
+ self.assertEqual(len(result["parent_hash"]), 64) # 32 bytes in hex 📝 Committable suggestion
Suggested change
|
Original file line number | Diff line number | Diff line change | ||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||
---|---|---|---|---|---|---|---|---|---|---|---|---|---|---|---|---|---|---|---|---|---|---|---|---|---|---|---|---|---|---|---|---|---|---|---|---|---|---|---|---|---|---|---|---|---|---|---|---|---|---|---|---|---|---|---|---|---|---|---|---|---|---|---|---|---|---|---|---|---|---|---|---|---|---|---|---|---|---|---|---|---|---|---|---|---|---|---|---|---|---|---|---|---|---|---|---|---|---|---|---|---|---|---|---|---|---|---|---|---|---|---|---|---|---|---|---|---|---|---|---|---|---|---|---|---|---|---|---|---|---|
|
@@ -3,9 +3,44 @@ | |||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||
`Field IDs <https://xrpl.org/serialization.html#field-ids>`_ | ||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||
""" | ||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||
|
||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||
from typing import Any, Dict | ||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||
|
||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||
from xrpl.core.binarycodec.binary_wrappers import BinaryParser | ||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||
from xrpl.core.binarycodec.definitions import definitions | ||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||
from xrpl.core.binarycodec.definitions.field_header import FieldHeader | ||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||
from xrpl.core.binarycodec.exceptions import XRPLBinaryCodecException | ||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||
from xrpl.core.binarycodec.types.hash256 import Hash256 | ||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||
from xrpl.core.binarycodec.types.uint64 import UInt64 | ||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||
|
||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||
|
||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||
def decode_ledger_header(serialized_str: str) -> Dict[str, Any]: | ||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||
""" | ||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||
Decodes a serialized ledger header. | ||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||
Note: The file located at xrpl/core/binarycodec/definitions/definitions.json file | ||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||
is used to parse the serialized data. If developers need custom definitions, | ||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||
please update that file. | ||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||
|
||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||
Args: | ||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||
serialized_str: A serialized ledger header, represented as a hexa-decimal string | ||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||
|
||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||
Returns: | ||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||
A Dict object describing a ledger header | ||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||
""" | ||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||
parser = BinaryParser(serialized_str) | ||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||
|
||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||
return { | ||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||
"ledger_index": parser.read_uint32(), | ||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||
# Uint64 types are represented as hex-strings for preserving precision | ||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||
# For ease of use, explicitly type-cast this value into base-10 | ||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||
"total_coins": str(int(parser.read_type(UInt64).to_hex(), base=16)), | ||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||
"parent_hash": parser.read_type(Hash256).to_hex(), | ||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||
"transaction_hash": parser.read_type(Hash256).to_hex(), | ||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||
"account_hash": parser.read_type(Hash256).to_hex(), | ||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||
"parent_close_time": parser.read_uint32(), | ||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||
"close_time": parser.read_uint32(), | ||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||
"close_time_resolution": parser.read_uint8(), | ||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||
"close_flags": parser.read_uint8(), | ||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||
} | ||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||
Comment on lines
+16
to
+43
There was a problem hiding this comment. Choose a reason for hiding this commentThe reason will be displayed to describe this comment to others. Learn more. 🛠️ Refactor suggestion Consider adding error handling for malformed input. The implementation looks solid and handles uint64 precision correctly. However, it should handle potential errors from malformed input. Consider wrapping the parsing in a try-except block: def decode_ledger_header(serialized_str: str) -> Dict[str, Any]:
"""
Decodes a serialized ledger header.
Note: The file located at xrpl/core/binarycodec/definitions/definitions.json file
is used to parse the serialized data. If developers need custom definitions,
please update that file.
Args:
serialized_str: A serialized ledger header, represented as a hexa-decimal string
Returns:
A Dict object describing a ledger header
+
+ Raises:
+ XRPLBinaryCodecException: If the input string is malformed or incomplete
"""
+ if not isinstance(serialized_str, str):
+ raise XRPLBinaryCodecException("serialized_str must be a string")
+
parser = BinaryParser(serialized_str)
+ try:
return {
"ledger_index": parser.read_uint32(),
# Uint64 types are represented as hex-strings for preserving precision
# For ease of use, explicitly type-cast this value into base-10
"total_coins": str(int(parser.read_type(UInt64).to_hex(), base=16)),
"parent_hash": parser.read_type(Hash256).to_hex(),
"transaction_hash": parser.read_type(Hash256).to_hex(),
"account_hash": parser.read_type(Hash256).to_hex(),
"parent_close_time": parser.read_uint32(),
"close_time": parser.read_uint32(),
"close_time_resolution": parser.read_uint8(),
"close_flags": parser.read_uint8(),
}
+ except Exception as e:
+ raise XRPLBinaryCodecException(f"Failed to decode ledger header: {str(e)}") 📝 Committable suggestion
Suggested change
|
||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||
|
||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||
|
||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||
def encode(field_name: str) -> bytes: | ||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||
|
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
Align implementation with existing fixture loading pattern.
The current implementation has several issues that should be addressed:
Consider refactoring to match the existing pattern: