Line data Source code
1 : #ifndef HEADER_fd_src_choreo_votor_test_ag_cert_builder_h
2 : #define HEADER_fd_src_choreo_votor_test_ag_cert_builder_h
3 :
4 : /* Certificates are built incrementally in ag_slot_state.c as votes
5 : arrive. These rebuild one from a complete vote list, which tests
6 : need to get a cert in isolation; they are not part of the ag_cert
7 : API. */
8 :
9 : #include "ag_cert.h"
10 : #include "ag_epoch_info.h"
11 : #include "ag_vote.h"
12 :
13 : /* epoch_info_build fills epoch_info from an already ranked validator
14 : list. Production ranks in the votor tile (rank_voters). */
15 :
16 : static inline void
17 : epoch_info_build( ag_epoch_info_t * epoch_info,
18 : ag_validator_info_t const * validators,
19 279 : ulong validator_cnt ) {
20 279 : epoch_info->total_stake = 0UL;
21 4704 : for( ulong i=0UL; i<validator_cnt; i++ ) {
22 4425 : FD_TEST( validators[i].id==i );
23 4425 : epoch_info->validators[i] = validators[i];
24 4425 : epoch_info->pubkeys[i] = validators[i].bls_key;
25 4425 : epoch_info->total_stake += validators[i].stake;
26 4425 : }
27 279 : epoch_info->validator_cnt = validator_cnt;
28 279 : }
29 :
30 : /* sec_sign_fn is the fd_bls_sign_fn of a test that holds the secret
31 : key in memory; ctx points to the fd_bls_sec_t. */
32 :
33 : static inline void
34 : sec_sign_fn( void * ctx,
35 : fd_bls_sig_t * sig,
36 : uchar const * msg,
37 8670 : ulong msg_sz ) {
38 8670 : fd_bls_sec_sign( (fd_bls_sec_t const *)ctx, msg, msg_sz, sig );
39 8670 : }
40 :
41 : static inline void
42 : agg_add( fd_bls_agg_t * agg,
43 : ulong rank,
44 4020 : fd_bls_sig_t const * sig ) {
45 4020 : fd_bls_set_insert( agg->set, rank );
46 4020 : blst_p2_add_or_double( &agg->sig, &agg->sig, sig );
47 4020 : }
48 :
49 : static inline int
50 234 : agg_is_identity( fd_bls_agg_t const * agg ) {
51 234 : return !!blst_p2_is_inf( &agg->sig );
52 234 : }
53 :
54 : static inline ag_cert_t
55 : cert_build_final( ag_vote_final_t const * votes, ulong vote_cnt, ag_epoch_info_t const * epoch_info );
56 : static inline ag_cert_t
57 : cert_build_fast_final( ag_vote_notar_t const * votes, ulong vote_cnt, ag_epoch_info_t const * epoch_info );
58 : static inline ag_cert_t
59 : cert_build_notar( ag_vote_notar_t const * votes, ulong vote_cnt, ag_epoch_info_t const * epoch_info );
60 : static inline ag_cert_t
61 : cert_build_notar_fallback( ag_vote_notar_t const * votes, ulong vote_cnt, ag_vote_notar_fallback_t const * fallback_votes, ulong fallback_vote_cnt, ag_epoch_info_t const * epoch_info );
62 : static inline ag_cert_t
63 : cert_build_skip( ag_vote_skip_t const * votes, ulong vote_cnt, ag_vote_skip_fallback_t const * fallback_votes, ulong fallback_vote_cnt, ag_epoch_info_t const * epoch_info );
64 :
65 : static inline ag_cert_t
66 : cert_build_final( ag_vote_final_t const * votes,
67 : ulong vote_cnt,
68 24 : ag_epoch_info_t const * epoch_info ) {
69 24 : ag_validator_info_t const * validators = ag_epoch_info_validators( epoch_info );
70 24 : FD_TEST( vote_cnt>0UL );
71 24 : ulong slot = votes[0].slot;
72 24 : ulong stake = 0UL;
73 462 : for( ulong i=0UL; i<vote_cnt; i++ ) {
74 438 : FD_TEST( votes[i].slot==slot );
75 438 : stake += validators[ votes[i].rank ].stake;
76 438 : }
77 24 : ag_cert_final_t cert;
78 24 : cert.slot = slot; cert.stake = stake; cert.shred_version = votes[0].shred_version;
79 24 : memset( &cert.agg, 0, sizeof(fd_bls_agg_t) );
80 462 : for( ulong i=0UL; i<vote_cnt; i++ ) agg_add( &cert.agg, votes[i].rank, &votes[i].sig );
81 24 : return (ag_cert_t){ .kind = AG_CERT_KIND_FINAL, .final = cert };
82 24 : }
83 :
84 : static inline ag_cert_t
85 : cert_build_fast_final( ag_vote_notar_t const * votes,
86 : ulong vote_cnt,
87 102 : ag_epoch_info_t const * epoch_info ) {
88 102 : ag_cert_notar_t notar = cert_build_notar( votes, vote_cnt, epoch_info ).notar;
89 102 : ag_cert_fast_final_t cert;
90 102 : cert.slot = notar.slot; cert.stake = notar.stake; cert.agg = notar.agg; cert.shred_version = notar.shred_version;
91 102 : memcpy( cert.block_hash, notar.block_hash, sizeof(ag_block_hash_t) );
92 102 : return (ag_cert_t){ .kind = AG_CERT_KIND_FAST_FINAL, .fast_final = cert };
93 102 : }
94 :
95 : static inline ag_cert_t
96 : cert_build_notar( ag_vote_notar_t const * votes,
97 : ulong vote_cnt,
98 150 : ag_epoch_info_t const * epoch_info ) {
99 150 : ag_validator_info_t const * validators = ag_epoch_info_validators( epoch_info );
100 150 : FD_TEST( vote_cnt>0UL );
101 150 : ulong slot = votes[0].slot;
102 150 : ulong stake = 0UL;
103 150 : ag_block_hash_t block_hash;
104 150 : memcpy( block_hash, votes[0].block_hash, sizeof(ag_block_hash_t) );
105 2142 : for( ulong i=0UL; i<vote_cnt; i++ ) {
106 1992 : FD_TEST( votes[i].slot==slot );
107 1992 : FD_TEST( !memcmp( votes[i].block_hash, block_hash, sizeof(ag_block_hash_t) ) );
108 1992 : stake += validators[ votes[i].rank ].stake;
109 1992 : }
110 150 : ag_cert_notar_t cert;
111 150 : cert.slot = slot; cert.stake = stake; cert.shred_version = votes[0].shred_version;
112 150 : memcpy( cert.block_hash, block_hash, sizeof(ag_block_hash_t) );
113 150 : memset( &cert.agg, 0, sizeof(fd_bls_agg_t) );
114 2142 : for( ulong i=0UL; i<vote_cnt; i++ ) agg_add( &cert.agg, votes[i].rank, &votes[i].sig );
115 150 : return (ag_cert_t){ .kind = AG_CERT_KIND_NOTAR, .notar = cert };
116 150 : }
117 :
118 : static inline ag_cert_t
119 : cert_build_notar_fallback( ag_vote_notar_t const * votes,
120 : ulong vote_cnt,
121 : ag_vote_notar_fallback_t const * fallback_votes,
122 : ulong fallback_vote_cnt,
123 42 : ag_epoch_info_t const * epoch_info ) {
124 42 : ag_validator_info_t const * validators = ag_epoch_info_validators( epoch_info );
125 42 : FD_TEST( vote_cnt>0UL || fallback_vote_cnt>0UL );
126 42 : ulong slot;
127 42 : ag_block_hash_t block_hash;
128 42 : if( vote_cnt>0UL ) { slot = votes[0].slot; memcpy( block_hash, votes[0].block_hash, sizeof(ag_block_hash_t) ); }
129 6 : else { slot = fallback_votes[0].slot; memcpy( block_hash, fallback_votes[0].block_hash, sizeof(ag_block_hash_t) ); }
130 :
131 42 : ulong stake = 0UL;
132 222 : for( ulong i=0UL; i<vote_cnt; i++ ) {
133 180 : FD_TEST( votes[i].slot==slot );
134 180 : FD_TEST( !memcmp( votes[i].block_hash, block_hash, sizeof(ag_block_hash_t) ) );
135 180 : stake += validators[ votes[i].rank ].stake;
136 180 : }
137 42 : ulong stake_fallback = 0UL;
138 468 : for( ulong i=0UL; i<fallback_vote_cnt; i++ ) {
139 426 : FD_TEST( fallback_votes[i].slot==slot );
140 426 : FD_TEST( !memcmp( fallback_votes[i].block_hash, block_hash, sizeof(ag_block_hash_t) ) );
141 426 : stake_fallback += validators[ fallback_votes[i].rank ].stake;
142 426 : }
143 :
144 42 : ag_cert_notar_fallback_t cert;
145 42 : cert.slot = slot; cert.shred_version = vote_cnt>0UL ? votes[0].shred_version : fallback_votes[0].shred_version;
146 42 : memcpy( cert.block_hash, block_hash, sizeof(ag_block_hash_t) );
147 42 : memset( &cert.agg_notar, 0, sizeof(fd_bls_agg_t) );
148 222 : for( ulong i=0UL; i<vote_cnt; i++ ) agg_add( &cert.agg_notar, votes[i].rank, &votes[i].sig );
149 42 : if( FD_UNLIKELY( agg_is_identity( &cert.agg_notar ) ) ) {
150 6 : memset( &cert.agg_notar, 0, sizeof(fd_bls_agg_t) );
151 6 : stake = 0UL;
152 6 : }
153 42 : memset( &cert.agg_notar_fallback, 0, sizeof(fd_bls_agg_t) );
154 468 : for( ulong i=0UL; i<fallback_vote_cnt; i++ ) agg_add( &cert.agg_notar_fallback, fallback_votes[i].rank, &fallback_votes[i].sig );
155 42 : if( FD_UNLIKELY( agg_is_identity( &cert.agg_notar_fallback ) ) ) {
156 9 : memset( &cert.agg_notar_fallback, 0, sizeof(fd_bls_agg_t) );
157 9 : stake_fallback = 0UL;
158 9 : }
159 42 : cert.stake = stake + stake_fallback;
160 42 : return (ag_cert_t){ .kind = AG_CERT_KIND_NOTAR_FALLBACK, .notar_fallback = cert };
161 42 : }
162 :
163 : static inline ag_cert_t
164 : cert_build_skip( ag_vote_skip_t const * votes,
165 : ulong vote_cnt,
166 : ag_vote_skip_fallback_t const * fallback_votes,
167 : ulong fallback_vote_cnt,
168 75 : ag_epoch_info_t const * epoch_info ) {
169 75 : ag_validator_info_t const * validators = ag_epoch_info_validators( epoch_info );
170 75 : FD_TEST( vote_cnt>0UL || fallback_vote_cnt>0UL );
171 75 : ulong slot = vote_cnt>0UL ? votes[0].slot : fallback_votes[0].slot;
172 :
173 75 : ulong stake = 0UL;
174 1002 : for( ulong i=0UL; i<vote_cnt; i++ ) {
175 927 : FD_TEST( votes[i].slot==slot );
176 927 : stake += validators[ votes[i].rank ].stake;
177 927 : }
178 75 : ulong stake_fallback = 0UL;
179 132 : for( ulong i=0UL; i<fallback_vote_cnt; i++ ) {
180 57 : FD_TEST( fallback_votes[i].slot==slot );
181 57 : stake_fallback += validators[ fallback_votes[i].rank ].stake;
182 57 : }
183 :
184 75 : ag_cert_skip_t cert;
185 75 : cert.slot = slot; cert.shred_version = vote_cnt>0UL ? votes[0].shred_version : fallback_votes[0].shred_version;
186 75 : memset( &cert.agg_skip, 0, sizeof(fd_bls_agg_t) );
187 1002 : for( ulong i=0UL; i<vote_cnt; i++ ) agg_add( &cert.agg_skip, votes[i].rank, &votes[i].sig );
188 75 : if( FD_UNLIKELY( agg_is_identity( &cert.agg_skip ) ) ) {
189 0 : memset( &cert.agg_skip, 0, sizeof(fd_bls_agg_t) );
190 0 : stake = 0UL;
191 0 : }
192 75 : memset( &cert.agg_skip_fallback, 0, sizeof(fd_bls_agg_t) );
193 132 : for( ulong i=0UL; i<fallback_vote_cnt; i++ ) agg_add( &cert.agg_skip_fallback, fallback_votes[i].rank, &fallback_votes[i].sig );
194 75 : if( FD_UNLIKELY( agg_is_identity( &cert.agg_skip_fallback ) ) ) {
195 60 : memset( &cert.agg_skip_fallback, 0, sizeof(fd_bls_agg_t) );
196 60 : stake_fallback = 0UL;
197 60 : }
198 75 : cert.stake = stake + stake_fallback;
199 75 : return (ag_cert_t){ .kind = AG_CERT_KIND_SKIP, .skip = cert };
200 75 : }
201 :
202 : #endif
|