Merge branch 'master' into new-jsonrpc

This commit is contained in:
Tomasz Drwięga 2017-03-16 15:51:00 +01:00
commit 44052e7d8d
No known key found for this signature in database
GPG Key ID: D066F497E62CAF66
67 changed files with 832 additions and 336 deletions

View File

@ -26,14 +26,14 @@ linux-stable:
- cargo build -j $(nproc) --release -p ethstore
- cargo build -j $(nproc) --release -p ethkey
- strip target/release/parity
- strip target/release/evm
- strip target/release/parity-evm
- strip target/release/ethstore
- strip target/release/ethkey
- export SHA3=$(target/release/parity tools hash target/release/parity)
- md5sum target/release/parity > parity.md5
- sh scripts/deb-build.sh amd64
- cp target/release/parity deb/usr/bin/parity
- cp target/release/evm deb/usr/bin/evm
- cp target/release/parity-evm deb/usr/bin/parity-evm
- cp target/release/ethstore deb/usr/bin/ethstore
- cp target/release/ethkey deb/usr/bin/ethkey
- export VER=$(grep -m 1 version Cargo.toml | awk '{print $3}' | tr -d '"' | tr -d "\n")
@ -55,9 +55,9 @@ linux-stable:
artifacts:
paths:
- target/release/parity
- target/release/parity/evmbin
- target/release/parity/ethstore
- target/release/parity/ethkey
- target/release/parity-evm
- target/release/ethstore
- target/release/ethkey
name: "stable-x86_64-unknown-linux-gnu_parity"
linux-stable-debian:
stage: build
@ -73,14 +73,14 @@ linux-stable-debian:
- cargo build -j $(nproc) --release -p ethstore
- cargo build -j $(nproc) --release -p ethkey
- strip target/release/parity
- strip target/release/evm
- strip target/release/parity-evm
- strip target/release/ethstore
- strip target/release/ethkey
- export SHA3=$(target/release/parity tools hash target/release/parity)
- md5sum target/release/parity > parity.md5
- sh scripts/deb-build.sh amd64
- cp target/release/parity deb/usr/bin/parity
- cp target/release/evm deb/usr/bin/evm
- cp target/release/parity-evm deb/usr/bin/parity-evm
- cp target/release/ethstore deb/usr/bin/ethstore
- cp target/release/ethkey deb/usr/bin/ethkey
- export VER=$(grep -m 1 version Cargo.toml | awk '{print $3}' | tr -d '"' | tr -d "\n")
@ -506,15 +506,16 @@ docker-build:
test-coverage:
stage: test
only:
- coverage
- master
script:
- git submodule update --init --recursive
- rm -rf target/*
- rm -rf js/.coverage
- scripts/cov.sh
- COVERAGE=$(grep -Po 'covered":.*?[^\\]"' target/kcov/index.json | grep "[0-9]*\.[0-9]" -o)
- echo "Coverage:" $COVERAGE
# - COVERAGE=$(grep -Po 'covered":.*?[^\\]"' target/cov/index.json | grep "[0-9]*\.[0-9]" -o)
# - echo "Coverage:" $COVERAGE
tags:
- kcov
allow_failure: true
test-darwin:
stage: test
only:

69
Cargo.lock generated
View File

@ -31,7 +31,7 @@ dependencies = [
"isatty 0.1.1 (registry+https://github.com/rust-lang/crates.io-index)",
"jsonrpc-core 7.0.0 (git+https://github.com/ethcore/jsonrpc.git)",
"log 0.3.6 (registry+https://github.com/rust-lang/crates.io-index)",
"num_cpus 0.2.11 (registry+https://github.com/rust-lang/crates.io-index)",
"num_cpus 1.2.0 (registry+https://github.com/rust-lang/crates.io-index)",
"number_prefix 0.2.5 (registry+https://github.com/rust-lang/crates.io-index)",
"parity-hash-fetch 1.7.0",
"parity-ipfs-api 1.7.0",
@ -44,6 +44,7 @@ dependencies = [
"rpassword 0.2.2 (registry+https://github.com/rust-lang/crates.io-index)",
"rpc-cli 1.4.0",
"rustc-serialize 0.3.19 (registry+https://github.com/rust-lang/crates.io-index)",
"rustc_version 0.2.0 (registry+https://github.com/rust-lang/crates.io-index)",
"semver 0.5.1 (registry+https://github.com/rust-lang/crates.io-index)",
"serde 0.9.6 (registry+https://github.com/rust-lang/crates.io-index)",
"serde_json 0.9.5 (registry+https://github.com/rust-lang/crates.io-index)",
@ -356,7 +357,7 @@ version = "0.5.6"
source = "git+https://github.com/ethcore/rust-secp256k1#98ad9b9ecae44a563efdd64273bcebc6b4ed81c6"
dependencies = [
"arrayvec 0.3.16 (registry+https://github.com/rust-lang/crates.io-index)",
"gcc 0.3.35 (registry+https://github.com/rust-lang/crates.io-index)",
"gcc 0.3.43 (registry+https://github.com/rust-lang/crates.io-index)",
"libc 0.2.16 (registry+https://github.com/rust-lang/crates.io-index)",
"rand 0.3.14 (registry+https://github.com/rust-lang/crates.io-index)",
"rustc-serialize 0.3.19 (registry+https://github.com/rust-lang/crates.io-index)",
@ -414,7 +415,7 @@ dependencies = [
"linked-hash-map 0.3.0 (registry+https://github.com/rust-lang/crates.io-index)",
"log 0.3.6 (registry+https://github.com/rust-lang/crates.io-index)",
"lru-cache 0.1.0 (registry+https://github.com/rust-lang/crates.io-index)",
"num_cpus 0.2.11 (registry+https://github.com/rust-lang/crates.io-index)",
"num_cpus 1.2.0 (registry+https://github.com/rust-lang/crates.io-index)",
"rand 0.3.14 (registry+https://github.com/rust-lang/crates.io-index)",
"rlp 0.1.0",
"rust-crypto 0.2.36 (registry+https://github.com/rust-lang/crates.io-index)",
@ -892,10 +893,10 @@ dependencies = [
[[package]]
name = "gcc"
version = "0.3.35"
version = "0.3.43"
source = "registry+https://github.com/rust-lang/crates.io-index"
dependencies = [
"rayon 0.4.2 (registry+https://github.com/rust-lang/crates.io-index)",
"rayon 0.6.0 (registry+https://github.com/rust-lang/crates.io-index)",
]
[[package]]
@ -942,7 +943,7 @@ name = "hidapi"
version = "0.3.1"
source = "git+https://github.com/ethcore/hidapi-rs#9a127c1dca7e327e4fdd428406a76c9f5ef48563"
dependencies = [
"gcc 0.3.35 (registry+https://github.com/rust-lang/crates.io-index)",
"gcc 0.3.43 (registry+https://github.com/rust-lang/crates.io-index)",
"libc 0.2.16 (registry+https://github.com/rust-lang/crates.io-index)",
]
@ -1245,7 +1246,7 @@ name = "libusb-sys"
version = "0.2.3"
source = "git+https://github.com/ethcore/libusb-sys#c10b1180646c9dc3f23a9b6bb825abcd3b7487ce"
dependencies = [
"gcc 0.3.35 (registry+https://github.com/rust-lang/crates.io-index)",
"gcc 0.3.43 (registry+https://github.com/rust-lang/crates.io-index)",
"libc 0.2.16 (registry+https://github.com/rust-lang/crates.io-index)",
]
@ -1309,7 +1310,7 @@ name = "miniz-sys"
version = "0.1.7"
source = "registry+https://github.com/rust-lang/crates.io-index"
dependencies = [
"gcc 0.3.35 (registry+https://github.com/rust-lang/crates.io-index)",
"gcc 0.3.43 (registry+https://github.com/rust-lang/crates.io-index)",
"libc 0.2.16 (registry+https://github.com/rust-lang/crates.io-index)",
]
@ -1445,7 +1446,7 @@ name = "nanomsg-sys"
version = "0.5.0"
source = "git+https://github.com/ethcore/nanomsg.rs.git#c40fe442c9afaea5b38009a3d992ca044dcceb00"
dependencies = [
"gcc 0.3.35 (registry+https://github.com/rust-lang/crates.io-index)",
"gcc 0.3.43 (registry+https://github.com/rust-lang/crates.io-index)",
"libc 0.2.16 (registry+https://github.com/rust-lang/crates.io-index)",
]
@ -1578,14 +1579,6 @@ name = "num-traits"
version = "0.1.32"
source = "registry+https://github.com/rust-lang/crates.io-index"
[[package]]
name = "num_cpus"
version = "0.2.11"
source = "registry+https://github.com/rust-lang/crates.io-index"
dependencies = [
"libc 0.2.16 (registry+https://github.com/rust-lang/crates.io-index)",
]
[[package]]
name = "num_cpus"
version = "1.2.0"
@ -1768,7 +1761,7 @@ dependencies = [
[[package]]
name = "parity-ui-precompiled"
version = "1.4.0"
source = "git+https://github.com/ethcore/js-precompiled.git#24514f56ade650f54b97c2cff4e27d798b274e41"
source = "git+https://github.com/ethcore/js-precompiled.git#547a5352d779bc7821a7a2ec14c6d480833aeabb"
dependencies = [
"parity-dapps-glue 1.4.0 (registry+https://github.com/rust-lang/crates.io-index)",
]
@ -1939,11 +1932,12 @@ dependencies = [
[[package]]
name = "rayon"
version = "0.4.2"
version = "0.6.0"
source = "registry+https://github.com/rust-lang/crates.io-index"
dependencies = [
"deque 0.3.1 (registry+https://github.com/rust-lang/crates.io-index)",
"num_cpus 0.2.11 (registry+https://github.com/rust-lang/crates.io-index)",
"libc 0.2.16 (registry+https://github.com/rust-lang/crates.io-index)",
"num_cpus 1.2.0 (registry+https://github.com/rust-lang/crates.io-index)",
"rand 0.3.14 (registry+https://github.com/rust-lang/crates.io-index)",
]
@ -2011,7 +2005,7 @@ name = "rocksdb-sys"
version = "0.3.0"
source = "git+https://github.com/ethcore/rust-rocksdb#64c63ccbe1f62c2e2b39262486f9ba813793af58"
dependencies = [
"gcc 0.3.35 (registry+https://github.com/rust-lang/crates.io-index)",
"gcc 0.3.43 (registry+https://github.com/rust-lang/crates.io-index)",
"libc 0.2.16 (registry+https://github.com/rust-lang/crates.io-index)",
]
@ -2066,7 +2060,7 @@ name = "rust-crypto"
version = "0.2.36"
source = "registry+https://github.com/rust-lang/crates.io-index"
dependencies = [
"gcc 0.3.35 (registry+https://github.com/rust-lang/crates.io-index)",
"gcc 0.3.43 (registry+https://github.com/rust-lang/crates.io-index)",
"libc 0.2.16 (registry+https://github.com/rust-lang/crates.io-index)",
"rand 0.3.14 (registry+https://github.com/rust-lang/crates.io-index)",
"rustc-serialize 0.3.19 (registry+https://github.com/rust-lang/crates.io-index)",
@ -2086,6 +2080,14 @@ dependencies = [
"semver 0.1.20 (registry+https://github.com/rust-lang/crates.io-index)",
]
[[package]]
name = "rustc_version"
version = "0.2.0"
source = "registry+https://github.com/rust-lang/crates.io-index"
dependencies = [
"semver 0.6.0 (registry+https://github.com/rust-lang/crates.io-index)",
]
[[package]]
name = "schannel"
version = "0.1.1"
@ -2155,6 +2157,14 @@ dependencies = [
"semver-parser 0.6.1 (registry+https://github.com/rust-lang/crates.io-index)",
]
[[package]]
name = "semver"
version = "0.6.0"
source = "registry+https://github.com/rust-lang/crates.io-index"
dependencies = [
"semver-parser 0.7.0 (registry+https://github.com/rust-lang/crates.io-index)",
]
[[package]]
name = "semver-parser"
version = "0.6.1"
@ -2164,6 +2174,11 @@ dependencies = [
"regex 0.1.68 (registry+https://github.com/rust-lang/crates.io-index)",
]
[[package]]
name = "semver-parser"
version = "0.7.0"
source = "registry+https://github.com/rust-lang/crates.io-index"
[[package]]
name = "serde"
version = "0.9.6"
@ -2218,7 +2233,7 @@ source = "registry+https://github.com/rust-lang/crates.io-index"
name = "sha3"
version = "0.1.0"
dependencies = [
"gcc 0.3.35 (registry+https://github.com/rust-lang/crates.io-index)",
"gcc 0.3.43 (registry+https://github.com/rust-lang/crates.io-index)",
]
[[package]]
@ -2714,7 +2729,7 @@ dependencies = [
"checksum flate2 0.2.14 (registry+https://github.com/rust-lang/crates.io-index)" = "3eeb481e957304178d2e782f2da1257f1434dfecbae883bafb61ada2a9fea3bb"
"checksum futures 0.1.11 (registry+https://github.com/rust-lang/crates.io-index)" = "8e51e7f9c150ba7fd4cee9df8bf6ea3dea5b63b68955ddad19ccd35b71dcfb4d"
"checksum futures-cpupool 0.1.2 (registry+https://github.com/rust-lang/crates.io-index)" = "bb982bb25cd8fa5da6a8eb3a460354c984ff1113da82bcb4f0b0862b5795db82"
"checksum gcc 0.3.35 (registry+https://github.com/rust-lang/crates.io-index)" = "91ecd03771effb0c968fd6950b37e89476a578aaf1c70297d8e92b6516ec3312"
"checksum gcc 0.3.43 (registry+https://github.com/rust-lang/crates.io-index)" = "c07c758b972368e703a562686adb39125707cc1ef3399da8c019fc6c2498a75d"
"checksum gdi32-sys 0.2.0 (registry+https://github.com/rust-lang/crates.io-index)" = "0912515a8ff24ba900422ecda800b52f4016a56251922d397c576bf92c690518"
"checksum glob 0.2.11 (registry+https://github.com/rust-lang/crates.io-index)" = "8be18de09a56b60ed0edf84bc9df007e30040691af7acd1c41874faac5895bfb"
"checksum hamming 0.1.3 (registry+https://github.com/rust-lang/crates.io-index)" = "65043da274378d68241eb9a8f8f8aa54e349136f7b8e12f63e3ef44043cc30e1"
@ -2783,7 +2798,6 @@ dependencies = [
"checksum num-iter 0.1.32 (registry+https://github.com/rust-lang/crates.io-index)" = "287a1c9969a847055e1122ec0ea7a5c5d6f72aad97934e131c83d5c08ab4e45c"
"checksum num-rational 0.1.32 (registry+https://github.com/rust-lang/crates.io-index)" = "48cdcc9ff4ae2a8296805ac15af88b3d88ce62128ded0cb74ffb63a587502a84"
"checksum num-traits 0.1.32 (registry+https://github.com/rust-lang/crates.io-index)" = "51eab148f171aefad295f8cece636fc488b9b392ef544da31ea4b8ef6b9e9c39"
"checksum num_cpus 0.2.11 (registry+https://github.com/rust-lang/crates.io-index)" = "51fedae97a05f7353612fe017ab705a37e6db8f4d67c5c6fe739a9e70d6eed09"
"checksum num_cpus 1.2.0 (registry+https://github.com/rust-lang/crates.io-index)" = "55aabf4e2d6271a2e4e4c0f2ea1f5b07cc589cc1a9e9213013b54a76678ca4f3"
"checksum number_prefix 0.2.5 (registry+https://github.com/rust-lang/crates.io-index)" = "084d05f4bf60621a9ac9bde941a410df548f4de9545f06e5ee9d3aef4b97cd77"
"checksum odds 0.2.12 (registry+https://github.com/rust-lang/crates.io-index)" = "b28c06e81b0f789122d415d6394b5fe849bde8067469f4c2980d3cdc10c78ec1"
@ -2814,7 +2828,7 @@ dependencies = [
"checksum quine-mc_cluskey 0.2.2 (registry+https://github.com/rust-lang/crates.io-index)" = "a6683b0e23d80813b1a535841f0048c1537d3f86d63c999e8373b39a9b0eb74a"
"checksum quote 0.3.10 (registry+https://github.com/rust-lang/crates.io-index)" = "6732e32663c9c271bfc7c1823486b471f18c47a2dbf87c066897b7b51afc83be"
"checksum rand 0.3.14 (registry+https://github.com/rust-lang/crates.io-index)" = "2791d88c6defac799c3f20d74f094ca33b9332612d9aef9078519c82e4fe04a5"
"checksum rayon 0.4.2 (registry+https://github.com/rust-lang/crates.io-index)" = "655df67c314c30fa3055a365eae276eb88aa4f3413a352a1ab32c1320eda41ea"
"checksum rayon 0.6.0 (registry+https://github.com/rust-lang/crates.io-index)" = "50c575b58c2b109e2fbc181820cbe177474f35610ff9e357dc75f6bac854ffbf"
"checksum regex 0.1.68 (registry+https://github.com/rust-lang/crates.io-index)" = "b4329b8928a284580a1c63ec9d846b12f6d3472317243ff7077aff11f23f2b29"
"checksum regex-syntax 0.3.1 (registry+https://github.com/rust-lang/crates.io-index)" = "841591b1e05609a643e3b4d0045fce04f701daba7151ddcd3ad47b080693d5a9"
"checksum reqwest 0.4.0 (registry+https://github.com/rust-lang/crates.io-index)" = "3bef9ed8fdfcc30947d6b774938dc0c3f369a474efe440df2c7f278180b2d2e6"
@ -2827,6 +2841,7 @@ dependencies = [
"checksum rust-crypto 0.2.36 (registry+https://github.com/rust-lang/crates.io-index)" = "f76d05d3993fd5f4af9434e8e436db163a12a9d40e1a58a726f27a01dfd12a2a"
"checksum rustc-serialize 0.3.19 (registry+https://github.com/rust-lang/crates.io-index)" = "6159e4e6e559c81bd706afe9c8fd68f547d3e851ce12e76b1de7914bab61691b"
"checksum rustc_version 0.1.7 (registry+https://github.com/rust-lang/crates.io-index)" = "c5f5376ea5e30ce23c03eb77cbe4962b988deead10910c372b226388b594c084"
"checksum rustc_version 0.2.0 (registry+https://github.com/rust-lang/crates.io-index)" = "1e114e275f7c9b5d50bb52b28f9aac1921209f02aa6077c8b255e21eefaf8ffa"
"checksum schannel 0.1.1 (registry+https://github.com/rust-lang/crates.io-index)" = "167852e03fcd0029c3ddebb5afb0715b2996f6e262b2c2aceaa7cd84edd4b158"
"checksum scoped-tls 0.1.0 (registry+https://github.com/rust-lang/crates.io-index)" = "f417c22df063e9450888a7561788e9bd46d3bb3c1466435b4eccb903807f147d"
"checksum secur32-sys 0.2.0 (registry+https://github.com/rust-lang/crates.io-index)" = "3f412dfa83308d893101dd59c10d6fda8283465976c28c287c5c855bf8d216bc"
@ -2835,7 +2850,9 @@ dependencies = [
"checksum semver 0.1.20 (registry+https://github.com/rust-lang/crates.io-index)" = "d4f410fedcf71af0345d7607d246e7ad15faaadd49d240ee3b24e5dc21a820ac"
"checksum semver 0.2.3 (registry+https://github.com/rust-lang/crates.io-index)" = "2d5b7638a1f03815d94e88cb3b3c08e87f0db4d683ef499d1836aaf70a45623f"
"checksum semver 0.5.1 (registry+https://github.com/rust-lang/crates.io-index)" = "ae2ff60ecdb19c255841c066cbfa5f8c2a4ada1eb3ae47c77ab6667128da71f5"
"checksum semver 0.6.0 (registry+https://github.com/rust-lang/crates.io-index)" = "7a3186ec9e65071a2095434b1f5bb24838d4e8e130f584c790f6033c79943537"
"checksum semver-parser 0.6.1 (registry+https://github.com/rust-lang/crates.io-index)" = "e88e43a5a74dd2a11707f9c21dfd4a423c66bd871df813227bb0a3e78f3a1ae9"
"checksum semver-parser 0.7.0 (registry+https://github.com/rust-lang/crates.io-index)" = "388a1df253eca08550bef6c72392cfe7c30914bf41df5269b68cbd6ff8f570a3"
"checksum serde 0.9.6 (registry+https://github.com/rust-lang/crates.io-index)" = "0ae9a3c8b07c09dbe43022486d55a18c629a0618d2241e49829aaef9b6d862f9"
"checksum serde_codegen_internals 0.13.0 (registry+https://github.com/rust-lang/crates.io-index)" = "c3172bf2940b975c0e4f6ab42a511c0a4407d4f46ccef87a9d3615db5c26fa96"
"checksum serde_derive 0.9.6 (registry+https://github.com/rust-lang/crates.io-index)" = "ecc6e0379ca933ece58302d2d3034443f06fbf38fd535857c1dc516195cbc3bf"

View File

@ -4,6 +4,7 @@ name = "parity"
version = "1.7.0"
license = "GPL-3.0"
authors = ["Parity Technologies <admin@parity.io>"]
build = "build.rs"
[dependencies]
log = "0.3"
@ -11,7 +12,7 @@ env_logger = "0.3"
rustc-serialize = "0.3"
docopt = "0.6"
time = "0.1"
num_cpus = "0.2"
num_cpus = "1.2"
number_prefix = "0.2"
rpassword = "0.2.1"
semver = "0.5"
@ -52,6 +53,9 @@ ethcore-dapps = { path = "dapps", optional = true }
clippy = { version = "0.0.103", optional = true}
ethcore-secretstore = { path = "secret_store", optional = true }
[build-dependencies]
rustc_version = "0.2"
[dev-dependencies]
ethcore-ipc-tests = { path = "ipc/tests" }

View File

@ -14,28 +14,22 @@
// You should have received a copy of the GNU General Public License
// along with Parity. If not, see <http://www.gnu.org/licenses/>.
//! `TraceDB` errors.
extern crate rustc_version;
use std::fmt::{Display, Formatter, Error as FmtError};
const MIN_RUSTC_VERSION: &'static str = "1.15.1";
const RESYNC_ERR: &'static str =
"Your current parity installation has synced without transaction tracing.
To use Parity with transaction tracing, you'll need to resync with tracing.
To do this, remove or move away your current database and restart parity. e.g.:
fn main() {
let is = rustc_version::version().unwrap();
let required = MIN_RUSTC_VERSION.parse().unwrap();
assert!(is >= required, format!("
> mv ~/.parity/906a34e69aec8c0d /tmp
> parity";
It looks like you are compiling Parity with an old rustc compiler {}.
Parity requires version {}. Please update your compiler.
If you use rustup, try this:
/// `TraceDB` errors.
#[derive(Debug)]
pub enum Error {
/// Returned when tracing is enabled,
/// but database does not contain traces of old transactions.
ResyncRequired,
}
impl Display for Error {
fn fmt(&self, f: &mut Formatter) -> Result<(), FmtError> {
write!(f, "{}", RESYNC_ERR)
}
rustup update stable
and try building Parity again.
", is, required));
}

View File

@ -15,7 +15,7 @@ log = "0.3"
env_logger = "0.3"
rustc-serialize = "0.3"
rust-crypto = "0.2.34"
num_cpus = "0.2"
num_cpus = "1.2"
crossbeam = "0.2.9"
lazy_static = "0.2"
bloomchain = "0.1"

View File

@ -30,7 +30,8 @@
"params": {
"maximumExtraDataSize": "0x20",
"minGasLimit": "0x1388",
"networkID" : "0x2A"
"networkID" : "0x2A",
"validateReceipts" : false
},
"genesis": {
"seal": {

View File

@ -139,6 +139,7 @@
}
},
"params": {
"eip98Transition": "0x7fffffffffffffff",
"accountStartNonce": "0x00",
"maximumExtraDataSize": "0x20",
"minGasLimit": "0x1388",

View File

@ -553,7 +553,6 @@ pub fn enact(
b.set_extra_data(header.extra_data().clone()).unwrap_or_else(|e| warn!("Couldn't set extradata: {}. Ignoring.", e));
b.set_uncles_hash(header.uncles_hash().clone());
b.set_transactions_root(header.transactions_root().clone());
b.set_receipts_root(header.receipts_root().clone());
push_transactions(&mut b, transactions)?;
for u in uncles {

View File

@ -393,7 +393,7 @@ impl Client {
})?;
// Final Verification
if let Err(e) = self.verifier.verify_block_final(header, locked_block.block().header()) {
if let Err(e) = self.verifier.verify_block_final(header, locked_block.block().header(), self.engine().params().validate_receipts) {
warn!(target: "client", "Stage 4 block verification failed for #{} ({})\nError: {:?}", header.number(), header.hash(), e);
return Err(());
}

View File

@ -14,7 +14,6 @@
// You should have received a copy of the GNU General Public License
// along with Parity. If not, see <http://www.gnu.org/licenses/>.
use trace::Error as TraceError;
use util::UtilError;
use std::fmt::{Display, Formatter, Error as FmtError};
@ -23,8 +22,6 @@ use util::trie::TrieError;
/// Client configuration errors.
#[derive(Debug)]
pub enum Error {
/// TraceDB configuration error.
Trace(TraceError),
/// TrieDB-related error.
Trie(TrieError),
/// Database error
@ -33,12 +30,6 @@ pub enum Error {
Util(UtilError),
}
impl From<TraceError> for Error {
fn from(err: TraceError) -> Self {
Error::Trace(err)
}
}
impl From<TrieError> for Error {
fn from(err: TrieError) -> Self {
Error::Trie(err)
@ -60,7 +51,6 @@ impl<E> From<Box<E>> for Error where Error: From<E> {
impl Display for Error {
fn fmt(&self, f: &mut Formatter) -> Result<(), FmtError> {
match *self {
Error::Trace(ref err) => write!(f, "{}", err),
Error::Trie(ref err) => write!(f, "{}", err),
Error::Util(ref err) => write!(f, "{}", err),
Error::Database(ref s) => write!(f, "Database error: {}", s),

View File

@ -90,6 +90,8 @@ pub struct MinerOptions {
pub reseal_on_own_tx: bool,
/// Minimum period between transaction-inspired reseals.
pub reseal_min_period: Duration,
/// Maximum period between blocks (enables force sealing after that).
pub reseal_max_period: Duration,
/// Maximum amount of gas to bother considering for block insertion.
pub tx_gas_limit: U256,
/// Maximum size of the transaction queue.
@ -123,6 +125,7 @@ impl Default for MinerOptions {
tx_queue_strategy: PrioritizationStrategy::GasPriceOnly,
pending_set: PendingSet::AlwaysQueue,
reseal_min_period: Duration::from_secs(2),
reseal_max_period: Duration::from_secs(120),
work_queue_size: 20,
enable_resubmission: true,
tx_queue_banning: Banning::Disabled,
@ -212,6 +215,7 @@ pub struct Miner {
transaction_queue: Arc<Mutex<BanningTransactionQueue>>,
sealing_work: Mutex<SealingWork>,
next_allowed_reseal: Mutex<Instant>,
next_mandatory_reseal: RwLock<Instant>,
sealing_block_last_request: Mutex<u64>,
// for sealing...
options: MinerOptions,
@ -268,6 +272,7 @@ impl Miner {
Miner {
transaction_queue: Arc::new(Mutex::new(txq)),
next_allowed_reseal: Mutex::new(Instant::now()),
next_mandatory_reseal: RwLock::new(Instant::now() + options.reseal_max_period),
sealing_block_last_request: Mutex::new(0),
sealing_work: Mutex::new(SealingWork{
queue: UsingQueue::new(options.work_queue_size),
@ -298,7 +303,9 @@ impl Miner {
}
fn forced_sealing(&self) -> bool {
self.options.force_sealing || !self.options.new_work_notify.is_empty()
self.options.force_sealing
|| !self.options.new_work_notify.is_empty()
|| Instant::now() > *self.next_mandatory_reseal.read()
}
/// Clear all pending block states
@ -482,6 +489,7 @@ impl Miner {
// Save proposal for later seal submission and broadcast it.
Seal::Proposal(seal) => {
trace!(target: "miner", "Received a Proposal seal.");
*self.next_mandatory_reseal.write() = Instant::now() + self.options.reseal_max_period;
{
let mut sealing_work = self.sealing_work.lock();
sealing_work.queue.push(block.clone());
@ -497,7 +505,8 @@ impl Miner {
})
},
// Directly import a regular sealed block.
Seal::Regular(seal) =>
Seal::Regular(seal) => {
*self.next_mandatory_reseal.write() = Instant::now() + self.options.reseal_max_period;
block
.lock()
.seal(&*self.engine, seal)
@ -505,7 +514,8 @@ impl Miner {
.unwrap_or_else(|e| {
warn!("ERROR: seal failed when given internally generated seal: {}", e);
false
}),
})
},
Seal::None => false,
}
} else {
@ -1290,6 +1300,7 @@ mod tests {
reseal_on_external_tx: false,
reseal_on_own_tx: true,
reseal_min_period: Duration::from_secs(5),
reseal_max_period: Duration::from_secs(120),
tx_gas_limit: !U256::zero(),
tx_queue_size: 1024,
tx_queue_gas_limit: GasLimit::None,

View File

@ -55,6 +55,8 @@ pub struct CommonParams {
pub fork_block: Option<(BlockNumber, H256)>,
/// Number of first block where EIP-98 rules begin.
pub eip98_transition: BlockNumber,
/// Validate block receipts root.
pub validate_receipts: bool,
}
impl From<ethjson::spec::Params> for CommonParams {
@ -68,6 +70,7 @@ impl From<ethjson::spec::Params> for CommonParams {
min_gas_limit: p.min_gas_limit.into(),
fork_block: if let (Some(n), Some(h)) = (p.fork_block, p.fork_hash) { Some((n.into(), h.into())) } else { None },
eip98_transition: p.eip98_transition.map_or(0, Into::into),
validate_receipts: p.validate_receipts.unwrap_or(true),
}
}
}

View File

@ -19,7 +19,6 @@
mod bloom;
mod config;
mod db;
mod error;
mod executive_tracer;
mod import;
mod noop_tracer;
@ -28,7 +27,6 @@ pub use types::trace_types::{filter, flat, localized, trace};
pub use types::trace_types::error::Error as TraceError;
pub use self::config::Config;
pub use self::db::TraceDB;
pub use self::error::Error;
pub use types::trace_types::trace::{VMTrace, VMOperation, VMExecutedOperation, MemoryDiff, StorageDiff};
pub use types::trace_types::flat::{FlatTrace, FlatTransactionTraces, FlatBlockTraces};
pub use self::noop_tracer::{NoopTracer, NoopVMTracer};

View File

@ -31,7 +31,7 @@ impl Verifier for CanonVerifier {
verification::verify_block_family(header, bytes, engine, bc)
}
fn verify_block_final(&self, expected: &Header, got: &Header) -> Result<(), Error> {
verification::verify_block_final(expected, got)
fn verify_block_final(&self, expected: &Header, got: &Header, receipts: bool) -> Result<(), Error> {
verification::verify_block_final(expected, got, receipts)
}
}

View File

@ -31,7 +31,7 @@ impl Verifier for NoopVerifier {
Ok(())
}
fn verify_block_final(&self, _expected: &Header, _got: &Header) -> Result<(), Error> {
fn verify_block_final(&self, _expected: &Header, _got: &Header, _receipts: bool) -> Result<(), Error> {
Ok(())
}
}

View File

@ -178,7 +178,7 @@ pub fn verify_block_family(header: &Header, bytes: &[u8], engine: &Engine, bc: &
}
/// Phase 4 verification. Check block information against transaction enactment results,
pub fn verify_block_final(expected: &Header, got: &Header) -> Result<(), Error> {
pub fn verify_block_final(expected: &Header, got: &Header, check_receipts: bool) -> Result<(), Error> {
if expected.gas_used() != got.gas_used() {
return Err(From::from(BlockError::InvalidGasUsed(Mismatch { expected: expected.gas_used().clone(), found: got.gas_used().clone() })))
}
@ -188,7 +188,7 @@ pub fn verify_block_final(expected: &Header, got: &Header) -> Result<(), Error>
if expected.state_root() != got.state_root() {
return Err(From::from(BlockError::InvalidStateRoot(Mismatch { expected: expected.state_root().clone(), found: got.state_root().clone() })))
}
if expected.receipts_root() != got.receipts_root() {
if check_receipts && expected.receipts_root() != got.receipts_root() {
return Err(From::from(BlockError::InvalidReceiptsRoot(Mismatch { expected: expected.receipts_root().clone(), found: got.receipts_root().clone() })))
}
Ok(())

View File

@ -26,5 +26,5 @@ pub trait Verifier: Send + Sync {
/// Verify a block relative to its parent and uncles.
fn verify_block_family(&self, header: &Header, bytes: &[u8], engine: &Engine, bc: &BlockProvider) -> Result<(), Error>;
/// Do a final verification check for an enacted header vs its expected counterpart.
fn verify_block_final(&self, expected: &Header, got: &Header) -> Result<(), Error>;
fn verify_block_final(&self, expected: &Header, got: &Header, receipts: bool) -> Result<(), Error>;
}

View File

@ -5,11 +5,11 @@ version = "0.1.0"
authors = ["Parity Technologies <admin@parity.io>"]
[lib]
name = "evm"
name = "evmbin"
path = "./src/main.rs"
[[bin]]
name = "evm"
name = "parity-evm"
path = "./src/main.rs"
[dependencies]

View File

@ -1,6 +1,6 @@
{
"name": "parity.js",
"version": "1.7.12",
"version": "1.7.18",
"main": "release/index.js",
"jsnext:main": "src/index.js",
"author": "Parity Team <admin@parity.io>",

View File

@ -1 +1,2 @@
// test script 7
// test script 8
// trigger rebuild on master 15 Mar 2017, 11:19

View File

@ -107,13 +107,25 @@ export default class Contract {
});
}
deploy (options, values, statecb = () => {}) {
deploy (options, values, statecb = () => {}, skipGasEstimate = false) {
let gasEstPromise;
if (skipGasEstimate) {
gasEstPromise = Promise.resolve(null);
} else {
statecb(null, { state: 'estimateGas' });
return this
.deployEstimateGas(options, values)
.then(([gasEst, gas]) => {
options.gas = gas.toFixed(0);
gasEstPromise = this.deployEstimateGas(options, values)
.then(([gasEst, gas]) => gas);
}
return gasEstPromise
.then((_gas) => {
if (_gas) {
options.gas = _gas.toFixed(0);
}
const gas = _gas || options.gas;
statecb(null, { state: 'postTransaction', gas });

View File

@ -253,23 +253,28 @@ export default class Deployment extends Component {
onDeploy = () => {
const { managerInstance, registryInstance, tokenregInstance } = this.context;
const { base, deployBusy, globalReg, globalFee, name, nameError, tla, tlaError, totalSupply, totalSupplyError } = this.state;
const { base, deployBusy, globalReg, name, nameError, tla, tlaError, totalSupply, totalSupplyError } = this.state;
const hasError = !!(nameError || tlaError || totalSupplyError);
if (hasError || deployBusy) {
return;
}
const tokenreg = (globalReg ? tokenregInstance : registryInstance).address;
const registry = globalReg ? tokenregInstance : registryInstance;
const tokenreg = registry.address;
const values = [base.mul(totalSupply), tla, name, tokenreg];
const options = {
value: globalReg ? globalFee : 0
};
const options = {};
this.setState({ deployBusy: true, deployState: 'Estimating gas for the transaction' });
return api.parity
.defaultAccount()
return registry.fee.call({}, [])
.then((fee) => {
console.log('deploying with fee of', fee.toFixed());
options.value = fee;
return api.parity.defaultAccount();
})
.then((defaultAddress) => {
options.from = defaultAddress;

View File

@ -19,7 +19,7 @@ import { Dialog, RaisedButton, FlatButton, SelectField, MenuItem } from 'materia
import AddIcon from 'material-ui/svg-icons/content/add';
import InputText from '../../Inputs/Text';
import { ADDRESS_TYPE } from '../../Inputs/validation';
import { ADDRESS_TYPE, URL_TYPE } from '../../Inputs/validation';
import styles from './token.css';
@ -128,6 +128,22 @@ export default class AddMeta extends Component {
renderForm () {
const selectedMeta = metaDataKeys[this.state.metaKeyIndex];
const metaLabel = selectedMeta.label.toLowerCase();
let metaType;
switch (selectedMeta.validation) {
case ADDRESS_TYPE:
metaType = 'Address';
break;
case URL_TYPE:
metaType = 'URL';
break;
default:
metaType = 'URL Hint';
break;
}
return (
<div>
@ -145,7 +161,7 @@ export default class AddMeta extends Component {
<InputText
key={ selectedMeta.value }
floatingLabelText={ `${selectedMeta.label} value` }
hintText={ `The value of the ${selectedMeta.label.toLowerCase()} (${selectedMeta.validation === ADDRESS_TYPE ? 'Address' : 'Url Hint'})` }
hintText={ `The value of the ${metaLabel} (${metaType})` }
validationType={ selectedMeta.validation }
onChange={ this.onChange }
@ -174,14 +190,20 @@ export default class AddMeta extends Component {
onAdd = () => {
const { index } = this.props;
const { form, metaKeyIndex } = this.state;
const selectedMeta = metaDataKeys[metaKeyIndex];
const keyIndex = this.state.metaKeyIndex;
const key = metaDataKeys[keyIndex].value;
const value = form.value;
const validationType = selectedMeta.validation;
this.props.handleAddMeta(
index,
key,
this.state.form.value
value,
validationType
);
this.setState({ complete: true });

View File

@ -61,8 +61,8 @@ const mapDispatchToProps = (dispatch) => {
dispatch(unregisterToken(index));
},
handleAddMeta: (index, key, value) => {
dispatch(addTokenMeta(index, key, value));
handleAddMeta: (index, key, value, validationType) => {
dispatch(addTokenMeta(index, key, value, validationType));
}
};
};

View File

@ -14,7 +14,8 @@
// You should have received a copy of the GNU General Public License
// along with Parity. If not, see <http://www.gnu.org/licenses/>.
import { getTokenTotalSupply } from '../utils';
import { URL_TYPE } from '../Inputs/validation';
import { getTokenTotalSupply, urlToHash } from '../utils';
const { bytesToHex } = window.parity.api.util;
@ -178,40 +179,63 @@ export const queryTokenMeta = (index, query) => (dispatch, getState) => {
});
};
export const addTokenMeta = (index, key, value) => (dispatch, getState) => {
export const addTokenMeta = (index, key, value, validationType) => (dispatch, getState) => {
const state = getState();
const contractInstance = state.status.contract.instance;
const ghhInstance = state.status.githubhint.instance;
const token = state.tokens.tokens.find(t => t.index === index);
const options = { from: token.owner };
const values = [ index, key, value ];
let valuesPromise;
contractInstance
// Get the right values (could be a hashed URL from GHH)
if (validationType === URL_TYPE) {
valuesPromise = addGithubhintURL(ghhInstance, options, value)
.then((hash) => [ index, key, hash ]);
} else {
valuesPromise = Promise.resolve([ index, key, value ]);
}
return valuesPromise
.then((values) => {
return contractInstance
.setMeta
.estimateGas(options, values)
.then((gasEstimate) => {
options.gas = gasEstimate.mul(1.2).toFixed(0);
return contractInstance.setMeta.postTransaction(options, values);
});
})
.catch((e) => {
console.error(`addTokenMeta: #${index} error`, e);
});
};
export const addGithubhintURL = (from, key, url) => (dispatch, getState) => {
const state = getState();
const contractInstance = state.status.githubhint.instance;
const options = { from };
const values = [ key, url ];
export const addGithubhintURL = (ghhInstance, _options, url) => {
return urlToHash(ghhInstance, url)
.then((result) => {
const { hash, registered } = result;
contractInstance
if (registered) {
return hash;
}
const options = { from: _options.from };
const values = [ hash, url ];
ghhInstance
.hintURL
.estimateGas(options, values)
.then((gasEstimate) => {
options.gas = gasEstimate.mul(1.2).toFixed(0);
return contractInstance.hintURL.postTransaction(options, values);
return ghhInstance.hintURL.postTransaction(options, values);
})
.catch((e) => {
console.error('addGithubhintURL error', e);
.catch((error) => {
console.error(`registering "${url}" to GHH`, error);
});
return hash;
});
};

View File

@ -14,13 +14,13 @@
// You should have received a copy of the GNU General Public License
// along with Parity. If not, see <http://www.gnu.org/licenses/>.
import { HEX_TYPE, ADDRESS_TYPE } from './Inputs/validation';
import { URL_TYPE, ADDRESS_TYPE } from './Inputs/validation';
export const metaDataKeys = [
{
label: 'Image',
value: 'IMG',
validation: HEX_TYPE
validation: URL_TYPE
},
{
label: 'Address',

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/>.
const { api } = window.parity;
const api = window.parent.secureApi;
export {
api

View File

@ -18,6 +18,45 @@ import { api } from './parity';
import { eip20 as eip20Abi } from '~/contracts/abi';
export const INVALID_URL_HASH = '0xc5d2460186f7233c927e7db2dcc703c0e500b653ca82273b7bfad8045d85a470';
export const ZERO_ADDRESS = '0x0000000000000000000000000000000000000000';
/**
* Convert the given URL to a content hash,
* and checks if it is already registered in GHH
*/
export const urlToHash = (ghhInstance, url) => {
if (!url || !url.length) {
return Promise.resolve(null);
}
return api.parity
.hashContent(url)
.catch((error) => {
const message = error.text || error.message || error.toString();
throw new Error(`${message} (${url})`);
})
.then((contentHash) => {
console.log('lookupHash', url, contentHash);
if (contentHash === INVALID_URL_HASH) {
throw new Error(`"${url}" is not a valid URL`);
}
return ghhInstance.entries
.call({}, [contentHash])
.then(([accountSlashRepo, commit, contentHashOwner]) => {
const registered = (contentHashOwner !== ZERO_ADDRESS);
return {
hash: contentHash,
registered
};
});
});
};
export const getTokenTotalSupply = (tokenAddress) => {
return api
.eth

View File

@ -130,7 +130,7 @@ export default class CreationType extends Component {
<div className={ styles.summary }>
<FormattedMessage
id='createAccount.creationType.info'
defaultMessage='Please select the type of account you want to create. Either create an account via name & password, or import it from a variety of existing sources. From here the wizard will guid you through the process of completing your account creation.'
defaultMessage='Please select the type of account you want to create. Either create an account via name & password, or import it from a variety of existing sources. From here the wizard will guide you through the process of completing your account creation.'
/>
</div>
{ this.renderList(createType) }

View File

@ -16,12 +16,16 @@
import React, { Component, PropTypes } from 'react';
import { FormattedMessage } from 'react-intl';
import { MenuItem } from 'material-ui';
import { Checkbox, MenuItem } from 'material-ui';
import { AddressSelect, Form, Input, Select } from '~/ui';
import { validateAbi } from '~/util/validation';
import { parseAbiType } from '~/util/abi';
const CHECK_STYLE = {
marginTop: '1em'
};
export default class DetailsStep extends Component {
static contextTypes = {
api: PropTypes.object.isRequired
@ -30,8 +34,10 @@ export default class DetailsStep extends Component {
static propTypes = {
accounts: PropTypes.object.isRequired,
onAbiChange: PropTypes.func.isRequired,
onAmountChange: PropTypes.func.isRequired,
onCodeChange: PropTypes.func.isRequired,
onDescriptionChange: PropTypes.func.isRequired,
onExtrasChange: PropTypes.func.isRequired,
onFromAddressChange: PropTypes.func.isRequired,
onInputsChange: PropTypes.func.isRequired,
onNameChange: PropTypes.func.isRequired,
@ -39,11 +45,14 @@ export default class DetailsStep extends Component {
abi: PropTypes.string,
abiError: PropTypes.string,
amount: PropTypes.string,
amountError: PropTypes.string,
balances: PropTypes.object,
code: PropTypes.string,
codeError: PropTypes.string,
description: PropTypes.string,
descriptionError: PropTypes.string,
extras: PropTypes.bool,
fromAddress: PropTypes.string,
fromAddressError: PropTypes.string,
name: PropTypes.string,
@ -52,6 +61,7 @@ export default class DetailsStep extends Component {
};
static defaultProps = {
extras: false,
readOnly: false
};
@ -83,7 +93,7 @@ export default class DetailsStep extends Component {
fromAddress, fromAddressError,
name, nameError,
description, descriptionError,
abiError,
abiError, extras,
code, codeError
} = this.props;
@ -189,10 +199,70 @@ export default class DetailsStep extends Component {
value={ code }
/>
{ this.renderValueInput() }
<div>
<Checkbox
checked={ extras }
label={
<FormattedMessage
id='deployContract.details.advanced.label'
defaultMessage='advanced sending options'
/>
}
onCheck={ this.onCheckExtras }
style={ CHECK_STYLE }
/>
</div>
</Form>
);
}
renderValueInput () {
const { abi, amount, amountError } = this.props;
let payable = false;
try {
const parsedAbi = JSON.parse(abi);
payable = parsedAbi.find((method) => method.type === 'constructor' && method.payable);
} catch (error) {
return null;
}
if (!payable) {
return null;
}
return (
<Input
error={ amountError }
hint={
<FormattedMessage
id='deployContract.details.amount.hint'
defaultMessage='the amount to transfer to the contract'
/>
}
label={
<FormattedMessage
id='deployContract.details.amount.label'
defaultMessage='amount to transfer (in {tag})'
values={ {
tag: 'ETH'
} }
/>
}
min={ 0 }
step={ 0.1 }
type='number'
onChange={ this.onAmountChange }
value={ amount }
/>
);
}
renderContractSelect () {
const { contracts } = this.state;
@ -295,6 +365,16 @@ export default class DetailsStep extends Component {
onDescriptionChange(description);
}
onAmountChange = (event, value) => {
const { onAmountChange } = this.props;
onAmountChange(value);
}
onCheckExtras = () => {
this.props.onExtrasChange(!this.props.extras);
}
onAbiChange = (abi) => {
const { api } = this.context;
const { onAbiChange, onParamsChange, onInputsChange } = this.props;

View File

@ -14,6 +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/>.
import BigNumber from 'bignumber.js';
import { pick } from 'lodash';
import { observer } from 'mobx-react';
import React, { Component, PropTypes } from 'react';
@ -22,12 +23,13 @@ import { connect } from 'react-redux';
import { BusyStep, Button, CompletedStep, CopyToClipboard, GasPriceEditor, IdentityIcon, Portal, TxHash, Warning } from '~/ui';
import { CancelIcon, DoneIcon } from '~/ui/Icons';
import { ERRORS, validateAbi, validateCode, validateName } from '~/util/validation';
import { ERRORS, validateAbi, validateCode, validateName, validatePositiveNumber } from '~/util/validation';
import { deploy, deployEstimateGas } from '~/util/tx';
import DetailsStep from './DetailsStep';
import ParametersStep from './ParametersStep';
import ErrorStep from './ErrorStep';
import Extras from '../Transfer/Extras';
import styles from './deployContract.css';
@ -50,6 +52,14 @@ const STEPS = {
/>
)
},
EXTRAS: {
title: (
<FormattedMessage
id='deployContract.title.extras'
defaultMessage='extra information'
/>
)
},
DEPLOYMENT: {
waiting: true,
title: (
@ -97,12 +107,16 @@ class DeployContract extends Component {
state = {
abi: '',
abiError: ERRORS.invalidAbi,
amount: '0',
amountValue: new BigNumber(0),
amountError: '',
code: '',
codeError: ERRORS.invalidCode,
deployState: '',
deployError: null,
description: '',
descriptionError: null,
extras: false,
fromAddress: Object.keys(this.props.accounts)[0],
fromAddressError: null,
name: '',
@ -144,7 +158,19 @@ class DeployContract extends Component {
const realStepKeys = deployError || rejected
? []
: Object.keys(STEPS).filter((k) => k !== 'CONTRACT_PARAMETERS' || inputs.length > 0);
: Object.keys(STEPS)
.filter((k) => {
if (k === 'CONTRACT_PARAMETERS') {
return inputs.length > 0;
}
if (k === 'EXTRAS') {
return this.state.extras;
}
return true;
});
const realStep = realStepKeys.findIndex((k) => k === step);
const realSteps = realStepKeys.length
? realStepKeys.map((k) => STEPS[k])
@ -207,8 +233,8 @@ class DeployContract extends Component {
}
renderDialogActions () {
const { deployError, abiError, codeError, nameError, descriptionError, fromAddressError, fromAddress, step } = this.state;
const isValid = !nameError && !fromAddressError && !descriptionError && !abiError && !codeError;
const { deployError, abiError, amountError, codeError, nameError, descriptionError, fromAddressError, fromAddress, step } = this.state;
const isValid = !nameError && !fromAddressError && !descriptionError && !abiError && !codeError && !amountError;
const cancelBtn = (
<Button
@ -256,32 +282,7 @@ class DeployContract extends Component {
return closeBtn;
}
switch (step) {
case 'CONTRACT_DETAILS':
return [
cancelBtn,
<Button
disabled={ !isValid }
key='next'
icon={
<IdentityIcon
address={ fromAddress }
button
/>
}
label={
<FormattedMessage
id='deployContract.button.next'
defaultMessage='Next'
/>
}
onClick={ this.onParametersStep }
/>
];
case 'CONTRACT_PARAMETERS':
return [
cancelBtn,
const createButton = (
<Button
icon={
<IdentityIcon
@ -298,6 +299,52 @@ class DeployContract extends Component {
}
onClick={ this.onDeployStart }
/>
);
const nextButton = (
<Button
disabled={ !isValid }
key='next'
icon={
<IdentityIcon
address={ fromAddress }
button
/>
}
label={
<FormattedMessage
id='deployContract.button.next'
defaultMessage='Next'
/>
}
onClick={ this.onNextStep }
/>
);
const hasParameters = this.state.inputs.length > 0;
const showExtras = this.state.extras;
switch (step) {
case 'CONTRACT_DETAILS':
return [
cancelBtn,
hasParameters || showExtras
? nextButton
: createButton
];
case 'CONTRACT_PARAMETERS':
return [
cancelBtn,
showExtras
? nextButton
: createButton
];
case 'EXTRAS':
return [
cancelBtn,
createButton
];
case 'DEPLOYMENT':
@ -344,6 +391,8 @@ class DeployContract extends Component {
{ ...this.state }
accounts={ accounts }
balances={ balances }
onAmountChange={ this.onAmountChange }
onExtrasChange={ this.onExtrasChange }
onFromAddressChange={ this.onFromAddressChange }
onDescriptionChange={ this.onDescriptionChange }
onNameChange={ this.onNameChange }
@ -365,6 +414,9 @@ class DeployContract extends Component {
/>
);
case 'EXTRAS':
return this.renderExtrasPage();
case 'DEPLOYMENT':
const body = txhash
? <TxHash hash={ txhash } />
@ -411,17 +463,32 @@ class DeployContract extends Component {
}
}
renderExtrasPage () {
if (!this.gasStore.histogram) {
return null;
}
return (
<Extras
gasStore={ this.gasStore }
hideData
isEth
/>
);
}
estimateGas = () => {
const { api } = this.context;
const { abiError, abiParsed, code, codeError, fromAddress, fromAddressError, params } = this.state;
const { abiError, abiParsed, amountValue, amountError, code, codeError, fromAddress, fromAddressError, params } = this.state;
if (abiError || codeError || fromAddressError) {
if (abiError || codeError || fromAddressError || amountError) {
return;
}
const options = {
data: code,
from: fromAddress
from: fromAddress,
value: amountValue
};
const contract = api.newContract(abiParsed);
@ -437,6 +504,19 @@ class DeployContract extends Component {
});
}
onNextStep = () => {
switch (this.state.step) {
case 'CONTRACT_DETAILS':
return this.onParametersStep();
case 'CONTRACT_PARAMETERS':
return this.onExtrasStep();
default:
console.warn('wrong call of "onNextStep" from', this.state.step);
}
}
onParametersStep = () => {
const { inputs } = this.state;
@ -444,6 +524,14 @@ class DeployContract extends Component {
return this.setState({ step: 'CONTRACT_PARAMETERS' });
}
return this.onExtrasStep();
}
onExtrasStep = () => {
if (this.state.extras) {
return this.setState({ step: 'EXTRAS' });
}
return this.onDeployStart();
}
@ -488,10 +576,24 @@ class DeployContract extends Component {
this.setState(validateCode(code), this.estimateGas);
}
onAmountChange = (amount) => {
const { numberError } = validatePositiveNumber(amount);
const nextAmountValue = numberError
? new BigNumber(0)
: this.context.api.util.toWei(amount);
this.gasStore.setEthValue(nextAmountValue);
this.setState({ amount, amountValue: nextAmountValue, amountError: numberError }, this.estimateGas);
}
onExtrasChange = (extras) => {
this.setState({ extras });
}
onDeployStart = () => {
const { api, store } = this.context;
const { source } = this.props;
const { abiParsed, code, description, name, params, fromAddress } = this.state;
const { abiParsed, amountValue, code, description, name, params, fromAddress } = this.state;
const metadata = {
abi: abiParsed,
@ -503,16 +605,17 @@ class DeployContract extends Component {
source
};
const options = {
const options = this.gasStore.overrideTransaction({
data: code,
from: fromAddress
};
from: fromAddress,
value: amountValue
});
this.setState({ step: 'DEPLOYMENT' });
const contract = api.newContract(abiParsed);
deploy(contract, options, params, metadata, this.onDeploymentState)
deploy(contract, options, params, metadata, this.onDeploymentState, true)
.then((address) => {
// No contract address given, might need some confirmations
// from the wallet owners...

View File

@ -49,7 +49,7 @@ export default class FirstRun extends Component {
defaultMessage='As part of a new installation, the next few steps will guide you through the process of setting up you Parity instance and your associated accounts. Our aim is to make it as simple as possible and to get you up and running in record-time, so please bear with us. Once completed you will have -'
/>
</p>
<p>
<div>
<ul>
<li>
<FormattedMessage
@ -70,7 +70,7 @@ export default class FirstRun extends Component {
/>
</li>
</ul>
</p>
</div>
<p>
<FormattedMessage
id='firstRun.welcome.next'

View File

@ -24,7 +24,7 @@ import { nullableProptype } from '~/util/proptypes';
import TokenSelect from './tokenSelect';
import styles from '../transfer.css';
const CHECK_STYLE = {
export const CHECK_STYLE = {
position: 'absolute',
top: '38px',
left: '1em'

View File

@ -25,12 +25,17 @@ export default class Extras extends Component {
static propTypes = {
data: PropTypes.string,
dataError: PropTypes.string,
hideData: PropTypes.bool,
gasStore: PropTypes.object.isRequired,
isEth: PropTypes.bool,
onChange: PropTypes.func.isRequired,
onChange: PropTypes.func,
total: PropTypes.string,
totalError: PropTypes.string
}
};
static defaultProps = {
hideData: false
};
render () {
const { gasStore, onChange } = this.props;
@ -49,9 +54,9 @@ export default class Extras extends Component {
}
renderData () {
const { isEth, data, dataError } = this.props;
const { isEth, data, dataError, hideData } = this.props;
if (!isEth) {
if (!isEth || hideData) {
return null;
}

View File

@ -92,6 +92,26 @@ export default class SecureApi extends Api {
return this._transport.token;
}
/**
* Configure the current API with the given values
* (`signerPort`, `dappsInterface`, `dappsPort`, ...)
*/
configure (configuration) {
const { dappsInterface, dappsPort, signerPort } = configuration;
if (dappsInterface) {
this._dappsInterface = dappsInterface;
}
if (dappsPort) {
this._dappsPort = dappsPort;
}
if (signerPort) {
this._signerPort = signerPort;
}
}
connect () {
if (this._isConnecting) {
return;

View File

@ -81,6 +81,7 @@ export default class Input extends Component {
tabIndex: PropTypes.number,
type: PropTypes.string,
submitOnBlur: PropTypes.bool,
step: PropTypes.number,
style: PropTypes.object,
value: PropTypes.oneOfType([
PropTypes.number,
@ -124,7 +125,7 @@ export default class Input extends Component {
render () {
const { value } = this.state;
const { autoFocus, children, className, hideUnderline, disabled, error, focused, label } = this.props;
const { hint, onClick, multiLine, rows, type, min, max, style, tabIndex } = this.props;
const { hint, onClick, multiLine, rows, type, min, max, step, style, tabIndex } = this.props;
const readOnly = this.props.readOnly || disabled;
@ -179,6 +180,7 @@ export default class Input extends Component {
readOnly={ readOnly }
ref='input'
rows={ rows }
step={ step }
style={ textFieldStyle }
tabIndex={ tabIndex }
type={ type || 'text' }

View File

@ -107,7 +107,7 @@ class MethodDecoding extends Component {
renderGas () {
const { historic, transaction } = this.props;
const { gas, gasPrice } = transaction;
const { gas, gasPrice, value } = transaction;
if (!gas || !gasPrice) {
return null;
@ -126,9 +126,9 @@ class MethodDecoding extends Component {
/>
</span>
);
const gasProvidedEth = (
const totalEthValue = (
<span className={ styles.highlight }>
{ this.renderEtherValue(gas.mul(gasPrice)) }
{ this.renderEtherValue(gas.mul(gasPrice).plus(value || 0)) }
</span>
);
const gasUsed = transaction.gasUsed
@ -149,12 +149,12 @@ class MethodDecoding extends Component {
<div className={ styles.gasDetails }>
<FormattedMessage
id='ui.methodDecoding.txValues'
defaultMessage='{historic, select, true {Provided} false {Provides}} {gasProvided}{gasUsed} for a total transaction value of {gasProvidedEth}'
defaultMessage='{historic, select, true {Provided} false {Provides}} {gasProvided}{gasUsed} for a total transaction value of {totalEthValue}'
values={ {
historic,
gasProvided,
gasProvidedEth,
gasUsed
gasUsed,
totalEthValue
} }
/>
{ this.renderMinBlock() }
@ -349,6 +349,7 @@ class MethodDecoding extends Component {
renderDeploy () {
const { historic, transaction } = this.props;
const { methodInputs } = this.state;
const { value } = transaction;
if (!historic) {
return (
@ -357,6 +358,19 @@ class MethodDecoding extends Component {
id='ui.methodDecoding.deploy.willDeploy'
defaultMessage='Will deploy a contract'
/>
{
value && value.gt(0)
? (
<FormattedMessage
id='ui.methodDecoding.deploy.withValue'
defaultMessage=', sending {value}'
values={ {
value: this.renderEtherValue(value)
} }
/>
)
: null
}
</div>
);
}

View File

@ -51,7 +51,7 @@ $popoverZ: 3600;
left: 0;
right: 0;
opacity: 0.25;
z-index: 0;
z-index: -1;
}
.overlay {

View File

@ -18,6 +18,7 @@ import React, { Component, PropTypes } from 'react';
import ReactDOM from 'react-dom';
import ReactPortal from 'react-portal';
import keycode from 'keycode';
import { noop } from 'lodash';
import { nodeOrStringProptype } from '~/util/proptypes';
import { CloseIcon } from '~/ui/Icons';
@ -29,7 +30,6 @@ import styles from './portal.css';
export default class Portal extends Component {
static propTypes = {
onClose: PropTypes.func.isRequired,
open: PropTypes.bool.isRequired,
activeStep: PropTypes.number,
busy: PropTypes.bool,
@ -45,11 +45,16 @@ export default class Portal extends Component {
isChildModal: PropTypes.bool,
isSmallModal: PropTypes.bool,
onClick: PropTypes.func,
onClose: PropTypes.func,
onKeyDown: PropTypes.func,
steps: PropTypes.array,
title: nodeOrStringProptype()
};
static defaultProps = {
onClose: noop
};
componentDidMount () {
this.setBodyOverflow(this.props.open);
}

View File

@ -44,6 +44,7 @@ $widthExpanded: 42%;
box-sizing: border-box;
display: flex;
flex: 0 1 $widthNormal;
max-width: $widthNormal;
opacity: 0.85;
padding: 0.25em;

View File

@ -73,7 +73,7 @@ export function postTransaction (_func, _options, _values = []) {
});
}
export function deploy (contract, _options, values, metadata = {}, statecb = () => {}) {
export function deploy (contract, _options, values, metadata = {}, statecb = () => {}, skipGasEstimate = false) {
const options = { ..._options };
const { api } = contract;
const address = options.from;
@ -82,16 +82,27 @@ export function deploy (contract, _options, values, metadata = {}, statecb = ()
.isWallet(api, address)
.then((isWallet) => {
if (!isWallet) {
return contract.deploy(options, values, statecb);
return contract.deploy(options, values, statecb, skipGasEstimate);
}
let gasEstPromise;
if (skipGasEstimate) {
gasEstPromise = Promise.resolve(null);
} else {
statecb(null, { state: 'estimateGas' });
return deployEstimateGas(contract, options, values)
.then(([gasEst, gas]) => {
options.gas = gas.toFixed(0);
gasEstPromise = deployEstimateGas(contract, options, values)
.then(([gasEst, gas]) => gas);
}
statecb(null, { state: 'postTransaction', gas });
return gasEstPromise
.then((gas) => {
if (gas) {
options.gas = gas.toFixed(0);
}
statecb(null, { state: 'postTransaction', gas: options.gas });
return WalletsUtils.getDeployArgs(contract, options, values);
})

View File

@ -17,12 +17,20 @@
import { action, observable } from 'mobx';
import store from 'store';
const OLD_LS_FIRST_RUN_KEY = 'showFirstRun';
const LS_FIRST_RUN_KEY = '_parity::showFirstRun';
export default class Store {
@observable firstrunVisible = false;
constructor (api) {
// Migrate the old key to the new one
this._migrateStore();
this._api = api;
this.firstrunVisible = store.get('showFirstRun');
// Show the first run if it hasn't been shown before
// (thus an undefined value)
this.firstrunVisible = store.get(LS_FIRST_RUN_KEY) === undefined;
this._checkAccounts();
}
@ -33,16 +41,41 @@ export default class Store {
@action toggleFirstrun = (visible = false) => {
this.firstrunVisible = visible;
store.set('showFirstRun', !!visible);
// There's no need to write to storage that the
// First Run should be visible
if (!visible) {
store.set(LS_FIRST_RUN_KEY, !!visible);
}
}
/**
* Migrate the old LocalStorage ket format
* to the new one
*/
_migrateStore () {
const oldValue = store.get(OLD_LS_FIRST_RUN_KEY);
const newValue = store.get(LS_FIRST_RUN_KEY);
if (newValue === undefined && oldValue !== undefined) {
store.set(LS_FIRST_RUN_KEY, oldValue);
store.remove(OLD_LS_FIRST_RUN_KEY);
}
}
_checkAccounts () {
this._api.parity
.allAccountsInfo()
.then((info) => {
return Promise
.all([
this._api.parity.listVaults(),
this._api.parity.allAccountsInfo()
])
.then(([ vaults, info ]) => {
const accounts = Object.keys(info).filter((address) => info[address].uuid);
// Has accounts if any vaults or accounts
const hasAccounts = (accounts && accounts.length > 0) || (vaults && vaults.length > 0);
this.toggleFirstrun(this.firstrunVisible || !accounts || !accounts.length);
// Show First Run if no accounts and no vaults
this.toggleFirstrun(this.firstrunVisible || !hasAccounts);
})
.catch((error) => {
console.error('checkAccounts', error);

View File

@ -32,7 +32,8 @@
"description": "A registry of transactable tokens on the network",
"author": "Parity Team <admin@ethcore.io>",
"version": "1.0.0",
"visible": true
"visible": true,
"secure": true
},
{
"id": "0xf49089046f53f5d2e5f3513c1c32f5ff57d986e46309a42d2b249070e4e72c46",

View File

@ -105,7 +105,7 @@ class WriteContract extends Component {
className={ styles.editor }
style={ { flex: `${size}%` } }
>
<h2>asd{ this.renderTitle() }</h2>
<h2>{ this.renderTitle() }</h2>
<Editor
ref='editor'

View File

@ -53,6 +53,9 @@ pub struct Params {
/// See `CommonParams` docs.
#[serde(rename="eip98Transition")]
pub eip98_transition: Option<Uint>,
/// See `CommonParams` docs.
#[serde(rename="validateReceipts")]
pub validate_receipts: Option<bool>,
}
#[cfg(test)]

View File

@ -85,6 +85,7 @@ engine_signer = "0xdeadbeefcafe0000000000000000000000000001"
force_sealing = true
reseal_on_txs = "all"
reseal_min_period = 4000
reseal_max_period = 60000
work_queue_size = 20
relay_set = "cheap"
usd_per_tx = "0.0025"

View File

@ -50,6 +50,7 @@ engine_signer = "0xdeadbeefcafe0000000000000000000000000001"
force_sealing = true
reseal_on_txs = "all"
reseal_min_period = 4000
reseal_max_period = 60000
price_update_period = "hourly"
tx_queue_size = 1024
tx_queue_gas = "auto"

View File

@ -224,6 +224,8 @@ usage! {
or |c: &Config| otry!(c.mining).reseal_on_txs.clone(),
flag_reseal_min_period: u64 = 2000u64,
or |c: &Config| otry!(c.mining).reseal_min_period.clone(),
flag_reseal_max_period: u64 = 120000u64,
or |c: &Config| otry!(c.mining).reseal_max_period.clone(),
flag_work_queue_size: usize = 20usize,
or |c: &Config| otry!(c.mining).work_queue_size.clone(),
flag_tx_gas_limit: Option<String> = None,
@ -460,6 +462,7 @@ struct Mining {
force_sealing: Option<bool>,
reseal_on_txs: Option<String>,
reseal_min_period: Option<u64>,
reseal_max_period: Option<u64>,
work_queue_size: Option<usize>,
tx_gas_limit: Option<String>,
tx_time_limit: Option<u64>,
@ -701,6 +704,7 @@ mod tests {
flag_force_sealing: true,
flag_reseal_on_txs: "all".into(),
flag_reseal_min_period: 4000u64,
flag_reseal_max_period: 60000u64,
flag_work_queue_size: 20usize,
flag_tx_gas_limit: Some("6283184".into()),
flag_tx_time_limit: Some(100u64),
@ -900,6 +904,7 @@ mod tests {
force_sealing: Some(true),
reseal_on_txs: Some("all".into()),
reseal_min_period: Some(4000),
reseal_max_period: Some(60000),
work_queue_size: None,
relay_set: None,
usd_per_tx: None,

View File

@ -224,6 +224,9 @@ Sealing/Mining Options:
--reseal-min-period MS Specify the minimum time between reseals from
incoming transactions. MS is time measured in
milliseconds (default: {flag_reseal_min_period}).
--reseal-max-period MS Specify the maximum time since last block to enable
force-sealing. MS is time measured in
milliseconds (default: {flag_reseal_max_period}).
--work-queue-size ITEMS Specify the number of historical work packages
which are kept cached lest a solution is found for
them later. High values take more memory but result

View File

@ -522,6 +522,7 @@ impl Configuration {
tx_queue_strategy: to_queue_strategy(&self.args.flag_tx_queue_strategy)?,
pending_set: to_pending_set(&self.args.flag_relay_set)?,
reseal_min_period: Duration::from_millis(reseal_min_period),
reseal_max_period: Duration::from_millis(self.args.flag_reseal_max_period),
work_queue_size: self.args.flag_work_queue_size,
enable_resubmission: !self.args.flag_remove_solved,
tx_queue_banning: match self.args.flag_tx_time_limit {

View File

@ -32,7 +32,6 @@ mod codes {
pub const NO_WORK: i64 = -32001;
pub const NO_AUTHOR: i64 = -32002;
pub const NO_NEW_WORK: i64 = -32003;
pub const NOT_ENOUGH_DATA: i64 = -32006;
pub const UNKNOWN_ERROR: i64 = -32009;
pub const TRANSACTION_ERROR: i64 = -32010;
pub const EXECUTION_ERROR: i64 = -32015;
@ -41,9 +40,6 @@ mod codes {
pub const ACCOUNT_LOCKED: i64 = -32020;
pub const PASSWORD_INVALID: i64 = -32021;
pub const ACCOUNT_ERROR: i64 = -32023;
pub const SIGNER_DISABLED: i64 = -32030;
pub const DAPPS_DISABLED: i64 = -32031;
pub const NETWORK_DISABLED: i64 = -32035;
pub const REQUEST_REJECTED: i64 = -32040;
pub const REQUEST_REJECTED_LIMIT: i64 = -32041;
pub const REQUEST_NOT_FOUND: i64 = -32042;
@ -174,9 +170,9 @@ pub fn no_author() -> Error {
pub fn not_enough_data() -> Error {
Error {
code: ErrorCode::ServerError(codes::NOT_ENOUGH_DATA),
code: ErrorCode::ServerError(codes::UNSUPPORTED_REQUEST),
message: "The node does not have enough data to compute the given statistic.".into(),
data: None
data: None,
}
}
@ -190,25 +186,25 @@ pub fn token(e: String) -> Error {
pub fn signer_disabled() -> Error {
Error {
code: ErrorCode::ServerError(codes::SIGNER_DISABLED),
code: ErrorCode::ServerError(codes::UNSUPPORTED_REQUEST),
message: "Trusted Signer is disabled. This API is not available.".into(),
data: None
data: None,
}
}
pub fn dapps_disabled() -> Error {
Error {
code: ErrorCode::ServerError(codes::DAPPS_DISABLED),
code: ErrorCode::ServerError(codes::UNSUPPORTED_REQUEST),
message: "Dapps Server is disabled. This API is not available.".into(),
data: None
data: None,
}
}
pub fn network_disabled() -> Error {
Error {
code: ErrorCode::ServerError(codes::NETWORK_DISABLED),
code: ErrorCode::ServerError(codes::UNSUPPORTED_REQUEST),
message: "Network is disabled or not yet up.".into(),
data: None
data: None,
}
}
@ -321,7 +317,7 @@ pub fn from_call_error(error: CallError) -> Error {
pub fn unknown_block() -> Error {
Error {
code: ErrorCode::ServerError(codes::UNSUPPORTED_REQUEST),
code: ErrorCode::InvalidParams,
message: "Unknown block number".into(),
data: None,
}

View File

@ -0,0 +1,43 @@
// Copyright 2015-2017 Parity Technologies (UK) Ltd.
// This file is part of Parity.
// Parity is free software: you can redistribute it and/or modify
// it under the terms of the GNU General Public License as published by
// the Free Software Foundation, either version 3 of the License, or
// (at your option) any later version.
// Parity is distributed in the hope that it will be useful,
// but WITHOUT ANY WARRANTY; without even the implied warranty of
// MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the
// GNU General Public License for more details.
// You should have received a copy of the GNU General Public License
// along with Parity. If not, see <http://www.gnu.org/licenses/>.
use std::sync::Weak;
use ethcore::client::MiningBlockChainClient;
use ethcore::miner::MinerService;
use ethcore::transaction::{Transaction, SignedTransaction, Action};
use jsonrpc_core::Error;
use v1::helpers::CallRequest;
use v1::helpers::dispatch::default_gas_price;
pub fn sign_call<B: MiningBlockChainClient, M: MinerService>(
client: &Weak<B>,
miner: &Weak<M>,
request: CallRequest,
) -> Result<SignedTransaction, Error> {
let client = take_weak!(client);
let miner = take_weak!(miner);
let from = request.from.unwrap_or(0.into());
Ok(Transaction {
nonce: request.nonce.unwrap_or_else(|| client.latest_nonce(&from)),
action: request.to.map_or(Action::Create, Action::Call),
gas: request.gas.unwrap_or(50_000_000.into()),
gas_price: request.gas_price.unwrap_or_else(|| default_gas_price(&*client, &*miner)),
value: request.value.unwrap_or(0.into()),
data: request.data.map_or_else(Vec::new, |d| d.to_vec())
}.fake_sign(from))
}

View File

@ -19,6 +19,7 @@ pub mod errors;
pub mod block_import;
pub mod dispatch;
pub mod fake_sign;
pub mod informant;
pub mod oneshot;

View File

@ -23,7 +23,7 @@ use std::sync::{Arc, Weak};
use futures::{self, future, BoxFuture, Future};
use rlp::{self, UntrustedRlp, View};
use time::get_time;
use util::{H160, H256, Address, U256, H64, Uint};
use util::{H160, H256, Address, U256, H64};
use util::sha3::Hashable;
use util::Mutex;
@ -36,14 +36,14 @@ use ethcore::filter::Filter as EthcoreFilter;
use ethcore::header::{Header as BlockHeader, BlockNumber as EthBlockNumber};
use ethcore::log_entry::LogEntry;
use ethcore::miner::{MinerService, ExternalMinerService};
use ethcore::transaction::{Transaction as EthTransaction, SignedTransaction, Action};
use ethcore::transaction::SignedTransaction;
use ethcore::snapshot::SnapshotService;
use ethsync::{SyncProvider};
use jsonrpc_core::Error;
use jsonrpc_macros::Trailing;
use v1::helpers::{CallRequest as CRequest, errors, limit_logs};
use v1::helpers::{errors, limit_logs, fake_sign};
use v1::helpers::dispatch::{Dispatcher, FullDispatcher, default_gas_price};
use v1::helpers::block_import::is_major_importing;
use v1::traits::Eth;
@ -222,19 +222,6 @@ impl<C, SN: ?Sized, S: ?Sized, M, EM> EthClient<C, SN, S, M, EM> where
Ok(Some(block))
}
fn sign_call(&self, request: CRequest) -> Result<SignedTransaction, Error> {
let (client, miner) = (take_weak!(self.client), take_weak!(self.miner));
let from = request.from.unwrap_or(Address::zero());
Ok(EthTransaction {
nonce: request.nonce.unwrap_or_else(|| client.latest_nonce(&from)),
action: request.to.map_or(Action::Create, Action::Call),
gas: request.gas.unwrap_or(U256::from(50_000_000)),
gas_price: request.gas_price.unwrap_or_else(|| default_gas_price(&*client, &*miner)),
value: request.value.unwrap_or_else(U256::zero),
data: request.data.map_or_else(Vec::new, |d| d.to_vec())
}.fake_sign(from))
}
fn dapp_accounts(&self, dapp: DappId) -> Result<Vec<H160>, Error> {
let store = take_weak!(self.accounts);
store
@ -654,7 +641,7 @@ impl<C, SN: ?Sized, S: ?Sized, M, EM> Eth for EthClient<C, SN, S, M, EM> where
fn call(&self, request: CallRequest, num: Trailing<BlockNumber>) -> BoxFuture<Bytes, Error> {
let request = CallRequest::into(request);
let signed = match self.sign_call(request) {
let signed = match fake_sign::sign_call(&self.client, &self.miner, request) {
Ok(signed) => signed,
Err(e) => return future::err(e).boxed(),
};
@ -672,7 +659,7 @@ impl<C, SN: ?Sized, S: ?Sized, M, EM> Eth for EthClient<C, SN, S, M, EM> where
fn estimate_gas(&self, request: CallRequest, num: Trailing<BlockNumber>) -> BoxFuture<RpcU256, Error> {
let request = CallRequest::into(request);
let signed = match self.sign_call(request) {
let signed = match fake_sign::sign_call(&self.client, &self.miner, request) {
Ok(signed) => signed,
Err(e) => return future::err(e).boxed(),
};

View File

@ -27,15 +27,15 @@ use v1::types::{TraceFilter, LocalizedTrace, BlockNumber, Index, CallRequest, By
pub struct TracesClient;
impl Traces for TracesClient {
fn filter(&self, _filter: TraceFilter) -> Result<Vec<LocalizedTrace>, Error> {
fn filter(&self, _filter: TraceFilter) -> Result<Option<Vec<LocalizedTrace>>, Error> {
Err(errors::light_unimplemented(None))
}
fn block_traces(&self, _block_number: BlockNumber) -> Result<Vec<LocalizedTrace>, Error> {
fn block_traces(&self, _block_number: BlockNumber) -> Result<Option<Vec<LocalizedTrace>>, Error> {
Err(errors::light_unimplemented(None))
}
fn transaction_traces(&self, _transaction_hash: H256) -> Result<Vec<LocalizedTrace>, Error> {
fn transaction_traces(&self, _transaction_hash: H256) -> Result<Option<Vec<LocalizedTrace>>, Error> {
Err(errors::light_unimplemented(None))
}
@ -43,15 +43,15 @@ impl Traces for TracesClient {
Err(errors::light_unimplemented(None))
}
fn call(&self, _request: CallRequest, _flags: Vec<String>, _block: Trailing<BlockNumber>) -> Result<Option<TraceResults>, Error> {
fn call(&self, _request: CallRequest, _flags: Vec<String>, _block: Trailing<BlockNumber>) -> Result<TraceResults, Error> {
Err(errors::light_unimplemented(None))
}
fn raw_transaction(&self, _raw_transaction: Bytes, _flags: Vec<String>, _block: Trailing<BlockNumber>) -> Result<Option<TraceResults>, Error> {
fn raw_transaction(&self, _raw_transaction: Bytes, _flags: Vec<String>, _block: Trailing<BlockNumber>) -> Result<TraceResults, Error> {
Err(errors::light_unimplemented(None))
}
fn replay_transaction(&self, _transaction_hash: H256, _flags: Vec<String>) -> Result<Option<TraceResults>, Error> {
fn replay_transaction(&self, _transaction_hash: H256, _flags: Vec<String>) -> Result<TraceResults, Error> {
Err(errors::light_unimplemented(None))
}
}

View File

@ -19,14 +19,14 @@
use std::sync::{Weak, Arc};
use rlp::{UntrustedRlp, View};
use ethcore::client::{BlockChainClient, CallAnalytics, TransactionId, TraceId};
use ethcore::client::{MiningBlockChainClient, CallAnalytics, TransactionId, TraceId};
use ethcore::miner::MinerService;
use ethcore::transaction::{Transaction as EthTransaction, SignedTransaction, Action};
use ethcore::transaction::SignedTransaction;
use jsonrpc_core::Error;
use jsonrpc_macros::Trailing;
use v1::traits::Traces;
use v1::helpers::{errors, CallRequest as CRequest};
use v1::helpers::{errors, fake_sign};
use v1::types::{TraceFilter, LocalizedTrace, BlockNumber, Index, CallRequest, Bytes, TraceResults, H256};
fn to_call_analytics(flags: Vec<String>) -> CallAnalytics {
@ -38,12 +38,12 @@ fn to_call_analytics(flags: Vec<String>) -> CallAnalytics {
}
/// Traces api implementation.
pub struct TracesClient<C, M> where C: BlockChainClient, M: MinerService {
pub struct TracesClient<C, M> {
client: Weak<C>,
miner: Weak<M>,
}
impl<C, M> TracesClient<C, M> where C: BlockChainClient, M: MinerService {
impl<C, M> TracesClient<C, M> {
/// Creates new Traces client.
pub fn new(client: &Arc<C>, miner: &Arc<M>) -> Self {
TracesClient {
@ -51,86 +51,59 @@ impl<C, M> TracesClient<C, M> where C: BlockChainClient, M: MinerService {
miner: Arc::downgrade(miner),
}
}
// TODO: share with eth.rs
fn sign_call(&self, request: CRequest) -> Result<SignedTransaction, Error> {
let client = take_weak!(self.client);
let miner = take_weak!(self.miner);
let from = request.from.unwrap_or(0.into());
Ok(EthTransaction {
nonce: request.nonce.unwrap_or_else(|| client.latest_nonce(&from)),
action: request.to.map_or(Action::Create, Action::Call),
gas: request.gas.unwrap_or(50_000_000.into()),
gas_price: request.gas_price.unwrap_or_else(|| miner.sensible_gas_price()),
value: request.value.unwrap_or(0.into()),
data: request.data.map_or_else(Vec::new, |d| d.to_vec())
}.fake_sign(from))
}
}
impl<C, M> Traces for TracesClient<C, M> where C: BlockChainClient + 'static, M: MinerService + 'static {
fn filter(&self, filter: TraceFilter) -> Result<Vec<LocalizedTrace>, Error> {
let client = take_weak!(self.client);
let traces = client.filter_traces(filter.into());
let traces = traces.map_or_else(Vec::new, |traces| traces.into_iter().map(LocalizedTrace::from).collect());
Ok(traces)
impl<C, M> Traces for TracesClient<C, M> where C: MiningBlockChainClient + 'static, M: MinerService + 'static {
fn filter(&self, filter: TraceFilter) -> Result<Option<Vec<LocalizedTrace>>, Error> {
Ok(take_weak!(self.client).filter_traces(filter.into())
.map(|traces| traces.into_iter().map(LocalizedTrace::from).collect()))
}
fn block_traces(&self, block_number: BlockNumber) -> Result<Vec<LocalizedTrace>, Error> {
let client = take_weak!(self.client);
let traces = client.block_traces(block_number.into());
let traces = traces.map_or_else(Vec::new, |traces| traces.into_iter().map(LocalizedTrace::from).collect());
Ok(traces)
fn block_traces(&self, block_number: BlockNumber) -> Result<Option<Vec<LocalizedTrace>>, Error> {
Ok(take_weak!(self.client).block_traces(block_number.into())
.map(|traces| traces.into_iter().map(LocalizedTrace::from).collect()))
}
fn transaction_traces(&self, transaction_hash: H256) -> Result<Vec<LocalizedTrace>, Error> {
let client = take_weak!(self.client);
let traces = client.transaction_traces(TransactionId::Hash(transaction_hash.into()));
let traces = traces.map_or_else(Vec::new, |traces| traces.into_iter().map(LocalizedTrace::from).collect());
Ok(traces)
fn transaction_traces(&self, transaction_hash: H256) -> Result<Option<Vec<LocalizedTrace>>, Error> {
Ok(take_weak!(self.client).transaction_traces(TransactionId::Hash(transaction_hash.into()))
.map(|traces| traces.into_iter().map(LocalizedTrace::from).collect()))
}
fn trace(&self, transaction_hash: H256, address: Vec<Index>) -> Result<Option<LocalizedTrace>, Error> {
let client = take_weak!(self.client);
let id = TraceId {
transaction: TransactionId::Hash(transaction_hash.into()),
address: address.into_iter().map(|i| i.value()).collect()
};
let trace = client.trace(id);
let trace = trace.map(LocalizedTrace::from);
Ok(trace)
Ok(take_weak!(self.client).trace(id)
.map(LocalizedTrace::from))
}
fn call(&self, request: CallRequest, flags: Vec<String>, block: Trailing<BlockNumber>) -> Result<Option<TraceResults>, Error> {
fn call(&self, request: CallRequest, flags: Vec<String>, block: Trailing<BlockNumber>) -> Result<TraceResults, Error> {
let block = block.0;
let request = CallRequest::into(request);
let signed = self.sign_call(request)?;
Ok(match take_weak!(self.client).call(&signed, block.into(), to_call_analytics(flags)) {
Ok(e) => Some(TraceResults::from(e)),
_ => None,
})
let signed = fake_sign::sign_call(&self.client, &self.miner, request)?;
take_weak!(self.client).call(&signed, block.into(), to_call_analytics(flags))
.map(TraceResults::from)
.map_err(errors::from_call_error)
}
fn raw_transaction(&self, raw_transaction: Bytes, flags: Vec<String>, block: Trailing<BlockNumber>) -> Result<Option<TraceResults>, Error> {
fn raw_transaction(&self, raw_transaction: Bytes, flags: Vec<String>, block: Trailing<BlockNumber>) -> Result<TraceResults, Error> {
let block = block.0;
UntrustedRlp::new(&raw_transaction.into_vec()).as_val()
.map_err(|e| errors::invalid_params("Transaction is not valid RLP", e))
.and_then(|tx| SignedTransaction::new(tx).map_err(errors::from_transaction_error))
.and_then(|signed| {
Ok(match take_weak!(self.client).call(&signed, block.into(), to_call_analytics(flags)) {
Ok(e) => Some(TraceResults::from(e)),
_ => None,
})
})
let tx = UntrustedRlp::new(&raw_transaction.into_vec()).as_val().map_err(|e| errors::invalid_params("Transaction is not valid RLP", e))?;
let signed = SignedTransaction::new(tx).map_err(errors::from_transaction_error)?;
take_weak!(self.client).call(&signed, block.into(), to_call_analytics(flags))
.map(TraceResults::from)
.map_err(errors::from_call_error)
}
fn replay_transaction(&self, transaction_hash: H256, flags: Vec<String>) -> Result<Option<TraceResults>, Error> {
Ok(match take_weak!(self.client).replay(TransactionId::Hash(transaction_hash.into()), to_call_analytics(flags)) {
Ok(e) => Some(TraceResults::from(e)),
_ => None,
})
fn replay_transaction(&self, transaction_hash: H256, flags: Vec<String>) -> Result<TraceResults, Error> {
take_weak!(self.client).replay(TransactionId::Hash(transaction_hash.into()), to_call_analytics(flags))
.map(TraceResults::from)
.map_err(errors::from_call_error)
}
}

View File

@ -64,6 +64,7 @@ fn miner_service(spec: &Spec, accounts: Arc<AccountProvider>) -> Arc<Miner> {
tx_queue_banning: Banning::Disabled,
pending_set: PendingSet::SealingOrElseQueue,
reseal_min_period: Duration::from_secs(0),
reseal_max_period: Duration::from_secs(120),
work_queue_size: 50,
enable_resubmission: true,
refuse_service_transactions: false,

View File

@ -901,7 +901,7 @@ fn rpc_eth_send_transaction_with_bad_to() {
"id": 1
}"#;
let response = r#"{"jsonrpc":"2.0","error":{"code":-32602,"message":"Invalid length."},"id":1}"#;
let response = r#"{"jsonrpc":"2.0","error":{"code":-32602,"message":"Invalid params: expected a hex-encoded hash with 0x prefix."},"id":1}"#;
assert_eq!(tester.io.handle_request_sync(&request), Some(response.into()));
}

View File

@ -357,7 +357,7 @@ fn rpc_parity_unsigned_transactions_count_when_signer_disabled() {
let io = deps.default_client();
let request = r#"{"jsonrpc": "2.0", "method": "parity_unsignedTransactionsCount", "params":[], "id": 1}"#;
let response = r#"{"jsonrpc":"2.0","error":{"code":-32030,"message":"Trusted Signer is disabled. This API is not available."},"id":1}"#;
let response = r#"{"jsonrpc":"2.0","error":{"code":-32000,"message":"Trusted Signer is disabled. This API is not available."},"id":1}"#;
assert_eq!(io.handle_request_sync(request), Some(response.to_owned()));
}
@ -393,7 +393,7 @@ fn rpc_parity_signer_port() {
// when
let request = r#"{"jsonrpc": "2.0", "method": "parity_signerPort", "params": [], "id": 1}"#;
let response1 = r#"{"jsonrpc":"2.0","result":18180,"id":1}"#;
let response2 = r#"{"jsonrpc":"2.0","error":{"code":-32030,"message":"Trusted Signer is disabled. This API is not available."},"id":1}"#;
let response2 = r#"{"jsonrpc":"2.0","error":{"code":-32000,"message":"Trusted Signer is disabled. This API is not available."},"id":1}"#;
// then
assert_eq!(io1.handle_request_sync(request), Some(response1.to_owned()));
@ -411,7 +411,7 @@ fn rpc_parity_dapps_port() {
// when
let request = r#"{"jsonrpc": "2.0", "method": "parity_dappsPort", "params": [], "id": 1}"#;
let response1 = r#"{"jsonrpc":"2.0","result":18080,"id":1}"#;
let response2 = r#"{"jsonrpc":"2.0","error":{"code":-32031,"message":"Dapps Server is disabled. This API is not available."},"id":1}"#;
let response2 = r#"{"jsonrpc":"2.0","error":{"code":-32000,"message":"Dapps Server is disabled. This API is not available."},"id":1}"#;
// then
assert_eq!(io1.handle_request_sync(request), Some(response1.to_owned()));
@ -429,7 +429,7 @@ fn rpc_parity_dapps_interface() {
// when
let request = r#"{"jsonrpc": "2.0", "method": "parity_dappsInterface", "params": [], "id": 1}"#;
let response1 = r#"{"jsonrpc":"2.0","result":"127.0.0.1","id":1}"#;
let response2 = r#"{"jsonrpc":"2.0","error":{"code":-32031,"message":"Dapps Server is disabled. This API is not available."},"id":1}"#;
let response2 = r#"{"jsonrpc":"2.0","error":{"code":-32000,"message":"Dapps Server is disabled. This API is not available."},"id":1}"#;
// then
assert_eq!(io1.handle_request_sync(request), Some(response1.to_owned()));

View File

@ -230,7 +230,7 @@ fn should_be_able_to_kill_account() {
let address = accounts[0];
let request = format!(r#"{{"jsonrpc": "2.0", "method": "parity_killAccount", "params": ["0xf00baba2f00baba2f00baba2f00baba2f00baba2"], "id": 1}}"#);
let response = r#"{"jsonrpc":"2.0","error":{"code":-32602,"message":"invalid length 1, expected a tuple of size 2"},"id":1}"#;
let response = r#"{"jsonrpc":"2.0","error":{"code":-32602,"message":"Invalid params: invalid length 1, expected a tuple of size 2."},"id":1}"#;
let res = tester.io.handle_request_sync(&request);
assert_eq!(res, Some(response.into()));

View File

@ -16,17 +16,17 @@
use std::sync::Arc;
use ethcore::executed::{CallType, Executed};
use ethcore::executed::{CallType, Executed, CallError};
use ethcore::trace::trace::{Action, Res, Call};
use ethcore::trace::LocalizedTrace;
use ethcore::client::{TestBlockChainClient};
use ethcore::client::TestBlockChainClient;
use jsonrpc_core::IoHandler;
use v1::tests::helpers::{TestMinerService};
use v1::{Traces, TracesClient};
struct Tester {
_client: Arc<TestBlockChainClient>,
client: Arc<TestBlockChainClient>,
_miner: Arc<TestMinerService>,
io: IoHandler,
}
@ -69,7 +69,7 @@ fn io() -> Tester {
io.extend_with(traces.to_delegate());
Tester {
_client: client,
client: client,
_miner: miner,
io: io,
}
@ -85,6 +85,17 @@ fn rpc_trace_filter() {
assert_eq!(tester.io.handle_request_sync(request), Some(response.to_owned()));
}
#[test]
fn rpc_trace_filter_missing_trace() {
let tester = io();
*tester.client.traces.write() = None;
let request = r#"{"jsonrpc":"2.0","method":"trace_filter","params": [{}],"id":1}"#;
let response = r#"{"jsonrpc":"2.0","result":null,"id":1}"#;
assert_eq!(tester.io.handle_request_sync(request), Some(response.to_owned()));
}
#[test]
fn rpc_trace_block() {
let tester = io();
@ -95,6 +106,17 @@ fn rpc_trace_block() {
assert_eq!(tester.io.handle_request_sync(request), Some(response.to_owned()));
}
#[test]
fn rpc_trace_block_missing_traces() {
let tester = io();
*tester.client.traces.write() = None;
let request = r#"{"jsonrpc":"2.0","method":"trace_block","params": ["0x10"],"id":1}"#;
let response = r#"{"jsonrpc":"2.0","result":null,"id":1}"#;
assert_eq!(tester.io.handle_request_sync(request), Some(response.to_owned()));
}
#[test]
fn rpc_trace_transaction() {
let tester = io();
@ -105,6 +127,17 @@ fn rpc_trace_transaction() {
assert_eq!(tester.io.handle_request_sync(request), Some(response.to_owned()));
}
#[test]
fn rpc_trace_transaction_missing_trace() {
let tester = io();
*tester.client.traces.write() = None;
let request = r#"{"jsonrpc":"2.0","method":"trace_transaction","params":["0x0000000000000000000000000000000000000000000000000000000000000005"],"id":1}"#;
let response = r#"{"jsonrpc":"2.0","result":null,"id":1}"#;
assert_eq!(tester.io.handle_request_sync(request), Some(response.to_owned()));
}
#[test]
fn rpc_trace_get() {
let tester = io();
@ -115,6 +148,16 @@ fn rpc_trace_get() {
assert_eq!(tester.io.handle_request_sync(request), Some(response.to_owned()));
}
#[test]
fn rpc_trace_get_missing_trace() {
let tester = io();
*tester.client.traces.write() = None;
let request = r#"{"jsonrpc":"2.0","method":"trace_get","params":["0x0000000000000000000000000000000000000000000000000000000000000005", ["0","0","0"]],"id":1}"#;
let response = r#"{"jsonrpc":"2.0","result":null,"id":1}"#;
assert_eq!(tester.io.handle_request_sync(request), Some(response.to_owned()));
}
#[test]
fn rpc_trace_call() {
let tester = io();
@ -125,6 +168,17 @@ fn rpc_trace_call() {
assert_eq!(tester.io.handle_request_sync(request), Some(response.to_owned()));
}
#[test]
fn rpc_trace_call_state_pruned() {
let tester = io();
*tester.client.execution_result.write() = Some(Err(CallError::StatePruned));
let request = r#"{"jsonrpc":"2.0","method":"trace_call","params":[{}, ["stateDiff", "vmTrace", "trace"]],"id":1}"#;
let response = r#"{"jsonrpc":"2.0","error":{"code":-32000,"message":"This request is not supported because your node is running with state pruning. Run with --pruning=archive."},"id":1}"#;
assert_eq!(tester.io.handle_request_sync(request), Some(response.to_owned()));
}
#[test]
fn rpc_trace_raw_transaction() {
let tester = io();
@ -135,6 +189,17 @@ fn rpc_trace_raw_transaction() {
assert_eq!(tester.io.handle_request_sync(request), Some(response.to_owned()));
}
#[test]
fn rpc_trace_raw_transaction_state_pruned() {
let tester = io();
*tester.client.execution_result.write() = Some(Err(CallError::StatePruned));
let request = r#"{"jsonrpc":"2.0","method":"trace_rawTransaction","params":["0xf869018609184e72a0008276c094d46e8dd67c5d32be8058bb8eb970870f07244567849184e72a801ba0617f39c1a107b63302449c476d96a6cb17a5842fc98ff0c5bcf4d5c4d8166b95a009fdb6097c6196b9bbafc3a59f02f38d91baeef23d0c60a8e4f23c7714cea3a9", ["stateDiff", "vmTrace", "trace"]],"id":1}"#;
let response = r#"{"jsonrpc":"2.0","error":{"code":-32000,"message":"This request is not supported because your node is running with state pruning. Run with --pruning=archive."},"id":1}"#;
assert_eq!(tester.io.handle_request_sync(request), Some(response.to_owned()));
}
#[test]
fn rpc_trace_replay_transaction() {
let tester = io();
@ -144,3 +209,14 @@ fn rpc_trace_replay_transaction() {
assert_eq!(tester.io.handle_request_sync(request), Some(response.to_owned()));
}
#[test]
fn rpc_trace_replay_transaction_state_pruned() {
let tester = io();
*tester.client.execution_result.write() = Some(Err(CallError::StatePruned));
let request = r#"{"jsonrpc":"2.0","method":"trace_replayTransaction","params":["0x0000000000000000000000000000000000000000000000000000000000000005", ["trace", "stateDiff", "vmTrace"]],"id":1}"#;
let response = r#"{"jsonrpc":"2.0","error":{"code":-32000,"message":"This request is not supported because your node is running with state pruning. Run with --pruning=archive."},"id":1}"#;
assert_eq!(tester.io.handle_request_sync(request), Some(response.to_owned()));
}

View File

@ -25,7 +25,7 @@ build_rpc_trait! {
pub trait Traces {
/// Returns traces matching given filter.
#[rpc(name = "trace_filter")]
fn filter(&self, TraceFilter) -> Result<Vec<LocalizedTrace>, Error>;
fn filter(&self, TraceFilter) -> Result<Option<Vec<LocalizedTrace>>, Error>;
/// Returns transaction trace at given index.
#[rpc(name = "trace_get")]
@ -33,22 +33,22 @@ build_rpc_trait! {
/// Returns all traces of given transaction.
#[rpc(name = "trace_transaction")]
fn transaction_traces(&self, H256) -> Result<Vec<LocalizedTrace>, Error>;
fn transaction_traces(&self, H256) -> Result<Option<Vec<LocalizedTrace>>, Error>;
/// Returns all traces produced at given block.
#[rpc(name = "trace_block")]
fn block_traces(&self, BlockNumber) -> Result<Vec<LocalizedTrace>, Error>;
fn block_traces(&self, BlockNumber) -> Result<Option<Vec<LocalizedTrace>>, Error>;
/// Executes the given call and returns a number of possible traces for it.
#[rpc(name = "trace_call")]
fn call(&self, CallRequest, Vec<String>, Trailing<BlockNumber>) -> Result<Option<TraceResults>, Error>;
fn call(&self, CallRequest, Vec<String>, Trailing<BlockNumber>) -> Result<TraceResults, Error>;
/// Executes the given raw transaction and returns a number of possible traces for it.
#[rpc(name = "trace_rawTransaction")]
fn raw_transaction(&self, Bytes, Vec<String>, Trailing<BlockNumber>) -> Result<Option<TraceResults>, Error>;
fn raw_transaction(&self, Bytes, Vec<String>, Trailing<BlockNumber>) -> Result<TraceResults, Error>;
/// Executes the transaction with the given hash and returns a number of possible traces for it.
#[rpc(name = "trace_replayTransaction")]
fn replay_transaction(&self, H256, Vec<String>) -> Result<Option<TraceResults>, Error>;
fn replay_transaction(&self, H256, Vec<String>) -> Result<TraceResults, Error>;
}
}

View File

@ -130,7 +130,7 @@ macro_rules! impl_hash {
fn visit_str<E>(self, value: &str) -> Result<Self::Value, E> where E: serde::de::Error {
if value.len() < 2 || &value[0..2] != "0x" {
return Err(E::custom("Expected hex-encoded hash with 0x prefix."));
return Err(E::custom("expected a hex-encoded hash with 0x prefix"));
}
if value.len() != 2 + $size * 2 {
return Err(E::invalid_length(value.len() - 2, &self));
@ -142,7 +142,7 @@ macro_rules! impl_hash {
result.copy_from_slice(v);
Ok($name(result))
},
Err(e) => Err(E::custom(format!("Invalid hex value: {:?}", e))),
Err(e) => Err(E::custom(format!("invalid hex value: {:?}", e))),
}
}

View File

@ -79,7 +79,7 @@ macro_rules! impl_uint {
fn visit_str<E>(self, value: &str) -> Result<Self::Value, E> where E: serde::de::Error {
if value.len() < 2 || &value[0..2] != "0x" {
return Err(E::custom("Use hex-encoded numbers with 0x prefix."))
return Err(E::custom("expected a hex-encoded numbers with 0x prefix"))
}
// 0x + len
@ -87,7 +87,7 @@ macro_rules! impl_uint {
return Err(E::invalid_length(value.len() - 2, &self));
}
$other::from_str(&value[2..]).map($name).map_err(|e| E::custom(&format!("Invalid hex value: {:?}", e)))
$other::from_str(&value[2..]).map($name).map_err(|e| E::custom(&format!("invalid hex value: {:?}", e)))
}
fn visit_string<E>(self, value: String) -> Result<Self::Value, E> where E: serde::de::Error {

View File

@ -1,4 +1,4 @@
#!/bin/sh
#!/bin/bash
# Installing KCOV under ubuntu
# https://users.rust-lang.org/t/tutorial-how-to-collect-test-coverages-for-rust-project/650#
### Install deps
@ -24,8 +24,7 @@ fi
cargo test $TARGETS --no-run || exit $?
KCOV_TARGET="target/kcov"
KCOV_TARGET="target/cov"
KCOV_FLAGS="--verify"
EXCLUDE="/usr/lib,\
/usr/include,\
@ -39,17 +38,25 @@ util/src/network/tests,\
ethcore/src/evm/tests,\
ethstore/tests,\
target/debug/build,\
target/release/build\
target/release/build,\
*.db
"
rm -rf $KCOV_TARGET
mkdir -p $KCOV_TARGET
echo "Cover RUST"
for FILE in `find target/debug/deps ! -name "*.*"`
do
$KCOV --exclude-pattern $EXCLUDE $KCOV_FLAGS $KCOV_TARGET $FILE
done
$KCOV --coveralls-id=${CI_BUILD_ID} --exclude-pattern $EXCLUDE $KCOV_FLAGS $KCOV_TARGET target/debug/parity-*
$KCOV --exclude-pattern $EXCLUDE $KCOV_FLAGS $KCOV_TARGET target/debug/parity-*
echo "Cover JS"
cd js
npm install&&npm run test:coverage
cd ..
codecov
bash <(curl -s https://codecov.io/bash)&&
echo "Uploaded code coverage"
exit 0

View File

@ -25,7 +25,7 @@ echo "Homepage: https://ethcore.io" >> $control
echo "Vcs-Git: git://github.com/ethcore/parity.git" >> $control
echo "Vcs-Browser: https://github.com/ethcore/parity" >> $control
echo "Architecture: $1" >> $control
echo "Depends: libssl1.0.0 (>=1.0.0), libudev-dev" >> $control
echo "Depends: libssl1.0.0 (>=1.0.0)" >> $control
echo "Description: Ethereum network client by Ethcore" >> $control
#build .deb package

View File

@ -1,4 +1,5 @@
#!/bin/bash
cd docker/hub
docker build --build-arg BUILD_TAG=$1 --no-cache=true --tag ethcore/parity:$1 .
if [ "$1" == "latest" ]; then DOCKER_BUILD_TAG="beta-release"; fi
docker build --build-arg BUILD_TAG=$DOCKER_BUILD_TAG --no-cache=true --tag ethcore/parity:$1 .
docker push ethcore/parity:$1