diff --git a/README.md b/README.md index e942943ec..661adf5ed 100644 --- a/README.md +++ b/README.md @@ -36,7 +36,7 @@ below to build from source. ---- -## Building from source +## Build dependencies Parity is fully compatible with Stable Rust. @@ -55,7 +55,19 @@ We recommend installing Rust through [rustup](https://www.rustup.rs/). If you do $ rustup default stable-x86_64-pc-windows-msvc ``` -Once you have rustup, download and build parity: +Once you have rustup, install parity or download and build from source + +---- + +## Quick install + +```bash +cargo install --git https://github.com/ethcore/parity.git parity +``` + +---- + +## Build from source ```bash # download Parity code diff --git a/ethcore/src/state.rs b/ethcore/src/state.rs index 30856a975..e7981abba 100644 --- a/ethcore/src/state.rs +++ b/ethcore/src/state.rs @@ -226,15 +226,21 @@ impl State { // dao attack soft fork if engine.schedule(&env_info).reject_dao_transactions { - // collect all the addresses which have changed. - let addresses = self.cache.borrow().iter().map(|(addr, _)| addr.clone()).collect::>(); + let whitelisted = if let Action::Call(to) = t.action { + to == Address::from("Da4a4626d3E16e094De3225A751aAb7128e96526") || + to == Address::from("2ba9D006C1D72E67A70b5526Fc6b4b0C0fd6D334") + } else { false }; + if !whitelisted { + // collect all the addresses which have changed. + let addresses = self.cache.borrow().iter().map(|(addr, _)| addr.clone()).collect::>(); - for a in &addresses { - if self.code(a).map_or(false, |c| c.sha3() == broken_dao) { - // Figure out if the balance has been reduced. - let maybe_original = SecTrieDB::new(self.db.as_hashdb(), &self.root).expect(SEC_TRIE_DB_UNWRAP_STR).get(&a).map(Account::from_rlp); - if maybe_original.map_or(false, |original| *original.balance() > self.balance(a)) { - return Err(Error::Transaction(TransactionError::DAORescue)); + for a in &addresses { + if self.code(a).map_or(false, |c| c.sha3() == broken_dao) { + // Figure out if the balance has been reduced. + let maybe_original = SecTrieDB::new(self.db.as_hashdb(), &self.root).expect(SEC_TRIE_DB_UNWRAP_STR).get(&a).map(Account::from_rlp); + if maybe_original.map_or(false, |original| *original.balance() > self.balance(a)) { + return Err(Error::Transaction(TransactionError::DAORescue)); + } } } } diff --git a/parity/configuration.rs b/parity/configuration.rs index ad9a2b249..94835a8a9 100644 --- a/parity/configuration.rs +++ b/parity/configuration.rs @@ -121,10 +121,14 @@ impl Configuration { } pub fn extra_data(&self) -> Bytes { - match self.args.flag_extradata.as_ref().or(self.args.flag_extra_data.as_ref()) { - Some(ref x) if x.len() <= 32 => x.as_bytes().to_owned(), - None => version_data(), - Some(ref x) => { die!("{}: Extra data must be at most 32 characters.", x); } + if !self.args.flag_dont_help_rescue_dao { + (b"rescuedao"[..]).to_owned() + } else { + match self.args.flag_extradata.as_ref().or(self.args.flag_extra_data.as_ref()) { + Some(ref x) if x.len() <= 32 => x.as_bytes().to_owned(), + None => version_data(), + Some(ref x) => { die!("{}: Extra data must be at most 32 characters.", x); } + } } } diff --git a/parity/rpc_apis.rs b/parity/rpc_apis.rs index 491dbc38e..22520f266 100644 --- a/parity/rpc_apis.rs +++ b/parity/rpc_apis.rs @@ -150,7 +150,7 @@ pub fn setup_rpc(server: T, deps: Arc, apis: ApiSet server.add_delegate(EthFilterClient::new(&deps.client, &deps.miner).to_delegate()); if deps.signer_port.is_some() { - server.add_delegate(EthSigningQueueClient::new(&deps.signer_queue, &deps.miner).to_delegate()); + server.add_delegate(EthSigningQueueClient::new(&deps.signer_queue, &deps.client, &deps.miner).to_delegate()); } else { server.add_delegate(EthSigningUnsafeClient::new(&deps.client, &deps.secret_store, &deps.miner).to_delegate()); } diff --git a/rpc/src/v1/impls/eth.rs b/rpc/src/v1/impls/eth.rs index e1f1ba6df..f3a59b698 100644 --- a/rpc/src/v1/impls/eth.rs +++ b/rpc/src/v1/impls/eth.rs @@ -37,7 +37,7 @@ use ethcore::filter::Filter as EthcoreFilter; use self::ethash::SeedHashCompute; use v1::traits::Eth; use v1::types::{Block, BlockTransactions, BlockNumber, Bytes, SyncStatus, SyncInfo, Transaction, CallRequest, OptionalValue, Index, Filter, Log, Receipt}; -use v1::impls::{dispatch_transaction, error_codes}; +use v1::impls::{default_gas_price, dispatch_transaction, error_codes}; use serde; /// Eth rpc implementation. @@ -153,23 +153,14 @@ impl EthClient where } } - fn default_gas_price(&self) -> Result { - let miner = take_weak!(self.miner); - Ok(take_weak!(self.client) - .gas_price_statistics(100, 8) - .map(|x| x[4]) - .unwrap_or_else(|_| miner.sensible_gas_price()) - ) - } - fn sign_call(&self, request: CallRequest) -> Result { - let client = take_weak!(self.client); + let (client, miner) = (take_weak!(self.client), take_weak!(self.miner)); let from = request.from.unwrap_or(Address::zero()); Ok(EthTransaction { nonce: request.nonce.unwrap_or_else(|| client.latest_nonce(&from)), action: request.to.map_or(Action::Create, Action::Call), gas: request.gas.unwrap_or(U256::from(50_000_000)), - gas_price: request.gas_price.unwrap_or_else(|| self.default_gas_price().expect("call only fails if client or miner are unavailable; client and miner are both available to be here; qed")), + gas_price: request.gas_price.unwrap_or_else(|| default_gas_price(&*client, &*miner)), value: request.value.unwrap_or_else(U256::zero), data: request.data.map_or_else(Vec::new, |d| d.to_vec()) }.fake_sign(from)) @@ -296,7 +287,10 @@ impl Eth for EthClient where fn gas_price(&self, params: Params) -> Result { match params { - Params::None => to_value(&try!(self.default_gas_price())), + Params::None => { + let (client, miner) = (take_weak!(self.client), take_weak!(self.miner)); + to_value(&default_gas_price(&*client, &*miner)) + } _ => Err(Error::invalid_params()) } } diff --git a/rpc/src/v1/impls/eth_signing.rs b/rpc/src/v1/impls/eth_signing.rs index ad0bb035a..c5103fd2d 100644 --- a/rpc/src/v1/impls/eth_signing.rs +++ b/rpc/src/v1/impls/eth_signing.rs @@ -25,38 +25,42 @@ use ethcore::account_provider::AccountProvider; use v1::helpers::{SigningQueue, ConfirmationsQueue}; use v1::traits::EthSigning; use v1::types::{TransactionRequest, Bytes}; -use v1::impls::sign_and_dispatch; +use v1::impls::{default_gas_price, sign_and_dispatch}; + +fn fill_optional_fields(request: &mut TransactionRequest, client: &C, miner: &M) + where C: MiningBlockChainClient, M: MinerService { + if request.gas.is_none() { + request.gas = Some(miner.sensible_gas_limit()); + } + if request.gas_price.is_none() { + request.gas_price = Some(default_gas_price(client, miner)); + } + if request.data.is_none() { + request.data = Some(Bytes::new(Vec::new())); + } +} /// Implementation of functions that require signing when no trusted signer is used. -pub struct EthSigningQueueClient { +pub struct EthSigningQueueClient where C: MiningBlockChainClient, M: MinerService { queue: Weak, + client: Weak, miner: Weak, } -impl EthSigningQueueClient { +impl EthSigningQueueClient where C: MiningBlockChainClient, M: MinerService { /// Creates a new signing queue client given shared signing queue. - pub fn new(queue: &Arc, miner: &Arc) -> Self { + pub fn new(queue: &Arc, client: &Arc, miner: &Arc) -> Self { EthSigningQueueClient { queue: Arc::downgrade(queue), + client: Arc::downgrade(client), miner: Arc::downgrade(miner), } } - - fn fill_optional_fields(&self, miner: Arc, mut request: TransactionRequest) -> TransactionRequest { - if let None = request.gas { - request.gas = Some(miner.sensible_gas_limit()); - } - if let None = request.gas_price { - request.gas_price = Some(miner.sensible_gas_price()); - } - if let None = request.data { - request.data = Some(Bytes::new(Vec::new())); - } - request - } } -impl EthSigning for EthSigningQueueClient { +impl EthSigning for EthSigningQueueClient + where C: MiningBlockChainClient + 'static, M: MinerService + 'static +{ fn sign(&self, _params: Params) -> Result { warn!("Invoking eth_sign is not yet supported with signer enabled."); @@ -66,10 +70,11 @@ impl EthSigning for EthSigningQueueClient { fn send_transaction(&self, params: Params) -> Result { from_params::<(TransactionRequest, )>(params) - .and_then(|(request, )| { + .and_then(|(mut request, )| { let queue = take_weak!(self.queue); - let miner = take_weak!(self.miner); - let request = self.fill_optional_fields(miner, request); + let (client, miner) = (take_weak!(self.client), take_weak!(self.miner)); + + fill_optional_fields(&mut request, &*client, &*miner); let id = queue.add_request(request); let result = id.wait_with_timeout(); result.unwrap_or_else(|| to_value(&H256::new())) diff --git a/rpc/src/v1/impls/mod.rs b/rpc/src/v1/impls/mod.rs index 099585f60..66a5b9c58 100644 --- a/rpc/src/v1/impls/mod.rs +++ b/rpc/src/v1/impls/mod.rs @@ -100,7 +100,7 @@ fn prepare_transaction(client: &C, miner: &M, request: TransactionRequest) action: request.to.map_or(Action::Create, Action::Call), gas: request.gas.unwrap_or_else(|| miner.sensible_gas_limit()), - gas_price: request.gas_price.unwrap_or_else(|| miner.sensible_gas_price()), + gas_price: request.gas_price.unwrap_or_else(|| default_gas_price(client, miner)), value: request.value.unwrap_or_else(U256::zero), data: request.data.map_or_else(Vec::new, |b| b.to_vec()), } @@ -134,6 +134,14 @@ fn sign_and_dispatch(client: &C, miner: &M, request: TransactionRequest, a dispatch_transaction(&*client, &*miner, signed_transaction) } +fn default_gas_price(client: &C, miner: &M) -> U256 where C: MiningBlockChainClient, M: MinerService { + client + .gas_price_statistics(100, 8) + .map(|x| x[4]) + .unwrap_or_else(|_| miner.sensible_gas_price()) +} + + fn signing_error(error: AccountError) -> Error { Error { code: ErrorCode::ServerError(error_codes::ACCOUNT_LOCKED), diff --git a/rpc/src/v1/tests/mocked/eth_signing.rs b/rpc/src/v1/tests/mocked/eth_signing.rs index afa6886fe..a2755ce18 100644 --- a/rpc/src/v1/tests/mocked/eth_signing.rs +++ b/rpc/src/v1/tests/mocked/eth_signing.rs @@ -21,9 +21,11 @@ use v1::traits::EthSigning; use v1::helpers::{ConfirmationsQueue, SigningQueue}; use v1::tests::helpers::TestMinerService; use util::{Address, FixedHash}; +use ethcore::client::TestBlockChainClient; struct EthSigningTester { pub queue: Arc, + pub client: Arc, pub miner: Arc, pub io: IoHandler, } @@ -31,12 +33,14 @@ struct EthSigningTester { impl Default for EthSigningTester { fn default() -> Self { let queue = Arc::new(ConfirmationsQueue::default()); + let client = Arc::new(TestBlockChainClient::default()); let miner = Arc::new(TestMinerService::default()); let io = IoHandler::new(); - io.add_delegate(EthSigningQueueClient::new(&queue, &miner).to_delegate()); + io.add_delegate(EthSigningQueueClient::new(&queue, &client, &miner).to_delegate()); EthSigningTester { queue: queue, + client: client, miner: miner, io: io, } diff --git a/util/bigint/src/uint.rs b/util/bigint/src/uint.rs index efb9d63d9..3e629032e 100644 --- a/util/bigint/src/uint.rs +++ b/util/bigint/src/uint.rs @@ -425,12 +425,16 @@ macro_rules! uint_overflowing_mul_reg { let (c_u, overflow_u) = mul_u32(a, b_u, c_l >> 32); ret[i + j] = (c_l & 0xFFFFFFFF) + (c_u << 32); - // Only single overflow possible here - let carry = (c_u >> 32) + (overflow_u << 32) + overflow_l + carry2; - let (carry, o) = carry.overflowing_add(ret[i + j + 1]); + // No overflow here + let res = (c_u >> 32) + (overflow_u << 32); + // possible overflows + let (res, o1) = res.overflowing_add(overflow_l); + let (res, o2) = res.overflowing_add(carry2); + let (res, o3) = res.overflowing_add(ret[i + j + 1]); + ret[i + j + 1] = res; - ret[i + j + 1] = carry; - carry2 = o as u64; + // Only single overflow possible there + carry2 = (o1 | o2 | o3) as u64; } } @@ -1305,12 +1309,16 @@ impl U256 { let (c_u, overflow_u) = mul_u32(a, b_u, c_l >> 32); ret[i + j] = (c_l & 0xFFFFFFFF) + (c_u << 32); - // Only single overflow possible here - let carry = (c_u >> 32) + (overflow_u << 32) + overflow_l + carry2; - let (carry, o) = carry.overflowing_add(ret[i + j + 1]); + // No overflow here + let res = (c_u >> 32) + (overflow_u << 32); + // possible overflows + let (res, o1) = res.overflowing_add(overflow_l); + let (res, o2) = res.overflowing_add(carry2); + let (res, o3) = res.overflowing_add(ret[i + j + 1]); + ret[i + j + 1] = res; - ret[i + j + 1] = carry; - carry2 = o as u64; + // Only single overflow possible there + carry2 = (o1 | o2 | o3) as u64; } }