Line data Source code
1 : #ifndef HEADER_fd_src_flamenco_runtime_fd_runtime_const_h 2 : #define HEADER_fd_src_flamenco_runtime_fd_runtime_const_h 3 : 4 : #include "../leaders/fd_leaders.h" 5 : #include "../../ballet/txn/fd_txn.h" /* for fd_acct_addr_t */ 6 : #include "../vm/fd_vm_base.h" /* fd_vm_trace_t */ 7 : 8 : FD_PROTOTYPES_BEGIN 9 : 10 : #define FD_RUNTIME_MAX_FORK_CNT (4096UL) 11 : 12 : /* FD_RUNTIME_MAX_{STAKE,VOTE}_ACCOUNTS are the maximum number of stake 13 : and vote accounts that the system supports: anything larger will 14 : result in a crash. The bounds were set with the intention of making a 15 : dos vector to mint stake/vote accounts financially infeasible. A 16 : reasonable value to guard against this attack is roughly 550,000 SOL. 17 : 18 : For vote accounts, the limit is set to 19,000,000 because the rent 19 : exempt reserve of creating a valid vote account is ~0.03 SOL. For 20 : each vote account, it also must be staked. Each stake account has a 21 : rent exempt value of ~0.022 SOL. This means the cost of minting 20M 22 : vote accounts is: 23 : 19,000,000 accounts * 0.02685 SOL = 510,150 SOL. 24 : 19,000,000 accounts * 0.00228 SOL = 43,320 SOL. 25 : Total cost: 553,470 SOL. 26 : In reality, the cost is slightly higher because of transaction fees 27 : and various CU costs to create the vote and stake accounts. 28 : 29 : For stake accounts, the limit is set to 241M because the rent exempt 30 : reserve of creating a valid stake account is 31 : 241,000,000 accounts * 0.00228 SOL = 549,480 SOL. 32 : If you just consider the transaction fee of 0.000005 per account 33 : 241,000,000 * 0.000005 = 1,205 SOL. 34 : This brings our total cost to 550,685 SOL. */ 35 : 36 6 : #define FD_RUNTIME_MAX_VOTE_ACCOUNTS (19000000UL) 37 3 : #define FD_RUNTIME_MAX_STAKE_ACCOUNTS (241000000UL) 38 : 39 : /* The expected stake and vote account values are based on observed 40 : values on mainnet and testnet allowing for some growth. These are 41 : chosen to size various caches and maps: they are not intended to be 42 : exact as they are not consensus critical values. */ 43 : 44 2964 : #define FD_RUNTIME_EXPECTED_STAKE_ACCOUNTS (2000000UL) 45 2961 : #define FD_RUNTIME_EXPECTED_VOTE_ACCOUNTS (16384UL) 46 : 47 : #define FD_RUNTIME_SLOTS_PER_EPOCH (432000UL) /* 432k slots per epoch */ 48 : 49 : #define FD_RUNTIME_MAX_VOTE_ACCOUNTS_VAT (2000UL) 50 : 51 : /* Maximum amount of writable accounts per transaction 52 : https://github.com/anza-xyz/agave/blob/v3.0.8/runtime/src/bank.rs#L2946 */ 53 : #define FD_RUNTIME_MAX_WRITABLE_ACCOUNTS_PER_TRANSACTION (64UL) 54 : 55 : /* FD_RUNTIME_ACC_SZ_MAX is the protocol level hardcoded size limit of a 56 : Solana account. */ 57 : 58 9804 : #define FD_RUNTIME_ACC_SZ_MAX (10UL<<20) /* 10MiB */ 59 : 60 : /* FD_RUNTIME_WRITABLE_ACCOUNTS_MAX is the protocol level hardcoded 61 : limit of writable accounts per transaction. */ 62 : 63 : #define FD_RUNTIME_WRITABLE_ACCOUNTS_MAX (64UL) 64 : 65 : /* Genesis creation times for major Solana clusters */ 66 : 67 0 : #define FD_RUNTIME_GENESIS_CREATION_TIME_MAINNET (1584368940UL) 68 0 : #define FD_RUNTIME_GENESIS_CREATION_TIME_TESTNET (1580834132UL) 69 0 : #define FD_RUNTIME_GENESIS_CREATION_TIME_DEVNET (1597081016UL) 70 : 71 : /* FeeStructure constants. Bank is always initialized with 72 : `FeeStructure::default()` 73 : https://github.com/anza-xyz/agave/blob/v3.1.0-beta.0/runtime/src/bank.rs#L1859 74 : https://github.com/anza-xyz/solana-sdk/blob/badc2c40071e6e7f7a8e8452b792b66613c5164c/fee-structure/src/lib.rs#L100 */ 75 183 : #define FD_RUNTIME_FEE_STRUCTURE_LAMPORTS_PER_SIGNATURE (5000UL) 76 : 77 : /* Various constant values used by the runtime. */ 78 : 79 366 : #define MICRO_LAMPORTS_PER_LAMPORT (1000000UL) 80 : 81 : #define DEFAULT_HASHES_PER_TICK (12500) 82 : #define UPDATED_HASHES_PER_TICK2 (17500) 83 : #define UPDATED_HASHES_PER_TICK3 (27500) 84 : #define UPDATED_HASHES_PER_TICK4 (47500) 85 : #define UPDATED_HASHES_PER_TICK5 (57500) 86 : #define UPDATED_HASHES_PER_TICK6 (62500) 87 : #define FD_RUNTIME_MAX_HASHES_PER_TICK ((ulong)UPDATED_HASHES_PER_TICK6) 88 : 89 3426 : #define SECONDS_PER_YEAR ((double)(365.242199 * 24.0 * 60.0 * 60.0)) 90 : 91 : /* https://github.com/anza-xyz/agave/blob/0d34a1a160129c4293dac248e14231e9e773b4ce/program-runtime/src/compute_budget.rs#L139 */ 92 : #define FD_MAX_INSTRUCTION_TRACE_LENGTH (64UL) 93 : /* https://github.com/anza-xyz/agave/blob/f70ab5598ccd86b216c3928e4397bf4a5b58d723/compute-budget/src/compute_budget.rs#L13 */ 94 2937 : #define FD_MAX_INSTRUCTION_STACK_DEPTH (5UL) 95 : 96 : 97 0 : #define FD_RUNTIME_VM_TRACE_EVENT_MAX (128UL<<20) 98 0 : #define FD_RUNTIME_VM_TRACE_EVENT_DATA_MAX (2048UL) 99 : 100 0 : #define FD_RUNTIME_VM_TRACE_STATIC_FOOTPRINT (FD_RUNTIME_VM_TRACE_EVENT_MAX + sizeof(fd_vm_trace_t)) 101 0 : #define FD_RUNTIME_VM_TRACE_STATIC_ALIGN (8UL) 102 : 103 : /* Maximum CPI instruction data size. 10 KiB was chosen to ensure that 104 : CPI instructions are not more limited than transaction instructions 105 : if the size of transactions is doubled in the future. 106 : https://github.com/anza-xyz/agave/blob/v3.1.1/transaction-context/src/lib.rs#L33 */ 107 : #define FD_RUNTIME_CPI_MAX_INSTR_DATA_LEN (10240UL) 108 : 109 : /* The bpf loader's serialization footprint is bounded in the worst case 110 : by 64 unique writable accounts which are each 10MiB in size (bounded 111 : by the amount of transaction accounts). We can also have up to 112 : FD_BPF_INSTR_ACCT_MAX (255) referenced accounts in an instruction. 113 : 114 : - 8 bytes for the account count 115 : For each account: 116 : If duplicated: 117 : - 8 bytes for each duplicated account 118 : If not duplicated: 119 : - header for each unique account (96 bytes) 120 : - 1 account idx byte 121 : - 1 is_signer byte 122 : - 1 is_writable byte 123 : - 1 executable byte 124 : - 4 bytes for the original data length 125 : - 32 bytes for the key 126 : - 32 bytes for the owner 127 : - 8 bytes for the lamports 128 : - 8 bytes for the data length 129 : - 8 bytes for the rent epoch 130 : - 10MiB for the data (10485760 bytes) 131 : - 10240 bytes for resizing the data 132 : - 0 padding bytes because this is already 8 byte aligned 133 : - 8 bytes for instruction data length 134 : - 10240 bytes for the instruction data (CPI_MAX_INSTR_DATA_LEN) 135 : - 32 bytes for the program id 136 : - up to 7 bytes of padding + 255 instr accounts * 8 bytes for the 137 : direct_account_pointers_in_program_input account pointer array 138 : 139 : So the total footprint is: 140 : 8 header bytes + 141 : 191 duplicate accounts (255 instr accounts - 64 unique accounts) * 8 bytes = 1528 duplicate account bytes + 142 : 64 unique accounts * (96 header bytes + 10485760 bytes + 10240 resizing bytes) = 671750144 unique account bytes + 143 : 8 + 10240 + 32 = 10280 trailer bytes + 144 : 7 + 255 * 8 = 2047 account pointer array bytes 145 : Subtotal: 671764007 bytes, aligned up to 16 = 671764016 bytes 146 : 147 : This is a reasonably tight-ish upper bound on the input region 148 : footprint for a single instruction at a single stack depth. */ 149 19092 : #define MAX_PERMITTED_DATA_INCREASE (10240UL) // 10KB 150 12888 : #define FD_BPF_ALIGN_OF_U128 (8UL) 151 1632 : #define FD_ACCOUNT_REC_ALIGN (8UL) 152 : /* https://github.com/anza-xyz/sbpf/blob/v0.12.2/src/ebpf.rs#L37-L38 */ 153 : #define FD_RUNTIME_EBPF_HOST_ALIGN (16UL) 154 : 155 : /* FD_INSTR_ACCT_MAX is the maximum number of accounts that can 156 : be referenced by a single instruction. 157 : 158 : This is different from FD_BPF_INSTR_ACCT_MAX, which is enforced by the 159 : BPF serializer. It is possible to pass in more than FD_BPF_INSTR_ACCT_MAX 160 : instruction accounts in a transaction (for example mainnet transaction) 161 : 3eDdfZE6HswPxFKrtnQPsEmTkyL1iP57gRPEXwaqNGAqF1paGXCYYMwh7z4uQDUMgFor742sikVSQZW1gFRDhPNh). 162 : 163 : A transaction like this will be loaded and sanitized, but will fail in the 164 : bpf serialization stage. It is also possible to invoke a native program with 165 : more than FD_BPF_INSTR_ACCT_MAX instruction accounts that will execute successfully. 166 : 167 : Therefore we need to derive a bound from a worst-case transaction: one that 168 : has the maximum possible number of instruction accounts at the expense of 169 : everything else. This is a legacy transaction with a single account address, 170 : a single signature, a single instruction with empty data and as many 171 : instruction accounts as possible. 172 : 173 : Therefore, the maximum number of instruction accounts is: 174 : (MTU - fixed overhead) / (size of instruction account) 175 : = (MTU 176 : - signature count (1 byte, value=1) 177 : - signature (64 bytes) 178 : - signature count in header (1 byte) 179 : - readonly signed count (1 byte) 180 : - readonly unsigned count (1 byte) 181 : - account count (1 byte, compact-u16 value=1) 182 : - 1 account address (32 bytes) 183 : - recent blockhash (32 bytes) 184 : - instruction count (1 byte, compact-u16 value=1) 185 : - program id index (1 byte) 186 : - instruction account count (2 bytes) 187 : - data len (1 byte, value=0) 188 : = 1232 - 1 - 64 - 1 - 1 - 1 - 1 - 32 - 32 - 1 - 1 - 2 - 1 189 : = 1094 190 : 191 : TODO: SIMD-406 (https://github.com/solana-foundation/solana-improvement-documents/pull/406) 192 : limits the number of instruction accounts to 255 in transaction sanitization. 193 : 194 : Once the corresponding feature gate has been activated, we can reduce 195 : FD_INSTR_ACCT_MAX to 255. We cannot reduce this before as this would cause 196 : the result of the get_processed_sibling_instruction syscall to diverge from 197 : Agave. */ 198 6 : #define FD_INSTR_ACCT_MAX (1094UL) 199 : 200 : /* FD_BPF_INSTR_ACCT_MAX is the maximum number of accounts that 201 : an instruction that goes through the bpf loader serializer can reference. 202 : 203 : The BPF loader has a lower limit for the number of instruction accounts 204 : than is enforced in transaction sanitization. 205 : 206 : TODO: remove this limit once SIMD-406 is activated, as we can then use the 207 : same limit everywhere. 208 : 209 : https://github.com/anza-xyz/agave/blob/v3.1.4/transaction-context/src/lib.rs#L30-L32 */ 210 : #define FD_BPF_INSTR_ACCT_MAX (255UL) 211 : 212 : #define FD_BPF_LOADER_UNIQUE_ACCOUNT_FOOTPRINT(direct_mapping) \ 213 : (1UL /* dup byte */ + \ 214 : sizeof(uchar) /* is_signer */ + \ 215 : sizeof(uchar) /* is_writable */ + \ 216 : sizeof(uchar) /* executable */ + \ 217 : sizeof(uint) /* original_data_len */ + \ 218 : sizeof(fd_pubkey_t) /* key */ + \ 219 : sizeof(fd_pubkey_t) /* owner */ + \ 220 : sizeof(ulong) /* lamports */ + \ 221 : sizeof(ulong) /* data len */ + \ 222 : (direct_mapping ? FD_BPF_ALIGN_OF_U128 : FD_ULONG_ALIGN_UP( FD_RUNTIME_ACC_SZ_MAX, FD_BPF_ALIGN_OF_U128 )) + \ 223 : MAX_PERMITTED_DATA_INCREASE + \ 224 : sizeof(ulong)) /* rent_epoch */ 225 : #define FD_BPF_LOADER_DUPLICATE_ACCOUNT_FOOTPRINT (8UL) /* 1 dup byte + 7 bytes for padding */ 226 : 227 : #define FD_BPF_LOADER_INPUT_REGION_FOOTPRINT(account_lock_limit, direct_mapping) \ 228 : (FD_ULONG_ALIGN_UP( (sizeof(ulong) /* acct_cnt */ + \ 229 : account_lock_limit*FD_BPF_LOADER_UNIQUE_ACCOUNT_FOOTPRINT(direct_mapping) + \ 230 : (FD_BPF_INSTR_ACCT_MAX-account_lock_limit)*FD_BPF_LOADER_DUPLICATE_ACCOUNT_FOOTPRINT + \ 231 : sizeof(ulong) /* instr data len */ + \ 232 : FD_RUNTIME_CPI_MAX_INSTR_DATA_LEN /* instr data */ + \ 233 : sizeof(fd_pubkey_t) /* program id */ + \ 234 : (FD_BPF_ALIGN_OF_U128-1UL) + \ 235 : FD_BPF_INSTR_ACCT_MAX*sizeof(ulong) /* direct_account_pointers_in_program_input */), \ 236 : FD_RUNTIME_EBPF_HOST_ALIGN )) 237 : 238 : 239 : 240 : #define BPF_LOADER_SERIALIZATION_FOOTPRINT (671764016UL) 241 : FD_STATIC_ASSERT( BPF_LOADER_SERIALIZATION_FOOTPRINT==FD_BPF_LOADER_INPUT_REGION_FOOTPRINT(64UL, 0), bpf_loader_serialization_footprint ); 242 : 243 6 : #define FD_HARD_FORKS_MAX (64UL) 244 : 245 : /* Snapshot manifest array bounds. They are used to size arrays and 246 : validate parsed lengths throughout the entire architecture. */ 247 : 248 3 : #define FD_VOTE_ACCOUNTS_MAX (40200UL) 249 6 : #define FD_STAKE_DELEGATIONS_MAX (3000000UL) 250 270 : #define FD_EPOCH_STAKES_LEN (3UL) 251 3 : #define FD_EPOCH_VOTE_STAKES_MAX (40200UL) 252 : 253 : static const FD_FN_UNUSED fd_account_meta_t FD_ACCOUNT_META_DEFAULT = {0}; 254 : 255 : FD_PROTOTYPES_END 256 : 257 : #endif /* HEADER_fd_src_flamenco_runtime_fd_runtime_const_h */