Skip to content

WIP: changes to merge gossip2 branch #5154

New issue

Have a question about this project? Sign up for a free GitHub account to open an issue and contact its maintainers and the community.

By clicking “Sign up for GitHub”, you agree to our terms of service and privacy statement. We’ll occasionally send you account related emails.

Already on GitHub? Sign in to your account

Draft
wants to merge 13 commits into
base: mmcgee/gossip2
Choose a base branch
from
1 change: 1 addition & 0 deletions src/disco/topo/fd_topo.h
Original file line number Diff line number Diff line change
Expand Up @@ -175,6 +175,7 @@ typedef struct {
fd_ip4_port_t entrypoints[ 16UL ];

uint ip_addr;
ushort listen_port;
int has_expected_shred_version;
ushort expected_shred_version;

Expand Down
85 changes: 83 additions & 2 deletions src/discof/gossip/fd_gossip_tile.c
Original file line number Diff line number Diff line change
Expand Up @@ -3,6 +3,7 @@
#include "generated/fd_gossip_tile_seccomp.h"

#include "../../flamenco/gossip/fd_gossip.h"
#include "../../flamenco/gossip/fd_gossip_private.h"
#include "../../disco/keyguard/fd_keyswitch.h"
#include "../../disco/keyguard/fd_keyload.h"
#include "../../disco/keyguard/fd_keyguard_client.h"
Expand Down Expand Up @@ -46,9 +47,13 @@ struct fd_gossip_tile_ctx {

fd_gossip_out_ctx_t net_out[ 1 ];
fd_gossip_out_ctx_t gossip_out[ 1 ];
fd_gossip_out_ctx_t sign_out[ 1 ];

fd_keyguard_client_t keyguard_client[ 1 ];
fd_keyswitch_t * keyswitch;

fd_ip4_udp_hdrs_t net_out_hdr[ 1 ]; /* Used to construct outgoing network packets */
fd_stem_context_t * stem; /* This is ugly! */
};

typedef struct fd_gossip_tile_ctx fd_gossip_tile_ctx_t;
Expand All @@ -66,6 +71,57 @@ scratch_footprint( fd_topo_tile_t const * tile ) {
return FD_LAYOUT_FINI( l, scratch_align() );
}

static void
gossip_send_fn( void * ctx,
uchar const * payload,
ulong payload_sz,
fd_ip4_port_t const * peer_address,
ulong tsorig ) {
fd_gossip_tile_ctx_t * gossip_ctx = (fd_gossip_tile_ctx_t *)ctx;

ulong packet_sz = payload_sz + sizeof(fd_ip4_udp_hdrs_t);
gossip_ctx->net_out->chunk = fd_dcache_compact_next( gossip_ctx->net_out->chunk, packet_sz, gossip_ctx->net_out->chunk0, gossip_ctx->net_out->wmark );

uchar * packet = (uchar *)fd_chunk_to_laddr( gossip_ctx->net_out->mem, gossip_ctx->net_out->chunk );
fd_ip4_udp_hdrs_t * hdr = (fd_ip4_udp_hdrs_t *)packet;
*hdr = *gossip_ctx->net_out_hdr;

fd_ip4_hdr_t * ip4 = hdr->ip4;
fd_udp_hdr_t * udp = hdr->udp;

/* Update payload size in headers */
ip4->net_tot_len = fd_ushort_bswap( (ushort)(packet_sz + sizeof(fd_ip4_hdr_t) + sizeof(fd_udp_hdr_t)) );
udp->net_len = fd_ushort_bswap( (ushort)(payload_sz + sizeof(fd_udp_hdr_t)) );

/* Fill in destination info */
ip4->daddr = peer_address->addr;
udp->net_dport = peer_address->port;

/* IP Checksum calculation */
ip4->check = fd_ip4_hdr_check_fast( ip4 );
/* TODO: ip4 net_id? */

/* Inject payload */
fd_memcpy( packet + sizeof(fd_ip4_udp_hdrs_t), payload, payload_sz );

/* Publish fragment */
ulong tspub = fd_frag_meta_ts_comp( fd_tickcount() );
ulong sig = fd_disco_netmux_sig( peer_address->addr, peer_address->port, peer_address->addr, DST_PROTO_OUTGOING, sizeof(fd_ip4_udp_hdrs_t) );
fd_stem_publish( gossip_ctx->stem, 0UL, 0UL, gossip_ctx->net_out->chunk, packet_sz, sig, tsorig, tspub );



}

static void
gossip_sign_fn( void * ctx,
uchar const * data,
ulong sz,
uchar * signature ) {
fd_gossip_tile_ctx_t * gossip_ctx = (fd_gossip_tile_ctx_t *)ctx;
fd_keyguard_client_sign( gossip_ctx->keyguard_client, data, sz, signature );
}

static inline void
during_housekeeping( fd_gossip_tile_ctx_t * ctx ) {
if( FD_UNLIKELY( fd_keyswitch_state_query( ctx->keyswitch )==FD_KEYSWITCH_STATE_SWITCH_PENDING ) ) {
Expand Down Expand Up @@ -124,12 +180,13 @@ after_frag( fd_gossip_tile_ctx_t * ctx,
ulong sz,
ulong tsorig FD_PARAM_UNUSED,
ulong tspub FD_PARAM_UNUSED,
fd_stem_context_t * stem FD_PARAM_UNUSED ) {
fd_stem_context_t * stem ) {
if( FD_UNLIKELY( ctx->in_kind[ in_idx ]==IN_KIND_NET ) ) {
long now = ctx->last_wallclock + (long)((double)(fd_tickcount()-ctx->last_tickcount)/ctx->ticks_per_ns);

fd_gossip_advance( ctx->gossip, now );
fd_gossip_rx( ctx->gossip, ctx->buffer, sz, now );
ctx->stem = stem;
} else if( FD_UNLIKELY( ctx->in_kind[ in_idx ]==IN_KIND_SHRED_VERSION ) ) {
FD_MGAUGE_SET( GOSSIP, SHRED_VERSION, (ushort)sig );
fd_gossip_set_expected_shred_version( ctx->gossip, 1, (ushort)sig );
Expand Down Expand Up @@ -181,7 +238,7 @@ static void
unprivileged_init( fd_topo_t * topo,
fd_topo_tile_t * tile ) {
void * scratch = fd_topo_obj_laddr( topo, tile->tile_obj_id );

FD_SCRATCH_ALLOC_INIT( l, scratch );
fd_gossip_tile_ctx_t * ctx = FD_SCRATCH_ALLOC_APPEND( l, alignof(fd_gossip_tile_ctx_t), sizeof(fd_gossip_tile_ctx_t) );
void * gossip = FD_SCRATCH_ALLOC_APPEND( l, fd_gossip_align(), fd_gossip_footprint( tile->gossip.max_entries ) );
Expand Down Expand Up @@ -211,6 +268,7 @@ unprivileged_init( fd_topo_t * topo,
ctx->last_wallclock = fd_log_wallclock();
ctx->last_tickcount = fd_tickcount();

ulong sign_in_tile_idx = ULONG_MAX;
for( ulong i=0UL; i<tile->in_cnt; i++ ) {
fd_topo_link_t * link = &topo->links[ tile->in_link_id[ i ] ];
fd_topo_wksp_t * link_wksp = &topo->workspaces[ topo->objs[ link->dcache_obj_id ].wksp_id ];
Expand All @@ -223,13 +281,36 @@ unprivileged_init( fd_topo_t * topo,
ctx->in_kind[ i ] = IN_KIND_SHRED_VERSION;
} else if( FD_UNLIKELY( !strcmp( link->name, "net_gossip" ) ) ) {
ctx->in_kind[ i ] = IN_KIND_NET;
} else if( FD_UNLIKELY( !strcmp( link->name, "sign_gossip" ) ) ) {
ctx->in_kind[ i ] = IN_KIND_SIGN;
sign_in_tile_idx = i;
} else {
FD_LOG_ERR(( "unexpected input link name %s", link->name ));
}
}

if( FD_UNLIKELY( sign_in_tile_idx==ULONG_MAX ) )
FD_LOG_ERR(( "tile %s:%lu had no input link named sign_gossip", tile->name, tile->kind_id ));

*ctx->net_out = out1( topo, tile, "gossip_net" );
*ctx->gossip_out = out1( topo, tile, "gossip_out" );
*ctx->sign_out = out1( topo, tile, "gossip_sign" );

fd_topo_link_t * sign_in = &topo->links[ tile->in_link_id [ sign_in_tile_idx ] ];
fd_topo_link_t * sign_out = &topo->links[ tile->out_link_id[ ctx->sign_out->idx ] ];

if( fd_keyguard_client_join( fd_keyguard_client_new( ctx->keyguard_client,
sign_out->mcache,
sign_out->dcache,
sign_in->mcache,
sign_in->dcache ) ) ) {
FD_LOG_ERR(( "failed to join keyguard client" ));
}

fd_ip4_udp_hdr_init( ctx->net_out_hdr,
FD_GOSSIP_MTU,
tile->gossip.ip_addr,
tile->gossip.listen_port );

ulong scratch_top = FD_SCRATCH_ALLOC_FINI( l, 1UL );
if( FD_UNLIKELY( scratch_top > (ulong)scratch + scratch_footprint( tile ) ) )
Expand Down
4 changes: 2 additions & 2 deletions src/flamenco/gossip/fd_active_set.h
Original file line number Diff line number Diff line change
Expand Up @@ -22,7 +22,7 @@
(2) Peers sometimes request that we don't forward messages from
other originating (origin) nodes to them, because they already
have a lot of paths from that node. This is called a prune.

Complication (1) is handled by keeping a list of the top 12 peers
(sorted by stake) for each of 25 buckets of stakes. These buckets
are all rotated together.
Expand Down Expand Up @@ -82,7 +82,7 @@ fd_active_set_join( void * shas );
have pruned the origin, except if ignore_prunes_if_peer_is_origin
is non-zero, in which case the list will include a peer if its pubkey
matches the origin pubkey.

Up to 12 peer nodes will be returned in out_nodes. The values
returned in out_nodes are an internal peer index of the active set
and should not be used for anything other than calling
Expand Down
2 changes: 1 addition & 1 deletion src/flamenco/gossip/fd_bloom.c
Original file line number Diff line number Diff line change
Expand Up @@ -49,7 +49,7 @@ fd_bloom_new( void * shmem,
if( FD_UNLIKELY( false_positive_rate>=1.0 ) ) return NULL;

if( FD_UNLIKELY( max_bits<1UL || max_bits>32768UL ) ) return NULL;

if( FD_UNLIKELY( !rng ) ) return NULL;

ulong num_keys = (ulong)( (double)max_bits*FD_BLOOM_LN_2 );
Expand Down
6 changes: 3 additions & 3 deletions src/flamenco/gossip/fd_crds.c
Original file line number Diff line number Diff line change
Expand Up @@ -31,7 +31,7 @@ struct fd_crds_value_private {

So we have a ContactInfo message for example. If a validator sends
us a new ContactInfo message, we want to replace the old one. This
lookup is serviced by a hash table, keyed by the public key of the
lookup is serviced by a hash table, keyed by the public key of the
originator, and in a few special cases an additional field. For
example, votes are (originator_key, vote_index), since we need to
know about more than one vote from a given originator.
Expand All @@ -50,7 +50,7 @@ struct fd_crds_value_private {
/* The CRDS needs to perform a variety of actions on the message table
quickly, so there are various indexes woven through them values to
support these actions. They are ...

lookup is used to enable the core map<key, value> functionality
described for upserts above. */
struct {
Expand Down Expand Up @@ -348,7 +348,7 @@ fd_crds_expire( fd_crds_t * crds,
fd_crds_value_t const * head = staked_expire_dlist_ele_peek_head_const( crds->expire_dlist crds->pool );

if( FD_LIKELY( head->expire.wallclock_nanos<now-STAKED_EXPIRE_DURATION_NANOS ) ) break;

staked_expire_dlist_ele_pop_head( crds->staked_expire_dlist, crds->pool );
hash_treap_ele_remove( crds->hash_treap, head, crds->pool );
lookup_map_ele_remove( crds->lookup_map, head, crds->pool );
Expand Down
7 changes: 4 additions & 3 deletions src/flamenco/gossip/fd_crds.h
Original file line number Diff line number Diff line change
Expand Up @@ -2,6 +2,7 @@
#define HEADER_fd_src_flamenco_gossip_fd_crds_h

#include "../../util/fd_util.h"
#include "../../util/net/fd_net_headers.h"
Copy link
Contributor

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

Not needed by the header, only add include to the .h file if the header uses it, this should be in the .c

Copy link
Contributor Author

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

both headers are needed here for types (fd_rng_t and fd_ip4_port_t respectively)


struct fd_crds_value_private;
typedef struct fd_crds_value_private fd_crds_value_t;
Expand Down Expand Up @@ -41,7 +42,7 @@ fd_crds_join( void * shcrds );
store. CRDS values from staked nodes expire roughly an epoch after
they are created, and values from non-staked nodes expire after 15
seconds.

There is one exception, when the node is first bootstrapping, and
has not yet seen any staked nodes, values do not expire at all. */

Expand All @@ -60,7 +61,7 @@ fd_crds_expire( fd_crds_t * crds,
are also excluded from the sampling. Peers with a different shred
version than us, or with an invalid gossip socket address are also
excluded from the sampling.

If no valid peer can be found, the returned fd_ip4_port_t will be
zeroed out. The caller should check for this case and handle it
appropriately. On success, the returned fd_ip4_port_t is a socket
Expand Down Expand Up @@ -101,7 +102,7 @@ fd_crds_release( fd_crds_t * crds,
/* fd_crds_upserts checks if inserting the value into the CRDS would
succeed. An insert will fail if the value is already present in the
CRDS with a newer timestamp, or if the value is not present. */

int
fd_crds_upserts( fd_crds_t * crds,
fd_crds_value_t * value );

Expand Down
77 changes: 77 additions & 0 deletions src/flamenco/gossip/fd_crds_value.h
Original file line number Diff line number Diff line change
Expand Up @@ -2,5 +2,82 @@
#define HEADER_fd_src_flamenco_gossip_fd_crds_value_h

#include "../../util/fd_util.h"
#include "../../util/net/fd_net_headers.h"

#define FD_GOSSIP_CONTACT_INFO_SOCKET_GOSSIP ( 0)
#define FD_GOSSIP_CONTACT_INFO_SOCKET_SERVE_REPAIR_QUIC ( 1)
#define FD_GOSSIP_CONTACT_INFO_SOCKET_RPC ( 2)
#define FD_GOSSIP_CONTACT_INFO_SOCKET_RPC_PUBSUB ( 3)
#define FD_GOSSIP_CONTACT_INFO_SOCKET_SERVE_REPAIR ( 4)
#define FD_GOSSIP_CONTACT_INFO_SOCKET_TPU ( 5)
#define FD_GOSSIP_CONTACT_INFO_SOCKET_TPU_FORWARDS ( 6)
#define FD_GOSSIP_CONTACT_INFO_SOCKET_TPU_FORWARDS_QUIC ( 7)
#define FD_GOSSIP_CONTACT_INFO_SOCKET_TPU_QUIC ( 8)
#define FD_GOSSIP_CONTACT_INFO_SOCKET_TPU_VOTE ( 9)
#define FD_GOSSIP_CONTACT_INFO_SOCKET_TVU (10)
#define FD_GOSSIP_CONTACT_INFO_SOCKET_TVU_QUIC (11)
#define FD_GOSSIP_CONTACT_INFO_SOCKET_TPU_VOTE_QUIC (12)

#define FD_GOSSIP_CLIENT_SOLANA (0)
#define FD_GOSSIP_CLIENT_JITO (1)
#define FD_GOSSIP_CLIENT_FD (2)
#define FD_GOSSIP_CLIENT_AGAVE (3)

struct fd_crds_key {
uchar tag;
uchar pubkey[ 32UL ];
union {
uchar vote_index;
uchar epoch_slots_index;
ushort duplicate_shred_index;
};
};
typedef struct fd_crds_key fd_crds_key_t;

struct fd_gossip_crds_contact_info {
long instance_creation_wallclock_nanos;
ushort shred_version;

struct {
uchar client;

ushort major;
ushort minor;
ushort patch;

int has_commit;
uint commit;
uint feature_set;
} version;

struct {
/* WARNING: in gossip contact info message,
ports are encoded in host form. The parser will
perform the conversion */
fd_ip4_port_t addr;
} sockets[ 13UL ];
};

typedef struct fd_gossip_crds_contact_info fd_gossip_crds_contact_info_t;

struct fd_gossip_crds_vote {
ulong slot;
uchar vote_tower_index;
uchar txn[ 1232UL ];
};

typedef struct fd_gossip_crds_vote fd_gossip_crds_vote_t;

struct fd_gossip_crds_value {

fd_crds_key_t key;
long wallclock_nanos;
uchar signature[64UL]; // signable data is always offset + sizeof(signature); signable_sz = sz - sizeof(signature)
union {
fd_gossip_crds_contact_info_t contact_info;
fd_gossip_crds_vote_t vote;
};
};
typedef struct fd_gossip_crds_value fd_gossip_crds_value_t;

#endif /* HEADER_fd_src_flamenco_gossip_fd_crds_value_h */
Loading
Loading