Line data Source code
1 : #include "fd_builtin_programs.h"
2 : #include "fd_precompiles.h"
3 : #include "../fd_system_ids.h"
4 : #include "../fd_system_ids_pp.h"
5 : #include "../fd_accdb_svm.h"
6 : #include "../../accdb/fd_accdb_sync.h"
7 :
8 : #define BUILTIN_PROGRAM(program_id, name, feature_offset, migration_config) \
9 : { \
10 : program_id, \
11 : name, \
12 : feature_offset, \
13 : migration_config \
14 : }
15 :
16 : #define STATELESS_BUILTIN(program_id, migration_config) \
17 : { \
18 : program_id, \
19 : migration_config \
20 : }
21 :
22 : #define CORE_BPF_MIGRATION_CONFIG(source_buffer_address, upgrade_authority_address, enable_feature_offset, builtin_program_id) \
23 : { \
24 : source_buffer_address, \
25 : upgrade_authority_address, \
26 : enable_feature_offset, \
27 : builtin_program_id \
28 : }
29 :
30 : /* Core BPF migration configs */
31 : static const fd_core_bpf_migration_config_t STATELESS_TO_CORE_BPF_FEATURE_GATE_PROGRAM_CONFIG = {
32 : &fd_solana_feature_program_buffer_address,
33 : NULL,
34 : offsetof(fd_features_t, migrate_feature_gate_program_to_core_bpf),
35 : FD_CORE_BPF_MIGRATION_TARGET_STATELESS,
36 : &fd_solana_feature_program_id,
37 : NULL
38 : };
39 : static const fd_core_bpf_migration_config_t * const MIGRATE_STATELESS_TO_CORE_BPF_FEATURE_GATE_PROGRAM_CONFIG = &STATELESS_TO_CORE_BPF_FEATURE_GATE_PROGRAM_CONFIG;
40 :
41 : /* FIXME: update to correct hash when slashing program is finalized */
42 : /* 9260b9ac8dfa1a6ed1022380a713bec7b75979ae136e91f9a86795b51c6c489f */
43 : #define SLASHING_PROG_HASH_SIMD_204 0x92U,0x60U,0xb9U,0xacU,0x8dU,0xfaU,0x1aU,0x6eU,0xd1U,0x02U,0x23U,0x80U,0xa7U,0x13U,0xbeU,0xc7U, \
44 : 0xb7U,0x59U,0x79U,0xaeU,0x13U,0x6eU,0x91U,0xf9U,0xa8U,0x67U,0x95U,0xb5U,0x1cU,0x6cU,0x48U,0x9fU
45 : const fd_hash_t fd_solana_slashing_program_verified_build_hash_simd_204 = { .uc = { SLASHING_PROG_HASH_SIMD_204 } };
46 : static const fd_core_bpf_migration_config_t STATELESS_TO_CORE_BPF_SLASHING_PROGRAM_CONFIG = {
47 : &fd_solana_slashing_program_buffer_address,
48 : NULL,
49 : offsetof(fd_features_t, enshrine_slashing_program),
50 : FD_CORE_BPF_MIGRATION_TARGET_STATELESS,
51 : &fd_solana_slashing_program_id,
52 : &fd_solana_slashing_program_verified_build_hash_simd_204
53 : };
54 : static const fd_core_bpf_migration_config_t * const MIGRATE_STATELESS_TO_CORE_BPF_SLASHING_PROGRAM_CONFIG = &STATELESS_TO_CORE_BPF_SLASHING_PROGRAM_CONFIG;
55 :
56 : #define SYSTEM_PROGRAM_BUILTIN BUILTIN_PROGRAM(&fd_solana_system_program_id, "system_program", NO_ENABLE_FEATURE_ID, NULL)
57 : #define VOTE_PROGRAM_BUILTIN BUILTIN_PROGRAM(&fd_solana_vote_program_id, "vote_program", NO_ENABLE_FEATURE_ID, NULL)
58 : #define LOADER_V4_BUILTIN BUILTIN_PROGRAM(&fd_solana_bpf_loader_v4_program_id, "loader_v4", offsetof(fd_features_t, enable_loader_v4), NULL)
59 : #define BPF_LOADER_DEPRECATED_BUILTIN BUILTIN_PROGRAM(&fd_solana_bpf_loader_deprecated_program_id, "solana_bpf_loader_deprecated_program", NO_ENABLE_FEATURE_ID, NULL)
60 : #define BPF_LOADER_BUILTIN BUILTIN_PROGRAM(&fd_solana_bpf_loader_program_id, "solana_bpf_loader_program", NO_ENABLE_FEATURE_ID, NULL)
61 : #define BPF_LOADER_UPGRADEABLE_BUILTIN BUILTIN_PROGRAM(&fd_solana_bpf_loader_upgradeable_program_id, "solana_bpf_loader_upgradeable_program", NO_ENABLE_FEATURE_ID, NULL)
62 : #define COMPUTE_BUDGET_PROGRAM_BUILTIN BUILTIN_PROGRAM(&fd_solana_compute_budget_program_id, "compute_budget_program", NO_ENABLE_FEATURE_ID, NULL)
63 : #define ZK_TOKEN_PROOF_PROGRAM_BUILTIN BUILTIN_PROGRAM(&fd_solana_zk_token_proof_program_id, "zk_token_proof_program", offsetof(fd_features_t, zk_token_sdk_enabled), NULL)
64 : #define ZK_ELGAMAL_PROOF_PROGRAM_BUILTIN BUILTIN_PROGRAM(&fd_solana_zk_elgamal_proof_program_id, "zk_elgamal_proof_program", offsetof(fd_features_t, zk_elgamal_proof_program_enabled), NULL)
65 :
66 : #define FEATURE_PROGRAM_BUILTIN STATELESS_BUILTIN(&fd_solana_feature_program_id, MIGRATE_STATELESS_TO_CORE_BPF_FEATURE_GATE_PROGRAM_CONFIG)
67 : #define SLASHING_PROGRAM_BUILTIN STATELESS_BUILTIN(&fd_solana_slashing_program_id, MIGRATE_STATELESS_TO_CORE_BPF_SLASHING_PROGRAM_CONFIG)
68 :
69 : /* https://github.com/anza-xyz/agave/blob/v2.1.0/runtime/src/bank/builtins/mod.rs#L133-L143 */
70 : static const fd_stateless_builtin_program_t stateless_programs_builtins[] = {
71 : FEATURE_PROGRAM_BUILTIN,
72 : SLASHING_PROGRAM_BUILTIN
73 : };
74 387 : #define STATELESS_BUILTINS_COUNT (sizeof(stateless_programs_builtins) / sizeof(fd_stateless_builtin_program_t))
75 :
76 : /* https://github.com/anza-xyz/agave/blob/v2.1.0/runtime/src/bank/builtins/mod.rs#L34-L131 */
77 : static fd_builtin_program_t const builtin_programs[] = {
78 : SYSTEM_PROGRAM_BUILTIN,
79 : VOTE_PROGRAM_BUILTIN,
80 : LOADER_V4_BUILTIN,
81 : BPF_LOADER_DEPRECATED_BUILTIN,
82 : BPF_LOADER_BUILTIN,
83 : BPF_LOADER_UPGRADEABLE_BUILTIN,
84 : COMPUTE_BUDGET_PROGRAM_BUILTIN,
85 : ZK_TOKEN_PROOF_PROGRAM_BUILTIN,
86 : ZK_ELGAMAL_PROOF_PROGRAM_BUILTIN
87 : };
88 3300 : #define BUILTIN_PROGRAMS_COUNT (sizeof(builtin_programs) / sizeof(fd_builtin_program_t))
89 :
90 : /* Used by the compute budget program to determine how many CUs to deduct by default
91 : https://github.com/anza-xyz/agave/blob/v2.1.13/builtins-default-costs/src/lib.rs#L113-L139 */
92 : static fd_core_bpf_migration_config_t const * migrating_builtins[] = {
93 : /* Any future migrating builtins should be added here. Intentionally
94 : not cleaned up to support future migrations. */
95 : NULL,
96 : };
97 306 : #define MIGRATING_BUILTINS_COUNT (sizeof(migrating_builtins) / sizeof(fd_core_bpf_migration_config_t const *))
98 :
99 : /* https://github.com/anza-xyz/agave/blob/v2.1.13/builtins-default-costs/src/lib.rs#L141-L193 */
100 : #define MAP_PERFECT_NAME fd_non_migrating_builtins_tbl
101 : #define MAP_PERFECT_LG_TBL_SZ 4
102 : #define MAP_PERFECT_T fd_pubkey_t
103 126 : #define MAP_PERFECT_HASH_C 146U
104 : #define MAP_PERFECT_KEY uc
105 : #define MAP_PERFECT_KEY_T fd_pubkey_t const *
106 : #define MAP_PERFECT_ZERO_KEY (0,0,0,0, 0,0,0,0, 0,0,0,0, 0,0,0,0, 0,0,0,0, 0,0,0,0, 0,0,0,0, 0,0,0,0)
107 : #define MAP_PERFECT_COMPLEX_KEY 1
108 126 : #define MAP_PERFECT_KEYS_EQUAL(k1,k2) (!memcmp( (k1), (k2), 32UL ))
109 :
110 126 : #define PERFECT_HASH( u ) (((MAP_PERFECT_HASH_C*(u))>>28)&0x0FU)
111 :
112 : #define MAP_PERFECT_HASH_PP( a00,a01,a02,a03,a04,a05,a06,a07,a08,a09,a10,a11,a12,a13,a14,a15, \
113 : a16,a17,a18,a19,a20,a21,a22,a23,a24,a25,a26,a27,a28,a29,a30,a31) \
114 : PERFECT_HASH( (a08 | (a09<<8) | (a10<<16) | (a11<<24)) )
115 126 : #define MAP_PERFECT_HASH_R( ptr ) PERFECT_HASH( fd_uint_load_4( (uchar const *)ptr->uc + 8UL ) )
116 :
117 : #define MAP_PERFECT_0 ( VOTE_PROG_ID ),
118 : #define MAP_PERFECT_1 ( SYS_PROG_ID ),
119 : #define MAP_PERFECT_2 ( COMPUTE_BUDGET_PROG_ID ),
120 : #define MAP_PERFECT_3 ( BPF_UPGRADEABLE_PROG_ID ),
121 : #define MAP_PERFECT_4 ( BPF_LOADER_1_PROG_ID ),
122 : #define MAP_PERFECT_5 ( BPF_LOADER_2_PROG_ID ),
123 : #define MAP_PERFECT_6 ( LOADER_V4_PROG_ID ),
124 : #define MAP_PERFECT_7 ( KECCAK_SECP_PROG_ID ),
125 : #define MAP_PERFECT_8 ( ED25519_SV_PROG_ID ),
126 :
127 : #include "../../../util/tmpl/fd_map_perfect.c"
128 : #undef PERFECT_HASH
129 :
130 : // https://github.com/anza-xyz/agave/blob/v2.3.7/runtime/src/bank.rs#L4944
131 : static int
132 : fd_builtin_is_bpf( fd_accdb_user_t * accdb,
133 : fd_funk_txn_xid_t const * xid,
134 0 : fd_pubkey_t const * pubkey ) {
135 0 : fd_accdb_ro_t ro[1];
136 0 : if( !fd_accdb_open_ro( accdb, ro, xid, pubkey ) ) {
137 0 : return 0;
138 0 : }
139 0 : int is_bpf = fd_pubkey_eq( fd_accdb_ref_owner( ro ), &fd_solana_bpf_loader_upgradeable_program_id );
140 0 : fd_accdb_close_ro( accdb, ro );
141 0 : return is_bpf;
142 0 : }
143 :
144 :
145 : /* BuiltIn programs need "bogus" executable accounts to exist.
146 : These are loaded and ignored during execution.
147 :
148 : Bogus accounts are marked as "executable", but their data is a
149 : hardcoded ASCII string. */
150 :
151 : /* https://github.com/solana-labs/solana/blob/8f2c8b8388a495d2728909e30460aa40dcc5d733/sdk/src/native_loader.rs#L19 */
152 : void
153 : fd_write_builtin_account( fd_bank_t * bank,
154 : fd_accdb_user_t * accdb,
155 : fd_funk_txn_xid_t const * xid,
156 : fd_capture_ctx_t * capture_ctx,
157 : fd_pubkey_t const pubkey,
158 : void const * data,
159 144 : ulong sz ) {
160 144 : fd_accdb_svm_write(
161 144 : accdb, bank, xid, capture_ctx,
162 144 : &pubkey,
163 144 : &fd_solana_native_loader_id, /* owner */
164 144 : data, sz, /* data */
165 144 : 1UL, /* lamports_min */
166 144 : 1, /* exec_bit */
167 144 : FD_ACCDB_FLAG_CREATE|FD_ACCDB_FLAG_TRUNCATE
168 144 : );
169 144 : }
170 :
171 : void
172 : fd_builtin_programs_init( fd_bank_t * bank,
173 : fd_accdb_user_t * accdb,
174 : fd_funk_txn_xid_t const * xid,
175 12 : fd_capture_ctx_t * capture_ctx ) {
176 : /* https://github.com/anza-xyz/agave/blob/v2.3.7/builtins/src/lib.rs#L52 */
177 12 : fd_builtin_program_t const * builtins = fd_builtins();
178 :
179 120 : for( ulong i=0UL; i<fd_num_builtins(); i++ ) {
180 : /** https://github.com/anza-xyz/agave/blob/v2.3.7/runtime/src/bank.rs#L4949 */
181 108 : if( bank->f.slot==0UL && builtins[i].enable_feature_offset==NO_ENABLE_FEATURE_ID && !fd_builtin_is_bpf( accdb, xid, builtins[i].pubkey ) ) {
182 0 : fd_write_builtin_account( bank, accdb, xid, capture_ctx, *builtins[i].pubkey, builtins[i].data, strlen( builtins[i].data ) );
183 108 : } else if( builtins[i].core_bpf_migration_config && FD_FEATURE_ACTIVE_OFFSET( bank->f.slot, &bank->f.features, builtins[i].core_bpf_migration_config->enable_feature_offset ) ) {
184 0 : continue;
185 108 : } else if( builtins[i].enable_feature_offset!=NO_ENABLE_FEATURE_ID && !FD_FEATURE_ACTIVE_OFFSET( bank->f.slot, &bank->f.features, builtins[i].enable_feature_offset ) ) {
186 0 : continue;
187 108 : } else {
188 108 : fd_write_builtin_account( bank, accdb, xid, capture_ctx, *builtins[i].pubkey, builtins[i].data, strlen(builtins[i].data) );
189 108 : }
190 108 : }
191 :
192 : /* Precompiles have empty account data */
193 12 : fd_write_builtin_account( bank, accdb, xid, capture_ctx, fd_solana_keccak_secp_256k_program_id, "", 0 );
194 12 : fd_write_builtin_account( bank, accdb, xid, capture_ctx, fd_solana_ed25519_sig_verify_program_id, "", 0 );
195 12 : fd_write_builtin_account( bank, accdb, xid, capture_ctx, fd_solana_secp256r1_program_id, "", 0 );
196 12 : }
197 :
198 : fd_builtin_program_t const *
199 330 : fd_builtins( void ) {
200 330 : return builtin_programs;
201 330 : }
202 :
203 : ulong
204 3300 : fd_num_builtins( void ) {
205 3300 : return BUILTIN_PROGRAMS_COUNT;
206 3300 : }
207 :
208 : fd_stateless_builtin_program_t const *
209 129 : fd_stateless_builtins( void ) {
210 129 : return stateless_programs_builtins;
211 129 : }
212 :
213 : ulong
214 387 : fd_num_stateless_builtins( void ) {
215 387 : return STATELESS_BUILTINS_COUNT;
216 387 : }
217 :
218 : uchar
219 : fd_is_migrating_builtin_program( fd_bank_t const * bank,
220 : fd_pubkey_t const * pubkey,
221 153 : uchar * migrated_yet ) {
222 153 : *migrated_yet = 0;
223 :
224 306 : for( ulong i=0; i<MIGRATING_BUILTINS_COUNT; i++ ) {
225 153 : fd_core_bpf_migration_config_t const * config = migrating_builtins[i];
226 153 : if( !config ) continue;
227 :
228 0 : if( !memcmp( pubkey->uc, config->builtin_program_id->key, sizeof(fd_pubkey_t) ) ) {
229 0 : if( config->enable_feature_offset!=NO_ENABLE_FEATURE_ID &&
230 0 : FD_FEATURE_ACTIVE_OFFSET( bank->f.slot, &bank->f.features, config->enable_feature_offset ) ) {
231 : /* The program has been migrated to BPF. */
232 0 : *migrated_yet = 1;
233 0 : }
234 :
235 0 : return 1;
236 0 : }
237 0 : }
238 :
239 : /* No migration config exists for this program */
240 153 : return 0;
241 153 : }
242 :
243 : FD_FN_PURE uchar
244 126 : fd_is_non_migrating_builtin_program( fd_pubkey_t const * pubkey ) {
245 126 : return !!( fd_non_migrating_builtins_tbl_contains( pubkey ) );
246 126 : }
|