Skip to content

Commit 5f02e63

Browse files
committed
feat(tower): monotonically increasing contiguous confirm / root frags
1 parent 7d02bbe commit 5f02e63

File tree

7 files changed

+258
-91
lines changed

7 files changed

+258
-91
lines changed

src/app/firedancer/topology.c

Lines changed: 4 additions & 2 deletions
Original file line numberDiff line numberDiff line change
@@ -667,15 +667,17 @@ fd_topo_initialize( config_t * config ) {
667667
fd_topob_tile_in ( topo, "replay", 0UL, "metric_in", "snapin_manif", 0UL, FD_TOPOB_RELIABLE, FD_TOPOB_POLLED );
668668
}
669669

670-
/**/ fd_topob_tile_in( topo, "replay", 0UL, "metric_in", "poh_replay", 0UL, FD_TOPOB_RELIABLE, FD_TOPOB_POLLED );
671-
FOR(exec_tile_cnt) fd_topob_tile_in( topo, "exec", i, "metric_in", "replay_exec", 0UL, FD_TOPOB_RELIABLE, FD_TOPOB_POLLED );
670+
/**/ fd_topob_tile_in ( topo, "replay", 0UL, "metric_in", "poh_replay", 0UL, FD_TOPOB_RELIABLE, FD_TOPOB_POLLED );
671+
FOR(exec_tile_cnt) fd_topob_tile_in ( topo, "exec", i, "metric_in", "replay_exec", 0UL, FD_TOPOB_RELIABLE, FD_TOPOB_POLLED );
672+
672673
/**/ fd_topob_tile_in ( topo, "tower", 0UL, "metric_in", "genesi_out", 0UL, FD_TOPOB_RELIABLE, FD_TOPOB_POLLED );
673674
/**/ fd_topob_tile_in ( topo, "tower", 0UL, "metric_in", "gossip_out", 0UL, FD_TOPOB_RELIABLE, FD_TOPOB_POLLED );
674675
/**/ fd_topob_tile_in ( topo, "tower", 0UL, "metric_in", "replay_out", 0UL, FD_TOPOB_RELIABLE, FD_TOPOB_POLLED );
675676
if( snapshots_enabled ) {
676677
fd_topob_tile_in ( topo, "tower", 0UL, "metric_in", "snapin_manif", 0UL, FD_TOPOB_RELIABLE, FD_TOPOB_POLLED );
677678
}
678679
/**/ fd_topob_tile_out( topo, "tower", 0UL, "tower_out", 0UL );
680+
679681
/**/ fd_topob_tile_in ( topo, "send", 0UL, "metric_in", "replay_stake", 0UL, FD_TOPOB_RELIABLE, FD_TOPOB_POLLED );
680682
/**/ fd_topob_tile_in ( topo, "send", 0UL, "metric_in", "gossip_out", 0UL, FD_TOPOB_RELIABLE, FD_TOPOB_POLLED );
681683
/**/ fd_topob_tile_in ( topo, "send", 0UL, "metric_in", "tower_out", 0UL, FD_TOPOB_RELIABLE, FD_TOPOB_POLLED );

src/choreo/notar/fd_notar.c

Lines changed: 9 additions & 15 deletions
Original file line numberDiff line numberDiff line change
@@ -94,31 +94,23 @@ fd_notar_delete( void * notar ) {
9494
return notar;
9595
}
9696

