diff --git a/Cargo.lock b/Cargo.lock index 3cef8b674c6..342b79562b1 100644 --- a/Cargo.lock +++ b/Cargo.lock @@ -4,146 +4,157 @@ name = "account_manager" version = "0.2.12" dependencies = [ - "account_utils 0.1.0", - "bls 0.2.0", - "clap 2.33.3 (registry+https://github.com/rust-lang/crates.io-index)", - "clap_utils 0.1.0", - "deposit_contract 0.2.0", - "directory 0.1.0", - "dirs 2.0.2 (registry+https://github.com/rust-lang/crates.io-index)", - "environment 0.1.2", - "eth2_keystore 0.1.0", - "eth2_ssz 0.1.2", - "eth2_ssz_derive 0.1.0", - "eth2_testnet_config 0.2.0", - "eth2_wallet 0.1.0", - "eth2_wallet_manager 0.1.0", - "futures 0.3.5 (registry+https://github.com/rust-lang/crates.io-index)", - "hex 0.4.2 (registry+https://github.com/rust-lang/crates.io-index)", - "libc 0.2.77 (registry+https://github.com/rust-lang/crates.io-index)", - "rand 0.7.3 (registry+https://github.com/rust-lang/crates.io-index)", - "rayon 1.4.0 (registry+https://github.com/rust-lang/crates.io-index)", - "slog 2.5.2 (registry+https://github.com/rust-lang/crates.io-index)", - "slog-async 2.5.0 (registry+https://github.com/rust-lang/crates.io-index)", - "slog-term 2.6.0 (registry+https://github.com/rust-lang/crates.io-index)", - "state_processing 0.2.0", - "tokio 0.2.22 (registry+https://github.com/rust-lang/crates.io-index)", - "types 0.2.0", - "validator_dir 0.1.0", - "web3 0.11.0 (registry+https://github.com/rust-lang/crates.io-index)", + "account_utils", + "bls", + "clap", + "clap_utils", + "deposit_contract", + "directory", + "dirs", + "environment", + "eth2_keystore", + "eth2_ssz", + "eth2_ssz_derive", + "eth2_testnet_config", + "eth2_wallet", + "eth2_wallet_manager", + "futures 0.3.5", + "hex 0.4.2", + "libc", + "rand 0.7.3", + "rayon", + "slog", + "slog-async", + "slog-term", + "state_processing", + "tokio 0.2.22", + "types", + "validator_dir", + "web3", ] [[package]] name = "account_utils" version = "0.1.0" dependencies = [ - "eth2_keystore 0.1.0", - "eth2_wallet 0.1.0", - "rand 0.7.3 (registry+https://github.com/rust-lang/crates.io-index)", - "regex 1.3.9 (registry+https://github.com/rust-lang/crates.io-index)", - "rpassword 4.0.5 (registry+https://github.com/rust-lang/crates.io-index)", - "serde 1.0.116 (registry+https://github.com/rust-lang/crates.io-index)", - "serde_derive 1.0.116 (registry+https://github.com/rust-lang/crates.io-index)", - "serde_yaml 0.8.13 (registry+https://github.com/rust-lang/crates.io-index)", - "slog 2.5.2 (registry+https://github.com/rust-lang/crates.io-index)", - "types 0.2.0", - "validator_dir 0.1.0", - "zeroize 1.1.1 (registry+https://github.com/rust-lang/crates.io-index)", + "eth2_keystore", + "eth2_wallet", + "rand 0.7.3", + "regex", + "rpassword", + "serde", + "serde_derive", + "serde_yaml", + "slog", + "types", + "validator_dir", + "zeroize", ] [[package]] name = "addr2line" version = "0.13.0" source = "registry+https://github.com/rust-lang/crates.io-index" +checksum = "1b6a2d3371669ab3ca9797670853d61402b03d0b4b9ebf33d677dfa720203072" dependencies = [ - "gimli 0.22.0 (registry+https://github.com/rust-lang/crates.io-index)", + "gimli", ] [[package]] name = "adler" version = "0.2.3" source = "registry+https://github.com/rust-lang/crates.io-index" +checksum = "ee2a4ec343196209d6594e19543ae87a39f96d5534d7174822a3ad825dd6ed7e" [[package]] name = "adler32" version = "1.2.0" source = "registry+https://github.com/rust-lang/crates.io-index" +checksum = "aae1277d39aeec15cb388266ecc24b11c80469deae6067e17a1a7aa9e5c1f234" [[package]] name = "aead" version = "0.3.2" source = "registry+https://github.com/rust-lang/crates.io-index" +checksum = "7fc95d1bdb8e6666b2b217308eeeb09f2d6728d104be3e31916cc74d15420331" dependencies = [ - "generic-array 0.14.4 (registry+https://github.com/rust-lang/crates.io-index)", + "generic-array 0.14.4", ] [[package]] name = "aes" version = "0.4.0" source = "registry+https://github.com/rust-lang/crates.io-index" +checksum = "f7001367fde4c768a19d1029f0a8be5abd9308e1119846d5bd9ad26297b8faf5" dependencies = [ - "aes-soft 0.4.0 (registry+https://github.com/rust-lang/crates.io-index)", - "aesni 0.7.0 (registry+https://github.com/rust-lang/crates.io-index)", - "block-cipher 0.7.1 (registry+https://github.com/rust-lang/crates.io-index)", + "aes-soft", + "aesni", + "block-cipher", ] [[package]] name = "aes-ctr" version = "0.4.0" source = "registry+https://github.com/rust-lang/crates.io-index" +checksum = "92e60aeefd2a0243bd53a42e92444e039f67c3d7f0382c9813577696e7c10bf3" dependencies = [ - "aes-soft 0.4.0 (registry+https://github.com/rust-lang/crates.io-index)", - "aesni 0.7.0 (registry+https://github.com/rust-lang/crates.io-index)", - "ctr 0.4.0 (registry+https://github.com/rust-lang/crates.io-index)", - "stream-cipher 0.4.1 (registry+https://github.com/rust-lang/crates.io-index)", + "aes-soft", + "aesni", + "ctr", + "stream-cipher", ] [[package]] name = "aes-gcm" version = "0.6.0" source = "registry+https://github.com/rust-lang/crates.io-index" +checksum = "86f5007801316299f922a6198d1d09a0bae95786815d066d5880d13f7c45ead1" dependencies = [ - "aead 0.3.2 (registry+https://github.com/rust-lang/crates.io-index)", - "aes 0.4.0 (registry+https://github.com/rust-lang/crates.io-index)", - "block-cipher 0.7.1 (registry+https://github.com/rust-lang/crates.io-index)", - "ghash 0.3.0 (registry+https://github.com/rust-lang/crates.io-index)", - "subtle 2.3.0 (registry+https://github.com/rust-lang/crates.io-index)", + "aead", + "aes", + "block-cipher", + "ghash", + "subtle 2.3.0", ] [[package]] name = "aes-soft" version = "0.4.0" source = "registry+https://github.com/rust-lang/crates.io-index" +checksum = "4925647ee64e5056cf231608957ce7c81e12d6d6e316b9ce1404778cc1d35fa7" dependencies = [ - "block-cipher 0.7.1 (registry+https://github.com/rust-lang/crates.io-index)", - "byteorder 1.3.4 (registry+https://github.com/rust-lang/crates.io-index)", - "opaque-debug 0.2.3 (registry+https://github.com/rust-lang/crates.io-index)", + "block-cipher", + "byteorder", + "opaque-debug 0.2.3", ] [[package]] name = "aesni" version = "0.7.0" source = "registry+https://github.com/rust-lang/crates.io-index" +checksum = "d050d39b0b7688b3a3254394c3e30a9d66c41dcf9b05b0e2dbdc623f6505d264" dependencies = [ - "block-cipher 0.7.1 (registry+https://github.com/rust-lang/crates.io-index)", - "opaque-debug 0.2.3 (registry+https://github.com/rust-lang/crates.io-index)", - "stream-cipher 0.4.1 (registry+https://github.com/rust-lang/crates.io-index)", + "block-cipher", + "opaque-debug 0.2.3", + "stream-cipher", ] [[package]] name = "ahash" version = "0.2.18" source = "registry+https://github.com/rust-lang/crates.io-index" +checksum = "6f33b5018f120946c1dcf279194f238a9f146725593ead1c08fa47ff22b0b5d3" dependencies = [ - "const-random 0.1.8 (registry+https://github.com/rust-lang/crates.io-index)", + "const-random", ] [[package]] name = "aho-corasick" version = "0.7.13" source = "registry+https://github.com/rust-lang/crates.io-index" +checksum = "043164d8ba5c4c3035fec9bbee8647c0261d788f3474306f93bb65901cae0e86" dependencies = [ - "memchr 2.3.3 (registry+https://github.com/rust-lang/crates.io-index)", + "memchr", ] [[package]] @@ -151,336 +162,359 @@ name = "amcl" version = "0.2.0" source = "git+https://github.com/sigp/milagro_bls?branch=paulh#7662690845f3f2594e46cfe71b6b0bb91d5e1f82" dependencies = [ - "hex 0.3.2 (registry+https://github.com/rust-lang/crates.io-index)", - "lazy_static 1.4.0 (registry+https://github.com/rust-lang/crates.io-index)", + "hex 0.3.2", + "lazy_static", ] [[package]] name = "ansi_term" version = "0.11.0" source = "registry+https://github.com/rust-lang/crates.io-index" +checksum = "ee49baf6cb617b853aa8d93bf420db2383fab46d314482ca2803b40d5fde979b" dependencies = [ - "winapi 0.3.9 (registry+https://github.com/rust-lang/crates.io-index)", + "winapi 0.3.9", ] [[package]] name = "anyhow" version = "1.0.32" source = "registry+https://github.com/rust-lang/crates.io-index" +checksum = "6b602bfe940d21c130f3895acd65221e8a61270debe89d628b9cb4e3ccb8569b" [[package]] name = "arbitrary" version = "0.4.6" source = "registry+https://github.com/rust-lang/crates.io-index" +checksum = "0922a3e746b5a44e111e5603feb6704e5cc959116f66737f50bb5cbd264e9d87" dependencies = [ - "derive_arbitrary 0.4.6 (registry+https://github.com/rust-lang/crates.io-index)", + "derive_arbitrary", ] [[package]] name = "arc-swap" version = "0.4.7" source = "registry+https://github.com/rust-lang/crates.io-index" +checksum = "4d25d88fd6b8041580a654f9d0c581a047baee2b3efee13275f2fc392fc75034" [[package]] name = "arrayref" version = "0.3.6" source = "registry+https://github.com/rust-lang/crates.io-index" +checksum = "a4c527152e37cf757a3f78aae5a06fbeefdb07ccc535c980a3208ee3060dd544" [[package]] name = "arrayvec" version = "0.5.1" source = "registry+https://github.com/rust-lang/crates.io-index" +checksum = "cff77d8686867eceff3105329d4698d96c2391c176d5d03adc90c7389162b5b8" [[package]] name = "asn1_der" version = "0.6.3" source = "registry+https://github.com/rust-lang/crates.io-index" +checksum = "6fce6b6a0ffdafebd82c87e79e3f40e8d2c523e5fea5566ff6b90509bf98d638" dependencies = [ - "asn1_der_derive 0.1.2 (registry+https://github.com/rust-lang/crates.io-index)", + "asn1_der_derive", ] [[package]] name = "asn1_der_derive" version = "0.1.2" source = "registry+https://github.com/rust-lang/crates.io-index" +checksum = "0d0864d84b8e07b145449be9a8537db86bf9de5ce03b913214694643b4743502" dependencies = [ - "quote 1.0.7 (registry+https://github.com/rust-lang/crates.io-index)", - "syn 1.0.42 (registry+https://github.com/rust-lang/crates.io-index)", + "quote", + "syn", ] -[[package]] -name = "assert_matches" -version = "1.3.0" -source = "registry+https://github.com/rust-lang/crates.io-index" - [[package]] name = "async-tls" version = "0.8.0" source = "registry+https://github.com/rust-lang/crates.io-index" +checksum = "df097e3f506bec0e1a24f06bb3c962c228f36671de841ff579cb99f371772634" dependencies = [ - "futures 0.3.5 (registry+https://github.com/rust-lang/crates.io-index)", - "rustls 0.18.1 (registry+https://github.com/rust-lang/crates.io-index)", - "webpki 0.21.2 (registry+https://github.com/rust-lang/crates.io-index)", - "webpki-roots 0.19.0 (registry+https://github.com/rust-lang/crates.io-index)", + "futures 0.3.5", + "rustls", + "webpki", + "webpki-roots 0.19.0", ] [[package]] name = "atomic" version = "0.4.6" source = "registry+https://github.com/rust-lang/crates.io-index" +checksum = "64f46ca51dca4837f1520754d1c8c36636356b81553d928dc9c177025369a06e" [[package]] name = "atomic-option" version = "0.1.2" source = "registry+https://github.com/rust-lang/crates.io-index" +checksum = "0db678acb667b525ac40a324fc5f7d3390e29239b31c7327bb8157f5b4fff593" [[package]] name = "atty" version = "0.2.14" source = "registry+https://github.com/rust-lang/crates.io-index" +checksum = "d9b39be18770d11421cdb1b9947a45dd3f37e93092cbf377614828a319d5fee8" dependencies = [ - "hermit-abi 0.1.16 (registry+https://github.com/rust-lang/crates.io-index)", - "libc 0.2.77 (registry+https://github.com/rust-lang/crates.io-index)", - "winapi 0.3.9 (registry+https://github.com/rust-lang/crates.io-index)", + "hermit-abi", + "libc", + "winapi 0.3.9", ] [[package]] name = "autocfg" version = "0.1.7" source = "registry+https://github.com/rust-lang/crates.io-index" +checksum = "1d49d90015b3c36167a20fe2810c5cd875ad504b39cff3d4eae7977e6b7c1cb2" [[package]] name = "autocfg" version = "1.0.1" source = "registry+https://github.com/rust-lang/crates.io-index" +checksum = "cdb031dd78e28731d87d56cc8ffef4a8f36ca26c38fe2de700543e627f8a464a" [[package]] name = "backtrace" version = "0.3.50" source = "registry+https://github.com/rust-lang/crates.io-index" +checksum = "46254cf2fdcdf1badb5934448c1bcbe046a56537b3987d96c51a7afc5d03f293" dependencies = [ - "addr2line 0.13.0 (registry+https://github.com/rust-lang/crates.io-index)", - "cfg-if 0.1.10 (registry+https://github.com/rust-lang/crates.io-index)", - "libc 0.2.77 (registry+https://github.com/rust-lang/crates.io-index)", - "miniz_oxide 0.4.2 (registry+https://github.com/rust-lang/crates.io-index)", - "object 0.20.0 (registry+https://github.com/rust-lang/crates.io-index)", - "rustc-demangle 0.1.16 (registry+https://github.com/rust-lang/crates.io-index)", + "addr2line", + "cfg-if", + "libc", + "miniz_oxide", + "object", + "rustc-demangle", ] [[package]] name = "base-x" version = "0.2.6" source = "registry+https://github.com/rust-lang/crates.io-index" +checksum = "1b20b618342cf9891c292c4f5ac2cde7287cc5c87e87e9c769d617793607dec1" [[package]] name = "base64" version = "0.9.3" source = "registry+https://github.com/rust-lang/crates.io-index" +checksum = "489d6c0ed21b11d038c31b6ceccca973e65d73ba3bd8ecb9a2babf5546164643" dependencies = [ - "byteorder 1.3.4 (registry+https://github.com/rust-lang/crates.io-index)", - "safemem 0.3.3 (registry+https://github.com/rust-lang/crates.io-index)", + "byteorder", + "safemem", ] [[package]] name = "base64" version = "0.12.3" source = "registry+https://github.com/rust-lang/crates.io-index" +checksum = "3441f0f7b02788e948e47f457ca01f1d7e6d92c693bc132c22b087d3141c03ff" [[package]] name = "beacon_chain" version = "0.2.0" dependencies = [ - "bitvec 0.17.4 (registry+https://github.com/rust-lang/crates.io-index)", - "bls 0.2.0", - "bus 2.2.3 (registry+https://github.com/rust-lang/crates.io-index)", - "derivative 2.1.1 (registry+https://github.com/rust-lang/crates.io-index)", - "environment 0.1.2", - "eth1 0.2.0", - "eth2_config 0.2.0", - "eth2_hashing 0.1.1", - "eth2_ssz 0.1.2", - "eth2_ssz_derive 0.1.0", - "eth2_ssz_types 0.2.0", - "fork_choice 0.1.0", - "futures 0.3.5 (registry+https://github.com/rust-lang/crates.io-index)", - "genesis 0.2.0", - "int_to_bytes 0.2.0", - "integer-sqrt 0.1.5 (registry+https://github.com/rust-lang/crates.io-index)", - "itertools 0.9.0 (registry+https://github.com/rust-lang/crates.io-index)", - "lazy_static 1.4.0 (registry+https://github.com/rust-lang/crates.io-index)", - "lighthouse_metrics 0.2.0", - "log 0.4.11 (registry+https://github.com/rust-lang/crates.io-index)", - "lru 0.5.3 (registry+https://github.com/rust-lang/crates.io-index)", - "maplit 1.0.2 (registry+https://github.com/rust-lang/crates.io-index)", - "merkle_proof 0.2.0", - "operation_pool 0.2.0", - "parking_lot 0.11.0 (registry+https://github.com/rust-lang/crates.io-index)", - "proto_array 0.2.0", - "rand 0.7.3 (registry+https://github.com/rust-lang/crates.io-index)", - "rand_core 0.5.1 (registry+https://github.com/rust-lang/crates.io-index)", - "rayon 1.4.0 (registry+https://github.com/rust-lang/crates.io-index)", - "regex 1.3.9 (registry+https://github.com/rust-lang/crates.io-index)", - "safe_arith 0.1.0", - "serde 1.0.116 (registry+https://github.com/rust-lang/crates.io-index)", - "serde_derive 1.0.116 (registry+https://github.com/rust-lang/crates.io-index)", - "serde_json 1.0.57 (registry+https://github.com/rust-lang/crates.io-index)", - "serde_yaml 0.8.13 (registry+https://github.com/rust-lang/crates.io-index)", - "slog 2.5.2 (registry+https://github.com/rust-lang/crates.io-index)", - "slog-term 2.6.0 (registry+https://github.com/rust-lang/crates.io-index)", - "sloggers 1.0.1 (registry+https://github.com/rust-lang/crates.io-index)", - "slot_clock 0.2.0", - "smallvec 1.4.2 (registry+https://github.com/rust-lang/crates.io-index)", - "state_processing 0.2.0", - "store 0.2.0", - "tempfile 3.1.0 (registry+https://github.com/rust-lang/crates.io-index)", - "tokio 0.2.22 (registry+https://github.com/rust-lang/crates.io-index)", - "tree_hash 0.1.1", - "types 0.2.0", - "websocket_server 0.2.0", + "bitvec", + "bls", + "bus", + "derivative", + "environment", + "eth1", + "eth2_config", + "eth2_hashing", + "eth2_ssz", + "eth2_ssz_derive", + "eth2_ssz_types", + "fork_choice", + "futures 0.3.5", + "genesis", + "int_to_bytes", + "integer-sqrt", + "itertools 0.9.0", + "lazy_static", + "lighthouse_metrics", + "log 0.4.11", + "lru", + "maplit", + "merkle_proof", + "operation_pool", + "parking_lot 0.11.0", + "proto_array", + "rand 0.7.3", + "rand_core 0.5.1", + "rayon", + "safe_arith", + "serde", + "serde_derive", + "serde_json", + "serde_yaml", + "slog", + "slog-term", + "sloggers", + "slot_clock", + "smallvec 1.4.2", + "state_processing", + "store", + "tempfile", + "tokio 0.2.22", + "tree_hash", + "types", + "websocket_server", ] [[package]] name = "beacon_node" version = "0.2.12" dependencies = [ - "beacon_chain 0.2.0", - "clap 2.33.3 (registry+https://github.com/rust-lang/crates.io-index)", - "clap_utils 0.1.0", - "client 0.2.0", - "ctrlc 3.1.6 (registry+https://github.com/rust-lang/crates.io-index)", - "directory 0.1.0", - "dirs 2.0.2 (registry+https://github.com/rust-lang/crates.io-index)", - "environment 0.1.2", - "eth2_config 0.2.0", - "eth2_libp2p 0.2.0", - "eth2_ssz 0.1.2", - "eth2_testnet_config 0.2.0", - "exit-future 0.2.0 (registry+https://github.com/rust-lang/crates.io-index)", - "futures 0.3.5 (registry+https://github.com/rust-lang/crates.io-index)", - "genesis 0.2.0", - "hyper 0.13.8 (registry+https://github.com/rust-lang/crates.io-index)", - "lighthouse_version 0.1.0", - "logging 0.2.0", - "node_test_rig 0.2.0", - "rand 0.7.3 (registry+https://github.com/rust-lang/crates.io-index)", - "serde 1.0.116 (registry+https://github.com/rust-lang/crates.io-index)", - "slog 2.5.2 (registry+https://github.com/rust-lang/crates.io-index)", - "slog-async 2.5.0 (registry+https://github.com/rust-lang/crates.io-index)", - "slog-term 2.6.0 (registry+https://github.com/rust-lang/crates.io-index)", - "store 0.2.0", - "tokio 0.2.22 (registry+https://github.com/rust-lang/crates.io-index)", - "types 0.2.0", + "beacon_chain", + "clap", + "clap_utils", + "client", + "ctrlc", + "directory", + "dirs", + "environment", + "eth2_config", + "eth2_libp2p", + "eth2_ssz", + "eth2_testnet_config", + "exit-future", + "futures 0.3.5", + "genesis", + "hyper 0.13.8", + "lighthouse_version", + "logging", + "node_test_rig", + "rand 0.7.3", + "serde", + "slog", + "slog-async", + "slog-term", + "store", + "tokio 0.2.22", + "types", ] [[package]] name = "bitflags" version = "0.9.1" source = "registry+https://github.com/rust-lang/crates.io-index" +checksum = "4efd02e230a02e18f92fc2735f44597385ed02ad8f831e7c1c1156ee5e1ab3a5" [[package]] name = "bitflags" version = "1.2.1" source = "registry+https://github.com/rust-lang/crates.io-index" +checksum = "cf1de2fe8c75bc145a2f577add951f8134889b4795d47466a54a5c846d691693" [[package]] name = "bitvec" version = "0.17.4" source = "registry+https://github.com/rust-lang/crates.io-index" +checksum = "41262f11d771fd4a61aa3ce019fca363b4b6c282fca9da2a31186d3965a47a5c" dependencies = [ - "either 1.6.1 (registry+https://github.com/rust-lang/crates.io-index)", - "radium 0.3.0 (registry+https://github.com/rust-lang/crates.io-index)", + "either", + "radium", ] [[package]] name = "blake2" version = "0.9.0" source = "registry+https://github.com/rust-lang/crates.io-index" +checksum = "84ce5b6108f8e154604bd4eb76a2f726066c3464d5a552a4229262a18c9bb471" dependencies = [ - "byte-tools 0.3.1 (registry+https://github.com/rust-lang/crates.io-index)", - "byteorder 1.3.4 (registry+https://github.com/rust-lang/crates.io-index)", - "crypto-mac 0.8.0 (registry+https://github.com/rust-lang/crates.io-index)", - "digest 0.9.0 (registry+https://github.com/rust-lang/crates.io-index)", - "opaque-debug 0.2.3 (registry+https://github.com/rust-lang/crates.io-index)", + "byte-tools", + "byteorder", + "crypto-mac 0.8.0", + "digest 0.9.0", + "opaque-debug 0.2.3", ] [[package]] name = "blake2b_simd" version = "0.5.10" source = "registry+https://github.com/rust-lang/crates.io-index" +checksum = "d8fb2d74254a3a0b5cac33ac9f8ed0e44aa50378d9dbb2e5d83bd21ed1dc2c8a" dependencies = [ - "arrayref 0.3.6 (registry+https://github.com/rust-lang/crates.io-index)", - "arrayvec 0.5.1 (registry+https://github.com/rust-lang/crates.io-index)", - "constant_time_eq 0.1.5 (registry+https://github.com/rust-lang/crates.io-index)", + "arrayref", + "arrayvec", + "constant_time_eq", ] [[package]] name = "blake2s_simd" version = "0.5.10" source = "registry+https://github.com/rust-lang/crates.io-index" +checksum = "ab9e07352b829279624ceb7c64adb4f585dacdb81d35cafae81139ccd617cf44" dependencies = [ - "arrayref 0.3.6 (registry+https://github.com/rust-lang/crates.io-index)", - "arrayvec 0.5.1 (registry+https://github.com/rust-lang/crates.io-index)", - "constant_time_eq 0.1.5 (registry+https://github.com/rust-lang/crates.io-index)", + "arrayref", + "arrayvec", + "constant_time_eq", ] [[package]] name = "block-buffer" version = "0.7.3" source = "registry+https://github.com/rust-lang/crates.io-index" +checksum = "c0940dc441f31689269e10ac70eb1002a3a1d3ad1390e030043662eb7fe4688b" dependencies = [ - "block-padding 0.1.5 (registry+https://github.com/rust-lang/crates.io-index)", - "byte-tools 0.3.1 (registry+https://github.com/rust-lang/crates.io-index)", - "byteorder 1.3.4 (registry+https://github.com/rust-lang/crates.io-index)", - "generic-array 0.12.3 (registry+https://github.com/rust-lang/crates.io-index)", + "block-padding 0.1.5", + "byte-tools", + "byteorder", + "generic-array 0.12.3", ] [[package]] name = "block-buffer" version = "0.9.0" source = "registry+https://github.com/rust-lang/crates.io-index" +checksum = "4152116fd6e9dadb291ae18fc1ec3575ed6d84c29642d97890f4b4a3417297e4" dependencies = [ - "block-padding 0.2.1 (registry+https://github.com/rust-lang/crates.io-index)", - "generic-array 0.14.4 (registry+https://github.com/rust-lang/crates.io-index)", + "block-padding 0.2.1", + "generic-array 0.14.4", ] [[package]] name = "block-cipher" version = "0.7.1" source = "registry+https://github.com/rust-lang/crates.io-index" +checksum = "fa136449e765dc7faa244561ccae839c394048667929af599b5d931ebe7b7f10" dependencies = [ - "generic-array 0.14.4 (registry+https://github.com/rust-lang/crates.io-index)", + "generic-array 0.14.4", ] [[package]] name = "block-padding" version = "0.1.5" source = "registry+https://github.com/rust-lang/crates.io-index" +checksum = "fa79dedbb091f449f1f39e53edf88d5dbe95f895dae6135a8d7b881fb5af73f5" dependencies = [ - "byte-tools 0.3.1 (registry+https://github.com/rust-lang/crates.io-index)", + "byte-tools", ] [[package]] name = "block-padding" version = "0.2.1" source = "registry+https://github.com/rust-lang/crates.io-index" +checksum = "8d696c370c750c948ada61c69a0ee2cbbb9c50b1019ddb86d9317157a99c2cae" [[package]] name = "bls" version = "0.2.0" dependencies = [ - "arbitrary 0.4.6 (registry+https://github.com/rust-lang/crates.io-index)", - "blst 0.1.1 (git+https://github.com/sigp/blst.git?rev=284f7059642851c760a09fb1708bcb59c7ca323c)", - "eth2_hashing 0.1.1", - "eth2_ssz 0.1.2", - "ethereum-types 0.9.2 (registry+https://github.com/rust-lang/crates.io-index)", - "hex 0.3.2 (registry+https://github.com/rust-lang/crates.io-index)", - "milagro_bls 1.1.0 (git+https://github.com/sigp/milagro_bls?branch=paulh)", - "rand 0.7.3 (registry+https://github.com/rust-lang/crates.io-index)", - "serde 1.0.116 (registry+https://github.com/rust-lang/crates.io-index)", - "serde_derive 1.0.116 (registry+https://github.com/rust-lang/crates.io-index)", - "serde_hex 0.2.0", - "tree_hash 0.1.1", - "zeroize 1.1.1 (registry+https://github.com/rust-lang/crates.io-index)", + "arbitrary", + "blst", + "eth2_hashing", + "eth2_ssz", + "ethereum-types", + "hex 0.3.2", + "milagro_bls", + "rand 0.7.3", + "serde", + "serde_derive", + "serde_utils", + "tree_hash", + "zeroize", ] [[package]] @@ -488,1993 +522,2276 @@ name = "blst" version = "0.1.1" source = "git+https://github.com/sigp/blst.git?rev=284f7059642851c760a09fb1708bcb59c7ca323c#284f7059642851c760a09fb1708bcb59c7ca323c" dependencies = [ - "cc 1.0.41 (registry+https://github.com/rust-lang/crates.io-index)", - "glob 0.3.0 (registry+https://github.com/rust-lang/crates.io-index)", - "threadpool 1.8.1 (registry+https://github.com/rust-lang/crates.io-index)", + "cc", + "glob", + "threadpool", ] [[package]] name = "boot_node" version = "0.2.12" dependencies = [ - "beacon_node 0.2.12", - "clap 2.33.3 (registry+https://github.com/rust-lang/crates.io-index)", - "discv5 0.1.0-alpha.11 (registry+https://github.com/rust-lang/crates.io-index)", - "eth2_libp2p 0.2.0", - "futures 0.3.5 (registry+https://github.com/rust-lang/crates.io-index)", - "log 0.4.11 (registry+https://github.com/rust-lang/crates.io-index)", - "logging 0.2.0", - "slog 2.5.2 (registry+https://github.com/rust-lang/crates.io-index)", - "slog-async 2.5.0 (registry+https://github.com/rust-lang/crates.io-index)", - "slog-scope 4.3.0 (registry+https://github.com/rust-lang/crates.io-index)", - "slog-stdlog 4.0.0 (registry+https://github.com/rust-lang/crates.io-index)", - "slog-term 2.6.0 (registry+https://github.com/rust-lang/crates.io-index)", - "sloggers 1.0.1 (registry+https://github.com/rust-lang/crates.io-index)", - "tokio 0.2.22 (registry+https://github.com/rust-lang/crates.io-index)", + "beacon_node", + "clap", + "discv5", + "eth2_libp2p", + "futures 0.3.5", + "log 0.4.11", + "logging", + "slog", + "slog-async", + "slog-scope", + "slog-stdlog", + "slog-term", + "sloggers", + "tokio 0.2.22", ] [[package]] name = "bs58" version = "0.3.1" source = "registry+https://github.com/rust-lang/crates.io-index" +checksum = "476e9cd489f9e121e02ffa6014a8ef220ecb15c05ed23fc34cca13925dc283fb" [[package]] name = "bstr" version = "0.2.13" source = "registry+https://github.com/rust-lang/crates.io-index" +checksum = "31accafdb70df7871592c058eca3985b71104e15ac32f64706022c58867da931" dependencies = [ - "lazy_static 1.4.0 (registry+https://github.com/rust-lang/crates.io-index)", - "memchr 2.3.3 (registry+https://github.com/rust-lang/crates.io-index)", - "regex-automata 0.1.9 (registry+https://github.com/rust-lang/crates.io-index)", - "serde 1.0.116 (registry+https://github.com/rust-lang/crates.io-index)", + "lazy_static", + "memchr", + "regex-automata", + "serde", +] + +[[package]] +name = "buf_redux" +version = "0.8.4" +source = "registry+https://github.com/rust-lang/crates.io-index" +checksum = "b953a6887648bb07a535631f2bc00fbdb2a2216f135552cb3f534ed136b9c07f" +dependencies = [ + "memchr", + "safemem", ] [[package]] name = "bumpalo" version = "3.4.0" source = "registry+https://github.com/rust-lang/crates.io-index" +checksum = "2e8c087f005730276d1096a652e92a8bacee2e2472bcc9715a74d2bec38b5820" [[package]] name = "bus" version = "2.2.3" source = "registry+https://github.com/rust-lang/crates.io-index" +checksum = "f1e66e1779f5b1440f1a58220ba3b3ded4427175f0a9fb8d7066521f8b4e8f2b" dependencies = [ - "atomic-option 0.1.2 (registry+https://github.com/rust-lang/crates.io-index)", - "crossbeam-channel 0.4.4 (registry+https://github.com/rust-lang/crates.io-index)", - "num_cpus 1.13.0 (registry+https://github.com/rust-lang/crates.io-index)", - "parking_lot_core 0.7.2 (registry+https://github.com/rust-lang/crates.io-index)", + "atomic-option", + "crossbeam-channel", + "num_cpus", + "parking_lot_core 0.7.2", ] [[package]] name = "byte-slice-cast" version = "0.3.5" source = "registry+https://github.com/rust-lang/crates.io-index" +checksum = "b0a5e3906bcbf133e33c1d4d95afc664ad37fbdb9f6568d8043e7ea8c27d93d3" [[package]] name = "byte-tools" version = "0.3.1" source = "registry+https://github.com/rust-lang/crates.io-index" +checksum = "e3b5ca7a04898ad4bcd41c90c5285445ff5b791899bb1b0abdd2a2aa791211d7" [[package]] name = "byteorder" version = "1.3.4" source = "registry+https://github.com/rust-lang/crates.io-index" +checksum = "08c48aae112d48ed9f069b33538ea9e3e90aa263cfa3d1c24309612b1f7472de" [[package]] name = "bytes" version = "0.4.12" source = "registry+https://github.com/rust-lang/crates.io-index" +checksum = "206fdffcfa2df7cbe15601ef46c813fce0965eb3286db6b56c583b814b51c81c" dependencies = [ - "byteorder 1.3.4 (registry+https://github.com/rust-lang/crates.io-index)", - "either 1.6.1 (registry+https://github.com/rust-lang/crates.io-index)", - "iovec 0.1.4 (registry+https://github.com/rust-lang/crates.io-index)", + "byteorder", + "either", + "iovec", ] [[package]] name = "bytes" version = "0.5.6" source = "registry+https://github.com/rust-lang/crates.io-index" +checksum = "0e4cec68f03f32e44924783795810fa50a7035d8c8ebe78580ad7e6c703fba38" [[package]] name = "bzip2" version = "0.3.3" source = "registry+https://github.com/rust-lang/crates.io-index" +checksum = "42b7c3cbf0fa9c1b82308d57191728ca0256cb821220f4e2fd410a72ade26e3b" dependencies = [ - "bzip2-sys 0.1.9+1.0.8 (registry+https://github.com/rust-lang/crates.io-index)", - "libc 0.2.77 (registry+https://github.com/rust-lang/crates.io-index)", + "bzip2-sys", + "libc", ] [[package]] name = "bzip2-sys" version = "0.1.9+1.0.8" source = "registry+https://github.com/rust-lang/crates.io-index" +checksum = "ad3b39a260062fca31f7b0b12f207e8f2590a67d32ec7d59c20484b07ea7285e" dependencies = [ - "cc 1.0.41 (registry+https://github.com/rust-lang/crates.io-index)", - "libc 0.2.77 (registry+https://github.com/rust-lang/crates.io-index)", - "pkg-config 0.3.18 (registry+https://github.com/rust-lang/crates.io-index)", + "cc", + "libc", + "pkg-config", ] [[package]] name = "c_linked_list" version = "1.1.1" source = "registry+https://github.com/rust-lang/crates.io-index" +checksum = "4964518bd3b4a8190e832886cdc0da9794f12e8e6c1613a9e90ff331c4c8724b" [[package]] name = "cached_tree_hash" version = "0.1.0" dependencies = [ - "eth2_hashing 0.1.1", - "eth2_ssz 0.1.2", - "eth2_ssz_derive 0.1.0", - "eth2_ssz_types 0.2.0", - "ethereum-types 0.9.2 (registry+https://github.com/rust-lang/crates.io-index)", - "quickcheck 0.9.2 (registry+https://github.com/rust-lang/crates.io-index)", - "quickcheck_macros 0.9.1 (registry+https://github.com/rust-lang/crates.io-index)", - "smallvec 1.4.2 (registry+https://github.com/rust-lang/crates.io-index)", - "tree_hash 0.1.1", + "eth2_hashing", + "eth2_ssz", + "eth2_ssz_derive", + "eth2_ssz_types", + "ethereum-types", + "quickcheck", + "quickcheck_macros", + "smallvec 1.4.2", + "tree_hash", ] [[package]] name = "cast" version = "0.2.3" source = "registry+https://github.com/rust-lang/crates.io-index" +checksum = "4b9434b9a5aa1450faa3f9cb14ea0e8c53bb5d2b3c1bfd1ab4fc03e9f33fbfb0" dependencies = [ - "rustc_version 0.2.3 (registry+https://github.com/rust-lang/crates.io-index)", + "rustc_version", ] [[package]] name = "cc" version = "1.0.41" source = "registry+https://github.com/rust-lang/crates.io-index" +checksum = "8dae9c4b8fedcae85592ba623c4fd08cfdab3e3b72d6df780c6ead964a69bfff" [[package]] name = "cfg-if" version = "0.1.10" source = "registry+https://github.com/rust-lang/crates.io-index" +checksum = "4785bdd1c96b2a846b2bd7cc02e86b6b3dbf14e7e53446c4f54c92a361040822" [[package]] name = "chacha20" version = "0.4.3" source = "registry+https://github.com/rust-lang/crates.io-index" +checksum = "086c0f07ac275808b7bf9a39f2fd013aae1498be83632814c8c4e0bd53f2dc58" dependencies = [ - "stream-cipher 0.4.1 (registry+https://github.com/rust-lang/crates.io-index)", - "zeroize 1.1.1 (registry+https://github.com/rust-lang/crates.io-index)", + "stream-cipher", + "zeroize", ] [[package]] name = "chacha20poly1305" version = "0.5.1" source = "registry+https://github.com/rust-lang/crates.io-index" +checksum = "18b0c90556d8e3fec7cf18d84a2f53d27b21288f2fe481b830fadcf809e48205" dependencies = [ - "aead 0.3.2 (registry+https://github.com/rust-lang/crates.io-index)", - "chacha20 0.4.3 (registry+https://github.com/rust-lang/crates.io-index)", - "poly1305 0.6.0 (registry+https://github.com/rust-lang/crates.io-index)", - "stream-cipher 0.4.1 (registry+https://github.com/rust-lang/crates.io-index)", - "zeroize 1.1.1 (registry+https://github.com/rust-lang/crates.io-index)", + "aead", + "chacha20", + "poly1305", + "stream-cipher", + "zeroize", ] [[package]] name = "chrono" -version = "0.4.18" +version = "0.4.17" source = "registry+https://github.com/rust-lang/crates.io-index" +checksum = "7b05acab8a90ff05c15f407779397ff10ed4049bbe086d47cd7c95817207ad81" dependencies = [ - "libc 0.2.77 (registry+https://github.com/rust-lang/crates.io-index)", - "num-integer 0.1.43 (registry+https://github.com/rust-lang/crates.io-index)", - "num-traits 0.2.12 (registry+https://github.com/rust-lang/crates.io-index)", - "time 0.1.44 (registry+https://github.com/rust-lang/crates.io-index)", - "winapi 0.3.9 (registry+https://github.com/rust-lang/crates.io-index)", + "libc", + "num-integer", + "num-traits", + "time 0.1.44", + "winapi 0.3.9", ] [[package]] name = "clap" version = "2.33.3" source = "registry+https://github.com/rust-lang/crates.io-index" +checksum = "37e58ac78573c40708d45522f0d80fa2f01cc4f9b4e2bf749807255454312002" dependencies = [ - "ansi_term 0.11.0 (registry+https://github.com/rust-lang/crates.io-index)", - "atty 0.2.14 (registry+https://github.com/rust-lang/crates.io-index)", - "bitflags 1.2.1 (registry+https://github.com/rust-lang/crates.io-index)", - "strsim 0.8.0 (registry+https://github.com/rust-lang/crates.io-index)", - "textwrap 0.11.0 (registry+https://github.com/rust-lang/crates.io-index)", - "unicode-width 0.1.8 (registry+https://github.com/rust-lang/crates.io-index)", - "vec_map 0.8.2 (registry+https://github.com/rust-lang/crates.io-index)", + "ansi_term", + "atty", + "bitflags 1.2.1", + "strsim", + "textwrap", + "unicode-width", + "vec_map", ] [[package]] name = "clap_utils" version = "0.1.0" dependencies = [ - "clap 2.33.3 (registry+https://github.com/rust-lang/crates.io-index)", - "dirs 2.0.2 (registry+https://github.com/rust-lang/crates.io-index)", - "eth2_ssz 0.1.2", - "eth2_testnet_config 0.2.0", - "hex 0.4.2 (registry+https://github.com/rust-lang/crates.io-index)", - "types 0.2.0", + "clap", + "dirs", + "eth2_ssz", + "eth2_testnet_config", + "hex 0.4.2", + "types", ] [[package]] name = "client" version = "0.2.0" dependencies = [ - "beacon_chain 0.2.0", - "bus 2.2.3 (registry+https://github.com/rust-lang/crates.io-index)", - "directory 0.1.0", - "dirs 2.0.2 (registry+https://github.com/rust-lang/crates.io-index)", - "environment 0.1.2", - "error-chain 0.12.4 (registry+https://github.com/rust-lang/crates.io-index)", - "eth1 0.2.0", - "eth2_config 0.2.0", - "eth2_libp2p 0.2.0", - "eth2_ssz 0.1.2", - "futures 0.3.5 (registry+https://github.com/rust-lang/crates.io-index)", - "genesis 0.2.0", - "lazy_static 1.4.0 (registry+https://github.com/rust-lang/crates.io-index)", - "lighthouse_metrics 0.2.0", - "network 0.2.0", - "parking_lot 0.11.0 (registry+https://github.com/rust-lang/crates.io-index)", - "prometheus 0.9.0 (registry+https://github.com/rust-lang/crates.io-index)", - "reqwest 0.10.8 (registry+https://github.com/rust-lang/crates.io-index)", - "rest_api 0.2.0", - "serde 1.0.116 (registry+https://github.com/rust-lang/crates.io-index)", - "serde_derive 1.0.116 (registry+https://github.com/rust-lang/crates.io-index)", - "serde_yaml 0.8.13 (registry+https://github.com/rust-lang/crates.io-index)", - "slog 2.5.2 (registry+https://github.com/rust-lang/crates.io-index)", - "slog-async 2.5.0 (registry+https://github.com/rust-lang/crates.io-index)", - "sloggers 1.0.1 (registry+https://github.com/rust-lang/crates.io-index)", - "slot_clock 0.2.0", - "store 0.2.0", - "time 0.2.22 (registry+https://github.com/rust-lang/crates.io-index)", - "timer 0.2.0", - "tokio 0.2.22 (registry+https://github.com/rust-lang/crates.io-index)", - "toml 0.5.6 (registry+https://github.com/rust-lang/crates.io-index)", - "tree_hash 0.1.1", - "types 0.2.0", - "url 2.1.1 (registry+https://github.com/rust-lang/crates.io-index)", - "websocket_server 0.2.0", + "beacon_chain", + "bus", + "directory", + "dirs", + "environment", + "error-chain", + "eth1", + "eth2_config", + "eth2_libp2p", + "eth2_ssz", + "futures 0.3.5", + "genesis", + "http_api", + "http_metrics", + "lazy_static", + "lighthouse_metrics", + "network", + "parking_lot 0.11.0", + "prometheus", + "reqwest", + "serde", + "serde_derive", + "serde_yaml", + "slog", + "slog-async", + "sloggers", + "slot_clock", + "store", + "time 0.2.22", + "timer", + "tokio 0.2.22", + "toml", + "tree_hash", + "types", + "url 2.1.1", + "websocket_server", ] [[package]] name = "cloudabi" version = "0.0.3" source = "registry+https://github.com/rust-lang/crates.io-index" +checksum = "ddfc5b9aa5d4507acaf872de71051dfd0e309860e88966e1051e462a077aac4f" dependencies = [ - "bitflags 1.2.1 (registry+https://github.com/rust-lang/crates.io-index)", + "bitflags 1.2.1", ] [[package]] name = "cloudabi" version = "0.1.0" source = "registry+https://github.com/rust-lang/crates.io-index" +checksum = "4344512281c643ae7638bbabc3af17a11307803ec8f0fcad9fae512a8bf36467" dependencies = [ - "bitflags 1.2.1 (registry+https://github.com/rust-lang/crates.io-index)", + "bitflags 1.2.1", ] [[package]] name = "cmake" version = "0.1.44" source = "registry+https://github.com/rust-lang/crates.io-index" +checksum = "0e56268c17a6248366d66d4a47a3381369d068cce8409bb1716ed77ea32163bb" dependencies = [ - "cc 1.0.41 (registry+https://github.com/rust-lang/crates.io-index)", + "cc", ] [[package]] name = "colored" version = "1.9.3" source = "registry+https://github.com/rust-lang/crates.io-index" +checksum = "f4ffc801dacf156c5854b9df4f425a626539c3a6ef7893cc0c5084a23f0b6c59" dependencies = [ - "atty 0.2.14 (registry+https://github.com/rust-lang/crates.io-index)", - "lazy_static 1.4.0 (registry+https://github.com/rust-lang/crates.io-index)", - "winapi 0.3.9 (registry+https://github.com/rust-lang/crates.io-index)", + "atty", + "lazy_static", + "winapi 0.3.9", ] [[package]] name = "compare_fields" version = "0.2.0" dependencies = [ - "compare_fields_derive 0.2.0", + "compare_fields_derive", ] [[package]] name = "compare_fields_derive" version = "0.2.0" dependencies = [ - "quote 1.0.7 (registry+https://github.com/rust-lang/crates.io-index)", - "syn 1.0.42 (registry+https://github.com/rust-lang/crates.io-index)", + "quote", + "syn", ] [[package]] name = "console_error_panic_hook" version = "0.1.6" source = "registry+https://github.com/rust-lang/crates.io-index" +checksum = "b8d976903543e0c48546a91908f21588a680a8c8f984df9a5d69feccb2b2a211" dependencies = [ - "cfg-if 0.1.10 (registry+https://github.com/rust-lang/crates.io-index)", - "wasm-bindgen 0.2.68 (registry+https://github.com/rust-lang/crates.io-index)", + "cfg-if", + "wasm-bindgen", ] [[package]] name = "const-random" version = "0.1.8" source = "registry+https://github.com/rust-lang/crates.io-index" +checksum = "2f1af9ac737b2dd2d577701e59fd09ba34822f6f2ebdb30a7647405d9e55e16a" dependencies = [ - "const-random-macro 0.1.8 (registry+https://github.com/rust-lang/crates.io-index)", - "proc-macro-hack 0.5.18 (registry+https://github.com/rust-lang/crates.io-index)", + "const-random-macro", + "proc-macro-hack", ] [[package]] name = "const-random-macro" version = "0.1.8" source = "registry+https://github.com/rust-lang/crates.io-index" +checksum = "25e4c606eb459dd29f7c57b2e0879f2b6f14ee130918c2b78ccb58a9624e6c7a" dependencies = [ - "getrandom 0.1.15 (registry+https://github.com/rust-lang/crates.io-index)", - "proc-macro-hack 0.5.18 (registry+https://github.com/rust-lang/crates.io-index)", + "getrandom", + "proc-macro-hack", ] [[package]] name = "const_fn" version = "0.4.2" source = "registry+https://github.com/rust-lang/crates.io-index" +checksum = "ce90df4c658c62f12d78f7508cf92f9173e5184a539c10bfe54a3107b3ffd0f2" [[package]] name = "constant_time_eq" version = "0.1.5" source = "registry+https://github.com/rust-lang/crates.io-index" +checksum = "245097e9a4535ee1e3e3931fcfcd55a796a44c643e8596ff6566d68f09b87bbc" [[package]] name = "core-foundation" version = "0.7.0" source = "registry+https://github.com/rust-lang/crates.io-index" +checksum = "57d24c7a13c43e870e37c1556b74555437870a04514f7685f5b354e090567171" dependencies = [ - "core-foundation-sys 0.7.0 (registry+https://github.com/rust-lang/crates.io-index)", - "libc 0.2.77 (registry+https://github.com/rust-lang/crates.io-index)", + "core-foundation-sys", + "libc", ] [[package]] name = "core-foundation-sys" version = "0.7.0" source = "registry+https://github.com/rust-lang/crates.io-index" +checksum = "b3a71ab494c0b5b860bdc8407ae08978052417070c2ced38573a9157ad75b8ac" [[package]] name = "cpuid-bool" version = "0.1.2" source = "registry+https://github.com/rust-lang/crates.io-index" +checksum = "8aebca1129a03dc6dc2b127edd729435bbc4a37e1d5f4d7513165089ceb02634" [[package]] name = "crc32fast" version = "1.2.0" source = "registry+https://github.com/rust-lang/crates.io-index" +checksum = "ba125de2af0df55319f41944744ad91c71113bf74a4646efff39afe1f6842db1" dependencies = [ - "cfg-if 0.1.10 (registry+https://github.com/rust-lang/crates.io-index)", + "cfg-if", ] [[package]] name = "criterion" version = "0.3.3" source = "registry+https://github.com/rust-lang/crates.io-index" -dependencies = [ - "atty 0.2.14 (registry+https://github.com/rust-lang/crates.io-index)", - "cast 0.2.3 (registry+https://github.com/rust-lang/crates.io-index)", - "clap 2.33.3 (registry+https://github.com/rust-lang/crates.io-index)", - "criterion-plot 0.4.3 (registry+https://github.com/rust-lang/crates.io-index)", - "csv 1.1.3 (registry+https://github.com/rust-lang/crates.io-index)", - "itertools 0.9.0 (registry+https://github.com/rust-lang/crates.io-index)", - "lazy_static 1.4.0 (registry+https://github.com/rust-lang/crates.io-index)", - "num-traits 0.2.12 (registry+https://github.com/rust-lang/crates.io-index)", - "oorandom 11.1.2 (registry+https://github.com/rust-lang/crates.io-index)", - "plotters 0.2.15 (registry+https://github.com/rust-lang/crates.io-index)", - "rayon 1.4.0 (registry+https://github.com/rust-lang/crates.io-index)", - "regex 1.3.9 (registry+https://github.com/rust-lang/crates.io-index)", - "serde 1.0.116 (registry+https://github.com/rust-lang/crates.io-index)", - "serde_cbor 0.11.1 (registry+https://github.com/rust-lang/crates.io-index)", - "serde_derive 1.0.116 (registry+https://github.com/rust-lang/crates.io-index)", - "serde_json 1.0.57 (registry+https://github.com/rust-lang/crates.io-index)", - "tinytemplate 1.1.0 (registry+https://github.com/rust-lang/crates.io-index)", - "walkdir 2.3.1 (registry+https://github.com/rust-lang/crates.io-index)", +checksum = "70daa7ceec6cf143990669a04c7df13391d55fb27bd4079d252fca774ba244d8" +dependencies = [ + "atty", + "cast", + "clap", + "criterion-plot", + "csv", + "itertools 0.9.0", + "lazy_static", + "num-traits", + "oorandom", + "plotters", + "rayon", + "regex", + "serde", + "serde_cbor", + "serde_derive", + "serde_json", + "tinytemplate", + "walkdir", ] [[package]] name = "criterion-plot" version = "0.4.3" source = "registry+https://github.com/rust-lang/crates.io-index" +checksum = "e022feadec601fba1649cfa83586381a4ad31c6bf3a9ab7d408118b05dd9889d" dependencies = [ - "cast 0.2.3 (registry+https://github.com/rust-lang/crates.io-index)", - "itertools 0.9.0 (registry+https://github.com/rust-lang/crates.io-index)", + "cast", + "itertools 0.9.0", ] [[package]] name = "crossbeam" version = "0.7.3" source = "registry+https://github.com/rust-lang/crates.io-index" +checksum = "69323bff1fb41c635347b8ead484a5ca6c3f11914d784170b158d8449ab07f8e" dependencies = [ - "cfg-if 0.1.10 (registry+https://github.com/rust-lang/crates.io-index)", - "crossbeam-channel 0.4.4 (registry+https://github.com/rust-lang/crates.io-index)", - "crossbeam-deque 0.7.3 (registry+https://github.com/rust-lang/crates.io-index)", - "crossbeam-epoch 0.8.2 (registry+https://github.com/rust-lang/crates.io-index)", - "crossbeam-queue 0.2.3 (registry+https://github.com/rust-lang/crates.io-index)", - "crossbeam-utils 0.7.2 (registry+https://github.com/rust-lang/crates.io-index)", + "cfg-if", + "crossbeam-channel", + "crossbeam-deque", + "crossbeam-epoch", + "crossbeam-queue", + "crossbeam-utils", ] [[package]] name = "crossbeam-channel" version = "0.4.4" source = "registry+https://github.com/rust-lang/crates.io-index" +checksum = "b153fe7cbef478c567df0f972e02e6d736db11affe43dfc9c56a9374d1adfb87" dependencies = [ - "crossbeam-utils 0.7.2 (registry+https://github.com/rust-lang/crates.io-index)", - "maybe-uninit 2.0.0 (registry+https://github.com/rust-lang/crates.io-index)", + "crossbeam-utils", + "maybe-uninit", ] [[package]] name = "crossbeam-deque" version = "0.7.3" source = "registry+https://github.com/rust-lang/crates.io-index" +checksum = "9f02af974daeee82218205558e51ec8768b48cf524bd01d550abe5573a608285" dependencies = [ - "crossbeam-epoch 0.8.2 (registry+https://github.com/rust-lang/crates.io-index)", - "crossbeam-utils 0.7.2 (registry+https://github.com/rust-lang/crates.io-index)", - "maybe-uninit 2.0.0 (registry+https://github.com/rust-lang/crates.io-index)", + "crossbeam-epoch", + "crossbeam-utils", + "maybe-uninit", ] [[package]] name = "crossbeam-epoch" version = "0.8.2" source = "registry+https://github.com/rust-lang/crates.io-index" +checksum = "058ed274caafc1f60c4997b5fc07bf7dc7cca454af7c6e81edffe5f33f70dace" dependencies = [ - "autocfg 1.0.1 (registry+https://github.com/rust-lang/crates.io-index)", - "cfg-if 0.1.10 (registry+https://github.com/rust-lang/crates.io-index)", - "crossbeam-utils 0.7.2 (registry+https://github.com/rust-lang/crates.io-index)", - "lazy_static 1.4.0 (registry+https://github.com/rust-lang/crates.io-index)", - "maybe-uninit 2.0.0 (registry+https://github.com/rust-lang/crates.io-index)", - "memoffset 0.5.6 (registry+https://github.com/rust-lang/crates.io-index)", - "scopeguard 1.1.0 (registry+https://github.com/rust-lang/crates.io-index)", + "autocfg 1.0.1", + "cfg-if", + "crossbeam-utils", + "lazy_static", + "maybe-uninit", + "memoffset", + "scopeguard", ] [[package]] name = "crossbeam-queue" version = "0.2.3" source = "registry+https://github.com/rust-lang/crates.io-index" +checksum = "774ba60a54c213d409d5353bda12d49cd68d14e45036a285234c8d6f91f92570" dependencies = [ - "cfg-if 0.1.10 (registry+https://github.com/rust-lang/crates.io-index)", - "crossbeam-utils 0.7.2 (registry+https://github.com/rust-lang/crates.io-index)", - "maybe-uninit 2.0.0 (registry+https://github.com/rust-lang/crates.io-index)", + "cfg-if", + "crossbeam-utils", + "maybe-uninit", ] [[package]] name = "crossbeam-utils" version = "0.7.2" source = "registry+https://github.com/rust-lang/crates.io-index" +checksum = "c3c7c73a2d1e9fc0886a08b93e98eb643461230d5f1925e4036204d5f2e261a8" dependencies = [ - "autocfg 1.0.1 (registry+https://github.com/rust-lang/crates.io-index)", - "cfg-if 0.1.10 (registry+https://github.com/rust-lang/crates.io-index)", - "lazy_static 1.4.0 (registry+https://github.com/rust-lang/crates.io-index)", + "autocfg 1.0.1", + "cfg-if", + "lazy_static", ] [[package]] name = "crunchy" version = "0.2.2" source = "registry+https://github.com/rust-lang/crates.io-index" +checksum = "7a81dae078cea95a014a339291cec439d2f232ebe854a9d672b796c6afafa9b7" [[package]] name = "crypto-mac" version = "0.7.0" source = "registry+https://github.com/rust-lang/crates.io-index" +checksum = "4434400df11d95d556bac068ddfedd482915eb18fe8bea89bc80b6e4b1c179e5" dependencies = [ - "generic-array 0.12.3 (registry+https://github.com/rust-lang/crates.io-index)", - "subtle 1.0.0 (registry+https://github.com/rust-lang/crates.io-index)", + "generic-array 0.12.3", + "subtle 1.0.0", ] [[package]] name = "crypto-mac" version = "0.8.0" source = "registry+https://github.com/rust-lang/crates.io-index" +checksum = "b584a330336237c1eecd3e94266efb216c56ed91225d634cb2991c5f3fd1aeab" dependencies = [ - "generic-array 0.14.4 (registry+https://github.com/rust-lang/crates.io-index)", - "subtle 2.3.0 (registry+https://github.com/rust-lang/crates.io-index)", + "generic-array 0.14.4", + "subtle 2.3.0", ] [[package]] name = "csv" version = "1.1.3" source = "registry+https://github.com/rust-lang/crates.io-index" +checksum = "00affe7f6ab566df61b4be3ce8cf16bc2576bca0963ceb0955e45d514bf9a279" dependencies = [ - "bstr 0.2.13 (registry+https://github.com/rust-lang/crates.io-index)", - "csv-core 0.1.10 (registry+https://github.com/rust-lang/crates.io-index)", - "itoa 0.4.6 (registry+https://github.com/rust-lang/crates.io-index)", - "ryu 1.0.5 (registry+https://github.com/rust-lang/crates.io-index)", - "serde 1.0.116 (registry+https://github.com/rust-lang/crates.io-index)", + "bstr", + "csv-core", + "itoa", + "ryu", + "serde", ] [[package]] name = "csv-core" version = "0.1.10" source = "registry+https://github.com/rust-lang/crates.io-index" +checksum = "2b2466559f260f48ad25fe6317b3c8dac77b5bdb5763ac7d9d6103530663bc90" dependencies = [ - "memchr 2.3.3 (registry+https://github.com/rust-lang/crates.io-index)", + "memchr", ] [[package]] name = "ctr" version = "0.4.0" source = "registry+https://github.com/rust-lang/crates.io-index" +checksum = "a3592740fd55aaf61dd72df96756bd0d11e6037b89dcf30ae2e1895b267692be" dependencies = [ - "stream-cipher 0.4.1 (registry+https://github.com/rust-lang/crates.io-index)", + "stream-cipher", ] [[package]] name = "ctrlc" version = "3.1.6" source = "registry+https://github.com/rust-lang/crates.io-index" +checksum = "d0b676fa23f995faf587496dcd1c80fead847ed58d2da52ac1caca9a72790dd2" dependencies = [ - "nix 0.17.0 (registry+https://github.com/rust-lang/crates.io-index)", - "winapi 0.3.9 (registry+https://github.com/rust-lang/crates.io-index)", + "nix", + "winapi 0.3.9", ] [[package]] name = "curve25519-dalek" version = "2.1.0" source = "registry+https://github.com/rust-lang/crates.io-index" +checksum = "5d85653f070353a16313d0046f173f70d1aadd5b42600a14de626f0dfb3473a5" dependencies = [ - "byteorder 1.3.4 (registry+https://github.com/rust-lang/crates.io-index)", - "digest 0.8.1 (registry+https://github.com/rust-lang/crates.io-index)", - "rand_core 0.5.1 (registry+https://github.com/rust-lang/crates.io-index)", - "subtle 2.3.0 (registry+https://github.com/rust-lang/crates.io-index)", - "zeroize 1.1.1 (registry+https://github.com/rust-lang/crates.io-index)", + "byteorder", + "digest 0.8.1", + "rand_core 0.5.1", + "subtle 2.3.0", + "zeroize", ] [[package]] name = "curve25519-dalek" version = "3.0.0" source = "registry+https://github.com/rust-lang/crates.io-index" +checksum = "c8492de420e9e60bc9a1d66e2dbb91825390b738a388606600663fc529b4b307" dependencies = [ - "byteorder 1.3.4 (registry+https://github.com/rust-lang/crates.io-index)", - "digest 0.9.0 (registry+https://github.com/rust-lang/crates.io-index)", - "rand_core 0.5.1 (registry+https://github.com/rust-lang/crates.io-index)", - "subtle 2.3.0 (registry+https://github.com/rust-lang/crates.io-index)", - "zeroize 1.1.1 (registry+https://github.com/rust-lang/crates.io-index)", + "byteorder", + "digest 0.9.0", + "rand_core 0.5.1", + "subtle 2.3.0", + "zeroize", ] [[package]] name = "darwin-libproc" version = "0.1.2" source = "registry+https://github.com/rust-lang/crates.io-index" +checksum = "9fb90051930c9a0f09e585762152048e23ac74d20c10590ef7cf01c0343c3046" dependencies = [ - "darwin-libproc-sys 0.1.2 (registry+https://github.com/rust-lang/crates.io-index)", - "libc 0.2.77 (registry+https://github.com/rust-lang/crates.io-index)", - "memchr 2.3.3 (registry+https://github.com/rust-lang/crates.io-index)", + "darwin-libproc-sys", + "libc", + "memchr", ] [[package]] name = "darwin-libproc-sys" version = "0.1.2" source = "registry+https://github.com/rust-lang/crates.io-index" +checksum = "57cebb5bde66eecdd30ddc4b9cd208238b15db4982ccc72db59d699ea10867c1" dependencies = [ - "libc 0.2.77 (registry+https://github.com/rust-lang/crates.io-index)", + "libc", ] [[package]] name = "data-encoding" version = "2.3.0" source = "registry+https://github.com/rust-lang/crates.io-index" +checksum = "d4d0e2d24e5ee3b23a01de38eefdcd978907890701f08ffffd4cb457ca4ee8d6" [[package]] name = "db-key" version = "0.0.5" source = "registry+https://github.com/rust-lang/crates.io-index" +checksum = "b72465f46d518f6015d9cf07f7f3013a95dd6b9c2747c3d65ae0cce43929d14f" [[package]] name = "deposit_contract" version = "0.2.0" dependencies = [ - "eth2_ssz 0.1.2", - "ethabi 12.0.0 (registry+https://github.com/rust-lang/crates.io-index)", - "hex 0.4.2 (registry+https://github.com/rust-lang/crates.io-index)", - "reqwest 0.10.8 (registry+https://github.com/rust-lang/crates.io-index)", - "serde_json 1.0.57 (registry+https://github.com/rust-lang/crates.io-index)", - "sha2 0.9.1 (registry+https://github.com/rust-lang/crates.io-index)", - "tree_hash 0.1.1", - "types 0.2.0", + "eth2_ssz", + "ethabi", + "hex 0.4.2", + "reqwest", + "serde_json", + "sha2 0.9.1", + "tree_hash", + "types", ] [[package]] name = "derivative" version = "2.1.1" source = "registry+https://github.com/rust-lang/crates.io-index" +checksum = "cb582b60359da160a9477ee80f15c8d784c477e69c217ef2cdd4169c24ea380f" dependencies = [ - "proc-macro2 1.0.23 (registry+https://github.com/rust-lang/crates.io-index)", - "quote 1.0.7 (registry+https://github.com/rust-lang/crates.io-index)", - "syn 1.0.42 (registry+https://github.com/rust-lang/crates.io-index)", + "proc-macro2", + "quote", + "syn", ] [[package]] name = "derive_arbitrary" version = "0.4.6" source = "registry+https://github.com/rust-lang/crates.io-index" +checksum = "d0f7c6c81276b6b8702074defbdb1938933ddf98c7f7e0dca8d9e9214dd6c730" dependencies = [ - "proc-macro2 1.0.23 (registry+https://github.com/rust-lang/crates.io-index)", - "quote 1.0.7 (registry+https://github.com/rust-lang/crates.io-index)", - "syn 1.0.42 (registry+https://github.com/rust-lang/crates.io-index)", + "proc-macro2", + "quote", + "syn", ] [[package]] name = "derive_more" version = "0.99.10" source = "registry+https://github.com/rust-lang/crates.io-index" +checksum = "1dcfabdab475c16a93d669dddfc393027803e347d09663f524447f642fbb84ba" dependencies = [ - "proc-macro2 1.0.23 (registry+https://github.com/rust-lang/crates.io-index)", - "quote 1.0.7 (registry+https://github.com/rust-lang/crates.io-index)", - "syn 1.0.42 (registry+https://github.com/rust-lang/crates.io-index)", + "proc-macro2", + "quote", + "syn", ] [[package]] name = "digest" version = "0.8.1" source = "registry+https://github.com/rust-lang/crates.io-index" +checksum = "f3d0c8c8752312f9713efd397ff63acb9f85585afbf179282e720e7704954dd5" dependencies = [ - "generic-array 0.12.3 (registry+https://github.com/rust-lang/crates.io-index)", + "generic-array 0.12.3", ] [[package]] name = "digest" version = "0.9.0" source = "registry+https://github.com/rust-lang/crates.io-index" +checksum = "d3dd60d1080a57a05ab032377049e0591415d2b31afd7028356dbf3cc6dcb066" dependencies = [ - "generic-array 0.14.4 (registry+https://github.com/rust-lang/crates.io-index)", + "generic-array 0.14.4", ] [[package]] name = "directory" version = "0.1.0" dependencies = [ - "clap 2.33.3 (registry+https://github.com/rust-lang/crates.io-index)", - "clap_utils 0.1.0", - "dirs 2.0.2 (registry+https://github.com/rust-lang/crates.io-index)", - "eth2_testnet_config 0.2.0", + "clap", + "clap_utils", + "dirs", + "eth2_testnet_config", ] [[package]] name = "dirs" version = "2.0.2" source = "registry+https://github.com/rust-lang/crates.io-index" +checksum = "13aea89a5c93364a98e9b37b2fa237effbb694d5cfe01c5b70941f7eb087d5e3" dependencies = [ - "cfg-if 0.1.10 (registry+https://github.com/rust-lang/crates.io-index)", - "dirs-sys 0.3.5 (registry+https://github.com/rust-lang/crates.io-index)", + "cfg-if", + "dirs-sys", ] [[package]] name = "dirs-sys" version = "0.3.5" source = "registry+https://github.com/rust-lang/crates.io-index" +checksum = "8e93d7f5705de3e49895a2b5e0b8855a1c27f080192ae9c32a6432d50741a57a" dependencies = [ - "libc 0.2.77 (registry+https://github.com/rust-lang/crates.io-index)", - "redox_users 0.3.5 (registry+https://github.com/rust-lang/crates.io-index)", - "winapi 0.3.9 (registry+https://github.com/rust-lang/crates.io-index)", + "libc", + "redox_users", + "winapi 0.3.9", ] [[package]] name = "discard" version = "1.0.4" source = "registry+https://github.com/rust-lang/crates.io-index" +checksum = "212d0f5754cb6769937f4501cc0e67f4f4483c8d2c3e1e922ee9edbe4ab4c7c0" [[package]] name = "discv5" version = "0.1.0-alpha.11" source = "registry+https://github.com/rust-lang/crates.io-index" -dependencies = [ - "aes-gcm 0.6.0 (registry+https://github.com/rust-lang/crates.io-index)", - "arrayvec 0.5.1 (registry+https://github.com/rust-lang/crates.io-index)", - "digest 0.8.1 (registry+https://github.com/rust-lang/crates.io-index)", - "enr 0.1.3 (registry+https://github.com/rust-lang/crates.io-index)", - "fnv 1.0.7 (registry+https://github.com/rust-lang/crates.io-index)", - "futures 0.3.5 (registry+https://github.com/rust-lang/crates.io-index)", - "hex 0.4.2 (registry+https://github.com/rust-lang/crates.io-index)", - "hkdf 0.8.0 (registry+https://github.com/rust-lang/crates.io-index)", - "lazy_static 1.4.0 (registry+https://github.com/rust-lang/crates.io-index)", - "libp2p-core 0.22.1 (registry+https://github.com/rust-lang/crates.io-index)", - "libsecp256k1 0.3.5 (registry+https://github.com/rust-lang/crates.io-index)", - "log 0.4.11 (registry+https://github.com/rust-lang/crates.io-index)", - "lru_time_cache 0.10.0 (registry+https://github.com/rust-lang/crates.io-index)", - "multihash 0.11.4 (registry+https://github.com/rust-lang/crates.io-index)", - "parking_lot 0.11.0 (registry+https://github.com/rust-lang/crates.io-index)", - "rand 0.7.3 (registry+https://github.com/rust-lang/crates.io-index)", - "rlp 0.4.5 (registry+https://github.com/rust-lang/crates.io-index)", - "sha2 0.8.2 (registry+https://github.com/rust-lang/crates.io-index)", - "smallvec 1.4.2 (registry+https://github.com/rust-lang/crates.io-index)", - "socket2 0.3.15 (registry+https://github.com/rust-lang/crates.io-index)", - "tokio 0.2.22 (registry+https://github.com/rust-lang/crates.io-index)", - "uint 0.8.5 (registry+https://github.com/rust-lang/crates.io-index)", - "zeroize 1.1.1 (registry+https://github.com/rust-lang/crates.io-index)", -] +checksum = "c68cb1b942aadd3bb3a13620c4d831c0aa49eda988cf8bcccfdfdc7ef69504a7" +dependencies = [ + "aes-gcm", + "arrayvec", + "digest 0.8.1", + "enr", + "fnv", + "futures 0.3.5", + "hex 0.4.2", + "hkdf", + "lazy_static", + "libp2p-core 0.22.1", + "libsecp256k1", + "log 0.4.11", + "lru_time_cache", + "multihash", + "parking_lot 0.11.0", + "rand 0.7.3", + "rlp", + "sha2 0.8.2", + "smallvec 1.4.2", + "socket2", + "tokio 0.2.22", + "uint", + "zeroize", +] + +[[package]] +name = "doc-comment" +version = "0.3.3" +source = "registry+https://github.com/rust-lang/crates.io-index" +checksum = "fea41bba32d969b513997752735605054bc0dfa92b4c56bf1189f2e174be7a10" [[package]] name = "dtoa" version = "0.4.6" source = "registry+https://github.com/rust-lang/crates.io-index" +checksum = "134951f4028bdadb9b84baf4232681efbf277da25144b9b0ad65df75946c422b" [[package]] name = "ed25519" version = "1.0.2" source = "registry+https://github.com/rust-lang/crates.io-index" +checksum = "07dfc993ea376e864fe29a4099a61ca0bb994c6d7745a61bf60ddb3d64e05237" dependencies = [ - "signature 1.2.2 (registry+https://github.com/rust-lang/crates.io-index)", + "signature", ] [[package]] name = "ed25519-dalek" version = "1.0.1" source = "registry+https://github.com/rust-lang/crates.io-index" +checksum = "c762bae6dcaf24c4c84667b8579785430908723d5c889f469d76a41d59cc7a9d" dependencies = [ - "curve25519-dalek 3.0.0 (registry+https://github.com/rust-lang/crates.io-index)", - "ed25519 1.0.2 (registry+https://github.com/rust-lang/crates.io-index)", - "rand 0.7.3 (registry+https://github.com/rust-lang/crates.io-index)", - "serde 1.0.116 (registry+https://github.com/rust-lang/crates.io-index)", - "sha2 0.9.1 (registry+https://github.com/rust-lang/crates.io-index)", - "zeroize 1.1.1 (registry+https://github.com/rust-lang/crates.io-index)", + "curve25519-dalek 3.0.0", + "ed25519", + "rand 0.7.3", + "serde", + "sha2 0.9.1", + "zeroize", ] [[package]] name = "ef_tests" version = "0.2.0" dependencies = [ - "bls 0.2.0", - "cached_tree_hash 0.1.0", - "compare_fields 0.2.0", - "eth2_ssz 0.1.2", - "eth2_ssz_derive 0.1.0", - "ethereum-types 0.9.2 (registry+https://github.com/rust-lang/crates.io-index)", - "hex 0.4.2 (registry+https://github.com/rust-lang/crates.io-index)", - "rayon 1.4.0 (registry+https://github.com/rust-lang/crates.io-index)", - "serde 1.0.116 (registry+https://github.com/rust-lang/crates.io-index)", - "serde_derive 1.0.116 (registry+https://github.com/rust-lang/crates.io-index)", - "serde_repr 0.1.6 (registry+https://github.com/rust-lang/crates.io-index)", - "serde_yaml 0.8.13 (registry+https://github.com/rust-lang/crates.io-index)", - "state_processing 0.2.0", - "swap_or_not_shuffle 0.2.0", - "tree_hash 0.1.1", - "tree_hash_derive 0.2.0", - "types 0.2.0", + "bls", + "cached_tree_hash", + "compare_fields", + "eth2_ssz", + "eth2_ssz_derive", + "ethereum-types", + "hex 0.4.2", + "rayon", + "serde", + "serde_derive", + "serde_repr", + "serde_yaml", + "state_processing", + "swap_or_not_shuffle", + "tree_hash", + "tree_hash_derive", + "types", ] [[package]] name = "either" version = "1.6.1" source = "registry+https://github.com/rust-lang/crates.io-index" +checksum = "e78d4f1cc4ae33bbfc157ed5d5a5ef3bc29227303d595861deb238fcec4e9457" [[package]] name = "encoding_rs" version = "0.8.24" source = "registry+https://github.com/rust-lang/crates.io-index" +checksum = "a51b8cf747471cb9499b6d59e59b0444f4c90eba8968c4e44874e92b5b64ace2" dependencies = [ - "cfg-if 0.1.10 (registry+https://github.com/rust-lang/crates.io-index)", + "cfg-if", ] [[package]] name = "enr" version = "0.1.3" source = "registry+https://github.com/rust-lang/crates.io-index" +checksum = "a3137b4854534673ea350751670c6fe53920394a328ba9ce4d9acabd4f60a586" dependencies = [ - "base64 0.12.3 (registry+https://github.com/rust-lang/crates.io-index)", - "bs58 0.3.1 (registry+https://github.com/rust-lang/crates.io-index)", - "ed25519-dalek 1.0.1 (registry+https://github.com/rust-lang/crates.io-index)", - "hex 0.4.2 (registry+https://github.com/rust-lang/crates.io-index)", - "libsecp256k1 0.3.5 (registry+https://github.com/rust-lang/crates.io-index)", - "log 0.4.11 (registry+https://github.com/rust-lang/crates.io-index)", - "rand 0.7.3 (registry+https://github.com/rust-lang/crates.io-index)", - "rlp 0.4.5 (registry+https://github.com/rust-lang/crates.io-index)", - "serde 1.0.116 (registry+https://github.com/rust-lang/crates.io-index)", - "tiny-keccak 2.0.2 (registry+https://github.com/rust-lang/crates.io-index)", - "zeroize 1.1.1 (registry+https://github.com/rust-lang/crates.io-index)", + "base64 0.12.3", + "bs58", + "ed25519-dalek", + "hex 0.4.2", + "libsecp256k1", + "log 0.4.11", + "rand 0.7.3", + "rlp", + "serde", + "tiny-keccak 2.0.2", + "zeroize", ] [[package]] name = "env_logger" version = "0.7.1" source = "registry+https://github.com/rust-lang/crates.io-index" +checksum = "44533bbbb3bb3c1fa17d9f2e4e38bbbaf8396ba82193c4cb1b6445d711445d36" dependencies = [ - "atty 0.2.14 (registry+https://github.com/rust-lang/crates.io-index)", - "humantime 1.3.0 (registry+https://github.com/rust-lang/crates.io-index)", - "log 0.4.11 (registry+https://github.com/rust-lang/crates.io-index)", - "regex 1.3.9 (registry+https://github.com/rust-lang/crates.io-index)", - "termcolor 1.1.0 (registry+https://github.com/rust-lang/crates.io-index)", + "atty", + "humantime", + "log 0.4.11", + "regex", + "termcolor", ] [[package]] name = "environment" version = "0.1.2" dependencies = [ - "ctrlc 3.1.6 (registry+https://github.com/rust-lang/crates.io-index)", - "discv5 0.1.0-alpha.11 (registry+https://github.com/rust-lang/crates.io-index)", - "eth2_config 0.2.0", - "eth2_testnet_config 0.2.0", - "exit-future 0.2.0 (registry+https://github.com/rust-lang/crates.io-index)", - "futures 0.3.5 (registry+https://github.com/rust-lang/crates.io-index)", - "lazy_static 1.4.0 (registry+https://github.com/rust-lang/crates.io-index)", - "lighthouse_metrics 0.2.0", - "logging 0.2.0", - "parking_lot 0.11.0 (registry+https://github.com/rust-lang/crates.io-index)", - "slog 2.5.2 (registry+https://github.com/rust-lang/crates.io-index)", - "slog-async 2.5.0 (registry+https://github.com/rust-lang/crates.io-index)", - "slog-json 2.3.0 (registry+https://github.com/rust-lang/crates.io-index)", - "slog-term 2.6.0 (registry+https://github.com/rust-lang/crates.io-index)", - "sloggers 1.0.1 (registry+https://github.com/rust-lang/crates.io-index)", - "tokio 0.2.22 (registry+https://github.com/rust-lang/crates.io-index)", - "types 0.2.0", + "ctrlc", + "discv5", + "eth2_config", + "eth2_testnet_config", + "exit-future", + "futures 0.3.5", + "lazy_static", + "lighthouse_metrics", + "logging", + "parking_lot 0.11.0", + "slog", + "slog-async", + "slog-json", + "slog-term", + "sloggers", + "tokio 0.2.22", + "types", ] [[package]] name = "error-chain" version = "0.12.4" source = "registry+https://github.com/rust-lang/crates.io-index" +checksum = "2d2f06b9cac1506ece98fe3231e3cc9c4410ec3d5b1f24ae1c8946f0742cdefc" dependencies = [ - "backtrace 0.3.50 (registry+https://github.com/rust-lang/crates.io-index)", - "version_check 0.9.2 (registry+https://github.com/rust-lang/crates.io-index)", + "backtrace", + "version_check 0.9.2", ] [[package]] name = "eth1" version = "0.2.0" dependencies = [ - "environment 0.1.2", - "eth1_test_rig 0.2.0", - "eth2_hashing 0.1.1", - "eth2_ssz 0.1.2", - "eth2_ssz_derive 0.1.0", - "futures 0.3.5 (registry+https://github.com/rust-lang/crates.io-index)", - "hex 0.4.2 (registry+https://github.com/rust-lang/crates.io-index)", - "lazy_static 1.4.0 (registry+https://github.com/rust-lang/crates.io-index)", - "libflate 1.0.2 (registry+https://github.com/rust-lang/crates.io-index)", - "lighthouse_metrics 0.2.0", - "merkle_proof 0.2.0", - "parking_lot 0.11.0 (registry+https://github.com/rust-lang/crates.io-index)", - "reqwest 0.10.8 (registry+https://github.com/rust-lang/crates.io-index)", - "serde 1.0.116 (registry+https://github.com/rust-lang/crates.io-index)", - "serde_json 1.0.57 (registry+https://github.com/rust-lang/crates.io-index)", - "slog 2.5.2 (registry+https://github.com/rust-lang/crates.io-index)", - "sloggers 1.0.1 (registry+https://github.com/rust-lang/crates.io-index)", - "state_processing 0.2.0", - "tokio 0.2.22 (registry+https://github.com/rust-lang/crates.io-index)", - "toml 0.5.6 (registry+https://github.com/rust-lang/crates.io-index)", - "tree_hash 0.1.1", - "types 0.2.0", - "web3 0.11.0 (registry+https://github.com/rust-lang/crates.io-index)", + "environment", + "eth1_test_rig", + "eth2_hashing", + "eth2_ssz", + "eth2_ssz_derive", + "futures 0.3.5", + "hex 0.4.2", + "lazy_static", + "libflate", + "lighthouse_metrics", + "merkle_proof", + "parking_lot 0.11.0", + "reqwest", + "serde", + "serde_json", + "slog", + "sloggers", + "state_processing", + "tokio 0.2.22", + "toml", + "tree_hash", + "types", + "web3", ] [[package]] name = "eth1_test_rig" version = "0.2.0" dependencies = [ - "deposit_contract 0.2.0", - "futures 0.3.5 (registry+https://github.com/rust-lang/crates.io-index)", - "serde_json 1.0.57 (registry+https://github.com/rust-lang/crates.io-index)", - "tokio 0.2.22 (registry+https://github.com/rust-lang/crates.io-index)", - "types 0.2.0", - "web3 0.11.0 (registry+https://github.com/rust-lang/crates.io-index)", + "deposit_contract", + "futures 0.3.5", + "serde_json", + "tokio 0.2.22", + "types", + "web3", +] + +[[package]] +name = "eth2" +version = "0.1.0" +dependencies = [ + "eth2_libp2p", + "hex 0.4.2", + "procinfo", + "proto_array", + "psutil", + "reqwest", + "serde", + "serde_json", + "serde_utils", + "types", ] [[package]] name = "eth2_config" version = "0.2.0" dependencies = [ - "serde 1.0.116 (registry+https://github.com/rust-lang/crates.io-index)", - "serde_derive 1.0.116 (registry+https://github.com/rust-lang/crates.io-index)", - "toml 0.5.6 (registry+https://github.com/rust-lang/crates.io-index)", - "types 0.2.0", + "serde", + "serde_derive", + "toml", + "types", ] [[package]] name = "eth2_hashing" version = "0.1.1" dependencies = [ - "lazy_static 1.4.0 (registry+https://github.com/rust-lang/crates.io-index)", - "ring 0.16.12 (registry+https://github.com/rust-lang/crates.io-index)", - "rustc-hex 2.1.0 (registry+https://github.com/rust-lang/crates.io-index)", - "sha2 0.9.1 (registry+https://github.com/rust-lang/crates.io-index)", - "wasm-bindgen-test 0.3.18 (registry+https://github.com/rust-lang/crates.io-index)", + "lazy_static", + "ring", + "rustc-hex", + "sha2 0.9.1", + "wasm-bindgen-test", ] [[package]] name = "eth2_interop_keypairs" version = "0.2.0" dependencies = [ - "base64 0.12.3 (registry+https://github.com/rust-lang/crates.io-index)", - "bls 0.2.0", - "eth2_hashing 0.1.1", - "hex 0.4.2 (registry+https://github.com/rust-lang/crates.io-index)", - "lazy_static 1.4.0 (registry+https://github.com/rust-lang/crates.io-index)", - "num-bigint 0.3.0 (registry+https://github.com/rust-lang/crates.io-index)", - "serde 1.0.116 (registry+https://github.com/rust-lang/crates.io-index)", - "serde_derive 1.0.116 (registry+https://github.com/rust-lang/crates.io-index)", - "serde_yaml 0.8.13 (registry+https://github.com/rust-lang/crates.io-index)", + "base64 0.12.3", + "bls", + "eth2_hashing", + "hex 0.4.2", + "lazy_static", + "num-bigint", + "serde", + "serde_derive", + "serde_yaml", ] [[package]] name = "eth2_key_derivation" version = "0.1.0" dependencies = [ - "bls 0.2.0", - "hex 0.4.2 (registry+https://github.com/rust-lang/crates.io-index)", - "num-bigint-dig 0.6.0 (registry+https://github.com/rust-lang/crates.io-index)", - "ring 0.16.12 (registry+https://github.com/rust-lang/crates.io-index)", - "sha2 0.9.1 (registry+https://github.com/rust-lang/crates.io-index)", - "zeroize 1.1.1 (registry+https://github.com/rust-lang/crates.io-index)", + "bls", + "hex 0.4.2", + "num-bigint-dig", + "ring", + "sha2 0.9.1", + "zeroize", ] [[package]] name = "eth2_keystore" version = "0.1.0" dependencies = [ - "aes-ctr 0.4.0 (registry+https://github.com/rust-lang/crates.io-index)", - "bls 0.2.0", - "eth2_key_derivation 0.1.0", - "eth2_ssz 0.1.2", - "hex 0.4.2 (registry+https://github.com/rust-lang/crates.io-index)", - "hmac 0.8.1 (registry+https://github.com/rust-lang/crates.io-index)", - "pbkdf2 0.4.0 (registry+https://github.com/rust-lang/crates.io-index)", - "rand 0.7.3 (registry+https://github.com/rust-lang/crates.io-index)", - "scrypt 0.3.1 (registry+https://github.com/rust-lang/crates.io-index)", - "serde 1.0.116 (registry+https://github.com/rust-lang/crates.io-index)", - "serde_json 1.0.57 (registry+https://github.com/rust-lang/crates.io-index)", - "serde_repr 0.1.6 (registry+https://github.com/rust-lang/crates.io-index)", - "sha2 0.9.1 (registry+https://github.com/rust-lang/crates.io-index)", - "tempfile 3.1.0 (registry+https://github.com/rust-lang/crates.io-index)", - "uuid 0.8.1 (registry+https://github.com/rust-lang/crates.io-index)", - "zeroize 1.1.1 (registry+https://github.com/rust-lang/crates.io-index)", + "aes-ctr", + "bls", + "eth2_key_derivation", + "eth2_ssz", + "hex 0.4.2", + "hmac 0.8.1", + "pbkdf2 0.4.0", + "rand 0.7.3", + "scrypt", + "serde", + "serde_json", + "serde_repr", + "sha2 0.9.1", + "tempfile", + "uuid", + "zeroize", ] [[package]] name = "eth2_libp2p" version = "0.2.0" dependencies = [ - "base64 0.12.3 (registry+https://github.com/rust-lang/crates.io-index)", - "directory 0.1.0", - "dirs 2.0.2 (registry+https://github.com/rust-lang/crates.io-index)", - "discv5 0.1.0-alpha.11 (registry+https://github.com/rust-lang/crates.io-index)", - "environment 0.1.2", - "error-chain 0.12.4 (registry+https://github.com/rust-lang/crates.io-index)", - "eth2_ssz 0.1.2", - "eth2_ssz_derive 0.1.0", - "eth2_ssz_types 0.2.0", - "exit-future 0.2.0 (registry+https://github.com/rust-lang/crates.io-index)", - "fnv 1.0.7 (registry+https://github.com/rust-lang/crates.io-index)", - "futures 0.3.5 (registry+https://github.com/rust-lang/crates.io-index)", - "hashset_delay 0.2.0", - "hex 0.4.2 (registry+https://github.com/rust-lang/crates.io-index)", - "lazy_static 1.4.0 (registry+https://github.com/rust-lang/crates.io-index)", - "libp2p 0.25.0 (git+https://github.com/sigp/rust-libp2p?rev=03f998022ce2f566a6c6e6c4206bc0ce4d45109f)", - "lighthouse_metrics 0.2.0", - "lighthouse_version 0.1.0", - "lru 0.5.3 (registry+https://github.com/rust-lang/crates.io-index)", - "parking_lot 0.11.0 (registry+https://github.com/rust-lang/crates.io-index)", - "rand 0.7.3 (registry+https://github.com/rust-lang/crates.io-index)", - "regex 1.3.9 (registry+https://github.com/rust-lang/crates.io-index)", - "serde 1.0.116 (registry+https://github.com/rust-lang/crates.io-index)", - "serde_derive 1.0.116 (registry+https://github.com/rust-lang/crates.io-index)", - "sha2 0.9.1 (registry+https://github.com/rust-lang/crates.io-index)", - "slog 2.5.2 (registry+https://github.com/rust-lang/crates.io-index)", - "slog-async 2.5.0 (registry+https://github.com/rust-lang/crates.io-index)", - "slog-stdlog 4.0.0 (registry+https://github.com/rust-lang/crates.io-index)", - "slog-term 2.6.0 (registry+https://github.com/rust-lang/crates.io-index)", - "smallvec 1.4.2 (registry+https://github.com/rust-lang/crates.io-index)", - "snap 1.0.1 (registry+https://github.com/rust-lang/crates.io-index)", - "tempdir 0.3.7 (registry+https://github.com/rust-lang/crates.io-index)", - "tiny-keccak 2.0.2 (registry+https://github.com/rust-lang/crates.io-index)", - "tokio 0.2.22 (registry+https://github.com/rust-lang/crates.io-index)", - "tokio-io-timeout 0.4.0 (registry+https://github.com/rust-lang/crates.io-index)", - "tokio-util 0.3.1 (registry+https://github.com/rust-lang/crates.io-index)", - "types 0.2.0", - "unsigned-varint 0.3.3 (git+https://github.com/sigp/unsigned-varint?branch=latest-codecs)", - "void 1.0.2 (registry+https://github.com/rust-lang/crates.io-index)", + "base64 0.12.3", + "directory", + "dirs", + "discv5", + "environment", + "error-chain", + "eth2_ssz", + "eth2_ssz_derive", + "eth2_ssz_types", + "exit-future", + "fnv", + "futures 0.3.5", + "hashset_delay", + "hex 0.4.2", + "lazy_static", + "libp2p", + "lighthouse_metrics", + "lighthouse_version", + "lru", + "parking_lot 0.11.0", + "rand 0.7.3", + "regex", + "serde", + "serde_derive", + "sha2 0.9.1", + "slog", + "slog-async", + "slog-stdlog", + "slog-term", + "smallvec 1.4.2", + "snap", + "tempdir", + "tiny-keccak 2.0.2", + "tokio 0.2.22", + "tokio-io-timeout", + "tokio-util", + "types", + "unsigned-varint 0.3.3", + "void", ] [[package]] name = "eth2_ssz" version = "0.1.2" dependencies = [ - "eth2_ssz_derive 0.1.0", - "ethereum-types 0.9.2 (registry+https://github.com/rust-lang/crates.io-index)", - "smallvec 1.4.2 (registry+https://github.com/rust-lang/crates.io-index)", + "eth2_ssz_derive", + "ethereum-types", + "smallvec 1.4.2", ] [[package]] name = "eth2_ssz_derive" version = "0.1.0" dependencies = [ - "quote 1.0.7 (registry+https://github.com/rust-lang/crates.io-index)", - "syn 1.0.42 (registry+https://github.com/rust-lang/crates.io-index)", + "quote", + "syn", ] [[package]] name = "eth2_ssz_types" version = "0.2.0" dependencies = [ - "arbitrary 0.4.6 (registry+https://github.com/rust-lang/crates.io-index)", - "eth2_ssz 0.1.2", - "serde 1.0.116 (registry+https://github.com/rust-lang/crates.io-index)", - "serde_derive 1.0.116 (registry+https://github.com/rust-lang/crates.io-index)", - "serde_hex 0.2.0", - "tree_hash 0.1.1", - "tree_hash_derive 0.2.0", - "typenum 1.12.0 (registry+https://github.com/rust-lang/crates.io-index)", + "arbitrary", + "eth2_ssz", + "serde", + "serde_derive", + "serde_utils", + "tree_hash", + "tree_hash_derive", + "typenum", ] [[package]] name = "eth2_testnet_config" version = "0.2.0" dependencies = [ - "enr 0.1.3 (registry+https://github.com/rust-lang/crates.io-index)", - "eth2_config 0.2.0", - "eth2_ssz 0.1.2", - "serde 1.0.116 (registry+https://github.com/rust-lang/crates.io-index)", - "serde_yaml 0.8.13 (registry+https://github.com/rust-lang/crates.io-index)", - "tempdir 0.3.7 (registry+https://github.com/rust-lang/crates.io-index)", - "types 0.2.0", - "zip 0.5.6 (registry+https://github.com/rust-lang/crates.io-index)", + "enr", + "eth2_config", + "eth2_ssz", + "serde", + "serde_yaml", + "tempdir", + "types", + "zip", ] [[package]] name = "eth2_wallet" version = "0.1.0" dependencies = [ - "eth2_key_derivation 0.1.0", - "eth2_keystore 0.1.0", - "hex 0.4.2 (registry+https://github.com/rust-lang/crates.io-index)", - "rand 0.7.3 (registry+https://github.com/rust-lang/crates.io-index)", - "serde 1.0.116 (registry+https://github.com/rust-lang/crates.io-index)", - "serde_json 1.0.57 (registry+https://github.com/rust-lang/crates.io-index)", - "serde_repr 0.1.6 (registry+https://github.com/rust-lang/crates.io-index)", - "tempfile 3.1.0 (registry+https://github.com/rust-lang/crates.io-index)", - "tiny-bip39 0.7.3 (registry+https://github.com/rust-lang/crates.io-index)", - "uuid 0.8.1 (registry+https://github.com/rust-lang/crates.io-index)", + "eth2_key_derivation", + "eth2_keystore", + "hex 0.4.2", + "rand 0.7.3", + "serde", + "serde_json", + "serde_repr", + "tempfile", + "tiny-bip39", + "uuid", ] [[package]] name = "eth2_wallet_manager" version = "0.1.0" dependencies = [ - "eth2_keystore 0.1.0", - "eth2_wallet 0.1.0", - "tempfile 3.1.0 (registry+https://github.com/rust-lang/crates.io-index)", + "eth2_keystore", + "eth2_wallet", + "tempfile", ] [[package]] name = "ethabi" version = "12.0.0" source = "registry+https://github.com/rust-lang/crates.io-index" +checksum = "052a565e3de82944527d6d10a465697e6bb92476b772ca7141080c901f6a63c6" dependencies = [ - "ethereum-types 0.9.2 (registry+https://github.com/rust-lang/crates.io-index)", - "rustc-hex 2.1.0 (registry+https://github.com/rust-lang/crates.io-index)", - "serde 1.0.116 (registry+https://github.com/rust-lang/crates.io-index)", - "serde_json 1.0.57 (registry+https://github.com/rust-lang/crates.io-index)", - "tiny-keccak 1.5.0 (registry+https://github.com/rust-lang/crates.io-index)", - "uint 0.8.5 (registry+https://github.com/rust-lang/crates.io-index)", + "ethereum-types", + "rustc-hex", + "serde", + "serde_json", + "tiny-keccak 1.5.0", + "uint", ] [[package]] name = "ethbloom" version = "0.9.2" source = "registry+https://github.com/rust-lang/crates.io-index" +checksum = "71a6567e6fd35589fea0c63b94b4cf2e55573e413901bdbe60ab15cf0e25e5df" dependencies = [ - "crunchy 0.2.2 (registry+https://github.com/rust-lang/crates.io-index)", - "fixed-hash 0.6.1 (registry+https://github.com/rust-lang/crates.io-index)", - "impl-rlp 0.2.1 (registry+https://github.com/rust-lang/crates.io-index)", - "impl-serde 0.3.1 (registry+https://github.com/rust-lang/crates.io-index)", - "tiny-keccak 2.0.2 (registry+https://github.com/rust-lang/crates.io-index)", + "crunchy", + "fixed-hash", + "impl-rlp", + "impl-serde", + "tiny-keccak 2.0.2", ] [[package]] name = "ethereum-types" version = "0.9.2" source = "registry+https://github.com/rust-lang/crates.io-index" +checksum = "473aecff686bd8e7b9db0165cbbb53562376b39bf35b427f0c60446a9e1634b0" dependencies = [ - "ethbloom 0.9.2 (registry+https://github.com/rust-lang/crates.io-index)", - "fixed-hash 0.6.1 (registry+https://github.com/rust-lang/crates.io-index)", - "impl-rlp 0.2.1 (registry+https://github.com/rust-lang/crates.io-index)", - "impl-serde 0.3.1 (registry+https://github.com/rust-lang/crates.io-index)", - "primitive-types 0.7.2 (registry+https://github.com/rust-lang/crates.io-index)", - "uint 0.8.5 (registry+https://github.com/rust-lang/crates.io-index)", + "ethbloom", + "fixed-hash", + "impl-rlp", + "impl-serde", + "primitive-types", + "uint", ] [[package]] name = "exit-future" version = "0.2.0" source = "registry+https://github.com/rust-lang/crates.io-index" +checksum = "e43f2f1833d64e33f15592464d6fdd70f349dda7b1a53088eb83cd94014008c5" dependencies = [ - "futures 0.3.5 (registry+https://github.com/rust-lang/crates.io-index)", + "futures 0.3.5", ] [[package]] name = "failure" version = "0.1.8" source = "registry+https://github.com/rust-lang/crates.io-index" +checksum = "d32e9bd16cc02eae7db7ef620b392808b89f6a5e16bb3497d159c6b92a0f4f86" dependencies = [ - "backtrace 0.3.50 (registry+https://github.com/rust-lang/crates.io-index)", - "failure_derive 0.1.8 (registry+https://github.com/rust-lang/crates.io-index)", + "backtrace", + "failure_derive", ] [[package]] name = "failure_derive" version = "0.1.8" source = "registry+https://github.com/rust-lang/crates.io-index" +checksum = "aa4da3c766cd7a0db8242e326e9e4e081edd567072893ed320008189715366a4" dependencies = [ - "proc-macro2 1.0.23 (registry+https://github.com/rust-lang/crates.io-index)", - "quote 1.0.7 (registry+https://github.com/rust-lang/crates.io-index)", - "syn 1.0.42 (registry+https://github.com/rust-lang/crates.io-index)", - "synstructure 0.12.4 (registry+https://github.com/rust-lang/crates.io-index)", + "proc-macro2", + "quote", + "syn", + "synstructure", ] [[package]] name = "fake-simd" version = "0.1.2" source = "registry+https://github.com/rust-lang/crates.io-index" +checksum = "e88a8acf291dafb59c2d96e8f59828f3838bb1a70398823ade51a84de6a6deed" [[package]] name = "fallible-iterator" version = "0.2.0" source = "registry+https://github.com/rust-lang/crates.io-index" +checksum = "4443176a9f2c162692bd3d352d745ef9413eec5782a80d8fd6f8a1ac692a07f7" [[package]] name = "fallible-streaming-iterator" version = "0.1.9" source = "registry+https://github.com/rust-lang/crates.io-index" +checksum = "7360491ce676a36bf9bb3c56c1aa791658183a54d2744120f27285738d90465a" [[package]] name = "fixed-hash" version = "0.6.1" source = "registry+https://github.com/rust-lang/crates.io-index" +checksum = "11498d382790b7a8f2fd211780bec78619bba81cdad3a283997c0c41f836759c" dependencies = [ - "arbitrary 0.4.6 (registry+https://github.com/rust-lang/crates.io-index)", - "byteorder 1.3.4 (registry+https://github.com/rust-lang/crates.io-index)", - "rand 0.7.3 (registry+https://github.com/rust-lang/crates.io-index)", - "rustc-hex 2.1.0 (registry+https://github.com/rust-lang/crates.io-index)", - "static_assertions 1.1.0 (registry+https://github.com/rust-lang/crates.io-index)", + "arbitrary", + "byteorder", + "rand 0.7.3", + "rustc-hex", + "static_assertions", ] [[package]] name = "fixedbitset" version = "0.2.0" source = "registry+https://github.com/rust-lang/crates.io-index" +checksum = "37ab347416e802de484e4d03c7316c48f1ecb56574dfd4a46a80f173ce1de04d" [[package]] name = "flate2" version = "1.0.17" source = "registry+https://github.com/rust-lang/crates.io-index" +checksum = "766d0e77a2c1502169d4a93ff3b8c15a71fd946cd0126309752104e5f3c46d94" dependencies = [ - "cfg-if 0.1.10 (registry+https://github.com/rust-lang/crates.io-index)", - "crc32fast 1.2.0 (registry+https://github.com/rust-lang/crates.io-index)", - "libc 0.2.77 (registry+https://github.com/rust-lang/crates.io-index)", - "libz-sys 1.1.2 (registry+https://github.com/rust-lang/crates.io-index)", - "miniz_oxide 0.4.2 (registry+https://github.com/rust-lang/crates.io-index)", + "cfg-if", + "crc32fast", + "libc", + "libz-sys", + "miniz_oxide", ] [[package]] name = "fnv" version = "1.0.7" source = "registry+https://github.com/rust-lang/crates.io-index" +checksum = "3f9eec918d3f24069decb9af1554cad7c880e2da24a9afd88aca000531ab82c1" [[package]] name = "foreign-types" version = "0.3.2" source = "registry+https://github.com/rust-lang/crates.io-index" +checksum = "f6f339eb8adc052cd2ca78910fda869aefa38d22d5cb648e6485e4d3fc06f3b1" dependencies = [ - "foreign-types-shared 0.1.1 (registry+https://github.com/rust-lang/crates.io-index)", + "foreign-types-shared", ] [[package]] name = "foreign-types-shared" version = "0.1.1" source = "registry+https://github.com/rust-lang/crates.io-index" +checksum = "00b0228411908ca8685dba7fc2cdd70ec9990a6e753e89b6ac91a84c40fbaf4b" [[package]] name = "fork_choice" version = "0.1.0" dependencies = [ - "beacon_chain 0.2.0", - "eth2_ssz 0.1.2", - "eth2_ssz_derive 0.1.0", - "proto_array 0.2.0", - "slot_clock 0.2.0", - "state_processing 0.2.0", - "store 0.2.0", - "tree_hash 0.1.1", - "types 0.2.0", + "beacon_chain", + "eth2_ssz", + "eth2_ssz_derive", + "proto_array", + "slot_clock", + "state_processing", + "store", + "tree_hash", + "types", ] [[package]] name = "fuchsia-cprng" version = "0.1.1" source = "registry+https://github.com/rust-lang/crates.io-index" +checksum = "a06f77d526c1a601b7c4cdd98f54b5eaabffc14d5f2f0296febdc7f357c6d3ba" [[package]] name = "fuchsia-zircon" version = "0.3.3" source = "registry+https://github.com/rust-lang/crates.io-index" +checksum = "2e9763c69ebaae630ba35f74888db465e49e259ba1bc0eda7d06f4a067615d82" dependencies = [ - "bitflags 1.2.1 (registry+https://github.com/rust-lang/crates.io-index)", - "fuchsia-zircon-sys 0.3.3 (registry+https://github.com/rust-lang/crates.io-index)", + "bitflags 1.2.1", + "fuchsia-zircon-sys", ] [[package]] name = "fuchsia-zircon-sys" version = "0.3.3" source = "registry+https://github.com/rust-lang/crates.io-index" +checksum = "3dcaa9ae7725d12cdb85b3ad99a434db70b468c09ded17e012d86b5c1010f7a7" [[package]] name = "futures" version = "0.1.29" source = "registry+https://github.com/rust-lang/crates.io-index" +checksum = "1b980f2816d6ee8673b6517b52cb0e808a180efc92e5c19d02cdda79066703ef" [[package]] name = "futures" version = "0.3.5" source = "registry+https://github.com/rust-lang/crates.io-index" +checksum = "1e05b85ec287aac0dc34db7d4a569323df697f9c55b99b15d6b4ef8cde49f613" dependencies = [ - "futures-channel 0.3.5 (registry+https://github.com/rust-lang/crates.io-index)", - "futures-core 0.3.5 (registry+https://github.com/rust-lang/crates.io-index)", - "futures-executor 0.3.5 (registry+https://github.com/rust-lang/crates.io-index)", - "futures-io 0.3.5 (registry+https://github.com/rust-lang/crates.io-index)", - "futures-sink 0.3.5 (registry+https://github.com/rust-lang/crates.io-index)", - "futures-task 0.3.5 (registry+https://github.com/rust-lang/crates.io-index)", - "futures-util 0.3.5 (registry+https://github.com/rust-lang/crates.io-index)", + "futures-channel", + "futures-core", + "futures-executor", + "futures-io", + "futures-sink", + "futures-task", + "futures-util", ] [[package]] name = "futures-channel" version = "0.3.5" source = "registry+https://github.com/rust-lang/crates.io-index" +checksum = "f366ad74c28cca6ba456d95e6422883cfb4b252a83bed929c83abfdbbf2967d5" dependencies = [ - "futures-core 0.3.5 (registry+https://github.com/rust-lang/crates.io-index)", - "futures-sink 0.3.5 (registry+https://github.com/rust-lang/crates.io-index)", + "futures-core", + "futures-sink", ] [[package]] name = "futures-core" version = "0.3.5" source = "registry+https://github.com/rust-lang/crates.io-index" +checksum = "59f5fff90fd5d971f936ad674802482ba441b6f09ba5e15fd8b39145582ca399" [[package]] name = "futures-cpupool" version = "0.1.8" source = "registry+https://github.com/rust-lang/crates.io-index" +checksum = "ab90cde24b3319636588d0c35fe03b1333857621051837ed769faefb4c2162e4" dependencies = [ - "futures 0.1.29 (registry+https://github.com/rust-lang/crates.io-index)", - "num_cpus 1.13.0 (registry+https://github.com/rust-lang/crates.io-index)", + "futures 0.1.29", + "num_cpus", ] [[package]] name = "futures-executor" version = "0.3.5" source = "registry+https://github.com/rust-lang/crates.io-index" +checksum = "10d6bb888be1153d3abeb9006b11b02cf5e9b209fda28693c31ae1e4e012e314" dependencies = [ - "futures-core 0.3.5 (registry+https://github.com/rust-lang/crates.io-index)", - "futures-task 0.3.5 (registry+https://github.com/rust-lang/crates.io-index)", - "futures-util 0.3.5 (registry+https://github.com/rust-lang/crates.io-index)", - "num_cpus 1.13.0 (registry+https://github.com/rust-lang/crates.io-index)", + "futures-core", + "futures-task", + "futures-util", + "num_cpus", ] [[package]] name = "futures-io" version = "0.3.5" source = "registry+https://github.com/rust-lang/crates.io-index" +checksum = "de27142b013a8e869c14957e6d2edeef89e97c289e69d042ee3a49acd8b51789" [[package]] name = "futures-macro" version = "0.3.5" source = "registry+https://github.com/rust-lang/crates.io-index" +checksum = "d0b5a30a4328ab5473878237c447333c093297bded83a4983d10f4deea240d39" dependencies = [ - "proc-macro-hack 0.5.18 (registry+https://github.com/rust-lang/crates.io-index)", - "proc-macro2 1.0.23 (registry+https://github.com/rust-lang/crates.io-index)", - "quote 1.0.7 (registry+https://github.com/rust-lang/crates.io-index)", - "syn 1.0.42 (registry+https://github.com/rust-lang/crates.io-index)", + "proc-macro-hack", + "proc-macro2", + "quote", + "syn", ] [[package]] name = "futures-sink" version = "0.3.5" source = "registry+https://github.com/rust-lang/crates.io-index" +checksum = "3f2032893cb734c7a05d85ce0cc8b8c4075278e93b24b66f9de99d6eb0fa8acc" [[package]] name = "futures-task" version = "0.3.5" source = "registry+https://github.com/rust-lang/crates.io-index" +checksum = "bdb66b5f09e22019b1ab0830f7785bcea8e7a42148683f99214f73f8ec21a626" dependencies = [ - "once_cell 1.4.1 (registry+https://github.com/rust-lang/crates.io-index)", + "once_cell", ] [[package]] name = "futures-timer" version = "3.0.2" source = "registry+https://github.com/rust-lang/crates.io-index" +checksum = "e64b03909df88034c26dc1547e8970b91f98bdb65165d6a4e9110d94263dbb2c" [[package]] name = "futures-util" version = "0.3.5" source = "registry+https://github.com/rust-lang/crates.io-index" +checksum = "8764574ff08b701a084482c3c7031349104b07ac897393010494beaa18ce32c6" dependencies = [ - "futures 0.1.29 (registry+https://github.com/rust-lang/crates.io-index)", - "futures-channel 0.3.5 (registry+https://github.com/rust-lang/crates.io-index)", - "futures-core 0.3.5 (registry+https://github.com/rust-lang/crates.io-index)", - "futures-io 0.3.5 (registry+https://github.com/rust-lang/crates.io-index)", - "futures-macro 0.3.5 (registry+https://github.com/rust-lang/crates.io-index)", - "futures-sink 0.3.5 (registry+https://github.com/rust-lang/crates.io-index)", - "futures-task 0.3.5 (registry+https://github.com/rust-lang/crates.io-index)", - "memchr 2.3.3 (registry+https://github.com/rust-lang/crates.io-index)", - "pin-project 0.4.24 (registry+https://github.com/rust-lang/crates.io-index)", - "pin-utils 0.1.0 (registry+https://github.com/rust-lang/crates.io-index)", - "proc-macro-hack 0.5.18 (registry+https://github.com/rust-lang/crates.io-index)", - "proc-macro-nested 0.1.6 (registry+https://github.com/rust-lang/crates.io-index)", - "slab 0.4.2 (registry+https://github.com/rust-lang/crates.io-index)", + "futures 0.1.29", + "futures-channel", + "futures-core", + "futures-io", + "futures-macro", + "futures-sink", + "futures-task", + "memchr", + "pin-project", + "pin-utils", + "proc-macro-hack", + "proc-macro-nested", + "slab 0.4.2", ] [[package]] name = "futures_codec" version = "0.4.1" source = "registry+https://github.com/rust-lang/crates.io-index" +checksum = "ce54d63f8b0c75023ed920d46fd71d0cbbb830b0ee012726b5b4f506fb6dea5b" dependencies = [ - "bytes 0.5.6 (registry+https://github.com/rust-lang/crates.io-index)", - "futures 0.3.5 (registry+https://github.com/rust-lang/crates.io-index)", - "memchr 2.3.3 (registry+https://github.com/rust-lang/crates.io-index)", - "pin-project 0.4.24 (registry+https://github.com/rust-lang/crates.io-index)", + "bytes 0.5.6", + "futures 0.3.5", + "memchr", + "pin-project", ] [[package]] name = "gcc" version = "0.3.55" source = "registry+https://github.com/rust-lang/crates.io-index" +checksum = "8f5f3913fa0bfe7ee1fd8248b6b9f42a5af4b9d65ec2dd2c3c26132b950ecfc2" [[package]] name = "generic-array" version = "0.12.3" source = "registry+https://github.com/rust-lang/crates.io-index" +checksum = "c68f0274ae0e023facc3c97b2e00f076be70e254bc851d972503b328db79b2ec" dependencies = [ - "typenum 1.12.0 (registry+https://github.com/rust-lang/crates.io-index)", + "typenum", ] [[package]] name = "generic-array" version = "0.14.4" source = "registry+https://github.com/rust-lang/crates.io-index" +checksum = "501466ecc8a30d1d3b7fc9229b122b2ce8ed6e9d9223f1138d4babb253e51817" dependencies = [ - "typenum 1.12.0 (registry+https://github.com/rust-lang/crates.io-index)", - "version_check 0.9.2 (registry+https://github.com/rust-lang/crates.io-index)", + "typenum", + "version_check 0.9.2", ] [[package]] name = "genesis" version = "0.2.0" dependencies = [ - "environment 0.1.2", - "eth1 0.2.0", - "eth1_test_rig 0.2.0", - "eth2_hashing 0.1.1", - "eth2_ssz 0.1.2", - "exit-future 0.2.0 (registry+https://github.com/rust-lang/crates.io-index)", - "futures 0.3.5 (registry+https://github.com/rust-lang/crates.io-index)", - "int_to_bytes 0.2.0", - "merkle_proof 0.2.0", - "parking_lot 0.11.0 (registry+https://github.com/rust-lang/crates.io-index)", - "rayon 1.4.0 (registry+https://github.com/rust-lang/crates.io-index)", - "serde 1.0.116 (registry+https://github.com/rust-lang/crates.io-index)", - "serde_derive 1.0.116 (registry+https://github.com/rust-lang/crates.io-index)", - "slog 2.5.2 (registry+https://github.com/rust-lang/crates.io-index)", - "state_processing 0.2.0", - "tokio 0.2.22 (registry+https://github.com/rust-lang/crates.io-index)", - "tree_hash 0.1.1", - "types 0.2.0", + "environment", + "eth1", + "eth1_test_rig", + "eth2_hashing", + "eth2_ssz", + "exit-future", + "futures 0.3.5", + "int_to_bytes", + "merkle_proof", + "parking_lot 0.11.0", + "rayon", + "serde", + "serde_derive", + "slog", + "state_processing", + "tokio 0.2.22", + "tree_hash", + "types", ] [[package]] name = "get_if_addrs" version = "0.5.3" source = "registry+https://github.com/rust-lang/crates.io-index" +checksum = "abddb55a898d32925f3148bd281174a68eeb68bbfd9a5938a57b18f506ee4ef7" dependencies = [ - "c_linked_list 1.1.1 (registry+https://github.com/rust-lang/crates.io-index)", - "get_if_addrs-sys 0.1.1 (registry+https://github.com/rust-lang/crates.io-index)", - "libc 0.2.77 (registry+https://github.com/rust-lang/crates.io-index)", - "winapi 0.2.8 (registry+https://github.com/rust-lang/crates.io-index)", + "c_linked_list", + "get_if_addrs-sys", + "libc", + "winapi 0.2.8", ] [[package]] name = "get_if_addrs-sys" version = "0.1.1" source = "registry+https://github.com/rust-lang/crates.io-index" +checksum = "0d04f9fb746cf36b191c00f3ede8bde9c8e64f9f4b05ae2694a9ccf5e3f5ab48" dependencies = [ - "gcc 0.3.55 (registry+https://github.com/rust-lang/crates.io-index)", - "libc 0.2.77 (registry+https://github.com/rust-lang/crates.io-index)", + "gcc", + "libc", ] [[package]] name = "getrandom" version = "0.1.15" source = "registry+https://github.com/rust-lang/crates.io-index" +checksum = "fc587bc0ec293155d5bfa6b9891ec18a1e330c234f896ea47fbada4cadbe47e6" dependencies = [ - "cfg-if 0.1.10 (registry+https://github.com/rust-lang/crates.io-index)", - "libc 0.2.77 (registry+https://github.com/rust-lang/crates.io-index)", - "wasi 0.9.0+wasi-snapshot-preview1 (registry+https://github.com/rust-lang/crates.io-index)", + "cfg-if", + "libc", + "wasi 0.9.0+wasi-snapshot-preview1", ] [[package]] name = "ghash" version = "0.3.0" source = "registry+https://github.com/rust-lang/crates.io-index" +checksum = "d6e27f0689a6e15944bdce7e45425efb87eaa8ab0c6e87f11d0987a9133e2531" dependencies = [ - "polyval 0.4.0 (registry+https://github.com/rust-lang/crates.io-index)", + "polyval", ] [[package]] name = "gimli" version = "0.22.0" source = "registry+https://github.com/rust-lang/crates.io-index" +checksum = "aaf91faf136cb47367fa430cd46e37a788775e7fa104f8b4bcb3861dc389b724" [[package]] name = "git-version" version = "0.3.4" source = "registry+https://github.com/rust-lang/crates.io-index" +checksum = "94918e83f1e01dedc2e361d00ce9487b14c58c7f40bab148026fa39d42cb41e2" dependencies = [ - "git-version-macro 0.3.4 (registry+https://github.com/rust-lang/crates.io-index)", - "proc-macro-hack 0.5.18 (registry+https://github.com/rust-lang/crates.io-index)", + "git-version-macro", + "proc-macro-hack", ] [[package]] name = "git-version-macro" version = "0.3.4" source = "registry+https://github.com/rust-lang/crates.io-index" +checksum = "34a97a52fdee1870a34fa6e4b77570cba531b27d1838874fef4429a791a3d657" dependencies = [ - "proc-macro-hack 0.5.18 (registry+https://github.com/rust-lang/crates.io-index)", - "proc-macro2 1.0.23 (registry+https://github.com/rust-lang/crates.io-index)", - "quote 1.0.7 (registry+https://github.com/rust-lang/crates.io-index)", - "syn 1.0.42 (registry+https://github.com/rust-lang/crates.io-index)", + "proc-macro-hack", + "proc-macro2", + "quote", + "syn", ] [[package]] name = "glob" version = "0.3.0" source = "registry+https://github.com/rust-lang/crates.io-index" +checksum = "9b919933a397b79c37e33b77bb2aa3dc8eb6e165ad809e58ff75bc7db2e34574" [[package]] name = "h2" version = "0.1.26" source = "registry+https://github.com/rust-lang/crates.io-index" +checksum = "a5b34c246847f938a410a03c5458c7fee2274436675e76d8b903c08efc29c462" dependencies = [ - "byteorder 1.3.4 (registry+https://github.com/rust-lang/crates.io-index)", - "bytes 0.4.12 (registry+https://github.com/rust-lang/crates.io-index)", - "fnv 1.0.7 (registry+https://github.com/rust-lang/crates.io-index)", - "futures 0.1.29 (registry+https://github.com/rust-lang/crates.io-index)", - "http 0.1.21 (registry+https://github.com/rust-lang/crates.io-index)", - "indexmap 1.6.0 (registry+https://github.com/rust-lang/crates.io-index)", - "log 0.4.11 (registry+https://github.com/rust-lang/crates.io-index)", - "slab 0.4.2 (registry+https://github.com/rust-lang/crates.io-index)", - "string 0.2.1 (registry+https://github.com/rust-lang/crates.io-index)", - "tokio-io 0.1.13 (registry+https://github.com/rust-lang/crates.io-index)", + "byteorder", + "bytes 0.4.12", + "fnv", + "futures 0.1.29", + "http 0.1.21", + "indexmap", + "log 0.4.11", + "slab 0.4.2", + "string", + "tokio-io", ] [[package]] name = "h2" version = "0.2.6" source = "registry+https://github.com/rust-lang/crates.io-index" +checksum = "993f9e0baeed60001cf565546b0d3dbe6a6ad23f2bd31644a133c641eccf6d53" dependencies = [ - "bytes 0.5.6 (registry+https://github.com/rust-lang/crates.io-index)", - "fnv 1.0.7 (registry+https://github.com/rust-lang/crates.io-index)", - "futures-core 0.3.5 (registry+https://github.com/rust-lang/crates.io-index)", - "futures-sink 0.3.5 (registry+https://github.com/rust-lang/crates.io-index)", - "futures-util 0.3.5 (registry+https://github.com/rust-lang/crates.io-index)", - "http 0.2.1 (registry+https://github.com/rust-lang/crates.io-index)", - "indexmap 1.6.0 (registry+https://github.com/rust-lang/crates.io-index)", - "slab 0.4.2 (registry+https://github.com/rust-lang/crates.io-index)", - "tokio 0.2.22 (registry+https://github.com/rust-lang/crates.io-index)", - "tokio-util 0.3.1 (registry+https://github.com/rust-lang/crates.io-index)", - "tracing 0.1.19 (registry+https://github.com/rust-lang/crates.io-index)", + "bytes 0.5.6", + "fnv", + "futures-core", + "futures-sink", + "futures-util", + "http 0.2.1", + "indexmap", + "slab 0.4.2", + "tokio 0.2.22", + "tokio-util", + "tracing", ] [[package]] name = "half" version = "1.6.0" source = "registry+https://github.com/rust-lang/crates.io-index" +checksum = "d36fab90f82edc3c747f9d438e06cf0a491055896f2a279638bb5beed6c40177" [[package]] name = "hashbrown" version = "0.6.3" source = "registry+https://github.com/rust-lang/crates.io-index" +checksum = "8e6073d0ca812575946eb5f35ff68dbe519907b25c42530389ff946dc84c6ead" dependencies = [ - "ahash 0.2.18 (registry+https://github.com/rust-lang/crates.io-index)", - "autocfg 0.1.7 (registry+https://github.com/rust-lang/crates.io-index)", + "ahash", + "autocfg 0.1.7", ] [[package]] name = "hashbrown" version = "0.9.0" source = "registry+https://github.com/rust-lang/crates.io-index" +checksum = "00d63df3d41950fb462ed38308eea019113ad1508da725bbedcd0fa5a85ef5f7" [[package]] name = "hashset_delay" version = "0.2.0" dependencies = [ - "futures 0.3.5 (registry+https://github.com/rust-lang/crates.io-index)", - "tokio 0.2.22 (registry+https://github.com/rust-lang/crates.io-index)", + "futures 0.3.5", + "tokio 0.2.22", +] + +[[package]] +name = "headers" +version = "0.3.2" +source = "registry+https://github.com/rust-lang/crates.io-index" +checksum = "ed18eb2459bf1a09ad2d6b1547840c3e5e62882fa09b9a6a20b1de8e3228848f" +dependencies = [ + "base64 0.12.3", + "bitflags 1.2.1", + "bytes 0.5.6", + "headers-core", + "http 0.2.1", + "mime 0.3.16", + "sha-1 0.8.2", + "time 0.1.44", +] + +[[package]] +name = "headers-core" +version = "0.2.0" +source = "registry+https://github.com/rust-lang/crates.io-index" +checksum = "e7f66481bfee273957b1f20485a4ff3362987f85b2c236580d81b4eb7a326429" +dependencies = [ + "http 0.2.1", ] [[package]] name = "heck" version = "0.3.1" source = "registry+https://github.com/rust-lang/crates.io-index" +checksum = "20564e78d53d2bb135c343b3f47714a56af2061f1c928fdb541dc7b9fdd94205" dependencies = [ - "unicode-segmentation 1.6.0 (registry+https://github.com/rust-lang/crates.io-index)", + "unicode-segmentation", ] [[package]] name = "hermit-abi" version = "0.1.16" source = "registry+https://github.com/rust-lang/crates.io-index" +checksum = "4c30f6d0bc6b00693347368a67d41b58f2fb851215ff1da49e90fe2c5c667151" dependencies = [ - "libc 0.2.77 (registry+https://github.com/rust-lang/crates.io-index)", + "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" source = "registry+https://github.com/rust-lang/crates.io-index" +checksum = "644f9158b2f133fd50f5fb3242878846d9eb792e445c893805ff0e3824006e35" [[package]] name = "hex_fmt" version = "0.3.0" source = "registry+https://github.com/rust-lang/crates.io-index" +checksum = "b07f60793ff0a4d9cef0f18e63b5357e06209987153a64648c972c1e5aff336f" [[package]] name = "hkdf" version = "0.8.0" source = "registry+https://github.com/rust-lang/crates.io-index" +checksum = "3fa08a006102488bd9cd5b8013aabe84955cf5ae22e304c2caf655b633aefae3" dependencies = [ - "digest 0.8.1 (registry+https://github.com/rust-lang/crates.io-index)", - "hmac 0.7.1 (registry+https://github.com/rust-lang/crates.io-index)", + "digest 0.8.1", + "hmac 0.7.1", ] [[package]] name = "hmac" version = "0.7.1" source = "registry+https://github.com/rust-lang/crates.io-index" +checksum = "5dcb5e64cda4c23119ab41ba960d1e170a774c8e4b9d9e6a9bc18aabf5e59695" dependencies = [ - "crypto-mac 0.7.0 (registry+https://github.com/rust-lang/crates.io-index)", - "digest 0.8.1 (registry+https://github.com/rust-lang/crates.io-index)", + "crypto-mac 0.7.0", + "digest 0.8.1", ] [[package]] name = "hmac" version = "0.8.1" source = "registry+https://github.com/rust-lang/crates.io-index" +checksum = "126888268dcc288495a26bf004b38c5fdbb31682f992c84ceb046a1f0fe38840" dependencies = [ - "crypto-mac 0.8.0 (registry+https://github.com/rust-lang/crates.io-index)", - "digest 0.9.0 (registry+https://github.com/rust-lang/crates.io-index)", + "crypto-mac 0.8.0", + "digest 0.9.0", ] [[package]] name = "hmac-drbg" version = "0.2.0" source = "registry+https://github.com/rust-lang/crates.io-index" +checksum = "c6e570451493f10f6581b48cdd530413b63ea9e780f544bfd3bdcaa0d89d1a7b" dependencies = [ - "digest 0.8.1 (registry+https://github.com/rust-lang/crates.io-index)", - "generic-array 0.12.3 (registry+https://github.com/rust-lang/crates.io-index)", - "hmac 0.7.1 (registry+https://github.com/rust-lang/crates.io-index)", + "digest 0.8.1", + "generic-array 0.12.3", + "hmac 0.7.1", ] [[package]] name = "http" version = "0.1.21" source = "registry+https://github.com/rust-lang/crates.io-index" +checksum = "d6ccf5ede3a895d8856620237b2f02972c1bbc78d2965ad7fe8838d4a0ed41f0" dependencies = [ - "bytes 0.4.12 (registry+https://github.com/rust-lang/crates.io-index)", - "fnv 1.0.7 (registry+https://github.com/rust-lang/crates.io-index)", - "itoa 0.4.6 (registry+https://github.com/rust-lang/crates.io-index)", + "bytes 0.4.12", + "fnv", + "itoa", ] [[package]] name = "http" version = "0.2.1" source = "registry+https://github.com/rust-lang/crates.io-index" +checksum = "28d569972648b2c512421b5f2a405ad6ac9666547189d0c5477a3f200f3e02f9" dependencies = [ - "bytes 0.5.6 (registry+https://github.com/rust-lang/crates.io-index)", - "fnv 1.0.7 (registry+https://github.com/rust-lang/crates.io-index)", - "itoa 0.4.6 (registry+https://github.com/rust-lang/crates.io-index)", + "bytes 0.5.6", + "fnv", + "itoa", ] [[package]] name = "http-body" version = "0.1.0" source = "registry+https://github.com/rust-lang/crates.io-index" +checksum = "6741c859c1b2463a423a1dbce98d418e6c3c3fc720fb0d45528657320920292d" dependencies = [ - "bytes 0.4.12 (registry+https://github.com/rust-lang/crates.io-index)", - "futures 0.1.29 (registry+https://github.com/rust-lang/crates.io-index)", - "http 0.1.21 (registry+https://github.com/rust-lang/crates.io-index)", - "tokio-buf 0.1.1 (registry+https://github.com/rust-lang/crates.io-index)", + "bytes 0.4.12", + "futures 0.1.29", + "http 0.1.21", + "tokio-buf", ] [[package]] name = "http-body" version = "0.3.1" source = "registry+https://github.com/rust-lang/crates.io-index" +checksum = "13d5ff830006f7646652e057693569bfe0d51760c0085a071769d142a205111b" +dependencies = [ + "bytes 0.5.6", + "http 0.2.1", +] + +[[package]] +name = "http_api" +version = "0.1.0" +dependencies = [ + "beacon_chain", + "discv5", + "environment", + "eth1", + "eth2", + "eth2_libp2p", + "fork_choice", + "hex 0.4.2", + "lazy_static", + "lighthouse_metrics", + "lighthouse_version", + "network", + "parking_lot 0.11.0", + "serde", + "slog", + "slot_clock", + "state_processing", + "store", + "tokio 0.2.22", + "tree_hash", + "types", + "warp", + "warp_utils", +] + +[[package]] +name = "http_metrics" +version = "0.1.0" dependencies = [ - "bytes 0.5.6 (registry+https://github.com/rust-lang/crates.io-index)", - "http 0.2.1 (registry+https://github.com/rust-lang/crates.io-index)", + "beacon_chain", + "environment", + "eth2", + "eth2_libp2p", + "lazy_static", + "lighthouse_metrics", + "lighthouse_version", + "prometheus", + "reqwest", + "serde", + "slog", + "slot_clock", + "store", + "tokio 0.2.22", + "types", + "warp", + "warp_utils", ] [[package]] name = "httparse" version = "1.3.4" source = "registry+https://github.com/rust-lang/crates.io-index" +checksum = "cd179ae861f0c2e53da70d892f5f3029f9594be0c41dc5269cd371691b1dc2f9" [[package]] name = "httpdate" version = "0.3.2" source = "registry+https://github.com/rust-lang/crates.io-index" +checksum = "494b4d60369511e7dea41cf646832512a94e542f68bb9c49e54518e0f468eb47" [[package]] name = "humantime" version = "1.3.0" source = "registry+https://github.com/rust-lang/crates.io-index" +checksum = "df004cfca50ef23c36850aaaa59ad52cc70d0e90243c3c7737a4dd32dc7a3c4f" dependencies = [ - "quick-error 1.2.3 (registry+https://github.com/rust-lang/crates.io-index)", + "quick-error", ] [[package]] name = "hyper" version = "0.10.16" source = "registry+https://github.com/rust-lang/crates.io-index" +checksum = "0a0652d9a2609a968c14be1a9ea00bf4b1d64e2e1f53a1b51b6fff3a6e829273" dependencies = [ - "base64 0.9.3 (registry+https://github.com/rust-lang/crates.io-index)", - "httparse 1.3.4 (registry+https://github.com/rust-lang/crates.io-index)", - "language-tags 0.2.2 (registry+https://github.com/rust-lang/crates.io-index)", - "log 0.3.9 (registry+https://github.com/rust-lang/crates.io-index)", - "mime 0.2.6 (registry+https://github.com/rust-lang/crates.io-index)", - "num_cpus 1.13.0 (registry+https://github.com/rust-lang/crates.io-index)", - "time 0.1.44 (registry+https://github.com/rust-lang/crates.io-index)", - "traitobject 0.1.0 (registry+https://github.com/rust-lang/crates.io-index)", - "typeable 0.1.2 (registry+https://github.com/rust-lang/crates.io-index)", - "unicase 1.4.2 (registry+https://github.com/rust-lang/crates.io-index)", - "url 1.7.2 (registry+https://github.com/rust-lang/crates.io-index)", + "base64 0.9.3", + "httparse", + "language-tags", + "log 0.3.9", + "mime 0.2.6", + "num_cpus", + "time 0.1.44", + "traitobject", + "typeable", + "unicase 1.4.2", + "url 1.7.2", ] [[package]] name = "hyper" version = "0.12.35" source = "registry+https://github.com/rust-lang/crates.io-index" -dependencies = [ - "bytes 0.4.12 (registry+https://github.com/rust-lang/crates.io-index)", - "futures 0.1.29 (registry+https://github.com/rust-lang/crates.io-index)", - "futures-cpupool 0.1.8 (registry+https://github.com/rust-lang/crates.io-index)", - "h2 0.1.26 (registry+https://github.com/rust-lang/crates.io-index)", - "http 0.1.21 (registry+https://github.com/rust-lang/crates.io-index)", - "http-body 0.1.0 (registry+https://github.com/rust-lang/crates.io-index)", - "httparse 1.3.4 (registry+https://github.com/rust-lang/crates.io-index)", - "iovec 0.1.4 (registry+https://github.com/rust-lang/crates.io-index)", - "itoa 0.4.6 (registry+https://github.com/rust-lang/crates.io-index)", - "log 0.4.11 (registry+https://github.com/rust-lang/crates.io-index)", - "net2 0.2.35 (registry+https://github.com/rust-lang/crates.io-index)", - "rustc_version 0.2.3 (registry+https://github.com/rust-lang/crates.io-index)", - "time 0.1.44 (registry+https://github.com/rust-lang/crates.io-index)", - "tokio 0.1.22 (registry+https://github.com/rust-lang/crates.io-index)", - "tokio-buf 0.1.1 (registry+https://github.com/rust-lang/crates.io-index)", - "tokio-executor 0.1.10 (registry+https://github.com/rust-lang/crates.io-index)", - "tokio-io 0.1.13 (registry+https://github.com/rust-lang/crates.io-index)", - "tokio-reactor 0.1.12 (registry+https://github.com/rust-lang/crates.io-index)", - "tokio-tcp 0.1.4 (registry+https://github.com/rust-lang/crates.io-index)", - "tokio-threadpool 0.1.18 (registry+https://github.com/rust-lang/crates.io-index)", - "tokio-timer 0.2.13 (registry+https://github.com/rust-lang/crates.io-index)", - "want 0.2.0 (registry+https://github.com/rust-lang/crates.io-index)", +checksum = "9dbe6ed1438e1f8ad955a4701e9a944938e9519f6888d12d8558b645e247d5f6" +dependencies = [ + "bytes 0.4.12", + "futures 0.1.29", + "futures-cpupool", + "h2 0.1.26", + "http 0.1.21", + "http-body 0.1.0", + "httparse", + "iovec", + "itoa", + "log 0.4.11", + "net2", + "rustc_version", + "time 0.1.44", + "tokio 0.1.22", + "tokio-buf", + "tokio-executor", + "tokio-io", + "tokio-reactor", + "tokio-tcp", + "tokio-threadpool", + "tokio-timer 0.2.13", + "want 0.2.0", ] [[package]] name = "hyper" version = "0.13.8" source = "registry+https://github.com/rust-lang/crates.io-index" +checksum = "2f3afcfae8af5ad0576a31e768415edb627824129e8e5a29b8bfccb2f234e835" dependencies = [ - "bytes 0.5.6 (registry+https://github.com/rust-lang/crates.io-index)", - "futures-channel 0.3.5 (registry+https://github.com/rust-lang/crates.io-index)", - "futures-core 0.3.5 (registry+https://github.com/rust-lang/crates.io-index)", - "futures-util 0.3.5 (registry+https://github.com/rust-lang/crates.io-index)", - "h2 0.2.6 (registry+https://github.com/rust-lang/crates.io-index)", - "http 0.2.1 (registry+https://github.com/rust-lang/crates.io-index)", - "http-body 0.3.1 (registry+https://github.com/rust-lang/crates.io-index)", - "httparse 1.3.4 (registry+https://github.com/rust-lang/crates.io-index)", - "httpdate 0.3.2 (registry+https://github.com/rust-lang/crates.io-index)", - "itoa 0.4.6 (registry+https://github.com/rust-lang/crates.io-index)", - "pin-project 0.4.24 (registry+https://github.com/rust-lang/crates.io-index)", - "socket2 0.3.15 (registry+https://github.com/rust-lang/crates.io-index)", - "tokio 0.2.22 (registry+https://github.com/rust-lang/crates.io-index)", - "tower-service 0.3.0 (registry+https://github.com/rust-lang/crates.io-index)", - "tracing 0.1.19 (registry+https://github.com/rust-lang/crates.io-index)", - "want 0.3.0 (registry+https://github.com/rust-lang/crates.io-index)", + "bytes 0.5.6", + "futures-channel", + "futures-core", + "futures-util", + "h2 0.2.6", + "http 0.2.1", + "http-body 0.3.1", + "httparse", + "httpdate", + "itoa", + "pin-project", + "socket2", + "tokio 0.2.22", + "tower-service", + "tracing", + "want 0.3.0", ] [[package]] name = "hyper-tls" version = "0.3.2" source = "registry+https://github.com/rust-lang/crates.io-index" +checksum = "3a800d6aa50af4b5850b2b0f659625ce9504df908e9733b635720483be26174f" dependencies = [ - "bytes 0.4.12 (registry+https://github.com/rust-lang/crates.io-index)", - "futures 0.1.29 (registry+https://github.com/rust-lang/crates.io-index)", - "hyper 0.12.35 (registry+https://github.com/rust-lang/crates.io-index)", - "native-tls 0.2.4 (registry+https://github.com/rust-lang/crates.io-index)", - "tokio-io 0.1.13 (registry+https://github.com/rust-lang/crates.io-index)", + "bytes 0.4.12", + "futures 0.1.29", + "hyper 0.12.35", + "native-tls", + "tokio-io", ] [[package]] name = "hyper-tls" version = "0.4.3" source = "registry+https://github.com/rust-lang/crates.io-index" +checksum = "d979acc56dcb5b8dddba3917601745e877576475aa046df3226eabdecef78eed" dependencies = [ - "bytes 0.5.6 (registry+https://github.com/rust-lang/crates.io-index)", - "hyper 0.13.8 (registry+https://github.com/rust-lang/crates.io-index)", - "native-tls 0.2.4 (registry+https://github.com/rust-lang/crates.io-index)", - "tokio 0.2.22 (registry+https://github.com/rust-lang/crates.io-index)", - "tokio-tls 0.3.1 (registry+https://github.com/rust-lang/crates.io-index)", + "bytes 0.5.6", + "hyper 0.13.8", + "native-tls", + "tokio 0.2.22", + "tokio-tls 0.3.1", ] [[package]] name = "idna" version = "0.1.5" source = "registry+https://github.com/rust-lang/crates.io-index" +checksum = "38f09e0f0b1fb55fdee1f17470ad800da77af5186a1a76c026b679358b7e844e" dependencies = [ - "matches 0.1.8 (registry+https://github.com/rust-lang/crates.io-index)", - "unicode-bidi 0.3.4 (registry+https://github.com/rust-lang/crates.io-index)", - "unicode-normalization 0.1.13 (registry+https://github.com/rust-lang/crates.io-index)", + "matches", + "unicode-bidi", + "unicode-normalization", ] [[package]] name = "idna" version = "0.2.0" source = "registry+https://github.com/rust-lang/crates.io-index" +checksum = "02e2673c30ee86b5b96a9cb52ad15718aa1f966f5ab9ad54a8b95d5ca33120a9" dependencies = [ - "matches 0.1.8 (registry+https://github.com/rust-lang/crates.io-index)", - "unicode-bidi 0.3.4 (registry+https://github.com/rust-lang/crates.io-index)", - "unicode-normalization 0.1.13 (registry+https://github.com/rust-lang/crates.io-index)", + "matches", + "unicode-bidi", + "unicode-normalization", ] [[package]] name = "impl-codec" version = "0.4.2" source = "registry+https://github.com/rust-lang/crates.io-index" +checksum = "1be51a921b067b0eaca2fad532d9400041561aa922221cc65f95a85641c6bf53" dependencies = [ - "parity-scale-codec 1.3.5 (registry+https://github.com/rust-lang/crates.io-index)", + "parity-scale-codec", ] [[package]] name = "impl-rlp" version = "0.2.1" source = "registry+https://github.com/rust-lang/crates.io-index" +checksum = "8f7a72f11830b52333f36e3b09a288333888bf54380fd0ac0790a3c31ab0f3c5" dependencies = [ - "rlp 0.4.5 (registry+https://github.com/rust-lang/crates.io-index)", + "rlp", ] [[package]] name = "impl-serde" version = "0.3.1" source = "registry+https://github.com/rust-lang/crates.io-index" +checksum = "b47ca4d2b6931707a55fce5cf66aff80e2178c8b63bbb4ecb5695cbc870ddf6f" dependencies = [ - "serde 1.0.116 (registry+https://github.com/rust-lang/crates.io-index)", + "serde", ] [[package]] name = "indexmap" version = "1.6.0" source = "registry+https://github.com/rust-lang/crates.io-index" +checksum = "55e2e4c765aa53a0424761bf9f41aa7a6ac1efa87238f59560640e27fca028f2" +dependencies = [ + "autocfg 1.0.1", + "hashbrown 0.9.0", +] + +[[package]] +name = "input_buffer" +version = "0.3.1" +source = "registry+https://github.com/rust-lang/crates.io-index" +checksum = "19a8a95243d5a0398cae618ec29477c6e3cb631152be5c19481f80bc71559754" dependencies = [ - "autocfg 1.0.1 (registry+https://github.com/rust-lang/crates.io-index)", - "hashbrown 0.9.0 (registry+https://github.com/rust-lang/crates.io-index)", + "bytes 0.5.6", ] [[package]] name = "instant" version = "0.1.7" source = "registry+https://github.com/rust-lang/crates.io-index" +checksum = "63312a18f7ea8760cdd0a7c5aac1a619752a246b833545e3e36d1f81f7cd9e66" dependencies = [ - "cfg-if 0.1.10 (registry+https://github.com/rust-lang/crates.io-index)", + "cfg-if", ] [[package]] name = "int_to_bytes" version = "0.2.0" dependencies = [ - "bytes 0.5.6 (registry+https://github.com/rust-lang/crates.io-index)", - "hex 0.4.2 (registry+https://github.com/rust-lang/crates.io-index)", - "yaml-rust 0.4.4 (registry+https://github.com/rust-lang/crates.io-index)", + "bytes 0.5.6", + "hex 0.4.2", + "yaml-rust", ] [[package]] name = "integer-sqrt" version = "0.1.5" source = "registry+https://github.com/rust-lang/crates.io-index" +checksum = "276ec31bcb4a9ee45f58bec6f9ec700ae4cf4f4f8f2fa7e06cb406bd5ffdd770" dependencies = [ - "num-traits 0.2.12 (registry+https://github.com/rust-lang/crates.io-index)", + "num-traits", ] [[package]] name = "iovec" version = "0.1.4" source = "registry+https://github.com/rust-lang/crates.io-index" +checksum = "b2b3ea6ff95e175473f8ffe6a7eb7c00d054240321b84c57051175fe3c1e075e" dependencies = [ - "libc 0.2.77 (registry+https://github.com/rust-lang/crates.io-index)", + "libc", ] [[package]] name = "ipnet" version = "2.3.0" source = "registry+https://github.com/rust-lang/crates.io-index" +checksum = "47be2f14c678be2fdcab04ab1171db51b2762ce6f0a8ee87c8dd4a04ed216135" [[package]] name = "itertools" version = "0.8.2" source = "registry+https://github.com/rust-lang/crates.io-index" +checksum = "f56a2d0bc861f9165be4eb3442afd3c236d8a98afd426f65d92324ae1091a484" dependencies = [ - "either 1.6.1 (registry+https://github.com/rust-lang/crates.io-index)", + "either", ] [[package]] name = "itertools" version = "0.9.0" source = "registry+https://github.com/rust-lang/crates.io-index" +checksum = "284f18f85651fe11e8a991b2adb42cb078325c996ed026d994719efcfca1d54b" dependencies = [ - "either 1.6.1 (registry+https://github.com/rust-lang/crates.io-index)", + "either", ] [[package]] name = "itoa" version = "0.4.6" source = "registry+https://github.com/rust-lang/crates.io-index" +checksum = "dc6f3ad7b9d11a0c00842ff8de1b60ee58661048eb8049ed33c73594f359d7e6" [[package]] name = "js-sys" version = "0.3.45" source = "registry+https://github.com/rust-lang/crates.io-index" +checksum = "ca059e81d9486668f12d455a4ea6daa600bd408134cd17e3d3fb5a32d1f016f8" dependencies = [ - "wasm-bindgen 0.2.68 (registry+https://github.com/rust-lang/crates.io-index)", + "wasm-bindgen", ] [[package]] name = "jsonrpc-core" version = "14.2.0" source = "registry+https://github.com/rust-lang/crates.io-index" +checksum = "a0747307121ffb9703afd93afbd0fb4f854c38fb873f2c8b90e0e902f27c7b62" dependencies = [ - "futures 0.1.29 (registry+https://github.com/rust-lang/crates.io-index)", - "log 0.4.11 (registry+https://github.com/rust-lang/crates.io-index)", - "serde 1.0.116 (registry+https://github.com/rust-lang/crates.io-index)", - "serde_derive 1.0.116 (registry+https://github.com/rust-lang/crates.io-index)", - "serde_json 1.0.57 (registry+https://github.com/rust-lang/crates.io-index)", + "futures 0.1.29", + "log 0.4.11", + "serde", + "serde_derive", + "serde_json", ] [[package]] name = "keccak" version = "0.1.0" source = "registry+https://github.com/rust-lang/crates.io-index" +checksum = "67c21572b4949434e4fc1e1978b99c5f77064153c59d998bf13ecd96fb5ecba7" [[package]] name = "kernel32-sys" version = "0.2.2" source = "registry+https://github.com/rust-lang/crates.io-index" +checksum = "7507624b29483431c0ba2d82aece8ca6cdba9382bff4ddd0f7490560c056098d" dependencies = [ - "winapi 0.2.8 (registry+https://github.com/rust-lang/crates.io-index)", - "winapi-build 0.1.1 (registry+https://github.com/rust-lang/crates.io-index)", + "winapi 0.2.8", + "winapi-build", ] [[package]] name = "language-tags" version = "0.2.2" source = "registry+https://github.com/rust-lang/crates.io-index" +checksum = "a91d884b6667cd606bb5a69aa0c99ba811a115fc68915e7056ec08a46e93199a" [[package]] name = "lazy_static" version = "1.4.0" source = "registry+https://github.com/rust-lang/crates.io-index" +checksum = "e2abad23fbc42b3700f2f279844dc832adb2b2eb069b2df918f455c4e18cc646" dependencies = [ - "spin 0.5.2 (registry+https://github.com/rust-lang/crates.io-index)", + "spin", ] [[package]] name = "lazycell" version = "1.3.0" source = "registry+https://github.com/rust-lang/crates.io-index" +checksum = "830d08ce1d1d941e6b30645f1a0eb5643013d835ce3779a5fc208261dbe10f55" [[package]] name = "lcli" version = "0.2.12" dependencies = [ - "bls 0.2.0", - "clap 2.33.3 (registry+https://github.com/rust-lang/crates.io-index)", - "clap_utils 0.1.0", - "deposit_contract 0.2.0", - "directory 0.1.0", - "dirs 2.0.2 (registry+https://github.com/rust-lang/crates.io-index)", - "environment 0.1.2", - "eth2_keystore 0.1.0", - "eth2_libp2p 0.2.0", - "eth2_ssz 0.1.2", - "eth2_testnet_config 0.2.0", - "futures 0.3.5 (registry+https://github.com/rust-lang/crates.io-index)", - "genesis 0.2.0", - "hex 0.4.2 (registry+https://github.com/rust-lang/crates.io-index)", - "lighthouse_version 0.1.0", - "log 0.4.11 (registry+https://github.com/rust-lang/crates.io-index)", - "rand 0.7.3 (registry+https://github.com/rust-lang/crates.io-index)", - "regex 1.3.9 (registry+https://github.com/rust-lang/crates.io-index)", - "serde 1.0.116 (registry+https://github.com/rust-lang/crates.io-index)", - "serde_yaml 0.8.13 (registry+https://github.com/rust-lang/crates.io-index)", - "simple_logger 1.9.0 (registry+https://github.com/rust-lang/crates.io-index)", - "state_processing 0.2.0", - "tokio 0.2.22 (registry+https://github.com/rust-lang/crates.io-index)", - "tree_hash 0.1.1", - "types 0.2.0", - "validator_dir 0.1.0", - "web3 0.11.0 (registry+https://github.com/rust-lang/crates.io-index)", + "bls", + "clap", + "clap_utils", + "deposit_contract", + "directory", + "dirs", + "environment", + "eth2_keystore", + "eth2_libp2p", + "eth2_ssz", + "eth2_testnet_config", + "futures 0.3.5", + "genesis", + "hex 0.4.2", + "lighthouse_version", + "log 0.4.11", + "rand 0.7.3", + "regex", + "serde", + "serde_yaml", + "simple_logger", + "state_processing", + "tokio 0.2.22", + "tree_hash", + "types", + "validator_dir", + "web3", ] [[package]] name = "leveldb" version = "0.8.6" source = "registry+https://github.com/rust-lang/crates.io-index" +checksum = "32651baaaa5596b3a6e0bee625e73fd0334c167db0ea5ac68750ef9a629a2d6a" dependencies = [ - "db-key 0.0.5 (registry+https://github.com/rust-lang/crates.io-index)", - "leveldb-sys 2.0.7 (registry+https://github.com/rust-lang/crates.io-index)", - "libc 0.2.77 (registry+https://github.com/rust-lang/crates.io-index)", + "db-key", + "leveldb-sys", + "libc", ] [[package]] name = "leveldb-sys" version = "2.0.7" source = "registry+https://github.com/rust-lang/crates.io-index" +checksum = "76c44b9b785ca705d58190ebd432a4e7edb900eadf236ff966d7d1307e482e87" dependencies = [ - "cmake 0.1.44 (registry+https://github.com/rust-lang/crates.io-index)", - "libc 0.2.77 (registry+https://github.com/rust-lang/crates.io-index)", - "num_cpus 1.13.0 (registry+https://github.com/rust-lang/crates.io-index)", + "cmake", + "libc", + "num_cpus", ] [[package]] name = "libc" version = "0.2.77" source = "registry+https://github.com/rust-lang/crates.io-index" +checksum = "f2f96b10ec2560088a8e76961b00d47107b3a625fecb76dedb29ee7ccbf98235" [[package]] name = "libflate" version = "1.0.2" source = "registry+https://github.com/rust-lang/crates.io-index" +checksum = "e9bac9023e1db29c084f9f8cd9d3852e5e8fddf98fb47c4964a0ea4663d95949" dependencies = [ - "adler32 1.2.0 (registry+https://github.com/rust-lang/crates.io-index)", - "crc32fast 1.2.0 (registry+https://github.com/rust-lang/crates.io-index)", - "libflate_lz77 1.0.0 (registry+https://github.com/rust-lang/crates.io-index)", - "rle-decode-fast 1.0.1 (registry+https://github.com/rust-lang/crates.io-index)", + "adler32", + "crc32fast", + "libflate_lz77", + "rle-decode-fast", ] [[package]] name = "libflate_lz77" version = "1.0.0" source = "registry+https://github.com/rust-lang/crates.io-index" +checksum = "3286f09f7d4926fc486334f28d8d2e6ebe4f7f9994494b6dab27ddfad2c9b11b" [[package]] name = "libm" version = "0.2.1" source = "registry+https://github.com/rust-lang/crates.io-index" +checksum = "c7d73b3f436185384286bd8098d17ec07c9a7d2388a6599f824d8502b529702a" [[package]] name = "libp2p" version = "0.25.0" source = "git+https://github.com/sigp/rust-libp2p?rev=03f998022ce2f566a6c6e6c4206bc0ce4d45109f#03f998022ce2f566a6c6e6c4206bc0ce4d45109f" dependencies = [ - "atomic 0.4.6 (registry+https://github.com/rust-lang/crates.io-index)", - "bytes 0.5.6 (registry+https://github.com/rust-lang/crates.io-index)", - "futures 0.3.5 (registry+https://github.com/rust-lang/crates.io-index)", - "lazy_static 1.4.0 (registry+https://github.com/rust-lang/crates.io-index)", - "libp2p-core 0.21.0 (git+https://github.com/sigp/rust-libp2p?rev=03f998022ce2f566a6c6e6c4206bc0ce4d45109f)", - "libp2p-core-derive 0.20.2 (git+https://github.com/sigp/rust-libp2p?rev=03f998022ce2f566a6c6e6c4206bc0ce4d45109f)", - "libp2p-dns 0.21.0 (git+https://github.com/sigp/rust-libp2p?rev=03f998022ce2f566a6c6e6c4206bc0ce4d45109f)", - "libp2p-gossipsub 0.22.0 (git+https://github.com/sigp/rust-libp2p?rev=03f998022ce2f566a6c6e6c4206bc0ce4d45109f)", - "libp2p-identify 0.22.0 (git+https://github.com/sigp/rust-libp2p?rev=03f998022ce2f566a6c6e6c4206bc0ce4d45109f)", - "libp2p-mplex 0.21.0 (git+https://github.com/sigp/rust-libp2p?rev=03f998022ce2f566a6c6e6c4206bc0ce4d45109f)", - "libp2p-noise 0.23.0 (git+https://github.com/sigp/rust-libp2p?rev=03f998022ce2f566a6c6e6c4206bc0ce4d45109f)", - "libp2p-swarm 0.22.0 (git+https://github.com/sigp/rust-libp2p?rev=03f998022ce2f566a6c6e6c4206bc0ce4d45109f)", - "libp2p-tcp 0.21.0 (git+https://github.com/sigp/rust-libp2p?rev=03f998022ce2f566a6c6e6c4206bc0ce4d45109f)", - "libp2p-websocket 0.22.0 (git+https://github.com/sigp/rust-libp2p?rev=03f998022ce2f566a6c6e6c4206bc0ce4d45109f)", - "multihash 0.11.4 (registry+https://github.com/rust-lang/crates.io-index)", - "parity-multiaddr 0.9.1 (git+https://github.com/sigp/rust-libp2p?rev=03f998022ce2f566a6c6e6c4206bc0ce4d45109f)", - "parking_lot 0.10.2 (registry+https://github.com/rust-lang/crates.io-index)", - "pin-project 0.4.24 (registry+https://github.com/rust-lang/crates.io-index)", - "smallvec 1.4.2 (registry+https://github.com/rust-lang/crates.io-index)", - "wasm-timer 0.2.5 (registry+https://github.com/rust-lang/crates.io-index)", + "atomic", + "bytes 0.5.6", + "futures 0.3.5", + "lazy_static", + "libp2p-core 0.21.0", + "libp2p-core-derive", + "libp2p-dns", + "libp2p-gossipsub", + "libp2p-identify", + "libp2p-mplex", + "libp2p-noise", + "libp2p-swarm", + "libp2p-tcp", + "libp2p-websocket", + "multihash", + "parity-multiaddr 0.9.1", + "parking_lot 0.10.2", + "pin-project", + "smallvec 1.4.2", + "wasm-timer", ] [[package]] @@ -2482,65 +2799,66 @@ name = "libp2p-core" version = "0.21.0" source = "git+https://github.com/sigp/rust-libp2p?rev=03f998022ce2f566a6c6e6c4206bc0ce4d45109f#03f998022ce2f566a6c6e6c4206bc0ce4d45109f" dependencies = [ - "asn1_der 0.6.3 (registry+https://github.com/rust-lang/crates.io-index)", - "bs58 0.3.1 (registry+https://github.com/rust-lang/crates.io-index)", - "ed25519-dalek 1.0.1 (registry+https://github.com/rust-lang/crates.io-index)", - "either 1.6.1 (registry+https://github.com/rust-lang/crates.io-index)", - "fnv 1.0.7 (registry+https://github.com/rust-lang/crates.io-index)", - "futures 0.3.5 (registry+https://github.com/rust-lang/crates.io-index)", - "futures-timer 3.0.2 (registry+https://github.com/rust-lang/crates.io-index)", - "lazy_static 1.4.0 (registry+https://github.com/rust-lang/crates.io-index)", - "libsecp256k1 0.3.5 (registry+https://github.com/rust-lang/crates.io-index)", - "log 0.4.11 (registry+https://github.com/rust-lang/crates.io-index)", - "multihash 0.11.4 (registry+https://github.com/rust-lang/crates.io-index)", + "asn1_der", + "bs58", + "ed25519-dalek", + "either", + "fnv", + "futures 0.3.5", + "futures-timer", + "lazy_static", + "libsecp256k1", + "log 0.4.11", + "multihash", "multistream-select 0.8.2 (git+https://github.com/sigp/rust-libp2p?rev=03f998022ce2f566a6c6e6c4206bc0ce4d45109f)", - "parity-multiaddr 0.9.1 (git+https://github.com/sigp/rust-libp2p?rev=03f998022ce2f566a6c6e6c4206bc0ce4d45109f)", - "parking_lot 0.10.2 (registry+https://github.com/rust-lang/crates.io-index)", - "pin-project 0.4.24 (registry+https://github.com/rust-lang/crates.io-index)", - "prost 0.6.1 (registry+https://github.com/rust-lang/crates.io-index)", - "prost-build 0.6.1 (registry+https://github.com/rust-lang/crates.io-index)", - "rand 0.7.3 (registry+https://github.com/rust-lang/crates.io-index)", - "ring 0.16.12 (registry+https://github.com/rust-lang/crates.io-index)", - "rw-stream-sink 0.2.1 (registry+https://github.com/rust-lang/crates.io-index)", - "sha2 0.8.2 (registry+https://github.com/rust-lang/crates.io-index)", - "smallvec 1.4.2 (registry+https://github.com/rust-lang/crates.io-index)", - "thiserror 1.0.20 (registry+https://github.com/rust-lang/crates.io-index)", - "unsigned-varint 0.4.0 (registry+https://github.com/rust-lang/crates.io-index)", - "void 1.0.2 (registry+https://github.com/rust-lang/crates.io-index)", - "zeroize 1.1.1 (registry+https://github.com/rust-lang/crates.io-index)", + "parity-multiaddr 0.9.1", + "parking_lot 0.10.2", + "pin-project", + "prost", + "prost-build", + "rand 0.7.3", + "ring", + "rw-stream-sink", + "sha2 0.8.2", + "smallvec 1.4.2", + "thiserror", + "unsigned-varint 0.4.0", + "void", + "zeroize", ] [[package]] name = "libp2p-core" version = "0.22.1" source = "registry+https://github.com/rust-lang/crates.io-index" -dependencies = [ - "asn1_der 0.6.3 (registry+https://github.com/rust-lang/crates.io-index)", - "bs58 0.3.1 (registry+https://github.com/rust-lang/crates.io-index)", - "ed25519-dalek 1.0.1 (registry+https://github.com/rust-lang/crates.io-index)", - "either 1.6.1 (registry+https://github.com/rust-lang/crates.io-index)", - "fnv 1.0.7 (registry+https://github.com/rust-lang/crates.io-index)", - "futures 0.3.5 (registry+https://github.com/rust-lang/crates.io-index)", - "futures-timer 3.0.2 (registry+https://github.com/rust-lang/crates.io-index)", - "lazy_static 1.4.0 (registry+https://github.com/rust-lang/crates.io-index)", - "libsecp256k1 0.3.5 (registry+https://github.com/rust-lang/crates.io-index)", - "log 0.4.11 (registry+https://github.com/rust-lang/crates.io-index)", - "multihash 0.11.4 (registry+https://github.com/rust-lang/crates.io-index)", +checksum = "52f13ba8c7df0768af2eb391696d562c7de88cc3a35122531aaa6a7d77754d25" +dependencies = [ + "asn1_der", + "bs58", + "ed25519-dalek", + "either", + "fnv", + "futures 0.3.5", + "futures-timer", + "lazy_static", + "libsecp256k1", + "log 0.4.11", + "multihash", "multistream-select 0.8.2 (registry+https://github.com/rust-lang/crates.io-index)", - "parity-multiaddr 0.9.2 (registry+https://github.com/rust-lang/crates.io-index)", - "parking_lot 0.10.2 (registry+https://github.com/rust-lang/crates.io-index)", - "pin-project 0.4.24 (registry+https://github.com/rust-lang/crates.io-index)", - "prost 0.6.1 (registry+https://github.com/rust-lang/crates.io-index)", - "prost-build 0.6.1 (registry+https://github.com/rust-lang/crates.io-index)", - "rand 0.7.3 (registry+https://github.com/rust-lang/crates.io-index)", - "ring 0.16.12 (registry+https://github.com/rust-lang/crates.io-index)", - "rw-stream-sink 0.2.1 (registry+https://github.com/rust-lang/crates.io-index)", - "sha2 0.8.2 (registry+https://github.com/rust-lang/crates.io-index)", - "smallvec 1.4.2 (registry+https://github.com/rust-lang/crates.io-index)", - "thiserror 1.0.20 (registry+https://github.com/rust-lang/crates.io-index)", - "unsigned-varint 0.4.0 (registry+https://github.com/rust-lang/crates.io-index)", - "void 1.0.2 (registry+https://github.com/rust-lang/crates.io-index)", - "zeroize 1.1.1 (registry+https://github.com/rust-lang/crates.io-index)", + "parity-multiaddr 0.9.2", + "parking_lot 0.10.2", + "pin-project", + "prost", + "prost-build", + "rand 0.7.3", + "ring", + "rw-stream-sink", + "sha2 0.8.2", + "smallvec 1.4.2", + "thiserror", + "unsigned-varint 0.4.0", + "void", + "zeroize", ] [[package]] @@ -2548,8 +2866,8 @@ name = "libp2p-core-derive" version = "0.20.2" source = "git+https://github.com/sigp/rust-libp2p?rev=03f998022ce2f566a6c6e6c4206bc0ce4d45109f#03f998022ce2f566a6c6e6c4206bc0ce4d45109f" dependencies = [ - "quote 1.0.7 (registry+https://github.com/rust-lang/crates.io-index)", - "syn 1.0.42 (registry+https://github.com/rust-lang/crates.io-index)", + "quote", + "syn", ] [[package]] @@ -2557,9 +2875,9 @@ name = "libp2p-dns" version = "0.21.0" source = "git+https://github.com/sigp/rust-libp2p?rev=03f998022ce2f566a6c6e6c4206bc0ce4d45109f#03f998022ce2f566a6c6e6c4206bc0ce4d45109f" dependencies = [ - "futures 0.3.5 (registry+https://github.com/rust-lang/crates.io-index)", - "libp2p-core 0.21.0 (git+https://github.com/sigp/rust-libp2p?rev=03f998022ce2f566a6c6e6c4206bc0ce4d45109f)", - "log 0.4.11 (registry+https://github.com/rust-lang/crates.io-index)", + "futures 0.3.5", + "libp2p-core 0.21.0", + "log 0.4.11", ] [[package]] @@ -2567,23 +2885,23 @@ name = "libp2p-gossipsub" version = "0.22.0" source = "git+https://github.com/sigp/rust-libp2p?rev=03f998022ce2f566a6c6e6c4206bc0ce4d45109f#03f998022ce2f566a6c6e6c4206bc0ce4d45109f" dependencies = [ - "base64 0.12.3 (registry+https://github.com/rust-lang/crates.io-index)", - "byteorder 1.3.4 (registry+https://github.com/rust-lang/crates.io-index)", - "bytes 0.5.6 (registry+https://github.com/rust-lang/crates.io-index)", - "fnv 1.0.7 (registry+https://github.com/rust-lang/crates.io-index)", - "futures 0.3.5 (registry+https://github.com/rust-lang/crates.io-index)", - "futures_codec 0.4.1 (registry+https://github.com/rust-lang/crates.io-index)", - "hex_fmt 0.3.0 (registry+https://github.com/rust-lang/crates.io-index)", - "libp2p-core 0.21.0 (git+https://github.com/sigp/rust-libp2p?rev=03f998022ce2f566a6c6e6c4206bc0ce4d45109f)", - "libp2p-swarm 0.22.0 (git+https://github.com/sigp/rust-libp2p?rev=03f998022ce2f566a6c6e6c4206bc0ce4d45109f)", - "log 0.4.11 (registry+https://github.com/rust-lang/crates.io-index)", - "prost 0.6.1 (registry+https://github.com/rust-lang/crates.io-index)", - "prost-build 0.6.1 (registry+https://github.com/rust-lang/crates.io-index)", - "rand 0.7.3 (registry+https://github.com/rust-lang/crates.io-index)", - "sha2 0.9.1 (registry+https://github.com/rust-lang/crates.io-index)", - "smallvec 1.4.2 (registry+https://github.com/rust-lang/crates.io-index)", - "unsigned-varint 0.5.1 (registry+https://github.com/rust-lang/crates.io-index)", - "wasm-timer 0.2.5 (registry+https://github.com/rust-lang/crates.io-index)", + "base64 0.12.3", + "byteorder", + "bytes 0.5.6", + "fnv", + "futures 0.3.5", + "futures_codec", + "hex_fmt", + "libp2p-core 0.21.0", + "libp2p-swarm", + "log 0.4.11", + "prost", + "prost-build", + "rand 0.7.3", + "sha2 0.9.1", + "smallvec 1.4.2", + "unsigned-varint 0.5.1", + "wasm-timer", ] [[package]] @@ -2591,14 +2909,14 @@ name = "libp2p-identify" version = "0.22.0" source = "git+https://github.com/sigp/rust-libp2p?rev=03f998022ce2f566a6c6e6c4206bc0ce4d45109f#03f998022ce2f566a6c6e6c4206bc0ce4d45109f" dependencies = [ - "futures 0.3.5 (registry+https://github.com/rust-lang/crates.io-index)", - "libp2p-core 0.21.0 (git+https://github.com/sigp/rust-libp2p?rev=03f998022ce2f566a6c6e6c4206bc0ce4d45109f)", - "libp2p-swarm 0.22.0 (git+https://github.com/sigp/rust-libp2p?rev=03f998022ce2f566a6c6e6c4206bc0ce4d45109f)", - "log 0.4.11 (registry+https://github.com/rust-lang/crates.io-index)", - "prost 0.6.1 (registry+https://github.com/rust-lang/crates.io-index)", - "prost-build 0.6.1 (registry+https://github.com/rust-lang/crates.io-index)", - "smallvec 1.4.2 (registry+https://github.com/rust-lang/crates.io-index)", - "wasm-timer 0.2.5 (registry+https://github.com/rust-lang/crates.io-index)", + "futures 0.3.5", + "libp2p-core 0.21.0", + "libp2p-swarm", + "log 0.4.11", + "prost", + "prost-build", + "smallvec 1.4.2", + "wasm-timer", ] [[package]] @@ -2606,14 +2924,14 @@ name = "libp2p-mplex" version = "0.21.0" source = "git+https://github.com/sigp/rust-libp2p?rev=03f998022ce2f566a6c6e6c4206bc0ce4d45109f#03f998022ce2f566a6c6e6c4206bc0ce4d45109f" dependencies = [ - "bytes 0.5.6 (registry+https://github.com/rust-lang/crates.io-index)", - "fnv 1.0.7 (registry+https://github.com/rust-lang/crates.io-index)", - "futures 0.3.5 (registry+https://github.com/rust-lang/crates.io-index)", - "futures_codec 0.4.1 (registry+https://github.com/rust-lang/crates.io-index)", - "libp2p-core 0.21.0 (git+https://github.com/sigp/rust-libp2p?rev=03f998022ce2f566a6c6e6c4206bc0ce4d45109f)", - "log 0.4.11 (registry+https://github.com/rust-lang/crates.io-index)", - "parking_lot 0.10.2 (registry+https://github.com/rust-lang/crates.io-index)", - "unsigned-varint 0.4.0 (registry+https://github.com/rust-lang/crates.io-index)", + "bytes 0.5.6", + "fnv", + "futures 0.3.5", + "futures_codec", + "libp2p-core 0.21.0", + "log 0.4.11", + "parking_lot 0.10.2", + "unsigned-varint 0.4.0", ] [[package]] @@ -2621,20 +2939,20 @@ name = "libp2p-noise" version = "0.23.0" source = "git+https://github.com/sigp/rust-libp2p?rev=03f998022ce2f566a6c6e6c4206bc0ce4d45109f#03f998022ce2f566a6c6e6c4206bc0ce4d45109f" dependencies = [ - "bytes 0.5.6 (registry+https://github.com/rust-lang/crates.io-index)", - "curve25519-dalek 2.1.0 (registry+https://github.com/rust-lang/crates.io-index)", - "futures 0.3.5 (registry+https://github.com/rust-lang/crates.io-index)", - "lazy_static 1.4.0 (registry+https://github.com/rust-lang/crates.io-index)", - "libp2p-core 0.21.0 (git+https://github.com/sigp/rust-libp2p?rev=03f998022ce2f566a6c6e6c4206bc0ce4d45109f)", - "log 0.4.11 (registry+https://github.com/rust-lang/crates.io-index)", - "prost 0.6.1 (registry+https://github.com/rust-lang/crates.io-index)", - "prost-build 0.6.1 (registry+https://github.com/rust-lang/crates.io-index)", - "rand 0.7.3 (registry+https://github.com/rust-lang/crates.io-index)", - "sha2 0.8.2 (registry+https://github.com/rust-lang/crates.io-index)", - "snow 0.7.1 (registry+https://github.com/rust-lang/crates.io-index)", - "static_assertions 1.1.0 (registry+https://github.com/rust-lang/crates.io-index)", - "x25519-dalek 0.6.0 (registry+https://github.com/rust-lang/crates.io-index)", - "zeroize 1.1.1 (registry+https://github.com/rust-lang/crates.io-index)", + "bytes 0.5.6", + "curve25519-dalek 2.1.0", + "futures 0.3.5", + "lazy_static", + "libp2p-core 0.21.0", + "log 0.4.11", + "prost", + "prost-build", + "rand 0.7.3", + "sha2 0.8.2", + "snow", + "static_assertions", + "x25519-dalek", + "zeroize", ] [[package]] @@ -2642,14 +2960,14 @@ name = "libp2p-swarm" version = "0.22.0" source = "git+https://github.com/sigp/rust-libp2p?rev=03f998022ce2f566a6c6e6c4206bc0ce4d45109f#03f998022ce2f566a6c6e6c4206bc0ce4d45109f" dependencies = [ - "either 1.6.1 (registry+https://github.com/rust-lang/crates.io-index)", - "futures 0.3.5 (registry+https://github.com/rust-lang/crates.io-index)", - "libp2p-core 0.21.0 (git+https://github.com/sigp/rust-libp2p?rev=03f998022ce2f566a6c6e6c4206bc0ce4d45109f)", - "log 0.4.11 (registry+https://github.com/rust-lang/crates.io-index)", - "rand 0.7.3 (registry+https://github.com/rust-lang/crates.io-index)", - "smallvec 1.4.2 (registry+https://github.com/rust-lang/crates.io-index)", - "void 1.0.2 (registry+https://github.com/rust-lang/crates.io-index)", - "wasm-timer 0.2.5 (registry+https://github.com/rust-lang/crates.io-index)", + "either", + "futures 0.3.5", + "libp2p-core 0.21.0", + "log 0.4.11", + "rand 0.7.3", + "smallvec 1.4.2", + "void", + "wasm-timer", ] [[package]] @@ -2657,14 +2975,14 @@ name = "libp2p-tcp" version = "0.21.0" source = "git+https://github.com/sigp/rust-libp2p?rev=03f998022ce2f566a6c6e6c4206bc0ce4d45109f#03f998022ce2f566a6c6e6c4206bc0ce4d45109f" dependencies = [ - "futures 0.3.5 (registry+https://github.com/rust-lang/crates.io-index)", - "futures-timer 3.0.2 (registry+https://github.com/rust-lang/crates.io-index)", - "get_if_addrs 0.5.3 (registry+https://github.com/rust-lang/crates.io-index)", - "ipnet 2.3.0 (registry+https://github.com/rust-lang/crates.io-index)", - "libp2p-core 0.21.0 (git+https://github.com/sigp/rust-libp2p?rev=03f998022ce2f566a6c6e6c4206bc0ce4d45109f)", - "log 0.4.11 (registry+https://github.com/rust-lang/crates.io-index)", - "socket2 0.3.15 (registry+https://github.com/rust-lang/crates.io-index)", - "tokio 0.2.22 (registry+https://github.com/rust-lang/crates.io-index)", + "futures 0.3.5", + "futures-timer", + "get_if_addrs", + "ipnet", + "libp2p-core 0.21.0", + "log 0.4.11", + "socket2", + "tokio 0.2.22", ] [[package]] @@ -2672,221 +2990,238 @@ name = "libp2p-websocket" version = "0.22.0" source = "git+https://github.com/sigp/rust-libp2p?rev=03f998022ce2f566a6c6e6c4206bc0ce4d45109f#03f998022ce2f566a6c6e6c4206bc0ce4d45109f" dependencies = [ - "async-tls 0.8.0 (registry+https://github.com/rust-lang/crates.io-index)", - "either 1.6.1 (registry+https://github.com/rust-lang/crates.io-index)", - "futures 0.3.5 (registry+https://github.com/rust-lang/crates.io-index)", - "libp2p-core 0.21.0 (git+https://github.com/sigp/rust-libp2p?rev=03f998022ce2f566a6c6e6c4206bc0ce4d45109f)", - "log 0.4.11 (registry+https://github.com/rust-lang/crates.io-index)", - "quicksink 0.1.2 (registry+https://github.com/rust-lang/crates.io-index)", - "rustls 0.18.1 (registry+https://github.com/rust-lang/crates.io-index)", - "rw-stream-sink 0.2.1 (registry+https://github.com/rust-lang/crates.io-index)", - "soketto 0.4.2 (registry+https://github.com/rust-lang/crates.io-index)", - "url 2.1.1 (registry+https://github.com/rust-lang/crates.io-index)", - "webpki 0.21.2 (registry+https://github.com/rust-lang/crates.io-index)", - "webpki-roots 0.18.0 (registry+https://github.com/rust-lang/crates.io-index)", + "async-tls", + "either", + "futures 0.3.5", + "libp2p-core 0.21.0", + "log 0.4.11", + "quicksink", + "rustls", + "rw-stream-sink", + "soketto", + "url 2.1.1", + "webpki", + "webpki-roots 0.18.0", ] [[package]] name = "libsecp256k1" version = "0.3.5" source = "registry+https://github.com/rust-lang/crates.io-index" +checksum = "1fc1e2c808481a63dc6da2074752fdd4336a3c8fcc68b83db6f1fd5224ae7962" dependencies = [ - "arrayref 0.3.6 (registry+https://github.com/rust-lang/crates.io-index)", - "crunchy 0.2.2 (registry+https://github.com/rust-lang/crates.io-index)", - "digest 0.8.1 (registry+https://github.com/rust-lang/crates.io-index)", - "hmac-drbg 0.2.0 (registry+https://github.com/rust-lang/crates.io-index)", - "rand 0.7.3 (registry+https://github.com/rust-lang/crates.io-index)", - "sha2 0.8.2 (registry+https://github.com/rust-lang/crates.io-index)", - "subtle 2.3.0 (registry+https://github.com/rust-lang/crates.io-index)", - "typenum 1.12.0 (registry+https://github.com/rust-lang/crates.io-index)", + "arrayref", + "crunchy", + "digest 0.8.1", + "hmac-drbg", + "rand 0.7.3", + "sha2 0.8.2", + "subtle 2.3.0", + "typenum", ] [[package]] name = "libsqlite3-sys" version = "0.18.0" source = "registry+https://github.com/rust-lang/crates.io-index" +checksum = "1e704a02bcaecd4a08b93a23f6be59d0bd79cd161e0963e9499165a0a35df7bd" dependencies = [ - "cc 1.0.41 (registry+https://github.com/rust-lang/crates.io-index)", - "pkg-config 0.3.18 (registry+https://github.com/rust-lang/crates.io-index)", - "vcpkg 0.2.10 (registry+https://github.com/rust-lang/crates.io-index)", + "cc", + "pkg-config", + "vcpkg", ] [[package]] name = "libz-sys" version = "1.1.2" source = "registry+https://github.com/rust-lang/crates.io-index" +checksum = "602113192b08db8f38796c4e85c39e960c145965140e918018bcde1952429655" dependencies = [ - "cc 1.0.41 (registry+https://github.com/rust-lang/crates.io-index)", - "pkg-config 0.3.18 (registry+https://github.com/rust-lang/crates.io-index)", - "vcpkg 0.2.10 (registry+https://github.com/rust-lang/crates.io-index)", + "cc", + "pkg-config", + "vcpkg", ] [[package]] name = "lighthouse" version = "0.2.12" dependencies = [ - "account_manager 0.2.12", - "account_utils 0.1.0", - "beacon_node 0.2.12", - "bls 0.2.0", - "boot_node 0.2.12", - "clap 2.33.3 (registry+https://github.com/rust-lang/crates.io-index)", - "clap_utils 0.1.0", - "directory 0.1.0", - "env_logger 0.7.1 (registry+https://github.com/rust-lang/crates.io-index)", - "environment 0.1.2", - "eth2_testnet_config 0.2.0", - "futures 0.3.5 (registry+https://github.com/rust-lang/crates.io-index)", - "lighthouse_version 0.1.0", - "logging 0.2.0", - "slog 2.5.2 (registry+https://github.com/rust-lang/crates.io-index)", - "slog-async 2.5.0 (registry+https://github.com/rust-lang/crates.io-index)", - "slog-term 2.6.0 (registry+https://github.com/rust-lang/crates.io-index)", - "sloggers 1.0.1 (registry+https://github.com/rust-lang/crates.io-index)", - "tempfile 3.1.0 (registry+https://github.com/rust-lang/crates.io-index)", - "tokio 0.2.22 (registry+https://github.com/rust-lang/crates.io-index)", - "types 0.2.0", - "validator_client 0.2.12", - "validator_dir 0.1.0", + "account_manager", + "account_utils", + "beacon_node", + "bls", + "boot_node", + "clap", + "clap_utils", + "directory", + "env_logger", + "environment", + "eth2_testnet_config", + "futures 0.3.5", + "lighthouse_version", + "logging", + "slog", + "slog-async", + "slog-term", + "sloggers", + "tempfile", + "tokio 0.2.22", + "types", + "validator_client", + "validator_dir", ] [[package]] name = "lighthouse_metrics" version = "0.2.0" dependencies = [ - "lazy_static 1.4.0 (registry+https://github.com/rust-lang/crates.io-index)", - "prometheus 0.9.0 (registry+https://github.com/rust-lang/crates.io-index)", + "lazy_static", + "prometheus", ] [[package]] name = "lighthouse_version" version = "0.1.0" dependencies = [ - "git-version 0.3.4 (registry+https://github.com/rust-lang/crates.io-index)", - "target_info 0.1.0 (registry+https://github.com/rust-lang/crates.io-index)", + "git-version", + "target_info", ] [[package]] name = "linked-hash-map" version = "0.5.3" source = "registry+https://github.com/rust-lang/crates.io-index" +checksum = "8dd5a6d5999d9907cda8ed67bbd137d3af8085216c2ac62de5be860bd41f304a" [[package]] name = "lock_api" version = "0.3.4" source = "registry+https://github.com/rust-lang/crates.io-index" +checksum = "c4da24a77a3d8a6d4862d95f72e6fdb9c09a643ecdb402d754004a557f2bec75" dependencies = [ - "scopeguard 1.1.0 (registry+https://github.com/rust-lang/crates.io-index)", + "scopeguard", ] [[package]] name = "lock_api" version = "0.4.1" source = "registry+https://github.com/rust-lang/crates.io-index" +checksum = "28247cc5a5be2f05fbcd76dd0cf2c7d3b5400cb978a28042abcd4fa0b3f8261c" dependencies = [ - "scopeguard 1.1.0 (registry+https://github.com/rust-lang/crates.io-index)", + "scopeguard", ] [[package]] name = "log" version = "0.3.9" source = "registry+https://github.com/rust-lang/crates.io-index" +checksum = "e19e8d5c34a3e0e2223db8e060f9e8264aeeb5c5fc64a4ee9965c062211c024b" dependencies = [ - "log 0.4.11 (registry+https://github.com/rust-lang/crates.io-index)", + "log 0.4.11", ] [[package]] name = "log" version = "0.4.11" source = "registry+https://github.com/rust-lang/crates.io-index" +checksum = "4fabed175da42fed1fa0746b0ea71f412aa9d35e76e95e59b192c64b9dc2bf8b" dependencies = [ - "cfg-if 0.1.10 (registry+https://github.com/rust-lang/crates.io-index)", + "cfg-if", ] [[package]] name = "logging" version = "0.2.0" dependencies = [ - "lazy_static 1.4.0 (registry+https://github.com/rust-lang/crates.io-index)", - "lighthouse_metrics 0.2.0", - "slog 2.5.2 (registry+https://github.com/rust-lang/crates.io-index)", - "slog-term 2.6.0 (registry+https://github.com/rust-lang/crates.io-index)", + "lazy_static", + "lighthouse_metrics", + "slog", + "slog-term", ] [[package]] name = "lru" version = "0.5.3" source = "registry+https://github.com/rust-lang/crates.io-index" +checksum = "35c456c123957de3a220cd03786e0d86aa542a88b46029973b542f426da6ef34" dependencies = [ - "hashbrown 0.6.3 (registry+https://github.com/rust-lang/crates.io-index)", + "hashbrown 0.6.3", ] [[package]] name = "lru-cache" version = "0.1.2" source = "registry+https://github.com/rust-lang/crates.io-index" +checksum = "31e24f1ad8321ca0e8a1e0ac13f23cb668e6f5466c2c57319f6a5cf1cc8e3b1c" dependencies = [ - "linked-hash-map 0.5.3 (registry+https://github.com/rust-lang/crates.io-index)", + "linked-hash-map", ] [[package]] name = "lru_cache" version = "0.1.0" dependencies = [ - "fnv 1.0.7 (registry+https://github.com/rust-lang/crates.io-index)", + "fnv", ] [[package]] name = "lru_time_cache" version = "0.10.0" source = "registry+https://github.com/rust-lang/crates.io-index" +checksum = "adb241df5c4caeb888755363fc95f8a896618dc0d435e9e775f7930cb099beab" [[package]] name = "mach" version = "0.3.2" source = "registry+https://github.com/rust-lang/crates.io-index" +checksum = "b823e83b2affd8f40a9ee8c29dbc56404c1e34cd2710921f2801e2cf29527afa" dependencies = [ - "libc 0.2.77 (registry+https://github.com/rust-lang/crates.io-index)", + "libc", ] [[package]] name = "maplit" version = "1.0.2" source = "registry+https://github.com/rust-lang/crates.io-index" +checksum = "3e2e65a1a2e43cfcb47a895c4c8b10d1f4a61097f9f254f183aee60cad9c651d" [[package]] name = "matches" version = "0.1.8" source = "registry+https://github.com/rust-lang/crates.io-index" +checksum = "7ffc5c5338469d4d3ea17d269fa8ea3512ad247247c30bd2df69e68309ed0a08" [[package]] name = "maybe-uninit" version = "2.0.0" source = "registry+https://github.com/rust-lang/crates.io-index" +checksum = "60302e4db3a61da70c0cb7991976248362f30319e88850c487b9b95bbf059e00" [[package]] name = "memchr" version = "2.3.3" source = "registry+https://github.com/rust-lang/crates.io-index" +checksum = "3728d817d99e5ac407411fa471ff9800a778d88a24685968b36824eaf4bee400" [[package]] name = "memoffset" version = "0.5.6" source = "registry+https://github.com/rust-lang/crates.io-index" +checksum = "043175f069eda7b85febe4a74abbaeff828d9f8b448515d3151a14a3542811aa" dependencies = [ - "autocfg 1.0.1 (registry+https://github.com/rust-lang/crates.io-index)", + "autocfg 1.0.1", ] [[package]] name = "merkle_proof" version = "0.2.0" dependencies = [ - "eth2_hashing 0.1.1", - "ethereum-types 0.9.2 (registry+https://github.com/rust-lang/crates.io-index)", - "lazy_static 1.4.0 (registry+https://github.com/rust-lang/crates.io-index)", - "quickcheck 0.9.2 (registry+https://github.com/rust-lang/crates.io-index)", - "quickcheck_macros 0.9.1 (registry+https://github.com/rust-lang/crates.io-index)", - "safe_arith 0.1.0", + "eth2_hashing", + "ethereum-types", + "lazy_static", + "quickcheck", + "quickcheck_macros", + "safe_arith", ] [[package]] @@ -2894,405 +3229,454 @@ name = "milagro_bls" version = "1.1.0" source = "git+https://github.com/sigp/milagro_bls?branch=paulh#7662690845f3f2594e46cfe71b6b0bb91d5e1f82" dependencies = [ - "amcl 0.2.0 (git+https://github.com/sigp/milagro_bls?branch=paulh)", - "hex 0.4.2 (registry+https://github.com/rust-lang/crates.io-index)", - "lazy_static 1.4.0 (registry+https://github.com/rust-lang/crates.io-index)", - "rand 0.7.3 (registry+https://github.com/rust-lang/crates.io-index)", - "zeroize 1.1.1 (registry+https://github.com/rust-lang/crates.io-index)", + "amcl", + "hex 0.4.2", + "lazy_static", + "rand 0.7.3", + "zeroize", ] [[package]] name = "mime" version = "0.2.6" source = "registry+https://github.com/rust-lang/crates.io-index" +checksum = "ba626b8a6de5da682e1caa06bdb42a335aee5a84db8e5046a3e8ab17ba0a3ae0" dependencies = [ - "log 0.3.9 (registry+https://github.com/rust-lang/crates.io-index)", + "log 0.3.9", ] [[package]] name = "mime" version = "0.3.16" source = "registry+https://github.com/rust-lang/crates.io-index" +checksum = "2a60c7ce501c71e03a9c9c0d35b861413ae925bd979cc7a4e30d060069aaac8d" [[package]] name = "mime_guess" version = "2.0.3" source = "registry+https://github.com/rust-lang/crates.io-index" +checksum = "2684d4c2e97d99848d30b324b00c8fcc7e5c897b7cbb5819b09e7c90e8baf212" dependencies = [ - "mime 0.3.16 (registry+https://github.com/rust-lang/crates.io-index)", - "unicase 2.6.0 (registry+https://github.com/rust-lang/crates.io-index)", + "mime 0.3.16", + "unicase 2.6.0", ] [[package]] name = "miniz_oxide" version = "0.4.2" source = "registry+https://github.com/rust-lang/crates.io-index" +checksum = "c60c0dfe32c10b43a144bad8fc83538c52f58302c92300ea7ec7bf7b38d5a7b9" dependencies = [ - "adler 0.2.3 (registry+https://github.com/rust-lang/crates.io-index)", - "autocfg 1.0.1 (registry+https://github.com/rust-lang/crates.io-index)", + "adler", + "autocfg 1.0.1", ] [[package]] name = "mio" version = "0.6.22" source = "registry+https://github.com/rust-lang/crates.io-index" +checksum = "fce347092656428bc8eaf6201042cb551b8d67855af7374542a92a0fbfcac430" dependencies = [ - "cfg-if 0.1.10 (registry+https://github.com/rust-lang/crates.io-index)", - "fuchsia-zircon 0.3.3 (registry+https://github.com/rust-lang/crates.io-index)", - "fuchsia-zircon-sys 0.3.3 (registry+https://github.com/rust-lang/crates.io-index)", - "iovec 0.1.4 (registry+https://github.com/rust-lang/crates.io-index)", - "kernel32-sys 0.2.2 (registry+https://github.com/rust-lang/crates.io-index)", - "libc 0.2.77 (registry+https://github.com/rust-lang/crates.io-index)", - "log 0.4.11 (registry+https://github.com/rust-lang/crates.io-index)", - "miow 0.2.1 (registry+https://github.com/rust-lang/crates.io-index)", - "net2 0.2.35 (registry+https://github.com/rust-lang/crates.io-index)", - "slab 0.4.2 (registry+https://github.com/rust-lang/crates.io-index)", - "winapi 0.2.8 (registry+https://github.com/rust-lang/crates.io-index)", + "cfg-if", + "fuchsia-zircon", + "fuchsia-zircon-sys", + "iovec", + "kernel32-sys", + "libc", + "log 0.4.11", + "miow 0.2.1", + "net2", + "slab 0.4.2", + "winapi 0.2.8", ] [[package]] name = "mio-extras" version = "2.0.6" source = "registry+https://github.com/rust-lang/crates.io-index" +checksum = "52403fe290012ce777c4626790c8951324a2b9e3316b3143779c72b029742f19" dependencies = [ - "lazycell 1.3.0 (registry+https://github.com/rust-lang/crates.io-index)", - "log 0.4.11 (registry+https://github.com/rust-lang/crates.io-index)", - "mio 0.6.22 (registry+https://github.com/rust-lang/crates.io-index)", - "slab 0.4.2 (registry+https://github.com/rust-lang/crates.io-index)", + "lazycell", + "log 0.4.11", + "mio", + "slab 0.4.2", ] [[package]] name = "mio-named-pipes" version = "0.1.7" source = "registry+https://github.com/rust-lang/crates.io-index" +checksum = "0840c1c50fd55e521b247f949c241c9997709f23bd7f023b9762cd561e935656" dependencies = [ - "log 0.4.11 (registry+https://github.com/rust-lang/crates.io-index)", - "mio 0.6.22 (registry+https://github.com/rust-lang/crates.io-index)", - "miow 0.3.5 (registry+https://github.com/rust-lang/crates.io-index)", - "winapi 0.3.9 (registry+https://github.com/rust-lang/crates.io-index)", + "log 0.4.11", + "mio", + "miow 0.3.5", + "winapi 0.3.9", ] [[package]] name = "mio-uds" version = "0.6.8" source = "registry+https://github.com/rust-lang/crates.io-index" +checksum = "afcb699eb26d4332647cc848492bbc15eafb26f08d0304550d5aa1f612e066f0" dependencies = [ - "iovec 0.1.4 (registry+https://github.com/rust-lang/crates.io-index)", - "libc 0.2.77 (registry+https://github.com/rust-lang/crates.io-index)", - "mio 0.6.22 (registry+https://github.com/rust-lang/crates.io-index)", + "iovec", + "libc", + "mio", ] [[package]] name = "miow" version = "0.2.1" source = "registry+https://github.com/rust-lang/crates.io-index" +checksum = "8c1f2f3b1cf331de6896aabf6e9d55dca90356cc9960cca7eaaf408a355ae919" dependencies = [ - "kernel32-sys 0.2.2 (registry+https://github.com/rust-lang/crates.io-index)", - "net2 0.2.35 (registry+https://github.com/rust-lang/crates.io-index)", - "winapi 0.2.8 (registry+https://github.com/rust-lang/crates.io-index)", - "ws2_32-sys 0.2.1 (registry+https://github.com/rust-lang/crates.io-index)", + "kernel32-sys", + "net2", + "winapi 0.2.8", + "ws2_32-sys", ] [[package]] name = "miow" version = "0.3.5" source = "registry+https://github.com/rust-lang/crates.io-index" +checksum = "07b88fb9795d4d36d62a012dfbf49a8f5cf12751f36d31a9dbe66d528e58979e" dependencies = [ - "socket2 0.3.15 (registry+https://github.com/rust-lang/crates.io-index)", - "winapi 0.3.9 (registry+https://github.com/rust-lang/crates.io-index)", + "socket2", + "winapi 0.3.9", ] [[package]] name = "multihash" version = "0.11.4" source = "registry+https://github.com/rust-lang/crates.io-index" +checksum = "567122ab6492f49b59def14ecc36e13e64dca4188196dd0cd41f9f3f979f3df6" dependencies = [ - "blake2b_simd 0.5.10 (registry+https://github.com/rust-lang/crates.io-index)", - "blake2s_simd 0.5.10 (registry+https://github.com/rust-lang/crates.io-index)", - "digest 0.9.0 (registry+https://github.com/rust-lang/crates.io-index)", - "sha-1 0.9.1 (registry+https://github.com/rust-lang/crates.io-index)", - "sha2 0.9.1 (registry+https://github.com/rust-lang/crates.io-index)", - "sha3 0.9.1 (registry+https://github.com/rust-lang/crates.io-index)", - "unsigned-varint 0.5.1 (registry+https://github.com/rust-lang/crates.io-index)", + "blake2b_simd", + "blake2s_simd", + "digest 0.9.0", + "sha-1 0.9.1", + "sha2 0.9.1", + "sha3", + "unsigned-varint 0.5.1", ] [[package]] name = "multimap" version = "0.8.2" source = "registry+https://github.com/rust-lang/crates.io-index" +checksum = "1255076139a83bb467426e7f8d0134968a8118844faa755985e077cf31850333" + +[[package]] +name = "multipart" +version = "0.17.0" +source = "registry+https://github.com/rust-lang/crates.io-index" +checksum = "8209c33c951f07387a8497841122fc6f712165e3f9bda3e6be4645b58188f676" +dependencies = [ + "buf_redux", + "httparse", + "log 0.4.11", + "mime 0.3.16", + "mime_guess", + "quick-error", + "rand 0.6.5", + "safemem", + "tempfile", + "twoway", +] [[package]] name = "multistream-select" version = "0.8.2" source = "git+https://github.com/sigp/rust-libp2p?rev=03f998022ce2f566a6c6e6c4206bc0ce4d45109f#03f998022ce2f566a6c6e6c4206bc0ce4d45109f" dependencies = [ - "bytes 0.5.6 (registry+https://github.com/rust-lang/crates.io-index)", - "futures 0.3.5 (registry+https://github.com/rust-lang/crates.io-index)", - "log 0.4.11 (registry+https://github.com/rust-lang/crates.io-index)", - "pin-project 0.4.24 (registry+https://github.com/rust-lang/crates.io-index)", - "smallvec 1.4.2 (registry+https://github.com/rust-lang/crates.io-index)", - "unsigned-varint 0.4.0 (registry+https://github.com/rust-lang/crates.io-index)", + "bytes 0.5.6", + "futures 0.3.5", + "log 0.4.11", + "pin-project", + "smallvec 1.4.2", + "unsigned-varint 0.4.0", ] [[package]] name = "multistream-select" version = "0.8.2" source = "registry+https://github.com/rust-lang/crates.io-index" +checksum = "c9157e87afbc2ef0d84cc0345423d715f445edde00141c93721c162de35a05e5" dependencies = [ - "bytes 0.5.6 (registry+https://github.com/rust-lang/crates.io-index)", - "futures 0.3.5 (registry+https://github.com/rust-lang/crates.io-index)", - "log 0.4.11 (registry+https://github.com/rust-lang/crates.io-index)", - "pin-project 0.4.24 (registry+https://github.com/rust-lang/crates.io-index)", - "smallvec 1.4.2 (registry+https://github.com/rust-lang/crates.io-index)", - "unsigned-varint 0.4.0 (registry+https://github.com/rust-lang/crates.io-index)", + "bytes 0.5.6", + "futures 0.3.5", + "log 0.4.11", + "pin-project", + "smallvec 1.4.2", + "unsigned-varint 0.4.0", ] [[package]] name = "native-tls" version = "0.2.4" source = "registry+https://github.com/rust-lang/crates.io-index" +checksum = "2b0d88c06fe90d5ee94048ba40409ef1d9315d86f6f38c2efdaad4fb50c58b2d" dependencies = [ - "lazy_static 1.4.0 (registry+https://github.com/rust-lang/crates.io-index)", - "libc 0.2.77 (registry+https://github.com/rust-lang/crates.io-index)", - "log 0.4.11 (registry+https://github.com/rust-lang/crates.io-index)", - "openssl 0.10.30 (registry+https://github.com/rust-lang/crates.io-index)", - "openssl-probe 0.1.2 (registry+https://github.com/rust-lang/crates.io-index)", - "openssl-sys 0.9.58 (registry+https://github.com/rust-lang/crates.io-index)", - "schannel 0.1.19 (registry+https://github.com/rust-lang/crates.io-index)", - "security-framework 0.4.4 (registry+https://github.com/rust-lang/crates.io-index)", - "security-framework-sys 0.4.3 (registry+https://github.com/rust-lang/crates.io-index)", - "tempfile 3.1.0 (registry+https://github.com/rust-lang/crates.io-index)", + "lazy_static", + "libc", + "log 0.4.11", + "openssl", + "openssl-probe", + "openssl-sys", + "schannel", + "security-framework", + "security-framework-sys", + "tempfile", ] [[package]] name = "net2" version = "0.2.35" source = "registry+https://github.com/rust-lang/crates.io-index" +checksum = "3ebc3ec692ed7c9a255596c67808dee269f64655d8baf7b4f0638e51ba1d6853" dependencies = [ - "cfg-if 0.1.10 (registry+https://github.com/rust-lang/crates.io-index)", - "libc 0.2.77 (registry+https://github.com/rust-lang/crates.io-index)", - "winapi 0.3.9 (registry+https://github.com/rust-lang/crates.io-index)", + "cfg-if", + "libc", + "winapi 0.3.9", ] [[package]] name = "network" version = "0.2.0" dependencies = [ - "beacon_chain 0.2.0", - "environment 0.1.2", - "error-chain 0.12.4 (registry+https://github.com/rust-lang/crates.io-index)", - "eth2_libp2p 0.2.0", - "eth2_ssz 0.1.2", - "eth2_ssz_types 0.2.0", - "exit-future 0.2.0 (registry+https://github.com/rust-lang/crates.io-index)", - "fnv 1.0.7 (registry+https://github.com/rust-lang/crates.io-index)", - "futures 0.3.5 (registry+https://github.com/rust-lang/crates.io-index)", - "genesis 0.2.0", - "hashset_delay 0.2.0", - "hex 0.4.2 (registry+https://github.com/rust-lang/crates.io-index)", - "itertools 0.9.0 (registry+https://github.com/rust-lang/crates.io-index)", - "lazy_static 1.4.0 (registry+https://github.com/rust-lang/crates.io-index)", - "lighthouse_metrics 0.2.0", - "lru_cache 0.1.0", - "matches 0.1.8 (registry+https://github.com/rust-lang/crates.io-index)", - "num_cpus 1.13.0 (registry+https://github.com/rust-lang/crates.io-index)", - "parking_lot 0.11.0 (registry+https://github.com/rust-lang/crates.io-index)", - "rand 0.7.3 (registry+https://github.com/rust-lang/crates.io-index)", - "rest_types 0.2.0", - "rlp 0.4.5 (registry+https://github.com/rust-lang/crates.io-index)", - "slog 2.5.2 (registry+https://github.com/rust-lang/crates.io-index)", - "sloggers 1.0.1 (registry+https://github.com/rust-lang/crates.io-index)", - "slot_clock 0.2.0", - "smallvec 1.4.2 (registry+https://github.com/rust-lang/crates.io-index)", - "state_processing 0.2.0", - "store 0.2.0", - "tempfile 3.1.0 (registry+https://github.com/rust-lang/crates.io-index)", - "tokio 0.2.22 (registry+https://github.com/rust-lang/crates.io-index)", - "tree_hash 0.1.1", - "types 0.2.0", + "beacon_chain", + "environment", + "error-chain", + "eth2_libp2p", + "eth2_ssz", + "eth2_ssz_types", + "exit-future", + "fnv", + "futures 0.3.5", + "genesis", + "hashset_delay", + "hex 0.4.2", + "itertools 0.9.0", + "lazy_static", + "lighthouse_metrics", + "lru_cache", + "matches", + "num_cpus", + "parking_lot 0.11.0", + "rand 0.7.3", + "rlp", + "slog", + "sloggers", + "slot_clock", + "smallvec 1.4.2", + "state_processing", + "store", + "tempfile", + "tokio 0.2.22", + "tree_hash", + "types", ] [[package]] name = "nix" version = "0.17.0" source = "registry+https://github.com/rust-lang/crates.io-index" +checksum = "50e4785f2c3b7589a0d0c1dd60285e1188adac4006e8abd6dd578e1567027363" dependencies = [ - "bitflags 1.2.1 (registry+https://github.com/rust-lang/crates.io-index)", - "cc 1.0.41 (registry+https://github.com/rust-lang/crates.io-index)", - "cfg-if 0.1.10 (registry+https://github.com/rust-lang/crates.io-index)", - "libc 0.2.77 (registry+https://github.com/rust-lang/crates.io-index)", - "void 1.0.2 (registry+https://github.com/rust-lang/crates.io-index)", + "bitflags 1.2.1", + "cc", + "cfg-if", + "libc", + "void", ] [[package]] name = "node_test_rig" version = "0.2.0" dependencies = [ - "beacon_node 0.2.12", - "environment 0.1.2", - "eth2_config 0.2.0", - "futures 0.3.5 (registry+https://github.com/rust-lang/crates.io-index)", - "genesis 0.2.0", - "remote_beacon_node 0.2.0", - "reqwest 0.10.8 (registry+https://github.com/rust-lang/crates.io-index)", - "serde 1.0.116 (registry+https://github.com/rust-lang/crates.io-index)", - "tempdir 0.3.7 (registry+https://github.com/rust-lang/crates.io-index)", - "types 0.2.0", - "url 2.1.1 (registry+https://github.com/rust-lang/crates.io-index)", - "validator_client 0.2.12", - "validator_dir 0.1.0", + "beacon_node", + "environment", + "eth2", + "eth2_config", + "futures 0.3.5", + "genesis", + "reqwest", + "serde", + "tempdir", + "types", + "url 2.1.1", + "validator_client", + "validator_dir", ] [[package]] name = "nom" version = "2.2.1" source = "registry+https://github.com/rust-lang/crates.io-index" +checksum = "cf51a729ecf40266a2368ad335a5fdde43471f545a967109cd62146ecf8b66ff" [[package]] name = "num-bigint" version = "0.3.0" source = "registry+https://github.com/rust-lang/crates.io-index" +checksum = "b7f3fc75e3697059fb1bc465e3d8cca6cf92f56854f201158b3f9c77d5a3cfa0" dependencies = [ - "autocfg 1.0.1 (registry+https://github.com/rust-lang/crates.io-index)", - "num-integer 0.1.43 (registry+https://github.com/rust-lang/crates.io-index)", - "num-traits 0.2.12 (registry+https://github.com/rust-lang/crates.io-index)", + "autocfg 1.0.1", + "num-integer", + "num-traits", ] [[package]] name = "num-bigint-dig" version = "0.6.0" source = "registry+https://github.com/rust-lang/crates.io-index" +checksum = "b3d03c330f9f7a2c19e3c0b42698e48141d0809c78cd9b6219f85bd7d7e892aa" dependencies = [ - "autocfg 0.1.7 (registry+https://github.com/rust-lang/crates.io-index)", - "byteorder 1.3.4 (registry+https://github.com/rust-lang/crates.io-index)", - "lazy_static 1.4.0 (registry+https://github.com/rust-lang/crates.io-index)", - "libm 0.2.1 (registry+https://github.com/rust-lang/crates.io-index)", - "num-integer 0.1.43 (registry+https://github.com/rust-lang/crates.io-index)", - "num-iter 0.1.41 (registry+https://github.com/rust-lang/crates.io-index)", - "num-traits 0.2.12 (registry+https://github.com/rust-lang/crates.io-index)", - "rand 0.7.3 (registry+https://github.com/rust-lang/crates.io-index)", - "serde 1.0.116 (registry+https://github.com/rust-lang/crates.io-index)", - "smallvec 1.4.2 (registry+https://github.com/rust-lang/crates.io-index)", - "zeroize 1.1.1 (registry+https://github.com/rust-lang/crates.io-index)", + "autocfg 0.1.7", + "byteorder", + "lazy_static", + "libm", + "num-integer", + "num-iter", + "num-traits", + "rand 0.7.3", + "serde", + "smallvec 1.4.2", + "zeroize", ] [[package]] name = "num-integer" version = "0.1.43" source = "registry+https://github.com/rust-lang/crates.io-index" +checksum = "8d59457e662d541ba17869cf51cf177c0b5f0cbf476c66bdc90bf1edac4f875b" dependencies = [ - "autocfg 1.0.1 (registry+https://github.com/rust-lang/crates.io-index)", - "num-traits 0.2.12 (registry+https://github.com/rust-lang/crates.io-index)", + "autocfg 1.0.1", + "num-traits", ] [[package]] name = "num-iter" version = "0.1.41" source = "registry+https://github.com/rust-lang/crates.io-index" +checksum = "7a6e6b7c748f995c4c29c5f5ae0248536e04a5739927c74ec0fa564805094b9f" dependencies = [ - "autocfg 1.0.1 (registry+https://github.com/rust-lang/crates.io-index)", - "num-integer 0.1.43 (registry+https://github.com/rust-lang/crates.io-index)", - "num-traits 0.2.12 (registry+https://github.com/rust-lang/crates.io-index)", + "autocfg 1.0.1", + "num-integer", + "num-traits", ] [[package]] name = "num-traits" version = "0.2.12" source = "registry+https://github.com/rust-lang/crates.io-index" +checksum = "ac267bcc07f48ee5f8935ab0d24f316fb722d7a1292e2913f0cc196b29ffd611" dependencies = [ - "autocfg 1.0.1 (registry+https://github.com/rust-lang/crates.io-index)", + "autocfg 1.0.1", ] [[package]] name = "num_cpus" version = "1.13.0" source = "registry+https://github.com/rust-lang/crates.io-index" +checksum = "05499f3756671c15885fee9034446956fff3f243d6077b91e5767df161f766b3" dependencies = [ - "hermit-abi 0.1.16 (registry+https://github.com/rust-lang/crates.io-index)", - "libc 0.2.77 (registry+https://github.com/rust-lang/crates.io-index)", + "hermit-abi", + "libc", ] [[package]] name = "object" version = "0.20.0" source = "registry+https://github.com/rust-lang/crates.io-index" +checksum = "1ab52be62400ca80aa00285d25253d7f7c437b7375c4de678f5405d3afe82ca5" [[package]] name = "once_cell" version = "1.4.1" source = "registry+https://github.com/rust-lang/crates.io-index" +checksum = "260e51e7efe62b592207e9e13a68e43692a7a279171d6ba57abd208bf23645ad" dependencies = [ - "parking_lot 0.11.0 (registry+https://github.com/rust-lang/crates.io-index)", + "parking_lot 0.11.0", ] [[package]] name = "oorandom" version = "11.1.2" source = "registry+https://github.com/rust-lang/crates.io-index" +checksum = "a170cebd8021a008ea92e4db85a72f80b35df514ec664b296fdcbb654eac0b2c" [[package]] name = "opaque-debug" version = "0.2.3" source = "registry+https://github.com/rust-lang/crates.io-index" +checksum = "2839e79665f131bdb5782e51f2c6c9599c133c6098982a54c794358bf432529c" [[package]] name = "opaque-debug" version = "0.3.0" source = "registry+https://github.com/rust-lang/crates.io-index" +checksum = "624a8340c38c1b80fd549087862da4ba43e08858af025b236e509b6649fc13d5" [[package]] name = "openssl" version = "0.10.30" source = "registry+https://github.com/rust-lang/crates.io-index" +checksum = "8d575eff3665419f9b83678ff2815858ad9d11567e082f5ac1814baba4e2bcb4" dependencies = [ - "bitflags 1.2.1 (registry+https://github.com/rust-lang/crates.io-index)", - "cfg-if 0.1.10 (registry+https://github.com/rust-lang/crates.io-index)", - "foreign-types 0.3.2 (registry+https://github.com/rust-lang/crates.io-index)", - "lazy_static 1.4.0 (registry+https://github.com/rust-lang/crates.io-index)", - "libc 0.2.77 (registry+https://github.com/rust-lang/crates.io-index)", - "openssl-sys 0.9.58 (registry+https://github.com/rust-lang/crates.io-index)", + "bitflags 1.2.1", + "cfg-if", + "foreign-types", + "lazy_static", + "libc", + "openssl-sys", ] [[package]] name = "openssl-probe" version = "0.1.2" source = "registry+https://github.com/rust-lang/crates.io-index" +checksum = "77af24da69f9d9341038eba93a073b1fdaaa1b788221b00a69bce9e762cb32de" [[package]] name = "openssl-src" version = "111.11.0+1.1.1h" source = "registry+https://github.com/rust-lang/crates.io-index" +checksum = "380fe324132bea01f45239fadfec9343adb044615f29930d039bec1ae7b9fa5b" dependencies = [ - "cc 1.0.41 (registry+https://github.com/rust-lang/crates.io-index)", + "cc", ] [[package]] name = "openssl-sys" version = "0.9.58" source = "registry+https://github.com/rust-lang/crates.io-index" +checksum = "a842db4709b604f0fe5d1170ae3565899be2ad3d9cbc72dedc789ac0511f78de" dependencies = [ - "autocfg 1.0.1 (registry+https://github.com/rust-lang/crates.io-index)", - "cc 1.0.41 (registry+https://github.com/rust-lang/crates.io-index)", - "libc 0.2.77 (registry+https://github.com/rust-lang/crates.io-index)", - "openssl-src 111.11.0+1.1.1h (registry+https://github.com/rust-lang/crates.io-index)", - "pkg-config 0.3.18 (registry+https://github.com/rust-lang/crates.io-index)", - "vcpkg 0.2.10 (registry+https://github.com/rust-lang/crates.io-index)", + "autocfg 1.0.1", + "cc", + "libc", + "openssl-src", + "pkg-config", + "vcpkg", ] [[package]] name = "operation_pool" version = "0.2.0" dependencies = [ - "eth2_ssz 0.1.2", - "eth2_ssz_derive 0.1.0", - "int_to_bytes 0.2.0", - "parking_lot 0.11.0 (registry+https://github.com/rust-lang/crates.io-index)", - "rand 0.7.3 (registry+https://github.com/rust-lang/crates.io-index)", - "serde 1.0.116 (registry+https://github.com/rust-lang/crates.io-index)", - "serde_derive 1.0.116 (registry+https://github.com/rust-lang/crates.io-index)", - "state_processing 0.2.0", - "store 0.2.0", - "types 0.2.0", + "eth2_ssz", + "eth2_ssz_derive", + "int_to_bytes", + "parking_lot 0.11.0", + "rand 0.7.3", + "serde", + "serde_derive", + "state_processing", + "store", + "types", ] [[package]] @@ -3300,823 +3684,905 @@ name = "parity-multiaddr" version = "0.9.1" source = "git+https://github.com/sigp/rust-libp2p?rev=03f998022ce2f566a6c6e6c4206bc0ce4d45109f#03f998022ce2f566a6c6e6c4206bc0ce4d45109f" dependencies = [ - "arrayref 0.3.6 (registry+https://github.com/rust-lang/crates.io-index)", - "bs58 0.3.1 (registry+https://github.com/rust-lang/crates.io-index)", - "byteorder 1.3.4 (registry+https://github.com/rust-lang/crates.io-index)", - "data-encoding 2.3.0 (registry+https://github.com/rust-lang/crates.io-index)", - "multihash 0.11.4 (registry+https://github.com/rust-lang/crates.io-index)", - "percent-encoding 2.1.0 (registry+https://github.com/rust-lang/crates.io-index)", - "serde 1.0.116 (registry+https://github.com/rust-lang/crates.io-index)", - "static_assertions 1.1.0 (registry+https://github.com/rust-lang/crates.io-index)", - "unsigned-varint 0.4.0 (registry+https://github.com/rust-lang/crates.io-index)", - "url 2.1.1 (registry+https://github.com/rust-lang/crates.io-index)", + "arrayref", + "bs58", + "byteorder", + "data-encoding", + "multihash", + "percent-encoding 2.1.0", + "serde", + "static_assertions", + "unsigned-varint 0.4.0", + "url 2.1.1", ] [[package]] name = "parity-multiaddr" version = "0.9.2" source = "registry+https://github.com/rust-lang/crates.io-index" +checksum = "2165a93382a93de55868dcbfa11e4a8f99676a9164eee6a2b4a9479ad319c257" dependencies = [ - "arrayref 0.3.6 (registry+https://github.com/rust-lang/crates.io-index)", - "bs58 0.3.1 (registry+https://github.com/rust-lang/crates.io-index)", - "byteorder 1.3.4 (registry+https://github.com/rust-lang/crates.io-index)", - "data-encoding 2.3.0 (registry+https://github.com/rust-lang/crates.io-index)", - "multihash 0.11.4 (registry+https://github.com/rust-lang/crates.io-index)", - "percent-encoding 2.1.0 (registry+https://github.com/rust-lang/crates.io-index)", - "serde 1.0.116 (registry+https://github.com/rust-lang/crates.io-index)", - "static_assertions 1.1.0 (registry+https://github.com/rust-lang/crates.io-index)", - "unsigned-varint 0.4.0 (registry+https://github.com/rust-lang/crates.io-index)", - "url 2.1.1 (registry+https://github.com/rust-lang/crates.io-index)", + "arrayref", + "bs58", + "byteorder", + "data-encoding", + "multihash", + "percent-encoding 2.1.0", + "serde", + "static_assertions", + "unsigned-varint 0.4.0", + "url 2.1.1", ] [[package]] name = "parity-scale-codec" version = "1.3.5" source = "registry+https://github.com/rust-lang/crates.io-index" +checksum = "7c740e5fbcb6847058b40ac7e5574766c6388f585e184d769910fe0d3a2ca861" dependencies = [ - "arrayvec 0.5.1 (registry+https://github.com/rust-lang/crates.io-index)", - "bitvec 0.17.4 (registry+https://github.com/rust-lang/crates.io-index)", - "byte-slice-cast 0.3.5 (registry+https://github.com/rust-lang/crates.io-index)", - "serde 1.0.116 (registry+https://github.com/rust-lang/crates.io-index)", + "arrayvec", + "bitvec", + "byte-slice-cast", + "serde", ] [[package]] name = "parking_lot" version = "0.9.0" source = "registry+https://github.com/rust-lang/crates.io-index" +checksum = "f842b1982eb6c2fe34036a4fbfb06dd185a3f5c8edfaacdf7d1ea10b07de6252" dependencies = [ - "lock_api 0.3.4 (registry+https://github.com/rust-lang/crates.io-index)", - "parking_lot_core 0.6.2 (registry+https://github.com/rust-lang/crates.io-index)", - "rustc_version 0.2.3 (registry+https://github.com/rust-lang/crates.io-index)", + "lock_api 0.3.4", + "parking_lot_core 0.6.2", + "rustc_version", ] [[package]] name = "parking_lot" version = "0.10.2" source = "registry+https://github.com/rust-lang/crates.io-index" +checksum = "d3a704eb390aafdc107b0e392f56a82b668e3a71366993b5340f5833fd62505e" dependencies = [ - "lock_api 0.3.4 (registry+https://github.com/rust-lang/crates.io-index)", - "parking_lot_core 0.7.2 (registry+https://github.com/rust-lang/crates.io-index)", + "lock_api 0.3.4", + "parking_lot_core 0.7.2", ] [[package]] name = "parking_lot" version = "0.11.0" source = "registry+https://github.com/rust-lang/crates.io-index" +checksum = "a4893845fa2ca272e647da5d0e46660a314ead9c2fdd9a883aabc32e481a8733" dependencies = [ - "instant 0.1.7 (registry+https://github.com/rust-lang/crates.io-index)", - "lock_api 0.4.1 (registry+https://github.com/rust-lang/crates.io-index)", - "parking_lot_core 0.8.0 (registry+https://github.com/rust-lang/crates.io-index)", + "instant", + "lock_api 0.4.1", + "parking_lot_core 0.8.0", ] [[package]] name = "parking_lot_core" version = "0.6.2" source = "registry+https://github.com/rust-lang/crates.io-index" +checksum = "b876b1b9e7ac6e1a74a6da34d25c42e17e8862aa409cbbbdcfc8d86c6f3bc62b" dependencies = [ - "cfg-if 0.1.10 (registry+https://github.com/rust-lang/crates.io-index)", - "cloudabi 0.0.3 (registry+https://github.com/rust-lang/crates.io-index)", - "libc 0.2.77 (registry+https://github.com/rust-lang/crates.io-index)", - "redox_syscall 0.1.57 (registry+https://github.com/rust-lang/crates.io-index)", - "rustc_version 0.2.3 (registry+https://github.com/rust-lang/crates.io-index)", - "smallvec 0.6.13 (registry+https://github.com/rust-lang/crates.io-index)", - "winapi 0.3.9 (registry+https://github.com/rust-lang/crates.io-index)", + "cfg-if", + "cloudabi 0.0.3", + "libc", + "redox_syscall", + "rustc_version", + "smallvec 0.6.13", + "winapi 0.3.9", ] [[package]] name = "parking_lot_core" version = "0.7.2" source = "registry+https://github.com/rust-lang/crates.io-index" +checksum = "d58c7c768d4ba344e3e8d72518ac13e259d7c7ade24167003b8488e10b6740a3" dependencies = [ - "cfg-if 0.1.10 (registry+https://github.com/rust-lang/crates.io-index)", - "cloudabi 0.0.3 (registry+https://github.com/rust-lang/crates.io-index)", - "libc 0.2.77 (registry+https://github.com/rust-lang/crates.io-index)", - "redox_syscall 0.1.57 (registry+https://github.com/rust-lang/crates.io-index)", - "smallvec 1.4.2 (registry+https://github.com/rust-lang/crates.io-index)", - "winapi 0.3.9 (registry+https://github.com/rust-lang/crates.io-index)", + "cfg-if", + "cloudabi 0.0.3", + "libc", + "redox_syscall", + "smallvec 1.4.2", + "winapi 0.3.9", ] [[package]] name = "parking_lot_core" version = "0.8.0" source = "registry+https://github.com/rust-lang/crates.io-index" +checksum = "c361aa727dd08437f2f1447be8b59a33b0edd15e0fcee698f935613d9efbca9b" dependencies = [ - "cfg-if 0.1.10 (registry+https://github.com/rust-lang/crates.io-index)", - "cloudabi 0.1.0 (registry+https://github.com/rust-lang/crates.io-index)", - "instant 0.1.7 (registry+https://github.com/rust-lang/crates.io-index)", - "libc 0.2.77 (registry+https://github.com/rust-lang/crates.io-index)", - "redox_syscall 0.1.57 (registry+https://github.com/rust-lang/crates.io-index)", - "smallvec 1.4.2 (registry+https://github.com/rust-lang/crates.io-index)", - "winapi 0.3.9 (registry+https://github.com/rust-lang/crates.io-index)", + "cfg-if", + "cloudabi 0.1.0", + "instant", + "libc", + "redox_syscall", + "smallvec 1.4.2", + "winapi 0.3.9", ] [[package]] name = "pbkdf2" version = "0.3.0" source = "registry+https://github.com/rust-lang/crates.io-index" +checksum = "006c038a43a45995a9670da19e67600114740e8511d4333bf97a56e66a7542d9" dependencies = [ - "byteorder 1.3.4 (registry+https://github.com/rust-lang/crates.io-index)", - "crypto-mac 0.7.0 (registry+https://github.com/rust-lang/crates.io-index)", + "byteorder", + "crypto-mac 0.7.0", ] [[package]] name = "pbkdf2" version = "0.4.0" source = "registry+https://github.com/rust-lang/crates.io-index" +checksum = "216eaa586a190f0a738f2f918511eecfa90f13295abec0e457cdebcceda80cbd" dependencies = [ - "crypto-mac 0.8.0 (registry+https://github.com/rust-lang/crates.io-index)", + "crypto-mac 0.8.0", ] [[package]] name = "percent-encoding" version = "1.0.1" source = "registry+https://github.com/rust-lang/crates.io-index" +checksum = "31010dd2e1ac33d5b46a5b413495239882813e0369f8ed8a5e266f173602f831" [[package]] name = "percent-encoding" version = "2.1.0" source = "registry+https://github.com/rust-lang/crates.io-index" +checksum = "d4fd5641d01c8f18a23da7b6fe29298ff4b55afcccdf78973b24cf3175fee32e" [[package]] name = "petgraph" version = "0.5.1" source = "registry+https://github.com/rust-lang/crates.io-index" +checksum = "467d164a6de56270bd7c4d070df81d07beace25012d5103ced4e9ff08d6afdb7" dependencies = [ - "fixedbitset 0.2.0 (registry+https://github.com/rust-lang/crates.io-index)", - "indexmap 1.6.0 (registry+https://github.com/rust-lang/crates.io-index)", + "fixedbitset", + "indexmap", ] [[package]] name = "pin-project" -version = "0.4.24" +version = "0.4.23" source = "registry+https://github.com/rust-lang/crates.io-index" +checksum = "ca4433fff2ae79342e497d9f8ee990d174071408f28f726d6d83af93e58e48aa" dependencies = [ - "pin-project-internal 0.4.24 (registry+https://github.com/rust-lang/crates.io-index)", + "pin-project-internal", ] [[package]] name = "pin-project-internal" -version = "0.4.24" +version = "0.4.23" source = "registry+https://github.com/rust-lang/crates.io-index" +checksum = "2c0e815c3ee9a031fdf5af21c10aa17c573c9c6a566328d99e3936c34e36461f" dependencies = [ - "proc-macro2 1.0.23 (registry+https://github.com/rust-lang/crates.io-index)", - "quote 1.0.7 (registry+https://github.com/rust-lang/crates.io-index)", - "syn 1.0.42 (registry+https://github.com/rust-lang/crates.io-index)", + "proc-macro2", + "quote", + "syn", ] [[package]] name = "pin-project-lite" -version = "0.1.8" +version = "0.1.7" source = "registry+https://github.com/rust-lang/crates.io-index" +checksum = "282adbf10f2698a7a77f8e983a74b2d18176c19a7fd32a45446139ae7b02b715" [[package]] name = "pin-utils" version = "0.1.0" source = "registry+https://github.com/rust-lang/crates.io-index" +checksum = "8b870d8c151b6f2fb93e84a13146138f05d02ed11c7e7c54f8826aaaf7c9f184" [[package]] name = "pkg-config" version = "0.3.18" source = "registry+https://github.com/rust-lang/crates.io-index" +checksum = "d36492546b6af1463394d46f0c834346f31548646f6ba10849802c9c9a27ac33" [[package]] name = "platforms" version = "0.2.1" source = "registry+https://github.com/rust-lang/crates.io-index" +checksum = "feb3b2b1033b8a60b4da6ee470325f887758c95d5320f52f9ce0df055a55940e" [[package]] name = "plotters" version = "0.2.15" source = "registry+https://github.com/rust-lang/crates.io-index" +checksum = "0d1685fbe7beba33de0330629da9d955ac75bd54f33d7b79f9a895590124f6bb" dependencies = [ - "js-sys 0.3.45 (registry+https://github.com/rust-lang/crates.io-index)", - "num-traits 0.2.12 (registry+https://github.com/rust-lang/crates.io-index)", - "wasm-bindgen 0.2.68 (registry+https://github.com/rust-lang/crates.io-index)", - "web-sys 0.3.45 (registry+https://github.com/rust-lang/crates.io-index)", + "js-sys", + "num-traits", + "wasm-bindgen", + "web-sys", ] [[package]] name = "podio" version = "0.1.7" source = "registry+https://github.com/rust-lang/crates.io-index" +checksum = "b18befed8bc2b61abc79a457295e7e838417326da1586050b919414073977f19" [[package]] name = "poly1305" version = "0.6.0" source = "registry+https://github.com/rust-lang/crates.io-index" +checksum = "d9b42192ab143ed7619bf888a7f9c6733a9a2153b218e2cd557cfdb52fbf9bb1" dependencies = [ - "universal-hash 0.4.0 (registry+https://github.com/rust-lang/crates.io-index)", + "universal-hash", ] [[package]] name = "polyval" version = "0.4.0" source = "registry+https://github.com/rust-lang/crates.io-index" +checksum = "d9a50142b55ab3ed0e9f68dfb3709f1d90d29da24e91033f28b96330643107dc" dependencies = [ - "cfg-if 0.1.10 (registry+https://github.com/rust-lang/crates.io-index)", - "universal-hash 0.4.0 (registry+https://github.com/rust-lang/crates.io-index)", + "cfg-if", + "universal-hash", ] [[package]] name = "ppv-lite86" version = "0.2.9" source = "registry+https://github.com/rust-lang/crates.io-index" +checksum = "c36fa947111f5c62a733b652544dd0016a43ce89619538a8ef92724a6f501a20" [[package]] name = "primitive-types" version = "0.7.2" source = "registry+https://github.com/rust-lang/crates.io-index" +checksum = "c55c21c64d0eaa4d7ed885d959ef2d62d9e488c27c0e02d9aa5ce6c877b7d5f8" dependencies = [ - "fixed-hash 0.6.1 (registry+https://github.com/rust-lang/crates.io-index)", - "impl-codec 0.4.2 (registry+https://github.com/rust-lang/crates.io-index)", - "impl-rlp 0.2.1 (registry+https://github.com/rust-lang/crates.io-index)", - "impl-serde 0.3.1 (registry+https://github.com/rust-lang/crates.io-index)", - "uint 0.8.5 (registry+https://github.com/rust-lang/crates.io-index)", + "fixed-hash", + "impl-codec", + "impl-rlp", + "impl-serde", + "uint", ] [[package]] name = "proc-macro-hack" version = "0.5.18" source = "registry+https://github.com/rust-lang/crates.io-index" +checksum = "99c605b9a0adc77b7211c6b1f722dcb613d68d66859a44f3d485a6da332b0598" [[package]] name = "proc-macro-nested" version = "0.1.6" source = "registry+https://github.com/rust-lang/crates.io-index" +checksum = "eba180dafb9038b050a4c280019bbedf9f2467b61e5d892dcad585bb57aadc5a" [[package]] name = "proc-macro2" -version = "1.0.23" +version = "1.0.22" source = "registry+https://github.com/rust-lang/crates.io-index" +checksum = "e4b93dba1818d32e781f9d008edd577bab215e83ef50e8a1ddf1ad301b19a09f" dependencies = [ - "unicode-xid 0.2.1 (registry+https://github.com/rust-lang/crates.io-index)", + "unicode-xid", ] [[package]] name = "procinfo" version = "0.4.2" source = "registry+https://github.com/rust-lang/crates.io-index" +checksum = "6ab1427f3d2635891f842892dda177883dca0639e05fe66796a62c9d2f23b49c" dependencies = [ - "byteorder 1.3.4 (registry+https://github.com/rust-lang/crates.io-index)", - "libc 0.2.77 (registry+https://github.com/rust-lang/crates.io-index)", - "nom 2.2.1 (registry+https://github.com/rust-lang/crates.io-index)", - "rustc_version 0.2.3 (registry+https://github.com/rust-lang/crates.io-index)", + "byteorder", + "libc", + "nom", + "rustc_version", ] [[package]] name = "prometheus" version = "0.9.0" source = "registry+https://github.com/rust-lang/crates.io-index" +checksum = "dd0ced56dee39a6e960c15c74dc48849d614586db2eaada6497477af7c7811cd" dependencies = [ - "cfg-if 0.1.10 (registry+https://github.com/rust-lang/crates.io-index)", - "fnv 1.0.7 (registry+https://github.com/rust-lang/crates.io-index)", - "lazy_static 1.4.0 (registry+https://github.com/rust-lang/crates.io-index)", - "protobuf 2.17.0 (registry+https://github.com/rust-lang/crates.io-index)", - "spin 0.5.2 (registry+https://github.com/rust-lang/crates.io-index)", - "thiserror 1.0.20 (registry+https://github.com/rust-lang/crates.io-index)", + "cfg-if", + "fnv", + "lazy_static", + "protobuf", + "spin", + "thiserror", ] [[package]] name = "prost" version = "0.6.1" source = "registry+https://github.com/rust-lang/crates.io-index" +checksum = "ce49aefe0a6144a45de32927c77bd2859a5f7677b55f220ae5b744e87389c212" dependencies = [ - "bytes 0.5.6 (registry+https://github.com/rust-lang/crates.io-index)", - "prost-derive 0.6.1 (registry+https://github.com/rust-lang/crates.io-index)", + "bytes 0.5.6", + "prost-derive", ] [[package]] name = "prost-build" version = "0.6.1" source = "registry+https://github.com/rust-lang/crates.io-index" +checksum = "02b10678c913ecbd69350e8535c3aef91a8676c0773fc1d7b95cdd196d7f2f26" dependencies = [ - "bytes 0.5.6 (registry+https://github.com/rust-lang/crates.io-index)", - "heck 0.3.1 (registry+https://github.com/rust-lang/crates.io-index)", - "itertools 0.8.2 (registry+https://github.com/rust-lang/crates.io-index)", - "log 0.4.11 (registry+https://github.com/rust-lang/crates.io-index)", - "multimap 0.8.2 (registry+https://github.com/rust-lang/crates.io-index)", - "petgraph 0.5.1 (registry+https://github.com/rust-lang/crates.io-index)", - "prost 0.6.1 (registry+https://github.com/rust-lang/crates.io-index)", - "prost-types 0.6.1 (registry+https://github.com/rust-lang/crates.io-index)", - "tempfile 3.1.0 (registry+https://github.com/rust-lang/crates.io-index)", - "which 3.1.1 (registry+https://github.com/rust-lang/crates.io-index)", + "bytes 0.5.6", + "heck", + "itertools 0.8.2", + "log 0.4.11", + "multimap", + "petgraph", + "prost", + "prost-types", + "tempfile", + "which", ] [[package]] name = "prost-derive" version = "0.6.1" source = "registry+https://github.com/rust-lang/crates.io-index" +checksum = "537aa19b95acde10a12fec4301466386f757403de4cd4e5b4fa78fb5ecb18f72" dependencies = [ - "anyhow 1.0.32 (registry+https://github.com/rust-lang/crates.io-index)", - "itertools 0.8.2 (registry+https://github.com/rust-lang/crates.io-index)", - "proc-macro2 1.0.23 (registry+https://github.com/rust-lang/crates.io-index)", - "quote 1.0.7 (registry+https://github.com/rust-lang/crates.io-index)", - "syn 1.0.42 (registry+https://github.com/rust-lang/crates.io-index)", + "anyhow", + "itertools 0.8.2", + "proc-macro2", + "quote", + "syn", ] [[package]] name = "prost-types" version = "0.6.1" source = "registry+https://github.com/rust-lang/crates.io-index" +checksum = "1834f67c0697c001304b75be76f67add9c89742eda3a085ad8ee0bb38c3417aa" dependencies = [ - "bytes 0.5.6 (registry+https://github.com/rust-lang/crates.io-index)", - "prost 0.6.1 (registry+https://github.com/rust-lang/crates.io-index)", + "bytes 0.5.6", + "prost", ] [[package]] name = "proto_array" version = "0.2.0" dependencies = [ - "eth2_ssz 0.1.2", - "eth2_ssz_derive 0.1.0", - "serde 1.0.116 (registry+https://github.com/rust-lang/crates.io-index)", - "serde_derive 1.0.116 (registry+https://github.com/rust-lang/crates.io-index)", - "serde_yaml 0.8.13 (registry+https://github.com/rust-lang/crates.io-index)", - "types 0.2.0", + "eth2_ssz", + "eth2_ssz_derive", + "serde", + "serde_derive", + "serde_yaml", + "types", ] [[package]] name = "protobuf" version = "2.17.0" source = "registry+https://github.com/rust-lang/crates.io-index" +checksum = "cb14183cc7f213ee2410067e1ceeadba2a7478a59432ff0747a335202798b1e2" [[package]] name = "psutil" -version = "3.2.0" +version = "3.1.0" source = "registry+https://github.com/rust-lang/crates.io-index" +checksum = "094d0f0f32f77f62cd7d137d9b9599ef257d5c1323b36b25746679de2806f547" dependencies = [ - "cfg-if 0.1.10 (registry+https://github.com/rust-lang/crates.io-index)", - "darwin-libproc 0.1.2 (registry+https://github.com/rust-lang/crates.io-index)", - "derive_more 0.99.10 (registry+https://github.com/rust-lang/crates.io-index)", - "glob 0.3.0 (registry+https://github.com/rust-lang/crates.io-index)", - "mach 0.3.2 (registry+https://github.com/rust-lang/crates.io-index)", - "nix 0.17.0 (registry+https://github.com/rust-lang/crates.io-index)", - "num_cpus 1.13.0 (registry+https://github.com/rust-lang/crates.io-index)", - "once_cell 1.4.1 (registry+https://github.com/rust-lang/crates.io-index)", - "platforms 0.2.1 (registry+https://github.com/rust-lang/crates.io-index)", - "thiserror 1.0.20 (registry+https://github.com/rust-lang/crates.io-index)", - "unescape 0.1.0 (registry+https://github.com/rust-lang/crates.io-index)", + "cfg-if", + "darwin-libproc", + "derive_more", + "glob", + "mach", + "nix", + "num_cpus", + "once_cell", + "platforms", + "snafu", + "unescape", ] [[package]] name = "quick-error" version = "1.2.3" source = "registry+https://github.com/rust-lang/crates.io-index" +checksum = "a1d01941d82fa2ab50be1e79e6714289dd7cde78eba4c074bc5a4374f650dfe0" [[package]] name = "quickcheck" version = "0.9.2" source = "registry+https://github.com/rust-lang/crates.io-index" +checksum = "a44883e74aa97ad63db83c4bf8ca490f02b2fc02f92575e720c8551e843c945f" dependencies = [ - "env_logger 0.7.1 (registry+https://github.com/rust-lang/crates.io-index)", - "log 0.4.11 (registry+https://github.com/rust-lang/crates.io-index)", - "rand 0.7.3 (registry+https://github.com/rust-lang/crates.io-index)", - "rand_core 0.5.1 (registry+https://github.com/rust-lang/crates.io-index)", + "env_logger", + "log 0.4.11", + "rand 0.7.3", + "rand_core 0.5.1", ] [[package]] name = "quickcheck_macros" version = "0.9.1" source = "registry+https://github.com/rust-lang/crates.io-index" +checksum = "608c156fd8e97febc07dc9c2e2c80bf74cfc6ef26893eae3daf8bc2bc94a4b7f" dependencies = [ - "proc-macro2 1.0.23 (registry+https://github.com/rust-lang/crates.io-index)", - "quote 1.0.7 (registry+https://github.com/rust-lang/crates.io-index)", - "syn 1.0.42 (registry+https://github.com/rust-lang/crates.io-index)", + "proc-macro2", + "quote", + "syn", ] [[package]] name = "quicksink" version = "0.1.2" source = "registry+https://github.com/rust-lang/crates.io-index" +checksum = "77de3c815e5a160b1539c6592796801df2043ae35e123b46d73380cfa57af858" dependencies = [ - "futures-core 0.3.5 (registry+https://github.com/rust-lang/crates.io-index)", - "futures-sink 0.3.5 (registry+https://github.com/rust-lang/crates.io-index)", - "pin-project-lite 0.1.8 (registry+https://github.com/rust-lang/crates.io-index)", + "futures-core", + "futures-sink", + "pin-project-lite", ] [[package]] name = "quote" version = "1.0.7" source = "registry+https://github.com/rust-lang/crates.io-index" +checksum = "aa563d17ecb180e500da1cfd2b028310ac758de548efdd203e18f283af693f37" dependencies = [ - "proc-macro2 1.0.23 (registry+https://github.com/rust-lang/crates.io-index)", + "proc-macro2", ] [[package]] name = "r2d2" version = "0.8.9" source = "registry+https://github.com/rust-lang/crates.io-index" +checksum = "545c5bc2b880973c9c10e4067418407a0ccaa3091781d1671d46eb35107cb26f" dependencies = [ - "log 0.4.11 (registry+https://github.com/rust-lang/crates.io-index)", - "parking_lot 0.11.0 (registry+https://github.com/rust-lang/crates.io-index)", - "scheduled-thread-pool 0.2.5 (registry+https://github.com/rust-lang/crates.io-index)", + "log 0.4.11", + "parking_lot 0.11.0", + "scheduled-thread-pool", ] [[package]] name = "r2d2_sqlite" version = "0.16.0" source = "registry+https://github.com/rust-lang/crates.io-index" +checksum = "ed60ebe88b27ac28c0563bc0fbeaecd302ff53e3a01e5ddc2ec9f4e6c707d929" dependencies = [ - "r2d2 0.8.9 (registry+https://github.com/rust-lang/crates.io-index)", - "rusqlite 0.23.1 (registry+https://github.com/rust-lang/crates.io-index)", + "r2d2", + "rusqlite", ] [[package]] name = "radium" version = "0.3.0" source = "registry+https://github.com/rust-lang/crates.io-index" +checksum = "def50a86306165861203e7f84ecffbbdfdea79f0e51039b33de1e952358c47ac" [[package]] name = "rand" version = "0.4.6" source = "registry+https://github.com/rust-lang/crates.io-index" +checksum = "552840b97013b1a26992c11eac34bdd778e464601a4c2054b5f0bff7c6761293" dependencies = [ - "fuchsia-cprng 0.1.1 (registry+https://github.com/rust-lang/crates.io-index)", - "libc 0.2.77 (registry+https://github.com/rust-lang/crates.io-index)", - "rand_core 0.3.1 (registry+https://github.com/rust-lang/crates.io-index)", - "rdrand 0.4.0 (registry+https://github.com/rust-lang/crates.io-index)", - "winapi 0.3.9 (registry+https://github.com/rust-lang/crates.io-index)", + "fuchsia-cprng", + "libc", + "rand_core 0.3.1", + "rdrand", + "winapi 0.3.9", ] [[package]] name = "rand" version = "0.5.6" source = "registry+https://github.com/rust-lang/crates.io-index" +checksum = "c618c47cd3ebd209790115ab837de41425723956ad3ce2e6a7f09890947cacb9" dependencies = [ - "cloudabi 0.0.3 (registry+https://github.com/rust-lang/crates.io-index)", - "fuchsia-cprng 0.1.1 (registry+https://github.com/rust-lang/crates.io-index)", - "libc 0.2.77 (registry+https://github.com/rust-lang/crates.io-index)", - "rand_core 0.3.1 (registry+https://github.com/rust-lang/crates.io-index)", - "winapi 0.3.9 (registry+https://github.com/rust-lang/crates.io-index)", + "cloudabi 0.0.3", + "fuchsia-cprng", + "libc", + "rand_core 0.3.1", + "winapi 0.3.9", +] + +[[package]] +name = "rand" +version = "0.6.5" +source = "registry+https://github.com/rust-lang/crates.io-index" +checksum = "6d71dacdc3c88c1fde3885a3be3fbab9f35724e6ce99467f7d9c5026132184ca" +dependencies = [ + "autocfg 0.1.7", + "libc", + "rand_chacha 0.1.1", + "rand_core 0.4.2", + "rand_hc 0.1.0", + "rand_isaac", + "rand_jitter", + "rand_os", + "rand_pcg", + "rand_xorshift 0.1.1", + "winapi 0.3.9", ] [[package]] name = "rand" version = "0.7.3" source = "registry+https://github.com/rust-lang/crates.io-index" +checksum = "6a6b1679d49b24bbfe0c803429aa1874472f50d9b363131f0e89fc356b544d03" +dependencies = [ + "getrandom", + "libc", + "rand_chacha 0.2.2", + "rand_core 0.5.1", + "rand_hc 0.2.0", +] + +[[package]] +name = "rand_chacha" +version = "0.1.1" +source = "registry+https://github.com/rust-lang/crates.io-index" +checksum = "556d3a1ca6600bfcbab7c7c91ccb085ac7fbbcd70e008a98742e7847f4f7bcef" dependencies = [ - "getrandom 0.1.15 (registry+https://github.com/rust-lang/crates.io-index)", - "libc 0.2.77 (registry+https://github.com/rust-lang/crates.io-index)", - "rand_chacha 0.2.2 (registry+https://github.com/rust-lang/crates.io-index)", - "rand_core 0.5.1 (registry+https://github.com/rust-lang/crates.io-index)", - "rand_hc 0.2.0 (registry+https://github.com/rust-lang/crates.io-index)", + "autocfg 0.1.7", + "rand_core 0.3.1", ] [[package]] name = "rand_chacha" version = "0.2.2" source = "registry+https://github.com/rust-lang/crates.io-index" +checksum = "f4c8ed856279c9737206bf725bf36935d8666ead7aa69b52be55af369d193402" dependencies = [ - "ppv-lite86 0.2.9 (registry+https://github.com/rust-lang/crates.io-index)", - "rand_core 0.5.1 (registry+https://github.com/rust-lang/crates.io-index)", + "ppv-lite86", + "rand_core 0.5.1", ] [[package]] name = "rand_core" version = "0.3.1" source = "registry+https://github.com/rust-lang/crates.io-index" +checksum = "7a6fdeb83b075e8266dcc8762c22776f6877a63111121f5f8c7411e5be7eed4b" dependencies = [ - "rand_core 0.4.2 (registry+https://github.com/rust-lang/crates.io-index)", + "rand_core 0.4.2", ] [[package]] name = "rand_core" version = "0.4.2" source = "registry+https://github.com/rust-lang/crates.io-index" +checksum = "9c33a3c44ca05fa6f1807d8e6743f3824e8509beca625669633be0acbdf509dc" [[package]] name = "rand_core" version = "0.5.1" source = "registry+https://github.com/rust-lang/crates.io-index" +checksum = "90bde5296fc891b0cef12a6d03ddccc162ce7b2aff54160af9338f8d40df6d19" dependencies = [ - "getrandom 0.1.15 (registry+https://github.com/rust-lang/crates.io-index)", + "getrandom", +] + +[[package]] +name = "rand_hc" +version = "0.1.0" +source = "registry+https://github.com/rust-lang/crates.io-index" +checksum = "7b40677c7be09ae76218dc623efbf7b18e34bced3f38883af07bb75630a21bc4" +dependencies = [ + "rand_core 0.3.1", ] [[package]] name = "rand_hc" version = "0.2.0" source = "registry+https://github.com/rust-lang/crates.io-index" +checksum = "ca3129af7b92a17112d59ad498c6f81eaf463253766b90396d39ea7a39d6613c" +dependencies = [ + "rand_core 0.5.1", +] + +[[package]] +name = "rand_isaac" +version = "0.1.1" +source = "registry+https://github.com/rust-lang/crates.io-index" +checksum = "ded997c9d5f13925be2a6fd7e66bf1872597f759fd9dd93513dd7e92e5a5ee08" +dependencies = [ + "rand_core 0.3.1", +] + +[[package]] +name = "rand_jitter" +version = "0.1.4" +source = "registry+https://github.com/rust-lang/crates.io-index" +checksum = "1166d5c91dc97b88d1decc3285bb0a99ed84b05cfd0bc2341bdf2d43fc41e39b" dependencies = [ - "rand_core 0.5.1 (registry+https://github.com/rust-lang/crates.io-index)", + "libc", + "rand_core 0.4.2", + "winapi 0.3.9", +] + +[[package]] +name = "rand_os" +version = "0.1.3" +source = "registry+https://github.com/rust-lang/crates.io-index" +checksum = "7b75f676a1e053fc562eafbb47838d67c84801e38fc1ba459e8f180deabd5071" +dependencies = [ + "cloudabi 0.0.3", + "fuchsia-cprng", + "libc", + "rand_core 0.4.2", + "rdrand", + "winapi 0.3.9", +] + +[[package]] +name = "rand_pcg" +version = "0.1.2" +source = "registry+https://github.com/rust-lang/crates.io-index" +checksum = "abf9b09b01790cfe0364f52bf32995ea3c39f4d2dd011eac241d2914146d0b44" +dependencies = [ + "autocfg 0.1.7", + "rand_core 0.4.2", +] + +[[package]] +name = "rand_xorshift" +version = "0.1.1" +source = "registry+https://github.com/rust-lang/crates.io-index" +checksum = "cbf7e9e623549b0e21f6e97cf8ecf247c1a8fd2e8a992ae265314300b2455d5c" +dependencies = [ + "rand_core 0.3.1", ] [[package]] name = "rand_xorshift" version = "0.2.0" source = "registry+https://github.com/rust-lang/crates.io-index" +checksum = "77d416b86801d23dde1aa643023b775c3a462efc0ed96443add11546cdf1dca8" dependencies = [ - "rand_core 0.5.1 (registry+https://github.com/rust-lang/crates.io-index)", + "rand_core 0.5.1", ] [[package]] name = "rayon" version = "1.4.0" source = "registry+https://github.com/rust-lang/crates.io-index" +checksum = "cfd016f0c045ad38b5251be2c9c0ab806917f82da4d36b2a327e5166adad9270" dependencies = [ - "autocfg 1.0.1 (registry+https://github.com/rust-lang/crates.io-index)", - "crossbeam-deque 0.7.3 (registry+https://github.com/rust-lang/crates.io-index)", - "either 1.6.1 (registry+https://github.com/rust-lang/crates.io-index)", - "rayon-core 1.8.1 (registry+https://github.com/rust-lang/crates.io-index)", + "autocfg 1.0.1", + "crossbeam-deque", + "either", + "rayon-core", ] [[package]] name = "rayon-core" version = "1.8.1" source = "registry+https://github.com/rust-lang/crates.io-index" +checksum = "e8c4fec834fb6e6d2dd5eece3c7b432a52f0ba887cf40e595190c4107edc08bf" dependencies = [ - "crossbeam-channel 0.4.4 (registry+https://github.com/rust-lang/crates.io-index)", - "crossbeam-deque 0.7.3 (registry+https://github.com/rust-lang/crates.io-index)", - "crossbeam-utils 0.7.2 (registry+https://github.com/rust-lang/crates.io-index)", - "lazy_static 1.4.0 (registry+https://github.com/rust-lang/crates.io-index)", - "num_cpus 1.13.0 (registry+https://github.com/rust-lang/crates.io-index)", + "crossbeam-channel", + "crossbeam-deque", + "crossbeam-utils", + "lazy_static", + "num_cpus", ] [[package]] name = "rdrand" version = "0.4.0" source = "registry+https://github.com/rust-lang/crates.io-index" +checksum = "678054eb77286b51581ba43620cc911abf02758c91f93f479767aed0f90458b2" dependencies = [ - "rand_core 0.3.1 (registry+https://github.com/rust-lang/crates.io-index)", + "rand_core 0.3.1", ] [[package]] name = "redox_syscall" version = "0.1.57" source = "registry+https://github.com/rust-lang/crates.io-index" +checksum = "41cc0f7e4d5d4544e8861606a285bb08d3e70712ccc7d2b84d7c0ccfaf4b05ce" [[package]] name = "redox_users" version = "0.3.5" source = "registry+https://github.com/rust-lang/crates.io-index" +checksum = "de0737333e7a9502c789a36d7c7fa6092a49895d4faa31ca5df163857ded2e9d" dependencies = [ - "getrandom 0.1.15 (registry+https://github.com/rust-lang/crates.io-index)", - "redox_syscall 0.1.57 (registry+https://github.com/rust-lang/crates.io-index)", - "rust-argon2 0.8.2 (registry+https://github.com/rust-lang/crates.io-index)", + "getrandom", + "redox_syscall", + "rust-argon2", ] [[package]] name = "regex" version = "1.3.9" source = "registry+https://github.com/rust-lang/crates.io-index" +checksum = "9c3780fcf44b193bc4d09f36d2a3c87b251da4a046c87795a0d35f4f927ad8e6" dependencies = [ - "aho-corasick 0.7.13 (registry+https://github.com/rust-lang/crates.io-index)", - "memchr 2.3.3 (registry+https://github.com/rust-lang/crates.io-index)", - "regex-syntax 0.6.18 (registry+https://github.com/rust-lang/crates.io-index)", - "thread_local 1.0.1 (registry+https://github.com/rust-lang/crates.io-index)", + "aho-corasick", + "memchr", + "regex-syntax", + "thread_local", ] [[package]] name = "regex-automata" version = "0.1.9" source = "registry+https://github.com/rust-lang/crates.io-index" +checksum = "ae1ded71d66a4a97f5e961fd0cb25a5f366a42a41570d16a763a69c092c26ae4" dependencies = [ - "byteorder 1.3.4 (registry+https://github.com/rust-lang/crates.io-index)", + "byteorder", ] [[package]] name = "regex-syntax" version = "0.6.18" source = "registry+https://github.com/rust-lang/crates.io-index" - -[[package]] -name = "remote_beacon_node" -version = "0.2.0" -dependencies = [ - "eth2_config 0.2.0", - "eth2_ssz 0.1.2", - "futures 0.3.5 (registry+https://github.com/rust-lang/crates.io-index)", - "hex 0.4.2 (registry+https://github.com/rust-lang/crates.io-index)", - "operation_pool 0.2.0", - "proto_array 0.2.0", - "reqwest 0.10.8 (registry+https://github.com/rust-lang/crates.io-index)", - "rest_types 0.2.0", - "serde 1.0.116 (registry+https://github.com/rust-lang/crates.io-index)", - "serde_json 1.0.57 (registry+https://github.com/rust-lang/crates.io-index)", - "types 0.2.0", - "url 2.1.1 (registry+https://github.com/rust-lang/crates.io-index)", -] +checksum = "26412eb97c6b088a6997e05f69403a802a92d520de2f8e63c2b65f9e0f47c4e8" [[package]] name = "remove_dir_all" version = "0.5.3" source = "registry+https://github.com/rust-lang/crates.io-index" +checksum = "3acd125665422973a33ac9d3dd2df85edad0f4ae9b00dafb1a05e43a9f5ef8e7" dependencies = [ - "winapi 0.3.9 (registry+https://github.com/rust-lang/crates.io-index)", + "winapi 0.3.9", ] [[package]] name = "reqwest" version = "0.10.8" source = "registry+https://github.com/rust-lang/crates.io-index" -dependencies = [ - "base64 0.12.3 (registry+https://github.com/rust-lang/crates.io-index)", - "bytes 0.5.6 (registry+https://github.com/rust-lang/crates.io-index)", - "encoding_rs 0.8.24 (registry+https://github.com/rust-lang/crates.io-index)", - "futures-core 0.3.5 (registry+https://github.com/rust-lang/crates.io-index)", - "futures-util 0.3.5 (registry+https://github.com/rust-lang/crates.io-index)", - "http 0.2.1 (registry+https://github.com/rust-lang/crates.io-index)", - "http-body 0.3.1 (registry+https://github.com/rust-lang/crates.io-index)", - "hyper 0.13.8 (registry+https://github.com/rust-lang/crates.io-index)", - "hyper-tls 0.4.3 (registry+https://github.com/rust-lang/crates.io-index)", - "ipnet 2.3.0 (registry+https://github.com/rust-lang/crates.io-index)", - "js-sys 0.3.45 (registry+https://github.com/rust-lang/crates.io-index)", - "lazy_static 1.4.0 (registry+https://github.com/rust-lang/crates.io-index)", - "log 0.4.11 (registry+https://github.com/rust-lang/crates.io-index)", - "mime 0.3.16 (registry+https://github.com/rust-lang/crates.io-index)", - "mime_guess 2.0.3 (registry+https://github.com/rust-lang/crates.io-index)", - "native-tls 0.2.4 (registry+https://github.com/rust-lang/crates.io-index)", - "percent-encoding 2.1.0 (registry+https://github.com/rust-lang/crates.io-index)", - "pin-project-lite 0.1.8 (registry+https://github.com/rust-lang/crates.io-index)", - "serde 1.0.116 (registry+https://github.com/rust-lang/crates.io-index)", - "serde_json 1.0.57 (registry+https://github.com/rust-lang/crates.io-index)", - "serde_urlencoded 0.6.1 (registry+https://github.com/rust-lang/crates.io-index)", - "tokio 0.2.22 (registry+https://github.com/rust-lang/crates.io-index)", - "tokio-tls 0.3.1 (registry+https://github.com/rust-lang/crates.io-index)", - "url 2.1.1 (registry+https://github.com/rust-lang/crates.io-index)", - "wasm-bindgen 0.2.68 (registry+https://github.com/rust-lang/crates.io-index)", - "wasm-bindgen-futures 0.4.18 (registry+https://github.com/rust-lang/crates.io-index)", - "web-sys 0.3.45 (registry+https://github.com/rust-lang/crates.io-index)", - "winreg 0.7.0 (registry+https://github.com/rust-lang/crates.io-index)", -] - -[[package]] -name = "rest_api" -version = "0.2.0" -dependencies = [ - "assert_matches 1.3.0 (registry+https://github.com/rust-lang/crates.io-index)", - "beacon_chain 0.2.0", - "bls 0.2.0", - "bus 2.2.3 (registry+https://github.com/rust-lang/crates.io-index)", - "environment 0.1.2", - "eth2_config 0.2.0", - "eth2_libp2p 0.2.0", - "eth2_ssz 0.1.2", - "eth2_ssz_derive 0.1.0", - "futures 0.3.5 (registry+https://github.com/rust-lang/crates.io-index)", - "hex 0.4.2 (registry+https://github.com/rust-lang/crates.io-index)", - "http 0.2.1 (registry+https://github.com/rust-lang/crates.io-index)", - "hyper 0.13.8 (registry+https://github.com/rust-lang/crates.io-index)", - "itertools 0.9.0 (registry+https://github.com/rust-lang/crates.io-index)", - "lazy_static 1.4.0 (registry+https://github.com/rust-lang/crates.io-index)", - "lighthouse_metrics 0.2.0", - "lighthouse_version 0.1.0", - "network 0.2.0", - "node_test_rig 0.2.0", - "operation_pool 0.2.0", - "parking_lot 0.11.0 (registry+https://github.com/rust-lang/crates.io-index)", - "remote_beacon_node 0.2.0", - "rest_types 0.2.0", - "serde 1.0.116 (registry+https://github.com/rust-lang/crates.io-index)", - "serde_json 1.0.57 (registry+https://github.com/rust-lang/crates.io-index)", - "serde_yaml 0.8.13 (registry+https://github.com/rust-lang/crates.io-index)", - "slog 2.5.2 (registry+https://github.com/rust-lang/crates.io-index)", - "slog-async 2.5.0 (registry+https://github.com/rust-lang/crates.io-index)", - "slog-term 2.6.0 (registry+https://github.com/rust-lang/crates.io-index)", - "slot_clock 0.2.0", - "state_processing 0.2.0", - "store 0.2.0", - "tokio 0.2.22 (registry+https://github.com/rust-lang/crates.io-index)", - "tree_hash 0.1.1", - "types 0.2.0", - "uhttp_sse 0.5.1 (registry+https://github.com/rust-lang/crates.io-index)", - "url 2.1.1 (registry+https://github.com/rust-lang/crates.io-index)", -] - -[[package]] -name = "rest_types" -version = "0.2.0" -dependencies = [ - "beacon_chain 0.2.0", - "bls 0.2.0", - "environment 0.1.2", - "eth2_hashing 0.1.1", - "eth2_ssz 0.1.2", - "eth2_ssz_derive 0.1.0", - "hyper 0.13.8 (registry+https://github.com/rust-lang/crates.io-index)", - "procinfo 0.4.2 (registry+https://github.com/rust-lang/crates.io-index)", - "psutil 3.2.0 (registry+https://github.com/rust-lang/crates.io-index)", - "rayon 1.4.0 (registry+https://github.com/rust-lang/crates.io-index)", - "serde 1.0.116 (registry+https://github.com/rust-lang/crates.io-index)", - "serde_json 1.0.57 (registry+https://github.com/rust-lang/crates.io-index)", - "serde_yaml 0.8.13 (registry+https://github.com/rust-lang/crates.io-index)", - "state_processing 0.2.0", - "store 0.2.0", - "tokio 0.2.22 (registry+https://github.com/rust-lang/crates.io-index)", - "tree_hash 0.1.1", - "types 0.2.0", +checksum = "e9eaa17ac5d7b838b7503d118fa16ad88f440498bf9ffe5424e621f93190d61e" +dependencies = [ + "base64 0.12.3", + "bytes 0.5.6", + "encoding_rs", + "futures-core", + "futures-util", + "http 0.2.1", + "http-body 0.3.1", + "hyper 0.13.8", + "hyper-tls 0.4.3", + "ipnet", + "js-sys", + "lazy_static", + "log 0.4.11", + "mime 0.3.16", + "mime_guess", + "native-tls", + "percent-encoding 2.1.0", + "pin-project-lite", + "serde", + "serde_json", + "serde_urlencoded", + "tokio 0.2.22", + "tokio-tls 0.3.1", + "url 2.1.1", + "wasm-bindgen", + "wasm-bindgen-futures", + "web-sys", + "winreg", ] [[package]] name = "ring" version = "0.16.12" source = "registry+https://github.com/rust-lang/crates.io-index" +checksum = "1ba5a8ec64ee89a76c98c549af81ff14813df09c3e6dc4766c3856da48597a0c" dependencies = [ - "cc 1.0.41 (registry+https://github.com/rust-lang/crates.io-index)", - "lazy_static 1.4.0 (registry+https://github.com/rust-lang/crates.io-index)", - "libc 0.2.77 (registry+https://github.com/rust-lang/crates.io-index)", - "spin 0.5.2 (registry+https://github.com/rust-lang/crates.io-index)", - "untrusted 0.7.1 (registry+https://github.com/rust-lang/crates.io-index)", - "web-sys 0.3.45 (registry+https://github.com/rust-lang/crates.io-index)", - "winapi 0.3.9 (registry+https://github.com/rust-lang/crates.io-index)", + "cc", + "lazy_static", + "libc", + "spin", + "untrusted", + "web-sys", + "winapi 0.3.9", ] [[package]] name = "rle-decode-fast" version = "1.0.1" source = "registry+https://github.com/rust-lang/crates.io-index" +checksum = "cabe4fa914dec5870285fa7f71f602645da47c486e68486d2b4ceb4a343e90ac" [[package]] name = "rlp" version = "0.4.5" source = "registry+https://github.com/rust-lang/crates.io-index" +checksum = "4a7d3f9bed94764eac15b8f14af59fac420c236adaff743b7bcc88e265cb4345" dependencies = [ - "rustc-hex 2.1.0 (registry+https://github.com/rust-lang/crates.io-index)", + "rustc-hex", ] [[package]] name = "rpassword" version = "4.0.5" source = "registry+https://github.com/rust-lang/crates.io-index" +checksum = "99371657d3c8e4d816fb6221db98fa408242b0b53bac08f8676a41f8554fe99f" dependencies = [ - "libc 0.2.77 (registry+https://github.com/rust-lang/crates.io-index)", - "winapi 0.3.9 (registry+https://github.com/rust-lang/crates.io-index)", + "libc", + "winapi 0.3.9", ] [[package]] name = "rusqlite" version = "0.23.1" source = "registry+https://github.com/rust-lang/crates.io-index" +checksum = "45d0fd62e1df63d254714e6cb40d0a0e82e7a1623e7a27f679d851af092ae58b" dependencies = [ - "bitflags 1.2.1 (registry+https://github.com/rust-lang/crates.io-index)", - "fallible-iterator 0.2.0 (registry+https://github.com/rust-lang/crates.io-index)", - "fallible-streaming-iterator 0.1.9 (registry+https://github.com/rust-lang/crates.io-index)", - "libsqlite3-sys 0.18.0 (registry+https://github.com/rust-lang/crates.io-index)", - "lru-cache 0.1.2 (registry+https://github.com/rust-lang/crates.io-index)", - "memchr 2.3.3 (registry+https://github.com/rust-lang/crates.io-index)", - "smallvec 1.4.2 (registry+https://github.com/rust-lang/crates.io-index)", - "time 0.1.44 (registry+https://github.com/rust-lang/crates.io-index)", + "bitflags 1.2.1", + "fallible-iterator", + "fallible-streaming-iterator", + "libsqlite3-sys", + "lru-cache", + "memchr", + "smallvec 1.4.2", + "time 0.1.44", ] [[package]] name = "rust-argon2" version = "0.8.2" source = "registry+https://github.com/rust-lang/crates.io-index" +checksum = "9dab61250775933275e84053ac235621dfb739556d5c54a2f2e9313b7cf43a19" dependencies = [ - "base64 0.12.3 (registry+https://github.com/rust-lang/crates.io-index)", - "blake2b_simd 0.5.10 (registry+https://github.com/rust-lang/crates.io-index)", - "constant_time_eq 0.1.5 (registry+https://github.com/rust-lang/crates.io-index)", - "crossbeam-utils 0.7.2 (registry+https://github.com/rust-lang/crates.io-index)", + "base64 0.12.3", + "blake2b_simd", + "constant_time_eq", + "crossbeam-utils", ] [[package]] name = "rustc-demangle" version = "0.1.16" source = "registry+https://github.com/rust-lang/crates.io-index" +checksum = "4c691c0e608126e00913e33f0ccf3727d5fc84573623b8d65b2df340b5201783" [[package]] name = "rustc-hash" version = "1.1.0" source = "registry+https://github.com/rust-lang/crates.io-index" +checksum = "08d43f7aa6b08d49f382cde6a7982047c3426db949b1424bc4b7ec9ae12c6ce2" [[package]] name = "rustc-hex" version = "2.1.0" source = "registry+https://github.com/rust-lang/crates.io-index" +checksum = "3e75f6a532d0fd9f7f13144f392b6ad56a32696bfcd9c78f797f16bbb6f072d6" [[package]] name = "rustc_version" version = "0.2.3" source = "registry+https://github.com/rust-lang/crates.io-index" +checksum = "138e3e0acb6c9fb258b19b67cb8abd63c00679d2851805ea151465464fe9030a" dependencies = [ - "semver 0.9.0 (registry+https://github.com/rust-lang/crates.io-index)", + "semver", ] [[package]] name = "rustls" version = "0.18.1" source = "registry+https://github.com/rust-lang/crates.io-index" +checksum = "5d1126dcf58e93cee7d098dbda643b5f92ed724f1f6a63007c1116eed6700c81" dependencies = [ - "base64 0.12.3 (registry+https://github.com/rust-lang/crates.io-index)", - "log 0.4.11 (registry+https://github.com/rust-lang/crates.io-index)", - "ring 0.16.12 (registry+https://github.com/rust-lang/crates.io-index)", - "sct 0.6.0 (registry+https://github.com/rust-lang/crates.io-index)", - "webpki 0.21.2 (registry+https://github.com/rust-lang/crates.io-index)", + "base64 0.12.3", + "log 0.4.11", + "ring", + "sct", + "webpki", ] [[package]] name = "rw-stream-sink" version = "0.2.1" source = "registry+https://github.com/rust-lang/crates.io-index" +checksum = "4da5fcb054c46f5a5dff833b129285a93d3f0179531735e6c866e8cc307d2020" dependencies = [ - "futures 0.3.5 (registry+https://github.com/rust-lang/crates.io-index)", - "pin-project 0.4.24 (registry+https://github.com/rust-lang/crates.io-index)", - "static_assertions 1.1.0 (registry+https://github.com/rust-lang/crates.io-index)", + "futures 0.3.5", + "pin-project", + "static_assertions", ] [[package]] name = "ryu" version = "1.0.5" source = "registry+https://github.com/rust-lang/crates.io-index" +checksum = "71d301d4193d031abdd79ff7e3dd721168a9572ef3fe51a1517aba235bd8f86e" [[package]] name = "safe_arith" @@ -4126,1379 +4592,1565 @@ version = "0.1.0" name = "safemem" version = "0.3.3" source = "registry+https://github.com/rust-lang/crates.io-index" +checksum = "ef703b7cb59335eae2eb93ceb664c0eb7ea6bf567079d843e09420219668e072" [[package]] name = "same-file" version = "1.0.6" source = "registry+https://github.com/rust-lang/crates.io-index" +checksum = "93fc1dc3aaa9bfed95e02e6eadabb4baf7e3078b0bd1b4d7b6b0b68378900502" dependencies = [ - "winapi-util 0.1.5 (registry+https://github.com/rust-lang/crates.io-index)", + "winapi-util", ] [[package]] name = "schannel" version = "0.1.19" source = "registry+https://github.com/rust-lang/crates.io-index" +checksum = "8f05ba609c234e60bee0d547fe94a4c7e9da733d1c962cf6e59efa4cd9c8bc75" dependencies = [ - "lazy_static 1.4.0 (registry+https://github.com/rust-lang/crates.io-index)", - "winapi 0.3.9 (registry+https://github.com/rust-lang/crates.io-index)", + "lazy_static", + "winapi 0.3.9", ] [[package]] name = "scheduled-thread-pool" version = "0.2.5" source = "registry+https://github.com/rust-lang/crates.io-index" +checksum = "dc6f74fd1204073fa02d5d5d68bec8021be4c38690b61264b2fdb48083d0e7d7" dependencies = [ - "parking_lot 0.11.0 (registry+https://github.com/rust-lang/crates.io-index)", + "parking_lot 0.11.0", ] [[package]] name = "scoped-tls" version = "0.1.2" source = "registry+https://github.com/rust-lang/crates.io-index" +checksum = "332ffa32bf586782a3efaeb58f127980944bbc8c4d6913a86107ac2a5ab24b28" [[package]] name = "scoped-tls" version = "1.0.0" source = "registry+https://github.com/rust-lang/crates.io-index" +checksum = "ea6a9290e3c9cf0f18145ef7ffa62d68ee0bf5fcd651017e586dc7fd5da448c2" [[package]] name = "scopeguard" version = "1.1.0" source = "registry+https://github.com/rust-lang/crates.io-index" +checksum = "d29ab0c6d3fc0ee92fe66e2d99f700eab17a8d57d1c1d3b748380fb20baa78cd" [[package]] name = "scrypt" version = "0.3.1" source = "registry+https://github.com/rust-lang/crates.io-index" +checksum = "10e7e75e27e8cd47e4be027d4b9fdc0b696116f981c22de21ca7bad63a9cb33a" dependencies = [ - "hmac 0.8.1 (registry+https://github.com/rust-lang/crates.io-index)", - "pbkdf2 0.4.0 (registry+https://github.com/rust-lang/crates.io-index)", - "sha2 0.9.1 (registry+https://github.com/rust-lang/crates.io-index)", + "hmac 0.8.1", + "pbkdf2 0.4.0", + "sha2 0.9.1", ] [[package]] name = "sct" version = "0.6.0" source = "registry+https://github.com/rust-lang/crates.io-index" +checksum = "e3042af939fca8c3453b7af0f1c66e533a15a86169e39de2657310ade8f98d3c" dependencies = [ - "ring 0.16.12 (registry+https://github.com/rust-lang/crates.io-index)", - "untrusted 0.7.1 (registry+https://github.com/rust-lang/crates.io-index)", + "ring", + "untrusted", ] [[package]] name = "secp256k1" version = "0.17.2" source = "registry+https://github.com/rust-lang/crates.io-index" +checksum = "2932dc07acd2066ff2e3921a4419606b220ba6cd03a9935123856cc534877056" dependencies = [ - "secp256k1-sys 0.1.2 (registry+https://github.com/rust-lang/crates.io-index)", + "secp256k1-sys", ] [[package]] name = "secp256k1-sys" version = "0.1.2" source = "registry+https://github.com/rust-lang/crates.io-index" +checksum = "7ab2c26f0d3552a0f12e639ae8a64afc2e3db9c52fe32f5fc6c289d38519f220" dependencies = [ - "cc 1.0.41 (registry+https://github.com/rust-lang/crates.io-index)", + "cc", ] [[package]] name = "security-framework" version = "0.4.4" source = "registry+https://github.com/rust-lang/crates.io-index" +checksum = "64808902d7d99f78eaddd2b4e2509713babc3dc3c85ad6f4c447680f3c01e535" dependencies = [ - "bitflags 1.2.1 (registry+https://github.com/rust-lang/crates.io-index)", - "core-foundation 0.7.0 (registry+https://github.com/rust-lang/crates.io-index)", - "core-foundation-sys 0.7.0 (registry+https://github.com/rust-lang/crates.io-index)", - "libc 0.2.77 (registry+https://github.com/rust-lang/crates.io-index)", - "security-framework-sys 0.4.3 (registry+https://github.com/rust-lang/crates.io-index)", + "bitflags 1.2.1", + "core-foundation", + "core-foundation-sys", + "libc", + "security-framework-sys", ] [[package]] name = "security-framework-sys" version = "0.4.3" source = "registry+https://github.com/rust-lang/crates.io-index" +checksum = "17bf11d99252f512695eb468de5516e5cf75455521e69dfe343f3b74e4748405" dependencies = [ - "core-foundation-sys 0.7.0 (registry+https://github.com/rust-lang/crates.io-index)", - "libc 0.2.77 (registry+https://github.com/rust-lang/crates.io-index)", + "core-foundation-sys", + "libc", ] [[package]] name = "semver" version = "0.9.0" source = "registry+https://github.com/rust-lang/crates.io-index" +checksum = "1d7eb9ef2c18661902cc47e535f9bc51b78acd254da71d375c2f6720d9a40403" dependencies = [ - "semver-parser 0.7.0 (registry+https://github.com/rust-lang/crates.io-index)", + "semver-parser", ] [[package]] name = "semver-parser" version = "0.7.0" source = "registry+https://github.com/rust-lang/crates.io-index" +checksum = "388a1df253eca08550bef6c72392cfe7c30914bf41df5269b68cbd6ff8f570a3" [[package]] name = "serde" version = "1.0.116" source = "registry+https://github.com/rust-lang/crates.io-index" +checksum = "96fe57af81d28386a513cbc6858332abc6117cfdb5999647c6444b8f43a370a5" dependencies = [ - "serde_derive 1.0.116 (registry+https://github.com/rust-lang/crates.io-index)", + "serde_derive", ] [[package]] name = "serde_cbor" version = "0.11.1" source = "registry+https://github.com/rust-lang/crates.io-index" +checksum = "1e18acfa2f90e8b735b2836ab8d538de304cbb6729a7360729ea5a895d15a622" dependencies = [ - "half 1.6.0 (registry+https://github.com/rust-lang/crates.io-index)", - "serde 1.0.116 (registry+https://github.com/rust-lang/crates.io-index)", + "half", + "serde", ] [[package]] name = "serde_derive" version = "1.0.116" source = "registry+https://github.com/rust-lang/crates.io-index" +checksum = "f630a6370fd8e457873b4bd2ffdae75408bc291ba72be773772a4c2a065d9ae8" dependencies = [ - "proc-macro2 1.0.23 (registry+https://github.com/rust-lang/crates.io-index)", - "quote 1.0.7 (registry+https://github.com/rust-lang/crates.io-index)", - "syn 1.0.42 (registry+https://github.com/rust-lang/crates.io-index)", -] - -[[package]] -name = "serde_hex" -version = "0.2.0" -dependencies = [ - "hex 0.4.2 (registry+https://github.com/rust-lang/crates.io-index)", - "serde 1.0.116 (registry+https://github.com/rust-lang/crates.io-index)", + "proc-macro2", + "quote", + "syn", ] [[package]] name = "serde_json" version = "1.0.57" source = "registry+https://github.com/rust-lang/crates.io-index" +checksum = "164eacbdb13512ec2745fb09d51fd5b22b0d65ed294a1dcf7285a360c80a675c" dependencies = [ - "itoa 0.4.6 (registry+https://github.com/rust-lang/crates.io-index)", - "ryu 1.0.5 (registry+https://github.com/rust-lang/crates.io-index)", - "serde 1.0.116 (registry+https://github.com/rust-lang/crates.io-index)", + "itoa", + "ryu", + "serde", ] [[package]] name = "serde_repr" version = "0.1.6" source = "registry+https://github.com/rust-lang/crates.io-index" +checksum = "2dc6b7951b17b051f3210b063f12cc17320e2fe30ae05b0fe2a3abb068551c76" dependencies = [ - "proc-macro2 1.0.23 (registry+https://github.com/rust-lang/crates.io-index)", - "quote 1.0.7 (registry+https://github.com/rust-lang/crates.io-index)", - "syn 1.0.42 (registry+https://github.com/rust-lang/crates.io-index)", + "proc-macro2", + "quote", + "syn", ] [[package]] name = "serde_urlencoded" version = "0.6.1" source = "registry+https://github.com/rust-lang/crates.io-index" +checksum = "9ec5d77e2d4c73717816afac02670d5c4f534ea95ed430442cad02e7a6e32c97" dependencies = [ - "dtoa 0.4.6 (registry+https://github.com/rust-lang/crates.io-index)", - "itoa 0.4.6 (registry+https://github.com/rust-lang/crates.io-index)", - "serde 1.0.116 (registry+https://github.com/rust-lang/crates.io-index)", - "url 2.1.1 (registry+https://github.com/rust-lang/crates.io-index)", + "dtoa", + "itoa", + "serde", + "url 2.1.1", ] [[package]] name = "serde_utils" version = "0.1.0" dependencies = [ - "serde 1.0.116 (registry+https://github.com/rust-lang/crates.io-index)", - "serde_derive 1.0.116 (registry+https://github.com/rust-lang/crates.io-index)", - "serde_json 1.0.57 (registry+https://github.com/rust-lang/crates.io-index)", + "hex 0.4.2", + "serde", + "serde_derive", + "serde_json", ] [[package]] name = "serde_yaml" version = "0.8.13" source = "registry+https://github.com/rust-lang/crates.io-index" +checksum = "ae3e2dd40a7cdc18ca80db804b7f461a39bb721160a85c9a1fa30134bf3c02a5" dependencies = [ - "dtoa 0.4.6 (registry+https://github.com/rust-lang/crates.io-index)", - "linked-hash-map 0.5.3 (registry+https://github.com/rust-lang/crates.io-index)", - "serde 1.0.116 (registry+https://github.com/rust-lang/crates.io-index)", - "yaml-rust 0.4.4 (registry+https://github.com/rust-lang/crates.io-index)", + "dtoa", + "linked-hash-map", + "serde", + "yaml-rust", ] [[package]] name = "sha-1" version = "0.8.2" source = "registry+https://github.com/rust-lang/crates.io-index" +checksum = "f7d94d0bede923b3cea61f3f1ff57ff8cdfd77b400fb8f9998949e0cf04163df" dependencies = [ - "block-buffer 0.7.3 (registry+https://github.com/rust-lang/crates.io-index)", - "digest 0.8.1 (registry+https://github.com/rust-lang/crates.io-index)", - "fake-simd 0.1.2 (registry+https://github.com/rust-lang/crates.io-index)", - "opaque-debug 0.2.3 (registry+https://github.com/rust-lang/crates.io-index)", + "block-buffer 0.7.3", + "digest 0.8.1", + "fake-simd", + "opaque-debug 0.2.3", ] [[package]] name = "sha-1" version = "0.9.1" source = "registry+https://github.com/rust-lang/crates.io-index" +checksum = "170a36ea86c864a3f16dd2687712dd6646f7019f301e57537c7f4dc9f5916770" dependencies = [ - "block-buffer 0.9.0 (registry+https://github.com/rust-lang/crates.io-index)", - "cfg-if 0.1.10 (registry+https://github.com/rust-lang/crates.io-index)", - "cpuid-bool 0.1.2 (registry+https://github.com/rust-lang/crates.io-index)", - "digest 0.9.0 (registry+https://github.com/rust-lang/crates.io-index)", - "opaque-debug 0.3.0 (registry+https://github.com/rust-lang/crates.io-index)", + "block-buffer 0.9.0", + "cfg-if", + "cpuid-bool", + "digest 0.9.0", + "opaque-debug 0.3.0", ] [[package]] name = "sha1" version = "0.6.0" source = "registry+https://github.com/rust-lang/crates.io-index" +checksum = "2579985fda508104f7587689507983eadd6a6e84dd35d6d115361f530916fa0d" [[package]] name = "sha2" version = "0.8.2" source = "registry+https://github.com/rust-lang/crates.io-index" +checksum = "a256f46ea78a0c0d9ff00077504903ac881a1dafdc20da66545699e7776b3e69" dependencies = [ - "block-buffer 0.7.3 (registry+https://github.com/rust-lang/crates.io-index)", - "digest 0.8.1 (registry+https://github.com/rust-lang/crates.io-index)", - "fake-simd 0.1.2 (registry+https://github.com/rust-lang/crates.io-index)", - "opaque-debug 0.2.3 (registry+https://github.com/rust-lang/crates.io-index)", + "block-buffer 0.7.3", + "digest 0.8.1", + "fake-simd", + "opaque-debug 0.2.3", ] [[package]] name = "sha2" version = "0.9.1" source = "registry+https://github.com/rust-lang/crates.io-index" +checksum = "2933378ddfeda7ea26f48c555bdad8bb446bf8a3d17832dc83e380d444cfb8c1" dependencies = [ - "block-buffer 0.9.0 (registry+https://github.com/rust-lang/crates.io-index)", - "cfg-if 0.1.10 (registry+https://github.com/rust-lang/crates.io-index)", - "cpuid-bool 0.1.2 (registry+https://github.com/rust-lang/crates.io-index)", - "digest 0.9.0 (registry+https://github.com/rust-lang/crates.io-index)", - "opaque-debug 0.3.0 (registry+https://github.com/rust-lang/crates.io-index)", + "block-buffer 0.9.0", + "cfg-if", + "cpuid-bool", + "digest 0.9.0", + "opaque-debug 0.3.0", ] [[package]] name = "sha3" version = "0.9.1" source = "registry+https://github.com/rust-lang/crates.io-index" +checksum = "f81199417d4e5de3f04b1e871023acea7389672c4135918f05aa9cbf2f2fa809" dependencies = [ - "block-buffer 0.9.0 (registry+https://github.com/rust-lang/crates.io-index)", - "digest 0.9.0 (registry+https://github.com/rust-lang/crates.io-index)", - "keccak 0.1.0 (registry+https://github.com/rust-lang/crates.io-index)", - "opaque-debug 0.3.0 (registry+https://github.com/rust-lang/crates.io-index)", + "block-buffer 0.9.0", + "digest 0.9.0", + "keccak", + "opaque-debug 0.3.0", ] [[package]] name = "signal-hook-registry" version = "1.2.1" source = "registry+https://github.com/rust-lang/crates.io-index" +checksum = "a3e12110bc539e657a646068aaf5eb5b63af9d0c1f7b29c97113fad80e15f035" dependencies = [ - "arc-swap 0.4.7 (registry+https://github.com/rust-lang/crates.io-index)", - "libc 0.2.77 (registry+https://github.com/rust-lang/crates.io-index)", + "arc-swap", + "libc", ] [[package]] name = "signature" version = "1.2.2" source = "registry+https://github.com/rust-lang/crates.io-index" +checksum = "29f060a7d147e33490ec10da418795238fd7545bba241504d6b31a409f2e6210" [[package]] name = "simple_logger" version = "1.9.0" source = "registry+https://github.com/rust-lang/crates.io-index" +checksum = "13a53ed2efd04911c8280f2da7bf9abd350c931b86bc7f9f2386fbafbf525ff9" dependencies = [ - "atty 0.2.14 (registry+https://github.com/rust-lang/crates.io-index)", - "chrono 0.4.18 (registry+https://github.com/rust-lang/crates.io-index)", - "colored 1.9.3 (registry+https://github.com/rust-lang/crates.io-index)", - "log 0.4.11 (registry+https://github.com/rust-lang/crates.io-index)", - "winapi 0.3.9 (registry+https://github.com/rust-lang/crates.io-index)", + "atty", + "chrono", + "colored", + "log 0.4.11", + "winapi 0.3.9", ] [[package]] name = "simulator" version = "0.2.0" dependencies = [ - "clap 2.33.3 (registry+https://github.com/rust-lang/crates.io-index)", - "env_logger 0.7.1 (registry+https://github.com/rust-lang/crates.io-index)", - "eth1 0.2.0", - "eth1_test_rig 0.2.0", - "futures 0.3.5 (registry+https://github.com/rust-lang/crates.io-index)", - "node_test_rig 0.2.0", - "parking_lot 0.11.0 (registry+https://github.com/rust-lang/crates.io-index)", - "rayon 1.4.0 (registry+https://github.com/rust-lang/crates.io-index)", - "tokio 0.2.22 (registry+https://github.com/rust-lang/crates.io-index)", - "types 0.2.0", - "validator_client 0.2.12", + "clap", + "env_logger", + "eth1", + "eth1_test_rig", + "futures 0.3.5", + "node_test_rig", + "parking_lot 0.11.0", + "rayon", + "tokio 0.2.22", + "types", + "validator_client", ] [[package]] name = "slab" version = "0.3.0" source = "registry+https://github.com/rust-lang/crates.io-index" +checksum = "17b4fcaed89ab08ef143da37bc52adbcc04d4a69014f4c1208d6b51f0c47bc23" [[package]] name = "slab" version = "0.4.2" source = "registry+https://github.com/rust-lang/crates.io-index" +checksum = "c111b5bd5695e56cffe5129854aa230b39c93a305372fdbb2668ca2394eea9f8" [[package]] name = "slashing_protection" version = "0.1.0" dependencies = [ - "parking_lot 0.11.0 (registry+https://github.com/rust-lang/crates.io-index)", - "r2d2 0.8.9 (registry+https://github.com/rust-lang/crates.io-index)", - "r2d2_sqlite 0.16.0 (registry+https://github.com/rust-lang/crates.io-index)", - "rayon 1.4.0 (registry+https://github.com/rust-lang/crates.io-index)", - "rusqlite 0.23.1 (registry+https://github.com/rust-lang/crates.io-index)", - "tempfile 3.1.0 (registry+https://github.com/rust-lang/crates.io-index)", - "tree_hash 0.1.1", - "types 0.2.0", + "parking_lot 0.11.0", + "r2d2", + "r2d2_sqlite", + "rayon", + "rusqlite", + "tempfile", + "tree_hash", + "types", ] [[package]] name = "slog" version = "2.5.2" source = "registry+https://github.com/rust-lang/crates.io-index" +checksum = "1cc9c640a4adbfbcc11ffb95efe5aa7af7309e002adab54b185507dbf2377b99" [[package]] name = "slog-async" version = "2.5.0" source = "registry+https://github.com/rust-lang/crates.io-index" +checksum = "51b3336ce47ce2f96673499fc07eb85e3472727b9a7a2959964b002c2ce8fbbb" dependencies = [ - "crossbeam-channel 0.4.4 (registry+https://github.com/rust-lang/crates.io-index)", - "slog 2.5.2 (registry+https://github.com/rust-lang/crates.io-index)", - "take_mut 0.2.2 (registry+https://github.com/rust-lang/crates.io-index)", - "thread_local 1.0.1 (registry+https://github.com/rust-lang/crates.io-index)", + "crossbeam-channel", + "slog", + "take_mut", + "thread_local", ] [[package]] name = "slog-json" version = "2.3.0" source = "registry+https://github.com/rust-lang/crates.io-index" +checksum = "ddc0d2aff1f8f325ef660d9a0eb6e6dcd20b30b3f581a5897f58bf42d061c37a" dependencies = [ - "chrono 0.4.18 (registry+https://github.com/rust-lang/crates.io-index)", - "serde 1.0.116 (registry+https://github.com/rust-lang/crates.io-index)", - "serde_json 1.0.57 (registry+https://github.com/rust-lang/crates.io-index)", - "slog 2.5.2 (registry+https://github.com/rust-lang/crates.io-index)", + "chrono", + "serde", + "serde_json", + "slog", ] [[package]] name = "slog-kvfilter" version = "0.7.0" source = "registry+https://github.com/rust-lang/crates.io-index" +checksum = "ae939ed7d169eed9699f4f5cd440f046f5dc5dfc27c19e3cd311619594c175e0" dependencies = [ - "regex 1.3.9 (registry+https://github.com/rust-lang/crates.io-index)", - "slog 2.5.2 (registry+https://github.com/rust-lang/crates.io-index)", + "regex", + "slog", ] [[package]] name = "slog-scope" version = "4.3.0" source = "registry+https://github.com/rust-lang/crates.io-index" +checksum = "7c44c89dd8b0ae4537d1ae318353eaf7840b4869c536e31c41e963d1ea523ee6" dependencies = [ - "arc-swap 0.4.7 (registry+https://github.com/rust-lang/crates.io-index)", - "lazy_static 1.4.0 (registry+https://github.com/rust-lang/crates.io-index)", - "slog 2.5.2 (registry+https://github.com/rust-lang/crates.io-index)", + "arc-swap", + "lazy_static", + "slog", ] [[package]] name = "slog-stdlog" version = "4.0.0" source = "registry+https://github.com/rust-lang/crates.io-index" +checksum = "be4d87903baf655da2d82bc3ac3f7ef43868c58bf712b3a661fda72009304c23" dependencies = [ - "crossbeam 0.7.3 (registry+https://github.com/rust-lang/crates.io-index)", - "log 0.4.11 (registry+https://github.com/rust-lang/crates.io-index)", - "slog 2.5.2 (registry+https://github.com/rust-lang/crates.io-index)", - "slog-scope 4.3.0 (registry+https://github.com/rust-lang/crates.io-index)", + "crossbeam", + "log 0.4.11", + "slog", + "slog-scope", ] [[package]] name = "slog-term" version = "2.6.0" source = "registry+https://github.com/rust-lang/crates.io-index" +checksum = "bab1d807cf71129b05ce36914e1dbb6fbfbdecaf686301cb457f4fa967f9f5b6" dependencies = [ - "atty 0.2.14 (registry+https://github.com/rust-lang/crates.io-index)", - "chrono 0.4.18 (registry+https://github.com/rust-lang/crates.io-index)", - "slog 2.5.2 (registry+https://github.com/rust-lang/crates.io-index)", - "term 0.6.1 (registry+https://github.com/rust-lang/crates.io-index)", - "thread_local 1.0.1 (registry+https://github.com/rust-lang/crates.io-index)", + "atty", + "chrono", + "slog", + "term", + "thread_local", ] [[package]] name = "sloggers" version = "1.0.1" source = "registry+https://github.com/rust-lang/crates.io-index" +checksum = "f01d37507aa6f37490cfa08d71e2639b16906e84c285ae4b9f7ec7ca35756d69" dependencies = [ - "chrono 0.4.18 (registry+https://github.com/rust-lang/crates.io-index)", - "libflate 1.0.2 (registry+https://github.com/rust-lang/crates.io-index)", - "regex 1.3.9 (registry+https://github.com/rust-lang/crates.io-index)", - "serde 1.0.116 (registry+https://github.com/rust-lang/crates.io-index)", - "slog 2.5.2 (registry+https://github.com/rust-lang/crates.io-index)", - "slog-async 2.5.0 (registry+https://github.com/rust-lang/crates.io-index)", - "slog-kvfilter 0.7.0 (registry+https://github.com/rust-lang/crates.io-index)", - "slog-scope 4.3.0 (registry+https://github.com/rust-lang/crates.io-index)", - "slog-stdlog 4.0.0 (registry+https://github.com/rust-lang/crates.io-index)", - "slog-term 2.6.0 (registry+https://github.com/rust-lang/crates.io-index)", - "trackable 1.0.0 (registry+https://github.com/rust-lang/crates.io-index)", + "chrono", + "libflate", + "regex", + "serde", + "slog", + "slog-async", + "slog-kvfilter", + "slog-scope", + "slog-stdlog", + "slog-term", + "trackable", ] [[package]] name = "slot_clock" version = "0.2.0" dependencies = [ - "lazy_static 1.4.0 (registry+https://github.com/rust-lang/crates.io-index)", - "lighthouse_metrics 0.2.0", - "parking_lot 0.11.0 (registry+https://github.com/rust-lang/crates.io-index)", - "types 0.2.0", + "lazy_static", + "lighthouse_metrics", + "parking_lot 0.11.0", + "types", ] [[package]] name = "smallvec" version = "0.6.13" source = "registry+https://github.com/rust-lang/crates.io-index" +checksum = "f7b0758c52e15a8b5e3691eae6cc559f08eee9406e548a4477ba4e67770a82b6" dependencies = [ - "maybe-uninit 2.0.0 (registry+https://github.com/rust-lang/crates.io-index)", + "maybe-uninit", ] [[package]] name = "smallvec" version = "1.4.2" source = "registry+https://github.com/rust-lang/crates.io-index" +checksum = "fbee7696b84bbf3d89a1c2eccff0850e3047ed46bfcd2e92c29a2d074d57e252" + +[[package]] +name = "snafu" +version = "0.6.9" +source = "registry+https://github.com/rust-lang/crates.io-index" +checksum = "9c4e6046e4691afe918fd1b603fd6e515bcda5388a1092a9edbada307d159f09" +dependencies = [ + "doc-comment", + "snafu-derive", +] + +[[package]] +name = "snafu-derive" +version = "0.6.9" +source = "registry+https://github.com/rust-lang/crates.io-index" +checksum = "7073448732a89f2f3e6581989106067f403d378faeafb4a50812eb814170d3e5" +dependencies = [ + "proc-macro2", + "quote", + "syn", +] [[package]] name = "snap" version = "1.0.1" source = "registry+https://github.com/rust-lang/crates.io-index" +checksum = "da73c8f77aebc0e40c300b93f0a5f1bece7a248a36eee287d4e095f35c7b7d6e" [[package]] name = "snow" version = "0.7.1" source = "registry+https://github.com/rust-lang/crates.io-index" +checksum = "32bf8474159a95551661246cda4976e89356999e3cbfef36f493dacc3fae1e8e" dependencies = [ - "aes-gcm 0.6.0 (registry+https://github.com/rust-lang/crates.io-index)", - "blake2 0.9.0 (registry+https://github.com/rust-lang/crates.io-index)", - "chacha20poly1305 0.5.1 (registry+https://github.com/rust-lang/crates.io-index)", - "rand 0.7.3 (registry+https://github.com/rust-lang/crates.io-index)", - "rand_core 0.5.1 (registry+https://github.com/rust-lang/crates.io-index)", - "ring 0.16.12 (registry+https://github.com/rust-lang/crates.io-index)", - "rustc_version 0.2.3 (registry+https://github.com/rust-lang/crates.io-index)", - "sha2 0.9.1 (registry+https://github.com/rust-lang/crates.io-index)", - "subtle 2.3.0 (registry+https://github.com/rust-lang/crates.io-index)", - "x25519-dalek 0.6.0 (registry+https://github.com/rust-lang/crates.io-index)", + "aes-gcm", + "blake2", + "chacha20poly1305", + "rand 0.7.3", + "rand_core 0.5.1", + "ring", + "rustc_version", + "sha2 0.9.1", + "subtle 2.3.0", + "x25519-dalek", ] [[package]] name = "socket2" version = "0.3.15" source = "registry+https://github.com/rust-lang/crates.io-index" +checksum = "b1fa70dc5c8104ec096f4fe7ede7a221d35ae13dcd19ba1ad9a81d2cab9a1c44" dependencies = [ - "cfg-if 0.1.10 (registry+https://github.com/rust-lang/crates.io-index)", - "libc 0.2.77 (registry+https://github.com/rust-lang/crates.io-index)", - "redox_syscall 0.1.57 (registry+https://github.com/rust-lang/crates.io-index)", - "winapi 0.3.9 (registry+https://github.com/rust-lang/crates.io-index)", + "cfg-if", + "libc", + "redox_syscall", + "winapi 0.3.9", ] [[package]] name = "soketto" version = "0.4.2" source = "registry+https://github.com/rust-lang/crates.io-index" +checksum = "b5c71ed3d54db0a699f4948e1bb3e45b450fa31fe602621dee6680361d569c88" dependencies = [ - "base64 0.12.3 (registry+https://github.com/rust-lang/crates.io-index)", - "bytes 0.5.6 (registry+https://github.com/rust-lang/crates.io-index)", - "flate2 1.0.17 (registry+https://github.com/rust-lang/crates.io-index)", - "futures 0.3.5 (registry+https://github.com/rust-lang/crates.io-index)", - "httparse 1.3.4 (registry+https://github.com/rust-lang/crates.io-index)", - "log 0.4.11 (registry+https://github.com/rust-lang/crates.io-index)", - "rand 0.7.3 (registry+https://github.com/rust-lang/crates.io-index)", - "sha-1 0.9.1 (registry+https://github.com/rust-lang/crates.io-index)", + "base64 0.12.3", + "bytes 0.5.6", + "flate2", + "futures 0.3.5", + "httparse", + "log 0.4.11", + "rand 0.7.3", + "sha-1 0.9.1", ] [[package]] name = "spin" version = "0.5.2" source = "registry+https://github.com/rust-lang/crates.io-index" +checksum = "6e63cff320ae2c57904679ba7cb63280a3dc4613885beafb148ee7bf9aa9042d" [[package]] name = "standback" version = "0.2.10" source = "registry+https://github.com/rust-lang/crates.io-index" +checksum = "33a71ea1ea5f8747d1af1979bfb7e65c3a025a70609f04ceb78425bc5adad8e6" dependencies = [ - "version_check 0.9.2 (registry+https://github.com/rust-lang/crates.io-index)", + "version_check 0.9.2", ] [[package]] name = "state_processing" version = "0.2.0" dependencies = [ - "arbitrary 0.4.6 (registry+https://github.com/rust-lang/crates.io-index)", - "bls 0.2.0", - "criterion 0.3.3 (registry+https://github.com/rust-lang/crates.io-index)", - "env_logger 0.7.1 (registry+https://github.com/rust-lang/crates.io-index)", - "eth2_hashing 0.1.1", - "eth2_ssz 0.1.2", - "eth2_ssz_types 0.2.0", - "int_to_bytes 0.2.0", - "integer-sqrt 0.1.5 (registry+https://github.com/rust-lang/crates.io-index)", - "itertools 0.9.0 (registry+https://github.com/rust-lang/crates.io-index)", - "lazy_static 1.4.0 (registry+https://github.com/rust-lang/crates.io-index)", - "log 0.4.11 (registry+https://github.com/rust-lang/crates.io-index)", - "merkle_proof 0.2.0", - "rayon 1.4.0 (registry+https://github.com/rust-lang/crates.io-index)", - "safe_arith 0.1.0", - "serde 1.0.116 (registry+https://github.com/rust-lang/crates.io-index)", - "serde_derive 1.0.116 (registry+https://github.com/rust-lang/crates.io-index)", - "serde_yaml 0.8.13 (registry+https://github.com/rust-lang/crates.io-index)", - "tree_hash 0.1.1", - "tree_hash_derive 0.2.0", - "types 0.2.0", + "arbitrary", + "bls", + "criterion", + "env_logger", + "eth2_hashing", + "eth2_ssz", + "eth2_ssz_types", + "int_to_bytes", + "integer-sqrt", + "itertools 0.9.0", + "lazy_static", + "log 0.4.11", + "merkle_proof", + "rayon", + "safe_arith", + "serde", + "serde_derive", + "serde_yaml", + "tree_hash", + "tree_hash_derive", + "types", ] [[package]] name = "state_transition_vectors" version = "0.1.0" dependencies = [ - "eth2_ssz 0.1.2", - "state_processing 0.2.0", - "types 0.2.0", + "eth2_ssz", + "state_processing", + "types", ] [[package]] name = "static_assertions" version = "1.1.0" source = "registry+https://github.com/rust-lang/crates.io-index" +checksum = "a2eb9349b6444b326872e140eb1cf5e7c522154d69e7a0ffb0fb81c06b37543f" [[package]] name = "stdweb" version = "0.4.20" source = "registry+https://github.com/rust-lang/crates.io-index" +checksum = "d022496b16281348b52d0e30ae99e01a73d737b2f45d38fed4edf79f9325a1d5" dependencies = [ - "discard 1.0.4 (registry+https://github.com/rust-lang/crates.io-index)", - "rustc_version 0.2.3 (registry+https://github.com/rust-lang/crates.io-index)", - "stdweb-derive 0.5.3 (registry+https://github.com/rust-lang/crates.io-index)", - "stdweb-internal-macros 0.2.9 (registry+https://github.com/rust-lang/crates.io-index)", - "stdweb-internal-runtime 0.1.5 (registry+https://github.com/rust-lang/crates.io-index)", - "wasm-bindgen 0.2.68 (registry+https://github.com/rust-lang/crates.io-index)", + "discard", + "rustc_version", + "stdweb-derive", + "stdweb-internal-macros", + "stdweb-internal-runtime", + "wasm-bindgen", ] [[package]] name = "stdweb-derive" version = "0.5.3" source = "registry+https://github.com/rust-lang/crates.io-index" +checksum = "c87a60a40fccc84bef0652345bbbbbe20a605bf5d0ce81719fc476f5c03b50ef" dependencies = [ - "proc-macro2 1.0.23 (registry+https://github.com/rust-lang/crates.io-index)", - "quote 1.0.7 (registry+https://github.com/rust-lang/crates.io-index)", - "serde 1.0.116 (registry+https://github.com/rust-lang/crates.io-index)", - "serde_derive 1.0.116 (registry+https://github.com/rust-lang/crates.io-index)", - "syn 1.0.42 (registry+https://github.com/rust-lang/crates.io-index)", + "proc-macro2", + "quote", + "serde", + "serde_derive", + "syn", ] [[package]] name = "stdweb-internal-macros" version = "0.2.9" source = "registry+https://github.com/rust-lang/crates.io-index" +checksum = "58fa5ff6ad0d98d1ffa8cb115892b6e69d67799f6763e162a1c9db421dc22e11" dependencies = [ - "base-x 0.2.6 (registry+https://github.com/rust-lang/crates.io-index)", - "proc-macro2 1.0.23 (registry+https://github.com/rust-lang/crates.io-index)", - "quote 1.0.7 (registry+https://github.com/rust-lang/crates.io-index)", - "serde 1.0.116 (registry+https://github.com/rust-lang/crates.io-index)", - "serde_derive 1.0.116 (registry+https://github.com/rust-lang/crates.io-index)", - "serde_json 1.0.57 (registry+https://github.com/rust-lang/crates.io-index)", - "sha1 0.6.0 (registry+https://github.com/rust-lang/crates.io-index)", - "syn 1.0.42 (registry+https://github.com/rust-lang/crates.io-index)", + "base-x", + "proc-macro2", + "quote", + "serde", + "serde_derive", + "serde_json", + "sha1", + "syn", ] [[package]] name = "stdweb-internal-runtime" version = "0.1.5" source = "registry+https://github.com/rust-lang/crates.io-index" +checksum = "213701ba3370744dcd1a12960caa4843b3d68b4d1c0a5d575e0d65b2ee9d16c0" [[package]] name = "store" version = "0.2.0" dependencies = [ - "criterion 0.3.3 (registry+https://github.com/rust-lang/crates.io-index)", - "db-key 0.0.5 (registry+https://github.com/rust-lang/crates.io-index)", - "eth2_ssz 0.1.2", - "eth2_ssz_derive 0.1.0", - "itertools 0.9.0 (registry+https://github.com/rust-lang/crates.io-index)", - "lazy_static 1.4.0 (registry+https://github.com/rust-lang/crates.io-index)", - "leveldb 0.8.6 (registry+https://github.com/rust-lang/crates.io-index)", - "lighthouse_metrics 0.2.0", - "lru 0.5.3 (registry+https://github.com/rust-lang/crates.io-index)", - "parking_lot 0.11.0 (registry+https://github.com/rust-lang/crates.io-index)", - "rayon 1.4.0 (registry+https://github.com/rust-lang/crates.io-index)", - "serde 1.0.116 (registry+https://github.com/rust-lang/crates.io-index)", - "serde_derive 1.0.116 (registry+https://github.com/rust-lang/crates.io-index)", - "slog 2.5.2 (registry+https://github.com/rust-lang/crates.io-index)", - "sloggers 1.0.1 (registry+https://github.com/rust-lang/crates.io-index)", - "state_processing 0.2.0", - "tempfile 3.1.0 (registry+https://github.com/rust-lang/crates.io-index)", - "tree_hash 0.1.1", - "types 0.2.0", + "criterion", + "db-key", + "eth2_ssz", + "eth2_ssz_derive", + "itertools 0.9.0", + "lazy_static", + "leveldb", + "lighthouse_metrics", + "lru", + "parking_lot 0.11.0", + "rayon", + "serde", + "serde_derive", + "slog", + "sloggers", + "state_processing", + "tempfile", + "tree_hash", + "types", ] [[package]] name = "stream-cipher" version = "0.4.1" source = "registry+https://github.com/rust-lang/crates.io-index" +checksum = "09f8ed9974042b8c3672ff3030a69fcc03b74c47c3d1ecb7755e8a3626011e88" dependencies = [ - "block-cipher 0.7.1 (registry+https://github.com/rust-lang/crates.io-index)", - "generic-array 0.14.4 (registry+https://github.com/rust-lang/crates.io-index)", + "block-cipher", + "generic-array 0.14.4", ] [[package]] name = "string" version = "0.2.1" source = "registry+https://github.com/rust-lang/crates.io-index" +checksum = "d24114bfcceb867ca7f71a0d3fe45d45619ec47a6fbfa98cb14e14250bfa5d6d" dependencies = [ - "bytes 0.4.12 (registry+https://github.com/rust-lang/crates.io-index)", + "bytes 0.4.12", ] [[package]] name = "strsim" version = "0.8.0" source = "registry+https://github.com/rust-lang/crates.io-index" +checksum = "8ea5119cdb4c55b55d432abb513a0429384878c15dde60cc77b1c99de1a95a6a" [[package]] name = "subtle" version = "1.0.0" source = "registry+https://github.com/rust-lang/crates.io-index" +checksum = "2d67a5a62ba6e01cb2192ff309324cb4875d0c451d55fe2319433abe7a05a8ee" [[package]] name = "subtle" version = "2.3.0" source = "registry+https://github.com/rust-lang/crates.io-index" +checksum = "343f3f510c2915908f155e94f17220b19ccfacf2a64a2a5d8004f2c3e311e7fd" [[package]] name = "swap_or_not_shuffle" version = "0.2.0" dependencies = [ - "criterion 0.3.3 (registry+https://github.com/rust-lang/crates.io-index)", - "eth2_hashing 0.1.1", - "ethereum-types 0.9.2 (registry+https://github.com/rust-lang/crates.io-index)", + "criterion", + "eth2_hashing", + "ethereum-types", ] [[package]] name = "syn" -version = "1.0.42" +version = "1.0.41" source = "registry+https://github.com/rust-lang/crates.io-index" +checksum = "6690e3e9f692504b941dc6c3b188fd28df054f7fb8469ab40680df52fdcc842b" dependencies = [ - "proc-macro2 1.0.23 (registry+https://github.com/rust-lang/crates.io-index)", - "quote 1.0.7 (registry+https://github.com/rust-lang/crates.io-index)", - "unicode-xid 0.2.1 (registry+https://github.com/rust-lang/crates.io-index)", + "proc-macro2", + "quote", + "unicode-xid", ] [[package]] name = "synstructure" version = "0.12.4" source = "registry+https://github.com/rust-lang/crates.io-index" +checksum = "b834f2d66f734cb897113e34aaff2f1ab4719ca946f9a7358dba8f8064148701" dependencies = [ - "proc-macro2 1.0.23 (registry+https://github.com/rust-lang/crates.io-index)", - "quote 1.0.7 (registry+https://github.com/rust-lang/crates.io-index)", - "syn 1.0.42 (registry+https://github.com/rust-lang/crates.io-index)", - "unicode-xid 0.2.1 (registry+https://github.com/rust-lang/crates.io-index)", + "proc-macro2", + "quote", + "syn", + "unicode-xid", ] [[package]] name = "take_mut" version = "0.2.2" source = "registry+https://github.com/rust-lang/crates.io-index" +checksum = "f764005d11ee5f36500a149ace24e00e3da98b0158b3e2d53a7495660d3f4d60" [[package]] name = "target_info" version = "0.1.0" source = "registry+https://github.com/rust-lang/crates.io-index" +checksum = "c63f48baada5c52e65a29eef93ab4f8982681b67f9e8d29c7b05abcfec2b9ffe" [[package]] name = "tempdir" version = "0.3.7" source = "registry+https://github.com/rust-lang/crates.io-index" +checksum = "15f2b5fb00ccdf689e0149d1b1b3c03fead81c2b37735d812fa8bddbbf41b6d8" dependencies = [ - "rand 0.4.6 (registry+https://github.com/rust-lang/crates.io-index)", - "remove_dir_all 0.5.3 (registry+https://github.com/rust-lang/crates.io-index)", + "rand 0.4.6", + "remove_dir_all", ] [[package]] name = "tempfile" version = "3.1.0" source = "registry+https://github.com/rust-lang/crates.io-index" +checksum = "7a6e24d9338a0a5be79593e2fa15a648add6138caa803e2d5bc782c371732ca9" dependencies = [ - "cfg-if 0.1.10 (registry+https://github.com/rust-lang/crates.io-index)", - "libc 0.2.77 (registry+https://github.com/rust-lang/crates.io-index)", - "rand 0.7.3 (registry+https://github.com/rust-lang/crates.io-index)", - "redox_syscall 0.1.57 (registry+https://github.com/rust-lang/crates.io-index)", - "remove_dir_all 0.5.3 (registry+https://github.com/rust-lang/crates.io-index)", - "winapi 0.3.9 (registry+https://github.com/rust-lang/crates.io-index)", + "cfg-if", + "libc", + "rand 0.7.3", + "redox_syscall", + "remove_dir_all", + "winapi 0.3.9", ] [[package]] name = "term" version = "0.6.1" source = "registry+https://github.com/rust-lang/crates.io-index" +checksum = "c0863a3345e70f61d613eab32ee046ccd1bcc5f9105fe402c61fcd0c13eeb8b5" dependencies = [ - "dirs 2.0.2 (registry+https://github.com/rust-lang/crates.io-index)", - "winapi 0.3.9 (registry+https://github.com/rust-lang/crates.io-index)", + "dirs", + "winapi 0.3.9", ] [[package]] name = "termcolor" version = "1.1.0" source = "registry+https://github.com/rust-lang/crates.io-index" +checksum = "bb6bfa289a4d7c5766392812c0a1f4c1ba45afa1ad47803c11e1f407d846d75f" dependencies = [ - "winapi-util 0.1.5 (registry+https://github.com/rust-lang/crates.io-index)", + "winapi-util", ] [[package]] name = "test_random_derive" version = "0.2.0" dependencies = [ - "quote 1.0.7 (registry+https://github.com/rust-lang/crates.io-index)", - "syn 1.0.42 (registry+https://github.com/rust-lang/crates.io-index)", + "quote", + "syn", ] [[package]] name = "textwrap" version = "0.11.0" source = "registry+https://github.com/rust-lang/crates.io-index" +checksum = "d326610f408c7a4eb6f51c37c330e496b08506c9457c9d34287ecc38809fb060" dependencies = [ - "unicode-width 0.1.8 (registry+https://github.com/rust-lang/crates.io-index)", + "unicode-width", ] [[package]] name = "thiserror" version = "1.0.20" source = "registry+https://github.com/rust-lang/crates.io-index" +checksum = "7dfdd070ccd8ccb78f4ad66bf1982dc37f620ef696c6b5028fe2ed83dd3d0d08" dependencies = [ - "thiserror-impl 1.0.20 (registry+https://github.com/rust-lang/crates.io-index)", + "thiserror-impl", ] [[package]] name = "thiserror-impl" version = "1.0.20" source = "registry+https://github.com/rust-lang/crates.io-index" +checksum = "bd80fc12f73063ac132ac92aceea36734f04a1d93c1240c6944e23a3b8841793" dependencies = [ - "proc-macro2 1.0.23 (registry+https://github.com/rust-lang/crates.io-index)", - "quote 1.0.7 (registry+https://github.com/rust-lang/crates.io-index)", - "syn 1.0.42 (registry+https://github.com/rust-lang/crates.io-index)", + "proc-macro2", + "quote", + "syn", ] [[package]] name = "thread_local" version = "1.0.1" source = "registry+https://github.com/rust-lang/crates.io-index" +checksum = "d40c6d1b69745a6ec6fb1ca717914848da4b44ae29d9b3080cbee91d72a69b14" dependencies = [ - "lazy_static 1.4.0 (registry+https://github.com/rust-lang/crates.io-index)", + "lazy_static", ] [[package]] name = "threadpool" version = "1.8.1" source = "registry+https://github.com/rust-lang/crates.io-index" +checksum = "d050e60b33d41c19108b32cea32164033a9013fe3b46cbd4457559bfbf77afaa" dependencies = [ - "num_cpus 1.13.0 (registry+https://github.com/rust-lang/crates.io-index)", + "num_cpus", ] [[package]] name = "time" version = "0.1.44" source = "registry+https://github.com/rust-lang/crates.io-index" +checksum = "6db9e6914ab8b1ae1c260a4ae7a49b6c5611b40328a735b21862567685e73255" dependencies = [ - "libc 0.2.77 (registry+https://github.com/rust-lang/crates.io-index)", - "wasi 0.10.0+wasi-snapshot-preview1 (registry+https://github.com/rust-lang/crates.io-index)", - "winapi 0.3.9 (registry+https://github.com/rust-lang/crates.io-index)", + "libc", + "wasi 0.10.0+wasi-snapshot-preview1", + "winapi 0.3.9", ] [[package]] name = "time" version = "0.2.22" source = "registry+https://github.com/rust-lang/crates.io-index" +checksum = "55b7151c9065e80917fbf285d9a5d1432f60db41d170ccafc749a136b41a93af" dependencies = [ - "const_fn 0.4.2 (registry+https://github.com/rust-lang/crates.io-index)", - "libc 0.2.77 (registry+https://github.com/rust-lang/crates.io-index)", - "standback 0.2.10 (registry+https://github.com/rust-lang/crates.io-index)", - "stdweb 0.4.20 (registry+https://github.com/rust-lang/crates.io-index)", - "time-macros 0.1.0 (registry+https://github.com/rust-lang/crates.io-index)", - "version_check 0.9.2 (registry+https://github.com/rust-lang/crates.io-index)", - "winapi 0.3.9 (registry+https://github.com/rust-lang/crates.io-index)", + "const_fn", + "libc", + "standback", + "stdweb", + "time-macros", + "version_check 0.9.2", + "winapi 0.3.9", ] [[package]] name = "time-macros" version = "0.1.0" source = "registry+https://github.com/rust-lang/crates.io-index" +checksum = "9ae9b6e9f095bc105e183e3cd493d72579be3181ad4004fceb01adbe9eecab2d" dependencies = [ - "proc-macro-hack 0.5.18 (registry+https://github.com/rust-lang/crates.io-index)", - "time-macros-impl 0.1.1 (registry+https://github.com/rust-lang/crates.io-index)", + "proc-macro-hack", + "time-macros-impl", ] [[package]] name = "time-macros-impl" version = "0.1.1" source = "registry+https://github.com/rust-lang/crates.io-index" +checksum = "e5c3be1edfad6027c69f5491cf4cb310d1a71ecd6af742788c6ff8bced86b8fa" dependencies = [ - "proc-macro-hack 0.5.18 (registry+https://github.com/rust-lang/crates.io-index)", - "proc-macro2 1.0.23 (registry+https://github.com/rust-lang/crates.io-index)", - "quote 1.0.7 (registry+https://github.com/rust-lang/crates.io-index)", - "standback 0.2.10 (registry+https://github.com/rust-lang/crates.io-index)", - "syn 1.0.42 (registry+https://github.com/rust-lang/crates.io-index)", + "proc-macro-hack", + "proc-macro2", + "quote", + "standback", + "syn", ] [[package]] name = "timer" version = "0.2.0" dependencies = [ - "beacon_chain 0.2.0", - "environment 0.1.2", - "futures 0.3.5 (registry+https://github.com/rust-lang/crates.io-index)", - "parking_lot 0.11.0 (registry+https://github.com/rust-lang/crates.io-index)", - "slog 2.5.2 (registry+https://github.com/rust-lang/crates.io-index)", - "slot_clock 0.2.0", - "tokio 0.2.22 (registry+https://github.com/rust-lang/crates.io-index)", - "types 0.2.0", + "beacon_chain", + "environment", + "futures 0.3.5", + "parking_lot 0.11.0", + "slog", + "slot_clock", + "tokio 0.2.22", + "types", ] [[package]] name = "tiny-bip39" version = "0.7.3" source = "registry+https://github.com/rust-lang/crates.io-index" +checksum = "b0165e045cc2ae1660270ca65e1676dbaab60feb0f91b10f7d0665e9b47e31f2" dependencies = [ - "failure 0.1.8 (registry+https://github.com/rust-lang/crates.io-index)", - "hmac 0.7.1 (registry+https://github.com/rust-lang/crates.io-index)", - "once_cell 1.4.1 (registry+https://github.com/rust-lang/crates.io-index)", - "pbkdf2 0.3.0 (registry+https://github.com/rust-lang/crates.io-index)", - "rand 0.7.3 (registry+https://github.com/rust-lang/crates.io-index)", - "rustc-hash 1.1.0 (registry+https://github.com/rust-lang/crates.io-index)", - "sha2 0.8.2 (registry+https://github.com/rust-lang/crates.io-index)", - "unicode-normalization 0.1.13 (registry+https://github.com/rust-lang/crates.io-index)", + "failure", + "hmac 0.7.1", + "once_cell", + "pbkdf2 0.3.0", + "rand 0.7.3", + "rustc-hash", + "sha2 0.8.2", + "unicode-normalization", ] [[package]] name = "tiny-keccak" version = "1.5.0" source = "registry+https://github.com/rust-lang/crates.io-index" +checksum = "1d8a021c69bb74a44ccedb824a046447e2c84a01df9e5c20779750acb38e11b2" dependencies = [ - "crunchy 0.2.2 (registry+https://github.com/rust-lang/crates.io-index)", + "crunchy", ] [[package]] name = "tiny-keccak" version = "2.0.2" source = "registry+https://github.com/rust-lang/crates.io-index" +checksum = "2c9d3793400a45f954c52e73d068316d76b6f4e36977e3fcebb13a2721e80237" dependencies = [ - "crunchy 0.2.2 (registry+https://github.com/rust-lang/crates.io-index)", + "crunchy", ] [[package]] name = "tinytemplate" version = "1.1.0" source = "registry+https://github.com/rust-lang/crates.io-index" +checksum = "6d3dc76004a03cec1c5932bca4cdc2e39aaa798e3f82363dd94f9adf6098c12f" dependencies = [ - "serde 1.0.116 (registry+https://github.com/rust-lang/crates.io-index)", - "serde_json 1.0.57 (registry+https://github.com/rust-lang/crates.io-index)", + "serde", + "serde_json", ] [[package]] name = "tinyvec" version = "0.3.4" source = "registry+https://github.com/rust-lang/crates.io-index" +checksum = "238ce071d267c5710f9d31451efec16c5ee22de34df17cc05e56cbc92e967117" [[package]] name = "tokio" version = "0.1.22" source = "registry+https://github.com/rust-lang/crates.io-index" +checksum = "5a09c0b5bb588872ab2f09afa13ee6e9dac11e10a0ec9e8e3ba39a5a5d530af6" dependencies = [ - "bytes 0.4.12 (registry+https://github.com/rust-lang/crates.io-index)", - "futures 0.1.29 (registry+https://github.com/rust-lang/crates.io-index)", - "mio 0.6.22 (registry+https://github.com/rust-lang/crates.io-index)", - "num_cpus 1.13.0 (registry+https://github.com/rust-lang/crates.io-index)", - "tokio-codec 0.1.2 (registry+https://github.com/rust-lang/crates.io-index)", - "tokio-current-thread 0.1.7 (registry+https://github.com/rust-lang/crates.io-index)", - "tokio-executor 0.1.10 (registry+https://github.com/rust-lang/crates.io-index)", - "tokio-fs 0.1.7 (registry+https://github.com/rust-lang/crates.io-index)", - "tokio-io 0.1.13 (registry+https://github.com/rust-lang/crates.io-index)", - "tokio-reactor 0.1.12 (registry+https://github.com/rust-lang/crates.io-index)", - "tokio-sync 0.1.8 (registry+https://github.com/rust-lang/crates.io-index)", - "tokio-tcp 0.1.4 (registry+https://github.com/rust-lang/crates.io-index)", - "tokio-threadpool 0.1.18 (registry+https://github.com/rust-lang/crates.io-index)", - "tokio-timer 0.2.13 (registry+https://github.com/rust-lang/crates.io-index)", - "tokio-udp 0.1.6 (registry+https://github.com/rust-lang/crates.io-index)", - "tokio-uds 0.2.7 (registry+https://github.com/rust-lang/crates.io-index)", + "bytes 0.4.12", + "futures 0.1.29", + "mio", + "num_cpus", + "tokio-codec", + "tokio-current-thread", + "tokio-executor", + "tokio-fs", + "tokio-io", + "tokio-reactor", + "tokio-sync", + "tokio-tcp", + "tokio-threadpool", + "tokio-timer 0.2.13", + "tokio-udp", + "tokio-uds 0.2.7", ] [[package]] name = "tokio" version = "0.2.22" source = "registry+https://github.com/rust-lang/crates.io-index" +checksum = "5d34ca54d84bf2b5b4d7d31e901a8464f7b60ac145a284fba25ceb801f2ddccd" dependencies = [ - "bytes 0.5.6 (registry+https://github.com/rust-lang/crates.io-index)", - "fnv 1.0.7 (registry+https://github.com/rust-lang/crates.io-index)", - "futures-core 0.3.5 (registry+https://github.com/rust-lang/crates.io-index)", - "iovec 0.1.4 (registry+https://github.com/rust-lang/crates.io-index)", - "lazy_static 1.4.0 (registry+https://github.com/rust-lang/crates.io-index)", - "libc 0.2.77 (registry+https://github.com/rust-lang/crates.io-index)", - "memchr 2.3.3 (registry+https://github.com/rust-lang/crates.io-index)", - "mio 0.6.22 (registry+https://github.com/rust-lang/crates.io-index)", - "mio-named-pipes 0.1.7 (registry+https://github.com/rust-lang/crates.io-index)", - "mio-uds 0.6.8 (registry+https://github.com/rust-lang/crates.io-index)", - "num_cpus 1.13.0 (registry+https://github.com/rust-lang/crates.io-index)", - "pin-project-lite 0.1.8 (registry+https://github.com/rust-lang/crates.io-index)", - "signal-hook-registry 1.2.1 (registry+https://github.com/rust-lang/crates.io-index)", - "slab 0.4.2 (registry+https://github.com/rust-lang/crates.io-index)", - "tokio-macros 0.2.5 (registry+https://github.com/rust-lang/crates.io-index)", - "winapi 0.3.9 (registry+https://github.com/rust-lang/crates.io-index)", + "bytes 0.5.6", + "fnv", + "futures-core", + "iovec", + "lazy_static", + "libc", + "memchr", + "mio", + "mio-named-pipes", + "mio-uds", + "num_cpus", + "pin-project-lite", + "signal-hook-registry", + "slab 0.4.2", + "tokio-macros", + "winapi 0.3.9", ] [[package]] name = "tokio-buf" version = "0.1.1" source = "registry+https://github.com/rust-lang/crates.io-index" +checksum = "8fb220f46c53859a4b7ec083e41dec9778ff0b1851c0942b211edb89e0ccdc46" dependencies = [ - "bytes 0.4.12 (registry+https://github.com/rust-lang/crates.io-index)", - "either 1.6.1 (registry+https://github.com/rust-lang/crates.io-index)", - "futures 0.1.29 (registry+https://github.com/rust-lang/crates.io-index)", + "bytes 0.4.12", + "either", + "futures 0.1.29", ] [[package]] name = "tokio-codec" version = "0.1.2" source = "registry+https://github.com/rust-lang/crates.io-index" +checksum = "25b2998660ba0e70d18684de5d06b70b70a3a747469af9dea7618cc59e75976b" dependencies = [ - "bytes 0.4.12 (registry+https://github.com/rust-lang/crates.io-index)", - "futures 0.1.29 (registry+https://github.com/rust-lang/crates.io-index)", - "tokio-io 0.1.13 (registry+https://github.com/rust-lang/crates.io-index)", + "bytes 0.4.12", + "futures 0.1.29", + "tokio-io", ] [[package]] name = "tokio-core" version = "0.1.17" source = "registry+https://github.com/rust-lang/crates.io-index" +checksum = "aeeffbbb94209023feaef3c196a41cbcdafa06b4a6f893f68779bb5e53796f71" dependencies = [ - "bytes 0.4.12 (registry+https://github.com/rust-lang/crates.io-index)", - "futures 0.1.29 (registry+https://github.com/rust-lang/crates.io-index)", - "iovec 0.1.4 (registry+https://github.com/rust-lang/crates.io-index)", - "log 0.4.11 (registry+https://github.com/rust-lang/crates.io-index)", - "mio 0.6.22 (registry+https://github.com/rust-lang/crates.io-index)", - "scoped-tls 0.1.2 (registry+https://github.com/rust-lang/crates.io-index)", - "tokio 0.1.22 (registry+https://github.com/rust-lang/crates.io-index)", - "tokio-executor 0.1.10 (registry+https://github.com/rust-lang/crates.io-index)", - "tokio-io 0.1.13 (registry+https://github.com/rust-lang/crates.io-index)", - "tokio-reactor 0.1.12 (registry+https://github.com/rust-lang/crates.io-index)", - "tokio-timer 0.2.13 (registry+https://github.com/rust-lang/crates.io-index)", + "bytes 0.4.12", + "futures 0.1.29", + "iovec", + "log 0.4.11", + "mio", + "scoped-tls 0.1.2", + "tokio 0.1.22", + "tokio-executor", + "tokio-io", + "tokio-reactor", + "tokio-timer 0.2.13", ] [[package]] name = "tokio-current-thread" version = "0.1.7" source = "registry+https://github.com/rust-lang/crates.io-index" +checksum = "b1de0e32a83f131e002238d7ccde18211c0a5397f60cbfffcb112868c2e0e20e" dependencies = [ - "futures 0.1.29 (registry+https://github.com/rust-lang/crates.io-index)", - "tokio-executor 0.1.10 (registry+https://github.com/rust-lang/crates.io-index)", + "futures 0.1.29", + "tokio-executor", ] [[package]] name = "tokio-executor" version = "0.1.10" source = "registry+https://github.com/rust-lang/crates.io-index" +checksum = "fb2d1b8f4548dbf5e1f7818512e9c406860678f29c300cdf0ebac72d1a3a1671" dependencies = [ - "crossbeam-utils 0.7.2 (registry+https://github.com/rust-lang/crates.io-index)", - "futures 0.1.29 (registry+https://github.com/rust-lang/crates.io-index)", + "crossbeam-utils", + "futures 0.1.29", ] [[package]] name = "tokio-fs" version = "0.1.7" source = "registry+https://github.com/rust-lang/crates.io-index" +checksum = "297a1206e0ca6302a0eed35b700d292b275256f596e2f3fea7729d5e629b6ff4" dependencies = [ - "futures 0.1.29 (registry+https://github.com/rust-lang/crates.io-index)", - "tokio-io 0.1.13 (registry+https://github.com/rust-lang/crates.io-index)", - "tokio-threadpool 0.1.18 (registry+https://github.com/rust-lang/crates.io-index)", + "futures 0.1.29", + "tokio-io", + "tokio-threadpool", ] [[package]] name = "tokio-io" version = "0.1.13" source = "registry+https://github.com/rust-lang/crates.io-index" +checksum = "57fc868aae093479e3131e3d165c93b1c7474109d13c90ec0dda2a1bbfff0674" dependencies = [ - "bytes 0.4.12 (registry+https://github.com/rust-lang/crates.io-index)", - "futures 0.1.29 (registry+https://github.com/rust-lang/crates.io-index)", - "log 0.4.11 (registry+https://github.com/rust-lang/crates.io-index)", + "bytes 0.4.12", + "futures 0.1.29", + "log 0.4.11", ] [[package]] name = "tokio-io-timeout" version = "0.4.0" source = "registry+https://github.com/rust-lang/crates.io-index" +checksum = "9390a43272c8a6ac912ed1d1e2b6abeafd5047e05530a2fa304deee041a06215" dependencies = [ - "bytes 0.5.6 (registry+https://github.com/rust-lang/crates.io-index)", - "tokio 0.2.22 (registry+https://github.com/rust-lang/crates.io-index)", + "bytes 0.5.6", + "tokio 0.2.22", ] [[package]] name = "tokio-macros" version = "0.2.5" source = "registry+https://github.com/rust-lang/crates.io-index" +checksum = "f0c3acc6aa564495a0f2e1d59fab677cd7f81a19994cfc7f3ad0e64301560389" dependencies = [ - "proc-macro2 1.0.23 (registry+https://github.com/rust-lang/crates.io-index)", - "quote 1.0.7 (registry+https://github.com/rust-lang/crates.io-index)", - "syn 1.0.42 (registry+https://github.com/rust-lang/crates.io-index)", + "proc-macro2", + "quote", + "syn", ] [[package]] name = "tokio-reactor" version = "0.1.12" source = "registry+https://github.com/rust-lang/crates.io-index" +checksum = "09bc590ec4ba8ba87652da2068d150dcada2cfa2e07faae270a5e0409aa51351" dependencies = [ - "crossbeam-utils 0.7.2 (registry+https://github.com/rust-lang/crates.io-index)", - "futures 0.1.29 (registry+https://github.com/rust-lang/crates.io-index)", - "lazy_static 1.4.0 (registry+https://github.com/rust-lang/crates.io-index)", - "log 0.4.11 (registry+https://github.com/rust-lang/crates.io-index)", - "mio 0.6.22 (registry+https://github.com/rust-lang/crates.io-index)", - "num_cpus 1.13.0 (registry+https://github.com/rust-lang/crates.io-index)", - "parking_lot 0.9.0 (registry+https://github.com/rust-lang/crates.io-index)", - "slab 0.4.2 (registry+https://github.com/rust-lang/crates.io-index)", - "tokio-executor 0.1.10 (registry+https://github.com/rust-lang/crates.io-index)", - "tokio-io 0.1.13 (registry+https://github.com/rust-lang/crates.io-index)", - "tokio-sync 0.1.8 (registry+https://github.com/rust-lang/crates.io-index)", + "crossbeam-utils", + "futures 0.1.29", + "lazy_static", + "log 0.4.11", + "mio", + "num_cpus", + "parking_lot 0.9.0", + "slab 0.4.2", + "tokio-executor", + "tokio-io", + "tokio-sync", ] [[package]] name = "tokio-sync" version = "0.1.8" source = "registry+https://github.com/rust-lang/crates.io-index" +checksum = "edfe50152bc8164fcc456dab7891fa9bf8beaf01c5ee7e1dd43a397c3cf87dee" dependencies = [ - "fnv 1.0.7 (registry+https://github.com/rust-lang/crates.io-index)", - "futures 0.1.29 (registry+https://github.com/rust-lang/crates.io-index)", + "fnv", + "futures 0.1.29", ] [[package]] name = "tokio-tcp" version = "0.1.4" source = "registry+https://github.com/rust-lang/crates.io-index" +checksum = "98df18ed66e3b72e742f185882a9e201892407957e45fbff8da17ae7a7c51f72" dependencies = [ - "bytes 0.4.12 (registry+https://github.com/rust-lang/crates.io-index)", - "futures 0.1.29 (registry+https://github.com/rust-lang/crates.io-index)", - "iovec 0.1.4 (registry+https://github.com/rust-lang/crates.io-index)", - "mio 0.6.22 (registry+https://github.com/rust-lang/crates.io-index)", - "tokio-io 0.1.13 (registry+https://github.com/rust-lang/crates.io-index)", - "tokio-reactor 0.1.12 (registry+https://github.com/rust-lang/crates.io-index)", + "bytes 0.4.12", + "futures 0.1.29", + "iovec", + "mio", + "tokio-io", + "tokio-reactor", ] [[package]] name = "tokio-threadpool" version = "0.1.18" source = "registry+https://github.com/rust-lang/crates.io-index" +checksum = "df720b6581784c118f0eb4310796b12b1d242a7eb95f716a8367855325c25f89" dependencies = [ - "crossbeam-deque 0.7.3 (registry+https://github.com/rust-lang/crates.io-index)", - "crossbeam-queue 0.2.3 (registry+https://github.com/rust-lang/crates.io-index)", - "crossbeam-utils 0.7.2 (registry+https://github.com/rust-lang/crates.io-index)", - "futures 0.1.29 (registry+https://github.com/rust-lang/crates.io-index)", - "lazy_static 1.4.0 (registry+https://github.com/rust-lang/crates.io-index)", - "log 0.4.11 (registry+https://github.com/rust-lang/crates.io-index)", - "num_cpus 1.13.0 (registry+https://github.com/rust-lang/crates.io-index)", - "slab 0.4.2 (registry+https://github.com/rust-lang/crates.io-index)", - "tokio-executor 0.1.10 (registry+https://github.com/rust-lang/crates.io-index)", + "crossbeam-deque", + "crossbeam-queue", + "crossbeam-utils", + "futures 0.1.29", + "lazy_static", + "log 0.4.11", + "num_cpus", + "slab 0.4.2", + "tokio-executor", ] [[package]] name = "tokio-timer" version = "0.1.2" source = "registry+https://github.com/rust-lang/crates.io-index" +checksum = "6131e780037787ff1b3f8aad9da83bca02438b72277850dd6ad0d455e0e20efc" dependencies = [ - "futures 0.1.29 (registry+https://github.com/rust-lang/crates.io-index)", - "slab 0.3.0 (registry+https://github.com/rust-lang/crates.io-index)", + "futures 0.1.29", + "slab 0.3.0", ] [[package]] name = "tokio-timer" version = "0.2.13" source = "registry+https://github.com/rust-lang/crates.io-index" +checksum = "93044f2d313c95ff1cb7809ce9a7a05735b012288a888b62d4434fd58c94f296" dependencies = [ - "crossbeam-utils 0.7.2 (registry+https://github.com/rust-lang/crates.io-index)", - "futures 0.1.29 (registry+https://github.com/rust-lang/crates.io-index)", - "slab 0.4.2 (registry+https://github.com/rust-lang/crates.io-index)", - "tokio-executor 0.1.10 (registry+https://github.com/rust-lang/crates.io-index)", + "crossbeam-utils", + "futures 0.1.29", + "slab 0.4.2", + "tokio-executor", ] [[package]] name = "tokio-tls" version = "0.2.1" source = "registry+https://github.com/rust-lang/crates.io-index" +checksum = "354b8cd83825b3c20217a9dc174d6a0c67441a2fae5c41bcb1ea6679f6ae0f7c" dependencies = [ - "futures 0.1.29 (registry+https://github.com/rust-lang/crates.io-index)", - "native-tls 0.2.4 (registry+https://github.com/rust-lang/crates.io-index)", - "tokio-io 0.1.13 (registry+https://github.com/rust-lang/crates.io-index)", + "futures 0.1.29", + "native-tls", + "tokio-io", ] [[package]] name = "tokio-tls" version = "0.3.1" source = "registry+https://github.com/rust-lang/crates.io-index" +checksum = "9a70f4fcd7b3b24fb194f837560168208f669ca8cb70d0c4b862944452396343" dependencies = [ - "native-tls 0.2.4 (registry+https://github.com/rust-lang/crates.io-index)", - "tokio 0.2.22 (registry+https://github.com/rust-lang/crates.io-index)", + "native-tls", + "tokio 0.2.22", +] + +[[package]] +name = "tokio-tungstenite" +version = "0.11.0" +source = "registry+https://github.com/rust-lang/crates.io-index" +checksum = "6d9e878ad426ca286e4dcae09cbd4e1973a7f8987d97570e2469703dd7f5720c" +dependencies = [ + "futures-util", + "log 0.4.11", + "pin-project", + "tokio 0.2.22", + "tungstenite", ] [[package]] name = "tokio-udp" version = "0.1.6" source = "registry+https://github.com/rust-lang/crates.io-index" +checksum = "e2a0b10e610b39c38b031a2fcab08e4b82f16ece36504988dcbd81dbba650d82" dependencies = [ - "bytes 0.4.12 (registry+https://github.com/rust-lang/crates.io-index)", - "futures 0.1.29 (registry+https://github.com/rust-lang/crates.io-index)", - "log 0.4.11 (registry+https://github.com/rust-lang/crates.io-index)", - "mio 0.6.22 (registry+https://github.com/rust-lang/crates.io-index)", - "tokio-codec 0.1.2 (registry+https://github.com/rust-lang/crates.io-index)", - "tokio-io 0.1.13 (registry+https://github.com/rust-lang/crates.io-index)", - "tokio-reactor 0.1.12 (registry+https://github.com/rust-lang/crates.io-index)", + "bytes 0.4.12", + "futures 0.1.29", + "log 0.4.11", + "mio", + "tokio-codec", + "tokio-io", + "tokio-reactor", ] [[package]] name = "tokio-uds" version = "0.1.7" source = "registry+https://github.com/rust-lang/crates.io-index" +checksum = "65ae5d255ce739e8537221ed2942e0445f4b3b813daebac1c0050ddaaa3587f9" dependencies = [ - "bytes 0.4.12 (registry+https://github.com/rust-lang/crates.io-index)", - "futures 0.1.29 (registry+https://github.com/rust-lang/crates.io-index)", - "iovec 0.1.4 (registry+https://github.com/rust-lang/crates.io-index)", - "libc 0.2.77 (registry+https://github.com/rust-lang/crates.io-index)", - "log 0.3.9 (registry+https://github.com/rust-lang/crates.io-index)", - "mio 0.6.22 (registry+https://github.com/rust-lang/crates.io-index)", - "mio-uds 0.6.8 (registry+https://github.com/rust-lang/crates.io-index)", - "tokio-core 0.1.17 (registry+https://github.com/rust-lang/crates.io-index)", - "tokio-io 0.1.13 (registry+https://github.com/rust-lang/crates.io-index)", + "bytes 0.4.12", + "futures 0.1.29", + "iovec", + "libc", + "log 0.3.9", + "mio", + "mio-uds", + "tokio-core", + "tokio-io", ] [[package]] name = "tokio-uds" version = "0.2.7" source = "registry+https://github.com/rust-lang/crates.io-index" +checksum = "ab57a4ac4111c8c9dbcf70779f6fc8bc35ae4b2454809febac840ad19bd7e4e0" dependencies = [ - "bytes 0.4.12 (registry+https://github.com/rust-lang/crates.io-index)", - "futures 0.1.29 (registry+https://github.com/rust-lang/crates.io-index)", - "iovec 0.1.4 (registry+https://github.com/rust-lang/crates.io-index)", - "libc 0.2.77 (registry+https://github.com/rust-lang/crates.io-index)", - "log 0.4.11 (registry+https://github.com/rust-lang/crates.io-index)", - "mio 0.6.22 (registry+https://github.com/rust-lang/crates.io-index)", - "mio-uds 0.6.8 (registry+https://github.com/rust-lang/crates.io-index)", - "tokio-codec 0.1.2 (registry+https://github.com/rust-lang/crates.io-index)", - "tokio-io 0.1.13 (registry+https://github.com/rust-lang/crates.io-index)", - "tokio-reactor 0.1.12 (registry+https://github.com/rust-lang/crates.io-index)", + "bytes 0.4.12", + "futures 0.1.29", + "iovec", + "libc", + "log 0.4.11", + "mio", + "mio-uds", + "tokio-codec", + "tokio-io", + "tokio-reactor", ] [[package]] name = "tokio-util" version = "0.3.1" source = "registry+https://github.com/rust-lang/crates.io-index" +checksum = "be8242891f2b6cbef26a2d7e8605133c2c554cd35b3e4948ea892d6d68436499" dependencies = [ - "bytes 0.5.6 (registry+https://github.com/rust-lang/crates.io-index)", - "futures-core 0.3.5 (registry+https://github.com/rust-lang/crates.io-index)", - "futures-io 0.3.5 (registry+https://github.com/rust-lang/crates.io-index)", - "futures-sink 0.3.5 (registry+https://github.com/rust-lang/crates.io-index)", - "log 0.4.11 (registry+https://github.com/rust-lang/crates.io-index)", - "pin-project-lite 0.1.8 (registry+https://github.com/rust-lang/crates.io-index)", - "tokio 0.2.22 (registry+https://github.com/rust-lang/crates.io-index)", + "bytes 0.5.6", + "futures-core", + "futures-io", + "futures-sink", + "log 0.4.11", + "pin-project-lite", + "tokio 0.2.22", ] [[package]] name = "toml" version = "0.5.6" source = "registry+https://github.com/rust-lang/crates.io-index" +checksum = "ffc92d160b1eef40665be3a05630d003936a3bc7da7421277846c2613e92c71a" dependencies = [ - "serde 1.0.116 (registry+https://github.com/rust-lang/crates.io-index)", + "serde", ] [[package]] name = "tower-service" version = "0.3.0" source = "registry+https://github.com/rust-lang/crates.io-index" +checksum = "e987b6bf443f4b5b3b6f38704195592cca41c5bb7aedd3c3693c7081f8289860" [[package]] name = "tracing" version = "0.1.19" source = "registry+https://github.com/rust-lang/crates.io-index" +checksum = "6d79ca061b032d6ce30c660fded31189ca0b9922bf483cd70759f13a2d86786c" dependencies = [ - "cfg-if 0.1.10 (registry+https://github.com/rust-lang/crates.io-index)", - "log 0.4.11 (registry+https://github.com/rust-lang/crates.io-index)", - "tracing-core 0.1.16 (registry+https://github.com/rust-lang/crates.io-index)", + "cfg-if", + "log 0.4.11", + "tracing-core", ] [[package]] name = "tracing-core" version = "0.1.16" source = "registry+https://github.com/rust-lang/crates.io-index" +checksum = "5bcf46c1f1f06aeea2d6b81f3c863d0930a596c86ad1920d4e5bad6dd1d7119a" +dependencies = [ + "lazy_static", +] + +[[package]] +name = "tracing-futures" +version = "0.2.4" +source = "registry+https://github.com/rust-lang/crates.io-index" +checksum = "ab7bb6f14721aa00656086e9335d363c5c8747bae02ebe32ea2c7dece5689b4c" dependencies = [ - "lazy_static 1.4.0 (registry+https://github.com/rust-lang/crates.io-index)", + "pin-project", + "tracing", ] [[package]] name = "trackable" version = "1.0.0" source = "registry+https://github.com/rust-lang/crates.io-index" +checksum = "30fb6e13d129dd92c501458f64d56c708e3685e3fd307e878ec5f934c5c5bdb0" dependencies = [ - "trackable_derive 1.0.0 (registry+https://github.com/rust-lang/crates.io-index)", + "trackable_derive", ] [[package]] name = "trackable_derive" version = "1.0.0" source = "registry+https://github.com/rust-lang/crates.io-index" +checksum = "ebeb235c5847e2f82cfe0f07eb971d1e5f6804b18dac2ae16349cc604380f82f" dependencies = [ - "quote 1.0.7 (registry+https://github.com/rust-lang/crates.io-index)", - "syn 1.0.42 (registry+https://github.com/rust-lang/crates.io-index)", + "quote", + "syn", ] [[package]] name = "traitobject" version = "0.1.0" source = "registry+https://github.com/rust-lang/crates.io-index" +checksum = "efd1f82c56340fdf16f2a953d7bda4f8fdffba13d93b00844c25572110b26079" [[package]] name = "tree_hash" version = "0.1.1" dependencies = [ - "criterion 0.3.3 (registry+https://github.com/rust-lang/crates.io-index)", - "eth2_hashing 0.1.1", - "ethereum-types 0.9.2 (registry+https://github.com/rust-lang/crates.io-index)", - "lazy_static 1.4.0 (registry+https://github.com/rust-lang/crates.io-index)", - "rand 0.7.3 (registry+https://github.com/rust-lang/crates.io-index)", - "smallvec 1.4.2 (registry+https://github.com/rust-lang/crates.io-index)", - "tree_hash_derive 0.2.0", - "types 0.2.0", + "criterion", + "eth2_hashing", + "ethereum-types", + "lazy_static", + "rand 0.7.3", + "smallvec 1.4.2", + "tree_hash_derive", + "types", ] [[package]] name = "tree_hash_derive" version = "0.2.0" dependencies = [ - "quote 1.0.7 (registry+https://github.com/rust-lang/crates.io-index)", - "syn 1.0.42 (registry+https://github.com/rust-lang/crates.io-index)", + "quote", + "syn", ] [[package]] name = "try-lock" version = "0.2.3" source = "registry+https://github.com/rust-lang/crates.io-index" +checksum = "59547bce71d9c38b83d9c0e92b6066c4253371f15005def0c30d9657f50c7642" + +[[package]] +name = "tungstenite" +version = "0.11.1" +source = "registry+https://github.com/rust-lang/crates.io-index" +checksum = "f0308d80d86700c5878b9ef6321f020f29b1bb9d5ff3cab25e75e23f3a492a23" +dependencies = [ + "base64 0.12.3", + "byteorder", + "bytes 0.5.6", + "http 0.2.1", + "httparse", + "input_buffer", + "log 0.4.11", + "rand 0.7.3", + "sha-1 0.9.1", + "url 2.1.1", + "utf-8", +] + +[[package]] +name = "twoway" +version = "0.1.8" +source = "registry+https://github.com/rust-lang/crates.io-index" +checksum = "59b11b2b5241ba34be09c3cc85a36e56e48f9888862e19cedf23336d35316ed1" +dependencies = [ + "memchr", +] [[package]] name = "typeable" version = "0.1.2" source = "registry+https://github.com/rust-lang/crates.io-index" +checksum = "1410f6f91f21d1612654e7cc69193b0334f909dcf2c790c4826254fbb86f8887" [[package]] name = "typenum" version = "1.12.0" source = "registry+https://github.com/rust-lang/crates.io-index" +checksum = "373c8a200f9e67a0c95e62a4f52fbf80c23b4381c05a17845531982fa99e6b33" [[package]] name = "types" version = "0.2.0" dependencies = [ - "arbitrary 0.4.6 (registry+https://github.com/rust-lang/crates.io-index)", - "bls 0.2.0", - "cached_tree_hash 0.1.0", - "compare_fields 0.2.0", - "compare_fields_derive 0.2.0", - "criterion 0.3.3 (registry+https://github.com/rust-lang/crates.io-index)", - "derivative 2.1.1 (registry+https://github.com/rust-lang/crates.io-index)", - "eth2_hashing 0.1.1", - "eth2_interop_keypairs 0.2.0", - "eth2_ssz 0.1.2", - "eth2_ssz_derive 0.1.0", - "eth2_ssz_types 0.2.0", - "ethereum-types 0.9.2 (registry+https://github.com/rust-lang/crates.io-index)", - "hex 0.4.2 (registry+https://github.com/rust-lang/crates.io-index)", - "int_to_bytes 0.2.0", - "log 0.4.11 (registry+https://github.com/rust-lang/crates.io-index)", - "merkle_proof 0.2.0", - "rand 0.7.3 (registry+https://github.com/rust-lang/crates.io-index)", - "rand_xorshift 0.2.0 (registry+https://github.com/rust-lang/crates.io-index)", - "rayon 1.4.0 (registry+https://github.com/rust-lang/crates.io-index)", - "rusqlite 0.23.1 (registry+https://github.com/rust-lang/crates.io-index)", - "safe_arith 0.1.0", - "serde 1.0.116 (registry+https://github.com/rust-lang/crates.io-index)", - "serde_derive 1.0.116 (registry+https://github.com/rust-lang/crates.io-index)", - "serde_json 1.0.57 (registry+https://github.com/rust-lang/crates.io-index)", - "serde_yaml 0.8.13 (registry+https://github.com/rust-lang/crates.io-index)", - "slog 2.5.2 (registry+https://github.com/rust-lang/crates.io-index)", - "swap_or_not_shuffle 0.2.0", - "tempfile 3.1.0 (registry+https://github.com/rust-lang/crates.io-index)", - "test_random_derive 0.2.0", - "tree_hash 0.1.1", - "tree_hash_derive 0.2.0", -] - -[[package]] -name = "uhttp_sse" -version = "0.5.1" -source = "registry+https://github.com/rust-lang/crates.io-index" + "arbitrary", + "bls", + "cached_tree_hash", + "compare_fields", + "compare_fields_derive", + "criterion", + "derivative", + "eth2_hashing", + "eth2_interop_keypairs", + "eth2_ssz", + "eth2_ssz_derive", + "eth2_ssz_types", + "ethereum-types", + "hex 0.4.2", + "int_to_bytes", + "log 0.4.11", + "merkle_proof", + "rand 0.7.3", + "rand_xorshift 0.2.0", + "rayon", + "regex", + "rusqlite", + "safe_arith", + "serde", + "serde_derive", + "serde_json", + "serde_utils", + "serde_yaml", + "slog", + "swap_or_not_shuffle", + "tempfile", + "test_random_derive", + "tree_hash", + "tree_hash_derive", +] [[package]] name = "uint" version = "0.8.5" source = "registry+https://github.com/rust-lang/crates.io-index" +checksum = "9db035e67dfaf7edd9aebfe8676afcd63eed53c8a4044fed514c8cccf1835177" dependencies = [ - "arbitrary 0.4.6 (registry+https://github.com/rust-lang/crates.io-index)", - "byteorder 1.3.4 (registry+https://github.com/rust-lang/crates.io-index)", - "crunchy 0.2.2 (registry+https://github.com/rust-lang/crates.io-index)", - "rustc-hex 2.1.0 (registry+https://github.com/rust-lang/crates.io-index)", - "static_assertions 1.1.0 (registry+https://github.com/rust-lang/crates.io-index)", + "arbitrary", + "byteorder", + "crunchy", + "rustc-hex", + "static_assertions", ] [[package]] name = "unescape" version = "0.1.0" source = "registry+https://github.com/rust-lang/crates.io-index" +checksum = "ccb97dac3243214f8d8507998906ca3e2e0b900bf9bf4870477f125b82e68f6e" [[package]] name = "unicase" version = "1.4.2" source = "registry+https://github.com/rust-lang/crates.io-index" +checksum = "7f4765f83163b74f957c797ad9253caf97f103fb064d3999aea9568d09fc8a33" dependencies = [ - "version_check 0.1.5 (registry+https://github.com/rust-lang/crates.io-index)", + "version_check 0.1.5", ] [[package]] name = "unicase" version = "2.6.0" source = "registry+https://github.com/rust-lang/crates.io-index" +checksum = "50f37be617794602aabbeee0be4f259dc1778fabe05e2d67ee8f79326d5cb4f6" dependencies = [ - "version_check 0.9.2 (registry+https://github.com/rust-lang/crates.io-index)", + "version_check 0.9.2", ] [[package]] name = "unicode-bidi" version = "0.3.4" source = "registry+https://github.com/rust-lang/crates.io-index" +checksum = "49f2bd0c6468a8230e1db229cff8029217cf623c767ea5d60bfbd42729ea54d5" dependencies = [ - "matches 0.1.8 (registry+https://github.com/rust-lang/crates.io-index)", + "matches", ] [[package]] name = "unicode-normalization" version = "0.1.13" source = "registry+https://github.com/rust-lang/crates.io-index" +checksum = "6fb19cf769fa8c6a80a162df694621ebeb4dafb606470b2b2fce0be40a98a977" dependencies = [ - "tinyvec 0.3.4 (registry+https://github.com/rust-lang/crates.io-index)", + "tinyvec", ] [[package]] name = "unicode-segmentation" version = "1.6.0" source = "registry+https://github.com/rust-lang/crates.io-index" +checksum = "e83e153d1053cbb5a118eeff7fd5be06ed99153f00dbcd8ae310c5fb2b22edc0" [[package]] name = "unicode-width" version = "0.1.8" source = "registry+https://github.com/rust-lang/crates.io-index" +checksum = "9337591893a19b88d8d87f2cec1e73fad5cdfd10e5a6f349f498ad6ea2ffb1e3" [[package]] name = "unicode-xid" version = "0.2.1" source = "registry+https://github.com/rust-lang/crates.io-index" +checksum = "f7fe0bb3479651439c9112f72b6c505038574c9fbb575ed1bf3b797fa39dd564" [[package]] name = "universal-hash" version = "0.4.0" source = "registry+https://github.com/rust-lang/crates.io-index" +checksum = "8326b2c654932e3e4f9196e69d08fdf7cfd718e1dc6f66b347e6024a0c961402" dependencies = [ - "generic-array 0.14.4 (registry+https://github.com/rust-lang/crates.io-index)", - "subtle 2.3.0 (registry+https://github.com/rust-lang/crates.io-index)", + "generic-array 0.14.4", + "subtle 2.3.0", ] [[package]] @@ -5506,1029 +6158,605 @@ name = "unsigned-varint" version = "0.3.3" source = "git+https://github.com/sigp/unsigned-varint?branch=latest-codecs#76fc423494e59f1ec4c8948bd0d3ae3c09851909" dependencies = [ - "bytes 0.5.6 (registry+https://github.com/rust-lang/crates.io-index)", - "tokio-util 0.3.1 (registry+https://github.com/rust-lang/crates.io-index)", + "bytes 0.5.6", + "tokio-util", ] [[package]] name = "unsigned-varint" version = "0.4.0" source = "registry+https://github.com/rust-lang/crates.io-index" +checksum = "669d776983b692a906c881fcd0cfb34271a48e197e4d6cb8df32b05bfc3d3fa5" dependencies = [ - "bytes 0.5.6 (registry+https://github.com/rust-lang/crates.io-index)", - "futures_codec 0.4.1 (registry+https://github.com/rust-lang/crates.io-index)", + "bytes 0.5.6", + "futures_codec", ] [[package]] name = "unsigned-varint" version = "0.5.1" source = "registry+https://github.com/rust-lang/crates.io-index" +checksum = "f7fdeedbf205afadfe39ae559b75c3240f24e257d0ca27e85f85cb82aa19ac35" dependencies = [ - "bytes 0.5.6 (registry+https://github.com/rust-lang/crates.io-index)", - "futures_codec 0.4.1 (registry+https://github.com/rust-lang/crates.io-index)", + "bytes 0.5.6", + "futures_codec", ] [[package]] name = "untrusted" version = "0.7.1" source = "registry+https://github.com/rust-lang/crates.io-index" +checksum = "a156c684c91ea7d62626509bce3cb4e1d9ed5c4d978f7b4352658f96a4c26b4a" [[package]] name = "url" version = "1.7.2" source = "registry+https://github.com/rust-lang/crates.io-index" +checksum = "dd4e7c0d531266369519a4aa4f399d748bd37043b00bde1e4ff1f60a120b355a" dependencies = [ - "idna 0.1.5 (registry+https://github.com/rust-lang/crates.io-index)", - "matches 0.1.8 (registry+https://github.com/rust-lang/crates.io-index)", - "percent-encoding 1.0.1 (registry+https://github.com/rust-lang/crates.io-index)", + "idna 0.1.5", + "matches", + "percent-encoding 1.0.1", ] [[package]] name = "url" version = "2.1.1" source = "registry+https://github.com/rust-lang/crates.io-index" +checksum = "829d4a8476c35c9bf0bbce5a3b23f4106f79728039b726d292bb93bc106787cb" dependencies = [ - "idna 0.2.0 (registry+https://github.com/rust-lang/crates.io-index)", - "matches 0.1.8 (registry+https://github.com/rust-lang/crates.io-index)", - "percent-encoding 2.1.0 (registry+https://github.com/rust-lang/crates.io-index)", + "idna 0.2.0", + "matches", + "percent-encoding 2.1.0", ] +[[package]] +name = "urlencoding" +version = "1.1.1" +source = "registry+https://github.com/rust-lang/crates.io-index" +checksum = "c9232eb53352b4442e40d7900465dfc534e8cb2dc8f18656fcb2ac16112b5593" + +[[package]] +name = "utf-8" +version = "0.7.5" +source = "registry+https://github.com/rust-lang/crates.io-index" +checksum = "05e42f7c18b8f902290b009cde6d651262f956c98bc51bca4cd1d511c9cd85c7" + [[package]] name = "uuid" version = "0.8.1" source = "registry+https://github.com/rust-lang/crates.io-index" +checksum = "9fde2f6a4bea1d6e007c4ad38c6839fa71cbb63b6dbf5b595aa38dc9b1093c11" dependencies = [ - "rand 0.7.3 (registry+https://github.com/rust-lang/crates.io-index)", - "serde 1.0.116 (registry+https://github.com/rust-lang/crates.io-index)", + "rand 0.7.3", + "serde", ] [[package]] name = "validator_client" version = "0.2.12" dependencies = [ - "account_utils 0.1.0", - "bls 0.2.0", - "clap 2.33.3 (registry+https://github.com/rust-lang/crates.io-index)", - "clap_utils 0.1.0", - "deposit_contract 0.2.0", - "directory 0.1.0", - "dirs 2.0.2 (registry+https://github.com/rust-lang/crates.io-index)", - "environment 0.1.2", - "eth2_config 0.2.0", - "eth2_interop_keypairs 0.2.0", - "eth2_keystore 0.1.0", - "eth2_ssz 0.1.2", - "eth2_ssz_derive 0.1.0", - "exit-future 0.2.0 (registry+https://github.com/rust-lang/crates.io-index)", - "futures 0.3.5 (registry+https://github.com/rust-lang/crates.io-index)", - "hex 0.4.2 (registry+https://github.com/rust-lang/crates.io-index)", - "libc 0.2.77 (registry+https://github.com/rust-lang/crates.io-index)", - "logging 0.2.0", - "parking_lot 0.11.0 (registry+https://github.com/rust-lang/crates.io-index)", - "rayon 1.4.0 (registry+https://github.com/rust-lang/crates.io-index)", - "remote_beacon_node 0.2.0", - "rest_types 0.2.0", - "serde 1.0.116 (registry+https://github.com/rust-lang/crates.io-index)", - "serde_derive 1.0.116 (registry+https://github.com/rust-lang/crates.io-index)", - "serde_json 1.0.57 (registry+https://github.com/rust-lang/crates.io-index)", - "serde_yaml 0.8.13 (registry+https://github.com/rust-lang/crates.io-index)", - "slashing_protection 0.1.0", - "slog 2.5.2 (registry+https://github.com/rust-lang/crates.io-index)", - "slog-async 2.5.0 (registry+https://github.com/rust-lang/crates.io-index)", - "slog-term 2.6.0 (registry+https://github.com/rust-lang/crates.io-index)", - "slot_clock 0.2.0", - "tempdir 0.3.7 (registry+https://github.com/rust-lang/crates.io-index)", - "tokio 0.2.22 (registry+https://github.com/rust-lang/crates.io-index)", - "tree_hash 0.1.1", - "types 0.2.0", - "validator_dir 0.1.0", + "account_utils", + "bls", + "clap", + "clap_utils", + "deposit_contract", + "directory", + "dirs", + "environment", + "eth2", + "eth2_config", + "eth2_interop_keypairs", + "eth2_keystore", + "eth2_ssz", + "eth2_ssz_derive", + "exit-future", + "futures 0.3.5", + "hex 0.4.2", + "libc", + "logging", + "parking_lot 0.11.0", + "rayon", + "serde", + "serde_derive", + "serde_json", + "serde_yaml", + "slashing_protection", + "slog", + "slog-async", + "slog-term", + "slot_clock", + "tempdir", + "tokio 0.2.22", + "tree_hash", + "types", + "validator_dir", ] [[package]] name = "validator_dir" version = "0.1.0" dependencies = [ - "bls 0.2.0", - "deposit_contract 0.2.0", - "eth2_keystore 0.1.0", - "hex 0.4.2 (registry+https://github.com/rust-lang/crates.io-index)", - "rand 0.7.3 (registry+https://github.com/rust-lang/crates.io-index)", - "rayon 1.4.0 (registry+https://github.com/rust-lang/crates.io-index)", - "slog 2.5.2 (registry+https://github.com/rust-lang/crates.io-index)", - "tempfile 3.1.0 (registry+https://github.com/rust-lang/crates.io-index)", - "tree_hash 0.1.1", - "types 0.2.0", + "bls", + "deposit_contract", + "eth2_keystore", + "hex 0.4.2", + "rand 0.7.3", + "rayon", + "slog", + "tempfile", + "tree_hash", + "types", ] [[package]] name = "vcpkg" version = "0.2.10" source = "registry+https://github.com/rust-lang/crates.io-index" +checksum = "6454029bf181f092ad1b853286f23e2c507d8e8194d01d92da4a55c274a5508c" [[package]] name = "vec_map" version = "0.8.2" source = "registry+https://github.com/rust-lang/crates.io-index" +checksum = "f1bddf1187be692e79c5ffeab891132dfb0f236ed36a43c7ed39f1165ee20191" [[package]] name = "version_check" version = "0.1.5" source = "registry+https://github.com/rust-lang/crates.io-index" +checksum = "914b1a6776c4c929a602fafd8bc742e06365d4bcbe48c30f9cca5824f70dc9dd" [[package]] name = "version_check" version = "0.9.2" source = "registry+https://github.com/rust-lang/crates.io-index" +checksum = "b5a972e5669d67ba988ce3dc826706fb0a8b01471c088cb0b6110b805cc36aed" [[package]] name = "void" version = "1.0.2" source = "registry+https://github.com/rust-lang/crates.io-index" +checksum = "6a02e4885ed3bc0f2de90ea6dd45ebcbb66dacffe03547fadbb0eeae2770887d" [[package]] name = "walkdir" version = "2.3.1" source = "registry+https://github.com/rust-lang/crates.io-index" +checksum = "777182bc735b6424e1a57516d35ed72cb8019d85c8c9bf536dccb3445c1a2f7d" dependencies = [ - "same-file 1.0.6 (registry+https://github.com/rust-lang/crates.io-index)", - "winapi 0.3.9 (registry+https://github.com/rust-lang/crates.io-index)", - "winapi-util 0.1.5 (registry+https://github.com/rust-lang/crates.io-index)", + "same-file", + "winapi 0.3.9", + "winapi-util", ] [[package]] name = "want" version = "0.2.0" source = "registry+https://github.com/rust-lang/crates.io-index" +checksum = "b6395efa4784b027708f7451087e647ec73cc74f5d9bc2e418404248d679a230" dependencies = [ - "futures 0.1.29 (registry+https://github.com/rust-lang/crates.io-index)", - "log 0.4.11 (registry+https://github.com/rust-lang/crates.io-index)", - "try-lock 0.2.3 (registry+https://github.com/rust-lang/crates.io-index)", + "futures 0.1.29", + "log 0.4.11", + "try-lock", ] [[package]] name = "want" version = "0.3.0" source = "registry+https://github.com/rust-lang/crates.io-index" +checksum = "1ce8a968cb1cd110d136ff8b819a556d6fb6d919363c61534f6860c7eb172ba0" dependencies = [ - "log 0.4.11 (registry+https://github.com/rust-lang/crates.io-index)", - "try-lock 0.2.3 (registry+https://github.com/rust-lang/crates.io-index)", + "log 0.4.11", + "try-lock", +] + +[[package]] +name = "warp" +version = "0.2.5" +source = "registry+https://github.com/rust-lang/crates.io-index" +checksum = "f41be6df54c97904af01aa23e613d4521eed7ab23537cede692d4058f6449407" +dependencies = [ + "bytes 0.5.6", + "futures 0.3.5", + "headers", + "http 0.2.1", + "hyper 0.13.8", + "log 0.4.11", + "mime 0.3.16", + "mime_guess", + "multipart", + "pin-project", + "scoped-tls 1.0.0", + "serde", + "serde_json", + "serde_urlencoded", + "tokio 0.2.22", + "tokio-tungstenite", + "tower-service", + "tracing", + "tracing-futures", + "urlencoding", +] + +[[package]] +name = "warp_utils" +version = "0.1.0" +dependencies = [ + "beacon_chain", + "eth2", + "safe_arith", + "state_processing", + "types", + "warp", ] [[package]] name = "wasi" version = "0.9.0+wasi-snapshot-preview1" source = "registry+https://github.com/rust-lang/crates.io-index" +checksum = "cccddf32554fecc6acb585f82a32a72e28b48f8c4c1883ddfeeeaa96f7d8e519" [[package]] name = "wasi" version = "0.10.0+wasi-snapshot-preview1" source = "registry+https://github.com/rust-lang/crates.io-index" +checksum = "1a143597ca7c7793eff794def352d41792a93c481eb1042423ff7ff72ba2c31f" [[package]] name = "wasm-bindgen" version = "0.2.68" source = "registry+https://github.com/rust-lang/crates.io-index" +checksum = "1ac64ead5ea5f05873d7c12b545865ca2b8d28adfc50a49b84770a3a97265d42" dependencies = [ - "cfg-if 0.1.10 (registry+https://github.com/rust-lang/crates.io-index)", - "serde 1.0.116 (registry+https://github.com/rust-lang/crates.io-index)", - "serde_json 1.0.57 (registry+https://github.com/rust-lang/crates.io-index)", - "wasm-bindgen-macro 0.2.68 (registry+https://github.com/rust-lang/crates.io-index)", + "cfg-if", + "serde", + "serde_json", + "wasm-bindgen-macro", ] [[package]] name = "wasm-bindgen-backend" version = "0.2.68" source = "registry+https://github.com/rust-lang/crates.io-index" +checksum = "f22b422e2a757c35a73774860af8e112bff612ce6cb604224e8e47641a9e4f68" dependencies = [ - "bumpalo 3.4.0 (registry+https://github.com/rust-lang/crates.io-index)", - "lazy_static 1.4.0 (registry+https://github.com/rust-lang/crates.io-index)", - "log 0.4.11 (registry+https://github.com/rust-lang/crates.io-index)", - "proc-macro2 1.0.23 (registry+https://github.com/rust-lang/crates.io-index)", - "quote 1.0.7 (registry+https://github.com/rust-lang/crates.io-index)", - "syn 1.0.42 (registry+https://github.com/rust-lang/crates.io-index)", - "wasm-bindgen-shared 0.2.68 (registry+https://github.com/rust-lang/crates.io-index)", + "bumpalo", + "lazy_static", + "log 0.4.11", + "proc-macro2", + "quote", + "syn", + "wasm-bindgen-shared", ] [[package]] name = "wasm-bindgen-futures" version = "0.4.18" source = "registry+https://github.com/rust-lang/crates.io-index" +checksum = "b7866cab0aa01de1edf8b5d7936938a7e397ee50ce24119aef3e1eaa3b6171da" dependencies = [ - "cfg-if 0.1.10 (registry+https://github.com/rust-lang/crates.io-index)", - "js-sys 0.3.45 (registry+https://github.com/rust-lang/crates.io-index)", - "wasm-bindgen 0.2.68 (registry+https://github.com/rust-lang/crates.io-index)", - "web-sys 0.3.45 (registry+https://github.com/rust-lang/crates.io-index)", + "cfg-if", + "js-sys", + "wasm-bindgen", + "web-sys", ] [[package]] name = "wasm-bindgen-macro" version = "0.2.68" source = "registry+https://github.com/rust-lang/crates.io-index" +checksum = "6b13312a745c08c469f0b292dd2fcd6411dba5f7160f593da6ef69b64e407038" dependencies = [ - "quote 1.0.7 (registry+https://github.com/rust-lang/crates.io-index)", - "wasm-bindgen-macro-support 0.2.68 (registry+https://github.com/rust-lang/crates.io-index)", + "quote", + "wasm-bindgen-macro-support", ] [[package]] name = "wasm-bindgen-macro-support" version = "0.2.68" source = "registry+https://github.com/rust-lang/crates.io-index" +checksum = "f249f06ef7ee334cc3b8ff031bfc11ec99d00f34d86da7498396dc1e3b1498fe" dependencies = [ - "proc-macro2 1.0.23 (registry+https://github.com/rust-lang/crates.io-index)", - "quote 1.0.7 (registry+https://github.com/rust-lang/crates.io-index)", - "syn 1.0.42 (registry+https://github.com/rust-lang/crates.io-index)", - "wasm-bindgen-backend 0.2.68 (registry+https://github.com/rust-lang/crates.io-index)", - "wasm-bindgen-shared 0.2.68 (registry+https://github.com/rust-lang/crates.io-index)", + "proc-macro2", + "quote", + "syn", + "wasm-bindgen-backend", + "wasm-bindgen-shared", ] [[package]] name = "wasm-bindgen-shared" version = "0.2.68" source = "registry+https://github.com/rust-lang/crates.io-index" +checksum = "1d649a3145108d7d3fbcde896a468d1bd636791823c9921135218ad89be08307" [[package]] name = "wasm-bindgen-test" version = "0.3.18" source = "registry+https://github.com/rust-lang/crates.io-index" +checksum = "34d1cdc8b98a557f24733d50a1199c4b0635e465eecba9c45b214544da197f64" dependencies = [ - "console_error_panic_hook 0.1.6 (registry+https://github.com/rust-lang/crates.io-index)", - "js-sys 0.3.45 (registry+https://github.com/rust-lang/crates.io-index)", - "scoped-tls 1.0.0 (registry+https://github.com/rust-lang/crates.io-index)", - "wasm-bindgen 0.2.68 (registry+https://github.com/rust-lang/crates.io-index)", - "wasm-bindgen-futures 0.4.18 (registry+https://github.com/rust-lang/crates.io-index)", - "wasm-bindgen-test-macro 0.3.18 (registry+https://github.com/rust-lang/crates.io-index)", + "console_error_panic_hook", + "js-sys", + "scoped-tls 1.0.0", + "wasm-bindgen", + "wasm-bindgen-futures", + "wasm-bindgen-test-macro", ] [[package]] name = "wasm-bindgen-test-macro" version = "0.3.18" source = "registry+https://github.com/rust-lang/crates.io-index" +checksum = "e8fb9c67be7439ee8ab1b7db502a49c05e51e2835b66796c705134d9b8e1a585" dependencies = [ - "proc-macro2 1.0.23 (registry+https://github.com/rust-lang/crates.io-index)", - "quote 1.0.7 (registry+https://github.com/rust-lang/crates.io-index)", + "proc-macro2", + "quote", ] [[package]] name = "wasm-timer" version = "0.2.5" source = "registry+https://github.com/rust-lang/crates.io-index" +checksum = "be0ecb0db480561e9a7642b5d3e4187c128914e58aa84330b9493e3eb68c5e7f" dependencies = [ - "futures 0.3.5 (registry+https://github.com/rust-lang/crates.io-index)", - "js-sys 0.3.45 (registry+https://github.com/rust-lang/crates.io-index)", - "parking_lot 0.11.0 (registry+https://github.com/rust-lang/crates.io-index)", - "pin-utils 0.1.0 (registry+https://github.com/rust-lang/crates.io-index)", - "wasm-bindgen 0.2.68 (registry+https://github.com/rust-lang/crates.io-index)", - "wasm-bindgen-futures 0.4.18 (registry+https://github.com/rust-lang/crates.io-index)", - "web-sys 0.3.45 (registry+https://github.com/rust-lang/crates.io-index)", + "futures 0.3.5", + "js-sys", + "parking_lot 0.11.0", + "pin-utils", + "wasm-bindgen", + "wasm-bindgen-futures", + "web-sys", ] [[package]] name = "web-sys" version = "0.3.45" source = "registry+https://github.com/rust-lang/crates.io-index" +checksum = "4bf6ef87ad7ae8008e15a355ce696bed26012b7caa21605188cfd8214ab51e2d" dependencies = [ - "js-sys 0.3.45 (registry+https://github.com/rust-lang/crates.io-index)", - "wasm-bindgen 0.2.68 (registry+https://github.com/rust-lang/crates.io-index)", + "js-sys", + "wasm-bindgen", ] [[package]] name = "web3" version = "0.11.0" source = "registry+https://github.com/rust-lang/crates.io-index" -dependencies = [ - "arrayvec 0.5.1 (registry+https://github.com/rust-lang/crates.io-index)", - "base64 0.12.3 (registry+https://github.com/rust-lang/crates.io-index)", - "derive_more 0.99.10 (registry+https://github.com/rust-lang/crates.io-index)", - "ethabi 12.0.0 (registry+https://github.com/rust-lang/crates.io-index)", - "ethereum-types 0.9.2 (registry+https://github.com/rust-lang/crates.io-index)", - "futures 0.1.29 (registry+https://github.com/rust-lang/crates.io-index)", - "hyper 0.12.35 (registry+https://github.com/rust-lang/crates.io-index)", - "hyper-tls 0.3.2 (registry+https://github.com/rust-lang/crates.io-index)", - "jsonrpc-core 14.2.0 (registry+https://github.com/rust-lang/crates.io-index)", - "log 0.4.11 (registry+https://github.com/rust-lang/crates.io-index)", - "native-tls 0.2.4 (registry+https://github.com/rust-lang/crates.io-index)", - "parking_lot 0.10.2 (registry+https://github.com/rust-lang/crates.io-index)", - "rlp 0.4.5 (registry+https://github.com/rust-lang/crates.io-index)", - "rustc-hex 2.1.0 (registry+https://github.com/rust-lang/crates.io-index)", - "secp256k1 0.17.2 (registry+https://github.com/rust-lang/crates.io-index)", - "serde 1.0.116 (registry+https://github.com/rust-lang/crates.io-index)", - "serde_json 1.0.57 (registry+https://github.com/rust-lang/crates.io-index)", - "tiny-keccak 2.0.2 (registry+https://github.com/rust-lang/crates.io-index)", - "tokio-core 0.1.17 (registry+https://github.com/rust-lang/crates.io-index)", - "tokio-io 0.1.13 (registry+https://github.com/rust-lang/crates.io-index)", - "tokio-timer 0.1.2 (registry+https://github.com/rust-lang/crates.io-index)", - "tokio-uds 0.1.7 (registry+https://github.com/rust-lang/crates.io-index)", - "url 2.1.1 (registry+https://github.com/rust-lang/crates.io-index)", - "websocket 0.21.1 (registry+https://github.com/rust-lang/crates.io-index)", - "zeroize 1.1.1 (registry+https://github.com/rust-lang/crates.io-index)", +checksum = "9a681e8d15deced7c510db88c59133d2eafa7b6298b6e91b545e2a3fed93b3fe" +dependencies = [ + "arrayvec", + "base64 0.12.3", + "derive_more", + "ethabi", + "ethereum-types", + "futures 0.1.29", + "hyper 0.12.35", + "hyper-tls 0.3.2", + "jsonrpc-core", + "log 0.4.11", + "native-tls", + "parking_lot 0.10.2", + "rlp", + "rustc-hex", + "secp256k1", + "serde", + "serde_json", + "tiny-keccak 2.0.2", + "tokio-core", + "tokio-io", + "tokio-timer 0.1.2", + "tokio-uds 0.1.7", + "url 2.1.1", + "websocket", + "zeroize", ] [[package]] name = "webpki" version = "0.21.2" source = "registry+https://github.com/rust-lang/crates.io-index" +checksum = "f1f50e1972865d6b1adb54167d1c8ed48606004c2c9d0ea5f1eeb34d95e863ef" dependencies = [ - "ring 0.16.12 (registry+https://github.com/rust-lang/crates.io-index)", - "untrusted 0.7.1 (registry+https://github.com/rust-lang/crates.io-index)", + "ring", + "untrusted", ] [[package]] name = "webpki-roots" version = "0.18.0" source = "registry+https://github.com/rust-lang/crates.io-index" +checksum = "91cd5736df7f12a964a5067a12c62fa38e1bd8080aff1f80bc29be7c80d19ab4" dependencies = [ - "webpki 0.21.2 (registry+https://github.com/rust-lang/crates.io-index)", + "webpki", ] [[package]] name = "webpki-roots" version = "0.19.0" source = "registry+https://github.com/rust-lang/crates.io-index" +checksum = "f8eff4b7516a57307f9349c64bf34caa34b940b66fed4b2fb3136cb7386e5739" dependencies = [ - "webpki 0.21.2 (registry+https://github.com/rust-lang/crates.io-index)", + "webpki", ] [[package]] name = "websocket" version = "0.21.1" source = "registry+https://github.com/rust-lang/crates.io-index" +checksum = "8c9faed2bff8af2ea6b9f8b917d3d00b467583f6781fe3def174a9e33c879703" dependencies = [ - "base64 0.9.3 (registry+https://github.com/rust-lang/crates.io-index)", - "bitflags 0.9.1 (registry+https://github.com/rust-lang/crates.io-index)", - "byteorder 1.3.4 (registry+https://github.com/rust-lang/crates.io-index)", - "bytes 0.4.12 (registry+https://github.com/rust-lang/crates.io-index)", - "futures 0.1.29 (registry+https://github.com/rust-lang/crates.io-index)", - "hyper 0.10.16 (registry+https://github.com/rust-lang/crates.io-index)", - "native-tls 0.2.4 (registry+https://github.com/rust-lang/crates.io-index)", - "rand 0.5.6 (registry+https://github.com/rust-lang/crates.io-index)", - "sha1 0.6.0 (registry+https://github.com/rust-lang/crates.io-index)", - "tokio-core 0.1.17 (registry+https://github.com/rust-lang/crates.io-index)", - "tokio-io 0.1.13 (registry+https://github.com/rust-lang/crates.io-index)", - "tokio-tls 0.2.1 (registry+https://github.com/rust-lang/crates.io-index)", - "unicase 1.4.2 (registry+https://github.com/rust-lang/crates.io-index)", - "url 1.7.2 (registry+https://github.com/rust-lang/crates.io-index)", + "base64 0.9.3", + "bitflags 0.9.1", + "byteorder", + "bytes 0.4.12", + "futures 0.1.29", + "hyper 0.10.16", + "native-tls", + "rand 0.5.6", + "sha1", + "tokio-core", + "tokio-io", + "tokio-tls 0.2.1", + "unicase 1.4.2", + "url 1.7.2", ] [[package]] name = "websocket_server" version = "0.2.0" dependencies = [ - "environment 0.1.2", - "futures 0.3.5 (registry+https://github.com/rust-lang/crates.io-index)", - "serde 1.0.116 (registry+https://github.com/rust-lang/crates.io-index)", - "serde_derive 1.0.116 (registry+https://github.com/rust-lang/crates.io-index)", - "serde_json 1.0.57 (registry+https://github.com/rust-lang/crates.io-index)", - "slog 2.5.2 (registry+https://github.com/rust-lang/crates.io-index)", - "tokio 0.2.22 (registry+https://github.com/rust-lang/crates.io-index)", - "types 0.2.0", - "ws 0.9.1 (registry+https://github.com/rust-lang/crates.io-index)", + "environment", + "futures 0.3.5", + "serde", + "serde_derive", + "serde_json", + "slog", + "tokio 0.2.22", + "types", + "ws", ] [[package]] name = "which" version = "3.1.1" source = "registry+https://github.com/rust-lang/crates.io-index" +checksum = "d011071ae14a2f6671d0b74080ae0cd8ebf3a6f8c9589a2cd45f23126fe29724" dependencies = [ - "libc 0.2.77 (registry+https://github.com/rust-lang/crates.io-index)", + "libc", ] [[package]] name = "winapi" version = "0.2.8" source = "registry+https://github.com/rust-lang/crates.io-index" +checksum = "167dc9d6949a9b857f3451275e911c3f44255842c1f7a76f33c55103a909087a" [[package]] name = "winapi" version = "0.3.9" source = "registry+https://github.com/rust-lang/crates.io-index" +checksum = "5c839a674fcd7a98952e593242ea400abe93992746761e38641405d28b00f419" dependencies = [ - "winapi-i686-pc-windows-gnu 0.4.0 (registry+https://github.com/rust-lang/crates.io-index)", - "winapi-x86_64-pc-windows-gnu 0.4.0 (registry+https://github.com/rust-lang/crates.io-index)", + "winapi-i686-pc-windows-gnu", + "winapi-x86_64-pc-windows-gnu", ] [[package]] name = "winapi-build" version = "0.1.1" source = "registry+https://github.com/rust-lang/crates.io-index" +checksum = "2d315eee3b34aca4797b2da6b13ed88266e6d612562a0c46390af8299fc699bc" [[package]] name = "winapi-i686-pc-windows-gnu" version = "0.4.0" source = "registry+https://github.com/rust-lang/crates.io-index" +checksum = "ac3b87c63620426dd9b991e5ce0329eff545bccbbb34f3be09ff6fb6ab51b7b6" [[package]] name = "winapi-util" version = "0.1.5" source = "registry+https://github.com/rust-lang/crates.io-index" +checksum = "70ec6ce85bb158151cae5e5c87f95a8e97d2c0c4b001223f33a334e3ce5de178" dependencies = [ - "winapi 0.3.9 (registry+https://github.com/rust-lang/crates.io-index)", + "winapi 0.3.9", ] [[package]] name = "winapi-x86_64-pc-windows-gnu" version = "0.4.0" source = "registry+https://github.com/rust-lang/crates.io-index" +checksum = "712e227841d057c1ee1cd2fb22fa7e5a5461ae8e48fa2ca79ec42cfc1931183f" [[package]] name = "winreg" version = "0.7.0" source = "registry+https://github.com/rust-lang/crates.io-index" +checksum = "0120db82e8a1e0b9fb3345a539c478767c0048d842860994d96113d5b667bd69" dependencies = [ - "winapi 0.3.9 (registry+https://github.com/rust-lang/crates.io-index)", + "winapi 0.3.9", ] [[package]] name = "ws" version = "0.9.1" source = "registry+https://github.com/rust-lang/crates.io-index" +checksum = "c51a2c47b5798ccc774ffb93ff536aec7c4275d722fd9c740c83cdd1af1f2d94" dependencies = [ - "byteorder 1.3.4 (registry+https://github.com/rust-lang/crates.io-index)", - "bytes 0.4.12 (registry+https://github.com/rust-lang/crates.io-index)", - "httparse 1.3.4 (registry+https://github.com/rust-lang/crates.io-index)", - "log 0.4.11 (registry+https://github.com/rust-lang/crates.io-index)", - "mio 0.6.22 (registry+https://github.com/rust-lang/crates.io-index)", - "mio-extras 2.0.6 (registry+https://github.com/rust-lang/crates.io-index)", - "rand 0.7.3 (registry+https://github.com/rust-lang/crates.io-index)", - "sha-1 0.8.2 (registry+https://github.com/rust-lang/crates.io-index)", - "slab 0.4.2 (registry+https://github.com/rust-lang/crates.io-index)", - "url 2.1.1 (registry+https://github.com/rust-lang/crates.io-index)", + "byteorder", + "bytes 0.4.12", + "httparse", + "log 0.4.11", + "mio", + "mio-extras", + "rand 0.7.3", + "sha-1 0.8.2", + "slab 0.4.2", + "url 2.1.1", ] [[package]] name = "ws2_32-sys" version = "0.2.1" source = "registry+https://github.com/rust-lang/crates.io-index" +checksum = "d59cefebd0c892fa2dd6de581e937301d8552cb44489cdff035c6187cb63fa5e" dependencies = [ - "winapi 0.2.8 (registry+https://github.com/rust-lang/crates.io-index)", - "winapi-build 0.1.1 (registry+https://github.com/rust-lang/crates.io-index)", + "winapi 0.2.8", + "winapi-build", ] [[package]] name = "x25519-dalek" version = "0.6.0" source = "registry+https://github.com/rust-lang/crates.io-index" +checksum = "637ff90c9540fa3073bb577e65033069e4bae7c79d49d74aa3ffdf5342a53217" dependencies = [ - "curve25519-dalek 2.1.0 (registry+https://github.com/rust-lang/crates.io-index)", - "rand_core 0.5.1 (registry+https://github.com/rust-lang/crates.io-index)", - "zeroize 1.1.1 (registry+https://github.com/rust-lang/crates.io-index)", + "curve25519-dalek 2.1.0", + "rand_core 0.5.1", + "zeroize", ] [[package]] name = "yaml-rust" version = "0.4.4" source = "registry+https://github.com/rust-lang/crates.io-index" +checksum = "39f0c922f1a334134dc2f7a8b67dc5d25f0735263feec974345ff706bcf20b0d" dependencies = [ - "linked-hash-map 0.5.3 (registry+https://github.com/rust-lang/crates.io-index)", + "linked-hash-map", ] [[package]] name = "zeroize" version = "1.1.1" source = "registry+https://github.com/rust-lang/crates.io-index" +checksum = "05f33972566adbd2d3588b0491eb94b98b43695c4ef897903470ede4f3f5a28a" dependencies = [ - "zeroize_derive 1.0.1 (registry+https://github.com/rust-lang/crates.io-index)", + "zeroize_derive", ] [[package]] name = "zeroize_derive" version = "1.0.1" source = "registry+https://github.com/rust-lang/crates.io-index" +checksum = "c3f369ddb18862aba61aa49bf31e74d29f0f162dec753063200e1dc084345d16" dependencies = [ - "proc-macro2 1.0.23 (registry+https://github.com/rust-lang/crates.io-index)", - "quote 1.0.7 (registry+https://github.com/rust-lang/crates.io-index)", - "syn 1.0.42 (registry+https://github.com/rust-lang/crates.io-index)", - "synstructure 0.12.4 (registry+https://github.com/rust-lang/crates.io-index)", + "proc-macro2", + "quote", + "syn", + "synstructure", ] [[package]] name = "zip" version = "0.5.6" source = "registry+https://github.com/rust-lang/crates.io-index" +checksum = "58287c28d78507f5f91f2a4cf1e8310e2c76fd4c6932f93ac60fd1ceb402db7d" dependencies = [ - "bzip2 0.3.3 (registry+https://github.com/rust-lang/crates.io-index)", - "crc32fast 1.2.0 (registry+https://github.com/rust-lang/crates.io-index)", - "flate2 1.0.17 (registry+https://github.com/rust-lang/crates.io-index)", - "podio 0.1.7 (registry+https://github.com/rust-lang/crates.io-index)", - "time 0.1.44 (registry+https://github.com/rust-lang/crates.io-index)", -] - -[metadata] -"checksum addr2line 0.13.0 (registry+https://github.com/rust-lang/crates.io-index)" = "1b6a2d3371669ab3ca9797670853d61402b03d0b4b9ebf33d677dfa720203072" -"checksum adler 0.2.3 (registry+https://github.com/rust-lang/crates.io-index)" = "ee2a4ec343196209d6594e19543ae87a39f96d5534d7174822a3ad825dd6ed7e" -"checksum adler32 1.2.0 (registry+https://github.com/rust-lang/crates.io-index)" = "aae1277d39aeec15cb388266ecc24b11c80469deae6067e17a1a7aa9e5c1f234" -"checksum aead 0.3.2 (registry+https://github.com/rust-lang/crates.io-index)" = "7fc95d1bdb8e6666b2b217308eeeb09f2d6728d104be3e31916cc74d15420331" -"checksum aes 0.4.0 (registry+https://github.com/rust-lang/crates.io-index)" = "f7001367fde4c768a19d1029f0a8be5abd9308e1119846d5bd9ad26297b8faf5" -"checksum aes-ctr 0.4.0 (registry+https://github.com/rust-lang/crates.io-index)" = "92e60aeefd2a0243bd53a42e92444e039f67c3d7f0382c9813577696e7c10bf3" -"checksum aes-gcm 0.6.0 (registry+https://github.com/rust-lang/crates.io-index)" = "86f5007801316299f922a6198d1d09a0bae95786815d066d5880d13f7c45ead1" -"checksum aes-soft 0.4.0 (registry+https://github.com/rust-lang/crates.io-index)" = "4925647ee64e5056cf231608957ce7c81e12d6d6e316b9ce1404778cc1d35fa7" -"checksum aesni 0.7.0 (registry+https://github.com/rust-lang/crates.io-index)" = "d050d39b0b7688b3a3254394c3e30a9d66c41dcf9b05b0e2dbdc623f6505d264" -"checksum ahash 0.2.18 (registry+https://github.com/rust-lang/crates.io-index)" = "6f33b5018f120946c1dcf279194f238a9f146725593ead1c08fa47ff22b0b5d3" -"checksum aho-corasick 0.7.13 (registry+https://github.com/rust-lang/crates.io-index)" = "043164d8ba5c4c3035fec9bbee8647c0261d788f3474306f93bb65901cae0e86" -"checksum amcl 0.2.0 (git+https://github.com/sigp/milagro_bls?branch=paulh)" = "" -"checksum ansi_term 0.11.0 (registry+https://github.com/rust-lang/crates.io-index)" = "ee49baf6cb617b853aa8d93bf420db2383fab46d314482ca2803b40d5fde979b" -"checksum anyhow 1.0.32 (registry+https://github.com/rust-lang/crates.io-index)" = "6b602bfe940d21c130f3895acd65221e8a61270debe89d628b9cb4e3ccb8569b" -"checksum arbitrary 0.4.6 (registry+https://github.com/rust-lang/crates.io-index)" = "0922a3e746b5a44e111e5603feb6704e5cc959116f66737f50bb5cbd264e9d87" -"checksum arc-swap 0.4.7 (registry+https://github.com/rust-lang/crates.io-index)" = "4d25d88fd6b8041580a654f9d0c581a047baee2b3efee13275f2fc392fc75034" -"checksum arrayref 0.3.6 (registry+https://github.com/rust-lang/crates.io-index)" = "a4c527152e37cf757a3f78aae5a06fbeefdb07ccc535c980a3208ee3060dd544" -"checksum arrayvec 0.5.1 (registry+https://github.com/rust-lang/crates.io-index)" = "cff77d8686867eceff3105329d4698d96c2391c176d5d03adc90c7389162b5b8" -"checksum asn1_der 0.6.3 (registry+https://github.com/rust-lang/crates.io-index)" = "6fce6b6a0ffdafebd82c87e79e3f40e8d2c523e5fea5566ff6b90509bf98d638" -"checksum asn1_der_derive 0.1.2 (registry+https://github.com/rust-lang/crates.io-index)" = "0d0864d84b8e07b145449be9a8537db86bf9de5ce03b913214694643b4743502" -"checksum assert_matches 1.3.0 (registry+https://github.com/rust-lang/crates.io-index)" = "7deb0a829ca7bcfaf5da70b073a8d128619259a7be8216a355e23f00763059e5" -"checksum async-tls 0.8.0 (registry+https://github.com/rust-lang/crates.io-index)" = "df097e3f506bec0e1a24f06bb3c962c228f36671de841ff579cb99f371772634" -"checksum atomic 0.4.6 (registry+https://github.com/rust-lang/crates.io-index)" = "64f46ca51dca4837f1520754d1c8c36636356b81553d928dc9c177025369a06e" -"checksum atomic-option 0.1.2 (registry+https://github.com/rust-lang/crates.io-index)" = "0db678acb667b525ac40a324fc5f7d3390e29239b31c7327bb8157f5b4fff593" -"checksum atty 0.2.14 (registry+https://github.com/rust-lang/crates.io-index)" = "d9b39be18770d11421cdb1b9947a45dd3f37e93092cbf377614828a319d5fee8" -"checksum autocfg 0.1.7 (registry+https://github.com/rust-lang/crates.io-index)" = "1d49d90015b3c36167a20fe2810c5cd875ad504b39cff3d4eae7977e6b7c1cb2" -"checksum autocfg 1.0.1 (registry+https://github.com/rust-lang/crates.io-index)" = "cdb031dd78e28731d87d56cc8ffef4a8f36ca26c38fe2de700543e627f8a464a" -"checksum backtrace 0.3.50 (registry+https://github.com/rust-lang/crates.io-index)" = "46254cf2fdcdf1badb5934448c1bcbe046a56537b3987d96c51a7afc5d03f293" -"checksum base-x 0.2.6 (registry+https://github.com/rust-lang/crates.io-index)" = "1b20b618342cf9891c292c4f5ac2cde7287cc5c87e87e9c769d617793607dec1" -"checksum base64 0.12.3 (registry+https://github.com/rust-lang/crates.io-index)" = "3441f0f7b02788e948e47f457ca01f1d7e6d92c693bc132c22b087d3141c03ff" -"checksum base64 0.9.3 (registry+https://github.com/rust-lang/crates.io-index)" = "489d6c0ed21b11d038c31b6ceccca973e65d73ba3bd8ecb9a2babf5546164643" -"checksum bitflags 0.9.1 (registry+https://github.com/rust-lang/crates.io-index)" = "4efd02e230a02e18f92fc2735f44597385ed02ad8f831e7c1c1156ee5e1ab3a5" -"checksum bitflags 1.2.1 (registry+https://github.com/rust-lang/crates.io-index)" = "cf1de2fe8c75bc145a2f577add951f8134889b4795d47466a54a5c846d691693" -"checksum bitvec 0.17.4 (registry+https://github.com/rust-lang/crates.io-index)" = "41262f11d771fd4a61aa3ce019fca363b4b6c282fca9da2a31186d3965a47a5c" -"checksum blake2 0.9.0 (registry+https://github.com/rust-lang/crates.io-index)" = "84ce5b6108f8e154604bd4eb76a2f726066c3464d5a552a4229262a18c9bb471" -"checksum blake2b_simd 0.5.10 (registry+https://github.com/rust-lang/crates.io-index)" = "d8fb2d74254a3a0b5cac33ac9f8ed0e44aa50378d9dbb2e5d83bd21ed1dc2c8a" -"checksum blake2s_simd 0.5.10 (registry+https://github.com/rust-lang/crates.io-index)" = "ab9e07352b829279624ceb7c64adb4f585dacdb81d35cafae81139ccd617cf44" -"checksum block-buffer 0.7.3 (registry+https://github.com/rust-lang/crates.io-index)" = "c0940dc441f31689269e10ac70eb1002a3a1d3ad1390e030043662eb7fe4688b" -"checksum block-buffer 0.9.0 (registry+https://github.com/rust-lang/crates.io-index)" = "4152116fd6e9dadb291ae18fc1ec3575ed6d84c29642d97890f4b4a3417297e4" -"checksum block-cipher 0.7.1 (registry+https://github.com/rust-lang/crates.io-index)" = "fa136449e765dc7faa244561ccae839c394048667929af599b5d931ebe7b7f10" -"checksum block-padding 0.1.5 (registry+https://github.com/rust-lang/crates.io-index)" = "fa79dedbb091f449f1f39e53edf88d5dbe95f895dae6135a8d7b881fb5af73f5" -"checksum block-padding 0.2.1 (registry+https://github.com/rust-lang/crates.io-index)" = "8d696c370c750c948ada61c69a0ee2cbbb9c50b1019ddb86d9317157a99c2cae" -"checksum blst 0.1.1 (git+https://github.com/sigp/blst.git?rev=284f7059642851c760a09fb1708bcb59c7ca323c)" = "" -"checksum bs58 0.3.1 (registry+https://github.com/rust-lang/crates.io-index)" = "476e9cd489f9e121e02ffa6014a8ef220ecb15c05ed23fc34cca13925dc283fb" -"checksum bstr 0.2.13 (registry+https://github.com/rust-lang/crates.io-index)" = "31accafdb70df7871592c058eca3985b71104e15ac32f64706022c58867da931" -"checksum bumpalo 3.4.0 (registry+https://github.com/rust-lang/crates.io-index)" = "2e8c087f005730276d1096a652e92a8bacee2e2472bcc9715a74d2bec38b5820" -"checksum bus 2.2.3 (registry+https://github.com/rust-lang/crates.io-index)" = "f1e66e1779f5b1440f1a58220ba3b3ded4427175f0a9fb8d7066521f8b4e8f2b" -"checksum byte-slice-cast 0.3.5 (registry+https://github.com/rust-lang/crates.io-index)" = "b0a5e3906bcbf133e33c1d4d95afc664ad37fbdb9f6568d8043e7ea8c27d93d3" -"checksum byte-tools 0.3.1 (registry+https://github.com/rust-lang/crates.io-index)" = "e3b5ca7a04898ad4bcd41c90c5285445ff5b791899bb1b0abdd2a2aa791211d7" -"checksum byteorder 1.3.4 (registry+https://github.com/rust-lang/crates.io-index)" = "08c48aae112d48ed9f069b33538ea9e3e90aa263cfa3d1c24309612b1f7472de" -"checksum bytes 0.4.12 (registry+https://github.com/rust-lang/crates.io-index)" = "206fdffcfa2df7cbe15601ef46c813fce0965eb3286db6b56c583b814b51c81c" -"checksum bytes 0.5.6 (registry+https://github.com/rust-lang/crates.io-index)" = "0e4cec68f03f32e44924783795810fa50a7035d8c8ebe78580ad7e6c703fba38" -"checksum bzip2 0.3.3 (registry+https://github.com/rust-lang/crates.io-index)" = "42b7c3cbf0fa9c1b82308d57191728ca0256cb821220f4e2fd410a72ade26e3b" -"checksum bzip2-sys 0.1.9+1.0.8 (registry+https://github.com/rust-lang/crates.io-index)" = "ad3b39a260062fca31f7b0b12f207e8f2590a67d32ec7d59c20484b07ea7285e" -"checksum c_linked_list 1.1.1 (registry+https://github.com/rust-lang/crates.io-index)" = "4964518bd3b4a8190e832886cdc0da9794f12e8e6c1613a9e90ff331c4c8724b" -"checksum cast 0.2.3 (registry+https://github.com/rust-lang/crates.io-index)" = "4b9434b9a5aa1450faa3f9cb14ea0e8c53bb5d2b3c1bfd1ab4fc03e9f33fbfb0" -"checksum cc 1.0.41 (registry+https://github.com/rust-lang/crates.io-index)" = "8dae9c4b8fedcae85592ba623c4fd08cfdab3e3b72d6df780c6ead964a69bfff" -"checksum cfg-if 0.1.10 (registry+https://github.com/rust-lang/crates.io-index)" = "4785bdd1c96b2a846b2bd7cc02e86b6b3dbf14e7e53446c4f54c92a361040822" -"checksum chacha20 0.4.3 (registry+https://github.com/rust-lang/crates.io-index)" = "086c0f07ac275808b7bf9a39f2fd013aae1498be83632814c8c4e0bd53f2dc58" -"checksum chacha20poly1305 0.5.1 (registry+https://github.com/rust-lang/crates.io-index)" = "18b0c90556d8e3fec7cf18d84a2f53d27b21288f2fe481b830fadcf809e48205" -"checksum chrono 0.4.18 (registry+https://github.com/rust-lang/crates.io-index)" = "d021fddb7bd3e734370acfa4a83f34095571d8570c039f1420d77540f68d5772" -"checksum clap 2.33.3 (registry+https://github.com/rust-lang/crates.io-index)" = "37e58ac78573c40708d45522f0d80fa2f01cc4f9b4e2bf749807255454312002" -"checksum cloudabi 0.0.3 (registry+https://github.com/rust-lang/crates.io-index)" = "ddfc5b9aa5d4507acaf872de71051dfd0e309860e88966e1051e462a077aac4f" -"checksum cloudabi 0.1.0 (registry+https://github.com/rust-lang/crates.io-index)" = "4344512281c643ae7638bbabc3af17a11307803ec8f0fcad9fae512a8bf36467" -"checksum cmake 0.1.44 (registry+https://github.com/rust-lang/crates.io-index)" = "0e56268c17a6248366d66d4a47a3381369d068cce8409bb1716ed77ea32163bb" -"checksum colored 1.9.3 (registry+https://github.com/rust-lang/crates.io-index)" = "f4ffc801dacf156c5854b9df4f425a626539c3a6ef7893cc0c5084a23f0b6c59" -"checksum console_error_panic_hook 0.1.6 (registry+https://github.com/rust-lang/crates.io-index)" = "b8d976903543e0c48546a91908f21588a680a8c8f984df9a5d69feccb2b2a211" -"checksum const-random 0.1.8 (registry+https://github.com/rust-lang/crates.io-index)" = "2f1af9ac737b2dd2d577701e59fd09ba34822f6f2ebdb30a7647405d9e55e16a" -"checksum const-random-macro 0.1.8 (registry+https://github.com/rust-lang/crates.io-index)" = "25e4c606eb459dd29f7c57b2e0879f2b6f14ee130918c2b78ccb58a9624e6c7a" -"checksum const_fn 0.4.2 (registry+https://github.com/rust-lang/crates.io-index)" = "ce90df4c658c62f12d78f7508cf92f9173e5184a539c10bfe54a3107b3ffd0f2" -"checksum constant_time_eq 0.1.5 (registry+https://github.com/rust-lang/crates.io-index)" = "245097e9a4535ee1e3e3931fcfcd55a796a44c643e8596ff6566d68f09b87bbc" -"checksum core-foundation 0.7.0 (registry+https://github.com/rust-lang/crates.io-index)" = "57d24c7a13c43e870e37c1556b74555437870a04514f7685f5b354e090567171" -"checksum core-foundation-sys 0.7.0 (registry+https://github.com/rust-lang/crates.io-index)" = "b3a71ab494c0b5b860bdc8407ae08978052417070c2ced38573a9157ad75b8ac" -"checksum cpuid-bool 0.1.2 (registry+https://github.com/rust-lang/crates.io-index)" = "8aebca1129a03dc6dc2b127edd729435bbc4a37e1d5f4d7513165089ceb02634" -"checksum crc32fast 1.2.0 (registry+https://github.com/rust-lang/crates.io-index)" = "ba125de2af0df55319f41944744ad91c71113bf74a4646efff39afe1f6842db1" -"checksum criterion 0.3.3 (registry+https://github.com/rust-lang/crates.io-index)" = "70daa7ceec6cf143990669a04c7df13391d55fb27bd4079d252fca774ba244d8" -"checksum criterion-plot 0.4.3 (registry+https://github.com/rust-lang/crates.io-index)" = "e022feadec601fba1649cfa83586381a4ad31c6bf3a9ab7d408118b05dd9889d" -"checksum crossbeam 0.7.3 (registry+https://github.com/rust-lang/crates.io-index)" = "69323bff1fb41c635347b8ead484a5ca6c3f11914d784170b158d8449ab07f8e" -"checksum crossbeam-channel 0.4.4 (registry+https://github.com/rust-lang/crates.io-index)" = "b153fe7cbef478c567df0f972e02e6d736db11affe43dfc9c56a9374d1adfb87" -"checksum crossbeam-deque 0.7.3 (registry+https://github.com/rust-lang/crates.io-index)" = "9f02af974daeee82218205558e51ec8768b48cf524bd01d550abe5573a608285" -"checksum crossbeam-epoch 0.8.2 (registry+https://github.com/rust-lang/crates.io-index)" = "058ed274caafc1f60c4997b5fc07bf7dc7cca454af7c6e81edffe5f33f70dace" -"checksum crossbeam-queue 0.2.3 (registry+https://github.com/rust-lang/crates.io-index)" = "774ba60a54c213d409d5353bda12d49cd68d14e45036a285234c8d6f91f92570" -"checksum crossbeam-utils 0.7.2 (registry+https://github.com/rust-lang/crates.io-index)" = "c3c7c73a2d1e9fc0886a08b93e98eb643461230d5f1925e4036204d5f2e261a8" -"checksum crunchy 0.2.2 (registry+https://github.com/rust-lang/crates.io-index)" = "7a81dae078cea95a014a339291cec439d2f232ebe854a9d672b796c6afafa9b7" -"checksum crypto-mac 0.7.0 (registry+https://github.com/rust-lang/crates.io-index)" = "4434400df11d95d556bac068ddfedd482915eb18fe8bea89bc80b6e4b1c179e5" -"checksum crypto-mac 0.8.0 (registry+https://github.com/rust-lang/crates.io-index)" = "b584a330336237c1eecd3e94266efb216c56ed91225d634cb2991c5f3fd1aeab" -"checksum csv 1.1.3 (registry+https://github.com/rust-lang/crates.io-index)" = "00affe7f6ab566df61b4be3ce8cf16bc2576bca0963ceb0955e45d514bf9a279" -"checksum csv-core 0.1.10 (registry+https://github.com/rust-lang/crates.io-index)" = "2b2466559f260f48ad25fe6317b3c8dac77b5bdb5763ac7d9d6103530663bc90" -"checksum ctr 0.4.0 (registry+https://github.com/rust-lang/crates.io-index)" = "a3592740fd55aaf61dd72df96756bd0d11e6037b89dcf30ae2e1895b267692be" -"checksum ctrlc 3.1.6 (registry+https://github.com/rust-lang/crates.io-index)" = "d0b676fa23f995faf587496dcd1c80fead847ed58d2da52ac1caca9a72790dd2" -"checksum curve25519-dalek 2.1.0 (registry+https://github.com/rust-lang/crates.io-index)" = "5d85653f070353a16313d0046f173f70d1aadd5b42600a14de626f0dfb3473a5" -"checksum curve25519-dalek 3.0.0 (registry+https://github.com/rust-lang/crates.io-index)" = "c8492de420e9e60bc9a1d66e2dbb91825390b738a388606600663fc529b4b307" -"checksum darwin-libproc 0.1.2 (registry+https://github.com/rust-lang/crates.io-index)" = "9fb90051930c9a0f09e585762152048e23ac74d20c10590ef7cf01c0343c3046" -"checksum darwin-libproc-sys 0.1.2 (registry+https://github.com/rust-lang/crates.io-index)" = "57cebb5bde66eecdd30ddc4b9cd208238b15db4982ccc72db59d699ea10867c1" -"checksum data-encoding 2.3.0 (registry+https://github.com/rust-lang/crates.io-index)" = "d4d0e2d24e5ee3b23a01de38eefdcd978907890701f08ffffd4cb457ca4ee8d6" -"checksum db-key 0.0.5 (registry+https://github.com/rust-lang/crates.io-index)" = "b72465f46d518f6015d9cf07f7f3013a95dd6b9c2747c3d65ae0cce43929d14f" -"checksum derivative 2.1.1 (registry+https://github.com/rust-lang/crates.io-index)" = "cb582b60359da160a9477ee80f15c8d784c477e69c217ef2cdd4169c24ea380f" -"checksum derive_arbitrary 0.4.6 (registry+https://github.com/rust-lang/crates.io-index)" = "d0f7c6c81276b6b8702074defbdb1938933ddf98c7f7e0dca8d9e9214dd6c730" -"checksum derive_more 0.99.10 (registry+https://github.com/rust-lang/crates.io-index)" = "1dcfabdab475c16a93d669dddfc393027803e347d09663f524447f642fbb84ba" -"checksum digest 0.8.1 (registry+https://github.com/rust-lang/crates.io-index)" = "f3d0c8c8752312f9713efd397ff63acb9f85585afbf179282e720e7704954dd5" -"checksum digest 0.9.0 (registry+https://github.com/rust-lang/crates.io-index)" = "d3dd60d1080a57a05ab032377049e0591415d2b31afd7028356dbf3cc6dcb066" -"checksum dirs 2.0.2 (registry+https://github.com/rust-lang/crates.io-index)" = "13aea89a5c93364a98e9b37b2fa237effbb694d5cfe01c5b70941f7eb087d5e3" -"checksum dirs-sys 0.3.5 (registry+https://github.com/rust-lang/crates.io-index)" = "8e93d7f5705de3e49895a2b5e0b8855a1c27f080192ae9c32a6432d50741a57a" -"checksum discard 1.0.4 (registry+https://github.com/rust-lang/crates.io-index)" = "212d0f5754cb6769937f4501cc0e67f4f4483c8d2c3e1e922ee9edbe4ab4c7c0" -"checksum discv5 0.1.0-alpha.11 (registry+https://github.com/rust-lang/crates.io-index)" = "c68cb1b942aadd3bb3a13620c4d831c0aa49eda988cf8bcccfdfdc7ef69504a7" -"checksum dtoa 0.4.6 (registry+https://github.com/rust-lang/crates.io-index)" = "134951f4028bdadb9b84baf4232681efbf277da25144b9b0ad65df75946c422b" -"checksum ed25519 1.0.2 (registry+https://github.com/rust-lang/crates.io-index)" = "07dfc993ea376e864fe29a4099a61ca0bb994c6d7745a61bf60ddb3d64e05237" -"checksum ed25519-dalek 1.0.1 (registry+https://github.com/rust-lang/crates.io-index)" = "c762bae6dcaf24c4c84667b8579785430908723d5c889f469d76a41d59cc7a9d" -"checksum either 1.6.1 (registry+https://github.com/rust-lang/crates.io-index)" = "e78d4f1cc4ae33bbfc157ed5d5a5ef3bc29227303d595861deb238fcec4e9457" -"checksum encoding_rs 0.8.24 (registry+https://github.com/rust-lang/crates.io-index)" = "a51b8cf747471cb9499b6d59e59b0444f4c90eba8968c4e44874e92b5b64ace2" -"checksum enr 0.1.3 (registry+https://github.com/rust-lang/crates.io-index)" = "a3137b4854534673ea350751670c6fe53920394a328ba9ce4d9acabd4f60a586" -"checksum env_logger 0.7.1 (registry+https://github.com/rust-lang/crates.io-index)" = "44533bbbb3bb3c1fa17d9f2e4e38bbbaf8396ba82193c4cb1b6445d711445d36" -"checksum error-chain 0.12.4 (registry+https://github.com/rust-lang/crates.io-index)" = "2d2f06b9cac1506ece98fe3231e3cc9c4410ec3d5b1f24ae1c8946f0742cdefc" -"checksum ethabi 12.0.0 (registry+https://github.com/rust-lang/crates.io-index)" = "052a565e3de82944527d6d10a465697e6bb92476b772ca7141080c901f6a63c6" -"checksum ethbloom 0.9.2 (registry+https://github.com/rust-lang/crates.io-index)" = "71a6567e6fd35589fea0c63b94b4cf2e55573e413901bdbe60ab15cf0e25e5df" -"checksum ethereum-types 0.9.2 (registry+https://github.com/rust-lang/crates.io-index)" = "473aecff686bd8e7b9db0165cbbb53562376b39bf35b427f0c60446a9e1634b0" -"checksum exit-future 0.2.0 (registry+https://github.com/rust-lang/crates.io-index)" = "e43f2f1833d64e33f15592464d6fdd70f349dda7b1a53088eb83cd94014008c5" -"checksum failure 0.1.8 (registry+https://github.com/rust-lang/crates.io-index)" = "d32e9bd16cc02eae7db7ef620b392808b89f6a5e16bb3497d159c6b92a0f4f86" -"checksum failure_derive 0.1.8 (registry+https://github.com/rust-lang/crates.io-index)" = "aa4da3c766cd7a0db8242e326e9e4e081edd567072893ed320008189715366a4" -"checksum fake-simd 0.1.2 (registry+https://github.com/rust-lang/crates.io-index)" = "e88a8acf291dafb59c2d96e8f59828f3838bb1a70398823ade51a84de6a6deed" -"checksum fallible-iterator 0.2.0 (registry+https://github.com/rust-lang/crates.io-index)" = "4443176a9f2c162692bd3d352d745ef9413eec5782a80d8fd6f8a1ac692a07f7" -"checksum fallible-streaming-iterator 0.1.9 (registry+https://github.com/rust-lang/crates.io-index)" = "7360491ce676a36bf9bb3c56c1aa791658183a54d2744120f27285738d90465a" -"checksum fixed-hash 0.6.1 (registry+https://github.com/rust-lang/crates.io-index)" = "11498d382790b7a8f2fd211780bec78619bba81cdad3a283997c0c41f836759c" -"checksum fixedbitset 0.2.0 (registry+https://github.com/rust-lang/crates.io-index)" = "37ab347416e802de484e4d03c7316c48f1ecb56574dfd4a46a80f173ce1de04d" -"checksum flate2 1.0.17 (registry+https://github.com/rust-lang/crates.io-index)" = "766d0e77a2c1502169d4a93ff3b8c15a71fd946cd0126309752104e5f3c46d94" -"checksum fnv 1.0.7 (registry+https://github.com/rust-lang/crates.io-index)" = "3f9eec918d3f24069decb9af1554cad7c880e2da24a9afd88aca000531ab82c1" -"checksum foreign-types 0.3.2 (registry+https://github.com/rust-lang/crates.io-index)" = "f6f339eb8adc052cd2ca78910fda869aefa38d22d5cb648e6485e4d3fc06f3b1" -"checksum foreign-types-shared 0.1.1 (registry+https://github.com/rust-lang/crates.io-index)" = "00b0228411908ca8685dba7fc2cdd70ec9990a6e753e89b6ac91a84c40fbaf4b" -"checksum fuchsia-cprng 0.1.1 (registry+https://github.com/rust-lang/crates.io-index)" = "a06f77d526c1a601b7c4cdd98f54b5eaabffc14d5f2f0296febdc7f357c6d3ba" -"checksum fuchsia-zircon 0.3.3 (registry+https://github.com/rust-lang/crates.io-index)" = "2e9763c69ebaae630ba35f74888db465e49e259ba1bc0eda7d06f4a067615d82" -"checksum fuchsia-zircon-sys 0.3.3 (registry+https://github.com/rust-lang/crates.io-index)" = "3dcaa9ae7725d12cdb85b3ad99a434db70b468c09ded17e012d86b5c1010f7a7" -"checksum futures 0.1.29 (registry+https://github.com/rust-lang/crates.io-index)" = "1b980f2816d6ee8673b6517b52cb0e808a180efc92e5c19d02cdda79066703ef" -"checksum futures 0.3.5 (registry+https://github.com/rust-lang/crates.io-index)" = "1e05b85ec287aac0dc34db7d4a569323df697f9c55b99b15d6b4ef8cde49f613" -"checksum futures-channel 0.3.5 (registry+https://github.com/rust-lang/crates.io-index)" = "f366ad74c28cca6ba456d95e6422883cfb4b252a83bed929c83abfdbbf2967d5" -"checksum futures-core 0.3.5 (registry+https://github.com/rust-lang/crates.io-index)" = "59f5fff90fd5d971f936ad674802482ba441b6f09ba5e15fd8b39145582ca399" -"checksum futures-cpupool 0.1.8 (registry+https://github.com/rust-lang/crates.io-index)" = "ab90cde24b3319636588d0c35fe03b1333857621051837ed769faefb4c2162e4" -"checksum futures-executor 0.3.5 (registry+https://github.com/rust-lang/crates.io-index)" = "10d6bb888be1153d3abeb9006b11b02cf5e9b209fda28693c31ae1e4e012e314" -"checksum futures-io 0.3.5 (registry+https://github.com/rust-lang/crates.io-index)" = "de27142b013a8e869c14957e6d2edeef89e97c289e69d042ee3a49acd8b51789" -"checksum futures-macro 0.3.5 (registry+https://github.com/rust-lang/crates.io-index)" = "d0b5a30a4328ab5473878237c447333c093297bded83a4983d10f4deea240d39" -"checksum futures-sink 0.3.5 (registry+https://github.com/rust-lang/crates.io-index)" = "3f2032893cb734c7a05d85ce0cc8b8c4075278e93b24b66f9de99d6eb0fa8acc" -"checksum futures-task 0.3.5 (registry+https://github.com/rust-lang/crates.io-index)" = "bdb66b5f09e22019b1ab0830f7785bcea8e7a42148683f99214f73f8ec21a626" -"checksum futures-timer 3.0.2 (registry+https://github.com/rust-lang/crates.io-index)" = "e64b03909df88034c26dc1547e8970b91f98bdb65165d6a4e9110d94263dbb2c" -"checksum futures-util 0.3.5 (registry+https://github.com/rust-lang/crates.io-index)" = "8764574ff08b701a084482c3c7031349104b07ac897393010494beaa18ce32c6" -"checksum futures_codec 0.4.1 (registry+https://github.com/rust-lang/crates.io-index)" = "ce54d63f8b0c75023ed920d46fd71d0cbbb830b0ee012726b5b4f506fb6dea5b" -"checksum gcc 0.3.55 (registry+https://github.com/rust-lang/crates.io-index)" = "8f5f3913fa0bfe7ee1fd8248b6b9f42a5af4b9d65ec2dd2c3c26132b950ecfc2" -"checksum generic-array 0.12.3 (registry+https://github.com/rust-lang/crates.io-index)" = "c68f0274ae0e023facc3c97b2e00f076be70e254bc851d972503b328db79b2ec" -"checksum generic-array 0.14.4 (registry+https://github.com/rust-lang/crates.io-index)" = "501466ecc8a30d1d3b7fc9229b122b2ce8ed6e9d9223f1138d4babb253e51817" -"checksum get_if_addrs 0.5.3 (registry+https://github.com/rust-lang/crates.io-index)" = "abddb55a898d32925f3148bd281174a68eeb68bbfd9a5938a57b18f506ee4ef7" -"checksum get_if_addrs-sys 0.1.1 (registry+https://github.com/rust-lang/crates.io-index)" = "0d04f9fb746cf36b191c00f3ede8bde9c8e64f9f4b05ae2694a9ccf5e3f5ab48" -"checksum getrandom 0.1.15 (registry+https://github.com/rust-lang/crates.io-index)" = "fc587bc0ec293155d5bfa6b9891ec18a1e330c234f896ea47fbada4cadbe47e6" -"checksum ghash 0.3.0 (registry+https://github.com/rust-lang/crates.io-index)" = "d6e27f0689a6e15944bdce7e45425efb87eaa8ab0c6e87f11d0987a9133e2531" -"checksum gimli 0.22.0 (registry+https://github.com/rust-lang/crates.io-index)" = "aaf91faf136cb47367fa430cd46e37a788775e7fa104f8b4bcb3861dc389b724" -"checksum git-version 0.3.4 (registry+https://github.com/rust-lang/crates.io-index)" = "94918e83f1e01dedc2e361d00ce9487b14c58c7f40bab148026fa39d42cb41e2" -"checksum git-version-macro 0.3.4 (registry+https://github.com/rust-lang/crates.io-index)" = "34a97a52fdee1870a34fa6e4b77570cba531b27d1838874fef4429a791a3d657" -"checksum glob 0.3.0 (registry+https://github.com/rust-lang/crates.io-index)" = "9b919933a397b79c37e33b77bb2aa3dc8eb6e165ad809e58ff75bc7db2e34574" -"checksum h2 0.1.26 (registry+https://github.com/rust-lang/crates.io-index)" = "a5b34c246847f938a410a03c5458c7fee2274436675e76d8b903c08efc29c462" -"checksum h2 0.2.6 (registry+https://github.com/rust-lang/crates.io-index)" = "993f9e0baeed60001cf565546b0d3dbe6a6ad23f2bd31644a133c641eccf6d53" -"checksum half 1.6.0 (registry+https://github.com/rust-lang/crates.io-index)" = "d36fab90f82edc3c747f9d438e06cf0a491055896f2a279638bb5beed6c40177" -"checksum hashbrown 0.6.3 (registry+https://github.com/rust-lang/crates.io-index)" = "8e6073d0ca812575946eb5f35ff68dbe519907b25c42530389ff946dc84c6ead" -"checksum hashbrown 0.9.0 (registry+https://github.com/rust-lang/crates.io-index)" = "00d63df3d41950fb462ed38308eea019113ad1508da725bbedcd0fa5a85ef5f7" -"checksum heck 0.3.1 (registry+https://github.com/rust-lang/crates.io-index)" = "20564e78d53d2bb135c343b3f47714a56af2061f1c928fdb541dc7b9fdd94205" -"checksum hermit-abi 0.1.16 (registry+https://github.com/rust-lang/crates.io-index)" = "4c30f6d0bc6b00693347368a67d41b58f2fb851215ff1da49e90fe2c5c667151" -"checksum hex 0.3.2 (registry+https://github.com/rust-lang/crates.io-index)" = "805026a5d0141ffc30abb3be3173848ad46a1b1664fe632428479619a3644d77" -"checksum hex 0.4.2 (registry+https://github.com/rust-lang/crates.io-index)" = "644f9158b2f133fd50f5fb3242878846d9eb792e445c893805ff0e3824006e35" -"checksum hex_fmt 0.3.0 (registry+https://github.com/rust-lang/crates.io-index)" = "b07f60793ff0a4d9cef0f18e63b5357e06209987153a64648c972c1e5aff336f" -"checksum hkdf 0.8.0 (registry+https://github.com/rust-lang/crates.io-index)" = "3fa08a006102488bd9cd5b8013aabe84955cf5ae22e304c2caf655b633aefae3" -"checksum hmac 0.7.1 (registry+https://github.com/rust-lang/crates.io-index)" = "5dcb5e64cda4c23119ab41ba960d1e170a774c8e4b9d9e6a9bc18aabf5e59695" -"checksum hmac 0.8.1 (registry+https://github.com/rust-lang/crates.io-index)" = "126888268dcc288495a26bf004b38c5fdbb31682f992c84ceb046a1f0fe38840" -"checksum hmac-drbg 0.2.0 (registry+https://github.com/rust-lang/crates.io-index)" = "c6e570451493f10f6581b48cdd530413b63ea9e780f544bfd3bdcaa0d89d1a7b" -"checksum http 0.1.21 (registry+https://github.com/rust-lang/crates.io-index)" = "d6ccf5ede3a895d8856620237b2f02972c1bbc78d2965ad7fe8838d4a0ed41f0" -"checksum http 0.2.1 (registry+https://github.com/rust-lang/crates.io-index)" = "28d569972648b2c512421b5f2a405ad6ac9666547189d0c5477a3f200f3e02f9" -"checksum http-body 0.1.0 (registry+https://github.com/rust-lang/crates.io-index)" = "6741c859c1b2463a423a1dbce98d418e6c3c3fc720fb0d45528657320920292d" -"checksum http-body 0.3.1 (registry+https://github.com/rust-lang/crates.io-index)" = "13d5ff830006f7646652e057693569bfe0d51760c0085a071769d142a205111b" -"checksum httparse 1.3.4 (registry+https://github.com/rust-lang/crates.io-index)" = "cd179ae861f0c2e53da70d892f5f3029f9594be0c41dc5269cd371691b1dc2f9" -"checksum httpdate 0.3.2 (registry+https://github.com/rust-lang/crates.io-index)" = "494b4d60369511e7dea41cf646832512a94e542f68bb9c49e54518e0f468eb47" -"checksum humantime 1.3.0 (registry+https://github.com/rust-lang/crates.io-index)" = "df004cfca50ef23c36850aaaa59ad52cc70d0e90243c3c7737a4dd32dc7a3c4f" -"checksum hyper 0.10.16 (registry+https://github.com/rust-lang/crates.io-index)" = "0a0652d9a2609a968c14be1a9ea00bf4b1d64e2e1f53a1b51b6fff3a6e829273" -"checksum hyper 0.12.35 (registry+https://github.com/rust-lang/crates.io-index)" = "9dbe6ed1438e1f8ad955a4701e9a944938e9519f6888d12d8558b645e247d5f6" -"checksum hyper 0.13.8 (registry+https://github.com/rust-lang/crates.io-index)" = "2f3afcfae8af5ad0576a31e768415edb627824129e8e5a29b8bfccb2f234e835" -"checksum hyper-tls 0.3.2 (registry+https://github.com/rust-lang/crates.io-index)" = "3a800d6aa50af4b5850b2b0f659625ce9504df908e9733b635720483be26174f" -"checksum hyper-tls 0.4.3 (registry+https://github.com/rust-lang/crates.io-index)" = "d979acc56dcb5b8dddba3917601745e877576475aa046df3226eabdecef78eed" -"checksum idna 0.1.5 (registry+https://github.com/rust-lang/crates.io-index)" = "38f09e0f0b1fb55fdee1f17470ad800da77af5186a1a76c026b679358b7e844e" -"checksum idna 0.2.0 (registry+https://github.com/rust-lang/crates.io-index)" = "02e2673c30ee86b5b96a9cb52ad15718aa1f966f5ab9ad54a8b95d5ca33120a9" -"checksum impl-codec 0.4.2 (registry+https://github.com/rust-lang/crates.io-index)" = "1be51a921b067b0eaca2fad532d9400041561aa922221cc65f95a85641c6bf53" -"checksum impl-rlp 0.2.1 (registry+https://github.com/rust-lang/crates.io-index)" = "8f7a72f11830b52333f36e3b09a288333888bf54380fd0ac0790a3c31ab0f3c5" -"checksum impl-serde 0.3.1 (registry+https://github.com/rust-lang/crates.io-index)" = "b47ca4d2b6931707a55fce5cf66aff80e2178c8b63bbb4ecb5695cbc870ddf6f" -"checksum indexmap 1.6.0 (registry+https://github.com/rust-lang/crates.io-index)" = "55e2e4c765aa53a0424761bf9f41aa7a6ac1efa87238f59560640e27fca028f2" -"checksum instant 0.1.7 (registry+https://github.com/rust-lang/crates.io-index)" = "63312a18f7ea8760cdd0a7c5aac1a619752a246b833545e3e36d1f81f7cd9e66" -"checksum integer-sqrt 0.1.5 (registry+https://github.com/rust-lang/crates.io-index)" = "276ec31bcb4a9ee45f58bec6f9ec700ae4cf4f4f8f2fa7e06cb406bd5ffdd770" -"checksum iovec 0.1.4 (registry+https://github.com/rust-lang/crates.io-index)" = "b2b3ea6ff95e175473f8ffe6a7eb7c00d054240321b84c57051175fe3c1e075e" -"checksum ipnet 2.3.0 (registry+https://github.com/rust-lang/crates.io-index)" = "47be2f14c678be2fdcab04ab1171db51b2762ce6f0a8ee87c8dd4a04ed216135" -"checksum itertools 0.8.2 (registry+https://github.com/rust-lang/crates.io-index)" = "f56a2d0bc861f9165be4eb3442afd3c236d8a98afd426f65d92324ae1091a484" -"checksum itertools 0.9.0 (registry+https://github.com/rust-lang/crates.io-index)" = "284f18f85651fe11e8a991b2adb42cb078325c996ed026d994719efcfca1d54b" -"checksum itoa 0.4.6 (registry+https://github.com/rust-lang/crates.io-index)" = "dc6f3ad7b9d11a0c00842ff8de1b60ee58661048eb8049ed33c73594f359d7e6" -"checksum js-sys 0.3.45 (registry+https://github.com/rust-lang/crates.io-index)" = "ca059e81d9486668f12d455a4ea6daa600bd408134cd17e3d3fb5a32d1f016f8" -"checksum jsonrpc-core 14.2.0 (registry+https://github.com/rust-lang/crates.io-index)" = "a0747307121ffb9703afd93afbd0fb4f854c38fb873f2c8b90e0e902f27c7b62" -"checksum keccak 0.1.0 (registry+https://github.com/rust-lang/crates.io-index)" = "67c21572b4949434e4fc1e1978b99c5f77064153c59d998bf13ecd96fb5ecba7" -"checksum kernel32-sys 0.2.2 (registry+https://github.com/rust-lang/crates.io-index)" = "7507624b29483431c0ba2d82aece8ca6cdba9382bff4ddd0f7490560c056098d" -"checksum language-tags 0.2.2 (registry+https://github.com/rust-lang/crates.io-index)" = "a91d884b6667cd606bb5a69aa0c99ba811a115fc68915e7056ec08a46e93199a" -"checksum lazy_static 1.4.0 (registry+https://github.com/rust-lang/crates.io-index)" = "e2abad23fbc42b3700f2f279844dc832adb2b2eb069b2df918f455c4e18cc646" -"checksum lazycell 1.3.0 (registry+https://github.com/rust-lang/crates.io-index)" = "830d08ce1d1d941e6b30645f1a0eb5643013d835ce3779a5fc208261dbe10f55" -"checksum leveldb 0.8.6 (registry+https://github.com/rust-lang/crates.io-index)" = "32651baaaa5596b3a6e0bee625e73fd0334c167db0ea5ac68750ef9a629a2d6a" -"checksum leveldb-sys 2.0.7 (registry+https://github.com/rust-lang/crates.io-index)" = "76c44b9b785ca705d58190ebd432a4e7edb900eadf236ff966d7d1307e482e87" -"checksum libc 0.2.77 (registry+https://github.com/rust-lang/crates.io-index)" = "f2f96b10ec2560088a8e76961b00d47107b3a625fecb76dedb29ee7ccbf98235" -"checksum libflate 1.0.2 (registry+https://github.com/rust-lang/crates.io-index)" = "e9bac9023e1db29c084f9f8cd9d3852e5e8fddf98fb47c4964a0ea4663d95949" -"checksum libflate_lz77 1.0.0 (registry+https://github.com/rust-lang/crates.io-index)" = "3286f09f7d4926fc486334f28d8d2e6ebe4f7f9994494b6dab27ddfad2c9b11b" -"checksum libm 0.2.1 (registry+https://github.com/rust-lang/crates.io-index)" = "c7d73b3f436185384286bd8098d17ec07c9a7d2388a6599f824d8502b529702a" -"checksum libp2p 0.25.0 (git+https://github.com/sigp/rust-libp2p?rev=03f998022ce2f566a6c6e6c4206bc0ce4d45109f)" = "" -"checksum libp2p-core 0.21.0 (git+https://github.com/sigp/rust-libp2p?rev=03f998022ce2f566a6c6e6c4206bc0ce4d45109f)" = "" -"checksum libp2p-core 0.22.1 (registry+https://github.com/rust-lang/crates.io-index)" = "52f13ba8c7df0768af2eb391696d562c7de88cc3a35122531aaa6a7d77754d25" -"checksum libp2p-core-derive 0.20.2 (git+https://github.com/sigp/rust-libp2p?rev=03f998022ce2f566a6c6e6c4206bc0ce4d45109f)" = "" -"checksum libp2p-dns 0.21.0 (git+https://github.com/sigp/rust-libp2p?rev=03f998022ce2f566a6c6e6c4206bc0ce4d45109f)" = "" -"checksum libp2p-gossipsub 0.22.0 (git+https://github.com/sigp/rust-libp2p?rev=03f998022ce2f566a6c6e6c4206bc0ce4d45109f)" = "" -"checksum libp2p-identify 0.22.0 (git+https://github.com/sigp/rust-libp2p?rev=03f998022ce2f566a6c6e6c4206bc0ce4d45109f)" = "" -"checksum libp2p-mplex 0.21.0 (git+https://github.com/sigp/rust-libp2p?rev=03f998022ce2f566a6c6e6c4206bc0ce4d45109f)" = "" -"checksum libp2p-noise 0.23.0 (git+https://github.com/sigp/rust-libp2p?rev=03f998022ce2f566a6c6e6c4206bc0ce4d45109f)" = "" -"checksum libp2p-swarm 0.22.0 (git+https://github.com/sigp/rust-libp2p?rev=03f998022ce2f566a6c6e6c4206bc0ce4d45109f)" = "" -"checksum libp2p-tcp 0.21.0 (git+https://github.com/sigp/rust-libp2p?rev=03f998022ce2f566a6c6e6c4206bc0ce4d45109f)" = "" -"checksum libp2p-websocket 0.22.0 (git+https://github.com/sigp/rust-libp2p?rev=03f998022ce2f566a6c6e6c4206bc0ce4d45109f)" = "" -"checksum libsecp256k1 0.3.5 (registry+https://github.com/rust-lang/crates.io-index)" = "1fc1e2c808481a63dc6da2074752fdd4336a3c8fcc68b83db6f1fd5224ae7962" -"checksum libsqlite3-sys 0.18.0 (registry+https://github.com/rust-lang/crates.io-index)" = "1e704a02bcaecd4a08b93a23f6be59d0bd79cd161e0963e9499165a0a35df7bd" -"checksum libz-sys 1.1.2 (registry+https://github.com/rust-lang/crates.io-index)" = "602113192b08db8f38796c4e85c39e960c145965140e918018bcde1952429655" -"checksum linked-hash-map 0.5.3 (registry+https://github.com/rust-lang/crates.io-index)" = "8dd5a6d5999d9907cda8ed67bbd137d3af8085216c2ac62de5be860bd41f304a" -"checksum lock_api 0.3.4 (registry+https://github.com/rust-lang/crates.io-index)" = "c4da24a77a3d8a6d4862d95f72e6fdb9c09a643ecdb402d754004a557f2bec75" -"checksum lock_api 0.4.1 (registry+https://github.com/rust-lang/crates.io-index)" = "28247cc5a5be2f05fbcd76dd0cf2c7d3b5400cb978a28042abcd4fa0b3f8261c" -"checksum log 0.3.9 (registry+https://github.com/rust-lang/crates.io-index)" = "e19e8d5c34a3e0e2223db8e060f9e8264aeeb5c5fc64a4ee9965c062211c024b" -"checksum log 0.4.11 (registry+https://github.com/rust-lang/crates.io-index)" = "4fabed175da42fed1fa0746b0ea71f412aa9d35e76e95e59b192c64b9dc2bf8b" -"checksum lru 0.5.3 (registry+https://github.com/rust-lang/crates.io-index)" = "35c456c123957de3a220cd03786e0d86aa542a88b46029973b542f426da6ef34" -"checksum lru-cache 0.1.2 (registry+https://github.com/rust-lang/crates.io-index)" = "31e24f1ad8321ca0e8a1e0ac13f23cb668e6f5466c2c57319f6a5cf1cc8e3b1c" -"checksum lru_time_cache 0.10.0 (registry+https://github.com/rust-lang/crates.io-index)" = "adb241df5c4caeb888755363fc95f8a896618dc0d435e9e775f7930cb099beab" -"checksum mach 0.3.2 (registry+https://github.com/rust-lang/crates.io-index)" = "b823e83b2affd8f40a9ee8c29dbc56404c1e34cd2710921f2801e2cf29527afa" -"checksum maplit 1.0.2 (registry+https://github.com/rust-lang/crates.io-index)" = "3e2e65a1a2e43cfcb47a895c4c8b10d1f4a61097f9f254f183aee60cad9c651d" -"checksum matches 0.1.8 (registry+https://github.com/rust-lang/crates.io-index)" = "7ffc5c5338469d4d3ea17d269fa8ea3512ad247247c30bd2df69e68309ed0a08" -"checksum maybe-uninit 2.0.0 (registry+https://github.com/rust-lang/crates.io-index)" = "60302e4db3a61da70c0cb7991976248362f30319e88850c487b9b95bbf059e00" -"checksum memchr 2.3.3 (registry+https://github.com/rust-lang/crates.io-index)" = "3728d817d99e5ac407411fa471ff9800a778d88a24685968b36824eaf4bee400" -"checksum memoffset 0.5.6 (registry+https://github.com/rust-lang/crates.io-index)" = "043175f069eda7b85febe4a74abbaeff828d9f8b448515d3151a14a3542811aa" -"checksum milagro_bls 1.1.0 (git+https://github.com/sigp/milagro_bls?branch=paulh)" = "" -"checksum mime 0.2.6 (registry+https://github.com/rust-lang/crates.io-index)" = "ba626b8a6de5da682e1caa06bdb42a335aee5a84db8e5046a3e8ab17ba0a3ae0" -"checksum mime 0.3.16 (registry+https://github.com/rust-lang/crates.io-index)" = "2a60c7ce501c71e03a9c9c0d35b861413ae925bd979cc7a4e30d060069aaac8d" -"checksum mime_guess 2.0.3 (registry+https://github.com/rust-lang/crates.io-index)" = "2684d4c2e97d99848d30b324b00c8fcc7e5c897b7cbb5819b09e7c90e8baf212" -"checksum miniz_oxide 0.4.2 (registry+https://github.com/rust-lang/crates.io-index)" = "c60c0dfe32c10b43a144bad8fc83538c52f58302c92300ea7ec7bf7b38d5a7b9" -"checksum mio 0.6.22 (registry+https://github.com/rust-lang/crates.io-index)" = "fce347092656428bc8eaf6201042cb551b8d67855af7374542a92a0fbfcac430" -"checksum mio-extras 2.0.6 (registry+https://github.com/rust-lang/crates.io-index)" = "52403fe290012ce777c4626790c8951324a2b9e3316b3143779c72b029742f19" -"checksum mio-named-pipes 0.1.7 (registry+https://github.com/rust-lang/crates.io-index)" = "0840c1c50fd55e521b247f949c241c9997709f23bd7f023b9762cd561e935656" -"checksum mio-uds 0.6.8 (registry+https://github.com/rust-lang/crates.io-index)" = "afcb699eb26d4332647cc848492bbc15eafb26f08d0304550d5aa1f612e066f0" -"checksum miow 0.2.1 (registry+https://github.com/rust-lang/crates.io-index)" = "8c1f2f3b1cf331de6896aabf6e9d55dca90356cc9960cca7eaaf408a355ae919" -"checksum miow 0.3.5 (registry+https://github.com/rust-lang/crates.io-index)" = "07b88fb9795d4d36d62a012dfbf49a8f5cf12751f36d31a9dbe66d528e58979e" -"checksum multihash 0.11.4 (registry+https://github.com/rust-lang/crates.io-index)" = "567122ab6492f49b59def14ecc36e13e64dca4188196dd0cd41f9f3f979f3df6" -"checksum multimap 0.8.2 (registry+https://github.com/rust-lang/crates.io-index)" = "1255076139a83bb467426e7f8d0134968a8118844faa755985e077cf31850333" -"checksum multistream-select 0.8.2 (git+https://github.com/sigp/rust-libp2p?rev=03f998022ce2f566a6c6e6c4206bc0ce4d45109f)" = "" -"checksum multistream-select 0.8.2 (registry+https://github.com/rust-lang/crates.io-index)" = "c9157e87afbc2ef0d84cc0345423d715f445edde00141c93721c162de35a05e5" -"checksum native-tls 0.2.4 (registry+https://github.com/rust-lang/crates.io-index)" = "2b0d88c06fe90d5ee94048ba40409ef1d9315d86f6f38c2efdaad4fb50c58b2d" -"checksum net2 0.2.35 (registry+https://github.com/rust-lang/crates.io-index)" = "3ebc3ec692ed7c9a255596c67808dee269f64655d8baf7b4f0638e51ba1d6853" -"checksum nix 0.17.0 (registry+https://github.com/rust-lang/crates.io-index)" = "50e4785f2c3b7589a0d0c1dd60285e1188adac4006e8abd6dd578e1567027363" -"checksum nom 2.2.1 (registry+https://github.com/rust-lang/crates.io-index)" = "cf51a729ecf40266a2368ad335a5fdde43471f545a967109cd62146ecf8b66ff" -"checksum num-bigint 0.3.0 (registry+https://github.com/rust-lang/crates.io-index)" = "b7f3fc75e3697059fb1bc465e3d8cca6cf92f56854f201158b3f9c77d5a3cfa0" -"checksum num-bigint-dig 0.6.0 (registry+https://github.com/rust-lang/crates.io-index)" = "b3d03c330f9f7a2c19e3c0b42698e48141d0809c78cd9b6219f85bd7d7e892aa" -"checksum num-integer 0.1.43 (registry+https://github.com/rust-lang/crates.io-index)" = "8d59457e662d541ba17869cf51cf177c0b5f0cbf476c66bdc90bf1edac4f875b" -"checksum num-iter 0.1.41 (registry+https://github.com/rust-lang/crates.io-index)" = "7a6e6b7c748f995c4c29c5f5ae0248536e04a5739927c74ec0fa564805094b9f" -"checksum num-traits 0.2.12 (registry+https://github.com/rust-lang/crates.io-index)" = "ac267bcc07f48ee5f8935ab0d24f316fb722d7a1292e2913f0cc196b29ffd611" -"checksum num_cpus 1.13.0 (registry+https://github.com/rust-lang/crates.io-index)" = "05499f3756671c15885fee9034446956fff3f243d6077b91e5767df161f766b3" -"checksum object 0.20.0 (registry+https://github.com/rust-lang/crates.io-index)" = "1ab52be62400ca80aa00285d25253d7f7c437b7375c4de678f5405d3afe82ca5" -"checksum once_cell 1.4.1 (registry+https://github.com/rust-lang/crates.io-index)" = "260e51e7efe62b592207e9e13a68e43692a7a279171d6ba57abd208bf23645ad" -"checksum oorandom 11.1.2 (registry+https://github.com/rust-lang/crates.io-index)" = "a170cebd8021a008ea92e4db85a72f80b35df514ec664b296fdcbb654eac0b2c" -"checksum opaque-debug 0.2.3 (registry+https://github.com/rust-lang/crates.io-index)" = "2839e79665f131bdb5782e51f2c6c9599c133c6098982a54c794358bf432529c" -"checksum opaque-debug 0.3.0 (registry+https://github.com/rust-lang/crates.io-index)" = "624a8340c38c1b80fd549087862da4ba43e08858af025b236e509b6649fc13d5" -"checksum openssl 0.10.30 (registry+https://github.com/rust-lang/crates.io-index)" = "8d575eff3665419f9b83678ff2815858ad9d11567e082f5ac1814baba4e2bcb4" -"checksum openssl-probe 0.1.2 (registry+https://github.com/rust-lang/crates.io-index)" = "77af24da69f9d9341038eba93a073b1fdaaa1b788221b00a69bce9e762cb32de" -"checksum openssl-src 111.11.0+1.1.1h (registry+https://github.com/rust-lang/crates.io-index)" = "380fe324132bea01f45239fadfec9343adb044615f29930d039bec1ae7b9fa5b" -"checksum openssl-sys 0.9.58 (registry+https://github.com/rust-lang/crates.io-index)" = "a842db4709b604f0fe5d1170ae3565899be2ad3d9cbc72dedc789ac0511f78de" -"checksum parity-multiaddr 0.9.1 (git+https://github.com/sigp/rust-libp2p?rev=03f998022ce2f566a6c6e6c4206bc0ce4d45109f)" = "" -"checksum parity-multiaddr 0.9.2 (registry+https://github.com/rust-lang/crates.io-index)" = "2165a93382a93de55868dcbfa11e4a8f99676a9164eee6a2b4a9479ad319c257" -"checksum parity-scale-codec 1.3.5 (registry+https://github.com/rust-lang/crates.io-index)" = "7c740e5fbcb6847058b40ac7e5574766c6388f585e184d769910fe0d3a2ca861" -"checksum parking_lot 0.10.2 (registry+https://github.com/rust-lang/crates.io-index)" = "d3a704eb390aafdc107b0e392f56a82b668e3a71366993b5340f5833fd62505e" -"checksum parking_lot 0.11.0 (registry+https://github.com/rust-lang/crates.io-index)" = "a4893845fa2ca272e647da5d0e46660a314ead9c2fdd9a883aabc32e481a8733" -"checksum parking_lot 0.9.0 (registry+https://github.com/rust-lang/crates.io-index)" = "f842b1982eb6c2fe34036a4fbfb06dd185a3f5c8edfaacdf7d1ea10b07de6252" -"checksum parking_lot_core 0.6.2 (registry+https://github.com/rust-lang/crates.io-index)" = "b876b1b9e7ac6e1a74a6da34d25c42e17e8862aa409cbbbdcfc8d86c6f3bc62b" -"checksum parking_lot_core 0.7.2 (registry+https://github.com/rust-lang/crates.io-index)" = "d58c7c768d4ba344e3e8d72518ac13e259d7c7ade24167003b8488e10b6740a3" -"checksum parking_lot_core 0.8.0 (registry+https://github.com/rust-lang/crates.io-index)" = "c361aa727dd08437f2f1447be8b59a33b0edd15e0fcee698f935613d9efbca9b" -"checksum pbkdf2 0.3.0 (registry+https://github.com/rust-lang/crates.io-index)" = "006c038a43a45995a9670da19e67600114740e8511d4333bf97a56e66a7542d9" -"checksum pbkdf2 0.4.0 (registry+https://github.com/rust-lang/crates.io-index)" = "216eaa586a190f0a738f2f918511eecfa90f13295abec0e457cdebcceda80cbd" -"checksum percent-encoding 1.0.1 (registry+https://github.com/rust-lang/crates.io-index)" = "31010dd2e1ac33d5b46a5b413495239882813e0369f8ed8a5e266f173602f831" -"checksum percent-encoding 2.1.0 (registry+https://github.com/rust-lang/crates.io-index)" = "d4fd5641d01c8f18a23da7b6fe29298ff4b55afcccdf78973b24cf3175fee32e" -"checksum petgraph 0.5.1 (registry+https://github.com/rust-lang/crates.io-index)" = "467d164a6de56270bd7c4d070df81d07beace25012d5103ced4e9ff08d6afdb7" -"checksum pin-project 0.4.24 (registry+https://github.com/rust-lang/crates.io-index)" = "f48fad7cfbff853437be7cf54d7b993af21f53be7f0988cbfe4a51535aa77205" -"checksum pin-project-internal 0.4.24 (registry+https://github.com/rust-lang/crates.io-index)" = "24c6d293bdd3ca5a1697997854c6cf7855e43fb6a0ba1c47af57a5bcafd158ae" -"checksum pin-project-lite 0.1.8 (registry+https://github.com/rust-lang/crates.io-index)" = "71f349a4f0e70676ffb2dbafe16d0c992382d02f0a952e3ddf584fc289dac6b3" -"checksum pin-utils 0.1.0 (registry+https://github.com/rust-lang/crates.io-index)" = "8b870d8c151b6f2fb93e84a13146138f05d02ed11c7e7c54f8826aaaf7c9f184" -"checksum pkg-config 0.3.18 (registry+https://github.com/rust-lang/crates.io-index)" = "d36492546b6af1463394d46f0c834346f31548646f6ba10849802c9c9a27ac33" -"checksum platforms 0.2.1 (registry+https://github.com/rust-lang/crates.io-index)" = "feb3b2b1033b8a60b4da6ee470325f887758c95d5320f52f9ce0df055a55940e" -"checksum plotters 0.2.15 (registry+https://github.com/rust-lang/crates.io-index)" = "0d1685fbe7beba33de0330629da9d955ac75bd54f33d7b79f9a895590124f6bb" -"checksum podio 0.1.7 (registry+https://github.com/rust-lang/crates.io-index)" = "b18befed8bc2b61abc79a457295e7e838417326da1586050b919414073977f19" -"checksum poly1305 0.6.0 (registry+https://github.com/rust-lang/crates.io-index)" = "d9b42192ab143ed7619bf888a7f9c6733a9a2153b218e2cd557cfdb52fbf9bb1" -"checksum polyval 0.4.0 (registry+https://github.com/rust-lang/crates.io-index)" = "d9a50142b55ab3ed0e9f68dfb3709f1d90d29da24e91033f28b96330643107dc" -"checksum ppv-lite86 0.2.9 (registry+https://github.com/rust-lang/crates.io-index)" = "c36fa947111f5c62a733b652544dd0016a43ce89619538a8ef92724a6f501a20" -"checksum primitive-types 0.7.2 (registry+https://github.com/rust-lang/crates.io-index)" = "c55c21c64d0eaa4d7ed885d959ef2d62d9e488c27c0e02d9aa5ce6c877b7d5f8" -"checksum proc-macro-hack 0.5.18 (registry+https://github.com/rust-lang/crates.io-index)" = "99c605b9a0adc77b7211c6b1f722dcb613d68d66859a44f3d485a6da332b0598" -"checksum proc-macro-nested 0.1.6 (registry+https://github.com/rust-lang/crates.io-index)" = "eba180dafb9038b050a4c280019bbedf9f2467b61e5d892dcad585bb57aadc5a" -"checksum proc-macro2 1.0.23 (registry+https://github.com/rust-lang/crates.io-index)" = "51ef7cd2518ead700af67bf9d1a658d90b6037d77110fd9c0445429d0ba1c6c9" -"checksum procinfo 0.4.2 (registry+https://github.com/rust-lang/crates.io-index)" = "6ab1427f3d2635891f842892dda177883dca0639e05fe66796a62c9d2f23b49c" -"checksum prometheus 0.9.0 (registry+https://github.com/rust-lang/crates.io-index)" = "dd0ced56dee39a6e960c15c74dc48849d614586db2eaada6497477af7c7811cd" -"checksum prost 0.6.1 (registry+https://github.com/rust-lang/crates.io-index)" = "ce49aefe0a6144a45de32927c77bd2859a5f7677b55f220ae5b744e87389c212" -"checksum prost-build 0.6.1 (registry+https://github.com/rust-lang/crates.io-index)" = "02b10678c913ecbd69350e8535c3aef91a8676c0773fc1d7b95cdd196d7f2f26" -"checksum prost-derive 0.6.1 (registry+https://github.com/rust-lang/crates.io-index)" = "537aa19b95acde10a12fec4301466386f757403de4cd4e5b4fa78fb5ecb18f72" -"checksum prost-types 0.6.1 (registry+https://github.com/rust-lang/crates.io-index)" = "1834f67c0697c001304b75be76f67add9c89742eda3a085ad8ee0bb38c3417aa" -"checksum protobuf 2.17.0 (registry+https://github.com/rust-lang/crates.io-index)" = "cb14183cc7f213ee2410067e1ceeadba2a7478a59432ff0747a335202798b1e2" -"checksum psutil 3.2.0 (registry+https://github.com/rust-lang/crates.io-index)" = "7cdb732329774b8765346796abd1e896e9b3c86aae7f135bb1dda98c2c460f55" -"checksum quick-error 1.2.3 (registry+https://github.com/rust-lang/crates.io-index)" = "a1d01941d82fa2ab50be1e79e6714289dd7cde78eba4c074bc5a4374f650dfe0" -"checksum quickcheck 0.9.2 (registry+https://github.com/rust-lang/crates.io-index)" = "a44883e74aa97ad63db83c4bf8ca490f02b2fc02f92575e720c8551e843c945f" -"checksum quickcheck_macros 0.9.1 (registry+https://github.com/rust-lang/crates.io-index)" = "608c156fd8e97febc07dc9c2e2c80bf74cfc6ef26893eae3daf8bc2bc94a4b7f" -"checksum quicksink 0.1.2 (registry+https://github.com/rust-lang/crates.io-index)" = "77de3c815e5a160b1539c6592796801df2043ae35e123b46d73380cfa57af858" -"checksum quote 1.0.7 (registry+https://github.com/rust-lang/crates.io-index)" = "aa563d17ecb180e500da1cfd2b028310ac758de548efdd203e18f283af693f37" -"checksum r2d2 0.8.9 (registry+https://github.com/rust-lang/crates.io-index)" = "545c5bc2b880973c9c10e4067418407a0ccaa3091781d1671d46eb35107cb26f" -"checksum r2d2_sqlite 0.16.0 (registry+https://github.com/rust-lang/crates.io-index)" = "ed60ebe88b27ac28c0563bc0fbeaecd302ff53e3a01e5ddc2ec9f4e6c707d929" -"checksum radium 0.3.0 (registry+https://github.com/rust-lang/crates.io-index)" = "def50a86306165861203e7f84ecffbbdfdea79f0e51039b33de1e952358c47ac" -"checksum rand 0.4.6 (registry+https://github.com/rust-lang/crates.io-index)" = "552840b97013b1a26992c11eac34bdd778e464601a4c2054b5f0bff7c6761293" -"checksum rand 0.5.6 (registry+https://github.com/rust-lang/crates.io-index)" = "c618c47cd3ebd209790115ab837de41425723956ad3ce2e6a7f09890947cacb9" -"checksum rand 0.7.3 (registry+https://github.com/rust-lang/crates.io-index)" = "6a6b1679d49b24bbfe0c803429aa1874472f50d9b363131f0e89fc356b544d03" -"checksum rand_chacha 0.2.2 (registry+https://github.com/rust-lang/crates.io-index)" = "f4c8ed856279c9737206bf725bf36935d8666ead7aa69b52be55af369d193402" -"checksum rand_core 0.3.1 (registry+https://github.com/rust-lang/crates.io-index)" = "7a6fdeb83b075e8266dcc8762c22776f6877a63111121f5f8c7411e5be7eed4b" -"checksum rand_core 0.4.2 (registry+https://github.com/rust-lang/crates.io-index)" = "9c33a3c44ca05fa6f1807d8e6743f3824e8509beca625669633be0acbdf509dc" -"checksum rand_core 0.5.1 (registry+https://github.com/rust-lang/crates.io-index)" = "90bde5296fc891b0cef12a6d03ddccc162ce7b2aff54160af9338f8d40df6d19" -"checksum rand_hc 0.2.0 (registry+https://github.com/rust-lang/crates.io-index)" = "ca3129af7b92a17112d59ad498c6f81eaf463253766b90396d39ea7a39d6613c" -"checksum rand_xorshift 0.2.0 (registry+https://github.com/rust-lang/crates.io-index)" = "77d416b86801d23dde1aa643023b775c3a462efc0ed96443add11546cdf1dca8" -"checksum rayon 1.4.0 (registry+https://github.com/rust-lang/crates.io-index)" = "cfd016f0c045ad38b5251be2c9c0ab806917f82da4d36b2a327e5166adad9270" -"checksum rayon-core 1.8.1 (registry+https://github.com/rust-lang/crates.io-index)" = "e8c4fec834fb6e6d2dd5eece3c7b432a52f0ba887cf40e595190c4107edc08bf" -"checksum rdrand 0.4.0 (registry+https://github.com/rust-lang/crates.io-index)" = "678054eb77286b51581ba43620cc911abf02758c91f93f479767aed0f90458b2" -"checksum redox_syscall 0.1.57 (registry+https://github.com/rust-lang/crates.io-index)" = "41cc0f7e4d5d4544e8861606a285bb08d3e70712ccc7d2b84d7c0ccfaf4b05ce" -"checksum redox_users 0.3.5 (registry+https://github.com/rust-lang/crates.io-index)" = "de0737333e7a9502c789a36d7c7fa6092a49895d4faa31ca5df163857ded2e9d" -"checksum regex 1.3.9 (registry+https://github.com/rust-lang/crates.io-index)" = "9c3780fcf44b193bc4d09f36d2a3c87b251da4a046c87795a0d35f4f927ad8e6" -"checksum regex-automata 0.1.9 (registry+https://github.com/rust-lang/crates.io-index)" = "ae1ded71d66a4a97f5e961fd0cb25a5f366a42a41570d16a763a69c092c26ae4" -"checksum regex-syntax 0.6.18 (registry+https://github.com/rust-lang/crates.io-index)" = "26412eb97c6b088a6997e05f69403a802a92d520de2f8e63c2b65f9e0f47c4e8" -"checksum remove_dir_all 0.5.3 (registry+https://github.com/rust-lang/crates.io-index)" = "3acd125665422973a33ac9d3dd2df85edad0f4ae9b00dafb1a05e43a9f5ef8e7" -"checksum reqwest 0.10.8 (registry+https://github.com/rust-lang/crates.io-index)" = "e9eaa17ac5d7b838b7503d118fa16ad88f440498bf9ffe5424e621f93190d61e" -"checksum ring 0.16.12 (registry+https://github.com/rust-lang/crates.io-index)" = "1ba5a8ec64ee89a76c98c549af81ff14813df09c3e6dc4766c3856da48597a0c" -"checksum rle-decode-fast 1.0.1 (registry+https://github.com/rust-lang/crates.io-index)" = "cabe4fa914dec5870285fa7f71f602645da47c486e68486d2b4ceb4a343e90ac" -"checksum rlp 0.4.5 (registry+https://github.com/rust-lang/crates.io-index)" = "4a7d3f9bed94764eac15b8f14af59fac420c236adaff743b7bcc88e265cb4345" -"checksum rpassword 4.0.5 (registry+https://github.com/rust-lang/crates.io-index)" = "99371657d3c8e4d816fb6221db98fa408242b0b53bac08f8676a41f8554fe99f" -"checksum rusqlite 0.23.1 (registry+https://github.com/rust-lang/crates.io-index)" = "45d0fd62e1df63d254714e6cb40d0a0e82e7a1623e7a27f679d851af092ae58b" -"checksum rust-argon2 0.8.2 (registry+https://github.com/rust-lang/crates.io-index)" = "9dab61250775933275e84053ac235621dfb739556d5c54a2f2e9313b7cf43a19" -"checksum rustc-demangle 0.1.16 (registry+https://github.com/rust-lang/crates.io-index)" = "4c691c0e608126e00913e33f0ccf3727d5fc84573623b8d65b2df340b5201783" -"checksum rustc-hash 1.1.0 (registry+https://github.com/rust-lang/crates.io-index)" = "08d43f7aa6b08d49f382cde6a7982047c3426db949b1424bc4b7ec9ae12c6ce2" -"checksum rustc-hex 2.1.0 (registry+https://github.com/rust-lang/crates.io-index)" = "3e75f6a532d0fd9f7f13144f392b6ad56a32696bfcd9c78f797f16bbb6f072d6" -"checksum rustc_version 0.2.3 (registry+https://github.com/rust-lang/crates.io-index)" = "138e3e0acb6c9fb258b19b67cb8abd63c00679d2851805ea151465464fe9030a" -"checksum rustls 0.18.1 (registry+https://github.com/rust-lang/crates.io-index)" = "5d1126dcf58e93cee7d098dbda643b5f92ed724f1f6a63007c1116eed6700c81" -"checksum rw-stream-sink 0.2.1 (registry+https://github.com/rust-lang/crates.io-index)" = "4da5fcb054c46f5a5dff833b129285a93d3f0179531735e6c866e8cc307d2020" -"checksum ryu 1.0.5 (registry+https://github.com/rust-lang/crates.io-index)" = "71d301d4193d031abdd79ff7e3dd721168a9572ef3fe51a1517aba235bd8f86e" -"checksum safemem 0.3.3 (registry+https://github.com/rust-lang/crates.io-index)" = "ef703b7cb59335eae2eb93ceb664c0eb7ea6bf567079d843e09420219668e072" -"checksum same-file 1.0.6 (registry+https://github.com/rust-lang/crates.io-index)" = "93fc1dc3aaa9bfed95e02e6eadabb4baf7e3078b0bd1b4d7b6b0b68378900502" -"checksum schannel 0.1.19 (registry+https://github.com/rust-lang/crates.io-index)" = "8f05ba609c234e60bee0d547fe94a4c7e9da733d1c962cf6e59efa4cd9c8bc75" -"checksum scheduled-thread-pool 0.2.5 (registry+https://github.com/rust-lang/crates.io-index)" = "dc6f74fd1204073fa02d5d5d68bec8021be4c38690b61264b2fdb48083d0e7d7" -"checksum scoped-tls 0.1.2 (registry+https://github.com/rust-lang/crates.io-index)" = "332ffa32bf586782a3efaeb58f127980944bbc8c4d6913a86107ac2a5ab24b28" -"checksum scoped-tls 1.0.0 (registry+https://github.com/rust-lang/crates.io-index)" = "ea6a9290e3c9cf0f18145ef7ffa62d68ee0bf5fcd651017e586dc7fd5da448c2" -"checksum scopeguard 1.1.0 (registry+https://github.com/rust-lang/crates.io-index)" = "d29ab0c6d3fc0ee92fe66e2d99f700eab17a8d57d1c1d3b748380fb20baa78cd" -"checksum scrypt 0.3.1 (registry+https://github.com/rust-lang/crates.io-index)" = "10e7e75e27e8cd47e4be027d4b9fdc0b696116f981c22de21ca7bad63a9cb33a" -"checksum sct 0.6.0 (registry+https://github.com/rust-lang/crates.io-index)" = "e3042af939fca8c3453b7af0f1c66e533a15a86169e39de2657310ade8f98d3c" -"checksum secp256k1 0.17.2 (registry+https://github.com/rust-lang/crates.io-index)" = "2932dc07acd2066ff2e3921a4419606b220ba6cd03a9935123856cc534877056" -"checksum secp256k1-sys 0.1.2 (registry+https://github.com/rust-lang/crates.io-index)" = "7ab2c26f0d3552a0f12e639ae8a64afc2e3db9c52fe32f5fc6c289d38519f220" -"checksum security-framework 0.4.4 (registry+https://github.com/rust-lang/crates.io-index)" = "64808902d7d99f78eaddd2b4e2509713babc3dc3c85ad6f4c447680f3c01e535" -"checksum security-framework-sys 0.4.3 (registry+https://github.com/rust-lang/crates.io-index)" = "17bf11d99252f512695eb468de5516e5cf75455521e69dfe343f3b74e4748405" -"checksum semver 0.9.0 (registry+https://github.com/rust-lang/crates.io-index)" = "1d7eb9ef2c18661902cc47e535f9bc51b78acd254da71d375c2f6720d9a40403" -"checksum semver-parser 0.7.0 (registry+https://github.com/rust-lang/crates.io-index)" = "388a1df253eca08550bef6c72392cfe7c30914bf41df5269b68cbd6ff8f570a3" -"checksum serde 1.0.116 (registry+https://github.com/rust-lang/crates.io-index)" = "96fe57af81d28386a513cbc6858332abc6117cfdb5999647c6444b8f43a370a5" -"checksum serde_cbor 0.11.1 (registry+https://github.com/rust-lang/crates.io-index)" = "1e18acfa2f90e8b735b2836ab8d538de304cbb6729a7360729ea5a895d15a622" -"checksum serde_derive 1.0.116 (registry+https://github.com/rust-lang/crates.io-index)" = "f630a6370fd8e457873b4bd2ffdae75408bc291ba72be773772a4c2a065d9ae8" -"checksum serde_json 1.0.57 (registry+https://github.com/rust-lang/crates.io-index)" = "164eacbdb13512ec2745fb09d51fd5b22b0d65ed294a1dcf7285a360c80a675c" -"checksum serde_repr 0.1.6 (registry+https://github.com/rust-lang/crates.io-index)" = "2dc6b7951b17b051f3210b063f12cc17320e2fe30ae05b0fe2a3abb068551c76" -"checksum serde_urlencoded 0.6.1 (registry+https://github.com/rust-lang/crates.io-index)" = "9ec5d77e2d4c73717816afac02670d5c4f534ea95ed430442cad02e7a6e32c97" -"checksum serde_yaml 0.8.13 (registry+https://github.com/rust-lang/crates.io-index)" = "ae3e2dd40a7cdc18ca80db804b7f461a39bb721160a85c9a1fa30134bf3c02a5" -"checksum sha-1 0.8.2 (registry+https://github.com/rust-lang/crates.io-index)" = "f7d94d0bede923b3cea61f3f1ff57ff8cdfd77b400fb8f9998949e0cf04163df" -"checksum sha-1 0.9.1 (registry+https://github.com/rust-lang/crates.io-index)" = "170a36ea86c864a3f16dd2687712dd6646f7019f301e57537c7f4dc9f5916770" -"checksum sha1 0.6.0 (registry+https://github.com/rust-lang/crates.io-index)" = "2579985fda508104f7587689507983eadd6a6e84dd35d6d115361f530916fa0d" -"checksum sha2 0.8.2 (registry+https://github.com/rust-lang/crates.io-index)" = "a256f46ea78a0c0d9ff00077504903ac881a1dafdc20da66545699e7776b3e69" -"checksum sha2 0.9.1 (registry+https://github.com/rust-lang/crates.io-index)" = "2933378ddfeda7ea26f48c555bdad8bb446bf8a3d17832dc83e380d444cfb8c1" -"checksum sha3 0.9.1 (registry+https://github.com/rust-lang/crates.io-index)" = "f81199417d4e5de3f04b1e871023acea7389672c4135918f05aa9cbf2f2fa809" -"checksum signal-hook-registry 1.2.1 (registry+https://github.com/rust-lang/crates.io-index)" = "a3e12110bc539e657a646068aaf5eb5b63af9d0c1f7b29c97113fad80e15f035" -"checksum signature 1.2.2 (registry+https://github.com/rust-lang/crates.io-index)" = "29f060a7d147e33490ec10da418795238fd7545bba241504d6b31a409f2e6210" -"checksum simple_logger 1.9.0 (registry+https://github.com/rust-lang/crates.io-index)" = "13a53ed2efd04911c8280f2da7bf9abd350c931b86bc7f9f2386fbafbf525ff9" -"checksum slab 0.3.0 (registry+https://github.com/rust-lang/crates.io-index)" = "17b4fcaed89ab08ef143da37bc52adbcc04d4a69014f4c1208d6b51f0c47bc23" -"checksum slab 0.4.2 (registry+https://github.com/rust-lang/crates.io-index)" = "c111b5bd5695e56cffe5129854aa230b39c93a305372fdbb2668ca2394eea9f8" -"checksum slog 2.5.2 (registry+https://github.com/rust-lang/crates.io-index)" = "1cc9c640a4adbfbcc11ffb95efe5aa7af7309e002adab54b185507dbf2377b99" -"checksum slog-async 2.5.0 (registry+https://github.com/rust-lang/crates.io-index)" = "51b3336ce47ce2f96673499fc07eb85e3472727b9a7a2959964b002c2ce8fbbb" -"checksum slog-json 2.3.0 (registry+https://github.com/rust-lang/crates.io-index)" = "ddc0d2aff1f8f325ef660d9a0eb6e6dcd20b30b3f581a5897f58bf42d061c37a" -"checksum slog-kvfilter 0.7.0 (registry+https://github.com/rust-lang/crates.io-index)" = "ae939ed7d169eed9699f4f5cd440f046f5dc5dfc27c19e3cd311619594c175e0" -"checksum slog-scope 4.3.0 (registry+https://github.com/rust-lang/crates.io-index)" = "7c44c89dd8b0ae4537d1ae318353eaf7840b4869c536e31c41e963d1ea523ee6" -"checksum slog-stdlog 4.0.0 (registry+https://github.com/rust-lang/crates.io-index)" = "be4d87903baf655da2d82bc3ac3f7ef43868c58bf712b3a661fda72009304c23" -"checksum slog-term 2.6.0 (registry+https://github.com/rust-lang/crates.io-index)" = "bab1d807cf71129b05ce36914e1dbb6fbfbdecaf686301cb457f4fa967f9f5b6" -"checksum sloggers 1.0.1 (registry+https://github.com/rust-lang/crates.io-index)" = "f01d37507aa6f37490cfa08d71e2639b16906e84c285ae4b9f7ec7ca35756d69" -"checksum smallvec 0.6.13 (registry+https://github.com/rust-lang/crates.io-index)" = "f7b0758c52e15a8b5e3691eae6cc559f08eee9406e548a4477ba4e67770a82b6" -"checksum smallvec 1.4.2 (registry+https://github.com/rust-lang/crates.io-index)" = "fbee7696b84bbf3d89a1c2eccff0850e3047ed46bfcd2e92c29a2d074d57e252" -"checksum snap 1.0.1 (registry+https://github.com/rust-lang/crates.io-index)" = "da73c8f77aebc0e40c300b93f0a5f1bece7a248a36eee287d4e095f35c7b7d6e" -"checksum snow 0.7.1 (registry+https://github.com/rust-lang/crates.io-index)" = "32bf8474159a95551661246cda4976e89356999e3cbfef36f493dacc3fae1e8e" -"checksum socket2 0.3.15 (registry+https://github.com/rust-lang/crates.io-index)" = "b1fa70dc5c8104ec096f4fe7ede7a221d35ae13dcd19ba1ad9a81d2cab9a1c44" -"checksum soketto 0.4.2 (registry+https://github.com/rust-lang/crates.io-index)" = "b5c71ed3d54db0a699f4948e1bb3e45b450fa31fe602621dee6680361d569c88" -"checksum spin 0.5.2 (registry+https://github.com/rust-lang/crates.io-index)" = "6e63cff320ae2c57904679ba7cb63280a3dc4613885beafb148ee7bf9aa9042d" -"checksum standback 0.2.10 (registry+https://github.com/rust-lang/crates.io-index)" = "33a71ea1ea5f8747d1af1979bfb7e65c3a025a70609f04ceb78425bc5adad8e6" -"checksum static_assertions 1.1.0 (registry+https://github.com/rust-lang/crates.io-index)" = "a2eb9349b6444b326872e140eb1cf5e7c522154d69e7a0ffb0fb81c06b37543f" -"checksum stdweb 0.4.20 (registry+https://github.com/rust-lang/crates.io-index)" = "d022496b16281348b52d0e30ae99e01a73d737b2f45d38fed4edf79f9325a1d5" -"checksum stdweb-derive 0.5.3 (registry+https://github.com/rust-lang/crates.io-index)" = "c87a60a40fccc84bef0652345bbbbbe20a605bf5d0ce81719fc476f5c03b50ef" -"checksum stdweb-internal-macros 0.2.9 (registry+https://github.com/rust-lang/crates.io-index)" = "58fa5ff6ad0d98d1ffa8cb115892b6e69d67799f6763e162a1c9db421dc22e11" -"checksum stdweb-internal-runtime 0.1.5 (registry+https://github.com/rust-lang/crates.io-index)" = "213701ba3370744dcd1a12960caa4843b3d68b4d1c0a5d575e0d65b2ee9d16c0" -"checksum stream-cipher 0.4.1 (registry+https://github.com/rust-lang/crates.io-index)" = "09f8ed9974042b8c3672ff3030a69fcc03b74c47c3d1ecb7755e8a3626011e88" -"checksum string 0.2.1 (registry+https://github.com/rust-lang/crates.io-index)" = "d24114bfcceb867ca7f71a0d3fe45d45619ec47a6fbfa98cb14e14250bfa5d6d" -"checksum strsim 0.8.0 (registry+https://github.com/rust-lang/crates.io-index)" = "8ea5119cdb4c55b55d432abb513a0429384878c15dde60cc77b1c99de1a95a6a" -"checksum subtle 1.0.0 (registry+https://github.com/rust-lang/crates.io-index)" = "2d67a5a62ba6e01cb2192ff309324cb4875d0c451d55fe2319433abe7a05a8ee" -"checksum subtle 2.3.0 (registry+https://github.com/rust-lang/crates.io-index)" = "343f3f510c2915908f155e94f17220b19ccfacf2a64a2a5d8004f2c3e311e7fd" -"checksum syn 1.0.42 (registry+https://github.com/rust-lang/crates.io-index)" = "9c51d92969d209b54a98397e1b91c8ae82d8c87a7bb87df0b29aa2ad81454228" -"checksum synstructure 0.12.4 (registry+https://github.com/rust-lang/crates.io-index)" = "b834f2d66f734cb897113e34aaff2f1ab4719ca946f9a7358dba8f8064148701" -"checksum take_mut 0.2.2 (registry+https://github.com/rust-lang/crates.io-index)" = "f764005d11ee5f36500a149ace24e00e3da98b0158b3e2d53a7495660d3f4d60" -"checksum target_info 0.1.0 (registry+https://github.com/rust-lang/crates.io-index)" = "c63f48baada5c52e65a29eef93ab4f8982681b67f9e8d29c7b05abcfec2b9ffe" -"checksum tempdir 0.3.7 (registry+https://github.com/rust-lang/crates.io-index)" = "15f2b5fb00ccdf689e0149d1b1b3c03fead81c2b37735d812fa8bddbbf41b6d8" -"checksum tempfile 3.1.0 (registry+https://github.com/rust-lang/crates.io-index)" = "7a6e24d9338a0a5be79593e2fa15a648add6138caa803e2d5bc782c371732ca9" -"checksum term 0.6.1 (registry+https://github.com/rust-lang/crates.io-index)" = "c0863a3345e70f61d613eab32ee046ccd1bcc5f9105fe402c61fcd0c13eeb8b5" -"checksum termcolor 1.1.0 (registry+https://github.com/rust-lang/crates.io-index)" = "bb6bfa289a4d7c5766392812c0a1f4c1ba45afa1ad47803c11e1f407d846d75f" -"checksum textwrap 0.11.0 (registry+https://github.com/rust-lang/crates.io-index)" = "d326610f408c7a4eb6f51c37c330e496b08506c9457c9d34287ecc38809fb060" -"checksum thiserror 1.0.20 (registry+https://github.com/rust-lang/crates.io-index)" = "7dfdd070ccd8ccb78f4ad66bf1982dc37f620ef696c6b5028fe2ed83dd3d0d08" -"checksum thiserror-impl 1.0.20 (registry+https://github.com/rust-lang/crates.io-index)" = "bd80fc12f73063ac132ac92aceea36734f04a1d93c1240c6944e23a3b8841793" -"checksum thread_local 1.0.1 (registry+https://github.com/rust-lang/crates.io-index)" = "d40c6d1b69745a6ec6fb1ca717914848da4b44ae29d9b3080cbee91d72a69b14" -"checksum threadpool 1.8.1 (registry+https://github.com/rust-lang/crates.io-index)" = "d050e60b33d41c19108b32cea32164033a9013fe3b46cbd4457559bfbf77afaa" -"checksum time 0.1.44 (registry+https://github.com/rust-lang/crates.io-index)" = "6db9e6914ab8b1ae1c260a4ae7a49b6c5611b40328a735b21862567685e73255" -"checksum time 0.2.22 (registry+https://github.com/rust-lang/crates.io-index)" = "55b7151c9065e80917fbf285d9a5d1432f60db41d170ccafc749a136b41a93af" -"checksum time-macros 0.1.0 (registry+https://github.com/rust-lang/crates.io-index)" = "9ae9b6e9f095bc105e183e3cd493d72579be3181ad4004fceb01adbe9eecab2d" -"checksum time-macros-impl 0.1.1 (registry+https://github.com/rust-lang/crates.io-index)" = "e5c3be1edfad6027c69f5491cf4cb310d1a71ecd6af742788c6ff8bced86b8fa" -"checksum tiny-bip39 0.7.3 (registry+https://github.com/rust-lang/crates.io-index)" = "b0165e045cc2ae1660270ca65e1676dbaab60feb0f91b10f7d0665e9b47e31f2" -"checksum tiny-keccak 1.5.0 (registry+https://github.com/rust-lang/crates.io-index)" = "1d8a021c69bb74a44ccedb824a046447e2c84a01df9e5c20779750acb38e11b2" -"checksum tiny-keccak 2.0.2 (registry+https://github.com/rust-lang/crates.io-index)" = "2c9d3793400a45f954c52e73d068316d76b6f4e36977e3fcebb13a2721e80237" -"checksum tinytemplate 1.1.0 (registry+https://github.com/rust-lang/crates.io-index)" = "6d3dc76004a03cec1c5932bca4cdc2e39aaa798e3f82363dd94f9adf6098c12f" -"checksum tinyvec 0.3.4 (registry+https://github.com/rust-lang/crates.io-index)" = "238ce071d267c5710f9d31451efec16c5ee22de34df17cc05e56cbc92e967117" -"checksum tokio 0.1.22 (registry+https://github.com/rust-lang/crates.io-index)" = "5a09c0b5bb588872ab2f09afa13ee6e9dac11e10a0ec9e8e3ba39a5a5d530af6" -"checksum tokio 0.2.22 (registry+https://github.com/rust-lang/crates.io-index)" = "5d34ca54d84bf2b5b4d7d31e901a8464f7b60ac145a284fba25ceb801f2ddccd" -"checksum tokio-buf 0.1.1 (registry+https://github.com/rust-lang/crates.io-index)" = "8fb220f46c53859a4b7ec083e41dec9778ff0b1851c0942b211edb89e0ccdc46" -"checksum tokio-codec 0.1.2 (registry+https://github.com/rust-lang/crates.io-index)" = "25b2998660ba0e70d18684de5d06b70b70a3a747469af9dea7618cc59e75976b" -"checksum tokio-core 0.1.17 (registry+https://github.com/rust-lang/crates.io-index)" = "aeeffbbb94209023feaef3c196a41cbcdafa06b4a6f893f68779bb5e53796f71" -"checksum tokio-current-thread 0.1.7 (registry+https://github.com/rust-lang/crates.io-index)" = "b1de0e32a83f131e002238d7ccde18211c0a5397f60cbfffcb112868c2e0e20e" -"checksum tokio-executor 0.1.10 (registry+https://github.com/rust-lang/crates.io-index)" = "fb2d1b8f4548dbf5e1f7818512e9c406860678f29c300cdf0ebac72d1a3a1671" -"checksum tokio-fs 0.1.7 (registry+https://github.com/rust-lang/crates.io-index)" = "297a1206e0ca6302a0eed35b700d292b275256f596e2f3fea7729d5e629b6ff4" -"checksum tokio-io 0.1.13 (registry+https://github.com/rust-lang/crates.io-index)" = "57fc868aae093479e3131e3d165c93b1c7474109d13c90ec0dda2a1bbfff0674" -"checksum tokio-io-timeout 0.4.0 (registry+https://github.com/rust-lang/crates.io-index)" = "9390a43272c8a6ac912ed1d1e2b6abeafd5047e05530a2fa304deee041a06215" -"checksum tokio-macros 0.2.5 (registry+https://github.com/rust-lang/crates.io-index)" = "f0c3acc6aa564495a0f2e1d59fab677cd7f81a19994cfc7f3ad0e64301560389" -"checksum tokio-reactor 0.1.12 (registry+https://github.com/rust-lang/crates.io-index)" = "09bc590ec4ba8ba87652da2068d150dcada2cfa2e07faae270a5e0409aa51351" -"checksum tokio-sync 0.1.8 (registry+https://github.com/rust-lang/crates.io-index)" = "edfe50152bc8164fcc456dab7891fa9bf8beaf01c5ee7e1dd43a397c3cf87dee" -"checksum tokio-tcp 0.1.4 (registry+https://github.com/rust-lang/crates.io-index)" = "98df18ed66e3b72e742f185882a9e201892407957e45fbff8da17ae7a7c51f72" -"checksum tokio-threadpool 0.1.18 (registry+https://github.com/rust-lang/crates.io-index)" = "df720b6581784c118f0eb4310796b12b1d242a7eb95f716a8367855325c25f89" -"checksum tokio-timer 0.1.2 (registry+https://github.com/rust-lang/crates.io-index)" = "6131e780037787ff1b3f8aad9da83bca02438b72277850dd6ad0d455e0e20efc" -"checksum tokio-timer 0.2.13 (registry+https://github.com/rust-lang/crates.io-index)" = "93044f2d313c95ff1cb7809ce9a7a05735b012288a888b62d4434fd58c94f296" -"checksum tokio-tls 0.2.1 (registry+https://github.com/rust-lang/crates.io-index)" = "354b8cd83825b3c20217a9dc174d6a0c67441a2fae5c41bcb1ea6679f6ae0f7c" -"checksum tokio-tls 0.3.1 (registry+https://github.com/rust-lang/crates.io-index)" = "9a70f4fcd7b3b24fb194f837560168208f669ca8cb70d0c4b862944452396343" -"checksum tokio-udp 0.1.6 (registry+https://github.com/rust-lang/crates.io-index)" = "e2a0b10e610b39c38b031a2fcab08e4b82f16ece36504988dcbd81dbba650d82" -"checksum tokio-uds 0.1.7 (registry+https://github.com/rust-lang/crates.io-index)" = "65ae5d255ce739e8537221ed2942e0445f4b3b813daebac1c0050ddaaa3587f9" -"checksum tokio-uds 0.2.7 (registry+https://github.com/rust-lang/crates.io-index)" = "ab57a4ac4111c8c9dbcf70779f6fc8bc35ae4b2454809febac840ad19bd7e4e0" -"checksum tokio-util 0.3.1 (registry+https://github.com/rust-lang/crates.io-index)" = "be8242891f2b6cbef26a2d7e8605133c2c554cd35b3e4948ea892d6d68436499" -"checksum toml 0.5.6 (registry+https://github.com/rust-lang/crates.io-index)" = "ffc92d160b1eef40665be3a05630d003936a3bc7da7421277846c2613e92c71a" -"checksum tower-service 0.3.0 (registry+https://github.com/rust-lang/crates.io-index)" = "e987b6bf443f4b5b3b6f38704195592cca41c5bb7aedd3c3693c7081f8289860" -"checksum tracing 0.1.19 (registry+https://github.com/rust-lang/crates.io-index)" = "6d79ca061b032d6ce30c660fded31189ca0b9922bf483cd70759f13a2d86786c" -"checksum tracing-core 0.1.16 (registry+https://github.com/rust-lang/crates.io-index)" = "5bcf46c1f1f06aeea2d6b81f3c863d0930a596c86ad1920d4e5bad6dd1d7119a" -"checksum trackable 1.0.0 (registry+https://github.com/rust-lang/crates.io-index)" = "30fb6e13d129dd92c501458f64d56c708e3685e3fd307e878ec5f934c5c5bdb0" -"checksum trackable_derive 1.0.0 (registry+https://github.com/rust-lang/crates.io-index)" = "ebeb235c5847e2f82cfe0f07eb971d1e5f6804b18dac2ae16349cc604380f82f" -"checksum traitobject 0.1.0 (registry+https://github.com/rust-lang/crates.io-index)" = "efd1f82c56340fdf16f2a953d7bda4f8fdffba13d93b00844c25572110b26079" -"checksum try-lock 0.2.3 (registry+https://github.com/rust-lang/crates.io-index)" = "59547bce71d9c38b83d9c0e92b6066c4253371f15005def0c30d9657f50c7642" -"checksum typeable 0.1.2 (registry+https://github.com/rust-lang/crates.io-index)" = "1410f6f91f21d1612654e7cc69193b0334f909dcf2c790c4826254fbb86f8887" -"checksum typenum 1.12.0 (registry+https://github.com/rust-lang/crates.io-index)" = "373c8a200f9e67a0c95e62a4f52fbf80c23b4381c05a17845531982fa99e6b33" -"checksum uhttp_sse 0.5.1 (registry+https://github.com/rust-lang/crates.io-index)" = "c6ff93345ba2206230b1bb1aa3ece1a63dd9443b7531024575d16a0680a59444" -"checksum uint 0.8.5 (registry+https://github.com/rust-lang/crates.io-index)" = "9db035e67dfaf7edd9aebfe8676afcd63eed53c8a4044fed514c8cccf1835177" -"checksum unescape 0.1.0 (registry+https://github.com/rust-lang/crates.io-index)" = "ccb97dac3243214f8d8507998906ca3e2e0b900bf9bf4870477f125b82e68f6e" -"checksum unicase 1.4.2 (registry+https://github.com/rust-lang/crates.io-index)" = "7f4765f83163b74f957c797ad9253caf97f103fb064d3999aea9568d09fc8a33" -"checksum unicase 2.6.0 (registry+https://github.com/rust-lang/crates.io-index)" = "50f37be617794602aabbeee0be4f259dc1778fabe05e2d67ee8f79326d5cb4f6" -"checksum unicode-bidi 0.3.4 (registry+https://github.com/rust-lang/crates.io-index)" = "49f2bd0c6468a8230e1db229cff8029217cf623c767ea5d60bfbd42729ea54d5" -"checksum unicode-normalization 0.1.13 (registry+https://github.com/rust-lang/crates.io-index)" = "6fb19cf769fa8c6a80a162df694621ebeb4dafb606470b2b2fce0be40a98a977" -"checksum unicode-segmentation 1.6.0 (registry+https://github.com/rust-lang/crates.io-index)" = "e83e153d1053cbb5a118eeff7fd5be06ed99153f00dbcd8ae310c5fb2b22edc0" -"checksum unicode-width 0.1.8 (registry+https://github.com/rust-lang/crates.io-index)" = "9337591893a19b88d8d87f2cec1e73fad5cdfd10e5a6f349f498ad6ea2ffb1e3" -"checksum unicode-xid 0.2.1 (registry+https://github.com/rust-lang/crates.io-index)" = "f7fe0bb3479651439c9112f72b6c505038574c9fbb575ed1bf3b797fa39dd564" -"checksum universal-hash 0.4.0 (registry+https://github.com/rust-lang/crates.io-index)" = "8326b2c654932e3e4f9196e69d08fdf7cfd718e1dc6f66b347e6024a0c961402" -"checksum unsigned-varint 0.3.3 (git+https://github.com/sigp/unsigned-varint?branch=latest-codecs)" = "" -"checksum unsigned-varint 0.4.0 (registry+https://github.com/rust-lang/crates.io-index)" = "669d776983b692a906c881fcd0cfb34271a48e197e4d6cb8df32b05bfc3d3fa5" -"checksum unsigned-varint 0.5.1 (registry+https://github.com/rust-lang/crates.io-index)" = "f7fdeedbf205afadfe39ae559b75c3240f24e257d0ca27e85f85cb82aa19ac35" -"checksum untrusted 0.7.1 (registry+https://github.com/rust-lang/crates.io-index)" = "a156c684c91ea7d62626509bce3cb4e1d9ed5c4d978f7b4352658f96a4c26b4a" -"checksum url 1.7.2 (registry+https://github.com/rust-lang/crates.io-index)" = "dd4e7c0d531266369519a4aa4f399d748bd37043b00bde1e4ff1f60a120b355a" -"checksum url 2.1.1 (registry+https://github.com/rust-lang/crates.io-index)" = "829d4a8476c35c9bf0bbce5a3b23f4106f79728039b726d292bb93bc106787cb" -"checksum uuid 0.8.1 (registry+https://github.com/rust-lang/crates.io-index)" = "9fde2f6a4bea1d6e007c4ad38c6839fa71cbb63b6dbf5b595aa38dc9b1093c11" -"checksum vcpkg 0.2.10 (registry+https://github.com/rust-lang/crates.io-index)" = "6454029bf181f092ad1b853286f23e2c507d8e8194d01d92da4a55c274a5508c" -"checksum vec_map 0.8.2 (registry+https://github.com/rust-lang/crates.io-index)" = "f1bddf1187be692e79c5ffeab891132dfb0f236ed36a43c7ed39f1165ee20191" -"checksum version_check 0.1.5 (registry+https://github.com/rust-lang/crates.io-index)" = "914b1a6776c4c929a602fafd8bc742e06365d4bcbe48c30f9cca5824f70dc9dd" -"checksum version_check 0.9.2 (registry+https://github.com/rust-lang/crates.io-index)" = "b5a972e5669d67ba988ce3dc826706fb0a8b01471c088cb0b6110b805cc36aed" -"checksum void 1.0.2 (registry+https://github.com/rust-lang/crates.io-index)" = "6a02e4885ed3bc0f2de90ea6dd45ebcbb66dacffe03547fadbb0eeae2770887d" -"checksum walkdir 2.3.1 (registry+https://github.com/rust-lang/crates.io-index)" = "777182bc735b6424e1a57516d35ed72cb8019d85c8c9bf536dccb3445c1a2f7d" -"checksum want 0.2.0 (registry+https://github.com/rust-lang/crates.io-index)" = "b6395efa4784b027708f7451087e647ec73cc74f5d9bc2e418404248d679a230" -"checksum want 0.3.0 (registry+https://github.com/rust-lang/crates.io-index)" = "1ce8a968cb1cd110d136ff8b819a556d6fb6d919363c61534f6860c7eb172ba0" -"checksum wasi 0.10.0+wasi-snapshot-preview1 (registry+https://github.com/rust-lang/crates.io-index)" = "1a143597ca7c7793eff794def352d41792a93c481eb1042423ff7ff72ba2c31f" -"checksum wasi 0.9.0+wasi-snapshot-preview1 (registry+https://github.com/rust-lang/crates.io-index)" = "cccddf32554fecc6acb585f82a32a72e28b48f8c4c1883ddfeeeaa96f7d8e519" -"checksum wasm-bindgen 0.2.68 (registry+https://github.com/rust-lang/crates.io-index)" = "1ac64ead5ea5f05873d7c12b545865ca2b8d28adfc50a49b84770a3a97265d42" -"checksum wasm-bindgen-backend 0.2.68 (registry+https://github.com/rust-lang/crates.io-index)" = "f22b422e2a757c35a73774860af8e112bff612ce6cb604224e8e47641a9e4f68" -"checksum wasm-bindgen-futures 0.4.18 (registry+https://github.com/rust-lang/crates.io-index)" = "b7866cab0aa01de1edf8b5d7936938a7e397ee50ce24119aef3e1eaa3b6171da" -"checksum wasm-bindgen-macro 0.2.68 (registry+https://github.com/rust-lang/crates.io-index)" = "6b13312a745c08c469f0b292dd2fcd6411dba5f7160f593da6ef69b64e407038" -"checksum wasm-bindgen-macro-support 0.2.68 (registry+https://github.com/rust-lang/crates.io-index)" = "f249f06ef7ee334cc3b8ff031bfc11ec99d00f34d86da7498396dc1e3b1498fe" -"checksum wasm-bindgen-shared 0.2.68 (registry+https://github.com/rust-lang/crates.io-index)" = "1d649a3145108d7d3fbcde896a468d1bd636791823c9921135218ad89be08307" -"checksum wasm-bindgen-test 0.3.18 (registry+https://github.com/rust-lang/crates.io-index)" = "34d1cdc8b98a557f24733d50a1199c4b0635e465eecba9c45b214544da197f64" -"checksum wasm-bindgen-test-macro 0.3.18 (registry+https://github.com/rust-lang/crates.io-index)" = "e8fb9c67be7439ee8ab1b7db502a49c05e51e2835b66796c705134d9b8e1a585" -"checksum wasm-timer 0.2.5 (registry+https://github.com/rust-lang/crates.io-index)" = "be0ecb0db480561e9a7642b5d3e4187c128914e58aa84330b9493e3eb68c5e7f" -"checksum web-sys 0.3.45 (registry+https://github.com/rust-lang/crates.io-index)" = "4bf6ef87ad7ae8008e15a355ce696bed26012b7caa21605188cfd8214ab51e2d" -"checksum web3 0.11.0 (registry+https://github.com/rust-lang/crates.io-index)" = "9a681e8d15deced7c510db88c59133d2eafa7b6298b6e91b545e2a3fed93b3fe" -"checksum webpki 0.21.2 (registry+https://github.com/rust-lang/crates.io-index)" = "f1f50e1972865d6b1adb54167d1c8ed48606004c2c9d0ea5f1eeb34d95e863ef" -"checksum webpki-roots 0.18.0 (registry+https://github.com/rust-lang/crates.io-index)" = "91cd5736df7f12a964a5067a12c62fa38e1bd8080aff1f80bc29be7c80d19ab4" -"checksum webpki-roots 0.19.0 (registry+https://github.com/rust-lang/crates.io-index)" = "f8eff4b7516a57307f9349c64bf34caa34b940b66fed4b2fb3136cb7386e5739" -"checksum websocket 0.21.1 (registry+https://github.com/rust-lang/crates.io-index)" = "8c9faed2bff8af2ea6b9f8b917d3d00b467583f6781fe3def174a9e33c879703" -"checksum which 3.1.1 (registry+https://github.com/rust-lang/crates.io-index)" = "d011071ae14a2f6671d0b74080ae0cd8ebf3a6f8c9589a2cd45f23126fe29724" -"checksum winapi 0.2.8 (registry+https://github.com/rust-lang/crates.io-index)" = "167dc9d6949a9b857f3451275e911c3f44255842c1f7a76f33c55103a909087a" -"checksum winapi 0.3.9 (registry+https://github.com/rust-lang/crates.io-index)" = "5c839a674fcd7a98952e593242ea400abe93992746761e38641405d28b00f419" -"checksum winapi-build 0.1.1 (registry+https://github.com/rust-lang/crates.io-index)" = "2d315eee3b34aca4797b2da6b13ed88266e6d612562a0c46390af8299fc699bc" -"checksum winapi-i686-pc-windows-gnu 0.4.0 (registry+https://github.com/rust-lang/crates.io-index)" = "ac3b87c63620426dd9b991e5ce0329eff545bccbbb34f3be09ff6fb6ab51b7b6" -"checksum winapi-util 0.1.5 (registry+https://github.com/rust-lang/crates.io-index)" = "70ec6ce85bb158151cae5e5c87f95a8e97d2c0c4b001223f33a334e3ce5de178" -"checksum winapi-x86_64-pc-windows-gnu 0.4.0 (registry+https://github.com/rust-lang/crates.io-index)" = "712e227841d057c1ee1cd2fb22fa7e5a5461ae8e48fa2ca79ec42cfc1931183f" -"checksum winreg 0.7.0 (registry+https://github.com/rust-lang/crates.io-index)" = "0120db82e8a1e0b9fb3345a539c478767c0048d842860994d96113d5b667bd69" -"checksum ws 0.9.1 (registry+https://github.com/rust-lang/crates.io-index)" = "c51a2c47b5798ccc774ffb93ff536aec7c4275d722fd9c740c83cdd1af1f2d94" -"checksum ws2_32-sys 0.2.1 (registry+https://github.com/rust-lang/crates.io-index)" = "d59cefebd0c892fa2dd6de581e937301d8552cb44489cdff035c6187cb63fa5e" -"checksum x25519-dalek 0.6.0 (registry+https://github.com/rust-lang/crates.io-index)" = "637ff90c9540fa3073bb577e65033069e4bae7c79d49d74aa3ffdf5342a53217" -"checksum yaml-rust 0.4.4 (registry+https://github.com/rust-lang/crates.io-index)" = "39f0c922f1a334134dc2f7a8b67dc5d25f0735263feec974345ff706bcf20b0d" -"checksum zeroize 1.1.1 (registry+https://github.com/rust-lang/crates.io-index)" = "05f33972566adbd2d3588b0491eb94b98b43695c4ef897903470ede4f3f5a28a" -"checksum zeroize_derive 1.0.1 (registry+https://github.com/rust-lang/crates.io-index)" = "c3f369ddb18862aba61aa49bf31e74d29f0f162dec753063200e1dc084345d16" -"checksum zip 0.5.6 (registry+https://github.com/rust-lang/crates.io-index)" = "58287c28d78507f5f91f2a4cf1e8310e2c76fd4c6932f93ac60fd1ceb402db7d" + "bzip2", + "crc32fast", + "flate2", + "podio", + "time 0.1.44", +] diff --git a/Cargo.toml b/Cargo.toml index 82922f5a5f6..b8b2fdde765 100644 --- a/Cargo.toml +++ b/Cargo.toml @@ -7,8 +7,9 @@ members = [ "beacon_node/client", "beacon_node/eth1", "beacon_node/eth2_libp2p", + "beacon_node/http_api", + "beacon_node/http_metrics", "beacon_node/network", - "beacon_node/rest_api", "beacon_node/store", "beacon_node/timer", "beacon_node/websocket_server", @@ -21,6 +22,7 @@ members = [ "common/compare_fields_derive", "common/deposit_contract", "common/directory", + "common/eth2", "common/eth2_config", "common/eth2_interop_keypairs", "common/eth2_testnet_config", @@ -30,10 +32,9 @@ members = [ "common/lighthouse_version", "common/logging", "common/lru_cache", - "common/remote_beacon_node", - "common/rest_types", "common/slot_clock", "common/test_random_derive", + "common/warp_utils", "common/validator_dir", "consensus/cached_tree_hash", @@ -44,7 +45,6 @@ members = [ "consensus/ssz", "consensus/ssz_derive", "consensus/ssz_types", - "consensus/serde_hex", "consensus/serde_utils", "consensus/state_processing", "consensus/swap_or_not_shuffle", diff --git a/beacon_node/beacon_chain/Cargo.toml b/beacon_node/beacon_chain/Cargo.toml index 05ae819c49c..04e22f4268f 100644 --- a/beacon_node/beacon_chain/Cargo.toml +++ b/beacon_node/beacon_chain/Cargo.toml @@ -58,4 +58,3 @@ environment = { path = "../../lighthouse/environment" } bus = "2.2.3" derivative = "2.1.1" itertools = "0.9.0" -regex = "1.3.9" diff --git a/beacon_node/beacon_chain/src/attestation_verification.rs b/beacon_node/beacon_chain/src/attestation_verification.rs index 64803304441..32a08590207 100644 --- a/beacon_node/beacon_chain/src/attestation_verification.rs +++ b/beacon_node/beacon_chain/src/attestation_verification.rs @@ -28,8 +28,7 @@ use crate::{ beacon_chain::{ - ATTESTATION_CACHE_LOCK_TIMEOUT, HEAD_LOCK_TIMEOUT, MAXIMUM_GOSSIP_CLOCK_DISPARITY, - VALIDATOR_PUBKEY_CACHE_LOCK_TIMEOUT, + HEAD_LOCK_TIMEOUT, MAXIMUM_GOSSIP_CLOCK_DISPARITY, VALIDATOR_PUBKEY_CACHE_LOCK_TIMEOUT, }, metrics, observed_attestations::ObserveOutcome, @@ -38,12 +37,10 @@ use crate::{ }; use bls::verify_signature_sets; use proto_array::Block as ProtoBlock; -use slog::debug; use slot_clock::SlotClock; use state_processing::{ common::get_indexed_attestation, per_block_processing::errors::AttestationValidationError, - per_slot_processing, signature_sets::{ indexed_attestation_signature_set_from_pubkeys, signed_aggregate_selection_proof_signature_set, signed_aggregate_signature_set, @@ -53,7 +50,7 @@ use std::borrow::Cow; use tree_hash::TreeHash; use types::{ Attestation, BeaconCommittee, CommitteeIndex, Epoch, EthSpec, Hash256, IndexedAttestation, - RelativeEpoch, SelectionProof, SignedAggregateAndProof, Slot, SubnetId, + SelectionProof, SignedAggregateAndProof, Slot, SubnetId, }; /// Returned when an attestation was not successfully verified. It might not have been verified for @@ -267,6 +264,7 @@ pub struct VerifiedAggregatedAttestation { pub struct VerifiedUnaggregatedAttestation { attestation: Attestation, indexed_attestation: IndexedAttestation, + subnet_id: SubnetId, } /// Custom `Clone` implementation is to avoid the restrictive trait bounds applied by the usual derive @@ -276,6 +274,7 @@ impl Clone for VerifiedUnaggregatedAttestation { Self { attestation: self.attestation.clone(), indexed_attestation: self.indexed_attestation.clone(), + subnet_id: self.subnet_id, } } } @@ -428,6 +427,11 @@ impl VerifiedAggregatedAttestation { pub fn attestation(&self) -> &Attestation { &self.signed_aggregate.message.aggregate } + + /// Returns the underlying `signed_aggregate`. + pub fn aggregate(&self) -> &SignedAggregateAndProof { + &self.signed_aggregate + } } impl VerifiedUnaggregatedAttestation { @@ -438,7 +442,7 @@ impl VerifiedUnaggregatedAttestation { /// verify that it was received on the correct subnet. pub fn verify( attestation: Attestation, - subnet_id: SubnetId, + subnet_id: Option, chain: &BeaconChain, ) -> Result { let attestation_epoch = attestation.data.slot.epoch(T::EthSpec::slots_per_epoch()); @@ -513,13 +517,15 @@ impl VerifiedUnaggregatedAttestation { ) .map_err(BeaconChainError::from)?; - // Ensure the attestation is from the correct subnet. - if subnet_id != expected_subnet_id { - return Err(Error::InvalidSubnetId { - received: subnet_id, - expected: expected_subnet_id, - }); - } + // If a subnet was specified, ensure that subnet is correct. + if let Some(subnet_id) = subnet_id { + if subnet_id != expected_subnet_id { + return Err(Error::InvalidSubnetId { + received: subnet_id, + expected: expected_subnet_id, + }); + } + }; let validator_index = *indexed_attestation .attesting_indices @@ -564,6 +570,7 @@ impl VerifiedUnaggregatedAttestation { Ok(Self { attestation, indexed_attestation, + subnet_id: expected_subnet_id, }) } @@ -572,6 +579,11 @@ impl VerifiedUnaggregatedAttestation { chain.add_to_naive_aggregation_pool(self) } + /// Returns the correct subnet for the attestation. + pub fn subnet_id(&self) -> SubnetId { + self.subnet_id + } + /// Returns the wrapped `attestation`. pub fn attestation(&self) -> &Attestation { &self.attestation @@ -587,6 +599,7 @@ impl VerifiedUnaggregatedAttestation { } /// Returns `Ok(())` if the `attestation.data.beacon_block_root` is known to this chain. +/// You can use this `shuffling_id` to read from the shuffling cache. /// /// The block root may not be known for two reasons: /// @@ -615,6 +628,7 @@ fn verify_head_block_is_known( }); } } + Ok(block) } else { Err(Error::UnknownHeadBlock { @@ -770,7 +784,7 @@ type CommitteesPerSlot = u64; /// Returns the `indexed_attestation` and committee count per slot for the `attestation` using the /// public keys cached in the `chain`. -pub fn obtain_indexed_attestation_and_committees_per_slot( +fn obtain_indexed_attestation_and_committees_per_slot( chain: &BeaconChain, attestation: &Attestation, ) -> Result<(IndexedAttestation, CommitteesPerSlot), Error> { @@ -790,8 +804,8 @@ pub fn obtain_indexed_attestation_and_committees_per_slot( /// /// If the committee for `attestation` isn't found in the `shuffling_cache`, we will read a state /// from disk and then update the `shuffling_cache`. -pub fn map_attestation_committee<'a, T, F, R>( - chain: &'a BeaconChain, +fn map_attestation_committee( + chain: &BeaconChain, attestation: &Attestation, map_fn: F, ) -> Result @@ -809,104 +823,23 @@ where // processing an attestation that does not include our latest finalized block in its chain. // // We do not delay consideration for later, we simply drop the attestation. - let target_block = chain - .fork_choice - .read() - .get_block(&target.root) - .ok_or_else(|| Error::UnknownTargetRoot(target.root))?; - - // Obtain the shuffling cache, timing how long we wait. - let cache_wait_timer = - metrics::start_timer(&metrics::ATTESTATION_PROCESSING_SHUFFLING_CACHE_WAIT_TIMES); - - let mut shuffling_cache = chain - .shuffling_cache - .try_write_for(ATTESTATION_CACHE_LOCK_TIMEOUT) - .ok_or_else(|| BeaconChainError::AttestationCacheLockTimeout)?; - - metrics::stop_timer(cache_wait_timer); - - if let Some(committee_cache) = shuffling_cache.get(attestation_epoch, target.root) { - let committees_per_slot = committee_cache.committees_per_slot(); - committee_cache - .get_beacon_committee(attestation.data.slot, attestation.data.index) - .map(|committee| map_fn((committee, committees_per_slot))) - .unwrap_or_else(|| { - Err(Error::NoCommitteeForSlotAndIndex { - slot: attestation.data.slot, - index: attestation.data.index, - }) - }) - } else { - // Drop the shuffling cache to avoid holding the lock for any longer than - // required. - drop(shuffling_cache); - - debug!( - chain.log, - "Attestation processing cache miss"; - "attn_epoch" => attestation_epoch.as_u64(), - "target_block_epoch" => target_block.slot.epoch(T::EthSpec::slots_per_epoch()).as_u64(), - ); - - let state_read_timer = - metrics::start_timer(&metrics::ATTESTATION_PROCESSING_STATE_READ_TIMES); - - let mut state = chain - .store - .get_inconsistent_state_for_attestation_verification_only( - &target_block.state_root, - Some(target_block.slot), - ) - .map_err(BeaconChainError::from)? - .ok_or_else(|| BeaconChainError::MissingBeaconState(target_block.state_root))?; - - metrics::stop_timer(state_read_timer); - let state_skip_timer = - metrics::start_timer(&metrics::ATTESTATION_PROCESSING_STATE_SKIP_TIMES); - - while state.current_epoch() + 1 < attestation_epoch { - // Here we tell `per_slot_processing` to skip hashing the state and just - // use the zero hash instead. - // - // The state roots are not useful for the shuffling, so there's no need to - // compute them. - per_slot_processing(&mut state, Some(Hash256::zero()), &chain.spec) - .map_err(BeaconChainError::from)?; - } - - metrics::stop_timer(state_skip_timer); - let committee_building_timer = - metrics::start_timer(&metrics::ATTESTATION_PROCESSING_COMMITTEE_BUILDING_TIMES); - - let relative_epoch = RelativeEpoch::from_epoch(state.current_epoch(), attestation_epoch) - .map_err(BeaconChainError::IncorrectStateForAttestation)?; - - state - .build_committee_cache(relative_epoch, &chain.spec) - .map_err(BeaconChainError::from)?; - - let committee_cache = state - .committee_cache(relative_epoch) - .map_err(BeaconChainError::from)?; - - chain - .shuffling_cache - .try_write_for(ATTESTATION_CACHE_LOCK_TIMEOUT) - .ok_or_else(|| BeaconChainError::AttestationCacheLockTimeout)? - .insert(attestation_epoch, target.root, committee_cache); - - metrics::stop_timer(committee_building_timer); - - let committees_per_slot = committee_cache.committees_per_slot(); - committee_cache - .get_beacon_committee(attestation.data.slot, attestation.data.index) - .map(|committee| map_fn((committee, committees_per_slot))) - .unwrap_or_else(|| { - Err(Error::NoCommitteeForSlotAndIndex { - slot: attestation.data.slot, - index: attestation.data.index, - }) - }) + if !chain.fork_choice.read().contains_block(&target.root) { + return Err(Error::UnknownTargetRoot(target.root)); } + + chain + .with_committee_cache(target.root, attestation_epoch, |committee_cache| { + let committees_per_slot = committee_cache.committees_per_slot(); + + Ok(committee_cache + .get_beacon_committee(attestation.data.slot, attestation.data.index) + .map(|committee| map_fn((committee, committees_per_slot))) + .unwrap_or_else(|| { + Err(Error::NoCommitteeForSlotAndIndex { + slot: attestation.data.slot, + index: attestation.data.index, + }) + })) + }) + .map_err(BeaconChainError::from)? } diff --git a/beacon_node/beacon_chain/src/beacon_chain.rs b/beacon_node/beacon_chain/src/beacon_chain.rs index 1caaec5fea4..3bf5ae282d4 100644 --- a/beacon_node/beacon_chain/src/beacon_chain.rs +++ b/beacon_node/beacon_chain/src/beacon_chain.rs @@ -21,7 +21,7 @@ use crate::observed_block_producers::ObservedBlockProducers; use crate::observed_operations::{ObservationOutcome, ObservedOperations}; use crate::persisted_beacon_chain::PersistedBeaconChain; use crate::persisted_fork_choice::PersistedForkChoice; -use crate::shuffling_cache::ShufflingCache; +use crate::shuffling_cache::{BlockShufflingIds, ShufflingCache}; use crate::snapshot_cache::SnapshotCache; use crate::timeout_rw_lock::TimeoutRwLock; use crate::validator_pubkey_cache::ValidatorPubkeyCache; @@ -31,7 +31,6 @@ use fork_choice::ForkChoice; use itertools::process_results; use operation_pool::{OperationPool, PersistedOperationPool}; use parking_lot::RwLock; -use regex::bytes::Regex; use slog::{crit, debug, error, info, trace, warn, Logger}; use slot_clock::SlotClock; use state_processing::{ @@ -201,6 +200,8 @@ pub struct BeaconChain { pub(crate) canonical_head: TimeoutRwLock>, /// The root of the genesis block. pub genesis_block_root: Hash256, + /// The root of the genesis state. + pub genesis_state_root: Hash256, /// The root of the list of genesis validators, used during syncing. pub genesis_validators_root: Hash256, @@ -459,6 +460,30 @@ impl BeaconChain { } } + /// Returns the block at the given slot, if any. Only returns blocks in the canonical chain. + /// + /// ## Errors + /// + /// May return a database error. + pub fn state_root_at_slot(&self, slot: Slot) -> Result, Error> { + process_results(self.rev_iter_state_roots()?, |mut iter| { + iter.find(|(_, this_slot)| *this_slot == slot) + .map(|(root, _)| root) + }) + } + + /// Returns the block root at the given slot, if any. Only returns roots in the canonical chain. + /// + /// ## Errors + /// + /// May return a database error. + pub fn block_root_at_slot(&self, slot: Slot) -> Result, Error> { + process_results(self.rev_iter_block_roots()?, |mut iter| { + iter.find(|(_, this_slot)| *this_slot == slot) + .map(|(root, _)| root) + }) + } + /// Returns the block at the given root, if any. /// /// ## Errors @@ -506,6 +531,30 @@ impl BeaconChain { f(&head_lock) } + /// Returns the beacon block root at the head of the canonical chain. + /// + /// See `Self::head` for more information. + pub fn head_beacon_block_root(&self) -> Result { + self.with_head(|s| Ok(s.beacon_block_root)) + } + + /// Returns the beacon block at the head of the canonical chain. + /// + /// See `Self::head` for more information. + pub fn head_beacon_block(&self) -> Result, Error> { + self.with_head(|s| Ok(s.beacon_block.clone())) + } + + /// Returns the beacon state at the head of the canonical chain. + /// + /// See `Self::head` for more information. + pub fn head_beacon_state(&self) -> Result, Error> { + self.with_head(|s| { + Ok(s.beacon_state + .clone_with(CloneConfig::committee_caches_only())) + }) + } + /// Returns info representing the head block and state. /// /// A summarized version of `Self::head` that involves less cloning. @@ -719,46 +768,20 @@ impl BeaconChain { .map_err(Into::into) } - /// Returns the attestation slot and committee index for a given validator index. + /// Returns the attestation duties for a given validator index. /// /// Information is read from the current state, so only information from the present and prior /// epoch is available. - pub fn validator_attestation_slot_and_index( + pub fn validator_attestation_duty( &self, validator_index: usize, epoch: Epoch, - ) -> Result, Error> { - let as_epoch = |slot: Slot| slot.epoch(T::EthSpec::slots_per_epoch()); - let head_state = &self.head()?.beacon_state; - - let mut state = if epoch == as_epoch(head_state.slot) { - self.head()?.beacon_state - } else { - // The block proposer shuffling is not affected by the state roots, so we don't need to - // calculate them. - self.state_at_slot( - epoch.start_slot(T::EthSpec::slots_per_epoch()), - StateSkipConfig::WithoutStateRoots, - )? - }; - - state.build_committee_cache(RelativeEpoch::Current, &self.spec)?; + ) -> Result, Error> { + let head_block_root = self.head_beacon_block_root()?; - if as_epoch(state.slot) != epoch { - return Err(Error::InvariantViolated(format!( - "Epochs in consistent in attestation duties lookup: state: {}, requested: {}", - as_epoch(state.slot), - epoch - ))); - } - - if let Some(attestation_duty) = - state.get_attestation_duties(validator_index, RelativeEpoch::Current)? - { - Ok(Some((attestation_duty.slot, attestation_duty.index))) - } else { - Ok(None) - } + self.with_committee_cache(head_block_root, epoch, |committee_cache| { + Ok(committee_cache.get_attestation_duties(validator_index)) + }) } /// Returns an aggregated `Attestation`, if any, that has a matching `attestation.data`. @@ -767,11 +790,22 @@ impl BeaconChain { pub fn get_aggregated_attestation( &self, data: &AttestationData, - ) -> Result>, Error> { + ) -> Option> { + self.naive_aggregation_pool.read().get(data) + } + + /// Returns an aggregated `Attestation`, if any, that has a matching + /// `attestation.data.tree_hash_root()`. + /// + /// The attestation will be obtained from `self.naive_aggregation_pool`. + pub fn get_aggregated_attestation_by_slot_and_root( + &self, + slot: Slot, + attestation_data_root: &Hash256, + ) -> Option> { self.naive_aggregation_pool .read() - .get(data) - .map_err(Into::into) + .get_by_slot_and_root(slot, attestation_data_root) } /// Produce an unaggregated `Attestation` that is valid for the given `slot` and `index`. @@ -898,7 +932,7 @@ impl BeaconChain { pub fn verify_unaggregated_attestation_for_gossip( &self, attestation: Attestation, - subnet_id: SubnetId, + subnet_id: Option, ) -> Result, AttestationError> { metrics::inc_counter(&metrics::UNAGGREGATED_ATTESTATION_PROCESSING_REQUESTS); let _timer = @@ -1320,11 +1354,7 @@ impl BeaconChain { block: SignedBeaconBlock, ) -> Result, BlockError> { let slot = block.message.slot; - #[allow(clippy::invalid_regex)] - let re = Regex::new("\\p{C}").expect("regex is valid"); - let graffiti_string = - String::from_utf8_lossy(&re.replace_all(&block.message.body.graffiti[..], &b""[..])) - .to_string(); + let graffiti_string = block.message.body.graffiti.as_utf8_lossy(); match GossipVerifiedBlock::new(block, self) { Ok(verified) => { @@ -1449,8 +1479,7 @@ impl BeaconChain { ) -> Result> { let signed_block = fully_verified_block.block; let block_root = fully_verified_block.block_root; - let state = fully_verified_block.state; - let parent_block = fully_verified_block.parent_block; + let mut state = fully_verified_block.state; let current_slot = self.slot()?; let mut ops = fully_verified_block.intermediate_states; @@ -1482,29 +1511,25 @@ impl BeaconChain { .ok_or_else(|| Error::ValidatorPubkeyCacheLockTimeout)? .import_new_pubkeys(&state)?; - // If the imported block is in the previous or current epochs (according to the - // wall-clock), check to see if this is the first block of the epoch. If so, add the - // committee to the shuffling cache. - if state.current_epoch() + 1 >= self.epoch()? - && parent_block.slot().epoch(T::EthSpec::slots_per_epoch()) != state.current_epoch() - { - let mut shuffling_cache = self - .shuffling_cache - .try_write_for(ATTESTATION_CACHE_LOCK_TIMEOUT) - .ok_or_else(|| Error::AttestationCacheLockTimeout)?; - - let committee_cache = state.committee_cache(RelativeEpoch::Current)?; + // For the current and next epoch of this state, ensure we have the shuffling from this + // block in our cache. + for relative_epoch in &[RelativeEpoch::Current, RelativeEpoch::Next] { + let shuffling_id = ShufflingId::new(block_root, &state, *relative_epoch)?; - let epoch_start_slot = state - .current_epoch() - .start_slot(T::EthSpec::slots_per_epoch()); - let target_root = if state.slot == epoch_start_slot { - block_root - } else { - *state.get_block_root(epoch_start_slot)? - }; - - shuffling_cache.insert(state.current_epoch(), target_root, committee_cache); + let shuffling_is_cached = self + .shuffling_cache + .try_read_for(ATTESTATION_CACHE_LOCK_TIMEOUT) + .ok_or_else(|| Error::AttestationCacheLockTimeout)? + .contains(&shuffling_id); + + if !shuffling_is_cached { + state.build_committee_cache(*relative_epoch, &self.spec)?; + let committee_cache = state.committee_cache(*relative_epoch)?; + self.shuffling_cache + .try_write_for(ATTESTATION_CACHE_LOCK_TIMEOUT) + .ok_or_else(|| Error::AttestationCacheLockTimeout)? + .insert(shuffling_id, committee_cache); + } } let mut fork_choice = self.fork_choice.write(); @@ -1992,6 +2017,129 @@ impl BeaconChain { Ok(()) } + /// Runs the `map_fn` with the committee cache for `shuffling_epoch` from the chain with head + /// `head_block_root`. + /// + /// It's not necessary that `head_block_root` matches our current view of the chain, it can be + /// any block that is: + /// + /// - Known to us. + /// - The finalized block or a descendant of the finalized block. + /// + /// It would be quite common for attestation verification operations to use a `head_block_root` + /// that differs from our view of the head. + /// + /// ## Important + /// + /// This function is **not** suitable for determining proposer duties. + /// + /// ## Notes + /// + /// This function exists in this odd "map" pattern because efficiently obtaining a committee + /// can be complex. It might involve reading straight from the `beacon_chain.shuffling_cache` + /// or it might involve reading it from a state from the DB. Due to the complexities of + /// `RwLock`s on the shuffling cache, a simple `Cow` isn't suitable here. + /// + /// If the committee for `(head_block_root, shuffling_epoch)` isn't found in the + /// `shuffling_cache`, we will read a state from disk and then update the `shuffling_cache`. + pub(crate) fn with_committee_cache( + &self, + head_block_root: Hash256, + shuffling_epoch: Epoch, + map_fn: F, + ) -> Result + where + F: Fn(&CommitteeCache) -> Result, + { + let head_block = self + .fork_choice + .read() + .get_block(&head_block_root) + .ok_or_else(|| Error::MissingBeaconBlock(head_block_root))?; + + let shuffling_id = BlockShufflingIds { + current: head_block.current_epoch_shuffling_id.clone(), + next: head_block.next_epoch_shuffling_id.clone(), + block_root: head_block.root, + } + .id_for_epoch(shuffling_epoch) + .ok_or_else(|| Error::InvalidShufflingId { + shuffling_epoch, + head_block_epoch: head_block.slot.epoch(T::EthSpec::slots_per_epoch()), + })?; + + // Obtain the shuffling cache, timing how long we wait. + let cache_wait_timer = + metrics::start_timer(&metrics::ATTESTATION_PROCESSING_SHUFFLING_CACHE_WAIT_TIMES); + + let mut shuffling_cache = self + .shuffling_cache + .try_write_for(ATTESTATION_CACHE_LOCK_TIMEOUT) + .ok_or_else(|| Error::AttestationCacheLockTimeout)?; + + metrics::stop_timer(cache_wait_timer); + + if let Some(committee_cache) = shuffling_cache.get(&shuffling_id) { + map_fn(committee_cache) + } else { + // Drop the shuffling cache to avoid holding the lock for any longer than + // required. + drop(shuffling_cache); + + debug!( + self.log, + "Committee cache miss"; + "shuffling_epoch" => shuffling_epoch.as_u64(), + "head_block_root" => head_block_root.to_string(), + ); + + let state_read_timer = + metrics::start_timer(&metrics::ATTESTATION_PROCESSING_STATE_READ_TIMES); + + let mut state = self + .store + .get_inconsistent_state_for_attestation_verification_only( + &head_block.state_root, + Some(head_block.slot), + )? + .ok_or_else(|| Error::MissingBeaconState(head_block.state_root))?; + + metrics::stop_timer(state_read_timer); + let state_skip_timer = + metrics::start_timer(&metrics::ATTESTATION_PROCESSING_STATE_SKIP_TIMES); + + while state.current_epoch() + 1 < shuffling_epoch { + // Here we tell `per_slot_processing` to skip hashing the state and just + // use the zero hash instead. + // + // The state roots are not useful for the shuffling, so there's no need to + // compute them. + per_slot_processing(&mut state, Some(Hash256::zero()), &self.spec) + .map_err(Error::from)?; + } + + metrics::stop_timer(state_skip_timer); + let committee_building_timer = + metrics::start_timer(&metrics::ATTESTATION_PROCESSING_COMMITTEE_BUILDING_TIMES); + + let relative_epoch = RelativeEpoch::from_epoch(state.current_epoch(), shuffling_epoch) + .map_err(Error::IncorrectStateForAttestation)?; + + state.build_committee_cache(relative_epoch, &self.spec)?; + + let committee_cache = state.committee_cache(relative_epoch)?; + + self.shuffling_cache + .try_write_for(ATTESTATION_CACHE_LOCK_TIMEOUT) + .ok_or_else(|| Error::AttestationCacheLockTimeout)? + .insert(shuffling_id, committee_cache); + + metrics::stop_timer(committee_building_timer); + + map_fn(&committee_cache) + } + } + /// Returns `true` if the given block root has not been processed. pub fn is_new_block_root(&self, beacon_block_root: &Hash256) -> Result { Ok(!self diff --git a/beacon_node/beacon_chain/src/builder.rs b/beacon_node/beacon_chain/src/builder.rs index ac9d1c4b1fd..ff47c7a2b81 100644 --- a/beacon_node/beacon_chain/src/builder.rs +++ b/beacon_node/beacon_chain/src/builder.rs @@ -374,8 +374,13 @@ where let fc_store = BeaconForkChoiceStore::get_forkchoice_store(store, &genesis); - let fork_choice = ForkChoice::from_genesis(fc_store, &genesis.beacon_block.message) - .map_err(|e| format!("Unable to build initialize ForkChoice: {:?}", e))?; + let fork_choice = ForkChoice::from_genesis( + fc_store, + genesis.beacon_block_root, + &genesis.beacon_block.message, + &genesis.beacon_state, + ) + .map_err(|e| format!("Unable to build initialize ForkChoice: {:?}", e))?; self.fork_choice = Some(fork_choice); self.genesis_time = Some(genesis.beacon_state.genesis_time); @@ -561,6 +566,7 @@ where observed_attester_slashings: <_>::default(), eth1_chain: self.eth1_chain, genesis_validators_root: canonical_head.beacon_state.genesis_validators_root, + genesis_state_root: canonical_head.beacon_state_root, canonical_head: TimeoutRwLock::new(canonical_head.clone()), genesis_block_root, fork_choice: RwLock::new(fork_choice), diff --git a/beacon_node/beacon_chain/src/errors.rs b/beacon_node/beacon_chain/src/errors.rs index 96f1c9a8411..6eb7bceeb21 100644 --- a/beacon_node/beacon_chain/src/errors.rs +++ b/beacon_node/beacon_chain/src/errors.rs @@ -83,6 +83,10 @@ pub enum BeaconChainError { ObservedBlockProducersError(ObservedBlockProducersError), PruningError(PruningError), ArithError(ArithError), + InvalidShufflingId { + shuffling_epoch: Epoch, + head_block_epoch: Epoch, + }, } easy_from_to!(SlotProcessingError, BeaconChainError); diff --git a/beacon_node/beacon_chain/src/naive_aggregation_pool.rs b/beacon_node/beacon_chain/src/naive_aggregation_pool.rs index c561141a1de..247f613a96d 100644 --- a/beacon_node/beacon_chain/src/naive_aggregation_pool.rs +++ b/beacon_node/beacon_chain/src/naive_aggregation_pool.rs @@ -1,7 +1,9 @@ use crate::metrics; use std::collections::HashMap; -use types::{Attestation, AttestationData, EthSpec, Slot}; +use tree_hash::TreeHash; +use types::{Attestation, AttestationData, EthSpec, Hash256, Slot}; +type AttestationDataRoot = Hash256; /// The number of slots that will be stored in the pool. /// /// For example, if `SLOTS_RETAINED == 3` and the pool is pruned at slot `6`, then all attestations @@ -53,7 +55,7 @@ pub enum Error { /// A collection of `Attestation` objects, keyed by their `attestation.data`. Enforces that all /// `attestation` are from the same slot. struct AggregatedAttestationMap { - map: HashMap>, + map: HashMap>, } impl AggregatedAttestationMap { @@ -87,7 +89,9 @@ impl AggregatedAttestationMap { return Err(Error::MoreThanOneAggregationBitSet(set_bits.len())); } - if let Some(existing_attestation) = self.map.get_mut(&a.data) { + let attestation_data_root = a.data.tree_hash_root(); + + if let Some(existing_attestation) = self.map.get_mut(&attestation_data_root) { if existing_attestation .aggregation_bits .get(committee_index) @@ -107,7 +111,7 @@ impl AggregatedAttestationMap { )); } - self.map.insert(a.data.clone(), a.clone()); + self.map.insert(attestation_data_root, a.clone()); Ok(InsertOutcome::NewAttestationData { committee_index }) } } @@ -115,8 +119,13 @@ impl AggregatedAttestationMap { /// Returns an aggregated `Attestation` with the given `data`, if any. /// /// The given `a.data.slot` must match the slot that `self` was initialized with. - pub fn get(&self, data: &AttestationData) -> Result>, Error> { - Ok(self.map.get(data).cloned()) + pub fn get(&self, data: &AttestationData) -> Option> { + self.map.get(&data.tree_hash_root()).cloned() + } + + /// Returns an aggregated `Attestation` with the given `root`, if any. + pub fn get_by_root(&self, root: &AttestationDataRoot) -> Option<&Attestation> { + self.map.get(root) } /// Iterate all attestations in `self`. @@ -220,12 +229,19 @@ impl NaiveAggregationPool { } /// Returns an aggregated `Attestation` with the given `data`, if any. - pub fn get(&self, data: &AttestationData) -> Result>, Error> { + pub fn get(&self, data: &AttestationData) -> Option> { + self.maps.get(&data.slot).and_then(|map| map.get(data)) + } + + /// Returns an aggregated `Attestation` with the given `data`, if any. + pub fn get_by_slot_and_root( + &self, + slot: Slot, + root: &AttestationDataRoot, + ) -> Option> { self.maps - .iter() - .find(|(slot, _map)| **slot == data.slot) - .map(|(_slot, map)| map.get(data)) - .unwrap_or_else(|| Ok(None)) + .get(&slot) + .and_then(|map| map.get_by_root(root).cloned()) } /// Iterate all attestations in all slots of `self`. @@ -338,8 +354,7 @@ mod tests { let retrieved = pool .get(&a.data) - .expect("should not error while getting attestation") - .expect("should get an attestation"); + .expect("should not error while getting attestation"); assert_eq!( retrieved, a, "retrieved attestation should equal the one inserted" @@ -378,8 +393,7 @@ mod tests { let retrieved = pool .get(&a_0.data) - .expect("should not error while getting attestation") - .expect("should get an attestation"); + .expect("should not error while getting attestation"); let mut a_01 = a_0.clone(); a_01.aggregate(&a_1); @@ -408,8 +422,7 @@ mod tests { assert_eq!( pool.get(&a_0.data) - .expect("should not error while getting attestation") - .expect("should get an attestation"), + .expect("should not error while getting attestation"), retrieved, "should not have aggregated different attestation data" ); diff --git a/beacon_node/beacon_chain/src/shuffling_cache.rs b/beacon_node/beacon_chain/src/shuffling_cache.rs index d8b6e8706e1..b76adf05e64 100644 --- a/beacon_node/beacon_chain/src/shuffling_cache.rs +++ b/beacon_node/beacon_chain/src/shuffling_cache.rs @@ -1,6 +1,6 @@ use crate::metrics; use lru::LruCache; -use types::{beacon_state::CommitteeCache, Epoch, Hash256}; +use types::{beacon_state::CommitteeCache, Epoch, Hash256, ShufflingId}; /// The size of the LRU cache that stores committee caches for quicker verification. /// @@ -14,7 +14,7 @@ const CACHE_SIZE: usize = 16; /// It has been named `ShufflingCache` because `CommitteeCacheCache` is a bit weird and looks like /// a find/replace error. pub struct ShufflingCache { - cache: LruCache<(Epoch, Hash256), CommitteeCache>, + cache: LruCache, } impl ShufflingCache { @@ -24,8 +24,8 @@ impl ShufflingCache { } } - pub fn get(&mut self, epoch: Epoch, root: Hash256) -> Option<&CommitteeCache> { - let opt = self.cache.get(&(epoch, root)); + pub fn get(&mut self, key: &ShufflingId) -> Option<&CommitteeCache> { + let opt = self.cache.get(key); if opt.is_some() { metrics::inc_counter(&metrics::SHUFFLING_CACHE_HITS); @@ -36,11 +36,37 @@ impl ShufflingCache { opt } - pub fn insert(&mut self, epoch: Epoch, root: Hash256, committee_cache: &CommitteeCache) { - let key = (epoch, root); + pub fn contains(&self, key: &ShufflingId) -> bool { + self.cache.contains(key) + } + pub fn insert(&mut self, key: ShufflingId, committee_cache: &CommitteeCache) { if !self.cache.contains(&key) { self.cache.put(key, committee_cache.clone()); } } } + +/// Contains the shuffling IDs for a beacon block. +pub struct BlockShufflingIds { + pub current: ShufflingId, + pub next: ShufflingId, + pub block_root: Hash256, +} + +impl BlockShufflingIds { + /// Returns the shuffling ID for the given epoch. + /// + /// Returns `None` if `epoch` is prior to `self.current.shuffling_epoch`. + pub fn id_for_epoch(&self, epoch: Epoch) -> Option { + if epoch == self.current.shuffling_epoch { + Some(self.current.clone()) + } else if epoch == self.next.shuffling_epoch { + Some(self.next.clone()) + } else if epoch > self.next.shuffling_epoch { + Some(ShufflingId::from_components(epoch, self.block_root)) + } else { + None + } + } +} diff --git a/beacon_node/beacon_chain/src/test_utils.rs b/beacon_node/beacon_chain/src/test_utils.rs index 8690c2e8d2d..2bad5f892e5 100644 --- a/beacon_node/beacon_chain/src/test_utils.rs +++ b/beacon_node/beacon_chain/src/test_utils.rs @@ -26,9 +26,11 @@ use store::{config::StoreConfig, BlockReplay, HotColdDB, ItemStore, LevelDB, Mem use tempfile::{tempdir, TempDir}; use tree_hash::TreeHash; use types::{ - AggregateSignature, Attestation, BeaconState, BeaconStateHash, ChainSpec, Domain, Epoch, - EthSpec, Hash256, Keypair, SelectionProof, SignedAggregateAndProof, SignedBeaconBlock, - SignedBeaconBlockHash, SignedRoot, Slot, SubnetId, + AggregateSignature, Attestation, AttestationData, AttesterSlashing, BeaconState, + BeaconStateHash, ChainSpec, Checkpoint, Domain, Epoch, EthSpec, Hash256, IndexedAttestation, + Keypair, ProposerSlashing, SelectionProof, SignedAggregateAndProof, SignedBeaconBlock, + SignedBeaconBlockHash, SignedRoot, SignedVoluntaryExit, Slot, SubnetId, VariableList, + VoluntaryExit, }; pub use types::test_utils::generate_deterministic_keypairs; @@ -129,7 +131,7 @@ impl BeaconChainHarness> { let decorator = slog_term::PlainDecorator::new(slog_term::TestStdoutWriter); let drain = slog_term::FullFormat::new(decorator).build(); - let debug_level = slog::LevelFilter::new(drain, slog::Level::Debug); + let debug_level = slog::LevelFilter::new(drain, slog::Level::Critical); let log = slog::Logger::root(std::sync::Mutex::new(debug_level).fuse(), o!()); let config = StoreConfig::default(); @@ -193,7 +195,7 @@ impl BeaconChainHarness> { let decorator = slog_term::PlainDecorator::new(slog_term::TestStdoutWriter); let drain = slog_term::FullFormat::new(decorator).build(); - let debug_level = slog::LevelFilter::new(drain, slog::Level::Debug); + let debug_level = slog::LevelFilter::new(drain, slog::Level::Critical); let log = slog::Logger::root(std::sync::Mutex::new(debug_level).fuse(), o!()); let store = HotColdDB::open_ephemeral(config, spec.clone(), log.clone()).unwrap(); @@ -238,7 +240,7 @@ impl BeaconChainHarness> { let decorator = slog_term::PlainDecorator::new(slog_term::TestStdoutWriter); let drain = slog_term::FullFormat::new(decorator).build(); - let debug_level = slog::LevelFilter::new(drain, slog::Level::Debug); + let debug_level = slog::LevelFilter::new(drain, slog::Level::Critical); let log = slog::Logger::root(std::sync::Mutex::new(debug_level).fuse(), o!()); let chain = BeaconChainBuilder::new(eth_spec_instance) @@ -397,7 +399,7 @@ where // If we produce two blocks for the same slot, they hash up to the same value and // BeaconChain errors out with `BlockIsAlreadyKnown`. Vary the graffiti so that we produce // different blocks each time. - self.chain.set_graffiti(self.rng.gen::<[u8; 32]>()); + self.chain.set_graffiti(self.rng.gen::<[u8; 32]>().into()); let randao_reveal = { let epoch = slot.epoch(E::slots_per_epoch()); @@ -442,8 +444,8 @@ where let committee_count = state.get_committee_count_at_slot(state.slot).unwrap(); state - .get_beacon_committees_at_slot(state.slot) - .unwrap() + .get_beacon_committees_at_slot(attestation_slot) + .expect("should get committees") .iter() .map(|bc| { bc.committee @@ -570,7 +572,6 @@ where let aggregate = self .chain .get_aggregated_attestation(&attestation.data) - .unwrap() .unwrap_or_else(|| { committee_attestations.iter().skip(1).fold(attestation.clone(), |mut agg, (att, _)| { agg.aggregate(att); @@ -601,6 +602,94 @@ where .collect() } + pub fn make_attester_slashing(&self, validator_indices: Vec) -> AttesterSlashing { + let mut attestation_1 = IndexedAttestation { + attesting_indices: VariableList::new(validator_indices).unwrap(), + data: AttestationData { + slot: Slot::new(0), + index: 0, + beacon_block_root: Hash256::zero(), + target: Checkpoint { + root: Hash256::zero(), + epoch: Epoch::new(0), + }, + source: Checkpoint { + root: Hash256::zero(), + epoch: Epoch::new(0), + }, + }, + signature: AggregateSignature::infinity(), + }; + + let mut attestation_2 = attestation_1.clone(); + attestation_2.data.index += 1; + + for attestation in &mut [&mut attestation_1, &mut attestation_2] { + for &i in &attestation.attesting_indices { + let sk = &self.validators_keypairs[i as usize].sk; + + let fork = self.chain.head_info().unwrap().fork; + let genesis_validators_root = self.chain.genesis_validators_root; + + let domain = self.chain.spec.get_domain( + attestation.data.target.epoch, + Domain::BeaconAttester, + &fork, + genesis_validators_root, + ); + let message = attestation.data.signing_root(domain); + + attestation.signature.add_assign(&sk.sign(message)); + } + } + + AttesterSlashing { + attestation_1, + attestation_2, + } + } + + pub fn make_proposer_slashing(&self, validator_index: u64) -> ProposerSlashing { + let mut block_header_1 = self + .chain + .head_beacon_block() + .unwrap() + .message + .block_header(); + block_header_1.proposer_index = validator_index; + + let mut block_header_2 = block_header_1.clone(); + block_header_2.state_root = Hash256::zero(); + + let sk = &self.validators_keypairs[validator_index as usize].sk; + let fork = self.chain.head_info().unwrap().fork; + let genesis_validators_root = self.chain.genesis_validators_root; + + let mut signed_block_headers = vec![block_header_1, block_header_2] + .into_iter() + .map(|block_header| { + block_header.sign::(&sk, &fork, genesis_validators_root, &self.chain.spec) + }) + .collect::>(); + + ProposerSlashing { + signed_header_2: signed_block_headers.remove(1), + signed_header_1: signed_block_headers.remove(0), + } + } + + pub fn make_voluntary_exit(&self, validator_index: u64, epoch: Epoch) -> SignedVoluntaryExit { + let sk = &self.validators_keypairs[validator_index as usize].sk; + let fork = self.chain.head_info().unwrap().fork; + let genesis_validators_root = self.chain.genesis_validators_root; + + VoluntaryExit { + epoch, + validator_index, + } + .sign(sk, &fork, genesis_validators_root, &self.chain.spec) + } + pub fn process_block(&self, slot: Slot, block: SignedBeaconBlock) -> SignedBeaconBlockHash { assert_eq!(self.chain.slot().unwrap(), slot); let block_hash: SignedBeaconBlockHash = self.chain.process_block(block).unwrap().into(); @@ -612,7 +701,10 @@ where for (unaggregated_attestations, maybe_signed_aggregate) in attestations.into_iter() { for (attestation, subnet_id) in unaggregated_attestations { self.chain - .verify_unaggregated_attestation_for_gossip(attestation.clone(), subnet_id) + .verify_unaggregated_attestation_for_gossip( + attestation.clone(), + Some(subnet_id), + ) .unwrap() .add_to_pool(&self.chain) .unwrap(); diff --git a/beacon_node/beacon_chain/tests/attestation_verification.rs b/beacon_node/beacon_chain/tests/attestation_verification.rs index 937850751c3..35c87c0d97f 100644 --- a/beacon_node/beacon_chain/tests/attestation_verification.rs +++ b/beacon_node/beacon_chain/tests/attestation_verification.rs @@ -570,7 +570,7 @@ fn unaggregated_gossip_verification() { matches!( harness .chain - .verify_unaggregated_attestation_for_gossip($attn_getter, $subnet_getter) + .verify_unaggregated_attestation_for_gossip($attn_getter, Some($subnet_getter)) .err() .expect(&format!( "{} should error during verify_unaggregated_attestation_for_gossip", @@ -837,7 +837,7 @@ fn unaggregated_gossip_verification() { harness .chain - .verify_unaggregated_attestation_for_gossip(valid_attestation.clone(), subnet_id) + .verify_unaggregated_attestation_for_gossip(valid_attestation.clone(), Some(subnet_id)) .expect("valid attestation should be verified"); /* @@ -926,6 +926,6 @@ fn attestation_that_skips_epochs() { harness .chain - .verify_unaggregated_attestation_for_gossip(attestation, subnet_id) + .verify_unaggregated_attestation_for_gossip(attestation, Some(subnet_id)) .expect("should gossip verify attestation that skips slots"); } diff --git a/beacon_node/beacon_chain/tests/store_tests.rs b/beacon_node/beacon_chain/tests/store_tests.rs index caa2f9d6cfc..e9006a6268d 100644 --- a/beacon_node/beacon_chain/tests/store_tests.rs +++ b/beacon_node/beacon_chain/tests/store_tests.rs @@ -326,7 +326,7 @@ fn epoch_boundary_state_attestation_processing() { let res = harness .chain - .verify_unaggregated_attestation_for_gossip(attestation.clone(), subnet_id); + .verify_unaggregated_attestation_for_gossip(attestation.clone(), Some(subnet_id)); let current_slot = harness.chain.slot().expect("should get slot"); let expected_attestation_slot = attestation.data.slot; diff --git a/beacon_node/beacon_chain/tests/tests.rs b/beacon_node/beacon_chain/tests/tests.rs index 12f1c4364a4..721eb409167 100644 --- a/beacon_node/beacon_chain/tests/tests.rs +++ b/beacon_node/beacon_chain/tests/tests.rs @@ -463,7 +463,7 @@ fn attestations_with_increasing_slots() { for (attestation, subnet_id) in attestations.into_iter().flatten() { let res = harness .chain - .verify_unaggregated_attestation_for_gossip(attestation.clone(), subnet_id); + .verify_unaggregated_attestation_for_gossip(attestation.clone(), Some(subnet_id)); let current_slot = harness.chain.slot().expect("should get slot"); let expected_attestation_slot = attestation.data.slot; diff --git a/beacon_node/client/Cargo.toml b/beacon_node/client/Cargo.toml index ba98eb946d4..797d7adb430 100644 --- a/beacon_node/client/Cargo.toml +++ b/beacon_node/client/Cargo.toml @@ -14,7 +14,6 @@ store = { path = "../store" } network = { path = "../network" } timer = { path = "../timer" } eth2_libp2p = { path = "../eth2_libp2p" } -rest_api = { path = "../rest_api" } parking_lot = "0.11.0" websocket_server = { path = "../websocket_server" } prometheus = "0.9.0" @@ -42,3 +41,5 @@ lighthouse_metrics = { path = "../../common/lighthouse_metrics" } time = "0.2.16" bus = "2.2.3" directory = {path = "../../common/directory"} +http_api = { path = "../http_api" } +http_metrics = { path = "../http_metrics" } diff --git a/beacon_node/client/src/builder.rs b/beacon_node/client/src/builder.rs index 15cd97ea8e4..05cc6aa6d7b 100644 --- a/beacon_node/client/src/builder.rs +++ b/beacon_node/client/src/builder.rs @@ -13,15 +13,14 @@ use beacon_chain::{ use bus::Bus; use environment::RuntimeContext; use eth1::{Config as Eth1Config, Service as Eth1Service}; -use eth2_config::Eth2Config; use eth2_libp2p::NetworkGlobals; use genesis::{interop_genesis_state, Eth1GenesisService}; use network::{NetworkConfig, NetworkMessage, NetworkService}; use parking_lot::Mutex; -use slog::info; +use slog::{debug, info}; use ssz::Decode; use std::net::SocketAddr; -use std::path::Path; +use std::path::{Path, PathBuf}; use std::sync::Arc; use std::time::Duration; use timer::spawn_timer; @@ -61,7 +60,10 @@ pub struct ClientBuilder { event_handler: Option, network_globals: Option>>, network_send: Option>>, - http_listen_addr: Option, + db_path: Option, + freezer_db_path: Option, + http_api_config: http_api::Config, + http_metrics_config: http_metrics::Config, websocket_listen_addr: Option, eth_spec_instance: T::EthSpec, } @@ -103,7 +105,10 @@ where event_handler: None, network_globals: None, network_send: None, - http_listen_addr: None, + db_path: None, + freezer_db_path: None, + http_api_config: <_>::default(), + http_metrics_config: <_>::default(), websocket_listen_addr: None, eth_spec_instance, } @@ -280,55 +285,16 @@ where Ok(self) } - /// Immediately starts the beacon node REST API http server. - pub fn http_server( - mut self, - client_config: &ClientConfig, - eth2_config: &Eth2Config, - events: Arc>>, - ) -> Result { - let beacon_chain = self - .beacon_chain - .clone() - .ok_or_else(|| "http_server requires a beacon chain")?; - let context = self - .runtime_context - .as_ref() - .ok_or_else(|| "http_server requires a runtime_context")? - .service_context("http".into()); - let network_globals = self - .network_globals - .clone() - .ok_or_else(|| "http_server requires a libp2p network")?; - let network_send = self - .network_send - .clone() - .ok_or_else(|| "http_server requires a libp2p network sender")?; - - let network_info = rest_api::NetworkInfo { - network_globals, - network_chan: network_send, - }; - - let listening_addr = rest_api::start_server( - context.executor, - &client_config.rest_api, - beacon_chain, - network_info, - client_config - .create_db_path() - .map_err(|_| "unable to read data dir")?, - client_config - .create_freezer_db_path() - .map_err(|_| "unable to read freezer DB dir")?, - eth2_config.clone(), - events, - ) - .map_err(|e| format!("Failed to start HTTP API: {:?}", e))?; - - self.http_listen_addr = Some(listening_addr); + /// Provides configuration for the HTTP API. + pub fn http_api_config(mut self, config: http_api::Config) -> Self { + self.http_api_config = config; + self + } - Ok(self) + /// Provides configuration for the HTTP server that serves Prometheus metrics. + pub fn http_metrics_config(mut self, config: http_metrics::Config) -> Self { + self.http_metrics_config = config; + self } /// Immediately starts the service that periodically logs information each slot. @@ -367,25 +333,85 @@ where /// specified. /// /// If type inference errors are being raised, see the comment on the definition of `Self`. + #[allow(clippy::type_complexity)] pub fn build( self, - ) -> Client< - Witness< - TStoreMigrator, - TSlotClock, - TEth1Backend, - TEthSpec, - TEventHandler, - THotStore, - TColdStore, + ) -> Result< + Client< + Witness< + TStoreMigrator, + TSlotClock, + TEth1Backend, + TEthSpec, + TEventHandler, + THotStore, + TColdStore, + >, >, + String, > { - Client { + let runtime_context = self + .runtime_context + .as_ref() + .ok_or_else(|| "build requires a runtime context".to_string())?; + let log = runtime_context.log().clone(); + + let http_api_listen_addr = if self.http_api_config.enabled { + let ctx = Arc::new(http_api::Context { + config: self.http_api_config.clone(), + chain: self.beacon_chain.clone(), + network_tx: self.network_send.clone(), + network_globals: self.network_globals.clone(), + log: log.clone(), + }); + + let exit = runtime_context.executor.exit(); + + let (listen_addr, server) = http_api::serve(ctx, exit) + .map_err(|e| format!("Unable to start HTTP API server: {:?}", e))?; + + runtime_context + .clone() + .executor + .spawn_without_exit(async move { server.await }, "http-api"); + + Some(listen_addr) + } else { + info!(log, "HTTP server is disabled"); + None + }; + + let http_metrics_listen_addr = if self.http_metrics_config.enabled { + let ctx = Arc::new(http_metrics::Context { + config: self.http_metrics_config.clone(), + chain: self.beacon_chain.clone(), + db_path: self.db_path.clone(), + freezer_db_path: self.freezer_db_path.clone(), + log: log.clone(), + }); + + let exit = runtime_context.executor.exit(); + + let (listen_addr, server) = http_metrics::serve(ctx, exit) + .map_err(|e| format!("Unable to start HTTP API server: {:?}", e))?; + + runtime_context + .executor + .spawn_without_exit(async move { server.await }, "http-api"); + + Some(listen_addr) + } else { + debug!(log, "Metrics server is disabled"); + None + }; + + Ok(Client { beacon_chain: self.beacon_chain, network_globals: self.network_globals, - http_listen_addr: self.http_listen_addr, + http_api_listen_addr, + http_metrics_listen_addr, websocket_listen_addr: self.websocket_listen_addr, - } + }) } } @@ -520,6 +546,9 @@ where .clone() .ok_or_else(|| "disk_store requires a chain spec".to_string())?; + self.db_path = Some(hot_path.into()); + self.freezer_db_path = Some(cold_path.into()); + let store = HotColdDB::open(hot_path, cold_path, config, spec, context.log().clone()) .map_err(|e| format!("Unable to open database: {:?}", e))?; self.store = Some(Arc::new(store)); diff --git a/beacon_node/client/src/config.rs b/beacon_node/client/src/config.rs index fdcd3d6e819..0cf90d6b45d 100644 --- a/beacon_node/client/src/config.rs +++ b/beacon_node/client/src/config.rs @@ -62,10 +62,11 @@ pub struct Config { pub genesis: ClientGenesis, pub store: store::StoreConfig, pub network: network::NetworkConfig, - pub rest_api: rest_api::Config, pub chain: beacon_chain::ChainConfig, pub websocket_server: websocket_server::Config, pub eth1: eth1::Config, + pub http_api: http_api::Config, + pub http_metrics: http_metrics::Config, } impl Default for Config { @@ -79,7 +80,6 @@ impl Default for Config { store: <_>::default(), network: NetworkConfig::default(), chain: <_>::default(), - rest_api: <_>::default(), websocket_server: <_>::default(), spec_constants: TESTNET_SPEC_CONSTANTS.into(), dummy_eth1_backend: false, @@ -87,6 +87,8 @@ impl Default for Config { eth1: <_>::default(), disabled_forks: Vec::new(), graffiti: Graffiti::default(), + http_api: <_>::default(), + http_metrics: <_>::default(), } } } diff --git a/beacon_node/client/src/lib.rs b/beacon_node/client/src/lib.rs index da670ff1344..6b721aee924 100644 --- a/beacon_node/client/src/lib.rs +++ b/beacon_node/client/src/lib.rs @@ -23,7 +23,10 @@ pub use eth2_config::Eth2Config; pub struct Client { beacon_chain: Option>>, network_globals: Option>>, - http_listen_addr: Option, + /// Listen address for the standard eth2.0 API, if the service was started. + http_api_listen_addr: Option, + /// Listen address for the HTTP server which serves Prometheus metrics. + http_metrics_listen_addr: Option, websocket_listen_addr: Option, } @@ -33,9 +36,14 @@ impl Client { self.beacon_chain.clone() } - /// Returns the address of the client's HTTP API server, if it was started. - pub fn http_listen_addr(&self) -> Option { - self.http_listen_addr + /// Returns the address of the client's standard eth2.0 API server, if it was started. + pub fn http_api_listen_addr(&self) -> Option { + self.http_api_listen_addr + } + + /// Returns the address of the client's HTTP Prometheus metrics server, if it was started. + pub fn http_metrics_listen_addr(&self) -> Option { + self.http_metrics_listen_addr } /// Returns the address of the client's WebSocket API server, if it was started. diff --git a/beacon_node/eth1/src/http.rs b/beacon_node/eth1/src/http.rs index 6dffdaa7c6d..e8f7d23a026 100644 --- a/beacon_node/eth1/src/http.rs +++ b/beacon_node/eth1/src/http.rs @@ -39,19 +39,34 @@ pub enum Eth1NetworkId { Custom(u64), } +impl Into for Eth1NetworkId { + fn into(self) -> u64 { + match self { + Eth1NetworkId::Mainnet => 1, + Eth1NetworkId::Goerli => 5, + Eth1NetworkId::Custom(id) => id, + } + } +} + +impl From for Eth1NetworkId { + fn from(id: u64) -> Self { + let into = |x: Eth1NetworkId| -> u64 { x.into() }; + match id { + id if id == into(Eth1NetworkId::Mainnet) => Eth1NetworkId::Mainnet, + id if id == into(Eth1NetworkId::Goerli) => Eth1NetworkId::Goerli, + id => Eth1NetworkId::Custom(id), + } + } +} + impl FromStr for Eth1NetworkId { type Err = String; fn from_str(s: &str) -> Result { - match s { - "1" => Ok(Eth1NetworkId::Mainnet), - "5" => Ok(Eth1NetworkId::Goerli), - custom => { - let network_id = u64::from_str_radix(custom, 10) - .map_err(|e| format!("Failed to parse eth1 network id {}", e))?; - Ok(Eth1NetworkId::Custom(network_id)) - } - } + u64::from_str_radix(s, 10) + .map(Into::into) + .map_err(|e| format!("Failed to parse eth1 network id {}", e)) } } diff --git a/beacon_node/eth1/src/lib.rs b/beacon_node/eth1/src/lib.rs index f5f018bd17b..a7aba85a28a 100644 --- a/beacon_node/eth1/src/lib.rs +++ b/beacon_node/eth1/src/lib.rs @@ -13,4 +13,6 @@ pub use block_cache::{BlockCache, Eth1Block}; pub use deposit_cache::DepositCache; pub use deposit_log::DepositLog; pub use inner::SszEth1Cache; -pub use service::{BlockCacheUpdateOutcome, Config, DepositCacheUpdateOutcome, Error, Service}; +pub use service::{ + BlockCacheUpdateOutcome, Config, DepositCacheUpdateOutcome, Error, Service, DEFAULT_NETWORK_ID, +}; diff --git a/beacon_node/rest_api/Cargo.toml b/beacon_node/http_api/Cargo.toml similarity index 51% rename from beacon_node/rest_api/Cargo.toml rename to beacon_node/http_api/Cargo.toml index 38a5a1e7d55..828d26deb3d 100644 --- a/beacon_node/rest_api/Cargo.toml +++ b/beacon_node/http_api/Cargo.toml @@ -1,50 +1,34 @@ [package] -name = "rest_api" -version = "0.2.0" -authors = ["Paul Hauner ", "Age Manning ", "Luke Anderson "] +name = "http_api" +version = "0.1.0" +authors = ["Paul Hauner "] edition = "2018" # See more keys and their definitions at https://doc.rust-lang.org/cargo/reference/manifest.html + [dependencies] -bls = { path = "../../crypto/bls" } -rest_types = { path = "../../common/rest_types" } +warp = "0.2.5" +serde = { version = "1.0.110", features = ["derive"] } +tokio = { version = "0.2.21", features = ["sync"] } +parking_lot = "0.11.0" +types = { path = "../../consensus/types" } +hex = "0.4.2" beacon_chain = { path = "../beacon_chain" } +eth2 = { path = "../../common/eth2", features = ["lighthouse"] } +slog = "2.5.2" network = { path = "../network" } eth2_libp2p = { path = "../eth2_libp2p" } -store = { path = "../store" } -serde = { version = "1.0.110", features = ["derive"] } -serde_json = "1.0.52" -serde_yaml = "0.8.11" -slog = "2.5.2" -slog-term = "2.5.0" -slog-async = "2.5.0" -eth2_ssz = "0.1.2" -eth2_ssz_derive = "0.1.0" +eth1 = { path = "../eth1" } +fork_choice = { path = "../../consensus/fork_choice" } state_processing = { path = "../../consensus/state_processing" } -types = { path = "../../consensus/types" } -http = "0.2.1" -hyper = "0.13.5" -tokio = { version = "0.2.21", features = ["sync"] } -url = "2.1.1" -lazy_static = "1.4.0" -eth2_config = { path = "../../common/eth2_config" } +lighthouse_version = { path = "../../common/lighthouse_version" } lighthouse_metrics = { path = "../../common/lighthouse_metrics" } +lazy_static = "1.4.0" +warp_utils = { path = "../../common/warp_utils" } slot_clock = { path = "../../common/slot_clock" } -hex = "0.4.2" -parking_lot = "0.11.0" -futures = "0.3.5" -operation_pool = { path = "../operation_pool" } -environment = { path = "../../lighthouse/environment" } -uhttp_sse = "0.5.1" -bus = "2.2.3" -itertools = "0.9.0" -lighthouse_version = { path = "../../common/lighthouse_version" } [dev-dependencies] -assert_matches = "1.3.0" -remote_beacon_node = { path = "../../common/remote_beacon_node" } -node_test_rig = { path = "../../testing/node_test_rig" } -tree_hash = "0.1.0" - -[features] -fake_crypto = [] +store = { path = "../store" } +environment = { path = "../../lighthouse/environment" } +tree_hash = { path = "../../consensus/tree_hash" } +discv5 = { version = "0.1.0-alpha.10", features = ["libp2p"] } diff --git a/beacon_node/http_api/src/beacon_proposer_cache.rs b/beacon_node/http_api/src/beacon_proposer_cache.rs new file mode 100644 index 00000000000..b062119e578 --- /dev/null +++ b/beacon_node/http_api/src/beacon_proposer_cache.rs @@ -0,0 +1,185 @@ +use crate::metrics; +use beacon_chain::{BeaconChain, BeaconChainError, BeaconChainTypes}; +use eth2::types::ProposerData; +use fork_choice::ProtoBlock; +use slot_clock::SlotClock; +use state_processing::per_slot_processing; +use types::{BeaconState, Epoch, EthSpec, Hash256, PublicKeyBytes}; + +/// This sets a maximum bound on the number of epochs to skip whilst instantiating the cache for +/// the first time. +const EPOCHS_TO_SKIP: u64 = 2; + +/// Caches the beacon block proposers for a given `epoch` and `epoch_boundary_root`. +/// +/// This cache is only able to contain a single set of proposers and is only +/// intended to cache the proposers for the current epoch according to the head +/// of the chain. A change in epoch or re-org to a different chain may cause a +/// cache miss and rebuild. +pub struct BeaconProposerCache { + epoch: Epoch, + decision_block_root: Hash256, + proposers: Vec, +} + +impl BeaconProposerCache { + /// Create a new cache for the current epoch of the `chain`. + pub fn new(chain: &BeaconChain) -> Result { + let head_root = chain.head_beacon_block_root()?; + let head_block = chain + .fork_choice + .read() + .get_block(&head_root) + .ok_or_else(|| BeaconChainError::MissingBeaconBlock(head_root))?; + + // If the head epoch is more than `EPOCHS_TO_SKIP` in the future, just build the cache at + // the epoch of the head. This prevents doing a massive amount of skip slots when starting + // a new database from genesis. + let epoch = { + let epoch_now = chain + .epoch() + .unwrap_or_else(|_| chain.spec.genesis_slot.epoch(T::EthSpec::slots_per_epoch())); + let head_epoch = head_block.slot.epoch(T::EthSpec::slots_per_epoch()); + if epoch_now > head_epoch + EPOCHS_TO_SKIP { + head_epoch + } else { + epoch_now + } + }; + + Self::for_head_block(chain, epoch, head_root, head_block) + } + + /// Create a new cache that contains the shuffling for `current_epoch`, + /// assuming that `head_root` and `head_block` represents the most recent + /// canonical block. + fn for_head_block( + chain: &BeaconChain, + current_epoch: Epoch, + head_root: Hash256, + head_block: ProtoBlock, + ) -> Result { + let _timer = metrics::start_timer(&metrics::HTTP_API_BEACON_PROPOSER_CACHE_TIMES); + + let mut head_state = chain + .get_state(&head_block.state_root, Some(head_block.slot))? + .ok_or_else(|| BeaconChainError::MissingBeaconState(head_block.state_root))?; + + let decision_block_root = Self::decision_block_root(current_epoch, head_root, &head_state)?; + + // We *must* skip forward to the current epoch to obtain valid proposer + // duties. We cannot skip to the previous epoch, like we do with + // attester duties. + while head_state.current_epoch() < current_epoch { + // Skip slots until the current epoch, providing `Hash256::zero()` as the state root + // since we don't require it to be valid to identify producers. + per_slot_processing(&mut head_state, Some(Hash256::zero()), &chain.spec)?; + } + + let proposers = current_epoch + .slot_iter(T::EthSpec::slots_per_epoch()) + .map(|slot| { + head_state + .get_beacon_proposer_index(slot, &chain.spec) + .map_err(BeaconChainError::from) + .and_then(|i| { + let pubkey = chain + .validator_pubkey(i)? + .ok_or_else(|| BeaconChainError::ValidatorPubkeyCacheIncomplete(i))?; + + Ok(ProposerData { + pubkey: PublicKeyBytes::from(pubkey), + slot, + }) + }) + }) + .collect::>()?; + + Ok(Self { + epoch: current_epoch, + decision_block_root, + proposers, + }) + } + + /// Returns a block root which can be used to key the shuffling obtained from the following + /// parameters: + /// + /// - `shuffling_epoch`: the epoch for which the shuffling pertains. + /// - `head_block_root`: the block root at the head of the chain. + /// - `head_block_state`: the state of `head_block_root`. + pub fn decision_block_root( + shuffling_epoch: Epoch, + head_block_root: Hash256, + head_block_state: &BeaconState, + ) -> Result { + let decision_slot = shuffling_epoch + .start_slot(E::slots_per_epoch()) + .saturating_sub(1_u64); + + // If decision slot is equal to or ahead of the head, the block root is the head block root + if decision_slot >= head_block_state.slot { + Ok(head_block_root) + } else { + head_block_state + .get_block_root(decision_slot) + .map(|root| *root) + .map_err(Into::into) + } + } + + /// Return the proposers for the given `Epoch`. + /// + /// The cache may be rebuilt if: + /// + /// - The epoch has changed since the last cache build. + /// - There has been a re-org that crosses an epoch boundary. + pub fn get_proposers( + &mut self, + chain: &BeaconChain, + epoch: Epoch, + ) -> Result, warp::Rejection> { + let current_epoch = chain + .slot_clock + .now_or_genesis() + .ok_or_else(|| { + warp_utils::reject::custom_server_error("unable to read slot clock".to_string()) + })? + .epoch(T::EthSpec::slots_per_epoch()); + + // Disallow requests that are outside the current epoch. This ensures the cache doesn't get + // washed-out with old values. + if current_epoch != epoch { + return Err(warp_utils::reject::custom_bad_request(format!( + "requested epoch is {} but only current epoch {} is allowed", + epoch, current_epoch + ))); + } + + let (head_block_root, head_decision_block_root) = chain + .with_head(|head| { + Self::decision_block_root(current_epoch, head.beacon_block_root, &head.beacon_state) + .map(|decision_root| (head.beacon_block_root, decision_root)) + }) + .map_err(warp_utils::reject::beacon_chain_error)?; + + let head_block = chain + .fork_choice + .read() + .get_block(&head_block_root) + .ok_or_else(|| BeaconChainError::MissingBeaconBlock(head_block_root)) + .map_err(warp_utils::reject::beacon_chain_error)?; + + // Rebuild the cache if this call causes a cache-miss. + if self.epoch != current_epoch || self.decision_block_root != head_decision_block_root { + metrics::inc_counter(&metrics::HTTP_API_BEACON_PROPOSER_CACHE_MISSES_TOTAL); + + *self = Self::for_head_block(chain, current_epoch, head_block_root, head_block) + .map_err(warp_utils::reject::beacon_chain_error)?; + } else { + metrics::inc_counter(&metrics::HTTP_API_BEACON_PROPOSER_CACHE_HITS_TOTAL); + } + + Ok(self.proposers.clone()) + } +} diff --git a/beacon_node/http_api/src/block_id.rs b/beacon_node/http_api/src/block_id.rs new file mode 100644 index 00000000000..5e358a2d683 --- /dev/null +++ b/beacon_node/http_api/src/block_id.rs @@ -0,0 +1,87 @@ +use beacon_chain::{BeaconChain, BeaconChainTypes}; +use eth2::types::BlockId as CoreBlockId; +use std::str::FromStr; +use types::{Hash256, SignedBeaconBlock, Slot}; + +/// Wraps `eth2::types::BlockId` and provides a simple way to obtain a block or root for a given +/// `BlockId`. +#[derive(Debug)] +pub struct BlockId(pub CoreBlockId); + +impl BlockId { + pub fn from_slot(slot: Slot) -> Self { + Self(CoreBlockId::Slot(slot)) + } + + pub fn from_root(root: Hash256) -> Self { + Self(CoreBlockId::Root(root)) + } + + /// Return the block root identified by `self`. + pub fn root( + &self, + chain: &BeaconChain, + ) -> Result { + match &self.0 { + CoreBlockId::Head => chain + .head_info() + .map(|head| head.block_root) + .map_err(warp_utils::reject::beacon_chain_error), + CoreBlockId::Genesis => Ok(chain.genesis_block_root), + CoreBlockId::Finalized => chain + .head_info() + .map(|head| head.finalized_checkpoint.root) + .map_err(warp_utils::reject::beacon_chain_error), + CoreBlockId::Justified => chain + .head_info() + .map(|head| head.current_justified_checkpoint.root) + .map_err(warp_utils::reject::beacon_chain_error), + CoreBlockId::Slot(slot) => chain + .block_root_at_slot(*slot) + .map_err(warp_utils::reject::beacon_chain_error) + .and_then(|root_opt| { + root_opt.ok_or_else(|| { + warp_utils::reject::custom_not_found(format!( + "beacon block at slot {}", + slot + )) + }) + }), + CoreBlockId::Root(root) => Ok(*root), + } + } + + /// Return the `SignedBeaconBlock` identified by `self`. + pub fn block( + &self, + chain: &BeaconChain, + ) -> Result, warp::Rejection> { + match &self.0 { + CoreBlockId::Head => chain + .head_beacon_block() + .map_err(warp_utils::reject::beacon_chain_error), + _ => { + let root = self.root(chain)?; + chain + .get_block(&root) + .map_err(warp_utils::reject::beacon_chain_error) + .and_then(|root_opt| { + root_opt.ok_or_else(|| { + warp_utils::reject::custom_not_found(format!( + "beacon block with root {}", + root + )) + }) + }) + } + } + } +} + +impl FromStr for BlockId { + type Err = String; + + fn from_str(s: &str) -> Result { + CoreBlockId::from_str(s).map(Self) + } +} diff --git a/beacon_node/http_api/src/lib.rs b/beacon_node/http_api/src/lib.rs new file mode 100644 index 00000000000..b23937b5df1 --- /dev/null +++ b/beacon_node/http_api/src/lib.rs @@ -0,0 +1,1749 @@ +//! This crate contains a HTTP server which serves the endpoints listed here: +//! +//! https://github.com/ethereum/eth2.0-APIs +//! +//! There are also some additional, non-standard endpoints behind the `/lighthouse/` path which are +//! used for development. + +mod beacon_proposer_cache; +mod block_id; +mod metrics; +mod state_id; +mod validator_inclusion; + +use beacon_chain::{ + observed_operations::ObservationOutcome, AttestationError as AttnError, BeaconChain, + BeaconChainError, BeaconChainTypes, +}; +use beacon_proposer_cache::BeaconProposerCache; +use block_id::BlockId; +use eth2::{ + types::{self as api_types, ValidatorId}, + StatusCode, +}; +use eth2_libp2p::{types::SyncState, NetworkGlobals, PubsubMessage}; +use lighthouse_version::version_with_platform; +use network::NetworkMessage; +use parking_lot::Mutex; +use serde::{Deserialize, Serialize}; +use slog::{crit, error, info, trace, warn, Logger}; +use slot_clock::SlotClock; +use state_id::StateId; +use state_processing::per_slot_processing; +use std::borrow::Cow; +use std::convert::TryInto; +use std::future::Future; +use std::net::{Ipv4Addr, SocketAddr, SocketAddrV4}; +use std::sync::Arc; +use tokio::sync::mpsc::UnboundedSender; +use types::{ + Attestation, AttestationDuty, AttesterSlashing, CloneConfig, CommitteeCache, Epoch, EthSpec, + Hash256, ProposerSlashing, PublicKey, RelativeEpoch, SignedAggregateAndProof, + SignedBeaconBlock, SignedVoluntaryExit, Slot, YamlConfig, +}; +use warp::Filter; + +const API_PREFIX: &str = "eth"; +const API_VERSION: &str = "v1"; + +/// If the node is within this many epochs from the head, we declare it to be synced regardless of +/// the network sync state. +/// +/// This helps prevent attacks where nodes can convince us that we're syncing some non-existent +/// finalized head. +const SYNC_TOLERANCE_EPOCHS: u64 = 8; + +/// A wrapper around all the items required to spawn the HTTP server. +/// +/// The server will gracefully handle the case where any fields are `None`. +pub struct Context { + pub config: Config, + pub chain: Option>>, + pub network_tx: Option>>, + pub network_globals: Option>>, + pub log: Logger, +} + +/// Configuration for the HTTP server. +#[derive(PartialEq, Debug, Clone, Serialize, Deserialize)] +pub struct Config { + pub enabled: bool, + pub listen_addr: Ipv4Addr, + pub listen_port: u16, + pub allow_origin: Option, +} + +impl Default for Config { + fn default() -> Self { + Self { + enabled: false, + listen_addr: Ipv4Addr::new(127, 0, 0, 1), + listen_port: 5052, + allow_origin: None, + } + } +} + +#[derive(Debug)] +pub enum Error { + Warp(warp::Error), + Other(String), +} + +impl From for Error { + fn from(e: warp::Error) -> Self { + Error::Warp(e) + } +} + +impl From for Error { + fn from(e: String) -> Self { + Error::Other(e) + } +} + +/// Creates a `warp` logging wrapper which we use to create `slog` logs. +pub fn slog_logging( + log: Logger, +) -> warp::filters::log::Log { + warp::log::custom(move |info| { + match info.status() { + status if status == StatusCode::OK || status == StatusCode::NOT_FOUND => { + trace!( + log, + "Processed HTTP API request"; + "elapsed" => format!("{:?}", info.elapsed()), + "status" => status.to_string(), + "path" => info.path(), + "method" => info.method().to_string(), + ); + } + status => { + warn!( + log, + "Error processing HTTP API request"; + "elapsed" => format!("{:?}", info.elapsed()), + "status" => status.to_string(), + "path" => info.path(), + "method" => info.method().to_string(), + ); + } + }; + }) +} + +/// Creates a `warp` logging wrapper which we use for Prometheus metrics (not necessarily logging, +/// per say). +pub fn prometheus_metrics() -> warp::filters::log::Log { + warp::log::custom(move |info| { + // Here we restrict the `info.path()` value to some predefined values. Without this, we end + // up with a new metric type each time someone includes something unique in the path (e.g., + // a block hash). + let path = { + let equals = |s: &'static str| -> Option<&'static str> { + if info.path() == format!("/{}/{}/{}", API_PREFIX, API_VERSION, s) { + Some(s) + } else { + None + } + }; + + let starts_with = |s: &'static str| -> Option<&'static str> { + if info + .path() + .starts_with(&format!("/{}/{}/{}", API_PREFIX, API_VERSION, s)) + { + Some(s) + } else { + None + } + }; + + equals("beacon/blocks") + .or_else(|| starts_with("validator/duties/attester")) + .or_else(|| starts_with("validator/duties/proposer")) + .or_else(|| starts_with("validator/attestation_data")) + .or_else(|| starts_with("validator/blocks")) + .or_else(|| starts_with("validator/aggregate_attestation")) + .or_else(|| starts_with("validator/aggregate_and_proofs")) + .or_else(|| starts_with("validator/beacon_committee_subscriptions")) + .or_else(|| starts_with("beacon/")) + .or_else(|| starts_with("config/")) + .or_else(|| starts_with("debug/")) + .or_else(|| starts_with("events/")) + .or_else(|| starts_with("node/")) + .or_else(|| starts_with("validator/")) + .unwrap_or("other") + }; + + metrics::inc_counter_vec(&metrics::HTTP_API_PATHS_TOTAL, &[path]); + metrics::inc_counter_vec( + &metrics::HTTP_API_STATUS_CODES_TOTAL, + &[&info.status().to_string()], + ); + metrics::observe_timer_vec(&metrics::HTTP_API_PATHS_TIMES, &[path], info.elapsed()); + }) +} + +/// Creates a server that will serve requests using information from `ctx`. +/// +/// The server will shut down gracefully when the `shutdown` future resolves. +/// +/// ## Returns +/// +/// This function will bind the server to the provided address and then return a tuple of: +/// +/// - `SocketAddr`: the address that the HTTP server will listen on. +/// - `Future`: the actual server future that will need to be awaited. +/// +/// ## Errors +/// +/// Returns an error if the server is unable to bind or there is another error during +/// configuration. +pub fn serve( + ctx: Arc>, + shutdown: impl Future + Send + Sync + 'static, +) -> Result<(SocketAddr, impl Future), Error> { + let config = ctx.config.clone(); + let log = ctx.log.clone(); + let allow_origin = config.allow_origin.clone(); + + // Sanity check. + if !config.enabled { + crit!(log, "Cannot start disabled HTTP server"); + return Err(Error::Other( + "A disabled server should not be started".to_string(), + )); + } + + let eth1_v1 = warp::path(API_PREFIX).and(warp::path(API_VERSION)); + + // Instantiate the beacon proposer cache. + let beacon_proposer_cache = ctx + .chain + .as_ref() + .map(|chain| BeaconProposerCache::new(&chain)) + .transpose() + .map_err(|e| format!("Unable to initialize beacon proposer cache: {:?}", e))? + .map(Mutex::new) + .map(Arc::new); + + // Create a `warp` filter that provides access to the proposer cache. + let beacon_proposer_cache = || { + warp::any() + .map(move || beacon_proposer_cache.clone()) + .and_then(|beacon_proposer_cache| async move { + match beacon_proposer_cache { + Some(cache) => Ok(cache), + None => Err(warp_utils::reject::custom_not_found( + "Beacon proposer cache is not initialized.".to_string(), + )), + } + }) + }; + + // Create a `warp` filter that provides access to the network globals. + let inner_network_globals = ctx.network_globals.clone(); + let network_globals = warp::any() + .map(move || inner_network_globals.clone()) + .and_then(|network_globals| async move { + match network_globals { + Some(globals) => Ok(globals), + None => Err(warp_utils::reject::custom_not_found( + "network globals are not initialized.".to_string(), + )), + } + }); + + // Create a `warp` filter that provides access to the beacon chain. + let inner_ctx = ctx.clone(); + let chain_filter = + warp::any() + .map(move || inner_ctx.chain.clone()) + .and_then(|chain| async move { + match chain { + Some(chain) => Ok(chain), + None => Err(warp_utils::reject::custom_not_found( + "Beacon chain genesis has not yet been observed.".to_string(), + )), + } + }); + + // Create a `warp` filter that provides access to the network sender channel. + let inner_ctx = ctx.clone(); + let network_tx_filter = warp::any() + .map(move || inner_ctx.network_tx.clone()) + .and_then(|network_tx| async move { + match network_tx { + Some(network_tx) => Ok(network_tx), + None => Err(warp_utils::reject::custom_not_found( + "The networking stack has not yet started.".to_string(), + )), + } + }); + + // Create a `warp` filter that rejects request whilst the node is syncing. + let not_while_syncing_filter = warp::any() + .and(network_globals.clone()) + .and(chain_filter.clone()) + .and_then( + |network_globals: Arc>, chain: Arc>| async move { + match *network_globals.sync_state.read() { + SyncState::SyncingFinalized { head_slot, .. } => { + let current_slot = chain + .slot_clock + .now_or_genesis() + .ok_or_else(|| { + warp_utils::reject::custom_server_error( + "unable to read slot clock".to_string(), + ) + })?; + + let tolerance = SYNC_TOLERANCE_EPOCHS * T::EthSpec::slots_per_epoch(); + + if head_slot + tolerance >= current_slot { + Ok(()) + } else { + Err(warp_utils::reject::not_synced(format!( + "head slot is {}, current slot is {}", + head_slot, current_slot + ))) + } + } + SyncState::SyncingHead { .. } => Ok(()), + SyncState::Synced => Ok(()), + SyncState::Stalled => Err(warp_utils::reject::not_synced( + "sync is stalled".to_string(), + )), + } + }, + ) + .untuple_one(); + + // Create a `warp` filter that provides access to the logger. + let log_filter = warp::any().map(move || ctx.log.clone()); + + /* + * + * Start of HTTP method definitions. + * + */ + + // GET beacon/genesis + let get_beacon_genesis = eth1_v1 + .and(warp::path("beacon")) + .and(warp::path("genesis")) + .and(warp::path::end()) + .and(chain_filter.clone()) + .and_then(|chain: Arc>| { + blocking_json_task(move || { + chain + .head_info() + .map_err(warp_utils::reject::beacon_chain_error) + .map(|head| api_types::GenesisData { + genesis_time: head.genesis_time, + genesis_validators_root: head.genesis_validators_root, + genesis_fork_version: chain.spec.genesis_fork_version, + }) + .map(api_types::GenericResponse::from) + }) + }); + + /* + * beacon/states/{state_id} + */ + + let beacon_states_path = eth1_v1 + .and(warp::path("beacon")) + .and(warp::path("states")) + .and(warp::path::param::()) + .and(chain_filter.clone()); + + // GET beacon/states/{state_id}/root + let get_beacon_state_root = beacon_states_path + .clone() + .and(warp::path("root")) + .and(warp::path::end()) + .and_then(|state_id: StateId, chain: Arc>| { + blocking_json_task(move || { + state_id + .root(&chain) + .map(api_types::RootData::from) + .map(api_types::GenericResponse::from) + }) + }); + + // GET beacon/states/{state_id}/fork + let get_beacon_state_fork = beacon_states_path + .clone() + .and(warp::path("fork")) + .and(warp::path::end()) + .and_then(|state_id: StateId, chain: Arc>| { + blocking_json_task(move || state_id.fork(&chain).map(api_types::GenericResponse::from)) + }); + + // GET beacon/states/{state_id}/finality_checkpoints + let get_beacon_state_finality_checkpoints = beacon_states_path + .clone() + .and(warp::path("finality_checkpoints")) + .and(warp::path::end()) + .and_then(|state_id: StateId, chain: Arc>| { + blocking_json_task(move || { + state_id + .map_state(&chain, |state| { + Ok(api_types::FinalityCheckpointsData { + previous_justified: state.previous_justified_checkpoint, + current_justified: state.current_justified_checkpoint, + finalized: state.finalized_checkpoint, + }) + }) + .map(api_types::GenericResponse::from) + }) + }); + + // GET beacon/states/{state_id}/validators + let get_beacon_state_validators = beacon_states_path + .clone() + .and(warp::path("validators")) + .and(warp::path::end()) + .and_then(|state_id: StateId, chain: Arc>| { + blocking_json_task(move || { + state_id + .map_state(&chain, |state| { + let epoch = state.current_epoch(); + let finalized_epoch = state.finalized_checkpoint.epoch; + let far_future_epoch = chain.spec.far_future_epoch; + + Ok(state + .validators + .iter() + .zip(state.balances.iter()) + .enumerate() + .map(|(index, (validator, balance))| api_types::ValidatorData { + index: index as u64, + balance: *balance, + status: api_types::ValidatorStatus::from_validator( + Some(validator), + epoch, + finalized_epoch, + far_future_epoch, + ), + validator: validator.clone(), + }) + .collect::>()) + }) + .map(api_types::GenericResponse::from) + }) + }); + + // GET beacon/states/{state_id}/validators/{validator_id} + let get_beacon_state_validators_id = beacon_states_path + .clone() + .and(warp::path("validators")) + .and(warp::path::param::()) + .and(warp::path::end()) + .and_then( + |state_id: StateId, chain: Arc>, validator_id: ValidatorId| { + blocking_json_task(move || { + state_id + .map_state(&chain, |state| { + let index_opt = match &validator_id { + ValidatorId::PublicKey(pubkey) => { + state.validators.iter().position(|v| v.pubkey == *pubkey) + } + ValidatorId::Index(index) => Some(*index as usize), + }; + + index_opt + .and_then(|index| { + let validator = state.validators.get(index)?; + let balance = *state.balances.get(index)?; + let epoch = state.current_epoch(); + let finalized_epoch = state.finalized_checkpoint.epoch; + let far_future_epoch = chain.spec.far_future_epoch; + + Some(api_types::ValidatorData { + index: index as u64, + balance, + status: api_types::ValidatorStatus::from_validator( + Some(validator), + epoch, + finalized_epoch, + far_future_epoch, + ), + validator: validator.clone(), + }) + }) + .ok_or_else(|| { + warp_utils::reject::custom_not_found(format!( + "unknown validator: {}", + validator_id + )) + }) + }) + .map(api_types::GenericResponse::from) + }) + }, + ); + + // GET beacon/states/{state_id}/committees/{epoch} + let get_beacon_state_committees = beacon_states_path + .clone() + .and(warp::path("committees")) + .and(warp::path::param::()) + .and(warp::query::()) + .and(warp::path::end()) + .and_then( + |state_id: StateId, + chain: Arc>, + epoch: Epoch, + query: api_types::CommitteesQuery| { + blocking_json_task(move || { + state_id.map_state(&chain, |state| { + let relative_epoch = + RelativeEpoch::from_epoch(state.current_epoch(), epoch).map_err( + |_| { + warp_utils::reject::custom_bad_request(format!( + "state is epoch {} and only previous, current and next epochs are supported", + state.current_epoch() + )) + }, + )?; + + let committee_cache = if state + .committee_cache_is_initialized(relative_epoch) + { + state.committee_cache(relative_epoch).map(Cow::Borrowed) + } else { + CommitteeCache::initialized(state, epoch, &chain.spec).map(Cow::Owned) + } + .map_err(BeaconChainError::BeaconStateError) + .map_err(warp_utils::reject::beacon_chain_error)?; + + // Use either the supplied slot or all slots in the epoch. + let slots = query.slot.map(|slot| vec![slot]).unwrap_or_else(|| { + epoch.slot_iter(T::EthSpec::slots_per_epoch()).collect() + }); + + // Use either the supplied committee index or all available indices. + let indices = query.index.map(|index| vec![index]).unwrap_or_else(|| { + (0..committee_cache.committees_per_slot()).collect() + }); + + let mut response = Vec::with_capacity(slots.len() * indices.len()); + + for slot in slots { + // It is not acceptable to query with a slot that is not within the + // specified epoch. + if slot.epoch(T::EthSpec::slots_per_epoch()) != epoch { + return Err(warp_utils::reject::custom_bad_request(format!( + "{} is not in epoch {}", + slot, epoch + ))); + } + + for &index in &indices { + let committee = committee_cache + .get_beacon_committee(slot, index) + .ok_or_else(|| { + warp_utils::reject::custom_bad_request(format!( + "committee index {} does not exist in epoch {}", + index, epoch + )) + })?; + + response.push(api_types::CommitteeData { + index, + slot, + validators: committee + .committee + .iter() + .map(|i| *i as u64) + .collect(), + }); + } + } + + Ok(api_types::GenericResponse::from(response)) + }) + }) + }, + ); + + // GET beacon/headers + // + // Note: this endpoint only returns information about blocks in the canonical chain. Given that + // there's a `canonical` flag on the response, I assume it should also return non-canonical + // things. Returning non-canonical things is hard for us since we don't already have a + // mechanism for arbitrary forwards block iteration, we only support iterating forwards along + // the canonical chain. + let get_beacon_headers = eth1_v1 + .and(warp::path("beacon")) + .and(warp::path("headers")) + .and(warp::query::()) + .and(warp::path::end()) + .and(chain_filter.clone()) + .and_then( + |query: api_types::HeadersQuery, chain: Arc>| { + blocking_json_task(move || { + let (root, block) = match (query.slot, query.parent_root) { + // No query parameters, return the canonical head block. + (None, None) => chain + .head_beacon_block() + .map_err(warp_utils::reject::beacon_chain_error) + .map(|block| (block.canonical_root(), block))?, + // Only the parent root parameter, do a forwards-iterator lookup. + (None, Some(parent_root)) => { + let parent = BlockId::from_root(parent_root).block(&chain)?; + let (root, _slot) = chain + .forwards_iter_block_roots(parent.slot()) + .map_err(warp_utils::reject::beacon_chain_error)? + // Ignore any skip-slots immediately following the parent. + .find(|res| { + res.as_ref().map_or(false, |(root, _)| *root != parent_root) + }) + .transpose() + .map_err(warp_utils::reject::beacon_chain_error)? + .ok_or_else(|| { + warp_utils::reject::custom_not_found(format!( + "child of block with root {}", + parent_root + )) + })?; + + BlockId::from_root(root) + .block(&chain) + .map(|block| (root, block))? + } + // Slot is supplied, search by slot and optionally filter by + // parent root. + (Some(slot), parent_root_opt) => { + let root = BlockId::from_slot(slot).root(&chain)?; + let block = BlockId::from_root(root).block(&chain)?; + + // If the parent root was supplied, check that it matches the block + // obtained via a slot lookup. + if let Some(parent_root) = parent_root_opt { + if block.parent_root() != parent_root { + return Err(warp_utils::reject::custom_not_found(format!( + "no canonical block at slot {} with parent root {}", + slot, parent_root + ))); + } + } + + (root, block) + } + }; + + let data = api_types::BlockHeaderData { + root, + canonical: true, + header: api_types::BlockHeaderAndSignature { + message: block.message.block_header(), + signature: block.signature.into(), + }, + }; + + Ok(api_types::GenericResponse::from(vec![data])) + }) + }, + ); + + // GET beacon/headers/{block_id} + let get_beacon_headers_block_id = eth1_v1 + .and(warp::path("beacon")) + .and(warp::path("headers")) + .and(warp::path::param::()) + .and(warp::path::end()) + .and(chain_filter.clone()) + .and_then(|block_id: BlockId, chain: Arc>| { + blocking_json_task(move || { + let root = block_id.root(&chain)?; + let block = BlockId::from_root(root).block(&chain)?; + + let canonical = chain + .block_root_at_slot(block.slot()) + .map_err(warp_utils::reject::beacon_chain_error)? + .map_or(false, |canonical| root == canonical); + + let data = api_types::BlockHeaderData { + root, + canonical, + header: api_types::BlockHeaderAndSignature { + message: block.message.block_header(), + signature: block.signature.into(), + }, + }; + + Ok(api_types::GenericResponse::from(data)) + }) + }); + + /* + * beacon/blocks + */ + + // POST beacon/blocks/{block_id} + let post_beacon_blocks = eth1_v1 + .and(warp::path("beacon")) + .and(warp::path("blocks")) + .and(warp::path::end()) + .and(warp::body::json()) + .and(chain_filter.clone()) + .and(network_tx_filter.clone()) + .and(log_filter.clone()) + .and_then( + |block: SignedBeaconBlock, + chain: Arc>, + network_tx: UnboundedSender>, + log: Logger| { + blocking_json_task(move || { + // Send the block, regardless of whether or not it is valid. The API + // specification is very clear that this is the desired behaviour. + publish_pubsub_message( + &network_tx, + PubsubMessage::BeaconBlock(Box::new(block.clone())), + )?; + + match chain.process_block(block.clone()) { + Ok(root) => { + info!( + log, + "Valid block from HTTP API"; + "root" => format!("{}", root) + ); + + // Update the head since it's likely this block will become the new + // head. + chain + .fork_choice() + .map_err(warp_utils::reject::beacon_chain_error)?; + + Ok(()) + } + Err(e) => { + let msg = format!("{:?}", e); + error!( + log, + "Invalid block provided to HTTP API"; + "reason" => &msg + ); + Err(warp_utils::reject::broadcast_without_import(msg)) + } + } + }) + }, + ); + + let beacon_blocks_path = eth1_v1 + .and(warp::path("beacon")) + .and(warp::path("blocks")) + .and(warp::path::param::()) + .and(chain_filter.clone()); + + // GET beacon/blocks/{block_id} + let get_beacon_block = beacon_blocks_path.clone().and(warp::path::end()).and_then( + |block_id: BlockId, chain: Arc>| { + blocking_json_task(move || block_id.block(&chain).map(api_types::GenericResponse::from)) + }, + ); + + // GET beacon/blocks/{block_id}/root + let get_beacon_block_root = beacon_blocks_path + .clone() + .and(warp::path("root")) + .and(warp::path::end()) + .and_then(|block_id: BlockId, chain: Arc>| { + blocking_json_task(move || { + block_id + .root(&chain) + .map(api_types::RootData::from) + .map(api_types::GenericResponse::from) + }) + }); + + // GET beacon/blocks/{block_id}/attestations + let get_beacon_block_attestations = beacon_blocks_path + .clone() + .and(warp::path("attestations")) + .and(warp::path::end()) + .and_then(|block_id: BlockId, chain: Arc>| { + blocking_json_task(move || { + block_id + .block(&chain) + .map(|block| block.message.body.attestations) + .map(api_types::GenericResponse::from) + }) + }); + + /* + * beacon/pool + */ + + let beacon_pool_path = eth1_v1 + .and(warp::path("beacon")) + .and(warp::path("pool")) + .and(chain_filter.clone()); + + // POST beacon/pool/attestations + let post_beacon_pool_attestations = beacon_pool_path + .clone() + .and(warp::path("attestations")) + .and(warp::path::end()) + .and(warp::body::json()) + .and(network_tx_filter.clone()) + .and_then( + |chain: Arc>, + attestation: Attestation, + network_tx: UnboundedSender>| { + blocking_json_task(move || { + let attestation = chain + .verify_unaggregated_attestation_for_gossip(attestation.clone(), None) + .map_err(|e| { + warp_utils::reject::object_invalid(format!( + "gossip verification failed: {:?}", + e + )) + })?; + + publish_pubsub_message( + &network_tx, + PubsubMessage::Attestation(Box::new(( + attestation.subnet_id(), + attestation.attestation().clone(), + ))), + )?; + + chain + .apply_attestation_to_fork_choice(&attestation) + .map_err(|e| { + warp_utils::reject::broadcast_without_import(format!( + "not applied to fork choice: {:?}", + e + )) + })?; + + chain + .add_to_naive_aggregation_pool(attestation) + .map_err(|e| { + warp_utils::reject::broadcast_without_import(format!( + "not applied to naive aggregation pool: {:?}", + e + )) + })?; + + Ok(()) + }) + }, + ); + + // GET beacon/pool/attestations + let get_beacon_pool_attestations = beacon_pool_path + .clone() + .and(warp::path("attestations")) + .and(warp::path::end()) + .and_then(|chain: Arc>| { + blocking_json_task(move || { + let mut attestations = chain.op_pool.get_all_attestations(); + attestations.extend(chain.naive_aggregation_pool.read().iter().cloned()); + Ok(api_types::GenericResponse::from(attestations)) + }) + }); + + // POST beacon/pool/attester_slashings + let post_beacon_pool_attester_slashings = beacon_pool_path + .clone() + .and(warp::path("attester_slashings")) + .and(warp::path::end()) + .and(warp::body::json()) + .and(network_tx_filter.clone()) + .and_then( + |chain: Arc>, + slashing: AttesterSlashing, + network_tx: UnboundedSender>| { + blocking_json_task(move || { + let outcome = chain + .verify_attester_slashing_for_gossip(slashing.clone()) + .map_err(|e| { + warp_utils::reject::object_invalid(format!( + "gossip verification failed: {:?}", + e + )) + })?; + + if let ObservationOutcome::New(slashing) = outcome { + publish_pubsub_message( + &network_tx, + PubsubMessage::AttesterSlashing(Box::new( + slashing.clone().into_inner(), + )), + )?; + + chain + .import_attester_slashing(slashing) + .map_err(warp_utils::reject::beacon_chain_error)?; + } + + Ok(()) + }) + }, + ); + + // GET beacon/pool/attester_slashings + let get_beacon_pool_attester_slashings = beacon_pool_path + .clone() + .and(warp::path("attester_slashings")) + .and(warp::path::end()) + .and_then(|chain: Arc>| { + blocking_json_task(move || { + let attestations = chain.op_pool.get_all_attester_slashings(); + Ok(api_types::GenericResponse::from(attestations)) + }) + }); + + // POST beacon/pool/proposer_slashings + let post_beacon_pool_proposer_slashings = beacon_pool_path + .clone() + .and(warp::path("proposer_slashings")) + .and(warp::path::end()) + .and(warp::body::json()) + .and(network_tx_filter.clone()) + .and_then( + |chain: Arc>, + slashing: ProposerSlashing, + network_tx: UnboundedSender>| { + blocking_json_task(move || { + let outcome = chain + .verify_proposer_slashing_for_gossip(slashing.clone()) + .map_err(|e| { + warp_utils::reject::object_invalid(format!( + "gossip verification failed: {:?}", + e + )) + })?; + + if let ObservationOutcome::New(slashing) = outcome { + publish_pubsub_message( + &network_tx, + PubsubMessage::ProposerSlashing(Box::new( + slashing.clone().into_inner(), + )), + )?; + + chain.import_proposer_slashing(slashing); + } + + Ok(()) + }) + }, + ); + + // GET beacon/pool/proposer_slashings + let get_beacon_pool_proposer_slashings = beacon_pool_path + .clone() + .and(warp::path("proposer_slashings")) + .and(warp::path::end()) + .and_then(|chain: Arc>| { + blocking_json_task(move || { + let attestations = chain.op_pool.get_all_proposer_slashings(); + Ok(api_types::GenericResponse::from(attestations)) + }) + }); + + // POST beacon/pool/voluntary_exits + let post_beacon_pool_voluntary_exits = beacon_pool_path + .clone() + .and(warp::path("voluntary_exits")) + .and(warp::path::end()) + .and(warp::body::json()) + .and(network_tx_filter.clone()) + .and_then( + |chain: Arc>, + exit: SignedVoluntaryExit, + network_tx: UnboundedSender>| { + blocking_json_task(move || { + let outcome = chain + .verify_voluntary_exit_for_gossip(exit.clone()) + .map_err(|e| { + warp_utils::reject::object_invalid(format!( + "gossip verification failed: {:?}", + e + )) + })?; + + if let ObservationOutcome::New(exit) = outcome { + publish_pubsub_message( + &network_tx, + PubsubMessage::VoluntaryExit(Box::new(exit.clone().into_inner())), + )?; + + chain.import_voluntary_exit(exit); + } + + Ok(()) + }) + }, + ); + + // GET beacon/pool/voluntary_exits + let get_beacon_pool_voluntary_exits = beacon_pool_path + .clone() + .and(warp::path("voluntary_exits")) + .and(warp::path::end()) + .and_then(|chain: Arc>| { + blocking_json_task(move || { + let attestations = chain.op_pool.get_all_voluntary_exits(); + Ok(api_types::GenericResponse::from(attestations)) + }) + }); + + /* + * config/fork_schedule + */ + + let config_path = eth1_v1.and(warp::path("config")); + + // GET config/fork_schedule + let get_config_fork_schedule = config_path + .clone() + .and(warp::path("fork_schedule")) + .and(warp::path::end()) + .and(chain_filter.clone()) + .and_then(|chain: Arc>| { + blocking_json_task(move || { + StateId::head() + .fork(&chain) + .map(|fork| api_types::GenericResponse::from(vec![fork])) + }) + }); + + // GET config/spec + let get_config_spec = config_path + .clone() + .and(warp::path("spec")) + .and(warp::path::end()) + .and(chain_filter.clone()) + .and_then(|chain: Arc>| { + blocking_json_task(move || { + Ok(api_types::GenericResponse::from(YamlConfig::from_spec::< + T::EthSpec, + >( + &chain.spec + ))) + }) + }); + + // GET config/deposit_contract + let get_config_deposit_contract = config_path + .clone() + .and(warp::path("deposit_contract")) + .and(warp::path::end()) + .and(chain_filter.clone()) + .and_then(|chain: Arc>| { + blocking_json_task(move || { + Ok(api_types::GenericResponse::from( + api_types::DepositContractData { + address: chain.spec.deposit_contract_address, + chain_id: eth1::DEFAULT_NETWORK_ID.into(), + }, + )) + }) + }); + + /* + * debug + */ + + // GET debug/beacon/states/{state_id} + let get_debug_beacon_states = eth1_v1 + .and(warp::path("debug")) + .and(warp::path("beacon")) + .and(warp::path("states")) + .and(warp::path::param::()) + .and(warp::path::end()) + .and(chain_filter.clone()) + .and_then(|state_id: StateId, chain: Arc>| { + blocking_task(move || { + state_id.map_state(&chain, |state| { + Ok(warp::reply::json(&api_types::GenericResponseRef::from( + &state, + ))) + }) + }) + }); + + // GET debug/beacon/heads + let get_debug_beacon_heads = eth1_v1 + .and(warp::path("debug")) + .and(warp::path("beacon")) + .and(warp::path("heads")) + .and(warp::path::end()) + .and(chain_filter.clone()) + .and_then(|chain: Arc>| { + blocking_json_task(move || { + let heads = chain + .heads() + .into_iter() + .map(|(root, slot)| api_types::ChainHeadData { root, slot }) + .collect::>(); + Ok(api_types::GenericResponse::from(heads)) + }) + }); + + /* + * node + */ + + // GET node/identity + let get_node_identity = eth1_v1 + .and(warp::path("node")) + .and(warp::path("identity")) + .and(warp::path::end()) + .and(network_globals.clone()) + .and_then(|network_globals: Arc>| { + blocking_json_task(move || { + Ok(api_types::GenericResponse::from(api_types::IdentityData { + peer_id: network_globals.local_peer_id().to_base58(), + enr: network_globals.local_enr(), + p2p_addresses: network_globals.listen_multiaddrs(), + })) + }) + }); + + // GET node/version + let get_node_version = eth1_v1 + .and(warp::path("node")) + .and(warp::path("version")) + .and(warp::path::end()) + .and_then(|| { + blocking_json_task(move || { + Ok(api_types::GenericResponse::from(api_types::VersionData { + version: version_with_platform(), + })) + }) + }); + + // GET node/syncing + let get_node_syncing = eth1_v1 + .and(warp::path("node")) + .and(warp::path("syncing")) + .and(warp::path::end()) + .and(network_globals.clone()) + .and(chain_filter.clone()) + .and_then( + |network_globals: Arc>, chain: Arc>| { + blocking_json_task(move || { + let head_slot = chain + .head_info() + .map(|info| info.slot) + .map_err(warp_utils::reject::beacon_chain_error)?; + let current_slot = chain + .slot() + .map_err(warp_utils::reject::beacon_chain_error)?; + + // Taking advantage of saturating subtraction on slot. + let sync_distance = current_slot - head_slot; + + let syncing_data = api_types::SyncingData { + is_syncing: network_globals.sync_state.read().is_syncing(), + head_slot, + sync_distance, + }; + + Ok(api_types::GenericResponse::from(syncing_data)) + }) + }, + ); + + /* + * validator + */ + + // GET validator/duties/attester/{epoch} + let get_validator_duties_attester = eth1_v1 + .and(warp::path("validator")) + .and(warp::path("duties")) + .and(warp::path("attester")) + .and(warp::path::param::()) + .and(warp::path::end()) + .and(not_while_syncing_filter.clone()) + .and(warp::query::()) + .and(chain_filter.clone()) + .and_then( + |epoch: Epoch, query: api_types::ValidatorDutiesQuery, chain: Arc>| { + blocking_json_task(move || { + let current_epoch = chain + .epoch() + .map_err(warp_utils::reject::beacon_chain_error)?; + + if epoch > current_epoch + 1 { + return Err(warp_utils::reject::custom_bad_request(format!( + "request epoch {} is more than one epoch past the current epoch {}", + epoch, current_epoch + ))); + } + + let validator_count = StateId::head() + .map_state(&chain, |state| Ok(state.validators.len() as u64))?; + + let indices = query + .index + .as_ref() + .map(|index| index.0.clone()) + .map(Result::Ok) + .unwrap_or_else(|| { + Ok::<_, warp::Rejection>((0..validator_count).collect()) + })?; + + let pubkeys = indices + .into_iter() + .filter(|i| *i < validator_count as u64) + .map(|i| { + let pubkey = chain + .validator_pubkey(i as usize) + .map_err(warp_utils::reject::beacon_chain_error)? + .ok_or_else(|| { + warp_utils::reject::custom_bad_request(format!( + "unknown validator index {}", + i + )) + })?; + + Ok((i, pubkey)) + }) + .collect::, warp::Rejection>>()?; + + // Converts the internal Lighthouse `AttestationDuty` struct into an + // API-conforming `AttesterData` struct. + let convert = |validator_index: u64, + pubkey: PublicKey, + duty: AttestationDuty| + -> api_types::AttesterData { + api_types::AttesterData { + pubkey: pubkey.into(), + validator_index, + committees_at_slot: duty.committees_at_slot, + committee_index: duty.index, + committee_length: duty.committee_len as u64, + validator_committee_index: duty.committee_position as u64, + slot: duty.slot, + } + }; + + // Here we have two paths: + // + // ## Fast + // + // If the request epoch is the current epoch, use the cached beacon chain + // method. + // + // ## Slow + // + // If the request epoch is prior to the current epoch, load a beacon state from + // disk + // + // The idea is to stop historical requests from washing out the cache on the + // beacon chain, whilst allowing a VC to request duties quickly. + let duties = if epoch == current_epoch { + // Fast path. + pubkeys + .into_iter() + // Exclude indices which do not represent a known public key and a + // validator duty. + .filter_map(|(i, pubkey)| { + Some( + chain + .validator_attestation_duty(i as usize, epoch) + .transpose()? + .map_err(warp_utils::reject::beacon_chain_error) + .map(|duty| convert(i, pubkey, duty)), + ) + }) + .collect::, warp::Rejection>>()? + } else { + // If the head state is equal to or earlier than the request epoch, use it. + let mut state = chain + .with_head(|head| { + if head.beacon_state.current_epoch() <= epoch { + Ok(Some( + head.beacon_state + .clone_with(CloneConfig::committee_caches_only()), + )) + } else { + Ok(None) + } + }) + .map_err(warp_utils::reject::beacon_chain_error)? + .map(Result::Ok) + .unwrap_or_else(|| { + StateId::slot(epoch.start_slot(T::EthSpec::slots_per_epoch())) + .state(&chain) + })?; + + // Only skip forward to the epoch prior to the request, since we have a + // one-epoch look-ahead on shuffling. + while state + .next_epoch() + .map_err(warp_utils::reject::beacon_state_error)? + < epoch + { + // Don't calculate state roots since they aren't required for calculating + // shuffling (achieved by providing Hash256::zero()). + per_slot_processing(&mut state, Some(Hash256::zero()), &chain.spec) + .map_err(warp_utils::reject::slot_processing_error)?; + } + + let relative_epoch = + RelativeEpoch::from_epoch(state.current_epoch(), epoch).map_err( + |e| { + warp_utils::reject::custom_server_error(format!( + "unable to obtain suitable state: {:?}", + e + )) + }, + )?; + + state + .build_committee_cache(relative_epoch, &chain.spec) + .map_err(warp_utils::reject::beacon_state_error)?; + pubkeys + .into_iter() + .filter_map(|(i, pubkey)| { + Some( + state + .get_attestation_duties(i as usize, relative_epoch) + .transpose()? + .map_err(warp_utils::reject::beacon_state_error) + .map(|duty| convert(i, pubkey, duty)), + ) + }) + .collect::, warp::Rejection>>()? + }; + + Ok(api_types::GenericResponse::from(duties)) + }) + }, + ); + + // GET validator/duties/proposer/{epoch} + let get_validator_duties_proposer = eth1_v1 + .and(warp::path("validator")) + .and(warp::path("duties")) + .and(warp::path("proposer")) + .and(warp::path::param::()) + .and(warp::path::end()) + .and(not_while_syncing_filter.clone()) + .and(chain_filter.clone()) + .and(beacon_proposer_cache()) + .and_then( + |epoch: Epoch, + chain: Arc>, + beacon_proposer_cache: Arc>| { + blocking_json_task(move || { + beacon_proposer_cache + .lock() + .get_proposers(&chain, epoch) + .map(api_types::GenericResponse::from) + }) + }, + ); + + // GET validator/blocks/{slot} + let get_validator_blocks = eth1_v1 + .and(warp::path("validator")) + .and(warp::path("blocks")) + .and(warp::path::param::()) + .and(warp::path::end()) + .and(not_while_syncing_filter.clone()) + .and(warp::query::()) + .and(chain_filter.clone()) + .and_then( + |slot: Slot, query: api_types::ValidatorBlocksQuery, chain: Arc>| { + blocking_json_task(move || { + let randao_reveal = (&query.randao_reveal).try_into().map_err(|e| { + warp_utils::reject::custom_bad_request(format!( + "randao reveal is not valid BLS signature: {:?}", + e + )) + })?; + + chain + .produce_block(randao_reveal, slot, query.graffiti.map(Into::into)) + .map(|block_and_state| block_and_state.0) + .map(api_types::GenericResponse::from) + .map_err(warp_utils::reject::block_production_error) + }) + }, + ); + + // GET validator/attestation_data?slot,committee_index + let get_validator_attestation_data = eth1_v1 + .and(warp::path("validator")) + .and(warp::path("attestation_data")) + .and(warp::path::end()) + .and(warp::query::()) + .and(not_while_syncing_filter.clone()) + .and(chain_filter.clone()) + .and_then( + |query: api_types::ValidatorAttestationDataQuery, chain: Arc>| { + blocking_json_task(move || { + chain + .produce_unaggregated_attestation(query.slot, query.committee_index) + .map(|attestation| attestation.data) + .map(api_types::GenericResponse::from) + .map_err(warp_utils::reject::beacon_chain_error) + }) + }, + ); + + // GET validator/aggregate_attestation?attestation_data_root,slot + let get_validator_aggregate_attestation = eth1_v1 + .and(warp::path("validator")) + .and(warp::path("aggregate_attestation")) + .and(warp::path::end()) + .and(warp::query::()) + .and(not_while_syncing_filter.clone()) + .and(chain_filter.clone()) + .and_then( + |query: api_types::ValidatorAggregateAttestationQuery, chain: Arc>| { + blocking_json_task(move || { + chain + .get_aggregated_attestation_by_slot_and_root( + query.slot, + &query.attestation_data_root, + ) + .map(api_types::GenericResponse::from) + .ok_or_else(|| { + warp_utils::reject::custom_not_found( + "no matching aggregate found".to_string(), + ) + }) + }) + }, + ); + + // POST validator/aggregate_and_proofs + let post_validator_aggregate_and_proofs = eth1_v1 + .and(warp::path("validator")) + .and(warp::path("aggregate_and_proofs")) + .and(warp::path::end()) + .and(not_while_syncing_filter) + .and(chain_filter.clone()) + .and(warp::body::json()) + .and(network_tx_filter.clone()) + .and_then( + |chain: Arc>, + aggregate: SignedAggregateAndProof, + network_tx: UnboundedSender>| { + blocking_json_task(move || { + let aggregate = + match chain.verify_aggregated_attestation_for_gossip(aggregate.clone()) { + Ok(aggregate) => aggregate, + // If we already know the attestation, don't broadcast it or attempt to + // further verify it. Return success. + // + // It's reasonably likely that two different validators produce + // identical aggregates, especially if they're using the same beacon + // node. + Err(AttnError::AttestationAlreadyKnown(_)) => return Ok(()), + Err(e) => { + return Err(warp_utils::reject::object_invalid(format!( + "gossip verification failed: {:?}", + e + ))) + } + }; + + publish_pubsub_message( + &network_tx, + PubsubMessage::AggregateAndProofAttestation(Box::new( + aggregate.aggregate().clone(), + )), + )?; + + chain + .apply_attestation_to_fork_choice(&aggregate) + .map_err(|e| { + warp_utils::reject::broadcast_without_import(format!( + "not applied to fork choice: {:?}", + e + )) + })?; + + chain.add_to_block_inclusion_pool(aggregate).map_err(|e| { + warp_utils::reject::broadcast_without_import(format!( + "not applied to block inclusion pool: {:?}", + e + )) + })?; + + Ok(()) + }) + }, + ); + + // POST validator/beacon_committee_subscriptions + let post_validator_beacon_committee_subscriptions = eth1_v1 + .and(warp::path("validator")) + .and(warp::path("beacon_committee_subscriptions")) + .and(warp::path::end()) + .and(warp::body::json()) + .and(network_tx_filter) + .and_then( + |subscriptions: Vec, + network_tx: UnboundedSender>| { + blocking_json_task(move || { + for subscription in &subscriptions { + let subscription = api_types::ValidatorSubscription { + validator_index: subscription.validator_index, + attestation_committee_index: subscription.committee_index, + slot: subscription.slot, + committee_count_at_slot: subscription.committees_at_slot, + is_aggregator: subscription.is_aggregator, + }; + + publish_network_message( + &network_tx, + NetworkMessage::Subscribe { + subscriptions: vec![subscription], + }, + )?; + } + + Ok(()) + }) + }, + ); + + // GET lighthouse/health + let get_lighthouse_health = warp::path("lighthouse") + .and(warp::path("health")) + .and(warp::path::end()) + .and_then(|| { + blocking_json_task(move || { + eth2::lighthouse::Health::observe() + .map(api_types::GenericResponse::from) + .map_err(warp_utils::reject::custom_bad_request) + }) + }); + + // GET lighthouse/syncing + let get_lighthouse_syncing = warp::path("lighthouse") + .and(warp::path("syncing")) + .and(warp::path::end()) + .and(network_globals.clone()) + .and_then(|network_globals: Arc>| { + blocking_json_task(move || { + Ok(api_types::GenericResponse::from( + network_globals.sync_state(), + )) + }) + }); + + // GET lighthouse/peers + let get_lighthouse_peers = warp::path("lighthouse") + .and(warp::path("peers")) + .and(warp::path::end()) + .and(network_globals.clone()) + .and_then(|network_globals: Arc>| { + blocking_json_task(move || { + Ok(network_globals + .peers + .read() + .peers() + .map(|(peer_id, peer_info)| eth2::lighthouse::Peer { + peer_id: peer_id.to_string(), + peer_info: peer_info.clone(), + }) + .collect::>()) + }) + }); + + // GET lighthouse/peers/connected + let get_lighthouse_peers_connected = warp::path("lighthouse") + .and(warp::path("peers")) + .and(warp::path("connected")) + .and(warp::path::end()) + .and(network_globals) + .and_then(|network_globals: Arc>| { + blocking_json_task(move || { + Ok(network_globals + .peers + .read() + .connected_peers() + .map(|(peer_id, peer_info)| eth2::lighthouse::Peer { + peer_id: peer_id.to_string(), + peer_info: peer_info.clone(), + }) + .collect::>()) + }) + }); + + // GET lighthouse/proto_array + let get_lighthouse_proto_array = warp::path("lighthouse") + .and(warp::path("proto_array")) + .and(warp::path::end()) + .and(chain_filter.clone()) + .and_then(|chain: Arc>| { + blocking_task(move || { + Ok::<_, warp::Rejection>(warp::reply::json(&api_types::GenericResponseRef::from( + chain.fork_choice.read().proto_array().core_proto_array(), + ))) + }) + }); + + // GET lighthouse/validator_inclusion/{epoch}/{validator_id} + let get_lighthouse_validator_inclusion_global = warp::path("lighthouse") + .and(warp::path("validator_inclusion")) + .and(warp::path::param::()) + .and(warp::path::param::()) + .and(warp::path::end()) + .and(chain_filter.clone()) + .and_then( + |epoch: Epoch, validator_id: ValidatorId, chain: Arc>| { + blocking_json_task(move || { + validator_inclusion::validator_inclusion_data(epoch, &validator_id, &chain) + .map(api_types::GenericResponse::from) + }) + }, + ); + + // GET lighthouse/validator_inclusion/{epoch}/global + let get_lighthouse_validator_inclusion = warp::path("lighthouse") + .and(warp::path("validator_inclusion")) + .and(warp::path::param::()) + .and(warp::path("global")) + .and(warp::path::end()) + .and(chain_filter) + .and_then(|epoch: Epoch, chain: Arc>| { + blocking_json_task(move || { + validator_inclusion::global_validator_inclusion_data(epoch, &chain) + .map(api_types::GenericResponse::from) + }) + }); + + // Define the ultimate set of routes that will be provided to the server. + let routes = warp::get() + .and( + get_beacon_genesis + .or(get_beacon_state_root.boxed()) + .or(get_beacon_state_fork.boxed()) + .or(get_beacon_state_finality_checkpoints.boxed()) + .or(get_beacon_state_validators.boxed()) + .or(get_beacon_state_validators_id.boxed()) + .or(get_beacon_state_committees.boxed()) + .or(get_beacon_headers.boxed()) + .or(get_beacon_headers_block_id.boxed()) + .or(get_beacon_block.boxed()) + .or(get_beacon_block_attestations.boxed()) + .or(get_beacon_block_root.boxed()) + .or(get_beacon_pool_attestations.boxed()) + .or(get_beacon_pool_attester_slashings.boxed()) + .or(get_beacon_pool_proposer_slashings.boxed()) + .or(get_beacon_pool_voluntary_exits.boxed()) + .or(get_config_fork_schedule.boxed()) + .or(get_config_spec.boxed()) + .or(get_config_deposit_contract.boxed()) + .or(get_debug_beacon_states.boxed()) + .or(get_debug_beacon_heads.boxed()) + .or(get_node_identity.boxed()) + .or(get_node_version.boxed()) + .or(get_node_syncing.boxed()) + .or(get_validator_duties_attester.boxed()) + .or(get_validator_duties_proposer.boxed()) + .or(get_validator_blocks.boxed()) + .or(get_validator_attestation_data.boxed()) + .or(get_validator_aggregate_attestation.boxed()) + .or(get_lighthouse_health.boxed()) + .or(get_lighthouse_syncing.boxed()) + .or(get_lighthouse_peers.boxed()) + .or(get_lighthouse_peers_connected.boxed()) + .or(get_lighthouse_proto_array.boxed()) + .or(get_lighthouse_validator_inclusion_global.boxed()) + .or(get_lighthouse_validator_inclusion.boxed()) + .boxed(), + ) + .or(warp::post() + .and( + post_beacon_blocks + .or(post_beacon_pool_attestations.boxed()) + .or(post_beacon_pool_attester_slashings.boxed()) + .or(post_beacon_pool_proposer_slashings.boxed()) + .or(post_beacon_pool_voluntary_exits.boxed()) + .or(post_validator_aggregate_and_proofs.boxed()) + .or(post_validator_beacon_committee_subscriptions.boxed()) + .boxed(), + ) + .boxed()) + .boxed() + // Maps errors into HTTP responses. + .recover(warp_utils::reject::handle_rejection) + .with(slog_logging(log.clone())) + .with(prometheus_metrics()) + // Add a `Server` header. + .map(|reply| warp::reply::with_header(reply, "Server", &version_with_platform())) + // Maybe add some CORS headers. + .map(move |reply| warp_utils::reply::maybe_cors(reply, allow_origin.as_ref())); + + let (listening_socket, server) = warp::serve(routes).try_bind_with_graceful_shutdown( + SocketAddrV4::new(config.listen_addr, config.listen_port), + async { + shutdown.await; + }, + )?; + + info!( + log, + "HTTP API started"; + "listen_address" => listening_socket.to_string(), + ); + + Ok((listening_socket, server)) +} + +/// Publish a message to the libp2p pubsub network. +fn publish_pubsub_message( + network_tx: &UnboundedSender>, + message: PubsubMessage, +) -> Result<(), warp::Rejection> { + publish_network_message( + network_tx, + NetworkMessage::Publish { + messages: vec![message], + }, + ) +} + +/// Publish a message to the libp2p network. +fn publish_network_message( + network_tx: &UnboundedSender>, + message: NetworkMessage, +) -> Result<(), warp::Rejection> { + network_tx.send(message).map_err(|e| { + warp_utils::reject::custom_server_error(format!( + "unable to publish to network channel: {}", + e + )) + }) +} + +/// Execute some task in a tokio "blocking thread". These threads are ideal for long-running +/// (blocking) tasks since they don't jam up the core executor. +async fn blocking_task(func: F) -> T +where + F: Fn() -> T, +{ + tokio::task::block_in_place(func) +} + +/// A convenience wrapper around `blocking_task` for use with `warp` JSON responses. +async fn blocking_json_task(func: F) -> Result +where + F: Fn() -> Result, + T: Serialize, +{ + blocking_task(func) + .await + .map(|resp| warp::reply::json(&resp)) +} diff --git a/beacon_node/http_api/src/metrics.rs b/beacon_node/http_api/src/metrics.rs new file mode 100644 index 00000000000..c641df6a4a5 --- /dev/null +++ b/beacon_node/http_api/src/metrics.rs @@ -0,0 +1,32 @@ +pub use lighthouse_metrics::*; + +lazy_static::lazy_static! { + pub static ref HTTP_API_PATHS_TOTAL: Result = try_create_int_counter_vec( + "http_api_paths_total", + "Count of HTTP requests received", + &["path"] + ); + pub static ref HTTP_API_STATUS_CODES_TOTAL: Result = try_create_int_counter_vec( + "http_api_status_codes_total", + "Count of HTTP status codes returned", + &["status"] + ); + pub static ref HTTP_API_PATHS_TIMES: Result = try_create_histogram_vec( + "http_api_paths_times", + "Duration to process HTTP requests per path", + &["path"] + ); + + pub static ref HTTP_API_BEACON_PROPOSER_CACHE_TIMES: Result = try_create_histogram( + "http_api_beacon_proposer_cache_build_times", + "Duration to process HTTP requests per path", + ); + pub static ref HTTP_API_BEACON_PROPOSER_CACHE_HITS_TOTAL: Result = try_create_int_counter( + "http_api_beacon_proposer_cache_hits_total", + "Count of times the proposer cache has been hit", + ); + pub static ref HTTP_API_BEACON_PROPOSER_CACHE_MISSES_TOTAL: Result = try_create_int_counter( + "http_api_beacon_proposer_cache_misses_total", + "Count of times the proposer cache has been missed", + ); +} diff --git a/beacon_node/http_api/src/state_id.rs b/beacon_node/http_api/src/state_id.rs new file mode 100644 index 00000000000..11800648f25 --- /dev/null +++ b/beacon_node/http_api/src/state_id.rs @@ -0,0 +1,118 @@ +use beacon_chain::{BeaconChain, BeaconChainTypes}; +use eth2::types::StateId as CoreStateId; +use std::str::FromStr; +use types::{BeaconState, EthSpec, Fork, Hash256, Slot}; + +/// Wraps `eth2::types::StateId` and provides common state-access functionality. E.g., reading +/// states or parts of states from the database. +pub struct StateId(CoreStateId); + +impl StateId { + pub fn head() -> Self { + Self(CoreStateId::Head) + } + + pub fn slot(slot: Slot) -> Self { + Self(CoreStateId::Slot(slot)) + } + + /// Return the state root identified by `self`. + pub fn root( + &self, + chain: &BeaconChain, + ) -> Result { + let slot = match &self.0 { + CoreStateId::Head => { + return chain + .head_info() + .map(|head| head.state_root) + .map_err(warp_utils::reject::beacon_chain_error) + } + CoreStateId::Genesis => return Ok(chain.genesis_state_root), + CoreStateId::Finalized => chain.head_info().map(|head| { + head.finalized_checkpoint + .epoch + .start_slot(T::EthSpec::slots_per_epoch()) + }), + CoreStateId::Justified => chain.head_info().map(|head| { + head.current_justified_checkpoint + .epoch + .start_slot(T::EthSpec::slots_per_epoch()) + }), + CoreStateId::Slot(slot) => Ok(*slot), + CoreStateId::Root(root) => return Ok(*root), + } + .map_err(warp_utils::reject::beacon_chain_error)?; + + chain + .state_root_at_slot(slot) + .map_err(warp_utils::reject::beacon_chain_error)? + .ok_or_else(|| { + warp_utils::reject::custom_not_found(format!("beacon state at slot {}", slot)) + }) + } + + /// Return the `fork` field of the state identified by `self`. + pub fn fork( + &self, + chain: &BeaconChain, + ) -> Result { + self.map_state(chain, |state| Ok(state.fork)) + } + + /// Return the `BeaconState` identified by `self`. + pub fn state( + &self, + chain: &BeaconChain, + ) -> Result, warp::Rejection> { + let (state_root, slot_opt) = match &self.0 { + CoreStateId::Head => { + return chain + .head_beacon_state() + .map_err(warp_utils::reject::beacon_chain_error) + } + CoreStateId::Slot(slot) => (self.root(chain)?, Some(*slot)), + _ => (self.root(chain)?, None), + }; + + chain + .get_state(&state_root, slot_opt) + .map_err(warp_utils::reject::beacon_chain_error) + .and_then(|opt| { + opt.ok_or_else(|| { + warp_utils::reject::custom_not_found(format!( + "beacon state at root {}", + state_root + )) + }) + }) + } + + /// Map a function across the `BeaconState` identified by `self`. + /// + /// This function will avoid instantiating/copying a new state when `self` points to the head + /// of the chain. + pub fn map_state( + &self, + chain: &BeaconChain, + func: F, + ) -> Result + where + F: Fn(&BeaconState) -> Result, + { + match &self.0 { + CoreStateId::Head => chain + .with_head(|snapshot| Ok(func(&snapshot.beacon_state))) + .map_err(warp_utils::reject::beacon_chain_error)?, + _ => func(&self.state(chain)?), + } + } +} + +impl FromStr for StateId { + type Err = String; + + fn from_str(s: &str) -> Result { + CoreStateId::from_str(s).map(Self) + } +} diff --git a/beacon_node/http_api/src/validator_inclusion.rs b/beacon_node/http_api/src/validator_inclusion.rs new file mode 100644 index 00000000000..90847dd6b4e --- /dev/null +++ b/beacon_node/http_api/src/validator_inclusion.rs @@ -0,0 +1,88 @@ +use crate::state_id::StateId; +use beacon_chain::{BeaconChain, BeaconChainTypes}; +use eth2::{ + lighthouse::{GlobalValidatorInclusionData, ValidatorInclusionData}, + types::ValidatorId, +}; +use state_processing::per_epoch_processing::ValidatorStatuses; +use types::{Epoch, EthSpec}; + +/// Returns information about *all validators* (i.e., global) and how they performed during a given +/// epoch. +pub fn global_validator_inclusion_data( + epoch: Epoch, + chain: &BeaconChain, +) -> Result { + let target_slot = epoch.end_slot(T::EthSpec::slots_per_epoch()); + + let state = StateId::slot(target_slot).state(chain)?; + + let mut validator_statuses = ValidatorStatuses::new(&state, &chain.spec) + .map_err(warp_utils::reject::beacon_state_error)?; + validator_statuses + .process_attestations(&state, &chain.spec) + .map_err(warp_utils::reject::beacon_state_error)?; + + let totals = validator_statuses.total_balances; + + Ok(GlobalValidatorInclusionData { + current_epoch_active_gwei: totals.current_epoch(), + previous_epoch_active_gwei: totals.previous_epoch(), + current_epoch_attesting_gwei: totals.current_epoch_attesters(), + current_epoch_target_attesting_gwei: totals.current_epoch_target_attesters(), + previous_epoch_attesting_gwei: totals.previous_epoch_attesters(), + previous_epoch_target_attesting_gwei: totals.previous_epoch_target_attesters(), + previous_epoch_head_attesting_gwei: totals.previous_epoch_head_attesters(), + }) +} + +/// Returns information about a single validator and how it performed during a given epoch. +pub fn validator_inclusion_data( + epoch: Epoch, + validator_id: &ValidatorId, + chain: &BeaconChain, +) -> Result, warp::Rejection> { + let target_slot = epoch.end_slot(T::EthSpec::slots_per_epoch()); + + let mut state = StateId::slot(target_slot).state(chain)?; + + let mut validator_statuses = ValidatorStatuses::new(&state, &chain.spec) + .map_err(warp_utils::reject::beacon_state_error)?; + validator_statuses + .process_attestations(&state, &chain.spec) + .map_err(warp_utils::reject::beacon_state_error)?; + + state + .update_pubkey_cache() + .map_err(warp_utils::reject::beacon_state_error)?; + + let validator_index = match validator_id { + ValidatorId::Index(index) => *index as usize, + ValidatorId::PublicKey(pubkey) => { + if let Some(index) = state + .get_validator_index(pubkey) + .map_err(warp_utils::reject::beacon_state_error)? + { + index + } else { + return Ok(None); + } + } + }; + + Ok(validator_statuses + .statuses + .get(validator_index) + .map(|vote| ValidatorInclusionData { + is_slashed: vote.is_slashed, + is_withdrawable_in_current_epoch: vote.is_withdrawable_in_current_epoch, + is_active_in_current_epoch: vote.is_active_in_current_epoch, + is_active_in_previous_epoch: vote.is_active_in_previous_epoch, + current_epoch_effective_balance_gwei: vote.current_epoch_effective_balance, + is_current_epoch_attester: vote.is_current_epoch_attester, + is_current_epoch_target_attester: vote.is_current_epoch_target_attester, + is_previous_epoch_attester: vote.is_previous_epoch_attester, + is_previous_epoch_target_attester: vote.is_previous_epoch_target_attester, + is_previous_epoch_head_attester: vote.is_previous_epoch_head_attester, + })) +} diff --git a/beacon_node/http_api/tests/tests.rs b/beacon_node/http_api/tests/tests.rs new file mode 100644 index 00000000000..2a7e8f6d40a --- /dev/null +++ b/beacon_node/http_api/tests/tests.rs @@ -0,0 +1,1786 @@ +use beacon_chain::{ + test_utils::{ + AttestationStrategy, BeaconChainHarness, BlockStrategy, + BlockingMigratorEphemeralHarnessType, + }, + BeaconChain, StateSkipConfig, +}; +use discv5::enr::{CombinedKey, EnrBuilder}; +use environment::null_logger; +use eth2::{types::*, BeaconNodeHttpClient, Url}; +use eth2_libp2p::{ + rpc::methods::MetaData, + types::{EnrBitfield, SyncState}, + NetworkGlobals, +}; +use http_api::{Config, Context}; +use network::NetworkMessage; +use state_processing::per_slot_processing; +use std::convert::TryInto; +use std::net::Ipv4Addr; +use std::sync::Arc; +use tokio::sync::mpsc; +use tokio::sync::oneshot; +use tree_hash::TreeHash; +use types::{ + test_utils::generate_deterministic_keypairs, AggregateSignature, BeaconState, BitList, Domain, + EthSpec, Hash256, Keypair, MainnetEthSpec, RelativeEpoch, SelectionProof, SignedRoot, Slot, +}; + +type E = MainnetEthSpec; + +const SLOTS_PER_EPOCH: u64 = 32; +const VALIDATOR_COUNT: usize = SLOTS_PER_EPOCH as usize; +const CHAIN_LENGTH: u64 = SLOTS_PER_EPOCH * 5; +const JUSTIFIED_EPOCH: u64 = 4; +const FINALIZED_EPOCH: u64 = 3; + +/// Skipping the slots around the epoch boundary allows us to check that we're obtaining states +/// from skipped slots for the finalized and justified checkpoints (instead of the state from the +/// block that those roots point to). +const SKIPPED_SLOTS: &[u64] = &[ + JUSTIFIED_EPOCH * SLOTS_PER_EPOCH - 1, + JUSTIFIED_EPOCH * SLOTS_PER_EPOCH, + FINALIZED_EPOCH * SLOTS_PER_EPOCH - 1, + FINALIZED_EPOCH * SLOTS_PER_EPOCH, +]; + +struct ApiTester { + chain: Arc>>, + client: BeaconNodeHttpClient, + next_block: SignedBeaconBlock, + attestations: Vec>, + attester_slashing: AttesterSlashing, + proposer_slashing: ProposerSlashing, + voluntary_exit: SignedVoluntaryExit, + _server_shutdown: oneshot::Sender<()>, + validator_keypairs: Vec, + network_rx: mpsc::UnboundedReceiver>, +} + +impl ApiTester { + pub fn new() -> Self { + let mut harness = BeaconChainHarness::new( + MainnetEthSpec, + generate_deterministic_keypairs(VALIDATOR_COUNT), + ); + + harness.advance_slot(); + + for _ in 0..CHAIN_LENGTH { + let slot = harness.chain.slot().unwrap().as_u64(); + + if !SKIPPED_SLOTS.contains(&slot) { + harness.extend_chain( + 1, + BlockStrategy::OnCanonicalHead, + AttestationStrategy::AllValidators, + ); + } + + harness.advance_slot(); + } + + let head = harness.chain.head().unwrap(); + + assert_eq!( + harness.chain.slot().unwrap(), + head.beacon_block.slot() + 1, + "precondition: current slot is one after head" + ); + + let (next_block, _next_state) = + harness.make_block(head.beacon_state.clone(), harness.chain.slot().unwrap()); + + let attestations = harness + .get_unaggregated_attestations( + &AttestationStrategy::AllValidators, + &head.beacon_state, + head.beacon_block_root, + harness.chain.slot().unwrap(), + ) + .into_iter() + .map(|vec| vec.into_iter().map(|(attestation, _subnet_id)| attestation)) + .flatten() + .collect::>(); + + assert!( + !attestations.is_empty(), + "precondition: attestations for testing" + ); + + let attester_slashing = harness.make_attester_slashing(vec![0, 1]); + let proposer_slashing = harness.make_proposer_slashing(2); + let voluntary_exit = harness.make_voluntary_exit(3, harness.chain.epoch().unwrap()); + + // Changing this *after* the chain has been initialized is a bit cheeky, but it shouldn't + // cause issue. + // + // This allows for testing voluntary exits without building out a massive chain. + harness.chain.spec.shard_committee_period = 2; + + let chain = Arc::new(harness.chain); + + assert_eq!( + chain.head_info().unwrap().finalized_checkpoint.epoch, + 3, + "precondition: finality" + ); + assert_eq!( + chain + .head_info() + .unwrap() + .current_justified_checkpoint + .epoch, + 4, + "precondition: justification" + ); + + let (network_tx, network_rx) = mpsc::unbounded_channel(); + + let log = null_logger().unwrap(); + + // Default metadata + let meta_data = MetaData { + seq_number: 0, + attnets: EnrBitfield::::default(), + }; + let enr_key = CombinedKey::generate_secp256k1(); + let enr = EnrBuilder::new("v4").build(&enr_key).unwrap(); + let network_globals = NetworkGlobals::new(enr, 42, 42, meta_data, vec![], &log); + + *network_globals.sync_state.write() = SyncState::Synced; + + let context = Arc::new(Context { + config: Config { + enabled: true, + listen_addr: Ipv4Addr::new(127, 0, 0, 1), + listen_port: 0, + allow_origin: None, + }, + chain: Some(chain.clone()), + network_tx: Some(network_tx), + network_globals: Some(Arc::new(network_globals)), + log, + }); + let ctx = context.clone(); + let (shutdown_tx, shutdown_rx) = oneshot::channel(); + let server_shutdown = async { + // It's not really interesting why this triggered, just that it happened. + let _ = shutdown_rx.await; + }; + let (listening_socket, server) = http_api::serve(ctx, server_shutdown).unwrap(); + + tokio::spawn(async { server.await }); + + let client = BeaconNodeHttpClient::new( + Url::parse(&format!( + "http://{}:{}", + listening_socket.ip(), + listening_socket.port() + )) + .unwrap(), + ); + + Self { + chain, + client, + next_block, + attestations, + attester_slashing, + proposer_slashing, + voluntary_exit, + _server_shutdown: shutdown_tx, + validator_keypairs: harness.validators_keypairs, + network_rx, + } + } + + fn skip_slots(self, count: u64) -> Self { + for _ in 0..count { + self.chain + .slot_clock + .set_slot(self.chain.slot().unwrap().as_u64() + 1); + } + + self + } + + fn interesting_state_ids(&self) -> Vec { + let mut ids = vec![ + StateId::Head, + StateId::Genesis, + StateId::Finalized, + StateId::Justified, + StateId::Slot(Slot::new(0)), + StateId::Slot(Slot::new(32)), + StateId::Slot(Slot::from(SKIPPED_SLOTS[0])), + StateId::Slot(Slot::from(SKIPPED_SLOTS[1])), + StateId::Slot(Slot::from(SKIPPED_SLOTS[2])), + StateId::Slot(Slot::from(SKIPPED_SLOTS[3])), + StateId::Root(Hash256::zero()), + ]; + ids.push(StateId::Root(self.chain.head_info().unwrap().state_root)); + ids + } + + fn interesting_block_ids(&self) -> Vec { + let mut ids = vec![ + BlockId::Head, + BlockId::Genesis, + BlockId::Finalized, + BlockId::Justified, + BlockId::Slot(Slot::new(0)), + BlockId::Slot(Slot::new(32)), + BlockId::Slot(Slot::from(SKIPPED_SLOTS[0])), + BlockId::Slot(Slot::from(SKIPPED_SLOTS[1])), + BlockId::Slot(Slot::from(SKIPPED_SLOTS[2])), + BlockId::Slot(Slot::from(SKIPPED_SLOTS[3])), + BlockId::Root(Hash256::zero()), + ]; + ids.push(BlockId::Root(self.chain.head_info().unwrap().block_root)); + ids + } + + fn get_state(&self, state_id: StateId) -> Option> { + match state_id { + StateId::Head => Some(self.chain.head().unwrap().beacon_state), + StateId::Genesis => self + .chain + .get_state(&self.chain.genesis_state_root, None) + .unwrap(), + StateId::Finalized => { + let finalized_slot = self + .chain + .head_info() + .unwrap() + .finalized_checkpoint + .epoch + .start_slot(E::slots_per_epoch()); + + let root = self + .chain + .state_root_at_slot(finalized_slot) + .unwrap() + .unwrap(); + + self.chain.get_state(&root, Some(finalized_slot)).unwrap() + } + StateId::Justified => { + let justified_slot = self + .chain + .head_info() + .unwrap() + .current_justified_checkpoint + .epoch + .start_slot(E::slots_per_epoch()); + + let root = self + .chain + .state_root_at_slot(justified_slot) + .unwrap() + .unwrap(); + + self.chain.get_state(&root, Some(justified_slot)).unwrap() + } + StateId::Slot(slot) => { + let root = self.chain.state_root_at_slot(slot).unwrap().unwrap(); + + self.chain.get_state(&root, Some(slot)).unwrap() + } + StateId::Root(root) => self.chain.get_state(&root, None).unwrap(), + } + } + + pub async fn test_beacon_genesis(self) -> Self { + let result = self.client.get_beacon_genesis().await.unwrap().data; + + let state = self.chain.head().unwrap().beacon_state; + let expected = GenesisData { + genesis_time: state.genesis_time, + genesis_validators_root: state.genesis_validators_root, + genesis_fork_version: self.chain.spec.genesis_fork_version, + }; + + assert_eq!(result, expected); + + self + } + + pub async fn test_beacon_states_root(self) -> Self { + for state_id in self.interesting_state_ids() { + let result = self + .client + .get_beacon_states_root(state_id) + .await + .unwrap() + .map(|res| res.data.root); + + let expected = match state_id { + StateId::Head => Some(self.chain.head_info().unwrap().state_root), + StateId::Genesis => Some(self.chain.genesis_state_root), + StateId::Finalized => { + let finalized_slot = self + .chain + .head_info() + .unwrap() + .finalized_checkpoint + .epoch + .start_slot(E::slots_per_epoch()); + + self.chain.state_root_at_slot(finalized_slot).unwrap() + } + StateId::Justified => { + let justified_slot = self + .chain + .head_info() + .unwrap() + .current_justified_checkpoint + .epoch + .start_slot(E::slots_per_epoch()); + + self.chain.state_root_at_slot(justified_slot).unwrap() + } + StateId::Slot(slot) => self.chain.state_root_at_slot(slot).unwrap(), + StateId::Root(root) => Some(root), + }; + + assert_eq!(result, expected, "{:?}", state_id); + } + + self + } + + pub async fn test_beacon_states_fork(self) -> Self { + for state_id in self.interesting_state_ids() { + let result = self + .client + .get_beacon_states_fork(state_id) + .await + .unwrap() + .map(|res| res.data); + + let expected = self.get_state(state_id).map(|state| state.fork); + + assert_eq!(result, expected, "{:?}", state_id); + } + + self + } + + pub async fn test_beacon_states_finality_checkpoints(self) -> Self { + for state_id in self.interesting_state_ids() { + let result = self + .client + .get_beacon_states_finality_checkpoints(state_id) + .await + .unwrap() + .map(|res| res.data); + + let expected = self + .get_state(state_id) + .map(|state| FinalityCheckpointsData { + previous_justified: state.previous_justified_checkpoint, + current_justified: state.current_justified_checkpoint, + finalized: state.finalized_checkpoint, + }); + + assert_eq!(result, expected, "{:?}", state_id); + } + + self + } + + pub async fn test_beacon_states_validators(self) -> Self { + for state_id in self.interesting_state_ids() { + let result = self + .client + .get_beacon_states_validators(state_id) + .await + .unwrap() + .map(|res| res.data); + + let expected = self.get_state(state_id).map(|state| { + let epoch = state.current_epoch(); + let finalized_epoch = state.finalized_checkpoint.epoch; + let far_future_epoch = self.chain.spec.far_future_epoch; + + let mut validators = Vec::with_capacity(state.validators.len()); + + for i in 0..state.validators.len() { + let validator = state.validators[i].clone(); + + validators.push(ValidatorData { + index: i as u64, + balance: state.balances[i], + status: ValidatorStatus::from_validator( + Some(&validator), + epoch, + finalized_epoch, + far_future_epoch, + ), + validator, + }) + } + + validators + }); + + assert_eq!(result, expected, "{:?}", state_id); + } + + self + } + + pub async fn test_beacon_states_validator_id(self) -> Self { + for state_id in self.interesting_state_ids() { + let state_opt = self.get_state(state_id); + let validators = match state_opt.as_ref() { + Some(state) => state.validators.clone().into(), + None => vec![], + }; + + for (i, validator) in validators.into_iter().enumerate() { + let validator_ids = &[ + ValidatorId::PublicKey(validator.pubkey.clone()), + ValidatorId::Index(i as u64), + ]; + + for validator_id in validator_ids { + let result = self + .client + .get_beacon_states_validator_id(state_id, validator_id) + .await + .unwrap() + .map(|res| res.data); + + if result.is_none() && state_opt.is_none() { + continue; + } + + let state = state_opt.as_ref().expect("result should be none"); + + let expected = { + let epoch = state.current_epoch(); + let finalized_epoch = state.finalized_checkpoint.epoch; + let far_future_epoch = self.chain.spec.far_future_epoch; + + ValidatorData { + index: i as u64, + balance: state.balances[i], + status: ValidatorStatus::from_validator( + Some(&validator), + epoch, + finalized_epoch, + far_future_epoch, + ), + validator: validator.clone(), + } + }; + + assert_eq!(result, Some(expected), "{:?}, {:?}", state_id, validator_id); + } + } + } + + self + } + + pub async fn test_beacon_states_committees(self) -> Self { + for state_id in self.interesting_state_ids() { + let mut state_opt = self.get_state(state_id); + + let epoch = state_opt + .as_ref() + .map(|state| state.current_epoch()) + .unwrap_or_else(|| Epoch::new(0)); + + let results = self + .client + .get_beacon_states_committees(state_id, epoch, None, None) + .await + .unwrap() + .map(|res| res.data); + + if results.is_none() && state_opt.is_none() { + continue; + } + + let state = state_opt.as_mut().expect("result should be none"); + state.build_all_committee_caches(&self.chain.spec).unwrap(); + let committees = state + .get_beacon_committees_at_epoch( + RelativeEpoch::from_epoch(state.current_epoch(), epoch).unwrap(), + ) + .unwrap(); + + for (i, result) in results.unwrap().into_iter().enumerate() { + let expected = &committees[i]; + + assert_eq!(result.index, expected.index, "{}", state_id); + assert_eq!(result.slot, expected.slot, "{}", state_id); + assert_eq!( + result + .validators + .into_iter() + .map(|i| i as usize) + .collect::>(), + expected.committee.to_vec(), + "{}", + state_id + ); + } + } + + self + } + + fn get_block_root(&self, block_id: BlockId) -> Option { + match block_id { + BlockId::Head => Some(self.chain.head_info().unwrap().block_root), + BlockId::Genesis => Some(self.chain.genesis_block_root), + BlockId::Finalized => Some(self.chain.head_info().unwrap().finalized_checkpoint.root), + BlockId::Justified => Some( + self.chain + .head_info() + .unwrap() + .current_justified_checkpoint + .root, + ), + BlockId::Slot(slot) => self.chain.block_root_at_slot(slot).unwrap(), + BlockId::Root(root) => Some(root), + } + } + + fn get_block(&self, block_id: BlockId) -> Option> { + let root = self.get_block_root(block_id); + root.and_then(|root| self.chain.get_block(&root).unwrap()) + } + + pub async fn test_beacon_headers_all_slots(self) -> Self { + for slot in 0..CHAIN_LENGTH { + let slot = Slot::from(slot); + + let result = self + .client + .get_beacon_headers(Some(slot), None) + .await + .unwrap() + .map(|res| res.data); + + let root = self.chain.block_root_at_slot(slot).unwrap(); + + if root.is_none() && result.is_none() { + continue; + } + + let root = root.unwrap(); + let block = self.chain.block_at_slot(slot).unwrap().unwrap(); + let header = BlockHeaderData { + root, + canonical: true, + header: BlockHeaderAndSignature { + message: block.message.block_header(), + signature: block.signature.into(), + }, + }; + let expected = vec![header]; + + assert_eq!(result.unwrap(), expected, "slot {:?}", slot); + } + + self + } + + pub async fn test_beacon_headers_all_parents(self) -> Self { + let mut roots = self + .chain + .rev_iter_block_roots() + .unwrap() + .map(Result::unwrap) + .map(|(root, _slot)| root) + .collect::>() + .into_iter() + .rev() + .collect::>(); + + // The iterator natively returns duplicate roots for skipped slots. + roots.dedup(); + + for i in 1..roots.len() { + let parent_root = roots[i - 1]; + let child_root = roots[i]; + + let result = self + .client + .get_beacon_headers(None, Some(parent_root)) + .await + .unwrap() + .unwrap() + .data; + + assert_eq!(result.len(), 1, "i {}", i); + assert_eq!(result[0].root, child_root, "i {}", i); + } + + self + } + + pub async fn test_beacon_headers_block_id(self) -> Self { + for block_id in self.interesting_block_ids() { + let result = self + .client + .get_beacon_headers_block_id(block_id) + .await + .unwrap() + .map(|res| res.data); + + let block_root_opt = self.get_block_root(block_id); + + let block_opt = block_root_opt.and_then(|root| self.chain.get_block(&root).unwrap()); + + if block_opt.is_none() && result.is_none() { + continue; + } + + let result = result.unwrap(); + let block = block_opt.unwrap(); + let block_root = block_root_opt.unwrap(); + let canonical = self + .chain + .block_root_at_slot(block.slot()) + .unwrap() + .map_or(false, |canonical| block_root == canonical); + + assert_eq!(result.canonical, canonical, "{:?}", block_id); + assert_eq!(result.root, block_root, "{:?}", block_id); + assert_eq!( + result.header.message, + block.message.block_header(), + "{:?}", + block_id + ); + assert_eq!( + result.header.signature, + block.signature.into(), + "{:?}", + block_id + ); + } + + self + } + + pub async fn test_beacon_blocks_root(self) -> Self { + for block_id in self.interesting_block_ids() { + let result = self + .client + .get_beacon_blocks_root(block_id) + .await + .unwrap() + .map(|res| res.data.root); + + let expected = self.get_block_root(block_id); + + assert_eq!(result, expected, "{:?}", block_id); + } + + self + } + + pub async fn test_post_beacon_blocks_valid(mut self) -> Self { + let next_block = &self.next_block; + + self.client.post_beacon_blocks(next_block).await.unwrap(); + + assert!( + self.network_rx.try_recv().is_ok(), + "valid blocks should be sent to network" + ); + + self + } + + pub async fn test_post_beacon_blocks_invalid(mut self) -> Self { + let mut next_block = self.next_block.clone(); + next_block.message.proposer_index += 1; + + assert!(self.client.post_beacon_blocks(&next_block).await.is_err()); + + assert!( + self.network_rx.try_recv().is_ok(), + "invalid blocks should be sent to network" + ); + + self + } + + pub async fn test_beacon_blocks(self) -> Self { + for block_id in self.interesting_block_ids() { + let result = self + .client + .get_beacon_blocks(block_id) + .await + .unwrap() + .map(|res| res.data); + + let expected = self.get_block(block_id); + + assert_eq!(result, expected, "{:?}", block_id); + } + + self + } + + pub async fn test_beacon_blocks_attestations(self) -> Self { + for block_id in self.interesting_block_ids() { + let result = self + .client + .get_beacon_blocks_attestations(block_id) + .await + .unwrap() + .map(|res| res.data); + + let expected = self + .get_block(block_id) + .map(|block| block.message.body.attestations.into()); + + assert_eq!(result, expected, "{:?}", block_id); + } + + self + } + + pub async fn test_post_beacon_pool_attestations_valid(mut self) -> Self { + for attestation in &self.attestations { + self.client + .post_beacon_pool_attestations(attestation) + .await + .unwrap(); + + assert!( + self.network_rx.try_recv().is_ok(), + "valid attestation should be sent to network" + ); + } + + self + } + + pub async fn test_post_beacon_pool_attestations_invalid(mut self) -> Self { + for attestation in &self.attestations { + let mut attestation = attestation.clone(); + attestation.data.slot += 1; + + assert!(self + .client + .post_beacon_pool_attestations(&attestation) + .await + .is_err()); + + assert!( + self.network_rx.try_recv().is_err(), + "invalid attestation should not be sent to network" + ); + } + + self + } + + pub async fn test_get_beacon_pool_attestations(self) -> Self { + let result = self + .client + .get_beacon_pool_attestations() + .await + .unwrap() + .data; + + let mut expected = self.chain.op_pool.get_all_attestations(); + expected.extend(self.chain.naive_aggregation_pool.read().iter().cloned()); + + assert_eq!(result, expected); + + self + } + + pub async fn test_post_beacon_pool_attester_slashings_valid(mut self) -> Self { + self.client + .post_beacon_pool_attester_slashings(&self.attester_slashing) + .await + .unwrap(); + + assert!( + self.network_rx.try_recv().is_ok(), + "valid attester slashing should be sent to network" + ); + + self + } + + pub async fn test_post_beacon_pool_attester_slashings_invalid(mut self) -> Self { + let mut slashing = self.attester_slashing.clone(); + slashing.attestation_1.data.slot += 1; + + self.client + .post_beacon_pool_attester_slashings(&slashing) + .await + .unwrap_err(); + + assert!( + self.network_rx.try_recv().is_err(), + "invalid attester slashing should not be sent to network" + ); + + self + } + + pub async fn test_get_beacon_pool_attester_slashings(self) -> Self { + let result = self + .client + .get_beacon_pool_attester_slashings() + .await + .unwrap() + .data; + + let expected = self.chain.op_pool.get_all_attester_slashings(); + + assert_eq!(result, expected); + + self + } + + pub async fn test_post_beacon_pool_proposer_slashings_valid(mut self) -> Self { + self.client + .post_beacon_pool_proposer_slashings(&self.proposer_slashing) + .await + .unwrap(); + + assert!( + self.network_rx.try_recv().is_ok(), + "valid proposer slashing should be sent to network" + ); + + self + } + + pub async fn test_post_beacon_pool_proposer_slashings_invalid(mut self) -> Self { + let mut slashing = self.proposer_slashing.clone(); + slashing.signed_header_1.message.slot += 1; + + self.client + .post_beacon_pool_proposer_slashings(&slashing) + .await + .unwrap_err(); + + assert!( + self.network_rx.try_recv().is_err(), + "invalid proposer slashing should not be sent to network" + ); + + self + } + + pub async fn test_get_beacon_pool_proposer_slashings(self) -> Self { + let result = self + .client + .get_beacon_pool_proposer_slashings() + .await + .unwrap() + .data; + + let expected = self.chain.op_pool.get_all_proposer_slashings(); + + assert_eq!(result, expected); + + self + } + + pub async fn test_post_beacon_pool_voluntary_exits_valid(mut self) -> Self { + self.client + .post_beacon_pool_voluntary_exits(&self.voluntary_exit) + .await + .unwrap(); + + assert!( + self.network_rx.try_recv().is_ok(), + "valid exit should be sent to network" + ); + + self + } + + pub async fn test_post_beacon_pool_voluntary_exits_invalid(mut self) -> Self { + let mut exit = self.voluntary_exit.clone(); + exit.message.epoch += 1; + + self.client + .post_beacon_pool_voluntary_exits(&exit) + .await + .unwrap_err(); + + assert!( + self.network_rx.try_recv().is_err(), + "invalid exit should not be sent to network" + ); + + self + } + + pub async fn test_get_beacon_pool_voluntary_exits(self) -> Self { + let result = self + .client + .get_beacon_pool_voluntary_exits() + .await + .unwrap() + .data; + + let expected = self.chain.op_pool.get_all_voluntary_exits(); + + assert_eq!(result, expected); + + self + } + + pub async fn test_get_config_fork_schedule(self) -> Self { + let result = self.client.get_config_fork_schedule().await.unwrap().data; + + let expected = vec![self.chain.head_info().unwrap().fork]; + + assert_eq!(result, expected); + + self + } + + pub async fn test_get_config_spec(self) -> Self { + let result = self.client.get_config_spec().await.unwrap().data; + + let expected = YamlConfig::from_spec::(&self.chain.spec); + + assert_eq!(result, expected); + + self + } + + pub async fn test_get_config_deposit_contract(self) -> Self { + let result = self + .client + .get_config_deposit_contract() + .await + .unwrap() + .data; + + let expected = DepositContractData { + address: self.chain.spec.deposit_contract_address, + chain_id: eth1::DEFAULT_NETWORK_ID.into(), + }; + + assert_eq!(result, expected); + + self + } + + pub async fn test_get_node_version(self) -> Self { + let result = self.client.get_node_version().await.unwrap().data; + + let expected = VersionData { + version: lighthouse_version::version_with_platform(), + }; + + assert_eq!(result, expected); + + self + } + + pub async fn test_get_node_syncing(self) -> Self { + let result = self.client.get_node_syncing().await.unwrap().data; + let head_slot = self.chain.head_info().unwrap().slot; + let sync_distance = self.chain.slot().unwrap() - head_slot; + + let expected = SyncingData { + is_syncing: false, + head_slot, + sync_distance, + }; + + assert_eq!(result, expected); + + self + } + + pub async fn test_get_debug_beacon_states(self) -> Self { + for state_id in self.interesting_state_ids() { + let result = self + .client + .get_debug_beacon_states(state_id) + .await + .unwrap() + .map(|res| res.data); + + let mut expected = self.get_state(state_id); + expected.as_mut().map(|state| state.drop_all_caches()); + + assert_eq!(result, expected, "{:?}", state_id); + } + + self + } + + pub async fn test_get_debug_beacon_heads(self) -> Self { + let result = self + .client + .get_debug_beacon_heads() + .await + .unwrap() + .data + .into_iter() + .map(|head| (head.root, head.slot)) + .collect::>(); + + let expected = self.chain.heads(); + + assert_eq!(result, expected); + + self + } + + fn validator_count(&self) -> usize { + self.chain.head().unwrap().beacon_state.validators.len() + } + + fn interesting_validator_indices(&self) -> Vec> { + let validator_count = self.validator_count() as u64; + + let mut interesting = vec![ + vec![], + vec![0], + vec![0, 1], + vec![0, 1, 3], + vec![validator_count], + vec![validator_count, 1], + vec![validator_count, 1, 3], + vec![u64::max_value()], + vec![u64::max_value(), 1], + vec![u64::max_value(), 1, 3], + ]; + + interesting.push((0..validator_count).collect()); + + interesting + } + + pub async fn test_get_validator_duties_attester(self) -> Self { + let current_epoch = self.chain.epoch().unwrap().as_u64(); + + let half = current_epoch / 2; + let first = current_epoch - half; + let last = current_epoch + half; + + for epoch in first..=last { + for indices in self.interesting_validator_indices() { + let epoch = Epoch::from(epoch); + + // The endpoint does not allow getting duties past the next epoch. + if epoch > current_epoch + 1 { + assert_eq!( + self.client + .get_validator_duties_attester(epoch, Some(&indices)) + .await + .unwrap_err() + .status() + .map(Into::into), + Some(400) + ); + continue; + } + + let results = self + .client + .get_validator_duties_attester(epoch, Some(&indices)) + .await + .unwrap() + .data; + + let mut state = self + .chain + .state_at_slot( + epoch.start_slot(E::slots_per_epoch()), + StateSkipConfig::WithStateRoots, + ) + .unwrap(); + state + .build_committee_cache(RelativeEpoch::Current, &self.chain.spec) + .unwrap(); + + let expected_len = indices + .iter() + .filter(|i| **i < state.validators.len() as u64) + .count(); + + assert_eq!(results.len(), expected_len); + + for (indices_set, &i) in indices.iter().enumerate() { + if let Some(duty) = state + .get_attestation_duties(i as usize, RelativeEpoch::Current) + .unwrap() + { + let expected = AttesterData { + pubkey: state.validators[i as usize].pubkey.clone().into(), + validator_index: i, + committees_at_slot: duty.committees_at_slot, + committee_index: duty.index, + committee_length: duty.committee_len as u64, + validator_committee_index: duty.committee_position as u64, + slot: duty.slot, + }; + + let result = results + .iter() + .find(|duty| duty.validator_index == i) + .unwrap(); + + assert_eq!( + *result, expected, + "epoch: {}, indices_set: {}", + epoch, indices_set + ); + } else { + assert!( + !results.iter().any(|duty| duty.validator_index == i), + "validator index should not exist in response" + ); + } + } + } + } + + self + } + + pub async fn test_get_validator_duties_proposer(self) -> Self { + let current_epoch = self.chain.epoch().unwrap(); + + let result = self + .client + .get_validator_duties_proposer(current_epoch) + .await + .unwrap() + .data; + + let mut state = self.chain.head_beacon_state().unwrap(); + + while state.current_epoch() < current_epoch { + per_slot_processing(&mut state, None, &self.chain.spec).unwrap(); + } + + state + .build_committee_cache(RelativeEpoch::Current, &self.chain.spec) + .unwrap(); + + let expected = current_epoch + .slot_iter(E::slots_per_epoch()) + .map(|slot| { + let index = state + .get_beacon_proposer_index(slot, &self.chain.spec) + .unwrap(); + let pubkey = state.validators[index].pubkey.clone().into(); + + ProposerData { pubkey, slot } + }) + .collect::>(); + + assert_eq!(result, expected); + + self + } + + pub async fn test_block_production(self) -> Self { + let fork = self.chain.head_info().unwrap().fork; + let genesis_validators_root = self.chain.genesis_validators_root; + + for _ in 0..E::slots_per_epoch() * 3 { + let slot = self.chain.slot().unwrap(); + let epoch = self.chain.epoch().unwrap(); + + let proposer_pubkey_bytes = self + .client + .get_validator_duties_proposer(epoch) + .await + .unwrap() + .data + .into_iter() + .find(|duty| duty.slot == slot) + .map(|duty| duty.pubkey) + .unwrap(); + let proposer_pubkey = (&proposer_pubkey_bytes).try_into().unwrap(); + + let sk = self + .validator_keypairs + .iter() + .find(|kp| kp.pk == proposer_pubkey) + .map(|kp| kp.sk.clone()) + .unwrap(); + + let randao_reveal = { + let domain = self.chain.spec.get_domain( + epoch, + Domain::Randao, + &fork, + genesis_validators_root, + ); + let message = epoch.signing_root(domain); + sk.sign(message).into() + }; + + let block = self + .client + .get_validator_blocks::(slot, randao_reveal, None) + .await + .unwrap() + .data; + + let signed_block = block.sign(&sk, &fork, genesis_validators_root, &self.chain.spec); + + self.client.post_beacon_blocks(&signed_block).await.unwrap(); + + assert_eq!(self.chain.head_beacon_block().unwrap(), signed_block); + + self.chain.slot_clock.set_slot(slot.as_u64() + 1); + } + + self + } + + pub async fn test_get_validator_attestation_data(self) -> Self { + let mut state = self.chain.head_beacon_state().unwrap(); + let slot = state.slot; + state + .build_committee_cache(RelativeEpoch::Current, &self.chain.spec) + .unwrap(); + + for index in 0..state.get_committee_count_at_slot(slot).unwrap() { + let result = self + .client + .get_validator_attestation_data(slot, index) + .await + .unwrap() + .data; + + let expected = self + .chain + .produce_unaggregated_attestation(slot, index) + .unwrap() + .data; + + assert_eq!(result, expected); + } + + self + } + + pub async fn test_get_validator_aggregate_attestation(self) -> Self { + let attestation = self + .chain + .head_beacon_block() + .unwrap() + .message + .body + .attestations[0] + .clone(); + + let result = self + .client + .get_validator_aggregate_attestation( + attestation.data.slot, + attestation.data.tree_hash_root(), + ) + .await + .unwrap() + .unwrap() + .data; + + let expected = attestation; + + assert_eq!(result, expected); + + self + } + + pub async fn get_aggregate(&mut self) -> SignedAggregateAndProof { + let slot = self.chain.slot().unwrap(); + let epoch = self.chain.epoch().unwrap(); + + let mut head = self.chain.head().unwrap(); + while head.beacon_state.current_epoch() < epoch { + per_slot_processing(&mut head.beacon_state, None, &self.chain.spec).unwrap(); + } + head.beacon_state + .build_committee_cache(RelativeEpoch::Current, &self.chain.spec) + .unwrap(); + + let committee_len = head.beacon_state.get_committee_count_at_slot(slot).unwrap(); + let fork = head.beacon_state.fork; + let genesis_validators_root = self.chain.genesis_validators_root; + + let mut duties = vec![]; + for i in 0..self.validator_keypairs.len() { + duties.push( + self.client + .get_validator_duties_attester(epoch, Some(&[i as u64])) + .await + .unwrap() + .data[0] + .clone(), + ) + } + + let (i, kp, duty, proof) = self + .validator_keypairs + .iter() + .enumerate() + .find_map(|(i, kp)| { + let duty = duties[i].clone(); + + let proof = SelectionProof::new::( + duty.slot, + &kp.sk, + &fork, + genesis_validators_root, + &self.chain.spec, + ); + + if proof + .is_aggregator(committee_len as usize, &self.chain.spec) + .unwrap() + { + Some((i, kp, duty, proof)) + } else { + None + } + }) + .expect("there is at least one aggregator for this epoch") + .clone(); + + if duty.slot > slot { + self.chain.slot_clock.set_slot(duty.slot.into()); + } + + let attestation_data = self + .client + .get_validator_attestation_data(duty.slot, duty.committee_index) + .await + .unwrap() + .data; + + let mut attestation = Attestation { + aggregation_bits: BitList::with_capacity(duty.committee_length as usize).unwrap(), + data: attestation_data, + signature: AggregateSignature::infinity(), + }; + + attestation + .sign( + &kp.sk, + duty.validator_committee_index as usize, + &fork, + genesis_validators_root, + &self.chain.spec, + ) + .unwrap(); + + SignedAggregateAndProof::from_aggregate( + i as u64, + attestation, + Some(proof), + &kp.sk, + &fork, + genesis_validators_root, + &self.chain.spec, + ) + } + + pub async fn test_get_validator_aggregate_and_proofs_valid(mut self) -> Self { + let aggregate = self.get_aggregate().await; + + self.client + .post_validator_aggregate_and_proof::(&aggregate) + .await + .unwrap(); + + assert!(self.network_rx.try_recv().is_ok()); + + self + } + + pub async fn test_get_validator_aggregate_and_proofs_invalid(mut self) -> Self { + let mut aggregate = self.get_aggregate().await; + + aggregate.message.aggregate.data.slot += 1; + + self.client + .post_validator_aggregate_and_proof::(&aggregate) + .await + .unwrap_err(); + + assert!(self.network_rx.try_recv().is_err()); + + self + } + + pub async fn test_get_validator_beacon_committee_subscriptions(mut self) -> Self { + let subscription = BeaconCommitteeSubscription { + validator_index: 0, + committee_index: 0, + committees_at_slot: 1, + slot: Slot::new(1), + is_aggregator: true, + }; + + self.client + .post_validator_beacon_committee_subscriptions(&[subscription]) + .await + .unwrap(); + + self.network_rx.try_recv().unwrap(); + + self + } + + #[cfg(target_os = "linux")] + pub async fn test_get_lighthouse_health(self) -> Self { + self.client.get_lighthouse_health().await.unwrap(); + + self + } + + #[cfg(not(target_os = "linux"))] + pub async fn test_get_lighthouse_health(self) -> Self { + self.client.get_lighthouse_health().await.unwrap_err(); + + self + } + + pub async fn test_get_lighthouse_syncing(self) -> Self { + self.client.get_lighthouse_syncing().await.unwrap(); + + self + } + + pub async fn test_get_lighthouse_proto_array(self) -> Self { + self.client.get_lighthouse_proto_array().await.unwrap(); + + self + } + + pub async fn test_get_lighthouse_validator_inclusion_global(self) -> Self { + let epoch = self.chain.epoch().unwrap() - 1; + self.client + .get_lighthouse_validator_inclusion_global(epoch) + .await + .unwrap(); + + self + } + + pub async fn test_get_lighthouse_validator_inclusion(self) -> Self { + let epoch = self.chain.epoch().unwrap() - 1; + self.client + .get_lighthouse_validator_inclusion(epoch, ValidatorId::Index(0)) + .await + .unwrap(); + + self + } +} + +#[tokio::test(core_threads = 2)] +async fn beacon_genesis() { + ApiTester::new().test_beacon_genesis().await; +} + +#[tokio::test(core_threads = 2)] +async fn beacon_states_root() { + ApiTester::new().test_beacon_states_root().await; +} + +#[tokio::test(core_threads = 2)] +async fn beacon_states_fork() { + ApiTester::new().test_beacon_states_fork().await; +} + +#[tokio::test(core_threads = 2)] +async fn beacon_states_finality_checkpoints() { + ApiTester::new() + .test_beacon_states_finality_checkpoints() + .await; +} + +#[tokio::test(core_threads = 2)] +async fn beacon_states_validators() { + ApiTester::new().test_beacon_states_validators().await; +} + +#[tokio::test(core_threads = 2)] +async fn beacon_states_committees() { + ApiTester::new().test_beacon_states_committees().await; +} + +#[tokio::test(core_threads = 2)] +async fn beacon_states_validator_id() { + ApiTester::new().test_beacon_states_validator_id().await; +} + +#[tokio::test(core_threads = 2)] +async fn beacon_headers() { + ApiTester::new() + .test_beacon_headers_all_slots() + .await + .test_beacon_headers_all_parents() + .await; +} + +#[tokio::test(core_threads = 2)] +async fn beacon_headers_block_id() { + ApiTester::new().test_beacon_headers_block_id().await; +} + +#[tokio::test(core_threads = 2)] +async fn beacon_blocks() { + ApiTester::new().test_beacon_blocks().await; +} + +#[tokio::test(core_threads = 2)] +async fn post_beacon_blocks_valid() { + ApiTester::new().test_post_beacon_blocks_valid().await; +} + +#[tokio::test(core_threads = 2)] +async fn post_beacon_blocks_invalid() { + ApiTester::new().test_post_beacon_blocks_invalid().await; +} + +#[tokio::test(core_threads = 2)] +async fn beacon_blocks_root() { + ApiTester::new().test_beacon_blocks_root().await; +} + +#[tokio::test(core_threads = 2)] +async fn beacon_blocks_attestations() { + ApiTester::new().test_beacon_blocks_attestations().await; +} + +#[tokio::test(core_threads = 2)] +async fn beacon_pools_get() { + ApiTester::new() + .test_get_beacon_pool_attestations() + .await + .test_get_beacon_pool_attester_slashings() + .await + .test_get_beacon_pool_proposer_slashings() + .await + .test_get_beacon_pool_voluntary_exits() + .await; +} + +#[tokio::test(core_threads = 2)] +async fn beacon_pools_post_attestations_valid() { + ApiTester::new() + .test_post_beacon_pool_attestations_valid() + .await; +} + +#[tokio::test(core_threads = 2)] +async fn beacon_pools_post_attestations_invalid() { + ApiTester::new() + .test_post_beacon_pool_attestations_invalid() + .await; +} + +#[tokio::test(core_threads = 2)] +async fn beacon_pools_post_attester_slashings_valid() { + ApiTester::new() + .test_post_beacon_pool_attester_slashings_valid() + .await; +} + +#[tokio::test(core_threads = 2)] +async fn beacon_pools_post_attester_slashings_invalid() { + ApiTester::new() + .test_post_beacon_pool_attester_slashings_invalid() + .await; +} + +#[tokio::test(core_threads = 2)] +async fn beacon_pools_post_proposer_slashings_valid() { + ApiTester::new() + .test_post_beacon_pool_proposer_slashings_valid() + .await; +} + +#[tokio::test(core_threads = 2)] +async fn beacon_pools_post_proposer_slashings_invalid() { + ApiTester::new() + .test_post_beacon_pool_proposer_slashings_invalid() + .await; +} + +#[tokio::test(core_threads = 2)] +async fn beacon_pools_post_voluntary_exits_valid() { + ApiTester::new() + .test_post_beacon_pool_voluntary_exits_valid() + .await; +} + +#[tokio::test(core_threads = 2)] +async fn beacon_pools_post_voluntary_exits_invalid() { + ApiTester::new() + .test_post_beacon_pool_voluntary_exits_invalid() + .await; +} + +#[tokio::test(core_threads = 2)] +async fn config_get() { + ApiTester::new() + .test_get_config_fork_schedule() + .await + .test_get_config_spec() + .await + .test_get_config_deposit_contract() + .await; +} + +#[tokio::test(core_threads = 2)] +async fn debug_get() { + ApiTester::new() + .test_get_debug_beacon_states() + .await + .test_get_debug_beacon_heads() + .await; +} + +#[tokio::test(core_threads = 2)] +async fn node_get() { + ApiTester::new() + .test_get_node_version() + .await + .test_get_node_syncing() + .await; +} + +#[tokio::test(core_threads = 2)] +async fn get_validator_duties_attester() { + ApiTester::new().test_get_validator_duties_attester().await; +} + +#[tokio::test(core_threads = 2)] +async fn get_validator_duties_attester_with_skip_slots() { + ApiTester::new() + .skip_slots(E::slots_per_epoch() * 2) + .test_get_validator_duties_attester() + .await; +} + +#[tokio::test(core_threads = 2)] +async fn get_validator_duties_proposer() { + ApiTester::new().test_get_validator_duties_proposer().await; +} + +#[tokio::test(core_threads = 2)] +async fn get_validator_duties_proposer_with_skip_slots() { + ApiTester::new() + .skip_slots(E::slots_per_epoch() * 2) + .test_get_validator_duties_proposer() + .await; +} + +#[tokio::test(core_threads = 2)] +async fn block_production() { + ApiTester::new().test_block_production().await; +} + +#[tokio::test(core_threads = 2)] +async fn block_production_with_skip_slots() { + ApiTester::new() + .skip_slots(E::slots_per_epoch() * 2) + .test_block_production() + .await; +} + +#[tokio::test(core_threads = 2)] +async fn get_validator_attestation_data() { + ApiTester::new().test_get_validator_attestation_data().await; +} + +#[tokio::test(core_threads = 2)] +async fn get_validator_attestation_data_with_skip_slots() { + ApiTester::new() + .skip_slots(E::slots_per_epoch() * 2) + .test_get_validator_attestation_data() + .await; +} + +#[tokio::test(core_threads = 2)] +async fn get_validator_aggregate_attestation() { + ApiTester::new() + .test_get_validator_aggregate_attestation() + .await; +} + +#[tokio::test(core_threads = 2)] +async fn get_validator_aggregate_attestation_with_skip_slots() { + ApiTester::new() + .skip_slots(E::slots_per_epoch() * 2) + .test_get_validator_aggregate_attestation() + .await; +} + +#[tokio::test(core_threads = 2)] +async fn get_validator_aggregate_and_proofs_valid() { + ApiTester::new() + .test_get_validator_aggregate_and_proofs_valid() + .await; +} + +#[tokio::test(core_threads = 2)] +async fn get_validator_aggregate_and_proofs_valid_with_skip_slots() { + ApiTester::new() + .skip_slots(E::slots_per_epoch() * 2) + .test_get_validator_aggregate_and_proofs_valid() + .await; +} + +#[tokio::test(core_threads = 2)] +async fn get_validator_aggregate_and_proofs_invalid() { + ApiTester::new() + .test_get_validator_aggregate_and_proofs_invalid() + .await; +} + +#[tokio::test(core_threads = 2)] +async fn get_validator_aggregate_and_proofs_invalid_with_skip_slots() { + ApiTester::new() + .skip_slots(E::slots_per_epoch() * 2) + .test_get_validator_aggregate_and_proofs_invalid() + .await; +} + +#[tokio::test(core_threads = 2)] +async fn get_validator_beacon_committee_subscriptions() { + ApiTester::new() + .test_get_validator_beacon_committee_subscriptions() + .await; +} + +#[tokio::test(core_threads = 2)] +async fn lighthouse_endpoints() { + ApiTester::new() + .test_get_lighthouse_health() + .await + .test_get_lighthouse_syncing() + .await + .test_get_lighthouse_proto_array() + .await + .test_get_lighthouse_validator_inclusion() + .await + .test_get_lighthouse_validator_inclusion_global() + .await; +} diff --git a/beacon_node/http_metrics/Cargo.toml b/beacon_node/http_metrics/Cargo.toml new file mode 100644 index 00000000000..482f7a5debc --- /dev/null +++ b/beacon_node/http_metrics/Cargo.toml @@ -0,0 +1,28 @@ +[package] +name = "http_metrics" +version = "0.1.0" +authors = ["Paul Hauner "] +edition = "2018" + +# See more keys and their definitions at https://doc.rust-lang.org/cargo/reference/manifest.html + +[dependencies] +prometheus = "0.9.0" +warp = "0.2.5" +serde = { version = "1.0.110", features = ["derive"] } +slog = "2.5.2" +beacon_chain = { path = "../beacon_chain" } +store = { path = "../store" } +eth2_libp2p = { path = "../eth2_libp2p" } +slot_clock = { path = "../../common/slot_clock" } +lighthouse_metrics = { path = "../../common/lighthouse_metrics" } +lazy_static = "1.4.0" +eth2 = { path = "../../common/eth2" } +lighthouse_version = { path = "../../common/lighthouse_version" } +warp_utils = { path = "../../common/warp_utils" } + +[dev-dependencies] +tokio = { version = "0.2.21", features = ["sync"] } +reqwest = { version = "0.10.8", features = ["json"] } +environment = { path = "../../lighthouse/environment" } +types = { path = "../../consensus/types" } diff --git a/beacon_node/http_metrics/src/lib.rs b/beacon_node/http_metrics/src/lib.rs new file mode 100644 index 00000000000..37eac82bda4 --- /dev/null +++ b/beacon_node/http_metrics/src/lib.rs @@ -0,0 +1,135 @@ +//! This crate provides a HTTP server that is solely dedicated to serving the `/metrics` endpoint. +//! +//! For other endpoints, see the `http_api` crate. + +#[macro_use] +extern crate lazy_static; + +mod metrics; + +use beacon_chain::{BeaconChain, BeaconChainTypes}; +use lighthouse_version::version_with_platform; +use serde::{Deserialize, Serialize}; +use slog::{crit, info, Logger}; +use std::future::Future; +use std::net::{Ipv4Addr, SocketAddr, SocketAddrV4}; +use std::path::PathBuf; +use std::sync::Arc; +use warp::{http::Response, Filter}; + +#[derive(Debug)] +pub enum Error { + Warp(warp::Error), + Other(String), +} + +impl From for Error { + fn from(e: warp::Error) -> Self { + Error::Warp(e) + } +} + +impl From for Error { + fn from(e: String) -> Self { + Error::Other(e) + } +} + +/// A wrapper around all the items required to spawn the HTTP server. +/// +/// The server will gracefully handle the case where any fields are `None`. +pub struct Context { + pub config: Config, + pub chain: Option>>, + pub db_path: Option, + pub freezer_db_path: Option, + pub log: Logger, +} + +/// Configuration for the HTTP server. +#[derive(PartialEq, Debug, Clone, Serialize, Deserialize)] +pub struct Config { + pub enabled: bool, + pub listen_addr: Ipv4Addr, + pub listen_port: u16, + pub allow_origin: Option, +} + +impl Default for Config { + fn default() -> Self { + Self { + enabled: false, + listen_addr: Ipv4Addr::new(127, 0, 0, 1), + listen_port: 5054, + allow_origin: None, + } + } +} + +/// Creates a server that will serve requests using information from `ctx`. +/// +/// The server will shut down gracefully when the `shutdown` future resolves. +/// +/// ## Returns +/// +/// This function will bind the server to the provided address and then return a tuple of: +/// +/// - `SocketAddr`: the address that the HTTP server will listen on. +/// - `Future`: the actual server future that will need to be awaited. +/// +/// ## Errors +/// +/// Returns an error if the server is unable to bind or there is another error during +/// configuration. +pub fn serve( + ctx: Arc>, + shutdown: impl Future + Send + Sync + 'static, +) -> Result<(SocketAddr, impl Future), Error> { + let config = &ctx.config; + let log = ctx.log.clone(); + let allow_origin = config.allow_origin.clone(); + + // Sanity check. + if !config.enabled { + crit!(log, "Cannot start disabled metrics HTTP server"); + return Err(Error::Other( + "A disabled metrics server should not be started".to_string(), + )); + } + + let inner_ctx = ctx.clone(); + let routes = warp::get() + .and(warp::path("metrics")) + .map(move || inner_ctx.clone()) + .and_then(|ctx: Arc>| async move { + Ok::<_, warp::Rejection>( + metrics::gather_prometheus_metrics(&ctx) + .map(|body| Response::builder().status(200).body(body).unwrap()) + .unwrap_or_else(|e| { + Response::builder() + .status(500) + .body(format!("Unable to gather metrics: {:?}", e)) + .unwrap() + }), + ) + }) + // Add a `Server` header. + .map(|reply| warp::reply::with_header(reply, "Server", &version_with_platform())) + // Maybe add some CORS headers. + .map(move |reply| warp_utils::reply::maybe_cors(reply, allow_origin.as_ref())); + + let (listening_socket, server) = warp::serve(routes).try_bind_with_graceful_shutdown( + SocketAddrV4::new(config.listen_addr, config.listen_port), + async { + shutdown.await; + }, + )?; + + info!( + log, + "Metrics HTTP server started"; + "listen_address" => listening_socket.to_string(), + ); + + Ok((listening_socket, server)) +} diff --git a/beacon_node/rest_api/src/metrics.rs b/beacon_node/http_metrics/src/metrics.rs similarity index 69% rename from beacon_node/rest_api/src/metrics.rs rename to beacon_node/http_metrics/src/metrics.rs index 4b1ba737d7a..bcd803c405e 100644 --- a/beacon_node/rest_api/src/metrics.rs +++ b/beacon_node/http_metrics/src/metrics.rs @@ -1,38 +1,11 @@ -use crate::{ApiError, Context}; +use crate::Context; use beacon_chain::BeaconChainTypes; +use eth2::lighthouse::Health; use lighthouse_metrics::{Encoder, TextEncoder}; -use rest_types::Health; -use std::sync::Arc; pub use lighthouse_metrics::*; lazy_static! { - pub static ref BEACON_HTTP_API_REQUESTS_TOTAL: Result = - try_create_int_counter_vec( - "beacon_http_api_requests_total", - "Count of HTTP requests received", - &["endpoint"] - ); - pub static ref BEACON_HTTP_API_SUCCESS_TOTAL: Result = - try_create_int_counter_vec( - "beacon_http_api_success_total", - "Count of HTTP requests that returned 200 OK", - &["endpoint"] - ); - pub static ref BEACON_HTTP_API_ERROR_TOTAL: Result = try_create_int_counter_vec( - "beacon_http_api_error_total", - "Count of HTTP that did not return 200 OK", - &["endpoint"] - ); - pub static ref BEACON_HTTP_API_TIMES_TOTAL: Result = try_create_histogram_vec( - "beacon_http_api_times_total", - "Duration to process HTTP requests", - &["endpoint"] - ); - pub static ref REQUEST_RESPONSE_TIME: Result = try_create_histogram( - "http_server_request_duration_seconds", - "Time taken to build a response to a HTTP request" - ); pub static ref PROCESS_NUM_THREADS: Result = try_create_int_gauge( "process_num_threads", "Number of threads used by the current process" @@ -67,14 +40,9 @@ lazy_static! { try_create_float_gauge("system_loadavg_15", "Loadavg over 15 minutes"); } -/// Returns the full set of Prometheus metrics for the Beacon Node application. -/// -/// # Note -/// -/// This is a HTTP handler method. -pub fn get_prometheus( - ctx: Arc>, -) -> std::result::Result { +pub fn gather_prometheus_metrics( + ctx: &Context, +) -> std::result::Result { let mut buffer = vec![]; let encoder = TextEncoder::new(); @@ -94,9 +62,17 @@ pub fn get_prometheus( // using `lighthouse_metrics::gather(..)` to collect the global `DEFAULT_REGISTRY` metrics into // a string that can be returned via HTTP. - slot_clock::scrape_for_metrics::(&ctx.beacon_chain.slot_clock); - store::scrape_for_metrics(&ctx.db_path, &ctx.freezer_db_path); - beacon_chain::scrape_for_metrics(&ctx.beacon_chain); + if let Some(beacon_chain) = ctx.chain.as_ref() { + slot_clock::scrape_for_metrics::(&beacon_chain.slot_clock); + beacon_chain::scrape_for_metrics(beacon_chain); + } + + if let (Some(db_path), Some(freezer_db_path)) = + (ctx.db_path.as_ref(), ctx.freezer_db_path.as_ref()) + { + store::scrape_for_metrics(db_path, freezer_db_path); + } + eth2_libp2p::scrape_discovery_metrics(); // This will silently fail if we are unable to observe the health. This is desired behaviour @@ -125,6 +101,5 @@ pub fn get_prometheus( .encode(&lighthouse_metrics::gather(), &mut buffer) .unwrap(); - String::from_utf8(buffer) - .map_err(|e| ApiError::ServerError(format!("Failed to encode prometheus info: {:?}", e))) + String::from_utf8(buffer).map_err(|e| format!("Failed to encode prometheus info: {:?}", e)) } diff --git a/beacon_node/http_metrics/tests/tests.rs b/beacon_node/http_metrics/tests/tests.rs new file mode 100644 index 00000000000..18a40d4f849 --- /dev/null +++ b/beacon_node/http_metrics/tests/tests.rs @@ -0,0 +1,46 @@ +use beacon_chain::test_utils::BlockingMigratorEphemeralHarnessType; +use environment::null_logger; +use http_metrics::Config; +use reqwest::StatusCode; +use std::net::Ipv4Addr; +use std::sync::Arc; +use tokio::sync::oneshot; +use types::MainnetEthSpec; + +type Context = http_metrics::Context>; + +#[tokio::test(core_threads = 2)] +async fn returns_200_ok() { + let log = null_logger().unwrap(); + + let context = Arc::new(Context { + config: Config { + enabled: true, + listen_addr: Ipv4Addr::new(127, 0, 0, 1), + listen_port: 0, + allow_origin: None, + }, + chain: None, + db_path: None, + freezer_db_path: None, + log, + }); + + let ctx = context.clone(); + let (_shutdown_tx, shutdown_rx) = oneshot::channel::<()>(); + let server_shutdown = async { + // It's not really interesting why this triggered, just that it happened. + let _ = shutdown_rx.await; + }; + let (listening_socket, server) = http_metrics::serve(ctx, server_shutdown).unwrap(); + + tokio::spawn(async { server.await }); + + let url = format!( + "http://{}:{}/metrics", + listening_socket.ip(), + listening_socket.port() + ); + + assert_eq!(reqwest::get(&url).await.unwrap().status(), StatusCode::OK); +} diff --git a/beacon_node/network/Cargo.toml b/beacon_node/network/Cargo.toml index 0448e7762f8..ad856a6d253 100644 --- a/beacon_node/network/Cargo.toml +++ b/beacon_node/network/Cargo.toml @@ -17,7 +17,6 @@ beacon_chain = { path = "../beacon_chain" } store = { path = "../store" } eth2_libp2p = { path = "../eth2_libp2p" } hashset_delay = { path = "../../common/hashset_delay" } -rest_types = { path = "../../common/rest_types" } types = { path = "../../consensus/types" } state_processing = { path = "../../consensus/state_processing" } slot_clock = { path = "../../common/slot_clock" } diff --git a/beacon_node/network/src/attestation_service/mod.rs b/beacon_node/network/src/attestation_service/mod.rs index 59f63890a29..7c017d295b9 100644 --- a/beacon_node/network/src/attestation_service/mod.rs +++ b/beacon_node/network/src/attestation_service/mod.rs @@ -15,9 +15,8 @@ use slog::{debug, error, o, trace, warn}; use beacon_chain::{BeaconChain, BeaconChainTypes}; use eth2_libp2p::SubnetDiscovery; use hashset_delay::HashSetDelay; -use rest_types::ValidatorSubscription; use slot_clock::SlotClock; -use types::{Attestation, EthSpec, Slot, SubnetId}; +use types::{Attestation, EthSpec, Slot, SubnetId, ValidatorSubscription}; use crate::metrics; diff --git a/beacon_node/network/src/beacon_processor/worker.rs b/beacon_node/network/src/beacon_processor/worker.rs index 653922dfe5e..1abb2a27917 100644 --- a/beacon_node/network/src/beacon_processor/worker.rs +++ b/beacon_node/network/src/beacon_processor/worker.rs @@ -45,7 +45,7 @@ impl Worker { let attestation = match self .chain - .verify_unaggregated_attestation_for_gossip(attestation, subnet_id) + .verify_unaggregated_attestation_for_gossip(attestation, Some(subnet_id)) { Ok(attestation) => attestation, Err(e) => { diff --git a/beacon_node/network/src/service.rs b/beacon_node/network/src/service.rs index a018750f3f4..0d4a75ac237 100644 --- a/beacon_node/network/src/service.rs +++ b/beacon_node/network/src/service.rs @@ -15,13 +15,12 @@ use eth2_libp2p::{ }; use eth2_libp2p::{MessageAcceptance, Service as LibP2PService}; use futures::prelude::*; -use rest_types::ValidatorSubscription; use slog::{debug, error, info, o, trace, warn}; use std::{collections::HashMap, sync::Arc, time::Duration}; use store::HotColdDB; use tokio::sync::mpsc; use tokio::time::Delay; -use types::EthSpec; +use types::{EthSpec, ValidatorSubscription}; mod tests; diff --git a/beacon_node/operation_pool/src/lib.rs b/beacon_node/operation_pool/src/lib.rs index 5b664c87726..6d6a8d1cdc1 100644 --- a/beacon_node/operation_pool/src/lib.rs +++ b/beacon_node/operation_pool/src/lib.rs @@ -332,6 +332,51 @@ impl OperationPool { pub fn num_voluntary_exits(&self) -> usize { self.voluntary_exits.read().len() } + + /// Returns all known `Attestation` objects. + /// + /// This method may return objects that are invalid for block inclusion. + pub fn get_all_attestations(&self) -> Vec> { + self.attestations + .read() + .iter() + .map(|(_, attns)| attns.iter().cloned()) + .flatten() + .collect() + } + + /// Returns all known `AttesterSlashing` objects. + /// + /// This method may return objects that are invalid for block inclusion. + pub fn get_all_attester_slashings(&self) -> Vec> { + self.attester_slashings + .read() + .iter() + .map(|(slashing, _)| slashing.clone()) + .collect() + } + + /// Returns all known `ProposerSlashing` objects. + /// + /// This method may return objects that are invalid for block inclusion. + pub fn get_all_proposer_slashings(&self) -> Vec { + self.proposer_slashings + .read() + .iter() + .map(|(_, slashing)| slashing.clone()) + .collect() + } + + /// Returns all known `SignedVoluntaryExit` objects. + /// + /// This method may return objects that are invalid for block inclusion. + pub fn get_all_voluntary_exits(&self) -> Vec { + self.voluntary_exits + .read() + .iter() + .map(|(_, exit)| exit.clone()) + .collect() + } } /// Filter up to a maximum number of operations out of an iterator. diff --git a/beacon_node/rest_api/src/beacon.rs b/beacon_node/rest_api/src/beacon.rs deleted file mode 100644 index ad2688bb0ff..00000000000 --- a/beacon_node/rest_api/src/beacon.rs +++ /dev/null @@ -1,499 +0,0 @@ -use crate::helpers::*; -use crate::validator::get_state_for_epoch; -use crate::Context; -use crate::{ApiError, UrlQuery}; -use beacon_chain::{ - observed_operations::ObservationOutcome, BeaconChain, BeaconChainTypes, StateSkipConfig, -}; -use futures::executor::block_on; -use hyper::body::Bytes; -use hyper::{Body, Request}; -use rest_types::{ - BlockResponse, CanonicalHeadResponse, Committee, HeadBeaconBlock, StateResponse, - ValidatorRequest, ValidatorResponse, -}; -use std::io::Write; -use std::sync::Arc; - -use slog::error; -use types::{ - AttesterSlashing, BeaconState, EthSpec, Hash256, ProposerSlashing, PublicKeyBytes, - RelativeEpoch, SignedBeaconBlockHash, Slot, -}; - -/// Returns a summary of the head of the beacon chain. -pub fn get_head( - ctx: Arc>, -) -> Result { - let beacon_chain = &ctx.beacon_chain; - let chain_head = beacon_chain.head()?; - - Ok(CanonicalHeadResponse { - slot: chain_head.beacon_state.slot, - block_root: chain_head.beacon_block_root, - state_root: chain_head.beacon_state_root, - finalized_slot: chain_head - .beacon_state - .finalized_checkpoint - .epoch - .start_slot(T::EthSpec::slots_per_epoch()), - finalized_block_root: chain_head.beacon_state.finalized_checkpoint.root, - justified_slot: chain_head - .beacon_state - .current_justified_checkpoint - .epoch - .start_slot(T::EthSpec::slots_per_epoch()), - justified_block_root: chain_head.beacon_state.current_justified_checkpoint.root, - previous_justified_slot: chain_head - .beacon_state - .previous_justified_checkpoint - .epoch - .start_slot(T::EthSpec::slots_per_epoch()), - previous_justified_block_root: chain_head.beacon_state.previous_justified_checkpoint.root, - }) -} - -/// Return the list of heads of the beacon chain. -pub fn get_heads(ctx: Arc>) -> Vec { - ctx.beacon_chain - .heads() - .into_iter() - .map(|(beacon_block_root, beacon_block_slot)| HeadBeaconBlock { - beacon_block_root, - beacon_block_slot, - }) - .collect() -} - -/// HTTP handler to return a `BeaconBlock` at a given `root` or `slot`. -pub fn get_block( - req: Request>, - ctx: Arc>, -) -> Result, ApiError> { - let beacon_chain = &ctx.beacon_chain; - let query_params = ["root", "slot"]; - let (key, value) = UrlQuery::from_request(&req)?.first_of(&query_params)?; - - let block_root = match (key.as_ref(), value) { - ("slot", value) => { - let target = parse_slot(&value)?; - - block_root_at_slot(beacon_chain, target)?.ok_or_else(|| { - ApiError::NotFound(format!( - "Unable to find SignedBeaconBlock for slot {:?}", - target - )) - })? - } - ("root", value) => parse_root(&value)?, - _ => return Err(ApiError::ServerError("Unexpected query parameter".into())), - }; - - let block = beacon_chain.store.get_block(&block_root)?.ok_or_else(|| { - ApiError::NotFound(format!( - "Unable to find SignedBeaconBlock for root {:?}", - block_root - )) - })?; - - Ok(BlockResponse { - root: block_root, - beacon_block: block, - }) -} - -/// HTTP handler to return a `SignedBeaconBlock` root at a given `slot`. -pub fn get_block_root( - req: Request>, - ctx: Arc>, -) -> Result { - let slot_string = UrlQuery::from_request(&req)?.only_one("slot")?; - let target = parse_slot(&slot_string)?; - - block_root_at_slot(&ctx.beacon_chain, target)?.ok_or_else(|| { - ApiError::NotFound(format!( - "Unable to find SignedBeaconBlock for slot {:?}", - target - )) - }) -} - -fn make_sse_response_chunk(new_head_hash: SignedBeaconBlockHash) -> std::io::Result { - let mut buffer = Vec::new(); - { - let mut sse_message = uhttp_sse::SseMessage::new(&mut buffer); - let untyped_hash: Hash256 = new_head_hash.into(); - write!(sse_message.data()?, "{:?}", untyped_hash)?; - } - let bytes: Bytes = buffer.into(); - Ok(bytes) -} - -pub fn stream_forks(ctx: Arc>) -> Result { - let mut events = ctx.events.lock().add_rx(); - let (mut sender, body) = Body::channel(); - std::thread::spawn(move || { - while let Ok(new_head_hash) = events.recv() { - let chunk = match make_sse_response_chunk(new_head_hash) { - Ok(chunk) => chunk, - Err(e) => { - error!(ctx.log, "Failed to make SSE chunk"; "error" => e.to_string()); - sender.abort(); - break; - } - }; - match block_on(sender.send_data(chunk)) { - Err(e) if e.is_closed() => break, - Err(e) => error!(ctx.log, "Couldn't stream piece {:?}", e), - Ok(_) => (), - } - } - }); - Ok(body) -} - -/// HTTP handler to which accepts a query string of a list of validator pubkeys and maps it to a -/// `ValidatorResponse`. -/// -/// This method is limited to as many `pubkeys` that can fit in a URL. See `post_validators` for -/// doing bulk requests. -pub fn get_validators( - req: Request>, - ctx: Arc>, -) -> Result, ApiError> { - let query = UrlQuery::from_request(&req)?; - - let validator_pubkeys = query - .all_of("validator_pubkeys")? - .iter() - .map(|validator_pubkey_str| parse_pubkey_bytes(validator_pubkey_str)) - .collect::, _>>()?; - - let state_root_opt = if let Some((_key, value)) = query.first_of_opt(&["state_root"]) { - Some(parse_root(&value)?) - } else { - None - }; - - validator_responses_by_pubkey(&ctx.beacon_chain, state_root_opt, validator_pubkeys) -} - -/// HTTP handler to return all validators, each as a `ValidatorResponse`. -pub fn get_all_validators( - req: Request>, - ctx: Arc>, -) -> Result, ApiError> { - let query = UrlQuery::from_request(&req)?; - - let state_root_opt = if let Some((_key, value)) = query.first_of_opt(&["state_root"]) { - Some(parse_root(&value)?) - } else { - None - }; - - let mut state = get_state_from_root_opt(&ctx.beacon_chain, state_root_opt)?; - - let validators = state.validators.clone(); - validators - .iter() - .map(|validator| validator_response_by_pubkey(&mut state, validator.pubkey.clone())) - .collect::, _>>() -} - -/// HTTP handler to return all active validators, each as a `ValidatorResponse`. -pub fn get_active_validators( - req: Request>, - ctx: Arc>, -) -> Result, ApiError> { - let query = UrlQuery::from_request(&req)?; - - let state_root_opt = if let Some((_key, value)) = query.first_of_opt(&["state_root"]) { - Some(parse_root(&value)?) - } else { - None - }; - - let mut state = get_state_from_root_opt(&ctx.beacon_chain, state_root_opt)?; - - let validators = state.validators.clone(); - let current_epoch = state.current_epoch(); - - validators - .iter() - .filter(|validator| validator.is_active_at(current_epoch)) - .map(|validator| validator_response_by_pubkey(&mut state, validator.pubkey.clone())) - .collect::, _>>() -} - -/// HTTP handler to which accepts a `ValidatorRequest` and returns a `ValidatorResponse` for -/// each of the given `pubkeys`. When `state_root` is `None`, the canonical head is used. -/// -/// This method allows for a basically unbounded list of `pubkeys`, where as the `get_validators` -/// request is limited by the max number of pubkeys you can fit in a URL. -pub fn post_validators( - req: Request>, - ctx: Arc>, -) -> Result, ApiError> { - serde_json::from_slice::(&req.into_body()) - .map_err(|e| { - ApiError::BadRequest(format!( - "Unable to parse JSON into ValidatorRequest: {:?}", - e - )) - }) - .and_then(|bulk_request| { - validator_responses_by_pubkey( - &ctx.beacon_chain, - bulk_request.state_root, - bulk_request.pubkeys, - ) - }) -} - -/// Returns either the state given by `state_root_opt`, or the canonical head state if it is -/// `None`. -fn get_state_from_root_opt( - beacon_chain: &BeaconChain, - state_root_opt: Option, -) -> Result, ApiError> { - if let Some(state_root) = state_root_opt { - beacon_chain - .get_state(&state_root, None) - .map_err(|e| { - ApiError::ServerError(format!( - "Database error when reading state root {}: {:?}", - state_root, e - )) - })? - .ok_or_else(|| ApiError::NotFound(format!("No state exists with root: {}", state_root))) - } else { - Ok(beacon_chain.head()?.beacon_state) - } -} - -/// Maps a vec of `validator_pubkey` to a vec of `ValidatorResponse`, using the state at the given -/// `state_root`. If `state_root.is_none()`, uses the canonial head state. -fn validator_responses_by_pubkey( - beacon_chain: &BeaconChain, - state_root_opt: Option, - validator_pubkeys: Vec, -) -> Result, ApiError> { - let mut state = get_state_from_root_opt(beacon_chain, state_root_opt)?; - - validator_pubkeys - .into_iter() - .map(|validator_pubkey| validator_response_by_pubkey(&mut state, validator_pubkey)) - .collect::, ApiError>>() -} - -/// Maps a `validator_pubkey` to a `ValidatorResponse`, using the given state. -/// -/// The provided `state` must have a fully up-to-date pubkey cache. -fn validator_response_by_pubkey( - state: &mut BeaconState, - validator_pubkey: PublicKeyBytes, -) -> Result { - let validator_index_opt = state - .get_validator_index(&validator_pubkey) - .map_err(|e| ApiError::ServerError(format!("Unable to read pubkey cache: {:?}", e)))?; - - if let Some(validator_index) = validator_index_opt { - let balance = state.balances.get(validator_index).ok_or_else(|| { - ApiError::ServerError(format!("Invalid balances index: {:?}", validator_index)) - })?; - - let validator = state - .validators - .get(validator_index) - .ok_or_else(|| { - ApiError::ServerError(format!("Invalid validator index: {:?}", validator_index)) - })? - .clone(); - - Ok(ValidatorResponse { - pubkey: validator_pubkey, - validator_index: Some(validator_index), - balance: Some(*balance), - validator: Some(validator), - }) - } else { - Ok(ValidatorResponse { - pubkey: validator_pubkey, - validator_index: None, - balance: None, - validator: None, - }) - } -} - -/// HTTP handler -pub fn get_committees( - req: Request>, - ctx: Arc>, -) -> Result, ApiError> { - let query = UrlQuery::from_request(&req)?; - - let epoch = query.epoch()?; - - let mut state = - get_state_for_epoch(&ctx.beacon_chain, epoch, StateSkipConfig::WithoutStateRoots)?; - - let relative_epoch = RelativeEpoch::from_epoch(state.current_epoch(), epoch).map_err(|e| { - ApiError::ServerError(format!("Failed to get state suitable for epoch: {:?}", e)) - })?; - - state - .build_committee_cache(relative_epoch, &ctx.beacon_chain.spec) - .map_err(|e| ApiError::ServerError(format!("Unable to build committee cache: {:?}", e)))?; - - Ok(state - .get_beacon_committees_at_epoch(relative_epoch) - .map_err(|e| ApiError::ServerError(format!("Unable to get all committees: {:?}", e)))? - .into_iter() - .map(|c| Committee { - slot: c.slot, - index: c.index, - committee: c.committee.to_vec(), - }) - .collect::>()) -} - -/// HTTP handler to return a `BeaconState` at a given `root` or `slot`. -/// -/// Will not return a state if the request slot is in the future. Will return states higher than -/// the current head by skipping slots. -pub fn get_state( - req: Request>, - ctx: Arc>, -) -> Result, ApiError> { - let head_state = ctx.beacon_chain.head()?.beacon_state; - - let (key, value) = match UrlQuery::from_request(&req) { - Ok(query) => { - // We have *some* parameters, just check them. - let query_params = ["root", "slot"]; - query.first_of(&query_params)? - } - Err(ApiError::BadRequest(_)) => { - // No parameters provided at all, use current slot. - (String::from("slot"), head_state.slot.to_string()) - } - Err(e) => { - return Err(e); - } - }; - - let (root, state): (Hash256, BeaconState) = match (key.as_ref(), value) { - ("slot", value) => state_at_slot(&ctx.beacon_chain, parse_slot(&value)?)?, - ("root", value) => { - let root = &parse_root(&value)?; - - let state = ctx - .beacon_chain - .store - .get_state(root, None)? - .ok_or_else(|| ApiError::NotFound(format!("No state for root: {:?}", root)))?; - - (*root, state) - } - _ => return Err(ApiError::ServerError("Unexpected query parameter".into())), - }; - - Ok(StateResponse { - root, - beacon_state: state, - }) -} - -/// HTTP handler to return a `BeaconState` root at a given `slot`. -/// -/// Will not return a state if the request slot is in the future. Will return states higher than -/// the current head by skipping slots. -pub fn get_state_root( - req: Request>, - ctx: Arc>, -) -> Result { - let slot_string = UrlQuery::from_request(&req)?.only_one("slot")?; - let slot = parse_slot(&slot_string)?; - - state_root_at_slot(&ctx.beacon_chain, slot, StateSkipConfig::WithStateRoots) -} - -/// HTTP handler to return a `BeaconState` at the genesis block. -/// -/// This is an undocumented convenience method used during testing. For production, simply do a -/// state request at slot 0. -pub fn get_genesis_state( - ctx: Arc>, -) -> Result, ApiError> { - state_at_slot(&ctx.beacon_chain, Slot::new(0)).map(|(_root, state)| state) -} - -pub fn proposer_slashing( - req: Request>, - ctx: Arc>, -) -> Result { - let body = req.into_body(); - - serde_json::from_slice::(&body) - .map_err(|e| format!("Unable to parse JSON into ProposerSlashing: {:?}", e)) - .and_then(move |proposer_slashing| { - if ctx.beacon_chain.eth1_chain.is_some() { - let obs_outcome = ctx - .beacon_chain - .verify_proposer_slashing_for_gossip(proposer_slashing) - .map_err(|e| format!("Error while verifying proposer slashing: {:?}", e))?; - if let ObservationOutcome::New(verified_proposer_slashing) = obs_outcome { - ctx.beacon_chain - .import_proposer_slashing(verified_proposer_slashing); - Ok(()) - } else { - Err("Proposer slashing for that validator index already known".into()) - } - } else { - Err("Cannot insert proposer slashing on node without Eth1 connection.".to_string()) - } - }) - .map_err(ApiError::BadRequest)?; - - Ok(true) -} - -pub fn attester_slashing( - req: Request>, - ctx: Arc>, -) -> Result { - let body = req.into_body(); - serde_json::from_slice::>(&body) - .map_err(|e| { - ApiError::BadRequest(format!( - "Unable to parse JSON into AttesterSlashing: {:?}", - e - )) - }) - .and_then(move |attester_slashing| { - if ctx.beacon_chain.eth1_chain.is_some() { - ctx.beacon_chain - .verify_attester_slashing_for_gossip(attester_slashing) - .map_err(|e| format!("Error while verifying attester slashing: {:?}", e)) - .and_then(|outcome| { - if let ObservationOutcome::New(verified_attester_slashing) = outcome { - ctx.beacon_chain - .import_attester_slashing(verified_attester_slashing) - .map_err(|e| { - format!("Error while importing attester slashing: {:?}", e) - }) - } else { - Err("Attester slashing only covers already slashed indices".to_string()) - } - }) - .map_err(ApiError::BadRequest) - } else { - Err(ApiError::BadRequest( - "Cannot insert attester slashing on node without Eth1 connection.".to_string(), - )) - } - })?; - - Ok(true) -} diff --git a/beacon_node/rest_api/src/config.rs b/beacon_node/rest_api/src/config.rs deleted file mode 100644 index 815fccfd01c..00000000000 --- a/beacon_node/rest_api/src/config.rs +++ /dev/null @@ -1,55 +0,0 @@ -use serde::{Deserialize, Serialize}; -use std::net::Ipv4Addr; - -/// Defines the encoding for the API. -#[derive(Clone, Serialize, Deserialize, Copy)] -pub enum ApiEncodingFormat { - JSON, - YAML, - SSZ, -} - -impl ApiEncodingFormat { - pub fn get_content_type(&self) -> &str { - match self { - ApiEncodingFormat::JSON => "application/json", - ApiEncodingFormat::YAML => "application/yaml", - ApiEncodingFormat::SSZ => "application/ssz", - } - } -} - -impl From<&str> for ApiEncodingFormat { - fn from(f: &str) -> ApiEncodingFormat { - match f { - "application/yaml" => ApiEncodingFormat::YAML, - "application/ssz" => ApiEncodingFormat::SSZ, - _ => ApiEncodingFormat::JSON, - } - } -} - -/// HTTP REST API Configuration -#[derive(Debug, Clone, Serialize, Deserialize)] -pub struct Config { - /// Enable the REST API server. - pub enabled: bool, - /// The IPv4 address the REST API HTTP server will listen on. - pub listen_address: Ipv4Addr, - /// The port the REST API HTTP server will listen on. - pub port: u16, - /// If something else than "", a 'Access-Control-Allow-Origin' header will be present in - /// responses. Put *, to allow any origin. - pub allow_origin: String, -} - -impl Default for Config { - fn default() -> Self { - Config { - enabled: false, - listen_address: Ipv4Addr::new(127, 0, 0, 1), - port: 5052, - allow_origin: "".to_string(), - } - } -} diff --git a/beacon_node/rest_api/src/consensus.rs b/beacon_node/rest_api/src/consensus.rs deleted file mode 100644 index 9df57f05528..00000000000 --- a/beacon_node/rest_api/src/consensus.rs +++ /dev/null @@ -1,126 +0,0 @@ -use crate::helpers::*; -use crate::{ApiError, Context, UrlQuery}; -use beacon_chain::BeaconChainTypes; -use hyper::Request; -use rest_types::{IndividualVotesRequest, IndividualVotesResponse}; -use serde::{Deserialize, Serialize}; -use ssz_derive::{Decode, Encode}; -use state_processing::per_epoch_processing::{TotalBalances, ValidatorStatuses}; -use std::sync::Arc; -use types::EthSpec; - -/// The results of validators voting during an epoch. -/// -/// Provides information about the current and previous epochs. -#[derive(Serialize, Deserialize, Encode, Decode)] -pub struct VoteCount { - /// The total effective balance of all active validators during the _current_ epoch. - pub current_epoch_active_gwei: u64, - /// The total effective balance of all active validators during the _previous_ epoch. - pub previous_epoch_active_gwei: u64, - /// The total effective balance of all validators who attested during the _current_ epoch. - pub current_epoch_attesting_gwei: u64, - /// The total effective balance of all validators who attested during the _current_ epoch and - /// agreed with the state about the beacon block at the first slot of the _current_ epoch. - pub current_epoch_target_attesting_gwei: u64, - /// The total effective balance of all validators who attested during the _previous_ epoch. - pub previous_epoch_attesting_gwei: u64, - /// The total effective balance of all validators who attested during the _previous_ epoch and - /// agreed with the state about the beacon block at the first slot of the _previous_ epoch. - pub previous_epoch_target_attesting_gwei: u64, - /// The total effective balance of all validators who attested during the _previous_ epoch and - /// agreed with the state about the beacon block at the time of attestation. - pub previous_epoch_head_attesting_gwei: u64, -} - -impl Into for TotalBalances { - fn into(self) -> VoteCount { - VoteCount { - current_epoch_active_gwei: self.current_epoch(), - previous_epoch_active_gwei: self.previous_epoch(), - current_epoch_attesting_gwei: self.current_epoch_attesters(), - current_epoch_target_attesting_gwei: self.current_epoch_target_attesters(), - previous_epoch_attesting_gwei: self.previous_epoch_attesters(), - previous_epoch_target_attesting_gwei: self.previous_epoch_target_attesters(), - previous_epoch_head_attesting_gwei: self.previous_epoch_head_attesters(), - } - } -} - -/// HTTP handler return a `VoteCount` for some given `Epoch`. -pub fn get_vote_count( - req: Request>, - ctx: Arc>, -) -> Result { - let query = UrlQuery::from_request(&req)?; - - let epoch = query.epoch()?; - // This is the last slot of the given epoch (one prior to the first slot of the next epoch). - let target_slot = (epoch + 1).start_slot(T::EthSpec::slots_per_epoch()) - 1; - - let (_root, state) = state_at_slot(&ctx.beacon_chain, target_slot)?; - let spec = &ctx.beacon_chain.spec; - - let mut validator_statuses = ValidatorStatuses::new(&state, spec)?; - validator_statuses.process_attestations(&state, spec)?; - - Ok(validator_statuses.total_balances.into()) -} - -pub fn post_individual_votes( - req: Request>, - ctx: Arc>, -) -> Result, ApiError> { - let body = req.into_body(); - - serde_json::from_slice::(&body) - .map_err(|e| { - ApiError::BadRequest(format!( - "Unable to parse JSON into ValidatorDutiesRequest: {:?}", - e - )) - }) - .and_then(move |body| { - let epoch = body.epoch; - - // This is the last slot of the given epoch (one prior to the first slot of the next epoch). - let target_slot = (epoch + 1).start_slot(T::EthSpec::slots_per_epoch()) - 1; - - let (_root, mut state) = state_at_slot(&ctx.beacon_chain, target_slot)?; - let spec = &ctx.beacon_chain.spec; - - let mut validator_statuses = ValidatorStatuses::new(&state, spec)?; - validator_statuses.process_attestations(&state, spec)?; - - body.pubkeys - .into_iter() - .map(|pubkey| { - let validator_index_opt = state.get_validator_index(&pubkey).map_err(|e| { - ApiError::ServerError(format!("Unable to read pubkey cache: {:?}", e)) - })?; - - if let Some(validator_index) = validator_index_opt { - let vote = validator_statuses - .statuses - .get(validator_index) - .cloned() - .map(Into::into); - - Ok(IndividualVotesResponse { - epoch, - pubkey, - validator_index: Some(validator_index), - vote, - }) - } else { - Ok(IndividualVotesResponse { - epoch, - pubkey, - validator_index: None, - vote: None, - }) - } - }) - .collect::, _>>() - }) -} diff --git a/beacon_node/rest_api/src/helpers.rs b/beacon_node/rest_api/src/helpers.rs deleted file mode 100644 index 66b5bd1a0c1..00000000000 --- a/beacon_node/rest_api/src/helpers.rs +++ /dev/null @@ -1,260 +0,0 @@ -use crate::{ApiError, NetworkChannel}; -use beacon_chain::{BeaconChain, BeaconChainTypes, StateSkipConfig}; -use bls::PublicKeyBytes; -use eth2_libp2p::PubsubMessage; -use itertools::process_results; -use network::NetworkMessage; -use ssz::Decode; -use store::iter::AncestorIter; -use types::{ - BeaconState, CommitteeIndex, Epoch, EthSpec, Hash256, RelativeEpoch, SignedBeaconBlock, Slot, -}; - -/// Parse a slot. -/// -/// E.g., `"1234"` -pub fn parse_slot(string: &str) -> Result { - string - .parse::() - .map(Slot::from) - .map_err(|e| ApiError::BadRequest(format!("Unable to parse slot: {:?}", e))) -} - -/// Parse an epoch. -/// -/// E.g., `"13"` -pub fn parse_epoch(string: &str) -> Result { - string - .parse::() - .map(Epoch::from) - .map_err(|e| ApiError::BadRequest(format!("Unable to parse epoch: {:?}", e))) -} - -/// Parse a CommitteeIndex. -/// -/// E.g., `"18"` -pub fn parse_committee_index(string: &str) -> Result { - string - .parse::() - .map_err(|e| ApiError::BadRequest(format!("Unable to parse committee index: {:?}", e))) -} - -/// Parse an SSZ object from some hex-encoded bytes. -/// -/// E.g., A signature is `"0x0000000000000000000000000000000000000000000000000000000000000000"` -pub fn parse_hex_ssz_bytes(string: &str) -> Result { - const PREFIX: &str = "0x"; - - if string.starts_with(PREFIX) { - let trimmed = string.trim_start_matches(PREFIX); - let bytes = hex::decode(trimmed) - .map_err(|e| ApiError::BadRequest(format!("Unable to parse SSZ hex: {:?}", e)))?; - T::from_ssz_bytes(&bytes) - .map_err(|e| ApiError::BadRequest(format!("Unable to parse SSZ bytes: {:?}", e))) - } else { - Err(ApiError::BadRequest( - "Hex bytes must have a 0x prefix".to_string(), - )) - } -} - -/// Parse a root from a `0x` prefixed string. -/// -/// E.g., `"0x0000000000000000000000000000000000000000000000000000000000000000"` -pub fn parse_root(string: &str) -> Result { - const PREFIX: &str = "0x"; - - if string.starts_with(PREFIX) { - let trimmed = string.trim_start_matches(PREFIX); - trimmed - .parse() - .map_err(|e| ApiError::BadRequest(format!("Unable to parse root: {:?}", e))) - } else { - Err(ApiError::BadRequest( - "Root must have a 0x prefix".to_string(), - )) - } -} - -/// Parse a PublicKey from a `0x` prefixed hex string -pub fn parse_pubkey_bytes(string: &str) -> Result { - const PREFIX: &str = "0x"; - if string.starts_with(PREFIX) { - let pubkey_bytes = hex::decode(string.trim_start_matches(PREFIX)) - .map_err(|e| ApiError::BadRequest(format!("Invalid hex string: {:?}", e)))?; - let pubkey = PublicKeyBytes::deserialize(pubkey_bytes.as_slice()).map_err(|e| { - ApiError::BadRequest(format!("Unable to deserialize public key: {:?}.", e)) - })?; - Ok(pubkey) - } else { - Err(ApiError::BadRequest( - "Public key must have a 0x prefix".to_string(), - )) - } -} - -/// Returns the root of the `SignedBeaconBlock` in the canonical chain of `beacon_chain` at the given -/// `slot`, if possible. -/// -/// May return a root for a previous slot, in the case of skip slots. -pub fn block_root_at_slot( - beacon_chain: &BeaconChain, - target: Slot, -) -> Result, ApiError> { - Ok(process_results( - beacon_chain.rev_iter_block_roots()?, - |iter| { - iter.take_while(|(_, slot)| *slot >= target) - .find(|(_, slot)| *slot == target) - .map(|(root, _)| root) - }, - )?) -} - -/// Returns a `BeaconState` and it's root in the canonical chain of `beacon_chain` at the given -/// `slot`, if possible. -/// -/// Will not return a state if the request slot is in the future. Will return states higher than -/// the current head by skipping slots. -pub fn state_at_slot( - beacon_chain: &BeaconChain, - slot: Slot, -) -> Result<(Hash256, BeaconState), ApiError> { - let head = beacon_chain.head()?; - - if head.beacon_state.slot == slot { - Ok((head.beacon_state_root, head.beacon_state)) - } else { - let root = state_root_at_slot(beacon_chain, slot, StateSkipConfig::WithStateRoots)?; - - let state: BeaconState = beacon_chain - .store - .get_state(&root, Some(slot))? - .ok_or_else(|| ApiError::NotFound(format!("Unable to find state at root {}", root)))?; - - Ok((root, state)) - } -} - -/// Returns the root of the `BeaconState` in the canonical chain of `beacon_chain` at the given -/// `slot`, if possible. -/// -/// Will not return a state root if the request slot is in the future. Will return state roots -/// higher than the current head by skipping slots. -pub fn state_root_at_slot( - beacon_chain: &BeaconChain, - slot: Slot, - config: StateSkipConfig, -) -> Result { - let head_state = &beacon_chain.head()?.beacon_state; - let current_slot = beacon_chain - .slot() - .map_err(|_| ApiError::ServerError("Unable to read slot clock".to_string()))?; - - // There are four scenarios when obtaining a state for a given slot: - // - // 1. The request slot is in the future. - // 2. The request slot is the same as the best block (head) slot. - // 3. The request slot is prior to the head slot. - // 4. The request slot is later than the head slot. - if current_slot < slot { - // 1. The request slot is in the future. Reject the request. - // - // We could actually speculate about future state roots by skipping slots, however that's - // likely to cause confusion for API users. - Err(ApiError::BadRequest(format!( - "Requested slot {} is past the current slot {}", - slot, current_slot - ))) - } else if head_state.slot == slot { - // 2. The request slot is the same as the best block (head) slot. - // - // The head state root is stored in memory, return a reference. - Ok(beacon_chain.head()?.beacon_state_root) - } else if head_state.slot > slot { - // 3. The request slot is prior to the head slot. - // - // Iterate through the state roots on the head state to find the root for that - // slot. Once the root is found, load it from the database. - process_results( - head_state - .try_iter_ancestor_roots(beacon_chain.store.clone()) - .ok_or_else(|| { - ApiError::ServerError("Failed to create roots iterator".to_string()) - })?, - |mut iter| iter.find(|(_, s)| *s == slot).map(|(root, _)| root), - )? - .ok_or_else(|| ApiError::NotFound(format!("Unable to find state at slot {}", slot))) - } else { - // 4. The request slot is later than the head slot. - // - // Use `per_slot_processing` to advance the head state to the present slot, - // assuming that all slots do not contain a block (i.e., they are skipped slots). - let mut state = beacon_chain.head()?.beacon_state; - let spec = &T::EthSpec::default_spec(); - - let skip_state_root = match config { - StateSkipConfig::WithStateRoots => None, - StateSkipConfig::WithoutStateRoots => Some(Hash256::zero()), - }; - - for _ in state.slot.as_u64()..slot.as_u64() { - // Ensure the next epoch state caches are built in case of an epoch transition. - state.build_committee_cache(RelativeEpoch::Next, spec)?; - - state_processing::per_slot_processing(&mut state, skip_state_root, spec)?; - } - - // Note: this is an expensive operation. Once the tree hash cache is implement it may be - // used here. - Ok(state.canonical_root()) - } -} - -pub fn publish_beacon_block_to_network( - chan: &NetworkChannel, - block: SignedBeaconBlock, -) -> Result<(), ApiError> { - // send the block via SSZ encoding - let messages = vec![PubsubMessage::BeaconBlock(Box::new(block))]; - - // Publish the block to the p2p network via gossipsub. - if let Err(e) = chan.send(NetworkMessage::Publish { messages }) { - return Err(ApiError::ServerError(format!( - "Unable to send new block to network: {:?}", - e - ))); - } - - Ok(()) -} - -#[cfg(test)] -mod test { - use super::*; - - #[test] - fn parse_root_works() { - assert_eq!( - parse_root("0x0000000000000000000000000000000000000000000000000000000000000000"), - Ok(Hash256::zero()) - ); - assert_eq!( - parse_root("0x000000000000000000000000000000000000000000000000000000000000002a"), - Ok(Hash256::from_low_u64_be(42)) - ); - assert!( - parse_root("0000000000000000000000000000000000000000000000000000000000000042").is_err() - ); - assert!(parse_root("0x").is_err()); - assert!(parse_root("0x00").is_err()); - } - - #[test] - fn parse_slot_works() { - assert_eq!(parse_slot("0"), Ok(Slot::new(0))); - assert_eq!(parse_slot("42"), Ok(Slot::new(42))); - assert_eq!(parse_slot("10000000"), Ok(Slot::new(10_000_000))); - assert!(parse_slot("cats").is_err()); - } -} diff --git a/beacon_node/rest_api/src/lib.rs b/beacon_node/rest_api/src/lib.rs deleted file mode 100644 index 405e08e217d..00000000000 --- a/beacon_node/rest_api/src/lib.rs +++ /dev/null @@ -1,127 +0,0 @@ -#[macro_use] -extern crate lazy_static; -mod router; -extern crate network as client_network; - -mod beacon; -pub mod config; -mod consensus; -mod helpers; -mod lighthouse; -mod metrics; -mod node; -mod url_query; -mod validator; - -use beacon_chain::{BeaconChain, BeaconChainTypes}; -use bus::Bus; -use client_network::NetworkMessage; -pub use config::ApiEncodingFormat; -use eth2_config::Eth2Config; -use eth2_libp2p::NetworkGlobals; -use futures::future::TryFutureExt; -use hyper::server::conn::AddrStream; -use hyper::service::{make_service_fn, service_fn}; -use hyper::{Body, Request, Server}; -use parking_lot::Mutex; -use rest_types::ApiError; -use slog::{info, warn}; -use std::net::SocketAddr; -use std::path::PathBuf; -use std::sync::Arc; -use tokio::sync::mpsc; -use types::SignedBeaconBlockHash; -use url_query::UrlQuery; - -pub use crate::helpers::parse_pubkey_bytes; -pub use config::Config; -pub use router::Context; - -pub type NetworkChannel = mpsc::UnboundedSender>; - -pub struct NetworkInfo { - pub network_globals: Arc>, - pub network_chan: NetworkChannel, -} - -// Allowing more than 7 arguments. -#[allow(clippy::too_many_arguments)] -pub fn start_server( - executor: environment::TaskExecutor, - config: &Config, - beacon_chain: Arc>, - network_info: NetworkInfo, - db_path: PathBuf, - freezer_db_path: PathBuf, - eth2_config: Eth2Config, - events: Arc>>, -) -> Result { - let log = executor.log(); - let eth2_config = Arc::new(eth2_config); - - let context = Arc::new(Context { - executor: executor.clone(), - config: config.clone(), - beacon_chain, - network_globals: network_info.network_globals.clone(), - network_chan: network_info.network_chan, - eth2_config, - log: log.clone(), - db_path, - freezer_db_path, - events, - }); - - // Define the function that will build the request handler. - let make_service = make_service_fn(move |_socket: &AddrStream| { - let ctx = context.clone(); - - async move { - Ok::<_, hyper::Error>(service_fn(move |req: Request| { - router::on_http_request(req, ctx.clone()) - })) - } - }); - - let bind_addr = (config.listen_address, config.port).into(); - let server = Server::bind(&bind_addr).serve(make_service); - - // Determine the address the server is actually listening on. - // - // This may be different to `bind_addr` if bind port was 0 (this allows the OS to choose a free - // port). - let actual_listen_addr = server.local_addr(); - - // Build a channel to kill the HTTP server. - let exit = executor.exit(); - let inner_log = log.clone(); - let server_exit = async move { - let _ = exit.await; - info!(inner_log, "HTTP service shutdown"); - }; - - // Configure the `hyper` server to gracefully shutdown when the shutdown channel is triggered. - let inner_log = log.clone(); - let server_future = server - .with_graceful_shutdown(async { - server_exit.await; - }) - .map_err(move |e| { - warn!( - inner_log, - "HTTP server failed to start, Unable to bind"; "address" => format!("{:?}", e) - ) - }) - .unwrap_or_else(|_| ()); - - info!( - log, - "HTTP API started"; - "address" => format!("{}", actual_listen_addr.ip()), - "port" => actual_listen_addr.port(), - ); - - executor.spawn_without_exit(server_future, "http"); - - Ok(actual_listen_addr) -} diff --git a/beacon_node/rest_api/src/lighthouse.rs b/beacon_node/rest_api/src/lighthouse.rs deleted file mode 100644 index 4d0fae926df..00000000000 --- a/beacon_node/rest_api/src/lighthouse.rs +++ /dev/null @@ -1,48 +0,0 @@ -//! This contains a collection of lighthouse specific HTTP endpoints. - -use crate::{ApiError, Context}; -use beacon_chain::BeaconChainTypes; -use eth2_libp2p::PeerInfo; -use serde::Serialize; -use std::sync::Arc; -use types::EthSpec; - -/// Returns all known peers and corresponding information -pub fn peers(ctx: Arc>) -> Result>, ApiError> { - Ok(ctx - .network_globals - .peers - .read() - .peers() - .map(|(peer_id, peer_info)| Peer { - peer_id: peer_id.to_string(), - peer_info: peer_info.clone(), - }) - .collect()) -} - -/// Returns all known connected peers and their corresponding information -pub fn connected_peers( - ctx: Arc>, -) -> Result>, ApiError> { - Ok(ctx - .network_globals - .peers - .read() - .connected_peers() - .map(|(peer_id, peer_info)| Peer { - peer_id: peer_id.to_string(), - peer_info: peer_info.clone(), - }) - .collect()) -} - -/// Information returned by `peers` and `connected_peers`. -#[derive(Clone, Debug, Serialize)] -#[serde(bound = "T: EthSpec")] -pub struct Peer { - /// The Peer's ID - peer_id: String, - /// The PeerInfo associated with the peer. - peer_info: PeerInfo, -} diff --git a/beacon_node/rest_api/src/node.rs b/beacon_node/rest_api/src/node.rs deleted file mode 100644 index bd5615de34d..00000000000 --- a/beacon_node/rest_api/src/node.rs +++ /dev/null @@ -1,39 +0,0 @@ -use crate::{ApiError, Context}; -use beacon_chain::BeaconChainTypes; -use eth2_libp2p::types::SyncState; -use rest_types::{SyncingResponse, SyncingStatus}; -use std::sync::Arc; -use types::Slot; - -/// Returns a syncing status. -pub fn syncing(ctx: Arc>) -> Result { - let current_slot = ctx - .beacon_chain - .head_info() - .map_err(|e| ApiError::ServerError(format!("Unable to read head slot: {:?}", e)))? - .slot; - - let (starting_slot, highest_slot) = match ctx.network_globals.sync_state() { - SyncState::SyncingFinalized { - start_slot, - head_slot, - .. - } - | SyncState::SyncingHead { - start_slot, - head_slot, - } => (start_slot, head_slot), - SyncState::Synced | SyncState::Stalled => (Slot::from(0u64), current_slot), - }; - - let sync_status = SyncingStatus { - starting_slot, - current_slot, - highest_slot, - }; - - Ok(SyncingResponse { - is_syncing: ctx.network_globals.is_syncing(), - sync_status, - }) -} diff --git a/beacon_node/rest_api/src/router.rs b/beacon_node/rest_api/src/router.rs deleted file mode 100644 index bed7ba77aa6..00000000000 --- a/beacon_node/rest_api/src/router.rs +++ /dev/null @@ -1,322 +0,0 @@ -use crate::{ - beacon, config::Config, consensus, lighthouse, metrics, node, validator, NetworkChannel, -}; -use beacon_chain::{BeaconChain, BeaconChainTypes}; -use bus::Bus; -use environment::TaskExecutor; -use eth2_config::Eth2Config; -use eth2_libp2p::{NetworkGlobals, PeerId}; -use hyper::header::HeaderValue; -use hyper::{Body, Method, Request, Response}; -use lighthouse_version::version_with_platform; -use operation_pool::PersistedOperationPool; -use parking_lot::Mutex; -use rest_types::{ApiError, Handler, Health}; -use slog::debug; -use std::path::PathBuf; -use std::sync::Arc; -use std::time::Instant; -use types::{EthSpec, SignedBeaconBlockHash}; - -pub struct Context { - pub executor: TaskExecutor, - pub config: Config, - pub beacon_chain: Arc>, - pub network_globals: Arc>, - pub network_chan: NetworkChannel, - pub eth2_config: Arc, - pub log: slog::Logger, - pub db_path: PathBuf, - pub freezer_db_path: PathBuf, - pub events: Arc>>, -} - -pub async fn on_http_request( - req: Request, - ctx: Arc>, -) -> Result, ApiError> { - let path = req.uri().path().to_string(); - - let _timer = metrics::start_timer_vec(&metrics::BEACON_HTTP_API_TIMES_TOTAL, &[&path]); - metrics::inc_counter_vec(&metrics::BEACON_HTTP_API_REQUESTS_TOTAL, &[&path]); - - let received_instant = Instant::now(); - let log = ctx.log.clone(); - let allow_origin = ctx.config.allow_origin.clone(); - - match route(req, ctx).await { - Ok(mut response) => { - metrics::inc_counter_vec(&metrics::BEACON_HTTP_API_SUCCESS_TOTAL, &[&path]); - - if allow_origin != "" { - let headers = response.headers_mut(); - headers.insert( - hyper::header::ACCESS_CONTROL_ALLOW_ORIGIN, - HeaderValue::from_str(&allow_origin)?, - ); - headers.insert(hyper::header::VARY, HeaderValue::from_static("Origin")); - } - - debug!( - log, - "HTTP API request successful"; - "path" => path, - "duration_ms" => Instant::now().duration_since(received_instant).as_millis() - ); - Ok(response) - } - - Err(error) => { - metrics::inc_counter_vec(&metrics::BEACON_HTTP_API_ERROR_TOTAL, &[&path]); - - debug!( - log, - "HTTP API request failure"; - "path" => path, - "duration_ms" => Instant::now().duration_since(received_instant).as_millis() - ); - Ok(error.into()) - } - } -} - -async fn route( - req: Request, - ctx: Arc>, -) -> Result, ApiError> { - let path = req.uri().path().to_string(); - let ctx = ctx.clone(); - let method = req.method().clone(); - let executor = ctx.executor.clone(); - let handler = Handler::new(req, ctx, executor)?; - - match (method, path.as_ref()) { - (Method::GET, "/node/version") => handler - .static_value(version_with_platform()) - .await? - .serde_encodings(), - (Method::GET, "/node/health") => handler - .static_value(Health::observe().map_err(ApiError::ServerError)?) - .await? - .serde_encodings(), - (Method::GET, "/node/syncing") => handler - .allow_body() - .in_blocking_task(|_, ctx| node::syncing(ctx)) - .await? - .serde_encodings(), - (Method::GET, "/network/enr") => handler - .in_core_task(|_, ctx| Ok(ctx.network_globals.local_enr().to_base64())) - .await? - .serde_encodings(), - (Method::GET, "/network/peer_count") => handler - .in_core_task(|_, ctx| Ok(ctx.network_globals.connected_peers())) - .await? - .serde_encodings(), - (Method::GET, "/network/peer_id") => handler - .in_core_task(|_, ctx| Ok(ctx.network_globals.local_peer_id().to_base58())) - .await? - .serde_encodings(), - (Method::GET, "/network/peers") => handler - .in_blocking_task(|_, ctx| { - Ok(ctx - .network_globals - .peers - .read() - .connected_peer_ids() - .map(PeerId::to_string) - .collect::>()) - }) - .await? - .serde_encodings(), - (Method::GET, "/network/listen_port") => handler - .in_core_task(|_, ctx| Ok(ctx.network_globals.listen_port_tcp())) - .await? - .serde_encodings(), - (Method::GET, "/network/listen_addresses") => handler - .in_blocking_task(|_, ctx| Ok(ctx.network_globals.listen_multiaddrs())) - .await? - .serde_encodings(), - (Method::GET, "/beacon/head") => handler - .in_blocking_task(|_, ctx| beacon::get_head(ctx)) - .await? - .all_encodings(), - (Method::GET, "/beacon/heads") => handler - .in_blocking_task(|_, ctx| Ok(beacon::get_heads(ctx))) - .await? - .all_encodings(), - (Method::GET, "/beacon/block") => handler - .in_blocking_task(beacon::get_block) - .await? - .all_encodings(), - (Method::GET, "/beacon/block_root") => handler - .in_blocking_task(beacon::get_block_root) - .await? - .all_encodings(), - (Method::GET, "/beacon/fork") => handler - .in_blocking_task(|_, ctx| Ok(ctx.beacon_chain.head_info()?.fork)) - .await? - .all_encodings(), - (Method::GET, "/beacon/fork/stream") => { - handler.sse_stream(|_, ctx| beacon::stream_forks(ctx)).await - } - (Method::GET, "/beacon/genesis_time") => handler - .in_blocking_task(|_, ctx| Ok(ctx.beacon_chain.head_info()?.genesis_time)) - .await? - .all_encodings(), - (Method::GET, "/beacon/genesis_validators_root") => handler - .in_blocking_task(|_, ctx| Ok(ctx.beacon_chain.head_info()?.genesis_validators_root)) - .await? - .all_encodings(), - (Method::GET, "/beacon/validators") => handler - .in_blocking_task(beacon::get_validators) - .await? - .all_encodings(), - (Method::POST, "/beacon/validators") => handler - .allow_body() - .in_blocking_task(beacon::post_validators) - .await? - .all_encodings(), - (Method::GET, "/beacon/validators/all") => handler - .in_blocking_task(beacon::get_all_validators) - .await? - .all_encodings(), - (Method::GET, "/beacon/validators/active") => handler - .in_blocking_task(beacon::get_active_validators) - .await? - .all_encodings(), - (Method::GET, "/beacon/state") => handler - .in_blocking_task(beacon::get_state) - .await? - .all_encodings(), - (Method::GET, "/beacon/state_root") => handler - .in_blocking_task(beacon::get_state_root) - .await? - .all_encodings(), - (Method::GET, "/beacon/state/genesis") => handler - .in_blocking_task(|_, ctx| beacon::get_genesis_state(ctx)) - .await? - .all_encodings(), - (Method::GET, "/beacon/committees") => handler - .in_blocking_task(beacon::get_committees) - .await? - .all_encodings(), - (Method::POST, "/beacon/proposer_slashing") => handler - .allow_body() - .in_blocking_task(beacon::proposer_slashing) - .await? - .serde_encodings(), - (Method::POST, "/beacon/attester_slashing") => handler - .allow_body() - .in_blocking_task(beacon::attester_slashing) - .await? - .serde_encodings(), - (Method::POST, "/validator/duties") => handler - .allow_body() - .in_blocking_task(validator::post_validator_duties) - .await? - .serde_encodings(), - (Method::POST, "/validator/subscribe") => handler - .allow_body() - .in_blocking_task(validator::post_validator_subscriptions) - .await? - .serde_encodings(), - (Method::GET, "/validator/duties/all") => handler - .in_blocking_task(validator::get_all_validator_duties) - .await? - .serde_encodings(), - (Method::GET, "/validator/duties/active") => handler - .in_blocking_task(validator::get_active_validator_duties) - .await? - .serde_encodings(), - (Method::GET, "/validator/block") => handler - .in_blocking_task(validator::get_new_beacon_block) - .await? - .serde_encodings(), - (Method::POST, "/validator/block") => handler - .allow_body() - .in_blocking_task(validator::publish_beacon_block) - .await? - .serde_encodings(), - (Method::GET, "/validator/attestation") => handler - .in_blocking_task(validator::get_new_attestation) - .await? - .serde_encodings(), - (Method::GET, "/validator/aggregate_attestation") => handler - .in_blocking_task(validator::get_aggregate_attestation) - .await? - .serde_encodings(), - (Method::POST, "/validator/attestations") => handler - .allow_body() - .in_blocking_task(validator::publish_attestations) - .await? - .serde_encodings(), - (Method::POST, "/validator/aggregate_and_proofs") => handler - .allow_body() - .in_blocking_task(validator::publish_aggregate_and_proofs) - .await? - .serde_encodings(), - (Method::GET, "/consensus/global_votes") => handler - .allow_body() - .in_blocking_task(consensus::get_vote_count) - .await? - .serde_encodings(), - (Method::POST, "/consensus/individual_votes") => handler - .allow_body() - .in_blocking_task(consensus::post_individual_votes) - .await? - .serde_encodings(), - (Method::GET, "/spec") => handler - // TODO: this clone is not ideal. - .in_blocking_task(|_, ctx| Ok(ctx.beacon_chain.spec.clone())) - .await? - .serde_encodings(), - (Method::GET, "/spec/slots_per_epoch") => handler - .static_value(T::EthSpec::slots_per_epoch()) - .await? - .serde_encodings(), - (Method::GET, "/spec/eth2_config") => handler - // TODO: this clone is not ideal. - .in_blocking_task(|_, ctx| Ok(ctx.eth2_config.as_ref().clone())) - .await? - .serde_encodings(), - (Method::GET, "/advanced/fork_choice") => handler - .in_blocking_task(|_, ctx| { - Ok(ctx - .beacon_chain - .fork_choice - .read() - .proto_array() - .core_proto_array() - .clone()) - }) - .await? - .serde_encodings(), - (Method::GET, "/advanced/operation_pool") => handler - .in_blocking_task(|_, ctx| { - Ok(PersistedOperationPool::from_operation_pool( - &ctx.beacon_chain.op_pool, - )) - }) - .await? - .serde_encodings(), - (Method::GET, "/metrics") => handler - .in_blocking_task(|_, ctx| metrics::get_prometheus(ctx)) - .await? - .text_encoding(), - (Method::GET, "/lighthouse/syncing") => handler - .in_blocking_task(|_, ctx| Ok(ctx.network_globals.sync_state())) - .await? - .serde_encodings(), - (Method::GET, "/lighthouse/peers") => handler - .in_blocking_task(|_, ctx| lighthouse::peers(ctx)) - .await? - .serde_encodings(), - (Method::GET, "/lighthouse/connected_peers") => handler - .in_blocking_task(|_, ctx| lighthouse::connected_peers(ctx)) - .await? - .serde_encodings(), - _ => Err(ApiError::NotFound( - "Request path and/or method not found.".to_owned(), - )), - } -} diff --git a/beacon_node/rest_api/src/url_query.rs b/beacon_node/rest_api/src/url_query.rs deleted file mode 100644 index fee0cf437e6..00000000000 --- a/beacon_node/rest_api/src/url_query.rs +++ /dev/null @@ -1,166 +0,0 @@ -use crate::helpers::{parse_committee_index, parse_epoch, parse_hex_ssz_bytes, parse_slot}; -use crate::ApiError; -use hyper::Request; -use types::{AttestationData, CommitteeIndex, Epoch, Signature, Slot}; - -/// Provides handy functions for parsing the query parameters of a URL. - -#[derive(Clone, Copy)] -pub struct UrlQuery<'a>(url::form_urlencoded::Parse<'a>); - -impl<'a> UrlQuery<'a> { - /// Instantiate from an existing `Request`. - /// - /// Returns `Err` if `req` does not contain any query parameters. - pub fn from_request(req: &'a Request) -> Result { - let query_str = req.uri().query().unwrap_or_else(|| ""); - - Ok(UrlQuery(url::form_urlencoded::parse(query_str.as_bytes()))) - } - - /// Returns the first `(key, value)` pair found where the `key` is in `keys`. - /// - /// If no match is found, an `InvalidQueryParams` error is returned. - pub fn first_of(mut self, keys: &[&str]) -> Result<(String, String), ApiError> { - self.0 - .find(|(key, _value)| keys.contains(&&**key)) - .map(|(key, value)| (key.into_owned(), value.into_owned())) - .ok_or_else(|| { - ApiError::BadRequest(format!( - "URL query must be valid and contain at least one of the following keys: {:?}", - keys - )) - }) - } - - /// Returns the first `(key, value)` pair found where the `key` is in `keys`, if any. - /// - /// Returns `None` if no match is found. - pub fn first_of_opt(mut self, keys: &[&str]) -> Option<(String, String)> { - self.0 - .find(|(key, _value)| keys.contains(&&**key)) - .map(|(key, value)| (key.into_owned(), value.into_owned())) - } - - /// Returns the value for `key`, if and only if `key` is the only key present in the query - /// parameters. - pub fn only_one(self, key: &str) -> Result { - let queries: Vec<_> = self - .0 - .map(|(k, v)| (k.into_owned(), v.into_owned())) - .collect(); - - if queries.len() == 1 { - let (first_key, first_value) = &queries[0]; // Must have 0 index if len is 1. - if first_key == key { - Ok(first_value.to_string()) - } else { - Err(ApiError::BadRequest(format!( - "Only the {} query parameter is supported", - key - ))) - } - } else { - Err(ApiError::BadRequest(format!( - "Only one query parameter is allowed, {} supplied", - queries.len() - ))) - } - } - - /// Returns a vector of all values present where `key` is in `keys - /// - /// If no match is found, an `InvalidQueryParams` error is returned. - pub fn all_of(self, key: &str) -> Result, ApiError> { - let queries: Vec<_> = self - .0 - .filter_map(|(k, v)| { - if k.eq(key) { - Some(v.into_owned()) - } else { - None - } - }) - .collect(); - Ok(queries) - } - - /// Returns the value of the first occurrence of the `epoch` key. - pub fn epoch(self) -> Result { - self.first_of(&["epoch"]) - .and_then(|(_key, value)| parse_epoch(&value)) - } - - /// Returns the value of the first occurrence of the `slot` key. - pub fn slot(self) -> Result { - self.first_of(&["slot"]) - .and_then(|(_key, value)| parse_slot(&value)) - } - - /// Returns the value of the first occurrence of the `committee_index` key. - pub fn committee_index(self) -> Result { - self.first_of(&["committee_index"]) - .and_then(|(_key, value)| parse_committee_index(&value)) - } - - /// Returns the value of the first occurrence of the `randao_reveal` key. - pub fn randao_reveal(self) -> Result { - self.first_of(&["randao_reveal"]) - .and_then(|(_key, value)| parse_hex_ssz_bytes(&value)) - } - - /// Returns the value of the first occurrence of the `attestation_data` key. - pub fn attestation_data(self) -> Result { - self.first_of(&["attestation_data"]) - .and_then(|(_key, value)| parse_hex_ssz_bytes(&value)) - } -} - -#[cfg(test)] -mod test { - use super::*; - - #[test] - fn only_one() { - let get_result = |addr: &str, key: &str| -> Result { - UrlQuery(url::Url::parse(addr).unwrap().query_pairs()).only_one(key) - }; - - assert_eq!(get_result("http://cat.io/?a=42", "a"), Ok("42".to_string())); - assert!(get_result("http://cat.io/?a=42", "b").is_err()); - assert!(get_result("http://cat.io/?a=42&b=12", "a").is_err()); - assert!(get_result("http://cat.io/", "").is_err()); - } - - #[test] - fn first_of() { - let url = url::Url::parse("http://lighthouse.io/cats?a=42&b=12&c=100").unwrap(); - let get_query = || UrlQuery(url.query_pairs()); - - assert_eq!( - get_query().first_of(&["a"]), - Ok(("a".to_string(), "42".to_string())) - ); - assert_eq!( - get_query().first_of(&["a", "b", "c"]), - Ok(("a".to_string(), "42".to_string())) - ); - assert_eq!( - get_query().first_of(&["a", "a", "a"]), - Ok(("a".to_string(), "42".to_string())) - ); - assert_eq!( - get_query().first_of(&["a", "b", "c"]), - Ok(("a".to_string(), "42".to_string())) - ); - assert_eq!( - get_query().first_of(&["b", "c"]), - Ok(("b".to_string(), "12".to_string())) - ); - assert_eq!( - get_query().first_of(&["c"]), - Ok(("c".to_string(), "100".to_string())) - ); - assert!(get_query().first_of(&["nothing"]).is_err()); - } -} diff --git a/beacon_node/rest_api/src/validator.rs b/beacon_node/rest_api/src/validator.rs deleted file mode 100644 index 49342ddaa30..00000000000 --- a/beacon_node/rest_api/src/validator.rs +++ /dev/null @@ -1,747 +0,0 @@ -use crate::helpers::{parse_hex_ssz_bytes, publish_beacon_block_to_network}; -use crate::{ApiError, Context, NetworkChannel, UrlQuery}; -use beacon_chain::{ - attestation_verification::Error as AttnError, BeaconChain, BeaconChainError, BeaconChainTypes, - BlockError, ForkChoiceError, StateSkipConfig, -}; -use bls::PublicKeyBytes; -use eth2_libp2p::PubsubMessage; -use hyper::Request; -use network::NetworkMessage; -use rest_types::{ValidatorDutiesRequest, ValidatorDutyBytes, ValidatorSubscription}; -use slog::{error, info, trace, warn, Logger}; -use std::sync::Arc; -use types::beacon_state::EthSpec; -use types::{ - Attestation, AttestationData, BeaconBlock, BeaconState, Epoch, RelativeEpoch, SelectionProof, - SignedAggregateAndProof, SignedBeaconBlock, SubnetId, -}; - -/// HTTP Handler to retrieve the duties for a set of validators during a particular epoch. This -/// method allows for collecting bulk sets of validator duties without risking exceeding the max -/// URL length with query pairs. -pub fn post_validator_duties( - req: Request>, - ctx: Arc>, -) -> Result, ApiError> { - let body = req.into_body(); - - serde_json::from_slice::(&body) - .map_err(|e| { - ApiError::BadRequest(format!( - "Unable to parse JSON into ValidatorDutiesRequest: {:?}", - e - )) - }) - .and_then(|bulk_request| { - return_validator_duties( - &ctx.beacon_chain.clone(), - bulk_request.epoch, - bulk_request.pubkeys.into_iter().map(Into::into).collect(), - ) - }) -} - -/// HTTP Handler to retrieve subscriptions for a set of validators. This allows the node to -/// organise peer discovery and topic subscription for known validators. -pub fn post_validator_subscriptions( - req: Request>, - ctx: Arc>, -) -> Result<(), ApiError> { - let body = req.into_body(); - - serde_json::from_slice(&body) - .map_err(|e| { - ApiError::BadRequest(format!( - "Unable to parse JSON into ValidatorSubscriptions: {:?}", - e - )) - }) - .and_then(move |subscriptions: Vec| { - ctx.network_chan - .send(NetworkMessage::Subscribe { subscriptions }) - .map_err(|e| { - ApiError::ServerError(format!( - "Unable to subscriptions to the network: {:?}", - e - )) - })?; - Ok(()) - }) -} - -/// HTTP Handler to retrieve all validator duties for the given epoch. -pub fn get_all_validator_duties( - req: Request>, - ctx: Arc>, -) -> Result, ApiError> { - let query = UrlQuery::from_request(&req)?; - - let epoch = query.epoch()?; - - let state = get_state_for_epoch(&ctx.beacon_chain, epoch, StateSkipConfig::WithoutStateRoots)?; - - let validator_pubkeys = state - .validators - .iter() - .map(|validator| validator.pubkey.clone()) - .collect(); - - return_validator_duties(&ctx.beacon_chain, epoch, validator_pubkeys) -} - -/// HTTP Handler to retrieve all active validator duties for the given epoch. -pub fn get_active_validator_duties( - req: Request>, - ctx: Arc>, -) -> Result, ApiError> { - let query = UrlQuery::from_request(&req)?; - - let epoch = query.epoch()?; - - let state = get_state_for_epoch(&ctx.beacon_chain, epoch, StateSkipConfig::WithoutStateRoots)?; - - let validator_pubkeys = state - .validators - .iter() - .filter(|validator| validator.is_active_at(state.current_epoch())) - .map(|validator| validator.pubkey.clone()) - .collect(); - - return_validator_duties(&ctx.beacon_chain, epoch, validator_pubkeys) -} - -/// Helper function to return the state that can be used to determine the duties for some `epoch`. -pub fn get_state_for_epoch( - beacon_chain: &BeaconChain, - epoch: Epoch, - config: StateSkipConfig, -) -> Result, ApiError> { - let slots_per_epoch = T::EthSpec::slots_per_epoch(); - let head = beacon_chain.head()?; - let current_epoch = beacon_chain.epoch()?; - let head_epoch = head.beacon_state.current_epoch(); - - if head_epoch == current_epoch && RelativeEpoch::from_epoch(current_epoch, epoch).is_ok() { - Ok(head.beacon_state) - } else { - // If epoch is ahead of current epoch, then it should be a "next epoch" request for - // attestation duties. So, go to the start slot of the epoch prior to that, - // which should be just the next wall-clock epoch. - let slot = if epoch > current_epoch { - (epoch - 1).start_slot(slots_per_epoch) - } - // Otherwise, go to the start of the request epoch. - else { - epoch.start_slot(slots_per_epoch) - }; - - beacon_chain.state_at_slot(slot, config).map_err(|e| { - ApiError::ServerError(format!("Unable to load state for epoch {}: {:?}", epoch, e)) - }) - } -} - -/// Helper function to get the duties for some `validator_pubkeys` in some `epoch`. -fn return_validator_duties( - beacon_chain: &BeaconChain, - epoch: Epoch, - validator_pubkeys: Vec, -) -> Result, ApiError> { - let mut state = get_state_for_epoch(&beacon_chain, epoch, StateSkipConfig::WithoutStateRoots)?; - - let relative_epoch = RelativeEpoch::from_epoch(state.current_epoch(), epoch) - .map_err(|_| ApiError::ServerError(String::from("Loaded state is in the wrong epoch")))?; - - state - .build_committee_cache(relative_epoch, &beacon_chain.spec) - .map_err(|e| ApiError::ServerError(format!("Unable to build committee cache: {:?}", e)))?; - - // Get a list of all validators for this epoch. - // - // Used for quickly determining the slot for a proposer. - let validator_proposers = if epoch == state.current_epoch() { - Some( - epoch - .slot_iter(T::EthSpec::slots_per_epoch()) - .map(|slot| { - state - .get_beacon_proposer_index(slot, &beacon_chain.spec) - .map(|i| (i, slot)) - .map_err(|e| { - ApiError::ServerError(format!( - "Unable to get proposer index for validator: {:?}", - e - )) - }) - }) - .collect::, _>>()?, - ) - } else { - None - }; - - validator_pubkeys - .into_iter() - .map(|validator_pubkey| { - // The `beacon_chain` can return a validator index that does not exist in all states. - // Therefore, we must check to ensure that the validator index is valid for our - // `state`. - let validator_index = beacon_chain - .validator_index(&validator_pubkey) - .map_err(|e| { - ApiError::ServerError(format!("Unable to get validator index: {:?}", e)) - })? - .filter(|i| *i < state.validators.len()); - - if let Some(validator_index) = validator_index { - let duties = state - .get_attestation_duties(validator_index, relative_epoch) - .map_err(|e| { - ApiError::ServerError(format!( - "Unable to obtain attestation duties: {:?}", - e - )) - })?; - - let committee_count_at_slot = duties - .map(|d| state.get_committee_count_at_slot(d.slot)) - .transpose() - .map_err(|e| { - ApiError::ServerError(format!( - "Unable to find committee count at slot: {:?}", - e - )) - })?; - - let aggregator_modulo = duties - .map(|duties| SelectionProof::modulo(duties.committee_len, &beacon_chain.spec)) - .transpose() - .map_err(|e| { - ApiError::ServerError(format!("Unable to find modulo: {:?}", e)) - })?; - - let block_proposal_slots = validator_proposers.as_ref().map(|proposers| { - proposers - .iter() - .filter(|(i, _slot)| validator_index == *i) - .map(|(_i, slot)| *slot) - .collect() - }); - - Ok(ValidatorDutyBytes { - validator_pubkey, - validator_index: Some(validator_index as u64), - attestation_slot: duties.map(|d| d.slot), - attestation_committee_index: duties.map(|d| d.index), - committee_count_at_slot, - attestation_committee_position: duties.map(|d| d.committee_position), - block_proposal_slots, - aggregator_modulo, - }) - } else { - Ok(ValidatorDutyBytes { - validator_pubkey, - validator_index: None, - attestation_slot: None, - attestation_committee_index: None, - attestation_committee_position: None, - block_proposal_slots: None, - committee_count_at_slot: None, - aggregator_modulo: None, - }) - } - }) - .collect::, ApiError>>() -} - -/// HTTP Handler to produce a new BeaconBlock from the current state, ready to be signed by a validator. -pub fn get_new_beacon_block( - req: Request>, - ctx: Arc>, -) -> Result, ApiError> { - let query = UrlQuery::from_request(&req)?; - - let slot = query.slot()?; - let randao_reveal = query.randao_reveal()?; - - let validator_graffiti = if let Some((_key, value)) = query.first_of_opt(&["graffiti"]) { - Some(parse_hex_ssz_bytes(&value)?) - } else { - None - }; - - let (new_block, _state) = ctx - .beacon_chain - .produce_block(randao_reveal, slot, validator_graffiti) - .map_err(|e| { - error!( - ctx.log, - "Error whilst producing block"; - "error" => format!("{:?}", e) - ); - - ApiError::ServerError(format!( - "Beacon node is not able to produce a block: {:?}", - e - )) - })?; - - Ok(new_block) -} - -/// HTTP Handler to publish a SignedBeaconBlock, which has been signed by a validator. -pub fn publish_beacon_block( - req: Request>, - ctx: Arc>, -) -> Result<(), ApiError> { - let body = req.into_body(); - - serde_json::from_slice(&body).map_err(|e| { - ApiError::BadRequest(format!("Unable to parse JSON into SignedBeaconBlock: {:?}", e)) - }) - .and_then(move |block: SignedBeaconBlock| { - let slot = block.slot(); - match ctx.beacon_chain.process_block(block.clone()) { - Ok(block_root) => { - // Block was processed, publish via gossipsub - info!( - ctx.log, - "Block from local validator"; - "block_root" => format!("{}", block_root), - "block_slot" => slot, - ); - - publish_beacon_block_to_network::(&ctx.network_chan, block)?; - - // Run the fork choice algorithm and enshrine a new canonical head, if - // found. - // - // The new head may or may not be the block we just received. - if let Err(e) = ctx.beacon_chain.fork_choice() { - error!( - ctx.log, - "Failed to find beacon chain head"; - "error" => format!("{:?}", e) - ); - } else { - // In the best case, validators should produce blocks that become the - // head. - // - // Potential reasons this may not be the case: - // - // - A quick re-org between block produce and publish. - // - Excessive time between block produce and publish. - // - A validator is using another beacon node to produce blocks and - // submitting them here. - if ctx.beacon_chain.head()?.beacon_block_root != block_root { - warn!( - ctx.log, - "Block from validator is not head"; - "desc" => "potential re-org", - ); - - } - } - - Ok(()) - } - Err(BlockError::BeaconChainError(e)) => { - error!( - ctx.log, - "Error whilst processing block"; - "error" => format!("{:?}", e) - ); - - Err(ApiError::ServerError(format!( - "Error while processing block: {:?}", - e - ))) - } - Err(other) => { - warn!( - ctx.log, - "Invalid block from local validator"; - "outcome" => format!("{:?}", other) - ); - - Err(ApiError::ProcessingError(format!( - "The SignedBeaconBlock could not be processed and has not been published: {:?}", - other - ))) - } - } - }) -} - -/// HTTP Handler to produce a new Attestation from the current state, ready to be signed by a validator. -pub fn get_new_attestation( - req: Request>, - ctx: Arc>, -) -> Result, ApiError> { - let query = UrlQuery::from_request(&req)?; - - let slot = query.slot()?; - let index = query.committee_index()?; - - ctx.beacon_chain - .produce_unaggregated_attestation(slot, index) - .map_err(|e| ApiError::BadRequest(format!("Unable to produce attestation: {:?}", e))) -} - -/// HTTP Handler to retrieve the aggregate attestation for a slot -pub fn get_aggregate_attestation( - req: Request>, - ctx: Arc>, -) -> Result, ApiError> { - let query = UrlQuery::from_request(&req)?; - - let attestation_data = query.attestation_data()?; - - match ctx - .beacon_chain - .get_aggregated_attestation(&attestation_data) - { - Ok(Some(attestation)) => Ok(attestation), - Ok(None) => Err(ApiError::NotFound(format!( - "No matching aggregate attestation for slot {:?} is known in slot {:?}", - attestation_data.slot, - ctx.beacon_chain.slot() - ))), - Err(e) => Err(ApiError::ServerError(format!( - "Unable to obtain attestation: {:?}", - e - ))), - } -} - -/// HTTP Handler to publish a list of Attestations, which have been signed by a number of validators. -pub fn publish_attestations( - req: Request>, - ctx: Arc>, -) -> Result<(), ApiError> { - let bytes = req.into_body(); - - serde_json::from_slice(&bytes) - .map_err(|e| { - ApiError::BadRequest(format!( - "Unable to deserialize JSON into a list of attestations: {:?}", - e - )) - }) - // Process all of the aggregates _without_ exiting early if one fails. - .map( - move |attestations: Vec<(Attestation, SubnetId)>| { - attestations - .into_iter() - .enumerate() - .map(|(i, (attestation, subnet_id))| { - process_unaggregated_attestation( - &ctx.beacon_chain, - ctx.network_chan.clone(), - attestation, - subnet_id, - i, - &ctx.log, - ) - }) - .collect::>>() - }, - ) - // Iterate through all the results and return on the first `Err`. - // - // Note: this will only provide info about the _first_ failure, not all failures. - .and_then(|processing_results| processing_results.into_iter().try_for_each(|result| result)) - .map(|_| ()) -} - -/// Processes an unaggregrated attestation that was included in a list of attestations with the -/// index `i`. -#[allow(clippy::redundant_clone)] // false positives in this function. -fn process_unaggregated_attestation( - beacon_chain: &BeaconChain, - network_chan: NetworkChannel, - attestation: Attestation, - subnet_id: SubnetId, - i: usize, - log: &Logger, -) -> Result<(), ApiError> { - let data = &attestation.data.clone(); - - // Verify that the attestation is valid to included on the gossip network. - let verified_attestation = beacon_chain - .verify_unaggregated_attestation_for_gossip(attestation.clone(), subnet_id) - .map_err(|e| { - handle_attestation_error( - e, - &format!("unaggregated attestation {} failed gossip verification", i), - data, - log, - ) - })?; - - // Publish the attestation to the network - if let Err(e) = network_chan.send(NetworkMessage::Publish { - messages: vec![PubsubMessage::Attestation(Box::new(( - subnet_id, - attestation, - )))], - }) { - return Err(ApiError::ServerError(format!( - "Unable to send unaggregated attestation {} to network: {:?}", - i, e - ))); - } - - beacon_chain - .apply_attestation_to_fork_choice(&verified_attestation) - .map_err(|e| { - handle_fork_choice_error( - e, - &format!( - "unaggregated attestation {} was unable to be added to fork choice", - i - ), - data, - log, - ) - })?; - - beacon_chain - .add_to_naive_aggregation_pool(verified_attestation) - .map_err(|e| { - handle_attestation_error( - e, - &format!( - "unaggregated attestation {} was unable to be added to aggregation pool", - i - ), - data, - log, - ) - })?; - - Ok(()) -} - -/// HTTP Handler to publish an Attestation, which has been signed by a validator. -pub fn publish_aggregate_and_proofs( - req: Request>, - ctx: Arc>, -) -> Result<(), ApiError> { - let body = req.into_body(); - - serde_json::from_slice(&body) - .map_err(|e| { - ApiError::BadRequest(format!( - "Unable to deserialize JSON into a list of SignedAggregateAndProof: {:?}", - e - )) - }) - // Process all of the aggregates _without_ exiting early if one fails. - .map( - move |signed_aggregates: Vec>| { - signed_aggregates - .into_iter() - .enumerate() - .map(|(i, signed_aggregate)| { - process_aggregated_attestation( - &ctx.beacon_chain, - ctx.network_chan.clone(), - signed_aggregate, - i, - &ctx.log, - ) - }) - .collect::>>() - }, - ) - // Iterate through all the results and return on the first `Err`. - // - // Note: this will only provide info about the _first_ failure, not all failures. - .and_then(|processing_results| processing_results.into_iter().try_for_each(|result| result)) -} - -/// Processes an aggregrated attestation that was included in a list of attestations with the index -/// `i`. -#[allow(clippy::redundant_clone)] // false positives in this function. -fn process_aggregated_attestation( - beacon_chain: &BeaconChain, - network_chan: NetworkChannel, - signed_aggregate: SignedAggregateAndProof, - i: usize, - log: &Logger, -) -> Result<(), ApiError> { - let data = &signed_aggregate.message.aggregate.data.clone(); - - // Verify that the attestation is valid to be included on the gossip network. - // - // Using this gossip check for local validators is not necessarily ideal, there will be some - // attestations that we reject that could possibly be included in a block (e.g., attestations - // that late by more than 1 epoch but less than 2). We can come pick this back up if we notice - // that it's materially affecting validator profits. Until then, I'm hesitant to introduce yet - // _another_ attestation verification path. - let verified_attestation = - match beacon_chain.verify_aggregated_attestation_for_gossip(signed_aggregate.clone()) { - Ok(verified_attestation) => verified_attestation, - Err(AttnError::AttestationAlreadyKnown(attestation_root)) => { - trace!( - log, - "Ignored known attn from local validator"; - "attn_root" => format!("{}", attestation_root) - ); - - // Exit early with success for a known attestation, there's no need to re-process - // an aggregate we already know. - return Ok(()); - } - /* - * It's worth noting that we don't check for `Error::AggregatorAlreadyKnown` since (at - * the time of writing) we check for `AttestationAlreadyKnown` first. - * - * Given this, it's impossible to hit `Error::AggregatorAlreadyKnown` without that - * aggregator having already produced a conflicting aggregation. This is not slashable - * but I think it's still the sort of condition we should error on, at least for now. - */ - Err(e) => { - return Err(handle_attestation_error( - e, - &format!("aggregated attestation {} failed gossip verification", i), - data, - log, - )) - } - }; - - // Publish the attestation to the network - if let Err(e) = network_chan.send(NetworkMessage::Publish { - messages: vec![PubsubMessage::AggregateAndProofAttestation(Box::new( - signed_aggregate, - ))], - }) { - return Err(ApiError::ServerError(format!( - "Unable to send aggregated attestation {} to network: {:?}", - i, e - ))); - } - - beacon_chain - .apply_attestation_to_fork_choice(&verified_attestation) - .map_err(|e| { - handle_fork_choice_error( - e, - &format!( - "aggregated attestation {} was unable to be added to fork choice", - i - ), - data, - log, - ) - })?; - - beacon_chain - .add_to_block_inclusion_pool(verified_attestation) - .map_err(|e| { - handle_attestation_error( - e, - &format!( - "aggregated attestation {} was unable to be added to op pool", - i - ), - data, - log, - ) - })?; - - Ok(()) -} - -/// Common handler for `AttnError` during attestation verification. -fn handle_attestation_error( - e: AttnError, - detail: &str, - data: &AttestationData, - log: &Logger, -) -> ApiError { - match e { - AttnError::BeaconChainError(e) => { - error!( - log, - "Internal error verifying local attestation"; - "detail" => detail, - "error" => format!("{:?}", e), - "target" => data.target.epoch, - "source" => data.source.epoch, - "index" => data.index, - "slot" => data.slot, - ); - - ApiError::ServerError(format!( - "Internal error verifying local attestation. Error: {:?}. Detail: {}", - e, detail - )) - } - e => { - error!( - log, - "Invalid local attestation"; - "detail" => detail, - "reason" => format!("{:?}", e), - "target" => data.target.epoch, - "source" => data.source.epoch, - "index" => data.index, - "slot" => data.slot, - ); - - ApiError::ProcessingError(format!( - "Invalid local attestation. Error: {:?} Detail: {}", - e, detail - )) - } - } -} - -/// Common handler for `ForkChoiceError` during attestation verification. -fn handle_fork_choice_error( - e: BeaconChainError, - detail: &str, - data: &AttestationData, - log: &Logger, -) -> ApiError { - match e { - BeaconChainError::ForkChoiceError(ForkChoiceError::InvalidAttestation(e)) => { - error!( - log, - "Local attestation invalid for fork choice"; - "detail" => detail, - "reason" => format!("{:?}", e), - "target" => data.target.epoch, - "source" => data.source.epoch, - "index" => data.index, - "slot" => data.slot, - ); - - ApiError::ProcessingError(format!( - "Invalid local attestation. Error: {:?} Detail: {}", - e, detail - )) - } - e => { - error!( - log, - "Internal error applying attn to fork choice"; - "detail" => detail, - "error" => format!("{:?}", e), - "target" => data.target.epoch, - "source" => data.source.epoch, - "index" => data.index, - "slot" => data.slot, - ); - - ApiError::ServerError(format!( - "Internal error verifying local attestation. Error: {:?}. Detail: {}", - e, detail - )) - } - } -} diff --git a/beacon_node/rest_api/tests/test.rs b/beacon_node/rest_api/tests/test.rs deleted file mode 100644 index 160ee667ccf..00000000000 --- a/beacon_node/rest_api/tests/test.rs +++ /dev/null @@ -1,1345 +0,0 @@ -#![cfg(test)] - -#[macro_use] -extern crate assert_matches; - -use beacon_chain::{BeaconChain, BeaconChainTypes, StateSkipConfig}; -use node_test_rig::{ - environment::{Environment, EnvironmentBuilder}, - testing_client_config, ClientConfig, ClientGenesis, LocalBeaconNode, -}; -use remote_beacon_node::{ - Committee, HeadBeaconBlock, PersistedOperationPool, PublishStatus, ValidatorResponse, -}; -use rest_types::ValidatorDutyBytes; -use std::convert::TryInto; -use std::sync::Arc; -use std::time::{SystemTime, UNIX_EPOCH}; -use types::{ - test_utils::{ - build_double_vote_attester_slashing, build_proposer_slashing, - generate_deterministic_keypair, AttesterSlashingTestTask, ProposerSlashingTestTask, - }, - BeaconBlock, BeaconState, ChainSpec, Domain, Epoch, EthSpec, MinimalEthSpec, PublicKey, - RelativeEpoch, Signature, SignedAggregateAndProof, SignedBeaconBlock, SignedRoot, Slot, - SubnetId, Validator, -}; - -type E = MinimalEthSpec; - -fn build_env() -> Environment { - EnvironmentBuilder::minimal() - .null_logger() - .expect("should build env logger") - .single_thread_tokio_runtime() - .expect("should start tokio runtime") - .build() - .expect("environment should build") -} - -fn build_node(env: &mut Environment, config: ClientConfig) -> LocalBeaconNode { - let context = env.core_context(); - env.runtime() - .block_on(LocalBeaconNode::production(context, config)) - .expect("should block until node created") -} - -/// Returns the randao reveal for the given slot (assuming the given `beacon_chain` uses -/// deterministic keypairs). -fn get_randao_reveal( - beacon_chain: Arc>, - slot: Slot, - spec: &ChainSpec, -) -> Signature { - let head = beacon_chain.head().expect("should get head"); - let fork = head.beacon_state.fork; - let genesis_validators_root = head.beacon_state.genesis_validators_root; - let proposer_index = beacon_chain - .block_proposer(slot) - .expect("should get proposer index"); - let keypair = generate_deterministic_keypair(proposer_index); - let epoch = slot.epoch(E::slots_per_epoch()); - let domain = spec.get_domain(epoch, Domain::Randao, &fork, genesis_validators_root); - let message = epoch.signing_root(domain); - keypair.sk.sign(message) -} - -/// Signs the given block (assuming the given `beacon_chain` uses deterministic keypairs). -fn sign_block( - beacon_chain: Arc>, - block: BeaconBlock, - spec: &ChainSpec, -) -> SignedBeaconBlock { - let head = beacon_chain.head().expect("should get head"); - let fork = head.beacon_state.fork; - let genesis_validators_root = head.beacon_state.genesis_validators_root; - let proposer_index = beacon_chain - .block_proposer(block.slot) - .expect("should get proposer index"); - let keypair = generate_deterministic_keypair(proposer_index); - block.sign(&keypair.sk, &fork, genesis_validators_root, spec) -} - -#[test] -fn validator_produce_attestation() { - let mut env = build_env(); - - let spec = &E::default_spec(); - - let node = build_node(&mut env, testing_client_config()); - let remote_node = node.remote_node().expect("should produce remote node"); - - let beacon_chain = node - .client - .beacon_chain() - .expect("client should have beacon chain"); - let genesis_validators_root = beacon_chain.genesis_validators_root; - let state = beacon_chain.head().expect("should get head").beacon_state; - - // Find a validator that has duties in the current slot of the chain. - let mut validator_index = 0; - let duties = loop { - let duties = state - .get_attestation_duties(validator_index, RelativeEpoch::Current) - .expect("should have attestation duties cache") - .expect("should have attestation duties"); - - if duties.slot == node.client.beacon_chain().unwrap().slot().unwrap() { - break duties; - } else { - validator_index += 1 - } - }; - - let mut attestation = env - .runtime() - .block_on( - remote_node - .http - .validator() - .produce_attestation(duties.slot, duties.index), - ) - .expect("should fetch attestation from http api"); - - assert_eq!( - attestation.data.index, duties.index, - "should have same index" - ); - assert_eq!(attestation.data.slot, duties.slot, "should have same slot"); - assert_eq!( - attestation.aggregation_bits.num_set_bits(), - 0, - "should have empty aggregation bits" - ); - - let keypair = generate_deterministic_keypair(validator_index); - - // Fetch the duties again, but via HTTP for authenticity. - let duties = env - .runtime() - .block_on(remote_node.http.validator().get_duties( - attestation.data.slot.epoch(E::slots_per_epoch()), - &[keypair.pk.clone()], - )) - .expect("should fetch duties from http api"); - let duties = &duties[0]; - let committee_count = duties - .committee_count_at_slot - .expect("should have committee count"); - let subnet_id = SubnetId::compute_subnet::( - attestation.data.slot, - attestation.data.index, - committee_count, - spec, - ) - .unwrap(); - // Try publishing the attestation without a signature or a committee bit set, ensure it is - // raises an error. - let publish_status = env - .runtime() - .block_on( - remote_node - .http - .validator() - .publish_attestations(vec![(attestation.clone(), subnet_id)]), - ) - .expect("should publish unsigned attestation"); - assert!( - !publish_status.is_valid(), - "the unsigned published attestation should be invalid" - ); - - // Set the aggregation bit. - attestation - .aggregation_bits - .set( - duties - .attestation_committee_position - .expect("should have committee position"), - true, - ) - .expect("should set attestation bit"); - - // Try publishing with an aggreagation bit set, but an invalid signature. - let publish_status = env - .runtime() - .block_on( - remote_node - .http - .validator() - .publish_attestations(vec![(attestation.clone(), subnet_id)]), - ) - .expect("should publish attestation with invalid signature"); - assert!( - !publish_status.is_valid(), - "the unsigned published attestation should not be valid" - ); - - // Un-set the aggregation bit, so signing doesn't error. - attestation - .aggregation_bits - .set( - duties - .attestation_committee_position - .expect("should have committee position"), - false, - ) - .expect("should un-set attestation bit"); - - attestation - .sign( - &keypair.sk, - duties - .attestation_committee_position - .expect("should have committee position"), - &state.fork, - state.genesis_validators_root, - spec, - ) - .expect("should sign attestation"); - - // Try publishing the valid attestation. - let publish_status = env - .runtime() - .block_on( - remote_node - .http - .validator() - .publish_attestations(vec![(attestation.clone(), subnet_id)]), - ) - .expect("should publish attestation"); - assert!( - publish_status.is_valid(), - "the signed published attestation should be valid" - ); - - // Try obtaining an aggregated attestation with a matching attestation data to the previous - // one. - let aggregated_attestation = env - .runtime() - .block_on( - remote_node - .http - .validator() - .produce_aggregate_attestation(&attestation.data), - ) - .expect("should fetch aggregated attestation from http api"); - - let signed_aggregate_and_proof = SignedAggregateAndProof::from_aggregate( - validator_index as u64, - aggregated_attestation, - None, - &keypair.sk, - &state.fork, - genesis_validators_root, - spec, - ); - - // Publish the signed aggregate. - let publish_status = env - .runtime() - .block_on( - remote_node - .http - .validator() - .publish_aggregate_and_proof(vec![signed_aggregate_and_proof]), - ) - .expect("should publish aggregate and proof"); - assert!( - publish_status.is_valid(), - "the signed aggregate and proof should be valid" - ); -} - -#[test] -fn validator_duties() { - let mut env = build_env(); - - let spec = &E::default_spec(); - - let node = build_node(&mut env, testing_client_config()); - let remote_node = node.remote_node().expect("should produce remote node"); - - let beacon_chain = node - .client - .beacon_chain() - .expect("client should have beacon chain"); - - let mut epoch = Epoch::new(0); - - let validators = beacon_chain - .head() - .expect("should get head") - .beacon_state - .validators - .iter() - .map(|v| (&v.pubkey).try_into().expect("pubkey should be valid")) - .collect::>(); - - let duties = env - .runtime() - .block_on(remote_node.http.validator().get_duties(epoch, &validators)) - .expect("should fetch duties from http api"); - - // 1. Check at the current epoch. - check_duties( - duties, - epoch, - validators.clone(), - beacon_chain.clone(), - spec, - ); - - epoch += 4; - let duties = env - .runtime() - .block_on(remote_node.http.validator().get_duties(epoch, &validators)) - .expect("should fetch duties from http api"); - - // 2. Check with a long skip forward. - check_duties(duties, epoch, validators, beacon_chain, spec); - - // TODO: test an epoch in the past. Blocked because the `LocalBeaconNode` cannot produce a - // chain, yet. -} - -fn check_duties( - duties: Vec, - epoch: Epoch, - validators: Vec, - beacon_chain: Arc>, - spec: &ChainSpec, -) { - assert_eq!( - validators.len(), - duties.len(), - "there should be a duty for each validator" - ); - - // Are the duties from the current epoch of the beacon chain, and thus are proposer indices - // known? - let proposers_known = epoch == beacon_chain.epoch().unwrap(); - - let mut state = beacon_chain - .state_at_slot( - epoch.start_slot(T::EthSpec::slots_per_epoch()), - StateSkipConfig::WithStateRoots, - ) - .expect("should get state at slot"); - - state.build_all_caches(spec).expect("should build caches"); - - validators - .iter() - .zip(duties.iter()) - .for_each(|(validator, duty)| { - assert_eq!( - *validator, - (&duty.validator_pubkey) - .try_into() - .expect("should be valid pubkey"), - "pubkey should match" - ); - - let validator_index = state - .get_validator_index(&validator.clone().into()) - .expect("should have pubkey cache") - .expect("pubkey should exist"); - - let attestation_duty = state - .get_attestation_duties(validator_index, RelativeEpoch::Current) - .expect("should have attestation duties cache") - .expect("should have attestation duties"); - - assert_eq!( - Some(attestation_duty.slot), - duty.attestation_slot, - "attestation slot should match" - ); - - assert_eq!( - Some(attestation_duty.index), - duty.attestation_committee_index, - "attestation index should match" - ); - - if proposers_known { - let block_proposal_slots = duty.block_proposal_slots.as_ref().unwrap(); - - if !block_proposal_slots.is_empty() { - for slot in block_proposal_slots { - let expected_proposer = state - .get_beacon_proposer_index(*slot, spec) - .expect("should know proposer"); - assert_eq!( - expected_proposer, validator_index, - "should get correct proposal slot" - ); - } - } else { - epoch.slot_iter(E::slots_per_epoch()).for_each(|slot| { - let slot_proposer = state - .get_beacon_proposer_index(slot, spec) - .expect("should know proposer"); - assert_ne!( - slot_proposer, validator_index, - "validator should not have proposal slot in this epoch" - ) - }) - } - } else { - assert_eq!(duty.block_proposal_slots, None); - } - }); - - if proposers_known { - // Validator duties should include a proposer for every slot of the epoch. - let mut all_proposer_slots: Vec = duties - .iter() - .flat_map(|duty| duty.block_proposal_slots.clone().unwrap()) - .collect(); - all_proposer_slots.sort(); - - let all_slots: Vec = epoch.slot_iter(E::slots_per_epoch()).collect(); - assert_eq!(all_proposer_slots, all_slots); - } -} - -#[test] -fn validator_block_post() { - let mut env = build_env(); - - let spec = &E::default_spec(); - - let two_slots_secs = (spec.milliseconds_per_slot / 1_000) * 2; - - let mut config = testing_client_config(); - config.genesis = ClientGenesis::Interop { - validator_count: 8, - genesis_time: SystemTime::now() - .duration_since(UNIX_EPOCH) - .unwrap() - .as_secs() - - two_slots_secs, - }; - - let node = build_node(&mut env, config); - let remote_node = node.remote_node().expect("should produce remote node"); - - let beacon_chain = node - .client - .beacon_chain() - .expect("client should have beacon chain"); - - let slot = Slot::new(1); - let randao_reveal = get_randao_reveal(beacon_chain.clone(), slot, spec); - - let block = env - .runtime() - .block_on( - remote_node - .http - .validator() - .produce_block(slot, randao_reveal, None), - ) - .expect("should fetch block from http api"); - - // Try publishing the block without a signature, ensure it is flagged as invalid. - let empty_sig_block = SignedBeaconBlock { - message: block.clone(), - signature: Signature::empty(), - }; - let publish_status = env - .runtime() - .block_on(remote_node.http.validator().publish_block(empty_sig_block)) - .expect("should publish block"); - if cfg!(not(feature = "fake_crypto")) { - assert!( - !publish_status.is_valid(), - "the unsigned published block should not be valid" - ); - } - - let signed_block = sign_block(beacon_chain.clone(), block, spec); - let block_root = signed_block.canonical_root(); - - let publish_status = env - .runtime() - .block_on(remote_node.http.validator().publish_block(signed_block)) - .expect("should publish block"); - - if cfg!(not(feature = "fake_crypto")) { - assert_eq!( - publish_status, - PublishStatus::Valid, - "the signed published block should be valid" - ); - } - - let head = env - .runtime() - .block_on(remote_node.http.beacon().get_head()) - .expect("should get head"); - - assert_eq!( - head.block_root, block_root, - "the published block should become the head block" - ); - - // Note: this heads check is not super useful for this test, however it is include so it get - // _some_ testing. If you remove this call, make sure it's tested somewhere else. - let heads = env - .runtime() - .block_on(remote_node.http.beacon().get_heads()) - .expect("should get heads"); - - assert_eq!(heads.len(), 1, "there should be only one head"); - assert_eq!( - heads, - vec![HeadBeaconBlock { - beacon_block_root: head.block_root, - beacon_block_slot: head.slot, - }], - "there should be only one head" - ); -} - -#[test] -fn validator_block_get() { - let mut env = build_env(); - - let spec = &E::default_spec(); - - let node = build_node(&mut env, testing_client_config()); - let remote_node = node.remote_node().expect("should produce remote node"); - - let beacon_chain = node - .client - .beacon_chain() - .expect("client should have beacon chain"); - - let slot = Slot::new(1); - let randao_reveal = get_randao_reveal(beacon_chain, slot, spec); - - let block = env - .runtime() - .block_on( - remote_node - .http - .validator() - .produce_block(slot, randao_reveal.clone(), None), - ) - .expect("should fetch block from http api"); - - let (expected_block, _state) = node - .client - .beacon_chain() - .expect("client should have beacon chain") - .produce_block(randao_reveal, slot, None) - .expect("should produce block"); - - assert_eq!( - block, expected_block, - "the block returned from the API should be as expected" - ); -} - -#[test] -fn validator_block_get_with_graffiti() { - let mut env = build_env(); - - let spec = &E::default_spec(); - - let node = build_node(&mut env, testing_client_config()); - let remote_node = node.remote_node().expect("should produce remote node"); - - let beacon_chain = node - .client - .beacon_chain() - .expect("client should have beacon chain"); - - let slot = Slot::new(1); - let randao_reveal = get_randao_reveal(beacon_chain, slot, spec); - - let block = env - .runtime() - .block_on(remote_node.http.validator().produce_block( - slot, - randao_reveal.clone(), - Some(*b"test-graffiti-test-graffiti-test"), - )) - .expect("should fetch block from http api"); - - let (expected_block, _state) = node - .client - .beacon_chain() - .expect("client should have beacon chain") - .produce_block( - randao_reveal, - slot, - Some(*b"test-graffiti-test-graffiti-test"), - ) - .expect("should produce block"); - - assert_eq!( - block, expected_block, - "the block returned from the API should be as expected" - ); -} - -#[test] -fn beacon_state() { - let mut env = build_env(); - - let node = build_node(&mut env, testing_client_config()); - let remote_node = node.remote_node().expect("should produce remote node"); - - let (state_by_slot, root) = env - .runtime() - .block_on(remote_node.http.beacon().get_state_by_slot(Slot::new(0))) - .expect("should fetch state from http api"); - - let (state_by_root, root_2) = env - .runtime() - .block_on(remote_node.http.beacon().get_state_by_root(root)) - .expect("should fetch state from http api"); - - let mut db_state = node - .client - .beacon_chain() - .expect("client should have beacon chain") - .state_at_slot(Slot::new(0), StateSkipConfig::WithStateRoots) - .expect("should find state"); - db_state.drop_all_caches(); - - assert_eq!( - root, root_2, - "the two roots returned from the api should be identical" - ); - assert_eq!( - root, - db_state.canonical_root(), - "root from database should match that from the API" - ); - assert_eq!( - state_by_slot, db_state, - "genesis state by slot from api should match that from the DB" - ); - assert_eq!( - state_by_root, db_state, - "genesis state by root from api should match that from the DB" - ); -} - -#[test] -fn beacon_block() { - let mut env = build_env(); - - let node = build_node(&mut env, testing_client_config()); - let remote_node = node.remote_node().expect("should produce remote node"); - - let (block_by_slot, root) = env - .runtime() - .block_on(remote_node.http.beacon().get_block_by_slot(Slot::new(0))) - .expect("should fetch block from http api"); - - let (block_by_root, root_2) = env - .runtime() - .block_on(remote_node.http.beacon().get_block_by_root(root)) - .expect("should fetch block from http api"); - - let db_block = node - .client - .beacon_chain() - .expect("client should have beacon chain") - .block_at_slot(Slot::new(0)) - .expect("should find block") - .expect("block should not be none"); - - assert_eq!( - root, root_2, - "the two roots returned from the api should be identical" - ); - assert_eq!( - root, - db_block.canonical_root(), - "root from database should match that from the API" - ); - assert_eq!( - block_by_slot, db_block, - "genesis block by slot from api should match that from the DB" - ); - assert_eq!( - block_by_root, db_block, - "genesis block by root from api should match that from the DB" - ); -} - -#[test] -fn genesis_time() { - let mut env = build_env(); - - let node = build_node(&mut env, testing_client_config()); - let remote_node = node.remote_node().expect("should produce remote node"); - - let genesis_time = env - .runtime() - .block_on(remote_node.http.beacon().get_genesis_time()) - .expect("should fetch genesis time from http api"); - - assert_eq!( - node.client - .beacon_chain() - .expect("should have beacon chain") - .head() - .expect("should get head") - .beacon_state - .genesis_time, - genesis_time, - "should match genesis time from head state" - ); -} - -#[test] -fn genesis_validators_root() { - let mut env = build_env(); - - let node = build_node(&mut env, testing_client_config()); - let remote_node = node.remote_node().expect("should produce remote node"); - - let genesis_validators_root = env - .runtime() - .block_on(remote_node.http.beacon().get_genesis_validators_root()) - .expect("should fetch genesis time from http api"); - - assert_eq!( - node.client - .beacon_chain() - .expect("should have beacon chain") - .head() - .expect("should get head") - .beacon_state - .genesis_validators_root, - genesis_validators_root, - "should match genesis time from head state" - ); -} - -#[test] -fn fork() { - let mut env = build_env(); - - let node = build_node(&mut env, testing_client_config()); - let remote_node = node.remote_node().expect("should produce remote node"); - - let fork = env - .runtime() - .block_on(remote_node.http.beacon().get_fork()) - .expect("should fetch from http api"); - - assert_eq!( - node.client - .beacon_chain() - .expect("should have beacon chain") - .head() - .expect("should get head") - .beacon_state - .fork, - fork, - "should match head state" - ); -} - -#[test] -fn eth2_config() { - let mut env = build_env(); - - let node = build_node(&mut env, testing_client_config()); - let remote_node = node.remote_node().expect("should produce remote node"); - - let eth2_config = env - .runtime() - .block_on(remote_node.http.spec().get_eth2_config()) - .expect("should fetch eth2 config from http api"); - - // TODO: check the entire eth2_config, not just the spec. - - assert_eq!( - node.client - .beacon_chain() - .expect("should have beacon chain") - .spec, - eth2_config.spec, - "should match genesis time from head state" - ); -} - -#[test] -fn get_version() { - let mut env = build_env(); - - let node = build_node(&mut env, testing_client_config()); - let remote_node = node.remote_node().expect("should produce remote node"); - - let version = env - .runtime() - .block_on(remote_node.http.node().get_version()) - .expect("should fetch version from http api"); - - assert_eq!( - lighthouse_version::version_with_platform(), - version, - "result should be as expected" - ); -} - -#[test] -fn get_genesis_state_root() { - let mut env = build_env(); - - let node = build_node(&mut env, testing_client_config()); - let remote_node = node.remote_node().expect("should produce remote node"); - - let slot = Slot::new(0); - - let result = env - .runtime() - .block_on(remote_node.http.beacon().get_state_root(slot)) - .expect("should fetch from http api"); - - let expected = node - .client - .beacon_chain() - .expect("should have beacon chain") - .rev_iter_state_roots() - .expect("should get iter") - .map(Result::unwrap) - .find(|(_cur_root, cur_slot)| slot == *cur_slot) - .map(|(cur_root, _)| cur_root) - .expect("chain should have state root at slot"); - - assert_eq!(result, expected, "result should be as expected"); -} - -#[test] -fn get_genesis_block_root() { - let mut env = build_env(); - - let node = build_node(&mut env, testing_client_config()); - let remote_node = node.remote_node().expect("should produce remote node"); - - let slot = Slot::new(0); - - let result = env - .runtime() - .block_on(remote_node.http.beacon().get_block_root(slot)) - .expect("should fetch from http api"); - - let expected = node - .client - .beacon_chain() - .expect("should have beacon chain") - .rev_iter_block_roots() - .expect("should get iter") - .map(Result::unwrap) - .find(|(_cur_root, cur_slot)| slot == *cur_slot) - .map(|(cur_root, _)| cur_root) - .expect("chain should have state root at slot"); - - assert_eq!(result, expected, "result should be as expected"); -} - -#[test] -fn get_validators() { - let mut env = build_env(); - - let node = build_node(&mut env, testing_client_config()); - let remote_node = node.remote_node().expect("should produce remote node"); - let chain = node - .client - .beacon_chain() - .expect("node should have beacon chain"); - let state = &chain.head().expect("should get head").beacon_state; - - let validators = state.validators.iter().take(2).collect::>(); - let pubkeys = validators - .iter() - .map(|v| (&v.pubkey).try_into().expect("should decode pubkey bytes")) - .collect(); - - let result = env - .runtime() - .block_on(remote_node.http.beacon().get_validators(pubkeys, None)) - .expect("should fetch from http api"); - - result - .iter() - .zip(validators.iter()) - .for_each(|(response, validator)| compare_validator_response(state, response, validator)); -} - -#[test] -fn get_all_validators() { - let mut env = build_env(); - - let node = build_node(&mut env, testing_client_config()); - let remote_node = node.remote_node().expect("should produce remote node"); - let chain = node - .client - .beacon_chain() - .expect("node should have beacon chain"); - let state = &chain.head().expect("should get head").beacon_state; - - let result = env - .runtime() - .block_on(remote_node.http.beacon().get_all_validators(None)) - .expect("should fetch from http api"); - - result - .iter() - .zip(state.validators.iter()) - .for_each(|(response, validator)| compare_validator_response(state, response, validator)); -} - -#[test] -fn get_active_validators() { - let mut env = build_env(); - - let node = build_node(&mut env, testing_client_config()); - let remote_node = node.remote_node().expect("should produce remote node"); - let chain = node - .client - .beacon_chain() - .expect("node should have beacon chain"); - let state = &chain.head().expect("should get head").beacon_state; - - let result = env - .runtime() - .block_on(remote_node.http.beacon().get_active_validators(None)) - .expect("should fetch from http api"); - - /* - * This test isn't comprehensive because all of the validators in the state are active (i.e., - * there is no one to exclude. - * - * This should be fixed once we can generate more interesting scenarios with the - * `NodeTestRig`. - */ - - let validators = state - .validators - .iter() - .filter(|validator| validator.is_active_at(state.current_epoch())); - - result - .iter() - .zip(validators) - .for_each(|(response, validator)| compare_validator_response(state, response, validator)); -} - -#[test] -fn get_committees() { - let mut env = build_env(); - - let node = build_node(&mut env, testing_client_config()); - let remote_node = node.remote_node().expect("should produce remote node"); - let chain = node - .client - .beacon_chain() - .expect("node should have beacon chain"); - - let epoch = Epoch::new(0); - - let result = env - .runtime() - .block_on(remote_node.http.beacon().get_committees(epoch)) - .expect("should fetch from http api"); - - let expected = chain - .head() - .expect("should get head") - .beacon_state - .get_beacon_committees_at_epoch(RelativeEpoch::Current) - .expect("should get committees") - .iter() - .map(|c| Committee { - slot: c.slot, - index: c.index, - committee: c.committee.to_vec(), - }) - .collect::>(); - - assert_eq!(result, expected, "result should be as expected"); -} - -#[test] -fn get_fork_choice() { - let mut env = build_env(); - - let node = build_node(&mut env, testing_client_config()); - let remote_node = node.remote_node().expect("should produce remote node"); - - let fork_choice = env - .runtime() - .block_on(remote_node.http.advanced().get_fork_choice()) - .expect("should not error when getting fork choice"); - - assert_eq!( - fork_choice, - *node - .client - .beacon_chain() - .expect("node should have beacon chain") - .fork_choice - .read() - .proto_array() - .core_proto_array(), - "result should be as expected" - ); -} - -#[test] -fn get_operation_pool() { - let mut env = build_env(); - - let node = build_node(&mut env, testing_client_config()); - let remote_node = node.remote_node().expect("should produce remote node"); - - let result = env - .runtime() - .block_on(remote_node.http.advanced().get_operation_pool()) - .expect("should not error when getting fork choice"); - - let expected = PersistedOperationPool::from_operation_pool( - &node - .client - .beacon_chain() - .expect("node should have chain") - .op_pool, - ); - - assert_eq!(result, expected, "result should be as expected"); -} - -fn compare_validator_response( - state: &BeaconState, - response: &ValidatorResponse, - validator: &Validator, -) { - let response_validator = response.validator.clone().expect("should have validator"); - let i = response - .validator_index - .expect("should have validator index"); - let balance = response.balance.expect("should have balance"); - - assert_eq!(response.pubkey, validator.pubkey, "pubkey"); - assert_eq!(response_validator, *validator, "validator"); - assert_eq!(state.balances[i], balance, "balances"); - assert_eq!(state.validators[i], *validator, "validator index"); -} - -#[test] -fn proposer_slashing() { - let mut env = build_env(); - - let node = build_node(&mut env, testing_client_config()); - let remote_node = node.remote_node().expect("should produce remote node"); - let chain = node - .client - .beacon_chain() - .expect("node should have beacon chain"); - - let state = chain - .head() - .expect("should have retrieved state") - .beacon_state; - - let spec = &chain.spec; - - // Check that there are no proposer slashings before insertion - let (proposer_slashings, _attester_slashings) = chain.op_pool.get_slashings(&state); - assert_eq!(proposer_slashings.len(), 0); - - let slot = state.slot; - let proposer_index = chain - .block_proposer(slot) - .expect("should get proposer index"); - let keypair = generate_deterministic_keypair(proposer_index); - let key = &keypair.sk; - let fork = &state.fork; - let proposer_slashing = build_proposer_slashing::( - ProposerSlashingTestTask::Valid, - proposer_index as u64, - &key, - fork, - state.genesis_validators_root, - spec, - ); - - let result = env - .runtime() - .block_on( - remote_node - .http - .beacon() - .proposer_slashing(proposer_slashing.clone()), - ) - .expect("should fetch from http api"); - assert!(result, true); - - // Length should be just one as we've inserted only one proposer slashing - let (proposer_slashings, _attester_slashings) = chain.op_pool.get_slashings(&state); - assert_eq!(proposer_slashings.len(), 1); - assert_eq!(proposer_slashing.clone(), proposer_slashings[0]); - - let mut invalid_proposer_slashing = build_proposer_slashing::( - ProposerSlashingTestTask::Valid, - proposer_index as u64, - &key, - fork, - state.genesis_validators_root, - spec, - ); - invalid_proposer_slashing.signed_header_2 = invalid_proposer_slashing.signed_header_1.clone(); - - let result = env.runtime().block_on( - remote_node - .http - .beacon() - .proposer_slashing(invalid_proposer_slashing), - ); - assert!(result.is_err()); - - // Length should still be one as we've inserted nothing since last time. - let (proposer_slashings, _attester_slashings) = chain.op_pool.get_slashings(&state); - assert_eq!(proposer_slashings.len(), 1); - assert_eq!(proposer_slashing, proposer_slashings[0]); -} - -#[test] -fn attester_slashing() { - let mut env = build_env(); - - let node = build_node(&mut env, testing_client_config()); - let remote_node = node.remote_node().expect("should produce remote node"); - let chain = node - .client - .beacon_chain() - .expect("node should have beacon chain"); - - let state = chain - .head() - .expect("should have retrieved state") - .beacon_state; - let slot = state.slot; - let spec = &chain.spec; - - let proposer_index = chain - .block_proposer(slot) - .expect("should get proposer index"); - let keypair = generate_deterministic_keypair(proposer_index); - - let secret_keys = vec![&keypair.sk]; - let validator_indices = vec![proposer_index as u64]; - let fork = &state.fork; - - // Checking there are no attester slashings before insertion - let (_proposer_slashings, attester_slashings) = chain.op_pool.get_slashings(&state); - assert_eq!(attester_slashings.len(), 0); - - let attester_slashing = build_double_vote_attester_slashing( - AttesterSlashingTestTask::Valid, - &validator_indices[..], - &secret_keys[..], - fork, - state.genesis_validators_root, - spec, - ); - - let result = env - .runtime() - .block_on( - remote_node - .http - .beacon() - .attester_slashing(attester_slashing.clone()), - ) - .expect("should fetch from http api"); - assert!(result, true); - - // Length should be just one as we've inserted only one attester slashing - let (_proposer_slashings, attester_slashings) = chain.op_pool.get_slashings(&state); - assert_eq!(attester_slashings.len(), 1); - assert_eq!(attester_slashing, attester_slashings[0]); - - // Building an invalid attester slashing - let mut invalid_attester_slashing = build_double_vote_attester_slashing( - AttesterSlashingTestTask::Valid, - &validator_indices[..], - &secret_keys[..], - fork, - state.genesis_validators_root, - spec, - ); - invalid_attester_slashing.attestation_2 = invalid_attester_slashing.attestation_1.clone(); - - let result = env.runtime().block_on( - remote_node - .http - .beacon() - .attester_slashing(invalid_attester_slashing), - ); - result.unwrap_err(); - - // Length should still be one as we've failed to insert the attester slashing. - let (_proposer_slashings, attester_slashings) = chain.op_pool.get_slashings(&state); - assert_eq!(attester_slashings.len(), 1); - assert_eq!(attester_slashing, attester_slashings[0]); -} - -mod validator_attestation { - use super::*; - use http::StatusCode; - use node_test_rig::environment::Environment; - use remote_beacon_node::{Error::DidNotSucceed, HttpClient}; - use types::{Attestation, AttestationDuty, MinimalEthSpec}; - use url::Url; - - fn setup() -> ( - Environment, - LocalBeaconNode, - HttpClient, - Url, - AttestationDuty, - ) { - let mut env = build_env(); - let node = build_node(&mut env, testing_client_config()); - let remote_node = node.remote_node().expect("should produce remote node"); - let client = remote_node.http.clone(); - let socket_addr = node - .client - .http_listen_addr() - .expect("A remote beacon node must have a http server"); - let url = Url::parse(&format!( - "http://{}:{}/validator/attestation", - socket_addr.ip(), - socket_addr.port() - )) - .expect("should be valid endpoint"); - - // Find a validator that has duties in the current slot of the chain. - let mut validator_index = 0; - let beacon_chain = node - .client - .beacon_chain() - .expect("client should have beacon chain"); - let state = beacon_chain.head().expect("should get head").beacon_state; - let duties = loop { - let duties = state - .get_attestation_duties(validator_index, RelativeEpoch::Current) - .expect("should have attestation duties cache") - .expect("should have attestation duties"); - - if duties.slot == node.client.beacon_chain().unwrap().slot().unwrap() { - break duties; - } else { - validator_index += 1 - } - }; - - (env, node, client, url, duties) - } - - #[test] - fn requires_query_parameters() { - let (mut env, _node, client, url, _duties) = setup(); - - let attestation = env.runtime().block_on( - // query parameters are missing - client.json_get::>(url.clone(), vec![]), - ); - - assert_matches!( - attestation.expect_err("should not succeed"), - DidNotSucceed { status, body } => { - assert_eq!(status, StatusCode::BAD_REQUEST); - assert_eq!(body, "URL query must be valid and contain at least one of the following keys: [\"slot\"]".to_owned()); - } - ); - } - - #[test] - fn requires_slot() { - let (mut env, _node, client, url, duties) = setup(); - - let attestation = env.runtime().block_on( - // `slot` is missing - client.json_get::>( - url.clone(), - vec![("committee_index".into(), format!("{}", duties.index))], - ), - ); - - assert_matches!( - attestation.expect_err("should not succeed"), - DidNotSucceed { status, body } => { - assert_eq!(status, StatusCode::BAD_REQUEST); - assert_eq!(body, "URL query must be valid and contain at least one of the following keys: [\"slot\"]".to_owned()); - } - ); - } - - #[test] - fn requires_committee_index() { - let (mut env, _node, client, url, duties) = setup(); - - let attestation = env.runtime().block_on( - // `committee_index` is missing. - client.json_get::>( - url.clone(), - vec![("slot".into(), format!("{}", duties.slot))], - ), - ); - - assert_matches!( - attestation.expect_err("should not succeed"), - DidNotSucceed { status, body } => { - assert_eq!(status, StatusCode::BAD_REQUEST); - assert_eq!(body, "URL query must be valid and contain at least one of the following keys: [\"committee_index\"]".to_owned()); - } - ); - } -} - -#[cfg(target_os = "linux")] -#[test] -fn get_health() { - let mut env = build_env(); - - let node = build_node(&mut env, testing_client_config()); - let remote_node = node.remote_node().expect("should produce remote node"); - - env.runtime() - .block_on(remote_node.http.node().get_health()) - .unwrap(); -} diff --git a/beacon_node/src/cli.rs b/beacon_node/src/cli.rs index 9f6ee79b15a..fd838e03384 100644 --- a/beacon_node/src/cli.rs +++ b/beacon_node/src/cli.rs @@ -142,7 +142,7 @@ pub fn cli_app<'a, 'b>() -> App<'a, 'b> { .arg( Arg::with_name("http") .long("http") - .help("Enable RESTful HTTP API server. Disabled by default.") + .help("Enable the RESTful HTTP API server. Disabled by default.") .takes_value(false), ) .arg( @@ -169,6 +169,38 @@ pub fn cli_app<'a, 'b>() -> App<'a, 'b> { .default_value("") .takes_value(true), ) + /* Prometheus metrics HTTP server related arguments */ + .arg( + Arg::with_name("metrics") + .long("metrics") + .help("Enable the Prometheus metrics HTTP server. Disabled by default.") + .takes_value(false), + ) + .arg( + Arg::with_name("metrics-address") + .long("metrics-address") + .value_name("ADDRESS") + .help("Set the listen address for the Prometheus metrics HTTP server.") + .default_value("127.0.0.1") + .takes_value(true), + ) + .arg( + Arg::with_name("metrics-port") + .long("metrics-port") + .value_name("PORT") + .help("Set the listen TCP port for the Prometheus metrics HTTP server.") + .default_value("5054") + .takes_value(true), + ) + .arg( + Arg::with_name("metrics-allow-origin") + .long("metrics-allow-origin") + .value_name("ORIGIN") + .help("Set the value of the Access-Control-Allow-Origin response HTTP header for the Prometheus metrics HTTP server. \ + Use * to allow any origin (not recommended in production)") + .default_value("") + .takes_value(true), + ) /* Websocket related arguments */ .arg( Arg::with_name("ws") diff --git a/beacon_node/src/config.rs b/beacon_node/src/config.rs index aabdbb35ca4..ba2dbe21a59 100644 --- a/beacon_node/src/config.rs +++ b/beacon_node/src/config.rs @@ -87,26 +87,26 @@ pub fn get_config( */ if cli_args.is_present("staking") { - client_config.rest_api.enabled = true; + client_config.http_api.enabled = true; client_config.sync_eth1_chain = true; } /* - * Http server + * Http API server */ if cli_args.is_present("http") { - client_config.rest_api.enabled = true; + client_config.http_api.enabled = true; } if let Some(address) = cli_args.value_of("http-address") { - client_config.rest_api.listen_address = address + client_config.http_api.listen_addr = address .parse::() .map_err(|_| "http-address is not a valid IPv4 address.")?; } if let Some(port) = cli_args.value_of("http-port") { - client_config.rest_api.port = port + client_config.http_api.listen_port = port .parse::() .map_err(|_| "http-port is not a valid u16.")?; } @@ -117,7 +117,36 @@ pub fn get_config( hyper::header::HeaderValue::from_str(allow_origin) .map_err(|_| "Invalid allow-origin value")?; - client_config.rest_api.allow_origin = allow_origin.to_string(); + client_config.http_api.allow_origin = Some(allow_origin.to_string()); + } + + /* + * Prometheus metrics HTTP server + */ + + if cli_args.is_present("metrics") { + client_config.http_metrics.enabled = true; + } + + if let Some(address) = cli_args.value_of("metrics-address") { + client_config.http_metrics.listen_addr = address + .parse::() + .map_err(|_| "metrics-address is not a valid IPv4 address.")?; + } + + if let Some(port) = cli_args.value_of("metrics-port") { + client_config.http_metrics.listen_port = port + .parse::() + .map_err(|_| "metrics-port is not a valid u16.")?; + } + + if let Some(allow_origin) = cli_args.value_of("metrics-allow-origin") { + // Pre-validate the config value to give feedback to the user on node startup, instead of + // as late as when the first API response is produced. + hyper::header::HeaderValue::from_str(allow_origin) + .map_err(|_| "Invalid allow-origin value")?; + + client_config.http_metrics.allow_origin = Some(allow_origin.to_string()); } // Log a warning indicating an open HTTP server if it wasn't specified explicitly @@ -125,7 +154,7 @@ pub fn get_config( if cli_args.is_present("staking") { warn!( log, - "Running HTTP server on port {}", client_config.rest_api.port + "Running HTTP server on port {}", client_config.http_api.listen_port ); } @@ -219,7 +248,8 @@ pub fn get_config( unused_port("tcp").map_err(|e| format!("Failed to get port for libp2p: {}", e))?; client_config.network.discovery_port = unused_port("udp").map_err(|e| format!("Failed to get port for discovery: {}", e))?; - client_config.rest_api.port = 0; + client_config.http_api.listen_port = 0; + client_config.http_metrics.listen_port = 0; client_config.websocket_server.port = 0; } @@ -230,6 +260,11 @@ pub fn get_config( client_config.eth1.deposit_contract_address = format!("{:?}", eth2_testnet_config.deposit_contract_address()?); + let spec_contract_address = format!("{:?}", spec.deposit_contract_address); + if client_config.eth1.deposit_contract_address != spec_contract_address { + return Err("Testnet contract address does not match spec".into()); + } + client_config.eth1.deposit_contract_deploy_block = eth2_testnet_config.deposit_contract_deploy_block; client_config.eth1.lowest_cached_block_number = @@ -265,7 +300,7 @@ pub fn get_config( }; let trimmed_graffiti_len = cmp::min(raw_graffiti.len(), GRAFFITI_BYTES_LEN); - client_config.graffiti[..trimmed_graffiti_len] + client_config.graffiti.0[..trimmed_graffiti_len] .copy_from_slice(&raw_graffiti[..trimmed_graffiti_len]); if let Some(max_skip_slots) = cli_args.value_of("max-skip-slots") { diff --git a/beacon_node/src/lib.rs b/beacon_node/src/lib.rs index a09f8c6cd32..feff1e3206f 100644 --- a/beacon_node/src/lib.rs +++ b/beacon_node/src/lib.rs @@ -71,7 +71,6 @@ impl ProductionBeaconNode { context: RuntimeContext, mut client_config: ClientConfig, ) -> Result { - let http_eth2_config = context.eth2_config().clone(); let spec = context.eth2_config().spec.clone(); let client_config_1 = client_config.clone(); let client_genesis = client_config.genesis.clone(); @@ -118,26 +117,22 @@ impl ProductionBeaconNode { builder.no_eth1_backend()? }; - let (builder, events) = builder + let (builder, _events) = builder .system_time_slot_clock()? .tee_event_handler(client_config.websocket_server.clone())?; // Inject the executor into the discv5 network config. client_config.network.discv5_config.executor = Some(Box::new(executor)); - let builder = builder + builder .build_beacon_chain()? .network(&client_config.network) .await? - .notifier()?; - - let builder = if client_config.rest_api.enabled { - builder.http_server(&client_config, &http_eth2_config, events)? - } else { - builder - }; - - Ok(Self(builder.build())) + .notifier()? + .http_api_config(client_config.http_api.clone()) + .http_metrics_config(client_config.http_metrics.clone()) + .build() + .map(Self) } pub fn into_inner(self) -> ProductionClient { diff --git a/beacon_node/tests/test.rs b/beacon_node/tests/test.rs index a845acf04df..7d860538f9b 100644 --- a/beacon_node/tests/test.rs +++ b/beacon_node/tests/test.rs @@ -3,6 +3,7 @@ use beacon_chain::StateSkipConfig; use node_test_rig::{ environment::{Environment, EnvironmentBuilder}, + eth2::types::StateId, testing_client_config, LocalBeaconNode, }; use types::{EthSpec, MinimalEthSpec, Slot}; @@ -34,10 +35,12 @@ fn http_server_genesis_state() { let node = build_node(&mut env); let remote_node = node.remote_node().expect("should produce remote node"); - let (api_state, _root) = env + let api_state = env .runtime() - .block_on(remote_node.http.beacon().get_state_by_slot(Slot::new(0))) - .expect("should fetch state from http api"); + .block_on(remote_node.get_debug_beacon_states(StateId::Slot(Slot::new(0)))) + .expect("should fetch state from http api") + .unwrap() + .data; let mut db_state = node .client diff --git a/book/src/SUMMARY.md b/book/src/SUMMARY.md index 18e0ccad246..b570357b9db 100644 --- a/book/src/SUMMARY.md +++ b/book/src/SUMMARY.md @@ -14,20 +14,15 @@ * [Key recovery](./key-recovery.md) * [Validator Management](./validator-management.md) * [Importing from the Eth2 Launchpad](./validator-import-launchpad.md) -* [Local Testnets](./local-testnets.md) -* [API](./api.md) - * [HTTP (RESTful JSON)](./http.md) - * [/node](./http/node.md) - * [/beacon](./http/beacon.md) - * [/validator](./http/validator.md) - * [/consensus](./http/consensus.md) - * [/network](./http/network.md) - * [/spec](./http/spec.md) - * [/advanced](./http/advanced.md) - * [/lighthouse](./http/lighthouse.md) - * [WebSocket](./websockets.md) +* [APIs](./api.md) + * [Beacon Node API](./api-bn.md) + * [/lighthouse](./api-lighthouse.md) + * [Validator Inclusion APIs](./validator-inclusion.md) + * [Validator Client API](./api-vc.md) + * [Prometheus Metrics](./advanced_metrics.md) * [Advanced Usage](./advanced.md) * [Database Configuration](./advanced_database.md) + * [Local Testnets](./local-testnets.md) * [Contributing](./contributing.md) * [Development Environment](./setup.md) * [FAQs](./faq.md) diff --git a/book/src/advanced_metrics.md b/book/src/advanced_metrics.md new file mode 100644 index 00000000000..6c901862ee0 --- /dev/null +++ b/book/src/advanced_metrics.md @@ -0,0 +1,34 @@ +# Prometheus Metrics + +Lighthouse provides an extensive suite of metrics and monitoring in the +[Prometheus](https://prometheus.io/docs/introduction/overview/) export format +via a HTTP server built into Lighthouse. + +These metrics are generally consumed by a Prometheus server and displayed via a +Grafana dashboard. These components are available in a docker-compose format at +[sigp/lighthouse-metrics](https://github.com/sigp/lighthouse-metrics). + +## Beacon Node Metrics + +By default, these metrics are disabled but can be enabled with the `--metrics` +flag. Use the `--metrics-address`, `--metrics-port` and +`--metrics-allow-origin` flags to customize the metrics server. + +### Example + +Start a beacon node with the metrics server enabled: + +```bash +lighthouse bn --metrics +``` + +Check to ensure that the metrics are available on the default port: + +```bash +curl localhost:5054/metrics +``` + +## Validator Client Metrics + +The validator client does not *yet* expose metrics, however this functionality +is expected to be implemented in late-September 2020. diff --git a/book/src/api-bn.md b/book/src/api-bn.md new file mode 100644 index 00000000000..d957e43768e --- /dev/null +++ b/book/src/api-bn.md @@ -0,0 +1,130 @@ +# Beacon Node API + +Lighthouse implements the standard [Eth2 Beacon Node API +specification][OpenAPI]. Please follow that link for a full description of each API endpoint. + +> **Warning:** the standard API specification is still in flux and the Lighthouse implementation is partially incomplete. You can track the status of each endpoint at [#1434](https://github.com/sigp/lighthouse/issues/1434). + +## Starting the server + +A Lighthouse beacon node can be configured to expose a HTTP server by supplying the `--http` flag. The default listen address is `127.0.0.1:5052`. + +The following CLI flags control the HTTP server: + +- `--http`: enable the HTTP server (required even if the following flags are + provided). +- `--http-port`: specify the listen port of the server. +- `--http-address`: specify the listen address of the server. +- `--http-allow-origin`: specify the value of the `Access-Control-Allow-Origin` + header. The default is to not supply a header. + +The schema of the API aligns with the standard Eth2 Beacon Node API as defined +at [github.com/ethereum/eth2.0-APIs](https://github.com/ethereum/eth2.0-APIs). +An interactive specification is available [here][OpenAPI]. + +### CLI Example + +Start the beacon node with the HTTP server listening on [http://localhost:5052](http://localhost:5052): + +```bash +lighthouse bn --http +``` + +## HTTP Request/Response Examples + +This section contains some simple examples of using the HTTP API via `curl`. +All endpoints are documented in the [Eth2 Beacon Node API +specification][OpenAPI]. + +### View the head of the beacon chain + +Returns the block header at the head of the canonical chain. + +```bash +curl -X GET "http://localhost:5052/eth/v1/beacon/headers/head" -H "accept: +application/json" +``` + +```json +{ + "data": { + "root": "0x4381454174fc28c7095077e959dcab407ae5717b5dca447e74c340c1b743d7b2", + "canonical": true, + "header": { + "message": { + "slot": 3199, + "proposer_index": "19077", + "parent_root": "0xf1934973041c5896d0d608e52847c3cd9a5f809c59c64e76f6020e3d7cd0c7cd", + "state_root": "0xe8e468f9f5961655dde91968f66480868dab8d4147de9498111df2b7e4e6fe60", + "body_root": "0x6f183abc6c4e97f832900b00d4e08d4373bfdc819055d76b0f4ff850f559b883" + }, + "signature": "0x988064a2f9cf13fe3aae051a3d85f6a4bca5a8ff6196f2f504e32f1203b549d5f86a39c6509f7113678880701b1881b50925a0417c1c88a750c8da7cd302dda5aabae4b941e3104d0cf19f5043c4f22a7d75d0d50dad5dbdaf6991381dc159ab" + } + } +} +``` + +### View the status of a validator + +Shows the status of validator at index `1` at the `head` state. + +```bash +curl -X GET "http://localhost:5052/eth/v1/beacon/states/head/validators/1" -H "accept: application/json" +``` + +```json +{ + "data": { + "index": "1", + "balance": "63985937939", + "status": "Active", + "validator": { + "pubkey": "0x873e73ee8b3e4fcf1d2fb0f1036ba996ac9910b5b348f6438b5f8ef50857d4da9075d0218a9d1b99a9eae235a39703e1", + "withdrawal_credentials": "0x00b8cdcf79ba7e74300a07e9d8f8121dd0d8dd11dcfd6d3f2807c45b426ac968", + "effective_balance": 32000000000, + "slashed": false, + "activation_eligibility_epoch": 0, + "activation_epoch": 0, + "exit_epoch": 18446744073709552000, + "withdrawable_epoch": 18446744073709552000 + } + } +} +``` + +## Troubleshooting + +### HTTP API is unavailable or refusing connections + +Ensure the `--http` flag has been supplied at the CLI. + +You can quickly check that the HTTP endpoint is up using `curl`: + +```bash +curl -X GET "http://localhost:5052/eth/v1/node/version" -H "accept: application/json" +``` + +The beacon node should respond with its version: + +```json +{"data":{"version":"Lighthouse/v0.2.9-6f7b4768a/x86_64-linux"}} +``` + +If this doesn't work, the server might not be started or there might be a +network connection error. + +### I cannot query my node from a web browser (e.g., Swagger) + +By default, the API does not provide an `Access-Control-Allow-Origin` header, +which causes browsers to reject responses with a CORS error. + +The `--http-allow-origin` flag can be used to add a wild-card CORS header: + +```bash +lighthouse bn --http --http-allow-origin "*" +``` + +> **Warning:** Adding the wild-card allow-origin flag can pose a security risk. +> Only use it in production if you understand the risks of a loose CORS policy. + +[OpenAPI]: https://ethereum.github.io/eth2.0-APIs/#/ diff --git a/book/src/api-lighthouse.md b/book/src/api-lighthouse.md new file mode 100644 index 00000000000..3f37673fa9d --- /dev/null +++ b/book/src/api-lighthouse.md @@ -0,0 +1,179 @@ +# Lighthouse Non-Standard APIs + +Lighthouse fully supports the standardization efforts at +[github.com/ethereum/eth2.0-APIs](https://github.com/ethereum/eth2.0-APIs), +however sometimes development requires additional endpoints that shouldn't +necessarily be defined as a broad-reaching standard. Such endpoints are placed +behind the `/lighthouse` path. + +The endpoints behind the `/lighthouse` path are: + +- Not intended to be stable. +- Not guaranteed to be safe. +- For testing and debugging purposes only. + +Although we don't recommend that users rely on these endpoints, we +document them briefly so they can be utilized by developers and +researchers. + +### `/lighthouse/health` + +*Presently only available on Linux.* + +```bash +curl -X GET "http://localhost:5052/lighthouse/health" -H "accept: application/json" | jq +``` + +```json +{ + "data": { + "pid": 1728254, + "pid_num_threads": 47, + "pid_mem_resident_set_size": 510054400, + "pid_mem_virtual_memory_size": 3963158528, + "sys_virt_mem_total": 16715530240, + "sys_virt_mem_available": 4065374208, + "sys_virt_mem_used": 11383402496, + "sys_virt_mem_free": 1368662016, + "sys_virt_mem_percent": 75.67906, + "sys_loadavg_1": 4.92, + "sys_loadavg_5": 5.53, + "sys_loadavg_15": 5.58 + } +} +``` + +### `/lighthouse/syncing` + +```bash +curl -X GET "http://localhost:5052/lighthouse/syncing" -H "accept: application/json" | jq +``` + +```json +{ + "data": { + "SyncingFinalized": { + "start_slot": 3104, + "head_slot": 343744, + "head_root": "0x1b434b5ed702338df53eb5e3e24336a90373bb51f74b83af42840be7421dd2bf" + } + } +} +``` + +### `/lighthouse/peers` + +```bash +curl -X GET "http://localhost:5052/lighthouse/peers" -H "accept: application/json" | jq +``` + +```json +[ + { + "peer_id": "16Uiu2HAmA9xa11dtNv2z5fFbgF9hER3yq35qYNTPvN7TdAmvjqqv", + "peer_info": { + "_status": "Healthy", + "score": { + "score": 0 + }, + "client": { + "kind": "Lighthouse", + "version": "v0.2.9-1c9a055c", + "os_version": "aarch64-linux", + "protocol_version": "lighthouse/libp2p", + "agent_string": "Lighthouse/v0.2.9-1c9a055c/aarch64-linux" + }, + "connection_status": { + "status": "disconnected", + "connections_in": 0, + "connections_out": 0, + "last_seen": 1082, + "banned_ips": [] + }, + "listening_addresses": [ + "/ip4/80.109.35.174/tcp/9000", + "/ip4/127.0.0.1/tcp/9000", + "/ip4/192.168.0.73/tcp/9000", + "/ip4/172.17.0.1/tcp/9000", + "/ip6/::1/tcp/9000" + ], + "sync_status": { + "Advanced": { + "info": { + "status_head_slot": 343829, + "status_head_root": "0xe34e43efc2bb462d9f364bc90e1f7f0094e74310fd172af698b5a94193498871", + "status_finalized_epoch": 10742, + "status_finalized_root": "0x1b434b5ed702338df53eb5e3e24336a90373bb51f74b83af42840be7421dd2bf" + } + } + }, + "meta_data": { + "seq_number": 160, + "attnets": "0x0000000800000080" + } + } + } +] +``` + +### `/lighthouse/peers/connected` + +```bash +curl -X GET "http://localhost:5052/lighthouse/peers/connected" -H "accept: application/json" | jq +``` + +```json +[ + { + "peer_id": "16Uiu2HAkzJC5TqDSKuLgVUsV4dWat9Hr8EjNZUb6nzFb61mrfqBv", + "peer_info": { + "_status": "Healthy", + "score": { + "score": 0 + }, + "client": { + "kind": "Lighthouse", + "version": "v0.2.8-87181204+", + "os_version": "x86_64-linux", + "protocol_version": "lighthouse/libp2p", + "agent_string": "Lighthouse/v0.2.8-87181204+/x86_64-linux" + }, + "connection_status": { + "status": "connected", + "connections_in": 1, + "connections_out": 0, + "last_seen": 0, + "banned_ips": [] + }, + "listening_addresses": [ + "/ip4/34.204.178.218/tcp/9000", + "/ip4/127.0.0.1/tcp/9000", + "/ip4/172.31.67.58/tcp/9000", + "/ip4/172.17.0.1/tcp/9000", + "/ip6/::1/tcp/9000" + ], + "sync_status": "Unknown", + "meta_data": { + "seq_number": 1819, + "attnets": "0xffffffffffffffff" + } + } + } +] +``` + +### `/lighthouse/proto_array` + +```bash +curl -X GET "http://localhost:5052/lighthouse/proto_array" -H "accept: application/json" | jq +``` + +*Example omitted for brevity.* + +### `/lighthouse/validator_inclusion/{epoch}/{validator_id}` + +See [Validator Inclusion APIs](./validator-inclusion.md). + +### `/lighthouse/validator_inclusion/{epoch}/global` + +See [Validator Inclusion APIs](./validator-inclusion.md). diff --git a/book/src/api-vc.md b/book/src/api-vc.md new file mode 100644 index 00000000000..e120f69bf5c --- /dev/null +++ b/book/src/api-vc.md @@ -0,0 +1,3 @@ +# Validator Client API + +The validator client API is planned for release in late September 2020. diff --git a/book/src/api.md b/book/src/api.md index 0fa6c300129..56c1ff5ce00 100644 --- a/book/src/api.md +++ b/book/src/api.md @@ -1,13 +1,9 @@ # APIs -The Lighthouse `beacon_node` provides two APIs for local consumption: +Lighthouse allows users to query the state of Eth2.0 using web-standard, +RESTful HTTP/JSON APIs. -- A [RESTful JSON HTTP API](http.html) which provides beacon chain, node and network - information. -- A read-only [WebSocket API](websockets.html) providing beacon chain events, as they occur. +There are two APIs served by Lighthouse: - -## Security - -These endpoints are not designed to be exposed to the public Internet or -untrusted users. They may pose a considerable DoS attack vector when used improperly. +- [Beacon Node API](./api-bn.md) +- [Validator Client API](./api-vc.md) (not yet released). diff --git a/book/src/http.md b/book/src/http.md index e07440e8da8..700535c2ac2 100644 --- a/book/src/http.md +++ b/book/src/http.md @@ -1,5 +1,9 @@ # HTTP API +[OpenAPI Specification](https://ethereum.github.io/eth2.0-APIs/#/) + +## Beacon Node + A Lighthouse beacon node can be configured to expose a HTTP server by supplying the `--http` flag. The default listen address is `localhost:5052`. The following CLI flags control the HTTP server: @@ -9,24 +13,10 @@ The following CLI flags control the HTTP server: - `--http-port`: specify the listen port of the server. - `--http-address`: specify the listen address of the server. -The API is logically divided into several core endpoints, each documented in -detail: - -Endpoint | Description | -| --- | -- | -[`/node`](./http/node.md) | General information about the beacon node. -[`/beacon`](./http/beacon.md) | General information about the beacon chain. -[`/validator`](./http/validator.md) | Provides functionality to validator clients. -[`/consensus`](./http/consensus.md) | Proof-of-stake voting statistics. -[`/network`](./http/network.md) | Information about the p2p network. -[`/spec`](./http/spec.md) | Information about the specs that the client is running. -[`/advanced`](./http/advanced.md) | Provides endpoints for advanced inspection of Lighthouse specific objects. -[`/lighthouse`](./http/lighthouse.md) | Provides lighthouse specific endpoints. - -_Please note: The OpenAPI format at -[SwaggerHub: Lighthouse REST -API](https://app.swaggerhub.com/apis-docs/spble/lighthouse_rest_api/0.2.0) has -been **deprecated**. This documentation is now the source of truth for the REST API._ +The schema of the API aligns with the standard Eth2 Beacon Node API as defined +at [github.com/ethereum/eth2.0-APIs](https://github.com/ethereum/eth2.0-APIs). +It is an easy-to-use RESTful HTTP/JSON API. An interactive specification is +available [here](https://ethereum.github.io/eth2.0-APIs/#/). ## Troubleshooting diff --git a/book/src/http/advanced.md b/book/src/http/advanced.md deleted file mode 100644 index 822b6ffffd6..00000000000 --- a/book/src/http/advanced.md +++ /dev/null @@ -1,115 +0,0 @@ -# Lighthouse REST API: `/advanced` - -The `/advanced` endpoints provide information Lighthouse specific data structures for advanced debugging. - -## Endpoints - -HTTP Path | Description | -| --- | -- | -[`/advanced/fork_choice`](#advancedfork_choice) | Get the `proto_array` fork choice object. -[`/advanced/operation_pool`](#advancedoperation_pool) | Get the Lighthouse `PersistedOperationPool` object. - - -## `/advanced/fork_choice` - -Requests the `proto_array` fork choice object as represented in Lighthouse. - -### HTTP Specification - -| Property | Specification | -| --- |--- | -Path | `/advanced/fork_choice` -Method | GET -JSON Encoding | Object -Query Parameters | None -Typical Responses | 200 - -### Example Response - -```json -{ - "prune_threshold": 256, - "justified_epoch": 25, - "finalized_epoch": 24, - "nodes": [ - { - "slot": 544, - "root": "0x27103c56d4427cb4309dd202920ead6381d54d43277c29cf0572ddf0d528e6ea", - "parent": null, - "justified_epoch": 16, - "finalized_epoch": 15, - "weight": 256000000000, - "best_child": 1, - "best_descendant": 296 - }, - { - "slot": 545, - "root": "0x09af0e8d4e781ea4280c9c969d168839c564fab3a03942e7db0bfbede7d4c745", - "parent": 0, - "justified_epoch": 16, - "finalized_epoch": 15, - "weight": 256000000000, - "best_child": 2, - "best_descendant": 296 - }, - ], - "indices": { - "0xb935bb3651eeddcb2d2961bf307156850de982021087062033f02576d5df00a3": 59, - "0x8f4ec47a34c6c1d69ede64d27165d195f7e2a97c711808ce51f1071a6e12d5b9": 189, - "0xf675eba701ef77ee2803a130dda89c3c5673a604d2782c9e25ea2be300d7d2da": 173, - "0x488a483c8d5083faaf5f9535c051b9f373ba60d5a16e77ddb1775f248245b281": 37 - } -} -``` -_Truncated for brevity._ - -## `/advanced/operation_pool` - -Requests the `PersistedOperationPool` object as represented in Lighthouse. - -### HTTP Specification - -| Property | Specification | -| --- |--- | -Path | `/advanced/operation_pool` -Method | GET -JSON Encoding | Object -Query Parameters | None -Typical Responses | 200 - -### Example Response - -```json -{ - "attestations": [ - [ - { - "v": [39, 3, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 112, 118, 215, 252, 51, 186, 76, 156, 157, 99, 91, 4, 137, 195, 209, 224, 26, 233, 233, 184, 38, 89, 215, 177, 247, 97, 243, 119, 229, 69, 50, 90, 24, 0, 0, 0, 0, 0, 0, 0, 79, 37, 38, 210, 96, 235, 121, 142, 129, 136, 206, 214, 179, 132, 22, 19, 222, 213, 203, 46, 112, 192, 26, 5, 254, 26, 103, 170, 158, 205, 72, 3, 25, 0, 0, 0, 0, 0, 0, 0, 164, 50, 214, 67, 98, 13, 50, 180, 108, 232, 248, 109, 128, 45, 177, 23, 221, 24, 218, 211, 8, 152, 172, 120, 24, 86, 198, 103, 68, 164, 67, 202, 1, 0, 0, 0, 0, 0, 0, 0] - }, - [ - { - "aggregation_bits": "0x03", - "data": { - "slot": 807, - "index": 0, - "beacon_block_root": "0x7076d7fc33ba4c9c9d635b0489c3d1e01ae9e9b82659d7b1f761f377e545325a", - "source": { - "epoch": 24, - "root": "0x4f2526d260eb798e8188ced6b3841613ded5cb2e70c01a05fe1a67aa9ecd4803" - }, - "target": { - "epoch": 25, - "root": "0xa432d643620d32b46ce8f86d802db117dd18dad30898ac781856c66744a443ca" - } - }, - "signature": "0x8b1d624b0cd5a7a0e13944e90826878a230e3901db34ea87dbef5b145ade2fedbc830b6752a38a0937a1594211ab85b615d65f9eef0baccd270acca945786036695f4db969d9ff1693c505c0fe568b2fe9831ea78a74cbf7c945122231f04026" - } - ] - ] - ], - "attester_slashings": [], - "proposer_slashings": [], - "voluntary_exits": [] -} -``` -_Truncated for brevity._ diff --git a/book/src/http/beacon.md b/book/src/http/beacon.md deleted file mode 100644 index 2149f444448..00000000000 --- a/book/src/http/beacon.md +++ /dev/null @@ -1,784 +0,0 @@ -# Lighthouse REST API: `/beacon` - -The `/beacon` endpoints provide information about the canonical head of the -beacon chain and also historical information about beacon blocks and states. - -## Endpoints - -HTTP Path | Description | -| --- | -- | -[`/beacon/head`](#beaconhead) | Info about the block at the head of the chain. -[`/beacon/heads`](#beaconheads) | Returns a list of all known chain heads. -[`/beacon/block`](#beaconblock) | Get a `BeaconBlock` by slot or root. -[`/beacon/block_root`](#beaconblock_root) | Resolve a slot to a block root. -[`/beacon/fork`](#beaconfork) | Get the fork of the head of the chain. -[`/beacon/genesis_time`](#beacongenesis_time) | Get the genesis time from the beacon state. -[`/beacon/genesis_validators_root`](#beacongenesis_validators_root) | Get the genesis validators root. -[`/beacon/validators`](#beaconvalidators) | Query for one or more validators. -[`/beacon/validators/all`](#beaconvalidatorsall) | Get all validators. -[`/beacon/validators/active`](#beaconvalidatorsactive) | Get all active validators. -[`/beacon/state`](#beaconstate) | Get a `BeaconState` by slot or root. -[`/beacon/state_root`](#beaconstate_root) | Resolve a slot to a state root. -[`/beacon/state/genesis`](#beaconstategenesis) | Get a `BeaconState` at genesis. -[`/beacon/committees`](#beaconcommittees) | Get the shuffling for an epoch. -[`/beacon/proposer_slashing`](#beaconproposer_slashing) | Insert a proposer slashing -[`/beacon/attester_slashing`](#beaconattester_slashing) | Insert an attester slashing - -## `/beacon/head` - -Requests information about the head of the beacon chain, from the node's -perspective. - -### HTTP Specification - -| Property | Specification | -| --- |--- | -Path | `/beacon/head` -Method | GET -JSON Encoding | Object -Query Parameters | None -Typical Responses | 200 - -### Example Response - -```json -{ - "slot": 37923, - "block_root": "0xe865d4805395a0776b8abe46d714a9e64914ab8dc5ff66624e5a1776bcc1684b", - "state_root": "0xe500e3567ab273c9a6f8a057440deff476ab236f0983da27f201ee9494a879f0", - "finalized_slot": 37856, - "finalized_block_root": "0xbdae152b62acef1e5c332697567d2b89e358628790b8273729096da670b23e86", - "justified_slot": 37888, - "justified_block_root": "0x01c2f516a407d8fdda23cad4ed4381e4ab8913d638f935a2fe9bd00d6ced5ec4", - "previous_justified_slot": 37856, - "previous_justified_block_root": "0xbdae152b62acef1e5c332697567d2b89e358628790b8273729096da670b23e86" -} -``` - -## `/beacon/heads` - -Returns the roots of all known head blocks. Only one of these roots is the -canonical head and that is decided by the fork choice algorithm. See [`/beacon/head`](#beaconhead) for the canonical head. - -### HTTP Specification - -| Property | Specification | -| --- |--- | -Path | `/beacon/heads` -Method | GET -JSON Encoding | Object -Query Parameters | None -Typical Responses | 200 - -### Example Response - -```json -[ - { - "beacon_block_root": "0x226b2fd7c5f3d31dbb21444b96dfafe715f0017cd16545ecc4ffa87229496a69", - "beacon_block_slot": 38373 - }, - { - "beacon_block_root": "0x41ed5b253c4fc841cba8a6d44acbe101866bc674c3cfa3c4e9f7388f465aa15b", - "beacon_block_slot": 38375 - } -] -``` - -## `/beacon/block` - -Request that the node return a beacon chain block that matches the provided -criteria (a block `root` or beacon chain `slot`). Only one of the parameters -should be provided as a criteria. - -### HTTP Specification - -| Property | Specification | -| --- |--- | -Path | `/beacon/block` -Method | GET -JSON Encoding | Object -Query Parameters | `slot`, `root` -Typical Responses | 200, 404 - -### Parameters - -Accepts **only one** of the following parameters: - -- `slot` (`Slot`): Query by slot number. Any block returned must be in the canonical chain (i.e., -either the head or an ancestor of the head). -- `root` (`Bytes32`): Query by tree hash root. A returned block is not required to be in the -canonical chain. - -### Returns - -Returns an object containing a single [`SignedBeaconBlock`](https://github.com/ethereum/eth2.0-specs/blob/v0.10.0/specs/phase0/beacon-chain.md#signedbeaconblock) and the block root of the inner [`BeaconBlock`](https://github.com/ethereum/eth2.0-specs/blob/v0.10.0/specs/phase0/beacon-chain.md#beaconblock). - -### Example Response - -```json -{ - "root": "0xc35ddf4e71c31774e0594bd7eb32dfe50b54dbc40abd594944254b4ec8895196", - "beacon_block": { - "message": { - "slot": 0, - "proposer_index": 14, - "parent_root": "0x0000000000000000000000000000000000000000000000000000000000000000", - "state_root": "0xf15690b6be4ed42ea1ee0741eb4bfd4619d37be8229b84b4ddd480fb028dcc8f", - "body": { - "randao_reveal": "0x000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000", - "eth1_data": { - "deposit_root": "0x0000000000000000000000000000000000000000000000000000000000000000", - "deposit_count": 0, - "block_hash": "0x0000000000000000000000000000000000000000000000000000000000000000" - }, - "graffiti": "0x0000000000000000000000000000000000000000000000000000000000000000", - "proposer_slashings": [], - "attester_slashings": [], - "attestations": [], - "deposits": [], - "voluntary_exits": [] - } - }, - "signature": "0x000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000" - } -} -``` - -## `/beacon/block_root` - -Returns the block root for the given slot in the canonical chain. If there -is a re-org, the same slot may return a different root. - -### HTTP Specification - -| Property | Specification | -| --- |--- | -Path | `/beacon/block_root` -Method | GET -JSON Encoding | Object -Query Parameters | `slot` -Typical Responses | 200, 404 - -## Parameters - -- `slot` (`Slot`): the slot to be resolved to a root. - -### Example Response - -```json -"0xc35ddf4e71c31774e0594bd7eb32dfe50b54dbc40abd594944254b4ec8895196" -``` - -## `/beacon/committees` - -Request the committees (a.k.a. "shuffling") for all slots and committee indices -in a given `epoch`. - -### HTTP Specification - -| Property | Specification | -| --- |--- | -Path | `/beacon/committees` -Method | GET -JSON Encoding | Object -Query Parameters | `epoch` -Typical Responses | 200/500 - -### Parameters - -The `epoch` (`Epoch`) query parameter is required and defines the epoch for -which the committees will be returned. All slots contained within the response will -be inside this epoch. - -### Returns - -A list of beacon committees. - -### Example Response - -```json -[ - { - "slot": 4768, - "index": 0, - "committee": [ - 1154, - 492, - 9667, - 3089, - 8987, - 1421, - 224, - 11243, - 2127, - 2329, - 188, - 482, - 486 - ] - }, - { - "slot": 4768, - "index": 1, - "committee": [ - 5929, - 8482, - 5528, - 6130, - 14343, - 9777, - 10808, - 12739, - 15234, - 12819, - 5423, - 6320, - 9991 - ] - } -] -``` - -_Truncated for brevity._ - -## `/beacon/fork` - -Request that the node return the `fork` of the current head. - -### HTTP Specification - -| Property | Specification | -| --- |--- | -Path | `/beacon/fork` -Method | GET -JSON Encoding | Object -Query Parameters | None -Typical Responses | 200 - - -### Returns - -Returns an object containing the [`Fork`](https://github.com/ethereum/eth2.0-specs/blob/v0.12.1/specs/phase0/beacon-chain.md#fork) of the current head. - -### Example Response - -```json -{ - "previous_version": "0x00000000", - "current_version": "0x00000000", - "epoch": 0 -} -``` - -## `/beacon/genesis_time` - -Request that the node return the genesis time from the beacon state. - -### HTTP Specification - -| Property | Specification | -| --- |--- | -Path | `/beacon/genesis_time` -Method | GET -JSON Encoding | Object -Query Parameters | None -Typical Responses | 200 - - -### Returns - -Returns an object containing the genesis time. - -### Example Response - -```json -1581576353 -``` - -## `/beacon/genesis_validators_root` - -Request that the node return the genesis validators root from the beacon state. - -### HTTP Specification - -| Property | Specification | -| --- |--- | -Path | `/beacon/genesis_validators_root` -Method | GET -JSON Encoding | Object -Query Parameters | None -Typical Responses | 200 - - -### Returns - -Returns an object containing the genesis validators root. - -### Example Response - -```json -0x4fbf23439a7a9b9dd91650e64e8124012dde5e2ea2940c552b86f04eb47f95de -``` - -## `/beacon/validators` - -Request that the node returns information about one or more validator public -keys. This request takes the form of a `POST` request to allow sending a large -number of pubkeys in the request. - -### HTTP Specification - -| Property | Specification | -| --- |--- | -Path | `/beacon/validators` -Method | POST -JSON Encoding | Object -Query Parameters | None -Typical Responses | 200 - -### Request Body - -Expects the following object in the POST request body: - -``` -{ - state_root: Bytes32, - pubkeys: [PublicKey] -} -``` - -The `state_root` field indicates which `BeaconState` should be used to collect -the information. The `state_root` is optional and omitting it will result in -the canonical head state being used. - - -### Returns - -Returns an object describing several aspects of the given validator. - -### Example - -### Request Body - -```json -{ - "pubkeys": [ - "0x98f87bc7c8fa10408425bbeeeb3dc387e3e0b4bd92f57775b60b39156a16f9ec80b273a64269332d97bdb7d93ae05a16", - "0x42f87bc7c8fa10408425bbeeeb3dc3874242b4bd92f57775b60b39142426f9ec80b273a64269332d97bdb7d93ae05a42" - ] -} -``` - -_Note: for demonstration purposes the second pubkey is some unknown pubkey._ - -### Response Body - -```json -[ - { - "pubkey": "0x98f87bc7c8fa10408425bbeeeb3dc387e3e0b4bd92f57775b60b39156a16f9ec80b273a64269332d97bdb7d93ae05a16", - "validator_index": 14935, - "balance": 3228885987, - "validator": { - "pubkey": "0x98f87bc7c8fa10408425bbeeeb3dc387e3e0b4bd92f57775b60b39156a16f9ec80b273a64269332d97bdb7d93ae05a16", - "withdrawal_credentials": "0x00b7bec22d5bda6b2cca1343d4f640d0e9ccc204a06a73703605c590d4c0d28e", - "effective_balance": 3200000000, - "slashed": false, - "activation_eligibility_epoch": 0, - "activation_epoch": 0, - "exit_epoch": 18446744073709551615, - "withdrawable_epoch": 18446744073709551615 - } - }, - { - "pubkey": "0x42f87bc7c8fa10408425bbeeeb3dc3874242b4bd92f57775b60b39142426f9ec80b273a64269332d97bdb7d93ae05a42", - "validator_index": null, - "balance": null, - "validator": null - } -] -``` - -## `/beacon/validators/all` - -Returns all validators. - -### HTTP Specification - -| Property | Specification | -| --- |--- | -Path | `/beacon/validators/all` -Method | GET -JSON Encoding | Object -Query Parameters | `state_root` (optional) -Typical Responses | 200 - -### Parameters - -The optional `state_root` (`Bytes32`) query parameter indicates which -`BeaconState` should be used to collect the information. When omitted, the -canonical head state will be used. - -### Returns - -The return format is identical to the [`/beacon/validators`](#beaconvalidators) response body. - - -## `/beacon/validators/active` - -Returns all validators that are active in the state defined by `state_root`. - -### HTTP Specification - -| Property | Specification | -| --- |--- | -Path | `/beacon/validators/active` -Method | GET -JSON Encoding | Object -Query Parameters | `state_root` (optional) -Typical Responses | 200 - -### Parameters - -The optional `state_root` (`Bytes32`) query parameter indicates which -`BeaconState` should be used to collect the information. When omitted, the -canonical head state will be used. - -### Returns - -The return format is identical to the [`/beacon/validators`](#beaconvalidators) response body. - - -## `/beacon/state` - -Request that the node return a beacon chain state that matches the provided -criteria (a state `root` or beacon chain `slot`). Only one of the parameters -should be provided as a criteria. - -### HTTP Specification - -| Property | Specification | -| --- |--- | -Path | `/beacon/state` -Method | GET -JSON Encoding | Object -Query Parameters | `slot`, `root` -Typical Responses | 200, 404 - -### Parameters - -Accepts **only one** of the following parameters: - -- `slot` (`Slot`): Query by slot number. Any state returned must be in the canonical chain (i.e., -either the head or an ancestor of the head). -- `root` (`Bytes32`): Query by tree hash root. A returned state is not required to be in the -canonical chain. - -### Returns - -Returns an object containing a single -[`BeaconState`](https://github.com/ethereum/eth2.0-specs/blob/v0.12.1/specs/phase0/beacon-chain.md#beaconstate) -and its tree hash root. - -### Example Response - -```json -{ - "root": "0x528e54ca5d4c957729a73f40fc513ae312e054c7295775c4a2b21f423416a72b", - "beacon_state": { - "genesis_time": 1575652800, - "genesis_validators_root": "0xa8a9226edee1b2627fb4117d7dea4996e64dec2998f37f6e824f74f2ce39a538", - "slot": 18478 - } -} -``` - -_Truncated for brevity._ - -## `/beacon/state_root` - -Returns the state root for the given slot in the canonical chain. If there -is a re-org, the same slot may return a different root. - - -### HTTP Specification - -| Property | Specification | -| --- |--- | -Path | `/beacon/state_root` -Method | GET -JSON Encoding | Object -Query Parameters | `slot` -Typical Responses | 200, 404 - -## Parameters - -- `slot` (`Slot`): the slot to be resolved to a root. - -### Example Response - -```json -"0xf15690b6be4ed42ea1ee0741eb4bfd4619d37be8229b84b4ddd480fb028dcc8f" -``` - -## `/beacon/state/genesis` - -Request that the node return a beacon chain state at genesis (slot 0). - -### HTTP Specification - -| Property | Specification | -| --- |--- | -Path | `/beacon/state/genesis` -Method | GET -JSON Encoding | Object -Query Parameters | None -Typical Responses | 200 - - -### Returns - -Returns an object containing the genesis -[`BeaconState`](https://github.com/ethereum/eth2.0-specs/blob/v0.12.1/specs/phase0/beacon-chain.md#beaconstate). - -### Example Response - -```json -{ - "genesis_time": 1581576353, - "slot": 0, - "fork": { - "previous_version": "0x00000000", - "current_version": "0x00000000", - "epoch": 0 - }, -} -``` - -_Truncated for brevity._ - - -## `/beacon/state/committees` - -Request that the node return a beacon chain state at genesis (slot 0). - -### HTTP Specification - -| Property | Specification | -| --- |--- | -Path | `/beacon/state/genesis` -Method | GET -JSON Encoding | Object -Query Parameters | `epoch` -Typical Responses | 200 - - -### Returns - -Returns an object containing the committees for a given epoch. - -### Example Response - -```json -[ - {"slot":64,"index":0,"committee":[]}, - {"slot":65,"index":0,"committee":[3]}, - {"slot":66,"index":0,"committee":[]}, - {"slot":67,"index":0,"committee":[14]}, - {"slot":68,"index":0,"committee":[]}, - {"slot":69,"index":0,"committee":[9]}, - {"slot":70,"index":0,"committee":[]}, - {"slot":71,"index":0,"committee":[11]}, - {"slot":72,"index":0,"committee":[]}, - {"slot":73,"index":0,"committee":[5]}, - {"slot":74,"index":0,"committee":[]}, - {"slot":75,"index":0,"committee":[15]}, - {"slot":76,"index":0,"committee":[]}, - {"slot":77,"index":0,"committee":[0]} -] -``` - -_Truncated for brevity._ - - -## `/beacon/attester_slashing` - -Accepts an `attester_slashing` and verifies it. If it is valid, it is added to the operations pool for potential inclusion in a future block. Returns a 400 error if the `attester_slashing` is invalid. - -### HTTP Specification - -| Property | Specification | -| --- |--- | -Path | `/beacon/attester_slashing` -Method | POST -JSON Encoding | Object -Query Parameters | None -Typical Responses | 200/400 - -### Parameters - -Expects the following object in the POST request body: - -``` -{ - attestation_1: { - attesting_indices: [u64], - data: { - slot: Slot, - index: u64, - beacon_block_root: Bytes32, - source: { - epoch: Epoch, - root: Bytes32 - }, - target: { - epoch: Epoch, - root: Bytes32 - } - } - signature: Bytes32 - }, - attestation_2: { - attesting_indices: [u64], - data: { - slot: Slot, - index: u64, - beacon_block_root: Bytes32, - source: { - epoch: Epoch, - root: Bytes32 - }, - target: { - epoch: Epoch, - root: Bytes32 - } - } - signature: Bytes32 - } -} -``` - -### Returns - -Returns `true` if the attester slashing was inserted successfully, or the corresponding error if it failed. - -### Example - -### Request Body - -```json -{ - "attestation_1": { - "attesting_indices": [0], - "data": { - "slot": 1, - "index": 0, - "beacon_block_root": "0x0000000000000000000000000000000000000000000000000100000000000000", - "source": { - "epoch": 1, - "root": "0x0000000000000000000000000000000000000000000000000100000000000000" - }, - "target": { - "epoch": 1, - "root": "0x0000000000000000000000000000000000000000000000000100000000000000" - } - }, - "signature": "0xb47f7397cd944b8d5856a13352166bbe74c85625a45b14b7347fc2c9f6f6f82acee674c65bc9ceb576fcf78387a6731c0b0eb3f8371c70db2da4e7f5dfbc451730c159d67263d3db56b6d0e009e4287a8ba3efcacac30b3ae3447e89dc71b5b9" - }, - "attestation_2": { - "attesting_indices": [0], - "data": { - "slot": 1, - "index": 0, - "beacon_block_root": "0x0000000000000000000000000000000000000000000000000100000000000000", - "source": { - "epoch": 1, - "root": "0x0000000000000000000000000000000000000000000000000100000000000000" - }, - "target": { - "epoch": 1, - "root": "0x0000000000000000000000000000000000000000000000000200000000000000" - } - }, - "signature": "0x93fef587a63acf72aaf8df627718fd43cb268035764071f802ffb4370a2969d226595cc650f4c0bf2291ae0c0a41fcac1700f318603d75d34bcb4b9f4a8368f61eeea0e1f5d969d92d5073ba5fbadec102b45ec87d418d25168d2e3c74b9fcbb" - } -} -``` - -_Note: data sent here is for demonstration purposes only_ - - - -## `/beacon/proposer_slashing` - -Accepts a `proposer_slashing` and verifies it. If it is valid, it is added to the operations pool for potential inclusion in a future block. Returns an 400 error if the `proposer_slashing` is invalid. - -### HTTP Specification - -| Property | Specification | -| --- |--- | -Path | `/beacon/proposer_slashing` -Method | POST -JSON Encoding | Object -Query Parameters | None -Typical Responses | 200/400 - -### Request Body - -Expects the following object in the POST request body: - -``` -{ - proposer_index: u64, - header_1: { - slot: Slot, - parent_root: Bytes32, - state_root: Bytes32, - body_root: Bytes32, - signature: Bytes32 - }, - header_2: { - slot: Slot, - parent_root: Bytes32, - state_root: Bytes32, - body_root: Bytes32, - signature: Bytes32 - } -} -``` - -### Returns - -Returns `true` if the proposer slashing was inserted successfully, or the corresponding error if it failed. - -### Example - -### Request Body - -```json -{ - "proposer_index": 0, - "header_1": { - "slot": 0, - "parent_root": "0x0101010101010101010101010101010101010101010101010101010101010101", - "state_root": "0x0101010101010101010101010101010101010101010101010101010101010101", - "body_root": "0x0101010101010101010101010101010101010101010101010101010101010101", - "signature": "0xb8970d1342c6d5779c700ec366efd0ca819937ca330960db3ca5a55eb370a3edd83f4cbb2f74d06e82f934fcbd4bb80609a19c2254cc8b3532a4efff9e80edf312ac735757c059d77126851e377f875593e64ba50d1dffe69a809a409202dd12" - }, - "header_2": { - "slot": 0, - "parent_root": "0x0202020202020202020202020202020202020202020202020202020202020202", - "state_root": "0x0101010101010101010101010101010101010101010101010101010101010101", - "body_root": "0x0101010101010101010101010101010101010101010101010101010101010101", - "signature": "0xb60e6b348698a34e59b22e0af96f8809f977f00f95d52375383ade8d22e9102270a66c6d52b0434214897e11ca4896871510c01b3fd74d62108a855658d5705fcfc4ced5136264a1c6496f05918576926aa191b1ad311b7e27f5aa2167aba294" - } -} -``` - -_Note: data sent here is for demonstration purposes only_ - - - - - diff --git a/book/src/http/lighthouse.md b/book/src/http/lighthouse.md deleted file mode 100644 index d80c0f694a5..00000000000 --- a/book/src/http/lighthouse.md +++ /dev/null @@ -1,182 +0,0 @@ -# Lighthouse REST API: `/lighthouse` - -The `/lighthouse` endpoints provide lighthouse-specific information about the beacon node. - -## Endpoints - -HTTP Path | Description | -| --- | -- | -[`/lighthouse/syncing`](#lighthousesyncing) | Get the node's syncing status -[`/lighthouse/peers`](#lighthousepeers) | Get the peers info known by the beacon node -[`/lighthouse/connected_peers`](#lighthousepeers) | Get the connected_peers known by the beacon node - -## `/lighthouse/syncing` - -Requests the syncing state of a Lighthouse beacon node. Lighthouse as a -custom sync protocol, this request gets Lighthouse-specific sync information. - -### HTTP Specification - -| Property | Specification | -| --- |--- | -Path | `/lighthouse/syncing` -Method | GET -JSON Encoding | Object -Query Parameters | None -Typical Responses | 200 - -### Example Response - -If the node is undergoing a finalization sync: -```json -{ - "SyncingFinalized": { - "start_slot": 10, - "head_slot": 20, - "head_root":"0x74020d0e3c3c02d2ea6279d5760f7d0dd376c4924beaaec4d5c0cefd1c0c4465" - } -} -``` - -If the node is undergoing a head chain sync: -```json -{ - "SyncingHead": { - "start_slot":0, - "head_slot":1195 - } -} -``` - -If the node is synced -```json -{ -"Synced" -} -``` - -## `/lighthouse/peers` - -Get all known peers info from the beacon node. - -### HTTP Specification - -| Property | Specification | -| --- |--- | -Path | `/lighthouse/peers` -Method | GET -JSON Encoding | Object -Query Parameters | None -Typical Responses | 200 - -### Example Response - -```json -[ -{ - "peer_id" : "16Uiu2HAmTEinipUS3haxqucrn7d7SmCKx5XzAVbAZCiNW54ncynG", - "peer_info" : { - "_status" : "Healthy", - "client" : { - "agent_string" : "github.com/libp2p/go-libp2p", - "kind" : "Prysm", - "os_version" : "unknown", - "protocol_version" : "ipfs/0.1.0", - "version" : "unknown" - }, - "connection_status" : { - "Disconnected" : { - "since" : 3 - } - }, - "listening_addresses" : [ - "/ip4/10.3.58.241/tcp/9001", - "/ip4/35.172.14.146/tcp/9001", - "/ip4/35.172.14.146/tcp/9001" - ], - "meta_data" : { - "attnets" : "0x0000000000000000", - "seq_number" : 0 - }, - "reputation" : 20, - "sync_status" : { - "Synced" : { - "status_head_slot" : 18146 - } - } - } - }, - { - "peer_id" : "16Uiu2HAm8XZfPv3YjktCjitSRtfS7UfHfEvpiUyHrdiX6uAD55xZ", - "peer_info" : { - "_status" : "Healthy", - "client" : { - "agent_string" : null, - "kind" : "Unknown", - "os_version" : "unknown", - "protocol_version" : "unknown", - "version" : "unknown" - }, - "connection_status" : { - "Disconnected" : { - "since" : 5 - } - }, - "listening_addresses" : [], - "meta_data" : { - "attnets" : "0x0900000000000000", - "seq_number" : 0 - }, - "reputation" : 20, - "sync_status" : "Unknown" - } - }, -] -``` - -## `/lighthouse/connected_peers` - -Get all known peers info from the beacon node. - -### HTTP Specification - -| Property | Specification | -| --- |--- | -Path | `/lighthouse/connected_peers` -Method | GET -JSON Encoding | Object -Query Parameters | None -Typical Responses | 200 - -### Example Response - -```json -[ - { - "peer_id" : "16Uiu2HAm8XZfPv3YjktCjitSRtfS7UfHfEvpiUyHrdiX6uAD55xZ", - "peer_info" : { - "_status" : "Healthy", - "client" : { - "agent_string" : null, - "kind" : "Unknown", - "os_version" : "unknown", - "protocol_version" : "unknown", - "version" : "unknown" - }, - "connection_status" : { - "Connected" : { - "in" : 5, - "out" : 2 - } - }, - "listening_addresses" : [], - "meta_data" : { - "attnets" : "0x0900000000000000", - "seq_number" : 0 - }, - "reputation" : 20, - "sync_status" : "Unknown" - } - }, - ] -``` diff --git a/book/src/http/network.md b/book/src/http/network.md deleted file mode 100644 index 2ac0c83ba49..00000000000 --- a/book/src/http/network.md +++ /dev/null @@ -1,148 +0,0 @@ -# Lighthouse REST API: `/network` - -The `/network` endpoints provide information about the p2p network that -Lighthouse uses to communicate with other beacon nodes. - -## Endpoints - -HTTP Path | Description | -| --- | -- | -[`/network/enr`](#networkenr) | Get the local node's `ENR` as base64 . -[`/network/peer_count`](#networkpeer_count) | Get the count of connected peers. -[`/network/peer_id`](#networkpeer_id) | Get a node's libp2p `PeerId`. -[`/network/peers`](#networkpeers) | List a node's connected peers (as `PeerIds`). -[`/network/listen_port`](#networklisten_port) | Get a node's libp2p listening port. -[`/network/listen_addresses`](#networklisten_addresses) | Get a list of libp2p multiaddr the node is listening on. - -## `network/enr` - -Requests the beacon node for its listening `ENR` address. - -### HTTP Specification - -| Property | Specification | -| --- |--- | -Path | `/network/enr` -Method | GET -JSON Encoding | String (base64) -Query Parameters | None -Typical Responses | 200 - -### Example Response - -```json -"-IW4QPYyGkXJSuJ2Eji8b-m4PTNrW4YMdBsNOBrYAdCk8NLMJcddAiQlpcv6G_hdNjiLACOPTkqTBhUjnC0wtIIhyQkEgmlwhKwqAPqDdGNwgiMog3VkcIIjKIlzZWNwMjU2azGhA1sBKo0yCfw4Z_jbggwflNfftjwKACu-a-CoFAQHJnrm" -``` - -## `/network/peer_count` - -Requests the count of peers connected to the client. - -### HTTP Specification - -| Property | Specification | -| --- |--- | -Path | `/network/peer_count` -Method | GET -JSON Encoding | Number -Query Parameters | None -Typical Responses | 200 - -### Example Response - -```json -5 -``` -## `/network/peer_id` - -Requests the beacon node's local `PeerId`. - -### HTTP Specification - -| Property | Specification | -| --- |--- | -Path | `/network/peer_id` -Method | GET -JSON Encoding | String (base58) -Query Parameters | None -Typical Responses | 200 - -### Example Response - -```json -"QmVFcULBYZecPdCKgGmpEYDqJLqvMecfhJadVBtB371Avd" -``` - -## `/network/peers` - -Requests one `MultiAddr` for each peer connected to the beacon node. - -### HTTP Specification - -| Property | Specification | -| --- |--- | -Path | `/network/peers` -Method | GET -JSON Encoding | [String] (base58) -Query Parameters | None -Typical Responses | 200 - -### Example Response - -```json -[ - "QmaPGeXcfKFMU13d8VgbnnpeTxcvoFoD9bUpnRGMUJ1L9w", - "QmZt47cP8V96MgiS35WzHKpPbKVBMqr1eoBNTLhQPqpP3m" -] -``` - - -## `/network/listen_port` - -Requests the TCP port that the client's libp2p service is listening on. - -### HTTP Specification - -| Property | Specification | -| --- |--- | -Path | `/network/listen_port` -Method | GET -JSON Encoding | Number -Query Parameters | None -Typical Responses | 200 - -### Example Response - -```json -9000 -``` - -## `/network/listen_addresses` - -Requests the list of multiaddr that the client's libp2p service is listening on. - -### HTTP Specification - -| Property | Specification | -| --- |--- | -Path | `/network/listen_addresses` -Method | GET -JSON Encoding | Array -Query Parameters | None -Typical Responses | 200 - -### Example Response - -```json -[ - "/ip4/127.0.0.1/tcp/9000", - "/ip4/192.168.31.115/tcp/9000", - "/ip4/172.24.0.1/tcp/9000", - "/ip4/172.21.0.1/tcp/9000", - "/ip4/172.17.0.1/tcp/9000", - "/ip4/172.18.0.1/tcp/9000", - "/ip4/172.19.0.1/tcp/9000", - "/ip4/172.42.0.1/tcp/9000", - "/ip6/::1/tcp/9000" -] -``` diff --git a/book/src/http/node.md b/book/src/http/node.md deleted file mode 100644 index ae370cbe981..00000000000 --- a/book/src/http/node.md +++ /dev/null @@ -1,91 +0,0 @@ -# Lighthouse REST API: `/node` - -The `/node` endpoints provide information about the lighthouse beacon node. - -## Endpoints - -HTTP Path | Description | -| --- | -- | -[`/node/version`](#nodeversion) | Get the node's version. -[`/node/syncing`](#nodesyncing) | Get the node's syncing status. -[`/node/health`](#nodehealth) | Get the node's health. - -## `/node/version` - -Requests the beacon node's version. - -### HTTP Specification - -| Property | Specification | -| --- |--- | -Path | `/node/version` -Method | GET -JSON Encoding | String -Query Parameters | None -Typical Responses | 200 - -### Example Response - -```json -"Lighthouse-0.2.0-unstable" -``` - -## `/node/syncing` - -Requests the syncing status of the beacon node. - -### HTTP Specification - -| Property | Specification | -| --- |--- | -Path | `/node/syncing` -Method | GET -JSON Encoding | Object -Query Parameters | None -Typical Responses | 200 - -### Example Response - -```json -{ - is_syncing: true, - sync_status: { - starting_slot: 0, - current_slot: 100, - highest_slot: 200, - } -} -``` - -## `/node/health` - -Requests information about the health of the beacon node. - -### HTTP Specification - -| Property | Specification | -| --- |--- | -Path | `/node/health` -Method | GET -JSON Encoding | Object -Query Parameters | None -Typical Responses | 200 - -### Example Response - -```json -{ - "pid": 96160, - "pid_num_threads": 30, - "pid_mem_resident_set_size": 55476224, - "pid_mem_virtual_memory_size": 2081382400, - "sys_virt_mem_total": 16721076224, - "sys_virt_mem_available": 7423197184, - "sys_virt_mem_used": 8450183168, - "sys_virt_mem_free": 3496345600, - "sys_virt_mem_percent": 55.605743, - "sys_loadavg_1": 1.56, - "sys_loadavg_5": 2.61, - "sys_loadavg_15": 2.43 -} -``` diff --git a/book/src/http/spec.md b/book/src/http/spec.md deleted file mode 100644 index 619a1d4e362..00000000000 --- a/book/src/http/spec.md +++ /dev/null @@ -1,154 +0,0 @@ -# Lighthouse REST API: `/spec` - -The `/spec` endpoints provide information about Eth2.0 specifications that the node is running. - -## Endpoints - -HTTP Path | Description | -| --- | -- | -[`/spec`](#spec) | Get the full spec object that a node's running. -[`/spec/slots_per_epoch`](#specslots_per_epoch) | Get the number of slots per epoch. -[`/spec/eth2_config`](#specseth2_config) | Get the full Eth2 config object. - -## `/spec` - -Requests the full spec object that a node's running. - -### HTTP Specification - -| Property | Specification | -| --- |--- | -Path | `/spec` -Method | GET -JSON Encoding | Object -Query Parameters | None -Typical Responses | 200 - -### Example Response - -```json -{ - "genesis_slot": 0, - "base_rewards_per_epoch": 4, - "deposit_contract_tree_depth": 32, - "max_committees_per_slot": 64, - "target_committee_size": 128, - "min_per_epoch_churn_limit": 4, - "churn_limit_quotient": 65536, - "shuffle_round_count": 90, - "min_genesis_active_validator_count": 16384, - "min_genesis_time": 1578009600, - "min_deposit_amount": 1000000000, - "max_effective_balance": 32000000000, - "ejection_balance": 16000000000, - "effective_balance_increment": 1000000000, - "genesis_fork_version": "0x00000000", - "bls_withdrawal_prefix_byte": "0x00", - "genesis_delay": 172800, - "milliseconds_per_slot": 12000, - "min_attestation_inclusion_delay": 1, - "min_seed_lookahead": 1, - "max_seed_lookahead": 4, - "min_epochs_to_inactivity_penalty": 4, - "min_validator_withdrawability_delay": 256, - "shard_committee_period": 2048, - "base_reward_factor": 64, - "whistleblower_reward_quotient": 512, - "proposer_reward_quotient": 8, - "inactivity_penalty_quotient": 33554432, - "min_slashing_penalty_quotient": 32, - "domain_beacon_proposer": 0, - "domain_beacon_attester": 1, - "domain_randao": 2, - "domain_deposit": 3, - "domain_voluntary_exit": 4, - "safe_slots_to_update_justified": 8, - "eth1_follow_distance": 1024, - "seconds_per_eth1_block": 14, - "boot_nodes": [], - "network_id": 1 -} -``` - -## `/spec/eth2_config` - -Requests the full `Eth2Config` object. - -### HTTP Specification - -| Property | Specification | -| --- |--- | -Path | `/spec/eth2_config` -Method | GET -JSON Encoding | Object -Query Parameters | None -Typical Responses | 200 - -### Example Response - -```json -{ - "spec_constants": "mainnet", - "spec": { - "genesis_slot": 0, - "base_rewards_per_epoch": 4, - "deposit_contract_tree_depth": 32, - "max_committees_per_slot": 64, - "target_committee_size": 128, - "min_per_epoch_churn_limit": 4, - "churn_limit_quotient": 65536, - "shuffle_round_count": 90, - "min_genesis_active_validator_count": 16384, - "min_genesis_time": 1578009600, - "min_deposit_amount": 1000000000, - "max_effective_balance": 32000000000, - "ejection_balance": 16000000000, - "effective_balance_increment": 1000000000, - "genesis_fork_version": "0x00000000", - "bls_withdrawal_prefix_byte": "0x00", - "genesis_delay": 172800, - "milliseconds_per_slot": 12000, - "min_attestation_inclusion_delay": 1, - "min_seed_lookahead": 1, - "max_seed_lookahead": 4, - "min_epochs_to_inactivity_penalty": 4, - "min_validator_withdrawability_delay": 256, - "shard_committee_period": 2048, - "base_reward_factor": 64, - "whistleblower_reward_quotient": 512, - "proposer_reward_quotient": 8, - "inactivity_penalty_quotient": 33554432, - "min_slashing_penalty_quotient": 32, - "domain_beacon_proposer": 0, - "domain_beacon_attester": 1, - "domain_randao": 2, - "domain_deposit": 3, - "domain_voluntary_exit": 4, - "safe_slots_to_update_justified": 8, - "eth1_follow_distance": 1024, - "seconds_per_eth1_block": 14, - "boot_nodes": [], - "network_id": 1 - } -} -``` - -## `/spec/slots_per_epoch` - -Requests the `SLOTS_PER_EPOCH` parameter from the specs that the node is running. - -### HTTP Specification - -| Property | Specification | -| --- |--- | -Path | `/spec/slots_per_epoch` -Method | GET -JSON Encoding | Number -Query Parameters | None -Typical Responses | 200 - -### Example Response - -```json -32 -``` \ No newline at end of file diff --git a/book/src/http/validator.md b/book/src/http/validator.md deleted file mode 100644 index eff0c609501..00000000000 --- a/book/src/http/validator.md +++ /dev/null @@ -1,545 +0,0 @@ -# Lighthouse REST API: `/validator` - -The `/validator` endpoints provide the minimum functionality required for a validator -client to connect to the beacon node and produce blocks and attestations. - -## Endpoints - -HTTP Path | HTTP Method | Description | -| - | - | ---- | -[`/validator/duties`](#validatorduties) | POST | Provides block and attestation production information for validators. -[`/validator/subscribe`](#validatorsubscribe) | POST | Subscribes a list of validators to the beacon node for a particular duty/slot. -[`/validator/duties/all`](#validatordutiesall) | GET |Provides block and attestation production information for all validators. -[`/validator/duties/active`](#validatordutiesactive) | GET | Provides block and attestation production information for all active validators. -[`/validator/block`](#validatorblock-get) | GET | Retrieves the current beacon block for the validator to publish. -[`/validator/block`](#validatorblock-post) | POST | Publishes a signed block to the network. -[`/validator/attestation`](#validatorattestation) | GET | Retrieves the current best attestation for a validator to publish. -[`/validator/aggregate_attestation`](#validatoraggregate_attestation) | GET | Gets an aggregate attestation for validators to sign and publish. -[`/validator/attestations`](#validatorattestations) | POST | Publishes a list of raw unaggregated attestations to their appropriate subnets. -[`/validator/aggregate_and_proofs`](#validatoraggregate_and_proofs) | POST | Publishes a list of Signed aggregate and proofs for validators who are aggregators. - -## `/validator/duties` - -Request information about when a validator must produce blocks and attestations -at some given `epoch`. The information returned always refers to the canonical -chain and the same input parameters may yield different results after a re-org. - -### HTTP Specification - -| Property | Specification | -| --- |--- | -Path | `/validator/duties` -Method | POST -JSON Encoding | Object -Query Parameters | None -Typical Responses | 200 - -### Request Body - -Expects the following object in the POST request body: - -``` -{ - epoch: Epoch, - pubkeys: [PublicKey] -} -``` - -Duties are assigned on a per-epoch basis, all duties returned will contain -slots that are inside the given `epoch`. A set of duties will be returned for -each of the `pubkeys`. - -Validators who are not known to the beacon chain (e.g., have not yet deposited) -will have `null` values for most fields. - - -### Returns - -A set of duties for each given pubkey. - -### Example - -#### Request Body - -```json -{ - "epoch": 1203, - "pubkeys": [ - "0x98f87bc7c8fa10408425bbeeeb3dc387e3e0b4bd92f57775b60b39156a16f9ec80b273a64269332d97bdb7d93ae05a16", - "0x42f87bc7c8fa10408425bbeeeb3dc3874242b4bd92f57775b60b39142426f9ec80b273a64269332d97bdb7d93ae05a42" - ] -} -``` - -_Note: for demonstration purposes the second pubkey is some unknown pubkey._ - -#### Response Body - -```json -[ - { - "validator_pubkey": "0x98f87bc7c8fa10408425bbeeeb3dc387e3e0b4bd92f57775b60b39156a16f9ec80b273a64269332d97bdb7d93ae05a16", - "validator_index": 14935, - "attestation_slot": 38511, - "attestation_committee_index": 3, - "attestation_committee_position": 39, - "block_proposal_slots": [], - "aggregator_modulo": 5, - }, - { - "validator_pubkey": "0x42f87bc7c8fa10408425bbeeeb3dc3874242b4bd92f57775b60b39142426f9ec80b273a64269332d97bdb7d93ae05a42", - "validator_index": null, - "attestation_slot": null, - "attestation_committee_index": null, - "attestation_committee_position": null, - "block_proposal_slots": [] - "aggregator_modulo": null, - } -] -``` - -## `/validator/duties/all` - -Returns the duties for all validators, equivalent to calling [Validator -Duties](#validator-duties) while providing all known validator public keys. - -Considering that duties for non-active validators will just be `null`, it is -generally more efficient to query using [Active Validator -Duties](#active-validator-duties). - -This endpoint will only return validators that were in the beacon state -in the given epoch. For example, if the query epoch is 10 and some validator -deposit was included in epoch 11, that validator will not be included in the -result. - -### HTTP Specification - -| Property | Specification | -| --- |--- | -Path | `/validator/duties/all` -Method | GET -JSON Encoding | Object -Query Parameters | `epoch` -Typical Responses | 200 - -### Parameters - -The duties returned will all be inside the given `epoch` (`Epoch`) query -parameter. This parameter is required. - -### Returns - -The return format is identical to the [Validator Duties](#validator-duties) response body. - -## `/validator/duties/active` - -Returns the duties for all active validators, equivalent to calling [Validator -Duties](#validator-duties) while providing all known validator public keys that -are active in the given epoch. - -This endpoint will only return validators that were in the beacon state -in the given epoch. For example, if the query epoch is 10 and some validator -deposit was included in epoch 11, that validator will not be included in the -result. - -### HTTP Specification - -| Property | Specification | -| --- |--- | -Path | `/validator/duties/active` -Method | GET -JSON Encoding | Object -Query Parameters | `epoch` -Typical Responses | 200 - -### Parameters - -The duties returned will all be inside the given `epoch` (`Epoch`) query -parameter. This parameter is required. - -### Returns - -The return format is identical to the [Validator Duties](#validator-duties) response body. - -## `/validator/subscribe` - -Posts a list of `ValidatorSubscription` to subscribe validators to -particular slots to perform attestation duties. - -This informs the beacon node to search for peers and subscribe to -required attestation subnets to perform the attestation duties required. - -### HTTP Specification - -| Property | Specification | -| --- |--- | -Path | `/validator/subscribe` -Method | POST -JSON Encoding | Object -Query Parameters | None -Typical Responses | 200 - -### Request Body - -Expects the following object in the POST request body: - -``` -[ - { - validator_index: 10, - attestation_committee_index: 12, - slot: 3, - is_aggregator: true - } -] -``` - -The `is_aggregator` informs the beacon node if the validator is an aggregator -for this slot/committee. - -### Returns - -A null object on success and an error indicating any failures. - -## `/validator/block` GET - - -Produces and returns an unsigned `BeaconBlock` object. - -The block will be produced with the given `slot` and the parent block will be the -highest block in the canonical chain that has a slot less than `slot`. The -block will still be produced if some other block is also known to be at `slot` -(i.e., it may produce a block that would be slashable if signed). - -### HTTP Specification - -| Property | Specification | -| --- |--- | -Path | `/validator/block` -Method | GET -JSON Encoding | Object -Query Parameters | `slot`, `randao_reveal` -Typical Responses | 200 - -### Parameters - - -- `slot` (`Slot`): The slot number for which the block is to be produced. -- `randao_reveal` (`Signature`): 96 bytes `Signature` for the randomness. - - -### Returns - -Returns a `BeaconBlock` object. - -#### Response Body - -```json -{ - "slot": 33, - "parent_root": "0xf54de54bd33e33aee4706cffff4bd991bcbf522f2551ab007180479c63f4fe912", - "state_root": "0x615c887bad27bc05754d627d941e1730e1b4c77b2eb4378c195ac8a8203bbf26", - "body": { - "randao_reveal": "0x8d7b2a32b026e9c79aae6ec6b83eabae89d60cacd65ac41ed7d2f4be9dd8c89c1bf7cd3d700374e18d03d12f6a054c23006f64f0e4e8b7cf37d6ac9a4c7d815c858120c54673b7d3cb2bb1550a4d659eaf46e34515677c678b70d6f62dbf89f", - "eth1_data": { - "deposit_root": "0x66687aadf862bd776c8fc18b8e9f8e20089714856ee233b3902a591d0d5f2925", - "deposit_count": 8, - "block_hash": "0x2b32db6c2c0a6235fb1397e8225ea85e0f0e6e8c7b126d0016ccbde0e667151e" - }, - "graffiti": "0x736967702f6c69676874686f7573652d302e312e312d7076572656c65617365", - "proposer_slashings": [], - "attester_slashings": [], - "attestations": [], - "deposits": [], - "voluntary_exits": [] - } -} -``` - -## `/validator/block` POST - -Accepts a `SignedBeaconBlock` for verification. If it is valid, it will be -imported into the local database and published on the network. Invalid blocks -will not be published to the network. - -A block may be considered invalid because it is fundamentally incorrect, or its -parent has not yet been imported. - -### HTTP Specification - -| Property | Specification | -| --- |--- | -Path | `/validator/block` -Method | POST -JSON Encoding | Object -Query Parameters | None -Typical Responses | 200/202 - - -### Request Body - -Expects a JSON encoded `SignedBeaconBlock` in the POST request body: - -### Returns - -Returns a null object if the block passed all block validation and is published to the network. -Else, returns a processing error description. - -### Example - -### Request Body - -```json -{ - "message": { - "slot": 33, - "parent_root": "0xf54de54bd33e33aee4706cffff4bd991bcbf522f2551ab007180479c63f4fe912", - "state_root": "0x615c887bad27bc05754d627d941e1730e1b4c77b2eb4378c195ac8a8203bbf26", - "body": { - "randao_reveal": "0x8d7b2a32b026e9c79aae6ec6b83eabae89d60cacd65ac41ed7d2f4be9dd8c89c1bf7cd3d700374e18d03d12f6a054c23006f64f0e4e8b7cf37d6ac9a4c7d815c858120c54673b7d3cb2bb1550a4d659eaf46e34515677c678b70d6f62dbf89f", - "eth1_data": { - "deposit_root": "0x66687aadf862bd776c8fc18b8e9f8e20089714856ee233b3902a591d0d5f2925", - "deposit_count": 8, - "block_hash": "0x2b32db6c2c0a6235fb1397e8225ea85e0f0e6e8c7b126d0016ccbde0e667151e" - }, - "graffiti": "0x736967702f6c69676874686f7573652d302e312e312d7076572656c65617365", - "proposer_slashings": [ - - ], - "attester_slashings": [ - - ], - "attestations": [ - - ], - "deposits": [ - - ], - "voluntary_exits": [ - - ] - } - }, - "signature": "0x965ced900dbabd0a78b81a0abb5d03407be0d38762104316416347f2ea6f82652b5759396f402e85df8ee18ba2c60145037c73b1c335f4272f1751a1cd89862b7b4937c035e350d0108554bd4a8930437ec3311c801a65fe8e5ba022689b5c24" -} -``` - -## `/validator/attestation` - -Produces and returns an unsigned `Attestation` from the current state. - -The attestation will reference the `beacon_block_root` of the highest block in -the canonical chain with a slot equal to or less than the given `slot`. - -An error will be returned if the given slot is more than -`SLOTS_PER_HISTORICAL_VECTOR` slots behind the current head block. - -This endpoint is not protected against slashing. Signing the returned -attestation may result in a slashable offence. - -### HTTP Specification - -| Property | Specification | -| --- |--- | -Path | `/validator/attestation` -Method | GET -JSON Encoding | Object -Query Parameters | `slot`, `committee_index` -Typical Responses | 200 - -### Parameters - - -- `slot` (`Slot`): The slot number for which the attestation is to be produced. -- `committee_index` (`CommitteeIndex`): The index of the committee that makes the attestation. - - -### Returns - -Returns a `Attestation` object with a default signature. The `signature` field should be replaced by the valid signature. - -#### Response Body - -```json -{ - "aggregation_bits": "0x01", - "data": { - "slot": 100, - "index": 0, - "beacon_block_root": "0xf22e4ec281136d119eabcd4d9d248aeacd042eb63d8d7642f73ad3e71f1c9283", - "source": { - "epoch": 2, - "root": "0x34c1244535c923f08e7f83170d41a076e4f1ec61013846b3a615a1d109d3c329" - }, - "target": { - "epoch": 3, - "root": "0xaefd23b384994dc0c1a6b77836bdb2f24f209ebfe6c4819324d9685f4a43b4e1" - } - }, - "signature": "0x000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000" -} -``` - - - -## `/validator/aggregate_attestation` - -Requests an `AggregateAttestation` from the beacon node that has a -specific `attestation.data`. If no aggregate attestation is known this will -return a null object. - -### HTTP Specification - -| Property | Specification | -| --- |--- | -Path | `/validator/aggregate_attestation` -Method | GET -JSON Encoding | Object -Query Parameters | `attestation_data` -Typical Responses | 200 - -### Returns - -Returns a null object if the attestation data passed is not known to the beacon -node. - -### Example - -### Request Body - -```json -{ - "aggregation_bits": "0x03", - "data": { - "slot": 3, - "index": 0, - "beacon_block_root": "0x0b6a1f7a9baa38d00ef079ba861b7587662565ca2502fb9901741c1feb8bb3c9", - "source": { - "epoch": 0, - "root": "0x0000000000000000000000000000000000000000000000000000000000000000" - }, - "target": { - "epoch": 0, - "root": "0xad2c360ab8c8523db278a7d7ced22f3810800f2fdc282defb6db216689d376bd" - } - }, - "signature": "0xb76a1768c18615b5ade91a92e7d2ed0294f7e088e56e30fbe7e3aa6799c443b11bccadd578ca2cbd95d395ab689b9e4d03c88a56641791ab38dfa95dc1f4d24d1b19b9d36c96c20147ad03$649bd3c6c7e8a39cf2ffb99e07b4964d52854559f" -} -``` - - -## `/validator/attestations` - -Accepts a list of `Attestation` for verification. If they are valid, they will be imported -into the local database and published to the network. Invalid attestations will -not be published to the network. - -An attestation may be considered invalid because it is fundamentally incorrect -or because the beacon node has not imported the relevant blocks required to -verify it. - -### HTTP Specification - -| Property | Specification | -| --- |--- | -Path | `/validator/attestations` -Method | POST -JSON Encoding | Object -Query Parameters | None -Typical Responses | 200/202 - - -### Request Body - -Expects a JSON encoded list of signed `Attestation` objects in the POST request body. In -accordance with the naive aggregation scheme, the attestation _must_ have -exactly one of the `attestation.aggregation_bits` fields set. - -### Returns - -Returns a null object if the attestation passed all validation and is published to the network. -Else, returns a processing error description. - -### Example - -### Request Body - -```json -{ - "aggregation_bits": "0x03", - "data": { - "slot": 3, - "index": 0, - "beacon_block_root": "0x0b6a1f7a9baa38d00ef079ba861b7587662565ca2502fb9901741c1feb8bb3c9", - "source": { - "epoch": 0, - "root": "0x0000000000000000000000000000000000000000000000000000000000000000" - }, - "target": { - "epoch": 0, - "root": "0xad2c360ab8c8523db278a7d7ced22f3810800f2fdc282defb6db216689d376bd" - } - }, - "signature": "0xb76a1768c18615b5ade91a92e7d2ed0294f7e088e56e30fbe7e3aa6799c443b11bccadd578ca2cbd95d395ab689b9e4d03c88a56641791ab38dfa95dc1f4d24d1b19b9d36c96c20147ad03$649bd3c6c7e8a39cf2ffb99e07b4964d52854559f" -} -``` - -## `/validator/aggregate_and_proofs` - -Accepts a list of `SignedAggregateAndProof` for publication. If they are valid -(the validator is an aggregator and the signatures can be verified) these -are published to the network on the global aggregate gossip topic. - -### HTTP Specification - -| Property | Specification | -| --- |--- | -Path | `/validator/aggregate_and_proofs` -Method | POST -JSON Encoding | Object -Query Parameters | None -Typical Responses | 200/202 - -### Request Body - -Expects a JSON encoded list of `SignedAggregateAndProof` objects in the POST request body. - -### Returns - -Returns a null object if the attestation passed all validation and is published to the network. -Else, returns a processing error description. - -### Example - -### Request Body - -```json -[ - { - "message": { - "aggregator_index": 12, - "aggregate": { - "aggregation_bits": "0x03", - "data": { - "slot": 3, - "index": 0, - "beacon_block_root": "0x0b6a1f7a9baa38d00ef079ba861b7587662565ca2502fb9901741c1feb8bb3c9", - "source": { - "epoch": 0, - "root": "0x0000000000000000000000000000000000000000000000000000000000000000" - }, - "target": { - "epoch": 0, - "root": "0xad2c360ab8c8523db278a7d7ced22f3810800f2fdc282defb6db216689d376bd" - } - }, - "signature": "0xb76a1768c18615b5ade91a92e7d2ed0294f7e088e56e30fbe7e3aa6799c443b11bccadd578ca2cbd95d395ab689b9e4d03c88a56641791ab38dfa95dc1f4d24d1b19b9d36c96c20147ad03649bd3c6c7e8a39cf2ffb99e07b4964d52854559f" - }, - "selection_proof": "0xb76a1768c18615b5ade91a92e7d2ed0294f7e088e56e30fbe7e3aa6799c443b11bccadd578ca2cbd95d395ab689b9e4d03c88a56641791ab38dfa95dc1f4d24d1b19b9d36c96c20147ad03649bd3c6c7e8a39cf2ffb99e07b4964d52854559f" - } - signature: "0xb76a1768c18615b5ade91a92e7d2ed0294f7e088e56e30fbe7e3aa6799c443b11bccadd578ca2cbd95d395ab689b9e4d03c88a56641791ab38dfa95dc1f4d24d1b19b9d36c96c20147ad03649bd3c6c7e8a39cf2ffb99e07b4964d52854559f" - } -] -``` -_Note: The data in this request is for demonstrating types and does not -contain real data_ diff --git a/book/src/http/consensus.md b/book/src/validator-inclusion.md similarity index 52% rename from book/src/http/consensus.md rename to book/src/validator-inclusion.md index c71b78ce3e9..ce8e61cafee 100644 --- a/book/src/http/consensus.md +++ b/book/src/validator-inclusion.md @@ -1,16 +1,21 @@ -# Lighthouse REST API: `/consensus` +# Validator Inclusion APIs -The `/consensus` endpoints provide information on results of the proof-of-stake -voting process used for finality/justification under Casper FFG. +The `/lighthouse/validator_inclusion` API endpoints provide information on +results of the proof-of-stake voting process used for finality/justification +under Casper FFG. + +These endpoints are not stable or included in the Eth2 standard API. As such, +they are subject to change or removal without a change in major release +version. ## Endpoints HTTP Path | Description | | --- | -- | -[`/consensus/global_votes`](#consensusglobal_votes) | A global vote count for a given epoch. -[`/consensus/individual_votes`](#consensusindividual_votes) | A per-validator breakdown of votes in a given epoch. +[`/lighthouse/validator_inclusion/{epoch}/global`](#global) | A global vote count for a given epoch. +[`/lighthouse/validator_inclusion/{epoch}/{validator_id}`](#individual) | A per-validator breakdown of votes in a given epoch. -## `/consensus/global_votes` +## Global Returns a global count of votes for some given `epoch`. The results are included both for the current and previous (`epoch - 1`) epochs since both are required @@ -75,40 +80,27 @@ voting upon the previous epoch included in a block. When this value is greater than or equal to `2/3` it is possible that the beacon chain may justify and/or finalize the epoch. -### HTTP Specification - -| Property | Specification | -| --- |--- | -Path | `/consensus/global_votes` -Method | GET -JSON Encoding | Object -Query Parameters | `epoch` -Typical Responses | 200 - -### Parameters - -Requires the `epoch` (`Epoch`) query parameter to determine which epoch will be -considered the current epoch. - -### Returns - -A report on global validator voting participation. +### HTTP Example -### Example +```bash +curl -X GET "http://localhost:5052/lighthouse/validator_inclusion/0/global" -H "accept: application/json" | jq +``` ```json { - "current_epoch_active_gwei": 52377600000000, - "previous_epoch_active_gwei": 52377600000000, - "current_epoch_attesting_gwei": 50740900000000, - "current_epoch_target_attesting_gwei": 49526000000000, - "previous_epoch_attesting_gwei": 52377600000000, - "previous_epoch_target_attesting_gwei": 51063400000000, - "previous_epoch_head_attesting_gwei": 9248600000000 + "data": { + "current_epoch_active_gwei": 642688000000000, + "previous_epoch_active_gwei": 642688000000000, + "current_epoch_attesting_gwei": 366208000000000, + "current_epoch_target_attesting_gwei": 366208000000000, + "previous_epoch_attesting_gwei": 1000000000, + "previous_epoch_target_attesting_gwei": 1000000000, + "previous_epoch_head_attesting_gwei": 1000000000 + } } ``` -## `/consensus/individual_votes` +## Individual Returns a per-validator summary of how that validator performed during the current epoch. @@ -117,73 +109,26 @@ The [Global Votes](#consensusglobal_votes) endpoint is the summation of all of t individual values, please see it for definitions of terms like "current_epoch", "previous_epoch" and "target_attester". -### HTTP Specification - -| Property | Specification | -| --- |--- | -Path | `/consensus/individual_votes` -Method | POST -JSON Encoding | Object -Query Parameters | None -Typical Responses | 200 - -### Request Body -Expects the following object in the POST request body: +### HTTP Example +```bash +curl -X GET "http://localhost:5052/lighthouse/validator_inclusion/0/42" -H "accept: application/json" | jq ``` -{ - epoch: Epoch, - pubkeys: [PublicKey] -} -``` - -### Returns - -A report on the validators voting participation. - -### Example - -#### Request Body ```json { - "epoch": 1203, - "pubkeys": [ - "0x98f87bc7c8fa10408425bbeeeb3dc387e3e0b4bd92f57775b60b39156a16f9ec80b273a64269332d97bdb7d93ae05a16", - "0x42f87bc7c8fa10408425bbeeeb3dc3874242b4bd92f57775b60b39142426f9ec80b273a64269332d97bdb7d93ae05a42" - ] + "data": { + "is_slashed": false, + "is_withdrawable_in_current_epoch": false, + "is_active_in_current_epoch": true, + "is_active_in_previous_epoch": true, + "current_epoch_effective_balance_gwei": 32000000000, + "is_current_epoch_attester": false, + "is_current_epoch_target_attester": false, + "is_previous_epoch_attester": false, + "is_previous_epoch_target_attester": false, + "is_previous_epoch_head_attester": false + } } ``` - -_Note: for demonstration purposes the second pubkey is some unknown pubkey._ - -#### Response Body - -```json -[ - { - "epoch": 1203, - "pubkey": "0x98f87bc7c8fa10408425bbeeeb3dc387e3e0b4bd92f57775b60b39156a16f9ec80b273a64269332d97bdb7d93ae05a16", - "validator_index": 14935, - "vote": { - "is_slashed": false, - "is_withdrawable_in_current_epoch": false, - "is_active_in_current_epoch": true, - "is_active_in_previous_epoch": true, - "current_epoch_effective_balance_gwei": 3200000000, - "is_current_epoch_attester": true, - "is_current_epoch_target_attester": true, - "is_previous_epoch_attester": true, - "is_previous_epoch_target_attester": true, - "is_previous_epoch_head_attester": false - } - }, - { - "epoch": 1203, - "pubkey": "0x42f87bc7c8fa10408425bbeeeb3dc3874242b4bd92f57775b60b39142426f9ec80b273a64269332d97bdb7d93ae05a42", - "validator_index": null, - "vote": null - } -] -``` diff --git a/book/src/websockets.md b/book/src/websockets.md deleted file mode 100644 index 69cf0e18d69..00000000000 --- a/book/src/websockets.md +++ /dev/null @@ -1,111 +0,0 @@ -# Websocket API - -**Note: the WebSocket server _only_ emits events. It does not accept any -requests. Use the [HTTP API](./http.md) for requests.** - -By default, a Lighthouse `beacon_node` exposes a websocket server on `localhost:5053`. - -The following CLI flags control the websocket server: - -- `--no-ws`: disable the websocket server. -- `--ws-port`: specify the listen port of the server. -- `--ws-address`: specify the listen address of the server. - -All clients connected to the websocket server will receive the same stream of events, all triggered -by the `BeaconChain`. Each event is a JSON object with the following schema: - -```json -{ - "event": "string", - "data": "object" -} -``` - -## Events - -The following events may be emitted: - -### Beacon Head Changed - -Occurs whenever the canonical head of the beacon chain changes. - -```json -{ - "event": "beacon_head_changed", - "data": { - "reorg": "boolean", - "current_head_beacon_block_root": "string", - "previous_head_beacon_block_root": "string" - } -} -``` - -### Beacon Finalization - -Occurs whenever the finalized checkpoint of the canonical head changes. - -```json -{ - "event": "beacon_finalization", - "data": { - "epoch": "number", - "root": "string" - } -} -``` - -### Beacon Block Imported - -Occurs whenever the beacon node imports a valid block. - -```json -{ - "event": "beacon_block_imported", - "data": { - "block": "object" - } -} -``` - -### Beacon Block Rejected - -Occurs whenever the beacon node rejects a block because it is invalid or an -error occurred during validation. - -```json -{ - "event": "beacon_block_rejected", - "data": { - "reason": "string", - "block": "object" - } -} -``` - -### Beacon Attestation Imported - -Occurs whenever the beacon node imports a valid attestation. - -```json -{ - "event": "beacon_attestation_imported", - "data": { - "attestation": "object" - } -} -``` - -### Beacon Attestation Rejected - -Occurs whenever the beacon node rejects an attestation because it is invalid or -an error occurred during validation. - -```json -{ - "event": "beacon_attestation_rejected", - "data": { - "reason": "string", - "attestation": "object" - } -} -``` diff --git a/common/eth2/Cargo.toml b/common/eth2/Cargo.toml new file mode 100644 index 00000000000..f7ccfcf34eb --- /dev/null +++ b/common/eth2/Cargo.toml @@ -0,0 +1,25 @@ +[package] +name = "eth2" +version = "0.1.0" +authors = ["Paul Hauner "] +edition = "2018" + +# See more keys and their definitions at https://doc.rust-lang.org/cargo/reference/manifest.html + +[dependencies] +serde = { version = "1.0.110", features = ["derive"] } +serde_json = "1.0.52" +types = { path = "../../consensus/types" } +hex = "0.4.2" +reqwest = { version = "0.10.8", features = ["json"] } +eth2_libp2p = { path = "../../beacon_node/eth2_libp2p" } +proto_array = { path = "../../consensus/proto_array", optional = true } +serde_utils = { path = "../../consensus/serde_utils" } + +[target.'cfg(target_os = "linux")'.dependencies] +psutil = { version = "3.1.0", optional = true } +procinfo = { version = "0.4.2", optional = true } + +[features] +default = ["lighthouse"] +lighthouse = ["proto_array", "psutil", "procinfo"] diff --git a/common/eth2/src/lib.rs b/common/eth2/src/lib.rs new file mode 100644 index 00000000000..b0fbc2566b1 --- /dev/null +++ b/common/eth2/src/lib.rs @@ -0,0 +1,784 @@ +//! This crate provides two major things: +//! +//! 1. The types served by the `http_api` crate. +//! 2. A wrapper around `reqwest` that forms a HTTP client, able of consuming the endpoints served +//! by the `http_api` crate. +//! +//! Eventually it would be ideal to publish this crate on crates.io, however we have some local +//! dependencies preventing this presently. + +#[cfg(feature = "lighthouse")] +pub mod lighthouse; +pub mod types; + +use self::types::*; +use reqwest::{IntoUrl, Response}; +use serde::{de::DeserializeOwned, Serialize}; +use std::convert::TryFrom; +use std::fmt; + +pub use reqwest; +pub use reqwest::{StatusCode, Url}; + +#[derive(Debug)] +pub enum Error { + /// The `reqwest` client raised an error. + Reqwest(reqwest::Error), + /// The server returned an error message where the body was able to be parsed. + ServerMessage(ErrorMessage), + /// The server returned an error message where the body was unable to be parsed. + StatusCode(StatusCode), + /// The supplied URL is badly formatted. It should look something like `http://127.0.0.1:5052`. + InvalidUrl(Url), +} + +impl Error { + /// If the error has a HTTP status code, return it. + pub fn status(&self) -> Option { + match self { + Error::Reqwest(error) => error.status(), + Error::ServerMessage(msg) => StatusCode::try_from(msg.code).ok(), + Error::StatusCode(status) => Some(*status), + Error::InvalidUrl(_) => None, + } + } +} + +impl fmt::Display for Error { + fn fmt(&self, f: &mut fmt::Formatter<'_>) -> fmt::Result { + write!(f, "{:?}", self) + } +} + +/// A wrapper around `reqwest::Client` which provides convenience methods for interfacing with a +/// Lighthouse Beacon Node HTTP server (`http_api`). +#[derive(Clone)] +pub struct BeaconNodeHttpClient { + client: reqwest::Client, + server: Url, +} + +impl BeaconNodeHttpClient { + pub fn new(server: Url) -> Self { + Self { + client: reqwest::Client::new(), + server, + } + } + + pub fn from_components(server: Url, client: reqwest::Client) -> Self { + Self { client, server } + } + + /// Return the path with the standard `/eth1/v1` prefix applied. + fn eth_path(&self) -> Result { + let mut path = self.server.clone(); + + path.path_segments_mut() + .map_err(|()| Error::InvalidUrl(self.server.clone()))? + .push("eth") + .push("v1"); + + Ok(path) + } + + /// Perform a HTTP GET request. + async fn get(&self, url: U) -> Result { + let response = self.client.get(url).send().await.map_err(Error::Reqwest)?; + ok_or_error(response) + .await? + .json() + .await + .map_err(Error::Reqwest) + } + + /// Perform a HTTP GET request, returning `None` on a 404 error. + async fn get_opt(&self, url: U) -> Result, Error> { + let response = self.client.get(url).send().await.map_err(Error::Reqwest)?; + match ok_or_error(response).await { + Ok(resp) => resp.json().await.map(Option::Some).map_err(Error::Reqwest), + Err(err) => { + if err.status() == Some(StatusCode::NOT_FOUND) { + Ok(None) + } else { + Err(err) + } + } + } + } + + /// Perform a HTTP POST request. + async fn post(&self, url: U, body: &T) -> Result<(), Error> { + let response = self + .client + .post(url) + .json(body) + .send() + .await + .map_err(Error::Reqwest)?; + ok_or_error(response).await?; + Ok(()) + } + + /// `GET beacon/genesis` + /// + /// ## Errors + /// + /// May return a `404` if beacon chain genesis has not yet occurred. + pub async fn get_beacon_genesis(&self) -> Result, Error> { + let mut path = self.eth_path()?; + + path.path_segments_mut() + .map_err(|()| Error::InvalidUrl(self.server.clone()))? + .push("beacon") + .push("genesis"); + + self.get(path).await + } + + /// `GET beacon/states/{state_id}/root` + /// + /// Returns `Ok(None)` on a 404 error. + pub async fn get_beacon_states_root( + &self, + state_id: StateId, + ) -> Result>, Error> { + let mut path = self.eth_path()?; + + path.path_segments_mut() + .map_err(|()| Error::InvalidUrl(self.server.clone()))? + .push("beacon") + .push("states") + .push(&state_id.to_string()) + .push("root"); + + self.get_opt(path).await + } + + /// `GET beacon/states/{state_id}/fork` + /// + /// Returns `Ok(None)` on a 404 error. + pub async fn get_beacon_states_fork( + &self, + state_id: StateId, + ) -> Result>, Error> { + let mut path = self.eth_path()?; + + path.path_segments_mut() + .map_err(|()| Error::InvalidUrl(self.server.clone()))? + .push("beacon") + .push("states") + .push(&state_id.to_string()) + .push("fork"); + + self.get_opt(path).await + } + + /// `GET beacon/states/{state_id}/finality_checkpoints` + /// + /// Returns `Ok(None)` on a 404 error. + pub async fn get_beacon_states_finality_checkpoints( + &self, + state_id: StateId, + ) -> Result>, Error> { + let mut path = self.eth_path()?; + + path.path_segments_mut() + .map_err(|()| Error::InvalidUrl(self.server.clone()))? + .push("beacon") + .push("states") + .push(&state_id.to_string()) + .push("finality_checkpoints"); + + self.get_opt(path).await + } + + /// `GET beacon/states/{state_id}/validators` + /// + /// Returns `Ok(None)` on a 404 error. + pub async fn get_beacon_states_validators( + &self, + state_id: StateId, + ) -> Result>>, Error> { + let mut path = self.eth_path()?; + + path.path_segments_mut() + .map_err(|()| Error::InvalidUrl(self.server.clone()))? + .push("beacon") + .push("states") + .push(&state_id.to_string()) + .push("validators"); + + self.get_opt(path).await + } + + /// `GET beacon/states/{state_id}/committees?slot,index` + /// + /// Returns `Ok(None)` on a 404 error. + pub async fn get_beacon_states_committees( + &self, + state_id: StateId, + epoch: Epoch, + slot: Option, + index: Option, + ) -> Result>>, Error> { + let mut path = self.eth_path()?; + + path.path_segments_mut() + .map_err(|()| Error::InvalidUrl(self.server.clone()))? + .push("beacon") + .push("states") + .push(&state_id.to_string()) + .push("committees") + .push(&epoch.to_string()); + + if let Some(slot) = slot { + path.query_pairs_mut() + .append_pair("slot", &slot.to_string()); + } + + if let Some(index) = index { + path.query_pairs_mut() + .append_pair("index", &index.to_string()); + } + + self.get_opt(path).await + } + + /// `GET beacon/states/{state_id}/validators/{validator_id}` + /// + /// Returns `Ok(None)` on a 404 error. + pub async fn get_beacon_states_validator_id( + &self, + state_id: StateId, + validator_id: &ValidatorId, + ) -> Result>, Error> { + let mut path = self.eth_path()?; + + path.path_segments_mut() + .map_err(|()| Error::InvalidUrl(self.server.clone()))? + .push("beacon") + .push("states") + .push(&state_id.to_string()) + .push("validators") + .push(&validator_id.to_string()); + + self.get_opt(path).await + } + + /// `GET beacon/headers?slot,parent_root` + /// + /// Returns `Ok(None)` on a 404 error. + pub async fn get_beacon_headers( + &self, + slot: Option, + parent_root: Option, + ) -> Result>>, Error> { + let mut path = self.eth_path()?; + + path.path_segments_mut() + .map_err(|()| Error::InvalidUrl(self.server.clone()))? + .push("beacon") + .push("headers"); + + if let Some(slot) = slot { + path.query_pairs_mut() + .append_pair("slot", &slot.to_string()); + } + + if let Some(root) = parent_root { + path.query_pairs_mut() + .append_pair("parent_root", &format!("{:?}", root)); + } + + self.get_opt(path).await + } + + /// `GET beacon/headers/{block_id}` + /// + /// Returns `Ok(None)` on a 404 error. + pub async fn get_beacon_headers_block_id( + &self, + block_id: BlockId, + ) -> Result>, Error> { + let mut path = self.eth_path()?; + + path.path_segments_mut() + .map_err(|()| Error::InvalidUrl(self.server.clone()))? + .push("beacon") + .push("headers") + .push(&block_id.to_string()); + + self.get_opt(path).await + } + + /// `POST beacon/blocks` + /// + /// Returns `Ok(None)` on a 404 error. + pub async fn post_beacon_blocks( + &self, + block: &SignedBeaconBlock, + ) -> Result<(), Error> { + let mut path = self.eth_path()?; + + path.path_segments_mut() + .map_err(|()| Error::InvalidUrl(self.server.clone()))? + .push("beacon") + .push("blocks"); + + self.post(path, block).await?; + + Ok(()) + } + + /// `GET beacon/blocks` + /// + /// Returns `Ok(None)` on a 404 error. + pub async fn get_beacon_blocks( + &self, + block_id: BlockId, + ) -> Result>>, Error> { + let mut path = self.eth_path()?; + + path.path_segments_mut() + .map_err(|()| Error::InvalidUrl(self.server.clone()))? + .push("beacon") + .push("blocks") + .push(&block_id.to_string()); + + self.get_opt(path).await + } + + /// `GET beacon/blocks/{block_id}/root` + /// + /// Returns `Ok(None)` on a 404 error. + pub async fn get_beacon_blocks_root( + &self, + block_id: BlockId, + ) -> Result>, Error> { + let mut path = self.eth_path()?; + + path.path_segments_mut() + .map_err(|()| Error::InvalidUrl(self.server.clone()))? + .push("beacon") + .push("blocks") + .push(&block_id.to_string()) + .push("root"); + + self.get_opt(path).await + } + + /// `GET beacon/blocks/{block_id}/attestations` + /// + /// Returns `Ok(None)` on a 404 error. + pub async fn get_beacon_blocks_attestations( + &self, + block_id: BlockId, + ) -> Result>>>, Error> { + let mut path = self.eth_path()?; + + path.path_segments_mut() + .map_err(|()| Error::InvalidUrl(self.server.clone()))? + .push("beacon") + .push("blocks") + .push(&block_id.to_string()) + .push("attestations"); + + self.get_opt(path).await + } + + /// `POST beacon/pool/attestations` + pub async fn post_beacon_pool_attestations( + &self, + attestation: &Attestation, + ) -> Result<(), Error> { + let mut path = self.eth_path()?; + + path.path_segments_mut() + .map_err(|()| Error::InvalidUrl(self.server.clone()))? + .push("beacon") + .push("pool") + .push("attestations"); + + self.post(path, attestation).await?; + + Ok(()) + } + + /// `GET beacon/pool/attestations` + pub async fn get_beacon_pool_attestations( + &self, + ) -> Result>>, Error> { + let mut path = self.eth_path()?; + + path.path_segments_mut() + .map_err(|()| Error::InvalidUrl(self.server.clone()))? + .push("beacon") + .push("pool") + .push("attestations"); + + self.get(path).await + } + + /// `POST beacon/pool/attester_slashings` + pub async fn post_beacon_pool_attester_slashings( + &self, + slashing: &AttesterSlashing, + ) -> Result<(), Error> { + let mut path = self.eth_path()?; + + path.path_segments_mut() + .map_err(|()| Error::InvalidUrl(self.server.clone()))? + .push("beacon") + .push("pool") + .push("attester_slashings"); + + self.post(path, slashing).await?; + + Ok(()) + } + + /// `GET beacon/pool/attester_slashings` + pub async fn get_beacon_pool_attester_slashings( + &self, + ) -> Result>>, Error> { + let mut path = self.eth_path()?; + + path.path_segments_mut() + .map_err(|()| Error::InvalidUrl(self.server.clone()))? + .push("beacon") + .push("pool") + .push("attester_slashings"); + + self.get(path).await + } + + /// `POST beacon/pool/proposer_slashings` + pub async fn post_beacon_pool_proposer_slashings( + &self, + slashing: &ProposerSlashing, + ) -> Result<(), Error> { + let mut path = self.eth_path()?; + + path.path_segments_mut() + .map_err(|()| Error::InvalidUrl(self.server.clone()))? + .push("beacon") + .push("pool") + .push("proposer_slashings"); + + self.post(path, slashing).await?; + + Ok(()) + } + + /// `GET beacon/pool/proposer_slashings` + pub async fn get_beacon_pool_proposer_slashings( + &self, + ) -> Result>, Error> { + let mut path = self.eth_path()?; + + path.path_segments_mut() + .map_err(|()| Error::InvalidUrl(self.server.clone()))? + .push("beacon") + .push("pool") + .push("proposer_slashings"); + + self.get(path).await + } + + /// `POST beacon/pool/voluntary_exits` + pub async fn post_beacon_pool_voluntary_exits( + &self, + exit: &SignedVoluntaryExit, + ) -> Result<(), Error> { + let mut path = self.eth_path()?; + + path.path_segments_mut() + .map_err(|()| Error::InvalidUrl(self.server.clone()))? + .push("beacon") + .push("pool") + .push("voluntary_exits"); + + self.post(path, exit).await?; + + Ok(()) + } + + /// `GET beacon/pool/voluntary_exits` + pub async fn get_beacon_pool_voluntary_exits( + &self, + ) -> Result>, Error> { + let mut path = self.eth_path()?; + + path.path_segments_mut() + .map_err(|()| Error::InvalidUrl(self.server.clone()))? + .push("beacon") + .push("pool") + .push("voluntary_exits"); + + self.get(path).await + } + + /// `GET config/fork_schedule` + pub async fn get_config_fork_schedule(&self) -> Result>, Error> { + let mut path = self.eth_path()?; + + path.path_segments_mut() + .map_err(|()| Error::InvalidUrl(self.server.clone()))? + .push("config") + .push("fork_schedule"); + + self.get(path).await + } + + /// `GET config/fork_schedule` + pub async fn get_config_spec(&self) -> Result, Error> { + let mut path = self.eth_path()?; + + path.path_segments_mut() + .map_err(|()| Error::InvalidUrl(self.server.clone()))? + .push("config") + .push("spec"); + + self.get(path).await + } + + /// `GET config/deposit_contract` + pub async fn get_config_deposit_contract( + &self, + ) -> Result, Error> { + let mut path = self.eth_path()?; + + path.path_segments_mut() + .map_err(|()| Error::InvalidUrl(self.server.clone()))? + .push("config") + .push("deposit_contract"); + + self.get(path).await + } + + /// `GET node/version` + pub async fn get_node_version(&self) -> Result, Error> { + let mut path = self.eth_path()?; + + path.path_segments_mut() + .map_err(|()| Error::InvalidUrl(self.server.clone()))? + .push("node") + .push("version"); + + self.get(path).await + } + + /// `GET node/syncing` + pub async fn get_node_syncing(&self) -> Result, Error> { + let mut path = self.eth_path()?; + + path.path_segments_mut() + .map_err(|()| Error::InvalidUrl(self.server.clone()))? + .push("node") + .push("syncing"); + + self.get(path).await + } + + /// `GET debug/beacon/states/{state_id}` + pub async fn get_debug_beacon_states( + &self, + state_id: StateId, + ) -> Result>>, Error> { + let mut path = self.eth_path()?; + + path.path_segments_mut() + .map_err(|()| Error::InvalidUrl(self.server.clone()))? + .push("debug") + .push("beacon") + .push("states") + .push(&state_id.to_string()); + + self.get_opt(path).await + } + + /// `GET debug/beacon/heads` + pub async fn get_debug_beacon_heads( + &self, + ) -> Result>, Error> { + let mut path = self.eth_path()?; + + path.path_segments_mut() + .map_err(|()| Error::InvalidUrl(self.server.clone()))? + .push("debug") + .push("beacon") + .push("heads"); + + self.get(path).await + } + + /// `GET validator/duties/attester/{epoch}?index` + /// + /// ## Note + /// + /// The `index` query parameter accepts a list of validator indices. + pub async fn get_validator_duties_attester( + &self, + epoch: Epoch, + index: Option<&[u64]>, + ) -> Result>, Error> { + let mut path = self.eth_path()?; + + path.path_segments_mut() + .map_err(|()| Error::InvalidUrl(self.server.clone()))? + .push("validator") + .push("duties") + .push("attester") + .push(&epoch.to_string()); + + if let Some(index) = index { + let string = index + .iter() + .map(|i| i.to_string()) + .collect::>() + .join(","); + path.query_pairs_mut().append_pair("index", &string); + } + + self.get(path).await + } + + /// `GET validator/duties/proposer/{epoch}` + pub async fn get_validator_duties_proposer( + &self, + epoch: Epoch, + ) -> Result>, Error> { + let mut path = self.eth_path()?; + + path.path_segments_mut() + .map_err(|()| Error::InvalidUrl(self.server.clone()))? + .push("validator") + .push("duties") + .push("proposer") + .push(&epoch.to_string()); + + self.get(path).await + } + + /// `GET validator/duties/attester/{epoch}?index` + /// + /// ## Note + /// + /// The `index` query parameter accepts a list of validator indices. + pub async fn get_validator_blocks( + &self, + slot: Slot, + randao_reveal: SignatureBytes, + graffiti: Option<&Graffiti>, + ) -> Result>, Error> { + let mut path = self.eth_path()?; + + path.path_segments_mut() + .map_err(|()| Error::InvalidUrl(self.server.clone()))? + .push("validator") + .push("blocks") + .push(&slot.to_string()); + + path.query_pairs_mut() + .append_pair("randao_reveal", &randao_reveal.to_string()); + + if let Some(graffiti) = graffiti { + path.query_pairs_mut() + .append_pair("graffiti", &graffiti.to_string()); + } + + self.get(path).await + } + + /// `GET validator/attestation_data?slot,committee_index` + pub async fn get_validator_attestation_data( + &self, + slot: Slot, + committee_index: CommitteeIndex, + ) -> Result, Error> { + let mut path = self.eth_path()?; + + path.path_segments_mut() + .map_err(|()| Error::InvalidUrl(self.server.clone()))? + .push("validator") + .push("attestation_data"); + + path.query_pairs_mut() + .append_pair("slot", &slot.to_string()) + .append_pair("committee_index", &committee_index.to_string()); + + self.get(path).await + } + + /// `GET validator/attestation_attestation?slot,attestation_data_root` + pub async fn get_validator_aggregate_attestation( + &self, + slot: Slot, + attestation_data_root: Hash256, + ) -> Result>>, Error> { + let mut path = self.eth_path()?; + + path.path_segments_mut() + .map_err(|()| Error::InvalidUrl(self.server.clone()))? + .push("validator") + .push("aggregate_attestation"); + + path.query_pairs_mut() + .append_pair("slot", &slot.to_string()) + .append_pair( + "attestation_data_root", + &format!("{:?}", attestation_data_root), + ); + + self.get_opt(path).await + } + + /// `POST validator/aggregate_and_proofs` + pub async fn post_validator_aggregate_and_proof( + &self, + aggregate: &SignedAggregateAndProof, + ) -> Result<(), Error> { + let mut path = self.eth_path()?; + + path.path_segments_mut() + .map_err(|()| Error::InvalidUrl(self.server.clone()))? + .push("validator") + .push("aggregate_and_proofs"); + + self.post(path, aggregate).await?; + + Ok(()) + } + + /// `POST validator/beacon_committee_subscriptions` + pub async fn post_validator_beacon_committee_subscriptions( + &self, + subscriptions: &[BeaconCommitteeSubscription], + ) -> Result<(), Error> { + let mut path = self.eth_path()?; + + path.path_segments_mut() + .map_err(|()| Error::InvalidUrl(self.server.clone()))? + .push("validator") + .push("beacon_committee_subscriptions"); + + self.post(path, &subscriptions).await?; + + Ok(()) + } +} + +/// Returns `Ok(response)` if the response is a `200 OK` response. Otherwise, creates an +/// appropriate error message. +async fn ok_or_error(response: Response) -> Result { + let status = response.status(); + + if status == StatusCode::OK { + Ok(response) + } else if let Ok(message) = response.json().await { + Err(Error::ServerMessage(message)) + } else { + Err(Error::StatusCode(status)) + } +} diff --git a/common/eth2/src/lighthouse.rs b/common/eth2/src/lighthouse.rs new file mode 100644 index 00000000000..8bfbad84ecf --- /dev/null +++ b/common/eth2/src/lighthouse.rs @@ -0,0 +1,224 @@ +//! This module contains endpoints that are non-standard and only available on Lighthouse servers. + +use crate::{ + types::{Epoch, EthSpec, GenericResponse, ValidatorId}, + BeaconNodeHttpClient, Error, +}; +use proto_array::core::ProtoArray; +use serde::{Deserialize, Serialize}; + +pub use eth2_libp2p::{types::SyncState, PeerInfo}; + +/// Information returned by `peers` and `connected_peers`. +// TODO: this should be deserializable.. +#[derive(Debug, Clone, Serialize)] +#[serde(bound = "T: EthSpec")] +pub struct Peer { + /// The Peer's ID + pub peer_id: String, + /// The PeerInfo associated with the peer. + pub peer_info: PeerInfo, +} + +/// The results of validators voting during an epoch. +/// +/// Provides information about the current and previous epochs. +#[derive(Debug, Clone, PartialEq, Serialize, Deserialize)] +pub struct GlobalValidatorInclusionData { + /// The total effective balance of all active validators during the _current_ epoch. + pub current_epoch_active_gwei: u64, + /// The total effective balance of all active validators during the _previous_ epoch. + pub previous_epoch_active_gwei: u64, + /// The total effective balance of all validators who attested during the _current_ epoch. + pub current_epoch_attesting_gwei: u64, + /// The total effective balance of all validators who attested during the _current_ epoch and + /// agreed with the state about the beacon block at the first slot of the _current_ epoch. + pub current_epoch_target_attesting_gwei: u64, + /// The total effective balance of all validators who attested during the _previous_ epoch. + pub previous_epoch_attesting_gwei: u64, + /// The total effective balance of all validators who attested during the _previous_ epoch and + /// agreed with the state about the beacon block at the first slot of the _previous_ epoch. + pub previous_epoch_target_attesting_gwei: u64, + /// The total effective balance of all validators who attested during the _previous_ epoch and + /// agreed with the state about the beacon block at the time of attestation. + pub previous_epoch_head_attesting_gwei: u64, +} + +#[derive(Debug, Clone, PartialEq, Serialize, Deserialize)] +pub struct ValidatorInclusionData { + /// True if the validator has been slashed, ever. + pub is_slashed: bool, + /// True if the validator can withdraw in the current epoch. + pub is_withdrawable_in_current_epoch: bool, + /// True if the validator was active in the state's _current_ epoch. + pub is_active_in_current_epoch: bool, + /// True if the validator was active in the state's _previous_ epoch. + pub is_active_in_previous_epoch: bool, + /// The validator's effective balance in the _current_ epoch. + pub current_epoch_effective_balance_gwei: u64, + /// True if the validator had an attestation included in the _current_ epoch. + pub is_current_epoch_attester: bool, + /// True if the validator's beacon block root attestation for the first slot of the _current_ + /// epoch matches the block root known to the state. + pub is_current_epoch_target_attester: bool, + /// True if the validator had an attestation included in the _previous_ epoch. + pub is_previous_epoch_attester: bool, + /// True if the validator's beacon block root attestation for the first slot of the _previous_ + /// epoch matches the block root known to the state. + pub is_previous_epoch_target_attester: bool, + /// True if the validator's beacon block root attestation in the _previous_ epoch at the + /// attestation's slot (`attestation_data.slot`) matches the block root known to the state. + pub is_previous_epoch_head_attester: bool, +} + +#[cfg(target_os = "linux")] +use {procinfo::pid, psutil::process::Process}; + +/// Reports on the health of the Lighthouse instance. +#[derive(Clone, Debug, PartialEq, Serialize, Deserialize)] +pub struct Health { + /// The pid of this process. + pub pid: u32, + /// The number of threads used by this pid. + pub pid_num_threads: i32, + /// The total resident memory used by this pid. + pub pid_mem_resident_set_size: u64, + /// The total virtual memory used by this pid. + pub pid_mem_virtual_memory_size: u64, + /// Total virtual memory on the system + pub sys_virt_mem_total: u64, + /// Total virtual memory available for new processes. + pub sys_virt_mem_available: u64, + /// Total virtual memory used on the system + pub sys_virt_mem_used: u64, + /// Total virtual memory not used on the system + pub sys_virt_mem_free: u64, + /// Percentage of virtual memory used on the system + pub sys_virt_mem_percent: f32, + /// System load average over 1 minute. + pub sys_loadavg_1: f64, + /// System load average over 5 minutes. + pub sys_loadavg_5: f64, + /// System load average over 15 minutes. + pub sys_loadavg_15: f64, +} + +impl Health { + #[cfg(not(target_os = "linux"))] + pub fn observe() -> Result { + Err("Health is only available on Linux".into()) + } + + #[cfg(target_os = "linux")] + pub fn observe() -> Result { + let process = + Process::current().map_err(|e| format!("Unable to get current process: {:?}", e))?; + + let process_mem = process + .memory_info() + .map_err(|e| format!("Unable to get process memory info: {:?}", e))?; + + let stat = pid::stat_self().map_err(|e| format!("Unable to get stat: {:?}", e))?; + + let vm = psutil::memory::virtual_memory() + .map_err(|e| format!("Unable to get virtual memory: {:?}", e))?; + let loadavg = + psutil::host::loadavg().map_err(|e| format!("Unable to get loadavg: {:?}", e))?; + + Ok(Self { + pid: process.pid(), + pid_num_threads: stat.num_threads, + pid_mem_resident_set_size: process_mem.rss(), + pid_mem_virtual_memory_size: process_mem.vms(), + sys_virt_mem_total: vm.total(), + sys_virt_mem_available: vm.available(), + sys_virt_mem_used: vm.used(), + sys_virt_mem_free: vm.free(), + sys_virt_mem_percent: vm.percent(), + sys_loadavg_1: loadavg.one, + sys_loadavg_5: loadavg.five, + sys_loadavg_15: loadavg.fifteen, + }) + } +} + +impl BeaconNodeHttpClient { + /// `GET lighthouse/health` + pub async fn get_lighthouse_health(&self) -> Result, Error> { + let mut path = self.server.clone(); + + path.path_segments_mut() + .map_err(|()| Error::InvalidUrl(self.server.clone()))? + .push("lighthouse") + .push("health"); + + self.get(path).await + } + + /// `GET lighthouse/syncing` + pub async fn get_lighthouse_syncing(&self) -> Result, Error> { + let mut path = self.server.clone(); + + path.path_segments_mut() + .map_err(|()| Error::InvalidUrl(self.server.clone()))? + .push("lighthouse") + .push("syncing"); + + self.get(path).await + } + + /* + * Note: + * + * The `lighthouse/peers` endpoints do not have functions here. We are yet to implement + * `Deserialize` on the `PeerInfo` struct since it contains use of `Instant`. This could be + * fairly simply achieved, if desired. + */ + + /// `GET lighthouse/proto_array` + pub async fn get_lighthouse_proto_array(&self) -> Result, Error> { + let mut path = self.server.clone(); + + path.path_segments_mut() + .map_err(|()| Error::InvalidUrl(self.server.clone()))? + .push("lighthouse") + .push("proto_array"); + + self.get(path).await + } + + /// `GET lighthouse/validator_inclusion/{epoch}/global` + pub async fn get_lighthouse_validator_inclusion_global( + &self, + epoch: Epoch, + ) -> Result, Error> { + let mut path = self.server.clone(); + + path.path_segments_mut() + .map_err(|()| Error::InvalidUrl(self.server.clone()))? + .push("lighthouse") + .push("validator_inclusion") + .push(&epoch.to_string()) + .push("global"); + + self.get(path).await + } + + /// `GET lighthouse/validator_inclusion/{epoch}/{validator_id}` + pub async fn get_lighthouse_validator_inclusion( + &self, + epoch: Epoch, + validator_id: ValidatorId, + ) -> Result>, Error> { + let mut path = self.server.clone(); + + path.path_segments_mut() + .map_err(|()| Error::InvalidUrl(self.server.clone()))? + .push("lighthouse") + .push("validator_inclusion") + .push(&epoch.to_string()) + .push(&validator_id.to_string()); + + self.get(path).await + } +} diff --git a/common/eth2/src/types.rs b/common/eth2/src/types.rs new file mode 100644 index 00000000000..c3a8d240c23 --- /dev/null +++ b/common/eth2/src/types.rs @@ -0,0 +1,432 @@ +//! This module exposes a superset of the `types` crate. It adds additional types that are only +//! required for the HTTP API. + +use eth2_libp2p::{Enr, Multiaddr}; +use serde::{Deserialize, Serialize}; +use std::convert::TryFrom; +use std::fmt; +use std::str::FromStr; + +pub use types::*; + +/// An API error serializable to JSON. +#[derive(Debug, Clone, PartialEq, Serialize, Deserialize)] +pub struct ErrorMessage { + pub code: u16, + pub message: String, + #[serde(default)] + pub stacktraces: Vec, +} + +#[derive(Debug, Clone, PartialEq, Serialize, Deserialize)] +pub struct GenesisData { + #[serde(with = "serde_utils::quoted_u64")] + pub genesis_time: u64, + pub genesis_validators_root: Hash256, + #[serde(with = "serde_utils::bytes_4_hex")] + pub genesis_fork_version: [u8; 4], +} + +#[derive(Debug, Copy, Clone, PartialEq)] +pub enum BlockId { + Head, + Genesis, + Finalized, + Justified, + Slot(Slot), + Root(Hash256), +} + +impl FromStr for BlockId { + type Err = String; + + fn from_str(s: &str) -> Result { + match s { + "head" => Ok(BlockId::Head), + "genesis" => Ok(BlockId::Genesis), + "finalized" => Ok(BlockId::Finalized), + "justified" => Ok(BlockId::Justified), + other => { + if other.starts_with("0x") { + Hash256::from_str(&s[2..]) + .map(BlockId::Root) + .map_err(|e| format!("{} cannot be parsed as a root", e)) + } else { + u64::from_str(s) + .map(Slot::new) + .map(BlockId::Slot) + .map_err(|_| format!("{} cannot be parsed as a parameter", s)) + } + } + } + } +} + +impl fmt::Display for BlockId { + fn fmt(&self, f: &mut fmt::Formatter<'_>) -> fmt::Result { + match self { + BlockId::Head => write!(f, "head"), + BlockId::Genesis => write!(f, "genesis"), + BlockId::Finalized => write!(f, "finalized"), + BlockId::Justified => write!(f, "justified"), + BlockId::Slot(slot) => write!(f, "{}", slot), + BlockId::Root(root) => write!(f, "{:?}", root), + } + } +} + +#[derive(Debug, Copy, Clone, PartialEq)] +pub enum StateId { + Head, + Genesis, + Finalized, + Justified, + Slot(Slot), + Root(Hash256), +} + +impl FromStr for StateId { + type Err = String; + + fn from_str(s: &str) -> Result { + match s { + "head" => Ok(StateId::Head), + "genesis" => Ok(StateId::Genesis), + "finalized" => Ok(StateId::Finalized), + "justified" => Ok(StateId::Justified), + other => { + if other.starts_with("0x") { + Hash256::from_str(&s[2..]) + .map(StateId::Root) + .map_err(|e| format!("{} cannot be parsed as a root", e)) + } else { + u64::from_str(s) + .map(Slot::new) + .map(StateId::Slot) + .map_err(|_| format!("{} cannot be parsed as a slot", s)) + } + } + } + } +} + +impl fmt::Display for StateId { + fn fmt(&self, f: &mut fmt::Formatter<'_>) -> fmt::Result { + match self { + StateId::Head => write!(f, "head"), + StateId::Genesis => write!(f, "genesis"), + StateId::Finalized => write!(f, "finalized"), + StateId::Justified => write!(f, "justified"), + StateId::Slot(slot) => write!(f, "{}", slot), + StateId::Root(root) => write!(f, "{:?}", root), + } + } +} + +#[derive(Debug, PartialEq, Clone, Serialize, Deserialize)] +#[serde(bound = "T: Serialize + serde::de::DeserializeOwned")] +pub struct GenericResponse { + pub data: T, +} + +impl From for GenericResponse { + fn from(data: T) -> Self { + Self { data } + } +} + +#[derive(Debug, PartialEq, Clone, Serialize)] +#[serde(bound = "T: Serialize")] +pub struct GenericResponseRef<'a, T: Serialize> { + pub data: &'a T, +} + +impl<'a, T: Serialize> From<&'a T> for GenericResponseRef<'a, T> { + fn from(data: &'a T) -> Self { + Self { data } + } +} + +#[derive(Debug, Clone, Copy, PartialEq, Serialize, Deserialize)] +pub struct RootData { + pub root: Hash256, +} + +impl From for RootData { + fn from(root: Hash256) -> Self { + Self { root } + } +} + +#[derive(Debug, Clone, PartialEq, Serialize, Deserialize)] +pub struct FinalityCheckpointsData { + pub previous_justified: Checkpoint, + pub current_justified: Checkpoint, + pub finalized: Checkpoint, +} + +#[derive(Debug, Clone, PartialEq)] +pub enum ValidatorId { + PublicKey(PublicKeyBytes), + Index(u64), +} + +impl FromStr for ValidatorId { + type Err = String; + + fn from_str(s: &str) -> Result { + if s.starts_with("0x") { + PublicKeyBytes::from_str(s) + .map(ValidatorId::PublicKey) + .map_err(|e| format!("{} cannot be parsed as a public key: {}", s, e)) + } else { + u64::from_str(s) + .map(ValidatorId::Index) + .map_err(|e| format!("{} cannot be parsed as a slot: {}", s, e)) + } + } +} + +impl fmt::Display for ValidatorId { + fn fmt(&self, f: &mut fmt::Formatter<'_>) -> fmt::Result { + match self { + ValidatorId::PublicKey(pubkey) => write!(f, "{:?}", pubkey), + ValidatorId::Index(index) => write!(f, "{}", index), + } + } +} + +#[derive(Debug, Clone, PartialEq, Serialize, Deserialize)] +pub struct ValidatorData { + #[serde(with = "serde_utils::quoted_u64")] + pub index: u64, + #[serde(with = "serde_utils::quoted_u64")] + pub balance: u64, + pub status: ValidatorStatus, + pub validator: Validator, +} + +// TODO: This does not currently match the spec, but I'm going to try and change the spec using +// this proposal: +// +// https://hackmd.io/bQxMDRt1RbS1TLno8K4NPg?view +#[derive(Debug, Clone, Copy, PartialEq, Serialize, Deserialize)] +pub enum ValidatorStatus { + Unknown, + WaitingForEligibility, + WaitingForFinality, + WaitingInQueue, + StandbyForActive(Epoch), + Active, + ActiveAwaitingVoluntaryExit(Epoch), + ActiveAwaitingSlashedExit(Epoch), + ExitedVoluntarily(Epoch), + ExitedSlashed(Epoch), + Withdrawable, + Withdrawn, +} + +impl ValidatorStatus { + pub fn from_validator( + validator_opt: Option<&Validator>, + epoch: Epoch, + finalized_epoch: Epoch, + far_future_epoch: Epoch, + ) -> Self { + if let Some(validator) = validator_opt { + if validator.is_withdrawable_at(epoch) { + ValidatorStatus::Withdrawable + } else if validator.is_exited_at(epoch) { + if validator.slashed { + ValidatorStatus::ExitedSlashed(validator.withdrawable_epoch) + } else { + ValidatorStatus::ExitedVoluntarily(validator.withdrawable_epoch) + } + } else if validator.is_active_at(epoch) { + if validator.exit_epoch < far_future_epoch { + if validator.slashed { + ValidatorStatus::ActiveAwaitingSlashedExit(validator.exit_epoch) + } else { + ValidatorStatus::ActiveAwaitingVoluntaryExit(validator.exit_epoch) + } + } else { + ValidatorStatus::Active + } + } else if validator.activation_epoch < far_future_epoch { + ValidatorStatus::StandbyForActive(validator.activation_epoch) + } else if validator.activation_eligibility_epoch < far_future_epoch { + if finalized_epoch < validator.activation_eligibility_epoch { + ValidatorStatus::WaitingForFinality + } else { + ValidatorStatus::WaitingInQueue + } + } else { + ValidatorStatus::WaitingForEligibility + } + } else { + ValidatorStatus::Unknown + } + } +} + +#[derive(Serialize, Deserialize)] +pub struct CommitteesQuery { + pub slot: Option, + pub index: Option, +} + +#[derive(Debug, Clone, PartialEq, Serialize, Deserialize)] +pub struct CommitteeData { + #[serde(with = "serde_utils::quoted_u64")] + pub index: u64, + pub slot: Slot, + #[serde(with = "serde_utils::quoted_u64_vec")] + pub validators: Vec, +} + +#[derive(Serialize, Deserialize)] +pub struct HeadersQuery { + pub slot: Option, + pub parent_root: Option, +} + +#[derive(Debug, Clone, PartialEq, Serialize, Deserialize)] +pub struct BlockHeaderAndSignature { + pub message: BeaconBlockHeader, + pub signature: SignatureBytes, +} + +#[derive(Debug, Clone, PartialEq, Serialize, Deserialize)] +pub struct BlockHeaderData { + pub root: Hash256, + pub canonical: bool, + pub header: BlockHeaderAndSignature, +} + +#[derive(Debug, Clone, PartialEq, Serialize, Deserialize)] +pub struct DepositContractData { + #[serde(with = "serde_utils::quoted_u64")] + pub chain_id: u64, + pub address: Address, +} + +#[derive(Debug, Clone, PartialEq, Serialize, Deserialize)] +pub struct ChainHeadData { + pub slot: Slot, + pub root: Hash256, +} + +#[derive(Debug, Clone, PartialEq, Serialize, Deserialize)] +pub struct IdentityData { + pub peer_id: String, + pub enr: Enr, + pub p2p_addresses: Vec, + // TODO: missing the following fields: + // + // - discovery_addresses + // - metadata + // + // Tracked here: https://github.com/sigp/lighthouse/issues/1434 +} + +#[derive(Debug, Clone, PartialEq, Serialize, Deserialize)] +pub struct VersionData { + pub version: String, +} + +#[derive(Debug, Clone, PartialEq, Serialize, Deserialize)] +pub struct SyncingData { + pub is_syncing: bool, + pub head_slot: Slot, + pub sync_distance: Slot, +} + +#[derive(Clone, PartialEq, Debug, Deserialize)] +#[serde(try_from = "String", bound = "T: FromStr")] +pub struct QueryVec(pub Vec); + +impl TryFrom for QueryVec { + type Error = String; + + fn try_from(string: String) -> Result { + if string == "" { + return Ok(Self(vec![])); + } + + string + .split(',') + .map(|s| s.parse().map_err(|_| "unable to parse".to_string())) + .collect::, String>>() + .map(Self) + } +} + +#[derive(Clone, Deserialize)] +pub struct ValidatorDutiesQuery { + pub index: Option>, +} + +#[derive(Debug, Clone, PartialEq, Serialize, Deserialize)] +pub struct AttesterData { + pub pubkey: PublicKeyBytes, + #[serde(with = "serde_utils::quoted_u64")] + pub validator_index: u64, + #[serde(with = "serde_utils::quoted_u64")] + pub committees_at_slot: u64, + #[serde(with = "serde_utils::quoted_u64")] + pub committee_index: CommitteeIndex, + #[serde(with = "serde_utils::quoted_u64")] + pub committee_length: u64, + #[serde(with = "serde_utils::quoted_u64")] + pub validator_committee_index: u64, + pub slot: Slot, +} + +#[derive(Debug, Clone, PartialEq, Serialize, Deserialize)] +pub struct ProposerData { + pub pubkey: PublicKeyBytes, + pub slot: Slot, +} + +#[derive(Clone, Serialize, Deserialize)] +pub struct ValidatorBlocksQuery { + pub randao_reveal: SignatureBytes, + pub graffiti: Option, +} + +#[derive(Clone, Serialize, Deserialize)] +pub struct ValidatorAttestationDataQuery { + pub slot: Slot, + pub committee_index: CommitteeIndex, +} + +#[derive(Clone, Serialize, Deserialize)] +pub struct ValidatorAggregateAttestationQuery { + pub attestation_data_root: Hash256, + pub slot: Slot, +} + +#[derive(Debug, Clone, PartialEq, Serialize, Deserialize)] +pub struct BeaconCommitteeSubscription { + #[serde(with = "serde_utils::quoted_u64")] + pub validator_index: u64, + #[serde(with = "serde_utils::quoted_u64")] + pub committee_index: u64, + #[serde(with = "serde_utils::quoted_u64")] + pub committees_at_slot: u64, + pub slot: Slot, + pub is_aggregator: bool, +} + +#[cfg(test)] +mod tests { + use super::*; + + #[test] + fn query_vec() { + assert_eq!( + QueryVec::try_from("0,1,2".to_string()).unwrap(), + QueryVec(vec![0_u64, 1, 2]) + ); + } +} diff --git a/common/lighthouse_metrics/src/lib.rs b/common/lighthouse_metrics/src/lib.rs index 0a4251e06df..0637b973c74 100644 --- a/common/lighthouse_metrics/src/lib.rs +++ b/common/lighthouse_metrics/src/lib.rs @@ -55,6 +55,7 @@ //! ``` use prometheus::{HistogramOpts, HistogramTimer, Opts}; +use std::time::Duration; pub use prometheus::{ Encoder, Gauge, GaugeVec, Histogram, HistogramVec, IntCounter, IntCounterVec, IntGauge, @@ -221,6 +222,19 @@ pub fn start_timer(histogram: &Result) -> Option { } } +/// Starts a timer on `vec` with the given `name`. +pub fn observe_timer_vec(vec: &Result, name: &[&str], duration: Duration) { + // This conversion was taken from here: + // + // https://docs.rs/prometheus/0.5.0/src/prometheus/histogram.rs.html#550-555 + let nanos = f64::from(duration.subsec_nanos()) / 1e9; + let secs = duration.as_secs() as f64 + nanos; + + if let Some(h) = get_histogram(vec, name) { + h.observe(secs) + } +} + /// Stops a timer created with `start_timer(..)`. pub fn stop_timer(timer: Option) { if let Some(t) = timer { diff --git a/common/remote_beacon_node/Cargo.toml b/common/remote_beacon_node/Cargo.toml deleted file mode 100644 index 38ee8c7ca58..00000000000 --- a/common/remote_beacon_node/Cargo.toml +++ /dev/null @@ -1,21 +0,0 @@ -[package] -name = "remote_beacon_node" -version = "0.2.0" -authors = ["Paul Hauner "] -edition = "2018" - -# See more keys and their definitions at https://doc.rust-lang.org/cargo/reference/manifest.html - -[dependencies] -reqwest = { version = "0.10.4", features = ["json", "native-tls-vendored"] } -url = "2.1.1" -serde = "1.0.110" -futures = "0.3.5" -types = { path = "../../consensus/types" } -rest_types = { path = "../rest_types" } -hex = "0.4.2" -eth2_ssz = "0.1.2" -serde_json = "1.0.52" -eth2_config = { path = "../eth2_config" } -proto_array = { path = "../../consensus/proto_array" } -operation_pool = { path = "../../beacon_node/operation_pool" } diff --git a/common/remote_beacon_node/src/lib.rs b/common/remote_beacon_node/src/lib.rs deleted file mode 100644 index 199efefd9da..00000000000 --- a/common/remote_beacon_node/src/lib.rs +++ /dev/null @@ -1,732 +0,0 @@ -//! Provides a `RemoteBeaconNode` which interacts with a HTTP API on another Lighthouse (or -//! compatible) instance. -//! -//! Presently, this is only used for testing but it _could_ become a user-facing library. - -use eth2_config::Eth2Config; -use reqwest::{Client, ClientBuilder, Response, StatusCode}; -use serde::{de::DeserializeOwned, Deserialize, Serialize}; -use ssz::Encode; -use std::marker::PhantomData; -use std::time::Duration; -use types::{ - Attestation, AttestationData, AttesterSlashing, BeaconBlock, BeaconState, CommitteeIndex, - Epoch, EthSpec, Fork, Graffiti, Hash256, ProposerSlashing, PublicKey, PublicKeyBytes, - Signature, SignedAggregateAndProof, SignedBeaconBlock, Slot, SubnetId, -}; -use url::Url; - -pub use operation_pool::PersistedOperationPool; -pub use proto_array::core::ProtoArray; -pub use rest_types::{ - CanonicalHeadResponse, Committee, HeadBeaconBlock, Health, IndividualVotesRequest, - IndividualVotesResponse, SyncingResponse, ValidatorDutiesRequest, ValidatorDutyBytes, - ValidatorRequest, ValidatorResponse, ValidatorSubscription, -}; - -// Setting a long timeout for debug ensures that crypto-heavy operations can still succeed. -#[cfg(debug_assertions)] -pub const REQUEST_TIMEOUT_SECONDS: u64 = 15; - -#[cfg(not(debug_assertions))] -pub const REQUEST_TIMEOUT_SECONDS: u64 = 5; - -#[derive(Clone)] -/// Connects to a remote Lighthouse (or compatible) node via HTTP. -pub struct RemoteBeaconNode { - pub http: HttpClient, -} - -impl RemoteBeaconNode { - /// Uses the default HTTP timeout. - pub fn new(http_endpoint: String) -> Result { - Self::new_with_timeout(http_endpoint, Duration::from_secs(REQUEST_TIMEOUT_SECONDS)) - } - - pub fn new_with_timeout(http_endpoint: String, timeout: Duration) -> Result { - Ok(Self { - http: HttpClient::new(http_endpoint, timeout) - .map_err(|e| format!("Unable to create http client: {:?}", e))?, - }) - } -} - -#[derive(Debug)] -pub enum Error { - /// Unable to parse a URL. Check the server URL. - UrlParseError(url::ParseError), - /// The `reqwest` library returned an error. - ReqwestError(reqwest::Error), - /// There was an error when encoding/decoding an object using serde. - SerdeJsonError(serde_json::Error), - /// The server responded to the request, however it did not return a 200-type success code. - DidNotSucceed { status: StatusCode, body: String }, - /// The request input was invalid. - InvalidInput, -} - -#[derive(Clone)] -pub struct HttpClient { - client: Client, - url: Url, - timeout: Duration, - _phantom: PhantomData, -} - -impl HttpClient { - /// Creates a new instance (without connecting to the node). - pub fn new(server_url: String, timeout: Duration) -> Result { - Ok(Self { - client: ClientBuilder::new() - .timeout(timeout) - .build() - .expect("should build from static configuration"), - url: Url::parse(&server_url)?, - timeout: Duration::from_secs(15), - _phantom: PhantomData, - }) - } - - pub fn beacon(&self) -> Beacon { - Beacon(self.clone()) - } - - pub fn validator(&self) -> Validator { - Validator(self.clone()) - } - - pub fn spec(&self) -> Spec { - Spec(self.clone()) - } - - pub fn node(&self) -> Node { - Node(self.clone()) - } - - pub fn advanced(&self) -> Advanced { - Advanced(self.clone()) - } - - pub fn consensus(&self) -> Consensus { - Consensus(self.clone()) - } - - fn url(&self, path: &str) -> Result { - self.url.join(path).map_err(|e| e.into()) - } - - pub async fn json_post(&self, url: Url, body: T) -> Result { - self.client - .post(&url.to_string()) - .json(&body) - .send() - .await - .map_err(Error::from) - } - - pub async fn json_get( - &self, - mut url: Url, - query_pairs: Vec<(String, String)>, - ) -> Result { - query_pairs.into_iter().for_each(|(key, param)| { - url.query_pairs_mut().append_pair(&key, ¶m); - }); - - let response = self - .client - .get(&url.to_string()) - .send() - .await - .map_err(Error::from)?; - - let success = error_for_status(response).await.map_err(Error::from)?; - success.json::().await.map_err(Error::from) - } -} - -/// Returns an `Error` (with a description) if the `response` was not a 200-type success response. -/// -/// Distinct from `Response::error_for_status` because it includes the body of the response as -/// text. This ensures the error message from the server is not discarded. -async fn error_for_status(response: Response) -> Result { - let status = response.status(); - - if status.is_success() { - Ok(response) - } else { - let text_result = response.text().await; - match text_result { - Err(e) => Err(Error::ReqwestError(e)), - Ok(body) => Err(Error::DidNotSucceed { status, body }), - } - } -} - -#[derive(Debug, PartialEq, Clone)] -pub enum PublishStatus { - /// The object was valid and has been published to the network. - Valid, - /// The object was not valid and may or may not have been published to the network. - Invalid(String), - /// The server responded with an unknown status code. The object may or may not have been - /// published to the network. - Unknown, -} - -impl PublishStatus { - /// Returns `true` if `*self == PublishStatus::Valid`. - pub fn is_valid(&self) -> bool { - *self == PublishStatus::Valid - } -} - -/// Provides the functions on the `/validator` endpoint of the node. -#[derive(Clone)] -pub struct Validator(HttpClient); - -impl Validator { - fn url(&self, path: &str) -> Result { - self.0 - .url("validator/") - .and_then(move |url| url.join(path).map_err(Error::from)) - .map_err(Into::into) - } - - /// Produces an unsigned attestation. - pub async fn produce_attestation( - &self, - slot: Slot, - committee_index: CommitteeIndex, - ) -> Result, Error> { - let query_params = vec![ - ("slot".into(), format!("{}", slot)), - ("committee_index".into(), format!("{}", committee_index)), - ]; - - let client = self.0.clone(); - let url = self.url("attestation")?; - client.json_get(url, query_params).await - } - - /// Produces an aggregate attestation. - pub async fn produce_aggregate_attestation( - &self, - attestation_data: &AttestationData, - ) -> Result, Error> { - let query_params = vec![( - "attestation_data".into(), - as_ssz_hex_string(attestation_data), - )]; - - let client = self.0.clone(); - let url = self.url("aggregate_attestation")?; - client.json_get(url, query_params).await - } - - /// Posts a list of attestations to the beacon node, expecting it to verify it and publish it to the network. - pub async fn publish_attestations( - &self, - attestation: Vec<(Attestation, SubnetId)>, - ) -> Result { - let client = self.0.clone(); - let url = self.url("attestations")?; - let response = client.json_post::<_>(url, attestation).await?; - - match response.status() { - StatusCode::OK => Ok(PublishStatus::Valid), - StatusCode::ACCEPTED => Ok(PublishStatus::Invalid( - response.text().await.map_err(Error::from)?, - )), - _ => response - .error_for_status() - .map_err(Error::from) - .map(|_| PublishStatus::Unknown), - } - } - - /// Posts a list of signed aggregates and proofs to the beacon node, expecting it to verify it and publish it to the network. - pub async fn publish_aggregate_and_proof( - &self, - signed_aggregate_and_proofs: Vec>, - ) -> Result { - let client = self.0.clone(); - let url = self.url("aggregate_and_proofs")?; - let response = client - .json_post::<_>(url, signed_aggregate_and_proofs) - .await?; - - match response.status() { - StatusCode::OK => Ok(PublishStatus::Valid), - StatusCode::ACCEPTED => Ok(PublishStatus::Invalid( - response.text().await.map_err(Error::from)?, - )), - _ => response - .error_for_status() - .map_err(Error::from) - .map(|_| PublishStatus::Unknown), - } - } - - /// Returns the duties required of the given validator pubkeys in the given epoch. - pub async fn get_duties( - &self, - epoch: Epoch, - validator_pubkeys: &[PublicKey], - ) -> Result, Error> { - let client = self.0.clone(); - - let bulk_request = ValidatorDutiesRequest { - epoch, - pubkeys: validator_pubkeys - .iter() - .map(|pubkey| pubkey.clone().into()) - .collect(), - }; - - let url = self.url("duties")?; - let response = client.json_post::<_>(url, bulk_request).await?; - let success = error_for_status(response).await.map_err(Error::from)?; - success.json().await.map_err(Error::from) - } - - /// Posts a block to the beacon node, expecting it to verify it and publish it to the network. - pub async fn publish_block(&self, block: SignedBeaconBlock) -> Result { - let client = self.0.clone(); - let url = self.url("block")?; - let response = client.json_post::<_>(url, block).await?; - - match response.status() { - StatusCode::OK => Ok(PublishStatus::Valid), - StatusCode::ACCEPTED => Ok(PublishStatus::Invalid( - response.text().await.map_err(Error::from)?, - )), - _ => response - .error_for_status() - .map_err(Error::from) - .map(|_| PublishStatus::Unknown), - } - } - - /// Requests a new (unsigned) block from the beacon node. - pub async fn produce_block( - &self, - slot: Slot, - randao_reveal: Signature, - graffiti: Option, - ) -> Result, Error> { - let client = self.0.clone(); - let url = self.url("block")?; - - let mut query_pairs = vec![ - ("slot".into(), format!("{}", slot.as_u64())), - ("randao_reveal".into(), as_ssz_hex_string(&randao_reveal)), - ]; - - if let Some(graffiti_bytes) = graffiti { - query_pairs.push(("graffiti".into(), as_ssz_hex_string(&graffiti_bytes))); - } - - client.json_get::>(url, query_pairs).await - } - - /// Subscribes a list of validators to particular slots for attestation production/publication. - pub async fn subscribe( - &self, - subscriptions: Vec, - ) -> Result { - let client = self.0.clone(); - let url = self.url("subscribe")?; - let response = client.json_post::<_>(url, subscriptions).await?; - - match response.status() { - StatusCode::OK => Ok(PublishStatus::Valid), - StatusCode::ACCEPTED => Ok(PublishStatus::Invalid( - response.text().await.map_err(Error::from)?, - )), - _ => response - .error_for_status() - .map_err(Error::from) - .map(|_| PublishStatus::Unknown), - } - } -} - -/// Provides the functions on the `/beacon` endpoint of the node. -#[derive(Clone)] -pub struct Beacon(HttpClient); - -impl Beacon { - fn url(&self, path: &str) -> Result { - self.0 - .url("beacon/") - .and_then(move |url| url.join(path).map_err(Error::from)) - .map_err(Into::into) - } - - /// Returns the genesis time. - pub async fn get_genesis_time(&self) -> Result { - let client = self.0.clone(); - let url = self.url("genesis_time")?; - client.json_get(url, vec![]).await - } - - /// Returns the genesis validators root. - pub async fn get_genesis_validators_root(&self) -> Result { - let client = self.0.clone(); - let url = self.url("genesis_validators_root")?; - client.json_get(url, vec![]).await - } - - /// Returns the fork at the head of the beacon chain. - pub async fn get_fork(&self) -> Result { - let client = self.0.clone(); - let url = self.url("fork")?; - client.json_get(url, vec![]).await - } - - /// Returns info about the head of the canonical beacon chain. - pub async fn get_head(&self) -> Result { - let client = self.0.clone(); - let url = self.url("head")?; - client.json_get::(url, vec![]).await - } - - /// Returns the set of known beacon chain head blocks. One of these will be the canonical head. - pub async fn get_heads(&self) -> Result, Error> { - let client = self.0.clone(); - let url = self.url("heads")?; - client.json_get(url, vec![]).await - } - - /// Returns the block and block root at the given slot. - pub async fn get_block_by_slot( - &self, - slot: Slot, - ) -> Result<(SignedBeaconBlock, Hash256), Error> { - self.get_block("slot".to_string(), format!("{}", slot.as_u64())) - .await - } - - /// Returns the block and block root at the given root. - pub async fn get_block_by_root( - &self, - root: Hash256, - ) -> Result<(SignedBeaconBlock, Hash256), Error> { - self.get_block("root".to_string(), root_as_string(root)) - .await - } - - /// Returns the block and block root at the given slot. - async fn get_block( - &self, - query_key: String, - query_param: String, - ) -> Result<(SignedBeaconBlock, Hash256), Error> { - let client = self.0.clone(); - let url = self.url("block")?; - client - .json_get::>(url, vec![(query_key, query_param)]) - .await - .map(|response| (response.beacon_block, response.root)) - } - - /// Returns the state and state root at the given slot. - pub async fn get_state_by_slot(&self, slot: Slot) -> Result<(BeaconState, Hash256), Error> { - self.get_state("slot".to_string(), format!("{}", slot.as_u64())) - .await - } - - /// Returns the state and state root at the given root. - pub async fn get_state_by_root( - &self, - root: Hash256, - ) -> Result<(BeaconState, Hash256), Error> { - self.get_state("root".to_string(), root_as_string(root)) - .await - } - - /// Returns the root of the state at the given slot. - pub async fn get_state_root(&self, slot: Slot) -> Result { - let client = self.0.clone(); - let url = self.url("state_root")?; - client - .json_get(url, vec![("slot".into(), format!("{}", slot.as_u64()))]) - .await - } - - /// Returns the root of the block at the given slot. - pub async fn get_block_root(&self, slot: Slot) -> Result { - let client = self.0.clone(); - let url = self.url("block_root")?; - client - .json_get(url, vec![("slot".into(), format!("{}", slot.as_u64()))]) - .await - } - - /// Returns the state and state root at the given slot. - async fn get_state( - &self, - query_key: String, - query_param: String, - ) -> Result<(BeaconState, Hash256), Error> { - let client = self.0.clone(); - let url = self.url("state")?; - client - .json_get::>(url, vec![(query_key, query_param)]) - .await - .map(|response| (response.beacon_state, response.root)) - } - - /// Returns the block and block root at the given slot. - /// - /// If `state_root` is `Some`, the query will use the given state instead of the default - /// canonical head state. - pub async fn get_validators( - &self, - validator_pubkeys: Vec, - state_root: Option, - ) -> Result, Error> { - let client = self.0.clone(); - - let bulk_request = ValidatorRequest { - state_root, - pubkeys: validator_pubkeys - .iter() - .map(|pubkey| pubkey.clone().into()) - .collect(), - }; - - let url = self.url("validators")?; - let response = client.json_post::<_>(url, bulk_request).await?; - let success = error_for_status(response).await.map_err(Error::from)?; - success.json().await.map_err(Error::from) - } - - /// Returns all validators. - /// - /// If `state_root` is `Some`, the query will use the given state instead of the default - /// canonical head state. - pub async fn get_all_validators( - &self, - state_root: Option, - ) -> Result, Error> { - let client = self.0.clone(); - - let query_params = if let Some(state_root) = state_root { - vec![("state_root".into(), root_as_string(state_root))] - } else { - vec![] - }; - - let url = self.url("validators/all")?; - client.json_get(url, query_params).await - } - - /// Returns the active validators. - /// - /// If `state_root` is `Some`, the query will use the given state instead of the default - /// canonical head state. - pub async fn get_active_validators( - &self, - state_root: Option, - ) -> Result, Error> { - let client = self.0.clone(); - - let query_params = if let Some(state_root) = state_root { - vec![("state_root".into(), root_as_string(state_root))] - } else { - vec![] - }; - - let url = self.url("validators/active")?; - client.json_get(url, query_params).await - } - - /// Returns committees at the given epoch. - pub async fn get_committees(&self, epoch: Epoch) -> Result, Error> { - let client = self.0.clone(); - - let url = self.url("committees")?; - client - .json_get(url, vec![("epoch".into(), format!("{}", epoch.as_u64()))]) - .await - } - - pub async fn proposer_slashing( - &self, - proposer_slashing: ProposerSlashing, - ) -> Result { - let client = self.0.clone(); - - let url = self.url("proposer_slashing")?; - let response = client.json_post::<_>(url, proposer_slashing).await?; - let success = error_for_status(response).await.map_err(Error::from)?; - success.json().await.map_err(Error::from) - } - - pub async fn attester_slashing( - &self, - attester_slashing: AttesterSlashing, - ) -> Result { - let client = self.0.clone(); - - let url = self.url("attester_slashing")?; - let response = client.json_post::<_>(url, attester_slashing).await?; - let success = error_for_status(response).await.map_err(Error::from)?; - success.json().await.map_err(Error::from) - } -} - -/// Provides the functions on the `/spec` endpoint of the node. -#[derive(Clone)] -pub struct Spec(HttpClient); - -impl Spec { - fn url(&self, path: &str) -> Result { - self.0 - .url("spec/") - .and_then(move |url| url.join(path).map_err(Error::from)) - .map_err(Into::into) - } - - pub async fn get_eth2_config(&self) -> Result { - let client = self.0.clone(); - let url = self.url("eth2_config")?; - client.json_get(url, vec![]).await - } -} - -/// Provides the functions on the `/node` endpoint of the node. -#[derive(Clone)] -pub struct Node(HttpClient); - -impl Node { - fn url(&self, path: &str) -> Result { - self.0 - .url("node/") - .and_then(move |url| url.join(path).map_err(Error::from)) - .map_err(Into::into) - } - - pub async fn get_version(&self) -> Result { - let client = self.0.clone(); - let url = self.url("version")?; - client.json_get(url, vec![]).await - } - - pub async fn get_health(&self) -> Result { - let client = self.0.clone(); - let url = self.url("health")?; - client.json_get(url, vec![]).await - } - - pub async fn syncing_status(&self) -> Result { - let client = self.0.clone(); - let url = self.url("syncing")?; - client.json_get(url, vec![]).await - } -} - -/// Provides the functions on the `/advanced` endpoint of the node. -#[derive(Clone)] -pub struct Advanced(HttpClient); - -impl Advanced { - fn url(&self, path: &str) -> Result { - self.0 - .url("advanced/") - .and_then(move |url| url.join(path).map_err(Error::from)) - .map_err(Into::into) - } - - /// Gets the core `ProtoArray` struct from the node. - pub async fn get_fork_choice(&self) -> Result { - let client = self.0.clone(); - let url = self.url("fork_choice")?; - client.json_get(url, vec![]).await - } - - /// Gets the core `PersistedOperationPool` struct from the node. - pub async fn get_operation_pool(&self) -> Result, Error> { - let client = self.0.clone(); - let url = self.url("operation_pool")?; - client.json_get(url, vec![]).await - } -} - -/// Provides the functions on the `/consensus` endpoint of the node. -#[derive(Clone)] -pub struct Consensus(HttpClient); - -impl Consensus { - fn url(&self, path: &str) -> Result { - self.0 - .url("consensus/") - .and_then(move |url| url.join(path).map_err(Error::from)) - .map_err(Into::into) - } - - /// Gets a `IndividualVote` for each of the given `pubkeys`. - pub async fn get_individual_votes( - &self, - epoch: Epoch, - pubkeys: Vec, - ) -> Result { - let client = self.0.clone(); - let req_body = IndividualVotesRequest { epoch, pubkeys }; - - let url = self.url("individual_votes")?; - let response = client.json_post::<_>(url, req_body).await?; - let success = error_for_status(response).await.map_err(Error::from)?; - success.json().await.map_err(Error::from) - } - - /// Gets a `VoteCount` for the given `epoch`. - pub async fn get_vote_count(&self, epoch: Epoch) -> Result { - let client = self.0.clone(); - let query_params = vec![("epoch".into(), format!("{}", epoch.as_u64()))]; - let url = self.url("vote_count")?; - client.json_get(url, query_params).await - } -} - -#[derive(Deserialize)] -#[serde(bound = "T: EthSpec")] -pub struct BlockResponse { - pub beacon_block: SignedBeaconBlock, - pub root: Hash256, -} - -#[derive(Deserialize)] -#[serde(bound = "T: EthSpec")] -pub struct StateResponse { - pub beacon_state: BeaconState, - pub root: Hash256, -} - -fn root_as_string(root: Hash256) -> String { - format!("0x{:?}", root) -} - -fn as_ssz_hex_string(item: &T) -> String { - format!("0x{}", hex::encode(item.as_ssz_bytes())) -} - -impl From for Error { - fn from(e: reqwest::Error) -> Error { - Error::ReqwestError(e) - } -} - -impl From for Error { - fn from(e: url::ParseError) -> Error { - Error::UrlParseError(e) - } -} - -impl From for Error { - fn from(e: serde_json::Error) -> Error { - Error::SerdeJsonError(e) - } -} diff --git a/common/rest_types/Cargo.toml b/common/rest_types/Cargo.toml deleted file mode 100644 index d9e021fe19d..00000000000 --- a/common/rest_types/Cargo.toml +++ /dev/null @@ -1,27 +0,0 @@ -[package] -name = "rest_types" -version = "0.2.0" -authors = ["Sigma Prime "] -edition = "2018" - -[dependencies] -types = { path = "../../consensus/types" } -eth2_ssz_derive = "0.1.0" -eth2_ssz = "0.1.2" -eth2_hashing = "0.1.0" -tree_hash = "0.1.0" -state_processing = { path = "../../consensus/state_processing" } -bls = { path = "../../crypto/bls" } -serde = { version = "1.0.110", features = ["derive"] } -rayon = "1.3.0" -hyper = "0.13.5" -tokio = { version = "0.2.21", features = ["sync"] } -environment = { path = "../../lighthouse/environment" } -store = { path = "../../beacon_node/store" } -beacon_chain = { path = "../../beacon_node/beacon_chain" } -serde_json = "1.0.52" -serde_yaml = "0.8.11" - -[target.'cfg(target_os = "linux")'.dependencies] -psutil = "3.1.0" -procinfo = "0.4.2" diff --git a/common/rest_types/src/api_error.rs b/common/rest_types/src/api_error.rs deleted file mode 100644 index 1eac8d4a468..00000000000 --- a/common/rest_types/src/api_error.rs +++ /dev/null @@ -1,99 +0,0 @@ -use hyper::{Body, Response, StatusCode}; -use std::error::Error as StdError; - -#[derive(PartialEq, Debug, Clone)] -pub enum ApiError { - MethodNotAllowed(String), - ServerError(String), - NotImplemented(String), - BadRequest(String), - NotFound(String), - UnsupportedType(String), - ImATeapot(String), // Just in case. - ProcessingError(String), // A 202 error, for when a block/attestation cannot be processed, but still transmitted. - InvalidHeaderValue(String), -} - -pub type ApiResult = Result, ApiError>; - -impl ApiError { - pub fn status_code(self) -> (StatusCode, String) { - match self { - ApiError::MethodNotAllowed(desc) => (StatusCode::METHOD_NOT_ALLOWED, desc), - ApiError::ServerError(desc) => (StatusCode::INTERNAL_SERVER_ERROR, desc), - ApiError::NotImplemented(desc) => (StatusCode::NOT_IMPLEMENTED, desc), - ApiError::BadRequest(desc) => (StatusCode::BAD_REQUEST, desc), - ApiError::NotFound(desc) => (StatusCode::NOT_FOUND, desc), - ApiError::UnsupportedType(desc) => (StatusCode::UNSUPPORTED_MEDIA_TYPE, desc), - ApiError::ImATeapot(desc) => (StatusCode::IM_A_TEAPOT, desc), - ApiError::ProcessingError(desc) => (StatusCode::ACCEPTED, desc), - ApiError::InvalidHeaderValue(desc) => (StatusCode::INTERNAL_SERVER_ERROR, desc), - } - } -} - -impl Into> for ApiError { - fn into(self) -> Response { - let (status_code, desc) = self.status_code(); - Response::builder() - .status(status_code) - .header("content-type", "text/plain; charset=utf-8") - .body(Body::from(desc)) - .expect("Response should always be created.") - } -} - -impl From for ApiError { - fn from(e: store::Error) -> ApiError { - ApiError::ServerError(format!("Database error: {:?}", e)) - } -} - -impl From for ApiError { - fn from(e: types::BeaconStateError) -> ApiError { - ApiError::ServerError(format!("BeaconState error: {:?}", e)) - } -} - -impl From for ApiError { - fn from(e: beacon_chain::BeaconChainError) -> ApiError { - ApiError::ServerError(format!("BeaconChainError error: {:?}", e)) - } -} - -impl From for ApiError { - fn from(e: state_processing::per_slot_processing::Error) -> ApiError { - ApiError::ServerError(format!("PerSlotProcessing error: {:?}", e)) - } -} - -impl From for ApiError { - fn from(e: hyper::error::Error) -> ApiError { - ApiError::ServerError(format!("Networking error: {:?}", e)) - } -} - -impl From for ApiError { - fn from(e: std::io::Error) -> ApiError { - ApiError::ServerError(format!("IO error: {:?}", e)) - } -} - -impl From for ApiError { - fn from(e: hyper::header::InvalidHeaderValue) -> ApiError { - ApiError::InvalidHeaderValue(format!("Invalid CORS header value: {:?}", e)) - } -} - -impl StdError for ApiError { - fn cause(&self) -> Option<&dyn StdError> { - None - } -} - -impl std::fmt::Display for ApiError { - fn fmt(&self, f: &mut std::fmt::Formatter) -> std::fmt::Result { - let status = self.clone().status_code(); - write!(f, "{:?}: {:?}", status.0, status.1) - } -} diff --git a/common/rest_types/src/beacon.rs b/common/rest_types/src/beacon.rs deleted file mode 100644 index 0a141ea282a..00000000000 --- a/common/rest_types/src/beacon.rs +++ /dev/null @@ -1,65 +0,0 @@ -//! A collection of REST API types for interaction with the beacon node. - -use bls::PublicKeyBytes; -use serde::{Deserialize, Serialize}; -use ssz_derive::{Decode, Encode}; -use types::beacon_state::EthSpec; -use types::{BeaconState, CommitteeIndex, Hash256, SignedBeaconBlock, Slot, Validator}; - -/// Information about a block that is at the head of a chain. May or may not represent the -/// canonical head. -#[derive(Clone, Debug, PartialEq, Serialize, Deserialize, Encode, Decode)] -pub struct HeadBeaconBlock { - pub beacon_block_root: Hash256, - pub beacon_block_slot: Slot, -} - -#[derive(Clone, Debug, PartialEq, Serialize, Deserialize, Encode, Decode)] -#[serde(bound = "T: EthSpec")] -pub struct BlockResponse { - pub root: Hash256, - pub beacon_block: SignedBeaconBlock, -} - -/// Information about the block and state that are at head of the beacon chain. -#[derive(Clone, Debug, PartialEq, Serialize, Deserialize, Encode, Decode)] -pub struct CanonicalHeadResponse { - pub slot: Slot, - pub block_root: Hash256, - pub state_root: Hash256, - pub finalized_slot: Slot, - pub finalized_block_root: Hash256, - pub justified_slot: Slot, - pub justified_block_root: Hash256, - pub previous_justified_slot: Slot, - pub previous_justified_block_root: Hash256, -} - -#[derive(Clone, Debug, PartialEq, Serialize, Deserialize, Encode, Decode)] -pub struct ValidatorResponse { - pub pubkey: PublicKeyBytes, - pub validator_index: Option, - pub balance: Option, - pub validator: Option, -} - -#[derive(Clone, Debug, PartialEq, Serialize, Deserialize, Encode, Decode)] -pub struct ValidatorRequest { - /// If set to `None`, uses the canonical head state. - pub state_root: Option, - pub pubkeys: Vec, -} - -#[derive(Clone, Debug, PartialEq, Serialize, Deserialize, Encode, Decode)] -pub struct Committee { - pub slot: Slot, - pub index: CommitteeIndex, - pub committee: Vec, -} - -#[derive(Clone, Debug, PartialEq, Serialize, Deserialize, Encode, Decode)] -#[serde(bound = "T: EthSpec")] -pub struct StateResponse { - pub root: Hash256, - pub beacon_state: BeaconState, -} diff --git a/common/rest_types/src/consensus.rs b/common/rest_types/src/consensus.rs deleted file mode 100644 index 519b1ae247c..00000000000 --- a/common/rest_types/src/consensus.rs +++ /dev/null @@ -1,66 +0,0 @@ -use serde::{Deserialize, Serialize}; -use ssz_derive::{Decode, Encode}; -use state_processing::per_epoch_processing::ValidatorStatus; -use types::{Epoch, PublicKeyBytes}; - -#[derive(PartialEq, Debug, Serialize, Deserialize, Clone, Encode, Decode)] -pub struct IndividualVotesRequest { - pub epoch: Epoch, - pub pubkeys: Vec, -} - -#[derive(PartialEq, Debug, Serialize, Deserialize, Clone, Encode, Decode)] -pub struct IndividualVote { - /// True if the validator has been slashed, ever. - pub is_slashed: bool, - /// True if the validator can withdraw in the current epoch. - pub is_withdrawable_in_current_epoch: bool, - /// True if the validator was active in the state's _current_ epoch. - pub is_active_in_current_epoch: bool, - /// True if the validator was active in the state's _previous_ epoch. - pub is_active_in_previous_epoch: bool, - /// The validator's effective balance in the _current_ epoch. - pub current_epoch_effective_balance_gwei: u64, - /// True if the validator had an attestation included in the _current_ epoch. - pub is_current_epoch_attester: bool, - /// True if the validator's beacon block root attestation for the first slot of the _current_ - /// epoch matches the block root known to the state. - pub is_current_epoch_target_attester: bool, - /// True if the validator had an attestation included in the _previous_ epoch. - pub is_previous_epoch_attester: bool, - /// True if the validator's beacon block root attestation for the first slot of the _previous_ - /// epoch matches the block root known to the state. - pub is_previous_epoch_target_attester: bool, - /// True if the validator's beacon block root attestation in the _previous_ epoch at the - /// attestation's slot (`attestation_data.slot`) matches the block root known to the state. - pub is_previous_epoch_head_attester: bool, -} - -impl Into for ValidatorStatus { - fn into(self) -> IndividualVote { - IndividualVote { - is_slashed: self.is_slashed, - is_withdrawable_in_current_epoch: self.is_withdrawable_in_current_epoch, - is_active_in_current_epoch: self.is_active_in_current_epoch, - is_active_in_previous_epoch: self.is_active_in_previous_epoch, - current_epoch_effective_balance_gwei: self.current_epoch_effective_balance, - is_current_epoch_attester: self.is_current_epoch_attester, - is_current_epoch_target_attester: self.is_current_epoch_target_attester, - is_previous_epoch_attester: self.is_previous_epoch_attester, - is_previous_epoch_target_attester: self.is_previous_epoch_target_attester, - is_previous_epoch_head_attester: self.is_previous_epoch_head_attester, - } - } -} - -#[derive(PartialEq, Debug, Serialize, Deserialize, Clone, Encode, Decode)] -pub struct IndividualVotesResponse { - /// The epoch which is considered the "current" epoch. - pub epoch: Epoch, - /// The validators public key. - pub pubkey: PublicKeyBytes, - /// The index of the validator in state.validators. - pub validator_index: Option, - /// Voting statistics for the validator, if they voted in the given epoch. - pub vote: Option, -} diff --git a/common/rest_types/src/handler.rs b/common/rest_types/src/handler.rs deleted file mode 100644 index cbbcd73b19a..00000000000 --- a/common/rest_types/src/handler.rs +++ /dev/null @@ -1,247 +0,0 @@ -use crate::{ApiError, ApiResult}; -use environment::TaskExecutor; -use hyper::header; -use hyper::{Body, Request, Response, StatusCode}; -use serde::Deserialize; -use serde::Serialize; -use ssz::Encode; - -/// Defines the encoding for the API. -#[derive(Clone, Serialize, Deserialize, Copy)] -pub enum ApiEncodingFormat { - JSON, - YAML, - SSZ, -} - -impl ApiEncodingFormat { - pub fn get_content_type(&self) -> &str { - match self { - ApiEncodingFormat::JSON => "application/json", - ApiEncodingFormat::YAML => "application/yaml", - ApiEncodingFormat::SSZ => "application/ssz", - } - } -} - -impl From<&str> for ApiEncodingFormat { - fn from(f: &str) -> ApiEncodingFormat { - match f { - "application/yaml" => ApiEncodingFormat::YAML, - "application/ssz" => ApiEncodingFormat::SSZ, - _ => ApiEncodingFormat::JSON, - } - } -} - -/// Provides a HTTP request handler with Lighthouse-specific functionality. -pub struct Handler { - executor: TaskExecutor, - req: Request<()>, - body: Body, - ctx: T, - encoding: ApiEncodingFormat, - allow_body: bool, -} - -impl Handler { - /// Start handling a new request. - pub fn new(req: Request, ctx: T, executor: TaskExecutor) -> Result { - let (req_parts, body) = req.into_parts(); - let req = Request::from_parts(req_parts, ()); - - let accept_header: String = req - .headers() - .get(header::ACCEPT) - .map_or(Ok(""), |h| h.to_str()) - .map_err(|e| { - ApiError::BadRequest(format!( - "The Accept header contains invalid characters: {:?}", - e - )) - }) - .map(String::from)?; - - Ok(Self { - executor, - req, - body, - ctx, - allow_body: false, - encoding: ApiEncodingFormat::from(accept_header.as_str()), - }) - } - - /// The default behaviour is to return an error if any body is supplied in the request. Calling - /// this function disables that error. - pub fn allow_body(mut self) -> Self { - self.allow_body = true; - self - } - - /// Return a simple static value. - /// - /// Does not use the blocking executor. - pub async fn static_value(self, value: V) -> Result, ApiError> { - // Always check and disallow a body for a static value. - let _ = Self::get_body(self.body, false).await?; - - Ok(HandledRequest { - value, - encoding: self.encoding, - }) - } - - /// Calls `func` in-line, on the core executor. - /// - /// This should only be used for very fast tasks. - pub async fn in_core_task(self, func: F) -> Result, ApiError> - where - V: Send + Sync + 'static, - F: Fn(Request>, T) -> Result + Send + Sync + 'static, - { - let body = Self::get_body(self.body, self.allow_body).await?; - let (req_parts, _) = self.req.into_parts(); - let req = Request::from_parts(req_parts, body); - - let value = func(req, self.ctx)?; - - Ok(HandledRequest { - value, - encoding: self.encoding, - }) - } - - /// Spawns `func` on the blocking executor. - /// - /// This method is suitable for handling long-running or intensive tasks. - pub async fn in_blocking_task(self, func: F) -> Result, ApiError> - where - V: Send + Sync + 'static, - F: Fn(Request>, T) -> Result + Send + Sync + 'static, - { - let ctx = self.ctx; - let body = Self::get_body(self.body, self.allow_body).await?; - let (req_parts, _) = self.req.into_parts(); - let req = Request::from_parts(req_parts, body); - - let value = self - .executor - .clone() - .handle - .spawn_blocking(move || func(req, ctx)) - .await - .map_err(|e| { - ApiError::ServerError(format!( - "Failed to get blocking join handle: {}", - e.to_string() - )) - })??; - - Ok(HandledRequest { - value, - encoding: self.encoding, - }) - } - - /// Call `func`, then return a response that is suitable for an SSE stream. - pub async fn sse_stream(self, func: F) -> ApiResult - where - F: Fn(Request<()>, T) -> Result, - { - let body = func(self.req, self.ctx)?; - - Response::builder() - .status(200) - .header("Content-Type", "text/event-stream") - .header("Connection", "Keep-Alive") - .header("Cache-Control", "no-cache") - .header("Access-Control-Allow-Origin", "*") - .body(body) - .map_err(|e| ApiError::ServerError(format!("Failed to build response: {:?}", e))) - } - - /// Downloads the bytes for `body`. - async fn get_body(body: Body, allow_body: bool) -> Result, ApiError> { - let bytes = hyper::body::to_bytes(body) - .await - .map_err(|e| ApiError::ServerError(format!("Unable to get request body: {:?}", e)))?; - - if !allow_body && !bytes[..].is_empty() { - Err(ApiError::BadRequest( - "The request body must be empty".to_string(), - )) - } else { - Ok(bytes.into_iter().collect()) - } - } -} - -/// A request that has been "handled" and now a result (`value`) needs to be serialize and -/// returned. -pub struct HandledRequest { - encoding: ApiEncodingFormat, - value: V, -} - -impl HandledRequest { - /// Simple encode a string as utf-8. - pub fn text_encoding(self) -> ApiResult { - Response::builder() - .status(StatusCode::OK) - .header("content-type", "text/plain; charset=utf-8") - .body(Body::from(self.value)) - .map_err(|e| ApiError::ServerError(format!("Failed to build response: {:?}", e))) - } -} - -impl HandledRequest { - /// Suitable for all items which implement `serde` and `ssz`. - pub fn all_encodings(self) -> ApiResult { - match self.encoding { - ApiEncodingFormat::SSZ => Response::builder() - .status(StatusCode::OK) - .header("content-type", "application/ssz") - .body(Body::from(self.value.as_ssz_bytes())) - .map_err(|e| ApiError::ServerError(format!("Failed to build response: {:?}", e))), - _ => self.serde_encodings(), - } - } -} - -impl HandledRequest { - /// Suitable for items which only implement `serde`. - pub fn serde_encodings(self) -> ApiResult { - let (body, content_type) = match self.encoding { - ApiEncodingFormat::JSON => ( - Body::from(serde_json::to_string(&self.value).map_err(|e| { - ApiError::ServerError(format!( - "Unable to serialize response body as JSON: {:?}", - e - )) - })?), - "application/json", - ), - ApiEncodingFormat::SSZ => { - return Err(ApiError::UnsupportedType( - "Response cannot be encoded as SSZ.".into(), - )); - } - ApiEncodingFormat::YAML => ( - Body::from(serde_yaml::to_string(&self.value).map_err(|e| { - ApiError::ServerError(format!( - "Unable to serialize response body as YAML: {:?}", - e - )) - })?), - "application/yaml", - ), - }; - - Response::builder() - .status(StatusCode::OK) - .header("content-type", content_type) - .body(body) - .map_err(|e| ApiError::ServerError(format!("Failed to build response: {:?}", e))) - } -} diff --git a/common/rest_types/src/lib.rs b/common/rest_types/src/lib.rs deleted file mode 100644 index 1bedd1cadbc..00000000000 --- a/common/rest_types/src/lib.rs +++ /dev/null @@ -1,22 +0,0 @@ -//! A collection of types used to pass data across the rest HTTP API. -//! -//! This is primarily used by the validator client and the beacon node rest API. - -mod api_error; -mod beacon; -mod consensus; -mod handler; -mod node; -mod validator; - -pub use api_error::{ApiError, ApiResult}; -pub use beacon::{ - BlockResponse, CanonicalHeadResponse, Committee, HeadBeaconBlock, StateResponse, - ValidatorRequest, ValidatorResponse, -}; -pub use consensus::{IndividualVote, IndividualVotesRequest, IndividualVotesResponse}; -pub use handler::{ApiEncodingFormat, Handler}; -pub use node::{Health, SyncingResponse, SyncingStatus}; -pub use validator::{ - ValidatorDutiesRequest, ValidatorDuty, ValidatorDutyBytes, ValidatorSubscription, -}; diff --git a/common/rest_types/src/node.rs b/common/rest_types/src/node.rs deleted file mode 100644 index ca98645cc8c..00000000000 --- a/common/rest_types/src/node.rs +++ /dev/null @@ -1,103 +0,0 @@ -//! Collection of types for the /node HTTP -use serde::{Deserialize, Serialize}; -use ssz_derive::{Decode, Encode}; -use types::Slot; - -#[cfg(target_os = "linux")] -use {procinfo::pid, psutil::process::Process}; - -#[derive(Clone, Debug, PartialEq, Serialize, Deserialize, Encode, Decode)] -/// The current syncing status of the node. -pub struct SyncingStatus { - /// The starting slot of sync. - /// - /// For a finalized sync, this is the start slot of the current finalized syncing - /// chain. - /// - /// For head sync this is the last finalized slot. - pub starting_slot: Slot, - /// The current slot. - pub current_slot: Slot, - /// The highest known slot. For the current syncing chain. - /// - /// For a finalized sync, the target finalized slot. - /// For head sync, this is the highest known slot of all head chains. - pub highest_slot: Slot, -} - -#[derive(Clone, Debug, PartialEq, Serialize, Deserialize, Encode, Decode)] -/// The response for the /node/syncing HTTP GET. -pub struct SyncingResponse { - /// Is the node syncing. - pub is_syncing: bool, - /// The current sync status. - pub sync_status: SyncingStatus, -} - -#[derive(Clone, Debug, PartialEq, Serialize, Deserialize)] -/// Reports on the health of the Lighthouse instance. -pub struct Health { - /// The pid of this process. - pub pid: u32, - /// The number of threads used by this pid. - pub pid_num_threads: i32, - /// The total resident memory used by this pid. - pub pid_mem_resident_set_size: u64, - /// The total virtual memory used by this pid. - pub pid_mem_virtual_memory_size: u64, - /// Total virtual memory on the system - pub sys_virt_mem_total: u64, - /// Total virtual memory available for new processes. - pub sys_virt_mem_available: u64, - /// Total virtual memory used on the system - pub sys_virt_mem_used: u64, - /// Total virtual memory not used on the system - pub sys_virt_mem_free: u64, - /// Percentage of virtual memory used on the system - pub sys_virt_mem_percent: f32, - /// System load average over 1 minute. - pub sys_loadavg_1: f64, - /// System load average over 5 minutes. - pub sys_loadavg_5: f64, - /// System load average over 15 minutes. - pub sys_loadavg_15: f64, -} - -impl Health { - #[cfg(not(target_os = "linux"))] - pub fn observe() -> Result { - Err("Health is only available on Linux".into()) - } - - #[cfg(target_os = "linux")] - pub fn observe() -> Result { - let process = - Process::current().map_err(|e| format!("Unable to get current process: {:?}", e))?; - - let process_mem = process - .memory_info() - .map_err(|e| format!("Unable to get process memory info: {:?}", e))?; - - let stat = pid::stat_self().map_err(|e| format!("Unable to get stat: {:?}", e))?; - - let vm = psutil::memory::virtual_memory() - .map_err(|e| format!("Unable to get virtual memory: {:?}", e))?; - let loadavg = - psutil::host::loadavg().map_err(|e| format!("Unable to get loadavg: {:?}", e))?; - - Ok(Self { - pid: process.pid(), - pid_num_threads: stat.num_threads, - pid_mem_resident_set_size: process_mem.rss(), - pid_mem_virtual_memory_size: process_mem.vms(), - sys_virt_mem_total: vm.total(), - sys_virt_mem_available: vm.available(), - sys_virt_mem_used: vm.used(), - sys_virt_mem_free: vm.free(), - sys_virt_mem_percent: vm.percent(), - sys_loadavg_1: loadavg.one, - sys_loadavg_5: loadavg.five, - sys_loadavg_15: loadavg.fifteen, - }) - } -} diff --git a/common/rest_types/src/validator.rs b/common/rest_types/src/validator.rs deleted file mode 100644 index 2b0f077298a..00000000000 --- a/common/rest_types/src/validator.rs +++ /dev/null @@ -1,103 +0,0 @@ -use bls::{PublicKey, PublicKeyBytes}; -use serde::{Deserialize, Serialize}; -use ssz_derive::{Decode, Encode}; -use types::{CommitteeIndex, Epoch, Slot}; - -/// A Validator duty with the validator public key represented a `PublicKeyBytes`. -pub type ValidatorDutyBytes = ValidatorDutyBase; -/// A validator duty with the pubkey represented as a `PublicKey`. -pub type ValidatorDuty = ValidatorDutyBase; - -// NOTE: if you add or remove fields, please adjust `eq_ignoring_proposal_slots` -#[derive(PartialEq, Debug, Serialize, Deserialize, Clone)] -pub struct ValidatorDutyBase { - /// The validator's BLS public key, uniquely identifying them. - pub validator_pubkey: T, - /// The validator's index in `state.validators` - pub validator_index: Option, - /// The slot at which the validator must attest. - pub attestation_slot: Option, - /// The index of the committee within `slot` of which the validator is a member. - pub attestation_committee_index: Option, - /// The position of the validator in the committee. - pub attestation_committee_position: Option, - /// The committee count at `attestation_slot`. - pub committee_count_at_slot: Option, - /// The slots in which a validator must propose a block (can be empty). - /// - /// Should be set to `None` when duties are not yet known (before the current epoch). - pub block_proposal_slots: Option>, - /// This provides the modulo: `max(1, len(committee) // TARGET_AGGREGATORS_PER_COMMITTEE)` - /// which allows the validator client to determine if this duty requires the validator to be - /// aggregate attestations. - pub aggregator_modulo: Option, -} - -impl ValidatorDutyBase { - /// Return `true` if these validator duties are equal, ignoring their `block_proposal_slots`. - pub fn eq_ignoring_proposal_slots(&self, other: &Self) -> bool - where - T: PartialEq, - { - self.validator_pubkey == other.validator_pubkey - && self.validator_index == other.validator_index - && self.attestation_slot == other.attestation_slot - && self.attestation_committee_index == other.attestation_committee_index - && self.attestation_committee_position == other.attestation_committee_position - && self.committee_count_at_slot == other.committee_count_at_slot - && self.aggregator_modulo == other.aggregator_modulo - } -} - -#[derive(PartialEq, Debug, Serialize, Deserialize, Clone, Encode, Decode)] -pub struct ValidatorDutiesRequest { - pub epoch: Epoch, - pub pubkeys: Vec, -} - -/// A validator subscription, created when a validator subscribes to a slot to perform optional aggregation -/// duties. -#[derive(PartialEq, Debug, Serialize, Deserialize, Clone, Encode, Decode)] -pub struct ValidatorSubscription { - /// The validators index. - pub validator_index: u64, - /// The index of the committee within `slot` of which the validator is a member. Used by the - /// beacon node to quickly evaluate the associated `SubnetId`. - pub attestation_committee_index: CommitteeIndex, - /// The slot in which to subscribe. - pub slot: Slot, - /// Committee count at slot to subscribe. - pub committee_count_at_slot: u64, - /// If true, the validator is an aggregator and the beacon node should aggregate attestations - /// for this slot. - pub is_aggregator: bool, -} - -#[cfg(test)] -mod test { - use super::*; - use bls::SecretKey; - - #[test] - fn eq_ignoring_proposal_slots() { - let validator_pubkey = SecretKey::deserialize(&[1; 32]).unwrap().public_key(); - - let duty1 = ValidatorDuty { - validator_pubkey, - validator_index: Some(10), - attestation_slot: Some(Slot::new(50)), - attestation_committee_index: Some(2), - attestation_committee_position: Some(6), - committee_count_at_slot: Some(4), - block_proposal_slots: None, - aggregator_modulo: Some(99), - }; - let duty2 = ValidatorDuty { - block_proposal_slots: Some(vec![Slot::new(42), Slot::new(45)]), - ..duty1.clone() - }; - assert_ne!(duty1, duty2); - assert!(duty1.eq_ignoring_proposal_slots(&duty2)); - assert!(duty2.eq_ignoring_proposal_slots(&duty1)); - } -} diff --git a/common/slot_clock/src/lib.rs b/common/slot_clock/src/lib.rs index 41c847498a6..0fe1bedfeda 100644 --- a/common/slot_clock/src/lib.rs +++ b/common/slot_clock/src/lib.rs @@ -24,6 +24,16 @@ pub trait SlotClock: Send + Sync + Sized { /// Returns the slot at this present time. fn now(&self) -> Option; + /// Returns the slot at this present time if genesis has happened. Otherwise, returns the + /// genesis slot. Returns `None` if there is an error reading the clock. + fn now_or_genesis(&self) -> Option { + if self.is_prior_to_genesis()? { + Some(self.genesis_slot()) + } else { + self.now() + } + } + /// Indicates if the current time is prior to genesis time. /// /// Returns `None` if the system clock cannot be read. diff --git a/common/warp_utils/Cargo.toml b/common/warp_utils/Cargo.toml new file mode 100644 index 00000000000..98ddab5d83d --- /dev/null +++ b/common/warp_utils/Cargo.toml @@ -0,0 +1,15 @@ +[package] +name = "warp_utils" +version = "0.1.0" +authors = ["Paul Hauner "] +edition = "2018" + +# See more keys and their definitions at https://doc.rust-lang.org/cargo/reference/manifest.html + +[dependencies] +warp = "0.2.5" +eth2 = { path = "../eth2" } +types = { path = "../../consensus/types" } +beacon_chain = { path = "../../beacon_node/beacon_chain" } +state_processing = { path = "../../consensus/state_processing" } +safe_arith = { path = "../../consensus/safe_arith" } diff --git a/common/warp_utils/src/lib.rs b/common/warp_utils/src/lib.rs new file mode 100644 index 00000000000..ec9cf3c3442 --- /dev/null +++ b/common/warp_utils/src/lib.rs @@ -0,0 +1,5 @@ +//! This crate contains functions that are common across multiple `warp` HTTP servers in the +//! Lighthouse project. E.g., the `http_api` and `http_metrics` crates. + +pub mod reject; +pub mod reply; diff --git a/common/warp_utils/src/reject.rs b/common/warp_utils/src/reject.rs new file mode 100644 index 00000000000..1243d5f685a --- /dev/null +++ b/common/warp_utils/src/reject.rs @@ -0,0 +1,168 @@ +use eth2::types::ErrorMessage; +use std::convert::Infallible; +use warp::{http::StatusCode, reject::Reject}; + +#[derive(Debug)] +pub struct BeaconChainError(pub beacon_chain::BeaconChainError); + +impl Reject for BeaconChainError {} + +pub fn beacon_chain_error(e: beacon_chain::BeaconChainError) -> warp::reject::Rejection { + warp::reject::custom(BeaconChainError(e)) +} + +#[derive(Debug)] +pub struct BeaconStateError(pub types::BeaconStateError); + +impl Reject for BeaconStateError {} + +pub fn beacon_state_error(e: types::BeaconStateError) -> warp::reject::Rejection { + warp::reject::custom(BeaconStateError(e)) +} + +#[derive(Debug)] +pub struct ArithError(pub safe_arith::ArithError); + +impl Reject for ArithError {} + +pub fn arith_error(e: safe_arith::ArithError) -> warp::reject::Rejection { + warp::reject::custom(ArithError(e)) +} + +#[derive(Debug)] +pub struct SlotProcessingError(pub state_processing::SlotProcessingError); + +impl Reject for SlotProcessingError {} + +pub fn slot_processing_error(e: state_processing::SlotProcessingError) -> warp::reject::Rejection { + warp::reject::custom(SlotProcessingError(e)) +} + +#[derive(Debug)] +pub struct BlockProductionError(pub beacon_chain::BlockProductionError); + +impl Reject for BlockProductionError {} + +pub fn block_production_error(e: beacon_chain::BlockProductionError) -> warp::reject::Rejection { + warp::reject::custom(BlockProductionError(e)) +} + +#[derive(Debug)] +pub struct CustomNotFound(pub String); + +impl Reject for CustomNotFound {} + +pub fn custom_not_found(msg: String) -> warp::reject::Rejection { + warp::reject::custom(CustomNotFound(msg)) +} + +#[derive(Debug)] +pub struct CustomBadRequest(pub String); + +impl Reject for CustomBadRequest {} + +pub fn custom_bad_request(msg: String) -> warp::reject::Rejection { + warp::reject::custom(CustomBadRequest(msg)) +} + +#[derive(Debug)] +pub struct CustomServerError(pub String); + +impl Reject for CustomServerError {} + +pub fn custom_server_error(msg: String) -> warp::reject::Rejection { + warp::reject::custom(CustomServerError(msg)) +} + +#[derive(Debug)] +pub struct BroadcastWithoutImport(pub String); + +impl Reject for BroadcastWithoutImport {} + +pub fn broadcast_without_import(msg: String) -> warp::reject::Rejection { + warp::reject::custom(BroadcastWithoutImport(msg)) +} + +#[derive(Debug)] +pub struct ObjectInvalid(pub String); + +impl Reject for ObjectInvalid {} + +pub fn object_invalid(msg: String) -> warp::reject::Rejection { + warp::reject::custom(ObjectInvalid(msg)) +} + +#[derive(Debug)] +pub struct NotSynced(pub String); + +impl Reject for NotSynced {} + +pub fn not_synced(msg: String) -> warp::reject::Rejection { + warp::reject::custom(NotSynced(msg)) +} + +/// This function receives a `Rejection` and tries to return a custom +/// value, otherwise simply passes the rejection along. +pub async fn handle_rejection(err: warp::Rejection) -> Result { + let code; + let message; + + if err.is_not_found() { + code = StatusCode::NOT_FOUND; + message = "NOT_FOUND".to_string(); + } else if let Some(e) = err.find::() { + message = format!("BAD_REQUEST: body deserialize error: {}", e); + code = StatusCode::BAD_REQUEST; + } else if let Some(e) = err.find::() { + code = StatusCode::BAD_REQUEST; + message = format!("BAD_REQUEST: invalid query: {}", e); + } else if let Some(e) = err.find::() { + code = StatusCode::INTERNAL_SERVER_ERROR; + message = format!("UNHANDLED_ERROR: {:?}", e.0); + } else if let Some(e) = err.find::() { + code = StatusCode::INTERNAL_SERVER_ERROR; + message = format!("UNHANDLED_ERROR: {:?}", e.0); + } else if let Some(e) = err.find::() { + code = StatusCode::INTERNAL_SERVER_ERROR; + message = format!("UNHANDLED_ERROR: {:?}", e.0); + } else if let Some(e) = err.find::() { + code = StatusCode::INTERNAL_SERVER_ERROR; + message = format!("UNHANDLED_ERROR: {:?}", e.0); + } else if let Some(e) = err.find::() { + code = StatusCode::NOT_FOUND; + message = format!("NOT_FOUND: {}", e.0); + } else if let Some(e) = err.find::() { + code = StatusCode::BAD_REQUEST; + message = format!("BAD_REQUEST: {}", e.0); + } else if let Some(e) = err.find::() { + code = StatusCode::INTERNAL_SERVER_ERROR; + message = format!("INTERNAL_SERVER_ERROR: {}", e.0); + } else if let Some(e) = err.find::() { + code = StatusCode::ACCEPTED; + message = format!( + "ACCEPTED: the object was broadcast to the network without being \ + fully imported to the local database: {}", + e.0 + ); + } else if let Some(e) = err.find::() { + code = StatusCode::BAD_REQUEST; + message = format!("BAD_REQUEST: Invalid object: {}", e.0); + } else if let Some(e) = err.find::() { + code = StatusCode::SERVICE_UNAVAILABLE; + message = format!("SERVICE_UNAVAILABLE: beacon node is syncing: {}", e.0); + } else if err.find::().is_some() { + code = StatusCode::METHOD_NOT_ALLOWED; + message = "METHOD_NOT_ALLOWED".to_string(); + } else { + code = StatusCode::INTERNAL_SERVER_ERROR; + message = "UNHANDLED_REJECTION".to_string(); + } + + let json = warp::reply::json(&ErrorMessage { + code: code.as_u16(), + message, + stacktraces: vec![], + }); + + Ok(warp::reply::with_status(json, code)) +} diff --git a/common/warp_utils/src/reply.rs b/common/warp_utils/src/reply.rs new file mode 100644 index 00000000000..dcec6214f0c --- /dev/null +++ b/common/warp_utils/src/reply.rs @@ -0,0 +1,15 @@ +/// Add CORS headers to `reply` only if `allow_origin.is_some()`. +pub fn maybe_cors( + reply: T, + allow_origin: Option<&String>, +) -> Box { + if let Some(allow_origin) = allow_origin { + Box::new(warp::reply::with_header( + reply, + "Access-Control-Allow-Origin", + allow_origin, + )) + } else { + Box::new(reply) + } +} diff --git a/consensus/fork_choice/src/fork_choice.rs b/consensus/fork_choice/src/fork_choice.rs index 99f998e5584..f6c43ae429a 100644 --- a/consensus/fork_choice/src/fork_choice.rs +++ b/consensus/fork_choice/src/fork_choice.rs @@ -4,7 +4,7 @@ use proto_array::{Block as ProtoBlock, ProtoArrayForkChoice}; use ssz_derive::{Decode, Encode}; use types::{ BeaconBlock, BeaconState, BeaconStateError, Checkpoint, Epoch, EthSpec, Hash256, - IndexedAttestation, Slot, + IndexedAttestation, RelativeEpoch, ShufflingId, Slot, }; use crate::ForkChoiceStore; @@ -240,10 +240,18 @@ where /// Instantiates `Self` from the genesis parameters. pub fn from_genesis( fc_store: T, + genesis_block_root: Hash256, genesis_block: &BeaconBlock, + genesis_state: &BeaconState, ) -> Result> { let finalized_block_slot = genesis_block.slot; let finalized_block_state_root = genesis_block.state_root; + let current_epoch_shuffling_id = + ShufflingId::new(genesis_block_root, genesis_state, RelativeEpoch::Current) + .map_err(Error::BeaconStateError)?; + let next_epoch_shuffling_id = + ShufflingId::new(genesis_block_root, genesis_state, RelativeEpoch::Next) + .map_err(Error::BeaconStateError)?; let proto_array = ProtoArrayForkChoice::new( finalized_block_slot, @@ -251,6 +259,8 @@ where fc_store.justified_checkpoint().epoch, fc_store.finalized_checkpoint().epoch, fc_store.finalized_checkpoint().root, + current_epoch_shuffling_id, + next_epoch_shuffling_id, )?; Ok(Self { @@ -534,6 +544,10 @@ where root: block_root, parent_root: Some(block.parent_root), target_root, + current_epoch_shuffling_id: ShufflingId::new(block_root, state, RelativeEpoch::Current) + .map_err(Error::BeaconStateError)?, + next_epoch_shuffling_id: ShufflingId::new(block_root, state, RelativeEpoch::Next) + .map_err(Error::BeaconStateError)?, state_root: block.state_root, justified_epoch: state.current_justified_checkpoint.epoch, finalized_epoch: state.finalized_checkpoint.epoch, diff --git a/consensus/fork_choice/src/lib.rs b/consensus/fork_choice/src/lib.rs index 78c7534cde9..7b508afd49c 100644 --- a/consensus/fork_choice/src/lib.rs +++ b/consensus/fork_choice/src/lib.rs @@ -6,3 +6,4 @@ pub use crate::fork_choice::{ SAFE_SLOTS_TO_UPDATE_JUSTIFIED, }; pub use fork_choice_store::ForkChoiceStore; +pub use proto_array::Block as ProtoBlock; diff --git a/consensus/fork_choice/tests/tests.rs b/consensus/fork_choice/tests/tests.rs index ffa9cbe6bd4..86fbbd8ec9e 100644 --- a/consensus/fork_choice/tests/tests.rs +++ b/consensus/fork_choice/tests/tests.rs @@ -351,7 +351,7 @@ impl ForkChoiceTest { let mut verified_attestation = self .harness .chain - .verify_unaggregated_attestation_for_gossip(attestation, subnet_id) + .verify_unaggregated_attestation_for_gossip(attestation, Some(subnet_id)) .expect("precondition: should gossip verify attestation"); if let MutationDelay::Blocks(slots) = delay { diff --git a/consensus/proto_array/src/fork_choice_test_definition.rs b/consensus/proto_array/src/fork_choice_test_definition.rs index 6e1bd970b00..9cac0bafb10 100644 --- a/consensus/proto_array/src/fork_choice_test_definition.rs +++ b/consensus/proto_array/src/fork_choice_test_definition.rs @@ -4,7 +4,7 @@ mod votes; use crate::proto_array_fork_choice::{Block, ProtoArrayForkChoice}; use serde_derive::{Deserialize, Serialize}; -use types::{Epoch, Hash256, Slot}; +use types::{Epoch, Hash256, ShufflingId, Slot}; pub use ffg_updates::*; pub use no_votes::*; @@ -55,12 +55,15 @@ pub struct ForkChoiceTestDefinition { impl ForkChoiceTestDefinition { pub fn run(self) { + let junk_shuffling_id = ShufflingId::from_components(Epoch::new(0), Hash256::zero()); let mut fork_choice = ProtoArrayForkChoice::new( self.finalized_block_slot, Hash256::zero(), self.justified_epoch, self.finalized_epoch, self.finalized_root, + junk_shuffling_id.clone(), + junk_shuffling_id, ) .expect("should create fork choice struct"); @@ -125,6 +128,14 @@ impl ForkChoiceTestDefinition { parent_root: Some(parent_root), state_root: Hash256::zero(), target_root: Hash256::zero(), + current_epoch_shuffling_id: ShufflingId::from_components( + Epoch::new(0), + Hash256::zero(), + ), + next_epoch_shuffling_id: ShufflingId::from_components( + Epoch::new(0), + Hash256::zero(), + ), justified_epoch, finalized_epoch, }; diff --git a/consensus/proto_array/src/proto_array.rs b/consensus/proto_array/src/proto_array.rs index 18db8d340ce..c89a96628a7 100644 --- a/consensus/proto_array/src/proto_array.rs +++ b/consensus/proto_array/src/proto_array.rs @@ -2,7 +2,7 @@ use crate::{error::Error, Block}; use serde_derive::{Deserialize, Serialize}; use ssz_derive::{Decode, Encode}; use std::collections::HashMap; -use types::{Epoch, Hash256, Slot}; +use types::{Epoch, Hash256, ShufflingId, Slot}; #[derive(Clone, PartialEq, Debug, Encode, Decode, Serialize, Deserialize)] pub struct ProtoNode { @@ -18,6 +18,8 @@ pub struct ProtoNode { /// The `target_root` is not necessary for `ProtoArray` either, it also just exists for upstream /// components (namely fork choice attestation verification). pub target_root: Hash256, + pub current_epoch_shuffling_id: ShufflingId, + pub next_epoch_shuffling_id: ShufflingId, pub root: Hash256, pub parent: Option, pub justified_epoch: Epoch, @@ -142,6 +144,8 @@ impl ProtoArray { slot: block.slot, root: block.root, target_root: block.target_root, + current_epoch_shuffling_id: block.current_epoch_shuffling_id, + next_epoch_shuffling_id: block.next_epoch_shuffling_id, state_root: block.state_root, parent: block .parent_root diff --git a/consensus/proto_array/src/proto_array_fork_choice.rs b/consensus/proto_array/src/proto_array_fork_choice.rs index 451f3999313..e4cf5bbc67b 100644 --- a/consensus/proto_array/src/proto_array_fork_choice.rs +++ b/consensus/proto_array/src/proto_array_fork_choice.rs @@ -4,7 +4,7 @@ use crate::ssz_container::SszContainer; use ssz::{Decode, Encode}; use ssz_derive::{Decode, Encode}; use std::collections::HashMap; -use types::{Epoch, Hash256, Slot}; +use types::{Epoch, Hash256, ShufflingId, Slot}; pub const DEFAULT_PRUNE_THRESHOLD: usize = 256; @@ -25,6 +25,8 @@ pub struct Block { pub parent_root: Option, pub state_root: Hash256, pub target_root: Hash256, + pub current_epoch_shuffling_id: ShufflingId, + pub next_epoch_shuffling_id: ShufflingId, pub justified_epoch: Epoch, pub finalized_epoch: Epoch, } @@ -70,6 +72,8 @@ impl ProtoArrayForkChoice { justified_epoch: Epoch, finalized_epoch: Epoch, finalized_root: Hash256, + current_epoch_shuffling_id: ShufflingId, + next_epoch_shuffling_id: ShufflingId, ) -> Result { let mut proto_array = ProtoArray { prune_threshold: DEFAULT_PRUNE_THRESHOLD, @@ -87,6 +91,8 @@ impl ProtoArrayForkChoice { // We are using the finalized_root as the target_root, since it always lies on an // epoch boundary. target_root: finalized_root, + current_epoch_shuffling_id, + next_epoch_shuffling_id, justified_epoch, finalized_epoch, }; @@ -194,6 +200,8 @@ impl ProtoArrayForkChoice { parent_root, state_root: block.state_root, target_root: block.target_root, + current_epoch_shuffling_id: block.current_epoch_shuffling_id.clone(), + next_epoch_shuffling_id: block.next_epoch_shuffling_id.clone(), justified_epoch: block.justified_epoch, finalized_epoch: block.finalized_epoch, }) @@ -341,6 +349,7 @@ mod test_compute_deltas { let finalized_desc = Hash256::from_low_u64_be(2); let not_finalized_desc = Hash256::from_low_u64_be(3); let unknown = Hash256::from_low_u64_be(4); + let junk_shuffling_id = ShufflingId::from_components(Epoch::new(0), Hash256::zero()); let mut fc = ProtoArrayForkChoice::new( genesis_slot, @@ -348,6 +357,8 @@ mod test_compute_deltas { genesis_epoch, genesis_epoch, finalized_root, + junk_shuffling_id.clone(), + junk_shuffling_id.clone(), ) .unwrap(); @@ -359,6 +370,8 @@ mod test_compute_deltas { parent_root: Some(finalized_root), state_root, target_root: finalized_root, + current_epoch_shuffling_id: junk_shuffling_id.clone(), + next_epoch_shuffling_id: junk_shuffling_id.clone(), justified_epoch: genesis_epoch, finalized_epoch: genesis_epoch, }) @@ -372,6 +385,8 @@ mod test_compute_deltas { parent_root: None, state_root, target_root: finalized_root, + current_epoch_shuffling_id: junk_shuffling_id.clone(), + next_epoch_shuffling_id: junk_shuffling_id.clone(), justified_epoch: genesis_epoch, finalized_epoch: genesis_epoch, }) diff --git a/consensus/serde_hex/Cargo.toml b/consensus/serde_hex/Cargo.toml deleted file mode 100644 index 2df5ff02a08..00000000000 --- a/consensus/serde_hex/Cargo.toml +++ /dev/null @@ -1,9 +0,0 @@ -[package] -name = "serde_hex" -version = "0.2.0" -authors = ["Paul Hauner "] -edition = "2018" - -[dependencies] -serde = "1.0.110" -hex = "0.4.2" diff --git a/consensus/serde_utils/Cargo.toml b/consensus/serde_utils/Cargo.toml index 1fb35736baf..8c0013562c1 100644 --- a/consensus/serde_utils/Cargo.toml +++ b/consensus/serde_utils/Cargo.toml @@ -7,6 +7,7 @@ edition = "2018" [dependencies] serde = { version = "1.0.110", features = ["derive"] } serde_derive = "1.0.110" +hex = "0.4.2" [dev-dependencies] serde_json = "1.0.52" diff --git a/consensus/serde_utils/src/bytes_4_hex.rs b/consensus/serde_utils/src/bytes_4_hex.rs new file mode 100644 index 00000000000..e057d1a1288 --- /dev/null +++ b/consensus/serde_utils/src/bytes_4_hex.rs @@ -0,0 +1,38 @@ +//! Formats `[u8; 4]` as a 0x-prefixed hex string. +//! +//! E.g., `[0, 1, 2, 3]` serializes as `"0x00010203"`. + +use crate::hex::PrefixedHexVisitor; +use serde::de::Error; +use serde::{Deserializer, Serializer}; + +const BYTES_LEN: usize = 4; + +pub fn serialize(bytes: &[u8; BYTES_LEN], serializer: S) -> Result +where + S: Serializer, +{ + let mut hex_string: String = "0x".to_string(); + hex_string.push_str(&hex::encode(&bytes)); + + serializer.serialize_str(&hex_string) +} + +pub fn deserialize<'de, D>(deserializer: D) -> Result<[u8; BYTES_LEN], D::Error> +where + D: Deserializer<'de>, +{ + let decoded = deserializer.deserialize_str(PrefixedHexVisitor)?; + + if decoded.len() != BYTES_LEN { + return Err(D::Error::custom(format!( + "expected {} bytes for array, got {}", + BYTES_LEN, + decoded.len() + ))); + } + + let mut array = [0; BYTES_LEN]; + array.copy_from_slice(&decoded); + Ok(array) +} diff --git a/consensus/serde_hex/src/lib.rs b/consensus/serde_utils/src/hex.rs similarity index 81% rename from consensus/serde_hex/src/lib.rs rename to consensus/serde_utils/src/hex.rs index db84222757d..79dfaa506b8 100644 --- a/consensus/serde_hex/src/lib.rs +++ b/consensus/serde_utils/src/hex.rs @@ -1,6 +1,9 @@ +//! Provides utilities for parsing 0x-prefixed hex strings. + use serde::de::{self, Visitor}; use std::fmt; +/// Encode `data` as a 0x-prefixed hex string. pub fn encode>(data: T) -> String { let hex = hex::encode(data); let mut s = "0x".to_string(); @@ -8,6 +11,15 @@ pub fn encode>(data: T) -> String { s } +/// Decode `data` from a 0x-prefixed hex string. +pub fn decode(s: &str) -> Result, String> { + if s.starts_with("0x") { + hex::decode(&s[2..]).map_err(|e| format!("invalid hex: {:?}", e)) + } else { + Err("hex must have 0x prefix".to_string()) + } +} + pub struct PrefixedHexVisitor; impl<'de> Visitor<'de> for PrefixedHexVisitor { diff --git a/consensus/serde_utils/src/lib.rs b/consensus/serde_utils/src/lib.rs index df2b44b6243..0016e67a3db 100644 --- a/consensus/serde_utils/src/lib.rs +++ b/consensus/serde_utils/src/lib.rs @@ -1,2 +1,9 @@ -pub mod quoted_u64; +mod quoted_int; + +pub mod bytes_4_hex; +pub mod hex; pub mod quoted_u64_vec; +pub mod u32_hex; +pub mod u8_hex; + +pub use quoted_int::{quoted_u32, quoted_u64, quoted_u8}; diff --git a/consensus/serde_utils/src/quoted_int.rs b/consensus/serde_utils/src/quoted_int.rs new file mode 100644 index 00000000000..24edf1ebee2 --- /dev/null +++ b/consensus/serde_utils/src/quoted_int.rs @@ -0,0 +1,144 @@ +//! Formats some integer types using quotes. +//! +//! E.g., `1` serializes as `"1"`. +//! +//! Quotes can be optional during decoding. + +use serde::{Deserializer, Serializer}; +use serde_derive::{Deserialize, Serialize}; +use std::convert::TryFrom; +use std::marker::PhantomData; + +macro_rules! define_mod { + ($int: ty, $visit_fn: ident) => { + /// Serde support for deserializing quoted integers. + /// + /// Configurable so that quotes are either required or optional. + pub struct QuotedIntVisitor { + require_quotes: bool, + _phantom: PhantomData, + } + + impl<'a, T> serde::de::Visitor<'a> for QuotedIntVisitor + where + T: From<$int> + Into<$int> + Copy + TryFrom, + { + type Value = T; + + fn expecting(&self, formatter: &mut std::fmt::Formatter) -> std::fmt::Result { + if self.require_quotes { + write!(formatter, "a quoted integer") + } else { + write!(formatter, "a quoted or unquoted integer") + } + } + + fn visit_str(self, s: &str) -> Result + where + E: serde::de::Error, + { + s.parse::<$int>() + .map(T::from) + .map_err(serde::de::Error::custom) + } + + fn visit_u64(self, v: u64) -> Result + where + E: serde::de::Error, + { + if self.require_quotes { + Err(serde::de::Error::custom( + "received unquoted integer when quotes are required", + )) + } else { + T::try_from(v).map_err(|_| serde::de::Error::custom("invalid integer")) + } + } + } + + /// Wrapper type for requiring quotes on a `$int`-like type. + /// + /// Unlike using `serde(with = "quoted_$int::require_quotes")` this is composable, and can be nested + /// inside types like `Option`, `Result` and `Vec`. + #[derive(Debug, Clone, Copy, PartialEq, Eq, Hash, Deserialize, Serialize)] + #[serde(transparent)] + pub struct Quoted + where + T: From<$int> + Into<$int> + Copy + TryFrom, + { + #[serde(with = "require_quotes")] + pub value: T, + } + + /// Serialize with quotes. + pub fn serialize(value: &T, serializer: S) -> Result + where + S: Serializer, + T: From<$int> + Into<$int> + Copy, + { + let v: $int = (*value).into(); + serializer.serialize_str(&format!("{}", v)) + } + + /// Deserialize with or without quotes. + pub fn deserialize<'de, D, T>(deserializer: D) -> Result + where + D: Deserializer<'de>, + T: From<$int> + Into<$int> + Copy + TryFrom, + { + deserializer.deserialize_any(QuotedIntVisitor { + require_quotes: false, + _phantom: PhantomData, + }) + } + + /// Requires quotes when deserializing. + /// + /// Usage: `#[serde(with = "quoted_u64::require_quotes")]`. + pub mod require_quotes { + pub use super::serialize; + use super::*; + + pub fn deserialize<'de, D, T>(deserializer: D) -> Result + where + D: Deserializer<'de>, + T: From<$int> + Into<$int> + Copy + TryFrom, + { + deserializer.deserialize_any(QuotedIntVisitor { + require_quotes: true, + _phantom: PhantomData, + }) + } + } + + #[cfg(test)] + mod test { + use super::*; + + #[test] + fn require_quotes() { + let x = serde_json::from_str::>("\"8\"").unwrap(); + assert_eq!(x.value, 8); + serde_json::from_str::>("8").unwrap_err(); + } + } + }; +} + +pub mod quoted_u8 { + use super::*; + + define_mod!(u8, visit_u8); +} + +pub mod quoted_u32 { + use super::*; + + define_mod!(u32, visit_u32); +} + +pub mod quoted_u64 { + use super::*; + + define_mod!(u64, visit_u64); +} diff --git a/consensus/serde_utils/src/quoted_u64.rs b/consensus/serde_utils/src/quoted_u64.rs deleted file mode 100644 index 2e73a104f19..00000000000 --- a/consensus/serde_utils/src/quoted_u64.rs +++ /dev/null @@ -1,115 +0,0 @@ -use serde::{Deserializer, Serializer}; -use serde_derive::{Deserialize, Serialize}; -use std::marker::PhantomData; - -/// Serde support for deserializing quoted integers. -/// -/// Configurable so that quotes are either required or optional. -pub struct QuotedIntVisitor { - require_quotes: bool, - _phantom: PhantomData, -} - -impl<'a, T> serde::de::Visitor<'a> for QuotedIntVisitor -where - T: From + Into + Copy, -{ - type Value = T; - - fn expecting(&self, formatter: &mut std::fmt::Formatter) -> std::fmt::Result { - if self.require_quotes { - write!(formatter, "a quoted integer") - } else { - write!(formatter, "a quoted or unquoted integer") - } - } - - fn visit_str(self, s: &str) -> Result - where - E: serde::de::Error, - { - s.parse::() - .map(T::from) - .map_err(serde::de::Error::custom) - } - - fn visit_u64(self, v: u64) -> Result - where - E: serde::de::Error, - { - if self.require_quotes { - Err(serde::de::Error::custom( - "received unquoted integer when quotes are required", - )) - } else { - Ok(T::from(v)) - } - } -} - -/// Wrapper type for requiring quotes on a `u64`-like type. -/// -/// Unlike using `serde(with = "quoted_u64::require_quotes")` this is composable, and can be nested -/// inside types like `Option`, `Result` and `Vec`. -#[derive(Debug, Clone, Copy, PartialEq, Eq, Hash, Deserialize, Serialize)] -#[serde(transparent)] -pub struct Quoted -where - T: From + Into + Copy, -{ - #[serde(with = "require_quotes")] - pub value: T, -} - -/// Serialize with quotes. -pub fn serialize(value: &T, serializer: S) -> Result -where - S: Serializer, - T: From + Into + Copy, -{ - let v: u64 = (*value).into(); - serializer.serialize_str(&format!("{}", v)) -} - -/// Deserialize with or without quotes. -pub fn deserialize<'de, D, T>(deserializer: D) -> Result -where - D: Deserializer<'de>, - T: From + Into + Copy, -{ - deserializer.deserialize_any(QuotedIntVisitor { - require_quotes: false, - _phantom: PhantomData, - }) -} - -/// Requires quotes when deserializing. -/// -/// Usage: `#[serde(with = "quoted_u64::require_quotes")]`. -pub mod require_quotes { - pub use super::serialize; - use super::*; - - pub fn deserialize<'de, D, T>(deserializer: D) -> Result - where - D: Deserializer<'de>, - T: From + Into + Copy, - { - deserializer.deserialize_any(QuotedIntVisitor { - require_quotes: true, - _phantom: PhantomData, - }) - } -} - -#[cfg(test)] -mod test { - use super::*; - - #[test] - fn require_quotes() { - let x = serde_json::from_str::>("\"8\"").unwrap(); - assert_eq!(x.value, 8); - serde_json::from_str::>("8").unwrap_err(); - } -} diff --git a/consensus/serde_utils/src/quoted_u64_vec.rs b/consensus/serde_utils/src/quoted_u64_vec.rs index c5badee5012..f124c989092 100644 --- a/consensus/serde_utils/src/quoted_u64_vec.rs +++ b/consensus/serde_utils/src/quoted_u64_vec.rs @@ -1,3 +1,9 @@ +//! Formats `Vec` using quotes. +//! +//! E.g., `vec![0, 1, 2]` serializes as `["0", "1", "2"]`. +//! +//! Quotes can be optional during decoding. + use serde::ser::SerializeSeq; use serde::{Deserializer, Serializer}; use serde_derive::{Deserialize, Serialize}; @@ -6,7 +12,7 @@ use serde_derive::{Deserialize, Serialize}; #[serde(transparent)] pub struct QuotedIntWrapper { #[serde(with = "crate::quoted_u64")] - int: u64, + pub int: u64, } pub struct QuotedIntVecVisitor; diff --git a/consensus/serde_utils/src/u32_hex.rs b/consensus/serde_utils/src/u32_hex.rs new file mode 100644 index 00000000000..c1ab3537b2a --- /dev/null +++ b/consensus/serde_utils/src/u32_hex.rs @@ -0,0 +1,21 @@ +//! Formats `u32` as a 0x-prefixed, little-endian hex string. +//! +//! E.g., `0` serializes as `"0x00000000"`. + +use crate::bytes_4_hex; +use serde::{Deserializer, Serializer}; + +pub fn serialize(num: &u32, serializer: S) -> Result +where + S: Serializer, +{ + let hex = format!("0x{}", hex::encode(num.to_le_bytes())); + serializer.serialize_str(&hex) +} + +pub fn deserialize<'de, D>(deserializer: D) -> Result +where + D: Deserializer<'de>, +{ + bytes_4_hex::deserialize(deserializer).map(u32::from_le_bytes) +} diff --git a/consensus/serde_utils/src/u8_hex.rs b/consensus/serde_utils/src/u8_hex.rs new file mode 100644 index 00000000000..8083e1d120b --- /dev/null +++ b/consensus/serde_utils/src/u8_hex.rs @@ -0,0 +1,29 @@ +//! Formats `u8` as a 0x-prefixed hex string. +//! +//! E.g., `0` serializes as `"0x00"`. + +use crate::hex::PrefixedHexVisitor; +use serde::de::Error; +use serde::{Deserializer, Serializer}; + +pub fn serialize(byte: &u8, serializer: S) -> Result +where + S: Serializer, +{ + let hex = format!("0x{}", hex::encode([*byte])); + serializer.serialize_str(&hex) +} + +pub fn deserialize<'de, D>(deserializer: D) -> Result +where + D: Deserializer<'de>, +{ + let bytes = deserializer.deserialize_str(PrefixedHexVisitor)?; + if bytes.len() != 1 { + return Err(D::Error::custom(format!( + "expected 1 byte for u8, got {}", + bytes.len() + ))); + } + Ok(bytes[0]) +} diff --git a/consensus/ssz_types/Cargo.toml b/consensus/ssz_types/Cargo.toml index 144b3ce31fd..ca6a5adbe81 100644 --- a/consensus/ssz_types/Cargo.toml +++ b/consensus/ssz_types/Cargo.toml @@ -11,7 +11,7 @@ name = "ssz_types" tree_hash = "0.1.0" serde = "1.0.110" serde_derive = "1.0.110" -serde_hex = { path = "../serde_hex" } +serde_utils = { path = "../serde_utils" } eth2_ssz = "0.1.2" typenum = "1.12.0" arbitrary = { version = "0.4.4", features = ["derive"], optional = true } diff --git a/consensus/ssz_types/src/bitfield.rs b/consensus/ssz_types/src/bitfield.rs index 1b6dce3ec0f..09fa9fc2df4 100644 --- a/consensus/ssz_types/src/bitfield.rs +++ b/consensus/ssz_types/src/bitfield.rs @@ -3,7 +3,7 @@ use crate::Error; use core::marker::PhantomData; use serde::de::{Deserialize, Deserializer}; use serde::ser::{Serialize, Serializer}; -use serde_hex::{encode as hex_encode, PrefixedHexVisitor}; +use serde_utils::hex::{encode as hex_encode, PrefixedHexVisitor}; use ssz::{Decode, Encode}; use tree_hash::Hash256; use typenum::Unsigned; diff --git a/consensus/types/Cargo.toml b/consensus/types/Cargo.toml index 80b4007b973..c3a5cd90d5d 100644 --- a/consensus/types/Cargo.toml +++ b/consensus/types/Cargo.toml @@ -39,6 +39,8 @@ tempfile = "3.1.0" derivative = "2.1.1" rusqlite = { version = "0.23.1", features = ["bundled"], optional = true } arbitrary = { version = "0.4.4", features = ["derive"], optional = true } +serde_utils = { path = "../serde_utils" } +regex = "1.3.9" [dev-dependencies] serde_json = "1.0.52" diff --git a/consensus/types/src/aggregate_and_proof.rs b/consensus/types/src/aggregate_and_proof.rs index 737c891c9fb..52871226107 100644 --- a/consensus/types/src/aggregate_and_proof.rs +++ b/consensus/types/src/aggregate_and_proof.rs @@ -16,6 +16,7 @@ use tree_hash_derive::TreeHash; #[serde(bound = "T: EthSpec")] pub struct AggregateAndProof { /// The index of the validator that created the attestation. + #[serde(with = "serde_utils::quoted_u64")] pub aggregator_index: u64, /// The aggregate attestation. pub aggregate: Attestation, diff --git a/consensus/types/src/attestation_data.rs b/consensus/types/src/attestation_data.rs index 67fb280025c..07fa529e0ff 100644 --- a/consensus/types/src/attestation_data.rs +++ b/consensus/types/src/attestation_data.rs @@ -26,6 +26,7 @@ use tree_hash_derive::TreeHash; )] pub struct AttestationData { pub slot: Slot, + #[serde(with = "serde_utils::quoted_u64")] pub index: u64, // LMD GHOST vote diff --git a/consensus/types/src/attestation_duty.rs b/consensus/types/src/attestation_duty.rs index c32e4683e18..613d7fd1c88 100644 --- a/consensus/types/src/attestation_duty.rs +++ b/consensus/types/src/attestation_duty.rs @@ -12,4 +12,7 @@ pub struct AttestationDuty { pub committee_position: usize, /// The total number of attesters in the committee. pub committee_len: usize, + /// The committee count at `attestation_slot`. + #[serde(with = "serde_utils::quoted_u64")] + pub committees_at_slot: u64, } diff --git a/consensus/types/src/beacon_block.rs b/consensus/types/src/beacon_block.rs index eeb10458bfa..d3a9160709c 100644 --- a/consensus/types/src/beacon_block.rs +++ b/consensus/types/src/beacon_block.rs @@ -16,6 +16,7 @@ use tree_hash_derive::TreeHash; #[serde(bound = "T: EthSpec")] pub struct BeaconBlock { pub slot: Slot, + #[serde(with = "serde_utils::quoted_u64")] pub proposer_index: u64, pub parent_root: Hash256, pub state_root: Hash256, diff --git a/consensus/types/src/beacon_block_body.rs b/consensus/types/src/beacon_block_body.rs index 489c5bc9d77..ef28307edcc 100644 --- a/consensus/types/src/beacon_block_body.rs +++ b/consensus/types/src/beacon_block_body.rs @@ -1,5 +1,4 @@ use crate::test_utils::TestRandom; -use crate::utils::{graffiti_from_hex_str, graffiti_to_hex_str, Graffiti}; use crate::*; use serde_derive::{Deserialize, Serialize}; @@ -17,10 +16,6 @@ use tree_hash_derive::TreeHash; pub struct BeaconBlockBody { pub randao_reveal: Signature, pub eth1_data: Eth1Data, - #[serde( - serialize_with = "graffiti_to_hex_str", - deserialize_with = "graffiti_from_hex_str" - )] pub graffiti: Graffiti, pub proposer_slashings: VariableList, pub attester_slashings: VariableList, T::MaxAttesterSlashings>, diff --git a/consensus/types/src/beacon_block_header.rs b/consensus/types/src/beacon_block_header.rs index 04a20e56d3f..708c0e16fe7 100644 --- a/consensus/types/src/beacon_block_header.rs +++ b/consensus/types/src/beacon_block_header.rs @@ -14,6 +14,7 @@ use tree_hash_derive::TreeHash; #[derive(Debug, PartialEq, Clone, Serialize, Deserialize, Encode, Decode, TreeHash, TestRandom)] pub struct BeaconBlockHeader { pub slot: Slot, + #[serde(with = "serde_utils::quoted_u64")] pub proposer_index: u64, pub parent_root: Hash256, pub state_root: Hash256, diff --git a/consensus/types/src/beacon_state.rs b/consensus/types/src/beacon_state.rs index a2d923da9d3..25cb85ce8cc 100644 --- a/consensus/types/src/beacon_state.rs +++ b/consensus/types/src/beacon_state.rs @@ -157,6 +157,7 @@ where T: EthSpec, { // Versioning + #[serde(with = "serde_utils::quoted_u64")] pub genesis_time: u64, pub genesis_validators_root: Hash256, pub slot: Slot, @@ -173,6 +174,7 @@ where // Ethereum 1.0 chain data pub eth1_data: Eth1Data, pub eth1_data_votes: VariableList, + #[serde(with = "serde_utils::quoted_u64")] pub eth1_deposit_index: u64, // Registry @@ -913,6 +915,13 @@ impl BeaconState { self.exit_cache = ExitCache::default(); } + /// Returns `true` if the committee cache for `relative_epoch` is built and ready to use. + pub fn committee_cache_is_initialized(&self, relative_epoch: RelativeEpoch) -> bool { + let i = Self::committee_cache_index(relative_epoch); + + self.committee_caches[i].is_initialized_at(relative_epoch.into_epoch(self.current_epoch())) + } + /// Build an epoch cache, unless it is has already been built. pub fn build_committee_cache( &mut self, diff --git a/consensus/types/src/beacon_state/committee_cache.rs b/consensus/types/src/beacon_state/committee_cache.rs index 6ee24cd2bb2..728c9cf026d 100644 --- a/consensus/types/src/beacon_state/committee_cache.rs +++ b/consensus/types/src/beacon_state/committee_cache.rs @@ -186,6 +186,7 @@ impl CommitteeCache { index, committee_position, committee_len, + committees_at_slot: self.committees_per_slot(), }) }) } diff --git a/consensus/types/src/chain_spec.rs b/consensus/types/src/chain_spec.rs index c621acb81b8..7327895eeef 100644 --- a/consensus/types/src/chain_spec.rs +++ b/consensus/types/src/chain_spec.rs @@ -4,10 +4,6 @@ use serde_derive::{Deserialize, Serialize}; use std::fs::File; use std::path::Path; use tree_hash::TreeHash; -use utils::{ - fork_from_hex_str, fork_to_hex_str, u32_from_hex_str, u32_to_hex_str, u8_from_hex_str, - u8_to_hex_str, -}; /// Each of the BLS signature domains. /// @@ -65,12 +61,9 @@ pub struct ChainSpec { /* * Initial Values */ - #[serde( - serialize_with = "fork_to_hex_str", - deserialize_with = "fork_from_hex_str" - )] + #[serde(with = "serde_utils::bytes_4_hex")] pub genesis_fork_version: [u8; 4], - #[serde(deserialize_with = "u8_from_hex_str", serialize_with = "u8_to_hex_str")] + #[serde(with = "serde_utils::u8_hex")] pub bls_withdrawal_prefix_byte: u8, /* @@ -115,6 +108,7 @@ pub struct ChainSpec { */ pub eth1_follow_distance: u64, pub seconds_per_eth1_block: u64, + pub deposit_contract_address: Address, /* * Networking @@ -326,6 +320,9 @@ impl ChainSpec { */ eth1_follow_distance: 1_024, seconds_per_eth1_block: 14, + deposit_contract_address: "1234567890123456789012345678901234567890" + .parse() + .expect("chain spec deposit contract address"), /* * Network specific @@ -448,104 +445,127 @@ pub struct YamlConfig { #[serde(default)] config_name: String, // ChainSpec - max_committees_per_slot: usize, - target_committee_size: usize, + #[serde(with = "serde_utils::quoted_u64")] + max_committees_per_slot: u64, + #[serde(with = "serde_utils::quoted_u64")] + target_committee_size: u64, + #[serde(with = "serde_utils::quoted_u64")] min_per_epoch_churn_limit: u64, + #[serde(with = "serde_utils::quoted_u64")] churn_limit_quotient: u64, + #[serde(with = "serde_utils::quoted_u8")] shuffle_round_count: u8, + #[serde(with = "serde_utils::quoted_u64")] min_genesis_active_validator_count: u64, + #[serde(with = "serde_utils::quoted_u64")] min_genesis_time: u64, + #[serde(with = "serde_utils::quoted_u64")] genesis_delay: u64, + #[serde(with = "serde_utils::quoted_u64")] min_deposit_amount: u64, + #[serde(with = "serde_utils::quoted_u64")] max_effective_balance: u64, + #[serde(with = "serde_utils::quoted_u64")] ejection_balance: u64, + #[serde(with = "serde_utils::quoted_u64")] effective_balance_increment: u64, + #[serde(with = "serde_utils::quoted_u64")] hysteresis_quotient: u64, + #[serde(with = "serde_utils::quoted_u64")] 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( - serialize_with = "fork_to_hex_str", - deserialize_with = "fork_from_hex_str" - )] + #[serde(with = "serde_utils::bytes_4_hex")] genesis_fork_version: [u8; 4], - #[serde(deserialize_with = "u8_from_hex_str", serialize_with = "u8_to_hex_str")] + #[serde(with = "serde_utils::u8_hex")] bls_withdrawal_prefix: u8, + #[serde(with = "serde_utils::quoted_u64")] seconds_per_slot: u64, + #[serde(with = "serde_utils::quoted_u64")] min_attestation_inclusion_delay: u64, + #[serde(with = "serde_utils::quoted_u64")] min_seed_lookahead: u64, + #[serde(with = "serde_utils::quoted_u64")] max_seed_lookahead: u64, + #[serde(with = "serde_utils::quoted_u64")] min_epochs_to_inactivity_penalty: u64, + #[serde(with = "serde_utils::quoted_u64")] min_validator_withdrawability_delay: u64, + #[serde(with = "serde_utils::quoted_u64")] shard_committee_period: u64, + #[serde(with = "serde_utils::quoted_u64")] base_reward_factor: u64, + #[serde(with = "serde_utils::quoted_u64")] whistleblower_reward_quotient: u64, + #[serde(with = "serde_utils::quoted_u64")] proposer_reward_quotient: u64, + #[serde(with = "serde_utils::quoted_u64")] inactivity_penalty_quotient: u64, + #[serde(with = "serde_utils::quoted_u64")] min_slashing_penalty_quotient: u64, + #[serde(with = "serde_utils::quoted_u64")] safe_slots_to_update_justified: u64, - #[serde( - deserialize_with = "u32_from_hex_str", - serialize_with = "u32_to_hex_str" - )] + #[serde(with = "serde_utils::u32_hex")] domain_beacon_proposer: u32, - #[serde( - deserialize_with = "u32_from_hex_str", - serialize_with = "u32_to_hex_str" - )] + #[serde(with = "serde_utils::u32_hex")] domain_beacon_attester: u32, - #[serde( - deserialize_with = "u32_from_hex_str", - serialize_with = "u32_to_hex_str" - )] + #[serde(with = "serde_utils::u32_hex")] domain_randao: u32, - #[serde( - deserialize_with = "u32_from_hex_str", - serialize_with = "u32_to_hex_str" - )] + #[serde(with = "serde_utils::u32_hex")] domain_deposit: u32, - #[serde( - deserialize_with = "u32_from_hex_str", - serialize_with = "u32_to_hex_str" - )] + #[serde(with = "serde_utils::u32_hex")] domain_voluntary_exit: u32, - #[serde( - deserialize_with = "u32_from_hex_str", - serialize_with = "u32_to_hex_str" - )] + #[serde(with = "serde_utils::u32_hex")] domain_selection_proof: u32, - #[serde( - deserialize_with = "u32_from_hex_str", - serialize_with = "u32_to_hex_str" - )] + #[serde(with = "serde_utils::u32_hex")] domain_aggregate_and_proof: u32, // EthSpec + #[serde(with = "serde_utils::quoted_u32")] max_validators_per_committee: u32, + #[serde(with = "serde_utils::quoted_u64")] slots_per_epoch: u64, + #[serde(with = "serde_utils::quoted_u64")] epochs_per_eth1_voting_period: u64, - slots_per_historical_root: usize, - epochs_per_historical_vector: usize, - epochs_per_slashings_vector: usize, + #[serde(with = "serde_utils::quoted_u64")] + slots_per_historical_root: u64, + #[serde(with = "serde_utils::quoted_u64")] + epochs_per_historical_vector: u64, + #[serde(with = "serde_utils::quoted_u64")] + epochs_per_slashings_vector: u64, + #[serde(with = "serde_utils::quoted_u64")] historical_roots_limit: u64, + #[serde(with = "serde_utils::quoted_u64")] validator_registry_limit: u64, + #[serde(with = "serde_utils::quoted_u32")] max_proposer_slashings: u32, + #[serde(with = "serde_utils::quoted_u32")] max_attester_slashings: u32, + #[serde(with = "serde_utils::quoted_u32")] max_attestations: u32, + #[serde(with = "serde_utils::quoted_u32")] max_deposits: u32, + #[serde(with = "serde_utils::quoted_u32")] max_voluntary_exits: u32, // Validator + #[serde(with = "serde_utils::quoted_u64")] eth1_follow_distance: u64, + #[serde(with = "serde_utils::quoted_u64")] target_aggregators_per_committee: u64, + #[serde(with = "serde_utils::quoted_u64")] random_subnets_per_validator: u64, + #[serde(with = "serde_utils::quoted_u64")] 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)` deposit_chain_id: u64, deposit_network_id: u64, - deposit_contract_address: String, */ } @@ -568,8 +588,8 @@ impl YamlConfig { Self { config_name: T::spec_name().to_string(), // ChainSpec - max_committees_per_slot: spec.max_committees_per_slot, - target_committee_size: spec.target_committee_size, + max_committees_per_slot: spec.max_committees_per_slot as u64, + target_committee_size: spec.target_committee_size as u64, min_per_epoch_churn_limit: spec.min_per_epoch_churn_limit, churn_limit_quotient: spec.churn_limit_quotient, shuffle_round_count: spec.shuffle_round_count, @@ -611,9 +631,9 @@ impl YamlConfig { max_validators_per_committee: T::MaxValidatorsPerCommittee::to_u32(), slots_per_epoch: T::slots_per_epoch(), epochs_per_eth1_voting_period: T::EpochsPerEth1VotingPeriod::to_u64(), - slots_per_historical_root: T::slots_per_historical_root(), - epochs_per_historical_vector: T::epochs_per_historical_vector(), - epochs_per_slashings_vector: T::EpochsPerSlashingsVector::to_usize(), + slots_per_historical_root: T::slots_per_historical_root() as u64, + epochs_per_historical_vector: T::epochs_per_historical_vector() as u64, + epochs_per_slashings_vector: T::EpochsPerSlashingsVector::to_u64(), historical_roots_limit: T::HistoricalRootsLimit::to_u64(), validator_registry_limit: T::ValidatorRegistryLimit::to_u64(), max_proposer_slashings: T::MaxProposerSlashings::to_u32(), @@ -628,6 +648,7 @@ 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_contract_address: spec.deposit_contract_address, } } @@ -643,9 +664,9 @@ impl YamlConfig { if self.max_validators_per_committee != T::MaxValidatorsPerCommittee::to_u32() || self.slots_per_epoch != T::slots_per_epoch() || self.epochs_per_eth1_voting_period != T::EpochsPerEth1VotingPeriod::to_u64() - || self.slots_per_historical_root != T::slots_per_historical_root() - || self.epochs_per_historical_vector != T::epochs_per_historical_vector() - || self.epochs_per_slashings_vector != T::EpochsPerSlashingsVector::to_usize() + || self.slots_per_historical_root != T::slots_per_historical_root() as u64 + || self.epochs_per_historical_vector != T::epochs_per_historical_vector() as u64 + || self.epochs_per_slashings_vector != T::EpochsPerSlashingsVector::to_u64() || self.historical_roots_limit != T::HistoricalRootsLimit::to_u64() || self.validator_registry_limit != T::ValidatorRegistryLimit::to_u64() || self.max_proposer_slashings != T::MaxProposerSlashings::to_u32() @@ -662,8 +683,8 @@ impl YamlConfig { /* * Misc */ - max_committees_per_slot: self.max_committees_per_slot, - target_committee_size: self.target_committee_size, + max_committees_per_slot: self.max_committees_per_slot as usize, + target_committee_size: self.target_committee_size as usize, min_per_epoch_churn_limit: self.min_per_epoch_churn_limit, churn_limit_quotient: self.churn_limit_quotient, shuffle_round_count: self.shuffle_round_count, @@ -685,6 +706,7 @@ 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_contract_address: self.deposit_contract_address, /* * Gwei values */ diff --git a/consensus/types/src/deposit_data.rs b/consensus/types/src/deposit_data.rs index ce72c362e21..8e2050a0b83 100644 --- a/consensus/types/src/deposit_data.rs +++ b/consensus/types/src/deposit_data.rs @@ -15,6 +15,7 @@ use tree_hash_derive::TreeHash; pub struct DepositData { pub pubkey: PublicKeyBytes, pub withdrawal_credentials: Hash256, + #[serde(with = "serde_utils::quoted_u64")] pub amount: u64, pub signature: SignatureBytes, } diff --git a/consensus/types/src/deposit_message.rs b/consensus/types/src/deposit_message.rs index fe283a17f93..92f6b66bf7f 100644 --- a/consensus/types/src/deposit_message.rs +++ b/consensus/types/src/deposit_message.rs @@ -15,6 +15,7 @@ use tree_hash_derive::TreeHash; pub struct DepositMessage { pub pubkey: PublicKeyBytes, pub withdrawal_credentials: Hash256, + #[serde(with = "serde_utils::quoted_u64")] pub amount: u64, } diff --git a/consensus/types/src/enr_fork_id.rs b/consensus/types/src/enr_fork_id.rs index e10744368f6..008b7933fff 100644 --- a/consensus/types/src/enr_fork_id.rs +++ b/consensus/types/src/enr_fork_id.rs @@ -1,5 +1,4 @@ use crate::test_utils::TestRandom; -use crate::utils::{fork_from_hex_str, fork_to_hex_str}; use crate::Epoch; use serde_derive::{Deserialize, Serialize}; @@ -16,15 +15,9 @@ use tree_hash_derive::TreeHash; Debug, Clone, PartialEq, Default, Serialize, Deserialize, Encode, Decode, TreeHash, TestRandom, )] pub struct EnrForkId { - #[serde( - serialize_with = "fork_to_hex_str", - deserialize_with = "fork_from_hex_str" - )] + #[serde(with = "serde_utils::bytes_4_hex")] pub fork_digest: [u8; 4], - #[serde( - serialize_with = "fork_to_hex_str", - deserialize_with = "fork_from_hex_str" - )] + #[serde(with = "serde_utils::bytes_4_hex")] pub next_fork_version: [u8; 4], pub next_fork_epoch: Epoch, } diff --git a/consensus/types/src/eth1_data.rs b/consensus/types/src/eth1_data.rs index dcc1ea09819..e3b74cc491c 100644 --- a/consensus/types/src/eth1_data.rs +++ b/consensus/types/src/eth1_data.rs @@ -26,6 +26,7 @@ use tree_hash_derive::TreeHash; )] pub struct Eth1Data { pub deposit_root: Hash256, + #[serde(with = "serde_utils::quoted_u64")] pub deposit_count: u64, pub block_hash: Hash256, } diff --git a/consensus/types/src/fork.rs b/consensus/types/src/fork.rs index 8e95710c4ad..b129271ba0f 100644 --- a/consensus/types/src/fork.rs +++ b/consensus/types/src/fork.rs @@ -1,5 +1,4 @@ use crate::test_utils::TestRandom; -use crate::utils::{fork_from_hex_str, fork_to_hex_str}; use crate::Epoch; use serde_derive::{Deserialize, Serialize}; @@ -25,15 +24,9 @@ use tree_hash_derive::TreeHash; TestRandom, )] pub struct Fork { - #[serde( - serialize_with = "fork_to_hex_str", - deserialize_with = "fork_from_hex_str" - )] + #[serde(with = "serde_utils::bytes_4_hex")] pub previous_version: [u8; 4], - #[serde( - serialize_with = "fork_to_hex_str", - deserialize_with = "fork_from_hex_str" - )] + #[serde(with = "serde_utils::bytes_4_hex")] pub current_version: [u8; 4], pub epoch: Epoch, } diff --git a/consensus/types/src/fork_data.rs b/consensus/types/src/fork_data.rs index bad6f6219e2..092102f779e 100644 --- a/consensus/types/src/fork_data.rs +++ b/consensus/types/src/fork_data.rs @@ -1,5 +1,4 @@ use crate::test_utils::TestRandom; -use crate::utils::{fork_from_hex_str, fork_to_hex_str}; use crate::{Hash256, SignedRoot}; use serde_derive::{Deserialize, Serialize}; @@ -15,10 +14,7 @@ use tree_hash_derive::TreeHash; Debug, Clone, PartialEq, Default, Serialize, Deserialize, Encode, Decode, TreeHash, TestRandom, )] pub struct ForkData { - #[serde( - serialize_with = "fork_to_hex_str", - deserialize_with = "fork_from_hex_str" - )] + #[serde(with = "serde_utils::bytes_4_hex")] pub current_version: [u8; 4], pub genesis_validators_root: Hash256, } diff --git a/consensus/types/src/free_attestation.rs b/consensus/types/src/free_attestation.rs index 6215fb0cd7d..79bc149e43e 100644 --- a/consensus/types/src/free_attestation.rs +++ b/consensus/types/src/free_attestation.rs @@ -9,5 +9,6 @@ use serde_derive::Serialize; pub struct FreeAttestation { pub data: AttestationData, pub signature: Signature, + #[serde(with = "serde_utils::quoted_u64")] pub validator_index: u64, } diff --git a/consensus/types/src/graffiti.rs b/consensus/types/src/graffiti.rs new file mode 100644 index 00000000000..f35df93838b --- /dev/null +++ b/consensus/types/src/graffiti.rs @@ -0,0 +1,132 @@ +use crate::{ + test_utils::{RngCore, TestRandom}, + Hash256, +}; +use regex::bytes::Regex; +use serde::{de::Error, Deserialize, Deserializer, Serialize, Serializer}; +use ssz::{Decode, DecodeError, Encode}; +use std::fmt; +use tree_hash::TreeHash; + +pub const GRAFFITI_BYTES_LEN: usize = 32; + +/// The 32-byte `graffiti` field on a beacon block. +#[derive(Default, Debug, PartialEq, Clone, Copy, Serialize, Deserialize)] +#[serde(transparent)] +#[cfg_attr(feature = "arbitrary-fuzz", derive(arbitrary::Arbitrary))] +pub struct Graffiti(#[serde(with = "serde_graffiti")] pub [u8; GRAFFITI_BYTES_LEN]); + +impl Graffiti { + pub fn as_utf8_lossy(&self) -> String { + #[allow(clippy::invalid_regex)] + let re = Regex::new("\\p{C}").expect("graffiti regex is valid"); + String::from_utf8_lossy(&re.replace_all(&self.0[..], &b""[..])).to_string() + } +} + +impl fmt::Display for Graffiti { + fn fmt(&self, f: &mut fmt::Formatter<'_>) -> fmt::Result { + write!(f, "{}", serde_utils::hex::encode(&self.0)) + } +} + +impl From<[u8; GRAFFITI_BYTES_LEN]> for Graffiti { + fn from(bytes: [u8; GRAFFITI_BYTES_LEN]) -> Self { + Self(bytes) + } +} + +impl Into<[u8; GRAFFITI_BYTES_LEN]> for Graffiti { + fn into(self) -> [u8; GRAFFITI_BYTES_LEN] { + self.0 + } +} + +pub mod serde_graffiti { + use super::*; + + pub fn serialize(bytes: &[u8; GRAFFITI_BYTES_LEN], serializer: S) -> Result + where + S: Serializer, + { + serializer.serialize_str(&serde_utils::hex::encode(bytes)) + } + + pub fn deserialize<'de, D>(deserializer: D) -> Result<[u8; GRAFFITI_BYTES_LEN], D::Error> + where + D: Deserializer<'de>, + { + let s: String = Deserialize::deserialize(deserializer)?; + + let bytes = serde_utils::hex::decode(&s).map_err(D::Error::custom)?; + + if bytes.len() != GRAFFITI_BYTES_LEN { + return Err(D::Error::custom(format!( + "incorrect byte length {}, expected {}", + bytes.len(), + GRAFFITI_BYTES_LEN + ))); + } + + let mut array = [0; GRAFFITI_BYTES_LEN]; + array[..].copy_from_slice(&bytes); + + Ok(array) + } +} + +impl Encode for Graffiti { + fn is_ssz_fixed_len() -> bool { + <[u8; GRAFFITI_BYTES_LEN] as Encode>::is_ssz_fixed_len() + } + + fn ssz_fixed_len() -> usize { + <[u8; GRAFFITI_BYTES_LEN] as Encode>::ssz_fixed_len() + } + + fn ssz_bytes_len(&self) -> usize { + self.0.ssz_bytes_len() + } + + fn ssz_append(&self, buf: &mut Vec) { + self.0.ssz_append(buf) + } +} + +impl Decode for Graffiti { + fn is_ssz_fixed_len() -> bool { + <[u8; GRAFFITI_BYTES_LEN] as Decode>::is_ssz_fixed_len() + } + + fn ssz_fixed_len() -> usize { + <[u8; GRAFFITI_BYTES_LEN] as Decode>::ssz_fixed_len() + } + + fn from_ssz_bytes(bytes: &[u8]) -> Result { + <[u8; GRAFFITI_BYTES_LEN]>::from_ssz_bytes(bytes).map(Self) + } +} + +impl TreeHash for Graffiti { + fn tree_hash_type() -> tree_hash::TreeHashType { + <[u8; GRAFFITI_BYTES_LEN]>::tree_hash_type() + } + + fn tree_hash_packed_encoding(&self) -> Vec { + self.0.tree_hash_packed_encoding() + } + + fn tree_hash_packing_factor() -> usize { + <[u8; GRAFFITI_BYTES_LEN]>::tree_hash_packing_factor() + } + + fn tree_hash_root(&self) -> tree_hash::Hash256 { + self.0.tree_hash_root() + } +} + +impl TestRandom for Graffiti { + fn random_for_test(rng: &mut impl RngCore) -> Self { + Self::from(Hash256::random_for_test(rng).to_fixed_bytes()) + } +} diff --git a/consensus/types/src/indexed_attestation.rs b/consensus/types/src/indexed_attestation.rs index 341db180750..eaae75de839 100644 --- a/consensus/types/src/indexed_attestation.rs +++ b/consensus/types/src/indexed_attestation.rs @@ -18,6 +18,7 @@ use tree_hash_derive::TreeHash; #[serde(bound = "T: EthSpec")] pub struct IndexedAttestation { /// Lists validator registry indices, not committee indices. + #[serde(with = "quoted_variable_list_u64")] pub attesting_indices: VariableList, pub data: AttestationData, pub signature: AggregateSignature, @@ -53,6 +54,43 @@ impl Hash for IndexedAttestation { } } +/// Serialize a variable list of `u64` such that each int is quoted. Deserialize a variable +/// list supporting both quoted and un-quoted ints. +/// +/// E.g.,`["0", "1", "2"]` +mod quoted_variable_list_u64 { + use super::*; + use crate::Unsigned; + use serde::ser::SerializeSeq; + use serde::{Deserializer, Serializer}; + use serde_utils::quoted_u64_vec::{QuotedIntVecVisitor, QuotedIntWrapper}; + + pub fn serialize(value: &VariableList, serializer: S) -> Result + where + S: Serializer, + T: Unsigned, + { + let mut seq = serializer.serialize_seq(Some(value.len()))?; + for &int in value.iter() { + seq.serialize_element(&QuotedIntWrapper { int })?; + } + seq.end() + } + + pub fn deserialize<'de, D, T>(deserializer: D) -> Result, D::Error> + where + D: Deserializer<'de>, + T: Unsigned, + { + deserializer + .deserialize_any(QuotedIntVecVisitor) + .and_then(|vec| { + VariableList::new(vec) + .map_err(|e| serde::de::Error::custom(format!("invalid length: {:?}", e))) + }) + } +} + #[cfg(test)] mod tests { use super::*; diff --git a/consensus/types/src/lib.rs b/consensus/types/src/lib.rs index 19697118a50..65c1290d7a7 100644 --- a/consensus/types/src/lib.rs +++ b/consensus/types/src/lib.rs @@ -29,19 +29,21 @@ pub mod eth_spec; pub mod fork; pub mod fork_data; pub mod free_attestation; +pub mod graffiti; pub mod historical_batch; pub mod indexed_attestation; pub mod pending_attestation; pub mod proposer_slashing; pub mod relative_epoch; pub mod selection_proof; +pub mod shuffling_id; pub mod signed_aggregate_and_proof; pub mod signed_beacon_block; pub mod signed_beacon_block_header; pub mod signed_voluntary_exit; pub mod signing_data; -pub mod utils; pub mod validator; +pub mod validator_subscription; pub mod voluntary_exit; #[macro_use] pub mod slot_epoch_macros; @@ -74,12 +76,14 @@ pub use crate::eth1_data::Eth1Data; pub use crate::fork::Fork; pub use crate::fork_data::ForkData; pub use crate::free_attestation::FreeAttestation; +pub use crate::graffiti::{Graffiti, GRAFFITI_BYTES_LEN}; pub use crate::historical_batch::HistoricalBatch; pub use crate::indexed_attestation::IndexedAttestation; pub use crate::pending_attestation::PendingAttestation; pub use crate::proposer_slashing::ProposerSlashing; pub use crate::relative_epoch::{Error as RelativeEpochError, RelativeEpoch}; pub use crate::selection_proof::SelectionProof; +pub use crate::shuffling_id::ShufflingId; pub use crate::signed_aggregate_and_proof::SignedAggregateAndProof; pub use crate::signed_beacon_block::{SignedBeaconBlock, SignedBeaconBlockHash}; pub use crate::signed_beacon_block_header::SignedBeaconBlockHeader; @@ -88,6 +92,7 @@ pub use crate::signing_data::{SignedRoot, SigningData}; pub use crate::slot_epoch::{Epoch, Slot}; pub use crate::subnet_id::SubnetId; pub use crate::validator::Validator; +pub use crate::validator_subscription::ValidatorSubscription; pub use crate::voluntary_exit::VoluntaryExit; pub type CommitteeIndex = u64; @@ -99,4 +104,3 @@ pub use bls::{ AggregateSignature, Keypair, PublicKey, PublicKeyBytes, SecretKey, Signature, SignatureBytes, }; pub use ssz_types::{typenum, typenum::Unsigned, BitList, BitVector, FixedVector, VariableList}; -pub use utils::{Graffiti, GRAFFITI_BYTES_LEN}; diff --git a/consensus/types/src/pending_attestation.rs b/consensus/types/src/pending_attestation.rs index 70ebb1bbd68..f4b0fd9b148 100644 --- a/consensus/types/src/pending_attestation.rs +++ b/consensus/types/src/pending_attestation.rs @@ -13,7 +13,9 @@ use tree_hash_derive::TreeHash; pub struct PendingAttestation { pub aggregation_bits: BitList, pub data: AttestationData, + #[serde(with = "serde_utils::quoted_u64")] pub inclusion_delay: u64, + #[serde(with = "serde_utils::quoted_u64")] pub proposer_index: u64, } diff --git a/consensus/types/src/shuffling_id.rs b/consensus/types/src/shuffling_id.rs new file mode 100644 index 00000000000..d54b5fa640f --- /dev/null +++ b/consensus/types/src/shuffling_id.rs @@ -0,0 +1,61 @@ +use crate::*; +use serde_derive::{Deserialize, Serialize}; +use ssz_derive::{Decode, Encode}; +use std::hash::Hash; + +/// Can be used to key (ID) the shuffling in some chain, in some epoch. +/// +/// ## Reasoning +/// +/// We say that the ID of some shuffling is always equal to a 2-tuple: +/// +/// - The epoch for which the shuffling should be effective. +/// - A block root, where this is the root at the *last* slot of the penultimate epoch. I.e., the +/// final block which contributed a randao reveal to the seed for the shuffling. +/// +/// The struct stores exactly that 2-tuple. +#[derive(Debug, PartialEq, Eq, Clone, Hash, Serialize, Deserialize, Encode, Decode)] +pub struct ShufflingId { + pub shuffling_epoch: Epoch, + shuffling_decision_block: Hash256, +} + +impl ShufflingId { + /// Using the given `state`, return the shuffling id for the shuffling at the given + /// `relative_epoch`. + /// + /// The `block_root` provided should be either: + /// + /// - The root of the block which produced this state. + /// - If the state is from a skip slot, the root of the latest block in that state. + pub fn new( + block_root: Hash256, + state: &BeaconState, + relative_epoch: RelativeEpoch, + ) -> Result { + let shuffling_epoch = relative_epoch.into_epoch(state.current_epoch()); + + let shuffling_decision_slot = shuffling_epoch + .saturating_sub(1_u64) + .start_slot(E::slots_per_epoch()) + .saturating_sub(1_u64); + + let shuffling_decision_block = if state.slot == shuffling_decision_slot { + block_root + } else { + *state.get_block_root(shuffling_decision_slot)? + }; + + Ok(Self { + shuffling_epoch, + shuffling_decision_block, + }) + } + + pub fn from_components(shuffling_epoch: Epoch, shuffling_decision_block: Hash256) -> Self { + Self { + shuffling_epoch, + shuffling_decision_block, + } + } +} diff --git a/consensus/types/src/slot_epoch_macros.rs b/consensus/types/src/slot_epoch_macros.rs index 26b80692c94..caf31417d66 100644 --- a/consensus/types/src/slot_epoch_macros.rs +++ b/consensus/types/src/slot_epoch_macros.rs @@ -313,6 +313,18 @@ macro_rules! impl_ssz { }; } +macro_rules! impl_from_str { + ($type: ident) => { + impl std::str::FromStr for $type { + type Err = std::num::ParseIntError; + + fn from_str(s: &str) -> Result<$type, Self::Err> { + u64::from_str(s).map($type) + } + } + }; +} + macro_rules! impl_common { ($type: ident) => { impl_from_into_u64!($type); @@ -328,6 +340,7 @@ macro_rules! impl_common { impl_display!($type); impl_debug!($type); impl_ssz!($type); + impl_from_str!($type); }; } diff --git a/consensus/types/src/subnet_id.rs b/consensus/types/src/subnet_id.rs index 80cc249776f..667e2c9b78e 100644 --- a/consensus/types/src/subnet_id.rs +++ b/consensus/types/src/subnet_id.rs @@ -6,7 +6,8 @@ use std::ops::{Deref, DerefMut}; #[cfg_attr(feature = "arbitrary-fuzz", derive(arbitrary::Arbitrary))] #[derive(Clone, Copy, Debug, PartialEq, Eq, Hash, Serialize, Deserialize)] -pub struct SubnetId(u64); +#[serde(transparent)] +pub struct SubnetId(#[serde(with = "serde_utils::quoted_u64")] u64); impl SubnetId { pub fn new(id: u64) -> Self { diff --git a/consensus/types/src/utils.rs b/consensus/types/src/utils.rs deleted file mode 100644 index a527fc18fd1..00000000000 --- a/consensus/types/src/utils.rs +++ /dev/null @@ -1,3 +0,0 @@ -mod serde_utils; - -pub use self::serde_utils::*; diff --git a/consensus/types/src/utils/serde_utils.rs b/consensus/types/src/utils/serde_utils.rs deleted file mode 100644 index 36b719646bf..00000000000 --- a/consensus/types/src/utils/serde_utils.rs +++ /dev/null @@ -1,134 +0,0 @@ -use serde::de::Error; -use serde::{Deserialize, Deserializer, Serializer}; - -pub const FORK_BYTES_LEN: usize = 4; -pub const GRAFFITI_BYTES_LEN: usize = 32; - -/// Type for a slice of `GRAFFITI_BYTES_LEN` bytes. -/// -/// Gets included inside each `BeaconBlockBody`. -pub type Graffiti = [u8; GRAFFITI_BYTES_LEN]; - -pub fn u8_from_hex_str<'de, D>(deserializer: D) -> Result -where - D: Deserializer<'de>, -{ - let s: String = Deserialize::deserialize(deserializer)?; - - let start = match s.as_str().get(2..) { - Some(start) => start, - None => return Err(D::Error::custom("string length too small")), - }; - u8::from_str_radix(&start, 16).map_err(D::Error::custom) -} - -#[allow(clippy::trivially_copy_pass_by_ref)] // Serde requires the `byte` to be a ref. -pub fn u8_to_hex_str(byte: &u8, serializer: S) -> Result -where - S: Serializer, -{ - let mut hex: String = "0x".to_string(); - hex.push_str(&hex::encode(&[*byte])); - - serializer.serialize_str(&hex) -} - -pub fn u32_from_hex_str<'de, D>(deserializer: D) -> Result -where - D: Deserializer<'de>, -{ - let s: String = Deserialize::deserialize(deserializer)?; - let start = s - .as_str() - .get(2..) - .ok_or_else(|| D::Error::custom("string length too small"))?; - - u32::from_str_radix(&start, 16) - .map_err(D::Error::custom) - .map(u32::from_be) -} - -#[allow(clippy::trivially_copy_pass_by_ref)] // Serde requires the `num` to be a ref. -pub fn u32_to_hex_str(num: &u32, serializer: S) -> Result -where - S: Serializer, -{ - let mut hex: String = "0x".to_string(); - let bytes = num.to_le_bytes(); - hex.push_str(&hex::encode(&bytes)); - - serializer.serialize_str(&hex) -} - -pub fn fork_from_hex_str<'de, D>(deserializer: D) -> Result<[u8; FORK_BYTES_LEN], D::Error> -where - D: Deserializer<'de>, -{ - let s: String = Deserialize::deserialize(deserializer)?; - let mut array = [0 as u8; FORK_BYTES_LEN]; - - let start = s - .as_str() - .get(2..) - .ok_or_else(|| D::Error::custom("string length too small"))?; - let decoded: Vec = hex::decode(&start).map_err(D::Error::custom)?; - - if decoded.len() != FORK_BYTES_LEN { - return Err(D::Error::custom("Fork length too long")); - } - - for (i, item) in array.iter_mut().enumerate() { - if i > decoded.len() { - break; - } - *item = decoded[i]; - } - Ok(array) -} - -#[allow(clippy::trivially_copy_pass_by_ref)] -pub fn fork_to_hex_str(bytes: &[u8; FORK_BYTES_LEN], serializer: S) -> Result -where - S: Serializer, -{ - let mut hex_string: String = "0x".to_string(); - hex_string.push_str(&hex::encode(&bytes)); - - serializer.serialize_str(&hex_string) -} - -pub fn graffiti_to_hex_str(bytes: &Graffiti, serializer: S) -> Result -where - S: Serializer, -{ - let mut hex_string: String = "0x".to_string(); - hex_string.push_str(&hex::encode(&bytes)); - - serializer.serialize_str(&hex_string) -} - -pub fn graffiti_from_hex_str<'de, D>(deserializer: D) -> Result -where - D: Deserializer<'de>, -{ - let s: String = Deserialize::deserialize(deserializer)?; - let mut array = Graffiti::default(); - - let start = s - .as_str() - .get(2..) - .ok_or_else(|| D::Error::custom("string length too small"))?; - let decoded: Vec = hex::decode(&start).map_err(D::Error::custom)?; - - if decoded.len() > GRAFFITI_BYTES_LEN { - return Err(D::Error::custom("Fork length too long")); - } - - for (i, item) in array.iter_mut().enumerate() { - if i > decoded.len() { - break; - } - *item = decoded[i]; - } - Ok(array) -} diff --git a/consensus/types/src/validator_subscription.rs b/consensus/types/src/validator_subscription.rs new file mode 100644 index 00000000000..fd48660c52b --- /dev/null +++ b/consensus/types/src/validator_subscription.rs @@ -0,0 +1,21 @@ +use crate::*; +use serde::{Deserialize, Serialize}; +use ssz_derive::{Decode, Encode}; + +/// A validator subscription, created when a validator subscribes to a slot to perform optional aggregation +/// duties. +#[derive(PartialEq, Debug, Serialize, Deserialize, Clone, Encode, Decode)] +pub struct ValidatorSubscription { + /// The validators index. + pub validator_index: u64, + /// The index of the committee within `slot` of which the validator is a member. Used by the + /// beacon node to quickly evaluate the associated `SubnetId`. + pub attestation_committee_index: CommitteeIndex, + /// The slot in which to subscribe. + pub slot: Slot, + /// Committee count at slot to subscribe. + pub committee_count_at_slot: u64, + /// If true, the validator is an aggregator and the beacon node should aggregate attestations + /// for this slot. + pub is_aggregator: bool, +} diff --git a/consensus/types/src/voluntary_exit.rs b/consensus/types/src/voluntary_exit.rs index a9509d7affa..c33ea7e79f7 100644 --- a/consensus/types/src/voluntary_exit.rs +++ b/consensus/types/src/voluntary_exit.rs @@ -16,6 +16,7 @@ use tree_hash_derive::TreeHash; pub struct VoluntaryExit { /// Earliest epoch when voluntary exit can be processed. pub epoch: Epoch, + #[serde(with = "serde_utils::quoted_u64")] pub validator_index: u64, } diff --git a/crypto/bls/Cargo.toml b/crypto/bls/Cargo.toml index e1cb1fde319..8fd004a80b2 100644 --- a/crypto/bls/Cargo.toml +++ b/crypto/bls/Cargo.toml @@ -11,7 +11,7 @@ milagro_bls = { git = "https://github.com/sigp/milagro_bls", branch = "paulh" } rand = "0.7.2" serde = "1.0.102" serde_derive = "1.0.102" -serde_hex = { path = "../../consensus/serde_hex" } +serde_utils = { path = "../../consensus/serde_utils" } hex = "0.3" eth2_hashing = "0.1.0" ethereum-types = "0.9.1" diff --git a/crypto/bls/src/generic_aggregate_signature.rs b/crypto/bls/src/generic_aggregate_signature.rs index 240b7d1880d..0517512f82a 100644 --- a/crypto/bls/src/generic_aggregate_signature.rs +++ b/crypto/bls/src/generic_aggregate_signature.rs @@ -6,7 +6,7 @@ use crate::{ }; use serde::de::{Deserialize, Deserializer}; use serde::ser::{Serialize, Serializer}; -use serde_hex::{encode as hex_encode, PrefixedHexVisitor}; +use serde_utils::hex::encode as hex_encode; use ssz::{Decode, Encode}; use std::fmt; use std::marker::PhantomData; @@ -245,6 +245,23 @@ where impl_tree_hash!(SIGNATURE_BYTES_LEN); } +impl fmt::Display for GenericAggregateSignature +where + Sig: TSignature, + AggSig: TAggregateSignature, +{ + impl_display!(); +} + +impl std::str::FromStr + for GenericAggregateSignature +where + Sig: TSignature, + AggSig: TAggregateSignature, +{ + impl_from_str!(); +} + impl Serialize for GenericAggregateSignature where Sig: TSignature, diff --git a/crypto/bls/src/generic_public_key.rs b/crypto/bls/src/generic_public_key.rs index 29814d24aca..7b22d272990 100644 --- a/crypto/bls/src/generic_public_key.rs +++ b/crypto/bls/src/generic_public_key.rs @@ -1,7 +1,7 @@ use crate::Error; use serde::de::{Deserialize, Deserializer}; use serde::ser::{Serialize, Serializer}; -use serde_hex::{encode as hex_encode, PrefixedHexVisitor}; +use serde_utils::hex::encode as hex_encode; use ssz::{Decode, Encode}; use std::fmt; use std::hash::{Hash, Hasher}; @@ -97,6 +97,14 @@ impl TreeHash for GenericPublicKey { impl_tree_hash!(PUBLIC_KEY_BYTES_LEN); } +impl fmt::Display for GenericPublicKey { + impl_display!(); +} + +impl std::str::FromStr for GenericPublicKey { + impl_from_str!(); +} + impl Serialize for GenericPublicKey { impl_serde_serialize!(); } diff --git a/crypto/bls/src/generic_public_key_bytes.rs b/crypto/bls/src/generic_public_key_bytes.rs index beceac1c904..387eb91c969 100644 --- a/crypto/bls/src/generic_public_key_bytes.rs +++ b/crypto/bls/src/generic_public_key_bytes.rs @@ -4,7 +4,7 @@ use crate::{ }; use serde::de::{Deserialize, Deserializer}; use serde::ser::{Serialize, Serializer}; -use serde_hex::{encode as hex_encode, PrefixedHexVisitor}; +use serde_utils::hex::encode as hex_encode; use ssz::{Decode, Encode}; use std::convert::TryInto; use std::fmt; @@ -101,6 +101,16 @@ where Pub: TPublicKey, { fn from(pk: GenericPublicKey) -> Self { + Self::from(&pk) + } +} + +/// Serializes the `PublicKey` in compressed form, storing the bytes in the newly created `Self`. +impl From<&GenericPublicKey> for GenericPublicKeyBytes +where + Pub: TPublicKey, +{ + fn from(pk: &GenericPublicKey) -> Self { Self { bytes: pk.serialize(), _phantom: PhantomData, @@ -132,6 +142,14 @@ impl TreeHash for GenericPublicKeyBytes { impl_tree_hash!(PUBLIC_KEY_BYTES_LEN); } +impl fmt::Display for GenericPublicKeyBytes { + impl_display!(); +} + +impl std::str::FromStr for GenericPublicKeyBytes { + impl_from_str!(); +} + impl Serialize for GenericPublicKeyBytes { impl_serde_serialize!(); } diff --git a/crypto/bls/src/generic_signature.rs b/crypto/bls/src/generic_signature.rs index 28a9361957a..44250d4a6ba 100644 --- a/crypto/bls/src/generic_signature.rs +++ b/crypto/bls/src/generic_signature.rs @@ -4,7 +4,7 @@ use crate::{ }; use serde::de::{Deserialize, Deserializer}; use serde::ser::{Serialize, Serializer}; -use serde_hex::{encode as hex_encode, PrefixedHexVisitor}; +use serde_utils::hex::encode as hex_encode; use ssz::{Decode, Encode}; use std::fmt; use std::marker::PhantomData; @@ -149,6 +149,14 @@ impl> TreeHash for GenericSignature> fmt::Display for GenericSignature { + impl_display!(); +} + +impl> std::str::FromStr for GenericSignature { + impl_from_str!(); +} + impl> Serialize for GenericSignature { impl_serde_serialize!(); } diff --git a/crypto/bls/src/generic_signature_bytes.rs b/crypto/bls/src/generic_signature_bytes.rs index 1f987ecd362..bc7e7f111e8 100644 --- a/crypto/bls/src/generic_signature_bytes.rs +++ b/crypto/bls/src/generic_signature_bytes.rs @@ -5,7 +5,7 @@ use crate::{ }; use serde::de::{Deserialize, Deserializer}; use serde::ser::{Serialize, Serializer}; -use serde_hex::{encode as hex_encode, PrefixedHexVisitor}; +use serde_utils::hex::encode as hex_encode; use ssz::{Decode, Encode}; use std::convert::TryInto; use std::fmt; @@ -124,6 +124,14 @@ impl TreeHash for GenericSignatureBytes { impl_tree_hash!(SIGNATURE_BYTES_LEN); } +impl fmt::Display for GenericSignatureBytes { + impl_display!(); +} + +impl std::str::FromStr for GenericSignatureBytes { + impl_from_str!(); +} + impl Serialize for GenericSignatureBytes { impl_serde_serialize!(); } diff --git a/crypto/bls/src/macros.rs b/crypto/bls/src/macros.rs index ca103da6da4..136faeb4423 100644 --- a/crypto/bls/src/macros.rs +++ b/crypto/bls/src/macros.rs @@ -76,6 +76,35 @@ macro_rules! impl_ssz_decode { }; } +/// Contains the functions required for a `fmt::Display` implementation. +/// +/// Does not include the `Impl` section since it gets very complicated when it comes to generics. +macro_rules! impl_display { + () => { + fn fmt(&self, f: &mut fmt::Formatter<'_>) -> fmt::Result { + write!(f, "{}", hex_encode(self.serialize().to_vec())) + } + }; +} + +/// Contains the functions required for a `fmt::Display` implementation. +/// +/// Does not include the `Impl` section since it gets very complicated when it comes to generics. +macro_rules! impl_from_str { + () => { + type Err = String; + + fn from_str(s: &str) -> Result { + if s.starts_with("0x") { + let bytes = hex::decode(&s[2..]).map_err(|e| e.to_string())?; + Self::deserialize(&bytes[..]).map_err(|e| format!("{:?}", e)) + } else { + Err("must start with 0x".to_string()) + } + } + }; +} + /// Contains the functions required for a `serde::Serialize` implementation. /// /// Does not include the `Impl` section since it gets very complicated when it comes to generics. @@ -85,7 +114,7 @@ macro_rules! impl_serde_serialize { where S: Serializer, { - serializer.serialize_str(&hex_encode(self.serialize().to_vec())) + serializer.serialize_str(&self.to_string()) } }; } @@ -99,9 +128,25 @@ macro_rules! impl_serde_deserialize { where D: Deserializer<'de>, { - let bytes = deserializer.deserialize_str(PrefixedHexVisitor)?; - Self::deserialize(&bytes[..]) - .map_err(|e| serde::de::Error::custom(format!("invalid pubkey ({:?})", e))) + pub struct StringVisitor; + + impl<'de> serde::de::Visitor<'de> for StringVisitor { + type Value = String; + + fn expecting(&self, formatter: &mut fmt::Formatter) -> fmt::Result { + formatter.write_str("a hex string with 0x prefix") + } + + fn visit_str(self, value: &str) -> Result + where + E: serde::de::Error, + { + Ok(value.to_string()) + } + } + + let string = deserializer.deserialize_str(StringVisitor)?; + ::from_str(&string).map_err(serde::de::Error::custom) } }; } diff --git a/testing/node_test_rig/Cargo.toml b/testing/node_test_rig/Cargo.toml index a48f24f3f04..ae23936369e 100644 --- a/testing/node_test_rig/Cargo.toml +++ b/testing/node_test_rig/Cargo.toml @@ -15,6 +15,6 @@ url = "2.1.1" serde = "1.0.110" futures = "0.3.5" genesis = { path = "../../beacon_node/genesis" } -remote_beacon_node = { path = "../../common/remote_beacon_node" } +eth2 = { path = "../../common/eth2" } validator_client = { path = "../../validator_client" } validator_dir = { path = "../../common/validator_dir", features = ["insecure_keys"] } diff --git a/testing/node_test_rig/src/lib.rs b/testing/node_test_rig/src/lib.rs index b1a74b64a73..e2391c0f880 100644 --- a/testing/node_test_rig/src/lib.rs +++ b/testing/node_test_rig/src/lib.rs @@ -4,7 +4,12 @@ use beacon_node::ProductionBeaconNode; use environment::RuntimeContext; +use eth2::{ + reqwest::{ClientBuilder, Url}, + BeaconNodeHttpClient, +}; use std::path::PathBuf; +use std::time::Duration; use std::time::{SystemTime, UNIX_EPOCH}; use tempdir::TempDir; use types::EthSpec; @@ -13,9 +18,12 @@ use validator_dir::insecure_keys::build_deterministic_validator_dirs; pub use beacon_node::{ClientConfig, ClientGenesis, ProductionClient}; pub use environment; -pub use remote_beacon_node::RemoteBeaconNode; +pub use eth2; pub use validator_client::Config as ValidatorConfig; +/// The global timeout for HTTP requests to the beacon node. +const HTTP_TIMEOUT: Duration = Duration::from_secs(4); + /// Provides a beacon node that is running in the current process on a given tokio executor (it /// is _local_ to this process). /// @@ -52,16 +60,23 @@ impl LocalBeaconNode { impl LocalBeaconNode { /// Returns a `RemoteBeaconNode` that can connect to `self`. Useful for testing the node as if /// it were external this process. - pub fn remote_node(&self) -> Result, String> { - let socket_addr = self + pub fn remote_node(&self) -> Result { + let listen_addr = self .client - .http_listen_addr() + .http_api_listen_addr() .ok_or_else(|| "A remote beacon node must have a http server".to_string())?; - Ok(RemoteBeaconNode::new(format!( - "http://{}:{}", - socket_addr.ip(), - socket_addr.port() - ))?) + + let beacon_node_url: Url = format!("http://{}:{}", listen_addr.ip(), listen_addr.port()) + .parse() + .map_err(|e| format!("Unable to parse beacon node URL: {:?}", e))?; + let beacon_node_http_client = ClientBuilder::new() + .timeout(HTTP_TIMEOUT) + .build() + .map_err(|e| format!("Unable to build HTTP client: {:?}", e))?; + Ok(BeaconNodeHttpClient::from_components( + beacon_node_url, + beacon_node_http_client, + )) } } @@ -71,8 +86,8 @@ pub fn testing_client_config() -> ClientConfig { // Setting ports to `0` means that the OS will choose some available port. client_config.network.libp2p_port = 0; client_config.network.discovery_port = 0; - client_config.rest_api.enabled = true; - client_config.rest_api.port = 0; + client_config.http_api.enabled = true; + client_config.http_api.listen_port = 0; client_config.websocket_server.enabled = true; client_config.websocket_server.port = 0; diff --git a/testing/simulator/src/checks.rs b/testing/simulator/src/checks.rs index 43ceaa14fdb..e755c9005fa 100644 --- a/testing/simulator/src/checks.rs +++ b/testing/simulator/src/checks.rs @@ -1,4 +1,5 @@ use crate::local_network::LocalNetwork; +use node_test_rig::eth2::types::StateId; use std::time::Duration; use types::{Epoch, EthSpec, Slot, Unsigned}; @@ -65,11 +66,9 @@ pub async fn verify_all_finalized_at( for remote_node in network.remote_nodes()? { epochs.push( remote_node - .http - .beacon() - .get_head() + .get_beacon_states_finality_checkpoints(StateId::Head) .await - .map(|head| head.finalized_slot.epoch(E::slots_per_epoch())) + .map(|body| body.unwrap().data.finalized.epoch) .map_err(|e| format!("Get head via http failed: {:?}", e))?, ); } @@ -95,17 +94,10 @@ async fn verify_validator_count( let validator_counts = { let mut validator_counts = Vec::new(); for remote_node in network.remote_nodes()? { - let beacon = remote_node.http.beacon(); - - let head = beacon - .get_head() - .await - .map_err(|e| format!("Get head via http failed: {:?}", e))?; - - let vc = beacon - .get_state_by_root(head.state_root) + let vc = remote_node + .get_debug_beacon_states::(StateId::Head) .await - .map(|(state, _root)| state) + .map(|body| body.unwrap().data) .map_err(|e| format!("Get state root via http failed: {:?}", e))? .validators .len(); diff --git a/testing/simulator/src/cli.rs b/testing/simulator/src/cli.rs index de78aaa0578..1ce8b2a5d9b 100644 --- a/testing/simulator/src/cli.rs +++ b/testing/simulator/src/cli.rs @@ -34,7 +34,7 @@ pub fn cli_app<'a, 'b>() -> App<'a, 'b> { .short("s") .long("speed_up_factor") .takes_value(true) - .default_value("4") + .default_value("3") .help("Speed up factor")) .arg(Arg::with_name("continue_after_checks") .short("c") @@ -62,7 +62,7 @@ pub fn cli_app<'a, 'b>() -> App<'a, 'b> { .short("s") .long("speed_up_factor") .takes_value(true) - .default_value("4") + .default_value("3") .help("Speed up factor")) .arg(Arg::with_name("continue_after_checks") .short("c") diff --git a/testing/simulator/src/local_network.rs b/testing/simulator/src/local_network.rs index 37ce3ab5664..0dd9b3424b8 100644 --- a/testing/simulator/src/local_network.rs +++ b/testing/simulator/src/local_network.rs @@ -1,6 +1,7 @@ use node_test_rig::{ - environment::RuntimeContext, ClientConfig, LocalBeaconNode, LocalValidatorClient, - RemoteBeaconNode, ValidatorConfig, ValidatorFiles, + environment::RuntimeContext, + eth2::{types::StateId, BeaconNodeHttpClient}, + ClientConfig, LocalBeaconNode, LocalValidatorClient, ValidatorConfig, ValidatorFiles, }; use parking_lot::RwLock; use std::ops::Deref; @@ -123,7 +124,7 @@ impl LocalNetwork { .ok_or_else(|| format!("No beacon node for index {}", beacon_node))?; beacon_node .client - .http_listen_addr() + .http_api_listen_addr() .expect("Must have http started") }; @@ -140,7 +141,7 @@ impl LocalNetwork { } /// For all beacon nodes in `Self`, return a HTTP client to access each nodes HTTP API. - pub fn remote_nodes(&self) -> Result>, String> { + pub fn remote_nodes(&self) -> Result, String> { let beacon_nodes = self.beacon_nodes.read(); beacon_nodes @@ -154,11 +155,9 @@ impl LocalNetwork { let nodes = self.remote_nodes().expect("Failed to get remote nodes"); let bootnode = nodes.first().expect("Should contain bootnode"); bootnode - .http - .beacon() - .get_head() + .get_beacon_states_finality_checkpoints(StateId::Head) .await .map_err(|e| format!("Cannot get head: {:?}", e)) - .map(|head| head.finalized_slot.epoch(E::slots_per_epoch())) + .map(|body| body.unwrap().data.finalized.epoch) } } diff --git a/testing/simulator/src/sync_sim.rs b/testing/simulator/src/sync_sim.rs index 7583a6eab20..47272f62681 100644 --- a/testing/simulator/src/sync_sim.rs +++ b/testing/simulator/src/sync_sim.rs @@ -350,11 +350,9 @@ pub async fn check_still_syncing(network: &LocalNetwork) -> Resul for remote_node in network.remote_nodes()? { status.push( remote_node - .http - .node() - .syncing_status() + .get_node_syncing() .await - .map(|status| status.is_syncing) + .map(|body| body.data.is_syncing) .map_err(|e| format!("Get syncing status via http failed: {:?}", e))?, ) } diff --git a/validator_client/Cargo.toml b/validator_client/Cargo.toml index f15118e849a..aa658b28136 100644 --- a/validator_client/Cargo.toml +++ b/validator_client/Cargo.toml @@ -19,7 +19,6 @@ clap = "2.33.0" eth2_interop_keypairs = { path = "../common/eth2_interop_keypairs" } slashing_protection = { path = "./slashing_protection" } slot_clock = { path = "../common/slot_clock" } -rest_types = { path = "../common/rest_types" } types = { path = "../consensus/types" } serde = "1.0.110" serde_derive = "1.0.110" @@ -41,7 +40,7 @@ eth2_ssz_derive = "0.1.0" hex = "0.4.2" deposit_contract = { path = "../common/deposit_contract" } bls = { path = "../crypto/bls" } -remote_beacon_node = { path = "../common/remote_beacon_node" } +eth2 = { path = "../common/eth2" } tempdir = "0.3.7" rayon = "1.3.0" validator_dir = { path = "../common/validator_dir" } diff --git a/validator_client/src/attestation_service.rs b/validator_client/src/attestation_service.rs index fa79877774b..d675ebda2e8 100644 --- a/validator_client/src/attestation_service.rs +++ b/validator_client/src/attestation_service.rs @@ -3,22 +3,26 @@ use crate::{ validator_store::ValidatorStore, }; use environment::RuntimeContext; +use eth2::BeaconNodeHttpClient; use futures::StreamExt; -use remote_beacon_node::{PublishStatus, RemoteBeaconNode}; -use slog::{crit, debug, error, info, trace}; +use slog::{crit, error, info, trace}; use slot_clock::SlotClock; use std::collections::HashMap; use std::ops::Deref; use std::sync::Arc; use tokio::time::{delay_until, interval_at, Duration, Instant}; -use types::{Attestation, ChainSpec, CommitteeIndex, EthSpec, Slot, SubnetId}; +use tree_hash::TreeHash; +use types::{ + AggregateSignature, Attestation, AttestationData, BitList, ChainSpec, CommitteeIndex, EthSpec, + Slot, +}; /// Builds an `AttestationService`. pub struct AttestationServiceBuilder { duties_service: Option>, validator_store: Option>, slot_clock: Option, - beacon_node: Option>, + beacon_node: Option, context: Option>, } @@ -48,7 +52,7 @@ impl AttestationServiceBuilder { self } - pub fn beacon_node(mut self, beacon_node: RemoteBeaconNode) -> Self { + pub fn beacon_node(mut self, beacon_node: BeaconNodeHttpClient) -> Self { self.beacon_node = Some(beacon_node); self } @@ -86,7 +90,7 @@ pub struct Inner { duties_service: DutiesService, validator_store: ValidatorStore, slot_clock: T, - beacon_node: RemoteBeaconNode, + beacon_node: BeaconNodeHttpClient, context: RuntimeContext, } @@ -262,7 +266,7 @@ impl AttestationService { // Step 2. // // If an attestation was produced, make an aggregate. - if let Some(attestation) = attestation_opt { + if let Some(attestation_data) = attestation_opt { // First, wait until the `aggregation_production_instant` (2/3rds // of the way though the slot). As verified in the // `delay_triggers_when_in_the_past` test, this code will still run @@ -272,7 +276,7 @@ impl AttestationService { // Then download, sign and publish a `SignedAggregateAndProof` for each // validator that is elected to aggregate for this `slot` and // `committee_index`. - self.produce_and_publish_aggregates(attestation, &validator_duties) + self.produce_and_publish_aggregates(attestation_data, &validator_duties) .await .map_err(move |e| { crit!( @@ -305,7 +309,7 @@ impl AttestationService { slot: Slot, committee_index: CommitteeIndex, validator_duties: &[DutyAndProof], - ) -> Result>, String> { + ) -> Result, String> { let log = self.context.log(); if validator_duties.is_empty() { @@ -318,124 +322,88 @@ impl AttestationService { .ok_or_else(|| "Unable to determine current slot from clock".to_string())? .epoch(E::slots_per_epoch()); - let attestation = self + let attestation_data = self .beacon_node - .http - .validator() - .produce_attestation(slot, committee_index) + .get_validator_attestation_data(slot, committee_index) .await - .map_err(|e| format!("Failed to produce attestation: {:?}", e))?; + .map_err(|e| format!("Failed to produce attestation data: {:?}", e))? + .data; + + for duty in validator_duties { + // Ensure that all required fields are present in the validator duty. + let ( + duty_slot, + duty_committee_index, + validator_committee_position, + _, + _, + committee_length, + ) = if let Some(tuple) = duty.attestation_duties() { + tuple + } else { + crit!( + log, + "Missing validator duties when signing"; + "duties" => format!("{:?}", duty) + ); + continue; + }; - // For each validator in `validator_duties`, clone the `attestation` and add - // their signature. - // - // If any validator is unable to sign, they are simply skipped. - let signed_attestations = validator_duties - .iter() - .filter_map(|duty| { - // Ensure that all required fields are present in the validator duty. - let ( - duty_slot, - duty_committee_index, - validator_committee_position, - _, - committee_count_at_slot, - ) = if let Some(tuple) = duty.attestation_duties() { - tuple - } else { - crit!( - log, - "Missing validator duties when signing"; - "duties" => format!("{:?}", duty) - ); - return None; - }; + // Ensure that the attestation matches the duties. + if duty_slot != attestation_data.slot || duty_committee_index != attestation_data.index + { + crit!( + log, + "Inconsistent validator duties during signing"; + "validator" => format!("{:?}", duty.validator_pubkey()), + "duty_slot" => duty_slot, + "attestation_slot" => attestation_data.slot, + "duty_index" => duty_committee_index, + "attestation_index" => attestation_data.index, + ); + continue; + } - // Ensure that the attestation matches the duties. - if duty_slot != attestation.data.slot - || duty_committee_index != attestation.data.index - { - crit!( - log, - "Inconsistent validator duties during signing"; - "validator" => format!("{:?}", duty.validator_pubkey()), - "duty_slot" => duty_slot, - "attestation_slot" => attestation.data.slot, - "duty_index" => duty_committee_index, - "attestation_index" => attestation.data.index, - ); - return None; - } + let mut attestation = Attestation { + aggregation_bits: BitList::with_capacity(committee_length as usize).unwrap(), + data: attestation_data.clone(), + signature: AggregateSignature::infinity(), + }; - let mut attestation = attestation.clone(); - let subnet_id = SubnetId::compute_subnet_for_attestation_data::( - &attestation.data, - committee_count_at_slot, - &self.context.eth2_config().spec, + self.validator_store + .sign_attestation( + duty.validator_pubkey(), + validator_committee_position, + &mut attestation, + current_epoch, ) - .map_err(|e| { - error!( - log, - "Failed to compute subnet id to publish attestation: {:?}", e - ) - }) - .ok()?; - self.validator_store - .sign_attestation( - duty.validator_pubkey(), - validator_committee_position, - &mut attestation, - current_epoch, - ) - .map(|_| (attestation, subnet_id)) - }) - .collect::>(); - - // If there are any signed attestations, publish them to the BN. Otherwise, - // just return early. - if let Some(attestation) = signed_attestations.first().cloned() { - let num_attestations = signed_attestations.len(); - let beacon_block_root = attestation.0.data.beacon_block_root; - - self.beacon_node - .http - .validator() - .publish_attestations(signed_attestations) + .ok_or_else(|| "Failed to sign attestation".to_string())?; + + match self + .beacon_node + .post_beacon_pool_attestations(&attestation) .await - .map_err(|e| format!("Failed to publish attestation: {:?}", e)) - .map(move |publish_status| match publish_status { - PublishStatus::Valid => info!( - log, - "Successfully published attestations"; - "count" => num_attestations, - "head_block" => format!("{:?}", beacon_block_root), - "committee_index" => committee_index, - "slot" => slot.as_u64(), - "type" => "unaggregated", - ), - PublishStatus::Invalid(msg) => crit!( - log, - "Published attestation was invalid"; - "message" => msg, - "committee_index" => committee_index, - "slot" => slot.as_u64(), - "type" => "unaggregated", - ), - PublishStatus::Unknown => { - crit!(log, "Unknown condition when publishing unagg. attestation") - } - }) - .map(|()| Some(attestation.0)) - } else { - debug!( - log, - "No attestations to publish"; - "committee_index" => committee_index, - "slot" => slot.as_u64(), - ); - - Ok(None) + { + Ok(()) => info!( + log, + "Successfully published attestation"; + "head_block" => format!("{:?}", attestation.data.beacon_block_root), + "committee_index" => attestation.data.index, + "slot" => attestation.data.slot.as_u64(), + "type" => "unaggregated", + ), + Err(e) => error!( + log, + "Unable to publish attestation"; + "error" => e.to_string(), + "committee_index" => attestation.data.index, + "slot" => slot.as_u64(), + "type" => "unaggregated", + ), + } } + + Ok(Some(attestation_data)) } /// Performs the second step of the attesting process: downloading an aggregated `Attestation`, @@ -453,103 +421,89 @@ impl AttestationService { /// returned to the BN. async fn produce_and_publish_aggregates( &self, - attestation: Attestation, + attestation_data: AttestationData, validator_duties: &[DutyAndProof], ) -> Result<(), String> { let log = self.context.log(); let aggregated_attestation = self .beacon_node - .http - .validator() - .produce_aggregate_attestation(&attestation.data) + .get_validator_aggregate_attestation( + attestation_data.slot, + attestation_data.tree_hash_root(), + ) .await - .map_err(|e| format!("Failed to produce an aggregate attestation: {:?}", e))?; - - // For each validator, clone the `aggregated_attestation` and convert it into - // a `SignedAggregateAndProof` - let signed_aggregate_and_proofs = validator_duties - .iter() - .filter_map(|duty_and_proof| { - // Do not produce a signed aggregator for validators that are not + .map_err(|e| format!("Failed to produce an aggregate attestation: {:?}", e))? + .ok_or_else(|| format!("No aggregate available for {:?}", attestation_data))? + .data; + + for duty_and_proof in validator_duties { + let selection_proof = if let Some(proof) = duty_and_proof.selection_proof.as_ref() { + proof + } else { + // Do not produce a signed aggregate for validators that are not // subscribed aggregators. - let selection_proof = duty_and_proof.selection_proof.as_ref()?.clone(); - - let (duty_slot, duty_committee_index, _, validator_index, _) = - duty_and_proof.attestation_duties().or_else(|| { - crit!(log, "Missing duties when signing aggregate"); - None - })?; + continue; + }; + let (duty_slot, duty_committee_index, _, validator_index, _, _) = + if let Some(tuple) = duty_and_proof.attestation_duties() { + tuple + } else { + crit!(log, "Missing duties when signing aggregate"); + continue; + }; - let pubkey = &duty_and_proof.duty.validator_pubkey; - let slot = attestation.data.slot; - let committee_index = attestation.data.index; + let pubkey = &duty_and_proof.duty.validator_pubkey; + let slot = attestation_data.slot; + let committee_index = attestation_data.index; - if duty_slot != slot || duty_committee_index != committee_index { - crit!(log, "Inconsistent validator duties during signing"); - return None; - } + if duty_slot != slot || duty_committee_index != committee_index { + crit!(log, "Inconsistent validator duties during signing"); + continue; + } - if let Some(signed_aggregate_and_proof) = - self.validator_store.produce_signed_aggregate_and_proof( - pubkey, - validator_index, - aggregated_attestation.clone(), - selection_proof, - ) - { - Some(signed_aggregate_and_proof) - } else { - crit!(log, "Failed to sign attestation"); - None - } - }) - .collect::>(); + let signed_aggregate_and_proof = if let Some(aggregate) = + self.validator_store.produce_signed_aggregate_and_proof( + pubkey, + validator_index, + aggregated_attestation.clone(), + selection_proof.clone(), + ) { + aggregate + } else { + crit!(log, "Failed to sign attestation"); + continue; + }; - // If there any signed aggregates and proofs were produced, publish them to the - // BN. - if let Some(first) = signed_aggregate_and_proofs.first().cloned() { - let attestation = first.message.aggregate; + let attestation = &signed_aggregate_and_proof.message.aggregate; - let publish_status = self + match self .beacon_node - .http - .validator() - .publish_aggregate_and_proof(signed_aggregate_and_proofs) + .post_validator_aggregate_and_proof(&signed_aggregate_and_proof) .await - .map_err(|e| format!("Failed to publish aggregate and proofs: {:?}", e))?; - match publish_status { - PublishStatus::Valid => info!( + { + Ok(()) => info!( log, - "Successfully published attestations"; + "Successfully published attestation"; + "aggregator" => signed_aggregate_and_proof.message.aggregator_index, "signatures" => attestation.aggregation_bits.num_set_bits(), "head_block" => format!("{:?}", attestation.data.beacon_block_root), "committee_index" => attestation.data.index, "slot" => attestation.data.slot.as_u64(), "type" => "aggregated", ), - PublishStatus::Invalid(msg) => crit!( + Err(e) => crit!( log, - "Published attestation was invalid"; - "message" => msg, + "Failed to publish attestation"; + "error" => e.to_string(), "committee_index" => attestation.data.index, "slot" => attestation.data.slot.as_u64(), "type" => "aggregated", ), - PublishStatus::Unknown => { - crit!(log, "Unknown condition when publishing agg. attestation") - } - }; - Ok(()) - } else { - debug!( - log, - "No signed aggregates to publish"; - "committee_index" => attestation.data.index, - "slot" => attestation.data.slot.as_u64(), - ); - Ok(()) + } } + + Ok(()) } } diff --git a/validator_client/src/block_service.rs b/validator_client/src/block_service.rs index 60d1f4d5514..bf52cacfc0b 100644 --- a/validator_client/src/block_service.rs +++ b/validator_client/src/block_service.rs @@ -1,19 +1,19 @@ use crate::validator_store::ValidatorStore; use environment::RuntimeContext; +use eth2::{types::Graffiti, BeaconNodeHttpClient}; use futures::channel::mpsc::Receiver; use futures::{StreamExt, TryFutureExt}; -use remote_beacon_node::{PublishStatus, RemoteBeaconNode}; use slog::{crit, debug, error, info, trace, warn}; use slot_clock::SlotClock; use std::ops::Deref; use std::sync::Arc; -use types::{EthSpec, Graffiti, PublicKey, Slot}; +use types::{EthSpec, PublicKey, Slot}; /// Builds a `BlockService`. pub struct BlockServiceBuilder { validator_store: Option>, slot_clock: Option>, - beacon_node: Option>, + beacon_node: Option, context: Option>, graffiti: Option, } @@ -39,7 +39,7 @@ impl BlockServiceBuilder { self } - pub fn beacon_node(mut self, beacon_node: RemoteBeaconNode) -> Self { + pub fn beacon_node(mut self, beacon_node: BeaconNodeHttpClient) -> Self { self.beacon_node = Some(beacon_node); self } @@ -79,7 +79,7 @@ impl BlockServiceBuilder { pub struct Inner { validator_store: ValidatorStore, slot_clock: Arc, - beacon_node: RemoteBeaconNode, + beacon_node: BeaconNodeHttpClient, context: RuntimeContext, graffiti: Option, } @@ -221,41 +221,28 @@ impl BlockService { let block = self .beacon_node - .http - .validator() - .produce_block(slot, randao_reveal, self.graffiti) + .get_validator_blocks(slot, randao_reveal.into(), self.graffiti.as_ref()) .await - .map_err(|e| format!("Error from beacon node when producing block: {:?}", e))?; + .map_err(|e| format!("Error from beacon node when producing block: {:?}", e))? + .data; let signed_block = self .validator_store .sign_block(&validator_pubkey, block, current_slot) .ok_or_else(|| "Unable to sign block".to_string())?; - let publish_status = self - .beacon_node - .http - .validator() - .publish_block(signed_block.clone()) + self.beacon_node + .post_beacon_blocks(&signed_block) .await .map_err(|e| format!("Error from beacon node when publishing block: {:?}", e))?; - match publish_status { - PublishStatus::Valid => info!( - log, - "Successfully published block"; - "deposits" => signed_block.message.body.deposits.len(), - "attestations" => signed_block.message.body.attestations.len(), - "slot" => signed_block.slot().as_u64(), - ), - PublishStatus::Invalid(msg) => crit!( - log, - "Published block was invalid"; - "message" => msg, - "slot" => signed_block.slot().as_u64(), - ), - PublishStatus::Unknown => crit!(log, "Unknown condition when publishing block"), - } + info!( + log, + "Successfully published block"; + "deposits" => signed_block.message.body.deposits.len(), + "attestations" => signed_block.message.body.attestations.len(), + "slot" => signed_block.slot().as_u64(), + ); Ok(()) } diff --git a/validator_client/src/config.rs b/validator_client/src/config.rs index 991b5516220..4d230b1b445 100644 --- a/validator_client/src/config.rs +++ b/validator_client/src/config.rs @@ -4,9 +4,10 @@ use directory::{ get_testnet_name, DEFAULT_HARDCODED_TESTNET, DEFAULT_ROOT_DIR, DEFAULT_SECRET_DIR, DEFAULT_VALIDATOR_DIR, }; +use eth2::types::Graffiti; use serde_derive::{Deserialize, Serialize}; use std::path::PathBuf; -use types::{Graffiti, GRAFFITI_BYTES_LEN}; +use types::GRAFFITI_BYTES_LEN; pub const DEFAULT_HTTP_SERVER: &str = "http://localhost:5052/"; /// Path to the slashing protection database within the datadir. @@ -119,15 +120,14 @@ impl Config { GRAFFITI_BYTES_LEN )); } else { - // Default graffiti to all 0 bytes. - let mut graffiti = Graffiti::default(); + let mut graffiti = [0; 32]; // Copy the provided bytes over. // // Panic-free because `graffiti_bytes.len()` <= `GRAFFITI_BYTES_LEN`. graffiti[..graffiti_bytes.len()].copy_from_slice(&graffiti_bytes); - config.graffiti = Some(graffiti); + config.graffiti = Some(graffiti.into()); } } diff --git a/validator_client/src/duties_service.rs b/validator_client/src/duties_service.rs index 7375d550235..7f6d33fe85b 100644 --- a/validator_client/src/duties_service.rs +++ b/validator_client/src/duties_service.rs @@ -1,16 +1,15 @@ use crate::{ - block_service::BlockServiceNotification, is_synced::is_synced, validator_store::ValidatorStore, + block_service::BlockServiceNotification, is_synced::is_synced, validator_duty::ValidatorDuty, + validator_store::ValidatorStore, }; use environment::RuntimeContext; +use eth2::BeaconNodeHttpClient; use futures::channel::mpsc::Sender; use futures::{SinkExt, StreamExt}; use parking_lot::RwLock; -use remote_beacon_node::{PublishStatus, RemoteBeaconNode}; -use rest_types::{ValidatorDuty, ValidatorDutyBytes, ValidatorSubscription}; use slog::{debug, error, trace, warn}; use slot_clock::SlotClock; use std::collections::HashMap; -use std::convert::TryInto; use std::ops::Deref; use std::sync::Arc; use tokio::time::{interval_at, Duration, Instant}; @@ -44,14 +43,14 @@ impl DutyAndProof { pub fn compute_selection_proof( &mut self, validator_store: &ValidatorStore, + spec: &ChainSpec, ) -> Result<(), String> { - let (modulo, slot) = if let (Some(modulo), Some(slot)) = - (self.duty.aggregator_modulo, self.duty.attestation_slot) + let (committee_length, slot) = if let (Some(count), Some(slot)) = + (self.duty.committee_length, self.duty.attestation_slot) { - (modulo, slot) + (count as usize, slot) } else { - // If there is no modulo or for the aggregator we assume they are not activated and - // therefore not an aggregator. + // If there are no attester duties we assume the validator is inactive. self.selection_proof = None; return Ok(()); }; @@ -61,7 +60,7 @@ impl DutyAndProof { .ok_or_else(|| "Failed to produce selection proof".to_string())?; self.selection_proof = selection_proof - .is_aggregator_from_modulo(modulo) + .is_aggregator(committee_length, spec) .map_err(|e| format!("Invalid modulo: {:?}", e)) .map(|is_aggregator| { if is_aggregator { @@ -87,19 +86,20 @@ impl DutyAndProof { /// It's important to note that this doesn't actually check `self.selection_proof`, instead it /// checks to see if the inputs to computing the selection proof are equal. fn selection_proof_eq(&self, other: &Self) -> bool { - self.duty.aggregator_modulo == other.duty.aggregator_modulo + self.duty.committee_count_at_slot == other.duty.committee_count_at_slot && self.duty.attestation_slot == other.duty.attestation_slot } /// Returns the information required for an attesting validator, if they are scheduled to /// attest. - pub fn attestation_duties(&self) -> Option<(Slot, CommitteeIndex, usize, u64, u64)> { + pub fn attestation_duties(&self) -> Option<(Slot, CommitteeIndex, usize, u64, u64, u64)> { Some(( self.duty.attestation_slot?, self.duty.attestation_committee_index?, self.duty.attestation_committee_position?, self.duty.validator_index?, self.duty.committee_count_at_slot?, + self.duty.committee_length?, )) } @@ -108,26 +108,12 @@ impl DutyAndProof { } } -impl TryInto for ValidatorDutyBytes { - type Error = String; - - fn try_into(self) -> Result { - let duty = ValidatorDuty { - validator_pubkey: (&self.validator_pubkey) - .try_into() - .map_err(|e| format!("Invalid pubkey bytes from server: {:?}", e))?, - validator_index: self.validator_index, - attestation_slot: self.attestation_slot, - attestation_committee_index: self.attestation_committee_index, - attestation_committee_position: self.attestation_committee_position, - committee_count_at_slot: self.committee_count_at_slot, - block_proposal_slots: self.block_proposal_slots, - aggregator_modulo: self.aggregator_modulo, - }; - Ok(DutyAndProof { - duty, +impl Into for ValidatorDuty { + fn into(self) -> DutyAndProof { + DutyAndProof { + duty: self, selection_proof: None, - }) + } } } @@ -260,6 +246,7 @@ impl DutiesStore { mut duties: DutyAndProof, slots_per_epoch: u64, validator_store: &ValidatorStore, + spec: &ChainSpec, ) -> Result { let mut store = self.store.write(); @@ -282,7 +269,7 @@ impl DutiesStore { } } else { // Compute the selection proof. - duties.compute_selection_proof(validator_store)?; + duties.compute_selection_proof(validator_store, spec)?; // Determine if a re-subscription is required. let should_resubscribe = !duties.subscription_eq(known_duties); @@ -294,7 +281,7 @@ impl DutiesStore { } } else { // Compute the selection proof. - duties.compute_selection_proof(validator_store)?; + duties.compute_selection_proof(validator_store, spec)?; validator_map.insert(epoch, duties); @@ -302,7 +289,7 @@ impl DutiesStore { } } else { // Compute the selection proof. - duties.compute_selection_proof(validator_store)?; + duties.compute_selection_proof(validator_store, spec)?; let validator_pubkey = duties.duty.validator_pubkey.clone(); @@ -328,7 +315,7 @@ impl DutiesStore { pub struct DutiesServiceBuilder { validator_store: Option>, slot_clock: Option, - beacon_node: Option>, + beacon_node: Option, context: Option>, allow_unsynced_beacon_node: bool, } @@ -354,7 +341,7 @@ impl DutiesServiceBuilder { self } - pub fn beacon_node(mut self, beacon_node: RemoteBeaconNode) -> Self { + pub fn beacon_node(mut self, beacon_node: BeaconNodeHttpClient) -> Self { self.beacon_node = Some(beacon_node); self } @@ -397,7 +384,7 @@ pub struct Inner { store: Arc, validator_store: ValidatorStore, pub(crate) slot_clock: T, - pub(crate) beacon_node: RemoteBeaconNode, + pub(crate) beacon_node: BeaconNodeHttpClient, context: RuntimeContext, /// If true, the duties service will poll for duties from the beacon node even if it is not /// synced. @@ -462,7 +449,7 @@ impl DutiesService { pub fn start_update_service( self, mut block_service_tx: Sender, - spec: &ChainSpec, + spec: Arc, ) -> Result<(), String> { let duration_to_next_slot = self .slot_clock @@ -481,17 +468,22 @@ impl DutiesService { // Run an immediate update before starting the updater service. let duties_service = self.clone(); let mut block_service_tx_clone = block_service_tx.clone(); + let inner_spec = spec.clone(); self.inner .context .executor .runtime_handle() - .spawn(async move { duties_service.do_update(&mut block_service_tx_clone).await }); + .spawn(async move { + duties_service + .do_update(&mut block_service_tx_clone, &inner_spec) + .await + }); let executor = self.inner.context.executor.clone(); let interval_fut = async move { while interval.next().await.is_some() { - self.clone().do_update(&mut block_service_tx).await; + self.clone().do_update(&mut block_service_tx, &spec).await; } }; @@ -501,7 +493,11 @@ impl DutiesService { } /// Attempt to download the duties of all managed validators for this epoch and the next. - async fn do_update(self, block_service_tx: &mut Sender) { + async fn do_update( + self, + block_service_tx: &mut Sender, + spec: &ChainSpec, + ) { let log = self.context.log(); if !is_synced(&self.beacon_node, &self.slot_clock, None).await @@ -534,7 +530,11 @@ impl DutiesService { // Update duties for the current epoch, but keep running if there's an error: // block production or the next epoch update could still succeed. - if let Err(e) = self.clone().update_epoch(current_epoch).await { + if let Err(e) = self + .clone() + .update_epoch(current_epoch, current_epoch, spec) + .await + { error!( log, "Failed to get current epoch duties"; @@ -558,7 +558,11 @@ impl DutiesService { }; // Update duties for the next epoch. - if let Err(e) = self.clone().update_epoch(current_epoch + 1).await { + if let Err(e) = self + .clone() + .update_epoch(current_epoch, current_epoch + 1, spec) + .await + { error!( log, "Failed to get next epoch duties"; @@ -567,18 +571,15 @@ impl DutiesService { } } - /// Attempt to download the duties of all managed validators for the given `epoch`. - async fn update_epoch(self, epoch: Epoch) -> Result<(), String> { - let pubkeys = self.validator_store.voting_pubkeys(); - let all_duties = self - .beacon_node - .http - .validator() - .get_duties(epoch, pubkeys.as_slice()) - .await - .map_err(move |e| format!("Failed to get duties for epoch {}: {:?}", epoch, e))?; - - let log = self.context.log().clone(); + /// Attempt to download the duties of all managed validators for the given `request_epoch`. The + /// `current_epoch` should be a local reading of the slot clock. + async fn update_epoch( + self, + current_epoch: Epoch, + request_epoch: Epoch, + spec: &ChainSpec, + ) -> Result<(), String> { + let log = self.context.log(); let mut new_validator = 0; let mut new_epoch = 0; @@ -587,74 +588,76 @@ impl DutiesService { let mut replaced = 0; let mut invalid = 0; - // For each of the duties, attempt to insert them into our local store and build a - // list of new or changed selections proofs for any aggregating validators. - let validator_subscriptions = all_duties - .into_iter() - .filter_map(|remote_duties| { - // Convert the remote duties into our local representation. - let duties: DutyAndProof = remote_duties - .clone() - .try_into() - .map_err(|e| { - error!( - log, - "Unable to convert remote duties"; - "error" => e - ) - }) - .ok()?; - - let validator_pubkey = duties.duty.validator_pubkey.clone(); - - // Attempt to update our local store. - let outcome = self - .store - .insert(epoch, duties, E::slots_per_epoch(), &self.validator_store) - .map_err(|e| { - error!( - log, - "Unable to store duties"; - "error" => e - ) - }) - .ok()?; - - match &outcome { - InsertOutcome::NewValidator => { - debug!( - log, - "First duty assignment for validator"; - "proposal_slots" => format!("{:?}", &remote_duties.block_proposal_slots), - "attestation_slot" => format!("{:?}", &remote_duties.attestation_slot), - "validator" => format!("{:?}", &remote_duties.validator_pubkey) - ); - new_validator += 1; + let mut validator_subscriptions = vec![]; + for pubkey in self.validator_store.voting_pubkeys() { + let remote_duties = match ValidatorDuty::download( + &self.beacon_node, + current_epoch, + request_epoch, + pubkey, + ) + .await + { + Ok(duties) => duties, + Err(e) => { + error!( + log, + "Failed to download validator duties"; + "error" => e + ); + continue; + } + }; + + // Convert the remote duties into our local representation. + let duties: DutyAndProof = remote_duties.clone().into(); + + let validator_pubkey = duties.duty.validator_pubkey.clone(); + + // Attempt to update our local store. + match self.store.insert( + request_epoch, + duties, + E::slots_per_epoch(), + &self.validator_store, + spec, + ) { + Ok(outcome) => { + match &outcome { + InsertOutcome::NewValidator => { + debug!( + log, + "First duty assignment for validator"; + "proposal_slots" => format!("{:?}", &remote_duties.block_proposal_slots), + "attestation_slot" => format!("{:?}", &remote_duties.attestation_slot), + "validator" => format!("{:?}", &remote_duties.validator_pubkey) + ); + new_validator += 1; + } + InsertOutcome::NewProposalSlots => new_proposal_slots += 1, + InsertOutcome::NewEpoch => new_epoch += 1, + InsertOutcome::Identical => identical += 1, + InsertOutcome::Replaced { .. } => replaced += 1, + InsertOutcome::Invalid => invalid += 1, + } + + if let Some(is_aggregator) = + self.store.is_aggregator(&validator_pubkey, request_epoch) + { + if outcome.is_subscription_candidate() { + if let Some(subscription) = remote_duties.subscription(is_aggregator) { + validator_subscriptions.push(subscription) + } + } } - InsertOutcome::NewProposalSlots => new_proposal_slots += 1, - InsertOutcome::NewEpoch => new_epoch += 1, - InsertOutcome::Identical => identical += 1, - InsertOutcome::Replaced { .. } => replaced += 1, - InsertOutcome::Invalid => invalid += 1, - }; - - // The selection proof is computed on `store.insert`, so it's necessary to check - // with the store that the validator is an aggregator. - let is_aggregator = self.store.is_aggregator(&validator_pubkey, epoch)?; - - if outcome.is_subscription_candidate() { - Some(ValidatorSubscription { - validator_index: remote_duties.validator_index?, - attestation_committee_index: remote_duties.attestation_committee_index?, - slot: remote_duties.attestation_slot?, - committee_count_at_slot: remote_duties.committee_count_at_slot?, - is_aggregator, - }) - } else { - None } - }) - .collect::>(); + Err(e) => error!( + log, + "Unable to store duties"; + "error" => e + ), + } + } if invalid > 0 { error!( @@ -673,7 +676,7 @@ impl DutiesService { "new_proposal_slots" => new_proposal_slots, "new_validator" => new_validator, "replaced" => replaced, - "epoch" => format!("{}", epoch) + "epoch" => format!("{}", request_epoch) ); if replaced > 0 { @@ -690,34 +693,19 @@ impl DutiesService { if count == 0 { debug!(log, "No new subscriptions required"); - - Ok(()) } else { self.beacon_node - .http - .validator() - .subscribe(validator_subscriptions) + .post_validator_beacon_committee_subscriptions(&validator_subscriptions) .await - .map_err(|e| format!("Failed to subscribe validators: {:?}", e)) - .map(move |status| { - match status { - PublishStatus::Valid => debug!( - log, - "Successfully subscribed validators"; - "count" => count - ), - PublishStatus::Unknown => error!( - log, - "Unknown response from subscription"; - ), - PublishStatus::Invalid(e) => error!( - log, - "Failed to subscribe validator"; - "error" => e - ), - }; - }) + .map_err(|e| format!("Failed to subscribe validators: {:?}", e))?; + debug!( + log, + "Successfully subscribed validators"; + "count" => count + ); } + + Ok(()) } } diff --git a/validator_client/src/fork_service.rs b/validator_client/src/fork_service.rs index b8db7b72e3c..e38a4cf3c1b 100644 --- a/validator_client/src/fork_service.rs +++ b/validator_client/src/fork_service.rs @@ -1,7 +1,7 @@ use environment::RuntimeContext; +use eth2::{types::StateId, BeaconNodeHttpClient}; use futures::StreamExt; use parking_lot::RwLock; -use remote_beacon_node::RemoteBeaconNode; use slog::{debug, trace}; use slot_clock::SlotClock; use std::ops::Deref; @@ -16,7 +16,7 @@ const TIME_DELAY_FROM_SLOT: Duration = Duration::from_millis(80); pub struct ForkServiceBuilder { fork: Option, slot_clock: Option, - beacon_node: Option>, + beacon_node: Option, context: Option>, } @@ -35,7 +35,7 @@ impl ForkServiceBuilder { self } - pub fn beacon_node(mut self, beacon_node: RemoteBeaconNode) -> Self { + pub fn beacon_node(mut self, beacon_node: BeaconNodeHttpClient) -> Self { self.beacon_node = Some(beacon_node); self } @@ -66,7 +66,7 @@ impl ForkServiceBuilder { /// Helper to minimise `Arc` usage. pub struct Inner { fork: RwLock>, - beacon_node: RemoteBeaconNode, + beacon_node: BeaconNodeHttpClient, context: RuntimeContext, slot_clock: T, } @@ -141,9 +141,7 @@ impl ForkService { let fork = self .inner .beacon_node - .http - .beacon() - .get_fork() + .get_beacon_states_fork(StateId::Head) .await .map_err(|e| { trace!( @@ -151,7 +149,15 @@ impl ForkService { "Fork update failed"; "error" => format!("Error retrieving fork: {:?}", e) ) - })?; + })? + .ok_or_else(|| { + trace!( + log, + "Fork update failed"; + "error" => "The beacon head fork is unknown" + ) + })? + .data; if self.fork.read().as_ref() != Some(&fork) { *(self.fork.write()) = Some(fork); diff --git a/validator_client/src/initialized_validators.rs b/validator_client/src/initialized_validators.rs index 400768f5cb4..a097d72456e 100644 --- a/validator_client/src/initialized_validators.rs +++ b/validator_client/src/initialized_validators.rs @@ -50,8 +50,6 @@ pub enum Error { UnableToSaveDefinitions(validator_definitions::Error), /// It is not legal to try and initialize a disabled validator definition. UnableToInitializeDisabledValidator, - /// It is not legal to try and initialize a disabled validator definition. - PasswordUnknown(PathBuf), /// There was an error reading from stdin. UnableToReadPasswordFromUser(String), /// There was an error running a tokio async task. @@ -333,6 +331,7 @@ 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, diff --git a/validator_client/src/is_synced.rs b/validator_client/src/is_synced.rs index e1017ac7719..f967d629c10 100644 --- a/validator_client/src/is_synced.rs +++ b/validator_client/src/is_synced.rs @@ -1,8 +1,6 @@ -use remote_beacon_node::RemoteBeaconNode; -use rest_types::SyncingResponse; -use slog::{debug, error, Logger}; +use eth2::BeaconNodeHttpClient; +use slog::{debug, error, warn, Logger}; use slot_clock::SlotClock; -use types::EthSpec; /// A distance in slots. const SYNC_TOLERANCE: u64 = 4; @@ -17,19 +15,19 @@ const SYNC_TOLERANCE: u64 = 4; /// /// The second condition means the even if the beacon node thinks that it's syncing, we'll still /// try to use it if it's close enough to the head. -pub async fn is_synced( - beacon_node: &RemoteBeaconNode, +pub async fn is_synced( + beacon_node: &BeaconNodeHttpClient, slot_clock: &T, log_opt: Option<&Logger>, ) -> bool { - let resp = match beacon_node.http.node().syncing_status().await { + let resp = match beacon_node.get_node_syncing().await { Ok(resp) => resp, Err(e) => { if let Some(log) = log_opt { error!( log, "Unable connect to beacon node"; - "error" => format!("{:?}", e) + "error" => e.to_string() ) } @@ -37,44 +35,38 @@ pub async fn is_synced( } }; - match &resp { - SyncingResponse { - is_syncing: false, .. - } => true, - SyncingResponse { - is_syncing: true, - sync_status, - } => { - if let Some(log) = log_opt { - debug!( - log, - "Beacon node sync status"; - "status" => format!("{:?}", resp), - ); - } + let is_synced = !resp.data.is_syncing || (resp.data.sync_distance.as_u64() < SYNC_TOLERANCE); + + if let Some(log) = log_opt { + if !is_synced { + debug!( + log, + "Beacon node sync status"; + "status" => format!("{:?}", resp), + ); - let now = if let Some(slot) = slot_clock.now() { - slot - } else { - // There's no good reason why we shouldn't be able to read the slot clock, so we'll - // indicate we're not synced if that's the case. - return false; - }; + warn!( + log, + "Beacon node is syncing"; + "msg" => "not receiving new duties", + "sync_distance" => resp.data.sync_distance.as_u64(), + "head_slot" => resp.data.head_slot.as_u64(), + ); + } - if sync_status.current_slot + SYNC_TOLERANCE >= now { - true - } else { - if let Some(log) = log_opt { - error!( - log, - "Beacon node is syncing"; - "msg" => "not receiving new duties", - "target_slot" => sync_status.highest_slot.as_u64(), - "current_slot" => sync_status.current_slot.as_u64(), - ); - } - false + if let Some(local_slot) = slot_clock.now() { + let remote_slot = resp.data.head_slot + resp.data.sync_distance; + if remote_slot + 1 < local_slot || local_slot + 1 < remote_slot { + error!( + log, + "Time discrepancy with beacon node"; + "msg" => "check the system time on this host and the beacon node", + "beacon_node_slot" => remote_slot, + "local_slot" => local_slot, + ); } } } + + is_synced } diff --git a/validator_client/src/lib.rs b/validator_client/src/lib.rs index 6d82baa6bfb..8a0e8ba1edb 100644 --- a/validator_client/src/lib.rs +++ b/validator_client/src/lib.rs @@ -7,6 +7,7 @@ mod fork_service; mod initialized_validators; mod is_synced; mod notifier; +mod validator_duty; mod validator_store; pub use cli::cli_app; @@ -18,18 +19,18 @@ use block_service::{BlockService, BlockServiceBuilder}; use clap::ArgMatches; use duties_service::{DutiesService, DutiesServiceBuilder}; use environment::RuntimeContext; -use eth2_config::Eth2Config; +use eth2::{reqwest::ClientBuilder, BeaconNodeHttpClient, StatusCode, Url}; use fork_service::{ForkService, ForkServiceBuilder}; use futures::channel::mpsc; use initialized_validators::InitializedValidators; use notifier::spawn_notifier; -use remote_beacon_node::RemoteBeaconNode; use slog::{error, info, Logger}; use slot_clock::SlotClock; use slot_clock::SystemTimeSlotClock; +use std::sync::Arc; use std::time::{SystemTime, UNIX_EPOCH}; use tokio::time::{delay_for, Duration}; -use types::{EthSpec, Hash256}; +use types::{EthSpec, Hash256, YamlConfig}; use validator_store::ValidatorStore; /// The interval between attempts to contact the beacon node during startup. @@ -61,7 +62,7 @@ impl ProductionValidatorClient { /// Instantiates the validator client, _without_ starting the timers to trigger block /// and attestation production. - pub async fn new(mut context: RuntimeContext, config: Config) -> Result { + pub async fn new(context: RuntimeContext, config: Config) -> Result { let log = context.log().clone(); info!( @@ -104,33 +105,36 @@ impl ProductionValidatorClient { "enabled" => validators.num_enabled(), ); + let beacon_node_url: Url = config + .http_server + .parse() + .map_err(|e| format!("Unable to parse beacon node URL: {:?}", e))?; + let beacon_node_http_client = ClientBuilder::new() + .timeout(HTTP_TIMEOUT) + .build() + .map_err(|e| format!("Unable to build HTTP client: {:?}", e))?; let beacon_node = - RemoteBeaconNode::new_with_timeout(config.http_server.clone(), HTTP_TIMEOUT) - .map_err(|e| format!("Unable to init beacon node http client: {}", e))?; + BeaconNodeHttpClient::from_components(beacon_node_url, beacon_node_http_client); // Perform some potentially long-running initialization tasks. - let (eth2_config, genesis_time, genesis_validators_root) = tokio::select! { + let (yaml_config, genesis_time, genesis_validators_root) = tokio::select! { tuple = init_from_beacon_node(&beacon_node, &context) => tuple?, () = context.executor.exit() => return Err("Shutting down".to_string()) }; - - // Do not permit a connection to a beacon node using different spec constants. - if context.eth2_config.spec_constants != eth2_config.spec_constants { - return Err(format!( - "Beacon node is using an incompatible spec. Got {}, expected {}", - eth2_config.spec_constants, context.eth2_config.spec_constants - )); + let beacon_node_spec = yaml_config.apply_to_chain_spec::(&T::default_spec()) + .ok_or_else(|| + "The minimal/mainnet spec type of the beacon node does not match the validator client. \ + See the --testnet command.".to_string() + )?; + + if context.eth2_config.spec != beacon_node_spec { + return Err( + "The beacon node is using a different Eth2 specification to this validator client. \ + See the --testnet command." + .to_string(), + ); } - // Note: here we just assume the spec variables of the remote node. This is very useful - // for testnets, but perhaps a security issue when it comes to mainnet. - // - // A damaging attack would be for a beacon node to convince the validator client of a - // different `SLOTS_PER_EPOCH` variable. This could result in slashable messages being - // produced. We are safe from this because `SLOTS_PER_EPOCH` is a type-level constant - // for Lighthouse. - context.eth2_config = eth2_config; - let slot_clock = SystemTimeSlotClock::new( context.eth2_config.spec.genesis_slot, Duration::from_secs(genesis_time), @@ -203,7 +207,10 @@ impl ProductionValidatorClient { self.duties_service .clone() - .start_update_service(block_service_tx, &self.context.eth2_config.spec) + .start_update_service( + block_service_tx, + Arc::new(self.context.eth2_config.spec.clone()), + ) .map_err(|e| format!("Unable to start duties service: {}", e))?; self.fork_service @@ -228,80 +235,85 @@ impl ProductionValidatorClient { } async fn init_from_beacon_node( - beacon_node: &RemoteBeaconNode, + beacon_node: &BeaconNodeHttpClient, context: &RuntimeContext, -) -> Result<(Eth2Config, u64, Hash256), String> { +) -> Result<(YamlConfig, u64, Hash256), String> { // Wait for the beacon node to come online. wait_for_node(beacon_node, context.log()).await?; - let eth2_config = beacon_node - .http - .spec() - .get_eth2_config() + let yaml_config = beacon_node + .get_config_spec() .await - .map_err(|e| format!("Unable to read eth2 config from beacon node: {:?}", e))?; - let genesis_time = beacon_node - .http - .beacon() - .get_genesis_time() - .await - .map_err(|e| format!("Unable to read genesis time from beacon node: {:?}", e))?; + .map_err(|e| format!("Unable to read spec from beacon node: {:?}", e))? + .data; + + let genesis = loop { + match beacon_node.get_beacon_genesis().await { + Ok(genesis) => break genesis.data, + Err(e) => { + // A 404 error on the genesis endpoint indicates that genesis has not yet occurred. + if e.status() == Some(StatusCode::NOT_FOUND) { + info!( + context.log(), + "Waiting for genesis"; + ); + } else { + error!( + context.log(), + "Error polling beacon node"; + "error" => format!("{:?}", e) + ); + } + } + } + + delay_for(RETRY_DELAY).await; + }; + let now = SystemTime::now() .duration_since(UNIX_EPOCH) .map_err(|e| format!("Unable to read system time: {:?}", e))?; - let genesis = Duration::from_secs(genesis_time); + let genesis_time = Duration::from_secs(genesis.genesis_time); // If the time now is less than (prior to) genesis, then delay until the // genesis instant. // // If the validator client starts before genesis, it will get errors from // the slot clock. - if now < genesis { + if now < genesis_time { info!( context.log(), "Starting node prior to genesis"; - "seconds_to_wait" => (genesis - now).as_secs() + "seconds_to_wait" => (genesis_time - now).as_secs() ); - delay_for(genesis - now).await; + delay_for(genesis_time - now).await; } else { info!( context.log(), "Genesis has already occurred"; - "seconds_ago" => (now - genesis).as_secs() + "seconds_ago" => (now - genesis_time).as_secs() ); } - let genesis_validators_root = beacon_node - .http - .beacon() - .get_genesis_validators_root() - .await - .map_err(|e| { - format!( - "Unable to read genesis validators root from beacon node: {:?}", - e - ) - })?; - Ok((eth2_config, genesis_time, genesis_validators_root)) + Ok(( + yaml_config, + genesis.genesis_time, + genesis.genesis_validators_root, + )) } /// Request the version from the node, looping back and trying again on failure. Exit once the node /// has been contacted. -async fn wait_for_node( - beacon_node: &RemoteBeaconNode, - log: &Logger, -) -> Result<(), String> { +async fn wait_for_node(beacon_node: &BeaconNodeHttpClient, log: &Logger) -> Result<(), String> { // Try to get the version string from the node, looping until success is returned. loop { let log = log.clone(); let result = beacon_node - .clone() - .http - .node() - .get_version() + .get_node_version() .await - .map_err(|e| format!("{:?}", e)); + .map_err(|e| format!("{:?}", e)) + .map(|body| body.data.version); match result { Ok(version) => { diff --git a/validator_client/src/validator_duty.rs b/validator_client/src/validator_duty.rs new file mode 100644 index 00000000000..e5f56c38555 --- /dev/null +++ b/validator_client/src/validator_duty.rs @@ -0,0 +1,131 @@ +use eth2::{ + types::{BeaconCommitteeSubscription, StateId, ValidatorId}, + BeaconNodeHttpClient, +}; +use serde::{Deserialize, Serialize}; +use types::{CommitteeIndex, Epoch, PublicKey, PublicKeyBytes, Slot}; + +/// This struct is being used as a shim since we deprecated the `rest_api` in favour of `http_api`. +/// +/// Tracking issue: https://github.com/sigp/lighthouse/issues/1643 +// NOTE: if you add or remove fields, please adjust `eq_ignoring_proposal_slots` +#[derive(PartialEq, Debug, Serialize, Deserialize, Clone)] +pub struct ValidatorDuty { + /// The validator's BLS public key, uniquely identifying them. + pub validator_pubkey: PublicKey, + /// The validator's index in `state.validators` + pub validator_index: Option, + /// The slot at which the validator must attest. + pub attestation_slot: Option, + /// The index of the committee within `slot` of which the validator is a member. + pub attestation_committee_index: Option, + /// The position of the validator in the committee. + pub attestation_committee_position: Option, + /// The committee count at `attestation_slot`. + pub committee_count_at_slot: Option, + /// The number of validators in the committee. + pub committee_length: Option, + /// The slots in which a validator must propose a block (can be empty). + /// + /// Should be set to `None` when duties are not yet known (before the current epoch). + pub block_proposal_slots: Option>, +} + +impl ValidatorDuty { + /// Instantiate `Self` as if there are no known dutes for `validator_pubkey`. + fn no_duties(validator_pubkey: PublicKey) -> Self { + ValidatorDuty { + validator_pubkey, + validator_index: None, + attestation_slot: None, + attestation_committee_index: None, + attestation_committee_position: None, + committee_count_at_slot: None, + committee_length: None, + block_proposal_slots: None, + } + } + + /// Instantiate `Self` by performing requests on the `beacon_node`. + /// + /// Will only request proposer duties if `current_epoch == request_epoch`. + pub async fn download( + beacon_node: &BeaconNodeHttpClient, + current_epoch: Epoch, + request_epoch: Epoch, + pubkey: PublicKey, + ) -> Result { + let pubkey_bytes = PublicKeyBytes::from(&pubkey); + + let validator_index = if let Some(index) = beacon_node + .get_beacon_states_validator_id( + StateId::Head, + &ValidatorId::PublicKey(pubkey_bytes.clone()), + ) + .await + .map_err(|e| format!("Failed to get validator index: {}", e))? + .map(|body| body.data.index) + { + index + } else { + return Ok(Self::no_duties(pubkey)); + }; + + if let Some(attester) = beacon_node + .get_validator_duties_attester(request_epoch, Some(&[validator_index])) + .await + .map_err(|e| format!("Failed to get attester duties: {}", e))? + .data + .first() + { + let block_proposal_slots = if current_epoch == request_epoch { + beacon_node + .get_validator_duties_proposer(current_epoch) + .await + .map_err(|e| format!("Failed to get proposer indices: {}", e))? + .data + .into_iter() + .filter(|data| data.pubkey == pubkey_bytes) + .map(|data| data.slot) + .collect() + } else { + vec![] + }; + + Ok(ValidatorDuty { + validator_pubkey: pubkey, + validator_index: Some(attester.validator_index), + attestation_slot: Some(attester.slot), + attestation_committee_index: Some(attester.committee_index), + attestation_committee_position: Some(attester.validator_committee_index as usize), + committee_count_at_slot: Some(attester.committees_at_slot), + committee_length: Some(attester.committee_length), + block_proposal_slots: Some(block_proposal_slots), + }) + } else { + Ok(Self::no_duties(pubkey)) + } + } + + /// Return `true` if these validator duties are equal, ignoring their `block_proposal_slots`. + pub fn eq_ignoring_proposal_slots(&self, other: &Self) -> bool { + self.validator_pubkey == other.validator_pubkey + && self.validator_index == other.validator_index + && self.attestation_slot == other.attestation_slot + && self.attestation_committee_index == other.attestation_committee_index + && self.attestation_committee_position == other.attestation_committee_position + && self.committee_count_at_slot == other.committee_count_at_slot + && self.committee_length == other.committee_length + } + + /// Generate a subscription for `self`, if `self` has appropriate attestation duties. + pub fn subscription(&self, is_aggregator: bool) -> Option { + Some(BeaconCommitteeSubscription { + validator_index: self.validator_index?, + committee_index: self.attestation_committee_index?, + committees_at_slot: self.committee_count_at_slot?, + slot: self.attestation_slot?, + is_aggregator, + }) + } +}