Merge remote-tracking branch 'origin/unstable' into gloas-walk-always

This commit is contained in:
Michael Sproul
2026-03-30 16:10:35 +11:00
37 changed files with 287 additions and 253 deletions

View File

@@ -4,7 +4,6 @@ on:
push:
branches:
- unstable
- stable
tags:
- v*
workflow_dispatch: # allows manual triggering for testing purposes and skips publishing an image
@@ -25,9 +24,6 @@ jobs:
if [[ "${{ github.ref }}" == refs/tags/* ]]; then
# It's a tag (e.g., v1.2.3)
VERSION="${GITHUB_REF#refs/tags/}"
elif [[ "${{ github.ref }}" == refs/heads/stable ]]; then
# stable branch -> latest
VERSION="latest"
elif [[ "${{ github.ref }}" == refs/heads/unstable ]]; then
# unstable branch -> latest-unstable
VERSION="latest-unstable"
@@ -174,3 +170,14 @@ jobs:
${IMAGE_NAME}:${VERSION}-arm64
docker manifest push ${IMAGE_NAME}:${VERSION}
# For version tags, also create/update the latest tag to keep stable up to date
# Only create latest tag for proper release versions (e.g. v1.2.3, not v1.2.3-alpha)
if [[ "${GITHUB_REF}" == refs/tags/* ]] && [[ "${VERSION}" =~ ^v[0-9]{1,2}\.[0-9]{1,2}\.[0-9]{1,2}$ ]]; then
docker manifest create \
${IMAGE_NAME}:latest \
${IMAGE_NAME}:${VERSION}-amd64 \
${IMAGE_NAME}:${VERSION}-arm64
docker manifest push ${IMAGE_NAME}:latest
fi

View File

@@ -4,7 +4,6 @@ on:
push:
branches:
- unstable
- stable
tags:
- v*
@@ -28,11 +27,6 @@ jobs:
extract-version:
runs-on: ubuntu-22.04
steps:
- name: Extract version (if stable)
if: github.event.ref == 'refs/heads/stable'
run: |
echo "VERSION=latest" >> $GITHUB_ENV
echo "VERSION_SUFFIX=" >> $GITHUB_ENV
- name: Extract version (if unstable)
if: github.event.ref == 'refs/heads/unstable'
run: |
@@ -159,7 +153,16 @@ jobs:
- name: Create and push multiarch manifests
run: |
# Create the main tag (versioned for releases, latest-unstable for unstable)
docker buildx imagetools create -t ${{ github.repository_owner}}/${{ matrix.binary }}:${VERSION}${VERSION_SUFFIX} \
${{ github.repository_owner}}/${{ matrix.binary }}:${VERSION}-arm64${VERSION_SUFFIX} \
${{ github.repository_owner}}/${{ matrix.binary }}:${VERSION}-amd64${VERSION_SUFFIX};
# For version tags, also create/update the latest tag to keep stable up to date
# Only create latest tag for proper release versions (e.g. v1.2.3, not v1.2.3-alpha)
if [[ "${GITHUB_REF}" == refs/tags/* ]] && [[ "${VERSION}" =~ ^v[0-9]{1,2}\.[0-9]{1,2}\.[0-9]{1,2}$ ]]; then
docker buildx imagetools create -t ${{ github.repository_owner}}/${{ matrix.binary }}:latest \
${{ github.repository_owner}}/${{ matrix.binary }}:${VERSION}-arm64${VERSION_SUFFIX} \
${{ github.repository_owner}}/${{ matrix.binary }}:${VERSION}-amd64${VERSION_SUFFIX};
fi

317
Cargo.lock generated

File diff suppressed because it is too large Load Diff

View File

@@ -91,7 +91,7 @@ resolver = "2"
[workspace.package]
edition = "2024"
version = "8.1.2"
version = "8.1.3"
[workspace.dependencies]
account_utils = { path = "common/account_utils" }
@@ -213,7 +213,6 @@ sensitive_url = { version = "0.1", features = ["serde"] }
serde = { version = "1", features = ["derive"] }
serde_json = "1"
serde_repr = "0.1"
serde_yaml = "0.9"
sha2 = "0.10"
signing_method = { path = "validator_client/signing_method" }
slasher = { path = "slasher", default-features = false }
@@ -260,6 +259,7 @@ warp = { version = "0.3.7", default-features = false, features = ["tls"] }
warp_utils = { path = "common/warp_utils" }
workspace_members = { path = "common/workspace_members" }
xdelta3 = { git = "https://github.com/sigp/xdelta3-rs", rev = "fe3906605c87b6c0515bd7c8fc671f47875e3ccc" }
yaml_serde = "0.10"
zeroize = { version = "1", features = ["zeroize_derive", "serde"] }
zip = { version = "6.0", default-features = false, features = ["deflate"] }
zstd = "0.13"
@@ -276,9 +276,7 @@ debug = true
[patch.crates-io]
quick-protobuf = { git = "https://github.com/sigp/quick-protobuf.git", rev = "87c4ccb9bb2af494de375f5f6c62850badd26304" }
yamux = { git = "https://github.com/sigp/rust-yamux", rev = "29efa6aebd4bdfcb16bfb21969ec0c785e570b74" }
quinn = { git = "https://github.com/sigp/quinn", rev = "59af87979c8411864c1cb68613222f54ed2930a7" }
[patch."https://github.com/libp2p/rust-libp2p.git"]
libp2p = { git = "https://github.com/sigp/rust-libp2p.git", rev = "f88e43de9eba00b416d0374b1a1fb2de47b65864" }
libp2p-mplex = { git = "https://github.com/sigp/rust-libp2p.git", rev = "f88e43de9eba00b416d0374b1a1fb2de47b65864" }
libp2p = { git = "https://github.com/sigp/rust-libp2p.git", rev = "defcaf1a78cf5b70a723b3fee0e0be051c1dbd88" }
libp2p-mplex = { git = "https://github.com/sigp/rust-libp2p.git", rev = "defcaf1a78cf5b70a723b3fee0e0be051c1dbd88" }

View File

@@ -42,6 +42,6 @@ types = { workspace = true }
[dev-dependencies]
operation_pool = { workspace = true }
serde_yaml = { workspace = true }
state_processing = { workspace = true }
tokio = { workspace = true }
yaml_serde = { workspace = true }

View File

@@ -236,7 +236,7 @@ mod tests {
fn serde() {
let config = Config::default();
let serialized =
serde_yaml::to_string(&config).expect("should serde encode default config");
serde_yaml::from_str::<Config>(&serialized).expect("should serde decode default config");
yaml_serde::to_string(&config).expect("should serde encode default config");
yaml_serde::from_str::<Config>(&serialized).expect("should serde decode default config");
}
}

View File

@@ -5,7 +5,7 @@ use crate::http::{
ENGINE_GET_PAYLOAD_BODIES_BY_HASH_V1, ENGINE_GET_PAYLOAD_BODIES_BY_RANGE_V1,
ENGINE_GET_PAYLOAD_V1, ENGINE_GET_PAYLOAD_V2, ENGINE_GET_PAYLOAD_V3, ENGINE_GET_PAYLOAD_V4,
ENGINE_GET_PAYLOAD_V5, ENGINE_NEW_PAYLOAD_V1, ENGINE_NEW_PAYLOAD_V2, ENGINE_NEW_PAYLOAD_V3,
ENGINE_NEW_PAYLOAD_V4,
ENGINE_NEW_PAYLOAD_V4, ENGINE_NEW_PAYLOAD_V5,
};
use eth2::types::{
BlobsBundle, SsePayloadAttributes, SsePayloadAttributesV1, SsePayloadAttributesV2,
@@ -551,6 +551,7 @@ pub struct EngineCapabilities {
pub new_payload_v2: bool,
pub new_payload_v3: bool,
pub new_payload_v4: bool,
pub new_payload_v5: bool,
pub forkchoice_updated_v1: bool,
pub forkchoice_updated_v2: bool,
pub forkchoice_updated_v3: bool,
@@ -581,6 +582,9 @@ impl EngineCapabilities {
if self.new_payload_v4 {
response.push(ENGINE_NEW_PAYLOAD_V4);
}
if self.new_payload_v5 {
response.push(ENGINE_NEW_PAYLOAD_V5);
}
if self.forkchoice_updated_v1 {
response.push(ENGINE_FORKCHOICE_UPDATED_V1);
}

View File

@@ -35,6 +35,7 @@ pub const ENGINE_NEW_PAYLOAD_V1: &str = "engine_newPayloadV1";
pub const ENGINE_NEW_PAYLOAD_V2: &str = "engine_newPayloadV2";
pub const ENGINE_NEW_PAYLOAD_V3: &str = "engine_newPayloadV3";
pub const ENGINE_NEW_PAYLOAD_V4: &str = "engine_newPayloadV4";
pub const ENGINE_NEW_PAYLOAD_V5: &str = "engine_newPayloadV5";
pub const ENGINE_NEW_PAYLOAD_TIMEOUT: Duration = Duration::from_secs(8);
pub const ENGINE_GET_PAYLOAD_V1: &str = "engine_getPayloadV1";
@@ -74,6 +75,7 @@ pub static LIGHTHOUSE_CAPABILITIES: &[&str] = &[
ENGINE_NEW_PAYLOAD_V2,
ENGINE_NEW_PAYLOAD_V3,
ENGINE_NEW_PAYLOAD_V4,
ENGINE_NEW_PAYLOAD_V5,
ENGINE_GET_PAYLOAD_V1,
ENGINE_GET_PAYLOAD_V2,
ENGINE_GET_PAYLOAD_V3,
@@ -883,7 +885,7 @@ impl HttpJsonRpc {
Ok(response.into())
}
pub async fn new_payload_v4_gloas<E: EthSpec>(
pub async fn new_payload_v5_gloas<E: EthSpec>(
&self,
new_payload_request_gloas: NewPayloadRequestGloas<'_, E>,
) -> Result<PayloadStatusV1, Error> {
@@ -903,7 +905,7 @@ impl HttpJsonRpc {
let response: JsonPayloadStatusV1 = self
.rpc_request(
ENGINE_NEW_PAYLOAD_V4,
ENGINE_NEW_PAYLOAD_V5,
params,
ENGINE_NEW_PAYLOAD_TIMEOUT * self.execution_timeout_multiplier,
)
@@ -1198,6 +1200,7 @@ impl HttpJsonRpc {
new_payload_v2: capabilities.contains(ENGINE_NEW_PAYLOAD_V2),
new_payload_v3: capabilities.contains(ENGINE_NEW_PAYLOAD_V3),
new_payload_v4: capabilities.contains(ENGINE_NEW_PAYLOAD_V4),
new_payload_v5: capabilities.contains(ENGINE_NEW_PAYLOAD_V5),
forkchoice_updated_v1: capabilities.contains(ENGINE_FORKCHOICE_UPDATED_V1),
forkchoice_updated_v2: capabilities.contains(ENGINE_FORKCHOICE_UPDATED_V2),
forkchoice_updated_v3: capabilities.contains(ENGINE_FORKCHOICE_UPDATED_V3),
@@ -1353,10 +1356,10 @@ impl HttpJsonRpc {
}
}
NewPayloadRequest::Gloas(new_payload_request_gloas) => {
if engine_capabilities.new_payload_v4 {
self.new_payload_v4_gloas(new_payload_request_gloas).await
if engine_capabilities.new_payload_v5 {
self.new_payload_v5_gloas(new_payload_request_gloas).await
} else {
Err(Error::RequiredMethodUnsupported("engine_newPayloadV4"))
Err(Error::RequiredMethodUnsupported("engine_newPayloadV5"))
}
}
}

View File

@@ -102,7 +102,8 @@ pub async fn handle_rpc<E: EthSpec>(
ENGINE_NEW_PAYLOAD_V1
| ENGINE_NEW_PAYLOAD_V2
| ENGINE_NEW_PAYLOAD_V3
| ENGINE_NEW_PAYLOAD_V4 => {
| ENGINE_NEW_PAYLOAD_V4
| ENGINE_NEW_PAYLOAD_V5 => {
let request = match method {
ENGINE_NEW_PAYLOAD_V1 => JsonExecutionPayload::Bellatrix(
get_param::<JsonExecutionPayloadBellatrix<E>>(params, 0)
@@ -118,17 +119,16 @@ pub async fn handle_rpc<E: EthSpec>(
ENGINE_NEW_PAYLOAD_V3 => get_param::<JsonExecutionPayloadDeneb<E>>(params, 0)
.map(|jep| JsonExecutionPayload::Deneb(jep))
.map_err(|s| (s, BAD_PARAMS_ERROR_CODE))?,
ENGINE_NEW_PAYLOAD_V4 => get_param::<JsonExecutionPayloadGloas<E>>(params, 0)
.map(|jep| JsonExecutionPayload::Gloas(jep))
.or_else(|_| {
get_param::<JsonExecutionPayloadFulu<E>>(params, 0)
ENGINE_NEW_PAYLOAD_V4 => get_param::<JsonExecutionPayloadFulu<E>>(params, 0)
.map(|jep| JsonExecutionPayload::Fulu(jep))
})
.or_else(|_| {
get_param::<JsonExecutionPayloadElectra<E>>(params, 0)
.map(|jep| JsonExecutionPayload::Electra(jep))
})
.map_err(|s| (s, BAD_PARAMS_ERROR_CODE))?,
ENGINE_NEW_PAYLOAD_V5 => get_param::<JsonExecutionPayloadGloas<E>>(params, 0)
.map(|jep| JsonExecutionPayload::Gloas(jep))
.map_err(|s| (s, BAD_PARAMS_ERROR_CODE))?,
_ => unreachable!(),
};
@@ -192,7 +192,7 @@ pub async fn handle_rpc<E: EthSpec>(
));
}
}
ForkName::Electra | ForkName::Fulu | ForkName::Gloas => {
ForkName::Electra | ForkName::Fulu => {
if method == ENGINE_NEW_PAYLOAD_V1
|| method == ENGINE_NEW_PAYLOAD_V2
|| method == ENGINE_NEW_PAYLOAD_V3
@@ -230,6 +230,14 @@ pub async fn handle_rpc<E: EthSpec>(
));
}
}
ForkName::Gloas => {
if method != ENGINE_NEW_PAYLOAD_V5 {
return Err((
format!("{} called after Gloas fork!", method),
GENERIC_ERROR_CODE,
));
}
}
_ => unreachable!(),
};

View File

@@ -43,6 +43,7 @@ pub const DEFAULT_ENGINE_CAPABILITIES: EngineCapabilities = EngineCapabilities {
new_payload_v2: true,
new_payload_v3: true,
new_payload_v4: true,
new_payload_v5: true,
forkchoice_updated_v1: true,
forkchoice_updated_v2: true,
forkchoice_updated_v3: true,

View File

@@ -14,8 +14,8 @@ rand = { workspace = true }
regex = { workspace = true }
rpassword = "5.0.0"
serde = { workspace = true }
serde_yaml = { workspace = true }
tracing = { workspace = true }
types = { workspace = true }
validator_dir = { workspace = true }
yaml_serde = { workspace = true }
zeroize = { workspace = true }

View File

@@ -31,11 +31,11 @@ pub enum Error {
/// The config file could not be opened.
UnableToOpenFile(io::Error),
/// The config file could not be parsed as YAML.
UnableToParseFile(serde_yaml::Error),
UnableToParseFile(yaml_serde::Error),
/// There was an error whilst performing the recursive keystore search function.
UnableToSearchForKeystores(io::Error),
/// The config file could not be serialized as YAML.
UnableToEncodeFile(serde_yaml::Error),
UnableToEncodeFile(yaml_serde::Error),
/// The config file or temp file could not be written to the filesystem.
UnableToWriteFile(filesystem::Error),
/// The public key from the keystore is invalid.
@@ -248,7 +248,7 @@ impl ValidatorDefinitions {
.create_new(false)
.open(config_path)
.map_err(Error::UnableToOpenFile)?;
serde_yaml::from_reader(file).map_err(Error::UnableToParseFile)
yaml_serde::from_reader(file).map_err(Error::UnableToParseFile)
}
/// Perform a recursive, exhaustive search through `validators_dir` and add any keystores
@@ -376,7 +376,7 @@ impl ValidatorDefinitions {
let config_path = validators_dir.as_ref().join(CONFIG_FILENAME);
let temp_path = validators_dir.as_ref().join(CONFIG_TEMP_FILENAME);
let mut bytes = vec![];
serde_yaml::to_writer(&mut bytes, self).map_err(Error::UnableToEncodeFile)?;
yaml_serde::to_writer(&mut bytes, self).map_err(Error::UnableToEncodeFile)?;
write_file_via_temporary(&config_path, &temp_path, &bytes)
.map_err(Error::UnableToWriteFile)?;
@@ -531,7 +531,7 @@ mod tests {
voting_keystore_path: ""
voting_public_key: "0xaf3c7ddab7e293834710fca2d39d068f884455ede270e0d0293dc818e4f2f0f975355067e8437955cb29aec674e5c9e7"
"#;
let def: ValidatorDefinition = serde_yaml::from_str(no_graffiti).unwrap();
let def: ValidatorDefinition = yaml_serde::from_str(no_graffiti).unwrap();
assert!(def.graffiti.is_none());
let invalid_graffiti = r#"---
@@ -543,7 +543,7 @@ mod tests {
voting_public_key: "0xaf3c7ddab7e293834710fca2d39d068f884455ede270e0d0293dc818e4f2f0f975355067e8437955cb29aec674e5c9e7"
"#;
let def: Result<ValidatorDefinition, _> = serde_yaml::from_str(invalid_graffiti);
let def: Result<ValidatorDefinition, _> = yaml_serde::from_str(invalid_graffiti);
assert!(def.is_err());
let valid_graffiti = r#"---
@@ -555,7 +555,7 @@ mod tests {
voting_public_key: "0xaf3c7ddab7e293834710fca2d39d068f884455ede270e0d0293dc818e4f2f0f975355067e8437955cb29aec674e5c9e7"
"#;
let def: ValidatorDefinition = serde_yaml::from_str(valid_graffiti).unwrap();
let def: ValidatorDefinition = yaml_serde::from_str(valid_graffiti).unwrap();
assert_eq!(
def.graffiti,
Some(GraffitiString::from_str("mrfwashere").unwrap())
@@ -571,7 +571,7 @@ mod tests {
voting_keystore_path: ""
voting_public_key: "0xaf3c7ddab7e293834710fca2d39d068f884455ede270e0d0293dc818e4f2f0f975355067e8437955cb29aec674e5c9e7"
"#;
let def: ValidatorDefinition = serde_yaml::from_str(no_suggested_fee_recipient).unwrap();
let def: ValidatorDefinition = yaml_serde::from_str(no_suggested_fee_recipient).unwrap();
assert!(def.suggested_fee_recipient.is_none());
let invalid_suggested_fee_recipient = r#"---
@@ -584,7 +584,7 @@ mod tests {
"#;
let def: Result<ValidatorDefinition, _> =
serde_yaml::from_str(invalid_suggested_fee_recipient);
yaml_serde::from_str(invalid_suggested_fee_recipient);
assert!(def.is_err());
let valid_suggested_fee_recipient = r#"---
@@ -596,7 +596,7 @@ mod tests {
voting_public_key: "0xaf3c7ddab7e293834710fca2d39d068f884455ede270e0d0293dc818e4f2f0f975355067e8437955cb29aec674e5c9e7"
"#;
let def: ValidatorDefinition = serde_yaml::from_str(valid_suggested_fee_recipient).unwrap();
let def: ValidatorDefinition = yaml_serde::from_str(valid_suggested_fee_recipient).unwrap();
assert_eq!(
def.suggested_fee_recipient,
Some(Address::from_str("0xa2e334e71511686bcfe38bb3ee1ad8f6babcc03d").unwrap())
@@ -613,7 +613,7 @@ mod tests {
voting_keystore_path: ""
voting_public_key: "0xaf3c7ddab7e293834710fca2d39d068f884455ede270e0d0293dc818e4f2f0f975355067e8437955cb29aec674e5c9e7"
"#;
let def: ValidatorDefinition = serde_yaml::from_str(no_gas_limit).unwrap();
let def: ValidatorDefinition = yaml_serde::from_str(no_gas_limit).unwrap();
assert!(def.gas_limit.is_none());
let invalid_gas_limit = r#"---
@@ -626,7 +626,7 @@ mod tests {
voting_public_key: "0xaf3c7ddab7e293834710fca2d39d068f884455ede270e0d0293dc818e4f2f0f975355067e8437955cb29aec674e5c9e7"
"#;
let def: Result<ValidatorDefinition, _> = serde_yaml::from_str(invalid_gas_limit);
let def: Result<ValidatorDefinition, _> = yaml_serde::from_str(invalid_gas_limit);
assert!(def.is_err());
let valid_gas_limit = r#"---
@@ -639,7 +639,7 @@ mod tests {
voting_public_key: "0xaf3c7ddab7e293834710fca2d39d068f884455ede270e0d0293dc818e4f2f0f975355067e8437955cb29aec674e5c9e7"
"#;
let def: ValidatorDefinition = serde_yaml::from_str(valid_gas_limit).unwrap();
let def: ValidatorDefinition = yaml_serde::from_str(valid_gas_limit).unwrap();
assert_eq!(def.gas_limit, Some(35000000));
}
@@ -653,7 +653,7 @@ mod tests {
voting_keystore_path: ""
voting_public_key: "0xaf3c7ddab7e293834710fca2d39d068f884455ede270e0d0293dc818e4f2f0f975355067e8437955cb29aec674e5c9e7"
"#;
let def: ValidatorDefinition = serde_yaml::from_str(no_builder_proposals).unwrap();
let def: ValidatorDefinition = yaml_serde::from_str(no_builder_proposals).unwrap();
assert!(def.builder_proposals.is_none());
let invalid_builder_proposals = r#"---
@@ -666,7 +666,7 @@ mod tests {
voting_public_key: "0xaf3c7ddab7e293834710fca2d39d068f884455ede270e0d0293dc818e4f2f0f975355067e8437955cb29aec674e5c9e7"
"#;
let def: Result<ValidatorDefinition, _> = serde_yaml::from_str(invalid_builder_proposals);
let def: Result<ValidatorDefinition, _> = yaml_serde::from_str(invalid_builder_proposals);
assert!(def.is_err());
let valid_builder_proposals = r#"---
@@ -679,7 +679,7 @@ mod tests {
voting_public_key: "0xaf3c7ddab7e293834710fca2d39d068f884455ede270e0d0293dc818e4f2f0f975355067e8437955cb29aec674e5c9e7"
"#;
let def: ValidatorDefinition = serde_yaml::from_str(valid_builder_proposals).unwrap();
let def: ValidatorDefinition = yaml_serde::from_str(valid_builder_proposals).unwrap();
assert_eq!(def.builder_proposals, Some(true));
}
}

View File

@@ -14,5 +14,5 @@ ethereum_ssz = { workspace = true }
hex = { workspace = true }
serde = { workspace = true }
serde_json = { workspace = true }
serde_yaml = { workspace = true }
types = { workspace = true }
yaml_serde = { workspace = true }

View File

@@ -159,7 +159,7 @@ where
let chain_config = Config::from_chain_spec::<E>(spec);
let mut file = std::fs::File::create(dump_path)
.map_err(|e| format!("Failed to open file for writing chain config: {:?}", e))?;
serde_yaml::to_writer(&mut file, &chain_config)
yaml_serde::to_writer(&mut file, &chain_config)
.map_err(|e| format!("Error serializing config: {:?}", e))?;
}
Ok(())

View File

@@ -12,7 +12,7 @@ ethereum_hashing = { workspace = true }
hex = { workspace = true }
num-bigint = "0.4.2"
serde = { workspace = true }
serde_yaml = { workspace = true }
yaml_serde = { workspace = true }
[dev-dependencies]
base64 = "0.13.0"

View File

@@ -118,7 +118,7 @@ fn string_to_bytes(string: &str) -> Result<Vec<u8>, String> {
pub fn keypairs_from_yaml_file(path: PathBuf) -> Result<Vec<Keypair>, String> {
let file = File::open(path).map_err(|e| format!("Unable to open YAML key file: {}", e))?;
serde_yaml::from_reader::<_, Vec<YamlKeypair>>(file)
yaml_serde::from_reader::<_, Vec<YamlKeypair>>(file)
.map_err(|e| format!("Could not parse YAML: {:?}", e))?
.into_iter()
.map(TryInto::try_into)

View File

@@ -15,11 +15,11 @@ kzg = { workspace = true }
pretty_reqwest_error = { workspace = true }
reqwest = { workspace = true }
sensitive_url = { workspace = true }
serde_yaml = { workspace = true }
sha2 = { workspace = true }
tracing = { workspace = true }
types = { workspace = true }
url = { workspace = true }
yaml_serde = { workspace = true }
[build-dependencies]
eth2_config = { workspace = true }

View File

@@ -46,7 +46,7 @@ ELECTRA_FORK_VERSION: 0x05000064
ELECTRA_FORK_EPOCH: 1337856 # 2025-04-30T14:03:40.000Z
# Fulu
FULU_FORK_VERSION: 0x06000064
FULU_FORK_EPOCH: 18446744073709551615
FULU_FORK_EPOCH: 1714688 # Tue Apr 14 2026 12:06:20 GMT+0000
# Gloas
GLOAS_FORK_VERSION: 0x07000064
GLOAS_FORK_EPOCH: 18446744073709551615
@@ -156,6 +156,11 @@ NUMBER_OF_CUSTODY_GROUPS: 128
DATA_COLUMN_SIDECAR_SUBNET_COUNT: 128
SAMPLES_PER_SLOT: 8
CUSTODY_REQUIREMENT: 4
VALIDATOR_CUSTODY_REQUIREMENT: 8
BALANCE_PER_ADDITIONAL_CUSTODY_GROUP: 32000000000
MAX_REQUEST_DATA_COLUMN_SIDECARS: 16384
# `2**14` (= 16384 epochs, ~15 days)
MIN_EPOCHS_FOR_DATA_COLUMN_SIDECARS_REQUESTS: 16384
MAX_BLOBS_PER_BLOCK_FULU: 12
# Gloas

View File

@@ -101,14 +101,14 @@ impl Eth2NetworkConfig {
/// Instantiates `Self` from a `HardcodedNet`.
fn from_hardcoded_net(net: &HardcodedNet) -> Result<Self, String> {
let config: Config = serde_yaml::from_reader(net.config)
let config: Config = yaml_serde::from_reader(net.config)
.map_err(|e| format!("Unable to parse yaml config: {:?}", e))?;
let kzg_trusted_setup = get_trusted_setup();
Ok(Self {
deposit_contract_deploy_block: serde_yaml::from_reader(net.deploy_block)
deposit_contract_deploy_block: yaml_serde::from_reader(net.deploy_block)
.map_err(|e| format!("Unable to parse deploy block: {:?}", e))?,
boot_enr: Some(
serde_yaml::from_reader(net.boot_enr)
yaml_serde::from_reader(net.boot_enr)
.map_err(|e| format!("Unable to parse boot enr: {:?}", e))?,
),
genesis_state_source: net.genesis_state_source,
@@ -286,7 +286,7 @@ impl Eth2NetworkConfig {
File::create(base_dir.join($file))
.map_err(|e| format!("Unable to create {}: {:?}", $file, e))
.and_then(|mut file| {
let yaml = serde_yaml::to_string(&$variable)
let yaml = yaml_serde::to_string(&$variable)
.map_err(|e| format!("Unable to YAML encode {}: {:?}", $file, e))?;
// Remove the doc header from the YAML file.
@@ -334,7 +334,7 @@ impl Eth2NetworkConfig {
File::open(base_dir.join($file))
.map_err(|e| format!("Unable to open {}: {:?}", $file, e))
.and_then(|file| {
serde_yaml::from_reader(file)
yaml_serde::from_reader(file)
.map_err(|e| format!("Unable to parse {}: {:?}", $file, e))
})?
};

View File

@@ -14,8 +14,8 @@ ethereum_ssz_derive = { workspace = true }
fixed_bytes = { workspace = true }
safe_arith = { workspace = true }
serde = { workspace = true }
serde_yaml = { workspace = true }
smallvec = { workspace = true }
superstruct = { workspace = true }
typenum = { workspace = true }
types = { workspace = true }
yaml_serde = { workspace = true }

View File

@@ -22,5 +22,5 @@ fn main() {
fn write_test_def_to_yaml(filename: &str, def: ForkChoiceTestDefinition) {
let file = File::create(filename).expect("Should be able to open file");
serde_yaml::to_writer(file, &def).expect("Should be able to write YAML to file");
yaml_serde::to_writer(file, &def).expect("Should be able to write YAML to file");
}

View File

@@ -4,8 +4,8 @@ use milhouse::List;
use std::sync::Arc;
use types::{
BeaconStateError, Epoch, EthSpec, ParticipationFlags, ProgressiveBalancesCache, SyncCommittee,
Validator,
consts::altair::{TIMELY_HEAD_FLAG_INDEX, TIMELY_SOURCE_FLAG_INDEX, TIMELY_TARGET_FLAG_INDEX},
state::Validators,
};
/// Provides a summary of validator participation during the epoch.
@@ -26,7 +26,7 @@ pub enum EpochProcessingSummary<E: EthSpec> {
#[derive(PartialEq, Debug)]
pub struct ParticipationEpochSummary<E: EthSpec> {
/// Copy of the validator registry prior to mutation.
validators: List<Validator, E::ValidatorRegistryLimit>,
validators: Validators<E>,
/// Copy of the participation flags for the previous epoch.
previous_epoch_participation: List<ParticipationFlags, E::ValidatorRegistryLimit>,
/// Copy of the participation flags for the current epoch.
@@ -37,7 +37,7 @@ pub struct ParticipationEpochSummary<E: EthSpec> {
impl<E: EthSpec> ParticipationEpochSummary<E> {
pub fn new(
validators: List<Validator, E::ValidatorRegistryLimit>,
validators: Validators<E>,
previous_epoch_participation: List<ParticipationFlags, E::ValidatorRegistryLimit>,
current_epoch_participation: List<ParticipationFlags, E::ValidatorRegistryLimit>,
previous_epoch: Epoch,

View File

@@ -53,7 +53,6 @@ rusqlite = { workspace = true, optional = true }
safe_arith = { workspace = true }
serde = { workspace = true, features = ["rc"] }
serde_json = { workspace = true }
serde_yaml = { workspace = true }
smallvec = { workspace = true }
ssz_types = { workspace = true }
superstruct = { workspace = true }
@@ -64,6 +63,7 @@ tracing = { workspace = true }
tree_hash = { workspace = true }
tree_hash_derive = { workspace = true }
typenum = { workspace = true }
yaml_serde = { workspace = true }
[dev-dependencies]
beacon_chain = { workspace = true }

View File

@@ -1616,7 +1616,7 @@ impl ChainSpec {
* Fulu hard fork params
*/
fulu_fork_version: [0x06, 0x00, 0x00, 0x64],
fulu_fork_epoch: None,
fulu_fork_epoch: Some(Epoch::new(1714688)),
custody_requirement: 4,
number_of_custody_groups: 128,
data_column_sidecar_subnet_count: 128,
@@ -1686,8 +1686,7 @@ impl ChainSpec {
* Networking Fulu specific
*/
blob_schedule: BlobSchedule::default(),
min_epochs_for_data_column_sidecars_requests:
default_min_epochs_for_data_column_sidecars_requests(),
min_epochs_for_data_column_sidecars_requests: 16384,
max_data_columns_by_root_request: default_data_columns_by_root_request(),
max_payload_envelopes_by_root_request: default_max_payload_envelopes_by_root_request(),
@@ -2532,7 +2531,7 @@ impl Config {
pub fn from_file(filename: &Path) -> Result<Self, String> {
let f = File::open(filename)
.map_err(|e| format!("Error opening spec at {}: {:?}", filename.display(), e))?;
serde_yaml::from_reader(f)
yaml_serde::from_reader(f)
.map_err(|e| format!("Error parsing spec at {}: {:?}", filename.display(), e))
}
@@ -2870,7 +2869,7 @@ mod yaml_tests {
let yamlconfig = Config::from_chain_spec::<MinimalEthSpec>(&minimal_spec);
// write fresh minimal config to file
serde_yaml::to_writer(writer, &yamlconfig).expect("failed to write or serialize");
yaml_serde::to_writer(writer, &yamlconfig).expect("failed to write or serialize");
let reader = File::options()
.read(true)
@@ -2878,7 +2877,7 @@ mod yaml_tests {
.open(tmp_file.as_ref())
.expect("error while opening the file");
// deserialize minimal config from file
let from: Config = serde_yaml::from_reader(reader).expect("error while deserializing");
let from: Config = yaml_serde::from_reader(reader).expect("error while deserializing");
assert_eq!(from, yamlconfig);
}
@@ -2892,14 +2891,14 @@ mod yaml_tests {
.expect("error opening file");
let mainnet_spec = ChainSpec::mainnet();
let yamlconfig = Config::from_chain_spec::<MainnetEthSpec>(&mainnet_spec);
serde_yaml::to_writer(writer, &yamlconfig).expect("failed to write or serialize");
yaml_serde::to_writer(writer, &yamlconfig).expect("failed to write or serialize");
let reader = File::options()
.read(true)
.write(false)
.open(tmp_file.as_ref())
.expect("error while opening the file");
let from: Config = serde_yaml::from_reader(reader).expect("error while deserializing");
let from: Config = yaml_serde::from_reader(reader).expect("error while deserializing");
assert_eq!(from, yamlconfig);
}
@@ -2961,7 +2960,7 @@ mod yaml_tests {
MAX_BLOBS_PER_BLOCK: 20
"#;
let config: Config =
serde_yaml::from_str(spec_contents).expect("error while deserializing");
yaml_serde::from_str(spec_contents).expect("error while deserializing");
let spec =
ChainSpec::from_config::<MainnetEthSpec>(&config).expect("error while creating spec");
@@ -3043,11 +3042,11 @@ mod yaml_tests {
assert_eq!(spec.max_blobs_per_block_within_fork(ForkName::Fulu), 20);
// Check that serialization is in ascending order
let yaml = serde_yaml::to_string(&spec.blob_schedule).expect("should serialize");
let yaml = yaml_serde::to_string(&spec.blob_schedule).expect("should serialize");
// Deserialize back to Vec<BlobParameters> to check order
let deserialized: Vec<BlobParameters> =
serde_yaml::from_str(&yaml).expect("should deserialize");
yaml_serde::from_str(&yaml).expect("should deserialize");
// Should be in ascending order by epoch
assert!(
@@ -3114,7 +3113,7 @@ mod yaml_tests {
MAX_BLOBS_PER_BLOCK: 300
"#;
let config: Config =
serde_yaml::from_str(spec_contents).expect("error while deserializing");
yaml_serde::from_str(spec_contents).expect("error while deserializing");
let spec =
ChainSpec::from_config::<MainnetEthSpec>(&config).expect("error while creating spec");
@@ -3204,7 +3203,7 @@ mod yaml_tests {
SAMPLES_PER_SLOT: 8
"#;
let chain_spec: Config = serde_yaml::from_str(spec).unwrap();
let chain_spec: Config = yaml_serde::from_str(spec).unwrap();
// Asserts that `chain_spec.$name` and `default_$name()` are equal.
macro_rules! check_default {

View File

@@ -174,7 +174,7 @@ mod test {
yamlconfig.extra_fields_mut().insert(k3.into(), v3.into());
yamlconfig.extra_fields_mut().insert(k4.into(), v4);
serde_yaml::to_writer(writer, &yamlconfig).expect("failed to write or serialize");
yaml_serde::to_writer(writer, &yamlconfig).expect("failed to write or serialize");
let reader = File::options()
.read(true)
@@ -182,7 +182,7 @@ mod test {
.open(tmp_file.as_ref())
.expect("error while opening the file");
let from: ConfigAndPresetGloas =
serde_yaml::from_reader(reader).expect("error while deserializing");
yaml_serde::from_reader(reader).expect("error while deserializing");
assert_eq!(ConfigAndPreset::Gloas(from), yamlconfig);
}

View File

@@ -359,7 +359,7 @@ mod test {
fn preset_from_file<T: DeserializeOwned>(preset_name: &str, filename: &str) -> T {
let f = File::open(presets_base_path().join(preset_name).join(filename))
.expect("preset file exists");
serde_yaml::from_reader(f).unwrap()
yaml_serde::from_reader(f).unwrap()
}
fn preset_test<E: EthSpec>() {

View File

@@ -14,6 +14,7 @@ use serde::{Deserialize, Deserializer, Serialize};
use ssz::{Decode, DecodeError, Encode, ssz_encode};
use ssz_derive::{Decode, Encode};
use ssz_types::{BitVector, FixedVector};
use std::collections::BTreeMap;
use superstruct::superstruct;
use swap_or_not_shuffle::compute_shuffled_index;
use test_random_derive::TestRandom;
@@ -71,7 +72,8 @@ const MAX_RANDOM_VALUE: u64 = (1 << 16) - 1;
// Spec: https://github.com/ethereum/consensus-specs/blob/1937aff86b41b5171a9bc3972515986f1bbbf303/specs/phase0/weak-subjectivity.md?plain=1#L50-L71
const SAFETY_DECAY: u64 = 10;
pub type Validators<E> = List<Validator, <E as EthSpec>::ValidatorRegistryLimit>;
pub type Validators<E> =
List<Validator, <E as EthSpec>::ValidatorRegistryLimit, BTreeMap<usize, Validator>>;
pub type Balances<E> = List<u64, <E as EthSpec>::ValidatorRegistryLimit>;
#[derive(Debug, PartialEq, Clone)]
@@ -477,7 +479,7 @@ where
// Registry
#[compare_fields(as_iter)]
#[test_random(default)]
pub validators: List<Validator, E::ValidatorRegistryLimit>,
pub validators: Validators<E>,
#[serde(with = "ssz_types::serde_utils::quoted_u64_var_list")]
#[compare_fields(as_iter)]
#[test_random(default)]

View File

@@ -17,7 +17,7 @@ pub use balance::Balance;
pub use beacon_state::{
BeaconState, BeaconStateAltair, BeaconStateBase, BeaconStateBellatrix, BeaconStateCapella,
BeaconStateDeneb, BeaconStateElectra, BeaconStateError, BeaconStateFulu, BeaconStateGloas,
BeaconStateHash, BeaconStateRef, CACHED_EPOCHS, DEFAULT_PRE_ELECTRA_WS_PERIOD,
BeaconStateHash, BeaconStateRef, CACHED_EPOCHS, DEFAULT_PRE_ELECTRA_WS_PERIOD, Validators,
};
pub use committee_cache::{
CommitteeCache, compute_committee_index_in_epoch, compute_committee_range_in_epoch,

View File

@@ -12,6 +12,7 @@ deny = [
{ crate = "ark-ff", reason = "present in Cargo.lock but not needed by Lighthouse" },
{ crate = "openssl", reason = "non-Rust dependency, use rustls instead" },
{ crate = "c-kzg", reason = "non-Rust dependency, use rust_eth_kzg instead" },
{ crate = "serde_yaml", reason = "deprecated, use yaml_serde instead" },
{ crate = "strum", deny-multiple-versions = true, reason = "takes a long time to compile" },
{ crate = "reqwest", deny-multiple-versions = true, reason = "takes a long time to compile" },
{ crate = "aes", deny-multiple-versions = true, reason = "takes a long time to compile" },

View File

@@ -35,7 +35,6 @@ network_utils = { workspace = true }
rayon = { workspace = true }
serde = { workspace = true }
serde_json = { workspace = true }
serde_yaml = { workspace = true }
snap = { workspace = true }
state_processing = { workspace = true }
store = { workspace = true }
@@ -44,6 +43,7 @@ tracing-subscriber = { workspace = true }
tree_hash = { workspace = true }
types = { workspace = true }
validator_dir = { workspace = true }
yaml_serde = { workspace = true }
[target.'cfg(not(target_os = "windows"))'.dependencies]
malloc_utils = { workspace = true, features = ["jemalloc"] }

View File

@@ -141,7 +141,7 @@ fn decode_and_print<T: Serialize>(
OutputFormat::Yaml => {
println!(
"{}",
serde_yaml::to_string(&item)
yaml_serde::to_string(&item)
.map_err(|e| format!("Unable to write object to YAML: {e:?}"))?
);
}

View File

@@ -62,7 +62,6 @@ opentelemetry-otlp = { workspace = true }
opentelemetry_sdk = { workspace = true }
serde = { workspace = true }
serde_json = { workspace = true }
serde_yaml = { workspace = true }
slasher = { workspace = true }
store = { workspace = true }
task_executor = { workspace = true }
@@ -73,6 +72,7 @@ tracing_samplers = { workspace = true }
types = { workspace = true }
validator_client = { workspace = true }
validator_manager = { path = "../validator_manager" }
yaml_serde = { workspace = true }
[target.'cfg(not(target_os = "windows"))'.dependencies]
malloc_utils = { workspace = true, features = ["jemalloc"] }

View File

@@ -65,7 +65,7 @@ pub trait CommandLineTestExec {
let spec_file =
File::open(tmp_chain_config_path).expect("Unable to open dumped chain spec");
let chain_config: Config =
serde_yaml::from_reader(spec_file).expect("Unable to deserialize config");
yaml_serde::from_reader(spec_file).expect("Unable to deserialize config");
CompletedTest::new(config, chain_config, tmp_dir)
}
@@ -102,7 +102,7 @@ pub trait CommandLineTestExec {
let spec_file =
File::open(tmp_chain_config_path).expect("Unable to open dumped chain spec");
let chain_config: Config =
serde_yaml::from_reader(spec_file).expect("Unable to deserialize config");
yaml_serde::from_reader(spec_file).expect("Unable to deserialize config");
CompletedTest::new(config, chain_config, tmp_dir)
}

View File

@@ -32,7 +32,6 @@ rayon = { workspace = true }
serde = { workspace = true }
serde_json = { workspace = true }
serde_repr = { workspace = true }
serde_yaml = { workspace = true }
snap = { workspace = true }
ssz_types = { workspace = true }
state_processing = { workspace = true }
@@ -41,3 +40,4 @@ tree_hash = { workspace = true }
tree_hash_derive = { workspace = true }
typenum = { workspace = true }
types = { workspace = true }
yaml_serde = { workspace = true }

View File

@@ -33,14 +33,14 @@ pub fn log_file_access<P: AsRef<Path>>(file_accessed: P) {
}
pub fn yaml_decode<T: serde::de::DeserializeOwned>(string: &str) -> Result<T, Error> {
serde_yaml::from_str(string).map_err(|e| Error::FailedToParseTest(format!("{:?}", e)))
yaml_serde::from_str(string).map_err(|e| Error::FailedToParseTest(format!("{:?}", e)))
}
pub fn context_yaml_decode<'de, T, C>(string: &'de str, context: C) -> Result<T, Error>
where
T: ContextDeserialize<'de, C>,
{
let deserializer = serde_yaml::Deserializer::from_str(string);
let deserializer = yaml_serde::Deserializer::from_str(string);
T::context_deserialize(deserializer, context)
.map_err(|e| Error::FailedToParseTest(format!("{:?}", e)))
}

View File

@@ -23,7 +23,6 @@ parking_lot = { workspace = true }
reqwest = { workspace = true }
serde = { workspace = true }
serde_json = { workspace = true }
serde_yaml = { workspace = true }
slashing_protection = { workspace = true }
slot_clock = { workspace = true }
ssz_types = { workspace = true }
@@ -33,4 +32,5 @@ tokio = { workspace = true }
types = { workspace = true }
url = { workspace = true }
validator_store = { workspace = true }
yaml_serde = { workspace = true }
zip = { workspace = true }

View File

@@ -210,7 +210,7 @@ mod tests {
};
let key_config_file =
File::create(keystore_dir.path().join("key-config.yaml")).unwrap();
serde_yaml::to_writer(key_config_file, &key_config).unwrap();
yaml_serde::to_writer(key_config_file, &key_config).unwrap();
let tls_keystore_file = tls_dir().join("web3signer").join("key.p12");
let tls_keystore_password_file = tls_dir().join("web3signer").join("password.txt");