Serialization - sample code in progress, clarifications

This commit is contained in:
mDuo13
2018-11-14 19:50:25 -08:00
parent be3c1c23a2
commit ce931fa89b
7 changed files with 2223 additions and 11 deletions

View File

@@ -5,17 +5,16 @@ XRP Ledger transactions have a canonical binary format, which is necessary to cr
The process of serializing a transaction from JSON or any other representation into their canonical binary format can be summarized with these steps:
1. Convert each field's data into its "internal" binary format.
2. Sort the fields in canonical order.
3. Concatenate the fields in their sorted order. ***TODO: seems there must be some sort of wrapping/control data to indicate which fields are present for cases with optional fields.***
1. Make sure all required fields are provided, including any required but "auto-fillable" fields.
**Note:** The `SigningPubKey` must also be provided at this step. When signing, you can derive this key from the secret key that is provided for signing.
2. Convert each field's data into its "internal" binary format.
3. Sort the fields in canonical order.
4. Prefix each field with an identifier.
5. Concatenate the fields (including prefixes) in their sorted order.
When serializing transaction instructions to be signed, you must also:
The result is a single binary blob that can be signed using well-known signature algorithms such as ECDSA (with the secp256k1 elliptic curve) and Ed25519. After signing, you must attach the signature to the transaction, calculate the transaction's identifying hash, then re-serialize the transaction with the additional fields.
- Make sure all required fields are provided, including any required but "auto-fillable" fields.
- Add the `SigningPubKey` field ***TODO: at what point in the above process? Probably before sorting, if it's a signing field?***
The result is a single binary blob that can be signed using well-known signature algorithms such as ECDSA (with the secp256k1 elliptic curve) and Ed25519. The hard work is the details of each of those steps.
The hard work is the details of each of those steps.
***Notes: some useful links for signing:***
@@ -32,6 +31,8 @@ For example, the `Flags` [common transaction field](transaction-common-fields.ht
All fields in a transaction are sorted in a specific order based on the field's type first, then the field itself second. (Think of it as sorting by family name, then given name, where the family name is the field's type and the given name is the field itself.)
When you combine the type code and sort code, you get the field's identifier, which is prefixed before the field in the final serialized blob. If both the type code and the field code
### Type Codes
Each field type has an arbitrary sort code, with lower codes sorting first. These codes are defined in [`SField.h`](https://github.com/ripple/rippled/blob/master/src/ripple/protocol/SField.h#L57-L74).
@@ -40,7 +41,7 @@ For example, [UInt32 has sort order 2](https://github.com/ripple/rippled/blob/72
### Field Codes
Each field also has a sort code, which is used to sort fields that have the same type as one another, with lower codes sorting first. These fields are defined in [`SField.cpp`](https://github.com/ripple/rippled/blob/72e6005f562a8f0818bc94803d222ac9345e1e40/src/ripple/protocol/impl/SField.cpp#L72-L266).
Each field also has a field code, which is used to sort fields that have the same type as one another, with lower codes sorting first. These fields are defined in [`SField.cpp`](https://github.com/ripple/rippled/blob/72e6005f562a8f0818bc94803d222ac9345e1e40/src/ripple/protocol/impl/SField.cpp#L72-L266).
For example, the `Account` field of a [Payment transaction][] [has sort code 1](https://github.com/ripple/rippled/blob/72e6005f562a8f0818bc94803d222ac9345e1e40/src/ripple/protocol/impl/SField.cpp#L219), so it comes before the `Destination` field which [has sort code 3](https://github.com/ripple/rippled/blob/72e6005f562a8f0818bc94803d222ac9345e1e40/src/ripple/protocol/impl/SField.cpp#L221).
@@ -55,4 +56,14 @@ Some fields, such as `SignerEntry` (in [SignerListSet transactions][]), and `Mem
### Amount Fields
The "AMOUNT" type is a special field type that represents an amount of currency, either XRP or an issued currency. ***TODO: details on how both are serialized in transactions.***
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.
- **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.
2. 160 bits indicating the [currency code](https://developers.ripple.com/currency-formats.html#currency-codes). The standard API converts 3-character codes such as "USD" into 160-bit codes using the [standard currency code format](currency-formats.html#standard-currency-codes), but custom 160-bit codes are also possible.
3. 160 bits indicating the issuer's Account ID. (See also: [Account Address Encoding](accounts.html#address-encoding))
You can tell which of the two sub-types it is based on the first bit: `0` for XRP; `1` for issued currency.