LCOV - code coverage report
Current view: top level - flamenco/runtime - fd_runtime_const.h (source / functions) Hit Total Coverage
Test: cov.lcov Lines: 9 26 34.6 %
Date: 2026-11-11 12:40:43 Functions: 0 0 -

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

Generated by: LCOV version 1.14