From 5e70507c7886f00626a6673989f4497ba0d2c4c3 Mon Sep 17 00:00:00 2001 From: Arkadiy Paronyan Date: Wed, 11 Jan 2017 20:03:08 +0100 Subject: [PATCH] Backporting to beta (#4118) * Ignore get_price_info test by default. (#4112) * Auto-detect hex encoded bytes in sha3 (#4108) * Auto-detect hex encoded bytes in sha3 * Using types/isHex * Removing unused imports * Use binary chop to estimate gas accurately (#4100) * Initial sketch. * Building. * Fix a few things. * Fix issue, add tracing. * Address grumbles * Raise upper limit if needed * Fix test. * Fixing decoding API with signatures in names (#4125) * Fix call/estimate_gas (#4121) * Return 0 instead of error with out of gas on estimate_gas * Fix stuff up. --- ethcore/src/client/client.rs | 75 +++++++++++++++++++ ethcore/src/client/test_client.rs | 4 + ethcore/src/client/traits.rs | 3 + ethcore/src/executive.rs | 2 +- ethcore/src/miner/miner.rs | 10 +-- ethcore/src/miner/price_info.rs | 2 +- ethcore/src/types/trace_types/trace.rs | 9 ++- ethcore/src/types/transaction.rs | 8 +- js/src/abi/spec/event/event.js | 4 +- js/src/abi/spec/function.js | 4 +- js/src/abi/spec/function.spec.js | 12 +++ js/src/abi/util/signature.js | 28 +++++-- js/src/abi/util/signature.spec.js | 73 ++++++++++++++---- js/src/api/util/sha3.js | 7 +- js/src/api/util/sha3.spec.js | 9 +++ js/src/api/util/types.js | 4 + js/src/api/util/types.spec.js | 6 ++ js/src/contracts/registry.js | 2 +- js/src/dapps/registry/Lookup/actions.js | 2 +- js/src/dapps/registry/Names/actions.js | 4 +- js/src/dapps/registry/Records/actions.js | 2 +- js/src/dapps/registry/util/registry.js | 2 +- .../ExecuteContract/executeContract.test.js | 6 +- js/src/modals/Verification/email-store.js | 2 +- js/src/modals/Verification/store.js | 4 +- .../Form/AddressSelect/addressSelectStore.js | 4 +- .../views/Settings/Background/background.js | 2 +- rpc/src/v1/impls/eth.rs | 9 +-- rpc/src/v1/tests/mocked/eth.rs | 4 +- 29 files changed, 243 insertions(+), 60 deletions(-) diff --git a/ethcore/src/client/client.rs b/ethcore/src/client/client.rs index 0a5bad75a..c612bb8fa 100644 --- a/ethcore/src/client/client.rs +++ b/ethcore/src/client/client.rs @@ -873,6 +873,81 @@ impl BlockChainClient for Client { Ok(ret) } + fn estimate_gas(&self, t: &SignedTransaction, block: BlockId) -> Result { + let header = self.block_header(block).ok_or(CallError::StatePruned)?; + let last_hashes = self.build_last_hashes(header.parent_hash()); + let env_info = EnvInfo { + number: header.number(), + author: header.author(), + timestamp: header.timestamp(), + difficulty: header.difficulty(), + last_hashes: last_hashes, + gas_used: U256::zero(), + gas_limit: U256::max_value(), + }; + // that's just a copy of the state. + let mut original_state = self.state_at(block).ok_or(CallError::StatePruned)?; + let sender = t.sender().map_err(|e| { + let message = format!("Transaction malformed: {:?}", e); + ExecutionError::TransactionMalformed(message) + })?; + let balance = original_state.balance(&sender); + let needed_balance = t.value + t.gas * t.gas_price; + if balance < needed_balance { + // give the sender a sufficient balance + original_state.add_balance(&sender, &(needed_balance - balance), CleanupMode::NoEmpty); + } + let options = TransactOptions { tracing: true, vm_tracing: false, check_nonce: false }; + let mut tx = t.clone(); + + let mut cond = |gas| { + let mut state = original_state.clone(); + tx.gas = gas; + Executive::new(&mut state, &env_info, &*self.engine, &self.factories.vm) + .transact(&tx, options.clone()) + .map(|r| r.trace[0].result.succeeded()) + .unwrap_or(false) + }; + + let mut upper = env_info.gas_limit; + if !cond(upper) { + // impossible at block gas limit - try `UPPER_CEILING` instead. + // TODO: consider raising limit by powers of two. + const UPPER_CEILING: u64 = 1_000_000_000_000u64; + upper = UPPER_CEILING.into(); + if !cond(upper) { + trace!(target: "estimate_gas", "estimate_gas failed with {}", upper); + return Err(CallError::Execution(ExecutionError::Internal)) + } + } + let lower = t.gas_required(&self.engine.schedule(&env_info)).into(); + if cond(lower) { + trace!(target: "estimate_gas", "estimate_gas succeeded with {}", lower); + return Ok(lower) + } + + /// Find transition point between `lower` and `upper` where `cond` changes from `false` to `true`. + /// Returns the lowest value between `lower` and `upper` for which `cond` returns true. + /// We assert: `cond(lower) = false`, `cond(upper) = true` + fn binary_chop(mut lower: U256, mut upper: U256, mut cond: F) -> U256 where F: FnMut(U256) -> bool { + while upper - lower > 1.into() { + let mid = (lower + upper) / 2.into(); + trace!(target: "estimate_gas", "{} .. {} .. {}", lower, mid, upper); + let c = cond(mid); + match c { + true => upper = mid, + false => lower = mid, + }; + trace!(target: "estimate_gas", "{} => {} .. {}", c, lower, upper); + } + upper + } + + // binary chop to non-excepting call with gas somewhere between 21000 and block gas limit + trace!(target: "estimate_gas", "estimate_gas chopping {} .. {}", lower, upper); + Ok(binary_chop(lower, upper, cond)) + } + fn replay(&self, id: TransactionId, analytics: CallAnalytics) -> Result { let address = self.transaction_address(id).ok_or(CallError::TransactionNotFound)?; let header = self.block_header(BlockId::Hash(address.block_hash)).ok_or(CallError::StatePruned)?; diff --git a/ethcore/src/client/test_client.rs b/ethcore/src/client/test_client.rs index 551b52437..22e61ab09 100644 --- a/ethcore/src/client/test_client.rs +++ b/ethcore/src/client/test_client.rs @@ -379,6 +379,10 @@ impl BlockChainClient for TestBlockChainClient { self.execution_result.read().clone().unwrap() } + fn estimate_gas(&self, _t: &SignedTransaction, _block: BlockId) -> Result { + Ok(21000.into()) + } + fn replay(&self, _id: TransactionId, _analytics: CallAnalytics) -> Result { self.execution_result.read().clone().unwrap() } diff --git a/ethcore/src/client/traits.rs b/ethcore/src/client/traits.rs index 571515198..8122aadef 100644 --- a/ethcore/src/client/traits.rs +++ b/ethcore/src/client/traits.rs @@ -184,6 +184,9 @@ pub trait BlockChainClient : Sync + Send { /// Makes a non-persistent transaction call. fn call(&self, t: &SignedTransaction, block: BlockId, analytics: CallAnalytics) -> Result; + /// Estimates how much gas will be necessary for a call. + fn estimate_gas(&self, t: &SignedTransaction, block: BlockId) -> Result; + /// Replays a given transaction for inspection. fn replay(&self, t: TransactionId, analytics: CallAnalytics) -> Result; diff --git a/ethcore/src/executive.rs b/ethcore/src/executive.rs index 57c63d7db..72427c668 100644 --- a/ethcore/src/executive.rs +++ b/ethcore/src/executive.rs @@ -45,7 +45,7 @@ pub fn contract_address(address: &Address, nonce: &U256) -> Address { } /// Transaction execution options. -#[derive(Default)] +#[derive(Default, Copy, Clone, PartialEq)] pub struct TransactOptions { /// Enable call tracing. pub tracing: bool, diff --git a/ethcore/src/miner/miner.rs b/ethcore/src/miner/miner.rs index 7a848b21d..59237ed6a 100644 --- a/ethcore/src/miner/miner.rs +++ b/ethcore/src/miner/miner.rs @@ -673,7 +673,7 @@ impl MinerService for Miner { } } - fn call(&self, chain: &MiningBlockChainClient, t: &SignedTransaction, analytics: CallAnalytics) -> Result { + fn call(&self, client: &MiningBlockChainClient, t: &SignedTransaction, analytics: CallAnalytics) -> Result { let sealing_work = self.sealing_work.lock(); match sealing_work.queue.peek_last_ref() { Some(work) => { @@ -681,7 +681,7 @@ impl MinerService for Miner { // TODO: merge this code with client.rs's fn call somwhow. let header = block.header(); - let last_hashes = Arc::new(chain.last_hashes()); + let last_hashes = Arc::new(client.last_hashes()); let env_info = EnvInfo { number: header.number(), author: *header.author(), @@ -706,16 +706,14 @@ impl MinerService for Miner { state.add_balance(&sender, &(needed_balance - balance), CleanupMode::NoEmpty); } let options = TransactOptions { tracing: analytics.transaction_tracing, vm_tracing: analytics.vm_tracing, check_nonce: false }; - let mut ret = Executive::new(&mut state, &env_info, &*self.engine, chain.vm_factory()).transact(t, options)?; + let mut ret = Executive::new(&mut state, &env_info, &*self.engine, client.vm_factory()).transact(t, options)?; // TODO gav move this into Executive. ret.state_diff = original_state.map(|original| state.diff_from(original)); Ok(ret) }, - None => { - chain.call(t, BlockId::Latest, analytics) - } + None => client.call(t, BlockId::Latest, analytics) } } diff --git a/ethcore/src/miner/price_info.rs b/ethcore/src/miner/price_info.rs index 897440ebe..9cd97e287 100644 --- a/ethcore/src/miner/price_info.rs +++ b/ethcore/src/miner/price_info.rs @@ -82,7 +82,7 @@ impl PriceInfo { } } -#[test] +#[test] #[ignore] fn should_get_price_info() { use std::sync::Arc; use std::time::Duration; diff --git a/ethcore/src/types/trace_types/trace.rs b/ethcore/src/types/trace_types/trace.rs index 2636caa52..619e1bd9f 100644 --- a/ethcore/src/types/trace_types/trace.rs +++ b/ethcore/src/types/trace_types/trace.rs @@ -391,6 +391,14 @@ impl Res { Res::Call(_) | Res::FailedCall(_) | Res::FailedCreate(_) | Res::None => Default::default(), } } + + /// Did this call fail? + pub fn succeeded(&self) -> bool { + match *self { + Res::Call(_) | Res::Create(_) => true, + _ => false, + } + } } #[derive(Debug, Clone, PartialEq)] @@ -561,4 +569,3 @@ impl Decodable for VMTrace { Ok(res) } } - diff --git a/ethcore/src/types/transaction.rs b/ethcore/src/types/transaction.rs index 4bd34da18..8dd7391bb 100644 --- a/ethcore/src/types/transaction.rs +++ b/ethcore/src/types/transaction.rs @@ -16,7 +16,7 @@ //! Transaction data structure. -use std::ops::Deref; +use std::ops::{Deref, DerefMut}; use std::cell::*; use rlp::*; use util::sha3::Hashable; @@ -239,6 +239,12 @@ impl Deref for SignedTransaction { } } +impl DerefMut for SignedTransaction { + fn deref_mut(&mut self) -> &mut Self::Target { + &mut self.unsigned + } +} + impl Decodable for SignedTransaction { fn decode(decoder: &D) -> Result where D: Decoder { let d = decoder.as_rlp(); diff --git a/js/src/abi/spec/event/event.js b/js/src/abi/spec/event/event.js index a17de1e64..025f2c316 100644 --- a/js/src/abi/spec/event/event.js +++ b/js/src/abi/spec/event/event.js @@ -23,12 +23,12 @@ import { eventSignature } from '../../util/signature'; export default class Event { constructor (abi) { - this._name = abi.name; this._inputs = EventParam.toEventParams(abi.inputs || []); this._anonymous = !!abi.anonymous; - const { id, signature } = eventSignature(this._name, this.inputParamTypes()); + const { id, name, signature } = eventSignature(abi.name, this.inputParamTypes()); this._id = id; + this._name = name; this._signature = signature; } diff --git a/js/src/abi/spec/function.js b/js/src/abi/spec/function.js index 68a6ca342..04e059c47 100644 --- a/js/src/abi/spec/function.js +++ b/js/src/abi/spec/function.js @@ -22,14 +22,14 @@ import { methodSignature } from '../util/signature'; export default class Func { constructor (abi) { this._abi = abi; - this._name = abi.name; this._constant = !!abi.constant; this._payable = abi.payable; this._inputs = Param.toParams(abi.inputs || []); this._outputs = Param.toParams(abi.outputs || []); - const { id, signature } = methodSignature(this._name, this.inputParamTypes()); + const { id, name, signature } = methodSignature(abi.name, this.inputParamTypes()); this._id = id; + this._name = name; this._signature = signature; } diff --git a/js/src/abi/spec/function.spec.js b/js/src/abi/spec/function.spec.js index 6ad755d70..af43958c9 100644 --- a/js/src/abi/spec/function.spec.js +++ b/js/src/abi/spec/function.spec.js @@ -35,6 +35,18 @@ describe('abi/spec/Function', () => { }); describe('constructor', () => { + it('returns signature correctly if name already contains it', () => { + const func = new Func({ + name: 'test(bool,string)', + inputs: inputsArr, + outputs: outputsArr + }); + + expect(func.name).to.equal('test'); + expect(func.id).to.equal('test(bool,string)'); + expect(func.signature).to.equal('02356205'); + }); + it('stores the parameters as received', () => { expect(func.name).to.equal('test'); expect(func.constant).to.be.false; diff --git a/js/src/abi/util/signature.js b/js/src/abi/util/signature.js index f192e576b..ad2b7ca5b 100644 --- a/js/src/abi/util/signature.js +++ b/js/src/abi/util/signature.js @@ -17,15 +17,31 @@ import { keccak_256 } from 'js-sha3'; // eslint-disable-line camelcase import { fromParamType } from '../spec/paramType/format'; -export function eventSignature (name, params) { +export function eventSignature (eventName, params) { + const { strName, name } = parseName(eventName); const types = (params || []).map(fromParamType).join(','); - const id = `${name || ''}(${types})`; + const id = `${strName}(${types})`; - return { id, signature: keccak_256(id) }; + return { id, name, signature: keccak_256(id) }; } -export function methodSignature (name, params) { - const { id, signature } = eventSignature(name, params); +export function methodSignature (methodName, params) { + const { id, name, signature } = eventSignature(methodName, params); - return { id, signature: signature.substr(0, 8) }; + return { id, name, signature: signature.substr(0, 8) }; +} + +function parseName (name) { + const strName = `${name || ''}`; + const idx = strName.indexOf('('); + + if (idx === -1) { + return { strName, name }; + } + + const trimmedName = strName.slice(0, idx); + return { + strName: trimmedName, + name: trimmedName + }; } diff --git a/js/src/abi/util/signature.spec.js b/js/src/abi/util/signature.spec.js index 144c1c7aa..dfa81333f 100644 --- a/js/src/abi/util/signature.spec.js +++ b/js/src/abi/util/signature.spec.js @@ -19,50 +19,93 @@ import { eventSignature, methodSignature } from './signature'; describe('abi/util/signature', () => { describe('eventSignature', () => { it('encodes signature baz() correctly', () => { - expect(eventSignature('baz', [])) - .to.deep.equal({ id: 'baz()', signature: 'a7916fac4f538170f7cd12c148552e2cba9fcd72329a2dd5b07a6fa906488ddf' }); + expect(eventSignature('baz', [])).to.deep.equal({ + id: 'baz()', + name: 'baz', + signature: 'a7916fac4f538170f7cd12c148552e2cba9fcd72329a2dd5b07a6fa906488ddf' + }); }); it('encodes signature baz(uint32) correctly', () => { - expect(eventSignature('baz', [{ type: 'uint', length: 32 }])) - .to.deep.equal({ id: 'baz(uint32)', signature: '7d68785e8fc871be024b75964bd86d093511d4bc2dc7cf7bea32c48a0efaecb1' }); + expect(eventSignature('baz', [{ type: 'uint', length: 32 }])).to.deep.equal({ + id: 'baz(uint32)', + name: 'baz', + signature: '7d68785e8fc871be024b75964bd86d093511d4bc2dc7cf7bea32c48a0efaecb1' + }); }); it('encodes signature baz(uint32, bool) correctly', () => { - expect(eventSignature('baz', [{ type: 'uint', length: 32 }, { type: 'bool' }])) - .to.deep.equal({ id: 'baz(uint32,bool)', signature: 'cdcd77c0992ec5bbfc459984220f8c45084cc24d9b6efed1fae540db8de801d2' }); + expect(eventSignature('baz', [{ type: 'uint', length: 32 }, { type: 'bool' }])).to.deep.equal({ + id: 'baz(uint32,bool)', + name: 'baz', + signature: 'cdcd77c0992ec5bbfc459984220f8c45084cc24d9b6efed1fae540db8de801d2' + }); }); it('encodes no-name signature correctly as ()', () => { - expect(eventSignature(undefined, [])) - .to.deep.equal({ id: '()', signature: '861731d50c3880a2ca1994d5ec287b94b2f4bd832a67d3e41c08177bdd5674fe' }); + expect(eventSignature(undefined, [])).to.deep.equal({ + id: '()', + name: undefined, + signature: '861731d50c3880a2ca1994d5ec287b94b2f4bd832a67d3e41c08177bdd5674fe' + }); }); it('encodes no-params signature correctly as ()', () => { - expect(eventSignature(undefined, undefined)) - .to.deep.equal({ id: '()', signature: '861731d50c3880a2ca1994d5ec287b94b2f4bd832a67d3e41c08177bdd5674fe' }); + expect(eventSignature(undefined, undefined)).to.deep.equal({ + id: '()', + name: undefined, + signature: '861731d50c3880a2ca1994d5ec287b94b2f4bd832a67d3e41c08177bdd5674fe' + }); }); }); describe('methodSignature', () => { it('encodes signature baz() correctly', () => { - expect(methodSignature('baz', [])).to.deep.equal({ id: 'baz()', signature: 'a7916fac' }); + expect(methodSignature('baz', [])).to.deep.equal({ + id: 'baz()', + name: 'baz', + signature: 'a7916fac' + }); }); it('encodes signature baz(uint32) correctly', () => { - expect(methodSignature('baz', [{ type: 'uint', length: 32 }])).to.deep.equal({ id: 'baz(uint32)', signature: '7d68785e' }); + expect(methodSignature('baz', [{ type: 'uint', length: 32 }])).to.deep.equal({ + id: 'baz(uint32)', + name: 'baz', + signature: '7d68785e' + }); }); it('encodes signature baz(uint32, bool) correctly', () => { - expect(methodSignature('baz', [{ type: 'uint', length: 32 }, { type: 'bool' }])).to.deep.equal({ id: 'baz(uint32,bool)', signature: 'cdcd77c0' }); + expect(methodSignature('baz', [{ type: 'uint', length: 32 }, { type: 'bool' }])).to.deep.equal({ + id: 'baz(uint32,bool)', + name: 'baz', + signature: 'cdcd77c0' + }); + }); + + it('encodes signature in name correctly', () => { + expect(methodSignature('baz(uint32,bool)', [{ type: 'uint', length: 32 }, { type: 'bool' }])).to.deep.equal({ + id: 'baz(uint32,bool)', + name: 'baz', + signature: 'cdcd77c0' + }); }); it('encodes no-name signature correctly as ()', () => { - expect(methodSignature(undefined, [])).to.deep.equal({ id: '()', signature: '861731d5' }); + expect(methodSignature(undefined, [])).to.deep.equal({ + id: '()', + name: undefined, + signature: '861731d5' + }); }); it('encodes no-params signature correctly as ()', () => { - expect(methodSignature(undefined, undefined)).to.deep.equal({ id: '()', signature: '861731d5' }); + expect(methodSignature(undefined, undefined)).to.deep.equal({ + id: '()', + name: undefined, + signature: '861731d5' + }); }); }); }); diff --git a/js/src/api/util/sha3.js b/js/src/api/util/sha3.js index 11ca6189a..f07f88068 100644 --- a/js/src/api/util/sha3.js +++ b/js/src/api/util/sha3.js @@ -17,9 +17,12 @@ import { keccak_256 } from 'js-sha3'; // eslint-disable-line import { hexToBytes } from './format'; +import { isHex } from './types'; export function sha3 (value, options) { - if (options && options.encoding === 'hex') { + const forceHex = options && options.encoding === 'hex'; + + if (forceHex || (!options && isHex(value))) { const bytes = hexToBytes(value); return sha3(bytes); } @@ -28,3 +31,5 @@ export function sha3 (value, options) { return `0x${hash}`; } + +sha3.text = (val) => sha3(val, { encoding: 'raw' }); diff --git a/js/src/api/util/sha3.spec.js b/js/src/api/util/sha3.spec.js index 3446f7def..2945ce51a 100644 --- a/js/src/api/util/sha3.spec.js +++ b/js/src/api/util/sha3.spec.js @@ -32,5 +32,14 @@ describe('api/util/sha3', () => { expect(sha3('01020304', { encoding: 'hex' })).to.equal('0xa6885b3731702da62e8e4a8f584ac46a7f6822f4e2ba50fba902f67b1588d23b'); expect(sha3(Uint8Array.from([1, 2, 3, 4]))).to.equal('0xa6885b3731702da62e8e4a8f584ac46a7f6822f4e2ba50fba902f67b1588d23b'); }); + + it('should interpret as bytes by default', () => { + expect(sha3('0x01020304')).to.equal('0xa6885b3731702da62e8e4a8f584ac46a7f6822f4e2ba50fba902f67b1588d23b'); + }); + + it('should force text if option is passed', () => { + expect(sha3('0x01020304', { encoding: 'raw' })).to.equal('0x16bff43de576d28857dcba65a56fc17c5e93c09bd6a709268eff8e62025ae869'); + expect(sha3.text('0x01020304')).to.equal('0x16bff43de576d28857dcba65a56fc17c5e93c09bd6a709268eff8e62025ae869'); + }); }); }); diff --git a/js/src/api/util/types.js b/js/src/api/util/types.js index 6fe442e93..96d7251d5 100644 --- a/js/src/api/util/types.js +++ b/js/src/api/util/types.js @@ -29,6 +29,10 @@ export function isFunction (test) { } export function isHex (_test) { + if (!isString(_test)) { + return false; + } + if (_test.substr(0, 2) === '0x') { return isHex(_test.slice(2)); } diff --git a/js/src/api/util/types.spec.js b/js/src/api/util/types.spec.js index df9bf2f1f..1436eb160 100644 --- a/js/src/api/util/types.spec.js +++ b/js/src/api/util/types.spec.js @@ -66,6 +66,12 @@ describe('api/util/types', () => { it('correctly identifies non-hex values', () => { expect(isHex('123j')).to.be.false; }); + + it('correctly indentifies non-string values', () => { + expect(isHex(false)).to.be.false; + expect(isHex()).to.be.false; + expect(isHex([1, 2, 3])).to.be.false; + }); }); describe('isInstanceOf', () => { diff --git a/js/src/contracts/registry.js b/js/src/contracts/registry.js index 04c562f50..ffb14c626 100644 --- a/js/src/contracts/registry.js +++ b/js/src/contracts/registry.js @@ -91,7 +91,7 @@ export default class Registry { lookupAddress (_name) { const name = _name.toLowerCase(); - const sha3 = this._api.util.sha3(name); + const sha3 = this._api.util.sha3.text(name); return this.getInstance().then((instance) => { return instance.getAddress.call({}, [sha3, 'A']); diff --git a/js/src/dapps/registry/Lookup/actions.js b/js/src/dapps/registry/Lookup/actions.js index 1e8ed5898..3a8ef515e 100644 --- a/js/src/dapps/registry/Lookup/actions.js +++ b/js/src/dapps/registry/Lookup/actions.js @@ -39,7 +39,7 @@ export const lookup = (name, key) => (dispatch, getState) => { name = name.toLowerCase(); dispatch(lookupStart(name, key)); - getAddress.call({}, [ sha3(name), key ]) + getAddress.call({}, [ sha3.text(name), key ]) .then((address) => dispatch(success('lookup', address))) .catch((err) => { console.error(`could not lookup ${key} for ${name}`); diff --git a/js/src/dapps/registry/Names/actions.js b/js/src/dapps/registry/Names/actions.js index 2396278cb..12600ff80 100644 --- a/js/src/dapps/registry/Names/actions.js +++ b/js/src/dapps/registry/Names/actions.js @@ -62,7 +62,7 @@ export const reserve = (name) => (dispatch, getState) => { value: fee }; const values = [ - sha3(name) + sha3.text(name) ]; return postTx(api, reserve, options, values); @@ -116,7 +116,7 @@ export const drop = (name) => (dispatch, getState) => { }; const values = [ - sha3(name) + sha3.text(name) ]; return postTx(api, drop, options, values); diff --git a/js/src/dapps/registry/Records/actions.js b/js/src/dapps/registry/Records/actions.js index f85304d5f..8318c9dcc 100644 --- a/js/src/dapps/registry/Records/actions.js +++ b/js/src/dapps/registry/Records/actions.js @@ -54,7 +54,7 @@ export const update = (name, key, value) => (dispatch, getState) => { }; const values = [ - sha3(name), + sha3.text(name), key, value ]; diff --git a/js/src/dapps/registry/util/registry.js b/js/src/dapps/registry/util/registry.js index 371b29aec..ed3039b4d 100644 --- a/js/src/dapps/registry/util/registry.js +++ b/js/src/dapps/registry/util/registry.js @@ -17,7 +17,7 @@ export const getOwner = (contract, name) => { const { address, api } = contract; - const key = api.util.sha3(name) + '0000000000000000000000000000000000000000000000000000000000000001'; + const key = api.util.sha3.text(name) + '0000000000000000000000000000000000000000000000000000000000000001'; const position = api.util.sha3(key, { encoding: 'hex' }); return api diff --git a/js/src/modals/ExecuteContract/executeContract.test.js b/js/src/modals/ExecuteContract/executeContract.test.js index 8d9e4ccca..ac1138a17 100644 --- a/js/src/modals/ExecuteContract/executeContract.test.js +++ b/js/src/modals/ExecuteContract/executeContract.test.js @@ -68,13 +68,13 @@ const STORE = { }; function createApi (result = true) { + const sha3 = sinon.stub().resolves('0x0000000000000000000000000000000000000000'); + sha3.text = sha3; return { parity: { registryAddress: sinon.stub().resolves('0x0000000000000000000000000000000000000000') }, - util: { - sha3: sinon.stub().resolves('0x0000000000000000000000000000000000000000') - } + util: { sha3 } }; } diff --git a/js/src/modals/Verification/email-store.js b/js/src/modals/Verification/email-store.js index a12d1968d..5360ad611 100644 --- a/js/src/modals/Verification/email-store.js +++ b/js/src/modals/Verification/email-store.js @@ -59,7 +59,7 @@ export default class EmailVerificationStore extends VerificationStore { super(api, EmailVerificationABI, EMAIL_VERIFICATION, account, isTestnet); } - requestValues = () => [ sha3(this.email) ] + requestValues = () => [ sha3.text(this.email) ] @action setEmail = (email) => { this.email = email; diff --git a/js/src/modals/Verification/store.js b/js/src/modals/Verification/store.js index 9d6680231..06250fd76 100644 --- a/js/src/modals/Verification/store.js +++ b/js/src/modals/Verification/store.js @@ -120,7 +120,7 @@ export default class VerificationStore { const confirm = contract.functions.find((fn) => fn.name === 'confirm'); const options = { from: account }; - const values = [ sha3(code) ]; + const values = [ sha3.text(code) ]; this.code = code; this.isCodeValid = null; @@ -192,7 +192,7 @@ export default class VerificationStore { @action sendConfirmation = () => { const { api, account, contract, code } = this; - const token = sha3(code); + const token = sha3.text(code); const confirm = contract.functions.find((fn) => fn.name === 'confirm'); const options = { from: account }; diff --git a/js/src/ui/Form/AddressSelect/addressSelectStore.js b/js/src/ui/Form/AddressSelect/addressSelectStore.js index bdb7c1fb2..e04f8b55d 100644 --- a/js/src/ui/Form/AddressSelect/addressSelectStore.js +++ b/js/src/ui/Form/AddressSelect/addressSelectStore.js @@ -85,7 +85,7 @@ export default class AddressSelectStore { return emailVerification .instance .reverse - .call({}, [ sha3(email) ]) + .call({}, [ sha3.text(email) ]) .then((address) => { return { address, @@ -109,7 +109,7 @@ export default class AddressSelectStore { this.regLookups.push((name) => { return registryInstance .getAddress - .call({}, [ sha3(name), 'A' ]) + .call({}, [ sha3.text(name), 'A' ]) .then((address) => { return { address, diff --git a/js/src/views/Settings/Background/background.js b/js/src/views/Settings/Background/background.js index 48f3a49ec..ebf3c7a96 100644 --- a/js/src/views/Settings/Background/background.js +++ b/js/src/views/Settings/Background/background.js @@ -141,7 +141,7 @@ class Background extends Component { generateSeed () { const { api, muiTheme } = this.context; - return api.util.sha3(`${muiTheme.backgroundSeed}${Math.random()}${counter++}`); + return api.util.sha3.text(`${muiTheme.backgroundSeed}${Math.random()}${counter++}`); } } diff --git a/rpc/src/v1/impls/eth.rs b/rpc/src/v1/impls/eth.rs index a11edc84e..fd5f3d4f3 100644 --- a/rpc/src/v1/impls/eth.rs +++ b/rpc/src/v1/impls/eth.rs @@ -671,13 +671,8 @@ impl Eth for EthClient where let request = CallRequest::into(request); let signed = self.sign_call(request)?; - let result = match num.0 { - BlockNumber::Pending => take_weak!(self.miner).call(&*take_weak!(self.client), &signed, Default::default()), - num => take_weak!(self.client).call(&signed, num.into(), Default::default()), - }; - - result - .map(|res| (res.gas_used + res.refunded).into()) + take_weak!(self.client).estimate_gas(&signed, num.0.into()) + .map(Into::into) .map_err(errors::from_call_error) } diff --git a/rpc/src/v1/tests/mocked/eth.rs b/rpc/src/v1/tests/mocked/eth.rs index 2adc50fc7..5f4424313 100644 --- a/rpc/src/v1/tests/mocked/eth.rs +++ b/rpc/src/v1/tests/mocked/eth.rs @@ -691,7 +691,7 @@ fn rpc_eth_estimate_gas() { "latest"], "id": 1 }"#; - let response = r#"{"jsonrpc":"2.0","result":"0xff35","id":1}"#; + let response = r#"{"jsonrpc":"2.0","result":"0x5208","id":1}"#; assert_eq!(tester.io.handle_request_sync(request), Some(response.to_owned())); } @@ -725,7 +725,7 @@ fn rpc_eth_estimate_gas_default_block() { }], "id": 1 }"#; - let response = r#"{"jsonrpc":"2.0","result":"0xff35","id":1}"#; + let response = r#"{"jsonrpc":"2.0","result":"0x5208","id":1}"#; assert_eq!(tester.io.handle_request_sync(request), Some(response.to_owned())); }