Whitepaper · v1.0 · October 2026

ZNode Grid: private storage on an open grid.

How files are sealed, where they are stored, how the network heals itself, and how storage payments become rewards for the people who run it.

Abstract

ZNode Grid is a file storage network in which files are encrypted in the user's browser before upload and stored as three replicas on storage nodes run by independent operators. Users sign in with a wallet instead of a password, and the same wallet deterministically unlocks their encryption key, so no server ever holds a key that can read user data. A coordinator admits nodes, places replicas, detects failures and repairs lost copies within seconds. Storage is bought with a single fixed on-chain payment to the StorageIncentive contract on Robinhood Chain. The contract splits each payment between a protocol fee and a reward pool, and only node operators can be paid out of that pool. This paper describes the design, its security properties and its current limitations.

1. Introduction

Most people store their files with a handful of large cloud providers. These services encrypt data at rest, but they hold the keys. A provider can read stored files, scan them, lose them in a breach, hand them over on request, or lock an account under terms that can change at any time. Users pay a recurring subscription for this, and every payment goes to the provider.

Decentralized storage networks address parts of this problem with trade-offs of their own. Content-addressed networks such as IPFS make files available to anyone who knows their identifier and keep them only as long as some node chooses to pin them. Incentivized object stores such as Storj provide encryption and durability, but are used much like a cloud account, with usage-based monthly billing and their own token for operator payouts.

ZNode Grid aims for a narrower, simpler target: private personal storage. It should be as easy to use as a cloud drive, private by construction, durable without user effort, and paid for in a way that funds the people who provide the disks.

2. Design goals

  1. Privacy by default. Plaintext and file names never leave the user's device. Every server-side component handles only ciphertext.
  2. No passwords. Identity and key recovery come from a wallet the user already controls.
  3. Durability without effort. Data survives node failures without the user doing anything.
  4. Open participation. Anyone can contribute disk space and be paid for it.
  5. Verifiable money. Payments and payouts follow rules enforced by a public contract, not by policy.
  6. Simplicity. Each component is small enough to audit and reason about.

Non-goals

  • Public content distribution. Files are private to their owner. Sharing is not part of v1.
  • Payment anonymity. Purchases are on-chain transactions, so a wallet's purchase is public. File contents are not.
  • Large-object throughput. Files are encrypted whole in the browser, and uploads are limited to 50 MB per file.

3. System overview

The system has four off-chain roles and one contract. Each role is given the least information it needs.

ComponentResponsibilityWhat it can see
Browser clientWallet sign-in, key derivation, encryption and decryptionEverything, only for its user
BackendSessions, payment verification, the encrypted file index, repair bookkeepingCiphertext, encrypted metadata, wrapped vault keys, wallet addresses
CoordinatorNode admission and authentication, replica placement, health checks, repair, reward metering and settlementOpaque blobs, file IDs, sizes, node addresses
Storage nodesStore and serve encrypted replicasRandom bytes under random IDs
StorageIncentive contractTakes storage payments, holds the reward pool, pays operatorsPublic: purchases and payouts

The backend never talks to nodes directly. All storage traffic goes through the coordinator. The two authenticate each other with a shared secret (INTERNAL_API_KEY), compared in constant time.

4. Cryptography

4.1 Sign-in

The client requests a random 256-bit nonce for its address and signs Login nonce:<nonce> with its wallet (EIP-191 personal message). The backend recovers the signer, deletes the nonce so it can't be reused, and issues a random session token. Signing costs no gas, and no password exists anywhere in the system.

4.2 Key hierarchy

There are two keys per user:

  • Unlock key. The wallet signs the fixed message ZNode Grid Master Unlock v1 followed by the lowercase address. The client hashes the message per EIP-191 and runs it through HKDF-SHA256 (salt znode-grid, info file-encryption) to get a 256-bit AES-GCM key. It exists only in the browser and is never sent anywhere.
  • Vault key. On first use, the client generates 32 random bytes with the Web Crypto CSPRNG. This key encrypts the user's files. It is stored on the backend only after being encrypted (wrapped) with the unlock key.

