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