Ethereum-types and various libs upgrade (#315)

* Upgrade Eth types

ethereum-types -> 0.9.2
rlp -> 0.4.6
keccak-hash -> 0.5.0
parity-crypto -> 0.6.2
ethabi -> 0.12.0
ethabi-derive -> 0.12.0
ethabi-contract -> 0.11.0
ethbloom -> 0.9.1
rand -> 0.7.3
trie-standardmap -> 0.15.2
triehash -> 0.5.0

* backport #10714. Small changes, merge fixes

Co-authored-by: mdben1247 <mdben1247@users.noreply.github.com>
This commit is contained in:
rakita
2021-03-12 10:12:42 +01:00
committed by GitHub
parent 3f8e0cfec4
commit a0f406e26b
273 changed files with 3051 additions and 4775 deletions

828
Cargo.lock generated

File diff suppressed because it is too large Load Diff

View File

@@ -47,12 +47,13 @@ ethcore-miner = { path = "crates/concensus/miner" }
ethcore-network = { path = "crates/net/network" }
ethcore-service = { path = "crates/ethcore/service" }
ethcore-sync = { path = "crates/ethcore/sync" }
ethereum-types = "0.4"
ethereum-types = "0.9.2"
ethkey = { path = "crates/accounts/ethkey" }
ethstore = { path = "crates/accounts/ethstore" }
fetch = { path = "crates/net/fetch" }
node-filter = { path = "crates/net/node-filter" }
rlp = { version = "0.3.0", features = ["ethereum"] }
parity-crypto = { version = "0.6.2", features = [ "publickey" ] }
rlp = { version = "0.4.6" }
cli-signer= { path = "crates/util/cli-signer" }
parity-daemonize = "0.3"
parity-local-store = { path = "crates/concensus/miner/local-store" }
@@ -62,7 +63,7 @@ parity-version = { path = "crates/util/version" }
parity-path = "0.1"
dir = { path = "crates/util/dir" }
panic_hook = { path = "crates/util/panic-hook" }
keccak-hash = "0.1"
keccak-hash = "0.5.0"
migration-rocksdb = { path = "crates/db/migration-rocksdb" }
kvdb = "0.1"
kvdb-rocksdb = "0.1.3"
@@ -130,6 +131,3 @@ members = [
"bin/evmbin",
"bin/chainspec"
]
[patch.crates-io]
heapsize = { git = "https://github.com/cheme/heapsize.git", branch = "ec-macfix" }

View File

@@ -9,6 +9,7 @@ docopt = "1.0"
env_logger = "0.5"
ethkey = { path = "../../crates/accounts/ethkey" }
panic_hook = { path = "../../crates/util/panic-hook" }
parity-crypto = { version = "0.6.2", features = [ "publickey" ] }
parity-wordlist="1.3"
rustc-hex = "1.0"
serde = "1.0"

View File

@@ -18,6 +18,7 @@ extern crate docopt;
extern crate env_logger;
extern crate ethkey;
extern crate panic_hook;
extern crate parity_crypto as crypto;
extern crate parity_wordlist;
extern crate rustc_hex;
extern crate serde;
@@ -28,11 +29,11 @@ extern crate serde_derive;
use std::{env, fmt, io, num::ParseIntError, process, sync};
use docopt::Docopt;
use ethkey::{
brain_recover, sign, verify_address, verify_public, Brain, BrainPrefix, Error as EthkeyError,
Generator, KeyPair, Prefix, Random,
use crypto::publickey::{
sign, verify_address, verify_public, Error as EthkeyError, Generator, KeyPair, Random,
};
use docopt::Docopt;
use ethkey::{brain_recover, Brain, BrainPrefix, Prefix};
use rustc_hex::{FromHex, FromHexError};
const USAGE: &'static str = r#"
@@ -202,15 +203,13 @@ where
let result = if args.flag_brain {
let phrase = args.arg_secret_or_phrase;
let phrase_info = validate_phrase(&phrase);
let keypair = Brain::new(phrase)
.generate()
.expect("Brain wallet generator is infallible; qed");
let keypair = Brain::new(phrase).generate();
(keypair, Some(phrase_info))
} else {
let secret = args
.arg_secret_or_phrase
.parse()
.map_err(|_| EthkeyError::InvalidSecret)?;
.map_err(|_| EthkeyError::InvalidSecretKey)?;
(KeyPair::from_secret(secret)?, None)
};
Ok(display(result, display_mode))
@@ -223,7 +222,7 @@ where
let phrase = format!("recovery phrase: {}", brain.phrase());
(keypair, Some(phrase))
} else {
(Random.generate()?, None)
(Random.generate(), None)
}
} else if args.cmd_prefix {
let prefix = args.arg_prefix.from_hex()?;
@@ -254,7 +253,7 @@ where
let secret = args
.arg_secret
.parse()
.map_err(|_| EthkeyError::InvalidSecret)?;
.map_err(|_| EthkeyError::InvalidSecretKey)?;
let message = args
.arg_message
.parse()
@@ -274,7 +273,7 @@ where
let public = args
.arg_public
.parse()
.map_err(|_| EthkeyError::InvalidPublic)?;
.map_err(|_| EthkeyError::InvalidPublicKey)?;
verify_public(&public, &signature, &message)?
} else if args.cmd_address {
let address = args
@@ -301,7 +300,7 @@ where
while let Some(phrase) = it.next() {
i += 1;
let keypair = Brain::new(phrase.clone()).generate().unwrap();
let keypair = Brain::new(phrase.clone()).generate();
if keypair.address() == address {
return Ok(Some((phrase, keypair)));
}

View File

@@ -13,7 +13,7 @@ common-types = { path = "../../crates/ethcore/types", features = ["test-helpers"
docopt = "1.0"
env_logger = "0.5"
ethcore = { path = "../../crates/ethcore", features = ["test-helpers", "json-tests", "to-pod-full"] }
ethereum-types = "0.4"
ethereum-types = "0.9.2"
ethjson = { path = "../../crates/ethjson" }
evm = { path = "../../crates/vm/evm" }
panic_hook = { path = "../../crates/util/panic-hook" }

View File

@@ -22,7 +22,7 @@ use super::config::Config;
use bytes::ToPretty;
use display;
use ethcore::trace;
use ethereum_types::{H256, U256};
use ethereum_types::{BigEndianHash, H256, U256};
use info as vm;
/// JSON formatting informant.
@@ -208,7 +208,10 @@ impl trace::VMTracer for Informant {
}
if let Some((pos, val)) = store_diff {
informant.storage.insert(pos.into(), val.into());
informant.storage.insert(
BigEndianHash::from_uint(&pos),
BigEndianHash::from_uint(&val),
);
}
if !informant.subtraces.is_empty() {

View File

@@ -22,7 +22,7 @@ use super::config::Config;
use bytes::ToPretty;
use display;
use ethcore::{pod_state, trace};
use ethereum_types::{H256, U256};
use ethereum_types::{BigEndianHash, H256, U256};
use info as vm;
pub trait Writer: io::Write + Send + Sized {
@@ -237,7 +237,10 @@ impl<Trace: Writer, Out: Writer> trace::VMTracer for Informant<Trace, Out> {
let subdepth = self.subdepth;
Self::with_informant_in_depth(self, subdepth, |informant: &mut Informant<Trace, Out>| {
if let Some((pos, val)) = store_written {
informant.storage.insert(pos.into(), val.into());
informant.storage.insert(
BigEndianHash::from_uint(&pos),
BigEndianHash::from_uint(&val),
);
}
});
}

View File

@@ -103,7 +103,7 @@ pub fn run_action<T: Informant>(
Ok(r) => (Ok(r.return_data.to_vec()), Some(r.gas_left)),
Err(err) => (Err(err), None),
};
(result.0, 0.into(), None, result.1, informant.drain())
(result.0, H256::zero(), None, result.1, informant.drain())
},
)
}
@@ -262,6 +262,7 @@ where
#[cfg(test)]
pub mod tests {
use super::*;
use ethereum_types::Address;
use rustc_hex::FromHex;
use std::sync::Arc;
use tempdir::TempDir;
@@ -291,7 +292,7 @@ pub mod tests {
let (inf, res) = informant(Config::default());
let mut params = ActionParams::default();
params.code_address = 0x20.into();
params.code_address = Address::from_low_u64_be(0x20);
params.gas = 0xffff.into();
let spec = ::ethcore::ethereum::load(None, include_bytes!("../res/testchain.json"));

View File

@@ -429,6 +429,7 @@ fn die<T: fmt::Display>(msg: T) -> ! {
mod tests {
use super::{Args, USAGE};
use docopt::Docopt;
use ethereum_types::Address;
fn run<T: AsRef<str>>(args: &[T]) -> Args {
Docopt::new(USAGE)
@@ -468,8 +469,8 @@ mod tests {
assert_eq!(args.flag_std_out_only, true);
assert_eq!(args.gas(), Ok(1.into()));
assert_eq!(args.gas_price(), Ok(2.into()));
assert_eq!(args.from(), Ok(3.into()));
assert_eq!(args.to(), Ok(4.into()));
assert_eq!(args.from(), Ok(Address::from_low_u64_be(3)));
assert_eq!(args.to(), Ok(Address::from_low_u64_be(4)));
assert_eq!(args.code(), Ok(Some(vec![05])));
assert_eq!(args.data(), Ok(Some(vec![06])));
assert_eq!(args.flag_chain, Some("./testfile".to_owned()));

View File

@@ -16,8 +16,9 @@
use std::sync::Arc;
use crypto::publickey;
use dir::Directories;
use ethereum_types::Address;
use ethereum_types::{Address, H160};
use ethkey::Password;
use params::{AccountsConfig, SpecType};
@@ -70,6 +71,7 @@ mod accounts {
#[cfg(feature = "accounts")]
mod accounts {
use super::*;
use std::str::FromStr;
use upgrade::upgrade_key_location;
pub use accounts::AccountProvider;
@@ -103,7 +105,8 @@ mod accounts {
| SpecType::Goerli
| SpecType::Sokol
| SpecType::Dev => vec![],
_ => vec!["00a329c0648769a73afac7f9381e08fb43dbea72".into()],
_ => vec![H160::from_str("00a329c0648769a73afac7f9381e08fb43dbea72")
.expect("the string is valid hex; qed")],
},
};
@@ -216,9 +219,11 @@ mod accounts {
}
fn insert_dev_account(account_provider: &AccountProvider) {
let secret: ethkey::Secret =
"4d5db4107d237df6a3d58ee5f70ae63d73d7658d4026f2eefd2f204c81682cb7".into();
let dev_account = ethkey::KeyPair::from_secret(secret.clone())
let secret = publickey::Secret::from_str(
"4d5db4107d237df6a3d58ee5f70ae63d73d7658d4026f2eefd2f204c81682cb7",
)
.expect("Valid account;qed");
let dev_account = publickey::KeyPair::from_secret(secret.clone())
.expect("Valid secret produces valid key;qed");
if !account_provider.has_account(dev_account.address()) {
match account_provider.insert_account(secret, &Password::from(String::new())) {

View File

@@ -17,6 +17,7 @@
use ansi_term::Colour;
use bytes::Bytes;
use cli::{Args, ArgsError};
use crypto::publickey::{Public, Secret};
use ethcore::{
client::VMType,
miner::{stratum, MinerOptions},
@@ -24,7 +25,6 @@ use ethcore::{
verification::queue::VerifierSettings,
};
use ethereum_types::{Address, H256, U256};
use ethkey::{Public, Secret};
use hash::keccak;
use metrics::MetricsConfiguration;
use miner::pool;
@@ -810,7 +810,7 @@ impl Configuration {
ret.public_address = public.map(|p| format!("{}", p));
ret.use_secret = match self.args.arg_node_key.as_ref().map(|s| {
s.parse::<Secret>()
.or_else(|_| Secret::from_unsafe_slice(&keccak(s)))
.or_else(|_| Secret::import_key(keccak(s).as_bytes()))
.map_err(|e| format!("Invalid key: {:?}", e))
}) {
None => None,

View File

@@ -21,7 +21,7 @@ use ethcore::{
client::{BlockId, ClientConfig, DatabaseCompactionProfile, Mode, VMType, VerifierType},
miner::{Penalization, PendingSet},
};
use ethereum_types::{clean_0x, Address, U256};
use ethereum_types::{Address, U256};
use ethkey::Password;
use journaldb::Algorithm;
use miner::pool::PrioritizationStrategy;
@@ -39,6 +39,14 @@ pub fn to_duration(s: &str) -> Result<Duration, String> {
to_seconds(s).map(Duration::from_secs)
}
fn clean_0x(s: &str) -> &str {
if s.starts_with("0x") {
&s[2..]
} else {
s
}
}
fn to_seconds(s: &str) -> Result<u64, String> {
let bad = |_| {
format!(

View File

@@ -61,6 +61,7 @@ extern crate keccak_hash as hash;
extern crate kvdb;
extern crate node_filter;
extern crate parity_bytes as bytes;
extern crate parity_crypto as crypto;
extern crate parity_local_store as local_store;
extern crate parity_path as path;
extern crate parity_rpc;

View File

@@ -14,6 +14,7 @@
// You should have received a copy of the GNU General Public License
// along with OpenEthereum. If not, see <http://www.gnu.org/licenses/>.
use crypto::publickey;
use ethkey::Password;
use ethstore::PresaleWallet;
use helpers::{password_from_file, password_prompt};
@@ -44,7 +45,7 @@ pub fn execute(cmd: ImportWallet) -> Result<String, String> {
}
#[cfg(feature = "accounts")]
pub fn import_account(cmd: &ImportWallet, kp: ethkey::KeyPair, password: Password) {
pub fn import_account(cmd: &ImportWallet, kp: publickey::KeyPair, password: Password) {
use accounts::{AccountProvider, AccountProviderSettings};
use ethstore::{accounts_dir::RootDiskDirectory, EthStore};
@@ -57,4 +58,4 @@ pub fn import_account(cmd: &ImportWallet, kp: ethkey::KeyPair, password: Passwor
}
#[cfg(not(feature = "accounts"))]
pub fn import_account(_cmd: &ImportWallet, _kp: ethkey::KeyPair, _password: Password) {}
pub fn import_account(_cmd: &ImportWallet, _kp: publickey::KeyPair, _password: Password) {}

View File

@@ -16,6 +16,7 @@
use std::{
any::Any,
str::FromStr,
sync::{atomic, Arc, Weak},
thread,
time::{Duration, Instant},
@@ -606,7 +607,10 @@ pub fn execute(cmd: RunCmd, logger: Arc<RotatingLogger>) -> Result<RunningClient
fn verification_bad_blocks(spec: &SpecType) -> Vec<H256> {
match *spec {
SpecType::Ropsten => {
vec!["1eac3d16c642411f13c287e29144c6f58fda859407c8f24c38deb168e1040714".into()]
vec![
H256::from_str("1eac3d16c642411f13c287e29144c6f58fda859407c8f24c38deb168e1040714")
.expect("Valid hex string"),
]
}
_ => vec![],
}

View File

@@ -15,10 +15,11 @@
// along with OpenEthereum. If not, see <http://www.gnu.org/licenses/>.
use account_utils::AccountProvider;
use crypto::publickey::{Public, Secret};
use dir::{default_data_path, helpers::replace_home};
use ethcore::{client::Client, miner::Miner};
use ethereum_types::Address;
use ethkey::{Password, Public, Secret};
use ethkey::Password;
use parity_runtime::Executor;
use std::{collections::BTreeMap, sync::Arc};
use sync::SyncProvider;

View File

@@ -12,11 +12,12 @@ common-types = { path = "../ethcore/types" }
ethkey = { path = "ethkey" }
ethstore = { path = "ethstore" }
log = "0.4"
parity-crypto = { version = "0.6.2", features = [ "publickey" ] }
parking_lot = "0.7"
serde = "1.0"
serde_derive = "1.0"
serde_json = "1.0"
[dev-dependencies]
ethereum-types = "0.4"
ethereum-types = "0.9.2"
tempdir = "0.3"

View File

@@ -6,15 +6,15 @@ authors = ["Parity Technologies <admin@parity.io>"]
[dependencies]
edit-distance = "2.0"
parity-crypto = "0.3.0"
eth-secp256k1 = { git = "https://github.com/paritytech/rust-secp256k1", rev = "ccc06e7480148b723eb44ac56cf4d20eec380b6f" }
ethereum-types = "0.4"
parity-crypto = { version = "0.6.2", features = ["publickey"] }
eth-secp256k1 = { git = "https://github.com/paritytech/rust-secp256k1", rev = "9791e79f21a5309dcb6e0bd254b1ef88fca2f1f4" }
ethereum-types = "0.9.2"
lazy_static = "1.0"
log = "0.4"
memzero = { path = "../../../crates/util/memzero" }
parity-wordlist = "1.3"
quick-error = "1.2.2"
rand = "0.4"
rand = "0.7.3"
rustc-hex = "1.0"
serde = "1.0"
serde_derive = "1.0"

View File

@@ -14,8 +14,10 @@
// You should have received a copy of the GNU General Public License
// along with OpenEthereum. If not, see <http://www.gnu.org/licenses/>.
use super::{Generator, KeyPair, Secret};
use keccak::Keccak256;
use parity_crypto::{
publickey::{KeyPair, Secret},
Keccak256,
};
use parity_wordlist;
/// Simple brainwallet.
@@ -29,12 +31,8 @@ impl Brain {
pub fn validate_phrase(phrase: &str, expected_words: usize) -> Result<(), ::WordlistError> {
parity_wordlist::validate_phrase(phrase, expected_words)
}
}
impl Generator for Brain {
type Error = ::Void;
fn generate(&mut self) -> Result<KeyPair, Self::Error> {
pub fn generate(&mut self) -> KeyPair {
let seed = self.0.clone();
let mut secret = seed.into_bytes().keccak256();
@@ -45,12 +43,10 @@ impl Generator for Brain {
match i > 16384 {
false => i += 1,
true => {
if let Ok(pair) =
Secret::from_unsafe_slice(&secret).and_then(KeyPair::from_secret)
{
if let Ok(pair) = Secret::import_key(&secret).and_then(KeyPair::from_secret) {
if pair.address()[0] == 0 {
trace!("Testing: {}, got: {:?}", self.0, pair.address());
return Ok(pair);
return pair;
}
}
}
@@ -62,13 +58,12 @@ impl Generator for Brain {
#[cfg(test)]
mod tests {
use Brain;
use Generator;
#[test]
fn test_brain() {
let words = "this is sparta!".to_owned();
let first_keypair = Brain::new(words.clone()).generate().unwrap();
let second_keypair = Brain::new(words.clone()).generate().unwrap();
let first_keypair = Brain::new(words.clone()).generate();
let second_keypair = Brain::new(words.clone()).generate();
assert_eq!(first_keypair.secret(), second_keypair.secret());
}
}

View File

@@ -14,7 +14,8 @@
// You should have received a copy of the GNU General Public License
// along with OpenEthereum. If not, see <http://www.gnu.org/licenses/>.
use super::{Brain, Error, Generator, KeyPair};
use super::Brain;
use parity_crypto::publickey::{Error, KeyPair};
use parity_wordlist as wordlist;
/// Tries to find brain-seed keypair with address starting with given prefix.
@@ -38,16 +39,12 @@ impl BrainPrefix {
pub fn phrase(&self) -> &str {
&self.last_phrase
}
}
impl Generator for BrainPrefix {
type Error = Error;
fn generate(&mut self) -> Result<KeyPair, Error> {
pub fn generate(&mut self) -> Result<KeyPair, Error> {
for _ in 0..self.iterations {
let phrase = wordlist::random_phrase(self.no_of_words);
let keypair = Brain::new(phrase.clone()).generate().unwrap();
if keypair.address().starts_with(&self.prefix) {
let keypair = Brain::new(phrase.clone()).generate();
if keypair.address().as_ref().starts_with(&self.prefix) {
self.last_phrase = phrase;
return Ok(keypair);
}
@@ -60,7 +57,6 @@ impl Generator for BrainPrefix {
#[cfg(test)]
mod tests {
use BrainPrefix;
use Generator;
#[test]
fn prefix_generator() {
@@ -68,6 +64,6 @@ mod tests {
let keypair = BrainPrefix::new(prefix.clone(), usize::max_value(), 12)
.generate()
.unwrap();
assert!(keypair.address().starts_with(&prefix));
assert!(keypair.address().as_bytes().starts_with(&prefix));
}
}

View File

@@ -17,9 +17,10 @@
use std::collections::HashSet;
use edit_distance::edit_distance;
use parity_crypto::publickey::Address;
use parity_wordlist;
use super::{Address, Brain, Generator};
use super::Brain;
/// Tries to find a phrase for address, given the number
/// of expected words and a partial phrase.
@@ -32,9 +33,7 @@ pub fn brain_recover(
) -> Option<String> {
let it = PhrasesIterator::from_known_phrase(known_phrase, expected_words);
for phrase in it {
let keypair = Brain::new(phrase.clone())
.generate()
.expect("Brain wallets are infallible; qed");
let keypair = Brain::new(phrase.clone()).generate();
trace!("Testing: {}, got: {:?}", phrase, keypair.address());
if &keypair.address() == address {
return Some(phrase);

View File

@@ -1,202 +0,0 @@
// Copyright 2015-2020 Parity Technologies (UK) Ltd.
// This file is part of OpenEthereum.
// OpenEthereum 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.
// OpenEthereum 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 OpenEthereum. If not, see <http://www.gnu.org/licenses/>.
#![allow(deprecated)]
use parity_crypto::error::SymmError;
use secp256k1;
use std::io;
quick_error! {
#[derive(Debug)]
pub enum Error {
Secp(e: secp256k1::Error) {
display("secp256k1 error: {}", e)
cause(e)
from()
}
Io(e: io::Error) {
display("i/o error: {}", e)
cause(e)
from()
}
InvalidMessage {
display("invalid message")
}
Symm(e: SymmError) {
cause(e)
from()
}
}
}
/// ECDH functions
pub mod ecdh {
use super::Error;
use secp256k1::{self, ecdh, key};
use Public;
use Secret;
use SECP256K1;
/// Agree on a shared secret
pub fn agree(secret: &Secret, public: &Public) -> Result<Secret, Error> {
let context = &SECP256K1;
let pdata = {
let mut temp = [4u8; 65];
(&mut temp[1..65]).copy_from_slice(&public[0..64]);
temp
};
let publ = key::PublicKey::from_slice(context, &pdata)?;
let sec = key::SecretKey::from_slice(context, &secret)?;
let shared = ecdh::SharedSecret::new_raw(context, &publ, &sec);
Secret::from_unsafe_slice(&shared[0..32])
.map_err(|_| Error::Secp(secp256k1::Error::InvalidSecretKey))
}
}
/// ECIES function
pub mod ecies {
use super::{ecdh, Error};
use ethereum_types::H128;
use parity_crypto::{aes, digest, hmac, is_equal};
use Generator;
use Public;
use Random;
use Secret;
/// Encrypt a message with a public key, writing an HMAC covering both
/// the plaintext and authenticated data.
///
/// Authenticated data may be empty.
pub fn encrypt(public: &Public, auth_data: &[u8], plain: &[u8]) -> Result<Vec<u8>, Error> {
let r = Random.generate()?;
let z = ecdh::agree(r.secret(), public)?;
let mut key = [0u8; 32];
kdf(&z, &[0u8; 0], &mut key);
let ekey = &key[0..16];
let mkey = hmac::SigKey::sha256(&digest::sha256(&key[16..32]));
let mut msg = vec![0u8; 1 + 64 + 16 + plain.len() + 32];
msg[0] = 0x04u8;
{
let msgd = &mut msg[1..];
msgd[0..64].copy_from_slice(r.public());
let iv = H128::random();
msgd[64..80].copy_from_slice(&iv);
{
let cipher = &mut msgd[(64 + 16)..(64 + 16 + plain.len())];
aes::encrypt_128_ctr(ekey, &iv, plain, cipher)?;
}
let mut hmac = hmac::Signer::with(&mkey);
{
let cipher_iv = &msgd[64..(64 + 16 + plain.len())];
hmac.update(cipher_iv);
}
hmac.update(auth_data);
let sig = hmac.sign();
msgd[(64 + 16 + plain.len())..].copy_from_slice(&sig);
}
Ok(msg)
}
/// Decrypt a message with a secret key, checking HMAC for ciphertext
/// and authenticated data validity.
pub fn decrypt(secret: &Secret, auth_data: &[u8], encrypted: &[u8]) -> Result<Vec<u8>, Error> {
let meta_len = 1 + 64 + 16 + 32;
if encrypted.len() < meta_len || encrypted[0] < 2 || encrypted[0] > 4 {
return Err(Error::InvalidMessage); //invalid message: publickey
}
let e = &encrypted[1..];
let p = Public::from_slice(&e[0..64]);
let z = ecdh::agree(secret, &p)?;
let mut key = [0u8; 32];
kdf(&z, &[0u8; 0], &mut key);
let ekey = &key[0..16];
let mkey = hmac::SigKey::sha256(&digest::sha256(&key[16..32]));
let clen = encrypted.len() - meta_len;
let cipher_with_iv = &e[64..(64 + 16 + clen)];
let cipher_iv = &cipher_with_iv[0..16];
let cipher_no_iv = &cipher_with_iv[16..];
let msg_mac = &e[(64 + 16 + clen)..];
// Verify tag
let mut hmac = hmac::Signer::with(&mkey);
hmac.update(cipher_with_iv);
hmac.update(auth_data);
let mac = hmac.sign();
if !is_equal(&mac.as_ref()[..], msg_mac) {
return Err(Error::InvalidMessage);
}
let mut msg = vec![0u8; clen];
aes::decrypt_128_ctr(ekey, cipher_iv, cipher_no_iv, &mut msg[..])?;
Ok(msg)
}
fn kdf(secret: &Secret, s1: &[u8], dest: &mut [u8]) {
// SEC/ISO/Shoup specify counter size SHOULD be equivalent
// to size of hash output, however, it also notes that
// the 4 bytes is okay. NIST specifies 4 bytes.
let mut ctr = 1u32;
let mut written = 0usize;
while written < dest.len() {
let mut hasher = digest::Hasher::sha256();
let ctrs = [
(ctr >> 24) as u8,
(ctr >> 16) as u8,
(ctr >> 8) as u8,
ctr as u8,
];
hasher.update(&ctrs);
hasher.update(secret);
hasher.update(s1);
let d = hasher.finish();
&mut dest[written..(written + 32)].copy_from_slice(&d);
written += 32;
ctr += 1;
}
}
}
#[cfg(test)]
mod tests {
use super::ecies;
use Generator;
use Random;
#[test]
fn ecies_shared() {
let kp = Random.generate().unwrap();
let message = b"So many books, so little time";
let shared = b"shared";
let wrong_shared = b"incorrect";
let encrypted = ecies::encrypt(kp.public(), shared, message).unwrap();
assert!(encrypted[..] != message[..]);
assert_eq!(encrypted[0], 0x04);
assert!(ecies::decrypt(kp.secret(), wrong_shared, &encrypted).is_err());
let decrypted = ecies::decrypt(kp.secret(), shared, &encrypted).unwrap();
assert_eq!(decrypted[..message.len()], message[..]);
}
}

View File

@@ -1,81 +0,0 @@
// Copyright 2015-2020 Parity Technologies (UK) Ltd.
// This file is part of OpenEthereum.
// OpenEthereum 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.
// OpenEthereum 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 OpenEthereum. If not, see <http://www.gnu.org/licenses/>.
use std::{error, fmt};
#[derive(Debug)]
/// Crypto error
pub enum Error {
/// Invalid secret key
InvalidSecret,
/// Invalid public key
InvalidPublic,
/// Invalid address
InvalidAddress,
/// Invalid EC signature
InvalidSignature,
/// Invalid AES message
InvalidMessage,
/// IO Error
Io(::std::io::Error),
/// Custom
Custom(String),
}
impl fmt::Display for Error {
fn fmt(&self, f: &mut fmt::Formatter) -> fmt::Result {
let msg = match *self {
Error::InvalidSecret => "Invalid secret".into(),
Error::InvalidPublic => "Invalid public".into(),
Error::InvalidAddress => "Invalid address".into(),
Error::InvalidSignature => "Invalid EC signature".into(),
Error::InvalidMessage => "Invalid AES message".into(),
Error::Io(ref err) => format!("I/O error: {}", err),
Error::Custom(ref s) => s.clone(),
};
f.write_fmt(format_args!("Crypto error ({})", msg))
}
}
impl error::Error for Error {
fn description(&self) -> &str {
"Crypto error"
}
}
impl Into<String> for Error {
fn into(self) -> String {
format!("{}", self)
}
}
impl From<::secp256k1::Error> for Error {
fn from(e: ::secp256k1::Error) -> Error {
match e {
::secp256k1::Error::InvalidMessage => Error::InvalidMessage,
::secp256k1::Error::InvalidPublicKey => Error::InvalidPublic,
::secp256k1::Error::InvalidSecretKey => Error::InvalidSecret,
_ => Error::InvalidSignature,
}
}
}
impl From<::std::io::Error> for Error {
fn from(err: ::std::io::Error) -> Error {
Error::Io(err)
}
}

View File

@@ -1,589 +0,0 @@
// Copyright 2015-2020 Parity Technologies (UK) Ltd.
// This file is part of OpenEthereum.
// OpenEthereum 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.
// OpenEthereum 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 OpenEthereum. If not, see <http://www.gnu.org/licenses/>.
//! Extended keys
pub use self::derivation::Error as DerivationError;
use ethereum_types::H256;
use secret::Secret;
use Public;
/// Represents label that can be stored as a part of key derivation
pub trait Label {
/// Length of the data that label occupies
fn len() -> usize;
/// Store label data to the key derivation sequence
/// Must not use more than `len()` bytes from slice
fn store(&self, target: &mut [u8]);
}
impl Label for u32 {
fn len() -> usize {
4
}
fn store(&self, target: &mut [u8]) {
let bytes = self.to_be_bytes();
target[0..4].copy_from_slice(&bytes);
}
}
/// Key derivation over generic label `T`
pub enum Derivation<T: Label> {
/// Soft key derivation (allow proof of parent)
Soft(T),
/// Hard key derivation (does not allow proof of parent)
Hard(T),
}
impl From<u32> for Derivation<u32> {
fn from(index: u32) -> Self {
if index < (2 << 30) {
Derivation::Soft(index)
} else {
Derivation::Hard(index)
}
}
}
impl Label for H256 {
fn len() -> usize {
32
}
fn store(&self, target: &mut [u8]) {
self.copy_to(&mut target[0..32]);
}
}
/// Extended secret key, allows deterministic derivation of subsequent keys.
pub struct ExtendedSecret {
secret: Secret,
chain_code: H256,
}
impl ExtendedSecret {
/// New extended key from given secret and chain code.
pub fn with_code(secret: Secret, chain_code: H256) -> ExtendedSecret {
ExtendedSecret {
secret: secret,
chain_code: chain_code,
}
}
/// New extended key from given secret with the random chain code.
pub fn new_random(secret: Secret) -> ExtendedSecret {
ExtendedSecret::with_code(secret, H256::random())
}
/// New extended key from given secret.
/// Chain code will be derived from the secret itself (in a deterministic way).
pub fn new(secret: Secret) -> ExtendedSecret {
let chain_code = derivation::chain_code(*secret);
ExtendedSecret::with_code(secret, chain_code)
}
/// Derive new private key
pub fn derive<T>(&self, index: Derivation<T>) -> ExtendedSecret
where
T: Label,
{
let (derived_key, next_chain_code) =
derivation::private(*self.secret, self.chain_code, index);
let derived_secret = Secret::from(derived_key.0);
ExtendedSecret::with_code(derived_secret, next_chain_code)
}
/// Private key component of the extended key.
pub fn as_raw(&self) -> &Secret {
&self.secret
}
}
/// Extended public key, allows deterministic derivation of subsequent keys.
pub struct ExtendedPublic {
public: Public,
chain_code: H256,
}
impl ExtendedPublic {
/// New extended public key from known parent and chain code
pub fn new(public: Public, chain_code: H256) -> Self {
ExtendedPublic {
public: public,
chain_code: chain_code,
}
}
/// Create new extended public key from known secret
pub fn from_secret(secret: &ExtendedSecret) -> Result<Self, DerivationError> {
Ok(ExtendedPublic::new(
derivation::point(**secret.as_raw())?,
secret.chain_code.clone(),
))
}
/// Derive new public key
/// Operation is defined only for index belongs [0..2^31)
pub fn derive<T>(&self, index: Derivation<T>) -> Result<Self, DerivationError>
where
T: Label,
{
let (derived_key, next_chain_code) =
derivation::public(self.public, self.chain_code, index)?;
Ok(ExtendedPublic::new(derived_key, next_chain_code))
}
pub fn public(&self) -> &Public {
&self.public
}
}
pub struct ExtendedKeyPair {
secret: ExtendedSecret,
public: ExtendedPublic,
}
impl ExtendedKeyPair {
pub fn new(secret: Secret) -> Self {
let extended_secret = ExtendedSecret::new(secret);
let extended_public = ExtendedPublic::from_secret(&extended_secret)
.expect("Valid `Secret` always produces valid public; qed");
ExtendedKeyPair {
secret: extended_secret,
public: extended_public,
}
}
pub fn with_code(secret: Secret, public: Public, chain_code: H256) -> Self {
ExtendedKeyPair {
secret: ExtendedSecret::with_code(secret, chain_code.clone()),
public: ExtendedPublic::new(public, chain_code),
}
}
pub fn with_secret(secret: Secret, chain_code: H256) -> Self {
let extended_secret = ExtendedSecret::with_code(secret, chain_code);
let extended_public = ExtendedPublic::from_secret(&extended_secret)
.expect("Valid `Secret` always produces valid public; qed");
ExtendedKeyPair {
secret: extended_secret,
public: extended_public,
}
}
pub fn with_seed(seed: &[u8]) -> Result<ExtendedKeyPair, DerivationError> {
let (master_key, chain_code) = derivation::seed_pair(seed);
Ok(ExtendedKeyPair::with_secret(
Secret::from_unsafe_slice(&*master_key).map_err(|_| DerivationError::InvalidSeed)?,
chain_code,
))
}
pub fn secret(&self) -> &ExtendedSecret {
&self.secret
}
pub fn public(&self) -> &ExtendedPublic {
&self.public
}
pub fn derive<T>(&self, index: Derivation<T>) -> Result<Self, DerivationError>
where
T: Label,
{
let derived = self.secret.derive(index);
Ok(ExtendedKeyPair {
public: ExtendedPublic::from_secret(&derived)?,
secret: derived,
})
}
}
// Derivation functions for private and public keys
// Work is based on BIP0032
// https://github.com/bitcoin/bips/blob/master/bip-0032.mediawiki
mod derivation {
use super::{Derivation, Label};
use ethereum_types::{H256, H512, U256, U512};
use keccak;
use math::curve_order;
use parity_crypto::hmac;
use secp256k1::key::{PublicKey, SecretKey};
use SECP256K1;
#[derive(Debug)]
pub enum Error {
InvalidHardenedUse,
InvalidPoint,
MissingIndex,
InvalidSeed,
}
// Deterministic derivation of the key using secp256k1 elliptic curve.
// Derivation can be either hardened or not.
// For hardened derivation, pass u32 index at least 2^31 or custom Derivation::Hard(T) enum
//
// Can panic if passed `private_key` is not a valid secp256k1 private key
// (outside of (0..curve_order()]) field
pub fn private<T>(private_key: H256, chain_code: H256, index: Derivation<T>) -> (H256, H256)
where
T: Label,
{
match index {
Derivation::Soft(index) => private_soft(private_key, chain_code, index),
Derivation::Hard(index) => private_hard(private_key, chain_code, index),
}
}
fn hmac_pair(data: &[u8], private_key: H256, chain_code: H256) -> (H256, H256) {
let private: U256 = private_key.into();
// produces 512-bit derived hmac (I)
let skey = hmac::SigKey::sha512(&*chain_code);
let i_512 = hmac::sign(&skey, &data[..]);
// left most 256 bits are later added to original private key
let hmac_key: U256 = H256::from_slice(&i_512[0..32]).into();
// right most 256 bits are new chain code for later derivations
let next_chain_code = H256::from(&i_512[32..64]);
let child_key = private_add(hmac_key, private).into();
(child_key, next_chain_code)
}
// Can panic if passed `private_key` is not a valid secp256k1 private key
// (outside of (0..curve_order()]) field
fn private_soft<T>(private_key: H256, chain_code: H256, index: T) -> (H256, H256)
where
T: Label,
{
let mut data = vec![0u8; 33 + T::len()];
let sec_private = SecretKey::from_slice(&SECP256K1, &*private_key)
.expect("Caller should provide valid private key");
let sec_public = PublicKey::from_secret_key(&SECP256K1, &sec_private)
.expect("Caller should provide valid private key");
let public_serialized = sec_public.serialize_vec(&SECP256K1, true);
// curve point (compressed public key) -- index
// 0.33 -- 33..end
data[0..33].copy_from_slice(&public_serialized);
index.store(&mut data[33..]);
hmac_pair(&data, private_key, chain_code)
}
// Deterministic derivation of the key using secp256k1 elliptic curve
// This is hardened derivation and does not allow to associate
// corresponding public keys of the original and derived private keys
fn private_hard<T>(private_key: H256, chain_code: H256, index: T) -> (H256, H256)
where
T: Label,
{
let mut data: Vec<u8> = vec![0u8; 33 + T::len()];
let private: U256 = private_key.into();
// 0x00 (padding) -- private_key -- index
// 0 -- 1..33 -- 33..end
private.to_big_endian(&mut data[1..33]);
index.store(&mut data[33..(33 + T::len())]);
hmac_pair(&data, private_key, chain_code)
}
fn private_add(k1: U256, k2: U256) -> U256 {
let sum = U512::from(k1) + U512::from(k2);
modulo(sum, curve_order())
}
// todo: surely can be optimized
fn modulo(u1: U512, u2: U256) -> U256 {
let dv = u1 / U512::from(u2);
let md = u1 - (dv * U512::from(u2));
md.into()
}
pub fn public<T>(
public_key: H512,
chain_code: H256,
derivation: Derivation<T>,
) -> Result<(H512, H256), Error>
where
T: Label,
{
let index = match derivation {
Derivation::Soft(index) => index,
Derivation::Hard(_) => {
return Err(Error::InvalidHardenedUse);
}
};
let mut public_sec_raw = [0u8; 65];
public_sec_raw[0] = 4;
public_sec_raw[1..65].copy_from_slice(&*public_key);
let public_sec =
PublicKey::from_slice(&SECP256K1, &public_sec_raw).map_err(|_| Error::InvalidPoint)?;
let public_serialized = public_sec.serialize_vec(&SECP256K1, true);
let mut data = vec![0u8; 33 + T::len()];
// curve point (compressed public key) -- index
// 0.33 -- 33..end
data[0..33].copy_from_slice(&public_serialized);
index.store(&mut data[33..(33 + T::len())]);
// HMAC512SHA produces [derived private(256); new chain code(256)]
let skey = hmac::SigKey::sha512(&*chain_code);
let i_512 = hmac::sign(&skey, &data[..]);
let new_private = H256::from(&i_512[0..32]);
let new_chain_code = H256::from(&i_512[32..64]);
// Generated private key can (extremely rarely) be out of secp256k1 key field
if curve_order() <= new_private.clone().into() {
return Err(Error::MissingIndex);
}
let new_private_sec = SecretKey::from_slice(&SECP256K1, &*new_private)
.expect("Private key belongs to the field [0..CURVE_ORDER) (checked above); So initializing can never fail; qed");
let mut new_public = PublicKey::from_secret_key(&SECP256K1, &new_private_sec)
.expect("Valid private key produces valid public key");
// Adding two points on the elliptic curves (combining two public keys)
new_public
.add_assign(&SECP256K1, &public_sec)
.expect("Addition of two valid points produce valid point");
let serialized = new_public.serialize_vec(&SECP256K1, false);
Ok((H512::from(&serialized[1..65]), new_chain_code))
}
fn sha3(slc: &[u8]) -> H256 {
keccak::Keccak256::keccak256(slc).into()
}
pub fn chain_code(secret: H256) -> H256 {
// 10,000 rounds of sha3
let mut running_sha3 = sha3(&*secret);
for _ in 0..99999 {
running_sha3 = sha3(&*running_sha3);
}
running_sha3
}
pub fn point(secret: H256) -> Result<H512, Error> {
let sec = SecretKey::from_slice(&SECP256K1, &*secret).map_err(|_| Error::InvalidPoint)?;
let public_sec =
PublicKey::from_secret_key(&SECP256K1, &sec).map_err(|_| Error::InvalidPoint)?;
let serialized = public_sec.serialize_vec(&SECP256K1, false);
Ok(H512::from(&serialized[1..65]))
}
pub fn seed_pair(seed: &[u8]) -> (H256, H256) {
let skey = hmac::SigKey::sha512(b"Bitcoin seed");
let i_512 = hmac::sign(&skey, seed);
let master_key = H256::from_slice(&i_512[0..32]);
let chain_code = H256::from_slice(&i_512[32..64]);
(master_key, chain_code)
}
}
#[cfg(test)]
mod tests {
use super::{derivation, Derivation, ExtendedKeyPair, ExtendedPublic, ExtendedSecret};
use ethereum_types::{H128, H256};
use secret::Secret;
use std::str::FromStr;
fn master_chain_basic() -> (H256, H256) {
let seed = H128::from_str("000102030405060708090a0b0c0d0e0f")
.expect("Seed should be valid H128")
.to_vec();
derivation::seed_pair(&*seed)
}
fn test_extended<F>(f: F, test_private: H256)
where
F: Fn(ExtendedSecret) -> ExtendedSecret,
{
let (private_seed, chain_code) = master_chain_basic();
let extended_secret = ExtendedSecret::with_code(Secret::from(private_seed.0), chain_code);
let derived = f(extended_secret);
assert_eq!(**derived.as_raw(), test_private);
}
#[test]
fn smoky() {
let secret =
Secret::from_str("a100df7a048e50ed308ea696dc600215098141cb391e9527329df289f9383f65")
.unwrap();
let extended_secret = ExtendedSecret::with_code(secret.clone(), 0u64.into());
// hardened
assert_eq!(&**extended_secret.as_raw(), &*secret);
assert_eq!(
&**extended_secret.derive(2147483648.into()).as_raw(),
&"0927453daed47839608e414a3738dfad10aed17c459bbd9ab53f89b026c834b6".into()
);
assert_eq!(
&**extended_secret.derive(2147483649.into()).as_raw(),
&"44238b6a29c6dcbe9b401364141ba11e2198c289a5fed243a1c11af35c19dc0f".into()
);
// normal
assert_eq!(
&**extended_secret.derive(0.into()).as_raw(),
&"bf6a74e3f7b36fc4c96a1e12f31abc817f9f5904f5a8fc27713163d1f0b713f6".into()
);
assert_eq!(
&**extended_secret.derive(1.into()).as_raw(),
&"bd4fca9eb1f9c201e9448c1eecd66e302d68d4d313ce895b8c134f512205c1bc".into()
);
assert_eq!(
&**extended_secret.derive(2.into()).as_raw(),
&"86932b542d6cab4d9c65490c7ef502d89ecc0e2a5f4852157649e3251e2a3268".into()
);
let extended_public = ExtendedPublic::from_secret(&extended_secret)
.expect("Extended public should be created");
let derived_public = extended_public
.derive(0.into())
.expect("First derivation of public should succeed");
assert_eq!(&*derived_public.public(), &"f7b3244c96688f92372bfd4def26dc4151529747bab9f188a4ad34e141d47bd66522ff048bc6f19a0a4429b04318b1a8796c000265b4fa200dae5f6dda92dd94".into());
let keypair = ExtendedKeyPair::with_secret(
Secret::from_str("a100df7a048e50ed308ea696dc600215098141cb391e9527329df289f9383f65")
.unwrap(),
064.into(),
);
assert_eq!(
&**keypair
.derive(2147483648u32.into())
.expect("Derivation of keypair should succeed")
.secret()
.as_raw(),
&"edef54414c03196557cf73774bc97a645c9a1df2164ed34f0c2a78d1375a930c".into()
);
}
#[test]
fn h256_soft_match() {
let secret =
Secret::from_str("a100df7a048e50ed308ea696dc600215098141cb391e9527329df289f9383f65")
.unwrap();
let derivation_secret =
H256::from_str("51eaf04f9dbbc1417dc97e789edd0c37ecda88bac490434e367ea81b71b7b015")
.unwrap();
let extended_secret = ExtendedSecret::with_code(secret.clone(), 0u64.into());
let extended_public = ExtendedPublic::from_secret(&extended_secret)
.expect("Extended public should be created");
let derived_secret0 = extended_secret.derive(Derivation::Soft(derivation_secret));
let derived_public0 = extended_public
.derive(Derivation::Soft(derivation_secret))
.expect("First derivation of public should succeed");
let public_from_secret0 = ExtendedPublic::from_secret(&derived_secret0)
.expect("Extended public should be created");
assert_eq!(public_from_secret0.public(), derived_public0.public());
}
#[test]
fn h256_hard() {
let secret =
Secret::from_str("a100df7a048e50ed308ea696dc600215098141cb391e9527329df289f9383f65")
.unwrap();
let derivation_secret =
H256::from_str("51eaf04f9dbbc1417dc97e789edd0c37ecda88bac490434e367ea81b71b7b015")
.unwrap();
let extended_secret = ExtendedSecret::with_code(secret.clone(), 1u64.into());
assert_eq!(
&**extended_secret
.derive(Derivation::Hard(derivation_secret))
.as_raw(),
&"2bc2d696fb744d77ff813b4a1ef0ad64e1e5188b622c54ba917acc5ebc7c5486".into()
);
}
#[test]
fn match_() {
let secret =
Secret::from_str("a100df7a048e50ed308ea696dc600215098141cb391e9527329df289f9383f65")
.unwrap();
let extended_secret = ExtendedSecret::with_code(secret.clone(), 1.into());
let extended_public = ExtendedPublic::from_secret(&extended_secret)
.expect("Extended public should be created");
let derived_secret0 = extended_secret.derive(0.into());
let derived_public0 = extended_public
.derive(0.into())
.expect("First derivation of public should succeed");
let public_from_secret0 = ExtendedPublic::from_secret(&derived_secret0)
.expect("Extended public should be created");
assert_eq!(public_from_secret0.public(), derived_public0.public());
}
#[test]
fn test_seeds() {
let seed = H128::from_str("000102030405060708090a0b0c0d0e0f")
.expect("Seed should be valid H128")
.to_vec();
// private key from bitcoin test vector
// xprv9wTYmMFdV23N2TdNG573QoEsfRrWKQgWeibmLntzniatZvR9BmLnvSxqu53Kw1UmYPxLgboyZQaXwTCg8MSY3H2EU4pWcQDnRnrVA1xe8fs
let test_private =
H256::from_str("e8f32e723decf4051aefac8e2c93c9c5b214313817cdb01a1494b917c8436b35")
.expect("Private should be decoded ok");
let (private_seed, _) = derivation::seed_pair(&*seed);
assert_eq!(private_seed, test_private);
}
#[test]
fn test_vector_1() {
// xprv9uHRZZhk6KAJC1avXpDAp4MDc3sQKNxDiPvvkX8Br5ngLNv1TxvUxt4cV1rGL5hj6KCesnDYUhd7oWgT11eZG7XnxHrnYeSvkzY7d2bhkJ7
// H(0)
test_extended(
|secret| secret.derive(2147483648.into()),
H256::from_str("edb2e14f9ee77d26dd93b4ecede8d16ed408ce149b6cd80b0715a2d911a0afea")
.expect("Private should be decoded ok"),
);
}
#[test]
fn test_vector_2() {
// xprv9wTYmMFdV23N2TdNG573QoEsfRrWKQgWeibmLntzniatZvR9BmLnvSxqu53Kw1UmYPxLgboyZQaXwTCg8MSY3H2EU4pWcQDnRnrVA1xe8fs
// H(0)/1
test_extended(
|secret| secret.derive(2147483648.into()).derive(1.into()),
H256::from_str("3c6cb8d0f6a264c91ea8b5030fadaa8e538b020f0a387421a12de9319dc93368")
.expect("Private should be decoded ok"),
);
}
}

View File

@@ -1,33 +0,0 @@
// Copyright 2015-2020 Parity Technologies (UK) Ltd.
// This file is part of OpenEthereum.
// OpenEthereum 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.
// OpenEthereum 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 OpenEthereum. If not, see <http://www.gnu.org/licenses/>.
use tiny_keccak::Keccak;
pub trait Keccak256<T> {
fn keccak256(&self) -> T
where
T: Sized;
}
impl Keccak256<[u8; 32]> for [u8] {
fn keccak256(&self) -> [u8; 32] {
let mut keccak = Keccak::new_keccak256();
let mut result = [0u8; 32];
keccak.update(self);
keccak.finalize(&mut result);
result
}
}

View File

@@ -1,120 +0,0 @@
// Copyright 2015-2020 Parity Technologies (UK) Ltd.
// This file is part of OpenEthereum.
// OpenEthereum 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.
// OpenEthereum 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 OpenEthereum. If not, see <http://www.gnu.org/licenses/>.
use super::{Address, Error, Public, Secret, SECP256K1};
use keccak::Keccak256;
use rustc_hex::ToHex;
use secp256k1::key;
use std::fmt;
pub fn public_to_address(public: &Public) -> Address {
let hash = public.keccak256();
let mut result = Address::default();
result.copy_from_slice(&hash[12..]);
result
}
#[derive(Debug, Clone, PartialEq)]
/// secp256k1 key pair
pub struct KeyPair {
secret: Secret,
public: Public,
}
impl fmt::Display for KeyPair {
fn fmt(&self, f: &mut fmt::Formatter) -> Result<(), fmt::Error> {
writeln!(f, "secret: {}", self.secret.to_hex())?;
writeln!(f, "public: {}", self.public.to_hex())?;
write!(f, "address: {}", self.address().to_hex())
}
}
impl KeyPair {
/// Create a pair from secret key
pub fn from_secret(secret: Secret) -> Result<KeyPair, Error> {
let context = &SECP256K1;
let s: key::SecretKey = key::SecretKey::from_slice(context, &secret[..])?;
let pub_key = key::PublicKey::from_secret_key(context, &s)?;
let serialized = pub_key.serialize_vec(context, false);
let mut public = Public::default();
public.copy_from_slice(&serialized[1..65]);
let keypair = KeyPair {
secret: secret,
public: public,
};
Ok(keypair)
}
pub fn from_secret_slice(slice: &[u8]) -> Result<KeyPair, Error> {
Self::from_secret(Secret::from_unsafe_slice(slice)?)
}
pub fn from_keypair(sec: key::SecretKey, publ: key::PublicKey) -> Self {
let context = &SECP256K1;
let serialized = publ.serialize_vec(context, false);
let secret = Secret::from(sec);
let mut public = Public::default();
public.copy_from_slice(&serialized[1..65]);
KeyPair {
secret: secret,
public: public,
}
}
pub fn secret(&self) -> &Secret {
&self.secret
}
pub fn public(&self) -> &Public {
&self.public
}
pub fn address(&self) -> Address {
public_to_address(&self.public)
}
}
#[cfg(test)]
mod tests {
use std::str::FromStr;
use KeyPair;
use Secret;
#[test]
fn from_secret() {
let secret =
Secret::from_str("a100df7a048e50ed308ea696dc600215098141cb391e9527329df289f9383f65")
.unwrap();
let _ = KeyPair::from_secret(secret).unwrap();
}
#[test]
fn keypair_display() {
let expected =
"secret: a100df7a048e50ed308ea696dc600215098141cb391e9527329df289f9383f65
public: 8ce0db0b0359ffc5866ba61903cc2518c3675ef2cf380a7e54bde7ea20e6fa1ab45b7617346cd11b7610001ee6ae5b0155c41cad9527cbcdff44ec67848943a4
address: 5b073e9233944b5e729e46d618f0d8edf3d9c34a".to_owned();
let secret =
Secret::from_str("a100df7a048e50ed308ea696dc600215098141cb391e9527329df289f9383f65")
.unwrap();
let kp = KeyPair::from_secret(secret).unwrap();
assert_eq!(format!("{}", kp), expected);
}
}

View File

@@ -17,20 +17,10 @@
// #![warn(missing_docs)]
extern crate edit_distance;
extern crate ethereum_types;
extern crate memzero;
extern crate parity_crypto;
extern crate parity_wordlist;
#[macro_use]
extern crate quick_error;
extern crate rand;
extern crate rustc_hex;
extern crate secp256k1;
extern crate serde;
extern crate tiny_keccak;
#[macro_use]
extern crate lazy_static;
#[macro_use]
extern crate log;
#[macro_use]
@@ -38,52 +28,12 @@ extern crate serde_derive;
mod brain;
mod brain_prefix;
mod error;
mod extended;
mod keccak;
mod keypair;
mod password;
mod prefix;
mod random;
mod secret;
mod signature;
pub mod brain_recover;
pub mod crypto;
pub mod math;
pub use self::{
brain::Brain,
brain_prefix::BrainPrefix,
error::Error,
extended::{Derivation, DerivationError, ExtendedKeyPair, ExtendedPublic, ExtendedSecret},
keypair::{public_to_address, KeyPair},
math::public_is_valid,
parity_wordlist::Error as WordlistError,
password::Password,
prefix::Prefix,
random::Random,
secret::Secret,
signature::{recover, sign, verify_address, verify_public, Signature},
brain::Brain, brain_prefix::BrainPrefix, parity_wordlist::Error as WordlistError,
password::Password, prefix::Prefix,
};
use ethereum_types::H256;
pub use ethereum_types::{Address, Public};
pub type Message = H256;
lazy_static! {
pub static ref SECP256K1: secp256k1::Secp256k1 = secp256k1::Secp256k1::new();
}
/// Uninstantiatable error type for infallible generators.
#[derive(Debug)]
pub enum Void {}
/// Generates new keypair.
pub trait Generator {
type Error;
/// Should be called to generate new keypair.
fn generate(&mut self) -> Result<KeyPair, Self::Error>;
}

View File

@@ -1,134 +0,0 @@
// Copyright 2015-2020 Parity Technologies (UK) Ltd.
// This file is part of OpenEthereum.
// OpenEthereum 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.
// OpenEthereum 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 OpenEthereum. If not, see <http://www.gnu.org/licenses/>.
use super::{Error, Public, Secret, SECP256K1};
use ethereum_types::{H256, U256};
use secp256k1::{
constants::{CURVE_ORDER, GENERATOR_X, GENERATOR_Y},
key,
};
/// Whether the public key is valid.
pub fn public_is_valid(public: &Public) -> bool {
to_secp256k1_public(public)
.ok()
.map_or(false, |p| p.is_valid())
}
/// Inplace multiply public key by secret key (EC point * scalar)
pub fn public_mul_secret(public: &mut Public, secret: &Secret) -> Result<(), Error> {
let key_secret = secret.to_secp256k1_secret()?;
let mut key_public = to_secp256k1_public(public)?;
key_public.mul_assign(&SECP256K1, &key_secret)?;
set_public(public, &key_public);
Ok(())
}
/// Inplace add one public key to another (EC point + EC point)
pub fn public_add(public: &mut Public, other: &Public) -> Result<(), Error> {
let mut key_public = to_secp256k1_public(public)?;
let other_public = to_secp256k1_public(other)?;
key_public.add_assign(&SECP256K1, &other_public)?;
set_public(public, &key_public);
Ok(())
}
/// Inplace sub one public key from another (EC point - EC point)
pub fn public_sub(public: &mut Public, other: &Public) -> Result<(), Error> {
let mut key_neg_other = to_secp256k1_public(other)?;
key_neg_other.mul_assign(&SECP256K1, &key::MINUS_ONE_KEY)?;
let mut key_public = to_secp256k1_public(public)?;
key_public.add_assign(&SECP256K1, &key_neg_other)?;
set_public(public, &key_public);
Ok(())
}
/// Replace public key with its negation (EC point = - EC point)
pub fn public_negate(public: &mut Public) -> Result<(), Error> {
let mut key_public = to_secp256k1_public(public)?;
key_public.mul_assign(&SECP256K1, &key::MINUS_ONE_KEY)?;
set_public(public, &key_public);
Ok(())
}
/// Return base point of secp256k1
pub fn generation_point() -> Public {
let mut public_sec_raw = [0u8; 65];
public_sec_raw[0] = 4;
public_sec_raw[1..33].copy_from_slice(&GENERATOR_X);
public_sec_raw[33..65].copy_from_slice(&GENERATOR_Y);
let public_key = key::PublicKey::from_slice(&SECP256K1, &public_sec_raw)
.expect("constructing using predefined constants; qed");
let mut public = Public::default();
set_public(&mut public, &public_key);
public
}
/// Return secp256k1 elliptic curve order
pub fn curve_order() -> U256 {
H256::from_slice(&CURVE_ORDER).into()
}
fn to_secp256k1_public(public: &Public) -> Result<key::PublicKey, Error> {
let public_data = {
let mut temp = [4u8; 65];
(&mut temp[1..65]).copy_from_slice(&public[0..64]);
temp
};
Ok(key::PublicKey::from_slice(&SECP256K1, &public_data)?)
}
fn set_public(public: &mut Public, key_public: &key::PublicKey) {
let key_public_serialized = key_public.serialize_vec(&SECP256K1, false);
public.copy_from_slice(&key_public_serialized[1..65]);
}
#[cfg(test)]
mod tests {
use super::{
super::{Generator, Random},
public_add, public_sub,
};
#[test]
fn public_addition_is_commutative() {
let public1 = Random.generate().unwrap().public().clone();
let public2 = Random.generate().unwrap().public().clone();
let mut left = public1.clone();
public_add(&mut left, &public2).unwrap();
let mut right = public2.clone();
public_add(&mut right, &public1).unwrap();
assert_eq!(left, right);
}
#[test]
fn public_addition_is_reversible_with_subtraction() {
let public1 = Random.generate().unwrap().public().clone();
let public2 = Random.generate().unwrap().public().clone();
let mut sum = public1.clone();
public_add(&mut sum, &public2).unwrap();
public_sub(&mut sum, &public2).unwrap();
assert_eq!(sum, public1);
}
}

View File

@@ -14,7 +14,7 @@
// You should have received a copy of the GNU General Public License
// along with OpenEthereum. If not, see <http://www.gnu.org/licenses/>.
use super::{Error, Generator, KeyPair, Random};
use parity_crypto::publickey::{Error, Generator, KeyPair, Random};
/// Tries to find keypair with address starting with given prefix.
pub struct Prefix {
@@ -24,20 +24,13 @@ pub struct Prefix {
impl Prefix {
pub fn new(prefix: Vec<u8>, iterations: usize) -> Self {
Prefix {
prefix: prefix,
iterations: iterations,
}
Prefix { prefix, iterations }
}
}
impl Generator for Prefix {
type Error = Error;
fn generate(&mut self) -> Result<KeyPair, Error> {
pub fn generate(&mut self) -> Result<KeyPair, Error> {
for _ in 0..self.iterations {
let keypair = Random.generate()?;
if keypair.address().starts_with(&self.prefix) {
let keypair = Random.generate();
if keypair.address().as_ref().starts_with(&self.prefix) {
return Ok(keypair);
}
}
@@ -48,7 +41,6 @@ impl Generator for Prefix {
#[cfg(test)]
mod tests {
use Generator;
use Prefix;
#[test]
@@ -57,6 +49,6 @@ mod tests {
let keypair = Prefix::new(prefix.clone(), usize::max_value())
.generate()
.unwrap();
assert!(keypair.address().starts_with(&prefix));
assert!(keypair.address().as_bytes().starts_with(&prefix));
}
}

View File

@@ -1,42 +0,0 @@
// Copyright 2015-2020 Parity Technologies (UK) Ltd.
// This file is part of OpenEthereum.
// OpenEthereum 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.
// OpenEthereum 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 OpenEthereum. If not, see <http://www.gnu.org/licenses/>.
use super::{Generator, KeyPair, SECP256K1};
use rand::os::OsRng;
/// Randomly generates new keypair, instantiating the RNG each time.
pub struct Random;
impl Generator for Random {
type Error = ::std::io::Error;
fn generate(&mut self) -> Result<KeyPair, Self::Error> {
let mut rng = OsRng::new()?;
rng.generate().or_else(|void| match void {})
}
}
impl Generator for OsRng {
type Error = ::Void;
fn generate(&mut self) -> Result<KeyPair, Self::Error> {
let (sec, publ) = SECP256K1
.generate_keypair(self)
.expect("context always created with full capabilities; qed");
Ok(KeyPair::from_keypair(sec, publ))
}
}

View File

@@ -1,322 +0,0 @@
// Copyright 2015-2020 Parity Technologies (UK) Ltd.
// This file is part of OpenEthereum.
// OpenEthereum 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.
// OpenEthereum 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 OpenEthereum. If not, see <http://www.gnu.org/licenses/>.
use ethereum_types::H256;
use memzero::Memzero;
use rustc_hex::ToHex;
use secp256k1::{constants::SECRET_KEY_SIZE as SECP256K1_SECRET_KEY_SIZE, key};
use std::{fmt, ops::Deref, str::FromStr};
use Error;
use SECP256K1;
#[derive(Clone, PartialEq, Eq)]
pub struct Secret {
inner: Memzero<H256>,
}
impl ToHex for Secret {
fn to_hex(&self) -> String {
format!("{:x}", *self.inner)
}
}
impl fmt::LowerHex for Secret {
fn fmt(&self, fmt: &mut fmt::Formatter) -> fmt::Result {
self.inner.fmt(fmt)
}
}
impl fmt::Debug for Secret {
fn fmt(&self, fmt: &mut fmt::Formatter) -> fmt::Result {
self.inner.fmt(fmt)
}
}
impl fmt::Display for Secret {
fn fmt(&self, fmt: &mut fmt::Formatter) -> fmt::Result {
write!(
fmt,
"Secret: 0x{:x}{:x}..{:x}{:x}",
self.inner[0], self.inner[1], self.inner[30], self.inner[31]
)
}
}
impl Secret {
/// Creates a `Secret` from the given slice, returning `None` if the slice length != 32.
pub fn from_slice(key: &[u8]) -> Option<Self> {
if key.len() != 32 {
return None;
}
let mut h = H256::default();
h.copy_from_slice(&key[0..32]);
Some(Secret {
inner: Memzero::from(h),
})
}
/// Creates zero key, which is invalid for crypto operations, but valid for math operation.
pub fn zero() -> Self {
Secret {
inner: Memzero::from(H256::default()),
}
}
/// Imports and validates the key.
pub fn from_unsafe_slice(key: &[u8]) -> Result<Self, Error> {
let secret = key::SecretKey::from_slice(&super::SECP256K1, key)?;
Ok(secret.into())
}
/// Checks validity of this key.
pub fn check_validity(&self) -> Result<(), Error> {
self.to_secp256k1_secret().map(|_| ())
}
/// Inplace add one secret key to another (scalar + scalar)
pub fn add(&mut self, other: &Secret) -> Result<(), Error> {
match (self.is_zero(), other.is_zero()) {
(true, true) | (false, true) => Ok(()),
(true, false) => {
*self = other.clone();
Ok(())
}
(false, false) => {
let mut key_secret = self.to_secp256k1_secret()?;
let other_secret = other.to_secp256k1_secret()?;
key_secret.add_assign(&SECP256K1, &other_secret)?;
*self = key_secret.into();
Ok(())
}
}
}
/// Inplace subtract one secret key from another (scalar - scalar)
pub fn sub(&mut self, other: &Secret) -> Result<(), Error> {
match (self.is_zero(), other.is_zero()) {
(true, true) | (false, true) => Ok(()),
(true, false) => {
*self = other.clone();
self.neg()
}
(false, false) => {
let mut key_secret = self.to_secp256k1_secret()?;
let mut other_secret = other.to_secp256k1_secret()?;
other_secret.mul_assign(&SECP256K1, &key::MINUS_ONE_KEY)?;
key_secret.add_assign(&SECP256K1, &other_secret)?;
*self = key_secret.into();
Ok(())
}
}
}
/// Inplace decrease secret key (scalar - 1)
pub fn dec(&mut self) -> Result<(), Error> {
match self.is_zero() {
true => {
*self = key::MINUS_ONE_KEY.into();
Ok(())
}
false => {
let mut key_secret = self.to_secp256k1_secret()?;
key_secret.add_assign(&SECP256K1, &key::MINUS_ONE_KEY)?;
*self = key_secret.into();
Ok(())
}
}
}
/// Inplace multiply one secret key to another (scalar * scalar)
pub fn mul(&mut self, other: &Secret) -> Result<(), Error> {
match (self.is_zero(), other.is_zero()) {
(true, true) | (true, false) => Ok(()),
(false, true) => {
*self = Self::zero();
Ok(())
}
(false, false) => {
let mut key_secret = self.to_secp256k1_secret()?;
let other_secret = other.to_secp256k1_secret()?;
key_secret.mul_assign(&SECP256K1, &other_secret)?;
*self = key_secret.into();
Ok(())
}
}
}
/// Inplace negate secret key (-scalar)
pub fn neg(&mut self) -> Result<(), Error> {
match self.is_zero() {
true => Ok(()),
false => {
let mut key_secret = self.to_secp256k1_secret()?;
key_secret.mul_assign(&SECP256K1, &key::MINUS_ONE_KEY)?;
*self = key_secret.into();
Ok(())
}
}
}
/// Inplace inverse secret key (1 / scalar)
pub fn inv(&mut self) -> Result<(), Error> {
let mut key_secret = self.to_secp256k1_secret()?;
key_secret.inv_assign(&SECP256K1)?;
*self = key_secret.into();
Ok(())
}
/// Compute power of secret key inplace (secret ^ pow).
/// This function is not intended to be used with large powers.
pub fn pow(&mut self, pow: usize) -> Result<(), Error> {
if self.is_zero() {
return Ok(());
}
match pow {
0 => *self = key::ONE_KEY.into(),
1 => (),
_ => {
let c = self.clone();
for _ in 1..pow {
self.mul(&c)?;
}
}
}
Ok(())
}
/// Create `secp256k1::key::SecretKey` based on this secret
pub fn to_secp256k1_secret(&self) -> Result<key::SecretKey, Error> {
Ok(key::SecretKey::from_slice(&SECP256K1, &self[..])?)
}
}
impl FromStr for Secret {
type Err = Error;
fn from_str(s: &str) -> Result<Self, Self::Err> {
Ok(H256::from_str(s)
.map_err(|e| Error::Custom(format!("{:?}", e)))?
.into())
}
}
impl From<[u8; 32]> for Secret {
fn from(k: [u8; 32]) -> Self {
Secret {
inner: Memzero::from(H256(k)),
}
}
}
impl From<H256> for Secret {
fn from(s: H256) -> Self {
s.0.into()
}
}
impl From<&'static str> for Secret {
fn from(s: &'static str) -> Self {
s.parse().expect(&format!(
"invalid string literal for {}: '{}'",
stringify!(Self),
s
))
}
}
impl From<key::SecretKey> for Secret {
fn from(key: key::SecretKey) -> Self {
let mut a = [0; SECP256K1_SECRET_KEY_SIZE];
a.copy_from_slice(&key[0..SECP256K1_SECRET_KEY_SIZE]);
a.into()
}
}
impl Deref for Secret {
type Target = H256;
fn deref(&self) -> &Self::Target {
&self.inner
}
}
#[cfg(test)]
mod tests {
use super::{
super::{Generator, Random},
Secret,
};
use std::str::FromStr;
#[test]
fn multiplicating_secret_inversion_with_secret_gives_one() {
let secret = Random.generate().unwrap().secret().clone();
let mut inversion = secret.clone();
inversion.inv().unwrap();
inversion.mul(&secret).unwrap();
assert_eq!(
inversion,
Secret::from_str("0000000000000000000000000000000000000000000000000000000000000001")
.unwrap()
);
}
#[test]
fn secret_inversion_is_reversible_with_inversion() {
let secret = Random.generate().unwrap().secret().clone();
let mut inversion = secret.clone();
inversion.inv().unwrap();
inversion.inv().unwrap();
assert_eq!(inversion, secret);
}
#[test]
fn secret_pow() {
let secret = Random.generate().unwrap().secret().clone();
let mut pow0 = secret.clone();
pow0.pow(0).unwrap();
assert_eq!(
pow0,
Secret::from_str("0000000000000000000000000000000000000000000000000000000000000001")
.unwrap()
);
let mut pow1 = secret.clone();
pow1.pow(1).unwrap();
assert_eq!(pow1, secret);
let mut pow2 = secret.clone();
pow2.pow(2).unwrap();
let mut pow2_expected = secret.clone();
pow2_expected.mul(&secret).unwrap();
assert_eq!(pow2, pow2_expected);
let mut pow3 = secret.clone();
pow3.pow(3).unwrap();
let mut pow3_expected = secret.clone();
pow3_expected.mul(&secret).unwrap();
pow3_expected.mul(&secret).unwrap();
assert_eq!(pow3, pow3_expected);
}
}

View File

@@ -1,325 +0,0 @@
// Copyright 2015-2020 Parity Technologies (UK) Ltd.
// This file is part of OpenEthereum.
// OpenEthereum 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.
// OpenEthereum 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 OpenEthereum. If not, see <http://www.gnu.org/licenses/>.
use ethereum_types::{H256, H520};
use public_to_address;
use rustc_hex::{FromHex, ToHex};
use secp256k1::{
key::{PublicKey, SecretKey},
Error as SecpError, Message as SecpMessage, RecoverableSignature, RecoveryId,
};
use std::{
cmp::PartialEq,
fmt,
hash::{Hash, Hasher},
ops::{Deref, DerefMut},
str::FromStr,
};
use Address;
use Error;
use Message;
use Public;
use Secret;
use SECP256K1;
/// Signature encoded as RSV components
#[repr(C)]
pub struct Signature([u8; 65]);
impl Signature {
/// Get a slice into the 'r' portion of the data.
pub fn r(&self) -> &[u8] {
&self.0[0..32]
}
/// Get a slice into the 's' portion of the data.
pub fn s(&self) -> &[u8] {
&self.0[32..64]
}
/// Get the recovery byte.
pub fn v(&self) -> u8 {
self.0[64]
}
/// Encode the signature into RSV array (V altered to be in "Electrum" notation).
pub fn into_electrum(mut self) -> [u8; 65] {
self.0[64] += 27;
self.0
}
/// Parse bytes as a signature encoded as RSV (V in "Electrum" notation).
/// May return empty (invalid) signature if given data has invalid length.
pub fn from_electrum(data: &[u8]) -> Self {
if data.len() != 65 || data[64] < 27 {
// fallback to empty (invalid) signature
return Signature::default();
}
let mut sig = [0u8; 65];
sig.copy_from_slice(data);
sig[64] -= 27;
Signature(sig)
}
/// Create a signature object from the sig.
pub fn from_rsv(r: &H256, s: &H256, v: u8) -> Self {
let mut sig = [0u8; 65];
sig[0..32].copy_from_slice(&r);
sig[32..64].copy_from_slice(&s);
sig[64] = v;
Signature(sig)
}
/// Check if this is a "low" signature.
pub fn is_low_s(&self) -> bool {
H256::from_slice(self.s())
<= "7FFFFFFFFFFFFFFFFFFFFFFFFFFFFFFF5D576E7357A4501DDFE92F46681B20A0".into()
}
/// Check if each component of the signature is in range.
pub fn is_valid(&self) -> bool {
self.v() <= 1
&& H256::from_slice(self.r())
< "fffffffffffffffffffffffffffffffebaaedce6af48a03bbfd25e8cd0364141".into()
&& H256::from_slice(self.r()) >= 1.into()
&& H256::from_slice(self.s())
< "fffffffffffffffffffffffffffffffebaaedce6af48a03bbfd25e8cd0364141".into()
&& H256::from_slice(self.s()) >= 1.into()
}
}
// manual implementation large arrays don't have trait impls by default.
// remove when integer generics exist
impl PartialEq for Signature {
fn eq(&self, other: &Self) -> bool {
&self.0[..] == &other.0[..]
}
}
// manual implementation required in Rust 1.13+, see `std::cmp::AssertParamIsEq`.
impl Eq for Signature {}
// also manual for the same reason, but the pretty printing might be useful.
impl fmt::Debug for Signature {
fn fmt(&self, f: &mut fmt::Formatter) -> Result<(), fmt::Error> {
f.debug_struct("Signature")
.field("r", &self.0[0..32].to_hex())
.field("s", &self.0[32..64].to_hex())
.field("v", &self.0[64..65].to_hex())
.finish()
}
}
impl fmt::Display for Signature {
fn fmt(&self, f: &mut fmt::Formatter) -> Result<(), fmt::Error> {
write!(f, "{}", self.to_hex())
}
}
impl FromStr for Signature {
type Err = Error;
fn from_str(s: &str) -> Result<Self, Self::Err> {
match s.from_hex() {
Ok(ref hex) if hex.len() == 65 => {
let mut data = [0; 65];
data.copy_from_slice(&hex[0..65]);
Ok(Signature(data))
}
_ => Err(Error::InvalidSignature),
}
}
}
impl Default for Signature {
fn default() -> Self {
Signature([0; 65])
}
}
impl Hash for Signature {
fn hash<H: Hasher>(&self, state: &mut H) {
H520::from(self.0).hash(state);
}
}
impl Clone for Signature {
fn clone(&self) -> Self {
Signature(self.0)
}
}
impl From<[u8; 65]> for Signature {
fn from(s: [u8; 65]) -> Self {
Signature(s)
}
}
impl Into<[u8; 65]> for Signature {
fn into(self) -> [u8; 65] {
self.0
}
}
impl From<Signature> for H520 {
fn from(s: Signature) -> Self {
H520::from(s.0)
}
}
impl From<H520> for Signature {
fn from(bytes: H520) -> Self {
Signature(bytes.into())
}
}
impl Deref for Signature {
type Target = [u8; 65];
fn deref(&self) -> &Self::Target {
&self.0
}
}
impl DerefMut for Signature {
fn deref_mut(&mut self) -> &mut Self::Target {
&mut self.0
}
}
pub fn sign(secret: &Secret, message: &Message) -> Result<Signature, Error> {
let context = &SECP256K1;
let sec = SecretKey::from_slice(context, &secret)?;
let s = context.sign_recoverable(&SecpMessage::from_slice(&message[..])?, &sec)?;
let (rec_id, data) = s.serialize_compact(context);
let mut data_arr = [0; 65];
// no need to check if s is low, it always is
data_arr[0..64].copy_from_slice(&data[0..64]);
data_arr[64] = rec_id.to_i32() as u8;
Ok(Signature(data_arr))
}
pub fn verify_public(
public: &Public,
signature: &Signature,
message: &Message,
) -> Result<bool, Error> {
let context = &SECP256K1;
let rsig = RecoverableSignature::from_compact(
context,
&signature[0..64],
RecoveryId::from_i32(signature[64] as i32)?,
)?;
let sig = rsig.to_standard(context);
let pdata: [u8; 65] = {
let mut temp = [4u8; 65];
temp[1..65].copy_from_slice(&**public);
temp
};
let publ = PublicKey::from_slice(context, &pdata)?;
match context.verify(&SecpMessage::from_slice(&message[..])?, &sig, &publ) {
Ok(_) => Ok(true),
Err(SecpError::IncorrectSignature) => Ok(false),
Err(x) => Err(Error::from(x)),
}
}
pub fn verify_address(
address: &Address,
signature: &Signature,
message: &Message,
) -> Result<bool, Error> {
let public = recover(signature, message)?;
let recovered_address = public_to_address(&public);
Ok(address == &recovered_address)
}
pub fn recover(signature: &Signature, message: &Message) -> Result<Public, Error> {
let context = &SECP256K1;
let rsig = RecoverableSignature::from_compact(
context,
&signature[0..64],
RecoveryId::from_i32(signature[64] as i32)?,
)?;
let pubkey = context.recover(&SecpMessage::from_slice(&message[..])?, &rsig)?;
let serialized = pubkey.serialize_vec(context, false);
let mut public = Public::default();
public.copy_from_slice(&serialized[1..65]);
Ok(public)
}
#[cfg(test)]
mod tests {
use super::{recover, sign, verify_address, verify_public, Signature};
use std::str::FromStr;
use Generator;
use Message;
use Random;
#[test]
fn vrs_conversion() {
// given
let keypair = Random.generate().unwrap();
let message = Message::default();
let signature = sign(keypair.secret(), &message).unwrap();
// when
let vrs = signature.clone().into_electrum();
let from_vrs = Signature::from_electrum(&vrs);
// then
assert_eq!(signature, from_vrs);
}
#[test]
fn signature_to_and_from_str() {
let keypair = Random.generate().unwrap();
let message = Message::default();
let signature = sign(keypair.secret(), &message).unwrap();
let string = format!("{}", signature);
let deserialized = Signature::from_str(&string).unwrap();
assert_eq!(signature, deserialized);
}
#[test]
fn sign_and_recover_public() {
let keypair = Random.generate().unwrap();
let message = Message::default();
let signature = sign(keypair.secret(), &message).unwrap();
assert_eq!(keypair.public(), &recover(&signature, &message).unwrap());
}
#[test]
fn sign_and_verify_public() {
let keypair = Random.generate().unwrap();
let message = Message::default();
let signature = sign(keypair.secret(), &message).unwrap();
assert!(verify_public(keypair.public(), &signature, &message).unwrap());
}
#[test]
fn sign_and_verify_address() {
let keypair = Random.generate().unwrap();
let message = Message::default();
let signature = sign(keypair.secret(), &message).unwrap();
assert!(verify_address(&keypair.address(), &signature, &message).unwrap());
}
}

View File

@@ -7,7 +7,7 @@ authors = ["Parity Technologies <admin@parity.io>"]
[dependencies]
log = "0.4"
libc = "0.2"
rand = "0.4"
rand = "0.7.3"
ethkey = { path = "../ethkey" }
serde = "1.0"
serde_json = "1.0"
@@ -16,8 +16,8 @@ rustc-hex = "1.0"
time = "0.1.34"
itertools = "0.5"
parking_lot = "0.7"
parity-crypto = "0.3.0"
ethereum-types = "0.4"
parity-crypto = { version = "0.6.2", features = [ "publickey"] }
ethereum-types = "0.9.2"
smallvec = "0.6"
parity-wordlist = "1.3"
tempdir = "0.3"

View File

@@ -15,8 +15,8 @@
// along with OpenEthereum. If not, see <http://www.gnu.org/licenses/>.
use account::{Aes128Ctr, Cipher, Kdf, Pbkdf2, Prf};
use crypto::{self, Keccak256};
use ethkey::{Password, Secret};
use crypto::{self, publickey::Secret, Keccak256};
use ethkey::Password;
use json;
use random::Random;
use smallvec::SmallVec;
@@ -79,7 +79,7 @@ impl Crypto {
password: &Password,
iterations: NonZeroU32,
) -> Result<Self, crypto::Error> {
Crypto::with_plain(&*secret, password, iterations)
Crypto::with_plain(secret.as_bytes(), password, iterations)
}
/// Encrypt custom plain data
@@ -94,7 +94,7 @@ impl Crypto {
// two parts of derived key
// DK = [ DK[0..15] DK[16..31] ] = [derived_left_bits, derived_right_bits]
let (derived_left_bits, derived_right_bits) =
crypto::derive_key_iterations(password.as_bytes(), &salt, iterations);
crypto::derive_key_iterations(password.as_bytes(), &salt, iterations.get());
// preallocated (on-stack in case of `Secret`) buffer to hold cipher
// length = length(plain) as we are using CTR-approach
@@ -127,7 +127,7 @@ impl Crypto {
}
let secret = self.do_decrypt(password, 32)?;
Ok(Secret::from_unsafe_slice(&secret)?)
Ok(Secret::import_key(&secret)?)
}
/// Try to decrypt and return result as is
@@ -139,7 +139,7 @@ impl Crypto {
fn do_decrypt(&self, password: &Password, expected_len: usize) -> Result<Vec<u8>, Error> {
let (derived_left_bits, derived_right_bits) = match self.kdf {
Kdf::Pbkdf2(ref params) => {
crypto::derive_key_iterations(password.as_bytes(), &params.salt, params.c)
crypto::derive_key_iterations(password.as_bytes(), &params.salt, params.c.get())
}
Kdf::Scrypt(ref params) => crypto::scrypt::derive_key(
password.as_bytes(),
@@ -179,7 +179,7 @@ impl Crypto {
#[cfg(test)]
mod tests {
use super::{Crypto, Error, NonZeroU32};
use ethkey::{Generator, Random};
use crypto::publickey::{Generator, Random};
lazy_static! {
static ref ITERATIONS: NonZeroU32 = NonZeroU32::new(10240).expect("10240 > 0; qed");
@@ -187,7 +187,7 @@ mod tests {
#[test]
fn crypto_with_secret_create() {
let keypair = Random.generate().unwrap();
let keypair = Random.generate();
let passwd = "this is sparta".into();
let crypto = Crypto::with_secret(keypair.secret(), &passwd, *ITERATIONS).unwrap();
let secret = crypto.secret(&passwd).unwrap();
@@ -196,7 +196,7 @@ mod tests {
#[test]
fn crypto_with_secret_invalid_password() {
let keypair = Random.generate().unwrap();
let keypair = Random.generate();
let crypto =
Crypto::with_secret(keypair.secret(), &"this is sparta".into(), *ITERATIONS).unwrap();
assert_matches!(

View File

@@ -16,10 +16,11 @@
use super::crypto::Crypto;
use account::Version;
use crypto;
use ethkey::{
self, crypto::ecdh::agree, sign, Address, KeyPair, Message, Password, Public, Secret, Signature,
use crypto::{
self,
publickey::{ecdh::agree, sign, Address, KeyPair, Message, Public, Secret, Signature},
};
use ethkey::Password;
use json;
use std::num::NonZeroU32;
use Error;
@@ -193,7 +194,7 @@ impl SafeAccount {
message: &[u8],
) -> Result<Vec<u8>, Error> {
let secret = self.crypto.secret(password)?;
ethkey::crypto::ecies::decrypt(&secret, shared_mac, message).map_err(From::from)
crypto::publickey::ecies::decrypt(&secret, shared_mac, message).map_err(From::from)
}
/// Agree on shared key.
@@ -237,7 +238,7 @@ impl SafeAccount {
#[cfg(test)]
mod tests {
use super::{NonZeroU32, SafeAccount};
use ethkey::{verify_public, Generator, Message, Random};
use crypto::publickey::{verify_public, Generator, Random};
lazy_static! {
static ref ITERATIONS: NonZeroU32 = NonZeroU32::new(10240).expect("10240 > 0; qed");
@@ -245,9 +246,9 @@ mod tests {
#[test]
fn sign_and_verify_public() {
let keypair = Random.generate().unwrap();
let keypair = Random.generate();
let password = "hello world".into();
let message = Message::default();
let message = [1u8; 32].into();
let account = SafeAccount::create(
&keypair,
[0u8; 16],
@@ -262,10 +263,10 @@ mod tests {
#[test]
fn change_password() {
let keypair = Random.generate().unwrap();
let keypair = Random.generate();
let first_password = "hello world".into();
let sec_password = "this is sparta".into();
let message = Message::default();
let message = [1u8; 32].into();
let account = SafeAccount::create(
&keypair,
[0u8; 16],

View File

@@ -420,7 +420,7 @@ mod test {
use self::tempdir::TempDir;
use super::{KeyDirectory, RootDiskDirectory, VaultKey};
use account::SafeAccount;
use ethkey::{Generator, Random};
use crypto::publickey::{Generator, Random};
use std::{env, fs, num::NonZeroU32};
lazy_static! {
@@ -432,7 +432,7 @@ mod test {
// given
let mut dir = env::temp_dir();
dir.push("ethstore_should_create_new_account");
let keypair = Random.generate().unwrap();
let keypair = Random.generate();
let password = "hello world".into();
let directory = RootDiskDirectory::create(dir.clone()).unwrap();
@@ -463,7 +463,7 @@ mod test {
// given
let mut dir = env::temp_dir();
dir.push("ethstore_should_handle_duplicate_filenames");
let keypair = Random.generate().unwrap();
let keypair = Random.generate();
let password = "hello world".into();
let directory = RootDiskDirectory::create(dir.clone()).unwrap();
@@ -582,7 +582,7 @@ mod test {
.expect("Files hash should be calculated ok");
assert_eq!(hash, 15130871412783076140);
let keypair = Random.generate().unwrap();
let keypair = Random.generate();
let password = "test pass".into();
let account = SafeAccount::create(
&keypair,

View File

@@ -14,7 +14,7 @@
// You should have received a copy of the GNU General Public License
// along with OpenEthereum. If not, see <http://www.gnu.org/licenses/>.
use ethkey::Address;
use crypto::publickey::Address;
use itertools;
use parking_lot::RwLock;
use std::collections::HashMap;
@@ -70,7 +70,7 @@ impl KeyDirectory for MemoryDirectory {
let mut val = 0u64;
let accounts = self.accounts.read();
for acc in accounts.keys() {
val = val ^ acc.low_u64()
val = val ^ acc.to_low_u64_be()
}
Ok(val)
}

View File

@@ -14,8 +14,7 @@
// You should have received a copy of the GNU General Public License
// along with OpenEthereum. If not, see <http://www.gnu.org/licenses/>.
use crypto::{self, Error as EthCryptoError};
use ethkey::{self, DerivationError, Error as EthKeyError};
use crypto::publickey::DerivationError;
use std::{fmt, io::Error as IoError};
/// Account-related errors.
@@ -45,12 +44,10 @@ pub enum Error {
VaultNotFound,
/// Account creation failed.
CreationFailed,
/// `EthKey` error
EthKey(EthKeyError),
/// `ethkey::crypto::Error`
EthKeyCrypto(ethkey::crypto::Error),
/// `crypto::publickey::Error`
EthCrypto(crypto::Error),
/// `EthCrypto` error
EthCrypto(EthCryptoError),
EthCryptoPublicKey(crypto::publickey::Error),
/// Derivation error
Derivation(DerivationError),
/// Custom error
@@ -72,9 +69,8 @@ impl fmt::Display for Error {
Error::InvalidVaultName => "Invalid vault name".into(),
Error::VaultNotFound => "Vault not found".into(),
Error::CreationFailed => "Account creation failed".into(),
Error::EthKey(ref err) => err.to_string(),
Error::EthKeyCrypto(ref err) => err.to_string(),
Error::EthCrypto(ref err) => err.to_string(),
Error::EthCryptoPublicKey(ref err) => err.to_string(),
Error::Derivation(ref err) => format!("Derivation error: {:?}", err),
Error::Custom(ref s) => s.clone(),
};
@@ -89,20 +85,14 @@ impl From<IoError> for Error {
}
}
impl From<EthKeyError> for Error {
fn from(err: EthKeyError) -> Self {
Error::EthKey(err)
impl From<crypto::publickey::Error> for Error {
fn from(err: crypto::publickey::Error) -> Self {
Error::EthCryptoPublicKey(err)
}
}
impl From<ethkey::crypto::Error> for Error {
fn from(err: ethkey::crypto::Error) -> Self {
Error::EthKeyCrypto(err)
}
}
impl From<EthCryptoError> for Error {
fn from(err: EthCryptoError) -> Self {
impl From<crypto::Error> for Error {
fn from(err: crypto::Error) -> Self {
Error::EthCrypto(err)
}
}

View File

@@ -16,6 +16,7 @@
//! ethkey reexport to make documentation look pretty.
pub use _ethkey::*;
pub use crypto::publickey::Address;
use json;
impl Into<json::H160> for Address {

View File

@@ -24,9 +24,10 @@ use std::{
use account::SafeAccount;
use accounts_dir::{KeyDirectory, SetKeyError, VaultKey, VaultKeyDirectory};
use ethkey::{
self, Address, ExtendedKeyPair, KeyPair, Message, Password, Public, Secret, Signature,
use crypto::publickey::{
self, Address, ExtendedKeyPair, KeyPair, Message, Public, Secret, Signature,
};
use ethkey::Password;
use json::{self, OpaqueKeyFile, Uuid};
use presale::PresaleWallet;
use random::Random;
@@ -554,17 +555,17 @@ impl EthMultiStore {
Derivation::Hierarchical(path) => {
for path_item in path {
extended = extended.derive(if path_item.soft {
ethkey::Derivation::Soft(path_item.index)
publickey::Derivation::Soft(path_item.index)
} else {
ethkey::Derivation::Hard(path_item.index)
publickey::Derivation::Hard(path_item.index)
})?;
}
}
Derivation::SoftHash(h256) => {
extended = extended.derive(ethkey::Derivation::Soft(h256))?;
extended = extended.derive(publickey::Derivation::Soft(h256))?;
}
Derivation::HardHash(h256) => {
extended = extended.derive(ethkey::Derivation::Hard(h256))?;
extended = extended.derive(publickey::Derivation::Hard(h256))?;
}
}
Ok(extended)
@@ -615,7 +616,7 @@ impl SimpleSecretStore for EthMultiStore {
let accounts = self.get_matching(&account_ref, password)?;
for account in accounts {
let extended = self.generate(account.crypto.secret(password)?, derivation)?;
return Ok(ethkey::public_to_address(extended.public().public()));
return Ok(publickey::public_to_address(extended.public().public()));
}
Err(Error::InvalidPassword)
}
@@ -631,7 +632,7 @@ impl SimpleSecretStore for EthMultiStore {
for account in accounts {
let extended = self.generate(account.crypto.secret(password)?, derivation)?;
let secret = extended.secret().as_raw();
return Ok(ethkey::sign(&secret, message)?);
return Ok(publickey::sign(&secret, message)?);
}
Err(Error::InvalidPassword)
}
@@ -898,14 +899,14 @@ mod tests {
use self::tempdir::TempDir;
use super::{EthMultiStore, EthStore};
use accounts_dir::{KeyDirectory, MemoryDirectory, RootDiskDirectory};
use crypto::publickey::{Generator, KeyPair, Random};
use ethereum_types::H256;
use ethkey::{Generator, KeyPair, Random};
use secret_store::{
Derivation, SecretStore, SecretVaultRef, SimpleSecretStore, StoreAccountRef,
};
fn keypair() -> KeyPair {
Random.generate().unwrap()
Random.generate()
}
fn store() -> EthStore {
@@ -1051,6 +1052,7 @@ mod tests {
let passwd2 = "xzy".into();
let multi_store = multi_store();
let keypair = keypair();
let message = [1u8; 32].into();
let address = store
.insert_account(SecretVaultRef::Root, keypair.secret().clone(), &passwd1)
.unwrap();
@@ -1073,9 +1075,7 @@ mod tests {
"First password should work for store."
);
assert!(
multi_store
.sign(&address, &passwd2, &Default::default())
.is_ok(),
multi_store.sign(&address, &passwd2, &message).is_ok(),
"Second password should work for second store."
);
assert_eq!(multi_store.accounts().unwrap().len(), 1);
@@ -1462,7 +1462,7 @@ mod tests {
SecretVaultRef::Root,
&address,
&"test".into(),
Derivation::HardHash(H256::from(0)),
Derivation::HardHash(H256::zero()),
)
.unwrap();
@@ -1470,11 +1470,10 @@ mod tests {
let accounts = store.accounts().unwrap();
assert_eq!(accounts.len(), 2);
let message = [1u8; 32].into();
// and we can sign with the derived contract
assert!(
store
.sign(&derived, &"test".into(), &Default::default())
.is_ok(),
store.sign(&derived, &"test".into(), &message).is_ok(),
"Second password should work for second store."
);
}

View File

@@ -17,7 +17,7 @@
use std::{collections::HashSet, fs, path::Path};
use accounts_dir::{DiskKeyFileManager, KeyDirectory, KeyFileManager};
use ethkey::Address;
use crypto::publickey::Address;
use Error;
/// Import an account from a file.

View File

@@ -74,4 +74,4 @@ pub use self::{
};
/// An opaque wrapper for secret.
pub struct OpaqueSecret(::ethkey::Secret);
pub struct OpaqueSecret(crypto::publickey::Secret);

View File

@@ -14,8 +14,12 @@
// You should have received a copy of the GNU General Public License
// along with OpenEthereum. If not, see <http://www.gnu.org/licenses/>.
use crypto::{self, pbkdf2, Keccak256};
use ethkey::{Address, KeyPair, Password, Secret};
use crypto::{
self, pbkdf2,
publickey::{Address, KeyPair, Secret},
Keccak256,
};
use ethkey::Password;
use json;
use std::{fs, num::NonZeroU32, path::Path};
use Error;
@@ -61,7 +65,7 @@ impl PresaleWallet {
let salt = pbkdf2::Salt(password.as_bytes());
let sec = pbkdf2::Secret(password.as_bytes());
let iter = NonZeroU32::new(2000).expect("2000 > 0; qed");
pbkdf2::sha256(iter, salt, sec, &mut derived_key);
pbkdf2::sha256(iter.get(), salt, sec, &mut derived_key);
let mut key = vec![0; self.ciphertext.len()];
let len =
@@ -69,7 +73,7 @@ impl PresaleWallet {
.map_err(|_| Error::InvalidPassword)?;
let unpadded = &key[..len];
let secret = Secret::from_unsafe_slice(&unpadded.keccak256())?;
let secret = Secret::import_key(&unpadded.keccak256())?;
if let Ok(kp) = KeyPair::from_secret(secret) {
if kp.address() == self.address {
return Ok(kp);

View File

@@ -14,7 +14,7 @@
// You should have received a copy of the GNU General Public License
// along with OpenEthereum. If not, see <http://www.gnu.org/licenses/>.
use rand::{OsRng, Rng};
use rand::{distributions::Alphanumeric, rngs::OsRng, Rng, RngCore};
pub trait Random {
fn random() -> Self
@@ -25,7 +25,7 @@ pub trait Random {
impl Random for [u8; 16] {
fn random() -> Self {
let mut result = [0u8; 16];
let mut rng = OsRng::new().unwrap();
let mut rng = OsRng;
rng.fill_bytes(&mut result);
result
}
@@ -34,7 +34,7 @@ impl Random for [u8; 16] {
impl Random for [u8; 32] {
fn random() -> Self {
let mut result = [0u8; 32];
let mut rng = OsRng::new().unwrap();
let mut rng = OsRng;
rng.fill_bytes(&mut result);
result
}
@@ -42,6 +42,6 @@ impl Random for [u8; 32] {
/// Generate a random string of given length.
pub fn random_string(length: usize) -> String {
let mut rng = OsRng::new().expect("Not able to operate without random source.");
rng.gen_ascii_chars().take(length).collect()
let rng = OsRng;
rng.sample_iter(&Alphanumeric).take(length).collect()
}

View File

@@ -14,8 +14,9 @@
// You should have received a copy of the GNU General Public License
// along with OpenEthereum. If not, see <http://www.gnu.org/licenses/>.
use crypto::publickey::{Address, Message, Public, Secret, Signature};
use ethereum_types::H256;
use ethkey::{Address, Message, Password, Public, Secret, Signature};
use ethkey::Password;
use json::{OpaqueKeyFile, Uuid};
use std::{
cmp::Ordering,
@@ -174,7 +175,7 @@ pub trait SecretStore: SimpleSecretStore {
secret: &OpaqueSecret,
message: &Message,
) -> Result<Signature, Error> {
Ok(::ethkey::sign(&secret.0, message)?)
Ok(crypto::publickey::sign(&secret.0, message)?)
}
/// Imports presale wallet

View File

@@ -14,15 +14,19 @@
// You should have received a copy of the GNU General Public License
// along with OpenEthereum. If not, see <http://www.gnu.org/licenses/>.
extern crate ethereum_types;
extern crate ethstore;
extern crate parity_crypto as crypto;
extern crate rand;
mod util;
use std::str::FromStr;
use crypto::publickey::{verify_address, Generator, KeyPair, Random, Secret};
use ethereum_types::H160;
use ethstore::{
accounts_dir::RootDiskDirectory,
ethkey::{verify_address, Generator, KeyPair, Random, Secret},
EthStore, SecretVaultRef, SimpleSecretStore, StoreAccountRef,
accounts_dir::RootDiskDirectory, EthStore, SecretVaultRef, SimpleSecretStore, StoreAccountRef,
};
use util::TransientDir;
@@ -40,7 +44,7 @@ fn secret_store_open_not_existing() {
}
fn random_secret() -> Secret {
Random.generate().unwrap().secret().clone()
Random.generate().secret().clone()
}
#[test]
@@ -66,13 +70,10 @@ fn secret_store_sign() {
.insert_account(SecretVaultRef::Root, random_secret(), &"".into())
.is_ok());
let accounts = store.accounts().unwrap();
let message = [1u8; 32].into();
assert_eq!(accounts.len(), 1);
assert!(store
.sign(&accounts[0], &"".into(), &Default::default())
.is_ok());
assert!(store
.sign(&accounts[0], &"1".into(), &Default::default())
.is_err());
assert!(store.sign(&accounts[0], &"".into(), &message).is_ok());
assert!(store.sign(&accounts[0], &"1".into(), &message).is_err());
}
#[test]
@@ -83,19 +84,14 @@ fn secret_store_change_password() {
.insert_account(SecretVaultRef::Root, random_secret(), &"".into())
.is_ok());
let accounts = store.accounts().unwrap();
let message = [1u8; 32].into();
assert_eq!(accounts.len(), 1);
assert!(store
.sign(&accounts[0], &"".into(), &Default::default())
.is_ok());
assert!(store.sign(&accounts[0], &"".into(), &message).is_ok());
assert!(store
.change_password(&accounts[0], &"".into(), &"1".into())
.is_ok());
assert!(store
.sign(&accounts[0], &"".into(), &Default::default())
.is_err());
assert!(store
.sign(&accounts[0], &"1".into(), &Default::default())
.is_ok());
assert!(store.sign(&accounts[0], &"".into(), &message).is_err());
assert!(store.sign(&accounts[0], &"1".into(), &message).is_ok());
}
#[test]
@@ -140,9 +136,15 @@ fn secret_store_laod_geth_files() {
assert_eq!(
store.accounts().unwrap(),
vec![
StoreAccountRef::root("3f49624084b67849c7b4e805c5988c21a430f9d9".into()),
StoreAccountRef::root("5ba4dcf897e97c2bdf8315b9ef26c13c085988cf".into()),
StoreAccountRef::root("63121b431a52f8043c16fcf0d1df9cb7b5f66649".into()),
StoreAccountRef::root(
H160::from_str("3f49624084b67849c7b4e805c5988c21a430f9d9").unwrap()
),
StoreAccountRef::root(
H160::from_str("5ba4dcf897e97c2bdf8315b9ef26c13c085988cf").unwrap()
),
StoreAccountRef::root(
H160::from_str("63121b431a52f8043c16fcf0d1df9cb7b5f66649").unwrap()
),
]
);
}
@@ -154,8 +156,12 @@ fn secret_store_load_pat_files() {
assert_eq!(
store.accounts().unwrap(),
vec![
StoreAccountRef::root("3f49624084b67849c7b4e805c5988c21a430f9d9".into()),
StoreAccountRef::root("5ba4dcf897e97c2bdf8315b9ef26c13c085988cf".into()),
StoreAccountRef::root(
H160::from_str("3f49624084b67849c7b4e805c5988c21a430f9d9").unwrap()
),
StoreAccountRef::root(
H160::from_str("5ba4dcf897e97c2bdf8315b9ef26c13c085988cf").unwrap()
),
]
);
}
@@ -182,12 +188,16 @@ fn test_decrypting_files_with_short_ciphertext() {
assert_eq!(
accounts,
vec![
StoreAccountRef::root("31e9d1e6d844bd3a536800ef8d8be6a9975db509".into()),
StoreAccountRef::root("d1e64e5480bfaf733ba7d48712decb8227797a4e".into()),
StoreAccountRef::root(
H160::from_str("31e9d1e6d844bd3a536800ef8d8be6a9975db509").unwrap()
),
StoreAccountRef::root(
H160::from_str("d1e64e5480bfaf733ba7d48712decb8227797a4e").unwrap()
),
]
);
let message = Default::default();
let message = [1u8; 32].into();
let s1 = store.sign(&accounts[0], &"foo".into(), &message).unwrap();
let s2 = store.sign(&accounts[1], &"foo".into(), &message).unwrap();

View File

@@ -18,11 +18,11 @@ use ethstore::{
accounts_dir::{KeyDirectory, RootDiskDirectory},
Error, SafeAccount,
};
use rand::{OsRng, Rng};
use rand::{rngs::OsRng, RngCore};
use std::{env, fs, path::PathBuf};
pub fn random_dir() -> PathBuf {
let mut rng = OsRng::new().unwrap();
let mut rng = OsRng;
let mut dir = env::temp_dir();
dir.push(format!("{:x}-{:x}", rng.next_u64(), rng.next_u64()));
dir

View File

@@ -18,7 +18,8 @@
use std::{collections::HashMap, time::Instant};
use ethkey::{Address, Password};
use crypto::publickey::Address;
use ethkey::Password;
use serde_derive::{Deserialize, Serialize};
use serde_json;

View File

@@ -18,6 +18,8 @@
//! Account management.
extern crate parity_crypto as crypto;
mod account_data;
mod error;
mod stores;
@@ -32,7 +34,8 @@ use std::{
time::{Duration, Instant},
};
use ethkey::{Address, Generator, Message, Password, Public, Random, Secret};
use crypto::publickey::{Address, Generator, Message, Public, Random, Secret};
use ethkey::Password;
use ethstore::{
accounts_dir::MemoryDirectory, random_string, EthMultiStore, EthStore, OpaqueSecret,
SecretStore, SecretVaultRef, SimpleSecretStore, StoreAccountRef,
@@ -40,7 +43,7 @@ use ethstore::{
use log::*;
use parking_lot::RwLock;
pub use ethkey::Signature;
pub use crypto::publickey::Signature;
pub use ethstore::{Derivation, Error, IndexDerivation, KeyFile};
pub use self::{account_data::AccountMeta, error::SignError};
@@ -134,9 +137,7 @@ impl AccountProvider {
/// Creates new random account and returns address and public key
pub fn new_account_and_public(&self, password: &Password) -> Result<(Address, Public), Error> {
let acc = Random
.generate()
.expect("secp context has generation capabilities; qed");
let acc = Random.generate();
let public = acc.public().clone();
let secret = acc.secret().clone();
let account = self
@@ -355,7 +356,8 @@ impl AccountProvider {
} else {
// verify password by signing dump message
// result may be discarded
let _ = self.sstore.sign(&account, &password, &Default::default())?;
let dummy_msg = [1u8; 32].into();
let _ = self.sstore.sign(&account, &password, &dummy_msg)?;
}
let data = AccountData {
@@ -632,15 +634,16 @@ impl AccountProvider {
#[cfg(test)]
mod tests {
use super::{AccountProvider, Unlock};
use crypto::publickey::{Address, Generator, Random};
use ethereum_types::H256;
use ethkey::{Address, Generator, Random};
use ethstore::{Derivation, StoreAccountRef};
use std::time::{Duration, Instant};
#[test]
fn unlock_account_temp() {
let kp = Random.generate().unwrap();
let kp = Random.generate();
let ap = AccountProvider::transient_provider();
let dummy_msg = [1u8; 32].into();
assert!(ap
.insert_account(kp.secret().clone(), &"test".into())
.is_ok());
@@ -650,13 +653,13 @@ mod tests {
assert!(ap
.unlock_account_temporarily(kp.address(), "test".into())
.is_ok());
assert!(ap.sign(kp.address(), None, Default::default()).is_ok());
assert!(ap.sign(kp.address(), None, Default::default()).is_err());
assert!(ap.sign(kp.address(), None, dummy_msg).is_ok());
assert!(ap.sign(kp.address(), None, dummy_msg).is_err());
}
#[test]
fn derived_account_nosave() {
let kp = Random.generate().unwrap();
let kp = Random.generate();
let ap = AccountProvider::transient_provider();
assert!(ap
.insert_account(kp.secret().clone(), &"base".into())
@@ -669,7 +672,7 @@ mod tests {
.derive_account(
&kp.address(),
None,
Derivation::SoftHash(H256::from(999)),
Derivation::SoftHash(H256::from_low_u64_be(999)),
false,
)
.expect("Derivation should not fail");
@@ -683,7 +686,7 @@ mod tests {
#[test]
fn derived_account_save() {
let kp = Random.generate().unwrap();
let kp = Random.generate();
let ap = AccountProvider::transient_provider();
assert!(ap
.insert_account(kp.secret().clone(), &"base".into())
@@ -696,7 +699,7 @@ mod tests {
.derive_account(
&kp.address(),
None,
Derivation::SoftHash(H256::from(999)),
Derivation::SoftHash(H256::from_low_u64_be(999)),
true,
)
.expect("Derivation should not fail");
@@ -716,7 +719,7 @@ mod tests {
#[test]
fn derived_account_sign() {
let kp = Random.generate().unwrap();
let kp = Random.generate();
let ap = AccountProvider::transient_provider();
assert!(ap
.insert_account(kp.secret().clone(), &"base".into())
@@ -729,14 +732,14 @@ mod tests {
.derive_account(
&kp.address(),
None,
Derivation::SoftHash(H256::from(1999)),
Derivation::SoftHash(H256::from_low_u64_be(1999)),
true,
)
.expect("Derivation should not fail");
ap.unlock_account_permanently(derived_addr, "base".into())
.expect("Should be ok because account is saved and password is valid");
let msg = Default::default();
let msg = [2u8; 32].into();
let signed_msg1 = ap
.sign(derived_addr, None, msg)
.expect("Signing with existing unlocked account should not fail");
@@ -744,7 +747,7 @@ mod tests {
.sign_derived(
&kp.address(),
None,
Derivation::SoftHash(H256::from(1999)),
Derivation::SoftHash(H256::from_low_u64_be(1999)),
msg,
)
.expect("Derived signing with existing unlocked account should not fail");
@@ -754,8 +757,9 @@ mod tests {
#[test]
fn unlock_account_perm() {
let kp = Random.generate().unwrap();
let kp = Random.generate();
let ap = AccountProvider::transient_provider();
let dummy_msg = [1u8; 32].into();
assert!(ap
.insert_account(kp.secret().clone(), &"test".into())
.is_ok());
@@ -765,19 +769,20 @@ mod tests {
assert!(ap
.unlock_account_permanently(kp.address(), "test".into())
.is_ok());
assert!(ap.sign(kp.address(), None, Default::default()).is_ok());
assert!(ap.sign(kp.address(), None, Default::default()).is_ok());
assert!(ap.sign(kp.address(), None, dummy_msg).is_ok());
assert!(ap.sign(kp.address(), None, dummy_msg).is_ok());
assert!(ap
.unlock_account_temporarily(kp.address(), "test".into())
.is_ok());
assert!(ap.sign(kp.address(), None, Default::default()).is_ok());
assert!(ap.sign(kp.address(), None, Default::default()).is_ok());
assert!(ap.sign(kp.address(), None, dummy_msg).is_ok());
assert!(ap.sign(kp.address(), None, dummy_msg).is_ok());
}
#[test]
fn unlock_account_timer() {
let kp = Random.generate().unwrap();
let kp = Random.generate();
let ap = AccountProvider::transient_provider();
let dummy_msg = [1u8; 32].into();
assert!(ap
.insert_account(kp.secret().clone(), &"test".into())
.is_ok());
@@ -787,35 +792,35 @@ mod tests {
assert!(ap
.unlock_account_timed(kp.address(), "test".into(), Duration::from_secs(60))
.is_ok());
assert!(ap.sign(kp.address(), None, Default::default()).is_ok());
assert!(ap.sign(kp.address(), None, dummy_msg).is_ok());
ap.unlocked
.write()
.get_mut(&StoreAccountRef::root(kp.address()))
.unwrap()
.unlock = Unlock::Timed(Instant::now());
assert!(ap.sign(kp.address(), None, Default::default()).is_err());
assert!(ap.sign(kp.address(), None, dummy_msg).is_err());
}
#[test]
fn should_sign_and_return_token() {
// given
let kp = Random.generate().unwrap();
let kp = Random.generate();
let ap = AccountProvider::transient_provider();
let dummy_msg = [1u8; 32].into();
assert!(ap
.insert_account(kp.secret().clone(), &"test".into())
.is_ok());
// when
let (_signature, token) = ap
.sign_with_token(kp.address(), "test".into(), Default::default())
.sign_with_token(kp.address(), "test".into(), dummy_msg)
.unwrap();
// then
ap.sign_with_token(kp.address(), token.clone(), Default::default())
ap.sign_with_token(kp.address(), token.clone(), dummy_msg)
.expect("First usage of token should be correct.");
assert!(
ap.sign_with_token(kp.address(), token, Default::default())
.is_err(),
ap.sign_with_token(kp.address(), token, dummy_msg).is_err(),
"Second usage of the same token should fail."
);
}

View File

@@ -22,7 +22,7 @@ use std::{
path::{Path, PathBuf},
};
use ethkey::Address;
use crypto::publickey::Address;
use log::{trace, warn};
use crate::AccountMeta;
@@ -172,6 +172,7 @@ impl<K: hash::Hash + Eq, V> DiskMap<K, V> {
mod tests {
use super::AddressBook;
use crate::account_data::AccountMeta;
use ethereum_types::H160;
use std::collections::HashMap;
use tempdir::TempDir;
@@ -179,8 +180,8 @@ mod tests {
fn should_save_and_reload_address_book() {
let tempdir = TempDir::new("").unwrap();
let mut b = AddressBook::new(tempdir.path());
b.set_name(1.into(), "One".to_owned());
b.set_meta(1.into(), "{1:1}".to_owned());
b.set_name(H160::from_low_u64_be(1), "One".to_owned());
b.set_meta(H160::from_low_u64_be(1), "{1:1}".to_owned());
let b = AddressBook::new(tempdir.path());
assert_eq!(
b.get(),
@@ -193,7 +194,7 @@ mod tests {
}
)]
.into_iter()
.map(|(a, b)| (a.into(), b))
.map(|(a, b)| (H160::from_low_u64_be(a), b))
.collect::<HashMap<_, _>>()
);
}
@@ -203,10 +204,10 @@ mod tests {
let tempdir = TempDir::new("").unwrap();
let mut b = AddressBook::new(tempdir.path());
b.set_name(1.into(), "One".to_owned());
b.set_name(2.into(), "Two".to_owned());
b.set_name(3.into(), "Three".to_owned());
b.remove(2.into());
b.set_name(H160::from_low_u64_be(1), "One".to_owned());
b.set_name(H160::from_low_u64_be(2), "Two".to_owned());
b.set_name(H160::from_low_u64_be(3), "Three".to_owned());
b.remove(H160::from_low_u64_be(2));
let b = AddressBook::new(tempdir.path());
assert_eq!(
@@ -230,7 +231,7 @@ mod tests {
),
]
.into_iter()
.map(|(a, b)| (a.into(), b))
.map(|(a, b)| (H160::from_low_u64_be(a), b))
.collect::<HashMap<_, _>>()
);
}

View File

@@ -7,8 +7,9 @@ authors = ["Parity Technologies <admin@parity.io>"]
[dependencies]
crunchy = "0.1.0"
either = "1.0.0"
ethereum-types = "0.4"
keccak-hash = "0.1"
ethereum-types = "0.9.2"
keccak-hash = "0.5.0"
tiny-keccak = "2.0.2"
log = "0.4"
memmap = "0.6"
parking_lot = "0.7"

View File

@@ -21,7 +21,7 @@ use memmap::MmapMut;
use parking_lot::Mutex;
use seed_compute::SeedHashCompute;
use shared::{epoch, get_cache_size, to_hex, Node, ETHASH_CACHE_ROUNDS, NODE_BYTES, NODE_DWORDS};
use shared::{epoch, get_cache_size, to_hex, Node, ETHASH_CACHE_ROUNDS, NODE_BYTES};
use std::{
borrow::Cow,
@@ -318,27 +318,22 @@ impl AsRef<[Node]> for NodeCache {
// out. It counts as a read and causes all writes afterwards to be elided. Yes, really. I know, I
// want to refactor this to use less `unsafe` as much as the next rustacean.
unsafe fn initialize_memory(memory: *mut Node, num_nodes: usize, ident: &H256) {
let dst = memory as *mut u8;
// We use raw pointers here, see above
let dst = slice::from_raw_parts_mut(memory as *mut u8, NODE_BYTES);
debug_assert_eq!(ident.len(), 32);
keccak_512::unchecked(dst, NODE_BYTES, ident.as_ptr(), ident.len());
keccak_512::write(&ident[..], dst);
for i in 1..num_nodes {
// We use raw pointers here, see above
let dst = memory.offset(i as _) as *mut u8;
let src = memory.offset(i as isize - 1) as *mut u8;
keccak_512::unchecked(dst, NODE_BYTES, src, NODE_BYTES);
let dst = slice::from_raw_parts_mut(memory.offset(i as _) as *mut u8, NODE_BYTES);
let src = slice::from_raw_parts(memory.offset(i as isize - 1) as *mut u8, NODE_BYTES);
keccak_512::write(src, dst);
}
// Now this is initialized, we can treat it as a slice.
let nodes: &mut [Node] = slice::from_raw_parts_mut(memory, num_nodes);
// For `unroll!`, see below. If the literal in `unroll!` is not the same as the RHS here then
// these have got out of sync! Don't let this happen!
debug_assert_eq!(NODE_DWORDS, 8);
// This _should_ get unrolled by the compiler, since it's not using the loop variable.
for _ in 0..ETHASH_CACHE_ROUNDS {
for i in 0..num_nodes {
let data_idx = (num_nodes - 1 + i) % num_nodes;
@@ -348,11 +343,8 @@ unsafe fn initialize_memory(memory: *mut Node, num_nodes: usize, ident: &H256) {
let mut data: Node = nodes.get_unchecked(data_idx).clone();
let rhs: &Node = nodes.get_unchecked(idx);
unroll! {
for w in 0..8 {
*data.as_dwords_mut().get_unchecked_mut(w) ^=
*rhs.as_dwords().get_unchecked(w);
}
for (a, b) in data.as_dwords_mut().iter_mut().zip(rhs.as_dwords()) {
*a ^= *b;
}
data

View File

@@ -26,7 +26,7 @@ use seed_compute::SeedHashCompute;
use shared::*;
use std::io;
use std::{mem, path::Path, ptr};
use std::{mem, path::Path};
const MIX_WORDS: usize = ETHASH_MIX_BYTES / 4;
const MIX_NODES: usize = MIX_WORDS / NODE_WORDS;
@@ -141,31 +141,24 @@ pub fn quick_get_difficulty(
mix_hash: &H256,
progpow: bool,
) -> H256 {
unsafe {
if progpow {
let seed = keccak_f800_short(*header_hash, nonce, [0u32; 8]);
keccak_f800_long(*header_hash, seed, mem::transmute(*mix_hash))
} else {
// This is safe - the `keccak_512` call below reads the first 40 bytes (which we explicitly set
// with two `copy_nonoverlapping` calls) but writes the first 64, and then we explicitly write
// the next 32 bytes before we read the whole thing with `keccak_256`.
//
// This cannot be elided by the compiler as it doesn't know the implementation of
// `keccak_512`.
let mut buf: [u8; 64 + 32] = ::mem::MaybeUninit::uninit().assume_init();
if progpow {
let seed = keccak_f800_short(*header_hash, nonce, [0u32; 8]);
keccak_f800_long(*header_hash, seed, unsafe { mem::transmute(*mix_hash) })
} else {
let mut buf = [0u8; 64 + 32];
ptr::copy_nonoverlapping(header_hash.as_ptr(), buf.as_mut_ptr(), 32);
ptr::copy_nonoverlapping(&nonce as *const u64 as *const u8, buf[32..].as_mut_ptr(), 8);
let hash_len = header_hash.len();
buf[..hash_len].copy_from_slice(header_hash);
let end = hash_len + mem::size_of::<u64>();
buf[hash_len..end].copy_from_slice(&nonce.to_ne_bytes());
keccak_512::unchecked(buf.as_mut_ptr(), 64, buf.as_ptr(), 40);
ptr::copy_nonoverlapping(mix_hash.as_ptr(), buf[64..].as_mut_ptr(), 32);
keccak_512::inplace_range(&mut buf, 0..end);
buf[64..].copy_from_slice(mix_hash);
// This is initialized in `keccak_256`
let mut hash: [u8; 32] = ::mem::MaybeUninit::uninit().assume_init();
keccak_256::unchecked(hash.as_mut_ptr(), hash.len(), buf.as_ptr(), buf.len());
let mut hash = [0u8; 32];
keccak_256::write(&buf, &mut hash);
hash
}
hash
}
}
@@ -214,32 +207,21 @@ fn hash_compute(light: &Light, full_size: usize, header_hash: &H256, nonce: u64)
// improvements, since I can't imagine that 3-5% of our runtime is taken up by catting two
// arrays together.
let mut buf: MixBuf = MixBuf {
half_mix: unsafe {
half_mix: {
// Pack `header_hash` and `nonce` together
// We explicitly write the first 40 bytes, leaving the last 24 as uninitialized. Then
// `keccak_512` reads the first 40 bytes (4th parameter) and overwrites the entire array,
// leaving it fully initialized.
let mut out: [u8; NODE_BYTES] = ::mem::MaybeUninit::uninit().assume_init();
let mut out = [0u8; NODE_BYTES];
ptr::copy_nonoverlapping(header_hash.as_ptr(), out.as_mut_ptr(), header_hash.len());
ptr::copy_nonoverlapping(
&nonce as *const u64 as *const u8,
out[header_hash.len()..].as_mut_ptr(),
mem::size_of::<u64>(),
);
let hash_len = header_hash.len();
out[..hash_len].copy_from_slice(header_hash);
let end = hash_len + mem::size_of::<u64>();
out[hash_len..end].copy_from_slice(&nonce.to_ne_bytes());
// compute keccak-512 hash and replicate across mix
keccak_512::unchecked(
out.as_mut_ptr(),
NODE_BYTES,
out.as_ptr(),
header_hash.len() + mem::size_of::<u64>(),
);
keccak_512::inplace_range(&mut out, 0..end);
Node { bytes: out }
},
// This is fully initialized before being read, see `let mut compress = ...` below
compress_bytes: unsafe { ::mem::MaybeUninit::uninit().assume_init() },
compress_bytes: [0u8; MIX_WORDS],
};
let mut mix: [_; MIX_NODES] = [buf.half_mix.clone(), buf.half_mix.clone()];
@@ -263,24 +245,13 @@ fn hash_compute(light: &Light, full_size: usize, header_hash: &H256, nonce: u64)
fnv_hash(first_val ^ i, mix_words[i as usize % MIX_WORDS]) % num_full_pages
};
unroll! {
// MIX_NODES
for n in 0..2 {
let tmp_node = calculate_dag_item(
index * MIX_NODES as u32 + n as u32,
cache,
);
// MIX_NODES
for n in 0..2 {
let tmp_node = calculate_dag_item(index * MIX_NODES as u32 + n as u32, cache);
unroll! {
// NODE_WORDS
for w in 0..16 {
mix[n].as_words_mut()[w] =
fnv_hash(
mix[n].as_words()[w],
tmp_node.as_words()[w],
);
}
}
// NODE_WORDS
for (a, b) in mix[n].as_words_mut().iter_mut().zip(tmp_node.as_words()) {
*a = fnv_hash(*a, *b);
}
}
}
@@ -288,25 +259,27 @@ fn hash_compute(light: &Light, full_size: usize, header_hash: &H256, nonce: u64)
let mix_words: [u32; MIX_WORDS] = unsafe { mem::transmute(mix) };
{
// This is an uninitialized buffer to begin with, but we iterate precisely `compress.len()`
// times and set each index, leaving the array fully initialized. THIS ONLY WORKS ON LITTLE-
// ENDIAN MACHINES. See a future PR to make this and the rest of the code work correctly on
// We iterate precisely `compress.len()` times and set each index,
// leaving the array fully initialized. THIS ONLY WORKS ON LITTLE-ENDIAN MACHINES.
// See a future PR to make this and the rest of the code work correctly on
// big-endian arches like mips.
let compress: &mut [u32; MIX_WORDS / 4] =
unsafe { make_const_array!(MIX_WORDS / 4, &mut buf.compress_bytes) };
#[cfg(target_endian = "big")]
{
compile_error!("OpenEthereum currently only supports little-endian targets");
}
// Compress mix
debug_assert_eq!(MIX_WORDS / 4, 8);
unroll! {
for i in 0..8 {
let w = i * 4;
for i in 0..8 {
let w = i * 4;
let mut reduction = mix_words[w + 0];
reduction = reduction.wrapping_mul(FNV_PRIME) ^ mix_words[w + 1];
reduction = reduction.wrapping_mul(FNV_PRIME) ^ mix_words[w + 2];
reduction = reduction.wrapping_mul(FNV_PRIME) ^ mix_words[w + 3];
compress[i] = reduction;
}
let mut reduction = mix_words[w + 0];
reduction = reduction.wrapping_mul(FNV_PRIME) ^ mix_words[w + 1];
reduction = reduction.wrapping_mul(FNV_PRIME) ^ mix_words[w + 2];
reduction = reduction.wrapping_mul(FNV_PRIME) ^ mix_words[w + 3];
compress[i] = reduction;
}
}
@@ -315,24 +288,20 @@ fn hash_compute(light: &Light, full_size: usize, header_hash: &H256, nonce: u64)
let value: H256 = {
// We can interpret the buffer as an array of `u8`s, since it's `repr(C)`.
let read_ptr: *const u8 = &buf as *const MixBuf as *const u8;
// We overwrite the second half since `keccak_256` has an internal buffer and so allows
// overlapping arrays as input.
let write_ptr: *mut u8 = &mut buf.compress_bytes as *mut [u8; 32] as *mut u8;
unsafe {
keccak_256::unchecked(
write_ptr,
buf.compress_bytes.len(),
let buffer = unsafe {
core::slice::from_raw_parts(
read_ptr,
buf.half_mix.bytes.len() + buf.compress_bytes.len(),
);
}
)
};
// We overwrite the buf.compress_bytes since `keccak_256` has an internal buffer and so allows
// overlapping arrays as input.
keccak_256::write(buffer, &mut buf.compress_bytes);
buf.compress_bytes
};
ProofOfWork {
mix_hash: mix_hash,
value: value,
}
ProofOfWork { mix_hash, value }
}
// TODO: Use the `simd` crate

View File

@@ -21,46 +21,15 @@ pub type H256 = [u8; 32];
pub mod keccak_512 {
use super::hash;
pub use self::hash::keccak_512_unchecked as unchecked;
pub fn write(input: &[u8], output: &mut [u8]) {
hash::keccak_512(input, output);
}
pub fn inplace(input: &mut [u8]) {
// This is safe since `keccak_*` uses an internal buffer and copies the result to the output. This
// means that we can reuse the input buffer for both input and output.
unsafe {
hash::keccak_512_unchecked(
input.as_mut_ptr(),
input.len(),
input.as_ptr(),
input.len(),
);
}
}
pub use self::hash::{
keccak512 as inplace, keccak512_range as inplace_range, keccak_512 as write,
};
}
pub mod keccak_256 {
use super::hash;
pub use self::hash::keccak_256_unchecked as unchecked;
#[allow(dead_code)]
pub fn write(input: &[u8], output: &mut [u8]) {
hash::keccak_256(input, output);
}
pub fn inplace(input: &mut [u8]) {
// This is safe since `keccak_*` uses an internal buffer and copies the result to the output. This
// means that we can reuse the input buffer for both input and output.
unsafe {
hash::keccak_256_unchecked(
input.as_mut_ptr(),
input.len(),
input.as_ptr(),
input.len(),
);
}
}
pub use self::hash::{
keccak256 as inplace, keccak256_range as inplace_range, keccak_256 as write,
};
}

View File

@@ -19,6 +19,7 @@ extern crate ethereum_types;
extern crate memmap;
extern crate parking_lot;
extern crate primal;
extern crate tiny_keccak;
#[macro_use]
extern crate crunchy;
@@ -52,12 +53,13 @@ mod progpow;
pub use cache::{NodeCacheBuilder, OptimizeFor};
use compute::Light;
pub use compute::{quick_get_difficulty, slow_hash_block_number, ProofOfWork};
use ethereum_types::{U256, U512};
use ethereum_types::{BigEndianHash, U256, U512};
use keccak::H256;
use parking_lot::Mutex;
pub use seed_compute::SeedHashCompute;
pub use shared::ETHASH_EPOCH_LENGTH;
use std::{
convert::TryFrom,
mem,
path::{Path, PathBuf},
};
@@ -168,12 +170,12 @@ impl EthashManager {
/// Convert an Ethash boundary to its original difficulty. Basically just `f(x) = 2^256 / x`.
pub fn boundary_to_difficulty(boundary: &ethereum_types::H256) -> U256 {
difficulty_to_boundary_aux(&**boundary)
difficulty_to_boundary_aux(&boundary.into_uint())
}
/// Convert an Ethash difficulty to the target boundary. Basically just `f(x) = 2^256 / x`.
pub fn difficulty_to_boundary(difficulty: &U256) -> ethereum_types::H256 {
difficulty_to_boundary_aux(difficulty).into()
BigEndianHash::from_uint(&difficulty_to_boundary_aux(difficulty))
}
fn difficulty_to_boundary_aux<T: Into<U512>>(difficulty: T) -> ethereum_types::U256 {
@@ -184,8 +186,8 @@ fn difficulty_to_boundary_aux<T: Into<U512>>(difficulty: T) -> ethereum_types::U
if difficulty == U512::one() {
U256::max_value()
} else {
// difficulty > 1, so result should never overflow 256 bits
U256::from((U512::one() << 256) / difficulty)
const PROOF: &str = "difficulty > 1, so result never overflows 256 bits; qed";
U256::try_from((U512::one() << 256) / difficulty).expect(PROOF)
}
}
@@ -210,12 +212,12 @@ fn test_lru() {
#[test]
fn test_difficulty_to_boundary() {
use ethereum_types::H256;
use ethereum_types::{BigEndianHash, H256};
use std::str::FromStr;
assert_eq!(
difficulty_to_boundary(&U256::from(1)),
H256::from(U256::max_value())
BigEndianHash::from_uint(&U256::max_value())
);
assert_eq!(
difficulty_to_boundary(&U256::from(2)),
@@ -243,16 +245,18 @@ fn test_difficulty_to_boundary_regression() {
boundary_to_difficulty(&difficulty_to_boundary(&difficulty.into()))
);
assert_eq!(
H256::from(difficulty),
difficulty_to_boundary(&boundary_to_difficulty(&difficulty.into()))
H256::from_low_u64_be(difficulty),
difficulty_to_boundary(&boundary_to_difficulty(&H256::from_low_u64_be(difficulty)))
);
assert_eq!(
U256::from(difficulty),
boundary_to_difficulty(&boundary_to_difficulty(&difficulty.into()).into())
boundary_to_difficulty(&BigEndianHash::from_uint(&boundary_to_difficulty(
&H256::from_low_u64_be(difficulty)
))),
);
assert_eq!(
H256::from(difficulty),
difficulty_to_boundary(&difficulty_to_boundary(&difficulty.into()).into())
H256::from_low_u64_be(difficulty),
difficulty_to_boundary(&difficulty_to_boundary(&difficulty.into()).into_uint())
);
}
}
@@ -266,5 +270,5 @@ fn test_difficulty_to_boundary_panics_on_zero() {
#[test]
#[should_panic]
fn test_boundary_to_difficulty_panics_on_zero() {
boundary_to_difficulty(&ethereum_types::H256::from(0));
boundary_to_difficulty(&ethereum_types::H256::zero());
}

View File

@@ -17,20 +17,21 @@ url = { version = "2", optional = true }
ansi_term = "0.10"
common-types = { path = "../../ethcore/types" }
error-chain = "0.12"
ethabi = "6.0"
ethabi-derive = "6.0"
ethabi-contract = "6.0"
ethabi = "12.0.0"
ethabi-derive = "12.0.0"
ethabi-contract = "11.0.0"
ethcore-call-contract = { path = "../../vm/call-contract" }
ethereum-types = "0.4"
ethereum-types = "0.9.2"
futures = "0.1"
heapsize = "0.4"
keccak-hash = "0.1"
keccak-hash = "0.5.0"
linked-hash-map = "0.5"
log = "0.4"
parity-crypto = { version = "0.6.2", features = [ "publickey" ] }
parity-runtime = { path = "../../runtime/runtime" }
parity-util-mem = "0.7"
parking_lot = "0.7"
price-info = { path = "./price-info", optional = true }
rlp = { version = "0.3.0", features = ["ethereum"] }
rlp = { version = "0.4.6" }
trace-time = "0.1"
transaction-pool = "2.0.1"

View File

@@ -10,7 +10,8 @@ ethcore-io = { path = "../../../runtime/io" }
ethcore-db = { path = "../../../db/db"}
kvdb = "0.1"
log = "0.4"
rlp = { version = "0.3.0", features = ["ethereum"] }
parity-crypto = { version = "0.6.2", features = [ "publickey" ] }
rlp = { version = "0.4.6" }
serde = "1.0"
serde_derive = "1.0"
serde_json = "1.0"

View File

@@ -29,6 +29,7 @@ extern crate common_types as types;
extern crate ethcore_db;
extern crate ethcore_io as io;
extern crate kvdb;
extern crate parity_crypto as crypto;
extern crate rlp;
extern crate serde;
extern crate serde_json;
@@ -238,7 +239,7 @@ impl<T: NodeInfo> Drop for LocalDataStore<T> {
mod tests {
use super::NodeInfo;
use ethkey::{Brain, Generator};
use ethkey::Brain;
use std::sync::Arc;
use types::transaction::{Condition, PendingTransaction, Transaction, TypedTransaction};
@@ -269,7 +270,7 @@ mod tests {
#[test]
fn with_condition() {
let keypair = Brain::new("abcd".into()).generate().unwrap();
let keypair = Brain::new("abcd".into()).generate();
let transactions: Vec<_> = (0..10u64)
.map(|nonce| {
let mut tx = TypedTransaction::Legacy(Transaction::default());
@@ -306,7 +307,7 @@ mod tests {
#[test]
fn skips_bad_transactions() {
let keypair = Brain::new("abcd".into()).generate().unwrap();
let keypair = Brain::new("abcd".into()).generate();
let mut transactions: Vec<_> = (0..10u64)
.map(|nonce| {
let mut tx = TypedTransaction::Legacy(Transaction::default());

View File

@@ -92,7 +92,7 @@ mod tests {
// given
let m = miner();
assert_eq!(m.hashrate(), U256::from(0));
m.submit_hashrate(U256::from(10), H256::from(1));
m.submit_hashrate(U256::from(10), H256::from_low_u64_be(1));
assert_eq!(m.hashrate(), U256::from(10));
// when
@@ -107,12 +107,12 @@ mod tests {
// given
let m = miner();
assert_eq!(m.hashrate(), U256::from(0));
m.submit_hashrate(U256::from(10), H256::from(1));
m.submit_hashrate(U256::from(10), H256::from_low_u64_be(1));
assert_eq!(m.hashrate(), U256::from(10));
// when
m.submit_hashrate(U256::from(15), H256::from(1));
m.submit_hashrate(U256::from(20), H256::from(2));
m.submit_hashrate(U256::from(15), H256::from_low_u64_be(1));
m.submit_hashrate(U256::from(20), H256::from_low_u64_be(2));
// then
assert_eq!(m.hashrate(), U256::from(35));

View File

@@ -22,13 +22,15 @@
extern crate ansi_term;
extern crate common_types as types;
extern crate ethabi;
extern crate ethabi_derive;
extern crate ethcore_call_contract as call_contract;
extern crate ethereum_types;
extern crate futures;
extern crate heapsize;
extern crate keccak_hash as hash;
extern crate linked_hash_map;
extern crate parity_crypto as crypto;
extern crate parity_runtime;
extern crate parity_util_mem;
extern crate parking_lot;
#[cfg(feature = "price-info")]
extern crate price_info;
@@ -38,8 +40,6 @@ extern crate transaction_pool as txpool;
#[macro_use]
extern crate ethabi_contract;
#[macro_use]
extern crate ethabi_derive;
#[macro_use]
extern crate error_chain;
#[macro_use]
extern crate log;

View File

@@ -124,6 +124,7 @@ impl txpool::Listener<Transaction> for Logger {
#[cfg(test)]
mod tests {
use super::*;
use ethereum_types::H160;
use parking_lot::Mutex;
use txpool::Listener;
use types::transaction;
@@ -166,7 +167,7 @@ mod tests {
gas_price: 5.into(),
value: 0.into(),
})
.fake_sign(5.into());
.fake_sign(H160::from_low_u64_be(5));
Arc::new(Transaction::from_pending_block_transaction(signed))
}

View File

@@ -254,8 +254,8 @@ impl txpool::Listener<Transaction> for LocalTransactionsList {
#[cfg(test)]
mod tests {
use super::*;
use crypto::publickey::{Generator, Random};
use ethereum_types::U256;
use ethkey::{Generator, Random};
use txpool::Listener;
use types::transaction;
@@ -339,7 +339,7 @@ mod tests {
}
fn new_tx<T: Into<U256>>(nonce: T) -> Arc<Transaction> {
let keypair = Random.generate().unwrap();
let keypair = Random.generate();
let signed = transaction::TypedTransaction::Legacy(transaction::Transaction {
action: transaction::Action::Create,
value: U256::from(100),

View File

@@ -17,7 +17,7 @@
//! Transaction Pool
use ethereum_types::{Address, H256, U256};
use heapsize::HeapSizeOf;
use parity_util_mem::MallocSizeOfExt;
use txpool;
use types::transaction;
@@ -177,7 +177,7 @@ impl txpool::VerifiedTransaction for VerifiedTransaction {
}
fn mem_usage(&self) -> usize {
self.transaction.heap_size_of_children()
self.transaction.malloc_size_of()
}
fn sender(&self) -> &Address {

View File

@@ -117,7 +117,7 @@ where
mod tests {
use super::*;
use ethkey::{Generator, KeyPair, Random};
use crypto::publickey::{Generator, KeyPair, Random};
use pool::{
scoring::*,
tests::{
@@ -160,7 +160,7 @@ mod tests {
let replace = ReplaceByScoreAndReadiness::new(scoring, client);
// same sender txs
let keypair = Random.generate().unwrap();
let keypair = Random.generate();
let same_sender_tx1 = local_tx_verified(
Tx {
@@ -190,7 +190,7 @@ mod tests {
);
// different sender txs
let sender1 = Random.generate().unwrap();
let sender1 = Random.generate();
let different_sender_tx1 = local_tx_verified(
Tx {
nonce: 2,
@@ -200,7 +200,7 @@ mod tests {
&sender1,
);
let sender2 = Random.generate().unwrap();
let sender2 = Random.generate();
let different_sender_tx2 = local_tx_verified(
Tx {
nonce: 1,
@@ -274,7 +274,7 @@ mod tests {
..Default::default()
};
let keypair = Random.generate().unwrap();
let keypair = Random.generate();
let txs = vec![tx1, tx2, tx3, tx4]
.into_iter()
.map(|tx| tx.unsigned().sign(keypair.secret(), None).verified())
@@ -440,7 +440,7 @@ mod tests {
let client = TestClient::new().with_nonce(1);
let replace = ReplaceByScoreAndReadiness::new(scoring, client);
let old_sender = Random.generate().unwrap();
let old_sender = Random.generate();
let tx_old_ready_1 = {
let tx = Tx {
nonce: 1,
@@ -518,7 +518,7 @@ mod tests {
tx.signed().verified()
};
let new_sender = Random.generate().unwrap();
let new_sender = Random.generate();
let tx_new_ready_1 = {
let tx = Tx {
nonce: 1,
@@ -586,7 +586,7 @@ mod tests {
tx.signed().verified()
};
let new_sender = Random.generate().unwrap();
let new_sender = Random.generate();
let tx_new_ready_1 = local_tx_verified(
Tx {
nonce: 1,
@@ -641,7 +641,7 @@ mod tests {
tx.signed().verified()
};
let new_sender = Random.generate().unwrap();
let new_sender = Random.generate();
let tx_new_ready_1 = local_tx_verified(
Tx {
nonce: 1,

View File

@@ -14,8 +14,8 @@
// You should have received a copy of the GNU General Public License
// along with OpenEthereum. If not, see <http://www.gnu.org/licenses/>.
use crypto::publickey::{Generator, Random};
use ethereum_types::{H256, U256};
use ethkey::{Generator, Random};
use rustc_hex::FromHex;
use types::transaction::{
self, SignedTransaction, Transaction, TypedTransaction, UnverifiedTransaction,
@@ -49,7 +49,7 @@ impl Tx {
}
pub fn signed(self) -> SignedTransaction {
let keypair = Random.generate().unwrap();
let keypair = Random.generate();
self.unsigned().sign(keypair.secret(), None)
}
@@ -59,7 +59,7 @@ impl Tx {
}
pub fn signed_triple(mut self) -> (SignedTransaction, SignedTransaction, SignedTransaction) {
let keypair = Random.generate().unwrap();
let keypair = Random.generate();
let tx1 = self.clone().unsigned().sign(keypair.secret(), None);
self.nonce += 1;
let tx2 = self.clone().unsigned().sign(keypair.secret(), None);
@@ -70,7 +70,7 @@ impl Tx {
}
pub fn signed_replacement(mut self) -> (SignedTransaction, SignedTransaction) {
let keypair = Random.generate().unwrap();
let keypair = Random.generate();
let tx1 = self.clone().unsigned().sign(keypair.secret(), None);
self.gas_price += 1;
let tx2 = self.unsigned().sign(keypair.secret(), None);
@@ -90,7 +90,7 @@ impl Tx {
}
pub fn big_one(self) -> SignedTransaction {
let keypair = Random.generate().unwrap();
let keypair = Random.generate();
let tx = TypedTransaction::Legacy(Transaction {
action: transaction::Action::Create,
value: U256::from(100),

View File

@@ -6,8 +6,8 @@ license = "GPL-3.0"
authors = ["Parity Technologies <admin@parity.io>"]
[dependencies]
ethereum-types = "0.4"
keccak-hash = "0.1"
ethereum-types = "0.9.2"
keccak-hash = "0.5.0"
jsonrpc-core = "15.0.0"
jsonrpc-tcp-server = "15.0.0"
log = "0.4"

View File

@@ -6,7 +6,7 @@ authors = ["Parity Technologies <admin@parity.io>"]
[dependencies]
byteorder = "1.2"
ethbloom = "=0.5.0"
ethbloom = "0.9.1"
parking_lot = "0.7"
tiny-keccak = "1.4"

View File

@@ -40,7 +40,7 @@ fn bench_blooms_filter_1_million_ok(c: &mut Criterion) {
database
.insert_blooms(999_999, iter::once(&Bloom::zero()))
.unwrap();
let bloom = Bloom::from(0x001);
let bloom = Bloom::from_low_u64_be(0x001);
database.insert_blooms(200_000, iter::once(&bloom)).unwrap();
database.insert_blooms(400_000, iter::once(&bloom)).unwrap();
database.insert_blooms(600_000, iter::once(&bloom)).unwrap();
@@ -60,8 +60,8 @@ fn bench_blooms_filter_1_million_miss(c: &mut Criterion) {
database
.insert_blooms(999_999, iter::once(&Bloom::zero()))
.unwrap();
let bloom = Bloom::from(0x001);
let bad_bloom = Bloom::from(0x0001);
let bloom = Bloom::from_low_u64_be(0x001);
let bad_bloom = Bloom::from_low_u64_be(0x0001);
database.insert_blooms(200_000, iter::once(&bloom)).unwrap();
database.insert_blooms(400_000, iter::once(&bloom)).unwrap();
database.insert_blooms(600_000, iter::once(&bloom)).unwrap();
@@ -81,8 +81,8 @@ fn bench_blooms_filter_1_million_miss_and_ok(c: &mut Criterion) {
database
.insert_blooms(999_999, iter::once(&Bloom::zero()))
.unwrap();
let bloom = Bloom::from(0x001);
let bad_bloom = Bloom::from(0x0001);
let bloom = Bloom::from_low_u64_be(0x001);
let bad_bloom = Bloom::from_low_u64_be(0x0001);
database.insert_blooms(200_000, iter::once(&bloom)).unwrap();
database.insert_blooms(400_000, iter::once(&bloom)).unwrap();
database.insert_blooms(600_000, iter::once(&bloom)).unwrap();

View File

@@ -346,59 +346,59 @@ mod tests {
.insert_blooms(
0,
vec![
Bloom::from(0),
Bloom::from(0x01),
Bloom::from(0x10),
Bloom::from(0x11),
Bloom::zero(),
Bloom::from_low_u64_be(0x01),
Bloom::from_low_u64_be(0x10),
Bloom::from_low_u64_be(0x11),
]
.iter(),
)
.unwrap();
let matches = database
.iterate_matching(0, 3, Some(&Bloom::from(0)))
.iterate_matching(0, 3, Some(&Bloom::zero()))
.unwrap()
.collect::<Result<Vec<_>, _>>()
.unwrap();
assert_eq!(matches, vec![0, 1, 2, 3]);
let matches = database
.iterate_matching(0, 4, Some(&Bloom::from(0)))
.iterate_matching(0, 4, Some(&Bloom::zero()))
.unwrap()
.collect::<Result<Vec<_>, _>>()
.unwrap();
assert_eq!(matches, vec![0, 1, 2, 3]);
let matches = database
.iterate_matching(1, 3, Some(&Bloom::from(0)))
.iterate_matching(1, 3, Some(&Bloom::zero()))
.unwrap()
.collect::<Result<Vec<_>, _>>()
.unwrap();
assert_eq!(matches, vec![1, 2, 3]);
let matches = database
.iterate_matching(1, 2, Some(&Bloom::from(0)))
.iterate_matching(1, 2, Some(&Bloom::zero()))
.unwrap()
.collect::<Result<Vec<_>, _>>()
.unwrap();
assert_eq!(matches, vec![1, 2]);
let matches = database
.iterate_matching(0, 3, Some(&Bloom::from(0x01)))
.iterate_matching(0, 3, Some(&Bloom::from_low_u64_be(0x01)))
.unwrap()
.collect::<Result<Vec<_>, _>>()
.unwrap();
assert_eq!(matches, vec![1, 3]);
let matches = database
.iterate_matching(0, 3, Some(&Bloom::from(0x10)))
.iterate_matching(0, 3, Some(&Bloom::from_low_u64_be(0x10)))
.unwrap()
.collect::<Result<Vec<_>, _>>()
.unwrap();
assert_eq!(matches, vec![2, 3]);
let matches = database
.iterate_matching(2, 2, Some(&Bloom::from(0x10)))
.iterate_matching(2, 2, Some(&Bloom::from_low_u64_be(0x10)))
.unwrap()
.collect::<Result<Vec<_>, _>>()
.unwrap();
@@ -413,52 +413,52 @@ mod tests {
.insert_blooms(
254,
vec![
Bloom::from(0x100),
Bloom::from(0x01),
Bloom::from(0x10),
Bloom::from(0x11),
Bloom::from_low_u64_be(0x100),
Bloom::from_low_u64_be(0x01),
Bloom::from_low_u64_be(0x10),
Bloom::from_low_u64_be(0x11),
]
.iter(),
)
.unwrap();
let matches = database
.iterate_matching(0, 257, Some(&Bloom::from(0x01)))
.iterate_matching(0, 257, Some(&Bloom::from_low_u64_be(0x01)))
.unwrap()
.collect::<Result<Vec<_>, _>>()
.unwrap();
assert_eq!(matches, vec![255, 257]);
let matches = database
.iterate_matching(0, 258, Some(&Bloom::from(0x100)))
.iterate_matching(0, 258, Some(&Bloom::from_low_u64_be(0x100)))
.unwrap()
.collect::<Result<Vec<_>, _>>()
.unwrap();
assert_eq!(matches, vec![254]);
let matches = database
.iterate_matching(0, 256, Some(&Bloom::from(0x01)))
.iterate_matching(0, 256, Some(&Bloom::from_low_u64_be(0x01)))
.unwrap()
.collect::<Result<Vec<_>, _>>()
.unwrap();
assert_eq!(matches, vec![255]);
let matches = database
.iterate_matching(255, 255, Some(&Bloom::from(0x01)))
.iterate_matching(255, 255, Some(&Bloom::from_low_u64_be(0x01)))
.unwrap()
.collect::<Result<Vec<_>, _>>()
.unwrap();
assert_eq!(matches, vec![255]);
let matches = database
.iterate_matching(256, 256, Some(&Bloom::from(0x10)))
.iterate_matching(256, 256, Some(&Bloom::from_low_u64_be(0x10)))
.unwrap()
.collect::<Result<Vec<_>, _>>()
.unwrap();
assert_eq!(matches, vec![256]);
let matches = database
.iterate_matching(256, 257, Some(&Bloom::from(0x10)))
.iterate_matching(256, 257, Some(&Bloom::from_low_u64_be(0x10)))
.unwrap()
.collect::<Result<Vec<_>, _>>()
.unwrap();
@@ -469,10 +469,10 @@ mod tests {
fn test_db_close() {
let tempdir = TempDir::new("").unwrap();
let blooms = vec![
Bloom::from(0x100),
Bloom::from(0x01),
Bloom::from(0x10),
Bloom::from(0x11),
Bloom::from_low_u64_be(0x100),
Bloom::from_low_u64_be(0x01),
Bloom::from_low_u64_be(0x10),
Bloom::from_low_u64_be(0x11),
];
let mut database = Database::open(tempdir.path()).unwrap();

View File

@@ -66,7 +66,7 @@ impl File {
let mut file_ref = &self.file;
file_ref.seek(SeekFrom::Start(pos * 256))?;
let mut bloom = ethbloom::Bloom::default();
file_ref.read_exact(&mut bloom)?;
file_ref.read_exact(bloom.as_bytes_mut())?;
Ok(bloom)
}
@@ -80,7 +80,7 @@ impl File {
old_bloom.accrue_bloom(bloom);
let mut file_ref = &self.file;
file_ref.seek(SeekFrom::Start(pos * 256))?;
file_ref.write_all(&old_bloom)
file_ref.write_all(old_bloom.as_bytes())
}
/// Replace bloom at given position with a new one.
@@ -133,7 +133,7 @@ impl<'a> Iterator for FileIterator<'a> {
fn next(&mut self) -> Option<Self::Item> {
let mut bloom = ethbloom::Bloom::default();
match self.file.read_exact(&mut bloom) {
match self.file.read_exact(bloom.as_bytes_mut()) {
Ok(_) => Some(Ok(bloom)),
Err(ref err) if err.kind() == io::ErrorKind::UnexpectedEof => None,
Err(err) => Some(Err(err)),
@@ -151,8 +151,8 @@ mod tests {
fn test_file() {
let tempdir = TempDir::new("").unwrap();
let mut file = File::open(tempdir.path().join("file")).unwrap();
file.accrue_bloom(0, &Bloom::from(1)).unwrap();
file.accrue_bloom(0, &Bloom::from_low_u64_be(1)).unwrap();
file.flush().unwrap();
assert_eq!(file.read_bloom(0).unwrap(), Bloom::from(1));
assert_eq!(file.read_bloom(0).unwrap(), Bloom::from_low_u64_be(1));
}
}

View File

@@ -9,12 +9,12 @@ edition = "2018"
[dependencies]
common-types = { path = "../../ethcore/types" }
ethereum-types = "0.4"
heapsize = "0.4"
ethereum-types = "0.9.2"
kvdb = "0.1"
kvdb-rocksdb = "0.1.3"
kvdb-memorydb = "0.1"
parity-util-mem = "0.7"
parking_lot = "0.7"
rlp = { version = "0.3.0", features = ["ethereum"] }
rlp = { version = "0.4.6" }
rlp_derive = { path = "../../util/rlp-derive" }
stats = { path = "../../util/stats" }

View File

@@ -20,7 +20,7 @@ use kvdb::DBTransaction;
use kvdb_rocksdb::Database;
use parking_lot::RwLock;
use stats::{PrometheusMetrics, PrometheusRegistry};
use std::{collections::HashMap, hash::Hash, io::Read, ops::Deref};
use std::{collections::HashMap, hash::Hash, io::Read};
use rlp;
@@ -84,7 +84,7 @@ where
/// Should be used to get database key associated with given value.
pub trait Key<T> {
/// The db key associated with this value.
type Target: Deref<Target = [u8]>;
type Target: AsRef<[u8]>;
/// Returns db key.
fn key(&self) -> Self::Target;
@@ -96,13 +96,13 @@ pub trait Writable {
fn write<T, R>(&mut self, col: Option<u32>, key: &dyn Key<T, Target = R>, value: &T)
where
T: rlp::Encodable,
R: Deref<Target = [u8]>;
R: AsRef<[u8]>;
/// Deletes key from the databse.
fn delete<T, R>(&mut self, col: Option<u32>, key: &dyn Key<T, Target = R>)
where
T: rlp::Encodable,
R: Deref<Target = [u8]>;
R: AsRef<[u8]>;
/// Writes the value into the database and updates the cache.
fn write_with_cache<K, T, R>(
@@ -115,7 +115,7 @@ pub trait Writable {
) where
K: Key<T, Target = R> + Hash + Eq,
T: rlp::Encodable,
R: Deref<Target = [u8]>,
R: AsRef<[u8]>,
{
self.write(col, &key, &value);
match policy {
@@ -138,7 +138,7 @@ pub trait Writable {
) where
K: Key<T, Target = R> + Hash + Eq,
T: rlp::Encodable,
R: Deref<Target = [u8]>,
R: AsRef<[u8]>,
{
match policy {
CacheUpdatePolicy::Overwrite => {
@@ -166,7 +166,7 @@ pub trait Writable {
) where
K: Key<T, Target = R> + Hash + Eq,
T: rlp::Encodable,
R: Deref<Target = [u8]>,
R: AsRef<[u8]>,
{
match policy {
CacheUpdatePolicy::Overwrite => {
@@ -197,7 +197,7 @@ pub trait Readable {
fn read<T, R>(&self, col: Option<u32>, key: &dyn Key<T, Target = R>) -> Option<T>
where
T: rlp::Decodable,
R: Deref<Target = [u8]>;
R: AsRef<[u8]>;
/// Returns value for given key either in cache or in database.
fn read_with_cache<K, T, C>(&self, col: Option<u32>, cache: &RwLock<C>, key: &K) -> Option<T>
@@ -246,13 +246,13 @@ pub trait Readable {
/// Returns true if given value exists.
fn exists<T, R>(&self, col: Option<u32>, key: &dyn Key<T, Target = R>) -> bool
where
R: Deref<Target = [u8]>;
R: AsRef<[u8]>;
/// Returns true if given value exists either in cache or in database.
fn exists_with_cache<K, T, R, C>(&self, col: Option<u32>, cache: &RwLock<C>, key: &K) -> bool
where
K: Eq + Hash + Key<T, Target = R>,
R: Deref<Target = [u8]>,
R: AsRef<[u8]>,
C: Cache<K, T>,
{
{
@@ -270,17 +270,17 @@ impl Writable for DBTransaction {
fn write<T, R>(&mut self, col: Option<u32>, key: &dyn Key<T, Target = R>, value: &T)
where
T: rlp::Encodable,
R: Deref<Target = [u8]>,
R: AsRef<[u8]>,
{
self.put(col, &key.key(), &rlp::encode(value));
self.put(col, key.key().as_ref(), &rlp::encode(value));
}
fn delete<T, R>(&mut self, col: Option<u32>, key: &dyn Key<T, Target = R>)
where
T: rlp::Encodable,
R: Deref<Target = [u8]>,
R: AsRef<[u8]>,
{
self.delete(col, &key.key());
self.delete(col, key.key().as_ref());
}
}
@@ -288,25 +288,25 @@ impl<KVDB: kvdb::KeyValueDB + ?Sized> Readable for KVDB {
fn read<T, R>(&self, col: Option<u32>, key: &dyn Key<T, Target = R>) -> Option<T>
where
T: rlp::Decodable,
R: Deref<Target = [u8]>,
R: AsRef<[u8]>,
{
self.get(col, &key.key())
.expect(&format!("db get failed, key: {:?}", &key.key() as &[u8]))
self.get(col, key.key().as_ref())
.expect(&format!("db get failed, key: {:?}", key.key().as_ref()))
.map(|v| rlp::decode(&v).expect("decode db value failed"))
}
fn exists<T, R>(&self, col: Option<u32>, key: &dyn Key<T, Target = R>) -> bool
where
R: Deref<Target = [u8]>,
R: AsRef<[u8]>,
{
let result = self.get(col, &key.key());
let result = self.get(col, key.key().as_ref());
match result {
Ok(v) => v.is_some(),
Err(err) => {
panic!(
"db get failed, key: {:?}, err: {:?}",
&key.key() as &[u8],
key.key().as_ref(),
err
);
}

View File

@@ -16,14 +16,14 @@
//! Blockchain DB extras.
use std::{io::Write, ops};
use std::io::Write;
use common_types::{
engines::epoch::Transition as EpochTransition, receipt::TypedReceipt, BlockNumber,
};
use ethereum_types::{H256, H264, U256};
use heapsize::HeapSizeOf;
use kvdb::PREFIX_LEN as DB_PREFIX_LEN;
use parity_util_mem::MallocSizeOf;
use rlp;
use rlp_derive::{RlpDecodable, RlpEncodable};
@@ -48,19 +48,17 @@ pub enum ExtrasIndex {
fn with_index(hash: &H256, i: ExtrasIndex) -> H264 {
let mut result = H264::default();
result[0] = i as u8;
(*result)[1..].clone_from_slice(hash);
result.as_bytes_mut()[0] = i as u8;
result.as_bytes_mut()[1..].clone_from_slice(hash.as_bytes());
result
}
/// Wrapper for block number used as a DB key.
pub struct BlockNumberKey([u8; 5]);
impl ops::Deref for BlockNumberKey {
type Target = [u8];
fn deref(&self) -> &Self::Target {
&self.0
impl AsRef<[u8]> for BlockNumberKey {
fn as_ref(&self) -> &[u8] {
&self.0[..]
}
}
@@ -133,10 +131,8 @@ pub const EPOCH_KEY_PREFIX: &'static [u8; DB_PREFIX_LEN] = &[
/// Epoch transitions key
pub struct EpochTransitionsKey([u8; EPOCH_KEY_LEN]);
impl ops::Deref for EpochTransitionsKey {
type Target = [u8];
fn deref(&self) -> &[u8] {
impl AsRef<[u8]> for EpochTransitionsKey {
fn as_ref(&self) -> &[u8] {
&self.0[..]
}
}
@@ -156,7 +152,7 @@ impl Key<EpochTransitions> for u64 {
}
/// Familial details concerning a block
#[derive(Debug, Clone)]
#[derive(Debug, Clone, MallocSizeOf)]
pub struct BlockDetails {
/// Block number
pub number: BlockNumber,
@@ -215,14 +211,8 @@ impl rlp::Decodable for BlockDetails {
}
}
impl HeapSizeOf for BlockDetails {
fn heap_size_of_children(&self) -> usize {
self.children.heap_size_of_children()
}
}
/// Represents address of certain transaction within block
#[derive(Debug, PartialEq, Clone, RlpEncodable, RlpDecodable)]
#[derive(Debug, PartialEq, Clone, RlpEncodable, RlpDecodable, MallocSizeOf)]
pub struct TransactionAddress {
/// Block hash
pub block_hash: H256,
@@ -230,14 +220,8 @@ pub struct TransactionAddress {
pub index: usize,
}
impl HeapSizeOf for TransactionAddress {
fn heap_size_of_children(&self) -> usize {
0
}
}
/// Contains all block receipts.
#[derive(Clone)]
#[derive(Clone, MallocSizeOf)]
pub struct BlockReceipts {
/// Block receipts
pub receipts: Vec<TypedReceipt>,
@@ -262,12 +246,6 @@ impl BlockReceipts {
}
}
impl HeapSizeOf for BlockReceipts {
fn heap_size_of_children(&self) -> usize {
self.receipts.heap_size_of_children()
}
}
/// Candidate transitions to an epoch with specific number.
#[derive(Clone, RlpEncodable, RlpDecodable)]
pub struct EpochTransitions {

View File

@@ -7,19 +7,19 @@ license = "GPL3"
[dependencies]
parity-bytes = "0.1"
ethereum-types = "0.4"
ethereum-types = "0.9.2"
hash-db = "0.11.0"
heapsize = "0.4"
keccak-hasher = { path = "../../util/keccak-hasher" }
ethcore-db = { path = "../../db/db"}
kvdb = "0.1"
log = "0.4"
memory-db = { path = "../memory-db" }
parity-util-mem = "0.7"
parking_lot = "0.7"
fastmap = { path = "../../util/fastmap" }
rlp = { version = "0.3.0", features = ["ethereum"] }
rlp = { version = "0.4.6" }
[dev-dependencies]
env_logger = "0.5"
keccak-hash = "0.1"
keccak-hash = "0.5.0"
kvdb-memorydb = "=0.1.0"

View File

@@ -63,7 +63,7 @@ impl ArchiveDB {
fn payload(&self, key: &H256) -> Option<DBValue> {
self.backing
.get(self.column, key)
.get(self.column, key.as_bytes())
.expect("Low-level database error. Some issue with your hard disk?")
}
}
@@ -147,7 +147,7 @@ impl JournalDB for ArchiveDB {
for i in self.overlay.drain() {
let (key, (value, rc)) = i;
if rc > 0 {
batch.put(self.column, &key, &value);
batch.put(self.column, key.as_bytes(), &value);
inserts += 1;
}
if rc < 0 {
@@ -180,18 +180,18 @@ impl JournalDB for ArchiveDB {
for i in self.overlay.drain() {
let (key, (value, rc)) = i;
if rc > 0 {
if self.backing.get(self.column, &key)?.is_some() {
if self.backing.get(self.column, key.as_bytes())?.is_some() {
return Err(error_key_already_exists(&key));
}
batch.put(self.column, &key, &value);
batch.put(self.column, key.as_bytes(), &value);
inserts += 1;
}
if rc < 0 {
assert!(rc == -1);
if self.backing.get(self.column, &key)?.is_none() {
if self.backing.get(self.column, key.as_bytes())?.is_none() {
return Err(error_negatively_reference_hash(&key));
}
batch.delete(self.column, &key);
batch.delete(self.column, key.as_bytes());
deletes += 1;
}
}

View File

@@ -29,25 +29,19 @@ use bytes::Bytes;
use ethcore_db::{DBTransaction, DBValue, KeyValueDB};
use ethereum_types::H256;
use hash_db::HashDB;
use heapsize::HeapSizeOf;
use keccak_hasher::KeccakHasher;
use memory_db::*;
use parity_util_mem::MallocSizeOf;
use parking_lot::RwLock;
use rlp::{decode, encode};
use util::{DatabaseKey, DatabaseValueRef, DatabaseValueView};
#[derive(Debug, Clone, PartialEq, Eq)]
#[derive(Debug, Clone, PartialEq, Eq, MallocSizeOf)]
struct RefInfo {
queue_refs: usize,
in_archive: bool,
}
impl HeapSizeOf for RefInfo {
fn heap_size_of_children(&self) -> usize {
0
}
}
#[derive(Clone, PartialEq, Eq)]
enum RemoveFrom {
Queue,
@@ -133,7 +127,7 @@ impl EarlyMergeDB {
}
fn morph_key(key: &H256, index: u8) -> Bytes {
let mut ret = (&**key).to_owned();
let mut ret = key.as_bytes().to_owned();
ret.push(index);
ret
}
@@ -170,7 +164,7 @@ impl EarlyMergeDB {
Entry::Vacant(entry) => {
// this is the first entry for this node in the journal.
let in_archive = backing
.get(col, h)
.get(col, h.as_bytes())
.expect("Low-level database error. Some issue with your hard disk?")
.is_some();
if in_archive {
@@ -182,7 +176,7 @@ impl EarlyMergeDB {
//Self::reset_already_in(&h);
assert!(!Self::is_already_in(backing, col, h));
trace!(target: "jdb.fine", " insert({}): New to queue, not in DB: Inserting into queue and DB", h);
batch.put(col, h, d);
batch.put(col, h.as_bytes(), d);
}
entry.insert(RefInfo {
queue_refs: 1,
@@ -258,7 +252,7 @@ impl EarlyMergeDB {
}
(1, false) => {
entry.remove();
batch.delete(col, h);
batch.delete(col, h.as_bytes());
trace!(target: "jdb.fine", " remove({}): Not in archive, only 1 ref in queue: Removing from queue and DB", h);
}
_ => panic!("Invalid value in refs: {:?}", entry.get()),
@@ -267,7 +261,7 @@ impl EarlyMergeDB {
Entry::Vacant(_entry) => {
// Gets removed when moving from 1 to 0 additional refs. Should never be here at 0 additional refs.
//assert!(!Self::is_already_in(db, &h));
batch.delete(col, h);
batch.delete(col, h.as_bytes());
trace!(target: "jdb.fine", " remove({}): Not in queue - MUST BE IN ARCHIVE: Removing from DB", h);
}
}
@@ -308,7 +302,7 @@ impl EarlyMergeDB {
fn payload(&self, key: &H256) -> Option<DBValue> {
self.backing
.get(self.column, key)
.get(self.column, key.as_bytes())
.expect("Low-level database error. Some issue with your hard disk?")
}
@@ -593,16 +587,16 @@ impl JournalDB for EarlyMergeDB {
match rc {
0 => {}
1 => {
if self.backing.get(self.column, &key)?.is_some() {
if self.backing.get(self.column, key.as_bytes())?.is_some() {
return Err(error_key_already_exists(&key));
}
batch.put(self.column, &key, &value)
batch.put(self.column, key.as_bytes(), &value)
}
-1 => {
if self.backing.get(self.column, &key)?.is_none() {
if self.backing.get(self.column, key.as_bytes())?.is_none() {
return Err(error_negatively_reference_hash(&key));
}
batch.delete(self.column, &key)
batch.delete(self.column, key.as_bytes())
}
_ => panic!("Attempted to inject invalid state."),
}

View File

@@ -16,7 +16,6 @@
//! `JournalDB` interface and implementation.
extern crate heapsize;
#[macro_use]
extern crate log;
@@ -28,6 +27,7 @@ extern crate keccak_hasher;
extern crate kvdb;
extern crate memory_db;
extern crate parity_bytes as bytes;
extern crate parity_util_mem;
extern crate parking_lot;
extern crate rlp;

View File

@@ -149,7 +149,7 @@ impl OverlayDB {
/// Get the refs and value of the given key.
fn payload(&self, key: &H256) -> Option<Payload> {
self.backing
.get(self.column, key)
.get(self.column, key.as_bytes())
.expect("Low-level database error. Some issue with your hard disk?")
.map(|ref d| decode(d).expect("decoding db value failed"))
}
@@ -162,10 +162,10 @@ impl OverlayDB {
payload: &Payload,
) -> bool {
if payload.count > 0 {
batch.put(self.column, key, &encode(payload));
batch.put(self.column, key.as_bytes(), &encode(payload));
false
} else {
batch.delete(self.column, key);
batch.delete(self.column, key.as_bytes());
true
}
}

View File

@@ -27,9 +27,9 @@ use ethcore_db::{DBTransaction, DBValue, KeyValueDB};
use ethereum_types::H256;
use fastmap::H256FastMap;
use hash_db::HashDB;
use heapsize::HeapSizeOf;
use keccak_hasher::KeccakHasher;
use memory_db::*;
use parity_util_mem::MallocSizeOf;
use parking_lot::RwLock;
use rlp::{decode, encode, Decodable, DecoderError, Encodable, Rlp, RlpStream};
use util::DatabaseKey;
@@ -132,19 +132,13 @@ struct JournalOverlay {
cumulative_size: usize, // cumulative size of all entries.
}
#[derive(PartialEq)]
#[derive(PartialEq, MallocSizeOf)]
struct JournalEntry {
id: H256,
insertions: Vec<H256>,
deletions: Vec<H256>,
}
impl HeapSizeOf for JournalEntry {
fn heap_size_of_children(&self) -> usize {
self.insertions.heap_size_of_children() + self.deletions.heap_size_of_children()
}
}
impl Clone for OverlayRecentDB {
fn clone(&self) -> OverlayRecentDB {
OverlayRecentDB {
@@ -181,7 +175,7 @@ impl OverlayRecentDB {
fn payload(&self, key: &H256) -> Option<DBValue> {
self.backing
.get(self.column, key)
.get(self.column, key.as_bytes())
.expect("Low-level database error. Some issue with your hard disk?")
}
@@ -256,7 +250,7 @@ impl OverlayRecentDB {
#[inline]
fn to_short_key(key: &H256) -> H256 {
let mut k = H256::new();
let mut k = H256::zero();
k[0..DB_PREFIX_LEN].copy_from_slice(&key[0..DB_PREFIX_LEN]);
k
}
@@ -453,7 +447,7 @@ impl JournalDB for OverlayRecentDB {
// apply canon inserts first
for (k, v) in canon_insertions {
batch.put(self.column, &k, &v);
batch.put(self.column, k.as_bytes(), &v);
journal_overlay.pending_overlay.insert(to_short_key(&k), v);
}
// update the overlay
@@ -468,7 +462,7 @@ impl JournalDB for OverlayRecentDB {
// apply canon deletions
for k in canon_deletions {
if !journal_overlay.backing_overlay.contains(&to_short_key(&k)) {
batch.delete(self.column, &k);
batch.delete(self.column, k.as_bytes());
}
}
}
@@ -496,12 +490,14 @@ impl JournalDB for OverlayRecentDB {
match rc {
0 => {}
_ if rc > 0 => batch.put(self.column, &key, &value),
_ if rc > 0 => batch.put(self.column, key.as_bytes(), &value),
-1 => {
if cfg!(debug_assertions) && self.backing.get(self.column, &key)?.is_none() {
if cfg!(debug_assertions)
&& self.backing.get(self.column, key.as_bytes())?.is_none()
{
return Err(error_negatively_reference_hash(&key));
}
batch.delete(self.column, &key)
batch.delete(self.column, key.as_bytes())
}
_ => panic!("Attempted to inject invalid state ({})", rc),
}

View File

@@ -26,10 +26,10 @@ use super::{traits::JournalDB, LATEST_ERA_KEY};
use ethcore_db::{DBTransaction, DBValue, KeyValueDB};
use ethereum_types::H256;
use hash_db::HashDB;
use heapsize::HeapSizeOf;
use keccak_hasher::KeccakHasher;
use memory_db::MemoryDB;
use overlaydb::OverlayDB;
use parity_util_mem::{allocators::new_malloc_size_ops, MallocSizeOf};
use rlp::{decode, encode};
use util::{DatabaseKey, DatabaseValueRef, DatabaseValueView};
@@ -121,13 +121,14 @@ impl JournalDB for RefCountedDB {
}
fn get_sizes(&self, sizes: &mut BTreeMap<String, usize>) {
let mut ops = new_malloc_size_ops();
sizes.insert(
String::from("db_ref_counted_inserts"),
self.inserts.heap_size_of_children(),
self.inserts.size_of(&mut ops),
);
sizes.insert(
String::from("db_ref_counted_removes"),
self.removes.heap_size_of_children(),
self.removes.size_of(&mut ops),
);
}

View File

@@ -21,13 +21,15 @@ repository = "https://github.com/paritytech/parity-common"
[[bench]]
name = "bench"
harness = false
[dependencies.hash-db]
version = "0.11.0"
[dependencies.heapsize]
version = "0.4"
[dependencies]
hash-db = "0.11.0"
[dev-dependencies.criterion]
version = "0.2.8"
[dev-dependencies.keccak-hasher]
version = "0.11.0"
version = "0.11.0"
[dependencies.parity-util-mem]
version = "0.7"

View File

@@ -15,12 +15,13 @@
//! Reference-counted memory-based `HashDB` implementation.
extern crate hash_db;
extern crate heapsize;
extern crate parity_util_mem;
#[cfg(test)]
extern crate keccak_hasher;
use hash_db::{AsHashDB, AsPlainDB, HashDB, HashDBRef, Hasher as KeyHasher, PlainDB, PlainDBRef};
use heapsize::HeapSizeOf;
use parity_util_mem::MallocSizeOf;
use std::{
collections::{hash_map::Entry, HashMap},
hash, mem,
@@ -233,12 +234,15 @@ where
impl<H, T> MemoryDB<H, T>
where
H: KeyHasher,
T: HeapSizeOf,
T: MallocSizeOf,
{
/// Returns the size of allocated heap memory
pub fn mem_used(&self) -> usize {
0 //self.data.heap_size_of_children()
// TODO Reenable above when HeapSizeOf supports arrays.
// TODO: figure out how to call malloc_size_of()
//let mut ops = new_malloc_size_ops();
//self.data.size_of(&mut ops)
//self.data.malloc_size_of()
0
}
}

View File

@@ -9,12 +9,12 @@ license = "GPL-3.0"
trie-db = "0.11.0"
keccak-hasher = { version = "0.1.1", path = "../../util/keccak-hasher" }
hash-db = "0.11.0"
rlp = { version = "0.3.0", features = ["ethereum"] }
rlp = { version = "0.4.6" }
parity-bytes = "0.1"
ethereum-types = "0.4"
ethereum-types = "0.9.2"
elastic-array = "0.10"
[dev-dependencies]
memory-db = "0.11.0"
keccak-hash = "0.1.2"
keccak-hash = "0.5.0"
journaldb = { path = "../journaldb" }

View File

@@ -63,7 +63,7 @@ pub type RlpCodec = RlpNodeCodec<KeccakHasher>;
///
/// fn main() {
/// let mut memdb = journaldb::new_memory_db();
/// let mut root = H256::new();
/// let mut root = H256::default();
/// TrieDBMut::new(&mut memdb, &mut root).insert(b"foo", b"bar").unwrap();
/// let t = TrieDB::new(&memdb, &root).unwrap();
/// assert!(t.contains(b"foo").unwrap());
@@ -107,7 +107,7 @@ pub type FatDB<'db> = trie::FatDB<'db, KeccakHasher, RlpCodec>;
///
/// fn main() {
/// let mut memdb = journaldb::new_memory_db();
/// let mut root = H256::new();
/// let mut root = H256::default();
/// let mut t = TrieDBMut::new(&mut memdb, &mut root);
/// assert!(t.is_empty());
/// assert_eq!(*t.root(), KECCAK_NULL_RLP);

View File

@@ -14,9 +14,9 @@ crossbeam-utils = "0.6"
eip-152 = { version = "0.1", path = "../util/EIP-152" }
env_logger = { version = "0.5", optional = true }
error-chain = { version = "0.12", default-features = false }
ethabi = "6.0"
ethabi-contract = "6.0"
ethabi-derive = "6.0"
ethabi = "12.0.0"
ethabi-contract = "11.0.0"
ethabi-derive = "12.0.0"
ethash = { path = "../concensus/ethash" }
ethcore-blockchain = { path = "./blockchain" }
ethcore-bloom-journal = { path = "../db/bloom" }
@@ -26,16 +26,15 @@ ethcore-db = { path = "../db/db" }
ethcore-io = { path = "../runtime/io" }
ethcore-miner = { path = "../concensus/miner" }
ethcore-stratum = { path = "../concensus/miner/stratum", optional = true }
ethereum-types = "0.4"
ethereum-types = "0.9.2"
ethjson = { path = "../ethjson" }
ethkey = { path = "../accounts/ethkey" }
evm = { path = "../vm/evm" }
globset = "0.4"
hash-db = "0.11.0"
heapsize = "0.4"
itertools = "0.5"
journaldb = { path = "../db/journaldb" }
keccak-hash = "0.1"
keccak-hash = "0.5.0"
keccak-hasher = { path = "../util/keccak-hasher" }
kvdb = "0.1"
kvdb-memorydb = "0.1"
@@ -50,14 +49,17 @@ memory-cache = { path = "../util/memory-cache" }
memory-db = { path = "../db/memory-db" }
num_cpus = "1.2"
parity-bytes = "0.1"
parity-crypto = { version = "0.6.2", features = [ "publickey" ] }
parity-snappy = "0.1"
parity-util-mem = "0.7"
parking_lot = "0.7"
trie-db = "0.11.0"
patricia-trie-ethereum = { path = "../db/patricia-trie-ethereum" }
rand = "0.4"
rand = "0.7.3"
rand_xorshift = "0.2.0"
rayon = "1.1"
regex = "1.3.9"
rlp = { version = "0.3.0", features = ["ethereum"] }
rlp = { version = "0.4.6" }
rlp_derive = { path = "../util/rlp-derive" }
rustc-hex = "1.0"
serde = "1.0"
@@ -87,7 +89,7 @@ kvdb-rocksdb = "0.1.3"
parity-runtime = { path = "../runtime/runtime" }
rlp_compress = { path = "../util/rlp-compress" }
tempdir = "0.3"
trie-standardmap = "0.1"
trie-standardmap = "0.15.2"
[features]
parity = ["work-notify", "price-info", "stratum"]

View File

@@ -25,10 +25,13 @@ extern crate ethereum_types;
extern crate parity_bytes as bytes;
extern crate rustc_hex;
use std::str::FromStr;
use bytes::BytesRef;
use criterion::{Bencher, Criterion};
use ethcore::{ethereum::new_byzantium_test_machine, machine::EthereumMachine};
use ethcore_builtin::Builtin;
use ethereum_types::H160;
use rustc_hex::FromHex;
lazy_static! {
@@ -45,7 +48,10 @@ impl<'a> BuiltinBenchmark<'a> {
fn new(builtin_address: &'static str, input: &str, expected: &str) -> BuiltinBenchmark<'a> {
let builtins = BYZANTIUM_MACHINE.builtins();
let builtin = builtins.get(&builtin_address.into()).unwrap().clone();
let builtin = builtins
.get(&H160::from_str(builtin_address).unwrap())
.unwrap()
.clone();
let input = FromHex::from_hex(input).unwrap();
let expected = FromHex::from_hex(expected).unwrap();

View File

@@ -12,17 +12,18 @@ ansi_term = "0.11"
blooms-db = { path = "../../db/blooms-db" }
common-types = { path = "../types" }
ethcore-db = { path = "../../db/db" }
ethereum-types = "0.4"
heapsize = "0.4"
ethereum-types = "0.9.2"
itertools = "0.5"
keccak-hash = "0.1"
keccak-hash = "0.5.0"
kvdb = "0.1"
log = "0.4"
parity-bytes = "0.1"
parity-crypto = { version = "0.6.2", features = [ "publickey" ] }
parity-util-mem = "0.7"
parking_lot = "0.7"
rand = "0.6"
rand = "0.7.3"
rayon = "1.1"
rlp = { version = "0.3.0", features = ["ethereum"] }
rlp = { version = "0.4.6" }
rlp_compress = { path = "../../util/rlp-compress" }
rlp_derive = { path = "../../util/rlp-derive" }
triehash-ethereum = { version = "0.2", path = "../../util/triehash-ethereum" }

View File

@@ -49,10 +49,10 @@ use ethcore_db::{
CacheUpdatePolicy, Readable, Writable,
};
use ethereum_types::{Bloom, BloomRef, H256, U256};
use heapsize::HeapSizeOf;
use itertools::Itertools;
use log::{info, trace, warn};
use parity_bytes::Bytes;
use parity_util_mem::{allocators::new_malloc_size_ops, MallocSizeOf};
use parking_lot::{Mutex, RwLock};
use rayon::prelude::*;
use rlp::RlpStream;
@@ -324,9 +324,13 @@ impl BlockProvider for BlockChain {
}
// Read from DB and populate cache
let b = self.db.key_value().get(db::COL_HEADERS, hash).expect(
"Low level database error when fetching block header data. Some issue with disk?",
)?;
let b = self
.db
.key_value()
.get(db::COL_HEADERS, hash.as_bytes())
.expect(
"Low level database error when fetching block header data. Some issue with disk?",
)?;
let header = encoded::Header::new(decompress(&b, blocks_swapper()).into_vec());
let mut write = self.block_headers.write();
@@ -357,9 +361,13 @@ impl BlockProvider for BlockChain {
}
// Read from DB and populate cache
let b = self.db.key_value().get(db::COL_BODIES, hash).expect(
"Low level database error when fetching block body data. Some issue with disk?",
)?;
let b = self
.db
.key_value()
.get(db::COL_BODIES, hash.as_bytes())
.expect(
"Low level database error when fetching block body data. Some issue with disk?",
)?;
let body = encoded::Body::new(decompress(&b, blocks_swapper()).into_vec());
let mut write = self.block_bodies.write();
@@ -672,13 +680,21 @@ impl BlockChain {
};
let mut batch = DBTransaction::new();
batch.put(db::COL_HEADERS, &hash, block.header_rlp().as_raw());
batch.put(db::COL_BODIES, &hash, &Self::block_to_body(genesis));
batch.put(
db::COL_HEADERS,
hash.as_bytes(),
block.header_rlp().as_raw(),
);
batch.put(
db::COL_BODIES,
hash.as_bytes(),
&Self::block_to_body(genesis),
);
batch.write(db::COL_EXTRA, &hash, &details);
batch.write(db::COL_EXTRA, &header.number(), &hash);
batch.put(db::COL_EXTRA, b"best", &hash);
batch.put(db::COL_EXTRA, b"best", hash.as_bytes());
bc.db.key_value().write(batch).expect(
"Low level database error when fetching 'best' block. Some issue with disk?",
);
@@ -752,7 +768,7 @@ impl BlockChain {
if hash != bc.genesis_hash() {
info!("First new block calculated: {:?}", hash);
let mut batch = db.key_value().transaction();
batch.put(db::COL_EXTRA, b"first", &hash);
batch.put(db::COL_EXTRA, b"first", hash.as_bytes());
db.key_value().write(batch).expect("Low level database error when writing 'first' block. Some issue with disk?");
bc.first_block = Some(hash);
}
@@ -916,8 +932,8 @@ impl BlockChain {
let compressed_body = compress(&Self::block_to_body(block.raw()), blocks_swapper());
// store block in db
batch.put(db::COL_HEADERS, &hash, &compressed_header);
batch.put(db::COL_BODIES, &hash, &compressed_body);
batch.put(db::COL_HEADERS, hash.as_bytes(), &compressed_header);
batch.put(db::COL_BODIES, hash.as_bytes(), &compressed_body);
let maybe_parent = self.uncommitted_block_details(&block_parent_hash);
@@ -1115,7 +1131,7 @@ impl BlockChain {
*pending_best_ancient_block = Some(None);
} else if block_number > ancient_number {
trace!(target: "blockchain", "Updating the best ancient block to {}.", block_number);
batch.put(db::COL_EXTRA, b"ancient", &block_hash);
batch.put(db::COL_EXTRA, b"ancient", block_hash.as_bytes());
*pending_best_ancient_block = Some(Some(BestAncientBlock {
hash: *block_hash,
number: block_number,
@@ -1301,8 +1317,8 @@ impl BlockChain {
let compressed_body = compress(&Self::block_to_body(block.raw()), blocks_swapper());
// store block in db
batch.put(db::COL_HEADERS, &hash, &compressed_header);
batch.put(db::COL_BODIES, &hash, &compressed_body);
batch.put(db::COL_HEADERS, hash.as_bytes(), &compressed_header);
batch.put(db::COL_BODIES, hash.as_bytes(), &compressed_body);
let info = self.block_info(&block.header_view(), route, &extras);
@@ -1444,7 +1460,7 @@ impl BlockChain {
{
let mut best_block = self.pending_best_block.write();
if is_best && update.info.location != BlockLocation::Branch {
batch.put(db::COL_EXTRA, b"best", &update.info.hash);
batch.put(db::COL_EXTRA, b"best", update.info.hash.as_bytes());
*best_block = Some(BestBlock {
total_difficulty: update.info.total_difficulty,
header: update.block.decode_header(),
@@ -1818,12 +1834,13 @@ impl BlockChain {
/// Get current cache size.
pub fn cache_size(&self) -> CacheSize {
let mut ops = new_malloc_size_ops();
CacheSize {
blocks: self.block_headers.read().heap_size_of_children()
+ self.block_bodies.read().heap_size_of_children(),
block_details: self.block_details.read().heap_size_of_children(),
transaction_addresses: self.transaction_addresses.read().heap_size_of_children(),
block_receipts: self.block_receipts.read().heap_size_of_children(),
blocks: self.block_headers.read().size_of(&mut ops)
+ self.block_bodies.read().size_of(&mut ops),
block_details: self.block_details.read().size_of(&mut ops),
transaction_addresses: self.transaction_addresses.read().size_of(&mut ops),
block_receipts: self.block_receipts.read().size_of(&mut ops),
}
}
@@ -1870,12 +1887,13 @@ impl BlockChain {
transaction_addresses.shrink_to_fit();
block_receipts.shrink_to_fit();
block_headers.heap_size_of_children()
+ block_bodies.heap_size_of_children()
+ block_details.heap_size_of_children()
+ block_hashes.heap_size_of_children()
+ transaction_addresses.heap_size_of_children()
+ block_receipts.heap_size_of_children()
let mut ops = new_malloc_size_ops();
block_headers.size_of(&mut ops)
+ block_bodies.size_of(&mut ops)
+ block_details.size_of(&mut ops)
+ block_hashes.size_of(&mut ops)
+ transaction_addresses.size_of(&mut ops)
+ block_receipts.size_of(&mut ops)
});
}
@@ -1918,14 +1936,14 @@ impl BlockChain {
mod tests {
use super::*;
use std::iter;
use std::{iter, str::FromStr};
use crate::generator::{BlockBuilder, BlockGenerator, BlockOptions};
use common_types::{
receipt::{LegacyReceipt, TransactionOutcome, TypedReceipt},
transaction::{Action, Transaction, TypedTransaction},
};
use ethkey::Secret;
use crypto::publickey::Secret;
use keccak_hash::keccak;
use rustc_hex::FromHex;
use tempdir::TempDir;
@@ -2492,8 +2510,9 @@ mod tests {
fn find_transaction_by_hash() {
let genesis = "f901fcf901f7a00000000000000000000000000000000000000000000000000000000000000000a01dcc4de8dec75d7aab85b567b6ccd41ad312451b948a7413f0a142fd40d49347948888f1f195afa192cfee860698584c030f4c9db1a0af81e09f8c46ca322193edfda764fa7e88e81923f802f1d325ec0b0308ac2cd0a056e81f171bcc55a6ff8345e692c0f86e5b48e01b996cadc001622fb5e363b421a056e81f171bcc55a6ff8345e692c0f86e5b48e01b996cadc001622fb5e363b421b9010000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000830200008083023e38808454c98c8142a056e81f171bcc55a6ff8345e692c0f86e5b48e01b996cadc001622fb5e363b421880102030405060708c0c0".from_hex().unwrap();
let b1 = "f904a8f901faa0ce1f26f798dd03c8782d63b3e42e79a64eaea5694ea686ac5d7ce3df5171d1aea01dcc4de8dec75d7aab85b567b6ccd41ad312451b948a7413f0a142fd40d49347948888f1f195afa192cfee860698584c030f4c9db1a0a65c2364cd0f1542d761823dc0109c6b072f14c20459598c5455c274601438f4a070616ebd7ad2ed6fb7860cf7e9df00163842351c38a87cac2c1cb193895035a2a05c5b4fc43c2d45787f54e1ae7d27afdb4ad16dfc567c5692070d5c4556e0b1d7b9010000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000830200000183023ec683021536845685109780a029f07836e4e59229b3a065913afc27702642c683bba689910b2b2fd45db310d3888957e6d004a31802f902a7f85f800a8255f094aaaf5374fce5edbc8e2a8697c15331677e6ebf0b0a801ca0575da4e21b66fa764be5f74da9389e67693d066fb0d1312e19e17e501da00ecda06baf5a5327595f6619dfc2fcb3f2e6fb410b5810af3cb52d0e7508038e91a188f85f010a82520894bbbf5374fce5edbc8e2a8697c15331677e6ebf0b0a801ba04fa966bf34b93abc1bcd665554b7f316b50f928477b50be0f3285ead29d18c5ba017bba0eeec1625ab433746955e125d46d80b7fdc97386c51266f842d8e02192ef85f020a82520894bbbf5374fce5edbc8e2a8697c15331677e6ebf0b0a801ca004377418ae981cc32b1312b4a427a1d69a821b28db8584f5f2bd8c6d42458adaa053a1dba1af177fac92f3b6af0a9fa46a22adf56e686c93794b6a012bf254abf5f85f030a82520894bbbf5374fce5edbc8e2a8697c15331677e6ebf0b0a801ca04fe13febd28a05f4fcb2f451d7ddc2dda56486d9f8c79a62b0ba4da775122615a0651b2382dd402df9ebc27f8cb4b2e0f3cea68dda2dca0ee9603608f0b6f51668f85f040a82520894bbbf5374fce5edbc8e2a8697c15331677e6ebf0b0a801ba078e6a0ba086a08f8450e208a399bb2f2d2a0d984acd2517c7c7df66ccfab567da013254002cd45a97fac049ae00afbc43ed0d9961d0c56a3b2382c80ce41c198ddf85f050a82520894bbbf5374fce5edbc8e2a8697c15331677e6ebf0b0a801ba0a7174d8f43ea71c8e3ca9477691add8d80ac8e0ed89d8d8b572041eef81f4a54a0534ea2e28ec4da3b5b944b18c51ec84a5cf35f5b3343c5fb86521fd2d388f506f85f060a82520894bbbf5374fce5edbc8e2a8697c15331677e6ebf0b0a801ba034bd04065833536a10c77ee2a43a5371bc6d34837088b861dd9d4b7f44074b59a078807715786a13876d3455716a6b9cb2186b7a4887a5c31160fc877454958616c0".from_hex().unwrap();
let b1_hash: H256 =
"f53f268d23a71e85c7d6d83a9504298712b84c1a2ba220441c86eeda0bf0b6e3".into();
let b1_hash =
H256::from_str("f53f268d23a71e85c7d6d83a9504298712b84c1a2ba220441c86eeda0bf0b6e3")
.unwrap();
let db = new_db();
let bc = new_chain(encoded::Block::new(genesis), db.clone());
@@ -2745,11 +2764,11 @@ mod tests {
#[test]
fn test_bloom_filter_simple() {
let bloom_b1: Bloom = "00000020000000000000000000000000000000000000000002000000000000000000000000000000020000000000000000000000000000000000000000000000000000000000000000000000000000010000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000040000000000000010000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000008000400000000000000000000002000".into();
let bloom_b1 = Bloom::from_str("00000020000000000000000000000000000000000000000002000000000000000000000000000000020000000000000000000000000000000000000000000000000000000000000000000000000000010000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000040000000000000010000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000008000400000000000000000000002000").unwrap();
let bloom_b2: Bloom = "00000000000000000000000000000000000000000000020000001000000000000000000000000000000000000000000000000000000000000000000000000000100000000000000000008000000000000000000000000000000000040000000000000000000000000000000000000000000000000000000000000000000000800000000000000000000000000000000000000000000000000000000000008000000000000000000000000000000000000000000000000000000000000000000000000000000000000002000000000000000000040000000000000000000000000000000000000000000000000000000000000000000000000000000000000000".into();
let bloom_b2 = Bloom::from_str("00000000000000000000000000000000000000000000020000001000000000000000000000000000000000000000000000000000000000000000000000000000100000000000000000008000000000000000000000000000000000040000000000000000000000000000000000000000000000000000000000000000000000800000000000000000000000000000000000000000000000000000000000008000000000000000000000000000000000000000000000000000000000000000000000000000000000000002000000000000000000040000000000000000000000000000000000000000000000000000000000000000000000000000000000000000").unwrap();
let bloom_ba: Bloom = "00000000000000000000000000000000000000000000020000000800000000000000000000000000000000000000000000000000000000000000000000000000100000000000000000008000000000000000000000000000000000040000000000000000000000000000000000000000000000000000000000000000000000800000000000000000000000000000000000000000000000000000000000008000000000000000000000000000000000000000000000000000000000000000000000000000000000000002000000000000000000040000000000000000000000000000000000000000000000000000000000000000000000000000000000000000".into();
let bloom_ba = Bloom::from_str("00000000000000000000000000000000000000000000020000000800000000000000000000000000000000000000000000000000000000000000000000000000100000000000000000008000000000000000000000000000000000040000000000000000000000000000000000000000000000000000000000000000000000800000000000000000000000000000000000000000000000000000000000008000000000000000000000000000000000000000000000000000000000000000000000000000000000000002000000000000000000040000000000000000000000000000000000000000000000000000000000000000000000000000000000000000").unwrap();
let genesis = BlockBuilder::genesis();
let b1 = genesis.add_block_with(|| BlockOptions {
@@ -2813,11 +2832,11 @@ mod tests {
#[test]
fn test_insert_unordered() {
let bloom_b1: Bloom = "00000020000000000000000000000000000000000000000002000000000000000000000000000000020000000000000000000000000000000000000000000000000000000000000000000000000000010000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000040000000000000010000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000008000400000000000000000000002000".into();
let bloom_b1 = Bloom::from_str("00000020000000000000000000000000000000000000000002000000000000000000000000000000020000000000000000000000000000000000000000000000000000000000000000000000000000010000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000040000000000000010000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000008000400000000000000000000002000").unwrap();
let bloom_b2: Bloom = "00000000000000000000000000000000000000000000020000001000000000000000000000000000000000000000000000000000000000000000000000000000100000000000000000008000000000000000000000000000000000040000000000000000000000000000000000000000000000000000000000000000000000800000000000000000000000000000000000000000000000000000000000008000000000000000000000000000000000000000000000000000000000000000000000000000000000000002000000000000000000040000000000000000000000000000000000000000000000000000000000000000000000000000000000000000".into();
let bloom_b2 = Bloom::from_str("00000000000000000000000000000000000000000000020000001000000000000000000000000000000000000000000000000000000000000000000000000000100000000000000000008000000000000000000000000000000000040000000000000000000000000000000000000000000000000000000000000000000000800000000000000000000000000000000000000000000000000000000000008000000000000000000000000000000000000000000000000000000000000000000000000000000000000002000000000000000000040000000000000000000000000000000000000000000000000000000000000000000000000000000000000000").unwrap();
let bloom_b3: Bloom = "00000000000000000000000000000000000000000000020000000800000000000000000000000000000000000000000000000000000000000000000000000000100000000000000000008000000000000000000000000000000000040000000000000000000000000000000000000000000000000000000000000000000000800000000000000000000000000000000000000000000000000000000000008000000000000000000000000000000000000000000000000000000000000000000000000000000000000002000000000000000000040000000000000000000000000000000000000000000000000000000000000000000000000000000000000000".into();
let bloom_b3 = Bloom::from_str("00000000000000000000000000000000000000000000020000000800000000000000000000000000000000000000000000000000000000000000000000000000100000000000000000008000000000000000000000000000000000040000000000000000000000000000000000000000000000000000000000000000000000800000000000000000000000000000000000000000000000000000000000008000000000000000000000000000000000000000000000000000000000000000000000000000000000000002000000000000000000040000000000000000000000000000000000000000000000000000000000000000000000000000000000000000").unwrap();
let genesis = BlockBuilder::genesis();
let b1 = genesis.add_block_with_bloom(bloom_b1);

View File

@@ -70,7 +70,7 @@ impl From<BlockInfo> for ImportRoute {
mod tests {
use super::ImportRoute;
use crate::block_info::{BlockInfo, BlockLocation, BranchBecomingCanonChainData};
use ethereum_types::{H256, U256};
use ethereum_types::{BigEndianHash, U256};
#[test]
fn import_route_none() {
@@ -87,7 +87,7 @@ mod tests {
#[test]
fn import_route_branch() {
let info = BlockInfo {
hash: H256::from(U256::from(1)),
hash: BigEndianHash::from_uint(&U256::from(1)),
number: 0,
total_difficulty: U256::from(0),
location: BlockLocation::Branch,
@@ -98,7 +98,7 @@ mod tests {
ImportRoute {
retracted: vec![],
enacted: vec![],
omitted: vec![H256::from(U256::from(1))],
omitted: vec![BigEndianHash::from_uint(&U256::from(1))],
}
);
}
@@ -106,7 +106,7 @@ mod tests {
#[test]
fn import_route_canon_chain() {
let info = BlockInfo {
hash: H256::from(U256::from(1)),
hash: BigEndianHash::from_uint(&U256::from(1)),
number: 0,
total_difficulty: U256::from(0),
location: BlockLocation::CanonChain,
@@ -116,7 +116,7 @@ mod tests {
ImportRoute::from(info),
ImportRoute {
retracted: vec![],
enacted: vec![H256::from(U256::from(1))],
enacted: vec![BigEndianHash::from_uint(&U256::from(1))],
omitted: vec![],
}
);
@@ -125,21 +125,30 @@ mod tests {
#[test]
fn import_route_branch_becoming_canon_chain() {
let info = BlockInfo {
hash: H256::from(U256::from(2)),
hash: BigEndianHash::from_uint(&U256::from(2)),
number: 0,
total_difficulty: U256::from(0),
location: BlockLocation::BranchBecomingCanonChain(BranchBecomingCanonChainData {
ancestor: H256::from(U256::from(0)),
enacted: vec![H256::from(U256::from(1))],
retracted: vec![H256::from(U256::from(3)), H256::from(U256::from(4))],
ancestor: BigEndianHash::from_uint(&U256::from(0)),
enacted: vec![BigEndianHash::from_uint(&U256::from(1))],
retracted: vec![
BigEndianHash::from_uint(&U256::from(3)),
BigEndianHash::from_uint(&U256::from(4)),
],
}),
};
assert_eq!(
ImportRoute::from(info),
ImportRoute {
retracted: vec![H256::from(U256::from(3)), H256::from(U256::from(4))],
enacted: vec![H256::from(U256::from(1)), H256::from(U256::from(2))],
retracted: vec![
BigEndianHash::from_uint(&U256::from(3)),
BigEndianHash::from_uint(&U256::from(4))
],
enacted: vec![
BigEndianHash::from_uint(&U256::from(1)),
BigEndianHash::from_uint(&U256::from(2))
],
omitted: vec![],
}
);

View File

@@ -18,6 +18,8 @@
#![warn(missing_docs)]
extern crate parity_crypto as crypto;
mod best_block;
mod block_info;
mod blockchain;

View File

@@ -11,7 +11,7 @@ ethcore = { path = ".." }
ethcore-blockchain = { path = "../blockchain" }
ethcore-io = { path = "../../runtime/io" }
ethcore-sync = { path = "../sync" }
ethereum-types = "0.4"
ethereum-types = "0.9.2"
kvdb = "0.1"
log = "0.4"
trace-time = "0.1"

View File

@@ -31,8 +31,8 @@ use ethereum_types::Address;
fn combine_key<'a>(address_hash: &'a H256, key: &'a H256) -> H256 {
let mut dst = key.clone();
{
let last_src: &[u8] = &*address_hash;
let last_dst: &mut [u8] = &mut *dst;
let last_src: &[u8] = address_hash.as_bytes();
let last_dst: &mut [u8] = dst.as_bytes_mut();
for (k, a) in last_dst[12..].iter_mut().zip(&last_src[12..]) {
*k ^= *a
}

View File

@@ -662,7 +662,7 @@ mod tests {
db,
parent,
last_hashes,
Address::new(),
Address::default(),
(3141562.into(), 31415620.into()),
vec![],
false,

View File

@@ -40,7 +40,7 @@ use ethereum_types::{Address, H256, H264, U256};
use hash::keccak;
use itertools::Itertools;
use parking_lot::{Mutex, RwLock};
use rand::OsRng;
use rand::rngs::OsRng;
use rlp::{PayloadInfo, Rlp};
use rustc_hex::FromHex;
use trie::{Trie, TrieFactory, TrieSpec};
@@ -541,7 +541,7 @@ impl Importer {
{
trace_time!("import_old_block");
// verify the block, passing the chain for updating the epoch verifier.
let mut rng = OsRng::new()?;
let mut rng = OsRng;
self.ancient_verifier
.verify(&mut rng, &unverified.header, &chain)?;
@@ -1641,8 +1641,8 @@ impl BlockChainReset for Client {
best_block_hash = current_header.parent_hash();
let (number, hash) = (current_header.number(), current_header.hash());
batch.delete(::db::COL_HEADERS, &hash);
batch.delete(::db::COL_BODIES, &hash);
batch.delete(::db::COL_HEADERS, hash.as_bytes());
batch.delete(::db::COL_BODIES, hash.as_bytes());
Writable::delete::<BlockDetails, H264>(&mut batch, ::db::COL_EXTRA, &hash);
Writable::delete::<H256, BlockNumberKey>(&mut batch, ::db::COL_EXTRA, &number);
@@ -1673,7 +1673,7 @@ impl BlockChainReset for Client {
best_block_details.children.retain(|h| *h != *last_hash);
batch.write(::db::COL_EXTRA, &best_block_hash, &best_block_details);
// update the new best block hash
batch.put(::db::COL_EXTRA, b"best", &best_block_hash);
batch.put(::db::COL_EXTRA, b"best", best_block_hash.as_bytes());
self.db
.read()
@@ -2203,7 +2203,7 @@ impl BlockChainClient for Client {
};
if let Some(after) = after {
if let Err(e) = iter.seek(after) {
if let Err(e) = iter.seek(after.as_bytes()) {
trace!(target: "fatdb", "list_accounts: Couldn't seek the DB: {:?}", e);
} else {
// Position the iterator after the `after` element
@@ -2261,7 +2261,7 @@ impl BlockChainClient for Client {
};
if let Some(after) = after {
if let Err(e) = iter.seek(after) {
if let Err(e) = iter.seek(after.as_bytes()) {
trace!(target: "fatdb", "list_storage: Couldn't seek the DB: {:?}", e);
} else {
// Position the iterator after the `after` element
@@ -3404,6 +3404,7 @@ impl PrometheusMetrics for Client {
#[cfg(test)]
mod tests {
use blockchain::{BlockProvider, ExtrasInsert};
use ethereum_types::{H160, H256};
use spec::Spec;
use test_helpers::generate_dummy_client_with_spec_and_data;
@@ -3484,7 +3485,7 @@ mod tests {
#[test]
fn should_return_correct_log_index() {
use super::transaction_receipt;
use ethkey::KeyPair;
use crypto::publickey::KeyPair;
use hash::keccak;
use types::{
log_entry::{LocalizedLogEntry, LogEntry},
@@ -3493,19 +3494,19 @@ mod tests {
};
// given
let key = KeyPair::from_secret_slice(&keccak("test")).unwrap();
let key = KeyPair::from_secret_slice(keccak("test").as_bytes()).unwrap();
let secret = key.secret();
let machine = ::ethereum::new_frontier_test_machine();
let block_number = 1;
let block_hash = 5.into();
let state_root = 99.into();
let block_hash = H256::from_low_u64_be(5);
let state_root = H256::from_low_u64_be(99);
let gas_used = 10.into();
let raw_tx = TypedTransaction::Legacy(Transaction {
nonce: 0.into(),
gas_price: 0.into(),
gas: 21000.into(),
action: Action::Call(10.into()),
action: Action::Call(H160::from_low_u64_be(10)),
value: 0.into(),
data: vec![],
});
@@ -3519,12 +3520,12 @@ mod tests {
};
let logs = vec![
LogEntry {
address: 5.into(),
address: H160::from_low_u64_be(5),
topics: vec![],
data: vec![],
},
LogEntry {
address: 15.into(),
address: H160::from_low_u64_be(15),
topics: vec![],
data: vec![],
},

View File

@@ -18,6 +18,7 @@
use std::{
collections::{BTreeMap, HashMap},
str::FromStr,
sync::{
atomic::{AtomicBool, AtomicUsize, Ordering as AtomicOrder},
Arc,
@@ -26,10 +27,10 @@ use std::{
use blockchain::{BlockReceipts, TreeRoute};
use bytes::Bytes;
use crypto::publickey::{Generator, Random};
use db::{COL_STATE, NUM_COLUMNS};
use ethcore_miner::pool::VerifiedTransaction;
use ethereum_types::{Address, H256, U256};
use ethkey::{Generator, Random};
use ethtrie;
use hash::keccak;
use itertools::Itertools;
@@ -174,9 +175,9 @@ impl TestBlockChainClient {
let mut client = TestBlockChainClient {
blocks: RwLock::new(HashMap::new()),
numbers: RwLock::new(HashMap::new()),
genesis_hash: H256::new(),
genesis_hash: H256::default(),
extra_data: extra_data,
last_hash: RwLock::new(H256::new()),
last_hash: RwLock::new(H256::default()),
difficulty: RwLock::new(spec.genesis_header().difficulty().clone()),
balances: RwLock::new(HashMap::new()),
nonces: RwLock::new(HashMap::new()),
@@ -293,7 +294,7 @@ impl TestBlockChainClient {
_ => 1,
};
let mut txs = RlpStream::new_list(num_transactions);
let keypair = Random.generate().unwrap();
let keypair = Random.generate();
let mut nonce = U256::zero();
for _ in 0..num_transactions {
@@ -340,7 +341,7 @@ impl TestBlockChainClient {
.unwrap()
.decode()
.expect("decoding failed");
header.set_parent_hash(H256::from(42));
header.set_parent_hash(H256::from_low_u64_be(42));
let mut rlp = RlpStream::new_list(3);
rlp.append(&header);
rlp.append_raw(&::rlp::NULL_RLP, 1);
@@ -370,7 +371,7 @@ impl TestBlockChainClient {
/// Inserts a transaction with given gas price to miners transactions queue.
pub fn insert_transaction_with_gas_price_to_queue(&self, gas_price: U256) -> H256 {
let keypair = Random.generate().unwrap();
let keypair = Random.generate();
let tx = TypedTransaction::Legacy(Transaction {
action: Action::Create,
value: U256::from(100),
@@ -753,7 +754,7 @@ impl BlockChainClient for TestBlockChainClient {
.clone()
.unwrap()
.into_iter()
.map(|t| t.transaction_hash.unwrap_or(H256::new()))
.map(|t| t.transaction_hash.unwrap_or(H256::default()))
.zip(self.execution_result.read().clone().unwrap().into_iter()),
))
}
@@ -784,7 +785,7 @@ impl BlockChainClient for TestBlockChainClient {
.read()
.get(&(address.clone(), position.clone()))
.cloned()
.unwrap_or_else(H256::new),
.unwrap_or_else(H256::default),
),
_ => None,
}
@@ -902,7 +903,7 @@ impl BlockChainClient for TestBlockChainClient {
// works only if blocks are one after another 1 -> 2 -> 3
fn tree_route(&self, from: &H256, to: &H256) -> Option<TreeRoute> {
Some(TreeRoute {
ancestor: H256::new(),
ancestor: H256::default(),
index: 0,
blocks: {
let numbers_read = self.numbers.read();
@@ -943,7 +944,10 @@ impl BlockChainClient for TestBlockChainClient {
fn block_receipts(&self, hash: &H256) -> Option<BlockReceipts> {
// starts with 'f' ?
if *hash > H256::from("f000000000000000000000000000000000000000000000000000000000000000") {
if *hash
> H256::from_str("f000000000000000000000000000000000000000000000000000000000000000")
.unwrap()
{
let receipt = BlockReceipts::new(vec![TypedReceipt::new(
TypedTxId::Legacy,
LegacyReceipt::new(

View File

@@ -36,6 +36,7 @@ use super::{
};
use block::*;
use client::{traits::ForceUpdateSealing, EngineClient};
use crypto::publickey::{self, Signature};
use engines::{
block_reward,
block_reward::{BlockRewardContract, RewardKind},
@@ -43,8 +44,8 @@ use engines::{
};
use error::{BlockError, Error, ErrorKind};
use ethereum_types::{Address, H256, H520, U128, U256};
use ethjson::{self, uint::Uint};
use ethkey::{self, Signature};
use hash::keccak;
use io::{IoContext, IoHandler, IoService, TimerToken};
use itertools::{self, Itertools};
@@ -378,14 +379,14 @@ impl EmptyStep {
let message = keccak(empty_step_rlp(self.step, &self.parent_hash));
let correct_proposer = step_proposer(validators, &self.parent_hash, self.step);
ethkey::verify_address(&correct_proposer, &self.signature.into(), &message)
publickey::verify_address(&correct_proposer, &self.signature.into(), &message)
.map_err(|e| e.into())
}
fn author(&self) -> Result<Address, Error> {
let message = keccak(empty_step_rlp(self.step, &self.parent_hash));
let public = ethkey::recover(&self.signature.into(), &message)?;
Ok(ethkey::public_to_address(&public))
let public = publickey::recover(&self.signature.into(), &message)?;
Ok(publickey::public_to_address(&public))
}
fn sealed(&self) -> SealedEmptyStep {
@@ -583,7 +584,7 @@ impl super::EpochVerifier<EthereumMachine> for EpochVerifier {
fn header_seal_hash(header: &Header, empty_steps_rlp: Option<&[u8]>) -> H256 {
match empty_steps_rlp {
Some(empty_steps_rlp) => {
let mut message = header.bare_hash().to_vec();
let mut message = header.bare_hash().as_bytes().to_vec();
message.extend_from_slice(empty_steps_rlp);
keccak(message)
}
@@ -717,7 +718,7 @@ fn verify_external(
};
let header_seal_hash = header_seal_hash(header, empty_steps_rlp);
!ethkey::verify_address(&correct_proposer, &proposer_signature, &header_seal_hash)?
!publickey::verify_address(&correct_proposer, &proposer_signature, &header_seal_hash)?
};
if is_invalid_proposer {
@@ -1312,7 +1313,7 @@ impl Engine<EthereumMachine> for AuthorityRound {
}
let mut fields =
vec![encode(&step), encode(&(&H520::from(signature) as &[u8]))];
vec![encode(&step), encode(&(H520::from(signature).as_bytes()))];
if let Some(empty_steps_rlp) = empty_steps_rlp {
fields.push(empty_steps_rlp);
@@ -1738,7 +1739,7 @@ impl Engine<EthereumMachine> for AuthorityRound {
.signer
.read()
.as_ref()
.ok_or(ethkey::Error::InvalidAddress)?
.ok_or(publickey::Error::InvalidAddress)?
.sign(hash)?)
}
@@ -1782,13 +1783,13 @@ mod tests {
};
use accounts::AccountProvider;
use block::*;
use crypto::publickey::Signature;
use engines::{
validator_set::{SimpleList, TestSet},
Engine, EngineError, EthEngine, Seal,
};
use error::{Error, ErrorKind};
use ethereum_types::{Address, H256, H520, U256};
use ethkey::Signature;
use hash::keccak;
use rlp::encode;
use spec::Spec;
@@ -2187,7 +2188,7 @@ mod tests {
fn set_empty_steps_seal(
header: &mut Header,
step: u64,
block_signature: &ethkey::Signature,
block_signature: &crypto::publickey::Signature,
empty_steps: &[SealedEmptyStep],
) {
header.set_seal(vec![
@@ -2539,7 +2540,7 @@ mod tests {
// empty step with invalid step
let empty_steps = vec![SealedEmptyStep {
signature: 0.into(),
signature: H520::zero(),
step: 2,
}];
set_empty_steps_seal(&mut header, 2, &signature, &empty_steps);
@@ -2551,7 +2552,7 @@ mod tests {
// empty step with invalid signature
let empty_steps = vec![SealedEmptyStep {
signature: 0.into(),
signature: H520::zero(),
step: 1,
}];
set_empty_steps_seal(&mut header, 2, &signature, &empty_steps);
@@ -2703,7 +2704,7 @@ mod tests {
p.maximum_empty_steps = 0;
});
let parent_hash: H256 = 1.into();
let parent_hash = H256::from_low_u64_be(1);
let signature = H520::default();
let step = |step: u64| EmptyStep {
step,

View File

@@ -19,11 +19,11 @@
use super::validator_set::{new_validator_set, SimpleList, ValidatorSet};
use block::*;
use client::EngineClient;
use crypto::publickey::{self, Signature};
use engines::{signer::EngineSigner, ConstructedVerifier, Engine, EngineError, Seal};
use error::{BlockError, Error};
use ethereum_types::{H256, H520};
use ethjson;
use ethkey::{self, Signature};
use machine::{AuxiliaryData, Call, EthereumMachine};
use parking_lot::RwLock;
use std::sync::Weak;
@@ -59,7 +59,8 @@ fn verify_external(header: &Header, validators: &dyn ValidatorSet) -> Result<(),
// Check if the signature belongs to a validator, can depend on parent state.
let sig = Rlp::new(&header.seal()[0]).as_val::<H520>()?;
let signer = ethkey::public_to_address(&ethkey::recover(&sig.into(), &header.bare_hash())?);
let signer =
publickey::public_to_address(&publickey::recover(&sig.into(), &header.bare_hash())?);
if *header.author() != signer {
return Err(EngineError::NotAuthorized(*header.author()).into());
@@ -114,7 +115,7 @@ impl Engine<EthereumMachine> for BasicAuthority {
if self.validators.contains(header.parent_hash(), author) {
// account should be pernamently unlocked, otherwise sealing will fail
if let Ok(signature) = self.sign(header.bare_hash()) {
return Seal::Regular(vec![::rlp::encode(&(&H520::from(signature) as &[u8]))]);
return Seal::Regular(vec![::rlp::encode(&(H520::from(signature).as_bytes()))]);
} else {
trace!(target: "basicauthority", "generate_seal: FAIL: accounts secret key unavailable");
}
@@ -205,7 +206,7 @@ impl Engine<EthereumMachine> for BasicAuthority {
.signer
.read()
.as_ref()
.ok_or_else(|| ethkey::Error::InvalidAddress)?
.ok_or_else(|| publickey::Error::InvalidAddress)?
.sign(hash)?)
}

View File

@@ -196,12 +196,13 @@ pub fn apply_block_rewards<M: Machine>(
#[cfg(test)]
mod test {
use client::PrepareOpenBlock;
use ethereum_types::U256;
use ethereum_types::{H160, U256};
use spec::Spec;
use test_helpers::generate_dummy_client_with_spec;
use super::{BlockRewardContract, RewardKind};
use engines::SystemOrCodeCallKind;
use std::str::FromStr;
#[test]
fn block_reward_contract() {
@@ -211,13 +212,13 @@ mod test {
// the spec has a block reward contract defined at the given address
let block_reward_contract = BlockRewardContract::new_from_address(
"0000000000000000000000000000000000000042".into(),
H160::from_str("0000000000000000000000000000000000000042").unwrap(),
);
let mut call = |to, data| {
let mut block = client
.prepare_open_block(
"0000000000000000000000000000000000000001".into(),
H160::from_str("0000000000000000000000000000000000000001").unwrap(),
(3141562.into(), 31415620.into()),
vec![],
)
@@ -244,15 +245,15 @@ mod test {
// the contract rewards (1000 + kind) for each benefactor
let beneficiaries = vec![
(
"0000000000000000000000000000000000000033".into(),
H160::from_str("0000000000000000000000000000000000000033").unwrap(),
RewardKind::Author,
),
(
"0000000000000000000000000000000000000034".into(),
H160::from_str("0000000000000000000000000000000000000034").unwrap(),
RewardKind::Uncle(1),
),
(
"0000000000000000000000000000000000000035".into(),
H160::from_str("0000000000000000000000000000000000000035").unwrap(),
RewardKind::EmptyStep,
),
];
@@ -262,15 +263,15 @@ mod test {
.unwrap();
let expected = vec![
(
"0000000000000000000000000000000000000033".into(),
H160::from_str("0000000000000000000000000000000000000033").unwrap(),
U256::from(1000),
),
(
"0000000000000000000000000000000000000034".into(),
H160::from_str("0000000000000000000000000000000000000034").unwrap(),
U256::from(1000 + 101),
),
(
"0000000000000000000000000000000000000035".into(),
H160::from_str("0000000000000000000000000000000000000035").unwrap(),
U256::from(1000 + 2),
),
];

View File

@@ -221,7 +221,7 @@ impl CliqueBlockState {
}))?
}
let nonce: H64 = decoded_seal[1].into();
let nonce = H64::from_slice(decoded_seal[1]);
self.update_signers_on_vote(
VoteType::from_nonce(nonce)?,
creator,

View File

@@ -68,13 +68,13 @@ use std::{
use super::signer::EngineSigner;
use block::ExecutedBlock;
use client::{traits::ForceUpdateSealing, BlockId, EngineClient};
use crypto::publickey::Signature;
use engines::{
clique::util::{extract_signers, recover_creator},
Engine, EngineError, Seal,
};
use error::{BlockError, Error};
use ethereum_types::{Address, H160, H256, H64, U256};
use ethkey::Signature;
use hash::KECCAK_EMPTY_LIST_RLP;
use itertools::Itertools;
use lru_cache::LruCache;
@@ -590,7 +590,7 @@ impl Engine<EthereumMachine> for Clique {
if is_checkpoint && *header.author() != NULL_AUTHOR {
return Err(EngineError::CliqueWrongAuthorCheckpoint(Mismatch {
expected: 0.into(),
expected: H160::zero(),
found: *header.author(),
}))?;
}
@@ -603,8 +603,8 @@ impl Engine<EthereumMachine> for Clique {
}))?
}
let mixhash: H256 = seal_fields[0].into();
let nonce: H64 = seal_fields[1].into();
let mixhash = H256::from_slice(seal_fields[0]);
let nonce = H64::from_slice(seal_fields[1]);
// Nonce must be 0x00..0 or 0xff..f
if nonce != NONCE_DROP_VOTE && nonce != NONCE_AUTH_VOTE {

Some files were not shown because too many files have changed in this diff Show More