Line data Source code
1 : #include "ag_cert_serde.h"
2 :
3 0 : #define FAIL( cond, err ) do { if( FD_UNLIKELY( cond ) ) return AG_CERT_DE_ERR_##err; } while( 0 )
4 :
5 : ulong
6 : ag_cert_ser( ag_cert_t const * self,
7 0 : uchar buf[ static AG_CERT_SER_MAX ] ) {
8 0 : fd_bls_agg_t const * agg;
9 0 : fd_bls_agg_t const * agg2 = NULL;
10 0 : uchar const * hash = NULL;
11 0 : ulong slot;
12 0 : switch( self->kind ) {
13 0 : case AG_CERT_KIND_FINAL:
14 0 : slot = self->final.slot;
15 0 : agg = &self->final.agg;
16 0 : break;
17 0 : case AG_CERT_KIND_FAST_FINAL:
18 0 : slot = self->fast_final.slot;
19 0 : agg = &self->fast_final.agg;
20 0 : hash = self->fast_final.block_hash;
21 0 : break;
22 0 : case AG_CERT_KIND_NOTAR:
23 0 : slot = self->notar.slot;
24 0 : agg = &self->notar.agg;
25 0 : hash = self->notar.block_hash;
26 0 : break;
27 0 : case AG_CERT_KIND_NOTAR_FALLBACK:
28 0 : slot = self->notar_fallback.slot;
29 0 : agg = &self->notar_fallback.agg_notar;
30 0 : agg2 = &self->notar_fallback.agg_notar_fallback;
31 0 : hash = self->notar_fallback.block_hash;
32 0 : break;
33 0 : case AG_CERT_KIND_SKIP:
34 0 : slot = self->skip.slot;
35 0 : agg = &self->skip.agg_skip;
36 0 : agg2 = &self->skip.agg_skip_fallback;
37 0 : break;
38 0 : default:
39 0 : FD_LOG_ERR(( "unimplemented" ));
40 0 : }
41 :
42 0 : if( FD_UNLIKELY( agg2 && !fd_bls_set_cnt( agg2->set ) ) ) agg2 = NULL; /* check empty */
43 :
44 0 : blst_p2 sig = agg->sig;
45 0 : if( FD_UNLIKELY( agg2 ) ) blst_p2_add_or_double( &sig, &sig, &agg2->sig );
46 :
47 0 : ag_cert_serde_t cert = {
48 0 : .version = (uchar)1,
49 0 : .tag = (uchar)( self->kind+AG_CERT_SERDE_TAG_FINAL ),
50 0 : .slot = slot,
51 0 : .block_id = hash,
52 0 : .bitmap_sz = agg2 ? ag_bls_agg_pair_ser_sz( agg, agg2 ) : ag_bls_agg_ser_sz( agg ),
53 0 : .shred_version = ag_cert_shred_version( self ),
54 0 : };
55 :
56 0 : ulong off = 0UL;
57 0 : buf[ off ] = cert.version; off += sizeof(uchar);
58 0 : buf[ off ] = cert.tag; off += sizeof(uchar);
59 0 : FD_STORE( ulong, buf+off, cert.slot ); off += sizeof(ulong);
60 0 : if( FD_LIKELY( cert.block_id ) ) { memcpy( buf+off, cert.block_id, sizeof(ag_block_hash_t) ); off += sizeof(ag_block_hash_t); }
61 0 : fd_bls_sig_t sig_aff[1];
62 0 : blst_p2_to_affine( sig_aff, &sig );
63 0 : blst_p2_affine_serialize( buf+off, sig_aff ); off += FD_BLS_SIG_SZ;
64 0 : FD_STORE( ulong, buf+off, cert.bitmap_sz ); off += sizeof(ulong);
65 0 : off += agg2 ? ag_bls_agg_pair_ser( agg, agg2, buf+off ) : ag_bls_agg_ser( agg, buf+off );
66 0 : FD_STORE( ushort, buf+off, cert.shred_version ); off += sizeof(ushort);
67 :
68 0 : return off;
69 0 : }
70 :
71 : int
72 : ag_cert_de( ag_cert_t * self,
73 : ulong * bit_cnt,
74 : uchar const * buf,
75 0 : ulong buf_sz ) {
76 0 : FAIL( buf_sz<2 /* version + tag */, SZ );
77 :
78 0 : ag_cert_serde_t cert; ulong off = 0UL;
79 0 : cert.version = buf[ off ]; off += sizeof(uchar);
80 0 : cert.tag = buf[ off ]; off += sizeof(uchar);
81 0 : FAIL( cert.version!=1, INVAL );
82 :
83 0 : fd_memset( self, 0, sizeof(ag_cert_t) );
84 0 : self->kind = (uint)cert.tag - AG_CERT_SERDE_TAG_FINAL;
85 :
86 0 : int has_block_id = self->kind==AG_CERT_KIND_FAST_FINAL || self->kind==AG_CERT_KIND_NOTAR || self->kind==AG_CERT_KIND_NOTAR_FALLBACK;
87 0 : ulong hdr_sz = AG_CERT_SER_HDR_SZ( has_block_id );
88 0 : FAIL( buf_sz<hdr_sz, SZ );
89 :
90 0 : cert.slot = FD_LOAD( ulong, buf+off ); off += sizeof(ulong);
91 0 : cert.block_id = NULL;
92 0 : if( FD_LIKELY( has_block_id ) ) {
93 0 : cert.block_id = buf+off; off += sizeof(ag_block_hash_t);
94 0 : }
95 0 : cert.signature = buf+off; off += FD_BLS_SIG_SZ;
96 :
97 0 : blst_p2 sig[1];
98 0 : fd_bls_sig_t sig_aff[1];
99 0 : FAIL( blst_p2_deserialize( sig_aff, cert.signature )!=BLST_SUCCESS, INVAL );
100 0 : blst_p2_from_affine( sig, sig_aff );
101 0 : cert.bitmap_sz = FD_LOAD( ulong, buf+off ); off += sizeof(ulong);
102 0 : cert.bitmap = buf+off;
103 0 : FD_TEST( off==hdr_sz );
104 :
105 0 : ulong rem = buf_sz - hdr_sz;
106 0 : FAIL( cert.bitmap_sz>rem || rem-cert.bitmap_sz<sizeof(ushort), SZ ); /* too few, trailing bytes are ignored */
107 :
108 0 : cert.shred_version = FD_LOAD( ushort, cert.bitmap+cert.bitmap_sz );
109 :
110 0 : int err;
111 0 : switch( self->kind ) {
112 0 : case AG_CERT_KIND_FINAL:
113 0 : self->final.slot = cert.slot;
114 0 : self->final.shred_version = cert.shred_version;
115 0 : if( FD_UNLIKELY( err = ag_bls_agg_de( &self->final.agg, bit_cnt, cert.bitmap, cert.bitmap_sz ) ) ) return err;
116 0 : self->final.agg.sig = *sig;
117 0 : break;
118 0 : case AG_CERT_KIND_FAST_FINAL:
119 0 : self->fast_final.slot = cert.slot;
120 0 : self->fast_final.shred_version = cert.shred_version;
121 0 : memcpy( self->fast_final.block_hash, cert.block_id, sizeof(ag_block_hash_t) );
122 0 : if( FD_UNLIKELY( err = ag_bls_agg_de( &self->fast_final.agg, bit_cnt, cert.bitmap, cert.bitmap_sz ) ) ) return err;
123 0 : self->fast_final.agg.sig = *sig;
124 0 : break;
125 0 : case AG_CERT_KIND_NOTAR:
126 0 : self->notar.slot = cert.slot;
127 0 : self->notar.shred_version = cert.shred_version;
128 0 : memcpy( self->notar.block_hash, cert.block_id, sizeof(ag_block_hash_t) );
129 0 : if( FD_UNLIKELY( err = ag_bls_agg_de( &self->notar.agg, bit_cnt, cert.bitmap, cert.bitmap_sz ) ) ) return err;
130 0 : self->notar.agg.sig = *sig;
131 0 : break;
132 0 : case AG_CERT_KIND_NOTAR_FALLBACK: {
133 0 : fd_bls_agg_t * agg = &self->notar_fallback.agg_notar;
134 0 : fd_bls_agg_t * agg2 = &self->notar_fallback.agg_notar_fallback;
135 0 : self->notar_fallback.slot = cert.slot;
136 0 : self->notar_fallback.shred_version = cert.shred_version;
137 0 : memcpy( self->notar_fallback.block_hash, cert.block_id, sizeof(ag_block_hash_t) );
138 0 : if( FD_UNLIKELY( err = ag_bls_agg_pair_de( agg, agg2, bit_cnt, cert.bitmap, cert.bitmap_sz ) ) ) return err;
139 0 : agg->sig = *sig;
140 0 : break;
141 0 : }
142 0 : case AG_CERT_KIND_SKIP: {
143 0 : fd_bls_agg_t * agg = &self->skip.agg_skip;
144 0 : fd_bls_agg_t * agg2 = &self->skip.agg_skip_fallback;
145 0 : self->skip.slot = cert.slot;
146 0 : self->skip.shred_version = cert.shred_version;
147 0 : if( FD_UNLIKELY( err = ag_bls_agg_pair_de( agg, agg2, bit_cnt, cert.bitmap, cert.bitmap_sz ) ) ) return err;
148 0 : agg->sig = *sig;
149 0 : break;
150 0 : }
151 0 : default:
152 0 : return AG_CERT_DE_ERR_INVAL;
153 0 : }
154 :
155 0 : return AG_CERT_DE_SUCCESS;
156 0 : }
|