51
51
#define FD_STAKE_ERR_REDELEGATE_TRANSIENT_OR_INACTIVE_STAKE ( 13 )
52
52
#define FD_STAKE_ERR_REDELEGATE_TO_SAME_VOTE_ACCOUNT ( 14 )
53
53
#define FD_STAKE_ERR_REDELEGATED_STAKE_MUST_FULLY_ACTIVATE_BEFORE_DEACTIVATION_IS_PERMITTED ( 15 )
54
+ #define FD_STAKE_ERR_EPOCH_REWARDS_ACTIVE ( 16 )
54
55
55
56
/**********************************************************************/
56
57
/* Constants */
@@ -1818,6 +1819,7 @@ merge( fd_exec_instr_ctx_t const * ctx,
1818
1819
return 0 ;
1819
1820
}
1820
1821
1822
+ // https://github.com/anza-xyz/agave/blob/e4ec48f865208cac7727f12e215ef050421d206c/programs/stake/src/stake_state.rs#590
1821
1823
static int
1822
1824
redelegate ( fd_exec_instr_ctx_t const * ctx ,
1823
1825
ulong stake_account_index ,
@@ -1830,6 +1832,7 @@ redelegate( fd_exec_instr_ctx_t const * ctx,
1830
1832
1831
1833
fd_valloc_t scratch_valloc = fd_scratch_virtual ();
1832
1834
1835
+ // https://github.com/anza-xyz/agave/blob/e4ec48f865208cac7727f12e215ef050421d206c/programs/stake/src/stake_state.rs#599
1833
1836
fd_sol_sysvar_clock_t const * clock = fd_sysvar_cache_clock ( ctx -> slot_ctx -> sysvar_cache );
1834
1837
if ( FD_UNLIKELY ( !clock ) )
1835
1838
return FD_EXECUTOR_INSTR_ERR_UNSUPPORTED_SYSVAR ;
@@ -1843,17 +1846,23 @@ redelegate( fd_exec_instr_ctx_t const * ctx,
1843
1846
if ( FD_UNLIKELY ( !fd_borrowed_account_acquire_write ( uninitialized_stake_account ) ) )
1844
1847
return FD_EXECUTOR_INSTR_ERR_ACC_BORROW_FAILED ;
1845
1848
1849
+ // https://github.com/anza-xyz/agave/blob/e4ec48f865208cac7727f12e215ef050421d206c/programs/stake/src/stake_state.rs#604
1846
1850
if ( FD_UNLIKELY ( 0 != memcmp ( & uninitialized_stake_account -> meta -> info .owner ,
1847
1851
fd_solana_stake_program_id .key , sizeof ( fd_pubkey_t ) ) ) )
1852
+ // https://github.com/anza-xyz/agave/blob/e4ec48f865208cac7727f12e215ef050421d206c/programs/stake/src/stake_state.rs#611
1848
1853
return FD_EXECUTOR_INSTR_ERR_INCORRECT_PROGRAM_ID ;
1849
1854
1855
+ // https://github.com/anza-xyz/agave/blob/e4ec48f865208cac7727f12e215ef050421d206c/programs/stake/src/stake_state.rs#613
1850
1856
if ( FD_UNLIKELY ( uninitialized_stake_account -> meta -> dlen != stake_state_v2_size_of () ) )
1857
+ // https://github.com/anza-xyz/agave/blob/e4ec48f865208cac7727f12e215ef050421d206c/programs/stake/src/stake_state.rs#620
1851
1858
return FD_EXECUTOR_INSTR_ERR_INVALID_ACC_DATA ;
1852
1859
1853
1860
fd_stake_state_v2_t uninitialized_stake_account_state = { 0 };
1854
1861
rc = get_state ( uninitialized_stake_account , fd_scratch_virtual (), & uninitialized_stake_account_state );
1855
1862
if ( FD_UNLIKELY ( rc ) ) return rc ;
1863
+ // https://github.com/anza-xyz/agave/blob/e4ec48f865208cac7727f12e215ef050421d206c/programs/stake/src/stake_state.rs#622
1856
1864
if ( FD_UNLIKELY ( uninitialized_stake_account_state .discriminant != fd_stake_state_v2_enum_uninitialized ) )
1865
+ // https://github.com/anza-xyz/agave/blob/e4ec48f865208cac7727f12e215ef050421d206c/programs/stake/src/stake_state.rs#630
1857
1866
return FD_EXECUTOR_INSTR_ERR_ACC_ALREADY_INITIALIZED ;
1858
1867
1859
1868
fd_borrowed_account_t * vote_account = NULL ;
@@ -1862,11 +1871,14 @@ redelegate( fd_exec_instr_ctx_t const * ctx,
1862
1871
if ( FD_UNLIKELY ( !fd_borrowed_account_acquire_write ( vote_account ) ) )
1863
1872
return FD_EXECUTOR_INSTR_ERR_ACC_BORROW_FAILED ;
1864
1873
1874
+ // https://github.com/anza-xyz/agave/blob/e4ec48f865208cac7727f12e215ef050421d206c/programs/stake/src/stake_state.rs#636
1865
1875
if ( FD_UNLIKELY ( 0 != memcmp ( & vote_account -> const_meta -> info .owner , fd_solana_vote_program_id .key , 32UL ) ) )
1866
1876
return FD_EXECUTOR_INSTR_ERR_INCORRECT_PROGRAM_ID ;
1867
1877
1878
+ // https://github.com/anza-xyz/agave/blob/e4ec48f865208cac7727f12e215ef050421d206c/programs/stake/src/stake_state.rs#645
1868
1879
fd_pubkey_t const * vote_pubkey = vote_account -> pubkey ;
1869
1880
fd_vote_state_versioned_t vote_state = { 0 };
1881
+ // https://github.com/anza-xyz/agave/blob/e4ec48f865208cac7727f12e215ef050421d206c/programs/stake/src/stake_state.rs#646
1870
1882
rc = fd_vote_get_state ( vote_account , scratch_valloc , & vote_state );
1871
1883
if ( FD_UNLIKELY ( rc ) ) return rc ;
1872
1884
@@ -1875,6 +1887,7 @@ redelegate( fd_exec_instr_ctx_t const * ctx,
1875
1887
fd_stake_state_v2_t stake_account_state = { 0 };
1876
1888
rc = get_state ( stake_account , fd_scratch_virtual (), & stake_account_state );
1877
1889
if ( FD_UNLIKELY ( rc ) ) return rc ;
1890
+ // https://github.com/anza-xyz/agave/blob/e4ec48f865208cac7727f12e215ef050421d206c/programs/stake/src/stake_state.rs#649
1878
1891
if ( FD_LIKELY ( stake_account_state .discriminant == fd_stake_state_v2_enum_stake ) ) {
1879
1892
fd_stake_meta_t meta = stake_account_state .inner .stake .meta ;
1880
1893
fd_stake_t stake = stake_account_state .inner .stake .stake ;
@@ -1888,20 +1901,24 @@ redelegate( fd_exec_instr_ctx_t const * ctx,
1888
1901
int is_some = new_warmup_cooldown_rate_epoch ( ctx , & new_rate_activation_epoch , & err );
1889
1902
if ( FD_UNLIKELY ( err ) ) return err ;
1890
1903
1904
+ // https://github.com/anza-xyz/agave/blob/e4ec48f865208cac7727f12e215ef050421d206c/programs/stake/src/stake_state.rs#650
1891
1905
fd_stake_history_entry_t status =
1892
1906
stake_activating_and_deactivating ( & stake .delegation ,
1893
1907
clock -> epoch ,
1894
1908
stake_history ,
1895
1909
fd_ptr_if ( is_some , & new_rate_activation_epoch , NULL ) );
1896
1910
1897
- if ( FD_UNLIKELY ( status .effective == 0 || status .activating != 0 ||
1898
- status .deactivating != 0 ) ) {
1911
+ // https://github.com/anza-xyz/agave/blob/e4ec48f865208cac7727f12e215ef050421d206c/programs/stake/src/stake_state.rs#651
1912
+ if ( FD_UNLIKELY ( status .effective == 0 || status .activating != 0 || status .deactivating != 0 ) ) {
1913
+ // https://github.com/anza-xyz/agave/blob/e4ec48f865208cac7727f12e215ef050421d206c/programs/stake/src/stake_state.rs#653
1899
1914
* custom_err = FD_STAKE_ERR_REDELEGATE_TRANSIENT_OR_INACTIVE_STAKE ;
1900
1915
return FD_EXECUTOR_INSTR_ERR_CUSTOM_ERR ;
1901
1916
}
1902
1917
1918
+ // https://github.com/anza-xyz/agave/blob/e4ec48f865208cac7727f12e215ef050421d206c/programs/stake/src/stake_state.rs#658
1903
1919
if ( FD_UNLIKELY (
1904
1920
0 == memcmp ( & stake .delegation .voter_pubkey , vote_pubkey , sizeof (fd_pubkey_t ) ) ) ) {
1921
+ // https://github.com/anza-xyz/agave/blob/e4ec48f865208cac7727f12e215ef050421d206c/programs/stake/src/stake_state.rs#663
1905
1922
* custom_err = FD_STAKE_ERR_REDELEGATE_TO_SAME_VOTE_ACCOUNT ;
1906
1923
return FD_EXECUTOR_INSTR_ERR_CUSTOM_ERR ;
1907
1924
}
@@ -1912,6 +1929,8 @@ redelegate( fd_exec_instr_ctx_t const * ctx,
1912
1929
return FD_EXECUTOR_INSTR_ERR_INVALID_ACC_DATA ;
1913
1930
}
1914
1931
1932
+ // https://github.com/anza-xyz/agave/blob/e4ec48f865208cac7727f12e215ef050421d206c/programs/stake/src/stake_state.rs#675
1933
+ // TODO: review
1915
1934
rc = deactivate ( ctx ,
1916
1935
stake_account ,
1917
1936
stake_account_index ,
@@ -1920,9 +1939,11 @@ redelegate( fd_exec_instr_ctx_t const * ctx,
1920
1939
& ctx -> txn_ctx -> custom_err );
1921
1940
if ( FD_UNLIKELY ( rc ) ) return rc ;
1922
1941
1942
+ // https://github.com/anza-xyz/agave/blob/e4ec48f865208cac7727f12e215ef050421d206c/programs/stake/src/stake_state.rs#678
1923
1943
rc = fd_account_checked_sub_lamports ( ctx , stake_account_index , effective_stake );
1924
1944
if ( FD_UNLIKELY ( rc ) ) return rc ;
1925
1945
1946
+ // https://github.com/anza-xyz/agave/blob/e4ec48f865208cac7727f12e215ef050421d206c/programs/stake/src/stake_state.rs#679
1926
1947
rc = fd_account_checked_add_lamports ( ctx , uninitialized_stake_account_index , effective_stake );
1927
1948
if ( FD_UNLIKELY ( rc ) ) return rc ;
1928
1949
@@ -1931,10 +1952,13 @@ redelegate( fd_exec_instr_ctx_t const * ctx,
1931
1952
return FD_EXECUTOR_INSTR_ERR_UNSUPPORTED_SYSVAR ;
1932
1953
1933
1954
fd_stake_meta_t uninitialized_stake_meta = stake_meta ;
1955
+ // https://github.com/anza-xyz/agave/blob/e4ec48f865208cac7727f12e215ef050421d206c/programs/stake/src/stake_state.rs#685
1934
1956
uninitialized_stake_meta .rent_exempt_reserve =
1935
1957
fd_rent_exempt_minimum_balance2 ( rent , uninitialized_stake_account -> meta -> dlen );
1936
1958
1937
1959
validated_delegated_info_t validated_delegated_info = { 0 };
1960
+ // https://github.com/anza-xyz/agave/blob/e4ec48f865208cac7727f12e215ef050421d206c/programs/stake/src/stake_state.rs#688
1961
+ // TODO: review
1938
1962
rc = validate_delegated_amount ( uninitialized_stake_account ,
1939
1963
& uninitialized_stake_meta ,
1940
1964
ctx -> slot_ctx ,
@@ -1950,7 +1974,9 @@ redelegate( fd_exec_instr_ctx_t const * ctx,
1950
1974
.discriminant = fd_stake_state_v2_enum_stake ,
1951
1975
.inner = { .stake = { .meta = uninitialized_stake_meta ,
1952
1976
.stake = new_stake_ ,
1977
+ // https://github.com/anza-xyz/agave/blob/e4ec48f865208cac7727f12e215ef050421d206c/programs/stake/src/stake_state.rs#701
1953
1978
.stake_flags = STAKE_FLAGS_MUST_FULLY_ACTIVATE_BEFORE_DEACTIVATION_IS_PERMITTED } } };
1979
+ // https://github.com/anza-xyz/agave/blob/e4ec48f865208cac7727f12e215ef050421d206c/programs/stake/src/stake_state.rs#693
1954
1980
rc = set_state ( ctx , uninitialized_stake_account_index , & new_stake_state );
1955
1981
if ( FD_UNLIKELY ( rc ) ) return rc ;
1956
1982
@@ -2270,6 +2296,17 @@ fd_stake_program_execute( fd_exec_instr_ctx_t ctx ) {
2270
2296
(ulong )ctx .instr -> data + 1232UL < (ulong )decode .data )
2271
2297
return FD_EXECUTOR_INSTR_ERR_INVALID_INSTR_DATA ;
2272
2298
2299
+ /* The EpochRewards sysvar only exists after the
2300
+ enable_partitioned_epoch_reward feature is activated. If it exists, check
2301
+ the `active` field */
2302
+ fd_sysvar_epoch_rewards_t const * rewards = fd_sysvar_cache_epoch_rewards ( ctx .slot_ctx -> sysvar_cache );
2303
+ int epoch_rewards_active = (NULL != rewards ) ? rewards -> epoch_rewards .active : false;
2304
+
2305
+ if (epoch_rewards_active && instruction -> discriminant != fd_stake_instruction_enum_get_minimum_delegation ) {
2306
+ ctx .txn_ctx -> custom_err = FD_STAKE_ERR_EPOCH_REWARDS_ACTIVE ;
2307
+ return FD_EXECUTOR_INSTR_ERR_CUSTOM_ERR ;
2308
+ }
2309
+
2273
2310
/* Replicate stake account changes to bank caches after processing the
2274
2311
transaction's instructions. */
2275
2312
ctx .txn_ctx -> dirty_stake_acc = 1 ;
@@ -2831,48 +2868,20 @@ fd_stake_program_execute( fd_exec_instr_ctx_t ctx ) {
2831
2868
* https://github.com/firedancer-io/solana/blob/v1.17/sdk/program/src/stake/instruction.rs#L296
2832
2869
*
2833
2870
* Processor:
2834
- * https://github.com/firedancer-io/solana /blob/v1.17 /programs/stake/src/stake_instruction.rs#L424
2871
+ * https://github.com/anza-xyz/agave /blob/e4ec48f865208cac7727f12e215ef050421d206c /programs/stake/src/stake_instruction.rs#L335
2835
2872
*/
2836
2873
case fd_stake_instruction_enum_redelegate : {
2837
2874
fd_borrowed_account_t * me = NULL ;
2838
2875
rc = get_stake_account ( & ctx , & me );
2839
2876
if ( FD_UNLIKELY ( rc ) ) return rc ;
2877
+ // https://github.com/anza-xyz/agave/blob/e4ec48f865208cac7727f12e215ef050421d206c/programs/stake/src/stake_instruction.rs#L339
2840
2878
2841
- // FIXME FD_LIKELY
2842
2879
if ( FD_LIKELY ( FD_FEATURE_ACTIVE ( ctx .slot_ctx , stake_redelegate_instruction ) ) ) {
2843
-
2880
+ // https://github.com/anza-xyz/agave/blob/e4ec48f865208cac7727f12e215ef050421d206c/programs/stake/src/stake_instruction.rs#L341
2844
2881
if ( FD_UNLIKELY ( ctx .instr -> acct_cnt < 3 ) )
2845
2882
return FD_EXECUTOR_INSTR_ERR_NOT_ENOUGH_ACC_KEYS ;
2846
2883
2847
- // FIXME FD_LIKELY
2848
- if ( FD_UNLIKELY ( !FD_FEATURE_ACTIVE ( ctx .slot_ctx , reduce_stake_warmup_cooldown ) ) ) {
2849
- fd_borrowed_account_t * config_account = NULL ;
2850
- rc = fd_instr_borrowed_account_view_idx ( & ctx , 3 , & config_account );
2851
- if ( FD_UNLIKELY ( rc ) ) return rc ;
2852
-
2853
- if ( FD_UNLIKELY ( !fd_borrowed_account_acquire_write ( config_account ) ) )
2854
- return FD_EXECUTOR_INSTR_ERR_ACC_BORROW_FAILED ;
2855
-
2856
- fd_pubkey_t const * config_account_key = & ctx .instr -> acct_pubkeys [3 ];
2857
- if ( FD_UNLIKELY ( 0 != memcmp ( config_account_key -> uc ,
2858
- fd_solana_stake_program_config_id .key ,
2859
- sizeof (fd_pubkey_t ) ) ) ) {
2860
- return FD_EXECUTOR_INSTR_ERR_INVALID_ARG ;
2861
- }
2862
- // https://github.com/firedancer-io/solana/blob/v1.17/programs/stake/src/stake_instruction.rs#L442
2863
- fd_bincode_decode_ctx_t decode_ctx ;
2864
- decode_ctx .data = config_account -> const_data ;
2865
- decode_ctx .dataend = config_account -> const_data + config_account -> const_meta -> dlen ;
2866
- decode_ctx .valloc = decode_ctx .valloc ;
2867
-
2868
- fd_stake_config_t stake_config ;
2869
- rc = fd_stake_config_decode ( & stake_config , & decode_ctx );
2870
- if ( FD_UNLIKELY ( rc != FD_BINCODE_SUCCESS ) )
2871
- return FD_EXECUTOR_INSTR_ERR_INVALID_ARG ;
2872
-
2873
- fd_borrowed_account_release_write ( config_account );
2874
- }
2875
-
2884
+ // https://github.com/anza-xyz/agave/blob/e4ec48f865208cac7727f12e215ef050421d206c/programs/stake/src/stake_instruction.rs#L342
2876
2885
rc = redelegate ( & ctx ,
2877
2886
0 ,
2878
2887
me ,
0 commit comments