Skip to content

Commit

Permalink
Merge pull request #1049 from matter-labs/popzxc-684-dockerized-exit
Browse files Browse the repository at this point in the history
Tool for Exodus exit tx
  • Loading branch information
popzxc authored Oct 22, 2020
2 parents 9fcb587 + 4251195 commit cd2ce48
Show file tree
Hide file tree
Showing 25 changed files with 494 additions and 51 deletions.
4 changes: 4 additions & 0 deletions .dockerignore
Original file line number Diff line number Diff line change
@@ -1,6 +1,10 @@
*
!docker/prover/prover-entry.sh
!docker/exit-tool/exit-tool-entry.sh
!docker/exit-tool/configs
!docker/keybase-secrets/entrypoint.sh
!etc/env/dev.env.example
!etc/tokens
!keys/packed
!docker/nginx/nginx.conf
!bin/
Expand Down
2 changes: 2 additions & 0 deletions Cargo.lock

Some generated files are not rendered by default. Learn more about how customized files appear on GitHub.

7 changes: 7 additions & 0 deletions Makefile
Original file line number Diff line number Diff line change
Expand Up @@ -10,6 +10,7 @@ export DEV_TICKER_DOCKER_IMAGE ?= matterlabs/dev-ticker:latest
export KEYBASE_DOCKER_IMAGE ?= matterlabs/keybase-secret:latest
export CI_DOCKER_IMAGE ?= matterlabs/ci
export FEE_SELLER_IMAGE ?=matterlabs/fee-seller:latest
export EXIT_TOOL_IMAGE ?=matterlabs/exit-tool:latest

# Getting started

Expand Down Expand Up @@ -291,3 +292,9 @@ push-image-dev-ticker: image-dev-ticker

api-test:
@cd core/tests/ts-tests && yarn && yarn api-test

image-exit-tool:
@docker build -t "${EXIT_TOOL_IMAGE}" -f ./docker/exit-tool/Dockerfile .

push-image-exit-tool: image-exit-tool
@docker push "${EXIT_TOOL_IMAGE}"
9 changes: 6 additions & 3 deletions bin/.setup_env
Original file line number Diff line number Diff line change
Expand Up @@ -2,15 +2,18 @@

pushd `dirname $0`/.. > /dev/null

cd $ZKSYNC_HOME

# Setup the git hooks folder.
if ! git config --local core.hooksPath > /dev/null; then
git config --local core.hooksPath $ZKSYNC_HOME/.githooks/ > /dev/null
if [ -d .git ]; then
if ! git config --local core.hooksPath > /dev/null; then
git config --local core.hooksPath $ZKSYNC_HOME/.githooks/ > /dev/null
fi
fi

# Setup env itself
if [ -z "$ZKSYNC_ENV" ]
then

if [ -f etc/env/current ]; then
export ZKSYNC_ENV=`cat etc/env/current`
else
Expand Down
14 changes: 14 additions & 0 deletions bin/db-check-sqlx
Original file line number Diff line number Diff line change
@@ -0,0 +1,14 @@
#!/bin/bash

set -e

cd core/lib/storage

# Check generated sqlx data
if ! cargo sqlx prepare --check
then
# Prepare sqlx bindings
# We're going to do it even on CI, since it seems that this file can be invalidated after several subsequent compilations.
echo "Going to rerun 'sqlx prepare'"
cargo sqlx prepare
fi
16 changes: 8 additions & 8 deletions bin/db-setup
Original file line number Diff line number Diff line change
Expand Up @@ -14,11 +14,11 @@ diesel migration run
# We don't need this file for sqlx
rm src/schema.rs.generated

# Check generated sqlx data
if ! cargo sqlx prepare --check
then
# Prepare sqlx bindings
# We're going to do it even on CI, since it seems that this file can be invalidated after several subsequent compilations.
echo "Going to rerun 'sqlx prepare'"
cargo sqlx prepare
fi
# # Check generated sqlx data
# if ! cargo sqlx prepare --check
# then
# # Prepare sqlx bindings
# # We're going to do it even on CI, since it seems that this file can be invalidated after several subsequent compilations.
# echo "Going to rerun 'sqlx prepare'"
# cargo sqlx prepare
# fi
1 change: 1 addition & 0 deletions bin/init
Original file line number Diff line number Diff line change
Expand Up @@ -10,6 +10,7 @@ zksync yarn || true # It can fail.
zksync plonk-setup check || zksync plonk-setup download
zksync verify-keys unpack
zksync db-setup
zksync db-check-sqlx
zksync build-dev-contracts
zksync deploy-erc20 dev
zksync build-contracts
Expand Down
1 change: 1 addition & 0 deletions core/bin/data_restore/Cargo.toml
Original file line number Diff line number Diff line change
Expand Up @@ -17,6 +17,7 @@ ethabi = "12.0.0"
web3 = "0.13.0"
hex = "0.4"
log = "0.4"
serde = { version = "1.0", features = ["derive"] }
serde_json = "1.0.0"
env_logger = "0.6"
anyhow = "1.0"
Expand Down
5 changes: 5 additions & 0 deletions core/bin/data_restore/src/data_restore_driver.rs
Original file line number Diff line number Diff line change
Expand Up @@ -237,6 +237,11 @@ impl<T: Transport> DataRestoreDriver<T> {
total_verified_blocks,
self.tree_state.root_hash()
);

