Skip to content
This repository has been archived by the owner on Nov 6, 2020. It is now read-only.

Commit

Permalink
Initial Whisper implementation (#6009)
Browse files Browse the repository at this point in the history
* whisper skeleton

* basic message store

* rallying and message logic

* pass host info to network protocol handlers

* choose who starts rally based on node key

* module reshuffling

* mining messages

* prune messages by low PoW until below size target

* associated error type for ethkey generators and `OsRng` generator

* beginnings of RPC

* generic message handler for whisper

* reshuffle code order

* standard payload encoding and decoding

* basic crypto

* minor restructuring of net code

* implement shh_post

* merge?

* implement filters

* rand trait for hash types

* filter RPCs for whisper

* symmetric encryption of payload

* pub-sub

* filter tests

* use only secure random IDs

* attach arbitrary protocols to network

* basic integration of whisper into Parity

* eagerly prune low PoW entries

* broadcast messages with salted topics

* node info RPC

* fix import

* fix leading zeros calculation

* address minor grumbles
  • Loading branch information
rphmeier authored and gavofyork committed Jul 14, 2017
1 parent a4fa6a3 commit 99075ad
Show file tree
Hide file tree
Showing 37 changed files with 3,642 additions and 55 deletions.
47 changes: 47 additions & 0 deletions Cargo.lock

Some generated files are not rendered by default. Learn more about how customized files appear on GitHub.

3 changes: 2 additions & 1 deletion Cargo.toml
Original file line number Diff line number Diff line change
Expand Up @@ -51,6 +51,7 @@ parity-reactor = { path = "util/reactor" }
parity-rpc = { path = "rpc" }
parity-rpc-client = { path = "rpc_client" }
parity-updater = { path = "updater" }
parity-whisper = { path = "whisper" }
path = { path = "util/path" }

parity-dapps = { path = "dapps", optional = true }
Expand Down Expand Up @@ -106,4 +107,4 @@ lto = false
panic = "abort"

[workspace]
members = ["ethstore/cli", "ethkey/cli", "evmbin"]
members = ["ethstore/cli", "ethkey/cli", "evmbin", "whisper"]
4 changes: 2 additions & 2 deletions ethcore/light/src/net/mod.rs
Original file line number Diff line number Diff line change
Expand Up @@ -21,7 +21,7 @@
use ethcore::transaction::UnverifiedTransaction;

use io::TimerToken;
use network::{NetworkProtocolHandler, NetworkContext, PeerId};
use network::{HostInfo, NetworkProtocolHandler, NetworkContext, PeerId};
use rlp::{RlpStream, UntrustedRlp};
use util::hash::H256;
use util::{DBValue, Mutex, RwLock, U256};
Expand Down Expand Up @@ -1074,7 +1074,7 @@ fn punish(peer: PeerId, io: &IoContext, e: Error) {
}

impl NetworkProtocolHandler for LightProtocol {
fn initialize(&self, io: &NetworkContext) {
fn initialize(&self, io: &NetworkContext, _host_info: &HostInfo) {
io.register_timer(TIMEOUT, TIMEOUT_INTERVAL_MS)
.expect("Error registering sync timer.");
io.register_timer(TICK_TIMEOUT, TICK_TIMEOUT_INTERVAL_MS)
Expand Down
49 changes: 49 additions & 0 deletions ethcore/src/engines/epoch_verifier.rs
Original file line number Diff line number Diff line change
@@ -0,0 +1,49 @@
// Copyright 2015-2017 Parity Technologies (UK) Ltd.
// This file is part of Parity.

// Parity is free software: you can redistribute it and/or modify
// it under the terms of the GNU General Public License as published by
// the Free Software Foundation, either version 3 of the License, or
// (at your option) any later version.

// Parity is distributed in the hope that it will be useful,
// but WITHOUT ANY WARRANTY; without even the implied warranty of
// MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the
// GNU General Public License for more details.

// You should have received a copy of the GNU General Public License
// along with Parity. If not, see <http://www.gnu.org/licenses/>.

// Epoch verifiers.

use error::Error;
use header::Header;

/// Verifier for all blocks within an epoch with self-contained state.
///
/// See docs on `Engine` relating to proving functions for more details.
pub trait EpochVerifier: Send + Sync {
/// Get the epoch number.
fn epoch_number(&self) -> u64;

/// Lightly verify the next block header.
/// This may not be a header belonging to a different epoch.
fn verify_light(&self, header: &Header) -> Result<(), Error>;

/// Perform potentially heavier checks on the next block header.
fn verify_heavy(&self, header: &Header) -> Result<(), Error> {
self.verify_light(header)
}

/// Check if the header is the end of an epoch.
fn is_epoch_end(&self, header: &Header, Ancestry) -> EpochChange;

}

/// Special "no-op" verifier for stateless, epoch-less engines.
pub struct NoOp;

impl EpochVerifier for NoOp {
fn epoch_number(&self) -> u64 { 0 }
fn verify_light(&self, _header: &Header) -> Result<(), Error> { Ok(()) }
}
15 changes: 8 additions & 7 deletions ethkey/src/brain.rs
Original file line number Diff line number Diff line change
Expand Up @@ -15,7 +15,7 @@
// along with Parity. If not, see <http://www.gnu.org/licenses/>.

use keccak::Keccak256;
use super::{KeyPair, Error, Generator, Secret};
use super::{KeyPair, Generator, Secret};

/// Simple brainwallet.
pub struct Brain(String);
Expand All @@ -27,7 +27,9 @@ impl Brain {
}

impl Generator for Brain {
fn generate(self) -> Result<KeyPair, Error> {
type Error = ::Void;

fn generate(self) -> Result<KeyPair, Self::Error> {
let seed = self.0;
let mut secret = seed.into_bytes().keccak256();

Expand All @@ -38,11 +40,10 @@ impl Generator for Brain {
match i > 16384 {
false => i += 1,
true => {
if let Ok(secret) = Secret::from_unsafe_slice(&secret) {
let result = KeyPair::from_secret(secret);
if result.as_ref().ok().map_or(false, |r| r.address()[0] == 0) {
return result;
}
if let Ok(pair) = Secret::from_unsafe_slice(&secret)
.and_then(KeyPair::from_secret)
{
if pair.address()[0] == 0 { return Ok(pair) }
}
},
}
Expand Down
32 changes: 20 additions & 12 deletions ethkey/src/lib.rs
Original file line number Diff line number Diff line change
Expand Up @@ -15,15 +15,16 @@
// along with Parity. If not, see <http://www.gnu.org/licenses/>.

extern crate rand;
#[macro_use]
extern crate lazy_static;
extern crate tiny_keccak;
extern crate secp256k1;
extern crate rustc_hex;
extern crate ethcore_bigint as bigint;
extern crate crypto as rcrypto;
extern crate byteorder;

#[macro_use]
extern crate lazy_static;

mod brain;
mod error;
mod keypair;
Expand All @@ -34,21 +35,12 @@ mod signature;
mod secret;
mod extended;

lazy_static! {
pub static ref SECP256K1: secp256k1::Secp256k1 = secp256k1::Secp256k1::new();
}

/// Generates new keypair.
pub trait Generator {
/// Should be called to generate new keypair.
fn generate(self) -> Result<KeyPair, Error>;
}

pub mod math;

pub use self::brain::Brain;
pub use self::error::Error;
pub use self::keypair::{KeyPair, public_to_address};
pub use self::math::public_is_valid;
pub use self::prefix::Prefix;
pub use self::random::Random;
pub use self::signature::{sign, verify_public, verify_address, recover, Signature};
Expand All @@ -57,6 +49,22 @@ pub use self::extended::{ExtendedPublic, ExtendedSecret, ExtendedKeyPair, Deriva

use bigint::hash::{H160, H256, H512};

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(self) -> Result<KeyPair, Self::Error>;
}

pub type Address = H160;
pub type Message = H256;
pub type Public = H512;
6 changes: 6 additions & 0 deletions ethkey/src/math.rs
Original file line number Diff line number Diff line change
Expand Up @@ -20,6 +20,12 @@ use secp256k1::constants::{GENERATOR_X, GENERATOR_Y, CURVE_ORDER};
use bigint::prelude::U256;
use bigint::hash::H256;

/// 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()?;
Expand Down
2 changes: 2 additions & 0 deletions ethkey/src/prefix.rs
Original file line number Diff line number Diff line change
Expand Up @@ -32,6 +32,8 @@ impl Prefix {
}

impl Generator for Prefix {
type Error = Error;

fn generate(self) -> Result<KeyPair, Error> {
for _ in 0..self.iterations {
let keypair = Random.generate()?;
Expand Down
24 changes: 18 additions & 6 deletions ethkey/src/random.rs
Original file line number Diff line number Diff line change
Expand Up @@ -15,18 +15,30 @@
// along with Parity. If not, see <http://www.gnu.org/licenses/>.

use rand::os::OsRng;
use super::{Generator, KeyPair, Error, SECP256K1};
use super::{Generator, KeyPair, SECP256K1};

/// Randomly generates new keypair.
/// Randomly generates new keypair, instantiating the RNG each time.
pub struct Random;

impl Generator for Random {
fn generate(self) -> Result<KeyPair, Error> {
let context = &SECP256K1;
type Error = ::std::io::Error;

fn generate(self) -> Result<KeyPair, Self::Error> {
let mut rng = OsRng::new()?;
let (sec, publ) = context.generate_keypair(&mut rng)?;
match rng.generate() {
Ok(pair) => Ok(pair),
Err(void) => match void {}, // LLVM unreachable
}
}
}

impl<'a> Generator for &'a mut OsRng {
type Error = ::Void;

fn generate(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))
}
}

4 changes: 4 additions & 0 deletions parity/cli/config.full.toml
Original file line number Diff line number Diff line change
Expand Up @@ -144,3 +144,7 @@ jit = false
logging = "own_tx=trace"
log_file = "/var/log/parity.log"
color = true

[whisper]
enabled = false
pool_size = 20
4 changes: 4 additions & 0 deletions parity/cli/config.toml
Original file line number Diff line number Diff line change
Expand Up @@ -84,3 +84,7 @@ log_file = "/var/log/parity.log"
color = true
ports_shift = 0
unsafe_expose = false

[whisper]
enabled = true
pool_size = 50

0 comments on commit 99075ad

Please sign in to comment.