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 <baird.k@outlook.com>
Co-authored-by: Paul Hauner <paul@paulhauner.com>
This commit is contained in:
Michael Sproul 2020-10-28 22:19:38 +00:00
parent ad846ad280
commit 36bd4d87f0
55 changed files with 596 additions and 661 deletions

263
Cargo.lock generated
View File

@ -2,7 +2,7 @@
# It is not intended for manual editing. # It is not intended for manual editing.
[[package]] [[package]]
name = "account_manager" name = "account_manager"
version = "0.3.1" version = "0.3.2"
dependencies = [ dependencies = [
"account_utils", "account_utils",
"bls", "bls",
@ -18,8 +18,8 @@ dependencies = [
"eth2_testnet_config", "eth2_testnet_config",
"eth2_wallet", "eth2_wallet",
"eth2_wallet_manager", "eth2_wallet_manager",
"futures 0.3.6", "futures 0.3.7",
"hex 0.4.2", "hex",
"libc", "libc",
"rand 0.7.3", "rand 0.7.3",
"rayon", "rayon",
@ -172,12 +172,8 @@ dependencies = [
[[package]] [[package]]
name = "amcl" name = "amcl"
version = "0.2.0" version = "0.3.0"
source = "git+https://github.com/sigp/milagro_bls?branch=paulh#7662690845f3f2594e46cfe71b6b0bb91d5e1f82" source = "git+https://github.com/sigp/milagro_bls?tag=v1.4.0#45a076a776a6f1d9f8157fd2d574bfefaee2c81a"
dependencies = [
"hex 0.3.2",
"lazy_static",
]
[[package]] [[package]]
name = "ansi_term" name = "ansi_term"
@ -226,9 +222,9 @@ checksum = "a4c527152e37cf757a3f78aae5a06fbeefdb07ccc535c980a3208ee3060dd544"
[[package]] [[package]]
name = "arrayvec" name = "arrayvec"
version = "0.5.1" version = "0.5.2"
source = "registry+https://github.com/rust-lang/crates.io-index" source = "registry+https://github.com/rust-lang/crates.io-index"
checksum = "cff77d8686867eceff3105329d4698d96c2391c176d5d03adc90c7389162b5b8" checksum = "23b62fc65de8e4e7f52534fb52b0f3ed04746ae267519eef2a83941e8085068b"
[[package]] [[package]]
name = "asn1_der" name = "asn1_der"
@ -357,7 +353,7 @@ checksum = "904dfeac50f3cdaba28fc6f57fdcddb75f49ed61346676a78c4ffe55877802fd"
name = "beacon_chain" name = "beacon_chain"
version = "0.2.0" version = "0.2.0"
dependencies = [ dependencies = [
"bitvec 0.19.3", "bitvec 0.19.4",
"bls", "bls",
"bus", "bus",
"derivative", "derivative",
@ -370,7 +366,7 @@ dependencies = [
"eth2_ssz_types", "eth2_ssz_types",
"exit-future", "exit-future",
"fork_choice", "fork_choice",
"futures 0.3.6", "futures 0.3.7",
"genesis", "genesis",
"int_to_bytes", "int_to_bytes",
"integer-sqrt", "integer-sqrt",
@ -409,7 +405,7 @@ dependencies = [
[[package]] [[package]]
name = "beacon_node" name = "beacon_node"
version = "0.3.1" version = "0.3.2"
dependencies = [ dependencies = [
"beacon_chain", "beacon_chain",
"clap", "clap",
@ -424,9 +420,9 @@ dependencies = [
"eth2_ssz", "eth2_ssz",
"eth2_testnet_config", "eth2_testnet_config",
"exit-future", "exit-future",
"futures 0.3.6", "futures 0.3.7",
"genesis", "genesis",
"hex 0.4.2", "hex",
"hyper 0.13.8", "hyper 0.13.8",
"lighthouse_version", "lighthouse_version",
"logging", "logging",
@ -487,9 +483,9 @@ dependencies = [
[[package]] [[package]]
name = "bitvec" name = "bitvec"
version = "0.19.3" version = "0.19.4"
source = "registry+https://github.com/rust-lang/crates.io-index" source = "registry+https://github.com/rust-lang/crates.io-index"
checksum = "11593270830d9b037fbead730bb0c05ef6fbf6be55537a1e8e5892edef7e1f03" checksum = "a7ba35e9565969edb811639dbebfe34edc0368e472c5018474c8eb2543397f81"
dependencies = [ dependencies = [
"funty", "funty",
"radium 0.5.3", "radium 0.5.3",
@ -499,15 +495,13 @@ dependencies = [
[[package]] [[package]]
name = "blake2" name = "blake2"
version = "0.9.0" version = "0.9.1"
source = "registry+https://github.com/rust-lang/crates.io-index" source = "registry+https://github.com/rust-lang/crates.io-index"
checksum = "84ce5b6108f8e154604bd4eb76a2f726066c3464d5a552a4229262a18c9bb471" checksum = "10a5720225ef5daecf08657f23791354e1685a8c91a4c60c7f3d3b2892f978f4"
dependencies = [ dependencies = [
"byte-tools",
"byteorder",
"crypto-mac 0.8.0", "crypto-mac 0.8.0",
"digest 0.9.0", "digest 0.9.0",
"opaque-debug 0.2.3", "opaque-debug 0.3.0",
] ]
[[package]] [[package]]
@ -587,7 +581,7 @@ dependencies = [
"eth2_hashing", "eth2_hashing",
"eth2_ssz", "eth2_ssz",
"ethereum-types", "ethereum-types",
"hex 0.4.2", "hex",
"milagro_bls", "milagro_bls",
"rand 0.7.3", "rand 0.7.3",
"serde", "serde",
@ -599,8 +593,8 @@ dependencies = [
[[package]] [[package]]
name = "blst" name = "blst"
version = "0.1.1" version = "0.2.0"
source = "git+https://github.com/sigp/blst.git?rev=284f7059642851c760a09fb1708bcb59c7ca323c#284f7059642851c760a09fb1708bcb59c7ca323c" source = "git+https://github.com/sigp/blst.git?rev=7cf47864627ca479cad06c2a164f30d0cbaf16ce#7cf47864627ca479cad06c2a164f30d0cbaf16ce"
dependencies = [ dependencies = [
"cc", "cc",
"glob", "glob",
@ -609,15 +603,15 @@ dependencies = [
[[package]] [[package]]
name = "boot_node" name = "boot_node"
version = "0.3.1" version = "0.3.2"
dependencies = [ dependencies = [
"beacon_node", "beacon_node",
"clap", "clap",
"eth2_libp2p", "eth2_libp2p",
"eth2_ssz", "eth2_ssz",
"eth2_testnet_config", "eth2_testnet_config",
"futures 0.3.6", "futures 0.3.7",
"hex 0.4.2", "hex",
"log 0.4.11", "log 0.4.11",
"logging", "logging",
"slog", "slog",
@ -839,7 +833,7 @@ dependencies = [
"dirs 3.0.1", "dirs 3.0.1",
"eth2_ssz", "eth2_ssz",
"eth2_testnet_config", "eth2_testnet_config",
"hex 0.4.2", "hex",
"types", "types",
] ]
@ -857,7 +851,7 @@ dependencies = [
"eth2_config", "eth2_config",
"eth2_libp2p", "eth2_libp2p",
"eth2_ssz", "eth2_ssz",
"futures 0.3.6", "futures 0.3.7",
"genesis", "genesis",
"http_api", "http_api",
"http_metrics", "http_metrics",
@ -1267,7 +1261,7 @@ version = "0.2.0"
dependencies = [ dependencies = [
"eth2_ssz", "eth2_ssz",
"ethabi", "ethabi",
"hex 0.4.2", "hex",
"reqwest", "reqwest",
"serde_json", "serde_json",
"sha2 0.9.1", "sha2 0.9.1",
@ -1384,8 +1378,8 @@ dependencies = [
"digest 0.9.0", "digest 0.9.0",
"enr", "enr",
"fnv", "fnv",
"futures 0.3.6", "futures 0.3.7",
"hex 0.4.2", "hex",
"hkdf", "hkdf",
"k256", "k256",
"lazy_static", "lazy_static",
@ -1416,8 +1410,8 @@ dependencies = [
"digest 0.9.0", "digest 0.9.0",
"enr", "enr",
"fnv", "fnv",
"futures 0.3.6", "futures 0.3.7",
"hex 0.4.2", "hex",
"hkdf", "hkdf",
"k256", "k256",
"lazy_static", "lazy_static",
@ -1487,7 +1481,7 @@ dependencies = [
"eth2_ssz", "eth2_ssz",
"eth2_ssz_derive", "eth2_ssz_derive",
"ethereum-types", "ethereum-types",
"hex 0.4.2", "hex",
"rayon", "rayon",
"serde", "serde",
"serde_derive", "serde_derive",
@ -1541,7 +1535,7 @@ dependencies = [
"base64 0.12.3", "base64 0.12.3",
"bs58", "bs58",
"ed25519-dalek", "ed25519-dalek",
"hex 0.4.2", "hex",
"k256", "k256",
"log 0.4.11", "log 0.4.11",
"rand 0.7.3", "rand 0.7.3",
@ -1572,7 +1566,7 @@ dependencies = [
"eth2_config", "eth2_config",
"eth2_testnet_config", "eth2_testnet_config",
"exit-future", "exit-future",
"futures 0.3.6", "futures 0.3.7",
"logging", "logging",
"parking_lot 0.11.0", "parking_lot 0.11.0",
"slog", "slog",
@ -1604,8 +1598,8 @@ dependencies = [
"eth2_hashing", "eth2_hashing",
"eth2_ssz", "eth2_ssz",
"eth2_ssz_derive", "eth2_ssz_derive",
"futures 0.3.6", "futures 0.3.7",
"hex 0.4.2", "hex",
"lazy_static", "lazy_static",
"libflate", "libflate",
"lighthouse_metrics", "lighthouse_metrics",
@ -1630,7 +1624,7 @@ name = "eth1_test_rig"
version = "0.2.0" version = "0.2.0"
dependencies = [ dependencies = [
"deposit_contract", "deposit_contract",
"futures 0.3.6", "futures 0.3.7",
"serde_json", "serde_json",
"tokio 0.2.22", "tokio 0.2.22",
"types", "types",
@ -1646,7 +1640,7 @@ dependencies = [
"eth2_keystore", "eth2_keystore",
"eth2_libp2p", "eth2_libp2p",
"eth2_ssz", "eth2_ssz",
"hex 0.4.2", "hex",
"libsecp256k1", "libsecp256k1",
"procinfo", "procinfo",
"proto_array", "proto_array",
@ -1688,7 +1682,7 @@ dependencies = [
"base64 0.13.0", "base64 0.13.0",
"bls", "bls",
"eth2_hashing", "eth2_hashing",
"hex 0.4.2", "hex",
"lazy_static", "lazy_static",
"num-bigint", "num-bigint",
"serde", "serde",
@ -1701,7 +1695,7 @@ name = "eth2_key_derivation"
version = "0.1.0" version = "0.1.0"
dependencies = [ dependencies = [
"bls", "bls",
"hex 0.4.2", "hex",
"num-bigint-dig", "num-bigint-dig",
"ring", "ring",
"sha2 0.9.1", "sha2 0.9.1",
@ -1716,7 +1710,7 @@ dependencies = [
"bls", "bls",
"eth2_key_derivation", "eth2_key_derivation",
"eth2_ssz", "eth2_ssz",
"hex 0.4.2", "hex",
"hmac 0.9.0", "hmac 0.9.0",
"pbkdf2 0.5.0", "pbkdf2 0.5.0",
"rand 0.7.3", "rand 0.7.3",
@ -1744,9 +1738,9 @@ dependencies = [
"eth2_ssz_types", "eth2_ssz_types",
"exit-future", "exit-future",
"fnv", "fnv",
"futures 0.3.6", "futures 0.3.7",
"hashset_delay", "hashset_delay",
"hex 0.4.2", "hex",
"lazy_static", "lazy_static",
"libp2p", "libp2p",
"lighthouse_metrics", "lighthouse_metrics",
@ -1825,7 +1819,7 @@ version = "0.1.0"
dependencies = [ dependencies = [
"eth2_key_derivation", "eth2_key_derivation",
"eth2_keystore", "eth2_keystore",
"hex 0.4.2", "hex",
"rand 0.7.3", "rand 0.7.3",
"serde", "serde",
"serde_json", "serde_json",
@ -1891,7 +1885,7 @@ version = "0.2.0"
source = "registry+https://github.com/rust-lang/crates.io-index" source = "registry+https://github.com/rust-lang/crates.io-index"
checksum = "e43f2f1833d64e33f15592464d6fdd70f349dda7b1a53088eb83cd94014008c5" checksum = "e43f2f1833d64e33f15592464d6fdd70f349dda7b1a53088eb83cd94014008c5"
dependencies = [ dependencies = [
"futures 0.3.6", "futures 0.3.7",
] ]
[[package]] [[package]]
@ -2005,7 +1999,7 @@ dependencies = [
"beacon_chain", "beacon_chain",
"eth2_ssz", "eth2_ssz",
"eth2_ssz_derive", "eth2_ssz_derive",
"hex 0.4.2", "hex",
"proto_array", "proto_array",
"slot_clock", "slot_clock",
"state_processing", "state_processing",
@ -2050,9 +2044,9 @@ checksum = "4c7e4c2612746b0df8fed4ce0c69156021b704c9aefa360311c04e6e9e002eed"
[[package]] [[package]]
name = "futures" name = "futures"
version = "0.3.6" version = "0.3.7"
source = "registry+https://github.com/rust-lang/crates.io-index" source = "registry+https://github.com/rust-lang/crates.io-index"
checksum = "5d8e3078b7b2a8a671cb7a3d17b4760e4181ea243227776ba83fd043b4ca034e" checksum = "95314d38584ffbfda215621d723e0a3906f032e03ae5551e650058dac83d4797"
dependencies = [ dependencies = [
"futures-channel", "futures-channel",
"futures-core", "futures-core",
@ -2065,9 +2059,9 @@ dependencies = [
[[package]] [[package]]
name = "futures-channel" name = "futures-channel"
version = "0.3.6" version = "0.3.7"
source = "registry+https://github.com/rust-lang/crates.io-index" source = "registry+https://github.com/rust-lang/crates.io-index"
checksum = "a7a4d35f7401e948629c9c3d6638fb9bf94e0b2121e96c3b428cc4e631f3eb74" checksum = "0448174b01148032eed37ac4aed28963aaaa8cfa93569a08e5b479bbc6c2c151"
dependencies = [ dependencies = [
"futures-core", "futures-core",
"futures-sink", "futures-sink",
@ -2075,9 +2069,9 @@ dependencies = [
[[package]] [[package]]
name = "futures-core" name = "futures-core"
version = "0.3.6" version = "0.3.7"
source = "registry+https://github.com/rust-lang/crates.io-index" source = "registry+https://github.com/rust-lang/crates.io-index"
checksum = "d674eaa0056896d5ada519900dbf97ead2e46a7b6621e8160d79e2f2e1e2784b" checksum = "18eaa56102984bed2c88ea39026cff3ce3b4c7f508ca970cedf2450ea10d4e46"
[[package]] [[package]]
name = "futures-cpupool" name = "futures-cpupool"
@ -2091,9 +2085,9 @@ dependencies = [
[[package]] [[package]]
name = "futures-executor" name = "futures-executor"
version = "0.3.6" version = "0.3.7"
source = "registry+https://github.com/rust-lang/crates.io-index" source = "registry+https://github.com/rust-lang/crates.io-index"
checksum = "cc709ca1da6f66143b8c9bec8e6260181869893714e9b5a490b169b0414144ab" checksum = "f5f8e0c9258abaea85e78ebdda17ef9666d390e987f006be6080dfe354b708cb"
dependencies = [ dependencies = [
"futures-core", "futures-core",
"futures-task", "futures-task",
@ -2103,15 +2097,15 @@ dependencies = [
[[package]] [[package]]
name = "futures-io" name = "futures-io"
version = "0.3.6" version = "0.3.7"
source = "registry+https://github.com/rust-lang/crates.io-index" source = "registry+https://github.com/rust-lang/crates.io-index"
checksum = "5fc94b64bb39543b4e432f1790b6bf18e3ee3b74653c5449f63310e9a74b123c" checksum = "6e1798854a4727ff944a7b12aa999f58ce7aa81db80d2dfaaf2ba06f065ddd2b"
[[package]] [[package]]
name = "futures-macro" name = "futures-macro"
version = "0.3.6" version = "0.3.7"
source = "registry+https://github.com/rust-lang/crates.io-index" source = "registry+https://github.com/rust-lang/crates.io-index"
checksum = "f57ed14da4603b2554682e9f2ff3c65d7567b53188db96cb71538217fc64581b" checksum = "e36fccf3fc58563b4a14d265027c627c3b665d7fed489427e88e7cc929559efe"
dependencies = [ dependencies = [
"proc-macro-hack", "proc-macro-hack",
"proc-macro2", "proc-macro2",
@ -2121,15 +2115,15 @@ dependencies = [
[[package]] [[package]]
name = "futures-sink" name = "futures-sink"
version = "0.3.6" version = "0.3.7"
source = "registry+https://github.com/rust-lang/crates.io-index" source = "registry+https://github.com/rust-lang/crates.io-index"
checksum = "0d8764258ed64ebc5d9ed185cf86a95db5cac810269c5d20ececb32e0088abbd" checksum = "0e3ca3f17d6e8804ae5d3df7a7d35b2b3a6fe89dac84b31872720fc3060a0b11"
[[package]] [[package]]
name = "futures-task" name = "futures-task"
version = "0.3.6" version = "0.3.7"
source = "registry+https://github.com/rust-lang/crates.io-index" source = "registry+https://github.com/rust-lang/crates.io-index"
checksum = "4dd26820a9f3637f1302da8bceba3ff33adbe53464b54ca24d4e2d4f1db30f94" checksum = "96d502af37186c4fef99453df03e374683f8a1eec9dcc1e66b3b82dc8278ce3c"
dependencies = [ dependencies = [
"once_cell", "once_cell",
] ]
@ -2142,9 +2136,9 @@ checksum = "e64b03909df88034c26dc1547e8970b91f98bdb65165d6a4e9110d94263dbb2c"
[[package]] [[package]]
name = "futures-util" name = "futures-util"
version = "0.3.6" version = "0.3.7"
source = "registry+https://github.com/rust-lang/crates.io-index" source = "registry+https://github.com/rust-lang/crates.io-index"
checksum = "8a894a0acddba51a2d49a6f4263b1e64b8c579ece8af50fa86503d52cd1eea34" checksum = "abcb44342f62e6f3e8ac427b8aa815f724fd705dfad060b18ac7866c15bb8e34"
dependencies = [ dependencies = [
"futures 0.1.30", "futures 0.1.30",
"futures-channel", "futures-channel",
@ -2154,7 +2148,7 @@ dependencies = [
"futures-sink", "futures-sink",
"futures-task", "futures-task",
"memchr", "memchr",
"pin-project 0.4.27", "pin-project 1.0.1",
"pin-utils", "pin-utils",
"proc-macro-hack", "proc-macro-hack",
"proc-macro-nested", "proc-macro-nested",
@ -2168,7 +2162,7 @@ source = "registry+https://github.com/rust-lang/crates.io-index"
checksum = "ce54d63f8b0c75023ed920d46fd71d0cbbb830b0ee012726b5b4f506fb6dea5b" checksum = "ce54d63f8b0c75023ed920d46fd71d0cbbb830b0ee012726b5b4f506fb6dea5b"
dependencies = [ dependencies = [
"bytes 0.5.6", "bytes 0.5.6",
"futures 0.3.6", "futures 0.3.7",
"memchr", "memchr",
"pin-project 0.4.27", "pin-project 0.4.27",
] ]
@ -2221,7 +2215,7 @@ dependencies = [
"eth2_hashing", "eth2_hashing",
"eth2_ssz", "eth2_ssz",
"exit-future", "exit-future",
"futures 0.3.6", "futures 0.3.7",
"int_to_bytes", "int_to_bytes",
"merkle_proof", "merkle_proof",
"parking_lot 0.11.0", "parking_lot 0.11.0",
@ -2342,9 +2336,9 @@ dependencies = [
[[package]] [[package]]
name = "h2" name = "h2"
version = "0.2.6" version = "0.2.7"
source = "registry+https://github.com/rust-lang/crates.io-index" source = "registry+https://github.com/rust-lang/crates.io-index"
checksum = "993f9e0baeed60001cf565546b0d3dbe6a6ad23f2bd31644a133c641eccf6d53" checksum = "5e4728fd124914ad25e99e3d15a9361a879f6620f63cb56bbb08f95abb97a535"
dependencies = [ dependencies = [
"bytes 0.5.6", "bytes 0.5.6",
"fnv", "fnv",
@ -2357,6 +2351,7 @@ dependencies = [
"tokio 0.2.22", "tokio 0.2.22",
"tokio-util", "tokio-util",
"tracing", "tracing",
"tracing-futures",
] ]
[[package]] [[package]]
@ -2397,7 +2392,7 @@ dependencies = [
name = "hashset_delay" name = "hashset_delay"
version = "0.2.0" version = "0.2.0"
dependencies = [ dependencies = [
"futures 0.3.6", "futures 0.3.7",
"tokio 0.2.22", "tokio 0.2.22",
] ]
@ -2444,12 +2439,6 @@ dependencies = [
"libc", "libc",
] ]
[[package]]
name = "hex"
version = "0.3.2"
source = "registry+https://github.com/rust-lang/crates.io-index"
checksum = "805026a5d0141ffc30abb3be3173848ad46a1b1664fe632428479619a3644d77"
[[package]] [[package]]
name = "hex" name = "hex"
version = "0.4.2" version = "0.4.2"
@ -2570,7 +2559,7 @@ dependencies = [
"eth2_libp2p", "eth2_libp2p",
"eth2_ssz", "eth2_ssz",
"fork_choice", "fork_choice",
"hex 0.4.2", "hex",
"lazy_static", "lazy_static",
"lighthouse_metrics", "lighthouse_metrics",
"lighthouse_version", "lighthouse_version",
@ -2691,7 +2680,7 @@ dependencies = [
"futures-channel", "futures-channel",
"futures-core", "futures-core",
"futures-util", "futures-util",
"h2 0.2.6", "h2 0.2.7",
"http 0.2.1", "http 0.2.1",
"http-body 0.3.1", "http-body 0.3.1",
"httparse", "httparse",
@ -2814,11 +2803,11 @@ dependencies = [
[[package]] [[package]]
name = "instant" name = "instant"
version = "0.1.7" version = "0.1.8"
source = "registry+https://github.com/rust-lang/crates.io-index" source = "registry+https://github.com/rust-lang/crates.io-index"
checksum = "63312a18f7ea8760cdd0a7c5aac1a619752a246b833545e3e36d1f81f7cd9e66" checksum = "cb1fc4429a33e1f80d41dc9fea4d108a88bec1de8053878898ae448a0b52f613"
dependencies = [ dependencies = [
"cfg-if 0.1.10", "cfg-if 1.0.0",
] ]
[[package]] [[package]]
@ -2826,7 +2815,7 @@ name = "int_to_bytes"
version = "0.2.0" version = "0.2.0"
dependencies = [ dependencies = [
"bytes 0.5.6", "bytes 0.5.6",
"hex 0.4.2", "hex",
"yaml-rust", "yaml-rust",
] ]
@ -2902,9 +2891,9 @@ dependencies = [
[[package]] [[package]]
name = "k256" name = "k256"
version = "0.5.9" version = "0.5.10"
source = "registry+https://github.com/rust-lang/crates.io-index" source = "registry+https://github.com/rust-lang/crates.io-index"
checksum = "c2967b7caf19e57f5d01ac0893551b0aaae1a8e2e2b2a28996e12c9c51b3b486" checksum = "3934640b1efbc660af5889d041854b6985d403771dc4d5fee984e13e8f82f313"
dependencies = [ dependencies = [
"cfg-if 1.0.0", "cfg-if 1.0.0",
"ecdsa", "ecdsa",
@ -2951,7 +2940,7 @@ checksum = "830d08ce1d1d941e6b30645f1a0eb5643013d835ce3779a5fc208261dbe10f55"
[[package]] [[package]]
name = "lcli" name = "lcli"
version = "0.3.1" version = "0.3.2"
dependencies = [ dependencies = [
"bls", "bls",
"clap", "clap",
@ -2964,9 +2953,9 @@ dependencies = [
"eth2_libp2p", "eth2_libp2p",
"eth2_ssz", "eth2_ssz",
"eth2_testnet_config", "eth2_testnet_config",
"futures 0.3.6", "futures 0.3.7",
"genesis", "genesis",
"hex 0.4.2", "hex",
"lighthouse_version", "lighthouse_version",
"log 0.4.11", "log 0.4.11",
"rand 0.7.3", "rand 0.7.3",
@ -3006,15 +2995,15 @@ dependencies = [
[[package]] [[package]]
name = "libc" name = "libc"
version = "0.2.79" version = "0.2.80"
source = "registry+https://github.com/rust-lang/crates.io-index" source = "registry+https://github.com/rust-lang/crates.io-index"
checksum = "2448f6066e80e3bfc792e9c98bf705b4b0fc6e8ef5b43e5889aff0eaa9c58743" checksum = "4d58d1b70b004888f764dfbf6a26a3b0342a1632d33968e4a179d8011c760614"
[[package]] [[package]]
name = "libflate" name = "libflate"
version = "1.0.2" version = "1.0.3"
source = "registry+https://github.com/rust-lang/crates.io-index" source = "registry+https://github.com/rust-lang/crates.io-index"
checksum = "e9bac9023e1db29c084f9f8cd9d3852e5e8fddf98fb47c4964a0ea4663d95949" checksum = "389de7875e06476365974da3e7ff85d55f1972188ccd9f6020dd7c8156e17914"
dependencies = [ dependencies = [
"adler32", "adler32",
"crc32fast", "crc32fast",
@ -3041,7 +3030,7 @@ source = "git+https://github.com/sigp/rust-libp2p?rev=8c6ce6eb1228de568568f6cd72
dependencies = [ dependencies = [
"atomic", "atomic",
"bytes 0.5.6", "bytes 0.5.6",
"futures 0.3.6", "futures 0.3.7",
"lazy_static", "lazy_static",
"libp2p-core 0.22.2", "libp2p-core 0.22.2",
"libp2p-core-derive", "libp2p-core-derive",
@ -3072,7 +3061,7 @@ dependencies = [
"ed25519-dalek", "ed25519-dalek",
"either", "either",
"fnv", "fnv",
"futures 0.3.6", "futures 0.3.7",
"futures-timer", "futures-timer",
"lazy_static", "lazy_static",
"libsecp256k1", "libsecp256k1",
@ -3105,7 +3094,7 @@ dependencies = [
"ed25519-dalek", "ed25519-dalek",
"either", "either",
"fnv", "fnv",
"futures 0.3.6", "futures 0.3.7",
"futures-timer", "futures-timer",
"lazy_static", "lazy_static",
"libsecp256k1", "libsecp256k1",
@ -3142,7 +3131,7 @@ name = "libp2p-dns"
version = "0.22.0" version = "0.22.0"
source = "git+https://github.com/sigp/rust-libp2p?rev=8c6ce6eb1228de568568f6cd72fb134dea5f9669#8c6ce6eb1228de568568f6cd72fb134dea5f9669" source = "git+https://github.com/sigp/rust-libp2p?rev=8c6ce6eb1228de568568f6cd72fb134dea5f9669#8c6ce6eb1228de568568f6cd72fb134dea5f9669"
dependencies = [ dependencies = [
"futures 0.3.6", "futures 0.3.7",
"libp2p-core 0.22.2", "libp2p-core 0.22.2",
"log 0.4.11", "log 0.4.11",
] ]
@ -3156,7 +3145,7 @@ dependencies = [
"byteorder", "byteorder",
"bytes 0.5.6", "bytes 0.5.6",
"fnv", "fnv",
"futures 0.3.6", "futures 0.3.7",
"futures_codec", "futures_codec",
"hex_fmt", "hex_fmt",
"libp2p-core 0.22.2", "libp2p-core 0.22.2",
@ -3176,7 +3165,7 @@ name = "libp2p-identify"
version = "0.22.0" version = "0.22.0"
source = "git+https://github.com/sigp/rust-libp2p?rev=8c6ce6eb1228de568568f6cd72fb134dea5f9669#8c6ce6eb1228de568568f6cd72fb134dea5f9669" source = "git+https://github.com/sigp/rust-libp2p?rev=8c6ce6eb1228de568568f6cd72fb134dea5f9669#8c6ce6eb1228de568568f6cd72fb134dea5f9669"
dependencies = [ dependencies = [
"futures 0.3.6", "futures 0.3.7",
"libp2p-core 0.22.2", "libp2p-core 0.22.2",
"libp2p-swarm", "libp2p-swarm",
"log 0.4.11", "log 0.4.11",
@ -3193,7 +3182,7 @@ source = "git+https://github.com/sigp/rust-libp2p?rev=8c6ce6eb1228de568568f6cd72
dependencies = [ dependencies = [
"bytes 0.5.6", "bytes 0.5.6",
"fnv", "fnv",
"futures 0.3.6", "futures 0.3.7",
"futures_codec", "futures_codec",
"libp2p-core 0.22.2", "libp2p-core 0.22.2",
"log 0.4.11", "log 0.4.11",
@ -3208,7 +3197,7 @@ source = "git+https://github.com/sigp/rust-libp2p?rev=8c6ce6eb1228de568568f6cd72
dependencies = [ dependencies = [
"bytes 0.5.6", "bytes 0.5.6",
"curve25519-dalek", "curve25519-dalek",
"futures 0.3.6", "futures 0.3.7",
"lazy_static", "lazy_static",
"libp2p-core 0.22.2", "libp2p-core 0.22.2",
"log 0.4.11", "log 0.4.11",
@ -3228,7 +3217,7 @@ version = "0.22.0"
source = "git+https://github.com/sigp/rust-libp2p?rev=8c6ce6eb1228de568568f6cd72fb134dea5f9669#8c6ce6eb1228de568568f6cd72fb134dea5f9669" source = "git+https://github.com/sigp/rust-libp2p?rev=8c6ce6eb1228de568568f6cd72fb134dea5f9669#8c6ce6eb1228de568568f6cd72fb134dea5f9669"
dependencies = [ dependencies = [
"either", "either",
"futures 0.3.6", "futures 0.3.7",
"libp2p-core 0.22.2", "libp2p-core 0.22.2",
"log 0.4.11", "log 0.4.11",
"rand 0.7.3", "rand 0.7.3",
@ -3242,7 +3231,7 @@ name = "libp2p-tcp"
version = "0.22.0" version = "0.22.0"
source = "git+https://github.com/sigp/rust-libp2p?rev=8c6ce6eb1228de568568f6cd72fb134dea5f9669#8c6ce6eb1228de568568f6cd72fb134dea5f9669" source = "git+https://github.com/sigp/rust-libp2p?rev=8c6ce6eb1228de568568f6cd72fb134dea5f9669#8c6ce6eb1228de568568f6cd72fb134dea5f9669"
dependencies = [ dependencies = [
"futures 0.3.6", "futures 0.3.7",
"futures-timer", "futures-timer",
"get_if_addrs", "get_if_addrs",
"ipnet", "ipnet",
@ -3259,7 +3248,7 @@ source = "git+https://github.com/sigp/rust-libp2p?rev=8c6ce6eb1228de568568f6cd72
dependencies = [ dependencies = [
"async-tls", "async-tls",
"either", "either",
"futures 0.3.6", "futures 0.3.7",
"libp2p-core 0.22.2", "libp2p-core 0.22.2",
"log 0.4.11", "log 0.4.11",
"quicksink", "quicksink",
@ -3312,7 +3301,7 @@ dependencies = [
[[package]] [[package]]
name = "lighthouse" name = "lighthouse"
version = "0.3.1" version = "0.3.2"
dependencies = [ dependencies = [
"account_manager", "account_manager",
"account_utils", "account_utils",
@ -3325,7 +3314,7 @@ dependencies = [
"env_logger", "env_logger",
"environment", "environment",
"eth2_testnet_config", "eth2_testnet_config",
"futures 0.3.6", "futures 0.3.7",
"lighthouse_version", "lighthouse_version",
"logging", "logging",
"slashing_protection", "slashing_protection",
@ -3481,9 +3470,9 @@ checksum = "60302e4db3a61da70c0cb7991976248362f30319e88850c487b9b95bbf059e00"
[[package]] [[package]]
name = "memchr" name = "memchr"
version = "2.3.3" version = "2.3.4"
source = "registry+https://github.com/rust-lang/crates.io-index" source = "registry+https://github.com/rust-lang/crates.io-index"
checksum = "3728d817d99e5ac407411fa471ff9800a778d88a24685968b36824eaf4bee400" checksum = "0ee1c47aaa256ecabcaea351eae4a9b01ef39ed810004e298d2511ed284b1525"
[[package]] [[package]]
name = "memoffset" name = "memoffset"
@ -3508,11 +3497,11 @@ dependencies = [
[[package]] [[package]]
name = "milagro_bls" name = "milagro_bls"
version = "1.1.0" version = "1.4.0"
source = "git+https://github.com/sigp/milagro_bls?branch=paulh#7662690845f3f2594e46cfe71b6b0bb91d5e1f82" source = "git+https://github.com/sigp/milagro_bls?tag=v1.4.0#45a076a776a6f1d9f8157fd2d574bfefaee2c81a"
dependencies = [ dependencies = [
"amcl", "amcl",
"hex 0.4.2", "hex",
"lazy_static", "lazy_static",
"rand 0.7.3", "rand 0.7.3",
"zeroize", "zeroize",
@ -3683,7 +3672,7 @@ version = "0.8.3"
source = "git+https://github.com/sigp/rust-libp2p?rev=8c6ce6eb1228de568568f6cd72fb134dea5f9669#8c6ce6eb1228de568568f6cd72fb134dea5f9669" source = "git+https://github.com/sigp/rust-libp2p?rev=8c6ce6eb1228de568568f6cd72fb134dea5f9669#8c6ce6eb1228de568568f6cd72fb134dea5f9669"
dependencies = [ dependencies = [
"bytes 0.5.6", "bytes 0.5.6",
"futures 0.3.6", "futures 0.3.7",
"log 0.4.11", "log 0.4.11",
"pin-project 0.4.27", "pin-project 0.4.27",
"smallvec 1.4.2", "smallvec 1.4.2",
@ -3697,7 +3686,7 @@ source = "registry+https://github.com/rust-lang/crates.io-index"
checksum = "36a6aa6e32fbaf16795142335967214b8564a7a4661eb6dc846ef343a6e00ac1" checksum = "36a6aa6e32fbaf16795142335967214b8564a7a4661eb6dc846ef343a6e00ac1"
dependencies = [ dependencies = [
"bytes 0.5.6", "bytes 0.5.6",
"futures 0.3.6", "futures 0.3.7",
"log 0.4.11", "log 0.4.11",
"pin-project 1.0.1", "pin-project 1.0.1",
"smallvec 1.4.2", "smallvec 1.4.2",
@ -3744,11 +3733,11 @@ dependencies = [
"eth2_ssz_types", "eth2_ssz_types",
"exit-future", "exit-future",
"fnv", "fnv",
"futures 0.3.6", "futures 0.3.7",
"genesis", "genesis",
"get_if_addrs", "get_if_addrs",
"hashset_delay", "hashset_delay",
"hex 0.4.2", "hex",
"igd", "igd",
"itertools 0.9.0", "itertools 0.9.0",
"lazy_static", "lazy_static",
@ -3805,7 +3794,7 @@ dependencies = [
"environment", "environment",
"eth2", "eth2",
"eth2_config", "eth2_config",
"futures 0.3.6", "futures 0.3.7",
"genesis", "genesis",
"reqwest", "reqwest",
"serde", "serde",
@ -4273,9 +4262,9 @@ dependencies = [
[[package]] [[package]]
name = "proc-macro-hack" name = "proc-macro-hack"
version = "0.5.18" version = "0.5.19"
source = "registry+https://github.com/rust-lang/crates.io-index" source = "registry+https://github.com/rust-lang/crates.io-index"
checksum = "99c605b9a0adc77b7211c6b1f722dcb613d68d66859a44f3d485a6da332b0598" checksum = "dbf0c48bc1d91375ae5c3cd81e3722dff1abcf81a30960240640d223f59fe0e5"
[[package]] [[package]]
name = "proc-macro-nested" name = "proc-macro-nested"
@ -4914,7 +4903,7 @@ version = "0.2.1"
source = "registry+https://github.com/rust-lang/crates.io-index" source = "registry+https://github.com/rust-lang/crates.io-index"
checksum = "4da5fcb054c46f5a5dff833b129285a93d3f0179531735e6c866e8cc307d2020" checksum = "4da5fcb054c46f5a5dff833b129285a93d3f0179531735e6c866e8cc307d2020"
dependencies = [ dependencies = [
"futures 0.3.6", "futures 0.3.7",
"pin-project 0.4.27", "pin-project 0.4.27",
"static_assertions", "static_assertions",
] ]
@ -5137,7 +5126,7 @@ dependencies = [
name = "serde_utils" name = "serde_utils"
version = "0.1.0" version = "0.1.0"
dependencies = [ dependencies = [
"hex 0.4.2", "hex",
"serde", "serde",
"serde_derive", "serde_derive",
"serde_json", "serde_json",
@ -5274,7 +5263,7 @@ dependencies = [
"env_logger", "env_logger",
"eth1", "eth1",
"eth1_test_rig", "eth1_test_rig",
"futures 0.3.6", "futures 0.3.7",
"node_test_rig", "node_test_rig",
"parking_lot 0.11.0", "parking_lot 0.11.0",
"rayon", "rayon",
@ -5477,7 +5466,7 @@ dependencies = [
"base64 0.12.3", "base64 0.12.3",
"bytes 0.5.6", "bytes 0.5.6",
"flate2", "flate2",
"futures 0.3.6", "futures 0.3.7",
"httparse", "httparse",
"log 0.4.11", "log 0.4.11",
"rand 0.7.3", "rand 0.7.3",
@ -5663,9 +5652,9 @@ dependencies = [
[[package]] [[package]]
name = "syn" name = "syn"
version = "1.0.46" version = "1.0.48"
source = "registry+https://github.com/rust-lang/crates.io-index" source = "registry+https://github.com/rust-lang/crates.io-index"
checksum = "5ad5de3220ea04da322618ded2c42233d02baca219d6f160a3e9c87cda16c942" checksum = "cc371affeffc477f42a221a1e4297aedcea33d47d19b61455588bd9d8f6b19ac"
dependencies = [ dependencies = [
"proc-macro2", "proc-macro2",
"quote", "quote",
@ -5707,7 +5696,7 @@ name = "task_executor"
version = "0.1.0" version = "0.1.0"
dependencies = [ dependencies = [
"exit-future", "exit-future",
"futures 0.3.6", "futures 0.3.7",
"lazy_static", "lazy_static",
"lighthouse_metrics", "lighthouse_metrics",
"slog", "slog",
@ -5866,7 +5855,7 @@ name = "timer"
version = "0.2.0" version = "0.2.0"
dependencies = [ dependencies = [
"beacon_chain", "beacon_chain",
"futures 0.3.6", "futures 0.3.7",
"parking_lot 0.11.0", "parking_lot 0.11.0",
"slog", "slog",
"slot_clock", "slot_clock",
@ -6469,7 +6458,7 @@ dependencies = [
"eth2_ssz_derive", "eth2_ssz_derive",
"eth2_ssz_types", "eth2_ssz_types",
"ethereum-types", "ethereum-types",
"hex 0.4.2", "hex",
"int_to_bytes", "int_to_bytes",
"log 0.4.11", "log 0.4.11",
"merkle_proof", "merkle_proof",
@ -6652,7 +6641,7 @@ dependencies = [
[[package]] [[package]]
name = "validator_client" name = "validator_client"
version = "0.3.1" version = "0.3.2"
dependencies = [ dependencies = [
"account_utils", "account_utils",
"bincode", "bincode",
@ -6670,8 +6659,8 @@ dependencies = [
"eth2_ssz", "eth2_ssz",
"eth2_ssz_derive", "eth2_ssz_derive",
"exit-future", "exit-future",
"futures 0.3.6", "futures 0.3.7",
"hex 0.4.2", "hex",
"hyper 0.13.8", "hyper 0.13.8",
"libc", "libc",
"libsecp256k1", "libsecp256k1",
@ -6709,7 +6698,7 @@ dependencies = [
"bls", "bls",
"deposit_contract", "deposit_contract",
"eth2_keystore", "eth2_keystore",
"hex 0.4.2", "hex",
"rand 0.7.3", "rand 0.7.3",
"rayon", "rayon",
"slog", "slog",
@ -6786,7 +6775,7 @@ version = "0.2.5"
source = "git+https://github.com/paulhauner/warp?branch=cors-wildcard#a7685b76d70c3e5628e31d60aee510acec3c5c30" source = "git+https://github.com/paulhauner/warp?branch=cors-wildcard#a7685b76d70c3e5628e31d60aee510acec3c5c30"
dependencies = [ dependencies = [
"bytes 0.5.6", "bytes 0.5.6",
"futures 0.3.6", "futures 0.3.7",
"headers", "headers",
"http 0.2.1", "http 0.2.1",
"hyper 0.13.8", "hyper 0.13.8",
@ -6932,7 +6921,7 @@ version = "0.2.5"
source = "registry+https://github.com/rust-lang/crates.io-index" source = "registry+https://github.com/rust-lang/crates.io-index"
checksum = "be0ecb0db480561e9a7642b5d3e4187c128914e58aa84330b9493e3eb68c5e7f" checksum = "be0ecb0db480561e9a7642b5d3e4187c128914e58aa84330b9493e3eb68c5e7f"
dependencies = [ dependencies = [
"futures 0.3.6", "futures 0.3.7",
"js-sys", "js-sys",
"parking_lot 0.11.0", "parking_lot 0.11.0",
"pin-utils", "pin-utils",
@ -7029,7 +7018,7 @@ dependencies = [
name = "websocket_server" name = "websocket_server"
version = "0.2.0" version = "0.2.0"
dependencies = [ dependencies = [
"futures 0.3.6", "futures 0.3.7",
"serde", "serde",
"serde_derive", "serde_derive",
"slog", "slog",

View File

@ -42,7 +42,7 @@ endif
# optimized CPU functions that may not be available on some systems. This # optimized CPU functions that may not be available on some systems. This
# results in a more portable binary with ~20% slower BLS verification. # results in a more portable binary with ~20% slower BLS verification.
build-x86_64: 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: build-x86_64-portable:
cross build --release --manifest-path lighthouse/Cargo.toml --target x86_64-unknown-linux-gnu --features portable cross build --release --manifest-path lighthouse/Cargo.toml --target x86_64-unknown-linux-gnu --features portable
build-aarch64: build-aarch64:

View File

@ -1,6 +1,6 @@
[package] [package]
name = "account_manager" name = "account_manager"
version = "0.3.1" version = "0.3.2"
authors = ["Paul Hauner <paul@paulhauner.com>", "Luke Anderson <luke@sigmaprime.io>"] authors = ["Paul Hauner <paul@paulhauner.com>", "Luke Anderson <luke@sigmaprime.io>"]
edition = "2018" edition = "2018"

View File

@ -5,7 +5,7 @@ use slashing_protection::{
}; };
use std::fs::File; use std::fs::File;
use std::path::PathBuf; use std::path::PathBuf;
use types::EthSpec; use types::{BeaconState, EthSpec};
pub const CMD: &str = "slashing-protection"; pub const CMD: &str = "slashing-protection";
pub const IMPORT_CMD: &str = "import"; pub const IMPORT_CMD: &str = "import";
@ -46,18 +46,18 @@ pub fn cli_run<T: EthSpec>(
) -> Result<(), String> { ) -> Result<(), String> {
let slashing_protection_db_path = validator_base_dir.join(SLASHING_PROTECTION_FILENAME); let slashing_protection_db_path = validator_base_dir.join(SLASHING_PROTECTION_FILENAME);
let genesis_validators_root = env let testnet_config = env
.testnet .testnet
.and_then(|testnet_config| { .ok_or_else(|| "Unable to get testnet configuration from the environment".to_string())?;
Some(
testnet_config let genesis_validators_root = testnet_config
.genesis_state .beacon_state::<T>()
.as_ref()? .map(|state: BeaconState<T>| state.genesis_validators_root)
.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() { match matches.subcommand() {

View File

@ -1,6 +1,6 @@
[package] [package]
name = "beacon_node" name = "beacon_node"
version = "0.3.1" version = "0.3.2"
authors = ["Paul Hauner <paul@paulhauner.com>", "Age Manning <Age@AgeManning.com"] authors = ["Paul Hauner <paul@paulhauner.com>", "Age Manning <Age@AgeManning.com"]
edition = "2018" edition = "2018"

View File

@ -5,9 +5,6 @@ use std::fs;
use std::path::PathBuf; use std::path::PathBuf;
use types::Graffiti; use types::Graffiti;
/// The number initial validators when starting the `Minimal`.
const TESTNET_SPEC_CONSTANTS: &str = "minimal";
/// Default directory name for the freezer database under the top-level data dir. /// Default directory name for the freezer database under the top-level data dir.
const DEFAULT_FREEZER_DB_DIR: &str = "freezer_db"; const DEFAULT_FREEZER_DB_DIR: &str = "freezer_db";
@ -46,7 +43,6 @@ pub struct Config {
/// Path where the freezer database will be located. /// Path where the freezer database will be located.
pub freezer_db_path: Option<PathBuf>, pub freezer_db_path: Option<PathBuf>,
pub log_file: PathBuf, pub log_file: PathBuf,
pub spec_constants: String,
/// If true, the node will use co-ordinated junk for eth1 values. /// If true, the node will use co-ordinated junk for eth1 values.
/// ///
/// This is the method used for the 2019 client interop in Canada. /// This is the method used for the 2019 client interop in Canada.
@ -81,7 +77,6 @@ impl Default for Config {
network: NetworkConfig::default(), network: NetworkConfig::default(),
chain: <_>::default(), chain: <_>::default(),
websocket_server: <_>::default(), websocket_server: <_>::default(),
spec_constants: TESTNET_SPEC_CONSTANTS.into(),
dummy_eth1_backend: false, dummy_eth1_backend: false,
sync_eth1_chain: false, sync_eth1_chain: false,
eth1: <_>::default(), eth1: <_>::default(),

View File

@ -5,8 +5,7 @@ use client::{ClientConfig, ClientGenesis};
use directory::{DEFAULT_BEACON_NODE_DIR, DEFAULT_NETWORK_DIR, DEFAULT_ROOT_DIR}; use directory::{DEFAULT_BEACON_NODE_DIR, DEFAULT_NETWORK_DIR, DEFAULT_ROOT_DIR};
use eth2_libp2p::{multiaddr::Protocol, Enr, Multiaddr, NetworkConfig, PeerIdSerialized}; use eth2_libp2p::{multiaddr::Protocol, Enr, Multiaddr, NetworkConfig, PeerIdSerialized};
use eth2_testnet_config::Eth2TestnetConfig; use eth2_testnet_config::Eth2TestnetConfig;
use slog::{crit, info, warn, Logger}; use slog::{info, warn, Logger};
use ssz::Encode;
use std::cmp; use std::cmp;
use std::fs; use std::fs;
use std::net::{IpAddr, Ipv4Addr, ToSocketAddrs}; 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. /// response of some remote server.
pub fn get_config<E: EthSpec>( pub fn get_config<E: EthSpec>(
cli_args: &ArgMatches, cli_args: &ArgMatches,
spec_constants: &str,
spec: &ChainSpec, spec: &ChainSpec,
log: Logger, log: Logger,
) -> Result<ClientConfig, String> { ) -> Result<ClientConfig, String> {
@ -67,8 +65,6 @@ pub fn get_config<E: EthSpec>(
log_dir.pop(); log_dir.pop();
info!(log, "Data directory initialised"; "datadir" => log_dir.into_os_string().into_string().expect("Datadir should be a valid os string")); 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 * Networking
*/ */
@ -222,14 +218,6 @@ pub fn get_config<E: EthSpec>(
.map_err(|_| "block-cache-size is not a valid integer".to_string())?; .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 * Zero-ports
* *
@ -255,7 +243,7 @@ pub fn get_config<E: EthSpec>(
/* /*
* Load the eth2 testnet dir to obtain some additional config values. * Load the eth2 testnet dir to obtain some additional config values.
*/ */
let eth2_testnet_config: Eth2TestnetConfig<E> = get_eth2_testnet_config(&cli_args)?; let eth2_testnet_config = get_eth2_testnet_config(&cli_args)?;
client_config.eth1.deposit_contract_address = client_config.eth1.deposit_contract_address =
format!("{:?}", eth2_testnet_config.deposit_contract_address()?); format!("{:?}", eth2_testnet_config.deposit_contract_address()?);
@ -275,12 +263,12 @@ pub fn get_config<E: EthSpec>(
client_config.network.boot_nodes_enr.append(&mut boot_nodes) 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 // 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 // trait bounds to the `ClientGenesis` enum. This would have significant flow-on
// effects. // effects.
client_config.genesis = ClientGenesis::SszBytes { client_config.genesis = ClientGenesis::SszBytes {
genesis_state_bytes: genesis_state.as_ssz_bytes(), genesis_state_bytes,
}; };
} else { } else {
client_config.genesis = ClientGenesis::DepositContract; 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. /// 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. /// Returns the default hardcoded testnet if neither flags are set.
pub fn get_eth2_testnet_config<E: EthSpec>( pub fn get_eth2_testnet_config(cli_args: &ArgMatches) -> Result<Eth2TestnetConfig, String> {
cli_args: &ArgMatches,
) -> Result<Eth2TestnetConfig<E>, String> {
let optional_testnet_config = if cli_args.is_present("testnet") { let optional_testnet_config = if cli_args.is_present("testnet") {
clap_utils::parse_hardcoded_network(cli_args, "testnet")? clap_utils::parse_hardcoded_network(cli_args, "testnet")?
} else if cli_args.is_present("testnet-dir") { } else if cli_args.is_present("testnet-dir") {

View File

@ -53,12 +53,8 @@ impl<E: EthSpec> ProductionBeaconNode<E> {
context: RuntimeContext<E>, context: RuntimeContext<E>,
matches: ArgMatches<'static>, matches: ArgMatches<'static>,
) -> Result<Self, String> { ) -> Result<Self, String> {
let client_config = get_config::<E>( let client_config =
&matches, get_config::<E>(&matches, &context.eth2_config().spec, context.log().clone())?;
&context.eth2_config.spec_constants,
&context.eth2_config().spec,
context.log().clone(),
)?;
Self::new(context, client_config).await Self::new(context, client_config).await
} }

View File

@ -18,17 +18,15 @@ project.
The `Makefile` in the project contains four targets for cross-compiling: The `Makefile` in the project contains four targets for cross-compiling:
- `build-x86_64`: builds an optimized version for x86_64 processors (suitable - `build-x86_64`: builds an optimized version for x86_64 processors (suitable for most users).
for most users). Supports Intel Broadwell (2014) and newer, and AMD Ryzen (2017) and newer.
- `build-x86_64-portable`: builds a version x86_64 processors which avoids - `build-x86_64-portable`: builds a version for x86_64 processors which avoids using some modern CPU
using some modern CPU instructions that might cause an "illegal instructions that are incompatible with older CPUs. Suitable for pre-Broadwell/Ryzen CPUs.
instruction" error on older CPUs. - `build-aarch64`: builds an optimized version for 64-bit ARM processors
- `build-aarch64`: builds an optimized version for 64bit ARM processors
(suitable for Raspberry Pi 4). (suitable for Raspberry Pi 4).
- `build-aarch64-portable`: builds a version 64 bit ARM processors which avoids - `build-aarch64-portable`: builds a version for 64-bit ARM processors which avoids using some
using some modern CPU instructions that might cause an "illegal modern CPU instructions. In practice, very few ARM processors lack the instructions necessary to
instruction" error on older CPUs. run the faster non-portable build.
### Example ### Example

View File

@ -43,9 +43,6 @@ OPTIONS:
--secrets-dir <SECRETS_DIR> --secrets-dir <SECRETS_DIR>
The path where the validator keystore passwords will be stored. Defaults to ~/.lighthouse/{testnet}/secrets The path where the validator keystore passwords will be stored. Defaults to ~/.lighthouse/{testnet}/secrets
-s, --spec <TITLE>
Specifies the default eth2 spec type. [default: mainnet] [possible values: mainnet, minimal, interop]
--testnet <testnet> --testnet <testnet>
Name of network lighthouse will connect to [possible values: medalla, altona] Name of network lighthouse will connect to [possible values: medalla, altona]
@ -81,4 +78,4 @@ This command will:
`--testnet` CLI param. `--testnet` CLI param.
- Store a password to the validators voting keypair in `~/.lighthouse/{testnet}/secrets`. - 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`). where `testnet` is the name of the testnet passed in the `--testnet` parameter (default is `medalla`).

View File

@ -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 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 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. 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> -t, --testnet-dir <DIR>
Path to directory containing eth2_testnet specs. Defaults to a hard-coded Lighthouse testnet. Only effective Path to directory containing eth2_testnet specs. Defaults to a hard-coded Lighthouse testnet. Only effective
if there is no existing database. if there is no existing database.

View File

@ -1,6 +1,6 @@
[package] [package]
name = "boot_node" name = "boot_node"
version = "0.3.1" version = "0.3.2"
authors = ["Sigma Prime <contact@sigmaprime.io>"] authors = ["Sigma Prime <contact@sigmaprime.io>"]
edition = "2018" edition = "2018"

View File

@ -5,7 +5,6 @@ use eth2_libp2p::{
discovery::{create_enr_builder_from_config, use_or_load_enr}, discovery::{create_enr_builder_from_config, use_or_load_enr},
load_private_key, CombinedKeyExt, NetworkConfig, load_private_key, CombinedKeyExt, NetworkConfig,
}; };
use eth2_testnet_config::Eth2TestnetConfig;
use ssz::Encode; use ssz::Encode;
use std::convert::TryFrom; use std::convert::TryFrom;
use std::marker::PhantomData; use std::marker::PhantomData;
@ -30,7 +29,7 @@ impl<T: EthSpec> TryFrom<&ArgMatches<'_>> for BootNodeConfig<T> {
let data_dir = get_data_dir(matches); let data_dir = get_data_dir(matches);
// Try and grab testnet config from input CLI params // 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") { if matches.is_present("testnet") {
Some(get_eth2_testnet_config(&matches)?) Some(get_eth2_testnet_config(&matches)?)
} else { } else {
@ -95,7 +94,9 @@ impl<T: EthSpec> TryFrom<&ArgMatches<'_>> for BootNodeConfig<T> {
.apply_to_chain_spec::<T>(&T::default_spec()) .apply_to_chain_spec::<T>(&T::default_spec())
.ok_or_else(|| "The loaded config is not compatible with the current 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()); slog::info!(logger, "Genesis state found"; "root" => genesis_state.canonical_root().to_string());
let enr_fork = spec.enr_fork_id( let enr_fork = spec.enr_fork_id(
types::Slot::from(0u64), types::Slot::from(0u64),

View File

@ -8,12 +8,12 @@ mod config;
mod server; mod server;
pub use cli::cli_app; pub use cli::cli_app;
use config::BootNodeConfig; use config::BootNodeConfig;
use types::EthSpec; use types::{EthSpec, EthSpecId};
const LOG_CHANNEL_SIZE: usize = 2048; const LOG_CHANNEL_SIZE: usize = 2048;
/// Run the bootnode given the CLI configuration. /// 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() { let debug_level = match debug_level.as_str() {
"trace" => log::Level::Trace, "trace" => log::Level::Trace,
"debug" => log::Level::Debug, "debug" => log::Level::Debug,
@ -48,11 +48,10 @@ pub fn run(matches: &ArgMatches<'_>, debug_level: String) {
let log = slog_scope::logger(); let log = slog_scope::logger();
// Run the main function emitting any errors // Run the main function emitting any errors
if let Err(e) = match matches.value_of("spec") { if let Err(e) = match eth_spec_id {
Some("minimal") => main::<types::MinimalEthSpec>(matches, log), EthSpecId::Minimal => main::<types::MinimalEthSpec>(matches, log),
Some("mainnet") => main::<types::MainnetEthSpec>(matches, log), EthSpecId::Mainnet => main::<types::MainnetEthSpec>(matches, log),
Some("interop") => main::<types::InteropEthSpec>(matches, log), EthSpecId::V012Legacy => main::<types::V012LegacyEthSpec>(matches, log),
spec => unreachable!("Unknown spec configuration: {:?}", spec),
} { } {
slog::crit!(slog_scope::logger(), "{}", e); slog::crit!(slog_scope::logger(), "{}", e);
} }

View File

@ -5,7 +5,6 @@ use eth2_testnet_config::Eth2TestnetConfig;
use ssz::Decode; use ssz::Decode;
use std::path::PathBuf; use std::path::PathBuf;
use std::str::FromStr; use std::str::FromStr;
use types::EthSpec;
pub const BAD_TESTNET_DIR_MESSAGE: &str = "The hard-coded testnet directory was invalid. \ pub const BAD_TESTNET_DIR_MESSAGE: &str = "The hard-coded testnet directory was invalid. \
This happens when Lighthouse is migrating between spec versions \ 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 /// 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. /// 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, matches: &ArgMatches,
name: &'static str, name: &'static str,
) -> Result<Option<Eth2TestnetConfig<E>>, String> { ) -> Result<Option<Eth2TestnetConfig>, String> {
let path = parse_required::<PathBuf>(matches, name)?; let path = parse_required::<PathBuf>(matches, name)?;
Eth2TestnetConfig::load(path.clone()) Eth2TestnetConfig::load(path.clone())
.map_err(|e| format!("Unable to open testnet dir at {:?}: {}", path, e)) .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 /// Attempts to load a hardcoded network config if `name` is in `matches`, returning an error if
/// the name is not a valid network name. /// the name is not a valid network name.
pub fn parse_hardcoded_network<E: EthSpec>( pub fn parse_hardcoded_network(
matches: &ArgMatches, matches: &ArgMatches,
name: &str, name: &str,
) -> Result<Option<Eth2TestnetConfig<E>>, String> { ) -> Result<Option<Eth2TestnetConfig>, String> {
let network_name = parse_required::<String>(matches, name)?; let network_name = parse_required::<String>(matches, name)?;
Eth2TestnetConfig::constant(network_name.as_str()) Eth2TestnetConfig::constant(network_name.as_str())
} }

View File

@ -1,7 +1,7 @@
use serde_derive::{Deserialize, Serialize}; use serde_derive::{Deserialize, Serialize};
use std::env; use std::env;
use std::path::PathBuf; 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!`. // A macro is used to define this constant so it can be used with `include_bytes!`.
#[macro_export] #[macro_export]
@ -19,14 +19,14 @@ pub const GENESIS_ZIP_FILE_NAME: &str = "genesis.ssz.zip";
#[derive(Debug, Clone, Serialize, Deserialize)] #[derive(Debug, Clone, Serialize, Deserialize)]
#[serde(default)] #[serde(default)]
pub struct Eth2Config { pub struct Eth2Config {
pub spec_constants: String, pub eth_spec_id: EthSpecId,
pub spec: ChainSpec, pub spec: ChainSpec,
} }
impl Default for Eth2Config { impl Default for Eth2Config {
fn default() -> Self { fn default() -> Self {
Self { Self {
spec_constants: "minimal".to_string(), eth_spec_id: EthSpecId::Minimal,
spec: ChainSpec::minimal(), spec: ChainSpec::minimal(),
} }
} }
@ -35,22 +35,22 @@ impl Default for Eth2Config {
impl Eth2Config { impl Eth2Config {
pub fn mainnet() -> Self { pub fn mainnet() -> Self {
Self { Self {
spec_constants: "mainnet".to_string(), eth_spec_id: EthSpecId::Mainnet,
spec: ChainSpec::mainnet(), spec: ChainSpec::mainnet(),
} }
} }
pub fn minimal() -> Self { pub fn minimal() -> Self {
Self { Self {
spec_constants: "minimal".to_string(), eth_spec_id: EthSpecId::Minimal,
spec: ChainSpec::minimal(), spec: ChainSpec::minimal(),
} }
} }
pub fn interop() -> Self { pub fn v012_legacy() -> Self {
Self { Self {
spec_constants: "interop".to_string(), eth_spec_id: EthSpecId::V012Legacy,
spec: ChainSpec::interop(), spec: ChainSpec::v012_legacy(),
} }
} }
} }

View File

@ -1,3 +1,4 @@
CONFIG_NAME: "altona"
MAX_COMMITTEES_PER_SLOT: 64 MAX_COMMITTEES_PER_SLOT: 64
TARGET_COMMITTEE_SIZE: 128 TARGET_COMMITTEE_SIZE: 128
MAX_VALIDATORS_PER_COMMITTEE: 2048 MAX_VALIDATORS_PER_COMMITTEE: 2048
@ -56,3 +57,4 @@ DOMAIN_SELECTION_PROOF: 0x05000000
DOMAIN_AGGREGATE_AND_PROOF: 0x06000000 DOMAIN_AGGREGATE_AND_PROOF: 0x06000000
DEPOSIT_CHAIN_ID: 5 DEPOSIT_CHAIN_ID: 5
DEPOSIT_NETWORK_ID: 5 DEPOSIT_NETWORK_ID: 5
PROPORTIONAL_SLASHING_MULTIPLIER: 3

View File

@ -1,3 +1,4 @@
CONFIG_NAME: "medalla"
MAX_COMMITTEES_PER_SLOT: 64 MAX_COMMITTEES_PER_SLOT: 64
TARGET_COMMITTEE_SIZE: 128 TARGET_COMMITTEE_SIZE: 128
MAX_VALIDATORS_PER_COMMITTEE: 2048 MAX_VALIDATORS_PER_COMMITTEE: 2048
@ -56,3 +57,4 @@ DOMAIN_SELECTION_PROOF: 0x05000000
DOMAIN_AGGREGATE_AND_PROOF: 0x06000000 DOMAIN_AGGREGATE_AND_PROOF: 0x06000000
DEPOSIT_CHAIN_ID: 5 DEPOSIT_CHAIN_ID: 5
DEPOSIT_NETWORK_ID: 5 DEPOSIT_NETWORK_ID: 5
PROPORTIONAL_SLASHING_MULTIPLIER: 3

View File

@ -1,3 +1,4 @@
CONFIG_NAME: "spadina"
MAX_COMMITTEES_PER_SLOT: 64 MAX_COMMITTEES_PER_SLOT: 64
TARGET_COMMITTEE_SIZE: 128 TARGET_COMMITTEE_SIZE: 128
MAX_VALIDATORS_PER_COMMITTEE: 2048 MAX_VALIDATORS_PER_COMMITTEE: 2048

View File

@ -13,11 +13,11 @@ use eth2_config::{
}; };
use enr::{CombinedKey, Enr}; use enr::{CombinedKey, Enr};
use ssz::{Decode, Encode}; use ssz::Decode;
use std::fs::{create_dir_all, File}; use std::fs::{create_dir_all, File};
use std::io::{Read, Write}; use std::io::{Read, Write};
use std::path::PathBuf; 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 ADDRESS_FILE: &str = "deposit_contract.txt";
pub const DEPLOY_BLOCK_FILE: &str = "deploy_block.txt"; pub const DEPLOY_BLOCK_FILE: &str = "deploy_block.txt";
@ -33,7 +33,7 @@ pub struct HardcodedNet {
pub deploy_block: &'static [u8], pub deploy_block: &'static [u8],
pub boot_enr: &'static [u8], pub boot_enr: &'static [u8],
pub deposit_contract_address: &'static [u8], pub deposit_contract_address: &'static [u8],
pub genesis_state: &'static [u8], pub genesis_state_bytes: &'static [u8],
} }
macro_rules! define_net { macro_rules! define_net {
@ -47,7 +47,7 @@ macro_rules! define_net {
deploy_block: $include_file!("../", "deploy_block.txt"), deploy_block: $include_file!("../", "deploy_block.txt"),
boot_enr: $include_file!("../", "boot_enr.yaml"), boot_enr: $include_file!("../", "boot_enr.yaml"),
deposit_contract_address: $include_file!("../", "deposit_contract.txt"), 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. /// See the crate-level documentation for more details.
#[derive(Clone, PartialEq, Debug)] #[derive(Clone, PartialEq, Debug)]
pub struct Eth2TestnetConfig<E: EthSpec> { pub struct Eth2TestnetConfig {
pub deposit_contract_address: String, pub deposit_contract_address: String,
pub deposit_contract_deploy_block: u64, pub deposit_contract_deploy_block: u64,
pub boot_enr: Option<Vec<Enr<CombinedKey>>>, 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>, pub yaml_config: Option<YamlConfig>,
} }
impl<E: EthSpec> Eth2TestnetConfig<E> { impl Eth2TestnetConfig {
/// Returns the default hard coded testnet. /// Returns the default hard coded testnet.
pub fn hard_coded_default() -> Result<Option<Self>, String> { pub fn hard_coded_default() -> Result<Option<Self>, String> {
Self::constant(DEFAULT_HARDCODED_TESTNET) Self::constant(DEFAULT_HARDCODED_TESTNET)
@ -89,15 +89,6 @@ impl<E: EthSpec> Eth2TestnetConfig<E> {
/// Instantiates `Self` from a `HardcodedNet`. /// Instantiates `Self` from a `HardcodedNet`.
fn from_hardcoded_net(net: &HardcodedNet) -> Result<Self, String> { 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 { Ok(Self {
deposit_contract_address: serde_yaml::from_reader(net.deposit_contract_address) deposit_contract_address: serde_yaml::from_reader(net.deposit_contract_address)
.map_err(|e| format!("Unable to parse contract address: {:?}", e))?, .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) serde_yaml::from_reader(net.boot_enr)
.map_err(|e| format!("Unable to parse boot enr: {:?}", e))?, .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( yaml_config: Some(
serde_yaml::from_reader(net.yaml_config) serde_yaml::from_reader(net.yaml_config)
.map_err(|e| format!("Unable to parse yaml config: {:?}", e))?, .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. /// Returns an identifier that should be used for selecting an `EthSpec` instance for this
// /// testnet.
// Overwrites files if specified to do so. 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> { pub fn write_to_file(&self, base_dir: PathBuf, overwrite: bool) -> Result<(), String> {
if base_dir.exists() && !overwrite { if base_dir.exists() && !overwrite {
return Err("Testnet directory already exists".to_string()); return Err("Testnet directory already exists".to_string());
@ -126,7 +147,7 @@ impl<E: EthSpec> Eth2TestnetConfig<E> {
self.force_write_to_file(base_dir) 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> { pub fn force_write_to_file(&self, base_dir: PathBuf) -> Result<(), String> {
create_dir_all(&base_dir) create_dir_all(&base_dir)
.map_err(|e| format!("Unable to create testnet directory: {:?}", e))?; .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. // 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); let file = base_dir.join(GENESIS_STATE_FILE);
File::create(&file) File::create(&file)
.map_err(|e| format!("Unable to create {:?}: {:?}", file, e)) .map_err(|e| format!("Unable to create {:?}: {:?}", file, e))
.and_then(|mut file| { .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)) .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. // 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_file_path = base_dir.join(GENESIS_STATE_FILE);
let genesis_state = if genesis_file_path.exists() { let genesis_state_bytes = if genesis_file_path.exists() {
Some( let mut bytes = vec![];
File::open(&genesis_file_path) File::open(&genesis_file_path)
.map_err(|e| format!("Unable to open {:?}: {:?}", genesis_file_path, e)) .map_err(|e| format!("Unable to open {:?}: {:?}", genesis_file_path, e))
.and_then(|mut file| { .and_then(|mut file| {
let mut bytes = vec![]; file.read_to_end(&mut bytes)
file.read_to_end(&mut bytes) .map_err(|e| format!("Unable to read {:?}: {:?}", file, e))
.map_err(|e| format!("Unable to read {:?}: {:?}", file, e))?; })?;
Some(bytes)
BeaconState::from_ssz_bytes(&bytes)
.map_err(|e| format!("Unable to SSZ decode {:?}: {:?}", file, e))
})?,
)
} else { } else {
None None
}; };
@ -231,7 +248,7 @@ impl<E: EthSpec> Eth2TestnetConfig<E> {
deposit_contract_address, deposit_contract_address,
deposit_contract_deploy_block, deposit_contract_deploy_block,
boot_enr, boot_enr,
genesis_state, genesis_state_bytes,
yaml_config, yaml_config,
}) })
} }
@ -250,18 +267,28 @@ impl<E: EthSpec> Eth2TestnetConfig<E> {
#[cfg(test)] #[cfg(test)]
mod tests { mod tests {
use super::*; use super::*;
use ssz::Encode;
use tempdir::TempDir; use tempdir::TempDir;
use types::{Eth1Data, Hash256, MainnetEthSpec, YamlConfig}; use types::{Eth1Data, Hash256, V012LegacyEthSpec, YamlConfig};
type E = MainnetEthSpec; type E = V012LegacyEthSpec;
#[test] #[test]
fn hard_coded_nets_work() { fn hard_coded_nets_work() {
for net in HARDCODED_NETS { for net in HARDCODED_NETS {
let config = 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!( assert_eq!(
config.genesis_state.is_some(), config.genesis_state_bytes.is_some(),
net.genesis_is_known, net.genesis_is_known,
"{:?}", "{:?}",
net.name net.name
@ -298,11 +325,11 @@ mod tests {
let deposit_contract_address = "0xBB9bc244D798123fDe783fCc1C72d3Bb8C189413".to_string(); let deposit_contract_address = "0xBB9bc244D798123fDe783fCc1C72d3Bb8C189413".to_string();
let deposit_contract_deploy_block = 42; let deposit_contract_deploy_block = 42;
let testnet: Eth2TestnetConfig<E> = Eth2TestnetConfig { let testnet: Eth2TestnetConfig = Eth2TestnetConfig {
deposit_contract_address, deposit_contract_address,
deposit_contract_deploy_block, deposit_contract_deploy_block,
boot_enr, boot_enr,
genesis_state, genesis_state_bytes: genesis_state.as_ref().map(Encode::as_ssz_bytes),
yaml_config, yaml_config,
}; };

View File

@ -10,7 +10,7 @@ use target_info::Target;
/// `Lighthouse/v0.2.0-1419501f2+` /// `Lighthouse/v0.2.0-1419501f2+`
pub const VERSION: &str = git_version!( pub const VERSION: &str = git_version!(
args = ["--always", "--dirty=+"], args = ["--always", "--dirty=+"],
prefix = "Lighthouse/v0.3.1-", prefix = "Lighthouse/v0.3.2-",
fallback = "unknown" fallback = "unknown"
); );

View File

@ -5,7 +5,7 @@ authors = ["Sigma Prime <contact@sigmaprime.io>"]
edition = "2018" edition = "2018"
[dependencies] [dependencies]
tokio = "0.2.22" tokio = { version = "0.2.22", features = ["rt-threaded", "macros", "blocking"] }
slog = "2.5.2" slog = "2.5.2"
futures = "0.3.5" futures = "0.3.5"
exit-future = "0.2.0" exit-future = "0.2.0"

View File

@ -264,7 +264,6 @@ impl ChainSpec {
hysteresis_quotient: 4, hysteresis_quotient: 4,
hysteresis_downward_multiplier: 1, hysteresis_downward_multiplier: 1,
hysteresis_upward_multiplier: 5, hysteresis_upward_multiplier: 5,
proportional_slashing_multiplier: 3,
/* /*
* Gwei values * Gwei values
@ -283,7 +282,7 @@ impl ChainSpec {
/* /*
* Time parameters * Time parameters
*/ */
genesis_delay: 172800, // 2 days genesis_delay: 604800, // 7 days
milliseconds_per_slot: 12_000, milliseconds_per_slot: 12_000,
min_attestation_inclusion_delay: 1, min_attestation_inclusion_delay: 1,
min_seed_lookahead: Epoch::new(1), min_seed_lookahead: Epoch::new(1),
@ -298,8 +297,9 @@ impl ChainSpec {
base_reward_factor: 64, base_reward_factor: 64,
whistleblower_reward_quotient: 512, whistleblower_reward_quotient: 512,
proposer_reward_quotient: 8, proposer_reward_quotient: 8,
inactivity_penalty_quotient: u64::pow(2, 24), inactivity_penalty_quotient: u64::pow(2, 26),
min_slashing_penalty_quotient: 32, min_slashing_penalty_quotient: 128,
proportional_slashing_multiplier: 1,
/* /*
* Signature domains * Signature domains
@ -320,7 +320,7 @@ impl ChainSpec {
/* /*
* Eth1 * Eth1
*/ */
eth1_follow_distance: 1_024, eth1_follow_distance: 2048,
seconds_per_eth1_block: 14, seconds_per_eth1_block: 14,
deposit_chain_id: 1, deposit_chain_id: 1,
deposit_network_id: 1, deposit_network_id: 1,
@ -359,6 +359,9 @@ impl ChainSpec {
shard_committee_period: 64, shard_committee_period: 64,
genesis_delay: 300, genesis_delay: 300,
milliseconds_per_slot: 6_000, 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, safe_slots_to_update_justified: 2,
network_id: 2, // lighthouse testnet network id network_id: 2, // lighthouse testnet network id
deposit_chain_id: 5, 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. /// This method only needs to exist whilst we provide support for "legacy" testnets prior to v1.0.0
pub fn interop() -> Self { /// (e.g., Medalla, Zinken, Spadina, Altona, etc.).
pub fn v012_legacy() -> Self {
let boot_nodes = vec![]; let boot_nodes = vec![];
Self { Self {
milliseconds_per_slot: 12_000, genesis_delay: 172_800, // 2 days
target_committee_size: 4, inactivity_penalty_quotient: u64::pow(2, 24),
shuffle_round_count: 10, min_slashing_penalty_quotient: 32,
network_id: 13, eth1_follow_distance: 1024,
boot_nodes, boot_nodes,
..ChainSpec::mainnet() ..ChainSpec::mainnet()
} }
@ -448,8 +453,7 @@ mod tests {
#[derive(Serialize, Deserialize, Debug, PartialEq, Clone)] #[derive(Serialize, Deserialize, Debug, PartialEq, Clone)]
#[serde(rename_all = "UPPERCASE", deny_unknown_fields)] #[serde(rename_all = "UPPERCASE", deny_unknown_fields)]
pub struct YamlConfig { pub struct YamlConfig {
#[serde(default)] pub config_name: String,
config_name: String,
// ChainSpec // ChainSpec
#[serde(with = "serde_utils::quoted_u64")] #[serde(with = "serde_utils::quoted_u64")]
max_committees_per_slot: u64, max_committees_per_slot: u64,
@ -481,10 +485,6 @@ pub struct YamlConfig {
hysteresis_downward_multiplier: u64, hysteresis_downward_multiplier: u64,
#[serde(with = "serde_utils::quoted_u64")] #[serde(with = "serde_utils::quoted_u64")]
hysteresis_upward_multiplier: 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")] #[serde(with = "serde_utils::bytes_4_hex")]
genesis_fork_version: [u8; 4], genesis_fork_version: [u8; 4],
#[serde(with = "serde_utils::u8_hex")] #[serde(with = "serde_utils::u8_hex")]
@ -514,6 +514,8 @@ pub struct YamlConfig {
#[serde(with = "serde_utils::quoted_u64")] #[serde(with = "serde_utils::quoted_u64")]
min_slashing_penalty_quotient: u64, min_slashing_penalty_quotient: u64,
#[serde(with = "serde_utils::quoted_u64")] #[serde(with = "serde_utils::quoted_u64")]
proportional_slashing_multiplier: u64,
#[serde(with = "serde_utils::quoted_u64")]
safe_slots_to_update_justified: u64, safe_slots_to_update_justified: u64,
#[serde(with = "serde_utils::u32_hex")] #[serde(with = "serde_utils::u32_hex")]
@ -575,11 +577,6 @@ pub struct YamlConfig {
deposit_contract_address: Address, 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 { impl Default for YamlConfig {
fn default() -> Self { fn default() -> Self {
let chain_spec = MainnetEthSpec::default_spec(); let chain_spec = MainnetEthSpec::default_spec();
@ -594,6 +591,21 @@ fn milliseconds_to_seconds(millis: u64) -> u64 {
/// Spec v0.12.1 /// Spec v0.12.1
impl YamlConfig { 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 { pub fn from_spec<T: EthSpec>(spec: &ChainSpec) -> Self {
Self { Self {
config_name: T::spec_name().to_string(), config_name: T::spec_name().to_string(),

View File

@ -6,7 +6,45 @@ use ssz_types::typenum::{
Unsigned, U0, U1024, U1099511627776, U128, U16, U16777216, U2, U2048, U32, U4, U4096, U64, Unsigned, U0, U1024, U1099511627776, U128, U16, U16777216, U2, U2048, U32, U4, U4096, U64,
U65536, U8, U8192, 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 { 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 default_spec() -> ChainSpec;
fn spec_name() -> &'static str; fn spec_name() -> EthSpecId;
fn genesis_epoch() -> Epoch { fn genesis_epoch() -> Epoch {
Epoch::new(Self::GenesisEpoch::to_u64()) Epoch::new(Self::GenesisEpoch::to_u64())
@ -144,7 +182,7 @@ impl EthSpec for MainnetEthSpec {
type MaxValidatorsPerCommittee = U2048; type MaxValidatorsPerCommittee = U2048;
type GenesisEpoch = U0; type GenesisEpoch = U0;
type SlotsPerEpoch = U32; type SlotsPerEpoch = U32;
type EpochsPerEth1VotingPeriod = U32; type EpochsPerEth1VotingPeriod = U64;
type SlotsPerHistoricalRoot = U8192; type SlotsPerHistoricalRoot = U8192;
type EpochsPerHistoricalVector = U65536; type EpochsPerHistoricalVector = U65536;
type EpochsPerSlashingsVector = U8192; type EpochsPerSlashingsVector = U8192;
@ -156,14 +194,14 @@ impl EthSpec for MainnetEthSpec {
type MaxDeposits = U16; type MaxDeposits = U16;
type MaxVoluntaryExits = U16; type MaxVoluntaryExits = U16;
type MaxPendingAttestations = U4096; // 128 max attestations * 32 slots per epoch 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 { fn default_spec() -> ChainSpec {
ChainSpec::mainnet() ChainSpec::mainnet()
} }
fn spec_name() -> &'static str { fn spec_name() -> EthSpecId {
"mainnet" EthSpecId::Mainnet
} }
} }
@ -203,28 +241,32 @@ impl EthSpec for MinimalEthSpec {
ChainSpec::minimal() ChainSpec::minimal()
} }
fn spec_name() -> &'static str { fn spec_name() -> EthSpecId {
"minimal" EthSpecId::Minimal
} }
} }
pub type MinimalBeaconState = BeaconState<MinimalEthSpec>; 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))] #[cfg_attr(feature = "arbitrary-fuzz", derive(arbitrary::Arbitrary))]
#[derive(Clone, PartialEq, Eq, Debug, Default, Serialize, Deserialize)] #[derive(Clone, PartialEq, Eq, Debug, Default, Serialize, Deserialize)]
pub struct InteropEthSpec; pub struct V012LegacyEthSpec;
impl EthSpec for InteropEthSpec { impl EthSpec for V012LegacyEthSpec {
type SlotsPerEpoch = U8; type EpochsPerEth1VotingPeriod = U32;
type EpochsPerEth1VotingPeriod = U2; type SlotsPerEth1VotingPeriod = U1024; // 32 epochs * 32 slots per epoch
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
params_from_eth_spec!(MainnetEthSpec { params_from_eth_spec!(MainnetEthSpec {
SlotsPerEpoch,
SlotsPerHistoricalRoot,
EpochsPerHistoricalVector,
EpochsPerSlashingsVector,
MaxPendingAttestations,
JustificationBitsLength, JustificationBitsLength,
SubnetBitfieldLength, SubnetBitfieldLength,
MaxValidatorsPerCommittee, MaxValidatorsPerCommittee,
@ -239,12 +281,10 @@ impl EthSpec for InteropEthSpec {
}); });
fn default_spec() -> ChainSpec { fn default_spec() -> ChainSpec {
ChainSpec::interop() ChainSpec::v012_legacy()
} }
fn spec_name() -> &'static str { fn spec_name() -> EthSpecId {
"interop" EthSpecId::V012Legacy
} }
} }
pub type InteropBeaconState = BeaconState<InteropEthSpec>;

View File

@ -73,6 +73,7 @@ pub use crate::deposit_data::DepositData;
pub use crate::deposit_message::DepositMessage; pub use crate::deposit_message::DepositMessage;
pub use crate::enr_fork_id::EnrForkId; pub use crate::enr_fork_id::EnrForkId;
pub use crate::eth1_data::Eth1Data; pub use crate::eth1_data::Eth1Data;
pub use crate::eth_spec::EthSpecId;
pub use crate::fork::Fork; pub use crate::fork::Fork;
pub use crate::fork_data::ForkData; pub use crate::fork_data::ForkData;
pub use crate::free_attestation::FreeAttestation; pub use crate::free_attestation::FreeAttestation;

View File

@ -8,6 +8,7 @@ use ssz_derive::{Decode, Encode};
use std::fmt; use std::fmt;
use test_random_derive::TestRandom; use test_random_derive::TestRandom;
use tree_hash::TreeHash; use tree_hash::TreeHash;
use tree_hash_derive::TreeHash;
#[cfg_attr(feature = "arbitrary-fuzz", derive(arbitrary::Arbitrary))] #[cfg_attr(feature = "arbitrary-fuzz", derive(arbitrary::Arbitrary))]
#[derive(PartialEq, Eq, Hash, Clone, Copy)] #[derive(PartialEq, Eq, Hash, Clone, Copy)]
@ -41,7 +42,7 @@ impl From<SignedBeaconBlockHash> for Hash256 {
/// ///
/// Spec v0.12.1 /// Spec v0.12.1
#[cfg_attr(feature = "arbitrary-fuzz", derive(arbitrary::Arbitrary))] #[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")] #[serde(bound = "E: EthSpec")]
pub struct SignedBeaconBlock<E: EthSpec> { pub struct SignedBeaconBlock<E: EthSpec> {
pub message: BeaconBlock<E>, pub message: BeaconBlock<E>,

View File

@ -7,7 +7,7 @@ edition = "2018"
[dependencies] [dependencies]
eth2_ssz = "0.1.2" eth2_ssz = "0.1.2"
tree_hash = "0.1.1" 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" rand = "0.7.3"
serde = "1.0.116" serde = "1.0.116"
serde_derive = "1.0.116" serde_derive = "1.0.116"
@ -17,7 +17,7 @@ eth2_hashing = "0.1.0"
ethereum-types = "0.9.2" ethereum-types = "0.9.2"
arbitrary = { version = "0.4.6", features = ["derive"], optional = true } arbitrary = { version = "0.4.6", features = ["derive"], optional = true }
zeroize = { version = "1.1.1", features = ["zeroize_derive"] } 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] [features]
default = ["supranational"] default = ["supranational"]
@ -25,3 +25,4 @@ fake_crypto = []
milagro = [] milagro = []
supranational = [] supranational = []
supranational-portable = ["supranational", "blst/portable"] supranational-portable = ["supranational", "blst/portable"]
supranational-force-adx = ["supranational", "blst/force-adx"]

View File

@ -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. /// Implemented on some struct from a BLS library so it may be used internally in this crate.
pub trait TAggregatePublicKey: Sized + Clone { 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>;
}
/* /*
* Note: there is no immediate need for a `GenericAggregatePublicKey` struct. * Note: there is no immediate need for a `GenericAggregatePublicKey` struct.

View File

@ -183,13 +183,6 @@ where
return false; 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() { match self.point.as_ref() {
Some(point) => point.fast_aggregate_verify(msg, pubkeys), Some(point) => point.fast_aggregate_verify(msg, pubkeys),
None => false, None => false,
@ -207,13 +200,6 @@ where
return false; 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() { match self.point.as_ref() {
Some(point) => point.aggregate_verify(msgs, pubkeys), Some(point) => point.aggregate_verify(msgs, pubkeys),
None => false, None => false,

View File

@ -33,8 +33,6 @@ pub trait TPublicKey: Sized + Clone {
pub struct GenericPublicKey<Pub> { pub struct GenericPublicKey<Pub> {
/// The underlying point which performs *actual* cryptographic operations. /// The underlying point which performs *actual* cryptographic operations.
point: Pub, point: Pub,
/// True if this point is equal to the `INFINITY_PUBLIC_KEY`.
pub(crate) is_infinity: bool,
} }
impl<Pub> GenericPublicKey<Pub> impl<Pub> GenericPublicKey<Pub>
@ -42,8 +40,8 @@ where
Pub: TPublicKey, Pub: TPublicKey,
{ {
/// Instantiates `Self` from a `point`. /// Instantiates `Self` from a `point`.
pub(crate) fn from_point(point: Pub, is_infinity: bool) -> Self { pub(crate) fn from_point(point: Pub) -> Self {
Self { point, is_infinity } Self { point }
} }
/// Returns a reference to the underlying BLS point. /// Returns a reference to the underlying BLS point.
@ -63,10 +61,13 @@ where
/// Deserialize `self` from compressed bytes. /// Deserialize `self` from compressed bytes.
pub fn deserialize(bytes: &[u8]) -> Result<Self, Error> { pub fn deserialize(bytes: &[u8]) -> Result<Self, Error> {
Ok(Self { if bytes == &INFINITY_PUBLIC_KEY[..] {
point: Pub::deserialize(bytes)?, Err(Error::InvalidInfinityPublicKey)
is_infinity: bytes == &INFINITY_PUBLIC_KEY[..], } else {
}) Ok(Self {
point: Pub::deserialize(bytes)?,
})
}
} }
} }

View File

@ -1,6 +1,6 @@
use crate::{ use crate::{
generic_public_key::{GenericPublicKey, TPublicKey}, 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::de::{Deserialize, Deserializer};
use serde::ser::{Serialize, Serializer}; use serde::ser::{Serialize, Serializer};
@ -32,8 +32,7 @@ where
/// ///
/// May fail if the bytes are invalid. /// May fail if the bytes are invalid.
pub fn decompress(&self) -> Result<GenericPublicKey<Pub>, Error> { pub fn decompress(&self) -> Result<GenericPublicKey<Pub>, Error> {
let is_infinity = self.bytes[..] == INFINITY_PUBLIC_KEY[..]; GenericPublicKey::deserialize(&self.bytes)
Pub::deserialize(&self.bytes).map(|point| GenericPublicKey::from_point(point, is_infinity))
} }
} }

View File

@ -58,8 +58,7 @@ where
/// Returns the public key that corresponds to self. /// Returns the public key that corresponds to self.
pub fn public_key(&self) -> GenericPublicKey<Pub> { pub fn public_key(&self) -> GenericPublicKey<Pub> {
let is_infinity = false; GenericPublicKey::from_point(self.point.public_key())
GenericPublicKey::from_point(self.point.public_key(), is_infinity)
} }
/// Serialize `self` as compressed bytes. /// Serialize `self` as compressed bytes.
@ -79,6 +78,8 @@ where
got: bytes.len(), got: bytes.len(),
expected: SECRET_KEY_BYTES_LEN, expected: SECRET_KEY_BYTES_LEN,
}) })
} else if bytes.iter().all(|b| *b == 0) {
Err(Error::InvalidZeroSecretKey)
} else { } else {
Ok(Self { Ok(Self {
point: Sec::deserialize(bytes)?, point: Sec::deserialize(bytes)?,

View File

@ -125,10 +125,6 @@ where
{ {
/// Returns `true` if `self` is a signature across `msg` by `pubkey`. /// Returns `true` if `self` is a signature across `msg` by `pubkey`.
pub fn verify(&self, pubkey: &GenericPublicKey<Pub>, msg: Hash256) -> bool { 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 { if let Some(point) = &self.point {
point.verify(pubkey.point(), msg) point.verify(pubkey.point(), msg)
} else { } else {

View File

@ -4,7 +4,7 @@ use crate::{
generic_public_key::{GenericPublicKey, TPublicKey, PUBLIC_KEY_BYTES_LEN}, generic_public_key::{GenericPublicKey, TPublicKey, PUBLIC_KEY_BYTES_LEN},
generic_secret_key::TSecretKey, generic_secret_key::TSecretKey,
generic_signature::{TSignature, SIGNATURE_BYTES_LEN}, 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; pub use blst::min_pk as blst_core;
use blst::{blst_scalar, BLST_ERROR}; use blst::{blst_scalar, BLST_ERROR};
@ -50,18 +50,12 @@ pub fn verify_signature_sets<'a>(
let mut pks = Vec::with_capacity(sets.len()); let mut pks = Vec::with_capacity(sets.len());
for set in &sets { 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. // Generate random scalars.
let mut vals = [0u64; 4]; 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(); let mut rand_i = std::mem::MaybeUninit::<blst_scalar>::uninit();
// TODO: remove this `unsafe` code-block once we get a safe option from `blst`. // 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. // Grab a slice of the message, to satisfy the blst API.
msgs_refs.push(set.message.as_bytes()); msgs_refs.push(set.message.as_bytes());
// Convert the aggregate signature into a signature.
if let Some(point) = set.signature.point() { 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()) sigs.push(point.0.to_signature())
} else { } else {
// Any "empty" signature should cause a signature failure. // 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()); 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 (sig_refs, pks_refs): (Vec<_>, Vec<_>) = sigs.iter().zip(pks.iter()).unzip();
let err = blst_core::Signature::verify_multiple_aggregate_signatures( 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> { 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 { 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 TSignature<blst_core::PublicKey> for blst_core::Signature { impl TSignature<blst_core::PublicKey> for blst_core::Signature {
fn serialize(&self) -> [u8; SIGNATURE_BYTES_LEN] { 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 { 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 self.verify(msg.as_bytes(), DST, &[], pubkey) == BLST_ERROR::BLST_SUCCESS
} }
} }
@ -232,6 +217,9 @@ impl TAggregateSignature<blst_core::PublicKey, BlstAggregatePublicKey, blst_core
) -> bool { ) -> bool {
let pubkeys = pubkeys.iter().map(|pk| pk.point()).collect::<Vec<_>>(); let pubkeys = pubkeys.iter().map(|pk| pk.point()).collect::<Vec<_>>();
let signature = self.0.clone().to_signature(); 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 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 pubkeys = pubkeys.iter().map(|pk| pk.point()).collect::<Vec<_>>();
let msgs = msgs.iter().map(|hash| hash.as_bytes()).collect::<Vec<_>>(); let msgs = msgs.iter().map(|hash| hash.as_bytes()).collect::<Vec<_>>();
let signature = self.0.clone().to_signature(); let signature = self.0.clone().to_signature();
if !signature.subgroup_check() {
return false;
}
signature.aggregate_verify(&msgs, DST, &pubkeys) == BLST_ERROR::BLST_SUCCESS signature.aggregate_verify(&msgs, DST, &pubkeys) == BLST_ERROR::BLST_SUCCESS
} }
} }

View File

@ -63,25 +63,7 @@ impl PartialEq for PublicKey {
#[derive(Clone)] #[derive(Clone)]
pub struct AggregatePublicKey([u8; PUBLIC_KEY_BYTES_LEN]); pub struct AggregatePublicKey([u8; PUBLIC_KEY_BYTES_LEN]);
impl TAggregatePublicKey for AggregatePublicKey { 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 Eq for AggregatePublicKey {} impl Eq for AggregatePublicKey {}

View File

@ -4,7 +4,7 @@ use crate::{
generic_public_key::{GenericPublicKey, TPublicKey, PUBLIC_KEY_BYTES_LEN}, generic_public_key::{GenericPublicKey, TPublicKey, PUBLIC_KEY_BYTES_LEN},
generic_secret_key::{TSecretKey, SECRET_KEY_BYTES_LEN}, generic_secret_key::{TSecretKey, SECRET_KEY_BYTES_LEN},
generic_signature::{TSignature, SIGNATURE_BYTES_LEN}, generic_signature::{TSignature, SIGNATURE_BYTES_LEN},
Error, Hash256, ZeroizeHash, INFINITY_PUBLIC_KEY, Error, Hash256, ZeroizeHash,
}; };
pub use milagro_bls as milagro; pub use milagro_bls as milagro;
use rand::thread_rng; use rand::thread_rng;
@ -86,21 +86,7 @@ impl TPublicKey for milagro::PublicKey {
} }
} }
impl TAggregatePublicKey for milagro::AggregatePublicKey { 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 TSignature<milagro::PublicKey> for milagro::Signature { impl TSignature<milagro::PublicKey> for milagro::Signature {
fn serialize(&self) -> [u8; SIGNATURE_BYTES_LEN] { fn serialize(&self) -> [u8; SIGNATURE_BYTES_LEN] {

View File

@ -56,6 +56,10 @@ pub enum Error {
InvalidByteLength { got: usize, expected: usize }, InvalidByteLength { got: usize, expected: usize },
/// The provided secret key bytes were an incorrect length. /// The provided secret key bytes were an incorrect length.
InvalidSecretKeyLength { got: usize, expected: usize }, 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 { impl From<AmclError> for Error {

View File

@ -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 ssz::{Decode, Encode};
use std::borrow::Cow; use std::borrow::Cow;
use std::fmt::Debug; use std::fmt::Debug;
@ -19,6 +19,11 @@ macro_rules! test_suite {
SecretKey::deserialize(&secret_bytes).unwrap() SecretKey::deserialize(&secret_bytes).unwrap()
} }
#[test]
fn invalid_zero_secret_key() {
assert!(SecretKey::deserialize(&[0; SECRET_KEY_BYTES_LEN]).is_err());
}
#[test] #[test]
fn infinity_agg_sig() { fn infinity_agg_sig() {
assert_eq!( assert_eq!(
@ -131,11 +136,6 @@ macro_rules! test_suite {
self 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) { pub fn assert_verify(self, is_valid: bool) {
assert_eq!(self.sig.verify(&self.pubkey, self.msg), is_valid); assert_eq!(self.sig.verify(&self.pubkey, self.msg), is_valid);
@ -153,14 +153,6 @@ macro_rules! test_suite {
SignatureTester::default().assert_verify(true) SignatureTester::default().assert_verify(true)
} }
#[test]
fn infinity_signature_is_valid_with_infinity_pubkey() {
SignatureTester::default()
.infinity_sig()
.infinity_pubkey()
.assert_verify(true)
}
#[test] #[test]
fn infinity_signature_is_invalid_with_standard_pubkey() { fn infinity_signature_is_invalid_with_standard_pubkey() {
SignatureTester::default() SignatureTester::default()
@ -168,13 +160,6 @@ macro_rules! test_suite {
.assert_verify(false) .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. /// A helper struct for composing tests via the builder pattern.
struct AggregateSignatureTester { struct AggregateSignatureTester {
sig: AggregateSignature, sig: AggregateSignature,
@ -234,17 +219,6 @@ macro_rules! test_suite {
self 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) { pub fn assert_single_message_verify(self, is_valid: bool) {
assert!(self.msgs.len() == 1); assert!(self.msgs.len() == 1);
let msg = self.msgs.first().unwrap(); let msg = self.msgs.first().unwrap();
@ -304,15 +278,6 @@ macro_rules! test_suite {
.assert_single_message_verify(false) .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. /// Adding a infinity signature (without an infinity pubkey) should verify.
#[test] #[test]
fn fast_aggregate_verify_with_one_aggregated_infinity_sig() { fn fast_aggregate_verify_with_one_aggregated_infinity_sig() {
@ -332,34 +297,6 @@ macro_rules! test_suite {
.assert_single_message_verify(true) .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. /// The wrong signature should not verify.
#[test] #[test]
fn fast_aggregate_verify_wrong_signature() { fn fast_aggregate_verify_wrong_signature() {
@ -463,18 +400,6 @@ macro_rules! test_suite {
self 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 { pub fn push_invalid_pubkey_infinity_set(mut self) -> Self {
self.owned_sets.push(OwnedSignatureSet { self.owned_sets.push(OwnedSignatureSet {
signature: AggregateSignature::deserialize(&INFINITY_SIGNATURE).unwrap(), signature: AggregateSignature::deserialize(&INFINITY_SIGNATURE).unwrap(),
@ -485,16 +410,6 @@ macro_rules! test_suite {
self 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) { pub fn run_checks(self) {
assert!(!self.owned_sets.is_empty(), "empty test is meaningless"); assert!(!self.owned_sets.is_empty(), "empty test is meaningless");
@ -568,22 +483,6 @@ macro_rules! test_suite {
.run_checks() .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] #[test]
fn signature_set_3_sets_with_one_invalid_pubkey_infinity_set() { fn signature_set_3_sets_with_one_invalid_pubkey_infinity_set() {
SignatureSetTester::default() SignatureSetTester::default()
@ -592,15 +491,6 @@ macro_rules! test_suite {
.push_valid_set(2) .push_valid_set(2)
.run_checks() .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()
}
}; };
} }

View File

@ -1,7 +1,7 @@
[package] [package]
name = "lcli" name = "lcli"
description = "Lighthouse CLI (modeled after zcli)" description = "Lighthouse CLI (modeled after zcli)"
version = "0.3.1" version = "0.3.2"
authors = ["Paul Hauner <paul@paulhauner.com>"] authors = ["Paul Hauner <paul@paulhauner.com>"]
edition = "2018" edition = "2018"

View File

@ -2,6 +2,7 @@ use clap::ArgMatches;
use environment::Environment; use environment::Environment;
use eth2_testnet_config::Eth2TestnetConfig; use eth2_testnet_config::Eth2TestnetConfig;
use genesis::{Eth1Config, Eth1GenesisService}; use genesis::{Eth1Config, Eth1GenesisService};
use ssz::Encode;
use std::path::PathBuf; use std::path::PathBuf;
use std::time::Duration; use std::time::Duration;
use types::EthSpec; use types::EthSpec;
@ -24,8 +25,7 @@ pub fn run<T: EthSpec>(mut env: Environment<T>, matches: &ArgMatches<'_>) -> Res
.expect("should locate home directory") .expect("should locate home directory")
}); });
let mut eth2_testnet_config: Eth2TestnetConfig<T> = let mut eth2_testnet_config = Eth2TestnetConfig::load(testnet_dir.clone())?;
Eth2TestnetConfig::load(testnet_dir.clone())?;
let spec = eth2_testnet_config let spec = eth2_testnet_config
.yaml_config .yaml_config
@ -35,7 +35,7 @@ pub fn run<T: EthSpec>(mut env: Environment<T>, matches: &ArgMatches<'_>) -> Res
.ok_or_else(|| { .ok_or_else(|| {
format!( format!(
"The loaded config is not compatible with the {} spec", "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 { env.runtime().block_on(async {
let _ = genesis_service let _ = genesis_service
.wait_for_genesis_state(ETH1_GENESIS_UPDATE_INTERVAL, spec) .wait_for_genesis_state::<T>(ETH1_GENESIS_UPDATE_INTERVAL, spec)
.await .await
.map(move |genesis_state| { .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) eth2_testnet_config.force_write_to_file(testnet_dir)
}) })
.map_err(|e| format!("Failed to find genesis: {}", e))?; .map_err(|e| format!("Failed to find genesis: {}", e))?;

View File

@ -3,6 +3,7 @@ use clap_utils::parse_ssz_optional;
use environment::Environment; use environment::Environment;
use eth2_testnet_config::Eth2TestnetConfig; use eth2_testnet_config::Eth2TestnetConfig;
use genesis::interop_genesis_state; use genesis::interop_genesis_state;
use ssz::Encode;
use std::path::PathBuf; use std::path::PathBuf;
use std::time::{SystemTime, UNIX_EPOCH}; use std::time::{SystemTime, UNIX_EPOCH};
use types::{test_utils::generate_deterministic_keypairs, EthSpec}; 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") .expect("should locate home directory")
}); });
let mut eth2_testnet_config: Eth2TestnetConfig<T> = let mut eth2_testnet_config = Eth2TestnetConfig::load(testnet_dir.clone())?;
Eth2TestnetConfig::load(testnet_dir.clone())?;
let mut spec = eth2_testnet_config let mut spec = eth2_testnet_config
.yaml_config .yaml_config
@ -46,7 +46,7 @@ pub fn run<T: EthSpec>(mut env: Environment<T>, matches: &ArgMatches) -> Result<
.ok_or_else(|| { .ok_or_else(|| {
format!( format!(
"The loaded config is not compatible with the {} spec", "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 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)?; eth2_testnet_config.force_write_to_file(testnet_dir)?;
Ok(()) Ok(())

View File

@ -20,9 +20,12 @@ use parse_hex::run_parse_hex;
use std::fs::File; use std::fs::File;
use std::path::PathBuf; use std::path::PathBuf;
use std::process; use std::process;
use std::str::FromStr;
use std::time::{SystemTime, UNIX_EPOCH}; use std::time::{SystemTime, UNIX_EPOCH};
use transition_blocks::run_transition_blocks; 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() { fn main() {
simple_logger::SimpleLogger::new() simple_logger::SimpleLogger::new()
@ -482,25 +485,21 @@ fn main() {
) )
.get_matches(); .get_matches();
macro_rules! run_with_spec { let result = matches
($env_builder: expr) => { .value_of("spec")
match run($env_builder, &matches) { .ok_or_else(|| "Missing --spec flag".to_string())
Ok(()) => process::exit(0), .and_then(FromStr::from_str)
Err(e) => { .and_then(|eth_spec_id| match eth_spec_id {
println!("Failed to run lcli: {}", e); EthSpecId::Minimal => run(EnvironmentBuilder::minimal(), &matches),
process::exit(1) EthSpecId::Mainnet => run(EnvironmentBuilder::mainnet(), &matches),
} EthSpecId::V012Legacy => run(EnvironmentBuilder::v012_legacy(), &matches),
} });
};
}
match matches.value_of("spec") { match result {
Some("minimal") => run_with_spec!(EnvironmentBuilder::minimal()), Ok(()) => process::exit(0),
Some("mainnet") => run_with_spec!(EnvironmentBuilder::mainnet()), Err(e) => {
Some("interop") => run_with_spec!(EnvironmentBuilder::interop()), println!("Failed to run lcli: {}", e);
spec => { process::exit(1)
// This path should be unreachable due to slog having a `default_value`
unreachable!("Unknown spec configuration: {:?}", spec);
} }
} }
} }

View File

@ -51,11 +51,11 @@ pub fn run<T: EthSpec>(matches: &ArgMatches) -> Result<(), String> {
spec.genesis_fork_version = v; spec.genesis_fork_version = v;
} }
let testnet: Eth2TestnetConfig<T> = Eth2TestnetConfig { let testnet = Eth2TestnetConfig {
deposit_contract_address: format!("{:?}", deposit_contract_address), deposit_contract_address: format!("{:?}", deposit_contract_address),
deposit_contract_deploy_block, deposit_contract_deploy_block,
boot_enr: Some(vec![]), boot_enr: Some(vec![]),
genesis_state: None, genesis_state_bytes: None,
yaml_config: Some(YamlConfig::from_spec::<T>(&spec)), yaml_config: Some(YamlConfig::from_spec::<T>(&spec)),
}; };

View File

@ -1,6 +1,6 @@
[package] [package]
name = "lighthouse" name = "lighthouse"
version = "0.3.1" version = "0.3.2"
authors = ["Sigma Prime <contact@sigmaprime.io>"] authors = ["Sigma Prime <contact@sigmaprime.io>"]
edition = "2018" edition = "2018"
@ -9,6 +9,8 @@ edition = "2018"
write_ssz_files = ["beacon_node/write_ssz_files"] write_ssz_files = ["beacon_node/write_ssz_files"]
# Compiles the BLS crypto code so that the binary is portable across machines. # Compiles the BLS crypto code so that the binary is portable across machines.
portable = ["bls/supranational-portable"] 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. # Uses the slower Milagro BLS library, which is written in native Rust.
milagro = ["bls/milagro"] milagro = ["bls/milagro"]

View File

@ -24,7 +24,7 @@ use std::path::PathBuf;
use std::time::{SystemTime, UNIX_EPOCH}; use std::time::{SystemTime, UNIX_EPOCH};
use task_executor::TaskExecutor; use task_executor::TaskExecutor;
use tokio::runtime::{Builder as RuntimeBuilder, Runtime}; 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"; pub const ETH2_CONFIG_FILENAME: &str = "eth2-spec.toml";
const LOG_CHANNEL_SIZE: usize = 2048; const LOG_CHANNEL_SIZE: usize = 2048;
@ -37,7 +37,7 @@ pub struct EnvironmentBuilder<E: EthSpec> {
log: Option<Logger>, log: Option<Logger>,
eth_spec_instance: E, eth_spec_instance: E,
eth2_config: Eth2Config, eth2_config: Eth2Config,
testnet: Option<Eth2TestnetConfig<E>>, testnet: Option<Eth2TestnetConfig>,
} }
impl EnvironmentBuilder<MinimalEthSpec> { impl EnvironmentBuilder<MinimalEthSpec> {
@ -66,14 +66,14 @@ impl EnvironmentBuilder<MainnetEthSpec> {
} }
} }
impl EnvironmentBuilder<InteropEthSpec> { impl EnvironmentBuilder<V012LegacyEthSpec> {
/// Creates a new builder using the `interop` eth2 specification. /// Creates a new builder using the v0.12.x eth2 specification.
pub fn interop() -> Self { pub fn v012_legacy() -> Self {
Self { Self {
runtime: None, runtime: None,
log: None, log: None,
eth_spec_instance: InteropEthSpec, eth_spec_instance: V012LegacyEthSpec,
eth2_config: Eth2Config::interop(), eth2_config: Eth2Config::v012_legacy(),
testnet: None, testnet: None,
} }
} }
@ -238,7 +238,7 @@ impl<E: EthSpec> EnvironmentBuilder<E> {
/// Adds a testnet configuration to the environment. /// Adds a testnet configuration to the environment.
pub fn eth2_testnet_config( pub fn eth2_testnet_config(
mut self, mut self,
eth2_testnet_config: Eth2TestnetConfig<E>, eth2_testnet_config: Eth2TestnetConfig,
) -> Result<Self, String> { ) -> Result<Self, String> {
// Create a new chain spec from the default configuration. // Create a new chain spec from the default configuration.
self.eth2_config.spec = eth2_testnet_config self.eth2_config.spec = eth2_testnet_config
@ -249,7 +249,7 @@ impl<E: EthSpec> EnvironmentBuilder<E> {
.ok_or_else(|| { .ok_or_else(|| {
format!( format!(
"The loaded config is not compatible with the {} spec", "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. /// Optionally adds a testnet configuration to the environment.
pub fn optional_eth2_testnet_config( pub fn optional_eth2_testnet_config(
self, self,
optional_config: Option<Eth2TestnetConfig<E>>, optional_config: Option<Eth2TestnetConfig>,
) -> Result<Self, String> { ) -> Result<Self, String> {
if let Some(config) = optional_config { if let Some(config) = optional_config {
self.eth2_testnet_config(config) self.eth2_testnet_config(config)
@ -339,7 +339,7 @@ pub struct Environment<E: EthSpec> {
log: Logger, log: Logger,
eth_spec_instance: E, eth_spec_instance: E,
pub eth2_config: Eth2Config, pub eth2_config: Eth2Config,
pub testnet: Option<Eth2TestnetConfig<E>>, pub testnet: Option<Eth2TestnetConfig>,
} }
impl<E: EthSpec> Environment<E> { impl<E: EthSpec> Environment<E> {

View File

@ -3,17 +3,17 @@
use environment::EnvironmentBuilder; use environment::EnvironmentBuilder;
use eth2_testnet_config::Eth2TestnetConfig; use eth2_testnet_config::Eth2TestnetConfig;
use std::path::PathBuf; use std::path::PathBuf;
use types::{MainnetEthSpec, YamlConfig}; use types::{V012LegacyEthSpec, YamlConfig};
fn builder() -> EnvironmentBuilder<MainnetEthSpec> { fn builder() -> EnvironmentBuilder<V012LegacyEthSpec> {
EnvironmentBuilder::mainnet() EnvironmentBuilder::v012_legacy()
.single_thread_tokio_runtime() .single_thread_tokio_runtime()
.expect("should set runtime") .expect("should set runtime")
.null_logger() .null_logger()
.expect("should set 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") Eth2TestnetConfig::hard_coded_default().expect("should decode hard_coded params")
} }

View File

@ -7,7 +7,7 @@ use lighthouse_version::VERSION;
use slog::{crit, info, warn}; use slog::{crit, info, warn};
use std::path::PathBuf; use std::path::PathBuf;
use std::process::exit; use std::process::exit;
use types::EthSpec; use types::{EthSpec, EthSpecId};
use validator_client::ProductionValidatorClient; use validator_client::ProductionValidatorClient;
pub const ETH2_CONFIG_FILENAME: &str = "eth2-spec.toml"; 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 { fn bls_library_name() -> &'static str {
if cfg!(feature = "portable") { if cfg!(feature = "portable") {
"blst-portable" "blst-portable"
} else if cfg!(feature = "modern") {
"blst-modern"
} else if cfg!(feature = "milagro") { } else if cfg!(feature = "milagro") {
"milagro" "milagro"
} else { } else {
@ -43,12 +45,11 @@ fn main() {
Arg::with_name("spec") Arg::with_name("spec")
.short("s") .short("s")
.long("spec") .long("spec")
.value_name("TITLE") .value_name("DEPRECATED")
.help("Specifies the default eth2 spec type.") .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) .takes_value(true)
.possible_values(&["mainnet", "minimal", "interop"])
.global(true) .global(true)
.default_value("mainnet"),
) )
.arg( .arg(
Arg::with_name("env_log") Arg::with_name("env_log")
@ -126,37 +127,35 @@ fn main() {
.subcommand(account_manager::cli_app()) .subcommand(account_manager::cli_app())
.get_matches(); .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. // Debugging output for libp2p and external crates.
if matches.is_present("env_log") { if matches.is_present("env_log") {
Builder::from_env(Env::default()).init(); Builder::from_env(Env::default()).init();
} }
macro_rules! run_with_spec { let result = load_testnet_config(&matches).and_then(|testnet_config| {
($env_builder: expr) => { let eth_spec_id = testnet_config.eth_spec_id()?;
run($env_builder, &matches)
};
}
let result = match matches.value_of("spec") { // boot node subcommand circumvents the environment
Some("minimal") => run_with_spec!(EnvironmentBuilder::minimal()), if let Some(bootnode_matches) = matches.subcommand_matches("boot_node") {
Some("mainnet") => run_with_spec!(EnvironmentBuilder::mainnet()), // The bootnode uses the main debug-level flag
Some("interop") => run_with_spec!(EnvironmentBuilder::interop()), let debug_info = matches
spec => { .value_of("debug-level")
// This path should be unreachable due to slog having a `default_value` .expect("Debug-level must be present")
unreachable!("Unknown spec configuration: {:?}", spec); .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. // `std::process::exit` does not run destructors so we drop manually.
drop(matches); 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>( fn run<E: EthSpec>(
environment_builder: EnvironmentBuilder<E>, environment_builder: EnvironmentBuilder<E>,
matches: &ArgMatches, matches: &ArgMatches,
testnet_config: Eth2TestnetConfig,
) -> Result<(), String> { ) -> Result<(), String> {
if std::mem::size_of::<usize>() != 8 { if std::mem::size_of::<usize>() != 8 {
return Err(format!( 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 let debug_level = matches
.value_of("debug-level") .value_of("debug-level")
.ok_or_else(|| "Expected --debug-level flag".to_string())?; .ok_or_else(|| "Expected --debug-level flag".to_string())?;
let log_format = matches.value_of("log-format"); 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 builder = if let Some(log_path) = matches.value_of("logfile") {
let path = log_path let path = log_path
.parse::<PathBuf>() .parse::<PathBuf>()
@ -213,11 +220,18 @@ fn run<E: EthSpec>(
let mut environment = builder let mut environment = builder
.multi_threaded_tokio_runtime()? .multi_threaded_tokio_runtime()?
.optional_eth2_testnet_config(optional_testnet_config)? .optional_eth2_testnet_config(Some(testnet_config))?
.build()?; .build()?;
let log = environment.core_context().log().clone(); 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 // Note: the current code technically allows for starting a beacon node _and_ a validator
// client at the same time. // client at the same time.
// //
@ -264,7 +278,6 @@ fn run<E: EthSpec>(
let executor = context.executor.clone(); let executor = context.executor.clone();
let config = beacon_node::get_config::<E>( let config = beacon_node::get_config::<E>(
matches, matches,
&context.eth2_config.spec_constants,
&context.eth2_config().spec, &context.eth2_config().spec,
context.log().clone(), context.log().clone(),
)?; )?;

View File

@ -1,4 +1,4 @@
TESTS_TAG := v0.12.3 TESTS_TAG := v1.0.0-rc.0
TESTS = general minimal mainnet TESTS = general minimal mainnet
TARBALLS = $(patsubst %,%-$(TESTS_TAG).tar.gz,$(TESTS)) TARBALLS = $(patsubst %,%-$(TESTS_TAG).tar.gz,$(TESTS))

View File

@ -1,13 +1,13 @@
use super::*; use super::*;
use crate::case_result::compare_result; use crate::case_result::compare_result;
use crate::cases::common::BlsCase; use crate::cases::common::BlsCase;
use bls::{AggregateSignature, PublicKey}; use bls::{AggregateSignature, PublicKeyBytes};
use serde_derive::Deserialize; use serde_derive::Deserialize;
use types::Hash256; use types::Hash256;
#[derive(Debug, Clone, Deserialize)] #[derive(Debug, Clone, Deserialize)]
pub struct BlsAggregateVerifyInput { pub struct BlsAggregateVerifyInput {
pub pubkeys: Vec<PublicKey>, pub pubkeys: Vec<PublicKeyBytes>,
pub messages: Vec<String>, pub messages: Vec<String>,
pub signature: String, pub signature: String,
} }
@ -33,14 +33,29 @@ impl Case for BlsAggregateVerify {
}) })
.collect::<Result<Vec<_>, _>>()?; .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..]) let signature_bytes = hex::decode(&self.input.signature[2..])
.map_err(|e| Error::FailedToParseTest(format!("{:?}", e)))?; .map_err(|e| Error::FailedToParseTest(format!("{:?}", e)))?;
let signature_valid = AggregateSignature::deserialize(&signature_bytes) let signature_valid = AggregateSignature::deserialize(&signature_bytes)
.ok() .ok()
.map(|signature| signature.aggregate_verify(&messages, &pubkey_refs)) .map(|signature| signature.aggregate_verify(&messages, &pubkey_refs[..]))
.unwrap_or(false); .unwrap_or(false);
compare_result::<bool, ()>(&Ok(signature_valid), &Some(self.output)) compare_result::<bool, ()>(&Ok(signature_valid), &Some(self.output))

View File

@ -1,7 +1,7 @@
use super::*; use super::*;
use crate::case_result::compare_result; use crate::case_result::compare_result;
use crate::cases::common::BlsCase; use crate::cases::common::BlsCase;
use bls::{AggregateSignature, PublicKey, PublicKeyBytes}; use bls::{AggregateSignature, PublicKeyBytes};
use serde_derive::Deserialize; use serde_derive::Deserialize;
use std::convert::TryInto; use std::convert::TryInto;
use types::Hash256; use types::Hash256;
@ -9,6 +9,7 @@ use types::Hash256;
#[derive(Debug, Clone, Deserialize)] #[derive(Debug, Clone, Deserialize)]
pub struct BlsFastAggregateVerifyInput { pub struct BlsFastAggregateVerifyInput {
pub pubkeys: Vec<PublicKeyBytes>, pub pubkeys: Vec<PublicKeyBytes>,
#[serde(alias = "messages")]
pub message: String, pub message: String,
pub signature: String, pub signature: String,
} }
@ -28,13 +29,20 @@ impl Case for BlsFastAggregateVerify {
.map_err(|e| Error::FailedToParseTest(format!("{:?}", e)))?, .map_err(|e| Error::FailedToParseTest(format!("{:?}", e)))?,
); );
let pubkeys = self let pubkeys_result = self
.input .input
.pubkeys .pubkeys
.iter() .iter()
.map(|pkb| pkb.try_into()) .map(|pkb| pkb.try_into())
.collect::<Result<Vec<PublicKey>, bls::Error>>() .collect::<Result<Vec<_>, _>>();
.map_err(|e| Error::FailedToParseTest(format!("{:?}", e)))?;
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 pubkey_refs = pubkeys.iter().collect::<Vec<_>>();

View File

@ -14,7 +14,7 @@ pub struct BlsSignInput {
#[derive(Debug, Clone, Deserialize)] #[derive(Debug, Clone, Deserialize)]
pub struct BlsSign { pub struct BlsSign {
pub input: BlsSignInput, pub input: BlsSignInput,
pub output: String, pub output: Option<String>,
} }
impl BlsCase for BlsSign {} impl BlsCase for BlsSign {}
@ -27,16 +27,25 @@ impl Case for BlsSign {
assert_eq!(sk.len(), 32); 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..]) let msg = hex::decode(&self.input.message[2..])
.map_err(|e| Error::FailedToParseTest(format!("{:?}", e)))?; .map_err(|e| Error::FailedToParseTest(format!("{:?}", e)))?;
let signature = sk.sign(Hash256::from_slice(&msg)); let signature = sk.sign(Hash256::from_slice(&msg));
// Convert the output to one set of bytes let decoded = self
let decoded = hex::decode(&self.output[2..]) .output
.as_ref()
.map(|output| hex::decode(&output[2..]))
.transpose()
.map_err(|e| Error::FailedToParseTest(format!("{:?}", e)))?; .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)
} }
} }

View File

@ -1,14 +1,14 @@
use super::*; use super::*;
use crate::case_result::compare_result; use crate::case_result::compare_result;
use crate::cases::common::BlsCase; use crate::cases::common::BlsCase;
use bls::{PublicKey, Signature, SignatureBytes}; use bls::{PublicKeyBytes, Signature, SignatureBytes};
use serde_derive::Deserialize; use serde_derive::Deserialize;
use std::convert::TryInto; use std::convert::TryInto;
use types::Hash256; use types::Hash256;
#[derive(Debug, Clone, Deserialize)] #[derive(Debug, Clone, Deserialize)]
pub struct BlsVerifyInput { pub struct BlsVerifyInput {
pub pubkey: PublicKey, pub pubkey: PublicKeyBytes,
pub message: String, pub message: String,
pub signature: SignatureBytes, pub signature: SignatureBytes,
} }
@ -28,8 +28,9 @@ impl Case for BlsVerify {
let signature_ok = (&self.input.signature) let signature_ok = (&self.input.signature)
.try_into() .try_into()
.map(|signature: Signature| { .and_then(|signature: Signature| {
signature.verify(&self.input.pubkey, Hash256::from_slice(&message)) let pk = self.input.pubkey.decompress()?;
Ok(signature.verify(&pk, Hash256::from_slice(&message)))
}) })
.unwrap_or(false); .unwrap_or(false);

View File

@ -36,6 +36,7 @@ macro_rules! type_name_generic {
type_name!(MinimalEthSpec, "minimal"); type_name!(MinimalEthSpec, "minimal");
type_name!(MainnetEthSpec, "mainnet"); type_name!(MainnetEthSpec, "mainnet");
type_name_generic!(AggregateAndProof);
type_name_generic!(Attestation); type_name_generic!(Attestation);
type_name!(AttestationData); type_name!(AttestationData);
type_name_generic!(AttesterSlashing); type_name_generic!(AttesterSlashing);
@ -46,12 +47,18 @@ type_name_generic!(BeaconState);
type_name!(Checkpoint); type_name!(Checkpoint);
type_name!(Deposit); type_name!(Deposit);
type_name!(DepositData); type_name!(DepositData);
type_name!(DepositMessage);
type_name!(Eth1Data); type_name!(Eth1Data);
type_name!(Fork); type_name!(Fork);
type_name!(ForkData);
type_name_generic!(HistoricalBatch); type_name_generic!(HistoricalBatch);
type_name_generic!(IndexedAttestation); type_name_generic!(IndexedAttestation);
type_name_generic!(PendingAttestation); type_name_generic!(PendingAttestation);
type_name!(ProposerSlashing); type_name!(ProposerSlashing);
type_name_generic!(SignedAggregateAndProof);
type_name_generic!(SignedBeaconBlock);
type_name!(SignedBeaconBlockHeader);
type_name!(SignedVoluntaryExit); type_name!(SignedVoluntaryExit);
type_name!(SigningData);
type_name!(Validator); type_name!(Validator);
type_name!(VoluntaryExit); type_name!(VoluntaryExit);

View File

@ -172,6 +172,7 @@ mod ssz_static {
use ef_tests::{Handler, SszStaticHandler, SszStaticTHCHandler}; use ef_tests::{Handler, SszStaticHandler, SszStaticTHCHandler};
use types::*; use types::*;
ssz_static_test!(aggregate_and_proof, AggregateAndProof<_>);
ssz_static_test!(attestation, Attestation<_>); ssz_static_test!(attestation, Attestation<_>);
ssz_static_test!(attestation_data, AttestationData); ssz_static_test!(attestation_data, AttestationData);
ssz_static_test!(attester_slashing, AttesterSlashing<_>); ssz_static_test!(attester_slashing, AttesterSlashing<_>);
@ -188,12 +189,24 @@ mod ssz_static {
ssz_static_test!(checkpoint, Checkpoint); ssz_static_test!(checkpoint, Checkpoint);
ssz_static_test!(deposit, Deposit); ssz_static_test!(deposit, Deposit);
ssz_static_test!(deposit_data, DepositData); 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!(eth1_data, Eth1Data);
ssz_static_test!(fork, Fork); ssz_static_test!(fork, Fork);
ssz_static_test!(fork_data, ForkData);
ssz_static_test!(historical_batch, HistoricalBatch<_>); ssz_static_test!(historical_batch, HistoricalBatch<_>);
ssz_static_test!(indexed_attestation, IndexedAttestation<_>); ssz_static_test!(indexed_attestation, IndexedAttestation<_>);
ssz_static_test!(pending_attestation, PendingAttestation<_>); ssz_static_test!(pending_attestation, PendingAttestation<_>);
ssz_static_test!(proposer_slashing, ProposerSlashing); 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!(validator, Validator);
ssz_static_test!(voluntary_exit, VoluntaryExit); ssz_static_test!(voluntary_exit, VoluntaryExit);
} }
@ -217,7 +230,7 @@ fn epoch_processing_justification_and_finalization() {
#[test] #[test]
fn epoch_processing_rewards_and_penalties() { fn epoch_processing_rewards_and_penalties() {
EpochProcessingHandler::<MinimalEthSpec, RewardsAndPenalties>::run(); EpochProcessingHandler::<MinimalEthSpec, RewardsAndPenalties>::run();
// Note: there are no reward and penalty tests for mainnet yet EpochProcessingHandler::<MainnetEthSpec, RewardsAndPenalties>::run();
} }
#[test] #[test]

View File

@ -1,6 +1,6 @@
[package] [package]
name = "validator_client" 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>"] authors = ["Paul Hauner <paul@paulhauner.com>", "Age Manning <Age@AgeManning.com>", "Luke Anderson <luke@lukeanderson.com.au>"]
edition = "2018" edition = "2018"