if self.finite_mode && (total_verified_blocks == last_verified_block) {
// We've already completed finalizing the state, so exit immediately.
std::process::exit(0);
}
}

/// Activates states updates
Expand Down
27 changes: 12 additions & 15 deletions core/bin/data_restore/src/events_state.rs
Original file line number Diff line number Diff line change
Expand Up @@ -307,24 +307,21 @@ impl EventsState {

for log in logs {
let topic = log.topics[0];
assert!(log.topics.len() >= 2, "Cant get enouth topics from event");

// Remove reverted committed blocks first
if topic == reverted_topic {
assert_eq!(
log.topics.len(),
3,
"Cant get enouth topics from reverted event"
);
let committed_total = U256::from(log.topics[2].as_bytes()).as_u32();
let mut i = 0;
while i != self.committed_events.len() {
if self.committed_events[i].block_num > committed_total {
self.committed_events.remove(i);
} else {
i += 1;
}
}
const U256_SIZE: usize = 32;
// Fields in `BlocksRevert` are not `indexed`, thus they're located in `data`.
assert_eq!(log.data.0.len(), U256_SIZE * 2);
let total_verified = U256::from_big_endian(&log.data.0[..U256_SIZE]).as_u32();
let total_committed = U256::from_big_endian(&log.data.0[U256_SIZE..]).as_u32();

self.committed_events
.retain(|bl| bl.block_num <= total_committed);
self.verified_events
.retain(|bl| bl.block_num <= total_verified);

continue;
}

// Go into new blocks
Expand Down
68 changes: 55 additions & 13 deletions core/bin/data_restore/src/main.rs
Original file line number Diff line number Diff line change
Expand Up @@ -8,17 +8,19 @@ pub mod storage_interactor;
pub mod tree_state;

use crate::data_restore_driver::DataRestoreDriver;
use serde::Deserialize;
use structopt::StructOpt;
use web3::transports::Http;
use zksync_config::ConfigurationOptions;
use zksync_crypto::convert::FeConvert;
use zksync_storage::ConnectionPool;
use zksync_types::{
tokens::{get_genesis_token_list, Token},
TokenId,
Address, TokenId, H256,
};

const ETH_BLOCKS_STEP: u64 = 1;
// How many blocks we will process at once.
const ETH_BLOCKS_STEP: u64 = 10_000;
const END_ETH_BLOCKS_OFFSET: u64 = 40;

async fn add_tokens_to_db(pool: &ConnectionPool, eth_network: &str) {
Expand Down Expand Up @@ -61,7 +63,7 @@ struct Opt {
genesis: bool,

/// Continues data restoring
#[structopt(long, name = "continue")]
#[structopt(long = "continue", name = "continue")]
continue_mode: bool,

/// Restore data until the last verified block and exit
Expand All @@ -71,6 +73,43 @@ struct Opt {
/// Expected tree root hash after restoring. This argument is ignored if mode is not `finite`
#[structopt(long)]
final_hash: Option<String>,

/// Sets the web3 API to be used to interact with the Ethereum blockchain
#[structopt(long = "web3", name = "web3")]
web3_url: Option<String>,

/// Provides a path to the configuration file for data restore
#[structopt(long = "config", name = "config")]
config_path: Option<String>,
}

#[derive(Debug, Deserialize)]
pub struct ContractsConfig {
eth_network: String,
governance_addr: Address,
genesis_tx_hash: H256,
contract_addr: Address,
available_block_chunk_sizes: Vec<usize>,
}

impl ContractsConfig {
pub fn from_file(path: &str) -> Self {
let content =
std::fs::read_to_string(path).expect("Unable to find the specified config file");
serde_json::from_str(&content).expect("Invalid configuration file provided")
}

pub fn from_env() -> Self {
let config_opts = ConfigurationOptions::from_env();

Self {
eth_network: config_opts.eth_network,
governance_addr: config_opts.governance_eth_addr,
genesis_tx_hash: config_opts.genesis_tx_hash,
contract_addr: config_opts.contract_eth_addr,
available_block_chunk_sizes: config_opts.available_block_chunk_sizes,
}
}
}

#[tokio::main]
Expand All @@ -82,11 +121,14 @@ async fn main() {

let opt = Opt::from_args();

let transport = Http::new(&config_opts.web3_url).expect("failed to start web3 transport");
let governance_addr = config_opts.governance_eth_addr;
let genesis_tx_hash = config_opts.genesis_tx_hash;
let contract_addr = config_opts.contract_eth_addr;
let available_block_chunk_sizes = config_opts.available_block_chunk_sizes;
let web3_url = opt.web3_url.unwrap_or(config_opts.web3_url);

let transport = Http::new(&web3_url).expect("failed to start web3 transport");

let config = opt
.config_path
.map(|path| ContractsConfig::from_file(&path))
.unwrap_or_else(ContractsConfig::from_env);

let finite_mode = opt.finite;
let final_hash = if finite_mode {
Expand All @@ -99,11 +141,11 @@ async fn main() {
let mut driver = DataRestoreDriver::new(
connection_pool,
transport,
governance_addr,
contract_addr,
config.governance_addr,
config.contract_addr,
ETH_BLOCKS_STEP,
END_ETH_BLOCKS_OFFSET,
available_block_chunk_sizes,
config.available_block_chunk_sizes,
finite_mode,
final_hash,
);
Expand All @@ -112,9 +154,9 @@ async fn main() {
if opt.genesis {
// We have to load pre-defined tokens into the database before restoring state,
// since these tokens do not have a corresponding Ethereum events.
add_tokens_to_db(&driver.connection_pool, &config_opts.eth_network).await;
add_tokens_to_db(&driver.connection_pool, &config.eth_network).await;

driver.set_genesis_state(genesis_tx_hash).await;
driver.set_genesis_state(config.genesis_tx_hash).await;
}

if opt.continue_mode {
Expand Down
1 change: 1 addition & 0 deletions core/bin/server/Cargo.toml
Original file line number Diff line number Diff line change
Expand Up @@ -32,6 +32,7 @@ tokio = { version = "0.2", features = ["full"] }
zksync_crypto = { path = "../../lib/crypto", version = "1.0" }
zksync_types = { path = "../../lib/types", version = "1.0" }
zksync_prover = { path = "../prover", version = "1.0" }
zksync_utils = { path = "../../lib/utils", version = "1.0" }

num = { version = "0.2", features = ["serde"] }
serde = "1.0.90"
Expand Down
29 changes: 19 additions & 10 deletions core/bin/server/examples/generate_exit_proof.rs
Original file line number Diff line number Diff line change
@@ -1,20 +1,20 @@
//! Generate exit proof for exodus mode given account and token
//! correct verified state should be present in the db (could be restored using `data-restore` module)
use num::BigUint;
use serde::Serialize;
use std::time::Instant;
use structopt::StructOpt;
use zksync_crypto::proof::EncodedProofPlonk;
use zksync_storage::ConnectionPool;
use zksync_types::{AccountId, Address, TokenId, TokenLike};
use zksync_utils::BigUintSerdeWrapper;

#[derive(Serialize, Debug)]
struct ExitProofData {
token_id: TokenId,
account_id: AccountId,
account_address: Address,
amount: BigUint,
amount: BigUintSerdeWrapper,
proof: EncodedProofPlonk,
}

Expand All @@ -41,10 +41,7 @@ async fn main() {
let opt = Opt::from_args();

let account_id = opt.account_id.parse::<AccountId>().unwrap();
let token = {
let token = &opt.token;
serde_json::from_str::<TokenLike>(token).expect("invalid token argument")
};
let token = TokenLike::parse(&opt.token);

let timer = Instant::now();
log::info!("Restoring state from db");
Expand All @@ -59,7 +56,10 @@ async fn main() {
.get_token(token)
.await
.expect("Db access fail")
.expect("Token not found")
.expect(
"Token not found. If you're addressing an ERC-20 token by it's symbol, \
it may not be available after data restore. Try using token address in that case",
)
.id;
let address = storage
.chain()
Expand All @@ -77,7 +77,7 @@ async fn main() {
.expect("Failed to load verified state")
.1;

log::info!("Resotred state from db: {} s", timer.elapsed().as_secs());
log::info!("Restored state from db: {} s", timer.elapsed().as_secs());

let (proof, amount) =
zksync_prover::exit_proof::create_exit_proof(accounts, account_id, address, token_id)
Expand All @@ -87,12 +87,21 @@ async fn main() {
token_id,
account_id,
account_address: address,
amount,
amount: amount.into(),
proof,
};

println!("\n\n");
println!("==========================");
println!("Generating proof completed");
println!("Below you can see the input data for the exit transaction on zkSync contract");
println!("Look up the manuals of your desired smart wallet in order to know how to sign and send this transaction to the Ethereum");
println!("==========================");

println!("Exit transaction inputs:");

println!(
"{}",
serde_json::to_string(&proof_data).expect("proof data serialize")
serde_json::to_string_pretty(&proof_data).expect("proof data serialize")
);
}
1 change: 1 addition & 0 deletions core/lib/storage/.env.backup
Original file line number Diff line number Diff line change
@@ -0,0 +1 @@
DATABASE_URL=postgres://postgres@localhost/plasma
Loading

0 comments on commit cd2ce48

Please sign in to comment.