Serialized Objects

Manipulate raw serialized xrpld objects!

What are Serialized Objects?

The XRP Ledger has canonical serialized forms of all objects subject to consensus. When writing a Hook it is inevitable you will come across serialized objects. These manifest as buffers containing what might appear to the developer as opaque binary blobs. In fact you can read these with the XRPL-Binary-Visualiser.

For example an sfAmount field serializes to a collection of bytes like 61D50F26109A32B7EC

Serialized Object API

To assist Hook developers in working with serialized objects the sto namespace was created within the Hooks API. These functions manipulate pointers within a Hook-provided buffer. See table below.

Hook API

What it does

sto_subfield

Index into a xrpld serialized object and return the location and length of a subfield

sto_subarray

Index into a xrpld serialized array and return the location and length of an index

sto_emplace

Emplace a field into an existing STObject at its canonical placement

sto_erase

Remove a field from an STObject

sto_validate

Validate an STObject

Where applicable these APIs return an offset and a length encoded into a single int64_t. See individual documentation for details.

Example

At typical scenario in which you would use the STO API is in processing memos on an Originating Transaction. Since you will likely need access to the whole memo anyway, an efficient way to process a set of memos is simply to dump the whole sfMemos field into a buffer then index around within it. While it is also possible to use the slot API to do this by slotting the Originating Transaction it would result in additional code and additional copying.

#define SUB_OFFSET(x) ((int32_t)(x >> 32))
#define SUB_LENGTH(x) ((int32_t)(x & 0xFFFFFFFFULL))
#define SBUF(str) (uint32_t)(str), sizeof(str)

uint8_t memos[2048];
int64_t memos_len = otxn_field(SBUF(memos), sfMemos);
for (int i = 0; GUARD(3), i < 3; ++i)
{
    int64_t memo_lookup = sto_subarray(memos, memos_len, i);
    if (memo_lookup < 0)
        rollback(SBUF("Memo lookup error"), 1);
    uint8_t*  memo_ptr = SUB_OFFSET(memo_lookup) + memos;
    uint32_t  memo_len = SUB_LENGTH(memo_lookup);
    // the above now point at the memo ... do something here
}

Overlap with slots

You may notice some overlap between slot APIs and STO APIs. The key difference here is who owns the underlying data:

  • If you are using slots then xrpld owns the object you are interacting with.
  • If you are using the STO API then the Hook owns the buffer you are interacting with.

Both sets of functions index into a Serialized Object without unnecessary copying.


What’s Next

Now that you've read all the concepts check the Hook API functions and the example hooks. You can do this on the Hooks Public Testnet using the provided docker. Read the README on the github for further instructions.