LCOV - code coverage report
Current view: top level - flamenco/runtime - fd_bank_hash_cmp.c (source / functions) Hit Total Coverage
Test: cov.lcov Lines: 0 182 0.0 %
Date: 2025-10-13 04:42:14 Functions: 0 8 0.0 %

          Line data    Source code
       1             : #include "fd_bank_hash_cmp.h"
       2             : #include <unistd.h>
       3             : 
       4             : void *
       5           0 : fd_bank_hash_cmp_new( void * mem ) {
       6             : 
       7           0 :   if( FD_UNLIKELY( !mem ) ) {
       8           0 :     FD_LOG_WARNING( ( "NULL mem" ) );
       9           0 :     return NULL;
      10           0 :   }
      11             : 
      12           0 :   if( FD_UNLIKELY( !fd_ulong_is_aligned( (ulong)mem, fd_bank_hash_cmp_align() ) ) ) {
      13           0 :     FD_LOG_WARNING( ( "misaligned mem" ) );
      14           0 :     return NULL;
      15           0 :   }
      16             : 
      17           0 :   ulong footprint = fd_bank_hash_cmp_footprint();
      18             : 
      19           0 :   fd_memset( mem, 0, footprint );
      20             : 
      21           0 :   ulong laddr = (ulong)mem;
      22           0 :   laddr += sizeof( fd_bank_hash_cmp_t );
      23             : 
      24           0 :   laddr = fd_ulong_align_up( laddr, fd_bank_hash_cmp_map_align() );
      25           0 :   fd_bank_hash_cmp_map_new( (void *)laddr );
      26           0 :   fd_bank_hash_cmp_set_map_offset( (fd_bank_hash_cmp_t *)mem, (uchar *)laddr );
      27           0 :   laddr += fd_bank_hash_cmp_map_footprint();
      28             : 
      29           0 :   laddr = fd_ulong_align_up( laddr, fd_bank_hash_cmp_align() );
      30           0 :   FD_TEST( laddr == (ulong)mem + fd_bank_hash_cmp_footprint() );
      31             : 
      32           0 :   return mem;
      33           0 : }
      34             : 
      35             : fd_bank_hash_cmp_t *
      36           0 : fd_bank_hash_cmp_join( void * bank_hash_cmp ) {
      37           0 :   if( FD_UNLIKELY( !bank_hash_cmp ) ) {
      38           0 :     FD_LOG_WARNING(( "NULL bank_hash_cmp" ));
      39           0 :     return NULL;
      40           0 :   }
      41             : 
      42           0 :   if( FD_UNLIKELY( !fd_ulong_is_aligned( (ulong)bank_hash_cmp, fd_bank_hash_cmp_align() ) ) ) {
      43           0 :     FD_LOG_WARNING(( "misaligned bank_hash_cmp" ));
      44           0 :     return NULL;
      45           0 :   }
      46             : 
      47           0 :   ulong laddr = (ulong)bank_hash_cmp;
      48           0 :   laddr += sizeof( fd_bank_hash_cmp_t );
      49             : 
      50           0 :   fd_bank_hash_cmp_entry_t * map_entry = fd_bank_hash_cmp_map_join( (void *)laddr );
      51           0 :   if( FD_UNLIKELY( !map_entry ) ) {
      52           0 :     FD_LOG_WARNING(( "invalid entry map" ));
      53           0 :     return NULL;
      54           0 :   }
      55             : 
      56           0 :   return bank_hash_cmp;
      57           0 : }
      58             : 
      59             : void *
      60           0 : fd_bank_hash_cmp_leave( fd_bank_hash_cmp_t const * bank_hash_cmp ) {
      61             : 
      62           0 :   if( FD_UNLIKELY( !bank_hash_cmp ) ) {
      63           0 :     FD_LOG_WARNING( ( "NULL bank_hash_cmp" ) );
      64           0 :     return NULL;
      65           0 :   }
      66             : 
      67           0 :   return (void *)bank_hash_cmp;
      68           0 : }
      69             : 
      70             : void *
      71           0 : fd_bank_hash_cmp_delete( void * bank_hash_cmp ) {
      72             : 
      73           0 :   if( FD_UNLIKELY( !bank_hash_cmp ) ) {
      74           0 :     FD_LOG_WARNING( ( "NULL bank_hash_cmp" ) );
      75           0 :     return NULL;
      76           0 :   }
      77             : 
      78           0 :   if( FD_UNLIKELY( !fd_ulong_is_aligned( (ulong)bank_hash_cmp, fd_bank_hash_cmp_align() ) ) ) {
      79           0 :     FD_LOG_WARNING( ( "misaligned bank_hash_cmp" ) );
      80           0 :     return NULL;
      81           0 :   }
      82             : 
      83           0 :   return bank_hash_cmp;
      84           0 : }
      85             : 
      86             : void
      87           0 : fd_bank_hash_cmp_lock( fd_bank_hash_cmp_t * bank_hash_cmp ) {
      88           0 :   volatile int * lock = &bank_hash_cmp->lock;
      89           0 : # if FD_HAS_THREADS
      90           0 :   for( ;; ) {
      91           0 :     if( FD_LIKELY( !FD_ATOMIC_CAS( lock, 0UL, 1UL ) ) ) break;
      92           0 :     FD_SPIN_PAUSE();
      93           0 :   }
      94             : # else
      95             :   *lock = 1;
      96             : # endif
      97           0 :   FD_COMPILER_MFENCE();
      98           0 : }
      99             : 
     100             : void
     101           0 : fd_bank_hash_cmp_unlock( fd_bank_hash_cmp_t * bank_hash_cmp ) {
     102           0 :   volatile int * lock = &bank_hash_cmp->lock;
     103           0 :   FD_COMPILER_MFENCE();
     104           0 :   FD_VOLATILE( *lock ) = 0UL;
     105           0 : }
     106             : 
     107             : void
     108             : fd_bank_hash_cmp_insert( fd_bank_hash_cmp_t * bank_hash_cmp,
     109             :                          ulong                slot,
     110             :                          fd_hash_t const *    hash,
     111             :                          int                  ours,
     112           0 :                          ulong                stake ) {
     113           0 :   fd_bank_hash_cmp_entry_t * map = fd_bank_hash_cmp_get_map( bank_hash_cmp );
     114             : 
     115           0 :   if( FD_UNLIKELY( slot <= bank_hash_cmp->watermark ) ) { return; }
     116           0 :   fd_bank_hash_cmp_entry_t * cmp = fd_bank_hash_cmp_map_query( map, slot, NULL );
     117             : 
     118           0 :   if( !cmp ) {
     119             : 
     120             :     /* If full, make room for new bank hashes */
     121             : 
     122           0 :     if( FD_UNLIKELY( bank_hash_cmp->cnt == fd_bank_hash_cmp_map_key_max() ) ) {
     123           0 :       FD_LOG_WARNING( ( "Bank matches unexpectedly full. Clearing. " ) );
     124           0 :       for( ulong i = 0; i < fd_bank_hash_cmp_map_slot_cnt(); i++ ) {
     125           0 :         fd_bank_hash_cmp_entry_t * entry = &map[i];
     126           0 :         if( FD_LIKELY( !fd_bank_hash_cmp_map_key_inval( entry->slot ) &&
     127           0 :                        entry->slot < bank_hash_cmp->watermark ) ) {
     128           0 :           fd_bank_hash_cmp_map_remove( map, entry );
     129           0 :           bank_hash_cmp->cnt--;
     130           0 :         }
     131           0 :       }
     132           0 :     }
     133             : 
     134           0 :     cmp      = fd_bank_hash_cmp_map_insert( map, slot );
     135           0 :     cmp->cnt = 0;
     136           0 :     bank_hash_cmp->cnt++;
     137           0 :   }
     138             : 
     139           0 :   if( FD_UNLIKELY( ours ) ) {
     140           0 :     cmp->ours = *hash;
     141           0 :     return;
     142           0 :   }
     143             : 
     144           0 :   for( ulong i = 0; i < cmp->cnt; i++ ) {
     145           0 :     if( FD_LIKELY( 0 == memcmp( &cmp->theirs[i], hash, sizeof( fd_hash_t ) ) ) ) {
     146           0 :       cmp->stakes[i] += stake;
     147           0 :       return;
     148           0 :     }
     149           0 :   }
     150             : 
     151           0 :   ulong max = sizeof( cmp->stakes ) / sizeof( ulong );
     152           0 :   if( FD_UNLIKELY( cmp->cnt == max ) ) {
     153           0 :     if( !cmp->overflow ) {
     154           0 :       FD_LOG_WARNING(( "[Bank Hash Comparison] more than %lu equivocating hashes for slot %lu. "
     155           0 :                        "new hash: %s. ignoring.",
     156           0 :                        max,
     157           0 :                        slot,
     158           0 :                        FD_BASE58_ENC_32_ALLOCA( hash ) ));
     159           0 :       cmp->overflow = 1;
     160           0 :     }
     161           0 :     return;
     162           0 :   }
     163           0 :   cmp->cnt++;
     164           0 :   cmp->theirs[cmp->cnt - 1] = *hash;
     165           0 :   cmp->stakes[cmp->cnt - 1] = stake;
     166           0 :   if( FD_UNLIKELY( cmp->cnt > 1 ) ) {
     167           0 :     for( ulong i = 0; i < cmp->cnt; i++ ) {
     168           0 :       FD_LOG_WARNING(( "slot: %lu. equivocating hash (#%lu): %s. stake: %lu",
     169           0 :                         cmp->slot,
     170           0 :                         i,
     171           0 :                         FD_BASE58_ENC_32_ALLOCA( cmp->theirs[i].hash ),
     172           0 :                         cmp->stakes[i] ));
     173           0 :     }
     174           0 :   }
     175           0 : }
     176             : 
     177             : int
     178           0 : fd_bank_hash_cmp_check( fd_bank_hash_cmp_t * bank_hash_cmp, ulong slot ) {
     179           0 :   fd_bank_hash_cmp_entry_t * map = fd_bank_hash_cmp_get_map( bank_hash_cmp );
     180             : 
     181           0 :   fd_bank_hash_cmp_entry_t * cmp = fd_bank_hash_cmp_map_query( map, slot, NULL );
     182             : 
     183           0 :   if( FD_UNLIKELY( !cmp ) ) return 0;
     184             : 
     185           0 :   fd_hash_t null_hash = { 0 };
     186           0 :   if( FD_LIKELY( 0 == memcmp( &cmp->ours, &null_hash, sizeof( fd_hash_t ) ) ) ) return 0;
     187             : 
     188           0 :   if( FD_UNLIKELY( cmp->cnt == 0 ) ) return 0;
     189             : 
     190           0 :   fd_hash_t * theirs = &cmp->theirs[0];
     191           0 :   ulong       stake  = cmp->stakes[0];
     192           0 :   for( ulong i = 1; i < cmp->cnt; i++ ) {
     193           0 :     if( FD_UNLIKELY( cmp->stakes[i] > stake ) ) {
     194           0 :       theirs = &cmp->theirs[i];
     195           0 :       stake  = cmp->stakes[i];
     196           0 :     }
     197           0 :   }
     198             : 
     199           0 :   double pct = (double)stake / (double)bank_hash_cmp->total_stake;
     200           0 :   if( FD_LIKELY( pct > 0.52 ) ) {
     201           0 :     if( FD_UNLIKELY( 0 != memcmp( &cmp->ours, theirs, sizeof( fd_hash_t ) ) ) ) {
     202           0 :       FD_LOG_WARNING(( "\n\n[Bank Hash Comparison]\n"
     203           0 :                         "slot:   %lu\n"
     204           0 :                         "ours:   %s\n"
     205           0 :                         "theirs: %s\n"
     206           0 :                         "stake:  %.0lf%%\n"
     207           0 :                         "result: mismatch!\n",
     208           0 :                         cmp->slot,
     209           0 :                         FD_BASE58_ENC_32_ALLOCA( cmp->ours.hash ),
     210           0 :                         FD_BASE58_ENC_32_ALLOCA( theirs->hash ),
     211           0 :                         pct * 100 ));
     212           0 :       if( FD_UNLIKELY( cmp->cnt > 1 ) ) {
     213           0 :         for( ulong i = 0; i < cmp->cnt; i++ ) {
     214           0 :           FD_LOG_WARNING(( "slot: %lu. hash (#%lu): %s. stake: %lu",
     215           0 :                            cmp->slot,
     216           0 :                            i,
     217           0 :                            FD_BASE58_ENC_32_ALLOCA( cmp->theirs[i].hash ),
     218           0 :                            cmp->stakes[i] ));
     219           0 :         }
     220           0 :       }
     221           0 :       return -1;
     222           0 :     } else {
     223           0 :       FD_LOG_INFO(( "\n\n[Bank Hash Comparison]\n"
     224           0 :                     "slot:   %lu\n"
     225           0 :                     "ours:   %s\n"
     226           0 :                     "theirs: %s\n"
     227           0 :                     "stake:  %.0lf%%\n"
     228           0 :                     "result: match!\n",
     229           0 :                     cmp->slot,
     230           0 :                     FD_BASE58_ENC_32_ALLOCA( cmp->ours.hash ),
     231           0 :                     FD_BASE58_ENC_32_ALLOCA( theirs->hash ),
     232           0 :                     pct * 100 ));
     233           0 :     }
     234           0 :     fd_bank_hash_cmp_map_remove( map, cmp );
     235           0 :     bank_hash_cmp->cnt--;
     236           0 :     return 1;
     237           0 :   }
     238           0 :   return 0;
     239           0 : }

Generated by: LCOV version 1.14