Eth1 Integration (#542)
* Refactor to cache Eth1Data * Fix merge conflicts and minor refactorings * Rename Eth1Cache to Eth1DataCache * Refactor events subscription * Add deposits module to interface with BeaconChain deposits * Remove utils * Rename to types.rs and add trait constraints to Eth1DataFetcher * Confirm to trait constraints. Make Web3DataFetcher cloneable * Make fetcher object member of deposit and eth1_data cache and other fixes * Fix update_cache function * Move fetch_eth1_data to impl block * Fix deposit tests * Create Eth1 object for interfacing with Beacon chain * Add `run` function for running update_cache and subscribe_deposit_logs tasks * Add logging * Run `cargo fmt` and make tests pass * Convert sync functions to async * Add timeouts to web3 functions * Return futures from cache functions * Add failed chaining of futures * Working cache updation * Clean up tests and `update_cache` function * Refactor `get_eth1_data` functions to work with future returning functions * Refactor eth1 `run` function to work with modified `update_cache` api * Minor changes * Add distance parameter to `update_cache` * Fix tests and other minor fixes * Working integration with cache and deposits * Add merkle_tree construction, proof generation and verification code * Add function to construct and fetch Deposits for BeaconNode * Add error handling * Import ssz * Add error handling to eth1 cache and fix minor errors * Run rustfmt * Fix minor bug * Rename Eth1Error and change to Result<T> * Change deposit fetching mechanism from notification based to poll based * Add deposits from eth1 chain in a given range every `x` blocks * Modify `run` function to accommodate changes * Minor fixes * Fix formatting * Initial commit. web3 api working. * Tidied up lib. Add function for fetching logs. * Refactor with `Eth1DataFetcher` trait * Add parsing for deposit contract logs and get_eth1_data function * Add `get_eth1_votes` function * Refactor to cache Eth1Data * Fix merge conflicts and minor refactorings * Rename Eth1Cache to Eth1DataCache * Refactor events subscription * Add deposits module to interface with BeaconChain deposits * Remove utils * Rename to types.rs and add trait constraints to Eth1DataFetcher * Confirm to trait constraints. Make Web3DataFetcher cloneable * Make fetcher object member of deposit and eth1_data cache and other fixes * Fix update_cache function * Move fetch_eth1_data to impl block * Fix deposit tests * Create Eth1 object for interfacing with Beacon chain * Add `run` function for running update_cache and subscribe_deposit_logs tasks * Add logging * Run `cargo fmt` and make tests pass * Convert sync functions to async * Add timeouts to web3 functions * Return futures from cache functions * Add failed chaining of futures * Working cache updation * Clean up tests and `update_cache` function * Refactor `get_eth1_data` functions to work with future returning functions * Refactor eth1 `run` function to work with modified `update_cache` api * Minor changes * Add distance parameter to `update_cache` * Fix tests and other minor fixes * Working integration with cache and deposits * Add merkle_tree construction, proof generation and verification code * Add function to construct and fetch Deposits for BeaconNode * Add error handling * Import ssz * Add error handling to eth1 cache and fix minor errors * Run rustfmt * Fix minor bug * Rename Eth1Error and change to Result<T> * Change deposit fetching mechanism from notification based to poll based * Add deposits from eth1 chain in a given range every `x` blocks * Modify `run` function to accommodate changes * Minor fixes * Fix formatting * Fix merge issue * Refactor with `Config` struct. Remote `ContractConfig` * Rename eth1_chain crate to eth1 * Rename files and read abi file using `fs::read` * Move eth1 to lib * Remove unnecessary mutability constraint * Add `Web3Backend` for returning actual eth1 data * Refactor `get_eth1_votes` to return a Result * Delete `eth1_chain` crate * Return `Result` from `get_deposits` * Fix range of deposits to return to beacon chain * Add `get_block_height_by_hash` trait function * Add naive method for getting `previous_eth1_distance` * Add eth1 config params to main config * Add instructions for setting up eth1 testing environment * Add build script to fetch deposit contract abi * Contract ABI is part of compiled binary * Fix minor bugs * Move docs to lib * Add timeout to config * Remove print statements * Change warn to error * Fix typos * Removed prints in test and get timeout value from config * Fixed error types * Added logging to web3_fetcher * Refactor for modified web3 api * Fix minor stuff * Add build script * Tidy, hide eth1 integration tests behind flag * Add http crate * Add first stages of eth1_test_rig * Fix deposits on test rig * Fix bug with deposit count method * Add block hash getter to http eth1 * Clean eth1 http crate and tests * Add script to start ganache * Adds deposit tree to eth1-http * Extend deposit tree tests * Tidy tests in eth1-http * Add more detail to get block request * Add block cache to eth1-http * Rename deposit tree to deposit cache * Add inital updating to eth1-http * Tidy updater * Fix compile bugs in tests * Adds an Eth1DataCache builder * Reorg eth1-http files * Add (failing) tests for eth1 updater * Rename files, fix bug in eth1-http * Ensure that ganache timestamps are increasing * Fix bugs with getting eth1data ancestors * Improve eth1 testing, fix bugs * Add truncate method to block cache * Add pruning to block cache update process * Add tests for block pruning * Allow for dropping an expired cache. * Add more comments * Add first compiling version of deposit updater * Add common fn for getting range of required blocks * Add passing deposit update test * Improve tests * Fix block pruning bug * Add tests for running two updates at once * Add updater services to eth1 * Add deposit collection to beacon chain * Add incomplete builder experiments * Add first working version of beacon chain builder * Update test harness to new beacon chain type * Rename builder file, tidy * Add first working client builder * Progress further on client builder * Update becaon node binary to use client builder * Ensure release tests compile * Remove old eth1 crate * Add first pass of new lighthouse binary * Fix websocket server startup * Remove old binary code from beacon_node crate * Add first working beacon node tests * Add genesis crate, new eth1 cache_2 * Add Serivce to Eth1Cache * Refactor with general eth1 improvements * Add passing genesis test * Tidy, add comments * Add more comments to eth1 service * Add further eth1 progress * Fix some bugs with genesis * Fix eth1 bugs, make eth1 linking more efficient * Shift logic in genesis service * Add more comments to genesis service * Add gzip, max request values, timeouts to http * Update testnet parameters to suit goerli testnet * Add ability to vary Fork, fix custom spec * Be more explicit about deposit fork version * Start adding beacon chain eth1 option * Add more flexibility to prod client * Further runtime refactoring * Allow for starting from store * Add bootstrapping to client config * Add remote_beacon_node crate * Update eth1 service for more configurability * Update eth1 tests to use less runtimes * Patch issues with tests using too many files * Move dummy eth1 backend flag * Ensure all tests pass * Add ganache-cli to Dockerfile * Use a special docker hub image for testing * Appease clippy * Move validator client into lighthouse binary * Allow starting with dummy eth1 backend * Improve logging * Fix dummy eth1 backend from cli * Add extra testnet command * Ensure consistent spec in beacon node * Update eth1 rig to work on goerli * Tidy lcli, start adding support for yaml config * Add incomplete YamlConfig struct * Remove efforts at YamlConfig * Add incomplete eth1 voting. Blocked on spec issues * Add (untested) first pass at eth1 vote algo * Add tests for winning vote * Add more tests for eth1 chain * Add more eth1 voting tests * Added more eth1 voting testing * Change test name * Add more tests to eth1 chain * Tidy eth1 generics, add more tests * Improve comments * Tidy beacon_node tests * Tidy, rename JsonRpc.. to Caching.. * Tidy voting logic * Tidy builder docs * Add comments, tidy eth1 * Add more comments to eth1 * Fix bug with winning_vote * Add doc comments to the `ClientBuilder` * Remove commented-out code * Improve `ClientBuilder` docs * Add comments to client config * Add decoding test for `ClientConfig` * Remove unused `DepositSet` struct * Tidy `block_cache` * Remove commented out lines * Remove unused code in `eth1` crate * Remove old validator binary `main.rs` * Tidy, fix tests compile error * Add initial tests for get_deposits * Remove dead code in eth1_test_rig * Update TestingDepositBuilder * Add testing for getting eth1 deposits * Fix duplicate rand dep * Remove dead code * Remove accidentally-added files * Fix comment in eth1_genesis_service * Add .gitignore for eth1_test_rig * Fix bug in eth1_genesis_service * Remove dead code from eth2_config * Fix tabs/spaces in root Cargo.toml * Tidy eth1 crate * Allow for re-use of eth1 service after genesis * Update docs for new CLI * Change README gif * Tidy eth1 http module * Tidy eth1 service * Tidy environment crate * Remove unused file * Tidy, add comments * Remove commented-out code * Address majority of Michael's comments * Address other PR comments * Add link to issue alongside TODO
This commit is contained in:
@@ -5,7 +5,7 @@ extern crate lazy_static;
|
||||
|
||||
use beacon_chain::test_utils::{
|
||||
generate_deterministic_keypairs, AttestationStrategy,
|
||||
BeaconChainHarness as BaseBeaconChainHarness, BlockStrategy,
|
||||
BeaconChainHarness as BaseBeaconChainHarness, BlockStrategy, HarnessType,
|
||||
};
|
||||
use lmd_ghost::{LmdGhost, ThreadSafeReducedTree as BaseThreadSafeReducedTree};
|
||||
use rand::{prelude::*, rngs::StdRng};
|
||||
@@ -21,7 +21,7 @@ pub const VALIDATOR_COUNT: usize = 3 * 8;
|
||||
|
||||
type TestEthSpec = MinimalEthSpec;
|
||||
type ThreadSafeReducedTree = BaseThreadSafeReducedTree<MemoryStore, TestEthSpec>;
|
||||
type BeaconChainHarness = BaseBeaconChainHarness<ThreadSafeReducedTree, TestEthSpec>;
|
||||
type BeaconChainHarness = BaseBeaconChainHarness<HarnessType<TestEthSpec>>;
|
||||
type RootAndSlot = (Hash256, Slot);
|
||||
|
||||
lazy_static! {
|
||||
@@ -52,7 +52,10 @@ struct ForkedHarness {
|
||||
impl ForkedHarness {
|
||||
/// A new standard instance of with constant parameters.
|
||||
pub fn new() -> Self {
|
||||
let harness = BeaconChainHarness::new(generate_deterministic_keypairs(VALIDATOR_COUNT));
|
||||
let harness = BeaconChainHarness::new(
|
||||
MinimalEthSpec,
|
||||
generate_deterministic_keypairs(VALIDATOR_COUNT),
|
||||
);
|
||||
|
||||
// Move past the zero slot.
|
||||
harness.advance_slot();
|
||||
|
||||
@@ -598,7 +598,7 @@ mod tests {
|
||||
|
||||
let mut state = BeaconState::random_for_test(rng);
|
||||
|
||||
state.fork = Fork::genesis(MainnetEthSpec::genesis_epoch());
|
||||
state.fork = Fork::default();
|
||||
|
||||
(spec, state)
|
||||
}
|
||||
|
||||
@@ -35,18 +35,7 @@ pub fn initialize_beacon_state_from_eth1<T: EthSpec>(
|
||||
process_deposit(&mut state, &deposit, spec, true)?;
|
||||
}
|
||||
|
||||
// Process activations
|
||||
for (index, validator) in state.validators.iter_mut().enumerate() {
|
||||
let balance = state.balances[index];
|
||||
validator.effective_balance = std::cmp::min(
|
||||
balance - balance % spec.effective_balance_increment,
|
||||
spec.max_effective_balance,
|
||||
);
|
||||
if validator.effective_balance == spec.max_effective_balance {
|
||||
validator.activation_eligibility_epoch = T::genesis_epoch();
|
||||
validator.activation_epoch = T::genesis_epoch();
|
||||
}
|
||||
}
|
||||
process_activations(&mut state, spec);
|
||||
|
||||
// Now that we have our validators, initialize the caches (including the committees)
|
||||
state.build_all_caches(spec)?;
|
||||
@@ -71,3 +60,20 @@ pub fn is_valid_genesis_state<T: EthSpec>(state: &BeaconState<T>, spec: &ChainSp
|
||||
&& state.get_active_validator_indices(T::genesis_epoch()).len() as u64
|
||||
>= spec.min_genesis_active_validator_count
|
||||
}
|
||||
|
||||
/// Activate genesis validators, if their balance is acceptable.
|
||||
///
|
||||
/// Spec v0.8.0
|
||||
pub fn process_activations<T: EthSpec>(state: &mut BeaconState<T>, spec: &ChainSpec) {
|
||||
for (index, validator) in state.validators.iter_mut().enumerate() {
|
||||
let balance = state.balances[index];
|
||||
validator.effective_balance = std::cmp::min(
|
||||
balance - balance % spec.effective_balance_increment,
|
||||
spec.max_effective_balance,
|
||||
);
|
||||
if validator.effective_balance == spec.max_effective_balance {
|
||||
validator.activation_eligibility_epoch = T::genesis_epoch();
|
||||
validator.activation_epoch = T::genesis_epoch();
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
@@ -8,7 +8,7 @@ pub mod per_epoch_processing;
|
||||
pub mod per_slot_processing;
|
||||
pub mod test_utils;
|
||||
|
||||
pub use genesis::{initialize_beacon_state_from_eth1, is_valid_genesis_state};
|
||||
pub use genesis::{initialize_beacon_state_from_eth1, is_valid_genesis_state, process_activations};
|
||||
pub use per_block_processing::{
|
||||
errors::BlockProcessingError, per_block_processing, BlockSignatureStrategy, VerifySignatures,
|
||||
};
|
||||
|
||||
@@ -444,7 +444,7 @@ pub fn process_deposit<T: EthSpec>(
|
||||
} else {
|
||||
// The signature should be checked for new validators. Return early for a bad
|
||||
// signature.
|
||||
if verify_deposit_signature(state, deposit, spec).is_err() {
|
||||
if verify_deposit_signature(&deposit.data, spec).is_err() {
|
||||
return Ok(());
|
||||
}
|
||||
|
||||
|
||||
@@ -7,7 +7,7 @@ use std::convert::TryInto;
|
||||
use tree_hash::{SignedRoot, TreeHash};
|
||||
use types::{
|
||||
AggregateSignature, AttestationDataAndCustodyBit, AttesterSlashing, BeaconBlock,
|
||||
BeaconBlockHeader, BeaconState, BeaconStateError, ChainSpec, Deposit, Domain, EthSpec, Fork,
|
||||
BeaconBlockHeader, BeaconState, BeaconStateError, ChainSpec, DepositData, Domain, EthSpec,
|
||||
Hash256, IndexedAttestation, ProposerSlashing, PublicKey, RelativeEpoch, Signature, Transfer,
|
||||
VoluntaryExit,
|
||||
};
|
||||
@@ -194,18 +194,17 @@ pub fn attester_slashing_signature_sets<'a, T: EthSpec>(
|
||||
///
|
||||
/// This method is separate to `deposit_signature_set` to satisfy lifetime requirements.
|
||||
pub fn deposit_pubkey_signature_message(
|
||||
deposit: &Deposit,
|
||||
deposit_data: &DepositData,
|
||||
) -> Option<(PublicKey, Signature, Vec<u8>)> {
|
||||
let pubkey = (&deposit.data.pubkey).try_into().ok()?;
|
||||
let signature = (&deposit.data.signature).try_into().ok()?;
|
||||
let message = deposit.data.signed_root();
|
||||
let pubkey = (&deposit_data.pubkey).try_into().ok()?;
|
||||
let signature = (&deposit_data.signature).try_into().ok()?;
|
||||
let message = deposit_data.signed_root();
|
||||
Some((pubkey, signature, message))
|
||||
}
|
||||
|
||||
/// Returns the signature set for some set of deposit signatures, made with
|
||||
/// `deposit_pubkey_signature_message`.
|
||||
pub fn deposit_signature_set<'a, T: EthSpec>(
|
||||
state: &'a BeaconState<T>,
|
||||
pub fn deposit_signature_set<'a>(
|
||||
pubkey_signature_message: &'a (PublicKey, Signature, Vec<u8>),
|
||||
spec: &'a ChainSpec,
|
||||
) -> SignatureSet<'a> {
|
||||
@@ -213,9 +212,12 @@ pub fn deposit_signature_set<'a, T: EthSpec>(
|
||||
|
||||
// Note: Deposits are valid across forks, thus the deposit domain is computed
|
||||
// with the fork zeroed.
|
||||
let domain = spec.get_domain(state.current_epoch(), Domain::Deposit, &Fork::default());
|
||||
|
||||
SignatureSet::single(signature, pubkey, message.clone(), domain)
|
||||
SignatureSet::single(
|
||||
signature,
|
||||
pubkey,
|
||||
message.clone(),
|
||||
spec.get_deposit_domain(),
|
||||
)
|
||||
}
|
||||
|
||||
/// Returns a signature set that is valid if the `VoluntaryExit` was signed by the indicated
|
||||
|
||||
@@ -15,16 +15,12 @@ fn error(reason: DepositInvalid) -> BlockOperationError<DepositInvalid> {
|
||||
/// Verify `Deposit.pubkey` signed `Deposit.signature`.
|
||||
///
|
||||
/// Spec v0.8.0
|
||||
pub fn verify_deposit_signature<T: EthSpec>(
|
||||
state: &BeaconState<T>,
|
||||
deposit: &Deposit,
|
||||
spec: &ChainSpec,
|
||||
) -> Result<()> {
|
||||
let deposit_signature_message = deposit_pubkey_signature_message(deposit)
|
||||
pub fn verify_deposit_signature(deposit_data: &DepositData, spec: &ChainSpec) -> Result<()> {
|
||||
let deposit_signature_message = deposit_pubkey_signature_message(&deposit_data)
|
||||
.ok_or_else(|| error(DepositInvalid::BadBlsBytes))?;
|
||||
|
||||
verify!(
|
||||
deposit_signature_set(state, &deposit_signature_message, spec).is_valid(),
|
||||
deposit_signature_set(&deposit_signature_message, spec).is_valid(),
|
||||
DepositInvalid::BadSignature
|
||||
);
|
||||
|
||||
|
||||
@@ -216,7 +216,7 @@ impl<T: EthSpec> BeaconState<T> {
|
||||
// Versioning
|
||||
genesis_time,
|
||||
slot: spec.genesis_slot,
|
||||
fork: Fork::genesis(T::genesis_epoch()),
|
||||
fork: spec.genesis_fork.clone(),
|
||||
|
||||
// History
|
||||
latest_block_header: BeaconBlock::<T>::empty(spec).temporary_block_header(),
|
||||
|
||||
@@ -91,8 +91,15 @@ pub struct ChainSpec {
|
||||
domain_voluntary_exit: u32,
|
||||
domain_transfer: u32,
|
||||
|
||||
/*
|
||||
* Eth1
|
||||
*/
|
||||
pub eth1_follow_distance: u64,
|
||||
|
||||
pub boot_nodes: Vec<String>,
|
||||
pub network_id: u8,
|
||||
|
||||
pub genesis_fork: Fork,
|
||||
}
|
||||
|
||||
impl ChainSpec {
|
||||
@@ -118,6 +125,22 @@ impl ChainSpec {
|
||||
u64::from_le_bytes(fork_and_domain)
|
||||
}
|
||||
|
||||
/// Get the domain for a deposit signature.
|
||||
///
|
||||
/// Deposits are valid across forks, thus the deposit domain is computed
|
||||
/// with the fork zeroed.
|
||||
///
|
||||
/// Spec v0.8.1
|
||||
pub fn get_deposit_domain(&self) -> u64 {
|
||||
let mut bytes: Vec<u8> = int_to_bytes4(self.domain_deposit);
|
||||
bytes.append(&mut vec![0; 4]);
|
||||
|
||||
let mut fork_and_domain = [0; 8];
|
||||
fork_and_domain.copy_from_slice(&bytes);
|
||||
|
||||
u64::from_le_bytes(fork_and_domain)
|
||||
}
|
||||
|
||||
/// Returns a `ChainSpec` compatible with the Ethereum Foundation specification.
|
||||
///
|
||||
/// Spec v0.8.1
|
||||
@@ -186,6 +209,20 @@ impl ChainSpec {
|
||||
domain_voluntary_exit: 4,
|
||||
domain_transfer: 5,
|
||||
|
||||
/*
|
||||
* Eth1
|
||||
*/
|
||||
eth1_follow_distance: 1_024,
|
||||
|
||||
/*
|
||||
* Fork
|
||||
*/
|
||||
genesis_fork: Fork {
|
||||
previous_version: [0; 4],
|
||||
current_version: [0; 4],
|
||||
epoch: Epoch::new(0),
|
||||
},
|
||||
|
||||
/*
|
||||
* Network specific
|
||||
*/
|
||||
@@ -210,6 +247,7 @@ impl ChainSpec {
|
||||
max_epochs_per_crosslink: 4,
|
||||
network_id: 2, // lighthouse testnet network id
|
||||
boot_nodes,
|
||||
eth1_follow_distance: 16,
|
||||
..ChainSpec::mainnet()
|
||||
}
|
||||
}
|
||||
@@ -248,7 +286,7 @@ mod tests {
|
||||
}
|
||||
|
||||
fn test_domain(domain_type: Domain, raw_domain: u32, spec: &ChainSpec) {
|
||||
let fork = Fork::genesis(Epoch::new(0));
|
||||
let fork = &spec.genesis_fork;
|
||||
let epoch = Epoch::new(0);
|
||||
|
||||
let domain = spec.get_domain(epoch, domain_type, &fork);
|
||||
|
||||
@@ -7,6 +7,8 @@ use ssz_derive::{Decode, Encode};
|
||||
use test_random_derive::TestRandom;
|
||||
use tree_hash_derive::TreeHash;
|
||||
|
||||
pub const DEPOSIT_TREE_DEPTH: usize = 32;
|
||||
|
||||
/// A deposit to potentially become a beacon chain validator.
|
||||
///
|
||||
/// Spec v0.8.0
|
||||
|
||||
@@ -36,15 +36,9 @@ impl DepositData {
|
||||
/// Generate the signature for a given DepositData details.
|
||||
///
|
||||
/// Spec v0.8.1
|
||||
pub fn create_signature(
|
||||
&self,
|
||||
secret_key: &SecretKey,
|
||||
epoch: Epoch,
|
||||
fork: &Fork,
|
||||
spec: &ChainSpec,
|
||||
) -> SignatureBytes {
|
||||
pub fn create_signature(&self, secret_key: &SecretKey, spec: &ChainSpec) -> SignatureBytes {
|
||||
let msg = self.signed_root();
|
||||
let domain = spec.get_domain(epoch, Domain::Deposit, fork);
|
||||
let domain = spec.get_deposit_domain();
|
||||
|
||||
SignatureBytes::from(Signature::new(msg.as_slice(), domain, secret_key))
|
||||
}
|
||||
|
||||
@@ -10,7 +10,18 @@ use tree_hash_derive::TreeHash;
|
||||
///
|
||||
/// Spec v0.8.1
|
||||
#[derive(
|
||||
Debug, PartialEq, Clone, Default, Serialize, Deserialize, Encode, Decode, TreeHash, TestRandom,
|
||||
Debug,
|
||||
PartialEq,
|
||||
Clone,
|
||||
Default,
|
||||
Eq,
|
||||
Hash,
|
||||
Serialize,
|
||||
Deserialize,
|
||||
Encode,
|
||||
Decode,
|
||||
TreeHash,
|
||||
TestRandom,
|
||||
)]
|
||||
pub struct Eth1Data {
|
||||
pub deposit_root: Hash256,
|
||||
|
||||
@@ -28,17 +28,6 @@ pub struct Fork {
|
||||
}
|
||||
|
||||
impl Fork {
|
||||
/// Initialize the `Fork` from the genesis parameters in the `spec`.
|
||||
///
|
||||
/// Spec v0.8.1
|
||||
pub fn genesis(genesis_epoch: Epoch) -> Self {
|
||||
Self {
|
||||
previous_version: [0; 4],
|
||||
current_version: [0; 4],
|
||||
epoch: genesis_epoch,
|
||||
}
|
||||
}
|
||||
|
||||
/// Return the fork version of the given ``epoch``.
|
||||
///
|
||||
/// Spec v0.8.1
|
||||
@@ -56,24 +45,6 @@ mod tests {
|
||||
|
||||
ssz_tests!(Fork);
|
||||
|
||||
fn test_genesis(epoch: Epoch) {
|
||||
let fork = Fork::genesis(epoch);
|
||||
|
||||
assert_eq!(fork.epoch, epoch, "epoch incorrect");
|
||||
assert_eq!(
|
||||
fork.previous_version, fork.current_version,
|
||||
"previous and current are not identical"
|
||||
);
|
||||
}
|
||||
|
||||
#[test]
|
||||
fn genesis() {
|
||||
test_genesis(Epoch::new(0));
|
||||
test_genesis(Epoch::new(11));
|
||||
test_genesis(Epoch::new(2_u64.pow(63)));
|
||||
test_genesis(Epoch::max_value());
|
||||
}
|
||||
|
||||
#[test]
|
||||
fn get_fork_version() {
|
||||
let previous_version = [1; 4];
|
||||
|
||||
@@ -58,7 +58,7 @@ pub use crate::checkpoint::Checkpoint;
|
||||
pub use crate::compact_committee::CompactCommittee;
|
||||
pub use crate::crosslink::Crosslink;
|
||||
pub use crate::crosslink_committee::{CrosslinkCommittee, OwnedCrosslinkCommittee};
|
||||
pub use crate::deposit::Deposit;
|
||||
pub use crate::deposit::{Deposit, DEPOSIT_TREE_DEPTH};
|
||||
pub use crate::deposit_data::DepositData;
|
||||
pub use crate::eth1_data::Eth1Data;
|
||||
pub use crate::fork::Fork;
|
||||
|
||||
@@ -294,13 +294,7 @@ impl<T: EthSpec> TestingBeaconBlockBuilder<T> {
|
||||
let keypair = Keypair::random();
|
||||
|
||||
let mut builder = TestingDepositBuilder::new(keypair.pk.clone(), amount);
|
||||
builder.sign(
|
||||
&test_task,
|
||||
&keypair,
|
||||
state.slot.epoch(T::slots_per_epoch()),
|
||||
&state.fork,
|
||||
spec,
|
||||
);
|
||||
builder.sign(&test_task, &keypair, spec);
|
||||
datas.push(builder.build().data);
|
||||
}
|
||||
|
||||
|
||||
@@ -30,14 +30,7 @@ impl TestingDepositBuilder {
|
||||
/// - `pubkey` to the signing pubkey.
|
||||
/// - `withdrawal_credentials` to the signing pubkey.
|
||||
/// - `proof_of_possession`
|
||||
pub fn sign(
|
||||
&mut self,
|
||||
test_task: &DepositTestTask,
|
||||
keypair: &Keypair,
|
||||
epoch: Epoch,
|
||||
fork: &Fork,
|
||||
spec: &ChainSpec,
|
||||
) {
|
||||
pub fn sign(&mut self, test_task: &DepositTestTask, keypair: &Keypair, spec: &ChainSpec) {
|
||||
let new_key = Keypair::random();
|
||||
let mut pubkeybytes = PublicKeyBytes::from(keypair.pk.clone());
|
||||
let mut secret_key = keypair.sk.clone();
|
||||
@@ -61,10 +54,7 @@ impl TestingDepositBuilder {
|
||||
// Building the data and signing it
|
||||
self.deposit.data.pubkey = pubkeybytes;
|
||||
self.deposit.data.withdrawal_credentials = withdrawal_credentials;
|
||||
self.deposit.data.signature =
|
||||
self.deposit
|
||||
.data
|
||||
.create_signature(&secret_key, epoch, fork, spec);
|
||||
self.deposit.data.signature = self.deposit.data.create_signature(&secret_key, spec);
|
||||
}
|
||||
|
||||
/// Builds the deposit, consuming the builder.
|
||||
|
||||
@@ -5,7 +5,6 @@ authors = ["Paul Hauner <paul@paulhauner.com>"]
|
||||
edition = "2018"
|
||||
|
||||
[dependencies]
|
||||
clap = "2.33.0"
|
||||
serde = "1.0.102"
|
||||
serde_derive = "1.0.102"
|
||||
toml = "0.5.4"
|
||||
|
||||
@@ -1,9 +1,7 @@
|
||||
use clap::ArgMatches;
|
||||
use serde_derive::{Deserialize, Serialize};
|
||||
use std::fs::File;
|
||||
use std::io::prelude::*;
|
||||
use std::path::PathBuf;
|
||||
use std::time::SystemTime;
|
||||
use types::ChainSpec;
|
||||
|
||||
/// The core configuration of a Lighthouse beacon node.
|
||||
@@ -46,33 +44,6 @@ impl Eth2Config {
|
||||
}
|
||||
}
|
||||
|
||||
impl Eth2Config {
|
||||
/// Apply the following arguments to `self`, replacing values if they are specified in `args`.
|
||||
///
|
||||
/// Returns an error if arguments are obviously invalid. May succeed even if some values are
|
||||
/// invalid.
|
||||
pub fn apply_cli_args(&mut self, args: &ArgMatches) -> Result<(), &'static str> {
|
||||
if args.is_present("recent-genesis") {
|
||||
self.spec.min_genesis_time = recent_genesis_time()
|
||||
}
|
||||
|
||||
Ok(())
|
||||
}
|
||||
}
|
||||
|
||||
/// Returns the system time, mod 30 minutes.
|
||||
///
|
||||
/// Used for easily creating testnets.
|
||||
fn recent_genesis_time() -> u64 {
|
||||
let now = SystemTime::now()
|
||||
.duration_since(SystemTime::UNIX_EPOCH)
|
||||
.unwrap()
|
||||
.as_secs();
|
||||
let secs_after_last_period = now.checked_rem(30 * 60).unwrap_or(0);
|
||||
// genesis is now the last 30 minute block.
|
||||
now - secs_after_last_period
|
||||
}
|
||||
|
||||
/// Write a configuration to file.
|
||||
pub fn write_to_file<T>(path: PathBuf, config: &T) -> Result<(), String>
|
||||
where
|
||||
@@ -111,3 +82,15 @@ where
|
||||
Ok(None)
|
||||
}
|
||||
}
|
||||
|
||||
#[cfg(test)]
|
||||
mod tests {
|
||||
use super::*;
|
||||
use toml;
|
||||
|
||||
#[test]
|
||||
fn serde_serialize() {
|
||||
let _ =
|
||||
toml::to_string(&Eth2Config::default()).expect("Should serde encode default config");
|
||||
}
|
||||
}
|
||||
|
||||
@@ -0,0 +1,14 @@
|
||||
[package]
|
||||
name = "remote_beacon_node"
|
||||
version = "0.1.0"
|
||||
authors = ["Paul Hauner <paul@paulhauner.com>"]
|
||||
edition = "2018"
|
||||
|
||||
# See more keys and their definitions at https://doc.rust-lang.org/cargo/reference/manifest.html
|
||||
|
||||
[dependencies]
|
||||
reqwest = "0.9"
|
||||
url = "1.2"
|
||||
serde = "1.0"
|
||||
futures = "0.1.25"
|
||||
types = { path = "../../../eth2/types" }
|
||||
@@ -0,0 +1,141 @@
|
||||
//! 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 futures::{Future, IntoFuture};
|
||||
use reqwest::r#async::{Client, RequestBuilder};
|
||||
use serde::Deserialize;
|
||||
use std::marker::PhantomData;
|
||||
use std::net::SocketAddr;
|
||||
use types::{BeaconBlock, BeaconState, EthSpec};
|
||||
use types::{Hash256, Slot};
|
||||
use url::Url;
|
||||
|
||||
/// Connects to a remote Lighthouse (or compatible) node via HTTP.
|
||||
pub struct RemoteBeaconNode<E: EthSpec> {
|
||||
pub http: HttpClient<E>,
|
||||
}
|
||||
|
||||
impl<E: EthSpec> RemoteBeaconNode<E> {
|
||||
pub fn new(http_endpoint: SocketAddr) -> Result<Self, String> {
|
||||
Ok(Self {
|
||||
http: HttpClient::new(format!("http://{}", http_endpoint.to_string()))
|
||||
.map_err(|e| format!("Unable to create http client: {:?}", e))?,
|
||||
})
|
||||
}
|
||||
}
|
||||
|
||||
#[derive(Debug)]
|
||||
pub enum Error {
|
||||
UrlParseError(url::ParseError),
|
||||
ReqwestError(reqwest::Error),
|
||||
}
|
||||
|
||||
#[derive(Clone)]
|
||||
pub struct HttpClient<E> {
|
||||
client: Client,
|
||||
url: Url,
|
||||
_phantom: PhantomData<E>,
|
||||
}
|
||||
|
||||
impl<E: EthSpec> HttpClient<E> {
|
||||
/// Creates a new instance (without connecting to the node).
|
||||
pub fn new(server_url: String) -> Result<Self, Error> {
|
||||
Ok(Self {
|
||||
client: Client::new(),
|
||||
url: Url::parse(&server_url)?,
|
||||
_phantom: PhantomData,
|
||||
})
|
||||
}
|
||||
|
||||
pub fn beacon(&self) -> Beacon<E> {
|
||||
Beacon(self.clone())
|
||||
}
|
||||
|
||||
fn url(&self, path: &str) -> Result<Url, Error> {
|
||||
self.url.join(path).map_err(|e| e.into())
|
||||
}
|
||||
|
||||
pub fn get(&self, path: &str) -> Result<RequestBuilder, Error> {
|
||||
self.url(path)
|
||||
.map(|url| Client::new().get(&url.to_string()))
|
||||
}
|
||||
}
|
||||
|
||||
/// Provides the functions on the `/beacon` endpoint of the node.
|
||||
#[derive(Clone)]
|
||||
pub struct Beacon<E>(HttpClient<E>);
|
||||
|
||||
impl<E: EthSpec> Beacon<E> {
|
||||
fn url(&self, path: &str) -> Result<Url, Error> {
|
||||
self.0
|
||||
.url("beacon/")
|
||||
.and_then(move |url| url.join(path).map_err(Error::from))
|
||||
.map_err(Into::into)
|
||||
}
|
||||
|
||||
/// Returns the block and block root at the given slot.
|
||||
pub fn block_at_slot(
|
||||
&self,
|
||||
slot: Slot,
|
||||
) -> impl Future<Item = (BeaconBlock<E>, Hash256), Error = Error> {
|
||||
let client = self.0.clone();
|
||||
self.url("block")
|
||||
.into_future()
|
||||
.and_then(move |mut url| {
|
||||
url.query_pairs_mut()
|
||||
.append_pair("slot", &format!("{}", slot.as_u64()));
|
||||
client.get(&url.to_string())
|
||||
})
|
||||
.and_then(|builder| builder.send().map_err(Error::from))
|
||||
.and_then(|response| response.error_for_status().map_err(Error::from))
|
||||
.and_then(|mut success| success.json::<BlockResponse<E>>().map_err(Error::from))
|
||||
.map(|response| (response.beacon_block, response.root))
|
||||
}
|
||||
|
||||
/// Returns the state and state root at the given slot.
|
||||
pub fn state_at_slot(
|
||||
&self,
|
||||
slot: Slot,
|
||||
) -> impl Future<Item = (BeaconState<E>, Hash256), Error = Error> {
|
||||
let client = self.0.clone();
|
||||
self.url("state")
|
||||
.into_future()
|
||||
.and_then(move |mut url| {
|
||||
url.query_pairs_mut()
|
||||
.append_pair("slot", &format!("{}", slot.as_u64()));
|
||||
client.get(&url.to_string())
|
||||
})
|
||||
.and_then(|builder| builder.send().map_err(Error::from))
|
||||
.and_then(|response| response.error_for_status().map_err(Error::from))
|
||||
.and_then(|mut success| success.json::<StateResponse<E>>().map_err(Error::from))
|
||||
.map(|response| (response.beacon_state, response.root))
|
||||
}
|
||||
}
|
||||
|
||||
#[derive(Deserialize)]
|
||||
#[serde(bound = "T: EthSpec")]
|
||||
pub struct BlockResponse<T: EthSpec> {
|
||||
pub beacon_block: BeaconBlock<T>,
|
||||
pub root: Hash256,
|
||||
}
|
||||
|
||||
#[derive(Deserialize)]
|
||||
#[serde(bound = "T: EthSpec")]
|
||||
pub struct StateResponse<T: EthSpec> {
|
||||
pub beacon_state: BeaconState<T>,
|
||||
pub root: Hash256,
|
||||
}
|
||||
|
||||
impl From<reqwest::Error> for Error {
|
||||
fn from(e: reqwest::Error) -> Error {
|
||||
Error::ReqwestError(e)
|
||||
}
|
||||
}
|
||||
|
||||
impl From<url::ParseError> for Error {
|
||||
fn from(e: url::ParseError) -> Error {
|
||||
Error::UrlParseError(e)
|
||||
}
|
||||
}
|
||||
Reference in New Issue
Block a user