Merge pull request #7043 from paritytech/beta-backport

backports to beta
This commit is contained in:
Marek Kotewicz 2017-11-14 15:51:13 +01:00 committed by GitHub
commit b49c44a198
No known key found for this signature in database
GPG Key ID: 4AEE18F83AFDEB23
22 changed files with 473 additions and 188 deletions

84
Cargo.lock generated
View File

@ -1,17 +1,3 @@
[root]
name = "wasm"
version = "0.1.0"
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.2",
"log 0.3.8 (registry+https://github.com/rust-lang/crates.io-index)",
"parity-wasm 0.15.1 (registry+https://github.com/rust-lang/crates.io-index)",
"vm 0.1.0",
"wasm-utils 0.1.0 (git+https://github.com/paritytech/wasm-utils)",
]
[[package]]
name = "adler32"
version = "1.0.2"
@ -374,7 +360,7 @@ dependencies = [
"bloomable 0.1.0",
"ethcore-bigint 0.1.3",
"ethcore-bytes 0.1.0",
"ethcore-util 1.8.2",
"ethcore-util 1.8.3",
"ethjson 0.1.0",
"hash 0.1.0",
"heapsize 0.4.1 (registry+https://github.com/rust-lang/crates.io-index)",
@ -588,7 +574,7 @@ dependencies = [
"ethcore-ipc-nano 1.8.0",
"ethcore-logger 1.8.0",
"ethcore-stratum 1.8.0",
"ethcore-util 1.8.2",
"ethcore-util 1.8.3",
"ethjson 0.1.0",
"ethkey 0.2.0",
"ethstore 0.1.0",
@ -682,7 +668,7 @@ version = "1.8.0"
dependencies = [
"ethcore-bigint 0.1.3",
"ethcore-devtools 1.8.0",
"ethcore-util 1.8.2",
"ethcore-util 1.8.3",
"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 +718,7 @@ dependencies = [
"ethcore-ipc 1.8.0",
"ethcore-ipc-codegen 1.8.0",
"ethcore-ipc-nano 1.8.0",
"ethcore-util 1.8.2",
"ethcore-util 1.8.3",
"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 +737,7 @@ dependencies = [
"ethcore-ipc 1.8.0",
"ethcore-ipc-codegen 1.8.0",
"ethcore-network 1.8.0",
"ethcore-util 1.8.2",
"ethcore-util 1.8.3",
"evm 0.1.0",
"futures 0.1.16 (registry+https://github.com/rust-lang/crates.io-index)",
"hash 0.1.0",
@ -801,7 +787,7 @@ dependencies = [
"ethcore-devtools 1.8.0",
"ethcore-io 1.8.0",
"ethcore-logger 1.8.0",
"ethcore-util 1.8.2",
"ethcore-util 1.8.3",
"ethcrypto 0.1.0",
"ethkey 0.2.0",
"hash 0.1.0",
@ -836,7 +822,7 @@ dependencies = [
"ethcore-ipc-codegen 1.8.0",
"ethcore-ipc-nano 1.8.0",
"ethcore-logger 1.8.0",
"ethcore-util 1.8.2",
"ethcore-util 1.8.3",
"ethcrypto 0.1.0",
"ethkey 0.2.0",
"futures 0.1.16 (registry+https://github.com/rust-lang/crates.io-index)",
@ -871,7 +857,7 @@ dependencies = [
"ethcore-ipc-codegen 1.8.0",
"ethcore-ipc-nano 1.8.0",
"ethcore-logger 1.8.0",
"ethcore-util 1.8.2",
"ethcore-util 1.8.3",
"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 +870,7 @@ dependencies = [
[[package]]
name = "ethcore-util"
version = "1.8.2"
version = "1.8.3"
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 +1004,7 @@ dependencies = [
"ethcore-ipc-nano 1.8.0",
"ethcore-light 1.8.0",
"ethcore-network 1.8.0",
"ethcore-util 1.8.2",
"ethcore-util 1.8.3",
"ethkey 0.2.0",
"hash 0.1.0",
"heapsize 0.4.1 (registry+https://github.com/rust-lang/crates.io-index)",
@ -1044,7 +1030,7 @@ dependencies = [
"common-types 0.1.0",
"ethcore-bigint 0.1.3",
"ethcore-logger 1.8.0",
"ethcore-util 1.8.2",
"ethcore-util 1.8.3",
"ethjson 0.1.0",
"evmjit 1.8.0",
"hash 0.1.0",
@ -1066,7 +1052,7 @@ dependencies = [
"ethcore 1.8.0",
"ethcore-bigint 0.1.3",
"ethcore-bytes 0.1.0",
"ethcore-util 1.8.2",
"ethcore-util 1.8.3",
"ethjson 0.1.0",
"evm 0.1.0",
"panic_hook 0.1.0",
@ -1364,7 +1350,7 @@ dependencies = [
"ethcore-bigint 0.1.3",
"ethcore-ipc 1.8.0",
"ethcore-ipc-codegen 1.8.0",
"ethcore-util 1.8.2",
"ethcore-util 1.8.3",
"semver 0.6.0 (registry+https://github.com/rust-lang/crates.io-index)",
]
@ -1857,7 +1843,7 @@ dependencies = [
"ethcore-bytes 0.1.0",
"ethcore-io 1.8.0",
"ethcore-network 1.8.0",
"ethcore-util 1.8.2",
"ethcore-util 1.8.3",
"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 +2042,7 @@ dependencies = [
[[package]]
name = "parity"
version = "1.8.2"
version = "1.8.3"
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 +2066,7 @@ dependencies = [
"ethcore-network 1.8.0",
"ethcore-secretstore 1.0.0",
"ethcore-stratum 1.8.0",
"ethcore-util 1.8.2",
"ethcore-util 1.8.3",
"ethkey 0.2.0",
"ethsync 1.8.0",
"fdlimit 0.1.1 (registry+https://github.com/rust-lang/crates.io-index)",
@ -2136,7 +2122,7 @@ dependencies = [
"ethcore-bigint 0.1.3",
"ethcore-bytes 0.1.0",
"ethcore-devtools 1.8.0",
"ethcore-util 1.8.2",
"ethcore-util 1.8.3",
"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 +2184,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.2",
"ethcore-util 1.8.3",
"fetch 0.1.0",
"futures 0.1.16 (registry+https://github.com/rust-lang/crates.io-index)",
"hash 0.1.0",
@ -2220,7 +2206,7 @@ dependencies = [
"ethcore 1.8.0",
"ethcore-bigint 0.1.3",
"ethcore-bytes 0.1.0",
"ethcore-util 1.8.2",
"ethcore-util 1.8.3",
"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 +2220,7 @@ version = "0.1.0"
dependencies = [
"ethcore 1.8.0",
"ethcore-io 1.8.0",
"ethcore-util 1.8.2",
"ethcore-util 1.8.3",
"ethkey 0.2.0",
"kvdb 0.1.0",
"log 0.3.8 (registry+https://github.com/rust-lang/crates.io-index)",
@ -2249,7 +2235,7 @@ name = "parity-machine"
version = "0.1.0"
dependencies = [
"ethcore-bigint 0.1.3",
"ethcore-util 1.8.2",
"ethcore-util 1.8.3",
]
[[package]]
@ -2277,7 +2263,7 @@ dependencies = [
"ethcore-light 1.8.0",
"ethcore-logger 1.8.0",
"ethcore-network 1.8.0",
"ethcore-util 1.8.2",
"ethcore-util 1.8.3",
"ethcrypto 0.1.0",
"ethjson 0.1.0",
"ethkey 0.2.0",
@ -2387,7 +2373,7 @@ dependencies = [
"ethcore-bytes 0.1.0",
"ethcore-ipc 1.8.0",
"ethcore-ipc-codegen 1.8.0",
"ethcore-util 1.8.2",
"ethcore-util 1.8.3",
"ethsync 1.8.0",
"futures 0.1.16 (registry+https://github.com/rust-lang/crates.io-index)",
"ipc-common-types 1.8.0",
@ -2401,7 +2387,7 @@ dependencies = [
[[package]]
name = "parity-wasm"
version = "0.15.1"
version = "0.15.3"
source = "registry+https://github.com/rust-lang/crates.io-index"
dependencies = [
"byteorder 1.1.0 (registry+https://github.com/rust-lang/crates.io-index)",
@ -2849,7 +2835,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.2",
"ethcore-util 1.8.3",
"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 +3551,7 @@ dependencies = [
"common-types 0.1.0",
"ethcore-bigint 0.1.3",
"ethcore-bytes 0.1.0",
"ethcore-util 1.8.2",
"ethcore-util 1.8.3",
"ethjson 0.1.0",
"evmjit 1.8.0",
"hash 0.1.0",
@ -3580,6 +3566,20 @@ name = "void"
version = "1.0.2"
source = "registry+https://github.com/rust-lang/crates.io-index"
[[package]]
name = "wasm"
version = "0.1.0"
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.3",
"log 0.3.8 (registry+https://github.com/rust-lang/crates.io-index)",
"parity-wasm 0.15.3 (registry+https://github.com/rust-lang/crates.io-index)",
"vm 0.1.0",
"wasm-utils 0.1.0 (git+https://github.com/paritytech/wasm-utils)",
]
[[package]]
name = "wasm-utils"
version = "0.1.0"
@ -3591,7 +3591,7 @@ dependencies = [
"glob 0.2.11 (registry+https://github.com/rust-lang/crates.io-index)",
"lazy_static 0.2.8 (registry+https://github.com/rust-lang/crates.io-index)",
"log 0.3.8 (registry+https://github.com/rust-lang/crates.io-index)",
"parity-wasm 0.15.1 (registry+https://github.com/rust-lang/crates.io-index)",
"parity-wasm 0.15.3 (registry+https://github.com/rust-lang/crates.io-index)",
]
[[package]]
@ -3815,7 +3815,7 @@ dependencies = [
"checksum parity-dapps-glue 1.8.0 (registry+https://github.com/rust-lang/crates.io-index)" = "ddaeb8543c6823e93dae65a25eb8083ebfeee8f0000031119d7a0055b2e8fc63"
"checksum parity-tokio-ipc 0.1.5 (git+https://github.com/nikvolf/parity-tokio-ipc)" = "<none>"
"checksum parity-ui-precompiled 1.4.0 (git+https://github.com/paritytech/js-precompiled.git?branch=beta)" = "<none>"
"checksum parity-wasm 0.15.1 (registry+https://github.com/rust-lang/crates.io-index)" = "95f6243c2d6fadf903b5edfd0011817efc20522ce5f360abf4648c24ea87581a"
"checksum parity-wasm 0.15.3 (registry+https://github.com/rust-lang/crates.io-index)" = "8431a184ad88cfbcd71a792aaca319cc7203a94300c26b8dce2d0df0681ea87d"
"checksum parity-wordlist 1.1.0 (registry+https://github.com/rust-lang/crates.io-index)" = "81451bfab101d186f8fc4a0aa13cb5539b31b02c4ed96425a0842e2a413daba6"
"checksum parking_lot 0.4.8 (registry+https://github.com/rust-lang/crates.io-index)" = "149d8f5b97f3c1133e3cfcd8886449959e856b557ff281e292b733d7c69e005e"
"checksum parking_lot_core 0.2.6 (registry+https://github.com/rust-lang/crates.io-index)" = "4f610cb9664da38e417ea3225f23051f589851999535290e077939838ab7a595"

View File

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

@ -1 +1 @@
Subproject commit c8129ce2f36c26ed634eda786960978a28e28d0e
Subproject commit 9a1fcbf0d4e73bea437577e807bc38c7ba243d80

View File

@ -1241,7 +1241,7 @@ impl BlockChainClient for Client {
// that's just a copy of the state.
let original_state = self.state_at(block).ok_or(CallError::StatePruned)?;
let sender = t.sender();
let options = || TransactOptions::with_tracing();
let options = || TransactOptions::with_tracing().dont_check_nonce();
let cond = |gas| {
let mut tx = t.as_unsigned().clone();

View File

@ -162,6 +162,12 @@ impl Header {
pub fn difficulty(&self) -> &U256 { &self.difficulty }
/// Get the seal field of the header.
pub fn seal(&self) -> &[Bytes] { &self.seal }
/// Get the seal field with RLP-decoded values as bytes.
pub fn decode_seal<'a, T: ::std::iter::FromIterator<&'a [u8]>>(&'a self) -> Result<T, DecoderError> {
self.seal.iter().map(|rlp| {
UntrustedRlp::new(rlp).data()
}).collect()
}
// TODO: seal_at, set_seal_at &c.
@ -340,13 +346,20 @@ mod tests {
// that's rlp of block header created with ethash engine.
let header_rlp = "f901f9a0d405da4e66f1445d455195229624e133f5baafe72b5cf7b3c36c12c8146e98b7a01dcc4de8dec75d7aab85b567b6ccd41ad312451b948a7413f0a142fd40d49347948888f1f195afa192cfee860698584c030f4c9db1a05fb2b4bfdef7b314451cb138a534d225c922fc0e5fbe25e451142732c3e25c25a088d2ec6b9860aae1a2c3b299f72b6a5d70d7f7ba4722c78f2c49ba96273c2158a007c6fdfa8eea7e86b81f5b0fc0f78f90cc19f4aa60d323151e0cac660199e9a1b90100000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000008302008003832fefba82524d84568e932a80a0a0349d8c3df71f1a48a9df7d03fd5f14aeee7d91332c009ecaff0a71ead405bd88ab4e252a7e8c2a23".from_hex().unwrap();
let mix_hash = "a0a0349d8c3df71f1a48a9df7d03fd5f14aeee7d91332c009ecaff0a71ead405bd".from_hex().unwrap();
let mix_hash_decoded = "a0349d8c3df71f1a48a9df7d03fd5f14aeee7d91332c009ecaff0a71ead405bd".from_hex().unwrap();
let nonce = "88ab4e252a7e8c2a23".from_hex().unwrap();
let nonce_decoded = "ab4e252a7e8c2a23".from_hex().unwrap();
let header: Header = rlp::decode(&header_rlp);
let seal_fields = header.seal;
let seal_fields = header.seal.clone();
assert_eq!(seal_fields.len(), 2);
assert_eq!(seal_fields[0], mix_hash);
assert_eq!(seal_fields[1], nonce);
let decoded_seal = header.decode_seal::<Vec<_>>().unwrap();
assert_eq!(decoded_seal.len(), 2);
assert_eq!(decoded_seal[0], &*mix_hash_decoded);
assert_eq!(decoded_seal[1], &*nonce_decoded);
}
#[test]

View File

@ -21,7 +21,7 @@ use bigint::prelude::U256;
use bigint::hash::{H256, H2048};
use util::Address;
use bytes::Bytes;
use rlp::Rlp;
use rlp::{self, Rlp};
use header::BlockNumber;
/// View onto block header rlp.
@ -99,6 +99,14 @@ impl<'a> HeaderView<'a> {
}
seal
}
/// Returns a vector of seal fields (RLP-decoded).
pub fn decode_seal(&self) -> Result<Vec<Bytes>, rlp::DecoderError> {
let seal = self.seal();
seal.into_iter()
.map(|s| rlp::UntrustedRlp::new(&s).data().map(|x| x.to_vec()))
.collect()
}
}
#[cfg(test)]

View File

@ -127,12 +127,14 @@ pub struct WasmCosts {
pub mul: u32,
/// Memory (load/store) operations multiplier.
pub mem: u32,
/// Memory copy operation.
/// Memory copy operation, per byte.
pub mem_copy: u32,
/// Memory move operation, per byte.
pub mem_move: u32,
/// Memory set operation, per byte.
pub mem_set: u32,
/// Static region charge, per byte.
pub static_region: u32,
/// General static query of u64 value from env-info
pub static_u64: u32,
/// General static query of U256 value from env-info
pub static_u256: u32,
/// General static query of Address value from env-info
@ -147,11 +149,9 @@ impl Default for WasmCosts {
mul: 4,
mem: 2,
mem_copy: 1,
mem_move: 1,
mem_set: 1,
static_region: 1,
// due to runtime issues, this can be slow
static_u64: 32,
static_u256: 64,
static_address: 40,
}

View File

@ -38,12 +38,12 @@ pub const SIGNATURES: &'static [UserFunctionDescriptor] = &[
None,
),
Static(
"_malloc",
"_ext_malloc",
&[I32],
Some(I32),
),
Static(
"_free",
"_ext_free",
&[I32],
None,
),
@ -92,6 +92,21 @@ pub const SIGNATURES: &'static [UserFunctionDescriptor] = &[
&[I32; 3],
Some(I32),
),
Static(
"_ext_memcpy",
&[I32; 3],
Some(I32),
),
Static(
"_ext_memset",
&[I32; 3],
Some(I32),
),
Static(
"_ext_memmove",
&[I32; 3],
Some(I32),
),
Static(
"_panic",
&[I32; 2],
@ -99,7 +114,7 @@ pub const SIGNATURES: &'static [UserFunctionDescriptor] = &[
),
Static(
"_blockhash",
&[I32; 3],
&[I64, I32],
Some(I32),
),
Static(
@ -130,12 +145,12 @@ pub const SIGNATURES: &'static [UserFunctionDescriptor] = &[
Static(
"_timestamp",
&[],
Some(I32),
Some(I64),
),
Static(
"_blocknumber",
&[],
Some(I32),
Some(I64),
),
Static(
"_difficulty",
@ -147,6 +162,11 @@ pub const SIGNATURES: &'static [UserFunctionDescriptor] = &[
&[I32],
None,
),
Static(
"_elog",
&[I32; 4],
None,
),
// TODO: Get rid of it also somehow?
Static(
@ -157,8 +177,8 @@ pub const SIGNATURES: &'static [UserFunctionDescriptor] = &[
Static(
"_llvm_bswap_i64",
&[I32; 2],
Some(I32)
&[I64],
Some(I64)
),
];

View File

@ -55,6 +55,8 @@ pub enum UserTrap {
Unknown,
/// Passed string had invalid utf-8 encoding
BadUtf8,
/// Log event error
Log,
/// Other error in native code
Other,
/// Panic with message
@ -75,6 +77,7 @@ impl ::std::fmt::Display for UserTrap {
UserTrap::AllocationFailed => write!(f, "Memory allocation failed (OOM)"),
UserTrap::BadUtf8 => write!(f, "String encoding is bad utf-8 sequence"),
UserTrap::GasLimit => write!(f, "Invocation resulted in gas limit violated"),
UserTrap::Log => write!(f, "Error occured while logging an event"),
UserTrap::Other => write!(f, "Other unspecified error"),
UserTrap::Panic(ref msg) => write!(f, "Panic: {}", msg),
}
@ -232,6 +235,21 @@ impl<'a, 'b> Runtime<'a, 'b> {
}
}
pub fn overflow_charge<F>(&mut self, f: F) -> Result<(), InterpreterError>
where F: FnOnce(&vm::Schedule) -> Option<u64>
{
let amount = match f(self.ext.schedule()) {
Some(amount) => amount,
None => { return Err(UserTrap::GasLimit.into()); }
};
if !self.charge_gas(amount as u64) {
Err(UserTrap::GasLimit.into())
} else {
Ok(())
}
}
/// Invoke create in the state runtime
pub fn create(&mut self, context: InterpreterCallerContext)
-> Result<Option<interpreter::RuntimeValue>, InterpreterError>
@ -542,32 +560,67 @@ impl<'a, 'b> Runtime<'a, 'b> {
fn mem_copy(&mut self, context: InterpreterCallerContext)
-> Result<Option<interpreter::RuntimeValue>, InterpreterError>
{
//
// method signature:
// fn memcpy(dest: *const u8, src: *const u8, len: u32) -> *mut u8;
//
let len = context.value_stack.pop_as::<i32>()? as u32;
let dst = context.value_stack.pop_as::<i32>()? as u32;
let src = context.value_stack.pop_as::<i32>()? as u32;
let dst = context.value_stack.pop_as::<i32>()? as u32;
self.charge(|schedule| schedule.wasm.mem_copy as u64 * len as u64)?;
let mem = self.memory().get(src, len as usize)?;
self.memory().set(dst, &mem)?;
self.memory().copy_nonoverlapping(src as usize, dst as usize, len as usize)?;
Ok(Some(0i32.into()))
Ok(Some(Into::into(dst as i32)))
}
fn bswap_32(x: u32) -> u32 {
x >> 24 | x >> 8 & 0xff00 | x << 8 & 0xff0000 | x << 24
fn mem_move(&mut self, context: InterpreterCallerContext)
-> Result<Option<interpreter::RuntimeValue>, InterpreterError>
{
//
// method signature:
// fn memmove(dest: *const u8, src: *const u8, len: u32) -> *mut u8;
//
let len = context.value_stack.pop_as::<i32>()? as u32;
let src = context.value_stack.pop_as::<i32>()? as u32;
let dst = context.value_stack.pop_as::<i32>()? as u32;
self.charge(|schedule| schedule.wasm.mem_move as u64 * len as u64)?;
self.memory().copy(src as usize, dst as usize, len as usize)?;
Ok(Some(Into::into(dst as i32)))
}
fn mem_set(&mut self, context: InterpreterCallerContext)
-> Result<Option<interpreter::RuntimeValue>, InterpreterError>
{
//
// method signature:
// fn memset(dest: *const u8, c: u32, len: u32) -> *mut u8;
//
let len = context.value_stack.pop_as::<i32>()? as u32;
let c = context.value_stack.pop_as::<i32>()? as u32;
let dst = context.value_stack.pop_as::<i32>()? as u32;
self.charge(|schedule| schedule.wasm.mem_set as u64 * len as u64)?;
self.memory().clear(dst as usize, c as u8, len as usize)?;
Ok(Some(Into::into(dst as i32)))
}
fn bitswap_i64(&mut self, context: InterpreterCallerContext)
-> Result<Option<interpreter::RuntimeValue>, InterpreterError>
{
let x1 = context.value_stack.pop_as::<i32>()?;
let x2 = context.value_stack.pop_as::<i32>()?;
let x = context.value_stack.pop_as::<i64>()?;
let result = x.swap_bytes();
let result = ((Runtime::bswap_32(x2 as u32) as u64) << 32
| Runtime::bswap_32(x1 as u32) as u64) as i64;
self.return_i64(result)
Ok(Some(result.into()))
}
fn user_panic(&mut self, context: InterpreterCallerContext)
@ -588,13 +641,10 @@ impl<'a, 'b> Runtime<'a, 'b> {
-> Result<Option<interpreter::RuntimeValue>, InterpreterError>
{
let return_ptr = context.value_stack.pop_as::<i32>()? as u32;
let block_hi = context.value_stack.pop_as::<i32>()? as u32;
let block_lo = context.value_stack.pop_as::<i32>()? as u32;
let block_num = context.value_stack.pop_as::<i64>()? as u64;
self.charge(|schedule| schedule.blockhash_gas as u64)?;
let block_num = (block_hi as u64) << 32 | block_lo as u64;
trace!("Requesting block hash for block #{}", block_num);
let hash = self.ext.blockhash(&U256::from(block_num));
@ -676,14 +726,14 @@ impl<'a, 'b> Runtime<'a, 'b> {
-> Result<Option<interpreter::RuntimeValue>, InterpreterError>
{
let timestamp = self.ext.env_info().timestamp as i64;
self.return_i64(timestamp)
Ok(Some(timestamp.into()))
}
fn block_number(&mut self, _context: InterpreterCallerContext)
-> Result<Option<interpreter::RuntimeValue>, InterpreterError>
{
let block_number: u64 = self.ext.env_info().number.into();
self.return_i64(block_number as i64)
let block_number = self.ext.env_info().number as i64;
Ok(Some(block_number.into()))
}
fn difficulty(&mut self, context: InterpreterCallerContext)
@ -708,25 +758,6 @@ impl<'a, 'b> Runtime<'a, 'b> {
Ok(None)
}
fn return_i64(&mut self, val: i64) -> Result<Option<interpreter::RuntimeValue>, InterpreterError> {
self.charge(|schedule| schedule.wasm.static_u64 as u64)?;
let uval = val as u64;
let hi = (uval >> 32) as i32;
let lo = (uval << 32 >> 32) as i32;
let target = self.instance.module("contract").ok_or(UserTrap::Other)?;
target.execute_export(
"setTempRet0",
self.execution_params().add_argument(
interpreter::RuntimeValue::I32(hi).into()
),
)?;
Ok(Some(
(lo).into()
))
}
pub fn execution_params(&mut self) -> interpreter::ExecutionParams<UserTrap> {
use super::env;
@ -749,6 +780,44 @@ impl<'a, 'b> Runtime<'a, 'b> {
pub fn ext(&mut self) -> &mut vm::Ext {
self.ext
}
pub fn log(&mut self, context: InterpreterCallerContext)
-> Result<Option<interpreter::RuntimeValue>, InterpreterError>
{
// signature is:
// pub fn elog(topic_ptr: *const u8, topic_count: u32, data_ptr: *const u8, data_len: u32);
let data_len = context.value_stack.pop_as::<i32>()? as u32;
let data_ptr = context.value_stack.pop_as::<i32>()? as u32;
let topic_count = context.value_stack.pop_as::<i32>()? as u32;
let topic_ptr = context.value_stack.pop_as::<i32>()? as u32;
if topic_count > 4 {
return Err(UserTrap::Log.into());
}
self.overflow_charge(|schedule|
{
let topics_gas = schedule.log_gas as u64 + schedule.log_topic_gas as u64 * topic_count as u64;
(schedule.log_data_gas as u64)
.checked_mul(schedule.log_data_gas as u64)
.and_then(|data_gas| data_gas.checked_add(topics_gas))
}
)?;
let mut topics: Vec<H256> = Vec::with_capacity(topic_count as usize);
topics.resize(topic_count as usize, H256::zero());
for i in 0..topic_count {
let offset = i.checked_mul(32).ok_or(UserTrap::MemoryAccessViolation)?
.checked_add(topic_ptr).ok_or(UserTrap::MemoryAccessViolation)?;
*topics.get_mut(i as usize)
.expect("topics is resized to `topic_count`, i is in 0..topic count iterator, get_mut uses i as an indexer, get_mut cannot fail; qed")
= H256::from(&self.memory.get(offset, 32)?[..]);
}
self.ext.log(topics, &self.memory.get(data_ptr, data_len as usize)?).map_err(|_| UserTrap::Log)?;
Ok(None)
}
}
impl<'a, 'b> interpreter::UserFunctionExecutor<UserTrap> for Runtime<'a, 'b> {
@ -756,10 +825,10 @@ impl<'a, 'b> interpreter::UserFunctionExecutor<UserTrap> for Runtime<'a, 'b> {
-> Result<Option<interpreter::RuntimeValue>, InterpreterError>
{
match name {
"_malloc" => {
"_ext_malloc" => {
self.malloc(context)
},
"_free" => {
"_ext_free" => {
// Since it is arena allocator, free does nothing
// todo: update if changed
self.user_noop(context)
@ -797,6 +866,15 @@ impl<'a, 'b> interpreter::UserFunctionExecutor<UserTrap> for Runtime<'a, 'b> {
"_emscripten_memcpy_big" => {
self.mem_copy(context)
},
"_ext_memcpy" => {
self.mem_copy(context)
},
"_ext_memmove" => {
self.mem_move(context)
},
"_ext_memset" => {
self.mem_set(context)
},
"_llvm_bswap_i64" => {
self.bitswap_i64(context)
},
@ -833,6 +911,9 @@ impl<'a, 'b> interpreter::UserFunctionExecutor<UserTrap> for Runtime<'a, 'b> {
"_value" => {
self.value(context)
},
"_elog" => {
self.log(context)
},
_ => {
trace!(target: "wasm", "Trapped due to unhandled function: '{}'", name);
Ok(self.unknown_trap(context)?)

View File

@ -60,7 +60,7 @@ fn empty() {
test_finalize(interpreter.exec(params, &mut ext)).unwrap()
};
assert_eq!(gas_left, U256::from(99_976));
assert_eq!(gas_left, U256::from(99_982));
}
// This test checks if the contract deserializes payload header properly.
@ -89,7 +89,6 @@ fn logger() {
test_finalize(interpreter.exec(params, &mut ext)).unwrap()
};
assert_eq!(gas_left, U256::from(15_177));
let address_val: H256 = address.into();
assert_eq!(
ext.store.get(&"0100000000000000000000000000000000000000000000000000000000000000".parse().unwrap()).expect("storage key to exist"),
@ -113,6 +112,7 @@ fn logger() {
U256::from(1_000_000_000),
"Logger sets 0x04 key to the trasferred value"
);
assert_eq!(gas_left, U256::from(19_143));
}
// This test checks if the contract can allocate memory and pass pointer to the result stream properly.
@ -142,13 +142,12 @@ fn identity() {
}
};
assert_eq!(gas_left, U256::from(99_695));
assert_eq!(
Address::from_slice(&result),
sender,
"Idenity test contract does not return the sender passed"
);
assert_eq!(gas_left, U256::from(99_844));
}
// Dispersion test sends byte array and expect the contract to 'disperse' the original elements with
@ -176,12 +175,12 @@ fn dispersion() {
}
};
assert_eq!(gas_left, U256::from(96_543));
assert_eq!(
result,
vec![0u8, 0, 125, 11, 197, 7, 255, 8, 19, 0]
);
assert_eq!(gas_left, U256::from(99_469));
}
#[test]
@ -205,12 +204,11 @@ fn suicide_not() {
}
};
assert_eq!(gas_left, U256::from(96_822));
assert_eq!(
result,
vec![0u8]
);
assert_eq!(gas_left, U256::from(99_724));
}
#[test]
@ -241,8 +239,8 @@ fn suicide() {
}
};
assert_eq!(gas_left, U256::from(96_580));
assert!(ext.suicides.contains(&refund));
assert_eq!(gas_left, U256::from(99_663));
}
#[test]
@ -272,7 +270,7 @@ fn create() {
assert!(ext.calls.contains(
&FakeCall {
call_type: FakeCallType::Create,
gas: U256::from(62_324),
gas: U256::from(65_903),
sender_address: None,
receive_address: None,
value: Some(1_000_000_000.into()),
@ -280,7 +278,7 @@ fn create() {
code_address: None,
}
));
assert_eq!(gas_left, U256::from(62_289));
assert_eq!(gas_left, U256::from(65_896));
}
@ -314,7 +312,7 @@ fn call_code() {
assert!(ext.calls.contains(
&FakeCall {
call_type: FakeCallType::Call,
gas: U256::from(95_585),
gas: U256::from(98_709),
sender_address: Some(sender),
receive_address: Some(receiver),
value: None,
@ -322,11 +320,11 @@ fn call_code() {
code_address: Some("0d13710000000000000000000000000000000000".parse().unwrap()),
}
));
assert_eq!(gas_left, U256::from(90_665));
// siphash result
let res = LittleEndian::read_u32(&result[..]);
assert_eq!(res, 4198595614);
assert_eq!(gas_left, U256::from(93_851));
}
#[test]
@ -359,7 +357,7 @@ fn call_static() {
assert!(ext.calls.contains(
&FakeCall {
call_type: FakeCallType::Call,
gas: U256::from(95_585),
gas: U256::from(98_709),
sender_address: Some(sender),
receive_address: Some(receiver),
value: None,
@ -367,11 +365,12 @@ fn call_static() {
code_address: Some("13077bfb00000000000000000000000000000000".parse().unwrap()),
}
));
assert_eq!(gas_left, U256::from(90_665));
// siphash result
let res = LittleEndian::read_u32(&result[..]);
assert_eq!(res, 317632590);
assert_eq!(gas_left, U256::from(93_851));
}
// Realloc test
@ -393,8 +392,8 @@ fn realloc() {
GasLeft::NeedsReturn { gas_left: gas, data: result, apply_state: _apply } => (gas, result.to_vec()),
}
};
assert_eq!(gas_left, U256::from(96_811));
assert_eq!(result, vec![0u8; 2]);
assert_eq!(gas_left, U256::from(99_787));
}
// Tests that contract's ability to read from a storage
@ -419,8 +418,8 @@ fn storage_read() {
}
};
assert_eq!(gas_left, U256::from(96_645));
assert_eq!(Address::from(&result[12..32]), address);
assert_eq!(gas_left, U256::from(99_702));
}
// Tests keccak calculation
@ -446,9 +445,97 @@ fn keccak() {
};
assert_eq!(H256::from_slice(&result), H256::from("68371d7e884c168ae2022c82bd837d51837718a7f7dfb7aa3f753074a35e1d87"));
assert_eq!(gas_left, U256::from(80_452));
assert_eq!(gas_left, U256::from(84_520));
}
// memcpy test.
#[test]
fn memcpy() {
::ethcore_logger::init_log();
let code = load_sample!("mem.wasm");
let mut test_payload = Vec::with_capacity(8192);
for i in 0..8192 {
test_payload.push((i % 255) as u8);
}
let mut data = vec![0u8];
data.extend(&test_payload);
let mut params = ActionParams::default();
params.gas = U256::from(100_000);
params.code = Some(Arc::new(code));
params.data = Some(data);
let mut ext = FakeExt::new();
let (gas_left, result) = {
let mut interpreter = wasm_interpreter();
let result = interpreter.exec(params, &mut ext).expect("Interpreter to execute without any errors");
match result {
GasLeft::Known(_) => { panic!("mem should return payload"); },
GasLeft::NeedsReturn { gas_left: gas, data: result, apply_state: _apply } => (gas, result.to_vec()),
}
};
assert_eq!(result, test_payload);
assert_eq!(gas_left, U256::from(75_324));
}
// memmove test.
#[test]
fn memmove() {
::ethcore_logger::init_log();
let code = load_sample!("mem.wasm");
let mut test_payload = Vec::with_capacity(8192);
for i in 0..8192 {
test_payload.push((i % 255) as u8);
}
let mut data = vec![1u8];
data.extend(&test_payload);
let mut params = ActionParams::default();
params.gas = U256::from(100_000);
params.code = Some(Arc::new(code));
params.data = Some(data);
let mut ext = FakeExt::new();
let (gas_left, result) = {
let mut interpreter = wasm_interpreter();
let result = interpreter.exec(params, &mut ext).expect("Interpreter to execute without any errors");
match result {
GasLeft::Known(_) => { panic!("mem should return payload"); },
GasLeft::NeedsReturn { gas_left: gas, data: result, apply_state: _apply } => (gas, result.to_vec()),
}
};
assert_eq!(result, test_payload);
assert_eq!(gas_left, U256::from(75_324));
}
// memset test
#[test]
fn memset() {
::ethcore_logger::init_log();
let code = load_sample!("mem.wasm");
let mut params = ActionParams::default();
params.gas = U256::from(100_000);
params.code = Some(Arc::new(code));
params.data = Some(vec![2u8, 228u8]);
let mut ext = FakeExt::new();
let (gas_left, result) = {
let mut interpreter = wasm_interpreter();
let result = interpreter.exec(params, &mut ext).expect("Interpreter to execute without any errors");
match result {
GasLeft::Known(_) => { panic!("mem should return payload"); },
GasLeft::NeedsReturn { gas_left: gas, data: result, apply_state: _apply } => (gas, result.to_vec()),
}
};
assert_eq!(result, vec![228u8; 8192]);
assert_eq!(gas_left, U256::from(75_324));
}
macro_rules! reqrep_test {
($name: expr, $input: expr) => {
@ -500,11 +587,11 @@ fn math_add() {
}
).expect("Interpreter to execute without any errors");
assert_eq!(gas_left, U256::from(94_666));
assert_eq!(
U256::from_dec_str("1888888888888888888888888888887").unwrap(),
(&result[..]).into()
);
assert_eq!(gas_left, U256::from(98_576));
}
// multiplication
@ -522,11 +609,11 @@ fn math_mul() {
}
).expect("Interpreter to execute without any errors");
assert_eq!(gas_left, U256::from(93_719));
assert_eq!(
U256::from_dec_str("888888888888888888888888888887111111111111111111111111111112").unwrap(),
(&result[..]).into()
);
assert_eq!(gas_left, U256::from(97_726));
}
// subtraction
@ -544,11 +631,11 @@ fn math_sub() {
}
).expect("Interpreter to execute without any errors");
assert_eq!(gas_left, U256::from(94_718));
assert_eq!(
U256::from_dec_str("111111111111111111111111111111").unwrap(),
(&result[..]).into()
);
assert_eq!(gas_left, U256::from(98_568));
}
// subtraction with overflow
@ -566,7 +653,10 @@ fn math_sub_with_overflow() {
}
);
assert_eq!(result, Err(vm::Error::Wasm("Wasm runtime error: User(Panic(\"arithmetic operation overflow\"))".into())));
match result {
Err(vm::Error::Wasm(_)) => {},
_ => panic!("Unexpected result {:?}", result),
}
}
#[test]
@ -583,11 +673,11 @@ fn math_div() {
}
).expect("Interpreter to execute without any errors");
assert_eq!(gas_left, U256::from(86_996));
assert_eq!(
U256::from_dec_str("1125000").unwrap(),
(&result[..]).into()
);
assert_eq!(gas_left, U256::from(91_564));
}
// This test checks the ability of wasm contract to invoke
@ -675,12 +765,11 @@ fn externs() {
"Gas limit requested and returned does not match"
);
assert_eq!(gas_left, U256::from(91_857));
assert_eq!(gas_left, U256::from(97_740));
}
#[test]
fn embedded_keccak() {
::ethcore_logger::init_log();
let mut code = load_sample!("keccak.wasm");
code.extend_from_slice(b"something");
@ -702,5 +791,40 @@ fn embedded_keccak() {
};
assert_eq!(H256::from_slice(&result), H256::from("68371d7e884c168ae2022c82bd837d51837718a7f7dfb7aa3f753074a35e1d87"));
assert_eq!(gas_left, U256::from(80_452));
assert_eq!(gas_left, U256::from(84_520));
}
/// This test checks the correctness of log extern
/// Target test puts one event with two topic [keccak(input), reverse(keccak(input))]
/// and reversed input as a data
#[test]
fn events() {
::ethcore_logger::init_log();
let code = load_sample!("events.wasm");
let mut params = ActionParams::default();
params.gas = U256::from(100_000);
params.code = Some(Arc::new(code));
params.data = Some(b"something".to_vec());
let mut ext = FakeExt::new();
let (gas_left, result) = {
let mut interpreter = wasm_interpreter();
let result = interpreter.exec(params, &mut ext).expect("Interpreter to execute without any errors");
match result {
GasLeft::Known(_) => { panic!("events should return payload"); },
GasLeft::NeedsReturn { gas_left: gas, data: result, apply_state: _apply } => (gas, result.to_vec()),
}
};
assert_eq!(ext.logs.len(), 1);
let log_entry = &ext.logs[0];
assert_eq!(log_entry.topics.len(), 2);
assert_eq!(&log_entry.topics[0], &H256::from("68371d7e884c168ae2022c82bd837d51837718a7f7dfb7aa3f753074a35e1d87"));
assert_eq!(&log_entry.topics[1], &H256::from("871d5ea37430753faab7dff7a7187783517d83bd822c02e28a164c887e1d3768"));
assert_eq!(&log_entry.data, b"gnihtemos");
assert_eq!(&result, b"gnihtemos");
assert_eq!(gas_left, U256::from(82_721));
}

View File

@ -462,7 +462,7 @@
<key>OVERWRITE_PERMISSIONS</key>
<false/>
<key>VERSION</key>
<string>1.8.2</string>
<string>1.8.3</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 2
!define VERSIONBUILD 3
!define ARGS ""
!define FIRST_START_ARGS "ui --mode=passive"
!define FIRST_START_ARGS "--mode=passive ui"
!addplugindir .\

Binary file not shown.

Before

Width:  |  Height:  |  Size: 66 KiB

After

Width:  |  Height:  |  Size: 114 KiB

View File

@ -24,6 +24,7 @@ usage! {
// Subcommands must start with cmd_ and have '_' in place of '-'
// Sub-subcommands must start with the name of the subcommand
// Arguments must start with arg_
// Flags must start with flag_
CMD cmd_ui {
"Manage ui",
@ -53,10 +54,6 @@ usage! {
CMD cmd_account_new {
"Create a new acount",
ARG arg_account_new_password: (Option<String>) = None,
"--password=[FILE]",
"Path to the password file",
}
CMD cmd_account_list {
@ -81,10 +78,6 @@ usage! {
{
"Import wallet",
ARG arg_wallet_import_password: (Option<String>) = None,
"--password=[FILE]",
"Path to the password file",
ARG arg_wallet_import_path: (Option<String>) = None,
"<PATH>",
"Path to the wallet",
@ -179,10 +172,6 @@ usage! {
{
"Sign",
ARG arg_signer_sign_password: (Option<String>) = None,
"--password=[FILE]",
"Path to the password file",
ARG arg_signer_sign_id: (Option<usize>) = None,
"[ID]",
"ID",
@ -244,7 +233,7 @@ usage! {
}
}
{
// Flags and arguments
// Global flags and arguments
["Operating Options"]
FLAG flag_public_node: (bool) = false, or |c: &Config| otry!(c.parity).public_node.clone(),
"--public-node",
@ -353,7 +342,6 @@ usage! {
ARG arg_password: (Vec<String>) = Vec::new(), or |c: &Config| otry!(c.account).password.clone(),
"--password=[FILE]...",
"Provide a file containing a password for unlocking an account. Leading and trailing whitespace is trimmed.",
["UI options"]
FLAG flag_force_ui: (bool) = false, or |c: &Config| otry!(c.ui).force.clone(),
"--force-ui",
@ -836,6 +824,10 @@ usage! {
"Target size of the whisper message pool in megabytes.",
["Legacy options"]
FLAG flag_warp: (bool) = false, or |_| None,
"--warp",
"Does nothing; warp sync is enabled by default.",
FLAG flag_dapps_apis_all: (bool) = false, or |_| None,
"--dapps-apis-all",
"Dapps server is merged with RPC server. Use --jsonrpc-apis.",
@ -1203,6 +1195,29 @@ mod tests {
use toml;
use clap::{ErrorKind as ClapErrorKind};
#[test]
fn should_accept_any_argument_order() {
let args = Args::parse(&["parity", "--no-warp", "account", "list"]).unwrap();
assert_eq!(args.flag_no_warp, true);
let args = Args::parse(&["parity", "account", "list", "--no-warp"]).unwrap();
assert_eq!(args.flag_no_warp, true);
let args = Args::parse(&["parity", "--chain=dev", "account", "list"]).unwrap();
assert_eq!(args.arg_chain, "dev");
let args = Args::parse(&["parity", "account", "list", "--chain=dev"]).unwrap();
assert_eq!(args.arg_chain, "dev");
}
#[test]
fn should_not_crash_on_warp() {
let args = Args::parse(&["parity", "--warp"]);
assert!(args.is_ok());
let args = Args::parse(&["parity", "account", "list", "--warp"]);
assert!(args.is_ok());
}
#[test]
fn should_reject_invalid_values() {
@ -1375,9 +1390,6 @@ mod tests {
arg_restore_file: None,
arg_tools_hash_file: None,
arg_account_new_password: None,
arg_signer_sign_password: None,
arg_wallet_import_password: None,
arg_signer_sign_id: None,
arg_signer_reject_id: None,
arg_dapp_path: None,
@ -1559,6 +1571,7 @@ mod tests {
arg_whisper_pool_size: 20,
// -- Legacy Options
flag_warp: false,
flag_geth: false,
flag_testnet: false,
flag_import_geth_keys: false,

View File

@ -153,7 +153,7 @@ macro_rules! usage {
use std::{fs, io, process};
use std::io::{Read, Write};
use util::version;
use clap::{Arg, App, SubCommand, AppSettings, Error as ClapError, ErrorKind as ClapErrorKind};
use clap::{Arg, App, SubCommand, AppSettings, ArgMatches as ClapArgMatches, Error as ClapError, ErrorKind as ClapErrorKind};
use helpers::replace_home;
use std::ffi::OsStr;
use std::collections::HashMap;
@ -503,6 +503,36 @@ macro_rules! usage {
args
}
pub fn hydrate_with_globals(self: &mut Self, matches: &ClapArgMatches) -> Result<(), ClapError> {
$(
$(
self.$flag = self.$flag || matches.is_present(stringify!($flag));
)*
$(
if let some @ Some(_) = return_if_parse_error!(if_option!(
$($arg_type_tt)+,
THEN {
if_option_vec!(
$($arg_type_tt)+,
THEN { values_t!(matches, stringify!($arg), inner_option_vec_type!($($arg_type_tt)+)) }
ELSE { value_t!(matches, stringify!($arg), inner_option_type!($($arg_type_tt)+)) }
)
}
ELSE {
if_vec!(
$($arg_type_tt)+,
THEN { values_t!(matches, stringify!($arg), inner_vec_type!($($arg_type_tt)+)) }
ELSE { value_t!(matches, stringify!($arg), $($arg_type_tt)+) }
)
}
)) {
self.$arg = some;
}
)*
)*
Ok(())
}
#[allow(unused_variables)] // the submatches of arg-less subcommands aren't used
pub fn parse<S: AsRef<str>>(command: &[S]) -> Result<Self, ClapError> {
@ -559,12 +589,14 @@ macro_rules! usage {
SubCommand::with_name(&underscore_to_hyphen!(&stringify!($subc)[4..]))
.about($subc_help)
.args(&subc_usages.get(stringify!($subc)).unwrap().iter().map(|u| Arg::from_usage(u).use_delimiter(false).allow_hyphen_values(true)).collect::<Vec<Arg>>())
.args(&usages.iter().map(|u| Arg::from_usage(u).use_delimiter(false).allow_hyphen_values(true)).collect::<Vec<Arg>>()) // accept global arguments at this position
$(
.setting(AppSettings::SubcommandRequired) // prevent from running `parity account`
.subcommand(
SubCommand::with_name(&underscore_to_hyphen!(&stringify!($subc_subc)[stringify!($subc).len()+1..]))
.about($subc_subc_help)
.args(&subc_usages.get(stringify!($subc_subc)).unwrap().iter().map(|u| Arg::from_usage(u).use_delimiter(false).allow_hyphen_values(true)).collect::<Vec<Arg>>())
.args(&usages.iter().map(|u| Arg::from_usage(u).use_delimiter(false).allow_hyphen_values(true)).collect::<Vec<Arg>>()) // accept global arguments at this position
)
)*
)
@ -572,36 +604,16 @@ macro_rules! usage {
.get_matches_from_safe(command.iter().map(|x| OsStr::new(x.as_ref())))?;
let mut raw_args : RawArgs = Default::default();
$(
$(
raw_args.$flag = matches.is_present(stringify!($flag));
)*
$(
raw_args.$arg = return_if_parse_error!(if_option!(
$($arg_type_tt)+,
THEN {
if_option_vec!(
$($arg_type_tt)+,
THEN { values_t!(matches, stringify!($arg), inner_option_vec_type!($($arg_type_tt)+)) }
ELSE { value_t!(matches, stringify!($arg), inner_option_type!($($arg_type_tt)+)) }
)
}
ELSE {
if_vec!(
$($arg_type_tt)+,
THEN { values_t!(matches, stringify!($arg), inner_vec_type!($($arg_type_tt)+)) }
ELSE { value_t!(matches, stringify!($arg), $($arg_type_tt)+) }
)
}
));
)*
)*
raw_args.hydrate_with_globals(&matches)?;
// Subcommands
$(
if let Some(submatches) = matches.subcommand_matches(&underscore_to_hyphen!(&stringify!($subc)[4..])) {
raw_args.$subc = true;
// Globals
raw_args.hydrate_with_globals(&submatches)?;
// Subcommand flags
$(
raw_args.$subc_flag = submatches.is_present(&stringify!($subc_flag));
@ -626,12 +638,13 @@ macro_rules! usage {
}
));
)*
// Sub-subcommands
$(
if let Some(subsubmatches) = submatches.subcommand_matches(&underscore_to_hyphen!(&stringify!($subc_subc)[stringify!($subc).len()+1..])) {
raw_args.$subc_subc = true;
// Globals
raw_args.hydrate_with_globals(&subsubmatches)?;
// Sub-subcommand flags
$(
raw_args.$subc_subc_flag = subsubmatches.is_present(&stringify!($subc_subc_flag));

View File

@ -143,7 +143,7 @@ impl Configuration {
if self.args.cmd_signer_new_token {
Cmd::SignerToken(ws_conf, ui_conf, logger_config.clone())
} else if self.args.cmd_signer_sign {
let pwfile = self.args.arg_signer_sign_password.map(|pwfile| {
let pwfile = self.args.arg_password.first().map(|pwfile| {
PathBuf::from(pwfile)
});
Cmd::SignerSign {
@ -180,7 +180,7 @@ impl Configuration {
iterations: self.args.arg_keys_iterations,
path: dirs.keys,
spec: spec,
password_file: self.args.arg_account_new_password.clone(),
password_file: self.args.arg_password.first().map(|x| x.to_owned()),
};
AccountCmd::New(new_acc)
} else if self.args.cmd_account_list {
@ -215,7 +215,7 @@ impl Configuration {
path: dirs.keys,
spec: spec,
wallet_path: self.args.arg_wallet_import_path.unwrap().clone(),
password_file: self.args.arg_wallet_import_password,
password_file: self.args.arg_password.first().map(|x| x.to_owned()),
};
Cmd::ImportPresaleWallet(presale_cmd)
} else if self.args.cmd_import {

View File

@ -37,6 +37,10 @@ impl fmt::Display for Deprecated {
pub fn find_deprecated(args: &Args) -> Vec<Deprecated> {
let mut result = vec![];
if args.flag_warp {
result.push(Deprecated::DoesNothing("--warp"));
}
if args.flag_jsonrpc {
result.push(Deprecated::DoesNothing("--jsonrpc"));
}
@ -117,6 +121,7 @@ mod tests {
assert_eq!(find_deprecated(&Args::default()), vec![]);
assert_eq!(find_deprecated(&{
let mut args = Args::default();
args.flag_warp = true;
args.flag_jsonrpc = true;
args.flag_rpc = true;
args.flag_jsonrpc_off = true;
@ -135,6 +140,7 @@ mod tests {
args.flag_dapps_apis_all = true;
args
}), vec![
Deprecated::DoesNothing("--warp"),
Deprecated::DoesNothing("--jsonrpc"),
Deprecated::DoesNothing("--rpc"),
Deprecated::Replaced("--jsonrpc-off", "--no-jsonrpc"),

View File

@ -302,9 +302,13 @@ 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))?;
// Make sure socket file can be created on unix-like OS.
// Windows pipe paths are not on the FS.
if !cfg!(windows) {
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) {

View File

@ -173,8 +173,10 @@ impl<'a> From<&'a EthHeader> for Header {
logs_bloom: h.log_bloom().into(),
timestamp: h.timestamp().into(),
difficulty: h.difficulty().into(),
seal_fields: h.seal().into_iter().map(Into::into).collect(),
extra_data: h.extra_data().into(),
seal_fields: h.view().decode_seal()
.expect("Client/Miner returns only valid headers. We only serialize headers from Client/Miner; qed")
.into_iter().map(Into::into).collect(),
}
}
}

View File

@ -14,7 +14,7 @@
// You should have received a copy of the GNU General Public License
// along with Parity. If not, see <http://www.gnu.org/licenses/>.
use v1::types::{Log, H160, H256, H2048, U256};
use v1::types::{Log, H160, H256, H2048, U256, U64};
use ethcore::receipt::{Receipt as EthReceipt, RichReceipt, LocalizedReceipt, TransactionOutcome};
/// Receipt
@ -51,7 +51,7 @@ pub struct Receipt {
pub logs_bloom: H2048,
/// Status code
#[serde(rename="status")]
pub status_code: Option<u8>,
pub status_code: Option<U64>,
}
impl Receipt {
@ -62,10 +62,10 @@ impl Receipt {
}
}
fn outcome_to_status_code(outcome: &TransactionOutcome) -> Option<u8> {
fn outcome_to_status_code(outcome: &TransactionOutcome) -> Option<U64> {
match *outcome {
TransactionOutcome::Unknown | TransactionOutcome::StateRoot(_) => None,
TransactionOutcome::StatusCode(ref code) => Some(*code),
TransactionOutcome::StatusCode(ref code) => Some((*code as u64).into()),
}
}
}
@ -131,7 +131,7 @@ mod tests {
#[test]
fn receipt_serialization() {
let s = r#"{"transactionHash":"0x0000000000000000000000000000000000000000000000000000000000000000","transactionIndex":"0x0","blockHash":"0xed76641c68a1c641aee09a94b3b471f4dc0316efe5ac19cf488e2674cf8d05b5","blockNumber":"0x4510c","cumulativeGasUsed":"0x20","gasUsed":"0x10","contractAddress":null,"logs":[{"address":"0x33990122638b9132ca29c723bdf037f1a891a70c","topics":["0xa6697e974e6a320f454390be03f74955e8978f1a6971ea6730542e37b66179bc","0x4861736852656700000000000000000000000000000000000000000000000000"],"data":"0x","blockHash":"0xed76641c68a1c641aee09a94b3b471f4dc0316efe5ac19cf488e2674cf8d05b5","blockNumber":"0x4510c","transactionHash":"0x0000000000000000000000000000000000000000000000000000000000000000","transactionIndex":"0x0","logIndex":"0x1","transactionLogIndex":null,"type":"mined"}],"root":"0x000000000000000000000000000000000000000000000000000000000000000a","logsBloom":"0x0000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000f","status":null}"#;
let s = r#"{"transactionHash":"0x0000000000000000000000000000000000000000000000000000000000000000","transactionIndex":"0x0","blockHash":"0xed76641c68a1c641aee09a94b3b471f4dc0316efe5ac19cf488e2674cf8d05b5","blockNumber":"0x4510c","cumulativeGasUsed":"0x20","gasUsed":"0x10","contractAddress":null,"logs":[{"address":"0x33990122638b9132ca29c723bdf037f1a891a70c","topics":["0xa6697e974e6a320f454390be03f74955e8978f1a6971ea6730542e37b66179bc","0x4861736852656700000000000000000000000000000000000000000000000000"],"data":"0x","blockHash":"0xed76641c68a1c641aee09a94b3b471f4dc0316efe5ac19cf488e2674cf8d05b5","blockNumber":"0x4510c","transactionHash":"0x0000000000000000000000000000000000000000000000000000000000000000","transactionIndex":"0x0","logIndex":"0x1","transactionLogIndex":null,"type":"mined"}],"root":"0x000000000000000000000000000000000000000000000000000000000000000a","logsBloom":"0x0000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000f","status":"0x1"}"#;
let receipt = Receipt {
transaction_hash: Some(0.into()),
@ -158,7 +158,7 @@ mod tests {
}],
logs_bloom: 15.into(),
state_root: Some(10.into()),
status_code: None,
status_code: Some(1u64.into()),
};
let serialized = serde_json::to_string(&receipt).unwrap();

View File

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

View File

@ -315,8 +315,9 @@ void OpenUI()
STARTUPINFO startupInfo = { sizeof(STARTUPINFO) };
LPWSTR args = new WCHAR[lstrlen(commandLineFiltered) + MAX_PATH + 2];
lstrcpy(args, L"parity.exe ui ");
lstrcpy(args, L"parity.exe ");
lstrcat(args, commandLineFiltered);
lstrcat(args, L" ui");
CreateProcess(path, args, nullptr, nullptr, false, CREATE_NO_WINDOW, nullptr, nullptr, &startupInfo, &procInfo);
}