Skip to content

Commit ba6e668

Browse files
committed
Optimize data storage of vk heights
1 parent 339ce75 commit ba6e668

File tree

3 files changed

+61
-84
lines changed

3 files changed

+61
-84
lines changed

crates/shielded_token/src/masp/shielded_sync/dispatcher.rs

Lines changed: 28 additions & 79 deletions
Original file line numberDiff line numberDiff line change
@@ -19,10 +19,9 @@ use namada_core::control_flow::time::{Duration, LinearBackoff, Sleep};
1919
use namada_core::hints;
2020
use namada_core::task_env::TaskSpawner;
2121
use namada_io::{MaybeSend, MaybeSync, ProgressBar};
22-
use namada_tx::IndexedTx;
2322
use namada_wallet::{DatedKeypair, DatedSpendingKey};
2423

25-
use super::utils::{IndexedNoteEntry, MaspClient, MaspIndexedTx, MaspTxKind};
24+
use super::utils::{IndexedNoteEntry, MaspClient, MaspIndexedTx};
2625
use crate::masp::shielded_sync::trial_decrypt;
2726
use crate::masp::utils::{
2827
DecryptedData, Fetched, RetryStrategy, TrialDecrypted, blocks_left_to_fetch,
@@ -390,7 +389,9 @@ where
390389
for (vk, _) in vk_heights
391390
.iter()
392391
// NB: skip keys that are synced past the given `indexed_tx`
393-
.filter(|(_vk, h)| h.as_ref() < Some(&masp_indexed_tx))
392+
.filter(|&(_vk, &vk_synced_height)| {
393+
vk_synced_height < masp_indexed_tx.indexed_tx.block_height
394+
})
394395
{
395396
for (note_pos_offset, (note, pa, memo)) in self
396397
.cache
@@ -411,21 +412,17 @@ where
411412
std::mem::swap(&mut vk_heights, &mut self.ctx.vk_heights);
412413
}
413414

414-
for (_, h) in self
415+
for vk_synced_height in self
415416
.ctx
416417
.vk_heights
417-
.iter_mut()
418+
.values_mut()
418419
// NB: skip keys that are synced past the last input height
419-
.filter(|(_vk, h)| {
420-
h.as_ref().map(|itx| &itx.indexed_tx.block_height)
421-
< Some(last_query_height)
420+
.filter(|&&mut vk_synced_height| {
421+
vk_synced_height < *last_query_height
422422
})
423423
{
424424
// NB: the entire block is synced
425-
*h = Some(MaspIndexedTx {
426-
indexed_tx: IndexedTx::entire_block(*last_query_height),
427-
kind: MaspTxKind::Transfer,
428-
});
425+
*vk_synced_height = *last_query_height;
429426
}
430427

431428
self.ctx.tree.as_mut().garbage_collect_ommers();
@@ -448,19 +445,10 @@ where
448445
})
449446
.chain(fvks.iter().copied())
450447
{
451-
if let Some(h) = self.ctx.vk_heights.entry(vk.key).or_default() {
452-
let birthday = IndexedTx::entire_block(vk.birthday);
453-
if birthday > h.indexed_tx {
454-
h.indexed_tx = birthday;
455-
}
456-
} else if vk.birthday >= BlockHeight::first() {
457-
self.ctx.vk_heights.insert(
458-
vk.key,
459-
Some(MaspIndexedTx {
460-
indexed_tx: IndexedTx::entire_block(vk.birthday),
461-
kind: MaspTxKind::Transfer,
462-
}),
463-
);
448+
let synced_height = self.ctx.vk_heights.entry(vk.key).or_default();
449+
450+
if vk.birthday > *synced_height {
451+
*synced_height = vk.birthday;
464452
}
465453
}
466454

@@ -667,8 +655,9 @@ where
667655
}
668656

669657
fn spawn_trial_decryptions(&self, itx: MaspIndexedTx, tx: &Transaction) {
670-
for (vk, vk_height) in self.ctx.vk_heights.iter() {
671-
let key_is_outdated = vk_height.as_ref() < Some(&itx);
658+
for (vk, vk_synced_height) in self.ctx.vk_heights.iter() {
659+
let key_is_outdated =
660+
*vk_synced_height < itx.indexed_tx.block_height;
672661
let cached = self.cache.trial_decrypted.get(&itx, vk).is_some();
673662

674663
if key_is_outdated && !cached {
@@ -743,6 +732,7 @@ mod dispatcher_tests {
743732
use namada_wallet::StoredKeypair;
744733
use tempfile::tempdir;
745734

735+
use super::super::utils::MaspTxKind;
746736
use super::*;
747737
use crate::masp::fs::FsShieldedUtils;
748738
use crate::masp::test_utils::{
@@ -773,9 +763,9 @@ mod dispatcher_tests {
773763
.run(|s| async {
774764
let mut dispatcher = config.dispatcher(s, &utils).await;
775765
dispatcher.ctx.vk_heights =
776-
BTreeMap::from([(arbitrary_vk(), None)]);
766+
BTreeMap::from([(arbitrary_vk(), BlockHeight(0))]);
777767
// fill up the dispatcher's cache
778-
for h in 0u64..10 {
768+
for h in 1u64..10 {
779769
let itx = MaspIndexedTx {
780770
indexed_tx: IndexedTx {
781771
block_height: h.into(),
@@ -796,19 +786,14 @@ mod dispatcher_tests {
796786
dispatcher
797787
.apply_cache_to_shielded_context(&InitialState {
798788
last_witnessed_tx: None,
799-
start_height: Default::default(),
789+
start_height: BlockHeight::first(),
800790
last_query_height: 9.into(),
801791
})
802792
.expect("Test failed");
803793
assert!(dispatcher.cache.fetched.is_empty());
804794
assert!(dispatcher.cache.trial_decrypted.is_empty());
805-
let expected = BTreeMap::from([(
806-
arbitrary_vk(),
807-
Some(MaspIndexedTx {
808-
indexed_tx: IndexedTx::entire_block(9.into()),
809-
kind: MaspTxKind::Transfer,
810-
}),
811-
)]);
795+
let expected =
796+
BTreeMap::from([(arbitrary_vk(), BlockHeight(9))]);
812797
assert_eq!(expected, dispatcher.ctx.vk_heights);
813798
})
814799
.await;
@@ -985,20 +970,13 @@ mod dispatcher_tests {
985970

986971
// the min height here should be 1, since
987972
// this vk hasn't decrypted any note yet
988-
shielded_ctx.vk_heights.insert(vk, None);
973+
shielded_ctx.vk_heights.insert(vk, BlockHeight(0));
989974

990975
let height = shielded_ctx.min_height_to_sync_from().unwrap();
991976
assert_eq!(height, BlockHeight(1));
992977

993978
// let's bump the vk height
994-
*shielded_ctx.vk_heights.get_mut(&vk).unwrap() = Some(MaspIndexedTx {
995-
indexed_tx: IndexedTx {
996-
block_height: 6.into(),
997-
block_index: TxIndex(0),
998-
batch_index: None,
999-
},
1000-
kind: MaspTxKind::Transfer,
1001-
});
979+
*shielded_ctx.vk_heights.get_mut(&vk).unwrap() = BlockHeight(6);
1002980

1003981
// the min height should now be 6
1004982
let height = shielded_ctx.min_height_to_sync_from().unwrap();
@@ -1128,13 +1106,7 @@ mod dispatcher_tests {
11281106
]);
11291107

11301108
assert_eq!(keys, expected);
1131-
assert_eq!(
1132-
*ctx.vk_heights[&vk.key].as_ref().unwrap(),
1133-
MaspIndexedTx {
1134-
indexed_tx: IndexedTx::entire_block(2.into(),),
1135-
kind: MaspTxKind::Transfer
1136-
}
1137-
);
1109+
assert_eq!(ctx.vk_heights[&vk.key], BlockHeight(2));
11381110
assert_eq!(ctx.note_map.len(), 2);
11391111
})
11401112
.await;
@@ -1293,6 +1265,7 @@ mod dispatcher_tests {
12931265
})
12941266
.await;
12951267
}
1268+
12961269
/// Test the the birthdays of keys are properly reflected in the key
12971270
/// sync heights when starting shielded sync.
12981271
#[tokio::test(flavor = "multi_thread", worker_threads = 2)]
@@ -1344,19 +1317,7 @@ mod dispatcher_tests {
13441317
.values()
13451318
.cloned()
13461319
.collect::<Vec<_>>();
1347-
assert_eq!(
1348-
birthdays,
1349-
vec![
1350-
Some(MaspIndexedTx {
1351-
indexed_tx: IndexedTx::entire_block(BlockHeight(30)),
1352-
kind: MaspTxKind::Transfer
1353-
}),
1354-
Some(MaspIndexedTx {
1355-
indexed_tx: IndexedTx::entire_block(BlockHeight(10)),
1356-
kind: MaspTxKind::Transfer
1357-
})
1358-
]
1359-
);
1320+
assert_eq!(birthdays, vec![BlockHeight(30), BlockHeight(10),]);
13601321

13611322
// Test two cases:
13621323
// * A birthday is less than the synced height of key
@@ -1391,18 +1352,6 @@ mod dispatcher_tests {
13911352
.values()
13921353
.cloned()
13931354
.collect::<Vec<_>>();
1394-
assert_eq!(
1395-
birthdays,
1396-
vec![
1397-
Some(MaspIndexedTx {
1398-
indexed_tx: IndexedTx::entire_block(BlockHeight(60)),
1399-
kind: MaspTxKind::Transfer
1400-
}),
1401-
Some(MaspIndexedTx {
1402-
indexed_tx: IndexedTx::entire_block(BlockHeight(10)),
1403-
kind: MaspTxKind::Transfer
1404-
})
1405-
]
1406-
)
1355+
assert_eq!(birthdays, vec![BlockHeight(60), BlockHeight(10),])
14071356
}
14081357
}

crates/shielded_token/src/masp/shielded_wallet.rs

Lines changed: 9 additions & 3 deletions
Original file line numberDiff line numberDiff line change
@@ -184,7 +184,7 @@ pub struct ShieldedWallet<U: ShieldedUtils> {
184184
pub tree: BridgeTree,
185185
/// Maps viewing keys to the block height to which they are synced.
186186
/// In particular, the height given by the value *has been scanned*.
187-
pub vk_heights: BTreeMap<ViewingKey, Option<MaspIndexedTx>>,
187+
pub vk_heights: BTreeMap<ViewingKey, BlockHeight>,
188188
/// The set of note positions that have been spent
189189
pub spents: HashSet<NotePosition>,
190190
/// Maps viewing keys to applicable note positions
@@ -329,8 +329,14 @@ impl<U: ShieldedUtils + MaybeSend + MaybeSync> ShieldedWallet<U> {
329329
.to_string(),
330330
));
331331
};
332-
Ok(maybe_least_synced_vk_height
333-
.map_or_else(BlockHeight::first, |itx| itx.indexed_tx.block_height))
332+
333+
Ok(if maybe_least_synced_vk_height == BlockHeight(0) {
334+
// NB: Height 0 is a sentinel, we must return height 1 instead
335+
// as the first height to sync from
336+
BlockHeight::first()
337+
} else {
338+
maybe_least_synced_vk_height
339+
})
334340
}
335341

336342
#[allow(missing_docs)]

crates/shielded_token/src/masp/wallet_migrations.rs

Lines changed: 24 additions & 2 deletions
Original file line numberDiff line numberDiff line change
@@ -264,7 +264,18 @@ pub mod v0 {
264264
&wallet.tree,
265265
&wallet.witness_map,
266266
),
267-
vk_heights: wallet.vk_heights,
267+
vk_heights: wallet
268+
.vk_heights
269+
.into_iter()
270+
.map(|(vk, itx)| {
271+
(
272+
vk,
273+
itx.map_or(0u64.into(), |itx| {
274+
itx.indexed_tx.block_height
275+
}),
276+
)
277+
})
278+
.collect(),
268279
pos_map: wallet
269280
.pos_map
270281
.into_iter()
@@ -396,7 +407,18 @@ pub mod v1 {
396407
&wallet.tree,
397408
&wallet.witness_map,
398409
),
399-
vk_heights: wallet.vk_heights,
410+
vk_heights: wallet
411+
.vk_heights
412+
.into_iter()
413+
.map(|(vk, itx)| {
414+
(
415+
vk,
416+
itx.map_or(0u64.into(), |itx| {
417+
itx.indexed_tx.block_height
418+
}),
419+
)
420+
})
421+
.collect(),
400422
pos_map: wallet
401423
.pos_map
402424
.into_iter()

0 commit comments

Comments
 (0)