From 5e34235a3645e7090c20e6804f5348098ba07074 Mon Sep 17 00:00:00 2001 From: NikVolf Date: Wed, 22 Mar 2017 04:01:46 +0300 Subject: [PATCH 01/72] initial, fallable built-ins --- Cargo.lock | 18 ++++++ ethcore/Cargo.toml | 1 + ethcore/res/ethereum/foundation.json | 2 + ethcore/src/builtin.rs | 77 +++++++++++++++++++++++--- ethcore/src/evm/evm.rs | 9 +++ ethcore/src/executive.rs | 3 +- ethcore/src/lib.rs | 1 + ethcore/src/types/trace_types/error.rs | 7 ++- 8 files changed, 107 insertions(+), 11 deletions(-) diff --git a/Cargo.lock b/Cargo.lock index e61658e16..42d6054e6 100644 --- a/Cargo.lock +++ b/Cargo.lock @@ -175,6 +175,21 @@ name = "bloomchain" version = "0.1.0" source = "registry+https://github.com/rust-lang/crates.io-index" +[[package]] +name = "bn" +version = "0.4.2" +source = "git+https://github.com/paritytech/bn#78cf02fd7b35e4a2398fedd96f68c92953badea7" +dependencies = [ + "byteorder 0.5.3 (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)", +] + +[[package]] +name = "byteorder" +version = "0.5.3" +source = "registry+https://github.com/rust-lang/crates.io-index" + [[package]] name = "byteorder" version = "1.0.0" @@ -382,6 +397,7 @@ version = "1.7.0" dependencies = [ "bit-set 0.4.0 (registry+https://github.com/rust-lang/crates.io-index)", "bloomchain 0.1.0 (registry+https://github.com/rust-lang/crates.io-index)", + "bn 0.4.2 (git+https://github.com/paritytech/bn)", "byteorder 1.0.0 (registry+https://github.com/rust-lang/crates.io-index)", "clippy 0.0.103 (registry+https://github.com/rust-lang/crates.io-index)", "crossbeam 0.2.10 (registry+https://github.com/rust-lang/crates.io-index)", @@ -2617,6 +2633,8 @@ dependencies = [ "checksum bitflags 0.7.0 (registry+https://github.com/rust-lang/crates.io-index)" = "aad18937a628ec6abcd26d1489012cc0e18c21798210f491af69ded9b881106d" "checksum blastfig 0.3.3 (registry+https://github.com/rust-lang/crates.io-index)" = "09640e0509d97d5cdff03a9f5daf087a8e04c735c3b113a75139634a19cfc7b2" "checksum bloomchain 0.1.0 (registry+https://github.com/rust-lang/crates.io-index)" = "3f421095d2a76fc24cd3fb3f912b90df06be7689912b1bdb423caefae59c258d" +"checksum bn 0.4.2 (git+https://github.com/paritytech/bn)" = "" +"checksum byteorder 0.5.3 (registry+https://github.com/rust-lang/crates.io-index)" = "0fc10e8cc6b2580fda3f36eb6dc5316657f812a3df879a44a66fc9f0fdbc4855" "checksum byteorder 1.0.0 (registry+https://github.com/rust-lang/crates.io-index)" = "c40977b0ee6b9885c9013cd41d9feffdd22deb3bb4dc3a71d901cc7a77de18c8" "checksum bytes 0.3.0 (registry+https://github.com/rust-lang/crates.io-index)" = "c129aff112dcc562970abb69e2508b40850dd24c274761bb50fb8a0067ba6c27" "checksum bytes 0.4.0-dev (git+https://github.com/carllerche/bytes)" = "" diff --git a/ethcore/Cargo.toml b/ethcore/Cargo.toml index d1c9d624b..c44e98763 100644 --- a/ethcore/Cargo.toml +++ b/ethcore/Cargo.toml @@ -45,6 +45,7 @@ ethcore-bloom-journal = { path = "../util/bloom" } hardware-wallet = { path = "../hw" } stats = { path = "../util/stats" } num = "0.1" +bn = { git = "https://github.com/paritytech/bn" } [dependencies.hyper] git = "https://github.com/ethcore/hyper" diff --git a/ethcore/res/ethereum/foundation.json b/ethcore/res/ethereum/foundation.json index 77b0d5533..1debff1d6 100644 --- a/ethcore/res/ethereum/foundation.json +++ b/ethcore/res/ethereum/foundation.json @@ -190,6 +190,8 @@ "0000000000000000000000000000000000000003": { "builtin": { "name": "ripemd160", "pricing": { "linear": { "base": 600, "word": 120 } } } }, "0000000000000000000000000000000000000004": { "builtin": { "name": "identity", "pricing": { "linear": { "base": 15, "word": 3 } } } }, "0000000000000000000000000000000000000005": { "builtin": { "name": "modexp", "activate_at": "0x7fffffffffffff", "pricing": { "modexp": { "divisor": 20 } } } }, + "0000000000000000000000000000000000000006": { "builtin": { "name": "alt_bn128_add", "activate_at": "0x7fffffffffffff", "pricing": { "linear": { "base": 999999, "word": 0 } } } }, + "0000000000000000000000000000000000000007": { "builtin": { "name": "alt_bn128_mul", "activate_at": "0x7fffffffffffff", "pricing": { "linear": { "base": 999999, "word": 0 } } } }, "3282791d6fd713f1e94f4bfd565eaa78b3a0599d": { "balance": "1337000000000000000000" }, diff --git a/ethcore/src/builtin.rs b/ethcore/src/builtin.rs index 9927435dd..7de9409a0 100644 --- a/ethcore/src/builtin.rs +++ b/ethcore/src/builtin.rs @@ -27,10 +27,19 @@ use util::{U256, H256, Uint, Hashable, BytesRef}; use ethkey::{Signature, recover as ec_recover}; use ethjson; +#[derive(Debug)] +pub struct Error(pub String); + +impl From<&'static str> for Error { + fn from(val: &'static str) -> Self { + Error(val.to_owned()) + } +} + /// Native implementation of a built-in contract. pub trait Impl: Send + Sync { /// execute this built-in on the given input, writing to the given output. - fn execute(&self, input: &[u8], output: &mut BytesRef); + fn execute(&self, input: &[u8], output: &mut BytesRef) -> Result<(), Error>; } /// A gas pricing scheme for built-in contracts. @@ -102,7 +111,10 @@ impl Builtin { pub fn cost(&self, input: &[u8]) -> U256 { self.pricer.cost(input) } /// Simple forwarder for execute. - pub fn execute(&self, input: &[u8], output: &mut BytesRef) { self.native.execute(input, output) } + pub fn execute(&self, input: &[u8], output: &mut BytesRef) -> Result<(), Error> { + self.native.execute(input, output); + Ok(()) + } /// Whether the builtin is activated at the given block number. pub fn is_active(&self, at: u64) -> bool { at >= self.activate_at } @@ -172,14 +184,21 @@ struct Ripemd160; #[derive(Debug)] struct ModexpImpl; +#[derive(Debug)] +struct Bn128AddImpl; + +#[derive(Debug)] +struct Bn128MulImpl; + impl Impl for Identity { - fn execute(&self, input: &[u8], output: &mut BytesRef) { + fn execute(&self, input: &[u8], output: &mut BytesRef) -> Result<(), Error> { output.write(0, input); + Ok(()) } } impl Impl for EcRecover { - fn execute(&self, i: &[u8], output: &mut BytesRef) { + fn execute(&self, i: &[u8], output: &mut BytesRef) -> Result<(), Error> { let len = min(i.len(), 128); let mut input = [0; 128]; @@ -192,7 +211,7 @@ impl Impl for EcRecover { let bit = match v[31] { 27 | 28 if &v.0[..31] == &[0; 31] => v[31] - 27, - _ => return, + _ => { return Ok(()); }, }; let s = Signature::from_rsv(&r, &s, bit); @@ -203,11 +222,13 @@ impl Impl for EcRecover { output.write(12, &r[12..r.len()]); } } + + Ok(()) } } impl Impl for Sha256 { - fn execute(&self, input: &[u8], output: &mut BytesRef) { + fn execute(&self, input: &[u8], output: &mut BytesRef) -> Result<(), Error> { let mut sha = Sha256Digest::new(); sha.input(input); @@ -215,11 +236,13 @@ impl Impl for Sha256 { sha.result(&mut out); output.write(0, &out); + + Ok(()) } } impl Impl for Ripemd160 { - fn execute(&self, input: &[u8], output: &mut BytesRef) { + fn execute(&self, input: &[u8], output: &mut BytesRef) -> Result<(), Error> { let mut sha = Ripemd160Digest::new(); sha.input(input); @@ -227,11 +250,13 @@ impl Impl for Ripemd160 { sha.result(&mut out[12..32]); output.write(0, &out); + + Ok(()) } } impl Impl for ModexpImpl { - fn execute(&self, input: &[u8], output: &mut BytesRef) { + fn execute(&self, input: &[u8], output: &mut BytesRef) -> Result<(), Error> { let mut reader = input.chain(io::repeat(0)); let mut buf = [0; 32]; @@ -294,9 +319,43 @@ impl Impl for ModexpImpl { let res_start = mod_len - bytes.len(); output.write(res_start, &bytes); } + + Ok(()) } } +impl Impl for Bn128AddImpl { + fn execute(&self, input: &[u8], output: &mut BytesRef) -> Result<(), Error> { + use bn::{Fq, AffineG1, G1}; + + let mut buf = [0u8; 32]; + let mut next_coord = |reader: &mut io::Chain<&[u8], io::Repeat>| { + reader.read_exact(&mut buf[..]).expect("reading from zero-extended memory cannot fail; qed"); + Fq::from_slice(&input[0..32]) + }; + + let mut padded_input = input.chain(io::repeat(0)); + + let p1x = next_coord(&mut padded_input).map_err(|_| Error::from("Invalid p1 x coordinate"))?; + let p1y = next_coord(&mut padded_input).map_err(|_| Error::from("Invalid p1 y coordinate"))?; + let p1: G1 = AffineG1::new(p1x, p1y).into(); + + let p2x = next_coord(&mut padded_input).map_err(|_| Error::from("Invalid p2 x coordinate"))?; + let p2y = next_coord(&mut padded_input).map_err(|_| Error::from("Invalid p2 y coordinate"))?; + let p2: G1 = AffineG1::new(p2x, p2y).into(); + + let sum = AffineG1::from_jacobian(p1 + p2).expect("Sum of two valid points is a valid point also; qed"); + + Ok(()) + } +} + +impl Impl for Bn128MulImpl { + fn execute(&self, input: &[u8], output: &mut BytesRef) -> Result<(), Error> { + Ok(()) + } +} + #[cfg(test)] mod tests { use super::{Builtin, Linear, ethereum_builtin, Pricer, Modexp}; @@ -574,4 +633,4 @@ mod tests { b.execute(&i[..], &mut BytesRef::Fixed(&mut o[..])); assert_eq!(i, o); } -} +} \ No newline at end of file diff --git a/ethcore/src/evm/evm.rs b/ethcore/src/evm/evm.rs index 09a93f087..b561c271f 100644 --- a/ethcore/src/evm/evm.rs +++ b/ethcore/src/evm/evm.rs @@ -20,6 +20,7 @@ use std::{ops, cmp, fmt}; use util::{U128, U256, U512, Uint, trie}; use action_params::ActionParams; use evm::Ext; +use builtin; /// Evm errors. #[derive(Debug, Clone, PartialEq)] @@ -59,6 +60,7 @@ pub enum Error { /// What was the stack limit limit: usize }, + BuiltIn(String), /// Returned on evm internal error. Should never be ignored during development. /// Likely to cause consensus issues. Internal(String), @@ -70,6 +72,12 @@ impl From> for Error { } } +impl From for Error { + fn from(err: builtin::Error) -> Self { + Error::BuiltIn(err.0) + } +} + impl fmt::Display for Error { fn fmt(&self, f: &mut fmt::Formatter) -> fmt::Result { use self::Error::*; @@ -79,6 +87,7 @@ impl fmt::Display for Error { BadInstruction { .. } => "Bad instruction", StackUnderflow { .. } => "Stack underflow", OutOfStack { .. } => "Out of stack", + BuiltIn { .. } => "Built-in failed", Internal(ref msg) => msg, }; message.fmt(f) diff --git a/ethcore/src/executive.rs b/ethcore/src/executive.rs index cdae8a85f..4fdd9cbbd 100644 --- a/ethcore/src/executive.rs +++ b/ethcore/src/executive.rs @@ -276,7 +276,7 @@ impl<'a, B: 'a + StateBackend> Executive<'a, B> { let cost = builtin.cost(data); if cost <= params.gas { - builtin.execute(data, &mut output); + builtin.execute(data, &mut output)?; self.state.discard_checkpoint(); // trace only top level calls to builtins to avoid DDoS attacks @@ -497,6 +497,7 @@ impl<'a, B: 'a + StateBackend> Executive<'a, B> { | Err(evm::Error::BadJumpDestination {..}) | Err(evm::Error::BadInstruction {.. }) | Err(evm::Error::StackUnderflow {..}) + | Err(evm::Error::BuiltIn {..}) | Err(evm::Error::OutOfStack {..}) => { self.state.revert_to_checkpoint(); }, diff --git a/ethcore/src/lib.rs b/ethcore/src/lib.rs index 75c8a80e1..641b841f3 100644 --- a/ethcore/src/lib.rs +++ b/ethcore/src/lib.rs @@ -107,6 +107,7 @@ extern crate ethabi; extern crate hardware_wallet; extern crate stats; extern crate num; +extern crate bn; #[macro_use] extern crate log; diff --git a/ethcore/src/types/trace_types/error.rs b/ethcore/src/types/trace_types/error.rs index 33ccf2bb7..c36d86728 100644 --- a/ethcore/src/types/trace_types/error.rs +++ b/ethcore/src/types/trace_types/error.rs @@ -34,7 +34,9 @@ pub enum Error { /// `StackUnderflow` when there is not enough stack elements to execute instruction StackUnderflow, /// When execution would exceed defined Stack Limit - OutOfStack, + OutOfStack, + /// When builtin contract failed on input data + BuiltIn, /// Returned on evm internal error. Should never be ignored during development. /// Likely to cause consensus issues. Internal, @@ -48,6 +50,7 @@ impl<'a> From<&'a EvmError> for Error { EvmError::BadInstruction { .. } => Error::BadInstruction, EvmError::StackUnderflow { .. } => Error::StackUnderflow, EvmError::OutOfStack { .. } => Error::OutOfStack, + EvmError::BuiltIn { .. } => Error::OutOfStack, EvmError::Internal(_) => Error::Internal, } } @@ -68,6 +71,7 @@ impl fmt::Display for Error { BadInstruction => "Bad instruction", StackUnderflow => "Stack underflow", OutOfStack => "Out of stack", + BuiltIn => "Built-in failed", Internal => "Internal error", }; message.fmt(f) @@ -84,6 +88,7 @@ impl Encodable for Error { StackUnderflow => 3, OutOfStack => 4, Internal => 5, + BuiltIn => 6, }; s.append_internal(&value); From 3e7dc57289eedc59dc1e87c8e334b92a23c474a0 Mon Sep 17 00:00:00 2001 From: NikVolf Date: Wed, 22 Mar 2017 15:41:32 +0300 Subject: [PATCH 02/72] some tests for simple cases --- Cargo.lock | 2 +- ethcore/src/builtin.rs | 81 ++++++++++++++++++++++++++++++++++++------ 2 files changed, 72 insertions(+), 11 deletions(-) diff --git a/Cargo.lock b/Cargo.lock index 42d6054e6..b92cbaed9 100644 --- a/Cargo.lock +++ b/Cargo.lock @@ -178,7 +178,7 @@ source = "registry+https://github.com/rust-lang/crates.io-index" [[package]] name = "bn" version = "0.4.2" -source = "git+https://github.com/paritytech/bn#78cf02fd7b35e4a2398fedd96f68c92953badea7" +source = "git+https://github.com/paritytech/bn#7e513a84330f02603759e370f22af90c99e3e717" dependencies = [ "byteorder 0.5.3 (registry+https://github.com/rust-lang/crates.io-index)", "rand 0.3.14 (registry+https://github.com/rust-lang/crates.io-index)", diff --git a/ethcore/src/builtin.rs b/ethcore/src/builtin.rs index 7de9409a0..112afbd97 100644 --- a/ethcore/src/builtin.rs +++ b/ethcore/src/builtin.rs @@ -112,7 +112,7 @@ impl Builtin { /// Simple forwarder for execute. pub fn execute(&self, input: &[u8], output: &mut BytesRef) -> Result<(), Error> { - self.native.execute(input, output); + self.native.execute(input, output)?; Ok(()) } @@ -157,6 +157,8 @@ fn ethereum_builtin(name: &str) -> Box { "sha256" => Box::new(Sha256) as Box, "ripemd160" => Box::new(Ripemd160) as Box, "modexp" => Box::new(ModexpImpl) as Box, + "alt_bn128_add" => Box::new(Bn128AddImpl) as Box, + "alt_bn128_mul" => Box::new(Bn128MulImpl) as Box, _ => panic!("invalid builtin name: {}", name), } } @@ -326,25 +328,39 @@ impl Impl for ModexpImpl { impl Impl for Bn128AddImpl { fn execute(&self, input: &[u8], output: &mut BytesRef) -> Result<(), Error> { - use bn::{Fq, AffineG1, G1}; + use bn::{Fq, AffineG1, G1, Group}; let mut buf = [0u8; 32]; let mut next_coord = |reader: &mut io::Chain<&[u8], io::Repeat>| { reader.read_exact(&mut buf[..]).expect("reading from zero-extended memory cannot fail; qed"); - Fq::from_slice(&input[0..32]) + Fq::from_slice(&buf[0..32]) }; let mut padded_input = input.chain(io::repeat(0)); - let p1x = next_coord(&mut padded_input).map_err(|_| Error::from("Invalid p1 x coordinate"))?; - let p1y = next_coord(&mut padded_input).map_err(|_| Error::from("Invalid p1 y coordinate"))?; - let p1: G1 = AffineG1::new(p1x, p1y).into(); + let px = next_coord(&mut padded_input).map_err(|_| Error::from("Invalid p1 x coordinate"))?; + let py = next_coord(&mut padded_input).map_err(|_| Error::from("Invalid p1 y coordinate"))?; + let p1: G1 = if px == Fq::zero() && py == Fq::zero() { + G1::zero() + } else { + AffineG1::new(px, py).map_err(|_| Error::from("Invalid curve point"))?.into() + }; - let p2x = next_coord(&mut padded_input).map_err(|_| Error::from("Invalid p2 x coordinate"))?; - let p2y = next_coord(&mut padded_input).map_err(|_| Error::from("Invalid p2 y coordinate"))?; - let p2: G1 = AffineG1::new(p2x, p2y).into(); + let px = next_coord(&mut padded_input).map_err(|_| Error::from("Invalid p1 x coordinate"))?; + let py = next_coord(&mut padded_input).map_err(|_| Error::from("Invalid p1 y coordinate"))?; + let p2: G1 = if px == Fq::zero() && py == Fq::zero() { + G1::zero() + } else { + AffineG1::new(px, py).map_err(|_| Error::from("Invalid curve point"))?.into() + }; - let sum = AffineG1::from_jacobian(p1 + p2).expect("Sum of two valid points is a valid point also; qed"); + let mut write_buf = [0u8; 64]; + if let Some(sum) = AffineG1::from_jacobian(p1 + p2) { + // point not at infinity + sum.x().to_big_endian(&mut write_buf[0..32]); + sum.y().to_big_endian(&mut write_buf[32..64]); + } + output.write(0, &write_buf); Ok(()) } @@ -572,6 +588,51 @@ mod tests { } } + #[test] + fn alt_bn128_add() { + use rustc_serialize::hex::FromHex; + + let f = Builtin { + pricer: Box::new(Linear { base: 0, word: 0 }), + native: ethereum_builtin("alt_bn128_add"), + activate_at: 0, + }; + + // zero-points additions + { + let input = FromHex::from_hex("\ + 0000000000000000000000000000000000000000000000000000000000000000\ + 0000000000000000000000000000000000000000000000000000000000000000\ + 0000000000000000000000000000000000000000000000000000000000000000\ + 0000000000000000000000000000000000000000000000000000000000000000" + ).unwrap(); + + let mut output = vec![0u8; 64]; + let expected = FromHex::from_hex("\ + 0000000000000000000000000000000000000000000000000000000000000000\ + 0000000000000000000000000000000000000000000000000000000000000000" + ).unwrap(); + + f.execute(&input[..], &mut BytesRef::Fixed(&mut output[..])).expect("Builtin should not fail"); + assert_eq!(output, expected); + } + + // should fail - point not on curve + { + let input = FromHex::from_hex("\ + 1111111111111111111111111111111111111111111111111111111111111111\ + 1111111111111111111111111111111111111111111111111111111111111111\ + 1111111111111111111111111111111111111111111111111111111111111111\ + 1111111111111111111111111111111111111111111111111111111111111111" + ).unwrap(); + + let mut output = vec![0u8; 64]; + + let res = f.execute(&input[..], &mut BytesRef::Fixed(&mut output[..])); + assert!(res.is_err(), "There should be built-in error here"); + } + } + #[test] #[should_panic] fn from_unknown_linear() { From d1293d9fb0d306b7d0d86398f77d6af66f164098 Mon Sep 17 00:00:00 2001 From: NikVolf Date: Wed, 22 Mar 2017 15:54:19 +0300 Subject: [PATCH 03/72] fix warnings --- ethcore/src/builtin.rs | 52 +++++++++++++++++++++--------------------- ethcore/src/evm/evm.rs | 1 + 2 files changed, 27 insertions(+), 26 deletions(-) diff --git a/ethcore/src/builtin.rs b/ethcore/src/builtin.rs index 112afbd97..acc495085 100644 --- a/ethcore/src/builtin.rs +++ b/ethcore/src/builtin.rs @@ -357,8 +357,8 @@ impl Impl for Bn128AddImpl { let mut write_buf = [0u8; 64]; if let Some(sum) = AffineG1::from_jacobian(p1 + p2) { // point not at infinity - sum.x().to_big_endian(&mut write_buf[0..32]); - sum.y().to_big_endian(&mut write_buf[32..64]); + sum.x().to_big_endian(&mut write_buf[0..32]).expect("Cannot fail since 0..32 is 32-byte length"); + sum.y().to_big_endian(&mut write_buf[32..64]).expect("Cannot fail since 32..64 is 32-byte length");; } output.write(0, &write_buf); @@ -385,15 +385,15 @@ mod tests { let i = [0u8, 1, 2, 3]; let mut o2 = [255u8; 2]; - f.execute(&i[..], &mut BytesRef::Fixed(&mut o2[..])); + f.execute(&i[..], &mut BytesRef::Fixed(&mut o2[..])).expect("Builtin should not fail"); assert_eq!(i[0..2], o2); let mut o4 = [255u8; 4]; - f.execute(&i[..], &mut BytesRef::Fixed(&mut o4[..])); + f.execute(&i[..], &mut BytesRef::Fixed(&mut o4[..])).expect("Builtin should not fail"); assert_eq!(i, o4); let mut o8 = [255u8; 8]; - f.execute(&i[..], &mut BytesRef::Fixed(&mut o8[..])); + f.execute(&i[..], &mut BytesRef::Fixed(&mut o8[..])).expect("Builtin should not fail"); assert_eq!(i, o8[..4]); assert_eq!([255u8; 4], o8[4..]); } @@ -406,19 +406,19 @@ mod tests { let i = [0u8; 0]; let mut o = [255u8; 32]; - f.execute(&i[..], &mut BytesRef::Fixed(&mut o[..])); + f.execute(&i[..], &mut BytesRef::Fixed(&mut o[..])).expect("Builtin should not fail"); assert_eq!(&o[..], &(FromHex::from_hex("e3b0c44298fc1c149afbf4c8996fb92427ae41e4649b934ca495991b7852b855").unwrap())[..]); let mut o8 = [255u8; 8]; - f.execute(&i[..], &mut BytesRef::Fixed(&mut o8[..])); + f.execute(&i[..], &mut BytesRef::Fixed(&mut o8[..])).expect("Builtin should not fail"); assert_eq!(&o8[..], &(FromHex::from_hex("e3b0c44298fc1c14").unwrap())[..]); let mut o34 = [255u8; 34]; - f.execute(&i[..], &mut BytesRef::Fixed(&mut o34[..])); + f.execute(&i[..], &mut BytesRef::Fixed(&mut o34[..])).expect("Builtin should not fail"); assert_eq!(&o34[..], &(FromHex::from_hex("e3b0c44298fc1c149afbf4c8996fb92427ae41e4649b934ca495991b7852b855ffff").unwrap())[..]); let mut ov = vec![]; - f.execute(&i[..], &mut BytesRef::Flexible(&mut ov)); + f.execute(&i[..], &mut BytesRef::Flexible(&mut ov)).expect("Builtin should not fail"); assert_eq!(&ov[..], &(FromHex::from_hex("e3b0c44298fc1c149afbf4c8996fb92427ae41e4649b934ca495991b7852b855").unwrap())[..]); } @@ -430,15 +430,15 @@ mod tests { let i = [0u8; 0]; let mut o = [255u8; 32]; - f.execute(&i[..], &mut BytesRef::Fixed(&mut o[..])); + f.execute(&i[..], &mut BytesRef::Fixed(&mut o[..])).expect("Builtin should not fail"); assert_eq!(&o[..], &(FromHex::from_hex("0000000000000000000000009c1185a5c5e9fc54612808977ee8f548b2258d31").unwrap())[..]); let mut o8 = [255u8; 8]; - f.execute(&i[..], &mut BytesRef::Fixed(&mut o8[..])); + f.execute(&i[..], &mut BytesRef::Fixed(&mut o8[..])).expect("Builtin should not fail"); assert_eq!(&o8[..], &(FromHex::from_hex("0000000000000000").unwrap())[..]); let mut o34 = [255u8; 34]; - f.execute(&i[..], &mut BytesRef::Fixed(&mut o34[..])); + f.execute(&i[..], &mut BytesRef::Fixed(&mut o34[..])).expect("Builtin should not fail"); assert_eq!(&o34[..], &(FromHex::from_hex("0000000000000000000000009c1185a5c5e9fc54612808977ee8f548b2258d31ffff").unwrap())[..]); } @@ -458,40 +458,40 @@ mod tests { let i = FromHex::from_hex("47173285a8d7341e5e972fc677286384f802f8ef42a5ec5f03bbfa254cb01fad000000000000000000000000000000000000000000000000000000000000001b650acf9d3f5f0a2c799776a1254355d5f4061762a237396a99a0e0e3fc2bcd6729514a0dacb2e623ac4abd157cb18163ff942280db4d5caad66ddf941ba12e03").unwrap(); let mut o = [255u8; 32]; - f.execute(&i[..], &mut BytesRef::Fixed(&mut o[..])); + f.execute(&i[..], &mut BytesRef::Fixed(&mut o[..])).expect("Builtin should not fail"); assert_eq!(&o[..], &(FromHex::from_hex("000000000000000000000000c08b5542d177ac6686946920409741463a15dddb").unwrap())[..]); let mut o8 = [255u8; 8]; - f.execute(&i[..], &mut BytesRef::Fixed(&mut o8[..])); + f.execute(&i[..], &mut BytesRef::Fixed(&mut o8[..])).expect("Builtin should not fail"); assert_eq!(&o8[..], &(FromHex::from_hex("0000000000000000").unwrap())[..]); let mut o34 = [255u8; 34]; - f.execute(&i[..], &mut BytesRef::Fixed(&mut o34[..])); + f.execute(&i[..], &mut BytesRef::Fixed(&mut o34[..])).expect("Builtin should not fail"); assert_eq!(&o34[..], &(FromHex::from_hex("000000000000000000000000c08b5542d177ac6686946920409741463a15dddbffff").unwrap())[..]); let i_bad = FromHex::from_hex("47173285a8d7341e5e972fc677286384f802f8ef42a5ec5f03bbfa254cb01fad000000000000000000000000000000000000000000000000000000000000001a650acf9d3f5f0a2c799776a1254355d5f4061762a237396a99a0e0e3fc2bcd6729514a0dacb2e623ac4abd157cb18163ff942280db4d5caad66ddf941ba12e03").unwrap(); let mut o = [255u8; 32]; - f.execute(&i_bad[..], &mut BytesRef::Fixed(&mut o[..])); + f.execute(&i_bad[..], &mut BytesRef::Fixed(&mut o[..])).expect("Builtin should not fail"); assert_eq!(&o[..], &(FromHex::from_hex("ffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffff").unwrap())[..]); let i_bad = FromHex::from_hex("47173285a8d7341e5e972fc677286384f802f8ef42a5ec5f03bbfa254cb01fad000000000000000000000000000000000000000000000000000000000000001b000000000000000000000000000000000000000000000000000000000000001b0000000000000000000000000000000000000000000000000000000000000000").unwrap(); let mut o = [255u8; 32]; - f.execute(&i_bad[..], &mut BytesRef::Fixed(&mut o[..])); + f.execute(&i_bad[..], &mut BytesRef::Fixed(&mut o[..])).expect("Builtin should not fail"); assert_eq!(&o[..], &(FromHex::from_hex("ffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffff").unwrap())[..]); let i_bad = FromHex::from_hex("47173285a8d7341e5e972fc677286384f802f8ef42a5ec5f03bbfa254cb01fad000000000000000000000000000000000000000000000000000000000000001b0000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000001b").unwrap(); let mut o = [255u8; 32]; - f.execute(&i_bad[..], &mut BytesRef::Fixed(&mut o[..])); + f.execute(&i_bad[..], &mut BytesRef::Fixed(&mut o[..])).expect("Builtin should not fail"); assert_eq!(&o[..], &(FromHex::from_hex("ffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffff").unwrap())[..]); let i_bad = FromHex::from_hex("47173285a8d7341e5e972fc677286384f802f8ef42a5ec5f03bbfa254cb01fad000000000000000000000000000000000000000000000000000000000000001bffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffff000000000000000000000000000000000000000000000000000000000000001b").unwrap(); let mut o = [255u8; 32]; - f.execute(&i_bad[..], &mut BytesRef::Fixed(&mut o[..])); + f.execute(&i_bad[..], &mut BytesRef::Fixed(&mut o[..])).expect("Builtin should not fail"); assert_eq!(&o[..], &(FromHex::from_hex("ffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffff").unwrap())[..]); let i_bad = FromHex::from_hex("47173285a8d7341e5e972fc677286384f802f8ef42a5ec5f03bbfa254cb01fad000000000000000000000000000000000000000000000000000000000000001b000000000000000000000000000000000000000000000000000000000000001bffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffff").unwrap(); let mut o = [255u8; 32]; - f.execute(&i_bad[..], &mut BytesRef::Fixed(&mut o[..])); + f.execute(&i_bad[..], &mut BytesRef::Fixed(&mut o[..])).expect("Builtin should not fail"); assert_eq!(&o[..], &(FromHex::from_hex("ffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffff").unwrap())[..]); // TODO: Should this (corrupted version of the above) fail rather than returning some address? @@ -525,7 +525,7 @@ mod tests { let expected = FromHex::from_hex("0000000000000000000000000000000000000000000000000000000000000001").unwrap(); let expected_cost = 1638; - f.execute(&input[..], &mut BytesRef::Fixed(&mut output[..])); + f.execute(&input[..], &mut BytesRef::Fixed(&mut output[..])).expect("Builtin should not fail"); assert_eq!(output, expected); assert_eq!(f.cost(&input[..]), expected_cost.into()); } @@ -544,7 +544,7 @@ mod tests { let expected = FromHex::from_hex("0000000000000000000000000000000000000000000000000000000000000000").unwrap(); let expected_cost = 1638; - f.execute(&input[..], &mut BytesRef::Fixed(&mut output[..])); + f.execute(&input[..], &mut BytesRef::Fixed(&mut output[..])).expect("Builtin should not fail"); assert_eq!(output, expected); assert_eq!(f.cost(&input[..]), expected_cost.into()); } @@ -564,7 +564,7 @@ mod tests { let expected = FromHex::from_hex("3b01b01ac41f2d6e917c6d6a221ce793802469026d9ab7578fa2e79e4da6aaab").unwrap(); let expected_cost = 102; - f.execute(&input[..], &mut BytesRef::Fixed(&mut output[..])); + f.execute(&input[..], &mut BytesRef::Fixed(&mut output[..])).expect("Builtin should not fail"); assert_eq!(output, expected); assert_eq!(f.cost(&input[..]), expected_cost.into()); } @@ -582,7 +582,7 @@ mod tests { let mut output = vec![]; let expected_cost = 0; - f.execute(&input[..], &mut BytesRef::Flexible(&mut output)); + f.execute(&input[..], &mut BytesRef::Flexible(&mut output)).expect("Builtin should not fail"); assert_eq!(output.len(), 0); // shouldn't have written any output. assert_eq!(f.cost(&input[..]), expected_cost.into()); } @@ -669,7 +669,7 @@ mod tests { let i = [0u8, 1, 2, 3]; let mut o = [255u8; 4]; - b.execute(&i[..], &mut BytesRef::Fixed(&mut o[..])); + b.execute(&i[..], &mut BytesRef::Fixed(&mut o[..])).expect("Builtin should not fail"); assert_eq!(i, o); } @@ -691,7 +691,7 @@ mod tests { let i = [0u8, 1, 2, 3]; let mut o = [255u8; 4]; - b.execute(&i[..], &mut BytesRef::Fixed(&mut o[..])); + b.execute(&i[..], &mut BytesRef::Fixed(&mut o[..])).expect("Builtin should not fail"); assert_eq!(i, o); } } \ No newline at end of file diff --git a/ethcore/src/evm/evm.rs b/ethcore/src/evm/evm.rs index b561c271f..0e7a4d968 100644 --- a/ethcore/src/evm/evm.rs +++ b/ethcore/src/evm/evm.rs @@ -60,6 +60,7 @@ pub enum Error { /// What was the stack limit limit: usize }, + /// Built-in contract failed on given input BuiltIn(String), /// Returned on evm internal error. Should never be ignored during development. /// Likely to cause consensus issues. From 8a4537fc731c7eda1c92333c5a0d17359192d3fb Mon Sep 17 00:00:00 2001 From: NikVolf Date: Wed, 22 Mar 2017 16:31:43 +0300 Subject: [PATCH 04/72] no-input test --- ethcore/src/builtin.rs | 127 +++++++++++++++++++++++++++++++++-------- 1 file changed, 104 insertions(+), 23 deletions(-) diff --git a/ethcore/src/builtin.rs b/ethcore/src/builtin.rs index acc495085..a638d06d9 100644 --- a/ethcore/src/builtin.rs +++ b/ethcore/src/builtin.rs @@ -326,33 +326,40 @@ impl Impl for ModexpImpl { } } +fn read_fr(reader: &mut io::Chain<&[u8], io::Repeat>) -> Result<::bn::Fr, Error> { + let mut buf = [0u8; 32]; + + reader.read_exact(&mut buf[..]).expect("reading from zero-extended memory cannot fail; qed"); + ::bn::Fr::from_slice(&buf[0..32]).map_err(|_| Error::from("Invalid field element")) +} + +fn read_point(reader: &mut io::Chain<&[u8], io::Repeat>) -> Result<::bn::G1, Error> { + use bn::{Fq, AffineG1, G1, Group}; + + let mut buf = [0u8; 32]; + + reader.read_exact(&mut buf[..]).expect("reading from zero-extended memory cannot fail; qed"); + let px = Fq::from_slice(&buf[0..32]).map_err(|_| Error::from("Invalid point x coordinate"))?; + + reader.read_exact(&mut buf[..]).expect("reading from zero-extended memory cannot fail; qed"); + let py = Fq::from_slice(&buf[0..32]).map_err(|_| Error::from("Invalid point x coordinate"))?; + + Ok( + if px == Fq::zero() && py == Fq::zero() { + G1::zero() + } else { + AffineG1::new(px, py).map_err(|_| Error::from("Invalid curve point"))?.into() + } + ) +} + impl Impl for Bn128AddImpl { fn execute(&self, input: &[u8], output: &mut BytesRef) -> Result<(), Error> { - use bn::{Fq, AffineG1, G1, Group}; - - let mut buf = [0u8; 32]; - let mut next_coord = |reader: &mut io::Chain<&[u8], io::Repeat>| { - reader.read_exact(&mut buf[..]).expect("reading from zero-extended memory cannot fail; qed"); - Fq::from_slice(&buf[0..32]) - }; + use bn::AffineG1; let mut padded_input = input.chain(io::repeat(0)); - - let px = next_coord(&mut padded_input).map_err(|_| Error::from("Invalid p1 x coordinate"))?; - let py = next_coord(&mut padded_input).map_err(|_| Error::from("Invalid p1 y coordinate"))?; - let p1: G1 = if px == Fq::zero() && py == Fq::zero() { - G1::zero() - } else { - AffineG1::new(px, py).map_err(|_| Error::from("Invalid curve point"))?.into() - }; - - let px = next_coord(&mut padded_input).map_err(|_| Error::from("Invalid p1 x coordinate"))?; - let py = next_coord(&mut padded_input).map_err(|_| Error::from("Invalid p1 y coordinate"))?; - let p2: G1 = if px == Fq::zero() && py == Fq::zero() { - G1::zero() - } else { - AffineG1::new(px, py).map_err(|_| Error::from("Invalid curve point"))?.into() - }; + let p1 = read_point(&mut padded_input)?; + let p2 = read_point(&mut padded_input)?; let mut write_buf = [0u8; 64]; if let Some(sum) = AffineG1::from_jacobian(p1 + p2) { @@ -368,6 +375,19 @@ impl Impl for Bn128AddImpl { impl Impl for Bn128MulImpl { fn execute(&self, input: &[u8], output: &mut BytesRef) -> Result<(), Error> { + use bn::AffineG1; + + let mut padded_input = input.chain(io::repeat(0)); + let p = read_point(&mut padded_input)?; + let fr = read_fr(&mut padded_input)?; + + let mut write_buf = [0u8; 64]; + if let Some(sum) = AffineG1::from_jacobian(p * fr) { + // point not at infinity + sum.x().to_big_endian(&mut write_buf[0..32]).expect("Cannot fail since 0..32 is 32-byte length"); + sum.y().to_big_endian(&mut write_buf[32..64]).expect("Cannot fail since 32..64 is 32-byte length");; + } + output.write(0, &write_buf); Ok(()) } } @@ -617,6 +637,22 @@ mod tests { assert_eq!(output, expected); } + + // no input, should not fail + { + let mut empty = [0u8; 0]; + let input = BytesRef::Fixed(&mut empty); + + let mut output = vec![0u8; 64]; + let expected = FromHex::from_hex("\ + 0000000000000000000000000000000000000000000000000000000000000000\ + 0000000000000000000000000000000000000000000000000000000000000000" + ).unwrap(); + + f.execute(&input[..], &mut BytesRef::Fixed(&mut output[..])).expect("Builtin should not fail"); + assert_eq!(output, expected); + } + // should fail - point not on curve { let input = FromHex::from_hex("\ @@ -633,6 +669,51 @@ mod tests { } } + + #[test] + fn alt_bn128_mul() { + use rustc_serialize::hex::FromHex; + + let f = Builtin { + pricer: Box::new(Linear { base: 0, word: 0 }), + native: ethereum_builtin("alt_bn128_mul"), + activate_at: 0, + }; + + // zero-point multiplication + { + let input = FromHex::from_hex("\ + 0000000000000000000000000000000000000000000000000000000000000000\ + 0000000000000000000000000000000000000000000000000000000000000000\ + 0200000000000000000000000000000000000000000000000000000000000000" + ).unwrap(); + + let mut output = vec![0u8; 64]; + let expected = FromHex::from_hex("\ + 0000000000000000000000000000000000000000000000000000000000000000\ + 0000000000000000000000000000000000000000000000000000000000000000" + ).unwrap(); + + f.execute(&input[..], &mut BytesRef::Fixed(&mut output[..])).expect("Builtin should not fail"); + assert_eq!(output, expected); + } + + // should fail - point not on curve + { + let input = FromHex::from_hex("\ + 1111111111111111111111111111111111111111111111111111111111111111\ + 1111111111111111111111111111111111111111111111111111111111111111\ + 0f00000000000000000000000000000000000000000000000000000000000000" + ).unwrap(); + + let mut output = vec![0u8; 64]; + + let res = f.execute(&input[..], &mut BytesRef::Fixed(&mut output[..])); + assert!(res.is_err(), "There should be built-in error here"); + } + } + + #[test] #[should_panic] fn from_unknown_linear() { From 436ae1333cbccc6cfcd4facc07ac5ba4c3769bb3 Mon Sep 17 00:00:00 2001 From: NikVolf Date: Wed, 22 Mar 2017 16:40:44 +0300 Subject: [PATCH 05/72] trace mapping fix --- ethcore/src/types/trace_types/error.rs | 3 ++- 1 file changed, 2 insertions(+), 1 deletion(-) diff --git a/ethcore/src/types/trace_types/error.rs b/ethcore/src/types/trace_types/error.rs index c36d86728..184ab962f 100644 --- a/ethcore/src/types/trace_types/error.rs +++ b/ethcore/src/types/trace_types/error.rs @@ -50,7 +50,7 @@ impl<'a> From<&'a EvmError> for Error { EvmError::BadInstruction { .. } => Error::BadInstruction, EvmError::StackUnderflow { .. } => Error::StackUnderflow, EvmError::OutOfStack { .. } => Error::OutOfStack, - EvmError::BuiltIn { .. } => Error::OutOfStack, + EvmError::BuiltIn { .. } => Error::BuiltIn, EvmError::Internal(_) => Error::Internal, } } @@ -106,6 +106,7 @@ impl Decodable for Error { 3 => Ok(StackUnderflow), 4 => Ok(OutOfStack), 5 => Ok(Internal), + 6 => Ok(BuiltIn), _ => Err(DecoderError::Custom("Invalid error type")), } } From 9d23101c9a6b19c5ad2a50b308e39b4a369da4bc Mon Sep 17 00:00:00 2001 From: NikVolf Date: Wed, 22 Mar 2017 17:43:19 +0300 Subject: [PATCH 06/72] update for rv --- ethcore/src/builtin.rs | 5 +++-- 1 file changed, 3 insertions(+), 2 deletions(-) diff --git a/ethcore/src/builtin.rs b/ethcore/src/builtin.rs index a638d06d9..f65759f72 100644 --- a/ethcore/src/builtin.rs +++ b/ethcore/src/builtin.rs @@ -112,8 +112,7 @@ impl Builtin { /// Simple forwarder for execute. pub fn execute(&self, input: &[u8], output: &mut BytesRef) -> Result<(), Error> { - self.native.execute(input, output)?; - Ok(()) + self.native.execute(input, output) } /// Whether the builtin is activated at the given block number. @@ -354,6 +353,7 @@ fn read_point(reader: &mut io::Chain<&[u8], io::Repeat>) -> Result<::bn::G1, Err } impl Impl for Bn128AddImpl { + // Can fail if any of the 2 points does not belong the bn128 curve fn execute(&self, input: &[u8], output: &mut BytesRef) -> Result<(), Error> { use bn::AffineG1; @@ -374,6 +374,7 @@ impl Impl for Bn128AddImpl { } impl Impl for Bn128MulImpl { + // Can fail if first paramter (bn128 curve point) does not actually belong to the curve fn execute(&self, input: &[u8], output: &mut BytesRef) -> Result<(), Error> { use bn::AffineG1; From 2de67538a25d870d7d51fa33e8758fc146d7baf2 Mon Sep 17 00:00:00 2001 From: NikVolf Date: Wed, 22 Mar 2017 18:07:41 +0300 Subject: [PATCH 07/72] updating deps --- Cargo.lock | 16 +++++----------- 1 file changed, 5 insertions(+), 11 deletions(-) diff --git a/Cargo.lock b/Cargo.lock index b92cbaed9..2b59df5e7 100644 --- a/Cargo.lock +++ b/Cargo.lock @@ -177,19 +177,14 @@ source = "registry+https://github.com/rust-lang/crates.io-index" [[package]] name = "bn" -version = "0.4.2" -source = "git+https://github.com/paritytech/bn#7e513a84330f02603759e370f22af90c99e3e717" +version = "0.4.3" +source = "git+https://github.com/paritytech/bn#59d848e642ad1ff0d60e39348576a6f11ee123b8" dependencies = [ - "byteorder 0.5.3 (registry+https://github.com/rust-lang/crates.io-index)", + "byteorder 1.0.0 (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)", ] -[[package]] -name = "byteorder" -version = "0.5.3" -source = "registry+https://github.com/rust-lang/crates.io-index" - [[package]] name = "byteorder" version = "1.0.0" @@ -397,7 +392,7 @@ version = "1.7.0" dependencies = [ "bit-set 0.4.0 (registry+https://github.com/rust-lang/crates.io-index)", "bloomchain 0.1.0 (registry+https://github.com/rust-lang/crates.io-index)", - "bn 0.4.2 (git+https://github.com/paritytech/bn)", + "bn 0.4.3 (git+https://github.com/paritytech/bn)", "byteorder 1.0.0 (registry+https://github.com/rust-lang/crates.io-index)", "clippy 0.0.103 (registry+https://github.com/rust-lang/crates.io-index)", "crossbeam 0.2.10 (registry+https://github.com/rust-lang/crates.io-index)", @@ -2633,8 +2628,7 @@ dependencies = [ "checksum bitflags 0.7.0 (registry+https://github.com/rust-lang/crates.io-index)" = "aad18937a628ec6abcd26d1489012cc0e18c21798210f491af69ded9b881106d" "checksum blastfig 0.3.3 (registry+https://github.com/rust-lang/crates.io-index)" = "09640e0509d97d5cdff03a9f5daf087a8e04c735c3b113a75139634a19cfc7b2" "checksum bloomchain 0.1.0 (registry+https://github.com/rust-lang/crates.io-index)" = "3f421095d2a76fc24cd3fb3f912b90df06be7689912b1bdb423caefae59c258d" -"checksum bn 0.4.2 (git+https://github.com/paritytech/bn)" = "" -"checksum byteorder 0.5.3 (registry+https://github.com/rust-lang/crates.io-index)" = "0fc10e8cc6b2580fda3f36eb6dc5316657f812a3df879a44a66fc9f0fdbc4855" +"checksum bn 0.4.3 (git+https://github.com/paritytech/bn)" = "" "checksum byteorder 1.0.0 (registry+https://github.com/rust-lang/crates.io-index)" = "c40977b0ee6b9885c9013cd41d9feffdd22deb3bb4dc3a71d901cc7a77de18c8" "checksum bytes 0.3.0 (registry+https://github.com/rust-lang/crates.io-index)" = "c129aff112dcc562970abb69e2508b40850dd24c274761bb50fb8a0067ba6c27" "checksum bytes 0.4.0-dev (git+https://github.com/carllerche/bytes)" = "" From 1490ba179cab6d98f3702d7353fd8e6a0a311cea Mon Sep 17 00:00:00 2001 From: Nicolas Gotchac Date: Thu, 23 Mar 2017 15:39:13 +0100 Subject: [PATCH 08/72] Dispatch an open event on drag of Parity Bar (#4987) * Dispatch an open event on drag of Parity Bar * Bette id for ParityBar position // Replace on dapp unload * Fix PairtyBar Positionning --- js/src/views/ParityBar/parityBar.js | 172 ++++++++++++++++++---------- 1 file changed, 111 insertions(+), 61 deletions(-) diff --git a/js/src/views/ParityBar/parityBar.js b/js/src/views/ParityBar/parityBar.js index 3d34f430f..9d5027acf 100644 --- a/js/src/views/ParityBar/parityBar.js +++ b/js/src/views/ParityBar/parityBar.js @@ -78,16 +78,33 @@ class ParityBar extends Component { // Hook to the dapp loaded event to position the // Parity Bar accordingly - DappsStore.get(api).on('loaded', (app) => { - this.app = app; + const dappsStore = DappsStore.get(api); + + dappsStore + .on('loaded', (app) => { + this.app = app; + this.loadPosition(); + }); + + if (this.props.dapp) { this.loadPosition(); - }); + } } componentWillReceiveProps (nextProps) { const count = this.props.pending.length; const newCount = nextProps.pending.length; + // Replace to default position when leaving a dapp + if (this.props.dapp && !nextProps.dapp) { + this.loadPosition(true); + } + + // Load position when dapp loads + if (!this.props.dapp && nextProps.dapp) { + this.loadPosition(); + } + if (count === newCount) { return; } @@ -101,7 +118,10 @@ class ParityBar extends Component { setOpened (opened, displayType = DISPLAY_SIGNER) { this.setState({ displayType, opened }); + this.dispatchOpenEvent(opened); + } + dispatchOpenEvent (opened) { if (!this.bar) { return; } @@ -241,10 +261,6 @@ class ParityBar extends Component { } renderDrag () { - if (this.props.externalLink) { - return; - } - const dragButtonClasses = [ styles.dragButton ]; if (this.state.moving) { @@ -457,51 +473,56 @@ class ParityBar extends Component { return position; } - onMouseDown = (event) => { - const containerElt = ReactDOM.findDOMNode(this.refs.container); - const dragButtonElt = ReactDOM.findDOMNode(this.refs.dragButton); + onMouseDown = () => { + // Dispatch an open event in case in an iframe (get full w and h) + this.dispatchOpenEvent(true); - if (!containerElt || !dragButtonElt) { - console.warn(containerElt ? 'drag button' : 'container', 'not found...'); - return; - } + window.setTimeout(() => { + const containerElt = ReactDOM.findDOMNode(this.refs.container); + const dragButtonElt = ReactDOM.findDOMNode(this.refs.dragButton); - const bodyRect = document.body.getBoundingClientRect(); - const containerRect = containerElt.getBoundingClientRect(); - const buttonRect = dragButtonElt.getBoundingClientRect(); + if (!containerElt || !dragButtonElt) { + console.warn(containerElt ? 'drag button' : 'container', 'not found...'); + return; + } - const buttonOffset = { - top: (buttonRect.top + buttonRect.height / 2) - containerRect.top, - left: (buttonRect.left + buttonRect.width / 2) - containerRect.left - }; + const bodyRect = document.body.getBoundingClientRect(); + const containerRect = containerElt.getBoundingClientRect(); + const buttonRect = dragButtonElt.getBoundingClientRect(); - buttonOffset.bottom = containerRect.height - buttonOffset.top; - buttonOffset.right = containerRect.width - buttonOffset.left; + const buttonOffset = { + top: (buttonRect.top + buttonRect.height / 2) - containerRect.top, + left: (buttonRect.left + buttonRect.width / 2) - containerRect.left + }; - const button = { - offset: buttonOffset, - height: buttonRect.height, - width: buttonRect.width - }; + buttonOffset.bottom = containerRect.height - buttonOffset.top; + buttonOffset.right = containerRect.width - buttonOffset.left; - const container = { - height: containerRect.height, - width: containerRect.width - }; + const button = { + offset: buttonOffset, + height: buttonRect.height, + width: buttonRect.width + }; - const page = { - height: bodyRect.height, - width: bodyRect.width - }; + const container = { + height: containerRect.height, + width: containerRect.width + }; - this.moving = true; - this.measures = { - button, - container, - page - }; + const page = { + height: bodyRect.height, + width: bodyRect.width + }; - this.setState({ moving: true }); + this.moving = true; + this.measures = { + button, + container, + page + }; + + this.setMovingState(true); + }, 50); } onMouseEnter = (event) => { @@ -570,7 +591,7 @@ class ParityBar extends Component { } this.moving = false; - this.setState({ moving: false, position }); + this.setMovingState(false, { position }); this.savePosition(position); } @@ -587,39 +608,61 @@ class ParityBar extends Component { } get config () { - let config; + const config = store.get(LS_STORE_KEY); - try { - config = JSON.parse(store.get(LS_STORE_KEY)); - } catch (error) { - config = {}; + if (typeof config === 'string') { + try { + return JSON.parse(config); + } catch (e) { + return {}; + } } - return config; + return config || {}; } - loadPosition (props = this.props) { - const { app, config } = this; + /** + * Return the config key for the current view. + * If inside a dapp, should be the dapp id. + * Otherwise, try to get the current hostname. + */ + getConfigKey () { + const { app } = this; - if (!app) { + if (app && app.id) { + return app.id; + } + + return window.location.hostname; + } + + loadPosition (loadDefault = false) { + if (loadDefault) { return this.setState({ position: DEFAULT_POSITION }); } - if (config[app.id]) { - return this.setState({ position: config[app.id] }); + const { app, config } = this; + const configKey = this.getConfigKey(); + + if (config[configKey]) { + return this.setState({ position: config[configKey] }); } - const position = this.stringToPosition(app.position); + if (app && app.position) { + const position = this.stringToPosition(app.position); - this.setState({ position }); + return this.setState({ position }); + } + + return this.setState({ position: DEFAULT_POSITION }); } savePosition (position) { - const { app, config } = this; + const { config } = this; + const configKey = this.getConfigKey(); - config[app.id] = position; - - store.set(LS_STORE_KEY, JSON.stringify(config)); + config[configKey] = position; + store.set(LS_STORE_KEY, config); } stringToPosition (value) { @@ -647,6 +690,13 @@ class ParityBar extends Component { return DEFAULT_POSITION; } } + + setMovingState (moving, extras = {}) { + this.setState({ moving, ...extras }); + + // Trigger an open event if it's moving + this.dispatchOpenEvent(moving); + } } function mapStateToProps (state) { From df76f010dadcdb5dd6a7493ff48e7555c70dbb26 Mon Sep 17 00:00:00 2001 From: Jaco Greeff Date: Thu, 23 Mar 2017 15:47:42 +0100 Subject: [PATCH 09/72] Create webpack analysis files (size) (#5009) --- js/package.json | 5 +++ js/webpack/app.js | 3 +- js/webpack/shared.js | 93 +++++++++++++++++++++++--------------------- 3 files changed, 56 insertions(+), 45 deletions(-) diff --git a/js/package.json b/js/package.json index 6a1e63fb1..2c0dae7cc 100644 --- a/js/package.json +++ b/js/package.json @@ -26,6 +26,10 @@ "Promise" ], "scripts": { + "analize": "npm run analize:lib && npm run analize:dll && npm run analize:app", + "analize:app": "WPANALIZE=1 webpack --config webpack/app --json > .build/analize.app.json && cat .build/analize.app.json | webpack-bundle-size-analyzer", + "analize:lib": "WPANALIZE=1 webpack --config webpack/libraries --json > .build/analize.lib.json && cat .build/analize.lib.json | webpack-bundle-size-analyzer", + "analize:dll": "WPANALIZE=1 webpack --config webpack/vendor --json > .build/analize.dll.json && cat .build/analize.app.json | webpack-bundle-size-analyzer", "build": "npm run build:lib && npm run build:dll && npm run build:app && npm run build:embed", "build:app": "webpack --config webpack/app", "build:lib": "webpack --config webpack/libraries", @@ -141,6 +145,7 @@ "to-source": "2.0.3", "url-loader": "0.5.7", "webpack": "2.2.1", + "webpack-bundle-size-analyzer": "2.5.0", "webpack-dev-middleware": "1.10.1", "webpack-error-notification": "0.1.6", "webpack-hot-middleware": "2.17.1", diff --git a/js/webpack/app.js b/js/webpack/app.js index 14f2876db..6b6b4c8cd 100644 --- a/js/webpack/app.js +++ b/js/webpack/app.js @@ -36,6 +36,7 @@ const EMBED = process.env.EMBED; const isProd = ENV === 'production'; const isEmbed = EMBED === '1' || EMBED === 'true'; +const isAnalize = process.env.WPANALIZE === '1'; const entry = isEmbed ? { @@ -215,7 +216,7 @@ module.exports = { ); } - if (!isProd) { + if (!isAnalize && !isProd) { const DEST_I18N = path.join(__dirname, '..', DEST, 'i18n'); plugins.push( diff --git a/js/webpack/shared.js b/js/webpack/shared.js index 3f5fcd66f..2f151944e 100644 --- a/js/webpack/shared.js +++ b/js/webpack/shared.js @@ -29,6 +29,7 @@ const ProgressBarPlugin = require('progress-bar-webpack-plugin'); const EMBED = process.env.EMBED; const ENV = process.env.NODE_ENV || 'development'; const isProd = ENV === 'production'; +const isAnalize = process.env.WPANALIZE === '1'; function getBabelrc () { const babelrc = JSON.parse(fs.readFileSync(path.resolve(__dirname, '../.babelrc'))); @@ -80,55 +81,59 @@ function getPlugins (_isProd = isProd) { }) ]; - const plugins = [ - new ProgressBarPlugin({ - format: '[:msg] [:bar] ' + ':percent' + ' (:elapsed seconds)' - }), + const plugins = (isAnalize + ? [] + : [ + new ProgressBarPlugin({ + format: '[:msg] [:bar] ' + ':percent' + ' (:elapsed seconds)' + }) + ]).concat([ + new HappyPack({ + id: 'css', + threads: 4, + loaders: [ + 'style-loader', + 'css-loader?modules&sourceMap&importLoaders=1&localIdentName=[name]__[local]___[hash:base64:5]', + 'postcss-loader' + ], + verbose: !isAnalize + }), - new HappyPack({ - id: 'css', - threads: 4, - loaders: [ - 'style-loader', - 'css-loader?modules&sourceMap&importLoaders=1&localIdentName=[name]__[local]___[hash:base64:5]', - 'postcss-loader' - ] - }), + new HappyPack({ + id: 'babel-js', + threads: 4, + loaders: [ isProd ? 'babel-loader' : 'babel-loader?cacheDirectory=true' ], + verbose: !isAnalize + }), - new HappyPack({ - id: 'babel-js', - threads: 4, - loaders: [ isProd ? 'babel-loader' : 'babel-loader?cacheDirectory=true' ] - }), + new webpack.DefinePlugin({ + 'process.env': { + EMBED: JSON.stringify(EMBED), + NODE_ENV: JSON.stringify(ENV), + RPC_ADDRESS: JSON.stringify(process.env.RPC_ADDRESS), + PARITY_URL: JSON.stringify(process.env.PARITY_URL), + DAPPS_URL: JSON.stringify(process.env.DAPPS_URL), + LOGGING: JSON.stringify(!isProd) + } + }), - new webpack.DefinePlugin({ - 'process.env': { - EMBED: JSON.stringify(EMBED), - NODE_ENV: JSON.stringify(ENV), - RPC_ADDRESS: JSON.stringify(process.env.RPC_ADDRESS), - PARITY_URL: JSON.stringify(process.env.PARITY_URL), - DAPPS_URL: JSON.stringify(process.env.DAPPS_URL), - LOGGING: JSON.stringify(!isProd) - } - }), + new webpack.LoaderOptionsPlugin({ + minimize: isProd, + debug: !isProd, + options: { + context: path.join(__dirname, '../src'), + postcss: postcss, + babel: getBabelrc() + } + }), - new webpack.LoaderOptionsPlugin({ - minimize: isProd, - debug: !isProd, - options: { - context: path.join(__dirname, '../src'), - postcss: postcss, - babel: getBabelrc() - } - }), + new webpack.optimize.OccurrenceOrderPlugin(!_isProd), - new webpack.optimize.OccurrenceOrderPlugin(!_isProd), - - new CircularDependencyPlugin({ - exclude: /node_modules/, - failOnError: true - }) - ]; + new CircularDependencyPlugin({ + exclude: /node_modules/, + failOnError: true + }) + ]); if (_isProd) { plugins.push(new webpack.optimize.UglifyJsPlugin({ From 35a43a1e82492cc28e7a90b915b58537d158c770 Mon Sep 17 00:00:00 2001 From: GitLab Build Bot Date: Thu, 23 Mar 2017 15:03:35 +0000 Subject: [PATCH 10/72] [ci skip] js-precompiled 20170323-150033 --- Cargo.lock | 2 +- js/package.json | 2 +- 2 files changed, 2 insertions(+), 2 deletions(-) diff --git a/Cargo.lock b/Cargo.lock index 974206727..7d3c577ad 100644 --- a/Cargo.lock +++ b/Cargo.lock @@ -1750,7 +1750,7 @@ dependencies = [ [[package]] name = "parity-ui-precompiled" version = "1.4.0" -source = "git+https://github.com/ethcore/js-precompiled.git#a44b1cb29b80e4d3372ee47494499a61db7a8116" +source = "git+https://github.com/ethcore/js-precompiled.git#744561d103ca832187930ca7532f1d093a8335af" dependencies = [ "parity-dapps-glue 1.7.0 (registry+https://github.com/rust-lang/crates.io-index)", ] diff --git a/js/package.json b/js/package.json index 2c0dae7cc..466779efe 100644 --- a/js/package.json +++ b/js/package.json @@ -1,6 +1,6 @@ { "name": "parity.js", - "version": "1.7.29", + "version": "1.7.30", "main": "release/index.js", "jsnext:main": "src/index.js", "author": "Parity Team ", From 9efab789aa875ad3b6930403135ea9bdf1c3468b Mon Sep 17 00:00:00 2001 From: GitLab Build Bot Date: Thu, 23 Mar 2017 15:10:28 +0000 Subject: [PATCH 11/72] [ci skip] js-precompiled 20170323-150743 --- Cargo.lock | 2 +- js/package.json | 2 +- 2 files changed, 2 insertions(+), 2 deletions(-) diff --git a/Cargo.lock b/Cargo.lock index 7d3c577ad..badb522c4 100644 --- a/Cargo.lock +++ b/Cargo.lock @@ -1750,7 +1750,7 @@ dependencies = [ [[package]] name = "parity-ui-precompiled" version = "1.4.0" -source = "git+https://github.com/ethcore/js-precompiled.git#744561d103ca832187930ca7532f1d093a8335af" +source = "git+https://github.com/ethcore/js-precompiled.git#8d7826d49c785726b17f14f150cab37e204fc84f" dependencies = [ "parity-dapps-glue 1.7.0 (registry+https://github.com/rust-lang/crates.io-index)", ] diff --git a/js/package.json b/js/package.json index 466779efe..b65ef6661 100644 --- a/js/package.json +++ b/js/package.json @@ -1,6 +1,6 @@ { "name": "parity.js", - "version": "1.7.30", + "version": "1.7.31", "main": "release/index.js", "jsnext:main": "src/index.js", "author": "Parity Team ", From 434ed1b91c7735a93bb3fd7591e93810ce5eea1a Mon Sep 17 00:00:00 2001 From: NikVolf Date: Fri, 24 Mar 2017 15:35:00 +0300 Subject: [PATCH 12/72] remove alt_ --- ethcore/res/ethereum/foundation.json | 4 ++-- ethcore/src/builtin.rs | 12 ++++++------ 2 files changed, 8 insertions(+), 8 deletions(-) diff --git a/ethcore/res/ethereum/foundation.json b/ethcore/res/ethereum/foundation.json index 1debff1d6..54f10b70c 100644 --- a/ethcore/res/ethereum/foundation.json +++ b/ethcore/res/ethereum/foundation.json @@ -190,8 +190,8 @@ "0000000000000000000000000000000000000003": { "builtin": { "name": "ripemd160", "pricing": { "linear": { "base": 600, "word": 120 } } } }, "0000000000000000000000000000000000000004": { "builtin": { "name": "identity", "pricing": { "linear": { "base": 15, "word": 3 } } } }, "0000000000000000000000000000000000000005": { "builtin": { "name": "modexp", "activate_at": "0x7fffffffffffff", "pricing": { "modexp": { "divisor": 20 } } } }, - "0000000000000000000000000000000000000006": { "builtin": { "name": "alt_bn128_add", "activate_at": "0x7fffffffffffff", "pricing": { "linear": { "base": 999999, "word": 0 } } } }, - "0000000000000000000000000000000000000007": { "builtin": { "name": "alt_bn128_mul", "activate_at": "0x7fffffffffffff", "pricing": { "linear": { "base": 999999, "word": 0 } } } }, + "0000000000000000000000000000000000000006": { "builtin": { "name": "bn128_add", "activate_at": "0x7fffffffffffff", "pricing": { "linear": { "base": 999999, "word": 0 } } } }, + "0000000000000000000000000000000000000007": { "builtin": { "name": "bn128_mul", "activate_at": "0x7fffffffffffff", "pricing": { "linear": { "base": 999999, "word": 0 } } } }, "3282791d6fd713f1e94f4bfd565eaa78b3a0599d": { "balance": "1337000000000000000000" }, diff --git a/ethcore/src/builtin.rs b/ethcore/src/builtin.rs index f65759f72..da0ee38e1 100644 --- a/ethcore/src/builtin.rs +++ b/ethcore/src/builtin.rs @@ -156,8 +156,8 @@ fn ethereum_builtin(name: &str) -> Box { "sha256" => Box::new(Sha256) as Box, "ripemd160" => Box::new(Ripemd160) as Box, "modexp" => Box::new(ModexpImpl) as Box, - "alt_bn128_add" => Box::new(Bn128AddImpl) as Box, - "alt_bn128_mul" => Box::new(Bn128MulImpl) as Box, + "bn128_add" => Box::new(Bn128AddImpl) as Box, + "bn128_mul" => Box::new(Bn128MulImpl) as Box, _ => panic!("invalid builtin name: {}", name), } } @@ -610,12 +610,12 @@ mod tests { } #[test] - fn alt_bn128_add() { + fn bn128_add() { use rustc_serialize::hex::FromHex; let f = Builtin { pricer: Box::new(Linear { base: 0, word: 0 }), - native: ethereum_builtin("alt_bn128_add"), + native: ethereum_builtin("bn128_add"), activate_at: 0, }; @@ -672,12 +672,12 @@ mod tests { #[test] - fn alt_bn128_mul() { + fn bn128_mul() { use rustc_serialize::hex::FromHex; let f = Builtin { pricer: Box::new(Linear { base: 0, word: 0 }), - native: ethereum_builtin("alt_bn128_mul"), + native: ethereum_builtin("bn128_mul"), activate_at: 0, }; From 3b54b49b0b899c56c25c0691117b529664145a24 Mon Sep 17 00:00:00 2001 From: Arkadiy Paronyan Date: Fri, 24 Mar 2017 18:55:57 +0100 Subject: [PATCH 13/72] Resilient warp sync (#5018) --- sync/src/chain.rs | 33 +++++++++++++++++++-------------- sync/src/snapshot.rs | 5 +++++ util/network/src/session.rs | 4 ++-- 3 files changed, 26 insertions(+), 16 deletions(-) diff --git a/sync/src/chain.rs b/sync/src/chain.rs index 47ddf6ab1..df5f65a86 100644 --- a/sync/src/chain.rs +++ b/sync/src/chain.rs @@ -164,8 +164,8 @@ const HEADERS_TIMEOUT_SEC: u64 = 15; const BODIES_TIMEOUT_SEC: u64 = 10; const RECEIPTS_TIMEOUT_SEC: u64 = 10; const FORK_HEADER_TIMEOUT_SEC: u64 = 3; -const SNAPSHOT_MANIFEST_TIMEOUT_SEC: u64 = 3; -const SNAPSHOT_DATA_TIMEOUT_SEC: u64 = 60; +const SNAPSHOT_MANIFEST_TIMEOUT_SEC: u64 = 5; +const SNAPSHOT_DATA_TIMEOUT_SEC: u64 = 120; #[derive(Copy, Clone, Eq, PartialEq, Debug)] /// Sync state @@ -463,12 +463,7 @@ impl ChainSync { /// Reset sync. Clear all downloaded data but keep the queue fn reset(&mut self, io: &mut SyncIo) { self.new_blocks.reset(); - self.snapshot.clear(); let chain_info = io.chain().chain_info(); - if self.state == SyncState::SnapshotData { - debug!(target:"sync", "Aborting snapshot restore"); - io.snapshot_service().abort_restore(); - } for (_, ref mut p) in &mut self.peers { if p.block_set != Some(BlockSet::OldBlocks) { p.reset_asking(); @@ -487,6 +482,11 @@ impl ChainSync { /// Restart sync pub fn reset_and_continue(&mut self, io: &mut SyncIo) { trace!(target: "sync", "Restarting"); + if self.state == SyncState::SnapshotData { + debug!(target:"sync", "Aborting snapshot restore"); + io.snapshot_service().abort_restore(); + } + self.snapshot.clear(); self.reset(io); self.continue_sync(io); } @@ -499,7 +499,7 @@ impl ChainSync { } fn maybe_start_snapshot_sync(&mut self, io: &mut SyncIo) { - if self.state != SyncState::WaitingPeers { + if self.state != SyncState::WaitingPeers && self.state != SyncState::Blocks && self.state != SyncState::Waiting { return; } // Make sure the snapshot block is not too far away from best block and network best block and @@ -531,7 +531,7 @@ impl ChainSync { (best_hash, max_peers, snapshot_peers) }; - let timeout = self.sync_start_time.map_or(false, |t| ((time::precise_time_ns() - t) / 1_000_000_000) > WAIT_PEERS_TIMEOUT_SEC); + let timeout = (self.state == SyncState::WaitingPeers) && self.sync_start_time.map_or(false, |t| ((time::precise_time_ns() - t) / 1_000_000_000) > WAIT_PEERS_TIMEOUT_SEC); if let (Some(hash), Some(peers)) = (best_hash, best_hash.map_or(None, |h| snapshot_peers.get(&h))) { if max_peers >= SNAPSHOT_MIN_PEERS { @@ -549,13 +549,18 @@ impl ChainSync { } fn start_snapshot_sync(&mut self, io: &mut SyncIo, peers: &[PeerId]) { - self.snapshot.clear(); - for p in peers { - if self.peers.get(p).map_or(false, |p| p.asking == PeerAsking::Nothing) { - self.request_snapshot_manifest(io, *p); + if !self.snapshot.have_manifest() { + for p in peers { + if self.peers.get(p).map_or(false, |p| p.asking == PeerAsking::Nothing) { + self.request_snapshot_manifest(io, *p); + } } + self.state = SyncState::SnapshotManifest; + trace!(target: "sync", "New snapshot sync with {:?}", peers); + } else { + self.state = SyncState::SnapshotData; + trace!(target: "sync", "Resumed snapshot sync with {:?}", peers); } - self.state = SyncState::SnapshotManifest; } /// Restart sync disregarding the block queue status. May end up re-downloading up to QUEUE_SIZE blocks diff --git a/sync/src/snapshot.rs b/sync/src/snapshot.rs index c19860101..94794a4d4 100644 --- a/sync/src/snapshot.rs +++ b/sync/src/snapshot.rs @@ -54,6 +54,11 @@ impl Snapshot { self.snapshot_hash = None; } + /// Check if currently downloading a snapshot. + pub fn have_manifest(&self) -> bool { + self.snapshot_hash.is_some() + } + /// Reset collection for a manifest RLP pub fn reset_to(&mut self, manifest: &ManifestData, hash: &H256) { self.clear(); diff --git a/util/network/src/session.rs b/util/network/src/session.rs index 59eac6e5d..8affb4cf7 100644 --- a/util/network/src/session.rs +++ b/util/network/src/session.rs @@ -35,8 +35,8 @@ use stats::NetworkStats; use time; // Timeout must be less than (interval - 1). -const PING_TIMEOUT_SEC: u64 = 15; -const PING_INTERVAL_SEC: u64 = 30; +const PING_TIMEOUT_SEC: u64 = 60; +const PING_INTERVAL_SEC: u64 = 120; #[derive(Debug, Clone)] enum ProtocolState { From 7e784808406ade575188d1ecec450d055ddda47e Mon Sep 17 00:00:00 2001 From: Gav Wood Date: Fri, 24 Mar 2017 19:03:59 +0100 Subject: [PATCH 14/72] Avoid clogging up tmp when updater dir has bad permissions. (#5024) --- updater/src/updater.rs | 2 +- 1 file changed, 1 insertion(+), 1 deletion(-) diff --git a/updater/src/updater.rs b/updater/src/updater.rs index 5a4e2e1c9..442b2268d 100644 --- a/updater/src/updater.rs +++ b/updater/src/updater.rs @@ -274,7 +274,7 @@ impl Updater { let running_latest = latest.track.version.hash == self.version_info().hash; let already_have_latest = s.installed.as_ref().or(s.ready.as_ref()).map_or(false, |t| *t == latest.track); - if self.update_policy.enable_downloading && !running_later && !running_latest && !already_have_latest { + if !s.disabled && self.update_policy.enable_downloading && !running_later && !running_latest && !already_have_latest { if let Some(b) = latest.track.binary { if s.fetching.is_none() { if self.updates_path(&Self::update_file_name(&latest.track.version)).exists() { From 109012cae894dde87dac96a3423a7cfafbaabd3b Mon Sep 17 00:00:00 2001 From: Robert Habermeier Date: Sat, 25 Mar 2017 10:00:50 +0100 Subject: [PATCH 15/72] force earliest era set in snapshot restore (#5021) --- ethcore/src/snapshot/mod.rs | 18 +++++++++++------- ethcore/src/snapshot/service.rs | 2 +- ethcore/src/snapshot/tests/state.rs | 26 ++++++++++++++++---------- 3 files changed, 28 insertions(+), 18 deletions(-) diff --git a/ethcore/src/snapshot/mod.rs b/ethcore/src/snapshot/mod.rs index d496139ff..89901502b 100644 --- a/ethcore/src/snapshot/mod.rs +++ b/ethcore/src/snapshot/mod.rs @@ -464,14 +464,18 @@ impl StateRebuilder { Ok(()) } - /// Check for accounts missing code. Once all chunks have been fed, there should - /// be none. - pub fn check_missing(self) -> Result<(), Error> { + /// Finalize the restoration. Check for accounts missing code and make a dummy + /// journal entry. + /// Once all chunks have been fed, there should be nothing missing. + pub fn finalize(mut self, era: u64, id: H256) -> Result<(), ::error::Error> { let missing = self.missing_code.keys().cloned().collect::>(); - match missing.is_empty() { - true => Ok(()), - false => Err(Error::MissingCode(missing)), - } + if !missing.is_empty() { return Err(Error::MissingCode(missing).into()) } + + let mut batch = self.db.backing().transaction(); + self.db.journal_under(&mut batch, era, &id)?; + self.db.backing().write_buffered(batch); + + Ok(()) } /// Get the state root of the rebuilder. diff --git a/ethcore/src/snapshot/service.rs b/ethcore/src/snapshot/service.rs index a354f3fd3..ee39203ff 100644 --- a/ethcore/src/snapshot/service.rs +++ b/ethcore/src/snapshot/service.rs @@ -166,7 +166,7 @@ impl Restoration { } // check for missing code. - self.state.check_missing()?; + self.state.finalize(self.manifest.block_number, self.manifest.block_hash)?; // connect out-of-order chunks and verify chain integrity. self.blocks.finalize(self.canonical_hashes)?; diff --git a/ethcore/src/snapshot/tests/state.rs b/ethcore/src/snapshot/tests/state.rs index 854cd07d4..4b0a33c71 100644 --- a/ethcore/src/snapshot/tests/state.rs +++ b/ethcore/src/snapshot/tests/state.rs @@ -61,7 +61,7 @@ fn snap_and_restore() { state_hashes: state_hashes, block_hashes: Vec::new(), state_root: state_root, - block_number: 0, + block_number: 1000, block_hash: H256::default(), }).unwrap(); @@ -69,7 +69,7 @@ fn snap_and_restore() { db_path.push("db"); let db = { let new_db = Arc::new(Database::open(&db_cfg, &db_path.to_string_lossy()).unwrap()); - let mut rebuilder = StateRebuilder::new(new_db.clone(), Algorithm::Archive); + let mut rebuilder = StateRebuilder::new(new_db.clone(), Algorithm::OverlayRecent); let reader = PackedReader::new(&snap_file).unwrap().unwrap(); let flag = AtomicBool::new(true); @@ -82,12 +82,13 @@ fn snap_and_restore() { } assert_eq!(rebuilder.state_root(), state_root); - rebuilder.check_missing().unwrap(); + rebuilder.finalize(1000, H256::default()).unwrap(); new_db }; - let new_db = journaldb::new(db, Algorithm::Archive, ::db::COL_STATE); + let new_db = journaldb::new(db, Algorithm::OverlayRecent, ::db::COL_STATE); + assert_eq!(new_db.earliest_era(), Some(1000)); compare_dbs(&old_db, new_db.as_hashdb()); } @@ -134,13 +135,18 @@ fn get_code_from_prev_chunk() { let db_cfg = DatabaseConfig::with_columns(::db::NUM_COLUMNS); let new_db = Arc::new(Database::open(&db_cfg, &db_path.to_string_lossy()).unwrap()); - let mut rebuilder = StateRebuilder::new(new_db, Algorithm::Archive); - let flag = AtomicBool::new(true); + { + let mut rebuilder = StateRebuilder::new(new_db.clone(), Algorithm::OverlayRecent); + let flag = AtomicBool::new(true); - rebuilder.feed(&chunk1, &flag).unwrap(); - rebuilder.feed(&chunk2, &flag).unwrap(); + rebuilder.feed(&chunk1, &flag).unwrap(); + rebuilder.feed(&chunk2, &flag).unwrap(); - rebuilder.check_missing().unwrap(); + rebuilder.finalize(1000, H256::random()).unwrap(); + } + + let state_db = journaldb::new(new_db, Algorithm::OverlayRecent, ::db::COL_STATE); + assert_eq!(state_db.earliest_era(), Some(1000)); } #[test] @@ -175,7 +181,7 @@ fn checks_flag() { db_path.push("db"); { let new_db = Arc::new(Database::open(&db_cfg, &db_path.to_string_lossy()).unwrap()); - let mut rebuilder = StateRebuilder::new(new_db.clone(), Algorithm::Archive); + let mut rebuilder = StateRebuilder::new(new_db.clone(), Algorithm::OverlayRecent); let reader = PackedReader::new(&snap_file).unwrap().unwrap(); let flag = AtomicBool::new(false); From 4ef89b5ccb85abb33277976b866d2a3ea3e8ced3 Mon Sep 17 00:00:00 2001 From: arkpar Date: Fri, 24 Mar 2017 14:02:04 +0100 Subject: [PATCH 16/72] Fine grained snapshot chunking --- Cargo.lock | 1 + ethcore/Cargo.toml | 1 + ethcore/src/lib.rs | 1 + ethcore/src/snapshot/account.rs | 138 +++++++++++++++---------- ethcore/src/snapshot/error.rs | 3 + ethcore/src/snapshot/io.rs | 32 ++++-- ethcore/src/snapshot/mod.rs | 27 +++-- ethcore/src/snapshot/service.rs | 1 + ethcore/src/snapshot/tests/blocks.rs | 2 + ethcore/src/snapshot/tests/mod.rs | 3 +- ethcore/src/snapshot/tests/service.rs | 1 + ethcore/src/snapshot/tests/state.rs | 6 +- ethcore/src/types/snapshot_manifest.rs | 21 ++-- sync/src/chain.rs | 10 +- util/src/journaldb/overlayrecentdb.rs | 7 +- 15 files changed, 172 insertions(+), 82 deletions(-) diff --git a/Cargo.lock b/Cargo.lock index badb522c4..bf4249000 100644 --- a/Cargo.lock +++ b/Cargo.lock @@ -414,6 +414,7 @@ dependencies = [ "evmjit 1.7.0", "hardware-wallet 1.7.0", "hyper 0.10.0-a.0 (git+https://github.com/paritytech/hyper)", + "itertools 0.5.9 (registry+https://github.com/rust-lang/crates.io-index)", "lazy_static 0.2.1 (registry+https://github.com/rust-lang/crates.io-index)", "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)", diff --git a/ethcore/Cargo.toml b/ethcore/Cargo.toml index d910f9a56..040b0ede0 100644 --- a/ethcore/Cargo.toml +++ b/ethcore/Cargo.toml @@ -27,6 +27,7 @@ byteorder = "1.0" transient-hashmap = "0.4" linked-hash-map = "0.3.0" lru-cache = "0.1.0" +itertools = "0.5" ethabi = "1.0.0" evmjit = { path = "../evmjit", optional = true } clippy = { version = "0.0.103", optional = true} diff --git a/ethcore/src/lib.rs b/ethcore/src/lib.rs index df0738997..f5a52ff3e 100644 --- a/ethcore/src/lib.rs +++ b/ethcore/src/lib.rs @@ -108,6 +108,7 @@ extern crate hardware_wallet; extern crate stats; extern crate ethcore_logger; extern crate num; +extern crate itertools; #[macro_use] extern crate log; diff --git a/ethcore/src/snapshot/account.rs b/ethcore/src/snapshot/account.rs index c086b5c44..9395eafac 100644 --- a/ethcore/src/snapshot/account.rs +++ b/ethcore/src/snapshot/account.rs @@ -23,6 +23,7 @@ use snapshot::Error; use util::{U256, H256, Bytes, HashDB, SHA3_EMPTY, SHA3_NULL_RLP}; use util::trie::{TrieDB, Trie}; use rlp::{RlpStream, UntrustedRlp}; +use itertools::Itertools; use std::collections::HashSet; @@ -62,53 +63,50 @@ impl CodeState { // walk the account's storage trie, returning an RLP item containing the // account properties and the storage. -pub fn to_fat_rlp(acc: &BasicAccount, acct_db: &AccountDB, used_code: &mut HashSet) -> Result { +pub fn to_fat_rlps(acc: &BasicAccount, acct_db: &AccountDB, used_code: &mut HashSet, preferred_size: usize) -> Result, Error> { + const AVERAGE_BYTES_PER_STORAGE_ENTRY: usize = 47; if acc == &ACC_EMPTY { - return Ok(::rlp::NULL_RLP.to_vec()); + return Ok(vec![::rlp::NULL_RLP.to_vec()]); } let db = TrieDB::new(acct_db, &acc.storage_root)?; - let mut pairs = Vec::new(); + let pair_chunks: Vec> = db.iter()?.chunks(preferred_size / AVERAGE_BYTES_PER_STORAGE_ENTRY).into_iter().map(|chunk| chunk.collect()).collect(); + pair_chunks.into_iter().pad_using(1, |_| Vec::new(), ).map(|pairs| { + let mut stream = RlpStream::new_list(pairs.len()); - for item in db.iter()? { - let (k, v) = item?; - pairs.push((k, v)); - } + for r in pairs { + let (k, v) = r?; + stream.begin_list(2).append(&k).append(&&*v); + } - let mut stream = RlpStream::new_list(pairs.len()); + let pairs_rlp = stream.out(); - for (k, v) in pairs { - stream.begin_list(2).append(&k).append(&&*v); - } + let mut account_stream = RlpStream::new_list(5); + account_stream.append(&acc.nonce) + .append(&acc.balance); - let pairs_rlp = stream.out(); - - let mut account_stream = RlpStream::new_list(5); - account_stream.append(&acc.nonce) - .append(&acc.balance); - - // [has_code, code_hash]. - if acc.code_hash == SHA3_EMPTY { - account_stream.append(&CodeState::Empty.raw()).append_empty_data(); - } else if used_code.contains(&acc.code_hash) { - account_stream.append(&CodeState::Hash.raw()).append(&acc.code_hash); - } else { - match acct_db.get(&acc.code_hash) { - Some(c) => { - used_code.insert(acc.code_hash.clone()); - account_stream.append(&CodeState::Inline.raw()).append(&&*c); - } - None => { - warn!("code lookup failed during snapshot"); - account_stream.append(&false).append_empty_data(); + // [has_code, code_hash]. + if acc.code_hash == SHA3_EMPTY { + account_stream.append(&CodeState::Empty.raw()).append_empty_data(); + } else if used_code.contains(&acc.code_hash) { + account_stream.append(&CodeState::Hash.raw()).append(&acc.code_hash); + } else { + match acct_db.get(&acc.code_hash) { + Some(c) => { + used_code.insert(acc.code_hash.clone()); + account_stream.append(&CodeState::Inline.raw()).append(&&*c); + } + None => { + warn!("code lookup failed during snapshot"); + account_stream.append(&false).append_empty_data(); + } } } - } - account_stream.append_raw(&pairs_rlp, 1); - - Ok(account_stream.out()) + account_stream.append_raw(&pairs_rlp, 1); + Ok(account_stream.out()) + }).collect() } // decode a fat rlp, and rebuild the storage trie as we go. @@ -117,6 +115,7 @@ pub fn to_fat_rlp(acc: &BasicAccount, acct_db: &AccountDB, used_code: &mut HashS pub fn from_fat_rlp( acct_db: &mut AccountDBMut, rlp: UntrustedRlp, + mut storage_root: H256, ) -> Result<(BasicAccount, Option), Error> { use util::{TrieDBMut, TrieMut}; @@ -148,10 +147,12 @@ pub fn from_fat_rlp( } }; - let mut storage_root = H256::zero(); - { - let mut storage_trie = TrieDBMut::new(acct_db, &mut storage_root); + let mut storage_trie = if storage_root.is_zero() { + TrieDBMut::new(acct_db, &mut storage_root) + } else { + TrieDBMut::from_existing(acct_db, &mut storage_root)? + }; let pairs = rlp.at(4)?; for pair_rlp in pairs.iter() { let k: Bytes = pair_rlp.val_at(0)?; @@ -184,7 +185,7 @@ mod tests { use std::collections::HashSet; - use super::{ACC_EMPTY, to_fat_rlp, from_fat_rlp}; + use super::{ACC_EMPTY, to_fat_rlps, from_fat_rlp}; #[test] fn encoding_basic() { @@ -201,9 +202,9 @@ mod tests { let thin_rlp = ::rlp::encode(&account); assert_eq!(::rlp::decode::(&thin_rlp), account); - let fat_rlp = to_fat_rlp(&account, &AccountDB::new(db.as_hashdb(), &addr), &mut Default::default()).unwrap(); - let fat_rlp = UntrustedRlp::new(&fat_rlp); - assert_eq!(from_fat_rlp(&mut AccountDBMut::new(db.as_hashdb_mut(), &addr), fat_rlp).unwrap().0, account); + let fat_rlps = to_fat_rlps(&account, &AccountDB::new(db.as_hashdb(), &addr), &mut Default::default(), usize::max_value()).unwrap(); + let fat_rlp = UntrustedRlp::new(&fat_rlps[0]); + assert_eq!(from_fat_rlp(&mut AccountDBMut::new(db.as_hashdb_mut(), &addr), fat_rlp, H256::zero()).unwrap().0, account); } #[test] @@ -226,9 +227,40 @@ mod tests { let thin_rlp = ::rlp::encode(&account); assert_eq!(::rlp::decode::(&thin_rlp), account); - let fat_rlp = to_fat_rlp(&account, &AccountDB::new(db.as_hashdb(), &addr), &mut Default::default()).unwrap(); - let fat_rlp = UntrustedRlp::new(&fat_rlp); - assert_eq!(from_fat_rlp(&mut AccountDBMut::new(db.as_hashdb_mut(), &addr), fat_rlp).unwrap().0, account); + let fat_rlp = to_fat_rlps(&account, &AccountDB::new(db.as_hashdb(), &addr), &mut Default::default(), usize::max_value()).unwrap(); + let fat_rlp = UntrustedRlp::new(&fat_rlp[0]); + assert_eq!(from_fat_rlp(&mut AccountDBMut::new(db.as_hashdb_mut(), &addr), fat_rlp, H256::zero()).unwrap().0, account); + } + + #[test] + fn encoding_storage_split() { + let mut db = get_temp_state_db(); + let addr = Address::random(); + + let account = { + let acct_db = AccountDBMut::new(db.as_hashdb_mut(), &addr); + let mut root = SHA3_NULL_RLP; + fill_storage(acct_db, &mut root, &mut H256::zero()); + BasicAccount { + nonce: 25.into(), + balance: 987654321.into(), + storage_root: root, + code_hash: SHA3_EMPTY, + } + }; + + let thin_rlp = ::rlp::encode(&account); + assert_eq!(::rlp::decode::(&thin_rlp), account); + + let fat_rlps = to_fat_rlps(&account, &AccountDB::new(db.as_hashdb(), &addr), &mut Default::default(), 1000).unwrap(); + let mut root = SHA3_NULL_RLP; + let mut restored_account = None; + for rlp in fat_rlps { + let fat_rlp = UntrustedRlp::new(&rlp); + restored_account = Some(from_fat_rlp(&mut AccountDBMut::new(db.as_hashdb_mut(), &addr), fat_rlp, root).unwrap().0); + root = restored_account.as_ref().unwrap().storage_root.clone(); + } + assert_eq!(restored_account, Some(account)); } #[test] @@ -264,18 +296,18 @@ mod tests { let mut used_code = HashSet::new(); - let fat_rlp1 = to_fat_rlp(&account1, &AccountDB::new(db.as_hashdb(), &addr1), &mut used_code).unwrap(); - let fat_rlp2 = to_fat_rlp(&account2, &AccountDB::new(db.as_hashdb(), &addr2), &mut used_code).unwrap(); + let fat_rlp1 = to_fat_rlps(&account1, &AccountDB::new(db.as_hashdb(), &addr1), &mut used_code, usize::max_value()).unwrap(); + let fat_rlp2 = to_fat_rlps(&account2, &AccountDB::new(db.as_hashdb(), &addr2), &mut used_code, usize::max_value()).unwrap(); assert_eq!(used_code.len(), 1); - let fat_rlp1 = UntrustedRlp::new(&fat_rlp1); - let fat_rlp2 = UntrustedRlp::new(&fat_rlp2); + let fat_rlp1 = UntrustedRlp::new(&fat_rlp1[0]); + let fat_rlp2 = UntrustedRlp::new(&fat_rlp2[0]); - let (acc, maybe_code) = from_fat_rlp(&mut AccountDBMut::new(db.as_hashdb_mut(), &addr2), fat_rlp2).unwrap(); + let (acc, maybe_code) = from_fat_rlp(&mut AccountDBMut::new(db.as_hashdb_mut(), &addr2), fat_rlp2, H256::zero()).unwrap(); assert!(maybe_code.is_none()); assert_eq!(acc, account2); - let (acc, maybe_code) = from_fat_rlp(&mut AccountDBMut::new(db.as_hashdb_mut(), &addr1), fat_rlp1).unwrap(); + let (acc, maybe_code) = from_fat_rlp(&mut AccountDBMut::new(db.as_hashdb_mut(), &addr1), fat_rlp1, H256::zero()).unwrap(); assert_eq!(maybe_code, Some(b"this is definitely code".to_vec())); assert_eq!(acc, account1); } @@ -285,7 +317,7 @@ mod tests { let mut db = get_temp_state_db(); let mut used_code = HashSet::new(); - assert_eq!(to_fat_rlp(&ACC_EMPTY, &AccountDB::new(db.as_hashdb(), &Address::default()), &mut used_code).unwrap(), ::rlp::NULL_RLP.to_vec()); - assert_eq!(from_fat_rlp(&mut AccountDBMut::new(db.as_hashdb_mut(), &Address::default()), UntrustedRlp::new(&::rlp::NULL_RLP)).unwrap(), (ACC_EMPTY, None)); + assert_eq!(to_fat_rlps(&ACC_EMPTY, &AccountDB::new(db.as_hashdb(), &Address::default()), &mut used_code, usize::max_value()).unwrap(), vec![::rlp::NULL_RLP.to_vec()]); + assert_eq!(from_fat_rlp(&mut AccountDBMut::new(db.as_hashdb_mut(), &Address::default()), UntrustedRlp::new(&::rlp::NULL_RLP), H256::zero()).unwrap(), (ACC_EMPTY, None)); } } diff --git a/ethcore/src/snapshot/error.rs b/ethcore/src/snapshot/error.rs index 11491cd73..da8a9816b 100644 --- a/ethcore/src/snapshot/error.rs +++ b/ethcore/src/snapshot/error.rs @@ -53,6 +53,8 @@ pub enum Error { Decoder(DecoderError), /// Io error. Io(::std::io::Error), + /// Snapshot version is not supported. + VersionNotSupported(u64), } impl fmt::Display for Error { @@ -73,6 +75,7 @@ impl fmt::Display for Error { Error::Io(ref err) => err.fmt(f), Error::Decoder(ref err) => err.fmt(f), Error::Trie(ref err) => err.fmt(f), + Error::VersionNotSupported(ref ver) => write!(f, "Snapshot version {} is not supprted.", ver), } } } diff --git a/ethcore/src/snapshot/io.rs b/ethcore/src/snapshot/io.rs index e8f11efd1..8cb778117 100644 --- a/ethcore/src/snapshot/io.rs +++ b/ethcore/src/snapshot/io.rs @@ -31,6 +31,8 @@ use rlp::{self, Encodable, RlpStream, UntrustedRlp}; use super::ManifestData; +const SNAPSHOT_VERSION: u64 = 2; + /// Something which can write snapshots. /// Writing the same chunk multiple times will lead to implementation-defined /// behavior, and is not advised. @@ -118,8 +120,9 @@ impl SnapshotWriter for PackedWriter { fn finish(mut self, manifest: ManifestData) -> io::Result<()> { // we ignore the hashes fields of the manifest under the assumption that // they are consistent with ours. - let mut stream = RlpStream::new_list(5); + let mut stream = RlpStream::new_list(6); stream + .append(&SNAPSHOT_VERSION) .append_list(&self.state_hashes) .append_list(&self.block_hashes) .append(&manifest.state_root) @@ -221,7 +224,7 @@ impl PackedReader { /// Create a new `PackedReader` for the file at the given path. /// This will fail if any io errors are encountered or the file /// is not a valid packed snapshot. - pub fn new(path: &Path) -> Result, ::error::Error> { + pub fn new(path: &Path) -> Result, ::snapshot::error::Error> { let mut file = File::open(path)?; let file_len = file.metadata()?.len(); if file_len < 8 { @@ -255,15 +258,26 @@ impl PackedReader { let rlp = UntrustedRlp::new(&manifest_buf); - let state: Vec = rlp.list_at(0)?; - let blocks: Vec = rlp.list_at(1)?; + let (start, version) = if rlp.item_count()? == 5 { + (0, 1) + } else { + (1, rlp.val_at(0)?) + }; + + if version > SNAPSHOT_VERSION { + return Err(::snapshot::error::Error::VersionNotSupported(version)); + } + + let state: Vec = rlp.list_at(0 + start)?; + let blocks: Vec = rlp.list_at(1 + start)?; let manifest = ManifestData { + version: version, state_hashes: state.iter().map(|c| c.0).collect(), block_hashes: blocks.iter().map(|c| c.0).collect(), - state_root: rlp.val_at(2)?, - block_number: rlp.val_at(3)?, - block_hash: rlp.val_at(4)?, + state_root: rlp.val_at(2 + start)?, + block_number: rlp.val_at(3 + start)?, + block_hash: rlp.val_at(4 + start)?, }; Ok(Some(PackedReader { @@ -346,7 +360,7 @@ mod tests { use util::sha3::Hashable; use snapshot::ManifestData; - use super::{SnapshotWriter, SnapshotReader, PackedWriter, PackedReader, LooseWriter, LooseReader}; + use super::{SnapshotWriter, SnapshotReader, PackedWriter, PackedReader, LooseWriter, LooseReader, SNAPSHOT_VERSION}; const STATE_CHUNKS: &'static [&'static [u8]] = &[b"dog", b"cat", b"hello world", b"hi", b"notarealchunk"]; const BLOCK_CHUNKS: &'static [&'static [u8]] = &[b"hello!", b"goodbye!", b"abcdefg", b"hijklmnop", b"qrstuvwxy", b"and", b"z"]; @@ -372,6 +386,7 @@ mod tests { } let manifest = ManifestData { + version: SNAPSHOT_VERSION, state_hashes: state_hashes, block_hashes: block_hashes, state_root: b"notarealroot".sha3(), @@ -410,6 +425,7 @@ mod tests { } let manifest = ManifestData { + version: SNAPSHOT_VERSION, state_hashes: state_hashes, block_hashes: block_hashes, state_root: b"notarealroot".sha3(), diff --git a/ethcore/src/snapshot/mod.rs b/ethcore/src/snapshot/mod.rs index 89901502b..57d044a47 100644 --- a/ethcore/src/snapshot/mod.rs +++ b/ethcore/src/snapshot/mod.rs @@ -56,6 +56,7 @@ pub use self::traits::SnapshotService; pub use self::watcher::Watcher; pub use types::snapshot_manifest::ManifestData; pub use types::restoration_status::RestorationStatus; +pub use types::basic_account::BasicAccount; pub mod io; pub mod service; @@ -147,6 +148,7 @@ pub fn take_snapshot( info!("produced {} state chunks and {} block chunks.", state_hashes.len(), block_hashes.len()); let manifest_data = ManifestData { + version: 2, state_hashes: state_hashes, block_hashes: block_hashes, state_root: *state_root, @@ -300,14 +302,14 @@ impl<'a> StateChunker<'a> { // // If the buffer is greater than the desired chunk size, // this will write out the data to disk. - fn push(&mut self, account_hash: Bytes, data: Bytes) -> Result<(), Error> { + fn push(&mut self, account_hash: Bytes, data: Bytes, force_chunk: bool) -> Result<(), Error> { let pair = { let mut stream = RlpStream::new_list(2); stream.append(&account_hash).append_raw(&data, 1); stream.out() }; - if self.cur_size + pair.len() >= PREFERRED_CHUNK_SIZE { + if force_chunk || self.cur_size + pair.len() >= PREFERRED_CHUNK_SIZE { self.write_chunk()?; } @@ -372,8 +374,10 @@ pub fn chunk_state<'a>(db: &HashDB, root: &H256, writer: &Mutex 0)?; + } } if chunker.cur_size != 0 { @@ -390,6 +394,7 @@ pub struct StateRebuilder { known_code: HashMap, // code hashes mapped to first account with this code. missing_code: HashMap>, // maps code hashes to lists of accounts missing that code. bloom: Bloom, + known_storage_roots: HashMap, // maps account hashes to last known storage root. Only filled for last account per chunk. } impl StateRebuilder { @@ -401,6 +406,7 @@ impl StateRebuilder { known_code: HashMap::new(), missing_code: HashMap::new(), bloom: StateDB::load_bloom(&*db), + known_storage_roots: HashMap::new(), } } @@ -418,6 +424,7 @@ impl StateRebuilder { rlp, &mut pairs, &self.known_code, + &mut self.known_storage_roots, flag )?; @@ -496,10 +503,11 @@ fn rebuild_accounts( account_fat_rlps: UntrustedRlp, out_chunk: &mut [(H256, Bytes)], known_code: &HashMap, + known_storage_roots: &mut HashMap, abort_flag: &AtomicBool, ) -> Result { let mut status = RebuiltStatus::default(); - for (account_rlp, out) in account_fat_rlps.into_iter().zip(out_chunk) { + for (account_rlp, out) in account_fat_rlps.into_iter().zip(out_chunk.iter_mut()) { if !abort_flag.load(Ordering::SeqCst) { return Err(Error::RestorationAborted.into()) } let hash: H256 = account_rlp.val_at(0)?; @@ -510,7 +518,8 @@ fn rebuild_accounts( // fill out the storage trie and code while decoding. let (acc, maybe_code) = { let mut acct_db = AccountDBMut::from_hash(db, hash); - account::from_fat_rlp(&mut acct_db, fat_rlp)? + let storage_root = known_storage_roots.get(&hash).cloned().unwrap_or(H256::zero()); + account::from_fat_rlp(&mut acct_db, fat_rlp, storage_root)? }; let code_hash = acc.code_hash.clone(); @@ -542,6 +551,12 @@ fn rebuild_accounts( *out = (hash, thin_rlp); } + if let Some(&(ref hash, ref rlp)) = out_chunk.iter().last() { + known_storage_roots.insert(*hash, ::rlp::decode::(rlp).storage_root); + } + if let Some(&(ref hash, ref rlp)) = out_chunk.iter().next() { + known_storage_roots.insert(*hash, ::rlp::decode::(rlp).storage_root); + } Ok(status) } diff --git a/ethcore/src/snapshot/service.rs b/ethcore/src/snapshot/service.rs index ee39203ff..06e659bc1 100644 --- a/ethcore/src/snapshot/service.rs +++ b/ethcore/src/snapshot/service.rs @@ -656,6 +656,7 @@ mod tests { assert_eq!(service.status(), RestorationStatus::Inactive); let manifest = ManifestData { + version: 2, state_hashes: vec![], block_hashes: vec![], state_root: Default::default(), diff --git a/ethcore/src/snapshot/tests/blocks.rs b/ethcore/src/snapshot/tests/blocks.rs index f2ee40a7b..ff63afdfc 100644 --- a/ethcore/src/snapshot/tests/blocks.rs +++ b/ethcore/src/snapshot/tests/blocks.rs @@ -63,6 +63,7 @@ fn chunk_and_restore(amount: u64) { let writer = Mutex::new(PackedWriter::new(&snapshot_path).unwrap()); let block_hashes = chunk_blocks(&bc, best_hash, &writer, &Progress::default()).unwrap(); let manifest = ::snapshot::ManifestData { + version: 2, state_hashes: Vec::new(), block_hashes: block_hashes, state_root: ::util::sha3::SHA3_NULL_RLP, @@ -125,6 +126,7 @@ fn checks_flag() { let chain = BlockChain::new(Default::default(), &genesis, db.clone()); let manifest = ::snapshot::ManifestData { + version: 2, state_hashes: Vec::new(), block_hashes: Vec::new(), state_root: ::util::sha3::SHA3_NULL_RLP, diff --git a/ethcore/src/snapshot/tests/mod.rs b/ethcore/src/snapshot/tests/mod.rs index e63cd6c7c..6530bb42a 100644 --- a/ethcore/src/snapshot/tests/mod.rs +++ b/ethcore/src/snapshot/tests/mod.rs @@ -27,6 +27,7 @@ use super::ManifestData; #[test] fn manifest_rlp() { let manifest = ManifestData { + version: 2, block_hashes: Vec::new(), state_hashes: Vec::new(), block_number: 1234567, @@ -35,4 +36,4 @@ fn manifest_rlp() { }; let raw = manifest.clone().into_rlp(); assert_eq!(ManifestData::from_rlp(&raw).unwrap(), manifest); -} \ No newline at end of file +} diff --git a/ethcore/src/snapshot/tests/service.rs b/ethcore/src/snapshot/tests/service.rs index 555ee665b..64a8407aa 100644 --- a/ethcore/src/snapshot/tests/service.rs +++ b/ethcore/src/snapshot/tests/service.rs @@ -122,6 +122,7 @@ fn guards_delete_folders() { path.push("restoration"); let manifest = ManifestData { + version: 2, state_hashes: vec![], block_hashes: vec![], block_number: 0, diff --git a/ethcore/src/snapshot/tests/state.rs b/ethcore/src/snapshot/tests/state.rs index 4b0a33c71..cbe7e172f 100644 --- a/ethcore/src/snapshot/tests/state.rs +++ b/ethcore/src/snapshot/tests/state.rs @@ -58,6 +58,7 @@ fn snap_and_restore() { let state_hashes = chunk_state(&old_db, &state_root, &writer, &Progress::default()).unwrap(); writer.into_inner().finish(::snapshot::ManifestData { + version: 2, state_hashes: state_hashes, block_hashes: Vec::new(), state_root: state_root, @@ -121,10 +122,10 @@ fn get_code_from_prev_chunk() { let mut db = MemoryDB::new(); AccountDBMut::from_hash(&mut db, hash).insert(&code[..]); - let fat_rlp = account::to_fat_rlp(&acc, &AccountDB::from_hash(&db, hash), &mut used_code).unwrap(); + let fat_rlp = account::to_fat_rlps(&acc, &AccountDB::from_hash(&db, hash), &mut used_code, usize::max_value()).unwrap(); let mut stream = RlpStream::new_list(1); - stream.begin_list(2).append(&hash).append_raw(&fat_rlp, 1); + stream.begin_list(2).append(&hash).append_raw(&fat_rlp[0], 1); stream.out() }; @@ -170,6 +171,7 @@ fn checks_flag() { let state_hashes = chunk_state(&old_db, &state_root, &writer, &Progress::default()).unwrap(); writer.into_inner().finish(::snapshot::ManifestData { + version: 2, state_hashes: state_hashes, block_hashes: Vec::new(), state_root: state_root, diff --git a/ethcore/src/types/snapshot_manifest.rs b/ethcore/src/types/snapshot_manifest.rs index 84ca05822..58b25b6a7 100644 --- a/ethcore/src/types/snapshot_manifest.rs +++ b/ethcore/src/types/snapshot_manifest.rs @@ -24,6 +24,8 @@ use util::Bytes; #[derive(Debug, Clone, PartialEq, Eq)] #[cfg_attr(feature = "ipc", binary)] pub struct ManifestData { + /// Snapshot format version. + pub version: u64, /// List of state chunk hashes. pub state_hashes: Vec, /// List of block chunk hashes. @@ -39,7 +41,8 @@ pub struct ManifestData { impl ManifestData { /// Encode the manifest data to rlp. pub fn into_rlp(self) -> Bytes { - let mut stream = RlpStream::new_list(5); + let mut stream = RlpStream::new_list(6); + stream.append(&self.version); stream.append_list(&self.state_hashes); stream.append_list(&self.block_hashes); stream.append(&self.state_root); @@ -52,14 +55,20 @@ impl ManifestData { /// Try to restore manifest data from raw bytes, interpreted as RLP. pub fn from_rlp(raw: &[u8]) -> Result { let decoder = UntrustedRlp::new(raw); + let (start, version) = if decoder.item_count()? == 5 { + (0, 1) + } else { + (1, decoder.val_at(0)?) + }; - let state_hashes: Vec = decoder.list_at(0)?; - let block_hashes: Vec = decoder.list_at(1)?; - let state_root: H256 = decoder.val_at(2)?; - let block_number: u64 = decoder.val_at(3)?; - let block_hash: H256 = decoder.val_at(4)?; + let state_hashes: Vec = decoder.list_at(start + 0)?; + let block_hashes: Vec = decoder.list_at(start + 1)?; + let state_root: H256 = decoder.val_at(start + 2)?; + let block_number: u64 = decoder.val_at(start + 3)?; + let block_hash: H256 = decoder.val_at(start + 4)?; Ok(ManifestData { + version: version, state_hashes: state_hashes, block_hashes: block_hashes, state_root: state_root, diff --git a/sync/src/chain.rs b/sync/src/chain.rs index df5f65a86..ca5172fc2 100644 --- a/sync/src/chain.rs +++ b/sync/src/chain.rs @@ -158,6 +158,8 @@ pub const SNAPSHOT_SYNC_PACKET_COUNT: u8 = 0x16; const MAX_SNAPSHOT_CHUNKS_DOWNLOAD_AHEAD: usize = 3; +const MIN_SUPPORTED_SNAPSHOT_MANIFEST_VERSION: u64 = 1; + const WAIT_PEERS_TIMEOUT_SEC: u64 = 5; const STATUS_TIMEOUT_SEC: u64 = 5; const HEADERS_TIMEOUT_SEC: u64 = 15; @@ -1028,12 +1030,18 @@ impl ChainSync { let manifest = match ManifestData::from_rlp(manifest_rlp.as_raw()) { Err(e) => { trace!(target: "sync", "{}: Ignored bad manifest: {:?}", peer_id, e); - io.disconnect_peer(peer_id); + io.disable_peer(peer_id); self.continue_sync(io); return Ok(()); } Ok(manifest) => manifest, }; + if manifest.version < MIN_SUPPORTED_SNAPSHOT_MANIFEST_VERSION { + trace!(target: "sync", "{}: Snapshot manifest version too low: {}", peer_id, manifest.version); + io.disable_peer(peer_id); + self.continue_sync(io); + return Ok(()); + } self.snapshot.reset_to(&manifest, &manifest_rlp.as_raw().sha3()); io.snapshot_service().begin_restore(manifest); self.state = SyncState::SnapshotData; diff --git a/util/src/journaldb/overlayrecentdb.rs b/util/src/journaldb/overlayrecentdb.rs index 7eeabf6df..af92d3b40 100644 --- a/util/src/journaldb/overlayrecentdb.rs +++ b/util/src/journaldb/overlayrecentdb.rs @@ -380,10 +380,7 @@ impl JournalDB for OverlayRecentDB { match rc { 0 => {} - 1 => { - if cfg!(debug_assertions) && self.backing.get(self.column, &key)?.is_some() { - return Err(BaseDataError::AlreadyExists(key).into()); - } + _ if rc > 0 => { batch.put(self.column, &key, &value) } -1 => { @@ -392,7 +389,7 @@ impl JournalDB for OverlayRecentDB { } batch.delete(self.column, &key) } - _ => panic!("Attempted to inject invalid state."), + _ => panic!("Attempted to inject invalid state ({})", rc), } } From 56ba9a30ac46e0830ed9a1258176f61c2ec295a9 Mon Sep 17 00:00:00 2001 From: arkpar Date: Fri, 24 Mar 2017 14:29:03 +0100 Subject: [PATCH 17/72] Fixed sync tests --- sync/src/snapshot.rs | 1 + sync/src/tests/snapshot.rs | 1 + 2 files changed, 2 insertions(+) diff --git a/sync/src/snapshot.rs b/sync/src/snapshot.rs index 94794a4d4..727991caa 100644 --- a/sync/src/snapshot.rs +++ b/sync/src/snapshot.rs @@ -144,6 +144,7 @@ mod test { let state_chunks: Vec = (0..20).map(|_| H256::random().to_vec()).collect(); let block_chunks: Vec = (0..20).map(|_| H256::random().to_vec()).collect(); let manifest = ManifestData { + version: 2, state_hashes: state_chunks.iter().map(|data| data.sha3()).collect(), block_hashes: block_chunks.iter().map(|data| data.sha3()).collect(), state_root: H256::new(), diff --git a/sync/src/tests/snapshot.rs b/sync/src/tests/snapshot.rs index 0affb0b1a..16114e216 100644 --- a/sync/src/tests/snapshot.rs +++ b/sync/src/tests/snapshot.rs @@ -49,6 +49,7 @@ impl TestSnapshotService { let state_chunks: Vec = (0..num_state_chunks).map(|_| H256::random().to_vec()).collect(); let block_chunks: Vec = (0..num_block_chunks).map(|_| H256::random().to_vec()).collect(); let manifest = ManifestData { + version: 2, state_hashes: state_chunks.iter().map(|data| data.sha3()).collect(), block_hashes: block_chunks.iter().map(|data| data.sha3()).collect(), state_root: H256::new(), From b52c7bba4bd325251636a9a24a1460b643852d6d Mon Sep 17 00:00:00 2001 From: arkpar Date: Fri, 24 Mar 2017 15:43:54 +0100 Subject: [PATCH 18/72] Fewer allocations --- ethcore/src/snapshot/account.rs | 5 +++-- 1 file changed, 3 insertions(+), 2 deletions(-) diff --git a/ethcore/src/snapshot/account.rs b/ethcore/src/snapshot/account.rs index 9395eafac..4f80d61ea 100644 --- a/ethcore/src/snapshot/account.rs +++ b/ethcore/src/snapshot/account.rs @@ -71,8 +71,9 @@ pub fn to_fat_rlps(acc: &BasicAccount, acct_db: &AccountDB, used_code: &mut Hash let db = TrieDB::new(acct_db, &acc.storage_root)?; - let pair_chunks: Vec> = db.iter()?.chunks(preferred_size / AVERAGE_BYTES_PER_STORAGE_ENTRY).into_iter().map(|chunk| chunk.collect()).collect(); - pair_chunks.into_iter().pad_using(1, |_| Vec::new(), ).map(|pairs| { + let chunks = db.iter()?.chunks(preferred_size / AVERAGE_BYTES_PER_STORAGE_ENTRY); + let pair_chunks = chunks.into_iter().map(|chunk| chunk.collect()); + pair_chunks.pad_using(1, |_| Vec::new(), ).map(|pairs| { let mut stream = RlpStream::new_list(pairs.len()); for r in pairs { From b0a9c1e0fa87eb25a729d47af4ae5d1ae3b838b5 Mon Sep 17 00:00:00 2001 From: arkpar Date: Sat, 25 Mar 2017 15:25:20 +0100 Subject: [PATCH 19/72] Limit by entry count --- ethcore/src/snapshot/account.rs | 7 +++---- ethcore/src/snapshot/mod.rs | 5 ++++- 2 files changed, 7 insertions(+), 5 deletions(-) diff --git a/ethcore/src/snapshot/account.rs b/ethcore/src/snapshot/account.rs index 4f80d61ea..b06c220e7 100644 --- a/ethcore/src/snapshot/account.rs +++ b/ethcore/src/snapshot/account.rs @@ -63,15 +63,14 @@ impl CodeState { // walk the account's storage trie, returning an RLP item containing the // account properties and the storage. -pub fn to_fat_rlps(acc: &BasicAccount, acct_db: &AccountDB, used_code: &mut HashSet, preferred_size: usize) -> Result, Error> { - const AVERAGE_BYTES_PER_STORAGE_ENTRY: usize = 47; +pub fn to_fat_rlps(acc: &BasicAccount, acct_db: &AccountDB, used_code: &mut HashSet, max_storage_items: usize) -> Result, Error> { if acc == &ACC_EMPTY { return Ok(vec![::rlp::NULL_RLP.to_vec()]); } let db = TrieDB::new(acct_db, &acc.storage_root)?; - let chunks = db.iter()?.chunks(preferred_size / AVERAGE_BYTES_PER_STORAGE_ENTRY); + let chunks = db.iter()?.chunks(max_storage_items); let pair_chunks = chunks.into_iter().map(|chunk| chunk.collect()); pair_chunks.pad_using(1, |_| Vec::new(), ).map(|pairs| { let mut stream = RlpStream::new_list(pairs.len()); @@ -253,7 +252,7 @@ mod tests { let thin_rlp = ::rlp::encode(&account); assert_eq!(::rlp::decode::(&thin_rlp), account); - let fat_rlps = to_fat_rlps(&account, &AccountDB::new(db.as_hashdb(), &addr), &mut Default::default(), 1000).unwrap(); + let fat_rlps = to_fat_rlps(&account, &AccountDB::new(db.as_hashdb(), &addr), &mut Default::default(), 100).unwrap(); let mut root = SHA3_NULL_RLP; let mut restored_account = None; for rlp in fat_rlps { diff --git a/ethcore/src/snapshot/mod.rs b/ethcore/src/snapshot/mod.rs index 57d044a47..1241152d0 100644 --- a/ethcore/src/snapshot/mod.rs +++ b/ethcore/src/snapshot/mod.rs @@ -83,6 +83,9 @@ mod traits { // Try to have chunks be around 4MB (before compression) const PREFERRED_CHUNK_SIZE: usize = 4 * 1024 * 1024; +// Try to have chunks be around 4MB (before compression) +const MAX_STORAGE_ENTRIES_PER_ACCOUNT_RECORD: usize = 80_000; + // How many blocks to include in a snapshot, starting from the head of the chain. const SNAPSHOT_BLOCKS: u64 = 30000; @@ -374,7 +377,7 @@ pub fn chunk_state<'a>(db: &HashDB, root: &H256, writer: &Mutex 0)?; } From 34fb39da5b902cc645b7c5b0f3811e72bf8374b3 Mon Sep 17 00:00:00 2001 From: NikVolf Date: Sat, 25 Mar 2017 23:30:11 +0300 Subject: [PATCH 20/72] avoid allocating string --- ethcore/src/builtin.rs | 4 ++-- ethcore/src/evm/evm.rs | 2 +- 2 files changed, 3 insertions(+), 3 deletions(-) diff --git a/ethcore/src/builtin.rs b/ethcore/src/builtin.rs index da0ee38e1..bdedd5739 100644 --- a/ethcore/src/builtin.rs +++ b/ethcore/src/builtin.rs @@ -28,11 +28,11 @@ use ethkey::{Signature, recover as ec_recover}; use ethjson; #[derive(Debug)] -pub struct Error(pub String); +pub struct Error(pub &'static str); impl From<&'static str> for Error { fn from(val: &'static str) -> Self { - Error(val.to_owned()) + Error(val) } } diff --git a/ethcore/src/evm/evm.rs b/ethcore/src/evm/evm.rs index 0e7a4d968..265b83559 100644 --- a/ethcore/src/evm/evm.rs +++ b/ethcore/src/evm/evm.rs @@ -61,7 +61,7 @@ pub enum Error { limit: usize }, /// Built-in contract failed on given input - BuiltIn(String), + BuiltIn(&'static str), /// Returned on evm internal error. Should never be ignored during development. /// Likely to cause consensus issues. Internal(String), From 387a5fb03b83dda786fc81e38020afd8871b4ff3 Mon Sep 17 00:00:00 2001 From: arkpar Date: Sun, 26 Mar 2017 13:26:20 +0200 Subject: [PATCH 21/72] Doc --- ethcore/src/snapshot/account.rs | 5 +++-- 1 file changed, 3 insertions(+), 2 deletions(-) diff --git a/ethcore/src/snapshot/account.rs b/ethcore/src/snapshot/account.rs index b06c220e7..dacd9ba52 100644 --- a/ethcore/src/snapshot/account.rs +++ b/ethcore/src/snapshot/account.rs @@ -61,8 +61,9 @@ impl CodeState { } } -// walk the account's storage trie, returning an RLP item containing the -// account properties and the storage. +// walk the account's storage trie, returning a vector of RLP items containing the +// account properties and the storage. Each item contains at most `max_storage_items` +// storage records split according to snapshot format definition. pub fn to_fat_rlps(acc: &BasicAccount, acct_db: &AccountDB, used_code: &mut HashSet, max_storage_items: usize) -> Result, Error> { if acc == &ACC_EMPTY { return Ok(vec![::rlp::NULL_RLP.to_vec()]); From 23d3b79d9aa2a411b6414bbe35de80569eb93fe2 Mon Sep 17 00:00:00 2001 From: Marek Kotewicz Date: Mon, 27 Mar 2017 16:42:40 +0700 Subject: [PATCH 22/72] eip100b (#5027) * eip100b * fix eip100b build and tests * Conventional comparison order --- ethcore/src/ethereum/ethash.rs | 28 ++++++++++++++++++++++------ ethcore/src/tests/helpers.rs | 2 ++ json/src/spec/ethash.rs | 8 ++++++++ 3 files changed, 32 insertions(+), 6 deletions(-) diff --git a/ethcore/src/ethereum/ethash.rs b/ethcore/src/ethereum/ethash.rs index b1907971c..5bc31c5d9 100644 --- a/ethcore/src/ethereum/ethash.rs +++ b/ethcore/src/ethereum/ethash.rs @@ -43,6 +43,8 @@ pub struct EthashParams { pub difficulty_bound_divisor: U256, /// Difficulty increment divisor. pub difficulty_increment_divisor: u64, + /// Metropolis difficulty increment divisor. + pub metropolis_difficulty_increment_divisor: u64, /// Block duration. pub duration_limit: u64, /// Block reward. @@ -63,6 +65,8 @@ pub struct EthashParams { pub difficulty_hardfork_bound_divisor: U256, /// Block on which there is no additional difficulty from the exponential bomb. pub bomb_defuse_transition: u64, + /// Number of first block where EIP-100 rules begin. + pub eip100b_transition: u64, /// Number of first block where EIP-150 rules begin. pub eip150_transition: u64, /// Number of first block where EIP-155 rules begin. @@ -96,6 +100,7 @@ impl From for EthashParams { minimum_difficulty: p.minimum_difficulty.into(), difficulty_bound_divisor: p.difficulty_bound_divisor.into(), difficulty_increment_divisor: p.difficulty_increment_divisor.map_or(10, Into::into), + metropolis_difficulty_increment_divisor: p.metropolis_difficulty_increment_divisor.map_or(9, Into::into), duration_limit: p.duration_limit.into(), block_reward: p.block_reward.into(), registrar: p.registrar.map_or_else(Address::new, Into::into), @@ -106,6 +111,7 @@ impl From for EthashParams { difficulty_hardfork_transition: p.difficulty_hardfork_transition.map_or(u64::max_value(), Into::into), difficulty_hardfork_bound_divisor: p.difficulty_hardfork_bound_divisor.map_or(p.difficulty_bound_divisor.into(), Into::into), bomb_defuse_transition: p.bomb_defuse_transition.map_or(u64::max_value(), Into::into), + eip100b_transition: p.eip100b_transition.map_or(u64::max_value(), Into::into), eip150_transition: p.eip150_transition.map_or(0, Into::into), eip155_transition: p.eip155_transition.map_or(0, Into::into), eip160_transition: p.eip160_transition.map_or(0, Into::into), @@ -406,6 +412,8 @@ impl Ethash { panic!("Can't calculate genesis block difficulty"); } + let parent_has_uncles = parent.uncles_hash() != &sha3::SHA3_EMPTY_LIST_RLP; + let min_difficulty = self.ethash_params.minimum_difficulty; let difficulty_hardfork = header.number() >= self.ethash_params.difficulty_hardfork_transition; let difficulty_bound_divisor = match difficulty_hardfork { @@ -417,19 +425,27 @@ impl Ethash { let mut target = if header.number() < frontier_limit { if header.timestamp() >= parent.timestamp() + duration_limit { - parent.difficulty().clone() - (parent.difficulty().clone() / difficulty_bound_divisor) + *parent.difficulty() - (*parent.difficulty() / difficulty_bound_divisor) } else { - parent.difficulty().clone() + (parent.difficulty().clone() / difficulty_bound_divisor) + *parent.difficulty() + (*parent.difficulty() / difficulty_bound_divisor) } } else { trace!(target: "ethash", "Calculating difficulty parent.difficulty={}, header.timestamp={}, parent.timestamp={}", parent.difficulty(), header.timestamp(), parent.timestamp()); //block_diff = parent_diff + parent_diff // 2048 * max(1 - (block_timestamp - parent_timestamp) // 10, -99) - let diff_inc = (header.timestamp() - parent.timestamp()) / self.ethash_params.difficulty_increment_divisor; - if diff_inc <= 1 { - parent.difficulty().clone() + parent.difficulty().clone() / From::from(difficulty_bound_divisor) * From::from(1 - diff_inc) + let (increment_divisor, threshold) = if header.number() < self.ethash_params.eip100b_transition { + (self.ethash_params.difficulty_increment_divisor, 1) + } else if parent_has_uncles { + (self.ethash_params.metropolis_difficulty_increment_divisor, 2) } else { - parent.difficulty().clone() - parent.difficulty().clone() / From::from(difficulty_bound_divisor) * From::from(min(diff_inc - 1, 99)) + (self.ethash_params.metropolis_difficulty_increment_divisor, 1) + }; + + let diff_inc = (header.timestamp() - parent.timestamp()) / increment_divisor; + if diff_inc <= threshold { + *parent.difficulty() + *parent.difficulty() / difficulty_bound_divisor * (threshold - diff_inc).into() + } else { + *parent.difficulty() - *parent.difficulty() / difficulty_bound_divisor * min(diff_inc - threshold, 99).into() } }; target = max(min_difficulty, target); diff --git a/ethcore/src/tests/helpers.rs b/ethcore/src/tests/helpers.rs index dcb173b63..2f55fd581 100644 --- a/ethcore/src/tests/helpers.rs +++ b/ethcore/src/tests/helpers.rs @@ -438,6 +438,7 @@ pub fn get_default_ethash_params() -> EthashParams{ minimum_difficulty: U256::from(131072), difficulty_bound_divisor: U256::from(2048), difficulty_increment_divisor: 10, + metropolis_difficulty_increment_divisor: 9, duration_limit: 13, block_reward: U256::from(0), registrar: "0000000000000000000000000000000000000001".into(), @@ -448,6 +449,7 @@ pub fn get_default_ethash_params() -> EthashParams{ difficulty_hardfork_transition: u64::max_value(), difficulty_hardfork_bound_divisor: U256::from(0), bomb_defuse_transition: u64::max_value(), + eip100b_transition: u64::max_value(), eip150_transition: u64::max_value(), eip155_transition: u64::max_value(), eip160_transition: u64::max_value(), diff --git a/json/src/spec/ethash.rs b/json/src/spec/ethash.rs index 95a70f8a0..16d05a18f 100644 --- a/json/src/spec/ethash.rs +++ b/json/src/spec/ethash.rs @@ -35,6 +35,9 @@ pub struct EthashParams { #[serde(rename="difficultyIncrementDivisor")] pub difficulty_increment_divisor: Option, /// See main EthashParams docs. + #[serde(rename="metropolisDifficultyIncrementDivisor")] + pub metropolis_difficulty_increment_divisor: Option, + /// See main EthashParams docs. #[serde(rename="durationLimit")] pub duration_limit: Uint, /// See main EthashParams docs. @@ -67,6 +70,10 @@ pub struct EthashParams { #[serde(rename="bombDefuseTransition")] pub bomb_defuse_transition: Option, + /// See main EthashParams docs. + #[serde(rename="eip100bTransition")] + pub eip100b_transition: Option, + /// See main EthashParams docs. #[serde(rename="eip150Transition")] pub eip150_transition: Option, @@ -164,6 +171,7 @@ mod tests { "difficultyHardforkTransition": "0x59d9", "difficultyHardforkBoundDivisor": "0x0200", "bombDefuseTransition": "0x42", + "eip100bTransition": "0x42", "eip150Transition": "0x42", "eip155Transition": "0x42", "eip160Transition": "0x42", From e8c64b802dbb0980ea815e4894f5913fb1620977 Mon Sep 17 00:00:00 2001 From: Jaco Greeff Date: Mon, 27 Mar 2017 11:42:59 +0200 Subject: [PATCH 23/72] Auto-extract new i18n strings (update) (#5288) * Update passwordHint chain * Update auto-extracted strings --- js/src/i18n/_default/account.js | 6 +- js/src/i18n/_default/accounts.js | 7 +- js/src/i18n/_default/addAddress.js | 1 + js/src/i18n/_default/address.js | 28 +++++ js/src/i18n/_default/addresses.js | 25 +++++ js/src/i18n/_default/application.js | 3 + js/src/i18n/_default/contract.js | 24 +++- js/src/i18n/_default/contracts.js | 28 +++++ js/src/i18n/_default/createAccount.js | 30 ++--- js/src/i18n/_default/createWallet.js | 1 + js/src/i18n/_default/dapps.js | 1 - js/src/i18n/_default/deployContract.js | 9 ++ js/src/i18n/_default/faucet.js | 28 +++++ js/src/i18n/_default/firstRun.js | 17 +++ js/src/i18n/_default/index.js | 10 ++ js/src/i18n/_default/passwordChange.js | 1 + js/src/i18n/_default/saveContract.js | 27 +++++ js/src/i18n/_default/settings.js | 26 +++-- js/src/i18n/_default/signer.js | 103 ++++++++++++++++++ js/src/i18n/_default/status.js | 66 +++++++++++ js/src/i18n/_default/transfer.js | 34 ++++++ js/src/i18n/_default/ui.js | 97 +++++++++++++++-- js/src/i18n/_default/upgradeParity.js | 9 +- js/src/i18n/_default/vaults.js | 37 ++++++- js/src/i18n/_default/verification.js | 85 +++++++++++++++ js/src/i18n/_default/wallet.js | 45 ++++++++ js/src/i18n/_default/walletSettings.js | 23 +++- js/src/i18n/_default/writeContract.js | 62 +++++++++++ .../modals/PasswordManager/passwordManager.js | 2 +- 29 files changed, 789 insertions(+), 46 deletions(-) create mode 100644 js/src/i18n/_default/address.js create mode 100644 js/src/i18n/_default/addresses.js create mode 100644 js/src/i18n/_default/contracts.js create mode 100644 js/src/i18n/_default/faucet.js create mode 100644 js/src/i18n/_default/saveContract.js create mode 100644 js/src/i18n/_default/signer.js create mode 100644 js/src/i18n/_default/status.js create mode 100644 js/src/i18n/_default/verification.js create mode 100644 js/src/i18n/_default/wallet.js create mode 100644 js/src/i18n/_default/writeContract.js diff --git a/js/src/i18n/_default/account.js b/js/src/i18n/_default/account.js index ce5d277dd..7c9d25520 100644 --- a/js/src/i18n/_default/account.js +++ b/js/src/i18n/_default/account.js @@ -16,13 +16,17 @@ export default { button: { - delete: `delete account`, + delete: `delete`, edit: `edit`, + faucet: `Kovan ETH`, password: `password`, shapeshift: `shapeshift`, transfer: `transfer`, verify: `verify` }, + hardware: { + confirmDelete: `Are you sure you want to remove the following hardware address from your account list?` + }, header: { outgoingTransactions: `{count} outgoing transactions`, uuid: `uuid: {uuid}` diff --git a/js/src/i18n/_default/accounts.js b/js/src/i18n/_default/accounts.js index d22c5a504..2db3d5fd9 100644 --- a/js/src/i18n/_default/accounts.js +++ b/js/src/i18n/_default/accounts.js @@ -16,8 +16,8 @@ export default { button: { - newAccount: `new account`, - newWallet: `new wallet`, + newAccount: `account`, + newWallet: `wallet`, vaults: `vaults` }, summary: { @@ -27,5 +27,8 @@ export default { tooltip: { actions: `actions relating to the current view are available on the toolbar for quick access, be it for performing actions or creating a new item`, overview: `your accounts are visible for easy access, allowing you to edit the meta information, make transfers, view transactions and fund the account` + }, + tooltips: { + owner: `{name} (owner)` } }; diff --git a/js/src/i18n/_default/addAddress.js b/js/src/i18n/_default/addAddress.js index 38fd7e361..59ae71518 100644 --- a/js/src/i18n/_default/addAddress.js +++ b/js/src/i18n/_default/addAddress.js @@ -19,6 +19,7 @@ export default { add: `Save Address`, close: `Cancel` }, + header: `To add a new entry to your addressbook, you need the network address of the account and can supply an optional description. Once added it will reflect in your address book.`, input: { address: { hint: `the network address for the entry`, diff --git a/js/src/i18n/_default/address.js b/js/src/i18n/_default/address.js new file mode 100644 index 000000000..ec06d4237 --- /dev/null +++ b/js/src/i18n/_default/address.js @@ -0,0 +1,28 @@ +// 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 . + +export default { + buttons: { + edit: `edit`, + forget: `forget`, + save: `save` + }, + delete: { + confirmInfo: `Are you sure you want to remove the following address from your addressbook?`, + title: `confirm removal` + }, + title: `Address Information` +}; diff --git a/js/src/i18n/_default/addresses.js b/js/src/i18n/_default/addresses.js new file mode 100644 index 000000000..00bb28272 --- /dev/null +++ b/js/src/i18n/_default/addresses.js @@ -0,0 +1,25 @@ +// 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 . + +export default { + buttons: { + add: `address` + }, + errors: { + invalidFile: `The provided file is invalid...` + }, + title: `Saved Addresses` +}; diff --git a/js/src/i18n/_default/application.js b/js/src/i18n/_default/application.js index 1edafff6d..4469d83b2 100644 --- a/js/src/i18n/_default/application.js +++ b/js/src/i18n/_default/application.js @@ -15,6 +15,9 @@ // along with Parity. If not, see . export default { + frame: { + error: `ERROR: This application cannot and should not be loaded in an embedded iFrame` + }, status: { consensus: { capable: `Capable`, diff --git a/js/src/i18n/_default/contract.js b/js/src/i18n/_default/contract.js index e6a2a110b..bf7f00298 100644 --- a/js/src/i18n/_default/contract.js +++ b/js/src/i18n/_default/contract.js @@ -15,5 +15,27 @@ // along with Parity. If not, see . export default { - minedBlock: `Mined at block #{blockNumber}` + buttons: { + close: `Close`, + details: `details`, + edit: `edit`, + execute: `execute`, + forget: `forget` + }, + details: { + title: `contract details` + }, + events: { + eventPending: `pending`, + noEvents: `No events has been sent from this contract.`, + title: `events` + }, + minedBlock: `Mined at block #{blockNumber}`, + queries: { + buttons: { + query: `Query` + }, + title: `queries` + }, + title: `Contract Information` }; diff --git a/js/src/i18n/_default/contracts.js b/js/src/i18n/_default/contracts.js new file mode 100644 index 000000000..4ff840759 --- /dev/null +++ b/js/src/i18n/_default/contracts.js @@ -0,0 +1,28 @@ +// 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 . + +export default { + buttons: { + deploy: `deploy`, + develop: `develop`, + watch: `watch` + }, + sortOrder: { + date: `date`, + minedBlock: `mined block` + }, + title: `Contracts` +}; diff --git a/js/src/i18n/_default/createAccount.js b/js/src/i18n/_default/createAccount.js index 485a877f8..8930fc7b4 100644 --- a/js/src/i18n/_default/createAccount.js +++ b/js/src/i18n/_default/createAccount.js @@ -20,46 +20,49 @@ export default { hint: `the network address for the account`, label: `address` }, - name: { - hint: `a descriptive name for the account`, - label: `account name` - }, phrase: { hint: `the account recovery phrase`, label: `owner recovery phrase (keep private and secure, it allows full and unlimited access to the account)` } }, accountDetailsGeth: { - imported: `You have imported {number} addresses from the Geth keystore:` + imported: `You have completed the import of {number} addresses from the Geth keystore. These will now be available in your accounts list as a normal account, along with their associated balances on the network.` }, button: { back: `Back`, cancel: `Cancel`, - close: `Close`, create: `Create`, + done: `Done`, import: `Import`, next: `Next`, print: `Print Phrase` }, creationType: { fromGeth: { - label: `Import accounts from Geth keystore` + description: `Import accounts from the Geth keystore with the original password`, + label: `Geth keystore` }, fromJSON: { - label: `Import account from a backup JSON file` + description: `Import an industry-standard JSON keyfile with the original password`, + label: `JSON file` }, fromNew: { - label: `Create new account manually` + description: `Selecting your identity icon and specifying the password`, + label: `New Account` }, fromPhrase: { - label: `Recover account from recovery phrase` + description: `Recover using a previously stored recovery phrase and new password`, + label: `Recovery phrase` }, fromPresale: { - label: `Import account from an Ethereum pre-sale wallet` + description: `Import an Ethereum presale wallet file with the original password`, + label: `Presale wallet` }, fromRaw: { - label: `Import raw private key` - } + description: `Enter a previously created raw private key with a new password`, + label: `Private key` + }, + info: `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.` }, newAccount: { hint: { @@ -80,6 +83,7 @@ export default { } }, newGeth: { + available: `There are currently {count} importable keys available from the Geth keystore which are not already available on your Parity instance. Select the accounts you wish to import and move to the next step to complete the import.`, noKeys: `There are currently no importable keys available from the Geth keystore, which are not already available on your Parity instance` }, newImport: { diff --git a/js/src/i18n/_default/createWallet.js b/js/src/i18n/_default/createWallet.js index 9c7d8df3e..eeb9e9a98 100644 --- a/js/src/i18n/_default/createWallet.js +++ b/js/src/i18n/_default/createWallet.js @@ -80,6 +80,7 @@ export default { }, states: { completed: `The contract deployment has been completed`, + confirmationNeeded: `The contract deployment needs confirmations from other owners of the Wallet`, preparing: `Preparing transaction for network transmission`, validatingCode: `Validating the deployed contract code`, waitingConfirm: `Waiting for confirmation of the transaction in the Parity Secure Signer`, diff --git a/js/src/i18n/_default/dapps.js b/js/src/i18n/_default/dapps.js index d13caa46d..9ed3415d1 100644 --- a/js/src/i18n/_default/dapps.js +++ b/js/src/i18n/_default/dapps.js @@ -40,7 +40,6 @@ export default { }, label: `Decentralized Applications`, permissions: { - description: `{activeIcon} account is available to application, {defaultIcon} account is the default account`, label: `visible dapp accounts` } }; diff --git a/js/src/i18n/_default/deployContract.js b/js/src/i18n/_default/deployContract.js index fe7c9a69e..0b5a05503 100644 --- a/js/src/i18n/_default/deployContract.js +++ b/js/src/i18n/_default/deployContract.js @@ -37,6 +37,13 @@ export default { hint: `the owner account for this contract`, label: `from account (contract owner)` }, + advanced: { + label: `advanced sending options` + }, + amount: { + hint: `the amount to transfer to the contract`, + label: `amount to transfer (in {tag})` + }, code: { hint: `the compiled code of the contract to deploy`, label: `code` @@ -65,6 +72,7 @@ export default { }, state: { completed: `The contract deployment has been completed`, + confirmationNeeded: `The operation needs confirmations from the other owners of the contract`, preparing: `Preparing transaction for network transmission`, validatingCode: `Validating the deployed contract code`, waitReceipt: `Waiting for the contract deployment transaction receipt`, @@ -74,6 +82,7 @@ export default { completed: `completed`, deployment: `deployment`, details: `contract details`, + extras: `extra information`, failed: `deployment failed`, parameters: `contract parameters`, rejected: `rejected` diff --git a/js/src/i18n/_default/faucet.js b/js/src/i18n/_default/faucet.js new file mode 100644 index 000000000..11aacef9c --- /dev/null +++ b/js/src/i18n/_default/faucet.js @@ -0,0 +1,28 @@ +// 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 . + +export default { + buttons: { + close: `close`, + done: `close`, + request: `request` + }, + summary: { + done: `Your Kovan ETH has been requested from the faucet which responded with -`, + info: `To request a deposit of Kovan ETH to this address, you need to ensure that the address is sms-verified on the mainnet. Once executed the faucet will deposit Kovan ETH into the current account.` + }, + title: `Kovan ETH Faucet` +}; diff --git a/js/src/i18n/_default/firstRun.js b/js/src/i18n/_default/firstRun.js index 8439d0479..5a3e04a17 100644 --- a/js/src/i18n/_default/firstRun.js +++ b/js/src/i18n/_default/firstRun.js @@ -22,11 +22,28 @@ export default { print: `Print Phrase`, skip: `Skip` }, + completed: { + congrats: `Congratulations! Your node setup has been completed successfully and you are ready to use the application.`, + next: `Next you will receive a walk-through of the available functions and the general application interface to get you up and running in record time.` + }, title: { completed: `completed`, newAccount: `new account`, recovery: `recovery`, terms: `terms`, welcome: `welcome` + }, + tnc: { + accept: `I accept these terms and conditions` + }, + welcome: { + description: `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 -`, + greeting: `Welcome to Parity, the fastest and simplest way to run your node.`, + next: `Click Next to continue your journey.`, + step: { + account: `Created your first Parity account`, + privacy: `Understood our privacy policy & terms of operation`, + recovery: `Have the ability to recover your account` + } } }; diff --git a/js/src/i18n/_default/index.js b/js/src/i18n/_default/index.js index 7e8bac8ef..687e558dc 100644 --- a/js/src/i18n/_default/index.js +++ b/js/src/i18n/_default/index.js @@ -18,10 +18,13 @@ export account from './account'; export accounts from './accounts'; export addAddress from './addAddress'; export addContract from './addContract'; +export address from './address'; export addressSelect from './addressSelect'; +export addresses from './addresses'; export application from './application'; export connection from './connection'; export contract from './contract'; +export contracts from './contracts'; export createAccount from './createAccount'; export createWallet from './createWallet'; export dapp from './dapp'; @@ -32,18 +35,25 @@ export editMeta from './editMeta'; export errors from './errors'; export executeContract from './executeContract'; export extension from './extension'; +export faucet from './faucet'; export firstRun from './firstRun'; export home from './home'; export loadContract from './loadContract'; export parityBar from './parityBar'; export passwordChange from './passwordChange'; +export saveContract from './saveContract'; export settings from './settings'; export shapeshift from './shapeshift'; +export signer from './signer'; +export status from './status'; export tabBar from './tabBar'; export transfer from './transfer'; export txEditor from './txEditor'; export ui from './ui'; export upgradeParity from './upgradeParity'; export vaults from './vaults'; +export verification from './verification'; +export wallet from './wallet'; export walletSettings from './walletSettings'; export web from './web'; +export writeContract from './writeContract'; diff --git a/js/src/i18n/_default/passwordChange.js b/js/src/i18n/_default/passwordChange.js index fc0579250..714a6e25b 100644 --- a/js/src/i18n/_default/passwordChange.js +++ b/js/src/i18n/_default/passwordChange.js @@ -30,6 +30,7 @@ export default { label: `new password` }, passwordHint: { + display: `Hint {hint}`, hint: `hint for the new password`, label: `(optional) new password hint` }, diff --git a/js/src/i18n/_default/saveContract.js b/js/src/i18n/_default/saveContract.js new file mode 100644 index 000000000..62ce1e33f --- /dev/null +++ b/js/src/i18n/_default/saveContract.js @@ -0,0 +1,27 @@ +// 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 . + +export default { + buttons: { + cancel: `Cancel`, + save: `Save` + }, + name: { + hint: `choose a name for this contract`, + label: `contract name` + }, + title: `save contract` +}; diff --git a/js/src/i18n/_default/settings.js b/js/src/i18n/_default/settings.js index 5a656ca6a..3e475e087 100644 --- a/js/src/i18n/_default/settings.js +++ b/js/src/i18n/_default/settings.js @@ -22,20 +22,32 @@ export default { label: `background` }, parity: { + chains: { + chain_classic: `Parity syncs to the Ethereum Classic network`, + chain_dev: `Parity uses a local development chain`, + chain_expanse: `Parity syncs to the Expanse network`, + chain_foundation: `Parity syncs to the Ethereum network launched by the Ethereum Foundation`, + chain_kovan: `Parity syncs to the Kovan test network`, + chain_olympic: `Parity syncs to the Olympic test network`, + chain_ropsten: `Parity syncs to the Ropsten test network`, + cmorden_kovan: `Parity syncs to Morden (Classic) test network`, + hint: `the chain for the Parity node to sync to`, + label: `chain/network to sync` + }, languages: { hint: `the language this interface is displayed with`, label: `UI language` }, loglevels: `Choose the different logs level.`, modes: { - hint: `the syning mode for the Parity node`, + hint: `the syncing mode for the Parity node`, label: `mode of operation`, mode_active: `Parity continuously syncs the chain`, mode_dark: `Parity syncs only when the RPC is active`, mode_offline: `Parity doesn't sync`, mode_passive: `Parity syncs initially, then sleeps and wakes regularly to resync` }, - overview_0: `Control the Parity node settings and mode of operation via this interface.`, + overview_0: `Control the Parity node settings and nature of syncing via this interface.`, label: `parity` }, proxy: { @@ -49,25 +61,25 @@ export default { }, views: { accounts: { - description: `A list of all the accounts associated to and imported into this Parity instance. Send transactions, receive incoming values, manage your balances and fund your accounts.`, + description: `A list of all the accounts associated with and imported into this Parity instance. Send transactions, receive incoming values, manage your balances and fund your accounts.`, label: `Accounts` }, addresses: { - description: `A list of all contacts and address book entries that is managed by this Parity instance. Watch accounts and have the details available at the click of a button when transacting.`, + description: `A list of all contacts and address book entries managed by this Parity instance. Watch accounts and have the details available at the click of a button when transacting.`, label: `Addressbook` }, apps: { - description: `Distributed applications that interact with the underlying network. Add applications, manage you application portfolio and interact with applications from around the network.`, + description: `Distributed applications that interact with the underlying network. Add applications, manage you application portfolio and interact with application from around the network.`, label: `Applications` }, contracts: { description: `Watch and interact with specific contracts that have been deployed on the network. This is a more technically-focused environment, specifically for advanced users that understand the inner working of certain contracts.`, label: `Contracts` }, - overview_0: `Manage the available application views, using only the parts of the application applicable to you.`, + overview_0: `Manage the available application views using only the parts of the application applicable to you.`, overview_1: `Are you an end-user? The defaults are setup for both beginner and advanced users alike.`, overview_2: `Are you a developer? Add some features to manage contracts and interact with application deployments.`, - overview_3: `Are you a miner or do you run a large-scale node? Add the features to give you all the information needed to watch the node operation.`, + overview_3: `Are you a miner or run a large-scale node? Add the features to give you all the information needed to watch the node operation.`, settings: { description: `This view. Allows you to customize the application in term of options, operation and look and feel.`, label: `Settings` diff --git a/js/src/i18n/_default/signer.js b/js/src/i18n/_default/signer.js new file mode 100644 index 000000000..3f8615c52 --- /dev/null +++ b/js/src/i18n/_default/signer.js @@ -0,0 +1,103 @@ +// 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 . + +export default { + embedded: { + noPending: `There are currently no pending requests awaiting your confirmation` + }, + mainDetails: { + editTx: `Edit conditions/gas/gasPrice`, + tooltips: { + total1: `The value of the transaction including the mining fee is {total} {type}.`, + total2: `(This includes a mining fee of {fee} {token})`, + value1: `The value of the transaction.` + } + }, + requestOrigin: { + dapp: `by a dapp at {url}`, + ipc: `via IPC session`, + rpc: `via RPC {rpc}`, + signerCurrent: `via current tab`, + signerUI: `via UI session`, + unknownInterface: `via unknown interface`, + unknownRpc: `unidentified`, + unknownUrl: `unknown URL` + }, + requestsPage: { + noPending: `There are no requests requiring your confirmation.`, + pendingTitle: `Pending Requests`, + queueTitle: `Local Transactions` + }, + sending: { + hardware: { + confirm: `Please confirm the transaction on your attached hardware device`, + connect: `Please attach your hardware device before confirming the transaction` + } + }, + signRequest: { + request: `A request to sign data using your account:`, + state: { + confirmed: `Confirmed`, + rejected: `Rejected` + }, + unknownBinary: `(Unknown binary data)`, + warning: `WARNING: This consequences of doing this may be grave. Confirm the request only if you are sure.` + }, + title: `Trusted Signer`, + txPending: { + buttons: { + viewToggle: `view transaction` + } + }, + txPendingConfirm: { + buttons: { + confirmBusy: `Confirming...`, + confirmRequest: `Confirm Request` + }, + errors: { + invalidWallet: `Given wallet file is invalid.` + }, + password: { + decrypt: { + hint: `decrypt the key`, + label: `Key Password` + }, + unlock: { + hint: `unlock the account`, + label: `Account Password` + } + }, + passwordHint: `(hint) {passwordHint}`, + selectKey: { + hint: `The keyfile to use for this account`, + label: `Select Local Key` + }, + tooltips: { + password: `Please provide a password for this account` + } + }, + txPendingForm: { + changedMind: `I've changed my mind`, + reject: `reject request` + }, + txPendingReject: { + buttons: { + reject: `Reject Request` + }, + info: `Are you sure you want to reject request?`, + undone: `This cannot be undone` + } +}; diff --git a/js/src/i18n/_default/status.js b/js/src/i18n/_default/status.js new file mode 100644 index 000000000..536c0ff90 --- /dev/null +++ b/js/src/i18n/_default/status.js @@ -0,0 +1,66 @@ +// 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 . + +export default { + debug: { + reverse: `Reverse Order`, + stopped: `Refresh and display of logs from Parity is currently stopped via the UI, start it to see the latest updates.`, + title: `Node Logs` + }, + miningSettings: { + input: { + author: { + hint: `the mining author`, + label: `author` + }, + extradata: { + hint: `extra data for mined blocks`, + label: `extradata` + }, + gasFloor: { + hint: `the gas floor target for mining`, + label: `gas floor target` + }, + gasPrice: { + hint: `the minimum gas price for mining`, + label: `minimal gas price` + } + }, + title: `mining settings` + }, + status: { + hashrate: `{hashrate} H/s`, + input: { + chain: `chain`, + enode: `enode`, + no: `no`, + peers: `peers`, + port: `network port`, + rpcEnabled: `rpc enabled`, + rpcInterface: `rpc interface`, + rpcPort: `rpc port`, + yes: `yes` + }, + title: { + bestBlock: `best block`, + hashRate: `hash rate`, + network: `network settings`, + node: `Node`, + peers: `peers` + } + }, + title: `Status` +}; diff --git a/js/src/i18n/_default/transfer.js b/js/src/i18n/_default/transfer.js index 742e816f1..3207f5b06 100644 --- a/js/src/i18n/_default/transfer.js +++ b/js/src/i18n/_default/transfer.js @@ -21,6 +21,40 @@ export default { label: `transaction data` } }, + buttons: { + back: `Back`, + cancel: `Cancel`, + close: `Close`, + next: `Next`, + send: `Send` + }, + details: { + advanced: { + label: `advanced sending options` + }, + amount: { + hint: `the amount to transfer to the recipient`, + label: `amount to transfer (in {tag})` + }, + fullBalance: { + label: `full account balance` + }, + recipient: { + hint: `the recipient address`, + label: `recipient address` + }, + sender: { + hint: `the sender address`, + label: `sender address` + }, + total: { + label: `total transaction amount` + } + }, + wallet: { + confirmation: `This transaction needs confirmation from other owners.`, + operationHash: `operation hash` + }, warning: { wallet_spent_limit: `This transaction value is above the remaining daily limit. It will need to be confirmed by other owners.` } diff --git a/js/src/i18n/_default/ui.js b/js/src/i18n/_default/ui.js index 242f14b9b..d84e7bd13 100644 --- a/js/src/i18n/_default/ui.js +++ b/js/src/i18n/_default/ui.js @@ -15,8 +15,40 @@ // along with Parity. If not, see . export default { + actionbar: { + export: { + button: { + export: `export` + } + }, + import: { + button: { + cancel: `Cancel`, + confirm: `Confirm`, + import: `import` + }, + confirm: `Confirm that this is what was intended to import.`, + error: `An error occured: {errorText}`, + step: { + error: `error`, + select: `select a file`, + validate: `validate` + }, + title: `Import from a file` + }, + search: { + hint: `Enter search input...` + }, + sort: { + sortBy: `Sort by {label}`, + typeDefault: `Default`, + typeEth: `Sort by ETH`, + typeName: `Sort by name`, + typeTags: `Sort by tags` + } + }, balance: { - none: `There are no balances associated with this account` + none: `No balances associated with this account` }, blockStatus: { bestBlock: `{blockNumber} best block`, @@ -28,10 +60,61 @@ export default { no: `no`, yes: `yes` }, + copyToClipboard: { + copied: `copied {data} to clipboard` + }, + errors: { + close: `close` + }, + fileSelect: { + defaultLabel: `Drop a file here, or click to select a file to upload` + }, + gasPriceSelector: { + customTooltip: { + transactions: `{number} {number, plural, one {transaction} other {transactions}} with gas price set from {minPrice} to {maxPrice}` + } + }, identityName: { null: `NULL`, unnamed: `UNNAMED` }, + methodDecoding: { + condition: { + block: `, {historic, select, true {Submitted} false {Submission}} at block {blockNumber}`, + time: `, {historic, select, true {Submitted} false {Submission}} at {timestamp}` + }, + deploy: { + address: `Deployed a contract at address`, + params: `with the following parameters:`, + willDeploy: `Will deploy a contract`, + withValue: `, sending {value}` + }, + gasUsed: `({gas} gas used)`, + gasValues: `{gas} gas ({gasPrice}M/{tag})`, + input: { + data: `data`, + input: `input`, + withInput: `with the {inputDesc} {inputValue}` + }, + receive: { + contract: `the contract`, + info: `{historic, select, true {Received} false {Will receive}} {valueEth} from {aContract}{address}` + }, + signature: { + info: `{historic, select, true {Executed} false {Will execute}} the {method} function on the contract {address} trsansferring {ethValue}{inputLength, plural, zero {,} other {passing the following {inputLength, plural, one {parameter} other {parameters}}}}` + }, + token: { + transfer: `{historic, select, true {Transferred} false {Will transfer}} {value} to {address}` + }, + transfer: { + contract: `the contract`, + info: `{historic, select, true {Transferred} false {Will transfer}} {valueEth} to {aContract}{address}` + }, + txValues: `{historic, select, true {Provided} false {Provides}} {gasProvided}{gasUsed} for a total transaction value of {totalEthValue}`, + unknown: { + info: `{historic, select, true {Executed} false {Will execute}} the {method} on the contract {address} transferring {ethValue}.` + } + }, passwordStrength: { label: `password strength` }, @@ -48,6 +131,10 @@ export default { posted: `The transaction has been posted to the network with a hash of {hashLink}`, waiting: `waiting for confirmations` }, + vaultSelect: { + hint: `the vault this account is attached to`, + label: `associated vault` + }, verification: { gatherData: { accountHasRequested: { @@ -60,10 +147,6 @@ export default { pending: `Checking if your account is verified…`, true: `Your account is already verified.` }, - email: { - hint: `the code will be sent to this address`, - label: `e-mail address` - }, fee: `The additional fee is {amount} ETH.`, isAbleToRequest: { pending: `Validating your input…` @@ -74,10 +157,6 @@ export default { true: `The verification server is running.` }, nofee: `There is no additional fee.`, - phoneNumber: { - hint: `the SMS will be sent to this number`, - label: `phone number in international format` - }, termsOfService: `I agree to the terms and conditions below.` } } diff --git a/js/src/i18n/_default/upgradeParity.js b/js/src/i18n/_default/upgradeParity.js index cca634b88..b3d871452 100644 --- a/js/src/i18n/_default/upgradeParity.js +++ b/js/src/i18n/_default/upgradeParity.js @@ -15,13 +15,13 @@ // along with Parity. If not, see . export default { - busy: `Your upgrade to Parity {newversion} is currently in progress`, + busy: `Your upgrade to Parity {newversion} is currently in progress. Please wait until the process completes.`, button: { close: `close`, done: `done`, upgrade: `upgrade now` }, - completed: `Your upgrade to Parity {newversion} has been successfully completed.`, + completed: `Your upgrade to Parity {newversion} has been successfully completed. Click "done" to automatically reload the application.`, consensus: { capable: `Your current Parity version is capable of handling the network requirements.`, capableUntil: `Your current Parity version is capable of handling the network requirements until block {blockNumber}`, @@ -30,7 +30,10 @@ export default { }, failed: `Your upgrade to Parity {newversion} has failed with an error.`, info: { - upgrade: `A new version of Parity, version {newversion} is available as an upgrade from your current version {currentversion}` + currentVersion: `You are currently running {currentversion}`, + next: `Proceed with "upgrade now" to start your Parity upgrade.`, + upgrade: `An upgrade to version {newversion} is available`, + welcome: `Welcome to the Parity upgrade wizard, allowing you a completely seamless upgrade experience to the next version of Parity.` }, step: { completed: `upgrade completed`, diff --git a/js/src/i18n/_default/vaults.js b/js/src/i18n/_default/vaults.js index 3024beed3..04ff4d558 100644 --- a/js/src/i18n/_default/vaults.js +++ b/js/src/i18n/_default/vaults.js @@ -26,8 +26,9 @@ export default { button: { accounts: `accounts`, add: `create vault`, - close: `close vault`, - open: `open vault` + close: `close`, + edit: `edit`, + open: `open` }, confirmClose: { info: `You are about to close a vault. Any accounts associated with the vault won't be visible after this operation concludes. To view the associated accounts, open the vault again.`, @@ -70,6 +71,38 @@ export default { }, title: `Create a new vault` }, + editMeta: { + allowPassword: `Change vault password`, + button: { + close: `close`, + save: `save` + }, + currentPassword: { + hint: `your current vault password`, + label: `current password` + }, + description: { + hint: `the description for this vault`, + label: `vault description` + }, + password: { + hint: `a strong, unique password`, + label: `new password` + }, + password2: { + hint: `verify your new password`, + label: `new password (repeat)` + }, + passwordHint: { + hint: `your password hint for this vault`, + label: `password hint` + }, + title: `Edit Vault Metadata` + }, empty: `There are currently no vaults to display.`, + selector: { + noneAvailable: `There are currently no vaults opened and available for selection. Create and open some first before attempting to select a vault for an account move.`, + title: `Select Account Vault` + }, title: `Vault Management` }; diff --git a/js/src/i18n/_default/verification.js b/js/src/i18n/_default/verification.js new file mode 100644 index 000000000..2d98ed82a --- /dev/null +++ b/js/src/i18n/_default/verification.js @@ -0,0 +1,85 @@ +// 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 . + +export default { + button: { + cancel: `Cancel`, + done: `Done`, + next: `Next` + }, + code: { + error: `invalid code`, + hint: `Enter the code you received.`, + label: `verification code`, + sent: `The verification code has been sent to {receiver}.` + }, + confirmation: { + authorise: `The verification code will be sent to the contract. Please authorize this using the Parity Signer.`, + windowOpen: `Please keep this window open.` + }, + done: { + message: `Congratulations, your account is verified!` + }, + email: { + enterCode: `Enter the code you received via e-mail.` + }, + gatherData: { + email: { + hint: `the code will be sent to this address`, + label: `e-mail address` + }, + phoneNumber: { + hint: `the SMS will be sent to this number`, + label: `phone number in international format` + } + }, + gatherDate: { + email: { + error: `invalid e-mail` + }, + phoneNumber: { + error: `invalid number` + } + }, + loading: `Loading verification data.`, + request: { + authorise: `A verification request will be sent to the contract. Please authorize this using the Parity Signer.`, + requesting: `Requesting a code from the Parity server and waiting for the puzzle to be put into the contract.`, + windowOpen: `Please keep this window open.` + }, + sms: { + enterCode: `Enter the code you received via SMS.` + }, + steps: { + code: `Enter Code`, + completed: `Completed`, + confirm: `Confirm`, + data: `Enter Data`, + method: `Method`, + request: `Request` + }, + title: `verify your account`, + types: { + email: { + description: `The hash of the e-mail address you prove control over will be stored on the blockchain.`, + label: `E-mail Verification` + }, + sms: { + description: `It will be stored on the blockchain that you control a phone number (not which).`, + label: `SMS Verification` + } + } +}; diff --git a/js/src/i18n/_default/wallet.js b/js/src/i18n/_default/wallet.js new file mode 100644 index 000000000..92063af8b --- /dev/null +++ b/js/src/i18n/_default/wallet.js @@ -0,0 +1,45 @@ +// 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 . + +export default { + buttons: { + edit: `edit`, + forget: `forget`, + settings: `settings`, + transfer: `transfer` + }, + confirmations: { + buttons: { + confirmAs: `Confirm As...`, + revokeAs: `Revoke As...` + }, + none: `No transactions needs confirmation right now.`, + tooltip: { + confirmed: `Confirmed by {number}/{required} owners` + } + }, + details: { + requiredOwners: `This wallet requires at least {owners} to validate any action (transactions, modifications).`, + requiredOwnersNumber: `{number} {numberValue, plural, one {owner} other {owners}}`, + spent: `{spent} has been spent today, out of {limit} set as the daily limit, which has been reset on {date}`, + title: `Details` + }, + title: `Wallet Management`, + transactions: { + none: `No transactions has been sent.`, + title: `Transactions` + } +}; diff --git a/js/src/i18n/_default/walletSettings.js b/js/src/i18n/_default/walletSettings.js index 57dc1a169..ddeae3798 100644 --- a/js/src/i18n/_default/walletSettings.js +++ b/js/src/i18n/_default/walletSettings.js @@ -15,6 +15,16 @@ // along with Parity. If not, see . export default { + addOwner: { + title: `Add Owner` + }, + buttons: { + cancel: `Cancel`, + close: `Close`, + next: `Next`, + send: `Send`, + sending: `Sending...` + }, changes: { modificationString: `For your modifications to be taken into account, other owners have to send the same modifications. They can paste @@ -48,11 +58,12 @@ export default { label: `from account (wallet owner)` } }, - rejected: { - busyStep: { - state: `The wallet settings will not be modified. You can safely close this window.`, - title: `The modifications have been rejected` - }, - title: `rejected` + ownersChange: { + details: `from {from} to {to}`, + title: `Change Required Owners` + }, + rejected: `The transaction #{txid} has been rejected`, + removeOwner: { + title: `Remove Owner` } }; diff --git a/js/src/i18n/_default/writeContract.js b/js/src/i18n/_default/writeContract.js new file mode 100644 index 000000000..fc1100b77 --- /dev/null +++ b/js/src/i18n/_default/writeContract.js @@ -0,0 +1,62 @@ +// 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 . + +export default { + buttons: { + autoCompile: `Auto-Compile`, + compile: `Compile`, + deploy: `Deploy`, + import: `Import Solidity`, + load: `Load`, + new: `New`, + optimise: `Optimise`, + save: `Save` + }, + compiling: { + action: `Please compile the source code.`, + busy: `Compiling...` + }, + details: { + saved: `(saved {timestamp})` + }, + error: { + noContract: `No contract has been found.`, + params: `An error occurred with the following description` + }, + input: { + abi: `ABI Interface`, + code: `Bytecode`, + metadata: `Metadata`, + swarm: `Swarm Metadata Hash` + }, + title: { + contract: `Select a contract`, + loading: `Loading...`, + main: `Write a Contract`, + messages: `Compiler messages`, + new: `New Solidity Contract`, + parameters: `Parameters`, + saved: `saved @ {timestamp}`, + selectSolidity: `Select a Solidity version`, + solidity: `Loading Solidity {version}` + }, + type: { + humanErc20: `Implementation of the Human Token Contract`, + implementErc20: `Implementation of ERC20 Token Contract`, + multisig: `Implementation of a multisig Wallet`, + standardErc20: `Standard ERC20 Token Contract` + } +}; diff --git a/js/src/modals/PasswordManager/passwordManager.js b/js/src/modals/PasswordManager/passwordManager.js index 6436bc4cc..d40ac7cde 100644 --- a/js/src/modals/PasswordManager/passwordManager.js +++ b/js/src/modals/PasswordManager/passwordManager.js @@ -122,7 +122,7 @@ class PasswordManager extends Component { Date: Mon, 27 Mar 2017 11:43:09 +0200 Subject: [PATCH 24/72] JS package bumps (#5287) * Update to React 15.4.2 * Update deprecated UglifyJS version --- js/package.json | 8 ++++---- 1 file changed, 4 insertions(+), 4 deletions(-) diff --git a/js/package.json b/js/package.json index b65ef6661..7462bb4c4 100644 --- a/js/package.json +++ b/js/package.json @@ -184,11 +184,11 @@ "push.js": "0.0.11", "qrcode-npm": "0.0.3", "qs": "6.3.0", - "react": "15.4.1", + "react": "15.4.2", "react-ace": "4.1.0", - "react-addons-css-transition-group": "15.4.1", + "react-addons-css-transition-group": "15.4.2", "react-copy-to-clipboard": "4.2.3", - "react-dom": "15.4.1", + "react-dom": "15.4.2", "react-dropzone": "3.7.3", "react-element-to-jsx-string": "6.0.0", "react-event-listener": "0.4.1", @@ -211,7 +211,7 @@ "sw-toolbox": "^3.6.0", "u2f-api": "0.0.9", "u2f-api-polyfill": "0.4.3", - "uglify-js": "2.8.2", + "uglify-js": "2.8.16", "useragent.js": "0.5.6", "utf8": "2.1.2", "valid-url": "1.0.9", From 9e02271a683c8fe1d6001cfa974988bf41e3f9e2 Mon Sep 17 00:00:00 2001 From: GitLab Build Bot Date: Mon, 27 Mar 2017 10:08:02 +0000 Subject: [PATCH 25/72] [ci skip] js-precompiled 20170327-100522 --- Cargo.lock | 2 +- js/package.json | 2 +- 2 files changed, 2 insertions(+), 2 deletions(-) diff --git a/Cargo.lock b/Cargo.lock index badb522c4..c9d6a7b49 100644 --- a/Cargo.lock +++ b/Cargo.lock @@ -1750,7 +1750,7 @@ dependencies = [ [[package]] name = "parity-ui-precompiled" version = "1.4.0" -source = "git+https://github.com/ethcore/js-precompiled.git#8d7826d49c785726b17f14f150cab37e204fc84f" +source = "git+https://github.com/ethcore/js-precompiled.git#9760f897356d6c2a2ec7c43e60c7c1d0f87545dd" dependencies = [ "parity-dapps-glue 1.7.0 (registry+https://github.com/rust-lang/crates.io-index)", ] diff --git a/js/package.json b/js/package.json index 7462bb4c4..e47130639 100644 --- a/js/package.json +++ b/js/package.json @@ -1,6 +1,6 @@ { "name": "parity.js", - "version": "1.7.31", + "version": "1.7.32", "main": "release/index.js", "jsnext:main": "src/index.js", "author": "Parity Team ", From 7707f7557af4672c0bcbd0fe960d82b167cfa6b3 Mon Sep 17 00:00:00 2001 From: GitLab Build Bot Date: Mon, 27 Mar 2017 10:23:02 +0000 Subject: [PATCH 26/72] [ci skip] js-precompiled 20170327-102018 --- Cargo.lock | 2 +- js/package.json | 2 +- 2 files changed, 2 insertions(+), 2 deletions(-) diff --git a/Cargo.lock b/Cargo.lock index c9d6a7b49..8edf235c5 100644 --- a/Cargo.lock +++ b/Cargo.lock @@ -1750,7 +1750,7 @@ dependencies = [ [[package]] name = "parity-ui-precompiled" version = "1.4.0" -source = "git+https://github.com/ethcore/js-precompiled.git#9760f897356d6c2a2ec7c43e60c7c1d0f87545dd" +source = "git+https://github.com/ethcore/js-precompiled.git#92cf06c1e8c3b79014a9d6adcb1f5c17f0a88030" dependencies = [ "parity-dapps-glue 1.7.0 (registry+https://github.com/rust-lang/crates.io-index)", ] diff --git a/js/package.json b/js/package.json index e47130639..c0a6df879 100644 --- a/js/package.json +++ b/js/package.json @@ -1,6 +1,6 @@ { "name": "parity.js", - "version": "1.7.32", + "version": "1.7.33", "main": "release/index.js", "jsnext:main": "src/index.js", "author": "Parity Team ", From 986762a0bca014e4539915b264b26cf6db2709c2 Mon Sep 17 00:00:00 2001 From: Jaco Greeff Date: Mon, 27 Mar 2017 16:19:30 +0200 Subject: [PATCH 27/72] Scaffolding for zh translations, including first-round by @btceth (#5289) MIME-Version: 1.0 Content-Type: text/plain; charset=UTF-8 Content-Transfer-Encoding: 8bit * Initial import of #5023 * Language naming * Update 简体中文 --- js/src/i18n/constants.js | 2 +- js/src/i18n/languages.js | 3 +- js/src/i18n/store.js | 7 +- js/src/i18n/zh/createAccount.js | 156 ++++++++++++++++++++++++++++++++ js/src/i18n/zh/index.js | 23 +++++ js/src/i18n/zh/settings.js | 67 ++++++++++++++ 6 files changed, 254 insertions(+), 4 deletions(-) create mode 100644 js/src/i18n/zh/createAccount.js create mode 100644 js/src/i18n/zh/index.js create mode 100644 js/src/i18n/zh/settings.js diff --git a/js/src/i18n/constants.js b/js/src/i18n/constants.js index c7d47a0fd..6b4d7dafd 100644 --- a/js/src/i18n/constants.js +++ b/js/src/i18n/constants.js @@ -17,7 +17,7 @@ const DEFAULT_LOCALE = 'en'; const DEFAULT_LOCALES = process.env.NODE_ENV === 'production' ? ['en'] - : ['en', 'de', 'nl']; + : ['en', 'de', 'nl', 'zh']; const LS_STORE_KEY = '_parity::locale'; export { diff --git a/js/src/i18n/languages.js b/js/src/i18n/languages.js index 76bd136ab..b178fe4c2 100644 --- a/js/src/i18n/languages.js +++ b/js/src/i18n/languages.js @@ -17,5 +17,6 @@ export default { de: 'Deutsch', en: 'English', - nl: 'Nederlands' + nl: 'Nederlands', + zh: '简体中文' }; diff --git a/js/src/i18n/store.js b/js/src/i18n/store.js index 43e580dd8..e9666c8c0 100644 --- a/js/src/i18n/store.js +++ b/js/src/i18n/store.js @@ -20,6 +20,7 @@ import { addLocaleData } from 'react-intl'; import de from 'react-intl/locale-data/de'; import en from 'react-intl/locale-data/en'; import nl from 'react-intl/locale-data/nl'; +import zh from 'react-intl/locale-data/zh'; import store from 'store'; import { DEFAULT_LOCALE, DEFAULT_LOCALES, LS_STORE_KEY } from './constants'; @@ -27,6 +28,7 @@ import languages from './languages'; import deMessages from './de'; import enMessages from './en'; import nlMessages from './nl'; +import zhMessages from './zh'; let instance = null; @@ -34,10 +36,11 @@ const LANGUAGES = flatten({ languages }); const MESSAGES = { de: Object.assign(flatten(deMessages), LANGUAGES), en: Object.assign(flatten(enMessages), LANGUAGES), - nl: Object.assign(flatten(nlMessages), LANGUAGES) + nl: Object.assign(flatten(nlMessages), LANGUAGES), + zh: Object.assign(flatten(zhMessages), LANGUAGES) }; -addLocaleData([...de, ...en, ...nl]); +addLocaleData([...de, ...en, ...nl, ...zh]); export default class Store { @observable locale = DEFAULT_LOCALE; diff --git a/js/src/i18n/zh/createAccount.js b/js/src/i18n/zh/createAccount.js new file mode 100644 index 000000000..bfe3ed2bc --- /dev/null +++ b/js/src/i18n/zh/createAccount.js @@ -0,0 +1,156 @@ +// 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 . + +export default { + accountDetails: { + address: { + hint: `账户地址`, + label: `地址` + }, + name: { + hint: `描述账户的名字`, + label: `账户名` + }, + phrase: { + hint: `账户恢复词`, + label: `账户恢复词(安全保存,别人拥有它就可以完全控制你的账户)` + } + }, + accountDetailsGeth: { + imported: `你已经从Geth keystore导入了{number}个地址` + }, + button: { + back: `返回`, + cancel: `取消`, + close: `关闭`, + create: `创建`, + import: `导入`, + next: `下一步`, + print: `打印恢复词` + }, + creationType: { + fromGeth: { + label: `从Geth keystore导入账户` + }, + fromJSON: { + label: `从JSON文件导入账户` + }, + fromNew: { + label: `手动创建新账户` + }, + fromPhrase: { + label: `通过恢复词恢复账户` + }, + fromPresale: { + label: `从以太坊预售钱包导入账户` + }, + fromRaw: { + label: `导入私钥` + } + }, + newAccount: { + hint: { + hint: `(可选)帮助你记住密码的提示`, + label: `密码提示` + }, + name: { + hint: `描述账户的名字`, + label: `账户名` + }, + password: { + hint: `足够强的密码`, + label: `密码` + }, + password2: { + hint: `确认你的密码`, + label: `再次输入密码` + } + }, + newGeth: { + noKeys: `现在Geth keystore中没有可导入的私钥` + }, + newImport: { + file: { + hint: `要导入的钱包文件`, + label: `钱包文件` + }, + hint: { + hint: `(可选)帮助你记住密码的提示`, + label: `密码提示` + }, + name: { + hint: `描述账户的名字`, + label: `账户名` + }, + password: { + hint: `输入密码,解锁钱包`, + label: `密码` + } + }, + rawKey: { + hint: { + hint: `(可选)帮助你记住密码的提示`, + label: `密码提示` + }, + name: { + hint: `描述账户的名字`, + label: `账户名` + }, + password: { + hint: `足够强的密码`, + label: `密码` + }, + password2: { + hint: `确认密码`, + label: `再次输入密码` + }, + private: { + hint: `原始的十六进制编码私钥`, + label: `私钥` + } + }, + recoveryPhrase: { + hint: { + hint: `(可选)帮助你记住密码的提示`, + label: `密码提示` + }, + name: { + hint: `描述账户的名字`, + label: `账户名` + }, + password: { + hint: `足够强的密码`, + label: `密码` + }, + password2: { + hint: `确认密码`, + label: `再次输入密码` + }, + phrase: { + hint: `账户恢复词`, + label: `账户恢复词` + }, + windowsKey: { + label: `在Windows系统上由Parity 1.4.5以前的版本创建的私钥` + } + }, + title: { + accountInfo: `账户信息`, + createAccount: `创建账户`, + createType: `创建类型`, + importWallet: `导入钱包` + } +}; diff --git a/js/src/i18n/zh/index.js b/js/src/i18n/zh/index.js new file mode 100644 index 000000000..107c8491a --- /dev/null +++ b/js/src/i18n/zh/index.js @@ -0,0 +1,23 @@ +// 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 . + +import createAccount from './createAccount'; +import settings from './settings'; + +export default { + createAccount, + settings +}; diff --git a/js/src/i18n/zh/settings.js b/js/src/i18n/zh/settings.js new file mode 100644 index 000000000..48a656b93 --- /dev/null +++ b/js/src/i18n/zh/settings.js @@ -0,0 +1,67 @@ +// 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 . + +export default { + label: 'settings', + + background: { + label: 'background' + }, + + parity: { + label: 'parity' + }, + + proxy: { + label: 'proxy' + }, + + views: { + label: 'views', + + accounts: { + label: 'Accounts' + }, + + addresses: { + label: 'Addressbook' + }, + + apps: { + label: 'Applications' + }, + + contracts: { + label: 'Contracts' + }, + + home: { + label: 'Home' + }, + + status: { + label: 'Status' + }, + + signer: { + label: 'Signer' + }, + + settings: { + label: 'Settings' + } + } +}; From a4c5375a639b1f5ce32d62549d207d0cfe47c32d Mon Sep 17 00:00:00 2001 From: Jaco Greeff Date: Mon, 27 Mar 2017 16:27:25 +0200 Subject: [PATCH 28/72] Add lint:i18n to find missing & extra keys (#5290) * Add npm run lint:i18n (missing keys check) * Check extraneous keys --- js/package.json | 1 + js/scripts/lint-i18n.js | 53 +++++++++++++++++++++++++++++++++++++++++ js/src/i18n/store.js | 5 ++++ 3 files changed, 59 insertions(+) create mode 100644 js/scripts/lint-i18n.js diff --git a/js/package.json b/js/package.json index c0a6df879..799948443 100644 --- a/js/package.json +++ b/js/package.json @@ -53,6 +53,7 @@ "lint:cached": "npm run lint:css && npm run lint:js:cached", "lint:css": "stylelint ./src/**/*.css", "lint:fix": "npm run lint:js:fix", + "lint:i18n": "babel-node ./scripts/lint-i18n.js", "lint:js": "eslint --ignore-path .gitignore ./src/", "lint:js:cached": "eslint --cache --ignore-path .gitignore ./src/", "lint:js:fix": "eslint --fix --ignore-path .gitignore ./src/", diff --git a/js/scripts/lint-i18n.js b/js/scripts/lint-i18n.js new file mode 100644 index 000000000..d392353d0 --- /dev/null +++ b/js/scripts/lint-i18n.js @@ -0,0 +1,53 @@ +// 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 . + +import flatten from 'flat'; + +import * as defaults from '../src/i18n/_default'; +import { LANGUAGES, MESSAGES } from '../src/i18n/store'; + +const SKIP_LANG = ['en']; +const defaultKeys = Object.keys(flatten(Object.assign({}, defaults, LANGUAGES))); + +Object + .keys(MESSAGES) + .filter((lang) => !SKIP_LANG.includes(lang)) + .forEach((lang) => { + const messageKeys = Object.keys(MESSAGES[lang]); + let extra = 0; + let found = 0; + let missing = 0; + + console.log(`*** Checking translations for ${lang}`); + + defaultKeys.forEach((key) => { + if (messageKeys.includes(key)) { + found++; + } else { + missing++; + console.log(` Missing ${key}`); + } + }); + + messageKeys.forEach((key) => { + if (!defaultKeys.includes(key)) { + extra++; + console.log(` Extra ${key}`); + } + }); + + console.log(`Found ${found} keys, missing ${missing} keys, ${extra} extraneous keys\n`); + }); diff --git a/js/src/i18n/store.js b/js/src/i18n/store.js index e9666c8c0..fdceb6beb 100644 --- a/js/src/i18n/store.js +++ b/js/src/i18n/store.js @@ -73,3 +73,8 @@ export default class Store { return instance; } } + +export { + LANGUAGES, + MESSAGES +}; From 90746bd8c9dd629b2e338b1694fef720f5e265ca Mon Sep 17 00:00:00 2001 From: GitLab Build Bot Date: Mon, 27 Mar 2017 14:43:26 +0000 Subject: [PATCH 29/72] [ci skip] js-precompiled 20170327-144027 --- Cargo.lock | 2 +- js/package.json | 2 +- 2 files changed, 2 insertions(+), 2 deletions(-) diff --git a/Cargo.lock b/Cargo.lock index 8edf235c5..23b2ac440 100644 --- a/Cargo.lock +++ b/Cargo.lock @@ -1750,7 +1750,7 @@ dependencies = [ [[package]] name = "parity-ui-precompiled" version = "1.4.0" -source = "git+https://github.com/ethcore/js-precompiled.git#92cf06c1e8c3b79014a9d6adcb1f5c17f0a88030" +source = "git+https://github.com/ethcore/js-precompiled.git#6f18d6f6ddfff55e93f67e11f445eb98bc860219" dependencies = [ "parity-dapps-glue 1.7.0 (registry+https://github.com/rust-lang/crates.io-index)", ] diff --git a/js/package.json b/js/package.json index 799948443..550f22075 100644 --- a/js/package.json +++ b/js/package.json @@ -1,6 +1,6 @@ { "name": "parity.js", - "version": "1.7.33", + "version": "1.7.34", "main": "release/index.js", "jsnext:main": "src/index.js", "author": "Parity Team ", From c313857485c7c51d12751fbab809a226e5dab747 Mon Sep 17 00:00:00 2001 From: NikVolf Date: Mon, 27 Mar 2017 18:17:49 +0300 Subject: [PATCH 30/72] fix error handling --- ethcore/src/executive.rs | 36 +++++++++++++++++++++--------------- 1 file changed, 21 insertions(+), 15 deletions(-) diff --git a/ethcore/src/executive.rs b/ethcore/src/executive.rs index 4fdd9cbbd..4183a5005 100644 --- a/ethcore/src/executive.rs +++ b/ethcore/src/executive.rs @@ -276,25 +276,31 @@ impl<'a, B: 'a + StateBackend> Executive<'a, B> { let cost = builtin.cost(data); if cost <= params.gas { - builtin.execute(data, &mut output)?; - self.state.discard_checkpoint(); + if let Err(e) = builtin.execute(data, &mut output) { + self.state.revert_to_checkpoint(); + let evm_err: evm::evm::Error = e.into(); + tracer.trace_failed_call(trace_info, vec![], evm_err.clone().into()); + Err(evm_err) + } else { + self.state.discard_checkpoint(); - // trace only top level calls to builtins to avoid DDoS attacks - if self.depth == 0 { - let mut trace_output = tracer.prepare_trace_output(); - if let Some(mut out) = trace_output.as_mut() { - *out = output.to_owned(); + // trace only top level calls to builtins to avoid DDoS attacks + if self.depth == 0 { + let mut trace_output = tracer.prepare_trace_output(); + if let Some(mut out) = trace_output.as_mut() { + *out = output.to_owned(); + } + + tracer.trace_call( + trace_info, + cost, + trace_output, + vec![] + ); } - tracer.trace_call( - trace_info, - cost, - trace_output, - vec![] - ); + Ok(params.gas - cost) } - - Ok(params.gas - cost) } else { // just drain the whole gas self.state.revert_to_checkpoint(); From a12583f762e6314b137df9476f50fe78a9e24b87 Mon Sep 17 00:00:00 2001 From: Nicolas Gotchac Date: Mon, 27 Mar 2017 17:27:35 +0200 Subject: [PATCH 31/72] Fix the use of MobX in playground (#5294) * Register new playground component onMount * No need of observer * Fix tests --- js/src/playground/store.js | 15 ++------------- js/src/playground/store.spec.js | 7 ------- 2 files changed, 2 insertions(+), 20 deletions(-) diff --git a/js/src/playground/store.js b/js/src/playground/store.js index e627cdcc1..db0df38b4 100644 --- a/js/src/playground/store.js +++ b/js/src/playground/store.js @@ -14,12 +14,12 @@ // You should have received a copy of the GNU General Public License // along with Parity. If not, see . -import { action, observable } from 'mobx'; +import { action } from 'mobx'; let instance = null; export default class PlaygroundStore { - @observable components = []; + components = []; static get () { if (!instance) { @@ -35,17 +35,6 @@ export default class PlaygroundStore { @action add (component) { - const name = component.type.displayName || component.type.name; - const hasComponent = this.components.find((c) => { - const cName = c.type.displayName || c.type.name; - - return name && cName && cName === name; - }); - - if (hasComponent) { - return; - } - this.components.push(component); } } diff --git a/js/src/playground/store.spec.js b/js/src/playground/store.spec.js index 27db2411b..172d244fd 100644 --- a/js/src/playground/store.spec.js +++ b/js/src/playground/store.spec.js @@ -31,11 +31,4 @@ describe('playground/store', () => { PlaygroundStore.register(); expect(store.components.length).greaterThan(0); }); - - it('adds new Components only once', () => { - PlaygroundStore.register(); - PlaygroundStore.register(); - - expect(store.components.filter((c) => /QrCode/i.test(c.type.name)).length).equal(1); - }); }); From 62158601fb55be616ccf4644958d3839f0ee20c2 Mon Sep 17 00:00:00 2001 From: Robert Habermeier Date: Mon, 27 Mar 2017 17:30:19 +0200 Subject: [PATCH 32/72] node kind RPC (#5025) * node kind RPC * JS interface for parity_nodeKind --- js/src/api/format/output.js | 4 ++ js/src/api/format/output.spec.js | 10 +++- js/src/api/rpc/parity/parity.js | 8 ++- js/src/jsonrpc/interfaces/parity.js | 24 ++++++++ rpc/src/v1/impls/light/parity.rs | 9 +++ rpc/src/v1/impls/parity.rs | 10 ++++ rpc/src/v1/tests/mocked/parity.rs | 11 ++++ rpc/src/v1/traits/parity.rs | 4 ++ rpc/src/v1/types/mod.rs | 2 + rpc/src/v1/types/node_kind.rs | 92 +++++++++++++++++++++++++++++ 10 files changed, 172 insertions(+), 2 deletions(-) create mode 100644 rpc/src/v1/types/node_kind.rs diff --git a/js/src/api/format/output.js b/js/src/api/format/output.js index 952002b60..7348487e7 100644 --- a/js/src/api/format/output.js +++ b/js/src/api/format/output.js @@ -140,6 +140,10 @@ export function outHwAccountInfo (infos) { }, {}); } +export function outNodeKind (info) { + return info; +} + export function outNumber (number) { return new BigNumber(number || 0); } diff --git a/js/src/api/format/output.spec.js b/js/src/api/format/output.spec.js index c23751670..fabe30b32 100644 --- a/js/src/api/format/output.spec.js +++ b/js/src/api/format/output.spec.js @@ -16,7 +16,7 @@ import BigNumber from 'bignumber.js'; -import { outBlock, outAccountInfo, outAddress, outChainStatus, outDate, outHistogram, outHwAccountInfo, outNumber, outPeer, outPeers, outReceipt, outRecentDapps, outSyncing, outTransaction, outTrace, outVaultMeta } from './output'; +import { outBlock, outAccountInfo, outAddress, outChainStatus, outDate, outHistogram, outHwAccountInfo, outNodeKind, outNumber, outPeer, outPeers, outReceipt, outRecentDapps, outSyncing, outTransaction, outTrace, outVaultMeta } from './output'; import { isAddress, isBigNumber, isInstanceOf } from '../../../test/types'; describe('api/format/output', () => { @@ -173,6 +173,14 @@ describe('api/format/output', () => { }); }); + describe('outNodeKind', () => { + it('formats the input as received', () => { + const kind = { availability: 'personal', capability: 'full' }; + + expect(outNodeKind(kind)).to.deep.equal(kind); + }); + }); + describe('outNumber', () => { it('returns a BigNumber equalling the value', () => { const bn = outNumber('0x123456'); diff --git a/js/src/api/rpc/parity/parity.js b/js/src/api/rpc/parity/parity.js index dba6e5d30..26cfac505 100644 --- a/js/src/api/rpc/parity/parity.js +++ b/js/src/api/rpc/parity/parity.js @@ -15,7 +15,7 @@ // along with Parity. If not, see . import { inAddress, inAddresses, inData, inHex, inNumber16, inOptions, inBlockNumber } from '../../format/input'; -import { outAccountInfo, outAddress, outAddresses, outChainStatus, outHistogram, outHwAccountInfo, outNumber, outPeers, outRecentDapps, outTransaction, outVaultMeta } from '../../format/output'; +import { outAccountInfo, outAddress, outAddresses, outChainStatus, outHistogram, outHwAccountInfo, outNodeKind, outNumber, outPeers, outRecentDapps, outTransaction, outVaultMeta } from '../../format/output'; export default class Parity { constructor (transport) { @@ -290,6 +290,12 @@ export default class Parity { .execute('parity_chain'); } + nodeKind () { + return this._transport + .execute('parity_nodeKind') + .then(outNodeKind); + } + chain () { return this._transport .execute('parity_chain'); diff --git a/js/src/jsonrpc/interfaces/parity.js b/js/src/jsonrpc/interfaces/parity.js index 1e6df05de..7a883726a 100644 --- a/js/src/jsonrpc/interfaces/parity.js +++ b/js/src/jsonrpc/interfaces/parity.js @@ -419,6 +419,30 @@ export default { } }, + nodeKind: { + section: SECTION_NODE, + desc: 'Returns the node type availability and capability', + params: [], + returns: { + type: Object, + desc: 'Availability and Capability.', + details: { + availability: { + type: String, + desc: 'Availability, either `personal` or `public`.' + }, + capability: { + type: String, + desc: 'Capability, either `full` or `light`.' + } + } + }, + example: { + availability: 'personal', + capability: 'light' + } + }, + netChain: { section: SECTION_NET, desc: 'Returns the name of the connected chain.', diff --git a/rpc/src/v1/impls/light/parity.rs b/rpc/src/v1/impls/light/parity.rs index 545935417..46062b15a 100644 --- a/rpc/src/v1/impls/light/parity.rs +++ b/rpc/src/v1/impls/light/parity.rs @@ -333,4 +333,13 @@ impl Parity for ParityClient { block_gap: gap.map(|(x, y)| (x.into(), y.into())), }) } + + fn node_kind(&self) -> Result<::v1::types::NodeKind, Error> { + use ::v1::types::{NodeKind, Availability, Capability}; + + Ok(NodeKind { + availability: Availability::Personal, + capability: Capability::Light, + }) + } } diff --git a/rpc/src/v1/impls/parity.rs b/rpc/src/v1/impls/parity.rs index 2a7f85aa3..d6e16f267 100644 --- a/rpc/src/v1/impls/parity.rs +++ b/rpc/src/v1/impls/parity.rs @@ -372,4 +372,14 @@ impl Parity for ParityClient where block_gap: gap.map(|(x, y)| (x.into(), y.into())), }) } + + fn node_kind(&self) -> Result<::v1::types::NodeKind, Error> { + use ::v1::types::{NodeKind, Availability, Capability}; + + // TODO [maciej]: public availability flag. + Ok(NodeKind { + availability: Availability::Personal, + capability: Capability::Full, + }) + } } diff --git a/rpc/src/v1/tests/mocked/parity.rs b/rpc/src/v1/tests/mocked/parity.rs index 3af627037..e9b252af8 100644 --- a/rpc/src/v1/tests/mocked/parity.rs +++ b/rpc/src/v1/tests/mocked/parity.rs @@ -497,3 +497,14 @@ fn rpc_parity_chain_status() { assert_eq!(io.handle_request_sync(request), Some(response.to_owned())); } + +#[test] +fn rpc_parity_node_kind() { + let deps = Dependencies::new(); + let io = deps.default_client(); + + let request = r#"{"jsonrpc": "2.0", "method": "parity_nodeKind", "params":[], "id": 1}"#; + let response = r#"{"jsonrpc":"2.0","result":{"availability":"personal","capability":"full"},"id":1}"#; + + assert_eq!(io.handle_request_sync(request), Some(response.to_owned())); +} diff --git a/rpc/src/v1/traits/parity.rs b/rpc/src/v1/traits/parity.rs index 263adf6b2..8a15addae 100644 --- a/rpc/src/v1/traits/parity.rs +++ b/rpc/src/v1/traits/parity.rs @@ -194,5 +194,9 @@ build_rpc_trait! { /// Get the current chain status. #[rpc(name = "parity_chainStatus")] fn chain_status(&self) -> Result; + + /// Get node kind info. + #[rpc(name = "parity_nodeKind")] + fn node_kind(&self) -> Result<::v1::types::NodeKind, Error>; } } diff --git a/rpc/src/v1/types/mod.rs b/rpc/src/v1/types/mod.rs index a4bfcb41f..0ec60a74f 100644 --- a/rpc/src/v1/types/mod.rs +++ b/rpc/src/v1/types/mod.rs @@ -30,6 +30,7 @@ mod hash; mod histogram; mod index; mod log; +mod node_kind; mod provenance; mod receipt; mod rpc_settings; @@ -58,6 +59,7 @@ pub use self::hash::{H64, H160, H256, H512, H520, H2048}; pub use self::histogram::Histogram; pub use self::index::Index; pub use self::log::Log; +pub use self::node_kind::{NodeKind, Availability, Capability}; pub use self::provenance::{Origin, DappId}; pub use self::receipt::Receipt; pub use self::rpc_settings::RpcSettings; diff --git a/rpc/src/v1/types/node_kind.rs b/rpc/src/v1/types/node_kind.rs new file mode 100644 index 000000000..5c96fafc6 --- /dev/null +++ b/rpc/src/v1/types/node_kind.rs @@ -0,0 +1,92 @@ +// 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 . + +//! Description of the node. + +/// Describes the kind of node. This information can provide a hint to +/// applications about how to utilize the RPC. +#[derive(Debug, Clone, PartialEq, Serialize, Deserialize)] +pub struct NodeKind { + /// The capability of the node. + pub capability: Capability, + /// Who the node is available to. + pub availability: Availability, +} + +/// Who the node is available to. +#[derive(Debug, Clone, PartialEq, Serialize, Deserialize)] +pub enum Availability { + /// A personal node, not intended to be available to everyone. + #[serde(rename="personal")] + Personal, + /// A public, open node. + #[serde(rename="public")] + Public, +} + +/// The capability of the node. +#[derive(Debug, Clone, PartialEq, Serialize, Deserialize)] +pub enum Capability { + /// A full node stores the full state and fully enacts incoming blocks. + #[serde(rename="full")] + Full, + /// A light node does a minimal header sync and fetches data as needed + /// from the network. + #[serde(rename="light")] + Light, +} + +#[cfg(test)] +mod tests { + use super::{NodeKind, Availability, Capability}; + use serde_json; + + #[test] + fn availability() { + let personal = r#""personal""#; + let public = r#""public""#; + + assert_eq!(serde_json::to_string(&Availability::Personal).unwrap(), personal); + assert_eq!(serde_json::to_string(&Availability::Public).unwrap(), public); + + assert_eq!(serde_json::from_str::(personal).unwrap(), Availability::Personal); + assert_eq!(serde_json::from_str::(public).unwrap(), Availability::Public); + } + + #[test] + fn capability() { + let light = r#""light""#; + let full = r#""full""#; + + assert_eq!(serde_json::to_string(&Capability::Light).unwrap(), light); + assert_eq!(serde_json::to_string(&Capability::Full).unwrap(), full); + + assert_eq!(serde_json::from_str::(light).unwrap(), Capability::Light); + assert_eq!(serde_json::from_str::(full).unwrap(), Capability::Full); + } + + #[test] + fn node_kind() { + let kind = NodeKind { + capability: Capability::Full, + availability: Availability::Public, + }; + let s = r#"{"capability":"full","availability":"public"}"#; + + assert_eq!(serde_json::to_string(&kind).unwrap(), s); + assert_eq!(serde_json::from_str::(s).unwrap(), kind); + } +} From f5bce0cd9ec9cd502194289a9cc7325eea792660 Mon Sep 17 00:00:00 2001 From: GitLab Build Bot Date: Mon, 27 Mar 2017 15:53:33 +0000 Subject: [PATCH 33/72] [ci skip] js-precompiled 20170327-155051 --- Cargo.lock | 2 +- js/package.json | 2 +- 2 files changed, 2 insertions(+), 2 deletions(-) diff --git a/Cargo.lock b/Cargo.lock index 9a241535c..d749f7878 100644 --- a/Cargo.lock +++ b/Cargo.lock @@ -1751,7 +1751,7 @@ dependencies = [ [[package]] name = "parity-ui-precompiled" version = "1.4.0" -source = "git+https://github.com/ethcore/js-precompiled.git#6f18d6f6ddfff55e93f67e11f445eb98bc860219" +source = "git+https://github.com/ethcore/js-precompiled.git#09b3034628b03814a6e2d672f50236a0b02627ef" dependencies = [ "parity-dapps-glue 1.7.0 (registry+https://github.com/rust-lang/crates.io-index)", ] diff --git a/js/package.json b/js/package.json index 550f22075..7b1faef90 100644 --- a/js/package.json +++ b/js/package.json @@ -1,6 +1,6 @@ { "name": "parity.js", - "version": "1.7.34", + "version": "1.7.35", "main": "release/index.js", "jsnext:main": "src/index.js", "author": "Parity Team ", From fb88e5d652b67522027cb121a4e846dfc7da92bb Mon Sep 17 00:00:00 2001 From: Nicolas Gotchac Date: Mon, 27 Mar 2017 17:56:08 +0200 Subject: [PATCH 34/72] Fix booleans in Typedinput (#5295) * Register new playground component onMount * No need of observer * getValue returns falsy values * Fix tests --- js/src/ui/Form/TypedInput/typedInput.js | 2 +- 1 file changed, 1 insertion(+), 1 deletion(-) diff --git a/js/src/ui/Form/TypedInput/typedInput.js b/js/src/ui/Form/TypedInput/typedInput.js index a6a84ad21..c3462a020 100644 --- a/js/src/ui/Form/TypedInput/typedInput.js +++ b/js/src/ui/Form/TypedInput/typedInput.js @@ -469,7 +469,7 @@ export default class TypedInput extends Component { * { value: Object, type: String } */ getValue (value = this.props.value) { - return value && value.value + return value && value.value !== undefined ? value.value : value; } From 6d5bfcfe444e1865072f2c8e86c33b99635cc087 Mon Sep 17 00:00:00 2001 From: GitLab Build Bot Date: Mon, 27 Mar 2017 16:17:42 +0000 Subject: [PATCH 35/72] [ci skip] js-precompiled 20170327-161452 --- Cargo.lock | 2 +- js/package.json | 2 +- 2 files changed, 2 insertions(+), 2 deletions(-) diff --git a/Cargo.lock b/Cargo.lock index d749f7878..1ae1159a9 100644 --- a/Cargo.lock +++ b/Cargo.lock @@ -1751,7 +1751,7 @@ dependencies = [ [[package]] name = "parity-ui-precompiled" version = "1.4.0" -source = "git+https://github.com/ethcore/js-precompiled.git#09b3034628b03814a6e2d672f50236a0b02627ef" +source = "git+https://github.com/ethcore/js-precompiled.git#38a485b837208427cbb9ee0b3db45f8ab2313884" dependencies = [ "parity-dapps-glue 1.7.0 (registry+https://github.com/rust-lang/crates.io-index)", ] diff --git a/js/package.json b/js/package.json index 7b1faef90..2d8d2de2b 100644 --- a/js/package.json +++ b/js/package.json @@ -1,6 +1,6 @@ { "name": "parity.js", - "version": "1.7.35", + "version": "1.7.36", "main": "release/index.js", "jsnext:main": "src/index.js", "author": "Parity Team ", From 1db72ad6e23259597a746143fde8743a00c57eee Mon Sep 17 00:00:00 2001 From: Jaco Greeff Date: Mon, 27 Mar 2017 21:46:39 +0200 Subject: [PATCH 36/72] Copy all existing i18n strings into zh (as-is translation aid) (#5305) * Copy available strings into zh * Update after lint * Force rebuild (upstream package update) --- js/scripts/test.js | 2 +- js/src/i18n/zh/account.js | 39 +++++++ js/src/i18n/zh/accounts.js | 34 +++++++ js/src/i18n/zh/addAddress.js | 38 +++++++ js/src/i18n/zh/addContract.js | 60 +++++++++++ js/src/i18n/zh/address.js | 28 +++++ js/src/i18n/zh/addressSelect.js | 26 +++++ js/src/i18n/zh/addresses.js | 25 +++++ js/src/i18n/zh/application.js | 30 ++++++ js/src/i18n/zh/connection.js | 26 +++++ js/src/i18n/zh/contract.js | 41 ++++++++ js/src/i18n/zh/contracts.js | 28 +++++ js/src/i18n/zh/createAccount.js | 11 +- js/src/i18n/zh/createWallet.js | 106 +++++++++++++++++++ js/src/i18n/zh/dapp.js | 20 ++++ js/src/i18n/zh/dapps.js | 45 +++++++++ js/src/i18n/zh/deleteAccount.js | 24 +++++ js/src/i18n/zh/deployContract.js | 90 +++++++++++++++++ js/src/i18n/zh/details_windows.js | 17 ++++ js/src/i18n/zh/editMeta.js | 34 +++++++ js/src/i18n/zh/errors.js | 24 +++++ js/src/i18n/zh/executeContract.js | 58 +++++++++++ js/src/i18n/zh/extension.js | 20 ++++ js/src/i18n/zh/faucet.js | 28 +++++ js/src/i18n/zh/firstRun.js | 49 +++++++++ js/src/i18n/zh/home.js | 38 +++++++ js/src/i18n/zh/index.js | 84 ++++++++++++++- js/src/i18n/zh/loadContract.js | 43 ++++++++ js/src/i18n/zh/parityBar.js | 29 ++++++ js/src/i18n/zh/passwordChange.js | 54 ++++++++++ js/src/i18n/zh/saveContract.js | 27 +++++ js/src/i18n/zh/settings.js | 98 ++++++++++++------ js/src/i18n/zh/shapeshift.js | 66 ++++++++++++ js/src/i18n/zh/signer.js | 103 +++++++++++++++++++ js/src/i18n/zh/status.js | 66 ++++++++++++ js/src/i18n/zh/tabBar.js | 21 ++++ js/src/i18n/zh/transfer.js | 61 +++++++++++ js/src/i18n/zh/txEditor.js | 39 +++++++ js/src/i18n/zh/ui.js | 163 ++++++++++++++++++++++++++++++ js/src/i18n/zh/upgradeParity.js | 47 +++++++++ js/src/i18n/zh/vaults.js | 108 ++++++++++++++++++++ js/src/i18n/zh/verification.js | 85 ++++++++++++++++ js/src/i18n/zh/wallet.js | 45 +++++++++ js/src/i18n/zh/walletSettings.js | 69 +++++++++++++ js/src/i18n/zh/web.js | 19 ++++ js/src/i18n/zh/writeContract.js | 62 ++++++++++++ 46 files changed, 2195 insertions(+), 35 deletions(-) create mode 100644 js/src/i18n/zh/account.js create mode 100644 js/src/i18n/zh/accounts.js create mode 100644 js/src/i18n/zh/addAddress.js create mode 100644 js/src/i18n/zh/addContract.js create mode 100644 js/src/i18n/zh/address.js create mode 100644 js/src/i18n/zh/addressSelect.js create mode 100644 js/src/i18n/zh/addresses.js create mode 100644 js/src/i18n/zh/application.js create mode 100644 js/src/i18n/zh/connection.js create mode 100644 js/src/i18n/zh/contract.js create mode 100644 js/src/i18n/zh/contracts.js create mode 100644 js/src/i18n/zh/createWallet.js create mode 100644 js/src/i18n/zh/dapp.js create mode 100644 js/src/i18n/zh/dapps.js create mode 100644 js/src/i18n/zh/deleteAccount.js create mode 100644 js/src/i18n/zh/deployContract.js create mode 100644 js/src/i18n/zh/details_windows.js create mode 100644 js/src/i18n/zh/editMeta.js create mode 100644 js/src/i18n/zh/errors.js create mode 100644 js/src/i18n/zh/executeContract.js create mode 100644 js/src/i18n/zh/extension.js create mode 100644 js/src/i18n/zh/faucet.js create mode 100644 js/src/i18n/zh/firstRun.js create mode 100644 js/src/i18n/zh/home.js create mode 100644 js/src/i18n/zh/loadContract.js create mode 100644 js/src/i18n/zh/parityBar.js create mode 100644 js/src/i18n/zh/passwordChange.js create mode 100644 js/src/i18n/zh/saveContract.js create mode 100644 js/src/i18n/zh/shapeshift.js create mode 100644 js/src/i18n/zh/signer.js create mode 100644 js/src/i18n/zh/status.js create mode 100644 js/src/i18n/zh/tabBar.js create mode 100644 js/src/i18n/zh/transfer.js create mode 100644 js/src/i18n/zh/txEditor.js create mode 100644 js/src/i18n/zh/ui.js create mode 100644 js/src/i18n/zh/upgradeParity.js create mode 100644 js/src/i18n/zh/vaults.js create mode 100644 js/src/i18n/zh/verification.js create mode 100644 js/src/i18n/zh/wallet.js create mode 100644 js/src/i18n/zh/walletSettings.js create mode 100644 js/src/i18n/zh/web.js create mode 100644 js/src/i18n/zh/writeContract.js diff --git a/js/scripts/test.js b/js/scripts/test.js index cadf88a52..f5bfb0835 100644 --- a/js/scripts/test.js +++ b/js/scripts/test.js @@ -1,2 +1,2 @@ -// test script 8 +// test script 9 // trigger rebuild on master 15 Mar 2017, 11:19 diff --git a/js/src/i18n/zh/account.js b/js/src/i18n/zh/account.js new file mode 100644 index 000000000..7c9d25520 --- /dev/null +++ b/js/src/i18n/zh/account.js @@ -0,0 +1,39 @@ +// 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 . + +export default { + button: { + delete: `delete`, + edit: `edit`, + faucet: `Kovan ETH`, + password: `password`, + shapeshift: `shapeshift`, + transfer: `transfer`, + verify: `verify` + }, + hardware: { + confirmDelete: `Are you sure you want to remove the following hardware address from your account list?` + }, + header: { + outgoingTransactions: `{count} outgoing transactions`, + uuid: `uuid: {uuid}` + }, + title: `Account Management`, + transactions: { + poweredBy: `Transaction list powered by {etherscan}`, + title: `transactions` + } +}; diff --git a/js/src/i18n/zh/accounts.js b/js/src/i18n/zh/accounts.js new file mode 100644 index 000000000..2db3d5fd9 --- /dev/null +++ b/js/src/i18n/zh/accounts.js @@ -0,0 +1,34 @@ +// 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 . + +export default { + button: { + newAccount: `account`, + newWallet: `wallet`, + vaults: `vaults` + }, + summary: { + minedBlock: `Mined at block #{blockNumber}` + }, + title: `Accounts Overview`, + tooltip: { + actions: `actions relating to the current view are available on the toolbar for quick access, be it for performing actions or creating a new item`, + overview: `your accounts are visible for easy access, allowing you to edit the meta information, make transfers, view transactions and fund the account` + }, + tooltips: { + owner: `{name} (owner)` + } +}; diff --git a/js/src/i18n/zh/addAddress.js b/js/src/i18n/zh/addAddress.js new file mode 100644 index 000000000..59ae71518 --- /dev/null +++ b/js/src/i18n/zh/addAddress.js @@ -0,0 +1,38 @@ +// 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 . + +export default { + button: { + add: `Save Address`, + close: `Cancel` + }, + header: `To add a new entry to your addressbook, you need the network address of the account and can supply an optional description. Once added it will reflect in your address book.`, + input: { + address: { + hint: `the network address for the entry`, + label: `network address` + }, + description: { + hint: `an expanded description for the entry`, + label: `(optional) address description` + }, + name: { + hint: `a descriptive name for the entry`, + label: `address name` + } + }, + label: `add saved address` +}; diff --git a/js/src/i18n/zh/addContract.js b/js/src/i18n/zh/addContract.js new file mode 100644 index 000000000..edbecf118 --- /dev/null +++ b/js/src/i18n/zh/addContract.js @@ -0,0 +1,60 @@ +// 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 . + +export default { + abi: { + hint: `the abi for the contract`, + label: `contract abi` + }, + abiType: { + custom: { + description: `Contract created from custom ABI`, + label: `Custom Contract` + }, + multisigWallet: { + description: `Ethereum Multisig contract {link}`, + label: `Multisig Wallet`, + link: `see contract code` + }, + token: { + description: `A standard {erc20} token`, + erc20: `ERC 20`, + label: `Token` + } + }, + address: { + hint: `the network address for the contract`, + label: `network address` + }, + button: { + add: `Add Contract`, + cancel: `Cancel`, + next: `Next`, + prev: `Back` + }, + description: { + hint: `an expanded description for the entry`, + label: `(optional) contract description` + }, + name: { + hint: `a descriptive name for the contract`, + label: `contract name` + }, + title: { + details: `enter contract details`, + type: `choose a contract type` + } +}; diff --git a/js/src/i18n/zh/address.js b/js/src/i18n/zh/address.js new file mode 100644 index 000000000..ec06d4237 --- /dev/null +++ b/js/src/i18n/zh/address.js @@ -0,0 +1,28 @@ +// 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 . + +export default { + buttons: { + edit: `edit`, + forget: `forget`, + save: `save` + }, + delete: { + confirmInfo: `Are you sure you want to remove the following address from your addressbook?`, + title: `confirm removal` + }, + title: `Address Information` +}; diff --git a/js/src/i18n/zh/addressSelect.js b/js/src/i18n/zh/addressSelect.js new file mode 100644 index 000000000..108ac80f5 --- /dev/null +++ b/js/src/i18n/zh/addressSelect.js @@ -0,0 +1,26 @@ +// 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 . + +export default { + fromEmail: `Verified using email {email}`, + fromRegistry: `{name} (from registry)`, + labels: { + accounts: `accounts`, + contacts: `contacts`, + contracts: `contracts` + }, + noAccount: `No account matches this query...` +}; diff --git a/js/src/i18n/zh/addresses.js b/js/src/i18n/zh/addresses.js new file mode 100644 index 000000000..00bb28272 --- /dev/null +++ b/js/src/i18n/zh/addresses.js @@ -0,0 +1,25 @@ +// 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 . + +export default { + buttons: { + add: `address` + }, + errors: { + invalidFile: `The provided file is invalid...` + }, + title: `Saved Addresses` +}; diff --git a/js/src/i18n/zh/application.js b/js/src/i18n/zh/application.js new file mode 100644 index 000000000..4469d83b2 --- /dev/null +++ b/js/src/i18n/zh/application.js @@ -0,0 +1,30 @@ +// 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 . + +export default { + frame: { + error: `ERROR: This application cannot and should not be loaded in an embedded iFrame` + }, + status: { + consensus: { + capable: `Capable`, + capableUntil: `Capable until #{blockNumber}`, + incapableSince: `Incapable since #{blockNumber}`, + unknown: `Unknown capability` + }, + upgrade: `Upgrade` + } +}; diff --git a/js/src/i18n/zh/connection.js b/js/src/i18n/zh/connection.js new file mode 100644 index 000000000..e51943178 --- /dev/null +++ b/js/src/i18n/zh/connection.js @@ -0,0 +1,26 @@ +// 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 . + +export default { + connectingAPI: `Connecting to the Parity Secure API.`, + connectingNode: `Connecting to the Parity Node. If this informational message persists, please ensure that your Parity node is running and reachable on the network.`, + invalidToken: `invalid signer token`, + noConnection: `Unable to make a connection to the Parity Secure API. To update your secure token or to generate a new one, run {newToken} and paste the generated token into the space below.`, + token: { + hint: `a generated token from Parity`, + label: `secure token` + } +}; diff --git a/js/src/i18n/zh/contract.js b/js/src/i18n/zh/contract.js new file mode 100644 index 000000000..bf7f00298 --- /dev/null +++ b/js/src/i18n/zh/contract.js @@ -0,0 +1,41 @@ +// 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 . + +export default { + buttons: { + close: `Close`, + details: `details`, + edit: `edit`, + execute: `execute`, + forget: `forget` + }, + details: { + title: `contract details` + }, + events: { + eventPending: `pending`, + noEvents: `No events has been sent from this contract.`, + title: `events` + }, + minedBlock: `Mined at block #{blockNumber}`, + queries: { + buttons: { + query: `Query` + }, + title: `queries` + }, + title: `Contract Information` +}; diff --git a/js/src/i18n/zh/contracts.js b/js/src/i18n/zh/contracts.js new file mode 100644 index 000000000..4ff840759 --- /dev/null +++ b/js/src/i18n/zh/contracts.js @@ -0,0 +1,28 @@ +// 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 . + +export default { + buttons: { + deploy: `deploy`, + develop: `develop`, + watch: `watch` + }, + sortOrder: { + date: `date`, + minedBlock: `mined block` + }, + title: `Contracts` +}; diff --git a/js/src/i18n/zh/createAccount.js b/js/src/i18n/zh/createAccount.js index bfe3ed2bc..5bae9e275 100644 --- a/js/src/i18n/zh/createAccount.js +++ b/js/src/i18n/zh/createAccount.js @@ -37,29 +37,37 @@ export default { cancel: `取消`, close: `关闭`, create: `创建`, + done: `Done`, import: `导入`, next: `下一步`, print: `打印恢复词` }, creationType: { fromGeth: { + description: `Import accounts from the Geth keystore with the original password`, label: `从Geth keystore导入账户` }, fromJSON: { + description: `Import an industry-standard JSON keyfile with the original password`, label: `从JSON文件导入账户` }, fromNew: { + description: `Selecting your identity icon and specifying the password`, label: `手动创建新账户` }, fromPhrase: { + description: `Recover using a previously stored recovery phrase and new password`, label: `通过恢复词恢复账户` }, fromPresale: { + description: `Import an Ethereum presale wallet file with the original password`, label: `从以太坊预售钱包导入账户` }, fromRaw: { + description: `Enter a previously created raw private key with a new password`, label: `导入私钥` - } + }, + info: `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.` }, newAccount: { hint: { @@ -80,6 +88,7 @@ export default { } }, newGeth: { + available: `There are currently {count} importable keys available from the Geth keystore which are not already available on your Parity instance. Select the accounts you wish to import and move to the next step to complete the import.`, noKeys: `现在Geth keystore中没有可导入的私钥` }, newImport: { diff --git a/js/src/i18n/zh/createWallet.js b/js/src/i18n/zh/createWallet.js new file mode 100644 index 000000000..eeb9e9a98 --- /dev/null +++ b/js/src/i18n/zh/createWallet.js @@ -0,0 +1,106 @@ +// 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 . + +export default { + button: { + add: `Add`, + cancel: `Cancel`, + close: `Close`, + create: `Create`, + done: `Done`, + next: `Next`, + sending: `Sending...` + }, + deployment: { + message: `The deployment is currently in progress` + }, + details: { + address: { + hint: `the wallet contract address`, + label: `wallet address` + }, + dayLimitMulti: { + hint: `amount of ETH spendable without confirmations`, + label: `wallet day limit` + }, + description: { + hint: `the local description for this wallet`, + label: `wallet description (optional)` + }, + descriptionMulti: { + hint: `the local description for this wallet`, + label: `wallet description (optional)` + }, + name: { + hint: `the local name for this wallet`, + label: `wallet name` + }, + nameMulti: { + hint: `the local name for this wallet`, + label: `wallet name` + }, + ownerMulti: { + hint: `the owner account for this contract`, + label: `from account (contract owner)` + }, + ownersMulti: { + label: `other wallet owners` + }, + ownersMultiReq: { + hint: `number of required owners to accept a transaction`, + label: `required owners` + } + }, + info: { + added: `added`, + copyAddress: `copy address to clipboard`, + created: `{name} has been {deployedOrAdded} at`, + dayLimit: `The daily limit is set to {dayLimit} ETH.`, + deployed: `deployed`, + numOwners: `{numOwners} owners are required to confirm a transaction.`, + owners: `The following are wallet owners` + }, + rejected: { + message: `The deployment has been rejected`, + state: `The wallet will not be created. You can safely close this window.`, + title: `rejected` + }, + states: { + completed: `The contract deployment has been completed`, + confirmationNeeded: `The contract deployment needs confirmations from other owners of the Wallet`, + preparing: `Preparing transaction for network transmission`, + validatingCode: `Validating the deployed contract code`, + waitingConfirm: `Waiting for confirmation of the transaction in the Parity Secure Signer`, + waitingReceipt: `Waiting for the contract deployment transaction receipt` + }, + steps: { + deployment: `wallet deployment`, + details: `wallet details`, + info: `wallet informaton`, + type: `wallet type` + }, + type: { + multisig: { + description: `Create/Deploy a {link} Wallet`, + label: `Multi-Sig wallet`, + link: `standard multi-signature` + }, + watch: { + description: `Add an existing wallet to your accounts`, + label: `Watch a wallet` + } + } +}; diff --git a/js/src/i18n/zh/dapp.js b/js/src/i18n/zh/dapp.js new file mode 100644 index 000000000..29dd2fd16 --- /dev/null +++ b/js/src/i18n/zh/dapp.js @@ -0,0 +1,20 @@ +// 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 . + +export default { + loading: `Loading`, + unavailable: `The dapp cannot be reached` +}; diff --git a/js/src/i18n/zh/dapps.js b/js/src/i18n/zh/dapps.js new file mode 100644 index 000000000..9ed3415d1 --- /dev/null +++ b/js/src/i18n/zh/dapps.js @@ -0,0 +1,45 @@ +// 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 . + +export default { + add: { + builtin: { + desc: `Experimental applications developed by the Parity team to show off dapp capabilities, integration, experimental features and to control certain network-wide client behaviour.`, + label: `Applications bundled with Parity` + }, + label: `visible applications`, + local: { + desc: `All applications installed locally on the machine by the user for access by the Parity client.`, + label: `Applications locally available` + }, + network: { + desc: `These applications are not affiliated with Parity nor are they published by Parity. Each remain under the control of their respective authors. Please ensure that you understand the goals for each application before interacting.`, + label: `Applications on the global network` + } + }, + button: { + edit: `edit`, + permissions: `permissions` + }, + external: { + accept: `I understand that these applications are not affiliated with Parity`, + warning: `Applications made available on the network by 3rd-party authors are not affiliated with Parity nor are they published by Parity. Each remain under the control of their respective authors. Please ensure that you understand the goals for each before interacting.` + }, + label: `Decentralized Applications`, + permissions: { + label: `visible dapp accounts` + } +}; diff --git a/js/src/i18n/zh/deleteAccount.js b/js/src/i18n/zh/deleteAccount.js new file mode 100644 index 000000000..4818a785a --- /dev/null +++ b/js/src/i18n/zh/deleteAccount.js @@ -0,0 +1,24 @@ +// 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 . + +export default { + password: { + hint: `provide the account password to confirm the account deletion`, + label: `account password` + }, + question: `Are you sure you want to permanently delete the following account?`, + title: `confirm removal` +}; diff --git a/js/src/i18n/zh/deployContract.js b/js/src/i18n/zh/deployContract.js new file mode 100644 index 000000000..0b5a05503 --- /dev/null +++ b/js/src/i18n/zh/deployContract.js @@ -0,0 +1,90 @@ +// 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 . + +export default { + busy: { + title: `The deployment is currently in progress` + }, + button: { + cancel: `Cancel`, + close: `Close`, + create: `Create`, + done: `Done`, + next: `Next` + }, + completed: { + description: `Your contract has been deployed at` + }, + details: { + abi: { + hint: `the abi of the contract to deploy or solc combined-output`, + label: `abi / solc combined-output` + }, + address: { + hint: `the owner account for this contract`, + label: `from account (contract owner)` + }, + advanced: { + label: `advanced sending options` + }, + amount: { + hint: `the amount to transfer to the contract`, + label: `amount to transfer (in {tag})` + }, + code: { + hint: `the compiled code of the contract to deploy`, + label: `code` + }, + contract: { + label: `select a contract` + }, + description: { + hint: `a description for the contract`, + label: `contract description (optional)` + }, + name: { + hint: `a name for the deployed contract`, + label: `contract name` + } + }, + owner: { + noneSelected: `a valid account as the contract owner needs to be selected` + }, + parameters: { + choose: `Choose the contract parameters` + }, + rejected: { + description: `You can safely close this window, the contract deployment will not occur.`, + title: `The deployment has been rejected` + }, + state: { + completed: `The contract deployment has been completed`, + confirmationNeeded: `The operation needs confirmations from the other owners of the contract`, + preparing: `Preparing transaction for network transmission`, + validatingCode: `Validating the deployed contract code`, + waitReceipt: `Waiting for the contract deployment transaction receipt`, + waitSigner: `Waiting for confirmation of the transaction in the Parity Secure Signer` + }, + title: { + completed: `completed`, + deployment: `deployment`, + details: `contract details`, + extras: `extra information`, + failed: `deployment failed`, + parameters: `contract parameters`, + rejected: `rejected` + } +}; diff --git a/js/src/i18n/zh/details_windows.js b/js/src/i18n/zh/details_windows.js new file mode 100644 index 000000000..fcc570066 --- /dev/null +++ b/js/src/i18n/zh/details_windows.js @@ -0,0 +1,17 @@ +// 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 . + +export default `Windows`; diff --git a/js/src/i18n/zh/editMeta.js b/js/src/i18n/zh/editMeta.js new file mode 100644 index 000000000..b5b521341 --- /dev/null +++ b/js/src/i18n/zh/editMeta.js @@ -0,0 +1,34 @@ +// 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 . + +export default { + description: { + hint: `description for this address`, + label: `address description` + }, + name: { + label: `name` + }, + passwordHint: { + hint: `a hint to allow password recovery`, + label: `(optional) password hint` + }, + tags: { + hint: `press to add a tag`, + label: `(optional) tags` + }, + title: `edit metadata` +}; diff --git a/js/src/i18n/zh/errors.js b/js/src/i18n/zh/errors.js new file mode 100644 index 000000000..76fed24cd --- /dev/null +++ b/js/src/i18n/zh/errors.js @@ -0,0 +1,24 @@ +// 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 . + +export default { + duplicateName: `the name already exists`, + invalidKey: `the raw key needs to be hex, 64 characters in length and contain the prefix "0x"`, + noFile: `select a valid wallet file to import`, + noKey: `you need to provide the raw private key`, + noMatchPassword: `the supplied passwords does not match`, + noName: `you need to specify a valid name` +}; diff --git a/js/src/i18n/zh/executeContract.js b/js/src/i18n/zh/executeContract.js new file mode 100644 index 000000000..011264d3f --- /dev/null +++ b/js/src/i18n/zh/executeContract.js @@ -0,0 +1,58 @@ +// 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 . + +export default { + busy: { + posted: `Your transaction has been posted to the network`, + title: `The function execution is in progress`, + waitAuth: `Waiting for authorization in the Parity Signer` + }, + button: { + cancel: `cancel`, + done: `done`, + next: `next`, + post: `post transaction`, + prev: `prev` + }, + details: { + address: { + hint: `from account`, + label: `the account to transact with` + }, + advancedCheck: { + label: `advanced sending options` + }, + amount: { + hint: `the amount to send to with the transaction`, + label: `transaction value (in ETH)` + }, + function: { + hint: `the function to call on the contract`, + label: `function to execute` + } + }, + rejected: { + state: `You can safely close this window, the function execution will not occur.`, + title: `The execution has been rejected` + }, + steps: { + advanced: `advanced options`, + complete: `complete`, + rejected: `rejected`, + sending: `sending`, + transfer: `function details` + } +}; diff --git a/js/src/i18n/zh/extension.js b/js/src/i18n/zh/extension.js new file mode 100644 index 000000000..88ba33674 --- /dev/null +++ b/js/src/i18n/zh/extension.js @@ -0,0 +1,20 @@ +// 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 . + +export default { + install: `Install the extension now`, + intro: `Parity now has an extension available for Chrome that allows safe browsing of Ethereum-enabled distributed applications. It is highly recommended that you install this extension to further enhance your Parity experience.` +}; diff --git a/js/src/i18n/zh/faucet.js b/js/src/i18n/zh/faucet.js new file mode 100644 index 000000000..11aacef9c --- /dev/null +++ b/js/src/i18n/zh/faucet.js @@ -0,0 +1,28 @@ +// 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 . + +export default { + buttons: { + close: `close`, + done: `close`, + request: `request` + }, + summary: { + done: `Your Kovan ETH has been requested from the faucet which responded with -`, + info: `To request a deposit of Kovan ETH to this address, you need to ensure that the address is sms-verified on the mainnet. Once executed the faucet will deposit Kovan ETH into the current account.` + }, + title: `Kovan ETH Faucet` +}; diff --git a/js/src/i18n/zh/firstRun.js b/js/src/i18n/zh/firstRun.js new file mode 100644 index 000000000..5a3e04a17 --- /dev/null +++ b/js/src/i18n/zh/firstRun.js @@ -0,0 +1,49 @@ +// 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 . + +export default { + button: { + close: `Close`, + create: `Create`, + next: `Next`, + print: `Print Phrase`, + skip: `Skip` + }, + completed: { + congrats: `Congratulations! Your node setup has been completed successfully and you are ready to use the application.`, + next: `Next you will receive a walk-through of the available functions and the general application interface to get you up and running in record time.` + }, + title: { + completed: `completed`, + newAccount: `new account`, + recovery: `recovery`, + terms: `terms`, + welcome: `welcome` + }, + tnc: { + accept: `I accept these terms and conditions` + }, + welcome: { + description: `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 -`, + greeting: `Welcome to Parity, the fastest and simplest way to run your node.`, + next: `Click Next to continue your journey.`, + step: { + account: `Created your first Parity account`, + privacy: `Understood our privacy policy & terms of operation`, + recovery: `Have the ability to recover your account` + } + } +}; diff --git a/js/src/i18n/zh/home.js b/js/src/i18n/zh/home.js new file mode 100644 index 000000000..0b5e68c04 --- /dev/null +++ b/js/src/i18n/zh/home.js @@ -0,0 +1,38 @@ +// 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 . + +export default { + account: { + visited: `accessed {when}` + }, + accounts: { + none: `No recent accounts history available`, + title: `Recent Accounts` + }, + dapp: { + visited: `accessed {when}` + }, + dapps: { + none: `No recent Applications history available`, + title: `Recent Dapps` + }, + title: `Parity Home`, + url: { + none: `No recent URL history available`, + title: `Web Applications`, + visited: `visited {when}` + } +}; diff --git a/js/src/i18n/zh/index.js b/js/src/i18n/zh/index.js index 107c8491a..7b20b6249 100644 --- a/js/src/i18n/zh/index.js +++ b/js/src/i18n/zh/index.js @@ -14,10 +14,92 @@ // You should have received a copy of the GNU General Public License // along with Parity. If not, see . +import account from './account'; +import accounts from './accounts'; +import addAddress from './addAddress'; +import addContract from './addContract'; +import address from './address'; +import addressSelect from './addressSelect'; +import addresses from './addresses'; +import application from './application'; +import connection from './connection'; +import contract from './contract'; +import contracts from './contracts'; import createAccount from './createAccount'; +import createWallet from './createWallet'; +import dapp from './dapp'; +import dapps from './dapps'; +import deleteAccount from './deleteAccount'; +import deployContract from './deployContract'; +import editMeta from './editMeta'; +import errors from './errors'; +import executeContract from './executeContract'; +import extension from './extension'; +import faucet from './faucet'; +import firstRun from './firstRun'; +import home from './home'; +import loadContract from './loadContract'; +import parityBar from './parityBar'; +import passwordChange from './passwordChange'; +import saveContract from './saveContract'; import settings from './settings'; +import shapeshift from './shapeshift'; +import signer from './signer'; +import status from './status'; +import tabBar from './tabBar'; +import transfer from './transfer'; +import txEditor from './txEditor'; +import ui from './ui'; +import upgradeParity from './upgradeParity'; +import vaults from './vaults'; +import verification from './verification'; +import wallet from './wallet'; +import walletSettings from './walletSettings'; +import web from './web'; +import writeContract from './writeContract'; export default { + account, + accounts, + addAddress, + addContract, + address, + addresses, + addressSelect, + application, + connection, + contract, + contracts, createAccount, - settings + createWallet, + dapp, + dapps, + deleteAccount, + deployContract, + editMeta, + errors, + executeContract, + extension, + faucet, + firstRun, + home, + loadContract, + parityBar, + passwordChange, + saveContract, + settings, + signer, + shapeshift, + status, + tabBar, + transfer, + txEditor, + ui, + upgradeParity, + vaults, + verification, + wallet, + walletSettings, + web, + writeContract }; diff --git a/js/src/i18n/zh/loadContract.js b/js/src/i18n/zh/loadContract.js new file mode 100644 index 000000000..d4edb3a81 --- /dev/null +++ b/js/src/i18n/zh/loadContract.js @@ -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 . + +export default { + button: { + cancel: `Cancel`, + load: `Load`, + no: `No`, + yes: `Yes` + }, + contract: { + savedAt: `Saved {when}` + }, + header: { + saved: `Saved Contracts`, + snippets: `Contract Snippets` + }, + removal: { + confirm: `Are you sure you want to remove the following contract from your saved contracts?`, + savedAt: `Saved {when}` + }, + tab: { + local: `Local`, + snippets: `Snippets` + }, + title: { + remove: `confirm removal`, + view: `view contracts` + } +}; diff --git a/js/src/i18n/zh/parityBar.js b/js/src/i18n/zh/parityBar.js new file mode 100644 index 000000000..94090a961 --- /dev/null +++ b/js/src/i18n/zh/parityBar.js @@ -0,0 +1,29 @@ +// 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 . + +export default { + button: { + close: `Close` + }, + label: { + parity: `Parity`, + signer: `Signer` + }, + title: { + accounts: `Default Account`, + signer: `Parity Signer: Pending` + } +}; diff --git a/js/src/i18n/zh/passwordChange.js b/js/src/i18n/zh/passwordChange.js new file mode 100644 index 000000000..714a6e25b --- /dev/null +++ b/js/src/i18n/zh/passwordChange.js @@ -0,0 +1,54 @@ +// 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 . + +export default { + button: { + cancel: `Cancel`, + change: `Change`, + test: `Test`, + wait: `Wait...` + }, + currentPassword: { + hint: `your current password for this account`, + label: `current password` + }, + newPassword: { + hint: `the new password for this account`, + label: `new password` + }, + passwordHint: { + display: `Hint {hint}`, + hint: `hint for the new password`, + label: `(optional) new password hint` + }, + repeatPassword: { + error: `the supplied passwords do not match`, + hint: `repeat the new password for this account`, + label: `repeat new password` + }, + success: `Your password has been successfully changed`, + tabChange: { + label: `Change Password` + }, + tabTest: { + label: `Test Password` + }, + testPassword: { + hint: `your account password`, + label: `password` + }, + title: `Password Manager` +}; diff --git a/js/src/i18n/zh/saveContract.js b/js/src/i18n/zh/saveContract.js new file mode 100644 index 000000000..62ce1e33f --- /dev/null +++ b/js/src/i18n/zh/saveContract.js @@ -0,0 +1,27 @@ +// 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 . + +export default { + buttons: { + cancel: `Cancel`, + save: `Save` + }, + name: { + hint: `choose a name for this contract`, + label: `contract name` + }, + title: `save contract` +}; diff --git a/js/src/i18n/zh/settings.js b/js/src/i18n/zh/settings.js index 48a656b93..3e475e087 100644 --- a/js/src/i18n/zh/settings.js +++ b/js/src/i18n/zh/settings.js @@ -15,53 +15,87 @@ // along with Parity. If not, see . export default { - label: 'settings', - background: { - label: 'background' + button_more: `generate more`, + overview_0: `The background pattern you can see right now is unique to your Parity installation. It will change every time you create a new Signer token. This is so that decentralized applications cannot pretend to be trustworthy.`, + overview_1: `Pick a pattern you like and memorize it. This Pattern will always be shown from now on, unless you clear your browser cache or use a new Signer token.`, + label: `background` }, - parity: { - label: 'parity' + chains: { + chain_classic: `Parity syncs to the Ethereum Classic network`, + chain_dev: `Parity uses a local development chain`, + chain_expanse: `Parity syncs to the Expanse network`, + chain_foundation: `Parity syncs to the Ethereum network launched by the Ethereum Foundation`, + chain_kovan: `Parity syncs to the Kovan test network`, + chain_olympic: `Parity syncs to the Olympic test network`, + chain_ropsten: `Parity syncs to the Ropsten test network`, + cmorden_kovan: `Parity syncs to Morden (Classic) test network`, + hint: `the chain for the Parity node to sync to`, + label: `chain/network to sync` + }, + languages: { + hint: `the language this interface is displayed with`, + label: `UI language` + }, + loglevels: `Choose the different logs level.`, + modes: { + hint: `the syncing mode for the Parity node`, + label: `mode of operation`, + mode_active: `Parity continuously syncs the chain`, + mode_dark: `Parity syncs only when the RPC is active`, + mode_offline: `Parity doesn't sync`, + mode_passive: `Parity syncs initially, then sleeps and wakes regularly to resync` + }, + overview_0: `Control the Parity node settings and nature of syncing via this interface.`, + label: `parity` }, - proxy: { - label: 'proxy' + details_0: `Instead of accessing Parity via the IP address and port, you will be able to access it via the .parity subdomain, by visiting {homeProxy}. To setup subdomain-based routing, you need to add the relevant proxy entries to your browser,`, + details_1: `To learn how to configure the proxy, instructions are provided for {windowsLink}, {macOSLink} or {ubuntuLink}.`, + details_macos: `macOS`, + details_ubuntu: `Ubuntu`, + details_windows: `Windows`, + overview_0: `The proxy setup allows you to access Parity and all associated decentralized applications via memorable addresses.`, + label: `proxy` }, - views: { - label: 'views', - accounts: { - label: 'Accounts' + description: `A list of all the accounts associated with and imported into this Parity instance. Send transactions, receive incoming values, manage your balances and fund your accounts.`, + label: `Accounts` }, - addresses: { - label: 'Addressbook' + description: `A list of all contacts and address book entries managed by this Parity instance. Watch accounts and have the details available at the click of a button when transacting.`, + label: `Addressbook` }, - apps: { - label: 'Applications' + description: `Distributed applications that interact with the underlying network. Add applications, manage you application portfolio and interact with application from around the network.`, + label: `Applications` }, - contracts: { - label: 'Contracts' + description: `Watch and interact with specific contracts that have been deployed on the network. This is a more technically-focused environment, specifically for advanced users that understand the inner working of certain contracts.`, + label: `Contracts` }, - - home: { - label: 'Home' - }, - - status: { - label: 'Status' - }, - - signer: { - label: 'Signer' - }, - + overview_0: `Manage the available application views using only the parts of the application applicable to you.`, + overview_1: `Are you an end-user? The defaults are setup for both beginner and advanced users alike.`, + overview_2: `Are you a developer? Add some features to manage contracts and interact with application deployments.`, + overview_3: `Are you a miner or run a large-scale node? Add the features to give you all the information needed to watch the node operation.`, settings: { - label: 'Settings' + description: `This view. Allows you to customize the application in term of options, operation and look and feel.`, + label: `Settings` + }, + signer: { + description: `The secure transaction management area of the application where you can approve any outgoing transactions made from the application as well as those placed into the queue by distributed applications.`, + label: `Signer` + }, + status: { + description: `See how the Parity node is performing in terms of connections to the network, logs from the actual running instance and details of mining (if enabled and configured).`, + label: `Status` + }, + label: `views`, + home: { + label: `Home` } - } + }, + label: `settings` }; diff --git a/js/src/i18n/zh/shapeshift.js b/js/src/i18n/zh/shapeshift.js new file mode 100644 index 000000000..247927834 --- /dev/null +++ b/js/src/i18n/zh/shapeshift.js @@ -0,0 +1,66 @@ +// 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 . + +export default { + awaitingDepositStep: { + awaitingConfirmation: `Awaiting confirmation of the deposit address for your {typeSymbol} funds exchange`, + awaitingDeposit: `{shapeshiftLink} is awaiting a {typeSymbol} deposit. Send the funds from your {typeSymbol} network client to -`, + minimumMaximum: `{minimum} minimum, {maximum} maximum` + }, + awaitingExchangeStep: { + awaitingCompletion: `Awaiting the completion of the funds exchange and transfer of funds to your Parity account.`, + receivedInfo: `{shapeshiftLink} has received a deposit of -` + }, + button: { + cancel: `Cancel`, + done: `Close`, + shift: `Shift Funds` + }, + completedStep: { + completed: `{shapeshiftLink} has completed the funds exchange.`, + parityFunds: `The change in funds will be reflected in your Parity account shortly.` + }, + errorStep: { + info: `The funds shifting via {shapeshiftLink} failed with a fatal error on the exchange. The error message received from the exchange is as follow:` + }, + optionsStep: { + noPairs: `There are currently no exchange pairs/coins available to fund with.`, + returnAddr: { + hint: `the return address for send failures`, + label: `(optional) {coinSymbol} return address` + }, + terms: { + label: `I understand that ShapeShift.io is a 3rd-party service and by using the service any transfer of information and/or funds is completely out of the control of Parity` + }, + typeSelect: { + hint: `the type of crypto conversion to do`, + label: `fund account from` + } + }, + price: { + minMax: `({minimum} minimum, {maximum} maximum)` + }, + title: { + completed: `completed`, + deposit: `awaiting deposit`, + details: `details`, + error: `exchange failed`, + exchange: `awaiting exchange` + }, + warning: { + noPrice: `No price match was found for the selected type` + } +}; diff --git a/js/src/i18n/zh/signer.js b/js/src/i18n/zh/signer.js new file mode 100644 index 000000000..3f8615c52 --- /dev/null +++ b/js/src/i18n/zh/signer.js @@ -0,0 +1,103 @@ +// 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 . + +export default { + embedded: { + noPending: `There are currently no pending requests awaiting your confirmation` + }, + mainDetails: { + editTx: `Edit conditions/gas/gasPrice`, + tooltips: { + total1: `The value of the transaction including the mining fee is {total} {type}.`, + total2: `(This includes a mining fee of {fee} {token})`, + value1: `The value of the transaction.` + } + }, + requestOrigin: { + dapp: `by a dapp at {url}`, + ipc: `via IPC session`, + rpc: `via RPC {rpc}`, + signerCurrent: `via current tab`, + signerUI: `via UI session`, + unknownInterface: `via unknown interface`, + unknownRpc: `unidentified`, + unknownUrl: `unknown URL` + }, + requestsPage: { + noPending: `There are no requests requiring your confirmation.`, + pendingTitle: `Pending Requests`, + queueTitle: `Local Transactions` + }, + sending: { + hardware: { + confirm: `Please confirm the transaction on your attached hardware device`, + connect: `Please attach your hardware device before confirming the transaction` + } + }, + signRequest: { + request: `A request to sign data using your account:`, + state: { + confirmed: `Confirmed`, + rejected: `Rejected` + }, + unknownBinary: `(Unknown binary data)`, + warning: `WARNING: This consequences of doing this may be grave. Confirm the request only if you are sure.` + }, + title: `Trusted Signer`, + txPending: { + buttons: { + viewToggle: `view transaction` + } + }, + txPendingConfirm: { + buttons: { + confirmBusy: `Confirming...`, + confirmRequest: `Confirm Request` + }, + errors: { + invalidWallet: `Given wallet file is invalid.` + }, + password: { + decrypt: { + hint: `decrypt the key`, + label: `Key Password` + }, + unlock: { + hint: `unlock the account`, + label: `Account Password` + } + }, + passwordHint: `(hint) {passwordHint}`, + selectKey: { + hint: `The keyfile to use for this account`, + label: `Select Local Key` + }, + tooltips: { + password: `Please provide a password for this account` + } + }, + txPendingForm: { + changedMind: `I've changed my mind`, + reject: `reject request` + }, + txPendingReject: { + buttons: { + reject: `Reject Request` + }, + info: `Are you sure you want to reject request?`, + undone: `This cannot be undone` + } +}; diff --git a/js/src/i18n/zh/status.js b/js/src/i18n/zh/status.js new file mode 100644 index 000000000..536c0ff90 --- /dev/null +++ b/js/src/i18n/zh/status.js @@ -0,0 +1,66 @@ +// 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 . + +export default { + debug: { + reverse: `Reverse Order`, + stopped: `Refresh and display of logs from Parity is currently stopped via the UI, start it to see the latest updates.`, + title: `Node Logs` + }, + miningSettings: { + input: { + author: { + hint: `the mining author`, + label: `author` + }, + extradata: { + hint: `extra data for mined blocks`, + label: `extradata` + }, + gasFloor: { + hint: `the gas floor target for mining`, + label: `gas floor target` + }, + gasPrice: { + hint: `the minimum gas price for mining`, + label: `minimal gas price` + } + }, + title: `mining settings` + }, + status: { + hashrate: `{hashrate} H/s`, + input: { + chain: `chain`, + enode: `enode`, + no: `no`, + peers: `peers`, + port: `network port`, + rpcEnabled: `rpc enabled`, + rpcInterface: `rpc interface`, + rpcPort: `rpc port`, + yes: `yes` + }, + title: { + bestBlock: `best block`, + hashRate: `hash rate`, + network: `network settings`, + node: `Node`, + peers: `peers` + } + }, + title: `Status` +}; diff --git a/js/src/i18n/zh/tabBar.js b/js/src/i18n/zh/tabBar.js new file mode 100644 index 000000000..1692a1997 --- /dev/null +++ b/js/src/i18n/zh/tabBar.js @@ -0,0 +1,21 @@ +// 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 . + +export default { + tooltip: { + overview: `navigate between the different parts and views of the application, switching between an account view, token view and distributed application view` + } +}; diff --git a/js/src/i18n/zh/transfer.js b/js/src/i18n/zh/transfer.js new file mode 100644 index 000000000..3207f5b06 --- /dev/null +++ b/js/src/i18n/zh/transfer.js @@ -0,0 +1,61 @@ +// 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 . + +export default { + advanced: { + data: { + hint: `the data to pass through with the transaction`, + label: `transaction data` + } + }, + buttons: { + back: `Back`, + cancel: `Cancel`, + close: `Close`, + next: `Next`, + send: `Send` + }, + details: { + advanced: { + label: `advanced sending options` + }, + amount: { + hint: `the amount to transfer to the recipient`, + label: `amount to transfer (in {tag})` + }, + fullBalance: { + label: `full account balance` + }, + recipient: { + hint: `the recipient address`, + label: `recipient address` + }, + sender: { + hint: `the sender address`, + label: `sender address` + }, + total: { + label: `total transaction amount` + } + }, + wallet: { + confirmation: `This transaction needs confirmation from other owners.`, + operationHash: `operation hash` + }, + warning: { + wallet_spent_limit: `This transaction value is above the remaining daily limit. It will need to be confirmed by other owners.` + } +}; diff --git a/js/src/i18n/zh/txEditor.js b/js/src/i18n/zh/txEditor.js new file mode 100644 index 000000000..7dab159a8 --- /dev/null +++ b/js/src/i18n/zh/txEditor.js @@ -0,0 +1,39 @@ +// 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 . + +export default { + condition: { + block: { + hint: `The minimum block to send from`, + label: `Transaction send block` + }, + blocknumber: `Send after BlockNumber`, + date: { + hint: `The minimum date to send from`, + label: `Transaction send date` + }, + datetime: `Send after Date & Time`, + label: `Condition where transaction activates`, + none: `No conditions`, + time: { + hint: `The minimum time to send from`, + label: `Transaction send time` + } + }, + gas: { + info: `You can choose the gas price based on the distribution of recent included transaction gas prices. The lower the gas price is, the cheaper the transaction will be. The higher the gas price is, the faster it should get mined by the network.` + } +}; diff --git a/js/src/i18n/zh/ui.js b/js/src/i18n/zh/ui.js new file mode 100644 index 000000000..d84e7bd13 --- /dev/null +++ b/js/src/i18n/zh/ui.js @@ -0,0 +1,163 @@ +// 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 . + +export default { + actionbar: { + export: { + button: { + export: `export` + } + }, + import: { + button: { + cancel: `Cancel`, + confirm: `Confirm`, + import: `import` + }, + confirm: `Confirm that this is what was intended to import.`, + error: `An error occured: {errorText}`, + step: { + error: `error`, + select: `select a file`, + validate: `validate` + }, + title: `Import from a file` + }, + search: { + hint: `Enter search input...` + }, + sort: { + sortBy: `Sort by {label}`, + typeDefault: `Default`, + typeEth: `Sort by ETH`, + typeName: `Sort by name`, + typeTags: `Sort by tags` + } + }, + balance: { + none: `No balances associated with this account` + }, + blockStatus: { + bestBlock: `{blockNumber} best block`, + syncStatus: `{currentBlock}/{highestBlock} syncing`, + warpRestore: `{percentage}% warp restore`, + warpStatus: `, {percentage}% historic` + }, + confirmDialog: { + no: `no`, + yes: `yes` + }, + copyToClipboard: { + copied: `copied {data} to clipboard` + }, + errors: { + close: `close` + }, + fileSelect: { + defaultLabel: `Drop a file here, or click to select a file to upload` + }, + gasPriceSelector: { + customTooltip: { + transactions: `{number} {number, plural, one {transaction} other {transactions}} with gas price set from {minPrice} to {maxPrice}` + } + }, + identityName: { + null: `NULL`, + unnamed: `UNNAMED` + }, + methodDecoding: { + condition: { + block: `, {historic, select, true {Submitted} false {Submission}} at block {blockNumber}`, + time: `, {historic, select, true {Submitted} false {Submission}} at {timestamp}` + }, + deploy: { + address: `Deployed a contract at address`, + params: `with the following parameters:`, + willDeploy: `Will deploy a contract`, + withValue: `, sending {value}` + }, + gasUsed: `({gas} gas used)`, + gasValues: `{gas} gas ({gasPrice}M/{tag})`, + input: { + data: `data`, + input: `input`, + withInput: `with the {inputDesc} {inputValue}` + }, + receive: { + contract: `the contract`, + info: `{historic, select, true {Received} false {Will receive}} {valueEth} from {aContract}{address}` + }, + signature: { + info: `{historic, select, true {Executed} false {Will execute}} the {method} function on the contract {address} trsansferring {ethValue}{inputLength, plural, zero {,} other {passing the following {inputLength, plural, one {parameter} other {parameters}}}}` + }, + token: { + transfer: `{historic, select, true {Transferred} false {Will transfer}} {value} to {address}` + }, + transfer: { + contract: `the contract`, + info: `{historic, select, true {Transferred} false {Will transfer}} {valueEth} to {aContract}{address}` + }, + txValues: `{historic, select, true {Provided} false {Provides}} {gasProvided}{gasUsed} for a total transaction value of {totalEthValue}`, + unknown: { + info: `{historic, select, true {Executed} false {Will execute}} the {method} on the contract {address} transferring {ethValue}.` + } + }, + passwordStrength: { + label: `password strength` + }, + tooltips: { + button: { + done: `Done`, + next: `Next`, + skip: `Skip` + } + }, + txHash: { + confirmations: `{count} {value, plural, one {confirmation} other {confirmations}}`, + oog: `The transaction might have gone out of gas. Try again with more gas.`, + posted: `The transaction has been posted to the network with a hash of {hashLink}`, + waiting: `waiting for confirmations` + }, + vaultSelect: { + hint: `the vault this account is attached to`, + label: `associated vault` + }, + verification: { + gatherData: { + accountHasRequested: { + false: `You did not request verification from this account yet.`, + pending: `Checking if you requested verification…`, + true: `You already requested verification from this account.` + }, + accountIsVerified: { + false: `Your account is not verified yet.`, + pending: `Checking if your account is verified…`, + true: `Your account is already verified.` + }, + fee: `The additional fee is {amount} ETH.`, + isAbleToRequest: { + pending: `Validating your input…` + }, + isServerRunning: { + false: `The verification server is not running.`, + pending: `Checking if the verification server is running…`, + true: `The verification server is running.` + }, + nofee: `There is no additional fee.`, + termsOfService: `I agree to the terms and conditions below.` + } + } +}; diff --git a/js/src/i18n/zh/upgradeParity.js b/js/src/i18n/zh/upgradeParity.js new file mode 100644 index 000000000..b3d871452 --- /dev/null +++ b/js/src/i18n/zh/upgradeParity.js @@ -0,0 +1,47 @@ +// 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 . + +export default { + busy: `Your upgrade to Parity {newversion} is currently in progress. Please wait until the process completes.`, + button: { + close: `close`, + done: `done`, + upgrade: `upgrade now` + }, + completed: `Your upgrade to Parity {newversion} has been successfully completed. Click "done" to automatically reload the application.`, + consensus: { + capable: `Your current Parity version is capable of handling the network requirements.`, + capableUntil: `Your current Parity version is capable of handling the network requirements until block {blockNumber}`, + incapableSince: `Your current Parity version is incapable of handling the network requirements since block {blockNumber}`, + unknown: `Your current Parity version is capable of handling the network requirements.` + }, + failed: `Your upgrade to Parity {newversion} has failed with an error.`, + info: { + currentVersion: `You are currently running {currentversion}`, + next: `Proceed with "upgrade now" to start your Parity upgrade.`, + upgrade: `An upgrade to version {newversion} is available`, + welcome: `Welcome to the Parity upgrade wizard, allowing you a completely seamless upgrade experience to the next version of Parity.` + }, + step: { + completed: `upgrade completed`, + error: `error`, + info: `upgrade available`, + updating: `upgrading parity` + }, + version: { + unknown: `unknown` + } +}; diff --git a/js/src/i18n/zh/vaults.js b/js/src/i18n/zh/vaults.js new file mode 100644 index 000000000..04ff4d558 --- /dev/null +++ b/js/src/i18n/zh/vaults.js @@ -0,0 +1,108 @@ +// 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 . + +export default { + accounts: { + button: { + cancel: `Cancel`, + execute: `Set` + }, + empty: `There are no accounts in this vault`, + title: `Manage Vault Accounts` + }, + button: { + accounts: `accounts`, + add: `create vault`, + close: `close`, + edit: `edit`, + open: `open` + }, + confirmClose: { + info: `You are about to close a vault. Any accounts associated with the vault won't be visible after this operation concludes. To view the associated accounts, open the vault again.`, + title: `Close Vault` + }, + confirmOpen: { + info: `You are about to open a vault. After confirming your password, all accounts associated with this vault will be visible. Closing the vault will remove the accounts from view until the vault is opened again.`, + password: { + hint: `the password specified when creating the vault`, + label: `vault password` + }, + title: `Open Vault` + }, + create: { + button: { + close: `close`, + vault: `create vault` + }, + description: { + hint: `an extended description for the vault` + }, + descriptions: { + label: `(optional) description` + }, + hint: { + hint: `(optional) a hint to help with remembering the password`, + label: `password hint` + }, + name: { + hint: `a name for the vault`, + label: `vault name` + }, + password: { + hint: `a strong, unique password`, + label: `password` + }, + password2: { + hint: `verify your password`, + label: `password (repeat)` + }, + title: `Create a new vault` + }, + editMeta: { + allowPassword: `Change vault password`, + button: { + close: `close`, + save: `save` + }, + currentPassword: { + hint: `your current vault password`, + label: `current password` + }, + description: { + hint: `the description for this vault`, + label: `vault description` + }, + password: { + hint: `a strong, unique password`, + label: `new password` + }, + password2: { + hint: `verify your new password`, + label: `new password (repeat)` + }, + passwordHint: { + hint: `your password hint for this vault`, + label: `password hint` + }, + title: `Edit Vault Metadata` + }, + empty: `There are currently no vaults to display.`, + selector: { + noneAvailable: `There are currently no vaults opened and available for selection. Create and open some first before attempting to select a vault for an account move.`, + title: `Select Account Vault` + }, + title: `Vault Management` +}; diff --git a/js/src/i18n/zh/verification.js b/js/src/i18n/zh/verification.js new file mode 100644 index 000000000..2d98ed82a --- /dev/null +++ b/js/src/i18n/zh/verification.js @@ -0,0 +1,85 @@ +// 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 . + +export default { + button: { + cancel: `Cancel`, + done: `Done`, + next: `Next` + }, + code: { + error: `invalid code`, + hint: `Enter the code you received.`, + label: `verification code`, + sent: `The verification code has been sent to {receiver}.` + }, + confirmation: { + authorise: `The verification code will be sent to the contract. Please authorize this using the Parity Signer.`, + windowOpen: `Please keep this window open.` + }, + done: { + message: `Congratulations, your account is verified!` + }, + email: { + enterCode: `Enter the code you received via e-mail.` + }, + gatherData: { + email: { + hint: `the code will be sent to this address`, + label: `e-mail address` + }, + phoneNumber: { + hint: `the SMS will be sent to this number`, + label: `phone number in international format` + } + }, + gatherDate: { + email: { + error: `invalid e-mail` + }, + phoneNumber: { + error: `invalid number` + } + }, + loading: `Loading verification data.`, + request: { + authorise: `A verification request will be sent to the contract. Please authorize this using the Parity Signer.`, + requesting: `Requesting a code from the Parity server and waiting for the puzzle to be put into the contract.`, + windowOpen: `Please keep this window open.` + }, + sms: { + enterCode: `Enter the code you received via SMS.` + }, + steps: { + code: `Enter Code`, + completed: `Completed`, + confirm: `Confirm`, + data: `Enter Data`, + method: `Method`, + request: `Request` + }, + title: `verify your account`, + types: { + email: { + description: `The hash of the e-mail address you prove control over will be stored on the blockchain.`, + label: `E-mail Verification` + }, + sms: { + description: `It will be stored on the blockchain that you control a phone number (not which).`, + label: `SMS Verification` + } + } +}; diff --git a/js/src/i18n/zh/wallet.js b/js/src/i18n/zh/wallet.js new file mode 100644 index 000000000..92063af8b --- /dev/null +++ b/js/src/i18n/zh/wallet.js @@ -0,0 +1,45 @@ +// 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 . + +export default { + buttons: { + edit: `edit`, + forget: `forget`, + settings: `settings`, + transfer: `transfer` + }, + confirmations: { + buttons: { + confirmAs: `Confirm As...`, + revokeAs: `Revoke As...` + }, + none: `No transactions needs confirmation right now.`, + tooltip: { + confirmed: `Confirmed by {number}/{required} owners` + } + }, + details: { + requiredOwners: `This wallet requires at least {owners} to validate any action (transactions, modifications).`, + requiredOwnersNumber: `{number} {numberValue, plural, one {owner} other {owners}}`, + spent: `{spent} has been spent today, out of {limit} set as the daily limit, which has been reset on {date}`, + title: `Details` + }, + title: `Wallet Management`, + transactions: { + none: `No transactions has been sent.`, + title: `Transactions` + } +}; diff --git a/js/src/i18n/zh/walletSettings.js b/js/src/i18n/zh/walletSettings.js new file mode 100644 index 000000000..ddeae3798 --- /dev/null +++ b/js/src/i18n/zh/walletSettings.js @@ -0,0 +1,69 @@ +// 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 . + +export default { + addOwner: { + title: `Add Owner` + }, + buttons: { + cancel: `Cancel`, + close: `Close`, + next: `Next`, + send: `Send`, + sending: `Sending...` + }, + changes: { + modificationString: `For your modifications to be taken into account, + other owners have to send the same modifications. They can paste + this string to make it easier:`, + none: `No modifications have been made to the Wallet settings.`, + overview: `You are about to make the following modifications` + }, + edit: { + message: `In order to edit this contract's settings, at + least {owners, number} {owners, plural, one {owner } other {owners }} have to + send the very same modifications. You can paste a stringified version + of the modifications here.` + }, + modifications: { + daylimit: { + hint: `amount of ETH spendable without confirmations`, + label: `wallet day limit` + }, + fromString: { + label: `modifications` + }, + owners: { + label: `other wallet owners` + }, + required: { + hint: `number of required owners to accept a transaction`, + label: `required owners` + }, + sender: { + hint: `send modifications as this owner`, + label: `from account (wallet owner)` + } + }, + ownersChange: { + details: `from {from} to {to}`, + title: `Change Required Owners` + }, + rejected: `The transaction #{txid} has been rejected`, + removeOwner: { + title: `Remove Owner` + } +}; diff --git a/js/src/i18n/zh/web.js b/js/src/i18n/zh/web.js new file mode 100644 index 000000000..6136d387f --- /dev/null +++ b/js/src/i18n/zh/web.js @@ -0,0 +1,19 @@ +// 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 . + +export default { + requestToken: `Requesting access token...` +}; diff --git a/js/src/i18n/zh/writeContract.js b/js/src/i18n/zh/writeContract.js new file mode 100644 index 000000000..fc1100b77 --- /dev/null +++ b/js/src/i18n/zh/writeContract.js @@ -0,0 +1,62 @@ +// 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 . + +export default { + buttons: { + autoCompile: `Auto-Compile`, + compile: `Compile`, + deploy: `Deploy`, + import: `Import Solidity`, + load: `Load`, + new: `New`, + optimise: `Optimise`, + save: `Save` + }, + compiling: { + action: `Please compile the source code.`, + busy: `Compiling...` + }, + details: { + saved: `(saved {timestamp})` + }, + error: { + noContract: `No contract has been found.`, + params: `An error occurred with the following description` + }, + input: { + abi: `ABI Interface`, + code: `Bytecode`, + metadata: `Metadata`, + swarm: `Swarm Metadata Hash` + }, + title: { + contract: `Select a contract`, + loading: `Loading...`, + main: `Write a Contract`, + messages: `Compiler messages`, + new: `New Solidity Contract`, + parameters: `Parameters`, + saved: `saved @ {timestamp}`, + selectSolidity: `Select a Solidity version`, + solidity: `Loading Solidity {version}` + }, + type: { + humanErc20: `Implementation of the Human Token Contract`, + implementErc20: `Implementation of ERC20 Token Contract`, + multisig: `Implementation of a multisig Wallet`, + standardErc20: `Standard ERC20 Token Contract` + } +}; From d6110d7332813519535831db7733c4036509f948 Mon Sep 17 00:00:00 2001 From: GitLab Build Bot Date: Mon, 27 Mar 2017 20:08:17 +0000 Subject: [PATCH 37/72] [ci skip] js-precompiled 20170327-200527 --- Cargo.lock | 2 +- js/package.json | 2 +- 2 files changed, 2 insertions(+), 2 deletions(-) diff --git a/Cargo.lock b/Cargo.lock index 1ae1159a9..dda7fe088 100644 --- a/Cargo.lock +++ b/Cargo.lock @@ -1751,7 +1751,7 @@ dependencies = [ [[package]] name = "parity-ui-precompiled" version = "1.4.0" -source = "git+https://github.com/ethcore/js-precompiled.git#38a485b837208427cbb9ee0b3db45f8ab2313884" +source = "git+https://github.com/ethcore/js-precompiled.git#647ecb9bd9087fd5ce882c3d81192d1529280dc3" dependencies = [ "parity-dapps-glue 1.7.0 (registry+https://github.com/rust-lang/crates.io-index)", ] diff --git a/js/package.json b/js/package.json index 2d8d2de2b..8d963f1a3 100644 --- a/js/package.json +++ b/js/package.json @@ -1,6 +1,6 @@ { "name": "parity.js", - "version": "1.7.36", + "version": "1.7.37", "main": "release/index.js", "jsnext:main": "src/index.js", "author": "Parity Team ", From 8a664c524c1904f940250b1aa0d93643782fb489 Mon Sep 17 00:00:00 2001 From: Nicolas Gotchac Date: Tue, 28 Mar 2017 08:34:54 +0200 Subject: [PATCH 38/72] Use uniq owners for multi sig wallets (#5298) --- js/src/util/wallets.js | 3 ++- 1 file changed, 2 insertions(+), 1 deletion(-) diff --git a/js/src/util/wallets.js b/js/src/util/wallets.js index af09dbd07..e90f4115f 100644 --- a/js/src/util/wallets.js +++ b/js/src/util/wallets.js @@ -222,7 +222,8 @@ export default class WalletsUtils { } return owners; - }); + }) + .then((owners) => uniq(owners)); }); } From d99aa3192c41b778f38d5734de61b24683385b12 Mon Sep 17 00:00:00 2001 From: Nicolas Gotchac Date: Tue, 28 Mar 2017 08:35:10 +0200 Subject: [PATCH 39/72] Fix default list sorting (#5303) * Fix default sorting for lists views * Linting --- js/src/ui/Actionbar/Sort/sortStore.js | 4 +++- js/src/views/Contracts/contracts.js | 14 ++++++++------ 2 files changed, 11 insertions(+), 7 deletions(-) diff --git a/js/src/ui/Actionbar/Sort/sortStore.js b/js/src/ui/Actionbar/Sort/sortStore.js index 0d32b2b06..ae02a34cb 100644 --- a/js/src/ui/Actionbar/Sort/sortStore.js +++ b/js/src/ui/Actionbar/Sort/sortStore.js @@ -47,7 +47,9 @@ export default class SortStore { @action restoreSavedOrder = () => { const order = this.getSavedOrder(); - this.onChange(order); + if (order) { + this.onChange(order); + } } getSavedOrder = () => { diff --git a/js/src/views/Contracts/contracts.js b/js/src/views/Contracts/contracts.js index 938fc12b5..33b475c5f 100644 --- a/js/src/views/Contracts/contracts.js +++ b/js/src/views/Contracts/contracts.js @@ -66,7 +66,7 @@ class Contracts extends Component { state = { addContract: false, deployContract: false, - sortOrder: 'blockNumber', + sortOrder: 'blockNumber:-1', searchValues: [], searchTokens: [] } @@ -121,18 +121,16 @@ class Contracts extends Component { } renderSortButton () { - const onChange = (sortOrder) => { - this.setState({ sortOrder }); - }; + const { sortOrder } = this.state; return ( ); } @@ -239,6 +237,10 @@ class Contracts extends Component { ); } + handleSortChange = (sortOrder) => { + this.setState({ sortOrder }); + } + onAddSearchToken = (token) => { const { searchTokens } = this.state; const newSearchTokens = uniq([].concat(searchTokens, token)); From 7039eaf9955136c8c3faca1bffe27513a5697213 Mon Sep 17 00:00:00 2001 From: GitLab Build Bot Date: Tue, 28 Mar 2017 07:02:31 +0000 Subject: [PATCH 40/72] [ci skip] js-precompiled 20170328-065931 --- Cargo.lock | 2 +- js/package.json | 2 +- 2 files changed, 2 insertions(+), 2 deletions(-) diff --git a/Cargo.lock b/Cargo.lock index dda7fe088..2eac32511 100644 --- a/Cargo.lock +++ b/Cargo.lock @@ -1751,7 +1751,7 @@ dependencies = [ [[package]] name = "parity-ui-precompiled" version = "1.4.0" -source = "git+https://github.com/ethcore/js-precompiled.git#647ecb9bd9087fd5ce882c3d81192d1529280dc3" +source = "git+https://github.com/ethcore/js-precompiled.git#a8269c81444111331d9897234f44869ec638d177" dependencies = [ "parity-dapps-glue 1.7.0 (registry+https://github.com/rust-lang/crates.io-index)", ] diff --git a/js/package.json b/js/package.json index 8d963f1a3..f5e741f3c 100644 --- a/js/package.json +++ b/js/package.json @@ -1,6 +1,6 @@ { "name": "parity.js", - "version": "1.7.37", + "version": "1.7.38", "main": "release/index.js", "jsnext:main": "src/index.js", "author": "Parity Team ", From a61b1567d0e69d0ca498fa2b3446b057554836ba Mon Sep 17 00:00:00 2001 From: keorn Date: Tue, 28 Mar 2017 04:46:52 -0400 Subject: [PATCH 41/72] Strict validation transitions (#4988) * ability to make validation stricter * fix consensus * remove logger --- ethcore/res/ethereum/kovan.json | 5 +++-- ethcore/src/client/client.rs | 2 +- ethcore/src/engines/authority_round.rs | 14 ++++++++++++-- ethcore/src/spec/spec.rs | 4 ++-- ethcore/src/verification/canon_verifier.rs | 2 +- ethcore/src/verification/noop_verifier.rs | 2 +- ethcore/src/verification/verification.rs | 4 ++-- ethcore/src/verification/verifier.rs | 2 +- json/src/spec/authority_round.rs | 3 +++ json/src/spec/params.rs | 4 ++-- 10 files changed, 28 insertions(+), 14 deletions(-) diff --git a/ethcore/res/ethereum/kovan.json b/ethcore/res/ethereum/kovan.json index 330b00c58..78a82ccca 100644 --- a/ethcore/res/ethereum/kovan.json +++ b/ethcore/res/ethereum/kovan.json @@ -23,7 +23,8 @@ "0x00a0a24b9f0e5ec7aa4c7389b8302fd0123194de" ] - } + }, + "validateScoreTransition": 1000000 } } }, @@ -31,7 +32,7 @@ "maximumExtraDataSize": "0x20", "minGasLimit": "0x1388", "networkID" : "0x2A", - "validateReceipts" : false + "validateReceiptsTransition" : 1000000 }, "genesis": { "seal": { diff --git a/ethcore/src/client/client.rs b/ethcore/src/client/client.rs index 978f7a99c..12f92177c 100644 --- a/ethcore/src/client/client.rs +++ b/ethcore/src/client/client.rs @@ -393,7 +393,7 @@ impl Client { })?; // Final Verification - if let Err(e) = self.verifier.verify_block_final(header, locked_block.block().header(), self.engine().params().validate_receipts) { + if let Err(e) = self.verifier.verify_block_final(header, locked_block.block().header(), self.engine().params().validate_receipts_transition) { warn!(target: "client", "Stage 4 block verification failed for #{} ({})\nError: {:?}", header.number(), header.hash(), e); return Err(()); } diff --git a/ethcore/src/engines/authority_round.rs b/ethcore/src/engines/authority_round.rs index 4f823fa8d..aeef176a9 100644 --- a/ethcore/src/engines/authority_round.rs +++ b/ethcore/src/engines/authority_round.rs @@ -53,6 +53,8 @@ pub struct AuthorityRoundParams { pub start_step: Option, /// Valid validators. pub validators: ethjson::spec::ValidatorSet, + /// Chain score validation transition block. + pub validate_score_transition: u64, } impl From for AuthorityRoundParams { @@ -64,6 +66,7 @@ impl From for AuthorityRoundParams { block_reward: p.block_reward.map_or_else(U256::zero, Into::into), registrar: p.registrar.map_or_else(Address::new, Into::into), start_step: p.start_step.map(Into::into), + validate_score_transition: p.validate_score_transition.map_or(0, Into::into), } } } @@ -85,6 +88,7 @@ pub struct AuthorityRound { validators: Box, /// Is this Engine just for testing (prevents step calibration). calibrate_step: bool, + validate_score_transition: u64, } fn header_step(header: &Header) -> Result { @@ -125,6 +129,7 @@ impl AuthorityRound { signer: Default::default(), validators: new_validator_set(our_params.validators), calibrate_step: our_params.start_step.is_none(), + validate_score_transition: our_params.validate_score_transition, }); // Do not initialize timeouts for tests. if should_timeout { @@ -295,13 +300,17 @@ impl Engine for AuthorityRound { Err(From::from(BlockError::InvalidSealArity( Mismatch { expected: self.seal_fields(), found: header.seal().len() } ))) + } else if header.number() >= self.validate_score_transition && *header.difficulty() >= U256::from(U128::max_value()) { + Err(From::from(BlockError::DifficultyOutOfBounds( + OutOfBounds { min: None, max: Some(U256::from(U128::max_value())), found: *header.difficulty() } + ))) } else { Ok(()) } } fn verify_block_unordered(&self, _header: &Header, _block: Option<&[u8]>) -> Result<(), Error> { - Ok(()) + Ok(()) } /// Do the validator and gas limit validation. @@ -327,7 +336,8 @@ impl Engine for AuthorityRound { } // Check if parent is from a previous step. - if step == header_step(parent)? { + let parent_step = header_step(parent)?; + if step == parent_step { trace!(target: "engine", "Multiple blocks proposed for step {}.", step); self.validators.report_malicious(header.author()); Err(EngineError::DoubleVote(header.author().clone()))?; diff --git a/ethcore/src/spec/spec.rs b/ethcore/src/spec/spec.rs index 455d0745f..9080f2929 100644 --- a/ethcore/src/spec/spec.rs +++ b/ethcore/src/spec/spec.rs @@ -56,7 +56,7 @@ pub struct CommonParams { /// Number of first block where EIP-98 rules begin. pub eip98_transition: BlockNumber, /// Validate block receipts root. - pub validate_receipts: bool, + pub validate_receipts_transition: u64, } impl From for CommonParams { @@ -70,7 +70,7 @@ impl From 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), + validate_receipts_transition: p.validate_receipts_transition.map_or(0, Into::into), } } } diff --git a/ethcore/src/verification/canon_verifier.rs b/ethcore/src/verification/canon_verifier.rs index 67d7e0e85..188d94a10 100644 --- a/ethcore/src/verification/canon_verifier.rs +++ b/ethcore/src/verification/canon_verifier.rs @@ -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, receipts: bool) -> Result<(), Error> { + fn verify_block_final(&self, expected: &Header, got: &Header, receipts: u64) -> Result<(), Error> { verification::verify_block_final(expected, got, receipts) } } diff --git a/ethcore/src/verification/noop_verifier.rs b/ethcore/src/verification/noop_verifier.rs index b60dbed2e..0512c8208 100644 --- a/ethcore/src/verification/noop_verifier.rs +++ b/ethcore/src/verification/noop_verifier.rs @@ -31,7 +31,7 @@ impl Verifier for NoopVerifier { Ok(()) } - fn verify_block_final(&self, _expected: &Header, _got: &Header, _receipts: bool) -> Result<(), Error> { + fn verify_block_final(&self, _expected: &Header, _got: &Header, _receipts: u64) -> Result<(), Error> { Ok(()) } } diff --git a/ethcore/src/verification/verification.rs b/ethcore/src/verification/verification.rs index ab21ef6c2..2e913a305 100644 --- a/ethcore/src/verification/verification.rs +++ b/ethcore/src/verification/verification.rs @@ -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, check_receipts: bool) -> Result<(), Error> { +pub fn verify_block_final(expected: &Header, got: &Header, check_receipts: u64) -> 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, check_receipts: bool) 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 check_receipts && expected.receipts_root() != got.receipts_root() { + if got.number() >= 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(()) diff --git a/ethcore/src/verification/verifier.rs b/ethcore/src/verification/verifier.rs index 9f0173003..08ec8c25a 100644 --- a/ethcore/src/verification/verifier.rs +++ b/ethcore/src/verification/verifier.rs @@ -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, receipts: bool) -> Result<(), Error>; + fn verify_block_final(&self, expected: &Header, got: &Header, receipts: u64) -> Result<(), Error>; } diff --git a/json/src/spec/authority_round.rs b/json/src/spec/authority_round.rs index 35f6298ae..1c01d81fe 100644 --- a/json/src/spec/authority_round.rs +++ b/json/src/spec/authority_round.rs @@ -40,6 +40,9 @@ pub struct AuthorityRoundParams { /// To be used for testing only. #[serde(rename="startStep")] pub start_step: Option, + /// Block at which score validation should start. + #[serde(rename="validateScoreTransition")] + pub validate_score_transition: Option, } /// Authority engine deserialization. diff --git a/json/src/spec/params.rs b/json/src/spec/params.rs index 1b2622316..aa2c15da4 100644 --- a/json/src/spec/params.rs +++ b/json/src/spec/params.rs @@ -54,8 +54,8 @@ pub struct Params { #[serde(rename="eip98Transition")] pub eip98_transition: Option, /// See `CommonParams` docs. - #[serde(rename="validateReceipts")] - pub validate_receipts: Option, + #[serde(rename="validateReceiptsTransition")] + pub validate_receipts_transition: Option, } #[cfg(test)] From c7d99c37fba1cb8aea88fe44b0c93b6f877912d8 Mon Sep 17 00:00:00 2001 From: Arkadiy Paronyan Date: Tue, 28 Mar 2017 10:47:21 +0200 Subject: [PATCH 42/72] Ropsten revival (#5302) --- ethcore/res/ethereum/ropsten.json | 11 ++++------- 1 file changed, 4 insertions(+), 7 deletions(-) diff --git a/ethcore/res/ethereum/ropsten.json b/ethcore/res/ethereum/ropsten.json index 231073e4d..539168279 100644 --- a/ethcore/res/ethereum/ropsten.json +++ b/ethcore/res/ethereum/ropsten.json @@ -25,8 +25,8 @@ "maximumExtraDataSize": "0x20", "minGasLimit": "0x1388", "networkID" : "0x3", - "forkBlock": 333922, - "forkCanonHash": "0x8737eb141d4f05db57af63fc8d3b4d4d8f9cddb0c4e1ab855de8c288fdc1924f", + "forkBlock": 641350, + "forkCanonHash": "0x8033403e9fe5811a7b6d6b469905915de1c59207ce2172cbcf5d6ff14fa6a2eb", "eip98Transition": "0x7fffffffffffff" }, "genesis": { @@ -44,11 +44,8 @@ "gasLimit": "0x1000000" }, "nodes": [ - "enode://a22f0977ce02653bf95e38730106356342df48b5222e2c2a1a6f9ef34769bf593bae9ca0a888cf60839edd52efc1b6e393c63a57d76f4c4fe14e641f1f9e637e@128.199.55.137:30303", - "enode://012239fccf3ff1d92b036983a430cb6705c6528c96c0354413f8854802138e5135c084ab36e7c54efb621c46728df8c3a6f4c1db9bb48a1330efe3f82f2dd7a6@52.169.94.142:30303", - "enode://1462682e4b7ba2258346d55e25e5b9d264b0db40cee12bdfba4e72b1d7050350ea954c006e9106dd96a128e6e0bd6dffb17eed51f9f99bf7f9cdadfeaf8da4ff@51.15.61.253:30303", - "enode://98fbb020c799ae39a828bd75dc2bd5d4721539faf317076b275f91182a5c8900b592e8abfdddceae674a7c3bb40ea00a6ca9ccb7805ab58c4b7b29c61c8f7239@51.15.62.44:30303", - "enode://d801dd4e3d15a8bf785931add164bd9c313e3f6b5749d9302b311f2b48064cba5c86c32b1302c27cd983fc89ae07d4d306dd1197610835b8782e95dfb1b3f9ea@51.15.43.255:30303" + "enode://20c9ad97c081d63397d7b685a412227a40e23c8bdc6688c6f37e97cfbc22d2b4d1db1510d8f61e6a8866ad7f0e17c02b14182d37ea7c3c8b9c2683aeb6b733a1@52.169.14.227:30303", + "enode://6ce05930c72abc632c58e2e4324f7c7ea478cec0ed4fa2528982cf34483094e9cbc9216e7aa349691242576d552a2a56aaeae426c5303ded677ce455ba1acd9d@13.84.180.240:30303" ], "accounts": { "0000000000000000000000000000000000000001": { "balance": "1", "nonce": "0", "builtin": { "name": "ecrecover", "pricing": { "linear": { "base": 3000, "word": 0 } } } }, From 8e91f7b7012e858863f98d516dab74b30154c479 Mon Sep 17 00:00:00 2001 From: Jaco Greeff Date: Tue, 28 Mar 2017 11:24:07 +0200 Subject: [PATCH 43/72] Fix eth_sign showing as wallet account (#5309) * defaultProps for account * Pass signing account * Update tests for Connect(...) --- .../RequestPending/requestPending.spec.js | 2 +- .../components/SignRequest/signRequest.js | 25 +++++++-- .../SignRequest/signRequest.spec.js | 52 ++++++++++++++++--- .../transactionPendingForm.js | 3 +- 4 files changed, 70 insertions(+), 12 deletions(-) diff --git a/js/src/views/Signer/components/RequestPending/requestPending.spec.js b/js/src/views/Signer/components/RequestPending/requestPending.spec.js index 686c23b67..130a9d319 100644 --- a/js/src/views/Signer/components/RequestPending/requestPending.spec.js +++ b/js/src/views/Signer/components/RequestPending/requestPending.spec.js @@ -92,7 +92,7 @@ describe('views/Signer/RequestPending', () => { }); it('renders SignRequest component', () => { - expect(component.find('SignRequest')).to.have.length(1); + expect(component.find('Connect(SignRequest)')).to.have.length(1); }); }); diff --git a/js/src/views/Signer/components/SignRequest/signRequest.js b/js/src/views/Signer/components/SignRequest/signRequest.js index 8c9984b4b..ef68e78a1 100644 --- a/js/src/views/Signer/components/SignRequest/signRequest.js +++ b/js/src/views/Signer/components/SignRequest/signRequest.js @@ -14,9 +14,10 @@ // You should have received a copy of the GNU General Public License // along with Parity. If not, see . +import { observer } from 'mobx-react'; import React, { Component, PropTypes } from 'react'; import { FormattedMessage } from 'react-intl'; -import { observer } from 'mobx-react'; +import { connect } from 'react-redux'; import Account from '../Account'; import TransactionPendingForm from '../TransactionPendingForm'; @@ -36,12 +37,13 @@ function isAscii (data) { } @observer -export default class SignRequest extends Component { +class SignRequest extends Component { static contextTypes = { api: PropTypes.object }; static propTypes = { + accounts: PropTypes.object.isRequired, address: PropTypes.string.isRequired, data: PropTypes.string.isRequired, id: PropTypes.object.isRequired, @@ -152,7 +154,10 @@ export default class SignRequest extends Component { } renderActions () { - const { address, focus, isFinished, status } = this.props; + const { accounts, address, focus, isFinished, status } = this.props; + const account = Object + .values(accounts) + .find((account) => address === account.address.toLowerCase()); if (isFinished) { if (status === 'confirmed') { @@ -182,6 +187,7 @@ export default class SignRequest extends Component { return ( { + return { + personal: { + accounts: {} + } + }; + } + }; +} + +function render () { + reduxStore = createReduxStore(); + signerStore = createSignerStore(); + + component = shallow( + , + { + context: { + store: reduxStore + } + } + ).find('SignRequest').shallow(); + + return component; +} describe('views/Signer/components/SignRequest', () => { + beforeEach(() => { + render(); + }); + it('renders', () => { - expect(shallow( - , - )).to.be.ok; + expect(component).to.be.ok; }); }); diff --git a/js/src/views/Signer/components/TransactionPendingForm/transactionPendingForm.js b/js/src/views/Signer/components/TransactionPendingForm/transactionPendingForm.js index 193eab9f4..73e3bb7ef 100644 --- a/js/src/views/Signer/components/TransactionPendingForm/transactionPendingForm.js +++ b/js/src/views/Signer/components/TransactionPendingForm/transactionPendingForm.js @@ -25,7 +25,7 @@ import styles from './transactionPendingForm.css'; export default class TransactionPendingForm extends Component { static propTypes = { - account: PropTypes.object.isRequired, + account: PropTypes.object, address: PropTypes.string.isRequired, disabled: PropTypes.bool, isSending: PropTypes.bool.isRequired, @@ -36,6 +36,7 @@ export default class TransactionPendingForm extends Component { }; static defaultProps = { + account: {}, focus: false }; From e28c47707593bfe5e4a602b67b4f94657acc9123 Mon Sep 17 00:00:00 2001 From: GitLab Build Bot Date: Tue, 28 Mar 2017 09:46:03 +0000 Subject: [PATCH 44/72] [ci skip] js-precompiled 20170328-094309 --- Cargo.lock | 2 +- js/package.json | 2 +- 2 files changed, 2 insertions(+), 2 deletions(-) diff --git a/Cargo.lock b/Cargo.lock index 2eac32511..3e7be60ac 100644 --- a/Cargo.lock +++ b/Cargo.lock @@ -1751,7 +1751,7 @@ dependencies = [ [[package]] name = "parity-ui-precompiled" version = "1.4.0" -source = "git+https://github.com/ethcore/js-precompiled.git#a8269c81444111331d9897234f44869ec638d177" +source = "git+https://github.com/ethcore/js-precompiled.git#05a4e30d179ba97f21a037d7508e18ab3e53a8e8" dependencies = [ "parity-dapps-glue 1.7.0 (registry+https://github.com/rust-lang/crates.io-index)", ] diff --git a/js/package.json b/js/package.json index f5e741f3c..0554d249b 100644 --- a/js/package.json +++ b/js/package.json @@ -1,6 +1,6 @@ { "name": "parity.js", - "version": "1.7.38", + "version": "1.7.39", "main": "release/index.js", "jsnext:main": "src/index.js", "author": "Parity Team ", From a99721004bdac7a3a4de4f126d1d6b6c84e2686c Mon Sep 17 00:00:00 2001 From: Nicolas Gotchac Date: Tue, 28 Mar 2017 14:34:31 +0200 Subject: [PATCH 45/72] Minimise transactions progress (#4942) * Watch the requests and display them throughout the app * Linting * Showing Requests * Fully working Transaction Requests Display * Add FormattedMessage to Requests * Clean-up the Transfer dialog * Update Validations * Cleanup Create Wallet * Clean Deploy Contract Dialog * Cleanup Contract Execution * Fix Requests * Cleanup Wallet Settings * Don't show stepper in Portal if less than 2 steps * WIP local storage requests * Caching requests and saving contract deployments * Add Historic prop to Requests MethodDecoding * Fix tests * Add Contract address to MethodDecoding * PR Grumbles - Part I * PR Grumbles - Part II * Use API Subscription methods * Linting * Move SavedRequests and add tests * Added tests for Requests Actions * Fixing tests * PR Grumbles + Playground fix * Revert Playground changes * PR Grumbles * Better showEth in MethodDecoding --- js/src/api/format/input.js | 68 ++-- js/src/api/rpc/parity/parity.js | 2 +- js/src/api/subscriptions/manager.js | 3 +- js/src/api/subscriptions/manager.spec.js | 2 +- js/src/api/subscriptions/signer.js | 19 +- js/src/modals/CreateWallet/createWallet.js | 113 ++----- .../modals/CreateWallet/createWallet.spec.js | 4 +- .../modals/CreateWallet/createWalletStore.js | 132 +------- .../modals/DeployContract/deployContract.css | 13 - .../modals/DeployContract/deployContract.js | 294 ++---------------- .../modals/ExecuteContract/executeContract.js | 176 ++--------- js/src/modals/Transfer/store.js | 105 +------ js/src/modals/Transfer/transfer.js | 100 +----- .../modals/WalletSettings/walletSettings.js | 102 +----- .../WalletSettings/walletSettingsStore.js | 72 +---- js/src/redux/providers/index.js | 1 + js/src/redux/providers/requestsActions.js | 171 ++++++++++ .../redux/providers/requestsActions.spec.js | 111 +++++++ js/src/redux/providers/requestsReducer.js | 43 +++ js/src/redux/providers/status.js | 2 +- js/src/redux/reducers.js | 3 +- js/src/redux/store.js | 2 + js/src/secureApi.js | 1 + js/src/ui/Form/InputAddress/inputAddress.js | 29 +- js/src/ui/MethodDecoding/methodDecoding.js | 78 +++-- .../ScrollableText/index.js} | 20 +- js/src/ui/ScrollableText/scrollableText.css | 34 ++ js/src/ui/ScrollableText/scrollableText.js | 40 +++ js/src/ui/ShortenedHash/shortenedHash.js | 2 +- js/src/ui/Title/title.js | 2 +- js/src/ui/index.js | 1 + js/src/util/tx.js | 193 ++++++------ js/src/util/validation.js | 29 ++ js/src/util/validation.spec.js | 90 ++++-- .../Application/Requests}/index.js | 2 +- .../views/Application/Requests/requests.css | 127 ++++++++ js/src/views/Application/Requests/requests.js | 233 ++++++++++++++ .../Application/Requests/savedRequests.js | 89 ++++++ .../Requests/savedRequests.spec.js | 88 ++++++ js/src/views/Application/application.js | 2 + 40 files changed, 1382 insertions(+), 1216 deletions(-) create mode 100644 js/src/redux/providers/requestsActions.js create mode 100644 js/src/redux/providers/requestsActions.spec.js create mode 100644 js/src/redux/providers/requestsReducer.js rename js/src/{modals/DeployContract/ErrorStep/errorStep.js => ui/ScrollableText/index.js} (64%) create mode 100644 js/src/ui/ScrollableText/scrollableText.css create mode 100644 js/src/ui/ScrollableText/scrollableText.js rename js/src/{modals/DeployContract/ErrorStep => views/Application/Requests}/index.js (95%) create mode 100644 js/src/views/Application/Requests/requests.css create mode 100644 js/src/views/Application/Requests/requests.js create mode 100644 js/src/views/Application/Requests/savedRequests.js create mode 100644 js/src/views/Application/Requests/savedRequests.spec.js diff --git a/js/src/api/format/input.js b/js/src/api/format/input.js index 34871c911..3a9cfee06 100644 --- a/js/src/api/format/input.js +++ b/js/src/api/format/input.js @@ -139,46 +139,46 @@ export function inOptionsCondition (condition) { return condition; } -export function inOptions (options) { - if (options) { - Object.keys(options).forEach((key) => { - switch (key) { - case 'to': - // Don't encode the `to` option if it's empty - // (eg. contract deployments) - if (options[key]) { - options[key] = inAddress(options[key]); - } - break; +export function inOptions (_options = {}) { + const options = { ..._options }; - case 'from': - options[key] = inAddress(options[key]); - break; + Object.keys(options).forEach((key) => { + switch (key) { + case 'to': + // Don't encode the `to` option if it's empty + // (eg. contract deployments) + if (options[key]) { + options.to = inAddress(options[key]); + } + break; - case 'condition': - options[key] = inOptionsCondition(options[key]); - break; + case 'from': + options[key] = inAddress(options[key]); + break; - case 'gas': - case 'gasPrice': - options[key] = inNumber16((new BigNumber(options[key])).round()); - break; + case 'condition': + options[key] = inOptionsCondition(options[key]); + break; - case 'minBlock': - options[key] = options[key] ? inNumber16(options[key]) : null; - break; + case 'gas': + case 'gasPrice': + options[key] = inNumber16((new BigNumber(options[key])).round()); + break; - case 'value': - case 'nonce': - options[key] = inNumber16(options[key]); - break; + case 'minBlock': + options[key] = options[key] ? inNumber16(options[key]) : null; + break; - case 'data': - options[key] = inData(options[key]); - break; - } - }); - } + case 'value': + case 'nonce': + options[key] = inNumber16(options[key]); + break; + + case 'data': + options[key] = inData(options[key]); + break; + } + }); return options; } diff --git a/js/src/api/rpc/parity/parity.js b/js/src/api/rpc/parity/parity.js index 26cfac505..752557d80 100644 --- a/js/src/api/rpc/parity/parity.js +++ b/js/src/api/rpc/parity/parity.js @@ -380,7 +380,7 @@ export default class Parity { .execute('parity_postSign', inAddress(address), inHex(hash)); } - postTransaction (options) { + postTransaction (options = {}) { return this._transport .execute('parity_postTransaction', inOptions(options)); } diff --git a/js/src/api/subscriptions/manager.js b/js/src/api/subscriptions/manager.js index 3284a82e7..6ca2f4015 100644 --- a/js/src/api/subscriptions/manager.js +++ b/js/src/api/subscriptions/manager.js @@ -27,6 +27,7 @@ const events = { 'parity_accountsInfo': { module: 'personal' }, 'parity_allAccountsInfo': { module: 'personal' }, 'parity_defaultAccount': { module: 'personal' }, + 'parity_postTransaction': { module: 'signer' }, 'eth_accounts': { module: 'personal' }, 'signer_requestsToConfirm': { module: 'signer' } }; @@ -83,7 +84,7 @@ export default class Manager { if (!engine.isStarted) { engine.start(); - } else { + } else if (error !== null || data !== null) { this._sendData(subscriptionId, error, data); } diff --git a/js/src/api/subscriptions/manager.spec.js b/js/src/api/subscriptions/manager.spec.js index 28d87d904..df708a36d 100644 --- a/js/src/api/subscriptions/manager.spec.js +++ b/js/src/api/subscriptions/manager.spec.js @@ -124,7 +124,7 @@ describe('api/subscriptions/manager', () => { }); }); - it('does not call the callback after unsibscription', () => { + it('does not call the callback after unsubscription', () => { expect(cb).to.have.been.calledWith(null, 'test'); expect(cb).to.not.have.been.calledWith(null, 'test2'); }); diff --git a/js/src/api/subscriptions/signer.js b/js/src/api/subscriptions/signer.js index cd1f1de62..d4acce163 100644 --- a/js/src/api/subscriptions/signer.js +++ b/js/src/api/subscriptions/signer.js @@ -14,6 +14,8 @@ // You should have received a copy of the GNU General Public License // along with Parity. If not, see . +import { outTransaction } from '../format/output'; + export default class Signer { constructor (updateSubscriptions, api, subscriber) { this._subscriber = subscriber; @@ -58,6 +60,15 @@ export default class Signer { .catch(nextTimeout); } + _postTransaction (data) { + const request = { + transaction: outTransaction(data.params[0]), + requestId: data.json.result.result + }; + + this._updateSubscriptions('parity_postTransaction', null, request); + } + _loggingSubscribe () { return this._subscriber.subscribe('logging', (error, data) => { if (error || !data) { @@ -65,11 +76,15 @@ export default class Signer { } switch (data.method) { - case 'parity_postTransaction': - case 'eth_sendTranasction': + case 'eth_sendTransaction': case 'eth_sendRawTransaction': this._listRequests(false); return; + + case 'parity_postTransaction': + this._postTransaction(data); + this._listRequests(false); + return; } }); } diff --git a/js/src/modals/CreateWallet/createWallet.js b/js/src/modals/CreateWallet/createWallet.js index b00478a53..63be12d34 100644 --- a/js/src/modals/CreateWallet/createWallet.js +++ b/js/src/modals/CreateWallet/createWallet.js @@ -17,9 +17,12 @@ import { observer } from 'mobx-react'; import React, { Component, PropTypes } from 'react'; import { FormattedMessage } from 'react-intl'; +import { connect } from 'react-redux'; +import { bindActionCreators } from 'redux'; -import { BusyStep, Button, Portal, TxHash } from '~/ui'; +import { Button, Portal } from '~/ui'; import { CancelIcon, DoneIcon, NextIcon } from '~/ui/Icons'; +import { setRequest } from '~/redux/providers/requestsActions'; import WalletType from './WalletType'; import WalletDetails from './WalletDetails'; @@ -27,56 +30,25 @@ import WalletInfo from './WalletInfo'; import CreateWalletStore from './createWalletStore'; @observer -export default class CreateWallet extends Component { +export class CreateWallet extends Component { static contextTypes = { api: PropTypes.object.isRequired }; static propTypes = { accounts: PropTypes.object.isRequired, - onClose: PropTypes.func.isRequired + onClose: PropTypes.func.isRequired, + onSetRequest: PropTypes.func.isRequired }; - store = new CreateWalletStore(this.context.api, this.props.accounts); + store = new CreateWalletStore(this.context.api, this.props); render () { - const { stage, steps, waiting, rejected } = this.store; - - if (rejected) { - return ( - - } - > - - } - state={ - - } - /> - - ); - } + const { stage, steps } = this.store; return ( - } - state={ this.store.deployState } - > - { - this.store.txhash - ? - : null - } - - ); - case 'INFO': return ( ); - const closeBtn = ( -