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