Skip to content

Commit

Permalink
flamenco, syscalls: implement enable_get_epoch_stake_syscall feature
Browse files Browse the repository at this point in the history
  • Loading branch information
mjain-jump committed Dec 5, 2024
1 parent 4a8027f commit 1de6821
Show file tree
Hide file tree
Showing 12 changed files with 128 additions and 11 deletions.
8 changes: 8 additions & 0 deletions src/flamenco/features/fd_features_generated.c
Original file line number Diff line number Diff line change
Expand Up @@ -1289,6 +1289,12 @@ fd_feature_id_t const ids[] = {
.name = "migrate_address_lookup_table_program_to_core_bpf",
.cleaned_up = {UINT_MAX, UINT_MAX, UINT_MAX} },

{ .index = offsetof(fd_features_t, enable_get_epoch_stake_syscall)>>3,
.id = {"\x64\x88\xa2\xd0\x5a\xcc\xbb\xae\xa0\x4e\xa8\xaf\xeb\x15\xfb\x71\xa7\x5b\x27\x71\x96\x6c\x2f\x05\x0d\xfe\xf3\x44\xbb\x07\x3b\x21"},
/* 7mScTYkJXsbdrcwTQRs7oeCSXoJm4WjzBsRyf8bCU3Np */
.name = "enable_get_epoch_stake_syscall",
.cleaned_up = {UINT_MAX, UINT_MAX, UINT_MAX} },

{ .index = ULONG_MAX }
};

Expand Down Expand Up @@ -1513,6 +1519,7 @@ fd_feature_id_query( ulong prefix ) {
case 0xf46b1f18665c4236: return &ids[ 210 ];
case 0xa9a90df1904da912: return &ids[ 211 ];
case 0x2434a84be5b684a5: return &ids[ 212 ];
case 0xaebbcc5ad0a28864: return &ids[ 213 ];
default: break;
}

