@@ -554,6 +554,7 @@ after_frag( fd_shred_ctx_t * ctx,
554
554
const ulong fanout = 200UL ;
555
555
fd_shred_dest_idx_t _dests [ 200 * (FD_REEDSOL_DATA_SHREDS_MAX + FD_REEDSOL_PARITY_SHREDS_MAX ) ];
556
556
557
+ fd_bmtree_node_t out_merkle_root [1 ];
557
558
if ( FD_LIKELY ( ctx -> in_kind [ in_idx ]== IN_KIND_NET ) ) {
558
559
uchar * shred_buffer = ctx -> shred_buffer ;
559
560
ulong shred_buffer_sz = ctx -> shred_buffer_sz ;
@@ -569,7 +570,6 @@ after_frag( fd_shred_ctx_t * ctx,
569
570
570
571
fd_fec_set_t const * out_fec_set [1 ];
571
572
fd_shred_t const * out_shred [1 ];
572
- fd_bmtree_node_t out_merkle_root [1 ];
573
573
574
574
long add_shred_timing = - fd_tickcount ();
575
575
int rv = fd_fec_resolver_add_shred ( ctx -> resolver , shred , shred_buffer_sz , slot_leader -> uc , out_fec_set , out_shred , out_merkle_root );
@@ -594,13 +594,25 @@ after_frag( fd_shred_ctx_t * ctx,
594
594
for ( ulong j = 0UL ; j < * max_dest_cnt ; j ++ ) send_shred ( ctx , * out_shred , sdest , dests [ j ], ctx -> tsorig );
595
595
} while ( 0 );
596
596
597
- if ( FD_LIKELY ( ctx -> blockstore && rv == FD_FEC_RESOLVER_SHRED_OKAY ) ) { /* optimize for the compiler - branch predictor will still be correct */
597
+ if ( FD_LIKELY ( ctx -> blockstore ) ) { /* always true or false depending on the topo, so hint to the compiler optimize this branch */
598
+
599
+ /* Construct the sig. */
600
+
601
+ int is_code = fd_shred_is_code ( fd_shred_type ( shred -> variant ) );
602
+ uint shred_idx_or_data_cnt = shred -> idx ;
603
+ if ( FD_LIKELY ( is_code ) ) shred_idx_or_data_cnt = shred -> code .data_cnt ; /* optimize for code_cnt >= data_cnt */
604
+ ulong sig = fd_disco_shred_replay_sig ( 0 , is_code , shred -> slot , shred -> fec_set_idx , shred_idx_or_data_cnt );
605
+
606
+ /* Copy the shred header into the frag. */
607
+
598
608
uchar * buf = fd_chunk_to_laddr ( ctx -> replay_out_mem , ctx -> replay_out_chunk );
599
609
ulong sz = fd_shred_header_sz ( shred -> variant );
600
610
fd_memcpy ( buf , shred , sz );
601
- ulong tspub = fd_frag_meta_ts_comp ( fd_tickcount () );
602
- ulong replay_sig = fd_disco_shred_replay_sig ( shred -> slot , shred -> idx , shred -> fec_set_idx , fd_shred_is_code ( fd_shred_type ( shred -> variant ) ), 0 );
603
- fd_stem_publish ( stem , REPLAY_OUT_IDX , replay_sig , ctx -> replay_out_chunk , sz , 0UL , ctx -> tsorig , tspub );
611
+
612
+ /* Publish the frag. */
613
+
614
+ ulong tspub = fd_frag_meta_ts_comp ( fd_tickcount () );
615
+ fd_stem_publish ( stem , REPLAY_OUT_IDX , sig , ctx -> replay_out_chunk , sz , 0UL , ctx -> tsorig , tspub );
604
616
ctx -> replay_out_chunk = fd_dcache_compact_next ( ctx -> replay_out_chunk , sz , ctx -> replay_out_chunk0 , ctx -> replay_out_wmark );
605
617
}
606
618
}
@@ -642,28 +654,43 @@ after_frag( fd_shred_ctx_t * ctx,
642
654
ulong sz3 = sizeof (fd_shred34_t ) - (34UL - s34 [ 3 ].shred_cnt )* FD_SHRED_MAX_SZ ;
643
655
644
656
if ( FD_LIKELY ( ctx -> blockstore ) ) {
645
- /* If the shred has a completes flag, then in the replay tile it
646
- will do immediate polling for shreds in that FEC set, under
647
- the assumption that they live in the blockstore. When a shred
648
- completes a FEC set, we need to add the shreds to the
649
- blockstore before we notify replay of a completed FEC set.
650
- Replay does not poll the blockstore for shreds on notifies of
651
- a regular non-completing shred. */
657
+
658
+ /* Insert shreds into the blockstore. Note we do this regardless of
659
+ whether the shreds are for one of our leader slots or not. Even
660
+ though there is a separate link that directly connects pack and
661
+ replay when we are leader, we still need the shreds in the
662
+ blockstore to, for example, serve repair requests. */
652
663
653
664
for ( ulong i = 0UL ; i < set -> data_shred_cnt ; i ++ ) {
654
665
fd_shred_t const * data_shred = (fd_shred_t const * )fd_type_pun_const ( set -> data_shreds [ i ] );
655
666
fd_blockstore_shred_insert ( ctx -> blockstore , data_shred );
656
667
}
668
+
657
669
if ( FD_LIKELY ( ctx -> in_kind [ in_idx ]== IN_KIND_NET ) ) {
658
- /* Shred came from block we didn't produce. This is not our leader
659
- slot. */
660
- fd_shred_t const * shred = (fd_shred_t const * )fd_type_pun_const ( ctx -> shred_buffer );
670
+
671
+ /* Additionally, if the shreds are not for our leader slot (ie.
672
+ receiving the shred via net) publish a notification to replay
673
+ that the FEC set is complete.
674
+
675
+ Note we intentionally insert shreds into the blockstore before
676
+ notifying replay. This is because the replay tile immediately
677
+ polls for shreds in the blockstore upon receiving a FEC set
678
+ complete notification. */
679
+
680
+ fd_shred_t const * last = (fd_shred_t const * )fd_type_pun_const ( set -> data_shreds [ set -> data_shred_cnt - 1 ] );
681
+ int data_completes = last -> data .flags & FD_SHRED_DATA_FLAG_DATA_COMPLETE ;
682
+ ulong sig = fd_disco_shred_replay_sig ( 1 , data_completes , last -> slot , last -> fec_set_idx , last -> data .parent_off );
683
+
684
+ /* Copy the merkle root and chained merkle root of the FEC set
685
+ into the frag (64 bytes). */
686
+
661
687
uchar * buf = fd_chunk_to_laddr ( ctx -> replay_out_mem , ctx -> replay_out_chunk );
662
- ulong sz = fd_shred_header_sz ( shred -> variant );
663
- fd_memcpy ( buf , shred , sz );
664
- ulong tspub = fd_frag_meta_ts_comp ( fd_tickcount () );
665
- ulong replay_sig = fd_disco_shred_replay_sig ( shred -> slot , shred -> idx , shred -> fec_set_idx , fd_shred_is_code ( fd_shred_type ( shred -> variant ) ), 1 );
666
- fd_stem_publish ( stem , REPLAY_OUT_IDX , replay_sig , ctx -> replay_out_chunk , sz , 0UL , ctx -> tsorig , tspub );
688
+ ulong sz = fd_shred_header_sz ( last -> variant );
689
+ memcpy ( buf , out_merkle_root , FD_SHRED_MERKLE_ROOT_SZ );
690
+ memcpy ( buf + FD_SHRED_MERKLE_ROOT_SZ , (uchar const * )last + fd_shred_chain_off ( last -> variant ), FD_SHRED_MERKLE_ROOT_SZ );
691
+
692
+ ulong tspub = fd_frag_meta_ts_comp ( fd_tickcount () );
693
+ fd_stem_publish ( stem , REPLAY_OUT_IDX , sig , ctx -> replay_out_chunk , sz , 0UL , ctx -> tsorig , tspub );
667
694
ctx -> replay_out_chunk = fd_dcache_compact_next ( ctx -> replay_out_chunk , sz , ctx -> replay_out_chunk0 , ctx -> replay_out_wmark );
668
695
}
669
696
}
0 commit comments