Line data Source code
1 : #include "ag_bls_serde.h"
2 :
3 354 : #define FAIL( cond, err ) do { if( FD_UNLIKELY( cond ) ) return AG_BLS_DE_ERR_##err; } while( 0 )
4 :
5 81 : #define BASE2_BITMAP (0)
6 75 : #define BASE3_BITMAP (1)
7 :
8 : static ulong
9 432 : agg_bit_cnt( fd_bls_agg_t const * agg ) {
10 432 : return fd_ulong_min( FD_BLS_SET_MAX, fd_bls_set_last( agg->set )+1UL );
11 432 : }
12 :
13 : ulong
14 123 : ag_bls_agg_ser_sz( fd_bls_agg_t const * agg ) {
15 123 : return AG_BLS_AGG_SER_SZ( agg_bit_cnt( agg ) );
16 123 : }
17 :
18 : ulong
19 : ag_bls_agg_pair_ser_sz( fd_bls_agg_t const * agg,
20 81 : fd_bls_agg_t const * agg_fb ) {
21 81 : return AG_BLS_AGG_PAIR_SER_SZ( fd_ulong_max( agg_bit_cnt( agg ), agg_bit_cnt( agg_fb ) ) );
22 81 : }
23 :
24 : ulong
25 : ag_bls_agg_ser( fd_bls_agg_t const * agg,
26 63 : uchar * buf ) {
27 :
28 63 : ulong bit_cnt = agg_bit_cnt( agg );
29 :
30 63 : ag_bls_agg_serde_t serde[1];
31 63 : serde->version = (uchar)BASE2_BITMAP;
32 63 : serde->bit_cnt = (ushort)bit_cnt;
33 63 : serde->payload = NULL;
34 63 : serde->payload_sz = ag_bls_agg_ser_sz( agg ) - AG_BLS_AGG_HDR_SZ;
35 :
36 63 : ulong off = 0UL;
37 63 : buf[ off ] = serde->version; off += sizeof(uchar);
38 63 : FD_STORE( ushort, buf+off, serde->bit_cnt ); off += sizeof(ushort);
39 :
40 63 : uchar * payload = buf+off;
41 63 : fd_memset( payload, 0, serde->payload_sz );
42 6633 : for( ulong i=0UL; i<bit_cnt; i++ ) {
43 6570 : if( FD_LIKELY( fd_bls_set_test( agg->set, i ) ) ) payload[ i>>3 ] |= (uchar)( 1U << (i&7U) );
44 6570 : }
45 63 : off += serde->payload_sz;
46 :
47 63 : return off;
48 63 : }
49 :
50 : ulong
51 : ag_bls_agg_pair_ser( fd_bls_agg_t const * agg,
52 : fd_bls_agg_t const * agg_fb,
53 42 : uchar * buf ) {
54 :
55 42 : ulong bit_cnt = fd_ulong_max( agg_bit_cnt( agg ), agg_bit_cnt( agg_fb ) );
56 :
57 42 : ag_bls_agg_serde_t serde[1];
58 42 : serde->version = (uchar)BASE3_BITMAP;
59 42 : serde->bit_cnt = (ushort)bit_cnt;
60 42 : serde->payload = NULL;
61 42 : serde->payload_sz = ag_bls_agg_pair_ser_sz( agg, agg_fb ) - AG_BLS_AGG_HDR_SZ;
62 :
63 42 : ulong off = 0UL;
64 42 : buf[ off ] = serde->version; off += sizeof(uchar);
65 42 : FD_STORE( ushort, buf+off, serde->bit_cnt ); off += sizeof(ushort);
66 :
67 42 : uchar * payload = buf+off;
68 2505 : for( ulong chunk=0UL; chunk<serde->payload_sz; chunk++ ) {
69 2463 : ulong start_bit = chunk*5UL;
70 2463 : ulong end_bit = fd_ulong_min( start_bit+5UL, bit_cnt );
71 2463 : uint block = 0U;
72 2463 : uint place = 1U;
73 14751 : for( ulong i=start_bit; i<end_bit; i++ ) {
74 12288 : uint digit = fd_bls_set_test( agg->set, i ) ? 1U
75 12288 : : fd_bls_set_test( agg_fb->set, i ) ? 2U : 0U;
76 12288 : block += digit*place;
77 12288 : place *= 3U;
78 12288 : }
79 2463 : payload[ chunk ] = (uchar)block;
80 2463 : }
81 42 : off += serde->payload_sz;
82 :
83 42 : return off;
84 42 : }
85 :
86 : static int
87 : bitmap_hdr( ag_bls_agg_serde_t * serde,
88 : uchar const * buf,
89 126 : ulong buf_sz ) {
90 126 : FAIL( buf_sz<AG_BLS_AGG_HDR_SZ, SZ );
91 :
92 108 : serde->version = buf[ 0 ];
93 108 : serde->bit_cnt = FD_LOAD( ushort, buf+1UL );
94 108 : serde->payload = buf+AG_BLS_AGG_HDR_SZ;
95 108 : serde->payload_sz = buf_sz-AG_BLS_AGG_HDR_SZ;
96 :
97 108 : return AG_BLS_DE_SUCCESS;
98 126 : }
99 :
100 : static int
101 : base2_de( fd_bls_agg_t * agg,
102 57 : ag_bls_agg_serde_t const * serde ) {
103 57 : ulong bit_cnt = (ulong)serde->bit_cnt;
104 57 : FAIL( bit_cnt>FD_BLS_SET_MAX, SZ );
105 54 : FAIL( serde->payload_sz!=AG_BLS_AGG_SER_SZ( bit_cnt )-AG_BLS_AGG_HDR_SZ, INVAL );
106 :
107 48 : memset( agg, 0, sizeof(fd_bls_agg_t) ); /* zero is the point at infinity */
108 :
109 12636 : for( ulong i=0UL; i<bit_cnt; i++ ) {
110 12588 : if( FD_LIKELY( (serde->payload[ i>>3 ] >> (i&7U)) & 1U ) ) fd_bls_set_insert( agg->set, i );
111 12588 : }
112 48 : return AG_BLS_DE_SUCCESS;
113 54 : }
114 :
115 : static int
116 : base3_de( fd_bls_agg_t * agg,
117 : fd_bls_agg_t * agg_fb,
118 33 : ag_bls_agg_serde_t const * serde ) {
119 33 : ulong bit_cnt = (ulong)serde->bit_cnt;
120 33 : ulong chunk_cnt = AG_BLS_AGG_PAIR_SER_SZ( bit_cnt )-AG_BLS_AGG_HDR_SZ;
121 33 : FAIL( bit_cnt>FD_BLS_SET_MAX, SZ );
122 30 : FAIL( serde->payload_sz!=chunk_cnt, INVAL );
123 :
124 30 : memset( agg, 0, sizeof(fd_bls_agg_t) ); /* zero is the point at infinity */
125 30 : memset( agg_fb, 0, sizeof(fd_bls_agg_t) );
126 :
127 2472 : for( ulong chunk=0UL; chunk<chunk_cnt; chunk++ ) {
128 2442 : uint block = (uint)serde->payload[ chunk ];
129 2442 : ulong start_bit = chunk*5UL;
130 2442 : ulong end_bit = fd_ulong_min( start_bit+5UL, bit_cnt );
131 14631 : for( ulong i=start_bit; i<end_bit; i++ ) {
132 12189 : uint digit = block % 3U; block /= 3U;
133 12189 : if( FD_LIKELY ( digit==1U ) ) fd_bls_set_insert( agg->set, i );
134 3099 : else if( FD_UNLIKELY( digit==2U ) ) fd_bls_set_insert( agg_fb->set, i );
135 12189 : }
136 2442 : }
137 30 : return AG_BLS_DE_SUCCESS;
138 30 : }
139 :
140 : int
141 : ag_bls_agg_de( fd_bls_agg_t * agg,
142 : uchar const * buf,
143 63 : ulong buf_sz ) {
144 63 : ag_bls_agg_serde_t serde[1];
145 :
146 63 : int err = bitmap_hdr( serde, buf, buf_sz );
147 63 : if( FD_UNLIKELY( err ) ) return err;
148 54 : FAIL( serde->version!=BASE2_BITMAP, INVAL );
149 :
150 39 : return base2_de( agg, serde );
151 54 : }
152 :
153 : int
154 : ag_bls_agg_pair_de( fd_bls_agg_t * agg,
155 : fd_bls_agg_t * agg_fb,
156 : uchar const * buf,
157 63 : ulong buf_sz ) {
158 63 : ag_bls_agg_serde_t serde[1];
159 :
160 63 : int err = bitmap_hdr( serde, buf, buf_sz );
161 63 : if( FD_UNLIKELY( err ) ) return err;
162 :
163 54 : switch( serde->version ) {
164 18 : case BASE2_BITMAP:
165 18 : err = base2_de( agg, serde );
166 18 : if( FD_UNLIKELY( err ) ) return err;
167 18 : memset( agg_fb, 0, sizeof(fd_bls_agg_t) );
168 18 : return AG_BLS_DE_SUCCESS;
169 33 : case BASE3_BITMAP:
170 33 : return base3_de( agg, agg_fb, serde );
171 3 : default:
172 3 : return AG_BLS_DE_ERR_INVAL;
173 54 : }
174 54 : }
|