Decentralised storage
Store data with staked providers: erasure-coded shards, an hourly proof of possession, and payment through storage claims that settle on validators' verdicts.
Any node with spare disk can hold data for the network and be paid for it. A home server, a homelab NAS or a data centre rack all join the same market. Payment is a storage claim in consensus state: the renter pays into the claim's vault up front, and the provider is paid hour by hour only for hours in which validators found it still holding the data. Providers back that promise with their stake.
How it works
- Store. An object is erasure-coded into data and parity shards and published over the iroh data plane. Storing returns the object's
descriptor_digest: the SHA-256 of its descriptor, which names every shard and its committed Merkle root. - Offer. The provider writes a storage claim that commits the descriptor digest, with collateral and a price per hour (the object size times its byte-epoch rate).
- Buy. The renter accepts the claim, paying the full term into the claim's vault, which nobody holds a key to.
- Prove. Every hour, validators' SLA probes ask the provider to prove possession of every object it is paid to keep.
- Settle. Anyone may settle the claim. Each hour with an available verdict pays the provider that hour's price; an unavailable hour refunds the renter and pays a penalty from collateral; an hour with no verdict refunds it.
Erasure coding
Objects are split into data shards and parity shards and spread across providers. The object can be rebuilt from any sufficient subset, so losing a provider does not lose the data. The operator chooses the scheme when storing; the default of four data and two parity shards survives any two shards being lost at once.
Proof of possession
When an object is stored, each shard is cut into 1 KiB chunks and committed as a Merkle root. A challenge is a fresh random nonce, and the nonce alone decides which chunks must be proven, so the provider cannot know them in advance. The answer is each sampled chunk with its Merkle path; the verifier checks it against the committed roots using only the descriptor and never downloads a shard. A proof is a few kilobytes whatever the object size.
Stake and SLAs
A storage provider stakes for the storage role, or delivers storage claims from the compute bond it already holds. The stake is the provider's SLA: an hour frozen unavailable takes the governed SLA penalty from it into the insurance pool, and the redundancy layer re-replicates the object onto a healthy provider. Storage and compute share one coverage budget per provider, so a provider cannot take on a claim its stake cannot cover on top of everything else it owes. See SLA attestation and metering and Slashing.
Pricing
Storage is priced at a fixed rate per byte-epoch, in wei, set by the provider. The rate never follows demand, and a new rate applies only to deals opened after it is set:
tenzro node storage set-pricing --rate <WEI_PER_BYTE_EPOCH>
tenzro node storage statustenzro_storageStatus returns is_storage_provider, effective_rate_wei and object_count.
Access control
Every stored object has an owner and an access policy. Retrieval is checked, fail-closed, before any shard is returned.
| Policy | Who may read |
|---|---|
public | Anyone; only the owner administers |
owner_only | Only the owner DID. The default. |
did_allowlist | A named set of DIDs |
capability_required | Holders of a capability token for the read action |
A sensitive object can also carry a confidential seal: encryption at rest, with one wrapped data key per authorised DID.
Store an object
Objects are addressed by an id you choose, and ownership, funding and naming are left to you. Storing an object is an admin method on the provider's own node (tenzro node storage store --object-id <ID> --owner <ADDRESS> --file <PATH> from the CLI):
{
"jsonrpc": "2.0",
"id": 1,
"method": "tenzro_storageStoreObject",
"params": {
"object_id": "0x...",
"owner": "0x...",
"owner_did": "did:tenzro:human:...",
"data": "<base64 bytes>",
"data_shards": 4,
"parity_shards": 2
}
}The result carries object_id, size_bytes, data_shards, parity_shards and descriptor_digest. tenzro_storageRetrieveObject (tenzro node storage retrieve --object-id <ID> --out <PATH>), also admin, rebuilds the object from its shards and returns its bytes as base64. The provider then offers a storage claim with a ComputeClaim transaction whose offer sets storage_descriptor to that digest; the renter accepts it the same way as any compute claim. Read claims with tenzro provider compute-claims --party <ADDRESS> or tenzro_computeListClaims.
| Method | Access |
|---|---|
tenzro_storageStatus | Open |
tenzro_storageStoreObject, tenzro_storageRetrieveObject, tenzro_storageSetPricing | Admin |
tenzro_computeGetClaim, tenzro_computeListClaims | Open |
Become a storage provider
Run a node with the storage role and stake for the capacity you offer:
tenzro-node --roles storage --data-dir ./data
tenzro stake bond --role storage --amount <AMOUNT_WEI> --terabytes 8
tenzro node storage statusSee Operators and roles.
Related
- Compute rental, which shares the same stake
- Compute claims and the price index
- Machine Economy