Skip to content

Commit

Permalink
Merge branch 'dev' into ib-port_transaction_batches_into_dev
Browse files Browse the repository at this point in the history
  • Loading branch information
popzxc committed Sep 17, 2020
2 parents a099c90 + dcddded commit 1d4cc8c
Show file tree
Hide file tree
Showing 25 changed files with 2,471 additions and 28 deletions.
24 changes: 24 additions & 0 deletions Cargo.lock

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

1 change: 1 addition & 0 deletions Cargo.toml
Original file line number Diff line number Diff line change
Expand Up @@ -15,5 +15,6 @@ members = [
"core/testkit",
"core/loadtest",
"core/crypto_exports",
"core/sdk",
"core/tok_cli"
]
14 changes: 13 additions & 1 deletion core/eth_client/src/lib.rs
Original file line number Diff line number Diff line change
Expand Up @@ -127,6 +127,18 @@ impl<T: Transport> ETHClient<T> {
&self,
data: Vec<u8>,
options: Options,
) -> Result<SignedCallResult, failure::Error> {
self.sign_prepared_tx_for_addr(data, self.contract_addr, options)
.await
}

/// Signs the transaction given the previously encoded data.
/// Fills in gas/nonce if not supplied inside options.
pub async fn sign_prepared_tx_for_addr(
&self,
data: Vec<u8>,
contract_addr: H160,
options: Options,
) -> Result<SignedCallResult, failure::Error> {
// fetch current gas_price
let gas_price = match options.gas_price {
Expand Down Expand Up @@ -158,7 +170,7 @@ impl<T: Transport> ETHClient<T> {
let tx = signer::RawTransaction {
chain_id: self.chain_id,
nonce,
to: Some(self.contract_addr),
to: Some(contract_addr),
value: options.value.unwrap_or_default(),
gas_price,
gas,
Expand Down
2 changes: 2 additions & 0 deletions core/models/src/abi.rs
Original file line number Diff line number Diff line change
Expand Up @@ -9,6 +9,8 @@ const IERC20_CONTRACT_FILE: &str = "contracts/build/IERC20.json";
const IEIP1271_CONTRACT_FILE: &str = "contracts/build/IEIP1271.json";

fn read_file_to_json_value(path: &str) -> io::Result<serde_json::Value> {
let zksync_home = std::env::var("ZKSYNC_HOME").unwrap_or_else(|_| ".".into());
let path = std::path::Path::new(&zksync_home).join(path);
let contents = fs::read_to_string(path)?;
let val = serde_json::Value::from_str(&contents)?;
Ok(val)
Expand Down
1 change: 0 additions & 1 deletion core/models/src/lib.rs
Original file line number Diff line number Diff line change
Expand Up @@ -14,7 +14,6 @@ pub mod params;
pub mod primitives;
pub mod prover_utils;
pub mod serialization;

// TODO: refactor, find new home for all this stuff

pub use crypto_exports::franklin_crypto;
Expand Down
7 changes: 7 additions & 0 deletions core/models/src/node/config.rs
Original file line number Diff line number Diff line change
Expand Up @@ -9,3 +9,10 @@ pub const MAX_WITHDRAWALS_TO_COMPLETE_IN_A_CALL: u64 = 20;
pub const LEADER_LOOKUP_INTERVAL: Duration = Duration::from_secs(1);
/// Interval between state updates in server replica's observer mode.
pub const OBSERVER_MODE_PULL_INTERVAL: Duration = Duration::from_secs(1);

// Parameters below are considered stable thus no need to keep them inside env.

/// Depth of the account tree.
pub const ACCOUNT_TREE_DEPTH: usize = 32;
/// Depth of the balance tree for each account.
pub const BALANCE_TREE_DEPTH: usize = 11;
12 changes: 12 additions & 0 deletions core/models/src/node/tokens.rs
Original file line number Diff line number Diff line change
Expand Up @@ -21,6 +21,18 @@ impl From<TokenId> for TokenLike {
}
}

impl From<Address> for TokenLike {
fn from(address: Address) -> Self {
Self::Address(address)
}
}

impl From<&str> for TokenLike {
fn from(symbol: &str) -> Self {
Self::Symbol(symbol.to_string())
}
}

/// Token supported in zkSync protocol
#[derive(Debug, Serialize, Deserialize, Clone, PartialEq)]
pub struct Token {
Expand Down
28 changes: 2 additions & 26 deletions core/models/src/params.rs
Original file line number Diff line number Diff line change
Expand Up @@ -6,43 +6,19 @@ use std::str::FromStr;
use crate::franklin_crypto::alt_babyjubjub::AltJubjubBn256;
use lazy_static::lazy_static;
// Workspace deps
use crate::config_options::parse_env;
use crate::franklin_crypto::rescue::bn256::Bn256RescueParams;
use crate::merkle_tree::pedersen_hasher::BabyPedersenHasher;
use crate::merkle_tree::rescue_hasher::BabyRescueHasher;
use crate::node::{AccountId, TokenId};

static mut ACCOUNT_TREE_DEPTH_VALUE: usize = 0;
/// account_tree_depth.
pub fn account_tree_depth() -> usize {
unsafe {
if ACCOUNT_TREE_DEPTH_VALUE == 0 {
let runtime_value = parse_env::<usize>("ACCOUNT_TREE_DEPTH");
ACCOUNT_TREE_DEPTH_VALUE = runtime_value;
}
assert!(ACCOUNT_TREE_DEPTH_VALUE <= ACCOUNT_ID_BIT_WIDTH);

ACCOUNT_TREE_DEPTH_VALUE
}
crate::node::config::ACCOUNT_TREE_DEPTH
}

static mut BALANCE_TREE_DEPTH_VALUE: usize = 0;
/// balance tree_depth.
/// Value must be specified as environment variable at compile time under `BALANCE_TREE_DEPTH_VALUE` key.
pub fn balance_tree_depth() -> usize {
// use of mutable static is unsafe as it can be mutated by multiple threads.
// There's no risk of data race, the worst that can happen is that we parse
// and set environment value multuple times, which is ok.

unsafe {
if BALANCE_TREE_DEPTH_VALUE == 0 {
let runtime_value = parse_env::<usize>("BALANCE_TREE_DEPTH");
BALANCE_TREE_DEPTH_VALUE = runtime_value;
}
assert!(BALANCE_TREE_DEPTH_VALUE <= TOKEN_BIT_WIDTH);

BALANCE_TREE_DEPTH_VALUE
}
crate::node::config::BALANCE_TREE_DEPTH
}
/// Number of supported tokens.
pub fn total_tokens() -> usize {
Expand Down
36 changes: 36 additions & 0 deletions core/sdk/Cargo.toml
Original file line number Diff line number Diff line change
@@ -0,0 +1,36 @@
[package]
name = "zksync"
version = "0.1.0"
authors = ["The Matter Labs Team <[email protected]>"]
edition = "2018"

[dependencies]
models = { path = "../models", version = "0.0.1" }
eth_client = { path = "../eth_client", version = "0.1.0" }
crypto_exports = { path = "../crypto_exports", version = "0.1.0" }
franklin_crypto = { package = "franklin-crypto", git = "https://github.com/matter-labs/franklin-crypto.git", branch="check-franklin-circuit-transpile"}

bellman = { package = "bellman_ce", git = "https://github.com/matter-labs/bellman", branch = "plonk_release" }
sha2 = "0.8"
web3 = "0.10.0"
ethabi = "9.0.0"
tokio = { version = "0.2", features = ["time"] }
futures = { version = "0.3", features = ["compat"] }

serde = "1.0.90"
serde_derive = "1.0.90"
serde_json = "1.0.0"

reqwest = { version = "0.10", features = ["json", "blocking"] }
anyhow = "1.0"
thiserror = "1.0"

jsonrpc-core = "14.0.3"

num = { version = "0.2", features = ["serde"] }

[dev-dependencies]
tokio = { version = "0.2", features = ["full"] }

[features]
integration-tests = []
91 changes: 91 additions & 0 deletions core/sdk/src/credentials.rs
Original file line number Diff line number Diff line change
@@ -0,0 +1,91 @@
use crate::{error::ClientError, utils::private_key_from_seed};
use models::node::{tx::PackedEthSignature, PrivateKey};
use web3::types::{Address, H256};

pub struct WalletCredentials {
pub(crate) eth_private_key: Option<H256>,
pub(crate) eth_address: Address,
pub(crate) zksync_private_key: PrivateKey,
}

impl std::fmt::Debug for WalletCredentials {
fn fmt(&self, f: &mut std::fmt::Formatter<'_>) -> std::fmt::Result {
f.debug_struct("WalletCredentials")
.field("eth_address", &self.eth_address)
.finish()
}
}

impl WalletCredentials {
/// Creates wallet credentials from the provided Ethereum wallet private key.
///
/// ## Arguments
///
/// - `eth_address`: Address of the corresponding Ethereum wallet.
/// - `eth_private_key`: Private key of a corresponding Ethereum account.
pub fn from_eth_pk(eth_address: Address, eth_private_key: H256) -> Result<Self, ClientError> {
// Pre-defined message to generate seed from.
const ETH_SIGN_MESSAGE: &[u8] =
b"Access zkSync account.\n\nOnly sign this message for a trusted client!";

// Check that private key is correct and corresponds to the provided address.
let address_from_pk = PackedEthSignature::address_from_private_key(&eth_private_key);
if !address_from_pk
.map(|address_from_pk| eth_address == address_from_pk)
.unwrap_or(false)
{
return Err(ClientError::IncorrectCredentials);
}

// Generate seed, and then zkSync private key.
let signature = PackedEthSignature::sign(&eth_private_key, ETH_SIGN_MESSAGE)
.map_err(|_| ClientError::IncorrectCredentials)?;

let signature_bytes = signature.serialize_packed();
let zksync_pk = private_key_from_seed(&signature_bytes)?;

Ok(Self {
eth_private_key: Some(eth_private_key),
eth_address,
zksync_private_key: zksync_pk,
})
}

/// Creates wallet credentials from the provided seed.
/// zkSync private key will be randomly generated and Ethereum private key will be not set.
/// Wallet created with such credentials won't be capable of performing on-chain operations,
/// such as deposits and full exits.
///
/// ## Arguments
///
/// - `eth_address`: Address of the corresponding Ethereum wallet.
/// - `seed`: A random bytearray to generate private key from. Must be at least 32 bytes long.
pub fn from_seed(eth_address: Address, seed: &[u8]) -> Result<Self, ClientError> {
let zksync_pk = private_key_from_seed(seed)?;

Ok(Self {
eth_private_key: None,
eth_address,
zksync_private_key: zksync_pk,
})
}

/// Creates wallet credentials from the provided keys.
///
/// ## Arguments
///
/// - `eth_address`: Address of the corresponding Ethereum wallet.
/// - `private_key`: Private key of a zkSync account.
/// - `eth_private_key`: Private key of a corresponding Ethereum wallet. If not set, on-chain operations won't be allowed for Wallet.
pub fn from_pk(
eth_address: Address,
private_key: PrivateKey,
eth_private_key: Option<H256>,
) -> Self {
Self {
eth_address,
eth_private_key,
zksync_private_key: private_key,
}
}
}
49 changes: 49 additions & 0 deletions core/sdk/src/error.rs
Original file line number Diff line number Diff line change
@@ -0,0 +1,49 @@
pub use jsonrpc_core::types::response::Failure as RpcFailure;
use thiserror::Error;

#[derive(Debug, Error)]
pub enum ClientError {
#[error("Network '{0}' is not supported")]
NetworkNotSupported(String),
#[error("Unable to decode server response")]
MalformedResponse(String),
#[error("RPC error: {0:?}")]
RpcError(RpcFailure),
#[error("Network error: {0}")]
NetworkError(String),

#[error("Provided account credentials are incorrect")]
IncorrectCredentials,
#[error("Seed too short, must be at least 32 bytes long")]
SeedTooShort,
#[error("Token is not supported by zkSync")]
UnknownToken,
#[error("Incorrect address")]
IncorrectAddress,

#[error("Operation timeout")]
OperationTimeout,
#[error("Polling interval is too small")]
PollingIntervalIsTooSmall,

#[error("Signing error: {0}")]
SigningError(SignerError),
#[error("Missing required field for a transaction: {0}")]
MissingRequiredField(String),

#[error("Ethereum private key was not provided for this wallet")]
NoEthereumPrivateKey,

#[error("Provided value is not packable")]
NotPackableValue,
}

#[derive(Debug, Error)]
pub enum SignerError {
#[error("Ethereum private key required to perform an operation")]
MissingEthPrivateKey,
#[error("Signing failed: {0}")]
SigningFailed(String),
#[error("Signing key is not set in account")]
NoSigningKey,
}
Loading

0 comments on commit 1d4cc8c

Please sign in to comment.