Look Ma, No Database: Documents With Shared Lifecycle State | EC Protocol
Most business software already runs on “documents”.
Vouchers, tickets, payment claims, receipts, licenses, account statements,<br>certificates, shipping documents, credentials. They may be JSON, PDF, XML, CBOR,<br>protobuf, plain text, or something more enterprise-shaped, but the pattern is<br>familiar: create a document, sign it, send it, store it, process it.
Developers already know how to do this. We know how to hash documents, sign<br>them, move them through apps, QR codes, NFC, RFID, HTTPS endpoints, files,<br>merchant systems, and mobile wallets. We know how to transform and store them.
The hard part starts when the document crosses an organizational boundary.
A shop receives a voucher and wants to know whether it was already spent<br>somewhere else.
A venue scans a ticket and wants to know whether the holder still controls it.
A merchant receives a payment claim and wants to know whether that same claim<br>was also sent to another merchant.
A verifier receives a credential and wants to know whether the issuer has<br>revoked or superseded it.
These are lifecycle questions. Not “what does the document say?” but “is this<br>document still the current, valid version that someone is allowed to act on?”<br>That is global state.
Today, the usual answer is: ask the database. But whose database?
That is where banks, card networks, platforms, issuer portals, SaaS registers,<br>and reconciliation systems enter the picture. Someone governs the shared<br>register. Everyone else integrates with it, waits for it, pays for it, or trusts<br>it.
EC Protocol explores a different split:
Keep the documents wherever the application wants. But track their lifecycle<br>through handles in a shared verification network.
The document carries the meaning. The hash of it is the handle. EC tells you whether that handle is still current.
Let’s explore a style of document application that becomes possible in that<br>world.
Let’s Build A Shared Gift Card
Suppose you want to build a gift card, voucher, or payment-claim system. That is<br>not simple with today’s infrastructure.
You could define a document format:
issuer: MallAuth<br>value: 100<br>currency: DKK<br>expiry: 2027-12-31<br>schema: https://example.net/schemas/voucher-v1<br>issuer_public_key: ...<br>issuer_signature: ...
Define canonical serialization, so everyone hashes the same bytes.
Define signature rules.
Define what counts as a valid transfer, redemption, revocation, or split.
None of that requires special infrastructure. It is ordinary document<br>processing.
When the system hands the document to a customer, it does this:
token_id = hash(document)<br>create token_id, owner = user_public_key
This registers the token in EC under the user’s public key. The user’s wallet<br>checks the issuer signature, verifies that the issuer is trusted, computes the<br>document hash, and confirms that the resulting token ID is controlled by the<br>user’s key.
At this point, EC does not know the voucher terms. It does not know the customer<br>identity. It does not need the document contents.
It only knows that this hash exists as a token, and that the user’s key<br>currently controls it.
The issuer created the meaning. EC tracks the lifecycle.
Spending Part Of A Document
Now the user wants to spend 30 units at a shop and keep 70 as change.
The wallet, or a transformer endpoint, creates two child<br>documents. Each child is a full copy of the parent with one new section appended.
The 30-unit child:
issuer: MallAuth<br>value: 100<br>currency: DKK<br>expiry: 2027-12-31<br>issuer_public_key: ...<br>issuer_signature: ...
split:<br>value: 30<br>salt: random_salt
The 70-unit change document:
issuer: MallAuth<br>value: 100<br>currency: DKK<br>expiry: 2027-12-31<br>issuer_public_key: ...<br>issuer_signature: ...
split:<br>value: 70<br>salt: same_random_salt
The wallet or a transformer endpoint computes:
parent_token = hash(parent_document)<br>shop_token = hash(child_document_30)<br>change_token = hash(child_document_70)
Then it submits one atomic EC transaction:
destroy parent_token, signature(user_public_key)<br>create shop_token, owner = shop_public_key<br>create change_token, owner = user_public_key
Notice that the signature for the existing parent_token is part of the<br>transaction, and that the public key of the change_token does not need to be the<br>same key used for the parent.
This write requires access to an EC node with write capability.<br>A wallet provider, issuer, merchant, gateway, or user-operated node could provide that<br>path. Reads are open, so even if the merchant submits the actual transaction,<br>the user can check the result independently.
But the document logic itself is ordinary:
Copy parent document.
Append a section.
Hash the new document.
Submit the lifecycle update with valid signatures.
There is no voucher balance database in the middle.
There is still shared infrastructure. The difference is that it tracks document<br>lifecycle by hash, not application-specific balances, accounts, or...