Encryption, decryption and public key RPCs. (#1946)
* Fix up pending receipts details. * Add support for additional params and registry over RPC. * Fix tests. * Add test, additional fix. Fixes #1932. * Fix up tests. * Fix test. * Fix test. * Remove unused use. * Add encryption, decryption and public-key RPCs. * Remove &
This commit is contained in:
parent
5e0dcd0892
commit
07b5e9a5c7
1
Cargo.lock
generated
1
Cargo.lock
generated
@ -458,6 +458,7 @@ dependencies = [
|
|||||||
"ethcore-io 1.4.0",
|
"ethcore-io 1.4.0",
|
||||||
"ethcore-ipc 1.4.0",
|
"ethcore-ipc 1.4.0",
|
||||||
"ethcore-util 1.4.0",
|
"ethcore-util 1.4.0",
|
||||||
|
"ethcrypto 0.1.0",
|
||||||
"ethjson 0.1.0",
|
"ethjson 0.1.0",
|
||||||
"ethkey 0.2.0",
|
"ethkey 0.2.0",
|
||||||
"ethstore 0.1.0",
|
"ethstore 0.1.0",
|
||||||
|
@ -322,6 +322,26 @@ impl AccountProvider {
|
|||||||
Ok(signature)
|
Ok(signature)
|
||||||
}
|
}
|
||||||
|
|
||||||
|
/// Decrypts a message. Account must be unlocked.
|
||||||
|
pub fn decrypt(&self, account: Address, shared_mac: &[u8], message: &[u8]) -> Result<Vec<u8>, Error> {
|
||||||
|
let data = {
|
||||||
|
let mut unlocked = self.unlocked.lock();
|
||||||
|
let data = try!(unlocked.get(&account).ok_or(Error::NotUnlocked)).clone();
|
||||||
|
if let Unlock::Temp = data.unlock {
|
||||||
|
unlocked.remove(&account).expect("data exists: so key must exist: qed");
|
||||||
|
}
|
||||||
|
if let Unlock::Timed((ref start, ref duration)) = data.unlock {
|
||||||
|
if start.elapsed() > Duration::from_millis(*duration as u64) {
|
||||||
|
unlocked.remove(&account).expect("data exists: so key must exist: qed");
|
||||||
|
return Err(Error::NotUnlocked);
|
||||||
|
}
|
||||||
|
}
|
||||||
|
data
|
||||||
|
};
|
||||||
|
|
||||||
|
Ok(try!(self.sstore.decrypt(&account, &data.password, shared_mac, message)))
|
||||||
|
}
|
||||||
|
|
||||||
/// Unlocks an account, signs the message, and locks it again.
|
/// Unlocks an account, signs the message, and locks it again.
|
||||||
pub fn sign_with_password(&self, account: Address, password: String, message: Message) -> Result<Signature, Error> {
|
pub fn sign_with_password(&self, account: Address, password: String, message: Message) -> Result<Signature, Error> {
|
||||||
let signature = try!(self.sstore.sign(&account, &password, &message));
|
let signature = try!(self.sstore.sign(&account, &password, &message));
|
||||||
|
@ -215,8 +215,11 @@ pub trait BlockChainClient : Sync + Send {
|
|||||||
/// Extended client interface used for mining
|
/// Extended client interface used for mining
|
||||||
pub trait MiningBlockChainClient : BlockChainClient {
|
pub trait MiningBlockChainClient : BlockChainClient {
|
||||||
/// Returns OpenBlock prepared for closing.
|
/// Returns OpenBlock prepared for closing.
|
||||||
fn prepare_open_block(&self, author: Address, gas_range_target: (U256, U256), extra_data: Bytes)
|
fn prepare_open_block(&self,
|
||||||
-> OpenBlock;
|
author: Address,
|
||||||
|
gas_range_target: (U256, U256),
|
||||||
|
extra_data: Bytes
|
||||||
|
) -> OpenBlock;
|
||||||
|
|
||||||
/// Returns EvmFactory.
|
/// Returns EvmFactory.
|
||||||
fn vm_factory(&self) -> &EvmFactory;
|
fn vm_factory(&self) -> &EvmFactory;
|
||||||
|
@ -21,7 +21,7 @@ use std::cell::*;
|
|||||||
use rlp::*;
|
use rlp::*;
|
||||||
use util::sha3::Hashable;
|
use util::sha3::Hashable;
|
||||||
use util::{H256, Address, U256, Bytes};
|
use util::{H256, Address, U256, Bytes};
|
||||||
use ethkey::{Signature, sign, Secret, recover, public_to_address, Error as EthkeyError};
|
use ethkey::{Signature, sign, Secret, Public, recover, public_to_address, Error as EthkeyError};
|
||||||
use error::*;
|
use error::*;
|
||||||
use evm::Schedule;
|
use evm::Schedule;
|
||||||
use header::BlockNumber;
|
use header::BlockNumber;
|
||||||
@ -305,13 +305,18 @@ impl SignedTransaction {
|
|||||||
match sender {
|
match sender {
|
||||||
Some(s) => Ok(s),
|
Some(s) => Ok(s),
|
||||||
None => {
|
None => {
|
||||||
let s = public_to_address(&try!(recover(&self.signature(), &self.unsigned.hash())));
|
let s = public_to_address(&try!(self.public_key()));
|
||||||
self.sender.set(Some(s));
|
self.sender.set(Some(s));
|
||||||
Ok(s)
|
Ok(s)
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
|
/// Returns the public key of the sender.
|
||||||
|
pub fn public_key(&self) -> Result<Public, Error> {
|
||||||
|
Ok(try!(recover(&self.signature(), &self.unsigned.hash())))
|
||||||
|
}
|
||||||
|
|
||||||
/// Do basic validation, checking for valid signature and minimum gas,
|
/// Do basic validation, checking for valid signature and minimum gas,
|
||||||
// TODO: consider use in block validation.
|
// TODO: consider use in block validation.
|
||||||
#[cfg(test)]
|
#[cfg(test)]
|
||||||
|
@ -22,6 +22,7 @@ extern crate crypto as rcrypto;
|
|||||||
extern crate secp256k1;
|
extern crate secp256k1;
|
||||||
extern crate ethkey;
|
extern crate ethkey;
|
||||||
|
|
||||||
|
use std::fmt;
|
||||||
use tiny_keccak::Keccak;
|
use tiny_keccak::Keccak;
|
||||||
use rcrypto::pbkdf2::pbkdf2;
|
use rcrypto::pbkdf2::pbkdf2;
|
||||||
use rcrypto::scrypt::{scrypt, ScryptParams};
|
use rcrypto::scrypt::{scrypt, ScryptParams};
|
||||||
@ -39,6 +40,17 @@ pub enum Error {
|
|||||||
InvalidMessage,
|
InvalidMessage,
|
||||||
}
|
}
|
||||||
|
|
||||||
|
impl fmt::Display for Error {
|
||||||
|
fn fmt(&self, f: &mut fmt::Formatter) -> Result<(), fmt::Error> {
|
||||||
|
let s = match *self {
|
||||||
|
Error::Secp(ref err) => err.to_string(),
|
||||||
|
Error::InvalidMessage => "Invalid message".into(),
|
||||||
|
};
|
||||||
|
|
||||||
|
write!(f, "{}", s)
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
impl From<SecpError> for Error {
|
impl From<SecpError> for Error {
|
||||||
fn from(e: SecpError) -> Self {
|
fn from(e: SecpError) -> Self {
|
||||||
Error::Secp(e)
|
Error::Secp(e)
|
||||||
|
@ -1,7 +1,7 @@
|
|||||||
[package]
|
[package]
|
||||||
name = "ethkey"
|
name = "ethkey"
|
||||||
version = "0.2.0"
|
version = "0.2.0"
|
||||||
authors = ["debris <marek.kotewicz@gmail.com>"]
|
authors = ["Ethcore <admin@ethcore.io>"]
|
||||||
|
|
||||||
[dependencies]
|
[dependencies]
|
||||||
rand = "0.3.14"
|
rand = "0.3.14"
|
||||||
|
@ -16,7 +16,7 @@
|
|||||||
|
|
||||||
use ethkey::{KeyPair, sign, Address, Secret, Signature, Message};
|
use ethkey::{KeyPair, sign, Address, Secret, Signature, Message};
|
||||||
use {json, Error, crypto};
|
use {json, Error, crypto};
|
||||||
use crypto::Keccak256;
|
use crypto::{Keccak256};
|
||||||
use random::Random;
|
use random::Random;
|
||||||
use account::{Version, Cipher, Kdf, Aes128Ctr, Pbkdf2, Prf};
|
use account::{Version, Cipher, Kdf, Aes128Ctr, Pbkdf2, Prf};
|
||||||
|
|
||||||
@ -170,6 +170,11 @@ impl SafeAccount {
|
|||||||
sign(&secret, message).map_err(From::from)
|
sign(&secret, message).map_err(From::from)
|
||||||
}
|
}
|
||||||
|
|
||||||
|
pub fn decrypt(&self, password: &str, shared_mac: &[u8], message: &[u8]) -> Result<Vec<u8>, Error> {
|
||||||
|
let secret = try!(self.crypto.secret(password));
|
||||||
|
crypto::ecies::decrypt(&secret, shared_mac, message).map_err(From::from)
|
||||||
|
}
|
||||||
|
|
||||||
pub fn change_password(&self, old_password: &str, new_password: &str, iterations: u32) -> Result<Self, Error> {
|
pub fn change_password(&self, old_password: &str, new_password: &str, iterations: u32) -> Result<Self, Error> {
|
||||||
let secret = try!(self.crypto.secret(old_password));
|
let secret = try!(self.crypto.secret(old_password));
|
||||||
let result = SafeAccount {
|
let result = SafeAccount {
|
||||||
|
@ -17,6 +17,7 @@
|
|||||||
use std::fmt;
|
use std::fmt;
|
||||||
use std::io::Error as IoError;
|
use std::io::Error as IoError;
|
||||||
use ethkey::Error as EthKeyError;
|
use ethkey::Error as EthKeyError;
|
||||||
|
use crypto::Error as EthCryptoError;
|
||||||
|
|
||||||
#[derive(Debug)]
|
#[derive(Debug)]
|
||||||
pub enum Error {
|
pub enum Error {
|
||||||
@ -28,6 +29,7 @@ pub enum Error {
|
|||||||
InvalidKeyFile(String),
|
InvalidKeyFile(String),
|
||||||
CreationFailed,
|
CreationFailed,
|
||||||
EthKey(EthKeyError),
|
EthKey(EthKeyError),
|
||||||
|
EthCrypto(EthCryptoError),
|
||||||
Custom(String),
|
Custom(String),
|
||||||
}
|
}
|
||||||
|
|
||||||
@ -42,6 +44,7 @@ impl fmt::Display for Error {
|
|||||||
Error::InvalidKeyFile(ref reason) => format!("Invalid key file: {}", reason),
|
Error::InvalidKeyFile(ref reason) => format!("Invalid key file: {}", reason),
|
||||||
Error::CreationFailed => "Account creation failed".into(),
|
Error::CreationFailed => "Account creation failed".into(),
|
||||||
Error::EthKey(ref err) => err.to_string(),
|
Error::EthKey(ref err) => err.to_string(),
|
||||||
|
Error::EthCrypto(ref err) => err.to_string(),
|
||||||
Error::Custom(ref s) => s.clone(),
|
Error::Custom(ref s) => s.clone(),
|
||||||
};
|
};
|
||||||
|
|
||||||
@ -60,3 +63,9 @@ impl From<EthKeyError> for Error {
|
|||||||
Error::EthKey(err)
|
Error::EthKey(err)
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
|
impl From<EthCryptoError> for Error {
|
||||||
|
fn from(err: EthCryptoError) -> Self {
|
||||||
|
Error::EthCrypto(err)
|
||||||
|
}
|
||||||
|
}
|
||||||
|
@ -144,6 +144,11 @@ impl SecretStore for EthStore {
|
|||||||
account.sign(password, message)
|
account.sign(password, message)
|
||||||
}
|
}
|
||||||
|
|
||||||
|
fn decrypt(&self, account: &Address, password: &str, shared_mac: &[u8], message: &[u8]) -> Result<Vec<u8>, Error> {
|
||||||
|
let account = try!(self.get(account));
|
||||||
|
account.decrypt(password, shared_mac, message)
|
||||||
|
}
|
||||||
|
|
||||||
fn uuid(&self, address: &Address) -> Result<UUID, Error> {
|
fn uuid(&self, address: &Address) -> Result<UUID, Error> {
|
||||||
let account = try!(self.get(address));
|
let account = try!(self.get(address));
|
||||||
Ok(account.id.into())
|
Ok(account.id.into())
|
||||||
|
@ -20,33 +20,24 @@ use json::UUID;
|
|||||||
|
|
||||||
pub trait SecretStore: Send + Sync {
|
pub trait SecretStore: Send + Sync {
|
||||||
fn insert_account(&self, secret: Secret, password: &str) -> Result<Address, Error>;
|
fn insert_account(&self, secret: Secret, password: &str) -> Result<Address, Error>;
|
||||||
|
|
||||||
fn import_presale(&self, json: &[u8], password: &str) -> Result<Address, Error>;
|
fn import_presale(&self, json: &[u8], password: &str) -> Result<Address, Error>;
|
||||||
|
|
||||||
fn import_wallet(&self, json: &[u8], password: &str) -> Result<Address, Error>;
|
fn import_wallet(&self, json: &[u8], password: &str) -> Result<Address, Error>;
|
||||||
|
|
||||||
fn accounts(&self) -> Result<Vec<Address>, Error>;
|
|
||||||
|
|
||||||
fn change_password(&self, account: &Address, old_password: &str, new_password: &str) -> Result<(), Error>;
|
fn change_password(&self, account: &Address, old_password: &str, new_password: &str) -> Result<(), Error>;
|
||||||
|
|
||||||
fn remove_account(&self, account: &Address, password: &str) -> Result<(), Error>;
|
fn remove_account(&self, account: &Address, password: &str) -> Result<(), Error>;
|
||||||
|
|
||||||
fn sign(&self, account: &Address, password: &str, message: &Message) -> Result<Signature, Error>;
|
fn sign(&self, account: &Address, password: &str, message: &Message) -> Result<Signature, Error>;
|
||||||
|
fn decrypt(&self, account: &Address, password: &str, shared_mac: &[u8], message: &[u8]) -> Result<Vec<u8>, Error>;
|
||||||
|
|
||||||
|
fn accounts(&self) -> Result<Vec<Address>, Error>;
|
||||||
fn uuid(&self, account: &Address) -> Result<UUID, Error>;
|
fn uuid(&self, account: &Address) -> Result<UUID, Error>;
|
||||||
|
|
||||||
fn name(&self, account: &Address) -> Result<String, Error>;
|
fn name(&self, account: &Address) -> Result<String, Error>;
|
||||||
|
|
||||||
fn meta(&self, account: &Address) -> Result<String, Error>;
|
fn meta(&self, account: &Address) -> Result<String, Error>;
|
||||||
|
|
||||||
fn set_name(&self, address: &Address, name: String) -> Result<(), Error>;
|
fn set_name(&self, address: &Address, name: String) -> Result<(), Error>;
|
||||||
|
|
||||||
fn set_meta(&self, address: &Address, meta: String) -> Result<(), Error>;
|
fn set_meta(&self, address: &Address, meta: String) -> Result<(), Error>;
|
||||||
|
|
||||||
fn local_path(&self) -> String;
|
fn local_path(&self) -> String;
|
||||||
|
|
||||||
fn list_geth_accounts(&self, testnet: bool) -> Vec<Address>;
|
fn list_geth_accounts(&self, testnet: bool) -> Vec<Address>;
|
||||||
|
|
||||||
fn import_geth_accounts(&self, desired: Vec<Address>, testnet: bool) -> Result<Vec<Address>, Error>;
|
fn import_geth_accounts(&self, desired: Vec<Address>, testnet: bool) -> Result<Vec<Address>, Error>;
|
||||||
}
|
}
|
||||||
|
|
||||||
|
@ -17,6 +17,7 @@ jsonrpc-http-server = { git = "https://github.com/ethcore/jsonrpc-http-server.gi
|
|||||||
ethcore-io = { path = "../util/io" }
|
ethcore-io = { path = "../util/io" }
|
||||||
ethcore-util = { path = "../util" }
|
ethcore-util = { path = "../util" }
|
||||||
ethcore = { path = "../ethcore" }
|
ethcore = { path = "../ethcore" }
|
||||||
|
ethcrypto = { path = "../ethcrypto" }
|
||||||
ethkey = { path = "../ethkey" }
|
ethkey = { path = "../ethkey" }
|
||||||
ethstore = { path = "../ethstore" }
|
ethstore = { path = "../ethstore" }
|
||||||
ethash = { path = "../ethash" }
|
ethash = { path = "../ethash" }
|
||||||
|
@ -28,6 +28,7 @@ extern crate jsonrpc_http_server;
|
|||||||
extern crate ethcore_io as io;
|
extern crate ethcore_io as io;
|
||||||
extern crate ethcore;
|
extern crate ethcore;
|
||||||
extern crate ethkey;
|
extern crate ethkey;
|
||||||
|
extern crate ethcrypto as crypto;
|
||||||
extern crate ethstore;
|
extern crate ethstore;
|
||||||
extern crate ethsync;
|
extern crate ethsync;
|
||||||
extern crate transient_hashmap;
|
extern crate transient_hashmap;
|
||||||
|
@ -45,7 +45,7 @@ use v1::traits::Eth;
|
|||||||
use v1::types::{Block, BlockTransactions, BlockNumber, Bytes, SyncStatus, SyncInfo, Transaction, CallRequest, Index, Filter, Log, Receipt, H64 as RpcH64, H256 as RpcH256, H160 as RpcH160, U256 as RpcU256};
|
use v1::types::{Block, BlockTransactions, BlockNumber, Bytes, SyncStatus, SyncInfo, Transaction, CallRequest, Index, Filter, Log, Receipt, H64 as RpcH64, H256 as RpcH256, H160 as RpcH160, U256 as RpcU256};
|
||||||
use v1::helpers::{CallRequest as CRequest, errors, limit_logs};
|
use v1::helpers::{CallRequest as CRequest, errors, limit_logs};
|
||||||
use v1::helpers::dispatch::{default_gas_price, dispatch_transaction};
|
use v1::helpers::dispatch::{default_gas_price, dispatch_transaction};
|
||||||
use v1::helpers::params::{expect_no_params, params_len, from_params_default_second, from_params_default_third};
|
use v1::helpers::params::{expect_no_params, from_params_default_second, from_params_default_third};
|
||||||
|
|
||||||
/// Eth RPC options
|
/// Eth RPC options
|
||||||
pub struct EthClientOptions {
|
pub struct EthClientOptions {
|
||||||
|
@ -26,7 +26,7 @@ use util::Mutex;
|
|||||||
use v1::traits::EthFilter;
|
use v1::traits::EthFilter;
|
||||||
use v1::types::{BlockNumber, Index, Filter, Log, H256 as RpcH256, U256 as RpcU256};
|
use v1::types::{BlockNumber, Index, Filter, Log, H256 as RpcH256, U256 as RpcU256};
|
||||||
use v1::helpers::{PollFilter, PollManager, limit_logs};
|
use v1::helpers::{PollFilter, PollManager, limit_logs};
|
||||||
use v1::helpers::params::{expect_no_params, params_len};
|
use v1::helpers::params::{expect_no_params};
|
||||||
use v1::impls::eth::pending_logs;
|
use v1::impls::eth::pending_logs;
|
||||||
|
|
||||||
/// Eth filter rpc implementation.
|
/// Eth filter rpc implementation.
|
||||||
|
@ -26,7 +26,7 @@ use ethcore::account_provider::AccountProvider;
|
|||||||
use v1::helpers::{errors, SigningQueue, ConfirmationPromise, ConfirmationResult, ConfirmationPayload, TransactionRequest as TRequest, FilledTransactionRequest as FilledRequest, SignerService};
|
use v1::helpers::{errors, SigningQueue, ConfirmationPromise, ConfirmationResult, ConfirmationPayload, TransactionRequest as TRequest, FilledTransactionRequest as FilledRequest, SignerService};
|
||||||
use v1::helpers::dispatch::{default_gas_price, sign_and_dispatch};
|
use v1::helpers::dispatch::{default_gas_price, sign_and_dispatch};
|
||||||
use v1::traits::EthSigning;
|
use v1::traits::EthSigning;
|
||||||
use v1::types::{TransactionRequest, H160 as RpcH160, H256 as RpcH256, H520 as RpcH520, U256 as RpcU256};
|
use v1::types::{TransactionRequest, H160 as RpcH160, H256 as RpcH256, H520 as RpcH520, U256 as RpcU256, Bytes as RpcBytes};
|
||||||
|
|
||||||
fn fill_optional_fields<C, M>(request: TRequest, client: &C, miner: &M) -> FilledRequest
|
fn fill_optional_fields<C, M>(request: TRequest, client: &C, miner: &M) -> FilledRequest
|
||||||
where C: MiningBlockChainClient, M: MinerService {
|
where C: MiningBlockChainClient, M: MinerService {
|
||||||
@ -168,6 +168,13 @@ impl<C, M> EthSigning for EthSigningQueueClient<C, M>
|
|||||||
})
|
})
|
||||||
}
|
}
|
||||||
|
|
||||||
|
fn decrypt_message(&self, params: Params) -> Result<Value, Error> {
|
||||||
|
try!(self.active());
|
||||||
|
from_params::<(RpcH160, RpcBytes)>(params).and_then(|(_account, _ciphertext)| {
|
||||||
|
Err(errors::unimplemented())
|
||||||
|
})
|
||||||
|
}
|
||||||
|
|
||||||
fn check_request(&self, params: Params) -> Result<Value, Error> {
|
fn check_request(&self, params: Params) -> Result<Value, Error> {
|
||||||
try!(self.active());
|
try!(self.active());
|
||||||
let mut pending = self.pending.lock();
|
let mut pending = self.pending.lock();
|
||||||
@ -241,6 +248,14 @@ impl<C, M> EthSigning for EthSigningUnsafeClient<C, M> where
|
|||||||
}))
|
}))
|
||||||
}
|
}
|
||||||
|
|
||||||
|
fn decrypt_message(&self, params: Params) -> Result<Value, Error> {
|
||||||
|
try!(self.active());
|
||||||
|
from_params::<(RpcH160, RpcBytes)>(params).and_then(|(address, ciphertext)| {
|
||||||
|
let s = try!(take_weak!(self.accounts).decrypt(address.into(), &[0; 0], &ciphertext.0).map_err(|_| Error::internal_error()));
|
||||||
|
Ok(to_value(RpcBytes::from(s)))
|
||||||
|
})
|
||||||
|
}
|
||||||
|
|
||||||
fn post_sign(&self, _: Params) -> Result<Value, Error> {
|
fn post_sign(&self, _: Params) -> Result<Value, Error> {
|
||||||
// We don't support this in non-signer mode.
|
// We don't support this in non-signer mode.
|
||||||
Err(errors::signer_disabled())
|
Err(errors::signer_disabled())
|
||||||
|
@ -21,6 +21,7 @@ use std::collections::{BTreeMap};
|
|||||||
use util::{RotatingLogger, Address};
|
use util::{RotatingLogger, Address};
|
||||||
use util::misc::version_data;
|
use util::misc::version_data;
|
||||||
|
|
||||||
|
use crypto::ecies;
|
||||||
use ethkey::{Brain, Generator};
|
use ethkey::{Brain, Generator};
|
||||||
use ethstore::random_phrase;
|
use ethstore::random_phrase;
|
||||||
use ethsync::{SyncProvider, ManageNetwork};
|
use ethsync::{SyncProvider, ManageNetwork};
|
||||||
@ -29,7 +30,7 @@ use ethcore::client::{MiningBlockChainClient};
|
|||||||
|
|
||||||
use jsonrpc_core::*;
|
use jsonrpc_core::*;
|
||||||
use v1::traits::Ethcore;
|
use v1::traits::Ethcore;
|
||||||
use v1::types::{Bytes, U256, H160, Peers};
|
use v1::types::{Bytes, U256, H160, H512, Peers};
|
||||||
use v1::helpers::{errors, SigningQueue, SignerService, NetworkSettings};
|
use v1::helpers::{errors, SigningQueue, SignerService, NetworkSettings};
|
||||||
use v1::helpers::params::expect_no_params;
|
use v1::helpers::params::expect_no_params;
|
||||||
|
|
||||||
@ -217,4 +218,12 @@ impl<C, M, S: ?Sized> Ethcore for EthcoreClient<C, M, S> where M: MinerService +
|
|||||||
to_value(&H160::from(Brain::new(phrase).generate().unwrap().address()))
|
to_value(&H160::from(Brain::new(phrase).generate().unwrap().address()))
|
||||||
)
|
)
|
||||||
}
|
}
|
||||||
|
|
||||||
|
fn encrypt_message(&self, params: Params) -> Result<Value, Error> {
|
||||||
|
try!(self.active());
|
||||||
|
from_params::<(H512, Bytes)>(params).and_then(|(key, phrase)| {
|
||||||
|
let s = try!(ecies::encrypt(&key.into(), &[0; 0], &phrase.0).map_err(|_| Error::internal_error()));
|
||||||
|
Ok(to_value(&Bytes::from(s)))
|
||||||
|
})
|
||||||
|
}
|
||||||
}
|
}
|
||||||
|
@ -457,7 +457,7 @@ fn rpc_eth_pending_transaction_by_hash() {
|
|||||||
tester.miner.pending_transactions.lock().insert(H256::zero(), tx);
|
tester.miner.pending_transactions.lock().insert(H256::zero(), tx);
|
||||||
}
|
}
|
||||||
|
|
||||||
let response = r#"{"jsonrpc":"2.0","result":{"blockHash":null,"blockNumber":null,"creates":null,"from":"0x0f65fe9276bc9a24ae7083ae28e2660ef72df99e","gas":"0x5208","gasPrice":"0x1","hash":"0x41df922fd0d4766fcc02e161f8295ec28522f329ae487f14d811e4b64c8d6e31","input":"0x","nonce":"0x0","raw":"0xf85f800182520894095e7baea6a6c7c4c2dfeb977efac326af552d870a801ba048b55bfa915ac795c431978d8a6a992b628d557da5ff759b307d495a36649353a0efffd310ac743f371de3b9f7f9cb56c0b28ad43601b4ab949f53faa07bd2c804","to":"0x095e7baea6a6c7c4c2dfeb977efac326af552d87","transactionIndex":null,"value":"0xa"},"id":1}"#;
|
let response = r#"{"jsonrpc":"2.0","result":{"blockHash":null,"blockNumber":null,"creates":null,"from":"0x0f65fe9276bc9a24ae7083ae28e2660ef72df99e","gas":"0x5208","gasPrice":"0x1","hash":"0x41df922fd0d4766fcc02e161f8295ec28522f329ae487f14d811e4b64c8d6e31","input":"0x","nonce":"0x0","publicKey":"0x7ae46da747962c2ee46825839c1ef9298e3bd2e70ca2938495c3693a485ec3eaa8f196327881090ff64cf4fbb0a48485d4f83098e189ed3b7a87d5941b59f789","raw":"0xf85f800182520894095e7baea6a6c7c4c2dfeb977efac326af552d870a801ba048b55bfa915ac795c431978d8a6a992b628d557da5ff759b307d495a36649353a0efffd310ac743f371de3b9f7f9cb56c0b28ad43601b4ab949f53faa07bd2c804","to":"0x095e7baea6a6c7c4c2dfeb977efac326af552d87","transactionIndex":null,"value":"0xa"},"id":1}"#;
|
||||||
let request = r#"{
|
let request = r#"{
|
||||||
"jsonrpc": "2.0",
|
"jsonrpc": "2.0",
|
||||||
"method": "eth_getTransactionByHash",
|
"method": "eth_getTransactionByHash",
|
||||||
|
@ -227,6 +227,10 @@ pub trait EthSigning: Sized + Send + Sync + 'static {
|
|||||||
/// or an error.
|
/// or an error.
|
||||||
fn check_request(&self, _: Params) -> Result<Value, Error>;
|
fn check_request(&self, _: Params) -> Result<Value, Error>;
|
||||||
|
|
||||||
|
/// Decrypt some ECIES-encrypted message.
|
||||||
|
/// First parameter is the address with which it is encrypted, second is the ciphertext.
|
||||||
|
fn decrypt_message(&self, _: Params) -> Result<Value, Error>;
|
||||||
|
|
||||||
/// Should be used to convert object to io delegate.
|
/// Should be used to convert object to io delegate.
|
||||||
fn to_delegate(self) -> IoDelegate<Self> {
|
fn to_delegate(self) -> IoDelegate<Self> {
|
||||||
let mut delegate = IoDelegate::new(Arc::new(self));
|
let mut delegate = IoDelegate::new(Arc::new(self));
|
||||||
@ -235,6 +239,7 @@ pub trait EthSigning: Sized + Send + Sync + 'static {
|
|||||||
delegate.add_method("eth_postSign", EthSigning::post_sign);
|
delegate.add_method("eth_postSign", EthSigning::post_sign);
|
||||||
delegate.add_method("eth_postTransaction", EthSigning::post_transaction);
|
delegate.add_method("eth_postTransaction", EthSigning::post_transaction);
|
||||||
delegate.add_method("eth_checkRequest", EthSigning::check_request);
|
delegate.add_method("eth_checkRequest", EthSigning::check_request);
|
||||||
|
delegate.add_method("ethcore_decryptMessage", EthSigning::decrypt_message);
|
||||||
delegate
|
delegate
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
@ -76,6 +76,10 @@ pub trait Ethcore: Sized + Send + Sync + 'static {
|
|||||||
/// Returns the value of the registrar for this network.
|
/// Returns the value of the registrar for this network.
|
||||||
fn registry_address(&self, _: Params) -> Result<Value, Error>;
|
fn registry_address(&self, _: Params) -> Result<Value, Error>;
|
||||||
|
|
||||||
|
/// Encrypt some data with a public key under ECIES.
|
||||||
|
/// First parameter is the 512-byte destination public key, second is the message.
|
||||||
|
fn encrypt_message(&self, _: Params) -> Result<Value, Error>;
|
||||||
|
|
||||||
/// Should be used to convert object to io delegate.
|
/// Should be used to convert object to io delegate.
|
||||||
fn to_delegate(self) -> IoDelegate<Self> {
|
fn to_delegate(self) -> IoDelegate<Self> {
|
||||||
let mut delegate = IoDelegate::new(Arc::new(self));
|
let mut delegate = IoDelegate::new(Arc::new(self));
|
||||||
@ -98,6 +102,7 @@ pub trait Ethcore: Sized + Send + Sync + 'static {
|
|||||||
delegate.add_method("ethcore_generateSecretPhrase", Ethcore::generate_secret_phrase);
|
delegate.add_method("ethcore_generateSecretPhrase", Ethcore::generate_secret_phrase);
|
||||||
delegate.add_method("ethcore_phraseToAddress", Ethcore::phrase_to_address);
|
delegate.add_method("ethcore_phraseToAddress", Ethcore::phrase_to_address);
|
||||||
delegate.add_method("ethcore_registryAddress", Ethcore::registry_address);
|
delegate.add_method("ethcore_registryAddress", Ethcore::registry_address);
|
||||||
|
delegate.add_method("ethcore_encryptMessage", Ethcore::encrypt_message);
|
||||||
|
|
||||||
delegate
|
delegate
|
||||||
}
|
}
|
||||||
|
@ -103,7 +103,7 @@ mod tests {
|
|||||||
fn test_serialize_block_transactions() {
|
fn test_serialize_block_transactions() {
|
||||||
let t = BlockTransactions::Full(vec![Transaction::default()]);
|
let t = BlockTransactions::Full(vec![Transaction::default()]);
|
||||||
let serialized = serde_json::to_string(&t).unwrap();
|
let serialized = serde_json::to_string(&t).unwrap();
|
||||||
assert_eq!(serialized, r#"[{"hash":"0x0000000000000000000000000000000000000000000000000000000000000000","nonce":"0x0","blockHash":null,"blockNumber":null,"transactionIndex":null,"from":"0x0000000000000000000000000000000000000000","to":null,"value":"0x0","gasPrice":"0x0","gas":"0x0","input":"0x","creates":null,"raw":"0x"}]"#);
|
assert_eq!(serialized, r#"[{"hash":"0x0000000000000000000000000000000000000000000000000000000000000000","nonce":"0x0","blockHash":null,"blockNumber":null,"transactionIndex":null,"from":"0x0000000000000000000000000000000000000000","to":null,"value":"0x0","gasPrice":"0x0","gas":"0x0","input":"0x","creates":null,"raw":"0x","publicKey":null}]"#);
|
||||||
|
|
||||||
let t = BlockTransactions::Hashes(vec![H256::default().into()]);
|
let t = BlockTransactions::Hashes(vec![H256::default().into()]);
|
||||||
let serialized = serde_json::to_string(&t).unwrap();
|
let serialized = serde_json::to_string(&t).unwrap();
|
||||||
|
@ -20,7 +20,7 @@ use std::cmp::Ordering;
|
|||||||
use std::hash::{Hash, Hasher};
|
use std::hash::{Hash, Hasher};
|
||||||
use serde;
|
use serde;
|
||||||
use rustc_serialize::hex::{ToHex, FromHex};
|
use rustc_serialize::hex::{ToHex, FromHex};
|
||||||
use util::{H64 as Eth64, H256 as EthH256, H520 as EthH520, H2048 as Eth2048, H160 as Eth160};
|
use util::{H64 as Eth64, H160 as Eth160, H256 as Eth256, H520 as Eth520, H512 as Eth512, H2048 as Eth2048};
|
||||||
|
|
||||||
macro_rules! impl_hash {
|
macro_rules! impl_hash {
|
||||||
($name: ident, $other: ident, $size: expr) => {
|
($name: ident, $other: ident, $size: expr) => {
|
||||||
@ -144,6 +144,7 @@ macro_rules! impl_hash {
|
|||||||
|
|
||||||
impl_hash!(H64, Eth64, 8);
|
impl_hash!(H64, Eth64, 8);
|
||||||
impl_hash!(H160, Eth160, 20);
|
impl_hash!(H160, Eth160, 20);
|
||||||
impl_hash!(H256, EthH256, 32);
|
impl_hash!(H256, Eth256, 32);
|
||||||
impl_hash!(H520, EthH520, 65);
|
impl_hash!(H512, Eth512, 64);
|
||||||
|
impl_hash!(H520, Eth520, 65);
|
||||||
impl_hash!(H2048, Eth2048, 256);
|
impl_hash!(H2048, Eth2048, 256);
|
||||||
|
@ -37,7 +37,7 @@ pub use self::block_number::BlockNumber;
|
|||||||
pub use self::call_request::CallRequest;
|
pub use self::call_request::CallRequest;
|
||||||
pub use self::confirmations::{ConfirmationPayload, ConfirmationRequest, TransactionModification};
|
pub use self::confirmations::{ConfirmationPayload, ConfirmationRequest, TransactionModification};
|
||||||
pub use self::filter::Filter;
|
pub use self::filter::Filter;
|
||||||
pub use self::hash::{H64, H160, H256, H520, H2048};
|
pub use self::hash::{H64, H160, H256, H512, H520, H2048};
|
||||||
pub use self::index::Index;
|
pub use self::index::Index;
|
||||||
pub use self::log::Log;
|
pub use self::log::Log;
|
||||||
pub use self::sync::{SyncStatus, SyncInfo, Peers};
|
pub use self::sync::{SyncStatus, SyncInfo, Peers};
|
||||||
|
@ -16,7 +16,7 @@
|
|||||||
|
|
||||||
use ethcore::contract_address;
|
use ethcore::contract_address;
|
||||||
use ethcore::transaction::{LocalizedTransaction, Action, SignedTransaction};
|
use ethcore::transaction::{LocalizedTransaction, Action, SignedTransaction};
|
||||||
use v1::types::{Bytes, H160, H256, U256};
|
use v1::types::{Bytes, H160, H256, U256, H512};
|
||||||
|
|
||||||
/// Transaction
|
/// Transaction
|
||||||
#[derive(Debug, Default, Serialize)]
|
#[derive(Debug, Default, Serialize)]
|
||||||
@ -51,6 +51,9 @@ pub struct Transaction {
|
|||||||
pub creates: Option<H160>,
|
pub creates: Option<H160>,
|
||||||
/// Raw transaction data
|
/// Raw transaction data
|
||||||
pub raw: Bytes,
|
pub raw: Bytes,
|
||||||
|
/// Public key of the signer.
|
||||||
|
#[serde(rename="publicKey")]
|
||||||
|
pub public_key: Option<H512>,
|
||||||
}
|
}
|
||||||
|
|
||||||
impl From<LocalizedTransaction> for Transaction {
|
impl From<LocalizedTransaction> for Transaction {
|
||||||
@ -75,6 +78,7 @@ impl From<LocalizedTransaction> for Transaction {
|
|||||||
Action::Call(_) => None,
|
Action::Call(_) => None,
|
||||||
},
|
},
|
||||||
raw: ::rlp::encode(&t.signed).to_vec().into(),
|
raw: ::rlp::encode(&t.signed).to_vec().into(),
|
||||||
|
public_key: t.public_key().ok().map(Into::into),
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
@ -101,6 +105,7 @@ impl From<SignedTransaction> for Transaction {
|
|||||||
Action::Call(_) => None,
|
Action::Call(_) => None,
|
||||||
},
|
},
|
||||||
raw: ::rlp::encode(&t).to_vec().into(),
|
raw: ::rlp::encode(&t).to_vec().into(),
|
||||||
|
public_key: t.public_key().ok().map(Into::into),
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
@ -114,7 +119,7 @@ mod tests {
|
|||||||
fn test_transaction_serialize() {
|
fn test_transaction_serialize() {
|
||||||
let t = Transaction::default();
|
let t = Transaction::default();
|
||||||
let serialized = serde_json::to_string(&t).unwrap();
|
let serialized = serde_json::to_string(&t).unwrap();
|
||||||
assert_eq!(serialized, r#"{"hash":"0x0000000000000000000000000000000000000000000000000000000000000000","nonce":"0x0","blockHash":null,"blockNumber":null,"transactionIndex":null,"from":"0x0000000000000000000000000000000000000000","to":null,"value":"0x0","gasPrice":"0x0","gas":"0x0","input":"0x","creates":null,"raw":"0x"}"#);
|
assert_eq!(serialized, r#"{"hash":"0x0000000000000000000000000000000000000000000000000000000000000000","nonce":"0x0","blockHash":null,"blockNumber":null,"transactionIndex":null,"from":"0x0000000000000000000000000000000000000000","to":null,"value":"0x0","gasPrice":"0x0","gas":"0x0","input":"0x","creates":null,"raw":"0x","publicKey":null}"#);
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
|
Loading…
Reference in New Issue
Block a user