Compare commits

..

5 Commits

Author SHA1 Message Date
Michael Sproul
36bd4d87f0 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>
2020-10-28 22:19:38 +00:00
divma
ad846ad280 Inform peers of requests that exceed the maximum rate limit + log downgrade (#1830)
## Issue Addressed

#1825 

## Proposed Changes

Since we penalize more blocks by range requests that have large steps, it is possible to get requests that will never be processed. We were not informing peers about this requests and also logging CRIT that is no longer relevant. Later we should check if more sophisticated handling for those requests is needed
2020-10-27 11:46:38 +00:00
Paul Hauner
92c8eba8ca Ensure eth1 deposit/chain IDs are used from YamlConfig (#1829)
## Issue Addressed

 NA

## Proposed Changes

Fixes a bug which causes the node to reject valid eth1 nodes.

- Fix core bug: failure to apply `YamlConfig` values to `ChainSpec`.
- Add a test to prevent regression in this specific case.
- Fix an invalid log message

## Additional Info

NA
2020-10-26 03:34:14 +00:00
Paul Hauner
f157d61cc7 Address clippy lints, panic in ssz_derive on overflow (#1714)
## Issue Addressed

NA

## Proposed Changes

- Panic or return error if we overflow `usize` in SSZ decoding/encoding derive macros.
  - I claim that the panics can only be triggered by a faulty type definition in lighthouse, they cannot be triggered externally on a validly defined struct.
- Use `Ordering` instead of some `if` statements, as demanded by clippy.
- Remove some old clippy `allow` that seem to no longer be required.
- Add comments to interesting clippy statements that we're going to continue to ignore.
- Create #1713

## Additional Info

NA
2020-10-25 23:27:39 +00:00
Paul Hauner
eba51f0973 Update testnet configs, change on-disk format (#1799)
## Issue Addressed

- Related to #1691

## Proposed Changes

- Add `DEPOSIT_CHAIN_ID` and `DEPOSIT_NETWORK_ID` to `config.yaml`.
    - Pass the `DEPOSIT_NETWORK_ID` to the `eth1::Service`.
- Remove the unused `MAX_EPOCHS_PER_CROSSLINK` from the `altona` and `medalla` configs (see [spec commit](2befe90032 (diff-efb845ac2ebd4aafbc23df40f47ce25699255064e99d36d0406d0a14ca7953ec))).
- Change from compressing the whole testnet directory, to only compressing the genesis state file. This is the only file we need to compress and *not* compressing the others makes them work nicely with git.
    - We can modify the boot nodes, configs, etc. without incurring an eternal binary-blob cost on our git history.
    - This change is backwards compatible (i.e., non-breaking).

## Additional Info

NA
2020-10-25 22:15:46 +00:00
87 changed files with 1016 additions and 746 deletions

263
Cargo.lock generated
View File

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

View File

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

View File

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

View File

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

View File

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

View File

@@ -5,9 +5,6 @@ use std::fs;
use std::path::PathBuf;
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.
const DEFAULT_FREEZER_DB_DIR: &str = "freezer_db";
@@ -46,7 +43,6 @@ pub struct Config {
/// Path where the freezer database will be located.
pub freezer_db_path: Option<PathBuf>,
pub log_file: PathBuf,
pub spec_constants: String,
/// If true, the node will use co-ordinated junk for eth1 values.
///
/// This is the method used for the 2019 client interop in Canada.
@@ -81,7 +77,6 @@ impl Default for Config {
network: NetworkConfig::default(),
chain: <_>::default(),
websocket_server: <_>::default(),
spec_constants: TESTNET_SPEC_CONSTANTS.into(),
dummy_eth1_backend: false,
sync_eth1_chain: false,
eth1: <_>::default(),

View File

@@ -370,7 +370,7 @@ impl Service {
crit!(
self.log,
"Invalid eth1 network. Please switch to correct network";
"expected" => format!("{:?}",DEFAULT_NETWORK_ID),
"expected" => format!("{:?}",config_network),
"received" => format!("{:?}",network_id),
"warning" => WARNING_MSG,
);

View File

@@ -233,9 +233,23 @@ where
}))
}
Err(RateLimitedErr::TooLarge) => {
// we set the batch sizes, so this is a coding/config err
crit!(self.log, "Batch too large to ever be processed";
"protocol" => format!("{}", req.protocol()));
// we set the batch sizes, so this is a coding/config err for most protocols
let protocol = req.protocol();
if matches!(protocol, Protocol::BlocksByRange) {
debug!(self.log, "Blocks by range request will never be processed"; "request" => %req);
} else {
crit!(self.log, "Request size too large to ever be processed"; "protocol" => %protocol);
}
// send an error code to the peer.
// the handler upon receiving the error code will send it back to the behaviour
self.send_response(
peer_id,
(conn_id, *id),
RPCCodedResponse::Error(
RPCResponseErrorCode::RateLimited,
"Rate limited. Request too large".into(),
),
);
}
Err(RateLimitedErr::TooSoon(wait_time)) => {
debug!(self.log, "Request exceeds the rate limit";

View File

@@ -5,8 +5,7 @@ use client::{ClientConfig, ClientGenesis};
use directory::{DEFAULT_BEACON_NODE_DIR, DEFAULT_NETWORK_DIR, DEFAULT_ROOT_DIR};
use eth2_libp2p::{multiaddr::Protocol, Enr, Multiaddr, NetworkConfig, PeerIdSerialized};
use eth2_testnet_config::Eth2TestnetConfig;
use slog::{crit, info, warn, Logger};
use ssz::Encode;
use slog::{info, warn, Logger};
use std::cmp;
use std::fs;
use std::net::{IpAddr, Ipv4Addr, ToSocketAddrs};
@@ -21,10 +20,8 @@ use types::{ChainSpec, Checkpoint, Epoch, EthSpec, Hash256, GRAFFITI_BYTES_LEN};
/// The output of this function depends primarily upon the given `cli_args`, however it's behaviour
/// may be influenced by other external services like the contents of the file system or the
/// response of some remote server.
#[allow(clippy::cognitive_complexity)]
pub fn get_config<E: EthSpec>(
cli_args: &ArgMatches,
spec_constants: &str,
spec: &ChainSpec,
log: Logger,
) -> Result<ClientConfig, String> {
@@ -68,8 +65,6 @@ pub fn get_config<E: EthSpec>(
log_dir.pop();
info!(log, "Data directory initialised"; "datadir" => log_dir.into_os_string().into_string().expect("Datadir should be a valid os string"));
client_config.spec_constants = spec_constants.into();
/*
* Networking
*/
@@ -223,14 +218,6 @@ pub fn get_config<E: EthSpec>(
.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
*
@@ -256,7 +243,7 @@ pub fn get_config<E: EthSpec>(
/*
* 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 =
format!("{:?}", eth2_testnet_config.deposit_contract_address()?);
@@ -270,17 +257,18 @@ pub fn get_config<E: EthSpec>(
client_config.eth1.lowest_cached_block_number =
client_config.eth1.deposit_contract_deploy_block;
client_config.eth1.follow_distance = spec.eth1_follow_distance;
client_config.eth1.network_id = spec.deposit_network_id.into();
if let Some(mut boot_nodes) = eth2_testnet_config.boot_enr {
client_config.network.boot_nodes_enr.append(&mut boot_nodes)
}
if let Some(genesis_state) = eth2_testnet_config.genesis_state {
if let Some(genesis_state_bytes) = eth2_testnet_config.genesis_state_bytes {
// Note: re-serializing the genesis state is not so efficient, however it avoids adding
// trait bounds to the `ClientGenesis` enum. This would have significant flow-on
// effects.
client_config.genesis = ClientGenesis::SszBytes {
genesis_state_bytes: genesis_state.as_ssz_bytes(),
genesis_state_bytes,
};
} else {
client_config.genesis = ClientGenesis::DepositContract;
@@ -545,9 +533,7 @@ pub fn get_data_dir(cli_args: &ArgMatches) -> PathBuf {
/// Try to parse the eth2 testnet config from the `testnet`, `testnet-dir` flags in that order.
/// Returns the default hardcoded testnet if neither flags are set.
pub fn get_eth2_testnet_config<E: EthSpec>(
cli_args: &ArgMatches,
) -> Result<Eth2TestnetConfig<E>, String> {
pub fn get_eth2_testnet_config(cli_args: &ArgMatches) -> Result<Eth2TestnetConfig, String> {
let optional_testnet_config = if cli_args.is_present("testnet") {
clap_utils::parse_hardcoded_network(cli_args, "testnet")?
} else if cli_args.is_present("testnet-dir") {

View File

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

View File

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

View File

@@ -43,9 +43,6 @@ OPTIONS:
--secrets-dir <SECRETS_DIR>
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>
Name of network lighthouse will connect to [possible values: medalla, altona]
@@ -81,4 +78,4 @@ This command will:
`--testnet` CLI param.
- Store a password to the validators voting keypair in `~/.lighthouse/{testnet}/secrets`.
where `testnet` is the name of the testnet passed in the `--testnet` parameter (default is `medalla`).
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
password will be generated and saved at that path. To avoid confusion, if the file does not already exist it
must include a '.pass' suffix.
-s, --spec <TITLE>
Specifies the default eth2 spec type. [default: mainnet] [possible values: mainnet, minimal, interop]
-t, --testnet-dir <DIR>
Path to directory containing eth2_testnet specs. Defaults to a hard-coded Lighthouse testnet. Only effective
if there is no existing database.

View File

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

View File

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

View File

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

View File

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

View File

@@ -1,20 +1,32 @@
use serde_derive::{Deserialize, Serialize};
use std::env;
use std::path::PathBuf;
use types::ChainSpec;
use types::{ChainSpec, EthSpecId};
// A macro is used to define this constant so it can be used with `include_bytes!`.
#[macro_export]
macro_rules! testnets_dir {
() => {
"built_in_testnet_configs"
};
}
pub const TESTNETS_DIR: &str = testnets_dir!();
pub const GENESIS_FILE_NAME: &str = "genesis.ssz";
pub const GENESIS_ZIP_FILE_NAME: &str = "genesis.ssz.zip";
/// The core configuration of a Lighthouse beacon node.
#[derive(Debug, Clone, Serialize, Deserialize)]
#[serde(default)]
pub struct Eth2Config {
pub spec_constants: String,
pub eth_spec_id: EthSpecId,
pub spec: ChainSpec,
}
impl Default for Eth2Config {
fn default() -> Self {
Self {
spec_constants: "minimal".to_string(),
eth_spec_id: EthSpecId::Minimal,
spec: ChainSpec::minimal(),
}
}
@@ -23,22 +35,22 @@ impl Default for Eth2Config {
impl Eth2Config {
pub fn mainnet() -> Self {
Self {
spec_constants: "mainnet".to_string(),
eth_spec_id: EthSpecId::Mainnet,
spec: ChainSpec::mainnet(),
}
}
pub fn minimal() -> Self {
Self {
spec_constants: "minimal".to_string(),
eth_spec_id: EthSpecId::Minimal,
spec: ChainSpec::minimal(),
}
}
pub fn interop() -> Self {
pub fn v012_legacy() -> Self {
Self {
spec_constants: "interop".to_string(),
spec: ChainSpec::interop(),
eth_spec_id: EthSpecId::V012Legacy,
spec: ChainSpec::v012_legacy(),
}
}
}
@@ -51,33 +63,23 @@ impl Eth2Config {
pub struct Eth2NetArchiveAndDirectory<'a> {
pub name: &'a str,
pub unique_id: &'a str,
pub archive_name: &'a str,
pub genesis_is_known: bool,
}
impl<'a> Eth2NetArchiveAndDirectory<'a> {
/// The directory that should be used to store files downloaded for this net.
fn pwd(&self) -> PathBuf {
pub fn dir(&self) -> PathBuf {
env::var("CARGO_MANIFEST_DIR")
.expect("should know manifest dir")
.parse::<PathBuf>()
.expect("should parse manifest dir as path")
.join(TESTNETS_DIR)
.join(self.unique_id)
}
pub fn dir(&self) -> PathBuf {
self.pwd().join(self.unique_id)
pub fn genesis_state_archive(&self) -> PathBuf {
self.dir().join(GENESIS_ZIP_FILE_NAME)
}
pub fn archive_fullpath(&self) -> PathBuf {
self.pwd().join(self.archive_name)
}
}
#[macro_export]
macro_rules! unique_id {
($name: tt) => {
concat!("testnet_", $name);
};
}
macro_rules! define_net {
@@ -88,8 +90,7 @@ macro_rules! define_net {
pub const ETH2_NET_DIR: Eth2NetArchiveAndDirectory = Eth2NetArchiveAndDirectory {
name: $name,
unique_id: unique_id!($name),
archive_name: concat!(unique_id!($name), ".zip"),
unique_id: $name,
genesis_is_known: $genesis_is_known,
};
@@ -98,7 +99,15 @@ macro_rules! define_net {
#[macro_export]
macro_rules! $macro_title {
($base_dir: tt, $filename: tt) => {
include_bytes!(concat!($base_dir, unique_id!($name), "/", $filename))
include_bytes!(concat!(
$base_dir,
"/",
testnets_dir!(),
"/",
$name,
"/",
$filename
))
};
}
}

View File

@@ -1,4 +1,5 @@
testnet*/*
schlesi-*
witti-*
altona*
/altona*
built_in_testnet_configs/*/genesis.ssz

View File

@@ -1,7 +1,8 @@
//! Downloads a testnet configuration from Github.
use eth2_config::{altona, medalla, spadina, zinken, Eth2NetArchiveAndDirectory};
use std::fs;
use eth2_config::{
altona, medalla, spadina, zinken, Eth2NetArchiveAndDirectory, GENESIS_FILE_NAME,
};
use std::fs::File;
use std::io;
use zip::ZipArchive;
@@ -15,42 +16,41 @@ const ETH2_NET_DIRS: &[Eth2NetArchiveAndDirectory<'static>] = &[
fn main() {
for testnet in ETH2_NET_DIRS {
match uncompress(testnet) {
match uncompress_state(testnet) {
Ok(()) => (),
Err(e) => panic!("Failed to uncompress testnet zip file: {}", e),
Err(e) => panic!(
"Failed to uncompress {} genesis state zip file: {}",
testnet.name, e
),
}
}
}
/// Uncompress the testnet configs archive into a testnet configs folder.
fn uncompress(testnet: &Eth2NetArchiveAndDirectory<'static>) -> Result<(), String> {
let archive_file = File::open(&testnet.archive_fullpath())
.map_err(|e| format!("Failed to open archive file: {:?}", e))?;
fn uncompress_state(testnet: &Eth2NetArchiveAndDirectory<'static>) -> Result<(), String> {
let archive_path = testnet.genesis_state_archive();
let archive_file = File::open(&archive_path)
.map_err(|e| format!("Failed to open archive file {:?}: {:?}", archive_path, e))?;
let mut archive =
ZipArchive::new(archive_file).map_err(|e| format!("Error with zip file: {}", e))?;
// Create testnet dir
fs::create_dir_all(testnet.dir())
.map_err(|e| format!("Failed to create testnet directory: {:?}", e))?;
// Create empty genesis.ssz if genesis is unknown
if !testnet.genesis_is_known {
File::create(testnet.dir().join("genesis.ssz"))
.map_err(|e| format!("Failed to create genesis.ssz: {}", e))?;
}
for i in 0..archive.len() {
let mut file = archive
.by_index(i)
.map_err(|e| format!("Error retrieving file {} inside zip: {}", i, e))?;
let path = testnet.dir().join(file.name());
if testnet.genesis_is_known {
let mut file = archive.by_name(GENESIS_FILE_NAME).map_err(|e| {
format!(
"Error retrieving file {} inside zip: {}",
GENESIS_FILE_NAME, e
)
})?;
let path = testnet.dir().join(GENESIS_FILE_NAME);
let mut outfile = File::create(&path)
.map_err(|e| format!("Error while creating file {:?}: {}", path, e))?;
io::copy(&mut file, &mut outfile)
.map_err(|e| format!("Error writing file {:?}: {}", path, e))?;
} else {
// Create empty genesis.ssz if genesis is unknown
File::create(testnet.dir().join(GENESIS_FILE_NAME))
.map_err(|e| format!("Failed to create {}: {}", GENESIS_FILE_NAME, e))?;
}
Ok(())

View File

@@ -0,0 +1,10 @@
- enr:-LK4QFtV7Pz4reD5a7cpfi1z6yPrZ2I9eMMU5mGQpFXLnLoKZW8TXvVubShzLLpsEj6aayvVO1vFx-MApijD3HLPhlECh2F0dG5ldHOIAAAAAAAAAACEZXRoMpD6etXjAAABIf__________gmlkgnY0gmlwhDMPYfCJc2VjcDI1NmsxoQIerw_qBc9apYfZqo2awiwS930_vvmGnW2psuHsTzrJ8YN0Y3CCIyiDdWRwgiMo
- enr:-LK4QPVkFd_MKzdW0219doTZryq40tTe8rwWYO75KDmeZM78fBskGsfCuAww9t8y3u0Q0FlhXOhjE1CWpx3SGbUaU80Ch2F0dG5ldHOIAAAAAAAAAACEZXRoMpD6etXjAAABIf__________gmlkgnY0gmlwhDMPRgeJc2VjcDI1NmsxoQNHu-QfNgzl8VxbMiPgv6wgAljojnqAOrN18tzJMuN8oYN0Y3CCIyiDdWRwgiMo
- enr:-LK4QHe52XPPrcv6-MvcmN5GqDe_sgCwo24n_2hedlfwD_oxNt7cXL3tXJ7h9aYv6CTS1C_H2G2_dkeqm_LBO9nrpiYBh2F0dG5ldHOIAAAAAAAAAACEZXRoMpD9yjmwAAABIf__________gmlkgnY0gmlwhANzD9uJc2VjcDI1NmsxoQJX7zMnRU3szfGfS8MAIfPaQKOBpu3sBVTXf4Qq0b_m-4N0Y3CCIyiDdWRwgiMo
- enr:-LK4QLkbbq7xuRa_EnWd_kc0TkQk0pd0B0cZYR5LvBsncFQBDyPbGdy8d24TzRVeK7ZWwM5_2EcSJK223f8TYUOQYfwBh2F0dG5ldHOIAAAAAAAAAACEZXRoMpD9yjmwAAABIf__________gmlkgnY0gmlwhAPsjtOJc2VjcDI1NmsxoQJNw_aZgWXl2SstD--WAjooGudjWLjEbbCIddJuEPxzWYN0Y3CCIyiDdWRwgiMo
- enr:-LK4QHy-glnxN1WTk5f6d7-xXwy_UKJLs5k7p_S4KRY9I925KTzW_kQLjfFriIpH0de7kygBwrSl726ukq9_OG_sgKMCh2F0dG5ldHOIUjEAIQEAFMiEZXRoMpD9yjmwAAABIf__________gmlkgnY0gmlwhBLmhrCJc2VjcDI1NmsxoQNlU7gT0HUvpLA41n-P5GrCgjwMwtG02YsRRO0lAmpmBYN0Y3CCIyiDdWRwgiMo
- enr:-LK4QDz0n0vpyOpuStB8e22h9ayHVcvmN7o0trC7eC0DnZV9GYGzK5uKv7WlzpMQM2nDTG43DWvF_DZYwJOZCbF4iCQBh2F0dG5ldHOI__________-EZXRoMpD9yjmwAAABIf__________gmlkgnY0gmlwhBKN136Jc2VjcDI1NmsxoQP5gcOUcaruHuMuTv8ht7ZEawp3iih7CmeLqcoY1hxOnoN0Y3CCIyiDdWRwgiMo
- enr:-LK4QOScOZ35sOXEH6CEW15lfv7I3DhqQAzCPQ_nRav95otuSh4yi9ol0AruKDiIk9qqGXyD-wQDaBAPLhwl4t-rUSQBh2F0dG5ldHOI__________-EZXRoMpD9yjmwAAABIf__________gmlkgnY0gmlwhCL68KuJc2VjcDI1NmsxoQK5fYR3Ipoc01dz0d2-EcL7m26zKQSkAbf4rwcMMM09CoN0Y3CCIyiDdWRwgiMo
- enr:-Ku4QMqmWPFkgM58F16wxB50cqWDaWaIsyANHL8wUNSB4Cy1TP9__uJQNRODvx_dvO6rY-BT3psrYTMAaxnMGXb6DuoBh2F0dG5ldHOIAAAAAAAAAACEZXRoMpD1pf1CAAAAAP__________gmlkgnY0gmlwhBLf22SJc2VjcDI1NmsxoQNoed9JnQh7ltcAacHEGOjwocL1BhMQbYTgaPX0kFuXtIN1ZHCCE4g
- enr:-LK4QDHu6BtDKnGbthNp-GvweQlW0jiOX9KFCj5Ql9kScrFed76tgHlFv7A-9ZRB-EVZpKItvlNjo3yxjj7jYIZUJa4Bh2F0dG5ldHOIAAAAAAAAAACEZXRoMpAAAAAAAAAAAAAAAAAAAAAAgmlkgnY0gmlwhDbUyQKJc2VjcDI1NmsxoQLV6Yse8baXDFu9r_dvm9BVd2ni2-wwvANWA-4ewbhniIN0Y3CCIyiDdWRwgiMo
- enr:-LK4QF3lT3Ch8Ljyx-KwoPrvoJHO-HDd3jOREMIZCWzi_HkHFVub5qt52MliDTLDgpXMS9tBzzLI4ObT_Z2m2Kus9vMBh2F0dG5ldHOIAAAAAAAAAACEZXRoMpAAAAAAAAAAAAAAAAAAAAAAgmlkgnY0gmlwhBKNqHeJc2VjcDI1NmsxoQOTO9uI9UZjuTOpcWvnCfhfQTmcMaIzBFsjMpXYnppET4N0Y3CCIyiDdWRwgiMo

View File

@@ -0,0 +1,60 @@
CONFIG_NAME: "altona"
MAX_COMMITTEES_PER_SLOT: 64
TARGET_COMMITTEE_SIZE: 128
MAX_VALIDATORS_PER_COMMITTEE: 2048
MIN_PER_EPOCH_CHURN_LIMIT: 4
CHURN_LIMIT_QUOTIENT: 65536
SHUFFLE_ROUND_COUNT: 90
MIN_GENESIS_ACTIVE_VALIDATOR_COUNT: 640
MIN_GENESIS_TIME: 1593433800
HYSTERESIS_QUOTIENT: 4
HYSTERESIS_DOWNWARD_MULTIPLIER: 1
HYSTERESIS_UPWARD_MULTIPLIER: 5
SAFE_SLOTS_TO_UPDATE_JUSTIFIED: 8
ETH1_FOLLOW_DISTANCE: 1024
TARGET_AGGREGATORS_PER_COMMITTEE: 16
RANDOM_SUBNETS_PER_VALIDATOR: 1
EPOCHS_PER_RANDOM_SUBNET_SUBSCRIPTION: 256
SECONDS_PER_ETH1_BLOCK: 14
DEPOSIT_CONTRACT_ADDRESS: 0x16e82D77882A663454Ef92806b7DeCa1D394810f
MIN_DEPOSIT_AMOUNT: 1000000000
MAX_EFFECTIVE_BALANCE: 32000000000
EJECTION_BALANCE: 16000000000
EFFECTIVE_BALANCE_INCREMENT: 1000000000
GENESIS_FORK_VERSION: 0x00000121
BLS_WITHDRAWAL_PREFIX: 0x00
GENESIS_DELAY: 172800
SECONDS_PER_SLOT: 12
MIN_ATTESTATION_INCLUSION_DELAY: 1
SLOTS_PER_EPOCH: 32
MIN_SEED_LOOKAHEAD: 1
MAX_SEED_LOOKAHEAD: 4
EPOCHS_PER_ETH1_VOTING_PERIOD: 32
SLOTS_PER_HISTORICAL_ROOT: 8192
MIN_VALIDATOR_WITHDRAWABILITY_DELAY: 256
SHARD_COMMITTEE_PERIOD: 256
MIN_EPOCHS_TO_INACTIVITY_PENALTY: 4
EPOCHS_PER_HISTORICAL_VECTOR: 65536
EPOCHS_PER_SLASHINGS_VECTOR: 8192
HISTORICAL_ROOTS_LIMIT: 16777216
VALIDATOR_REGISTRY_LIMIT: 1099511627776
BASE_REWARD_FACTOR: 64
WHISTLEBLOWER_REWARD_QUOTIENT: 512
PROPOSER_REWARD_QUOTIENT: 8
INACTIVITY_PENALTY_QUOTIENT: 16777216
MIN_SLASHING_PENALTY_QUOTIENT: 32
MAX_PROPOSER_SLASHINGS: 16
MAX_ATTESTER_SLASHINGS: 2
MAX_ATTESTATIONS: 128
MAX_DEPOSITS: 16
MAX_VOLUNTARY_EXITS: 16
DOMAIN_BEACON_PROPOSER: 0x00000000
DOMAIN_BEACON_ATTESTER: 0x01000000
DOMAIN_RANDAO: 0x02000000
DOMAIN_DEPOSIT: 0x03000000
DOMAIN_VOLUNTARY_EXIT: 0x04000000
DOMAIN_SELECTION_PROOF: 0x05000000
DOMAIN_AGGREGATE_AND_PROOF: 0x06000000
DEPOSIT_CHAIN_ID: 5
DEPOSIT_NETWORK_ID: 5
PROPORTIONAL_SLASHING_MULTIPLIER: 3

View File

@@ -0,0 +1 @@
0x16e82D77882A663454Ef92806b7DeCa1D394810f

View File

@@ -0,0 +1,10 @@
- enr:-LK4QKWk9yZo258PQouLshTOEEGWVHH7GhKwpYmB5tmKE4eHeSfman0PZvM2Rpp54RWgoOagAsOfKoXgZSbiCYzERWABh2F0dG5ldHOIAAAAAAAAAACEZXRoMpAAAAAAAAAAAAAAAAAAAAAAgmlkgnY0gmlwhDQlA5CJc2VjcDI1NmsxoQOYiWqrQtQksTEtS3qY6idxJE5wkm0t9wKqpzv2gCR21oN0Y3CCIyiDdWRwgiMo
- enr:-LK4QEnIS-PIxxLCadJdnp83VXuJqgKvC9ZTIWaJpWqdKlUFCiup2sHxWihF9EYGlMrQLs0mq_2IyarhNq38eoaOHUoBh2F0dG5ldHOIAAAAAAAAAACEZXRoMpAAAAAAAAAAAAAAAAAAAAAAgmlkgnY0gmlwhA37LMaJc2VjcDI1NmsxoQJ7k0mKtTd_kdEq251flOjD1HKpqgMmIETDoD-Msy_O-4N0Y3CCIyiDdWRwgiMo
- enr:-KG4QIOJRu0BBlcXJcn3lI34Ub1aBLYipbnDaxBnr2uf2q6nE1TWnKY5OAajg3eG6mHheQSfRhXLuy-a8V5rqXKSoUEChGV0aDKQGK5MywAAAAH__________4JpZIJ2NIJpcIQKAAFhiXNlY3AyNTZrMaEDESplmV9c2k73v0DjxVXJ6__2bWyP-tK28_80lf7dUhqDdGNwgiMog3VkcIIjKA
- enr:-Ku4QLglCMIYAgHd51uFUqejD9DWGovHOseHQy7Od1SeZnHnQ3fSpE4_nbfVs8lsy8uF07ae7IgrOOUFU0NFvZp5D4wBh2F0dG5ldHOIAAAAAAAAAACEZXRoMpAYrkzLAAAAAf__________gmlkgnY0gmlwhBLf22SJc2VjcDI1NmsxoQJxCnE6v_x2ekgY_uoE1rtwzvGy40mq9eD66XfHPBWgIIN1ZHCCD6A
- enr:-Ku4QOzU2MY51tYFcoByfULugCu2mepfqAbB0DajbRzg8xlILLfi5Iv_Wx-ARn8SiFoZZb3yp2x05cnUDYSoDYZupjIBh2F0dG5ldHOIAAAAAAAAAACEZXRoMpAYrkzLAAAAAf__________gmlkgnY0gmlwhBLf22SJc2VjcDI1NmsxoQLEq16KLm1vPjUKYGkHq296D60i7y209NYPUpwZPXDVgYN1ZHCCD6A
- enr:-Ku4QOYFmi2BW_YPDew_CKdfMvsrcRY1ARA-ImtcqFl-lgoxOFbxte4PU44-1M3uRNSRM-6rVa8USGohmWwtgwalEt8Bh2F0dG5ldHOIAAAAAAAAAACEZXRoMpAYrkzLAAAAAf__________gmlkgnY0gmlwhBLf22SJc2VjcDI1NmsxoQKH3lxnglLqrA7L6sl5r7XFnckr3XCnlZMaBTYSdE8SHIN1ZHCCD6A
- enr:-LK4QC3FCb7-JTNRiWAezECk_QUJc9c2IkJA1-EAmqAA5wmdbPWsAeRpnMXKRJqOYG0TE99ycB1nOb9y26mjb_UoHS4Bh2F0dG5ldHOIAAAAAAAAAACEZXRoMpDnp11aAAAAAf__________gmlkgnY0gmlwhDMPYfCJc2VjcDI1NmsxoQOmDQryZJApMwIT-dQAbxjvxLbPzyKn9GFk5dqam4MDTYN0Y3CCIyiDdWRwgiMo
- enr:-LK4QLvxLzt346gAPkTxohygiJvjd97lGcFeE5yXgZKtsMfEOveLE_FO2slJoHNzNF7vhwfwjt4X2vqzwGiR9gcrmDMBh2F0dG5ldHOIAAAAAAAAAACEZXRoMpDnp11aAAAAAf__________gmlkgnY0gmlwhDMPRgeJc2VjcDI1NmsxoQPjXTGx3HkaCG2neFxJmaTn5eCgbra3LY1twCeXPHChL4N0Y3CCIyiDdWRwgiMo
- enr:-Ku4QFVactU18ogiqPPasKs3jhUm5ISszUrUMK2c6SUPbGtANXVJ2wFapsKwVEVnVKxZ7Gsr9yEc4PYF-a14ahPa1q0Bh2F0dG5ldHOIAAAAAAAAAACEZXRoMpAYrkzLAAAAAf__________gmlkgnY0gmlwhGQbAHyJc2VjcDI1NmsxoQILF-Ya2i5yowVkQtlnZLjG0kqC4qtwmSk8ha7tKLuME4N1ZHCCIyg

View File

@@ -0,0 +1,60 @@
CONFIG_NAME: "medalla"
MAX_COMMITTEES_PER_SLOT: 64
TARGET_COMMITTEE_SIZE: 128
MAX_VALIDATORS_PER_COMMITTEE: 2048
MIN_PER_EPOCH_CHURN_LIMIT: 4
CHURN_LIMIT_QUOTIENT: 65536
SHUFFLE_ROUND_COUNT: 90
MIN_GENESIS_ACTIVE_VALIDATOR_COUNT: 16384
MIN_GENESIS_TIME: 1596546000
HYSTERESIS_QUOTIENT: 4
HYSTERESIS_DOWNWARD_MULTIPLIER: 1
HYSTERESIS_UPWARD_MULTIPLIER: 5
SAFE_SLOTS_TO_UPDATE_JUSTIFIED: 8
ETH1_FOLLOW_DISTANCE: 1024
TARGET_AGGREGATORS_PER_COMMITTEE: 16
RANDOM_SUBNETS_PER_VALIDATOR: 1
EPOCHS_PER_RANDOM_SUBNET_SUBSCRIPTION: 256
SECONDS_PER_ETH1_BLOCK: 14
DEPOSIT_CONTRACT_ADDRESS: 0x07b39F4fDE4A38bACe212b546dAc87C58DfE3fDC
MIN_DEPOSIT_AMOUNT: 1000000000
MAX_EFFECTIVE_BALANCE: 32000000000
EJECTION_BALANCE: 16000000000
EFFECTIVE_BALANCE_INCREMENT: 1000000000
GENESIS_FORK_VERSION: 0x00000001
BLS_WITHDRAWAL_PREFIX: 0x00
GENESIS_DELAY: 172800
SECONDS_PER_SLOT: 12
MIN_ATTESTATION_INCLUSION_DELAY: 1
SLOTS_PER_EPOCH: 32
MIN_SEED_LOOKAHEAD: 1
MAX_SEED_LOOKAHEAD: 4
EPOCHS_PER_ETH1_VOTING_PERIOD: 32
SLOTS_PER_HISTORICAL_ROOT: 8192
MIN_VALIDATOR_WITHDRAWABILITY_DELAY: 256
SHARD_COMMITTEE_PERIOD: 256
MIN_EPOCHS_TO_INACTIVITY_PENALTY: 4
EPOCHS_PER_HISTORICAL_VECTOR: 65536
EPOCHS_PER_SLASHINGS_VECTOR: 8192
HISTORICAL_ROOTS_LIMIT: 16777216
VALIDATOR_REGISTRY_LIMIT: 1099511627776
BASE_REWARD_FACTOR: 64
WHISTLEBLOWER_REWARD_QUOTIENT: 512
PROPOSER_REWARD_QUOTIENT: 8
INACTIVITY_PENALTY_QUOTIENT: 16777216
MIN_SLASHING_PENALTY_QUOTIENT: 32
MAX_PROPOSER_SLASHINGS: 16
MAX_ATTESTER_SLASHINGS: 2
MAX_ATTESTATIONS: 128
MAX_DEPOSITS: 16
MAX_VOLUNTARY_EXITS: 16
DOMAIN_BEACON_PROPOSER: 0x00000000
DOMAIN_BEACON_ATTESTER: 0x01000000
DOMAIN_RANDAO: 0x02000000
DOMAIN_DEPOSIT: 0x03000000
DOMAIN_VOLUNTARY_EXIT: 0x04000000
DOMAIN_SELECTION_PROOF: 0x05000000
DOMAIN_AGGREGATE_AND_PROOF: 0x06000000
DEPOSIT_CHAIN_ID: 5
DEPOSIT_NETWORK_ID: 5
PROPORTIONAL_SLASHING_MULTIPLIER: 3

View File

@@ -0,0 +1 @@
0x07b39F4fDE4A38bACe212b546dAc87C58DfE3fDC

View File

@@ -0,0 +1,8 @@
# Lighthouse
- enr:-KG4QEPVpcw8HLNsDuqNPIx4sXLCUsuDOHVtPcNmgSewWcDgSkd6s-vGCXlac86BTYIU8sYqhvD-ZeTW1uG5OtEBm-QDhGV0aDKQCfsKEgAAAAL__________4JpZIJ2NIJpcIQ0ECjWiXNlY3AyNTZrMaEDCavdC37lb2fgBgKrvrLRZ-ZvL6JFNeUHHc5TXZ_BYqmDdGNwgiMog3VkcIIjKA
# teku
- enr:-KG4QA-EcFfXQsL2dcneG8vp8HTWLrpwHQ5HhfyIytfpeKOISzROy2kYSsf_v-BZKnIx5XHDjqJ-ttz0hoz6qJA7tasEhGV0aDKQxKgkDQAAAAL__________4JpZIJ2NIJpcIQDFt-UiXNlY3AyNTZrMaECkR4C5DVO_9rB48eHTY4kdyOHsguTEDlvb7Ce0_mvghSDdGNwgiMog3VkcIIjKA
# prysm
- enr:-Ku4QGQJf2bcDAwVGvbvtq3AB4KKwAvStTenY-i_QnW2ABNRRBncIU_5qR_e_um-9t3s9g-Y5ZfFATj1nhtzq6lvgc4Bh2F0dG5ldHOIAAAAAAAAAACEZXRoMpDEqCQNAAAAAv__________gmlkgnY0gmlwhBLf22SJc2VjcDI1NmsxoQNoed9JnQh7ltcAacHEGOjwocL1BhMQbYTgaPX0kFuXtIN1ZHCCE4g
# proto
- enr:-Ku4QFW1SLbtzJ_ghQQC8-8xezvZ1Mx95J-zer9IPmDE2BKeD_SM7j4vH6xmroUFVuyK-54n2Ey2ueB-Lf-fkbcLwAQBh2F0dG5ldHOIAAAAAAAAAACEZXRoMpDEqCQNAAAAAv__________gmlkgnY0gmlwhGQZkSyJc2VjcDI1NmsxoQJMcbZhTCEKYSH5-qPQPgYfSHHUMLGBAKU-f-96yYKFMIN1ZHCCIyg

View File

@@ -0,0 +1,60 @@
CONFIG_NAME: "spadina"
MAX_COMMITTEES_PER_SLOT: 64
TARGET_COMMITTEE_SIZE: 128
MAX_VALIDATORS_PER_COMMITTEE: 2048
MIN_PER_EPOCH_CHURN_LIMIT: 4
CHURN_LIMIT_QUOTIENT: 65536
SHUFFLE_ROUND_COUNT: 90
MIN_GENESIS_ACTIVE_VALIDATOR_COUNT: 1024
MIN_GENESIS_TIME: 1601380800
HYSTERESIS_QUOTIENT: 4
HYSTERESIS_DOWNWARD_MULTIPLIER: 1
HYSTERESIS_UPWARD_MULTIPLIER: 5
PROPORTIONAL_SLASHING_MULTIPLIER: 3
SAFE_SLOTS_TO_UPDATE_JUSTIFIED: 8
ETH1_FOLLOW_DISTANCE: 1024
TARGET_AGGREGATORS_PER_COMMITTEE: 16
RANDOM_SUBNETS_PER_VALIDATOR: 1
EPOCHS_PER_RANDOM_SUBNET_SUBSCRIPTION: 256
SECONDS_PER_ETH1_BLOCK: 14
DEPOSIT_CHAIN_ID: 5
DEPOSIT_NETWORK_ID: 5
DEPOSIT_CONTRACT_ADDRESS: 0x48B597F4b53C21B48AD95c7256B49D1779Bd5890
MIN_DEPOSIT_AMOUNT: 1000000000
MAX_EFFECTIVE_BALANCE: 32000000000
EJECTION_BALANCE: 16000000000
EFFECTIVE_BALANCE_INCREMENT: 1000000000
GENESIS_FORK_VERSION: 0x00000002
BLS_WITHDRAWAL_PREFIX: 0x00
GENESIS_DELAY: 172800
SECONDS_PER_SLOT: 12
MIN_ATTESTATION_INCLUSION_DELAY: 1
SLOTS_PER_EPOCH: 32
MIN_SEED_LOOKAHEAD: 1
MAX_SEED_LOOKAHEAD: 4
EPOCHS_PER_ETH1_VOTING_PERIOD: 32
SLOTS_PER_HISTORICAL_ROOT: 8192
MIN_VALIDATOR_WITHDRAWABILITY_DELAY: 256
SHARD_COMMITTEE_PERIOD: 256
MIN_EPOCHS_TO_INACTIVITY_PENALTY: 4
EPOCHS_PER_HISTORICAL_VECTOR: 65536
EPOCHS_PER_SLASHINGS_VECTOR: 8192
HISTORICAL_ROOTS_LIMIT: 16777216
VALIDATOR_REGISTRY_LIMIT: 1099511627776
BASE_REWARD_FACTOR: 64
WHISTLEBLOWER_REWARD_QUOTIENT: 512
PROPOSER_REWARD_QUOTIENT: 8
INACTIVITY_PENALTY_QUOTIENT: 16777216
MIN_SLASHING_PENALTY_QUOTIENT: 32
MAX_PROPOSER_SLASHINGS: 16
MAX_ATTESTER_SLASHINGS: 2
MAX_ATTESTATIONS: 128
MAX_DEPOSITS: 16
MAX_VOLUNTARY_EXITS: 16
DOMAIN_BEACON_PROPOSER: 0x00000000
DOMAIN_BEACON_ATTESTER: 0x01000000
DOMAIN_RANDAO: 0x02000000
DOMAIN_DEPOSIT: 0x03000000
DOMAIN_VOLUNTARY_EXIT: 0x04000000
DOMAIN_SELECTION_PROOF: 0x05000000
DOMAIN_AGGREGATE_AND_PROOF: 0x06000000

View File

@@ -0,0 +1 @@
0x48B597F4b53C21B48AD95c7256B49D1779Bd5890

View File

@@ -0,0 +1,4 @@
- enr:-KG4QHPtVnKHEOkEJT1f5C6Hs-C_c4SlipTfkPrDIikLTzhqA_3m6bTq-CirsljlVP4IJybXelHE7J3l9DojR14_ZHUGhGV0aDKQ2jUIggAAAAP__________4JpZIJ2NIJpcIQSv2qciXNlY3AyNTZrMaECi_CNPDkKPilhimY7aEY-mBtSzI8AKMDvvv_I2Un74_qDdGNwgiMog3VkcIIjKA
- enr:-Ku4QH63huZ12miIY0kLI9dunG5fwKpnn-zR3XyA_kH6rQpRD1VoyLyzIcFysCJ09JDprdX-EzXp-Nc8swYqBznkXggBh2F0dG5ldHOIAAAAAAAAAACEZXRoMpDaNQiCAAAAA___________gmlkgnY0gmlwhBLf22SJc2VjcDI1NmsxoQILqxBY-_SF8o_5FjFD3yM92s50zT_ciFi8hStde5AEjIN1ZHCCH0A
- enr:-Ku4QMGGAuQO8NPhYCz29wsahrFR-betfxKx6ltyzLUM70yJWoaRjJZ-n1Oiof2PiKnzjVG1n6RoyO4ZNJkQtqEkqNkBh2F0dG5ldHOIAAAAAAAAAACEZXRoMpDaNQiCAAAAA___________gmlkgnY0gmlwhDZUyU6Jc2VjcDI1NmsxoQNMOowBnXeUYjK71_Zz78j3y7EYKSXH9ZGhYB4wB6V8lIN1ZHCCIyg
- enr:-KG4QDCt7b_zpzEoKEATUYgvdfBy28DCtGs54E4U_IIKd5e1Pj71nUAJKqdNjjqH5L8wNVsGNI67dzX5_ATfVMHQ7ygChGV0aDKQufleewAAAAP__________4JpZIJ2NIJpcIQ0ECjWiXNlY3AyNTZrMaEC64bJmIc-R6ynv5PqUqMBjblHILK46WWi4bbXO9DAGbeDdGNwgiMog3VkcIIjKA

View File

@@ -0,0 +1,60 @@
CONFIG_NAME: "zinken"
MAX_COMMITTEES_PER_SLOT: 64
TARGET_COMMITTEE_SIZE: 128
MAX_VALIDATORS_PER_COMMITTEE: 2048
MIN_PER_EPOCH_CHURN_LIMIT: 4
CHURN_LIMIT_QUOTIENT: 65536
SHUFFLE_ROUND_COUNT: 90
MIN_GENESIS_ACTIVE_VALIDATOR_COUNT: 1024
MIN_GENESIS_TIME: 1602504000
HYSTERESIS_QUOTIENT: 4
HYSTERESIS_DOWNWARD_MULTIPLIER: 1
HYSTERESIS_UPWARD_MULTIPLIER: 5
PROPORTIONAL_SLASHING_MULTIPLIER: 3
SAFE_SLOTS_TO_UPDATE_JUSTIFIED: 8
ETH1_FOLLOW_DISTANCE: 1024
TARGET_AGGREGATORS_PER_COMMITTEE: 16
RANDOM_SUBNETS_PER_VALIDATOR: 1
EPOCHS_PER_RANDOM_SUBNET_SUBSCRIPTION: 256
SECONDS_PER_ETH1_BLOCK: 14
DEPOSIT_CHAIN_ID: 5
DEPOSIT_NETWORK_ID: 5
DEPOSIT_CONTRACT_ADDRESS: 0x99F0Ec06548b086E46Cb0019C78D0b9b9F36cD53
MIN_DEPOSIT_AMOUNT: 1000000000
MAX_EFFECTIVE_BALANCE: 32000000000
EJECTION_BALANCE: 16000000000
EFFECTIVE_BALANCE_INCREMENT: 1000000000
GENESIS_FORK_VERSION: 0x00000003
BLS_WITHDRAWAL_PREFIX: 0x00
GENESIS_DELAY: 345600
SECONDS_PER_SLOT: 12
MIN_ATTESTATION_INCLUSION_DELAY: 1
SLOTS_PER_EPOCH: 32
MIN_SEED_LOOKAHEAD: 1
MAX_SEED_LOOKAHEAD: 4
EPOCHS_PER_ETH1_VOTING_PERIOD: 32
SLOTS_PER_HISTORICAL_ROOT: 8192
MIN_VALIDATOR_WITHDRAWABILITY_DELAY: 256
SHARD_COMMITTEE_PERIOD: 256
MIN_EPOCHS_TO_INACTIVITY_PENALTY: 4
EPOCHS_PER_HISTORICAL_VECTOR: 65536
EPOCHS_PER_SLASHINGS_VECTOR: 8192
HISTORICAL_ROOTS_LIMIT: 16777216
VALIDATOR_REGISTRY_LIMIT: 1099511627776
BASE_REWARD_FACTOR: 64
WHISTLEBLOWER_REWARD_QUOTIENT: 512
PROPOSER_REWARD_QUOTIENT: 8
INACTIVITY_PENALTY_QUOTIENT: 16777216
MIN_SLASHING_PENALTY_QUOTIENT: 32
MAX_PROPOSER_SLASHINGS: 16
MAX_ATTESTER_SLASHINGS: 2
MAX_ATTESTATIONS: 128
MAX_DEPOSITS: 16
MAX_VOLUNTARY_EXITS: 16
DOMAIN_BEACON_PROPOSER: 0x00000000
DOMAIN_BEACON_ATTESTER: 0x01000000
DOMAIN_RANDAO: 0x02000000
DOMAIN_DEPOSIT: 0x03000000
DOMAIN_VOLUNTARY_EXIT: 0x04000000
DOMAIN_SELECTION_PROOF: 0x05000000
DOMAIN_AGGREGATE_AND_PROOF: 0x06000000

View File

@@ -0,0 +1 @@
0x99F0Ec06548b086E46Cb0019C78D0b9b9F36cD53

View File

@@ -8,15 +8,16 @@
//! https://github.com/sigp/lighthouse/pull/605
//!
use eth2_config::{
include_altona_file, include_medalla_file, include_spadina_file, include_zinken_file, unique_id,
include_altona_file, include_medalla_file, include_spadina_file, include_zinken_file,
testnets_dir,
};
use enr::{CombinedKey, Enr};
use ssz::{Decode, Encode};
use ssz::Decode;
use std::fs::{create_dir_all, File};
use std::io::{Read, Write};
use std::path::PathBuf;
use types::{Address, BeaconState, EthSpec, YamlConfig};
use types::{Address, BeaconState, EthSpec, EthSpecId, YamlConfig};
pub const ADDRESS_FILE: &str = "deposit_contract.txt";
pub const DEPLOY_BLOCK_FILE: &str = "deploy_block.txt";
@@ -26,14 +27,13 @@ pub const YAML_CONFIG_FILE: &str = "config.yaml";
#[derive(Copy, Clone, Debug, PartialEq)]
pub struct HardcodedNet {
pub unique_id: &'static str,
pub name: &'static str,
pub genesis_is_known: bool,
pub yaml_config: &'static [u8],
pub deploy_block: &'static [u8],
pub boot_enr: &'static [u8],
pub deposit_contract_address: &'static [u8],
pub genesis_state: &'static [u8],
pub genesis_state_bytes: &'static [u8],
}
macro_rules! define_net {
@@ -41,14 +41,13 @@ macro_rules! define_net {
use eth2_config::$mod::ETH2_NET_DIR;
HardcodedNet {
unique_id: ETH2_NET_DIR.unique_id,
name: ETH2_NET_DIR.name,
genesis_is_known: ETH2_NET_DIR.genesis_is_known,
yaml_config: $include_file!("../", "config.yaml"),
deploy_block: $include_file!("../", "deploy_block.txt"),
boot_enr: $include_file!("../", "boot_enr.yaml"),
deposit_contract_address: $include_file!("../", "deposit_contract.txt"),
genesis_state: $include_file!("../", "genesis.ssz"),
genesis_state_bytes: $include_file!("../", "genesis.ssz"),
}
}};
}
@@ -65,15 +64,15 @@ pub const DEFAULT_HARDCODED_TESTNET: &str = "medalla";
///
/// See the crate-level documentation for more details.
#[derive(Clone, PartialEq, Debug)]
pub struct Eth2TestnetConfig<E: EthSpec> {
pub struct Eth2TestnetConfig {
pub deposit_contract_address: String,
pub deposit_contract_deploy_block: u64,
pub boot_enr: Option<Vec<Enr<CombinedKey>>>,
pub genesis_state: Option<BeaconState<E>>,
pub genesis_state_bytes: Option<Vec<u8>>,
pub yaml_config: Option<YamlConfig>,
}
impl<E: EthSpec> Eth2TestnetConfig<E> {
impl Eth2TestnetConfig {
/// Returns the default hard coded testnet.
pub fn hard_coded_default() -> Result<Option<Self>, String> {
Self::constant(DEFAULT_HARDCODED_TESTNET)
@@ -90,15 +89,6 @@ impl<E: EthSpec> Eth2TestnetConfig<E> {
/// Instantiates `Self` from a `HardcodedNet`.
fn from_hardcoded_net(net: &HardcodedNet) -> Result<Self, String> {
let genesis_state = if net.genesis_state.is_empty() {
None
} else {
Some(
BeaconState::from_ssz_bytes(net.genesis_state)
.map_err(|e| format!("Unable to parse genesis state: {:?}", e))?,
)
};
Ok(Self {
deposit_contract_address: serde_yaml::from_reader(net.deposit_contract_address)
.map_err(|e| format!("Unable to parse contract address: {:?}", e))?,
@@ -108,7 +98,8 @@ impl<E: EthSpec> Eth2TestnetConfig<E> {
serde_yaml::from_reader(net.boot_enr)
.map_err(|e| format!("Unable to parse boot enr: {:?}", e))?,
),
genesis_state,
genesis_state_bytes: Some(net.genesis_state_bytes.to_vec())
.filter(|bytes| !bytes.is_empty()),
yaml_config: Some(
serde_yaml::from_reader(net.yaml_config)
.map_err(|e| format!("Unable to parse yaml config: {:?}", e))?,
@@ -116,9 +107,38 @@ impl<E: EthSpec> Eth2TestnetConfig<E> {
})
}
// Write the files to the directory.
//
// Overwrites files if specified to do so.
/// Returns an identifier that should be used for selecting an `EthSpec` instance for this
/// testnet.
pub fn eth_spec_id(&self) -> Result<EthSpecId, String> {
self.yaml_config
.as_ref()
.ok_or_else(|| "YAML specification file missing".to_string())
.and_then(|config| {
config
.eth_spec_id()
.ok_or_else(|| format!("Unknown CONFIG_NAME: {}", config.config_name))
})
}
/// Returns `true` if this configuration contains a `BeaconState`.
pub fn beacon_state_is_known(&self) -> bool {
self.genesis_state_bytes.is_some()
}
/// Attempts to deserialize `self.beacon_state`, returning an error if it's missing or invalid.
pub fn beacon_state<E: EthSpec>(&self) -> Result<BeaconState<E>, String> {
let genesis_state_bytes = self
.genesis_state_bytes
.as_ref()
.ok_or_else(|| "Genesis state is unknown".to_string())?;
BeaconState::from_ssz_bytes(genesis_state_bytes)
.map_err(|e| format!("Genesis state SSZ bytes are invalid: {:?}", e))
}
/// Write the files to the directory.
///
/// Overwrites files if specified to do so.
pub fn write_to_file(&self, base_dir: PathBuf, overwrite: bool) -> Result<(), String> {
if base_dir.exists() && !overwrite {
return Err("Testnet directory already exists".to_string());
@@ -127,7 +147,7 @@ impl<E: EthSpec> Eth2TestnetConfig<E> {
self.force_write_to_file(base_dir)
}
// Write the files to the directory, even if the directory already exists.
/// Write the files to the directory, even if the directory already exists.
pub fn force_write_to_file(&self, base_dir: PathBuf) -> Result<(), String> {
create_dir_all(&base_dir)
.map_err(|e| format!("Unable to create testnet directory: {:?}", e))?;
@@ -168,13 +188,13 @@ impl<E: EthSpec> Eth2TestnetConfig<E> {
}
// The genesis state is a special case because it uses SSZ, not YAML.
if let Some(genesis_state) = &self.genesis_state {
if let Some(genesis_state_bytes) = &self.genesis_state_bytes {
let file = base_dir.join(GENESIS_STATE_FILE);
File::create(&file)
.map_err(|e| format!("Unable to create {:?}: {:?}", file, e))
.and_then(|mut file| {
file.write_all(&genesis_state.as_ssz_bytes())
file.write_all(genesis_state_bytes)
.map_err(|e| format!("Unable to write {:?}: {:?}", file, e))
})?;
}
@@ -211,19 +231,15 @@ impl<E: EthSpec> Eth2TestnetConfig<E> {
// The genesis state is a special case because it uses SSZ, not YAML.
let genesis_file_path = base_dir.join(GENESIS_STATE_FILE);
let genesis_state = if genesis_file_path.exists() {
Some(
File::open(&genesis_file_path)
.map_err(|e| format!("Unable to open {:?}: {:?}", genesis_file_path, e))
.and_then(|mut file| {
let mut bytes = vec![];
file.read_to_end(&mut bytes)
.map_err(|e| format!("Unable to read {:?}: {:?}", file, e))?;
BeaconState::from_ssz_bytes(&bytes)
.map_err(|e| format!("Unable to SSZ decode {:?}: {:?}", file, e))
})?,
)
let genesis_state_bytes = if genesis_file_path.exists() {
let mut bytes = vec![];
File::open(&genesis_file_path)
.map_err(|e| format!("Unable to open {:?}: {:?}", genesis_file_path, e))
.and_then(|mut file| {
file.read_to_end(&mut bytes)
.map_err(|e| format!("Unable to read {:?}: {:?}", file, e))
})?;
Some(bytes)
} else {
None
};
@@ -232,7 +248,7 @@ impl<E: EthSpec> Eth2TestnetConfig<E> {
deposit_contract_address,
deposit_contract_deploy_block,
boot_enr,
genesis_state,
genesis_state_bytes,
yaml_config,
})
}
@@ -251,16 +267,32 @@ impl<E: EthSpec> Eth2TestnetConfig<E> {
#[cfg(test)]
mod tests {
use super::*;
use ssz::Encode;
use tempdir::TempDir;
use types::{Eth1Data, Hash256, MainnetEthSpec, YamlConfig};
use types::{Eth1Data, Hash256, V012LegacyEthSpec, YamlConfig};
type E = MainnetEthSpec;
type E = V012LegacyEthSpec;
#[test]
fn hard_coded_nets_work() {
for net in HARDCODED_NETS {
let config = Eth2TestnetConfig::<E>::from_hardcoded_net(net).unwrap();
assert_eq!(config.genesis_state.is_some(), net.genesis_is_known);
let config =
Eth2TestnetConfig::from_hardcoded_net(net).expect(&format!("{:?}", net.name));
// Ensure we can parse the YAML config to a chain spec.
config
.yaml_config
.as_ref()
.unwrap()
.apply_to_chain_spec::<E>(&E::default_spec())
.unwrap();
assert_eq!(
config.genesis_state_bytes.is_some(),
net.genesis_is_known,
"{:?}",
net.name
);
}
}
@@ -293,11 +325,11 @@ mod tests {
let deposit_contract_address = "0xBB9bc244D798123fDe783fCc1C72d3Bb8C189413".to_string();
let deposit_contract_deploy_block = 42;
let testnet: Eth2TestnetConfig<E> = Eth2TestnetConfig {
let testnet: Eth2TestnetConfig = Eth2TestnetConfig {
deposit_contract_address,
deposit_contract_deploy_block,
boot_enr,
genesis_state,
genesis_state_bytes: genesis_state.as_ref().map(Encode::as_ssz_bytes),
yaml_config,
};

View File

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

View File

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

View File

@@ -1,6 +1,7 @@
use crate::SmallVec8;
use ssz::{Decode, Encode};
use ssz_derive::{Decode, Encode};
use std::cmp::Ordering;
use std::marker::PhantomData;
use std::ops::Range;
@@ -89,7 +90,6 @@ impl<T: Encode + Decode> CacheArena<T> {
/// To reiterate, the given `range` should be relative to the given `alloc_id`, not
/// `self.backing`. E.g., if the allocation has an offset of `20` and the range is `0..1`, then
/// the splice will translate to `self.backing[20..21]`.
#[allow(clippy::comparison_chain)]
fn splice_forgetful<I: IntoIterator<Item = T>>(
&mut self,
alloc_id: usize,
@@ -113,10 +113,10 @@ impl<T: Encode + Decode> CacheArena<T> {
self.backing.splice(start..end, replace_with);
if prev_len < self.backing.len() {
self.grow(alloc_id, self.backing.len() - prev_len)?;
} else if prev_len > self.backing.len() {
self.shrink(alloc_id, prev_len - self.backing.len())?;
match prev_len.cmp(&self.backing.len()) {
Ordering::Greater => self.shrink(alloc_id, prev_len - self.backing.len())?,
Ordering::Less => self.grow(alloc_id, self.backing.len() - prev_len)?,
Ordering::Equal => {}
}
Ok(())

View File

@@ -300,7 +300,6 @@ where
/// Equivalent to:
///
/// https://github.com/ethereum/eth2.0-specs/blob/v0.12.1/specs/phase0/fork-choice.md#get_ancestor
#[allow(clippy::if_same_then_else)]
fn get_ancestor(
&self,
block_root: Hash256,

View File

@@ -2,7 +2,6 @@ use ethereum_types::H256;
use ssz::{Decode, DecodeError, Encode};
use ssz_derive::{Decode, Encode};
#[allow(clippy::zero_prefixed_literal)]
mod round_trip {
use super::*;

View File

@@ -87,7 +87,6 @@ pub fn ssz_encode_derive(input: TokenStream) -> TokenStream {
let field_types_f = field_types_a.clone();
let output = quote! {
#[allow(clippy::integer_arithmetic)]
impl #impl_generics ssz::Encode for #name #ty_generics #where_clause {
fn is_ssz_fixed_len() -> bool {
#(
@@ -98,10 +97,13 @@ pub fn ssz_encode_derive(input: TokenStream) -> TokenStream {
fn ssz_fixed_len() -> usize {
if <Self as ssz::Encode>::is_ssz_fixed_len() {
let mut len: usize = 0;
#(
<#field_types_b as ssz::Encode>::ssz_fixed_len() +
len = len
.checked_add(<#field_types_b as ssz::Encode>::ssz_fixed_len())
.expect("encode ssz_fixed_len length overflow");
)*
0
len
} else {
ssz::BYTES_PER_LENGTH_OFFSET
}
@@ -111,13 +113,19 @@ pub fn ssz_encode_derive(input: TokenStream) -> TokenStream {
if <Self as ssz::Encode>::is_ssz_fixed_len() {
<Self as ssz::Encode>::ssz_fixed_len()
} else {
let mut len = 0;
let mut len: usize = 0;
#(
if <#field_types_d as ssz::Encode>::is_ssz_fixed_len() {
len += <#field_types_e as ssz::Encode>::ssz_fixed_len();
len = len
.checked_add(<#field_types_e as ssz::Encode>::ssz_fixed_len())
.expect("encode ssz_bytes_len length overflow");
} else {
len += ssz::BYTES_PER_LENGTH_OFFSET;
len += self.#field_idents_a.ssz_bytes_len();
len = len
.checked_add(ssz::BYTES_PER_LENGTH_OFFSET)
.expect("encode ssz_bytes_len length overflow for offset");
len = len
.checked_add(self.#field_idents_a.ssz_bytes_len())
.expect("encode ssz_bytes_len length overflow for bytes");
}
)*
@@ -126,10 +134,12 @@ pub fn ssz_encode_derive(input: TokenStream) -> TokenStream {
}
fn ssz_append(&self, buf: &mut Vec<u8>) {
let offset = #(
<#field_types_f as ssz::Encode>::ssz_fixed_len() +
)*
0;
let mut offset: usize = 0;
#(
offset = offset
.checked_add(<#field_types_f as ssz::Encode>::ssz_fixed_len())
.expect("encode ssz_append offset overflow");
)*
let mut encoder = ssz::SszEncoder::container(buf, offset);
@@ -229,7 +239,6 @@ pub fn ssz_decode_derive(input: TokenStream) -> TokenStream {
}
let output = quote! {
#[allow(clippy::integer_arithmetic)]
impl #impl_generics ssz::Decode for #name #ty_generics #where_clause {
fn is_ssz_fixed_len() -> bool {
#(
@@ -240,10 +249,13 @@ pub fn ssz_decode_derive(input: TokenStream) -> TokenStream {
fn ssz_fixed_len() -> usize {
if <Self as ssz::Decode>::is_ssz_fixed_len() {
let mut len: usize = 0;
#(
#fixed_lens +
len = len
.checked_add(#fixed_lens)
.expect("decode ssz_fixed_len overflow");
)*
0
len
} else {
ssz::BYTES_PER_LENGTH_OFFSET
}
@@ -258,13 +270,17 @@ pub fn ssz_decode_derive(input: TokenStream) -> TokenStream {
});
}
let mut start = 0;
let mut start: usize = 0;
let mut end = start;
macro_rules! decode_field {
($type: ty) => {{
start = end;
end += <$type as ssz::Decode>::ssz_fixed_len();
end = end
.checked_add(<$type as ssz::Decode>::ssz_fixed_len())
.ok_or_else(|| ssz::DecodeError::OutOfBoundsByte {
i: usize::max_value()
})?;
let slice = bytes.get(start..end)
.ok_or_else(|| ssz::DecodeError::InvalidByteLength {
len: bytes.len(),

View File

@@ -22,7 +22,7 @@ macro_rules! impl_for_bitsize {
HASHSIZE / ($bit_size / 8)
}
#[allow(clippy::cast_lossless)]
#[allow(clippy::cast_lossless)] // Lint does not apply to all uses of this macro.
fn tree_hash_root(&self) -> Hash256 {
int_to_hash256(*self as u64)
}

View File

@@ -23,11 +23,13 @@ impl PubkeyCache {
///
/// The added index must equal the number of validators already added to the map. This ensures
/// that an index is never skipped.
#[allow(clippy::integer_arithmetic)]
pub fn insert(&mut self, pubkey: PublicKeyBytes, index: ValidatorIndex) -> bool {
if index == self.len {
self.map.insert(pubkey, index);
self.len += 1;
self.len = self
.len
.checked_add(1)
.expect("map length cannot exceed usize");
true
} else {
false

View File

@@ -108,6 +108,8 @@ pub struct ChainSpec {
*/
pub eth1_follow_distance: u64,
pub seconds_per_eth1_block: u64,
pub deposit_chain_id: u64,
pub deposit_network_id: u64,
pub deposit_contract_address: Address,
/*
@@ -262,7 +264,6 @@ impl ChainSpec {
hysteresis_quotient: 4,
hysteresis_downward_multiplier: 1,
hysteresis_upward_multiplier: 5,
proportional_slashing_multiplier: 3,
/*
* Gwei values
@@ -281,7 +282,7 @@ impl ChainSpec {
/*
* Time parameters
*/
genesis_delay: 172800, // 2 days
genesis_delay: 604800, // 7 days
milliseconds_per_slot: 12_000,
min_attestation_inclusion_delay: 1,
min_seed_lookahead: Epoch::new(1),
@@ -296,8 +297,9 @@ impl ChainSpec {
base_reward_factor: 64,
whistleblower_reward_quotient: 512,
proposer_reward_quotient: 8,
inactivity_penalty_quotient: u64::pow(2, 24),
min_slashing_penalty_quotient: 32,
inactivity_penalty_quotient: u64::pow(2, 26),
min_slashing_penalty_quotient: 128,
proportional_slashing_multiplier: 1,
/*
* Signature domains
@@ -318,8 +320,10 @@ impl ChainSpec {
/*
* Eth1
*/
eth1_follow_distance: 1_024,
eth1_follow_distance: 2048,
seconds_per_eth1_block: 14,
deposit_chain_id: 1,
deposit_network_id: 1,
deposit_contract_address: "1234567890123456789012345678901234567890"
.parse()
.expect("chain spec deposit contract address"),
@@ -355,24 +359,31 @@ impl ChainSpec {
shard_committee_period: 64,
genesis_delay: 300,
milliseconds_per_slot: 6_000,
inactivity_penalty_quotient: u64::pow(2, 25),
min_slashing_penalty_quotient: 64,
proportional_slashing_multiplier: 2,
safe_slots_to_update_justified: 2,
network_id: 2, // lighthouse testnet network id
deposit_chain_id: 5,
deposit_network_id: 5,
boot_nodes,
..ChainSpec::mainnet()
}
}
/// Interop testing spec
/// Suits the `v0.12.3` version of the eth2 spec:
/// https://github.com/ethereum/eth2.0-specs/blob/v0.12.3/configs/mainnet/phase0.yaml
///
/// This allows us to customize a chain spec for interop testing.
pub fn interop() -> Self {
/// This method only needs to exist whilst we provide support for "legacy" testnets prior to v1.0.0
/// (e.g., Medalla, Zinken, Spadina, Altona, etc.).
pub fn v012_legacy() -> Self {
let boot_nodes = vec![];
Self {
milliseconds_per_slot: 12_000,
target_committee_size: 4,
shuffle_round_count: 10,
network_id: 13,
genesis_delay: 172_800, // 2 days
inactivity_penalty_quotient: u64::pow(2, 24),
min_slashing_penalty_quotient: 32,
eth1_follow_distance: 1024,
boot_nodes,
..ChainSpec::mainnet()
}
@@ -440,10 +451,9 @@ mod tests {
///
/// Spec v0.12.3
#[derive(Serialize, Deserialize, Debug, PartialEq, Clone)]
#[serde(rename_all = "UPPERCASE")]
#[serde(rename_all = "UPPERCASE", deny_unknown_fields)]
pub struct YamlConfig {
#[serde(default)]
config_name: String,
pub config_name: String,
// ChainSpec
#[serde(with = "serde_utils::quoted_u64")]
max_committees_per_slot: u64,
@@ -475,10 +485,6 @@ pub struct YamlConfig {
hysteresis_downward_multiplier: u64,
#[serde(with = "serde_utils::quoted_u64")]
hysteresis_upward_multiplier: u64,
// Proportional slashing multiplier defaults to 3 for compatibility with Altona and Medalla.
#[serde(default = "default_proportional_slashing_multiplier")]
#[serde(with = "serde_utils::quoted_u64")]
proportional_slashing_multiplier: u64,
#[serde(with = "serde_utils::bytes_4_hex")]
genesis_fork_version: [u8; 4],
#[serde(with = "serde_utils::u8_hex")]
@@ -508,6 +514,8 @@ pub struct YamlConfig {
#[serde(with = "serde_utils::quoted_u64")]
min_slashing_penalty_quotient: u64,
#[serde(with = "serde_utils::quoted_u64")]
proportional_slashing_multiplier: u64,
#[serde(with = "serde_utils::quoted_u64")]
safe_slots_to_update_justified: u64,
#[serde(with = "serde_utils::u32_hex")]
@@ -562,16 +570,11 @@ pub struct YamlConfig {
epochs_per_random_subnet_subscription: u64,
#[serde(with = "serde_utils::quoted_u64")]
seconds_per_eth1_block: u64,
deposit_contract_address: Address,
/* TODO: incorporate these into ChainSpec and turn on `serde(deny_unknown_fields)`
#[serde(with = "serde_utils::quoted_u64")]
deposit_chain_id: u64,
#[serde(with = "serde_utils::quoted_u64")]
deposit_network_id: u64,
*/
}
// Compatibility shim for proportional slashing multpilier on Altona and Medalla.
fn default_proportional_slashing_multiplier() -> u64 {
3
deposit_contract_address: Address,
}
impl Default for YamlConfig {
@@ -581,9 +584,28 @@ impl Default for YamlConfig {
}
}
#[allow(clippy::integer_arithmetic)] // Arith cannot overflow or panic.
fn milliseconds_to_seconds(millis: u64) -> u64 {
millis / 1000
}
/// Spec v0.12.1
impl YamlConfig {
#[allow(clippy::integer_arithmetic)]
/// Maps `self.config_name` to an identifier for an `EthSpec` instance.
///
/// Returns `None` if there is no match.
pub fn eth_spec_id(&self) -> Option<EthSpecId> {
Some(match self.config_name.as_str() {
"mainnet" => EthSpecId::Mainnet,
"minimal" => EthSpecId::Minimal,
"zinken" => EthSpecId::V012Legacy,
"spadina" => EthSpecId::V012Legacy,
"medalla" => EthSpecId::V012Legacy,
"altona" => EthSpecId::V012Legacy,
_ => return None,
})
}
pub fn from_spec<T: EthSpec>(spec: &ChainSpec) -> Self {
Self {
config_name: T::spec_name().to_string(),
@@ -605,7 +627,7 @@ impl YamlConfig {
hysteresis_upward_multiplier: spec.hysteresis_upward_multiplier,
proportional_slashing_multiplier: spec.proportional_slashing_multiplier,
bls_withdrawal_prefix: spec.bls_withdrawal_prefix_byte,
seconds_per_slot: spec.milliseconds_per_slot / 1000,
seconds_per_slot: milliseconds_to_seconds(spec.milliseconds_per_slot),
min_attestation_inclusion_delay: spec.min_attestation_inclusion_delay,
min_seed_lookahead: spec.min_seed_lookahead.into(),
max_seed_lookahead: spec.max_seed_lookahead.into(),
@@ -648,6 +670,8 @@ impl YamlConfig {
random_subnets_per_validator: spec.random_subnets_per_validator,
epochs_per_random_subnet_subscription: spec.epochs_per_random_subnet_subscription,
seconds_per_eth1_block: spec.seconds_per_eth1_block,
deposit_chain_id: spec.deposit_chain_id,
deposit_network_id: spec.deposit_network_id,
deposit_contract_address: spec.deposit_contract_address,
}
}
@@ -706,6 +730,8 @@ impl YamlConfig {
random_subnets_per_validator: self.random_subnets_per_validator,
epochs_per_random_subnet_subscription: self.epochs_per_random_subnet_subscription,
seconds_per_eth1_block: self.seconds_per_eth1_block,
deposit_chain_id: self.deposit_chain_id,
deposit_network_id: self.deposit_network_id,
deposit_contract_address: self.deposit_contract_address,
/*
* Gwei values
@@ -832,6 +858,8 @@ mod yaml_tests {
// modifying the original spec
spec.max_committees_per_slot += 1;
spec.deposit_chain_id += 1;
spec.deposit_network_id += 1;
// Applying a yaml config with incorrect EthSpec should fail
let res = yamlconfig.apply_to_chain_spec::<MainnetEthSpec>(&spec);
assert_eq!(res, None);

View File

@@ -6,7 +6,45 @@ use ssz_types::typenum::{
Unsigned, U0, U1024, U1099511627776, U128, U16, U16777216, U2, U2048, U32, U4, U4096, U64,
U65536, U8, U8192,
};
use std::fmt::Debug;
use std::fmt::{self, Debug};
use std::str::FromStr;
const MAINNET: &str = "mainnet";
const MINIMAL: &str = "minimal";
const LEGACY: &str = "v0.12-legacy";
/// Used to identify one of the `EthSpec` instances defined here.
#[derive(Copy, Clone, Debug, PartialEq, Serialize, Deserialize)]
#[serde(rename_all = "lowercase")]
pub enum EthSpecId {
Mainnet,
Minimal,
V012Legacy,
}
impl FromStr for EthSpecId {
type Err = String;
fn from_str(s: &str) -> Result<Self, Self::Err> {
match s {
MAINNET => Ok(EthSpecId::Mainnet),
MINIMAL => Ok(EthSpecId::Minimal),
LEGACY => Ok(EthSpecId::V012Legacy),
_ => Err(format!("Unknown eth spec: {}", s)),
}
}
}
impl fmt::Display for EthSpecId {
fn fmt(&self, f: &mut fmt::Formatter<'_>) -> fmt::Result {
let s = match self {
EthSpecId::Mainnet => MAINNET,
EthSpecId::Minimal => MINIMAL,
EthSpecId::V012Legacy => LEGACY,
};
write!(f, "{}", s)
}
}
pub trait EthSpec: 'static + Default + Sync + Send + Clone + Debug + PartialEq + Eq {
/*
@@ -56,7 +94,7 @@ pub trait EthSpec: 'static + Default + Sync + Send + Clone + Debug + PartialEq +
fn default_spec() -> ChainSpec;
fn spec_name() -> &'static str;
fn spec_name() -> EthSpecId;
fn genesis_epoch() -> Epoch {
Epoch::new(Self::GenesisEpoch::to_u64())
@@ -144,7 +182,7 @@ impl EthSpec for MainnetEthSpec {
type MaxValidatorsPerCommittee = U2048;
type GenesisEpoch = U0;
type SlotsPerEpoch = U32;
type EpochsPerEth1VotingPeriod = U32;
type EpochsPerEth1VotingPeriod = U64;
type SlotsPerHistoricalRoot = U8192;
type EpochsPerHistoricalVector = U65536;
type EpochsPerSlashingsVector = U8192;
@@ -156,14 +194,14 @@ impl EthSpec for MainnetEthSpec {
type MaxDeposits = U16;
type MaxVoluntaryExits = U16;
type MaxPendingAttestations = U4096; // 128 max attestations * 32 slots per epoch
type SlotsPerEth1VotingPeriod = U1024; // 32 epochs * 32 slots per epoch
type SlotsPerEth1VotingPeriod = U2048; // 64 epochs * 32 slots per epoch
fn default_spec() -> ChainSpec {
ChainSpec::mainnet()
}
fn spec_name() -> &'static str {
"mainnet"
fn spec_name() -> EthSpecId {
EthSpecId::Mainnet
}
}
@@ -203,28 +241,32 @@ impl EthSpec for MinimalEthSpec {
ChainSpec::minimal()
}
fn spec_name() -> &'static str {
"minimal"
fn spec_name() -> EthSpecId {
EthSpecId::Minimal
}
}
pub type MinimalBeaconState = BeaconState<MinimalEthSpec>;
/// Interop testnet spec
/// Suits the `v0.12.3` version of the eth2 spec:
/// https://github.com/ethereum/eth2.0-specs/blob/v0.12.3/configs/mainnet/phase0.yaml
///
/// This struct only needs to exist whilst we provide support for "legacy" testnets prior to v1.0.0
/// (e.g., Medalla, Zinken, Spadina, Altona, etc.).
#[cfg_attr(feature = "arbitrary-fuzz", derive(arbitrary::Arbitrary))]
#[derive(Clone, PartialEq, Eq, Debug, Default, Serialize, Deserialize)]
pub struct InteropEthSpec;
pub struct V012LegacyEthSpec;
impl EthSpec for InteropEthSpec {
type SlotsPerEpoch = U8;
type EpochsPerEth1VotingPeriod = U2;
type SlotsPerHistoricalRoot = U64;
type EpochsPerHistoricalVector = U64;
type EpochsPerSlashingsVector = U64;
type MaxPendingAttestations = U1024; // 128 max attestations * 8 slots per epoch
type SlotsPerEth1VotingPeriod = U16; // 2 epochs * 8 slots per epoch
impl EthSpec for V012LegacyEthSpec {
type EpochsPerEth1VotingPeriod = U32;
type SlotsPerEth1VotingPeriod = U1024; // 32 epochs * 32 slots per epoch
params_from_eth_spec!(MainnetEthSpec {
SlotsPerEpoch,
SlotsPerHistoricalRoot,
EpochsPerHistoricalVector,
EpochsPerSlashingsVector,
MaxPendingAttestations,
JustificationBitsLength,
SubnetBitfieldLength,
MaxValidatorsPerCommittee,
@@ -239,12 +281,10 @@ impl EthSpec for InteropEthSpec {
});
fn default_spec() -> ChainSpec {
ChainSpec::interop()
ChainSpec::v012_legacy()
}
fn spec_name() -> &'static str {
"interop"
fn spec_name() -> EthSpecId {
EthSpecId::V012Legacy
}
}
pub type InteropBeaconState = BeaconState<InteropEthSpec>;

View File

@@ -18,7 +18,7 @@ pub struct Graffiti(#[serde(with = "serde_graffiti")] pub [u8; GRAFFITI_BYTES_LE
impl Graffiti {
pub fn as_utf8_lossy(&self) -> String {
#[allow(clippy::invalid_regex)]
#[allow(clippy::invalid_regex)] // This is a false positive, this regex is valid.
let re = Regex::new("\\p{C}").expect("graffiti regex is valid");
String::from_utf8_lossy(&re.replace_all(&self.0[..], &b""[..])).to_string()
}

View File

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

View File

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

View File

@@ -7,7 +7,7 @@ edition = "2018"
[dependencies]
eth2_ssz = "0.1.2"
tree_hash = "0.1.1"
milagro_bls = { git = "https://github.com/sigp/milagro_bls", branch = "paulh" }
milagro_bls = { git = "https://github.com/sigp/milagro_bls", tag = "v1.4.0" }
rand = "0.7.3"
serde = "1.0.116"
serde_derive = "1.0.116"
@@ -17,7 +17,7 @@ eth2_hashing = "0.1.0"
ethereum-types = "0.9.2"
arbitrary = { version = "0.4.6", features = ["derive"], optional = true }
zeroize = { version = "1.1.1", features = ["zeroize_derive"] }
blst = { git = "https://github.com/sigp/blst.git", rev = "284f7059642851c760a09fb1708bcb59c7ca323c" }
blst = { git = "https://github.com/sigp/blst.git", rev = "7cf47864627ca479cad06c2a164f30d0cbaf16ce" }
[features]
default = ["supranational"]
@@ -25,3 +25,4 @@ fake_crypto = []
milagro = []
supranational = []
supranational-portable = ["supranational", "blst/portable"]
supranational-force-adx = ["supranational", "blst/force-adx"]

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.
pub trait TAggregatePublicKey: Sized + Clone {
/// Initialize `Self` to the infinity value which can then have other public keys aggregated
/// upon it.
fn infinity() -> Self;
/// Serialize `self` as compressed bytes.
fn serialize(&self) -> [u8; PUBLIC_KEY_BYTES_LEN];
/// Deserialize `self` from compressed bytes.
fn deserialize(bytes: &[u8]) -> Result<Self, Error>;
}
pub trait TAggregatePublicKey: Sized + Clone {}
/*
* Note: there is no immediate need for a `GenericAggregatePublicKey` struct.

View File

@@ -183,13 +183,6 @@ where
return false;
}
if self.is_infinity
&& pubkeys.len() == 1
&& pubkeys.first().map_or(false, |pk| pk.is_infinity)
{
return true;
}
match self.point.as_ref() {
Some(point) => point.fast_aggregate_verify(msg, pubkeys),
None => false,
@@ -207,13 +200,6 @@ where
return false;
}
if self.is_infinity
&& pubkeys.len() == 1
&& pubkeys.first().map_or(false, |pk| pk.is_infinity)
{
return true;
}
match self.point.as_ref() {
Some(point) => point.aggregate_verify(msgs, pubkeys),
None => false,

View File

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

View File

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

View File

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

View File

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

View File

@@ -4,7 +4,7 @@ use crate::{
generic_public_key::{GenericPublicKey, TPublicKey, PUBLIC_KEY_BYTES_LEN},
generic_secret_key::TSecretKey,
generic_signature::{TSignature, SIGNATURE_BYTES_LEN},
Error, Hash256, ZeroizeHash, INFINITY_PUBLIC_KEY, INFINITY_SIGNATURE,
Error, Hash256, ZeroizeHash, INFINITY_SIGNATURE,
};
pub use blst::min_pk as blst_core;
use blst::{blst_scalar, BLST_ERROR};
@@ -50,18 +50,12 @@ pub fn verify_signature_sets<'a>(
let mut pks = Vec::with_capacity(sets.len());
for set in &sets {
// If this set is simply an infinity signature and infinity pubkey then skip verification.
// This has the effect of always declaring that this sig/pubkey combination is valid.
if set.signature.is_infinity
&& set.signing_keys.len() == 1
&& set.signing_keys.first().map_or(false, |pk| pk.is_infinity)
{
continue;
}
// Generate random scalars.
let mut vals = [0u64; 4];
vals[0] = rng.gen();
while vals[0] == 0 {
// Do not use zero
vals[0] = rng.gen();
}
let mut rand_i = std::mem::MaybeUninit::<blst_scalar>::uninit();
// TODO: remove this `unsafe` code-block once we get a safe option from `blst`.
@@ -75,8 +69,12 @@ pub fn verify_signature_sets<'a>(
// Grab a slice of the message, to satisfy the blst API.
msgs_refs.push(set.message.as_bytes());
// Convert the aggregate signature into a signature.
if let Some(point) = set.signature.point() {
// Subgroup check the signature
if !point.0.subgroup_check() {
return false;
}
// Convert the aggregate signature into a signature.
sigs.push(point.0.to_signature())
} else {
// Any "empty" signature should cause a signature failure.
@@ -103,12 +101,6 @@ pub fn verify_signature_sets<'a>(
pks.push(blst_core::AggregatePublicKey::aggregate(&signing_keys).to_public_key());
}
// Due to an earlier check, the only case this can be empty is if all the sets consisted of
// infinity pubkeys/sigs. In such a case we wish to return `true`.
if msgs_refs.is_empty() {
return true;
}
let (sig_refs, pks_refs): (Vec<_>, Vec<_>) = sigs.iter().zip(pks.iter()).unzip();
let err = blst_core::Signature::verify_multiple_aggregate_signatures(
@@ -124,7 +116,15 @@ impl TPublicKey for blst_core::PublicKey {
}
fn deserialize(bytes: &[u8]) -> Result<Self, Error> {
Self::uncompress(&bytes).map_err(Into::into)
// key_validate accepts uncompressed bytes too so enforce byte length here.
// It also does subgroup checks, noting infinity check is done in `generic_public_key.rs`.
if bytes.len() != PUBLIC_KEY_BYTES_LEN {
return Err(Error::InvalidByteLength {
got: bytes.len(),
expected: PUBLIC_KEY_BYTES_LEN,
});
}
Self::key_validate(&bytes).map_err(Into::into)
}
}
@@ -145,25 +145,7 @@ impl PartialEq for BlstAggregatePublicKey {
}
}
impl TAggregatePublicKey for BlstAggregatePublicKey {
fn infinity() -> Self {
blst_core::PublicKey::from_bytes(&INFINITY_PUBLIC_KEY)
.map(|pk| blst_core::AggregatePublicKey::from_public_key(&pk))
.map(Self)
.expect("should decode infinity public key")
}
fn serialize(&self) -> [u8; PUBLIC_KEY_BYTES_LEN] {
self.0.to_public_key().compress()
}
fn deserialize(bytes: &[u8]) -> Result<Self, Error> {
blst_core::PublicKey::from_bytes(&bytes)
.map_err(Into::into)
.map(|pk| blst_core::AggregatePublicKey::from_public_key(&pk))
.map(Self)
}
}
impl TAggregatePublicKey for BlstAggregatePublicKey {}
impl TSignature<blst_core::PublicKey> for blst_core::Signature {
fn serialize(&self) -> [u8; SIGNATURE_BYTES_LEN] {
@@ -175,6 +157,9 @@ impl TSignature<blst_core::PublicKey> for blst_core::Signature {
}
fn verify(&self, pubkey: &blst_core::PublicKey, msg: Hash256) -> bool {
if !self.subgroup_check() {
return false;
}
self.verify(msg.as_bytes(), DST, &[], pubkey) == BLST_ERROR::BLST_SUCCESS
}
}
@@ -232,6 +217,9 @@ impl TAggregateSignature<blst_core::PublicKey, BlstAggregatePublicKey, blst_core
) -> bool {
let pubkeys = pubkeys.iter().map(|pk| pk.point()).collect::<Vec<_>>();
let signature = self.0.clone().to_signature();
if !signature.subgroup_check() {
return false;
}
signature.fast_aggregate_verify(msg.as_bytes(), DST, &pubkeys) == BLST_ERROR::BLST_SUCCESS
}
@@ -243,6 +231,9 @@ impl TAggregateSignature<blst_core::PublicKey, BlstAggregatePublicKey, blst_core
let pubkeys = pubkeys.iter().map(|pk| pk.point()).collect::<Vec<_>>();
let msgs = msgs.iter().map(|hash| hash.as_bytes()).collect::<Vec<_>>();
let signature = self.0.clone().to_signature();
if !signature.subgroup_check() {
return false;
}
signature.aggregate_verify(&msgs, DST, &pubkeys) == BLST_ERROR::BLST_SUCCESS
}
}

View File

@@ -63,25 +63,7 @@ impl PartialEq for PublicKey {
#[derive(Clone)]
pub struct AggregatePublicKey([u8; PUBLIC_KEY_BYTES_LEN]);
impl TAggregatePublicKey for AggregatePublicKey {
fn infinity() -> Self {
Self([0; PUBLIC_KEY_BYTES_LEN])
}
fn serialize(&self) -> [u8; PUBLIC_KEY_BYTES_LEN] {
let mut bytes = [0; PUBLIC_KEY_BYTES_LEN];
bytes[..].copy_from_slice(&self.0);
bytes
}
fn deserialize(bytes: &[u8]) -> Result<Self, Error> {
let mut key = [0; PUBLIC_KEY_BYTES_LEN];
key[..].copy_from_slice(&bytes);
Ok(Self(key))
}
}
impl TAggregatePublicKey for AggregatePublicKey {}
impl Eq for AggregatePublicKey {}

View File

@@ -4,7 +4,7 @@ use crate::{
generic_public_key::{GenericPublicKey, TPublicKey, PUBLIC_KEY_BYTES_LEN},
generic_secret_key::{TSecretKey, SECRET_KEY_BYTES_LEN},
generic_signature::{TSignature, SIGNATURE_BYTES_LEN},
Error, Hash256, ZeroizeHash, INFINITY_PUBLIC_KEY,
Error, Hash256, ZeroizeHash,
};
pub use milagro_bls as milagro;
use rand::thread_rng;
@@ -86,21 +86,7 @@ impl TPublicKey for milagro::PublicKey {
}
}
impl TAggregatePublicKey for milagro::AggregatePublicKey {
fn infinity() -> Self {
Self::from_bytes(&INFINITY_PUBLIC_KEY).expect("should decode infinity public key")
}
fn serialize(&self) -> [u8; PUBLIC_KEY_BYTES_LEN] {
let mut bytes = [0; PUBLIC_KEY_BYTES_LEN];
bytes[..].copy_from_slice(&self.as_bytes());
bytes
}
fn deserialize(bytes: &[u8]) -> Result<Self, Error> {
Self::from_bytes(&bytes).map_err(Into::into)
}
}
impl TAggregatePublicKey for milagro::AggregatePublicKey {}
impl TSignature<milagro::PublicKey> for milagro::Signature {
fn serialize(&self) -> [u8; SIGNATURE_BYTES_LEN] {

View File

@@ -56,6 +56,10 @@ pub enum Error {
InvalidByteLength { got: usize, expected: usize },
/// The provided secret key bytes were an incorrect length.
InvalidSecretKeyLength { got: usize, expected: usize },
/// The public key represents the point at infinity, which is invalid.
InvalidInfinityPublicKey,
/// The secret key is all zero bytes, which is invalid.
InvalidZeroSecretKey,
}
impl From<AmclError> for Error {

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 std::borrow::Cow;
use std::fmt::Debug;
@@ -19,6 +19,11 @@ macro_rules! test_suite {
SecretKey::deserialize(&secret_bytes).unwrap()
}
#[test]
fn invalid_zero_secret_key() {
assert!(SecretKey::deserialize(&[0; SECRET_KEY_BYTES_LEN]).is_err());
}
#[test]
fn infinity_agg_sig() {
assert_eq!(
@@ -131,11 +136,6 @@ macro_rules! test_suite {
self
}
pub fn infinity_pubkey(mut self) -> Self {
self.pubkey = PublicKey::deserialize(&INFINITY_PUBLIC_KEY[..]).unwrap();
self
}
pub fn assert_verify(self, is_valid: bool) {
assert_eq!(self.sig.verify(&self.pubkey, self.msg), is_valid);
@@ -153,14 +153,6 @@ macro_rules! test_suite {
SignatureTester::default().assert_verify(true)
}
#[test]
fn infinity_signature_is_valid_with_infinity_pubkey() {
SignatureTester::default()
.infinity_sig()
.infinity_pubkey()
.assert_verify(true)
}
#[test]
fn infinity_signature_is_invalid_with_standard_pubkey() {
SignatureTester::default()
@@ -168,13 +160,6 @@ macro_rules! test_suite {
.assert_verify(false)
}
#[test]
fn standard_signature_is_invalid_with_infinity_pubkey() {
SignatureTester::default()
.infinity_pubkey()
.assert_verify(false)
}
/// A helper struct for composing tests via the builder pattern.
struct AggregateSignatureTester {
sig: AggregateSignature,
@@ -234,17 +219,6 @@ macro_rules! test_suite {
self
}
pub fn single_infinity_pubkey(mut self) -> Self {
self.pubkeys = vec![PublicKey::deserialize(&INFINITY_PUBLIC_KEY[..]).unwrap()];
self
}
pub fn push_infinity_pubkey(mut self) -> Self {
self.pubkeys
.push(PublicKey::deserialize(&INFINITY_PUBLIC_KEY[..]).unwrap());
self
}
pub fn assert_single_message_verify(self, is_valid: bool) {
assert!(self.msgs.len() == 1);
let msg = self.msgs.first().unwrap();
@@ -304,15 +278,6 @@ macro_rules! test_suite {
.assert_single_message_verify(false)
}
/// The infinity signature and one infinity pubkey should verify.
#[test]
fn fast_aggregate_verify_infinity_signature_with_one_infinity_pubkey() {
AggregateSignatureTester::new_with_single_msg(1)
.infinity_sig()
.single_infinity_pubkey()
.assert_single_message_verify(true)
}
/// Adding a infinity signature (without an infinity pubkey) should verify.
#[test]
fn fast_aggregate_verify_with_one_aggregated_infinity_sig() {
@@ -332,34 +297,6 @@ macro_rules! test_suite {
.assert_single_message_verify(true)
}
/// Adding a infinity pubkey and an infinity signature should verify.
#[test]
fn fast_aggregate_verify_with_one_additional_infinity_pubkey_and_matching_sig() {
AggregateSignatureTester::new_with_single_msg(1)
.aggregate_infinity_sig()
.push_infinity_pubkey()
.assert_single_message_verify(true)
}
/// Adding a single infinity pubkey **without** updating the signature **should verify**.
#[test]
fn fast_aggregate_verify_with_one_additional_infinity_pubkey() {
AggregateSignatureTester::new_with_single_msg(1)
.push_infinity_pubkey()
.assert_single_message_verify(true)
}
/// Adding multiple infinity pubkeys **without** updating the signature **should verify**.
#[test]
fn fast_aggregate_verify_with_four_additional_infinity_pubkeys() {
AggregateSignatureTester::new_with_single_msg(1)
.push_infinity_pubkey()
.push_infinity_pubkey()
.push_infinity_pubkey()
.push_infinity_pubkey()
.assert_single_message_verify(true)
}
/// The wrong signature should not verify.
#[test]
fn fast_aggregate_verify_wrong_signature() {
@@ -463,18 +400,6 @@ macro_rules! test_suite {
self
}
pub fn push_invalid_sig_infinity_set(mut self) -> Self {
let mut signature = AggregateSignature::infinity();
signature.add_assign(&secret_from_u64(42).sign(Hash256::zero()));
self.owned_sets.push(OwnedSignatureSet {
signature,
signing_keys: vec![PublicKey::deserialize(&INFINITY_PUBLIC_KEY).unwrap()],
message: Hash256::zero(),
should_be_valid: false,
});
self
}
pub fn push_invalid_pubkey_infinity_set(mut self) -> Self {
self.owned_sets.push(OwnedSignatureSet {
signature: AggregateSignature::deserialize(&INFINITY_SIGNATURE).unwrap(),
@@ -485,16 +410,6 @@ macro_rules! test_suite {
self
}
pub fn push_valid_infinity_set(mut self) -> Self {
self.owned_sets.push(OwnedSignatureSet {
signature: AggregateSignature::deserialize(&INFINITY_SIGNATURE).unwrap(),
signing_keys: vec![PublicKey::deserialize(&INFINITY_PUBLIC_KEY).unwrap()],
message: Hash256::zero(),
should_be_valid: true,
});
self
}
pub fn run_checks(self) {
assert!(!self.owned_sets.is_empty(), "empty test is meaningless");
@@ -568,22 +483,6 @@ macro_rules! test_suite {
.run_checks()
}
#[test]
fn signature_set_1_valid_set_with_1_infinity_set() {
SignatureSetTester::default()
.push_valid_infinity_set()
.run_checks()
}
#[test]
fn signature_set_3_sets_with_one_valid_infinity_set() {
SignatureSetTester::default()
.push_valid_set(2)
.push_valid_infinity_set()
.push_valid_set(2)
.run_checks()
}
#[test]
fn signature_set_3_sets_with_one_invalid_pubkey_infinity_set() {
SignatureSetTester::default()
@@ -592,15 +491,6 @@ macro_rules! test_suite {
.push_valid_set(2)
.run_checks()
}
#[test]
fn signature_set_3_sets_with_one_invalid_sig_infinity_set() {
SignatureSetTester::default()
.push_valid_set(2)
.push_invalid_sig_infinity_set()
.push_valid_set(2)
.run_checks()
}
};
}

View File

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

View File

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

View File

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

View File

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

View File

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

View File

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

View File

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

View File

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

View File

@@ -7,7 +7,7 @@ use lighthouse_version::VERSION;
use slog::{crit, info, warn};
use std::path::PathBuf;
use std::process::exit;
use types::EthSpec;
use types::{EthSpec, EthSpecId};
use validator_client::ProductionValidatorClient;
pub const ETH2_CONFIG_FILENAME: &str = "eth2-spec.toml";
@@ -15,6 +15,8 @@ pub const ETH2_CONFIG_FILENAME: &str = "eth2-spec.toml";
fn bls_library_name() -> &'static str {
if cfg!(feature = "portable") {
"blst-portable"
} else if cfg!(feature = "modern") {
"blst-modern"
} else if cfg!(feature = "milagro") {
"milagro"
} else {
@@ -43,12 +45,11 @@ fn main() {
Arg::with_name("spec")
.short("s")
.long("spec")
.value_name("TITLE")
.help("Specifies the default eth2 spec type.")
.value_name("DEPRECATED")
.help("This flag is deprecated, it will be disallowed in a future release. This \
value is now derived from the --testnet or --testnet-dir flags.")
.takes_value(true)
.possible_values(&["mainnet", "minimal", "interop"])
.global(true)
.default_value("mainnet"),
)
.arg(
Arg::with_name("env_log")
@@ -126,37 +127,35 @@ fn main() {
.subcommand(account_manager::cli_app())
.get_matches();
// boot node subcommand circumvents the environment
if let Some(bootnode_matches) = matches.subcommand_matches("boot_node") {
// The bootnode uses the main debug-level flag
let debug_info = matches
.value_of("debug-level")
.expect("Debug-level must be present")
.into();
boot_node::run(bootnode_matches, debug_info);
return;
}
// Debugging output for libp2p and external crates.
if matches.is_present("env_log") {
Builder::from_env(Env::default()).init();
}
macro_rules! run_with_spec {
($env_builder: expr) => {
run($env_builder, &matches)
};
}
let result = load_testnet_config(&matches).and_then(|testnet_config| {
let eth_spec_id = testnet_config.eth_spec_id()?;
let result = match matches.value_of("spec") {
Some("minimal") => run_with_spec!(EnvironmentBuilder::minimal()),
Some("mainnet") => run_with_spec!(EnvironmentBuilder::mainnet()),
Some("interop") => run_with_spec!(EnvironmentBuilder::interop()),
spec => {
// This path should be unreachable due to slog having a `default_value`
unreachable!("Unknown spec configuration: {:?}", spec);
// boot node subcommand circumvents the environment
if let Some(bootnode_matches) = matches.subcommand_matches("boot_node") {
// The bootnode uses the main debug-level flag
let debug_info = matches
.value_of("debug-level")
.expect("Debug-level must be present")
.into();
boot_node::run(bootnode_matches, eth_spec_id, debug_info);
return Ok(());
}
};
match eth_spec_id {
EthSpecId::Minimal => run(EnvironmentBuilder::minimal(), &matches, testnet_config),
EthSpecId::Mainnet => run(EnvironmentBuilder::mainnet(), &matches, testnet_config),
EthSpecId::V012Legacy => {
run(EnvironmentBuilder::v012_legacy(), &matches, testnet_config)
}
}
});
// `std::process::exit` does not run destructors so we drop manually.
drop(matches);
@@ -172,9 +171,23 @@ fn main() {
}
}
fn load_testnet_config(matches: &ArgMatches) -> Result<Eth2TestnetConfig, String> {
if matches.is_present("testnet-dir") {
clap_utils::parse_testnet_dir(matches, "testnet-dir")?
.ok_or_else(|| "Unable to load testnet dir".to_string())
} else if matches.is_present("testnet") {
clap_utils::parse_hardcoded_network(matches, "testnet")?
.ok_or_else(|| "Unable to load hard coded network config".to_string())
} else {
Eth2TestnetConfig::hard_coded_default()?
.ok_or_else(|| "Unable to load default network config".to_string())
}
}
fn run<E: EthSpec>(
environment_builder: EnvironmentBuilder<E>,
matches: &ArgMatches,
testnet_config: Eth2TestnetConfig,
) -> Result<(), String> {
if std::mem::size_of::<usize>() != 8 {
return Err(format!(
@@ -183,25 +196,19 @@ fn run<E: EthSpec>(
));
}
#[cfg(all(feature = "modern", target_arch = "x86_64"))]
if !std::is_x86_feature_detected!("adx") {
return Err(format!(
"CPU incompatible with optimized binary, please try Lighthouse portable build"
));
}
let debug_level = matches
.value_of("debug-level")
.ok_or_else(|| "Expected --debug-level flag".to_string())?;
let log_format = matches.value_of("log-format");
// Parse testnet config from the `testnet` and `testnet-dir` flag in that order
// else, use the default
let mut optional_testnet_config = None;
if matches.is_present("testnet") {
optional_testnet_config = clap_utils::parse_hardcoded_network(matches, "testnet")?;
};
if matches.is_present("testnet-dir") {
optional_testnet_config = clap_utils::parse_testnet_dir(matches, "testnet-dir")?;
};
if optional_testnet_config.is_none() {
optional_testnet_config = Eth2TestnetConfig::hard_coded_default()?;
}
let builder = if let Some(log_path) = matches.value_of("logfile") {
let path = log_path
.parse::<PathBuf>()
@@ -213,11 +220,18 @@ fn run<E: EthSpec>(
let mut environment = builder
.multi_threaded_tokio_runtime()?
.optional_eth2_testnet_config(optional_testnet_config)?
.optional_eth2_testnet_config(Some(testnet_config))?
.build()?;
let log = environment.core_context().log().clone();
if matches.is_present("spec") {
warn!(
log,
"The --spec flag is deprecated and will be removed in a future release"
);
}
// Note: the current code technically allows for starting a beacon node _and_ a validator
// client at the same time.
//
@@ -264,7 +278,6 @@ fn run<E: EthSpec>(
let executor = context.executor.clone();
let config = beacon_node::get_config::<E>(
matches,
&context.eth2_config.spec_constants,
&context.eth2_config().spec,
context.log().clone(),
)?;

View File

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

View File

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

View File

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

View File

@@ -14,7 +14,7 @@ pub struct BlsSignInput {
#[derive(Debug, Clone, Deserialize)]
pub struct BlsSign {
pub input: BlsSignInput,
pub output: String,
pub output: Option<String>,
}
impl BlsCase for BlsSign {}
@@ -27,16 +27,25 @@ impl Case for BlsSign {
assert_eq!(sk.len(), 32);
let sk = SecretKey::deserialize(&sk).unwrap();
let sk = match SecretKey::deserialize(&sk) {
Ok(sk) => sk,
Err(_) if self.output.is_none() => {
return Ok(());
}
Err(e) => return Err(Error::FailedToParseTest(format!("{:?}", e))),
};
let msg = hex::decode(&self.input.message[2..])
.map_err(|e| Error::FailedToParseTest(format!("{:?}", e)))?;
let signature = sk.sign(Hash256::from_slice(&msg));
// Convert the output to one set of bytes
let decoded = hex::decode(&self.output[2..])
let decoded = self
.output
.as_ref()
.map(|output| hex::decode(&output[2..]))
.transpose()
.map_err(|e| Error::FailedToParseTest(format!("{:?}", e)))?;
compare_result::<Vec<u8>, Vec<u8>>(&Ok(signature.serialize().to_vec()), &Some(decoded))
compare_result::<Vec<u8>, Vec<u8>>(&Ok(signature.serialize().to_vec()), &decoded)
}
}

View File

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

View File

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

View File

@@ -172,6 +172,7 @@ mod ssz_static {
use ef_tests::{Handler, SszStaticHandler, SszStaticTHCHandler};
use types::*;
ssz_static_test!(aggregate_and_proof, AggregateAndProof<_>);
ssz_static_test!(attestation, Attestation<_>);
ssz_static_test!(attestation_data, AttestationData);
ssz_static_test!(attester_slashing, AttesterSlashing<_>);
@@ -188,12 +189,24 @@ mod ssz_static {
ssz_static_test!(checkpoint, Checkpoint);
ssz_static_test!(deposit, Deposit);
ssz_static_test!(deposit_data, DepositData);
ssz_static_test!(deposit_message, DepositMessage);
// FIXME(sproul): move Eth1Block to consensus/types
//
// Tracked at: https://github.com/sigp/lighthouse/issues/1835
//
// ssz_static_test!(eth1_block, Eth1Block);
ssz_static_test!(eth1_data, Eth1Data);
ssz_static_test!(fork, Fork);
ssz_static_test!(fork_data, ForkData);
ssz_static_test!(historical_batch, HistoricalBatch<_>);
ssz_static_test!(indexed_attestation, IndexedAttestation<_>);
ssz_static_test!(pending_attestation, PendingAttestation<_>);
ssz_static_test!(proposer_slashing, ProposerSlashing);
ssz_static_test!(signed_aggregate_and_proof, SignedAggregateAndProof<_>);
ssz_static_test!(signed_beacon_block, SignedBeaconBlock<_>);
ssz_static_test!(signed_beacon_block_header, SignedBeaconBlockHeader);
ssz_static_test!(signed_voluntary_exit, SignedVoluntaryExit);
ssz_static_test!(signing_data, SigningData);
ssz_static_test!(validator, Validator);
ssz_static_test!(voluntary_exit, VoluntaryExit);
}
@@ -217,7 +230,7 @@ fn epoch_processing_justification_and_finalization() {
#[test]
fn epoch_processing_rewards_and_penalties() {
EpochProcessingHandler::<MinimalEthSpec, RewardsAndPenalties>::run();
// Note: there are no reward and penalty tests for mainnet yet
EpochProcessingHandler::<MainnetEthSpec, RewardsAndPenalties>::run();
}
#[test]

View File

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

View File

@@ -414,7 +414,6 @@ impl InitializedValidators {
/// validator will be removed from `self.validators`.
///
/// Saves the `ValidatorDefinitions` to file, even if no definitions were changed.
#[allow(dead_code)] // Will be used once VC API is enabled.
pub async fn set_validator_status(
&mut self,
voting_public_key: &PublicKey,