Skip to content
Tenzro
Documentation menu
Compute, data and storage

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

  1. 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.
  2. 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).
  3. Buy. The renter accepts the claim, paying the full term into the claim's vault, which nobody holds a key to.
  4. Prove. Every hour, validators' SLA probes ask the provider to prove possession of every object it is paid to keep.
  5. 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. Files uploaded through /v1/files use four data and two parity shards, which survives any two providers disappearing at once. On the market layer the operator chooses the scheme.

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 per byte-epoch. A provider chooses:

  • Fixed: a flat rate per byte-epoch;
  • Network-dynamic: a rate that follows storage utilisation through an EIP-1559-style controller, with a gentler curve than compute (each step bounded at 6.25%) because storage commitments last longer.

Access control

Every stored object has an owner and an access policy. Retrieval is checked, fail-closed, before any shard is returned.

PolicyWho may read
publicAnyone; only the owner administers
owner_onlyOnly the owner DID. The default.
did_allowlistA named set of DIDs
capability_requiredHolders 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 files as a developer

The tenant layer, /v1/files, is shaped like a familiar files API. The DID your access token proves owns the file, and filenames come back on every listing. Every route, reads included, needs a signed-in caller the node's access policy admits, and other tenants' files are indistinguishable from files that do not exist.

bash
tenzro files upload ./dataset.parquet --purpose fine_tune
tenzro files list
tenzro files download <FILE_ID> --out ./dataset.parquet
tenzro files usage
tenzro files delete <FILE_ID>
bash
curl -s https://rpc.tenzro.com/v1/files \
  -H "Authorization: DPoP $TENZRO_BEARER_JWT" -H "DPoP: $TENZRO_DPOP_PROOF" \
  -F purpose=fine_tune -F file=@dataset.parquet

Every upload returns the file's descriptor_digest; buy a storage claim that commits it to pay for keeping the file. The same operations are JSON-RPC methods (tenzro_uploadFile, tenzro_listFiles, tenzro_getFile, tenzro_downloadFile, tenzro_deleteFile, tenzro_fileStorageUsage) and MCP tools.

Build on the market layer

The market layer addresses objects by an id you choose and leaves ownership, funding and naming to you. Storing an object is an admin method on the provider's own node:

json
{
  "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 the descriptor_digest. 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.

MethodAccess
tenzro_uploadFileOwner: the signed-in caller
tenzro_listFiles, tenzro_getFile, tenzro_downloadFile, tenzro_fileStorageUsageThe owning caller only
tenzro_storageStatusOpen
tenzro_storageStoreObject, tenzro_storageSetPricingAdmin
tenzro_computeGetClaim, tenzro_computeListClaimsOpen

Become a storage provider

Run a node with the storage role and stake for the capacity you offer:

bash
tenzro-node --roles storage --data-dir ./data
tenzro stake bond --role storage --amount <AMOUNT_WEI> --terabytes 8
tenzro node storage status

See Operators and roles.