Skip to content

Recovery pallet modernization#10482

Merged
ggwpez merged 90 commits into
masterfrom
oty-recovery-pallet
Apr 30, 2026
Merged

Recovery pallet modernization#10482
ggwpez merged 90 commits into
masterfrom
oty-recovery-pallet

Conversation

@ggwpez

@ggwpez ggwpez commented Dec 1, 2025

Copy link
Copy Markdown
Member

Recovery Pallet

Pallet Recovery allows you to have friends or family recover access to your account if you lose
your seed phrase or private key.

Terminology

  • lost: An account that has lost access to its private key and needs to be recovered.
  • friend: A befriended account that can approve a recovery process.
  • initiator: An account that initiated a recovery attempt.
  • recovered: An account that has been successfully recovered.
  • inheritor: An account that is inheriting access to a lost account after recovery.
  • attempt: An attempt to recover a lost account by an initiator.
  • order: The level of trust that an account has in a friend group.
  • deposit: The amount that a friends of this group needs to reserve to initiate an attempt.
  • threshold: The number of friends that need to approve an attempt.
  • inheritance delay: How long an attempt will be delayed before it can succeed.
  • provided block: The blocks that are provided by the T::BlockNumberProvider.

Scenario: Recovering a lost account

Story of how the user Alice loses access and is recovered by her friends.

  1. Alice uses the recovery pallet to configure one or more friends groups:
  • Alice picks a suitable inheritor account that will inherit the access to her account for
    each friend group. This could be a multisig.
  • Alice configures all groups with via set_friend_groups.
  1. Alice loses access to her account and becomes a lost account.
  2. Any member (aka initiator) of Alice's friend groups become aware of the situation and
    starts a recovery attempt via initiate_attempt.
  3. The friend group self-organizes and one-by-one approve the ongoing attempt via
    approve_attempt.
  4. Exactly threshold friends approve the attempt (further approvals will fail since they are
    useless).
  5. Any account finishes the attempt via finish_attempt after at least inheritance delay
    blocks since the initiation have passed.
  6. Alice's account is now officially recovered and accessible by the inheritor account.
  7. The inheritor may call control_inherited_account at any point to transfer Alice's funds
    to her new account.

Scenario: Multiple friend group try to recover an account

Alice may have configured multiple friend groups that all try to recover her account at the same
time. This can lead to a conflict of which friend group should eventually inherit the access.

  1. Alice configures groups Family (delay 10d, order 0) and Friends (delay 20d, order 1).
  2. Day 0: Alice loses access to her account.
  3. Day 6: Friends initiate a recovery attempt for Alice.
  4. Day 15: Family finally understands Polkadot and initiates an attempt as well.
  5. Day 25: Family inherits access to Alice account.
  6. Day 26: Friends group gets nothing since inheritance order is higher the one from Family.

In the case above you see how the Friends group is now unable to recover Alice account since
the Family group already did it and has a lower inheritance order.
Now, imagine the case that the Friends group would have started on day 4 and would have
already recovered the account on day 24. Two days later, the Family group can take access back
and will replace the inheritor account with their own. The Friends group had access for two
days since they were faster.
If Alice account has most balance locked in 28 day staking this would not make a big difference,
since only the free balance would be immediately transferable.

After a recovery attempt was completed, friend groups with a higher inheritance order cannot
open a new attempt to recover the account.

Data Structures

The pallet has three storage items, see the in-code docs [FriendGroups], [Attempts] and
[Inheritor]. Storage items may contain deposit "tickets" or similar noise and should therefore
not be read directly but only through the API.

API

Reading data can be done through the view functions:

  • provided_block_number: The block number that will be used to measure time.
  • friend_groups: The friend groups of an account that can initiate recovery attempts.
  • attempts: Ongoing recovery attempts for a lost account.
  • inheritor: The account that inherited full access to the lost account.
  • inheritance: All the recovered accounts that an account inherited access to.

TODO

  • Create migration from old format for Kusama
  • Weights

