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