97-
int
97+
fd_notar_blk_t *
9898
fd_notar_count_vote( fd_notar_t * notar,
9999
ulong total_stake,
100100
fd_pubkey_t const * addr,
101101
ulong vote_slot,
102102
fd_hash_t const * vote_block_id ) {
103103

104-
if( FD_UNLIKELY( !notar ) ) {
105-
FD_LOG_WARNING(( "NULL notar" ));
106-
return 0;
107-
}
104+
if( FD_UNLIKELY( !notar ) ) { FD_LOG_WARNING(( "NULL notar" )); return NULL; }
108105

109106
/* Ignore if this vote slot isn't in range. */
110107

111-
if( FD_UNLIKELY( vote_slot < notar->lo_wmark || vote_slot > notar->hi_wmark ) ) return 0;
108+
if( FD_UNLIKELY( vote_slot < notar->lo_wmark || vote_slot > notar->hi_wmark ) ) return NULL;
112109

113110
/* Ignore if this vote account isn't in the voter set. */
114111

115112
fd_notar_vtr_t const * vtr = fd_notar_vtr_query( notar->vtr_map, *addr, NULL );
116-
if( FD_UNLIKELY( !vtr ) ) return 0;
117-
118-
/* Ignore if this notar blk was already duplicate confirmed. */
119-
120-
fd_notar_blk_t * notar_blk = fd_notar_blk_query( notar->blk_map, *vote_block_id, NULL );
121-
if( FD_LIKELY( notar_blk && notar_blk->dup_conf ) ) return 0;
113+
if( FD_UNLIKELY( !vtr ) ) return NULL;
122114

123115
/* Check we haven't already counted the voter's stake for this slot.
124116
If a voter voted for multiple block ids for the same slot, we only
@@ -138,12 +130,13 @@ fd_notar_count_vote( fd_notar_t * notar,
138130
fd_notar_slot_vtrs_null( notar_slot->prev_vtrs );
139131
fd_notar_slot_vtrs_null( notar_slot->vtrs );
140132
}
141-
if( FD_LIKELY( fd_notar_slot_vtrs_test( notar_slot->vtrs, vtr->bit ) ) ) return 0;
133+
if( FD_LIKELY( fd_notar_slot_vtrs_test( notar_slot->vtrs, vtr->bit ) ) ) return NULL;
142134
fd_notar_slot_vtrs_insert( notar_slot->vtrs, vtr->bit );
143135
notar_slot->stake += vtr->stake;
144136

145137
/* Get the actual block with the block_id. */
146138

139+
fd_notar_blk_t * notar_blk = fd_notar_blk_query( notar->blk_map, *vote_block_id, NULL );
147140
if( FD_UNLIKELY( !notar_blk ) ) {
148141
notar_blk = fd_notar_blk_insert( notar->blk_map, *vote_block_id );
149142
notar_blk->slot = vote_slot;
@@ -152,8 +145,9 @@ fd_notar_count_vote( fd_notar_t * notar,
152145
notar_slot->block_ids[notar_slot->block_ids_cnt++] = *vote_block_id;
153146
}
154147
notar_blk->stake += vtr->stake;
155-
notar_blk->dup_conf = (double)notar_blk->stake / (double)total_stake > 0.52; /* duplicate confirmed if > 52% stake */
156-
return notar_blk->dup_conf;
148+
notar_blk->dup_conf = ((double)notar_blk->stake / (double)total_stake) > 0.52;
149+
notar_blk->opt_conf = ((double)notar_blk->stake / (double)total_stake) > (2.0/3.0);
150+
return notar_blk;
157151
}
158152

159153
void

src/choreo/notar/fd_notar.h

Lines changed: 16 additions & 12 deletions
Original file line numberDiff line numberDiff line change
@@ -10,16 +10,16 @@
1010
important in two contexts:
1111
1212
1. When becoming leader, we need to check that our "previous"
13-
leader block _as of_ the parent slot we're building on, has
14-
propagated. If it's not propagated, we need to instead
15-
retransmit our last block that failed to propagate. "Previous"
16-
is quoted, because there is a grace period of one leader
17-
rotation for leader blocks to propagate.
13+
leader block _as of_ the parent slot we're building on, has
14+
propagated. If it's not propagated, we need to instead
15+
retransmit our last block that failed to propagate. "Previous"
16+
is quoted, because there is a grace period of one leader
17+
rotation for leader blocks to propagate.
1818
1919
2. When voting, we need to check our previous leader block _as of_
20-
the slot we're voting for has propagated (unless we're voting
21-
for one of our leader blocks). We cannot vote for slots in
22-
which our last leader block failed to propagate.
20+
the slot we're voting for has propagated (unless we're voting
21+
for one of our own leader blocks). We cannot vote for slots in
22+
which our last leader block failed to propagate.
2323
2424
- duplicate confirmed: a block is duplicate confirmed if it has
2525
received votes from at least 52% of stake in the cluster. The
@@ -85,6 +85,10 @@
8585
#define FD_NOTAR_PARANOID 1
8686
#endif
8787

