forked from matter-labs/zksync
-
Notifications
You must be signed in to change notification settings - Fork 0
Commit
This commit does not belong to any branch on this repository, and may belong to a fork outside of the repository.
- Loading branch information
1 parent
bce4fb7
commit 79b2e27
Showing
9 changed files
with
1,343 additions
and
0 deletions.
There are no files selected for viewing
This file contains bidirectional Unicode text that may be interpreted or compiled differently than what appears below. To review, open the file in an editor that reveals hidden Unicode characters.
Learn more about bidirectional Unicode characters
This file contains bidirectional Unicode text that may be interpreted or compiled differently than what appears below. To review, open the file in an editor that reveals hidden Unicode characters.
Learn more about bidirectional Unicode characters
Original file line number | Diff line number | Diff line change |
---|---|---|
@@ -0,0 +1,18 @@ | ||
[package] | ||
name = "data_restore" | ||
version = "0.1.0" | ||
|
||
[dependencies] | ||
bigdecimal = { version = "0.1.0", features = ["serde"]} | ||
futures = "0.1.26" | ||
web3 = { git = "https://github.com/tomusdrw/rust-web3" } | ||
tiny-keccak = "1.4.2" | ||
ethabi = "7.0.0" | ||
hex = "0.3.2" | ||
sapling-crypto = { package = "sapling-crypto_ce", version = "0.0.5" } | ||
ff = { package = "ff_ce", version = "0.6.0", features = ["derive"] } | ||
pairing = { package = "pairing_ce", version = "0.17.0" } | ||
tokio = "0.1" | ||
bitvec = "0.11" | ||
|
||
plasma = { path = "../plasma" } |
Large diffs are not rendered by default.
Oops, something went wrong.
Large diffs are not rendered by default.
Oops, something went wrong.
This file contains bidirectional Unicode text that may be interpreted or compiled differently than what appears below. To review, open the file in an editor that reveals hidden Unicode characters.
Learn more about bidirectional Unicode characters
Original file line number | Diff line number | Diff line change |
---|---|---|
@@ -0,0 +1,34 @@ | ||
use std::cmp::Ordering; | ||
use web3::types::H256; | ||
|
||
#[derive(Debug, Copy, Clone, PartialEq, Eq)] | ||
pub enum BlockType { | ||
Committed, | ||
Verified, | ||
Unknown | ||
} | ||
|
||
#[derive(Debug, Copy, Clone, Eq)] | ||
pub struct LogBlockData { | ||
pub block_num: u32, | ||
pub transaction_hash: H256, | ||
pub block_type: BlockType | ||
} | ||
|
||
impl PartialOrd for LogBlockData { | ||
fn partial_cmp(&self, other: &LogBlockData) -> Option<Ordering> { | ||
Some(self.cmp(other)) | ||
} | ||
} | ||
|
||
impl Ord for LogBlockData { | ||
fn cmp(&self, other: &LogBlockData) -> Ordering { | ||
self.block_num.cmp(&other.block_num) | ||
} | ||
} | ||
|
||
impl PartialEq for LogBlockData { | ||
fn eq(&self, other: &LogBlockData) -> bool { | ||
self.block_num == other.block_num | ||
} | ||
} |
This file contains bidirectional Unicode text that may be interpreted or compiled differently than what appears below. To review, open the file in an editor that reveals hidden Unicode characters.
Learn more about bidirectional Unicode characters
Original file line number | Diff line number | Diff line change |
---|---|---|
@@ -0,0 +1,202 @@ | ||
use web3::types::U256; | ||
use franklin_transaction::FranklinTransaction; | ||
use helpers::*; | ||
use block_events::BlockEventsFranklin; | ||
use accounts_state::FranklinAccountsStates; | ||
use blocks::LogBlockData; | ||
use std::sync::mpsc::Sender; | ||
use plasma::models::Fr; | ||
|
||
pub struct ProtoAccountsState { | ||
errored: bool, | ||
root_hash: Fr, | ||
} | ||
|
||
pub struct DataRestoreDriver { | ||
pub channel: Option<Sender<ProtoAccountsState>>, | ||
pub endpoint: InfuraEndpoint, | ||
pub genesis_block: U256, | ||
pub blocks_delta: U256, | ||
pub run_updates: bool, | ||
pub block_events: BlockEventsFranklin, | ||
pub account_states: FranklinAccountsStates, | ||
} | ||
|
||
impl DataRestoreDriver { | ||
|
||
pub fn new(endpoint: InfuraEndpoint, genesis_block: U256, blocks_delta: U256, channel: Option<Sender<ProtoAccountsState>>) -> Self { | ||
Self { | ||
channel: channel, | ||
endpoint: endpoint, | ||
genesis_block: genesis_block, | ||
blocks_delta: blocks_delta, | ||
run_updates: false, | ||
block_events: BlockEventsFranklin::new(endpoint), | ||
account_states: FranklinAccountsStates::new(endpoint), | ||
} | ||
} | ||
|
||
pub fn load_past_state(&mut self) -> Result<(), DataRestoreError> { | ||
println!("Loading past state"); | ||
let states = DataRestoreDriver::get_past_franklin_blocks_events_and_accounts_tree_state(self.endpoint, self.genesis_block, self.blocks_delta).map_err(|e| DataRestoreError::NoData(e.to_string()))?; | ||
self.block_events = states.0; | ||
self.account_states = states.1; | ||
|
||
// let accs = &self.account_states.get_accounts(); | ||
// println!("Accs: {:?}", accs); | ||
let root = &self.account_states.root_hash(); | ||
println!("Root: {:?}", &root); | ||
println!("______________"); | ||
|
||
if let Some(ref _channel) = self.channel { | ||
let state = ProtoAccountsState { | ||
errored: false, | ||
root_hash: root.clone(), | ||
}; | ||
let _send_result = _channel.send(state); | ||
if _send_result.is_err() { | ||
return Err(DataRestoreError::StateUpdate("Cant send last state".to_string())); | ||
} | ||
} | ||
println!("Finished loading past state"); | ||
Ok(()) | ||
} | ||
|
||
pub fn stop_state_updates(&mut self) { | ||
self.run_updates = false | ||
} | ||
|
||
pub fn run_state_updates(&mut self) -> Option<DataRestoreError> { | ||
println!("Start state updates"); | ||
self.run_updates = true; | ||
let mut err: Option<DataRestoreError> = None; | ||
while self.run_updates { | ||
match DataRestoreDriver::update_franklin_blocks_events_and_accounts_tree_state(self) { | ||
Err(error) => { | ||
println!("Something goes wrong: {:?}", error); | ||
self.run_updates = false; | ||
err = Some(DataRestoreError::StateUpdate(format!("Error occured: {:?}", error))); | ||
}, | ||
Ok(()) => { | ||
// println!("Updated, last watched ethereum block: {:?}", &self.block_events.last_watched_block_number); | ||
// println!("Committed franklin blocks count: {:?}", &self.block_events.committed_blocks.len()); | ||
// println!("Last committed franklin block: {:?}", &self.block_events.committed_blocks.last()); | ||
// println!("Verified franklin blocks count: {:?}", &self.block_events.verified_blocks.len()); | ||
// println!("Last verified franklin block: {:?}", &self.block_events.verified_blocks.last()); | ||
// let accs = self.account_states.get_accounts(); | ||
// let root = self.account_states.root_hash(); | ||
// println!("Accs: {:?}", accs); | ||
// println!("Root: {:?}", &root); | ||
}, | ||
}; | ||
let root = self.account_states.root_hash(); | ||
println!("New root: {:?}", &root); | ||
println!("______________"); | ||
if let Some(ref _channel) = self.channel { | ||
let state = ProtoAccountsState { | ||
errored: !self.run_updates, | ||
root_hash: root.clone(), | ||
}; | ||
let _send_result = _channel.send(state); | ||
if _send_result.is_err() { | ||
self.run_updates = false; | ||
err = Some(DataRestoreError::StateUpdate("Cant send last state".to_string())); | ||
} | ||
} | ||
} | ||
println!("Stopped state updates"); | ||
return err; | ||
} | ||
|
||
fn get_past_franklin_blocks_events_and_accounts_tree_state(endpoint: InfuraEndpoint, genesis_block: U256, blocks_delta: U256) -> Result<(BlockEventsFranklin, FranklinAccountsStates), DataRestoreError> { | ||
let events_state = DataRestoreDriver::get_past_blocks_state(endpoint, genesis_block, blocks_delta).map_err(|e| DataRestoreError::NoData(e.to_string()))?; | ||
// println!("Last watched block: {:?}", events_state.last_watched_block_number); | ||
let verified_blocks = events_state.verified_blocks.clone(); | ||
let txs = DataRestoreDriver::get_verified_committed_blocks_transactions_from_blocks_state(&events_state, &verified_blocks); | ||
let sorted_txs = DataRestoreDriver::sort_transactions_by_block_number(txs); | ||
// println!("Transactions: {:?}", sorted_txs); | ||
|
||
let mut accounts_state = FranklinAccountsStates::new(endpoint); | ||
let _ = DataRestoreDriver::update_accounts_state_from_transactions(&mut accounts_state, &sorted_txs).map_err(|e| DataRestoreError::StateUpdate(e.to_string()))?; | ||
println!("Accounts and events state finished update"); | ||
Ok((events_state, accounts_state)) | ||
} | ||
|
||
fn get_past_blocks_state(endpoint: InfuraEndpoint, genesis_block: U256, blocks_delta: U256) -> Result<BlockEventsFranklin, DataRestoreError> { | ||
let events = BlockEventsFranklin::get_past_state_from_genesis_with_blocks_delta(endpoint, genesis_block, blocks_delta).map_err(|e| DataRestoreError::NoData(e.to_string()))?; | ||
println!("Got past events state till ethereum block: {:?}", &events.last_watched_block_number); | ||
println!("Committed franklin blocks count: {:?}", &events.committed_blocks.len()); | ||
println!("Last committed franklin block: {:?}", &events.committed_blocks.last()); | ||
println!("Verified franklin blocks count: {:?}", &events.verified_blocks.len()); | ||
println!("Last verified franklin block: {:?}", &events.verified_blocks.last()); | ||
Ok(events) | ||
} | ||
|
||
fn get_verified_committed_blocks_transactions_from_blocks_state(block_events_state: &BlockEventsFranklin, verified_blocks: &Vec<LogBlockData>) -> Vec<FranklinTransaction> { | ||
let committed_blocks = block_events_state.get_only_verified_committed_blocks(verified_blocks); | ||
// println!("Committed verified blocks: {:?}", committed_blocks); | ||
let mut transactions = vec![]; | ||
for block in committed_blocks { | ||
let tx = FranklinTransaction::get_transaction(block_events_state.endpoint, &block); | ||
if tx.is_none() { | ||
continue; | ||
} | ||
transactions.push(tx.unwrap()); | ||
} | ||
println!("Transactions sorted: only verified commited"); | ||
transactions | ||
} | ||
|
||
fn sort_transactions_by_block_number(transactions: Vec<FranklinTransaction>) -> Vec<FranklinTransaction> { | ||
let mut sorted_transactions = transactions; | ||
sorted_transactions.sort_by_key(|x| x.block_number); | ||
println!("Transactions sorted: by number"); | ||
sorted_transactions | ||
} | ||
|
||
fn update_accounts_state_from_transactions(state: &mut FranklinAccountsStates, transactions: &Vec<FranklinTransaction>) -> Result<(), DataRestoreError> { | ||
// let mut state = accounts_state::FranklinAccountsStates::new(endpoint); | ||
println!("Start accounts state updating"); | ||
for transaction in transactions { | ||
let _ = state.update_accounts_states_from_transaction(&transaction).map_err(|e| DataRestoreError::StateUpdate(e.to_string()))?; | ||
} | ||
println!("Finished accounts state updating"); | ||
Ok(()) | ||
} | ||
|
||
fn update_franklin_blocks_events_and_accounts_tree_state(data_restore_driver: &mut DataRestoreDriver) -> Result<(), DataRestoreError> { | ||
let mut new_events: (Vec<LogBlockData>, Vec<LogBlockData>) = (vec![], vec![]); | ||
while data_restore_driver.run_updates { | ||
let ne = data_restore_driver.block_events.update_state_from_last_watched_block_with_blocks_delta_and_return_new_blocks(data_restore_driver.blocks_delta); | ||
match ne { | ||
Ok(result) => new_events = result, | ||
Err(error) => { | ||
println!("Got no events: {:?}", error); | ||
continue | ||
}, | ||
} | ||
if new_events.1.is_empty() { | ||
println!("No new verified blocks"); | ||
continue | ||
// return Err(DataRestoreError::NoData("No verified blocks".to_string())) | ||
} else { | ||
println!("Got new events state till ethereum block: {:?}", &data_restore_driver.block_events.last_watched_block_number); | ||
println!("Committed franklin blocks count: {:?}", &data_restore_driver.block_events.committed_blocks.len()); | ||
println!("Last committed franklin block: {:?}", &data_restore_driver.block_events.committed_blocks.last()); | ||
println!("Verified franklin blocks count: {:?}", &data_restore_driver.block_events.verified_blocks.len()); | ||
println!("Last verified franklin block: {:?}", &data_restore_driver.block_events.verified_blocks.last()); | ||
break | ||
} | ||
} | ||
if !data_restore_driver.run_updates { | ||
return Err(DataRestoreError::StateUpdate("Stopped getting new blocks".to_string())) | ||
} | ||
let verified_blocks = &new_events.1; | ||
let txs = DataRestoreDriver::get_verified_committed_blocks_transactions_from_blocks_state(&data_restore_driver.block_events, &verified_blocks); | ||
let sorted_txs = DataRestoreDriver::sort_transactions_by_block_number(txs); | ||
|
||
let _ = DataRestoreDriver::update_accounts_state_from_transactions(&mut data_restore_driver.account_states, &sorted_txs).map_err(|e| DataRestoreError::StateUpdate(e.to_string()))?; | ||
|
||
Ok(()) | ||
} | ||
} |
This file contains bidirectional Unicode text that may be interpreted or compiled differently than what appears below. To review, open the file in an editor that reveals hidden Unicode characters.
Learn more about bidirectional Unicode characters
Original file line number | Diff line number | Diff line change |
---|---|---|
@@ -0,0 +1,98 @@ | ||
use web3::futures::Future; | ||
use web3::types::{H256, Transaction, TransactionId}; | ||
|
||
use helpers::*; | ||
use blocks::LogBlockData; | ||
|
||
#[derive(Debug, Copy, Clone)] | ||
pub enum FranklinTransactionType { | ||
Deposit, | ||
Transfer, | ||
FullExit, | ||
Unknown | ||
} | ||
|
||
#[derive(Debug, Clone)] | ||
pub struct FranklinTransaction { | ||
pub network: InfuraEndpoint, | ||
pub franklin_transaction_type: FranklinTransactionType, | ||
pub block_number: u32, | ||
pub ethereum_transaction: Transaction, | ||
pub commitment_data: Vec<u8>, | ||
} | ||
|
||
impl FranklinTransaction { | ||
pub fn get_transaction(network: InfuraEndpoint, franklin_block: &LogBlockData) -> Option<Self> { | ||
let transaction = FranklinTransaction::get_ethereum_transaction(network, &franklin_block.transaction_hash)?; | ||
let input_data = FranklinTransaction::get_input_data_from_ethereum_transaction(&transaction); | ||
let tx_type = FranklinTransaction::get_transaction_type(&input_data); | ||
let commitment_data = FranklinTransaction::get_commitment_data_from_input_data(&input_data)?; | ||
let this = Self { | ||
network: network, | ||
franklin_transaction_type: tx_type, | ||
block_number: franklin_block.block_num, | ||
ethereum_transaction: transaction, | ||
commitment_data: commitment_data, | ||
}; | ||
Some(this) | ||
} | ||
|
||
fn get_ethereum_transaction(network: InfuraEndpoint, transaction_hash: &H256) -> Option<Transaction> { | ||
let infura_endpoint = match network { | ||
InfuraEndpoint::Mainnet => INFURA_MAINNET_ENDPOINT, | ||
InfuraEndpoint::Rinkeby => INFURA_RINKEBY_ENDPOINT, | ||
}; | ||
let (_eloop, transport) = web3::transports::Http::new(infura_endpoint).unwrap(); | ||
let web3 = web3::Web3::new(transport); | ||
let tx_id = TransactionId::Hash(transaction_hash.clone()); | ||
let web3_transaction = web3.eth().transaction(tx_id).wait(); | ||
let tx = match web3_transaction { | ||
Ok(tx) => { | ||
tx | ||
}, | ||
Err(_) => { | ||
None | ||
} | ||
}; | ||
tx | ||
} | ||
|
||
fn get_input_data_from_ethereum_transaction(transaction: &Transaction) -> Vec<u8> { | ||
transaction.clone().input.0 | ||
} | ||
|
||
fn get_commitment_data_from_input_data(input_data: &Vec<u8>) -> Option<Vec<u8>> { | ||
let input_data_contains_more_than_4_bytes = input_data.len() > 4; | ||
let commitment_data = match input_data_contains_more_than_4_bytes { | ||
true => Some(input_data[4..input_data.len()].to_vec()), | ||
false => None | ||
}; | ||
commitment_data | ||
} | ||
|
||
fn get_transaction_type(input_data: &Vec<u8>) -> FranklinTransactionType { | ||
let input_data_contains_more_than_4_bytes = input_data.len() > 4; | ||
if input_data_contains_more_than_4_bytes == false { | ||
return FranklinTransactionType::Unknown | ||
} | ||
let deposit_method_bytes: Vec<u8> = vec![83, 61, 227, 10]; | ||
let transaction_method_bytes: Vec<u8> = vec![244, 135, 178, 142]; | ||
let full_exit_method_bytes: Vec<u8> = vec![121, 178, 173, 112]; | ||
let method_bytes: Vec<u8> = input_data[0..4].to_vec(); | ||
let method_type = match method_bytes { | ||
_ if method_bytes == deposit_method_bytes => { | ||
FranklinTransactionType::Deposit | ||
}, | ||
_ if method_bytes == transaction_method_bytes => { | ||
FranklinTransactionType::Transfer | ||
}, | ||
_ if method_bytes == full_exit_method_bytes => { | ||
FranklinTransactionType::FullExit | ||
}, | ||
_ => { | ||
FranklinTransactionType::Unknown | ||
} | ||
}; | ||
method_type | ||
} | ||
} |
Oops, something went wrong.