Line data Source code
1 : #ifndef HEADER_fd_src_flamenco_runtime_program_fd_compute_budget_program_h 2 : #define HEADER_fd_src_flamenco_runtime_program_fd_compute_budget_program_h 3 : 4 : #include "../../fd_flamenco_base.h" 5 : 6 : /* FIXME: put these elsewhere */ 7 18 : #define FD_MIN_HEAP_FRAME_BYTES (32 * 1024) /* Min heap size */ 8 12 : #define FD_MAX_HEAP_FRAME_BYTES (256 * 1024) /* Max heap size */ 9 6 : #define FD_HEAP_FRAME_BYTES_GRANULARITY (1024) /* Heap frame requests must be a multiple of this number */ 10 189 : #define FD_MAX_COMPUTE_UNIT_LIMIT (1400000) /* Max compute unit limit */ 11 : 12 : /* SIMD-170 defines new default compute units for builtin, non-builtin, and migrated programs: 13 : - Any non-migrated builtins have a conservative default CU limit of 3,000 CUs. 14 : - Any migrated and non-builtins have a default CU limit of 200,000 CUs. 15 : 16 : https://github.com/anza-xyz/agave/blob/v2.1.13/runtime-transaction/src/builtin_programs_filter.rs#L9-L19 */ 17 0 : #define FD_PROGRAM_KIND_NOT_BUILTIN (0) 18 252 : #define FD_PROGRAM_KIND_BUILTIN (1) 19 6 : #define FD_PROGRAM_KIND_MIGRATING_BUILTIN (2) 20 : 21 : /* Borsh-encoded ComputeBudgetInstruction discriminants. 22 : https://github.com/anza-xyz/agave/blob/v4.0.0-beta.7/sdk/src/compute_budget.rs */ 23 : 24 6 : #define FD_COMPUTE_BUDGET_INSTR_DISC_REQUEST_UNITS_DEPRECATED (0U) 25 9 : #define FD_COMPUTE_BUDGET_INSTR_DISC_REQUEST_HEAP_FRAME (1U) 26 33 : #define FD_COMPUTE_BUDGET_INSTR_DISC_SET_COMPUTE_UNIT_LIMIT (2U) 27 9 : #define FD_COMPUTE_BUDGET_INSTR_DISC_SET_COMPUTE_UNIT_PRICE (3U) 28 3 : #define FD_COMPUTE_BUDGET_INSTR_DISC_SET_LOADED_ACCOUNTS_DATA_SIZE_LIMIT (4U) 29 : 30 : /* fd_compute_budget_instr_t is the in-memory representation of a 31 : decoded ComputeBudgetInstruction. Agave uses borsh with a 1-byte 32 : u8 discriminant. Trailing bytes are allowed (try_from_slice_unchecked). */ 33 : 34 : struct fd_compute_budget_instr { 35 : uchar discriminant; 36 : union { 37 : uint request_heap_frame; 38 : uint set_compute_unit_limit; 39 : ulong set_compute_unit_price; 40 : uint set_loaded_accounts_data_size_limit; 41 : }; 42 : }; 43 : typedef struct fd_compute_budget_instr fd_compute_budget_instr_t; 44 : 45 : /* fd_compute_budget_instr_decode decodes a borsh-serialized 46 : ComputeBudgetInstruction from [data, data+data_sz). 47 : Returns 0 on success, -1 on decode failure. On an unknown 48 : discriminant, out->discriminant is still populated before -1 is 49 : returned. */ 50 : 51 : static inline int 52 : fd_compute_budget_instr_decode( uchar const * data, 53 : ulong data_sz, 54 57 : fd_compute_budget_instr_t * out ) { 55 57 : uchar const * _payload = data; 56 57 : ulong const _payload_sz = data_sz; 57 57 : ulong _i = 0UL; 58 : 59 102 : # define CHECK( cond ) { if( FD_UNLIKELY( !(cond) ) ) { return -1; } } 60 102 : # define CHECK_LEFT( n ) CHECK( (n)<=(_payload_sz-_i) ) 61 87 : # define INC( n ) (_i += (ulong)(n)) 62 57 : # define CURSOR (_payload+_i) 63 : 64 57 : CHECK_LEFT( 1UL ); uchar disc = FD_LOAD( uchar, CURSOR ); INC( 1UL ); 65 54 : out->discriminant = disc; 66 : 67 54 : switch( disc ) { 68 6 : case FD_COMPUTE_BUDGET_INSTR_DISC_REQUEST_UNITS_DEPRECATED: 69 6 : CHECK_LEFT( 8UL ); 70 3 : break; 71 9 : case FD_COMPUTE_BUDGET_INSTR_DISC_REQUEST_HEAP_FRAME: 72 9 : CHECK_LEFT( 4UL ); out->request_heap_frame = FD_LOAD( uint, CURSOR ); INC( 4UL ); 73 6 : break; 74 18 : case FD_COMPUTE_BUDGET_INSTR_DISC_SET_COMPUTE_UNIT_LIMIT: 75 18 : CHECK_LEFT( 4UL ); out->set_compute_unit_limit = FD_LOAD( uint, CURSOR ); INC( 4UL ); 76 18 : break; 77 9 : case FD_COMPUTE_BUDGET_INSTR_DISC_SET_COMPUTE_UNIT_PRICE: 78 9 : CHECK_LEFT( 8UL ); out->set_compute_unit_price = FD_LOAD( ulong, CURSOR ); INC( 8UL ); 79 6 : break; 80 3 : case FD_COMPUTE_BUDGET_INSTR_DISC_SET_LOADED_ACCOUNTS_DATA_SIZE_LIMIT: 81 3 : CHECK_LEFT( 4UL ); out->set_loaded_accounts_data_size_limit = FD_LOAD( uint, CURSOR ); INC( 4UL ); 82 3 : break; 83 9 : default: 84 9 : return -1; 85 54 : } 86 : 87 36 : # undef CHECK 88 36 : # undef CHECK_LEFT 89 36 : # undef INC 90 36 : # undef CURSOR 91 : 92 36 : return 0; 93 54 : } 94 : 95 : FD_PROTOTYPES_BEGIN 96 : 97 : /* Validates the requested compute budget limits. Returns an error if 98 : the requested heap size is invalid, or if the loaded accounts data 99 : size limit is 0. Also bounds the compute unit and loaded 100 : accounts data size limits to a specified min / max value. 101 : 102 : https://github.com/anza-xyz/agave/blob/v2.3.1/compute-budget-instruction/src/compute_budget_instruction_details.rs#L101-L153 */ 103 : int 104 : fd_sanitize_compute_unit_limits( fd_txn_out_t * txn_out ); 105 : 106 : int 107 : fd_executor_compute_budget_program_execute_instructions( fd_bank_t const * bank, 108 : fd_txn_in_t const * txn_in, 109 : fd_txn_out_t * txn_out ); 110 : 111 : int 112 : fd_compute_budget_program_execute( fd_exec_instr_ctx_t * ctx ); 113 : 114 : FD_PROTOTYPES_END 115 : 116 : #endif /* HEADER_fd_src_flamenco_runtime_program_fd_compute_budget_program_h */