88+
#define FD_NOTAR_FLAG_CONFIRMED_PROPAGATED (0)
89+
#define FD_NOTAR_FLAG_CONFIRMED_DUPLICATE (1)
90+
#define FD_NOTAR_FLAG_CONFIRMED_OPTIMISTIC (2)
91+
8892
#define SET_NAME fd_notar_slot_vtrs
8993
#define SET_MAX FD_VOTER_MAX
9094
#include "../../util/tmpl/fd_set.c"
@@ -95,7 +99,7 @@ struct fd_notar_slot {
9599
ulong prev_leader_slot; /* previous slot in which we were leader */
96100
ulong stake; /* amount of stake that has voted for this slot */
97101
int is_leader; /* whether this slot was our own leader slot */
98-
int is_propagated; /* whether this slot has reached 33% of stake */
102+
int is_propagated; /* whether this slot has reached 1/3 of stake */
99103

100104
fd_hash_t block_ids[FD_VOTER_MAX]; /* one block id per voter per slot */
101105
ulong block_ids_cnt; /* count of block ids */
@@ -105,13 +109,13 @@ struct fd_notar_slot {
105109
};
106110
typedef struct fd_notar_slot fd_notar_slot_t;
107111

108-
109112
struct fd_notar_blk {
110113
fd_hash_t block_id; /* map key */
111114
uint hash; /* reserved for fd_map_dynamic */
112115
ulong slot; /* slot associated with this block */
113116
ulong stake; /* sum of stake that has voted for this block_id */
114117
int dup_conf; /* whether this block has reached 52% of stake */
118+
int opt_conf; /* whether this block has reached 2/3 of stake */
115119
};
116120
typedef struct fd_notar_blk fd_notar_blk_t;
117121

@@ -161,7 +165,7 @@ struct __attribute__((aligned(128UL))) fd_notar {
161165
ulong epoch; /* highest replayed epoch */
162166
ulong lo_wmark; /* notar ignores votes < lo_wmark */
163167
ulong hi_wmark; /* notar ignores votes > hi_wmark */
164-
ulong slot_max; /* maximum slot number */
168+
ulong slot_max; /* maximum number of slots notar can track */
165169

166170
fd_notar_slot_t * slot_map; /* tracks who has voted for a given slot */
167171
fd_notar_blk_t * blk_map; /* tracks amount of stake for a given block (keyed by block id) */
@@ -237,7 +241,7 @@ fd_notar_delete( void * notar );
237241
account in the current epoch, slot is slot being voted for, block_id
238242
is the voter's proposed block id for this vote slot. */
239243

240-
int
244+
fd_notar_blk_t *
241245
fd_notar_count_vote( fd_notar_t * notar,
242246
ulong total_stake,
243247
fd_pubkey_t const * addr,

src/choreo/tower/fd_tower.c

Lines changed: 2 additions & 2 deletions
Original file line numberDiff line numberDiff line change
@@ -541,7 +541,7 @@ fd_tower_vote_and_reset( fd_tower_t * tower,
541541
542542
So if we have a confirmed block id, we return that. Otherwise
543543
we return our own vote block id for that slot, which we assume
544-
is the cluster confirmed version by the time it gets rooted.
544+
is the cluster converged on by the time we're rooting it.
545545
546546
The only way it is possible for us to root the wrong version of
547547
a block (ie. not the one the cluster confirmed) is if there is
@@ -641,7 +641,7 @@ fd_tower_to_vote_txn( fd_tower_t const * tower,
641641
for( fd_tower_iter_t iter = fd_tower_iter_init( tower );
642642
!fd_tower_iter_done( tower, iter );
643643
iter = fd_tower_iter_next( tower, iter ) ) {
644-
fd_tower_t const * vote = fd_tower_iter_ele_const( tower, iter );
644+
fd_tower_t const * vote = fd_tower_iter_ele_const( tower, iter );
645645
tower_sync.lockouts[i].offset = vote->slot - prev;
646646
tower_sync.lockouts[i].confirmation_count = (uchar)vote->conf;
647647
prev = vote->slot;

src/discof/replay/fd_replay_tile.c

Lines changed: 17 additions & 5 deletions
Original file line numberDiff line numberDiff line change
@@ -2139,9 +2139,9 @@ process_exec_task_done( fd_replay_tile_t * ctx,
21392139
}
21402140

21412141
static void
2142-
process_tower_update( fd_replay_tile_t * ctx,
2143-
fd_stem_context_t * stem,
2144-
fd_tower_slot_done_t const * msg ) {
2142+
process_tower_slot_done( fd_replay_tile_t * ctx,
2143+
fd_stem_context_t * stem,
2144+
fd_tower_slot_done_t const * msg ) {
21452145
ctx->reset_block_id = msg->reset_block_id;
21462146
ctx->reset_slot = msg->reset_slot;
21472147
ctx->reset_timestamp_nanos = fd_log_wallclock();
@@ -2200,7 +2200,7 @@ process_tower_update( fd_replay_tile_t * ctx,
22002200
ctx->replay_out->chunk = fd_dcache_compact_next( ctx->replay_out->chunk, sizeof(fd_poh_reset_t), ctx->replay_out->chunk0, ctx->replay_out->wmark );
22012201
}
22022202

2203-
FD_LOG_INFO(( "tower_update(reset_slot=%lu, next_leader_slot=%lu, vote_slot=%lu, root_slot=%lu, root_block_id=%s)", msg->reset_slot, ctx->next_leader_slot, msg->vote_slot, msg->root_slot, FD_BASE58_ENC_32_ALLOCA( &msg->root_block_id ) ));
2203+
FD_LOG_INFO(( "tower_slot_done(reset_slot=%lu, next_leader_slot=%lu, vote_slot=%lu)", msg->reset_slot, ctx->next_leader_slot, msg->vote_slot ));
22042204
maybe_become_leader( ctx, stem );
22052205

22062206
if( FD_LIKELY( msg->root_slot!=ULONG_MAX ) ) {
@@ -2385,7 +2385,19 @@ returnable_frag( fd_replay_tile_t * ctx,
23852385
break;
23862386
}
23872387
case IN_KIND_TOWER: {
2388-
if( FD_LIKELY( sig==FD_TOWER_SIG_SLOT_DONE ) ) process_tower_update( ctx, stem, fd_chunk_to_laddr( ctx->in[ in_idx ].mem, chunk ) );
2388+
if ( FD_LIKELY( sig==FD_TOWER_SIG_SLOT_DONE ) ) process_tower_slot_done( ctx, stem, fd_chunk_to_laddr( ctx->in[ in_idx ].mem, chunk ) );
2389+
else if( FD_LIKELY( sig==FD_TOWER_SIG_SLOT_CONFIRMED ) ) {
2390+
fd_tower_slot_confirmed_t const * msg = fd_chunk_to_laddr( ctx->in[ in_idx ].mem, chunk );
2391+
2392+
/* Implement replay plugin API here */
2393+
2394+
switch( msg->kind ) {
2395+
case FD_TOWER_SLOT_CONFIRMED_OPTIMISTIC:
2396+
break;
2397+
case FD_TOWER_SLOT_CONFIRMED_ROOTED:
2398+
break;
2399+
}
2400+
};
23892401
break;
23902402
}
23912403
case IN_KIND_SHRED: {

0 commit comments

Comments
 (0)