6
6
#define SORT_BEFORE (a ,b ) (memcmp( (a).pubkey.uc, (b).pubkey.uc, 32UL )<0)
7
7
#include "../../util/tmpl/fd_sort.c"
8
8
9
+ #define SORT_NAME sort_weights_by_stake_id
10
+ #define SORT_KEY_T fd_stake_weight_t
11
+ #define SORT_BEFORE (a ,b ) ((a).stake > (b).stake ? 1 : ((a).stake < (b).stake ? 0 : memcmp( (a).key.uc, (b).key.uc, 32UL )>0))
12
+ #include "../../util/tmpl/fd_sort.c"
13
+
14
+ #define SORT_NAME sort_weights_by_id
15
+ #define SORT_KEY_T fd_stake_weight_t
16
+ #define SORT_BEFORE (a ,b ) (memcmp( (a).key.uc, (b).key.uc, 32UL )>0)
17
+ #include "../../util/tmpl/fd_sort.c"
18
+
9
19
/* We don't have or need real contact info for the local validator, but
10
20
we want to be able to distinguish it from staked nodes with no
11
21
contact info. */
@@ -16,20 +26,21 @@ fd_stake_ci_new( void * mem,
16
26
fd_pubkey_t const * identity_key ) {
17
27
fd_stake_ci_t * info = (fd_stake_ci_t * )mem ;
18
28
19
- fd_stake_weight_t dummy_stakes [ 1 ] = {{ .key = {{0 }}, .stake = 1UL }};
29
+ fd_vote_stake_weight_t dummy_stakes [ 1 ] = {{ .vote_key = {{ 0 }}, . id_key = {{0 }}, .stake = 1UL }};
20
30
fd_shred_dest_weighted_t dummy_dests [ 1 ] = {{ .pubkey = * identity_key , .ip4 = SELF_DUMMY_IP }};
21
31
22
32
/* Initialize first 2 to satisfy invariants */
23
- info -> stake_weight [ 0 ] = dummy_stakes [ 0 ];
33
+ info -> vote_stake_weight [ 0 ] = dummy_stakes [ 0 ];
24
34
info -> shred_dest [ 0 ] = dummy_dests [ 0 ];
25
35
for ( ulong i = 0UL ; i < 2UL ; i ++ ) {
26
36
fd_per_epoch_info_t * ei = info -> epoch_info + i ;
27
37
ei -> epoch = i ;
28
38
ei -> start_slot = 0UL ;
29
39
ei -> slot_cnt = 0UL ;
30
40
ei -> excluded_stake = 0UL ;
41
+ ei -> vote_keyed_lsched = 0UL ;
31
42
32
- ei -> lsched = fd_epoch_leaders_join ( fd_epoch_leaders_new ( ei -> _lsched , 0UL , 0UL , 1UL , 1UL , info -> stake_weight , 0UL ) );
43
+ ei -> lsched = fd_epoch_leaders_join ( fd_epoch_leaders_new ( ei -> _lsched , 0UL , 0UL , 1UL , 1UL , info -> vote_stake_weight , 0UL , ei -> vote_keyed_lsched ) );
33
44
ei -> sdest = fd_shred_dest_join ( fd_shred_dest_new ( ei -> _sdest , info -> shred_dest , 1UL , ei -> lsched , identity_key , 0UL ) );
34
45
}
35
46
info -> identity_key [ 0 ] = * identity_key ;
@@ -55,8 +66,9 @@ fd_stake_ci_stake_msg_init( fd_stake_ci_t * info,
55
66
info -> scratch -> slot_cnt = msg -> slot_cnt ;
56
67
info -> scratch -> staked_cnt = msg -> staked_cnt ;
57
68
info -> scratch -> excluded_stake = msg -> excluded_stake ;
69
+ info -> scratch -> vote_keyed_lsched = msg -> vote_keyed_lsched ;
58
70
59
- fd_memcpy ( info -> stake_weight , msg -> weights , msg -> staked_cnt * sizeof (fd_stake_weight_t ) );
71
+ fd_memcpy ( info -> vote_stake_weight , msg -> weights , msg -> staked_cnt * sizeof (fd_vote_stake_weight_t ) );
60
72
}
61
73
62
74
static inline void
@@ -78,6 +90,40 @@ log_summary( char const * msg, fd_stake_ci_t * info ) {
78
90
#endif
79
91
}
80
92
93
+ ulong
94
+ compute_id_weights_from_vote_weights ( fd_stake_weight_t * stake_weight ,
95
+ fd_vote_stake_weight_t const * vote_stake_weight ,
96
+ ulong staked_cnt ) {
97
+ /* Copy from input message [(vote, id, stake)] into old format [(id, stake)]. */
98
+ for ( ulong i = 0UL ; i < staked_cnt ; i ++ ) {
99
+ memcpy ( stake_weight [ i ].key .uc , vote_stake_weight [ i ].id_key .uc , sizeof (fd_pubkey_t ) );
100
+ stake_weight [ i ].stake = vote_stake_weight [ i ].stake ;
101
+ }
102
+
103
+ /* Sort [(id, stake)] by id, so we can dedup */
104
+ sort_weights_by_id_inplace ( stake_weight , staked_cnt );
105
+
106
+ /* Dedup entries, aggregating stake */
107
+ ulong j = 0UL ;
108
+ for ( ulong i = 1UL ; i < staked_cnt ; i ++ ) {
109
+ fd_pubkey_t * pre = & stake_weight [ j ].key ;
110
+ fd_pubkey_t * cur = & stake_weight [ i ].key ;
111
+ if ( 0 == memcmp ( pre , cur , sizeof (fd_pubkey_t ) ) ) {
112
+ stake_weight [ j ].stake += stake_weight [ i ].stake ;
113
+ } else {
114
+ ++ j ;
115
+ stake_weight [ j ].stake = stake_weight [ i ].stake ;
116
+ memcpy ( stake_weight [ j ].key .uc , stake_weight [ i ].key .uc , sizeof (fd_pubkey_t ) );
117
+ }
118
+ }
119
+ ulong staked_cnt_by_id = fd_ulong_min ( staked_cnt , j + 1 );
120
+
121
+ /* Sort [(id, stake)] by stake then id, as expected */
122
+ sort_weights_by_stake_id_inplace ( stake_weight , staked_cnt_by_id );
123
+
124
+ return staked_cnt_by_id ;
125
+ }
126
+
81
127
#define SET_NAME unhit_set
82
128
#define SET_MAX MAX_SHRED_DESTS
83
129
#include "../../util/tmpl/fd_set.c"
@@ -90,6 +136,8 @@ fd_stake_ci_stake_msg_fini( fd_stake_ci_t * info ) {
90
136
and whatever contact info we previously knew. */
91
137
ulong epoch = info -> scratch -> epoch ;
92
138
ulong staked_cnt = info -> scratch -> staked_cnt ;
139
+ ulong unchanged_staked_cnt = info -> scratch -> staked_cnt ;
140
+ ulong vote_keyed_lsched = info -> scratch -> vote_keyed_lsched ;
93
141
94
142
/* Just take the first one arbitrarily because they both have the same
95
143
contact info, other than possibly some staked nodes with no contact
@@ -106,6 +154,8 @@ fd_stake_ci_stake_msg_fini( fd_stake_ci_t * info ) {
106
154
unhit_set_t * unhit = unhit_set_join ( unhit_set_new ( _unhit ) );
107
155
unhit_set_full ( unhit );
108
156
157
+ staked_cnt = compute_id_weights_from_vote_weights ( info -> stake_weight , info -> vote_stake_weight , staked_cnt );
158
+
109
159
for ( ulong i = 0UL ; i < staked_cnt ; i ++ ) {
110
160
fd_shred_dest_idx_t old_idx = fd_shred_dest_pubkey_to_idx ( existing_sdest , & (info -> stake_weight [ i ].key ) );
111
161
fd_shred_dest_weighted_t * in_prev = fd_shred_dest_idx_to_dest ( existing_sdest , old_idx );
@@ -159,11 +209,12 @@ fd_stake_ci_stake_msg_fini( fd_stake_ci_t * info ) {
159
209
new_ei -> start_slot = info -> scratch -> start_slot ;
160
210
new_ei -> slot_cnt = info -> scratch -> slot_cnt ;
161
211
new_ei -> excluded_stake = excluded_stake ;
212
+ new_ei -> vote_keyed_lsched = vote_keyed_lsched ;
162
213
163
214
new_ei -> lsched = fd_epoch_leaders_join ( fd_epoch_leaders_new ( new_ei -> _lsched , epoch , new_ei -> start_slot , new_ei -> slot_cnt ,
164
- staked_cnt , info -> stake_weight , excluded_stake ) );
215
+ unchanged_staked_cnt , info -> vote_stake_weight , excluded_stake , vote_keyed_lsched ) );
165
216
new_ei -> sdest = fd_shred_dest_join ( fd_shred_dest_new ( new_ei -> _sdest , info -> shred_dest , j ,
166
- new_ei -> lsched , info -> identity_key , excluded_stake ) );
217
+ new_ei -> lsched , info -> identity_key , excluded_stake ) );
167
218
log_summary ( "stake update" , info );
168
219
}
169
220
0 commit comments