Skip to content

Commit 2f6c79e

Browse files
committed
feat(repair): implement blk repair structure and API
1 parent a3e4a3d commit 2f6c79e

25 files changed

+1631
-300
lines changed

.gitignore

Lines changed: 1 addition & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -73,6 +73,7 @@ mainnet.sh
7373
localnet.sh
7474
sim.sh
7575
backtest.sh
76+
local.toml
7677

7778
# Python
7879
venv

src/ballet/shred/fd_shred.h

Lines changed: 11 additions & 3 deletions
Original file line numberDiff line numberDiff line change
@@ -149,17 +149,25 @@ FD_STATIC_ASSERT( sizeof(fd_bmtree_node_t) == FD_SHRED_MERKLE_ROOT_SZ, update FD
149149
#define FD_SHRED_DATA_FLAG_DATA_COMPLETE ((uchar)0x40)
150150

151151
/* Maximum number of data shreds in a slot, also maximum number of parity shreds in a slot */
152-
#define FD_SHRED_MAX_PER_SLOT (1 << 15UL) /* 32,768 shreds */
152+
#define FD_SHRED_BLK_MAX (1 << 15UL) /* 32,768 shreds */
153+
#define FD_SHRED_IDX_MAX (FD_SHRED_BLK_MAX - 1)
153154

154155
/* Many static bounds are specified around the assumption that this is a
155156
protocol limit on the max number of shreds in a slot. If this limit
156157
changes, all the relevant usages in other areas of the Firedancer
157158
codebase should be updated before modifying this assertion. */
158159

159-
FD_STATIC_ASSERT( FD_SHRED_MAX_PER_SLOT == 32768, check all usages before changing this limit! );
160+
FD_STATIC_ASSERT( FD_SHRED_BLK_MAX == 32768, check all usages before changing this limit! );
161+
162+
/* Many static bounds are specified around the assumption that this is a
163+
protocol limit on the max number of shreds in a slot. If this limit
164+
changes, all the relevant usages in other areas of the Firedancer
165+
codebase should be updated before modifying this assertion. */
166+
167+
FD_STATIC_ASSERT( FD_SHRED_BLK_MAX == 32768, check all usages before changing this limit! );
160168

161169
/* 36,536,320 bytes per slot */
162-
#define FD_SHRED_DATA_PAYLOAD_MAX_PER_SLOT (FD_SHRED_DATA_PAYLOAD_MAX * FD_SHRED_MAX_PER_SLOT)
170+
#define FD_SHRED_DATA_PAYLOAD_MAX_PER_SLOT (FD_SHRED_DATA_PAYLOAD_MAX * FD_SHRED_BLK_MAX)
163171

164172
/* Offset of the shred variant. Used for parsing. */
165173
#define FD_SHRED_VARIANT_OFF 0x40

src/disco/fd_disco_base.h

Lines changed: 5 additions & 5 deletions
Original file line numberDiff line numberDiff line change
@@ -186,8 +186,8 @@ fd_disco_shred_repair_shred_sig( int completes,
186186
int is_code,
187187
uint shred_idx_or_data_cnt ) {
188188
ulong slot_ul = fd_ulong_min( slot, (ulong)UINT_MAX );
189-
ulong shred_idx_or_data_cnt_ul = fd_ulong_min( (ulong)shred_idx_or_data_cnt, (ulong)FD_SHRED_MAX_PER_SLOT );
190-
ulong fec_set_idx_ul = fd_ulong_min( (ulong)fec_set_idx, (ulong)FD_SHRED_MAX_PER_SLOT );
189+
ulong shred_idx_or_data_cnt_ul = fd_ulong_min( (ulong)shred_idx_or_data_cnt, (ulong)FD_SHRED_BLK_MAX );
190+
ulong fec_set_idx_ul = fd_ulong_min( (ulong)fec_set_idx, (ulong)FD_SHRED_BLK_MAX );
191191
ulong completes_ul = !!completes;
192192
ulong is_code_ul = !!is_code;
193193

@@ -212,8 +212,8 @@ FD_FN_CONST static inline uint fd_disco_shred_repair_shred_sig_data_cnt ( ulo
212212
FD_FN_CONST static inline ulong
213213
fd_disco_shred_repair_fec_sig( ulong slot, uint fec_set_idx, uint data_cnt, int is_slot_complete, int is_batch_complete ) {
214214
ulong slot_ul = fd_ulong_min( slot, (ulong)UINT_MAX );
215-
ulong fec_set_idx_ul = fd_ulong_min( (ulong)fec_set_idx, (ulong)FD_SHRED_MAX_PER_SLOT );
216-
ulong data_cnt_ul = fd_ulong_min( (ulong)data_cnt, (ulong)FD_SHRED_MAX_PER_SLOT );
215+
ulong fec_set_idx_ul = fd_ulong_min( (ulong)fec_set_idx, (ulong)FD_SHRED_BLK_MAX );
216+
ulong data_cnt_ul = fd_ulong_min( (ulong)data_cnt, (ulong)FD_SHRED_BLK_MAX );
217217
ulong is_slot_complete_ul = !!is_slot_complete;
218218
ulong is_batch_complete_ul = !!is_batch_complete;
219219
return slot_ul << 32 | fec_set_idx_ul << 17 | data_cnt_ul << 2 | is_slot_complete_ul << 1 | is_batch_complete_ul;
@@ -242,7 +242,7 @@ fd_disco_repair_replay_sig( ulong slot, uint data_cnt, ushort parent_off, int sl
242242
| [32, 63] | [17, 31] | [1, 16] | [0]
243243
*/
244244
ulong slot_ul = fd_ulong_min( slot, (ulong)UINT_MAX );
245-
ulong data_cnt_ul = fd_ulong_min( (ulong)data_cnt, (ulong)FD_SHRED_MAX_PER_SLOT );
245+
ulong data_cnt_ul = fd_ulong_min( (ulong)data_cnt, (ulong)FD_SHRED_BLK_MAX );
246246
ulong parent_off_ul = (ulong)parent_off;
247247
ulong slot_complete_ul = !!slot_complete;
248248
return slot_ul << 32 | data_cnt_ul << 17 | parent_off_ul << 1 | slot_complete_ul;

src/disco/net/sock/fd_sock_tile.c

Lines changed: 6 additions & 6 deletions
Original file line numberDiff line numberDiff line change
@@ -188,18 +188,18 @@ privileged_init( fd_topo_t * topo,
188188
static char const * udp_port_links[] = {
189189
"net_quic", /* legacy_transaction_listen_port */
190190
"net_quic", /* quic_transaction_listen_port */
191-
"net_shred", /* shred_listen_port */
191+
"net_shred", /* shred_listen_port (turbine) */
192192
"net_gossip", /* gossip_listen_port */
193-
"net_repair", /* repair_intake_listen_port */
194-
"net_repair" /* repair_intake_listen_port */
193+
"net_shred", /* shred_listen_port (repair) */
194+
"net_repair" /* repair_serve_listen_port */
195195
};
196196
static uchar const udp_port_protos[] = {
197197
DST_PROTO_TPU_UDP, /* legacy_transaction_listen_port */
198198
DST_PROTO_TPU_QUIC, /* quic_transaction_listen_port */
199-
DST_PROTO_SHRED, /* shred_listen_port */
199+
DST_PROTO_SHRED, /* shred_listen_port (turbine) */
200200
DST_PROTO_GOSSIP, /* gossip_listen_port */
201-
DST_PROTO_REPAIR, /* repair_intake_listen_port */
202-
DST_PROTO_REPAIR /* repair_intake_listen_port */
201+
DST_PROTO_SHRED, /* shred_listen_port (repair) */
202+
DST_PROTO_REPAIR /* repair_serve_listen_port */
203203
};
204204
for( uint candidate_idx=0U; candidate_idx<6; candidate_idx++ ) {
205205
if( !udp_port_candidates[ candidate_idx ] ) continue;

src/disco/net/xdp/fd_xdp_tile.c

Lines changed: 8 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -39,6 +39,14 @@
3939

4040
#define FD_XDP_STATS_INTERVAL_NS (11e6) /* 11ms */
4141

42+
/* REPAIR_PING_SZ is the sz of a ping packet for the repair protocol.
43+
Because pings are routed to the same port as shreds without any
44+
discriminant encoding, we have to use the packet sz to interpret the
45+
payload. Note that any valid shred must be either FD_SHRED_MAX_SZ
46+
or FD_SHRED_MIN_SZ ie. will never be FD_REPAIR_PING_SZ.*/
47+
48+
#define REPAIR_PING_SZ (174UL)
49+
4250
/* fd_net_in_ctx_t contains consumer information for an incoming tango
4351
link. It is used as part of the TX path. */
4452

src/disco/shred/fd_shred_tile.c

Lines changed: 26 additions & 22 deletions
Original file line numberDiff line numberDiff line change
@@ -309,11 +309,13 @@ before_frag( fd_shred_ctx_t * ctx,
309309
ulong in_idx,
310310
ulong seq,
311311
ulong sig ) {
312-
if( FD_LIKELY( ctx->in_kind[ in_idx ]==IN_KIND_POH ) ) ctx->poh_in_expect_seq = seq+1UL;
313-
314-
if( FD_LIKELY( ctx->in_kind[ in_idx ]==IN_KIND_NET ) ) return fd_disco_netmux_sig_proto( sig )!=DST_PROTO_SHRED;
315-
else if( FD_LIKELY( ctx->in_kind[ in_idx ]==IN_KIND_POH ) ) return (fd_disco_poh_sig_pkt_type( sig )!=POH_PKT_TYPE_MICROBLOCK) &
316-
(fd_disco_poh_sig_pkt_type( sig )!=POH_PKT_TYPE_FEAT_ACT_SLOT);
312+
if( FD_LIKELY( ctx->in_kind[ in_idx ]==IN_KIND_POH ) ) {
313+
ctx->poh_in_expect_seq = seq+1UL;
314+
return (fd_disco_poh_sig_pkt_type( sig )!=POH_PKT_TYPE_MICROBLOCK) & (fd_disco_poh_sig_pkt_type( sig )!=POH_PKT_TYPE_FEAT_ACT_SLOT);
315+
}
316+
if( FD_LIKELY( ctx->in_kind[ in_idx ]==IN_KIND_NET ) ) {
317+
return (fd_disco_netmux_sig_proto( sig )!=DST_PROTO_SHRED) && (fd_disco_netmux_sig_proto( sig )!=DST_PROTO_REPAIR);
318+
}
317319
return 0;
318320
}
319321

@@ -724,22 +726,24 @@ after_frag( fd_shred_ctx_t * ctx,
724726
}
725727

726728
if( (rv==FD_FEC_RESOLVER_SHRED_OKAY) | (rv==FD_FEC_RESOLVER_SHRED_COMPLETES) ) {
727-
/* Relay this shred */
728-
ulong max_dest_cnt[1];
729-
do {
730-
/* If we've validated the shred and it COMPLETES but we can't
731-
compute the destination for whatever reason, don't forward
732-
the shred, but still send it to the blockstore. */
733-
fd_shred_dest_t * sdest = fd_stake_ci_get_sdest_for_slot( ctx->stake_ci, shred->slot );
734-
if( FD_UNLIKELY( !sdest ) ) break;
735-
fd_shred_dest_idx_t * dests = fd_shred_dest_compute_children( sdest, &shred, 1UL, ctx->scratchpad_dests, 1UL, fanout, fanout, max_dest_cnt );
736-
if( FD_UNLIKELY( !dests ) ) break;
737-
738-
send_shred( ctx, *out_shred, ctx->adtl_dest, ctx->tsorig );
739-
for( ulong j=0UL; j<*max_dest_cnt; j++ ) send_shred( ctx, *out_shred, fd_shred_dest_idx_to_dest( sdest, dests[ j ]), ctx->tsorig );
740-
} while( 0 );
741-
742-
if( FD_LIKELY( ctx->repair_out_idx!=ULONG_MAX ) ) { /* Optimize for full firedancer. The branch predictor will learn quickly if this is frankendancer instead */
729+
if( FD_LIKELY( fd_disco_netmux_sig_proto( sig ) != DST_PROTO_REPAIR ) ) {
730+
/* Relay this shred */
731+
ulong max_dest_cnt[1];
732+
do {
733+
/* If we've validated the shred and it COMPLETES but we can't
734+
compute the destination for whatever reason, don't forward
735+
the shred, but still send it to the blockstore. */
736+
fd_shred_dest_t * sdest = fd_stake_ci_get_sdest_for_slot( ctx->stake_ci, shred->slot );
737+
if( FD_UNLIKELY( !sdest ) ) break;
738+
fd_shred_dest_idx_t * dests = fd_shred_dest_compute_children( sdest, &shred, 1UL, ctx->scratchpad_dests, 1UL, fanout, fanout, max_dest_cnt );
739+
if( FD_UNLIKELY( !dests ) ) break;
740+
741+
send_shred( ctx, *out_shred, ctx->adtl_dest, ctx->tsorig );
742+
for( ulong j=0UL; j<*max_dest_cnt; j++ ) send_shred( ctx, *out_shred, fd_shred_dest_idx_to_dest( sdest, dests[ j ]), ctx->tsorig );
743+
} while( 0 );
744+
}
745+
746+
if( FD_LIKELY( ctx->repair_out_idx!=ULONG_MAX ) ) { /* Only send to repair in full Firedancer */
743747

744748
/* Construct the sig from the shred. */
745749

@@ -796,7 +800,7 @@ after_frag( fd_shred_ctx_t * ctx,
796800
ulong sz2 = sizeof(fd_shred34_t) - (34UL - s34[ 2 ].shred_cnt)*FD_SHRED_MAX_SZ;
797801
ulong sz3 = sizeof(fd_shred34_t) - (34UL - s34[ 3 ].shred_cnt)*FD_SHRED_MAX_SZ;
798802

799-
if( FD_LIKELY( ctx->blockstore ) ) { /* firedancer topo compiler hint */
803+
if( FD_LIKELY( ctx->blockstore ) ) {
800804

801805
/* Insert shreds into the blockstore. Note we do this regardless of
802806
whether the shreds are for one of our leader slots or not. Even

src/discof/forest/Local.mk

Lines changed: 4 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -0,0 +1,4 @@
1+
ifdef FD_HAS_INT128
2+
$(call add-objs,fd_forest,fd_discof)
3+
$(call make-unit-test,test_forest,test_forest,fd_discof fd_disco fd_flamenco fd_tango fd_ballet fd_util)
4+
endif

0 commit comments

Comments
 (0)