XLS-48d: Document Storage #132
Replies: 4 comments 7 replies
-
Im confused as to how the URI data is accessible on ledger? For any on ledger transactor to act on the data present in the URI it would need to fetch that data. From the perspective of oracle data it's useful only on ledger, as the point of the oracle is to bring off ledger data on ledger to act on. The oracle spec XLS-47d defines this more granularly than this.. esp if oracles are bringing multiple pairs of data. The definition here can be already achieved via an accountSet operation which has much the same limitations as this from the perspective of oracle data. From my first pass reading through this it seems to indicate this is possible (fetching the URI). Not even hooks could access data off ledger. |
Beta Was this translation helpful? Give feedback.
-
Interesting proposal and thank you for writing this up! I think what you proposed is basically a URIToken that is soulbound. Under soulbound we understand NFTs, or objects containing a URI, that are non transferable. XLS20 does have this flag, tfTransferable, it's not a first class object so you need to have an indexer like clio. URITokens or xls40 can both act the same way with a flag to make them soulbound. Can you share your thoughts around this? 😊 |
Beta Was this translation helpful? Give feedback.
-
Hello, thank you for writing this proposal. I have two questions:
A rebuttal to the use case of preserving document integrity: Today, we are publishing documents along with their checksums in order to prove their integrity. For example -- software downloads are accompanied with a public display of the expected md5 hashes. Why would an app developer want to add an extra layer of indirection? Instead she could publish the ipfs/magnet/Google-Drive link directly on her website. |
Beta Was this translation helpful? Give feedback.
-
It sounds like there's not all that much demand for / interest in this functionality, so I guess I'll retire this proposal for now. We can always dig it back out if the need arises. |
Beta Was this translation helpful? Give feedback.
-
Document Storage
Many use cases call for storing arbitrary, unstructured data in the ledger and retrieving it. This might be used for app configurations, identity data, oracles, user storage for play-to-earn games, provenance tracking of objects, and so on.
This proposal defines "CRUD operations" (create, retrieve, update, delete) for arbitrary documents.
ledger_entry
andaccount_object
API methods for getting Document entries from the ledgerThese changes require an amendment to the XRP Ledger.
(This standards draft draws heavily on a previous draft of the XLS-40d: Decentralized Identity specification.)
Rationale
Blockchains are fundamentally good at storing data in a manner that is public, highly-available, and cryptographically verifiable. (Changes require a signed transaction and data integrity is verified with cryptographic hashes.) Various blockchain use cases depend on being able to store and retrieve data from the ledger in various formats. This specification aims to support further general purpose use of the XRP Ledger by allowing users to store small chunks of data, called Documents, either directly on-ledger or with an on-ledger reference to data stored off-ledger.
In general, this spec is applicable for anything where all of the following are true:
Non-fungible tokens provide a similar ability to store arbitrary URIs or small data blocks in the ledger. However, NFTs have some properties that are critical to their use cases but other inconvenient for the use cases Document Storage targets.
The functionality defined by Document Storage is similar to Stellar's "Manage Data" operation, but the amount and format of data allowed is different. Stellar allows for a 64-byte data field identified by a 64-byte identifying string; Document Storage allows up to two 256-byte data fields identified by a 4-byte identifying integer.
One example of a use case for Document Storage is non-sensitive client application settings. Wallet applications are already highly portable; as long as you know your secret keys, you can use a wallet app from any device and switch at any time. Most of the data about your XRP Ledger account is natively part of the ledger, such as your balances, trust lines, and various account settings. However, there is currently no place on-ledger to store settings that are specific to the client application, which means that switching to a different device means either exporting and re-importing certain settings, or having a separate backend service hosted by the wallet provider. With Document Storage, a client application can define a specific document number to store its settings at, which would be the same for every user, and define/retrieve settings from that Document purely on-ledger. Then, if the user connected using the same static wallet code from any device, they could instantly access their saved settings with no outside service or file needed. Taking it a step further, other apps could read these settings, or multiple separate apps could share settings in a standard format, allowing greater portability and compatibility. This allows many more dApps to have no backend other than the XRP Ledger itself.
Document Storage also has a potential for synergy with other proposed extensions, such as Hooks, which could read or modify Documents beyond what they can do with Hooks' built in state management.
Of course, since all data in the XRP Ledger is public, Document storage is not suited for storing secret, sensitive, or personal information. (Even if it is encrypted, having the data permanently publicly accessible is poor operational security.)
DocumentSet transaction
This transaction type creates or updates a
Document
ledger entry. In addition to transaction common fields, it has:DocumentNumber
Owner
,DocumentNumber
). By convention, values of 65535 or less are reserved for "well known" documents and values of 65536 or greater are unreserved.Data
URI
The
Data
andURI
fields are collectively called the data fields of the Document. You can specify one, both, or neither of these.The
URI
field can only contain bytes that correspond to characters valid in URIs, specifically the ASCII values for the following characters:ABCDEFGHIJKLMNOPQRSTUVWXYZabcdefghijklmnopqrstuvwxyz0123456789-._~:/?#[]@!$&'()*+,;=%
. (This is the same restriction that applies to theMemoType
andMemoFormat
fields.) It is intended, but not required, for theURI
field to encode a reference to an off-ledger document that is too large to store on-ledger, such as anipfs:
URL.The
Data
field may contain fully arbitrary data.The transaction creates or updates (aka "upserts") the corresponding Document entry in the ledger with the matching
DocumentNumber
, adding or replacing theData
andURI
fields with the ones provided. Specify an emptyData
orURI
field to remove it. (If the field already does not exist in the Document, this has no effect.) This transaction always updates thePreviousTxnID
andPreviousTxnLgrSeq
fields of a Document even if it did not make changes to the data fields, so you can use an otherwise no-op transaction to "renew" a document.The DocumentSet transaction has no specific transaction flags.
DocumentDelete transaction
This transaction removes a
Document
ledger entry. In addition to transaction common fields, it has the following field:DocumentNumber
The DocumentDelete transaction has no specific transaction flags.
Document ledger entry
A Document ledger entry stores arbitrary data on behalf of a given account.
A Document entry counts as one item for purposes of the owner reserve, and is tracked in an owner directory. Only the owner of an object can update it, although you can use multi-signing to share that power. Each account can have (theoretically) up to 232 Document entries, each with a different
DocumentNumber
, but practically speaking the owner reserve puts a stricter limit on how many Document entries one account can afford.This ledger entry has the following fields:
Owner
DocumentSet
transaction that created this ledger entry.DocumentNumber
Data
URI
PreviousTxnID
PreviousTxnLgrSeq
The fields
Data
andURI
are guaranteed to be nonzero length if present.Document ID format
The ledger entry ID of a Document object is the SHA-512Half of the following values, concatenated in order:
0x0044
)DocumentNumber
valueWell-Known Document Numbers
It some cases, it is helpful to have certain types of documents conventionally stored at a predetermined
DocumentNumber
so that you can look up an account's document of that type without further information. Similar to reserved ports in TCP/IP, we define a range of "reserved" document numbers and a registry (a list to be maintained on xrpl.org) mapping specific numbers to specific types of documents.The reserved range of
DocumentNumber
values is 0 through 65535 inclusive. To register a given document number for a specific purpose, create an XLS draft and specify the meaning and format of the document type to be stored at that number. The registry will be updated when that XLS draft is accepted.Values of 65536 or greater are unreserved and may be used for any type of document.
At a protocol level, no rules are enforced regarding the type of document stored at any number.
API Changes
The
account_objects
method can returnDocument
ledger entries. Extend the API method to allow filtering by"type": "document"
to return only these types of documents. The same applies to theledger
andledger_data
methods, which can also retrieve arbitrary ledger entries and filter by type.The
ledger_entry
method can retrieve a specificDocument
ledger entry, similar to how it returns other types. There are two ways to look up a givenDocument
:index
request field)DocumentNumber
and the account that owns it, using a newdocument
request field, which is an Object with two nested, required sub-fields as follows:document.owner
document.number
DocumentNumber
of the document to look up.This is similar to how you can look up offers, escrows, tickets, and others.
Size Considerations
At 572 bytes including the bookkeeping fields, the maximum size of a single Document ledger entry is slightly larger than most directly user-editable ledger entries (for comparison, a trust line is between 234 and 250 bytes and a payment channel can be up to 247 bytes if my math is right), but much smaller than a single NFTokenPage entry, which can be over 73,000 bytes if it stores the maximum number of NFTs. Therefore, we consider it appropriate to require a single owner reserve increment per Document object owned in the ledger.
Users can doubtlessly find various ways to store arbitrary data in the ledger, but to discourage wasteful use of resources we explicitly don't define a way of linking multiple Document entries together for storing larger amounts of data. Users can use the data fields to identify, locate, and verify documents which are stored and distributed using another system such as IPFS or even BitTorrent. For example, the
Data
field can contain a hash, the URI field can be amagnet:
link, and so on.Document History
Some use cases may call for examining multiple recent values for a given Document. This is already possible using past ledger versions and transaction metadata. The
PreviousTxnID
andPreviousTxnLgrSeq
fields can be used to directly look up the previous version of a Document the same way they can for other types of ledger entry with those fields. (Note: most ledger entry types have these fields; the big exception is RippleState, for trust lines. The other types that don't have these fields are not directly user-modifiable: Amendments, DirectoryNode, FeeSettings, LedgerHashes, and NegativeUNL.)In the edge case where a ledger entry is modified more than once within a single ledger, you must use the transaction metadata (specifically the
FinalFields
of aModifiedNode
entry) to look up the intermediate state of the entry. This state exists for only a brief moment while executing the transactions to build the ledger, but it may be necessary to understand the full history of the entry.A limitation of the
PreviousTxnID
andPreviousTxnLgrSeq
fields is that the "thread" they create of an entry's history does not go back further than its creation. If an entry was previously deleted and later recreated with the same ID, each instance's history is separate.It may be useful to add an API method to the server or client libraries for looking up past states of a ledger entry. This would not require an amendment.
Beta Was this translation helpful? Give feedback.
All reactions