Skip to content

runtime: make BPF Loader v3 structs zero-alloc #5079

New issue

Have a question about this project? Sign up for a free GitHub account to open an issue and contact its maintainers and the community.

By clicking “Sign up for GitHub”, you agree to our terms of service and privacy statement. We’ll occasionally send you account related emails.

Already on GitHub? Sign in to your account

Open
wants to merge 2 commits into
base: main
Choose a base branch
from
Open
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
10 changes: 6 additions & 4 deletions src/flamenco/runtime/fd_runtime.c
Original file line number Diff line number Diff line change
Expand Up @@ -2365,8 +2365,8 @@ fd_new_target_program_data_account( fd_exec_slot_ctx_t * slot_ctx,

/* https://github.com/anza-xyz/agave/blob/v2.1.0/runtime/src/bank/builtins/core_bpf_migration/mod.rs#L118-L125 */
if( config_upgrade_authority_address!=NULL ) {
if( FD_UNLIKELY( state->inner.buffer.authority_address==NULL ||
memcmp( config_upgrade_authority_address, state->inner.buffer.authority_address, sizeof(fd_pubkey_t) ) ) ) {
if( FD_UNLIKELY( !state->inner.buffer.has_authority_address ||
!fd_pubkey_eq( config_upgrade_authority_address, &state->inner.buffer.authority_address ) ) ) {
return -1;
}
}
Expand All @@ -2386,11 +2386,13 @@ fd_new_target_program_data_account( fd_exec_slot_ctx_t * slot_ctx,
.discriminant = fd_bpf_upgradeable_loader_state_enum_program_data,
.inner = {
.program_data = {
.slot = slot_ctx->slot_bank.slot,
.upgrade_authority_address = config_upgrade_authority_address
.slot = slot_ctx->slot_bank.slot
}
}
};
fd_types_option_flat_from_nullable(
Copy link
Contributor

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

fd_types_option_flat_from_nullable ends up getting repeated everywhere we set up a bpf loader state struct. I'd prefer using a setup / init function for fd_bpf_upfradeable_loader_state_t to reduce the repetition.

Copy link
Contributor Author

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

@cali-jumptrading Good point. We could also have a macro that expands to initializer syntax like this:

my_struct_t s = {
  .inner = {
    fd_types_option_flat_init_from_nullable(  option_name, pointer ),
    .bla = x,
  }
};

The macro name is disgusting. If you have better ideas, please shout!

programdata_metadata.inner.program_data, upgrade_authority_address,
config_upgrade_authority_address );

/* https://github.com/anza-xyz/agave/blob/v2.1.0/runtime/src/bank/builtins/core_bpf_migration/mod.rs#L139-L144 */
new_target_program_data_account->vt->set_lamports( new_target_program_data_account, lamports );
Expand Down
98 changes: 53 additions & 45 deletions src/flamenco/runtime/program/fd_bpf_loader_program.c

Large diffs are not rendered by default.

16 changes: 8 additions & 8 deletions src/flamenco/runtime/program/fd_bpf_program_util.c
Original file line number Diff line number Diff line change
Expand Up @@ -82,17 +82,17 @@ static int
fd_bpf_get_executable_program_content_for_upgradeable_loader( fd_exec_slot_ctx_t * slot_ctx,
fd_txn_account_t * program_acc,
uchar const ** program_data,
ulong * program_data_len,
fd_spad_t * runtime_spad ) {
ulong * program_data_len ) {
FD_TXN_ACCOUNT_DECL( programdata_acc );

fd_bpf_upgradeable_loader_state_t * program_account_state =
fd_bincode_decode_spad(
bpf_upgradeable_loader_state, runtime_spad,
fd_bpf_upgradeable_loader_state_t program_account_state[1];
if( FD_UNLIKELY( !fd_bincode_decode_flat(
program_account_state,
bpf_upgradeable_loader_state,
program_acc->vt->get_data( program_acc ),
program_acc->vt->get_data_len( program_acc ),
NULL );
if( FD_UNLIKELY( !program_account_state ) ) {
NULL
) ) ) {
return -1;
}
if( !fd_bpf_upgradeable_loader_state_is_program( program_account_state ) ) {
Expand Down Expand Up @@ -182,7 +182,7 @@ fd_bpf_create_bpf_program_cache_entry( fd_exec_slot_ctx_t * slot_ctx,

int res;
if( !memcmp( program_acc->vt->get_owner( program_acc ), fd_solana_bpf_loader_upgradeable_program_id.key, sizeof(fd_pubkey_t) ) ) {
res = fd_bpf_get_executable_program_content_for_upgradeable_loader( slot_ctx, program_acc, &program_data, &program_data_len, runtime_spad );
res = fd_bpf_get_executable_program_content_for_upgradeable_loader( slot_ctx, program_acc, &program_data, &program_data_len );
} else if( !memcmp( program_acc->vt->get_owner( program_acc ), fd_solana_bpf_loader_v4_program_id.key, sizeof(fd_pubkey_t) ) ) {
res = fd_bpf_get_executable_program_content_for_v4_loader( program_acc, &program_data, &program_data_len );
} else {
Expand Down
3 changes: 0 additions & 3 deletions src/flamenco/runtime/program/fd_builtin_programs.h
Original file line number Diff line number Diff line change
Expand Up @@ -3,9 +3,6 @@

#include "../../fd_flamenco_base.h"
#include "../../runtime/fd_system_ids.h"
#include "../../features/fd_features.h"
#include "../context/fd_exec_epoch_ctx.h"
#include "../context/fd_exec_slot_ctx.h"
#include "../fd_system_ids.h"
#include "../fd_system_ids_pp.h"

Expand Down
55 changes: 54 additions & 1 deletion src/flamenco/types/fd_bincode.h
Original file line number Diff line number Diff line change
Expand Up @@ -2,7 +2,6 @@
#define HEADER_fd_src_util_encoders_fd_bincode_h

#include "../../util/fd_util.h"
#include "../../util/valloc/fd_valloc.h"

typedef void
(* fd_types_walk_fn_t)( void * self,
Expand Down Expand Up @@ -552,4 +551,58 @@ static inline int fd_archive_decode_check_length( fd_bincode_decode_ctx_t * ctx,
#define fd_bincode_decode_scratch( type, buf, buf_sz, perr ) \
fd_bincode_decode1_scratch( type, buf, buf_sz, perr, NULL )

/* fd_bincode_decode_flat decodes a bincode type without dynamic
allocations. */

#define fd_bincode_decode_flat( outp, type, buf, buf_sz, perr ) \
__extension__({ \
__typeof__(*outp) * const outp_ = (outp); \
__typeof__(*outp_) * out = NULL; \
void const * const buf_ = (buf); \
ulong const buf_sz_ = (buf_sz); \
int * perr_ = (perr); \
fd_bincode_decode_ctx_t ctx = {0}; \
if( perr_ ) *perr_ = -1; \
ctx.data = (void const *)( buf_ ); \
ctx.dataend = (void const *)( (ulong)ctx.data + buf_sz_ ); \
ulong total_sz = 0UL; \
int err = fd_##type##_decode_footprint( &ctx, &total_sz ); \
if( FD_LIKELY( err==FD_BINCODE_SUCCESS ) ) { \
if( FD_UNLIKELY( sizeof(*out)!=total_sz ) ) { \
FD_LOG_ERR(( "fd_bincode_" #type "_decode failed: decode requires %lu bytes, but out var is only %lu bytes", sizeof(*out), total_sz )); \
} \
out = fd_##type##_decode( outp_, &ctx ); \
} \
if( perr_ ) *perr_ = err; \
out; \
})

#define fd_bincode_decode_scratch( type, buf, buf_sz, perr ) \
fd_bincode_decode1_scratch( type, buf, buf_sz, perr, NULL )

/* Helpers for dealing with option types */

/* fd_types_option_flat_from_nullable populates a flat option from a
pointer. Sets target.has_name = 0 if pointer is NULL, otherwise sets
target.has_name = 1, and sets target.name = *pointer */

#define fd_types_option_flat_from_nullable( target, name, pointer ) \
{ \
__typeof__ (pointer) ptr = (pointer); \
(target . has_##name) = !!ptr; \
if( ptr ) (target . name) = *ptr; \
}

/* fd_types_option_flat_to_nullable creates a nullable pointer to a flat
Copy link
Contributor

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

Suggested change
/* fd_types_option_flat_to_nullable creates a nullable pointer to a flat
/* fd_types_option_flat_to_nullable creates a nullable pointer from a flat

option. Returns NULL if target.has_name == 0, otherwise returns
&target.name */

#define fd_types_option_flat_to_nullable( target, name ) \
__extension__({ \
__typeof__( &( (target . name) ) ) ptr; \
if( (target . has_##name) ) ptr = &(target . name); \
else ptr = NULL; \
ptr; \
})

#endif /* HEADER_fd_src_util_encoders_fd_bincode_h */
24 changes: 6 additions & 18 deletions src/flamenco/types/fd_fuzz_types.h
Original file line number Diff line number Diff line change
Expand Up @@ -2748,15 +2748,9 @@ void *fd_bpf_upgradeable_loader_state_buffer_generate( void *mem, void **alloc_m
*alloc_mem = (uchar *) *alloc_mem + sizeof(fd_bpf_upgradeable_loader_state_buffer_t);
fd_bpf_upgradeable_loader_state_buffer_new(mem);
{
uchar is_null = fd_rng_uchar( rng ) % 2;
if( !is_null ) {
self->authority_address = (fd_pubkey_t *) *alloc_mem;
*alloc_mem = (uchar *) *alloc_mem + sizeof(fd_pubkey_t);
fd_pubkey_new( self->authority_address );
fd_pubkey_generate( self->authority_address, alloc_mem, rng );
}
else {
self->authority_address = NULL;
self->has_authority_address = fd_rng_uchar( rng ) % 2;
if( self->has_authority_address ) {
fd_pubkey_generate( &self->authority_address, alloc_mem, rng );
}
}
return mem;
Expand All @@ -2776,15 +2770,9 @@ void *fd_bpf_upgradeable_loader_state_program_data_generate( void *mem, void **a
fd_bpf_upgradeable_loader_state_program_data_new(mem);
self->slot = fd_rng_ulong( rng );
{
uchar is_null = fd_rng_uchar( rng ) % 2;
if( !is_null ) {
self->upgrade_authority_address = (fd_pubkey_t *) *alloc_mem;
*alloc_mem = (uchar *) *alloc_mem + sizeof(fd_pubkey_t);
fd_pubkey_new( self->upgrade_authority_address );
fd_pubkey_generate( self->upgrade_authority_address, alloc_mem, rng );
}
else {
self->upgrade_authority_address = NULL;
self->has_upgrade_authority_address = fd_rng_uchar( rng ) % 2;
if( self->has_upgrade_authority_address ) {
fd_pubkey_generate( &self->upgrade_authority_address, alloc_mem, rng );
}
}
return mem;
Expand Down
60 changes: 22 additions & 38 deletions src/flamenco/types/fd_types.c

Some generated files are not rendered by default. Learn more about how customized files appear on GitHub.

6 changes: 4 additions & 2 deletions src/flamenco/types/fd_types.h

Some generated files are not rendered by default. Learn more about how customized files appear on GitHub.

4 changes: 2 additions & 2 deletions src/flamenco/types/fd_types.json
Original file line number Diff line number Diff line change
Expand Up @@ -1785,7 +1785,7 @@
"name": "bpf_upgradeable_loader_state_buffer",
"type": "struct",
"fields": [
{ "name": "authority_address", "type": "option", "element": "pubkey" }
{ "name": "authority_address", "type": "option", "element": "pubkey", "flat": true }
]
},
{
Expand All @@ -1800,7 +1800,7 @@
"type": "struct",
"fields": [
{ "name": "slot", "type": "ulong" },
{ "name": "upgrade_authority_address", "type": "option", "element": "pubkey" }
{ "name": "upgrade_authority_address", "type": "option", "element": "pubkey", "flat": true }
]
},
{
Expand Down
Loading