LCOV - code coverage report
Current view: top level - flamenco/shredcap - fd_shredcap.c (source / functions) Hit Total Coverage
Test: cov.lcov Lines: 0 855 0.0 %
Date: 2024-11-13 11:58:15 Functions: 0 9 0.0 %

          Line data    Source code
       1             : #include "fd_shredcap.h"
       2             : #include "../runtime/fd_rocksdb.h"
       3             : 
       4             : #define BUF_ALIGN               (16UL)
       5           0 : #define WBUF_FOOTPRINT          (65536UL)
       6             : #define MANIFEST_BUF_FOOTPRINT  (512UL)
       7             : #define BANK_HASH_BUF_FOOTPRINT (64UL)
       8             : #define RBUF_FOOTPRINT          (65536UL)
       9           0 : #define FILE_SLOT_NUM_DIGITS    (20UL) /* Max number of digits in a ulong */
      10             : 
      11             : /**** Helpers *****************************************************************/
      12             : void
      13           0 : set_file_name( char * file_name_ptr, ulong start_slot, ulong end_slot ) {
      14             :   /* File name should be "startslot_endslot" */
      15           0 :   fd_memset( file_name_ptr, '\0', FD_SHREDCAP_CAPTURE_FILE_NAME_LENGTH );
      16           0 :   fd_cstr_append_ulong_as_text( file_name_ptr, '0', '\0', start_slot, FILE_SLOT_NUM_DIGITS );
      17           0 :   fd_cstr_append_char( file_name_ptr + FILE_SLOT_NUM_DIGITS, '_' );
      18           0 :   fd_cstr_append_ulong_as_text( file_name_ptr + FILE_SLOT_NUM_DIGITS + 1,
      19           0 :                                 '0', '\0', end_slot, FILE_SLOT_NUM_DIGITS );
      20           0 : }
      21             : 
      22             : void
      23           0 : fd_shredcap_concat( char * buf, const char * dir, const char * file ) {
      24           0 :   fd_memset( buf, '\0', FD_SHREDCAP_CAPTURE_PATH_NAME_LENGTH );
      25           0 :   fd_cstr_append_cstr( buf, dir );
      26           0 :   fd_cstr_append_cstr( buf + strlen( dir ), file );
      27           0 : }
      28             : 
      29             : /**** Ingest ******************************************************************/
      30             : void
      31             : fd_shredcap_ingest_rocksdb_to_capture( const char * rocksdb_dir,
      32             :                                          const char * capture_dir,
      33             :                                          ulong        max_file_sz,
      34             :                                          ulong        start_slot,
      35           0 :                                          ulong        end_slot ) {
      36             :   /* Setup and start rocksdb ingest */
      37           0 :   fd_rocksdb_t rocks_db;
      38           0 :   char * rocksdb_err = fd_rocksdb_init( &rocks_db, rocksdb_dir );
      39           0 :   if ( rocksdb_err != NULL ) {
      40           0 :     FD_LOG_ERR(( "fd_rocksdb_init returned %s", rocksdb_err ));
      41           0 :   }
      42             : 
      43           0 :   if ( rocksdb_err != NULL ) {
      44           0 :     FD_LOG_ERR(( "fd_rocksdb_last_slot returned %s", rocksdb_err ));
      45           0 :   }
      46             : 
      47           0 :   if ( end_slot < start_slot ) {
      48           0 :     FD_LOG_ERR(( "rocksdb blocks are older than snapshot. first=%lu last=%lu wanted=%lu",
      49           0 :                  fd_rocksdb_first_slot(&rocks_db, &rocksdb_err), end_slot, start_slot ));
      50           0 :   }
      51             : 
      52           0 :   fd_rocksdb_root_iter_t iter;
      53           0 :   fd_rocksdb_root_iter_new( &iter );
      54             : 
      55           0 :   fd_slot_meta_t metadata;
      56           0 :   fd_memset( &metadata, 0, sizeof(metadata) );
      57             : 
      58           0 :   fd_valloc_t valloc = fd_libc_alloc_virtual();
      59             : 
      60           0 :   int ret = fd_rocksdb_root_iter_seek( &iter, &rocks_db, start_slot, &metadata, valloc );
      61           0 :   if ( ret != 0 ) {
      62           0 :     FD_LOG_ERR(( "fd_rocksdb_root_iter_seek returned %d", ret ));
      63           0 :   }
      64             : 
      65             :   /* Create directory for shredcap capture */
      66           0 :   int mkdir_res = mkdir( capture_dir, 0777 );
      67           0 :   if ( mkdir_res ) {
      68           0 :     FD_LOG_ERR(( "unable to create directory=%s", capture_dir ));
      69           0 :   }
      70             : 
      71             :   /* Setup manifest file and buffered I/O. Write out header. */
      72           0 :   char manifest_path_buf[ FD_SHREDCAP_CAPTURE_PATH_NAME_LENGTH ];
      73           0 :   fd_shredcap_concat( manifest_path_buf, capture_dir, "manifest" );
      74           0 :   int manifest_fd = open( manifest_path_buf, O_CREAT|O_WRONLY, (mode_t)0666 );
      75           0 :   if( FD_UNLIKELY( manifest_fd == -1 ) ) {
      76           0 :     FD_LOG_WARNING(( "open(\"%s\",O_CREAT|O_WRONLY|,0%03o) failed (%i-%s)",
      77           0 :                      manifest_path_buf, (uint)0666, errno, fd_io_strerror( errno ) ));
      78           0 :     return;
      79           0 :   }
      80           0 :   uchar manifest_buf[ WBUF_FOOTPRINT ] __attribute__((aligned(BUF_ALIGN)));
      81           0 :   fd_io_buffered_ostream_t manifest_ostream[ 1 ];
      82           0 :   fd_io_buffered_ostream_init( manifest_ostream, manifest_fd, manifest_buf, WBUF_FOOTPRINT );
      83           0 :   int err;
      84             : 
      85           0 :   fd_shredcap_manifest_hdr_t manifest_hdr;
      86           0 :   manifest_hdr.magic      = FD_SHREDCAP_MANIFEST_MAGIC;
      87           0 :   manifest_hdr.version    = FD_SHREDCAP_MANIFEST_VERSION;
      88           0 :   manifest_hdr.num_files  = UINT_MAX; /* This is written after the fact */
      89           0 :   manifest_hdr.start_slot = start_slot;
      90           0 :   manifest_hdr.end_slot   = end_slot;
      91           0 :   err = fd_io_buffered_ostream_write( manifest_ostream, &manifest_hdr,
      92           0 :                                       FD_SHREDCAP_MANIFEST_HDR_FOOTPRINT );
      93           0 :   if ( FD_UNLIKELY( err ) ) {
      94           0 :     FD_LOG_ERR(( "error writing manifest header" ));
      95           0 :   }
      96             : 
      97             :   /* Create and setup bank hash file */
      98           0 :   char bank_hash_path_buf[ FD_SHREDCAP_CAPTURE_PATH_NAME_LENGTH ];
      99           0 :   fd_shredcap_concat( bank_hash_path_buf, capture_dir, "bank_hash" );
     100           0 :   int bank_hash_fd = open( bank_hash_path_buf, O_CREAT|O_WRONLY, (mode_t)0666 );
     101           0 :   if( FD_UNLIKELY( bank_hash_fd == -1 ) ) {
     102           0 :     FD_LOG_WARNING(( "open(\"%s\",O_CREAT|O_WRONLY|,0%03o) failed (%i-%s)",
     103           0 :                      bank_hash_path_buf, (uint)0666, errno, fd_io_strerror( errno ) ));
     104           0 :     FD_LOG_ERR(( "can't create and open bank hash file" ));
     105           0 :   }
     106           0 :   uchar bank_hash_buf[ WBUF_FOOTPRINT ] __attribute__((aligned(BUF_ALIGN)));
     107           0 :   fd_io_buffered_ostream_t bank_hash_ostream[ 1 ];
     108           0 :   fd_io_buffered_ostream_init( bank_hash_ostream, bank_hash_fd, bank_hash_buf, WBUF_FOOTPRINT );
     109             : 
     110           0 :   fd_shredcap_bank_hash_hdr_t bank_hash_hdr;
     111           0 :   bank_hash_hdr.magic      = FD_SHREDCAP_BANK_HASH_MAGIC;
     112           0 :   bank_hash_hdr.version    = FD_SHREDCAP_BANK_HASH_VERSION;
     113           0 :   bank_hash_hdr.start_slot = start_slot;
     114           0 :   bank_hash_hdr.end_slot   = end_slot;
     115           0 :   err = fd_io_buffered_ostream_write( bank_hash_ostream, &bank_hash_hdr,
     116           0 :                                       FD_SHREDCAP_BANK_HASH_HDR_FOOTPRINT );
     117           0 :   if ( FD_UNLIKELY( err ) ) {
     118           0 :     FD_LOG_ERR(( "error writing bank hash file header" ));
     119           0 :   }
     120             : 
     121             :   /* The file size limit should be able to hold at least one full sized block (~40MiB) */
     122           0 :   long real_max_file_sz = (long)fd_ulong_if( max_file_sz < FD_SHREDCAP_MAX_BLOCK_STORAGE_FOOTPRINT,
     123           0 :                                              FD_SHREDCAP_MAX_BLOCK_STORAGE_FOOTPRINT, max_file_sz );
     124           0 :   uint num_files = 0;
     125           0 :   ulong block_count = 0;
     126             : 
     127             :   /* Create temporary name file for writing out shreds */
     128           0 :   char tmp_path_buf[ FD_SHREDCAP_CAPTURE_PATH_NAME_LENGTH ];
     129           0 :   fd_shredcap_concat( tmp_path_buf, capture_dir, "temp" );
     130           0 :   uchar wbuf[ WBUF_FOOTPRINT ] __attribute__((aligned(BUF_ALIGN)));
     131             : 
     132           0 :   ulong sz;
     133           0 :   long file_start_offset;
     134             : 
     135             :   /* Stop iterating when we current slot reaches end slot of end of rocksdb*/
     136           0 :   while( metadata.slot < end_slot && ret == 0 ) {
     137           0 :     ++num_files;
     138             : 
     139             :     /* Setup output file and I/O streaming */
     140           0 :     ulong file_block_count = 0;
     141           0 :     int fd = open( tmp_path_buf, O_CREAT|O_WRONLY, (mode_t)0666 );
     142           0 :     if( FD_UNLIKELY( fd == -1 ) ) {
     143           0 :       FD_LOG_ERR(( "open(\"%s\",O_CREAT|O_WRONLY|,0%03o) failed (%i-%s)",
     144           0 :                    tmp_path_buf, (uint)0666, errno, fd_io_strerror( errno ) ));
     145           0 :     }
     146           0 :     fd_io_buffered_ostream_t ostream[ 1 ];
     147           0 :     fd_io_buffered_ostream_init( ostream, fd, wbuf, WBUF_FOOTPRINT );
     148             : 
     149             :     /* File header and write it out */
     150           0 :     fd_shredcap_file_hdr_t file_hdr;
     151           0 :     file_hdr.magic      = FD_SHREDCAP_FILE_MAGIC;
     152           0 :     file_hdr.version    = FD_SHREDCAP_FILE_VERSION;
     153           0 :     file_hdr.start_slot = metadata.slot;
     154           0 :     file_hdr.end_slot   = ULONG_MAX; /* This is updated after file is populated */
     155           0 :     file_hdr.num_blocks = ULONG_MAX; /* This is updated after file is populated */
     156           0 :     err = fd_io_buffered_ostream_write( ostream, &file_hdr, FD_SHREDCAP_FILE_HDR_FOOTPRINT );
     157           0 :     if ( FD_UNLIKELY( err ) ) {
     158           0 :       FD_LOG_ERR(( "error writing capture file header" ));
     159           0 :     }
     160             : 
     161             :     /* Start iterating through slots*/
     162           0 :     ulong file_start_slot = metadata.slot;
     163           0 :     ulong file_end_slot   = 0;
     164             : 
     165             :     /* Keep adding to the file unless max file size is exceeded or current slot
     166             :        exceeeds the range */
     167           0 :     while ( metadata.slot < end_slot && lseek( ostream->fd, 0, SEEK_CUR ) < real_max_file_sz  ) {
     168           0 :       ulong cur_slot = metadata.slot;
     169             :       /* Import shreds for entire slot */
     170             : 
     171           0 :       int err = fd_rocksdb_import_block_shredcap( &rocks_db, &metadata, ostream, bank_hash_ostream );
     172           0 :       if( FD_UNLIKELY( err ) ) {
     173           0 :         FD_LOG_ERR(( "fd_rocksdb_get_block failed at slot=%lu", cur_slot ));
     174           0 :       }
     175             : 
     176           0 :       file_end_slot = metadata.slot;
     177           0 :       ++file_block_count;
     178             : 
     179           0 :       fd_bincode_destroy_ctx_t ctx = { .valloc = valloc };
     180           0 :       fd_slot_meta_destroy( &metadata, &ctx );
     181             : 
     182             :       /* Get next slot and handle case where end_slot is larger than the last
     183             :          slot in the rocksdb */
     184           0 :       ret = fd_rocksdb_root_iter_next( &iter, &metadata, valloc );
     185           0 :       if ( ret != 0 ) {
     186           0 :         ret = fd_rocksdb_get_meta( &rocks_db, cur_slot + 1, &metadata, valloc );
     187           0 :         if ( ret != 0 ) {
     188           0 :           break;
     189           0 :         }
     190           0 :       }
     191           0 :     }
     192           0 :     block_count += file_block_count;
     193             : 
     194             :     /* To finish out writing to capture file, copy the header into the footer,
     195             :        flush the buffer. The header needs to be updated to include the payload
     196             :        size. Clear any fd_io and close the fd. Rename the file. */
     197           0 :     file_hdr.end_slot   = file_end_slot;
     198           0 :     file_hdr.num_blocks = file_block_count;
     199           0 :     err = fd_io_buffered_ostream_write( ostream, &file_hdr, FD_SHREDCAP_FILE_FTR_FOOTPRINT );
     200           0 :     if ( FD_UNLIKELY( err ) ) {
     201           0 :       FD_LOG_ERR(( "error writing capture file footer" ));
     202           0 :     }
     203             : 
     204           0 :     if( FD_UNLIKELY( fd_io_buffered_ostream_flush( ostream ) ) ) {
     205           0 :       FD_LOG_ERR(( "error during fd_io_buffered_ostream_flush" ));
     206           0 :     }
     207           0 :     fd_io_buffered_ostream_fini( ostream );
     208             : 
     209           0 :     file_start_offset = lseek( ostream->fd, 0, SEEK_SET );
     210           0 :     if ( FD_UNLIKELY( file_start_offset == -1 ) ) {
     211           0 :       FD_LOG_ERR(( "lseek error when moving to start of file" ));
     212           0 :     }
     213           0 :     err = fd_io_write( ostream->fd, &file_hdr, FD_SHREDCAP_FILE_FTR_FOOTPRINT,
     214           0 :                        FD_SHREDCAP_FILE_FTR_FOOTPRINT, &sz );
     215           0 :     if ( FD_UNLIKELY( err ) ) {
     216           0 :       FD_LOG_ERR(( "error when writing to update file header" ));
     217           0 :     }
     218           0 :     if ( FD_UNLIKELY( sz != FD_SHREDCAP_FILE_FTR_FOOTPRINT ) ) {
     219           0 :       FD_LOG_ERR(( "unexpected size written when updating file header" ));
     220           0 :     }
     221             : 
     222           0 :     if ( FD_UNLIKELY( close( fd ) ) ) {
     223           0 :       FD_LOG_ERR(( "error while closing file descriptor" ));
     224           0 :     }
     225             : 
     226           0 :     char new_path_buf[ FD_SHREDCAP_CAPTURE_FILE_NAME_LENGTH ];
     227           0 :     set_file_name( new_path_buf, file_start_slot, file_end_slot );
     228           0 :     char new_file_name[ FD_SHREDCAP_CAPTURE_PATH_NAME_LENGTH ];
     229           0 :     fd_shredcap_concat( new_file_name, capture_dir, new_path_buf );
     230           0 :     rename( tmp_path_buf, new_file_name );
     231             : 
     232             :     /* Add a directory manifest entry */
     233           0 :     fd_shredcap_manifest_entry_t manifest_entry;
     234           0 :     manifest_entry.start_slot = file_start_slot;
     235           0 :     manifest_entry.end_slot   = file_end_slot;
     236           0 :     fd_memcpy( &manifest_entry.path, &new_path_buf, strlen( new_path_buf ) );
     237           0 :     err = fd_io_buffered_ostream_write( manifest_ostream, &manifest_entry,
     238           0 :                                         FD_SHREDCAP_MANIFEST_ENTRY_FOOTPRINT );
     239           0 :     if ( FD_UNLIKELY( err ) ) {
     240           0 :       FD_LOG_ERR(( "error writing manifest entry" ));
     241           0 :     }
     242             : 
     243           0 :     FD_LOG_NOTICE(( "ingested %lu blocks at file=%s", block_count, new_file_name ));
     244           0 :   }
     245             : 
     246             :   /* Write manifest footer and update header */
     247           0 :   manifest_hdr.num_files = num_files;
     248           0 :   err = fd_io_buffered_ostream_write( manifest_ostream, &manifest_hdr,
     249           0 :                                       FD_SHREDCAP_MANIFEST_FTR_FOOTPRINT );
     250           0 :   if ( FD_UNLIKELY( err ) ) {
     251           0 :     FD_LOG_ERR(( "error writing manifest footer" ));
     252           0 :   }
     253           0 :   fd_io_buffered_ostream_flush( manifest_ostream );
     254           0 :   fd_io_buffered_ostream_fini( manifest_ostream );
     255             : 
     256           0 :   file_start_offset = lseek( manifest_fd, 0, SEEK_SET );
     257           0 :   if ( FD_UNLIKELY( file_start_offset == -1 ) ) {
     258           0 :     FD_LOG_ERR(( "lseek failed when seeking to start of manifest" ));
     259           0 :   }
     260             : 
     261           0 :   err = fd_io_write( manifest_fd, &manifest_hdr, FD_SHREDCAP_MANIFEST_HDR_FOOTPRINT,
     262           0 :                      FD_SHREDCAP_MANIFEST_HDR_FOOTPRINT, &sz );
     263           0 :   if ( FD_UNLIKELY( err ) ) {
     264           0 :     FD_LOG_ERR(( "unable to write num_files=%u to manifest header", num_files ));
     265           0 :   }
     266           0 :   if ( FD_UNLIKELY( sz != FD_SHREDCAP_MANIFEST_HDR_FOOTPRINT ) ) {
     267           0 :     FD_LOG_ERR(( "size=%lu doesn't match expected size of manifest header=%lu",
     268           0 :                  sz, FD_SHREDCAP_MANIFEST_HDR_FOOTPRINT ));
     269           0 :   }
     270           0 :   if ( FD_UNLIKELY( close( manifest_fd ) ) ) {
     271           0 :     FD_LOG_ERR(( "unable to close the manifest file" ));
     272           0 :   }
     273             : 
     274             :   /* Write bank hash footer and update header */
     275           0 :   bank_hash_hdr.num_blocks = block_count;
     276           0 :   err = fd_io_buffered_ostream_write( bank_hash_ostream, &bank_hash_hdr,
     277           0 :                                       FD_SHREDCAP_BANK_HASH_FTR_FOOTPRINT );
     278           0 :   if ( FD_UNLIKELY( err ) ) {
     279           0 :     FD_LOG_ERR(( "error writing bank hash file footer" ));
     280           0 :   }
     281           0 :   fd_io_buffered_ostream_flush( bank_hash_ostream );
     282           0 :   fd_io_buffered_ostream_fini( bank_hash_ostream );
     283             : 
     284           0 :   file_start_offset = lseek( bank_hash_fd, 0, SEEK_SET );
     285           0 :   if ( FD_UNLIKELY( file_start_offset == -1 ) ) {
     286           0 :     FD_LOG_ERR(( "lseek error when seeking to start of bank hash" ));
     287           0 :   }
     288             : 
     289           0 :   err = fd_io_write( bank_hash_fd, &bank_hash_hdr, FD_SHREDCAP_BANK_HASH_HDR_FOOTPRINT,
     290           0 :                                FD_SHREDCAP_BANK_HASH_HDR_FOOTPRINT, &sz );
     291           0 :   if ( FD_UNLIKELY( err ) ) {
     292           0 :     FD_LOG_ERR(( "unable to write num_blocks=%u for bank hash file header", num_files ));
     293           0 :   }
     294           0 :   if ( FD_UNLIKELY( sz != FD_SHREDCAP_BANK_HASH_HDR_FOOTPRINT ) ) {
     295           0 :     FD_LOG_ERR(( "size=%lu doesn't match expected size of bank hash header=%lu",
     296           0 :                  sz, FD_SHREDCAP_BANK_HASH_HDR_FOOTPRINT ));
     297           0 :   }
     298           0 :   if ( FD_UNLIKELY( close( bank_hash_fd ) ) ) {
     299           0 :     FD_LOG_ERR(( "unable to close the bank_hash file" ));
     300           0 :   }
     301             : 
     302           0 :   fd_rocksdb_root_iter_destroy( &iter );
     303           0 :   fd_rocksdb_destroy( &rocks_db );
     304           0 : }
     305             : 
     306             : /***************** Verify Helpers *********************************************/
     307             : void
     308             : fd_shredcap_verify_slot( fd_shredcap_slot_hdr_t * slot_hdr,
     309             :                            fd_blockstore_t *          blockstore,
     310             :                            int                        fd,
     311           0 :                            char *                     rbuf ) {
     312             : 
     313             : 
     314           0 :   if ( FD_UNLIKELY( slot_hdr->magic != FD_SHREDCAP_SLOT_HDR_MAGIC ) ) {
     315           0 :     FD_LOG_ERR(( "slot header magic=%lu doesn't match expected magic=%lu",
     316           0 :                   slot_hdr->magic, FD_SHREDCAP_SLOT_HDR_MAGIC ));
     317           0 :   }
     318           0 :   if ( FD_UNLIKELY( slot_hdr->version != FD_SHREDCAP_SLOT_HDR_VERSION ) ) {
     319           0 :     FD_LOG_ERR(( "slot header version=%u doesn't match expected version=%lu",
     320           0 :                   slot_hdr->version, FD_SHREDCAP_SLOT_HDR_VERSION ));
     321           0 :   }
     322           0 :   if ( FD_UNLIKELY( slot_hdr->payload_sz == ULONG_MAX ) ) {
     323           0 :     FD_LOG_ERR(( "slot payload_sz=%lu is at default value", slot_hdr->payload_sz ));
     324           0 :   }
     325             : 
     326           0 :   ulong slot       = slot_hdr->slot;
     327           0 :   ulong max_idx    = slot_hdr->received;
     328           0 :   ulong payload_sz = slot_hdr->payload_sz;
     329             : 
     330           0 :   int err;
     331           0 :   ulong sz;
     332           0 :   for ( ulong idx = 0; idx < max_idx; ++idx ) {
     333             :     /* Read shred header */
     334           0 :     err = fd_io_read( fd, rbuf, FD_SHREDCAP_SHRED_HDR_FOOTPRINT,
     335           0 :                       FD_SHREDCAP_SHRED_HDR_FOOTPRINT, &sz );
     336           0 :     if ( FD_UNLIKELY( err != 0 ) ) {
     337           0 :       FD_LOG_ERR(( "unable to read shred hdr" ));
     338           0 :     }
     339           0 :     if ( FD_UNLIKELY( sz != FD_SHREDCAP_SHRED_HDR_FOOTPRINT ) ) {
     340           0 :       FD_LOG_ERR(( "read in size=%lu not equal to shred header footprint=%u",
     341           0 :                    sz, FD_SHREDCAP_SHRED_HDR_FOOTPRINT ));
     342           0 :     }
     343             : 
     344           0 :     fd_shredcap_shred_hdr_t * shred_hdr = (fd_shredcap_shred_hdr_t*)rbuf;
     345             : 
     346             :     /* Read shred body and verify slot number */
     347           0 :     ulong shred_boundary_sz = shred_hdr->shred_boundary_sz;
     348           0 :     err = fd_io_read( fd, rbuf, shred_boundary_sz, shred_boundary_sz, &sz );
     349           0 :     if ( FD_UNLIKELY( err != 0 ) ) {
     350           0 :       FD_LOG_ERR(( "unable to read shred" ));
     351           0 :     }
     352           0 :     if ( FD_UNLIKELY( sz != shred_boundary_sz ) ) {
     353           0 :       FD_LOG_ERR(( "read in size=%lu not equal to shred footprint=%lu", sz, shred_boundary_sz ));
     354           0 :     }
     355             : 
     356           0 :     fd_shred_t * shred = (fd_shred_t*)rbuf;
     357           0 :     if ( FD_UNLIKELY( blockstore != NULL ) ) {
     358           0 :       fd_buf_shred_insert( blockstore, shred );
     359           0 :     }
     360           0 :     if ( FD_UNLIKELY( slot != shred->slot ) ) {
     361           0 :       FD_LOG_ERR(( "slot header's slot=%lu doesn't match shred's slot=%lu", slot, shred->slot ));
     362           0 :     }
     363           0 :   }
     364             : 
     365             :   /* Ensure that a block exists for the given slot */
     366           0 :   fd_block_t * block = fd_blockstore_block_query( blockstore, slot );
     367           0 :   if ( FD_UNLIKELY( block == NULL) ) {
     368           0 :     FD_LOG_ERR(( "block doesn't exist for slot=%lu", slot ));
     369           0 :   }
     370             : 
     371             :   /* Validate slot footer */
     372           0 :   err = fd_io_read( fd, rbuf, 0, FD_SHREDCAP_SLOT_FTR_FOOTPRINT, &sz );
     373           0 :   if ( FD_UNLIKELY( err != 0 ) ) {
     374           0 :     FD_LOG_ERR(( "unable to read slot footer" ));
     375           0 :   }
     376           0 :   if ( FD_UNLIKELY( sz != FD_SHREDCAP_SLOT_FTR_FOOTPRINT ) ) {
     377           0 :     FD_LOG_ERR(( "read in size=%lu not equal to slot footer footprint=%lu",
     378           0 :                   sz, FD_SHREDCAP_SLOT_FTR_FOOTPRINT ));
     379           0 :   }
     380             : 
     381           0 :   fd_shredcap_slot_ftr_t * slot_ftr = (fd_shredcap_slot_ftr_t*)rbuf;
     382             : 
     383           0 :   if ( FD_UNLIKELY( slot_ftr->magic != FD_SHREDCAP_SLOT_FTR_MAGIC ) ) {
     384           0 :     FD_LOG_ERR(( "slot footer's magic=%lu doesn't match expected magic=%lu",
     385           0 :                  slot_ftr->magic, FD_SHREDCAP_SLOT_FTR_MAGIC ));
     386           0 :   }
     387           0 :   if ( FD_UNLIKELY( slot_ftr->payload_sz != payload_sz ) ) {
     388           0 :     FD_LOG_ERR(( "slot header's payload_sz=%lu doesn't match block footers's payload_sz=%lu",
     389           0 :                  slot_hdr->payload_sz, slot_ftr->payload_sz ));
     390           0 :   }
     391           0 : }
     392             : 
     393             : void
     394             : fd_shredcap_verify_capture_file( const char *      capture_dir,
     395             :                                    const char *      capture_file,
     396             :                                    fd_blockstore_t * blockstore,
     397             :                                    ulong             expected_start_slot,
     398             :                                    ulong             expected_end_slot,
     399             :                                    int               bank_hash_fd,
     400             :                                    char *            bank_hash_buf,
     401           0 :                                    ulong *           slots_seen ) {
     402             : 
     403           0 :   char capture_file_buf[ FD_SHREDCAP_CAPTURE_PATH_NAME_LENGTH ];
     404           0 :   fd_shredcap_concat( capture_file_buf, capture_dir, capture_file );
     405             : 
     406           0 :   int capture_fd = open( capture_file_buf, O_RDONLY, (mode_t)0 );
     407           0 :   if( FD_UNLIKELY( capture_fd == -1 ) ) {
     408           0 :     FD_LOG_WARNING(( "open(\"%s\",O_RDONLY,0) failed (%i-%s)", capture_file_buf, errno, fd_io_strerror( errno ) ));
     409           0 :     FD_LOG_ERR(( "can't read capture file, may not exist" ));
     410           0 :   }
     411             : 
     412           0 :   char rbuf[ RBUF_FOOTPRINT ] __attribute__((aligned(BUF_ALIGN)));
     413             : 
     414             :   /* Restore Header */
     415           0 :   ulong sz;
     416           0 :   int err = fd_io_read( capture_fd, &rbuf, 0, FD_SHREDCAP_FILE_HDR_FOOTPRINT, &sz );
     417           0 :   if ( FD_UNLIKELY( err != 0 ) ) {
     418           0 :     FD_LOG_ERR(( "unable to read file header" ));
     419           0 :   }
     420           0 :   if ( FD_UNLIKELY( sz != FD_SHREDCAP_FILE_HDR_FOOTPRINT ) ) {
     421           0 :     FD_LOG_ERR(( "read in size=%lu not equal to file header footprint=%lu",
     422           0 :                   sz, FD_SHREDCAP_FILE_HDR_FOOTPRINT ));
     423           0 :   }
     424           0 :   fd_shredcap_file_hdr_t * file_hdr_ptr = (fd_shredcap_file_hdr_t*)rbuf;
     425             : 
     426             :   /* Verifying file header */
     427           0 :   if ( FD_UNLIKELY( file_hdr_ptr->magic != FD_SHREDCAP_FILE_MAGIC ) ) {
     428           0 :     FD_LOG_ERR(( "file header magic=%lu doesn't match expected magic=%lu",
     429           0 :                  file_hdr_ptr->magic, FD_SHREDCAP_FILE_MAGIC ));
     430           0 :   }
     431           0 :   if ( FD_UNLIKELY( file_hdr_ptr->version != FD_SHREDCAP_FILE_VERSION ) ) {
     432           0 :     FD_LOG_ERR(( "file header version=%u doesn't match expected version=%lu",
     433           0 :                  file_hdr_ptr->version, FD_SHREDCAP_FILE_VERSION ));
     434           0 :   }
     435           0 :   if ( FD_UNLIKELY( file_hdr_ptr->start_slot != expected_start_slot ) ) {
     436           0 :     FD_LOG_ERR(( "file header start_slot=%lu doesn't match manifest entry's start_slot=%lu",
     437           0 :                  file_hdr_ptr->start_slot, expected_start_slot ));
     438           0 :   }
     439           0 :   if ( FD_UNLIKELY( file_hdr_ptr->end_slot != expected_end_slot ) ) {
     440           0 :     FD_LOG_ERR(( "file header end_slot=%lu doesn't match manifest entry's end_slot=%lu",
     441           0 :                  file_hdr_ptr->end_slot, expected_end_slot ));
     442           0 :   }
     443             : 
     444           0 :   fd_shredcap_file_hdr_t file_hdr;
     445           0 :   fd_memcpy( &file_hdr, file_hdr_ptr, FD_SHREDCAP_FILE_HDR_FOOTPRINT );
     446             : 
     447             :   /* Want to create a loop here for the slot_hdr */
     448           0 :   ulong cur_slot = 0;
     449           0 :   while( cur_slot < expected_end_slot ) {
     450           0 :     ++(*slots_seen);
     451           0 :     err = fd_io_read( capture_fd, rbuf, FD_SHREDCAP_SLOT_HDR_FOOTPRINT,
     452           0 :                       FD_SHREDCAP_SLOT_HDR_FOOTPRINT, &sz );
     453           0 :     if ( FD_UNLIKELY( err != 0 ) ) {
     454           0 :       FD_LOG_ERR(( "unable to read slot header" ));
     455           0 :     }
     456           0 :     if ( FD_UNLIKELY( sz != FD_SHREDCAP_SLOT_HDR_FOOTPRINT ) ) {
     457           0 :       FD_LOG_ERR(( "read in size=%lu not equal to slot header footprint=%lu",
     458           0 :                     sz, FD_SHREDCAP_SLOT_HDR_FOOTPRINT ));
     459           0 :     }
     460             : 
     461             :     /* Verify header contents and assemble blocks from shreds */
     462           0 :     fd_shredcap_slot_hdr_t * slot_hdr = (fd_shredcap_slot_hdr_t*)rbuf;
     463           0 :     cur_slot = slot_hdr->slot;
     464           0 :     fd_shredcap_verify_slot( slot_hdr, blockstore, capture_fd, rbuf );
     465             : 
     466           0 :     err = fd_io_read( bank_hash_fd, bank_hash_buf, FD_SHREDCAP_BANK_HASH_ENTRY_FOOTPRINT,
     467           0 :                       FD_SHREDCAP_BANK_HASH_ENTRY_FOOTPRINT, &sz );
     468           0 :     if ( FD_UNLIKELY( err != 0 ) ) {
     469           0 :       FD_LOG_ERR(( "unable to read bank hash entry" ));
     470           0 :     }
     471           0 :     if ( FD_UNLIKELY( sz != FD_SHREDCAP_BANK_HASH_ENTRY_FOOTPRINT ) ) {
     472           0 :       FD_LOG_ERR(( "read in size=%lu not equal to bank hash entry footprint=%lu",
     473           0 :                     sz, FD_SHREDCAP_BANK_HASH_ENTRY_FOOTPRINT ));
     474           0 :     }
     475           0 :     fd_shredcap_bank_hash_entry_t * bank_hash_entry = (fd_shredcap_bank_hash_entry_t *)bank_hash_buf;
     476           0 :     if ( FD_UNLIKELY( bank_hash_entry->slot != cur_slot ) ) {
     477           0 :       FD_LOG_ERR(( "bank hash entry slot=%lu does not match capture file slot=%lu",
     478           0 :                    bank_hash_entry->slot, cur_slot ));
     479           0 :     }
     480           0 :   }
     481             : 
     482             :   /* Verify num blocks */
     483           0 :   if ( FD_UNLIKELY( file_hdr.num_blocks != *slots_seen ) ) {
     484           0 :     FD_LOG_ERR(( "file header num_blocks=%lu not equal to number of seen slots=%lu",
     485           0 :                  file_hdr.num_blocks, *slots_seen ));
     486           0 :   }
     487             : 
     488             :   /* Verify file footer */
     489           0 :   err = fd_io_read( capture_fd, &rbuf, 0, FD_SHREDCAP_FILE_FTR_FOOTPRINT, &sz );
     490           0 :   if ( FD_UNLIKELY( err != 0 ) ) {
     491           0 :     FD_LOG_ERR(( "unable to read file footer" ));
     492           0 :   }
     493           0 :   if ( FD_UNLIKELY( sz != FD_SHREDCAP_FILE_FTR_FOOTPRINT ) ) {
     494           0 :     FD_LOG_ERR(( "read in size=%lu not equal to file footer footprint=%lu",
     495           0 :                   sz, FD_SHREDCAP_FILE_FTR_FOOTPRINT ));
     496           0 :   }
     497             : 
     498           0 :   fd_shredcap_file_ftr_t * file_ftr = (fd_shredcap_file_ftr_t*)rbuf;
     499             : 
     500           0 :   if ( FD_UNLIKELY( file_hdr.magic != file_ftr->magic ) ) {
     501           0 :     FD_LOG_ERR(( "file header magic=%lu doesn't match file footer magic=%lu",
     502           0 :                  file_hdr.magic, file_ftr->magic ));
     503           0 :   }
     504           0 :   if ( FD_UNLIKELY( file_hdr.version != file_ftr->version ) ) {
     505           0 :     FD_LOG_ERR(( "file header version=%u doesn't match file footer version=%u",
     506           0 :                  file_hdr.version, file_ftr->version ));
     507           0 :   }
     508           0 :   if ( FD_UNLIKELY( file_hdr.start_slot != file_ftr->start_slot ) ) {
     509           0 :     FD_LOG_ERR(( "file header start_slot=%lu doesn't match file footer start_slot=%lu",
     510           0 :                  file_hdr.start_slot, file_ftr->start_slot ));
     511           0 :   }
     512           0 :   if ( FD_UNLIKELY( file_hdr.end_slot != file_ftr->end_slot ) ) {
     513           0 :     FD_LOG_ERR(( "file header end_slot=%lu doesn't match file footer end_slot=%lu",
     514           0 :                  file_hdr.end_slot, file_ftr->end_slot ));
     515           0 :   }
     516           0 :   if ( FD_UNLIKELY( file_hdr.num_blocks != file_ftr->num_blocks ) ) {
     517           0 :     FD_LOG_ERR(( "file header num_blocks=%lu doesn't match file footer num_blocks=%lu",
     518           0 :                  file_hdr.num_blocks, file_ftr->num_blocks ));
     519           0 :   }
     520             : 
     521           0 :   if ( FD_UNLIKELY( close( capture_fd ) ) ) {
     522           0 :     FD_LOG_ERR(( "unable to close capture file=%s", capture_file ));
     523           0 :   }
     524           0 : }
     525             : 
     526             : void
     527           0 : fd_shredcap_verify( const char * capture_dir, fd_blockstore_t * blockstore ) {
     528           0 :   FD_LOG_NOTICE(( "starting verify" ));
     529             :   /* Take the manifest file as the source of truth for what files we expect to
     530             :     read. This means we don't check for the case in which there are any files
     531             :     not described in the manifest. */
     532           0 :   char manifest_file_buf[ FD_SHREDCAP_CAPTURE_PATH_NAME_LENGTH ];
     533           0 :   fd_shredcap_concat( manifest_file_buf, capture_dir, "manifest" );
     534             : 
     535             :  /* Want to iterate through the manifest and make sure that every entry
     536             :      corresponds to a file. Also need to ensure that every file in the directory
     537             :      maps back to a manifest entry */
     538           0 :   int manifest_fd = open( manifest_file_buf, O_RDONLY, (mode_t)0 );
     539           0 :   if( FD_UNLIKELY( manifest_fd == -1 ) ) {
     540           0 :     FD_LOG_WARNING(( "open(\"%s\",O_RDONLY,0) failed (%i-%s)",
     541           0 :                      manifest_file_buf, errno, fd_io_strerror( errno ) ));
     542           0 :     FD_LOG_ERR(( "can't open manifest file, may not exist" ));
     543           0 :   }
     544             : 
     545             :   /* Iterate through each entry on the bank_hash file and ensure that there is
     546             :      a corresponding 1-to-1 entry for the capture*/
     547           0 :   char bank_hash_file_buf[ FD_SHREDCAP_CAPTURE_PATH_NAME_LENGTH ];
     548           0 :   fd_shredcap_concat( bank_hash_file_buf, capture_dir, "bank_hash" );
     549             : 
     550           0 :   int bank_hash_fd = open( bank_hash_file_buf, O_RDONLY, (mode_t)0 );
     551           0 :   if( FD_UNLIKELY( bank_hash_fd == -1 ) ) {
     552           0 :     FD_LOG_WARNING(( "open(\"%s\",O_RDONLY,0) failed (%i-%s)",
     553           0 :                      bank_hash_file_buf, errno, fd_io_strerror( errno ) ));
     554           0 :     FD_LOG_ERR(( "can't open manifest file, may not exist" ));
     555           0 :   }
     556             : 
     557           0 :   char manifest_rbuf[ MANIFEST_BUF_FOOTPRINT ] __attribute__((aligned(BUF_ALIGN)));
     558           0 :   char bank_hash_rbuf[ BANK_HASH_BUF_FOOTPRINT ] __attribute__((aligned(BUF_ALIGN)));
     559             : 
     560             :   /* Read in manifest header */
     561           0 :   ulong sz;
     562           0 :   int err;
     563           0 :   err = fd_io_read( manifest_fd, &manifest_rbuf, FD_SHREDCAP_MANIFEST_HDR_FOOTPRINT,
     564           0 :                     FD_SHREDCAP_MANIFEST_HDR_FOOTPRINT, &sz );
     565           0 :   if ( FD_UNLIKELY( err ) ) {
     566           0 :     FD_LOG_ERR(( "unable to read manifest header" ));
     567           0 :   }
     568           0 :   if ( FD_UNLIKELY( sz != FD_SHREDCAP_MANIFEST_HDR_FOOTPRINT ) ) {
     569           0 :     FD_LOG_ERR(( "read in size=%lu not equal to manifest header footprint=%lu",
     570           0 :                  sz, FD_SHREDCAP_MANIFEST_HDR_FOOTPRINT ));
     571           0 :   }
     572             : 
     573           0 :   fd_shredcap_manifest_hdr_t * manifest_hdr = (fd_shredcap_manifest_hdr_t*)manifest_rbuf;
     574           0 :   if ( FD_UNLIKELY( manifest_hdr->magic != FD_SHREDCAP_MANIFEST_MAGIC ) ) {
     575           0 :     FD_LOG_ERR(( "manifest header magic=%lu doesn't match expected value=%lu",
     576           0 :                  manifest_hdr->magic, FD_SHREDCAP_MANIFEST_MAGIC ));
     577           0 :   }
     578           0 :   if ( FD_UNLIKELY( manifest_hdr->version != FD_SHREDCAP_MANIFEST_VERSION ) ) {
     579           0 :     FD_LOG_ERR(( "manifest header version=%lu doesn't match expected version=%lu",
     580           0 :                  manifest_hdr->magic, FD_SHREDCAP_MANIFEST_VERSION ));
     581           0 :   }
     582             : 
     583             :   /* Read in bank hash header*/
     584           0 :   err = fd_io_read( bank_hash_fd, &bank_hash_rbuf, FD_SHREDCAP_BANK_HASH_HDR_FOOTPRINT,
     585           0 :                     FD_SHREDCAP_BANK_HASH_HDR_FOOTPRINT, &sz );
     586           0 :   if ( FD_UNLIKELY( err ) ) {
     587           0 :     FD_LOG_ERR(( "unable to read bank hash header" ));
     588           0 :   }
     589           0 :   if ( FD_UNLIKELY( sz != FD_SHREDCAP_BANK_HASH_HDR_FOOTPRINT ) ) {
     590           0 :     FD_LOG_ERR(( "read in size=%lu not equal to bank hash header footprint=%lu",
     591           0 :                  sz, FD_SHREDCAP_BANK_HASH_HDR_FOOTPRINT ));
     592           0 :   }
     593             : 
     594           0 :   fd_shredcap_bank_hash_hdr_t * bank_hash_hdr = (fd_shredcap_bank_hash_hdr_t*)bank_hash_rbuf;
     595           0 :   if ( FD_UNLIKELY( bank_hash_hdr->magic != FD_SHREDCAP_BANK_HASH_MAGIC ) ) {
     596           0 :     FD_LOG_ERR(( "bank hash header magic=%lu is not equal to the expected magic=%lu",
     597           0 :                  bank_hash_hdr->magic, FD_SHREDCAP_BANK_HASH_MAGIC ));
     598           0 :   }
     599           0 :   if ( FD_UNLIKELY( bank_hash_hdr->version != FD_SHREDCAP_BANK_HASH_VERSION ) ) {
     600           0 :     FD_LOG_ERR(( "bank hash header version=%u is not equal to the expected version=%lu",
     601           0 :                  bank_hash_hdr->version, FD_SHREDCAP_BANK_HASH_VERSION ));
     602           0 :   }
     603           0 :   if ( FD_UNLIKELY( manifest_hdr->start_slot != bank_hash_hdr->start_slot ) ) {
     604           0 :     FD_LOG_ERR(( "manifest header start_slot=%lu is not equal to bank hash start_slot=%lu",
     605           0 :                  manifest_hdr->start_slot, bank_hash_hdr->start_slot ));
     606           0 :   }
     607           0 :   if ( FD_UNLIKELY( manifest_hdr->end_slot != bank_hash_hdr->end_slot ) ) {
     608           0 :     FD_LOG_ERR(( "manifest header end_slot=%lu is not equal to bank hash start_slot=%lu",
     609           0 :                  manifest_hdr->end_slot, bank_hash_hdr->end_slot ));
     610           0 :   }
     611             :   /* Count slots seen to make sure that it matches with the bank hash header */
     612           0 :   ulong num_blocks = bank_hash_hdr->num_blocks;
     613           0 :   ulong slots_seen = 0;
     614             : 
     615           0 :   ulong start_slot = manifest_hdr->start_slot;
     616           0 :   ulong end_slot   = manifest_hdr->end_slot;
     617           0 :   uint  num_files  = manifest_hdr->num_files;
     618             : 
     619           0 :   for ( ulong i = 0; i < num_files; ++i ) {
     620           0 :     err = fd_io_read( manifest_fd, &manifest_rbuf, FD_SHREDCAP_MANIFEST_ENTRY_FOOTPRINT,
     621           0 :                       FD_SHREDCAP_MANIFEST_ENTRY_FOOTPRINT, &sz );
     622           0 :     if ( FD_UNLIKELY( err ) ) {
     623           0 :       FD_LOG_ERR(( "unable to read manifest entry" ));
     624           0 :     }
     625           0 :     if ( FD_UNLIKELY( sz != FD_SHREDCAP_MANIFEST_ENTRY_FOOTPRINT ) ) {
     626           0 :       FD_LOG_ERR(( "read in size=%lu not equal to manifest entry footprint=%lu",
     627           0 :                   sz, FD_SHREDCAP_MANIFEST_ENTRY_FOOTPRINT ));
     628           0 :     }
     629             : 
     630           0 :     FD_TEST( sz == FD_SHREDCAP_MANIFEST_ENTRY_FOOTPRINT );
     631           0 :     fd_shredcap_manifest_entry_t * entry = (fd_shredcap_manifest_entry_t*)manifest_rbuf;
     632           0 :     ulong file_slots_seen = 0;
     633           0 :     fd_shredcap_verify_capture_file( capture_dir, entry->path, blockstore,
     634           0 :                                        entry->start_slot, entry->end_slot,
     635           0 :                                        bank_hash_fd, bank_hash_rbuf, &file_slots_seen );
     636           0 :     slots_seen += file_slots_seen;
     637           0 :   }
     638             : 
     639           0 :   if ( ( FD_UNLIKELY( num_blocks != slots_seen ) ) ) {
     640           0 :     FD_LOG_ERR(( "expected block count=%lu, seen=%lu", num_blocks, slots_seen ));
     641           0 :   }
     642             : 
     643           0 :   err = fd_io_read( manifest_fd, &manifest_rbuf, FD_SHREDCAP_MANIFEST_FTR_FOOTPRINT,
     644           0 :                     FD_SHREDCAP_MANIFEST_FTR_FOOTPRINT, &sz );
     645           0 :   if ( FD_UNLIKELY( err ) ) {
     646           0 :     FD_LOG_ERR(( "unable to read manifest footer" ));
     647           0 :   }
     648           0 :   if ( FD_UNLIKELY( sz != FD_SHREDCAP_MANIFEST_FTR_FOOTPRINT ) ) {
     649           0 :     FD_LOG_ERR(( "read in size=%lu not equal to manifest footer footprint=%lu",
     650           0 :                  sz, FD_SHREDCAP_MANIFEST_FTR_FOOTPRINT ));
     651           0 :   }
     652             : 
     653           0 :   fd_shredcap_manifest_ftr_t * manifest_ftr = (fd_shredcap_manifest_ftr_t*)manifest_rbuf;
     654           0 :   if ( FD_UNLIKELY( manifest_ftr->magic != FD_SHREDCAP_MANIFEST_MAGIC ) ) {
     655           0 :     FD_LOG_ERR(( "manifest footer magic=%lu doesn't match expected value=%lu",
     656           0 :                  manifest_ftr->magic, FD_SHREDCAP_MANIFEST_MAGIC ));
     657           0 :   }
     658           0 :   if ( FD_UNLIKELY( manifest_ftr->version != FD_SHREDCAP_SLOT_HDR_VERSION ) ) {
     659           0 :     FD_LOG_ERR(( "manifest footer version=%lu doesn't match expected version=%lu",
     660           0 :                  manifest_ftr->magic, FD_SHREDCAP_SLOT_HDR_VERSION ));
     661           0 :   }
     662           0 :   if ( FD_UNLIKELY( start_slot != manifest_ftr->start_slot ) ) {
     663           0 :     FD_LOG_ERR(( "manifest footer start_slot=%lu doesn't match manifest footer start_slot=%lu",
     664           0 :                  start_slot, manifest_ftr->start_slot ));
     665           0 :   }
     666           0 :   if ( FD_UNLIKELY( end_slot != manifest_ftr->end_slot ) ) {
     667           0 :     FD_LOG_ERR(( "manifest footer end_slot=%lu doesn't match manifest footer end_slot=%lu",
     668           0 :                  end_slot, manifest_ftr->end_slot ));
     669           0 :   }
     670           0 :   if ( FD_UNLIKELY( num_files != manifest_ftr->num_files ) ) {
     671           0 :     FD_LOG_ERR(( "manifest footer end_slot=%u doesn't match manifest footer num_files=%u",
     672           0 :                  num_files, manifest_ftr->num_files ));
     673           0 :   }
     674             : 
     675           0 :   if ( FD_UNLIKELY( close( manifest_fd ) ) ) {
     676           0 :     FD_LOG_ERR(( "unable to successfully close manifest file %s", manifest_file_buf ));
     677           0 :   }
     678             : 
     679           0 :   err = fd_io_read( bank_hash_fd, bank_hash_rbuf, FD_SHREDCAP_BANK_HASH_FTR_FOOTPRINT,
     680           0 :                     FD_SHREDCAP_BANK_HASH_FTR_FOOTPRINT, &sz );
     681           0 :   if ( FD_UNLIKELY( err ) ) {
     682           0 :     FD_LOG_ERR(( "unable to read bank hash footer" ));
     683           0 :   }
     684           0 :   if ( FD_UNLIKELY( sz != FD_SHREDCAP_BANK_HASH_FTR_FOOTPRINT ) ) {
     685           0 :     FD_LOG_ERR(( "read in size=%lu not equal to bank hash footer footprint=%lu",
     686           0 :                   sz, FD_SHREDCAP_BANK_HASH_FTR_FOOTPRINT ));
     687           0 :   }
     688             : 
     689           0 :   fd_shredcap_bank_hash_ftr_t * bank_hash_ftr = (fd_shredcap_bank_hash_ftr_t*)bank_hash_rbuf;
     690           0 :   if ( FD_UNLIKELY( bank_hash_ftr->magic != FD_SHREDCAP_BANK_HASH_MAGIC ) ) {
     691           0 :     FD_LOG_ERR(( "bank hash footer magic=%lu is not equal to the expected magic=%lu",
     692           0 :                  bank_hash_ftr->magic, FD_SHREDCAP_BANK_HASH_MAGIC ));
     693           0 :   }
     694           0 :   if ( FD_UNLIKELY( bank_hash_ftr->num_blocks != num_blocks ) ) {
     695           0 :     FD_LOG_ERR(( "bank hash footer num blocks=%lu is not equal to the header's num_blocks=%lu",
     696           0 :                  bank_hash_ftr->num_blocks, num_blocks ));
     697           0 :   }
     698           0 :   if ( FD_UNLIKELY( manifest_ftr->start_slot != bank_hash_ftr->start_slot ) ) {
     699           0 :     FD_LOG_ERR(( "manifest footer start_slot=%lu is not equal to bank hash start_slot=%lu",
     700           0 :                  manifest_hdr->start_slot, bank_hash_ftr->start_slot ));
     701           0 :   }
     702           0 :   if ( FD_UNLIKELY( manifest_ftr->end_slot != bank_hash_ftr->end_slot ) ) {
     703           0 :     FD_LOG_ERR(( "manifest footer end_slot=%lu is not equal to bank hash start_slot=%lu",
     704           0 :                  manifest_hdr->end_slot, bank_hash_ftr->end_slot ));
     705           0 :   }
     706             : 
     707           0 :   if ( FD_UNLIKELY( close( bank_hash_fd ) ) ) {
     708           0 :     FD_LOG_ERR(( "unable to close the bank hash file" ));
     709           0 :   }
     710           0 : }
     711             : /******************************************************************************/
     712             : void
     713             : fd_shredcap_manifest_seek_range( const char * capture_dir,
     714             :                                  char * manifest_buf,
     715             :                                  ulong start_slot,
     716             :                                  ulong end_slot,
     717             :                                  ulong * start_file_idx,
     718             :                                  ulong * end_file_idx,
     719           0 :                                  int * manifest_fd ) {
     720             : 
     721           0 :   char manifest_file_buf[ FD_SHREDCAP_CAPTURE_PATH_NAME_LENGTH ];
     722           0 :   fd_shredcap_concat( manifest_file_buf, capture_dir, "manifest" );
     723             : 
     724           0 :   *manifest_fd = open( manifest_file_buf, O_RDONLY, (mode_t)0 );
     725           0 :   if( FD_UNLIKELY( *manifest_fd == -1 ) ) {
     726           0 :     FD_LOG_WARNING(( "open(\"%s\",O_RDONLY,0) failed (%i-%s)",
     727           0 :                      manifest_file_buf, errno, fd_io_strerror( errno ) ));
     728           0 :     FD_LOG_ERR(( "unable to open manifest file for blockstore range" ));
     729           0 :   }
     730             : 
     731           0 :   ulong sz;
     732           0 :   int err;
     733           0 :   err = fd_io_read( *manifest_fd, manifest_buf, FD_SHREDCAP_MANIFEST_HDR_FOOTPRINT,
     734           0 :                     FD_SHREDCAP_MANIFEST_HDR_FOOTPRINT, &sz );
     735           0 :   if ( FD_UNLIKELY( err != 0 ) ) {
     736           0 :     FD_LOG_ERR(( "unable to read manifest header" ));
     737           0 :   }
     738           0 :   if ( FD_UNLIKELY( sz != FD_SHREDCAP_MANIFEST_HDR_FOOTPRINT ) ) {
     739           0 :     FD_LOG_ERR(( "read in size=%lu not equal to manifest header footprint=%lu",
     740           0 :                   sz, FD_SHREDCAP_MANIFEST_HDR_FOOTPRINT ));
     741           0 :   }
     742             : 
     743             :   /* Do basic checks on user input */
     744           0 :   fd_shredcap_manifest_hdr_t * manifest_hdr = (fd_shredcap_manifest_hdr_t*)manifest_buf;
     745           0 :   ulong num_files = manifest_hdr->num_files;
     746             : 
     747           0 :   if ( FD_UNLIKELY( start_slot < manifest_hdr->start_slot ) ) {
     748           0 :     FD_LOG_ERR(( "start_slot=%lu is less than the capture's first slot=%lu",
     749           0 :                  start_slot, manifest_hdr->start_slot ));
     750           0 :   }
     751           0 :   if ( FD_UNLIKELY( start_slot > manifest_hdr->end_slot ) ) {
     752           0 :     FD_LOG_ERR(( "start_slot=%lu is greater than the capture's last slot=%lu",
     753           0 :                  start_slot, manifest_hdr->start_slot ));
     754           0 :   }
     755           0 :   if ( FD_UNLIKELY( end_slot < manifest_hdr->start_slot ) ) {
     756           0 :     FD_LOG_ERR(( "end_slot=%lu is less than the capture's first slot=%lu",
     757           0 :                  end_slot, manifest_hdr->start_slot ));
     758           0 :   }
     759           0 :   if ( FD_UNLIKELY( end_slot > manifest_hdr->end_slot ) ) {
     760           0 :     FD_LOG_ERR(( "end_slot=%lu is greater than the capture's last slot=%lu",
     761           0 :                  end_slot, manifest_hdr->end_slot ));
     762           0 :   }
     763             : 
     764             :   /* Binary search through the manifest for the start_file */
     765           0 :   ulong left  = 0;
     766           0 :   ulong right = num_files - 1;
     767           0 :   while ( left < right ) {
     768           0 :     ulong middle = ( left + right ) / 2;
     769             :     /* Seek to correct offset */
     770           0 :     ulong middle_offset = middle * FD_SHREDCAP_MANIFEST_ENTRY_FOOTPRINT +
     771           0 :                           FD_SHREDCAP_MANIFEST_HDR_FOOTPRINT;
     772           0 :     long offset = lseek( *manifest_fd, (long)middle_offset, SEEK_SET );
     773           0 :     if ( FD_UNLIKELY( offset == -1 ) ) {
     774           0 :       FD_LOG_ERR(( "unable to lseek to manifest entry offset=%lu", middle_offset ));
     775           0 :     }
     776             : 
     777           0 :     err = fd_io_read( *manifest_fd, manifest_buf, FD_SHREDCAP_MANIFEST_ENTRY_FOOTPRINT,
     778           0 :                       FD_SHREDCAP_MANIFEST_ENTRY_FOOTPRINT, &sz );
     779           0 :     if ( FD_UNLIKELY( err != 0 ) ) {
     780           0 :       FD_LOG_ERR(( "unable to read manifest entry for file index=%lu", middle ));
     781           0 :     }
     782           0 :     if ( FD_UNLIKELY( sz != FD_SHREDCAP_MANIFEST_ENTRY_FOOTPRINT ) ) {
     783           0 :       FD_LOG_ERR(( "read in size=%lu not equal to manifest entry footprint=%lu",
     784           0 :                    sz, FD_SHREDCAP_MANIFEST_ENTRY_FOOTPRINT ));
     785           0 :     }
     786           0 :     fd_shredcap_manifest_entry_t * entry = (fd_shredcap_manifest_entry_t*)manifest_buf;
     787             : 
     788           0 :     if ( start_slot <= entry->end_slot ) {
     789           0 :       right = middle;
     790           0 :     }
     791           0 :     else {
     792           0 :       left = middle + 1;
     793           0 :     }
     794           0 :   }
     795           0 :   *start_file_idx = left;
     796             : 
     797             :   /* Repeat binary search for the end file */
     798           0 :   left  = 0;
     799           0 :   right = num_files - 1;
     800           0 :   while ( left < right ) {
     801           0 :     ulong middle = ( left + right ) / 2;
     802             :     /* Seek to correct offset */
     803           0 :     ulong middle_offset = middle * FD_SHREDCAP_MANIFEST_ENTRY_FOOTPRINT +
     804           0 :                           FD_SHREDCAP_MANIFEST_HDR_FOOTPRINT;
     805           0 :     long offset = lseek( *manifest_fd, (long)middle_offset, SEEK_SET );
     806           0 :     if ( FD_UNLIKELY( offset == -1 ) ) {
     807           0 :       FD_LOG_ERR(( "unable to lseek to manifest entry offset=%lu", middle_offset ));
     808           0 :     }
     809             : 
     810           0 :     err = fd_io_read( *manifest_fd, manifest_buf, FD_SHREDCAP_MANIFEST_ENTRY_FOOTPRINT,
     811           0 :                       FD_SHREDCAP_MANIFEST_ENTRY_FOOTPRINT, &sz );
     812           0 :     if ( FD_UNLIKELY( err != 0 ) ) {
     813           0 :       FD_LOG_ERR(( "unable to read manifest entry for file index=%lu", middle ));
     814           0 :     }
     815           0 :     if ( FD_UNLIKELY( sz != FD_SHREDCAP_MANIFEST_ENTRY_FOOTPRINT ) ) {
     816           0 :       FD_LOG_ERR(( "read in size=%lu not equal to manifest entry footprint=%lu",
     817           0 :                    sz, FD_SHREDCAP_MANIFEST_ENTRY_FOOTPRINT ));
     818           0 :     }
     819           0 :     fd_shredcap_manifest_entry_t * entry = (fd_shredcap_manifest_entry_t*)manifest_buf;
     820             : 
     821           0 :     if ( end_slot <= entry->end_slot ) {
     822           0 :       right = middle;
     823           0 :     }
     824           0 :     else {
     825           0 :       left = middle + 1;
     826           0 :     }
     827           0 :   }
     828           0 :   *end_file_idx = left;
     829           0 : }
     830             : 
     831             : void
     832             : fd_shredcap_bank_hash_seek_first( const char * capture_dir,
     833             :                                   char * bank_hash_buf,
     834             :                                   ulong start_slot,
     835             :                                   ulong end_slot,
     836             :                                   ulong * first_slot_idx,
     837           0 :                                   int * bank_hash_fd ) {
     838             : 
     839           0 :   char bank_hash_file_buf[ FD_SHREDCAP_CAPTURE_PATH_NAME_LENGTH ];
     840           0 :   fd_shredcap_concat( bank_hash_file_buf, capture_dir,"bank_hash" );
     841             : 
     842           0 :   *bank_hash_fd = open( bank_hash_file_buf, O_RDONLY, (mode_t)0 );
     843           0 :   if( FD_UNLIKELY( *bank_hash_fd == -1 ) ) {
     844           0 :     FD_LOG_WARNING(( "open(\"%s\",O_RDONLY,0) failed (%i-%s)",
     845           0 :                      bank_hash_file_buf, errno, fd_io_strerror( errno ) ));
     846           0 :     FD_LOG_ERR(( "unable to open bank hash file for blockstore range" ));
     847           0 :   }
     848             : 
     849           0 :   ulong sz;
     850           0 :   int err;
     851           0 :   err = fd_io_read( *bank_hash_fd, bank_hash_buf, FD_SHREDCAP_BANK_HASH_HDR_FOOTPRINT,
     852           0 :                     FD_SHREDCAP_BANK_HASH_HDR_FOOTPRINT, &sz );
     853           0 :   if ( FD_UNLIKELY( err != 0 ) ) {
     854           0 :     FD_LOG_ERR(( "unable to read bank hash header" ));
     855           0 :   }
     856           0 :   if ( FD_UNLIKELY( sz != FD_SHREDCAP_BANK_HASH_HDR_FOOTPRINT ) ) {
     857           0 :     FD_LOG_ERR(( "read in size=%lu not equal to bank hash header footprint=%lu",
     858           0 :                  sz, FD_SHREDCAP_BANK_HASH_HDR_FOOTPRINT ));
     859           0 :   }
     860             : 
     861             :   /* Do basic checks on user input */
     862           0 :   fd_shredcap_bank_hash_hdr_t * bank_hash_hdr = (fd_shredcap_bank_hash_hdr_t*)bank_hash_buf;
     863           0 :   ulong num_blocks = bank_hash_hdr->num_blocks;
     864             : 
     865             :   /* Leaving these as warnings because bank hashes aren't needed to populate a
     866             :      blockstore. This should really not be happening however. */
     867           0 :   if ( FD_UNLIKELY( start_slot < bank_hash_hdr->start_slot ) ) {
     868           0 :     FD_LOG_WARNING(( "start_slot=%lu is less than the bank_hash's first slot=%lu",
     869           0 :                  start_slot, bank_hash_hdr->start_slot ));
     870           0 :   }
     871           0 :   if ( FD_UNLIKELY( start_slot > bank_hash_hdr->end_slot ) ) {
     872           0 :     FD_LOG_ERR(( "start_slot=%lu is greater than the bank_hash's last slot=%lu",
     873           0 :                  start_slot, bank_hash_hdr->start_slot ));
     874           0 :   }
     875           0 :   if ( FD_UNLIKELY( end_slot < bank_hash_hdr->start_slot ) ) {
     876           0 :     FD_LOG_ERR(( "end_slot=%lu is less than the bank_hash's first slot=%lu",
     877           0 :                  end_slot, bank_hash_hdr->start_slot ));
     878           0 :   }
     879           0 :   if ( FD_UNLIKELY( end_slot > bank_hash_hdr->end_slot ) ) {
     880           0 :     FD_LOG_ERR(( "end_slot=%lu is greater than the bank_hash's last slot=%lu",
     881           0 :                  end_slot, bank_hash_hdr->start_slot ));
     882           0 :   }
     883             : 
     884             :   /* Binary search through the bank hash file */
     885           0 :   ulong left  = 0;
     886           0 :   ulong right = num_blocks - 1;
     887           0 :   while ( left < right ) {
     888           0 :     ulong middle = ( left + right ) / 2;
     889             :     /* Seek to correct offset*/
     890           0 :     ulong middle_offset = middle * FD_SHREDCAP_BANK_HASH_ENTRY_FOOTPRINT +
     891           0 :                           FD_SHREDCAP_BANK_HASH_HDR_FOOTPRINT;
     892           0 :     long offset = lseek( *bank_hash_fd, (long)middle_offset, SEEK_SET );
     893           0 :     if ( FD_UNLIKELY( offset == -1 ) ) {
     894           0 :       FD_LOG_ERR(( "unable to lseek to bank hash file offset=%ld", offset ));
     895           0 :     }
     896             : 
     897           0 :     err = fd_io_read( *bank_hash_fd, bank_hash_buf, FD_SHREDCAP_BANK_HASH_ENTRY_FOOTPRINT,
     898           0 :                       FD_SHREDCAP_BANK_HASH_ENTRY_FOOTPRINT, &sz );
     899           0 :     if ( FD_UNLIKELY( err != 0 ) ) {
     900           0 :       FD_LOG_ERR(( "unable to read bank hash entry at slot index=%lu", middle ));
     901           0 :     }
     902           0 :     if ( FD_UNLIKELY( sz != FD_SHREDCAP_BANK_HASH_ENTRY_FOOTPRINT ) ) {
     903           0 :       FD_LOG_ERR(( "read in size=%lu not equal to bank hash entry footprint=%lu",
     904           0 :                   sz, FD_SHREDCAP_BANK_HASH_ENTRY_FOOTPRINT ));
     905           0 :     }
     906             : 
     907           0 :     fd_shredcap_bank_hash_entry_t * entry = (fd_shredcap_bank_hash_entry_t*)bank_hash_buf;
     908           0 :     if ( entry->slot >= start_slot ) {
     909           0 :       right = middle;
     910           0 :     }
     911           0 :     else {
     912           0 :       left = middle + 1;
     913           0 :     }
     914           0 :   }
     915             : 
     916             :   /* left corresponds to the index in the bank hash file which is the smallest
     917             :      slot number greater than or equal to start_slot */
     918           0 :   *first_slot_idx = left;
     919           0 : }
     920             : 
     921             : void
     922             : fd_shredcap_populate_blockstore( const char *      capture_dir,
     923             :                                    fd_blockstore_t * blockstore,
     924             :                                    ulong             start_slot,
     925           0 :                                    ulong             end_slot ) {
     926           0 :   if ( FD_UNLIKELY( start_slot > end_slot ) ) {
     927           0 :     FD_LOG_ERR(( "start_slot=%lu must be less than the end_slot=%lu", start_slot, end_slot ));
     928           0 :   }
     929             : 
     930             :   /* Get start file idx from the manifest */
     931           0 :   char manifest_buf[ MANIFEST_BUF_FOOTPRINT ];
     932           0 :   ulong start_file_idx;
     933           0 :   ulong end_file_idx;
     934           0 :   int manifest_fd;
     935           0 :   fd_shredcap_manifest_seek_range( capture_dir, manifest_buf, start_slot, end_slot,
     936           0 :                                    &start_file_idx, &end_file_idx, &manifest_fd );
     937             : 
     938             :   /* Get first relevant slot and idx from the bank hash file */
     939           0 :   char bank_hash_buf[ BANK_HASH_BUF_FOOTPRINT ];
     940           0 :   ulong first_slot_idx;
     941           0 :   int bank_hash_fd;
     942           0 :   fd_shredcap_bank_hash_seek_first( capture_dir, bank_hash_buf, start_slot, end_slot,
     943           0 :                                     &first_slot_idx, &bank_hash_fd );
     944           0 :   ulong cur_bank_hash_slot_idx = first_slot_idx;
     945             : 
     946           0 :   char capture_buf[ RBUF_FOOTPRINT ];
     947             : 
     948           0 :   ulong sz;
     949           0 :   int err;
     950           0 :   long offset;
     951             : 
     952             :   /* Open and iterate through as many files as necesary to build up blockstore */
     953           0 :   for ( ulong file_idx = start_file_idx; file_idx <= end_file_idx; ++file_idx ) {
     954           0 :     ulong file_offset = file_idx * FD_SHREDCAP_MANIFEST_ENTRY_FOOTPRINT +
     955           0 :                         FD_SHREDCAP_MANIFEST_HDR_FOOTPRINT;
     956           0 :     offset = lseek( manifest_fd, (long)file_offset, SEEK_SET );
     957           0 :     if ( FD_UNLIKELY( offset == -1 ) ) {
     958           0 :       FD_LOG_ERR(( "unable to seek to offset=%lu in manifest", file_offset ));
     959           0 :     }
     960             : 
     961           0 :     err = fd_io_read( manifest_fd, manifest_buf, FD_SHREDCAP_MANIFEST_ENTRY_FOOTPRINT,
     962           0 :                       FD_SHREDCAP_MANIFEST_ENTRY_FOOTPRINT, &sz );
     963           0 :     if ( FD_UNLIKELY( err ) ) {
     964           0 :       FD_LOG_ERR(( "error when reading manifest entry" ));
     965           0 :     }
     966           0 :     if ( FD_UNLIKELY( sz != FD_SHREDCAP_MANIFEST_ENTRY_FOOTPRINT ) ) {
     967           0 :       FD_LOG_ERR(( "unexpected size read=%lu for manifest entry", sz ));
     968           0 :     }
     969             : 
     970           0 :     fd_shredcap_manifest_entry_t * entry = (fd_shredcap_manifest_entry_t*)manifest_buf;
     971             : 
     972           0 :     char file_path_buf[ FD_SHREDCAP_CAPTURE_PATH_NAME_LENGTH ];
     973           0 :     fd_memset( file_path_buf, '\0', FD_SHREDCAP_CAPTURE_PATH_NAME_LENGTH );
     974           0 :     fd_cstr_append_text( file_path_buf, capture_dir, strlen( capture_dir ) );
     975           0 :     fd_cstr_append_cstr( file_path_buf + strlen( capture_dir ), entry->path );
     976             : 
     977           0 :     int capture_fd = open( file_path_buf, O_RDONLY, (mode_t)0 );
     978           0 :     if( FD_UNLIKELY( capture_fd == -1 ) ) {
     979           0 :       FD_LOG_WARNING(( "open(\"%s\",O_RDONLY,0) failed (%i-%s)",
     980           0 :                        file_path_buf, errno, fd_io_strerror( errno ) ));
     981           0 :       FD_LOG_ERR(( "unable to open capture file for blockstore range" ));
     982           0 :     }
     983             : 
     984           0 :     err = fd_io_read( capture_fd, capture_buf, FD_SHREDCAP_FILE_HDR_FOOTPRINT,
     985           0 :                       FD_SHREDCAP_FILE_HDR_FOOTPRINT, &sz );
     986           0 :     if ( FD_UNLIKELY( err ) ) {
     987           0 :       FD_LOG_ERR(( "error when reading shredcap file header" ));
     988           0 :     }
     989           0 :     if ( FD_UNLIKELY( sz != FD_SHREDCAP_FILE_HDR_FOOTPRINT ) ) {
     990           0 :       FD_LOG_ERR(( "unexpected size read=%lu for capture file header", sz ));
     991           0 :     }
     992           0 :     fd_shredcap_file_hdr_t * file_hdr = (fd_shredcap_file_hdr_t*)capture_buf;
     993           0 :     FD_TEST((file_hdr->magic == FD_SHREDCAP_FILE_MAGIC));
     994             : 
     995           0 :     ulong cur_slot      = file_hdr->start_slot;
     996           0 :     ulong file_end_slot = file_hdr->end_slot;
     997             : 
     998           0 :     while ( cur_slot < file_end_slot ) {
     999             :       /* Read in block header */
    1000           0 :       err = fd_io_read( capture_fd, capture_buf, FD_SHREDCAP_SLOT_HDR_FOOTPRINT,
    1001           0 :                         FD_SHREDCAP_SLOT_HDR_FOOTPRINT, &sz );
    1002           0 :       if ( FD_UNLIKELY( err ) ) {
    1003           0 :         FD_LOG_ERR(( "error when reading shredcap slot header" ));
    1004           0 :       }
    1005           0 :       if ( FD_UNLIKELY( sz != FD_SHREDCAP_SLOT_HDR_FOOTPRINT ) ) {
    1006           0 :         FD_LOG_ERR(( "unexpected size read=%lu for capture slot header", sz ));
    1007           0 :       }
    1008             : 
    1009           0 :       fd_shredcap_slot_hdr_t * slot_hdr = (fd_shredcap_slot_hdr_t*)capture_buf;
    1010           0 :       cur_slot = slot_hdr->slot;
    1011           0 :       ulong max_idx = slot_hdr->received;
    1012           0 :       FD_TEST((slot_hdr->magic == FD_SHREDCAP_SLOT_HDR_MAGIC));
    1013           0 :       if ( cur_slot > end_slot ) {
    1014           0 :         break;
    1015           0 :       }
    1016             : 
    1017           0 :       if ( cur_slot < start_slot ) {
    1018             :         /* Skip forward to next slot*/
    1019           0 :         offset = lseek( capture_fd, (long)(slot_hdr->payload_sz + FD_SHREDCAP_SLOT_FTR_FOOTPRINT), SEEK_CUR );
    1020           0 :         if ( FD_UNLIKELY( offset == -1 ) ) {
    1021           0 :           FD_LOG_ERR(( "unable to lseek to next slot entry from slot=%lu", cur_slot ));
    1022           0 :         }
    1023           0 :         continue;
    1024           0 :       }
    1025             : 
    1026             :       /* Read in shreds and assemble */
    1027           0 :       for ( ulong shred_idx = 0; shred_idx < max_idx; ++shred_idx ) {
    1028           0 :         err = fd_io_read( capture_fd, capture_buf, FD_SHREDCAP_SHRED_HDR_FOOTPRINT,
    1029           0 :                           FD_SHREDCAP_SHRED_HDR_FOOTPRINT, &sz );
    1030           0 :         if ( FD_UNLIKELY( err ) ) {
    1031           0 :           FD_LOG_ERR(( "error when reading shredcap shred header" ));
    1032           0 :         }
    1033           0 :         if ( FD_UNLIKELY( sz != FD_SHREDCAP_SHRED_HDR_FOOTPRINT ) ) {
    1034           0 :           FD_LOG_ERR(( "unexpected size read=%lu for shred header", sz ));
    1035           0 :         }
    1036             : 
    1037           0 :         fd_shredcap_shred_hdr_t * shred_hdr = (fd_shredcap_shred_hdr_t*)capture_buf;
    1038           0 :         ulong shred_boundary_sz = shred_hdr->shred_boundary_sz;
    1039           0 :         FD_TEST((shred_hdr->hdr_sz == FD_SHREDCAP_SHRED_HDR_FOOTPRINT));
    1040           0 :         err = fd_io_read( capture_fd, capture_buf, shred_boundary_sz, shred_boundary_sz, &sz );
    1041           0 :         if ( FD_UNLIKELY( err ) ) {
    1042           0 :           FD_LOG_ERR(( "error when reading shredcap shred for slot=%lu", cur_slot ));
    1043           0 :         }
    1044           0 :         if ( FD_UNLIKELY( sz != shred_boundary_sz ) ) {
    1045           0 :           FD_LOG_ERR(( "unexpected size read=%lu for shred", sz ));
    1046           0 :         }
    1047             : 
    1048           0 :         fd_shred_t * shred = (fd_shred_t*)capture_buf;
    1049           0 :         fd_buf_shred_insert( blockstore, shred );
    1050           0 :       }
    1051             : 
    1052           0 :       offset = lseek( capture_fd, (long)FD_SHREDCAP_SLOT_FTR_FOOTPRINT, SEEK_CUR );
    1053           0 :       if ( FD_UNLIKELY( offset == -1 ) ) {
    1054           0 :         FD_LOG_ERR(( "unable to lseek past slot footer for slot=%lu", cur_slot ));
    1055           0 :       }
    1056             : 
    1057             :       /* Populate bank hash for each slot */
    1058           0 :       ulong cur_bank_hash_slot_offset = cur_bank_hash_slot_idx * FD_SHREDCAP_BANK_HASH_ENTRY_FOOTPRINT +
    1059           0 :                                 FD_SHREDCAP_BANK_HASH_HDR_FOOTPRINT;
    1060           0 :       offset = lseek( bank_hash_fd, (long)cur_bank_hash_slot_offset, SEEK_SET );
    1061           0 :       if ( FD_UNLIKELY( offset == -1 ) ) {
    1062           0 :         FD_LOG_ERR(( "unable to lseek to bank hash_slot at index=%lu", cur_bank_hash_slot_idx ));
    1063           0 :       }
    1064             : 
    1065           0 :       err = fd_io_read( bank_hash_fd, bank_hash_buf, FD_SHREDCAP_BANK_HASH_ENTRY_FOOTPRINT,
    1066           0 :                         FD_SHREDCAP_BANK_HASH_ENTRY_FOOTPRINT, &sz );
    1067           0 :       if ( FD_UNLIKELY( err ) ) {
    1068           0 :         FD_LOG_ERR(( "error when reading bank hash entry" ));
    1069           0 :       }
    1070           0 :       if ( FD_UNLIKELY( sz != FD_SHREDCAP_BANK_HASH_ENTRY_FOOTPRINT ) ) {
    1071           0 :         FD_LOG_ERR(( "unexpected size read=%lu for bank hash entry", sz ));
    1072           0 :       }
    1073             : 
    1074           0 :       fd_shredcap_bank_hash_entry_t * entry = (fd_shredcap_bank_hash_entry_t*)bank_hash_buf;
    1075           0 :       fd_block_map_t * block = fd_blockstore_block_map_query( blockstore, cur_slot );
    1076           0 :       if ( FD_LIKELY( block ) ) {
    1077           0 :         fd_memcpy( block->bank_hash.hash, &entry->bank_hash.hash, 32UL );
    1078           0 :       }
    1079             : 
    1080           0 :       ++cur_bank_hash_slot_idx;
    1081           0 :     }
    1082             : 
    1083           0 :     if ( FD_UNLIKELY( close( capture_fd ) ) ) {
    1084           0 :       FD_LOG_ERR(( "unable to close the capture file=%s", file_path_buf ));
    1085           0 :     }
    1086           0 :     if ( cur_slot > end_slot ) {
    1087           0 :       break;
    1088           0 :     }
    1089           0 :   }
    1090           0 :   if ( FD_UNLIKELY( close( manifest_fd ) ) ) {
    1091           0 :     FD_LOG_ERR(( "unable to close the manifest file" ));
    1092           0 :   }
    1093           0 :   if ( FD_UNLIKELY( close( bank_hash_fd ) ) ) {
    1094           0 :     FD_LOG_ERR(( "unable to close the bank hash file" ));
    1095           0 :   }
    1096           0 : }

Generated by: LCOV version 1.14