Merge pull request #7043 from paritytech/beta-backport
backports to beta
This commit is contained in:
commit
b49c44a198
84
Cargo.lock
generated
84
Cargo.lock
generated
@ -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"
|
||||
|
@ -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
|
@ -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();
|
||||
|
@ -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]
|
||||
|
@ -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)]
|
||||
|
@ -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,
|
||||
}
|
||||
|
@ -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)
|
||||
),
|
||||
];
|
||||
|
||||
|
@ -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)?)
|
||||
|
@ -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));
|
||||
}
|
@ -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>
|
||||
|
@ -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 .\
|
||||
|
||||
|
BIN
nsis/logo.ico
BIN
nsis/logo.ico
Binary file not shown.
Before Width: | Height: | Size: 66 KiB After Width: | Height: | Size: 114 KiB |
@ -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,
|
||||
|
@ -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));
|
||||
|
@ -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 {
|
||||
|
@ -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"),
|
||||
|
@ -302,10 +302,14 @@ 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);
|
||||
// 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) {
|
||||
Ok(server) => Ok(Some(server)),
|
||||
|
@ -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(),
|
||||
}
|
||||
}
|
||||
}
|
||||
|
@ -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();
|
||||
|
@ -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"
|
||||
|
||||
|
@ -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);
|
||||
}
|
||||
|
||||
|
Loading…
Reference in New Issue
Block a user