THE HIVEThe desktop is open. Mine a private token in your browser
propolis

Docs / Protocol / Ledger and key pinning

Ledger and key pinning

One issuer key for everyone, pinned on Robinhood Chain behind a 24 hour timelock, and the totals of every active hour anchored next to it.

The contract

PropolisLedger lives on Robinhood Chain (chain id 4663) at 0x9316D05E6b790215C244ee4bF6026F576e6337a4, verified on Sourcify. It does two things: it pins the issuer key, and it records one line per active hour.

Key pinning

Privacy Pass has one known way to cheat: an issuer that signs with a different key for each holder can recognise that holder's tokens later. Propolis closes it by publishing the key id on chain. The Hive and the SDK read currentKey() from PropolisLedger and refuse to mint when the served key differs.

FieldValue
First pinned key0x4b2b1ee31ddc863d998ea10ba44b737489d86c0ac37e7d0a892bb83ce188dc47
RotationproposeKey(keyId), then activateKey() after a 24 hour delay
ReadscurrentKey(), pendingKey(), pendingSince()

A rotation is visible a full day before it takes effect, which gives anyone time to notice and ask why.

Hourly anchors

solidity
anchor(uint64 hour, bytes32 keyId, uint32 minted, uint32 spent, uint96 work, bytes32 nullRoot)

hour is unix seconds divided by 3,600. Hours are strictly increasing and only hours with activity are written. nullRoot is a binary SHA-256 Merkle root over that hour's nullifiers: leaves sorted, each pair sorted before hashing, an odd leaf promoted, zero when no token was spent.

Verify an hour

bash
# the nullifiers spent in an hour, and the root the relay computed
curl https://propoliscompute.com/api/v1/epoch/<hour>

# the anchored hours with their transactions
curl https://propoliscompute.com/api/v1/epochs?limit=20

Recompute the root from the list and compare it with the Anchored event of that hour on Blockscout. If a nullifier you spent is missing, or one appears twice across hours, the relay is lying and the chain shows it.