Line data Source code
1 : #include "fd_authorized_voters.h" 2 : #include "fd_vote_state_v3.h" 3 : #include "fd_vote_state_v4.h" 4 : 5 : fd_vote_authorized_voters_t * 6 : fd_authorized_voters_new( ulong epoch, 7 : fd_pubkey_t const * pubkey, 8 2 : uchar * mem ) { 9 : 10 2 : FD_SCRATCH_ALLOC_INIT( l, mem ); 11 2 : fd_vote_authorized_voters_t * authorized_voters = FD_SCRATCH_ALLOC_APPEND( l, fd_vote_authorized_voters_align(), sizeof(fd_vote_authorized_voters_t) ); 12 2 : void * pool_mem = FD_SCRATCH_ALLOC_APPEND( l, fd_vote_authorized_voters_pool_align(), fd_vote_authorized_voters_pool_footprint( FD_VOTE_AUTHORIZED_VOTERS_MIN ) ); 13 2 : void * treap_mem = FD_SCRATCH_ALLOC_APPEND( l, fd_vote_authorized_voters_treap_align(), fd_vote_authorized_voters_treap_footprint( FD_VOTE_AUTHORIZED_VOTERS_MIN ) ); 14 : 15 2 : authorized_voters->pool = fd_vote_authorized_voters_pool_join( fd_vote_authorized_voters_pool_new( pool_mem, FD_VOTE_AUTHORIZED_VOTERS_MIN ) ); 16 2 : authorized_voters->treap = fd_vote_authorized_voters_treap_join( fd_vote_authorized_voters_treap_new( treap_mem, FD_VOTE_AUTHORIZED_VOTERS_MIN ) ); 17 2 : if( FD_UNLIKELY( !fd_vote_authorized_voters_pool_free( authorized_voters->pool ) ) ) { 18 0 : FD_LOG_CRIT(( "invariant violation: max authorized voter count of vote account exceeded" )); 19 0 : } 20 2 : fd_vote_authorized_voter_t * ele = fd_vote_authorized_voters_pool_ele_acquire( authorized_voters->pool ); 21 2 : ele->epoch = epoch; 22 2 : ele->pubkey = *pubkey; 23 2 : ele->prio = (ulong)&ele->pubkey; 24 2 : fd_vote_authorized_voters_treap_ele_insert( authorized_voters->treap, ele, authorized_voters->pool ); 25 2 : return authorized_voters; 26 2 : } 27 : 28 : fd_vote_authorized_voters_t * 29 0 : fd_authorized_voters_new_empty( uchar * mem ) { 30 0 : FD_SCRATCH_ALLOC_INIT( l, mem ); 31 0 : fd_vote_authorized_voters_t * authorized_voters = FD_SCRATCH_ALLOC_APPEND( l, fd_vote_authorized_voters_align(), sizeof(fd_vote_authorized_voters_t) ); 32 0 : void * pool_mem = FD_SCRATCH_ALLOC_APPEND( l, fd_vote_authorized_voters_pool_align(), fd_vote_authorized_voters_pool_footprint( FD_VOTE_AUTHORIZED_VOTERS_MIN ) ); 33 0 : void * treap_mem = FD_SCRATCH_ALLOC_APPEND( l, fd_vote_authorized_voters_treap_align(), fd_vote_authorized_voters_treap_footprint( FD_VOTE_AUTHORIZED_VOTERS_MIN ) ); 34 : 35 0 : authorized_voters->pool = fd_vote_authorized_voters_pool_join( fd_vote_authorized_voters_pool_new( pool_mem, FD_VOTE_AUTHORIZED_VOTERS_MIN ) ); 36 0 : authorized_voters->treap = fd_vote_authorized_voters_treap_join( fd_vote_authorized_voters_treap_new( treap_mem, FD_VOTE_AUTHORIZED_VOTERS_MIN ) ); 37 0 : return authorized_voters; 38 0 : } 39 : 40 : int 41 345 : fd_authorized_voters_is_empty( fd_vote_authorized_voters_t * self ) { 42 345 : return fd_vote_authorized_voters_treap_ele_cnt( self->treap ) == 0; 43 345 : } 44 : 45 : int 46 16 : fd_authorized_voters_contains( fd_vote_authorized_voters_t * self, ulong epoch ) { 47 16 : return !!fd_vote_authorized_voters_treap_ele_query( self->treap, epoch, self->pool ); 48 16 : } 49 : 50 : fd_vote_authorized_voter_t * 51 15 : fd_authorized_voters_last( fd_vote_authorized_voters_t * self ) { 52 15 : fd_vote_authorized_voters_treap_rev_iter_t iter = 53 15 : fd_vote_authorized_voters_treap_rev_iter_init( self->treap, self->pool ); 54 15 : return fd_vote_authorized_voters_treap_rev_iter_ele( iter, self->pool ); 55 15 : } 56 : 57 : void 58 : fd_authorized_voters_purge_authorized_voters( fd_vote_authorized_voters_t * self, 59 336 : ulong current_epoch ) { 60 : 61 : // https://github.com/anza-xyz/agave/blob/v2.0.1/sdk/program/src/vote/authorized_voters.rs#L46 62 336 : ulong expired_keys[ FD_VOTE_AUTHORIZED_VOTERS_MIN ]; 63 336 : ulong key_cnt = 0; 64 336 : for( fd_vote_authorized_voters_treap_fwd_iter_t iter = 65 336 : fd_vote_authorized_voters_treap_fwd_iter_init( self->treap, self->pool ); 66 1026 : !fd_vote_authorized_voters_treap_fwd_iter_done( iter ); 67 690 : iter = fd_vote_authorized_voters_treap_fwd_iter_next( iter, self->pool ) ) { 68 690 : fd_vote_authorized_voter_t * ele = 69 690 : fd_vote_authorized_voters_treap_fwd_iter_ele( iter, self->pool ); 70 690 : if( ele->epoch < current_epoch ) expired_keys[key_cnt++] = ele->epoch; 71 690 : } 72 : 73 : // https://github.com/anza-xyz/agave/blob/v2.0.1/sdk/program/src/vote/authorized_voters.rs#L52 74 388 : for( ulong i = 0; i < key_cnt; i++ ) { 75 52 : fd_vote_authorized_voter_t * ele = 76 52 : fd_vote_authorized_voters_treap_ele_query( self->treap, expired_keys[i], self->pool ); 77 52 : fd_vote_authorized_voters_treap_ele_remove( self->treap, ele, self->pool ); 78 52 : fd_vote_authorized_voters_pool_ele_release( self->pool, ele ); 79 52 : } 80 : 81 : // https://github.com/anza-xyz/agave/blob/v2.0.1/sdk/program/src/vote/authorized_voters.rs#L60 82 336 : FD_TEST( !fd_authorized_voters_is_empty( self ) ); 83 : 84 336 : } 85 : 86 : fd_vote_authorized_voter_t * 87 : fd_authorized_voters_get_or_calculate_authorized_voter_for_epoch( fd_vote_authorized_voters_t * self, 88 : ulong epoch, 89 338 : int * existed ) { 90 338 : *existed = 0; 91 338 : ulong latest_epoch = 0; 92 338 : fd_vote_authorized_voter_t * res = 93 338 : fd_vote_authorized_voters_treap_ele_query( self->treap, epoch, self->pool ); 94 : // "predecessor" would be more big-O optimal here, but mirroring labs logic 95 : // https://github.com/anza-xyz/agave/blob/v2.0.1/sdk/program/src/vote/authorized_voters.rs#L93 96 338 : if( FD_UNLIKELY( !res ) ) { 97 36 : for( fd_vote_authorized_voters_treap_fwd_iter_t iter = 98 36 : fd_vote_authorized_voters_treap_fwd_iter_init( self->treap, self->pool ); 99 92 : !fd_vote_authorized_voters_treap_fwd_iter_done( iter ); 100 56 : iter = fd_vote_authorized_voters_treap_fwd_iter_next( iter, self->pool ) ) { 101 56 : fd_vote_authorized_voter_t * ele = 102 56 : fd_vote_authorized_voters_treap_fwd_iter_ele( iter, self->pool ); 103 56 : if( ele->epoch < epoch && ( latest_epoch == 0 || ele->epoch > latest_epoch ) ) { 104 53 : latest_epoch = ele->epoch; 105 53 : res = ele; 106 53 : } 107 56 : } 108 36 : *existed = 0; 109 36 : return res; 110 302 : } else { 111 302 : *existed = 1; 112 302 : return res; 113 302 : } 114 0 : return res; 115 338 : } 116 : 117 : fd_vote_authorized_voter_t * 118 : fd_authorized_voters_get_and_cache_authorized_voter_for_epoch( fd_vote_authorized_voters_t * self, 119 338 : ulong epoch ) { 120 338 : int existed = 0; 121 : // https://github.com/anza-xyz/agave/blob/v2.0.1/sdk/program/src/vote/authorized_voters.rs#L29 122 338 : fd_vote_authorized_voter_t * res = 123 338 : fd_authorized_voters_get_or_calculate_authorized_voter_for_epoch( self, epoch, &existed ); 124 338 : if( !res ) return NULL; 125 : // https://github.com/anza-xyz/agave/blob/v2.0.1/sdk/program/src/vote/authorized_voters.rs#L32 126 336 : if( !existed ) { 127 : /* insert cannot fail because !existed */ 128 34 : if( FD_UNLIKELY( !fd_vote_authorized_voters_pool_free( self->pool ) ) ) { 129 0 : FD_LOG_CRIT(( "invariant violation: max authorized voter count of vote account exceeded" )); 130 0 : } 131 34 : fd_vote_authorized_voter_t * ele = fd_vote_authorized_voters_pool_ele_acquire( self->pool ); 132 34 : ele->epoch = epoch; 133 34 : ele->pubkey = res->pubkey; 134 34 : ele->prio = (ulong)&res->pubkey; 135 : // https://github.com/anza-xyz/agave/blob/v2.0.1/sdk/program/src/vote/authorized_voters.rs#L33 136 34 : fd_vote_authorized_voters_treap_ele_insert( self->treap, ele, self->pool ); 137 34 : return ele; 138 34 : } 139 302 : return res; 140 336 : } 141 : 142 : int 143 : fd_authorized_voters_get_and_update_authorized_voter( fd_vote_state_versioned_t * self, 144 : ulong current_epoch, 145 307 : fd_pubkey_t ** pubkey /* out */ ) { 146 307 : switch( self->discriminant ) { 147 8 : case fd_vote_state_versioned_enum_v3: 148 8 : return fd_vote_state_v3_get_and_update_authorized_voter( &self->inner.v3, current_epoch, pubkey ); 149 299 : case fd_vote_state_versioned_enum_v4: 150 299 : return fd_vote_state_v4_get_and_update_authorized_voter( &self->inner.v4, current_epoch, pubkey ); 151 0 : default: 152 0 : FD_LOG_CRIT(( "unsupported vote state versioned discriminant: %u", self->discriminant )); 153 307 : } 154 307 : }