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 "../../ballet/txn/fd_txn.h" /* for FD_TXN_ACCT_ADDR_MAX */ 5 : #include "../vm/fd_vm_base.h" /* fd_vm_trace_t */ 6 : 7 : FD_PROTOTYPES_BEGIN 8 : 9 : /* FD_INSTR_SIGNERS_MAX: The (inclusive) maximum number of distinct 10 : signers a single instruction can have. 11 : 12 : This is the runtime bound, which is larger than the transaction 13 : parser bound because during CPI calls PDAs can be promoted to 14 : signers. Therefore in the runtime, the effective limit is the 15 : amount of distinct accounts the transaction can access. */ 16 : #define FD_INSTR_SIGNERS_MAX FD_TXN_ACCT_ADDR_MAX 17 : 18 : /* FD_RUNTIME_MAX_STAKE_ACCOUNTS is the maximum number of stake accounts 19 : that the system supports: anything larger will result in a crash. 20 : The bounds were set with the intention of making a dos vector to mint 21 : stake accounts financially infeasible. Similarly, the number of 22 : stake accounts that the system supports is also the maximum number of 23 : staked vote accounts that the system supports since in the worst case 24 : we have one stake account per vote account. 25 : 26 : Prior to the feature upgrade_bpf_stake_program_to_v5, which 27 : introduced the minimum 1 SOL delegation amount, there were 1.6 28 : million stake accounts on mainnet. With a bound of 2.15 million 29 : stake accounts, this means an attacker would need roughly 0.75 30 : million SOL to attack the system which is a reasonable bound. */ 31 : 32 0 : #define FD_RUNTIME_MAX_STAKE_ACCOUNTS (2150000UL) 33 : 34 : /* FD_RUNTIME_MAX_STAKE_DELEGATION_DISK_RECORDS is the maximum number 35 : of records in each stake-delegation disk tier. */ 36 : 37 : #define FD_RUNTIME_MAX_STAKE_DELEGATION_DISK_RECORDS (100000000UL) 38 : 39 : /* The runtime only supports post-validator_admission_ticket banks. The 40 : accumulator can still see one distinct voter per stake account before 41 : the final eligible set is reduced to the VAT limit below. */ 42 : 43 0 : #define FD_RUNTIME_MAX_STAKED_VOTE_ACCOUNTS (FD_RUNTIME_MAX_STAKE_ACCOUNTS) 44 : 45 : /* Maximum number of vote accounts eligible to receive rewards or 46 : meaningfully contribute to consensus after 47 : validator_admission_ticket activation. */ 48 : 49 248601 : #define FD_RUNTIME_MAX_VAT_VOTE_ACCOUNTS (2000UL) 50 : 51 : /* Bound on the snapshot manifest's vote account map, which holds 52 : every staked voter rather than only the VAT-admitted set. Wait 53 : for supermajority is the sole consumer. */ 54 : 55 6 : #define FD_RUNTIME_MAX_SNAPSHOT_VOTE_ACCOUNTS (40200UL) 56 : 57 : /* The maximum number of epoch stakes that are needed to be parsed out 58 : from the manifest. Agave produced snapshots include 5 epoch stakes 59 : (MAX_LEADER_SCHEDULE_STAKES), E-3..E+1 for a snapshot in epoch E, and 60 : a block footer may carry a finalization cert from any of E-3..E, so 61 : all 5 are loaded. */ 62 : 63 1056 : #define FD_RUNTIME_MANIFEST_EPOCH_STAKES_LEN (5UL) 64 : 65 12 : #define FD_RUNTIME_SLOTS_PER_EPOCH (432000UL) 66 : 67 : /* FD_RUNTIME_ACC_SZ_MAX is the protocol level hardcoded size limit of a 68 : Solana account. */ 69 : 70 31458897 : #define FD_RUNTIME_ACC_SZ_MAX (10UL<<20) /* 10MiB */ 71 : 72 : /* Bound the number of distinct writable accounts that can enter the 73 : cost tracker in a 200ms block with raise_block_limits_to_100m, a 50M 74 : CU block (FD_SLOT_PARAMS_200MS_MAX_BLOCK_UNITS*100/60). Clusters 75 : with a larger block cost limit (slower slots or [development.bench]) 76 : are not supported. A transaction with w writable accounts costs at 77 : least 720+300*w CUs and carries at most 64 writable accounts. Thus W 78 : writables need at least ceil(W/64) transactions: 79 : 80 : 300*W + 720*ceil(W/64) <= 50000000 81 : 82 : The largest solution is 160640: 2510 full 64-account transactions 83 : cost 49999200 CUs. A 160641st writable would cost 50000220 CUs. */ 84 : 85 0 : #define FD_RUNTIME_MAX_TXN_ACC_WRITES_PER_SLOT (160640UL) 86 : 87 : /* With 100M stake accounts, ceil(100M/4096)=24415 partitions. 88 : Assuming uniform hashing, one partition has 89 : X~Binomial(100M,1/24415), with mean 4095.84. So, 90 : P(any partition has X>8192) <= 24415*P(X>=8193) ~= 5.75e-686. */ 91 : 92 0 : #define FD_RUNTIME_MAX_EPOCH_REWARD_ACC_WRITES_PER_SLOT (8192UL) 93 : 94 : /* FD_RUNTIME_MAX_ACC_WRITES_PER_SLOT defines a reasonable upper bound 95 : on the number of unique accounts that can be written to in a single 96 : slot. The worst case can be defined by: 97 : 1. Worst case number of writable accounts in a slot from worst-case 98 : transactions. This bound comes from the cost tracker: 160640. 99 : 2. During partitioned epoch rewards. A reasonable upper bound is 100 : 8192 accounts per stake partition since the odds of this happening 101 : are very very low. 102 : 3. All of the other account updates that can happen in a slot. In 103 : the standard case this would be the sysvars, the incinerator, 104 : and the fee collector (7 accounts.) 105 : - Clock 106 : - SlotHashes 107 : - RecentBlockhashes 108 : - SlotHistory 109 : - Epoch Rewards 110 : - Fee Collector 111 : - Incinerator 112 : - Alpenclock (Alpenglow) 113 : - Leader Vote Account (Alpenglow) 114 : 4. Alpenglow rewards can touch the full VAT vote set up to 2 times. 115 : This happens in the case near the epoch boundary where the reward 116 : cert and the finalization cert are in two different epochs. */ 117 0 : #define FD_RUNTIME_MAX_ACC_WRITES_PER_SLOT (FD_RUNTIME_MAX_TXN_ACC_WRITES_PER_SLOT + \ 118 0 : FD_RUNTIME_MAX_EPOCH_REWARD_ACC_WRITES_PER_SLOT + \ 119 0 : 9UL + \ 120 0 : (2UL * FD_RUNTIME_MAX_VAT_VOTE_ACCOUNTS)) 121 : 122 : /* FD_RUNTIME_ACC_DATA_GROWTH_MAX_PER_TXN is the protocol level hardcoded 123 : limit on the total account data growth (sum of resize deltas) across a 124 : single transaction. Defined here (alongside FD_RUNTIME_ACC_SZ_MAX) so 125 : low-level size bounds can reference it; fd_borrowed_account.h's 126 : MAX_PERMITTED_ACCOUNT_DATA_ALLOCS_PER_TXN and fd_vm_private.h's 127 : FD_MAX_ACCOUNT_DATA_GROWTH_PER_TRANSACTION are kept equal to this via 128 : static asserts in those headers. */ 129 : 130 : #define FD_RUNTIME_ACC_DATA_GROWTH_MAX_PER_TXN (2UL*FD_RUNTIME_ACC_SZ_MAX) /* 20MiB */ 131 : 132 : /* FD_RUNTIME_WRITABLE_ACCOUNTS_MAX is the protocol level hardcoded 133 : limit of writable accounts per transaction. */ 134 : 135 : #define FD_RUNTIME_WRITABLE_ACCOUNTS_MAX (64UL) 136 : 137 : /* Genesis creation times for major Solana clusters */ 138 : 139 0 : #define FD_RUNTIME_GENESIS_CREATION_TIME_MAINNET (1584368940UL) 140 0 : #define FD_RUNTIME_GENESIS_CREATION_TIME_TESTNET (1580834132UL) 141 0 : #define FD_RUNTIME_GENESIS_CREATION_TIME_DEVNET (1597081016UL) 142 : 143 : /* FeeStructure constants. Bank is always initialized with 144 : `FeeStructure::default()` 145 : https://github.com/anza-xyz/agave/blob/v3.1.0-beta.0/runtime/src/bank.rs#L1859 146 : https://github.com/anza-xyz/solana-sdk/blob/badc2c40071e6e7f7a8e8452b792b66613c5164c/fee-structure/src/lib.rs#L100 */ 147 594 : #define FD_RUNTIME_FEE_STRUCTURE_LAMPORTS_PER_SIGNATURE (5000UL) 148 : 149 : /* Various constant values used by the runtime. */ 150 : 151 1182 : #define MICRO_LAMPORTS_PER_LAMPORT (1000000UL) 152 : 153 : #define DEFAULT_HASHES_PER_TICK (12500) 154 3 : #define FD_RUNTIME_MAX_HASHES_PER_TICK (62500UL) 155 : 156 4740 : #define SECONDS_PER_YEAR ((double)(365.242199 * 24.0 * 60.0 * 60.0)) 157 : 158 : /* https://github.com/anza-xyz/agave/blob/0d34a1a160129c4293dac248e14231e9e773b4ce/program-runtime/src/compute_budget.rs#L139 */ 159 : #define FD_MAX_INSTRUCTION_TRACE_LENGTH (64UL) 160 : /* https://github.com/anza-xyz/agave/blob/f70ab5598ccd86b216c3928e4397bf4a5b58d723/compute-budget/src/compute_budget.rs#L13 */ 161 122304 : #define FD_MAX_INSTRUCTION_STACK_DEPTH (5UL) 162 : 163 : 164 0 : #define FD_RUNTIME_VM_TRACE_EVENT_MAX (128UL<<20) 165 : 166 0 : #define FD_RUNTIME_VM_TRACE_STATIC_FOOTPRINT (FD_RUNTIME_VM_TRACE_EVENT_MAX + sizeof(fd_vm_trace_t)) 167 0 : #define FD_RUNTIME_VM_TRACE_STATIC_ALIGN (8UL) 168 : 169 : /* Maximum CPI instruction data size. 10 KiB was chosen to ensure that 170 : CPI instructions are not more limited than transaction instructions 171 : if the size of transactions is doubled in the future. 172 : https://github.com/anza-xyz/agave/blob/v3.1.1/transaction-context/src/lib.rs#L33 */ 173 : #define FD_RUNTIME_CPI_MAX_INSTR_DATA_LEN (10240UL) 174 : 175 : /* The bpf loader's serialization footprint (the size of the per-stack- 176 : frame input region buffer) is bounded by FD_BPF_LOADER_INPUT_REGION_ 177 : FOOTPRINT / BPF_LOADER_SERIALIZATION_FOOTPRINT below; see the comment 178 : there for the derivation. Briefly: per-account fixed overhead 179 : (metadata + per-account resize headroom + alignment) for up to 64 180 : unique accounts, plus the total account-data body bounded once by the 181 : per-transaction loaded-data cap (64 MiB) plus the per-transaction data 182 : growth cap (20 MiB), plus instruction/program-id/pointer-array 183 : trailers. This is far tighter than the previous 64 * 10MiB worst 184 : case, which assumed all 64 accounts could simultaneously be at the 185 : per-account max size (the loaded-data + growth caps make that 186 : impossible). */ 187 16410 : #define MAX_PERMITTED_DATA_INCREASE (10240UL) // 10KB 188 14517 : #define FD_BPF_ALIGN_OF_U128 (8UL) 189 2640 : #define FD_ACCOUNT_REC_ALIGN (8UL) 190 : /* https://github.com/anza-xyz/sbpf/blob/v0.12.2/src/ebpf.rs#L37-L38 */ 191 : #define FD_RUNTIME_EBPF_HOST_ALIGN (16UL) 192 : 193 : /* FD_BPF_LOADER_UNIQUE_ACCOUNT_FIXED_FOOTPRINT is the per-unique-account 194 : serialization overhead EXCLUDING the account's data body: the fixed 195 : metadata fields, plus the realloc headroom (MAX_PERMITTED_DATA_INCREASE) 196 : and the worst-case per-account alignment padding (FD_BPF_ALIGN_OF_U128). 197 : The account data body itself is bounded separately, at the region level, 198 : by the per-transaction loaded-accounts-data cap (see below). */ 199 : #define FD_BPF_LOADER_UNIQUE_ACCOUNT_FIXED_FOOTPRINT \ 200 : (1UL /* dup byte */ + \ 201 : sizeof(uchar) /* is_signer */ + \ 202 : sizeof(uchar) /* is_writable */ + \ 203 : sizeof(uchar) /* executable */ + \ 204 : sizeof(uint) /* original_data_len */ + \ 205 : sizeof(fd_pubkey_t) /* key */ + \ 206 : sizeof(fd_pubkey_t) /* owner */ + \ 207 : sizeof(ulong) /* lamports */ + \ 208 : sizeof(ulong) /* data len */ + \ 209 : FD_BPF_ALIGN_OF_U128 /* per-account data alignment padding */ + \ 210 : MAX_PERMITTED_DATA_INCREASE /* realloc headroom (additive to loaded size) */ + \ 211 : sizeof(ulong)) /* rent_epoch */ 212 : #define FD_BPF_LOADER_DUPLICATE_ACCOUNT_FOOTPRINT (8UL) /* 1 dup byte + 7 bytes for padding */ 213 : 214 : /* FD_SYSVAR_INSTRUCTIONS_FOOTPRINT bounds the worst-case serialized 215 : size of the sysvar instructions account. See 216 : fd_sysvar_instructions.c for the format. 217 : 218 : Worst case size for V0/legacy transactions. Each bullet is bounded by 219 : its own maximum; those maxima compete for the same 1232-byte tx and 220 : can't all be reached at once, so the sum is a deliberately loose 221 : over-estimate: 222 : - 2 bytes header (num_instructions) 223 : - instruction offsets: 2 bytes * FD_TXN_INSTR_MAX (64) = 128 bytes 224 : - per-instr fixed: 2 (num_accounts) + 32 (program_id) + 2 (data_len) 225 : = 36 bytes * FD_TXN_INSTR_MAX (64) = 2304 bytes 226 : - account refs: each takes 1 byte (an index) in the tx but serializes 227 : to 33 bytes (1 flag + 32-byte pubkey); a 1232-byte tx holds at most 228 : ~1094 indices across all its instructions, so 33 * 1094 = 36102 bytes 229 : - instr data: bounded by the legacy MTU FD_TXN_MTU_V0 (1232 bytes) 230 : - 2 bytes tail (current_instr_idx) 231 : Total: 39770 bytes 232 : 233 : Worst case size for V1 transactions: 234 : Instruction start offsets are u16, so an accepted sysvar has every 235 : offset <= 65535; a larger offset overflows and is rejected (matching 236 : agave). The worst case is the last instruction starting at 65535: 237 : 238 : - 65535 bytes (offset of the last instruction) 239 : - per-acct ref: 33 bytes * 255 = 8415 bytes 240 : - per-instr fixed: 2 (num_accounts) + 32 (program_id) + 2 (data_len) 241 : = 36 bytes 242 : - instr data: bounded by FD_TXN_MTU (4096 bytes) 243 : - 2 bytes tail (current_instr_idx) 244 : Total: 78084 bytes, rounded up to 81920. */ 245 : #define FD_SYSVAR_INSTRUCTIONS_FOOTPRINT (81920UL) 246 : 247 : /* FD_BPF_LOADER_INPUT_REGION_FOOTPRINT bounds the bytes a single 248 : instruction can serialize into one input region. 249 : 250 : The account data bodies are NOT bounded by account_lock_limit * 251 : FD_RUNTIME_ACC_SZ_MAX (64 * 10 MiB = 640 MiB): a transaction is 252 : rejected before execution (and therefore before serialization) if the 253 : sum of its loaded account data exceeds 254 : FD_VM_LOADED_ACCOUNTS_DATA_SIZE_LIMIT (see 255 : fd_executor_load_transaction_accounts -> 256 : fd_increase_calculated_data_size, called from 257 : fd_runtime_pre_execute_check before fd_execute_txn). Note that this 258 : does not include the instructions sysvar, as this is not counted 259 : towards the loaded accounts data size limit. An instruction 260 : serializes a subset of the transaction's (<= account_lock_limit 261 : unique) accounts, each unique account's data copied at most once (dups 262 : cost 8 bytes). 263 : 264 : However, a program may GROW account data during execution before a 265 : later instruction (or CPI) re-serializes it. Total account-data 266 : growth across a transaction is itself capped, at 267 : FD_RUNTIME_ACC_DATA_GROWTH_MAX_PER_TXN (== fd_borrowed_account.h's 268 : MAX_PERMITTED_ACCOUNT_DATA_ALLOCS_PER_TXN, which fd_borrowed_account.c 269 : enforces by rejecting any resize that pushes accounts_resize_delta 270 : over the cap). So the worst-case account-data body serialized by any 271 : one instruction is bounded by 272 : 273 : FD_VM_LOADED_ACCOUNTS_DATA_SIZE_LIMIT (initial loaded data) 274 : + FD_RUNTIME_ACC_DATA_GROWTH_MAX_PER_TXN (max growth this txn) 275 : 276 : i.e. 64 MiB + 20 MiB = 84 MiB. We charge the data bodies once at the 277 : region level with that combined bound, plus the fixed per-account 278 : overhead (metadata + per-account realloc headroom + alignment). 279 : 280 : When direct_mapping is enabled the data body is mapped rather than 281 : copied, so it costs nothing in this buffer at all. */ 282 : #define FD_BPF_LOADER_INPUT_REGION_FOOTPRINT(account_lock_limit, direct_mapping) \ 283 : (FD_ULONG_ALIGN_UP( (sizeof(ulong) /* acct_cnt */ + \ 284 : account_lock_limit*FD_BPF_LOADER_UNIQUE_ACCOUNT_FIXED_FOOTPRINT + \ 285 : ((direct_mapping) ? 0UL : ((ulong)FD_VM_LOADED_ACCOUNTS_DATA_SIZE_LIMIT + \ 286 : (ulong)FD_RUNTIME_ACC_DATA_GROWTH_MAX_PER_TXN)) + \ 287 : FD_SYSVAR_INSTRUCTIONS_FOOTPRINT + \ 288 : (FD_TXN_INSTR_ACCT_MAX-account_lock_limit)*FD_BPF_LOADER_DUPLICATE_ACCOUNT_FOOTPRINT + \ 289 : sizeof(ulong) /* instr data len */ + \ 290 : FD_RUNTIME_CPI_MAX_INSTR_DATA_LEN /* instr data */ + \ 291 : sizeof(fd_pubkey_t) /* program id */ + \ 292 : (FD_BPF_ALIGN_OF_U128-1UL) + \ 293 : FD_TXN_INSTR_ACCT_MAX*sizeof(ulong) /* direct_account_pointers_in_program_input */), \ 294 : FD_RUNTIME_EBPF_HOST_ALIGN )) 295 : 296 : 297 : 298 : #define BPF_LOADER_SERIALIZATION_FOOTPRINT (FD_BPF_LOADER_INPUT_REGION_FOOTPRINT(64UL, 0)) 299 : 300 6 : #define FD_HARD_FORKS_MAX (64UL) 301 : 302 : FD_PROTOTYPES_END 303 : 304 : #endif /* HEADER_fd_src_flamenco_runtime_fd_runtime_const_h */