Skip to content

Commit 91e194d

Browse files
atergasea-snake
andauthored
chore: Migrate recovery phrases to populate the new index (#3490)
* first * second * save * save * works * first * clippy * Adjust comments and return accidentally removed init_salt * Add unit tests * cleanup * Print unlikely overflow error rather than aggregate it * clippy --------- Co-authored-by: sea-snake <[email protected]>
1 parent 58ccf42 commit 91e194d

File tree

7 files changed

+560
-43
lines changed

7 files changed

+560
-43
lines changed

src/frontend/src/lib/generated/internet_identity_types.d.ts

Lines changed: 3 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -1212,6 +1212,9 @@ export interface _SERVICE {
12121212
[RegistrationId],
12131213
[] | [IdentityNumber]
12141214
>,
1215+
/**
1216+
* Looks up identity number when called with a recovery phrase
1217+
*/
12151218
'lookup_caller_identity_by_recovery_phrase' : ActorMethod<
12161219
[],
12171220
[] | [IdentityNumber]

src/internet_identity/src/main.rs

Lines changed: 82 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -13,6 +13,7 @@ use ic_canister_sig_creation::signature_map::LABEL_SIG;
1313
use ic_cdk::api::{caller, set_certified_data, trap};
1414
use ic_cdk::call;
1515
use ic_cdk_macros::{init, post_upgrade, pre_upgrade, query, update};
16+
use ic_cdk_timers::TimerId;
1617
use internet_identity_interface::archive::types::{BufferedEntry, Operation};
1718
use internet_identity_interface::http_gateway::{HttpRequest, HttpResponse};
1819
use internet_identity_interface::internet_identity::types::openid::{
@@ -25,7 +26,9 @@ use internet_identity_interface::internet_identity::types::vc_mvp::{
2526
};
2627
use internet_identity_interface::internet_identity::types::*;
2728
use serde_bytes::ByteBuf;
29+
use std::cell::RefCell;
2830
use std::collections::HashMap;
31+
use std::time::Duration;
2932
use storage::account::{AccountDelegationError, PrepareAccountDelegation};
3033
use storage::{Salt, Storage};
3134

@@ -34,6 +37,7 @@ mod anchor_management;
3437
mod archive;
3538
mod assets;
3639
mod authz_utils;
40+
mod migrations;
3741

3842
/// Type conversions between internal and external types.
3943
mod conversions;
@@ -62,6 +66,51 @@ const INTERNETCOMPUTER_ORG_ORIGIN: &str = "https://identity.internetcomputer.org
6266
const ID_AI_DOMAIN: &str = "id.ai";
6367
const ID_AI_ORIGIN: &str = "https://id.ai";
6468

69+
/// Number of anchors to process in one batch during the recovery phrase migration.
70+
pub(crate) const RECOVERY_PHRASE_MIGRATION_BATCH_SIZE: u64 = 2000;
71+
72+
/// Batch dispatch frequency to minimize the chance of DoS.
73+
pub(crate) const RECOVERY_PHRASE_MIGRATION_BATCH_BACKOFF_SECONDS: Duration = Duration::from_secs(1);
74+
75+
thread_local! {
76+
// TODO: Remove this state after the data migration is complete.
77+
pub(crate) static RECOVERY_PHRASE_MIGRATION_BATCH_ID: RefCell<u64> = const { RefCell::new(0) };
78+
pub(crate) static RECOVERY_PHRASE_MIGRATION_ERRORS: RefCell<Vec<String>> = const { RefCell::new(Vec::new()) };
79+
pub(crate) static RECOVERY_PHRASE_MIGRATION_LAST_ANCHOR_ID: RefCell<Option<u64>> = const { RefCell::new(None) };
80+
81+
static TIMER_ID: RefCell<Option<TimerId>> = const { RefCell::new(None) };
82+
}
83+
84+
/// Temporary function to list migration errors.
85+
///
86+
/// Can be called to retrieve any errors that occurred during the recovery phrase migration.
87+
#[update(hidden = true)]
88+
fn list_recovery_phrase_migration_errors() -> Vec<String> {
89+
RECOVERY_PHRASE_MIGRATION_ERRORS.with_borrow(|errors| errors.clone())
90+
}
91+
92+
/// Temporary function to fetch the current migration batch id.
93+
///
94+
/// Can be called to retrieve the current batch id of the ongoing data recovery phrase migration.
95+
///
96+
/// The special value `u64::MAX` indicates that the migration is complete.
97+
#[query(hidden = true)]
98+
fn list_recovery_phrase_migration_current_batch_id() -> u64 {
99+
RECOVERY_PHRASE_MIGRATION_BATCH_ID.with_borrow(|id| *id)
100+
}
101+
102+
/// Temporary function to count migrated recovery phrases.
103+
///
104+
/// Can be called to retrieve the number of recovery phrases indexed so far.
105+
#[query(hidden = true)]
106+
fn count_recovery_phrases() -> u64 {
107+
state::storage_borrow(|storage| {
108+
storage
109+
.lookup_anchor_with_recovery_phrase_principal_memory
110+
.len()
111+
})
112+
}
113+
65114
#[update]
66115
async fn init_salt() {
67116
state::init_salt().await;
@@ -576,13 +625,46 @@ fn init(maybe_arg: Option<InternetIdentityInit>) {
576625
initialize(maybe_arg);
577626
}
578627

628+
async fn run_periodic_tasks() {
629+
state::storage_borrow_mut(|storage| {
630+
storage.sync_anchor_indices(RECOVERY_PHRASE_MIGRATION_BATCH_SIZE);
631+
});
632+
633+
if RECOVERY_PHRASE_MIGRATION_BATCH_ID.with(|id| *id.borrow()) == u64::MAX {
634+
// Migration complete, clear timer.
635+
TIMER_ID.with_borrow_mut(|saved_timer_id| {
636+
if let Some(saved_timer_id) = *saved_timer_id {
637+
ic_cdk_timers::clear_timer(saved_timer_id);
638+
}
639+
*saved_timer_id = None;
640+
});
641+
}
642+
}
643+
644+
fn init_timers() {
645+
let new_timer_id =
646+
ic_cdk_timers::set_timer_interval(RECOVERY_PHRASE_MIGRATION_BATCH_BACKOFF_SECONDS, || {
647+
ic_cdk::spawn(run_periodic_tasks())
648+
});
649+
650+
TIMER_ID.with_borrow_mut(|saved_timer_id| {
651+
if let Some(saved_timer_id) = *saved_timer_id {
652+
ic_cdk_timers::clear_timer(saved_timer_id);
653+
}
654+
saved_timer_id.replace(new_timer_id);
655+
});
656+
}
657+
579658
#[post_upgrade]
580659
fn post_upgrade(maybe_arg: Option<InternetIdentityInit>) {
581660
state::init_from_stable_memory();
582661
// load the persistent state after initializing storage as it manages the respective stable cell
583662
state::load_persistent_state();
584663

585664
initialize(maybe_arg);
665+
666+
// TODO: Remove the data migration.
667+
init_timers();
586668
}
587669

588670
fn initialize(maybe_arg: Option<InternetIdentityInit>) {
Lines changed: 1 addition & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -0,0 +1 @@
1+
pub mod sync_anchor_indices;

0 commit comments

Comments
 (0)