@@ -105,6 +105,26 @@ impl CollatorStdImpl {
105
105
} ;
106
106
let created_by = author. to_bytes ( ) . into ( ) ;
107
107
108
+ let is_first_block_after_prev_master = is_first_block_after_prev_master (
109
+ prev_shard_data. blocks_ids ( ) [ 0 ] , // TODO: consider split/merge
110
+ & mc_data. shards ,
111
+ ) ;
112
+ let part_stat_ranges = if is_first_block_after_prev_master && mc_data. block_id . seqno > 0 {
113
+ if next_block_id_short. is_masterchain ( ) {
114
+ self . mc_compute_part_stat_ranges (
115
+ & mc_data,
116
+ & next_block_id_short,
117
+ top_shard_blocks_info. clone ( ) . unwrap ( ) ,
118
+ )
119
+ . await ?
120
+ } else {
121
+ self . compute_part_stat_ranges ( & mc_data, & next_block_id_short)
122
+ . await ?
123
+ }
124
+ } else {
125
+ None
126
+ } ;
127
+
108
128
let collation_data = self . create_collation_data (
109
129
next_block_id_short,
110
130
next_chain_time,
@@ -117,18 +137,6 @@ impl CollatorStdImpl {
117
137
let anchors_cache = std:: mem:: take ( & mut self . anchors_cache ) ;
118
138
let block_serializer_cache = self . block_serializer_cache . clone ( ) ;
119
139
120
- let is_first_block_after_prev_master = is_first_block_after_prev_master (
121
- prev_shard_data. blocks_ids ( ) [ 0 ] , // TODO: consider split/merge
122
- & mc_data. shards ,
123
- ) ;
124
-
125
- let part_stat_ranges = if is_first_block_after_prev_master && mc_data. block_id . seqno > 0 {
126
- self . compute_part_stat_ranges ( & mc_data, & collation_data. block_id_short )
127
- . await ?
128
- } else {
129
- None
130
- } ;
131
-
132
140
let state = Box :: new ( ActualState {
133
141
collation_config,
134
142
collation_data,
@@ -1199,27 +1207,34 @@ impl CollatorStdImpl {
1199
1207
) ;
1200
1208
}
1201
1209
1210
+ /// Collect ranges for loading statistics if current block is first after master
1211
+ /// Using previous masterchain block diff for range
1212
+ /// and other shards diffs between previous masterchain block - 1 and previous masterchain block
1202
1213
async fn compute_part_stat_ranges (
1203
1214
& self ,
1204
1215
mc_data : & McData ,
1205
1216
block_id_short : & BlockIdShort ,
1206
1217
) -> Result < Option < Vec < QueueShardBoundedRange > > > {
1207
1218
let mc_block_id = mc_data. block_id ;
1219
+
1208
1220
let prev_mc_block_id = mc_data
1209
1221
. prev_mc_block_id
1210
1222
. context ( "Prev MC block must be present" ) ?;
1211
1223
1212
1224
if prev_mc_block_id. seqno + 1 != mc_block_id. seqno {
1213
- bail ! (
1225
+ tracing:: error!(
1226
+ target: tracing_targets:: COLLATOR ,
1214
1227
"Prev MC block ID has an incorrect sequence. Prev: {prev_mc_block_id:?}. \
1215
1228
Current: {mc_block_id:?}"
1216
1229
) ;
1230
+ return Ok ( None ) ;
1217
1231
}
1218
1232
1219
1233
let prev_mc_state = self
1220
1234
. state_node_adapter
1221
1235
. load_state ( & prev_mc_block_id)
1222
1236
. await ?;
1237
+
1223
1238
let prev_mc_block_shards: FastHashMap < ShardIdent , ShardDescriptionShort > = prev_mc_state
1224
1239
. state_extra ( )
1225
1240
. cloned ( ) ?
@@ -1257,6 +1272,10 @@ impl CollatorStdImpl {
1257
1272
return Ok ( None ) ;
1258
1273
} ;
1259
1274
1275
+ if prev_descr. seqno == 0 {
1276
+ return Ok ( None ) ;
1277
+ }
1278
+
1260
1279
let Some ( first_diff_msg) = self
1261
1280
. get_max_message ( & prev_descr. get_block_id ( * shard) )
1262
1281
. await
@@ -1282,7 +1301,96 @@ impl CollatorStdImpl {
1282
1301
Ok ( Some ( ranges) )
1283
1302
}
1284
1303
1285
- // Async helper function that retrieves max_message from either MQ or state diff
1304
+ /// Collect ranges for loading cumulative statistics if collation block is master
1305
+ /// Using range from previous masterchain block diff
1306
+ /// and diffs between previous masterchain top blocks and current top blocks
1307
+ async fn mc_compute_part_stat_ranges (
1308
+ & self ,
1309
+ mc_data : & McData ,
1310
+ block_id_short : & BlockIdShort ,
1311
+ top_shard_blocks_info : Vec < TopBlockDescription > ,
1312
+ ) -> Result < Option < Vec < QueueShardBoundedRange > > > {
1313
+ let prev_mc_block_id = mc_data. block_id ;
1314
+
1315
+ if prev_mc_block_id. seqno + 1 != block_id_short. seqno {
1316
+ tracing:: error!(
1317
+ target: tracing_targets:: COLLATOR ,
1318
+ "Prev MC block ID has an incorrect sequence. Prev: {prev_mc_block_id:?}.
1319
+ Current: {:?}" ,
1320
+ block_id_short. seqno
1321
+ ) ;
1322
+ return Ok ( None ) ;
1323
+ }
1324
+
1325
+ let prev_mc_state = self
1326
+ . state_node_adapter
1327
+ . load_state ( & prev_mc_block_id)
1328
+ . await ?;
1329
+
1330
+ let prev_mc_block_shards: FastHashMap < ShardIdent , ShardDescriptionShort > = prev_mc_state
1331
+ . state_extra ( )
1332
+ . cloned ( ) ?
1333
+ . shards
1334
+ . as_vec ( ) ?
1335
+ . iter ( )
1336
+ . cloned ( )
1337
+ . collect ( ) ;
1338
+
1339
+ let mut ranges = Vec :: < QueueShardBoundedRange > :: new ( ) ;
1340
+
1341
+ // Load max_message from masterchain block diff
1342
+ let Some ( master_max_msg) = self
1343
+ . get_max_message ( & prev_mc_block_id)
1344
+ . await
1345
+ . context ( "loading diff for mc block" ) ?
1346
+ else {
1347
+ return Ok ( None ) ;
1348
+ } ;
1349
+
1350
+ ranges. push ( QueueShardBoundedRange {
1351
+ shard_ident : prev_mc_block_id. shard ,
1352
+ from : Bound :: Included ( master_max_msg) ,
1353
+ to : Bound :: Included ( master_max_msg) ,
1354
+ } ) ;
1355
+
1356
+ // Iterate over all updated shard blocks and add their diff ranges
1357
+ for top_block_description in top_shard_blocks_info {
1358
+ let Some ( prev_descr) = prev_mc_block_shards. get ( & top_block_description. block_id . shard )
1359
+ else {
1360
+ tracing:: warn!( target: tracing_targets:: COLLATOR , "prev_mc_block_shards not found: {:?}" , top_block_description. block_id. shard) ;
1361
+ return Ok ( None ) ;
1362
+ } ;
1363
+
1364
+ if prev_descr. seqno == 0 {
1365
+ return Ok ( None ) ;
1366
+ }
1367
+
1368
+ let Some ( first_diff_msg) = self
1369
+ . get_max_message ( & prev_descr. get_block_id ( top_block_description. block_id . shard ) )
1370
+ . await
1371
+ . context ( "loading first diff msg" ) ?
1372
+ else {
1373
+ return Ok ( None ) ;
1374
+ } ;
1375
+ let Some ( last_diff_msg) = self
1376
+ . get_max_message ( & top_block_description. block_id )
1377
+ . await
1378
+ . context ( "loading last diff msg" ) ?
1379
+ else {
1380
+ return Ok ( None ) ;
1381
+ } ;
1382
+
1383
+ ranges. push ( QueueShardBoundedRange {
1384
+ shard_ident : top_block_description. block_id . shard ,
1385
+ from : Bound :: Excluded ( first_diff_msg) ,
1386
+ to : Bound :: Included ( last_diff_msg) ,
1387
+ } ) ;
1388
+ }
1389
+
1390
+ Ok ( Some ( ranges) )
1391
+ }
1392
+
1393
+ /// Helper function that retrieves `max_message` from either MQ or state diff
1286
1394
async fn get_max_message ( & self , block_id : & BlockId ) -> Result < Option < QueueKey > > {
1287
1395
if let Some ( diff) =
1288
1396
self . mq_adapter
0 commit comments