Files
lighthouse/lighthouse/tests/beacon_node.rs
Lion - dapplion f75a2cf65b PeerDAS implementation (#5683)
* 1D PeerDAS prototype: Data format and Distribution (#5050)

* Build and publish column sidecars. Add stubs for gossip.

* Add blob column subnets

* Add `BlobColumnSubnetId` and initial compute subnet logic.

* Subscribe to blob column subnets.

* Introduce `BLOB_COLUMN_SUBNET_COUNT` based on DAS configuration parameter changes.

* Fix column sidecar type to use `VariableList` for data.

* Fix lint errors.

* Update types and naming to latest consensus-spec #3574.

* Fix test and some cleanups.

* Merge branch 'unstable' into das

* Merge branch 'unstable' into das

* Merge branch 'unstable' into das

# Conflicts:
#	consensus/types/src/chain_spec.rs

* Add `DataColumnSidecarsByRoot ` req/resp protocol (#5196)

* Add stub for `DataColumnsByRoot`

* Add basic implementation of serving RPC data column from DA checker.

* Store data columns in early attester cache and blobs db.

* Apply suggestions from code review

Co-authored-by: Eitan Seri-Levi <eserilev@gmail.com>
Co-authored-by: Jacob Kaufmann <jacobkaufmann18@gmail.com>

* Fix build.

* Store `DataColumnInfo` in database and various cleanups.

* Update `DataColumnSidecar` ssz max size and remove panic code.

---------

Co-authored-by: Eitan Seri-Levi <eserilev@gmail.com>
Co-authored-by: Jacob Kaufmann <jacobkaufmann18@gmail.com>

* feat: add DAS KZG in data col construction (#5210)

* feat: add DAS KZG in data col construction

* refactor data col sidecar construction

* refactor: add data cols to GossipVerifiedBlockContents

* Disable windows tests for `das` branch. (c-kzg doesn't build on windows)

* Formatting and lint changes only.

* refactor: remove iters in construction of data cols

* Update vec capacity and error handling.

* Add `data_column_sidecar_computation_seconds` metric.

---------

Co-authored-by: Jimmy Chen <jchen.tc@gmail.com>

* Merge branch 'unstable' into das

# Conflicts:
#	.github/workflows/test-suite.yml
#	beacon_node/lighthouse_network/src/types/topics.rs

* fix: update data col subnet count from 64 to 32 (#5413)

* feat: add peerdas custody field to ENR (#5409)

* feat: add peerdas custody field to ENR

* add hash prefix step in subnet computation

* refactor test and fix possible u64 overflow

* default to min custody value if not present in ENR

* Merge branch 'unstable' into das

* Merge branch 'unstable' into das-unstable-merge-0415

# Conflicts:
#	Cargo.lock
#	beacon_node/beacon_chain/src/data_availability_checker.rs
#	beacon_node/beacon_chain/src/data_availability_checker/availability_view.rs
#	beacon_node/beacon_chain/src/data_availability_checker/overflow_lru_cache.rs
#	beacon_node/beacon_chain/src/data_availability_checker/processing_cache.rs
#	beacon_node/lighthouse_network/src/rpc/methods.rs
#	beacon_node/network/src/network_beacon_processor/mod.rs
#	beacon_node/network/src/sync/block_lookups/tests.rs
#	crypto/kzg/Cargo.toml

* Merge remote-tracking branch 'sigp/unstable' into das

* Merge remote-tracking branch 'sigp/unstable' into das

* Fix merge conflicts.

* Send custody data column to `DataAvailabilityChecker` for determining block importability (#5570)

* Only import custody data columns after publishing a block.

* Add `subscribe-all-data-column-subnets` and pass custody column count to `availability_cache`.

* Add custody requirement checks to `availability_cache`.

* Fix config not being passed to DAChecker and add more logging.

* Introduce `peer_das_epoch` and make blobs and columns mutually exclusive.

* Add DA filter for PeerDAS.

* Fix data availability check and use test_logger in tests.

* Fix subscribe to all data column subnets not working correctly.

* Fix tests.

* Only publish column sidecars if PeerDAS is activated. Add `PEER_DAS_EPOCH` chain spec serialization.

* Remove unused data column index in `OverflowKey`.

* Fix column sidecars incorrectly produced when there are no blobs.

* Re-instate index to `OverflowKey::DataColumn` and downgrade noisy debug log to `trace`.

* DAS sampling on sync (#5616)

* Data availability sampling on sync

* Address @jimmygchen review

* Trigger sampling

* Address some review comments and only send `SamplingBlock` sync message after PEER_DAS_EPOCH.

---------

Co-authored-by: Jimmy Chen <jchen.tc@gmail.com>

* Merge branch 'unstable' into das

# Conflicts:
#	Cargo.lock
#	Cargo.toml
#	beacon_node/beacon_chain/src/block_verification.rs
#	beacon_node/http_api/src/publish_blocks.rs
#	beacon_node/lighthouse_network/src/rpc/codec/ssz_snappy.rs
#	beacon_node/lighthouse_network/src/rpc/protocol.rs
#	beacon_node/lighthouse_network/src/types/pubsub.rs
#	beacon_node/network/src/sync/block_lookups/single_block_lookup.rs
#	beacon_node/store/src/hot_cold_store.rs
#	consensus/types/src/beacon_state.rs
#	consensus/types/src/chain_spec.rs
#	consensus/types/src/eth_spec.rs

* Merge branch 'unstable' into das

* Re-process early sampling requests (#5569)

* Re-process early sampling requests

# Conflicts:
#	beacon_node/beacon_processor/src/work_reprocessing_queue.rs
#	beacon_node/lighthouse_network/src/rpc/methods.rs
#	beacon_node/network/src/network_beacon_processor/rpc_methods.rs

* Update beacon_node/beacon_processor/src/work_reprocessing_queue.rs

Co-authored-by: Jimmy Chen <jchen.tc@gmail.com>

* Add missing var

* Beta compiler fixes and small typo fixes.

* Remove duplicate method.

---------

Co-authored-by: Jimmy Chen <jchen.tc@gmail.com>

* Merge remote-tracking branch 'sigp/unstable' into das

* Fix merge conflict.

* Add data columns by root to currently supported protocol list (#5678)

* Add data columns by root to currently supported protocol list.

* Add missing data column by roots handling.

* Merge branch 'unstable' into das

# Conflicts:
#	Cargo.lock
#	Cargo.toml
#	beacon_node/network/src/sync/block_lookups/tests.rs
#	beacon_node/network/src/sync/manager.rs

* Fix simulator tests on `das` branch (#5731)

* Bump genesis delay in sim tests as KZG setup takes longer for DAS.

* Fix incorrect YAML spacing.

* DataColumnByRange boilerplate (#5353)

* add boilerplate

* fmt

* PeerDAS custody lookup sync (#5684)

* Implement custody sync

* Lint

* Fix tests

* Fix rebase issue

* Add data column kzg verification and update `c-kzg`. (#5701)

* Add data column kzg verification and update `c-kzg`.

* Fix incorrect `Cell` size.

* Add kzg verification on rpc blocks.

* Add kzg verification on rpc data columns.

* Rename `PEER_DAS_EPOCH` to `EIP7594_FORK_EPOCH` for client interop. (#5750)

* Fetch custody columns in range sync (#5747)

* Fetch custody columns in range sync

* Clean up todos

* Remove `BlobSidecar` construction and publish after PeerDAS activated (#5759)

* Avoid building and publishing blob sidecars after PeerDAS.

* Ignore gossip blobs with a slot greater than peer das activation epoch.

* Only attempt to verify blob count and import blobs before PeerDAS.

* #5684 review comments (#5748)

* #5684 review comments.

* Doc and message update only.

* Fix incorrect condition when constructing `RpcBlock` with `DataColumn`s

* Make sampling tests deterministic (#5775)

* PeerDAS spec tests (#5772)

* Add get_custody_columns spec tests.

* Add kzg merkle proof spec tests.

* Add SSZ spec tests.

* Add remaining KZG tests

* Load KZG only once per process, exclude electra tests and add missing SSZ tests.

* Fix lint and missing changes.

* Ignore macOS generated file.

* Merge remote branch 'sigp/unstable' into das

* Merge remote tracking branch 'origin/unstable' into das

* Implement unconditional reconstruction for supernodes (#5781)

* Implement unconditional reconstruction for supernodes

* Move code into KzgVerifiedCustodyDataColumn

* Remove expect

* Add test

* Thanks justin

* Add withhold attack mode for interop (#5788)

* Add withhold attack mode

* Update readme

* Drop added readmes

* Undo styling changes

* Add column gossip verification and handle unknown parent block (#5783)

* Add column gossip verification and handle missing parent for columns.

* Review PR

* Fix rebase issue

* more lint issues :)

---------

Co-authored-by: dapplion <35266934+dapplion@users.noreply.github.com>

* Trigger sampling on sync events (#5776)

* Trigger sampling on sync events

* Update beacon_chain.rs

* Fix tests

* Fix tests

* PeerDAS parameter changes for devnet-0 (#5779)

* Update PeerDAS parameters to latest values.

* Lint fix

* Fix lint.

* Update hardcoded subnet count to 64 (#5791)

* Fix incorrect columns per subnet and config cleanup (#5792)

* Tidy up PeerDAS preset and config values.

* Fix broken config

* Fix DAS branch CI (#5793)

* Fix invalid syntax.

* Update cli doc. Ignore get_custody_columns test temporarily.

* Fix failing test and add verify inclusion test.

* Undo accidentally removed code.

* Only attempt reconstruct columns once. (#5794)

* Re-enable precompute table for peerdas kzg (#5795)

* Merge branch 'unstable' into das

* Update subscription filter. (#5797)

* Remove penalty for duplicate columns (expected due to reconstruction) (#5798)

* Revert DAS config for interop testing. Optimise get_custody_columns function. (#5799)

* Don't perform reconstruction for proposer node as it already has all the columns. (#5806)

* Multithread compute_cells_and_proofs (#5805)

* Multi-thread reconstruct data columns

* Multi-thread path for block production

* Merge branch 'unstable' into das

# Conflicts:
#	.github/workflows/test-suite.yml
#	beacon_node/network/src/sync/block_lookups/mod.rs
#	beacon_node/network/src/sync/block_lookups/single_block_lookup.rs
#	beacon_node/network/src/sync/network_context.rs

* Fix CI errors.

* Move PeerDAS type-level config to configurable `ChainSpec` (#5828)

* Move PeerDAS type level config to `ChainSpec`.

* Fix tests

* Misc custody lookup improvements (#5821)

* Improve custody requests

* Type DataColumnsByRootRequestId

* Prioritize peers and load balance

* Update tests

* Address PR review

* Merge branch 'unstable' into das

* Rename deploy_block in network config (`das` branch) (#5852)

* Rename deploy_block.txt to deposit_contract_block.txt

* fmt

---------

Co-authored-by: Pawan Dhananjay <pawandhananjay@gmail.com>

* Merge branch 'unstable' into das

* Fix CI and merge issues.

* Merge branch 'unstable' into das

# Conflicts:
#	beacon_node/beacon_chain/src/data_availability_checker/overflow_lru_cache.rs
#	lcli/src/main.rs

* Store data columns individually in store and caches (#5890)

* Store data columns individually in store and caches

* Implement data column pruning

* Merge branch 'unstable' into das

# Conflicts:
#	Cargo.lock

* Update reconstruction benches to newer criterion version. (#5949)

* Merge branch 'unstable' into das

# Conflicts:
#	.github/workflows/test-suite.yml

* chore: add `recover_cells_and_compute_proofs` method (#5938)

* chore: add recover_cells_and_compute_proofs method

* Introduce type alias `CellsAndKzgProofs` to address type complexity.

---------

Co-authored-by: Jimmy Chen <jchen.tc@gmail.com>

* Update `csc` format in ENR and spec tests for devnet-1 (#5966)

* Update `csc` format in ENR.

* Add spec tests for `recover_cells_and_kzg_proofs`.

* Add tests for ENR.

* Fix failing tests.

* Add protection against invalid csc value in ENR.

* Fix lint

* Fix csc encoding and decoding (#5997)

* Fix data column rpc request not being sent due to incorrect limits set. (#6000)

* Fix incorrect inbound request count causing rate limiting. (#6025)

* Merge branch 'stable' into das

# Conflicts:
#	beacon_node/network/src/sync/block_lookups/tests.rs
#	beacon_node/network/src/sync/block_sidecar_coupling.rs
#	beacon_node/network/src/sync/manager.rs
#	beacon_node/network/src/sync/network_context.rs
#	beacon_node/network/src/sync/network_context/requests.rs

* Merge remote-tracking branch 'unstable' into das

* Add kurtosis config for DAS testing (#5968)

* Add kurtosis config for DAS testing.

* Fix invalid yaml file

* Update network parameter files.

* chore: add rust PeerdasKZG crypto library for peerdas functionality and rollback c-kzg dependency to 4844 version (#5941)

* chore: add recover_cells_and_compute_proofs method

* chore: add rust peerdas crypto library

* chore: integrate peerdaskzg rust library into kzg crate

* chore(multi):

- update `ssz_cell_to_crypto_cell`
- update conversion from the crypto cell type to a Vec<u8>. Since the Rust library defines them as references to an array, the conversion is simply `to_vec`

* chore(multi):

- update rest of code to handle the new crypto `Cell` type
- update test case code to no longer use the Box type

* chore: cleanup of superfluous conversions

* chore: revert c-kzg dependency back to v1

* chore: move dependency into correct order

* chore: update rust dependency

- This version includes a new method `PeerDasContext::with_num_threads`

* chore: remove Default initialization of PeerDasContext and explicitly set the parameters in `new_from_trusted_setup`

* chore: cleanup exports

* chore: commit updated cargo.lock

* Update Cargo.toml

Co-authored-by: Jimmy Chen <jchen.tc@gmail.com>

* chore: rename dependency

* chore: update peerdas lib

- sets the blst version to 0.3 so that it matches whatever lighthouse is using. Although 0.3.12 is latest, lighthouse is pinned to 0.3.3

* chore: fix clippy lifetime

- Rust doesn't allow you to elide the lifetime on type aliases

* chore: cargo clippy fix

* chore: cargo fmt

* chore: update lib to add redundant checks (these will be removed in consensus-specs PR 3819)

* chore: update dependency to ignore proofs

* chore: update peerdas lib to latest

* update lib

* chore: remove empty proof parameter

---------

Co-authored-by: Jimmy Chen <jchen.tc@gmail.com>

* Update PeerDAS interop testnet config (#6069)

* Update interop testnet config.

* Fix typo and remove target peers

* Avoid retrying same sampling peer that previously failed. (#6084)

* Various fixes to custody range sync  (#6004)

* Only start requesting batches when there are good peers across all custody columns to avoid spaming block requests.

* Add custody peer check before mutating `BatchInfo` to avoid inconsistent state.

* Add check to cover a case where batch is not processed while waiting for custody peers to become available.

* Fix lint and logic error

* Fix `good_peers_on_subnet` always returning false for `DataColumnSubnet`.

* Add test for `get_custody_peers_for_column`

* Revert epoch parameter refactor.

* Fall back to default custody requiremnt if peer ENR is not present.

* Add metrics and update code comment.

* Add more debug logs.

* Use subscribed peers on subnet before MetaDataV3 is implemented. Remove peer_id matching when injecting error because multiple peers are used for range requests. Use randomized custodial peer to avoid repeatedly sending requests to failing peers. Batch by range request where possible.

* Remove unused code and update docs.

* Add comment

* chore: update peerdas-kzg library (#6118)

* chore: update peerDAS lib

* chore: update library

* chore: update library to version that include "init context" benchmarks and optional validation checks

* chore: (can remove) -- Add benchmarks for init context

* Prevent continuous searchers for low-peer networks (#6162)

* Merge branch 'unstable' into das

* Fix merge conflicts

* Add cli flag to enable sampling and disable by default. (#6209)

* chore: Use reference to an array representing a blob instead of an owned KzgBlob (#6179)

* add KzgBlobRef type

* modify code to use KzgBlobRef

* clippy

* Remove Deneb blob related changes to maintain compatibility with `c-kzg-4844`.

---------

Co-authored-by: Jimmy Chen <jchen.tc@gmail.com>

* Store computed custody subnets in PeerDB and fix custody lookup test (#6218)

* Fix failing custody lookup tests.

* Store custody subnets in PeerDB, fix custody lookup test and refactor some methods.

* Merge branch 'unstable' into das

# Conflicts:
#	beacon_node/beacon_chain/src/beacon_chain.rs
#	beacon_node/beacon_chain/src/block_verification_types.rs
#	beacon_node/beacon_chain/src/builder.rs
#	beacon_node/beacon_chain/src/data_availability_checker.rs
#	beacon_node/beacon_chain/src/data_availability_checker/overflow_lru_cache.rs
#	beacon_node/beacon_chain/src/data_column_verification.rs
#	beacon_node/beacon_chain/src/early_attester_cache.rs
#	beacon_node/beacon_chain/src/historical_blocks.rs
#	beacon_node/beacon_chain/tests/store_tests.rs
#	beacon_node/lighthouse_network/src/discovery/enr.rs
#	beacon_node/network/src/service.rs
#	beacon_node/src/cli.rs
#	beacon_node/store/src/hot_cold_store.rs
#	beacon_node/store/src/lib.rs
#	lcli/src/generate_bootnode_enr.rs

* Fix CI failures after merge.

* Batch sampling requests by peer (#6256)

* Batch sampling requests by peer

* Fix clippy errors

* Fix tests

* Add column_index to error message for ease of tracing

* Remove outdated comment

* Fix range sync never evaluating request as finished, causing it to get stuck. (#6276)

* Merge branch 'unstable' into das-0821-merge

# Conflicts:
#	Cargo.lock
#	Cargo.toml
#	beacon_node/beacon_chain/src/beacon_chain.rs
#	beacon_node/beacon_chain/src/data_availability_checker.rs
#	beacon_node/beacon_chain/src/data_availability_checker/overflow_lru_cache.rs
#	beacon_node/beacon_chain/src/data_column_verification.rs
#	beacon_node/beacon_chain/src/kzg_utils.rs
#	beacon_node/beacon_chain/src/metrics.rs
#	beacon_node/beacon_processor/src/lib.rs
#	beacon_node/lighthouse_network/src/rpc/codec/ssz_snappy.rs
#	beacon_node/lighthouse_network/src/rpc/config.rs
#	beacon_node/lighthouse_network/src/rpc/methods.rs
#	beacon_node/lighthouse_network/src/rpc/outbound.rs
#	beacon_node/lighthouse_network/src/rpc/rate_limiter.rs
#	beacon_node/lighthouse_network/src/service/api_types.rs
#	beacon_node/lighthouse_network/src/types/globals.rs
#	beacon_node/network/src/network_beacon_processor/mod.rs
#	beacon_node/network/src/network_beacon_processor/rpc_methods.rs
#	beacon_node/network/src/network_beacon_processor/sync_methods.rs
#	beacon_node/network/src/sync/block_lookups/common.rs
#	beacon_node/network/src/sync/block_lookups/mod.rs
#	beacon_node/network/src/sync/block_lookups/single_block_lookup.rs
#	beacon_node/network/src/sync/block_lookups/tests.rs
#	beacon_node/network/src/sync/manager.rs
#	beacon_node/network/src/sync/network_context.rs
#	consensus/types/src/data_column_sidecar.rs
#	crypto/kzg/Cargo.toml
#	crypto/kzg/benches/benchmark.rs
#	crypto/kzg/src/lib.rs

* Fix custody tests and load PeerDAS KZG instead.

* Fix ef tests and bench compilation.

* Fix failing sampling test.

* Merge pull request #6287 from jimmygchen/das-0821-merge

Merge `unstable` into `das` 20240821

* Remove get_block_import_status

* Merge branch 'unstable' into das

* Re-enable Windows release tests.

* Address some review comments.

* Address more review comments and cleanups.

* Comment out peer DAS KZG EF tests for now

* Address more review comments and fix build.

* Merge branch 'das' of github.com:sigp/lighthouse into das

* Unignore Electra tests

* Fix metric name

* Address some of Pawan's review comments

* Merge remote-tracking branch 'origin/unstable' into das

* Update PeerDAS network parameters for peerdas-devnet-2  (#6290)

* update subnet count & custody req

* das network params

* update ef tests

---------

Co-authored-by: Jimmy Chen <jchen.tc@gmail.com>
2024-08-27 04:10:22 +00:00

2739 lines
88 KiB
Rust

use beacon_node::ClientConfig as Config;
use crate::exec::{CommandLineTestExec, CompletedTest};
use beacon_node::beacon_chain::chain_config::{
DisallowedReOrgOffsets, DEFAULT_RE_ORG_CUTOFF_DENOMINATOR, DEFAULT_RE_ORG_HEAD_THRESHOLD,
DEFAULT_RE_ORG_MAX_EPOCHS_SINCE_FINALIZATION,
};
use beacon_node::beacon_chain::graffiti_calculator::GraffitiOrigin;
use beacon_processor::BeaconProcessorConfig;
use eth1::Eth1Endpoint;
use lighthouse_network::PeerId;
use lighthouse_version;
use std::fs::File;
use std::io::{Read, Write};
use std::net::{IpAddr, Ipv4Addr, Ipv6Addr};
use std::path::Path;
use std::path::PathBuf;
use std::process::Command;
use std::str::FromStr;
use std::string::ToString;
use std::time::Duration;
use tempfile::TempDir;
use types::non_zero_usize::new_non_zero_usize;
use types::{Address, Checkpoint, Epoch, ExecutionBlockHash, Hash256, MainnetEthSpec};
use unused_port::{unused_tcp4_port, unused_tcp6_port, unused_udp4_port, unused_udp6_port};
const DEFAULT_ETH1_ENDPOINT: &str = "http://localhost:8545/";
// These dummy ports should ONLY be used for `enr-xxx-port` flags that do not bind.
const DUMMY_ENR_TCP_PORT: u16 = 7777;
const DUMMY_ENR_UDP_PORT: u16 = 8888;
const DUMMY_ENR_QUIC_PORT: u16 = 9999;
const _: () =
assert!(DUMMY_ENR_QUIC_PORT != 0 && DUMMY_ENR_TCP_PORT != 0 && DUMMY_ENR_UDP_PORT != 0);
/// Returns the `lighthouse beacon_node` command.
fn base_cmd() -> Command {
let lighthouse_bin = env!("CARGO_BIN_EXE_lighthouse");
let path = lighthouse_bin
.parse::<PathBuf>()
.expect("should parse CARGO_TARGET_DIR");
let mut cmd = Command::new(path);
cmd.arg("beacon_node");
cmd
}
// Wrapper around `Command` for easier Command Line Testing.
struct CommandLineTest {
cmd: Command,
}
impl CommandLineTest {
fn new() -> CommandLineTest {
let base_cmd = base_cmd();
CommandLineTest { cmd: base_cmd }
}
fn run_with_zero_port(&mut self) -> CompletedTest<Config> {
// Required since Deneb was enabled on mainnet.
self.set_allow_insecure_genesis_sync()
.run_with_zero_port_and_no_genesis_sync()
}
fn run_with_zero_port_and_no_genesis_sync(&mut self) -> CompletedTest<Config> {
self.set_zero_port().run()
}
fn set_allow_insecure_genesis_sync(&mut self) -> &mut Self {
self.cmd.arg("--allow-insecure-genesis-sync");
self
}
fn set_zero_port(&mut self) -> &mut Self {
self.cmd.arg("-z");
self
}
}
impl CommandLineTestExec for CommandLineTest {
type Config = Config;
fn cmd_mut(&mut self) -> &mut Command {
&mut self.cmd
}
}
#[test]
fn datadir_flag() {
CommandLineTest::new()
.run_with_zero_port()
.with_config_and_dir(|config, dir| {
assert_eq!(*config.data_dir(), dir.path().join("beacon"))
});
}
#[test]
fn staking_flag() {
CommandLineTest::new()
.flag("staking", None)
.run_with_zero_port()
.with_config(|config| {
assert!(config.http_api.enabled);
assert!(config.sync_eth1_chain);
assert_eq!(
config.eth1.endpoint.get_endpoint().to_string(),
DEFAULT_ETH1_ENDPOINT
);
});
}
#[test]
fn allow_insecure_genesis_sync_default() {
CommandLineTest::new()
.run_with_zero_port_and_no_genesis_sync()
.with_config(|config| {
assert_eq!(config.allow_insecure_genesis_sync, false);
});
}
#[test]
#[should_panic]
fn insecure_genesis_sync_should_panic() {
CommandLineTest::new()
.set_zero_port()
.run_with_immediate_shutdown(false);
}
#[test]
fn allow_insecure_genesis_sync_enabled() {
CommandLineTest::new()
.flag("allow-insecure-genesis-sync", None)
.run_with_zero_port_and_no_genesis_sync()
.with_config(|config| {
assert_eq!(config.allow_insecure_genesis_sync, true);
});
}
#[test]
fn wss_checkpoint_flag() {
let state = Some(Checkpoint {
epoch: Epoch::new(1010),
root: Hash256::from_str("deadbeefdeadbeefdeadbeefdeadbeefdeadbeefdeadbeefdeadbeefdeadbeef")
.unwrap(),
});
CommandLineTest::new()
.flag(
"wss-checkpoint",
Some("0xdeadbeefdeadbeefdeadbeefdeadbeefdeadbeefdeadbeefdeadbeefdeadbeef:1010"),
)
.run_with_zero_port()
.with_config(|config| assert_eq!(config.chain.weak_subjectivity_checkpoint, state));
}
#[test]
fn max_skip_slots_flag() {
CommandLineTest::new()
.flag("max-skip-slots", Some("10"))
.run_with_zero_port()
.with_config(|config| assert_eq!(config.chain.import_max_skip_slots, Some(10)));
}
#[test]
fn disable_lock_timeouts_flag() {
CommandLineTest::new()
.flag("disable-lock-timeouts", None)
.run_with_zero_port();
}
#[test]
fn shuffling_cache_default() {
CommandLineTest::new()
.run_with_zero_port()
.with_config(|config| {
assert_eq!(
config.chain.shuffling_cache_size,
beacon_node::beacon_chain::shuffling_cache::DEFAULT_CACHE_SIZE
)
});
}
#[test]
fn shuffling_cache_set() {
CommandLineTest::new()
.flag("shuffling-cache-size", Some("500"))
.run_with_zero_port()
.with_config(|config| assert_eq!(config.chain.shuffling_cache_size, 500));
}
#[test]
fn fork_choice_before_proposal_timeout_default() {
CommandLineTest::new()
.run_with_zero_port()
.with_config(|config| {
assert_eq!(
config.chain.fork_choice_before_proposal_timeout_ms,
beacon_node::beacon_chain::chain_config::DEFAULT_FORK_CHOICE_BEFORE_PROPOSAL_TIMEOUT
)
});
}
#[test]
fn fork_choice_before_proposal_timeout_zero() {
CommandLineTest::new()
.flag("fork-choice-before-proposal-timeout", Some("0"))
.run_with_zero_port()
.with_config(|config| assert_eq!(config.chain.fork_choice_before_proposal_timeout_ms, 0));
}
#[test]
fn checkpoint_sync_url_timeout_flag() {
CommandLineTest::new()
.flag("checkpoint-sync-url-timeout", Some("300"))
.run_with_zero_port()
.with_config(|config| {
assert_eq!(config.chain.checkpoint_sync_url_timeout, 300);
});
}
#[test]
fn checkpoint_sync_url_timeout_default() {
CommandLineTest::new()
.run_with_zero_port()
.with_config(|config| {
assert_eq!(config.chain.checkpoint_sync_url_timeout, 180);
});
}
#[test]
fn prepare_payload_lookahead_default() {
CommandLineTest::new()
.run_with_zero_port()
.with_config(|config| {
assert_eq!(
config.chain.prepare_payload_lookahead,
Duration::from_secs(4),
)
});
}
#[test]
fn prepare_payload_lookahead_shorter() {
CommandLineTest::new()
.flag("prepare-payload-lookahead", Some("1500"))
.run_with_zero_port()
.with_config(|config| {
assert_eq!(
config.chain.prepare_payload_lookahead,
Duration::from_millis(1500)
)
});
}
#[test]
fn always_prepare_payload_default() {
CommandLineTest::new()
.run_with_zero_port()
.with_config(|config| assert!(!config.chain.always_prepare_payload));
}
#[test]
fn always_prepare_payload_override() {
let dir = TempDir::new().expect("Unable to create temporary directory");
CommandLineTest::new()
.flag("always-prepare-payload", None)
.flag(
"suggested-fee-recipient",
Some("0x00000000219ab540356cbb839cbe05303d7705fa"),
)
.flag("execution-endpoint", Some("http://localhost:8551/"))
.flag(
"execution-jwt",
dir.path().join("jwt-file").as_os_str().to_str(),
)
.run_with_zero_port()
.with_config(|config| assert!(config.chain.always_prepare_payload));
}
#[test]
fn paranoid_block_proposal_default() {
CommandLineTest::new()
.run_with_zero_port()
.with_config(|config| assert!(!config.chain.paranoid_block_proposal));
}
#[test]
fn paranoid_block_proposal_on() {
CommandLineTest::new()
.flag("paranoid-block-proposal", None)
.run_with_zero_port()
.with_config(|config| assert!(config.chain.paranoid_block_proposal));
}
#[test]
fn reset_payload_statuses_default() {
CommandLineTest::new()
.run_with_zero_port()
.with_config(|config| assert!(!config.chain.always_reset_payload_statuses));
}
#[test]
fn reset_payload_statuses_present() {
CommandLineTest::new()
.flag("reset-payload-statuses", None)
.run_with_zero_port()
.with_config(|config| assert!(config.chain.always_reset_payload_statuses));
}
#[test]
fn freezer_dir_flag() {
let dir = TempDir::new().expect("Unable to create temporary directory");
CommandLineTest::new()
.flag("freezer-dir", dir.path().as_os_str().to_str())
.run_with_zero_port()
.with_config(|config| assert_eq!(config.freezer_db_path, Some(dir.path().to_path_buf())));
}
#[test]
fn graffiti_flag() {
CommandLineTest::new()
.flag("graffiti", Some("nice-graffiti"))
.run_with_zero_port()
.with_config(|config| {
assert!(matches!(
config.beacon_graffiti,
GraffitiOrigin::UserSpecified(_)
));
assert_eq!(
config.beacon_graffiti.graffiti().to_string(),
"0x6e6963652d677261666669746900000000000000000000000000000000000000",
);
});
}
#[test]
fn default_graffiti() {
use types::GRAFFITI_BYTES_LEN;
// test default graffiti when no graffiti flags are provided
CommandLineTest::new()
.run_with_zero_port()
.with_config(|config| {
assert!(matches!(
config.beacon_graffiti,
GraffitiOrigin::Calculated(_)
));
let version_bytes = lighthouse_version::VERSION.as_bytes();
let trimmed_len = std::cmp::min(version_bytes.len(), GRAFFITI_BYTES_LEN);
let mut bytes = [0u8; GRAFFITI_BYTES_LEN];
bytes[..trimmed_len].copy_from_slice(&version_bytes[..trimmed_len]);
assert_eq!(config.beacon_graffiti.graffiti().0, bytes);
});
}
#[test]
fn trusted_peers_flag() {
let peers = vec![PeerId::random(), PeerId::random()];
CommandLineTest::new()
.flag(
"trusted-peers",
Some(format!("{},{}", peers[0].to_string(), peers[1].to_string()).as_str()),
)
.run_with_zero_port()
.with_config(|config| {
assert_eq!(
PeerId::from(config.network.trusted_peers[0].clone()).to_bytes(),
peers[0].to_bytes()
);
assert_eq!(
PeerId::from(config.network.trusted_peers[1].clone()).to_bytes(),
peers[1].to_bytes()
);
});
}
#[test]
fn genesis_backfill_flag() {
CommandLineTest::new()
.flag("genesis-backfill", None)
.run_with_zero_port()
.with_config(|config| assert_eq!(config.chain.genesis_backfill, true));
}
/// The genesis backfill flag should be enabled if historic states flag is set.
#[test]
fn genesis_backfill_with_historic_flag() {
CommandLineTest::new()
.flag("reconstruct-historic-states", None)
.run_with_zero_port()
.with_config(|config| assert_eq!(config.chain.genesis_backfill, true));
}
// Tests for Eth1 flags.
#[test]
fn dummy_eth1_flag() {
CommandLineTest::new()
.flag("dummy-eth1", None)
.run_with_zero_port()
.with_config(|config| assert!(config.dummy_eth1_backend));
}
#[test]
fn eth1_flag() {
CommandLineTest::new()
.flag("eth1", None)
.run_with_zero_port()
.with_config(|config| assert!(config.sync_eth1_chain));
}
#[test]
fn eth1_blocks_per_log_query_flag() {
CommandLineTest::new()
.flag("eth1-blocks-per-log-query", Some("500"))
.run_with_zero_port()
.with_config(|config| assert_eq!(config.eth1.blocks_per_log_query, 500));
}
#[test]
fn eth1_purge_cache_flag() {
CommandLineTest::new()
.flag("eth1-purge-cache", None)
.run_with_zero_port()
.with_config(|config| assert!(config.eth1.purge_cache));
}
#[test]
fn eth1_cache_follow_distance_default() {
CommandLineTest::new()
.run_with_zero_port()
.with_config(|config| {
assert_eq!(config.eth1.cache_follow_distance, None);
assert_eq!(config.eth1.cache_follow_distance(), 3 * 2048 / 4);
});
}
#[test]
fn eth1_cache_follow_distance_manual() {
CommandLineTest::new()
.flag("eth1-cache-follow-distance", Some("128"))
.run_with_zero_port()
.with_config(|config| {
assert_eq!(config.eth1.cache_follow_distance, Some(128));
assert_eq!(config.eth1.cache_follow_distance(), 128);
});
}
// Tests for Bellatrix flags.
fn run_bellatrix_execution_endpoints_flag_test(flag: &str) {
use sensitive_url::SensitiveUrl;
let urls = vec!["http://sigp.io/no-way:1337", "http://infura.not_real:4242"];
// we don't support redundancy for execution-endpoints
// only the first provided endpoint is parsed.
let mut endpoint_arg = urls[0].to_string();
for url in urls.iter().skip(1) {
endpoint_arg.push(',');
endpoint_arg.push_str(url);
}
let (_dirs, jwts): (Vec<_>, Vec<_>) = (0..2)
.map(|i| {
let dir = TempDir::new().expect("Unable to create temporary directory");
let path = dir.path().join(format!("jwt-{}", i));
(dir, path)
})
.unzip();
let mut jwts_arg = jwts[0].as_os_str().to_str().unwrap().to_string();
for jwt in jwts.iter().skip(1) {
jwts_arg.push(',');
jwts_arg.push_str(jwt.as_os_str().to_str().unwrap());
}
// this is way better but intersperse is still a nightly feature :/
// let endpoint_arg: String = urls.into_iter().intersperse(",").collect();
CommandLineTest::new()
.flag(flag, Some(&endpoint_arg))
.flag("execution-jwt", Some(&jwts_arg))
.run_with_zero_port()
.with_config(|config| {
let config = config.execution_layer.as_ref().unwrap();
assert_eq!(config.execution_endpoint.is_some(), true);
assert_eq!(
config.execution_endpoint.as_ref().unwrap().clone(),
SensitiveUrl::parse(&urls[0]).unwrap()
);
// Only the first secret file should be used.
assert_eq!(
config.secret_file.as_ref().unwrap().clone(),
jwts[0].clone()
);
});
}
#[test]
fn run_execution_jwt_secret_key_is_persisted() {
let jwt_secret_key = "0x3cbc11b0d8fa16f3344eacfd6ff6430b9d30734450e8adcf5400f88d327dcb33";
CommandLineTest::new()
.flag("execution-endpoint", Some("http://localhost:8551/"))
.flag("execution-jwt-secret-key", Some(jwt_secret_key))
.run_with_zero_port()
.with_config(|config| {
let config = config.execution_layer.as_ref().unwrap();
assert_eq!(
config.execution_endpoint.as_ref().unwrap().full.to_string(),
"http://localhost:8551/"
);
let mut file_jwt_secret_key = String::new();
File::open(config.secret_file.as_ref().unwrap())
.expect("could not open jwt_secret_key file")
.read_to_string(&mut file_jwt_secret_key)
.expect("could not read from file");
assert_eq!(file_jwt_secret_key, jwt_secret_key);
});
}
#[test]
fn execution_timeout_multiplier_flag() {
let dir = TempDir::new().expect("Unable to create temporary directory");
CommandLineTest::new()
.flag("execution-endpoint", Some("http://meow.cats"))
.flag(
"execution-jwt",
dir.path().join("jwt-file").as_os_str().to_str(),
)
.flag("execution-timeout-multiplier", Some("3"))
.run_with_zero_port()
.with_config(|config| {
let config = config.execution_layer.as_ref().unwrap();
assert_eq!(config.execution_timeout_multiplier, Some(3));
});
}
#[test]
fn bellatrix_execution_endpoints_flag() {
run_bellatrix_execution_endpoints_flag_test("execution-endpoints")
}
#[test]
fn bellatrix_execution_endpoint_flag() {
run_bellatrix_execution_endpoints_flag_test("execution-endpoint")
}
#[test]
fn bellatrix_jwt_secrets_flag() {
let dir = TempDir::new().expect("Unable to create temporary directory");
let mut file = File::create(dir.path().join("jwtsecrets")).expect("Unable to create file");
file.write_all(b"0x3cbc11b0d8fa16f3344eacfd6ff6430b9d30734450e8adcf5400f88d327dcb33")
.expect("Unable to write to file");
CommandLineTest::new()
.flag("execution-endpoints", Some("http://localhost:8551/"))
.flag(
"jwt-secrets",
dir.path().join("jwt-file").as_os_str().to_str(),
)
.run_with_zero_port()
.with_config(|config| {
let config = config.execution_layer.as_ref().unwrap();
assert_eq!(
config.execution_endpoint.as_ref().unwrap().full.to_string(),
"http://localhost:8551/"
);
assert_eq!(
config.secret_file.as_ref().unwrap().clone(),
dir.path().join("jwt-file")
);
});
}
#[test]
fn bellatrix_fee_recipient_flag() {
let dir = TempDir::new().expect("Unable to create temporary directory");
CommandLineTest::new()
.flag("execution-endpoint", Some("http://meow.cats"))
.flag(
"execution-jwt",
dir.path().join("jwt-file").as_os_str().to_str(),
)
.flag(
"suggested-fee-recipient",
Some("0x00000000219ab540356cbb839cbe05303d7705fa"),
)
.run_with_zero_port()
.with_config(|config| {
let config = config.execution_layer.as_ref().unwrap();
assert_eq!(
config.suggested_fee_recipient,
Some(Address::from_str("0x00000000219ab540356cbb839cbe05303d7705fa").unwrap())
);
});
}
fn run_payload_builder_flag_test(flag: &str, builders: &str) {
use sensitive_url::SensitiveUrl;
let all_builders: Vec<_> = builders
.split(",")
.map(|builder| SensitiveUrl::parse(builder).expect("valid builder url"))
.collect();
run_payload_builder_flag_test_with_config(flag, builders, None, None, |config| {
let config = config.execution_layer.as_ref().unwrap();
// Only first provided endpoint is parsed as we don't support
// redundancy.
assert_eq!(config.builder_url, all_builders.get(0).cloned());
})
}
fn run_payload_builder_flag_test_with_config<F: Fn(&Config)>(
flag: &str,
builders: &str,
additional_flag: Option<&str>,
additional_flag_value: Option<&str>,
f: F,
) {
let dir = TempDir::new().expect("Unable to create temporary directory");
let mut test = CommandLineTest::new();
test.flag("execution-endpoint", Some("http://meow.cats"))
.flag(
"execution-jwt",
dir.path().join("jwt-file").as_os_str().to_str(),
)
.flag(flag, Some(builders));
if let Some(additional_flag_name) = additional_flag {
test.flag(additional_flag_name, additional_flag_value);
}
test.run_with_zero_port().with_config(f);
}
#[test]
fn payload_builder_flags() {
run_payload_builder_flag_test("builder", "http://meow.cats");
run_payload_builder_flag_test("payload-builder", "http://meow.cats");
run_payload_builder_flag_test("payload-builders", "http://meow.cats,http://woof.dogs");
}
#[test]
fn builder_fallback_flags() {
run_payload_builder_flag_test_with_config(
"builder",
"http://meow.cats",
Some("builder-fallback-skips"),
Some("7"),
|config| {
assert_eq!(config.chain.builder_fallback_skips, 7);
},
);
run_payload_builder_flag_test_with_config(
"builder",
"http://meow.cats",
Some("builder-fallback-skips-per-epoch"),
Some("11"),
|config| {
assert_eq!(config.chain.builder_fallback_skips_per_epoch, 11);
},
);
run_payload_builder_flag_test_with_config(
"builder",
"http://meow.cats",
Some("builder-fallback-epochs-since-finalization"),
Some("4"),
|config| {
assert_eq!(config.chain.builder_fallback_epochs_since_finalization, 4);
},
);
run_payload_builder_flag_test_with_config(
"builder",
"http://meow.cats",
Some("builder-fallback-disable-checks"),
None,
|config| {
assert_eq!(config.chain.builder_fallback_disable_checks, true);
},
);
}
#[test]
fn builder_get_header_timeout() {
run_payload_builder_flag_test_with_config(
"builder",
"http://meow.cats",
Some("builder-header-timeout"),
Some("1500"),
|config| {
assert_eq!(
config
.execution_layer
.as_ref()
.unwrap()
.builder_header_timeout,
Some(Duration::from_millis(1500))
);
},
);
}
#[test]
fn builder_user_agent() {
run_payload_builder_flag_test_with_config(
"builder",
"http://meow.cats",
None,
None,
|config| {
assert_eq!(
config.execution_layer.as_ref().unwrap().builder_user_agent,
None
);
},
);
run_payload_builder_flag_test_with_config(
"builder",
"http://meow.cats",
Some("builder-user-agent"),
Some("anon"),
|config| {
assert_eq!(
config
.execution_layer
.as_ref()
.unwrap()
.builder_user_agent
.as_ref()
.unwrap(),
"anon"
);
},
);
}
fn run_jwt_optional_flags_test(jwt_flag: &str, jwt_id_flag: &str, jwt_version_flag: &str) {
use sensitive_url::SensitiveUrl;
let dir = TempDir::new().expect("Unable to create temporary directory");
let execution_endpoint = "http://meow.cats";
let jwt_file = "jwt-file";
let id = "bn-1";
let version = "Lighthouse-v2.1.3";
CommandLineTest::new()
.flag("execution-endpoint", Some(execution_endpoint))
.flag(jwt_flag, dir.path().join(jwt_file).as_os_str().to_str())
.flag(jwt_id_flag, Some(id))
.flag(jwt_version_flag, Some(version))
.run_with_zero_port()
.with_config(|config| {
let el_config = config.execution_layer.as_ref().unwrap();
assert_eq!(el_config.jwt_id, Some(id.to_string()));
assert_eq!(el_config.jwt_version, Some(version.to_string()));
assert_eq!(
config.eth1.endpoint,
Eth1Endpoint::Auth {
endpoint: SensitiveUrl::parse(execution_endpoint).unwrap(),
jwt_path: dir.path().join(jwt_file),
jwt_id: Some(id.to_string()),
jwt_version: Some(version.to_string()),
}
);
});
}
#[test]
fn jwt_optional_flags() {
run_jwt_optional_flags_test("execution-jwt", "execution-jwt-id", "execution-jwt-version");
}
#[test]
fn jwt_optional_alias_flags() {
run_jwt_optional_flags_test("jwt-secrets", "jwt-id", "jwt-version");
}
#[test]
fn terminal_total_difficulty_override_flag() {
use beacon_node::beacon_chain::types::Uint256;
CommandLineTest::new()
.flag("terminal-total-difficulty-override", Some("1337424242"))
.run_with_zero_port()
.with_spec::<MainnetEthSpec, _>(|spec| {
assert_eq!(spec.terminal_total_difficulty, Uint256::from(1337424242))
});
}
#[test]
fn terminal_block_hash_and_activation_epoch_override_flags() {
CommandLineTest::new()
.flag("terminal-block-hash-epoch-override", Some("1337"))
.flag(
"terminal-block-hash-override",
Some("0x4242424242424242424242424242424242424242424242424242424242424242"),
)
.run_with_zero_port()
.with_spec::<MainnetEthSpec, _>(|spec| {
assert_eq!(
spec.terminal_block_hash,
ExecutionBlockHash::from_str(
"0x4242424242424242424242424242424242424242424242424242424242424242"
)
.unwrap()
);
assert_eq!(spec.terminal_block_hash_activation_epoch, 1337);
});
}
#[test]
#[should_panic]
fn terminal_block_hash_missing_activation_epoch() {
CommandLineTest::new()
.flag(
"terminal-block-hash-override",
Some("0x4242424242424242424242424242424242424242424242424242424242424242"),
)
.run_with_zero_port();
}
#[test]
#[should_panic]
fn epoch_override_missing_terminal_block_hash() {
CommandLineTest::new()
.flag("terminal-block-hash-epoch-override", Some("1337"))
.run_with_zero_port();
}
#[test]
fn safe_slots_to_import_optimistically_flag() {
CommandLineTest::new()
.flag("safe-slots-to-import-optimistically", Some("421337"))
.run_with_zero_port()
.with_spec::<MainnetEthSpec, _>(|spec| {
assert_eq!(spec.safe_slots_to_import_optimistically, 421337)
});
}
// Tests for Network flags.
#[test]
fn network_dir_flag() {
let dir = TempDir::new().expect("Unable to create temporary directory");
CommandLineTest::new()
.flag("network-dir", dir.path().as_os_str().to_str())
.run_with_zero_port()
.with_config(|config| assert_eq!(config.network.network_dir, dir.path()));
}
#[test]
fn network_target_peers_flag() {
CommandLineTest::new()
.flag("target-peers", Some("55"))
.run_with_zero_port()
.with_config(|config| {
assert_eq!(config.network.target_peers, "55".parse::<usize>().unwrap());
});
}
#[test]
fn network_subscribe_all_data_column_subnets_flag() {
CommandLineTest::new()
.flag("subscribe-all-data-column-subnets", None)
.run_with_zero_port()
.with_config(|config| assert!(config.network.subscribe_all_data_column_subnets));
}
#[test]
fn network_enable_sampling_flag() {
CommandLineTest::new()
.flag("enable-sampling", None)
.run_with_zero_port()
.with_config(|config| assert!(config.chain.enable_sampling));
}
#[test]
fn network_enable_sampling_flag_default() {
CommandLineTest::new()
.run_with_zero_port()
.with_config(|config| assert!(!config.chain.enable_sampling));
}
#[test]
fn network_subscribe_all_subnets_flag() {
CommandLineTest::new()
.flag("subscribe-all-subnets", None)
.run_with_zero_port()
.with_config(|config| assert!(config.network.subscribe_all_subnets));
}
#[test]
fn network_import_all_attestations_flag() {
CommandLineTest::new()
.flag("import-all-attestations", None)
.run_with_zero_port()
.with_config(|config| assert!(config.network.import_all_attestations));
}
#[test]
fn network_shutdown_after_sync_flag() {
CommandLineTest::new()
.flag("shutdown-after-sync", None)
.run_with_zero_port()
.with_config(|config| assert!(config.network.shutdown_after_sync));
}
#[test]
fn network_shutdown_after_sync_disabled_flag() {
CommandLineTest::new()
.run_with_zero_port()
.with_config(|config| assert!(!config.network.shutdown_after_sync));
}
#[test]
fn network_listen_address_flag_v4() {
let addr = "127.0.0.2".parse::<Ipv4Addr>().unwrap();
CommandLineTest::new()
.flag("listen-address", Some("127.0.0.2"))
.run_with_zero_port()
.with_config(|config| {
assert_eq!(
config.network.listen_addrs().v4().map(|addr| addr.addr),
Some(addr)
)
});
}
#[test]
fn network_listen_address_flag_v6() {
const ADDR: &str = "::1";
let addr = ADDR.parse::<Ipv6Addr>().unwrap();
CommandLineTest::new()
.flag("listen-address", Some(ADDR))
.run_with_zero_port()
.with_config(|config| {
assert_eq!(
config.network.listen_addrs().v6().map(|addr| addr.addr),
Some(addr)
)
});
}
#[test]
fn network_listen_address_flag_dual_stack() {
const V4_ADDR: &str = "127.0.0.1";
const V6_ADDR: &str = "::1";
let ipv6_addr = V6_ADDR.parse::<Ipv6Addr>().unwrap();
let ipv4_addr = V4_ADDR.parse::<Ipv4Addr>().unwrap();
CommandLineTest::new()
.flag("listen-address", Some(V6_ADDR))
.flag("listen-address", Some(V4_ADDR))
.run_with_zero_port()
.with_config(|config| {
assert_eq!(
config.network.listen_addrs().v6().map(|addr| addr.addr),
Some(ipv6_addr)
);
assert_eq!(
config.network.listen_addrs().v4().map(|addr| addr.addr),
Some(ipv4_addr)
)
});
}
#[test]
#[should_panic]
fn network_listen_address_flag_wrong_double_v4_value_config() {
// It's actually possible to listen over multiple sockets in libp2p over the same ip version.
// However this is not compatible with the single contactable address over each version in ENR.
// Because of this, it's important to test this is disallowed.
const V4_ADDR1: &str = "127.0.0.1";
const V4_ADDR2: &str = "0.0.0.0";
CommandLineTest::new()
.flag("listen-address", Some(V4_ADDR1))
.flag("listen-address", Some(V4_ADDR2))
.run_with_zero_port();
}
#[test]
#[should_panic]
fn network_listen_address_flag_wrong_double_v6_value_config() {
// It's actually possible to listen over multiple sockets in libp2p over the same ip version.
// However this is not compatible with the single contactable address over each version in ENR.
// Because of this, it's important to test this is disallowed.
const V6_ADDR1: &str = "::3";
const V6_ADDR2: &str = "::1";
CommandLineTest::new()
.flag("listen-address", Some(V6_ADDR1))
.flag("listen-address", Some(V6_ADDR2))
.run_with_zero_port();
}
#[test]
fn network_port_flag_over_ipv4() {
let port = 0;
CommandLineTest::new()
.flag("port", Some(port.to_string().as_str()))
.flag("allow-insecure-genesis-sync", None)
.run()
.with_config(|config| {
assert_eq!(
config.network.listen_addrs().v4().map(|listen_addr| (
listen_addr.disc_port,
listen_addr.quic_port,
listen_addr.tcp_port
)),
// quic_port should be 0 if tcp_port is given as 0.
Some((port, 0, port))
);
});
let port = unused_tcp4_port().expect("Unable to find unused port.");
CommandLineTest::new()
.flag("port", Some(port.to_string().as_str()))
.flag("allow-insecure-genesis-sync", None)
.run()
.with_config(|config| {
assert_eq!(
config.network.listen_addrs().v4().map(|listen_addr| (
listen_addr.disc_port,
listen_addr.quic_port,
listen_addr.tcp_port
)),
// quic_port should be (tcp_port + 1) if tcp_port is given as non-zero.
Some((port, port + 1, port))
);
});
}
#[test]
fn network_port_flag_over_ipv6() {
let port = 0;
CommandLineTest::new()
.flag("listen-address", Some("::1"))
.flag("port", Some(port.to_string().as_str()))
.flag("allow-insecure-genesis-sync", None)
.run()
.with_config(|config| {
assert_eq!(
config.network.listen_addrs().v6().map(|listen_addr| (
listen_addr.disc_port,
listen_addr.quic_port,
listen_addr.tcp_port
)),
// quic_port should be 0 if tcp_port is given as 0.
Some((port, 0, port))
);
});
let port = unused_tcp4_port().expect("Unable to find unused port.");
CommandLineTest::new()
.flag("listen-address", Some("::1"))
.flag("port", Some(port.to_string().as_str()))
.flag("allow-insecure-genesis-sync", None)
.run()
.with_config(|config| {
assert_eq!(
config.network.listen_addrs().v6().map(|listen_addr| (
listen_addr.disc_port,
listen_addr.quic_port,
listen_addr.tcp_port
)),
// quic_port should be (tcp_port + 1) if tcp_port is given as non-zero.
Some((port, port + 1, port))
);
});
}
#[test]
fn network_port_flag_over_ipv4_and_ipv6() {
let port = 0;
let port6 = 0;
CommandLineTest::new()
.flag("listen-address", Some("127.0.0.1"))
.flag("listen-address", Some("::1"))
.flag("port", Some(port.to_string().as_str()))
.flag("port6", Some(port6.to_string().as_str()))
.flag("allow-insecure-genesis-sync", None)
.run()
.with_config(|config| {
assert_eq!(
config.network.listen_addrs().v4().map(|listen_addr| (
listen_addr.disc_port,
listen_addr.quic_port,
listen_addr.tcp_port
)),
// quic_port should be 0 if tcp_port is given as 0.
Some((port, 0, port))
);
assert_eq!(
config.network.listen_addrs().v6().map(|listen_addr| (
listen_addr.disc_port,
listen_addr.quic_port,
listen_addr.tcp_port
)),
// quic_port should be 0 if tcp_port is given as 0.
Some((port6, 0, port6))
);
});
let port = unused_tcp4_port().expect("Unable to find unused port.");
let port6 = unused_tcp6_port().expect("Unable to find unused port.");
CommandLineTest::new()
.flag("listen-address", Some("127.0.0.1"))
.flag("listen-address", Some("::1"))
.flag("port", Some(port.to_string().as_str()))
.flag("port6", Some(port6.to_string().as_str()))
.flag("allow-insecure-genesis-sync", None)
.run()
.with_config(|config| {
assert_eq!(
config.network.listen_addrs().v4().map(|listen_addr| (
listen_addr.disc_port,
listen_addr.quic_port,
listen_addr.tcp_port
)),
// quic_port should be (tcp_port + 1) if tcp_port is given as non-zero.
Some((port, port + 1, port))
);
assert_eq!(
config.network.listen_addrs().v6().map(|listen_addr| (
listen_addr.disc_port,
listen_addr.quic_port,
listen_addr.tcp_port
)),
// quic_port should be (tcp_port + 1) if tcp_port is given as non-zero.
Some((port6, port6 + 1, port6))
);
});
}
#[test]
fn network_port_and_discovery_port_flags_over_ipv4() {
let tcp4_port = 0;
let disc4_port = 0;
CommandLineTest::new()
.flag("port", Some(tcp4_port.to_string().as_str()))
.flag("discovery-port", Some(disc4_port.to_string().as_str()))
.flag("allow-insecure-genesis-sync", None)
.run()
.with_config(|config| {
assert_eq!(
config
.network
.listen_addrs()
.v4()
.map(|listen_addr| (listen_addr.tcp_port, listen_addr.disc_port)),
Some((tcp4_port, disc4_port))
);
});
}
#[test]
fn network_port_and_discovery_port_flags_over_ipv6() {
let tcp6_port = 0;
let disc6_port = 0;
CommandLineTest::new()
.flag("listen-address", Some("::1"))
.flag("port", Some(tcp6_port.to_string().as_str()))
.flag("discovery-port", Some(disc6_port.to_string().as_str()))
.flag("allow-insecure-genesis-sync", None)
.run()
.with_config(|config| {
assert_eq!(
config
.network
.listen_addrs()
.v6()
.map(|listen_addr| (listen_addr.tcp_port, listen_addr.disc_port)),
Some((tcp6_port, disc6_port))
);
});
}
#[test]
fn network_port_and_discovery_port_flags_over_ipv4_and_ipv6() {
let tcp4_port = 0;
let disc4_port = 0;
let tcp6_port = 0;
let disc6_port = 0;
CommandLineTest::new()
.flag("listen-address", Some("::1"))
.flag("listen-address", Some("127.0.0.1"))
.flag("port", Some(tcp4_port.to_string().as_str()))
.flag("discovery-port", Some(disc4_port.to_string().as_str()))
.flag("port6", Some(tcp6_port.to_string().as_str()))
.flag("discovery-port6", Some(disc6_port.to_string().as_str()))
.flag("allow-insecure-genesis-sync", None)
.run()
.with_config(|config| {
assert_eq!(
config
.network
.listen_addrs()
.v4()
.map(|listen_addr| (listen_addr.tcp_port, listen_addr.disc_port)),
Some((tcp4_port, disc4_port))
);
assert_eq!(
config
.network
.listen_addrs()
.v6()
.map(|listen_addr| (listen_addr.tcp_port, listen_addr.disc_port)),
Some((tcp6_port, disc6_port))
);
});
}
#[test]
fn network_port_discovery_quic_port_flags_over_ipv4_and_ipv6() {
let tcp4_port = 0;
let disc4_port = 0;
let quic4_port = 0;
let tcp6_port = 0;
let disc6_port = 0;
let quic6_port = 0;
CommandLineTest::new()
.flag("listen-address", Some("::1"))
.flag("listen-address", Some("127.0.0.1"))
.flag("port", Some(tcp4_port.to_string().as_str()))
.flag("discovery-port", Some(disc4_port.to_string().as_str()))
.flag("quic-port", Some(quic4_port.to_string().as_str()))
.flag("port6", Some(tcp6_port.to_string().as_str()))
.flag("discovery-port6", Some(disc6_port.to_string().as_str()))
.flag("quic-port6", Some(quic6_port.to_string().as_str()))
.flag("allow-insecure-genesis-sync", None)
.run()
.with_config(|config| {
assert_eq!(
config.network.listen_addrs().v4().map(|listen_addr| (
listen_addr.tcp_port,
listen_addr.disc_port,
listen_addr.quic_port
)),
Some((tcp4_port, disc4_port, quic4_port))
);
assert_eq!(
config.network.listen_addrs().v6().map(|listen_addr| (
listen_addr.tcp_port,
listen_addr.disc_port,
listen_addr.quic_port
)),
Some((tcp6_port, disc6_port, quic6_port))
);
});
}
#[test]
fn disable_discovery_flag() {
CommandLineTest::new()
.flag("disable-discovery", None)
.run_with_zero_port()
.with_config(|config| assert!(config.network.disable_discovery));
}
#[test]
fn disable_quic_flag() {
CommandLineTest::new()
.flag("disable-quic", None)
.run_with_zero_port()
.with_config(|config| assert!(config.network.disable_quic_support));
}
#[test]
fn disable_peer_scoring_flag() {
CommandLineTest::new()
.flag("disable-peer-scoring", None)
.run_with_zero_port()
.with_config(|config| assert!(config.network.disable_peer_scoring));
}
#[test]
fn disable_upnp_flag() {
CommandLineTest::new()
.flag("disable-upnp", None)
.run_with_zero_port()
.with_config(|config| assert!(!config.network.upnp_enabled));
}
#[test]
fn disable_backfill_rate_limiting_flag() {
CommandLineTest::new()
.flag("disable-backfill-rate-limiting", None)
.run_with_zero_port()
.with_config(|config| assert!(!config.beacon_processor.enable_backfill_rate_limiting));
}
#[test]
fn default_backfill_rate_limiting_flag() {
CommandLineTest::new()
.run_with_zero_port()
.with_config(|config| assert!(config.beacon_processor.enable_backfill_rate_limiting));
}
#[test]
fn default_boot_nodes() {
let number_of_boot_nodes = 15;
CommandLineTest::new()
.run_with_zero_port()
.with_config(|config| {
// Lighthouse Team (Sigma Prime)
assert_eq!(config.network.boot_nodes_enr.len(), number_of_boot_nodes);
});
}
#[test]
fn boot_nodes_flag() {
let nodes = "enr:-IS4QHCYrYZbAKWCBRlAy5zzaDZXJBGkcnh4MHcBFZntXNFrdvJjX04jRzjzCBOonrkTfj499SZuOh8R33Ls8RRcy5wBgmlkgnY0gmlwhH8AAAGJc2VjcDI1NmsxoQPKY0yuDUmstAHYpMa2_oxVtw0RW_QAdpzBQA8yWM0xOIN1ZHCCdl8,\
enr:-LK4QFOFWca5ABQzxiCRcy37G7wy1K6zD4qMYBSN5ozzanwze_XVvXVhCk9JvF0cHXOBZrHK1E4vU7Gn-a0bHVczoDU6h2F0dG5ldHOIAAAAAAAAAACEZXRoMpA7CIeVAAAgCf__________gmlkgnY0gmlwhNIy-4iJc2VjcDI1NmsxoQJA3AXQJ6M3NpBWtJS3HPtbXG14t7qHjXuIaL6IOz89T4N0Y3CCIyiDdWRwgiMo";
let enr: Vec<&str> = nodes.split(',').collect();
CommandLineTest::new()
.flag("boot-nodes", Some(nodes))
.run_with_zero_port()
.with_config(|config| {
assert_eq!(config.network.boot_nodes_enr[0].to_base64(), enr[0]);
assert_eq!(config.network.boot_nodes_enr[1].to_base64(), enr[1]);
});
}
#[test]
fn boot_nodes_multiaddr_flag() {
let nodes = "/ip4/0.0.0.0/tcp/9000/p2p/16Uiu2HAkynrfLjeoAP7R3WFySad2NfduShkTpx8f8ygpSSfP1yen,\
/ip4/192.167.55.55/tcp/9000/p2p/16Uiu2HAkynrfLjeoBP7R3WFyDad2NfduVhkWpx8f8ygpSSfP1yen";
let multiaddr: Vec<&str> = nodes.split(',').collect();
CommandLineTest::new()
.flag("boot-nodes", Some(nodes))
.run_with_zero_port()
.with_config(|config| {
assert_eq!(
config.network.boot_nodes_multiaddr[0].to_string(),
multiaddr[0]
);
assert_eq!(
config.network.boot_nodes_multiaddr[1].to_string(),
multiaddr[1]
);
});
}
#[test]
fn private_flag() {
CommandLineTest::new()
.flag("private", None)
.run_with_zero_port()
.with_config(|config| {
assert!(config.network.private);
assert!(matches!(
config.beacon_graffiti,
GraffitiOrigin::UserSpecified(_)
));
assert_eq!(
config.beacon_graffiti.graffiti().to_string(),
"0x0000000000000000000000000000000000000000000000000000000000000000".to_string(),
);
});
}
#[test]
fn zero_ports_flag() {
CommandLineTest::new()
.run_with_zero_port()
.with_config(|config| {
assert_eq!(config.http_api.listen_port, 0);
assert_eq!(config.http_metrics.listen_port, 0);
});
}
#[test]
fn network_load_flag() {
CommandLineTest::new()
.flag("network-load", Some("4"))
.run_with_zero_port()
.with_config(|config| {
assert_eq!(config.network.network_load, 4);
});
}
// Tests for ENR flags.
#[test]
fn enr_udp_port_flag() {
let port = DUMMY_ENR_UDP_PORT;
assert!(port != 0);
CommandLineTest::new()
.flag("enr-udp-port", Some(port.to_string().as_str()))
.run_with_zero_port()
.with_config(|config| {
assert_eq!(
config.network.enr_udp4_port.map(|port| port.get()),
Some(port)
)
});
}
#[test]
fn enr_quic_port_flag() {
let port = DUMMY_ENR_QUIC_PORT;
CommandLineTest::new()
.flag("enr-quic-port", Some(port.to_string().as_str()))
.run_with_zero_port()
.with_config(|config| {
assert_eq!(
config.network.enr_quic4_port.map(|port| port.get()),
Some(port)
)
});
}
#[test]
fn enr_tcp_port_flag() {
let port = DUMMY_ENR_TCP_PORT;
CommandLineTest::new()
.flag("enr-tcp-port", Some(port.to_string().as_str()))
.run_with_zero_port()
.with_config(|config| {
assert_eq!(
config.network.enr_tcp4_port.map(|port| port.get()),
Some(port)
)
});
}
#[test]
fn enr_udp6_port_flag() {
let port = DUMMY_ENR_UDP_PORT;
CommandLineTest::new()
.flag("enr-udp6-port", Some(port.to_string().as_str()))
.run_with_zero_port()
.with_config(|config| {
assert_eq!(
config.network.enr_udp6_port.map(|port| port.get()),
Some(port)
)
});
}
#[test]
fn enr_quic6_port_flag() {
let port = DUMMY_ENR_QUIC_PORT;
CommandLineTest::new()
.flag("enr-quic6-port", Some(port.to_string().as_str()))
.run_with_zero_port()
.with_config(|config| {
assert_eq!(
config.network.enr_quic6_port.map(|port| port.get()),
Some(port)
)
});
}
#[test]
fn enr_tcp6_port_flag() {
let port = DUMMY_ENR_TCP_PORT;
CommandLineTest::new()
.flag("enr-tcp6-port", Some(port.to_string().as_str()))
.run_with_zero_port()
.with_config(|config| {
assert_eq!(
config.network.enr_tcp6_port.map(|port| port.get()),
Some(port)
)
});
}
#[test]
fn enr_match_flag_over_ipv4() {
let addr = "127.0.0.2".parse::<Ipv4Addr>().unwrap();
let udp4_port = unused_udp4_port().expect("Unable to find unused port.");
let tcp4_port = unused_tcp4_port().expect("Unable to find unused port.");
CommandLineTest::new()
.flag("enr-match", None)
.flag("listen-address", Some("127.0.0.2"))
.flag("discovery-port", Some(udp4_port.to_string().as_str()))
.flag("port", Some(tcp4_port.to_string().as_str()))
.flag("allow-insecure-genesis-sync", None)
.run()
.with_config(|config| {
assert_eq!(
config.network.listen_addrs().v4().map(|listen_addr| (
listen_addr.addr,
listen_addr.disc_port,
listen_addr.tcp_port
)),
Some((addr, udp4_port, tcp4_port))
);
assert_eq!(config.network.enr_address, (Some(addr), None));
assert_eq!(
config.network.enr_udp4_port.map(|port| port.get()),
Some(udp4_port)
);
});
}
#[test]
fn enr_match_flag_over_ipv6() {
const ADDR: &str = "::1";
let addr = ADDR.parse::<Ipv6Addr>().unwrap();
let udp6_port = unused_udp6_port().expect("Unable to find unused port.");
let tcp6_port = unused_tcp6_port().expect("Unable to find unused port.");
CommandLineTest::new()
.flag("enr-match", None)
.flag("listen-address", Some(ADDR))
.flag("discovery-port", Some(udp6_port.to_string().as_str()))
.flag("port", Some(tcp6_port.to_string().as_str()))
.flag("allow-insecure-genesis-sync", None)
.run()
.with_config(|config| {
assert_eq!(
config.network.listen_addrs().v6().map(|listen_addr| (
listen_addr.addr,
listen_addr.disc_port,
listen_addr.tcp_port
)),
Some((addr, udp6_port, tcp6_port))
);
assert_eq!(config.network.enr_address, (None, Some(addr)));
assert_eq!(
config.network.enr_udp6_port.map(|port| port.get()),
Some(udp6_port)
);
});
}
#[test]
fn enr_match_flag_over_ipv4_and_ipv6() {
const IPV6_ADDR: &str = "::1";
let udp6_port = unused_udp6_port().expect("Unable to find unused port.");
let tcp6_port = unused_tcp6_port().expect("Unable to find unused port.");
let ipv6_addr = IPV6_ADDR.parse::<Ipv6Addr>().unwrap();
const IPV4_ADDR: &str = "127.0.0.1";
let udp4_port = unused_udp4_port().expect("Unable to find unused port.");
let tcp4_port = unused_tcp4_port().expect("Unable to find unused port.");
let ipv4_addr = IPV4_ADDR.parse::<Ipv4Addr>().unwrap();
CommandLineTest::new()
.flag("enr-match", None)
.flag("listen-address", Some(IPV4_ADDR))
.flag("discovery-port", Some(udp4_port.to_string().as_str()))
.flag("port", Some(tcp4_port.to_string().as_str()))
.flag("listen-address", Some(IPV6_ADDR))
.flag("discovery-port6", Some(udp6_port.to_string().as_str()))
.flag("port6", Some(tcp6_port.to_string().as_str()))
.flag("allow-insecure-genesis-sync", None)
.run()
.with_config(|config| {
assert_eq!(
config.network.listen_addrs().v6().map(|listen_addr| (
listen_addr.addr,
listen_addr.disc_port,
listen_addr.tcp_port
)),
Some((ipv6_addr, udp6_port, tcp6_port))
);
assert_eq!(
config.network.listen_addrs().v4().map(|listen_addr| (
listen_addr.addr,
listen_addr.disc_port,
listen_addr.tcp_port
)),
Some((ipv4_addr, udp4_port, tcp4_port))
);
assert_eq!(
config.network.enr_address,
(Some(ipv4_addr), Some(ipv6_addr))
);
assert_eq!(
config.network.enr_udp6_port.map(|port| port.get()),
Some(udp6_port)
);
assert_eq!(
config.network.enr_udp4_port.map(|port| port.get()),
Some(udp4_port)
);
});
}
#[test]
fn enr_address_flag_with_ipv4() {
let addr = "192.167.1.1".parse::<Ipv4Addr>().unwrap();
let port = DUMMY_ENR_UDP_PORT;
CommandLineTest::new()
.flag("enr-address", Some("192.167.1.1"))
.flag("enr-udp-port", Some(port.to_string().as_str()))
.run_with_zero_port()
.with_config(|config| {
assert_eq!(config.network.enr_address, (Some(addr), None));
assert_eq!(
config.network.enr_udp4_port.map(|port| port.get()),
Some(port)
);
});
}
#[test]
fn enr_address_flag_with_ipv6() {
let addr = "192.167.1.1".parse::<Ipv4Addr>().unwrap();
let port = DUMMY_ENR_UDP_PORT;
CommandLineTest::new()
.flag("enr-address", Some("192.167.1.1"))
.flag("enr-udp-port", Some(port.to_string().as_str()))
.run_with_zero_port()
.with_config(|config| {
assert_eq!(config.network.enr_address, (Some(addr), None));
assert_eq!(
config.network.enr_udp4_port.map(|port| port.get()),
Some(port)
);
});
}
#[test]
fn enr_address_dns_flag() {
let addr = Ipv4Addr::LOCALHOST;
let ipv6addr = Ipv6Addr::LOCALHOST;
let port = DUMMY_ENR_UDP_PORT;
CommandLineTest::new()
.flag("enr-address", Some("localhost"))
.flag("enr-udp-port", Some(port.to_string().as_str()))
.run_with_zero_port()
.with_config(|config| {
assert!(
config.network.enr_address.0 == Some(addr)
|| config.network.enr_address.1 == Some(ipv6addr)
);
assert_eq!(
config.network.enr_udp4_port.map(|port| port.get()),
Some(port)
);
});
}
#[test]
fn disable_enr_auto_update_flag() {
CommandLineTest::new()
.flag("disable-enr-auto-update", None)
.run_with_zero_port()
.with_config(|config| assert!(config.network.discv5_config.enr_update));
}
// Tests for HTTP flags.
#[test]
fn http_flag() {
CommandLineTest::new()
.flag("http", None)
.run_with_zero_port()
.with_config(|config| assert!(config.http_api.enabled));
}
#[test]
fn http_address_flag() {
let addr = "127.0.0.99".parse::<IpAddr>().unwrap();
CommandLineTest::new()
.flag("http", None)
.flag("http-address", Some("127.0.0.99"))
.run_with_zero_port()
.with_config(|config| assert_eq!(config.http_api.listen_addr, addr));
}
#[test]
fn http_address_ipv6_flag() {
let addr = "::1".parse::<IpAddr>().unwrap();
CommandLineTest::new()
.flag("http", None)
.flag("http-address", Some("::1"))
.run_with_zero_port()
.with_config(|config| assert_eq!(config.http_api.listen_addr, addr));
}
#[test]
fn http_port_flag() {
let port1 = 0;
let port2 = 0;
CommandLineTest::new()
.flag("http", None)
.flag("http-port", Some(port1.to_string().as_str()))
.flag("port", Some(port2.to_string().as_str()))
.flag("allow-insecure-genesis-sync", None)
.run()
.with_config(|config| assert_eq!(config.http_api.listen_port, port1));
}
#[test]
fn empty_self_limiter_flag() {
// Test that empty rate limiter is accepted using the default rate limiting configurations.
CommandLineTest::new()
.flag("self-limiter", None)
.run_with_zero_port()
.with_config(|config| {
assert_eq!(
config.network.outbound_rate_limiter_config,
Some(lighthouse_network::rpc::config::OutboundRateLimiterConfig::default())
)
});
}
#[test]
fn empty_inbound_rate_limiter_flag() {
CommandLineTest::new()
.run_with_zero_port()
.with_config(|config| {
assert_eq!(
config.network.inbound_rate_limiter_config,
Some(lighthouse_network::rpc::config::InboundRateLimiterConfig::default())
)
});
}
#[test]
fn disable_inbound_rate_limiter_flag() {
CommandLineTest::new()
.flag("disable-inbound-rate-limiter", None)
.run_with_zero_port()
.with_config(|config| assert_eq!(config.network.inbound_rate_limiter_config, None));
}
#[test]
fn http_allow_origin_flag() {
CommandLineTest::new()
.flag("http", None)
.flag("http-allow-origin", Some("http://127.0.0.99"))
.run_with_zero_port()
.with_config(|config| {
assert_eq!(
config.http_api.allow_origin,
Some("http://127.0.0.99".to_string())
);
});
}
#[test]
fn http_allow_origin_all_flag() {
CommandLineTest::new()
.flag("http", None)
.flag("http-allow-origin", Some("*"))
.run_with_zero_port()
.with_config(|config| assert_eq!(config.http_api.allow_origin, Some("*".to_string())));
}
#[test]
fn http_allow_sync_stalled_flag() {
CommandLineTest::new()
.flag("http", None)
.flag("http-allow-sync-stalled", None)
.run_with_zero_port();
}
#[test]
fn http_enable_beacon_processor() {
CommandLineTest::new()
.flag("http", None)
.run_with_zero_port()
.with_config(|config| assert_eq!(config.http_api.enable_beacon_processor, true));
CommandLineTest::new()
.flag("http", None)
.flag("http-enable-beacon-processor", Some("true"))
.run_with_zero_port()
.with_config(|config| assert_eq!(config.http_api.enable_beacon_processor, true));
CommandLineTest::new()
.flag("http", None)
.flag("http-enable-beacon-processor", Some("false"))
.run_with_zero_port()
.with_config(|config| assert_eq!(config.http_api.enable_beacon_processor, false));
}
#[test]
fn http_tls_flags() {
CommandLineTest::new()
.flag("http", None)
.flag("http-enable-tls", None)
.flag("http-tls-cert", Some("tests/tls/cert.pem"))
.flag("http-tls-key", Some("tests/tls/key.rsa"))
.run_with_zero_port()
.with_config(|config| {
let tls_config = config
.http_api
.tls_config
.as_ref()
.expect("tls_config was empty.");
assert_eq!(tls_config.cert, Path::new("tests/tls/cert.pem"));
assert_eq!(tls_config.key, Path::new("tests/tls/key.rsa"));
});
}
#[test]
fn http_spec_fork_default() {
CommandLineTest::new()
.flag("http", None)
.run_with_zero_port()
.with_config(|config| assert_eq!(config.http_api.spec_fork_name, None));
}
#[test]
fn http_spec_fork_override() {
CommandLineTest::new()
.flag("http", None)
.flag("http-spec-fork", Some("altair"))
.run_with_zero_port();
}
// Tests for Metrics flags.
#[test]
fn metrics_flag() {
CommandLineTest::new()
.flag("metrics", None)
.run_with_zero_port()
.with_config(|config| {
assert!(config.http_metrics.enabled);
assert!(config.network.metrics_enabled);
});
}
#[test]
fn metrics_address_flag() {
let addr = "127.0.0.99".parse::<IpAddr>().unwrap();
CommandLineTest::new()
.flag("metrics", None)
.flag("metrics-address", Some("127.0.0.99"))
.run_with_zero_port()
.with_config(|config| assert_eq!(config.http_metrics.listen_addr, addr));
}
#[test]
fn metrics_address_ipv6_flag() {
let addr = "::1".parse::<IpAddr>().unwrap();
CommandLineTest::new()
.flag("metrics", None)
.flag("metrics-address", Some("::1"))
.run_with_zero_port()
.with_config(|config| assert_eq!(config.http_metrics.listen_addr, addr));
}
#[test]
fn metrics_port_flag() {
let port1 = 0;
let port2 = 0;
CommandLineTest::new()
.flag("metrics", None)
.flag("metrics-port", Some(port1.to_string().as_str()))
.flag("port", Some(port2.to_string().as_str()))
.flag("allow-insecure-genesis-sync", None)
.run()
.with_config(|config| assert_eq!(config.http_metrics.listen_port, port1));
}
#[test]
fn metrics_allow_origin_flag() {
CommandLineTest::new()
.flag("metrics", None)
.flag("metrics-allow-origin", Some("http://localhost:5059"))
.run_with_zero_port()
.with_config(|config| {
assert_eq!(
config.http_metrics.allow_origin,
Some("http://localhost:5059".to_string())
)
});
}
#[test]
fn metrics_allow_origin_all_flag() {
CommandLineTest::new()
.flag("metrics", None)
.flag("metrics-allow-origin", Some("*"))
.run_with_zero_port()
.with_config(|config| assert_eq!(config.http_metrics.allow_origin, Some("*".to_string())));
}
// Tests for Validator Monitor flags.
#[test]
fn validator_monitor_default_values() {
CommandLineTest::new()
.run_with_zero_port()
.with_config(|config| assert!(config.validator_monitor == <_>::default()));
}
#[test]
fn validator_monitor_auto_flag() {
CommandLineTest::new()
.flag("validator-monitor-auto", None)
.run_with_zero_port()
.with_config(|config| assert!(config.validator_monitor.auto_register));
}
#[test]
fn validator_monitor_pubkeys_flag() {
CommandLineTest::new()
.flag("validator-monitor-pubkeys", Some("0xdeadbeefdeadbeefdeadbeefdeadbeefdeadbeefdeadbeefdeadbeefdeadbeefdeadbeefdeadbeefdeadbeefdeadbeef,\
0xbeefdeadbeefdeaddeadbeefdeadbeefdeadbeefdeadbeefdeadbeefdeadbeefdeadbeefdeadbeefdeadbeefdeadbeef"))
.run_with_zero_port()
.with_config(|config| {
assert_eq!(config.validator_monitor.validators[0].to_string(), "0xdeadbeefdeadbeefdeadbeefdeadbeefdeadbeefdeadbeefdeadbeefdeadbeefdeadbeefdeadbeefdeadbeefdeadbeef");
assert_eq!(config.validator_monitor.validators[1].to_string(), "0xbeefdeadbeefdeaddeadbeefdeadbeefdeadbeefdeadbeefdeadbeefdeadbeefdeadbeefdeadbeefdeadbeefdeadbeef");
});
}
#[test]
fn validator_monitor_file_flag() {
let dir = TempDir::new().expect("Unable to create temporary directory");
let mut file = File::create(dir.path().join("pubkeys.txt")).expect("Unable to create file");
file.write_all(b"0xdeadbeefdeadbeefdeadbeefdeadbeefdeadbeefdeadbeefdeadbeefdeadbeefdeadbeefdeadbeefdeadbeefdeadbeef,\
0xbeefdeadbeefdeaddeadbeefdeadbeefdeadbeefdeadbeefdeadbeefdeadbeefdeadbeefdeadbeefdeadbeefdeadbeef")
.expect("Unable to write to file");
CommandLineTest::new()
.flag("validator-monitor-file", dir.path().join("pubkeys.txt").as_os_str().to_str())
.run_with_zero_port()
.with_config(|config| {
assert_eq!(config.validator_monitor.validators[0].to_string(), "0xdeadbeefdeadbeefdeadbeefdeadbeefdeadbeefdeadbeefdeadbeefdeadbeefdeadbeefdeadbeefdeadbeefdeadbeef");
assert_eq!(config.validator_monitor.validators[1].to_string(), "0xbeefdeadbeefdeaddeadbeefdeadbeefdeadbeefdeadbeefdeadbeefdeadbeefdeadbeefdeadbeefdeadbeefdeadbeef");
});
}
#[test]
fn validator_monitor_metrics_threshold_default() {
CommandLineTest::new()
.run_with_zero_port()
.with_config(|config| {
assert_eq!(
config.validator_monitor.individual_tracking_threshold,
// If this value changes make sure to update the help text for
// the CLI command.
64
)
});
}
#[test]
fn validator_monitor_metrics_threshold_custom() {
CommandLineTest::new()
.flag(
"validator-monitor-individual-tracking-threshold",
Some("42"),
)
.run_with_zero_port()
.with_config(|config| {
assert_eq!(config.validator_monitor.individual_tracking_threshold, 42)
});
}
// Tests for Store flags.
#[test]
fn slots_per_restore_point_flag() {
CommandLineTest::new()
.flag("slots-per-restore-point", Some("64"))
.run_with_zero_port()
.with_config(|config| assert_eq!(config.store.slots_per_restore_point, 64));
}
#[test]
fn slots_per_restore_point_update_prev_default() {
use beacon_node::beacon_chain::store::config::{
DEFAULT_SLOTS_PER_RESTORE_POINT, PREV_DEFAULT_SLOTS_PER_RESTORE_POINT,
};
CommandLineTest::new()
.flag("slots-per-restore-point", Some("2048"))
.run_with_zero_port()
.with_config_and_dir(|config, dir| {
// Check that 2048 is the previous default.
assert_eq!(
config.store.slots_per_restore_point,
PREV_DEFAULT_SLOTS_PER_RESTORE_POINT
);
// Restart the BN with the same datadir and the new default SPRP. It should
// allow this.
CommandLineTest::new()
.flag("datadir", Some(&dir.path().display().to_string()))
.flag("zero-ports", None)
.run_with_no_datadir()
.with_config(|config| {
// The dumped config will have the new default 8192 value, but the fact that
// the BN started and ran (with the same datadir) means that the override
// was successful.
assert_eq!(
config.store.slots_per_restore_point,
DEFAULT_SLOTS_PER_RESTORE_POINT
);
});
})
}
#[test]
fn block_cache_size_flag() {
CommandLineTest::new()
.flag("block-cache-size", Some("4"))
.run_with_zero_port()
.with_config(|config| assert_eq!(config.store.block_cache_size, new_non_zero_usize(4)));
}
#[test]
fn state_cache_size_default() {
CommandLineTest::new()
.run_with_zero_port()
.with_config(|config| assert_eq!(config.store.state_cache_size, new_non_zero_usize(128)));
}
#[test]
fn state_cache_size_flag() {
CommandLineTest::new()
.flag("state-cache-size", Some("64"))
.run_with_zero_port()
.with_config(|config| assert_eq!(config.store.state_cache_size, new_non_zero_usize(64)));
}
#[test]
fn historic_state_cache_size_flag() {
CommandLineTest::new()
.flag("historic-state-cache-size", Some("4"))
.run_with_zero_port()
.with_config(|config| {
assert_eq!(
config.store.historic_state_cache_size,
new_non_zero_usize(4)
)
});
}
#[test]
fn historic_state_cache_size_default() {
use beacon_node::beacon_chain::store::config::DEFAULT_HISTORIC_STATE_CACHE_SIZE;
CommandLineTest::new()
.run_with_zero_port()
.with_config(|config| {
assert_eq!(
config.store.historic_state_cache_size,
DEFAULT_HISTORIC_STATE_CACHE_SIZE
);
});
}
#[test]
fn auto_compact_db_flag() {
CommandLineTest::new()
.flag("auto-compact-db", Some("false"))
.run_with_zero_port()
.with_config(|config| assert!(!config.store.compact_on_prune));
}
#[test]
fn compact_db_flag() {
CommandLineTest::new()
.flag("auto-compact-db", Some("false"))
.flag("compact-db", None)
.run_with_zero_port()
.with_config(|config| assert!(config.store.compact_on_init));
}
#[test]
fn prune_payloads_default() {
CommandLineTest::new()
.run_with_zero_port()
.with_config(|config| assert!(config.store.prune_payloads));
}
#[test]
fn prune_payloads_on_startup_false() {
CommandLineTest::new()
.flag("prune-payloads", Some("false"))
.run_with_zero_port()
.with_config(|config| assert!(!config.store.prune_payloads));
}
#[test]
fn prune_blobs_default() {
CommandLineTest::new()
.run_with_zero_port()
.with_config(|config| assert!(config.store.prune_blobs));
}
#[test]
fn prune_blobs_on_startup_false() {
CommandLineTest::new()
.flag("prune-blobs", Some("false"))
.run_with_zero_port()
.with_config(|config| assert!(!config.store.prune_blobs));
}
#[test]
fn epochs_per_blob_prune_default() {
CommandLineTest::new()
.run_with_zero_port()
.with_config(|config| assert!(config.store.epochs_per_blob_prune == 1));
}
#[test]
fn epochs_per_blob_prune_on_startup_five() {
CommandLineTest::new()
.flag("epochs-per-blob-prune", Some("5"))
.run_with_zero_port()
.with_config(|config| assert!(config.store.epochs_per_blob_prune == 5));
}
#[test]
fn blob_prune_margin_epochs_default() {
CommandLineTest::new()
.run_with_zero_port()
.with_config(|config| assert!(config.store.blob_prune_margin_epochs == 0));
}
#[test]
fn blob_prune_margin_epochs_on_startup_ten() {
CommandLineTest::new()
.flag("blob-prune-margin-epochs", Some("10"))
.run_with_zero_port()
.with_config(|config| assert!(config.store.blob_prune_margin_epochs == 10));
}
#[test]
fn reconstruct_historic_states_flag() {
CommandLineTest::new()
.flag("reconstruct-historic-states", None)
.run_with_zero_port()
.with_config(|config| assert!(config.chain.reconstruct_historic_states));
}
#[test]
fn no_reconstruct_historic_states_flag() {
CommandLineTest::new()
.run_with_zero_port()
.with_config(|config| assert!(!config.chain.reconstruct_historic_states));
}
#[test]
fn epochs_per_migration_default() {
CommandLineTest::new()
.run_with_zero_port()
.with_config(|config| {
assert_eq!(
config.chain.epochs_per_migration,
beacon_node::beacon_chain::migrate::DEFAULT_EPOCHS_PER_MIGRATION
)
});
}
#[test]
fn epochs_per_migration_override() {
CommandLineTest::new()
.flag("epochs-per-migration", Some("128"))
.run_with_zero_port()
.with_config(|config| assert_eq!(config.chain.epochs_per_migration, 128));
}
#[test]
fn malicious_withhold_count_flag() {
CommandLineTest::new()
.flag("malicious-withhold-count", Some("128"))
.run_with_zero_port()
.with_config(|config| assert_eq!(config.chain.malicious_withhold_count, 128));
}
// Tests for Slasher flags.
// Using `--slasher-max-db-size` to work around https://github.com/sigp/lighthouse/issues/2342
#[test]
fn slasher_flag() {
CommandLineTest::new()
.flag("slasher", None)
.flag("slasher-max-db-size", Some("1"))
.run_with_zero_port()
.with_config_and_dir(|config, dir| {
if let Some(slasher_config) = &config.slasher {
assert_eq!(
slasher_config.database_path,
dir.path().join("beacon").join("slasher_db")
)
} else {
panic!("Slasher config was parsed incorrectly");
}
});
}
#[test]
fn slasher_dir_flag() {
let dir = TempDir::new().expect("Unable to create temporary directory");
CommandLineTest::new()
.flag("slasher", None)
.flag("slasher-max-db-size", Some("1"))
.flag("slasher-dir", dir.path().as_os_str().to_str())
.run_with_zero_port()
.with_config(|config| {
if let Some(slasher_config) = &config.slasher {
assert_eq!(slasher_config.database_path, dir.path());
} else {
panic!("Slasher config was parsed incorrectly");
}
});
}
#[test]
fn slasher_update_period_flag() {
CommandLineTest::new()
.flag("slasher", None)
.flag("slasher-max-db-size", Some("1"))
.flag("slasher-update-period", Some("100"))
.run_with_zero_port()
.with_config(|config| {
if let Some(slasher_config) = &config.slasher {
assert_eq!(slasher_config.update_period, 100);
} else {
panic!("Slasher config was parsed incorrectly");
}
});
}
#[test]
fn slasher_slot_offset_flag() {
CommandLineTest::new()
.flag("slasher", None)
.flag("slasher-max-db-size", Some("1"))
.flag("slasher-slot-offset", Some("11.25"))
.run_with_zero_port()
.with_config(|config| {
let slasher_config = config.slasher.as_ref().unwrap();
assert_eq!(slasher_config.slot_offset, 11.25);
});
}
#[test]
#[should_panic]
fn slasher_slot_offset_nan_flag() {
CommandLineTest::new()
.flag("slasher", None)
.flag("slasher-max-db-size", Some("1"))
.flag("slasher-slot-offset", Some("NaN"))
.run_with_zero_port();
}
#[test]
fn slasher_history_length_flag() {
CommandLineTest::new()
.flag("slasher", None)
.flag("slasher-max-db-size", Some("1"))
.flag("slasher-history-length", Some("2048"))
.run_with_zero_port()
.with_config(|config| {
if let Some(slasher_config) = &config.slasher {
assert_eq!(slasher_config.history_length, 2048);
} else {
panic!("Slasher config was parsed incorrectly");
}
});
}
#[test]
fn slasher_max_db_size_flag() {
CommandLineTest::new()
.flag("slasher", None)
.flag("slasher-max-db-size", Some("2"))
.run_with_zero_port()
.with_config(|config| {
let slasher_config = config
.slasher
.as_ref()
.expect("Unable to parse Slasher config");
assert_eq!(slasher_config.max_db_size_mbs, 2048);
});
}
#[test]
fn slasher_attestation_cache_size_flag() {
CommandLineTest::new()
.flag("slasher", None)
.flag("slasher-max-db-size", Some("1"))
.flag("slasher-att-cache-size", Some("10000"))
.run_with_zero_port()
.with_config(|config| {
let slasher_config = config
.slasher
.as_ref()
.expect("Unable to parse Slasher config");
assert_eq!(
slasher_config.attestation_root_cache_size,
new_non_zero_usize(10000)
);
});
}
#[test]
fn slasher_chunk_size_flag() {
CommandLineTest::new()
.flag("slasher", None)
.flag("slasher-max-db-size", Some("1"))
.flag("slasher-chunk-size", Some("32"))
.run_with_zero_port()
.with_config(|config| {
let slasher_config = config
.slasher
.as_ref()
.expect("Unable to parse Slasher config");
assert_eq!(slasher_config.chunk_size, 32);
});
}
#[test]
fn slasher_validator_chunk_size_flag() {
CommandLineTest::new()
.flag("slasher", None)
.flag("slasher-max-db-size", Some("1"))
.flag("slasher-validator-chunk-size", Some("512"))
.run_with_zero_port()
.with_config(|config| {
let slasher_config = config
.slasher
.as_ref()
.expect("Unable to parse Slasher config");
assert_eq!(slasher_config.validator_chunk_size, 512);
});
}
#[test]
fn slasher_broadcast_flag_no_args() {
CommandLineTest::new()
.flag("slasher", None)
.flag("slasher-max-db-size", Some("1"))
.run_with_zero_port()
.with_config(|config| {
let slasher_config = config
.slasher
.as_ref()
.expect("Unable to parse Slasher config");
assert!(slasher_config.broadcast);
});
}
#[test]
fn slasher_broadcast_flag_no_default() {
CommandLineTest::new()
.flag("slasher", None)
.flag("slasher-max-db-size", Some("1"))
.run_with_zero_port()
.with_config(|config| {
let slasher_config = config
.slasher
.as_ref()
.expect("Unable to parse Slasher config");
assert!(slasher_config.broadcast);
});
}
#[test]
fn slasher_broadcast_flag_no_argument() {
CommandLineTest::new()
.flag("slasher", None)
.flag("slasher-max-db-size", Some("1"))
.flag("slasher-broadcast", None)
.run_with_zero_port()
.with_config(|config| {
let slasher_config = config
.slasher
.as_ref()
.expect("Unable to parse Slasher config");
assert!(slasher_config.broadcast);
});
}
#[test]
fn slasher_broadcast_flag_true() {
CommandLineTest::new()
.flag("slasher", None)
.flag("slasher-max-db-size", Some("1"))
.flag("slasher-broadcast", Some("true"))
.run_with_zero_port()
.with_config(|config| {
let slasher_config = config
.slasher
.as_ref()
.expect("Unable to parse Slasher config");
assert!(slasher_config.broadcast);
});
}
#[test]
fn slasher_broadcast_flag_false() {
CommandLineTest::new()
.flag("slasher", None)
.flag("slasher-max-db-size", Some("1"))
.flag("slasher-broadcast", Some("false"))
.run_with_zero_port()
.with_config(|config| {
let slasher_config = config
.slasher
.as_ref()
.expect("Unable to parse Slasher config");
assert!(!slasher_config.broadcast);
});
}
#[cfg(all(feature = "slasher-lmdb"))]
#[test]
fn slasher_backend_override_to_default() {
// Hard to test this flag because all but one backend is disabled by default and the backend
// called "disabled" results in a panic.
CommandLineTest::new()
.flag("slasher", None)
.flag("slasher-max-db-size", Some("1"))
.flag("slasher-backend", Some("lmdb"))
.run_with_zero_port()
.with_config(|config| {
let slasher_config = config.slasher.as_ref().unwrap();
assert_eq!(slasher_config.backend, slasher::DatabaseBackend::Lmdb);
});
}
#[test]
fn malloc_tuning_flag() {
CommandLineTest::new()
.flag("disable-malloc-tuning", None)
.run_with_zero_port()
.with_config(|config| {
assert!(!config.http_metrics.allocator_metrics_enabled);
});
}
#[test]
#[should_panic]
fn ensure_panic_on_failed_launch() {
CommandLineTest::new()
.flag("slasher", None)
.flag("slasher-chunk-size", Some("10"))
.set_allow_insecure_genesis_sync()
.set_zero_port()
.run_with_immediate_shutdown(false)
.with_config(|config| {
let slasher_config = config
.slasher
.as_ref()
.expect("Unable to parse Slasher config");
assert_eq!(slasher_config.chunk_size, 10);
});
}
#[test]
fn enable_proposer_re_orgs_default() {
CommandLineTest::new()
.run_with_zero_port()
.with_config(|config| {
assert_eq!(
config.chain.re_org_head_threshold,
Some(DEFAULT_RE_ORG_HEAD_THRESHOLD)
);
assert_eq!(
config.chain.re_org_max_epochs_since_finalization,
DEFAULT_RE_ORG_MAX_EPOCHS_SINCE_FINALIZATION,
);
assert_eq!(
config.chain.re_org_cutoff(12),
Duration::from_secs(12) / DEFAULT_RE_ORG_CUTOFF_DENOMINATOR
);
});
}
#[test]
fn disable_proposer_re_orgs() {
CommandLineTest::new()
.flag("disable-proposer-reorgs", None)
.run_with_zero_port()
.with_config(|config| {
assert_eq!(config.chain.re_org_head_threshold, None);
assert_eq!(config.chain.re_org_parent_threshold, None)
});
}
#[test]
fn proposer_re_org_parent_threshold() {
CommandLineTest::new()
.flag("proposer-reorg-parent-threshold", Some("90"))
.run_with_zero_port()
.with_config(|config| assert_eq!(config.chain.re_org_parent_threshold.unwrap().0, 90));
}
#[test]
fn proposer_re_org_head_threshold() {
CommandLineTest::new()
.flag("proposer-reorg-threshold", Some("90"))
.run_with_zero_port()
.with_config(|config| assert_eq!(config.chain.re_org_head_threshold.unwrap().0, 90));
}
#[test]
fn proposer_re_org_max_epochs_since_finalization() {
CommandLineTest::new()
.flag("proposer-reorg-epochs-since-finalization", Some("8"))
.run_with_zero_port()
.with_config(|config| {
assert_eq!(
config.chain.re_org_max_epochs_since_finalization.as_u64(),
8
)
});
}
#[test]
fn proposer_re_org_cutoff() {
CommandLineTest::new()
.flag("proposer-reorg-cutoff", Some("500"))
.run_with_zero_port()
.with_config(|config| {
assert_eq!(config.chain.re_org_cutoff(12), Duration::from_millis(500))
});
}
#[test]
fn proposer_re_org_disallowed_offsets_default() {
CommandLineTest::new()
.run_with_zero_port()
.with_config(|config| {
assert_eq!(
config.chain.re_org_disallowed_offsets,
DisallowedReOrgOffsets::new::<MainnetEthSpec>(vec![0]).unwrap()
)
});
}
#[test]
fn proposer_re_org_disallowed_offsets_override() {
CommandLineTest::new()
.flag("proposer-reorg-disallowed-offsets", Some("1,2,3"))
.run_with_zero_port()
.with_config(|config| {
assert_eq!(
config.chain.re_org_disallowed_offsets,
DisallowedReOrgOffsets::new::<MainnetEthSpec>(vec![1, 2, 3]).unwrap()
)
});
}
#[test]
#[should_panic]
fn proposer_re_org_disallowed_offsets_invalid() {
CommandLineTest::new()
.flag("proposer-reorg-disallowed-offsets", Some("32,33,34"))
.run_with_zero_port();
}
#[test]
fn monitoring_endpoint() {
CommandLineTest::new()
.flag("monitoring-endpoint", Some("http://example:8000"))
.flag("monitoring-endpoint-period", Some("30"))
.run_with_zero_port()
.with_config(|config| {
let api_conf = config.monitoring_api.as_ref().unwrap();
assert_eq!(api_conf.monitoring_endpoint.as_str(), "http://example:8000");
assert_eq!(api_conf.update_period_secs, Some(30));
});
}
// Tests for Logger flags.
#[test]
fn default_log_color_flag() {
CommandLineTest::new()
.run_with_zero_port()
.with_config(|config| {
assert!(!config.logger_config.log_color);
});
}
#[test]
fn enabled_log_color_flag() {
CommandLineTest::new()
.flag("log-color", None)
.run_with_zero_port()
.with_config(|config| {
assert!(config.logger_config.log_color);
});
}
#[test]
fn default_disable_log_timestamp_flag() {
CommandLineTest::new()
.run_with_zero_port()
.with_config(|config| {
assert!(!config.logger_config.disable_log_timestamp);
});
}
#[test]
fn enabled_disable_log_timestamp_flag() {
CommandLineTest::new()
.flag("disable-log-timestamp", None)
.run_with_zero_port()
.with_config(|config| {
assert!(config.logger_config.disable_log_timestamp);
});
}
#[test]
fn logfile_restricted_perms_default() {
CommandLineTest::new()
.run_with_zero_port()
.with_config(|config| {
assert!(config.logger_config.is_restricted);
});
}
#[test]
fn logfile_no_restricted_perms_flag() {
CommandLineTest::new()
.flag("logfile-no-restricted-perms", None)
.run_with_zero_port()
.with_config(|config| {
assert!(config.logger_config.is_restricted == false);
});
}
#[test]
fn logfile_format_default() {
CommandLineTest::new()
.run_with_zero_port()
.with_config(|config| assert_eq!(config.logger_config.logfile_format, None));
}
#[test]
fn logfile_format_flag() {
CommandLineTest::new()
.flag("logfile-format", Some("JSON"))
.run_with_zero_port()
.with_config(|config| {
assert_eq!(
config.logger_config.logfile_format,
Some("JSON".to_string())
)
});
}
#[test]
fn sync_eth1_chain_default() {
CommandLineTest::new()
.run_with_zero_port()
.with_config(|config| assert_eq!(config.sync_eth1_chain, false));
}
#[test]
fn sync_eth1_chain_execution_endpoints_flag() {
let dir = TempDir::new().expect("Unable to create temporary directory");
CommandLineTest::new()
.flag("execution-endpoints", Some("http://localhost:8551/"))
.flag(
"execution-jwt",
dir.path().join("jwt-file").as_os_str().to_str(),
)
.run_with_zero_port()
.with_config(|config| assert_eq!(config.sync_eth1_chain, true));
}
#[test]
fn sync_eth1_chain_disable_deposit_contract_sync_flag() {
let dir = TempDir::new().expect("Unable to create temporary directory");
CommandLineTest::new()
.flag("disable-deposit-contract-sync", None)
.flag("execution-endpoints", Some("http://localhost:8551/"))
.flag(
"execution-jwt",
dir.path().join("jwt-file").as_os_str().to_str(),
)
.run_with_zero_port()
.with_config(|config| assert_eq!(config.sync_eth1_chain, false));
}
#[test]
fn light_client_server_default() {
CommandLineTest::new()
.run_with_zero_port()
.with_config(|config| {
assert_eq!(config.network.enable_light_client_server, false);
assert_eq!(config.chain.enable_light_client_server, false);
assert_eq!(config.http_api.enable_light_client_server, false);
});
}
#[test]
fn light_client_server_enabled() {
CommandLineTest::new()
.flag("light-client-server", None)
.run_with_zero_port()
.with_config(|config| {
assert_eq!(config.network.enable_light_client_server, true);
assert_eq!(config.chain.enable_light_client_server, true);
});
}
#[test]
fn light_client_http_server_enabled() {
CommandLineTest::new()
.flag("http", None)
.flag("light-client-server", None)
.run_with_zero_port()
.with_config(|config| {
assert_eq!(config.http_api.enable_light_client_server, true);
});
}
#[test]
fn gui_flag() {
CommandLineTest::new()
.flag("gui", None)
.run_with_zero_port()
.with_config(|config| {
assert!(config.http_api.enabled);
assert!(config.validator_monitor.auto_register);
});
}
#[test]
fn multiple_http_enabled_flags() {
CommandLineTest::new()
.flag("gui", None)
.flag("http", None)
.flag("staking", None)
.run_with_zero_port()
.with_config(|config| {
assert!(config.http_api.enabled);
});
}
#[test]
fn optimistic_finalized_sync_default() {
CommandLineTest::new()
.run_with_zero_port()
.with_config(|config| {
assert!(config.chain.optimistic_finalized_sync);
});
}
#[test]
fn disable_optimistic_finalized_sync() {
CommandLineTest::new()
.flag("disable-optimistic-finalized-sync", None)
.run_with_zero_port()
.with_config(|config| {
assert!(!config.chain.optimistic_finalized_sync);
});
}
#[test]
fn invalid_gossip_verified_blocks_path_default() {
CommandLineTest::new()
.run_with_zero_port()
.with_config(|config| assert_eq!(config.network.invalid_block_storage, None));
}
#[test]
fn invalid_gossip_verified_blocks_path() {
let path = "/home/karlm/naughty-blocks";
CommandLineTest::new()
.flag("invalid-gossip-verified-blocks-path", Some(path))
.run_with_zero_port()
.with_config(|config| {
assert_eq!(
config.network.invalid_block_storage,
Some(PathBuf::from(path))
)
});
}
#[test]
fn progressive_balances_checked() {
// Flag is deprecated but supplying it should not crash until we remove it completely.
CommandLineTest::new()
.flag("progressive-balances", Some("checked"))
.run_with_zero_port();
}
#[test]
fn beacon_processor() {
CommandLineTest::new()
.run_with_zero_port()
.with_config(|config| assert_eq!(config.beacon_processor, <_>::default()));
CommandLineTest::new()
.flag("beacon-processor-max-workers", Some("1"))
.flag("beacon-processor-work-queue-len", Some("2"))
.flag("beacon-processor-reprocess-queue-len", Some("3"))
.flag("beacon-processor-attestation-batch-size", Some("4"))
.flag("beacon-processor-aggregate-batch-size", Some("5"))
.flag("disable-backfill-rate-limiting", None)
.run_with_zero_port()
.with_config(|config| {
assert_eq!(
config.beacon_processor,
BeaconProcessorConfig {
max_workers: 1,
max_work_event_queue_len: 2,
max_scheduled_work_queue_len: 3,
max_gossip_attestation_batch_size: 4,
max_gossip_aggregate_batch_size: 5,
enable_backfill_rate_limiting: false
}
)
});
}
#[test]
#[should_panic]
fn beacon_processor_zero_workers() {
CommandLineTest::new()
.flag("beacon-processor-max-workers", Some("0"))
.run_with_zero_port();
}
#[test]
fn http_sse_capacity_multiplier_default() {
CommandLineTest::new()
.run_with_zero_port()
.with_config(|config| assert_eq!(config.http_api.sse_capacity_multiplier, 1));
}
#[test]
fn http_sse_capacity_multiplier_override() {
CommandLineTest::new()
.flag("http", None)
.flag("http-sse-capacity-multiplier", Some("10"))
.run_with_zero_port()
.with_config(|config| assert_eq!(config.http_api.sse_capacity_multiplier, 10));
}
#[test]
fn http_duplicate_block_status_default() {
CommandLineTest::new()
.run_with_zero_port()
.with_config(|config| {
assert_eq!(config.http_api.duplicate_block_status_code.as_u16(), 202)
});
}
#[test]
fn http_duplicate_block_status_override() {
CommandLineTest::new()
.flag("http", None)
.flag("http-duplicate-block-status", Some("301"))
.run_with_zero_port()
.with_config(|config| {
assert_eq!(config.http_api.duplicate_block_status_code.as_u16(), 301)
});
}
#[test]
fn genesis_state_url_default() {
CommandLineTest::new()
.run_with_zero_port()
.with_config(|config| {
assert_eq!(config.genesis_state_url, None);
assert_eq!(config.genesis_state_url_timeout, Duration::from_secs(180));
});
}
#[test]
fn genesis_state_url_value() {
CommandLineTest::new()
.flag("genesis-state-url", Some("http://genesis.com"))
.flag("genesis-state-url-timeout", Some("42"))
.run_with_zero_port()
.with_config(|config| {
assert_eq!(
config.genesis_state_url.as_deref(),
Some("http://genesis.com")
);
assert_eq!(config.genesis_state_url_timeout, Duration::from_secs(42));
});
}