diff --git a/Cargo.lock b/Cargo.lock index 481808b41f..6ed7bfd0b6 100644 --- a/Cargo.lock +++ b/Cargo.lock @@ -34,6 +34,7 @@ dependencies = [ name = "account_utils" version = "0.1.0" dependencies = [ + "bls", "eth2_keystore", "eth2_wallet", "filesystem", @@ -137,14 +138,14 @@ checksum = "4bc32535569185cbcb6ad5fa64d989a47bccb9a08e27284b1f2a3ccf16e6d010" dependencies = [ "alloy-primitives", "num_enum", - "strum 0.27.2", + "strum", ] [[package]] name = "alloy-consensus" -version = "1.0.42" +version = "1.1.3" source = "registry+https://github.com/rust-lang/crates.io-index" -checksum = "3abecb92ba478a285fbf5689100dbafe4003ded4a09bf4b5ef62cca87cd4f79e" +checksum = "2e318e25fb719e747a7e8db1654170fc185024f3ed5b10f86c08d448a912f6e2" dependencies = [ "alloy-eips", "alloy-primitives", @@ -153,6 +154,7 @@ dependencies = [ "alloy-trie", "alloy-tx-macros", "auto_impl", + "borsh", "c-kzg", "derive_more 2.0.1", "either", @@ -168,9 +170,9 @@ dependencies = [ [[package]] name = "alloy-consensus-any" -version = "1.0.42" +version = "1.1.3" source = "registry+https://github.com/rust-lang/crates.io-index" -checksum = "2e864d4f11d1fb8d3ac2fd8f3a15f1ee46d55ec6d116b342ed1b2cb737f25894" +checksum = "364380a845193a317bcb7a5398fc86cdb66c47ebe010771dde05f6869bf9e64a" dependencies = [ "alloy-consensus", "alloy-eips", @@ -191,8 +193,6 @@ dependencies = [ "alloy-sol-type-parser", "alloy-sol-types", "itoa", - "serde", - "serde_json", "winnow", ] @@ -236,9 +236,9 @@ dependencies = [ [[package]] name = "alloy-eips" -version = "1.1.1" +version = "1.1.3" source = "registry+https://github.com/rust-lang/crates.io-index" -checksum = "7e867b5fd52ed0372a95016f3a37cbff95a9d5409230fbaef2d8ea00e8618098" +checksum = "a4c4d7c5839d9f3a467900c625416b24328450c65702eb3d8caff8813e4d1d33" dependencies = [ "alloy-eip2124", "alloy-eip2930", @@ -271,9 +271,9 @@ dependencies = [ [[package]] name = "alloy-json-rpc" -version = "1.1.1" +version = "1.1.3" source = "registry+https://github.com/rust-lang/crates.io-index" -checksum = "dcab4c51fb1273e3b0f59078e0cdf8aa99f697925b09f0d2055c18be46b4d48c" +checksum = "f72cf87cda808e593381fb9f005ffa4d2475552b7a6c5ac33d087bf77d82abd0" dependencies = [ "alloy-primitives", "alloy-sol-types", @@ -286,9 +286,9 @@ dependencies = [ [[package]] name = "alloy-network" -version = "1.0.42" +version = "1.1.3" source = "registry+https://github.com/rust-lang/crates.io-index" -checksum = "d5d6ed73d440bae8f27771b7cd507fa8f10f19ddf0b8f67e7622a52e0dbf798e" +checksum = "12aeb37b6f2e61b93b1c3d34d01ee720207c76fe447e2a2c217e433ac75b17f5" dependencies = [ "alloy-consensus", "alloy-consensus-any", @@ -312,9 +312,9 @@ dependencies = [ [[package]] name = "alloy-network-primitives" -version = "1.0.42" +version = "1.1.3" source = "registry+https://github.com/rust-lang/crates.io-index" -checksum = "219dccd2cf753a43bd9b0fbb7771a16927ffdb56e43e3a15755bef1a74d614aa" +checksum = "abd29ace62872083e30929cd9b282d82723196d196db589f3ceda67edcc05552" dependencies = [ "alloy-consensus", "alloy-eips", @@ -355,9 +355,9 @@ dependencies = [ [[package]] name = "alloy-provider" -version = "1.0.42" +version = "1.1.3" source = "registry+https://github.com/rust-lang/crates.io-index" -checksum = "f0ef8cbc2b68e2512acf04b2d296c05c98a661bc460462add6414528f4ff3d9b" +checksum = "9b710636d7126e08003b8217e24c09f0cca0b46d62f650a841736891b1ed1fc1" dependencies = [ "alloy-chains", "alloy-consensus", @@ -416,9 +416,9 @@ dependencies = [ [[package]] name = "alloy-rpc-client" -version = "1.1.1" +version = "1.1.3" source = "registry+https://github.com/rust-lang/crates.io-index" -checksum = "e7c2630fde9ff6033a780635e1af6ef40e92d74a9cacb8af3defc1b15cfebca5" +checksum = "d0882e72d2c1c0c79dcf4ab60a67472d3f009a949f774d4c17d0bdb669cfde05" dependencies = [ "alloy-json-rpc", "alloy-primitives", @@ -439,9 +439,9 @@ dependencies = [ [[package]] name = "alloy-rpc-types-any" -version = "1.0.42" +version = "1.1.3" source = "registry+https://github.com/rust-lang/crates.io-index" -checksum = "425e14ee32eb8b7edd6a2247fe0ed640785e6eba75af27db27f1e6220c15ef0d" +checksum = "6a63fb40ed24e4c92505f488f9dd256e2afaed17faa1b7a221086ebba74f4122" dependencies = [ "alloy-consensus-any", "alloy-rpc-types-eth", @@ -450,9 +450,9 @@ dependencies = [ [[package]] name = "alloy-rpc-types-eth" -version = "1.0.42" +version = "1.1.3" source = "registry+https://github.com/rust-lang/crates.io-index" -checksum = "0185f68a0f8391ab996d335a887087d7ccdbc97952efab3516f6307d456ba2cd" +checksum = "9eae0c7c40da20684548cbc8577b6b7447f7bf4ddbac363df95e3da220e41e72" dependencies = [ "alloy-consensus", "alloy-consensus-any", @@ -471,9 +471,9 @@ dependencies = [ [[package]] name = "alloy-serde" -version = "1.1.1" +version = "1.1.3" source = "registry+https://github.com/rust-lang/crates.io-index" -checksum = "01e856112bfa0d9adc85bd7c13db03fad0e71d1d6fb4c2010e475b6718108236" +checksum = "c0df1987ed0ff2d0159d76b52e7ddfc4e4fbddacc54d2fbee765e0d14d7c01b5" dependencies = [ "alloy-primitives", "serde", @@ -482,9 +482,9 @@ dependencies = [ [[package]] name = "alloy-signer" -version = "1.1.1" +version = "1.1.3" source = "registry+https://github.com/rust-lang/crates.io-index" -checksum = "66a4f629da632d5279bbc5731634f0f5c9484ad9c4cad0cd974d9669dc1f46d6" +checksum = "6ff69deedee7232d7ce5330259025b868c5e6a52fa8dffda2c861fb3a5889b24" dependencies = [ "alloy-primitives", "async-trait", @@ -497,9 +497,9 @@ dependencies = [ [[package]] name = "alloy-signer-local" -version = "1.0.42" +version = "1.1.3" source = "registry+https://github.com/rust-lang/crates.io-index" -checksum = "590dcaeb290cdce23155e68af4791d093afc3754b1a331198a25d2d44c5456e8" +checksum = "72cfe0be3ec5a8c1a46b2e5a7047ed41121d360d97f4405bb7c1c784880c86cb" dependencies = [ "alloy-consensus", "alloy-network", @@ -533,7 +533,7 @@ checksum = "6d792e205ed3b72f795a8044c52877d2e6b6e9b1d13f431478121d8d4eaa9028" dependencies = [ "alloy-sol-macro-input", "const-hex", - "heck 0.5.0", + "heck", "indexmap 2.12.0", "proc-macro-error2", "proc-macro2", @@ -551,7 +551,7 @@ checksum = "0bd1247a8f90b465ef3f1207627547ec16940c35597875cdc09c49d58b19693c" dependencies = [ "const-hex", "dunce", - "heck 0.5.0", + "heck", "macro-string", "proc-macro2", "quote", @@ -583,9 +583,9 @@ dependencies = [ [[package]] name = "alloy-transport" -version = "1.1.1" +version = "1.1.3" source = "registry+https://github.com/rust-lang/crates.io-index" -checksum = "fe215a2f9b51d5f1aa5c8cf22c8be8cdb354934de09c9a4e37aefb79b77552fd" +checksum = "be98b07210d24acf5b793c99b759e9a696e4a2e67593aec0487ae3b3e1a2478c" dependencies = [ "alloy-json-rpc", "auto_impl", @@ -606,9 +606,9 @@ dependencies = [ [[package]] name = "alloy-transport-http" -version = "1.1.1" +version = "1.1.3" source = "registry+https://github.com/rust-lang/crates.io-index" -checksum = "dc1b37b1a30d23deb3a8746e882c70b384c574d355bc2bbea9ea918b0c31366e" +checksum = "4198a1ee82e562cab85e7f3d5921aab725d9bd154b6ad5017f82df1695877c97" dependencies = [ "alloy-json-rpc", "alloy-transport", @@ -637,9 +637,9 @@ dependencies = [ [[package]] name = "alloy-tx-macros" -version = "1.1.1" +version = "1.1.3" source = "registry+https://github.com/rust-lang/crates.io-index" -checksum = "7ccf423f6de62e8ce1d6c7a11fb7508ae3536d02e0d68aaeb05c8669337d0937" +checksum = "333544408503f42d7d3792bfc0f7218b643d968a03d2c0ed383ae558fb4a76d0" dependencies = [ "darling 0.21.3", "proc-macro2", @@ -1238,6 +1238,7 @@ dependencies = [ "ethereum_ssz", "ethereum_ssz_derive", "execution_layer", + "fixed_bytes", "fork_choice", "futures", "genesis", @@ -1252,6 +1253,7 @@ dependencies = [ "maplit", "merkle_proof", "metrics", + "milhouse", "mockall", "mockall_double", "once_cell", @@ -1271,7 +1273,7 @@ dependencies = [ "ssz_types", "state_processing", "store", - "strum 0.24.1", + "strum", "superstruct", "task_executor", "tempfile", @@ -1280,6 +1282,7 @@ dependencies = [ "tracing", "tree_hash", "tree_hash_derive", + "typenum", "types", "zstd 0.13.3", ] @@ -1290,6 +1293,7 @@ version = "8.0.1" dependencies = [ "account_utils", "beacon_chain", + "bls", "clap", "clap_utils", "client", @@ -1310,7 +1314,7 @@ dependencies = [ "serde_json", "slasher", "store", - "strum 0.24.1", + "strum", "task_executor", "tracing", "types", @@ -1320,6 +1324,7 @@ dependencies = [ name = "beacon_node_fallback" version = "0.1.0" dependencies = [ + "bls", "clap", "eth2", "futures", @@ -1327,7 +1332,7 @@ dependencies = [ "sensitive_url", "serde", "slot_clock", - "strum 0.24.1", + "strum", "task_executor", "tokio", "tracing", @@ -1350,7 +1355,7 @@ dependencies = [ "parking_lot", "serde", "slot_clock", - "strum 0.24.1", + "strum", "task_executor", "tokio", "tokio-util", @@ -1592,6 +1597,8 @@ dependencies = [ name = "builder_client" version = "0.1.0" dependencies = [ + "bls", + "context_deserialize", "eth2", "ethereum_ssz", "lighthouse_version", @@ -1861,7 +1868,7 @@ version = "4.5.49" source = "registry+https://github.com/rust-lang/crates.io-index" checksum = "2a0b5487afeab2deb2ff4e03a807ad1a03ac532ff5a2cee5d86884440c7f7671" dependencies = [ - "heck 0.5.0", + "heck", "proc-macro2", "quote", "syn 2.0.110", @@ -2517,7 +2524,7 @@ dependencies = [ "hex", "serde", "store", - "strum 0.24.1", + "strum", "tracing", "types", ] @@ -2546,6 +2553,7 @@ dependencies = [ "alloy-dyn-abi", "alloy-json-abi", "alloy-primitives", + "bls", "ethereum_ssz", "hex", "reqwest", @@ -2756,6 +2764,7 @@ name = "doppelganger_service" version = "0.1.0" dependencies = [ "beacon_node_fallback", + "bls", "environment", "eth2", "futures", @@ -2864,16 +2873,19 @@ dependencies = [ "hex", "kzg", "logging", + "milhouse", "rayon", "serde", "serde_json", "serde_repr", "serde_yaml", "snap", + "ssz_types", "state_processing", "swap_or_not_shuffle", "tree_hash", "tree_hash_derive", + "typenum", "types", ] @@ -2901,7 +2913,9 @@ name = "eip_3076" version = "0.1.0" dependencies = [ "arbitrary", + "bls", "ethereum_serde_utils", + "fixed_bytes", "serde", "serde_json", "tempfile", @@ -3057,7 +3071,7 @@ version = "0.6.1" source = "registry+https://github.com/rust-lang/crates.io-index" checksum = "a1e6a265c649f3f5979b601d26f1d05ada116434c87741c9493cb56218f76cbc" dependencies = [ - "heck 0.5.0", + "heck", "proc-macro2", "quote", "syn 2.0.110", @@ -3125,20 +3139,17 @@ dependencies = [ name = "eth2" version = "0.1.0" dependencies = [ + "bls", "context_deserialize", "educe", "eip_3076", - "either", - "enr", "eth2_keystore", "ethereum_serde_utils", "ethereum_ssz", "ethereum_ssz_derive", "futures", "futures-util", - "libp2p-identity", "mediatype", - "multiaddr", "pretty_reqwest_error", "proto_array", "rand 0.9.2", @@ -3148,6 +3159,7 @@ dependencies = [ "serde", "serde_json", "ssz_types", + "superstruct", "test_random_derive", "tokio", "types", @@ -3217,6 +3229,7 @@ dependencies = [ "discv5", "eth2_config", "ethereum_ssz", + "fixed_bytes", "kzg", "pretty_reqwest_error", "reqwest", @@ -3357,8 +3370,10 @@ dependencies = [ "alloy-rpc-types-eth", "alloy-signer-local", "async-channel 1.9.0", + "bls", "deposit_contract", "execution_layer", + "fixed_bytes", "fork_choice", "futures", "hex", @@ -3370,6 +3385,7 @@ dependencies = [ "task_executor", "tempfile", "tokio", + "typenum", "types", ] @@ -3382,6 +3398,7 @@ dependencies = [ "alloy-rlp", "alloy-rpc-types-eth", "arc-swap", + "bls", "builder_client", "bytes", "eth2", @@ -3410,7 +3427,7 @@ dependencies = [ "slot_clock", "ssz_types", "state_processing", - "strum 0.24.1", + "strum", "superstruct", "task_executor", "tempfile", @@ -3420,6 +3437,7 @@ dependencies = [ "tree_hash", "tree_hash_derive", "triehash", + "typenum", "types", "warp", "zeroize", @@ -3593,6 +3611,7 @@ dependencies = [ "beacon_chain", "ethereum_ssz", "ethereum_ssz_derive", + "fixed_bytes", "logging", "metrics", "proto_array", @@ -3783,6 +3802,7 @@ dependencies = [ name = "genesis" version = "0.2.0" dependencies = [ + "bls", "ethereum_hashing", "ethereum_ssz", "int_to_bytes", @@ -4037,12 +4057,6 @@ dependencies = [ "psutil", ] -[[package]] -name = "heck" -version = "0.4.1" -source = "registry+https://github.com/rust-lang/crates.io-index" -checksum = "95505c38b4572b2d910cecb0281560f54b440a19336cbbcb27bf6ce6adc6f5a8" - [[package]] name = "heck" version = "0.5.0" @@ -4228,14 +4242,17 @@ version = "0.1.0" dependencies = [ "beacon_chain", "beacon_processor", + "bls", "bs58 0.4.0", "bytes", + "context_deserialize", "directory", "either", "eth2", "ethereum_serde_utils", "ethereum_ssz", "execution_layer", + "fixed_bytes", "futures", "genesis", "health_metrics", @@ -4942,6 +4959,7 @@ dependencies = [ "ethereum_hashing", "ethereum_ssz", "execution_layer", + "fixed_bytes", "hex", "lighthouse_network", "lighthouse_version", @@ -5331,7 +5349,7 @@ version = "0.35.1" source = "registry+https://github.com/rust-lang/crates.io-index" checksum = "dd297cf53f0cb3dee4d2620bb319ae47ef27c702684309f682bdb7e55a18ae9c" dependencies = [ - "heck 0.5.0", + "heck", "quote", "syn 2.0.110", ] @@ -5491,6 +5509,7 @@ dependencies = [ "alloy-primitives", "alloy-rlp", "async-channel 1.9.0", + "bls", "bytes", "delay_map", "directory", @@ -5500,6 +5519,7 @@ dependencies = [ "eth2", "ethereum_ssz", "ethereum_ssz_derive", + "fixed_bytes", "fnv", "futures", "hex", @@ -5524,7 +5544,7 @@ dependencies = [ "smallvec", "snap", "ssz_types", - "strum 0.24.1", + "strum", "superstruct", "task_executor", "tempfile", @@ -5532,6 +5552,7 @@ dependencies = [ "tokio-util", "tracing", "tracing-subscriber", + "typenum", "types", "unsigned-varint 0.8.0", ] @@ -5546,6 +5567,7 @@ version = "0.1.0" dependencies = [ "account_utils", "beacon_node_fallback", + "bls", "doppelganger_service", "either", "environment", @@ -6213,6 +6235,7 @@ dependencies = [ "eth2_network_config", "ethereum_ssz", "execution_layer", + "fixed_bytes", "fnv", "futures", "genesis", @@ -6239,12 +6262,13 @@ dependencies = [ "smallvec", "ssz_types", "store", - "strum 0.24.1", + "strum", "task_executor", "tokio", "tokio-stream", "tracing", "tracing-subscriber", + "typenum", "types", ] @@ -6649,9 +6673,11 @@ version = "0.2.0" dependencies = [ "beacon_chain", "bitvec", + "bls", "educe", "ethereum_ssz", "ethereum_ssz_derive", + "fixed_bytes", "itertools 0.10.5", "maplit", "metrics", @@ -6661,7 +6687,9 @@ dependencies = [ "serde", "state_processing", "store", + "superstruct", "tokio", + "typenum", "types", ] @@ -7159,6 +7187,7 @@ version = "0.2.0" dependencies = [ "ethereum_ssz", "ethereum_ssz_derive", + "fixed_bytes", "safe_arith", "serde", "serde_yaml", @@ -8330,6 +8359,7 @@ dependencies = [ name = "signing_method" version = "0.1.0" dependencies = [ + "bls", "eth2_keystore", "ethereum_serde_utils", "lockfile", @@ -8385,6 +8415,7 @@ dependencies = [ "tokio", "tracing", "tracing-subscriber", + "typenum", "types", ] @@ -8399,11 +8430,13 @@ name = "slasher" version = "0.1.0" dependencies = [ "bincode", + "bls", "byteorder", "educe", "ethereum_ssz", "ethereum_ssz_derive", "filesystem", + "fixed_bytes", "flate2", "libmdbx", "lmdb-rkv", @@ -8418,11 +8451,12 @@ dependencies = [ "safe_arith", "serde", "ssz_types", - "strum 0.24.1", + "strum", "tempfile", "tracing", "tree_hash", "tree_hash_derive", + "typenum", "types", ] @@ -8448,9 +8482,11 @@ name = "slashing_protection" version = "0.1.0" dependencies = [ "arbitrary", + "bls", "eip_3076", "ethereum_serde_utils", "filesystem", + "fixed_bytes", "r2d2", "r2d2_sqlite", "rayon", @@ -8576,11 +8612,13 @@ dependencies = [ "ethereum_hashing", "ethereum_ssz", "ethereum_ssz_derive", + "fixed_bytes", "int_to_bytes", "integer-sqrt", "itertools 0.10.5", "merkle_proof", "metrics", + "milhouse", "rand 0.9.2", "rayon", "safe_arith", @@ -8590,6 +8628,7 @@ dependencies = [ "tokio", "tracing", "tree_hash", + "typenum", "types", ] @@ -8598,7 +8637,9 @@ name = "state_transition_vectors" version = "0.1.0" dependencies = [ "beacon_chain", + "bls", "ethereum_ssz", + "fixed_bytes", "state_processing", "tokio", "types", @@ -8621,11 +8662,13 @@ dependencies = [ "directory", "ethereum_ssz", "ethereum_ssz_derive", + "fixed_bytes", "itertools 0.10.5", "leveldb", "logging", "lru 0.12.5", "metrics", + "milhouse", "parking_lot", "rand 0.9.2", "redb", @@ -8634,11 +8677,12 @@ dependencies = [ "smallvec", "ssz_types", "state_processing", - "strum 0.24.1", + "strum", "superstruct", "tempfile", "tracing", "tracing-subscriber", + "typenum", "types", "xdelta3", "zstd 0.13.3", @@ -8656,35 +8700,13 @@ version = "0.11.1" source = "registry+https://github.com/rust-lang/crates.io-index" checksum = "7da8b5736845d9f2fcb837ea5d9e2628564b3b043a70948a3f0b778838c5fb4f" -[[package]] -name = "strum" -version = "0.24.1" -source = "registry+https://github.com/rust-lang/crates.io-index" -checksum = "063e6045c0e62079840579a7e47a355ae92f60eb74daaf156fb1e84ba164e63f" -dependencies = [ - "strum_macros 0.24.3", -] - [[package]] name = "strum" version = "0.27.2" source = "registry+https://github.com/rust-lang/crates.io-index" checksum = "af23d6f6c1a224baef9d3f61e287d2761385a5b88fdab4eb4c6f11aeb54c4bcf" dependencies = [ - "strum_macros 0.27.2", -] - -[[package]] -name = "strum_macros" -version = "0.24.3" -source = "registry+https://github.com/rust-lang/crates.io-index" -checksum = "1e385be0d24f186b4ce2f9982191e7101bb737312ad61c1f2f984f34bcf85d59" -dependencies = [ - "heck 0.4.1", - "proc-macro2", - "quote", - "rustversion", - "syn 1.0.109", + "strum_macros", ] [[package]] @@ -8693,7 +8715,7 @@ version = "0.27.2" source = "registry+https://github.com/rust-lang/crates.io-index" checksum = "7695ce3845ea4b33927c055a39dc438a45b059f7c1b3d91d38d10355fb8cbca7" dependencies = [ - "heck 0.5.0", + "heck", "proc-macro2", "quote", "syn 2.0.110", @@ -8898,7 +8920,7 @@ name = "test_random_derive" version = "0.2.0" dependencies = [ "quote", - "syn 1.0.109", + "syn 2.0.110", ] [[package]] @@ -9551,6 +9573,7 @@ dependencies = [ "tracing", "tree_hash", "tree_hash_derive", + "typenum", ] [[package]] @@ -9774,6 +9797,7 @@ dependencies = [ "eth2_keystore", "ethereum_serde_utils", "filesystem", + "fixed_bytes", "futures", "graffiti_file", "health_metrics", @@ -9790,6 +9814,7 @@ dependencies = [ "signing_method", "slashing_protection", "slot_clock", + "ssz_types", "sysinfo", "system_health", "task_executor", @@ -9797,6 +9822,7 @@ dependencies = [ "tokio", "tokio-stream", "tracing", + "typenum", "types", "url", "validator_dir", @@ -9834,6 +9860,7 @@ version = "0.1.0" dependencies = [ "account_utils", "beacon_chain", + "bls", "clap", "clap_utils", "educe", @@ -9890,6 +9917,7 @@ dependencies = [ name = "validator_store" version = "0.1.0" dependencies = [ + "bls", "eth2", "slashing_protection", "types", @@ -10131,10 +10159,12 @@ version = "0.1.0" dependencies = [ "account_utils", "async-channel 1.9.0", + "bls", "environment", "eth2", "eth2_keystore", "eth2_network_config", + "fixed_bytes", "futures", "initialized_validators", "lighthouse_validator_store", @@ -10146,6 +10176,7 @@ dependencies = [ "serde_yaml", "slashing_protection", "slot_clock", + "ssz_types", "task_executor", "tempfile", "tokio", diff --git a/Cargo.toml b/Cargo.toml index 21cf551c48..d5d1687c76 100644 --- a/Cargo.toml +++ b/Cargo.toml @@ -95,10 +95,15 @@ version = "8.0.1" [workspace.dependencies] account_utils = { path = "common/account_utils" } -alloy-consensus = { version = "=1.0.42", default-features = false } -alloy-primitives = { version = "=1.4.1", default-features = false, features = ["rlp", "getrandom"] } -alloy-rlp = { version = "=0.3.12", default-features = false } -alloy-rpc-types-eth = { version = "=1.0.42", default-features = false, features = ["serde"] } +alloy-consensus = { version = "1", default-features = false } +alloy-dyn-abi = { version = "1", default-features = false } +alloy-json-abi = { version = "1", default-features = false } +alloy-network = { version = "1", default-features = false } +alloy-primitives = { version = "1", default-features = false, features = ["rlp", "getrandom"] } +alloy-provider = { version = "1", default-features = false, features = ["reqwest"] } +alloy-rlp = { version = "0.3", default-features = false } +alloy-rpc-types-eth = { version = "1", default-features = false, features = ["serde"] } +alloy-signer-local = { version = "1", default-features = false } anyhow = "1" arbitrary = { version = "1", features = ["derive"] } async-channel = "1.9.0" @@ -230,10 +235,10 @@ snap = "1" ssz_types = { version = "0.14.0", features = ["context_deserialize", "runtime_types"] } state_processing = { path = "consensus/state_processing" } store = { path = "beacon_node/store" } -strum = { version = "0.24", features = ["derive"] } +strum = { version = "0.27", features = ["derive"] } superstruct = "0.10" swap_or_not_shuffle = { path = "consensus/swap_or_not_shuffle" } -syn = "1" +syn = "2" sysinfo = "0.26" system_health = { path = "common/system_health" } task_executor = { path = "common/task_executor" } @@ -254,6 +259,7 @@ tracing-opentelemetry = "0.31.0" tracing-subscriber = { version = "0.3", features = ["env-filter", "json"] } tree_hash = "0.12.0" tree_hash_derive = "0.12.0" +typenum = "1" types = { path = "consensus/types" } url = "2" uuid = { version = "0.8", features = ["serde", "v4"] } diff --git a/Makefile b/Makefile index 788e537c4f..c1cccb9270 100644 --- a/Makefile +++ b/Makefile @@ -3,7 +3,7 @@ EF_TESTS = "testing/ef_tests" STATE_TRANSITION_VECTORS = "testing/state_transition_vectors" EXECUTION_ENGINE_INTEGRATION = "testing/execution_engine_integration" -GIT_TAG := $(shell git describe --tags --candidates 1) +GIT_TAG = $(shell git describe --tags --candidates 1) BIN_DIR = "bin" X86_64_TAG = "x86_64-unknown-linux-gnu" diff --git a/account_manager/src/validator/slashing_protection.rs b/account_manager/src/validator/slashing_protection.rs index 18064b990f..96098ccbbd 100644 --- a/account_manager/src/validator/slashing_protection.rs +++ b/account_manager/src/validator/slashing_protection.rs @@ -1,3 +1,4 @@ +use bls::PublicKeyBytes; use clap::{Arg, ArgAction, ArgMatches, Command}; use environment::Environment; use slashing_protection::{ @@ -7,7 +8,7 @@ use slashing_protection::{ use std::fs::File; use std::path::PathBuf; use std::str::FromStr; -use types::{Epoch, EthSpec, PublicKeyBytes, Slot}; +use types::{Epoch, EthSpec, Slot}; pub const CMD: &str = "slashing-protection"; pub const IMPORT_CMD: &str = "import"; diff --git a/beacon_node/Cargo.toml b/beacon_node/Cargo.toml index fd01355978..5352814dd5 100644 --- a/beacon_node/Cargo.toml +++ b/beacon_node/Cargo.toml @@ -20,6 +20,7 @@ testing = [] # Enables testing-only CLI flags [dependencies] account_utils = { workspace = true } beacon_chain = { workspace = true } +bls = { workspace = true } clap = { workspace = true } clap_utils = { workspace = true } client = { path = "client" } diff --git a/beacon_node/beacon_chain/Cargo.toml b/beacon_node/beacon_chain/Cargo.toml index e889f53bb0..734cfdf32b 100644 --- a/beacon_node/beacon_chain/Cargo.toml +++ b/beacon_node/beacon_chain/Cargo.toml @@ -19,13 +19,14 @@ alloy-primitives = { workspace = true } bitvec = { workspace = true } bls = { workspace = true } educe = { workspace = true } -eth2 = { workspace = true } +eth2 = { workspace = true, features = ["lighthouse"] } eth2_network_config = { workspace = true } ethereum_hashing = { workspace = true } ethereum_serde_utils = { workspace = true } ethereum_ssz = { workspace = true } ethereum_ssz_derive = { workspace = true } execution_layer = { workspace = true } +fixed_bytes = { workspace = true } fork_choice = { workspace = true } futures = { workspace = true } genesis = { workspace = true } @@ -39,6 +40,7 @@ logging = { workspace = true } lru = { workspace = true } merkle_proof = { workspace = true } metrics = { workspace = true } +milhouse = { workspace = true } once_cell = { workspace = true } oneshot_broadcast = { path = "../../common/oneshot_broadcast/" } operation_pool = { workspace = true } @@ -65,6 +67,7 @@ tokio-stream = { workspace = true } tracing = { workspace = true } tree_hash = { workspace = true } tree_hash_derive = { workspace = true } +typenum = { workspace = true } types = { workspace = true } zstd = { workspace = true } diff --git a/beacon_node/beacon_chain/src/attester_cache.rs b/beacon_node/beacon_chain/src/attester_cache.rs index beaa1e581c..26a3389812 100644 --- a/beacon_node/beacon_chain/src/attester_cache.rs +++ b/beacon_node/beacon_chain/src/attester_cache.rs @@ -10,13 +10,14 @@ //! and penalties can be computed and the `state.current_justified_checkpoint` can be updated. use crate::{BeaconChain, BeaconChainError, BeaconChainTypes}; +use fixed_bytes::FixedBytesExtended; use parking_lot::RwLock; use state_processing::state_advance::{Error as StateAdvanceError, partial_state_advance}; use std::collections::HashMap; use std::ops::Range; use types::{ - BeaconState, BeaconStateError, ChainSpec, Checkpoint, Epoch, EthSpec, FixedBytesExtended, - Hash256, RelativeEpoch, Slot, + BeaconState, BeaconStateError, ChainSpec, Checkpoint, Epoch, EthSpec, Hash256, RelativeEpoch, + Slot, attestation::AttestationError, beacon_state::{ compute_committee_index_in_epoch, compute_committee_range_in_epoch, epoch_committee_count, diff --git a/beacon_node/beacon_chain/src/beacon_block_streamer.rs b/beacon_node/beacon_chain/src/beacon_block_streamer.rs index a0a193cef9..a462376cc0 100644 --- a/beacon_node/beacon_chain/src/beacon_block_streamer.rs +++ b/beacon_node/beacon_chain/src/beacon_block_streamer.rs @@ -685,13 +685,13 @@ impl From for BeaconChainError { mod tests { use crate::beacon_block_streamer::{BeaconBlockStreamer, CheckCaches}; use crate::test_utils::{BeaconChainHarness, EphemeralHarnessType, test_spec}; + use bls::Keypair; use execution_layer::test_utils::Block; + use fixed_bytes::FixedBytesExtended; use std::sync::Arc; use std::sync::LazyLock; use tokio::sync::mpsc; - use types::{ - ChainSpec, Epoch, EthSpec, FixedBytesExtended, Hash256, Keypair, MinimalEthSpec, Slot, - }; + use types::{ChainSpec, Epoch, EthSpec, Hash256, MinimalEthSpec, Slot}; const VALIDATOR_COUNT: usize = 48; diff --git a/beacon_node/beacon_chain/src/beacon_chain.rs b/beacon_node/beacon_chain/src/beacon_chain.rs index 079fabd8a5..03b12a8b1b 100644 --- a/beacon_node/beacon_chain/src/beacon_chain.rs +++ b/beacon_node/beacon_chain/src/beacon_chain.rs @@ -74,6 +74,7 @@ use crate::{ AvailabilityPendingExecutedBlock, BeaconChainError, BeaconForkChoiceStore, BeaconSnapshot, CachedHead, metrics, }; +use bls::{PublicKey, PublicKeyBytes, Signature}; use eth2::beacon_response::ForkVersionedResponse; use eth2::types::{ EventKind, SseBlobSidecar, SseBlock, SseDataColumnSidecar, SseExtendedPayloadAttributes, @@ -82,6 +83,7 @@ use execution_layer::{ BlockProposalContents, BlockProposalContentsType, BuilderParams, ChainHealth, ExecutionLayer, FailedCondition, PayloadAttributes, PayloadStatus, }; +use fixed_bytes::FixedBytesExtended; use fork_choice::{ AttestationFromBlock, ExecutionStatus, ForkChoice, ForkchoiceUpdateParameters, InvalidationOperation, PayloadVerificationStatus, ResetPayloadStatuses, diff --git a/beacon_node/beacon_chain/src/beacon_fork_choice_store.rs b/beacon_node/beacon_chain/src/beacon_fork_choice_store.rs index 0c203009bb..60487f9c46 100644 --- a/beacon_node/beacon_chain/src/beacon_fork_choice_store.rs +++ b/beacon_node/beacon_chain/src/beacon_fork_choice_store.rs @@ -6,6 +6,7 @@ use crate::{BeaconSnapshot, metrics}; use educe::Educe; +use fixed_bytes::FixedBytesExtended; use fork_choice::ForkChoiceStore; use proto_array::JustifiedBalances; use safe_arith::ArithError; @@ -17,7 +18,7 @@ use store::{Error as StoreError, HotColdDB, ItemStore}; use superstruct::superstruct; use types::{ AbstractExecPayload, BeaconBlockRef, BeaconState, BeaconStateError, Checkpoint, Epoch, EthSpec, - FixedBytesExtended, Hash256, Slot, + Hash256, Slot, }; #[derive(Debug)] diff --git a/beacon_node/beacon_chain/src/beacon_proposer_cache.rs b/beacon_node/beacon_chain/src/beacon_proposer_cache.rs index bd6460eba7..a923d657a8 100644 --- a/beacon_node/beacon_chain/src/beacon_proposer_cache.rs +++ b/beacon_node/beacon_chain/src/beacon_proposer_cache.rs @@ -18,10 +18,9 @@ use state_processing::state_advance::partial_state_advance; use std::num::NonZeroUsize; use std::sync::Arc; use tracing::instrument; +use typenum::Unsigned; use types::non_zero_usize::new_non_zero_usize; -use types::{ - BeaconState, BeaconStateError, ChainSpec, Epoch, EthSpec, Fork, Hash256, Slot, Unsigned, -}; +use types::{BeaconState, BeaconStateError, ChainSpec, Epoch, EthSpec, Fork, Hash256, Slot}; /// The number of sets of proposer indices that should be cached. const CACHE_SIZE: NonZeroUsize = new_non_zero_usize(16); diff --git a/beacon_node/beacon_chain/src/block_times_cache.rs b/beacon_node/beacon_chain/src/block_times_cache.rs index bd1adb7e40..e8d4c75dce 100644 --- a/beacon_node/beacon_chain/src/block_times_cache.rs +++ b/beacon_node/beacon_chain/src/block_times_cache.rs @@ -294,7 +294,7 @@ impl BlockTimesCache { #[cfg(test)] mod test { use super::*; - use types::FixedBytesExtended; + use fixed_bytes::FixedBytesExtended; #[test] fn observed_time_uses_minimum() { diff --git a/beacon_node/beacon_chain/src/block_verification.rs b/beacon_node/beacon_chain/src/block_verification.rs index 374f1e2b36..bca8d2bc57 100644 --- a/beacon_node/beacon_chain/src/block_verification.rs +++ b/beacon_node/beacon_chain/src/block_verification.rs @@ -66,6 +66,7 @@ use crate::{ beacon_chain::{BeaconForkChoice, ForkChoiceError}, metrics, }; +use bls::{PublicKey, PublicKeyBytes}; use educe::Educe; use eth2::types::{BlockGossip, EventKind}; use execution_layer::PayloadStatus; @@ -97,7 +98,7 @@ use tracing::{Instrument, Span, debug, debug_span, error, info_span, instrument} use types::{ BeaconBlockRef, BeaconState, BeaconStateError, BlobsList, ChainSpec, DataColumnSidecarList, Epoch, EthSpec, ExecutionBlockHash, FullPayload, Hash256, InconsistentFork, KzgProofs, - PublicKey, PublicKeyBytes, RelativeEpoch, SignedBeaconBlock, SignedBeaconBlockHeader, Slot, + RelativeEpoch, SignedBeaconBlock, SignedBeaconBlockHeader, Slot, data_column_sidecar::DataColumnSidecarError, }; diff --git a/beacon_node/beacon_chain/src/builder.rs b/beacon_node/beacon_chain/src/builder.rs index ef438b16e0..58dbf1c35e 100644 --- a/beacon_node/beacon_chain/src/builder.rs +++ b/beacon_node/beacon_chain/src/builder.rs @@ -21,7 +21,9 @@ use crate::validator_pubkey_cache::ValidatorPubkeyCache; use crate::{ BeaconChain, BeaconChainTypes, BeaconForkChoiceStore, BeaconSnapshot, ServerSentEventHandler, }; +use bls::Signature; use execution_layer::ExecutionLayer; +use fixed_bytes::FixedBytesExtended; use fork_choice::{ForkChoice, ResetPayloadStatuses}; use futures::channel::mpsc::Sender; use kzg::Kzg; @@ -43,7 +45,7 @@ use tracing::{debug, error, info}; use types::data_column_custody_group::CustodyIndex; use types::{ BeaconBlock, BeaconState, BlobSidecarList, ChainSpec, ColumnIndex, DataColumnSidecarList, - Epoch, EthSpec, FixedBytesExtended, Hash256, Signature, SignedBeaconBlock, Slot, + Epoch, EthSpec, Hash256, SignedBeaconBlock, Slot, }; /// An empty struct used to "witness" all the `BeaconChainTypes` traits. It has no user-facing diff --git a/beacon_node/beacon_chain/src/data_availability_checker/overflow_lru_cache.rs b/beacon_node/beacon_chain/src/data_availability_checker/overflow_lru_cache.rs index e7c536c0d8..776fb50f61 100644 --- a/beacon_node/beacon_chain/src/data_availability_checker/overflow_lru_cache.rs +++ b/beacon_node/beacon_chain/src/data_availability_checker/overflow_lru_cache.rs @@ -1261,15 +1261,14 @@ mod pending_components_tests { use crate::PayloadVerificationOutcome; use crate::block_verification_types::BlockImportData; use crate::test_utils::{NumBlobs, generate_rand_block_and_blobs, test_spec}; + use fixed_bytes::FixedBytesExtended; use fork_choice::PayloadVerificationStatus; use kzg::KzgCommitment; use rand::SeedableRng; use rand::rngs::StdRng; use state_processing::ConsensusContext; use types::test_utils::TestRandom; - use types::{ - BeaconState, FixedBytesExtended, ForkName, MainnetEthSpec, SignedBeaconBlock, Slot, - }; + use types::{BeaconState, ForkName, MainnetEthSpec, SignedBeaconBlock, Slot}; type E = MainnetEthSpec; diff --git a/beacon_node/beacon_chain/src/errors.rs b/beacon_node/beacon_chain/src/errors.rs index be16b2629b..b021df2c33 100644 --- a/beacon_node/beacon_chain/src/errors.rs +++ b/beacon_node/beacon_chain/src/errors.rs @@ -9,9 +9,11 @@ use crate::observed_aggregates::Error as ObservedAttestationsError; use crate::observed_attesters::Error as ObservedAttestersError; use crate::observed_block_producers::Error as ObservedBlockProducersError; use crate::observed_data_sidecars::Error as ObservedDataSidecarsError; +use bls::PublicKeyBytes; use execution_layer::PayloadStatus; use fork_choice::ExecutionStatus; use futures::channel::mpsc::TrySendError; +use milhouse::Error as MilhouseError; use operation_pool::OpPoolError; use safe_arith::ArithError; use ssz_types::Error as SszTypesError; @@ -28,7 +30,6 @@ use state_processing::{ }; use task_executor::ShutdownReason; use tokio::task::JoinError; -use types::milhouse::Error as MilhouseError; use types::*; macro_rules! easy_from_to { diff --git a/beacon_node/beacon_chain/src/graffiti_calculator.rs b/beacon_node/beacon_chain/src/graffiti_calculator.rs index e8110d14cd..56808e0e67 100644 --- a/beacon_node/beacon_chain/src/graffiti_calculator.rs +++ b/beacon_node/beacon_chain/src/graffiti_calculator.rs @@ -225,13 +225,14 @@ async fn engine_version_cache_refresh_service( mod tests { use crate::ChainConfig; use crate::test_utils::{BeaconChainHarness, EphemeralHarnessType, test_spec}; + use bls::Keypair; use execution_layer::EngineCapabilities; use execution_layer::test_utils::{DEFAULT_CLIENT_VERSION, DEFAULT_ENGINE_CAPABILITIES}; use std::sync::Arc; use std::sync::LazyLock; use std::time::Duration; use tracing::info; - use types::{ChainSpec, GRAFFITI_BYTES_LEN, Graffiti, Keypair, MinimalEthSpec}; + use types::{ChainSpec, GRAFFITI_BYTES_LEN, Graffiti, MinimalEthSpec}; const VALIDATOR_COUNT: usize = 48; /// A cached set of keys. diff --git a/beacon_node/beacon_chain/src/historical_blocks.rs b/beacon_node/beacon_chain/src/historical_blocks.rs index e4040eea6b..91b0f12cbb 100644 --- a/beacon_node/beacon_chain/src/historical_blocks.rs +++ b/beacon_node/beacon_chain/src/historical_blocks.rs @@ -1,5 +1,6 @@ use crate::data_availability_checker::{AvailableBlock, AvailableBlockData}; use crate::{BeaconChain, BeaconChainTypes, WhenSlotSkipped, metrics}; +use fixed_bytes::FixedBytesExtended; use itertools::Itertools; use state_processing::{ per_block_processing::ParallelSignatureSets, @@ -12,7 +13,7 @@ use store::metadata::DataColumnInfo; use store::{AnchorInfo, BlobInfo, DBColumn, Error as StoreError, KeyValueStore, KeyValueStoreOp}; use strum::IntoStaticStr; use tracing::{debug, instrument}; -use types::{FixedBytesExtended, Hash256, Slot}; +use types::{Hash256, Slot}; /// Use a longer timeout on the pubkey cache. /// diff --git a/beacon_node/beacon_chain/src/naive_aggregation_pool.rs b/beacon_node/beacon_chain/src/naive_aggregation_pool.rs index 4c4478d17e..beefc2d678 100644 --- a/beacon_node/beacon_chain/src/naive_aggregation_pool.rs +++ b/beacon_node/beacon_chain/src/naive_aggregation_pool.rs @@ -577,12 +577,11 @@ where #[cfg(test)] mod tests { use super::*; - use ssz_types::BitList; - use store::BitVector; + use fixed_bytes::FixedBytesExtended; + use ssz_types::{BitList, BitVector}; use tree_hash::TreeHash; use types::{ - Attestation, AttestationBase, AttestationElectra, FixedBytesExtended, Fork, Hash256, - SyncCommitteeMessage, + Attestation, AttestationBase, AttestationElectra, Fork, Hash256, SyncCommitteeMessage, test_utils::{generate_deterministic_keypair, test_random_instance}, }; diff --git a/beacon_node/beacon_chain/src/observed_aggregates.rs b/beacon_node/beacon_chain/src/observed_aggregates.rs index f6f62e1b73..b2c5cb4b38 100644 --- a/beacon_node/beacon_chain/src/observed_aggregates.rs +++ b/beacon_node/beacon_chain/src/observed_aggregates.rs @@ -473,7 +473,8 @@ where #[cfg(not(debug_assertions))] mod tests { use super::*; - use types::{AttestationBase, FixedBytesExtended, Hash256, test_utils::test_random_instance}; + use fixed_bytes::FixedBytesExtended; + use types::{AttestationBase, Hash256, test_utils::test_random_instance}; type E = types::MainnetEthSpec; diff --git a/beacon_node/beacon_chain/src/observed_attesters.rs b/beacon_node/beacon_chain/src/observed_attesters.rs index 34d68fe3ac..d5433f49d1 100644 --- a/beacon_node/beacon_chain/src/observed_attesters.rs +++ b/beacon_node/beacon_chain/src/observed_attesters.rs @@ -19,8 +19,9 @@ use bitvec::vec::BitVec; use std::collections::{HashMap, HashSet}; use std::hash::Hash; use std::marker::PhantomData; +use typenum::Unsigned; use types::slot_data::SlotData; -use types::{Epoch, EthSpec, Hash256, Slot, Unsigned}; +use types::{Epoch, EthSpec, Hash256, Slot}; /// The maximum capacity of the `AutoPruningEpochContainer`. /// @@ -619,7 +620,7 @@ impl SlotSubcommitteeIndex { #[cfg(test)] mod tests { use super::*; - use types::FixedBytesExtended; + use fixed_bytes::FixedBytesExtended; type E = types::MainnetEthSpec; diff --git a/beacon_node/beacon_chain/src/observed_block_producers.rs b/beacon_node/beacon_chain/src/observed_block_producers.rs index 096c8bff77..b740735ac4 100644 --- a/beacon_node/beacon_chain/src/observed_block_producers.rs +++ b/beacon_node/beacon_chain/src/observed_block_producers.rs @@ -4,7 +4,8 @@ use std::collections::hash_map::Entry; use std::collections::{HashMap, HashSet}; use std::marker::PhantomData; -use types::{BeaconBlockRef, Epoch, EthSpec, Hash256, Slot, Unsigned}; +use typenum::Unsigned; +use types::{BeaconBlockRef, Epoch, EthSpec, Hash256, Slot}; #[derive(Debug, PartialEq)] pub enum Error { diff --git a/beacon_node/beacon_chain/src/observed_slashable.rs b/beacon_node/beacon_chain/src/observed_slashable.rs index 001a0d4a86..704d605436 100644 --- a/beacon_node/beacon_chain/src/observed_slashable.rs +++ b/beacon_node/beacon_chain/src/observed_slashable.rs @@ -5,7 +5,8 @@ use crate::observed_block_producers::Error; use std::collections::hash_map::Entry; use std::collections::{HashMap, HashSet}; use std::marker::PhantomData; -use types::{EthSpec, Hash256, Slot, Unsigned}; +use typenum::Unsigned; +use types::{EthSpec, Hash256, Slot}; #[derive(Eq, Hash, PartialEq, Debug, Default)] pub struct ProposalKey { diff --git a/beacon_node/beacon_chain/src/shuffling_cache.rs b/beacon_node/beacon_chain/src/shuffling_cache.rs index 22921147a6..618d459754 100644 --- a/beacon_node/beacon_chain/src/shuffling_cache.rs +++ b/beacon_node/beacon_chain/src/shuffling_cache.rs @@ -290,6 +290,7 @@ impl BlockShufflingIds { #[cfg(not(debug_assertions))] #[cfg(test)] mod test { + use fixed_bytes::FixedBytesExtended; use types::*; use crate::test_utils::EphemeralHarnessType; diff --git a/beacon_node/beacon_chain/src/single_attestation.rs b/beacon_node/beacon_chain/src/single_attestation.rs index 33a093687e..955eb98e92 100644 --- a/beacon_node/beacon_chain/src/single_attestation.rs +++ b/beacon_node/beacon_chain/src/single_attestation.rs @@ -1,7 +1,7 @@ use crate::attestation_verification::Error; +use ssz_types::{BitList, BitVector}; use types::{ - Attestation, AttestationBase, AttestationElectra, BitList, BitVector, EthSpec, ForkName, - SingleAttestation, + Attestation, AttestationBase, AttestationElectra, EthSpec, ForkName, SingleAttestation, }; pub fn single_attestation_to_attestation( diff --git a/beacon_node/beacon_chain/src/sync_committee_verification.rs b/beacon_node/beacon_chain/src/sync_committee_verification.rs index 88b040a6e5..e74e284e58 100644 --- a/beacon_node/beacon_chain/src/sync_committee_verification.rs +++ b/beacon_node/beacon_chain/src/sync_committee_verification.rs @@ -30,6 +30,7 @@ use crate::observed_attesters::SlotSubcommitteeIndex; use crate::{ BeaconChain, BeaconChainError, BeaconChainTypes, metrics, observed_aggregates::ObserveOutcome, }; +use bls::AggregateSignature; use bls::{PublicKeyBytes, verify_signature_sets}; use educe::Educe; use safe_arith::ArithError; @@ -51,7 +52,7 @@ use types::consts::altair::SYNC_COMMITTEE_SUBNET_COUNT; use types::slot_data::SlotData; use types::sync_committee::SyncCommitteeError; use types::{ - AggregateSignature, BeaconStateError, EthSpec, Hash256, SignedContributionAndProof, Slot, + BeaconStateError, EthSpec, Hash256, SignedContributionAndProof, Slot, SyncCommitteeContribution, SyncCommitteeMessage, SyncSelectionProof, SyncSubnetId, sync_committee_contribution::Error as ContributionError, }; diff --git a/beacon_node/beacon_chain/src/test_utils.rs b/beacon_node/beacon_chain/src/test_utils.rs index e3a8eecdb9..ec58a8d4d5 100644 --- a/beacon_node/beacon_chain/src/test_utils.rs +++ b/beacon_node/beacon_chain/src/test_utils.rs @@ -20,6 +20,9 @@ pub use crate::{ validator_monitor::{ValidatorMonitor, ValidatorMonitorConfig}, }; use bls::get_withdrawal_credentials; +use bls::{ + AggregateSignature, Keypair, PublicKey, PublicKeyBytes, SecretKey, Signature, SignatureBytes, +}; use eth2::types::SignedBlockContentsTuple; use execution_layer::test_utils::generate_genesis_header; use execution_layer::{ @@ -30,6 +33,7 @@ use execution_layer::{ MockExecutionLayer, }, }; +use fixed_bytes::FixedBytesExtended; use futures::channel::mpsc::Receiver; pub use genesis::{DEFAULT_ETH1_BLOCK_HASH, InteropGenesisBuilder}; use int_to_bytes::int_to_bytes32; @@ -46,7 +50,7 @@ use rand::seq::SliceRandom; use rayon::prelude::*; use sensitive_url::SensitiveUrl; use slot_clock::{SlotClock, TestingSlotClock}; -use ssz_types::RuntimeVariableList; +use ssz_types::{RuntimeVariableList, VariableList}; use state_processing::per_block_processing::compute_timestamp_at_slot; use state_processing::state_advance::complete_state_advance; use std::borrow::Cow; @@ -61,12 +65,13 @@ use store::{HotColdDB, ItemStore, MemoryStore, config::StoreConfig}; use task_executor::TaskExecutor; use task_executor::{ShutdownReason, test_utils::TestRuntime}; use tree_hash::TreeHash; +use typenum::U4294967296; use types::data_column_custody_group::CustodyIndex; use types::indexed_attestation::IndexedAttestationBase; use types::payload::BlockProductionVersion; use types::test_utils::TestRandom; pub use types::test_utils::generate_deterministic_keypairs; -use types::{typenum::U4294967296, *}; +use types::*; // 4th September 2019 pub const HARNESS_GENESIS_TIME: u64 = 1_567_552_690; @@ -2918,7 +2923,6 @@ where let chain_dump = self.chain.chain_dump().unwrap(); chain_dump .iter() - .cloned() .map(|checkpoint| checkpoint.beacon_state.finalized_checkpoint().root) .filter(|block_hash| *block_hash != Hash256::zero()) .map(|hash| hash.into()) @@ -3276,7 +3280,7 @@ pub fn generate_rand_block_and_blobs( ) -> (SignedBeaconBlock>, Vec>) { let inner = map_fork_name!(fork_name, BeaconBlock, <_>::random_for_test(rng)); - let mut block = SignedBeaconBlock::from_block(inner, types::Signature::random_for_test(rng)); + let mut block = SignedBeaconBlock::from_block(inner, Signature::random_for_test(rng)); let mut blob_sidecars = vec![]; let bundle = match block { diff --git a/beacon_node/beacon_chain/src/validator_monitor.rs b/beacon_node/beacon_chain/src/validator_monitor.rs index ba06d5da4e..2a76d65d32 100644 --- a/beacon_node/beacon_chain/src/validator_monitor.rs +++ b/beacon_node/beacon_chain/src/validator_monitor.rs @@ -4,6 +4,7 @@ use crate::beacon_proposer_cache::{BeaconProposerCache, TYPICAL_SLOTS_PER_EPOCH}; use crate::metrics; +use bls::PublicKeyBytes; use itertools::Itertools; use logging::crit; use parking_lot::{Mutex, RwLock}; @@ -28,9 +29,10 @@ use types::consts::altair::{ use types::{ Attestation, AttestationData, AttesterSlashingRef, BeaconBlockRef, BeaconState, BeaconStateError, ChainSpec, Epoch, EthSpec, Hash256, IndexedAttestation, - IndexedAttestationRef, ProposerSlashing, PublicKeyBytes, SignedAggregateAndProof, - SignedContributionAndProof, Slot, SyncCommitteeMessage, VoluntaryExit, + IndexedAttestationRef, ProposerSlashing, SignedAggregateAndProof, SignedContributionAndProof, + Slot, SyncCommitteeMessage, VoluntaryExit, }; + /// Used for Prometheus labels. /// /// We've used `total` for this value to align with Nimbus, as per: diff --git a/beacon_node/beacon_chain/src/validator_pubkey_cache.rs b/beacon_node/beacon_chain/src/validator_pubkey_cache.rs index a346a649f0..26ac02d91b 100644 --- a/beacon_node/beacon_chain/src/validator_pubkey_cache.rs +++ b/beacon_node/beacon_chain/src/validator_pubkey_cache.rs @@ -1,6 +1,8 @@ use crate::errors::BeaconChainError; use crate::{BeaconChainTypes, BeaconStore}; use bls::PUBLIC_KEY_UNCOMPRESSED_BYTES_LEN; +use bls::{PublicKey, PublicKeyBytes}; +use fixed_bytes::FixedBytesExtended; use rayon::prelude::*; use smallvec::SmallVec; use ssz::{Decode, Encode}; @@ -9,7 +11,7 @@ use std::collections::HashMap; use std::marker::PhantomData; use store::{DBColumn, Error as StoreError, StoreItem, StoreOp}; use tracing::instrument; -use types::{BeaconState, FixedBytesExtended, Hash256, PublicKey, PublicKeyBytes}; +use types::{BeaconState, Hash256}; /// Provides a mapping of `validator_index -> validator_publickey`. /// @@ -244,10 +246,11 @@ impl DatabasePubkey { mod test { use super::*; use crate::test_utils::{BeaconChainHarness, EphemeralHarnessType}; + use bls::Keypair; use logging::create_test_tracing_subscriber; use std::sync::Arc; use store::HotColdDB; - use types::{EthSpec, Keypair, MainnetEthSpec}; + use types::{EthSpec, MainnetEthSpec}; type E = MainnetEthSpec; type T = EphemeralHarnessType; diff --git a/beacon_node/beacon_chain/tests/attestation_production.rs b/beacon_node/beacon_chain/tests/attestation_production.rs index 0acb23d512..017c249d10 100644 --- a/beacon_node/beacon_chain/tests/attestation_production.rs +++ b/beacon_node/beacon_chain/tests/attestation_production.rs @@ -4,11 +4,10 @@ use beacon_chain::attestation_simulator::produce_unaggregated_attestation; use beacon_chain::test_utils::{AttestationStrategy, BeaconChainHarness, BlockStrategy}; use beacon_chain::validator_monitor::UNAGGREGATED_ATTESTATION_LAG_SLOTS; use beacon_chain::{StateSkipConfig, WhenSlotSkipped, metrics}; +use bls::{AggregateSignature, Keypair}; use std::sync::{Arc, LazyLock}; use tree_hash::TreeHash; -use types::{ - AggregateSignature, Attestation, EthSpec, Keypair, MainnetEthSpec, RelativeEpoch, Slot, -}; +use types::{Attestation, EthSpec, MainnetEthSpec, RelativeEpoch, Slot}; pub const VALIDATOR_COUNT: usize = 16; diff --git a/beacon_node/beacon_chain/tests/attestation_verification.rs b/beacon_node/beacon_chain/tests/attestation_verification.rs index 706ffad3c1..7984ea4708 100644 --- a/beacon_node/beacon_chain/tests/attestation_verification.rs +++ b/beacon_node/beacon_chain/tests/attestation_verification.rs @@ -13,15 +13,17 @@ use beacon_chain::{ single_attestation_to_attestation, test_spec, }, }; +use bls::{AggregateSignature, Keypair, SecretKey}; +use fixed_bytes::FixedBytesExtended; use genesis::{DEFAULT_ETH1_BLOCK_HASH, interop_genesis_state}; use int_to_bytes::int_to_bytes32; use state_processing::per_slot_processing; use std::sync::{Arc, LazyLock}; use tree_hash::TreeHash; +use typenum::Unsigned; use types::{ - Address, AggregateSignature, Attestation, AttestationRef, ChainSpec, Epoch, EthSpec, - FixedBytesExtended, ForkName, Hash256, Keypair, MainnetEthSpec, SecretKey, SelectionProof, - SignedAggregateAndProof, SingleAttestation, Slot, SubnetId, Unsigned, + Address, Attestation, AttestationRef, ChainSpec, Epoch, EthSpec, ForkName, Hash256, + MainnetEthSpec, SelectionProof, SignedAggregateAndProof, SingleAttestation, Slot, SubnetId, signed_aggregate_and_proof::SignedAggregateAndProofRefMut, test_utils::generate_deterministic_keypair, }; diff --git a/beacon_node/beacon_chain/tests/blob_verification.rs b/beacon_node/beacon_chain/tests/blob_verification.rs index c42a2828c0..d1a0d87adf 100644 --- a/beacon_node/beacon_chain/tests/blob_verification.rs +++ b/beacon_node/beacon_chain/tests/blob_verification.rs @@ -7,6 +7,7 @@ use beacon_chain::{ AvailabilityProcessingStatus, BlockError, ChainConfig, InvalidSignature, NotifyExecutionLayer, block_verification_types::AsBlock, }; +use bls::{Keypair, Signature}; use logging::create_test_tracing_subscriber; use std::sync::{Arc, LazyLock}; use types::{blob_sidecar::FixedBlobSidecarList, *}; diff --git a/beacon_node/beacon_chain/tests/block_verification.rs b/beacon_node/beacon_chain/tests/block_verification.rs index 881885cef2..2644b74b28 100644 --- a/beacon_node/beacon_chain/tests/block_verification.rs +++ b/beacon_node/beacon_chain/tests/block_verification.rs @@ -13,6 +13,8 @@ use beacon_chain::{ BeaconSnapshot, BlockError, ChainConfig, ChainSegmentResult, IntoExecutionPendingBlock, InvalidSignature, NotifyExecutionLayer, }; +use bls::{AggregateSignature, Keypair, Signature}; +use fixed_bytes::FixedBytesExtended; use logging::create_test_tracing_subscriber; use slasher::{Config as SlasherConfig, Slasher}; use state_processing::{ diff --git a/beacon_node/beacon_chain/tests/column_verification.rs b/beacon_node/beacon_chain/tests/column_verification.rs index 229ae1e199..be9b3b2fa1 100644 --- a/beacon_node/beacon_chain/tests/column_verification.rs +++ b/beacon_node/beacon_chain/tests/column_verification.rs @@ -9,6 +9,7 @@ use beacon_chain::{ AvailabilityProcessingStatus, BlockError, ChainConfig, InvalidSignature, NotifyExecutionLayer, block_verification_types::AsBlock, }; +use bls::{Keypair, Signature}; use logging::create_test_tracing_subscriber; use std::sync::{Arc, LazyLock}; use types::*; diff --git a/beacon_node/beacon_chain/tests/op_verification.rs b/beacon_node/beacon_chain/tests/op_verification.rs index c18af0bde7..2f97f10745 100644 --- a/beacon_node/beacon_chain/tests/op_verification.rs +++ b/beacon_node/beacon_chain/tests/op_verification.rs @@ -9,6 +9,7 @@ use beacon_chain::{ AttestationStrategy, BeaconChainHarness, BlockStrategy, DiskHarnessType, test_spec, }, }; +use bls::Keypair; use state_processing::per_block_processing::errors::{ AttesterSlashingInvalid, BlockOperationError, ExitInvalid, ProposerSlashingInvalid, }; diff --git a/beacon_node/beacon_chain/tests/rewards.rs b/beacon_node/beacon_chain/tests/rewards.rs index 0a5881e486..ee9cf511ea 100644 --- a/beacon_node/beacon_chain/tests/rewards.rs +++ b/beacon_node/beacon_chain/tests/rewards.rs @@ -7,8 +7,9 @@ use beacon_chain::test_utils::{ use beacon_chain::{ BlockError, ChainConfig, StateSkipConfig, WhenSlotSkipped, test_utils::{AttestationStrategy, BlockStrategy, RelativeSyncCommittee}, - types::{Epoch, EthSpec, Keypair, MinimalEthSpec}, + types::{Epoch, EthSpec, MinimalEthSpec}, }; +use bls::Keypair; use eth2::types::{StandardAttestationRewards, TotalAttestationRewards, ValidatorId}; use state_processing::{BlockReplayError, BlockReplayer}; use std::array::IntoIter; diff --git a/beacon_node/beacon_chain/tests/schema_stability.rs b/beacon_node/beacon_chain/tests/schema_stability.rs index 3b09921c15..db7f7dbdbb 100644 --- a/beacon_node/beacon_chain/tests/schema_stability.rs +++ b/beacon_node/beacon_chain/tests/schema_stability.rs @@ -4,6 +4,7 @@ use beacon_chain::{ persisted_custody::PersistedCustody, test_utils::{BeaconChainHarness, DiskHarnessType, test_spec}, }; +use bls::Keypair; use logging::create_test_tracing_subscriber; use operation_pool::PersistedOperationPool; use ssz::Encode; @@ -16,7 +17,7 @@ use store::{ }; use strum::IntoEnumIterator; use tempfile::{TempDir, tempdir}; -use types::{ChainSpec, Hash256, Keypair, MainnetEthSpec, Slot}; +use types::{ChainSpec, Hash256, MainnetEthSpec, Slot}; type E = MainnetEthSpec; type Store = Arc, BeaconNodeBackend>>; diff --git a/beacon_node/beacon_chain/tests/store_tests.rs b/beacon_node/beacon_chain/tests/store_tests.rs index bfb274b24a..ba0621ae72 100644 --- a/beacon_node/beacon_chain/tests/store_tests.rs +++ b/beacon_node/beacon_chain/tests/store_tests.rs @@ -25,11 +25,14 @@ use beacon_chain::{ historical_blocks::HistoricalBlockError, migrate::MigratorConfig, }; +use bls::{Keypair, Signature, SignatureBytes}; +use fixed_bytes::FixedBytesExtended; use logging::create_test_tracing_subscriber; use maplit::hashset; use rand::Rng; use rand::rngs::StdRng; use slot_clock::{SlotClock, TestingSlotClock}; +use ssz_types::VariableList; use state_processing::{BlockReplayer, state_advance::complete_state_advance}; use std::collections::HashMap; use std::collections::HashSet; @@ -2783,6 +2786,158 @@ async fn weak_subjectivity_sync_without_blobs() { weak_subjectivity_sync_test(slots, checkpoint_slot, None, false).await } +// Ensures that an unaligned checkpoint sync (the block is older than the state) +// works correctly even when `prune_payloads` is enabled. +// +// Previously, the `HotColdDB` would refuse to load the execution payload for the +// anchor block because it was considered "pruned", causing the node to fail startup. +#[tokio::test] +async fn reproduction_unaligned_checkpoint_sync_pruned_payload() { + let spec = test_spec::(); + + // Requires Execution Payloads. + let Some(_) = spec.deneb_fork_epoch else { + return; + }; + + // Create an unaligned checkpoint with a gap of 3 slots. + let num_initial_slots = E::slots_per_epoch() * 11; + let checkpoint_slot = Slot::new(E::slots_per_epoch() * 9 - 3); + + let slots = (1..num_initial_slots) + .map(Slot::new) + .filter(|&slot| slot <= checkpoint_slot || slot > checkpoint_slot + 3) + .collect::>(); + + let temp1 = tempdir().unwrap(); + let full_store = get_store_generic(&temp1, StoreConfig::default(), spec.clone()); + + let harness = get_harness_import_all_data_columns(full_store.clone(), LOW_VALIDATOR_COUNT); + let all_validators = (0..LOW_VALIDATOR_COUNT).collect::>(); + + let (genesis_state, genesis_state_root) = harness.get_current_state_and_root(); + harness + .add_attested_blocks_at_slots( + genesis_state.clone(), + genesis_state_root, + &slots, + &all_validators, + ) + .await; + + // Extract snapshot data from the harness. + let wss_block_root = harness + .chain + .block_root_at_slot(checkpoint_slot, WhenSlotSkipped::Prev) + .unwrap() + .unwrap(); + let wss_state_root = harness + .chain + .state_root_at_slot(checkpoint_slot) + .unwrap() + .unwrap(); + + let wss_block = harness + .chain + .store + .get_full_block(&wss_block_root) + .unwrap() + .unwrap(); + + // The test premise requires the anchor block to have a payload. + assert!(wss_block.message().execution_payload().is_ok()); + + let wss_blobs_opt = harness + .chain + .get_or_reconstruct_blobs(&wss_block_root) + .unwrap(); + + let wss_state = full_store + .get_state(&wss_state_root, Some(checkpoint_slot), CACHE_STATE_IN_TESTS) + .unwrap() + .unwrap(); + + // Configure the client with `prune_payloads = true`. + // This triggers the path where `try_get_full_block` must explicitly handle the anchor block. + let temp2 = tempdir().unwrap(); + let store_config = StoreConfig { + prune_payloads: true, + ..StoreConfig::default() + }; + + let store = get_store_generic(&temp2, store_config, spec.clone()); + + let slot_clock = TestingSlotClock::new( + Slot::new(0), + Duration::from_secs(harness.chain.genesis_time), + Duration::from_secs(spec.seconds_per_slot), + ); + slot_clock.set_slot(harness.get_current_slot().as_u64()); + + let chain_config = ChainConfig { + reconstruct_historic_states: true, + ..ChainConfig::default() + }; + + let trusted_setup = get_kzg(&spec); + let (shutdown_tx, _shutdown_rx) = futures::channel::mpsc::channel(1); + let mock = mock_execution_layer_from_parts( + harness.spec.clone(), + harness.runtime.task_executor.clone(), + ); + let all_custody_columns = (0..spec.number_of_custody_groups).collect::>(); + + // Attempt to build the BeaconChain. + // If the bug is present, this will panic with `MissingFullBlockExecutionPayloadPruned`. + let beacon_chain = BeaconChainBuilder::>::new(MinimalEthSpec, trusted_setup) + .chain_config(chain_config) + .store(store.clone()) + .custom_spec(spec.clone().into()) + .task_executor(harness.chain.task_executor.clone()) + .weak_subjectivity_state( + wss_state, + wss_block.clone(), + wss_blobs_opt.clone(), + genesis_state, + ) + .unwrap() + .store_migrator_config(MigratorConfig::default().blocking()) + .slot_clock(slot_clock) + .shutdown_sender(shutdown_tx) + .event_handler(Some(ServerSentEventHandler::new_with_capacity(1))) + .execution_layer(Some(mock.el)) + .ordered_custody_column_indices(all_custody_columns) + .rng(Box::new(StdRng::seed_from_u64(42))) + .build(); + + assert!( + beacon_chain.is_ok(), + "Beacon Chain failed to build. The anchor payload may have been incorrectly pruned. Error: {:?}", + beacon_chain.err() + ); + + let chain = beacon_chain.as_ref().unwrap(); + let wss_block_slot = wss_block.slot(); + + assert_ne!( + wss_block_slot, + chain.head_snapshot().beacon_state.slot(), + "Test invalid: Checkpoint was aligned (Slot {} == Slot {}). The test did not trigger the unaligned edge case.", + wss_block_slot, + chain.head_snapshot().beacon_state.slot() + ); + + let payload_exists = chain + .store + .execution_payload_exists(&wss_block_root) + .unwrap_or(false); + + assert!( + payload_exists, + "Split block payload must exist in the new node's store after checkpoint sync" + ); +} + async fn weak_subjectivity_sync_test( slots: Vec, checkpoint_slot: Slot, @@ -5529,7 +5684,6 @@ fn get_finalized_epoch_boundary_blocks( dump: &[BeaconSnapshot>], ) -> HashSet { dump.iter() - .cloned() .map(|checkpoint| checkpoint.beacon_state.finalized_checkpoint().root.into()) .collect() } @@ -5538,7 +5692,6 @@ fn get_blocks( dump: &[BeaconSnapshot>], ) -> HashSet { dump.iter() - .cloned() .map(|checkpoint| checkpoint.beacon_block_root.into()) .collect() } diff --git a/beacon_node/beacon_chain/tests/sync_committee_verification.rs b/beacon_node/beacon_chain/tests/sync_committee_verification.rs index 9dd12410fb..d2124c6641 100644 --- a/beacon_node/beacon_chain/tests/sync_committee_verification.rs +++ b/beacon_node/beacon_chain/tests/sync_committee_verification.rs @@ -2,6 +2,8 @@ use beacon_chain::sync_committee_verification::{Error as SyncCommitteeError, SyncCommitteeData}; use beacon_chain::test_utils::{BeaconChainHarness, EphemeralHarnessType, RelativeSyncCommittee}; +use bls::{AggregateSignature, Keypair, SecretKey}; +use fixed_bytes::FixedBytesExtended; use int_to_bytes::int_to_bytes32; use safe_arith::SafeArith; use state_processing::{ @@ -11,10 +13,11 @@ use state_processing::{ use std::sync::LazyLock; use store::{SignedContributionAndProof, SyncCommitteeMessage}; use tree_hash::TreeHash; +use typenum::Unsigned; use types::consts::altair::SYNC_COMMITTEE_SUBNET_COUNT; use types::{ - AggregateSignature, Epoch, EthSpec, FixedBytesExtended, Hash256, Keypair, MainnetEthSpec, - SecretKey, Slot, SyncContributionData, SyncSelectionProof, SyncSubnetId, Unsigned, + Epoch, EthSpec, Hash256, MainnetEthSpec, Slot, SyncContributionData, SyncSelectionProof, + SyncSubnetId, }; pub type E = MainnetEthSpec; diff --git a/beacon_node/beacon_chain/tests/tests.rs b/beacon_node/beacon_chain/tests/tests.rs index ec0e607d00..17d9c5f697 100644 --- a/beacon_node/beacon_chain/tests/tests.rs +++ b/beacon_node/beacon_chain/tests/tests.rs @@ -8,13 +8,14 @@ use beacon_chain::{ OP_POOL_DB_KEY, }, }; +use bls::Keypair; use operation_pool::PersistedOperationPool; use state_processing::EpochProcessingError; use state_processing::{per_slot_processing, per_slot_processing::Error as SlotProcessingError}; use std::sync::LazyLock; use types::{ - BeaconState, BeaconStateError, BlockImportSource, Checkpoint, EthSpec, Hash256, Keypair, - MinimalEthSpec, RelativeEpoch, Slot, + BeaconState, BeaconStateError, BlockImportSource, Checkpoint, EthSpec, Hash256, MinimalEthSpec, + RelativeEpoch, Slot, }; type E = MinimalEthSpec; diff --git a/beacon_node/beacon_chain/tests/validator_monitor.rs b/beacon_node/beacon_chain/tests/validator_monitor.rs index 95732abeb5..521fc4ac97 100644 --- a/beacon_node/beacon_chain/tests/validator_monitor.rs +++ b/beacon_node/beacon_chain/tests/validator_monitor.rs @@ -2,8 +2,9 @@ use beacon_chain::test_utils::{ AttestationStrategy, BeaconChainHarness, BlockStrategy, EphemeralHarnessType, }; use beacon_chain::validator_monitor::{MISSED_BLOCK_LAG_SLOTS, ValidatorMonitorConfig}; +use bls::{Keypair, PublicKeyBytes}; use std::sync::LazyLock; -use types::{Epoch, EthSpec, Hash256, Keypair, MainnetEthSpec, PublicKeyBytes, Slot}; +use types::{Epoch, EthSpec, Hash256, MainnetEthSpec, Slot}; // Should ideally be divisible by 3. pub const VALIDATOR_COUNT: usize = 48; diff --git a/beacon_node/builder_client/Cargo.toml b/beacon_node/builder_client/Cargo.toml index 9b1f86360d..09bf3f48b4 100644 --- a/beacon_node/builder_client/Cargo.toml +++ b/beacon_node/builder_client/Cargo.toml @@ -5,6 +5,8 @@ edition = { workspace = true } authors = ["Sean Anderson "] [dependencies] +bls = { workspace = true } +context_deserialize = { workspace = true } eth2 = { workspace = true } ethereum_ssz = { workspace = true } lighthouse_version = { workspace = true } diff --git a/beacon_node/builder_client/src/lib.rs b/beacon_node/builder_client/src/lib.rs index b486e77083..4fc6b3a379 100644 --- a/beacon_node/builder_client/src/lib.rs +++ b/beacon_node/builder_client/src/lib.rs @@ -1,9 +1,11 @@ +use bls::PublicKeyBytes; +use context_deserialize::ContextDeserialize; pub use eth2::Error; use eth2::types::beacon_response::EmptyMetadata; use eth2::types::builder_bid::SignedBuilderBid; use eth2::types::{ - ContentType, ContextDeserialize, EthSpec, ExecutionBlockHash, ForkName, ForkVersionDecode, - ForkVersionedResponse, PublicKeyBytes, SignedValidatorRegistrationData, Slot, + ContentType, EthSpec, ExecutionBlockHash, ForkName, ForkVersionDecode, ForkVersionedResponse, + SignedValidatorRegistrationData, Slot, }; use eth2::types::{FullPayloadContents, SignedBlindedBeaconBlock}; use eth2::{ @@ -538,9 +540,10 @@ impl BuilderHttpClient { #[cfg(test)] mod tests { use super::*; + use bls::Signature; + use eth2::types::MainnetEthSpec; use eth2::types::builder_bid::{BuilderBid, BuilderBidFulu}; use eth2::types::test_utils::{SeedableRng, TestRandom, XorShiftRng}; - use eth2::types::{MainnetEthSpec, Signature}; use mockito::{Matcher, Server, ServerGuard}; type E = MainnetEthSpec; diff --git a/beacon_node/execution_layer/Cargo.toml b/beacon_node/execution_layer/Cargo.toml index 43b2e1dd75..c443e94574 100644 --- a/beacon_node/execution_layer/Cargo.toml +++ b/beacon_node/execution_layer/Cargo.toml @@ -10,9 +10,10 @@ alloy-primitives = { workspace = true } alloy-rlp = { workspace = true } alloy-rpc-types-eth = { workspace = true } arc-swap = "1.6.0" +bls = { workspace = true } builder_client = { path = "../builder_client" } bytes = { workspace = true } -eth2 = { workspace = true } +eth2 = { workspace = true, features = ["events", "lighthouse"] } ethereum_serde_utils = { workspace = true } ethereum_ssz = { workspace = true } fixed_bytes = { workspace = true } @@ -48,6 +49,7 @@ tracing = { workspace = true } tree_hash = { workspace = true } tree_hash_derive = { workspace = true } triehash = "0.8.4" +typenum = { workspace = true } types = { workspace = true } warp = { workspace = true } zeroize = { workspace = true } diff --git a/beacon_node/execution_layer/src/engine_api.rs b/beacon_node/execution_layer/src/engine_api.rs index c0314935e1..bf913fe510 100644 --- a/beacon_node/execution_layer/src/engine_api.rs +++ b/beacon_node/execution_layer/src/engine_api.rs @@ -20,8 +20,8 @@ use strum::IntoStaticStr; use superstruct::superstruct; pub use types::{ Address, BeaconBlockRef, ConsolidationRequest, EthSpec, ExecutionBlockHash, ExecutionPayload, - ExecutionPayloadHeader, ExecutionPayloadRef, FixedVector, ForkName, Hash256, Transactions, - Uint256, VariableList, Withdrawal, Withdrawals, + ExecutionPayloadHeader, ExecutionPayloadRef, ForkName, Hash256, Transactions, Uint256, + Withdrawal, Withdrawals, }; use types::{ ExecutionPayloadBellatrix, ExecutionPayloadCapella, ExecutionPayloadDeneb, @@ -742,7 +742,7 @@ impl ClientVersionV1 { self.commit .0 .get(..4) - .map_or_else(|| self.commit.0.as_str(), |s| s) + .unwrap_or(self.commit.0.as_str()) .to_lowercase(), lighthouse_commit_prefix .0 diff --git a/beacon_node/execution_layer/src/engine_api/http.rs b/beacon_node/execution_layer/src/engine_api/http.rs index 8f7564ace6..c421491f80 100644 --- a/beacon_node/execution_layer/src/engine_api/http.rs +++ b/beacon_node/execution_layer/src/engine_api/http.rs @@ -103,9 +103,10 @@ pub static LIGHTHOUSE_JSON_CLIENT_VERSION: LazyLock = /// Contains methods to convert arbitrary bytes to an ETH2 deposit contract object. pub mod deposit_log { + use bls::{PublicKeyBytes, SignatureBytes}; use ssz::Decode; use state_processing::per_block_processing::signature_sets::deposit_pubkey_signature_message; - use types::{ChainSpec, DepositData, Hash256, PublicKeyBytes, SignatureBytes}; + use types::{ChainSpec, DepositData, Hash256}; pub use eth2::lighthouse::DepositLog; @@ -1466,10 +1467,13 @@ mod test { use super::auth::JwtKey; use super::*; use crate::test_utils::{DEFAULT_JWT_SECRET, MockServer}; + use fixed_bytes::FixedBytesExtended; + use ssz_types::VariableList; use std::future::Future; use std::str::FromStr; use std::sync::Arc; - use types::{FixedBytesExtended, MainnetEthSpec, Unsigned}; + use typenum::Unsigned; + use types::MainnetEthSpec; struct Tester { server: MockServer, diff --git a/beacon_node/execution_layer/src/engine_api/json_structures.rs b/beacon_node/execution_layer/src/engine_api/json_structures.rs index cc46070325..fc8eae015b 100644 --- a/beacon_node/execution_layer/src/engine_api/json_structures.rs +++ b/beacon_node/execution_layer/src/engine_api/json_structures.rs @@ -1101,10 +1101,10 @@ impl TryFrom for ClientVersionV1 { #[cfg(test)] mod tests { + use bls::{PublicKeyBytes, SignatureBytes}; use ssz::Encode; use types::{ - ConsolidationRequest, DepositRequest, MainnetEthSpec, PublicKeyBytes, RequestType, - SignatureBytes, WithdrawalRequest, + ConsolidationRequest, DepositRequest, MainnetEthSpec, RequestType, WithdrawalRequest, }; use super::*; diff --git a/beacon_node/execution_layer/src/lib.rs b/beacon_node/execution_layer/src/lib.rs index ffb55ce884..554668dd8a 100644 --- a/beacon_node/execution_layer/src/lib.rs +++ b/beacon_node/execution_layer/src/lib.rs @@ -9,6 +9,7 @@ use crate::payload_cache::PayloadCache; use arc_swap::ArcSwapOption; use auth::{Auth, JwtKey, strip_prefix}; pub use block_hash::calculate_execution_block_hash; +use bls::{PublicKeyBytes, Signature}; use builder_client::BuilderHttpClient; pub use engine_api::EngineCapabilities; use engine_api::Error as ApiError; @@ -55,7 +56,7 @@ use types::{ use types::{ BeaconStateError, BlindedPayload, ChainSpec, Epoch, ExecPayload, ExecutionPayloadBellatrix, ExecutionPayloadCapella, ExecutionPayloadElectra, ExecutionPayloadFulu, FullPayload, - ProposerPreparationData, PublicKeyBytes, Signature, Slot, + ProposerPreparationData, Slot, }; mod block_hash; diff --git a/beacon_node/execution_layer/src/test_utils/execution_block_generator.rs b/beacon_node/execution_layer/src/test_utils/execution_block_generator.rs index 2385c03609..6b247a4cd4 100644 --- a/beacon_node/execution_layer/src/test_utils/execution_block_generator.rs +++ b/beacon_node/execution_layer/src/test_utils/execution_block_generator.rs @@ -8,6 +8,7 @@ use crate::engines::ForkchoiceState; use alloy_consensus::TxEnvelope; use alloy_rpc_types_eth::Transaction as AlloyTransaction; use eth2::types::BlobsBundle; +use fixed_bytes::FixedBytesExtended; use kzg::{Kzg, KzgCommitment, KzgProof}; use parking_lot::Mutex; use rand::{Rng, SeedableRng, rngs::StdRng}; @@ -22,8 +23,8 @@ use tree_hash_derive::TreeHash; use types::{ Blob, ChainSpec, EthSpec, ExecutionBlockHash, ExecutionPayload, ExecutionPayloadBellatrix, ExecutionPayloadCapella, ExecutionPayloadDeneb, ExecutionPayloadElectra, ExecutionPayloadFulu, - ExecutionPayloadGloas, ExecutionPayloadHeader, FixedBytesExtended, ForkName, Hash256, - KzgProofs, Transaction, Transactions, Uint256, + ExecutionPayloadGloas, ExecutionPayloadHeader, ForkName, Hash256, KzgProofs, Transaction, + Transactions, Uint256, }; use super::DEFAULT_TERMINAL_BLOCK; @@ -41,7 +42,7 @@ pub enum Block { PoS(ExecutionPayload), } -pub fn mock_el_extra_data() -> types::VariableList { +pub fn mock_el_extra_data() -> VariableList { "block gen was here".as_bytes().to_vec().try_into().unwrap() } diff --git a/beacon_node/execution_layer/src/test_utils/mock_builder.rs b/beacon_node/execution_layer/src/test_utils/mock_builder.rs index 35140764b6..884aa9bf47 100644 --- a/beacon_node/execution_layer/src/test_utils/mock_builder.rs +++ b/beacon_node/execution_layer/src/test_utils/mock_builder.rs @@ -1,5 +1,6 @@ use crate::test_utils::{DEFAULT_BUILDER_PAYLOAD_VALUE_WEI, DEFAULT_JWT_SECRET}; use crate::{Config, ExecutionLayer, PayloadAttributes, PayloadParameters}; +use bls::{PublicKeyBytes, SecretKey, Signature}; use bytes::Bytes; use eth2::beacon_response::ForkVersionedResponse; use eth2::types::PublishBlockRequest; @@ -15,6 +16,7 @@ use fork_choice::ForkchoiceUpdateParameters; use parking_lot::RwLock; use sensitive_url::SensitiveUrl; use ssz::Encode; +use ssz_types::VariableList; use std::collections::HashMap; use std::fmt::Debug; use std::future::Future; @@ -26,6 +28,7 @@ use tempfile::NamedTempFile; use tokio_stream::StreamExt; use tracing::{debug, error, info, warn}; use tree_hash::TreeHash; +use types::ExecutionBlockHash; use types::builder_bid::{ BuilderBid, BuilderBidBellatrix, BuilderBidCapella, BuilderBidDeneb, BuilderBidElectra, BuilderBidFulu, SignedBuilderBid, @@ -33,10 +36,8 @@ use types::builder_bid::{ use types::{ Address, BeaconState, ChainSpec, Epoch, EthSpec, ExecPayload, ExecutionPayload, ExecutionPayloadHeaderRefMut, ExecutionRequests, ForkName, ForkVersionDecode, Hash256, - PublicKeyBytes, Signature, SignedBlindedBeaconBlock, SignedRoot, - SignedValidatorRegistrationData, Slot, Uint256, + SignedBlindedBeaconBlock, SignedRoot, SignedValidatorRegistrationData, Slot, Uint256, }; -use types::{ExecutionBlockHash, SecretKey}; use warp::reply::{self, Reply}; use warp::{Filter, Rejection}; @@ -72,7 +73,7 @@ impl Operation { } } -pub fn mock_builder_extra_data() -> types::VariableList { +pub fn mock_builder_extra_data() -> VariableList { "mock_builder".as_bytes().to_vec().try_into().unwrap() } diff --git a/beacon_node/execution_layer/src/test_utils/mock_execution_layer.rs b/beacon_node/execution_layer/src/test_utils/mock_execution_layer.rs index 73c998956c..c69edb8f39 100644 --- a/beacon_node/execution_layer/src/test_utils/mock_execution_layer.rs +++ b/beacon_node/execution_layer/src/test_utils/mock_execution_layer.rs @@ -5,9 +5,10 @@ use crate::{ *, }; use alloy_primitives::B256 as H256; +use fixed_bytes::FixedBytesExtended; use kzg::Kzg; use tempfile::NamedTempFile; -use types::{FixedBytesExtended, MainnetEthSpec}; +use types::MainnetEthSpec; pub struct MockExecutionLayer { pub server: MockServer, diff --git a/beacon_node/execution_layer/src/versioned_hashes.rs b/beacon_node/execution_layer/src/versioned_hashes.rs index 97c3100de9..21cfd5a322 100644 --- a/beacon_node/execution_layer/src/versioned_hashes.rs +++ b/beacon_node/execution_layer/src/versioned_hashes.rs @@ -1,6 +1,7 @@ use alloy_consensus::TxEnvelope; use alloy_rlp::Decodable; -use types::{EthSpec, ExecutionPayloadRef, Hash256, Unsigned, VersionedHash}; +use typenum::Unsigned; +use types::{EthSpec, ExecutionPayloadRef, Hash256, VersionedHash}; #[derive(Debug)] pub enum Error { diff --git a/beacon_node/genesis/Cargo.toml b/beacon_node/genesis/Cargo.toml index 8f6f3516fc..124231a57e 100644 --- a/beacon_node/genesis/Cargo.toml +++ b/beacon_node/genesis/Cargo.toml @@ -5,6 +5,7 @@ authors = ["Paul Hauner "] edition = { workspace = true } [dependencies] +bls = { workspace = true } ethereum_hashing = { workspace = true } ethereum_ssz = { workspace = true } int_to_bytes = { workspace = true } diff --git a/beacon_node/genesis/src/interop.rs b/beacon_node/genesis/src/interop.rs index dfa4daab9a..349b8f19c8 100644 --- a/beacon_node/genesis/src/interop.rs +++ b/beacon_node/genesis/src/interop.rs @@ -1,12 +1,10 @@ use crate::common::genesis_deposits; +use bls::{Keypair, PublicKey, Signature}; use ethereum_hashing::hash; use rayon::prelude::*; use ssz::Encode; use state_processing::initialize_beacon_state_from_eth1; -use types::{ - BeaconState, ChainSpec, DepositData, EthSpec, ExecutionPayloadHeader, Hash256, Keypair, - PublicKey, Signature, -}; +use types::{BeaconState, ChainSpec, DepositData, EthSpec, ExecutionPayloadHeader, Hash256}; pub const DEFAULT_ETH1_BLOCK_HASH: &[u8] = &[0x42; 32]; diff --git a/beacon_node/http_api/Cargo.toml b/beacon_node/http_api/Cargo.toml index 7dd0d0223f..571dab1027 100644 --- a/beacon_node/http_api/Cargo.toml +++ b/beacon_node/http_api/Cargo.toml @@ -8,14 +8,17 @@ autotests = false # using a single test binary com [dependencies] beacon_chain = { workspace = true } beacon_processor = { workspace = true } +bls = { workspace = true } bs58 = "0.4.0" bytes = { workspace = true } +context_deserialize = { workspace = true } directory = { workspace = true } either = { workspace = true } -eth2 = { workspace = true } +eth2 = { workspace = true, features = ["lighthouse"] } ethereum_serde_utils = { workspace = true } ethereum_ssz = { workspace = true } execution_layer = { workspace = true } +fixed_bytes = { workspace = true } futures = { workspace = true } health_metrics = { workspace = true } hex = { workspace = true } diff --git a/beacon_node/http_api/src/beacon/mod.rs b/beacon_node/http_api/src/beacon/mod.rs index 20394784ae..df5e6eee5c 100644 --- a/beacon_node/http_api/src/beacon/mod.rs +++ b/beacon_node/http_api/src/beacon/mod.rs @@ -1 +1,2 @@ +pub mod pool; pub mod states; diff --git a/beacon_node/http_api/src/beacon/pool.rs b/beacon_node/http_api/src/beacon/pool.rs new file mode 100644 index 0000000000..059573c317 --- /dev/null +++ b/beacon_node/http_api/src/beacon/pool.rs @@ -0,0 +1,522 @@ +use crate::task_spawner::{Priority, TaskSpawner}; +use crate::utils::{NetworkTxFilter, OptionalConsensusVersionHeaderFilter, ResponseFilter}; +use crate::version::{ + ResponseIncludesVersion, V1, V2, add_consensus_version_header, beacon_response, + unsupported_version_rejection, +}; +use crate::{sync_committees, utils}; +use beacon_chain::observed_operations::ObservationOutcome; +use beacon_chain::{BeaconChain, BeaconChainTypes}; +use eth2::types::{AttestationPoolQuery, EndpointVersion, Failure, GenericResponse}; +use lighthouse_network::PubsubMessage; +use network::NetworkMessage; +use operation_pool::ReceivedPreCapella; +use slot_clock::SlotClock; +use std::collections::HashSet; +use std::sync::Arc; +use tokio::sync::mpsc::UnboundedSender; +use tracing::{debug, info, warn}; +use types::{ + Attestation, AttestationData, AttesterSlashing, ForkName, ProposerSlashing, + SignedBlsToExecutionChange, SignedVoluntaryExit, SingleAttestation, SyncCommitteeMessage, +}; +use warp::filters::BoxedFilter; +use warp::{Filter, Reply}; +use warp_utils::reject::convert_rejection; + +pub type BeaconPoolPathFilter = BoxedFilter<( + TaskSpawner<::EthSpec>, + Arc>, +)>; +pub type BeaconPoolPathV2Filter = BoxedFilter<( + TaskSpawner<::EthSpec>, + Arc>, +)>; +pub type BeaconPoolPathAnyFilter = BoxedFilter<( + EndpointVersion, + TaskSpawner<::EthSpec>, + Arc>, +)>; + +/// POST beacon/pool/bls_to_execution_changes +pub fn post_beacon_pool_bls_to_execution_changes( + network_tx_filter: &NetworkTxFilter, + beacon_pool_path: &BeaconPoolPathFilter, +) -> ResponseFilter { + beacon_pool_path + .clone() + .and(warp::path("bls_to_execution_changes")) + .and(warp::path::end()) + .and(warp_utils::json::json()) + .and(network_tx_filter.clone()) + .then( + |task_spawner: TaskSpawner, + chain: Arc>, + address_changes: Vec, + network_tx: UnboundedSender>| { + task_spawner.blocking_json_task(Priority::P0, move || { + let mut failures = vec![]; + + for (index, address_change) in address_changes.into_iter().enumerate() { + let validator_index = address_change.message.validator_index; + + match chain.verify_bls_to_execution_change_for_http_api(address_change) { + Ok(ObservationOutcome::New(verified_address_change)) => { + let validator_index = + verified_address_change.as_inner().message.validator_index; + let address = verified_address_change + .as_inner() + .message + .to_execution_address; + + // New to P2P *and* op pool, gossip immediately if post-Capella. + 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) { + utils::publish_pubsub_message( + &network_tx, + PubsubMessage::BlsToExecutionChange(Box::new( + verified_address_change.as_inner().clone(), + )), + )?; + } + + // Import to op pool (may return `false` if there's a race). + let imported = chain.import_bls_to_execution_change( + verified_address_change, + received_pre_capella, + ); + + info!( + %validator_index, + ?address, + published = + matches!(received_pre_capella, ReceivedPreCapella::No), + imported, + "Processed BLS to execution change" + ); + } + Ok(ObservationOutcome::AlreadyKnown) => { + debug!(%validator_index, "BLS to execution change already known"); + } + Err(e) => { + warn!( + validator_index, + reason = ?e, + source = "HTTP", + "Invalid BLS to execution change" + ); + failures.push(Failure::new(index, format!("invalid: {e:?}"))); + } + } + } + + if failures.is_empty() { + Ok(()) + } else { + Err(warp_utils::reject::indexed_bad_request( + "some BLS to execution changes failed to verify".into(), + failures, + )) + } + }) + }, + ) + .boxed() +} + +/// GET beacon/pool/bls_to_execution_changes +pub fn get_beacon_pool_bls_to_execution_changes( + beacon_pool_path: &BeaconPoolPathFilter, +) -> ResponseFilter { + beacon_pool_path + .clone() + .and(warp::path("bls_to_execution_changes")) + .and(warp::path::end()) + .then( + |task_spawner: TaskSpawner, chain: Arc>| { + task_spawner.blocking_json_task(Priority::P1, move || { + let address_changes = chain.op_pool.get_all_bls_to_execution_changes(); + Ok(GenericResponse::from(address_changes)) + }) + }, + ) + .boxed() +} + +/// POST beacon/pool/sync_committees +pub fn post_beacon_pool_sync_committees( + network_tx_filter: &NetworkTxFilter, + beacon_pool_path: &BeaconPoolPathFilter, +) -> ResponseFilter { + beacon_pool_path + .clone() + .and(warp::path("sync_committees")) + .and(warp::path::end()) + .and(warp_utils::json::json()) + .and(network_tx_filter.clone()) + .then( + |task_spawner: TaskSpawner, + chain: Arc>, + signatures: Vec, + network_tx: UnboundedSender>| { + task_spawner.blocking_json_task(Priority::P0, move || { + sync_committees::process_sync_committee_signatures( + signatures, network_tx, &chain, + )?; + Ok(GenericResponse::from(())) + }) + }, + ) + .boxed() +} + +/// GET beacon/pool/voluntary_exits +pub fn get_beacon_pool_voluntary_exits( + beacon_pool_path: &BeaconPoolPathFilter, +) -> ResponseFilter { + beacon_pool_path + .clone() + .and(warp::path("voluntary_exits")) + .and(warp::path::end()) + .then( + |task_spawner: TaskSpawner, chain: Arc>| { + task_spawner.blocking_json_task(Priority::P1, move || { + let attestations = chain.op_pool.get_all_voluntary_exits(); + Ok(GenericResponse::from(attestations)) + }) + }, + ) + .boxed() +} + +/// POST beacon/pool/voluntary_exits +pub fn post_beacon_pool_voluntary_exits( + network_tx_filter: &NetworkTxFilter, + beacon_pool_path: &BeaconPoolPathFilter, +) -> ResponseFilter { + beacon_pool_path + .clone() + .and(warp::path("voluntary_exits")) + .and(warp::path::end()) + .and(warp_utils::json::json()) + .and(network_tx_filter.clone()) + .then( + |task_spawner: TaskSpawner, + chain: Arc>, + exit: SignedVoluntaryExit, + network_tx: UnboundedSender>| { + task_spawner.blocking_json_task(Priority::P0, move || { + let outcome = chain + .verify_voluntary_exit_for_gossip(exit.clone()) + .map_err(|e| { + warp_utils::reject::object_invalid(format!( + "gossip verification failed: {:?}", + e + )) + })?; + + // Notify the validator monitor. + chain + .validator_monitor + .read() + .register_api_voluntary_exit(&exit.message); + + if let ObservationOutcome::New(exit) = outcome { + utils::publish_pubsub_message( + &network_tx, + PubsubMessage::VoluntaryExit(Box::new(exit.clone().into_inner())), + )?; + + chain.import_voluntary_exit(exit); + } + + Ok(()) + }) + }, + ) + .boxed() +} + +/// GET beacon/pool/proposer_slashings +pub fn get_beacon_pool_proposer_slashings( + beacon_pool_path: &BeaconPoolPathFilter, +) -> ResponseFilter { + beacon_pool_path + .clone() + .and(warp::path("proposer_slashings")) + .and(warp::path::end()) + .then( + |task_spawner: TaskSpawner, chain: Arc>| { + task_spawner.blocking_json_task(Priority::P1, move || { + let attestations = chain.op_pool.get_all_proposer_slashings(); + Ok(GenericResponse::from(attestations)) + }) + }, + ) + .boxed() +} + +/// POST beacon/pool/proposer_slashings +pub fn post_beacon_pool_proposer_slashings( + network_tx_filter: &NetworkTxFilter, + beacon_pool_path: &BeaconPoolPathFilter, +) -> ResponseFilter { + beacon_pool_path + .clone() + .and(warp::path("proposer_slashings")) + .and(warp::path::end()) + .and(warp_utils::json::json()) + .and(network_tx_filter.clone()) + .then( + |task_spawner: TaskSpawner, + chain: Arc>, + slashing: ProposerSlashing, + network_tx: UnboundedSender>| { + task_spawner.blocking_json_task(Priority::P0, move || { + let outcome = chain + .verify_proposer_slashing_for_gossip(slashing.clone()) + .map_err(|e| { + warp_utils::reject::object_invalid(format!( + "gossip verification failed: {:?}", + e + )) + })?; + + // Notify the validator monitor. + chain + .validator_monitor + .read() + .register_api_proposer_slashing(&slashing); + + if let ObservationOutcome::New(slashing) = outcome { + utils::publish_pubsub_message( + &network_tx, + PubsubMessage::ProposerSlashing(Box::new( + slashing.clone().into_inner(), + )), + )?; + + chain.import_proposer_slashing(slashing); + } + + Ok(()) + }) + }, + ) + .boxed() +} + +/// GET beacon/pool/attester_slashings +pub fn get_beacon_pool_attester_slashings( + beacon_pool_path_any: &BeaconPoolPathAnyFilter, +) -> ResponseFilter { + beacon_pool_path_any + .clone() + .and(warp::path("attester_slashings")) + .and(warp::path::end()) + .then( + |endpoint_version: EndpointVersion, + task_spawner: TaskSpawner, + chain: Arc>| { + task_spawner.blocking_response_task(Priority::P1, move || { + let slashings = chain.op_pool.get_all_attester_slashings(); + + // Use the current slot to find the fork version, and convert all messages to the + // current fork's format. This is to ensure consistent message types matching + // `Eth-Consensus-Version`. + let current_slot = + chain + .slot_clock + .now() + .ok_or(warp_utils::reject::custom_server_error( + "unable to read slot clock".to_string(), + ))?; + let fork_name = chain.spec.fork_name_at_slot::(current_slot); + let slashings = slashings + .into_iter() + .filter(|slashing| { + (fork_name.electra_enabled() + && matches!(slashing, AttesterSlashing::Electra(_))) + || (!fork_name.electra_enabled() + && matches!(slashing, AttesterSlashing::Base(_))) + }) + .collect::>(); + + let require_version = match endpoint_version { + V1 => ResponseIncludesVersion::No, + V2 => ResponseIncludesVersion::Yes(fork_name), + _ => return Err(unsupported_version_rejection(endpoint_version)), + }; + + let res = beacon_response(require_version, &slashings); + Ok(add_consensus_version_header( + warp::reply::json(&res).into_response(), + fork_name, + )) + }) + }, + ) + .boxed() +} + +// POST beacon/pool/attester_slashings +pub fn post_beacon_pool_attester_slashings( + network_tx_filter: &NetworkTxFilter, + beacon_pool_path_any: &BeaconPoolPathAnyFilter, +) -> ResponseFilter { + beacon_pool_path_any + .clone() + .and(warp::path("attester_slashings")) + .and(warp::path::end()) + .and(warp_utils::json::json()) + .and(network_tx_filter.clone()) + .then( + // V1 and V2 are identical except V2 has a consensus version header in the request. + // We only require this header for SSZ deserialization, which isn't supported for + // this endpoint presently. + |_endpoint_version: EndpointVersion, + task_spawner: TaskSpawner, + chain: Arc>, + slashing: AttesterSlashing, + network_tx: UnboundedSender>| { + task_spawner.blocking_json_task(Priority::P0, move || { + let outcome = chain + .verify_attester_slashing_for_gossip(slashing.clone()) + .map_err(|e| { + warp_utils::reject::object_invalid(format!( + "gossip verification failed: {:?}", + e + )) + })?; + + // Notify the validator monitor. + chain + .validator_monitor + .read() + .register_api_attester_slashing(slashing.to_ref()); + + if let ObservationOutcome::New(slashing) = outcome { + utils::publish_pubsub_message( + &network_tx, + PubsubMessage::AttesterSlashing(Box::new( + slashing.clone().into_inner(), + )), + )?; + + chain.import_attester_slashing(slashing); + } + + Ok(()) + }) + }, + ) + .boxed() +} + +/// GET beacon/pool/attestations?committee_index,slot +pub fn get_beacon_pool_attestations( + beacon_pool_path_any: &BeaconPoolPathAnyFilter, +) -> ResponseFilter { + beacon_pool_path_any + .clone() + .and(warp::path("attestations")) + .and(warp::path::end()) + .and(warp::query::()) + .then( + |endpoint_version: EndpointVersion, + task_spawner: TaskSpawner, + chain: Arc>, + query: AttestationPoolQuery| { + task_spawner.blocking_response_task(Priority::P1, move || { + let query_filter = |data: &AttestationData, committee_indices: HashSet| { + query.slot.is_none_or(|slot| slot == data.slot) + && query + .committee_index + .is_none_or(|index| committee_indices.contains(&index)) + }; + + let mut attestations = chain.op_pool.get_filtered_attestations(query_filter); + attestations.extend( + chain + .naive_aggregation_pool + .read() + .iter() + .filter(|&att| { + query_filter(att.data(), att.get_committee_indices_map()) + }) + .cloned(), + ); + // Use the current slot to find the fork version, and convert all messages to the + // current fork's format. This is to ensure consistent message types matching + // `Eth-Consensus-Version`. + let current_slot = + chain + .slot_clock + .now() + .ok_or(warp_utils::reject::custom_server_error( + "unable to read slot clock".to_string(), + ))?; + let fork_name = chain.spec.fork_name_at_slot::(current_slot); + let attestations = attestations + .into_iter() + .filter(|att| { + (fork_name.electra_enabled() && matches!(att, Attestation::Electra(_))) + || (!fork_name.electra_enabled() + && matches!(att, Attestation::Base(_))) + }) + .collect::>(); + + let require_version = match endpoint_version { + V1 => ResponseIncludesVersion::No, + V2 => ResponseIncludesVersion::Yes(fork_name), + _ => return Err(unsupported_version_rejection(endpoint_version)), + }; + + let res = beacon_response(require_version, &attestations); + Ok(add_consensus_version_header( + warp::reply::json(&res).into_response(), + fork_name, + )) + }) + }, + ) + .boxed() +} + +pub fn post_beacon_pool_attestations_v2( + network_tx_filter: &NetworkTxFilter, + optional_consensus_version_header_filter: OptionalConsensusVersionHeaderFilter, + beacon_pool_path_v2: &BeaconPoolPathV2Filter, +) -> ResponseFilter { + beacon_pool_path_v2 + .clone() + .and(warp::path("attestations")) + .and(warp::path::end()) + .and(warp_utils::json::json::>()) + .and(optional_consensus_version_header_filter) + .and(network_tx_filter.clone()) + .then( + |task_spawner: TaskSpawner, + chain: Arc>, + attestations: Vec, + _fork_name: Option, + network_tx: UnboundedSender>| async move { + let result = crate::publish_attestations::publish_attestations( + task_spawner, + chain, + attestations, + network_tx, + true, + ) + .await + .map(|()| warp::reply::json(&())); + convert_rejection(result).await + }, + ) + .boxed() +} diff --git a/beacon_node/http_api/src/block_id.rs b/beacon_node/http_api/src/block_id.rs index 64f5451560..ea8b47f91e 100644 --- a/beacon_node/http_api/src/block_id.rs +++ b/beacon_node/http_api/src/block_id.rs @@ -6,12 +6,13 @@ use eth2::beacon_response::{ExecutionOptimisticFinalizedMetadata, UnversionedRes use eth2::types::BlockId as CoreBlockId; use eth2::types::DataColumnIndicesQuery; use eth2::types::{BlobIndicesQuery, BlobWrapper, BlobsVersionedHashesQuery}; +use fixed_bytes::FixedBytesExtended; use std::fmt; use std::str::FromStr; use std::sync::Arc; use types::{ - BlobSidecarList, DataColumnSidecarList, EthSpec, FixedBytesExtended, ForkName, Hash256, - SignedBeaconBlock, SignedBlindedBeaconBlock, Slot, + BlobSidecarList, DataColumnSidecarList, EthSpec, ForkName, Hash256, SignedBeaconBlock, + SignedBlindedBeaconBlock, Slot, }; use warp::Rejection; diff --git a/beacon_node/http_api/src/lib.rs b/beacon_node/http_api/src/lib.rs index ccd0698161..58cd2a3bdb 100644 --- a/beacon_node/http_api/src/lib.rs +++ b/beacon_node/http_api/src/lib.rs @@ -36,35 +36,35 @@ mod validator_inclusion; mod validators; mod version; +use crate::beacon::pool::*; use crate::light_client::{get_light_client_bootstrap, get_light_client_updates}; -use crate::produce_block::{produce_blinded_block_v2, produce_block_v2, produce_block_v3}; +use crate::utils::{AnyVersionFilter, EthV1Filter}; +use crate::validator::post_validator_liveness_epoch; +use crate::validator::*; use crate::version::beacon_response; use beacon::states; -use beacon_chain::{ - AttestationError as AttnError, BeaconChain, BeaconChainError, BeaconChainTypes, - WhenSlotSkipped, attestation_verification::VerifiedAttestation, - observed_operations::ObservationOutcome, validator_monitor::timestamp_now, -}; +use beacon_chain::{BeaconChain, BeaconChainError, BeaconChainTypes, WhenSlotSkipped}; use beacon_processor::BeaconProcessorSend; pub use block_id::BlockId; use builder_states::get_next_withdrawals; use bytes::Bytes; +use context_deserialize::ContextDeserialize; use directory::DEFAULT_ROOT_DIR; use eth2::StatusCode; +use eth2::lighthouse::sync_state::SyncState; use eth2::types::{ - self as api_types, BroadcastValidation, ContextDeserialize, EndpointVersion, ForkChoice, - ForkChoiceExtraData, ForkChoiceNode, LightClientUpdatesQuery, PublishBlockRequest, - StateId as CoreStateId, ValidatorId, ValidatorStatus, + self as api_types, BroadcastValidation, EndpointVersion, ForkChoice, ForkChoiceExtraData, + ForkChoiceNode, LightClientUpdatesQuery, PublishBlockRequest, ValidatorId, }; use eth2::{CONSENSUS_VERSION_HEADER, CONTENT_TYPE_HEADER, SSZ_CONTENT_TYPE_HEADER}; use health_metrics::observe::Observe; -use lighthouse_network::rpc::methods::MetaData; -use lighthouse_network::{Enr, NetworkGlobals, PeerId, PubsubMessage, types::SyncState}; +use lighthouse_network::Enr; +use lighthouse_network::NetworkGlobals; +use lighthouse_network::PeerId; use lighthouse_version::version_with_platform; use logging::{SSELoggingComponents, crit}; -use network::{NetworkMessage, NetworkSenders, ValidatorSubscriptionMessage}; +use network::{NetworkMessage, NetworkSenders}; use network_utils::enr_ext::EnrExt; -use operation_pool::ReceivedPreCapella; use parking_lot::RwLock; pub use publish_blocks::{ ProvenancedBlock, publish_blinded_block, publish_block, reconstruct_block, @@ -73,7 +73,6 @@ use serde::{Deserialize, Serialize}; use slot_clock::SlotClock; use ssz::Encode; pub use state_id::StateId; -use std::collections::HashSet; use std::future::Future; use std::net::{IpAddr, Ipv4Addr, SocketAddr}; use std::path::PathBuf; @@ -83,24 +82,18 @@ use std::sync::Arc; use sysinfo::{System, SystemExt}; use system_health::{observe_nat, observe_system_health_bn}; use task_spawner::{Priority, TaskSpawner}; -use tokio::sync::{ - mpsc::{Sender, UnboundedSender}, - oneshot, -}; +use tokio::sync::mpsc::UnboundedSender; use tokio_stream::{ StreamExt, wrappers::{BroadcastStream, errors::BroadcastStreamRecvError}, }; -use tracing::{debug, error, info, warn}; +use tracing::{debug, info, warn}; use types::{ - Attestation, AttestationData, AttesterSlashing, BeaconStateError, ChainSpec, Checkpoint, - ConfigAndPreset, Epoch, EthSpec, ForkName, Hash256, ProposerPreparationData, ProposerSlashing, - SignedAggregateAndProof, SignedBlindedBeaconBlock, SignedBlsToExecutionChange, - SignedContributionAndProof, SignedValidatorRegistrationData, SignedVoluntaryExit, - SingleAttestation, Slot, SyncCommitteeMessage, SyncContributionData, + BeaconStateError, Checkpoint, ConfigAndPreset, Epoch, EthSpec, ForkName, Hash256, + SignedBlindedBeaconBlock, Slot, }; use version::{ - ResponseIncludesVersion, V1, V2, V3, add_consensus_version_header, add_ssz_content_type_header, + ResponseIncludesVersion, V1, V2, add_consensus_version_header, add_ssz_content_type_header, execution_optimistic_finalized_beacon_response, inconsistent_fork_rejection, unsupported_version_rejection, }; @@ -108,7 +101,7 @@ use warp::Reply; use warp::hyper::Body; use warp::sse::Event; use warp::{Filter, Rejection, http::Response}; -use warp_utils::{query::multi_key_query, reject::convert_rejection, uor::UnifyingOrFilter}; +use warp_utils::{query::multi_key_query, uor::UnifyingOrFilter}; const API_PREFIX: &str = "eth"; @@ -360,16 +353,18 @@ pub fn serve( } // Create a filter that extracts the endpoint version. - let any_version = warp::path(API_PREFIX).and(warp::path::param::().or_else( - |_| async move { - Err(warp_utils::reject::custom_bad_request( - "Invalid version identifier".to_string(), - )) - }, - )); + let any_version = warp::path(API_PREFIX) + .and( + warp::path::param::().or_else(|_| async move { + Err(warp_utils::reject::custom_bad_request( + "Invalid version identifier".to_string(), + )) + }), + ) + .boxed(); // Filter that enforces a single endpoint version and then discards the `EndpointVersion`. - let single_version = |reqd: EndpointVersion| { + fn single_version(any_version: AnyVersionFilter, reqd: EndpointVersion) -> EthV1Filter { any_version .and_then(move |version| async move { if version == reqd { @@ -379,10 +374,11 @@ pub fn serve( } }) .untuple_one() - }; + .boxed() + } - let eth_v1 = single_version(V1); - let eth_v2 = single_version(V2); + let eth_v1 = single_version(any_version.clone(), V1); + let eth_v2 = single_version(any_version.clone(), V2); // Create a `warp` filter that provides access to the network globals. let inner_network_globals = ctx.network_globals.clone(); @@ -403,34 +399,34 @@ pub fn serve( // Create a `warp` filter that provides access to the beacon chain. let inner_ctx = ctx.clone(); - let chain_filter = - warp::any() - .map(move || inner_ctx.chain.clone()) - .and_then(|chain| async move { - match chain { - Some(chain) => Ok(chain), - None => Err(warp_utils::reject::custom_not_found( - "Beacon chain genesis has not yet been observed.".to_string(), - )), - } - }); + let chain_filter = warp::any() + .map(move || inner_ctx.chain.clone()) + .and_then(|chain| async move { + match chain { + Some(chain) => Ok(chain), + None => Err(warp_utils::reject::custom_not_found( + "Beacon chain genesis has not yet been observed.".to_string(), + )), + } + }) + .boxed(); // Create a `warp` filter that provides access to the network sender channel. let network_tx = ctx .network_senders .as_ref() .map(|senders| senders.network_send()); - let network_tx_filter = - warp::any() - .map(move || network_tx.clone()) - .and_then(|network_tx| async move { - match network_tx { - Some(network_tx) => Ok(network_tx), - None => Err(warp_utils::reject::custom_not_found( - "The networking stack has not yet started (network_tx).".to_string(), - )), - } - }); + let network_tx_filter = warp::any() + .map(move || network_tx.clone()) + .and_then(|network_tx| async move { + match network_tx { + Some(network_tx) => Ok(network_tx), + None => Err(warp_utils::reject::custom_not_found( + "The networking stack has not yet started (network_tx).".to_string(), + )), + } + }) + .boxed(); // Create a `warp` filter that provides access to the network attestation subscription channel. let validator_subscriptions_tx = ctx @@ -447,7 +443,8 @@ pub fn serve( .to_string(), )), } - }); + }) + .boxed(); // Create a `warp` filter that rejects requests whilst the node is syncing. let not_while_syncing_filter = @@ -487,7 +484,8 @@ pub fn serve( SyncState::Stalled => Ok(()), } }, - ); + ) + .boxed(); // Create a `warp` filter that returns 404s if the light client server is disabled. let light_client_server_filter = @@ -540,8 +538,9 @@ pub fn serve( .beacon_processor_send .clone() .filter(|_| config.enable_beacon_processor); - let task_spawner_filter = - warp::any().map(move || TaskSpawner::new(beacon_processor_send.clone())); + let task_spawner_filter = warp::any() + .map(move || TaskSpawner::new(beacon_processor_send.clone())) + .boxed(); let duplicate_block_status_code = ctx.config.duplicate_block_status_code; @@ -553,6 +552,7 @@ pub fn serve( // GET beacon/genesis let get_beacon_genesis = eth_v1 + .clone() .and(warp::path("beacon")) .and(warp::path("genesis")) .and(warp::path::end()) @@ -576,6 +576,7 @@ pub fn serve( */ let beacon_states_path = eth_v1 + .clone() .and(warp::path("beacon")) .and(warp::path("states")) .and(warp::path::param::().or_else(|_| async { @@ -652,6 +653,7 @@ pub fn serve( // mechanism for arbitrary forwards block iteration, we only support iterating forwards along // the canonical chain. let get_beacon_headers = eth_v1 + .clone() .and(warp::path("beacon")) .and(warp::path("headers")) .and(warp::query::()) @@ -748,6 +750,7 @@ pub fn serve( // GET beacon/headers/{block_id} let get_beacon_headers_block_id = eth_v1 + .clone() .and(warp::path("beacon")) .and(warp::path("headers")) .and(warp::path::param::().or_else(|_| async { @@ -796,18 +799,19 @@ pub fn serve( * beacon/blocks */ let consensus_version_header_filter = - warp::header::header::(CONSENSUS_VERSION_HEADER); + warp::header::header::(CONSENSUS_VERSION_HEADER).boxed(); let optional_consensus_version_header_filter = - warp::header::optional::(CONSENSUS_VERSION_HEADER); + warp::header::optional::(CONSENSUS_VERSION_HEADER).boxed(); // POST beacon/blocks let post_beacon_blocks = eth_v1 + .clone() .and(warp::path("beacon")) .and(warp::path("blocks")) .and(warp::path::end()) .and(warp::body::json()) - .and(consensus_version_header_filter) + .and(consensus_version_header_filter.clone()) .and(task_spawner_filter.clone()) .and(chain_filter.clone()) .and(network_tx_filter.clone()) @@ -839,11 +843,12 @@ pub fn serve( ); let post_beacon_blocks_ssz = eth_v1 + .clone() .and(warp::path("beacon")) .and(warp::path("blocks")) .and(warp::path::end()) .and(warp::body::bytes()) - .and(consensus_version_header_filter) + .and(consensus_version_header_filter.clone()) .and(task_spawner_filter.clone()) .and(chain_filter.clone()) .and(network_tx_filter.clone()) @@ -875,12 +880,13 @@ pub fn serve( ); let post_beacon_blocks_v2 = eth_v2 + .clone() .and(warp::path("beacon")) .and(warp::path("blocks")) .and(warp::query::()) .and(warp::path::end()) .and(warp::body::json()) - .and(consensus_version_header_filter) + .and(consensus_version_header_filter.clone()) .and(task_spawner_filter.clone()) .and(chain_filter.clone()) .and(network_tx_filter.clone()) @@ -914,12 +920,13 @@ pub fn serve( ); let post_beacon_blocks_v2_ssz = eth_v2 + .clone() .and(warp::path("beacon")) .and(warp::path("blocks")) .and(warp::query::()) .and(warp::path::end()) .and(warp::body::bytes()) - .and(consensus_version_header_filter) + .and(consensus_version_header_filter.clone()) .and(task_spawner_filter.clone()) .and(chain_filter.clone()) .and(network_tx_filter.clone()) @@ -957,6 +964,7 @@ pub fn serve( // POST beacon/blinded_blocks let post_beacon_blinded_blocks = eth_v1 + .clone() .and(warp::path("beacon")) .and(warp::path("blinded_blocks")) .and(warp::path::end()) @@ -984,6 +992,7 @@ pub fn serve( // POST beacon/blocks let post_beacon_blinded_blocks_ssz = eth_v1 + .clone() .and(warp::path("beacon")) .and(warp::path("blinded_blocks")) .and(warp::path::end()) @@ -1018,6 +1027,7 @@ pub fn serve( ); let post_beacon_blinded_blocks_v2 = eth_v2 + .clone() .and(warp::path("beacon")) .and(warp::path("blinded_blocks")) .and(warp::query::()) @@ -1057,6 +1067,7 @@ pub fn serve( ); let post_beacon_blinded_blocks_v2_ssz = eth_v2 + .clone() .and(warp::path("beacon")) .and(warp::path("blinded_blocks")) .and(warp::query::()) @@ -1099,6 +1110,7 @@ pub fn serve( }); let beacon_blocks_path_v1 = eth_v1 + .clone() .and(warp::path("beacon")) .and(warp::path("blocks")) .and(block_id_or_err) @@ -1106,6 +1118,7 @@ pub fn serve( .and(chain_filter.clone()); let beacon_blocks_path_any = any_version + .clone() .and(warp::path("beacon")) .and(warp::path("blocks")) .and(block_id_or_err) @@ -1231,6 +1244,7 @@ pub fn serve( // GET beacon/blinded_blocks/{block_id} let get_beacon_blinded_block = eth_v1 + .clone() .and(warp::path("beacon")) .and(warp::path("blinded_blocks")) .and(block_id_or_err) @@ -1283,6 +1297,7 @@ pub fn serve( // GET beacon/blob_sidecars/{block_id} let get_blob_sidecars = eth_v1 + .clone() .and(warp::path("beacon")) .and(warp::path("blob_sidecars")) .and(block_id_or_err) @@ -1334,6 +1349,7 @@ pub fn serve( // GET beacon/blobs/{block_id} let get_blobs = eth_v1 + .clone() .and(warp::path("beacon")) .and(warp::path("blobs")) .and(block_id_or_err) @@ -1383,447 +1399,74 @@ pub fn serve( */ let beacon_pool_path = eth_v1 + .clone() .and(warp::path("beacon")) .and(warp::path("pool")) .and(task_spawner_filter.clone()) - .and(chain_filter.clone()); + .and(chain_filter.clone()) + .boxed(); let beacon_pool_path_v2 = eth_v2 + .clone() .and(warp::path("beacon")) .and(warp::path("pool")) .and(task_spawner_filter.clone()) - .and(chain_filter.clone()); + .and(chain_filter.clone()) + .boxed(); let beacon_pool_path_any = any_version + .clone() .and(warp::path("beacon")) .and(warp::path("pool")) .and(task_spawner_filter.clone()) - .and(chain_filter.clone()); + .and(chain_filter.clone()) + .boxed(); - let post_beacon_pool_attestations_v2 = beacon_pool_path_v2 - .clone() - .and(warp::path("attestations")) - .and(warp::path::end()) - .and(warp_utils::json::json::>()) - .and(optional_consensus_version_header_filter) - .and(network_tx_filter.clone()) - .then( - |task_spawner: TaskSpawner, - chain: Arc>, - attestations: Vec, - _fork_name: Option, - network_tx: UnboundedSender>| async move { - let result = crate::publish_attestations::publish_attestations( - task_spawner, - chain, - attestations, - network_tx, - true, - ) - .await - .map(|()| warp::reply::json(&())); - convert_rejection(result).await - }, - ); + let post_beacon_pool_attestations_v2 = post_beacon_pool_attestations_v2( + &network_tx_filter, + optional_consensus_version_header_filter, + &beacon_pool_path_v2, + ); // GET beacon/pool/attestations?committee_index,slot - let get_beacon_pool_attestations = beacon_pool_path_any - .clone() - .and(warp::path("attestations")) - .and(warp::path::end()) - .and(warp::query::()) - .then( - |endpoint_version: EndpointVersion, - task_spawner: TaskSpawner, - chain: Arc>, - query: api_types::AttestationPoolQuery| { - task_spawner.blocking_response_task(Priority::P1, move || { - let query_filter = |data: &AttestationData, committee_indices: HashSet| { - query.slot.is_none_or(|slot| slot == data.slot) - && query - .committee_index - .is_none_or(|index| committee_indices.contains(&index)) - }; - - let mut attestations = chain.op_pool.get_filtered_attestations(query_filter); - attestations.extend( - chain - .naive_aggregation_pool - .read() - .iter() - .filter(|&att| { - query_filter(att.data(), att.get_committee_indices_map()) - }) - .cloned(), - ); - // Use the current slot to find the fork version, and convert all messages to the - // current fork's format. This is to ensure consistent message types matching - // `Eth-Consensus-Version`. - let current_slot = - chain - .slot_clock - .now() - .ok_or(warp_utils::reject::custom_server_error( - "unable to read slot clock".to_string(), - ))?; - let fork_name = chain.spec.fork_name_at_slot::(current_slot); - let attestations = attestations - .into_iter() - .filter(|att| { - (fork_name.electra_enabled() && matches!(att, Attestation::Electra(_))) - || (!fork_name.electra_enabled() - && matches!(att, Attestation::Base(_))) - }) - .collect::>(); - - let require_version = match endpoint_version { - V1 => ResponseIncludesVersion::No, - V2 => ResponseIncludesVersion::Yes(fork_name), - _ => return Err(unsupported_version_rejection(endpoint_version)), - }; - - let res = beacon_response(require_version, &attestations); - Ok(add_consensus_version_header( - warp::reply::json(&res).into_response(), - fork_name, - )) - }) - }, - ); + let get_beacon_pool_attestations = get_beacon_pool_attestations(&beacon_pool_path_any); // POST beacon/pool/attester_slashings - let post_beacon_pool_attester_slashings = beacon_pool_path_any - .clone() - .and(warp::path("attester_slashings")) - .and(warp::path::end()) - .and(warp_utils::json::json()) - .and(network_tx_filter.clone()) - .then( - // V1 and V2 are identical except V2 has a consensus version header in the request. - // We only require this header for SSZ deserialization, which isn't supported for - // this endpoint presently. - |_endpoint_version: EndpointVersion, - task_spawner: TaskSpawner, - chain: Arc>, - slashing: AttesterSlashing, - network_tx: UnboundedSender>| { - task_spawner.blocking_json_task(Priority::P0, move || { - let outcome = chain - .verify_attester_slashing_for_gossip(slashing.clone()) - .map_err(|e| { - warp_utils::reject::object_invalid(format!( - "gossip verification failed: {:?}", - e - )) - })?; - - // Notify the validator monitor. - chain - .validator_monitor - .read() - .register_api_attester_slashing(slashing.to_ref()); - - if let ObservationOutcome::New(slashing) = outcome { - publish_pubsub_message( - &network_tx, - PubsubMessage::AttesterSlashing(Box::new( - slashing.clone().into_inner(), - )), - )?; - - chain.import_attester_slashing(slashing); - } - - Ok(()) - }) - }, - ); + let post_beacon_pool_attester_slashings = + post_beacon_pool_attester_slashings(&network_tx_filter, &beacon_pool_path_any); // GET beacon/pool/attester_slashings let get_beacon_pool_attester_slashings = - beacon_pool_path_any - .clone() - .and(warp::path("attester_slashings")) - .and(warp::path::end()) - .then( - |endpoint_version: EndpointVersion, - task_spawner: TaskSpawner, - chain: Arc>| { - task_spawner.blocking_response_task(Priority::P1, move || { - let slashings = chain.op_pool.get_all_attester_slashings(); - - // Use the current slot to find the fork version, and convert all messages to the - // current fork's format. This is to ensure consistent message types matching - // `Eth-Consensus-Version`. - let current_slot = chain.slot_clock.now().ok_or( - warp_utils::reject::custom_server_error( - "unable to read slot clock".to_string(), - ), - )?; - let fork_name = chain.spec.fork_name_at_slot::(current_slot); - let slashings = slashings - .into_iter() - .filter(|slashing| { - (fork_name.electra_enabled() - && matches!(slashing, AttesterSlashing::Electra(_))) - || (!fork_name.electra_enabled() - && matches!(slashing, AttesterSlashing::Base(_))) - }) - .collect::>(); - - let require_version = match endpoint_version { - V1 => ResponseIncludesVersion::No, - V2 => ResponseIncludesVersion::Yes(fork_name), - _ => return Err(unsupported_version_rejection(endpoint_version)), - }; - - let res = beacon_response(require_version, &slashings); - Ok(add_consensus_version_header( - warp::reply::json(&res).into_response(), - fork_name, - )) - }) - }, - ); + get_beacon_pool_attester_slashings(&beacon_pool_path_any); // POST beacon/pool/proposer_slashings - let post_beacon_pool_proposer_slashings = beacon_pool_path - .clone() - .and(warp::path("proposer_slashings")) - .and(warp::path::end()) - .and(warp_utils::json::json()) - .and(network_tx_filter.clone()) - .then( - |task_spawner: TaskSpawner, - chain: Arc>, - slashing: ProposerSlashing, - network_tx: UnboundedSender>| { - task_spawner.blocking_json_task(Priority::P0, move || { - let outcome = chain - .verify_proposer_slashing_for_gossip(slashing.clone()) - .map_err(|e| { - warp_utils::reject::object_invalid(format!( - "gossip verification failed: {:?}", - e - )) - })?; - - // Notify the validator monitor. - chain - .validator_monitor - .read() - .register_api_proposer_slashing(&slashing); - - if let ObservationOutcome::New(slashing) = outcome { - publish_pubsub_message( - &network_tx, - PubsubMessage::ProposerSlashing(Box::new( - slashing.clone().into_inner(), - )), - )?; - - chain.import_proposer_slashing(slashing); - } - - Ok(()) - }) - }, - ); + let post_beacon_pool_proposer_slashings = + post_beacon_pool_proposer_slashings(&network_tx_filter, &beacon_pool_path); // GET beacon/pool/proposer_slashings - let get_beacon_pool_proposer_slashings = beacon_pool_path - .clone() - .and(warp::path("proposer_slashings")) - .and(warp::path::end()) - .then( - |task_spawner: TaskSpawner, chain: Arc>| { - task_spawner.blocking_json_task(Priority::P1, move || { - let attestations = chain.op_pool.get_all_proposer_slashings(); - Ok(api_types::GenericResponse::from(attestations)) - }) - }, - ); + let get_beacon_pool_proposer_slashings = get_beacon_pool_proposer_slashings(&beacon_pool_path); // POST beacon/pool/voluntary_exits - let post_beacon_pool_voluntary_exits = beacon_pool_path - .clone() - .and(warp::path("voluntary_exits")) - .and(warp::path::end()) - .and(warp_utils::json::json()) - .and(network_tx_filter.clone()) - .then( - |task_spawner: TaskSpawner, - chain: Arc>, - exit: SignedVoluntaryExit, - network_tx: UnboundedSender>| { - task_spawner.blocking_json_task(Priority::P0, move || { - let outcome = chain - .verify_voluntary_exit_for_gossip(exit.clone()) - .map_err(|e| { - warp_utils::reject::object_invalid(format!( - "gossip verification failed: {:?}", - e - )) - })?; - - // Notify the validator monitor. - chain - .validator_monitor - .read() - .register_api_voluntary_exit(&exit.message); - - if let ObservationOutcome::New(exit) = outcome { - publish_pubsub_message( - &network_tx, - PubsubMessage::VoluntaryExit(Box::new(exit.clone().into_inner())), - )?; - - chain.import_voluntary_exit(exit); - } - - Ok(()) - }) - }, - ); + let post_beacon_pool_voluntary_exits = + post_beacon_pool_voluntary_exits(&network_tx_filter, &beacon_pool_path); // GET beacon/pool/voluntary_exits - let get_beacon_pool_voluntary_exits = beacon_pool_path - .clone() - .and(warp::path("voluntary_exits")) - .and(warp::path::end()) - .then( - |task_spawner: TaskSpawner, chain: Arc>| { - task_spawner.blocking_json_task(Priority::P1, move || { - let attestations = chain.op_pool.get_all_voluntary_exits(); - Ok(api_types::GenericResponse::from(attestations)) - }) - }, - ); + let get_beacon_pool_voluntary_exits = get_beacon_pool_voluntary_exits(&beacon_pool_path); // POST beacon/pool/sync_committees - let post_beacon_pool_sync_committees = beacon_pool_path - .clone() - .and(warp::path("sync_committees")) - .and(warp::path::end()) - .and(warp_utils::json::json()) - .and(network_tx_filter.clone()) - .then( - |task_spawner: TaskSpawner, - chain: Arc>, - signatures: Vec, - network_tx: UnboundedSender>| { - task_spawner.blocking_json_task(Priority::P0, move || { - sync_committees::process_sync_committee_signatures( - signatures, network_tx, &chain, - )?; - Ok(api_types::GenericResponse::from(())) - }) - }, - ); + let post_beacon_pool_sync_committees = + post_beacon_pool_sync_committees(&network_tx_filter, &beacon_pool_path); // GET beacon/pool/bls_to_execution_changes - let get_beacon_pool_bls_to_execution_changes = beacon_pool_path - .clone() - .and(warp::path("bls_to_execution_changes")) - .and(warp::path::end()) - .then( - |task_spawner: TaskSpawner, chain: Arc>| { - task_spawner.blocking_json_task(Priority::P1, move || { - let address_changes = chain.op_pool.get_all_bls_to_execution_changes(); - Ok(api_types::GenericResponse::from(address_changes)) - }) - }, - ); + let get_beacon_pool_bls_to_execution_changes = + get_beacon_pool_bls_to_execution_changes(&beacon_pool_path); // POST beacon/pool/bls_to_execution_changes - let post_beacon_pool_bls_to_execution_changes = beacon_pool_path - .clone() - .and(warp::path("bls_to_execution_changes")) - .and(warp::path::end()) - .and(warp_utils::json::json()) - .and(network_tx_filter.clone()) - .then( - |task_spawner: TaskSpawner, - chain: Arc>, - address_changes: Vec, - network_tx: UnboundedSender>| { - task_spawner.blocking_json_task(Priority::P0, move || { - let mut failures = vec![]; - - for (index, address_change) in address_changes.into_iter().enumerate() { - let validator_index = address_change.message.validator_index; - - match chain.verify_bls_to_execution_change_for_http_api(address_change) { - Ok(ObservationOutcome::New(verified_address_change)) => { - let validator_index = - verified_address_change.as_inner().message.validator_index; - let address = verified_address_change - .as_inner() - .message - .to_execution_address; - - // New to P2P *and* op pool, gossip immediately if post-Capella. - 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( - verified_address_change.as_inner().clone(), - )), - )?; - } - - // Import to op pool (may return `false` if there's a race). - let imported = chain.import_bls_to_execution_change( - verified_address_change, - received_pre_capella, - ); - - info!( - %validator_index, - ?address, - published = - matches!(received_pre_capella, ReceivedPreCapella::No), - imported, - "Processed BLS to execution change" - ); - } - Ok(ObservationOutcome::AlreadyKnown) => { - debug!(%validator_index, "BLS to execution change already known"); - } - Err(e) => { - warn!( - validator_index, - reason = ?e, - source = "HTTP", - "Invalid BLS to execution change" - ); - failures.push(api_types::Failure::new( - index, - format!("invalid: {e:?}"), - )); - } - } - } - - if failures.is_empty() { - Ok(()) - } else { - Err(warp_utils::reject::indexed_bad_request( - "some BLS to execution changes failed to verify".into(), - failures, - )) - } - }) - }, - ); + let post_beacon_pool_bls_to_execution_changes = + post_beacon_pool_bls_to_execution_changes(&network_tx_filter, &beacon_pool_path); let beacon_rewards_path = eth_v1 + .clone() .and(warp::path("beacon")) .and(warp::path("rewards")) .and(task_spawner_filter.clone()) @@ -1854,6 +1497,7 @@ pub fn serve( */ let builder_states_path = eth_v1 + .clone() .and(warp::path("builder")) .and(warp::path("states")) .and(chain_filter.clone()); @@ -1908,6 +1552,7 @@ pub fn serve( */ let beacon_light_client_path = eth_v1 + .clone() .and(warp::path("beacon")) .and(warp::path("light_client")) .and(light_client_server_filter) @@ -2060,6 +1705,7 @@ pub fn serve( */ let beacon_rewards_path = eth_v1 + .clone() .and(warp::path("beacon")) .and(warp::path("rewards")) .and(task_spawner_filter.clone()) @@ -2144,10 +1790,11 @@ pub fn serve( * config */ - let config_path = eth_v1.and(warp::path("config")); + let config_path = eth_v1.clone().and(warp::path("config")); // GET config/fork_schedule let get_config_fork_schedule = config_path + .clone() .and(warp::path("fork_schedule")) .and(warp::path::end()) .and(task_spawner_filter.clone()) @@ -2166,6 +1813,7 @@ pub fn serve( // GET config/spec let get_config_spec = config_path + .clone() .and(warp::path("spec")) .and(warp::path::end()) .and(task_spawner_filter.clone()) @@ -2205,6 +1853,7 @@ pub fn serve( // GET debug/beacon/data_column_sidecars/{block_id} let get_debug_data_column_sidecars = eth_v1 + .clone() .and(warp::path("debug")) .and(warp::path("beacon")) .and(warp::path("data_column_sidecars")) @@ -2254,6 +1903,7 @@ pub fn serve( // GET debug/beacon/states/{state_id} let get_debug_beacon_states = any_version + .clone() .and(warp::path("debug")) .and(warp::path("beacon")) .and(warp::path("states")) @@ -2329,6 +1979,7 @@ pub fn serve( // GET debug/beacon/heads let get_debug_beacon_heads = any_version + .clone() .and(warp::path("debug")) .and(warp::path("beacon")) .and(warp::path("heads")) @@ -2369,6 +2020,7 @@ pub fn serve( // GET debug/fork_choice let get_debug_fork_choice = eth_v1 + .clone() .and(warp::path("debug")) .and(warp::path("fork_choice")) .and(warp::path::end()) @@ -2450,6 +2102,7 @@ pub fn serve( // GET node/identity let get_node_identity = eth_v1 + .clone() .and(warp::path("node")) .and(warp::path("identity")) .and(warp::path::end()) @@ -2466,10 +2119,13 @@ pub fn serve( let discovery_addresses = enr.multiaddr_p2p_udp(); Ok(api_types::GenericResponse::from(api_types::IdentityData { peer_id: network_globals.local_peer_id().to_base58(), - enr, - p2p_addresses, - discovery_addresses, - metadata: from_meta_data::( + enr: enr.to_base64(), + p2p_addresses: p2p_addresses.iter().map(|a| a.to_string()).collect(), + discovery_addresses: discovery_addresses + .iter() + .map(|a| a.to_string()) + .collect(), + metadata: utils::from_meta_data::( &network_globals.local_metadata, &chain.spec, ), @@ -2480,6 +2136,7 @@ pub fn serve( // GET node/version let get_node_version = eth_v1 + .clone() .and(warp::path("node")) .and(warp::path("version")) .and(warp::path::end()) @@ -2493,6 +2150,7 @@ pub fn serve( // GET node/syncing let get_node_syncing = eth_v1 + .clone() .and(warp::path("node")) .and(warp::path("syncing")) .and(warp::path::end()) @@ -2554,6 +2212,7 @@ pub fn serve( // GET node/health let get_node_health = eth_v1 + .clone() .and(warp::path("node")) .and(warp::path("health")) .and(warp::path::end()) @@ -2602,6 +2261,7 @@ pub fn serve( // GET node/peers/{peer_id} let get_node_peers_by_id = eth_v1 + .clone() .and(warp::path("node")) .and(warp::path("peers")) .and(warp::path::param::()) @@ -2656,6 +2316,7 @@ pub fn serve( // GET node/peers let get_node_peers = eth_v1 + .clone() .and(warp::path("node")) .and(warp::path("peers")) .and(warp::path::end()) @@ -2720,6 +2381,7 @@ pub fn serve( // GET node/peer_count let get_node_peer_count = eth_v1 + .clone() .and(warp::path("node")) .and(warp::path("peer_count")) .and(warp::path::end()) @@ -2763,804 +2425,124 @@ pub fn serve( */ // GET validator/duties/proposer/{epoch} - let get_validator_duties_proposer = eth_v1 - .and(warp::path("validator")) - .and(warp::path("duties")) - .and(warp::path("proposer")) - .and(warp::path::param::().or_else(|_| async { - Err(warp_utils::reject::custom_bad_request( - "Invalid epoch".to_string(), - )) - })) - .and(warp::path::end()) - .and(not_while_syncing_filter.clone()) - .and(task_spawner_filter.clone()) - .and(chain_filter.clone()) - .then( - |epoch: Epoch, - not_synced_filter: Result<(), Rejection>, - task_spawner: TaskSpawner, - chain: Arc>| { - task_spawner.blocking_json_task(Priority::P0, move || { - not_synced_filter?; - proposer_duties::proposer_duties(epoch, &chain) - }) - }, - ); + let get_validator_duties_proposer = get_validator_duties_proposer( + eth_v1.clone().clone(), + chain_filter.clone(), + not_while_syncing_filter.clone(), + task_spawner_filter.clone(), + ); // GET validator/blocks/{slot} - let get_validator_blocks = any_version - .and(warp::path("validator")) - .and(warp::path("blocks")) - .and(warp::path::param::().or_else(|_| async { - Err(warp_utils::reject::custom_bad_request( - "Invalid slot".to_string(), - )) - })) - .and(warp::path::end()) - .and(warp::header::optional::("accept")) - .and(not_while_syncing_filter.clone()) - .and(warp::query::()) - .and(task_spawner_filter.clone()) - .and(chain_filter.clone()) - .then( - |endpoint_version: EndpointVersion, - slot: Slot, - accept_header: Option, - not_synced_filter: Result<(), Rejection>, - query: api_types::ValidatorBlocksQuery, - task_spawner: TaskSpawner, - chain: Arc>| { - task_spawner.spawn_async_with_rejection(Priority::P0, async move { - debug!(?slot, "Block production request from HTTP API"); - - not_synced_filter?; - - if endpoint_version == V3 { - produce_block_v3(accept_header, chain, slot, query).await - } else { - produce_block_v2(accept_header, chain, slot, query).await - } - }) - }, - ); + let get_validator_blocks = get_validator_blocks( + any_version.clone().clone(), + chain_filter.clone(), + not_while_syncing_filter.clone(), + task_spawner_filter.clone(), + ); // GET validator/blinded_blocks/{slot} - let get_validator_blinded_blocks = eth_v1 - .and(warp::path("validator")) - .and(warp::path("blinded_blocks")) - .and(warp::path::param::().or_else(|_| async { - Err(warp_utils::reject::custom_bad_request( - "Invalid slot".to_string(), - )) - })) - .and(warp::path::end()) - .and(not_while_syncing_filter.clone()) - .and(warp::query::()) - .and(warp::header::optional::("accept")) - .and(task_spawner_filter.clone()) - .and(chain_filter.clone()) - .then( - |slot: Slot, - not_synced_filter: Result<(), Rejection>, - query: api_types::ValidatorBlocksQuery, - accept_header: Option, - task_spawner: TaskSpawner, - chain: Arc>| { - task_spawner.spawn_async_with_rejection(Priority::P0, async move { - not_synced_filter?; - produce_blinded_block_v2(accept_header, chain, slot, query).await - }) - }, - ); + let get_validator_blinded_blocks = get_validator_blinded_blocks( + eth_v1.clone().clone(), + chain_filter.clone(), + not_while_syncing_filter.clone(), + task_spawner_filter.clone(), + ); // GET validator/attestation_data?slot,committee_index - let get_validator_attestation_data = eth_v1 - .and(warp::path("validator")) - .and(warp::path("attestation_data")) - .and(warp::path::end()) - .and(warp::query::()) - .and(not_while_syncing_filter.clone()) - .and(task_spawner_filter.clone()) - .and(chain_filter.clone()) - .then( - |query: api_types::ValidatorAttestationDataQuery, - not_synced_filter: Result<(), Rejection>, - task_spawner: TaskSpawner, - chain: Arc>| { - task_spawner.blocking_json_task(Priority::P0, move || { - not_synced_filter?; - - let current_slot = chain.slot().map_err(warp_utils::reject::unhandled_error)?; - - // allow a tolerance of one slot to account for clock skew - if query.slot > current_slot + 1 { - return Err(warp_utils::reject::custom_bad_request(format!( - "request slot {} is more than one slot past the current slot {}", - query.slot, current_slot - ))); - } - - chain - .produce_unaggregated_attestation(query.slot, query.committee_index) - .map(|attestation| attestation.data().clone()) - .map(api_types::GenericResponse::from) - .map_err(warp_utils::reject::unhandled_error) - }) - }, - ); + let get_validator_attestation_data = get_validator_attestation_data( + eth_v1.clone().clone(), + chain_filter.clone(), + not_while_syncing_filter.clone(), + task_spawner_filter.clone(), + ); // GET validator/aggregate_attestation?attestation_data_root,slot - let get_validator_aggregate_attestation = any_version - .and(warp::path("validator")) - .and(warp::path("aggregate_attestation")) - .and(warp::path::end()) - .and(warp::query::()) - .and(not_while_syncing_filter.clone()) - .and(task_spawner_filter.clone()) - .and(chain_filter.clone()) - .then( - |endpoint_version: EndpointVersion, - query: api_types::ValidatorAggregateAttestationQuery, - not_synced_filter: Result<(), Rejection>, - task_spawner: TaskSpawner, - chain: Arc>| { - task_spawner.blocking_response_task(Priority::P0, move || { - not_synced_filter?; - crate::aggregate_attestation::get_aggregate_attestation( - query.slot, - &query.attestation_data_root, - query.committee_index, - endpoint_version, - chain, - ) - }) - }, - ); + let get_validator_aggregate_attestation = get_validator_aggregate_attestation( + any_version.clone().clone(), + chain_filter.clone(), + not_while_syncing_filter.clone(), + task_spawner_filter.clone(), + ); // POST validator/duties/attester/{epoch} - let post_validator_duties_attester = eth_v1 - .and(warp::path("validator")) - .and(warp::path("duties")) - .and(warp::path("attester")) - .and(warp::path::param::().or_else(|_| async { - Err(warp_utils::reject::custom_bad_request( - "Invalid epoch".to_string(), - )) - })) - .and(warp::path::end()) - .and(not_while_syncing_filter.clone()) - .and(warp_utils::json::json()) - .and(task_spawner_filter.clone()) - .and(chain_filter.clone()) - .then( - |epoch: Epoch, - not_synced_filter: Result<(), Rejection>, - indices: api_types::ValidatorIndexData, - task_spawner: TaskSpawner, - chain: Arc>| { - task_spawner.blocking_json_task(Priority::P0, move || { - not_synced_filter?; - attester_duties::attester_duties(epoch, &indices.0, &chain) - }) - }, - ); + let post_validator_duties_attester = post_validator_duties_attester( + eth_v1.clone().clone(), + chain_filter.clone(), + not_while_syncing_filter.clone(), + task_spawner_filter.clone(), + ); // POST validator/duties/sync/{epoch} - let post_validator_duties_sync = eth_v1 - .and(warp::path("validator")) - .and(warp::path("duties")) - .and(warp::path("sync")) - .and(warp::path::param::().or_else(|_| async { - Err(warp_utils::reject::custom_bad_request( - "Invalid epoch".to_string(), - )) - })) - .and(warp::path::end()) - .and(not_while_syncing_filter.clone()) - .and(warp_utils::json::json()) - .and(task_spawner_filter.clone()) - .and(chain_filter.clone()) - .then( - |epoch: Epoch, - not_synced_filter: Result<(), Rejection>, - indices: api_types::ValidatorIndexData, - task_spawner: TaskSpawner, - chain: Arc>| { - task_spawner.blocking_json_task(Priority::P0, move || { - not_synced_filter?; - sync_committees::sync_committee_duties(epoch, &indices.0, &chain) - }) - }, - ); + let post_validator_duties_sync = post_validator_duties_sync( + eth_v1.clone().clone(), + chain_filter.clone(), + not_while_syncing_filter.clone(), + task_spawner_filter.clone(), + ); // GET validator/sync_committee_contribution - let get_validator_sync_committee_contribution = eth_v1 - .and(warp::path("validator")) - .and(warp::path("sync_committee_contribution")) - .and(warp::path::end()) - .and(warp::query::()) - .and(not_while_syncing_filter.clone()) - .and(task_spawner_filter.clone()) - .and(chain_filter.clone()) - .then( - |sync_committee_data: SyncContributionData, - not_synced_filter: Result<(), Rejection>, - task_spawner: TaskSpawner, - chain: Arc>| { - task_spawner.blocking_json_task(Priority::P0, move || { - not_synced_filter?; - chain - .get_aggregated_sync_committee_contribution(&sync_committee_data) - .map_err(|e| { - warp_utils::reject::custom_bad_request(format!( - "unable to fetch sync contribution: {:?}", - e - )) - })? - .map(api_types::GenericResponse::from) - .ok_or_else(|| { - warp_utils::reject::custom_not_found( - "no matching sync contribution found".to_string(), - ) - }) - }) - }, - ); + let get_validator_sync_committee_contribution = get_validator_sync_committee_contribution( + eth_v1.clone().clone(), + chain_filter.clone(), + not_while_syncing_filter.clone(), + task_spawner_filter.clone(), + ); // POST validator/aggregate_and_proofs - let post_validator_aggregate_and_proofs = any_version - .and(warp::path("validator")) - .and(warp::path("aggregate_and_proofs")) - .and(warp::path::end()) - .and(not_while_syncing_filter.clone()) - .and(task_spawner_filter.clone()) - .and(chain_filter.clone()) - .and(warp_utils::json::json()) - .and(network_tx_filter.clone()) - .then( - // V1 and V2 are identical except V2 has a consensus version header in the request. - // We only require this header for SSZ deserialization, which isn't supported for - // this endpoint presently. - |_endpoint_version: EndpointVersion, - not_synced_filter: Result<(), Rejection>, - task_spawner: TaskSpawner, - chain: Arc>, - aggregates: Vec>, - network_tx: UnboundedSender>| { - task_spawner.blocking_json_task(Priority::P0, move || { - not_synced_filter?; - let seen_timestamp = timestamp_now(); - let mut verified_aggregates = Vec::with_capacity(aggregates.len()); - let mut messages = Vec::with_capacity(aggregates.len()); - let mut failures = Vec::new(); + let post_validator_aggregate_and_proofs = post_validator_aggregate_and_proofs( + any_version.clone().clone(), + chain_filter.clone(), + network_tx_filter.clone(), + not_while_syncing_filter.clone(), + task_spawner_filter.clone(), + ); - // Verify that all messages in the post are valid before processing further - for (index, aggregate) in aggregates.iter().enumerate() { - match chain.verify_aggregated_attestation_for_gossip(aggregate) { - Ok(verified_aggregate) => { - messages.push(PubsubMessage::AggregateAndProofAttestation(Box::new( - verified_aggregate.aggregate().clone(), - ))); - - // Notify the validator monitor. - chain - .validator_monitor - .read() - .register_api_aggregated_attestation( - seen_timestamp, - verified_aggregate.aggregate(), - verified_aggregate.indexed_attestation(), - &chain.slot_clock, - ); - - verified_aggregates.push((index, verified_aggregate)); - } - // If we already know the attestation, don't broadcast it or attempt to - // further verify it. Return success. - // - // It's reasonably likely that two different validators produce - // identical aggregates, especially if they're using the same beacon - // node. - Err(AttnError::AttestationSupersetKnown(_)) => continue, - // If we've already seen this aggregator produce an aggregate, just - // skip this one. - // - // We're likely to see this with VCs that use fallback BNs. The first - // BN might time-out *after* publishing the aggregate and then the - // second BN will indicate it's already seen the aggregate. - // - // There's no actual error for the user or the network since the - // aggregate has been successfully published by some other node. - Err(AttnError::AggregatorAlreadyKnown(_)) => continue, - Err(e) => { - error!( - error = ?e, - request_index = index, - aggregator_index = aggregate.message().aggregator_index(), - attestation_index = aggregate.message().aggregate().committee_index(), - attestation_slot = %aggregate.message().aggregate().data().slot, - "Failure verifying aggregate and proofs" - ); - failures.push(api_types::Failure::new(index, format!("Verification: {:?}", e))); - } - } - } - - // Publish aggregate attestations to the libp2p network - if !messages.is_empty() { - publish_network_message(&network_tx, NetworkMessage::Publish { messages })?; - } - - // Import aggregate attestations - for (index, verified_aggregate) in verified_aggregates { - if let Err(e) = chain.apply_attestation_to_fork_choice(&verified_aggregate) { - error!( - error = ?e, - request_index = index, - aggregator_index = verified_aggregate.aggregate().message().aggregator_index(), - attestation_index = verified_aggregate.attestation().committee_index(), - attestation_slot = %verified_aggregate.attestation().data().slot, - "Failure applying verified aggregate attestation to fork choice" - ); - failures.push(api_types::Failure::new(index, format!("Fork choice: {:?}", e))); - } - if let Err(e) = chain.add_to_block_inclusion_pool(verified_aggregate) { - warn!( - error = ?e, - request_index = index, - "Could not add verified aggregate attestation to the inclusion pool" - ); - failures.push(api_types::Failure::new(index, format!("Op pool: {:?}", e))); - } - } - - if !failures.is_empty() { - Err(warp_utils::reject::indexed_bad_request("error processing aggregate and proofs".to_string(), - failures, - )) - } else { - Ok(()) - } - }) - }, - ); - - let post_validator_contribution_and_proofs = eth_v1 - .and(warp::path("validator")) - .and(warp::path("contribution_and_proofs")) - .and(warp::path::end()) - .and(not_while_syncing_filter.clone()) - .and(task_spawner_filter.clone()) - .and(chain_filter.clone()) - .and(warp_utils::json::json()) - .and(network_tx_filter.clone()) - .then( - |not_synced_filter: Result<(), Rejection>, - task_spawner: TaskSpawner, - chain: Arc>, - contributions: Vec>, - network_tx: UnboundedSender>| { - task_spawner.blocking_json_task(Priority::P0, move || { - not_synced_filter?; - sync_committees::process_signed_contribution_and_proofs( - contributions, - network_tx, - &chain, - )?; - Ok(api_types::GenericResponse::from(())) - }) - }, - ); + let post_validator_contribution_and_proofs = post_validator_contribution_and_proofs( + eth_v1.clone().clone(), + chain_filter.clone(), + network_tx_filter.clone(), + not_while_syncing_filter.clone(), + task_spawner_filter.clone(), + ); // POST validator/beacon_committee_subscriptions - let post_validator_beacon_committee_subscriptions = eth_v1 - .and(warp::path("validator")) - .and(warp::path("beacon_committee_subscriptions")) - .and(warp::path::end()) - .and(warp_utils::json::json()) - .and(validator_subscription_tx_filter.clone()) - .and(task_spawner_filter.clone()) - .and(chain_filter.clone()) - .then( - |committee_subscriptions: Vec, - validator_subscription_tx: Sender, - task_spawner: TaskSpawner, - chain: Arc>| { - task_spawner.blocking_json_task(Priority::P0, move || { - let subscriptions: std::collections::BTreeSet<_> = committee_subscriptions - .iter() - .map(|subscription| { - chain - .validator_monitor - .write() - .auto_register_local_validator(subscription.validator_index); - api_types::ValidatorSubscription { - attestation_committee_index: subscription.committee_index, - slot: subscription.slot, - committee_count_at_slot: subscription.committees_at_slot, - is_aggregator: subscription.is_aggregator, - } - }) - .collect(); - - let message = - ValidatorSubscriptionMessage::AttestationSubscribe { subscriptions }; - if let Err(e) = validator_subscription_tx.try_send(message) { - warn!( - info = "the host may be overloaded or resource-constrained", - error = ?e, - "Unable to process committee subscriptions" - ); - return Err(warp_utils::reject::custom_server_error( - "unable to queue subscription, host may be overloaded or shutting down" - .to_string(), - )); - } - Ok(()) - }) - }, + let post_validator_beacon_committee_subscriptions = + post_validator_beacon_committee_subscriptions( + eth_v1.clone().clone(), + chain_filter.clone(), + validator_subscription_tx_filter.clone(), + task_spawner_filter.clone(), ); // POST validator/prepare_beacon_proposer - let post_validator_prepare_beacon_proposer = eth_v1 - .and(warp::path("validator")) - .and(warp::path("prepare_beacon_proposer")) - .and(warp::path::end()) - .and(not_while_syncing_filter.clone()) - .and(network_tx_filter.clone()) - .and(task_spawner_filter.clone()) - .and(chain_filter.clone()) - .and(warp_utils::json::json()) - .then( - |not_synced_filter: Result<(), Rejection>, - network_tx: UnboundedSender>, - task_spawner: TaskSpawner, - chain: Arc>, - preparation_data: Vec| { - task_spawner.spawn_async_with_rejection(Priority::P0, async move { - not_synced_filter?; - let execution_layer = chain - .execution_layer - .as_ref() - .ok_or(BeaconChainError::ExecutionLayerMissing) - .map_err(warp_utils::reject::unhandled_error)?; - - let current_slot = chain - .slot_clock - .now_or_genesis() - .ok_or(BeaconChainError::UnableToReadSlot) - .map_err(warp_utils::reject::unhandled_error)?; - let current_epoch = current_slot.epoch(T::EthSpec::slots_per_epoch()); - - debug!( - count = preparation_data.len(), - "Received proposer preparation data" - ); - - execution_layer - .update_proposer_preparation( - current_epoch, - preparation_data.iter().map(|data| (data, &None)), - ) - .await; - - chain - .prepare_beacon_proposer(current_slot) - .await - .map_err(|e| { - warp_utils::reject::custom_bad_request(format!( - "error updating proposer preparations: {:?}", - e - )) - })?; - - if chain.spec.is_peer_das_scheduled() { - let (finalized_beacon_state, _, _) = - StateId(CoreStateId::Finalized).state(&chain)?; - let validators_and_balances = preparation_data - .iter() - .filter_map(|preparation| { - if let Ok(effective_balance) = finalized_beacon_state - .get_effective_balance(preparation.validator_index as usize) - { - Some((preparation.validator_index as usize, effective_balance)) - } else { - None - } - }) - .collect::>(); - - let current_slot = - chain.slot().map_err(warp_utils::reject::unhandled_error)?; - if let Some(cgc_change) = chain - .data_availability_checker - .custody_context() - .register_validators(validators_and_balances, current_slot, &chain.spec) - { - chain.update_data_column_custody_info(Some( - cgc_change - .effective_epoch - .start_slot(T::EthSpec::slots_per_epoch()), - )); - - network_tx.send(NetworkMessage::CustodyCountChanged { - new_custody_group_count: cgc_change.new_custody_group_count, - sampling_count: cgc_change.sampling_count, - }).unwrap_or_else(|e| { - debug!(error = %e, "Could not send message to the network service. \ - Likely shutdown") - }); - } - } - - Ok::<_, warp::reject::Rejection>(warp::reply::json(&()).into_response()) - }) - }, - ); + let post_validator_prepare_beacon_proposer = post_validator_prepare_beacon_proposer( + eth_v1.clone().clone(), + chain_filter.clone(), + network_tx_filter.clone(), + not_while_syncing_filter.clone(), + task_spawner_filter.clone(), + ); // POST validator/register_validator - let post_validator_register_validator = eth_v1 - .and(warp::path("validator")) - .and(warp::path("register_validator")) - .and(warp::path::end()) - .and(task_spawner_filter.clone()) - .and(chain_filter.clone()) - .and(warp_utils::json::json()) - .then( - |task_spawner: TaskSpawner, - chain: Arc>, - register_val_data: Vec| async { - let (tx, rx) = oneshot::channel(); - - let initial_result = task_spawner - .spawn_async_with_rejection_no_conversion(Priority::P0, async move { - let execution_layer = chain - .execution_layer - .as_ref() - .ok_or(BeaconChainError::ExecutionLayerMissing) - .map_err(warp_utils::reject::unhandled_error)?; - let current_slot = chain - .slot_clock - .now_or_genesis() - .ok_or(BeaconChainError::UnableToReadSlot) - .map_err(warp_utils::reject::unhandled_error)?; - let current_epoch = current_slot.epoch(T::EthSpec::slots_per_epoch()); - - debug!( - count = register_val_data.len(), - "Received register validator request" - ); - - let head_snapshot = chain.head_snapshot(); - let spec = &chain.spec; - - let (preparation_data, filtered_registration_data): ( - Vec<(ProposerPreparationData, Option)>, - Vec, - ) = register_val_data - .into_iter() - .filter_map(|register_data| { - chain - .validator_index(®ister_data.message.pubkey) - .ok() - .flatten() - .and_then(|validator_index| { - let validator = head_snapshot - .beacon_state - .get_validator(validator_index) - .ok()?; - let validator_status = ValidatorStatus::from_validator( - validator, - current_epoch, - spec.far_future_epoch, - ) - .superstatus(); - let is_active_or_pending = - matches!(validator_status, ValidatorStatus::Pending) - || matches!( - validator_status, - ValidatorStatus::Active - ); - - // Filter out validators who are not 'active' or 'pending'. - is_active_or_pending.then_some({ - ( - ( - ProposerPreparationData { - validator_index: validator_index as u64, - fee_recipient: register_data - .message - .fee_recipient, - }, - Some(register_data.message.gas_limit), - ), - register_data, - ) - }) - }) - }) - .unzip(); - - // Update the prepare beacon proposer cache based on this request. - execution_layer - .update_proposer_preparation( - current_epoch, - preparation_data.iter().map(|(data, limit)| (data, limit)), - ) - .await; - - // Call prepare beacon proposer blocking with the latest update in order to make - // sure we have a local payload to fall back to in the event of the blinded block - // flow failing. - chain - .prepare_beacon_proposer(current_slot) - .await - .map_err(|e| { - warp_utils::reject::custom_bad_request(format!( - "error updating proposer preparations: {:?}", - e - )) - })?; - - info!( - count = filtered_registration_data.len(), - "Forwarding register validator request to connected builder" - ); - - // It's a waste of a `BeaconProcessor` worker to just - // wait on a response from the builder (especially since - // they have frequent timeouts). Spawn a new task and - // send the response back to our original HTTP request - // task via a channel. - let builder_future = async move { - let arc_builder = chain - .execution_layer - .as_ref() - .ok_or(BeaconChainError::ExecutionLayerMissing) - .map_err(warp_utils::reject::unhandled_error)? - .builder(); - let builder = arc_builder - .as_ref() - .ok_or(BeaconChainError::BuilderMissing) - .map_err(warp_utils::reject::unhandled_error)?; - builder - .post_builder_validators(&filtered_registration_data) - .await - .map(|resp| warp::reply::json(&resp).into_response()) - .map_err(|e| { - warn!( - num_registrations = filtered_registration_data.len(), - error = ?e, - "Relay error when registering validator(s)" - ); - // Forward the HTTP status code if we are able to, otherwise fall back - // to a server error. - if let eth2::Error::ServerMessage(message) = e { - if message.code == StatusCode::BAD_REQUEST.as_u16() { - return warp_utils::reject::custom_bad_request( - message.message, - ); - } else { - // According to the spec this response should only be a 400 or 500, - // so we fall back to a 500 here. - return warp_utils::reject::custom_server_error( - message.message, - ); - } - } - warp_utils::reject::custom_server_error(format!("{e:?}")) - }) - }; - tokio::task::spawn(async move { tx.send(builder_future.await) }); - - // Just send a generic 200 OK from this closure. We'll - // ignore the `Ok` variant and form a proper response - // from what is sent back down the channel. - Ok(warp::reply::reply().into_response()) - }) - .await; - - if initial_result.is_err() { - return convert_rejection(initial_result).await; - } - - // Await a response from the builder without blocking a - // `BeaconProcessor` worker. - convert_rejection(rx.await.unwrap_or_else(|_| { - Ok(warp::reply::with_status( - warp::reply::json(&"No response from channel"), - warp::http::StatusCode::INTERNAL_SERVER_ERROR, - ) - .into_response()) - })) - .await - }, - ); + let post_validator_register_validator = post_validator_register_validator( + eth_v1.clone().clone(), + chain_filter.clone(), + task_spawner_filter.clone(), + ); // POST validator/sync_committee_subscriptions - let post_validator_sync_committee_subscriptions = eth_v1 - .and(warp::path("validator")) - .and(warp::path("sync_committee_subscriptions")) - .and(warp::path::end()) - .and(warp_utils::json::json()) - .and(validator_subscription_tx_filter) - .and(task_spawner_filter.clone()) - .and(chain_filter.clone()) - .then( - |subscriptions: Vec, - validator_subscription_tx: Sender, - task_spawner: TaskSpawner, - chain: Arc>, - | { - task_spawner.blocking_json_task(Priority::P0, move || { - for subscription in subscriptions { - chain - .validator_monitor - .write() - .auto_register_local_validator(subscription.validator_index); - - let message = ValidatorSubscriptionMessage::SyncCommitteeSubscribe { - subscriptions: vec![subscription], - }; - if let Err(e) = validator_subscription_tx.try_send(message) { - warn!( - info = "the host may be overloaded or resource-constrained", - error = ?e, - "Unable to process sync subscriptions" - ); - return Err(warp_utils::reject::custom_server_error( - "unable to queue subscription, host may be overloaded or shutting down".to_string(), - )); - } - } - - Ok(()) - }) - }, - ); + let post_validator_sync_committee_subscriptions = post_validator_sync_committee_subscriptions( + eth_v1.clone().clone(), + chain_filter.clone(), + validator_subscription_tx_filter.clone(), + task_spawner_filter.clone(), + ); // POST validator/liveness/{epoch} - let post_validator_liveness_epoch = eth_v1 - .and(warp::path("validator")) - .and(warp::path("liveness")) - .and(warp::path::param::()) - .and(warp::path::end()) - .and(warp_utils::json::json()) - .and(task_spawner_filter.clone()) - .and(chain_filter.clone()) - .then( - |epoch: Epoch, - indices: api_types::ValidatorIndexData, - task_spawner: TaskSpawner, - chain: Arc>| { - task_spawner.blocking_json_task(Priority::P0, move || { - // Ensure the request is for either the current, previous or next epoch. - let current_epoch = - chain.epoch().map_err(warp_utils::reject::unhandled_error)?; - let prev_epoch = current_epoch.saturating_sub(Epoch::new(1)); - let next_epoch = current_epoch.saturating_add(Epoch::new(1)); - - if epoch < prev_epoch || epoch > next_epoch { - return Err(warp_utils::reject::custom_bad_request(format!( - "request epoch {} is more than one epoch from the current epoch {}", - epoch, current_epoch - ))); - } - - let liveness: Vec = indices - .0 - .iter() - .cloned() - .map(|index| { - let is_live = chain.validator_seen_at_epoch(index as usize, epoch); - api_types::StandardLivenessResponseData { index, is_live } - }) - .collect(); - - Ok(api_types::GenericResponse::from(liveness)) - }) - }, - ); + let post_validator_liveness_epoch = post_validator_liveness_epoch( + eth_v1.clone().clone(), + chain_filter.clone(), + task_spawner_filter.clone(), + ); // POST lighthouse/finalize let post_lighthouse_finalize = warp::path("lighthouse") @@ -3632,7 +2614,10 @@ pub fn serve( ); network_globals.add_trusted_peer(enr.clone()); - publish_network_message(&network_tx, NetworkMessage::ConnectTrustedPeer(enr))?; + utils::publish_network_message( + &network_tx, + NetworkMessage::ConnectTrustedPeer(enr), + )?; Ok(()) }) @@ -3663,7 +2648,7 @@ pub fn serve( ); network_globals.remove_trusted_peer(enr.clone()); - publish_network_message( + utils::publish_network_message( &network_tx, NetworkMessage::DisconnectTrustedPeer(enr), )?; @@ -4115,6 +3100,7 @@ pub fn serve( ); let get_events = eth_v1 + .clone() .and(warp::path("events")) .and(warp::path::end()) .and(multi_key_query::()) @@ -4436,70 +3422,3 @@ pub fn serve( Ok(http_server) } - -fn from_meta_data( - meta_data: &RwLock>, - spec: &ChainSpec, -) -> api_types::MetaData { - let meta_data = meta_data.read(); - let format_hex = |bytes: &[u8]| format!("0x{}", hex::encode(bytes)); - - let seq_number = *meta_data.seq_number(); - let attnets = format_hex(&meta_data.attnets().clone().into_bytes()); - let syncnets = format_hex( - &meta_data - .syncnets() - .cloned() - .unwrap_or_default() - .into_bytes(), - ); - - if spec.is_peer_das_scheduled() { - api_types::MetaData::V3(api_types::MetaDataV3 { - seq_number, - attnets, - syncnets, - custody_group_count: meta_data.custody_group_count().cloned().unwrap_or_default(), - }) - } else { - api_types::MetaData::V2(api_types::MetaDataV2 { - seq_number, - attnets, - syncnets, - }) - } -} - -/// Publish a message to the libp2p pubsub network. -fn publish_pubsub_message( - network_tx: &UnboundedSender>, - message: PubsubMessage, -) -> Result<(), warp::Rejection> { - publish_network_message( - network_tx, - NetworkMessage::Publish { - messages: vec![message], - }, - ) -} - -/// Publish a message to the libp2p pubsub network. -fn publish_pubsub_messages( - network_tx: &UnboundedSender>, - messages: Vec>, -) -> Result<(), warp::Rejection> { - publish_network_message(network_tx, NetworkMessage::Publish { messages }) -} - -/// Publish a message to the libp2p network. -fn publish_network_message( - network_tx: &UnboundedSender>, - message: NetworkMessage, -) -> Result<(), warp::Rejection> { - network_tx.send(message).map_err(|e| { - warp_utils::reject::custom_server_error(format!( - "unable to publish to network channel: {}", - e - )) - }) -} diff --git a/beacon_node/http_api/src/publish_blocks.rs b/beacon_node/http_api/src/publish_blocks.rs index 9671a72da2..b54c071eb8 100644 --- a/beacon_node/http_api/src/publish_blocks.rs +++ b/beacon_node/http_api/src/publish_blocks.rs @@ -138,9 +138,10 @@ pub async fn publish_block>( "Signed block published to network via HTTP API" ); - crate::publish_pubsub_message(&sender, PubsubMessage::BeaconBlock(block.clone())).map_err( - |_| BlockError::BeaconChainError(Box::new(BeaconChainError::UnableToPublish)), - )?; + crate::utils::publish_pubsub_message(&sender, PubsubMessage::BeaconBlock(block.clone())) + .map_err(|_| { + BlockError::BeaconChainError(Box::new(BeaconChainError::UnableToPublish)) + })?; Ok(()) }; @@ -492,7 +493,7 @@ fn publish_blob_sidecars( blob: &GossipVerifiedBlob, ) -> Result<(), BlockError> { let pubsub_message = PubsubMessage::BlobSidecar(Box::new((blob.index(), blob.clone_blob()))); - crate::publish_pubsub_message(sender_clone, pubsub_message) + crate::utils::publish_pubsub_message(sender_clone, pubsub_message) .map_err(|_| BlockError::BeaconChainError(Box::new(BeaconChainError::UnableToPublish))) } @@ -525,7 +526,7 @@ fn publish_column_sidecars( PubsubMessage::DataColumnSidecar(Box::new((subnet, data_col))) }) .collect::>(); - crate::publish_pubsub_messages(sender_clone, pubsub_messages) + crate::utils::publish_pubsub_messages(sender_clone, pubsub_messages) .map_err(|_| BlockError::BeaconChainError(Box::new(BeaconChainError::UnableToPublish))) } diff --git a/beacon_node/http_api/src/sync_committees.rs b/beacon_node/http_api/src/sync_committees.rs index edda0e60a6..b9fa24ad6a 100644 --- a/beacon_node/http_api/src/sync_committees.rs +++ b/beacon_node/http_api/src/sync_committees.rs @@ -1,6 +1,6 @@ //! Handlers for sync committee endpoints. -use crate::publish_pubsub_message; +use crate::utils::publish_pubsub_message; use beacon_chain::sync_committee_verification::{ Error as SyncVerificationError, VerifiedSyncCommitteeMessage, }; diff --git a/beacon_node/http_api/src/utils.rs b/beacon_node/http_api/src/utils.rs index cf61fa481c..f2b859ebe5 100644 --- a/beacon_node/http_api/src/utils.rs +++ b/beacon_node/http_api/src/utils.rs @@ -1,3 +1,90 @@ +use crate::task_spawner::TaskSpawner; +use beacon_chain::{BeaconChain, BeaconChainTypes}; +use eth2::types::EndpointVersion; +use lighthouse_network::PubsubMessage; +use lighthouse_network::rpc::methods::MetaData; +use network::{NetworkMessage, ValidatorSubscriptionMessage}; +use parking_lot::RwLock; +use std::sync::Arc; +use tokio::sync::mpsc::{Sender, UnboundedSender}; +use types::{ChainSpec, EthSpec, ForkName}; +use warp::Rejection; use warp::filters::BoxedFilter; pub type ResponseFilter = BoxedFilter<(warp::reply::Response,)>; +pub type AnyVersionFilter = BoxedFilter<(EndpointVersion,)>; +pub type EthV1Filter = BoxedFilter<()>; +pub type ChainFilter = BoxedFilter<(Arc>,)>; +pub type NotWhileSyncingFilter = BoxedFilter<(Result<(), Rejection>,)>; +pub type TaskSpawnerFilter = BoxedFilter<(TaskSpawner<::EthSpec>,)>; +pub type ValidatorSubscriptionTxFilter = BoxedFilter<(Sender,)>; +pub type NetworkTxFilter = + BoxedFilter<(UnboundedSender::EthSpec>>,)>; +pub type OptionalConsensusVersionHeaderFilter = BoxedFilter<(Option,)>; + +pub fn from_meta_data( + meta_data: &RwLock>, + spec: &ChainSpec, +) -> eth2::types::MetaData { + let meta_data = meta_data.read(); + let format_hex = |bytes: &[u8]| format!("0x{}", hex::encode(bytes)); + + let seq_number = *meta_data.seq_number(); + let attnets = format_hex(&meta_data.attnets().clone().into_bytes()); + let syncnets = format_hex( + &meta_data + .syncnets() + .cloned() + .unwrap_or_default() + .into_bytes(), + ); + + if spec.is_peer_das_scheduled() { + eth2::types::MetaData::V3(eth2::types::MetaDataV3 { + seq_number, + attnets, + syncnets, + custody_group_count: meta_data.custody_group_count().cloned().unwrap_or_default(), + }) + } else { + eth2::types::MetaData::V2(eth2::types::MetaDataV2 { + seq_number, + attnets, + syncnets, + }) + } +} + +/// Publish a message to the libp2p pubsub network. +pub fn publish_pubsub_message( + network_tx: &UnboundedSender>, + message: PubsubMessage, +) -> Result<(), warp::Rejection> { + publish_network_message( + network_tx, + NetworkMessage::Publish { + messages: vec![message], + }, + ) +} + +/// Publish a message to the libp2p pubsub network. +pub fn publish_pubsub_messages( + network_tx: &UnboundedSender>, + messages: Vec>, +) -> Result<(), warp::Rejection> { + publish_network_message(network_tx, NetworkMessage::Publish { messages }) +} + +/// Publish a message to the libp2p network. +pub fn publish_network_message( + network_tx: &UnboundedSender>, + message: NetworkMessage, +) -> Result<(), warp::Rejection> { + network_tx.send(message).map_err(|e| { + warp_utils::reject::custom_server_error(format!( + "unable to publish to network channel: {}", + e + )) + }) +} diff --git a/beacon_node/http_api/src/validator.rs b/beacon_node/http_api/src/validator.rs deleted file mode 100644 index 25b0feb99e..0000000000 --- a/beacon_node/http_api/src/validator.rs +++ /dev/null @@ -1,22 +0,0 @@ -use beacon_chain::{BeaconChain, BeaconChainError, BeaconChainTypes}; -use types::{BeaconState, PublicKeyBytes}; - -/// Uses the `chain.validator_pubkey_cache` to resolve a pubkey to a validator -/// index and then ensures that the validator exists in the given `state`. -pub fn pubkey_to_validator_index( - chain: &BeaconChain, - state: &BeaconState, - pubkey: &PublicKeyBytes, -) -> Result, Box> { - chain - .validator_index(pubkey) - .map_err(Box::new)? - .filter(|&index| { - state - .validators() - .get(index) - .is_some_and(|v| v.pubkey == *pubkey) - }) - .map(Result::Ok) - .transpose() -} diff --git a/beacon_node/http_api/src/validator/mod.rs b/beacon_node/http_api/src/validator/mod.rs new file mode 100644 index 0000000000..8baf7c5245 --- /dev/null +++ b/beacon_node/http_api/src/validator/mod.rs @@ -0,0 +1,972 @@ +use crate::produce_block::{produce_blinded_block_v2, produce_block_v2, produce_block_v3}; +use crate::task_spawner::{Priority, TaskSpawner}; +use crate::utils::{ + AnyVersionFilter, ChainFilter, EthV1Filter, NetworkTxFilter, NotWhileSyncingFilter, + ResponseFilter, TaskSpawnerFilter, ValidatorSubscriptionTxFilter, publish_network_message, +}; +use crate::version::V3; +use crate::{StateId, attester_duties, proposer_duties, sync_committees}; +use beacon_chain::attestation_verification::VerifiedAttestation; +use beacon_chain::validator_monitor::timestamp_now; +use beacon_chain::{AttestationError, BeaconChain, BeaconChainError, BeaconChainTypes}; +use bls::PublicKeyBytes; +use eth2::StatusCode; +use eth2::types::{ + Accept, BeaconCommitteeSubscription, EndpointVersion, Failure, GenericResponse, + StandardLivenessResponseData, StateId as CoreStateId, ValidatorAggregateAttestationQuery, + ValidatorAttestationDataQuery, ValidatorBlocksQuery, ValidatorIndexData, ValidatorStatus, +}; +use lighthouse_network::PubsubMessage; +use network::{NetworkMessage, ValidatorSubscriptionMessage}; +use slot_clock::SlotClock; +use std::sync::Arc; +use tokio::sync::mpsc::{Sender, UnboundedSender}; +use tokio::sync::oneshot; +use tracing::{debug, error, info, warn}; +use types::{ + BeaconState, Epoch, EthSpec, ProposerPreparationData, SignedAggregateAndProof, + SignedContributionAndProof, SignedValidatorRegistrationData, Slot, SyncContributionData, + ValidatorSubscription, +}; +use warp::{Filter, Rejection, Reply}; +use warp_utils::reject::convert_rejection; + +/// Uses the `chain.validator_pubkey_cache` to resolve a pubkey to a validator +/// index and then ensures that the validator exists in the given `state`. +pub fn pubkey_to_validator_index( + chain: &BeaconChain, + state: &BeaconState, + pubkey: &PublicKeyBytes, +) -> Result, Box> { + chain + .validator_index(pubkey) + .map_err(Box::new)? + .filter(|&index| { + state + .validators() + .get(index) + .is_some_and(|v| v.pubkey == *pubkey) + }) + .map(Result::Ok) + .transpose() +} + +// GET validator/sync_committee_contribution +pub fn get_validator_sync_committee_contribution( + eth_v1: EthV1Filter, + chain_filter: ChainFilter, + not_while_syncing_filter: NotWhileSyncingFilter, + task_spawner_filter: TaskSpawnerFilter, +) -> ResponseFilter { + eth_v1 + .and(warp::path("validator")) + .and(warp::path("sync_committee_contribution")) + .and(warp::path::end()) + .and(warp::query::()) + .and(not_while_syncing_filter.clone()) + .and(task_spawner_filter.clone()) + .and(chain_filter.clone()) + .then( + |sync_committee_data: SyncContributionData, + not_synced_filter: Result<(), Rejection>, + task_spawner: TaskSpawner, + chain: Arc>| { + task_spawner.blocking_json_task(Priority::P0, move || { + not_synced_filter?; + chain + .get_aggregated_sync_committee_contribution(&sync_committee_data) + .map_err(|e| { + warp_utils::reject::custom_bad_request(format!( + "unable to fetch sync contribution: {:?}", + e + )) + })? + .map(GenericResponse::from) + .ok_or_else(|| { + warp_utils::reject::custom_not_found( + "no matching sync contribution found".to_string(), + ) + }) + }) + }, + ) + .boxed() +} + +// POST validator/duties/sync/{epoch} +pub fn post_validator_duties_sync( + eth_v1: EthV1Filter, + chain_filter: ChainFilter, + not_while_syncing_filter: NotWhileSyncingFilter, + task_spawner_filter: TaskSpawnerFilter, +) -> ResponseFilter { + eth_v1 + .and(warp::path("validator")) + .and(warp::path("duties")) + .and(warp::path("sync")) + .and(warp::path::param::().or_else(|_| async { + Err(warp_utils::reject::custom_bad_request( + "Invalid epoch".to_string(), + )) + })) + .and(warp::path::end()) + .and(not_while_syncing_filter.clone()) + .and(warp_utils::json::json()) + .and(task_spawner_filter.clone()) + .and(chain_filter.clone()) + .then( + |epoch: Epoch, + not_synced_filter: Result<(), Rejection>, + indices: ValidatorIndexData, + task_spawner: TaskSpawner, + chain: Arc>| { + task_spawner.blocking_json_task(Priority::P0, move || { + not_synced_filter?; + sync_committees::sync_committee_duties(epoch, &indices.0, &chain) + }) + }, + ) + .boxed() +} + +// POST validator/duties/attester/{epoch} +pub fn post_validator_duties_attester( + eth_v1: EthV1Filter, + chain_filter: ChainFilter, + not_while_syncing_filter: NotWhileSyncingFilter, + task_spawner_filter: TaskSpawnerFilter, +) -> ResponseFilter { + eth_v1 + .and(warp::path("validator")) + .and(warp::path("duties")) + .and(warp::path("attester")) + .and(warp::path::param::().or_else(|_| async { + Err(warp_utils::reject::custom_bad_request( + "Invalid epoch".to_string(), + )) + })) + .and(warp::path::end()) + .and(not_while_syncing_filter.clone()) + .and(warp_utils::json::json()) + .and(task_spawner_filter.clone()) + .and(chain_filter.clone()) + .then( + |epoch: Epoch, + not_synced_filter: Result<(), Rejection>, + indices: ValidatorIndexData, + task_spawner: TaskSpawner, + chain: Arc>| { + task_spawner.blocking_json_task(Priority::P0, move || { + not_synced_filter?; + attester_duties::attester_duties(epoch, &indices.0, &chain) + }) + }, + ) + .boxed() +} + +// GET validator/aggregate_attestation?attestation_data_root,slot +pub fn get_validator_aggregate_attestation( + any_version: AnyVersionFilter, + chain_filter: ChainFilter, + not_while_syncing_filter: NotWhileSyncingFilter, + task_spawner_filter: TaskSpawnerFilter, +) -> ResponseFilter { + any_version + .and(warp::path("validator")) + .and(warp::path("aggregate_attestation")) + .and(warp::path::end()) + .and(warp::query::()) + .and(not_while_syncing_filter.clone()) + .and(task_spawner_filter.clone()) + .and(chain_filter.clone()) + .then( + |endpoint_version: EndpointVersion, + query: ValidatorAggregateAttestationQuery, + not_synced_filter: Result<(), Rejection>, + task_spawner: TaskSpawner, + chain: Arc>| { + task_spawner.blocking_response_task(Priority::P0, move || { + not_synced_filter?; + crate::aggregate_attestation::get_aggregate_attestation( + query.slot, + &query.attestation_data_root, + query.committee_index, + endpoint_version, + chain, + ) + }) + }, + ) + .boxed() +} + +// GET validator/attestation_data?slot,committee_index +pub fn get_validator_attestation_data( + eth_v1: EthV1Filter, + chain_filter: ChainFilter, + not_while_syncing_filter: NotWhileSyncingFilter, + task_spawner_filter: TaskSpawnerFilter, +) -> ResponseFilter { + eth_v1 + .and(warp::path("validator")) + .and(warp::path("attestation_data")) + .and(warp::path::end()) + .and(warp::query::()) + .and(not_while_syncing_filter.clone()) + .and(task_spawner_filter.clone()) + .and(chain_filter.clone()) + .then( + |query: ValidatorAttestationDataQuery, + not_synced_filter: Result<(), Rejection>, + task_spawner: TaskSpawner, + chain: Arc>| { + task_spawner.blocking_json_task(Priority::P0, move || { + not_synced_filter?; + + let current_slot = chain.slot().map_err(warp_utils::reject::unhandled_error)?; + + // allow a tolerance of one slot to account for clock skew + if query.slot > current_slot + 1 { + return Err(warp_utils::reject::custom_bad_request(format!( + "request slot {} is more than one slot past the current slot {}", + query.slot, current_slot + ))); + } + + chain + .produce_unaggregated_attestation(query.slot, query.committee_index) + .map(|attestation| attestation.data().clone()) + .map(GenericResponse::from) + .map_err(warp_utils::reject::unhandled_error) + }) + }, + ) + .boxed() +} + +// GET validator/blinded_blocks/{slot} +pub fn get_validator_blinded_blocks( + eth_v1: EthV1Filter, + chain_filter: ChainFilter, + not_while_syncing_filter: NotWhileSyncingFilter, + task_spawner_filter: TaskSpawnerFilter, +) -> ResponseFilter { + eth_v1 + .and(warp::path("validator")) + .and(warp::path("blinded_blocks")) + .and(warp::path::param::().or_else(|_| async { + Err(warp_utils::reject::custom_bad_request( + "Invalid slot".to_string(), + )) + })) + .and(warp::path::end()) + .and(not_while_syncing_filter.clone()) + .and(warp::query::()) + .and(warp::header::optional::("accept")) + .and(task_spawner_filter.clone()) + .and(chain_filter.clone()) + .then( + |slot: Slot, + not_synced_filter: Result<(), Rejection>, + query: ValidatorBlocksQuery, + accept_header: Option, + task_spawner: TaskSpawner, + chain: Arc>| { + task_spawner.spawn_async_with_rejection(Priority::P0, async move { + not_synced_filter?; + produce_blinded_block_v2(accept_header, chain, slot, query).await + }) + }, + ) + .boxed() +} + +// GET validator/blocks/{slot} +pub fn get_validator_blocks( + any_version: AnyVersionFilter, + chain_filter: ChainFilter, + not_while_syncing_filter: NotWhileSyncingFilter, + task_spawner_filter: TaskSpawnerFilter, +) -> ResponseFilter { + any_version + .and(warp::path("validator")) + .and(warp::path("blocks")) + .and(warp::path::param::().or_else(|_| async { + Err(warp_utils::reject::custom_bad_request( + "Invalid slot".to_string(), + )) + })) + .and(warp::path::end()) + .and(warp::header::optional::("accept")) + .and(not_while_syncing_filter) + .and(warp::query::()) + .and(task_spawner_filter) + .and(chain_filter) + .then( + |endpoint_version: EndpointVersion, + slot: Slot, + accept_header: Option, + not_synced_filter: Result<(), Rejection>, + query: ValidatorBlocksQuery, + task_spawner: TaskSpawner, + chain: Arc>| { + task_spawner.spawn_async_with_rejection(Priority::P0, async move { + debug!(?slot, "Block production request from HTTP API"); + + not_synced_filter?; + + if endpoint_version == V3 { + produce_block_v3(accept_header, chain, slot, query).await + } else { + produce_block_v2(accept_header, chain, slot, query).await + } + }) + }, + ) + .boxed() +} + +// POST validator/liveness/{epoch} +pub fn post_validator_liveness_epoch( + eth_v1: EthV1Filter, + chain_filter: ChainFilter, + task_spawner_filter: TaskSpawnerFilter, +) -> ResponseFilter { + eth_v1 + .and(warp::path("validator")) + .and(warp::path("liveness")) + .and(warp::path::param::()) + .and(warp::path::end()) + .and(warp_utils::json::json()) + .and(task_spawner_filter.clone()) + .and(chain_filter.clone()) + .then( + |epoch: Epoch, + indices: ValidatorIndexData, + task_spawner: TaskSpawner, + chain: Arc>| { + task_spawner.blocking_json_task(Priority::P0, move || { + // Ensure the request is for either the current, previous or next epoch. + let current_epoch = + chain.epoch().map_err(warp_utils::reject::unhandled_error)?; + let prev_epoch = current_epoch.saturating_sub(Epoch::new(1)); + let next_epoch = current_epoch.saturating_add(Epoch::new(1)); + + if epoch < prev_epoch || epoch > next_epoch { + return Err(warp_utils::reject::custom_bad_request(format!( + "request epoch {} is more than one epoch from the current epoch {}", + epoch, current_epoch + ))); + } + + let liveness: Vec = indices + .0 + .iter() + .cloned() + .map(|index| { + let is_live = chain.validator_seen_at_epoch(index as usize, epoch); + StandardLivenessResponseData { index, is_live } + }) + .collect(); + + Ok(GenericResponse::from(liveness)) + }) + }, + ) + .boxed() +} + +// POST validator/sync_committee_subscriptions +pub fn post_validator_sync_committee_subscriptions( + eth_v1: EthV1Filter, + chain_filter: ChainFilter, + validator_subscription_tx_filter: ValidatorSubscriptionTxFilter, + task_spawner_filter: TaskSpawnerFilter, +) -> ResponseFilter { + eth_v1 + .and(warp::path("validator")) + .and(warp::path("sync_committee_subscriptions")) + .and(warp::path::end()) + .and(warp_utils::json::json()) + .and(validator_subscription_tx_filter) + .and(task_spawner_filter.clone()) + .and(chain_filter.clone()) + .then( + |subscriptions: Vec, + validator_subscription_tx: Sender, + task_spawner: TaskSpawner, + chain: Arc>, + | { + task_spawner.blocking_json_task(Priority::P0, move || { + for subscription in subscriptions { + chain + .validator_monitor + .write() + .auto_register_local_validator(subscription.validator_index); + + let message = ValidatorSubscriptionMessage::SyncCommitteeSubscribe { + subscriptions: vec![subscription], + }; + if let Err(e) = validator_subscription_tx.try_send(message) { + warn!( + info = "the host may be overloaded or resource-constrained", + error = ?e, + "Unable to process sync subscriptions" + ); + return Err(warp_utils::reject::custom_server_error( + "unable to queue subscription, host may be overloaded or shutting down".to_string(), + )); + } + } + + Ok(()) + }) + }, + ).boxed() +} + +// POST validator/register_validator +pub fn post_validator_register_validator( + eth_v1: EthV1Filter, + chain_filter: ChainFilter, + task_spawner_filter: TaskSpawnerFilter, +) -> ResponseFilter { + eth_v1 + .and(warp::path("validator")) + .and(warp::path("register_validator")) + .and(warp::path::end()) + .and(task_spawner_filter.clone()) + .and(chain_filter.clone()) + .and(warp_utils::json::json()) + .then( + |task_spawner: TaskSpawner, + chain: Arc>, + register_val_data: Vec| async { + let (tx, rx) = oneshot::channel(); + + let initial_result = task_spawner + .spawn_async_with_rejection_no_conversion(Priority::P0, async move { + let execution_layer = chain + .execution_layer + .as_ref() + .ok_or(BeaconChainError::ExecutionLayerMissing) + .map_err(warp_utils::reject::unhandled_error)?; + let current_slot = chain + .slot_clock + .now_or_genesis() + .ok_or(BeaconChainError::UnableToReadSlot) + .map_err(warp_utils::reject::unhandled_error)?; + let current_epoch = current_slot.epoch(T::EthSpec::slots_per_epoch()); + + debug!( + count = register_val_data.len(), + "Received register validator request" + ); + + let head_snapshot = chain.head_snapshot(); + let spec = &chain.spec; + + let (preparation_data, filtered_registration_data): ( + Vec<(ProposerPreparationData, Option)>, + Vec, + ) = register_val_data + .into_iter() + .filter_map(|register_data| { + chain + .validator_index(®ister_data.message.pubkey) + .ok() + .flatten() + .and_then(|validator_index| { + let validator = head_snapshot + .beacon_state + .get_validator(validator_index) + .ok()?; + let validator_status = ValidatorStatus::from_validator( + validator, + current_epoch, + spec.far_future_epoch, + ) + .superstatus(); + let is_active_or_pending = + matches!(validator_status, ValidatorStatus::Pending) + || matches!( + validator_status, + ValidatorStatus::Active + ); + + // Filter out validators who are not 'active' or 'pending'. + is_active_or_pending.then_some({ + ( + ( + ProposerPreparationData { + validator_index: validator_index as u64, + fee_recipient: register_data + .message + .fee_recipient, + }, + Some(register_data.message.gas_limit), + ), + register_data, + ) + }) + }) + }) + .unzip(); + + // Update the prepare beacon proposer cache based on this request. + execution_layer + .update_proposer_preparation( + current_epoch, + preparation_data.iter().map(|(data, limit)| (data, limit)), + ) + .await; + + // Call prepare beacon proposer blocking with the latest update in order to make + // sure we have a local payload to fall back to in the event of the blinded block + // flow failing. + chain + .prepare_beacon_proposer(current_slot) + .await + .map_err(|e| { + warp_utils::reject::custom_bad_request(format!( + "error updating proposer preparations: {:?}", + e + )) + })?; + + info!( + count = filtered_registration_data.len(), + "Forwarding register validator request to connected builder" + ); + + // It's a waste of a `BeaconProcessor` worker to just + // wait on a response from the builder (especially since + // they have frequent timeouts). Spawn a new task and + // send the response back to our original HTTP request + // task via a channel. + let builder_future = async move { + let arc_builder = chain + .execution_layer + .as_ref() + .ok_or(BeaconChainError::ExecutionLayerMissing) + .map_err(warp_utils::reject::unhandled_error)? + .builder(); + let builder = arc_builder + .as_ref() + .ok_or(BeaconChainError::BuilderMissing) + .map_err(warp_utils::reject::unhandled_error)?; + builder + .post_builder_validators(&filtered_registration_data) + .await + .map(|resp| warp::reply::json(&resp).into_response()) + .map_err(|e| { + warn!( + num_registrations = filtered_registration_data.len(), + error = ?e, + "Relay error when registering validator(s)" + ); + // Forward the HTTP status code if we are able to, otherwise fall back + // to a server error. + if let eth2::Error::ServerMessage(message) = e { + if message.code == StatusCode::BAD_REQUEST.as_u16() { + return warp_utils::reject::custom_bad_request( + message.message, + ); + } else { + // According to the spec this response should only be a 400 or 500, + // so we fall back to a 500 here. + return warp_utils::reject::custom_server_error( + message.message, + ); + } + } + warp_utils::reject::custom_server_error(format!("{e:?}")) + }) + }; + tokio::task::spawn(async move { tx.send(builder_future.await) }); + + // Just send a generic 200 OK from this closure. We'll + // ignore the `Ok` variant and form a proper response + // from what is sent back down the channel. + Ok(warp::reply::reply().into_response()) + }) + .await; + + if initial_result.is_err() { + return convert_rejection(initial_result).await; + } + + // Await a response from the builder without blocking a + // `BeaconProcessor` worker. + convert_rejection(rx.await.unwrap_or_else(|_| { + Ok(warp::reply::with_status( + warp::reply::json(&"No response from channel"), + warp::http::StatusCode::INTERNAL_SERVER_ERROR, + ) + .into_response()) + })) + .await + }, + ) + .boxed() +} + +// POST validator/prepare_beacon_proposer +pub fn post_validator_prepare_beacon_proposer( + eth_v1: EthV1Filter, + chain_filter: ChainFilter, + network_tx_filter: NetworkTxFilter, + not_while_syncing_filter: NotWhileSyncingFilter, + task_spawner_filter: TaskSpawnerFilter, +) -> ResponseFilter { + eth_v1 + .and(warp::path("validator")) + .and(warp::path("prepare_beacon_proposer")) + .and(warp::path::end()) + .and(not_while_syncing_filter.clone()) + .and(network_tx_filter.clone()) + .and(task_spawner_filter.clone()) + .and(chain_filter.clone()) + .and(warp_utils::json::json()) + .then( + |not_synced_filter: Result<(), Rejection>, + network_tx: UnboundedSender>, + task_spawner: TaskSpawner, + chain: Arc>, + preparation_data: Vec| { + task_spawner.spawn_async_with_rejection(Priority::P0, async move { + not_synced_filter?; + let execution_layer = chain + .execution_layer + .as_ref() + .ok_or(BeaconChainError::ExecutionLayerMissing) + .map_err(warp_utils::reject::unhandled_error)?; + + let current_slot = chain + .slot_clock + .now_or_genesis() + .ok_or(BeaconChainError::UnableToReadSlot) + .map_err(warp_utils::reject::unhandled_error)?; + let current_epoch = current_slot.epoch(T::EthSpec::slots_per_epoch()); + + debug!( + count = preparation_data.len(), + "Received proposer preparation data" + ); + + execution_layer + .update_proposer_preparation( + current_epoch, + preparation_data.iter().map(|data| (data, &None)), + ) + .await; + + chain + .prepare_beacon_proposer(current_slot) + .await + .map_err(|e| { + warp_utils::reject::custom_bad_request(format!( + "error updating proposer preparations: {:?}", + e + )) + })?; + + if chain.spec.is_peer_das_scheduled() { + let (finalized_beacon_state, _, _) = + StateId(CoreStateId::Finalized).state(&chain)?; + let validators_and_balances = preparation_data + .iter() + .filter_map(|preparation| { + if let Ok(effective_balance) = finalized_beacon_state + .get_effective_balance(preparation.validator_index as usize) + { + Some((preparation.validator_index as usize, effective_balance)) + } else { + None + } + }) + .collect::>(); + + let current_slot = + chain.slot().map_err(warp_utils::reject::unhandled_error)?; + if let Some(cgc_change) = chain + .data_availability_checker + .custody_context() + .register_validators(validators_and_balances, current_slot, &chain.spec) + { + chain.update_data_column_custody_info(Some( + cgc_change + .effective_epoch + .start_slot(T::EthSpec::slots_per_epoch()), + )); + + network_tx.send(NetworkMessage::CustodyCountChanged { + new_custody_group_count: cgc_change.new_custody_group_count, + sampling_count: cgc_change.sampling_count, + }).unwrap_or_else(|e| { + debug!(error = %e, "Could not send message to the network service. \ + Likely shutdown") + }); + } + } + + Ok::<_, warp::reject::Rejection>(warp::reply::json(&()).into_response()) + }) + }, + ) + .boxed() +} + +// POST validator/beacon_committee_subscriptions +pub fn post_validator_beacon_committee_subscriptions( + eth_v1: EthV1Filter, + chain_filter: ChainFilter, + validator_subscription_tx_filter: ValidatorSubscriptionTxFilter, + task_spawner_filter: TaskSpawnerFilter, +) -> ResponseFilter { + eth_v1 + .and(warp::path("validator")) + .and(warp::path("beacon_committee_subscriptions")) + .and(warp::path::end()) + .and(warp_utils::json::json()) + .and(validator_subscription_tx_filter.clone()) + .and(task_spawner_filter.clone()) + .and(chain_filter.clone()) + .then( + |committee_subscriptions: Vec, + validator_subscription_tx: Sender, + task_spawner: TaskSpawner, + chain: Arc>| { + task_spawner.blocking_json_task(Priority::P0, move || { + let subscriptions: std::collections::BTreeSet<_> = committee_subscriptions + .iter() + .map(|subscription| { + chain + .validator_monitor + .write() + .auto_register_local_validator(subscription.validator_index); + ValidatorSubscription { + attestation_committee_index: subscription.committee_index, + slot: subscription.slot, + committee_count_at_slot: subscription.committees_at_slot, + is_aggregator: subscription.is_aggregator, + } + }) + .collect(); + + let message = + ValidatorSubscriptionMessage::AttestationSubscribe { subscriptions }; + if let Err(e) = validator_subscription_tx.try_send(message) { + warn!( + info = "the host may be overloaded or resource-constrained", + error = ?e, + "Unable to process committee subscriptions" + ); + return Err(warp_utils::reject::custom_server_error( + "unable to queue subscription, host may be overloaded or shutting down" + .to_string(), + )); + } + Ok(()) + }) + }, + ) + .boxed() +} + +pub fn post_validator_contribution_and_proofs( + eth_v1: EthV1Filter, + chain_filter: ChainFilter, + network_tx_filter: NetworkTxFilter, + not_while_syncing_filter: NotWhileSyncingFilter, + task_spawner_filter: TaskSpawnerFilter, +) -> ResponseFilter { + eth_v1 + .and(warp::path("validator")) + .and(warp::path("contribution_and_proofs")) + .and(warp::path::end()) + .and(not_while_syncing_filter.clone()) + .and(task_spawner_filter.clone()) + .and(chain_filter.clone()) + .and(warp_utils::json::json()) + .and(network_tx_filter.clone()) + .then( + |not_synced_filter: Result<(), Rejection>, + task_spawner: TaskSpawner, + chain: Arc>, + contributions: Vec>, + network_tx: UnboundedSender>| { + task_spawner.blocking_json_task(Priority::P0, move || { + not_synced_filter?; + sync_committees::process_signed_contribution_and_proofs( + contributions, + network_tx, + &chain, + )?; + Ok(GenericResponse::from(())) + }) + }, + ) + .boxed() +} + +// POST validator/aggregate_and_proofs +pub fn post_validator_aggregate_and_proofs( + any_version: AnyVersionFilter, + chain_filter: ChainFilter, + network_tx_filter: NetworkTxFilter, + not_while_syncing_filter: NotWhileSyncingFilter, + task_spawner_filter: TaskSpawnerFilter, +) -> ResponseFilter { + any_version + .and(warp::path("validator")) + .and(warp::path("aggregate_and_proofs")) + .and(warp::path::end()) + .and(not_while_syncing_filter.clone()) + .and(task_spawner_filter.clone()) + .and(chain_filter.clone()) + .and(warp_utils::json::json()) + .and(network_tx_filter.clone()) + .then( + // V1 and V2 are identical except V2 has a consensus version header in the request. + // We only require this header for SSZ deserialization, which isn't supported for + // this endpoint presently. + |_endpoint_version: EndpointVersion, + not_synced_filter: Result<(), Rejection>, + task_spawner: TaskSpawner, + chain: Arc>, + aggregates: Vec>, + network_tx: UnboundedSender>| { + task_spawner.blocking_json_task(Priority::P0, move || { + not_synced_filter?; + let seen_timestamp = timestamp_now(); + let mut verified_aggregates = Vec::with_capacity(aggregates.len()); + let mut messages = Vec::with_capacity(aggregates.len()); + let mut failures = Vec::new(); + + // Verify that all messages in the post are valid before processing further + for (index, aggregate) in aggregates.iter().enumerate() { + match chain.verify_aggregated_attestation_for_gossip(aggregate) { + Ok(verified_aggregate) => { + messages.push(PubsubMessage::AggregateAndProofAttestation(Box::new( + verified_aggregate.aggregate().clone(), + ))); + + // Notify the validator monitor. + chain + .validator_monitor + .read() + .register_api_aggregated_attestation( + seen_timestamp, + verified_aggregate.aggregate(), + verified_aggregate.indexed_attestation(), + &chain.slot_clock, + ); + + verified_aggregates.push((index, verified_aggregate)); + } + // If we already know the attestation, don't broadcast it or attempt to + // further verify it. Return success. + // + // It's reasonably likely that two different validators produce + // identical aggregates, especially if they're using the same beacon + // node. + Err(AttestationError::AttestationSupersetKnown(_)) => continue, + // If we've already seen this aggregator produce an aggregate, just + // skip this one. + // + // We're likely to see this with VCs that use fallback BNs. The first + // BN might time-out *after* publishing the aggregate and then the + // second BN will indicate it's already seen the aggregate. + // + // There's no actual error for the user or the network since the + // aggregate has been successfully published by some other node. + Err(AttestationError::AggregatorAlreadyKnown(_)) => continue, + Err(e) => { + error!( + error = ?e, + request_index = index, + aggregator_index = aggregate.message().aggregator_index(), + attestation_index = aggregate.message().aggregate().committee_index(), + attestation_slot = %aggregate.message().aggregate().data().slot, + "Failure verifying aggregate and proofs" + ); + failures.push(Failure::new(index, format!("Verification: {:?}", e))); + } + } + } + + // Publish aggregate attestations to the libp2p network + if !messages.is_empty() { + publish_network_message(&network_tx, NetworkMessage::Publish { messages })?; + } + + // Import aggregate attestations + for (index, verified_aggregate) in verified_aggregates { + if let Err(e) = chain.apply_attestation_to_fork_choice(&verified_aggregate) { + error!( + error = ?e, + request_index = index, + aggregator_index = verified_aggregate.aggregate().message().aggregator_index(), + attestation_index = verified_aggregate.attestation().committee_index(), + attestation_slot = %verified_aggregate.attestation().data().slot, + "Failure applying verified aggregate attestation to fork choice" + ); + failures.push(Failure::new(index, format!("Fork choice: {:?}", e))); + } + if let Err(e) = chain.add_to_block_inclusion_pool(verified_aggregate) { + warn!( + error = ?e, + request_index = index, + "Could not add verified aggregate attestation to the inclusion pool" + ); + failures.push(Failure::new(index, format!("Op pool: {:?}", e))); + } + } + + if !failures.is_empty() { + Err(warp_utils::reject::indexed_bad_request("error processing aggregate and proofs".to_string(), + failures, + )) + } else { + Ok(()) + } + }) + }, + ).boxed() +} + +// GET validator/duties/proposer/{epoch} +pub fn get_validator_duties_proposer( + eth_v1: EthV1Filter, + chain_filter: ChainFilter, + not_while_syncing_filter: NotWhileSyncingFilter, + task_spawner_filter: TaskSpawnerFilter, +) -> ResponseFilter { + eth_v1 + .and(warp::path("validator")) + .and(warp::path("duties")) + .and(warp::path("proposer")) + .and(warp::path::param::().or_else(|_| async { + Err(warp_utils::reject::custom_bad_request( + "Invalid epoch".to_string(), + )) + })) + .and(warp::path::end()) + .and(not_while_syncing_filter) + .and(task_spawner_filter) + .and(chain_filter) + .then( + |epoch: Epoch, + not_synced_filter: Result<(), Rejection>, + task_spawner: TaskSpawner, + chain: Arc>| { + task_spawner.blocking_json_task(Priority::P0, move || { + not_synced_filter?; + proposer_duties::proposer_duties(epoch, &chain) + }) + }, + ) + .boxed() +} diff --git a/beacon_node/http_api/tests/broadcast_validation_tests.rs b/beacon_node/http_api/tests/broadcast_validation_tests.rs index 33f462fa5e..357b78cf41 100644 --- a/beacon_node/http_api/tests/broadcast_validation_tests.rs +++ b/beacon_node/http_api/tests/broadcast_validation_tests.rs @@ -6,13 +6,12 @@ use beacon_chain::{ }; use eth2::reqwest::{Response, StatusCode}; use eth2::types::{BroadcastValidation, PublishBlockRequest}; +use fixed_bytes::FixedBytesExtended; use http_api::test_utils::InteractiveTester; use http_api::{Config, ProvenancedBlock, publish_blinded_block, publish_block, reconstruct_block}; use std::collections::HashSet; use std::sync::Arc; -use types::{ - ColumnIndex, Epoch, EthSpec, FixedBytesExtended, ForkName, Hash256, MainnetEthSpec, Slot, -}; +use types::{ColumnIndex, Epoch, EthSpec, ForkName, Hash256, MainnetEthSpec, Slot}; use warp::Rejection; use warp_utils::reject::CustomBadRequest; diff --git a/beacon_node/http_api/tests/fork_tests.rs b/beacon_node/http_api/tests/fork_tests.rs index 50cf866b6a..b96c8bd112 100644 --- a/beacon_node/http_api/tests/fork_tests.rs +++ b/beacon_node/http_api/tests/fork_tests.rs @@ -4,13 +4,15 @@ use beacon_chain::{ StateSkipConfig, test_utils::{DEFAULT_ETH1_BLOCK_HASH, HARNESS_GENESIS_TIME, RelativeSyncCommittee}, }; +use bls::PublicKey; use eth2::types::{IndexedErrorMessage, StateId, SyncSubcommittee}; use execution_layer::test_utils::generate_genesis_header; +use fixed_bytes::FixedBytesExtended; use genesis::{InteropGenesisBuilder, bls_withdrawal_credentials}; use http_api::test_utils::*; use std::collections::HashSet; use types::{ - Address, ChainSpec, Epoch, EthSpec, FixedBytesExtended, Hash256, MinimalEthSpec, Slot, + Address, ChainSpec, Epoch, EthSpec, Hash256, MinimalEthSpec, Slot, test_utils::{generate_deterministic_keypair, generate_deterministic_keypairs}, }; @@ -392,7 +394,7 @@ async fn bls_to_execution_changes_update_all_around_capella_fork() { fn withdrawal_credentials_fn<'a>( index: usize, - _: &'a types::PublicKey, + _: &'a PublicKey, spec: &'a ChainSpec, ) -> Hash256 { // It is a bit inefficient to regenerate the whole keypair here, but this is a workaround. diff --git a/beacon_node/http_api/tests/interactive_tests.rs b/beacon_node/http_api/tests/interactive_tests.rs index 125c004c3b..a00eed87ae 100644 --- a/beacon_node/http_api/tests/interactive_tests.rs +++ b/beacon_node/http_api/tests/interactive_tests.rs @@ -11,6 +11,7 @@ use beacon_processor::{Work, WorkEvent, work_reprocessing_queue::ReprocessQueueM use eth2::types::ProduceBlockV3Response; use eth2::types::{DepositContractData, StateId}; use execution_layer::{ForkchoiceState, PayloadAttributes}; +use fixed_bytes::FixedBytesExtended; use http_api::test_utils::InteractiveTester; use parking_lot::Mutex; use slot_clock::SlotClock; @@ -21,8 +22,8 @@ use std::collections::HashMap; use std::sync::Arc; use std::time::Duration; use types::{ - Address, Epoch, EthSpec, ExecPayload, ExecutionBlockHash, FixedBytesExtended, ForkName, - Hash256, MainnetEthSpec, MinimalEthSpec, ProposerPreparationData, Slot, Uint256, + Address, Epoch, EthSpec, ExecPayload, ExecutionBlockHash, ForkName, Hash256, MainnetEthSpec, + MinimalEthSpec, ProposerPreparationData, Slot, Uint256, }; type E = MainnetEthSpec; diff --git a/beacon_node/http_api/tests/tests.rs b/beacon_node/http_api/tests/tests.rs index 8d99e696cf..f8eba0ee2b 100644 --- a/beacon_node/http_api/tests/tests.rs +++ b/beacon_node/http_api/tests/tests.rs @@ -6,6 +6,7 @@ use beacon_chain::{ AttestationStrategy, BeaconChainHarness, BlockStrategy, EphemeralHarnessType, test_spec, }, }; +use bls::{AggregateSignature, Keypair, PublicKeyBytes, Signature, SignatureBytes}; use eth2::{ BeaconNodeHttpClient, Error, Error::ServerMessage, @@ -21,6 +22,7 @@ use execution_layer::test_utils::{ DEFAULT_BUILDER_PAYLOAD_VALUE_WEI, DEFAULT_GAS_LIMIT, DEFAULT_MOCK_EL_PAYLOAD_VALUE_WEI, MockBuilder, Operation, mock_builder_extra_data, mock_el_extra_data, }; +use fixed_bytes::FixedBytesExtended; use futures::FutureExt; use futures::stream::{Stream, StreamExt}; use http_api::{ @@ -34,6 +36,7 @@ use operation_pool::attestation_storage::CheckpointKey; use proto_array::ExecutionStatus; use sensitive_url::SensitiveUrl; use slot_clock::SlotClock; +use ssz::BitList; use state_processing::per_block_processing::get_expected_withdrawals; use state_processing::per_slot_processing; use state_processing::state_advance::partial_state_advance; @@ -43,9 +46,8 @@ use tokio::time::Duration; use tree_hash::TreeHash; use types::application_domain::ApplicationDomain; use types::{ - AggregateSignature, BitList, Domain, EthSpec, ExecutionBlockHash, Hash256, Keypair, - MainnetEthSpec, RelativeEpoch, SelectionProof, SignedRoot, SingleAttestation, Slot, - attestation::AttestationBase, + Domain, EthSpec, ExecutionBlockHash, Hash256, MainnetEthSpec, RelativeEpoch, SelectionProof, + SignedRoot, SingleAttestation, Slot, attestation::AttestationBase, }; type E = MainnetEthSpec; @@ -2853,9 +2855,19 @@ impl ApiTester { let expected = IdentityData { peer_id: self.local_enr.peer_id().to_string(), - enr: self.local_enr.clone(), - p2p_addresses: self.local_enr.multiaddr_p2p_tcp(), - discovery_addresses: self.local_enr.multiaddr_p2p_udp(), + enr: self.local_enr.to_base64(), + p2p_addresses: self + .local_enr + .multiaddr_p2p_tcp() + .iter() + .map(|a| a.to_string()) + .collect(), + discovery_addresses: self + .local_enr + .multiaddr_p2p_udp() + .iter() + .map(|a| a.to_string()) + .collect(), metadata: MetaData::V2(MetaDataV2 { seq_number: 0, attnets: "0x0000000000000000".to_string(), @@ -2884,7 +2896,7 @@ impl ApiTester { pub async fn test_get_node_peers_by_id(self) -> Self { let result = self .client - .get_node_peers_by_id(self.external_peer_id) + .get_node_peers_by_id(&self.external_peer_id.to_string()) .await .unwrap() .data; diff --git a/beacon_node/lighthouse_network/Cargo.toml b/beacon_node/lighthouse_network/Cargo.toml index a6dd276c19..efb6f27dc5 100644 --- a/beacon_node/lighthouse_network/Cargo.toml +++ b/beacon_node/lighthouse_network/Cargo.toml @@ -11,15 +11,17 @@ libp2p-websocket = [] [dependencies] alloy-primitives = { workspace = true } alloy-rlp = { workspace = true } +bls = { workspace = true } bytes = { workspace = true } delay_map = { workspace = true } directory = { workspace = true } dirs = { workspace = true } discv5 = { workspace = true } either = { workspace = true } -eth2 = { workspace = true } +eth2 = { workspace = true, features = ["lighthouse"] } ethereum_ssz = { workspace = true } ethereum_ssz_derive = { workspace = true } +fixed_bytes = { workspace = true } fnv = { workspace = true } futures = { workspace = true } gossipsub = { workspace = true } @@ -49,6 +51,7 @@ tokio = { workspace = true } tokio-util = { workspace = true } tracing = { workspace = true } tracing-subscriber = { workspace = true } +typenum = { workspace = true } types = { workspace = true } unsigned-varint = { version = "0.8", features = ["codec"] } diff --git a/beacon_node/lighthouse_network/src/discovery/mod.rs b/beacon_node/lighthouse_network/src/discovery/mod.rs index 3589882ae9..a8c87523a5 100644 --- a/beacon_node/lighthouse_network/src/discovery/mod.rs +++ b/beacon_node/lighthouse_network/src/discovery/mod.rs @@ -1231,7 +1231,8 @@ mod tests { use super::*; use crate::rpc::methods::{MetaData, MetaDataV3}; use libp2p::identity::secp256k1; - use types::{BitVector, MinimalEthSpec, SubnetId}; + use ssz_types::BitVector; + use types::{MinimalEthSpec, SubnetId}; type E = MinimalEthSpec; diff --git a/beacon_node/lighthouse_network/src/peer_manager/mod.rs b/beacon_node/lighthouse_network/src/peer_manager/mod.rs index dfa8b374e9..3cfe2b3c3b 100644 --- a/beacon_node/lighthouse_network/src/peer_manager/mod.rs +++ b/beacon_node/lighthouse_network/src/peer_manager/mod.rs @@ -2978,7 +2978,8 @@ mod tests { use proptest::prelude::*; use std::collections::HashSet; use tokio::runtime::Runtime; - use types::{DataColumnSubnetId, Unsigned}; + use typenum::Unsigned; + use types::DataColumnSubnetId; use types::{EthSpec, MainnetEthSpec as E}; #[derive(Clone, Debug)] diff --git a/beacon_node/lighthouse_network/src/rpc/codec.rs b/beacon_node/lighthouse_network/src/rpc/codec.rs index 5b3574d48a..48a29699c8 100644 --- a/beacon_node/lighthouse_network/src/rpc/codec.rs +++ b/beacon_node/lighthouse_network/src/rpc/codec.rs @@ -908,11 +908,12 @@ mod tests { use super::*; use crate::rpc::protocol::*; use crate::types::{EnrAttestationBitfield, EnrSyncCommitteeBitfield}; + use bls::Signature; + use fixed_bytes::FixedBytesExtended; use types::{ BeaconBlock, BeaconBlockAltair, BeaconBlockBase, BeaconBlockBellatrix, BeaconBlockHeader, - DataColumnsByRootIdentifier, EmptyBlock, Epoch, FixedBytesExtended, FullPayload, - KzgCommitment, KzgProof, Signature, SignedBeaconBlockHeader, Slot, - blob_sidecar::BlobIdentifier, data_column_sidecar::Cell, + DataColumnsByRootIdentifier, EmptyBlock, Epoch, FullPayload, KzgCommitment, KzgProof, + SignedBeaconBlockHeader, Slot, blob_sidecar::BlobIdentifier, data_column_sidecar::Cell, }; type Spec = types::MainnetEthSpec; diff --git a/beacon_node/lighthouse_network/src/rpc/protocol.rs b/beacon_node/lighthouse_network/src/rpc/protocol.rs index 08085f3c27..366515d42f 100644 --- a/beacon_node/lighthouse_network/src/rpc/protocol.rs +++ b/beacon_node/lighthouse_network/src/rpc/protocol.rs @@ -1,5 +1,6 @@ use super::methods::*; use crate::rpc::codec::SSZSnappyInboundCodec; +use bls::Signature; use futures::future::BoxFuture; use futures::prelude::{AsyncRead, AsyncWrite}; use futures::{FutureExt, StreamExt}; @@ -20,7 +21,7 @@ use types::{ EmptyBlock, Epoch, EthSpec, EthSpecId, ForkContext, ForkName, LightClientBootstrap, LightClientBootstrapAltair, LightClientFinalityUpdate, LightClientFinalityUpdateAltair, LightClientOptimisticUpdate, LightClientOptimisticUpdateAltair, LightClientUpdate, - MainnetEthSpec, MinimalEthSpec, Signature, SignedBeaconBlock, + MainnetEthSpec, MinimalEthSpec, SignedBeaconBlock, }; // Note: Hardcoding the `EthSpec` type for `SignedBeaconBlock` as min/max values is diff --git a/beacon_node/lighthouse_network/src/types/mod.rs b/beacon_node/lighthouse_network/src/types/mod.rs index 3f57406fc7..eea8782b2d 100644 --- a/beacon_node/lighthouse_network/src/types/mod.rs +++ b/beacon_node/lighthouse_network/src/types/mod.rs @@ -3,7 +3,8 @@ mod pubsub; mod subnet; mod topics; -use types::{BitVector, EthSpec}; +use ssz_types::BitVector; +use types::EthSpec; pub type EnrAttestationBitfield = BitVector<::SubnetBitfieldLength>; pub type EnrSyncCommitteeBitfield = BitVector<::SyncCommitteeSubnetCount>; diff --git a/beacon_node/lighthouse_network/src/types/topics.rs b/beacon_node/lighthouse_network/src/types/topics.rs index cfdee907b9..0c988f35c3 100644 --- a/beacon_node/lighthouse_network/src/types/topics.rs +++ b/beacon_node/lighthouse_network/src/types/topics.rs @@ -2,7 +2,8 @@ use gossipsub::{IdentTopic as Topic, TopicHash}; use serde::{Deserialize, Serialize}; use std::collections::HashSet; use strum::AsRefStr; -use types::{ChainSpec, DataColumnSubnetId, EthSpec, ForkName, SubnetId, SyncSubnetId, Unsigned}; +use typenum::Unsigned; +use types::{ChainSpec, DataColumnSubnetId, EthSpec, ForkName, SubnetId, SyncSubnetId}; use crate::Subnet; diff --git a/beacon_node/lighthouse_network/tests/common.rs b/beacon_node/lighthouse_network/tests/common.rs index d04f1211cf..412ee5aca5 100644 --- a/beacon_node/lighthouse_network/tests/common.rs +++ b/beacon_node/lighthouse_network/tests/common.rs @@ -1,4 +1,5 @@ #![cfg(test)] +use fixed_bytes::FixedBytesExtended; use lighthouse_network::Enr; use lighthouse_network::Multiaddr; use lighthouse_network::service::Network as LibP2PService; @@ -9,10 +10,7 @@ use std::sync::Weak; use tokio::runtime::Runtime; use tracing::{Instrument, debug, error, info_span}; use tracing_subscriber::EnvFilter; -use types::{ - ChainSpec, EnrForkId, Epoch, EthSpec, FixedBytesExtended, ForkContext, ForkName, Hash256, - MinimalEthSpec, -}; +use types::{ChainSpec, EnrForkId, Epoch, EthSpec, ForkContext, ForkName, Hash256, MinimalEthSpec}; type E = MinimalEthSpec; diff --git a/beacon_node/lighthouse_network/tests/rpc_tests.rs b/beacon_node/lighthouse_network/tests/rpc_tests.rs index 8613edf5f5..599fcd242b 100644 --- a/beacon_node/lighthouse_network/tests/rpc_tests.rs +++ b/beacon_node/lighthouse_network/tests/rpc_tests.rs @@ -3,6 +3,8 @@ use crate::common; use crate::common::spec_with_all_forks_enabled; use crate::common::{Protocol, build_tracing_subscriber}; +use bls::Signature; +use fixed_bytes::FixedBytesExtended; use lighthouse_network::rpc::{RequestType, methods::*}; use lighthouse_network::service::api_types::AppRequestId; use lighthouse_network::{NetworkEvent, ReportSource, Response}; @@ -16,8 +18,8 @@ use tracing::{Instrument, debug, error, info_span, warn}; use types::{ BeaconBlock, BeaconBlockAltair, BeaconBlockBase, BeaconBlockBellatrix, BeaconBlockHeader, BlobSidecar, ChainSpec, DataColumnSidecar, DataColumnsByRootIdentifier, EmptyBlock, Epoch, - EthSpec, FixedBytesExtended, ForkName, Hash256, KzgCommitment, KzgProof, MinimalEthSpec, - Signature, SignedBeaconBlock, SignedBeaconBlockHeader, Slot, + EthSpec, ForkName, Hash256, KzgCommitment, KzgProof, MinimalEthSpec, SignedBeaconBlock, + SignedBeaconBlockHeader, Slot, }; type E = MinimalEthSpec; diff --git a/beacon_node/network/Cargo.toml b/beacon_node/network/Cargo.toml index b60c5e6dbf..bf26196576 100644 --- a/beacon_node/network/Cargo.toml +++ b/beacon_node/network/Cargo.toml @@ -22,6 +22,7 @@ delay_map = { workspace = true } educe = { workspace = true } ethereum_ssz = { workspace = true } execution_layer = { workspace = true } +fixed_bytes = { workspace = true } fnv = { workspace = true } futures = { workspace = true } hex = { workspace = true } @@ -45,6 +46,7 @@ tokio = { workspace = true } tokio-stream = { workspace = true } tracing = { workspace = true } tracing-subscriber = { workspace = true } +typenum = { workspace = true } types = { workspace = true } [dev-dependencies] diff --git a/beacon_node/network/src/service.rs b/beacon_node/network/src/service.rs index a416f5cb12..0869b442ae 100644 --- a/beacon_node/network/src/service.rs +++ b/beacon_node/network/src/service.rs @@ -37,8 +37,9 @@ use task_executor::ShutdownReason; use tokio::sync::mpsc; use tokio::time::Sleep; use tracing::{debug, error, info, trace, warn}; +use typenum::Unsigned; use types::{ - EthSpec, ForkContext, Slot, SubnetId, SyncCommitteeSubscription, SyncSubnetId, Unsigned, + EthSpec, ForkContext, Slot, SubnetId, SyncCommitteeSubscription, SyncSubnetId, ValidatorSubscription, }; diff --git a/beacon_node/network/src/status.rs b/beacon_node/network/src/status.rs index ebf5c1829e..c571a40485 100644 --- a/beacon_node/network/src/status.rs +++ b/beacon_node/network/src/status.rs @@ -1,5 +1,6 @@ use beacon_chain::{BeaconChain, BeaconChainTypes}; -use types::{EthSpec, FixedBytesExtended, Hash256}; +use fixed_bytes::FixedBytesExtended; +use types::{EthSpec, Hash256}; use lighthouse_network::rpc::{StatusMessage, methods::StatusMessageV2}; /// Trait to produce a `StatusMessage` representing the state of the given `beacon_chain`. diff --git a/beacon_node/network/src/sync/block_lookups/parent_chain.rs b/beacon_node/network/src/sync/block_lookups/parent_chain.rs index 551a0261f2..5deea1dd94 100644 --- a/beacon_node/network/src/sync/block_lookups/parent_chain.rs +++ b/beacon_node/network/src/sync/block_lookups/parent_chain.rs @@ -118,7 +118,8 @@ pub(crate) fn find_oldest_fork_ancestor( #[cfg(test)] mod tests { use super::{Node, compute_parent_chains, find_oldest_fork_ancestor}; - use types::{FixedBytesExtended, Hash256}; + use fixed_bytes::FixedBytesExtended; + use types::Hash256; fn h(n: u64) -> Hash256 { Hash256::from_low_u64_be(n) diff --git a/beacon_node/network/src/sync/range_sync/chain.rs b/beacon_node/network/src/sync/range_sync/chain.rs index 014d728ffe..4ce10e23ca 100644 --- a/beacon_node/network/src/sync/range_sync/chain.rs +++ b/beacon_node/network/src/sync/range_sync/chain.rs @@ -1331,7 +1331,7 @@ impl SyncingChain { .get(&(self.processing_target + batch_index as u64 * EPOCHS_PER_BATCH)) { visualization_string.push(batch.visualize()); - if batch_index != BATCH_BUFFER_SIZE { + if batch_index < BATCH_BUFFER_SIZE - 1 { // Add a comma in between elements visualization_string.push(','); } diff --git a/beacon_node/operation_pool/Cargo.toml b/beacon_node/operation_pool/Cargo.toml index eeddb53c23..6fab7a752a 100644 --- a/beacon_node/operation_pool/Cargo.toml +++ b/beacon_node/operation_pool/Cargo.toml @@ -9,9 +9,11 @@ portable = ["beacon_chain/portable"] [dependencies] bitvec = { workspace = true } +bls = { workspace = true } educe = { workspace = true } ethereum_ssz = { workspace = true } ethereum_ssz_derive = { workspace = true } +fixed_bytes = { workspace = true } itertools = { workspace = true } metrics = { workspace = true } parking_lot = { workspace = true } @@ -20,6 +22,8 @@ rayon = { workspace = true } serde = { workspace = true } state_processing = { workspace = true } store = { workspace = true } +superstruct = { workspace = true } +typenum = { workspace = true } types = { workspace = true } [dev-dependencies] diff --git a/beacon_node/operation_pool/src/attestation.rs b/beacon_node/operation_pool/src/attestation.rs index f28d8f278a..897a7e5ecc 100644 --- a/beacon_node/operation_pool/src/attestation.rs +++ b/beacon_node/operation_pool/src/attestation.rs @@ -1,12 +1,13 @@ use crate::attestation_storage::{CompactAttestationRef, CompactIndexedAttestation}; use crate::max_cover::MaxCover; use crate::reward_cache::RewardCache; +use ssz::BitList; use state_processing::common::{ attesting_indices_base::get_attesting_indices, base, get_attestation_participation_flag_indices, }; use std::collections::HashMap; use types::{ - Attestation, BeaconState, BitList, ChainSpec, EthSpec, + Attestation, BeaconState, ChainSpec, EthSpec, beacon_state::BeaconStateBase, consts::altair::{PARTICIPATION_FLAG_WEIGHTS, PROPOSER_WEIGHT, WEIGHT_DENOMINATOR}, }; diff --git a/beacon_node/operation_pool/src/attestation_storage.rs b/beacon_node/operation_pool/src/attestation_storage.rs index 4f1b8b81fe..9094c9cd4d 100644 --- a/beacon_node/operation_pool/src/attestation_storage.rs +++ b/beacon_node/operation_pool/src/attestation_storage.rs @@ -1,11 +1,13 @@ use crate::AttestationStats; +use bls::AggregateSignature; use itertools::Itertools; +use ssz::{BitList, BitVector}; use std::collections::{BTreeMap, HashMap, HashSet}; +use superstruct::superstruct; +use typenum::Unsigned; use types::{ - AggregateSignature, Attestation, AttestationData, BeaconState, BitList, BitVector, Checkpoint, - Epoch, EthSpec, Hash256, Slot, Unsigned, + Attestation, AttestationData, BeaconState, Checkpoint, Epoch, EthSpec, Hash256, Slot, attestation::{AttestationBase, AttestationElectra}, - superstruct, }; #[derive(Debug, PartialEq, Eq, Hash, Clone, Copy)] diff --git a/beacon_node/operation_pool/src/lib.rs b/beacon_node/operation_pool/src/lib.rs index e92d381bac..00361450a5 100644 --- a/beacon_node/operation_pool/src/lib.rs +++ b/beacon_node/operation_pool/src/lib.rs @@ -35,12 +35,12 @@ use state_processing::{SigVerifiedOp, VerifyOperation}; use std::collections::{HashMap, HashSet, hash_map::Entry}; use std::marker::PhantomData; use std::ptr; +use typenum::Unsigned; use types::{ AbstractExecPayload, Attestation, AttestationData, AttesterSlashing, BeaconState, BeaconStateError, ChainSpec, Epoch, EthSpec, ProposerSlashing, SignedBeaconBlock, SignedBlsToExecutionChange, SignedVoluntaryExit, Slot, SyncAggregate, SyncCommitteeContribution, Validator, sync_aggregate::Error as SyncAggregateError, - typenum::Unsigned, }; type SyncContributions = RwLock>>>; @@ -793,6 +793,8 @@ mod release_tests { use beacon_chain::test_utils::{ BeaconChainHarness, EphemeralHarnessType, RelativeSyncCommittee, test_spec, }; + use bls::Keypair; + use fixed_bytes::FixedBytesExtended; use maplit::hashset; use state_processing::epoch_cache::initialize_epoch_cache; use state_processing::{VerifyOperation, common::get_attesting_indices_from_state}; diff --git a/beacon_node/operation_pool/src/persistence.rs b/beacon_node/operation_pool/src/persistence.rs index ee45c8dd05..241b5fec53 100644 --- a/beacon_node/operation_pool/src/persistence.rs +++ b/beacon_node/operation_pool/src/persistence.rs @@ -11,6 +11,7 @@ use state_processing::SigVerifiedOp; use std::collections::HashSet; use std::mem; use store::{DBColumn, Error as StoreError, StoreItem}; +use superstruct::superstruct; use types::attestation::AttestationOnDisk; use types::*; diff --git a/beacon_node/operation_pool/src/reward_cache.rs b/beacon_node/operation_pool/src/reward_cache.rs index adedcb5e39..1e3fc4cf2d 100644 --- a/beacon_node/operation_pool/src/reward_cache.rs +++ b/beacon_node/operation_pool/src/reward_cache.rs @@ -1,8 +1,7 @@ use crate::OpPoolError; use bitvec::vec::BitVec; -use types::{ - BeaconState, BeaconStateError, Epoch, EthSpec, FixedBytesExtended, Hash256, ParticipationFlags, -}; +use fixed_bytes::FixedBytesExtended; +use types::{BeaconState, BeaconStateError, Epoch, EthSpec, Hash256, ParticipationFlags}; #[derive(Debug, PartialEq, Eq, Clone)] struct Initialization { diff --git a/beacon_node/src/config.rs b/beacon_node/src/config.rs index 0f169ffaad..26dd3b6642 100644 --- a/beacon_node/src/config.rs +++ b/beacon_node/src/config.rs @@ -6,6 +6,7 @@ use beacon_chain::chain_config::{ }; use beacon_chain::custody_context::NodeCustodyType; use beacon_chain::graffiti_calculator::GraffitiOrigin; +use bls::PublicKeyBytes; use clap::{ArgMatches, Id, parser::ValueSource}; use clap_utils::flags::DISABLE_MALLOC_TUNING_FLAG; use clap_utils::{parse_flag, parse_required}; @@ -29,7 +30,7 @@ use std::str::FromStr; use std::time::Duration; use tracing::{error, info, warn}; use types::graffiti::GraffitiString; -use types::{Checkpoint, Epoch, EthSpec, Hash256, PublicKeyBytes}; +use types::{Checkpoint, Epoch, EthSpec, Hash256}; const PURGE_DB_CONFIRMATION: &str = "confirm"; diff --git a/beacon_node/store/Cargo.toml b/beacon_node/store/Cargo.toml index 61a8474a73..50028fe73f 100644 --- a/beacon_node/store/Cargo.toml +++ b/beacon_node/store/Cargo.toml @@ -15,11 +15,13 @@ db-key = "0.0.5" directory = { workspace = true } ethereum_ssz = { workspace = true } ethereum_ssz_derive = { workspace = true } +fixed_bytes = { workspace = true } itertools = { workspace = true } leveldb = { version = "0.8.6", optional = true, default-features = false } logging = { workspace = true } lru = { workspace = true } metrics = { workspace = true } +milhouse = { workspace = true } parking_lot = { workspace = true } redb = { version = "2.1.3", optional = true } safe_arith = { workspace = true } @@ -31,6 +33,7 @@ strum = { workspace = true } superstruct = { workspace = true } tracing = { workspace = true } tracing-subscriber = { workspace = true } +typenum = { workspace = true } types = { workspace = true } xdelta3 = { workspace = true } zstd = { workspace = true } diff --git a/beacon_node/store/src/chunked_vector.rs b/beacon_node/store/src/chunked_vector.rs index ee043c14f4..9c8114e0c1 100644 --- a/beacon_node/store/src/chunked_vector.rs +++ b/beacon_node/store/src/chunked_vector.rs @@ -16,7 +16,9 @@ //! of elements. To find the chunk index of a vector index: `cindex = vindex / chunk_size`. use self::UpdatePattern::*; use crate::*; +use milhouse::{List, Vector}; use ssz::{Decode, Encode}; +use typenum::Unsigned; use types::historical_summary::HistoricalSummary; /// Description of how a `BeaconState` field is updated during state processing. @@ -784,6 +786,7 @@ impl From for ChunkError { #[cfg(test)] mod test { use super::*; + use fixed_bytes::FixedBytesExtended; use types::MainnetEthSpec as TestSpec; use types::*; diff --git a/beacon_node/store/src/config.rs b/beacon_node/store/src/config.rs index c0f15f2417..0aa00e659b 100644 --- a/beacon_node/store/src/config.rs +++ b/beacon_node/store/src/config.rs @@ -1,12 +1,12 @@ use crate::hdiff::HierarchyConfig; -use crate::superstruct; use crate::{DBColumn, Error, StoreItem}; use serde::{Deserialize, Serialize}; use ssz::{Decode, Encode}; use ssz_derive::{Decode, Encode}; use std::io::{Read, Write}; use std::num::NonZeroUsize; -use strum::{Display, EnumString, EnumVariantNames}; +use strum::{Display, EnumString, VariantNames}; +use superstruct::superstruct; use types::EthSpec; use types::non_zero_usize::new_non_zero_usize; use zstd::{Decoder, Encoder}; @@ -267,7 +267,7 @@ mod test { } #[derive( - Debug, Clone, Copy, Eq, PartialEq, Serialize, Deserialize, Display, EnumString, EnumVariantNames, + Debug, Clone, Copy, Eq, PartialEq, Serialize, Deserialize, Display, EnumString, VariantNames, )] #[strum(serialize_all = "lowercase")] pub enum DatabaseBackend { diff --git a/beacon_node/store/src/database/leveldb_impl.rs b/beacon_node/store/src/database/leveldb_impl.rs index 8fdd5812ea..6b8c615631 100644 --- a/beacon_node/store/src/database/leveldb_impl.rs +++ b/beacon_node/store/src/database/leveldb_impl.rs @@ -3,6 +3,7 @@ use crate::hot_cold_store::{BytesKey, HotColdDBError}; use crate::{ ColumnIter, ColumnKeyIter, DBColumn, Error, KeyValueStoreOp, get_key_for_col, metrics, }; +use fixed_bytes::FixedBytesExtended; use leveldb::{ compaction::Compaction, database::{ @@ -16,7 +17,7 @@ use leveldb::{ use std::collections::HashSet; use std::marker::PhantomData; use std::path::Path; -use types::{EthSpec, FixedBytesExtended, Hash256}; +use types::{EthSpec, Hash256}; use super::interface::WriteOptions; diff --git a/beacon_node/store/src/errors.rs b/beacon_node/store/src/errors.rs index f62647ae54..6da99b7bd6 100644 --- a/beacon_node/store/src/errors.rs +++ b/beacon_node/store/src/errors.rs @@ -6,7 +6,7 @@ use crate::{DBColumn, hdiff}; use leveldb::error::Error as LevelDBError; use ssz::DecodeError; use state_processing::BlockReplayError; -use types::{BeaconStateError, EpochCacheError, Hash256, InconsistentFork, Slot, milhouse}; +use types::{BeaconStateError, EpochCacheError, Hash256, InconsistentFork, Slot}; pub type Result = std::result::Result; diff --git a/beacon_node/store/src/hdiff.rs b/beacon_node/store/src/hdiff.rs index 3e20aab9bf..323c87a914 100644 --- a/beacon_node/store/src/hdiff.rs +++ b/beacon_node/store/src/hdiff.rs @@ -2,6 +2,7 @@ use crate::{DBColumn, StoreConfig, StoreItem, metrics}; use bls::PublicKeyBytes; use itertools::Itertools; +use milhouse::List; use serde::{Deserialize, Serialize}; use ssz::{Decode, Encode}; use ssz_derive::{Decode, Encode}; @@ -11,7 +12,7 @@ use std::str::FromStr; use std::sync::LazyLock; use superstruct::superstruct; use types::historical_summary::HistoricalSummary; -use types::{BeaconState, ChainSpec, Epoch, EthSpec, Hash256, List, Slot, Validator}; +use types::{BeaconState, ChainSpec, Epoch, EthSpec, Hash256, Slot, Validator}; static EMPTY_PUBKEY: LazyLock = LazyLock::new(PublicKeyBytes::empty); diff --git a/beacon_node/store/src/hot_cold_store.rs b/beacon_node/store/src/hot_cold_store.rs index 8f5eead8c2..c413719174 100644 --- a/beacon_node/store/src/hot_cold_store.rs +++ b/beacon_node/store/src/hot_cold_store.rs @@ -18,6 +18,7 @@ use crate::{ metrics::{self, COLD_METRIC, HOT_METRIC}, parse_data_column_key, }; +use fixed_bytes::FixedBytesExtended; use itertools::{Itertools, process_results}; use lru::LruCache; use parking_lot::{Mutex, RwLock}; @@ -38,6 +39,7 @@ use std::path::Path; use std::sync::Arc; use std::time::Duration; use tracing::{debug, error, info, instrument, warn}; +use typenum::Unsigned; use types::data_column_sidecar::{ColumnIndex, DataColumnSidecar, DataColumnSidecarList}; use types::*; use zstd::{Decoder, Encoder}; diff --git a/beacon_node/store/src/iter.rs b/beacon_node/store/src/iter.rs index 88d509731c..e2b666e597 100644 --- a/beacon_node/store/src/iter.rs +++ b/beacon_node/store/src/iter.rs @@ -2,9 +2,9 @@ use crate::errors::HandleUnavailable; use crate::{Error, HotColdDB, ItemStore}; use std::borrow::Cow; use std::marker::PhantomData; +use typenum::Unsigned; use types::{ BeaconState, BeaconStateError, BlindedPayload, EthSpec, Hash256, SignedBeaconBlock, Slot, - typenum::Unsigned, }; /// Implemented for types that have ancestors (e.g., blocks, states) that may be iterated over. @@ -387,8 +387,8 @@ mod test { use crate::{MemoryStore, StoreConfig as Config}; use beacon_chain::test_utils::BeaconChainHarness; use beacon_chain::types::MainnetEthSpec; + use fixed_bytes::FixedBytesExtended; use std::sync::Arc; - use types::FixedBytesExtended; fn get_state() -> BeaconState { let harness = BeaconChainHarness::builder(E::default()) diff --git a/beacon_node/store/src/partial_beacon_state.rs b/beacon_node/store/src/partial_beacon_state.rs index bd9153ecfd..9e5e1ebbb4 100644 --- a/beacon_node/store/src/partial_beacon_state.rs +++ b/beacon_node/store/src/partial_beacon_state.rs @@ -3,11 +3,12 @@ use crate::chunked_vector::{ load_variable_list_from_db, load_vector_from_db, }; use crate::{DBColumn, Error, KeyValueStore, KeyValueStoreOp}; -use ssz::{Decode, DecodeError, Encode}; +use milhouse::{List, Vector}; +use ssz::{BitVector, Decode, DecodeError, Encode}; use ssz_derive::{Decode, Encode}; use std::sync::Arc; +use superstruct::superstruct; use types::historical_summary::HistoricalSummary; -use types::superstruct; use types::*; /// DEPRECATED Lightweight variant of the `BeaconState` that is stored in the database. diff --git a/common/account_utils/Cargo.toml b/common/account_utils/Cargo.toml index 00c74a1303..d0a3e487c4 100644 --- a/common/account_utils/Cargo.toml +++ b/common/account_utils/Cargo.toml @@ -6,6 +6,7 @@ edition = { workspace = true } # See more keys and their definitions at https://doc.rust-lang.org/cargo/reference/manifest.html [dependencies] +bls = { workspace = true } eth2_keystore = { workspace = true } eth2_wallet = { workspace = true } filesystem = { workspace = true } diff --git a/common/account_utils/src/validator_definitions.rs b/common/account_utils/src/validator_definitions.rs index 596d50de42..bffdfcc38b 100644 --- a/common/account_utils/src/validator_definitions.rs +++ b/common/account_utils/src/validator_definitions.rs @@ -4,6 +4,7 @@ //! attempt) to load into the `crate::intialized_validators::InitializedValidators` struct. use crate::{default_keystore_password_path, read_password_string, write_file_via_temporary}; +use bls::PublicKey; use eth2_keystore::Keystore; use regex::Regex; use serde::{Deserialize, Serialize}; @@ -12,7 +13,7 @@ use std::fs::{self, File, create_dir_all}; use std::io; use std::path::{Path, PathBuf}; use tracing::error; -use types::{Address, PublicKey, graffiti::GraffitiString}; +use types::{Address, graffiti::GraffitiString}; use validator_dir::VOTING_KEYSTORE_FILE; use zeroize::Zeroizing; diff --git a/common/deposit_contract/Cargo.toml b/common/deposit_contract/Cargo.toml index dfaad43719..76c18ef242 100644 --- a/common/deposit_contract/Cargo.toml +++ b/common/deposit_contract/Cargo.toml @@ -7,9 +7,10 @@ edition = { workspace = true } build = "build.rs" [dependencies] -alloy-dyn-abi = "1.4" -alloy-json-abi = "1.4" +alloy-dyn-abi = { workspace = true } +alloy-json-abi = { workspace = true } alloy-primitives = { workspace = true } +bls = { workspace = true } ethereum_ssz = { workspace = true } serde_json = { workspace = true } tree_hash = { workspace = true } diff --git a/common/deposit_contract/src/lib.rs b/common/deposit_contract/src/lib.rs index e5f11bb89c..6200a4ca15 100644 --- a/common/deposit_contract/src/lib.rs +++ b/common/deposit_contract/src/lib.rs @@ -1,9 +1,10 @@ use alloy_dyn_abi::{DynSolValue, JsonAbiExt}; use alloy_json_abi::JsonAbi; use alloy_primitives::FixedBytes; +use bls::{PublicKeyBytes, SignatureBytes}; use ssz::{Decode, DecodeError as SszDecodeError, Encode}; use tree_hash::TreeHash; -use types::{DepositData, Hash256, PublicKeyBytes, SignatureBytes}; +use types::{DepositData, Hash256}; #[derive(Debug)] pub enum Error { @@ -126,10 +127,8 @@ pub fn decode_eth1_tx_data(bytes: &[u8], amount: u64) -> Result<(DepositData, Ha #[cfg(test)] mod tests { use super::*; - use types::{ - ChainSpec, EthSpec, Keypair, MinimalEthSpec, Signature, - test_utils::generate_deterministic_keypair, - }; + use bls::{Keypair, Signature}; + use types::{ChainSpec, EthSpec, MinimalEthSpec, test_utils::generate_deterministic_keypair}; type E = MinimalEthSpec; diff --git a/common/eip_3076/Cargo.toml b/common/eip_3076/Cargo.toml index 851ef26238..058e1fd1a0 100644 --- a/common/eip_3076/Cargo.toml +++ b/common/eip_3076/Cargo.toml @@ -11,7 +11,9 @@ json = ["dep:serde_json"] [dependencies] arbitrary = { workspace = true, features = ["derive"], optional = true } +bls = { workspace = true } ethereum_serde_utils = { workspace = true } +fixed_bytes = { workspace = true } serde = { workspace = true } serde_json = { workspace = true, optional = true } types = { workspace = true } diff --git a/common/eip_3076/src/lib.rs b/common/eip_3076/src/lib.rs index 2d47a77de4..cdd05d7b1e 100644 --- a/common/eip_3076/src/lib.rs +++ b/common/eip_3076/src/lib.rs @@ -1,9 +1,10 @@ +use bls::PublicKeyBytes; use serde::{Deserialize, Serialize}; use std::cmp::max; use std::collections::{HashMap, HashSet}; #[cfg(feature = "json")] use std::io; -use types::{Epoch, Hash256, PublicKeyBytes, Slot}; +use types::{Epoch, Hash256, Slot}; #[derive(Debug)] pub enum Error { @@ -170,9 +171,9 @@ impl Interchange { #[cfg(test)] mod tests { use super::*; + use fixed_bytes::FixedBytesExtended; use std::fs::File; use tempfile::tempdir; - use types::FixedBytesExtended; fn get_interchange() -> Interchange { Interchange { diff --git a/common/eth2/Cargo.toml b/common/eth2/Cargo.toml index f7e6cde210..da8aba5ded 100644 --- a/common/eth2/Cargo.toml +++ b/common/eth2/Cargo.toml @@ -5,36 +5,35 @@ authors = ["Paul Hauner "] edition = { workspace = true } [features] -default = ["lighthouse"] -lighthouse = [] +default = [] +lighthouse = ["proto_array", "eth2_keystore", "eip_3076", "zeroize"] +events = ["reqwest-eventsource", "futures", "futures-util"] [dependencies] +bls = { workspace = true } context_deserialize = { workspace = true } educe = { workspace = true } -eip_3076 = { workspace = true } -either = { workspace = true } -enr = { version = "0.13.0", features = ["ed25519"] } -eth2_keystore = { workspace = true } +eip_3076 = { workspace = true, optional = true } +eth2_keystore = { workspace = true, optional = true } ethereum_serde_utils = { workspace = true } ethereum_ssz = { workspace = true } ethereum_ssz_derive = { workspace = true } -futures = { workspace = true } -futures-util = "0.3.8" -libp2p-identity = { version = "0.2", features = ["peerid"] } +futures = { workspace = true, optional = true } +futures-util = { version = "0.3.8", optional = true } mediatype = "0.19.13" -multiaddr = "0.18.2" pretty_reqwest_error = { workspace = true } -proto_array = { workspace = true } -rand = { workspace = true } +proto_array = { workspace = true, optional = true } reqwest = { workspace = true } -reqwest-eventsource = "0.6.0" +reqwest-eventsource = { version = "0.6.0", optional = true } sensitive_url = { workspace = true } serde = { workspace = true } serde_json = { workspace = true } ssz_types = { workspace = true } -test_random_derive = { path = "../../common/test_random_derive" } +superstruct = { workspace = true } types = { workspace = true } -zeroize = { workspace = true } +zeroize = { workspace = true, optional = true } [dev-dependencies] +rand = { workspace = true } +test_random_derive = { path = "../../common/test_random_derive" } tokio = { workspace = true } diff --git a/common/eth2/src/error.rs b/common/eth2/src/error.rs index c1bacb4510..1f21220b79 100644 --- a/common/eth2/src/error.rs +++ b/common/eth2/src/error.rs @@ -14,6 +14,7 @@ use std::{fmt, path::PathBuf}; pub enum Error { /// The `reqwest` client raised an error. HttpClient(PrettyReqwestError), + #[cfg(feature = "events")] /// The `reqwest_eventsource` client raised an error. SseClient(Box), /// The server returned an error message where the body was able to be parsed. @@ -91,6 +92,7 @@ impl Error { pub fn status(&self) -> Option { match self { Error::HttpClient(error) => error.inner().status(), + #[cfg(feature = "events")] Error::SseClient(error) => { if let reqwest_eventsource::Error::InvalidStatusCode(status, _) = error.as_ref() { Some(*status) diff --git a/common/eth2/src/lib.rs b/common/eth2/src/lib.rs index 4e832a11df..820d817d9d 100644 --- a/common/eth2/src/lib.rs +++ b/common/eth2/src/lib.rs @@ -22,20 +22,25 @@ pub use beacon_response::{ }; pub use self::error::{Error, ok_or_error, success_or_error}; +pub use reqwest; +pub use reqwest::{StatusCode, Url}; +pub use sensitive_url::SensitiveUrl; + use self::mixin::{RequestAccept, ResponseOptional}; use self::types::*; +use bls::SignatureBytes; +use context_deserialize::ContextDeserialize; use educe::Educe; +#[cfg(feature = "events")] use futures::Stream; +#[cfg(feature = "events")] use futures_util::StreamExt; -use libp2p_identity::PeerId; -pub use reqwest; use reqwest::{ Body, IntoUrl, RequestBuilder, Response, header::{HeaderMap, HeaderValue}, }; -pub use reqwest::{StatusCode, Url}; +#[cfg(feature = "events")] use reqwest_eventsource::{Event, EventSource}; -pub use sensitive_url::SensitiveUrl; use serde::{Serialize, de::DeserializeOwned}; use ssz::Encode; use std::fmt; @@ -1978,7 +1983,7 @@ impl BeaconNodeHttpClient { /// `GET node/peers/{peer_id}` pub async fn get_node_peers_by_id( &self, - peer_id: PeerId, + peer_id: &str, ) -> Result, Error> { let mut path = self.eth_path(V1)?; @@ -1986,7 +1991,7 @@ impl BeaconNodeHttpClient { .map_err(|()| Error::InvalidUrl(self.server.clone()))? .push("node") .push("peers") - .push(&peer_id.to_string()); + .push(peer_id); self.get(path).await } @@ -2761,6 +2766,7 @@ impl BeaconNodeHttpClient { } /// `GET events?topics` + #[cfg(feature = "events")] pub async fn get_events( &self, topic: &[EventTopic], diff --git a/common/eth2/src/lighthouse_vc/http_client.rs b/common/eth2/src/lighthouse_vc/http_client.rs index 8c9d3397a8..3c850fcb05 100644 --- a/common/eth2/src/lighthouse_vc/http_client.rs +++ b/common/eth2/src/lighthouse_vc/http_client.rs @@ -1,5 +1,6 @@ use super::types::*; use crate::{Error, success_or_error}; +use bls::PublicKeyBytes; use reqwest::{ IntoUrl, header::{HeaderMap, HeaderValue}, diff --git a/common/eth2/src/lighthouse_vc/std_types.rs b/common/eth2/src/lighthouse_vc/std_types.rs index 0290bdd0b7..c54252b9e3 100644 --- a/common/eth2/src/lighthouse_vc/std_types.rs +++ b/common/eth2/src/lighthouse_vc/std_types.rs @@ -1,6 +1,7 @@ +use bls::PublicKeyBytes; use eth2_keystore::Keystore; use serde::{Deserialize, Serialize}; -use types::{Address, Graffiti, PublicKeyBytes}; +use types::{Address, Graffiti}; use zeroize::Zeroizing; pub use eip_3076::Interchange; diff --git a/common/eth2/src/lighthouse_vc/types.rs b/common/eth2/src/lighthouse_vc/types.rs index 8e1d90f8f9..07f8421dc5 100644 --- a/common/eth2/src/lighthouse_vc/types.rs +++ b/common/eth2/src/lighthouse_vc/types.rs @@ -1,6 +1,7 @@ pub use crate::lighthouse::Health; pub use crate::lighthouse_vc::std_types::*; pub use crate::types::{GenericResponse, VersionData}; +use bls::{PublicKey, PublicKeyBytes}; use eth2_keystore::Keystore; use serde::{Deserialize, Serialize}; use std::path::PathBuf; diff --git a/common/eth2/src/types.rs b/common/eth2/src/types.rs index cbdaa004d0..aace8f936c 100644 --- a/common/eth2/src/types.rs +++ b/common/eth2/src/types.rs @@ -1,13 +1,15 @@ //! This module exposes a superset of the `types` crate. It adds additional types that are only //! required for the HTTP API. +pub use types::*; + use crate::{ CONSENSUS_BLOCK_VALUE_HEADER, CONSENSUS_VERSION_HEADER, EXECUTION_PAYLOAD_BLINDED_HEADER, EXECUTION_PAYLOAD_VALUE_HEADER, Error as ServerError, }; -use enr::{CombinedKey, Enr}; +use bls::{PublicKeyBytes, SecretKey, Signature, SignatureBytes}; +use context_deserialize::ContextDeserialize; use mediatype::{MediaType, MediaTypeList, names}; -use multiaddr::Multiaddr; use reqwest::header::HeaderMap; use serde::{Deserialize, Deserializer, Serialize}; use serde_utils::quoted_u64::Quoted; @@ -18,9 +20,12 @@ use std::fmt::{self, Display}; use std::str::FromStr; use std::sync::Arc; use std::time::Duration; +use superstruct::superstruct; + +#[cfg(test)] use test_random_derive::TestRandom; +#[cfg(test)] use types::test_utils::TestRandom; -pub use types::*; // TODO(mac): Temporary module and re-export hack to expose old `consensus/types` via `eth2/types`. pub use crate::beacon_response::*; @@ -557,9 +562,9 @@ pub struct ChainHeadData { #[derive(Debug, Clone, PartialEq, Serialize, Deserialize)] pub struct IdentityData { pub peer_id: String, - pub enr: Enr, - pub p2p_addresses: Vec, - pub discovery_addresses: Vec, + pub enr: String, + pub p2p_addresses: Vec, + pub discovery_addresses: Vec, pub metadata: MetaData, } @@ -2208,7 +2213,8 @@ pub enum ContentType { Ssz, } -#[derive(Clone, Debug, Default, PartialEq, Serialize, Deserialize, Encode, Decode, TestRandom)] +#[cfg_attr(test, derive(TestRandom))] +#[derive(Clone, Debug, Default, PartialEq, Serialize, Deserialize, Encode, Decode)] #[serde(bound = "E: EthSpec")] pub struct BlobsBundle { pub commitments: KzgCommitments, diff --git a/common/eth2_network_config/Cargo.toml b/common/eth2_network_config/Cargo.toml index ec5b0cc1d7..416ffb1975 100644 --- a/common/eth2_network_config/Cargo.toml +++ b/common/eth2_network_config/Cargo.toml @@ -10,6 +10,7 @@ build = "build.rs" bytes = { workspace = true } discv5 = { workspace = true } eth2_config = { workspace = true } +fixed_bytes = { workspace = true } kzg = { workspace = true } pretty_reqwest_error = { workspace = true } reqwest = { workspace = true } diff --git a/common/eth2_network_config/src/lib.rs b/common/eth2_network_config/src/lib.rs index 12de21239a..16ee45e524 100644 --- a/common/eth2_network_config/src/lib.rs +++ b/common/eth2_network_config/src/lib.rs @@ -464,9 +464,10 @@ fn parse_state_download_url(url: &str) -> Result { #[cfg(test)] mod tests { use super::*; + use fixed_bytes::FixedBytesExtended; use ssz::Encode; use tempfile::Builder as TempBuilder; - use types::{Eth1Data, FixedBytesExtended, GnosisEthSpec, MainnetEthSpec}; + use types::{Eth1Data, GnosisEthSpec, MainnetEthSpec}; type E = MainnetEthSpec; diff --git a/common/health_metrics/Cargo.toml b/common/health_metrics/Cargo.toml index 20a8c6e4e4..816d4ec68c 100644 --- a/common/health_metrics/Cargo.toml +++ b/common/health_metrics/Cargo.toml @@ -4,7 +4,7 @@ version = "0.1.0" edition = { workspace = true } [dependencies] -eth2 = { workspace = true } +eth2 = { workspace = true, features = ["lighthouse"] } metrics = { workspace = true } [target.'cfg(target_os = "linux")'.dependencies] diff --git a/common/monitoring_api/Cargo.toml b/common/monitoring_api/Cargo.toml index 9e2c36e2c7..e00b1f027b 100644 --- a/common/monitoring_api/Cargo.toml +++ b/common/monitoring_api/Cargo.toml @@ -6,7 +6,7 @@ edition = { workspace = true } # See more keys and their definitions at https://doc.rust-lang.org/cargo/reference/manifest.html [dependencies] -eth2 = { workspace = true } +eth2 = { workspace = true, features = ["lighthouse"] } health_metrics = { workspace = true } lighthouse_version = { workspace = true } metrics = { workspace = true } diff --git a/common/test_random_derive/src/lib.rs b/common/test_random_derive/src/lib.rs index 3017936f1a..bf57d79aaa 100644 --- a/common/test_random_derive/src/lib.rs +++ b/common/test_random_derive/src/lib.rs @@ -8,7 +8,8 @@ use syn::{DeriveInput, parse_macro_input}; /// The field attribute is: `#[test_random(default)]` fn should_use_default(field: &syn::Field) -> bool { field.attrs.iter().any(|attr| { - attr.path.is_ident("test_random") && attr.tokens.to_string().replace(' ', "") == "(default)" + attr.path().is_ident("test_random") + && matches!(&attr.meta, syn::Meta::List(list) if list.tokens.to_string().replace(' ', "") == "default") }) } diff --git a/common/validator_dir/src/builder.rs b/common/validator_dir/src/builder.rs index bae36789bb..ab495242e4 100644 --- a/common/validator_dir/src/builder.rs +++ b/common/validator_dir/src/builder.rs @@ -1,5 +1,5 @@ use crate::{Error as DirError, ValidatorDir}; -use bls::get_withdrawal_credentials; +use bls::{Keypair, Signature, get_withdrawal_credentials}; use deposit_contract::{Error as DepositError, encode_eth1_tx_data}; use eth2_keystore::{Error as KeystoreError, Keystore, KeystoreBuilder, PlainText}; use filesystem::create_with_600_perms; @@ -7,7 +7,7 @@ use rand::{Rng, distr::Alphanumeric}; use std::fs::{File, create_dir_all}; use std::io::{self, Write}; use std::path::{Path, PathBuf}; -use types::{ChainSpec, DepositData, Hash256, Keypair, Signature}; +use types::{ChainSpec, DepositData, Hash256}; /// The `Alphanumeric` crate only generates a-z, A-Z, 0-9, therefore it has a range of 62 /// characters. diff --git a/common/validator_dir/src/validator_dir.rs b/common/validator_dir/src/validator_dir.rs index 8b50ea6687..0799897a70 100644 --- a/common/validator_dir/src/validator_dir.rs +++ b/common/validator_dir/src/validator_dir.rs @@ -2,6 +2,7 @@ use crate::builder::{ ETH1_DEPOSIT_AMOUNT_FILE, ETH1_DEPOSIT_DATA_FILE, VOTING_KEYSTORE_FILE, WITHDRAWAL_KEYSTORE_FILE, keystore_password_path, }; +use bls::Keypair; use deposit_contract::decode_eth1_tx_data; use educe::Educe; use eth2_keystore::{Error as KeystoreError, Keystore, PlainText}; @@ -10,7 +11,7 @@ use std::fs::{File, read, write}; use std::io; use std::path::{Path, PathBuf}; use tree_hash::TreeHash; -use types::{DepositData, Hash256, Keypair}; +use types::{DepositData, Hash256}; /// The file used to save the Eth1 transaction hash from a deposit. pub const ETH1_DEPOSIT_TX_HASH_FILE: &str = "eth1-deposit-tx-hash.txt"; diff --git a/common/validator_dir/tests/tests.rs b/common/validator_dir/tests/tests.rs index 7d9730ebd3..ede80c244e 100644 --- a/common/validator_dir/tests/tests.rs +++ b/common/validator_dir/tests/tests.rs @@ -1,10 +1,11 @@ #![cfg(not(debug_assertions))] +use bls::Keypair; use eth2_keystore::{Keystore, KeystoreBuilder, PlainText}; use std::fs::{self, File}; use std::path::Path; use tempfile::{TempDir, tempdir}; -use types::{EthSpec, Keypair, MainnetEthSpec, test_utils::generate_deterministic_keypair}; +use types::{EthSpec, MainnetEthSpec, test_utils::generate_deterministic_keypair}; use validator_dir::{ Builder, BuilderError, ETH1_DEPOSIT_DATA_FILE, ETH1_DEPOSIT_TX_HASH_FILE, VOTING_KEYSTORE_FILE, ValidatorDir, WITHDRAWAL_KEYSTORE_FILE, diff --git a/consensus/fork_choice/Cargo.toml b/consensus/fork_choice/Cargo.toml index 0a244c2ba1..a07aa38aa5 100644 --- a/consensus/fork_choice/Cargo.toml +++ b/consensus/fork_choice/Cargo.toml @@ -8,6 +8,7 @@ edition = { workspace = true } [dependencies] ethereum_ssz = { workspace = true } ethereum_ssz_derive = { workspace = true } +fixed_bytes = { workspace = true } logging = { workspace = true } metrics = { workspace = true } proto_array = { workspace = true } diff --git a/consensus/fork_choice/src/fork_choice.rs b/consensus/fork_choice/src/fork_choice.rs index 6565e7cdaf..9a8cae0c36 100644 --- a/consensus/fork_choice/src/fork_choice.rs +++ b/consensus/fork_choice/src/fork_choice.rs @@ -1,5 +1,6 @@ use crate::metrics::{self, scrape_for_metrics}; use crate::{ForkChoiceStore, InvalidationOperation}; +use fixed_bytes::FixedBytesExtended; use logging::crit; use proto_array::{ Block as ProtoBlock, DisallowedReOrgOffsets, ExecutionStatus, JustifiedBalances, @@ -19,7 +20,7 @@ use tracing::{debug, instrument, warn}; use types::{ AbstractExecPayload, AttestationShufflingId, AttesterSlashingRef, BeaconBlockRef, BeaconState, BeaconStateError, ChainSpec, Checkpoint, Epoch, EthSpec, ExecPayload, ExecutionBlockHash, - FixedBytesExtended, Hash256, IndexedAttestationRef, RelativeEpoch, SignedBeaconBlock, Slot, + Hash256, IndexedAttestationRef, RelativeEpoch, SignedBeaconBlock, Slot, consts::bellatrix::INTERVALS_PER_SLOT, }; diff --git a/consensus/fork_choice/tests/tests.rs b/consensus/fork_choice/tests/tests.rs index 67b792ef0d..d3a84ee85b 100644 --- a/consensus/fork_choice/tests/tests.rs +++ b/consensus/fork_choice/tests/tests.rs @@ -7,6 +7,7 @@ use beacon_chain::{ BeaconChain, BeaconChainError, BeaconForkChoiceStore, ChainConfig, ForkChoiceError, StateSkipConfig, WhenSlotSkipped, }; +use fixed_bytes::FixedBytesExtended; use fork_choice::{ ForkChoiceStore, InvalidAttestation, InvalidBlock, PayloadVerificationStatus, QueuedAttestation, }; @@ -17,9 +18,9 @@ use std::time::Duration; use store::MemoryStore; use types::SingleAttestation; use types::{ - BeaconBlockRef, BeaconState, ChainSpec, Checkpoint, Epoch, EthSpec, FixedBytesExtended, - ForkName, Hash256, IndexedAttestation, MainnetEthSpec, RelativeEpoch, SignedBeaconBlock, Slot, - SubnetId, test_utils::generate_deterministic_keypair, + BeaconBlockRef, BeaconState, ChainSpec, Checkpoint, Epoch, EthSpec, ForkName, Hash256, + IndexedAttestation, MainnetEthSpec, RelativeEpoch, SignedBeaconBlock, Slot, SubnetId, + test_utils::generate_deterministic_keypair, }; pub type E = MainnetEthSpec; diff --git a/consensus/proto_array/Cargo.toml b/consensus/proto_array/Cargo.toml index bd6757c0fa..782610e0d3 100644 --- a/consensus/proto_array/Cargo.toml +++ b/consensus/proto_array/Cargo.toml @@ -11,6 +11,7 @@ path = "src/bin.rs" [dependencies] ethereum_ssz = { workspace = true } ethereum_ssz_derive = { workspace = true } +fixed_bytes = { workspace = true } safe_arith = { workspace = true } serde = { workspace = true } serde_yaml = { workspace = true } diff --git a/consensus/proto_array/src/fork_choice_test_definition.rs b/consensus/proto_array/src/fork_choice_test_definition.rs index 43a7e3b77f..e9deb6759f 100644 --- a/consensus/proto_array/src/fork_choice_test_definition.rs +++ b/consensus/proto_array/src/fork_choice_test_definition.rs @@ -5,11 +5,12 @@ mod votes; use crate::proto_array_fork_choice::{Block, ExecutionStatus, ProtoArrayForkChoice}; use crate::{InvalidationOperation, JustifiedBalances}; +use fixed_bytes::FixedBytesExtended; use serde::{Deserialize, Serialize}; use std::collections::BTreeSet; use types::{ - AttestationShufflingId, Checkpoint, Epoch, EthSpec, ExecutionBlockHash, FixedBytesExtended, - Hash256, MainnetEthSpec, Slot, + AttestationShufflingId, Checkpoint, Epoch, EthSpec, ExecutionBlockHash, Hash256, + MainnetEthSpec, Slot, }; pub use execution_status::*; diff --git a/consensus/proto_array/src/fork_choice_test_definition/no_votes.rs b/consensus/proto_array/src/fork_choice_test_definition/no_votes.rs index de84fbdd12..d20eaacb99 100644 --- a/consensus/proto_array/src/fork_choice_test_definition/no_votes.rs +++ b/consensus/proto_array/src/fork_choice_test_definition/no_votes.rs @@ -1,4 +1,4 @@ -use types::FixedBytesExtended; +use fixed_bytes::FixedBytesExtended; use super::*; diff --git a/consensus/proto_array/src/proto_array.rs b/consensus/proto_array/src/proto_array.rs index 1d78ce9f44..5bfcdae463 100644 --- a/consensus/proto_array/src/proto_array.rs +++ b/consensus/proto_array/src/proto_array.rs @@ -1,5 +1,6 @@ use crate::error::InvalidBestNodeInfo; use crate::{Block, ExecutionStatus, JustifiedBalances, error::Error}; +use fixed_bytes::FixedBytesExtended; use serde::{Deserialize, Serialize}; use ssz::Encode; use ssz::four_byte_option_impl; @@ -7,8 +8,8 @@ use ssz_derive::{Decode, Encode}; use std::collections::{HashMap, HashSet}; use superstruct::superstruct; use types::{ - AttestationShufflingId, ChainSpec, Checkpoint, Epoch, EthSpec, ExecutionBlockHash, - FixedBytesExtended, Hash256, Slot, + AttestationShufflingId, ChainSpec, Checkpoint, Epoch, EthSpec, ExecutionBlockHash, Hash256, + Slot, }; // Define a "legacy" implementation of `Option` which uses four bytes for encoding the union diff --git a/consensus/proto_array/src/proto_array_fork_choice.rs b/consensus/proto_array/src/proto_array_fork_choice.rs index 137471ce36..3edf1e0644 100644 --- a/consensus/proto_array/src/proto_array_fork_choice.rs +++ b/consensus/proto_array/src/proto_array_fork_choice.rs @@ -7,6 +7,7 @@ use crate::{ }, ssz_container::SszContainer, }; +use fixed_bytes::FixedBytesExtended; use serde::{Deserialize, Serialize}; use ssz::{Decode, Encode}; use ssz_derive::{Decode, Encode}; @@ -15,8 +16,8 @@ use std::{ fmt, }; use types::{ - AttestationShufflingId, ChainSpec, Checkpoint, Epoch, EthSpec, ExecutionBlockHash, - FixedBytesExtended, Hash256, Slot, + AttestationShufflingId, ChainSpec, Checkpoint, Epoch, EthSpec, ExecutionBlockHash, Hash256, + Slot, }; pub const DEFAULT_PRUNE_THRESHOLD: usize = 256; @@ -1095,7 +1096,8 @@ fn compute_deltas( #[cfg(test)] mod test_compute_deltas { use super::*; - use types::{FixedBytesExtended, MainnetEthSpec}; + use fixed_bytes::FixedBytesExtended; + use types::MainnetEthSpec; /// Gives a hash that is not the zero hash (unless i is `usize::MAX)`. fn hash_from_index(i: usize) -> Hash256 { diff --git a/consensus/state_processing/Cargo.toml b/consensus/state_processing/Cargo.toml index 3821aa1689..a08035d583 100644 --- a/consensus/state_processing/Cargo.toml +++ b/consensus/state_processing/Cargo.toml @@ -24,11 +24,13 @@ educe = { workspace = true } ethereum_hashing = { workspace = true } ethereum_ssz = { workspace = true } ethereum_ssz_derive = { workspace = true } +fixed_bytes = { workspace = true } int_to_bytes = { workspace = true } integer-sqrt = "0.1.5" itertools = { workspace = true } merkle_proof = { workspace = true } metrics = { workspace = true } +milhouse = { workspace = true } rand = { workspace = true } rayon = { workspace = true } safe_arith = { workspace = true } @@ -37,6 +39,7 @@ ssz_types = { workspace = true } test_random_derive = { path = "../../common/test_random_derive" } tracing = { workspace = true } tree_hash = { workspace = true } +typenum = { workspace = true } types = { workspace = true } [dev-dependencies] diff --git a/consensus/state_processing/src/common/get_attesting_indices.rs b/consensus/state_processing/src/common/get_attesting_indices.rs index e4f5aa3c8b..dc7be7c251 100644 --- a/consensus/state_processing/src/common/get_attesting_indices.rs +++ b/consensus/state_processing/src/common/get_attesting_indices.rs @@ -2,6 +2,7 @@ use types::*; pub mod attesting_indices_base { use crate::per_block_processing::errors::{AttestationInvalid as Invalid, BlockOperationError}; + use ssz_types::{BitList, VariableList}; use types::*; /// Convert `attestation` to (almost) indexed-verifiable form. @@ -44,10 +45,10 @@ pub mod attesting_indices_base { } pub mod attesting_indices_electra { - use std::collections::HashSet; - use crate::per_block_processing::errors::{AttestationInvalid as Invalid, BlockOperationError}; use safe_arith::SafeArith; + use ssz_types::{BitList, BitVector, VariableList}; + use std::collections::HashSet; use types::*; /// Compute an Electra IndexedAttestation given a list of committees. diff --git a/consensus/state_processing/src/common/slash_validator.rs b/consensus/state_processing/src/common/slash_validator.rs index 52f360849e..01c1855fb1 100644 --- a/consensus/state_processing/src/common/slash_validator.rs +++ b/consensus/state_processing/src/common/slash_validator.rs @@ -6,6 +6,7 @@ use crate::{ }; use safe_arith::SafeArith; use std::cmp; +use typenum::Unsigned; use types::{ consts::altair::{PROPOSER_WEIGHT, WEIGHT_DENOMINATOR}, *, diff --git a/consensus/state_processing/src/epoch_cache.rs b/consensus/state_processing/src/epoch_cache.rs index 86db037446..ee03596d09 100644 --- a/consensus/state_processing/src/epoch_cache.rs +++ b/consensus/state_processing/src/epoch_cache.rs @@ -2,12 +2,11 @@ use crate::common::altair::BaseRewardPerIncrement; use crate::common::base::SqrtTotalActiveBalance; use crate::common::{altair, base}; use crate::metrics; +use fixed_bytes::FixedBytesExtended; use safe_arith::SafeArith; use tracing::instrument; use types::epoch_cache::{EpochCache, EpochCacheError, EpochCacheKey}; -use types::{ - ActivationQueue, BeaconState, ChainSpec, EthSpec, FixedBytesExtended, ForkName, Hash256, -}; +use types::{ActivationQueue, BeaconState, ChainSpec, EthSpec, ForkName, Hash256}; /// Precursor to an `EpochCache`. pub struct PreEpochCache { diff --git a/consensus/state_processing/src/genesis.rs b/consensus/state_processing/src/genesis.rs index b8657676fd..1575fce22f 100644 --- a/consensus/state_processing/src/genesis.rs +++ b/consensus/state_processing/src/genesis.rs @@ -7,6 +7,7 @@ use crate::upgrade::{ upgrade_to_altair, upgrade_to_bellatrix, upgrade_to_capella, upgrade_to_deneb, upgrade_to_fulu, upgrade_to_gloas, }; +use fixed_bytes::FixedBytesExtended; use safe_arith::{ArithError, SafeArith}; use std::sync::Arc; use tree_hash::TreeHash; diff --git a/consensus/state_processing/src/per_block_processing.rs b/consensus/state_processing/src/per_block_processing.rs index 1695a638f1..07149ff2ee 100644 --- a/consensus/state_processing/src/per_block_processing.rs +++ b/consensus/state_processing/src/per_block_processing.rs @@ -5,6 +5,7 @@ use safe_arith::{ArithError, SafeArith, SafeArithIter}; use signature_sets::{block_proposal_signature_set, get_pubkey_from_state, randao_signature_set}; use std::borrow::Cow; use tree_hash::TreeHash; +use typenum::Unsigned; use types::*; pub use self::verify_attester_slashing::{ diff --git a/consensus/state_processing/src/per_block_processing/altair/sync_committee.rs b/consensus/state_processing/src/per_block_processing/altair/sync_committee.rs index 1219c7df44..8cc9de42db 100644 --- a/consensus/state_processing/src/per_block_processing/altair/sync_committee.rs +++ b/consensus/state_processing/src/per_block_processing/altair/sync_committee.rs @@ -1,12 +1,12 @@ use crate::common::{altair::BaseRewardPerIncrement, decrease_balance, increase_balance}; use crate::per_block_processing::errors::{BlockProcessingError, SyncAggregateInvalid}; use crate::{VerifySignatures, signature_sets::sync_aggregate_signature_set}; +use bls::PublicKeyBytes; use safe_arith::SafeArith; use std::borrow::Cow; +use typenum::Unsigned; use types::consts::altair::{PROPOSER_WEIGHT, SYNC_REWARD_WEIGHT, WEIGHT_DENOMINATOR}; -use types::{ - BeaconState, BeaconStateError, ChainSpec, EthSpec, PublicKeyBytes, SyncAggregate, Unsigned, -}; +use types::{BeaconState, BeaconStateError, ChainSpec, EthSpec, SyncAggregate}; pub fn process_sync_aggregate( state: &mut BeaconState, diff --git a/consensus/state_processing/src/per_block_processing/process_operations.rs b/consensus/state_processing/src/per_block_processing/process_operations.rs index 9a1c6c2f6a..8afeeb685b 100644 --- a/consensus/state_processing/src/per_block_processing/process_operations.rs +++ b/consensus/state_processing/src/per_block_processing/process_operations.rs @@ -5,8 +5,9 @@ use crate::common::{ slash_validator, }; use crate::per_block_processing::errors::{BlockProcessingError, IntoWithIndex}; +use ssz_types::FixedVector; +use typenum::U33; use types::consts::altair::{PARTICIPATION_FLAG_WEIGHTS, PROPOSER_WEIGHT, WEIGHT_DENOMINATOR}; -use types::typenum::U33; pub fn process_operations>( state: &mut BeaconState, diff --git a/consensus/state_processing/src/per_block_processing/signature_sets.rs b/consensus/state_processing/src/per_block_processing/signature_sets.rs index dafd0d79ea..0e936007ee 100644 --- a/consensus/state_processing/src/per_block_processing/signature_sets.rs +++ b/consensus/state_processing/src/per_block_processing/signature_sets.rs @@ -2,17 +2,18 @@ //! validated individually, or alongside in others in a potentially cheaper bulk operation. //! //! This module exposes one function to extract each type of `SignatureSet` from a `BeaconBlock`. -use bls::SignatureSet; +use bls::{AggregateSignature, PublicKey, PublicKeyBytes, Signature, SignatureSet}; use ssz::DecodeError; use std::borrow::Cow; use tree_hash::TreeHash; +use typenum::Unsigned; use types::{ - AbstractExecPayload, AggregateSignature, AttesterSlashingRef, BeaconBlockRef, BeaconState, - BeaconStateError, ChainSpec, DepositData, Domain, Epoch, EthSpec, Fork, Hash256, - InconsistentFork, IndexedAttestation, IndexedAttestationRef, ProposerSlashing, PublicKey, - PublicKeyBytes, Signature, SignedAggregateAndProof, SignedBeaconBlock, SignedBeaconBlockHeader, - SignedBlsToExecutionChange, SignedContributionAndProof, SignedRoot, SignedVoluntaryExit, - SigningData, Slot, SyncAggregate, SyncAggregatorSelectionData, Unsigned, + AbstractExecPayload, AttesterSlashingRef, BeaconBlockRef, BeaconState, BeaconStateError, + ChainSpec, DepositData, Domain, Epoch, EthSpec, Fork, Hash256, InconsistentFork, + IndexedAttestation, IndexedAttestationRef, ProposerSlashing, SignedAggregateAndProof, + SignedBeaconBlock, SignedBeaconBlockHeader, SignedBlsToExecutionChange, + SignedContributionAndProof, SignedRoot, SignedVoluntaryExit, SigningData, Slot, SyncAggregate, + SyncAggregatorSelectionData, }; pub type Result = std::result::Result; diff --git a/consensus/state_processing/src/per_block_processing/tests.rs b/consensus/state_processing/src/per_block_processing/tests.rs index c32797f77f..739717b33f 100644 --- a/consensus/state_processing/src/per_block_processing/tests.rs +++ b/consensus/state_processing/src/per_block_processing/tests.rs @@ -11,7 +11,10 @@ use crate::{ per_block_processing::{process_operations, verify_exit::verify_exit}, }; use beacon_chain::test_utils::{BeaconChainHarness, EphemeralHarnessType}; +use bls::{AggregateSignature, Keypair, PublicKeyBytes, Signature, SignatureBytes}; +use fixed_bytes::FixedBytesExtended; use ssz_types::Bitfield; +use ssz_types::VariableList; use std::sync::{Arc, LazyLock}; use test_utils::generate_deterministic_keypairs; use types::*; diff --git a/consensus/state_processing/src/per_block_processing/verify_deposit.rs b/consensus/state_processing/src/per_block_processing/verify_deposit.rs index c996e580a7..d403bfa82b 100644 --- a/consensus/state_processing/src/per_block_processing/verify_deposit.rs +++ b/consensus/state_processing/src/per_block_processing/verify_deposit.rs @@ -1,5 +1,6 @@ use super::errors::{BlockOperationError, DepositInvalid}; use crate::per_block_processing::signature_sets::deposit_pubkey_signature_message; +use bls::PublicKeyBytes; use merkle_proof::verify_merkle_proof; use safe_arith::SafeArith; use tree_hash::TreeHash; diff --git a/consensus/state_processing/src/per_epoch_processing/altair/participation_flag_updates.rs b/consensus/state_processing/src/per_epoch_processing/altair/participation_flag_updates.rs index 5c08406eae..5e177c5d2b 100644 --- a/consensus/state_processing/src/per_epoch_processing/altair/participation_flag_updates.rs +++ b/consensus/state_processing/src/per_epoch_processing/altair/participation_flag_updates.rs @@ -1,5 +1,5 @@ use crate::EpochProcessingError; -use types::List; +use milhouse::List; use types::beacon_state::BeaconState; use types::eth_spec::EthSpec; use types::participation_flags::ParticipationFlags; diff --git a/consensus/state_processing/src/per_epoch_processing/epoch_processing_summary.rs b/consensus/state_processing/src/per_epoch_processing/epoch_processing_summary.rs index fd712cc8e5..a818e08775 100644 --- a/consensus/state_processing/src/per_epoch_processing/epoch_processing_summary.rs +++ b/consensus/state_processing/src/per_epoch_processing/epoch_processing_summary.rs @@ -1,9 +1,10 @@ use super::base::{TotalBalances, ValidatorStatus, validator_statuses::InclusionInfo}; use crate::metrics; +use milhouse::List; use std::sync::Arc; use types::{ - BeaconStateError, Epoch, EthSpec, List, ParticipationFlags, ProgressiveBalancesCache, - SyncCommittee, Validator, + BeaconStateError, Epoch, EthSpec, ParticipationFlags, ProgressiveBalancesCache, SyncCommittee, + Validator, consts::altair::{TIMELY_HEAD_FLAG_INDEX, TIMELY_SOURCE_FLAG_INDEX, TIMELY_TARGET_FLAG_INDEX}, }; diff --git a/consensus/state_processing/src/per_epoch_processing/errors.rs b/consensus/state_processing/src/per_epoch_processing/errors.rs index a5a2a69ebf..4818dcbf67 100644 --- a/consensus/state_processing/src/per_epoch_processing/errors.rs +++ b/consensus/state_processing/src/per_epoch_processing/errors.rs @@ -1,4 +1,5 @@ -use types::{BeaconStateError, EpochCacheError, InconsistentFork, milhouse}; +use milhouse; +use types::{BeaconStateError, EpochCacheError, InconsistentFork}; #[derive(Debug, PartialEq)] pub enum EpochProcessingError { diff --git a/consensus/state_processing/src/per_epoch_processing/historical_roots_update.rs b/consensus/state_processing/src/per_epoch_processing/historical_roots_update.rs index 8fcdda062c..9172d954bc 100644 --- a/consensus/state_processing/src/per_epoch_processing/historical_roots_update.rs +++ b/consensus/state_processing/src/per_epoch_processing/historical_roots_update.rs @@ -1,7 +1,7 @@ use super::errors::EpochProcessingError; use safe_arith::SafeArith; use tree_hash::TreeHash; -use types::Unsigned; +use typenum::Unsigned; use types::beacon_state::BeaconState; use types::eth_spec::EthSpec; diff --git a/consensus/state_processing/src/per_epoch_processing/justification_and_finalization_state.rs b/consensus/state_processing/src/per_epoch_processing/justification_and_finalization_state.rs index 66d68804e1..8d712fd19b 100644 --- a/consensus/state_processing/src/per_epoch_processing/justification_and_finalization_state.rs +++ b/consensus/state_processing/src/per_epoch_processing/justification_and_finalization_state.rs @@ -1,4 +1,5 @@ -use types::{BeaconState, BeaconStateError, BitVector, Checkpoint, Epoch, EthSpec, Hash256}; +use ssz_types::BitVector; +use types::{BeaconState, BeaconStateError, Checkpoint, Epoch, EthSpec, Hash256}; /// This is a subset of the `BeaconState` which is used to compute justification and finality /// without modifying the `BeaconState`. diff --git a/consensus/state_processing/src/per_epoch_processing/resets.rs b/consensus/state_processing/src/per_epoch_processing/resets.rs index c9f69c3c95..e05fb30c33 100644 --- a/consensus/state_processing/src/per_epoch_processing/resets.rs +++ b/consensus/state_processing/src/per_epoch_processing/resets.rs @@ -1,8 +1,9 @@ use super::errors::EpochProcessingError; +use milhouse::List; use safe_arith::SafeArith; +use typenum::Unsigned; use types::beacon_state::BeaconState; use types::eth_spec::EthSpec; -use types::{List, Unsigned}; pub fn process_eth1_data_reset( state: &mut BeaconState, diff --git a/consensus/state_processing/src/per_epoch_processing/single_pass.rs b/consensus/state_processing/src/per_epoch_processing/single_pass.rs index 1584e932bd..914e025f2f 100644 --- a/consensus/state_processing/src/per_epoch_processing/single_pass.rs +++ b/consensus/state_processing/src/per_epoch_processing/single_pass.rs @@ -8,19 +8,20 @@ use crate::{ per_epoch_processing::{Delta, Error, ParticipationEpochSummary}, }; use itertools::izip; +use milhouse::{Cow, List, Vector}; use safe_arith::{SafeArith, SafeArithIter}; use std::cmp::{max, min}; use std::collections::{BTreeSet, HashMap}; use tracing::instrument; +use typenum::Unsigned; use types::{ ActivationQueue, BeaconState, BeaconStateError, ChainSpec, Checkpoint, DepositData, Epoch, - EthSpec, ExitCache, ForkName, List, ParticipationFlags, PendingDeposit, - ProgressiveBalancesCache, RelativeEpoch, Unsigned, Validator, Vector, + EthSpec, ExitCache, ForkName, ParticipationFlags, PendingDeposit, ProgressiveBalancesCache, + RelativeEpoch, Validator, consts::altair::{ NUM_FLAG_INDICES, PARTICIPATION_FLAG_WEIGHTS, TIMELY_HEAD_FLAG_INDEX, TIMELY_TARGET_FLAG_INDEX, WEIGHT_DENOMINATOR, }, - milhouse::Cow, }; pub struct SinglePassConfig { diff --git a/consensus/state_processing/src/per_epoch_processing/slashings.rs b/consensus/state_processing/src/per_epoch_processing/slashings.rs index 47eb06e907..6008276d15 100644 --- a/consensus/state_processing/src/per_epoch_processing/slashings.rs +++ b/consensus/state_processing/src/per_epoch_processing/slashings.rs @@ -4,7 +4,8 @@ use crate::per_epoch_processing::{ single_pass::{SinglePassConfig, process_epoch_single_pass}, }; use safe_arith::{SafeArith, SafeArithIter}; -use types::{BeaconState, ChainSpec, EthSpec, Unsigned}; +use typenum::Unsigned; +use types::{BeaconState, ChainSpec, EthSpec}; /// Process slashings. pub fn process_slashings( diff --git a/consensus/state_processing/src/per_slot_processing.rs b/consensus/state_processing/src/per_slot_processing.rs index 8695054e1e..0f8e5dc52d 100644 --- a/consensus/state_processing/src/per_slot_processing.rs +++ b/consensus/state_processing/src/per_slot_processing.rs @@ -3,6 +3,7 @@ use crate::upgrade::{ upgrade_to_electra, upgrade_to_fulu, upgrade_to_gloas, }; use crate::{per_epoch_processing::EpochProcessingSummary, *}; +use fixed_bytes::FixedBytesExtended; use safe_arith::{ArithError, SafeArith}; use tracing::instrument; use types::*; diff --git a/consensus/state_processing/src/state_advance.rs b/consensus/state_processing/src/state_advance.rs index 4d38e7797e..19b21dad19 100644 --- a/consensus/state_processing/src/state_advance.rs +++ b/consensus/state_processing/src/state_advance.rs @@ -5,7 +5,8 @@ //! duplication and protect against some easy-to-make mistakes when performing state advances. use crate::*; -use types::{BeaconState, ChainSpec, EthSpec, FixedBytesExtended, Hash256, Slot}; +use fixed_bytes::FixedBytesExtended; +use types::{BeaconState, ChainSpec, EthSpec, Hash256, Slot}; #[derive(Debug, PartialEq)] pub enum Error { diff --git a/consensus/state_processing/src/upgrade/altair.rs b/consensus/state_processing/src/upgrade/altair.rs index 3006da25ae..022175ff99 100644 --- a/consensus/state_processing/src/upgrade/altair.rs +++ b/consensus/state_processing/src/upgrade/altair.rs @@ -2,11 +2,12 @@ use crate::common::update_progressive_balances_cache::initialize_progressive_bal use crate::common::{ attesting_indices_base::get_attesting_indices, get_attestation_participation_flag_indices, }; +use milhouse::List; use std::mem; use std::sync::Arc; use types::{ BeaconState, BeaconStateAltair, BeaconStateError as Error, ChainSpec, EpochCache, EthSpec, - Fork, List, ParticipationFlags, PendingAttestation, RelativeEpoch, SyncCommittee, + Fork, ParticipationFlags, PendingAttestation, RelativeEpoch, SyncCommittee, }; /// Translate the participation information from the epoch prior to the fork into Altair's format. diff --git a/consensus/state_processing/src/upgrade/capella.rs b/consensus/state_processing/src/upgrade/capella.rs index ae0dbde767..948fa511b7 100644 --- a/consensus/state_processing/src/upgrade/capella.rs +++ b/consensus/state_processing/src/upgrade/capella.rs @@ -1,7 +1,8 @@ +use milhouse::List; use std::mem; use types::{ BeaconState, BeaconStateCapella, BeaconStateError as Error, ChainSpec, EpochCache, EthSpec, - Fork, List, + Fork, }; /// Transform a `Bellatrix` state into an `Capella` state. diff --git a/consensus/state_processing/src/upgrade/fulu.rs b/consensus/state_processing/src/upgrade/fulu.rs index c2aced7047..c14c1edbec 100644 --- a/consensus/state_processing/src/upgrade/fulu.rs +++ b/consensus/state_processing/src/upgrade/fulu.rs @@ -1,8 +1,7 @@ +use milhouse::Vector; use safe_arith::SafeArith; use std::mem; -use types::{ - BeaconState, BeaconStateError as Error, BeaconStateFulu, ChainSpec, EthSpec, Fork, Vector, -}; +use types::{BeaconState, BeaconStateError as Error, BeaconStateFulu, ChainSpec, EthSpec, Fork}; /// Transform a `Electra` state into an `Fulu` state. pub fn upgrade_to_fulu( diff --git a/consensus/state_processing/src/upgrade/gloas.rs b/consensus/state_processing/src/upgrade/gloas.rs index d95b42343c..d6c353cc2a 100644 --- a/consensus/state_processing/src/upgrade/gloas.rs +++ b/consensus/state_processing/src/upgrade/gloas.rs @@ -1,8 +1,10 @@ use bls::Hash256; +use milhouse::{List, Vector}; +use ssz_types::BitVector; use std::mem; use types::{ - BeaconState, BeaconStateError as Error, BeaconStateGloas, BitVector, BuilderPendingPayment, - ChainSpec, EthSpec, ExecutionPayloadBid, Fork, List, Vector, + BeaconState, BeaconStateError as Error, BeaconStateGloas, BuilderPendingPayment, ChainSpec, + EthSpec, ExecutionPayloadBid, Fork, }; /// Transform a `Fulu` state into a `Gloas` state. diff --git a/consensus/types/Cargo.toml b/consensus/types/Cargo.toml index 559a181948..78c6f871cb 100644 --- a/consensus/types/Cargo.toml +++ b/consensus/types/Cargo.toml @@ -65,6 +65,7 @@ test_random_derive = { path = "../../common/test_random_derive" } tracing = { workspace = true } tree_hash = { workspace = true } tree_hash_derive = { workspace = true } +typenum = { workspace = true } [dev-dependencies] beacon_chain = { workspace = true } diff --git a/consensus/types/benches/benches.rs b/consensus/types/benches/benches.rs index 814001d966..397c33163e 100644 --- a/consensus/types/benches/benches.rs +++ b/consensus/types/benches/benches.rs @@ -1,10 +1,11 @@ use criterion::{BatchSize, BenchmarkId, Criterion, black_box, criterion_group, criterion_main}; +use fixed_bytes::FixedBytesExtended; use milhouse::List; use rayon::prelude::*; use ssz::Encode; use std::sync::Arc; use types::{ - BeaconState, Epoch, Eth1Data, EthSpec, FixedBytesExtended, Hash256, MainnetEthSpec, Validator, + BeaconState, Epoch, Eth1Data, EthSpec, Hash256, MainnetEthSpec, Validator, test_utils::generate_deterministic_keypair, }; diff --git a/consensus/types/src/attestation/indexed_payload_attestation.rs b/consensus/types/src/attestation/indexed_payload_attestation.rs index d75801c111..4de805570c 100644 --- a/consensus/types/src/attestation/indexed_payload_attestation.rs +++ b/consensus/types/src/attestation/indexed_payload_attestation.rs @@ -1,6 +1,7 @@ use crate::test_utils::TestRandom; -use crate::{EthSpec, ForkName, PayloadAttestationData, context_deserialize}; +use crate::{EthSpec, ForkName, PayloadAttestationData}; use bls::AggregateSignature; +use context_deserialize::context_deserialize; use core::slice::Iter; use serde::{Deserialize, Serialize}; use ssz_derive::{Decode, Encode}; diff --git a/consensus/types/src/attestation/payload_attestation.rs b/consensus/types/src/attestation/payload_attestation.rs index 746aa46c52..192a4a8fea 100644 --- a/consensus/types/src/attestation/payload_attestation.rs +++ b/consensus/types/src/attestation/payload_attestation.rs @@ -1,7 +1,8 @@ use crate::attestation::payload_attestation_data::PayloadAttestationData; use crate::test_utils::TestRandom; -use crate::{EthSpec, ForkName, context_deserialize}; +use crate::{EthSpec, ForkName}; use bls::AggregateSignature; +use context_deserialize::context_deserialize; use educe::Educe; use serde::{Deserialize, Serialize}; use ssz::BitList; diff --git a/consensus/types/src/attestation/payload_attestation_data.rs b/consensus/types/src/attestation/payload_attestation_data.rs index 46ae5bf221..58d36fd01d 100644 --- a/consensus/types/src/attestation/payload_attestation_data.rs +++ b/consensus/types/src/attestation/payload_attestation_data.rs @@ -1,5 +1,6 @@ use crate::test_utils::TestRandom; -use crate::{ForkName, Hash256, SignedRoot, Slot, context_deserialize}; +use crate::{ForkName, Hash256, SignedRoot, Slot}; +use context_deserialize::context_deserialize; use serde::{Deserialize, Serialize}; use ssz_derive::{Decode, Encode}; use test_random_derive::TestRandom; diff --git a/consensus/types/src/attestation/payload_attestation_message.rs b/consensus/types/src/attestation/payload_attestation_message.rs index 24744114a2..82e2137b09 100644 --- a/consensus/types/src/attestation/payload_attestation_message.rs +++ b/consensus/types/src/attestation/payload_attestation_message.rs @@ -1,7 +1,8 @@ +use crate::ForkName; use crate::attestation::payload_attestation_data::PayloadAttestationData; use crate::test_utils::TestRandom; -use crate::{ForkName, context_deserialize}; use bls::Signature; +use context_deserialize::context_deserialize; use serde::{Deserialize, Serialize}; use ssz_derive::{Decode, Encode}; use test_random_derive::TestRandom; diff --git a/consensus/types/src/block/beacon_block.rs b/consensus/types/src/block/beacon_block.rs index c42ed5fa07..bee3cdb274 100644 --- a/consensus/types/src/block/beacon_block.rs +++ b/consensus/types/src/block/beacon_block.rs @@ -7,11 +7,12 @@ use fixed_bytes::FixedBytesExtended; use serde::{Deserialize, Deserializer, Serialize}; use ssz::{Decode, DecodeError}; use ssz_derive::{Decode, Encode}; -use ssz_types::{BitList, BitVector, FixedVector, VariableList, typenum::Unsigned}; +use ssz_types::{BitList, BitVector, FixedVector, VariableList}; use superstruct::superstruct; use test_random_derive::TestRandom; use tree_hash::TreeHash; use tree_hash_derive::TreeHash; +use typenum::Unsigned; use crate::{ SignedExecutionPayloadBid, diff --git a/consensus/types/src/builder/builder_pending_payment.rs b/consensus/types/src/builder/builder_pending_payment.rs index 7241419ec9..0f1b68ad97 100644 --- a/consensus/types/src/builder/builder_pending_payment.rs +++ b/consensus/types/src/builder/builder_pending_payment.rs @@ -1,5 +1,6 @@ use crate::test_utils::TestRandom; -use crate::{BuilderPendingWithdrawal, ForkName, context_deserialize}; +use crate::{BuilderPendingWithdrawal, ForkName}; +use context_deserialize::context_deserialize; use serde::{Deserialize, Serialize}; use ssz_derive::{Decode, Encode}; use test_random_derive::TestRandom; diff --git a/consensus/types/src/builder/builder_pending_withdrawal.rs b/consensus/types/src/builder/builder_pending_withdrawal.rs index 9c82d5a64a..436d331c00 100644 --- a/consensus/types/src/builder/builder_pending_withdrawal.rs +++ b/consensus/types/src/builder/builder_pending_withdrawal.rs @@ -1,5 +1,6 @@ use crate::test_utils::TestRandom; -use crate::{Address, Epoch, ForkName, context_deserialize}; +use crate::{Address, Epoch, ForkName}; +use context_deserialize::context_deserialize; use serde::{Deserialize, Serialize}; use ssz_derive::{Decode, Encode}; use test_random_derive::TestRandom; diff --git a/consensus/types/src/core/eth_spec.rs b/consensus/types/src/core/eth_spec.rs index dbae48c0b6..74795fdfc3 100644 --- a/consensus/types/src/core/eth_spec.rs +++ b/consensus/types/src/core/eth_spec.rs @@ -5,7 +5,7 @@ use std::{ use safe_arith::SafeArith; use serde::{Deserialize, Serialize}; -use ssz_types::typenum::{ +use typenum::{ U0, U1, U2, U4, U8, U16, U17, U32, U64, U128, U256, U512, U625, U1024, U2048, U4096, U8192, U65536, U131072, U262144, U1048576, U16777216, U33554432, U134217728, U1073741824, U1099511627776, UInt, Unsigned, bit::B0, @@ -665,7 +665,7 @@ impl EthSpec for GnosisEthSpec { #[cfg(test)] mod test { use crate::{EthSpec, GnosisEthSpec, MainnetEthSpec, MinimalEthSpec}; - use ssz_types::typenum::Unsigned; + use typenum::Unsigned; fn assert_valid_spec() { let spec = E::default_spec(); diff --git a/consensus/types/src/core/preset.rs b/consensus/types/src/core/preset.rs index b436fafd3a..75d2d8df6b 100644 --- a/consensus/types/src/core/preset.rs +++ b/consensus/types/src/core/preset.rs @@ -1,5 +1,5 @@ use serde::{Deserialize, Serialize}; -use ssz_types::typenum::Unsigned; +use typenum::Unsigned; use crate::core::{ChainSpec, Epoch, EthSpec}; diff --git a/consensus/types/src/deposit/deposit.rs b/consensus/types/src/deposit/deposit.rs index 67f8572def..0b08bd6509 100644 --- a/consensus/types/src/deposit/deposit.rs +++ b/consensus/types/src/deposit/deposit.rs @@ -1,9 +1,10 @@ use context_deserialize::context_deserialize; use serde::{Deserialize, Serialize}; use ssz_derive::{Decode, Encode}; -use ssz_types::{FixedVector, typenum::U33}; +use ssz_types::FixedVector; use test_random_derive::TestRandom; use tree_hash_derive::TreeHash; +use typenum::U33; use crate::{core::Hash256, deposit::DepositData, fork::ForkName, test_utils::TestRandom}; diff --git a/consensus/types/src/execution/execution_payload_bid.rs b/consensus/types/src/execution/execution_payload_bid.rs index ed4712a02d..20e461334d 100644 --- a/consensus/types/src/execution/execution_payload_bid.rs +++ b/consensus/types/src/execution/execution_payload_bid.rs @@ -1,7 +1,6 @@ use crate::test_utils::TestRandom; -use crate::{ - Address, ExecutionBlockHash, ForkName, Hash256, SignedRoot, Slot, context_deserialize, -}; +use crate::{Address, ExecutionBlockHash, ForkName, Hash256, SignedRoot, Slot}; +use context_deserialize::context_deserialize; use educe::Educe; use serde::{Deserialize, Serialize}; use ssz_derive::{Decode, Encode}; diff --git a/consensus/types/src/execution/execution_payload_envelope.rs b/consensus/types/src/execution/execution_payload_envelope.rs index 9999713515..64e03cec5a 100644 --- a/consensus/types/src/execution/execution_payload_envelope.rs +++ b/consensus/types/src/execution/execution_payload_envelope.rs @@ -1,8 +1,9 @@ use crate::test_utils::TestRandom; use crate::{ EthSpec, ExecutionPayloadGloas, ExecutionRequests, ForkName, Hash256, KzgCommitments, - SignedRoot, Slot, context_deserialize, + SignedRoot, Slot, }; +use context_deserialize::context_deserialize; use educe::Educe; use serde::{Deserialize, Serialize}; use ssz_derive::{Decode, Encode}; diff --git a/consensus/types/src/execution/signed_execution_payload_bid.rs b/consensus/types/src/execution/signed_execution_payload_bid.rs index 84ac024d91..29dfd03ba0 100644 --- a/consensus/types/src/execution/signed_execution_payload_bid.rs +++ b/consensus/types/src/execution/signed_execution_payload_bid.rs @@ -1,6 +1,7 @@ -use crate::execution::execution_payload_bid::ExecutionPayloadBid; use crate::test_utils::TestRandom; -use crate::*; +use crate::{ExecutionPayloadBid, ForkName}; +use bls::Signature; +use context_deserialize::context_deserialize; use educe::Educe; use serde::{Deserialize, Serialize}; use ssz_derive::{Decode, Encode}; diff --git a/consensus/types/src/execution/signed_execution_payload_envelope.rs b/consensus/types/src/execution/signed_execution_payload_envelope.rs index bed695712a..1641041615 100644 --- a/consensus/types/src/execution/signed_execution_payload_envelope.rs +++ b/consensus/types/src/execution/signed_execution_payload_envelope.rs @@ -1,6 +1,6 @@ -use crate::execution::execution_payload_envelope::ExecutionPayloadEnvelope; use crate::test_utils::TestRandom; -use crate::*; +use crate::{EthSpec, ExecutionPayloadEnvelope}; +use bls::Signature; use educe::Educe; use serde::{Deserialize, Serialize}; use ssz_derive::{Decode, Encode}; diff --git a/consensus/types/src/fork/fork_context.rs b/consensus/types/src/fork/fork_context.rs index 615eb002c0..3407689e79 100644 --- a/consensus/types/src/fork/fork_context.rs +++ b/consensus/types/src/fork/fork_context.rs @@ -63,8 +63,7 @@ impl ForkContext { let current_epoch = current_slot.epoch(E::slots_per_epoch()); let current_fork = epoch_to_forks .values() - .filter(|&fork| fork.fork_epoch <= current_epoch) - .next_back() + .rfind(|&fork| fork.fork_epoch <= current_epoch) .cloned() .expect("should match at least genesis epoch"); diff --git a/consensus/types/src/lib.rs b/consensus/types/src/lib.rs index f1a9751cbe..5a89fcb1d4 100644 --- a/consensus/types/src/lib.rs +++ b/consensus/types/src/lib.rs @@ -175,14 +175,3 @@ pub mod application_domain { pub use crate::kzg_ext::consts::VERSIONED_HASH_VERSION_KZG; pub use crate::light_client::LightClientError as LightClientUpdateError; pub use crate::state::BeaconStateError as Error; - -pub use bls::{ - AggregatePublicKey, AggregateSignature, Error as BlsError, Keypair, PUBLIC_KEY_BYTES_LEN, - PublicKey, PublicKeyBytes, SIGNATURE_BYTES_LEN, SecretKey, Signature, SignatureBytes, - get_withdrawal_credentials, -}; -pub use context_deserialize::{ContextDeserialize, context_deserialize}; -pub use fixed_bytes::FixedBytesExtended; -pub use milhouse::{self, List, Vector}; -pub use ssz_types::{BitList, BitVector, FixedVector, VariableList, typenum, typenum::Unsigned}; -pub use superstruct::superstruct; diff --git a/consensus/types/src/light_client/light_client_update.rs b/consensus/types/src/light_client/light_client_update.rs index ed19cbcd41..cd33f6ae54 100644 --- a/consensus/types/src/light_client/light_client_update.rs +++ b/consensus/types/src/light_client/light_client_update.rs @@ -9,10 +9,10 @@ use ssz::{Decode, Encode}; use ssz_derive::Decode; use ssz_derive::Encode; use ssz_types::FixedVector; -use ssz_types::typenum::{U4, U5, U6, U7}; use superstruct::superstruct; use test_random_derive::TestRandom; use tree_hash_derive::TreeHash; +use typenum::{U4, U5, U6, U7}; use crate::{ block::SignedBlindedBeaconBlock, @@ -540,7 +540,7 @@ fn compute_sync_committee_period_at_slot( mod tests { use super::*; use crate::light_client::consts::*; - use ssz_types::typenum::Unsigned; + use typenum::Unsigned; // `ssz_tests!` can only be defined once per namespace #[cfg(test)] diff --git a/consensus/types/src/state/beacon_state.rs b/consensus/types/src/state/beacon_state.rs index 6f99a07129..c1b6f0dc0c 100644 --- a/consensus/types/src/state/beacon_state.rs +++ b/consensus/types/src/state/beacon_state.rs @@ -13,13 +13,14 @@ use safe_arith::{ArithError, SafeArith}; use serde::{Deserialize, Deserializer, Serialize}; use ssz::{Decode, DecodeError, Encode, ssz_encode}; use ssz_derive::{Decode, Encode}; -use ssz_types::{BitVector, FixedVector, typenum::Unsigned}; +use ssz_types::{BitVector, FixedVector}; use superstruct::superstruct; use swap_or_not_shuffle::compute_shuffled_index; use test_random_derive::TestRandom; use tracing::instrument; use tree_hash::TreeHash; use tree_hash_derive::TreeHash; +use typenum::Unsigned; use crate::{ BuilderPendingPayment, BuilderPendingWithdrawal, ExecutionBlockHash, ExecutionPayloadBid, diff --git a/consensus/types/src/state/iter.rs b/consensus/types/src/state/iter.rs index d761a6bd85..63f28d74c4 100644 --- a/consensus/types/src/state/iter.rs +++ b/consensus/types/src/state/iter.rs @@ -56,6 +56,7 @@ impl Iterator for BlockRootsIter<'_, E> { #[cfg(test)] mod test { use crate::*; + use fixed_bytes::FixedBytesExtended; type E = MinimalEthSpec; diff --git a/consensus/types/src/sync_committee/sync_selection_proof.rs b/consensus/types/src/sync_committee/sync_selection_proof.rs index 7efc6c4c76..723f0c06c9 100644 --- a/consensus/types/src/sync_committee/sync_selection_proof.rs +++ b/consensus/types/src/sync_committee/sync_selection_proof.rs @@ -5,7 +5,7 @@ use ethereum_hashing::hash; use safe_arith::{ArithError, SafeArith}; use serde::{Deserialize, Serialize}; use ssz::Encode; -use ssz_types::typenum::Unsigned; +use typenum::Unsigned; use crate::{ core::{ @@ -112,8 +112,9 @@ impl From for SyncSelectionProof { #[cfg(test)] mod test { use super::*; - use crate::{FixedBytesExtended, MainnetEthSpec}; + use crate::MainnetEthSpec; use eth2_interop_keypairs::keypair; + use fixed_bytes::FixedBytesExtended; #[test] fn proof_sign_and_verify() { diff --git a/consensus/types/src/sync_committee/sync_subnet_id.rs b/consensus/types/src/sync_committee/sync_subnet_id.rs index fb58146178..6cb11f6b03 100644 --- a/consensus/types/src/sync_committee/sync_subnet_id.rs +++ b/consensus/types/src/sync_committee/sync_subnet_id.rs @@ -8,7 +8,7 @@ use std::{ use safe_arith::{ArithError, SafeArith}; use serde::{Deserialize, Serialize}; -use ssz_types::typenum::Unsigned; +use typenum::Unsigned; use crate::core::{EthSpec, consts::altair::SYNC_COMMITTEE_SUBNET_COUNT}; diff --git a/consensus/types/src/test_utils/test_random/bitfield.rs b/consensus/types/src/test_utils/test_random/bitfield.rs index 3bc0d37c62..762f41eb34 100644 --- a/consensus/types/src/test_utils/test_random/bitfield.rs +++ b/consensus/types/src/test_utils/test_random/bitfield.rs @@ -1,5 +1,6 @@ use smallvec::smallvec; -use ssz_types::{BitList, BitVector, typenum::Unsigned}; +use ssz_types::{BitList, BitVector}; +use typenum::Unsigned; use crate::test_utils::TestRandom; diff --git a/consensus/types/src/test_utils/test_random/test_random.rs b/consensus/types/src/test_utils/test_random/test_random.rs index f31be97c03..101fbec51b 100644 --- a/consensus/types/src/test_utils/test_random/test_random.rs +++ b/consensus/types/src/test_utils/test_random/test_random.rs @@ -3,7 +3,8 @@ use std::{marker::PhantomData, sync::Arc}; use rand::{RngCore, SeedableRng}; use rand_xorshift::XorShiftRng; use smallvec::{SmallVec, smallvec}; -use ssz_types::{VariableList, typenum::Unsigned}; +use ssz_types::VariableList; +use typenum::Unsigned; pub fn test_random_instance() -> T { let mut rng = XorShiftRng::from_seed([0x42; 16]); diff --git a/crypto/bls/src/generic_aggregate_signature.rs b/crypto/bls/src/generic_aggregate_signature.rs index 98a634ee11..35674394a0 100644 --- a/crypto/bls/src/generic_aggregate_signature.rs +++ b/crypto/bls/src/generic_aggregate_signature.rs @@ -124,13 +124,15 @@ where /// Aggregates a signature onto `self`. pub fn add_assign(&mut self, other: &GenericSignature) { if let Some(other_point) = other.point() { - self.is_infinity = self.is_infinity && other.is_infinity; if let Some(self_point) = &mut self.point { - self_point.add_assign(other_point) + self_point.add_assign(other_point); + self.is_infinity = self.is_infinity && other.is_infinity; } else { let mut self_point = AggSig::infinity(); self_point.add_assign(other_point); - self.point = Some(self_point) + self.point = Some(self_point); + // the result is infinity, if `other` is + self.is_infinity = other.is_infinity; } } } @@ -138,13 +140,15 @@ where /// Aggregates an aggregate signature onto `self`. pub fn add_assign_aggregate(&mut self, other: &Self) { if let Some(other_point) = other.point() { - self.is_infinity = self.is_infinity && other.is_infinity; if let Some(self_point) = &mut self.point { - self_point.add_assign_aggregate(other_point) + self_point.add_assign_aggregate(other_point); + self.is_infinity = self.is_infinity && other.is_infinity; } else { let mut self_point = AggSig::infinity(); self_point.add_assign_aggregate(other_point); - self.point = Some(self_point) + self.point = Some(self_point); + // the result is infinity, if `other` is + self.is_infinity = other.is_infinity; } } } diff --git a/crypto/bls/tests/tests.rs b/crypto/bls/tests/tests.rs index 00f82bfcec..1827ea9921 100644 --- a/crypto/bls/tests/tests.rs +++ b/crypto/bls/tests/tests.rs @@ -356,6 +356,17 @@ macro_rules! test_suite { .assert_single_message_verify(true) } + #[test] + fn empty_aggregate_plus_infinity_should_be_infinity() { + let mut agg = AggregateSignature::empty(); + let infinity_sig = Signature::deserialize(&INFINITY_SIGNATURE).unwrap(); + agg.add_assign(&infinity_sig); + assert!( + agg.is_infinity(), + "is_infinity flag should be true after adding infinity to empty" + ); + } + #[test] fn deserialize_infinity_public_key() { PublicKey::deserialize(&bls::INFINITY_PUBLIC_KEY).unwrap_err(); diff --git a/database_manager/src/lib.rs b/database_manager/src/lib.rs index 6bb7531493..608400fa7e 100644 --- a/database_manager/src/lib.rs +++ b/database_manager/src/lib.rs @@ -21,7 +21,7 @@ use store::{ errors::Error, metadata::{CURRENT_SCHEMA_VERSION, SchemaVersion}, }; -use strum::{EnumString, EnumVariantNames}; +use strum::{EnumString, VariantNames}; use tracing::{info, warn}; use types::{BeaconState, EthSpec, Slot}; @@ -80,7 +80,7 @@ pub fn display_db_version( } #[derive( - Debug, PartialEq, Eq, Clone, EnumString, Deserialize, Serialize, EnumVariantNames, ValueEnum, + Debug, PartialEq, Eq, Clone, EnumString, Deserialize, Serialize, VariantNames, ValueEnum, )] pub enum InspectTarget { #[strum(serialize = "sizes")] diff --git a/lcli/Cargo.toml b/lcli/Cargo.toml index 04eb41960b..43e361b60d 100644 --- a/lcli/Cargo.toml +++ b/lcli/Cargo.toml @@ -26,6 +26,7 @@ eth2_wallet = { workspace = true } ethereum_hashing = { workspace = true } ethereum_ssz = { workspace = true } execution_layer = { workspace = true } +fixed_bytes = { workspace = true } hex = { workspace = true } lighthouse_network = { workspace = true } lighthouse_version = { workspace = true } diff --git a/lcli/src/generate_bootnode_enr.rs b/lcli/src/generate_bootnode_enr.rs index 71186904d0..620539a95f 100644 --- a/lcli/src/generate_bootnode_enr.rs +++ b/lcli/src/generate_bootnode_enr.rs @@ -1,4 +1,5 @@ use clap::ArgMatches; +use fixed_bytes::FixedBytesExtended; use lighthouse_network::{ NETWORK_KEY_FILENAME, NetworkConfig, discovery::{CombinedKey, ENR_FILENAME, build_enr}, @@ -9,7 +10,7 @@ use std::io::Write; use std::path::PathBuf; use std::{fs, net::Ipv4Addr}; use std::{fs::File, num::NonZeroU16}; -use types::{ChainSpec, EnrForkId, Epoch, EthSpec, FixedBytesExtended, Hash256}; +use types::{ChainSpec, EnrForkId, Epoch, EthSpec, Hash256}; pub fn run(matches: &ArgMatches, spec: &ChainSpec) -> Result<(), String> { let ip: Ipv4Addr = clap_utils::parse_required(matches, "ip")?; diff --git a/lcli/src/http_sync.rs b/lcli/src/http_sync.rs index dd941cda74..6a0eb2a0e1 100644 --- a/lcli/src/http_sync.rs +++ b/lcli/src/http_sync.rs @@ -132,7 +132,6 @@ async fn get_block_from_source( let (kzg_proofs, blobs): (Vec<_>, Vec<_>) = blobs_from_source .iter() - .cloned() .map(|sidecar| (sidecar.kzg_proof, sidecar.blob.clone())) .unzip(); diff --git a/lighthouse/tests/account_manager.rs b/lighthouse/tests/account_manager.rs index 0b945bcb2d..9bfcae85e5 100644 --- a/lighthouse/tests/account_manager.rs +++ b/lighthouse/tests/account_manager.rs @@ -18,6 +18,7 @@ use account_utils::{ eth2_keystore::KeystoreBuilder, validator_definitions::{SigningDefinition, ValidatorDefinition, ValidatorDefinitions}, }; +use bls::{Keypair, PublicKey}; use slashing_protection::{SLASHING_PROTECTION_FILENAME, SlashingDatabase}; use std::env; use std::fs::{self, File}; @@ -26,7 +27,6 @@ use std::path::{Path, PathBuf}; use std::process::{Child, Command, Output, Stdio}; use std::str::from_utf8; use tempfile::{TempDir, tempdir}; -use types::{Keypair, PublicKey}; use validator_dir::ValidatorDir; use zeroize::Zeroizing; diff --git a/lighthouse/tests/validator_manager.rs b/lighthouse/tests/validator_manager.rs index 99afa7b682..d6d720a561 100644 --- a/lighthouse/tests/validator_manager.rs +++ b/lighthouse/tests/validator_manager.rs @@ -1,3 +1,4 @@ +use bls::PublicKeyBytes; use eth2::SensitiveUrl; use serde::de::DeserializeOwned; use std::fs; diff --git a/scripts/tests/genesis-sync-config-electra.yaml b/scripts/tests/genesis-sync-config-electra.yaml index 153f754c94..1d1ed4d315 100644 --- a/scripts/tests/genesis-sync-config-electra.yaml +++ b/scripts/tests/genesis-sync-config-electra.yaml @@ -6,15 +6,14 @@ participants: # nodes without validators, used for testing sync. - cl_type: lighthouse cl_image: lighthouse:local - supernode: true # no supernode in Electra, this is for future proof validator_count: 0 - cl_type: lighthouse cl_image: lighthouse:local - supernode: false validator_count: 0 network_params: seconds_per_slot: 6 electra_fork_epoch: 0 + fulu_fork_epoch: 100000 # a really big number so this test stays in electra preset: "minimal" additional_services: - tx_fuzz diff --git a/scripts/tests/genesis-sync-config-fulu.yaml b/scripts/tests/genesis-sync-config-fulu.yaml index 98dc8751d6..6d2c2647a9 100644 --- a/scripts/tests/genesis-sync-config-fulu.yaml +++ b/scripts/tests/genesis-sync-config-fulu.yaml @@ -21,8 +21,7 @@ participants: validator_count: 0 network_params: seconds_per_slot: 6 - electra_fork_epoch: 0 - fulu_fork_epoch: 1 + fulu_fork_epoch: 0 preset: "minimal" additional_services: - tx_fuzz diff --git a/scripts/tests/network_params.yaml b/scripts/tests/network_params.yaml index 0fda1aa34b..35916ac1e4 100644 --- a/scripts/tests/network_params.yaml +++ b/scripts/tests/network_params.yaml @@ -6,9 +6,10 @@ participants: cl_image: lighthouse:local cl_extra_params: - --target-peers=3 + supernode: true count: 4 network_params: - electra_fork_epoch: 0 + fulu_fork_epoch: 0 seconds_per_slot: 3 num_validator_keys_per_node: 20 global_log_level: debug diff --git a/slasher/Cargo.toml b/slasher/Cargo.toml index 94d048ef72..a068b2e885 100644 --- a/slasher/Cargo.toml +++ b/slasher/Cargo.toml @@ -14,11 +14,13 @@ portable = ["types/portable"] [dependencies] bincode = { workspace = true } +bls = { workspace = true } byteorder = { workspace = true } educe = { workspace = true } ethereum_ssz = { workspace = true } ethereum_ssz_derive = { workspace = true } filesystem = { workspace = true } +fixed_bytes = { workspace = true } flate2 = { version = "1.0.14", features = ["zlib"], default-features = false } lmdb-rkv = { git = "https://github.com/sigp/lmdb-rs", rev = "f33845c6469b94265319aac0ed5085597862c27e", optional = true } lmdb-rkv-sys = { git = "https://github.com/sigp/lmdb-rs", rev = "f33845c6469b94265319aac0ed5085597862c27e", optional = true } @@ -38,6 +40,7 @@ strum = { workspace = true } tracing = { workspace = true } tree_hash = { workspace = true } tree_hash_derive = { workspace = true } +typenum = { workspace = true } types = { workspace = true } [dev-dependencies] diff --git a/slasher/src/attester_record.rs b/slasher/src/attester_record.rs index 67145193ac..db326a9d80 100644 --- a/slasher/src/attester_record.rs +++ b/slasher/src/attester_record.rs @@ -1,5 +1,7 @@ use crate::{Error, database::IndexedAttestationId}; +use bls::AggregateSignature; use ssz_derive::{Decode, Encode}; +use ssz_types::VariableList; use std::borrow::Cow; use std::sync::{ Arc, @@ -7,7 +9,7 @@ use std::sync::{ }; use tree_hash::TreeHash as _; use tree_hash_derive::TreeHash; -use types::{AggregateSignature, EthSpec, Hash256, IndexedAttestation, VariableList}; +use types::{EthSpec, Hash256, IndexedAttestation}; #[derive(Debug, Clone, Copy)] pub struct AttesterRecord { diff --git a/slasher/src/config.rs b/slasher/src/config.rs index a8194bed49..144016efd2 100644 --- a/slasher/src/config.rs +++ b/slasher/src/config.rs @@ -2,7 +2,7 @@ use crate::Error; use serde::{Deserialize, Serialize}; use std::num::NonZeroUsize; use std::path::PathBuf; -use strum::{Display, EnumString, EnumVariantNames}; +use strum::{Display, EnumString, VariantNames}; use types::non_zero_usize::new_non_zero_usize; use types::{Epoch, EthSpec, IndexedAttestation}; @@ -59,7 +59,7 @@ pub struct DiskConfig { } #[derive( - Debug, Clone, Copy, PartialEq, Serialize, Deserialize, Display, EnumString, EnumVariantNames, + Debug, Clone, Copy, PartialEq, Serialize, Deserialize, Display, EnumString, VariantNames, )] #[strum(serialize_all = "lowercase")] pub enum DatabaseBackend { diff --git a/slasher/src/database.rs b/slasher/src/database.rs index 2df2849612..80d073a81c 100644 --- a/slasher/src/database.rs +++ b/slasher/src/database.rs @@ -7,6 +7,7 @@ use crate::{ AttesterRecord, AttesterSlashingStatus, CompactAttesterRecord, Config, Database, Error, ProposerSlashingStatus, metrics, }; +use bls::AggregateSignature; use byteorder::{BigEndian, ByteOrder}; use interface::{Environment, OpenDatabases, RwTransaction}; use lru::LruCache; @@ -14,15 +15,16 @@ use parking_lot::Mutex; use serde::de::DeserializeOwned; use ssz::{Decode, Encode}; use ssz_derive::{Decode, Encode}; +use ssz_types::VariableList; use std::borrow::{Borrow, Cow}; use std::marker::PhantomData; use std::sync::Arc; use tracing::info; use tree_hash::TreeHash; use types::{ - AggregateSignature, AttestationData, ChainSpec, Epoch, EthSpec, Hash256, IndexedAttestation, + AttestationData, ChainSpec, Epoch, EthSpec, Hash256, IndexedAttestation, IndexedAttestationBase, IndexedAttestationElectra, ProposerSlashing, SignedBeaconBlockHeader, - Slot, VariableList, + Slot, }; /// Current database schema version, to check compatibility of on-disk DB with software. @@ -860,7 +862,8 @@ impl SlasherDB { #[cfg(test)] mod test { use super::*; - use types::{Checkpoint, ForkName, MainnetEthSpec, Unsigned}; + use typenum::Unsigned; + use types::{Checkpoint, ForkName, MainnetEthSpec}; type E = MainnetEthSpec; diff --git a/slasher/src/test_utils.rs b/slasher/src/test_utils.rs index bbbadac761..20d1ee9217 100644 --- a/slasher/src/test_utils.rs +++ b/slasher/src/test_utils.rs @@ -1,10 +1,11 @@ +use bls::{AggregateSignature, Signature}; +use fixed_bytes::FixedBytesExtended; use std::collections::HashSet; use std::sync::Arc; use types::{ - AggregateSignature, AttestationData, AttesterSlashing, AttesterSlashingBase, - AttesterSlashingElectra, BeaconBlockHeader, ChainSpec, Checkpoint, Epoch, EthSpec, - FixedBytesExtended, Hash256, IndexedAttestation, MainnetEthSpec, Signature, - SignedBeaconBlockHeader, Slot, + AttestationData, AttesterSlashing, AttesterSlashingBase, AttesterSlashingElectra, + BeaconBlockHeader, ChainSpec, Checkpoint, Epoch, EthSpec, Hash256, IndexedAttestation, + MainnetEthSpec, SignedBeaconBlockHeader, Slot, indexed_attestation::{IndexedAttestationBase, IndexedAttestationElectra}, }; diff --git a/testing/ef_tests/Cargo.toml b/testing/ef_tests/Cargo.toml index 581785e2a9..cef201ee91 100644 --- a/testing/ef_tests/Cargo.toml +++ b/testing/ef_tests/Cargo.toml @@ -27,14 +27,17 @@ fs2 = { workspace = true } hex = { workspace = true } kzg = { workspace = true } logging = { workspace = true } +milhouse = { workspace = true } 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 } swap_or_not_shuffle = { workspace = true } tree_hash = { workspace = true } tree_hash_derive = { workspace = true } +typenum = { workspace = true } types = { workspace = true } diff --git a/testing/ef_tests/src/cases/merkle_proof_validity.rs b/testing/ef_tests/src/cases/merkle_proof_validity.rs index 1103d2fe82..52f5333df1 100644 --- a/testing/ef_tests/src/cases/merkle_proof_validity.rs +++ b/testing/ef_tests/src/cases/merkle_proof_validity.rs @@ -1,11 +1,12 @@ use super::*; use crate::decode::{ssz_decode_file, ssz_decode_state, yaml_decode_file}; use serde::Deserialize; +use ssz_types::FixedVector; use tree_hash::Hash256; +use typenum::Unsigned; use types::{ BeaconBlockBody, BeaconBlockBodyCapella, BeaconBlockBodyDeneb, BeaconBlockBodyElectra, - BeaconBlockBodyFulu, BeaconBlockBodyGloas, BeaconState, FixedVector, FullPayload, Unsigned, - light_client_update, + BeaconBlockBodyFulu, BeaconBlockBodyGloas, BeaconState, FullPayload, light_client_update, }; #[derive(Debug, Clone, Deserialize)] diff --git a/testing/ef_tests/src/cases/ssz_generic.rs b/testing/ef_tests/src/cases/ssz_generic.rs index 8742f8a140..1dd37a22ee 100644 --- a/testing/ef_tests/src/cases/ssz_generic.rs +++ b/testing/ef_tests/src/cases/ssz_generic.rs @@ -5,12 +5,14 @@ use crate::cases::common::{DecimalU128, DecimalU256, SszStaticType}; use crate::cases::ssz_static::{check_serialization, check_tree_hash}; use crate::decode::{context_yaml_decode_file, log_file_access, snappy_decode_file}; use context_deserialize::{ContextDeserialize, context_deserialize}; +use milhouse::Vector; use serde::{Deserialize, Deserializer, de::Error as SerdeError}; use ssz_derive::{Decode, Encode}; +use ssz_types::{BitList, BitVector, FixedVector, VariableList}; use tree_hash::TreeHash; use tree_hash_derive::TreeHash; -use types::typenum::*; -use types::{BitList, BitVector, FixedVector, ForkName, VariableList, Vector}; +use typenum::*; +use types::ForkName; #[derive(Debug, Clone, Deserialize)] #[context_deserialize(ForkName)] diff --git a/testing/ef_tests/tests/tests.rs b/testing/ef_tests/tests/tests.rs index 089e4464cd..0cec69c97e 100644 --- a/testing/ef_tests/tests/tests.rs +++ b/testing/ef_tests/tests/tests.rs @@ -1,6 +1,7 @@ #![cfg(feature = "ef_tests")] use ef_tests::*; +use typenum::Unsigned; use types::*; // Check that the hand-computed multiplications on EthSpec are correctly computed. diff --git a/testing/execution_engine_integration/Cargo.toml b/testing/execution_engine_integration/Cargo.toml index 74bf43e3ae..034b6c5c8a 100644 --- a/testing/execution_engine_integration/Cargo.toml +++ b/testing/execution_engine_integration/Cargo.toml @@ -7,14 +7,16 @@ edition = { workspace = true } portable = ["types/portable"] [dependencies] -alloy-network = "1.0" +alloy-network = { workspace = true } alloy-primitives = { workspace = true } -alloy-provider = "1.0" +alloy-provider = { workspace = true } alloy-rpc-types-eth = { workspace = true } -alloy-signer-local = "1.0" +alloy-signer-local = { workspace = true } async-channel = { workspace = true } +bls = { workspace = true } deposit_contract = { workspace = true } execution_layer = { workspace = true } +fixed_bytes = { workspace = true } fork_choice = { workspace = true } futures = { workspace = true } hex = { workspace = true } @@ -26,4 +28,5 @@ serde_json = { workspace = true } task_executor = { workspace = true } tempfile = { workspace = true } tokio = { workspace = true } +typenum = { workspace = true } types = { workspace = true } diff --git a/testing/execution_engine_integration/src/test_rig.rs b/testing/execution_engine_integration/src/test_rig.rs index 57501c6ee2..8413da4c5e 100644 --- a/testing/execution_engine_integration/src/test_rig.rs +++ b/testing/execution_engine_integration/src/test_rig.rs @@ -6,11 +6,13 @@ use alloy_network::{EthereumWallet, TransactionBuilder}; use alloy_primitives::Address as AlloyAddress; use alloy_provider::{Provider, ProviderBuilder}; use alloy_signer_local::PrivateKeySigner; +use bls::PublicKeyBytes; use execution_layer::test_utils::DEFAULT_GAS_LIMIT; use execution_layer::{ BlockProposalContentsType, BuilderParams, ChainHealth, ExecutionLayer, PayloadAttributes, PayloadParameters, PayloadStatus, }; +use fixed_bytes::FixedBytesExtended; use fork_choice::ForkchoiceUpdateParameters; use reqwest::{Client, header::CONTENT_TYPE}; use sensitive_url::SensitiveUrl; @@ -22,8 +24,9 @@ use tokio::time::sleep; use types::payload::BlockProductionVersion; use types::{ Address, ChainSpec, EthSpec, ExecutionBlockHash, ExecutionPayload, ExecutionPayloadHeader, - FixedBytesExtended, ForkName, Hash256, MainnetEthSpec, PublicKeyBytes, Slot, Uint256, + ForkName, Hash256, MainnetEthSpec, Slot, Uint256, }; + const EXECUTION_ENGINE_START_TIMEOUT: Duration = Duration::from_secs(60); const TEST_FORK: ForkName = ForkName::Capella; diff --git a/testing/execution_engine_integration/src/transactions.rs b/testing/execution_engine_integration/src/transactions.rs index fe36a1bf67..8cd63ce307 100644 --- a/testing/execution_engine_integration/src/transactions.rs +++ b/testing/execution_engine_integration/src/transactions.rs @@ -1,8 +1,10 @@ use alloy_network::TransactionBuilder; use alloy_primitives::{Address, U256}; use alloy_rpc_types_eth::{AccessList, TransactionRequest}; +use bls::{Keypair, Signature}; use deposit_contract::{BYTECODE, CONTRACT_DEPLOY_GAS, DEPOSIT_GAS, encode_eth1_tx_data}; -use types::{DepositData, EthSpec, FixedBytesExtended, Hash256, Keypair, Signature}; +use fixed_bytes::FixedBytesExtended; +use types::{DepositData, EthSpec, Hash256}; /// Hardcoded deposit contract address based on sender address and nonce pub const DEPOSIT_CONTRACT_ADDRESS: &str = "64f43BEc7F86526686C931d65362bB8698872F90"; diff --git a/testing/simulator/Cargo.toml b/testing/simulator/Cargo.toml index 54035f2e82..a1b1b6f95d 100644 --- a/testing/simulator/Cargo.toml +++ b/testing/simulator/Cargo.toml @@ -20,4 +20,5 @@ serde_json = { workspace = true } tokio = { workspace = true } tracing = { workspace = true } tracing-subscriber = { workspace = true } +typenum = { workspace = true } types = { workspace = true } diff --git a/testing/simulator/src/checks.rs b/testing/simulator/src/checks.rs index 1240785121..35200692c3 100644 --- a/testing/simulator/src/checks.rs +++ b/testing/simulator/src/checks.rs @@ -1,7 +1,8 @@ use crate::local_network::LocalNetwork; use node_test_rig::eth2::types::{BlockId, FinalityCheckpointsData, StateId}; use std::time::Duration; -use types::{Epoch, EthSpec, ExecPayload, ExecutionBlockHash, Slot, Unsigned}; +use typenum::Unsigned; +use types::{Epoch, EthSpec, ExecPayload, ExecutionBlockHash, Slot}; /// Checks that all of the validators have on-boarded by the start of the second eth1 voting /// period. diff --git a/testing/state_transition_vectors/Cargo.toml b/testing/state_transition_vectors/Cargo.toml index 66376f0a51..437aa539f4 100644 --- a/testing/state_transition_vectors/Cargo.toml +++ b/testing/state_transition_vectors/Cargo.toml @@ -10,7 +10,9 @@ portable = ["beacon_chain/portable"] [dependencies] beacon_chain = { workspace = true } +bls = { workspace = true } ethereum_ssz = { workspace = true } +fixed_bytes = { workspace = true } state_processing = { workspace = true } tokio = { workspace = true } types = { workspace = true } diff --git a/testing/state_transition_vectors/src/main.rs b/testing/state_transition_vectors/src/main.rs index 4a829b6803..80c30489b7 100644 --- a/testing/state_transition_vectors/src/main.rs +++ b/testing/state_transition_vectors/src/main.rs @@ -3,6 +3,8 @@ mod macros; mod exit; use beacon_chain::test_utils::{BeaconChainHarness, EphemeralHarnessType}; +use bls::Keypair; +use fixed_bytes::FixedBytesExtended; use ssz::Encode; use std::env; use std::fs::{self, File}; @@ -10,10 +12,8 @@ use std::io::Write; use std::path::{Path, PathBuf}; use std::process::exit; use std::sync::LazyLock; -use types::{ - BeaconState, EthSpec, Keypair, SignedBeaconBlock, test_utils::generate_deterministic_keypairs, -}; -use types::{FixedBytesExtended, Hash256, MainnetEthSpec, Slot}; +use types::{BeaconState, EthSpec, SignedBeaconBlock, test_utils::generate_deterministic_keypairs}; +use types::{Hash256, MainnetEthSpec, Slot}; type E = MainnetEthSpec; diff --git a/testing/web3signer_tests/Cargo.toml b/testing/web3signer_tests/Cargo.toml index b4637b4030..3ef2e0f7f7 100644 --- a/testing/web3signer_tests/Cargo.toml +++ b/testing/web3signer_tests/Cargo.toml @@ -9,10 +9,12 @@ edition = { workspace = true } [dev-dependencies] account_utils = { workspace = true } async-channel = { workspace = true } +bls = { workspace = true } environment = { workspace = true } eth2 = { workspace = true } eth2_keystore = { workspace = true } eth2_network_config = { workspace = true } +fixed_bytes = { workspace = true } futures = { workspace = true } initialized_validators = { workspace = true } lighthouse_validator_store = { workspace = true } @@ -24,6 +26,7 @@ serde_json = { workspace = true } serde_yaml = { workspace = true } slashing_protection = { workspace = true } slot_clock = { workspace = true } +ssz_types = { workspace = true } task_executor = { workspace = true } tempfile = { workspace = true } tokio = { workspace = true } diff --git a/testing/web3signer_tests/src/lib.rs b/testing/web3signer_tests/src/lib.rs index 15ec745e3f..541f9b2b4a 100644 --- a/testing/web3signer_tests/src/lib.rs +++ b/testing/web3signer_tests/src/lib.rs @@ -20,9 +20,11 @@ mod tests { use account_utils::validator_definitions::{ SigningDefinition, ValidatorDefinition, ValidatorDefinitions, Web3SignerDefinition, }; + use bls::{AggregateSignature, Keypair, PublicKeyBytes, SecretKey, Signature}; use eth2::types::FullBlockContents; use eth2_keystore::KeystoreBuilder; use eth2_network_config::Eth2NetworkConfig; + use fixed_bytes::FixedBytesExtended; use initialized_validators::{ InitializedValidators, load_pem_certificate, load_pkcs12_identity, }; @@ -32,6 +34,7 @@ mod tests { use serde::Serialize; use slashing_protection::{SLASHING_PROTECTION_FILENAME, SlashingDatabase}; use slot_clock::{SlotClock, TestingSlotClock}; + use ssz_types::BitList; use std::env; use std::fmt::Debug; use std::fs::{self, File}; diff --git a/validator_client/beacon_node_fallback/Cargo.toml b/validator_client/beacon_node_fallback/Cargo.toml index 5fe2af4cb0..481aece48b 100644 --- a/validator_client/beacon_node_fallback/Cargo.toml +++ b/validator_client/beacon_node_fallback/Cargo.toml @@ -9,6 +9,7 @@ name = "beacon_node_fallback" path = "src/lib.rs" [dependencies] +bls = { workspace = true } clap = { workspace = true } eth2 = { workspace = true } futures = { workspace = true } diff --git a/validator_client/beacon_node_fallback/src/lib.rs b/validator_client/beacon_node_fallback/src/lib.rs index 0f13d8c8b7..2d75df2fa3 100644 --- a/validator_client/beacon_node_fallback/src/lib.rs +++ b/validator_client/beacon_node_fallback/src/lib.rs @@ -20,7 +20,7 @@ use std::future::Future; use std::sync::Arc; use std::time::{Duration, Instant}; use std::vec::Vec; -use strum::EnumVariantNames; +use strum::VariantNames; use task_executor::TaskExecutor; use tokio::{sync::RwLock, time::sleep}; use tracing::{debug, error, warn}; @@ -752,7 +752,7 @@ async fn sort_nodes_by_health(nodes: &mut Vec) { } /// Serves as a cue for `BeaconNodeFallback` to tell which requests need to be broadcasted. -#[derive(Clone, Copy, Debug, PartialEq, Deserialize, Serialize, EnumVariantNames, ValueEnum)] +#[derive(Clone, Copy, Debug, PartialEq, Deserialize, Serialize, VariantNames, ValueEnum)] #[strum(serialize_all = "kebab-case")] pub enum ApiTopic { None, @@ -773,12 +773,13 @@ impl ApiTopic { mod tests { use super::*; use crate::beacon_node_health::BeaconNodeHealthTier; + use bls::Signature; use eth2::SensitiveUrl; use eth2::Timeouts; use slot_clock::TestingSlotClock; use strum::VariantNames; use types::{BeaconBlockDeneb, MainnetEthSpec, Slot}; - use types::{EmptyBlock, Signature, SignedBeaconBlockDeneb, SignedBlindedBeaconBlock}; + use types::{EmptyBlock, SignedBeaconBlockDeneb, SignedBlindedBeaconBlock}; use validator_test_rig::mock_beacon_node::MockBeaconNode; type E = MainnetEthSpec; diff --git a/validator_client/doppelganger_service/Cargo.toml b/validator_client/doppelganger_service/Cargo.toml index e5b183570d..66b27eb39d 100644 --- a/validator_client/doppelganger_service/Cargo.toml +++ b/validator_client/doppelganger_service/Cargo.toml @@ -6,6 +6,7 @@ authors = ["Sigma Prime "] [dependencies] beacon_node_fallback = { workspace = true } +bls = { workspace = true } environment = { workspace = true } eth2 = { workspace = true } logging = { workspace = true } diff --git a/validator_client/doppelganger_service/src/lib.rs b/validator_client/doppelganger_service/src/lib.rs index b0ed78e996..600ae82c54 100644 --- a/validator_client/doppelganger_service/src/lib.rs +++ b/validator_client/doppelganger_service/src/lib.rs @@ -30,6 +30,7 @@ //! Doppelganger protection is a best-effort, last-line-of-defence mitigation. Do not rely upon it. use beacon_node_fallback::BeaconNodeFallback; +use bls::PublicKeyBytes; use environment::RuntimeContext; use eth2::types::LivenessResponseData; use logging::crit; @@ -41,7 +42,7 @@ use std::sync::Arc; use task_executor::ShutdownReason; use tokio::time::sleep; use tracing::{error, info}; -use types::{Epoch, EthSpec, PublicKeyBytes, Slot}; +use types::{Epoch, EthSpec, Slot}; use validator_store::{DoppelgangerStatus, ValidatorStore}; struct LivenessResponses { diff --git a/validator_client/http_api/Cargo.toml b/validator_client/http_api/Cargo.toml index 588aa2ca93..2bd57867ac 100644 --- a/validator_client/http_api/Cargo.toml +++ b/validator_client/http_api/Cargo.toml @@ -16,10 +16,11 @@ deposit_contract = { workspace = true } directory = { workspace = true } dirs = { workspace = true } doppelganger_service = { workspace = true } -eth2 = { workspace = true } +eth2 = { workspace = true, features = ["lighthouse"] } eth2_keystore = { workspace = true } ethereum_serde_utils = { workspace = true } filesystem = { workspace = true } +fixed_bytes = { workspace = true } graffiti_file = { workspace = true } health_metrics = { workspace = true } initialized_validators = { workspace = true } @@ -41,6 +42,7 @@ tempfile = { workspace = true } tokio = { workspace = true } tokio-stream = { workspace = true } tracing = { workspace = true } +typenum = { workspace = true } types = { workspace = true } url = { workspace = true } validator_dir = { workspace = true } @@ -54,3 +56,4 @@ zeroize = { workspace = true } futures = { workspace = true } itertools = { workspace = true } rand = { workspace = true, features = ["small_rng"] } +ssz_types = { workspace = true } diff --git a/validator_client/http_api/src/keystores.rs b/validator_client/http_api/src/keystores.rs index c0f918f9bb..18accf0d5a 100644 --- a/validator_client/http_api/src/keystores.rs +++ b/validator_client/http_api/src/keystores.rs @@ -1,5 +1,6 @@ //! Implementation of the standard keystore management API. use account_utils::validator_definitions::PasswordStorage; +use bls::PublicKeyBytes; use eth2::lighthouse_vc::{ std_types::{ DeleteKeystoreStatus, DeleteKeystoresRequest, DeleteKeystoresResponse, @@ -18,7 +19,7 @@ use std::sync::Arc; use task_executor::TaskExecutor; use tokio::runtime::Handle; use tracing::{info, warn}; -use types::{EthSpec, PublicKeyBytes}; +use types::EthSpec; use validator_dir::{Builder as ValidatorDirBuilder, keystore_password_path}; use warp::Rejection; use warp_utils::reject::{custom_bad_request, custom_server_error}; diff --git a/validator_client/http_api/src/lib.rs b/validator_client/http_api/src/lib.rs index 4494fca957..a35b4ec6c6 100644 --- a/validator_client/http_api/src/lib.rs +++ b/validator_client/http_api/src/lib.rs @@ -22,6 +22,7 @@ use account_utils::{ }; pub use api_secret::ApiSecret; use beacon_node_fallback::CandidateInfo; +use bls::{PublicKey, PublicKeyBytes}; use core::convert::Infallible; use create_validator::{ create_validators_mnemonic, create_validators_web3signer, get_voting_password_storage, @@ -30,8 +31,8 @@ use directory::{DEFAULT_HARDCODED_NETWORK, DEFAULT_ROOT_DIR, DEFAULT_VALIDATOR_D use eth2::lighthouse_vc::{ std_types::{AuthResponse, GetFeeRecipientResponse, GetGasLimitResponse}, types::{ - self as api_types, GenericResponse, GetGraffitiResponse, Graffiti, PublicKey, - PublicKeyBytes, SetGraffitiRequest, UpdateCandidatesRequest, UpdateCandidatesResponse, + self as api_types, GenericResponse, GetGraffitiResponse, Graffiti, SetGraffitiRequest, + UpdateCandidatesRequest, UpdateCandidatesResponse, }, }; use health_metrics::observe::Observe; diff --git a/validator_client/http_api/src/remotekeys.rs b/validator_client/http_api/src/remotekeys.rs index 5aa63baac3..987e1b8740 100644 --- a/validator_client/http_api/src/remotekeys.rs +++ b/validator_client/http_api/src/remotekeys.rs @@ -2,6 +2,7 @@ use account_utils::validator_definitions::{ SigningDefinition, ValidatorDefinition, Web3SignerDefinition, }; +use bls::PublicKeyBytes; use eth2::lighthouse_vc::std_types::{ DeleteRemotekeyStatus, DeleteRemotekeysRequest, DeleteRemotekeysResponse, ImportRemotekeyStatus, ImportRemotekeysRequest, ImportRemotekeysResponse, @@ -14,7 +15,7 @@ use std::sync::Arc; use task_executor::TaskExecutor; use tokio::runtime::Handle; use tracing::{info, warn}; -use types::{EthSpec, PublicKeyBytes}; +use types::EthSpec; use url::Url; use warp::Rejection; use warp_utils::reject::custom_server_error; diff --git a/validator_client/http_api/src/test_utils.rs b/validator_client/http_api/src/test_utils.rs index 9a8784f202..f83d9f4d52 100644 --- a/validator_client/http_api/src/test_utils.rs +++ b/validator_client/http_api/src/test_utils.rs @@ -4,6 +4,7 @@ use account_utils::validator_definitions::ValidatorDefinitions; use account_utils::{ eth2_wallet::WalletBuilder, mnemonic_from_phrase, random_mnemonic, random_password, }; +use bls::Keypair; use deposit_contract::decode_eth1_tx_data; use doppelganger_service::DoppelgangerService; use eth2::{ diff --git a/validator_client/http_api/src/tests.rs b/validator_client/http_api/src/tests.rs index b0780e7427..5cb631983c 100644 --- a/validator_client/http_api/src/tests.rs +++ b/validator_client/http_api/src/tests.rs @@ -11,6 +11,7 @@ use account_utils::{ eth2_wallet::WalletBuilder, mnemonic_from_phrase, random_mnemonic, random_password, random_password_string, validator_definitions::ValidatorDefinitions, }; +use bls::{Keypair, PublicKeyBytes}; use deposit_contract::decode_eth1_tx_data; use eth2::{ Error as ApiError, diff --git a/validator_client/http_api/src/tests/keystores.rs b/validator_client/http_api/src/tests/keystores.rs index dd2266e3f6..eeb3cd94de 100644 --- a/validator_client/http_api/src/tests/keystores.rs +++ b/validator_client/http_api/src/tests/keystores.rs @@ -1,19 +1,23 @@ use super::*; use account_utils::random_password_string; use bls::PublicKeyBytes; +use bls::{AggregateSignature, PublicKey}; use eth2::lighthouse_vc::types::UpdateFeeRecipientRequest; use eth2::lighthouse_vc::{ http_client::ValidatorClientHttpClient as HttpClient, std_types::{KeystoreJsonStr as Keystore, *}, types::Web3SignerValidatorRequest, }; +use fixed_bytes::FixedBytesExtended; use itertools::Itertools; use lighthouse_validator_store::DEFAULT_GAS_LIMIT; use rand::rngs::StdRng; use rand::{Rng, SeedableRng}; use slashing_protection::interchange::{Interchange, InterchangeMetadata}; +use ssz_types::BitList; use std::{collections::HashMap, path::Path}; use tokio::runtime::Handle; +use typenum::Unsigned; use types::{Address, attestation::AttestationBase}; use validator_store::ValidatorStore; use zeroize::Zeroizing; diff --git a/validator_client/initialized_validators/src/lib.rs b/validator_client/initialized_validators/src/lib.rs index 4d61bd4ed8..db6d03174d 100644 --- a/validator_client/initialized_validators/src/lib.rs +++ b/validator_client/initialized_validators/src/lib.rs @@ -15,6 +15,7 @@ use account_utils::{ Web3SignerDefinition, }, }; +use bls::{Keypair, PublicKey, PublicKeyBytes}; use eth2_keystore::Keystore; use lockfile::{Lockfile, LockfileError}; use metrics::set_gauge; @@ -30,7 +31,7 @@ use std::sync::Arc; use std::time::Duration; use tracing::{debug, error, info, warn}; use types::graffiti::GraffitiString; -use types::{Address, Graffiti, Keypair, PublicKey, PublicKeyBytes}; +use types::{Address, Graffiti}; use url::{ParseError, Url}; use validator_dir::Builder as ValidatorDirBuilder; use zeroize::Zeroizing; diff --git a/validator_client/lighthouse_validator_store/Cargo.toml b/validator_client/lighthouse_validator_store/Cargo.toml index 0f8220bdc9..01c7616be1 100644 --- a/validator_client/lighthouse_validator_store/Cargo.toml +++ b/validator_client/lighthouse_validator_store/Cargo.toml @@ -7,6 +7,7 @@ authors = ["Sigma Prime "] [dependencies] account_utils = { workspace = true } beacon_node_fallback = { workspace = true } +bls = { workspace = true } doppelganger_service = { workspace = true } either = { workspace = true } environment = { workspace = true } diff --git a/validator_client/lighthouse_validator_store/src/lib.rs b/validator_client/lighthouse_validator_store/src/lib.rs index dc8fb07b65..3bea21a05d 100644 --- a/validator_client/lighthouse_validator_store/src/lib.rs +++ b/validator_client/lighthouse_validator_store/src/lib.rs @@ -1,4 +1,5 @@ use account_utils::validator_definitions::{PasswordStorage, ValidatorDefinition}; +use bls::{PublicKeyBytes, Signature}; use doppelganger_service::DoppelgangerService; use eth2::types::PublishBlockRequest; use initialized_validators::InitializedValidators; @@ -19,9 +20,9 @@ use tracing::{error, info, instrument, warn}; use types::{ AbstractExecPayload, Address, AggregateAndProof, Attestation, BeaconBlock, BlindedPayload, ChainSpec, ContributionAndProof, Domain, Epoch, EthSpec, Fork, Graffiti, Hash256, - PublicKeyBytes, SelectionProof, Signature, SignedAggregateAndProof, SignedBeaconBlock, - SignedContributionAndProof, SignedRoot, SignedValidatorRegistrationData, SignedVoluntaryExit, - Slot, SyncAggregatorSelectionData, SyncCommitteeContribution, SyncCommitteeMessage, + SelectionProof, SignedAggregateAndProof, SignedBeaconBlock, SignedContributionAndProof, + SignedRoot, SignedValidatorRegistrationData, SignedVoluntaryExit, Slot, + SyncAggregatorSelectionData, SyncCommitteeContribution, SyncCommitteeMessage, SyncSelectionProof, SyncSubnetId, ValidatorRegistrationData, VoluntaryExit, graffiti::GraffitiString, }; diff --git a/validator_client/signing_method/Cargo.toml b/validator_client/signing_method/Cargo.toml index 2defd25caa..cb321c2d49 100644 --- a/validator_client/signing_method/Cargo.toml +++ b/validator_client/signing_method/Cargo.toml @@ -5,6 +5,7 @@ edition = { workspace = true } authors = ["Sigma Prime "] [dependencies] +bls = { workspace = true } eth2_keystore = { workspace = true } ethereum_serde_utils = { workspace = true } lockfile = { workspace = true } diff --git a/validator_client/signing_method/src/lib.rs b/validator_client/signing_method/src/lib.rs index 7e0f2c02f7..d0d9868952 100644 --- a/validator_client/signing_method/src/lib.rs +++ b/validator_client/signing_method/src/lib.rs @@ -3,6 +3,7 @@ //! - Via a local `Keypair`. //! - Via a remote signer (Web3Signer) +use bls::{Keypair, PublicKey, Signature}; use eth2_keystore::Keystore; use lockfile::Lockfile; use parking_lot::Mutex; diff --git a/validator_client/signing_method/src/web3signer.rs b/validator_client/signing_method/src/web3signer.rs index 99fad10303..246d9e9e09 100644 --- a/validator_client/signing_method/src/web3signer.rs +++ b/validator_client/signing_method/src/web3signer.rs @@ -1,6 +1,7 @@ //! Contains the types required to make JSON requests to Web3Signer servers. use super::Error; +use bls::{PublicKeyBytes, Signature}; use serde::{Deserialize, Serialize}; use types::*; diff --git a/validator_client/slashing_protection/Cargo.toml b/validator_client/slashing_protection/Cargo.toml index 6a778c5de3..b80da6c786 100644 --- a/validator_client/slashing_protection/Cargo.toml +++ b/validator_client/slashing_protection/Cargo.toml @@ -11,9 +11,11 @@ portable = ["types/portable"] [dependencies] arbitrary = { workspace = true, features = ["derive"] } +bls = { workspace = true } eip_3076 = { workspace = true, features = ["json"] } ethereum_serde_utils = { workspace = true } filesystem = { workspace = true } +fixed_bytes = { workspace = true } r2d2 = { workspace = true } r2d2_sqlite = "0.21.0" rusqlite = { workspace = true } diff --git a/validator_client/slashing_protection/src/attestation_tests.rs b/validator_client/slashing_protection/src/attestation_tests.rs index 37766f271b..d16c961336 100644 --- a/validator_client/slashing_protection/src/attestation_tests.rs +++ b/validator_client/slashing_protection/src/attestation_tests.rs @@ -2,7 +2,8 @@ use crate::test_utils::*; use crate::*; -use types::{AttestationData, Checkpoint, Epoch, FixedBytesExtended, Slot}; +use fixed_bytes::FixedBytesExtended; +use types::{AttestationData, Checkpoint, Epoch, Slot}; pub fn build_checkpoint(epoch_num: u64) -> Checkpoint { Checkpoint { diff --git a/validator_client/slashing_protection/src/bin/test_generator.rs b/validator_client/slashing_protection/src/bin/test_generator.rs index dfda7983f7..df1c63f37d 100644 --- a/validator_client/slashing_protection/src/bin/test_generator.rs +++ b/validator_client/slashing_protection/src/bin/test_generator.rs @@ -1,11 +1,12 @@ use eip_3076::{Interchange, InterchangeData, InterchangeMetadata, SignedAttestation, SignedBlock}; +use fixed_bytes::FixedBytesExtended; use slashing_protection::SUPPORTED_INTERCHANGE_FORMAT_VERSION; use slashing_protection::interchange_test::{MultiTestCase, TestCase}; use slashing_protection::test_utils::{DEFAULT_GENESIS_VALIDATORS_ROOT, pubkey}; use std::fs::{self, File}; use std::io::Write; use std::path::Path; -use types::{Epoch, FixedBytesExtended, Hash256, Slot}; +use types::{Epoch, Hash256, Slot}; fn metadata(genesis_validators_root: Hash256) -> InterchangeMetadata { InterchangeMetadata { diff --git a/validator_client/slashing_protection/src/block_tests.rs b/validator_client/slashing_protection/src/block_tests.rs index b3273015f4..2531f52d8c 100644 --- a/validator_client/slashing_protection/src/block_tests.rs +++ b/validator_client/slashing_protection/src/block_tests.rs @@ -2,7 +2,8 @@ use super::*; use crate::test_utils::*; -use types::{BeaconBlockHeader, FixedBytesExtended, Slot}; +use fixed_bytes::FixedBytesExtended; +use types::{BeaconBlockHeader, Slot}; pub fn block(slot: u64) -> BeaconBlockHeader { BeaconBlockHeader { diff --git a/validator_client/slashing_protection/src/extra_interchange_tests.rs b/validator_client/slashing_protection/src/extra_interchange_tests.rs index 0f88ec8b1d..18457720e4 100644 --- a/validator_client/slashing_protection/src/extra_interchange_tests.rs +++ b/validator_client/slashing_protection/src/extra_interchange_tests.rs @@ -2,8 +2,8 @@ use crate::test_utils::pubkey; use crate::*; +use fixed_bytes::FixedBytesExtended; use tempfile::tempdir; -use types::FixedBytesExtended; #[test] fn export_non_existent_key() { diff --git a/validator_client/slashing_protection/src/interchange_test.rs b/validator_client/slashing_protection/src/interchange_test.rs index ebe0105f24..0dfcda204d 100644 --- a/validator_client/slashing_protection/src/interchange_test.rs +++ b/validator_client/slashing_protection/src/interchange_test.rs @@ -2,11 +2,13 @@ use crate::{ SigningRoot, SlashingDatabase, test_utils::{DEFAULT_GENESIS_VALIDATORS_ROOT, pubkey}, }; +use bls::PublicKeyBytes; use eip_3076::{Interchange, SignedAttestation, SignedBlock}; +use fixed_bytes::FixedBytesExtended; use serde::{Deserialize, Serialize}; use std::collections::HashSet; use tempfile::tempdir; -use types::{Epoch, FixedBytesExtended, Hash256, PublicKeyBytes, Slot}; +use types::{Epoch, Hash256, Slot}; #[derive(Debug, Clone, Deserialize, Serialize)] #[cfg_attr(feature = "arbitrary-fuzz", derive(arbitrary::Arbitrary))] diff --git a/validator_client/slashing_protection/src/lib.rs b/validator_client/slashing_protection/src/lib.rs index 917d51d38b..f8580e7315 100644 --- a/validator_client/slashing_protection/src/lib.rs +++ b/validator_client/slashing_protection/src/lib.rs @@ -19,10 +19,11 @@ pub use crate::slashing_database::{ InterchangeError, InterchangeImportOutcome, SUPPORTED_INTERCHANGE_FORMAT_VERSION, SlashingDatabase, }; +use bls::PublicKeyBytes; use rusqlite::Error as SQLError; use std::fmt::Display; use std::io::{Error as IOError, ErrorKind}; -use types::{Hash256, PublicKeyBytes}; +use types::Hash256; /// The filename within the `validators` directory that contains the slashing protection DB. pub const SLASHING_PROTECTION_FILENAME: &str = "slashing_protection.sqlite"; @@ -133,7 +134,7 @@ impl Display for NotSafe { #[cfg(test)] mod test { - use types::FixedBytesExtended; + use fixed_bytes::FixedBytesExtended; use super::*; diff --git a/validator_client/slashing_protection/src/slashing_database.rs b/validator_client/slashing_protection/src/slashing_database.rs index 00677212a3..67e1234ac5 100644 --- a/validator_client/slashing_protection/src/slashing_database.rs +++ b/validator_client/slashing_protection/src/slashing_database.rs @@ -1,6 +1,7 @@ use crate::signed_attestation::InvalidAttestation; use crate::signed_block::InvalidBlock; use crate::{NotSafe, Safe, SignedAttestation, SignedBlock, SigningRoot, signing_root_from_row}; +use bls::PublicKeyBytes; use eip_3076::{ Interchange, InterchangeData, InterchangeMetadata, SignedAttestation as InterchangeAttestation, SignedBlock as InterchangeBlock, @@ -12,7 +13,7 @@ use std::fs::File; use std::path::Path; use std::time::Duration; use tracing::instrument; -use types::{AttestationData, BeaconBlockHeader, Epoch, Hash256, PublicKeyBytes, SignedRoot, Slot}; +use types::{AttestationData, BeaconBlockHeader, Epoch, Hash256, SignedRoot, Slot}; type Pool = r2d2::Pool; diff --git a/validator_client/slashing_protection/tests/migration.rs b/validator_client/slashing_protection/tests/migration.rs index 3d4ec7ea9a..14bf0d63f9 100644 --- a/validator_client/slashing_protection/tests/migration.rs +++ b/validator_client/slashing_protection/tests/migration.rs @@ -1,10 +1,11 @@ //! Tests for upgrading a previous version of the database to the latest schema. +use fixed_bytes::FixedBytesExtended; use slashing_protection::{NotSafe, SlashingDatabase}; use std::collections::HashMap; use std::fs; use std::path::{Path, PathBuf}; use tempfile::tempdir; -use types::{FixedBytesExtended, Hash256}; +use types::Hash256; fn test_data_dir() -> PathBuf { Path::new(&std::env::var("CARGO_MANIFEST_DIR").unwrap()).join("migration-tests") diff --git a/validator_client/validator_services/src/attestation_service.rs b/validator_client/validator_services/src/attestation_service.rs index b2b8bc81e2..587d4668b8 100644 --- a/validator_client/validator_services/src/attestation_service.rs +++ b/validator_client/validator_services/src/attestation_service.rs @@ -193,6 +193,12 @@ impl AttestationService = self.duties_service.attesters(slot).into_iter().collect(); + + // Return early if there is no attestation duties + if attestation_duties.is_empty() { + return Ok(()); + } + let attestation_service = self.clone(); let attestation_data_handle = self @@ -371,10 +377,6 @@ impl AttestationService"] [dependencies] +bls = { workspace = true } eth2 = { workspace = true } slashing_protection = { workspace = true } types = { workspace = true } diff --git a/validator_client/validator_store/src/lib.rs b/validator_client/validator_store/src/lib.rs index 6fd2e27064..2b472799d2 100644 --- a/validator_client/validator_store/src/lib.rs +++ b/validator_client/validator_store/src/lib.rs @@ -1,3 +1,4 @@ +use bls::{PublicKeyBytes, Signature}; use eth2::types::{FullBlockContents, PublishBlockRequest}; use slashing_protection::NotSafe; use std::fmt::Debug; @@ -5,9 +6,9 @@ use std::future::Future; use std::sync::Arc; use types::{ Address, Attestation, AttestationError, BlindedBeaconBlock, Epoch, EthSpec, Graffiti, Hash256, - PublicKeyBytes, SelectionProof, Signature, SignedAggregateAndProof, SignedBlindedBeaconBlock, - SignedContributionAndProof, SignedValidatorRegistrationData, Slot, SyncCommitteeContribution, - SyncCommitteeMessage, SyncSelectionProof, SyncSubnetId, ValidatorRegistrationData, + SelectionProof, SignedAggregateAndProof, SignedBlindedBeaconBlock, SignedContributionAndProof, + SignedValidatorRegistrationData, Slot, SyncCommitteeContribution, SyncCommitteeMessage, + SyncSelectionProof, SyncSubnetId, ValidatorRegistrationData, }; #[derive(Debug, PartialEq, Clone)] diff --git a/validator_manager/Cargo.toml b/validator_manager/Cargo.toml index 6ef179fbe9..16ce1e023f 100644 --- a/validator_manager/Cargo.toml +++ b/validator_manager/Cargo.toml @@ -6,6 +6,7 @@ edition = { workspace = true } [dependencies] account_utils = { workspace = true } +bls = { workspace = true } clap = { workspace = true } clap_utils = { workspace = true } educe = { workspace = true } diff --git a/validator_manager/src/common.rs b/validator_manager/src/common.rs index 0e93b25773..a95d2a1fd6 100644 --- a/validator_manager/src/common.rs +++ b/validator_manager/src/common.rs @@ -1,5 +1,6 @@ pub use account_utils::STDIN_INPUTS_FLAG; use account_utils::strip_off_newlines; +use bls::{Keypair, PublicKeyBytes, SignatureBytes}; use eth2::lighthouse_vc::std_types::{InterchangeJsonStr, KeystoreJsonStr}; use eth2::{ SensitiveUrl, diff --git a/validator_manager/src/create_validators.rs b/validator_manager/src/create_validators.rs index 19f78be2ea..8682705956 100644 --- a/validator_manager/src/create_validators.rs +++ b/validator_manager/src/create_validators.rs @@ -1,6 +1,7 @@ use super::common::*; use crate::DumpConfig; use account_utils::{random_password_string, read_mnemonic_from_cli, read_password_from_user}; +use bls::PublicKeyBytes; use clap::{Arg, ArgAction, ArgMatches, Command}; use clap_utils::FLAG_HEADER; use eth2::{ @@ -586,6 +587,7 @@ async fn run(config: CreateConfig, spec: &ChainSpec) -> Result<(), S #[cfg(test)] pub mod tests { use super::*; + use bls::SignatureBytes; use eth2_network_config::Eth2NetworkConfig; use regex::Regex; use std::path::Path; diff --git a/validator_manager/src/delete_validators.rs b/validator_manager/src/delete_validators.rs index 3ff0c9529d..2421b002aa 100644 --- a/validator_manager/src/delete_validators.rs +++ b/validator_manager/src/delete_validators.rs @@ -1,3 +1,4 @@ +use bls::PublicKeyBytes; use clap::{Arg, ArgAction, ArgMatches, Command}; use eth2::{ SensitiveUrl, @@ -5,7 +6,6 @@ use eth2::{ }; use serde::{Deserialize, Serialize}; use std::path::PathBuf; -use types::PublicKeyBytes; use crate::{DumpConfig, common::vc_http_client}; diff --git a/validator_manager/src/exit_validators.rs b/validator_manager/src/exit_validators.rs index 4a398793ce..b53d9c0a16 100644 --- a/validator_manager/src/exit_validators.rs +++ b/validator_manager/src/exit_validators.rs @@ -1,5 +1,6 @@ use crate::{DumpConfig, common::vc_http_client}; +use bls::PublicKeyBytes; use clap::{Arg, ArgAction, ArgMatches, Command}; use clap_utils::FLAG_HEADER; use eth2::types::{ConfigAndPreset, Epoch, StateId, ValidatorId, ValidatorStatus}; @@ -10,7 +11,7 @@ use slot_clock::{SlotClock, SystemTimeSlotClock}; use std::fs::write; use std::path::PathBuf; use std::time::Duration; -use types::{ChainSpec, EthSpec, PublicKeyBytes}; +use types::{ChainSpec, EthSpec}; pub const CMD: &str = "exit"; pub const BEACON_URL_FLAG: &str = "beacon-node"; diff --git a/validator_manager/src/list_validators.rs b/validator_manager/src/list_validators.rs index 082894a995..f7a09f8d8e 100644 --- a/validator_manager/src/list_validators.rs +++ b/validator_manager/src/list_validators.rs @@ -1,3 +1,4 @@ +use bls::PublicKeyBytes; use clap::{Arg, ArgAction, ArgMatches, Command}; use eth2::lighthouse_vc::types::SingleKeystoreResponse; use eth2::types::{ConfigAndPreset, StateId, ValidatorId, ValidatorStatus}; @@ -5,7 +6,7 @@ use eth2::{BeaconNodeHttpClient, SensitiveUrl, Timeouts}; use serde::{Deserialize, Serialize}; use std::path::PathBuf; use std::time::Duration; -use types::{ChainSpec, EthSpec, PublicKeyBytes}; +use types::{ChainSpec, EthSpec}; use crate::exit_validators::get_current_epoch; use crate::{DumpConfig, common::vc_http_client}; diff --git a/validator_manager/src/move_validators.rs b/validator_manager/src/move_validators.rs index 08b50eb929..ace1d1941f 100644 --- a/validator_manager/src/move_validators.rs +++ b/validator_manager/src/move_validators.rs @@ -1,6 +1,7 @@ use super::common::*; use crate::DumpConfig; use account_utils::read_password_from_user; +use bls::PublicKeyBytes; use clap::{Arg, ArgAction, ArgMatches, Command}; use eth2::{ SensitiveUrl, @@ -18,7 +19,7 @@ use std::path::PathBuf; use std::str::FromStr; use std::time::Duration; use tokio::time::sleep; -use types::{Address, PublicKeyBytes}; +use types::Address; use zeroize::Zeroizing; pub const MOVE_DIR_NAME: &str = "lighthouse-validator-move";