walletkit_core/authenticator/
with_storage.rs1use crate::error::WalletKitError;
2
3use super::Authenticator;
4
5use world_id_core::primitives::merkle::AccountInclusionProof;
6use world_id_core::primitives::TREE_DEPTH;
7
8const MERKLE_PROOF_VALIDITY_SECONDS: u64 = 60 * 15;
10
11#[uniffi::export]
12impl Authenticator {
13 pub fn init_storage(&self, now: u64) -> Result<(), WalletKitError> {
19 self.store.init(self.leaf_index(), now)?;
20 Ok(())
21 }
22
23 pub fn destroy_storage(&self) -> Result<(), WalletKitError> {
33 self.store.destroy_storage()?;
34 Ok(())
35 }
36}
37
38impl Authenticator {
39 #[tracing::instrument(
45 target = "walletkit_latency",
46 name = "indexer_inclusion_proof",
47 skip_all
48 )]
49 pub(crate) async fn fetch_inclusion_proof_with_cache(
50 &self,
51 now: u64,
52 ) -> Result<AccountInclusionProof<TREE_DEPTH>, WalletKitError> {
53 if let Some(account_inclusion_proof) = self.store.merkle_cache_get(now)? {
55 if account_inclusion_proof.inclusion_proof.leaf_index == self.leaf_index() {
56 return Ok(account_inclusion_proof);
57 }
58 }
59
60 let account_inclusion_proof = self.inner.fetch_inclusion_proof().await?;
62
63 if let Err(e) = self.store.merkle_cache_put(
64 &account_inclusion_proof,
65 now,
66 MERKLE_PROOF_VALIDITY_SECONDS,
67 ) {
68 tracing::error!("Failed to cache Merkle inclusion proof: {e}");
69 }
70
71 Ok(account_inclusion_proof)
72 }
73}
74
75#[cfg(test)]
76mod tests {
77 use super::*;
78 use crate::storage::tests_utils::{
79 cleanup_test_storage, temp_root_path, InMemoryStorageProvider,
80 };
81 use crate::storage::CredentialStore;
82 use world_id_core::primitives::merkle::MerkleInclusionProof;
83 use world_id_core::primitives::AuthenticatorPublicKeySet;
84 use world_id_core::FieldElement;
85
86 #[test]
87 fn test_cached_inclusion_round_trip() {
88 let root = temp_root_path();
89 let provider = InMemoryStorageProvider::new(&root);
90 let store = CredentialStore::from_provider(&provider).expect("store");
91 store.init(42, 100).expect("init storage");
92
93 let siblings = [FieldElement::from(0u64); TREE_DEPTH];
94 let root_fe = FieldElement::from(123u64);
95 let inclusion_proof = MerkleInclusionProof::new(root_fe, 42, siblings);
96 let authenticator_pubkeys =
97 AuthenticatorPublicKeySet::new(vec![]).expect("key set");
98 let account_inclusion_proof = AccountInclusionProof {
99 inclusion_proof,
100 authenticator_pubkeys,
101 };
102
103 store
104 .merkle_cache_put(&account_inclusion_proof, 100, 60)
105 .expect("cache put");
106 let now = 110;
107 let decoded = store
108 .merkle_cache_get(now)
109 .expect("cache get")
110 .expect("cache hit");
111 assert_eq!(decoded.inclusion_proof.leaf_index, 42);
112 assert_eq!(decoded.inclusion_proof.root, root_fe);
113 assert_eq!(decoded.authenticator_pubkeys.len(), 0);
114 cleanup_test_storage(&root);
115 }
116}