Merge remote-tracking branch 'origin/unstable' into tree-states

This commit is contained in:
Michael Sproul
2023-11-12 22:19:07 +03:00
161 changed files with 3635 additions and 2227 deletions

View File

@@ -92,8 +92,7 @@ impl ForkChoiceTest {
T: Fn(&BeaconForkChoiceStore<E, MemoryStore<E>, MemoryStore<E>>) -> U,
{
func(
&self
.harness
self.harness
.chain
.canonical_head
.fork_choice_read_lock()
@@ -386,8 +385,7 @@ impl ForkChoiceTest {
&self.harness.chain.spec,
self.harness.logger(),
)
.err()
.expect("on_block did not return an error");
.expect_err("on_block did not return an error");
comparison_func(err);
self
}
@@ -841,7 +839,7 @@ async fn valid_attestation() {
.apply_attestation_to_chain(
MutationDelay::NoDelay,
|_, _| {},
|result| assert_eq!(result.unwrap(), ()),
|result| assert!(result.is_ok()),
)
.await;
}
@@ -1074,7 +1072,7 @@ async fn invalid_attestation_delayed_slot() {
.apply_attestation_to_chain(
MutationDelay::NoDelay,
|_, _| {},
|result| assert_eq!(result.unwrap(), ()),
|result| assert!(result.is_ok()),
)
.await
.inspect_queued_attestations(|queue| assert_eq!(queue.len(), 1))
@@ -1183,7 +1181,7 @@ async fn weak_subjectivity_check_fails_early_epoch() {
let mut checkpoint = setup_harness.harness.finalized_checkpoint();
checkpoint.epoch = checkpoint.epoch - 1;
checkpoint.epoch -= 1;
let chain_config = ChainConfig {
weak_subjectivity_checkpoint: Some(checkpoint),
@@ -1210,7 +1208,7 @@ async fn weak_subjectivity_check_fails_late_epoch() {
let mut checkpoint = setup_harness.harness.finalized_checkpoint();
checkpoint.epoch = checkpoint.epoch + 1;
checkpoint.epoch += 1;
let chain_config = ChainConfig {
weak_subjectivity_checkpoint: Some(checkpoint),

View File

@@ -1035,13 +1035,11 @@ impl ProtoArray {
.epoch
.start_slot(E::slots_per_epoch());
let mut node = if let Some(node) = self
let Some(mut node) = self
.indices
.get(&root)
.and_then(|index| self.nodes.get(*index))
{
node
} else {
else {
// An unknown root is not a finalized descendant. This line can only
// be reached if the user supplies a root that is not known to fork
// choice.

View File

@@ -41,3 +41,4 @@ arbitrary-fuzz = [
"ssz_types/arbitrary",
"tree_hash/arbitrary",
]
portable = ["bls/supranational-portable"]

View File

@@ -30,12 +30,11 @@ impl<E: EthSpec> AllCaches for BeaconState<E> {
fn all_caches_built(&self) -> bool {
let current_epoch = self.current_epoch();
let epoch_cache_decision_block_root =
if let Ok(root) = self.proposer_shuffling_decision_root(Hash256::zero()) {
root
} else {
return false;
};
let Ok(epoch_cache_decision_block_root) =
self.proposer_shuffling_decision_root(Hash256::zero())
else {
return false;
};
self.get_total_active_balance_at_epoch(current_epoch)
.is_ok()
&& self.committee_cache_is_initialized(RelativeEpoch::Previous)

View File

@@ -70,3 +70,4 @@ sqlite = []
# The `arbitrary-fuzz` feature is a no-op provided for backwards compatibility.
# For simplicity `Arbitrary` is now derived regardless of the feature's presence.
arbitrary-fuzz = []
portable = ["bls/supranational-portable"]

View File

@@ -3,7 +3,7 @@
# Misc
# ---------------------------------------------------------------
# [customized]
FIELD_ELEMENTS_PER_BLOB: 4
FIELD_ELEMENTS_PER_BLOB: 4096
# [customized]
MAX_BLOB_COMMITMENTS_PER_BLOCK: 16
# `uint64(6)`

View File

@@ -508,6 +508,14 @@ impl<E: EthSpec> From<BeaconBlockBody<E, FullPayload<E>>>
}
}
/// Util method helpful for logging.
pub fn format_kzg_commitments(commitments: &[KzgCommitment]) -> String {
let commitment_strings: Vec<String> = commitments.iter().map(|x| x.to_string()).collect();
let commitments_joined = commitment_strings.join(", ");
let surrounded_commitments = format!("[{}]", commitments_joined);
surrounded_commitments
}
#[cfg(test)]
mod tests {
mod base {

View File

@@ -750,6 +750,25 @@ impl<T: EthSpec> BeaconState<T> {
cache.get_all_beacon_committees()
}
/// Returns the block root which decided the proposer shuffling for the epoch passed in parameter. This root
/// can be used to key this proposer shuffling.
///
/// ## Notes
///
/// The `block_root` must be equal to the latest block applied to `self`.
pub fn proposer_shuffling_decision_root_at_epoch(
&self,
epoch: Epoch,
block_root: Hash256,
) -> Result<Hash256, Error> {
let decision_slot = self.proposer_shuffling_decision_slot(epoch);
if self.slot() <= decision_slot {
Ok(block_root)
} else {
self.get_block_root(decision_slot).map(|root| *root)
}
}
/// Returns the block root which decided the proposer shuffling for the current epoch. This root
/// can be used to key this proposer shuffling.
///
@@ -758,7 +777,7 @@ impl<T: EthSpec> BeaconState<T> {
/// The `block_root` covers the one-off scenario where the genesis block decides its own
/// shuffling. It should be set to the latest block applied to `self` or the genesis block root.
pub fn proposer_shuffling_decision_root(&self, block_root: Hash256) -> Result<Hash256, Error> {
let decision_slot = self.proposer_shuffling_decision_slot();
let decision_slot = self.proposer_shuffling_decision_slot(self.current_epoch());
if self.slot() == decision_slot {
Ok(block_root)
} else {
@@ -767,11 +786,9 @@ impl<T: EthSpec> BeaconState<T> {
}
/// Returns the slot at which the proposer shuffling was decided. The block root at this slot
/// can be used to key the proposer shuffling for the current epoch.
fn proposer_shuffling_decision_slot(&self) -> Slot {
self.current_epoch()
.start_slot(T::slots_per_epoch())
.saturating_sub(1_u64)
/// can be used to key the proposer shuffling for the given epoch.
fn proposer_shuffling_decision_slot(&self, epoch: Epoch) -> Slot {
epoch.start_slot(T::slots_per_epoch()).saturating_sub(1_u64)
}
/// Returns the block root which decided the attester shuffling for the given `relative_epoch`.

View File

@@ -1,7 +1,10 @@
use crate::test_utils::TestRandom;
use crate::{Blob, EthSpec, Hash256, SignedRoot, Slot};
use derivative::Derivative;
use kzg::{Kzg, KzgCommitment, KzgPreset, KzgProof, BYTES_PER_FIELD_ELEMENT};
use kzg::{
Blob as KzgBlob, Kzg, KzgCommitment, KzgProof, BYTES_PER_BLOB, BYTES_PER_FIELD_ELEMENT,
FIELD_ELEMENTS_PER_BLOB,
};
use rand::Rng;
use serde::{Deserialize, Serialize};
use ssz::Encode;
@@ -142,12 +145,12 @@ impl<T: EthSpec> BlobSidecar<T> {
}
}
pub fn random_valid<R: Rng>(rng: &mut R, kzg: &Kzg<T::Kzg>) -> Result<Self, String> {
let mut blob_bytes = vec![0u8; T::Kzg::BYTES_PER_BLOB];
pub fn random_valid<R: Rng>(rng: &mut R, kzg: &Kzg) -> Result<Self, String> {
let mut blob_bytes = vec![0u8; BYTES_PER_BLOB];
rng.fill_bytes(&mut blob_bytes);
// Ensure that the blob is canonical by ensuring that
// each field element contained in the blob is < BLS_MODULUS
for i in 0..T::Kzg::FIELD_ELEMENTS_PER_BLOB {
for i in 0..FIELD_ELEMENTS_PER_BLOB {
let Some(byte) = blob_bytes.get_mut(
i.checked_mul(BYTES_PER_FIELD_ELEMENT)
.ok_or("overflow".to_string())?,
@@ -159,7 +162,7 @@ impl<T: EthSpec> BlobSidecar<T> {
let blob = Blob::<T>::new(blob_bytes)
.map_err(|e| format!("error constructing random blob: {:?}", e))?;
let kzg_blob = T::blob_from_bytes(&blob).unwrap();
let kzg_blob = KzgBlob::from_bytes(&blob).unwrap();
let commitment = kzg
.blob_to_kzg_commitment(&kzg_blob)

View File

@@ -1,6 +1,5 @@
use crate::*;
use kzg::{BlobTrait, KzgPreset, MainnetKzgPreset, MinimalKzgPreset};
use safe_arith::SafeArith;
use serde::{Deserialize, Serialize};
use ssz_types::typenum::{
@@ -52,8 +51,6 @@ impl fmt::Display for EthSpecId {
pub trait EthSpec:
'static + Default + Sync + Send + Clone + Debug + PartialEq + Eq + for<'a> arbitrary::Arbitrary<'a>
{
type Kzg: KzgPreset;
/*
* Constants
*/
@@ -270,10 +267,6 @@ pub trait EthSpec:
Self::FieldElementsPerBlob::to_usize()
}
fn blob_from_bytes(bytes: &[u8]) -> Result<<Self::Kzg as KzgPreset>::Blob, kzg::Error> {
<Self::Kzg as KzgPreset>::Blob::from_bytes(bytes)
}
/// Returns the `BYTES_PER_BLOB` constant for this specification.
fn bytes_per_blob() -> usize {
Self::BytesPerBlob::to_usize()
@@ -293,8 +286,6 @@ macro_rules! params_from_eth_spec {
pub struct MainnetEthSpec;
impl EthSpec for MainnetEthSpec {
type Kzg = MainnetKzgPreset;
type JustificationBitsLength = U4;
type SubnetBitfieldLength = U64;
type MaxValidatorsPerCommittee = U2048;
@@ -344,8 +335,6 @@ impl EthSpec for MainnetEthSpec {
pub struct MinimalEthSpec;
impl EthSpec for MinimalEthSpec {
type Kzg = MinimalKzgPreset;
type SlotsPerEpoch = U8;
type EpochsPerEth1VotingPeriod = U4;
type SlotsPerHistoricalRoot = U64;
@@ -356,8 +345,8 @@ impl EthSpec for MinimalEthSpec {
type MaxPendingAttestations = U1024; // 128 max attestations * 8 slots per epoch
type SlotsPerEth1VotingPeriod = U32; // 4 epochs * 8 slots per epoch
type MaxWithdrawalsPerPayload = U4;
type FieldElementsPerBlob = U4;
type BytesPerBlob = U128;
type FieldElementsPerBlob = U4096;
type BytesPerBlob = U131072;
type MaxBlobCommitmentsPerBlock = U16;
params_from_eth_spec!(MainnetEthSpec {
@@ -398,8 +387,6 @@ impl EthSpec for MinimalEthSpec {
pub struct GnosisEthSpec;
impl EthSpec for GnosisEthSpec {
type Kzg = MainnetKzgPreset;
type JustificationBitsLength = U4;
type SubnetBitfieldLength = U64;
type MaxValidatorsPerCommittee = U2048;

View File

@@ -979,3 +979,10 @@ impl<T: EthSpec> From<BlindedPayload<T>> for ExecutionPayloadHeader<T> {
}
}
}
/// The block production flow version to be used.
pub enum BlockProductionVersion {
V3,
BlindedV2,
FullV2,
}

View File

@@ -1,3 +1,4 @@
use crate::beacon_block_body::format_kzg_commitments;
use crate::*;
use bls::Signature;
use derivative::Derivative;
@@ -256,6 +257,15 @@ impl<E: EthSpec, Payload: AbstractExecPayload<E>> SignedBeaconBlock<E, Payload>
.map(|c| c.len())
.unwrap_or(0)
}
/// Used for displaying commitments in logs.
pub fn commitments_formatted(&self) -> String {
let Ok(commitments) = self.message().body().blob_kzg_commitments() else {
return "[]".to_string();
};
format_kzg_commitments(commitments.as_ref())
}
}
// We can convert pre-Bellatrix blocks without payloads into blocks with payloads.