Skip to content

Commit 7fbdd6c

Browse files
committed
flamenco, feature: enshrine_slashing_program
1 parent dd70fa6 commit 7fbdd6c

File tree

9 files changed

+218
-90
lines changed

9 files changed

+218
-90
lines changed

src/flamenco/features/fd_features_generated.c

Lines changed: 8 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -1633,6 +1633,12 @@ fd_feature_id_t const ids[] = {
16331633
.name = "enable_vote_address_leader_schedule",
16341634
.cleaned_up = {UINT_MAX, UINT_MAX, UINT_MAX} },
16351635

1636+
{ .index = offsetof(fd_features_t, enshrine_slashing_program)>>3,
1637+
.id = {"\x0c\xe8\xe3\x0a\x1b\x9d\x30\xc1\x5d\x98\x93\xa3\x19\x40\xb4\xc8\x7f\x92\x5b\x24\x5e\x7a\xe6\xec\x6b\xe8\x87\xd5\xaa\x22\xb2\x6d"},
1638+
/* sProgVaNWkYdP2eTRAy1CPrgb3b9p8yXCASrPEqo6VJ */
1639+
.name = "enshrine_slashing_program",
1640+
.cleaned_up = {UINT_MAX, UINT_MAX, UINT_MAX} },
1641+
16361642
{ .index = ULONG_MAX }
16371643
};
16381644
/* TODO replace this with fd_map_perfect */
@@ -1878,6 +1884,7 @@ fd_feature_id_query( ulong prefix ) {
18781884
case 0x7170cf84367fbb1a: return &ids[ 236 ];
18791885
case 0xa9e3bfbaf8d67260: return &ids[ 237 ];
18801886
case 0x3711b30f40730240: return &ids[ 238 ];
1887+
case 0xc1309d1b0ae3e80c: return &ids[ 239 ];
18811888
default: break;
18821889
}
18831890
return NULL;
@@ -2122,4 +2129,5 @@ FD_STATIC_ASSERT( offsetof( fd_features_t, formalize_loaded_transaction_data_siz
21222129
FD_STATIC_ASSERT( offsetof( fd_features_t, enable_extend_program_checked )>>3==236UL, layout );
21232130
FD_STATIC_ASSERT( offsetof( fd_features_t, require_static_nonce_account )>>3==237UL, layout );
21242131
FD_STATIC_ASSERT( offsetof( fd_features_t, enable_vote_address_leader_schedule )>>3==238UL, layout );
2132+
FD_STATIC_ASSERT( offsetof( fd_features_t, enshrine_slashing_program )>>3==239UL, layout );
21252133
FD_STATIC_ASSERT( sizeof( fd_features_t )>>3==FD_FEATURE_ID_CNT, layout );

src/flamenco/features/fd_features_generated.h

Lines changed: 2 additions & 1 deletion
Original file line numberDiff line numberDiff line change
@@ -8,7 +8,7 @@
88
#endif
99

1010
/* FEATURE_ID_CNT is the number of features in ids */
11-
#define FD_FEATURE_ID_CNT (239UL)
11+
#define FD_FEATURE_ID_CNT (240UL)
1212
union fd_features {
1313
ulong f[ FD_FEATURE_ID_CNT ];
1414
struct {
@@ -251,5 +251,6 @@ union fd_features {
251251
/* 0x7170cf84367fbb1a */ ulong enable_extend_program_checked;
252252
/* 0xa9e3bfbaf8d67260 */ ulong require_static_nonce_account;
253253
/* 0x3711b30f40730240 */ ulong enable_vote_address_leader_schedule;
254+
/* 0xc1309d1b0ae3e80c */ ulong enshrine_slashing_program;
254255
};
255256
};

src/flamenco/features/feature_map.json

Lines changed: 2 additions & 1 deletion
Original file line numberDiff line numberDiff line change
@@ -237,5 +237,6 @@
237237
{"name":"formalize_loaded_transaction_data_size","pubkey":"DeS7sR48ZcFTUmt5FFEVDr1v1bh73aAbZiZq3SYr8Eh8"},
238238
{"name":"enable_extend_program_checked","pubkey":"2oMRZEDWT2tqtYMofhmmfQ8SsjqUFzT6sYXppQDavxwz"},
239239
{"name":"require_static_nonce_account","pubkey":"7VVhpg5oAjAmnmz1zCcSHb2Z9ecZB2FQqpnEwReka9Zm"},
240-
{"name":"enable_vote_address_leader_schedule","pubkey":"5JsG4NWH8Jbrqdd8uL6BNwnyZK3dQSoieRXG5vmofj9y"}
240+
{"name":"enable_vote_address_leader_schedule","pubkey":"5JsG4NWH8Jbrqdd8uL6BNwnyZK3dQSoieRXG5vmofj9y"},
241+
{"name":"enshrine_slashing_program","pubkey":"sProgVaNWkYdP2eTRAy1CPrgb3b9p8yXCASrPEqo6VJ"}
241242
]

src/flamenco/runtime/fd_runtime.c

Lines changed: 113 additions & 49 deletions
Original file line numberDiff line numberDiff line change
@@ -1756,24 +1756,105 @@ fd_new_target_program_data_account( fd_exec_slot_ctx_t * slot_ctx,
17561756
} FD_SPAD_FRAME_END;
17571757
}
17581758

1759-
/* Mimics migrate_builtin_to_core_bpf(). The arguments map as follows:
1760-
- builtin_program_id: builtin_program_id
1761-
- config
1762-
- source_buffer_address: source_buffer_address
1763-
- migration_target
1764-
- Builtin: !stateless
1765-
- Stateless: stateless
1766-
- upgrade_authority_address: upgrade_authority_address
1759+
/* Initializes a source buffer account from funk. Returns 1 if the
1760+
buffer account does not exist or is not owned by the upgradeable
1761+
loader. Returns 0 on success.
1762+
1763+
https://github.com/anza-xyz/agave/blob/v2.3.0/runtime/src/bank/builtins/core_bpf_migration/source_buffer.rs#L22-L49 */
1764+
static int
1765+
fd_source_buffer_account_new( fd_exec_slot_ctx_t * slot_ctx,
1766+
fd_txn_account_t * buffer_account,
1767+
fd_pubkey_t const * buffer_address,
1768+
fd_funk_rec_prepare_t * prepare ) {
1769+
/* The buffer account should exist.
1770+
https://github.com/anza-xyz/agave/blob/v2.3.0/runtime/src/bank/builtins/core_bpf_migration/source_buffer.rs#L27-L29 */
1771+
if( FD_UNLIKELY( fd_txn_account_init_from_funk_mutable( buffer_account, buffer_address, slot_ctx->funk, slot_ctx->funk_txn, 0, 0UL, prepare )!=FD_ACC_MGR_SUCCESS ) ) {
1772+
FD_LOG_WARNING(( "Buffer account %s does not exist, skipping migration...", FD_BASE58_ENC_32_ALLOCA( buffer_address ) ));
1773+
return 1;
1774+
}
1775+
1776+
/* The buffer account should be owned by the upgradeable loader.
1777+
https://github.com/anza-xyz/agave/blob/v2.3.0/runtime/src/bank/builtins/core_bpf_migration/source_buffer.rs#L31-L34 */
1778+
if( FD_UNLIKELY( memcmp( fd_txn_account_get_owner( buffer_account ), fd_solana_bpf_loader_upgradeable_program_id.uc, sizeof(fd_pubkey_t) ) ) ) {
1779+
FD_LOG_WARNING(( "Buffer account %s is not owned by the upgradeable loader, skipping migration...", FD_BASE58_ENC_32_ALLOCA( buffer_address ) ));
1780+
return 1;
1781+
}
1782+
1783+
/* The buffer account should have the correct state. We already check
1784+
the buffer account state in fd_new_target_program_data_account(),
1785+
so we can skip the checks here.
1786+
https://github.com/anza-xyz/agave/blob/v2.3.0/runtime/src/bank/builtins/core_bpf_migration/source_buffer.rs#L37-L47 */
1787+
1788+
return 0;
1789+
}
1790+
1791+
/* Similar to fd_source_buffer_account_new() but also checks the build
1792+
hash of the buffer account for verification. verified_build_hash must
1793+
be valid and non-NULL. Returns 1 if fd_source_buffer_account_new()
1794+
fails, the buffer dlen is too small, or if the build hash mismatches.
1795+
Returns 0 on success.
1796+
1797+
https://github.com/anza-xyz/agave/blob/v2.3.0/runtime/src/bank/builtins/core_bpf_migration/source_buffer.rs#L51-L75 */
1798+
static int
1799+
fd_source_buffer_account_new_with_hash( fd_exec_slot_ctx_t * slot_ctx,
1800+
fd_txn_account_t * buffer_account,
1801+
fd_pubkey_t const * buffer_address,
1802+
fd_hash_t const * verified_build_hash,
1803+
fd_funk_rec_prepare_t * prepare ) {
1804+
/* https://github.com/anza-xyz/agave/blob/v2.3.0/runtime/src/bank/builtins/core_bpf_migration/source_buffer.rs#L58 */
1805+
int err = fd_source_buffer_account_new( slot_ctx, buffer_account, buffer_address, prepare );
1806+
if( FD_UNLIKELY( err ) ) {
1807+
return err;
1808+
}
1809+
1810+
/* https://github.com/anza-xyz/agave/blob/v2.3.0/runtime/src/bank/builtins/core_bpf_migration/source_buffer.rs#L59 */
1811+
uchar const * data = fd_txn_account_get_data( buffer_account );
1812+
ulong data_len = fd_txn_account_get_data_len( buffer_account );
1813+
1814+
/* https://github.com/anza-xyz/agave/blob/v2.3.0/runtime/src/bank/builtins/core_bpf_migration/source_buffer.rs#L61 */
1815+
ulong offset = BUFFER_METADATA_SIZE;
1816+
if( FD_UNLIKELY( data_len<offset ) ) {
1817+
return 1;
1818+
}
1819+
1820+
/* Search for the first nonzero byte in the buffer account data starting
1821+
from the right.
1822+
https://github.com/anza-xyz/agave/blob/v2.3.0/runtime/src/bank/builtins/core_bpf_migration/source_buffer.rs#L62 */
1823+
ulong end_offset = offset;
1824+
for( ulong i=data_len-1UL; i>=offset; i-- ) {
1825+
if( data[i]!=0 ) {
1826+
end_offset = i+1UL;
1827+
break;
1828+
}
1829+
}
1830+
1831+
/* Compute and verify the hash.
1832+
https://github.com/anza-xyz/agave/blob/v2.3.0/runtime/src/bank/builtins/core_bpf_migration/source_buffer.rs#L64-L71 */
1833+
fd_hash_t hash[1];
1834+
fd_sha256_hash( data+offset, end_offset-offset, hash );
1835+
if( FD_UNLIKELY( memcmp( verified_build_hash, hash, sizeof(fd_hash_t) ) ) ) {
1836+
FD_LOG_WARNING(( "Mismatching build hash for Buffer account %s (expected=%s, actual=%s). Skipping migration...", FD_BASE58_ENC_32_ALLOCA( buffer_address ), FD_BASE58_ENC_32_ALLOCA( verified_build_hash ), FD_BASE58_ENC_32_ALLOCA( hash ) ));
1837+
return 1;
1838+
}
1839+
1840+
return 0;
1841+
}
1842+
1843+
/* Mimics migrate_builtin_to_core_bpf().
17671844
https://github.com/anza-xyz/agave/blob/v2.1.0/runtime/src/bank/builtins/core_bpf_migration/mod.rs#L235-L318 */
17681845
static void
1769-
fd_migrate_builtin_to_core_bpf( fd_exec_slot_ctx_t * slot_ctx,
1770-
fd_pubkey_t * upgrade_authority_address,
1771-
fd_pubkey_t const * builtin_program_id,
1772-
fd_pubkey_t const * source_buffer_address,
1773-
uchar stateless,
1774-
fd_spad_t * runtime_spad ) {
1846+
fd_migrate_builtin_to_core_bpf( fd_exec_slot_ctx_t * slot_ctx,
1847+
fd_core_bpf_migration_config_t const * config,
1848+
fd_spad_t * runtime_spad ) {
17751849
int err;
17761850

1851+
/* Initialize local variables from the config */
1852+
fd_pubkey_t const * source_buffer_address = config->source_buffer_address;
1853+
fd_pubkey_t * upgrade_authority_address = config->upgrade_authority_address;
1854+
uchar stateless = !!( config->migration_target==FD_CORE_BPF_MIGRATION_TARGET_STATELESS );
1855+
fd_pubkey_t const * builtin_program_id = config->builtin_program_id;
1856+
fd_hash_t const * verified_build_hash = config->verified_build_hash;
1857+
17771858
/* https://github.com/anza-xyz/agave/blob/v2.1.0/runtime/src/bank/builtins/core_bpf_migration/mod.rs#L242-L243
17781859
17791860
The below logic is used to obtain a TargetBuiltin account. There
@@ -1836,19 +1917,22 @@ fd_migrate_builtin_to_core_bpf( fd_exec_slot_ctx_t * slot_ctx,
18361917
return;
18371918
}
18381919

1839-
/* https://github.com/anza-xyz/agave/blob/v2.1.0/runtime/src/bank/builtins/core_bpf_migration/mod.rs#L244
1920+
/* https://github.com/anza-xyz/agave/blob/v2.3.0/runtime/src/bank/builtins/core_bpf_migration/mod.rs#L221-L229
18401921
18411922
Obtains a SourceBuffer account. There are two fields returned:
18421923
- source.buffer_address: source_buffer_address
1843-
- source.buffer_account: the existing buffer account */
1844-
1845-
/* The buffer account should exist.
1846-
https://github.com/anza-xyz/agave/blob/v2.1.0/runtime/src/bank/builtins/core_bpf_migration/source_buffer.rs#L26-L29 */
1924+
- source.buffer_account: the existing buffer account
1925+
Depending on if the verified build hash is provided, */
18471926
FD_TXN_ACCOUNT_DECL( source_buffer_account );
18481927
fd_funk_rec_prepare_t source_buffer_prepare = {0};
1849-
if( FD_UNLIKELY( fd_txn_account_init_from_funk_mutable( source_buffer_account, source_buffer_address, slot_ctx->funk, slot_ctx->funk_txn, 0, 0UL, &source_buffer_prepare )!=FD_ACC_MGR_SUCCESS ) ) {
1850-
FD_LOG_NOTICE(( "Buffer account %s does not exist, skipping migration...", FD_BASE58_ENC_32_ALLOCA( source_buffer_address ) ));
1851-
return;
1928+
if( verified_build_hash!=NULL ) {
1929+
if( FD_UNLIKELY( fd_source_buffer_account_new_with_hash( slot_ctx, source_buffer_account, source_buffer_address, verified_build_hash, &source_buffer_prepare ) ) ) {
1930+
return;
1931+
}
1932+
} else {
1933+
if( FD_UNLIKELY( fd_source_buffer_account_new( slot_ctx, source_buffer_account, source_buffer_address, &source_buffer_prepare ) ) ) {
1934+
return;
1935+
}
18521936
}
18531937

18541938
fd_lthash_value_t prev_source_buffer_hash[1];
@@ -1858,19 +1942,8 @@ fd_migrate_builtin_to_core_bpf( fd_exec_slot_ctx_t * slot_ctx,
18581942
fd_txn_account_get_data( source_buffer_account ),
18591943
prev_source_buffer_hash );
18601944

1861-
/* The buffer account should be owned by the upgradeable loader.
1862-
https://github.com/anza-xyz/agave/blob/v2.1.0/runtime/src/bank/builtins/core_bpf_migration/source_buffer.rs#L31-L34 */
1863-
if( FD_UNLIKELY( memcmp( fd_txn_account_get_owner( source_buffer_account ), fd_solana_bpf_loader_upgradeable_program_id.uc, sizeof(fd_pubkey_t) ) ) ) {
1864-
FD_LOG_WARNING(( "Buffer account %s is not owned by the upgradeable loader, skipping migration...", FD_BASE58_ENC_32_ALLOCA( source_buffer_address ) ));
1865-
return;
1866-
}
1867-
1868-
/* The buffer account should have the correct state. We already check
1869-
the buffer account state in fd_new_target_program_data_account, so
1870-
we can skip the checks here.
1871-
https://github.com/anza-xyz/agave/blob/v2.1.0/runtime/src/bank/builtins/core_bpf_migration/source_buffer.rs#L37-L47 */
1872-
1873-
/* This check is done a bit prematurely because we calculate the previous account state's lamports. We use 0 for starting lamports
1945+
/* This check is done a bit prematurely because we calculate the
1946+
previous account state's lamports. We use 0 for starting lamports
18741947
for stateless accounts because they don't yet exist.
18751948
18761949
https://github.com/anza-xyz/agave/blob/v2.1.0/runtime/src/bank/builtins/core_bpf_migration/mod.rs#L277-L280 */
@@ -1883,8 +1956,9 @@ fd_migrate_builtin_to_core_bpf( fd_exec_slot_ctx_t * slot_ctx,
18831956
slot_ctx->funk_txn = fd_funk_txn_prepare( slot_ctx->funk, slot_ctx->funk_txn, &migration_xid, 0UL );
18841957
fd_funk_txn_end_write( slot_ctx->funk );
18851958

1886-
/* Attempt serialization of program account. If the program is stateless, we want to create the account. Otherwise,
1887-
we want a writable handle to modify the existing account.
1959+
/* Attempt serialization of program account. If the program is
1960+
stateless, we want to create the account. Otherwise, we want a
1961+
writable handle to modify the existing account.
18881962
https://github.com/anza-xyz/agave/blob/v2.1.0/runtime/src/bank/builtins/core_bpf_migration/mod.rs#L246-L249 */
18891963
FD_TXN_ACCOUNT_DECL( new_target_program_account );
18901964
fd_funk_rec_prepare_t new_target_program_prepare = {0};
@@ -2037,12 +2111,7 @@ fd_apply_builtin_program_feature_transitions( fd_exec_slot_ctx_t * slot_ctx,
20372111
/* https://github.com/anza-xyz/agave/blob/v2.1.0/runtime/src/bank.rs#L6732-L6751 */
20382112
if( builtins[i].core_bpf_migration_config && FD_FEATURE_ACTIVE_OFFSET( fd_bank_slot_get( slot_ctx->bank ), fd_bank_features_get( slot_ctx->bank ), builtins[i].core_bpf_migration_config->enable_feature_offset ) ) {
20392113
FD_LOG_NOTICE(( "Migrating builtin program %s to core BPF", FD_BASE58_ENC_32_ALLOCA( builtins[i].pubkey->key ) ));
2040-
fd_migrate_builtin_to_core_bpf( slot_ctx,
2041-
builtins[i].core_bpf_migration_config->upgrade_authority_address,
2042-
builtins[i].core_bpf_migration_config->builtin_program_id,
2043-
builtins[i].core_bpf_migration_config->source_buffer_address,
2044-
0,
2045-
runtime_spad );
2114+
fd_migrate_builtin_to_core_bpf( slot_ctx, builtins[i].core_bpf_migration_config, runtime_spad );
20462115
}
20472116
/* https://github.com/anza-xyz/agave/blob/v2.1.0/runtime/src/bank.rs#L6753-L6774 */
20482117
if( builtins[i].enable_feature_offset!=NO_ENABLE_FEATURE_ID && FD_FEATURE_JUST_ACTIVATED_OFFSET( slot_ctx, builtins[i].enable_feature_offset ) ) {
@@ -2056,12 +2125,7 @@ fd_apply_builtin_program_feature_transitions( fd_exec_slot_ctx_t * slot_ctx,
20562125
for( ulong i=0UL; i<fd_num_stateless_builtins(); i++ ) {
20572126
if( stateless_builtins[i].core_bpf_migration_config && FD_FEATURE_ACTIVE_OFFSET( fd_bank_slot_get( slot_ctx->bank ), fd_bank_features_get( slot_ctx->bank ), stateless_builtins[i].core_bpf_migration_config->enable_feature_offset ) ) {
20582127
FD_LOG_NOTICE(( "Migrating stateless builtin program %s to core BPF", FD_BASE58_ENC_32_ALLOCA( stateless_builtins[i].pubkey->key ) ));
2059-
fd_migrate_builtin_to_core_bpf( slot_ctx,
2060-
stateless_builtins[i].core_bpf_migration_config->upgrade_authority_address,
2061-
stateless_builtins[i].core_bpf_migration_config->builtin_program_id,
2062-
stateless_builtins[i].core_bpf_migration_config->source_buffer_address,
2063-
1,
2064-
runtime_spad );
2128+
fd_migrate_builtin_to_core_bpf( slot_ctx, stateless_builtins[i].core_bpf_migration_config, runtime_spad );
20652129
}
20662130
}
20672131

src/flamenco/runtime/fd_system_ids.c

Lines changed: 7 additions & 5 deletions
Original file line numberDiff line numberDiff line change
@@ -36,13 +36,15 @@ const fd_pubkey_t fd_solana_spl_native_mint_id = { .uc = { NATIVE
3636
const fd_pubkey_t fd_solana_spl_token_id = { .uc = { TOKEN_PROG_ID } };
3737
const fd_pubkey_t fd_solana_zk_token_proof_program_id = { .uc = { ZK_TOKEN_PROG_ID } };
3838
const fd_pubkey_t fd_solana_zk_elgamal_proof_program_id = { .uc = { ZK_EL_GAMAL_PROG_ID } };
39+
const fd_pubkey_t fd_solana_slashing_program_id = { .uc = { SLASHING_PROG_ID } };
3940

40-
const fd_pubkey_t fd_solana_address_lookup_table_program_buffer_address = { .uc = { ADDR_LUT_PROG_BUFFER_ID } };
41-
const fd_pubkey_t fd_solana_config_program_buffer_address = { .uc = { CONFIG_PROG_BUFFER_ID } };
42-
const fd_pubkey_t fd_solana_feature_program_buffer_address = { .uc = { FEATURE_PROG_BUFFER_ID } };
43-
const fd_pubkey_t fd_solana_stake_program_buffer_address = { .uc = { STAKE_PROG_BUFFER_ID } };
41+
const fd_pubkey_t fd_solana_address_lookup_table_program_buffer_address = { .uc = { ADDR_LUT_PROG_BUFFER_ID } };
42+
const fd_pubkey_t fd_solana_config_program_buffer_address = { .uc = { CONFIG_PROG_BUFFER_ID } };
43+
const fd_pubkey_t fd_solana_feature_program_buffer_address = { .uc = { FEATURE_PROG_BUFFER_ID } };
44+
const fd_pubkey_t fd_solana_stake_program_buffer_address = { .uc = { STAKE_PROG_BUFFER_ID } };
45+
const fd_pubkey_t fd_solana_slashing_program_buffer_address = { .uc = { SLASHING_PROG_BUFFER_ID } };
4446

45-
const fd_pubkey_t fd_solana_migration_authority = { .uc = { MIGRATION_AUTHORITY_ID } };
47+
const fd_pubkey_t fd_solana_migration_authority = { .uc = { MIGRATION_AUTHORITY_ID } };
4648

4749
/* https://github.com/firedancer-io/agave/blob/66c126b41ec2b55b3f747a4ac4e3ee6b439164a5/sdk/src/reserved_account_keys.rs#L152-L194 */
4850
#define MAP_PERFECT_NAME fd_pubkey_active_reserved_keys_tbl

src/flamenco/runtime/fd_system_ids.h

Lines changed: 2 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -43,13 +43,15 @@ extern const fd_pubkey_t fd_solana_spl_native_mint_id;
4343
extern const fd_pubkey_t fd_solana_spl_token_id;
4444
extern const fd_pubkey_t fd_solana_zk_token_proof_program_id;
4545
extern const fd_pubkey_t fd_solana_zk_elgamal_proof_program_id;
46+
extern const fd_pubkey_t fd_solana_slashing_program_id;
4647

4748
/* Buffer accounts for BPF migrations
4849
https://github.com/anza-xyz/agave/blob/v2.1.6/runtime/src/bank/builtins/mod.rs#L151-L165 */
4950
extern const fd_pubkey_t fd_solana_address_lookup_table_program_buffer_address;
5051
extern const fd_pubkey_t fd_solana_config_program_buffer_address;
5152
extern const fd_pubkey_t fd_solana_feature_program_buffer_address;
5253
extern const fd_pubkey_t fd_solana_stake_program_buffer_address;
54+
extern const fd_pubkey_t fd_solana_slashing_program_buffer_address;
5355

5456
/* BPF migration authority
5557
https://github.com/anza-xyz/agave/blob/v2.2.6/programs/bpf_loader/src/lib.rs#L399-L401 */

0 commit comments

Comments
 (0)