mirror of
https://github.com/sigp/lighthouse.git
synced 2026-05-07 16:55:46 +00:00
Add deposit_contract crate
This commit is contained in:
@@ -7,6 +7,7 @@ members = [
|
|||||||
"eth2/utils/bls",
|
"eth2/utils/bls",
|
||||||
"eth2/utils/compare_fields",
|
"eth2/utils/compare_fields",
|
||||||
"eth2/utils/compare_fields_derive",
|
"eth2/utils/compare_fields_derive",
|
||||||
|
"eth2/utils/deposit_contract",
|
||||||
"eth2/utils/eth2_config",
|
"eth2/utils/eth2_config",
|
||||||
"eth2/utils/eth2_interop_keypairs",
|
"eth2/utils/eth2_interop_keypairs",
|
||||||
"eth2/utils/logging",
|
"eth2/utils/logging",
|
||||||
|
|||||||
1
eth2/utils/deposit_contract/.gitignore
vendored
Normal file
1
eth2/utils/deposit_contract/.gitignore
vendored
Normal file
@@ -0,0 +1 @@
|
|||||||
|
contract/
|
||||||
17
eth2/utils/deposit_contract/Cargo.toml
Normal file
17
eth2/utils/deposit_contract/Cargo.toml
Normal file
@@ -0,0 +1,17 @@
|
|||||||
|
[package]
|
||||||
|
name = "deposit_contract"
|
||||||
|
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]
|
||||||
|
types = { path = "../../types"}
|
||||||
|
eth2_ssz = { path = "../ssz"}
|
||||||
|
tree_hash = { path = "../tree_hash"}
|
||||||
|
ethabi = "9.0"
|
||||||
56
eth2/utils/deposit_contract/src/lib.rs
Normal file
56
eth2/utils/deposit_contract/src/lib.rs
Normal file
@@ -0,0 +1,56 @@
|
|||||||
|
use ethabi::{Contract, Token};
|
||||||
|
use ssz::Encode;
|
||||||
|
use types::{ChainSpec, DepositData, SecretKey};
|
||||||
|
|
||||||
|
pub use ethabi::Error;
|
||||||
|
|
||||||
|
pub const CONTRACT_DEPLOY_GAS: usize = 4_000_000;
|
||||||
|
pub const DEPOSIT_GAS: usize = 4_000_000;
|
||||||
|
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");
|
||||||
|
|
||||||
|
pub fn eth1_tx_data(deposit_data: &DepositData) -> Result<Vec<u8>, Error> {
|
||||||
|
let params = vec![
|
||||||
|
Token::Bytes(deposit_data.pubkey.as_ssz_bytes()),
|
||||||
|
Token::Bytes(deposit_data.withdrawal_credentials.as_ssz_bytes()),
|
||||||
|
Token::Bytes(deposit_data.signature.as_ssz_bytes()),
|
||||||
|
];
|
||||||
|
|
||||||
|
let abi = Contract::load(ABI)?;
|
||||||
|
let function = abi.function("deposit")?;
|
||||||
|
function.encode_input(¶ms)
|
||||||
|
}
|
||||||
|
|
||||||
|
#[cfg(test)]
|
||||||
|
mod tests {
|
||||||
|
use super::*;
|
||||||
|
use types::{
|
||||||
|
test_utils::generate_deterministic_keypair, EthSpec, Hash256, Keypair, MinimalEthSpec,
|
||||||
|
Signature,
|
||||||
|
};
|
||||||
|
|
||||||
|
type E = MinimalEthSpec;
|
||||||
|
|
||||||
|
fn get_deposit(keypair: Keypair, spec: &ChainSpec) -> DepositData {
|
||||||
|
let mut deposit_data = DepositData {
|
||||||
|
pubkey: keypair.pk.into(),
|
||||||
|
withdrawal_credentials: Hash256::from_slice(&[42; 32]),
|
||||||
|
amount: u64::max_value(),
|
||||||
|
signature: Signature::empty_signature().into(),
|
||||||
|
};
|
||||||
|
deposit_data.signature = deposit_data.create_signature(&keypair.sk, spec);
|
||||||
|
deposit_data
|
||||||
|
}
|
||||||
|
|
||||||
|
#[test]
|
||||||
|
fn basic() {
|
||||||
|
let spec = &E::default_spec();
|
||||||
|
|
||||||
|
let keypair = generate_deterministic_keypair(42);
|
||||||
|
let deposit = get_deposit(keypair.clone(), spec);
|
||||||
|
|
||||||
|
let data = eth1_tx_data(&deposit).expect("should produce tx data");
|
||||||
|
|
||||||
|
assert_eq!(data.len(), 388, "bytes should be correct length");
|
||||||
|
}
|
||||||
|
}
|
||||||
@@ -4,12 +4,6 @@ version = "0.1.0"
|
|||||||
authors = ["Paul Hauner <paul@paulhauner.com>"]
|
authors = ["Paul Hauner <paul@paulhauner.com>"]
|
||||||
edition = "2018"
|
edition = "2018"
|
||||||
|
|
||||||
build = "build.rs"
|
|
||||||
|
|
||||||
[build-dependencies]
|
|
||||||
reqwest = "0.9.20"
|
|
||||||
serde_json = "1.0"
|
|
||||||
|
|
||||||
[dependencies]
|
[dependencies]
|
||||||
web3 = "0.8.0"
|
web3 = "0.8.0"
|
||||||
tokio = "0.1.17"
|
tokio = "0.1.17"
|
||||||
@@ -17,3 +11,4 @@ futures = "0.1.25"
|
|||||||
types = { path = "../../eth2/types"}
|
types = { path = "../../eth2/types"}
|
||||||
eth2_ssz = { path = "../../eth2/utils/ssz"}
|
eth2_ssz = { path = "../../eth2/utils/ssz"}
|
||||||
serde_json = "1.0"
|
serde_json = "1.0"
|
||||||
|
deposit_contract = { path = "../../eth2/utils/deposit_contract"}
|
||||||
|
|||||||
@@ -7,6 +7,7 @@
|
|||||||
//! some initial issues.
|
//! some initial issues.
|
||||||
mod ganache;
|
mod ganache;
|
||||||
|
|
||||||
|
use deposit_contract::{eth1_tx_data, ABI, BYTECODE, CONTRACT_DEPLOY_GAS, DEPOSIT_GAS};
|
||||||
use futures::{stream, Future, IntoFuture, Stream};
|
use futures::{stream, Future, IntoFuture, Stream};
|
||||||
use ganache::GanacheInstance;
|
use ganache::GanacheInstance;
|
||||||
use ssz::Encode;
|
use ssz::Encode;
|
||||||
@@ -16,19 +17,12 @@ use types::DepositData;
|
|||||||
use types::{EthSpec, Hash256, Keypair, Signature};
|
use types::{EthSpec, Hash256, Keypair, Signature};
|
||||||
use web3::contract::{Contract, Options};
|
use web3::contract::{Contract, Options};
|
||||||
use web3::transports::Http;
|
use web3::transports::Http;
|
||||||
use web3::types::{Address, U256};
|
use web3::types::{Address, TransactionRequest, U256};
|
||||||
use web3::{Transport, Web3};
|
use web3::{Transport, Web3};
|
||||||
|
|
||||||
pub const DEPLOYER_ACCOUNTS_INDEX: usize = 0;
|
pub const DEPLOYER_ACCOUNTS_INDEX: usize = 0;
|
||||||
pub const DEPOSIT_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.
|
/// Provides a dedicated ganache-cli instance with the deposit contract already deployed.
|
||||||
pub struct GanacheEth1Instance {
|
pub struct GanacheEth1Instance {
|
||||||
pub ganache: GanacheInstance,
|
pub ganache: GanacheInstance,
|
||||||
@@ -138,6 +132,7 @@ impl DepositContract {
|
|||||||
deposit_data: DepositData,
|
deposit_data: DepositData,
|
||||||
) -> impl Future<Item = (), Error = String> {
|
) -> impl Future<Item = (), Error = String> {
|
||||||
let contract = self.contract.clone();
|
let contract = self.contract.clone();
|
||||||
|
let web3_1 = self.web3.clone();
|
||||||
|
|
||||||
self.web3
|
self.web3
|
||||||
.eth()
|
.eth()
|
||||||
@@ -149,19 +144,27 @@ impl DepositContract {
|
|||||||
.cloned()
|
.cloned()
|
||||||
.ok_or_else(|| "Insufficient accounts for deposit".to_string())
|
.ok_or_else(|| "Insufficient accounts for deposit".to_string())
|
||||||
})
|
})
|
||||||
.and_then(move |from_address| {
|
.and_then(move |from| {
|
||||||
let params = (
|
let tx_request = TransactionRequest {
|
||||||
deposit_data.pubkey.as_ssz_bytes(),
|
from,
|
||||||
deposit_data.withdrawal_credentials.as_ssz_bytes(),
|
to: Some(contract.address()),
|
||||||
deposit_data.signature.as_ssz_bytes(),
|
|
||||||
);
|
|
||||||
let options = Options {
|
|
||||||
gas: Some(U256::from(DEPOSIT_GAS)),
|
gas: Some(U256::from(DEPOSIT_GAS)),
|
||||||
|
gas_price: None,
|
||||||
value: Some(from_gwei(deposit_data.amount)),
|
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_err(|e| format!("Failed to call deposit fn: {:?}", e))
|
||||||
})
|
})
|
||||||
.map(|_| ())
|
.map(|_| ())
|
||||||
|
|||||||
Reference in New Issue
Block a user