Skip to content

Commit 2ff6c12

Browse files
committed
Merge branch 'FI-735' into 'master'
feat(FI-735) [icrc index-ng] fix oldest_tx_id and add tests 1. efficient way to find oldest_tx_id 2. add tests See merge request dfinity-lab/public/ic!12639
2 parents 58bb6f2 + 91ede01 commit 2ff6c12

File tree

2 files changed

+76
-9
lines changed

2 files changed

+76
-9
lines changed

rs/rosetta-api/icrc1/index-ng/src/main.rs

Lines changed: 11 additions & 9 deletions
Original file line numberDiff line numberDiff line change
@@ -592,17 +592,19 @@ fn encoded_block_bytes_to_flat_transaction(
592592
}
593593

594594
fn get_oldest_tx_id(account: Account) -> Option<BlockIndex64> {
595-
// TODO: there is no easy way to get the oldest_tx_id so we traverse
596-
// all the transaction of the account for now. This will be
597-
// fixed in future by storying the oldest_tx_id somewhere and
598-
// replace the body of this function.
599-
let first_key = account_block_ids_key(account, u64::MAX);
595+
// There is no easy way to get the oldest index for an account
596+
// in one step. Instead, we do it in two steps:
597+
// 1. check if index 0 is owned by the account
598+
// 2. if not then return the oldest index of the account that
599+
// is not 0 via iter_upper_bound
600600
let last_key = account_block_ids_key(account, 0);
601601
with_account_block_ids(|account_block_ids| {
602-
account_block_ids
603-
.range(first_key..=last_key)
604-
.last()
605-
.map(|(k, _)| k.1 .0)
602+
account_block_ids.get(&last_key).map(|_| 0).or_else(|| {
603+
account_block_ids
604+
.iter_upper_bound(&last_key)
605+
.find(|((account_bytes, _), _)| account_bytes == &last_key.0)
606+
.map(|(key, _)| key.1 .0)
607+
})
606608
})
607609
}
608610

rs/rosetta-api/icrc1/index-ng/tests/tests.rs

Lines changed: 65 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -783,3 +783,68 @@ fn test_post_upgrade_start_timer() {
783783
transfer(env, ledger_id, account(1, 0), account(2, 0), 2_000_000);
784784
wait_until_sync_is_completed(env, index_id, ledger_id);
785785
}
786+
787+
#[test]
788+
fn test_oldest_tx_id() {
789+
let env = &StateMachine::new();
790+
let ledger_id = install_ledger(
791+
env,
792+
vec![(account(1, 0), 10_000_000)],
793+
default_archive_options(),
794+
);
795+
let index_id = install_index(env, ledger_id);
796+
797+
// account(2, 0) and account(3, 0) have no transactions so oldest_tx_id should be None
798+
for account in [account(2, 0), account(3, 0)] {
799+
let oldest_tx_id =
800+
get_account_transactions(env, index_id, account, None, u64::MAX).oldest_tx_id;
801+
assert_eq!(None, oldest_tx_id);
802+
}
803+
804+
// account(1, 0) oldest_tx_id is 0, i.e. the mint at ledger init
805+
let oldest_tx_id =
806+
get_account_transactions(env, index_id, account(1, 0), None, u64::MAX).oldest_tx_id;
807+
assert_eq!(Some(0.into()), oldest_tx_id);
808+
809+
////
810+
// add one block for account(1, 0) and account(2, 0)
811+
transfer(env, ledger_id, account(1, 0), account(2, 0), 1_000_000);
812+
wait_until_sync_is_completed(env, index_id, ledger_id);
813+
814+
// account(1, 0) oldest_tx_id is still 0
815+
let oldest_tx_id =
816+
get_account_transactions(env, index_id, account(1, 0), None, u64::MAX).oldest_tx_id;
817+
assert_eq!(Some(0.into()), oldest_tx_id);
818+
819+
// account(2, 0) oldest_tx_id is 1, i.e. the new transfer
820+
let oldest_tx_id =
821+
get_account_transactions(env, index_id, account(2, 0), None, u64::MAX).oldest_tx_id;
822+
assert_eq!(Some(1.into()), oldest_tx_id);
823+
824+
// account(3, 0) oldest_tx_id is still None
825+
let oldest_tx_id =
826+
get_account_transactions(env, index_id, account(3, 0), None, u64::MAX).oldest_tx_id;
827+
assert_eq!(None, oldest_tx_id);
828+
829+
////
830+
// add one block for account(1, 0) and account(2, 0)
831+
// add the first block for account(3, 0)
832+
transfer(env, ledger_id, account(1, 0), account(2, 0), 2_000_000);
833+
transfer(env, ledger_id, account(1, 0), account(3, 0), 3_000_000);
834+
wait_until_sync_is_completed(env, index_id, ledger_id);
835+
836+
// account(1, 0) oldest_tx_id is still 0
837+
let oldest_tx_id =
838+
get_account_transactions(env, index_id, account(1, 0), None, u64::MAX).oldest_tx_id;
839+
assert_eq!(Some(0.into()), oldest_tx_id);
840+
841+
// account(2, 0) oldest_tx_id is still 1
842+
let oldest_tx_id =
843+
get_account_transactions(env, index_id, account(2, 0), None, u64::MAX).oldest_tx_id;
844+
assert_eq!(Some(1.into()), oldest_tx_id);
845+
846+
// account(3, 0) oldest_tx_id is 3, i.e. the last block index
847+
let oldest_tx_id =
848+
get_account_transactions(env, index_id, account(3, 0), None, u64::MAX).oldest_tx_id;
849+
assert_eq!(Some(3.into()), oldest_tx_id);
850+
}

0 commit comments

Comments
 (0)