Line data Source code
1 : #include "fd_features.h"
2 : #include "../runtime/fd_bank.h"
3 : #include "../runtime/fd_system_ids.h"
4 : #include "../accdb/fd_accdb_sync.h"
5 :
6 : FD_STATIC_ASSERT( sizeof ( fd_feature_t )==9UL, layout );
7 : FD_STATIC_ASSERT( offsetof( fd_feature_t, is_active )==0UL, layout );
8 : FD_STATIC_ASSERT( offsetof( fd_feature_t, activation_slot )==1UL, layout );
9 :
10 : fd_feature_t *
11 : fd_feature_decode( fd_feature_t * feature,
12 : uchar const * data,
13 0 : ulong data_sz ) {
14 0 : if( FD_UNLIKELY( data_sz < sizeof(fd_feature_t) ) ) return NULL;
15 0 : *feature = FD_LOAD( fd_feature_t, data );
16 0 : if( FD_UNLIKELY( feature->is_active>1 ) ) return NULL;
17 0 : return feature;
18 0 : }
19 :
20 : void
21 3 : fd_features_enable_all( fd_features_t * f ) {
22 3 : for( fd_feature_id_t const * id = fd_feature_iter_init();
23 780 : !fd_feature_iter_done( id );
24 777 : id = fd_feature_iter_next( id ) ) {
25 777 : fd_features_set( f, id, 0UL );
26 777 : }
27 3 : }
28 :
29 : void
30 387 : fd_features_disable_all( fd_features_t * f ) {
31 387 : for( fd_feature_id_t const * id = fd_feature_iter_init();
32 100620 : !fd_feature_iter_done( id );
33 100233 : id = fd_feature_iter_next( id ) ) {
34 100233 : fd_features_set( f, id, FD_FEATURE_DISABLED );
35 100233 : }
36 387 : }
37 :
38 : void
39 15 : fd_features_enable_cleaned_up( fd_features_t * f, fd_cluster_version_t const * cluster_version ) {
40 15 : for( fd_feature_id_t const * id = fd_feature_iter_init();
41 3900 : !fd_feature_iter_done( id );
42 3885 : id = fd_feature_iter_next( id ) ) {
43 3885 : if( ( id->cleaned_up[0]<cluster_version->major ) ||
44 3885 : ( id->cleaned_up[0]==cluster_version->major && id->cleaned_up[1]<cluster_version->minor ) ||
45 3885 : ( id->cleaned_up[0]==cluster_version->major && id->cleaned_up[1]==cluster_version->minor && id->cleaned_up[2]<=cluster_version->patch ) ) {
46 2745 : fd_features_set( f, id, 0UL );
47 2745 : } else {
48 1140 : fd_features_set( f, id, FD_FEATURE_DISABLED );
49 1140 : }
50 3885 : }
51 15 : }
52 :
53 : void
54 18 : fd_features_enable_one_offs( fd_features_t * f, char const * * one_offs, uint one_offs_cnt, ulong slot ) {
55 18 : uchar pubkey[32];
56 36 : for( uint i=0U; i<one_offs_cnt; i++ ) {
57 18 : fd_base58_decode_32( one_offs[i], pubkey );
58 18 : for( fd_feature_id_t const * id = fd_feature_iter_init();
59 4680 : !fd_feature_iter_done( id );
60 4662 : id = fd_feature_iter_next( id ) ) {
61 4662 : if( !memcmp( &id->id, pubkey, sizeof(fd_pubkey_t) ) ) {
62 0 : fd_features_set( f, id, slot );
63 0 : break;
64 0 : }
65 4662 : }
66 18 : }
67 18 : }
68 :
69 : static void
70 : fd_feature_restore( fd_bank_t * bank,
71 : fd_accdb_user_t * accdb,
72 : fd_funk_txn_xid_t const * xid,
73 : fd_feature_id_t const * id,
74 11655 : fd_pubkey_t const * addr ) {
75 :
76 11655 : fd_features_t * features = fd_bank_features_modify( bank );
77 :
78 : /* Skip reverted features */
79 11655 : if( FD_UNLIKELY( id->reverted ) ) return;
80 :
81 11205 : fd_accdb_ro_t ro[1];
82 11205 : if( FD_UNLIKELY( !fd_accdb_open_ro( accdb, ro, xid, addr ) ) ) {
83 11205 : return;
84 11205 : }
85 :
86 : /* Skip accounts that are not owned by the feature program
87 : https://github.com/anza-xyz/solana-sdk/blob/6512aca61167088ce10f2b545c35c9bcb1400e70/feature-gate-interface/src/lib.rs#L42-L44 */
88 0 : if( FD_UNLIKELY( memcmp( fd_accdb_ref_owner( ro ), fd_solana_feature_program_id.key, sizeof(fd_pubkey_t) ) ) ) {
89 0 : fd_accdb_close_ro( accdb, ro );
90 0 : return;
91 0 : }
92 :
93 : /* Account data size must be >= FD_FEATURE_SIZEOF (9 bytes)
94 : https://github.com/anza-xyz/solana-sdk/blob/6512aca61167088ce10f2b545c35c9bcb1400e70/feature-gate-interface/src/lib.rs#L45-L47 */
95 0 : if( FD_UNLIKELY( fd_accdb_ref_data_sz( ro ) < sizeof(fd_feature_t) ) ) {
96 0 : fd_accdb_close_ro( accdb, ro );
97 0 : return;
98 0 : }
99 :
100 : /* Deserialize the feature account data
101 : https://github.com/anza-xyz/solana-sdk/blob/6512aca61167088ce10f2b545c35c9bcb1400e70/feature-gate-interface/src/lib.rs#L48-L50 */
102 0 : fd_feature_t feature[1];
103 0 : if( FD_UNLIKELY( !fd_feature_decode(
104 0 : feature,
105 0 : fd_accdb_ref_data_const( ro ),
106 0 : fd_accdb_ref_data_sz ( ro ) ) ) ) {
107 0 : fd_accdb_close_ro( accdb, ro );
108 0 : return;
109 0 : }
110 0 : fd_accdb_close_ro( accdb, ro );
111 :
112 0 : FD_BASE58_ENCODE_32_BYTES( addr->uc, addr_b58 );
113 0 : if( feature->is_active ) {
114 0 : FD_LOG_DEBUG(( "feature %s activated at slot %lu", addr_b58, feature->activation_slot ));
115 0 : fd_features_set( features, id, feature->activation_slot );
116 0 : } else {
117 0 : FD_LOG_DEBUG(( "feature %s not activated at slot %lu", addr_b58, feature->activation_slot ));
118 0 : }
119 0 : }
120 :
121 : void
122 : fd_features_restore( fd_bank_t * bank,
123 : fd_accdb_user_t * accdb,
124 45 : fd_funk_txn_xid_t const * xid ) {
125 :
126 45 : for( fd_feature_id_t const * id = fd_feature_iter_init();
127 11700 : !fd_feature_iter_done( id );
128 11655 : id = fd_feature_iter_next( id ) ) {
129 11655 : fd_feature_restore( bank, accdb, xid, id, &id->id );
130 11655 : }
131 45 : }
|