Line data Source code
1 : #include "fd_cert_serde.h"
2 :
3 0 : #define FAIL( cond, err ) do { if( FD_UNLIKELY( cond ) ) return FD_CERT_DE_ERR_##err; } while( 0 )
4 :
5 : ulong
6 : fd_cert_ser( fd_cert_t const * self,
7 0 : uchar buf[ static FD_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 FD_CERT_KIND_FINAL:
14 0 : slot = self->final.slot;
15 0 : agg = &self->final.agg;
16 0 : break;
17 0 : case FD_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.uc;
21 0 : break;
22 0 : case FD_CERT_KIND_NOTAR:
23 0 : slot = self->notar.slot;
24 0 : agg = &self->notar.agg;
25 0 : hash = self->notar.block_hash.uc;
26 0 : break;
27 0 : case FD_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.uc;
32 0 : break;
33 0 : case FD_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 : fd_bls_sig_t sig = agg->sig;
45 0 : if( FD_UNLIKELY( agg2 ) ) fd_bls_sig_add( &sig, &sig, &agg2->sig );
46 :
47 0 : fd_cert_serde_t cert = {
48 0 : .version = (uchar)1,
49 0 : .tag = (uchar)( self->kind+FD_CERT_SERDE_TAG_FINAL ),
50 0 : .slot = slot,
51 0 : .block_id = hash,
52 0 : .bitmap_sz = agg2 ? fd_bls_agg_pair_ser_sz( agg, agg2 ) : fd_bls_agg_ser_sz( agg ),
53 0 : .shred_version = fd_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(fd_block_hash_t) ); off += sizeof(fd_block_hash_t); }
61 0 : fd_bls_sig_ser( &sig, buf+off ); off += FD_BLS_SIG_SZ;
62 0 : FD_STORE( ulong, buf+off, cert.bitmap_sz ); off += sizeof(ulong);
63 0 : off += agg2 ? fd_bls_agg_pair_ser( agg, agg2, buf+off ) : fd_bls_agg_ser( agg, buf+off );
64 0 : FD_STORE( ushort, buf+off, cert.shred_version ); off += sizeof(ushort);
65 :
66 0 : return off;
67 0 : }
68 :
69 : int
70 : fd_cert_de( fd_cert_t * self,
71 : ulong * bit_cnt,
72 : uchar const * buf,
73 0 : ulong buf_sz ) {
74 0 : FAIL( buf_sz<2 /* version + tag */, SZ );
75 :
76 0 : fd_cert_serde_t cert; ulong off = 0UL;
77 0 : cert.version = buf[ off ]; off += sizeof(uchar);
78 0 : cert.tag = buf[ off ]; off += sizeof(uchar);
79 0 : FAIL( cert.version!=1, INVAL );
80 :
81 0 : fd_memset( self, 0, sizeof(fd_cert_t) );
82 0 : self->kind = (uint)cert.tag - FD_CERT_SERDE_TAG_FINAL;
83 :
84 0 : int has_block_id = self->kind==FD_CERT_KIND_FAST_FINAL || self->kind==FD_CERT_KIND_NOTAR || self->kind==FD_CERT_KIND_NOTAR_FALLBACK;
85 0 : ulong hdr_sz = FD_CERT_SER_HDR_SZ( has_block_id );
86 0 : FAIL( buf_sz<hdr_sz, SZ );
87 :
88 0 : cert.slot = FD_LOAD( ulong, buf+off ); off += sizeof(ulong);
89 0 : cert.block_id = NULL;
90 0 : if( FD_LIKELY( has_block_id ) ) {
91 0 : cert.block_id = buf+off; off += sizeof(fd_block_hash_t);
92 0 : }
93 0 : cert.signature = buf+off; off += FD_BLS_SIG_SZ;
94 :
95 0 : fd_bls_sig_t sig[1];
96 0 : FAIL( fd_bls_sig_de_unchecked( sig, cert.signature ), INVAL ); /* deserialize now, defer the g2 subgroup check to verify */
97 0 : cert.bitmap_sz = FD_LOAD( ulong, buf+off ); off += sizeof(ulong);
98 0 : cert.bitmap = buf+off;
99 0 : FD_TEST( off==hdr_sz );
100 :
101 0 : ulong rem = buf_sz - hdr_sz;
102 0 : FAIL( cert.bitmap_sz>rem || rem-cert.bitmap_sz<sizeof(ushort), SZ ); /* too few, trailing bytes are ignored */
103 :
104 0 : cert.shred_version = FD_LOAD( ushort, cert.bitmap+cert.bitmap_sz );
105 :
106 0 : int err;
107 0 : switch( self->kind ) {
108 0 : case FD_CERT_KIND_FINAL:
109 0 : self->final.slot = cert.slot;
110 0 : self->final.shred_version = cert.shred_version;
111 0 : if( FD_UNLIKELY( err = fd_bls_agg_de( &self->final.agg, bit_cnt, cert.bitmap, cert.bitmap_sz ) ) ) return err;
112 0 : self->final.agg.sig = *sig;
113 0 : break;
114 0 : case FD_CERT_KIND_FAST_FINAL:
115 0 : self->fast_final.slot = cert.slot;
116 0 : self->fast_final.shred_version = cert.shred_version;
117 0 : memcpy( &self->fast_final.block_hash, cert.block_id, sizeof(fd_block_hash_t) );
118 0 : if( FD_UNLIKELY( err = fd_bls_agg_de( &self->fast_final.agg, bit_cnt, cert.bitmap, cert.bitmap_sz ) ) ) return err;
119 0 : self->fast_final.agg.sig = *sig;
120 0 : break;
121 0 : case FD_CERT_KIND_NOTAR:
122 0 : self->notar.slot = cert.slot;
123 0 : self->notar.shred_version = cert.shred_version;
124 0 : memcpy( &self->notar.block_hash, cert.block_id, sizeof(fd_block_hash_t) );
125 0 : if( FD_UNLIKELY( err = fd_bls_agg_de( &self->notar.agg, bit_cnt, cert.bitmap, cert.bitmap_sz ) ) ) return err;
126 0 : self->notar.agg.sig = *sig;
127 0 : break;
128 0 : case FD_CERT_KIND_NOTAR_FALLBACK: {
129 0 : fd_bls_agg_t * agg = &self->notar_fallback.agg_notar;
130 0 : fd_bls_agg_t * agg2 = &self->notar_fallback.agg_notar_fallback;
131 0 : self->notar_fallback.slot = cert.slot;
132 0 : self->notar_fallback.shred_version = cert.shred_version;
133 0 : memcpy( &self->notar_fallback.block_hash, cert.block_id, sizeof(fd_block_hash_t) );
134 0 : if( FD_UNLIKELY( err = fd_bls_agg_pair_de( agg, agg2, bit_cnt, cert.bitmap, cert.bitmap_sz ) ) ) return err;
135 0 : agg->sig = *sig;
136 0 : break;
137 0 : }
138 0 : case FD_CERT_KIND_SKIP: {
139 0 : fd_bls_agg_t * agg = &self->skip.agg_skip;
140 0 : fd_bls_agg_t * agg2 = &self->skip.agg_skip_fallback;
141 0 : self->skip.slot = cert.slot;
142 0 : self->skip.shred_version = cert.shred_version;
143 0 : if( FD_UNLIKELY( err = fd_bls_agg_pair_de( agg, agg2, bit_cnt, cert.bitmap, cert.bitmap_sz ) ) ) return err;
144 0 : agg->sig = *sig;
145 0 : break;
146 0 : }
147 0 : default:
148 0 : return FD_CERT_DE_ERR_INVAL;
149 0 : }
150 :
151 0 : return FD_CERT_DE_SUCCESS;
152 0 : }
|