Skip to content

Commit c6919b7

Browse files
committed
feat(tower): minor hard fork detector revisions and integration
1 parent 2dbb1b0 commit c6919b7

File tree

9 files changed

+31
-28
lines changed

9 files changed

+31
-28
lines changed

src/app/firedancer/topology.c

Lines changed: 0 additions & 1 deletion
Original file line numberDiff line numberDiff line change
@@ -345,7 +345,6 @@ fd_topo_initialize( config_t * config ) {
345345

346346
fd_topob_wksp( topo, "funk" );
347347
fd_topob_wksp( topo, "progcache" );
348-
fd_topob_wksp( topo, "bh_cmp" );
349348
fd_topob_wksp( topo, "fec_sets" );
350349
fd_topob_wksp( topo, "txncache" );
351350
fd_topob_wksp( topo, "banks" );

src/discof/bank/fd_bank_tile.c

Lines changed: 0 additions & 1 deletion
Original file line numberDiff line numberDiff line change
@@ -587,7 +587,6 @@ unprivileged_init( fd_topo_t * topo,
587587
ctx->txn_ctx[ i ].bundle.prev_txn_ctxs[ j ] = &ctx->txn_ctx[ j ];
588588
}
589589

590-
ctx->txn_ctx[ i ].bank_hash_cmp = NULL; /* TODO - do we need this? */
591590
ctx->txn_ctx[ i ].progcache = ctx->txn_ctx[ i ]._progcache;
592591
ctx->txn_ctx[ i ].status_cache = txncache;
593592
*(ctx->txn_ctx[ i ].funk) = *funk;

src/discof/exec/fd_exec_tile.c

Lines changed: 0 additions & 1 deletion
Original file line numberDiff line numberDiff line change
@@ -288,7 +288,6 @@ unprivileged_init( fd_topo_t * topo,
288288
FD_LOG_CRIT(( "fd_progcache_join() failed" ));
289289
}
290290
ctx->txn_ctx->status_cache = ctx->txncache;
291-
ctx->txn_ctx->bank_hash_cmp = ctx->bank_hash_cmp;
292291
ctx->txn_ctx->bundle.is_bundle = 0;
293292

294293
/********************************************************************/

src/discof/tower/fd_hard_fork_detector.c

Lines changed: 15 additions & 15 deletions
Original file line numberDiff line numberDiff line change
@@ -86,7 +86,7 @@ typedef struct voted_on voted_on_t;
8686

8787
struct block_result_key {
8888
fd_pubkey_t block_id;
89-
fd_pubkey_t block_hash;
89+
fd_pubkey_t bank_hash;
9090
};
9191

9292
typedef struct block_result_key block_result_key_t;
@@ -126,8 +126,8 @@ typedef struct block_result block_result_t;
126126
#define MAP_PREV map.prev
127127
#define MAP_NEXT map.next
128128
#define MAP_KEY_EQ(k0,k1) ( fd_pubkey_eq( &((k0)->block_id), &((k1)->block_id) ) &\
129-
fd_pubkey_eq( &((k0)->block_hash), &((k1)->block_hash) ) )
130-
#define MAP_KEY_HASH(key,seed) ( seed ^ fd_ulong_load_8( (key)->block_id.uc ) ^ fd_ulong_load_8( (key)->block_hash.uc ) )
129+
fd_pubkey_eq( &((k0)->bank_hash), &((k1)->bank_hash) ) )
130+
#define MAP_KEY_HASH(key,seed) ( seed ^ fd_ulong_load_8( (key)->block_id.uc ) ^ fd_ulong_load_8( (key)->bank_hash.uc ) )
131131
#define MAP_OPTIMIZE_RANDOM_ACCESS_REMOVAL 1
132132
#include "../../util/tmpl/fd_map_chain.c"
133133

@@ -139,7 +139,7 @@ typedef struct block_result block_result_t;
139139

