Merge branch 'capella' of https://github.com/sigp/lighthouse into eip4844
# Conflicts: # beacon_node/beacon_chain/src/beacon_chain.rs # beacon_node/beacon_chain/src/block_verification.rs # beacon_node/beacon_chain/src/test_utils.rs # beacon_node/execution_layer/src/engine_api.rs # beacon_node/execution_layer/src/engine_api/http.rs # beacon_node/execution_layer/src/lib.rs # beacon_node/execution_layer/src/test_utils/handle_rpc.rs # beacon_node/http_api/src/lib.rs # beacon_node/http_api/tests/fork_tests.rs # beacon_node/network/src/beacon_processor/mod.rs # beacon_node/network/src/beacon_processor/work_reprocessing_queue.rs # beacon_node/network/src/beacon_processor/worker/sync_methods.rs # beacon_node/operation_pool/src/bls_to_execution_changes.rs # beacon_node/operation_pool/src/lib.rs # beacon_node/operation_pool/src/persistence.rs # consensus/serde_utils/src/u256_hex_be_opt.rs # testing/antithesis/Dockerfile.libvoidstar
This commit is contained in:
@@ -36,6 +36,7 @@ tree_hash = "0.4.1"
|
||||
sysinfo = "0.26.5"
|
||||
system_health = { path = "../../common/system_health" }
|
||||
directory = { path = "../../common/directory" }
|
||||
operation_pool = { path = "../operation_pool" }
|
||||
|
||||
[dev-dependencies]
|
||||
store = { path = "../store" }
|
||||
|
||||
@@ -35,6 +35,7 @@ use eth2::types::{
|
||||
use lighthouse_network::{types::SyncState, EnrExt, NetworkGlobals, PeerId, PubsubMessage};
|
||||
use lighthouse_version::version_with_platform;
|
||||
use network::{NetworkMessage, NetworkSenders, ValidatorSubscriptionMessage};
|
||||
use operation_pool::ReceivedPreCapella;
|
||||
use parking_lot::RwLock;
|
||||
use serde::{Deserialize, Serialize};
|
||||
use slog::{crit, debug, error, info, warn, Logger};
|
||||
@@ -1690,8 +1691,12 @@ pub fn serve<T: BeaconChainTypes>(
|
||||
.to_execution_address;
|
||||
|
||||
// New to P2P *and* op pool, gossip immediately if post-Capella.
|
||||
let publish = chain.current_slot_is_post_capella().unwrap_or(false);
|
||||
if publish {
|
||||
let received_pre_capella = if chain.current_slot_is_post_capella().unwrap_or(false) {
|
||||
ReceivedPreCapella::No
|
||||
} else {
|
||||
ReceivedPreCapella::Yes
|
||||
};
|
||||
if matches!(received_pre_capella, ReceivedPreCapella::No) {
|
||||
publish_pubsub_message(
|
||||
&network_tx,
|
||||
PubsubMessage::BlsToExecutionChange(Box::new(
|
||||
@@ -1702,14 +1707,14 @@ pub fn serve<T: BeaconChainTypes>(
|
||||
|
||||
// Import to op pool (may return `false` if there's a race).
|
||||
let imported =
|
||||
chain.import_bls_to_execution_change(verified_address_change);
|
||||
chain.import_bls_to_execution_change(verified_address_change, received_pre_capella);
|
||||
|
||||
info!(
|
||||
log,
|
||||
"Processed BLS to execution change";
|
||||
"validator_index" => validator_index,
|
||||
"address" => ?address,
|
||||
"published" => publish,
|
||||
"published" => matches!(received_pre_capella, ReceivedPreCapella::No),
|
||||
"imported" => imported,
|
||||
);
|
||||
}
|
||||
@@ -3566,6 +3571,7 @@ pub fn serve<T: BeaconChainTypes>(
|
||||
.or(post_beacon_pool_sync_committees.boxed())
|
||||
.or(post_beacon_rewards_sync_committee.boxed())
|
||||
.or(post_beacon_pool_bls_to_execution_changes.boxed())
|
||||
.or(post_beacon_rewards_sync_committee.boxed())
|
||||
.or(post_validator_duties_attester.boxed())
|
||||
.or(post_validator_duties_sync.boxed())
|
||||
.or(post_validator_aggregate_and_proofs.boxed())
|
||||
|
||||
@@ -6,6 +6,7 @@ use beacon_chain::{
|
||||
};
|
||||
use eth2::types::{IndexedErrorMessage, StateId, SyncSubcommittee};
|
||||
use genesis::{bls_withdrawal_credentials, interop_genesis_state_with_withdrawal_credentials};
|
||||
use std::collections::HashSet;
|
||||
use types::{
|
||||
test_utils::{generate_deterministic_keypair, generate_deterministic_keypairs},
|
||||
Address, ChainSpec, Epoch, EthSpec, Hash256, MinimalEthSpec, Slot,
|
||||
@@ -438,6 +439,8 @@ async fn bls_to_execution_changes_update_all_around_capella_fork() {
|
||||
.await
|
||||
.unwrap();
|
||||
|
||||
let expected_received_pre_capella_messages = valid_address_changes[..num_pre_capella].to_vec();
|
||||
|
||||
// Conflicting changes for the same validators should all fail.
|
||||
let error = client
|
||||
.post_beacon_pool_bls_to_execution_changes(&conflicting_address_changes[..num_pre_capella])
|
||||
@@ -464,6 +467,20 @@ async fn bls_to_execution_changes_update_all_around_capella_fork() {
|
||||
harness.extend_to_slot(capella_slot - 1).await;
|
||||
assert_eq!(harness.head_slot(), capella_slot - 1);
|
||||
|
||||
assert_eq!(
|
||||
harness
|
||||
.chain
|
||||
.op_pool
|
||||
.get_bls_to_execution_changes_received_pre_capella(
|
||||
&harness.chain.head_snapshot().beacon_state,
|
||||
&spec,
|
||||
)
|
||||
.into_iter()
|
||||
.collect::<HashSet<_>>(),
|
||||
HashSet::from_iter(expected_received_pre_capella_messages.into_iter()),
|
||||
"all pre-capella messages should be queued for capella broadcast"
|
||||
);
|
||||
|
||||
// Add Capella blocks which should be full of BLS to execution changes.
|
||||
for i in 0..validator_count / max_bls_to_execution_changes {
|
||||
let head_block_root = harness.extend_slots(1).await;
|
||||
|
||||
@@ -11,9 +11,11 @@ use eth2::{
|
||||
types::{BlockId as CoreBlockId, StateId as CoreStateId, *},
|
||||
BeaconNodeHttpClient, Error, StatusCode, Timeouts,
|
||||
};
|
||||
use execution_layer::test_utils::Operation;
|
||||
use execution_layer::test_utils::TestingBuilder;
|
||||
use execution_layer::test_utils::DEFAULT_BUILDER_THRESHOLD_WEI;
|
||||
use execution_layer::test_utils::{
|
||||
Operation, DEFAULT_BUILDER_PAYLOAD_VALUE_WEI, DEFAULT_MOCK_EL_PAYLOAD_VALUE_WEI,
|
||||
};
|
||||
use futures::stream::{Stream, StreamExt};
|
||||
use futures::FutureExt;
|
||||
use http_api::{BlockId, StateId};
|
||||
@@ -72,38 +74,53 @@ struct ApiTester {
|
||||
mock_builder: Option<Arc<TestingBuilder<E>>>,
|
||||
}
|
||||
|
||||
struct ApiTesterConfig {
|
||||
spec: ChainSpec,
|
||||
builder_threshold: Option<u128>,
|
||||
}
|
||||
|
||||
impl Default for ApiTesterConfig {
|
||||
fn default() -> Self {
|
||||
let mut spec = E::default_spec();
|
||||
spec.shard_committee_period = 2;
|
||||
Self {
|
||||
spec,
|
||||
builder_threshold: None,
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
impl ApiTester {
|
||||
pub async fn new() -> Self {
|
||||
// This allows for testing voluntary exits without building out a massive chain.
|
||||
let mut spec = E::default_spec();
|
||||
spec.shard_committee_period = 2;
|
||||
Self::new_from_spec(spec).await
|
||||
Self::new_from_config(ApiTesterConfig::default()).await
|
||||
}
|
||||
|
||||
pub async fn new_with_hard_forks(altair: bool, bellatrix: bool) -> Self {
|
||||
let mut spec = E::default_spec();
|
||||
spec.shard_committee_period = 2;
|
||||
let mut config = ApiTesterConfig::default();
|
||||
// Set whether the chain has undergone each hard fork.
|
||||
if altair {
|
||||
spec.altair_fork_epoch = Some(Epoch::new(0));
|
||||
config.spec.altair_fork_epoch = Some(Epoch::new(0));
|
||||
}
|
||||
if bellatrix {
|
||||
spec.bellatrix_fork_epoch = Some(Epoch::new(0));
|
||||
config.spec.bellatrix_fork_epoch = Some(Epoch::new(0));
|
||||
}
|
||||
Self::new_from_spec(spec).await
|
||||
Self::new_from_config(config).await
|
||||
}
|
||||
|
||||
pub async fn new_from_spec(spec: ChainSpec) -> Self {
|
||||
pub async fn new_from_config(config: ApiTesterConfig) -> Self {
|
||||
// Get a random unused port
|
||||
let spec = config.spec;
|
||||
let port = unused_port::unused_tcp_port().unwrap();
|
||||
let beacon_url = SensitiveUrl::parse(format!("http://127.0.0.1:{port}").as_str()).unwrap();
|
||||
|
||||
let harness = Arc::new(
|
||||
BeaconChainHarness::builder(MainnetEthSpec)
|
||||
.spec(spec.clone())
|
||||
.logger(logging::test_logger())
|
||||
.deterministic_keypairs(VALIDATOR_COUNT)
|
||||
.fresh_ephemeral_store()
|
||||
.mock_execution_layer_with_builder(beacon_url.clone())
|
||||
.mock_execution_layer_with_builder(beacon_url.clone(), config.builder_threshold)
|
||||
.build(),
|
||||
);
|
||||
|
||||
@@ -358,6 +375,28 @@ impl ApiTester {
|
||||
tester
|
||||
}
|
||||
|
||||
pub async fn new_mev_tester_no_builder_threshold() -> Self {
|
||||
let mut config = ApiTesterConfig {
|
||||
builder_threshold: Some(0),
|
||||
spec: E::default_spec(),
|
||||
};
|
||||
config.spec.altair_fork_epoch = Some(Epoch::new(0));
|
||||
config.spec.bellatrix_fork_epoch = Some(Epoch::new(0));
|
||||
let tester = Self::new_from_config(config)
|
||||
.await
|
||||
.test_post_validator_register_validator()
|
||||
.await;
|
||||
tester
|
||||
.mock_builder
|
||||
.as_ref()
|
||||
.unwrap()
|
||||
.builder
|
||||
.add_operation(Operation::Value(Uint256::from(
|
||||
DEFAULT_BUILDER_PAYLOAD_VALUE_WEI,
|
||||
)));
|
||||
tester
|
||||
}
|
||||
|
||||
fn skip_slots(self, count: u64) -> Self {
|
||||
for _ in 0..count {
|
||||
self.chain
|
||||
@@ -3278,6 +3317,117 @@ impl ApiTester {
|
||||
self
|
||||
}
|
||||
|
||||
pub async fn test_builder_payload_chosen_when_more_profitable(self) -> Self {
|
||||
// Mutate value.
|
||||
self.mock_builder
|
||||
.as_ref()
|
||||
.unwrap()
|
||||
.builder
|
||||
.add_operation(Operation::Value(Uint256::from(
|
||||
DEFAULT_MOCK_EL_PAYLOAD_VALUE_WEI + 1,
|
||||
)));
|
||||
|
||||
let slot = self.chain.slot().unwrap();
|
||||
let epoch = self.chain.epoch().unwrap();
|
||||
|
||||
let (_, randao_reveal) = self.get_test_randao(slot, epoch).await;
|
||||
|
||||
let payload: BlindedPayload<E> = self
|
||||
.client
|
||||
.get_validator_blinded_blocks::<E, BlindedPayload<E>>(slot, &randao_reveal, None)
|
||||
.await
|
||||
.unwrap()
|
||||
.data
|
||||
.body()
|
||||
.execution_payload()
|
||||
.unwrap()
|
||||
.into();
|
||||
|
||||
// The builder's payload should've been chosen, so this cache should not be populated
|
||||
assert!(self
|
||||
.chain
|
||||
.execution_layer
|
||||
.as_ref()
|
||||
.unwrap()
|
||||
.get_payload_by_root(&payload.tree_hash_root())
|
||||
.is_none());
|
||||
self
|
||||
}
|
||||
|
||||
pub async fn test_local_payload_chosen_when_equally_profitable(self) -> Self {
|
||||
// Mutate value.
|
||||
self.mock_builder
|
||||
.as_ref()
|
||||
.unwrap()
|
||||
.builder
|
||||
.add_operation(Operation::Value(Uint256::from(
|
||||
DEFAULT_MOCK_EL_PAYLOAD_VALUE_WEI,
|
||||
)));
|
||||
|
||||
let slot = self.chain.slot().unwrap();
|
||||
let epoch = self.chain.epoch().unwrap();
|
||||
|
||||
let (_, randao_reveal) = self.get_test_randao(slot, epoch).await;
|
||||
|
||||
let payload: BlindedPayload<E> = self
|
||||
.client
|
||||
.get_validator_blinded_blocks::<E, BlindedPayload<E>>(slot, &randao_reveal, None)
|
||||
.await
|
||||
.unwrap()
|
||||
.data
|
||||
.body()
|
||||
.execution_payload()
|
||||
.unwrap()
|
||||
.into();
|
||||
|
||||
// The local payload should've been chosen, so this cache should be populated
|
||||
assert!(self
|
||||
.chain
|
||||
.execution_layer
|
||||
.as_ref()
|
||||
.unwrap()
|
||||
.get_payload_by_root(&payload.tree_hash_root())
|
||||
.is_some());
|
||||
self
|
||||
}
|
||||
|
||||
pub async fn test_local_payload_chosen_when_more_profitable(self) -> Self {
|
||||
// Mutate value.
|
||||
self.mock_builder
|
||||
.as_ref()
|
||||
.unwrap()
|
||||
.builder
|
||||
.add_operation(Operation::Value(Uint256::from(
|
||||
DEFAULT_MOCK_EL_PAYLOAD_VALUE_WEI - 1,
|
||||
)));
|
||||
|
||||
let slot = self.chain.slot().unwrap();
|
||||
let epoch = self.chain.epoch().unwrap();
|
||||
|
||||
let (_, randao_reveal) = self.get_test_randao(slot, epoch).await;
|
||||
|
||||
let payload: BlindedPayload<E> = self
|
||||
.client
|
||||
.get_validator_blinded_blocks::<E, BlindedPayload<E>>(slot, &randao_reveal, None)
|
||||
.await
|
||||
.unwrap()
|
||||
.data
|
||||
.body()
|
||||
.execution_payload()
|
||||
.unwrap()
|
||||
.into();
|
||||
|
||||
// The local payload should've been chosen, so this cache should be populated
|
||||
assert!(self
|
||||
.chain
|
||||
.execution_layer
|
||||
.as_ref()
|
||||
.unwrap()
|
||||
.get_payload_by_root(&payload.tree_hash_root())
|
||||
.is_some());
|
||||
self
|
||||
}
|
||||
|
||||
#[cfg(target_os = "linux")]
|
||||
pub async fn test_get_lighthouse_health(self) -> Self {
|
||||
self.client.get_lighthouse_health().await.unwrap();
|
||||
@@ -3747,9 +3897,9 @@ async fn get_events() {
|
||||
|
||||
#[tokio::test(flavor = "multi_thread", worker_threads = 2)]
|
||||
async fn get_events_altair() {
|
||||
let mut spec = E::default_spec();
|
||||
spec.altair_fork_epoch = Some(Epoch::new(0));
|
||||
ApiTester::new_from_spec(spec)
|
||||
let mut config = ApiTesterConfig::default();
|
||||
config.spec.altair_fork_epoch = Some(Epoch::new(0));
|
||||
ApiTester::new_from_config(config)
|
||||
.await
|
||||
.test_get_events_altair()
|
||||
.await;
|
||||
@@ -4262,6 +4412,18 @@ async fn builder_inadequate_builder_threshold() {
|
||||
.await;
|
||||
}
|
||||
|
||||
#[tokio::test(flavor = "multi_thread", worker_threads = 2)]
|
||||
async fn builder_payload_chosen_by_profit() {
|
||||
ApiTester::new_mev_tester_no_builder_threshold()
|
||||
.await
|
||||
.test_builder_payload_chosen_when_more_profitable()
|
||||
.await
|
||||
.test_local_payload_chosen_when_equally_profitable()
|
||||
.await
|
||||
.test_local_payload_chosen_when_more_profitable()
|
||||
.await;
|
||||
}
|
||||
|
||||
#[tokio::test(flavor = "multi_thread", worker_threads = 2)]
|
||||
async fn lighthouse_endpoints() {
|
||||
ApiTester::new()
|
||||
|
||||
Reference in New Issue
Block a user