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