Skip to content

Commit 201219d

Browse files
committed
Merge branch 'develop' into pectra-devnet4
2 parents c664f18 + b5b2c95 commit 201219d

File tree

6 files changed

+255
-76
lines changed

6 files changed

+255
-76
lines changed

eth1_api/src/eth1_api.rs

+132
Original file line numberDiff line numberDiff line change
@@ -561,6 +561,7 @@ struct RawForkChoiceUpdatedResponse {
561561
}
562562

563563
#[derive(Debug, Error)]
564+
#[cfg_attr(test, derive(PartialEq, Eq))]
564565
enum Error {
565566
#[error("all Eth1 RPC endpoints exhausted")]
566567
EndpointsExhausted,
@@ -589,6 +590,137 @@ mod tests {
589590

590591
use super::*;
591592

593+
#[tokio::test]
594+
async fn test_eth1_endpoints_error_with_no_endpoints() -> Result<()> {
595+
let config = Arc::new(Config::mainnet());
596+
let auth = Arc::default();
597+
598+
let eth1_api = Arc::new(Eth1Api::new(
599+
config,
600+
Client::new(),
601+
auth,
602+
vec![],
603+
None,
604+
None,
605+
));
606+
607+
assert!(eth1_api.el_offline().await);
608+
assert_eq!(eth1_api.current_endpoint().await, None);
609+
610+
assert_eq!(
611+
eth1_api
612+
.current_head_number()
613+
.await
614+
.expect_err("Eth1Api with no endpoints should return an error")
615+
.downcast::<Error>()?,
616+
Error::NoEndpointsProvided,
617+
);
618+
619+
Ok(())
620+
}
621+
622+
#[tokio::test]
623+
async fn test_eth1_endpoints_error_with_single_endpoint() -> Result<()> {
624+
let server = MockServer::start();
625+
626+
server.mock(|when, then| {
627+
when.method(Method::POST).path("/");
628+
then.status(500).body("{}");
629+
});
630+
631+
let config = Arc::new(Config::mainnet());
632+
let auth = Arc::default();
633+
let server_url = server.url("/").parse()?;
634+
635+
let eth1_api = Arc::new(Eth1Api::new(
636+
config,
637+
Client::new(),
638+
auth,
639+
vec![server_url],
640+
None,
641+
None,
642+
));
643+
644+
assert!(!eth1_api.el_offline().await);
645+
assert_eq!(
646+
eth1_api
647+
.current_head_number()
648+
.await
649+
.expect_err("500 response should be a an error")
650+
.downcast::<Error>()?,
651+
Error::EndpointsExhausted,
652+
);
653+
654+
// Despite the endpoint returning an error, it remains the only available option
655+
assert!(eth1_api.current_endpoint().await.is_some());
656+
assert!(eth1_api.el_offline().await);
657+
658+
Ok(())
659+
}
660+
661+
#[tokio::test]
662+
async fn test_eth1_endpoints_error_with_multiple_endpoints() -> Result<()> {
663+
let server = MockServer::start();
664+
665+
server.mock(|when, then| {
666+
when.method(Method::POST).path("/");
667+
then.status(500).body("{}");
668+
});
669+
670+
let body = json!({
671+
"jsonrpc": "2.0",
672+
"id": 1,
673+
"result": "0x1d243",
674+
});
675+
676+
server.mock(|when, then| {
677+
when.method(Method::POST).path("/next");
678+
then.status(200).body(body.to_string());
679+
});
680+
681+
let config = Arc::new(Config::mainnet());
682+
let auth = Arc::default();
683+
let server_url = server.url("/").parse()?;
684+
let next_server_url = server.url("/next").parse()?;
685+
686+
let eth1_api = Arc::new(Eth1Api::new(
687+
config,
688+
Client::new(),
689+
auth,
690+
vec![server_url, next_server_url],
691+
None,
692+
None,
693+
));
694+
695+
// Set to use the primary endpoint which is not a fallback
696+
assert!(!eth1_api.el_offline().await);
697+
assert!(!eth1_api
698+
.current_endpoint()
699+
.await
700+
.expect("endpoint should be avaialble")
701+
.is_fallback());
702+
703+
assert_eq!(
704+
eth1_api
705+
.current_head_number()
706+
.await
707+
.expect("the fallback endpoint should be working"),
708+
119_363,
709+
);
710+
711+
// Expect to use the fallback endpoint when the primary endpoint returns an error
712+
assert!(eth1_api
713+
.current_endpoint()
714+
.await
715+
.expect("the fallback endpoint should be avaialble")
716+
.is_fallback());
717+
718+
// Even though the primary endpoint is offline, eth1_api itself is not offline
719+
assert!(!eth1_api.el_offline().await);
720+
721+
Ok(())
722+
}
723+
592724
#[tokio::test]
593725
async fn test_bellatrix_payload_deserialization_with_real_response() -> Result<()> {
594726
let body = json!({

fork_choice_control/src/block_processor.rs

+3-8
Original file line numberDiff line numberDiff line change
@@ -24,7 +24,7 @@ use types::{
2424
nonstandard::{BlockRewards, Phase, SlashingKind},
2525
phase0::primitives::H256,
2626
preset::Preset,
27-
traits::{BeaconBlock as _, BeaconState as _, SignedBeaconBlock as _},
27+
traits::{BeaconBlock as _, SignedBeaconBlock as _},
2828
};
2929

3030
#[derive(Constructor)]
@@ -165,16 +165,11 @@ impl<P: Preset> BlockProcessor<P> {
165165
let block_slot = block.message().slot();
166166

167167
// > Make a copy of the state to avoid mutability issues
168-
let mut state = self
168+
let state = self
169169
.state_cache
170-
.before_or_at_slot(store, parent.block_root, block_slot)
170+
.try_state_at_slot(store, parent.block_root, block_slot)?
171171
.unwrap_or_else(|| parent.state(store));
172172

173-
// > Process slots (including those with no blocks) since block
174-
if state.slot() < block_slot {
175-
combined::process_slots(&self.chain_config, state.make_mut(), block_slot)?;
176-
}
177-
178173
combined::process_block_for_gossip(&self.chain_config, &state, block)?;
179174

180175
Ok(None)

fork_choice_control/src/mutator.rs

+4-4
Original file line numberDiff line numberDiff line change
@@ -650,7 +650,7 @@ where
650650
Ok(AggregateAndProofAction::Accept {
651651
aggregate_and_proof,
652652
attesting_indices,
653-
is_superset,
653+
is_subset_aggregate,
654654
}) => {
655655
if let Some(metrics) = self.metrics.as_ref() {
656656
metrics.register_mutator_aggregate_and_proof(&["accepted"]);
@@ -671,10 +671,10 @@ where
671671
let (gossip_id, sender) = origin.split();
672672

673673
if let Some(gossip_id) = gossip_id {
674-
if is_superset {
675-
P2pMessage::Accept(gossip_id).send(&self.p2p_tx);
676-
} else {
674+
if is_subset_aggregate {
677675
P2pMessage::Ignore(gossip_id).send(&self.p2p_tx);
676+
} else {
677+
P2pMessage::Accept(gossip_id).send(&self.p2p_tx);
678678
}
679679
}
680680

fork_choice_store/src/misc.rs

+1-1
Original file line numberDiff line numberDiff line change
@@ -548,7 +548,7 @@ pub enum AggregateAndProofAction<P: Preset> {
548548
Accept {
549549
aggregate_and_proof: Arc<SignedAggregateAndProof<P>>,
550550
attesting_indices: AttestingIndices<P>,
551-
is_superset: bool,
551+
is_subset_aggregate: bool,
552552
},
553553
Ignore,
554554
DelayUntilBlock(Arc<SignedAggregateAndProof<P>>, H256),

fork_choice_store/src/store.rs

+12-46
Original file line numberDiff line numberDiff line change
@@ -1057,13 +1057,7 @@ impl<P: Preset> Store<P> {
10571057
};
10581058

10591059
// > Check the block is valid and compute the post-state
1060-
let block_action = state_transition_for_gossip(parent)?;
1061-
1062-
if let Some(action) = block_action {
1063-
return Ok(Some(action));
1064-
}
1065-
1066-
Ok(None)
1060+
state_transition_for_gossip(parent)
10671061
}
10681062

10691063
pub fn validate_block_with_custom_state_transition(
@@ -1275,30 +1269,19 @@ impl<P: Preset> Store<P> {
12751269
},
12761270
);
12771271

1278-
let committee = if let Some(committee_bits) = aggregate.committee_bits() {
1279-
let committee_indices = misc::get_committee_indices::<P>(*committee_bits);
1272+
let index = aggregate
1273+
.committee_bits()
1274+
.and_then(|bits| misc::get_committee_indices::<P>(*bits).next())
1275+
.unwrap_or(index);
12801276

1281-
let mut committees = vec![];
1282-
1283-
for committee_index in committee_indices {
1284-
let committee = accessors::beacon_committee(&target_state, slot, committee_index)?;
1285-
1286-
committees.extend(committee);
1287-
}
1288-
1289-
committees.into()
1290-
} else {
1291-
accessors::beacon_committee(&target_state, slot, index)?
1292-
.into_iter()
1293-
.collect::<Box<[_]>>()
1294-
};
1277+
let committee = accessors::beacon_committee(&target_state, slot, index)?;
12951278

12961279
// > The aggregator's validator index is within the committee
12971280
ensure!(
1298-
committee.contains(&aggregator_index),
1281+
committee.into_iter().contains(&aggregator_index),
12991282
Error::AggregatorNotInCommittee {
13001283
aggregate_and_proof,
1301-
committee,
1284+
committee: committee.into_iter().collect(),
13021285
},
13031286
);
13041287

@@ -1333,12 +1316,12 @@ impl<P: Preset> Store<P> {
13331316
)?;
13341317

13351318
// https://github.com/ethereum/consensus-specs/pull/2847
1336-
let is_superset = self.aggregate_and_proof_supersets.check(&aggregate);
1319+
let is_subset_aggregate = !self.aggregate_and_proof_supersets.check(&aggregate);
13371320

13381321
Ok(AggregateAndProofAction::Accept {
13391322
aggregate_and_proof,
13401323
attesting_indices,
1341-
is_superset,
1324+
is_subset_aggregate,
13421325
})
13431326
}
13441327

@@ -1757,33 +1740,16 @@ impl<P: Preset> Store<P> {
17571740
return Ok(BlobSidecarAction::Ignore(true));
17581741
}
17591742

1760-
let mut state = self
1743+
let state = self
17611744
.state_cache
1762-
.before_or_at_slot(self, block_header.parent_root, block_header.slot)
1745+
.try_state_at_slot(self, block_header.parent_root, block_header.slot)?
17631746
.unwrap_or_else(|| {
17641747
self.chain_link(block_header.parent_root)
17651748
.or_else(|| self.chain_link_before_or_at(block_header.slot))
17661749
.map(|chain_link| chain_link.state(self))
17671750
.unwrap_or_else(|| self.head().state(self))
17681751
});
17691752

1770-
if state.slot() < block_header.slot {
1771-
if Feature::WarnOnStateCacheSlotProcessing.is_enabled() && self.is_forward_synced() {
1772-
// `Backtrace::force_capture` can be costly and a warning may be excessive,
1773-
// but this is controlled by a `Feature` that should be disabled by default.
1774-
warn!(
1775-
"processing slots for beacon state not found in state cache before state transition \
1776-
(block root: {:?}, from slot {} to {})\n{}",
1777-
block_header.parent_root,
1778-
state.slot(),
1779-
block_header.slot,
1780-
Backtrace::force_capture(),
1781-
);
1782-
}
1783-
1784-
combined::process_slots(&self.chain_config, state.make_mut(), block_header.slot)?;
1785-
}
1786-
17871753
// [REJECT] The proposer signature of blob_sidecar.signed_block_header, is valid with respect to the block_header.proposer_index pubkey.
17881754
SingleVerifier.verify_singular(
17891755
blob_sidecar

0 commit comments

Comments
 (0)