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 "../metrics/generated/fd_metrics_enums.h" 12 : 13 21 : #define FD_TXN_VERIFY_SUCCESS 0 14 21 : #define FD_TXN_VERIFY_FAILED -1 15 15 : #define FD_TXN_VERIFY_DEDUP -2 16 : 17 : extern fd_topo_run_tile_t fd_tile_verify; 18 : 19 : /* fd_verify_in_ctx_t is a context object for each in (producer) mcache 20 : connected to the verify tile. */ 21 : 22 : typedef struct { 23 : fd_wksp_t * mem; 24 : ulong chunk0; 25 : ulong wmark; 26 : } fd_verify_in_ctx_t; 27 : 28 : typedef struct { 29 : /* TODO switch to fd_sha512_batch_t? */ 30 : fd_sha512_t * sha[ FD_TXN_SIG_MAX ]; 31 : 32 : int bundle_failed; 33 : ulong bundle_id; 34 : 35 : ulong round_robin_idx; 36 : ulong round_robin_cnt; 37 : 38 : ulong tcache_depth; 39 : ulong tcache_map_cnt; 40 : ulong * tcache_sync; 41 : ulong * tcache_ring; 42 : ulong * tcache_map; 43 : 44 : ulong in_kind[ 32 ]; 45 : fd_verify_in_ctx_t in[ 32 ]; 46 : 47 : fd_wksp_t * out_mem; 48 : ulong out_chunk0; 49 : ulong out_wmark; 50 : ulong out_chunk; 51 : 52 : ulong hashmap_seed; 53 : 54 : struct { 55 : ulong verify_tile_result[ FD_METRICS_ENUM_VERIFY_TILE_RESULT_CNT ]; 56 : ulong gossiped_votes_cnt; 57 : } metrics; 58 : } fd_verify_ctx_t; 59 : 60 : static inline int 61 : fd_txn_verify( fd_verify_ctx_t * ctx, 62 : uchar const * udp_payload, 63 : ushort const payload_sz, 64 : fd_txn_t const * txn, 65 : int dedup, 66 57 : ulong * opt_sig ) { 67 : 68 : /* We do not want to deref any non-data field from the txn struct more than once */ 69 57 : uchar signature_cnt = txn->signature_cnt; 70 57 : ushort signature_off = txn->signature_off; 71 57 : ushort acct_addr_off = txn->acct_addr_off; 72 57 : ushort message_off = txn->message_off; 73 : 74 57 : uchar const * signatures = udp_payload + signature_off; 75 57 : uchar const * pubkeys = udp_payload + acct_addr_off; 76 57 : uchar const * msg = udp_payload + message_off; 77 57 : ulong msg_sz = fd_txn_msg_sz( txn, (ulong)payload_sz ); 78 : 79 : /* The first signature is the transaction id, i.e. a unique identifier. 80 : So use this to do a quick dedup of ha traffic. */ 81 : 82 57 : ulong ha_dedup_tag = fd_hash( ctx->hashmap_seed, signatures, 64UL ); 83 57 : int ha_dup = 0; 84 57 : if( FD_LIKELY( dedup ) ) { 85 48 : FD_FN_UNUSED ulong tcache_map_idx = 0; /* ignored */ 86 48 : FD_TCACHE_QUERY( ha_dup, tcache_map_idx, ctx->tcache_map, ctx->tcache_map_cnt, ha_dedup_tag ); 87 48 : if( FD_UNLIKELY( ha_dup ) ) { 88 15 : return FD_TXN_VERIFY_DEDUP; 89 15 : } 90 48 : } 91 : 92 : /* Verify signatures */ 93 42 : int res = fd_ed25519_verify_batch_single_msg( msg, msg_sz, signatures, pubkeys, ctx->sha, signature_cnt ); 94 42 : if( FD_UNLIKELY( res != FD_ED25519_SUCCESS ) ) { 95 21 : return FD_TXN_VERIFY_FAILED; 96 21 : } 97 : 98 : /* Insert into the tcache to dedup ha traffic. 99 : The dedup check is repeated to guard against duped txs verifying signatures at the same time */ 100 21 : if( FD_LIKELY( dedup ) ) { 101 15 : FD_TCACHE_INSERT( ha_dup, *ctx->tcache_sync, ctx->tcache_ring, ctx->tcache_depth, ctx->tcache_map, ctx->tcache_map_cnt, ha_dedup_tag ); 102 15 : if( FD_UNLIKELY( ha_dup ) ) { 103 0 : return FD_TXN_VERIFY_DEDUP; 104 0 : } 105 15 : } 106 : 107 21 : *opt_sig = ha_dedup_tag; 108 21 : return FD_TXN_VERIFY_SUCCESS; 109 21 : } 110 : 111 : #endif /* HEADER_fd_src_disco_verify_fd_verify_tile_h */