@@ -2,8 +2,8 @@ use candid::{Decode, Encode, Nat};
2
2
use ic_base_types:: { CanisterId , PrincipalId } ;
3
3
use ic_icrc1_index_ng:: {
4
4
GetAccountTransactionsArgs , GetAccountTransactionsResponse , GetAccountTransactionsResult ,
5
- GetBlocksResponse , IndexArg , InitArg as IndexInitArg , ListSubaccountsArgs , TransactionWithId ,
6
- DEFAULT_MAX_BLOCKS_PER_RESPONSE ,
5
+ GetBlocksResponse , IndexArg , InitArg as IndexInitArg , ListSubaccountsArgs , Status ,
6
+ TransactionWithId , DEFAULT_MAX_BLOCKS_PER_RESPONSE ,
7
7
} ;
8
8
use ic_icrc1_ledger:: { InitArgs as LedgerInitArgs , LedgerArgument } ;
9
9
use ic_icrc1_test_utils:: { valid_transactions_strategy, CallerTransferArg } ;
@@ -12,7 +12,7 @@ use ic_state_machine_tests::StateMachine;
12
12
use icrc_ledger_types:: icrc:: generic_metadata_value:: MetadataValue as Value ;
13
13
use icrc_ledger_types:: icrc1:: account:: { Account , Subaccount } ;
14
14
use icrc_ledger_types:: icrc1:: transfer:: { BlockIndex , TransferArg , TransferError } ;
15
- use icrc_ledger_types:: icrc3:: blocks:: { BlockRange , GenericBlock , GetBlocksRequest } ;
15
+ use icrc_ledger_types:: icrc3:: blocks:: { BlockRange , GetBlocksRequest } ;
16
16
use icrc_ledger_types:: icrc3:: transactions:: { Mint , Transaction , Transfer } ;
17
17
use num_traits:: cast:: ToPrimitive ;
18
18
use proptest:: test_runner:: { Config as TestRunnerConfig , TestRunner } ;
@@ -115,6 +115,34 @@ fn account(owner: u64, subaccount: u128) -> Account {
115
115
}
116
116
}
117
117
118
+ fn status ( env : & StateMachine , index_id : CanisterId ) -> Status {
119
+ let res = env
120
+ . query ( index_id, "status" , Encode ! ( & ( ) ) . unwrap ( ) )
121
+ . expect ( "Failed to send status" )
122
+ . bytes ( ) ;
123
+ Decode ! ( & res, Status ) . expect ( "Failed to decode status response" )
124
+ }
125
+
126
+ // Helper function that calls tick on env until either
127
+ // the index canister has synced all the blocks up to the
128
+ // last one in the ledger or enough attempts passed and therefore
129
+ // it fails
130
+ fn wait_until_sync_is_completed ( env : & StateMachine , index_id : CanisterId , ledger_id : CanisterId ) {
131
+ const MAX_ATTEMPTS : u8 = 100 ; // no reason for this number
132
+ let mut num_blocks_synced = u64:: MAX ;
133
+ let mut chain_length = u64:: MAX ;
134
+ for _i in 0 ..MAX_ATTEMPTS {
135
+ env. advance_time ( Duration :: from_secs ( 60 ) ) ;
136
+ env. tick ( ) ;
137
+ num_blocks_synced = status ( env, index_id) . num_blocks_synced . 0 . to_u64 ( ) . unwrap ( ) ;
138
+ chain_length = icrc1_get_blocks ( env, ledger_id, 0 , 1 ) . chain_length ;
139
+ if num_blocks_synced == chain_length {
140
+ return ;
141
+ }
142
+ }
143
+ panic ! ( "The index canister was unable to sync all the blocks with the ledger. Number of blocks synced {} but the Ledger chain length is {}" , num_blocks_synced, chain_length) ;
144
+ }
145
+
118
146
fn icrc1_balance_of ( env : & StateMachine , canister_id : CanisterId , account : Account ) -> u64 {
119
147
let res = env
120
148
. execute_ingress ( canister_id, "icrc1_balance_of" , Encode ! ( & account) . unwrap ( ) )
@@ -127,10 +155,15 @@ fn icrc1_balance_of(env: &StateMachine, canister_id: CanisterId, account: Accoun
127
155
. expect ( "Balance must be a u64!" )
128
156
}
129
157
130
- fn icrc1_get_blocks ( env : & StateMachine , ledger_id : CanisterId ) -> Vec < GenericBlock > {
158
+ fn icrc1_get_blocks (
159
+ env : & StateMachine ,
160
+ ledger_id : CanisterId ,
161
+ start : u64 ,
162
+ length : u64 ,
163
+ ) -> icrc_ledger_types:: icrc3:: blocks:: GetBlocksResponse {
131
164
let req = GetBlocksRequest {
132
- start : 0 . into ( ) ,
133
- length : u64 :: MAX . into ( ) ,
165
+ start : start . into ( ) ,
166
+ length : length . into ( ) ,
134
167
} ;
135
168
let req = Encode ! ( & req) . expect ( "Failed to encode GetBlocksRequest" ) ;
136
169
let res = env
@@ -140,15 +173,15 @@ fn icrc1_get_blocks(env: &StateMachine, ledger_id: CanisterId) -> Vec<GenericBlo
140
173
let res = Decode ! ( & res, icrc_ledger_types:: icrc3:: blocks:: GetBlocksResponse )
141
174
. expect ( "Failed to decode GetBlocksResponse" ) ;
142
175
let mut blocks = vec ! [ ] ;
143
- for archived in res. archived_blocks {
176
+ for archived in & res. archived_blocks {
144
177
let req = GetBlocksRequest {
145
- start : archived. start ,
146
- length : archived. length ,
178
+ start : archived. start . clone ( ) ,
179
+ length : archived. length . clone ( ) ,
147
180
} ;
148
181
let req = Encode ! ( & req) . expect ( "Failed to encode GetBlocksRequest for archive node" ) ;
149
182
let canister_id = archived. callback . canister_id . as_ref ( ) . try_into ( ) . unwrap ( ) ;
150
183
let res = env
151
- . execute_ingress ( canister_id, archived. callback . method , req)
184
+ . execute_ingress ( canister_id, archived. callback . method . clone ( ) , req)
152
185
. expect ( "Failed to send get_blocks request to archive" )
153
186
. bytes ( ) ;
154
187
let res = Decode ! ( & res, BlockRange )
@@ -157,7 +190,7 @@ fn icrc1_get_blocks(env: &StateMachine, ledger_id: CanisterId) -> Vec<GenericBlo
157
190
blocks. extend ( res) ;
158
191
}
159
192
blocks. extend ( res. blocks ) ;
160
- blocks
193
+ icrc_ledger_types :: icrc3 :: blocks:: GetBlocksResponse { blocks , ..res }
161
194
}
162
195
163
196
fn get_blocks ( env : & StateMachine , index_id : CanisterId ) -> GetBlocksResponse {
@@ -256,14 +289,9 @@ fn list_subaccounts(
256
289
257
290
// Assert that the index canister contains the same blocks as the ledger
258
291
fn assert_ledger_index_parity ( env : & StateMachine , ledger_id : CanisterId , index_id : CanisterId ) {
259
- let ledger_blocks = icrc1_get_blocks ( env, ledger_id) ;
292
+ let ledger_blocks = icrc1_get_blocks ( env, ledger_id, 0 , u64 :: MAX ) ;
260
293
let index_blocks = get_blocks ( env, index_id) ;
261
- assert_eq ! ( ledger_blocks, index_blocks. blocks) ;
262
- }
263
-
264
- fn trigger_heartbeat ( env : & StateMachine ) {
265
- env. advance_time ( Duration :: from_secs ( 60 ) ) ;
266
- env. tick ( ) ;
294
+ assert_eq ! ( ledger_blocks. blocks, index_blocks. blocks) ;
267
295
}
268
296
269
297
#[ test]
@@ -276,12 +304,12 @@ fn test_ledger_growing() {
276
304
let index_id = install_index ( env, ledger_id) ;
277
305
278
306
// test initial mint block
279
- trigger_heartbeat ( env) ;
307
+ wait_until_sync_is_completed ( env, index_id , ledger_id ) ;
280
308
assert_ledger_index_parity ( env, ledger_id, index_id) ;
281
309
282
310
// test first transfer block
283
311
transfer ( env, ledger_id, account ( 1 , 0 ) , account ( 2 , 0 ) , 1 ) ;
284
- trigger_heartbeat ( env) ;
312
+ wait_until_sync_is_completed ( env, index_id , ledger_id ) ;
285
313
assert_ledger_index_parity ( env, ledger_id, index_id) ;
286
314
287
315
// test multiple blocks
@@ -292,14 +320,14 @@ fn test_ledger_growing() {
292
320
] {
293
321
transfer ( env, ledger_id, from, to, amount) ;
294
322
}
295
- trigger_heartbeat ( env) ;
323
+ wait_until_sync_is_completed ( env, index_id , ledger_id ) ;
296
324
assert_ledger_index_parity ( env, ledger_id, index_id) ;
297
325
298
326
// test archived blocks
299
327
for _i in 0 ..( ARCHIVE_TRIGGER_THRESHOLD as usize + 1 ) {
300
328
transfer ( env, ledger_id, account ( 1 , 0 ) , account ( 1 , 2 ) , 1 ) ;
301
329
}
302
- trigger_heartbeat ( env) ;
330
+ wait_until_sync_is_completed ( env, index_id , ledger_id ) ;
303
331
assert_ledger_index_parity ( env, ledger_id, index_id) ;
304
332
}
305
333
@@ -316,7 +344,7 @@ fn test_archive_indexing() {
316
344
let ledger_id = install_ledger ( env, initial_balances, default_archive_options ( ) ) ;
317
345
let index_id = install_index ( env, ledger_id) ;
318
346
319
- trigger_heartbeat ( env) ;
347
+ wait_until_sync_is_completed ( env, index_id , ledger_id ) ;
320
348
assert_ledger_index_parity ( env, ledger_id, index_id) ;
321
349
}
322
350
@@ -431,7 +459,7 @@ fn test_get_account_transactions() {
431
459
432
460
////////////
433
461
//// phase 1: only 1 mint to (1, 0)
434
- trigger_heartbeat ( env) ;
462
+ wait_until_sync_is_completed ( env, index_id , ledger_id ) ;
435
463
436
464
// account (1, 0) has one mint
437
465
let actual_txs =
@@ -446,7 +474,7 @@ fn test_get_account_transactions() {
446
474
/////////////
447
475
//// phase 2: transfer from (1, 0) to (2, 0)
448
476
transfer ( env, ledger_id, account ( 1 , 0 ) , account ( 2 , 0 ) , 1_000_000 ) ;
449
- trigger_heartbeat ( env) ;
477
+ wait_until_sync_is_completed ( env, index_id , ledger_id ) ;
450
478
451
479
// account (1, 0) has one transfer and one mint
452
480
let actual_txs =
@@ -470,7 +498,7 @@ fn test_get_account_transactions() {
470
498
//// transfer from (2, 0) to (1, 1)
471
499
transfer ( env, ledger_id, account ( 1 , 0 ) , account ( 2 , 0 ) , 2_000_000 ) ;
472
500
transfer ( env, ledger_id, account ( 2 , 0 ) , account ( 1 , 1 ) , 1_000_000 ) ;
473
- trigger_heartbeat ( env) ;
501
+ wait_until_sync_is_completed ( env, index_id , ledger_id ) ;
474
502
475
503
// account (1, 0) has two transfers and one mint
476
504
let actual_txs =
@@ -511,7 +539,7 @@ fn test_get_account_transactions_start_length() {
511
539
} )
512
540
. collect ( ) ;
513
541
514
- trigger_heartbeat ( env) ;
542
+ wait_until_sync_is_completed ( env, index_id , ledger_id ) ;
515
543
516
544
// get the most n recent transaction with start set to none
517
545
for n in 1 ..10 {
@@ -548,7 +576,7 @@ fn test_get_account_transactions_pagination() {
548
576
let ledger_id = install_ledger ( env, initial_balances, default_archive_options ( ) ) ;
549
577
let index_id = install_index ( env, ledger_id) ;
550
578
551
- trigger_heartbeat ( env) ;
579
+ wait_until_sync_is_completed ( env, index_id , ledger_id ) ;
552
580
553
581
// The index get_account_transactions endpoint returns batches of transactions
554
582
// in descending order of index, i.e. the first index returned in the result
@@ -625,7 +653,7 @@ fn test_icrc1_balance_of() {
625
653
{
626
654
icrc1_transfer ( env, ledger_id, PrincipalId ( * caller) , transfer_arg. clone ( ) ) ;
627
655
}
628
- trigger_heartbeat ( env) ;
656
+ wait_until_sync_is_completed ( env, index_id , ledger_id ) ;
629
657
630
658
for account in transactions
631
659
. iter ( )
@@ -680,7 +708,7 @@ fn test_list_subaccounts() {
680
708
let ledger_id = install_ledger ( env, initial_balances, default_archive_options ( ) ) ;
681
709
let index_id = install_index ( env, ledger_id) ;
682
710
683
- trigger_heartbeat ( env) ;
711
+ wait_until_sync_is_completed ( env, index_id , ledger_id ) ;
684
712
685
713
// list account_1.owner subaccounts when no starting subaccount is specified
686
714
assert_eq ! (
0 commit comments