Line data Source code
1 : #ifndef HEADER_fd_src_disco_verify_fd_verify_tile_h 2 : #define HEADER_fd_src_disco_verify_fd_verify_tile_h 3 : 4 : /* The verify tile verifies that the cryptographic signatures of 5 : incoming transactions match the data being signed. Transactions with 6 : invalid signatures are filtered out of the frag stream. */ 7 : 8 : #include "../topo/fd_topo.h" 9 : #include "../../ballet/txn/fd_txn.h" 10 : #include "../../ballet/sha512/fd_sha512.h" 11 : #include "../../ballet/ed25519/fd_ed25519.h" 12 : #include "../metrics/generated/fd_metrics_enums.h" 13 : 14 0 : #define FD_TXN_VERIFY_SUCCESS 0 15 0 : #define FD_TXN_VERIFY_FAILED -1 16 0 : #define FD_TXN_VERIFY_DEDUP -2 17 : 18 : /* Signer precomputation cache entries per verify tile (gossip votes 19 : are signed by ~1.5k vote authorities) */ 20 0 : #define FD_VERIFY_ED25519_CACHE_ENT_CNT (2048UL) 21 : 22 : extern fd_topo_run_tile_t fd_tile_verify; 23 : 24 : /* fd_verify_in_ctx_t is a context object for each in (producer) mcache 25 : connected to the verify tile. */ 26 : 27 : typedef struct { 28 : fd_wksp_t * mem; 29 : ulong chunk0; 30 : ulong wmark; 31 : } fd_verify_in_ctx_t; 32 : 33 : typedef struct { 34 : /* TODO switch to fd_sha512_batch_t? */ 35 : fd_sha512_t * sha[ FD_TXN_SIG_MAX ]; 36 : 37 : fd_ed25519_cache_t * ed25519_cache; 38 : 39 : int bundle_failed; 40 : ulong bundle_id; 41 : 42 : ulong round_robin_idx; 43 : ulong round_robin_cnt; 44 : 45 : ulong tcache_depth; 46 : ulong tcache_map_cnt; 47 : ulong * tcache_sync; 48 : ulong * tcache_ring; 49 : ulong * tcache_map; 50 : 51 : ulong in_kind[ 32 ]; 52 : fd_verify_in_ctx_t in[ 32 ]; 53 : 54 : fd_wksp_t * out_mem; 55 : ulong out_chunk0; 56 : ulong out_wmark; 57 : ulong out_chunk; 58 : 59 : ulong hashmap_seed; 60 : 61 : struct { 62 : ulong verify_tile_result[ FD_METRICS_ENUM_VERIFY_RESULT_CNT ]; 63 : ulong gossiped_votes_cnt; 64 : ulong own_votes_cnt; 65 : } metrics; 66 : } fd_verify_ctx_t; 67 : 68 : static inline int 69 : fd_txn_verify( fd_verify_ctx_t * ctx, 70 : uchar const * udp_payload, 71 : ushort const payload_sz, 72 : fd_txn_t const * txn, 73 : int dedup, 74 0 : ulong * opt_sig ) { 75 : 76 : /* We do not want to deref any non-data field from the txn struct more than once */ 77 0 : uchar signature_cnt = txn->signature_cnt; 78 0 : ushort signature_off = txn->signature_off; 79 0 : ushort acct_addr_off = txn->acct_addr_off; 80 0 : ushort message_off = txn->message_off; 81 : 82 0 : uchar const * signatures = udp_payload + signature_off; 83 0 : uchar const * pubkeys = udp_payload + acct_addr_off; 84 0 : uchar const * msg = udp_payload + message_off; 85 0 : ulong msg_sz = fd_txn_msg_sz( txn, (ulong)payload_sz ); 86 : 87 : /* The first signature is the transaction id, i.e. a unique identifier. 88 : So use this to do a quick dedup of ha traffic. */ 89 : 90 0 : ulong ha_dedup_tag = fd_hash( ctx->hashmap_seed, signatures, 64UL ); 91 0 : int ha_dup = 0; 92 0 : if( FD_LIKELY( dedup ) ) { 93 0 : FD_FN_UNUSED ulong tcache_map_idx = 0; /* ignored */ 94 0 : FD_TCACHE_QUERY( ha_dup, tcache_map_idx, ctx->tcache_map, ctx->tcache_map_cnt, ha_dedup_tag ); 95 0 : if( FD_UNLIKELY( ha_dup ) ) { 96 0 : return FD_TXN_VERIFY_DEDUP; 97 0 : } 98 0 : } 99 : 100 : /* Verify signatures */ 101 0 : int res = fd_ed25519_verify_batch_single_msg_cached( msg, msg_sz, signatures, pubkeys, ctx->sha, signature_cnt, ctx->ed25519_cache ); 102 0 : if( FD_UNLIKELY( res != FD_ED25519_SUCCESS ) ) { 103 0 : return FD_TXN_VERIFY_FAILED; 104 0 : } 105 : 106 : /* Insert into the tcache to dedup ha traffic. 107 : The dedup check is repeated to guard against duped txs verifying signatures at the same time */ 108 0 : if( FD_LIKELY( dedup ) ) { 109 0 : FD_TCACHE_INSERT( ha_dup, *ctx->tcache_sync, ctx->tcache_ring, ctx->tcache_depth, ctx->tcache_map, ctx->tcache_map_cnt, ha_dedup_tag ); 110 0 : if( FD_UNLIKELY( ha_dup ) ) { 111 0 : return FD_TXN_VERIFY_DEDUP; 112 0 : } 113 0 : } 114 : 115 0 : *opt_sig = ha_dedup_tag; 116 0 : return FD_TXN_VERIFY_SUCCESS; 117 0 : } 118 : 119 : #endif /* HEADER_fd_src_disco_verify_fd_verify_tile_h */