Package: centurymetadata
centurymetadata.org: Long-term Bitcoin Metadata StorageAboutCentury Metadatais a project to provide storage for small amounts
of auxiliary data.  As an example, this is useful for Bitcoin wallets,
which can be restored from 12 seed words, but cannot know about more
complex funds without additional data.  On restore, your wallet would attempt to
fetch this data fromhttps://centurymetadata.orgor a mirror.We are currently in alpha, seeking feedback.File FormatThe file format is designed to be self-explanatory and use standard,
long-lived primitives as much as possible.  Every file contains a
preamble, followed by 8192 bytes.  The preamble describes the data
format which follows:centurymetadata v0\0SIG[64]|WRITER[33]|READER[33]|GEN[8]|AES[8054]

SIG: BIP-340 SHA256(TAG|TAG|WRITER|READER|GEN|AES)
WRITER, READER: secp256k1 x-only keys
TAG: SHA256("centurymetadata v0"[18])
AESKEY: SHA256(EC Diffie-Hellman of WRITER,READER)
AES: CTR mode (starting 0, nonce 0) using AESKEY of DATA
DATA: gzip([TITLE\0CONTENTS\0]+), padded with 0 bytes to 8054\0The data itself is a series of NUL-separated title, contents pairs.
Obviously this cannot be validated on the production server, but the
test server (which only allows known keys) will check the file is
compliant.Usage with BitcoinThe BIP 32 path recommended for centurymetadata is0x44315441'(DATA), with/0'as the writer key,/1'as the reader key.  Of course, others can also send data
to your reader key, but you know that the record from your own writer
key can be trusted.The types of records accepted are as follows:Title:bitcoin psbt, Body: base64-encoded PSBTTitle:bitcoin transactionBody: hex-encoded transactionTitle:bitcoin miniscriptBody: miniscript stringAPIThe test API endpoint can be found attestapi.centurymetadata.org.Entry Creation: POST /api/v0/authorize/{READER}/{WRITER}/{AUTHTOKEN}You need to get anAUTHTOKENfor each new entry.  There can only be
one entry for anyREADER/WRITERpair, but once the entry is
authorized it can be updated by the writer at any time.Entry Update: POST /api/v0/updateUpdates a previously authorized writer/reader entry.  TheContent-Type: application/x-centurymetadatashould contain a valid
centurymetadata file.Entries Depth: GET /api/v0/fetchdepthSince we bundle records by reader prefix (e.g. all readers starting with42a3might be bundled together), you need to know how long the prefix is: it starts as an empty prefix and increases by one hex digit as we grow, so bundles are always a reasonable size.Returns a JSON object with memberdepthcontaining how many hex digits of reader to use forfetchbundle.Retrieiving Entries: GET /api/v0/fetchbundle/{READERPREFIX}This returns the given bundle, asContent-Type: application/x-centurymetadata, consisting of multiple back-to-back
century metadata files.ToolsThere is an experimental Python package to encode and decode
centurymetadata files in theGitHub repositoryRoadmapI'm committed to maintaining this service for at least 5 years
as a trial.  After that if it's proven useful I would like to
spin it into a real not-for-profit foundation to provide as much
certainty on continuity as possible.How Much?There will never be a charge for ratelimited updates or retrievals;
the idea is to charge a small cost for the creation of new entries to
cover ongoing running costs.  We may also accept donations.Who?Rusty Russell started this as a side project; my original problem was
how to give someone timelocked bitcoin, but realized there was a large
related class of problems for someone to solve.FeedbackAdvice, suggestions, kudos, blame: hosting is onGitHub, and you can reach us onTwitter, or sendme emailor other contact as listed onmy personal site.