From 36bd4d87f04260d6c329c16600f26d7de98fedf9 Mon Sep 17 00:00:00 2001 From: Michael Sproul Date: Wed, 28 Oct 2020 22:19:38 +0000 Subject: [PATCH] Update to spec v1.0.0-rc.0 and BLSv4 (#1765) ## Issue Addressed Closes #1504 Closes #1505 Replaces #1703 Closes #1707 ## Proposed Changes * Update BLST and Milagro to versions compatible with BLSv4 spec * Update Lighthouse to spec v1.0.0-rc.0, and update EF test vectors * Use the v1.0.0 constants for `MainnetEthSpec`. * Rename `InteropEthSpec` -> `V012LegacyEthSpec` * Change all constants to suit the mainnet `v0.12.3` specification (i.e., Medalla). * Deprecate the `--spec` flag for the `lighthouse` binary * This value is now obtained from the `config_name` field of the `YamlConfig`. * Built in testnet YAML files have been updated. * Ignore the `--spec` value, if supplied, log a warning that it will be deprecated * `lcli` still has the spec flag, that's fine because it's dev tooling. * Remove the `E: EthSpec` from `YamlConfig` * This means we need to deser the genesis `BeaconState` on-demand, but this is fine. * Swap the old "minimal", "mainnet" strings over to the new `EthSpecId` enum. * Always require a `CONFIG_NAME` field in `YamlConfig` (it used to have a default). ## Additional Info Lots of breaking changes, do not merge! ~~We will likely need a Lighthouse v0.4.0 branch, and possibly a long-term v0.3.0 branch to keep Medalla alive~~. Co-authored-by: Kirk Baird Co-authored-by: Paul Hauner --- Cargo.lock | 263 +++++++++--------- Makefile | 2 +- account_manager/Cargo.toml | 2 +- .../src/validator/slashing_protection.rs | 22 +- beacon_node/Cargo.toml | 2 +- beacon_node/client/src/config.rs | 5 - beacon_node/src/config.rs | 24 +- beacon_node/src/lib.rs | 8 +- book/src/cross-compiling.md | 18 +- book/src/validator-create.md | 5 +- book/src/wallet-create.md | 3 - boot_node/Cargo.toml | 2 +- boot_node/src/config.rs | 7 +- boot_node/src/lib.rs | 13 +- common/clap_utils/src/lib.rs | 9 +- common/eth2_config/src/lib.rs | 16 +- .../altona/config.yaml | 2 + .../medalla/config.yaml | 2 + .../spadina/config.yaml | 1 + common/eth2_testnet_config/src/lib.rs | 113 +++++--- common/lighthouse_version/src/lib.rs | 2 +- common/task_executor/Cargo.toml | 2 +- consensus/types/src/chain_spec.rs | 58 ++-- consensus/types/src/eth_spec.rs | 86 ++++-- consensus/types/src/lib.rs | 1 + consensus/types/src/signed_beacon_block.rs | 3 +- crypto/bls/Cargo.toml | 5 +- .../bls/src/generic_aggregate_public_key.rs | 14 +- crypto/bls/src/generic_aggregate_signature.rs | 14 - crypto/bls/src/generic_public_key.rs | 17 +- crypto/bls/src/generic_public_key_bytes.rs | 5 +- crypto/bls/src/generic_secret_key.rs | 5 +- crypto/bls/src/generic_signature.rs | 4 - crypto/bls/src/impls/blst.rs | 67 ++--- crypto/bls/src/impls/fake_crypto.rs | 20 +- crypto/bls/src/impls/milagro.rs | 18 +- crypto/bls/src/lib.rs | 4 + crypto/bls/tests/tests.rs | 122 +------- lcli/Cargo.toml | 2 +- lcli/src/eth1_genesis.rs | 10 +- lcli/src/interop_genesis.rs | 10 +- lcli/src/main.rs | 37 ++- lcli/src/new_testnet.rs | 4 +- lighthouse/Cargo.toml | 4 +- lighthouse/environment/src/lib.rs | 22 +- .../environment/tests/environment_builder.rs | 8 +- lighthouse/src/main.rs | 101 ++++--- testing/ef_tests/Makefile | 2 +- .../src/cases/bls_aggregate_verify.rs | 23 +- .../src/cases/bls_fast_aggregate_verify.rs | 16 +- testing/ef_tests/src/cases/bls_sign_msg.rs | 19 +- testing/ef_tests/src/cases/bls_verify_msg.rs | 9 +- testing/ef_tests/src/type_name.rs | 7 + testing/ef_tests/tests/tests.rs | 15 +- validator_client/Cargo.toml | 2 +- 55 files changed, 596 insertions(+), 661 deletions(-) diff --git a/Cargo.lock b/Cargo.lock index 02c47002b..e1555410d 100644 --- a/Cargo.lock +++ b/Cargo.lock @@ -2,7 +2,7 @@ # It is not intended for manual editing. [[package]] name = "account_manager" -version = "0.3.1" +version = "0.3.2" dependencies = [ "account_utils", "bls", @@ -18,8 +18,8 @@ dependencies = [ "eth2_testnet_config", "eth2_wallet", "eth2_wallet_manager", - "futures 0.3.6", - "hex 0.4.2", + "futures 0.3.7", + "hex", "libc", "rand 0.7.3", "rayon", @@ -172,12 +172,8 @@ dependencies = [ [[package]] name = "amcl" -version = "0.2.0" -source = "git+https://github.com/sigp/milagro_bls?branch=paulh#7662690845f3f2594e46cfe71b6b0bb91d5e1f82" -dependencies = [ - "hex 0.3.2", - "lazy_static", -] +version = "0.3.0" +source = "git+https://github.com/sigp/milagro_bls?tag=v1.4.0#45a076a776a6f1d9f8157fd2d574bfefaee2c81a" [[package]] name = "ansi_term" @@ -226,9 +222,9 @@ checksum = "a4c527152e37cf757a3f78aae5a06fbeefdb07ccc535c980a3208ee3060dd544" [[package]] name = "arrayvec" -version = "0.5.1" +version = "0.5.2" source = "registry+https://github.com/rust-lang/crates.io-index" -checksum = "cff77d8686867eceff3105329d4698d96c2391c176d5d03adc90c7389162b5b8" +checksum = "23b62fc65de8e4e7f52534fb52b0f3ed04746ae267519eef2a83941e8085068b" [[package]] name = "asn1_der" @@ -357,7 +353,7 @@ checksum = "904dfeac50f3cdaba28fc6f57fdcddb75f49ed61346676a78c4ffe55877802fd" name = "beacon_chain" version = "0.2.0" dependencies = [ - "bitvec 0.19.3", + "bitvec 0.19.4", "bls", "bus", "derivative", @@ -370,7 +366,7 @@ dependencies = [ "eth2_ssz_types", "exit-future", "fork_choice", - "futures 0.3.6", + "futures 0.3.7", "genesis", "int_to_bytes", "integer-sqrt", @@ -409,7 +405,7 @@ dependencies = [ [[package]] name = "beacon_node" -version = "0.3.1" +version = "0.3.2" dependencies = [ "beacon_chain", "clap", @@ -424,9 +420,9 @@ dependencies = [ "eth2_ssz", "eth2_testnet_config", "exit-future", - "futures 0.3.6", + "futures 0.3.7", "genesis", - "hex 0.4.2", + "hex", "hyper 0.13.8", "lighthouse_version", "logging", @@ -487,9 +483,9 @@ dependencies = [ [[package]] name = "bitvec" -version = "0.19.3" +version = "0.19.4" source = "registry+https://github.com/rust-lang/crates.io-index" -checksum = "11593270830d9b037fbead730bb0c05ef6fbf6be55537a1e8e5892edef7e1f03" +checksum = "a7ba35e9565969edb811639dbebfe34edc0368e472c5018474c8eb2543397f81" dependencies = [ "funty", "radium 0.5.3", @@ -499,15 +495,13 @@ dependencies = [ [[package]] name = "blake2" -version = "0.9.0" +version = "0.9.1" source = "registry+https://github.com/rust-lang/crates.io-index" -checksum = "84ce5b6108f8e154604bd4eb76a2f726066c3464d5a552a4229262a18c9bb471" +checksum = "10a5720225ef5daecf08657f23791354e1685a8c91a4c60c7f3d3b2892f978f4" dependencies = [ - "byte-tools", - "byteorder", "crypto-mac 0.8.0", "digest 0.9.0", - "opaque-debug 0.2.3", + "opaque-debug 0.3.0", ] [[package]] @@ -587,7 +581,7 @@ dependencies = [ "eth2_hashing", "eth2_ssz", "ethereum-types", - "hex 0.4.2", + "hex", "milagro_bls", "rand 0.7.3", "serde", @@ -599,8 +593,8 @@ dependencies = [ [[package]] name = "blst" -version = "0.1.1" -source = "git+https://github.com/sigp/blst.git?rev=284f7059642851c760a09fb1708bcb59c7ca323c#284f7059642851c760a09fb1708bcb59c7ca323c" +version = "0.2.0" +source = "git+https://github.com/sigp/blst.git?rev=7cf47864627ca479cad06c2a164f30d0cbaf16ce#7cf47864627ca479cad06c2a164f30d0cbaf16ce" dependencies = [ "cc", "glob", @@ -609,15 +603,15 @@ dependencies = [ [[package]] name = "boot_node" -version = "0.3.1" +version = "0.3.2" dependencies = [ "beacon_node", "clap", "eth2_libp2p", "eth2_ssz", "eth2_testnet_config", - "futures 0.3.6", - "hex 0.4.2", + "futures 0.3.7", + "hex", "log 0.4.11", "logging", "slog", @@ -839,7 +833,7 @@ dependencies = [ "dirs 3.0.1", "eth2_ssz", "eth2_testnet_config", - "hex 0.4.2", + "hex", "types", ] @@ -857,7 +851,7 @@ dependencies = [ "eth2_config", "eth2_libp2p", "eth2_ssz", - "futures 0.3.6", + "futures 0.3.7", "genesis", "http_api", "http_metrics", @@ -1267,7 +1261,7 @@ version = "0.2.0" dependencies = [ "eth2_ssz", "ethabi", - "hex 0.4.2", + "hex", "reqwest", "serde_json", "sha2 0.9.1", @@ -1384,8 +1378,8 @@ dependencies = [ "digest 0.9.0", "enr", "fnv", - "futures 0.3.6", - "hex 0.4.2", + "futures 0.3.7", + "hex", "hkdf", "k256", "lazy_static", @@ -1416,8 +1410,8 @@ dependencies = [ "digest 0.9.0", "enr", "fnv", - "futures 0.3.6", - "hex 0.4.2", + "futures 0.3.7", + "hex", "hkdf", "k256", "lazy_static", @@ -1487,7 +1481,7 @@ dependencies = [ "eth2_ssz", "eth2_ssz_derive", "ethereum-types", - "hex 0.4.2", + "hex", "rayon", "serde", "serde_derive", @@ -1541,7 +1535,7 @@ dependencies = [ "base64 0.12.3", "bs58", "ed25519-dalek", - "hex 0.4.2", + "hex", "k256", "log 0.4.11", "rand 0.7.3", @@ -1572,7 +1566,7 @@ dependencies = [ "eth2_config", "eth2_testnet_config", "exit-future", - "futures 0.3.6", + "futures 0.3.7", "logging", "parking_lot 0.11.0", "slog", @@ -1604,8 +1598,8 @@ dependencies = [ "eth2_hashing", "eth2_ssz", "eth2_ssz_derive", - "futures 0.3.6", - "hex 0.4.2", + "futures 0.3.7", + "hex", "lazy_static", "libflate", "lighthouse_metrics", @@ -1630,7 +1624,7 @@ name = "eth1_test_rig" version = "0.2.0" dependencies = [ "deposit_contract", - "futures 0.3.6", + "futures 0.3.7", "serde_json", "tokio 0.2.22", "types", @@ -1646,7 +1640,7 @@ dependencies = [ "eth2_keystore", "eth2_libp2p", "eth2_ssz", - "hex 0.4.2", + "hex", "libsecp256k1", "procinfo", "proto_array", @@ -1688,7 +1682,7 @@ dependencies = [ "base64 0.13.0", "bls", "eth2_hashing", - "hex 0.4.2", + "hex", "lazy_static", "num-bigint", "serde", @@ -1701,7 +1695,7 @@ name = "eth2_key_derivation" version = "0.1.0" dependencies = [ "bls", - "hex 0.4.2", + "hex", "num-bigint-dig", "ring", "sha2 0.9.1", @@ -1716,7 +1710,7 @@ dependencies = [ "bls", "eth2_key_derivation", "eth2_ssz", - "hex 0.4.2", + "hex", "hmac 0.9.0", "pbkdf2 0.5.0", "rand 0.7.3", @@ -1744,9 +1738,9 @@ dependencies = [ "eth2_ssz_types", "exit-future", "fnv", - "futures 0.3.6", + "futures 0.3.7", "hashset_delay", - "hex 0.4.2", + "hex", "lazy_static", "libp2p", "lighthouse_metrics", @@ -1825,7 +1819,7 @@ version = "0.1.0" dependencies = [ "eth2_key_derivation", "eth2_keystore", - "hex 0.4.2", + "hex", "rand 0.7.3", "serde", "serde_json", @@ -1891,7 +1885,7 @@ version = "0.2.0" source = "registry+https://github.com/rust-lang/crates.io-index" checksum = "e43f2f1833d64e33f15592464d6fdd70f349dda7b1a53088eb83cd94014008c5" dependencies = [ - "futures 0.3.6", + "futures 0.3.7", ] [[package]] @@ -2005,7 +1999,7 @@ dependencies = [ "beacon_chain", "eth2_ssz", "eth2_ssz_derive", - "hex 0.4.2", + "hex", "proto_array", "slot_clock", "state_processing", @@ -2050,9 +2044,9 @@ checksum = "4c7e4c2612746b0df8fed4ce0c69156021b704c9aefa360311c04e6e9e002eed" [[package]] name = "futures" -version = "0.3.6" +version = "0.3.7" source = "registry+https://github.com/rust-lang/crates.io-index" -checksum = "5d8e3078b7b2a8a671cb7a3d17b4760e4181ea243227776ba83fd043b4ca034e" +checksum = "95314d38584ffbfda215621d723e0a3906f032e03ae5551e650058dac83d4797" dependencies = [ "futures-channel", "futures-core", @@ -2065,9 +2059,9 @@ dependencies = [ [[package]] name = "futures-channel" -version = "0.3.6" +version = "0.3.7" source = "registry+https://github.com/rust-lang/crates.io-index" -checksum = "a7a4d35f7401e948629c9c3d6638fb9bf94e0b2121e96c3b428cc4e631f3eb74" +checksum = "0448174b01148032eed37ac4aed28963aaaa8cfa93569a08e5b479bbc6c2c151" dependencies = [ "futures-core", "futures-sink", @@ -2075,9 +2069,9 @@ dependencies = [ [[package]] name = "futures-core" -version = "0.3.6" +version = "0.3.7" source = "registry+https://github.com/rust-lang/crates.io-index" -checksum = "d674eaa0056896d5ada519900dbf97ead2e46a7b6621e8160d79e2f2e1e2784b" +checksum = "18eaa56102984bed2c88ea39026cff3ce3b4c7f508ca970cedf2450ea10d4e46" [[package]] name = "futures-cpupool" @@ -2091,9 +2085,9 @@ dependencies = [ [[package]] name = "futures-executor" -version = "0.3.6" +version = "0.3.7" source = "registry+https://github.com/rust-lang/crates.io-index" -checksum = "cc709ca1da6f66143b8c9bec8e6260181869893714e9b5a490b169b0414144ab" +checksum = "f5f8e0c9258abaea85e78ebdda17ef9666d390e987f006be6080dfe354b708cb" dependencies = [ "futures-core", "futures-task", @@ -2103,15 +2097,15 @@ dependencies = [ [[package]] name = "futures-io" -version = "0.3.6" +version = "0.3.7" source = "registry+https://github.com/rust-lang/crates.io-index" -checksum = "5fc94b64bb39543b4e432f1790b6bf18e3ee3b74653c5449f63310e9a74b123c" +checksum = "6e1798854a4727ff944a7b12aa999f58ce7aa81db80d2dfaaf2ba06f065ddd2b" [[package]] name = "futures-macro" -version = "0.3.6" +version = "0.3.7" source = "registry+https://github.com/rust-lang/crates.io-index" -checksum = "f57ed14da4603b2554682e9f2ff3c65d7567b53188db96cb71538217fc64581b" +checksum = "e36fccf3fc58563b4a14d265027c627c3b665d7fed489427e88e7cc929559efe" dependencies = [ "proc-macro-hack", "proc-macro2", @@ -2121,15 +2115,15 @@ dependencies = [ [[package]] name = "futures-sink" -version = "0.3.6" +version = "0.3.7" source = "registry+https://github.com/rust-lang/crates.io-index" -checksum = "0d8764258ed64ebc5d9ed185cf86a95db5cac810269c5d20ececb32e0088abbd" +checksum = "0e3ca3f17d6e8804ae5d3df7a7d35b2b3a6fe89dac84b31872720fc3060a0b11" [[package]] name = "futures-task" -version = "0.3.6" +version = "0.3.7" source = "registry+https://github.com/rust-lang/crates.io-index" -checksum = "4dd26820a9f3637f1302da8bceba3ff33adbe53464b54ca24d4e2d4f1db30f94" +checksum = "96d502af37186c4fef99453df03e374683f8a1eec9dcc1e66b3b82dc8278ce3c" dependencies = [ "once_cell", ] @@ -2142,9 +2136,9 @@ checksum = "e64b03909df88034c26dc1547e8970b91f98bdb65165d6a4e9110d94263dbb2c" [[package]] name = "futures-util" -version = "0.3.6" +version = "0.3.7" source = "registry+https://github.com/rust-lang/crates.io-index" -checksum = "8a894a0acddba51a2d49a6f4263b1e64b8c579ece8af50fa86503d52cd1eea34" +checksum = "abcb44342f62e6f3e8ac427b8aa815f724fd705dfad060b18ac7866c15bb8e34" dependencies = [ "futures 0.1.30", "futures-channel", @@ -2154,7 +2148,7 @@ dependencies = [ "futures-sink", "futures-task", "memchr", - "pin-project 0.4.27", + "pin-project 1.0.1", "pin-utils", "proc-macro-hack", "proc-macro-nested", @@ -2168,7 +2162,7 @@ source = "registry+https://github.com/rust-lang/crates.io-index" checksum = "ce54d63f8b0c75023ed920d46fd71d0cbbb830b0ee012726b5b4f506fb6dea5b" dependencies = [ "bytes 0.5.6", - "futures 0.3.6", + "futures 0.3.7", "memchr", "pin-project 0.4.27", ] @@ -2221,7 +2215,7 @@ dependencies = [ "eth2_hashing", "eth2_ssz", "exit-future", - "futures 0.3.6", + "futures 0.3.7", "int_to_bytes", "merkle_proof", "parking_lot 0.11.0", @@ -2342,9 +2336,9 @@ dependencies = [ [[package]] name = "h2" -version = "0.2.6" +version = "0.2.7" source = "registry+https://github.com/rust-lang/crates.io-index" -checksum = "993f9e0baeed60001cf565546b0d3dbe6a6ad23f2bd31644a133c641eccf6d53" +checksum = "5e4728fd124914ad25e99e3d15a9361a879f6620f63cb56bbb08f95abb97a535" dependencies = [ "bytes 0.5.6", "fnv", @@ -2357,6 +2351,7 @@ dependencies = [ "tokio 0.2.22", "tokio-util", "tracing", + "tracing-futures", ] [[package]] @@ -2397,7 +2392,7 @@ dependencies = [ name = "hashset_delay" version = "0.2.0" dependencies = [ - "futures 0.3.6", + "futures 0.3.7", "tokio 0.2.22", ] @@ -2444,12 +2439,6 @@ dependencies = [ "libc", ] -[[package]] -name = "hex" -version = "0.3.2" -source = "registry+https://github.com/rust-lang/crates.io-index" -checksum = "805026a5d0141ffc30abb3be3173848ad46a1b1664fe632428479619a3644d77" - [[package]] name = "hex" version = "0.4.2" @@ -2570,7 +2559,7 @@ dependencies = [ "eth2_libp2p", "eth2_ssz", "fork_choice", - "hex 0.4.2", + "hex", "lazy_static", "lighthouse_metrics", "lighthouse_version", @@ -2691,7 +2680,7 @@ dependencies = [ "futures-channel", "futures-core", "futures-util", - "h2 0.2.6", + "h2 0.2.7", "http 0.2.1", "http-body 0.3.1", "httparse", @@ -2814,11 +2803,11 @@ dependencies = [ [[package]] name = "instant" -version = "0.1.7" +version = "0.1.8" source = "registry+https://github.com/rust-lang/crates.io-index" -checksum = "63312a18f7ea8760cdd0a7c5aac1a619752a246b833545e3e36d1f81f7cd9e66" +checksum = "cb1fc4429a33e1f80d41dc9fea4d108a88bec1de8053878898ae448a0b52f613" dependencies = [ - "cfg-if 0.1.10", + "cfg-if 1.0.0", ] [[package]] @@ -2826,7 +2815,7 @@ name = "int_to_bytes" version = "0.2.0" dependencies = [ "bytes 0.5.6", - "hex 0.4.2", + "hex", "yaml-rust", ] @@ -2902,9 +2891,9 @@ dependencies = [ [[package]] name = "k256" -version = "0.5.9" +version = "0.5.10" source = "registry+https://github.com/rust-lang/crates.io-index" -checksum = "c2967b7caf19e57f5d01ac0893551b0aaae1a8e2e2b2a28996e12c9c51b3b486" +checksum = "3934640b1efbc660af5889d041854b6985d403771dc4d5fee984e13e8f82f313" dependencies = [ "cfg-if 1.0.0", "ecdsa", @@ -2951,7 +2940,7 @@ checksum = "830d08ce1d1d941e6b30645f1a0eb5643013d835ce3779a5fc208261dbe10f55" [[package]] name = "lcli" -version = "0.3.1" +version = "0.3.2" dependencies = [ "bls", "clap", @@ -2964,9 +2953,9 @@ dependencies = [ "eth2_libp2p", "eth2_ssz", "eth2_testnet_config", - "futures 0.3.6", + "futures 0.3.7", "genesis", - "hex 0.4.2", + "hex", "lighthouse_version", "log 0.4.11", "rand 0.7.3", @@ -3006,15 +2995,15 @@ dependencies = [ [[package]] name = "libc" -version = "0.2.79" +version = "0.2.80" source = "registry+https://github.com/rust-lang/crates.io-index" -checksum = "2448f6066e80e3bfc792e9c98bf705b4b0fc6e8ef5b43e5889aff0eaa9c58743" +checksum = "4d58d1b70b004888f764dfbf6a26a3b0342a1632d33968e4a179d8011c760614" [[package]] name = "libflate" -version = "1.0.2" +version = "1.0.3" source = "registry+https://github.com/rust-lang/crates.io-index" -checksum = "e9bac9023e1db29c084f9f8cd9d3852e5e8fddf98fb47c4964a0ea4663d95949" +checksum = "389de7875e06476365974da3e7ff85d55f1972188ccd9f6020dd7c8156e17914" dependencies = [ "adler32", "crc32fast", @@ -3041,7 +3030,7 @@ source = "git+https://github.com/sigp/rust-libp2p?rev=8c6ce6eb1228de568568f6cd72 dependencies = [ "atomic", "bytes 0.5.6", - "futures 0.3.6", + "futures 0.3.7", "lazy_static", "libp2p-core 0.22.2", "libp2p-core-derive", @@ -3072,7 +3061,7 @@ dependencies = [ "ed25519-dalek", "either", "fnv", - "futures 0.3.6", + "futures 0.3.7", "futures-timer", "lazy_static", "libsecp256k1", @@ -3105,7 +3094,7 @@ dependencies = [ "ed25519-dalek", "either", "fnv", - "futures 0.3.6", + "futures 0.3.7", "futures-timer", "lazy_static", "libsecp256k1", @@ -3142,7 +3131,7 @@ name = "libp2p-dns" version = "0.22.0" source = "git+https://github.com/sigp/rust-libp2p?rev=8c6ce6eb1228de568568f6cd72fb134dea5f9669#8c6ce6eb1228de568568f6cd72fb134dea5f9669" dependencies = [ - "futures 0.3.6", + "futures 0.3.7", "libp2p-core 0.22.2", "log 0.4.11", ] @@ -3156,7 +3145,7 @@ dependencies = [ "byteorder", "bytes 0.5.6", "fnv", - "futures 0.3.6", + "futures 0.3.7", "futures_codec", "hex_fmt", "libp2p-core 0.22.2", @@ -3176,7 +3165,7 @@ name = "libp2p-identify" version = "0.22.0" source = "git+https://github.com/sigp/rust-libp2p?rev=8c6ce6eb1228de568568f6cd72fb134dea5f9669#8c6ce6eb1228de568568f6cd72fb134dea5f9669" dependencies = [ - "futures 0.3.6", + "futures 0.3.7", "libp2p-core 0.22.2", "libp2p-swarm", "log 0.4.11", @@ -3193,7 +3182,7 @@ source = "git+https://github.com/sigp/rust-libp2p?rev=8c6ce6eb1228de568568f6cd72 dependencies = [ "bytes 0.5.6", "fnv", - "futures 0.3.6", + "futures 0.3.7", "futures_codec", "libp2p-core 0.22.2", "log 0.4.11", @@ -3208,7 +3197,7 @@ source = "git+https://github.com/sigp/rust-libp2p?rev=8c6ce6eb1228de568568f6cd72 dependencies = [ "bytes 0.5.6", "curve25519-dalek", - "futures 0.3.6", + "futures 0.3.7", "lazy_static", "libp2p-core 0.22.2", "log 0.4.11", @@ -3228,7 +3217,7 @@ version = "0.22.0" source = "git+https://github.com/sigp/rust-libp2p?rev=8c6ce6eb1228de568568f6cd72fb134dea5f9669#8c6ce6eb1228de568568f6cd72fb134dea5f9669" dependencies = [ "either", - "futures 0.3.6", + "futures 0.3.7", "libp2p-core 0.22.2", "log 0.4.11", "rand 0.7.3", @@ -3242,7 +3231,7 @@ name = "libp2p-tcp" version = "0.22.0" source = "git+https://github.com/sigp/rust-libp2p?rev=8c6ce6eb1228de568568f6cd72fb134dea5f9669#8c6ce6eb1228de568568f6cd72fb134dea5f9669" dependencies = [ - "futures 0.3.6", + "futures 0.3.7", "futures-timer", "get_if_addrs", "ipnet", @@ -3259,7 +3248,7 @@ source = "git+https://github.com/sigp/rust-libp2p?rev=8c6ce6eb1228de568568f6cd72 dependencies = [ "async-tls", "either", - "futures 0.3.6", + "futures 0.3.7", "libp2p-core 0.22.2", "log 0.4.11", "quicksink", @@ -3312,7 +3301,7 @@ dependencies = [ [[package]] name = "lighthouse" -version = "0.3.1" +version = "0.3.2" dependencies = [ "account_manager", "account_utils", @@ -3325,7 +3314,7 @@ dependencies = [ "env_logger", "environment", "eth2_testnet_config", - "futures 0.3.6", + "futures 0.3.7", "lighthouse_version", "logging", "slashing_protection", @@ -3481,9 +3470,9 @@ checksum = "60302e4db3a61da70c0cb7991976248362f30319e88850c487b9b95bbf059e00" [[package]] name = "memchr" -version = "2.3.3" +version = "2.3.4" source = "registry+https://github.com/rust-lang/crates.io-index" -checksum = "3728d817d99e5ac407411fa471ff9800a778d88a24685968b36824eaf4bee400" +checksum = "0ee1c47aaa256ecabcaea351eae4a9b01ef39ed810004e298d2511ed284b1525" [[package]] name = "memoffset" @@ -3508,11 +3497,11 @@ dependencies = [ [[package]] name = "milagro_bls" -version = "1.1.0" -source = "git+https://github.com/sigp/milagro_bls?branch=paulh#7662690845f3f2594e46cfe71b6b0bb91d5e1f82" +version = "1.4.0" +source = "git+https://github.com/sigp/milagro_bls?tag=v1.4.0#45a076a776a6f1d9f8157fd2d574bfefaee2c81a" dependencies = [ "amcl", - "hex 0.4.2", + "hex", "lazy_static", "rand 0.7.3", "zeroize", @@ -3683,7 +3672,7 @@ version = "0.8.3" source = "git+https://github.com/sigp/rust-libp2p?rev=8c6ce6eb1228de568568f6cd72fb134dea5f9669#8c6ce6eb1228de568568f6cd72fb134dea5f9669" dependencies = [ "bytes 0.5.6", - "futures 0.3.6", + "futures 0.3.7", "log 0.4.11", "pin-project 0.4.27", "smallvec 1.4.2", @@ -3697,7 +3686,7 @@ source = "registry+https://github.com/rust-lang/crates.io-index" checksum = "36a6aa6e32fbaf16795142335967214b8564a7a4661eb6dc846ef343a6e00ac1" dependencies = [ "bytes 0.5.6", - "futures 0.3.6", + "futures 0.3.7", "log 0.4.11", "pin-project 1.0.1", "smallvec 1.4.2", @@ -3744,11 +3733,11 @@ dependencies = [ "eth2_ssz_types", "exit-future", "fnv", - "futures 0.3.6", + "futures 0.3.7", "genesis", "get_if_addrs", "hashset_delay", - "hex 0.4.2", + "hex", "igd", "itertools 0.9.0", "lazy_static", @@ -3805,7 +3794,7 @@ dependencies = [ "environment", "eth2", "eth2_config", - "futures 0.3.6", + "futures 0.3.7", "genesis", "reqwest", "serde", @@ -4273,9 +4262,9 @@ dependencies = [ [[package]] name = "proc-macro-hack" -version = "0.5.18" +version = "0.5.19" source = "registry+https://github.com/rust-lang/crates.io-index" -checksum = "99c605b9a0adc77b7211c6b1f722dcb613d68d66859a44f3d485a6da332b0598" +checksum = "dbf0c48bc1d91375ae5c3cd81e3722dff1abcf81a30960240640d223f59fe0e5" [[package]] name = "proc-macro-nested" @@ -4914,7 +4903,7 @@ version = "0.2.1" source = "registry+https://github.com/rust-lang/crates.io-index" checksum = "4da5fcb054c46f5a5dff833b129285a93d3f0179531735e6c866e8cc307d2020" dependencies = [ - "futures 0.3.6", + "futures 0.3.7", "pin-project 0.4.27", "static_assertions", ] @@ -5137,7 +5126,7 @@ dependencies = [ name = "serde_utils" version = "0.1.0" dependencies = [ - "hex 0.4.2", + "hex", "serde", "serde_derive", "serde_json", @@ -5274,7 +5263,7 @@ dependencies = [ "env_logger", "eth1", "eth1_test_rig", - "futures 0.3.6", + "futures 0.3.7", "node_test_rig", "parking_lot 0.11.0", "rayon", @@ -5477,7 +5466,7 @@ dependencies = [ "base64 0.12.3", "bytes 0.5.6", "flate2", - "futures 0.3.6", + "futures 0.3.7", "httparse", "log 0.4.11", "rand 0.7.3", @@ -5663,9 +5652,9 @@ dependencies = [ [[package]] name = "syn" -version = "1.0.46" +version = "1.0.48" source = "registry+https://github.com/rust-lang/crates.io-index" -checksum = "5ad5de3220ea04da322618ded2c42233d02baca219d6f160a3e9c87cda16c942" +checksum = "cc371affeffc477f42a221a1e4297aedcea33d47d19b61455588bd9d8f6b19ac" dependencies = [ "proc-macro2", "quote", @@ -5707,7 +5696,7 @@ name = "task_executor" version = "0.1.0" dependencies = [ "exit-future", - "futures 0.3.6", + "futures 0.3.7", "lazy_static", "lighthouse_metrics", "slog", @@ -5866,7 +5855,7 @@ name = "timer" version = "0.2.0" dependencies = [ "beacon_chain", - "futures 0.3.6", + "futures 0.3.7", "parking_lot 0.11.0", "slog", "slot_clock", @@ -6469,7 +6458,7 @@ dependencies = [ "eth2_ssz_derive", "eth2_ssz_types", "ethereum-types", - "hex 0.4.2", + "hex", "int_to_bytes", "log 0.4.11", "merkle_proof", @@ -6652,7 +6641,7 @@ dependencies = [ [[package]] name = "validator_client" -version = "0.3.1" +version = "0.3.2" dependencies = [ "account_utils", "bincode", @@ -6670,8 +6659,8 @@ dependencies = [ "eth2_ssz", "eth2_ssz_derive", "exit-future", - "futures 0.3.6", - "hex 0.4.2", + "futures 0.3.7", + "hex", "hyper 0.13.8", "libc", "libsecp256k1", @@ -6709,7 +6698,7 @@ dependencies = [ "bls", "deposit_contract", "eth2_keystore", - "hex 0.4.2", + "hex", "rand 0.7.3", "rayon", "slog", @@ -6786,7 +6775,7 @@ version = "0.2.5" source = "git+https://github.com/paulhauner/warp?branch=cors-wildcard#a7685b76d70c3e5628e31d60aee510acec3c5c30" dependencies = [ "bytes 0.5.6", - "futures 0.3.6", + "futures 0.3.7", "headers", "http 0.2.1", "hyper 0.13.8", @@ -6932,7 +6921,7 @@ version = "0.2.5" source = "registry+https://github.com/rust-lang/crates.io-index" checksum = "be0ecb0db480561e9a7642b5d3e4187c128914e58aa84330b9493e3eb68c5e7f" dependencies = [ - "futures 0.3.6", + "futures 0.3.7", "js-sys", "parking_lot 0.11.0", "pin-utils", @@ -7029,7 +7018,7 @@ dependencies = [ name = "websocket_server" version = "0.2.0" dependencies = [ - "futures 0.3.6", + "futures 0.3.7", "serde", "serde_derive", "slog", diff --git a/Makefile b/Makefile index 0f6a69b97..823620788 100644 --- a/Makefile +++ b/Makefile @@ -42,7 +42,7 @@ endif # optimized CPU functions that may not be available on some systems. This # results in a more portable binary with ~20% slower BLS verification. build-x86_64: - cross build --release --manifest-path lighthouse/Cargo.toml --target x86_64-unknown-linux-gnu + cross build --release --manifest-path lighthouse/Cargo.toml --target x86_64-unknown-linux-gnu --features modern build-x86_64-portable: cross build --release --manifest-path lighthouse/Cargo.toml --target x86_64-unknown-linux-gnu --features portable build-aarch64: diff --git a/account_manager/Cargo.toml b/account_manager/Cargo.toml index 41f7c819a..4145b19dc 100644 --- a/account_manager/Cargo.toml +++ b/account_manager/Cargo.toml @@ -1,6 +1,6 @@ [package] name = "account_manager" -version = "0.3.1" +version = "0.3.2" authors = ["Paul Hauner ", "Luke Anderson "] edition = "2018" diff --git a/account_manager/src/validator/slashing_protection.rs b/account_manager/src/validator/slashing_protection.rs index 53a7edd51..5ba5352c9 100644 --- a/account_manager/src/validator/slashing_protection.rs +++ b/account_manager/src/validator/slashing_protection.rs @@ -5,7 +5,7 @@ use slashing_protection::{ }; use std::fs::File; use std::path::PathBuf; -use types::EthSpec; +use types::{BeaconState, EthSpec}; pub const CMD: &str = "slashing-protection"; pub const IMPORT_CMD: &str = "import"; @@ -46,18 +46,18 @@ pub fn cli_run( ) -> Result<(), String> { let slashing_protection_db_path = validator_base_dir.join(SLASHING_PROTECTION_FILENAME); - let genesis_validators_root = env + let testnet_config = env .testnet - .and_then(|testnet_config| { - Some( - testnet_config - .genesis_state - .as_ref()? - .genesis_validators_root, + .ok_or_else(|| "Unable to get testnet configuration from the environment".to_string())?; + + let genesis_validators_root = testnet_config + .beacon_state::() + .map(|state: BeaconState| state.genesis_validators_root) + .map_err(|e| { + format!( + "Unable to get genesis state, has genesis occurred? Detail: {:?}", + e ) - }) - .ok_or_else(|| { - "Unable to get genesis validators root from testnet config, has genesis occurred?" })?; match matches.subcommand() { diff --git a/beacon_node/Cargo.toml b/beacon_node/Cargo.toml index 4209b52e4..4f2bd3216 100644 --- a/beacon_node/Cargo.toml +++ b/beacon_node/Cargo.toml @@ -1,6 +1,6 @@ [package] name = "beacon_node" -version = "0.3.1" +version = "0.3.2" authors = ["Paul Hauner ", "Age Manning , pub log_file: PathBuf, - pub spec_constants: String, /// If true, the node will use co-ordinated junk for eth1 values. /// /// This is the method used for the 2019 client interop in Canada. @@ -81,7 +77,6 @@ impl Default for Config { network: NetworkConfig::default(), chain: <_>::default(), websocket_server: <_>::default(), - spec_constants: TESTNET_SPEC_CONSTANTS.into(), dummy_eth1_backend: false, sync_eth1_chain: false, eth1: <_>::default(), diff --git a/beacon_node/src/config.rs b/beacon_node/src/config.rs index f0721bce3..5711395e8 100644 --- a/beacon_node/src/config.rs +++ b/beacon_node/src/config.rs @@ -5,8 +5,7 @@ use client::{ClientConfig, ClientGenesis}; use directory::{DEFAULT_BEACON_NODE_DIR, DEFAULT_NETWORK_DIR, DEFAULT_ROOT_DIR}; use eth2_libp2p::{multiaddr::Protocol, Enr, Multiaddr, NetworkConfig, PeerIdSerialized}; use eth2_testnet_config::Eth2TestnetConfig; -use slog::{crit, info, warn, Logger}; -use ssz::Encode; +use slog::{info, warn, Logger}; use std::cmp; use std::fs; use std::net::{IpAddr, Ipv4Addr, ToSocketAddrs}; @@ -23,7 +22,6 @@ use types::{ChainSpec, Checkpoint, Epoch, EthSpec, Hash256, GRAFFITI_BYTES_LEN}; /// response of some remote server. pub fn get_config( cli_args: &ArgMatches, - spec_constants: &str, spec: &ChainSpec, log: Logger, ) -> Result { @@ -67,8 +65,6 @@ pub fn get_config( log_dir.pop(); info!(log, "Data directory initialised"; "datadir" => log_dir.into_os_string().into_string().expect("Datadir should be a valid os string")); - client_config.spec_constants = spec_constants.into(); - /* * Networking */ @@ -222,14 +218,6 @@ pub fn get_config( .map_err(|_| "block-cache-size is not a valid integer".to_string())?; } - if spec_constants != client_config.spec_constants { - crit!(log, "Specification constants do not match."; - "client_config" => client_config.spec_constants, - "eth2_config" => spec_constants - ); - return Err("Specification constant mismatch".into()); - } - /* * Zero-ports * @@ -255,7 +243,7 @@ pub fn get_config( /* * Load the eth2 testnet dir to obtain some additional config values. */ - let eth2_testnet_config: Eth2TestnetConfig = get_eth2_testnet_config(&cli_args)?; + let eth2_testnet_config = get_eth2_testnet_config(&cli_args)?; client_config.eth1.deposit_contract_address = format!("{:?}", eth2_testnet_config.deposit_contract_address()?); @@ -275,12 +263,12 @@ pub fn get_config( client_config.network.boot_nodes_enr.append(&mut boot_nodes) } - if let Some(genesis_state) = eth2_testnet_config.genesis_state { + if let Some(genesis_state_bytes) = eth2_testnet_config.genesis_state_bytes { // Note: re-serializing the genesis state is not so efficient, however it avoids adding // trait bounds to the `ClientGenesis` enum. This would have significant flow-on // effects. client_config.genesis = ClientGenesis::SszBytes { - genesis_state_bytes: genesis_state.as_ssz_bytes(), + genesis_state_bytes, }; } else { client_config.genesis = ClientGenesis::DepositContract; @@ -545,9 +533,7 @@ pub fn get_data_dir(cli_args: &ArgMatches) -> PathBuf { /// Try to parse the eth2 testnet config from the `testnet`, `testnet-dir` flags in that order. /// Returns the default hardcoded testnet if neither flags are set. -pub fn get_eth2_testnet_config( - cli_args: &ArgMatches, -) -> Result, String> { +pub fn get_eth2_testnet_config(cli_args: &ArgMatches) -> Result { let optional_testnet_config = if cli_args.is_present("testnet") { clap_utils::parse_hardcoded_network(cli_args, "testnet")? } else if cli_args.is_present("testnet-dir") { diff --git a/beacon_node/src/lib.rs b/beacon_node/src/lib.rs index 9a3504a3d..9fccfb1a5 100644 --- a/beacon_node/src/lib.rs +++ b/beacon_node/src/lib.rs @@ -53,12 +53,8 @@ impl ProductionBeaconNode { context: RuntimeContext, matches: ArgMatches<'static>, ) -> Result { - let client_config = get_config::( - &matches, - &context.eth2_config.spec_constants, - &context.eth2_config().spec, - context.log().clone(), - )?; + let client_config = + get_config::(&matches, &context.eth2_config().spec, context.log().clone())?; Self::new(context, client_config).await } diff --git a/book/src/cross-compiling.md b/book/src/cross-compiling.md index 837cc13a6..7dee3320e 100644 --- a/book/src/cross-compiling.md +++ b/book/src/cross-compiling.md @@ -18,17 +18,15 @@ project. The `Makefile` in the project contains four targets for cross-compiling: -- `build-x86_64`: builds an optimized version for x86_64 processors (suitable - for most users). -- `build-x86_64-portable`: builds a version x86_64 processors which avoids - using some modern CPU instructions that might cause an "illegal - instruction" error on older CPUs. -- `build-aarch64`: builds an optimized version for 64bit ARM processors +- `build-x86_64`: builds an optimized version for x86_64 processors (suitable for most users). + Supports Intel Broadwell (2014) and newer, and AMD Ryzen (2017) and newer. +- `build-x86_64-portable`: builds a version for x86_64 processors which avoids using some modern CPU + instructions that are incompatible with older CPUs. Suitable for pre-Broadwell/Ryzen CPUs. +- `build-aarch64`: builds an optimized version for 64-bit ARM processors (suitable for Raspberry Pi 4). -- `build-aarch64-portable`: builds a version 64 bit ARM processors which avoids - using some modern CPU instructions that might cause an "illegal - instruction" error on older CPUs. - +- `build-aarch64-portable`: builds a version for 64-bit ARM processors which avoids using some + modern CPU instructions. In practice, very few ARM processors lack the instructions necessary to + run the faster non-portable build. ### Example diff --git a/book/src/validator-create.md b/book/src/validator-create.md index b19c42793..101056140 100644 --- a/book/src/validator-create.md +++ b/book/src/validator-create.md @@ -43,9 +43,6 @@ OPTIONS: --secrets-dir The path where the validator keystore passwords will be stored. Defaults to ~/.lighthouse/{testnet}/secrets - -s, --spec - Specifies the default eth2 spec type. [default: mainnet] [possible values: mainnet, minimal, interop] - --testnet <testnet> Name of network lighthouse will connect to [possible values: medalla, altona] @@ -81,4 +78,4 @@ This command will: `--testnet` CLI param. - Store a password to the validators voting keypair in `~/.lighthouse/{testnet}/secrets`. -where `testnet` is the name of the testnet passed in the `--testnet` parameter (default is `medalla`). \ No newline at end of file +where `testnet` is the name of the testnet passed in the `--testnet` parameter (default is `medalla`). diff --git a/book/src/wallet-create.md b/book/src/wallet-create.md index 7e4731914..365580a8a 100644 --- a/book/src/wallet-create.md +++ b/book/src/wallet-create.md @@ -43,9 +43,6 @@ OPTIONS: A path to a file containing the password which will unlock the wallet. If the file does not exist, a random password will be generated and saved at that path. To avoid confusion, if the file does not already exist it must include a '.pass' suffix. - -s, --spec <TITLE> - Specifies the default eth2 spec type. [default: mainnet] [possible values: mainnet, minimal, interop] - -t, --testnet-dir <DIR> Path to directory containing eth2_testnet specs. Defaults to a hard-coded Lighthouse testnet. Only effective if there is no existing database. diff --git a/boot_node/Cargo.toml b/boot_node/Cargo.toml index 872df4bf0..385f6c4f3 100644 --- a/boot_node/Cargo.toml +++ b/boot_node/Cargo.toml @@ -1,6 +1,6 @@ [package] name = "boot_node" -version = "0.3.1" +version = "0.3.2" authors = ["Sigma Prime <contact@sigmaprime.io>"] edition = "2018" diff --git a/boot_node/src/config.rs b/boot_node/src/config.rs index edc3e3b21..842c98513 100644 --- a/boot_node/src/config.rs +++ b/boot_node/src/config.rs @@ -5,7 +5,6 @@ use eth2_libp2p::{ discovery::{create_enr_builder_from_config, use_or_load_enr}, load_private_key, CombinedKeyExt, NetworkConfig, }; -use eth2_testnet_config::Eth2TestnetConfig; use ssz::Encode; use std::convert::TryFrom; use std::marker::PhantomData; @@ -30,7 +29,7 @@ impl<T: EthSpec> TryFrom<&ArgMatches<'_>> for BootNodeConfig<T> { let data_dir = get_data_dir(matches); // Try and grab testnet config from input CLI params - let eth2_testnet_config: Option<Eth2TestnetConfig<T>> = { + let eth2_testnet_config = { if matches.is_present("testnet") { Some(get_eth2_testnet_config(&matches)?) } else { @@ -95,7 +94,9 @@ impl<T: EthSpec> TryFrom<&ArgMatches<'_>> for BootNodeConfig<T> { .apply_to_chain_spec::<T>(&T::default_spec()) .ok_or_else(|| "The loaded config is not compatible with the current spec")?; - if let Some(genesis_state) = config.genesis_state.as_ref() { + if config.beacon_state_is_known() { + let genesis_state = config.beacon_state::<T>()?; + slog::info!(logger, "Genesis state found"; "root" => genesis_state.canonical_root().to_string()); let enr_fork = spec.enr_fork_id( types::Slot::from(0u64), diff --git a/boot_node/src/lib.rs b/boot_node/src/lib.rs index 3b6b6f391..be3536f3e 100644 --- a/boot_node/src/lib.rs +++ b/boot_node/src/lib.rs @@ -8,12 +8,12 @@ mod config; mod server; pub use cli::cli_app; use config::BootNodeConfig; -use types::EthSpec; +use types::{EthSpec, EthSpecId}; const LOG_CHANNEL_SIZE: usize = 2048; /// Run the bootnode given the CLI configuration. -pub fn run(matches: &ArgMatches<'_>, debug_level: String) { +pub fn run(matches: &ArgMatches<'_>, eth_spec_id: EthSpecId, debug_level: String) { let debug_level = match debug_level.as_str() { "trace" => log::Level::Trace, "debug" => log::Level::Debug, @@ -48,11 +48,10 @@ pub fn run(matches: &ArgMatches<'_>, debug_level: String) { let log = slog_scope::logger(); // Run the main function emitting any errors - if let Err(e) = match matches.value_of("spec") { - Some("minimal") => main::<types::MinimalEthSpec>(matches, log), - Some("mainnet") => main::<types::MainnetEthSpec>(matches, log), - Some("interop") => main::<types::InteropEthSpec>(matches, log), - spec => unreachable!("Unknown spec configuration: {:?}", spec), + if let Err(e) = match eth_spec_id { + EthSpecId::Minimal => main::<types::MinimalEthSpec>(matches, log), + EthSpecId::Mainnet => main::<types::MainnetEthSpec>(matches, log), + EthSpecId::V012Legacy => main::<types::V012LegacyEthSpec>(matches, log), } { slog::crit!(slog_scope::logger(), "{}", e); } diff --git a/common/clap_utils/src/lib.rs b/common/clap_utils/src/lib.rs index d1a8eaf66..1eba1efac 100644 --- a/common/clap_utils/src/lib.rs +++ b/common/clap_utils/src/lib.rs @@ -5,7 +5,6 @@ use eth2_testnet_config::Eth2TestnetConfig; use ssz::Decode; use std::path::PathBuf; use std::str::FromStr; -use types::EthSpec; pub const BAD_TESTNET_DIR_MESSAGE: &str = "The hard-coded testnet directory was invalid. \ This happens when Lighthouse is migrating between spec versions \ @@ -14,10 +13,10 @@ pub const BAD_TESTNET_DIR_MESSAGE: &str = "The hard-coded testnet directory was /// Attempts to load the testnet dir at the path if `name` is in `matches`, returning an error if /// the path cannot be found or the testnet dir is invalid. -pub fn parse_testnet_dir<E: EthSpec>( +pub fn parse_testnet_dir( matches: &ArgMatches, name: &'static str, -) -> Result<Option<Eth2TestnetConfig<E>>, String> { +) -> Result<Option<Eth2TestnetConfig>, String> { let path = parse_required::<PathBuf>(matches, name)?; Eth2TestnetConfig::load(path.clone()) .map_err(|e| format!("Unable to open testnet dir at {:?}: {}", path, e)) @@ -26,10 +25,10 @@ pub fn parse_testnet_dir<E: EthSpec>( /// Attempts to load a hardcoded network config if `name` is in `matches`, returning an error if /// the name is not a valid network name. -pub fn parse_hardcoded_network<E: EthSpec>( +pub fn parse_hardcoded_network( matches: &ArgMatches, name: &str, -) -> Result<Option<Eth2TestnetConfig<E>>, String> { +) -> Result<Option<Eth2TestnetConfig>, String> { let network_name = parse_required::<String>(matches, name)?; Eth2TestnetConfig::constant(network_name.as_str()) } diff --git a/common/eth2_config/src/lib.rs b/common/eth2_config/src/lib.rs index 598aadbe1..0002a4d7c 100644 --- a/common/eth2_config/src/lib.rs +++ b/common/eth2_config/src/lib.rs @@ -1,7 +1,7 @@ use serde_derive::{Deserialize, Serialize}; use std::env; use std::path::PathBuf; -use types::ChainSpec; +use types::{ChainSpec, EthSpecId}; // A macro is used to define this constant so it can be used with `include_bytes!`. #[macro_export] @@ -19,14 +19,14 @@ pub const GENESIS_ZIP_FILE_NAME: &str = "genesis.ssz.zip"; #[derive(Debug, Clone, Serialize, Deserialize)] #[serde(default)] pub struct Eth2Config { - pub spec_constants: String, + pub eth_spec_id: EthSpecId, pub spec: ChainSpec, } impl Default for Eth2Config { fn default() -> Self { Self { - spec_constants: "minimal".to_string(), + eth_spec_id: EthSpecId::Minimal, spec: ChainSpec::minimal(), } } @@ -35,22 +35,22 @@ impl Default for Eth2Config { impl Eth2Config { pub fn mainnet() -> Self { Self { - spec_constants: "mainnet".to_string(), + eth_spec_id: EthSpecId::Mainnet, spec: ChainSpec::mainnet(), } } pub fn minimal() -> Self { Self { - spec_constants: "minimal".to_string(), + eth_spec_id: EthSpecId::Minimal, spec: ChainSpec::minimal(), } } - pub fn interop() -> Self { + pub fn v012_legacy() -> Self { Self { - spec_constants: "interop".to_string(), - spec: ChainSpec::interop(), + eth_spec_id: EthSpecId::V012Legacy, + spec: ChainSpec::v012_legacy(), } } } diff --git a/common/eth2_testnet_config/built_in_testnet_configs/altona/config.yaml b/common/eth2_testnet_config/built_in_testnet_configs/altona/config.yaml index bcda638e0..0a3bff66b 100644 --- a/common/eth2_testnet_config/built_in_testnet_configs/altona/config.yaml +++ b/common/eth2_testnet_config/built_in_testnet_configs/altona/config.yaml @@ -1,3 +1,4 @@ +CONFIG_NAME: "altona" MAX_COMMITTEES_PER_SLOT: 64 TARGET_COMMITTEE_SIZE: 128 MAX_VALIDATORS_PER_COMMITTEE: 2048 @@ -56,3 +57,4 @@ DOMAIN_SELECTION_PROOF: 0x05000000 DOMAIN_AGGREGATE_AND_PROOF: 0x06000000 DEPOSIT_CHAIN_ID: 5 DEPOSIT_NETWORK_ID: 5 +PROPORTIONAL_SLASHING_MULTIPLIER: 3 diff --git a/common/eth2_testnet_config/built_in_testnet_configs/medalla/config.yaml b/common/eth2_testnet_config/built_in_testnet_configs/medalla/config.yaml index dbe384f5c..7b0c8a3ff 100644 --- a/common/eth2_testnet_config/built_in_testnet_configs/medalla/config.yaml +++ b/common/eth2_testnet_config/built_in_testnet_configs/medalla/config.yaml @@ -1,3 +1,4 @@ +CONFIG_NAME: "medalla" MAX_COMMITTEES_PER_SLOT: 64 TARGET_COMMITTEE_SIZE: 128 MAX_VALIDATORS_PER_COMMITTEE: 2048 @@ -56,3 +57,4 @@ DOMAIN_SELECTION_PROOF: 0x05000000 DOMAIN_AGGREGATE_AND_PROOF: 0x06000000 DEPOSIT_CHAIN_ID: 5 DEPOSIT_NETWORK_ID: 5 +PROPORTIONAL_SLASHING_MULTIPLIER: 3 diff --git a/common/eth2_testnet_config/built_in_testnet_configs/spadina/config.yaml b/common/eth2_testnet_config/built_in_testnet_configs/spadina/config.yaml index 59b810531..5cc153174 100644 --- a/common/eth2_testnet_config/built_in_testnet_configs/spadina/config.yaml +++ b/common/eth2_testnet_config/built_in_testnet_configs/spadina/config.yaml @@ -1,3 +1,4 @@ +CONFIG_NAME: "spadina" MAX_COMMITTEES_PER_SLOT: 64 TARGET_COMMITTEE_SIZE: 128 MAX_VALIDATORS_PER_COMMITTEE: 2048 diff --git a/common/eth2_testnet_config/src/lib.rs b/common/eth2_testnet_config/src/lib.rs index 572eb168e..3f2c2ca96 100644 --- a/common/eth2_testnet_config/src/lib.rs +++ b/common/eth2_testnet_config/src/lib.rs @@ -13,11 +13,11 @@ use eth2_config::{ }; use enr::{CombinedKey, Enr}; -use ssz::{Decode, Encode}; +use ssz::Decode; use std::fs::{create_dir_all, File}; use std::io::{Read, Write}; use std::path::PathBuf; -use types::{Address, BeaconState, EthSpec, YamlConfig}; +use types::{Address, BeaconState, EthSpec, EthSpecId, YamlConfig}; pub const ADDRESS_FILE: &str = "deposit_contract.txt"; pub const DEPLOY_BLOCK_FILE: &str = "deploy_block.txt"; @@ -33,7 +33,7 @@ pub struct HardcodedNet { pub deploy_block: &'static [u8], pub boot_enr: &'static [u8], pub deposit_contract_address: &'static [u8], - pub genesis_state: &'static [u8], + pub genesis_state_bytes: &'static [u8], } macro_rules! define_net { @@ -47,7 +47,7 @@ macro_rules! define_net { deploy_block: $include_file!("../", "deploy_block.txt"), boot_enr: $include_file!("../", "boot_enr.yaml"), deposit_contract_address: $include_file!("../", "deposit_contract.txt"), - genesis_state: $include_file!("../", "genesis.ssz"), + genesis_state_bytes: $include_file!("../", "genesis.ssz"), } }}; } @@ -64,15 +64,15 @@ pub const DEFAULT_HARDCODED_TESTNET: &str = "medalla"; /// /// See the crate-level documentation for more details. #[derive(Clone, PartialEq, Debug)] -pub struct Eth2TestnetConfig<E: EthSpec> { +pub struct Eth2TestnetConfig { pub deposit_contract_address: String, pub deposit_contract_deploy_block: u64, pub boot_enr: Option<Vec<Enr<CombinedKey>>>, - pub genesis_state: Option<BeaconState<E>>, + pub genesis_state_bytes: Option<Vec<u8>>, pub yaml_config: Option<YamlConfig>, } -impl<E: EthSpec> Eth2TestnetConfig<E> { +impl Eth2TestnetConfig { /// Returns the default hard coded testnet. pub fn hard_coded_default() -> Result<Option<Self>, String> { Self::constant(DEFAULT_HARDCODED_TESTNET) @@ -89,15 +89,6 @@ impl<E: EthSpec> Eth2TestnetConfig<E> { /// Instantiates `Self` from a `HardcodedNet`. fn from_hardcoded_net(net: &HardcodedNet) -> Result<Self, String> { - let genesis_state = if net.genesis_state.is_empty() { - None - } else { - Some( - BeaconState::from_ssz_bytes(net.genesis_state) - .map_err(|e| format!("Unable to parse genesis state: {:?}", e))?, - ) - }; - Ok(Self { deposit_contract_address: serde_yaml::from_reader(net.deposit_contract_address) .map_err(|e| format!("Unable to parse contract address: {:?}", e))?, @@ -107,7 +98,8 @@ impl<E: EthSpec> Eth2TestnetConfig<E> { serde_yaml::from_reader(net.boot_enr) .map_err(|e| format!("Unable to parse boot enr: {:?}", e))?, ), - genesis_state, + genesis_state_bytes: Some(net.genesis_state_bytes.to_vec()) + .filter(|bytes| !bytes.is_empty()), yaml_config: Some( serde_yaml::from_reader(net.yaml_config) .map_err(|e| format!("Unable to parse yaml config: {:?}", e))?, @@ -115,9 +107,38 @@ impl<E: EthSpec> Eth2TestnetConfig<E> { }) } - // Write the files to the directory. - // - // Overwrites files if specified to do so. + /// Returns an identifier that should be used for selecting an `EthSpec` instance for this + /// testnet. + pub fn eth_spec_id(&self) -> Result<EthSpecId, String> { + self.yaml_config + .as_ref() + .ok_or_else(|| "YAML specification file missing".to_string()) + .and_then(|config| { + config + .eth_spec_id() + .ok_or_else(|| format!("Unknown CONFIG_NAME: {}", config.config_name)) + }) + } + + /// Returns `true` if this configuration contains a `BeaconState`. + pub fn beacon_state_is_known(&self) -> bool { + self.genesis_state_bytes.is_some() + } + + /// Attempts to deserialize `self.beacon_state`, returning an error if it's missing or invalid. + pub fn beacon_state<E: EthSpec>(&self) -> Result<BeaconState<E>, String> { + let genesis_state_bytes = self + .genesis_state_bytes + .as_ref() + .ok_or_else(|| "Genesis state is unknown".to_string())?; + + BeaconState::from_ssz_bytes(genesis_state_bytes) + .map_err(|e| format!("Genesis state SSZ bytes are invalid: {:?}", e)) + } + + /// Write the files to the directory. + /// + /// Overwrites files if specified to do so. pub fn write_to_file(&self, base_dir: PathBuf, overwrite: bool) -> Result<(), String> { if base_dir.exists() && !overwrite { return Err("Testnet directory already exists".to_string()); @@ -126,7 +147,7 @@ impl<E: EthSpec> Eth2TestnetConfig<E> { self.force_write_to_file(base_dir) } - // Write the files to the directory, even if the directory already exists. + /// Write the files to the directory, even if the directory already exists. pub fn force_write_to_file(&self, base_dir: PathBuf) -> Result<(), String> { create_dir_all(&base_dir) .map_err(|e| format!("Unable to create testnet directory: {:?}", e))?; @@ -167,13 +188,13 @@ impl<E: EthSpec> Eth2TestnetConfig<E> { } // The genesis state is a special case because it uses SSZ, not YAML. - if let Some(genesis_state) = &self.genesis_state { + if let Some(genesis_state_bytes) = &self.genesis_state_bytes { let file = base_dir.join(GENESIS_STATE_FILE); File::create(&file) .map_err(|e| format!("Unable to create {:?}: {:?}", file, e)) .and_then(|mut file| { - file.write_all(&genesis_state.as_ssz_bytes()) + file.write_all(genesis_state_bytes) .map_err(|e| format!("Unable to write {:?}: {:?}", file, e)) })?; } @@ -210,19 +231,15 @@ impl<E: EthSpec> Eth2TestnetConfig<E> { // The genesis state is a special case because it uses SSZ, not YAML. let genesis_file_path = base_dir.join(GENESIS_STATE_FILE); - let genesis_state = if genesis_file_path.exists() { - Some( - File::open(&genesis_file_path) - .map_err(|e| format!("Unable to open {:?}: {:?}", genesis_file_path, e)) - .and_then(|mut file| { - let mut bytes = vec![]; - file.read_to_end(&mut bytes) - .map_err(|e| format!("Unable to read {:?}: {:?}", file, e))?; - - BeaconState::from_ssz_bytes(&bytes) - .map_err(|e| format!("Unable to SSZ decode {:?}: {:?}", file, e)) - })?, - ) + let genesis_state_bytes = if genesis_file_path.exists() { + let mut bytes = vec![]; + File::open(&genesis_file_path) + .map_err(|e| format!("Unable to open {:?}: {:?}", genesis_file_path, e)) + .and_then(|mut file| { + file.read_to_end(&mut bytes) + .map_err(|e| format!("Unable to read {:?}: {:?}", file, e)) + })?; + Some(bytes) } else { None }; @@ -231,7 +248,7 @@ impl<E: EthSpec> Eth2TestnetConfig<E> { deposit_contract_address, deposit_contract_deploy_block, boot_enr, - genesis_state, + genesis_state_bytes, yaml_config, }) } @@ -250,18 +267,28 @@ impl<E: EthSpec> Eth2TestnetConfig<E> { #[cfg(test)] mod tests { use super::*; + use ssz::Encode; use tempdir::TempDir; - use types::{Eth1Data, Hash256, MainnetEthSpec, YamlConfig}; + use types::{Eth1Data, Hash256, V012LegacyEthSpec, YamlConfig}; - type E = MainnetEthSpec; + type E = V012LegacyEthSpec; #[test] fn hard_coded_nets_work() { for net in HARDCODED_NETS { let config = - Eth2TestnetConfig::<E>::from_hardcoded_net(net).expect(&format!("{:?}", net.name)); + Eth2TestnetConfig::from_hardcoded_net(net).expect(&format!("{:?}", net.name)); + + // Ensure we can parse the YAML config to a chain spec. + config + .yaml_config + .as_ref() + .unwrap() + .apply_to_chain_spec::<E>(&E::default_spec()) + .unwrap(); + assert_eq!( - config.genesis_state.is_some(), + config.genesis_state_bytes.is_some(), net.genesis_is_known, "{:?}", net.name @@ -298,11 +325,11 @@ mod tests { let deposit_contract_address = "0xBB9bc244D798123fDe783fCc1C72d3Bb8C189413".to_string(); let deposit_contract_deploy_block = 42; - let testnet: Eth2TestnetConfig<E> = Eth2TestnetConfig { + let testnet: Eth2TestnetConfig = Eth2TestnetConfig { deposit_contract_address, deposit_contract_deploy_block, boot_enr, - genesis_state, + genesis_state_bytes: genesis_state.as_ref().map(Encode::as_ssz_bytes), yaml_config, }; diff --git a/common/lighthouse_version/src/lib.rs b/common/lighthouse_version/src/lib.rs index fa3dbe706..28b05f52c 100644 --- a/common/lighthouse_version/src/lib.rs +++ b/common/lighthouse_version/src/lib.rs @@ -10,7 +10,7 @@ use target_info::Target; /// `Lighthouse/v0.2.0-1419501f2+` pub const VERSION: &str = git_version!( args = ["--always", "--dirty=+"], - prefix = "Lighthouse/v0.3.1-", + prefix = "Lighthouse/v0.3.2-", fallback = "unknown" ); diff --git a/common/task_executor/Cargo.toml b/common/task_executor/Cargo.toml index ec0f2cfbf..a0996c7d0 100644 --- a/common/task_executor/Cargo.toml +++ b/common/task_executor/Cargo.toml @@ -5,7 +5,7 @@ authors = ["Sigma Prime <contact@sigmaprime.io>"] edition = "2018" [dependencies] -tokio = "0.2.22" +tokio = { version = "0.2.22", features = ["rt-threaded", "macros", "blocking"] } slog = "2.5.2" futures = "0.3.5" exit-future = "0.2.0" diff --git a/consensus/types/src/chain_spec.rs b/consensus/types/src/chain_spec.rs index e755f6722..3744014d5 100644 --- a/consensus/types/src/chain_spec.rs +++ b/consensus/types/src/chain_spec.rs @@ -264,7 +264,6 @@ impl ChainSpec { hysteresis_quotient: 4, hysteresis_downward_multiplier: 1, hysteresis_upward_multiplier: 5, - proportional_slashing_multiplier: 3, /* * Gwei values @@ -283,7 +282,7 @@ impl ChainSpec { /* * Time parameters */ - genesis_delay: 172800, // 2 days + genesis_delay: 604800, // 7 days milliseconds_per_slot: 12_000, min_attestation_inclusion_delay: 1, min_seed_lookahead: Epoch::new(1), @@ -298,8 +297,9 @@ impl ChainSpec { base_reward_factor: 64, whistleblower_reward_quotient: 512, proposer_reward_quotient: 8, - inactivity_penalty_quotient: u64::pow(2, 24), - min_slashing_penalty_quotient: 32, + inactivity_penalty_quotient: u64::pow(2, 26), + min_slashing_penalty_quotient: 128, + proportional_slashing_multiplier: 1, /* * Signature domains @@ -320,7 +320,7 @@ impl ChainSpec { /* * Eth1 */ - eth1_follow_distance: 1_024, + eth1_follow_distance: 2048, seconds_per_eth1_block: 14, deposit_chain_id: 1, deposit_network_id: 1, @@ -359,6 +359,9 @@ impl ChainSpec { shard_committee_period: 64, genesis_delay: 300, milliseconds_per_slot: 6_000, + inactivity_penalty_quotient: u64::pow(2, 25), + min_slashing_penalty_quotient: 64, + proportional_slashing_multiplier: 2, safe_slots_to_update_justified: 2, network_id: 2, // lighthouse testnet network id deposit_chain_id: 5, @@ -368,17 +371,19 @@ impl ChainSpec { } } - /// Interop testing spec + /// Suits the `v0.12.3` version of the eth2 spec: + /// https://github.com/ethereum/eth2.0-specs/blob/v0.12.3/configs/mainnet/phase0.yaml /// - /// This allows us to customize a chain spec for interop testing. - pub fn interop() -> Self { + /// This method only needs to exist whilst we provide support for "legacy" testnets prior to v1.0.0 + /// (e.g., Medalla, Zinken, Spadina, Altona, etc.). + pub fn v012_legacy() -> Self { let boot_nodes = vec![]; Self { - milliseconds_per_slot: 12_000, - target_committee_size: 4, - shuffle_round_count: 10, - network_id: 13, + genesis_delay: 172_800, // 2 days + inactivity_penalty_quotient: u64::pow(2, 24), + min_slashing_penalty_quotient: 32, + eth1_follow_distance: 1024, boot_nodes, ..ChainSpec::mainnet() } @@ -448,8 +453,7 @@ mod tests { #[derive(Serialize, Deserialize, Debug, PartialEq, Clone)] #[serde(rename_all = "UPPERCASE", deny_unknown_fields)] pub struct YamlConfig { - #[serde(default)] - config_name: String, + pub config_name: String, // ChainSpec #[serde(with = "serde_utils::quoted_u64")] max_committees_per_slot: u64, @@ -481,10 +485,6 @@ pub struct YamlConfig { hysteresis_downward_multiplier: u64, #[serde(with = "serde_utils::quoted_u64")] hysteresis_upward_multiplier: u64, - // Proportional slashing multiplier defaults to 3 for compatibility with Altona and Medalla. - #[serde(default = "default_proportional_slashing_multiplier")] - #[serde(with = "serde_utils::quoted_u64")] - proportional_slashing_multiplier: u64, #[serde(with = "serde_utils::bytes_4_hex")] genesis_fork_version: [u8; 4], #[serde(with = "serde_utils::u8_hex")] @@ -514,6 +514,8 @@ pub struct YamlConfig { #[serde(with = "serde_utils::quoted_u64")] min_slashing_penalty_quotient: u64, #[serde(with = "serde_utils::quoted_u64")] + proportional_slashing_multiplier: u64, + #[serde(with = "serde_utils::quoted_u64")] safe_slots_to_update_justified: u64, #[serde(with = "serde_utils::u32_hex")] @@ -575,11 +577,6 @@ pub struct YamlConfig { deposit_contract_address: Address, } -// Compatibility shim for proportional slashing multpilier on Altona and Medalla. -fn default_proportional_slashing_multiplier() -> u64 { - 3 -} - impl Default for YamlConfig { fn default() -> Self { let chain_spec = MainnetEthSpec::default_spec(); @@ -594,6 +591,21 @@ fn milliseconds_to_seconds(millis: u64) -> u64 { /// Spec v0.12.1 impl YamlConfig { + /// Maps `self.config_name` to an identifier for an `EthSpec` instance. + /// + /// Returns `None` if there is no match. + pub fn eth_spec_id(&self) -> Option<EthSpecId> { + Some(match self.config_name.as_str() { + "mainnet" => EthSpecId::Mainnet, + "minimal" => EthSpecId::Minimal, + "zinken" => EthSpecId::V012Legacy, + "spadina" => EthSpecId::V012Legacy, + "medalla" => EthSpecId::V012Legacy, + "altona" => EthSpecId::V012Legacy, + _ => return None, + }) + } + pub fn from_spec<T: EthSpec>(spec: &ChainSpec) -> Self { Self { config_name: T::spec_name().to_string(), diff --git a/consensus/types/src/eth_spec.rs b/consensus/types/src/eth_spec.rs index 45e0a1cb4..27b3255dc 100644 --- a/consensus/types/src/eth_spec.rs +++ b/consensus/types/src/eth_spec.rs @@ -6,7 +6,45 @@ use ssz_types::typenum::{ Unsigned, U0, U1024, U1099511627776, U128, U16, U16777216, U2, U2048, U32, U4, U4096, U64, U65536, U8, U8192, }; -use std::fmt::Debug; +use std::fmt::{self, Debug}; +use std::str::FromStr; + +const MAINNET: &str = "mainnet"; +const MINIMAL: &str = "minimal"; +const LEGACY: &str = "v0.12-legacy"; + +/// Used to identify one of the `EthSpec` instances defined here. +#[derive(Copy, Clone, Debug, PartialEq, Serialize, Deserialize)] +#[serde(rename_all = "lowercase")] +pub enum EthSpecId { + Mainnet, + Minimal, + V012Legacy, +} + +impl FromStr for EthSpecId { + type Err = String; + + fn from_str(s: &str) -> Result<Self, Self::Err> { + match s { + MAINNET => Ok(EthSpecId::Mainnet), + MINIMAL => Ok(EthSpecId::Minimal), + LEGACY => Ok(EthSpecId::V012Legacy), + _ => Err(format!("Unknown eth spec: {}", s)), + } + } +} + +impl fmt::Display for EthSpecId { + fn fmt(&self, f: &mut fmt::Formatter<'_>) -> fmt::Result { + let s = match self { + EthSpecId::Mainnet => MAINNET, + EthSpecId::Minimal => MINIMAL, + EthSpecId::V012Legacy => LEGACY, + }; + write!(f, "{}", s) + } +} pub trait EthSpec: 'static + Default + Sync + Send + Clone + Debug + PartialEq + Eq { /* @@ -56,7 +94,7 @@ pub trait EthSpec: 'static + Default + Sync + Send + Clone + Debug + PartialEq + fn default_spec() -> ChainSpec; - fn spec_name() -> &'static str; + fn spec_name() -> EthSpecId; fn genesis_epoch() -> Epoch { Epoch::new(Self::GenesisEpoch::to_u64()) @@ -144,7 +182,7 @@ impl EthSpec for MainnetEthSpec { type MaxValidatorsPerCommittee = U2048; type GenesisEpoch = U0; type SlotsPerEpoch = U32; - type EpochsPerEth1VotingPeriod = U32; + type EpochsPerEth1VotingPeriod = U64; type SlotsPerHistoricalRoot = U8192; type EpochsPerHistoricalVector = U65536; type EpochsPerSlashingsVector = U8192; @@ -156,14 +194,14 @@ impl EthSpec for MainnetEthSpec { type MaxDeposits = U16; type MaxVoluntaryExits = U16; type MaxPendingAttestations = U4096; // 128 max attestations * 32 slots per epoch - type SlotsPerEth1VotingPeriod = U1024; // 32 epochs * 32 slots per epoch + type SlotsPerEth1VotingPeriod = U2048; // 64 epochs * 32 slots per epoch fn default_spec() -> ChainSpec { ChainSpec::mainnet() } - fn spec_name() -> &'static str { - "mainnet" + fn spec_name() -> EthSpecId { + EthSpecId::Mainnet } } @@ -203,28 +241,32 @@ impl EthSpec for MinimalEthSpec { ChainSpec::minimal() } - fn spec_name() -> &'static str { - "minimal" + fn spec_name() -> EthSpecId { + EthSpecId::Minimal } } pub type MinimalBeaconState = BeaconState<MinimalEthSpec>; -/// Interop testnet spec +/// Suits the `v0.12.3` version of the eth2 spec: +/// https://github.com/ethereum/eth2.0-specs/blob/v0.12.3/configs/mainnet/phase0.yaml +/// +/// This struct only needs to exist whilst we provide support for "legacy" testnets prior to v1.0.0 +/// (e.g., Medalla, Zinken, Spadina, Altona, etc.). #[cfg_attr(feature = "arbitrary-fuzz", derive(arbitrary::Arbitrary))] #[derive(Clone, PartialEq, Eq, Debug, Default, Serialize, Deserialize)] -pub struct InteropEthSpec; +pub struct V012LegacyEthSpec; -impl EthSpec for InteropEthSpec { - type SlotsPerEpoch = U8; - type EpochsPerEth1VotingPeriod = U2; - type SlotsPerHistoricalRoot = U64; - type EpochsPerHistoricalVector = U64; - type EpochsPerSlashingsVector = U64; - type MaxPendingAttestations = U1024; // 128 max attestations * 8 slots per epoch - type SlotsPerEth1VotingPeriod = U16; // 2 epochs * 8 slots per epoch +impl EthSpec for V012LegacyEthSpec { + type EpochsPerEth1VotingPeriod = U32; + type SlotsPerEth1VotingPeriod = U1024; // 32 epochs * 32 slots per epoch params_from_eth_spec!(MainnetEthSpec { + SlotsPerEpoch, + SlotsPerHistoricalRoot, + EpochsPerHistoricalVector, + EpochsPerSlashingsVector, + MaxPendingAttestations, JustificationBitsLength, SubnetBitfieldLength, MaxValidatorsPerCommittee, @@ -239,12 +281,10 @@ impl EthSpec for InteropEthSpec { }); fn default_spec() -> ChainSpec { - ChainSpec::interop() + ChainSpec::v012_legacy() } - fn spec_name() -> &'static str { - "interop" + fn spec_name() -> EthSpecId { + EthSpecId::V012Legacy } } - -pub type InteropBeaconState = BeaconState<InteropEthSpec>; diff --git a/consensus/types/src/lib.rs b/consensus/types/src/lib.rs index 65c1290d7..3ee69c726 100644 --- a/consensus/types/src/lib.rs +++ b/consensus/types/src/lib.rs @@ -73,6 +73,7 @@ pub use crate::deposit_data::DepositData; pub use crate::deposit_message::DepositMessage; pub use crate::enr_fork_id::EnrForkId; pub use crate::eth1_data::Eth1Data; +pub use crate::eth_spec::EthSpecId; pub use crate::fork::Fork; pub use crate::fork_data::ForkData; pub use crate::free_attestation::FreeAttestation; diff --git a/consensus/types/src/signed_beacon_block.rs b/consensus/types/src/signed_beacon_block.rs index 9ab342542..ac0e67fe0 100644 --- a/consensus/types/src/signed_beacon_block.rs +++ b/consensus/types/src/signed_beacon_block.rs @@ -8,6 +8,7 @@ use ssz_derive::{Decode, Encode}; use std::fmt; use test_random_derive::TestRandom; use tree_hash::TreeHash; +use tree_hash_derive::TreeHash; #[cfg_attr(feature = "arbitrary-fuzz", derive(arbitrary::Arbitrary))] #[derive(PartialEq, Eq, Hash, Clone, Copy)] @@ -41,7 +42,7 @@ impl From<SignedBeaconBlockHash> for Hash256 { /// /// Spec v0.12.1 #[cfg_attr(feature = "arbitrary-fuzz", derive(arbitrary::Arbitrary))] -#[derive(Debug, PartialEq, Clone, Serialize, Deserialize, Encode, Decode, TestRandom)] +#[derive(Debug, PartialEq, Clone, Serialize, Deserialize, Encode, Decode, TreeHash, TestRandom)] #[serde(bound = "E: EthSpec")] pub struct SignedBeaconBlock<E: EthSpec> { pub message: BeaconBlock<E>, diff --git a/crypto/bls/Cargo.toml b/crypto/bls/Cargo.toml index 7461a70b6..06fe5dd9d 100644 --- a/crypto/bls/Cargo.toml +++ b/crypto/bls/Cargo.toml @@ -7,7 +7,7 @@ edition = "2018" [dependencies] eth2_ssz = "0.1.2" tree_hash = "0.1.1" -milagro_bls = { git = "https://github.com/sigp/milagro_bls", branch = "paulh" } +milagro_bls = { git = "https://github.com/sigp/milagro_bls", tag = "v1.4.0" } rand = "0.7.3" serde = "1.0.116" serde_derive = "1.0.116" @@ -17,7 +17,7 @@ eth2_hashing = "0.1.0" ethereum-types = "0.9.2" arbitrary = { version = "0.4.6", features = ["derive"], optional = true } zeroize = { version = "1.1.1", features = ["zeroize_derive"] } -blst = { git = "https://github.com/sigp/blst.git", rev = "284f7059642851c760a09fb1708bcb59c7ca323c" } +blst = { git = "https://github.com/sigp/blst.git", rev = "7cf47864627ca479cad06c2a164f30d0cbaf16ce" } [features] default = ["supranational"] @@ -25,3 +25,4 @@ fake_crypto = [] milagro = [] supranational = [] supranational-portable = ["supranational", "blst/portable"] +supranational-force-adx = ["supranational", "blst/force-adx"] diff --git a/crypto/bls/src/generic_aggregate_public_key.rs b/crypto/bls/src/generic_aggregate_public_key.rs index 09002e94e..ad25a59e8 100644 --- a/crypto/bls/src/generic_aggregate_public_key.rs +++ b/crypto/bls/src/generic_aggregate_public_key.rs @@ -1,17 +1,5 @@ -use crate::{Error, PUBLIC_KEY_BYTES_LEN}; - /// Implemented on some struct from a BLS library so it may be used internally in this crate. -pub trait TAggregatePublicKey: Sized + Clone { - /// Initialize `Self` to the infinity value which can then have other public keys aggregated - /// upon it. - fn infinity() -> Self; - - /// Serialize `self` as compressed bytes. - fn serialize(&self) -> [u8; PUBLIC_KEY_BYTES_LEN]; - - /// Deserialize `self` from compressed bytes. - fn deserialize(bytes: &[u8]) -> Result<Self, Error>; -} +pub trait TAggregatePublicKey: Sized + Clone {} /* * Note: there is no immediate need for a `GenericAggregatePublicKey` struct. diff --git a/crypto/bls/src/generic_aggregate_signature.rs b/crypto/bls/src/generic_aggregate_signature.rs index 0517512f8..d0cfac848 100644 --- a/crypto/bls/src/generic_aggregate_signature.rs +++ b/crypto/bls/src/generic_aggregate_signature.rs @@ -183,13 +183,6 @@ where return false; } - if self.is_infinity - && pubkeys.len() == 1 - && pubkeys.first().map_or(false, |pk| pk.is_infinity) - { - return true; - } - match self.point.as_ref() { Some(point) => point.fast_aggregate_verify(msg, pubkeys), None => false, @@ -207,13 +200,6 @@ where return false; } - if self.is_infinity - && pubkeys.len() == 1 - && pubkeys.first().map_or(false, |pk| pk.is_infinity) - { - return true; - } - match self.point.as_ref() { Some(point) => point.aggregate_verify(msgs, pubkeys), None => false, diff --git a/crypto/bls/src/generic_public_key.rs b/crypto/bls/src/generic_public_key.rs index 7b22d2729..c5f164bb0 100644 --- a/crypto/bls/src/generic_public_key.rs +++ b/crypto/bls/src/generic_public_key.rs @@ -33,8 +33,6 @@ pub trait TPublicKey: Sized + Clone { pub struct GenericPublicKey<Pub> { /// The underlying point which performs *actual* cryptographic operations. point: Pub, - /// True if this point is equal to the `INFINITY_PUBLIC_KEY`. - pub(crate) is_infinity: bool, } impl<Pub> GenericPublicKey<Pub> @@ -42,8 +40,8 @@ where Pub: TPublicKey, { /// Instantiates `Self` from a `point`. - pub(crate) fn from_point(point: Pub, is_infinity: bool) -> Self { - Self { point, is_infinity } + pub(crate) fn from_point(point: Pub) -> Self { + Self { point } } /// Returns a reference to the underlying BLS point. @@ -63,10 +61,13 @@ where /// Deserialize `self` from compressed bytes. pub fn deserialize(bytes: &[u8]) -> Result<Self, Error> { - Ok(Self { - point: Pub::deserialize(bytes)?, - is_infinity: bytes == &INFINITY_PUBLIC_KEY[..], - }) + if bytes == &INFINITY_PUBLIC_KEY[..] { + Err(Error::InvalidInfinityPublicKey) + } else { + Ok(Self { + point: Pub::deserialize(bytes)?, + }) + } } } diff --git a/crypto/bls/src/generic_public_key_bytes.rs b/crypto/bls/src/generic_public_key_bytes.rs index 387eb91c9..3fc16dbfb 100644 --- a/crypto/bls/src/generic_public_key_bytes.rs +++ b/crypto/bls/src/generic_public_key_bytes.rs @@ -1,6 +1,6 @@ use crate::{ generic_public_key::{GenericPublicKey, TPublicKey}, - Error, INFINITY_PUBLIC_KEY, PUBLIC_KEY_BYTES_LEN, + Error, PUBLIC_KEY_BYTES_LEN, }; use serde::de::{Deserialize, Deserializer}; use serde::ser::{Serialize, Serializer}; @@ -32,8 +32,7 @@ where /// /// May fail if the bytes are invalid. pub fn decompress(&self) -> Result<GenericPublicKey<Pub>, Error> { - let is_infinity = self.bytes[..] == INFINITY_PUBLIC_KEY[..]; - Pub::deserialize(&self.bytes).map(|point| GenericPublicKey::from_point(point, is_infinity)) + GenericPublicKey::deserialize(&self.bytes) } } diff --git a/crypto/bls/src/generic_secret_key.rs b/crypto/bls/src/generic_secret_key.rs index 168fa191d..a0a433111 100644 --- a/crypto/bls/src/generic_secret_key.rs +++ b/crypto/bls/src/generic_secret_key.rs @@ -58,8 +58,7 @@ where /// Returns the public key that corresponds to self. pub fn public_key(&self) -> GenericPublicKey<Pub> { - let is_infinity = false; - GenericPublicKey::from_point(self.point.public_key(), is_infinity) + GenericPublicKey::from_point(self.point.public_key()) } /// Serialize `self` as compressed bytes. @@ -79,6 +78,8 @@ where got: bytes.len(), expected: SECRET_KEY_BYTES_LEN, }) + } else if bytes.iter().all(|b| *b == 0) { + Err(Error::InvalidZeroSecretKey) } else { Ok(Self { point: Sec::deserialize(bytes)?, diff --git a/crypto/bls/src/generic_signature.rs b/crypto/bls/src/generic_signature.rs index 44250d4a6..3f313ea1c 100644 --- a/crypto/bls/src/generic_signature.rs +++ b/crypto/bls/src/generic_signature.rs @@ -125,10 +125,6 @@ where { /// Returns `true` if `self` is a signature across `msg` by `pubkey`. pub fn verify(&self, pubkey: &GenericPublicKey<Pub>, msg: Hash256) -> bool { - if self.is_infinity && pubkey.is_infinity { - return true; - } - if let Some(point) = &self.point { point.verify(pubkey.point(), msg) } else { diff --git a/crypto/bls/src/impls/blst.rs b/crypto/bls/src/impls/blst.rs index 6a35637b4..b71fcbc63 100644 --- a/crypto/bls/src/impls/blst.rs +++ b/crypto/bls/src/impls/blst.rs @@ -4,7 +4,7 @@ use crate::{ generic_public_key::{GenericPublicKey, TPublicKey, PUBLIC_KEY_BYTES_LEN}, generic_secret_key::TSecretKey, generic_signature::{TSignature, SIGNATURE_BYTES_LEN}, - Error, Hash256, ZeroizeHash, INFINITY_PUBLIC_KEY, INFINITY_SIGNATURE, + Error, Hash256, ZeroizeHash, INFINITY_SIGNATURE, }; pub use blst::min_pk as blst_core; use blst::{blst_scalar, BLST_ERROR}; @@ -50,18 +50,12 @@ pub fn verify_signature_sets<'a>( let mut pks = Vec::with_capacity(sets.len()); for set in &sets { - // If this set is simply an infinity signature and infinity pubkey then skip verification. - // This has the effect of always declaring that this sig/pubkey combination is valid. - if set.signature.is_infinity - && set.signing_keys.len() == 1 - && set.signing_keys.first().map_or(false, |pk| pk.is_infinity) - { - continue; - } - // Generate random scalars. let mut vals = [0u64; 4]; - vals[0] = rng.gen(); + while vals[0] == 0 { + // Do not use zero + vals[0] = rng.gen(); + } let mut rand_i = std::mem::MaybeUninit::<blst_scalar>::uninit(); // TODO: remove this `unsafe` code-block once we get a safe option from `blst`. @@ -75,8 +69,12 @@ pub fn verify_signature_sets<'a>( // Grab a slice of the message, to satisfy the blst API. msgs_refs.push(set.message.as_bytes()); - // Convert the aggregate signature into a signature. if let Some(point) = set.signature.point() { + // Subgroup check the signature + if !point.0.subgroup_check() { + return false; + } + // Convert the aggregate signature into a signature. sigs.push(point.0.to_signature()) } else { // Any "empty" signature should cause a signature failure. @@ -103,12 +101,6 @@ pub fn verify_signature_sets<'a>( pks.push(blst_core::AggregatePublicKey::aggregate(&signing_keys).to_public_key()); } - // Due to an earlier check, the only case this can be empty is if all the sets consisted of - // infinity pubkeys/sigs. In such a case we wish to return `true`. - if msgs_refs.is_empty() { - return true; - } - let (sig_refs, pks_refs): (Vec<_>, Vec<_>) = sigs.iter().zip(pks.iter()).unzip(); let err = blst_core::Signature::verify_multiple_aggregate_signatures( @@ -124,7 +116,15 @@ impl TPublicKey for blst_core::PublicKey { } fn deserialize(bytes: &[u8]) -> Result<Self, Error> { - Self::uncompress(&bytes).map_err(Into::into) + // key_validate accepts uncompressed bytes too so enforce byte length here. + // It also does subgroup checks, noting infinity check is done in `generic_public_key.rs`. + if bytes.len() != PUBLIC_KEY_BYTES_LEN { + return Err(Error::InvalidByteLength { + got: bytes.len(), + expected: PUBLIC_KEY_BYTES_LEN, + }); + } + Self::key_validate(&bytes).map_err(Into::into) } } @@ -145,25 +145,7 @@ impl PartialEq for BlstAggregatePublicKey { } } -impl TAggregatePublicKey for BlstAggregatePublicKey { - fn infinity() -> Self { - blst_core::PublicKey::from_bytes(&INFINITY_PUBLIC_KEY) - .map(|pk| blst_core::AggregatePublicKey::from_public_key(&pk)) - .map(Self) - .expect("should decode infinity public key") - } - - fn serialize(&self) -> [u8; PUBLIC_KEY_BYTES_LEN] { - self.0.to_public_key().compress() - } - - fn deserialize(bytes: &[u8]) -> Result<Self, Error> { - blst_core::PublicKey::from_bytes(&bytes) - .map_err(Into::into) - .map(|pk| blst_core::AggregatePublicKey::from_public_key(&pk)) - .map(Self) - } -} +impl TAggregatePublicKey for BlstAggregatePublicKey {} impl TSignature<blst_core::PublicKey> for blst_core::Signature { fn serialize(&self) -> [u8; SIGNATURE_BYTES_LEN] { @@ -175,6 +157,9 @@ impl TSignature<blst_core::PublicKey> for blst_core::Signature { } fn verify(&self, pubkey: &blst_core::PublicKey, msg: Hash256) -> bool { + if !self.subgroup_check() { + return false; + } self.verify(msg.as_bytes(), DST, &[], pubkey) == BLST_ERROR::BLST_SUCCESS } } @@ -232,6 +217,9 @@ impl TAggregateSignature<blst_core::PublicKey, BlstAggregatePublicKey, blst_core ) -> bool { let pubkeys = pubkeys.iter().map(|pk| pk.point()).collect::<Vec<_>>(); let signature = self.0.clone().to_signature(); + if !signature.subgroup_check() { + return false; + } signature.fast_aggregate_verify(msg.as_bytes(), DST, &pubkeys) == BLST_ERROR::BLST_SUCCESS } @@ -243,6 +231,9 @@ impl TAggregateSignature<blst_core::PublicKey, BlstAggregatePublicKey, blst_core let pubkeys = pubkeys.iter().map(|pk| pk.point()).collect::<Vec<_>>(); let msgs = msgs.iter().map(|hash| hash.as_bytes()).collect::<Vec<_>>(); let signature = self.0.clone().to_signature(); + if !signature.subgroup_check() { + return false; + } signature.aggregate_verify(&msgs, DST, &pubkeys) == BLST_ERROR::BLST_SUCCESS } } diff --git a/crypto/bls/src/impls/fake_crypto.rs b/crypto/bls/src/impls/fake_crypto.rs index d5501d587..72cc641aa 100644 --- a/crypto/bls/src/impls/fake_crypto.rs +++ b/crypto/bls/src/impls/fake_crypto.rs @@ -63,25 +63,7 @@ impl PartialEq for PublicKey { #[derive(Clone)] pub struct AggregatePublicKey([u8; PUBLIC_KEY_BYTES_LEN]); -impl TAggregatePublicKey for AggregatePublicKey { - fn infinity() -> Self { - Self([0; PUBLIC_KEY_BYTES_LEN]) - } - - fn serialize(&self) -> [u8; PUBLIC_KEY_BYTES_LEN] { - let mut bytes = [0; PUBLIC_KEY_BYTES_LEN]; - bytes[..].copy_from_slice(&self.0); - bytes - } - - fn deserialize(bytes: &[u8]) -> Result<Self, Error> { - let mut key = [0; PUBLIC_KEY_BYTES_LEN]; - - key[..].copy_from_slice(&bytes); - - Ok(Self(key)) - } -} +impl TAggregatePublicKey for AggregatePublicKey {} impl Eq for AggregatePublicKey {} diff --git a/crypto/bls/src/impls/milagro.rs b/crypto/bls/src/impls/milagro.rs index 2830c9987..829c5aa3d 100644 --- a/crypto/bls/src/impls/milagro.rs +++ b/crypto/bls/src/impls/milagro.rs @@ -4,7 +4,7 @@ use crate::{ generic_public_key::{GenericPublicKey, TPublicKey, PUBLIC_KEY_BYTES_LEN}, generic_secret_key::{TSecretKey, SECRET_KEY_BYTES_LEN}, generic_signature::{TSignature, SIGNATURE_BYTES_LEN}, - Error, Hash256, ZeroizeHash, INFINITY_PUBLIC_KEY, + Error, Hash256, ZeroizeHash, }; pub use milagro_bls as milagro; use rand::thread_rng; @@ -86,21 +86,7 @@ impl TPublicKey for milagro::PublicKey { } } -impl TAggregatePublicKey for milagro::AggregatePublicKey { - fn infinity() -> Self { - Self::from_bytes(&INFINITY_PUBLIC_KEY).expect("should decode infinity public key") - } - - fn serialize(&self) -> [u8; PUBLIC_KEY_BYTES_LEN] { - let mut bytes = [0; PUBLIC_KEY_BYTES_LEN]; - bytes[..].copy_from_slice(&self.as_bytes()); - bytes - } - - fn deserialize(bytes: &[u8]) -> Result<Self, Error> { - Self::from_bytes(&bytes).map_err(Into::into) - } -} +impl TAggregatePublicKey for milagro::AggregatePublicKey {} impl TSignature<milagro::PublicKey> for milagro::Signature { fn serialize(&self) -> [u8; SIGNATURE_BYTES_LEN] { diff --git a/crypto/bls/src/lib.rs b/crypto/bls/src/lib.rs index a22fdd8bf..40a120fba 100644 --- a/crypto/bls/src/lib.rs +++ b/crypto/bls/src/lib.rs @@ -56,6 +56,10 @@ pub enum Error { InvalidByteLength { got: usize, expected: usize }, /// The provided secret key bytes were an incorrect length. InvalidSecretKeyLength { got: usize, expected: usize }, + /// The public key represents the point at infinity, which is invalid. + InvalidInfinityPublicKey, + /// The secret key is all zero bytes, which is invalid. + InvalidZeroSecretKey, } impl From<AmclError> for Error { diff --git a/crypto/bls/tests/tests.rs b/crypto/bls/tests/tests.rs index 676783718..872049414 100644 --- a/crypto/bls/tests/tests.rs +++ b/crypto/bls/tests/tests.rs @@ -1,4 +1,4 @@ -use bls::{Hash256, INFINITY_PUBLIC_KEY, INFINITY_SIGNATURE}; +use bls::{Hash256, INFINITY_SIGNATURE, SECRET_KEY_BYTES_LEN}; use ssz::{Decode, Encode}; use std::borrow::Cow; use std::fmt::Debug; @@ -19,6 +19,11 @@ macro_rules! test_suite { SecretKey::deserialize(&secret_bytes).unwrap() } + #[test] + fn invalid_zero_secret_key() { + assert!(SecretKey::deserialize(&[0; SECRET_KEY_BYTES_LEN]).is_err()); + } + #[test] fn infinity_agg_sig() { assert_eq!( @@ -131,11 +136,6 @@ macro_rules! test_suite { self } - pub fn infinity_pubkey(mut self) -> Self { - self.pubkey = PublicKey::deserialize(&INFINITY_PUBLIC_KEY[..]).unwrap(); - self - } - pub fn assert_verify(self, is_valid: bool) { assert_eq!(self.sig.verify(&self.pubkey, self.msg), is_valid); @@ -153,14 +153,6 @@ macro_rules! test_suite { SignatureTester::default().assert_verify(true) } - #[test] - fn infinity_signature_is_valid_with_infinity_pubkey() { - SignatureTester::default() - .infinity_sig() - .infinity_pubkey() - .assert_verify(true) - } - #[test] fn infinity_signature_is_invalid_with_standard_pubkey() { SignatureTester::default() @@ -168,13 +160,6 @@ macro_rules! test_suite { .assert_verify(false) } - #[test] - fn standard_signature_is_invalid_with_infinity_pubkey() { - SignatureTester::default() - .infinity_pubkey() - .assert_verify(false) - } - /// A helper struct for composing tests via the builder pattern. struct AggregateSignatureTester { sig: AggregateSignature, @@ -234,17 +219,6 @@ macro_rules! test_suite { self } - pub fn single_infinity_pubkey(mut self) -> Self { - self.pubkeys = vec![PublicKey::deserialize(&INFINITY_PUBLIC_KEY[..]).unwrap()]; - self - } - - pub fn push_infinity_pubkey(mut self) -> Self { - self.pubkeys - .push(PublicKey::deserialize(&INFINITY_PUBLIC_KEY[..]).unwrap()); - self - } - pub fn assert_single_message_verify(self, is_valid: bool) { assert!(self.msgs.len() == 1); let msg = self.msgs.first().unwrap(); @@ -304,15 +278,6 @@ macro_rules! test_suite { .assert_single_message_verify(false) } - /// The infinity signature and one infinity pubkey should verify. - #[test] - fn fast_aggregate_verify_infinity_signature_with_one_infinity_pubkey() { - AggregateSignatureTester::new_with_single_msg(1) - .infinity_sig() - .single_infinity_pubkey() - .assert_single_message_verify(true) - } - /// Adding a infinity signature (without an infinity pubkey) should verify. #[test] fn fast_aggregate_verify_with_one_aggregated_infinity_sig() { @@ -332,34 +297,6 @@ macro_rules! test_suite { .assert_single_message_verify(true) } - /// Adding a infinity pubkey and an infinity signature should verify. - #[test] - fn fast_aggregate_verify_with_one_additional_infinity_pubkey_and_matching_sig() { - AggregateSignatureTester::new_with_single_msg(1) - .aggregate_infinity_sig() - .push_infinity_pubkey() - .assert_single_message_verify(true) - } - - /// Adding a single infinity pubkey **without** updating the signature **should verify**. - #[test] - fn fast_aggregate_verify_with_one_additional_infinity_pubkey() { - AggregateSignatureTester::new_with_single_msg(1) - .push_infinity_pubkey() - .assert_single_message_verify(true) - } - - /// Adding multiple infinity pubkeys **without** updating the signature **should verify**. - #[test] - fn fast_aggregate_verify_with_four_additional_infinity_pubkeys() { - AggregateSignatureTester::new_with_single_msg(1) - .push_infinity_pubkey() - .push_infinity_pubkey() - .push_infinity_pubkey() - .push_infinity_pubkey() - .assert_single_message_verify(true) - } - /// The wrong signature should not verify. #[test] fn fast_aggregate_verify_wrong_signature() { @@ -463,18 +400,6 @@ macro_rules! test_suite { self } - pub fn push_invalid_sig_infinity_set(mut self) -> Self { - let mut signature = AggregateSignature::infinity(); - signature.add_assign(&secret_from_u64(42).sign(Hash256::zero())); - self.owned_sets.push(OwnedSignatureSet { - signature, - signing_keys: vec![PublicKey::deserialize(&INFINITY_PUBLIC_KEY).unwrap()], - message: Hash256::zero(), - should_be_valid: false, - }); - self - } - pub fn push_invalid_pubkey_infinity_set(mut self) -> Self { self.owned_sets.push(OwnedSignatureSet { signature: AggregateSignature::deserialize(&INFINITY_SIGNATURE).unwrap(), @@ -485,16 +410,6 @@ macro_rules! test_suite { self } - pub fn push_valid_infinity_set(mut self) -> Self { - self.owned_sets.push(OwnedSignatureSet { - signature: AggregateSignature::deserialize(&INFINITY_SIGNATURE).unwrap(), - signing_keys: vec![PublicKey::deserialize(&INFINITY_PUBLIC_KEY).unwrap()], - message: Hash256::zero(), - should_be_valid: true, - }); - self - } - pub fn run_checks(self) { assert!(!self.owned_sets.is_empty(), "empty test is meaningless"); @@ -568,22 +483,6 @@ macro_rules! test_suite { .run_checks() } - #[test] - fn signature_set_1_valid_set_with_1_infinity_set() { - SignatureSetTester::default() - .push_valid_infinity_set() - .run_checks() - } - - #[test] - fn signature_set_3_sets_with_one_valid_infinity_set() { - SignatureSetTester::default() - .push_valid_set(2) - .push_valid_infinity_set() - .push_valid_set(2) - .run_checks() - } - #[test] fn signature_set_3_sets_with_one_invalid_pubkey_infinity_set() { SignatureSetTester::default() @@ -592,15 +491,6 @@ macro_rules! test_suite { .push_valid_set(2) .run_checks() } - - #[test] - fn signature_set_3_sets_with_one_invalid_sig_infinity_set() { - SignatureSetTester::default() - .push_valid_set(2) - .push_invalid_sig_infinity_set() - .push_valid_set(2) - .run_checks() - } }; } diff --git a/lcli/Cargo.toml b/lcli/Cargo.toml index 2993ef7a2..66d4948b5 100644 --- a/lcli/Cargo.toml +++ b/lcli/Cargo.toml @@ -1,7 +1,7 @@ [package] name = "lcli" description = "Lighthouse CLI (modeled after zcli)" -version = "0.3.1" +version = "0.3.2" authors = ["Paul Hauner <paul@paulhauner.com>"] edition = "2018" diff --git a/lcli/src/eth1_genesis.rs b/lcli/src/eth1_genesis.rs index 9fd0757d8..eb0b78f74 100644 --- a/lcli/src/eth1_genesis.rs +++ b/lcli/src/eth1_genesis.rs @@ -2,6 +2,7 @@ use clap::ArgMatches; use environment::Environment; use eth2_testnet_config::Eth2TestnetConfig; use genesis::{Eth1Config, Eth1GenesisService}; +use ssz::Encode; use std::path::PathBuf; use std::time::Duration; use types::EthSpec; @@ -24,8 +25,7 @@ pub fn run<T: EthSpec>(mut env: Environment<T>, matches: &ArgMatches<'_>) -> Res .expect("should locate home directory") }); - let mut eth2_testnet_config: Eth2TestnetConfig<T> = - Eth2TestnetConfig::load(testnet_dir.clone())?; + let mut eth2_testnet_config = Eth2TestnetConfig::load(testnet_dir.clone())?; let spec = eth2_testnet_config .yaml_config @@ -35,7 +35,7 @@ pub fn run<T: EthSpec>(mut env: Environment<T>, matches: &ArgMatches<'_>) -> Res .ok_or_else(|| { format!( "The loaded config is not compatible with the {} spec", - &env.core_context().eth2_config.spec_constants + &env.core_context().eth2_config.eth_spec_id ) })?; @@ -51,10 +51,10 @@ pub fn run<T: EthSpec>(mut env: Environment<T>, matches: &ArgMatches<'_>) -> Res env.runtime().block_on(async { let _ = genesis_service - .wait_for_genesis_state(ETH1_GENESIS_UPDATE_INTERVAL, spec) + .wait_for_genesis_state::<T>(ETH1_GENESIS_UPDATE_INTERVAL, spec) .await .map(move |genesis_state| { - eth2_testnet_config.genesis_state = Some(genesis_state); + eth2_testnet_config.genesis_state_bytes = Some(genesis_state.as_ssz_bytes()); eth2_testnet_config.force_write_to_file(testnet_dir) }) .map_err(|e| format!("Failed to find genesis: {}", e))?; diff --git a/lcli/src/interop_genesis.rs b/lcli/src/interop_genesis.rs index 28cd2625b..68414c856 100644 --- a/lcli/src/interop_genesis.rs +++ b/lcli/src/interop_genesis.rs @@ -3,6 +3,7 @@ use clap_utils::parse_ssz_optional; use environment::Environment; use eth2_testnet_config::Eth2TestnetConfig; use genesis::interop_genesis_state; +use ssz::Encode; use std::path::PathBuf; use std::time::{SystemTime, UNIX_EPOCH}; use types::{test_utils::generate_deterministic_keypairs, EthSpec}; @@ -35,8 +36,7 @@ pub fn run<T: EthSpec>(mut env: Environment<T>, matches: &ArgMatches) -> Result< .expect("should locate home directory") }); - let mut eth2_testnet_config: Eth2TestnetConfig<T> = - Eth2TestnetConfig::load(testnet_dir.clone())?; + let mut eth2_testnet_config = Eth2TestnetConfig::load(testnet_dir.clone())?; let mut spec = eth2_testnet_config .yaml_config @@ -46,7 +46,7 @@ pub fn run<T: EthSpec>(mut env: Environment<T>, matches: &ArgMatches) -> Result< .ok_or_else(|| { format!( "The loaded config is not compatible with the {} spec", - &env.core_context().eth2_config.spec_constants + &env.core_context().eth2_config.eth_spec_id ) })?; @@ -55,9 +55,9 @@ pub fn run<T: EthSpec>(mut env: Environment<T>, matches: &ArgMatches) -> Result< } let keypairs = generate_deterministic_keypairs(validator_count); - let genesis_state = interop_genesis_state(&keypairs, genesis_time, &spec)?; + let genesis_state = interop_genesis_state::<T>(&keypairs, genesis_time, &spec)?; - eth2_testnet_config.genesis_state = Some(genesis_state); + eth2_testnet_config.genesis_state_bytes = Some(genesis_state.as_ssz_bytes()); eth2_testnet_config.force_write_to_file(testnet_dir)?; Ok(()) diff --git a/lcli/src/main.rs b/lcli/src/main.rs index a8663556a..596ee3e89 100644 --- a/lcli/src/main.rs +++ b/lcli/src/main.rs @@ -20,9 +20,12 @@ use parse_hex::run_parse_hex; use std::fs::File; use std::path::PathBuf; use std::process; +use std::str::FromStr; use std::time::{SystemTime, UNIX_EPOCH}; use transition_blocks::run_transition_blocks; -use types::{test_utils::TestingBeaconStateBuilder, EthSpec, MainnetEthSpec, MinimalEthSpec}; +use types::{ + test_utils::TestingBeaconStateBuilder, EthSpec, EthSpecId, MainnetEthSpec, MinimalEthSpec, +}; fn main() { simple_logger::SimpleLogger::new() @@ -482,25 +485,21 @@ fn main() { ) .get_matches(); - macro_rules! run_with_spec { - ($env_builder: expr) => { - match run($env_builder, &matches) { - Ok(()) => process::exit(0), - Err(e) => { - println!("Failed to run lcli: {}", e); - process::exit(1) - } - } - }; - } + let result = matches + .value_of("spec") + .ok_or_else(|| "Missing --spec flag".to_string()) + .and_then(FromStr::from_str) + .and_then(|eth_spec_id| match eth_spec_id { + EthSpecId::Minimal => run(EnvironmentBuilder::minimal(), &matches), + EthSpecId::Mainnet => run(EnvironmentBuilder::mainnet(), &matches), + EthSpecId::V012Legacy => run(EnvironmentBuilder::v012_legacy(), &matches), + }); - match matches.value_of("spec") { - Some("minimal") => run_with_spec!(EnvironmentBuilder::minimal()), - Some("mainnet") => run_with_spec!(EnvironmentBuilder::mainnet()), - Some("interop") => run_with_spec!(EnvironmentBuilder::interop()), - spec => { - // This path should be unreachable due to slog having a `default_value` - unreachable!("Unknown spec configuration: {:?}", spec); + match result { + Ok(()) => process::exit(0), + Err(e) => { + println!("Failed to run lcli: {}", e); + process::exit(1) } } } diff --git a/lcli/src/new_testnet.rs b/lcli/src/new_testnet.rs index fc60e8c98..89affc392 100644 --- a/lcli/src/new_testnet.rs +++ b/lcli/src/new_testnet.rs @@ -51,11 +51,11 @@ pub fn run<T: EthSpec>(matches: &ArgMatches) -> Result<(), String> { spec.genesis_fork_version = v; } - let testnet: Eth2TestnetConfig<T> = Eth2TestnetConfig { + let testnet = Eth2TestnetConfig { deposit_contract_address: format!("{:?}", deposit_contract_address), deposit_contract_deploy_block, boot_enr: Some(vec![]), - genesis_state: None, + genesis_state_bytes: None, yaml_config: Some(YamlConfig::from_spec::<T>(&spec)), }; diff --git a/lighthouse/Cargo.toml b/lighthouse/Cargo.toml index e580f2bf4..db66339b0 100644 --- a/lighthouse/Cargo.toml +++ b/lighthouse/Cargo.toml @@ -1,6 +1,6 @@ [package] name = "lighthouse" -version = "0.3.1" +version = "0.3.2" authors = ["Sigma Prime <contact@sigmaprime.io>"] edition = "2018" @@ -9,6 +9,8 @@ edition = "2018" write_ssz_files = ["beacon_node/write_ssz_files"] # Compiles the BLS crypto code so that the binary is portable across machines. portable = ["bls/supranational-portable"] +# Compiles BLST so that it always uses ADX instructions. +modern = ["bls/supranational-force-adx"] # Uses the slower Milagro BLS library, which is written in native Rust. milagro = ["bls/milagro"] diff --git a/lighthouse/environment/src/lib.rs b/lighthouse/environment/src/lib.rs index a58930842..7f7eb8216 100644 --- a/lighthouse/environment/src/lib.rs +++ b/lighthouse/environment/src/lib.rs @@ -24,7 +24,7 @@ use std::path::PathBuf; use std::time::{SystemTime, UNIX_EPOCH}; use task_executor::TaskExecutor; use tokio::runtime::{Builder as RuntimeBuilder, Runtime}; -use types::{EthSpec, InteropEthSpec, MainnetEthSpec, MinimalEthSpec}; +use types::{EthSpec, MainnetEthSpec, MinimalEthSpec, V012LegacyEthSpec}; pub const ETH2_CONFIG_FILENAME: &str = "eth2-spec.toml"; const LOG_CHANNEL_SIZE: usize = 2048; @@ -37,7 +37,7 @@ pub struct EnvironmentBuilder<E: EthSpec> { log: Option<Logger>, eth_spec_instance: E, eth2_config: Eth2Config, - testnet: Option<Eth2TestnetConfig<E>>, + testnet: Option<Eth2TestnetConfig>, } impl EnvironmentBuilder<MinimalEthSpec> { @@ -66,14 +66,14 @@ impl EnvironmentBuilder<MainnetEthSpec> { } } -impl EnvironmentBuilder<InteropEthSpec> { - /// Creates a new builder using the `interop` eth2 specification. - pub fn interop() -> Self { +impl EnvironmentBuilder<V012LegacyEthSpec> { + /// Creates a new builder using the v0.12.x eth2 specification. + pub fn v012_legacy() -> Self { Self { runtime: None, log: None, - eth_spec_instance: InteropEthSpec, - eth2_config: Eth2Config::interop(), + eth_spec_instance: V012LegacyEthSpec, + eth2_config: Eth2Config::v012_legacy(), testnet: None, } } @@ -238,7 +238,7 @@ impl<E: EthSpec> EnvironmentBuilder<E> { /// Adds a testnet configuration to the environment. pub fn eth2_testnet_config( mut self, - eth2_testnet_config: Eth2TestnetConfig<E>, + eth2_testnet_config: Eth2TestnetConfig, ) -> Result<Self, String> { // Create a new chain spec from the default configuration. self.eth2_config.spec = eth2_testnet_config @@ -249,7 +249,7 @@ impl<E: EthSpec> EnvironmentBuilder<E> { .ok_or_else(|| { format!( "The loaded config is not compatible with the {} spec", - &self.eth2_config.spec_constants + &self.eth2_config.eth_spec_id ) })?; @@ -261,7 +261,7 @@ impl<E: EthSpec> EnvironmentBuilder<E> { /// Optionally adds a testnet configuration to the environment. pub fn optional_eth2_testnet_config( self, - optional_config: Option<Eth2TestnetConfig<E>>, + optional_config: Option<Eth2TestnetConfig>, ) -> Result<Self, String> { if let Some(config) = optional_config { self.eth2_testnet_config(config) @@ -339,7 +339,7 @@ pub struct Environment<E: EthSpec> { log: Logger, eth_spec_instance: E, pub eth2_config: Eth2Config, - pub testnet: Option<Eth2TestnetConfig<E>>, + pub testnet: Option<Eth2TestnetConfig>, } impl<E: EthSpec> Environment<E> { diff --git a/lighthouse/environment/tests/environment_builder.rs b/lighthouse/environment/tests/environment_builder.rs index 8594825a5..b2aabf761 100644 --- a/lighthouse/environment/tests/environment_builder.rs +++ b/lighthouse/environment/tests/environment_builder.rs @@ -3,17 +3,17 @@ use environment::EnvironmentBuilder; use eth2_testnet_config::Eth2TestnetConfig; use std::path::PathBuf; -use types::{MainnetEthSpec, YamlConfig}; +use types::{V012LegacyEthSpec, YamlConfig}; -fn builder() -> EnvironmentBuilder<MainnetEthSpec> { - EnvironmentBuilder::mainnet() +fn builder() -> EnvironmentBuilder<V012LegacyEthSpec> { + EnvironmentBuilder::v012_legacy() .single_thread_tokio_runtime() .expect("should set runtime") .null_logger() .expect("should set logger") } -fn eth2_testnet_config() -> Option<Eth2TestnetConfig<MainnetEthSpec>> { +fn eth2_testnet_config() -> Option<Eth2TestnetConfig> { Eth2TestnetConfig::hard_coded_default().expect("should decode hard_coded params") } diff --git a/lighthouse/src/main.rs b/lighthouse/src/main.rs index 65ed602fe..8ce6fff4e 100644 --- a/lighthouse/src/main.rs +++ b/lighthouse/src/main.rs @@ -7,7 +7,7 @@ use lighthouse_version::VERSION; use slog::{crit, info, warn}; use std::path::PathBuf; use std::process::exit; -use types::EthSpec; +use types::{EthSpec, EthSpecId}; use validator_client::ProductionValidatorClient; pub const ETH2_CONFIG_FILENAME: &str = "eth2-spec.toml"; @@ -15,6 +15,8 @@ pub const ETH2_CONFIG_FILENAME: &str = "eth2-spec.toml"; fn bls_library_name() -> &'static str { if cfg!(feature = "portable") { "blst-portable" + } else if cfg!(feature = "modern") { + "blst-modern" } else if cfg!(feature = "milagro") { "milagro" } else { @@ -43,12 +45,11 @@ fn main() { Arg::with_name("spec") .short("s") .long("spec") - .value_name("TITLE") - .help("Specifies the default eth2 spec type.") + .value_name("DEPRECATED") + .help("This flag is deprecated, it will be disallowed in a future release. This \ + value is now derived from the --testnet or --testnet-dir flags.") .takes_value(true) - .possible_values(&["mainnet", "minimal", "interop"]) .global(true) - .default_value("mainnet"), ) .arg( Arg::with_name("env_log") @@ -126,37 +127,35 @@ fn main() { .subcommand(account_manager::cli_app()) .get_matches(); - // boot node subcommand circumvents the environment - if let Some(bootnode_matches) = matches.subcommand_matches("boot_node") { - // The bootnode uses the main debug-level flag - let debug_info = matches - .value_of("debug-level") - .expect("Debug-level must be present") - .into(); - boot_node::run(bootnode_matches, debug_info); - return; - } - // Debugging output for libp2p and external crates. if matches.is_present("env_log") { Builder::from_env(Env::default()).init(); } - macro_rules! run_with_spec { - ($env_builder: expr) => { - run($env_builder, &matches) - }; - } + let result = load_testnet_config(&matches).and_then(|testnet_config| { + let eth_spec_id = testnet_config.eth_spec_id()?; - let result = match matches.value_of("spec") { - Some("minimal") => run_with_spec!(EnvironmentBuilder::minimal()), - Some("mainnet") => run_with_spec!(EnvironmentBuilder::mainnet()), - Some("interop") => run_with_spec!(EnvironmentBuilder::interop()), - spec => { - // This path should be unreachable due to slog having a `default_value` - unreachable!("Unknown spec configuration: {:?}", spec); + // boot node subcommand circumvents the environment + if let Some(bootnode_matches) = matches.subcommand_matches("boot_node") { + // The bootnode uses the main debug-level flag + let debug_info = matches + .value_of("debug-level") + .expect("Debug-level must be present") + .into(); + + boot_node::run(bootnode_matches, eth_spec_id, debug_info); + + return Ok(()); } - }; + + match eth_spec_id { + EthSpecId::Minimal => run(EnvironmentBuilder::minimal(), &matches, testnet_config), + EthSpecId::Mainnet => run(EnvironmentBuilder::mainnet(), &matches, testnet_config), + EthSpecId::V012Legacy => { + run(EnvironmentBuilder::v012_legacy(), &matches, testnet_config) + } + } + }); // `std::process::exit` does not run destructors so we drop manually. drop(matches); @@ -172,9 +171,23 @@ fn main() { } } +fn load_testnet_config(matches: &ArgMatches) -> Result<Eth2TestnetConfig, String> { + if matches.is_present("testnet-dir") { + clap_utils::parse_testnet_dir(matches, "testnet-dir")? + .ok_or_else(|| "Unable to load testnet dir".to_string()) + } else if matches.is_present("testnet") { + clap_utils::parse_hardcoded_network(matches, "testnet")? + .ok_or_else(|| "Unable to load hard coded network config".to_string()) + } else { + Eth2TestnetConfig::hard_coded_default()? + .ok_or_else(|| "Unable to load default network config".to_string()) + } +} + fn run<E: EthSpec>( environment_builder: EnvironmentBuilder<E>, matches: &ArgMatches, + testnet_config: Eth2TestnetConfig, ) -> Result<(), String> { if std::mem::size_of::<usize>() != 8 { return Err(format!( @@ -183,25 +196,19 @@ fn run<E: EthSpec>( )); } + #[cfg(all(feature = "modern", target_arch = "x86_64"))] + if !std::is_x86_feature_detected!("adx") { + return Err(format!( + "CPU incompatible with optimized binary, please try Lighthouse portable build" + )); + } + let debug_level = matches .value_of("debug-level") .ok_or_else(|| "Expected --debug-level flag".to_string())?; let log_format = matches.value_of("log-format"); - // Parse testnet config from the `testnet` and `testnet-dir` flag in that order - // else, use the default - let mut optional_testnet_config = None; - if matches.is_present("testnet") { - optional_testnet_config = clap_utils::parse_hardcoded_network(matches, "testnet")?; - }; - if matches.is_present("testnet-dir") { - optional_testnet_config = clap_utils::parse_testnet_dir(matches, "testnet-dir")?; - }; - if optional_testnet_config.is_none() { - optional_testnet_config = Eth2TestnetConfig::hard_coded_default()?; - } - let builder = if let Some(log_path) = matches.value_of("logfile") { let path = log_path .parse::<PathBuf>() @@ -213,11 +220,18 @@ fn run<E: EthSpec>( let mut environment = builder .multi_threaded_tokio_runtime()? - .optional_eth2_testnet_config(optional_testnet_config)? + .optional_eth2_testnet_config(Some(testnet_config))? .build()?; let log = environment.core_context().log().clone(); + if matches.is_present("spec") { + warn!( + log, + "The --spec flag is deprecated and will be removed in a future release" + ); + } + // Note: the current code technically allows for starting a beacon node _and_ a validator // client at the same time. // @@ -264,7 +278,6 @@ fn run<E: EthSpec>( let executor = context.executor.clone(); let config = beacon_node::get_config::<E>( matches, - &context.eth2_config.spec_constants, &context.eth2_config().spec, context.log().clone(), )?; diff --git a/testing/ef_tests/Makefile b/testing/ef_tests/Makefile index e9d7275ad..20edfeadb 100644 --- a/testing/ef_tests/Makefile +++ b/testing/ef_tests/Makefile @@ -1,4 +1,4 @@ -TESTS_TAG := v0.12.3 +TESTS_TAG := v1.0.0-rc.0 TESTS = general minimal mainnet TARBALLS = $(patsubst %,%-$(TESTS_TAG).tar.gz,$(TESTS)) diff --git a/testing/ef_tests/src/cases/bls_aggregate_verify.rs b/testing/ef_tests/src/cases/bls_aggregate_verify.rs index 22fc76035..4f6df9981 100644 --- a/testing/ef_tests/src/cases/bls_aggregate_verify.rs +++ b/testing/ef_tests/src/cases/bls_aggregate_verify.rs @@ -1,13 +1,13 @@ use super::*; use crate::case_result::compare_result; use crate::cases::common::BlsCase; -use bls::{AggregateSignature, PublicKey}; +use bls::{AggregateSignature, PublicKeyBytes}; use serde_derive::Deserialize; use types::Hash256; #[derive(Debug, Clone, Deserialize)] pub struct BlsAggregateVerifyInput { - pub pubkeys: Vec<PublicKey>, + pub pubkeys: Vec<PublicKeyBytes>, pub messages: Vec<String>, pub signature: String, } @@ -33,14 +33,29 @@ impl Case for BlsAggregateVerify { }) .collect::<Result<Vec<_>, _>>()?; - let pubkey_refs = self.input.pubkeys.iter().collect::<Vec<_>>(); + let pubkeys_result = self + .input + .pubkeys + .iter() + .map(|pkb| pkb.decompress()) + .collect::<Result<Vec<_>, _>>(); + + let pubkeys = match pubkeys_result { + Ok(pubkeys) => pubkeys, + Err(bls::Error::InvalidInfinityPublicKey) if !self.output => { + return Ok(()); + } + Err(e) => return Err(Error::FailedToParseTest(format!("{:?}", e))), + }; + + let pubkey_refs = pubkeys.iter().collect::<Vec<_>>(); let signature_bytes = hex::decode(&self.input.signature[2..]) .map_err(|e| Error::FailedToParseTest(format!("{:?}", e)))?; let signature_valid = AggregateSignature::deserialize(&signature_bytes) .ok() - .map(|signature| signature.aggregate_verify(&messages, &pubkey_refs)) + .map(|signature| signature.aggregate_verify(&messages, &pubkey_refs[..])) .unwrap_or(false); compare_result::<bool, ()>(&Ok(signature_valid), &Some(self.output)) diff --git a/testing/ef_tests/src/cases/bls_fast_aggregate_verify.rs b/testing/ef_tests/src/cases/bls_fast_aggregate_verify.rs index d63f4da37..7a0d870e0 100644 --- a/testing/ef_tests/src/cases/bls_fast_aggregate_verify.rs +++ b/testing/ef_tests/src/cases/bls_fast_aggregate_verify.rs @@ -1,7 +1,7 @@ use super::*; use crate::case_result::compare_result; use crate::cases::common::BlsCase; -use bls::{AggregateSignature, PublicKey, PublicKeyBytes}; +use bls::{AggregateSignature, PublicKeyBytes}; use serde_derive::Deserialize; use std::convert::TryInto; use types::Hash256; @@ -9,6 +9,7 @@ use types::Hash256; #[derive(Debug, Clone, Deserialize)] pub struct BlsFastAggregateVerifyInput { pub pubkeys: Vec<PublicKeyBytes>, + #[serde(alias = "messages")] pub message: String, pub signature: String, } @@ -28,13 +29,20 @@ impl Case for BlsFastAggregateVerify { .map_err(|e| Error::FailedToParseTest(format!("{:?}", e)))?, ); - let pubkeys = self + let pubkeys_result = self .input .pubkeys .iter() .map(|pkb| pkb.try_into()) - .collect::<Result<Vec<PublicKey>, bls::Error>>() - .map_err(|e| Error::FailedToParseTest(format!("{:?}", e)))?; + .collect::<Result<Vec<_>, _>>(); + + let pubkeys = match pubkeys_result { + Ok(pubkeys) => pubkeys, + Err(bls::Error::InvalidInfinityPublicKey) if !self.output => { + return Ok(()); + } + Err(e) => return Err(Error::FailedToParseTest(format!("{:?}", e))), + }; let pubkey_refs = pubkeys.iter().collect::<Vec<_>>(); diff --git a/testing/ef_tests/src/cases/bls_sign_msg.rs b/testing/ef_tests/src/cases/bls_sign_msg.rs index 05edc1884..6687dda22 100644 --- a/testing/ef_tests/src/cases/bls_sign_msg.rs +++ b/testing/ef_tests/src/cases/bls_sign_msg.rs @@ -14,7 +14,7 @@ pub struct BlsSignInput { #[derive(Debug, Clone, Deserialize)] pub struct BlsSign { pub input: BlsSignInput, - pub output: String, + pub output: Option<String>, } impl BlsCase for BlsSign {} @@ -27,16 +27,25 @@ impl Case for BlsSign { assert_eq!(sk.len(), 32); - let sk = SecretKey::deserialize(&sk).unwrap(); + let sk = match SecretKey::deserialize(&sk) { + Ok(sk) => sk, + Err(_) if self.output.is_none() => { + return Ok(()); + } + Err(e) => return Err(Error::FailedToParseTest(format!("{:?}", e))), + }; let msg = hex::decode(&self.input.message[2..]) .map_err(|e| Error::FailedToParseTest(format!("{:?}", e)))?; let signature = sk.sign(Hash256::from_slice(&msg)); - // Convert the output to one set of bytes - let decoded = hex::decode(&self.output[2..]) + let decoded = self + .output + .as_ref() + .map(|output| hex::decode(&output[2..])) + .transpose() .map_err(|e| Error::FailedToParseTest(format!("{:?}", e)))?; - compare_result::<Vec<u8>, Vec<u8>>(&Ok(signature.serialize().to_vec()), &Some(decoded)) + compare_result::<Vec<u8>, Vec<u8>>(&Ok(signature.serialize().to_vec()), &decoded) } } diff --git a/testing/ef_tests/src/cases/bls_verify_msg.rs b/testing/ef_tests/src/cases/bls_verify_msg.rs index cd4bb93af..0684d7698 100644 --- a/testing/ef_tests/src/cases/bls_verify_msg.rs +++ b/testing/ef_tests/src/cases/bls_verify_msg.rs @@ -1,14 +1,14 @@ use super::*; use crate::case_result::compare_result; use crate::cases::common::BlsCase; -use bls::{PublicKey, Signature, SignatureBytes}; +use bls::{PublicKeyBytes, Signature, SignatureBytes}; use serde_derive::Deserialize; use std::convert::TryInto; use types::Hash256; #[derive(Debug, Clone, Deserialize)] pub struct BlsVerifyInput { - pub pubkey: PublicKey, + pub pubkey: PublicKeyBytes, pub message: String, pub signature: SignatureBytes, } @@ -28,8 +28,9 @@ impl Case for BlsVerify { let signature_ok = (&self.input.signature) .try_into() - .map(|signature: Signature| { - signature.verify(&self.input.pubkey, Hash256::from_slice(&message)) + .and_then(|signature: Signature| { + let pk = self.input.pubkey.decompress()?; + Ok(signature.verify(&pk, Hash256::from_slice(&message))) }) .unwrap_or(false); diff --git a/testing/ef_tests/src/type_name.rs b/testing/ef_tests/src/type_name.rs index 1d8d3e14b..9cf7fa40b 100644 --- a/testing/ef_tests/src/type_name.rs +++ b/testing/ef_tests/src/type_name.rs @@ -36,6 +36,7 @@ macro_rules! type_name_generic { type_name!(MinimalEthSpec, "minimal"); type_name!(MainnetEthSpec, "mainnet"); +type_name_generic!(AggregateAndProof); type_name_generic!(Attestation); type_name!(AttestationData); type_name_generic!(AttesterSlashing); @@ -46,12 +47,18 @@ type_name_generic!(BeaconState); type_name!(Checkpoint); type_name!(Deposit); type_name!(DepositData); +type_name!(DepositMessage); type_name!(Eth1Data); type_name!(Fork); +type_name!(ForkData); type_name_generic!(HistoricalBatch); type_name_generic!(IndexedAttestation); type_name_generic!(PendingAttestation); type_name!(ProposerSlashing); +type_name_generic!(SignedAggregateAndProof); +type_name_generic!(SignedBeaconBlock); +type_name!(SignedBeaconBlockHeader); type_name!(SignedVoluntaryExit); +type_name!(SigningData); type_name!(Validator); type_name!(VoluntaryExit); diff --git a/testing/ef_tests/tests/tests.rs b/testing/ef_tests/tests/tests.rs index 149b2c059..72bede138 100644 --- a/testing/ef_tests/tests/tests.rs +++ b/testing/ef_tests/tests/tests.rs @@ -172,6 +172,7 @@ mod ssz_static { use ef_tests::{Handler, SszStaticHandler, SszStaticTHCHandler}; use types::*; + ssz_static_test!(aggregate_and_proof, AggregateAndProof<_>); ssz_static_test!(attestation, Attestation<_>); ssz_static_test!(attestation_data, AttestationData); ssz_static_test!(attester_slashing, AttesterSlashing<_>); @@ -188,12 +189,24 @@ mod ssz_static { ssz_static_test!(checkpoint, Checkpoint); ssz_static_test!(deposit, Deposit); ssz_static_test!(deposit_data, DepositData); + ssz_static_test!(deposit_message, DepositMessage); + // FIXME(sproul): move Eth1Block to consensus/types + // + // Tracked at: https://github.com/sigp/lighthouse/issues/1835 + // + // ssz_static_test!(eth1_block, Eth1Block); ssz_static_test!(eth1_data, Eth1Data); ssz_static_test!(fork, Fork); + ssz_static_test!(fork_data, ForkData); ssz_static_test!(historical_batch, HistoricalBatch<_>); ssz_static_test!(indexed_attestation, IndexedAttestation<_>); ssz_static_test!(pending_attestation, PendingAttestation<_>); ssz_static_test!(proposer_slashing, ProposerSlashing); + ssz_static_test!(signed_aggregate_and_proof, SignedAggregateAndProof<_>); + ssz_static_test!(signed_beacon_block, SignedBeaconBlock<_>); + ssz_static_test!(signed_beacon_block_header, SignedBeaconBlockHeader); + ssz_static_test!(signed_voluntary_exit, SignedVoluntaryExit); + ssz_static_test!(signing_data, SigningData); ssz_static_test!(validator, Validator); ssz_static_test!(voluntary_exit, VoluntaryExit); } @@ -217,7 +230,7 @@ fn epoch_processing_justification_and_finalization() { #[test] fn epoch_processing_rewards_and_penalties() { EpochProcessingHandler::<MinimalEthSpec, RewardsAndPenalties>::run(); - // Note: there are no reward and penalty tests for mainnet yet + EpochProcessingHandler::<MainnetEthSpec, RewardsAndPenalties>::run(); } #[test] diff --git a/validator_client/Cargo.toml b/validator_client/Cargo.toml index a82adeff3..ab04cc62e 100644 --- a/validator_client/Cargo.toml +++ b/validator_client/Cargo.toml @@ -1,6 +1,6 @@ [package] name = "validator_client" -version = "0.3.1" +version = "0.3.2" authors = ["Paul Hauner <paul@paulhauner.com>", "Age Manning <Age@AgeManning.com>", "Luke Anderson <luke@lukeanderson.com.au>"] edition = "2018"