Skip to content
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

flamenco: adding cpi to system program to bpf deploy #1654

Merged
merged 5 commits into from
Apr 26, 2024
Merged
Show file tree
Hide file tree
Changes from 4 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
3 changes: 3 additions & 0 deletions src/flamenco/runtime/program/Local.mk
Original file line number Diff line number Diff line change
Expand Up @@ -45,4 +45,7 @@ $(call add-objs,fd_system_program fd_system_program_nonce,fd_flamenco)

$(call add-hdrs,fd_vote_program.h)
$(call add-objs,fd_vote_program,fd_flamenco)

$(call add-hdrs,fd_native_cpi.h)
$(call add-objs,fd_native_cpi,fd_flamenco)
endif
108 changes: 10 additions & 98 deletions src/flamenco/runtime/program/fd_address_lookup_table_program.c
Original file line number Diff line number Diff line change
Expand Up @@ -10,6 +10,7 @@
#include "../../../ballet/ed25519/fd_curve25519.h"
#include "../../vm/fd_vm_syscalls.h"
#include "../../vm/fd_vm_cpi.h"
#include "fd_native_cpi.h"

#include <string.h>

Expand Down Expand Up @@ -123,95 +124,6 @@ fd_addrlut_status( fd_lookup_table_meta_t const * state,
return FD_ADDRLUT_STATUS_DEACTIVATED;
}

static inline void create_account_meta(fd_pubkey_t const * key, uchar is_signer, uchar is_writable, fd_vm_rust_account_meta_t * meta) {
meta->is_signer = is_signer;
meta->is_writable = is_writable;
fd_memcpy(meta->pubkey, key->key, sizeof(fd_pubkey_t));
}

static int execute_system_program_instruction(fd_exec_instr_ctx_t * ctx,
fd_system_program_instruction_t const * instr,
fd_vm_rust_account_meta_t const * acct_metas,
ulong acct_metas_len,
fd_pubkey_t const * signers,
ulong signers_cnt) {
fd_instr_info_t instr_info[1];
fd_instruction_account_t instruction_accounts[256];
ulong instruction_accounts_cnt;

for (ulong i = 0; i < ctx->txn_ctx->accounts_cnt; i++) {
if (memcmp(fd_solana_system_program_id.key, ctx->txn_ctx->accounts[i].key, sizeof(fd_pubkey_t)) == 0) {
instr_info->program_id = (uchar)i;
break;
}
}

ulong starting_lamports = 0;
uchar acc_idx_seen[256];
memset(acc_idx_seen, 0, 256);

instr_info->program_id_pubkey = fd_solana_system_program_id;
instr_info->acct_cnt = (ushort)acct_metas_len;
for (ulong j = 0; j < acct_metas_len; j++) {
fd_vm_rust_account_meta_t const * acct_meta = &acct_metas[j];

for (ulong k = 0; k < ctx->txn_ctx->accounts_cnt; k++) {
if (memcmp(acct_meta->pubkey, ctx->txn_ctx->accounts[k].uc, sizeof(fd_pubkey_t)) == 0) {
instr_info->acct_pubkeys[j] = ctx->txn_ctx->accounts[k];
instr_info->acct_txn_idxs[j] = (uchar)k;
instr_info->acct_flags[j] = 0;
instr_info->borrowed_accounts[j] = &ctx->txn_ctx->borrowed_accounts[k];

instr_info->is_duplicate[j] = acc_idx_seen[k];
if( FD_LIKELY( !acc_idx_seen[k] ) ) {
/* This is the first time seeing this account */
acc_idx_seen[k] = 1;
if( instr_info->borrowed_accounts[j]->const_meta != NULL ) {
starting_lamports += instr_info->borrowed_accounts[j]->const_meta->info.lamports;
}
}

if( acct_meta->is_writable ) {
instr_info->acct_flags[j] |= FD_INSTR_ACCT_FLAGS_IS_WRITABLE;
}
// TODO: should check the parent has signer flag set
if( acct_meta->is_signer ) {
instr_info->acct_flags[j] |= FD_INSTR_ACCT_FLAGS_IS_SIGNER;
} else {
for( ulong k = 0; k < signers_cnt; k++ ) {
if( memcmp( &signers[k], &acct_meta->pubkey, sizeof( fd_pubkey_t ) ) == 0 ) {
instr_info->acct_flags[j] |= FD_INSTR_ACCT_FLAGS_IS_SIGNER;
break;
}
}
}
break;
}
}

instr_info->starting_lamports = starting_lamports;
}

fd_bincode_encode_ctx_t ctx2;
void * buf = fd_valloc_malloc(ctx->valloc, FD_SYSTEM_PROGRAM_INSTRUCTION_ALIGN, sizeof(fd_system_program_instruction_t));
ctx2.data = buf;
ctx2.dataend = (uchar*)ctx2.data + sizeof(fd_system_program_instruction_t);
int err = fd_system_program_instruction_encode(instr, &ctx2);
if (err != FD_EXECUTOR_INSTR_SUCCESS) {
FD_LOG_WARNING(("Encode failed"));
return err;
}

instr_info->data = buf;
instr_info->data_sz = (ushort) sizeof(fd_system_program_instruction_t);
ulong exec_err = fd_vm_prepare_instruction(ctx->instr, instr_info, ctx, instruction_accounts, &instruction_accounts_cnt, signers, signers_cnt);
if( exec_err != FD_EXECUTOR_INSTR_SUCCESS ) {
FD_LOG_WARNING(("PREPARE FAILED"));
return (int)exec_err;
}
return fd_execute_instr( ctx->txn_ctx, instr_info );
}