On a new device, the user signs in, re-derives the unlock key, downloads the wrapped vault key and unwraps it locally. The backend stores the wrapped key but never has anything that can unwrap it.

The unlock message must stay byte-for-byte identical, and the wallet must sign deterministically (RFC 6979 ECDSA, as standard externally owned accounts do). Anyone who obtains a user's signature over the unlock message can derive that user's key, so the message should only ever be signed on the genuine site.

4.3 File and metadata encryption

Each file is encrypted with AES-256-GCM under the vault key, using a fresh random 96-bit IV that is prepended to the ciphertext. File metadata (name, type, size) is encrypted the same way, as a separate object. Storage nodes and the coordinator only ever handle the encrypted blob, under a random UUID.

4.4 Properties

  • Confidentiality: no server-side component holds a key that can decrypt user data.
  • Integrity: GCM's authentication tag makes any change to a stored replica fail decryption, so tampering can't go unnoticed.
  • Portability: any browser with the same wallet can recover the vault. No key files to back up.

5. Data lifecycle

5.1 Upload

  1. The client encrypts the file and its metadata.
  2. The backend checks the session and confirms the wallet has paid for storage (section 7.1).
  3. The backend forwards the ciphertext to the coordinator.
  4. The coordinator selects three nodes. A node qualifies if it is online, active and has enough free capacity. Qualifying nodes are ranked by load, and nodes from operators not already chosen go first, so a single operator going offline can't take out every replica.
  5. The replica is written to every selected node. The backend records the file and one record per replica.

5.2 Download

The backend checks that the session's wallet owns the file and asks the coordinator for it, trying each replica in turn until one answers. The ciphertext streams back to the browser, which decrypts it locally.

5.3 Delete

The replica is deleted from every node that holds it, and then the file and replica records are removed.

6. Node network

6.1 Joining

An operator signs in to the node dashboard with their wallet and creates a join token. Tokens are single-use, expire after 24 hours and are stored only as a hash. On first start, a node generates its own secp256k1 identity key, then signs a join message that binds the token, its identity address and the URL it will serve on. Before accepting the node, the coordinator performs a contact check: it calls the node's /health endpoint at that URL and requires the node there to report the same identity. A node can't register an address it doesn't control.

6.2 Authentication

After joining, a node proves its identity with challenge-response: the coordinator issues a random nonce, the node signs it together with its node ID and URL, and receives a session token valid for 24 hours. Every request between coordinator and node carries that token.

6.3 Liveness and repair

Nodes send a heartbeat every 5 seconds, reporting used space, file count, capacity and version. A node that has been silent for 15 seconds is marked offline. The coordinator then asks the backend to repair every replica that node held: for each one, a surviving copy is fetched and written to a new node chosen under the same placement rules, and the records are updated. When an offline node comes back, it re-authenticates and resumes serving.

6.4 Graceful exit

An operator can retire a node from the dashboard. The node moves to EXITING, its replicas are migrated to other nodes while it is still online, and it becomes EXITED only once its data is safe elsewhere. An exited node can't rejoin under the same identity.

7. Economics

7.1 Storage payments

Users buy storage by calling purchaseStorage() on the StorageIncentive contract with exactly the current storagePrice. Underpaying, overpaying, buying twice and plain ETH transfers all revert. Before granting storage, the backend independently checks that the transaction is on the right chain, was sent to the contract, carries the purchase call data, paid exactly the price, has the required confirmations, and emitted a matching StoragePurchased event for that wallet. A transaction hash can only be used once. If the hash is lost, the contract's hasPurchased flag recovers the purchase.

7.2 Fee split

Each payment is split on-chain. protocolFeeBps goes to protocol fees and the rest to the reward pool. The fee is immutable after deployment and capped at 20% by the contract. The current deployment uses 10%, so 90% of every purchase funds node operators.

7.3 Reward metering

The coordinator meters three kinds of work for each node while it is online:

ComponentAccrues as
Storagebytes stored × time online × rate per GB-hour
Egressbytes served to users × rate per GB
Uptimetime online × rate per hour

Rates are published by the coordinator and can be tuned so that accrued rewards track what the pool actually receives. All amounts are tracked in wei as integers.

7.4 Settlement

