Compare commits

...

7 Commits

Author SHA1 Message Date
Arkadiy Paronyan
1b6588cb27 [beta] Backports (#6891)
* v1.8.2

* Refactor static context check in CREATE. (#6886)

* Refactor static context check in CREATE.

* Fix wasm.

* Fix serialization of non-localized transactions (#6868)

* Fix serialization of non-localized transactions.

* Return proper SignedTransactions representation.

* Allow force sealing and reseal=0 for non-dev chains. (#6878)
2017-10-25 13:13:11 +02:00
Afri Schoedon
0e4a06d078 Add ECIP1017 to Morden config (#6810) (#6845)
* Add ECIP1017 setting to Morden config

* Convert spaces to tabs

* Update Morden bootnodes to match Geth
2017-10-20 20:42:51 +02:00
Arkadiy Paronyan
d470773fec Ethstore optimizations (#6827) (#6844) 2017-10-20 20:22:01 +02:00
Arkadiy Paronyan
8f0eb3e192 v1.8.1 (#6843) 2017-10-20 16:40:59 +02:00
Arkadiy Paronyan
48c7e4ab8c Backport #6815 and #6829 (#6837)
* Tweaked snapshot sync threshold

* Change keypath derivation logic (#6815)

While the standard defined by Trezor as the default derivation path here
https://blog.trezor.io/trezor-integration-with-myetherwallet-3e217a652e08
says that it should be `m/44'/60'/0`, in practice they don't have an
implementation of a wallet for Ethereum themselves and refer customers
to MEW.

MEW has a custom implementation of the path derivation logic that allows them to
generate multiple addresses by essentially adding `/0`, `/1` etc to the path.

In my initial implementation of Trezor I didn't take this into
consideration unfortunately and just used the keypath that Trezor
themselves recommended. However, given that it's seemingly standard
practice to append `/0` for a "sub-address" (and this is what we've done
for Ledger as well) it seems like a mistake on my part to not take that
into consideration.

Unfortunately, anyone who has used their Trezor device with Parity
previously would now see a different address when they connect the
Trezor device the next time. The only way they would have to access the
old address is to use an old version, or by going through MEW and
selecting the Ledger keypath.

Also see #6811
2017-10-20 12:51:02 +02:00
GitLab Build Bot
8362bc7f2d [ci skip] js-precompiled 20171019-155727 2017-10-19 16:02:16 +00:00
Jaco Greeff
284fc65c70 Refresh cached tokens based on registry info & random balances (#6818) (#6824)
* Refresh cached tokens based on registry info & random balances

* Don't display errored token images
2017-10-19 17:49:25 +02:00
33 changed files with 254 additions and 168 deletions

54
Cargo.lock generated
View File

@@ -5,7 +5,7 @@ dependencies = [
"byteorder 1.1.0 (registry+https://github.com/rust-lang/crates.io-index)",
"ethcore-bigint 0.1.3",
"ethcore-logger 1.8.0",
"ethcore-util 1.8.0",
"ethcore-util 1.8.2",
"log 0.3.8 (registry+https://github.com/rust-lang/crates.io-index)",
"parity-wasm 0.14.5 (registry+https://github.com/rust-lang/crates.io-index)",
"vm 0.1.0",
@@ -374,7 +374,7 @@ dependencies = [
"bloomable 0.1.0",
"ethcore-bigint 0.1.3",
"ethcore-bytes 0.1.0",
"ethcore-util 1.8.0",
"ethcore-util 1.8.2",
"ethjson 0.1.0",
"hash 0.1.0",
"heapsize 0.4.1 (registry+https://github.com/rust-lang/crates.io-index)",
@@ -588,7 +588,7 @@ dependencies = [
"ethcore-ipc-nano 1.8.0",
"ethcore-logger 1.8.0",
"ethcore-stratum 1.8.0",
"ethcore-util 1.8.0",
"ethcore-util 1.8.2",
"ethjson 0.1.0",
"ethkey 0.2.0",
"ethstore 0.1.0",
@@ -682,7 +682,7 @@ version = "1.8.0"
dependencies = [
"ethcore-bigint 0.1.3",
"ethcore-devtools 1.8.0",
"ethcore-util 1.8.0",
"ethcore-util 1.8.2",
"nanomsg 0.5.1 (git+https://github.com/paritytech/nanomsg.rs.git?branch=parity-1.7)",
"semver 0.6.0 (registry+https://github.com/rust-lang/crates.io-index)",
]
@@ -732,7 +732,7 @@ dependencies = [
"ethcore-ipc 1.8.0",
"ethcore-ipc-codegen 1.8.0",
"ethcore-ipc-nano 1.8.0",
"ethcore-util 1.8.0",
"ethcore-util 1.8.2",
"log 0.3.8 (registry+https://github.com/rust-lang/crates.io-index)",
"nanomsg 0.5.1 (git+https://github.com/paritytech/nanomsg.rs.git?branch=parity-1.7)",
"semver 0.6.0 (registry+https://github.com/rust-lang/crates.io-index)",
@@ -751,7 +751,7 @@ dependencies = [
"ethcore-ipc 1.8.0",
"ethcore-ipc-codegen 1.8.0",
"ethcore-network 1.8.0",
"ethcore-util 1.8.0",
"ethcore-util 1.8.2",
"evm 0.1.0",
"futures 0.1.16 (registry+https://github.com/rust-lang/crates.io-index)",
"hash 0.1.0",
@@ -801,7 +801,7 @@ dependencies = [
"ethcore-devtools 1.8.0",
"ethcore-io 1.8.0",
"ethcore-logger 1.8.0",
"ethcore-util 1.8.0",
"ethcore-util 1.8.2",
"ethcrypto 0.1.0",
"ethkey 0.2.0",
"hash 0.1.0",
@@ -836,7 +836,7 @@ dependencies = [
"ethcore-ipc-codegen 1.8.0",
"ethcore-ipc-nano 1.8.0",
"ethcore-logger 1.8.0",
"ethcore-util 1.8.0",
"ethcore-util 1.8.2",
"ethcrypto 0.1.0",
"ethkey 0.2.0",
"futures 0.1.16 (registry+https://github.com/rust-lang/crates.io-index)",
@@ -871,7 +871,7 @@ dependencies = [
"ethcore-ipc-codegen 1.8.0",
"ethcore-ipc-nano 1.8.0",
"ethcore-logger 1.8.0",
"ethcore-util 1.8.0",
"ethcore-util 1.8.2",
"hash 0.1.0",
"jsonrpc-core 8.0.0 (git+https://github.com/paritytech/jsonrpc.git?branch=parity-1.8)",
"jsonrpc-macros 8.0.0 (git+https://github.com/paritytech/jsonrpc.git?branch=parity-1.8)",
@@ -884,7 +884,7 @@ dependencies = [
[[package]]
name = "ethcore-util"
version = "1.8.0"
version = "1.8.2"
dependencies = [
"clippy 0.0.103 (registry+https://github.com/rust-lang/crates.io-index)",
"elastic-array 0.9.0 (registry+https://github.com/rust-lang/crates.io-index)",
@@ -1018,7 +1018,7 @@ dependencies = [
"ethcore-ipc-nano 1.8.0",
"ethcore-light 1.8.0",
"ethcore-network 1.8.0",
"ethcore-util 1.8.0",
"ethcore-util 1.8.2",
"ethkey 0.2.0",
"hash 0.1.0",
"heapsize 0.4.1 (registry+https://github.com/rust-lang/crates.io-index)",
@@ -1044,7 +1044,7 @@ dependencies = [
"common-types 0.1.0",
"ethcore-bigint 0.1.3",
"ethcore-logger 1.8.0",
"ethcore-util 1.8.0",
"ethcore-util 1.8.2",
"ethjson 0.1.0",
"evmjit 1.8.0",
"hash 0.1.0",
@@ -1066,7 +1066,7 @@ dependencies = [
"ethcore 1.8.0",
"ethcore-bigint 0.1.3",
"ethcore-bytes 0.1.0",
"ethcore-util 1.8.0",
"ethcore-util 1.8.2",
"ethjson 0.1.0",
"evm 0.1.0",
"panic_hook 0.1.0",
@@ -1364,7 +1364,7 @@ dependencies = [
"ethcore-bigint 0.1.3",
"ethcore-ipc 1.8.0",
"ethcore-ipc-codegen 1.8.0",
"ethcore-util 1.8.0",
"ethcore-util 1.8.2",
"semver 0.6.0 (registry+https://github.com/rust-lang/crates.io-index)",
]
@@ -1857,7 +1857,7 @@ dependencies = [
"ethcore-bytes 0.1.0",
"ethcore-io 1.8.0",
"ethcore-network 1.8.0",
"ethcore-util 1.8.0",
"ethcore-util 1.8.2",
"futures 0.1.16 (registry+https://github.com/rust-lang/crates.io-index)",
"kvdb 0.1.0",
"log 0.3.8 (registry+https://github.com/rust-lang/crates.io-index)",
@@ -2056,7 +2056,7 @@ dependencies = [
[[package]]
name = "parity"
version = "1.8.0"
version = "1.8.2"
dependencies = [
"ansi_term 0.9.0 (registry+https://github.com/rust-lang/crates.io-index)",
"app_dirs 1.1.1 (registry+https://github.com/rust-lang/crates.io-index)",
@@ -2080,7 +2080,7 @@ dependencies = [
"ethcore-network 1.8.0",
"ethcore-secretstore 1.0.0",
"ethcore-stratum 1.8.0",
"ethcore-util 1.8.0",
"ethcore-util 1.8.2",
"ethkey 0.2.0",
"ethsync 1.8.0",
"fdlimit 0.1.1 (registry+https://github.com/rust-lang/crates.io-index)",
@@ -2136,7 +2136,7 @@ dependencies = [
"ethcore-bigint 0.1.3",
"ethcore-bytes 0.1.0",
"ethcore-devtools 1.8.0",
"ethcore-util 1.8.0",
"ethcore-util 1.8.2",
"fetch 0.1.0",
"futures 0.1.16 (registry+https://github.com/rust-lang/crates.io-index)",
"futures-cpupool 0.1.6 (registry+https://github.com/rust-lang/crates.io-index)",
@@ -2198,7 +2198,7 @@ dependencies = [
"ethabi 2.0.1 (registry+https://github.com/rust-lang/crates.io-index)",
"ethcore-bigint 0.1.3",
"ethcore-bytes 0.1.0",
"ethcore-util 1.8.0",
"ethcore-util 1.8.2",
"fetch 0.1.0",
"futures 0.1.16 (registry+https://github.com/rust-lang/crates.io-index)",
"hash 0.1.0",
@@ -2220,7 +2220,7 @@ dependencies = [
"ethcore 1.8.0",
"ethcore-bigint 0.1.3",
"ethcore-bytes 0.1.0",
"ethcore-util 1.8.0",
"ethcore-util 1.8.2",
"jsonrpc-core 8.0.0 (git+https://github.com/paritytech/jsonrpc.git?branch=parity-1.8)",
"jsonrpc-http-server 8.0.0 (git+https://github.com/paritytech/jsonrpc.git?branch=parity-1.8)",
"multihash 0.6.0 (registry+https://github.com/rust-lang/crates.io-index)",
@@ -2234,7 +2234,7 @@ version = "0.1.0"
dependencies = [
"ethcore 1.8.0",
"ethcore-io 1.8.0",
"ethcore-util 1.8.0",
"ethcore-util 1.8.2",
"ethkey 0.2.0",
"kvdb 0.1.0",
"log 0.3.8 (registry+https://github.com/rust-lang/crates.io-index)",
@@ -2249,7 +2249,7 @@ name = "parity-machine"
version = "0.1.0"
dependencies = [
"ethcore-bigint 0.1.3",
"ethcore-util 1.8.0",
"ethcore-util 1.8.2",
]
[[package]]
@@ -2277,7 +2277,7 @@ dependencies = [
"ethcore-light 1.8.0",
"ethcore-logger 1.8.0",
"ethcore-network 1.8.0",
"ethcore-util 1.8.0",
"ethcore-util 1.8.2",
"ethcrypto 0.1.0",
"ethjson 0.1.0",
"ethkey 0.2.0",
@@ -2372,7 +2372,7 @@ dependencies = [
[[package]]
name = "parity-ui-precompiled"
version = "1.4.0"
source = "git+https://github.com/paritytech/js-precompiled.git?branch=beta#05dcad20e3797f21c2bda800983aa94a8b07164c"
source = "git+https://github.com/paritytech/js-precompiled.git?branch=beta#3fc3409a902f5c8dc1360592b228b05755f042a9"
dependencies = [
"parity-dapps-glue 1.8.0 (registry+https://github.com/rust-lang/crates.io-index)",
]
@@ -2387,7 +2387,7 @@ dependencies = [
"ethcore-bytes 0.1.0",
"ethcore-ipc 1.8.0",
"ethcore-ipc-codegen 1.8.0",
"ethcore-util 1.8.0",
"ethcore-util 1.8.2",
"ethsync 1.8.0",
"futures 0.1.16 (registry+https://github.com/rust-lang/crates.io-index)",
"ipc-common-types 1.8.0",
@@ -2849,7 +2849,7 @@ name = "rpc-cli"
version = "1.4.0"
dependencies = [
"bigint 4.2.0 (registry+https://github.com/rust-lang/crates.io-index)",
"ethcore-util 1.8.0",
"ethcore-util 1.8.2",
"futures 0.1.16 (registry+https://github.com/rust-lang/crates.io-index)",
"parity-rpc 1.8.0",
"parity-rpc-client 1.4.0",
@@ -3565,7 +3565,7 @@ dependencies = [
"common-types 0.1.0",
"ethcore-bigint 0.1.3",
"ethcore-bytes 0.1.0",
"ethcore-util 1.8.0",
"ethcore-util 1.8.2",
"ethjson 0.1.0",
"evmjit 1.8.0",
"hash 0.1.0",

View File

@@ -1,7 +1,7 @@
[package]
description = "Parity Ethereum client"
name = "parity"
version = "1.8.0"
version = "1.8.2"
license = "GPL-3.0"
authors = ["Parity Technologies <admin@parity.io>"]
build = "build.rs"

View File

@@ -322,20 +322,24 @@ impl<Cost: CostType> Interpreter<Cost> {
let init_off = stack.pop_back();
let init_size = stack.pop_back();
let address_scheme = if instruction == instructions::CREATE { CreateContractAddress::FromSenderAndNonce } else { CreateContractAddress::FromSenderAndCodeHash };
let create_gas = provided.expect("`provided` comes through Self::exec from `Gasometer::get_gas_cost_mem`; `gas_gas_mem_cost` guarantees `Some` when instruction is `CALL`/`CALLCODE`/`DELEGATECALL`/`CREATE`; this is `CREATE`; qed");
let contract_code = self.mem.read_slice(init_off, init_size);
let can_create = ext.balance(&params.address)? >= endowment && ext.depth() < ext.schedule().max_depth;
if ext.is_static() {
return Err(vm::Error::MutableCallInStaticContext);
}
// clear return data buffer before creating new call frame.
self.return_data = ReturnData::empty();
let can_create = ext.balance(&params.address)? >= endowment && ext.depth() < ext.schedule().max_depth;
if !can_create {
stack.push(U256::zero());
return Ok(InstructionResult::UnusedGas(create_gas));
}
let contract_code = self.mem.read_slice(init_off, init_size);
let address_scheme = if instruction == instructions::CREATE { CreateContractAddress::FromSenderAndNonce } else { CreateContractAddress::FromSenderAndCodeHash };
let create_result = ext.create(&create_gas.as_u256(), &endowment, contract_code, address_scheme);
return match create_result {
ContractCreateResult::Created(address, gas_left) => {
@@ -351,9 +355,6 @@ impl<Cost: CostType> Interpreter<Cost> {
stack.push(U256::zero());
Ok(InstructionResult::Ok)
},
ContractCreateResult::FailedInStaticCall => {
Err(vm::Error::MutableCallInStaticContext)
},
};
},
instructions::CALL | instructions::CALLCODE | instructions::DELEGATECALL | instructions::STATICCALL => {

View File

@@ -724,7 +724,6 @@ fn test_jumps(factory: super::Factory) {
assert_eq!(gas_left, U256::from(54_117));
}
evm_test!{test_calls: test_calls_jit, test_calls_int}
fn test_calls(factory: super::Factory) {
let code = "600054602d57600160005560006000600060006050610998610100f160006000600060006050610998610100f25b".from_hex().unwrap();
@@ -769,6 +768,27 @@ fn test_calls(factory: super::Factory) {
assert_eq!(ext.calls.len(), 2);
}
evm_test!{test_create_in_staticcall: test_create_in_staticcall_jit, test_create_in_staticcall_int}
fn test_create_in_staticcall(factory: super::Factory) {
let code = "600060006064f000".from_hex().unwrap();
let address = Address::from(0x155);
let mut params = ActionParams::default();
params.gas = U256::from(100_000);
params.code = Some(Arc::new(code));
params.address = address.clone();
let mut ext = FakeExt::new_byzantium();
ext.is_static = true;
let err = {
let mut vm = factory.create(params.gas);
test_finalize(vm.exec(params, &mut ext)).unwrap_err()
};
assert_eq!(err, vm::Error::MutableCallInStaticContext);
assert_eq!(ext.calls.len(), 0);
}
fn assert_set_contains<T : Debug + Eq + PartialEq + Hash>(set: &HashSet<T>, val: &T) {
let contains = set.contains(val);
if !contains {

View File

@@ -13,6 +13,7 @@
"eip160Transition": 1915000,
"ecip1010PauseTransition": 1915000,
"ecip1010ContinueTransition": 3415000,
"ecip1017EraRounds": 2000000,
"eip161abcTransition": "0x7fffffffffffffff",
"eip161dTransition": "0x7fffffffffffffff"
@@ -49,11 +50,13 @@
"gasLimit": "0x2fefd8"
},
"nodes": [
"enode://e731347db0521f3476e6bbbb83375dcd7133a1601425ebd15fd10f3835fd4c304fba6282087ca5a0deeafadf0aa0d4fd56c3323331901c1f38bd181c283e3e35@128.199.55.137:30303",
"enode://ceb5c0f85eb994dbe9693bf46d99b03f6b838d17cc74e68d5eb003171ff39e5f120b17f965b267c319303f94d80b9d994b77062fb1486d76ce95d9f3d8fe1cb4@46.101.122.141:30303",
"enode://fb28713820e718066a2f5df6250ae9d07cff22f672dbf26be6c75d088f821a9ad230138ba492c533a80407d054b1436ef18e951bb65e6901553516c8dffe8ff0@104.155.176.151:30304",
"enode://afdc6076b9bf3e7d3d01442d6841071e84c76c73a7016cb4f35c0437df219db38565766234448f1592a07ba5295a867f0ce87b359bf50311ed0b830a2361392d@104.154.136.117:30403",
"enode://21101a9597b79e933e17bc94ef3506fe99a137808907aa8fefa67eea4b789792ad11fb391f38b00087f8800a2d3dff011572b62a31232133dd1591ac2d1502c8@104.198.71.200:30403"
"enode://21101a9597b79e933e17bc94ef3506fe99a137808907aa8fefa67eea4b789792ad11fb391f38b00087f8800a2d3dff011572b62a31232133dd1591ac2d1502c8@104.198.71.200:30403",
"enode://fd008499e9c4662f384b3cff23438879d31ced24e2d19504c6389bc6da6c882f9c2f8dbed972f7058d7650337f54e4ba17bb49c7d11882dd1731d26a6e62e3cb@35.187.57.94:30304",
"enode://30a1fd71f28aa6f66fe662af9ecc75f0a6980f06b71598f2b19d3dda04223fc0e53b47e40c9171d5014e9f5b59d9954de125782da592f5d95ea39066e2591d5d@104.237.131.102:30304",
"enode://7909d51011d8a153351169f21d3a7bbedb3be1e17d38c1f2fad06504dd5aa07a00f00845835d535fe702bf379c4d7209a51f4d1b723e0ca8b8732bd21fba3b30@139.162.133.42:30303",
"enode://a088dfb2f5305be9232e8071c5535f13718a4017e247a0b35074b807d43d99e022880c27302cdb5b1e98ad34c083dbbb483f2b17bdc66149bad037154d6ace96@139.162.127.72:30303"
],
"accounts": {
"0000000000000000000000000000000000000001": { "balance": "1", "nonce": "1048576", "builtin": { "name": "ecrecover", "pricing": { "linear": { "base": 3000, "word": 0 } } } },

View File

@@ -269,7 +269,7 @@ impl AccountProvider {
/// Checks whether an account with a given address is present.
pub fn has_account(&self, address: Address) -> Result<bool, Error> {
Ok(self.accounts()?.iter().any(|&a| a == address))
Ok(self.sstore.account_ref(&address).is_ok() && !self.blacklisted_accounts.contains(&address))
}
/// Returns addresses of all accounts.

View File

@@ -240,7 +240,6 @@ impl<'a, T: 'a, V: 'a, B: 'a> Ext for Externalities<'a, T, V, B>
Ok(FinalizationResult{ gas_left, apply_state: false, return_data }) => {
ContractCreateResult::Reverted(gas_left, return_data)
},
Err(vm::Error::MutableCallInStaticContext) => ContractCreateResult::FailedInStaticCall,
_ => ContractCreateResult::Failed,
}
}

View File

@@ -647,10 +647,6 @@ impl Miner {
condition: Option<TransactionCondition>,
transaction_queue: &mut BanningTransactionQueue,
) -> Vec<Result<TransactionImportResult, Error>> {
let accounts = self.accounts.as_ref()
.and_then(|provider| provider.accounts().ok())
.map(|accounts| accounts.into_iter().collect::<HashSet<_>>());
let best_block_header = client.best_block_header().decode();
let insertion_time = client.chain_info().best_block_number;
@@ -669,8 +665,8 @@ impl Miner {
Err(e)
},
Ok(transaction) => {
let origin = accounts.as_ref().and_then(|accounts| {
match accounts.contains(&transaction.sender()) {
let origin = self.accounts.as_ref().and_then(|accounts| {
match accounts.has_account(transaction.sender()).unwrap_or(false) {
true => Some(TransactionOrigin::Local),
false => None,
}

View File

@@ -469,6 +469,11 @@ impl SignedTransaction {
pub fn is_unsigned(&self) -> bool {
self.transaction.is_unsigned()
}
/// Deconstructs this transaction back into `UnverifiedTransaction`
pub fn deconstruct(self) -> (UnverifiedTransaction, Address, Option<Public>) {
(self.transaction, self.sender, self.public)
}
}
/// Signed Transaction that is a part of canon blockchain.

View File

@@ -35,9 +35,6 @@ pub enum ContractCreateResult {
/// Returned when contract creation failed.
/// VM doesn't have to know the reason.
Failed,
/// Returned when contract creation failed.
/// VM doesn't have to know the reason.
FailedInStaticCall,
/// Reverted with REVERT.
Reverted(U256, ReturnData),
}

View File

@@ -65,6 +65,7 @@ pub struct FakeExt {
pub schedule: Schedule,
pub balances: HashMap<Address, U256>,
pub tracing: bool,
pub is_static: bool,
}
// similar to the normal `finalize` function, but ignoring NeedsReturn.
@@ -192,7 +193,7 @@ impl Ext for FakeExt {
}
fn is_static(&self) -> bool {
false
self.is_static
}
fn inc_sstore_clears(&mut self) {

View File

@@ -221,8 +221,8 @@ impl<'a, 'b> Runtime<'a, 'b> {
}
/// Charge gas according to closure
pub fn charge<F>(&mut self, f: F) -> Result<(), InterpreterError>
where F: FnOnce(&vm::Schedule) -> u64
pub fn charge<F>(&mut self, f: F) -> Result<(), InterpreterError>
where F: FnOnce(&vm::Schedule) -> u64
{
let amount = f(self.ext.schedule());
if !self.charge_gas(amount as u64) {
@@ -277,10 +277,6 @@ impl<'a, 'b> Runtime<'a, 'b> {
self.gas_counter = self.gas_limit - gas_left.low_u64();
Ok(Some((-1i32).into()))
},
vm::ContractCreateResult::FailedInStaticCall => {
trace!(target: "wasm", "runtime: create contract called in static context");
Err(interpreter::Error::Trap("CREATE in static context".to_owned()))
},
}
}
@@ -615,11 +611,11 @@ impl<'a, 'b> Runtime<'a, 'b> {
}
fn return_u256_ptr(&mut self, ptr: u32, val: U256) -> Result<(), InterpreterError> {
let value: H256 = val.into();
let value: H256 = val.into();
self.charge(|schedule| schedule.wasm.static_u256 as u64)?;
self.memory.set(ptr, &*value)?;
Ok(())
}
}
fn coinbase(&mut self, context: InterpreterCallerContext)
-> Result<Option<interpreter::RuntimeValue>, InterpreterError>
@@ -640,7 +636,7 @@ impl<'a, 'b> Runtime<'a, 'b> {
context.value_stack.pop_as::<i32>()? as u32,
sender,
)?;
Ok(None)
Ok(None)
}
fn address(&mut self, context: InterpreterCallerContext)
@@ -651,7 +647,7 @@ impl<'a, 'b> Runtime<'a, 'b> {
context.value_stack.pop_as::<i32>()? as u32,
addr,
)?;
Ok(None)
Ok(None)
}
fn origin(&mut self, context: InterpreterCallerContext)
@@ -662,7 +658,7 @@ impl<'a, 'b> Runtime<'a, 'b> {
context.value_stack.pop_as::<i32>()? as u32,
origin,
)?;
Ok(None)
Ok(None)
}
fn value(&mut self, context: InterpreterCallerContext)
@@ -709,7 +705,7 @@ impl<'a, 'b> Runtime<'a, 'b> {
context.value_stack.pop_as::<i32>()? as u32,
gas_limit,
)?;
Ok(None)
Ok(None)
}
fn return_i64(&mut self, val: i64) -> Result<Option<interpreter::RuntimeValue>, InterpreterError> {

View File

@@ -122,6 +122,13 @@ impl<T> DiskDirectory<T> where T: KeyFileManager {
Ok(hasher.finish())
}
fn last_modification_date(&self) -> Result<u64, Error> {
use std::time::{Duration, UNIX_EPOCH};
let duration = fs::metadata(&self.path)?.modified()?.duration_since(UNIX_EPOCH).unwrap_or(Duration::default());
let timestamp = duration.as_secs() ^ (duration.subsec_nanos() as u64);
Ok(timestamp)
}
/// all accounts found in keys directory
fn files_content(&self) -> Result<HashMap<PathBuf, SafeAccount>, Error> {
// it's not done using one iterator cause
@@ -226,7 +233,7 @@ impl<T> KeyDirectory for DiskDirectory<T> where T: KeyFileManager {
}
fn unique_repr(&self) -> Result<u64, Error> {
self.files_hash()
self.last_modification_date()
}
}

View File

@@ -18,6 +18,7 @@ use std::collections::{BTreeMap, HashMap};
use std::mem;
use std::path::PathBuf;
use parking_lot::{Mutex, RwLock};
use std::time::{Instant, Duration};
use crypto::KEY_ITERATIONS;
use random::Random;
@@ -28,6 +29,8 @@ use presale::PresaleWallet;
use json::{self, Uuid, OpaqueKeyFile};
use {import, Error, SimpleSecretStore, SecretStore, SecretVaultRef, StoreAccountRef, Derivation, OpaqueSecret};
const REFRESH_TIME_SEC: u64 = 5;
/// Accounts store.
pub struct EthStore {
store: EthMultiStore,
@@ -245,7 +248,12 @@ pub struct EthMultiStore {
// order lock: cache, then vaults
cache: RwLock<BTreeMap<StoreAccountRef, Vec<SafeAccount>>>,
vaults: Mutex<HashMap<String, Box<VaultKeyDirectory>>>,
dir_hash: Mutex<Option<u64>>,
timestamp: Mutex<Timestamp>,
}
struct Timestamp {
dir_hash: Option<u64>,
last_checked: Instant,
}
impl EthMultiStore {
@@ -261,20 +269,27 @@ impl EthMultiStore {
vaults: Mutex::new(HashMap::new()),
iterations: iterations,
cache: Default::default(),
dir_hash: Default::default(),
timestamp: Mutex::new(Timestamp {
dir_hash: None,
last_checked: Instant::now(),
}),
};
store.reload_accounts()?;
Ok(store)
}
fn reload_if_changed(&self) -> Result<(), Error> {
let mut last_dir_hash = self.dir_hash.lock();
let dir_hash = Some(self.dir.unique_repr()?);
if *last_dir_hash == dir_hash {
return Ok(())
let mut last_timestamp = self.timestamp.lock();
let now = Instant::now();
if (now - last_timestamp.last_checked) > Duration::from_secs(REFRESH_TIME_SEC) {
let dir_hash = Some(self.dir.unique_repr()?);
last_timestamp.last_checked = now;
if last_timestamp.dir_hash == dir_hash {
return Ok(())
}
self.reload_accounts()?;
last_timestamp.dir_hash = dir_hash;
}
self.reload_accounts()?;
*last_dir_hash = dir_hash;
Ok(())
}
@@ -455,11 +470,11 @@ impl SimpleSecretStore for EthMultiStore {
}
fn account_ref(&self, address: &Address) -> Result<StoreAccountRef, Error> {
use std::collections::Bound;
self.reload_if_changed()?;
self.cache.read().keys()
.find(|r| &r.address == address)
.cloned()
.ok_or(Error::InvalidAccount)
let cache = self.cache.read();
let mut r = cache.range((Bound::Included(*address), Bound::Included(*address)));
r.next().ok_or(Error::InvalidAccount).map(|(k, _)| k.clone())
}
fn accounts(&self) -> Result<Vec<StoreAccountRef>, Error> {

View File

@@ -16,6 +16,7 @@
use std::hash::{Hash, Hasher};
use std::path::PathBuf;
use std::cmp::Ordering;
use ethkey::{Address, Message, Signature, Secret, Public};
use Error;
use json::{Uuid, OpaqueKeyFile};
@@ -32,12 +33,24 @@ pub enum SecretVaultRef {
}
/// Stored account reference
#[derive(Debug, Clone, PartialEq, Eq, PartialOrd, Ord)]
#[derive(Debug, Clone, PartialEq, Eq, Ord)]
pub struct StoreAccountRef {
/// Vault reference
pub vault: SecretVaultRef,
/// Account address
pub address: Address,
/// Vault reference
pub vault: SecretVaultRef,
}
impl PartialOrd for StoreAccountRef {
fn partial_cmp(&self, other: &StoreAccountRef) -> Option<Ordering> {
Some(self.address.cmp(&other.address).then_with(|| self.vault.cmp(&other.vault)))
}
}
impl ::std::borrow::Borrow<Address> for StoreAccountRef {
fn borrow(&self) -> &Address {
&self.address
}
}
/// Simple Secret Store API

View File

@@ -37,8 +37,8 @@ use trezor_sys::messages::{EthereumAddress, PinMatrixAck, MessageType, EthereumT
const TREZOR_VID: u16 = 0x534c;
const TREZOR_PIDS: [u16; 1] = [0x0001]; // Trezor v1, keeping this as an array to leave room for Trezor v2 which is in progress
const ETH_DERIVATION_PATH: [u32; 4] = [0x8000002C, 0x8000003C, 0x80000000, 0]; // m/44'/60'/0'/0
const ETC_DERIVATION_PATH: [u32; 4] = [0x8000002C, 0x8000003D, 0x80000000, 0]; // m/44'/61'/0'/0
const ETH_DERIVATION_PATH: [u32; 5] = [0x8000002C, 0x8000003C, 0x80000000, 0, 0]; // m/44'/60'/0'/0/0
const ETC_DERIVATION_PATH: [u32; 5] = [0x8000002C, 0x8000003D, 0x80000000, 0, 0]; // m/44'/61'/0'/0/0
/// Hardware wallet error.

View File

@@ -71,7 +71,6 @@ function loadCachedTokens (tokenRegContract) {
// Check if we have data from the right contract
if (cached.tokenreg === tokenRegContract.address && cached.tokens) {
log.debug('found cached tokens', cached.tokens);
dispatch(_setTokens(cached.tokens));
// Fetch all the tokens images on load
// (it's the only thing that might have changed)
@@ -105,22 +104,13 @@ export function loadTokens (options = {}) {
};
}
export function loadTokensBasics (_tokenIndexes, options) {
export function loadTokensBasics (tokenIndexes, options) {
const limit = 64;
return (dispatch, getState) => {
const { api, tokens } = getState();
const { api } = getState();
const { tokenReg } = Contracts.get();
const nextTokens = {};
const prevTokensIndexes = Object.values(tokens).map((t) => t.index);
// Only fetch tokens we don't have yet
const tokenIndexes = _tokenIndexes
.filter((tokenIndex) => {
return !prevTokensIndexes.includes(tokenIndex);
})
.sort();
const count = tokenIndexes.length;
log.debug('loading basic tokens', tokenIndexes);
@@ -240,6 +230,7 @@ function fetchTokensData (tokenRegContract, tokenIndexes) {
log.debug('fetched', { fullResults, partialResults });
return [].concat(fullResults, partialResults)
.filter(({ address }) => !/0x0*$/.test(address))
.reduce((tokens, token) => {
const { id, image, address } = token;

View File

@@ -32,14 +32,19 @@ class TokenImage extends Component {
}).isRequired
};
state = {
error: false
};
render () {
const { error } = this.state;
const { api } = this.context;
const { image, token } = this.props;
const imageurl = token.image || image;
let imagesrc = unknownImage;
if (imageurl) {
if (imageurl && !error) {
const host = /^(\/)?api/.test(imageurl)
? api.dappsUrl
: '';
@@ -49,11 +54,16 @@ class TokenImage extends Component {
return (
<img
src={ imagesrc }
alt={ token.name }
onError={ this.handleError }
src={ imagesrc }
/>
);
}
handleError = () => {
this.setState({ error: true });
};
}
function mapStateToProps (iniState) {

View File

@@ -55,9 +55,14 @@ export function fetchTokensBasics (api, tokenReg, start = 0, limit = 100) {
return api.eth
.call({ data: tokenAddressesBytcode + tokenAddressesCallData })
.then((result) => {
const tokenAddresses = decodeArray(api, 'address[]', result);
return decodeArray(api, 'address[]', result);
})
.then((tokenAddresses) => {
return tokenAddresses.map((tokenAddress, index) => {
if (/^0x0*$/.test(tokenAddress)) {
return null;
}
const tokenIndex = start + index;
return {
@@ -68,6 +73,17 @@ export function fetchTokensBasics (api, tokenReg, start = 0, limit = 100) {
fetched: false
};
});
})
.then((tokens) => tokens.filter((token) => token))
.then((tokens) => {
const randomAddress = sha3(`${Date.now()}`).substr(0, 42);
return fetchTokensBalances(api, tokens, [randomAddress])
.then((_balances) => {
const balances = _balances[randomAddress];
return tokens.filter(({ id }) => balances[id].eq(0));
});
});
}

View File

@@ -462,7 +462,7 @@
<key>OVERWRITE_PERMISSIONS</key>
<false/>
<key>VERSION</key>
<string>1.8.0</string>
<string>1.8.2</string>
</dict>
<key>UUID</key>
<string>2DCD5B81-7BAF-4DA1-9251-6274B089FD36</string>

View File

@@ -10,9 +10,9 @@
!define DESCRIPTION "Fast, light, robust Ethereum implementation"
!define VERSIONMAJOR 1
!define VERSIONMINOR 8
!define VERSIONBUILD 0
!define ARGS "--warp"
!define FIRST_START_ARGS "ui --warp --mode=passive"
!define VERSIONBUILD 2
!define ARGS ""
!define FIRST_START_ARGS "ui --mode=passive"
!addplugindir .\

View File

@@ -40,7 +40,7 @@ use parity_rpc::NetworkSettings;
use cache::CacheConfig;
use helpers::{to_duration, to_mode, to_block_id, to_u256, to_pending_set, to_price, replace_home, replace_home_and_local,
geth_ipc_path, parity_ipc_path, to_bootnodes, to_addresses, to_address, to_gas_limit, to_queue_strategy};
use params::{ResealPolicy, AccountsConfig, GasPricerConfig, MinerExtras};
use params::{ResealPolicy, AccountsConfig, GasPricerConfig, MinerExtras, SpecType};
use ethcore_logger::Config as LogConfig;
use dir::{self, Directories, default_hypervisor_path, default_local_path, default_data_path};
use dapps::Configuration as DappsConfiguration;
@@ -109,7 +109,7 @@ impl Configuration {
let pruning = self.args.arg_pruning.parse()?;
let pruning_history = self.args.arg_pruning_history;
let vm_type = self.vm_type()?;
let spec = self.chain().parse()?;
let spec = self.chain()?;
let mode = match self.args.arg_mode.as_ref() {
"last" => None,
mode => Some(to_mode(&mode, self.args.arg_mode_timeout, self.args.arg_mode_alarm)?),
@@ -336,7 +336,7 @@ impl Configuration {
pruning_memory: self.args.arg_pruning_memory,
daemon: daemon,
logger_config: logger_config.clone(),
miner_options: self.miner_options(self.args.arg_reseal_min_period)?,
miner_options: self.miner_options()?,
ntp_servers: self.ntp_servers(),
ws_conf: ws_conf,
http_conf: http_conf,
@@ -441,15 +441,16 @@ impl Configuration {
}
}
fn chain(&self) -> String {
if let Some(ref s) = self.spec_name_override {
fn chain(&self) -> Result<SpecType, String> {
let name = if let Some(ref s) = self.spec_name_override {
s.clone()
}
else if self.args.flag_testnet {
} else if self.args.flag_testnet {
"testnet".to_owned()
} else {
self.args.arg_chain.clone()
}
};
Ok(name.parse()?)
}
fn max_peers(&self) -> u32 {
@@ -504,8 +505,9 @@ impl Configuration {
} else { Ok(None) }
}
fn miner_options(&self, reseal_min_period: u64) -> Result<MinerOptions, String> {
if self.args.flag_force_sealing && reseal_min_period == 0 {
fn miner_options(&self) -> Result<MinerOptions, String> {
let is_dev_chain = self.chain()? == SpecType::Dev;
if is_dev_chain && self.args.flag_force_sealing && self.args.arg_reseal_min_period == 0 {
return Err("Force sealing can't be used with reseal_min_period = 0".into());
}
@@ -528,7 +530,7 @@ impl Configuration {
tx_queue_gas_limit: to_gas_limit(&self.args.arg_tx_queue_gas)?,
tx_queue_strategy: to_queue_strategy(&self.args.arg_tx_queue_strategy)?,
pending_set: to_pending_set(&self.args.arg_relay_set)?,
reseal_min_period: Duration::from_millis(reseal_min_period),
reseal_min_period: Duration::from_millis(self.args.arg_reseal_min_period),
reseal_max_period: Duration::from_millis(self.args.arg_reseal_max_period),
work_queue_size: self.args.arg_work_queue_size,
enable_resubmission: !self.args.flag_remove_solved,
@@ -883,7 +885,7 @@ impl Configuration {
let net_addresses = self.net_addresses()?;
Ok(NetworkSettings {
name: self.args.arg_identity.clone(),
chain: self.chain(),
chain: format!("{}", self.chain()?),
network_port: net_addresses.0.port(),
rpc_enabled: http_conf.enabled,
rpc_interface: http_conf.interface,
@@ -914,8 +916,6 @@ impl Configuration {
}
fn directories(&self) -> Directories {
use path;
let local_path = default_local_path();
let base_path = self.args.arg_base_path.as_ref().or_else(|| self.args.arg_datadir.as_ref()).map_or_else(|| default_data_path(), |s| s.clone());
let data_path = replace_home("", &base_path);
@@ -935,21 +935,6 @@ impl Configuration {
let secretstore_path = replace_home(&data_path, &self.args.arg_secretstore_path);
let ui_path = replace_home(&data_path, &self.args.arg_ui_path);
if self.args.flag_geth && !cfg!(windows) {
let geth_root = if self.chain() == "testnet".to_owned() { path::ethereum::test() } else { path::ethereum::default() };
::std::fs::create_dir_all(geth_root.as_path()).unwrap_or_else(
|e| warn!("Failed to create '{}' for geth mode: {}", &geth_root.to_str().unwrap(), e));
}
if cfg!(feature = "ipc") && !cfg!(feature = "windows") {
let mut path_buf = PathBuf::from(data_path.clone());
path_buf.push("ipc");
let ipc_path = path_buf.to_str().unwrap();
::std::fs::create_dir_all(ipc_path).unwrap_or_else(
|e| warn!("Failed to directory '{}' for ipc sockets: {}", ipc_path, e)
);
}
Directories {
keys: keys_path,
base: data_path,
@@ -1401,21 +1386,20 @@ mod tests {
let conf3 = parse(&["parity", "--tx-queue-strategy", "gas"]);
// then
let min_period = conf0.args.arg_reseal_min_period;
assert_eq!(conf0.miner_options(min_period).unwrap(), mining_options);
assert_eq!(conf0.miner_options().unwrap(), mining_options);
mining_options.tx_queue_strategy = PrioritizationStrategy::GasFactorAndGasPrice;
assert_eq!(conf1.miner_options(min_period).unwrap(), mining_options);
assert_eq!(conf1.miner_options().unwrap(), mining_options);
mining_options.tx_queue_strategy = PrioritizationStrategy::GasPriceOnly;
assert_eq!(conf2.miner_options(min_period).unwrap(), mining_options);
assert_eq!(conf2.miner_options().unwrap(), mining_options);
mining_options.tx_queue_strategy = PrioritizationStrategy::GasAndGasPrice;
assert_eq!(conf3.miner_options(min_period).unwrap(), mining_options);
assert_eq!(conf3.miner_options().unwrap(), mining_options);
}
#[test]
fn should_fail_on_force_reseal_and_reseal_min_period() {
let conf = parse(&["parity", "--chain", "dev", "--force-sealing"]);
let conf = parse(&["parity", "--chain", "dev", "--force-sealing", "--reseal-min-period", "0"]);
assert!(conf.miner_options(0).is_err());
assert!(conf.miner_options().is_err());
}
#[test]
@@ -1443,7 +1427,7 @@ mod tests {
// then
assert_eq!(conf.network_settings(), Ok(NetworkSettings {
name: "testname".to_owned(),
chain: "testnet".to_owned(),
chain: "kovan".to_owned(),
network_port: 30303,
rpc_enabled: true,
rpc_interface: "127.0.0.1".to_owned(),

View File

@@ -301,6 +301,12 @@ pub fn new_ipc<D: rpc_apis::Dependencies>(
let handler = setup_apis(conf.apis, dependencies);
let remote = dependencies.remote.clone();
let path = PathBuf::from(&conf.socket_addr);
if let Some(dir) = path.parent() {
::std::fs::create_dir_all(&dir)
.map_err(|err| format!("Unable to create IPC directory at {}: {}", dir.display(), err))?;
}
match rpc::start_ipc(&conf.socket_addr, handler, remote, rpc::RpcExtractor) {
Ok(server) => Ok(Some(server)),
Err(io_error) => Err(format!("IPC error: {}", io_error)),

View File

@@ -71,6 +71,9 @@ pub trait Dispatcher: Send + Sync + Clone {
fn sign(&self, accounts: Arc<AccountProvider>, filled: FilledTransactionRequest, password: SignWith)
-> BoxFuture<WithToken<SignedTransaction>, Error>;
/// Converts a `SignedTransaction` into `RichRawTransaction`
fn enrich(&self, SignedTransaction) -> RpcRichRawTransaction;
/// "Dispatch" a local transaction.
fn dispatch_transaction(&self, signed_transaction: PendingTransaction) -> Result<H256, Error>;
}
@@ -163,6 +166,11 @@ impl<C: MiningBlockChainClient, M: MinerService> Dispatcher for FullDispatcher<C
}))
}
fn enrich(&self, signed_transaction: SignedTransaction) -> RpcRichRawTransaction {
let block_number = self.client.best_block_header().number();
RpcRichRawTransaction::from_signed(signed_transaction, block_number, self.client.eip86_transition())
}
fn dispatch_transaction(&self, signed_transaction: PendingTransaction) -> Result<H256, Error> {
let hash = signed_transaction.transaction.hash();
@@ -261,11 +269,11 @@ impl LightDispatcher {
transaction_queue: Arc<RwLock<LightTransactionQueue>>,
) -> Self {
LightDispatcher {
sync: sync,
client: client,
on_demand: on_demand,
cache: cache,
transaction_queue: transaction_queue,
sync,
client,
on_demand,
cache,
transaction_queue,
}
}
@@ -399,6 +407,11 @@ impl Dispatcher for LightDispatcher {
.and_then(move |nonce| with_nonce(filled, nonce)))
}
fn enrich(&self, signed_transaction: SignedTransaction) -> RpcRichRawTransaction {
let block_number = self.client.best_block_header().number();
RpcRichRawTransaction::from_signed(signed_transaction, block_number, self.client.eip86_transition())
}
fn dispatch_transaction(&self, signed_transaction: PendingTransaction) -> Result<H256, Error> {
let hash = signed_transaction.transaction.hash();
@@ -510,8 +523,8 @@ pub fn execute<D: Dispatcher + 'static>(
},
ConfirmationPayload::SignTransaction(request) => {
Box::new(dispatcher.sign(accounts, request, pass)
.map(|result| result
.map(RpcRichRawTransaction::from)
.map(move |result| result
.map(move |tx| dispatcher.enrich(tx))
.map(ConfirmationResponse::SignTransaction)
))
},

View File

@@ -23,7 +23,7 @@ use ethcore::encoded;
use ethcore::executed::{Executed, ExecutionError};
use ethcore::ids::BlockId;
use ethcore::filter::Filter as EthcoreFilter;
use ethcore::transaction::{Action, Transaction as EthTransaction, SignedTransaction};
use ethcore::transaction::{Action, Transaction as EthTransaction, SignedTransaction, LocalizedTransaction};
use ethcore::receipt::Receipt;
use jsonrpc_core::{BoxFuture, Error};
@@ -65,13 +65,24 @@ pub struct LightFetch {
/// Extract a transaction at given index.
pub fn extract_transaction_at_index(block: encoded::Block, index: usize, eip86_transition: u64) -> Option<Transaction> {
block.transactions().into_iter().nth(index)
// Verify if transaction signature is correct.
.and_then(|tx| SignedTransaction::new(tx).ok())
.map(|tx| Transaction::from_signed(tx, block.number(), eip86_transition))
.map(|mut tx| {
tx.block_hash = Some(block.hash().into());
tx.transaction_index = Some(index.into());
tx
.map(|signed_tx| {
let (signed, sender, _) = signed_tx.deconstruct();
let block_hash = block.hash();
let block_number = block.number();
let transaction_index = index;
let cached_sender = Some(sender);
LocalizedTransaction {
signed,
block_number,
block_hash,
transaction_index,
cached_sender,
}
})
.map(|tx| Transaction::from_localized(tx, eip86_transition))
}

View File

@@ -73,8 +73,8 @@ impl<D: Dispatcher + 'static> SignerClient<D> {
SignerClient {
signer: signer.clone(),
accounts: store.clone(),
dispatcher: dispatcher,
subscribers: subscribers,
dispatcher,
subscribers,
}
}
@@ -205,7 +205,8 @@ impl<D: Dispatcher + 'static> Signer for SignerClient<D> {
},
ConfirmationPayload::SignTransaction(request) => {
Self::verify_transaction(bytes, request, |pending_transaction| {
Ok(ConfirmationResponse::SignTransaction(pending_transaction.transaction.into()))
let rich = self.dispatcher.enrich(pending_transaction.transaction);
Ok(ConfirmationResponse::SignTransaction(rich))
})
},
ConfirmationPayload::EthSignMessage(address, data) => {

View File

@@ -547,7 +547,7 @@ fn rpc_eth_pending_transaction_by_hash() {
tester.miner.pending_transactions.lock().insert(H256::zero(), tx);
}
let response = r#"{"jsonrpc":"2.0","result":{"blockHash":null,"blockNumber":"0x0","chainId":null,"condition":null,"creates":null,"from":"0x0f65fe9276bc9a24ae7083ae28e2660ef72df99e","gas":"0x5208","gasPrice":"0x1","hash":"0x41df922fd0d4766fcc02e161f8295ec28522f329ae487f14d811e4b64c8d6e31","input":"0x","nonce":"0x0","publicKey":"0x7ae46da747962c2ee46825839c1ef9298e3bd2e70ca2938495c3693a485ec3eaa8f196327881090ff64cf4fbb0a48485d4f83098e189ed3b7a87d5941b59f789","r":"0x48b55bfa915ac795c431978d8a6a992b628d557da5ff759b307d495a36649353","raw":"0xf85f800182520894095e7baea6a6c7c4c2dfeb977efac326af552d870a801ba048b55bfa915ac795c431978d8a6a992b628d557da5ff759b307d495a36649353a0efffd310ac743f371de3b9f7f9cb56c0b28ad43601b4ab949f53faa07bd2c804","s":"0xefffd310ac743f371de3b9f7f9cb56c0b28ad43601b4ab949f53faa07bd2c804","standardV":"0x0","to":"0x095e7baea6a6c7c4c2dfeb977efac326af552d87","transactionIndex":null,"v":"0x1b","value":"0xa"},"id":1}"#;
let response = r#"{"jsonrpc":"2.0","result":{"blockHash":null,"blockNumber":null,"chainId":null,"condition":null,"creates":null,"from":"0x0f65fe9276bc9a24ae7083ae28e2660ef72df99e","gas":"0x5208","gasPrice":"0x1","hash":"0x41df922fd0d4766fcc02e161f8295ec28522f329ae487f14d811e4b64c8d6e31","input":"0x","nonce":"0x0","publicKey":"0x7ae46da747962c2ee46825839c1ef9298e3bd2e70ca2938495c3693a485ec3eaa8f196327881090ff64cf4fbb0a48485d4f83098e189ed3b7a87d5941b59f789","r":"0x48b55bfa915ac795c431978d8a6a992b628d557da5ff759b307d495a36649353","raw":"0xf85f800182520894095e7baea6a6c7c4c2dfeb977efac326af552d870a801ba048b55bfa915ac795c431978d8a6a992b628d557da5ff759b307d495a36649353a0efffd310ac743f371de3b9f7f9cb56c0b28ad43601b4ab949f53faa07bd2c804","s":"0xefffd310ac743f371de3b9f7f9cb56c0b28ad43601b4ab949f53faa07bd2c804","standardV":"0x0","to":"0x095e7baea6a6c7c4c2dfeb977efac326af552d87","transactionIndex":null,"v":"0x1b","value":"0xa"},"id":1}"#;
let request = r#"{
"jsonrpc": "2.0",
"method": "eth_getTransactionByHash",
@@ -863,7 +863,7 @@ fn rpc_eth_sign_transaction() {
let response = r#"{"jsonrpc":"2.0","result":{"#.to_owned() +
r#""raw":"0x"# + &rlp.to_hex() + r#"","# +
r#""tx":{"# +
r#""blockHash":null,"blockNumber":"0x0","# +
r#""blockHash":null,"blockNumber":null,"# +
&format!("\"chainId\":{},", t.chain_id().map_or("null".to_owned(), |n| format!("{}", n))) +
r#""condition":null,"creates":null,"# +
&format!("\"from\":\"0x{:?}\",", &address) +

View File

@@ -234,7 +234,7 @@ fn rpc_parity_remove_transaction() {
let hash = signed.hash();
let request = r#"{"jsonrpc": "2.0", "method": "parity_removeTransaction", "params":[""#.to_owned() + &format!("0x{:?}", hash) + r#""], "id": 1}"#;
let response = r#"{"jsonrpc":"2.0","result":{"blockHash":null,"blockNumber":"0x0","chainId":null,"condition":null,"creates":null,"from":"0x0000000000000000000000000000000000000002","gas":"0x76c0","gasPrice":"0x9184e72a000","hash":"0xa2e0da8a8064e0b9f93e95a53c2db6d01280efb8ac72a708d25487e67dd0f8fc","input":"0x","nonce":"0x1","publicKey":null,"r":"0x1","raw":"0xe9018609184e72a0008276c0940000000000000000000000000000000000000005849184e72a80800101","s":"0x1","standardV":"0x4","to":"0x0000000000000000000000000000000000000005","transactionIndex":null,"v":"0x0","value":"0x9184e72a"},"id":1}"#;
let response = r#"{"jsonrpc":"2.0","result":{"blockHash":null,"blockNumber":null,"chainId":null,"condition":null,"creates":null,"from":"0x0000000000000000000000000000000000000002","gas":"0x76c0","gasPrice":"0x9184e72a000","hash":"0xa2e0da8a8064e0b9f93e95a53c2db6d01280efb8ac72a708d25487e67dd0f8fc","input":"0x","nonce":"0x1","publicKey":null,"r":"0x1","raw":"0xe9018609184e72a0008276c0940000000000000000000000000000000000000005849184e72a80800101","s":"0x1","standardV":"0x4","to":"0x0000000000000000000000000000000000000005","transactionIndex":null,"v":"0x0","value":"0x9184e72a"},"id":1}"#;
miner.pending_transactions.lock().insert(hash, signed);
assert_eq!(io.handle_request_sync(&request), Some(response.to_owned()));

View File

@@ -456,7 +456,7 @@ fn should_confirm_sign_transaction_with_rlp() {
let response = r#"{"jsonrpc":"2.0","result":{"#.to_owned() +
r#""raw":"0x"# + &rlp.to_hex() + r#"","# +
r#""tx":{"# +
r#""blockHash":null,"blockNumber":"0x0","# +
r#""blockHash":null,"blockNumber":null,"# +
&format!("\"chainId\":{},", t.chain_id().map_or("null".to_owned(), |n| format!("{}", n))) +
r#""condition":null,"creates":null,"# +
&format!("\"from\":\"0x{:?}\",", &address) +

View File

@@ -25,7 +25,7 @@ use v1::impls::SigningQueueClient;
use v1::metadata::Metadata;
use v1::traits::{EthSigning, ParitySigning, Parity};
use v1::helpers::{SignerService, SigningQueue, FullDispatcher};
use v1::types::ConfirmationResponse;
use v1::types::{ConfirmationResponse, RichRawTransaction};
use v1::tests::helpers::TestMinerService;
use v1::tests::mocked::parity;
@@ -299,7 +299,7 @@ fn should_add_sign_transaction_to_the_queue() {
let response = r#"{"jsonrpc":"2.0","result":{"#.to_owned() +
r#""raw":"0x"# + &rlp.to_hex() + r#"","# +
r#""tx":{"# +
r#""blockHash":null,"blockNumber":"0x0","# +
r#""blockHash":null,"blockNumber":null,"# +
&format!("\"chainId\":{},", t.chain_id().map_or("null".to_owned(), |n| format!("{}", n))) +
r#""condition":null,"creates":null,"# +
&format!("\"from\":\"0x{:?}\",", &address) +
@@ -326,7 +326,9 @@ fn should_add_sign_transaction_to_the_queue() {
::std::thread::spawn(move || loop {
if signer.requests().len() == 1 {
// respond
signer.request_confirmed(1.into(), Ok(ConfirmationResponse::SignTransaction(t.into())));
signer.request_confirmed(1.into(), Ok(ConfirmationResponse::SignTransaction(
RichRawTransaction::from_signed(t.into(), 0x0, u64::max_value())
)));
break
}
::std::thread::sleep(Duration::from_millis(100))

View File

@@ -158,11 +158,10 @@ pub struct RichRawTransaction {
pub transaction: Transaction
}
impl From<SignedTransaction> for RichRawTransaction {
fn from(t: SignedTransaction) -> Self {
// TODO: change transition to 0 when EIP-86 is commonly used.
let tx: Transaction = Transaction::from_signed(t, 0, u64::max_value());
impl RichRawTransaction {
/// Creates new `RichRawTransaction` from `SignedTransaction`.
pub fn from_signed(tx: SignedTransaction, block_number: u64, eip86_transition: u64) -> Self {
let tx = Transaction::from_signed(tx, block_number, eip86_transition);
RichRawTransaction {
raw: tx.raw.clone(),
transaction: tx,
@@ -213,7 +212,7 @@ impl Transaction {
hash: t.hash().into(),
nonce: t.nonce.into(),
block_hash: None,
block_number: Some(block_number.into()),
block_number: None,
transaction_index: None,
from: t.sender().into(),
to: match t.action {

View File

@@ -137,7 +137,7 @@ const MAX_TRANSACTION_PACKET_SIZE: usize = 8 * 1024 * 1024;
// Maximal number of transactions in sent in single packet.
const MAX_TRANSACTIONS_TO_PROPAGATE: usize = 64;
// Min number of blocks to be behind for a snapshot sync
const SNAPSHOT_RESTORE_THRESHOLD: BlockNumber = 10000;
const SNAPSHOT_RESTORE_THRESHOLD: BlockNumber = 30000;
const SNAPSHOT_MIN_PEERS: usize = 3;
const STATUS_PACKET: u8 = 0x00;

View File

@@ -3,7 +3,7 @@ description = "Ethcore utility library"
homepage = "http://parity.io"
license = "GPL-3.0"
name = "ethcore-util"
version = "1.8.0"
version = "1.8.2"
authors = ["Parity Technologies <admin@parity.io>"]
build = "build.rs"