// static ulong
// find_slot_hash( fd_slot_hash_t const * hashes, ulong slot ) {

Expand Down Expand Up @@ -406,8 +318,8 @@ create_lookup_table( fd_exec_instr_ctx_t * ctx,
if( required_lamports > 0UL ) {
// Create account metas
fd_vm_rust_account_meta_t * acct_metas = (fd_vm_rust_account_meta_t*) fd_valloc_malloc(ctx->valloc, FD_VM_RUST_ACCOUNT_META_ALIGN, 2 * sizeof(fd_vm_rust_account_meta_t));
create_account_meta(payer_key, 1, 1, &acct_metas[0]);
create_account_meta(lut_key, 0, 1, &acct_metas[1]);
fd_native_cpi_create_account_meta(payer_key, 1, 1, &acct_metas[0]);
fd_native_cpi_create_account_meta(lut_key, 0, 1, &acct_metas[1]);

// Create signers list
fd_pubkey_t signers[16];
Expand All @@ -419,7 +331,7 @@ create_lookup_table( fd_exec_instr_ctx_t * ctx,
instr.discriminant = fd_system_program_instruction_enum_transfer;
instr.inner.transfer = required_lamports;

int err = execute_system_program_instruction(
int err = fd_native_cpi_execute_system_program_instruction(
ctx,
&instr,
acct_metas,
Expand All @@ -434,7 +346,7 @@ create_lookup_table( fd_exec_instr_ctx_t * ctx,
}

fd_vm_rust_account_meta_t * acct_metas = (fd_vm_rust_account_meta_t*) fd_valloc_malloc(ctx->valloc, FD_VM_RUST_ACCOUNT_META_ALIGN, sizeof(fd_vm_rust_account_meta_t));
create_account_meta(lut_key, 1, 1, &acct_metas[0]);
fd_native_cpi_create_account_meta(lut_key, 1, 1, &acct_metas[0]);

// Create signers list
fd_pubkey_t signers[16];
Expand All @@ -447,7 +359,7 @@ create_lookup_table( fd_exec_instr_ctx_t * ctx,
instr.inner.allocate = 56;

// Execute allocate instruction
int err = execute_system_program_instruction(
int err = fd_native_cpi_execute_system_program_instruction(
ctx,
&instr,
acct_metas,
Expand All @@ -463,7 +375,7 @@ create_lookup_table( fd_exec_instr_ctx_t * ctx,
instr.inner.assign = fd_solana_address_lookup_table_program_id;

// Execute assign instruction
err = execute_system_program_instruction(
err = fd_native_cpi_execute_system_program_instruction(
ctx,
&instr,
acct_metas,
Expand Down Expand Up @@ -792,8 +704,8 @@ extend_lookup_table( fd_exec_instr_ctx_t * ctx,

// Create account metas
fd_vm_rust_account_meta_t * acct_metas = (fd_vm_rust_account_meta_t*) fd_valloc_malloc(ctx->valloc, FD_VM_RUST_ACCOUNT_META_ALIGN, 2 * sizeof(fd_vm_rust_account_meta_t));
create_account_meta(payer_key, 1, 1, &acct_metas[0]);
create_account_meta(lut_key, 0, 1, &acct_metas[1]);
fd_native_cpi_create_account_meta(payer_key, 1, 1, &acct_metas[0]);
fd_native_cpi_create_account_meta(lut_key, 0, 1, &acct_metas[1]);

// Create signers list
fd_pubkey_t signers[16];
Expand All @@ -805,7 +717,7 @@ extend_lookup_table( fd_exec_instr_ctx_t * ctx,
instr.discriminant = fd_system_program_instruction_enum_transfer;
instr.inner.transfer = required_lamports;

int err = execute_system_program_instruction(
int err = fd_native_cpi_execute_system_program_instruction(
ctx,
&instr,
acct_metas,
Expand Down
44 changes: 34 additions & 10 deletions src/flamenco/runtime/program/fd_bpf_loader_v3_program.c
Original file line number Diff line number Diff line change
Expand Up @@ -10,6 +10,7 @@
#include "../../vm/fd_vm_disasm.h"
#include "fd_bpf_loader_serialization.h"
#include "fd_bpf_program_util.h"
#include "fd_native_cpi.h"

#include <stdio.h>

Expand Down Expand Up @@ -668,7 +669,7 @@ fd_bpf_loader_v3_program_execute( fd_exec_instr_ctx_t ctx ) {
// }

// Drain buffer lamports to payer
int write_result = fd_instr_borrowed_account_modify( &ctx, buffer_acc,0UL, &buffer_rec);
int write_result = fd_instr_borrowed_account_modify( &ctx, buffer_acc, 0UL, &buffer_rec );
if( FD_UNLIKELY( write_result != FD_ACC_MGR_SUCCESS ) ) {
FD_LOG_WARNING(( "failed to read account metadata" ));
return FD_EXECUTOR_INSTR_ERR_MISSING_ACC;
Expand All @@ -681,23 +682,48 @@ fd_bpf_loader_v3_program_execute( fd_exec_instr_ctx_t ctx ) {
return FD_EXECUTOR_INSTR_ERR_MISSING_ACC;
}

/* Drain the buffer account to the payer before paying for the programdata account */
// FIXME: Do checked addition
ulong buffer_lamports = buffer_rec->meta->info.lamports;
payer->meta->info.lamports += buffer_lamports;
// TODO: Does this mean this account is dead?
buffer_rec->meta->info.lamports = 0;

// TODO: deploy program
err = setup_program(&ctx, buffer_rec->data + BUFFER_METADATA_SIZE, buffer_data_len);
if (err != 0) {
err = setup_program( &ctx, buffer_rec->data + BUFFER_METADATA_SIZE, buffer_data_len );
if ( err != 0 ) {
return err;
}

// Create program data account
// fd_funk_rec_t * program_data_rec = NULL;
ulong sz2 = PROGRAMDATA_METADATA_SIZE + instruction.inner.deploy_with_max_data_len.max_data_len;
/* Actually invoke the system program via native cpi */
fd_system_program_instruction_create_account_t create_acct;
create_acct.lamports = fd_rent_exempt_minimum_balance(ctx.slot_ctx, programdata_len);
create_acct.space = programdata_len;
create_acct.owner = ctx.instr->program_id_pubkey;

fd_system_program_instruction_t FD_FN_UNUSED instr;
instr.discriminant = fd_system_program_instruction_enum_create_account;
instr.inner.create_account = create_acct;

/* Setup the accounts passed into the system program create call. Index zero and
one are the from and to accounts respectively for the transfer. The buffer
account is also passed in here. */ //TODO: free these afterwards
fd_vm_rust_account_meta_t * acct_metas = (fd_vm_rust_account_meta_t *)
fd_valloc_malloc( ctx.valloc, FD_VM_RUST_ACCOUNT_META_ALIGN, 2 * sizeof(fd_vm_rust_account_meta_t) );
fd_native_cpi_create_account_meta( payer_acc, 1, 1, &acct_metas[0] );
fd_native_cpi_create_account_meta( programdata_acc, 1, 1, &acct_metas[1] );
fd_pubkey_t signers[2];
ulong signers_cnt = 2;
signers[0] = *payer_acc;
signers[1] = *programdata_acc;

fd_native_cpi_execute_system_program_instruction( &ctx, &instr, acct_metas, 2, signers, signers_cnt );

fd_valloc_free( ctx.valloc, acct_metas );

ulong total_size = PROGRAMDATA_METADATA_SIZE + instruction.inner.deploy_with_max_data_len.max_data_len;
fd_borrowed_account_t * programdata_rec = NULL;
int modify_err = fd_instr_borrowed_account_modify( &ctx, programdata_acc, sz2, &programdata_rec);
int modify_err = fd_instr_borrowed_account_modify( &ctx, programdata_acc, total_size, &programdata_rec );
FD_TEST( modify_err == FD_ACC_MGR_SUCCESS );
fd_account_meta_t * meta = programdata_rec->meta;
uchar * acct_data = programdata_rec->data;
Expand All @@ -723,12 +749,10 @@ fd_bpf_loader_v3_program_execute( fd_exec_instr_ctx_t ctx ) {
meta->info.lamports = fd_rent_exempt_minimum_balance(ctx.slot_ctx, meta->dlen);
meta->info.rent_epoch = 0;

// payer->meta->info.lamports += buffer_rec->meta->info.lamports;
payer->meta->info.lamports -= buffer_lamports;
buffer_data_len = fd_ulong_sat_sub(buffer_rec->meta->dlen, BUFFER_METADATA_SIZE);

err = fd_instr_borrowed_account_view(&ctx, buffer_acc, &buffer_rec);
fd_memcpy( acct_data+PROGRAMDATA_METADATA_SIZE, buffer_rec->const_data+BUFFER_METADATA_SIZE, buffer_data_len );
fd_memcpy( acct_data + PROGRAMDATA_METADATA_SIZE, buffer_rec->const_data + BUFFER_METADATA_SIZE, buffer_data_len );
// fd_memset( acct_data+PROGRAMDATA_METADATA_SIZE+buffer_data_len, 0, instruction.inner.deploy_with_max_data_len.max_data_len-buffer_data_len );
// FD_LOG_WARNING(("AAA: %x", *(acct_data+meta->dlen-3)));
programdata_rec->meta->slot = ctx.slot_ctx->slot_bank.slot;
Expand Down
97 changes: 97 additions & 0 deletions src/flamenco/runtime/program/fd_native_cpi.c
Original file line number Diff line number Diff line change
@@ -0,0 +1,97 @@
#include "../fd_account.h"
#include "../../vm/fd_vm_syscalls.h"
#include "../../vm/fd_vm_interp.h"

int
fd_native_cpi_execute_system_program_instruction( fd_exec_instr_ctx_t * ctx,
fd_system_program_instruction_t const * instr,
fd_vm_rust_account_meta_t const * acct_metas,
ulong acct_metas_len,
fd_pubkey_t const * signers,
ulong signers_cnt ) {
fd_instr_info_t instr_info[1];
fd_instruction_account_t instruction_accounts[256];
ulong instruction_accounts_cnt;

for ( ulong i = 0; i < ctx->txn_ctx->accounts_cnt; i++ ) {
if ( memcmp( fd_solana_system_program_id.key, ctx->txn_ctx->accounts[i].key, sizeof(fd_pubkey_t) ) == 0 ) {
instr_info->program_id = (uchar)i;
break;
}
}

ulong starting_lamports = 0;
uchar acc_idx_seen[256];
memset( acc_idx_seen, 0, 256 );

instr_info->program_id_pubkey = fd_solana_system_program_id;
instr_info->acct_cnt = (ushort)acct_metas_len;
for ( ulong j = 0; j < acct_metas_len; j++ ) {
fd_vm_rust_account_meta_t const * acct_meta = &acct_metas[j];

for ( ulong k = 0; k < ctx->txn_ctx->accounts_cnt; k++ ) {
if ( memcmp( acct_meta->pubkey, ctx->txn_ctx->accounts[k].uc, sizeof(fd_pubkey_t) ) == 0 ) {
instr_info->acct_pubkeys[j] = ctx->txn_ctx->accounts[k];
instr_info->acct_txn_idxs[j] = (uchar)k;
instr_info->acct_flags[j] = 0;
instr_info->borrowed_accounts[j] = &ctx->txn_ctx->borrowed_accounts[k];

instr_info->is_duplicate[j] = acc_idx_seen[k];
if( FD_LIKELY( !acc_idx_seen[k] ) ) {
/* This is the first time seeing this account */
acc_idx_seen[k] = 1;
if( instr_info->borrowed_accounts[j]->const_meta != NULL ) {
starting_lamports += instr_info->borrowed_accounts[j]->const_meta->info.lamports;
}
}

if( acct_meta->is_writable ) {
instr_info->acct_flags[j] |= FD_INSTR_ACCT_FLAGS_IS_WRITABLE;
}
// TODO: should check the parent has signer flag set
if( acct_meta->is_signer ) {
instr_info->acct_flags[j] |= FD_INSTR_ACCT_FLAGS_IS_SIGNER;
} else {
for( ulong k = 0; k < signers_cnt; k++ ) {
if( memcmp( &signers[k], &acct_meta->pubkey, sizeof( fd_pubkey_t ) ) == 0 ) {
instr_info->acct_flags[j] |= FD_INSTR_ACCT_FLAGS_IS_SIGNER;
break;
}
}
}
break;
}
}

instr_info->starting_lamports = starting_lamports;
}

fd_bincode_encode_ctx_t ctx2;
uchar buf[4096UL];
ctx2.data = buf;
ctx2.dataend = (uchar*)ctx2.data + sizeof(fd_system_program_instruction_t);
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
ctx2.dataend = (uchar*)ctx2.data + sizeof(fd_system_program_instruction_t);
ctx2.dataend = (uchar*)ctx2.data + sizeof(buf);

int err = fd_system_program_instruction_encode( instr, &ctx2 );
if (err != FD_EXECUTOR_INSTR_SUCCESS) {
FD_LOG_WARNING(("Encode failed"));
return err;
}

instr_info->data = buf;
instr_info->data_sz = (ushort) sizeof(fd_system_program_instruction_t);
ulong exec_err = fd_vm_prepare_instruction( ctx->instr, instr_info, ctx, instruction_accounts,
&instruction_accounts_cnt, signers, signers_cnt );
if( exec_err != FD_EXECUTOR_INSTR_SUCCESS ) {
FD_LOG_WARNING(("Preparing instruction failed"));
return (int)exec_err;
}

return fd_execute_instr( ctx->txn_ctx, instr_info );
}

void
fd_native_cpi_create_account_meta( fd_pubkey_t const * key, uchar is_signer,
uchar is_writable, fd_vm_rust_account_meta_t * meta ) {
meta->is_signer = is_signer;
meta->is_writable = is_writable;
fd_memcpy( meta->pubkey, key->key, sizeof(fd_pubkey_t) );
}
24 changes: 24 additions & 0 deletions src/flamenco/runtime/program/fd_native_cpi.h
Original file line number Diff line number Diff line change
@@ -0,0 +1,24 @@
#ifndef HEADER_fd_src_flamenco_runtime_program_fd_native_program_cpi_h
#define HEADER_fd_src_flamenco_runtime_program_fd_native_program_cpi_h

#include "../../fd_flamenco_base.h"
#include "../fd_executor.h"
#include "../fd_runtime.h"

FD_PROTOTYPES_BEGIN

int
fd_native_cpi_execute_system_program_instruction( fd_exec_instr_ctx_t * ctx,
fd_system_program_instruction_t const * instr,
fd_vm_rust_account_meta_t const * acct_metas,
ulong acct_metas_len,
fd_pubkey_t const * signers,
ulong signers_cnt );

void
fd_native_cpi_create_account_meta( fd_pubkey_t const * key, uchar is_signer,
uchar is_writable, fd_vm_rust_account_meta_t * meta );

FD_PROTOTYPES_END

#endif /* HEADER_fd_src_flamenco_runtime_program_fd_native_program_cpi_h */
1 change: 1 addition & 0 deletions src/flamenco/runtime/tests/Local.mk
Original file line number Diff line number Diff line change
Expand Up @@ -26,6 +26,7 @@ run-runtime-test-1: $(OBJDIR)/unit-test/test_runtime $(OBJDIR)/bin/fd_frank_ledg
OBJDIR=$(OBJDIR) src/flamenco/runtime/tests/run_ledger_tests.sh -l testnet-519 -s snapshot-255311992-Fju7xb3XaTY6SBxkGcsKko15EGAqnvdfkXBd1o6agPDq.tar.zst -p 64 -m 1000000 -e 255312010
OBJDIR=$(OBJDIR) src/flamenco/runtime/tests/run_ledger_tests.sh -l mainnet-251418170 -s snapshot-251418170-8sAkojR9PYTZvqiQZ1VWu27ewX5tXeVdC97wMXAtgHnT.tar.zst -p 64 -m 2000000 -e 251418233
OBJDIR=$(OBJDIR) src/flamenco/runtime/tests/run_ledger_tests.sh -l mainnet-257066033 -s snapshot-257066033-AD2nFFTCtZVmo5nXLVsQMV1hiQDjzoEBXibRicBJc5Vw.tar.zst -p 16 -m 5000000 -e 257066038 --zst
OBJDIR=$(OBJDIR) src/flamenco/runtime/tests/run_ledger_tests.sh -l mainnet-257066844 -s snapshot-257066844-B5JpRYzvMa4iyQeR8w9co4y7oEayphgbXVeQHXLDoWvV.tar.zst -p 16 -m 5000000 -e 257066849 --zst

# src/flamenco/runtime/run_bpf_tests.sh

Expand Down
Loading