Project
Limits & safeguards
What MERKI protects, what it leaves to others, the risks we found while building it and what the contracts and the wallet do about them.
Post-quantum, here, means account authorisation only. The chain, the submitting wallet, your device, your connection and your privacy are outside it.MERKI is a prototype.
Covered
Your keyhold accepts nothing but hash-based one-time signatures. Their safety rests on Keccak-256, on correct derivation and verification, and on each key signing once. This is a custom Winternitz construction with per-step tweaks, not a standardised scheme such as XMSS or SLH-DSA.
Not covered
- Robinhood Chain consensus, sequencing and bridges.
- The submitting wallet. It signs an ordinary transaction. Whoever controls it can delay or drop your operation, not forge it.
- Your device. The phrase is encrypted at rest. During an unlocked session, malware on the device or hostile code injected into the page could still read it.
- Privacy. See What stays public.
- Assets with an issuer. Stock tokens and stablecoins can be paused or blocked by their issuer, whatever account holds them.
Risks and how they are handled
| Risk | Impact | Handling |
|---|---|---|
| A key signs twice (journal out of sync) | Critical | Read the index on chain before signing; under a cross-tab lock, re-read the journal from storage, sign, save it and read it back before the signature reaches any RPC or wallet; refuse any index at or below one already used; block new signing while one is unfinished |
| Browser storage blocked or cleared | High | Signing stops when the journal cannot be saved. A cleared journal falls back to the chain's key index; an operation signed but never included is then unknown to the device, so after clearing, use the recovery key or wait until the chain moves past it |
| Recovery key revealed without landing | High | Every other operation is blocked until a normal operation replaces the recovery key |
| Same phrase on two devices | Critical | Restored phrases open read-only; signing needs an explicit confirmation |
| Same phrase on two networks | High | Chain id is part of every key |
| Operation stuck after signing | Medium | Recovery key replaces it with the same nonce |
| Verifier or rotation bug | Loss of funds | Fuzz, invariant and fork tests; browser and contract checked against shared vectors |
| Wrong contracts behind the address | Loss of funds | verify-deployment compares code byte for byte; the wallet checks EntryPoint code before use |
| Overclaiming the protection | Misplaced trust | This page, the home page and the wallet state the limits |
Enforced on chain
- Signatures have exact lengths (2,209 and 2,241 bytes) and a mode byte; anything else fails.
- What gets signed is the full operation (via userOpHash, which folds in chain id and EntryPoint) together with the successor key.
- A rejected signature leaves state untouched. An accepted one retires the key, even if the calls revert later.
- No owner key, no admin, no proxy upgrade, no pause. The keyhold takes orders from the EntryPoint and from itself only.
- The implementation is locked at deployment and can never be opened as a keyhold.
In the browser
- The phrase sits under AES-256-GCM with a key stretched by PBKDF2-SHA256 (600,000 rounds), new salt and IV each time; passwords need 12+ characters.
- The unlocked secret stays in memory only, and is gone after five idle minutes or any reload.
- The userOpHash is computed locally and compared with the EntryPoint's answer before signing; a mismatch stops the send.
- The site sends security headers that forbid framing and limit referrers.