Signed-off-by: Oliver Tale-Yazdi <oliver.tale-yazdi@parity.io>
Signed-off-by: Oliver Tale-Yazdi <oliver.tale-yazdi@parity.io>
Signed-off-by: Oliver Tale-Yazdi <oliver.tale-yazdi@parity.io>
Signed-off-by: Oliver Tale-Yazdi <oliver.tale-yazdi@parity.io>
Signed-off-by: Oliver Tale-Yazdi <oliver.tale-yazdi@parity.io>
Signed-off-by: Oliver Tale-Yazdi <oliver.tale-yazdi@parity.io>
Signed-off-by: Oliver Tale-Yazdi <oliver.tale-yazdi@parity.io>
Signed-off-by: Oliver Tale-Yazdi <oliver.tale-yazdi@parity.io>
Comment thread substrate/frame/recovery/src/lib.rs
Signed-off-by: Oliver Tale-Yazdi <oliver.tale-yazdi@parity.io>
Signed-off-by: Oliver Tale-Yazdi <oliver.tale-yazdi@parity.io>
Signed-off-by: Oliver Tale-Yazdi <oliver.tale-yazdi@parity.io>
Signed-off-by: Oliver Tale-Yazdi <oliver.tale-yazdi@parity.io>
Signed-off-by: Oliver Tale-Yazdi <oliver.tale-yazdi@parity.io>
Signed-off-by: Oliver Tale-Yazdi <oliver.tale-yazdi@parity.io>
Signed-off-by: Oliver Tale-Yazdi <oliver.tale-yazdi@parity.io>
Signed-off-by: Oliver Tale-Yazdi <oliver.tale-yazdi@parity.io>
Signed-off-by: Oliver Tale-Yazdi <oliver.tale-yazdi@parity.io>
@ggwpez ggwpez marked this pull request as ready for review December 15, 2025 11:43
@ggwpez ggwpez requested a review from a team as a code owner December 15, 2025 11:43
ggwpez and others added 8 commits December 15, 2025 13:45
Signed-off-by: Oliver Tale-Yazdi <oliver.tale-yazdi@parity.io>
Signed-off-by: Oliver Tale-Yazdi <oliver.tale-yazdi@parity.io>
Signed-off-by: Oliver Tale-Yazdi <oliver.tale-yazdi@parity.io>
Signed-off-by: Oliver Tale-Yazdi <oliver.tale-yazdi@parity.io>
Signed-off-by: Oliver Tale-Yazdi <oliver.tale-yazdi@parity.io>
Signed-off-by: Oliver Tale-Yazdi <oliver.tale-yazdi@parity.io>
Comment thread substrate/frame/recovery/src/lib.rs
Comment thread substrate/frame/recovery/src/lib.rs Outdated

@rockbmb rockbmb left a comment

Copy link
Copy Markdown
Contributor

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

I created an PET E2E suite for this: open-web3-stack/polkadot-ecosystem-tests#602

it's not complete coverage, plus I had to run it against a patched version of WAH, but the scenarios covered all pass.

LGTM modulo audits (will also revisit as I expand the test suite)

ggwpez and others added 10 commits April 30, 2026 18:58
Signed-off-by: Oliver Tale-Yazdi <oliver.tale-yazdi@parity.io>
Signed-off-by: Oliver Tale-Yazdi <oliver.tale-yazdi@parity.io>
Signed-off-by: Oliver Tale-Yazdi <oliver.tale-yazdi@parity.io>
Signed-off-by: Oliver Tale-Yazdi <oliver.tale-yazdi@parity.io>
Signed-off-by: Oliver Tale-Yazdi <oliver.tale-yazdi@parity.io>
Co-authored-by: Alexandre R. Baldé <alexandre.balde@parity.io>
…now how to do it well and its low prio

