LCOV - code coverage report
Current view: top level - flamenco/shredcap - fd_shredcap.c (source / functions) Hit Total Coverage
Test: cov.lcov Lines: 0 860 0.0 %
Date: 2025-01-08 12:08:44 Functions: 0 9 0.0 %

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

Generated by: LCOV version 1.14