mirror of
https://github.com/sigp/lighthouse.git
synced 2026-04-18 13:28:33 +00:00
Merge branch 'deposit-flow' into kill-grpc
This commit is contained in:
@@ -4,12 +4,6 @@ version = "0.1.0"
|
||||
authors = ["Paul Hauner <paul@paulhauner.com>"]
|
||||
edition = "2018"
|
||||
|
||||
build = "build.rs"
|
||||
|
||||
[build-dependencies]
|
||||
reqwest = "0.9.20"
|
||||
serde_json = "1.0"
|
||||
|
||||
[dependencies]
|
||||
web3 = "0.8.0"
|
||||
tokio = "0.1.17"
|
||||
@@ -17,3 +11,4 @@ futures = "0.1.25"
|
||||
types = { path = "../../eth2/types"}
|
||||
eth2_ssz = { path = "../../eth2/utils/ssz"}
|
||||
serde_json = "1.0"
|
||||
deposit_contract = { path = "../../eth2/utils/deposit_contract"}
|
||||
|
||||
@@ -1,95 +0,0 @@
|
||||
//! Downloads the ABI and bytecode for the deposit contract from the ethereum spec repository and
|
||||
//! stores them in a `contract/` directory in the crate root.
|
||||
//!
|
||||
//! These files are required for some `include_bytes` calls used in this crate.
|
||||
|
||||
use reqwest::Response;
|
||||
use serde_json::Value;
|
||||
use std::env;
|
||||
use std::fs::File;
|
||||
use std::io::Write;
|
||||
use std::path::PathBuf;
|
||||
|
||||
const GITHUB_RAW: &str = "https://raw.githubusercontent.com";
|
||||
const SPEC_REPO: &str = "ethereum/eth2.0-specs";
|
||||
const SPEC_TAG: &str = "v0.8.3";
|
||||
const ABI_FILE: &str = "validator_registration.json";
|
||||
const BYTECODE_FILE: &str = "validator_registration.bytecode";
|
||||
|
||||
fn main() {
|
||||
match init_deposit_contract_abi() {
|
||||
Ok(()) => (),
|
||||
Err(e) => panic!(e),
|
||||
}
|
||||
}
|
||||
|
||||
/// Attempts to download the deposit contract ABI from github if a local copy is not already
|
||||
/// present.
|
||||
pub fn init_deposit_contract_abi() -> Result<(), String> {
|
||||
let abi_file = abi_dir().join(format!("{}_{}", SPEC_TAG, ABI_FILE));
|
||||
let bytecode_file = abi_dir().join(format!("{}_{}", SPEC_TAG, BYTECODE_FILE));
|
||||
|
||||
if abi_file.exists() {
|
||||
// Nothing to do.
|
||||
} else {
|
||||
match download_abi() {
|
||||
Ok(mut response) => {
|
||||
let mut abi_file = File::create(abi_file)
|
||||
.map_err(|e| format!("Failed to create local abi file: {:?}", e))?;
|
||||
let mut bytecode_file = File::create(bytecode_file)
|
||||
.map_err(|e| format!("Failed to create local bytecode file: {:?}", e))?;
|
||||
|
||||
let contract: Value = response
|
||||
.json()
|
||||
.map_err(|e| format!("Respsonse is not a valid json {:?}", e))?;
|
||||
|
||||
let abi = contract
|
||||
.get("abi")
|
||||
.ok_or(format!("Response does not contain key: abi"))?
|
||||
.to_string();
|
||||
abi_file
|
||||
.write(abi.as_bytes())
|
||||
.map_err(|e| format!("Failed to write http response to abi file: {:?}", e))?;
|
||||
|
||||
let bytecode = contract
|
||||
.get("bytecode")
|
||||
.ok_or(format!("Response does not contain key: bytecode"))?
|
||||
.to_string();
|
||||
bytecode_file.write(bytecode.as_bytes()).map_err(|e| {
|
||||
format!("Failed to write http response to bytecode file: {:?}", e)
|
||||
})?;
|
||||
}
|
||||
Err(e) => {
|
||||
return Err(format!(
|
||||
"No abi file found. Failed to download from github: {:?}",
|
||||
e
|
||||
))
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
Ok(())
|
||||
}
|
||||
|
||||
/// Attempts to download the deposit contract file from the Ethereum github.
|
||||
fn download_abi() -> Result<Response, String> {
|
||||
reqwest::get(&format!(
|
||||
"{}/{}/{}/deposit_contract/contracts/{}",
|
||||
GITHUB_RAW, SPEC_REPO, SPEC_TAG, ABI_FILE
|
||||
))
|
||||
.map_err(|e| format!("Failed to download deposit ABI from github: {:?}", e))
|
||||
}
|
||||
|
||||
/// Returns the directory that will be used to store the deposit contract ABI.
|
||||
fn abi_dir() -> PathBuf {
|
||||
let base = env::var("CARGO_MANIFEST_DIR")
|
||||
.expect("should know manifest dir")
|
||||
.parse::<PathBuf>()
|
||||
.expect("should parse manifest dir as path")
|
||||
.join("contract");
|
||||
|
||||
std::fs::create_dir_all(base.clone())
|
||||
.expect("should be able to create abi directory in manifest");
|
||||
|
||||
base
|
||||
}
|
||||
@@ -7,6 +7,7 @@
|
||||
//! some initial issues.
|
||||
mod ganache;
|
||||
|
||||
use deposit_contract::{eth1_tx_data, ABI, BYTECODE, CONTRACT_DEPLOY_GAS, DEPOSIT_GAS};
|
||||
use futures::{stream, Future, IntoFuture, Stream};
|
||||
use ganache::GanacheInstance;
|
||||
use ssz::Encode;
|
||||
@@ -16,19 +17,12 @@ use types::DepositData;
|
||||
use types::{EthSpec, Hash256, Keypair, Signature};
|
||||
use web3::contract::{Contract, Options};
|
||||
use web3::transports::Http;
|
||||
use web3::types::{Address, U256};
|
||||
use web3::types::{Address, TransactionRequest, U256};
|
||||
use web3::{Transport, Web3};
|
||||
|
||||
pub const DEPLOYER_ACCOUNTS_INDEX: usize = 0;
|
||||
pub const DEPOSIT_ACCOUNTS_INDEX: usize = 0;
|
||||
|
||||
const CONTRACT_DEPLOY_GAS: usize = 4_000_000;
|
||||
const DEPOSIT_GAS: usize = 4_000_000;
|
||||
|
||||
// Deposit contract
|
||||
pub const ABI: &[u8] = include_bytes!("../contract/v0.8.3_validator_registration.json");
|
||||
pub const BYTECODE: &[u8] = include_bytes!("../contract/v0.8.3_validator_registration.bytecode");
|
||||
|
||||
/// Provides a dedicated ganache-cli instance with the deposit contract already deployed.
|
||||
pub struct GanacheEth1Instance {
|
||||
pub ganache: GanacheInstance,
|
||||
@@ -138,6 +132,7 @@ impl DepositContract {
|
||||
deposit_data: DepositData,
|
||||
) -> impl Future<Item = (), Error = String> {
|
||||
let contract = self.contract.clone();
|
||||
let web3_1 = self.web3.clone();
|
||||
|
||||
self.web3
|
||||
.eth()
|
||||
@@ -149,19 +144,27 @@ impl DepositContract {
|
||||
.cloned()
|
||||
.ok_or_else(|| "Insufficient accounts for deposit".to_string())
|
||||
})
|
||||
.and_then(move |from_address| {
|
||||
let params = (
|
||||
deposit_data.pubkey.as_ssz_bytes(),
|
||||
deposit_data.withdrawal_credentials.as_ssz_bytes(),
|
||||
deposit_data.signature.as_ssz_bytes(),
|
||||
);
|
||||
let options = Options {
|
||||
.and_then(move |from| {
|
||||
let tx_request = TransactionRequest {
|
||||
from,
|
||||
to: Some(contract.address()),
|
||||
gas: Some(U256::from(DEPOSIT_GAS)),
|
||||
gas_price: None,
|
||||
value: Some(from_gwei(deposit_data.amount)),
|
||||
..Options::default()
|
||||
// Note: the reason we use this `TransactionRequest` instead of just using the
|
||||
// function in `self.contract` is so that the `eth1_tx_data` function gets used
|
||||
// during testing.
|
||||
//
|
||||
// It's important that `eth1_tx_data` stays correct and does not suffer from
|
||||
// code-rot.
|
||||
data: eth1_tx_data(&deposit_data).map(Into::into).ok(),
|
||||
nonce: None,
|
||||
condition: None,
|
||||
};
|
||||
contract
|
||||
.call("deposit", params, from_address, options)
|
||||
|
||||
web3_1
|
||||
.eth()
|
||||
.send_transaction(tx_request)
|
||||
.map_err(|e| format!("Failed to call deposit fn: {:?}", e))
|
||||
})
|
||||
.map(|_| ())
|
||||
|
||||
Reference in New Issue
Block a user