diff --git a/contrib/offline-replay/offline_replay.toml b/contrib/offline-replay/offline_replay.toml index 8330793b5d..78e56b6feb 100644 --- a/contrib/offline-replay/offline_replay.toml +++ b/contrib/offline-replay/offline_replay.toml @@ -31,10 +31,11 @@ [paths] snapshots = "{ledger}" [snapshots] - download = false incremental_snapshots = false - minimum_download_speed_mib = 0 - maximum_local_snapshot_age = 0 - maximum_download_retry_abort = 0 + [snapshots.sources] + servers = [] + [snapshots.sources.gossip] + allow_any = false + allow_list = [] [gossip] entrypoints = [ "0.0.0.0:1" ] diff --git a/contrib/test/run_solcap_tests.sh b/contrib/test/run_solcap_tests.sh index 894ef6be97..afd5af6832 100755 --- a/contrib/test/run_solcap_tests.sh +++ b/contrib/test/run_solcap_tests.sh @@ -57,12 +57,21 @@ cp $DUMP/$LEDGER/devnet-398736132.toml $DUMP/$LEDGER/devnet-398736132_current.to export ledger_dir=$(realpath $DUMP/$LEDGER) sed -i "s#{ledger_dir}#${ledger_dir}#g" "$DUMP/$LEDGER/devnet-398736132_current.toml" sed -i "s/max_total_banks = [0-9]*/max_total_banks = 32/g" "$DUMP/$LEDGER/devnet-398736132_current.toml" -sed -i "s/minimum_download_speed_mib = 0/download = false/g" "$DUMP/$LEDGER/devnet-398736132_current.toml" # TODO: Set this properly in the configs +sed -i -z "s/\[snapshots\].*\[layout\]/[layout]/" "$DUMP/$LEDGER/devnet-398736132_current.toml" echo " [gossip] entrypoints = [ \"0.0.0.0:1\" ]" >> "$DUMP/$LEDGER/devnet-398736132_current.toml" +echo " +[snapshots] + incremental_snapshots = false + [snapshots.sources] + servers = [] + [snapshots.sources.gossip] + allow_any = false + allow_list = []" >> "$DUMP/$LEDGER/devnet-398736132_current.toml" + $OBJDIR/bin/firedancer-dev configure init all --config $DUMP/$LEDGER/devnet-398736132_current.toml &> /dev/null $OBJDIR/bin/firedancer-dev backtest --config $DUMP/$LEDGER/devnet-398736132_current.toml $OBJDIR/bin/firedancer-dev configure fini all --config $DUMP/$LEDGER/devnet-398736132_current.toml &> /dev/null diff --git a/src/app/firedancer-dev/commands/backtest.c b/src/app/firedancer-dev/commands/backtest.c index 987057885f..e72c943308 100644 --- a/src/app/firedancer-dev/commands/backtest.c +++ b/src/app/firedancer-dev/commands/backtest.c @@ -138,18 +138,18 @@ backtest_topo( config_t * config ) { fd_topob_wksp( topo, "snapct_ld" ); fd_topob_wksp( topo, "snapld_dc" ); fd_topob_wksp( topo, "snapdc_in" ); - fd_topob_wksp( topo, "snapin_rd" ); + fd_topob_wksp( topo, "snapin_ct" ); fd_topob_wksp( topo, "snapin_manif" ); fd_topob_wksp( topo, "snapct_repr" ); fd_topob_link( topo, "snapct_ld", "snapct_ld", 128UL, sizeof(fd_ssctrl_init_t), 1UL ); fd_topob_link( topo, "snapld_dc", "snapld_dc", 16384UL, USHORT_MAX, 1UL ); fd_topob_link( topo, "snapdc_in", "snapdc_in", 16384UL, USHORT_MAX, 1UL ); - fd_topob_link( topo, "snapin_rd", "snapin_rd", 128UL, 0UL, 1UL ); + fd_topob_link( topo, "snapin_ct", "snapin_ct", 128UL, 0UL, 1UL ); fd_topob_link( topo, "snapin_manif", "snapin_manif", 4UL, sizeof(fd_snapshot_manifest_t), 1UL ); /* TODO: Should be depth 1 or 2 but replay backpressures */ fd_topob_link( topo, "snapct_repr", "snapct_repr", 128UL, 0UL, 1UL )->permit_no_consumers = 1; - fd_topob_tile_in ( topo, "snapct", 0UL, "metric_in", "snapin_rd", 0UL, FD_TOPOB_RELIABLE, FD_TOPOB_POLLED ); + fd_topob_tile_in ( topo, "snapct", 0UL, "metric_in", "snapin_ct", 0UL, FD_TOPOB_RELIABLE, FD_TOPOB_POLLED ); fd_topob_tile_in ( topo, "snapct", 0UL, "metric_in", "snapld_dc", 0UL, FD_TOPOB_RELIABLE, FD_TOPOB_POLLED ); fd_topob_tile_out( topo, "snapct", 0UL, "snapct_ld", 0UL ); fd_topob_tile_out( topo, "snapct", 0UL, "snapct_repr", 0UL ); @@ -158,7 +158,7 @@ backtest_topo( config_t * config ) { fd_topob_tile_in ( topo, "snapdc", 0UL, "metric_in", "snapld_dc", 0UL, FD_TOPOB_RELIABLE, FD_TOPOB_POLLED ); fd_topob_tile_out( topo, "snapdc", 0UL, "snapdc_in", 0UL ); fd_topob_tile_in ( topo, "snapin", 0UL, "metric_in", "snapdc_in", 0UL, FD_TOPOB_RELIABLE, FD_TOPOB_POLLED ); - fd_topob_tile_out( topo, "snapin", 0UL, "snapin_rd", 0UL ); + fd_topob_tile_out( topo, "snapin", 0UL, "snapin_ct", 0UL ); fd_topob_tile_out( topo, "snapin", 0UL, "snapin_manif", 0UL ); fd_topob_tile_in ( topo, "replay", 0UL, "metric_in", "snapin_manif", 0UL, FD_TOPOB_RELIABLE, FD_TOPOB_POLLED ); } else { diff --git a/src/app/firedancer-dev/commands/snapshot_load.c b/src/app/firedancer-dev/commands/snapshot_load.c index f01ac24582..8f36e35276 100644 --- a/src/app/firedancer-dev/commands/snapshot_load.c +++ b/src/app/firedancer-dev/commands/snapshot_load.c @@ -77,18 +77,18 @@ snapshot_load_topo( config_t * config, fd_topob_wksp( topo, "snapct_ld" ); fd_topob_wksp( topo, "snapld_dc" ); fd_topob_wksp( topo, "snapdc_in" ); - fd_topob_wksp( topo, "snapin_rd" ); + fd_topob_wksp( topo, "snapin_ct" ); fd_topob_wksp( topo, "snapin_manif" ); fd_topob_wksp( topo, "snapct_repr" ); fd_topob_link( topo, "snapct_ld", "snapct_ld", 128UL, sizeof(fd_ssctrl_init_t), 1UL ); fd_topob_link( topo, "snapld_dc", "snapld_dc", 16384UL, USHORT_MAX, 1UL ); fd_topob_link( topo, "snapdc_in", "snapdc_in", 16384UL, USHORT_MAX, 1UL ); - fd_topob_link( topo, "snapin_rd", "snapin_rd", 128UL, 0UL, 1UL ); + fd_topob_link( topo, "snapin_ct", "snapin_ct", 128UL, 0UL, 1UL ); fd_topob_link( topo, "snapin_manif", "snapin_manif", 2UL, sizeof(fd_snapshot_manifest_t), 1UL )->permit_no_consumers = 1; fd_topob_link( topo, "snapct_repr", "snapct_repr", 128UL, 0UL, 1UL )->permit_no_consumers = 1; - fd_topob_tile_in ( topo, "snapct", 0UL, "metric_in", "snapin_rd", 0UL, FD_TOPOB_RELIABLE, FD_TOPOB_POLLED ); + fd_topob_tile_in ( topo, "snapct", 0UL, "metric_in", "snapin_ct", 0UL, FD_TOPOB_RELIABLE, FD_TOPOB_POLLED ); fd_topob_tile_in ( topo, "snapct", 0UL, "metric_in", "snapld_dc", 0UL, FD_TOPOB_RELIABLE, FD_TOPOB_POLLED ); fd_topob_tile_out( topo, "snapct", 0UL, "snapct_ld", 0UL ); fd_topob_tile_out( topo, "snapct", 0UL, "snapct_repr", 0UL ); @@ -97,7 +97,7 @@ snapshot_load_topo( config_t * config, fd_topob_tile_in ( topo, "snapdc", 0UL, "metric_in", "snapld_dc", 0UL, FD_TOPOB_RELIABLE, FD_TOPOB_POLLED ); fd_topob_tile_out( topo, "snapdc", 0UL, "snapdc_in", 0UL ); fd_topob_tile_in ( topo, "snapin", 0UL, "metric_in", "snapdc_in", 0UL, FD_TOPOB_RELIABLE, FD_TOPOB_POLLED ); - fd_topob_tile_out( topo, "snapin", 0UL, "snapin_rd", 0UL ); + fd_topob_tile_out( topo, "snapin", 0UL, "snapin_ct", 0UL ); fd_topob_tile_out( topo, "snapin", 0UL, "snapin_manif", 0UL ); /* snapin funk / txncache access */ @@ -137,7 +137,7 @@ extern int * fd_log_private_shared_lock; static void snapshot_load_cmd_fn( args_t * args, config_t * config ) { - if( FD_UNLIKELY( config->firedancer.snapshots.sources.gossip.enabled ) ) { + if( FD_UNLIKELY( config->firedancer.snapshots.sources.gossip.allow_any || 0UL!=config->firedancer.snapshots.sources.gossip.allow_list_cnt ) ) { FD_LOG_ERR(( "snapshot-load command is incompatible with gossip snapshot sources" )); } snapshot_load_topo( config, args ); diff --git a/src/app/firedancer/config/default.toml b/src/app/firedancer/config/default.toml index 106377df0d..0570676752 100644 --- a/src/app/firedancer/config/default.toml +++ b/src/app/firedancer/config/default.toml @@ -280,20 +280,6 @@ user = "" # a validator to catch up more quickly. incremental_snapshots = true - # How old a local incremental snapshot on disk can be, in slots, and - # still be loaded on startup. The age of a snapshot is determined - # by looking at the highest incremental snapshot slot available for - # download from cluster peers. - # - # If a local snapshot exists on disk, within the given age, other - # options are ignored and no snapshot will be downloaded. - # - # If the local snapshot is older than this, we will instead download - # a new snapshot. If the local snapshot is too old, and we cannot - # download a snapshot because `download` is `false`, the validator - # will exit with an error. - maximum_local_snapshot_age = 2500 - # Whether to allow downloading a new genesis file from a peer when # booting. If set to false, the validator will only reuse a locally # stored genesis file, and if one does not exist, the validator will @@ -313,65 +299,7 @@ user = "" # will exit with an error. genesis_download = true - # Whether to allow downloading a new snapshot from a peer when - # booting. - # - # If set to true, the validator will contact peers from the gossip - # network to locate both a full and incremental snapshot and - # download it, assuming there is no loadable local snapshot. If - # false, the validator will attempt to load the most recently - # downloaded snapshot that exists locally on the disk. If there is - # no local snapshot, the validator will abort with an error. - # - # When downloading a snapshot, it will optionally be stored on disk - # if `[paths.snapshots]` is specified. The number of downloaded - # snapshots that will be stored on disk is controlled below by the - # max_*_snapshots to keep options. - # - # TODO: implement the "at most one downloaded" logic. " - download = true - - # A snapshot hash must be published in gossip by one of the - # validator identities listed here for it to be accepted. The list - # should be a list of identity public keys, specified as base58 - # strings. - # - # If a snapshot hash is received that is not published by a known - # validator the validator will exit with an error. - # - # If no known validators are specified here, any snapshot hash will - # be accepted. - # - # TODO: Implement this once gossip is wired up. - known_validators = [] - - # The minimum acceptable speed for snapshot download from a peer, in - # megabits per second. If the initial download speed falls below - # this threshold, the validator will abandon the download, find a - # new peer and start downloading the snapshot from them. - # - # The initial download speed is measured over every 10 mib for the - # first 400 mib of downloaded content. The validator continues - # to measure download speed over every 10 mib until the download is - # complete, but only the initial download speed is used to decide - # whether to abort and retry the download. - # TODO: refine the initial download speed measurement and threshold. - # - # If set to zero, no minimum threshold will be applied. - minimum_download_speed_mib = 0 - - # The maximum number of times to abort and retry when encountering a - # slow snapshot download. If the maximum attempts is reached while - # downloading a snapshot the validator will exit with an error. - # - # The number of attempts is reset when starting a download for a - # new full or incremental snapshot. - # - # If set to zero, the validator will continually retry until - # completing snapshot download. - maximum_download_retry_abort = 5 - - # Controls how many full snapshots are allowed to be kept in the + # Controls how many snapshots are allowed to be kept in the # snapshots directory on disk. # # Firedancer does not currently support creating snapshots, and so @@ -380,6 +308,15 @@ user = "" max_full_snapshots_to_keep = 1 max_incremental_snapshots_to_keep = 1 + # If an in-progress loading (local, or download) of a full snapshot + # has its effective age rise above this threshold, we will cancel + # the load and start over. The most common reason this would + # happen is if the network is all using the same full snapshot + # interval (e.g. 100_000) and while we are downloading a full + # snapshot from interval N, the network moves on to N+1, removing + # availability of all incremental snapshots that build on N. + full_effective_age_cancel_threshold = 20_000 + # Controls for where we look to find snapshots. If multiple sources # and peers are available, the one with the lowest latency and # fastest download will be automatically selected among them. @@ -396,38 +333,89 @@ user = "" # validate and work well, but could later crash, corrupt, or cause # your node to vote incorrectly in an attacker controlled way. # - # It is strongly recommended to only fetch snapshots from peers that - # you highly trust, and this is the default behavior of the - # configuration. + # It is strongly recommended to only download snapshots from peers + # that you highly trust. [snapshots.sources] - # Allow fetching of snapshots from arbitrary gossip peers that - # are hosting a snapshot server. This may allow faster snapshot - # download if a peer in a local data-center is serving a good - # snapshot, but it is extremely dangerous as the peer could - # serve you a specially crafted malicious snapshot with no way - # to tell. - [snapshots.sources.gossip] - enabled = false - - # If any HTTP peers are listed, the following paths will be - # fetched from these peers to determine if they have a snapshot + # The local age parameters control whether or not we use locally + # stored full / incremental snapshots, if they exist. Slot age + # is measured against the highest slot we could currently arrive + # at by downloading new full and incremental snapshots from any + # of our trusted sources. + # + # The effective usable slot of the local full snapshot is + # defined as the max slot of all trusted incremental snapshots + # that we could possibly use (local, or downloaded) which apply + # on top of this full snapshot. + # + # The ultimate goal of these parameters is to minimize cluster + # catchup time. To that end, they are a tradeoff between the + # catchup time from a snapshot slot and download time of the + # snapshot. A local snapshot that has an older age than one + # we can download might actually result in a faster catchup + # time because of the faster loading speed. The full age + # should be set higher because, as full snapshots are much + # larger than incremental snapshots, the time penalty for + # downloading a full snapshot is much higher. + max_local_full_effective_age = 1000 + max_local_incremental_age = 200 + + # If any HTTP server URLs are listed, the following paths will be + # fetched from these servers to determine if they have a snapshot # available: # # /snapshot.tar.bz2 # /incremental-snapshot.tar.bz2 # - # If these peers have snapshots at the given paths, they will be + # If these servers have snapshots at the given paths, they will be # considered as additional sources for downloading snapshots - # when enabled alongside gossip sources. - [[snapshots.sources.http]] - # Whether to enable fetching snapshots from a list of - # HTTP peers. - enabled = false + # when enabled alongside gossip and entrypoint sources. + servers = [] - # The url to fetch snapshots from. The paths /snapshot.tar.bz2 - # and /incremental-snapshot.tar.bz2 will be queried from this - # URL. - url = "http://example.com:1234" + [snapshots.sources.gossip] + # Allow downloading of snapshots from arbitrary gossip peers + # that are hosting a snapshot server. This may allow faster + # snapshot download if a peer in a local data-center is + # serving a good snapshot, but it is extremely dangerous as + # the peer could serve you a specially crafted malicious + # snapshot with no way to tell. + allow_any = true + + # Allow downloading of snapshots from the gossip peers + # identified by the given base58-encoded public keys. + allow_list = [] + + # Do not attempt downloads from the given base58-encoded + # gossip public keys. For an example, this can be useful + # if a peer is frequently selected by the automatic logic + # but does not yield successful / usable snapshots. + block_list = [] + + [snapshots.download] + # The minimum acceptable speed for snapshot download from a peer, in + # megabits per second. If the initial download speed falls below + # this threshold, the validator will abandon the download, find a + # new peer and start downloading the snapshot from them. + # + # The initial download speed is measured over every 10 mib for the + # first 400 mib of downloaded content. The validator continues + # to measure download speed over every 10 mib until the download is + # complete, but only the initial download speed is used to decide + # whether to abort and retry the download. + # TODO: refine the initial download speed measurement and threshold. + # + # If set to zero, no minimum threshold will be applied. + min_speed_mib = 0 + + # The maximum number of times to abort and retry when encountering a + # slow snapshot download. If the maximum attempts is reached while + # downloading a snapshot the validator will exit with an error. + # + # The number of attempts is reset when starting a download for a + # new full or incremental snapshot. + # + # If set to zero, the validator will continually retry until + # completing snapshot download. + max_retry_abort = 5 [rpc] # If nonzero, enable JSON RPC on this port, and use the next port @@ -520,10 +508,6 @@ user = "" # is not recommended to change this setting. mean_cache_entry_size = 131072 -# This section configures the "groove" persistent account database. -# [groove] -# ... - [store] # Similar to max_pending_shred_sets, this parameter configures the # maximum number of shred sets that can be buffered. However, this diff --git a/src/app/firedancer/config/testnet.toml b/src/app/firedancer/config/testnet.toml index 6179da4035..c1a3d18a20 100644 --- a/src/app/firedancer/config/testnet.toml +++ b/src/app/firedancer/config/testnet.toml @@ -10,7 +10,3 @@ max_account_records = 200_000_000 [layout] gossvf_tile_count = 4 -[snapshots] - [[snapshots.sources.http]] - enabled = true - url = "http://solana-testnet-rpc.jumpisolated.com:8899" diff --git a/src/app/firedancer/topology.c b/src/app/firedancer/topology.c index 313412ff68..8605229718 100644 --- a/src/app/firedancer/topology.c +++ b/src/app/firedancer/topology.c @@ -335,7 +335,7 @@ fd_topo_initialize( config_t * config ) { fd_topob_wksp( topo, "snapct_ld" ); fd_topob_wksp( topo, "snapld_dc" ); fd_topob_wksp( topo, "snapdc_in" ); - fd_topob_wksp( topo, "snapin_rd" ); + fd_topob_wksp( topo, "snapin_ct" ); if( FD_LIKELY( config->tiles.gui.enabled ) ) fd_topob_wksp( topo, "snapct_gui" ); fd_topob_wksp( topo, "snapin_manif" ); @@ -359,7 +359,7 @@ fd_topo_initialize( config_t * config ) { /**/ fd_topob_link( topo, "snapct_ld", "snapct_ld", 128UL, sizeof(fd_ssctrl_init_t), 1UL ); /**/ fd_topob_link( topo, "snapld_dc", "snapld_dc", 16384UL, USHORT_MAX, 1UL ); /**/ fd_topob_link( topo, "snapdc_in", "snapdc_in", 16384UL, USHORT_MAX, 1UL ); - /**/ fd_topob_link( topo, "snapin_rd", "snapin_rd", 128UL, 0UL, 1UL ); + /**/ fd_topob_link( topo, "snapin_ct", "snapin_ct", 128UL, 0UL, 1UL ); /**/ fd_topob_link( topo, "snapin_manif", "snapin_manif", 2UL, sizeof(fd_snapshot_manifest_t),1UL ); /**/ fd_topob_link( topo, "snapct_repr", "snapct_repr", 128UL, 0UL, 1UL )->permit_no_consumers = 1; /* TODO: wire in repair later */ @@ -506,9 +506,12 @@ fd_topo_initialize( config_t * config ) { /**/ fd_topob_tile_in( topo, "gossip", 0UL, "metric_in", "send_txns", 0UL, FD_TOPOB_RELIABLE, FD_TOPOB_POLLED ); /**/ fd_topob_tile_out( topo, "gossip", 0UL, "gossip_gossv", 0UL ); + int snapshots_gossip_enabled = config->firedancer.snapshots.sources.gossip.allow_any || config->firedancer.snapshots.sources.gossip.allow_list_cnt>0UL; if( FD_LIKELY( snapshots_enabled ) ) { + if( FD_LIKELY( snapshots_gossip_enabled ) ) { fd_topob_tile_in ( topo, "snapct", 0UL, "metric_in", "gossip_out", 0UL, FD_TOPOB_RELIABLE, FD_TOPOB_POLLED ); - fd_topob_tile_in ( topo, "snapct", 0UL, "metric_in", "snapin_rd", 0UL, FD_TOPOB_RELIABLE, FD_TOPOB_POLLED ); + } + fd_topob_tile_in ( topo, "snapct", 0UL, "metric_in", "snapin_ct", 0UL, FD_TOPOB_RELIABLE, FD_TOPOB_POLLED ); fd_topob_tile_in ( topo, "snapct", 0UL, "metric_in", "snapld_dc", 0UL, FD_TOPOB_RELIABLE, FD_TOPOB_POLLED ); fd_topob_tile_out( topo, "snapct", 0UL, "snapct_ld", 0UL ); fd_topob_tile_out( topo, "snapct", 0UL, "snapct_repr", 0UL ); @@ -523,7 +526,7 @@ fd_topo_initialize( config_t * config ) { fd_topob_tile_out( topo, "snapdc", 0UL, "snapdc_in", 0UL ); fd_topob_tile_in ( topo, "snapin", 0UL, "metric_in", "snapdc_in", 0UL, FD_TOPOB_RELIABLE, FD_TOPOB_POLLED ); - fd_topob_tile_out( topo, "snapin", 0UL, "snapin_rd", 0UL ); + fd_topob_tile_out( topo, "snapin", 0UL, "snapin_ct", 0UL ); fd_topob_tile_out( topo, "snapin", 0UL, "snapin_manif", 0UL ); } @@ -908,30 +911,33 @@ fd_topo_configure_tile( fd_topo_tile_t * tile, } else if( FD_UNLIKELY( !strcmp( tile->name, "snapct" ) ) ) { fd_memcpy( tile->snapct.snapshots_path, config->paths.snapshots, PATH_MAX ); - tile->snapct.incremental_snapshot_fetch = config->firedancer.snapshots.incremental_snapshots; - tile->snapct.do_download = config->firedancer.snapshots.download; - tile->snapct.maximum_local_snapshot_age = config->firedancer.snapshots.maximum_local_snapshot_age; - tile->snapct.minimum_download_speed_mib = config->firedancer.snapshots.minimum_download_speed_mib; - tile->snapct.maximum_download_retry_abort = config->firedancer.snapshots.maximum_download_retry_abort; - tile->snapct.max_full_snapshots_to_keep = config->firedancer.snapshots.max_full_snapshots_to_keep; - tile->snapct.max_incremental_snapshots_to_keep = config->firedancer.snapshots.max_incremental_snapshots_to_keep; - tile->snapct.gossip_peers_enabled = config->firedancer.snapshots.sources.gossip.enabled; - - ulong peers_cnt = config->firedancer.snapshots.sources.http.peers_cnt; - ulong resolved_peers_cnt = 0UL; - - for( ulong j=0UL; jfiredancer.snapshots.sources.http.peers[ j ].enabled ) ) continue; - - if( FD_UNLIKELY( 0==resolve_peer( config->firedancer.snapshots.sources.http.peers[ j ].url, &tile->snapct.http.peers[ resolved_peers_cnt ] ) ) ) { - FD_LOG_ERR(( "failed to resolve address of [snapshots.sources.http.peers] entry \"%s\"", config->firedancer.snapshots.sources.http.peers[ j ].url )); - } else { - resolved_peers_cnt++; + tile->snapct.sources.max_local_full_effective_age = config->firedancer.snapshots.sources.max_local_full_effective_age; + tile->snapct.sources.max_local_incremental_age = config->firedancer.snapshots.sources.max_local_incremental_age; + tile->snapct.incremental_snapshots = config->firedancer.snapshots.incremental_snapshots; + tile->snapct.max_full_snapshots_to_keep = config->firedancer.snapshots.max_full_snapshots_to_keep; + tile->snapct.max_incremental_snapshots_to_keep = config->firedancer.snapshots.max_incremental_snapshots_to_keep; + tile->snapct.full_effective_age_cancel_threshold = config->firedancer.snapshots.full_effective_age_cancel_threshold; + tile->snapct.download.min_speed_mib = config->firedancer.snapshots.download.min_speed_mib; + tile->snapct.download.max_retry_abort = config->firedancer.snapshots.download.max_retry_abort; + tile->snapct.sources.gossip.allow_any = config->firedancer.snapshots.sources.gossip.allow_any; + tile->snapct.sources.gossip.allow_list_cnt = config->firedancer.snapshots.sources.gossip.allow_list_cnt; + tile->snapct.sources.gossip.block_list_cnt = config->firedancer.snapshots.sources.gossip.block_list_cnt; + tile->snapct.sources.servers_cnt = config->firedancer.snapshots.sources.servers_cnt; + for( ulong i=0UL; isnapct.sources.gossip.allow_list_cnt; i++ ) { + if( FD_UNLIKELY( !fd_base58_decode_32( config->firedancer.snapshots.sources.gossip.allow_list[ i ], tile->snapct.sources.gossip.allow_list[ i ].uc ) ) ) { + FD_LOG_ERR(( "[snapshots.sources.gossip.allow_list[%lu] invalid (%s)", i, config->firedancer.snapshots.sources.gossip.allow_list[ i ] )); + } + } + for( ulong i=0UL; isnapct.sources.gossip.block_list_cnt; i++ ) { + if( FD_UNLIKELY( !fd_base58_decode_32( config->firedancer.snapshots.sources.gossip.block_list[ i ], tile->snapct.sources.gossip.block_list[ i ].uc ) ) ) { + FD_LOG_ERR(( "[snapshots.sources.gossip.block_list[%lu] invalid (%s)", i, config->firedancer.snapshots.sources.gossip.block_list[ i ] )); + } + } + for( ulong i=0UL; isnapct.sources.servers_cnt; i++ ) { + if( FD_UNLIKELY( !resolve_peer( config->firedancer.snapshots.sources.servers[ i ], &tile->snapct.sources.servers[ i ] ) ) ) { + FD_LOG_ERR(( "[snapshots.sources.servers[%lu] invalid (%s)", i, config->firedancer.snapshots.sources.servers[ i ] )); } } - - tile->snapct.http.peers_cnt = resolved_peers_cnt; - /* TODO: set up known validators and known validators cnt */ } else if( FD_UNLIKELY( !strcmp( tile->name, "snapld" ) ) ) { diff --git a/src/app/shared/fd_config.c b/src/app/shared/fd_config.c index 4c0c98cc5d..2d5efc3af9 100644 --- a/src/app/shared/fd_config.c +++ b/src/app/shared/fd_config.c @@ -461,6 +461,13 @@ fd_config_validatef( fd_configf_t const * config ) { if( FD_UNLIKELY( config->layout.sign_tile_count < 2 ) ) { FD_LOG_ERR(( "layout.sign_tile_count must be >= 2" )); } + + if( FD_UNLIKELY( config->snapshots.sources.gossip.allow_any && config->snapshots.sources.gossip.allow_list_cnt>0UL ) ) { + FD_LOG_ERR(( "`snapshots.sources.gossip` has an explicit list of %lu allowed peer(s) in `allow_list` " + "but also allows any peer with `allow_any=true`. `allow_list` has no effect and may " + "give a false sense of security. Please modify one of the two options and restart. ", + config->snapshots.sources.gossip.allow_list_cnt )); + } } static void diff --git a/src/app/shared/fd_config.h b/src/app/shared/fd_config.h index dca7d21975..a1928cce4e 100644 --- a/src/app/shared/fd_config.h +++ b/src/app/shared/fd_config.h @@ -11,7 +11,6 @@ #define AFFINITY_SZ (256UL) #define CONFIGURE_STAGE_COUNT ( 12UL) #define GOSSIP_TILE_ENTRYPOINTS_MAX ( 16UL) -#define SNAPSHOT_TILE_HTTP_PEERS_MAX ( 16UL) #define IP4_PORT_STR_MAX ( 22UL) struct fd_configh { @@ -123,33 +122,33 @@ struct fd_configf { } gossip; struct { - struct { + uint max_local_full_effective_age; + uint max_local_incremental_age; struct { - int enabled; + int allow_any; + ulong allow_list_cnt; + char allow_list[ 16 ][ FD_BASE58_ENCODED_32_SZ ]; + ulong block_list_cnt; + char block_list[ 16 ][ FD_BASE58_ENCODED_32_SZ ]; } gossip; - struct { - ulong peers_cnt; - struct { - int enabled; - char url[ PATH_MAX ]; - } peers[ SNAPSHOT_TILE_HTTP_PEERS_MAX ]; - } http; - + ulong servers_cnt; + char servers[ 16 ][ 128 ]; } sources; - int incremental_snapshots; - uint maximum_local_snapshot_age; - int genesis_download; - int download; - ulong known_validators_cnt; - char known_validators[ 16 ][ 256 ]; - uint minimum_download_speed_mib; - uint maximum_download_retry_abort; - uint max_full_snapshots_to_keep; - uint max_incremental_snapshots_to_keep; + int incremental_snapshots; + int genesis_download; + uint max_full_snapshots_to_keep; + uint max_incremental_snapshots_to_keep; + uint full_effective_age_cancel_threshold; + + struct { + uint min_speed_mib; + uint max_retry_abort; + } download; + } snapshots; struct { diff --git a/src/app/shared/fd_config_parse.c b/src/app/shared/fd_config_parse.c index 37e8f8b75e..b949319c57 100644 --- a/src/app/shared/fd_config_parse.c +++ b/src/app/shared/fd_config_parse.c @@ -95,19 +95,19 @@ fd_config_extract_podf( uchar * pod, CFG_POP ( ulong, store.max_completed_shred_sets ); + CFG_POP ( uint, snapshots.sources.max_local_full_effective_age ); + CFG_POP ( uint, snapshots.sources.max_local_incremental_age ); + CFG_POP ( bool, snapshots.sources.gossip.allow_any ); + CFG_POP_ARRAY( cstr, snapshots.sources.gossip.allow_list ); + CFG_POP_ARRAY( cstr, snapshots.sources.gossip.block_list ); + CFG_POP_ARRAY( cstr, snapshots.sources.servers ); CFG_POP ( bool, snapshots.incremental_snapshots ); - CFG_POP ( uint, snapshots.maximum_local_snapshot_age ); - CFG_POP ( bool, snapshots.genesis_download ); - CFG_POP ( bool, snapshots.download ); - CFG_POP_ARRAY( cstr, snapshots.known_validators ); - CFG_POP ( uint, snapshots.minimum_download_speed_mib ); - CFG_POP ( uint, snapshots.maximum_download_retry_abort ); + CFG_POP ( bool, snapshots.genesis_download ); CFG_POP ( uint, snapshots.max_full_snapshots_to_keep ); CFG_POP ( uint, snapshots.max_incremental_snapshots_to_keep ); - CFG_POP ( bool, snapshots.sources.gossip.enabled ); - CFG_POP_TABLE( bool, snapshots.sources.http, snapshots.sources.http.peers, enabled, 0 ); - CFG_POP_TABLE( cstr, snapshots.sources.http, snapshots.sources.http.peers, url, 1 ); - CFG_POP_TABLE_FINI( snapshots.sources.http ); + CFG_POP ( uint, snapshots.full_effective_age_cancel_threshold ); + CFG_POP ( uint, snapshots.download.min_speed_mib ); + CFG_POP ( uint, snapshots.download.max_retry_abort ); return config; } diff --git a/src/disco/topo/fd_topo.h b/src/disco/topo/fd_topo.h index 0a2e70f297..6a55a93451 100644 --- a/src/disco/topo/fd_topo.h +++ b/src/disco/topo/fd_topo.h @@ -502,22 +502,34 @@ struct fd_topo_tile { int slices_fd; } shredcap; - struct { + struct fd_topo_tile_snapct { char snapshots_path[ PATH_MAX ]; - int incremental_snapshot_fetch; - int do_download; - uint maximum_local_snapshot_age; - uint minimum_download_speed_mib; - uint maximum_download_retry_abort; + + struct { + uint max_local_full_effective_age; + uint max_local_incremental_age; + + struct { + int allow_any; + ulong allow_list_cnt; + fd_pubkey_t allow_list[ 16 ]; + ulong block_list_cnt; + fd_pubkey_t block_list[ 16 ]; + } gossip; + + ulong servers_cnt; + fd_ip4_port_t servers[ 16 ]; + } sources; + + int incremental_snapshots; uint max_full_snapshots_to_keep; uint max_incremental_snapshots_to_keep; - - int gossip_peers_enabled; + uint full_effective_age_cancel_threshold; struct { - ulong peers_cnt; - fd_ip4_port_t peers[ 16UL ]; - } http; + uint min_speed_mib; + uint max_retry_abort; + } download; } snapct; struct { diff --git a/src/discof/restore/fd_snapct_tile.c b/src/discof/restore/fd_snapct_tile.c index d34b540c6d..a2f87da06d 100644 --- a/src/discof/restore/fd_snapct_tile.c +++ b/src/discof/restore/fd_snapct_tile.c @@ -21,16 +21,26 @@ #define NAME "snapct" +/* FIXME: Implement gossip allow_list and block_list logic. */ +/* FIXME: Implement full_effective_age_cancel_threshold */ +/* FIXME: Implement min_speed_mib and other download health logic */ +/* FIXME: Implement max_retry_abort and retry logic in general */ +/* FIXME: Add more timeout config options and have consistent behavior */ +/* FIXME: Do a finishing pass over the default.toml config options / comments */ + #define GOSSIP_PEERS_MAX (FD_CONTACT_INFO_TABLE_SIZE) -#define SERVER_PEERS_MAX (16UL) /* Maximum number of configured http peers */ +#define SERVER_PEERS_MAX (FD_ARRAY_CNT((struct fd_topo_tile_snapct){0}.sources.servers)) #define TOTAL_PEERS_MAX (GOSSIP_PEERS_MAX + SERVER_PEERS_MAX) -#define IN_KIND_SNAPIN (0) -#define IN_KIND_SNAPLD (1) -#define IN_KIND_GOSSIP (2) -#define MAX_IN_LINKS (3) +#define IN_KIND_SNAPIN (0) +#define IN_KIND_SNAPLD (1) +#define IN_KIND_GOSSIP (2) +#define MAX_IN_LINKS (3) + +#define TEMP_FULL_SNAP_NAME ".snapshot.tar.bz2-partial" +#define TEMP_INCR_SNAP_NAME ".incremental-snapshot.tar.bz2-partial" -struct fd_restore_out_link { +struct fd_snapct_out_link { ulong idx; fd_wksp_t * mem; ulong chunk0; @@ -38,8 +48,7 @@ struct fd_restore_out_link { ulong chunk; ulong mtu; }; - -typedef struct fd_restore_out_link fd_restore_out_link_t; +typedef struct fd_snapct_out_link fd_snapct_out_link_t; #define FD_SNAPCT_GOSSIP_FRESH_DEADLINE_NANOS (7.5L*1000L*1000L*1000L) /* gossip contact info is pushed every 7.5 seconds */ #define FD_SNAPCT_GOSSIP_SATURATION_THRESHOLD (0.05) /* 5% fresh peers */ @@ -64,29 +73,32 @@ typedef struct fd_snapct_gossip_ci_entry fd_snapct_gossip_ci_entry_t; #include "../../util/tmpl/fd_map_chain.c" struct fd_snapct_tile { + struct fd_topo_tile_snapct config; + int gossip_enabled; + int download_enabled; + fd_ssping_t * ssping; fd_http_resolver_t * ssresolver; fd_sspeer_selector_t * selector; - int state; - int malformed; - long deadline_nanos; - int flush_ack; - + int state; + int malformed; + long deadline_nanos; + int flush_ack; fd_ip4_port_t addr; struct { - char full_snapshot_path[ PATH_MAX ]; - char incremental_snapshot_path[ PATH_MAX ]; - char full_snapshot_name[ PATH_MAX ]; - char incremental_snapshot_name[ PATH_MAX ]; - - int dir_fd; - int full_snapshot_fd; - int incremental_snapshot_fd; + int dir_fd; + int full_snapshot_fd; + int incremental_snapshot_fd; } local_out; - uchar in_kind[ MAX_IN_LINKS ]; + char http_full_snapshot_name[ PATH_MAX ]; + char http_incr_snapshot_name[ PATH_MAX ]; + + void const * gossip_in_mem; + void const * snapld_in_mem; + uchar in_kind[ MAX_IN_LINKS ]; struct { ulong full_slot; @@ -104,18 +116,6 @@ struct fd_snapct_tile { ulong incremental_snapshot_size; } local_in; - struct { - char path[ PATH_MAX ]; - int do_download; - int incremental_snapshot_fetch; - uint maximum_local_snapshot_age; - uint minimum_download_speed_mib; - uint maximum_download_retry_abort; - uint max_full_snapshots_to_keep; - uint max_incremental_snapshots_to_keep; - int gossip_peers_enabled; - } config; - struct { struct { ulong bytes_read; @@ -132,36 +132,30 @@ struct fd_snapct_tile { } incremental; } metrics; - struct { - fd_wksp_t * mem; - ulong chunk0; - ulong wmark; - ulong mtu; - } gossip_in; - - struct { - fd_wksp_t * mem; - ulong chunk0; - ulong wmark; - ulong mtu; - } snapld_in; - struct { fd_snapct_gossip_ci_entry_t * ci_table; gossip_ci_map_t * ci_map; - double fresh; ulong fresh_cnt; ulong total_cnt; int saturated; } gossip; - fd_restore_out_link_t out_ld; - fd_restore_out_link_t out_gui; - fd_restore_out_link_t out_rp; + fd_snapct_out_link_t out_ld; + fd_snapct_out_link_t out_gui; + fd_snapct_out_link_t out_rp; }; - typedef struct fd_snapct_tile fd_snapct_tile_t; +static int +gossip_enabled( fd_topo_tile_t const * tile ) { + return tile->snapct.sources.gossip.allow_any || tile->snapct.sources.gossip.allow_list_cnt>0UL; +} + +static int +download_enabled( fd_topo_tile_t const * tile ) { + return gossip_enabled( tile ) || tile->snapct.sources.servers_cnt>0UL; +} + static ulong scratch_align( void ) { return fd_ulong_max( alignof(fd_snapct_tile_t), @@ -192,9 +186,12 @@ should_shutdown( fd_snapct_tile_t * ctx ) { static int gossip_saturated( fd_snapct_tile_t * ctx, long now ) { - if( FD_UNLIKELY( !ctx->config.gossip_peers_enabled ) ) return 1; + if( FD_UNLIKELY( !ctx->gossip_enabled ) ) return 1; if( FD_UNLIKELY( ctx->gossip.saturated ) ) return 1; + /* FIXME: In the FD_SNAPCT_STATE_COLLECTING_PEERS state we are + constantly spinning on this function, re-iterating this large map. */ + ulong fresh_cnt = 0UL; ulong total_cnt = 0UL; for( gossip_ci_map_iter_t iter = gossip_ci_map_iter_init( ctx->gossip.ci_map, ctx->gossip.ci_table ); @@ -208,13 +205,14 @@ gossip_saturated( fd_snapct_tile_t * ctx, double fresh = total_cnt ? (double)fresh_cnt/(double)total_cnt : 1.0; ctx->gossip.fresh_cnt = fresh_cnt; ctx->gossip.total_cnt = total_cnt; - ctx->gossip.fresh = fresh; ctx->gossip.saturated = freshgossip.saturated; } static void metrics_write( fd_snapct_tile_t * ctx ) { + /* FIXME: Track/report FULL_NUM_RETRIES & INCREMENTAL_NUM_RETRIES */ + FD_MGAUGE_SET( SNAPCT, FULL_BYTES_READ, ctx->metrics.full.bytes_read ); FD_MGAUGE_SET( SNAPCT, FULL_BYTES_WRITTEN, ctx->metrics.full.bytes_written ); FD_MGAUGE_SET( SNAPCT, FULL_BYTES_TOTAL, ctx->metrics.full.bytes_total ); @@ -238,6 +236,8 @@ snapshot_path_gui_publish( fd_snapct_tile_t * ctx, fd_stem_context_t * stem, char const * path, int is_full ) { + /* FIXME: Consider whether we can get everything we need from metrics + rather than creating an entire link for this rare message */ fd_snapct_update_t * out = fd_chunk_to_laddr( ctx->out_gui.mem, ctx->out_gui.chunk ); FD_TEST( fd_cstr_printf_check( out->read_path, PATH_MAX, NULL, "%s", path ) ); out->is_download = 0; @@ -248,7 +248,7 @@ snapshot_path_gui_publish( fd_snapct_tile_t * ctx, static void predict_incremental( fd_snapct_tile_t * ctx ) { - if( FD_UNLIKELY( !ctx->config.incremental_snapshot_fetch ) ) return; + if( FD_UNLIKELY( !ctx->config.incremental_snapshots ) ) return; if( FD_UNLIKELY( ctx->predicted_incremental.full_slot==ULONG_MAX ) ) return; fd_sspeer_t best = fd_sspeer_selector_best( ctx->selector, 1, ctx->predicted_incremental.full_slot ); @@ -314,43 +314,30 @@ send_expected_slot( fd_snapct_tile_t * ctx, static void rename_snapshots( fd_snapct_tile_t * ctx ) { - if( FD_UNLIKELY( -1==ctx->local_out.dir_fd ) ) return; + FD_TEST( -1!=ctx->local_out.dir_fd ); + + /* FIXME: We should rename the full snapshot earlier as soon as the + download is complete. That way, if the validator crashes during the + incremental load, we can still use the snapshot on the next run. */ - if( FD_LIKELY( -1!=ctx->local_out.full_snapshot_fd && ctx->local_out.full_snapshot_name[ 0 ]!='\0' ) ) { - if( FD_UNLIKELY( -1==renameat( ctx->local_out.dir_fd, "snapshot.tar.bz2-partial", ctx->local_out.dir_fd, ctx->local_out.full_snapshot_name ) ) ) + if( FD_LIKELY( -1!=ctx->local_out.full_snapshot_fd && ctx->http_full_snapshot_name[ 0 ]!='\0' ) ) { + if( FD_UNLIKELY( -1==renameat( ctx->local_out.dir_fd, TEMP_FULL_SNAP_NAME, ctx->local_out.dir_fd, ctx->http_full_snapshot_name ) ) ) FD_LOG_ERR(( "renameat() failed (%i-%s)", errno, fd_io_strerror( errno ) )); } - if( FD_LIKELY( -1!=ctx->local_out.incremental_snapshot_fd && ctx->local_out.incremental_snapshot_name[ 0 ]!='\0' ) ) { - if( FD_UNLIKELY( -1==renameat( ctx->local_out.dir_fd, "incremental-snapshot.tar.bz2-partial", ctx->local_out.dir_fd, ctx->local_out.incremental_snapshot_name ) ) ) + if( FD_LIKELY( -1!=ctx->local_out.incremental_snapshot_fd && ctx->http_incr_snapshot_name[ 0 ]!='\0' ) ) { + if( FD_UNLIKELY( -1==renameat( ctx->local_out.dir_fd, TEMP_INCR_SNAP_NAME, ctx->local_out.dir_fd, ctx->http_incr_snapshot_name ) ) ) FD_LOG_ERR(( "renameat() failed (%i-%s)", errno, fd_io_strerror( errno ) )); } } -static void -remove_temp_files( fd_snapct_tile_t * ctx ) { - if( FD_UNLIKELY( -1==ctx->local_out.dir_fd ) ) return; - - if( FD_LIKELY( -1!=ctx->local_out.full_snapshot_fd ) ) { - if( FD_UNLIKELY( -1==unlinkat( ctx->local_out.dir_fd, "snapshot.tar.bz2-partial", 0 ) ) ) - FD_LOG_ERR(( "unlinkat(snapshot.tar.bz2-partial) failed (%i-%s)", errno, fd_io_strerror( errno ) )); - } - if( FD_LIKELY( -1!=ctx->local_out.incremental_snapshot_fd ) ) { - if( FD_UNLIKELY( -1==unlinkat( ctx->local_out.dir_fd, "incremental-snapshot.tar.bz2-partial", 0 ) ) ) - FD_LOG_ERR(( "unlinkat(incremental-snapshot.tar.bz2-partial) failed (%i-%s)", errno, fd_io_strerror( errno ) )); - } -} - static ulong rlimit_file_cnt( fd_topo_t const * topo FD_PARAM_UNUSED, - fd_topo_tile_t const * tile FD_PARAM_UNUSED ) { - /* stderr, logfile, dirfd, local out full fd, local out incremental - fd, and one spare for a socket(). */ - - return 1UL + /* stderr */ - 1UL + /* logfile */ - 1UL + /* ssping socket */ - SERVER_PEERS_MAX + /* http resolver max peers sockets */ - 3UL; /* dirfd + 2 snapshot file fds in the worst case */ + fd_topo_tile_t const * tile ) { + return 1UL + /* stderr */ + 1UL + /* logfile */ + 3UL + /* dirfd + 2 snapshot file fds in the worst case */ + !!download_enabled( tile ) + /* ssping socket */ + 2UL*tile->snapct.sources.servers_cnt; /* http resolver peer sockets (full + incr) */ } static ulong @@ -364,7 +351,8 @@ populate_allowed_seccomp( fd_topo_t const * topo, FD_SCRATCH_ALLOC_INIT( l, scratch ); fd_snapct_tile_t * ctx = FD_SCRATCH_ALLOC_APPEND( l, alignof(fd_snapct_tile_t), sizeof(fd_snapct_tile_t) ); - populate_sock_filter_policy_fd_snapct_tile( out_cnt, out, (uint)fd_log_private_logfile_fd(), (uint)ctx->local_out.dir_fd, (uint)ctx->local_out.full_snapshot_fd, (uint)ctx->local_out.incremental_snapshot_fd, (uint)fd_ssping_get_sockfd( ctx->ssping ) ); + int ping_fd = download_enabled( tile ) ? fd_ssping_get_sockfd( ctx->ssping ) : -1; + populate_sock_filter_policy_fd_snapct_tile( out_cnt, out, (uint)fd_log_private_logfile_fd(), (uint)ctx->local_out.dir_fd, (uint)ctx->local_out.full_snapshot_fd, (uint)ctx->local_out.incremental_snapshot_fd, (uint)ping_fd ); return sock_filter_policy_fd_snapct_tile_instr_cnt; } @@ -373,7 +361,7 @@ populate_allowed_fds( fd_topo_t const * topo, fd_topo_tile_t const * tile, ulong out_fds_cnt, int * out_fds ) { - if( FD_UNLIKELY( out_fds_cnt<5UL ) ) FD_LOG_ERR(( "out_fds_cnt %lu", out_fds_cnt )); + if( FD_UNLIKELY( out_fds_cnt<6UL ) ) FD_LOG_ERR(( "out_fds_cnt %lu", out_fds_cnt )); ulong out_cnt = 0; out_fds[ out_cnt++ ] = 2UL; /* stderr */ @@ -388,7 +376,7 @@ populate_allowed_fds( fd_topo_t const * topo, if( FD_LIKELY( -1!=ctx->local_out.dir_fd ) ) out_fds[ out_cnt++ ] = ctx->local_out.dir_fd; if( FD_LIKELY( -1!=ctx->local_out.full_snapshot_fd ) ) out_fds[ out_cnt++ ] = ctx->local_out.full_snapshot_fd; if( FD_LIKELY( -1!=ctx->local_out.incremental_snapshot_fd ) ) out_fds[ out_cnt++ ] = ctx->local_out.incremental_snapshot_fd; - out_fds[ out_cnt++ ] = fd_ssping_get_sockfd( ctx->ssping ); + if( FD_LIKELY( download_enabled( tile ) ) ) out_fds[ out_cnt++ ] = fd_ssping_get_sockfd( ctx->ssping ); return out_cnt; } @@ -410,13 +398,13 @@ init_load( fd_snapct_tile_t * ctx, these are already known immediately. */ if( full ) { ctx->metrics.full.bytes_total = ctx->local_in.full_snapshot_size; - fd_cstr_fini( ctx->local_out.full_snapshot_name ); + fd_cstr_fini( ctx->http_full_snapshot_name ); if( FD_LIKELY( !!ctx->out_gui.mem ) ) { snapshot_path_gui_publish( ctx, stem, ctx->local_in.full_snapshot_path, 1 ); } } else { ctx->metrics.incremental.bytes_total = ctx->local_in.incremental_snapshot_size; - fd_cstr_fini( ctx->local_out.incremental_snapshot_name ); + fd_cstr_fini( ctx->http_incr_snapshot_name ); if( FD_LIKELY( !!ctx->out_gui.mem ) ) { snapshot_path_gui_publish( ctx, stem, ctx->local_in.incremental_snapshot_path, 0 ); } @@ -431,8 +419,8 @@ after_credit( fd_snapct_tile_t * ctx, int * charge_busy FD_PARAM_UNUSED ) { long now = fd_log_wallclock(); - fd_ssping_advance( ctx->ssping, now, ctx->selector ); - fd_http_resolver_advance( ctx->ssresolver, now, ctx->selector ); + if( FD_LIKELY( ctx->ssping ) ) fd_ssping_advance( ctx->ssping, now, ctx->selector ); + if( FD_LIKELY( ctx->ssresolver ) ) fd_http_resolver_advance( ctx->ssresolver, now, ctx->selector ); /* send an expected slot message as the predicted incremental could have changed as a result of the pinger, resolver, or from @@ -445,14 +433,19 @@ after_credit( fd_snapct_tile_t * ctx, /* Note: All state transitions should occur within this switch statement to make it easier to reason about the state management. */ + /* FIXME: Collapse WAITING_FOR_PEERS and COLLECTING_PEERS states for + both full and incremental variants? */ + /* FIXME: Add INIT state so that we don't put the !download_enabled + logic in waiting_for_peers, which is weird. */ + switch ( ctx->state ) { /* ============================================================== */ case FD_SNAPCT_STATE_WAITING_FOR_PEERS: { if( FD_UNLIKELY( now>ctx->deadline_nanos ) ) FD_LOG_ERR(( "timed out waiting for peers." )); - if( FD_UNLIKELY( !ctx->config.do_download ) ) { - ulong local_slot = ctx->config.incremental_snapshot_fetch ? ctx->local_in.incremental_snapshot_slot : ctx->local_in.full_snapshot_slot; + if( FD_UNLIKELY( !ctx->download_enabled ) ) { + ulong local_slot = ctx->config.incremental_snapshots ? ctx->local_in.incremental_snapshot_slot : ctx->local_in.full_snapshot_slot; send_expected_slot( ctx, stem, local_slot ); FD_LOG_NOTICE(( "reading full snapshot from local file `%s`", ctx->local_in.full_snapshot_path )); ctx->predicted_incremental.full_slot = ctx->local_in.full_snapshot_slot; @@ -490,20 +483,25 @@ after_credit( fd_snapct_tile_t * ctx, } fd_sscluster_slot_t cluster = fd_sspeer_selector_cluster_slot( ctx->selector ); - if( FD_UNLIKELY( cluster.incremental==ULONG_MAX && ctx->config.incremental_snapshot_fetch ) ) { + if( FD_UNLIKELY( cluster.incremental==ULONG_MAX && ctx->config.incremental_snapshots ) ) { /* We must have a cluster full slot to be in this state. */ FD_TEST( cluster.full!=ULONG_MAX ); /* fall back to full snapshot only if the highest cluster slot is a full snapshot only */ - ctx->config.incremental_snapshot_fetch = 0; + ctx->config.incremental_snapshots = 0; } - ulong cluster_slot = ctx->config.incremental_snapshot_fetch ? cluster.incremental : cluster.full; - ulong local_slot = ctx->config.incremental_snapshot_fetch ? ctx->local_in.incremental_snapshot_slot : ctx->local_in.full_snapshot_slot; + /* FIXME: Revisit the local age logic with new effective age + concept. Measure cluster slot based on snapshots we can + download / trust. Reevaluate incremental age after the full + snapshot download is completed. etc. etc. */ + + ulong cluster_slot = ctx->config.incremental_snapshots ? cluster.incremental : cluster.full; + ulong local_slot = ctx->config.incremental_snapshots ? ctx->local_in.incremental_snapshot_slot : ctx->local_in.full_snapshot_slot; ulong local_slot_with_download = local_slot; - int local_too_old = local_slot!=ULONG_MAX && local_slotconfig.maximum_local_snapshot_age ); + int local_too_old = local_slot!=ULONG_MAX && local_slotconfig.sources.max_local_incremental_age ); int local_full_only = ctx->local_in.incremental_snapshot_slot==ULONG_MAX && ctx->local_in.full_snapshot_slot!=ULONG_MAX; - if( FD_LIKELY( (ctx->config.incremental_snapshot_fetch && local_full_only) || local_too_old ) ) { + if( FD_LIKELY( (ctx->config.incremental_snapshots && local_full_only) || local_too_old ) ) { fd_sspeer_t best_incremental = fd_sspeer_selector_best( ctx->selector, 1, ctx->local_in.full_snapshot_slot ); if( FD_LIKELY( best_incremental.addr.l ) ) { ctx->predicted_incremental.slot = best_incremental.ssinfo.incremental.slot; @@ -512,7 +510,7 @@ after_credit( fd_snapct_tile_t * ctx, } } - int can_use_local_full = local_slot_with_download!=ULONG_MAX && local_slot_with_download>=fd_ulong_sat_sub( cluster_slot, ctx->config.maximum_local_snapshot_age ); + int can_use_local_full = local_slot_with_download!=ULONG_MAX && local_slot_with_download>=fd_ulong_sat_sub( cluster_slot, ctx->config.sources.max_local_full_effective_age ); if( FD_LIKELY( can_use_local_full ) ) { send_expected_slot( ctx, stem, local_slot ); @@ -521,7 +519,7 @@ after_credit( fd_snapct_tile_t * ctx, ctx->state = FD_SNAPCT_STATE_READING_FULL_FILE; init_load( ctx, stem, 1, 1 ); } else { - if( FD_UNLIKELY( !ctx->config.incremental_snapshot_fetch ) ) send_expected_slot( ctx, stem, best.ssinfo.full.slot ); + if( FD_UNLIKELY( !ctx->config.incremental_snapshots ) ) send_expected_slot( ctx, stem, best.ssinfo.full.slot ); fd_sspeer_t best_incremental = fd_sspeer_selector_best( ctx->selector, 1, best.ssinfo.full.slot ); if( FD_LIKELY( best_incremental.addr.l ) ) { @@ -529,7 +527,7 @@ after_credit( fd_snapct_tile_t * ctx, send_expected_slot( ctx, stem, best_incremental.ssinfo.incremental.slot ); } - FD_LOG_NOTICE(( "downloading full snapshot from http://" FD_IP4_ADDR_FMT ":%hu/snapshot.tar.bz2", FD_IP4_ADDR_FMT_ARGS( best.addr.addr ), best.addr.port )); + FD_LOG_NOTICE(( "downloading full snapshot from http://" FD_IP4_ADDR_FMT ":%hu/snapshot.tar.bz2", FD_IP4_ADDR_FMT_ARGS( best.addr.addr ), fd_ushort_bswap( best.addr.port ) )); ctx->addr = best.addr; ctx->state = FD_SNAPCT_STATE_READING_FULL_HTTP; ctx->predicted_incremental.full_slot = best.ssinfo.full.slot; @@ -549,7 +547,7 @@ after_credit( fd_snapct_tile_t * ctx, } ctx->addr = best.addr; - FD_LOG_NOTICE(( "downloading incremental snapshot from http://" FD_IP4_ADDR_FMT ":%hu/incremental-snapshot.tar.bz2", FD_IP4_ADDR_FMT_ARGS( best.addr.addr ), best.addr.port )); + FD_LOG_NOTICE(( "downloading incremental snapshot from http://" FD_IP4_ADDR_FMT ":%hu/incremental-snapshot.tar.bz2", FD_IP4_ADDR_FMT_ARGS( best.addr.addr ), fd_ushort_bswap( best.addr.port ) )); ctx->state = FD_SNAPCT_STATE_READING_INCREMENTAL_HTTP; init_load( ctx, stem, 0, 0 ); break; @@ -569,7 +567,6 @@ after_credit( fd_snapct_tile_t * ctx, } ctx->state = FD_SNAPCT_STATE_SHUTDOWN; - remove_temp_files( ctx ); metrics_write( ctx ); /* ensures that shutdown state is written to metrics workspace before the tile actually shuts down */ fd_stem_publish( stem, ctx->out_ld.idx, FD_SNAPSHOT_MSG_CTRL_SHUTDOWN, 0UL, 0UL, 0UL, 0UL, 0UL ); break; @@ -584,7 +581,7 @@ after_credit( fd_snapct_tile_t * ctx, ctx->flush_ack = 0; ctx->state = FD_SNAPCT_STATE_FLUSHING_INCREMENTAL_HTTP_RESET; FD_LOG_WARNING(( "error downloading snapshot from http://" FD_IP4_ADDR_FMT ":%hu/incremental-snapshot.tar.bz2", - FD_IP4_ADDR_FMT_ARGS( ctx->addr.addr ), ctx->addr.port )); + FD_IP4_ADDR_FMT_ARGS( ctx->addr.addr ), fd_ushort_bswap( ctx->addr.port ) )); fd_ssping_invalidate( ctx->ssping, ctx->addr, fd_log_wallclock() ); fd_sspeer_selector_remove( ctx->selector, ctx->addr ); break; @@ -609,9 +606,8 @@ after_credit( fd_snapct_tile_t * ctx, break; } - if( FD_LIKELY( !ctx->config.incremental_snapshot_fetch ) ) { + if( FD_LIKELY( !ctx->config.incremental_snapshots ) ) { ctx->state = FD_SNAPCT_STATE_SHUTDOWN; - remove_temp_files( ctx ); metrics_write( ctx ); /* ensures that shutdown state is written to metrics workspace before the tile actually shuts down */ fd_stem_publish( stem, ctx->out_ld.idx, FD_SNAPSHOT_MSG_CTRL_SHUTDOWN, 0UL, 0UL, 0UL, 0UL, 0UL ); break; @@ -637,13 +633,13 @@ after_credit( fd_snapct_tile_t * ctx, ctx->flush_ack = 0; ctx->state = FD_SNAPCT_STATE_FLUSHING_FULL_HTTP_RESET; FD_LOG_WARNING(( "error downloading snapshot from http://" FD_IP4_ADDR_FMT ":%hu/snapshot.tar.bz2", - FD_IP4_ADDR_FMT_ARGS( ctx->addr.addr ), ctx->addr.port )); + FD_IP4_ADDR_FMT_ARGS( ctx->addr.addr ), fd_ushort_bswap( ctx->addr.port ) )); fd_ssping_invalidate( ctx->ssping, ctx->addr, fd_log_wallclock() ); fd_sspeer_selector_remove( ctx->selector, ctx->addr ); break; } - if( FD_LIKELY( !ctx->config.incremental_snapshot_fetch ) ) { + if( FD_LIKELY( !ctx->config.incremental_snapshots ) ) { ctx->state = FD_SNAPCT_STATE_SHUTDOWN; rename_snapshots( ctx ); metrics_write( ctx ); /* ensures that shutdown state is written to metrics workspace before the tile actually shuts down */ @@ -652,10 +648,10 @@ after_credit( fd_snapct_tile_t * ctx, } /* Get the best incremental peer to download from */ - /* TODO: We should just transition to collecting_peers_incremental - here rather than failing the full snapshot? */ fd_sspeer_t best = fd_sspeer_selector_best( ctx->selector, 1, ctx->predicted_incremental.full_slot ); if( FD_UNLIKELY( !best.addr.l ) ) { + /* FIXME: We should just transition to collecting_peers_incremental + here rather than failing the full snapshot? */ fd_stem_publish( stem, ctx->out_ld.idx, FD_SNAPSHOT_MSG_CTRL_FAIL, 0UL, 0UL, 0UL, 0UL, 0UL ); ctx->flush_ack = 0; ctx->state = FD_SNAPCT_STATE_FLUSHING_FULL_HTTP_RESET; @@ -668,7 +664,7 @@ after_credit( fd_snapct_tile_t * ctx, } ctx->addr = best.addr; - FD_LOG_NOTICE(( "downloading incremental snapshot from http://" FD_IP4_ADDR_FMT ":%hu/incremental-snapshot.tar.bz2", FD_IP4_ADDR_FMT_ARGS( ctx->addr.addr ), ctx->addr.port )); + FD_LOG_NOTICE(( "downloading incremental snapshot from http://" FD_IP4_ADDR_FMT ":%hu/incremental-snapshot.tar.bz2", FD_IP4_ADDR_FMT_ARGS( ctx->addr.addr ), fd_ushort_bswap( ctx->addr.port ) )); ctx->state = FD_SNAPCT_STATE_READING_INCREMENTAL_HTTP; init_load( ctx, stem, 0, 0 ); break; @@ -678,9 +674,9 @@ after_credit( fd_snapct_tile_t * ctx, case FD_SNAPCT_STATE_FLUSHING_FULL_FILE_RESET: if( !ctx->flush_ack ) break; - ctx->metrics.full.bytes_read = 0UL; - ctx->metrics.full.bytes_written = 0UL; - ctx->metrics.full.bytes_total = 0UL; + ctx->metrics.full.bytes_read = 0UL; + ctx->metrics.full.bytes_written = 0UL; + ctx->metrics.full.bytes_total = 0UL; ctx->metrics.incremental.bytes_read = 0UL; ctx->metrics.incremental.bytes_written = 0UL; @@ -715,7 +711,7 @@ after_credit( fd_snapct_tile_t * ctx, } FD_TEST( ctx->metrics.full.bytes_total!=0UL ); if( FD_UNLIKELY( ctx->metrics.full.bytes_read == ctx->metrics.full.bytes_total ) ) { - ulong sig = ctx->config.incremental_snapshot_fetch ? FD_SNAPSHOT_MSG_CTRL_NEXT : FD_SNAPSHOT_MSG_CTRL_DONE; + ulong sig = ctx->config.incremental_snapshots ? FD_SNAPSHOT_MSG_CTRL_NEXT : FD_SNAPSHOT_MSG_CTRL_DONE; fd_stem_publish( stem, ctx->out_ld.idx, sig, 0UL, 0UL, 0UL, 0UL, 0UL ); ctx->state = FD_SNAPCT_STATE_FLUSHING_FULL_FILE; ctx->flush_ack = 0; @@ -748,13 +744,13 @@ after_credit( fd_snapct_tile_t * ctx, ctx->flush_ack = 0; ctx->state = FD_SNAPCT_STATE_FLUSHING_FULL_HTTP_RESET; FD_LOG_WARNING(( "error downloading snapshot from http://" FD_IP4_ADDR_FMT ":%hu/snapshot.tar.bz2", - FD_IP4_ADDR_FMT_ARGS( ctx->addr.addr ), ctx->addr.port )); + FD_IP4_ADDR_FMT_ARGS( ctx->addr.addr ), fd_ushort_bswap( ctx->addr.port ) )); fd_ssping_invalidate( ctx->ssping, ctx->addr, fd_log_wallclock() ); fd_sspeer_selector_remove( ctx->selector, ctx->addr ); break; } if( FD_UNLIKELY( ctx->metrics.full.bytes_total!=0UL && ctx->metrics.full.bytes_read==ctx->metrics.full.bytes_total ) ) { - ulong sig = ctx->config.incremental_snapshot_fetch ? FD_SNAPSHOT_MSG_CTRL_NEXT : FD_SNAPSHOT_MSG_CTRL_DONE; + ulong sig = ctx->config.incremental_snapshots ? FD_SNAPSHOT_MSG_CTRL_NEXT : FD_SNAPSHOT_MSG_CTRL_DONE; fd_stem_publish( stem, ctx->out_ld.idx, sig, 0UL, 0UL, 0UL, 0UL, 0UL ); ctx->state = FD_SNAPCT_STATE_FLUSHING_FULL_HTTP; ctx->flush_ack = 0; @@ -769,7 +765,7 @@ after_credit( fd_snapct_tile_t * ctx, ctx->flush_ack = 0; ctx->state = FD_SNAPCT_STATE_FLUSHING_INCREMENTAL_HTTP_RESET; FD_LOG_WARNING(( "error downloading snapshot from http://" FD_IP4_ADDR_FMT ":%hu/incremental-snapshot.tar.bz2", - FD_IP4_ADDR_FMT_ARGS( ctx->addr.addr ), ctx->addr.port )); + FD_IP4_ADDR_FMT_ARGS( ctx->addr.addr ), fd_ushort_bswap( ctx->addr.port ) )); fd_ssping_invalidate( ctx->ssping, ctx->addr, fd_log_wallclock() ); fd_sspeer_selector_remove( ctx->selector, ctx->addr ); break; @@ -795,38 +791,33 @@ gossip_frag( fd_snapct_tile_t * ctx, ulong sig, ulong sz FD_PARAM_UNUSED, ulong chunk ) { + FD_TEST( ctx->gossip_enabled ); - if( !( ( sig==FD_GOSSIP_UPDATE_TAG_CONTACT_INFO || - sig==FD_GOSSIP_UPDATE_TAG_CONTACT_INFO_REMOVE || - sig==FD_GOSSIP_UPDATE_TAG_SNAPSHOT_HASHES ) && - ctx->config.gossip_peers_enabled ) ) return; + if( !( sig==FD_GOSSIP_UPDATE_TAG_CONTACT_INFO || + sig==FD_GOSSIP_UPDATE_TAG_CONTACT_INFO_REMOVE || + sig==FD_GOSSIP_UPDATE_TAG_SNAPSHOT_HASHES ) ) return; - FD_TEST( chunk>=ctx->gossip_in.chunk0 && chunk<=ctx->gossip_in.wmark ); - fd_gossip_update_message_t const * msg = fd_chunk_to_laddr_const( ctx->gossip_in.mem, chunk ); + fd_gossip_update_message_t const * msg = fd_chunk_to_laddr_const( ctx->gossip_in_mem, chunk ); switch( msg->tag ) { case FD_GOSSIP_UPDATE_TAG_CONTACT_INFO: { - /* FIXME: Keep ports as network byte order */ - fd_ip4_port_t new_addr = msg->contact_info.contact_info->sockets[ FD_CONTACT_INFO_SOCKET_RPC ]; - new_addr.port = fd_ushort_bswap( new_addr.port ); - - if( FD_LIKELY( ctx->config.gossip_peers_enabled ) ) { - fd_snapct_gossip_ci_entry_t * entry = ctx->gossip.ci_table + msg->contact_info.idx; - if( FD_UNLIKELY( !fd_pubkey_eq( &entry->pubkey, (fd_pubkey_t const *)msg->origin_pubkey ) ) ) { - FD_TEST( fd_pubkey_check_zero( &entry->pubkey ) ); - FD_TEST( ULONG_MAX==gossip_ci_map_idx_query_const( ctx->gossip.ci_map, (fd_pubkey_t const *)msg->origin_pubkey, ULONG_MAX, ctx->gossip.ci_table ) ); - gossip_ci_map_idx_insert( ctx->gossip.ci_map, msg->contact_info.idx, ctx->gossip.ci_table ); - entry->pubkey = *(fd_pubkey_t const *)msg->origin_pubkey; - entry->wallclock_nanos = msg->wallclock_nanos; - } - fd_ip4_port_t cur_addr = entry->rpc_addr; - if( new_addr.l!=cur_addr.l ) { - entry->rpc_addr = new_addr; - if( FD_LIKELY( !!cur_addr.l ) ) { - int removed = fd_ssping_remove( ctx->ssping, cur_addr ); - if( FD_LIKELY( removed ) ) fd_sspeer_selector_remove( ctx->selector, cur_addr ); - } - if( FD_LIKELY( !!new_addr.l ) ) fd_ssping_add( ctx->ssping, new_addr ); + fd_snapct_gossip_ci_entry_t * entry = ctx->gossip.ci_table + msg->contact_info.idx; + if( FD_UNLIKELY( !fd_pubkey_eq( &entry->pubkey, (fd_pubkey_t const *)msg->origin_pubkey ) ) ) { + FD_TEST( fd_pubkey_check_zero( &entry->pubkey ) ); + FD_TEST( ULONG_MAX==gossip_ci_map_idx_query_const( ctx->gossip.ci_map, (fd_pubkey_t const *)msg->origin_pubkey, ULONG_MAX, ctx->gossip.ci_table ) ); + entry->pubkey = *(fd_pubkey_t const *)msg->origin_pubkey; + entry->rpc_addr.l = 0UL; + entry->wallclock_nanos = msg->wallclock_nanos; + gossip_ci_map_idx_insert( ctx->gossip.ci_map, msg->contact_info.idx, ctx->gossip.ci_table ); + } + fd_ip4_port_t cur_addr = entry->rpc_addr; + fd_ip4_port_t new_addr = msg->contact_info.contact_info->sockets[ FD_CONTACT_INFO_SOCKET_RPC ]; + if( new_addr.l!=cur_addr.l ) { + entry->rpc_addr = new_addr; + if( FD_LIKELY( !!cur_addr.l ) ) { + int removed = fd_ssping_remove( ctx->ssping, cur_addr ); + if( FD_LIKELY( removed ) ) fd_sspeer_selector_remove( ctx->selector, cur_addr ); } + if( FD_LIKELY( !!new_addr.l ) ) fd_ssping_add( ctx->ssping, new_addr ); } break; } @@ -850,9 +841,7 @@ gossip_frag( fd_snapct_tile_t * ctx, ulong idx = gossip_ci_map_idx_query_const( ctx->gossip.ci_map, (fd_pubkey_t const *)msg->origin_pubkey, ULONG_MAX, ctx->gossip.ci_table ); if( FD_LIKELY( idx!=ULONG_MAX ) ) { fd_snapct_gossip_ci_entry_t * entry = ctx->gossip.ci_table + idx; - if( FD_LIKELY( ctx->config.gossip_peers_enabled ) ) { - on_snapshot_hash( ctx, entry->rpc_addr, msg ); - } + on_snapshot_hash( ctx, entry->rpc_addr, msg ); } break; } @@ -884,10 +873,9 @@ snapld_frag( fd_snapct_tile_t * ctx, } FD_TEST( sz==sizeof(fd_ssctrl_meta_t) ); - fd_ssctrl_meta_t const * meta = fd_chunk_to_laddr_const( ctx->snapld_in.mem, chunk ); + fd_ssctrl_meta_t const * meta = fd_chunk_to_laddr_const( ctx->snapld_in_mem, chunk ); - if( full ) fd_memcpy( ctx->local_out.full_snapshot_name, meta->name, PATH_MAX ); - else fd_memcpy( ctx->local_out.incremental_snapshot_name, meta->name, PATH_MAX ); + fd_memcpy( full ? ctx->http_full_snapshot_name : ctx->http_incr_snapshot_name, meta->name, PATH_MAX ); if( FD_LIKELY( !!ctx->out_gui.mem ) ) { char snapshot_path[ PATH_MAX+30UL ]; /* 30 is fd_cstr_nlen( "https://255.255.255.255:65536/", ULONG_MAX ) */ @@ -949,12 +937,11 @@ snapld_frag( fd_snapct_tile_t * ctx, else ctx->metrics.incremental.bytes_read += sz; if( !file && -1!=ctx->local_out.dir_fd ) { - uchar const * data = fd_chunk_to_laddr_const( ctx->snapld_in.mem, chunk ); + uchar const * data = fd_chunk_to_laddr_const( ctx->snapld_in_mem, chunk ); int fd = full ? ctx->local_out.full_snapshot_fd : ctx->local_out.incremental_snapshot_fd; long result = write( fd, data, sz ); if( FD_UNLIKELY( -1==result && errno==ENOSPC ) ) { - char const * snapshot_path = full ? ctx->local_out.full_snapshot_path : ctx->local_out.incremental_snapshot_path; - FD_LOG_ERR(( "Out of disk space when writing out snapshot data to `%s`", snapshot_path )); + FD_LOG_ERR(( "Out of disk space when writing out snapshot data to `%s`", ctx->config.snapshots_path )); } else if( FD_UNLIKELY( 0L>result ) ) { FD_LOG_ERR(( "write() failed (%i-%s)", errno, fd_io_strerror( errno ) )); } else if( FD_UNLIKELY( sz!=(ulong)result ) ) { @@ -971,7 +958,7 @@ snapld_frag( fd_snapct_tile_t * ctx, FD_LOG_WARNING(( "expected %s snapshot size of %lu bytes but read %lu bytes", full ? "full" : "incremental", full ? ctx->metrics.full.bytes_total : ctx->metrics.incremental.bytes_total, - full ? ctx->metrics.full.bytes_read : ctx->metrics.incremental.bytes_read )); + full ? ctx->metrics.full.bytes_read : ctx->metrics.incremental.bytes_read )); } } @@ -1055,7 +1042,7 @@ returnable_frag( fd_snapct_tile_t * ctx, snapld_frag( ctx, sig, sz, chunk, stem ); } else if( ctx->in_kind[ in_idx ]==IN_KIND_SNAPIN ) { snapin_frag( ctx, sig ); - } else FD_LOG_ERR(( "invalid in_kind %lu %hhu", in_idx, ctx->in_kind[ in_idx ] )); + } else FD_LOG_ERR(( "invalid in_kind %lu %u", in_idx, (uint)ctx->in_kind[ in_idx ] )); return 0; } @@ -1068,22 +1055,11 @@ privileged_init( fd_topo_t * topo, fd_snapct_tile_t * ctx = FD_SCRATCH_ALLOC_APPEND( l, alignof(fd_snapct_tile_t), sizeof(fd_snapct_tile_t) ); void * _ssping = FD_SCRATCH_ALLOC_APPEND( l, fd_ssping_align(), fd_ssping_footprint( TOTAL_PEERS_MAX ) ); - fd_memset( &ctx->metrics, 0, sizeof(ctx->metrics) ); - - ctx->ssping = fd_ssping_join( fd_ssping_new( _ssping, TOTAL_PEERS_MAX, 1UL, on_ping, ctx ) ); - FD_TEST( ctx->ssping ); - - /* By default, the snapct tile selects peers and its initial state is - WAITING_FOR_PEERS. */ - ctx->state = FD_SNAPCT_STATE_WAITING_FOR_PEERS; - ctx->deadline_nanos = fd_log_wallclock() + FD_SNAPCT_WAITING_FOR_PEERS_TIMEOUT_DEADLINE_NANOS; - - ctx->local_out.dir_fd = -1; - ctx->local_out.full_snapshot_fd = -1; - ctx->local_out.incremental_snapshot_fd = -1; - fd_memset( ctx->local_out.full_snapshot_name, 0, PATH_MAX ); - fd_memset( ctx->local_out.incremental_snapshot_name, 0, PATH_MAX ); + ctx->ssping = NULL; + if( FD_LIKELY( download_enabled( tile ) ) ) ctx->ssping = fd_ssping_join( fd_ssping_new( _ssping, TOTAL_PEERS_MAX, 1UL, on_ping, ctx ) ); + /* FIXME: We will keep too many snapshots if we have local snapshots + but elect not to use them due to their age. */ fd_ssarchive_remove_old_snapshots( tile->snapct.snapshots_path, tile->snapct.max_full_snapshots_to_keep, tile->snapct.max_incremental_snapshots_to_keep ); @@ -1093,17 +1069,21 @@ privileged_init( fd_topo_t * topo, char full_path[ PATH_MAX ] = {0}; char incremental_path[ PATH_MAX ] = {0}; if( FD_UNLIKELY( -1==fd_ssarchive_latest_pair( tile->snapct.snapshots_path, - tile->snapct.incremental_snapshot_fetch, + tile->snapct.incremental_snapshots, &full_slot, &incremental_slot, full_path, incremental_path ) ) ) { - if( FD_UNLIKELY( !tile->snapct.do_download ) ) { - FD_LOG_ERR(( "No snapshots found in `%s` and downloading is disabled. " - "Please enable downloading via [snapshots.download] and restart.", tile->snapct.snapshots_path )); + if( FD_UNLIKELY( !download_enabled( tile ) ) ) { + FD_LOG_ERR(( "No snapshots found in `%s` and no download sources are enabled. " + "Please enable downloading via [snapshots.sources] and restart.", tile->snapct.snapshots_path )); } ctx->local_in.full_snapshot_slot = ULONG_MAX; ctx->local_in.incremental_snapshot_slot = ULONG_MAX; + ctx->local_in.full_snapshot_size = 0UL; + ctx->local_in.incremental_snapshot_size = 0UL; + fd_cstr_fini( ctx->local_in.full_snapshot_path ); + fd_cstr_fini( ctx->local_in.incremental_snapshot_path ); } else { FD_TEST( full_slot!=ULONG_MAX ); @@ -1122,33 +1102,41 @@ privileged_init( fd_topo_t * topo, if( FD_UNLIKELY( -1==stat( ctx->local_in.incremental_snapshot_path, &incremental_stat ) ) ) FD_LOG_ERR(( "stat() failed `%s` (%i-%s)", incremental_path, errno, fd_io_strerror( errno ) )); if( FD_UNLIKELY( !S_ISREG( incremental_stat.st_mode ) ) ) FD_LOG_ERR(( "incremental snapshot path `%s` is not a regular file", incremental_path )); ctx->local_in.incremental_snapshot_size = (ulong)incremental_stat.st_size; + } else { + ctx->local_in.incremental_snapshot_size = 0UL; + fd_cstr_fini( ctx->local_in.incremental_snapshot_path ); } - - ctx->local_out.dir_fd = -1; - ctx->local_out.full_snapshot_fd = -1; - ctx->local_out.incremental_snapshot_fd = -1; } + /* FIXME: Do not create the temporary files if downloading is not + enabled by the configuration. Account for this in rlimit. */ + + ctx->local_out.dir_fd = -1; + ctx->local_out.full_snapshot_fd = -1; + ctx->local_out.incremental_snapshot_fd = -1; + /* Set up download descriptors because even if we have local snapshots, we may need to download new snapshots if the local snapshots are too old. */ ctx->local_out.dir_fd = open( tile->snapct.snapshots_path, O_DIRECTORY|O_CLOEXEC ); if( FD_UNLIKELY( -1==ctx->local_out.dir_fd ) ) FD_LOG_ERR(( "open() failed `%s` (%i-%s)", tile->snapct.snapshots_path, errno, fd_io_strerror( errno ) )); - FD_TEST( fd_cstr_printf_check( ctx->local_out.full_snapshot_path, PATH_MAX, NULL, "%s/snapshot.tar.bz2-partial", tile->snapct.snapshots_path ) ); - ctx->local_out.full_snapshot_fd = openat( ctx->local_out.dir_fd, "snapshot.tar.bz2-partial", O_WRONLY|O_CREAT|O_TRUNC|O_NONBLOCK, S_IRUSR|S_IWUSR ); - if( FD_UNLIKELY( -1==ctx->local_out.full_snapshot_fd ) ) FD_LOG_ERR(( "open() failed `%s` (%i-%s)", ctx->local_out.full_snapshot_path, errno, fd_io_strerror( errno ) )); + char full_snapshot_path[ PATH_MAX ]; + FD_TEST( fd_cstr_printf_check( full_snapshot_path, PATH_MAX, NULL, "%s/" TEMP_FULL_SNAP_NAME, tile->snapct.snapshots_path ) ); + ctx->local_out.full_snapshot_fd = openat( ctx->local_out.dir_fd, TEMP_FULL_SNAP_NAME, O_WRONLY|O_CREAT|O_TRUNC|O_NONBLOCK, S_IRUSR|S_IWUSR ); + if( FD_UNLIKELY( -1==ctx->local_out.full_snapshot_fd ) ) FD_LOG_ERR(( "open() failed `%s` (%i-%s)", full_snapshot_path, errno, fd_io_strerror( errno ) )); - if( FD_LIKELY( tile->snapct.incremental_snapshot_fetch ) ) { - FD_TEST( fd_cstr_printf_check( ctx->local_out.incremental_snapshot_path, PATH_MAX, NULL, "%s/incremental-snapshot.tar.bz2-partial", tile->snapct.snapshots_path ) ); - ctx->local_out.incremental_snapshot_fd = openat( ctx->local_out.dir_fd, "incremental-snapshot.tar.bz2-partial", O_WRONLY|O_CREAT|O_TRUNC|O_NONBLOCK, S_IRUSR|S_IWUSR ); - if( FD_UNLIKELY( -1==ctx->local_out.incremental_snapshot_fd ) ) FD_LOG_ERR(( "open() failed `%s` (%i-%s)", ctx->local_out.incremental_snapshot_path, errno, fd_io_strerror( errno ) )); + if( FD_LIKELY( tile->snapct.incremental_snapshots ) ) { + char incremental_snapshot_path[ PATH_MAX ]; + FD_TEST( fd_cstr_printf_check( incremental_snapshot_path, PATH_MAX, NULL, "%s/" TEMP_INCR_SNAP_NAME, tile->snapct.snapshots_path ) ); + ctx->local_out.incremental_snapshot_fd = openat( ctx->local_out.dir_fd, TEMP_INCR_SNAP_NAME, O_WRONLY|O_CREAT|O_TRUNC|O_NONBLOCK, S_IRUSR|S_IWUSR ); + if( FD_UNLIKELY( -1==ctx->local_out.incremental_snapshot_fd ) ) FD_LOG_ERR(( "open() failed `%s` (%i-%s)", incremental_snapshot_path, errno, fd_io_strerror( errno ) )); } else { ctx->local_out.incremental_snapshot_fd = -1; } } -static inline fd_restore_out_link_t +static inline fd_snapct_out_link_t out1( fd_topo_t const * topo, fd_topo_tile_t const * tile, char const * name ) { @@ -1162,15 +1150,15 @@ out1( fd_topo_t const * topo, } } - if( FD_UNLIKELY( idx==ULONG_MAX ) ) return (fd_restore_out_link_t){ .idx = ULONG_MAX, .mem = NULL, .chunk0 = 0, .wmark = 0, .chunk = 0, .mtu = 0 }; + if( FD_UNLIKELY( idx==ULONG_MAX ) ) return (fd_snapct_out_link_t){ .idx = ULONG_MAX, .mem = NULL, .chunk0 = 0, .wmark = 0, .chunk = 0, .mtu = 0 }; ulong mtu = topo->links[ tile->out_link_id[ idx ] ].mtu; - if( FD_UNLIKELY( mtu==0UL ) ) return (fd_restore_out_link_t){ .idx = idx, .mem = NULL, .chunk0 = ULONG_MAX, .wmark = ULONG_MAX, .chunk = ULONG_MAX, .mtu = mtu }; + if( FD_UNLIKELY( mtu==0UL ) ) return (fd_snapct_out_link_t){ .idx = idx, .mem = NULL, .chunk0 = ULONG_MAX, .wmark = ULONG_MAX, .chunk = ULONG_MAX, .mtu = mtu }; void * mem = topo->workspaces[ topo->objs[ topo->links[ tile->out_link_id[ idx ] ].dcache_obj_id ].wksp_id ].wksp; ulong chunk0 = fd_dcache_compact_chunk0( mem, topo->links[ tile->out_link_id[ idx ] ].dcache ); ulong wmark = fd_dcache_compact_wmark ( mem, topo->links[ tile->out_link_id[ idx ] ].dcache, mtu ); - return (fd_restore_out_link_t){ .idx = idx, .mem = mem, .chunk0 = chunk0, .wmark = wmark, .chunk = chunk0, .mtu = mtu }; + return (fd_snapct_out_link_t){ .idx = idx, .mem = mem, .chunk0 = chunk0, .wmark = wmark, .chunk = chunk0, .mtu = mtu }; } static void @@ -1186,72 +1174,69 @@ unprivileged_init( fd_topo_t * topo, void * _ssresolver = FD_SCRATCH_ALLOC_APPEND( l, fd_http_resolver_align(), fd_http_resolver_footprint( SERVER_PEERS_MAX ) ); void * _selector = FD_SCRATCH_ALLOC_APPEND( l, fd_sspeer_selector_align(), fd_sspeer_selector_footprint( TOTAL_PEERS_MAX ) ); - ctx->malformed = 0; - - fd_memcpy( ctx->config.path, tile->snapct.snapshots_path, PATH_MAX ); - ctx->config.incremental_snapshot_fetch = tile->snapct.incremental_snapshot_fetch; - ctx->config.do_download = tile->snapct.do_download; - ctx->config.maximum_local_snapshot_age = tile->snapct.maximum_local_snapshot_age; - ctx->config.minimum_download_speed_mib = tile->snapct.minimum_download_speed_mib; - ctx->config.max_full_snapshots_to_keep = tile->snapct.max_full_snapshots_to_keep; - ctx->config.max_incremental_snapshots_to_keep = tile->snapct.max_incremental_snapshots_to_keep; - ctx->config.gossip_peers_enabled = tile->snapct.gossip_peers_enabled; + fd_memcpy( &ctx->config, &tile->snapct, sizeof(ctx->config) ); + ctx->gossip_enabled = gossip_enabled( tile ); + ctx->download_enabled = download_enabled( tile ); - if( FD_UNLIKELY( !tile->snapct.maximum_download_retry_abort ) ) ctx->config.maximum_download_retry_abort = UINT_MAX; - else ctx->config.maximum_download_retry_abort = tile->snapct.maximum_download_retry_abort; + ctx->ssresolver = NULL; + if( ctx->config.sources.servers_cnt ) { + ctx->ssresolver = fd_http_resolver_join( fd_http_resolver_new( _ssresolver, SERVER_PEERS_MAX, ctx->config.incremental_snapshots, on_resolve, ctx ) ); + for( ulong i=0UL; isnapct.sources.servers_cnt; i++ ) { + fd_ssping_add ( ctx->ssping, tile->snapct.sources.servers[ i ] ); + fd_http_resolver_add( ctx->ssresolver, tile->snapct.sources.servers[ i ] ); + } + } - ctx->selector = fd_sspeer_selector_join( fd_sspeer_selector_new( _selector, TOTAL_PEERS_MAX, ctx->config.incremental_snapshot_fetch, 1UL ) ); + ctx->selector = fd_sspeer_selector_join( fd_sspeer_selector_new( _selector, TOTAL_PEERS_MAX, ctx->config.incremental_snapshots, 1UL ) ); - fd_memset( _ci_table, 0, sizeof(fd_snapct_gossip_ci_entry_t) * GOSSIP_PEERS_MAX ); - ctx->gossip.ci_table = _ci_table; + ctx->state = FD_SNAPCT_STATE_WAITING_FOR_PEERS; + ctx->malformed = 0; + ctx->deadline_nanos = fd_log_wallclock() + FD_SNAPCT_WAITING_FOR_PEERS_TIMEOUT_DEADLINE_NANOS; + ctx->flush_ack = 0; + ctx->addr.l = 0UL; - ctx->gossip.ci_map = gossip_ci_map_join( gossip_ci_map_new( _ci_map, gossip_ci_map_chain_cnt_est( GOSSIP_PEERS_MAX ), 0UL ) ); + fd_memset( ctx->http_full_snapshot_name, 0, PATH_MAX ); + fd_memset( ctx->http_incr_snapshot_name, 0, PATH_MAX ); - int has_snapld_dc = 0, has_snapin_rd = 0; + ctx->gossip_in_mem = NULL; + int has_snapld_dc = 0, has_snapin_ct = 0; FD_TEST( tile->in_cnt<=MAX_IN_LINKS ); for( ulong i=0UL; i<(tile->in_cnt); i++ ) { fd_topo_link_t * in_link = &topo->links[ tile->in_link_id[ i ] ]; if( 0==strcmp( in_link->name, "gossip_out" ) ) { - ctx->in_kind[ i ] = IN_KIND_GOSSIP; - ctx->gossip_in.mem = topo->workspaces[ topo->objs[ in_link->dcache_obj_id ].wksp_id ].wksp; - ctx->gossip_in.chunk0 = fd_dcache_compact_chunk0( ctx->gossip_in.mem, in_link->dcache ); - ctx->gossip_in.wmark = fd_dcache_compact_wmark ( ctx->gossip_in.mem, in_link->dcache, in_link->mtu ); - ctx->gossip_in.mtu = in_link->mtu; + ctx->in_kind[ i ] = IN_KIND_GOSSIP; + ctx->gossip_in_mem = topo->workspaces[ topo->objs[ in_link->dcache_obj_id ].wksp_id ].wksp; } else if( 0==strcmp( in_link->name, "snapld_dc" ) ) { - ctx->in_kind[ i ] = IN_KIND_SNAPLD; - ctx->snapld_in.mem = topo->workspaces[ topo->objs[ in_link->dcache_obj_id ].wksp_id ].wksp; - ctx->snapld_in.chunk0 = fd_dcache_compact_chunk0( ctx->snapld_in.mem, in_link->dcache ); - ctx->snapld_in.wmark = fd_dcache_compact_wmark ( ctx->snapld_in.mem, in_link->dcache, in_link->mtu ); - ctx->snapld_in.mtu = in_link->mtu; + ctx->in_kind[ i ] = IN_KIND_SNAPLD; + ctx->snapld_in_mem = topo->workspaces[ topo->objs[ in_link->dcache_obj_id ].wksp_id ].wksp; FD_TEST( !has_snapld_dc ); has_snapld_dc = 1; - } else if( 0==strcmp( in_link->name, "snapin_rd" ) ) { + } else if( 0==strcmp( in_link->name, "snapin_ct" ) ) { ctx->in_kind[ i ] = IN_KIND_SNAPIN; - FD_TEST( !has_snapin_rd ); - has_snapin_rd = 1; + FD_TEST( !has_snapin_ct ); + has_snapin_ct = 1; } } - FD_TEST( has_snapld_dc && has_snapin_rd ); + FD_TEST( has_snapld_dc && has_snapin_ct ); + FD_TEST( ctx->gossip_enabled==(ctx->gossip_in_mem!=NULL) ); + + ctx->predicted_incremental.full_slot = ULONG_MAX; + ctx->predicted_incremental.slot = ULONG_MAX; + ctx->predicted_incremental.dirty = 0; + + fd_memset( &ctx->metrics, 0, sizeof(ctx->metrics) ); - ctx->ssresolver = fd_http_resolver_join( fd_http_resolver_new( _ssresolver, SERVER_PEERS_MAX, ctx->config.incremental_snapshot_fetch, on_resolve, ctx ) ); - FD_TEST( ctx->ssresolver ); + fd_memset( _ci_table, 0, sizeof(fd_snapct_gossip_ci_entry_t) * GOSSIP_PEERS_MAX ); + ctx->gossip.ci_table = _ci_table; + ctx->gossip.ci_map = gossip_ci_map_join( gossip_ci_map_new( _ci_map, gossip_ci_map_chain_cnt_est( GOSSIP_PEERS_MAX ), 0UL ) ); + ctx->gossip.fresh_cnt = 0UL; + ctx->gossip.total_cnt = 0UL; + ctx->gossip.saturated = 0; if( FD_UNLIKELY( tile->out_cnt<2UL || tile->out_cnt>3UL ) ) FD_LOG_ERR(( "tile `" NAME "` has %lu outs, expected 2-3", tile->out_cnt )); ctx->out_ld = out1( topo, tile, "snapct_ld" ); ctx->out_gui = out1( topo, tile, "snapct_gui" ); ctx->out_rp = out1( topo, tile, "snapct_repr" ); - - for( ulong i=0UL; isnapct.http.peers_cnt; i++ ) { - tile->snapct.http.peers[ i ].port = fd_ushort_bswap( tile->snapct.http.peers[ i ].port ); /* TODO: should be fixed in a future PR */ - fd_ssping_add( ctx->ssping, tile->snapct.http.peers[ i ] ); - fd_http_resolver_add( ctx->ssresolver, tile->snapct.http.peers[ i ] ); - } - - ctx->predicted_incremental.full_slot = ULONG_MAX; - ctx->predicted_incremental.slot = ULONG_MAX; - ctx->predicted_incremental.dirty = 0; - - ctx->gossip.saturated = 0; } /* after_credit can result in as many as 5 stem publishes in some code diff --git a/src/discof/restore/fd_snapct_tile.seccomppolicy b/src/discof/restore/fd_snapct_tile.seccomppolicy index 6d8cd32f57..88fa53a0e8 100644 --- a/src/discof/restore/fd_snapct_tile.seccomppolicy +++ b/src/discof/restore/fd_snapct_tile.seccomppolicy @@ -113,13 +113,5 @@ setsockopt: (and (not (or (eq (arg 0) 2) renameat: (and (eq (arg 0) dir_fd) (eq (arg 2) dir_fd)) -# snapshot: the temporary snapshot files are unlinked if just local -# snapshot directories are loaded in. -# -# arg 0 is the file descriptor for the directory that the temporary -# files are located in -unlinkat: (and (eq (arg 0) dir_fd) - (eq (arg 2) 0)) - # shutdown: exit is called on shutdown exit: (eq (arg 0) 0) diff --git a/src/discof/restore/fd_snapin_tile.c b/src/discof/restore/fd_snapin_tile.c index e2a00a8ca5..4769cc8d61 100644 --- a/src/discof/restore/fd_snapin_tile.c +++ b/src/discof/restore/fd_snapin_tile.c @@ -941,7 +941,7 @@ unprivileged_init( fd_topo_t * topo, if( FD_UNLIKELY( tile->out_cnt!=2UL ) ) FD_LOG_ERR(( "tile `" NAME "` has %lu outs, expected 2", tile->out_cnt )); fd_topo_link_t * snapct_link = &topo->links[ tile->out_link_id[ FD_SNAPIN_OUT_SNAPCT ] ]; - FD_TEST( 0==strcmp( snapct_link->name, "snapin_rd" ) ); + FD_TEST( 0==strcmp( snapct_link->name, "snapin_ct" ) ); fd_topo_link_t * writer_link = &topo->links[ tile->out_link_id[ FD_SNAPIN_OUT_MANIFEST ] ]; FD_TEST( 0==strcmp( writer_link->name, "snapin_manif" ) ); diff --git a/src/discof/restore/generated/fd_snapct_tile_seccomp.h b/src/discof/restore/generated/fd_snapct_tile_seccomp.h index 30d362383f..5c1931957e 100644 --- a/src/discof/restore/generated/fd_snapct_tile_seccomp.h +++ b/src/discof/restore/generated/fd_snapct_tile_seccomp.h @@ -21,224 +21,214 @@ #else # error "Target architecture is unsupported by seccomp." #endif -static const unsigned int sock_filter_policy_fd_snapct_tile_instr_cnt = 111; +static const unsigned int sock_filter_policy_fd_snapct_tile_instr_cnt = 106; static void populate_sock_filter_policy_fd_snapct_tile( ulong out_cnt, struct sock_filter * out, uint logfile_fd, uint dir_fd, uint out_full_fd, uint out_inc_fd, uint ping_fd ) { - FD_TEST( out_cnt >= 111 ); - struct sock_filter filter[111] = { + FD_TEST( out_cnt >= 106 ); + struct sock_filter filter[106] = { /* Check: Jump to RET_KILL_PROCESS if the script's arch != the runtime arch */ BPF_STMT( BPF_LD | BPF_W | BPF_ABS, ( offsetof( struct seccomp_data, arch ) ) ), - BPF_JUMP( BPF_JMP | BPF_JEQ | BPF_K, ARCH_NR, 0, /* RET_KILL_PROCESS */ 107 ), + BPF_JUMP( BPF_JMP | BPF_JEQ | BPF_K, ARCH_NR, 0, /* RET_KILL_PROCESS */ 102 ), /* loading syscall number in accumulator */ BPF_STMT( BPF_LD | BPF_W | BPF_ABS, ( offsetof( struct seccomp_data, nr ) ) ), /* allow write based on expression */ - BPF_JUMP( BPF_JMP | BPF_JEQ | BPF_K, SYS_write, /* check_write */ 13, 0 ), + BPF_JUMP( BPF_JMP | BPF_JEQ | BPF_K, SYS_write, /* check_write */ 12, 0 ), /* allow fsync based on expression */ - BPF_JUMP( BPF_JMP | BPF_JEQ | BPF_K, SYS_fsync, /* check_fsync */ 20, 0 ), + BPF_JUMP( BPF_JMP | BPF_JEQ | BPF_K, SYS_fsync, /* check_fsync */ 19, 0 ), /* allow socket based on expression */ - BPF_JUMP( BPF_JMP | BPF_JEQ | BPF_K, SYS_socket, /* check_socket */ 21, 0 ), + BPF_JUMP( BPF_JMP | BPF_JEQ | BPF_K, SYS_socket, /* check_socket */ 20, 0 ), /* allow connect based on expression */ - BPF_JUMP( BPF_JMP | BPF_JEQ | BPF_K, SYS_connect, /* check_connect */ 26, 0 ), + BPF_JUMP( BPF_JMP | BPF_JEQ | BPF_K, SYS_connect, /* check_connect */ 25, 0 ), /* allow close based on expression */ - BPF_JUMP( BPF_JMP | BPF_JEQ | BPF_K, SYS_close, /* check_close */ 37, 0 ), + BPF_JUMP( BPF_JMP | BPF_JEQ | BPF_K, SYS_close, /* check_close */ 36, 0 ), /* simply allow ppoll */ - BPF_JUMP( BPF_JMP | BPF_JEQ | BPF_K, SYS_ppoll, /* RET_ALLOW */ 101, 0 ), + BPF_JUMP( BPF_JMP | BPF_JEQ | BPF_K, SYS_ppoll, /* RET_ALLOW */ 96, 0 ), /* allow sendto based on expression */ - BPF_JUMP( BPF_JMP | BPF_JEQ | BPF_K, SYS_sendto, /* check_sendto */ 47, 0 ), + BPF_JUMP( BPF_JMP | BPF_JEQ | BPF_K, SYS_sendto, /* check_sendto */ 46, 0 ), /* allow sendmmsg based on expression */ - BPF_JUMP( BPF_JMP | BPF_JEQ | BPF_K, SYS_sendmmsg, /* check_sendmmsg */ 58, 0 ), + BPF_JUMP( BPF_JMP | BPF_JEQ | BPF_K, SYS_sendmmsg, /* check_sendmmsg */ 57, 0 ), /* allow recvfrom based on expression */ - BPF_JUMP( BPF_JMP | BPF_JEQ | BPF_K, SYS_recvfrom, /* check_recvfrom */ 61, 0 ), + BPF_JUMP( BPF_JMP | BPF_JEQ | BPF_K, SYS_recvfrom, /* check_recvfrom */ 60, 0 ), /* allow setsockopt based on expression */ - BPF_JUMP( BPF_JMP | BPF_JEQ | BPF_K, SYS_setsockopt, /* check_setsockopt */ 70, 0 ), + BPF_JUMP( BPF_JMP | BPF_JEQ | BPF_K, SYS_setsockopt, /* check_setsockopt */ 69, 0 ), /* allow renameat based on expression */ - BPF_JUMP( BPF_JMP | BPF_JEQ | BPF_K, SYS_renameat, /* check_renameat */ 85, 0 ), - /* allow unlinkat based on expression */ - BPF_JUMP( BPF_JMP | BPF_JEQ | BPF_K, SYS_unlinkat, /* check_unlinkat */ 88, 0 ), + BPF_JUMP( BPF_JMP | BPF_JEQ | BPF_K, SYS_renameat, /* check_renameat */ 84, 0 ), /* allow exit based on expression */ - BPF_JUMP( BPF_JMP | BPF_JEQ | BPF_K, SYS_exit, /* check_exit */ 91, 0 ), + BPF_JUMP( BPF_JMP | BPF_JEQ | BPF_K, SYS_exit, /* check_exit */ 87, 0 ), /* none of the syscalls matched */ - { BPF_JMP | BPF_JA, 0, 0, /* RET_KILL_PROCESS */ 92 }, + { BPF_JMP | BPF_JA, 0, 0, /* RET_KILL_PROCESS */ 88 }, // check_write: /* load syscall argument 0 in accumulator */ BPF_STMT( BPF_LD | BPF_W | BPF_ABS, offsetof(struct seccomp_data, args[0])), - BPF_JUMP( BPF_JMP | BPF_JEQ | BPF_K, 2, /* RET_ALLOW */ 91, /* lbl_1 */ 0 ), + BPF_JUMP( BPF_JMP | BPF_JEQ | BPF_K, 2, /* RET_ALLOW */ 87, /* lbl_1 */ 0 ), // lbl_1: /* load syscall argument 0 in accumulator */ BPF_STMT( BPF_LD | BPF_W | BPF_ABS, offsetof(struct seccomp_data, args[0])), - BPF_JUMP( BPF_JMP | BPF_JEQ | BPF_K, logfile_fd, /* RET_ALLOW */ 89, /* lbl_2 */ 0 ), + BPF_JUMP( BPF_JMP | BPF_JEQ | BPF_K, logfile_fd, /* RET_ALLOW */ 85, /* lbl_2 */ 0 ), // lbl_2: /* load syscall argument 0 in accumulator */ BPF_STMT( BPF_LD | BPF_W | BPF_ABS, offsetof(struct seccomp_data, args[0])), - BPF_JUMP( BPF_JMP | BPF_JEQ | BPF_K, out_full_fd, /* RET_ALLOW */ 87, /* lbl_3 */ 0 ), + BPF_JUMP( BPF_JMP | BPF_JEQ | BPF_K, out_full_fd, /* RET_ALLOW */ 83, /* lbl_3 */ 0 ), // lbl_3: /* load syscall argument 0 in accumulator */ BPF_STMT( BPF_LD | BPF_W | BPF_ABS, offsetof(struct seccomp_data, args[0])), - BPF_JUMP( BPF_JMP | BPF_JEQ | BPF_K, out_inc_fd, /* RET_ALLOW */ 85, /* RET_KILL_PROCESS */ 84 ), + BPF_JUMP( BPF_JMP | BPF_JEQ | BPF_K, out_inc_fd, /* RET_ALLOW */ 81, /* RET_KILL_PROCESS */ 80 ), // check_fsync: /* load syscall argument 0 in accumulator */ BPF_STMT( BPF_LD | BPF_W | BPF_ABS, offsetof(struct seccomp_data, args[0])), - BPF_JUMP( BPF_JMP | BPF_JEQ | BPF_K, logfile_fd, /* RET_ALLOW */ 83, /* RET_KILL_PROCESS */ 82 ), + BPF_JUMP( BPF_JMP | BPF_JEQ | BPF_K, logfile_fd, /* RET_ALLOW */ 79, /* RET_KILL_PROCESS */ 78 ), // check_socket: /* load syscall argument 0 in accumulator */ BPF_STMT( BPF_LD | BPF_W | BPF_ABS, offsetof(struct seccomp_data, args[0])), - BPF_JUMP( BPF_JMP | BPF_JEQ | BPF_K, AF_INET, /* lbl_4 */ 0, /* RET_KILL_PROCESS */ 80 ), + BPF_JUMP( BPF_JMP | BPF_JEQ | BPF_K, AF_INET, /* lbl_4 */ 0, /* RET_KILL_PROCESS */ 76 ), // lbl_4: /* load syscall argument 1 in accumulator */ BPF_STMT( BPF_LD | BPF_W | BPF_ABS, offsetof(struct seccomp_data, args[1])), - BPF_JUMP( BPF_JMP | BPF_JEQ | BPF_K, SOCK_STREAM|SOCK_NONBLOCK, /* lbl_5 */ 0, /* RET_KILL_PROCESS */ 78 ), + BPF_JUMP( BPF_JMP | BPF_JEQ | BPF_K, SOCK_STREAM|SOCK_NONBLOCK, /* lbl_5 */ 0, /* RET_KILL_PROCESS */ 74 ), // lbl_5: /* load syscall argument 2 in accumulator */ BPF_STMT( BPF_LD | BPF_W | BPF_ABS, offsetof(struct seccomp_data, args[2])), - BPF_JUMP( BPF_JMP | BPF_JEQ | BPF_K, 0, /* RET_ALLOW */ 77, /* RET_KILL_PROCESS */ 76 ), + BPF_JUMP( BPF_JMP | BPF_JEQ | BPF_K, 0, /* RET_ALLOW */ 73, /* RET_KILL_PROCESS */ 72 ), // check_connect: /* load syscall argument 0 in accumulator */ BPF_STMT( BPF_LD | BPF_W | BPF_ABS, offsetof(struct seccomp_data, args[0])), - BPF_JUMP( BPF_JMP | BPF_JEQ | BPF_K, 2, /* RET_KILL_PROCESS */ 74, /* lbl_6 */ 0 ), + BPF_JUMP( BPF_JMP | BPF_JEQ | BPF_K, 2, /* RET_KILL_PROCESS */ 70, /* lbl_6 */ 0 ), // lbl_6: /* load syscall argument 0 in accumulator */ BPF_STMT( BPF_LD | BPF_W | BPF_ABS, offsetof(struct seccomp_data, args[0])), - BPF_JUMP( BPF_JMP | BPF_JEQ | BPF_K, logfile_fd, /* RET_KILL_PROCESS */ 72, /* lbl_7 */ 0 ), + BPF_JUMP( BPF_JMP | BPF_JEQ | BPF_K, logfile_fd, /* RET_KILL_PROCESS */ 68, /* lbl_7 */ 0 ), // lbl_7: /* load syscall argument 0 in accumulator */ BPF_STMT( BPF_LD | BPF_W | BPF_ABS, offsetof(struct seccomp_data, args[0])), - BPF_JUMP( BPF_JMP | BPF_JEQ | BPF_K, dir_fd, /* RET_KILL_PROCESS */ 70, /* lbl_8 */ 0 ), + BPF_JUMP( BPF_JMP | BPF_JEQ | BPF_K, dir_fd, /* RET_KILL_PROCESS */ 66, /* lbl_8 */ 0 ), // lbl_8: /* load syscall argument 0 in accumulator */ BPF_STMT( BPF_LD | BPF_W | BPF_ABS, offsetof(struct seccomp_data, args[0])), - BPF_JUMP( BPF_JMP | BPF_JEQ | BPF_K, out_full_fd, /* RET_KILL_PROCESS */ 68, /* lbl_9 */ 0 ), + BPF_JUMP( BPF_JMP | BPF_JEQ | BPF_K, out_full_fd, /* RET_KILL_PROCESS */ 64, /* lbl_9 */ 0 ), // lbl_9: /* load syscall argument 0 in accumulator */ BPF_STMT( BPF_LD | BPF_W | BPF_ABS, offsetof(struct seccomp_data, args[0])), - BPF_JUMP( BPF_JMP | BPF_JEQ | BPF_K, out_inc_fd, /* RET_KILL_PROCESS */ 66, /* lbl_10 */ 0 ), + BPF_JUMP( BPF_JMP | BPF_JEQ | BPF_K, out_inc_fd, /* RET_KILL_PROCESS */ 62, /* lbl_10 */ 0 ), // lbl_10: /* load syscall argument 0 in accumulator */ BPF_STMT( BPF_LD | BPF_W | BPF_ABS, offsetof(struct seccomp_data, args[0])), - BPF_JUMP( BPF_JMP | BPF_JEQ | BPF_K, ping_fd, /* RET_KILL_PROCESS */ 64, /* RET_ALLOW */ 65 ), + BPF_JUMP( BPF_JMP | BPF_JEQ | BPF_K, ping_fd, /* RET_KILL_PROCESS */ 60, /* RET_ALLOW */ 61 ), // check_close: /* load syscall argument 0 in accumulator */ BPF_STMT( BPF_LD | BPF_W | BPF_ABS, offsetof(struct seccomp_data, args[0])), - BPF_JUMP( BPF_JMP | BPF_JEQ | BPF_K, 2, /* RET_KILL_PROCESS */ 62, /* lbl_11 */ 0 ), + BPF_JUMP( BPF_JMP | BPF_JEQ | BPF_K, 2, /* RET_KILL_PROCESS */ 58, /* lbl_11 */ 0 ), // lbl_11: /* load syscall argument 0 in accumulator */ BPF_STMT( BPF_LD | BPF_W | BPF_ABS, offsetof(struct seccomp_data, args[0])), - BPF_JUMP( BPF_JMP | BPF_JEQ | BPF_K, logfile_fd, /* RET_KILL_PROCESS */ 60, /* lbl_12 */ 0 ), + BPF_JUMP( BPF_JMP | BPF_JEQ | BPF_K, logfile_fd, /* RET_KILL_PROCESS */ 56, /* lbl_12 */ 0 ), // lbl_12: /* load syscall argument 0 in accumulator */ BPF_STMT( BPF_LD | BPF_W | BPF_ABS, offsetof(struct seccomp_data, args[0])), - BPF_JUMP( BPF_JMP | BPF_JEQ | BPF_K, dir_fd, /* RET_KILL_PROCESS */ 58, /* lbl_13 */ 0 ), + BPF_JUMP( BPF_JMP | BPF_JEQ | BPF_K, dir_fd, /* RET_KILL_PROCESS */ 54, /* lbl_13 */ 0 ), // lbl_13: /* load syscall argument 0 in accumulator */ BPF_STMT( BPF_LD | BPF_W | BPF_ABS, offsetof(struct seccomp_data, args[0])), - BPF_JUMP( BPF_JMP | BPF_JEQ | BPF_K, out_full_fd, /* RET_KILL_PROCESS */ 56, /* lbl_14 */ 0 ), + BPF_JUMP( BPF_JMP | BPF_JEQ | BPF_K, out_full_fd, /* RET_KILL_PROCESS */ 52, /* lbl_14 */ 0 ), // lbl_14: /* load syscall argument 0 in accumulator */ BPF_STMT( BPF_LD | BPF_W | BPF_ABS, offsetof(struct seccomp_data, args[0])), - BPF_JUMP( BPF_JMP | BPF_JEQ | BPF_K, out_inc_fd, /* RET_KILL_PROCESS */ 54, /* lbl_15 */ 0 ), + BPF_JUMP( BPF_JMP | BPF_JEQ | BPF_K, out_inc_fd, /* RET_KILL_PROCESS */ 50, /* lbl_15 */ 0 ), // lbl_15: /* load syscall argument 0 in accumulator */ BPF_STMT( BPF_LD | BPF_W | BPF_ABS, offsetof(struct seccomp_data, args[0])), - BPF_JUMP( BPF_JMP | BPF_JEQ | BPF_K, ping_fd, /* RET_KILL_PROCESS */ 52, /* RET_ALLOW */ 53 ), + BPF_JUMP( BPF_JMP | BPF_JEQ | BPF_K, ping_fd, /* RET_KILL_PROCESS */ 48, /* RET_ALLOW */ 49 ), // check_sendto: /* load syscall argument 0 in accumulator */ BPF_STMT( BPF_LD | BPF_W | BPF_ABS, offsetof(struct seccomp_data, args[0])), - BPF_JUMP( BPF_JMP | BPF_JEQ | BPF_K, 2, /* RET_KILL_PROCESS */ 50, /* lbl_16 */ 0 ), + BPF_JUMP( BPF_JMP | BPF_JEQ | BPF_K, 2, /* RET_KILL_PROCESS */ 46, /* lbl_16 */ 0 ), // lbl_16: /* load syscall argument 0 in accumulator */ BPF_STMT( BPF_LD | BPF_W | BPF_ABS, offsetof(struct seccomp_data, args[0])), - BPF_JUMP( BPF_JMP | BPF_JEQ | BPF_K, logfile_fd, /* RET_KILL_PROCESS */ 48, /* lbl_17 */ 0 ), + BPF_JUMP( BPF_JMP | BPF_JEQ | BPF_K, logfile_fd, /* RET_KILL_PROCESS */ 44, /* lbl_17 */ 0 ), // lbl_17: /* load syscall argument 0 in accumulator */ BPF_STMT( BPF_LD | BPF_W | BPF_ABS, offsetof(struct seccomp_data, args[0])), - BPF_JUMP( BPF_JMP | BPF_JEQ | BPF_K, dir_fd, /* RET_KILL_PROCESS */ 46, /* lbl_18 */ 0 ), + BPF_JUMP( BPF_JMP | BPF_JEQ | BPF_K, dir_fd, /* RET_KILL_PROCESS */ 42, /* lbl_18 */ 0 ), // lbl_18: /* load syscall argument 0 in accumulator */ BPF_STMT( BPF_LD | BPF_W | BPF_ABS, offsetof(struct seccomp_data, args[0])), - BPF_JUMP( BPF_JMP | BPF_JEQ | BPF_K, out_full_fd, /* RET_KILL_PROCESS */ 44, /* lbl_19 */ 0 ), + BPF_JUMP( BPF_JMP | BPF_JEQ | BPF_K, out_full_fd, /* RET_KILL_PROCESS */ 40, /* lbl_19 */ 0 ), // lbl_19: /* load syscall argument 0 in accumulator */ BPF_STMT( BPF_LD | BPF_W | BPF_ABS, offsetof(struct seccomp_data, args[0])), - BPF_JUMP( BPF_JMP | BPF_JEQ | BPF_K, out_inc_fd, /* RET_KILL_PROCESS */ 42, /* lbl_20 */ 0 ), + BPF_JUMP( BPF_JMP | BPF_JEQ | BPF_K, out_inc_fd, /* RET_KILL_PROCESS */ 38, /* lbl_20 */ 0 ), // lbl_20: /* load syscall argument 0 in accumulator */ BPF_STMT( BPF_LD | BPF_W | BPF_ABS, offsetof(struct seccomp_data, args[0])), - BPF_JUMP( BPF_JMP | BPF_JEQ | BPF_K, ping_fd, /* RET_KILL_PROCESS */ 40, /* RET_ALLOW */ 41 ), + BPF_JUMP( BPF_JMP | BPF_JEQ | BPF_K, ping_fd, /* RET_KILL_PROCESS */ 36, /* RET_ALLOW */ 37 ), // check_sendmmsg: /* load syscall argument 0 in accumulator */ BPF_STMT( BPF_LD | BPF_W | BPF_ABS, offsetof(struct seccomp_data, args[0])), - BPF_JUMP( BPF_JMP | BPF_JEQ | BPF_K, ping_fd, /* lbl_21 */ 0, /* RET_KILL_PROCESS */ 38 ), + BPF_JUMP( BPF_JMP | BPF_JEQ | BPF_K, ping_fd, /* lbl_21 */ 0, /* RET_KILL_PROCESS */ 34 ), // lbl_21: /* load syscall argument 3 in accumulator */ BPF_STMT( BPF_LD | BPF_W | BPF_ABS, offsetof(struct seccomp_data, args[3])), - BPF_JUMP( BPF_JMP | BPF_JEQ | BPF_K, 0, /* RET_ALLOW */ 37, /* RET_KILL_PROCESS */ 36 ), + BPF_JUMP( BPF_JMP | BPF_JEQ | BPF_K, 0, /* RET_ALLOW */ 33, /* RET_KILL_PROCESS */ 32 ), // check_recvfrom: /* load syscall argument 0 in accumulator */ BPF_STMT( BPF_LD | BPF_W | BPF_ABS, offsetof(struct seccomp_data, args[0])), - BPF_JUMP( BPF_JMP | BPF_JEQ | BPF_K, 2, /* RET_KILL_PROCESS */ 34, /* lbl_22 */ 0 ), + BPF_JUMP( BPF_JMP | BPF_JEQ | BPF_K, 2, /* RET_KILL_PROCESS */ 30, /* lbl_22 */ 0 ), // lbl_22: /* load syscall argument 0 in accumulator */ BPF_STMT( BPF_LD | BPF_W | BPF_ABS, offsetof(struct seccomp_data, args[0])), - BPF_JUMP( BPF_JMP | BPF_JEQ | BPF_K, logfile_fd, /* RET_KILL_PROCESS */ 32, /* lbl_23 */ 0 ), + BPF_JUMP( BPF_JMP | BPF_JEQ | BPF_K, logfile_fd, /* RET_KILL_PROCESS */ 28, /* lbl_23 */ 0 ), // lbl_23: /* load syscall argument 0 in accumulator */ BPF_STMT( BPF_LD | BPF_W | BPF_ABS, offsetof(struct seccomp_data, args[0])), - BPF_JUMP( BPF_JMP | BPF_JEQ | BPF_K, dir_fd, /* RET_KILL_PROCESS */ 30, /* lbl_24 */ 0 ), + BPF_JUMP( BPF_JMP | BPF_JEQ | BPF_K, dir_fd, /* RET_KILL_PROCESS */ 26, /* lbl_24 */ 0 ), // lbl_24: /* load syscall argument 0 in accumulator */ BPF_STMT( BPF_LD | BPF_W | BPF_ABS, offsetof(struct seccomp_data, args[0])), - BPF_JUMP( BPF_JMP | BPF_JEQ | BPF_K, out_full_fd, /* RET_KILL_PROCESS */ 28, /* lbl_25 */ 0 ), + BPF_JUMP( BPF_JMP | BPF_JEQ | BPF_K, out_full_fd, /* RET_KILL_PROCESS */ 24, /* lbl_25 */ 0 ), // lbl_25: /* load syscall argument 0 in accumulator */ BPF_STMT( BPF_LD | BPF_W | BPF_ABS, offsetof(struct seccomp_data, args[0])), - BPF_JUMP( BPF_JMP | BPF_JEQ | BPF_K, out_inc_fd, /* RET_KILL_PROCESS */ 26, /* RET_ALLOW */ 27 ), + BPF_JUMP( BPF_JMP | BPF_JEQ | BPF_K, out_inc_fd, /* RET_KILL_PROCESS */ 22, /* RET_ALLOW */ 23 ), // check_setsockopt: /* load syscall argument 0 in accumulator */ BPF_STMT( BPF_LD | BPF_W | BPF_ABS, offsetof(struct seccomp_data, args[0])), - BPF_JUMP( BPF_JMP | BPF_JEQ | BPF_K, 2, /* RET_KILL_PROCESS */ 24, /* lbl_27 */ 0 ), + BPF_JUMP( BPF_JMP | BPF_JEQ | BPF_K, 2, /* RET_KILL_PROCESS */ 20, /* lbl_27 */ 0 ), // lbl_27: /* load syscall argument 0 in accumulator */ BPF_STMT( BPF_LD | BPF_W | BPF_ABS, offsetof(struct seccomp_data, args[0])), - BPF_JUMP( BPF_JMP | BPF_JEQ | BPF_K, logfile_fd, /* RET_KILL_PROCESS */ 22, /* lbl_28 */ 0 ), + BPF_JUMP( BPF_JMP | BPF_JEQ | BPF_K, logfile_fd, /* RET_KILL_PROCESS */ 18, /* lbl_28 */ 0 ), // lbl_28: /* load syscall argument 0 in accumulator */ BPF_STMT( BPF_LD | BPF_W | BPF_ABS, offsetof(struct seccomp_data, args[0])), - BPF_JUMP( BPF_JMP | BPF_JEQ | BPF_K, dir_fd, /* RET_KILL_PROCESS */ 20, /* lbl_29 */ 0 ), + BPF_JUMP( BPF_JMP | BPF_JEQ | BPF_K, dir_fd, /* RET_KILL_PROCESS */ 16, /* lbl_29 */ 0 ), // lbl_29: /* load syscall argument 0 in accumulator */ BPF_STMT( BPF_LD | BPF_W | BPF_ABS, offsetof(struct seccomp_data, args[0])), - BPF_JUMP( BPF_JMP | BPF_JEQ | BPF_K, out_full_fd, /* RET_KILL_PROCESS */ 18, /* lbl_30 */ 0 ), + BPF_JUMP( BPF_JMP | BPF_JEQ | BPF_K, out_full_fd, /* RET_KILL_PROCESS */ 14, /* lbl_30 */ 0 ), // lbl_30: /* load syscall argument 0 in accumulator */ BPF_STMT( BPF_LD | BPF_W | BPF_ABS, offsetof(struct seccomp_data, args[0])), - BPF_JUMP( BPF_JMP | BPF_JEQ | BPF_K, out_inc_fd, /* RET_KILL_PROCESS */ 16, /* lbl_31 */ 0 ), + BPF_JUMP( BPF_JMP | BPF_JEQ | BPF_K, out_inc_fd, /* RET_KILL_PROCESS */ 12, /* lbl_31 */ 0 ), // lbl_31: /* load syscall argument 0 in accumulator */ BPF_STMT( BPF_LD | BPF_W | BPF_ABS, offsetof(struct seccomp_data, args[0])), - BPF_JUMP( BPF_JMP | BPF_JEQ | BPF_K, ping_fd, /* RET_KILL_PROCESS */ 14, /* lbl_26 */ 0 ), + BPF_JUMP( BPF_JMP | BPF_JEQ | BPF_K, ping_fd, /* RET_KILL_PROCESS */ 10, /* lbl_26 */ 0 ), // lbl_26: /* load syscall argument 1 in accumulator */ BPF_STMT( BPF_LD | BPF_W | BPF_ABS, offsetof(struct seccomp_data, args[1])), - BPF_JUMP( BPF_JMP | BPF_JEQ | BPF_K, IPPROTO_TCP, /* lbl_32 */ 0, /* RET_KILL_PROCESS */ 12 ), + BPF_JUMP( BPF_JMP | BPF_JEQ | BPF_K, IPPROTO_TCP, /* lbl_32 */ 0, /* RET_KILL_PROCESS */ 8 ), // lbl_32: /* load syscall argument 2 in accumulator */ BPF_STMT( BPF_LD | BPF_W | BPF_ABS, offsetof(struct seccomp_data, args[2])), - BPF_JUMP( BPF_JMP | BPF_JEQ | BPF_K, TCP_NODELAY, /* RET_ALLOW */ 11, /* RET_KILL_PROCESS */ 10 ), + BPF_JUMP( BPF_JMP | BPF_JEQ | BPF_K, TCP_NODELAY, /* RET_ALLOW */ 7, /* RET_KILL_PROCESS */ 6 ), // check_renameat: /* load syscall argument 0 in accumulator */ BPF_STMT( BPF_LD | BPF_W | BPF_ABS, offsetof(struct seccomp_data, args[0])), - BPF_JUMP( BPF_JMP | BPF_JEQ | BPF_K, dir_fd, /* lbl_33 */ 0, /* RET_KILL_PROCESS */ 8 ), + BPF_JUMP( BPF_JMP | BPF_JEQ | BPF_K, dir_fd, /* lbl_33 */ 0, /* RET_KILL_PROCESS */ 4 ), // lbl_33: /* load syscall argument 2 in accumulator */ BPF_STMT( BPF_LD | BPF_W | BPF_ABS, offsetof(struct seccomp_data, args[2])), - BPF_JUMP( BPF_JMP | BPF_JEQ | BPF_K, dir_fd, /* RET_ALLOW */ 7, /* RET_KILL_PROCESS */ 6 ), -// check_unlinkat: - /* load syscall argument 0 in accumulator */ - BPF_STMT( BPF_LD | BPF_W | BPF_ABS, offsetof(struct seccomp_data, args[0])), - BPF_JUMP( BPF_JMP | BPF_JEQ | BPF_K, dir_fd, /* lbl_34 */ 0, /* RET_KILL_PROCESS */ 4 ), -// lbl_34: - /* load syscall argument 2 in accumulator */ - BPF_STMT( BPF_LD | BPF_W | BPF_ABS, offsetof(struct seccomp_data, args[2])), - BPF_JUMP( BPF_JMP | BPF_JEQ | BPF_K, 0, /* RET_ALLOW */ 3, /* RET_KILL_PROCESS */ 2 ), + BPF_JUMP( BPF_JMP | BPF_JEQ | BPF_K, dir_fd, /* RET_ALLOW */ 3, /* RET_KILL_PROCESS */ 2 ), // check_exit: /* load syscall argument 0 in accumulator */ BPF_STMT( BPF_LD | BPF_W | BPF_ABS, offsetof(struct seccomp_data, args[0])), diff --git a/src/discof/restore/utils/fd_http_resolver.c b/src/discof/restore/utils/fd_http_resolver.c index 08ecf461fa..69c30265e1 100644 --- a/src/discof/restore/utils/fd_http_resolver.c +++ b/src/discof/restore/utils/fd_http_resolver.c @@ -210,7 +210,7 @@ create_socket( fd_http_resolver_t * resolver, struct sockaddr_in addr = { .sin_family = AF_INET, - .sin_port = fd_ushort_bswap( peer->addr.port ), + .sin_port = peer->addr.port, .sin_addr = { .s_addr = peer->addr.addr } }; @@ -388,7 +388,7 @@ fd_http_resolver_advance( fd_http_resolver_t * resolver, while( !deadline_list_is_empty( resolver->unresolved, resolver->pool ) ) { fd_ssresolve_peer_t * peer = deadline_list_ele_pop_head( resolver->unresolved, resolver->pool ); - FD_LOG_INFO(( "resolving " FD_IP4_ADDR_FMT ":%hu", FD_IP4_ADDR_FMT_ARGS( peer->addr.addr ), peer->addr.port )); + FD_LOG_INFO(( "resolving " FD_IP4_ADDR_FMT ":%hu", FD_IP4_ADDR_FMT_ARGS( peer->addr.addr ), fd_ushort_bswap( peer->addr.port ) )); int result = peer_connect( resolver, peer ); if( FD_UNLIKELY( -1==result ) ) { peer->state = PEER_STATE_INVALID; diff --git a/src/discof/restore/utils/fd_sshttp.c b/src/discof/restore/utils/fd_sshttp.c index 207dbb7ebe..77b34d9d19 100644 --- a/src/discof/restore/utils/fd_sshttp.c +++ b/src/discof/restore/utils/fd_sshttp.c @@ -140,7 +140,7 @@ fd_sshttp_init( fd_sshttp_t * http, struct sockaddr_in addr_in = { .sin_family = AF_INET, - .sin_port = fd_ushort_bswap( addr.port ), + .sin_port = addr.port, .sin_addr = { .s_addr = addr.addr } }; @@ -266,7 +266,7 @@ follow_redirect( fd_sshttp_t * http, } FD_LOG_NOTICE(( "following redirect to http://" FD_IP4_ADDR_FMT ":%hu%.*s", - FD_IP4_ADDR_FMT_ARGS( http->addr.addr ), http->addr.port, + FD_IP4_ADDR_FMT_ARGS( http->addr.addr ), fd_ushort_bswap( http->addr.port ), (int)headers[ 0 ].value_len, headers[ 0 ].value )); fd_sshttp_cancel( http ); diff --git a/src/discof/restore/utils/fd_ssping.c b/src/discof/restore/utils/fd_ssping.c index 35f7f514bd..e9b7c31c1b 100644 --- a/src/discof/restore/utils/fd_ssping.c +++ b/src/discof/restore/utils/fd_ssping.c @@ -106,7 +106,7 @@ struct fd_ssping_private { IP address and UDP port. The ICMP echo protocol has no concept of UDP port which is why we must do this manually. */ -struct ssping_pkt { +struct __attribute__((packed)) ssping_pkt { struct icmphdr icmp; ushort port; }; @@ -321,7 +321,7 @@ recv_pings( fd_ssping_t * ssping, deadline_list_ele_push_tail( ssping->valid, peer, ssping->pool ); FD_LOG_INFO(( "pinged " FD_IP4_ADDR_FMT ":%hu in %lu nanos", - FD_IP4_ADDR_FMT_ARGS( peer->addr.addr ), peer->addr.port, peer->latency_nanos )); + FD_IP4_ADDR_FMT_ARGS( peer->addr.addr ), fd_ushort_bswap( peer->addr.port ), peer->latency_nanos )); ssping->on_ping_cb( ssping->cb_arg, peer->addr, peer->latency_nanos ); } } diff --git a/src/discof/restore/utils/test_sspeer_selector.c b/src/discof/restore/utils/test_sspeer_selector.c index bca518c92d..bdc003d73f 100644 --- a/src/discof/restore/utils/test_sspeer_selector.c +++ b/src/discof/restore/utils/test_sspeer_selector.c @@ -27,7 +27,7 @@ test_basic_peer_selection( fd_sspeer_selector_t * selector ) { }; fd_sspeer_selector_process_cluster_slot( selector, cluster_ssinfo.full.slot, cluster_ssinfo.incremental.slot ); /* Add a peer and it should be the best peer */ - fd_ip4_port_t addr = { .addr = FD_IP4_ADDR( 35, 123, 172, 227 ), .port = 8899 }; + fd_ip4_port_t addr = { .addr = FD_IP4_ADDR( 35, 123, 172, 227 ), .port = fd_ushort_bswap( 8899 ) }; FD_TEST( add_peer( selector, addr, 1000UL, 1500UL, 5L*1000L*1000L )==5UL*1000UL*1000UL ); fd_sspeer_t best = fd_sspeer_selector_best( selector, 0, ULONG_MAX); FD_TEST( best.addr.l==addr.l ); @@ -38,7 +38,7 @@ test_basic_peer_selection( fd_sspeer_selector_t * selector ) { /* Add a peer with better latency at the same slot and it should be the best peer */ - fd_ip4_port_t addr2 = { .addr = FD_IP4_ADDR( 35, 123, 172, 228 ), .port = 8899 }; + fd_ip4_port_t addr2 = { .addr = FD_IP4_ADDR( 35, 123, 172, 228 ), .port = fd_ushort_bswap( 8899 ) }; FD_TEST( add_peer( selector, addr2, 1000UL, 1500UL, 3L*1000L*1000L )==3UL*1000UL*1000UL ); best = fd_sspeer_selector_best( selector, 0, ULONG_MAX); FD_TEST( best.addr.l==addr2.l ); @@ -48,7 +48,7 @@ test_basic_peer_selection( fd_sspeer_selector_t * selector ) { FD_TEST( best.score==3L*1000L*1000L ); /* Add a peer with the same latency but lagging slots behind */ - fd_ip4_port_t addr3 = { .addr = FD_IP4_ADDR( 35, 123, 172, 229 ), .port = 8899 }; + fd_ip4_port_t addr3 = { .addr = FD_IP4_ADDR( 35, 123, 172, 229 ), .port = fd_ushort_bswap( 8899 ) }; FD_TEST( add_peer( selector, addr3, 1000UL, 1400UL, 3L*1000L*1000L )==3UL*1000UL*1000UL + 100UL*1000UL ); best = fd_sspeer_selector_best( selector, 0, ULONG_MAX); FD_TEST( best.addr.l==addr2.l ); @@ -61,7 +61,7 @@ test_basic_peer_selection( fd_sspeer_selector_t * selector ) { fd_sspeer_selector_process_cluster_slot( selector, cluster_ssinfo.full.slot, cluster_ssinfo.incremental.slot ); /* Add a peer that is slightly slower but caught up in slots */ - fd_ip4_port_t addr4 = { .addr = FD_IP4_ADDR( 35, 123, 172, 230 ), .port = 8899 }; + fd_ip4_port_t addr4 = { .addr = FD_IP4_ADDR( 35, 123, 172, 230 ), .port = fd_ushort_bswap( 8899 ) }; FD_TEST( add_peer( selector, addr4, 1000UL, 1600UL, 3L*1000L*1000L + 75L*1000L )==3UL*1000UL*1000UL + 75UL*1000UL ); best = fd_sspeer_selector_best( selector, 0, ULONG_MAX ); FD_TEST( best.addr.l==addr4.l ); @@ -71,7 +71,7 @@ test_basic_peer_selection( fd_sspeer_selector_t * selector ) { FD_TEST( best.score==3L*1000L*1000L + 75L*1000L ); /* Add a fast peer that doesn't have resolved slots */ - fd_ip4_port_t addr5 = { .addr = FD_IP4_ADDR( 35, 123, 172, 231 ), .port = 8899 }; + fd_ip4_port_t addr5 = { .addr = FD_IP4_ADDR( 35, 123, 172, 231 ), .port = fd_ushort_bswap( 8899 ) }; FD_TEST( add_peer( selector, addr5, ULONG_MAX, ULONG_MAX, 2L*1000L*1000L )==2UL*1000UL*1000UL + 1000UL*1000UL*1000UL); best = fd_sspeer_selector_best( selector, 0, ULONG_MAX ); FD_TEST( best.addr.l==addr4.l ); @@ -93,7 +93,7 @@ test_basic_peer_selection( fd_sspeer_selector_t * selector ) { /* Add a peer that is fast and at the highest slot but not building off full slot, which makes it invalid an incremental peer */ - fd_ip4_port_t addr6 = { .addr = FD_IP4_ADDR( 35, 123, 172, 232 ), .port = 8899 }; + fd_ip4_port_t addr6 = { .addr = FD_IP4_ADDR( 35, 123, 172, 232 ), .port = fd_ushort_bswap( 8899 ) }; FD_TEST( add_peer( selector, addr6, 900UL, 1700UL, 2L*1000L*1000L )==2UL*1000UL*1000UL ); best = fd_sspeer_selector_best( selector, 1, 1000UL ); FD_TEST( best.addr.l==addr4.l ); @@ -103,7 +103,7 @@ test_basic_peer_selection( fd_sspeer_selector_t * selector ) { FD_TEST( best.score==3L*1000L*1000L + 75L*1000L + 100UL*1000UL ); /* Add a fast incremental peer that is caught up to the cluster slot */ - fd_ip4_port_t addr7 = { .addr = FD_IP4_ADDR( 35, 123, 172, 233 ), .port = 8899 }; + fd_ip4_port_t addr7 = { .addr = FD_IP4_ADDR( 35, 123, 172, 233 ), .port = fd_ushort_bswap( 8899 ) }; FD_TEST( add_peer( selector, addr7, 1000UL, 1700UL, 2L*1000L*1000L )==2UL*1000UL*1000UL ); best = fd_sspeer_selector_best( selector, 1, 1000UL ); FD_TEST( best.addr.l==addr7.l ); diff --git a/src/flamenco/runtime/tests/run_ledger_backtest.sh b/src/flamenco/runtime/tests/run_ledger_backtest.sh index a47077eb87..974593708f 100755 --- a/src/flamenco/runtime/tests/run_ledger_backtest.sh +++ b/src/flamenco/runtime/tests/run_ledger_backtest.sh @@ -215,10 +215,11 @@ fi echo " [snapshots] incremental_snapshots = $HAS_INCREMENTAL - download = false - minimum_download_speed_mib = 0 - maximum_local_snapshot_age = 0 - maximum_download_retry_abort = 0 + [snapshots.sources] + servers = [] + [snapshots.sources.gossip] + allow_any = false + allow_list = [] [layout] shred_tile_count = 4 [tiles] diff --git a/src/util/fd_util_base.h b/src/util/fd_util_base.h index 67d4890cc6..2d5fa0303e 100644 --- a/src/util/fd_util_base.h +++ b/src/util/fd_util_base.h @@ -391,6 +391,10 @@ __extension__ typedef unsigned __int128 uint128; (__typeof__(&(x)))_fd_aopm; \ })) +/* FD_ARRAY_CNT returns the number of elements of the given array. */ + +#define FD_ARRAY_CNT(x) (sizeof(x)/sizeof((x)[0])) + /* FD_PROTOTYPES_{BEGIN,END}: Headers that might be included in C++ source should encapsulate the prototypes of code and globals contained in compilation units compiled as C with a