Skip to content
Merged
Show file tree
Hide file tree
Changes from all commits
Commits
File filter

Filter by extension

Filter by extension

Conversations
Failed to load comments.
Loading
Jump to
Jump to file
Failed to load files.
Loading
Diff view
Diff view
30 changes: 5 additions & 25 deletions src/discof/backup/fd_ssmanifest_encoder.c
Original file line number Diff line number Diff line change
Expand Up @@ -189,7 +189,6 @@ ENCODE_FN {

ulong ec_cnt = 0UL;
fd_epoch_credits_t const * ec = NULL;
ulong ag_marker_idx = ULONG_MAX;

fd_vote_stakes_t * vote_stakes = fd_bank_vote_stakes( bank );
ulong fork_id = bank->vote_stakes_fork_id;
Expand All @@ -203,13 +202,6 @@ ENCODE_FN {
ec = find_epoch_credits( enc->bank, &ele->pubkey );
FD_TEST( ec );
ec_cnt = ec->cnt;
if( FD_UNLIKELY( ec->has_ag_migration_marker ) ) {
ulong ag_migration_slot = bank->f.alpenglow_migration_slot;
FD_TEST( ag_migration_slot!=ULONG_MAX );
ulong ag_migration_epoch = fd_slot_to_epoch( &bank->f.epoch_schedule, ag_migration_slot, NULL );
ag_marker_idx = fd_epoch_credits_ag_marker_idx( ec, ag_migration_epoch );
ec_cnt++;
}
}

/* SIMD-0232 collectors. t-3..t-5 collectors are never consulted on
Expand Down Expand Up @@ -260,15 +252,10 @@ ENCODE_FN {
.accumulated_lamports_len = (uint)( ec_cnt-ec_skip )
};
memcpy( v5.bls_pubkey_compressed, ele->bls_key, FD_BLS_PUB_COMPRESSED_SZ );
for( ulong k=0UL, j=0UL; k<ec_cnt; k++ ) {
if( FD_UNLIKELY( k==ag_marker_idx ) ) {
if( k>=ec_skip ) v5.accumulated_lamports[ k-ec_skip ] = (fd_vote_epoch_credits_t){ ULONG_MAX, ULONG_MAX, ULONG_MAX };
continue;
}
if( k>=ec_skip ) v5.accumulated_lamports[ k-ec_skip ] = (fd_vote_epoch_credits_t){ (ulong)ec->epoch[j],
ec->base_credits + (ulong)ec->credits_delta[j],
ec->base_credits + (ulong)ec->prev_credits_delta[j] };
j++;
for( ulong j=ec_skip; j<ec_cnt; j++ ) {
v5.accumulated_lamports[ j-ec_skip ] = (fd_vote_epoch_credits_t){ (ulong)ec->epoch[j],
ec->base_credits + (ulong)ec->credits_delta[j],
ec->base_credits + (ulong)ec->prev_credits_delta[j] };
}
typedef struct { uchar b[ FD_VOTE_STATE_V5_PAD_SZ ]; } v5_tail_t;
PUSH_VAL( uint, fd_vote_state_versioned_enum_v5 );
Expand Down Expand Up @@ -297,17 +284,10 @@ ENCODE_FN {

/* Epoch credits */
PUSH_VAL( ulong, ec_cnt );
for( ulong k=0UL, j=0UL; k<ec_cnt; k++ ) {
if( FD_UNLIKELY( k==ag_marker_idx ) ) {
PUSH_VAL( ulong, ULONG_MAX );
PUSH_VAL( ulong, ULONG_MAX );
PUSH_VAL( ulong, ULONG_MAX );
continue;
}
for( ulong j=0UL; j<ec_cnt; j++ ) {
PUSH_VAL( ulong, (ulong)ec->epoch[j] );
PUSH_VAL( ulong, ec->base_credits + (ulong)ec->credits_delta[j] );
PUSH_VAL( ulong, ec->base_credits + (ulong)ec->prev_credits_delta[j] );
j++;
}

PUSH_VAL( ulong, 0UL ); /* last_timestamp_slot */
Expand Down
1 change: 0 additions & 1 deletion src/discof/backup/fd_ssmanifest_writer.c
Original file line number Diff line number Diff line change
@@ -1,6 +1,5 @@
#include "fd_ssmanifest_writer.h"
#include "../../flamenco/runtime/fd_system_ids.h"
#include "../../flamenco/runtime/sysvar/fd_sysvar_epoch_schedule.h"
#include "../../flamenco/runtime/program/vote/fd_vote_state_versioned.h"
#include "../../ballet/bls/fd_bls.h"

Expand Down
29 changes: 9 additions & 20 deletions src/discof/backup/test_snap_roundtrip.c
Original file line number Diff line number Diff line change
Expand Up @@ -10,7 +10,6 @@
#include "../../flamenco/runtime/fd_txncache.h"
#include "../../flamenco/runtime/fd_txncache_shmem.h"
#include "../../flamenco/runtime/fd_txncache_private.h"
#include "../../flamenco/runtime/sysvar/fd_sysvar_epoch_schedule.h"
#include "../../flamenco/runtime/sysvar/fd_sysvar_slot_history.h"
#if FD_HAS_RACESAN
#include "../../util/racesan/fd_racesan.h"
Expand Down Expand Up @@ -73,13 +72,11 @@ seed_epoch_credits( fd_bank_t * bank ) {
FD_TEST( fd_epoch_credits_view_init( view, fd_bank_epoch_credits( bank ), bank->epoch_credits_fork_id ) );
FD_TEST( view->len==VALIDATOR_CNT );
FD_TEST( EPOCH_CREDITS_CNT<=FD_EPOCH_CREDITS_MAX );
bank->f.alpenglow_migration_slot = fd_epoch_slot0( &bank->f.epoch_schedule, EPOCH_CREDITS_CNT );
for( ulong i=0UL; i<view->len; i++ ) {
fd_epoch_credits_t * ec = &view->credits[ i ];
ec->cnt = EPOCH_CREDITS_CNT;
ec->commission = (ushort)( 4321U + i );
ec->base_credits = 10000UL + 1000UL*i;
ec->has_ag_migration_marker = i==1UL;
fd_epoch_credits_t * ec = &view->credits[ i ];
ec->cnt = EPOCH_CREDITS_CNT;
ec->commission = (ushort)( 4321U + i );
ec->base_credits = 10000UL + 1000UL*i;
for( ulong j=0UL; j<EPOCH_CREDITS_CNT; j++ ) {
ec->epoch[ j ] = (ushort)( j+1UL );
ec->prev_credits_delta[ j ] = (uint)( 100UL*j + 7UL*i );
Expand All @@ -101,19 +98,11 @@ check_epoch_credits( fd_bank_t * bank,
}
FD_TEST( ec );
FD_TEST( ec->cnt==EPOCH_CREDITS_CNT );
ulong ag_marker_idx = ec->has_ag_migration_marker ? EPOCH_CREDITS_CNT-1UL : ULONG_MAX;
FD_TEST( vs->epoch_credits_history_len==ec->cnt+(ulong)ec->has_ag_migration_marker );
for( ulong k=0UL, j=0UL; k<vs->epoch_credits_history_len; k++ ) {
if( k==ag_marker_idx ) {
FD_TEST( vs->epoch_credits[k].epoch ==ULONG_MAX );
FD_TEST( vs->epoch_credits[k].credits ==ULONG_MAX );
FD_TEST( vs->epoch_credits[k].prev_credits==ULONG_MAX );
continue;
}
FD_TEST( vs->epoch_credits[k].epoch ==(ulong)ec->epoch[j] );
FD_TEST( vs->epoch_credits[k].credits ==ec->base_credits+(ulong)ec->credits_delta[j] );
FD_TEST( vs->epoch_credits[k].prev_credits==ec->base_credits+(ulong)ec->prev_credits_delta[j] );
j++;
FD_TEST( vs->epoch_credits_history_len==ec->cnt );
for( ulong j=0UL; j<ec->cnt; j++ ) {
FD_TEST( vs->epoch_credits[j].epoch ==(ulong)ec->epoch[j] );
FD_TEST( vs->epoch_credits[j].credits ==ec->base_credits+(ulong)ec->credits_delta[j] );
FD_TEST( vs->epoch_credits[j].prev_credits==ec->base_credits+(ulong)ec->prev_credits_delta[j] );
}
fd_epoch_credits_view_fini( view );
}
Expand Down
10 changes: 3 additions & 7 deletions src/discof/restore/utils/fd_ssload.c
Original file line number Diff line number Diff line change
Expand Up @@ -501,14 +501,10 @@ fd_ssload_recover_apply( fd_snapshot_manifest_t * manifest,
fd_epoch_credits_t * ec = &epoch_credits_view->credits[epoch_credits_len];
fd_memcpy( ec->pubkey, elem->vote, 32UL );

ulong cnt = 0UL;
ec->base_credits = 0UL;
ec->has_ag_migration_marker = 0;
ulong cnt = 0UL;
ec->base_credits = 0UL;
for( ulong j=0UL; j<elem->epoch_credits_history_len; j++ ) {
if( FD_UNLIKELY( fd_epoch_credits_is_alpenglow_marker( &elem->epoch_credits[ j ] ) ) ) {
ec->has_ag_migration_marker = 1;
continue;
}
if( FD_UNLIKELY( fd_epoch_credits_is_alpenglow_marker( &elem->epoch_credits[ j ] ) ) ) continue;
if( FD_UNLIKELY( !cnt ) ) ec->base_credits = elem->epoch_credits[ j ].prev_credits;
ec->epoch[ cnt ] = (ushort)elem->epoch_credits[ j ].epoch;
ec->credits_delta[ cnt ] = elem->epoch_credits[ j ].credits - ec->base_credits;
Expand Down
63 changes: 0 additions & 63 deletions src/flamenco/fd_flamenco_base.h
Original file line number Diff line number Diff line change
Expand Up @@ -146,82 +146,19 @@ struct fd_epoch_credits {
ulong credits_delta [ FD_EPOCH_CREDITS_MAX ];
ulong prev_credits_delta[ FD_EPOCH_CREDITS_MAX ];
ushort commission;
/* cnt does not include the Alpenglow marker entry */
uchar cnt;
uchar fast_path_ok; /* True if the entries satisfy the boundary fast path prerequisites:
(1) initial[n]<=final[n], (2) initial[n]==final[n-1], and (3)
epoch[n]>=epoch[n-1]. Always true for production accounts written
by vote programs. Points calculation takes the fast paths only
when true and the slow reference implementation otherwise. So
synthetic fuzzer inputs fall back gracefully. */
/* has_ag_migration_marker is 1 if the Alpenglow migration marker
is present in the vote account's epoch credits, and 0 otherwise.
This is only needed to correctly pay out rewards earnt during the
Alpenglow migration epoch.

The Alpenglow migration changes what epoch credit entries
represent. Entries from before the migration are Tower credits,
and entries from after are Alpenglow credits.

During the migration epoch, vote accounts can earn both Tower
credits before the migration slot and Alpenglow credits after.
This means there can be two entries for the migration epoch, and
if there is only one entry we don't know if it represents Tower
credits or Alpenglow credits. The marker is used to disambiguate:
entries from epochs before the marker are Tower credits, and
entries at/after the marker are Alpenglow credits.

It is also true that:
- At most one entry per epoch is written in non-migration epochs.
- At most one entry per epoch is written for Tower credits during
the migration epoch.
- At most one entry per epoch is written for Alpenglow credits
during the migration epoch.
- The marker is only written during the migration epoch, whilst
crediting any Alpenglow credits earnt. If the vote account did
not earn any Alpenglow credits during the migration epoch,
there will never be a marker in its epoch credits.

Therefore, we know that:
- If the marker is not present and there is only 1 entry for the
migration epoch, that entry must represent Tower credits
- If the marker is present and there is only 1 entry for the
migration epoch, that entry must represent Alpenglow credits
- If the marker is present and there are 2 entries for the
migration epoch, the first represents Tower credits and the
second represents Alpenglow credits

https://github.com/anza-xyz/agave/blob/v4.3.0/runtime/src/block_component_processor/vote_reward.rs#L532-L596 */
uchar has_ag_migration_marker;
};
typedef struct fd_epoch_credits fd_epoch_credits_t;

FD_STATIC_ASSERT( (ulong)UCHAR_MAX>=FD_EPOCH_CREDITS_MAX, cnt_width );
FD_STATIC_ASSERT( sizeof(fd_epoch_credits_t)==1200UL, fd_epoch_credits );

/* fd_epoch_credits_ag_marker_idx returns the index of the Alpenglow
migration marker in the on-chain epoch credits state, given the
epoch_credits and the migration epoch. This is so that our
serialized epoch credits are Agave-compatible. */

static inline ulong
fd_epoch_credits_ag_marker_idx( fd_epoch_credits_t const * epoch_credits,
ulong ag_migration_epoch ) {
if( FD_LIKELY( !epoch_credits->has_ag_migration_marker ) ) return ULONG_MAX;

/* Find the last entry for the migration epoch - the marker goes
immediately before this entry. */
for( ulong i=epoch_credits->cnt; i; i-- ) {
if( FD_UNLIKELY ((ulong)epoch_credits->epoch[ i-1UL ]==ag_migration_epoch )) {
return i-1UL;
}
}

/* If there is no entry for the migration epoch, the marker is the
last entry. */
return epoch_credits->cnt;
}

static inline uchar
fd_epoch_credits_fast_path_ok( fd_epoch_credits_t const * epoch_credits ) {
for( ulong i=0UL; i<epoch_credits->cnt; i++ ) {
Expand Down
Loading
Loading