An operator registers their payout wallet on the contract with registerNode() and claims from the dashboard. The coordinator's settler key calls rewardNode(operator, amount), which moves funds from the reward pool to the operator's balance. The contract rejects any reward larger than the pool, so every credited balance is fully backed. Operators then call withdraw() whenever they like (pull payments, protected against re-entrancy). Claims above what the pool holds stay unclaimed until enough purchases arrive. Anyone can top up the pool with fundRewardPool().

7.5 Owner powers

The contract owner can change the price for future purchases, replace the settler, and withdraw protocol fees. The owner can't touch the reward pool or any operator's balance, and can't raise the fee. Ownership moves only through a two-step transfer, so it can't be sent to a mistyped address.

8. Security analysis

8.1 Compromise scenarios

If this is compromised…The attacker getsThe attacker can't
A storage nodeEncrypted replicas under random IDsRead files, or change them without detection
The backendEncrypted metadata, wrapped vault keys, the wallet-to-file indexUnwrap keys or decrypt any file
The coordinatorNode addresses, routing of opaque blobs, the settler keyDecrypt files. With a dedicated settler, it also can't change prices or take fees
The network pathCiphertext in transit (inside TLS on public links)Read or silently alter content

8.2 Known limitations

  • Metadata leakage. The backend and coordinator learn how many files a wallet stores, their sizes, and when they are accessed.
  • Signature phishing. A malicious site that gets a user to sign the unlock message can derive their key. Users must sign it only on the genuine domain.
  • Wallet loss. Losing the wallet means losing the key. There is no recovery by design.
  • Coordinator trust. The coordinator is a single operator-run service. It is trusted for availability, honest placement and accurate metering, though not for confidentiality. It could under-report rewards, but it can never pay out more than the pool holds.
  • No storage proofs yet. Nodes are not currently audited with proofs of retrievability. A node that silently drops data is detected when that replica is read or repaired, and the other replicas cover it.
  • Settler separation. The settler should be a dedicated wallet, not the owner. When the same key holds both roles, a coordinator compromise also exposes owner powers.

9. Comparison

ZNode GridStorjIPFSCloud drives
Client-side encryptionAlwaysYesNoRarely, provider holds keys
Persistence3 replicas, auto-repairErasure coding, auto-repairWhile pinnedProvider-managed
IdentityWallet signatureAccountNoneAccount
PaymentOne-time, on-chainMonthly usageNot built inSubscription
Operator payoutsETH, on demand, contract-enforcedSTORJ token, monthlyNonen/a
Storage overhead3×~2.75×VariesProvider-managed
CoordinationSingle coordinatorStorj satellitesPeer-to-peerCentralized

ZNode Grid trades some storage efficiency and decentralization of coordination for simplicity: full replicas mean any single surviving copy can serve a download, and a single coordinator keeps placement and repair easy to reason about.

10. Future work

The following are directions under consideration, not commitments:

  • Storage audits: periodic challenges that make nodes prove they still hold their replicas.
  • Erasure coding: lower storage overhead at the same durability.
  • Multiple coordinators: federated or replicated coordination, removing the single point of failure.
  • Chunked, streaming encryption: to lift the per-file size limit.
  • Sharing: per-file keys that can be granted to another wallet.
  • On-chain node registry: making node admission and reward rates publicly verifiable.

11. Conclusion

ZNode Grid gives users cloud-drive convenience without handing a provider the keys. Encryption happens on the user's device, durability comes from replication and automatic repair across independent operators, and the money flows through a contract that guarantees every operator reward is backed. The design is deliberately small, so its security properties and its limits can both be stated plainly.

Appendix: parameters

Replication factor3
Heartbeat interval5 s
Offline after15 s without a heartbeat
Join token lifetime24 h, single use
Node session lifetime24 h
Maximum file size50 MB
CipherAES-256-GCM, 96-bit random IV
Key derivationHKDF-SHA256 over the EIP-191 hash of the unlock message
ChainRobinhood Chain (chain ID 4663)
Contract0x305A4b17C7D55B5956B348469f61113D764B0e53
Storage price0.0002 ETH, once per wallet
Protocol fee10% (immutable, contract cap 20%)