Signed-off-by: Oliver Tale-Yazdi <oliver.tale-yazdi@parity.io>
Signed-off-by: Oliver Tale-Yazdi <oliver.tale-yazdi@parity.io>
Signed-off-by: Oliver Tale-Yazdi <oliver.tale-yazdi@parity.io>
@ggwpez ggwpez enabled auto-merge April 30, 2026 20:24
ggwpez added 2 commits April 30, 2026 23:10
Signed-off-by: Oliver Tale-Yazdi <oliver.tale-yazdi@parity.io>
Signed-off-by: Oliver Tale-Yazdi <oliver.tale-yazdi@parity.io>
@ggwpez ggwpez added this pull request to the merge queue Apr 30, 2026
Merged via the queue into master with commit 1d65ee9 Apr 30, 2026
387 of 392 checks passed
@ggwpez ggwpez deleted the oty-recovery-pallet branch April 30, 2026 23:56
@github-project-automation github-project-automation Bot moved this from In Progress to Done in Runtime / FRAME Apr 30, 2026
ggwpez added a commit to polkadot-fellows/runtimes that referenced this pull request May 4, 2026
Signed-off-by: Oliver Tale-Yazdi <oliver.tale-yazdi@parity.io>
@rachsrl rachsrl moved this from Backlog to Scheduled in Security Audit (PRs) - SRLabs May 26, 2026
@rachsrl rachsrl moved this from Scheduled to In progress in Security Audit (PRs) - SRLabs May 26, 2026
fellowship-merge-bot Bot pushed a commit to polkadot-fellows/runtimes that referenced this pull request May 29, 2026
Integrates SDK release 2604.

## Contracts

- [x] @0xRVE —
[#11460](paritytech/polkadot-sdk#11460)
`CallbackHandle` check
- [x] @0xRVE —
[#11590](paritytech/polkadot-sdk#11590)
Asset-conversion precompile ·
[4759eb9](4759eb9)
- [x] @pgherveou —
[#11416](paritytech/polkadot-sdk#11416)
Auto-mapping (`AutoMap`) ·
[6dd3ddc](6dd3ddc)
#1165
- [x] @mokita-j —
[#11507](paritytech/polkadot-sdk#11507) Revive
debug enable

## Bridges

- [x] @acatangiu —
[#11694](paritytech/polkadot-sdk#11694)
`pallet_xcm_bridge_hub_router` `UnpaidExport` flag ·
[635ac29](635ac29)
- [x] @yrong —
[#11354](paritytech/polkadot-sdk#11354)
Snowbridge inbound nonce API ·
[c6fa9f2](c6fa9f2)

## Async backing / collator

- [x] @sandreim —
[#11778](paritytech/polkadot-sdk#11778)
Relay-parent offset

## Account recovery

- [x] @ggwpez —
[#10482](paritytech/polkadot-sdk#10482)
pallet-recovery modernization (HoldConsideration follow-up + re-bench) ·
[7401ea9](7401ea9)

## Penpal / integration tests

- [x] @clangenb —
[#10726](paritytech/polkadot-sdk#10726) Penpal
merged `Assets`/`ForeignAssets` (downstream fixups) ·
[3a8aa42](3a8aa42)
- [x] @clangenb — Encointer pallet integration 2604: Revert this
afterwards c944b09

## General

- [ ] Re-benchmark weights #1163 
- [x] Check for in-code TODOs
- [x] Check for all migrations

---------

Signed-off-by: Oliver Tale-Yazdi <oliver.tale-yazdi@parity.io>
Signed-off-by: Adrian Catangiu <adrian@parity.io>
Co-authored-by: Ankan <10196091+Ank4n@users.noreply.github.com>
Co-authored-by: clangenb <37865735+clangenb@users.noreply.github.com>
Co-authored-by: Christian Langenbacher <clangenb@pm.me>
Co-authored-by: Monica Jin <monicachenjin@gmail.com>
Co-authored-by: Adrian Catangiu <adrian@parity.io>
Co-authored-by: Andrei Trandafir <142614787+andreitrand@users.noreply.github.com>
Co-authored-by: Christian Langenbacher <clangenb+gh@protonmail.ch>
Co-authored-by: Paolo La Camera <paolo@parity.io>
Co-authored-by: Branislav Kontur <bkontur@gmail.com>
Co-authored-by: GitHub Action <action@github.com>
@rachsrl rachsrl moved this from In progress to Waiting for fix in Security Audit (PRs) - SRLabs Jun 9, 2026
Sign up for free to join this conversation on GitHub. Already have an account? Sign in to comment

Labels

T2-pallets This PR/Issue is related to a particular pallet.

Projects

Status: Done
Status: Waiting for fix

Development

Successfully merging this pull request may close these issues.

7 participants