LCOV - code coverage report
Current view: top level - flamenco/runtime - fd_runtime_const.h (source / functions) Hit Total Coverage
Test: cov.lcov Lines: 18 25 72.0 %
Date: 2026-05-26 08:02:49 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 "../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 */

Generated by: LCOV version 1.14