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 : } metrics; 64 : } fd_verify_ctx_t; 65 : 66 : static inline int 67 : fd_txn_verify( fd_verify_ctx_t * ctx, 68 : uchar const * udp_payload, 69 : ushort const payload_sz, 70 : fd_txn_t const * txn, 71 : int dedup, 72 0 : ulong * opt_sig ) { 73 : 74 : /* We do not want to deref any non-data field from the txn struct more than once */ 75 0 : uchar signature_cnt = txn->signature_cnt; 76 0 : ushort signature_off = txn->signature_off; 77 0 : ushort acct_addr_off = txn->acct_addr_off; 78 0 : ushort message_off = txn->message_off; 79 : 80 0 : uchar const * signatures = udp_payload + signature_off; 81 0 : uchar const * pubkeys = udp_payload + acct_addr_off; 82 0 : uchar const * msg = udp_payload + message_off; 83 0 : ulong msg_sz = fd_txn_msg_sz( txn, (ulong)payload_sz ); 84 : 85 : /* The first signature is the transaction id, i.e. a unique identifier. 86 : So use this to do a quick dedup of ha traffic. */ 87 : 88 0 : ulong ha_dedup_tag = fd_hash( ctx->hashmap_seed, signatures, 64UL ); 89 0 : int ha_dup = 0; 90 0 : if( FD_LIKELY( dedup ) ) { 91 0 : FD_FN_UNUSED ulong tcache_map_idx = 0; /* ignored */ 92 0 : FD_TCACHE_QUERY( ha_dup, tcache_map_idx, ctx->tcache_map, ctx->tcache_map_cnt, ha_dedup_tag ); 93 0 : if( FD_UNLIKELY( ha_dup ) ) { 94 0 : return FD_TXN_VERIFY_DEDUP; 95 0 : } 96 0 : } 97 : 98 : /* Verify signatures */ 99 0 : int res = fd_ed25519_verify_batch_single_msg_cached( msg, msg_sz, signatures, pubkeys, ctx->sha, signature_cnt, ctx->ed25519_cache ); 100 0 : if( FD_UNLIKELY( res != FD_ED25519_SUCCESS ) ) { 101 0 : return FD_TXN_VERIFY_FAILED; 102 0 : } 103 : 104 : /* Insert into the tcache to dedup ha traffic. 105 : The dedup check is repeated to guard against duped txs verifying signatures at the same time */ 106 0 : if( FD_LIKELY( dedup ) ) { 107 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 ); 108 0 : if( FD_UNLIKELY( ha_dup ) ) { 109 0 : return FD_TXN_VERIFY_DEDUP; 110 0 : } 111 0 : } 112 : 113 0 : *opt_sig = ha_dedup_tag; 114 0 : return FD_TXN_VERIFY_SUCCESS; 115 0 : } 116 : 117 : #endif /* HEADER_fd_src_disco_verify_fd_verify_tile_h */