Line data Source code
1 : #include "fd_solcap_writer.h"
2 : #include "fd_solcap_proto.h"
3 :
4 : #include <errno.h>
5 : #include <unistd.h>
6 : #include <fcntl.h>
7 :
8 : ulong
9 0 : fd_solcap_writer_align( void ) {
10 0 : return alignof(fd_solcap_writer_t);
11 0 : }
12 :
13 : ulong
14 0 : fd_solcap_writer_footprint( void ) {
15 0 : return sizeof(fd_solcap_writer_t);
16 0 : }
17 :
18 : fd_solcap_writer_t *
19 : fd_solcap_writer_init( fd_solcap_writer_t * writer,
20 0 : int fd ) {
21 :
22 0 : if( FD_UNLIKELY( !writer ) ) {
23 0 : FD_LOG_WARNING(( "NULL writer" ));
24 0 : return NULL;
25 0 : }
26 0 : if( FD_UNLIKELY( fd < 0 ) ) {
27 0 : FD_LOG_WARNING(( "invalid file descriptor" ));
28 0 : return NULL;
29 0 : }
30 :
31 0 : writer->fd = fd;
32 :
33 0 : off_t pos = lseek( fd, 0L, SEEK_SET );
34 0 : if( FD_UNLIKELY( pos < 0L ) ) {
35 0 : FD_LOG_WARNING(( "lseek failed (%d-%s)", errno, strerror( errno ) ));
36 0 : return NULL;
37 0 : }
38 :
39 : /* Write Section Header Block (SHB) - PCapNG file header */
40 0 : uint shb_size = (uint)(sizeof(fd_pcapng_shb_t) + 4U); /* +4 for redundant length */
41 0 : fd_pcapng_shb_t shb = {
42 0 : .block_type = FD_PCAPNG_BLOCK_TYPE_SHB,
43 0 : .block_sz = shb_size,
44 0 : .byte_order_magic = FD_PCAPNG_BYTE_ORDER_MAGIC,
45 0 : .version_major = 1,
46 0 : .version_minor = 0,
47 : .section_sz = ULONG_MAX /* -1 = unlimited */
48 0 : };
49 0 : FD_TEST( sizeof(fd_pcapng_shb_t) == (ulong)write(fd, &shb, sizeof(fd_pcapng_shb_t)) );
50 : /* Write redundant block length footer */
51 0 : FD_TEST( 4U == (uint)write(fd, &shb_size, 4U) );
52 :
53 : /* Write Interface Description Block (IDB) */
54 0 : uint idb_size = (uint)(sizeof(fd_pcapng_idb_t) + 4U); /* +4 for redundant length */
55 0 : fd_pcapng_idb_t idb = {
56 0 : .block_type = FD_PCAPNG_BLOCK_TYPE_IDB,
57 0 : .block_sz = idb_size,
58 0 : .link_type = SOLCAP_IDB_HDR_LINK_TYPE,
59 0 : ._pad_0a = 0,
60 0 : .snap_len = SOLCAP_IDB_HDR_SNAP_LEN
61 0 : };
62 0 : FD_TEST( sizeof(fd_pcapng_idb_t) == (ulong)write(fd, &idb, sizeof(fd_pcapng_idb_t)) );
63 : /* Write redundant block length footer */
64 0 : FD_TEST( 4U == (uint)write(fd, &idb_size, 4U) );
65 :
66 0 : return writer;
67 0 : }
68 :
69 : uint
70 : fd_solcap_write_account_hdr( fd_solcap_writer_t * writer,
71 : fd_solcap_buf_msg_t * msg_hdr,
72 0 : fd_solcap_account_update_hdr_t * account_update ) {
73 0 : int fd = writer->fd;
74 :
75 0 : ulong data_sz = account_update->data_sz;
76 :
77 0 : uint packet_len = (uint)(sizeof(fd_solcap_chunk_int_hdr_t) +
78 0 : sizeof(fd_solcap_account_update_hdr_t) +
79 0 : data_sz);
80 :
81 0 : uint unaligned_block_len = (uint)(sizeof(fd_pcapng_epb_t) +
82 0 : packet_len +
83 0 : 4U); /* +4 for redundant length footer */
84 :
85 0 : uint block_len = (uint)((unaligned_block_len + 3UL) & ~3UL);
86 :
87 0 : fd_pcapng_epb_t epb = {
88 0 : .block_type = FD_PCAPNG_BLOCK_TYPE_EPB,
89 0 : .block_sz = block_len,
90 0 : .if_idx = 0,
91 0 : .ts_hi = 0,
92 0 : .ts_lo = 0,
93 0 : .cap_len = packet_len,
94 0 : .orig_len = packet_len
95 0 : };
96 0 : FD_TEST( sizeof(fd_pcapng_epb_t) == (ulong)write(fd, &epb, sizeof(fd_pcapng_epb_t)) );
97 :
98 0 : fd_solcap_chunk_int_hdr_t int_hdr = {
99 0 : .block_type = SOLCAP_WRITE_ACCOUNT,
100 0 : .slot = (uint)msg_hdr->slot,
101 0 : .txn_idx = msg_hdr->txn_idx
102 0 : };
103 0 : FD_TEST( sizeof(fd_solcap_chunk_int_hdr_t) == (ulong)write(fd, &int_hdr, sizeof(fd_solcap_chunk_int_hdr_t)) );
104 :
105 0 : FD_TEST( sizeof(fd_solcap_account_update_hdr_t) == (ulong)write(fd, account_update, sizeof(fd_solcap_account_update_hdr_t)) );
106 :
107 0 : return block_len;
108 0 : }
109 :
110 : uint
111 : fd_solcap_write_data( fd_solcap_writer_t * writer,
112 : void const * data,
113 0 : ulong data_sz ) {
114 0 : int fd = writer->fd;
115 0 : FD_TEST( data_sz == (ulong)write(fd, data, data_sz) );
116 0 : return 0;
117 0 : }
118 :
119 :
120 : uint
121 : fd_solcap_write_bank_preimage( fd_solcap_writer_t * writer,
122 : fd_solcap_buf_msg_t * msg_hdr,
123 0 : fd_solcap_bank_preimage_t * bank_preimage ) {
124 0 : int fd = writer->fd;
125 :
126 0 : uint packet_len = (uint)(sizeof(fd_solcap_chunk_int_hdr_t) +
127 0 : sizeof(fd_solcap_bank_preimage_t));
128 :
129 0 : uint unaligned_block_len = (uint)(sizeof(fd_pcapng_epb_t) +
130 0 : packet_len + 4U); /* +4 for redundant length footer */
131 :
132 0 : uint block_len = (uint)((unaligned_block_len + 3UL) & ~3UL);
133 :
134 0 : fd_pcapng_epb_t epb = {
135 0 : .block_type = FD_PCAPNG_BLOCK_TYPE_EPB,
136 0 : .block_sz = block_len,
137 0 : .if_idx = 0,
138 0 : .ts_hi = 0,
139 0 : .ts_lo = 0,
140 0 : .cap_len = packet_len,
141 0 : .orig_len = packet_len
142 0 : };
143 0 : FD_TEST( sizeof(fd_pcapng_epb_t) == (ulong)write(fd, &epb, sizeof(fd_pcapng_epb_t)) );
144 :
145 0 : fd_solcap_chunk_int_hdr_t int_hdr = {
146 0 : .block_type = SOLCAP_WRITE_BANK_PREIMAGE,
147 0 : .slot = (uint)msg_hdr->slot,
148 0 : .txn_idx = msg_hdr->txn_idx
149 0 : };
150 0 : FD_TEST( sizeof(fd_solcap_chunk_int_hdr_t) == (ulong)write(fd, &int_hdr, sizeof(fd_solcap_chunk_int_hdr_t)) );
151 :
152 0 : FD_TEST( sizeof(fd_solcap_bank_preimage_t) == (ulong)write(fd, bank_preimage, sizeof(fd_solcap_bank_preimage_t)) );
153 :
154 0 : return block_len;
155 0 : }
156 :
157 : uint
158 : fd_solcap_write_ftr( fd_solcap_writer_t * writer,
159 0 : uint block_len_redundant ) {
160 0 : int fd = writer->fd;
161 0 : off_t current_pos = lseek( fd, 0L, SEEK_CUR );
162 0 : FD_TEST( current_pos >= 0L );
163 0 : uint padding_needed = (-(uint)current_pos & 3);
164 :
165 : /* Write padding to align to 4-byte boundary */
166 0 : if( padding_needed > 0 ) {
167 0 : static const char zeros[4] = {0};
168 0 : FD_TEST( padding_needed == (uint)write(fd, zeros, padding_needed) );
169 0 : }
170 :
171 : /* Write redundant block length footer (4 bytes) */
172 0 : FD_TEST( 4U == (uint)write(fd, &block_len_redundant, 4U) );
173 0 : return 0;
174 0 : }
175 :
176 : uint
177 : fd_solcap_write_stake_rewards_begin( fd_solcap_writer_t * writer,
178 : fd_solcap_buf_msg_t * msg_hdr,
179 0 : fd_solcap_stake_rewards_begin_t * stake_rewards_begin ) {
180 0 : int fd = writer->fd;
181 :
182 0 : uint packet_len = (uint)(sizeof(fd_solcap_chunk_int_hdr_t) +
183 0 : sizeof(fd_solcap_stake_rewards_begin_t));
184 :
185 0 : uint unaligned_block_len = (uint)(sizeof(fd_pcapng_epb_t) +
186 0 : packet_len + 4U); /* +4 for redundant length footer */
187 :
188 0 : uint block_len = (uint)((unaligned_block_len + 3UL) & ~3UL);
189 :
190 0 : fd_pcapng_epb_t epb = {
191 0 : .block_type = FD_PCAPNG_BLOCK_TYPE_EPB,
192 0 : .block_sz = block_len,
193 0 : .if_idx = 0,
194 0 : .ts_hi = 0,
195 0 : .ts_lo = 0,
196 0 : .cap_len = packet_len,
197 0 : .orig_len = packet_len
198 0 : };
199 0 : FD_TEST( sizeof(fd_pcapng_epb_t) == (ulong)write(fd, &epb, sizeof(fd_pcapng_epb_t)) );
200 :
201 0 : fd_solcap_chunk_int_hdr_t int_hdr = {
202 0 : .block_type = SOLCAP_STAKE_REWARDS_BEGIN,
203 0 : .slot = (uint)msg_hdr->slot,
204 0 : .txn_idx = msg_hdr->txn_idx
205 0 : };
206 0 : FD_TEST( sizeof(fd_solcap_chunk_int_hdr_t) == (ulong)write(fd, &int_hdr, sizeof(fd_solcap_chunk_int_hdr_t)) );
207 :
208 0 : FD_TEST( sizeof(fd_solcap_stake_rewards_begin_t) == (ulong)write(fd, stake_rewards_begin, sizeof(fd_solcap_stake_rewards_begin_t)) );
209 :
210 0 : return block_len;
211 0 : }
212 :
213 : uint
214 : fd_solcap_write_stake_account_payout( fd_solcap_writer_t * writer,
215 : fd_solcap_buf_msg_t * msg_hdr,
216 0 : fd_solcap_stake_account_payout_t * stake_account_payout ) {
217 0 : int fd = writer->fd;
218 :
219 0 : uint packet_len = (uint)(sizeof(fd_solcap_chunk_int_hdr_t) +
220 0 : sizeof(fd_solcap_stake_account_payout_t));
221 :
222 0 : uint unaligned_block_len = (uint)(sizeof(fd_pcapng_epb_t) +
223 0 : packet_len + 4U); /* +4 for redundant length footer */
224 :
225 0 : uint block_len = (uint)((unaligned_block_len + 3UL) & ~3UL);
226 :
227 0 : fd_pcapng_epb_t epb = {
228 0 : .block_type = FD_PCAPNG_BLOCK_TYPE_EPB,
229 0 : .block_sz = block_len,
230 0 : .if_idx = 0,
231 0 : .ts_hi = 0,
232 0 : .ts_lo = 0,
233 0 : .cap_len = packet_len,
234 0 : .orig_len = packet_len
235 0 : };
236 0 : FD_TEST( sizeof(fd_pcapng_epb_t) == (ulong)write(fd, &epb, sizeof(fd_pcapng_epb_t)) );
237 :
238 0 : fd_solcap_chunk_int_hdr_t int_hdr = {
239 0 : .block_type = SOLCAP_STAKE_ACCOUNT_PAYOUT,
240 0 : .slot = (uint)msg_hdr->slot,
241 0 : .txn_idx = msg_hdr->txn_idx
242 0 : };
243 0 : FD_TEST( sizeof(fd_solcap_chunk_int_hdr_t) == (ulong)write(fd, &int_hdr, sizeof(fd_solcap_chunk_int_hdr_t)) );
244 :
245 0 : FD_TEST( sizeof(fd_solcap_stake_account_payout_t) == (ulong)write(fd, stake_account_payout, sizeof(fd_solcap_stake_account_payout_t)) );
246 :
247 0 : return block_len;
248 0 : }
249 :
250 : uint
251 : fd_solcap_write_stake_reward_event( fd_solcap_writer_t * writer,
252 : fd_solcap_buf_msg_t * msg_hdr,
253 0 : fd_solcap_stake_reward_event_t * stake_reward_event ) {
254 0 : int fd = writer->fd;
255 :
256 0 : uint packet_len = (uint)(sizeof(fd_solcap_chunk_int_hdr_t) +
257 0 : sizeof(fd_solcap_stake_reward_event_t));
258 :
259 0 : uint unaligned_block_len = (uint)(sizeof(fd_pcapng_epb_t) +
260 0 : packet_len + 4U); /* +4 for redundant length footer */
261 :
262 0 : uint block_len = (uint)((unaligned_block_len + 3UL) & ~3UL);
263 :
264 0 : fd_pcapng_epb_t epb = {
265 0 : .block_type = FD_PCAPNG_BLOCK_TYPE_EPB,
266 0 : .block_sz = block_len,
267 0 : .if_idx = 0,
268 0 : .ts_hi = 0,
269 0 : .ts_lo = 0,
270 0 : .cap_len = packet_len,
271 0 : .orig_len = packet_len
272 0 : };
273 0 : FD_TEST( sizeof(fd_pcapng_epb_t) == (ulong)write(fd, &epb, sizeof(fd_pcapng_epb_t)) );
274 :
275 0 : fd_solcap_chunk_int_hdr_t int_hdr = {
276 0 : .block_type = SOLCAP_STAKE_REWARD_EVENT,
277 0 : .slot = (uint)msg_hdr->slot,
278 0 : .txn_idx = msg_hdr->txn_idx
279 0 : };
280 0 : FD_TEST( sizeof(fd_solcap_chunk_int_hdr_t) == (ulong)write(fd, &int_hdr, sizeof(fd_solcap_chunk_int_hdr_t)) );
281 :
282 0 : FD_TEST( sizeof(fd_solcap_stake_reward_event_t) == (ulong)write(fd, stake_reward_event, sizeof(fd_solcap_stake_reward_event_t)) );
283 :
284 0 : return block_len;
285 0 : }
|