Expand Down Expand Up @@ -1734,5 +1741,6 @@ FD_STATIC_ASSERT( offsetof( fd_features_t, enable_sbpf_v3_deployment_and_executi
FD_STATIC_ASSERT( offsetof( fd_features_t, migrate_feature_gate_program_to_core_bpf )>>3==210UL, layout );
FD_STATIC_ASSERT( offsetof( fd_features_t, migrate_config_program_to_core_bpf )>>3==211UL, layout );
FD_STATIC_ASSERT( offsetof( fd_features_t, migrate_address_lookup_table_program_to_core_bpf )>>3==212UL, layout );
FD_STATIC_ASSERT( offsetof( fd_features_t, enable_get_epoch_stake_syscall )>>3==213UL, layout );

FD_STATIC_ASSERT( sizeof( fd_features_t )>>3==FD_FEATURE_ID_CNT, layout );
3 changes: 2 additions & 1 deletion src/flamenco/features/fd_features_generated.h
Original file line number Diff line number Diff line change
Expand Up @@ -6,7 +6,7 @@

/* FEATURE_ID_CNT is the number of features in ids */

#define FD_FEATURE_ID_CNT (213UL)
#define FD_FEATURE_ID_CNT (214UL)

union fd_features {

Expand Down Expand Up @@ -226,6 +226,7 @@ union fd_features {
/* 0xf46b1f18665c4236 */ ulong migrate_feature_gate_program_to_core_bpf;
/* 0xa9a90df1904da912 */ ulong migrate_config_program_to_core_bpf;
/* 0x2434a84be5b684a5 */ ulong migrate_address_lookup_table_program_to_core_bpf;
/* 0xaebbcc5ad0a28864 */ ulong enable_get_epoch_stake_syscall;
};

};
3 changes: 2 additions & 1 deletion src/flamenco/features/feature_map.json
Original file line number Diff line number Diff line change
Expand Up @@ -211,5 +211,6 @@
{"name":"enable_sbpf_v3_deployment_and_execution", "pubkey": "C8XZNs1bfzaiT3YDeXZJ7G5swQWQv7tVzDnCxtHvnSpw"},
{"name":"migrate_feature_gate_program_to_core_bpf","pubkey":"4eohviozzEeivk1y9UbrnekbAFMDQyJz5JjA9Y6gyvky"},
{"name":"migrate_config_program_to_core_bpf","pubkey":"2Fr57nzzkLYXW695UdDxDeR5fhnZWSttZeZYemrnpGFV"},
{"name":"migrate_address_lookup_table_program_to_core_bpf","pubkey":"C97eKZygrkU4JxJsZdjgbUY7iQR7rKTr4NyDWo2E5pRm"}
{"name":"migrate_address_lookup_table_program_to_core_bpf","pubkey":"C97eKZygrkU4JxJsZdjgbUY7iQR7rKTr4NyDWo2E5pRm"},
{"name":"enable_get_epoch_stake_syscall","pubkey":"7mScTYkJXsbdrcwTQRs7oeCSXoJm4WjzBsRyf8bCU3Np"}
]
1 change: 1 addition & 0 deletions src/flamenco/runtime/context/fd_exec_epoch_ctx.c
Original file line number Diff line number Diff line change
Expand Up @@ -267,6 +267,7 @@ void
fd_exec_epoch_ctx_from_prev( fd_exec_epoch_ctx_t * self, fd_exec_epoch_ctx_t * prev ) {
fd_memcpy( &self->features, &prev->features, sizeof(fd_features_t) );
self->bank_hash_cmp = prev->bank_hash_cmp;
self->total_epoch_stake = 0UL;

fd_epoch_bank_t * old_epoch_bank = fd_exec_epoch_ctx_epoch_bank( prev );
fd_epoch_bank_t * new_epoch_bank = fd_exec_epoch_ctx_bank_mem_setup( self );
Expand Down
2 changes: 2 additions & 0 deletions src/flamenco/runtime/context/fd_exec_epoch_ctx.h
Original file line number Diff line number Diff line change
Expand Up @@ -32,6 +32,8 @@ struct __attribute__((aligned(64UL))) fd_exec_epoch_ctx {
fd_epoch_bank_t epoch_bank;

fd_bank_hash_cmp_t * bank_hash_cmp;

ulong total_epoch_stake;
};

#define FD_EXEC_EPOCH_CTX_ALIGN (4096UL)
Expand Down
13 changes: 8 additions & 5 deletions src/flamenco/runtime/fd_runtime.c
Original file line number Diff line number Diff line change
Expand Up @@ -4032,6 +4032,7 @@ FD_SCRATCH_SCOPE_BEGIN {

// Update the epoch bank vote_accounts with the latest values from the slot bank
// FIXME: resize the vote_accounts_pool if necessary
ulong total_epoch_stake = 0UL;
for ( fd_vote_accounts_pair_t_mapnode_t * n = fd_vote_accounts_pair_t_map_minimum(
slot_ctx->slot_bank.vote_account_keys.vote_accounts_pool,
slot_ctx->slot_bank.vote_account_keys.vote_accounts_root );
Expand All @@ -4043,17 +4044,19 @@ FD_SCRATCH_SCOPE_BEGIN {
fd_memcpy( &key.elem.key, &n->elem.key, FD_PUBKEY_FOOTPRINT );
fd_vote_accounts_pair_t_mapnode_t * epoch_cache_node = fd_vote_accounts_pair_t_map_find( stakes->vote_accounts.vote_accounts_pool, stakes->vote_accounts.vote_accounts_root, &key );
if( epoch_cache_node == NULL ) {
fd_vote_accounts_pair_t_mapnode_t * new_entry = fd_vote_accounts_pair_t_map_acquire( stakes->vote_accounts.vote_accounts_pool );
epoch_cache_node = fd_vote_accounts_pair_t_map_acquire( stakes->vote_accounts.vote_accounts_pool );

fd_memcpy(&new_entry->elem.key, &n->elem.key, sizeof(fd_pubkey_t));
fd_memcpy(&new_entry->elem.stake, &n->elem.stake, sizeof(ulong));
fd_memcpy(&new_entry->elem.value, &n->elem.value, sizeof(fd_solana_account_t));
fd_memcpy(&epoch_cache_node->elem.key, &n->elem.key, sizeof(fd_pubkey_t));
fd_memcpy(&epoch_cache_node->elem.stake, &n->elem.stake, sizeof(ulong));
fd_memcpy(&epoch_cache_node->elem.value, &n->elem.value, sizeof(fd_solana_account_t));

fd_vote_accounts_pair_t_map_insert( stakes->vote_accounts.vote_accounts_pool, &stakes->vote_accounts.vote_accounts_root, new_entry );
fd_vote_accounts_pair_t_map_insert( stakes->vote_accounts.vote_accounts_pool, &stakes->vote_accounts.vote_accounts_root, epoch_cache_node );
} else {
epoch_cache_node->elem.stake = n->elem.stake;
}
total_epoch_stake += epoch_cache_node->elem.stake;
}
slot_ctx->epoch_ctx->total_epoch_stake = total_epoch_stake;

fd_bincode_destroy_ctx_t destroy_slot = {.valloc = slot_ctx->valloc};
fd_vote_accounts_destroy( &slot_ctx->slot_bank.vote_account_keys, &destroy_slot );
Expand Down
6 changes: 3 additions & 3 deletions src/flamenco/runtime/program/fd_vote_program.c
Original file line number Diff line number Diff line change
Expand Up @@ -1933,8 +1933,8 @@ do_process_vote_state_update( fd_vote_state_t * vote_state,
}

// ??
static ulong
query_pubkey_stake( fd_pubkey_t const * pubkey, fd_vote_accounts_t const * vote_accounts ) {
ulong
fd_query_pubkey_stake( fd_pubkey_t const * pubkey, fd_vote_accounts_t const * vote_accounts ) {
fd_vote_accounts_pair_t_mapnode_t key = { 0 };
key.elem.key = *pubkey;
fd_vote_accounts_pair_t_mapnode_t * vote_node = fd_vote_accounts_pair_t_map_find(
Expand Down Expand Up @@ -1965,7 +1965,7 @@ process_vote_state_update( ulong vote_acct_idx,
lockout->slot,
&vote_state_update->hash,
0,
query_pubkey_stake( vote_account->pubkey,
fd_query_pubkey_stake( vote_account->pubkey,
&ctx->epoch_ctx->epoch_bank.stakes.vote_accounts ) );

if( FD_LIKELY( vote_state_update->has_root ) ) {
Expand Down
5 changes: 5 additions & 0 deletions src/flamenco/runtime/program/fd_vote_program.h
Original file line number Diff line number Diff line change
Expand Up @@ -46,6 +46,11 @@ FD_PROTOTYPES_BEGIN
int
fd_vote_program_execute( fd_exec_instr_ctx_t * ctx );

/* Queries the delegated stake amount for the given vote account pubkey,
given the vote accounts map. Returns 0 if nonexistent. */
ulong
fd_query_pubkey_stake( fd_pubkey_t const * pubkey, fd_vote_accounts_t const * vote_accounts );

int
fd_vote_get_state( fd_borrowed_account_t const * self,
fd_valloc_t valloc,
Expand Down
1 change: 1 addition & 0 deletions src/flamenco/runtime/tests/run_ledger_tests_all.txt
Original file line number Diff line number Diff line change
Expand Up @@ -75,3 +75,4 @@ src/flamenco/runtime/tests/run_ledger_test.sh -l testnet-302734641 -s snapshot-3
src/flamenco/runtime/tests/run_ledger_test.sh -l migrate-feature-program -s snapshot-500-Cz6iotFK7kNcGTpyUZeX4CHbT2uff2uzVW8RXXysBnVk.tar.zst -p 50 -y 16 -m 5000000 -e 675 -c 2.1.0 -o 4eohviozzEeivk1y9UbrnekbAFMDQyJz5JjA9Y6gyvky
src/flamenco/runtime/tests/run_ledger_test.sh -l migrate-config-program -s snapshot-500-HCg5AHVPC6JAqZo4p6iMcDmo586ZjkxxPpxfAwCHqroy.tar.zst -p 50 -y 16 -m 5000000 -e 675 -c 2.1.0 -o 2Fr57nzzkLYXW695UdDxDeR5fhnZWSttZeZYemrnpGFV
src/flamenco/runtime/tests/run_ledger_test.sh -l per-stake-history-new-rate-activation-epoch -s snapshot-50-47DbuHpi6gXmZKQ1FUSAAfkgnuWrkfTAtx3Hk5Gqsu5W.tar.zst -p 50 -y 16 -m 5000000 -e 675 -c 2.1.0
src/flamenco/runtime/tests/run_ledger_test.sh -l enable-get-epoch-stake-syscall -s snapshot-50-FfJQ3ePJx2s5BDymDoiLVRHDHj5doYNQBzyrqus8LocL.tar.zst -p 50 -y 16 -m 5000000 -e 686 -c 2.1.0 -o 7mScTYkJXsbdrcwTQRs7oeCSXoJm4WjzBsRyf8bCU3Np
7 changes: 7 additions & 0 deletions src/flamenco/vm/syscall/fd_vm_syscall.c
Original file line number Diff line number Diff line change
Expand Up @@ -28,6 +28,7 @@ fd_vm_syscall_register_slot( fd_sbpf_syscalls_t * syscalls,
int enable_alt_bn128_compression_syscall = 0;
int enable_last_restart_slot_syscall = 0;
int enable_get_sysvar_syscall = 0;
int enable_get_epoch_stake_syscall = 0;

int disable_fees_sysvar = 0;

Expand All @@ -40,6 +41,7 @@ fd_vm_syscall_register_slot( fd_sbpf_syscalls_t * syscalls,
enable_alt_bn128_compression_syscall = FD_FEATURE_ACTIVE( slot_ctx, enable_alt_bn128_compression_syscall );
enable_last_restart_slot_syscall = FD_FEATURE_ACTIVE( slot_ctx, last_restart_slot_sysvar );
enable_get_sysvar_syscall = FD_FEATURE_ACTIVE( slot_ctx, get_sysvar_syscall_enabled );
enable_get_epoch_stake_syscall = FD_FEATURE_ACTIVE( slot_ctx, enable_get_epoch_stake_syscall );

disable_fees_sysvar = !FD_FEATURE_ACTIVE( slot_ctx, disable_fees_sysvar );

Expand All @@ -52,6 +54,7 @@ fd_vm_syscall_register_slot( fd_sbpf_syscalls_t * syscalls,
enable_alt_bn128_compression_syscall = 1;
enable_last_restart_slot_syscall = 1;
enable_get_sysvar_syscall = 1;
enable_get_epoch_stake_syscall = 1;

}

Expand Down Expand Up @@ -110,6 +113,10 @@ fd_vm_syscall_register_slot( fd_sbpf_syscalls_t * syscalls,
REGISTER( "sol_get_sysvar", fd_vm_syscall_sol_get_sysvar );
}

if( enable_get_epoch_stake_syscall ) {
REGISTER( "sol_get_epoch_stake", fd_vm_syscall_sol_get_epoch_stake );
}

REGISTER( "sol_memcpy_", fd_vm_syscall_sol_memcpy );
REGISTER( "sol_memmove_", fd_vm_syscall_sol_memmove );
REGISTER( "sol_memcmp_", fd_vm_syscall_sol_memcmp );
Expand Down
55 changes: 54 additions & 1 deletion src/flamenco/vm/syscall/fd_vm_syscall.h
Original file line number Diff line number Diff line change
Expand Up @@ -16,6 +16,27 @@
https://github.com/solana-labs/solana/blob/2afde1b028ed4593da5b6c735729d8994c4bfac6/sdk/program/src/pubkey.rs#L19 */
#define FD_VM_PDA_SEED_MEM_MAX (32UL)

/* PYTHON3 CODE FOR COMPUTING THE SYSCALL MURMUR3 HASH (e.g. sol_get_epoch_stake):
```
import mmh3
import ctypes
def compute_murmur3_hash(input_string):
# Compute the Murmur3 hash of the input string
hash_value = mmh3.hash(input_string)
# Convert the hash value to a 32-bit unsigned integer
u32_hash_value = ctypes.c_uint32(hash_value).value
return u32_hash_value
input_string = b"sol_get_epoch_stake"
hash_value = compute_murmur3_hash(input_string)
print(f"The Murmur3 hash of '{input_string}' as u32 is: {hex(hash_value)}")
Output:
The Murmur3 hash of 'b'sol_get_epoch_stake'' as u32 is: 0x5be92f4a
```
*/

/* https://github.com/solana-labs/solana/blob/2afde1b028ed4593da5b6c735729d8994c4bfac6/sdk/program/src/pubkey.rs#L22 */

/* FIXME: CONSIDER NOT PREFIXING SYSCALLS WITH SOL_? (OR MAYBE THIS
Expand Down Expand Up @@ -478,12 +499,44 @@ FD_VM_SYSCALL_DECL( sol_get_last_restart_slot_sysvar );
- *_ret = 2 if sysvar id is not in {clock,schedule,rewards,rent,slot hashes,stake history,last restart slot}
OR sysvar account does not exist.
- *_ret = 1 if [offset,offset+sz) is outside of sysvar data buffer.
= *_ret = 0 if success.
- *_ret = 0 if success.
On return, sz bytes of appropriate offset sysvar data will be copied into
haddr belonging to out_vaddr. */
FD_VM_SYSCALL_DECL( sol_get_sysvar );

/* syscall(5be92f4a) "sol_get_epoch_stake"
Gets a vote account's delegated stake for the current epoch, or the total active stake
on the cluster for the current epoch.
Inputs:
r1 - var_addr, vote pubkey VM pointer
r2 - ignored
r3 - ignored
r4 - ignored
r5 - ignored
Return:
FD_VM_ERR_SIGCALL: the VM is not running within the Solana runtime.
*_ret unchanged. vm->cu unchanged.
FD_VM_ERR_SIGCOST: insufficient compute budget. *_ret unchanged.
vm->cu==0.
FD_VM_ERR_SIGSEGV: bad var_addr. _ret unchanged. vm->cu unchanged.
FD_VM_ERR_ABORT: offset+sz overflow. *_ret unchanged.
FD_VM_SUCCESS: success. vm->cu decremented and vm->cu>0.
- *_ret = 0 if success.
- if var_addr == 0, returns the total active stake on the cluster. Otherwise,
returns the vote account's delegated stake. */

FD_VM_SYSCALL_DECL( sol_get_epoch_stake );

/* syscall(85532d94) "sol_get_stack_height"
Inputs:
Expand Down
35 changes: 35 additions & 0 deletions src/flamenco/vm/syscall/fd_vm_syscall_runtime.c
Original file line number Diff line number Diff line change
@@ -1,4 +1,5 @@
#include "fd_vm_syscall.h"
#include "../../runtime/program/fd_vote_program.h"
#include "../../runtime/sysvar/fd_sysvar.h"
#include "../../runtime/sysvar/fd_sysvar_clock.h"
#include "../../runtime/sysvar/fd_sysvar_epoch_schedule.h"
Expand Down Expand Up @@ -248,6 +249,40 @@ fd_vm_syscall_sol_get_sysvar( /**/ void * _vm,
return FD_VM_SUCCESS;
}

/* https://github.com/anza-xyz/agave/blob/v2.1.0/programs/bpf_loader/src/syscalls/mod.rs#L2043-L2118 */
int
fd_vm_syscall_sol_get_epoch_stake( /**/ void * _vm,
/**/ ulong var_addr,
FD_PARAM_UNUSED ulong r2,
FD_PARAM_UNUSED ulong r3,
FD_PARAM_UNUSED ulong r4,
FD_PARAM_UNUSED ulong r5,
/**/ ulong * _ret ) {
fd_vm_t * vm = (fd_vm_t *)_vm;

/* Var addr of 0 returns the total active stake on the cluster.
https://github.com/anza-xyz/agave/blob/v2.1.0/programs/bpf_loader/src/syscalls/mod.rs#L2057-L2075 */
if( FD_UNLIKELY( var_addr==0UL ) ) {
/* https://github.com/anza-xyz/agave/blob/v2.1.0/programs/bpf_loader/src/syscalls/mod.rs#L2065-L2066 */
FD_VM_CU_UPDATE( vm, FD_VM_SYSCALL_BASE_COST );

/* https://github.com/anza-xyz/agave/blob/v2.1.0/programs/bpf_loader/src/syscalls/mod.rs#L2074 */
*_ret = vm->instr_ctx->epoch_ctx->total_epoch_stake;
return FD_VM_SUCCESS;
}

/* https://github.com/anza-xyz/agave/blob/v2.1.0/programs/bpf_loader/src/syscalls/mod.rs#L2083-L2091 */
FD_VM_CU_UPDATE( vm, fd_ulong_sat_add( FD_VM_MEM_OP_BASE_COST,
fd_ulong_sat_add( FD_VM_SYSCALL_BASE_COST, FD_PUBKEY_FOOTPRINT / FD_VM_CPI_BYTES_PER_UNIT ) ) );

/* https://github.com/anza-xyz/agave/blob/v2.1.0/programs/bpf_loader/src/syscalls/mod.rs#L2103-L2104 */
const fd_pubkey_t * vote_address = FD_VM_MEM_HADDR_LD( vm, var_addr, FD_VM_ALIGN_RUST_PUBKEY, FD_PUBKEY_FOOTPRINT );
*_ret = fd_query_pubkey_stake( vote_address, &vm->instr_ctx->epoch_ctx->epoch_bank.stakes.vote_accounts );

return FD_VM_SUCCESS;
}

int
fd_vm_syscall_sol_get_stack_height( /**/ void * _vm,
FD_PARAM_UNUSED ulong r1,
Expand Down

0 comments on commit 1de6821

Please sign in to comment.