diff --git a/content/_img-sources/serialization-amount.uxf b/content/_img-sources/serialization-amount.uxf new file mode 100644 index 0000000000..a8818ce839 --- /dev/null +++ b/content/_img-sources/serialization-amount.uxf @@ -0,0 +1,341 @@ + + + 10 + + UMLPackage + + 30 + 240 + 850 + 70 + + Issued Currency Amount Format + + + + UMLClass + + 40 + 270 + 20 + 30 + + 1 + + + + UMLClass + + 70 + 270 + 20 + 30 + + + + + + UMLClass + + 100 + 270 + 150 + 30 + + exponent (8 bits) + + + + UMLClass + + 260 + 270 + 190 + 30 + + mantissa (54 bits) + + + + Relation + + 70 + 290 + 50 + 60 + + lt=<<- + 10.0;10.0;10.0;40.0;30.0;40.0 + + + Text + + 100 + 320 + 260 + 30 + + Sign bit (0=negative, 1=positive) +style=wordwrap + + + + Text + + 80 + 350 + 160 + 60 + + "Not XRP" bit +(0=XRP, 1=not XRP) +style=wordwrap + + + + Relation + + 40 + 290 + 50 + 90 + + lt=<<- + 10.0;10.0;10.0;70.0;30.0;70.0 + + + UMLClass + + 460 + 270 + 200 + 30 + + currency code (160 bits) + + + + UMLClass + + 670 + 270 + 200 + 30 + + issuer AccountID (160 bits) + + + + UMLClass + + 40 + 510 + 20 + 30 + + 00 + + + + Relation + + 40 + 520 + 60 + 70 + + lt=<<- + 10.0;10.0;10.0;50.0;40.0;50.0 + + + Text + + 80 + 560 + 300 + 40 + + Type code (8 bits) +0x00 for ISO 4217/pseudo-ISO currency + + + + UMLClass + + 70 + 510 + 220 + 30 + + Reserved (88 bits) + + + + UMLClass + + 460 + 510 + 180 + 30 + + Reserved (40 bits) + + + + UMLClass + + 300 + 510 + 150 + 30 + + ISO code (24 bits) + + + + UMLPackage + + 30 + 480 + 620 + 70 + + Issued Currency Code Format + + + + Relation + + 310 + 530 + 40 + 50 + + lt=<<- + 10.0;10.0;10.0;30.0;20.0;30.0 + + + Text + + 330 + 550 + 130 + 30 + + 3 chars of ASCII + + + + Relation + + 20 + 290 + 460 + 210 + + lt=.. + 10.0;190.0;440.0;10.0 + + + Relation + + 640 + 290 + 40 + 230 + + lt=.. + 10.0;210.0;20.0;10.0 + + + UMLPackage + + 30 + 30 + 620 + 70 + + XRP Amount Format + + + + UMLClass + + 40 + 60 + 20 + 30 + + 0 + + + + UMLClass + + 70 + 60 + 20 + 30 + + 1 + + + + Text + + 100 + 110 + 260 + 30 + + Sign bit (always 1 for positive) +style=wordwrap + + + + Relation + + 70 + 80 + 50 + 60 + + lt=<<- + 10.0;10.0;10.0;40.0;30.0;40.0 + + + Text + + 80 + 140 + 160 + 60 + + "Not XRP" bit +(0=XRP, 1=not XRP) +style=wordwrap + + + + Relation + + 40 + 80 + 50 + 90 + + lt=<<- + 10.0;10.0;10.0;70.0;30.0;70.0 + + + UMLClass + + 100 + 60 + 540 + 30 + + integer drops (62 bits) + + + diff --git a/content/_img-sources/serialization-array.uxf b/content/_img-sources/serialization-array.uxf index 92f81f9e78..f5b443c100 100644 --- a/content/_img-sources/serialization-array.uxf +++ b/content/_img-sources/serialization-array.uxf @@ -1,17 +1,6 @@ 10 - - UMLClass - - 130 - 110 - 600 - 50 - - - - UMLClass @@ -148,4 +137,15 @@ Field ID (SignerEntry Contents) + + UMLPackage + + 130 + 90 + 600 + 70 + + SignerEntries field + + diff --git a/content/_img-sources/serialization-object.uxf b/content/_img-sources/serialization-object.uxf index 4924e729c6..37ee31ac98 100644 --- a/content/_img-sources/serialization-object.uxf +++ b/content/_img-sources/serialization-object.uxf @@ -1,17 +1,6 @@ 10 - - UMLClass - - 80 - 160 - 600 - 50 - - - - UMLClass @@ -73,17 +62,17 @@ Field ID 630 190 - 30 - 80 + 80 + 60 lt=<<- - 10.0;10.0;10.0;60.0 + 10.0;10.0;10.0;30.0;60.0;30.0;60.0;40.0 Text - 590 - 250 + 640 + 230 100 60 @@ -109,22 +98,10 @@ no contents 160 190 50 - 80 + 60 lt=<<- - 10.0;10.0;10.0;60.0;30.0;60.0 - - - Text - - 220 - 120 - 190 - 50 - - Length prefix for -variable-length Blob fields - + 10.0;10.0;10.0;40.0;30.0;40.0 UMLClass @@ -148,22 +125,11 @@ variable-length Blob fields - - Relation - - 190 - 130 - 50 - 60 - - lt=<<- - 10.0;40.0;10.0;10.0;30.0;10.0 - Text 190 - 230 + 210 110 50 @@ -193,33 +159,22 @@ Field ID - - Relation - - 400 - 130 - 70 - 60 - - lt=<<- - 50.0;40.0;50.0;10.0;10.0;10.0 - Relation 130 - 80 - 490 + 210 + 500 90 lt=. - 10.0;60.0;10.0;20.0;220.0;20.0;220.0;10.0;220.0;20.0;470.0;20.0;470.0;70.0 + 10.0;10.0;10.0;70.0;480.0;70.0;480.0;10.0 Text - 290 - 40 + 300 + 280 170 50 @@ -230,24 +185,56 @@ style=wordwrap Text - 340 + 290 230 - 110 - 50 + 150 + 30 - MemoData -Field ID + MemoData Field ID Relation - 390 + 350 190 - 30 + 70 60 lt=<<- - 10.0;10.0;10.0;40.0 + 50.0;10.0;50.0;30.0;10.0;30.0;10.0;40.0 + + + UMLPackage + + 80 + 140 + 600 + 70 + + Memos field + + + + Relation + + 430 + 190 + 50 + 50 + + lt=<<- + 10.0;10.0;10.0;30.0;30.0;30.0 + + + Text + + 460 + 210 + 140 + 40 + + Length prefix + diff --git a/content/references/rippled-api/api-conventions/serialization.md b/content/references/rippled-api/api-conventions/serialization.md index d029e4cfff..1b832200f9 100644 --- a/content/references/rippled-api/api-conventions/serialization.md +++ b/content/references/rippled-api/api-conventions/serialization.md @@ -1,5 +1,5 @@ # Serialization Format -[[Source]
](https://github.com/ripple/rippled/blob/develop/src/ripple/protocol/impl/STObject.cpp#L697-L718 "Source") +[[Source]
](https://github.com/ripple/rippled/blob/develop/src/ripple/protocol/impl/STObject.cpp#L696-L718 "Source") This page describes the XRP Ledger's canonical binary format for transactions and other data. This binary format is necessary to create and verify digital signatures of those transactions' contents, and is also used in other places. The [rippled APIs](rippled-apis.html) typically use JSON to communicate with client applications. However, JSON is unsuitable as a format for serializing transactions for being digitally signed, because JSON can represent the same data in many different but equivalent ways. @@ -18,6 +18,17 @@ The result is a single binary blob that can be signed using well-known signature **Note:** The XRP Ledger uses the same serialization format to represent other types of data, such as [ledger objects](ledger-object-types.html) and processed transactions. However, only certain fields are appropriate for including in a transaction that gets signed. (For example, the `TxnSignature` field, containing the signature itself, should not be present in the binary blob that you sign.) Thus, some fields are designated as "Signing" fields, which are included in objects when those objects are signed, and "non-signing" fields, which are not. +## Sample Code + +The serialization processes described here are implemented in multiple places and programming languages: + +- In C++ [in the `rippled` code base](https://github.com/ripple/rippled/blob/develop/src/ripple/protocol/impl/STObject.cpp). +- In JavaScript in the [`ripple-binary-codec`](https://github.com/ripple/ripple-binary-codec/) package. +- In Python 3 [this repository's code samples section]({{target.github_forkurl}}/blob/{{target.github_branch}}/content/_code-samples/tx-serialization/serialize.py). + +These implementations are all provided with permissive open-source licenses, so you can import, use, or adapt the code for your needs in addition to using it alongside these documents for learning purposes. + + ## Internal Format @@ -165,7 +176,7 @@ AccountIDs that appear as stand-alone fields (such as `Account` and `Destination The "Amount" type is a special field type that represents an amount of currency, either XRP or an issued currency. This type consists of two sub-types: - **XRP** - XRP is serialized as a 64-bit unsigned integer (big-endian order), except that the second-most-significant bit is `1` to indicate that it is positive. In other words, take a standard UInt64 and calculate the bitwise-OR of that with `0x4000000000000000` to get the serialized format. + XRP is serialized as a 64-bit unsigned integer (big-endian order), except that the most significant bit is always 0 to indicate that it's XRP, and the second-most-significant bit is `1` to indicate that it is positive. Since the maximum amount of XRP (1017 drops) only requires 57 bits, you can calculate XRP serialized format by taking standard 64-bit unsigned integer and performing a bitwise-OR with `0x4000000000000000`. - **Issued Currencies** Issued currencies consist of three segments in order: 1. 64 bits indicating the amount in the [internal currency format](currency-formats.html#issued-currency-math). The first bit is `1` to indicate that this is not XRP. @@ -174,6 +185,10 @@ The "Amount" type is a special field type that represents an amount of currency, You can tell which of the two sub-types it is based on the first bit: `0` for XRP; `1` for issued currency. +The following diagram shows the serialization formats for both XRP amounts and issued currency amounts: + +![XRP amounts have a "not XRP" bit, a sign bit, and 62 bits of precision. Issued currency amounts consist of a "not XRP" bit, a sign bit, an exponent (8 bits), mantissa (54 bits), currency code (160 bits), and issuer (160 bits).](img/serialization-amount.png) + ### Array Fields [STArray]: #array-fields diff --git a/img/serialization-amount.png b/img/serialization-amount.png new file mode 100644 index 0000000000..6f0bd314f3 Binary files /dev/null and b/img/serialization-amount.png differ diff --git a/img/serialization-array.png b/img/serialization-array.png index ed0eb008eb..ef56a8a0df 100644 Binary files a/img/serialization-array.png and b/img/serialization-array.png differ diff --git a/img/serialization-object.png b/img/serialization-object.png index faae809cc9..d62f99922d 100644 Binary files a/img/serialization-object.png and b/img/serialization-object.png differ