Archive
The Archive function provides a general purpose data storage facility paid with usage tokens. You can Look at an archive entry by its hash, which lets you read the content but not change it. You can also Touch an entry directly by its location, which lets you change the content with the Write operation. Writing new content costs 1 usage token per 16 bytes of encrypted data added to the database, or yields a 1 token refund per 16 bytes reduced. (There can be a few bytes of overhead added in the encryption process.)
Before you can write an entry, you must first Buy its location for 1 usage token. This helps prevent accidentally writing to an incorrect location. You may then write arbitrary content into the purchased location. Later, if you want to Sell the location back to receive a 1 token refund, you must first clear it out by writing null content into it.
All content is encrypted in the database using a key derived from the archive location.
Example API Call
Here is a url which writes the string "abc" into archive location c80481226973dfec6dc06c8dfe8a5b1c, paying for the storage from usage location 29013fc66a653f6765151dd352675d0f. Note that in order for this to work, you must have already bought the archive location.
https://fexl.com/loom?function=archive&action=write &usage=29013fc66a653f6765151dd352675d0f &loc=c80481226973dfec6dc06c8dfe8a5b1c &content=abc
(The url is broken up across lines for clarity. In practice you would keep the entire url on a single line.)
You may use content with multiple lines or arbitrary binary characters. All you have to do is "uri_escape" the content to convert it into a form suitable for use in a url. (For you perl programmers, see the URI::Escape module.) For example, this multi-line string:
first/line second/line
would be encoded by uri_escape as:
first%2Fline%0Asecond%2Fline%0A
For better support of very large content, there will soon be an API call which is compatible with the HTTP "file upload" protocol. But for now, the simple "write" operation should suffice just fine for most purposes (even with large content).
Archive Operations
Here we describe the API (application programming interface) for the Archive. The operations are Buy, Sell, Touch, Look, and Write.
Buy
Buy a location in the archive. This costs 1 usage token. The location must currently be vacant (not bought) in order to buy it. The input is:
Key | Value | Description |
---|---|---|
function | archive | |
action | buy | Name of operation |
loc | id | Location to buy |
usage | id | Location of usage tokens |
If the Buy operation succeeds, you will see the following keys in the result:
Key | Value | Description |
---|---|---|
status | success | Everything went well. |
cost | qty | Cost of operation |
usage_balance | qty | New usage balance |
hash | hash | Hash of location |
If the operation fails, the status will be fail, and the reason for the failure will be indicated with any keys below which apply:
Key | Value | Description |
---|---|---|
status | fail | Something went wrong. |
error_loc | not_valid_id | loc is not a valid id |
error_loc | occupied | loc is already occupied (bought) |
content | string | existing content at loc if occupied |
error_usage | not_valid_id | usage is not a valid id |
error_usage | insufficent | usage location did not have at least one usage token |
Sell
Sell a location in the archive. This refunds 1 usage token. The content at the location must currently be empty (null) in order to sell the location. The input is:
Key | Value | Description |
---|---|---|
function | archive | |
action | sell | Name of operation |
loc | id | Location to sell |
usage | id | Location of usage tokens |
If the Sell operation succeeds, you will see the following keys in the result:
Key | Value | Description |
---|---|---|
status | success | Everything went well. |
cost | qty | Cost of operation (-1 meaning refund) |
usage_balance | qty | New usage balance |
hash | hash | Hash of location |
If the operation fails, the status will be fail, and the reason for the failure will be indicated with any keys below which apply:
Key | Value | Description |
---|---|---|
status | fail | Something went wrong. |
error_loc | not_valid_id | loc is not a valid id |
error_loc | vacant | loc is already vacant (sold) |
error_loc | not_empty | loc has non-empty content |
content | string | existing content at loc (if non-empty) |
error_usage | not_valid_id | usage is not a valid id |
Touch
Touch a location in the archive. The input is:
Key | Value | Description |
---|---|---|
function | archive | |
action | touch | Name of operation |
loc | id | Location to touch |
If the Touch operation succeeds, you will see the following keys in the result:
Key | Value | Description |
---|---|---|
status | success | Everything went well. |
content | string | Content at archive location |
hash | hash | Hash of location |
content_hash | hash | Hash of content |
If the operation fails, the status will be fail, and the reason for the failure will be indicated with any keys below which apply:
Key | Value | Description |
---|---|---|
status | fail | Something went wrong. |
error_loc | not_valid_id | loc is not a valid id |
error_loc | vacant | loc is vacant (sold) |
Look
Look at a location in the archive by its hash. The input is:
Key | Value | Description |
---|---|---|
function | archive | |
action | look | Name of operation |
hash | hash | Hash of location to examine |
If the Look operation succeeds, you will see the following keys in the result:
Key | Value | Description |
---|---|---|
status | success | Everything went well. |
content | string | Content at hash of location |
content_hash | hash | Hash of content |
If the operation fails, the status will be fail, and the reason for the failure will be indicated with any keys below which apply:
Key | Value | Description |
---|---|---|
status | fail | Something went wrong. |
error_hash | not_valid_id | hash is not a valid hash |
error_loc | vacant | loc is vacant (sold) |
Write
Write content into the archive. The system first encrypts the content using a key derived from the location. This may impose an overhead of a few bytes. It then compares the new encrypted length with the length of any existing content at this location, and determines how many bytes would be added or subtracted on net if it were to write out the new content. It then charges 1 usage token per 16 bytes added, or refunds 1 usage token per 16 bytes subtracted.
The input is:
Key | Value | Description |
---|---|---|
function | archive | |
action | write | Name of operation |
loc | id | Location to write |
content | id | Content to write into that location |
usage | id | Location of usage tokens |
guard | hash | Optional SHA256 hash of previous content to guard against overlapping writes |
If the Write operation succeeds, you will see the following keys in the result:
Key | Value | Description |
---|---|---|
status | success | Everything went well. |
cost | qty | Cost of operation |
usage_balance | qty | New usage balance |
hash | hash | Hash of location |
content_hash | hash | Hash of content |
NOTE: the "content" key supplied in the input is not echoed back in the result, because that would just be a waste of time and bandwidth.
If the operation fails, the status will be fail, and the reason for the failure will be indicated with any keys below which apply:
Key | Value | Description |
---|---|---|
status | fail | Something went wrong. |
error_loc | not_valid_id | loc is not a valid id |
error_loc | vacant | loc is vacant (sold) |
error_usage | not_valid_id | usage is not a valid id |
error_usage | insufficent | usage location is vacant or did not have enough usage tokens to cover the cost |
error_guard | not_valid_hash | guard was specified and is not a valid hash |
error_guard | changed | The hash of the previous content did not match the specified guard, so the new content was not written. Essentially this means that the content changed "under our feet" since the last time we looked at it, so we don't clobber those changes. |