mirror of
https://github.com/XRPLF/xrpl-dev-portal.git
synced 2025-12-06 17:27:57 +00:00
Serialization: objects, arrays, hashes
This commit is contained in:
@@ -39,6 +39,11 @@ def field_sort_key(field_name):
|
||||
return (DEFINITIONS["TYPES"][field_type_name], DEFINITIONS["FIELDS"][field_name]["nth"])
|
||||
|
||||
def field_id(field_name):
|
||||
"""
|
||||
Returns the unique field ID for a given field name.
|
||||
This field ID consists of the type code and field code, in 1 to 3 bytes
|
||||
depending on whether those values are "common" (<16) or uncommon (>=16)
|
||||
"""
|
||||
field_type_name = DEFINITIONS["FIELDS"][field_name]["type"]
|
||||
type_code = DEFINITIONS["TYPES"][field_type_name]
|
||||
field_code = DEFINITIONS["FIELDS"][field_name]["nth"]
|
||||
@@ -145,10 +150,59 @@ def vl_to_bytes(field_val):
|
||||
vl_contents = bytes.fromhex(field_val)
|
||||
return vl_encode(vl_contents)
|
||||
|
||||
def hash_to_bytes(contents):
|
||||
return bytes.fromhex(field_val)
|
||||
|
||||
def accountid_to_bytes(address):
|
||||
return vl_encode(decode_address(address))
|
||||
|
||||
def array_to_bytes(array):
|
||||
"""
|
||||
Serialize an array of objects.
|
||||
Each member object must have a type wrapper and an inner object.
|
||||
"""
|
||||
members_as_bytes = []
|
||||
for el in array:
|
||||
wrapper_key = list(el.keys())[0]
|
||||
inner_obj = el[wrapper_key]
|
||||
members_as_bytes.append(field_to_bytes(field_name=wrapper_key, field_val=el))
|
||||
members_as_bytes.append(field_id("ArrayEndMarker"))
|
||||
return b''.join(members_as_bytes)
|
||||
|
||||
def object_to_bytes(obj):
|
||||
"""
|
||||
Serialize an object, assuming a type wrapper, for example:
|
||||
|
||||
{
|
||||
"SignerEntry": {
|
||||
"Account": "rUpy3eEg8rqjqfUoLeBnZkscbKbFsKXC3v",
|
||||
"SignerWeight": 1
|
||||
}
|
||||
}
|
||||
|
||||
Puts the child fields (e.g. Account, SignerWeight) in canonical order
|
||||
and appends an object end marker.
|
||||
"""
|
||||
wrapper_key = list(obj.keys())[0]
|
||||
inner_obj = obj[wrapper_key]
|
||||
child_order = sorted(inner_obj.keys(), key=field_sort_key)
|
||||
fields_as_bytes = []
|
||||
for field_name in child_order:
|
||||
if (DEFINITIONS["FIELDS"][field_name]["isSerialized"]):
|
||||
field_val = inner_obj[field_name]
|
||||
field_bytes = field_to_bytes(field_name, field_val)
|
||||
logger.debug("{n}: {h}".format(n=field_name, h=field_bytes.hex()))
|
||||
fields_as_bytes.append(field_bytes)
|
||||
|
||||
fields_as_bytes.append(field_id("ObjectEndMarker"))
|
||||
return b''.join(fields_as_bytes)
|
||||
|
||||
|
||||
def field_to_bytes(field_name, field_val):
|
||||
"""
|
||||
Returns a bytes object containing the serialized version of a field
|
||||
including its field ID prefix.
|
||||
"""
|
||||
field_type = DEFINITIONS["FIELDS"][field_name]["type"]
|
||||
logger.debug("Serializing field {f} of type {t}".format(f=field_name, t=field_type))
|
||||
|
||||
@@ -161,13 +215,19 @@ def field_to_bytes(field_name, field_val):
|
||||
|
||||
dispatch = {
|
||||
# TypeName: function(field): bytes object
|
||||
"UInt64": lambda x:bytes_from_uint(x, 64),
|
||||
"UInt32": lambda x:bytes_from_uint(x, 32),
|
||||
"UInt16": lambda x:bytes_from_uint(x, 16),
|
||||
"UInt8" : lambda x:bytes_from_uint(x, 8),
|
||||
"AccountID": accountid_to_bytes,
|
||||
"Amount": amount_to_bytes,
|
||||
"Blob": vl_to_bytes
|
||||
"Blob": vl_to_bytes,
|
||||
"Hash128": hash_to_bytes,
|
||||
"Hash160": hash_to_bytes,
|
||||
"Hash256": hash_to_bytes,
|
||||
# TODO: PathSet
|
||||
"STArray": array_to_bytes,
|
||||
"STObject": object_to_bytes,
|
||||
"UInt8" : lambda x:bytes_from_uint(x, 8),
|
||||
"UInt16": lambda x:bytes_from_uint(x, 16),
|
||||
"UInt32": lambda x:bytes_from_uint(x, 32),
|
||||
"UInt64": lambda x:bytes_from_uint(x, 64),
|
||||
}
|
||||
field_binary = dispatch[field_type](field_val)
|
||||
return b''.join( (id_prefix, field_binary) )
|
||||
@@ -210,7 +270,7 @@ if __name__ == "__main__":
|
||||
# "Sequence": 2
|
||||
# }
|
||||
|
||||
with open("test-cases/tx1-nometa.json") as f:
|
||||
with open("test-cases/tx2-nometa.json") as f:
|
||||
example_tx = json.load(f)
|
||||
|
||||
serialize_tx(example_tx)
|
||||
|
||||
@@ -0,0 +1 @@
|
||||
1200022280000000240000000120190000000B68400000000000277573210268D79CD579D077750740FA18A2370B7C2018B2714ECE70BA65C38D223E79BC9C74473045022100F06FB54049D6D50142E5CF2E2AC21946AF305A13E2A2D4BA881B36484DD01A540220311557EC8BEF536D729605A4CB4D4DC51B1E37C06C93434DD5B7651E1E2E28BF811452C7F01AD13B3CA9C1D133FA8F3482D2EF08FA7D82145A380FBD236B6A1CD14B939AD21101E5B6B6FFA2F9EA7D0F04C4D46544659A2D58525043686174E1F1
|
||||
@@ -0,0 +1,94 @@
|
||||
{
|
||||
"hash": "C0B450C8601E19CB0BDED71C4B523B2A4AAB77415B08E7923D8DA3F831631702",
|
||||
"ledger_index": 36259236,
|
||||
"date": "2018-02-01T09:45:32+00:00",
|
||||
"tx": {
|
||||
"TransactionType": "EscrowFinish",
|
||||
"Flags": 2147483648,
|
||||
"Sequence": 1,
|
||||
"OfferSequence": 11,
|
||||
"Fee": "10101",
|
||||
"SigningPubKey": "0268D79CD579D077750740FA18A2370B7C2018B2714ECE70BA65C38D223E79BC9C",
|
||||
"TxnSignature": "3045022100F06FB54049D6D50142E5CF2E2AC21946AF305A13E2A2D4BA881B36484DD01A540220311557EC8BEF536D729605A4CB4D4DC51B1E37C06C93434DD5B7651E1E2E28BF",
|
||||
"Account": "r3Y6vCE8XqfZmYBRngy22uFYkmz3y9eCRA",
|
||||
"Owner": "r9NpyVfLfUG8hatuCCHKzosyDtKnBdsEN3",
|
||||
"Memos": [
|
||||
{
|
||||
"Memo": {
|
||||
"MemoData": "04C4D46544659A2D58525043686174"
|
||||
}
|
||||
}
|
||||
]
|
||||
},
|
||||
"meta": {
|
||||
"TransactionIndex": 35,
|
||||
"AffectedNodes": [
|
||||
{
|
||||
"DeletedNode": {
|
||||
"LedgerEntryType": "Escrow",
|
||||
"LedgerIndex": "983EBDF89C1C30CECDB105B593E7DEBE602AF89012EDB4DD76D24ACEF92C89EF",
|
||||
"FinalFields": {
|
||||
"Flags": 0,
|
||||
"PreviousTxnLgrSeq": 35059511,
|
||||
"FinishAfter": 570758400,
|
||||
"OwnerNode": "0000000000000000",
|
||||
"PreviousTxnID": "6F54E04D7B205CBE2FCAEF1C249E62A9759721C7FE1F6992FD800266C8E4814C",
|
||||
"Amount": "1000000000000000",
|
||||
"Account": "r9NpyVfLfUG8hatuCCHKzosyDtKnBdsEN3",
|
||||
"Destination": "r9NpyVfLfUG8hatuCCHKzosyDtKnBdsEN3"
|
||||
}
|
||||
}
|
||||
},
|
||||
{
|
||||
"ModifiedNode": {
|
||||
"LedgerEntryType": "DirectoryNode",
|
||||
"LedgerIndex": "C05DC35EBDCA5D8697190FF41950EC5AFCBF7F61C1177DC73000CC17C2149886",
|
||||
"FinalFields": {
|
||||
"Flags": 0,
|
||||
"RootIndex": "C05DC35EBDCA5D8697190FF41950EC5AFCBF7F61C1177DC73000CC17C2149886",
|
||||
"Owner": "r9NpyVfLfUG8hatuCCHKzosyDtKnBdsEN3"
|
||||
}
|
||||
}
|
||||
},
|
||||
{
|
||||
"ModifiedNode": {
|
||||
"LedgerEntryType": "AccountRoot",
|
||||
"PreviousTxnLgrSeq": 36230933,
|
||||
"PreviousTxnID": "9366F75CD350ACE0EEFC0A392ECBD5AC2B84C06E5DEC2DE895B76FFC7BD55553",
|
||||
"LedgerIndex": "C180CA555CE8820D8F1086CDCA756FF8D5813FEB2AE3FF002B9F48F870CA08A0",
|
||||
"PreviousFields": {
|
||||
"Sequence": 1,
|
||||
"Balance": "26000000"
|
||||
},
|
||||
"FinalFields": {
|
||||
"Flags": 0,
|
||||
"Sequence": 2,
|
||||
"OwnerCount": 0,
|
||||
"Balance": "25989899",
|
||||
"Account": "r3Y6vCE8XqfZmYBRngy22uFYkmz3y9eCRA"
|
||||
}
|
||||
}
|
||||
},
|
||||
{
|
||||
"ModifiedNode": {
|
||||
"LedgerEntryType": "AccountRoot",
|
||||
"PreviousTxnLgrSeq": 36253527,
|
||||
"PreviousTxnID": "F2AA5584005847C19F59A9C87E7BF3108F97F2567C5083159EEC40B08ED90F46",
|
||||
"LedgerIndex": "DCED5AAFE87AA8D00E651DBBFBA2F992927BC3DC5FFD905EF49019ED02824B3A",
|
||||
"PreviousFields": {
|
||||
"OwnerCount": 14,
|
||||
"Balance": "200923000"
|
||||
},
|
||||
"FinalFields": {
|
||||
"Flags": 1048576,
|
||||
"Sequence": 18,
|
||||
"OwnerCount": 13,
|
||||
"Balance": "1000000200923000",
|
||||
"Account": "r9NpyVfLfUG8hatuCCHKzosyDtKnBdsEN3"
|
||||
}
|
||||
}
|
||||
}
|
||||
],
|
||||
"TransactionResult": "tesSUCCESS"
|
||||
}
|
||||
}
|
||||
@@ -0,0 +1,18 @@
|
||||
{
|
||||
"TransactionType": "EscrowFinish",
|
||||
"Flags": 2147483648,
|
||||
"Sequence": 1,
|
||||
"OfferSequence": 11,
|
||||
"Fee": "10101",
|
||||
"SigningPubKey": "0268D79CD579D077750740FA18A2370B7C2018B2714ECE70BA65C38D223E79BC9C",
|
||||
"TxnSignature": "3045022100F06FB54049D6D50142E5CF2E2AC21946AF305A13E2A2D4BA881B36484DD01A540220311557EC8BEF536D729605A4CB4D4DC51B1E37C06C93434DD5B7651E1E2E28BF",
|
||||
"Account": "r3Y6vCE8XqfZmYBRngy22uFYkmz3y9eCRA",
|
||||
"Owner": "r9NpyVfLfUG8hatuCCHKzosyDtKnBdsEN3",
|
||||
"Memos": [
|
||||
{
|
||||
"Memo": {
|
||||
"MemoData": "04C4D46544659A2D58525043686174"
|
||||
}
|
||||
}
|
||||
]
|
||||
}
|
||||
Reference in New Issue
Block a user