From 6d3ed92fc6edaa9abfcf4e382477b6a86d4ae61e Mon Sep 17 00:00:00 2001 From: Richard Patel Date: Fri, 15 Dec 2023 21:55:37 +0000 Subject: [PATCH] Add fd_sysvar_rent query helper --- src/flamenco/runtime/sysvar/Local.mk | 7 +- src/flamenco/runtime/sysvar/fd_sysvar_rent.c | 40 +++++++++++ src/flamenco/runtime/sysvar/fd_sysvar_rent.h | 17 +++++ .../runtime/sysvar/test_sysvar_rent.c | 67 +++++++++++++++++++ 4 files changed, 130 insertions(+), 1 deletion(-) create mode 100644 src/flamenco/runtime/sysvar/test_sysvar_rent.c diff --git a/src/flamenco/runtime/sysvar/Local.mk b/src/flamenco/runtime/sysvar/Local.mk index 6943ff7dc6..3af3e289e7 100644 --- a/src/flamenco/runtime/sysvar/Local.mk +++ b/src/flamenco/runtime/sysvar/Local.mk @@ -1,2 +1,7 @@ +ifdef FD_HAS_INT128 $(call add-hdrs,fd_sysvar_rent.h) - \ No newline at end of file +$(call add-objs,fd_sysvar_rent,fd_flamenco) + +$(call make-unit-test,test_sysvar_rent,test_sysvar_rent,fd_flamenco fd_funk fd_ballet fd_util) +$(call run-unit-test,test_sysvar_rent) +endif diff --git a/src/flamenco/runtime/sysvar/fd_sysvar_rent.c b/src/flamenco/runtime/sysvar/fd_sysvar_rent.c index 5444cc7ccf..32cee33633 100644 --- a/src/flamenco/runtime/sysvar/fd_sysvar_rent.c +++ b/src/flamenco/runtime/sysvar/fd_sysvar_rent.c @@ -1,11 +1,51 @@ #include "fd_sysvar_rent.h" +#include "../fd_acc_mgr.h" +#include "../fd_system_ids.h" +#include /* https://github.com/solana-labs/solana/blob/8f2c8b8388a495d2728909e30460aa40dcc5d733/sdk/program/src/rent.rs#L36 */ #define ACCOUNT_STORAGE_OVERHEAD (128) +fd_rent_t * +fd_sysvar_rent_read( fd_rent_t * result, + fd_exec_slot_ctx_t * slot_ctx ) { + + FD_BORROWED_ACCOUNT_DECL(rent_rec); + + int err = fd_acc_mgr_view( slot_ctx->acc_mgr, slot_ctx->funk_txn, &fd_sysvar_rent_id, rent_rec ); + if( FD_UNLIKELY( err != FD_ACC_MGR_SUCCESS ) ) { + FD_LOG_WARNING(( "failed to read rent sysvar: %d", err )); + return NULL; + } + + fd_bincode_decode_ctx_t decode = { + .data = rent_rec->const_data, + .dataend = rent_rec->const_data + rent_rec->const_meta->dlen, + .valloc = slot_ctx->valloc + }; + err = fd_rent_decode( result, &decode ); + if( FD_UNLIKELY( err ) ) { + FD_LOG_WARNING(( "fd_rent_decode failed" )); + return NULL; + } + + return result; +} + ulong fd_rent_exempt_minimum_balance2( fd_rent_t const * rent, ulong data_len ) { /* https://github.com/solana-labs/solana/blob/792fafe0c25ac06868e3ac80a2b13f1a5b4a1ef8/sdk/program/src/rent.rs#L72 */ return (ulong)( (double)((data_len + ACCOUNT_STORAGE_OVERHEAD) * rent->lamports_per_uint8_year) * (double)rent->exemption_threshold ); } + +ulong +fd_rent_exempt_minimum_balance( fd_exec_slot_ctx_t * slot_ctx, + ulong data_len ) { + /* TODO wire up with sysvar cache */ + fd_rent_t rent; + fd_rent_new( &rent ); + fd_rent_t * result = fd_sysvar_rent_read( &rent, slot_ctx ); + assert( result ); + return fd_rent_exempt_minimum_balance2( &rent, data_len ); +} diff --git a/src/flamenco/runtime/sysvar/fd_sysvar_rent.h b/src/flamenco/runtime/sysvar/fd_sysvar_rent.h index e3e4e78963..dad3924be9 100644 --- a/src/flamenco/runtime/sysvar/fd_sysvar_rent.h +++ b/src/flamenco/runtime/sysvar/fd_sysvar_rent.h @@ -7,6 +7,23 @@ FD_PROTOTYPES_BEGIN +/* fd_sysvar_rent_read queries the rent sysvar from the given slot + context. Rent sysvar is written into *result (may be uninitialized). + Returns result on success, NULL otherwise. */ + +fd_rent_t * +fd_sysvar_rent_read( fd_rent_t * result, + fd_exec_slot_ctx_t * slot_ctx ); + +/* fd_rent_exempt_minimum_balance returns the minimum balance needed + for an account with the given data_len to be rent exempt. slot_ctx + is a slot execution context that has a rent sysvar. (Aborts program + if rent sysvar is invalid) */ + +ulong +fd_rent_exempt_minimum_balance( fd_exec_slot_ctx_t * slot_ctx, + ulong data_len ); + /* fd_rent_exempt_minimum_balance2 returns the minimum balance needed for an account with the given data_len to be rent exempt. rent points to the current rent parameters. */ diff --git a/src/flamenco/runtime/sysvar/test_sysvar_rent.c b/src/flamenco/runtime/sysvar/test_sysvar_rent.c new file mode 100644 index 0000000000..142fa12aea --- /dev/null +++ b/src/flamenco/runtime/sysvar/test_sysvar_rent.c @@ -0,0 +1,67 @@ +#include "../../fd_flamenco.h" +#include "fd_sysvar_rent.h" + +struct fd_rent_exempt_fixture { + /* Inputs */ + ulong data_len; + ulong lamports_per_byte_year; + union { + double exemption_threshold; + ulong exemption_threshold_bits; + }; + /* Output */ + ulong min_balance; +}; + +typedef struct fd_rent_exempt_fixture fd_rent_exempt_fixture_t; + + +static fd_rent_exempt_fixture_t const +test_rent_exempt_vector[] = { + { .data_len= 0, .lamports_per_byte_year=46980000, .exemption_threshold_bits=0x3f236b06e70b7421UL, .min_balance= 890880UL }, + { .data_len= 10, .lamports_per_byte_year=46980000, .exemption_threshold_bits=0x3f236b06e70b7421UL, .min_balance= 960480UL }, + { .data_len=131097, .lamports_per_byte_year=46980000, .exemption_threshold_bits=0x3f236b06e70b7421UL, .min_balance= 913326000UL }, + { .data_len= 16392, .lamports_per_byte_year=46980000, .exemption_threshold_bits=0x3f236b06e70b7421UL, .min_balance= 114979200UL }, + { .data_len= 17, .lamports_per_byte_year=46980000, .exemption_threshold_bits=0x3f236b06e70b7421UL, .min_balance= 1009200UL }, + { .data_len= 200, .lamports_per_byte_year= 3480, .exemption_threshold_bits=0x4000000000000000UL, .min_balance= 2282880UL }, + { .data_len= 200, .lamports_per_byte_year=46980000, .exemption_threshold_bits=0x3f236b06e70b7421UL, .min_balance= 2282880UL }, + { .data_len= 20488, .lamports_per_byte_year=46980000, .exemption_threshold_bits=0x3f236b06e70b7421UL, .min_balance= 143487360UL }, + { .data_len= 24, .lamports_per_byte_year=46980000, .exemption_threshold_bits=0x3f236b06e70b7421UL, .min_balance= 1057920UL }, + { .data_len= 33, .lamports_per_byte_year=46980000, .exemption_threshold_bits=0x3f236b06e70b7421UL, .min_balance= 1120560UL }, + { .data_len= 3731, .lamports_per_byte_year=46980000, .exemption_threshold_bits=0x3f236b06e70b7421UL, .min_balance= 26858640UL }, + { .data_len= 3762, .lamports_per_byte_year= 3480, .exemption_threshold_bits=0x4000000000000000UL, .min_balance= 27074400UL }, + { .data_len= 3762, .lamports_per_byte_year=46980000, .exemption_threshold_bits=0x3f236b06e70b7421UL, .min_balance= 27074400UL }, + { .data_len=395693, .lamports_per_byte_year=46980000, .exemption_threshold_bits=0x3f236b06e70b7421UL, .min_balance=2754914160UL }, + { .data_len= 40, .lamports_per_byte_year=46980000, .exemption_threshold_bits=0x3f236b06e70b7421UL, .min_balance= 1169280UL }, + { .data_len= 6008, .lamports_per_byte_year=46980000, .exemption_threshold_bits=0x3f236b06e70b7421UL, .min_balance= 42706560UL }, + { .data_len= 82, .lamports_per_byte_year=46980000, .exemption_threshold_bits=0x3f236b06e70b7421UL, .min_balance= 1461600UL }, + { .data_len= 8, .lamports_per_byte_year= 3480, .exemption_threshold_bits=0x4000000000000000UL, .min_balance= 946560UL }, + { .data_len= 8, .lamports_per_byte_year=46980000, .exemption_threshold_bits=0x3f236b06e70b7421UL, .min_balance= 946560UL }, + { .data_len= 9, .lamports_per_byte_year=46980000, .exemption_threshold_bits=0x3f236b06e70b7421UL, .min_balance= 953520UL } +}; +#define test_rent_exempt_vector_end (fd_rent_exempt_fixture_t const *)( (uchar const *)test_rent_exempt_vector + sizeof(test_rent_exempt_vector) ) + + +int +main( int argc, + char ** argv ) { + fd_boot( &argc, &argv ); + fd_flamenco_boot( &argc, &argv ); + + fd_rent_exempt_fixture_t const * iter; + for( iter = test_rent_exempt_vector; + iter < test_rent_exempt_vector_end; + iter++ ) { + fd_rent_t rent = { + .lamports_per_uint8_year = iter->lamports_per_byte_year, + .exemption_threshold = iter->exemption_threshold, + }; + ulong min_balance = fd_rent_exempt_minimum_balance2( &rent, iter->data_len ); + FD_TEST( min_balance == iter->min_balance ); + } + + FD_LOG_NOTICE(( "pass" )); + fd_flamenco_halt(); + fd_halt(); + return 0; +}