140140
struct my_result {
141141
fd_pubkey_t block_id;
142-
fd_pubkey_t block_hash;
142+
fd_pubkey_t bank_hash;
143143

144144
ulong slot;
145145

@@ -332,7 +332,7 @@ fd_hard_fork_detector_new( void * shmem,
332332
FD_TEST( hf->my_vote_map );
333333

334334
hf->my_vote_lru = my_vote_lru_join( my_vote_lru_new( _my_vote_lru ) );
335-
FD_TEST( hf->my_vote_lru );
335+
FD_TEST( hf->my_vote_lru );
336336

337337
hf->block_id_pool = block_id_pool_join( block_id_pool_new( _block_id_pool, max_live_slots*max_vote_accounts ) );
338338
FD_TEST( hf->block_id_pool );
@@ -412,16 +412,16 @@ check( fd_hard_fork_detector_t const * detector,
412412
if( detector->fatal ) FD_LOG_ERR(( "%s", msg ));
413413
else FD_LOG_WARNING(( "%s", msg ));
414414
} else {
415-
if( FD_UNLIKELY( memcmp( my_result->block_hash.uc, block_result->key.block_hash.uc, 32UL ) ) ) {
415+
if( FD_UNLIKELY( memcmp( my_result->bank_hash.uc, block_result->key.bank_hash.uc, 32UL ) ) ) {
416416
char msg[ 4096UL ];
417417
FD_TEST( fd_cstr_printf_check( msg, sizeof( msg ), NULL,
418418
"HARD FORK DETECTED: our validator has produced block hash `%s` for slot %lu with block ID `%s`, but %lu validators with %.1f of stake have voted on a different block hash `%s` for the same slot",
419-
FD_BASE58_ENC_32_ALLOCA( my_result->block_hash.uc ),
419+
FD_BASE58_ENC_32_ALLOCA( my_result->bank_hash.uc ),
420420
my_result->slot,
421421
FD_BASE58_ENC_32_ALLOCA( my_result->block_id.uc ),
422422
block_result->voter_count,
423423
100.0*(double)block_result->stake/(double)detector->total_stake,
424-
FD_BASE58_ENC_32_ALLOCA( block_result->key.block_hash.uc ) ) );
424+
FD_BASE58_ENC_32_ALLOCA( block_result->key.bank_hash.uc ) ) );
425425

426426
if( detector->fatal ) FD_LOG_ERR(( "%s", msg ));
427427
else FD_LOG_WARNING(( "%s", msg ));
@@ -433,7 +433,7 @@ void
433433
fd_hard_fork_detector_vote( fd_hard_fork_detector_t * detector,
434434
uchar const * vote_account,
435435
uchar const * block_id,
436-
uchar const * block_hash ) {
436+
uchar const * bank_hash ) {
437437
stake_t const * _stake = stake_map_ele_query_const( detector->stake_map, fd_type_pun_const( vote_account ), NULL, detector->stake_pool );
438438
if( FD_UNLIKELY( !_stake ) ) return; /* Don't care about votes from unstaked */
439439

@@ -482,9 +482,9 @@ fd_hard_fork_detector_vote( fd_hard_fork_detector_t * detector,
482482

483483
block_result_key_t br_key;
484484
fd_memcpy( br_key.block_id.uc, block_id, 32UL );
485-
fd_memcpy( br_key.block_hash.uc, block_hash, 32UL );
485+
fd_memcpy( br_key.bank_hash.uc, bank_hash, 32UL );
486486

487-
block_result_t * block_result = block_result_map_ele_query( detector->block_result_map, fd_type_pun_const( block_hash ), NULL, detector->block_result_pool );
487+
block_result_t * block_result = block_result_map_ele_query( detector->block_result_map, fd_type_pun_const( bank_hash ), NULL, detector->block_result_pool );
488488
if( FD_UNLIKELY( !block_result ) ) {
489489
/* Guaranteed to be space, because the block result pool is larger
490490
than the voted on pool, and there can be at most one unique
@@ -493,7 +493,7 @@ fd_hard_fork_detector_vote( fd_hard_fork_detector_t * detector,
493493

494494
block_result = block_result_pool_ele_acquire( detector->block_result_pool );
495495
fd_memcpy( block_result->key.block_id.uc, block_id, 32UL );
496-
fd_memcpy( block_result->key.block_hash.uc, block_hash, 32UL );
496+
fd_memcpy( block_result->key.bank_hash.uc, bank_hash, 32UL );
497497
block_result->stake = 0UL;
498498
block_result_map_ele_insert( detector->block_result_map, block_result, detector->block_result_pool );
499499
}
@@ -523,7 +523,7 @@ void
523523
fd_hard_fork_detector_block( fd_hard_fork_detector_t * detector,
524524
ulong slot,
525525
uchar const * block_id,
526-
uchar const * block_hash ) {
526+
uchar const * bank_hash ) {
527527
if( FD_LIKELY( !my_vote_pool_free( detector->my_vote_pool ) ) ) {
528528
/* Might also be good eventually to evict a little bit smarter here ... */
529529
my_result_t * lru_result = my_vote_lru_ele_pop_tail( detector->my_vote_lru, detector->my_vote_pool );
@@ -534,10 +534,10 @@ fd_hard_fork_detector_block( fd_hard_fork_detector_t * detector,
534534
my_result_t * my_result = my_vote_pool_ele_acquire( detector->my_vote_pool );
535535
my_result->slot = slot;
536536
fd_memcpy( my_result->block_id.uc, block_id, 32UL );
537-
fd_memcpy( my_result->block_hash.uc, block_hash, 32UL );
537+
fd_memcpy( my_result->bank_hash.uc, bank_hash, 32UL );
538538

539539
uchar zero32[32] = {0};
540-
if( FD_UNLIKELY( !memcmp( block_hash, zero32, 32UL ) ) ) my_result->invalid = 1;
540+
if( FD_UNLIKELY( !memcmp( bank_hash, zero32, 32UL ) ) ) my_result->invalid = 1;
541541

542542
my_vote_map_ele_insert( detector->my_vote_map, my_result, detector->my_vote_pool );
543543
my_vote_lru_ele_push_head( detector->my_vote_lru, my_result, detector->my_vote_pool );

src/discof/tower/fd_hard_fork_detector.h

Lines changed: 5 additions & 5 deletions
Original file line numberDiff line numberDiff line change
@@ -27,10 +27,10 @@
2727
We detect hard forked blocks by monitoring votes from validators, the
2828
specific criteria is:
2929
30-
- 52% of stake has voted on a block_id and agreed on a blockhash
31-
which is different than the blockhash we have for that block_id.
30+
- 52% of stake has voted on a block_id and agreed on a bank_hash
31+
which is different than the bank_hash we have for that block_id.
3232
33-
- 52% of stake has voted on a block_id and agreed on a blockhash
33+
- 52% of stake has voted on a block_id and agreed on a bank_hash
3434
when we marked the block dead because it failed to execute.
3535
3636
Interestingly we do not need to handle the case where we thought a
@@ -42,7 +42,7 @@
4242
4343
We are essentially receiving a
4444
45-
Stream<Either<(VoteAccountPubkey, BlockId, BlockHash), EpochStakes>>
45+
Stream<Either<(VoteAccountPubkey, BlockId, BankHash), EpochStakes>>
4646
4747
The first variant is a vote from some validator for a certain
4848
block_id and block_hash. This could come from either any replayed
@@ -51,7 +51,7 @@
5151
marked dead because it did not validate), all the matters is that the
5252
vote is validly signed by the vote account.
5353
54-
Internally, we maintain a Map<BlockId, Map<BlockHash, StakeWeight>>.
54+
Internally, we maintain a Map<BlockId, Map<BankHash, StakeWeight>>.
5555
Any time we receive a vote, if it causes an entry in this map to
5656
exceed 52% of the total stake weight, or it is from our own
5757
validator identity, we check if our vote is different, and

src/discof/tower/fd_tower_tile.c

Lines changed: 11 additions & 1 deletion
Original file line numberDiff line numberDiff line change
@@ -1,6 +1,7 @@
11
#include "fd_tower_tile.h"
22
#include "generated/fd_tower_tile_seccomp.h"
33

4+
#include "fd_hard_fork_detector.h"
45
#include "../genesis/fd_genesi_tile.h"
56
#include "../../choreo/ghost/fd_ghost.h"
67
#include "../../choreo/notar/fd_notar.h"
@@ -93,6 +94,7 @@ typedef struct {
9394
conf_t * confs; /* deque of confirmations queued for publishing */
9495
fd_banks_t * banks;
9596
fd_accdb_user_t accdb[1];
97+
fd_hard_fork_detector_t * hfd;
9698

9799
fd_tower_accts_t * tower_accts; /* deque of accts, stake, and pubkey for the currently replayed slot */
98100
fd_epoch_stakes_t * epoch_stakes; /* tracks the stakes for each voter in the epoch per fork */
@@ -307,11 +309,14 @@ count_vote_txn( ctx_t * ctx,
307309

308310
fd_tower_vote_t const * their_last_vote = fd_tower_peek_tail_const( ctx->tower_spare );
309311
fd_hash_t const * their_block_id = &ctx->compact_tower_sync_serde.block_id;
312+
fd_hash_t const * their_bank_hash = &ctx->compact_tower_sync_serde.hash;
310313

311314
ulong total_stake = fd_ghost_root( ctx->ghost )->total_stake;
312315
fd_notar_blk_t * notar_blk = fd_notar_count_vote( ctx->notar, total_stake, vote_acc, their_last_vote->slot, their_block_id );
313316
if( FD_LIKELY( notar_blk ) ) notar_confirm( ctx, stem, tsorig, notar_blk );
314317

318+
fd_hard_fork_detector_vote( ctx->hfd, vote_acc->uc, their_block_id->uc, their_bank_hash->uc );
319+
315320
fd_tower_forks_t * fork = fd_forks_query( ctx->forks, their_last_vote->slot );
316321
if( FD_UNLIKELY( !fork ) ) { ctx->metrics.vote_txn_ignored++; return; /* we haven't replayed this slot yet */ };
317322

@@ -455,6 +460,11 @@ replay_slot_completed( ctx_t * ctx,
455460
ctx->conf_slot = slot_info->slot;
456461
}
457462

463+
/* Insert the just replayed block into hard fork detector. */
464+
465+
slot_info->bank_hash.uc[31] &= 0xFE; /* clear lowest bit to ignore minor bank hash differences */
466+
fd_hard_fork_detector_block( ctx->hfd, slot_info->slot, slot_info->block_id.uc, slot_info->bank_hash.uc );
467+
458468
/* Insert the just replayed block into ghost. */
459469

460470
fd_hash_t const * parent_block_id = &slot_info->parent_block_id;
@@ -696,7 +706,7 @@ privileged_init( fd_topo_t * topo,
696706
ctx_t * ctx = FD_SCRATCH_ALLOC_APPEND( l, alignof(ctx_t), sizeof(ctx_t) );
697707
FD_SCRATCH_ALLOC_FINI( l, scratch_align() );
698708

699-
FD_TEST( fd_rng_secure( &ctx->seed, 8 ) );
709+
FD_TEST( fd_rng_secure( &ctx->seed, sizeof(ctx->seed) ) );
700710

701711
if( FD_UNLIKELY( !strcmp( tile->tower.identity_key, "" ) ) ) FD_LOG_ERR(( "identity_key_path not set" ));
702712
ctx->identity_key[ 0 ] = *(fd_pubkey_t const *)fd_type_pun_const( fd_keyload_load( tile->tower.identity_key, /* pubkey only: */ 1 ) );

src/flamenco/runtime/program/fd_bpf_loader_program.c

Lines changed: 0 additions & 1 deletion
Original file line numberDiff line numberDiff line change
@@ -2624,7 +2624,6 @@ fd_directly_invoke_loader_v3_deploy( fd_bank_t * bank,
26242624
txn_ctx->xid[0] = *xid;
26252625
txn_ctx->progcache = NULL;
26262626
txn_ctx->status_cache = NULL;
2627-
txn_ctx->bank_hash_cmp = NULL;
26282627
txn_ctx->log.enable_exec_recording = !!(bank->flags & FD_BANK_FLAGS_EXEC_RECORDING);
26292628
txn_ctx->bank = bank;
26302629

src/flamenco/runtime/tests/fd_instr_harness.c

Lines changed: 0 additions & 2 deletions
Original file line numberDiff line numberDiff line change
@@ -94,7 +94,6 @@ fd_solfuzz_pb_instr_ctx_create( fd_solfuzz_runner_t * runner,
9494

9595
txn_ctx->xid[0] = *xid;
9696
txn_ctx->status_cache = NULL;
97-
txn_ctx->bank_hash_cmp = NULL;
9897
txn_ctx->log.enable_exec_recording = !!( runner->bank->flags & FD_BANK_FLAGS_EXEC_RECORDING );
9998
txn_ctx->bank = runner->bank;
10099

@@ -352,7 +351,6 @@ fd_solfuzz_pb_instr_ctx_create( fd_solfuzz_runner_t * runner,
352351

353352
txn_ctx->xid[0] = *xid;
354353
txn_ctx->status_cache = NULL;
355-
txn_ctx->bank_hash_cmp = NULL;
356354
txn_ctx->log.enable_exec_recording = !!( runner->bank->flags & FD_BANK_FLAGS_EXEC_RECORDING );
357355
txn_ctx->bank = runner->bank;
358356

src/flamenco/runtime/tests/fd_txn_harness.c

Lines changed: 0 additions & 1 deletion
Original file line numberDiff line numberDiff line change
@@ -348,7 +348,6 @@ fd_solfuzz_txn_ctx_exec( fd_solfuzz_runner_t * runner,
348348
if( FD_UNLIKELY( !txn_ctx->progcache ) ) {
349349
FD_LOG_CRIT(( "fd_progcache_join failed" ));
350350
}
351-
txn_ctx->bank_hash_cmp = NULL;
352351
txn_ctx->xid[0] = *xid;
353352

354353
txn_ctx->log.enable_vm_tracing = runner->enable_vm_tracing;

0 commit comments

Comments
 (0)