mirror of
https://github.com/XRPLF/xrpl-dev-portal.git
synced 2025-11-20 19:55:54 +00:00
Binary serialization: implement MPT amounts in sample code
This commit is contained in:
@@ -133,12 +133,13 @@ def accountid_to_bytes(address):
|
||||
|
||||
def amount_to_bytes(a):
|
||||
"""
|
||||
Serializes an "Amount" type, which can be either XRP or an issued currency:
|
||||
Serializes an "Amount" type, which can be XRP, an issued currency, or MPT:
|
||||
- XRP: total 64 bits: 0, followed by 1 ("is positive"), then 0, then 61 bit UInt amount
|
||||
- Issued Currency: total 384 bits: 64 bits of amount, followed by 160 bit currency code and
|
||||
160 bit issuer AccountID.
|
||||
- MPT: 8-bit header with the binary value 01100000 (0x60), then 64 bit UInt amount,
|
||||
32 bit Sequence number, and 160 bit issuer AccountID.
|
||||
- Issued Currency: total 384 bits: 64 bits of amount, followed by 160 bit
|
||||
currency code and 160 bit issuer AccountID.
|
||||
- MPT: total 264 bits: 8-bit header with the binary value 01100000 (0x60),
|
||||
then 64 bit amount, 32 bit Sequence number, and 160 bit issuer AccountID.
|
||||
The Sequence and issuer are adjoined as mpt_issuance_id.
|
||||
"""
|
||||
if type(a) == str:
|
||||
# is XRP
|
||||
@@ -153,17 +154,26 @@ def amount_to_bytes(a):
|
||||
xrp_amt = -xrp_amt
|
||||
return xrp_amt.to_bytes(8, byteorder="big", signed=False)
|
||||
elif type(a) == dict:
|
||||
#TODO: handle mpt amounts
|
||||
if sorted(a.keys()) != ["currency", "issuer", "value"]:
|
||||
if sorted(a.keys()) == ["mpt_issuance_id", "value"]:
|
||||
# MPT Amount
|
||||
mpt_prefix = uint8_to_bytes(0x60)
|
||||
mpt_amt = int(a["value"])
|
||||
assert mpt_amt < 2**63 and mpt_amt >= 0
|
||||
mpt_amt_bytes = mpt_amt.to_bytes(8, byteorder="big", signed=False)
|
||||
mpt_issuance_id = uint192_to_bytes(a["mpt_issuance_id"])
|
||||
return mpt_prefix + mpt_amt_bytes + mpt_issuance_id
|
||||
|
||||
elif sorted(a.keys()) != ["currency", "issuer", "value"]:
|
||||
raise ValueError("amount must have currency, value, issuer only (actually had: %s)" %
|
||||
sorted(a.keys()))
|
||||
|
||||
# Fungible token amount (non-MPT)
|
||||
issued_amt = IssuedAmount(a["value"]).to_bytes()
|
||||
logger.debug("Issued amount: %s"%issued_amt.hex())
|
||||
currency_code = currency_code_to_bytes(a["currency"])
|
||||
return issued_amt + currency_code + decode_address(a["issuer"])
|
||||
else:
|
||||
raise ValueError("amount must be XRP string or {currency, value, issuer}")
|
||||
raise ValueError("amount must be XRP string, {currency, value, issuer}, or {mpt_issuance_id, value}")
|
||||
|
||||
def array_to_bytes(array):
|
||||
"""
|
||||
@@ -389,6 +399,12 @@ def uint64_to_bytes(i):
|
||||
raise ValueError("UInt64 is not 64 bits long")
|
||||
return b
|
||||
|
||||
def uint192_to_bytes(i):
|
||||
b = hex_to_bytes(i)
|
||||
if len(b) != 24: # 24 bytes = 192 bits
|
||||
raise ValueError("UInt192 is not 192 bits long")
|
||||
return b
|
||||
|
||||
def uint384_to_bytes(i):
|
||||
b = hex_to_bytes(i)
|
||||
if len(b) != 8: # 8 bytes = 64 bits
|
||||
@@ -440,6 +456,7 @@ def field_to_bytes(field_name, field_val):
|
||||
"UInt16": uint16_to_bytes,
|
||||
"UInt32": uint32_to_bytes,
|
||||
"UInt64": uint64_to_bytes,
|
||||
"UInt192": uint192_to_bytes,
|
||||
"UInt384": uint384_to_bytes,
|
||||
"Vector256": vector256_to_bytes,
|
||||
}
|
||||
|
||||
@@ -244,8 +244,8 @@ The _Amount_ type (also called "STAmount") is a special field type that represen
|
||||
|
||||
Multi-Purpose Tokens (MPTs) consist of four segments in order:
|
||||
|
||||
1. 8 bits indicating that this is an MPT. The most significant bit is `0` to indicate that it's not a fungible token. The second bit is `1` to indicate that it is postiive. The third most significant bit is `1` to indicate that it is an MPT. The remaining 5 bits are reserved and must all be `0`.
|
||||
2. 64 bits indicating the quantity of the MPT, as a 64-bit _signed_ integer. (However, in most contexts, negative amounts are not allowed.)
|
||||
1. 8 bits indicating that this is an MPT. The most significant bit is `0` to indicate that it's not a fungible token. The second bit is `1` to indicate that it is postiive. The third most significant bit is `1` to indicate that it is an MPT. The remaining 5 bits are reserved and must all be `0`. In other words, the first byte is `0x60`.
|
||||
2. 64 bits indicating the quantity of the MPT, as a 64-bit unsigned integer. (However, the maximum amount cannot be larger than 2<sup>63</sup>-1.)
|
||||
3. 32 bits indicating the `Sequence` number of the transaction that created the MPT issuance.
|
||||
4. 160 bits indicating the [AccountID][] of the MPT's issuer.
|
||||
|
||||
|
||||
Reference in New Issue
Block a user