Line data Source code
1 : #include "fd_features.h"
2 : #include "../runtime/fd_system_ids.h"
3 : #include "../runtime/sysvar/fd_sysvar_epoch_schedule.h"
4 :
5 : FD_STATIC_ASSERT( sizeof ( fd_feature_t )==9UL, layout );
6 : FD_STATIC_ASSERT( offsetof( fd_feature_t, is_active )==0UL, layout );
7 : FD_STATIC_ASSERT( offsetof( fd_feature_t, activation_slot )==1UL, layout );
8 :
9 : fd_feature_t *
10 : fd_feature_decode( fd_feature_t * feature,
11 : uchar const * data,
12 717 : ulong data_sz ) {
13 717 : if( FD_UNLIKELY( data_sz < sizeof(fd_feature_t) ) ) return NULL;
14 714 : *feature = FD_LOAD( fd_feature_t, data );
15 714 : if( FD_UNLIKELY( feature->is_active>1 ) ) return NULL;
16 714 : return feature;
17 714 : }
18 :
19 : void
20 36 : fd_features_enable_all( fd_features_t * f ) {
21 36 : for( fd_feature_id_t const * id = fd_feature_iter_init();
22 10872 : !fd_feature_iter_done( id );
23 10836 : id = fd_feature_iter_next( id ) ) {
24 10836 : fd_features_set( f, id, 0UL );
25 10836 : }
26 36 : }
27 :
28 : void
29 8094 : fd_features_disable_all( fd_features_t * f ) {
30 8094 : for( fd_feature_id_t const * id = fd_feature_iter_init();
31 2444388 : !fd_feature_iter_done( id );
32 2436294 : id = fd_feature_iter_next( id ) ) {
33 2436294 : fd_features_set( f, id, FD_FEATURE_DISABLED );
34 2436294 : }
35 8094 : }
36 :
37 : void
38 5028 : fd_features_enable_cleaned_up( fd_features_t * f ) {
39 5028 : for( fd_feature_id_t const * id = fd_feature_iter_init();
40 1518456 : !fd_feature_iter_done( id );
41 1513428 : id = fd_feature_iter_next( id ) ) {
42 1513428 : if( FD_LIKELY( id->cleaned_up ) ) {
43 1091076 : fd_features_set( f, id, 0UL );
44 1091076 : } else {
45 422352 : fd_features_set( f, id, FD_FEATURE_DISABLED );
46 422352 : }
47 1513428 : }
48 5028 : }
49 :
50 : static uchar one_off_forced[ FD_FEATURE_ID_CNT ];
51 :
52 : void
53 18 : fd_features_enable_one_offs( fd_features_t * f, char const * * one_offs, uint one_offs_cnt, ulong slot ) {
54 18 : uchar pubkey[32];
55 72 : for( uint i=0U; i<one_offs_cnt; i++ ) {
56 54 : fd_base58_decode_32( one_offs[i], pubkey );
57 54 : for( fd_feature_id_t const * id = fd_feature_iter_init();
58 13230 : !fd_feature_iter_done( id );
59 13230 : id = fd_feature_iter_next( id ) ) {
60 13230 : if( !memcmp( &id->id, pubkey, sizeof(fd_pubkey_t) ) ) {
61 54 : fd_features_set( f, id, slot );
62 54 : one_off_forced[ id->index ] = (uchar)( slot!=FD_FEATURE_DISABLED );
63 54 : break;
64 54 : }
65 13230 : }
66 54 : }
67 18 : }
68 :
69 : static void
70 : fd_feature_restore( fd_features_t * features,
71 : fd_accdb_t * accdb,
72 : fd_accdb_fork_id_t fork_id,
73 : ulong slot,
74 : fd_epoch_schedule_t const * epoch_schedule,
75 169764 : fd_feature_id_t const * id ) {
76 :
77 169764 : if( FD_UNLIKELY( id->cleaned_up ) ) {
78 122388 : fd_features_set( features, id, 0UL );
79 122388 : return;
80 122388 : }
81 :
82 47376 : fd_features_set( features, id, FD_FEATURE_DISABLED );
83 :
84 : /* Skip reverted features */
85 47376 : if( FD_UNLIKELY( id->reverted ) ) return;
86 :
87 37224 : fd_acc_t acc = fd_accdb_read_one( accdb, fork_id, id->id.uc );
88 37224 : if( FD_UNLIKELY( !acc.lamports ) ) {
89 36711 : fd_accdb_unread_one( accdb, &acc );
90 36711 : return;
91 36711 : }
92 :
93 : /* Skip accounts that are not owned by the feature program
94 : https://github.com/anza-xyz/solana-sdk/blob/6512aca61167088ce10f2b545c35c9bcb1400e70/feature-gate-interface/src/lib.rs#L42-L44 */
95 513 : if( FD_UNLIKELY( memcmp( acc.owner, fd_solana_feature_program_id.uc, 32UL ) ) ) {
96 9 : fd_accdb_unread_one( accdb, &acc );
97 9 : return;
98 9 : }
99 :
100 : /* Account data size must be >= FD_FEATURE_SIZEOF (9 bytes)
101 : https://github.com/anza-xyz/solana-sdk/blob/6512aca61167088ce10f2b545c35c9bcb1400e70/feature-gate-interface/src/lib.rs#L45-L47 */
102 504 : if( FD_UNLIKELY( acc.data_len<sizeof(fd_feature_t) ) ) {
103 6 : fd_accdb_unread_one( accdb, &acc );
104 6 : return;
105 6 : }
106 :
107 : /* Deserialize the feature account data
108 : https://github.com/anza-xyz/solana-sdk/blob/6512aca61167088ce10f2b545c35c9bcb1400e70/feature-gate-interface/src/lib.rs#L48-L50 */
109 498 : fd_feature_t feature[1];
110 498 : if( FD_UNLIKELY( !fd_feature_decode( feature, acc.data, acc.data_len ) ) ) {
111 0 : fd_accdb_unread_one( accdb, &acc );
112 0 : return;
113 0 : }
114 498 : fd_accdb_unread_one( accdb, &acc );
115 :
116 498 : FD_BASE58_ENCODE_32_BYTES( id->id.uc, addr_b58 );
117 498 : if( feature->is_active ) {
118 459 : FD_LOG_DEBUG(( "feature %s activated at slot %lu", addr_b58, feature->activation_slot ));
119 459 : fd_features_set( features, id, feature->activation_slot );
120 459 : } else if( fd_slot_to_epoch( epoch_schedule, slot, NULL )!=fd_slot_to_epoch( epoch_schedule, slot+1UL, NULL ) ) {
121 39 : ulong activation_slot = slot+1UL;
122 39 : FD_LOG_DEBUG(( "feature %s pending, pre-populating activation at slot %lu", addr_b58, activation_slot ));
123 39 : fd_features_set( features, id, activation_slot );
124 39 : } else {
125 0 : FD_LOG_DEBUG(( "feature %s not activated at slot %lu", addr_b58, feature->activation_slot ));
126 0 : }
127 498 : }
128 :
129 : void
130 : fd_features_restore_chunk( fd_features_t * features,
131 : fd_accdb_t * accdb,
132 : fd_accdb_fork_id_t fork_id,
133 : ulong slot,
134 : fd_epoch_schedule_t const * epoch_schedule,
135 : ulong chunk_idx,
136 582 : ulong chunk_cnt ) {
137 582 : FD_TEST( chunk_cnt>0UL );
138 582 : FD_TEST( chunk_idx<chunk_cnt );
139 :
140 582 : ulong begin = chunk_idx * FD_FEATURE_ID_CNT / chunk_cnt;
141 582 : ulong end = (chunk_idx+1) * FD_FEATURE_ID_CNT / chunk_cnt;
142 :
143 170346 : for( fd_feature_id_t const * id=ids+begin; id<ids+end; id++ ) {
144 169764 : fd_feature_restore( features, accdb, fork_id, slot, epoch_schedule, id );
145 169764 : if( FD_UNLIKELY( one_off_forced[ id->index ] ) ) fd_features_set( features, id, 0UL );
146 169764 : }
147 582 : }
148 :
149 : void
150 : fd_features_restore( fd_features_t * features,
151 : fd_accdb_t * accdb,
152 : fd_accdb_fork_id_t fork_id,
153 : ulong slot,
154 561 : fd_epoch_schedule_t const * epoch_schedule ) {
155 561 : fd_features_restore_chunk( features, accdb, fork_id, slot, epoch_schedule, 0UL, 1UL );
156 561 : }
|