Line data Source code
1 : #include "fd_solcap_reader.h"
2 : #include "fd_solcap_proto.h"
3 : #include "../nanopb/pb_decode.h"
4 :
5 : #if !FD_HAS_HOSTED
6 : #error "fd_solcap_reader requires FD_HAS_HOSTED"
7 : #endif
8 :
9 : #include <errno.h>
10 : #include <stdio.h>
11 :
12 : fd_solcap_chunk_iter_t *
13 : fd_solcap_chunk_iter_new( fd_solcap_chunk_iter_t * iter,
14 0 : void * _stream ) {
15 :
16 0 : FILE * stream = (FILE *)_stream;
17 :
18 0 : long pos = ftell( stream );
19 0 : if( FD_UNLIKELY( pos<0L ) ) {
20 0 : iter->err = errno;
21 0 : return iter;
22 0 : }
23 :
24 0 : *iter = (fd_solcap_chunk_iter_t) {
25 0 : .stream = stream,
26 0 : .chunk = {0},
27 0 : .chunk_off = 0UL,
28 0 : .chunk_end = (ulong)pos,
29 0 : };
30 0 : return iter;
31 0 : }
32 :
33 : long
34 0 : fd_solcap_chunk_iter_next( fd_solcap_chunk_iter_t * iter ) {
35 :
36 0 : FILE * stream = (FILE *)iter->stream;
37 :
38 0 : long chunk_gaddr = (long)iter->chunk_end;
39 0 : if( FD_UNLIKELY( 0!=fseek( iter->stream, chunk_gaddr, SEEK_SET ) ) ) {
40 0 : FD_LOG_WARNING(( "fseek failed (%d-%s)", errno, strerror( errno ) ));
41 0 : iter->err = errno;
42 0 : return -1L;
43 0 : }
44 0 : iter->chunk_off = (ulong)chunk_gaddr;
45 :
46 0 : ulong n = fread( &iter->chunk, sizeof(fd_solcap_chunk_t), 1UL, stream );
47 0 : if( FD_UNLIKELY( n!=1UL ) ) {
48 0 : int err = ferror( stream );
49 0 : if( FD_UNLIKELY( err ) ) {
50 0 : FD_LOG_WARNING(( "fread failed (%d-%s)", errno, strerror( errno ) ));
51 0 : iter->err = err;
52 0 : }
53 0 : iter->err = 0;
54 0 : return -1L;
55 0 : }
56 :
57 0 : if( FD_UNLIKELY( ( !fd_solcap_is_chunk_magic( iter->chunk.magic ) )
58 0 : | ( iter->chunk.total_sz < sizeof(fd_solcap_chunk_t) ) ) ) {
59 0 : FD_LOG_WARNING(( "invalid chunk (offset=%#lx magic=0x%016lx total_sz=%lu)",
60 0 : (ulong)chunk_gaddr, iter->chunk.magic, iter->chunk.total_sz ));
61 0 : iter->err = EPROTO;
62 0 : return -1L;
63 0 : }
64 :
65 0 : iter->chunk_end = (ulong)chunk_gaddr + iter->chunk.total_sz;
66 :
67 0 : return chunk_gaddr;
68 0 : }
69 :
70 : int
71 0 : fd_solcap_chunk_iter_done( fd_solcap_chunk_iter_t const * iter ) {
72 0 : return feof( (FILE *)iter->stream ) || fd_solcap_chunk_iter_err( iter );
73 0 : }
74 :
75 :
76 : int
77 : fd_solcap_read_bank_preimage( void * _file,
78 : ulong chunk_goff,
79 : fd_solcap_BankPreimage * preimage,
80 0 : fd_solcap_chunk_t const * hdr ) {
81 :
82 0 : if( FD_UNLIKELY( hdr->magic != FD_SOLCAP_V1_BANK_MAGIC ) )
83 0 : return EPROTO;
84 :
85 : /* Seek to Protobuf */
86 0 : FILE * file = (FILE *)_file;
87 0 : if( FD_UNLIKELY( 0!=fseek( file, (long)chunk_goff + hdr->meta_coff, SEEK_SET ) ) )
88 0 : return errno;
89 :
90 : /* Read into stack buffer */
91 0 : uchar buf[ FD_SOLCAP_BANK_PREIMAGE_FOOTPRINT ];
92 0 : if( FD_UNLIKELY( hdr->meta_sz > FD_SOLCAP_BANK_PREIMAGE_FOOTPRINT ) )
93 0 : return ENOMEM;
94 0 : if( FD_UNLIKELY( hdr->meta_sz != fread( buf, 1UL, hdr->meta_sz, file ) ) )
95 0 : return ferror( file );
96 :
97 : /* Decode */
98 0 : pb_istream_t stream = pb_istream_from_buffer( buf, hdr->meta_sz );
99 0 : if( FD_UNLIKELY( !pb_decode( &stream, fd_solcap_BankPreimage_fields, preimage ) ) ) {
100 0 : FD_LOG_WARNING(( "pb_decode failed (%s)", PB_GET_ERROR(&stream) ));
101 0 : return EPROTO;
102 0 : }
103 :
104 0 : return 0;
105 0 : }
106 :
107 : int
108 : fd_solcap_find_account_table( void * _file,
109 : fd_solcap_AccountTableMeta * meta,
110 0 : ulong _chunk_goff ) {
111 :
112 : /* Read account table chunk header */
113 0 : long chunk_goff = (long)_chunk_goff;
114 0 : fd_solcap_chunk_t hdr[1];
115 0 : FILE * file = (FILE *)_file;
116 0 : if( FD_UNLIKELY( 0!=fseek( file, chunk_goff, SEEK_SET ) ) )
117 0 : return errno;
118 0 : if( FD_UNLIKELY( 1UL != fread( hdr, sizeof(fd_solcap_chunk_t), 1UL, file ) ) )
119 0 : return ferror( file );
120 0 : if( FD_UNLIKELY( hdr->magic != FD_SOLCAP_V1_ACTB_MAGIC ) )
121 0 : return EPROTO;
122 :
123 : /* Seek to Protobuf */
124 0 : if( FD_UNLIKELY( 0!=fseek( file, chunk_goff + hdr->meta_coff, SEEK_SET ) ) )
125 0 : return errno;
126 :
127 : /* Read into stack buffer */
128 0 : uchar buf[ FD_SOLCAP_ACTB_META_FOOTPRINT ];
129 0 : if( FD_UNLIKELY( hdr->meta_sz > FD_SOLCAP_ACTB_META_FOOTPRINT ) )
130 0 : return ENOMEM;
131 0 : if( FD_UNLIKELY( hdr->meta_sz != fread( buf, 1UL, hdr->meta_sz, file ) ) )
132 0 : return ferror( file );
133 :
134 : /* Decode */
135 0 : pb_istream_t stream = pb_istream_from_buffer( buf, hdr->meta_sz );
136 0 : if( FD_UNLIKELY( !pb_decode( &stream, fd_solcap_AccountTableMeta_fields, meta ) ) ) {
137 0 : FD_LOG_WARNING(( "pb_decode failed (%s)", PB_GET_ERROR(&stream) ));
138 0 : return EPROTO;
139 0 : }
140 :
141 : /* Seek to table */
142 0 : if( meta->account_table_coff ) {
143 0 : if( FD_UNLIKELY( 0!=fseek( file, chunk_goff + (long)meta->account_table_coff, SEEK_SET ) ) )
144 0 : return errno;
145 0 : }
146 :
147 0 : return 0;
148 0 : }
149 :
150 : int
151 : fd_solcap_find_account( void * _file,
152 : fd_solcap_AccountMeta * meta,
153 : ulong * opt_data_off,
154 : fd_solcap_account_tbl_t const * rec,
155 0 : ulong acc_tbl_goff ) {
156 :
157 : /* Read account chunk header */
158 0 : long chunk_goff = (long)acc_tbl_goff + rec->acc_coff;
159 0 : fd_solcap_chunk_t hdr[1];
160 0 : FILE * file = (FILE *)_file;
161 0 : if( FD_UNLIKELY( 0!=fseek( file, chunk_goff, SEEK_SET ) ) )
162 0 : return errno;
163 0 : if( FD_UNLIKELY( 1UL != fread( hdr, sizeof(fd_solcap_chunk_t), 1UL, file ) ) )
164 0 : return ferror( file );
165 0 : if( FD_UNLIKELY( hdr->magic != FD_SOLCAP_V1_ACCT_MAGIC ) )
166 0 : return EPROTO;
167 :
168 : /* Seek to Protobuf */
169 0 : if( FD_UNLIKELY( 0!=fseek( file, chunk_goff + hdr->meta_coff, SEEK_SET ) ) )
170 0 : return errno;
171 :
172 : /* Read into stack buffer */
173 0 : uchar buf[ FD_SOLCAP_ACCOUNT_META_FOOTPRINT ];
174 0 : if( FD_UNLIKELY( hdr->meta_sz > FD_SOLCAP_ACCOUNT_META_FOOTPRINT ) )
175 0 : return ENOMEM;
176 0 : if( FD_UNLIKELY( hdr->meta_sz != fread( buf, 1UL, hdr->meta_sz, file ) ) )
177 0 : return ferror( file );
178 :
179 : /* Decode */
180 0 : pb_istream_t stream = pb_istream_from_buffer( buf, hdr->meta_sz );
181 0 : if( FD_UNLIKELY( !pb_decode( &stream, fd_solcap_AccountMeta_fields, meta ) ) ) {
182 0 : FD_LOG_WARNING(( "pb_decode failed (%s)", PB_GET_ERROR(&stream) ));
183 0 : return EPROTO;
184 0 : }
185 :
186 : /* Seek to account data */
187 0 : if( fd_solcap_includes_account_data( meta ) && opt_data_off )
188 0 : *opt_data_off = (ulong)( chunk_goff + (long)meta->data_coff );
189 :
190 0 : return 0;
191 0 : }
|