Skip to content

Commit

Permalink
Implement dev signer (#197)
Browse files Browse the repository at this point in the history
* Implement dev signer

* Fix indentation
  • Loading branch information
sorpaas authored Nov 16, 2020
1 parent 229fcc2 commit 3e7265b
Show file tree
Hide file tree
Showing 6 changed files with 113 additions and 10 deletions.
7 changes: 4 additions & 3 deletions rpc/src/eth.rs
Original file line number Diff line number Diff line change
Expand Up @@ -61,15 +61,16 @@ impl<B: BlockT, C, P, CT, BE, H: ExHashT> EthApi<B, C, P, CT, BE, H> {
pool: Arc<P>,
convert_transaction: CT,
network: Arc<NetworkService<B, H>>,
is_authority: bool
signers: Vec<Box<dyn EthSigner>>,
is_authority: bool,
) -> Self {
Self {
client,
pool,
convert_transaction,
network,
is_authority,
signers: Vec::new(),
signers,
_marker: PhantomData,
}
}
Expand Down Expand Up @@ -548,7 +549,7 @@ impl<B, C, P, CT, BE, H: ExHashT> EthApiT for EthApi<B, C, P, CT, BE, H> where

for signer in &self.signers {
if signer.accounts().contains(&from) {
match signer.sign(message) {
match signer.sign(message, &from) {
Ok(t) => transaction = Some(t),
Err(e) => return Box::new(future::result(Err(e))),
}
Expand Down
86 changes: 84 additions & 2 deletions rpc/src/lib.rs
Original file line number Diff line number Diff line change
Expand Up @@ -20,10 +20,11 @@ mod eth_pubsub;
pub use eth::{EthApi, EthApiServer, NetApi, NetApiServer};
pub use eth_pubsub::{EthPubSubApi, EthPubSubApiServer};

use ethereum_types::H160;
use ethereum_types::{H160, H256};
use jsonrpc_core::{ErrorCode, Error, Value};
use rustc_hex::ToHex;
use pallet_evm::ExitReason;
use sha3::{Digest, Keccak256};

pub fn internal_err<T: ToString>(message: T) -> Error {
Error {
Expand Down Expand Up @@ -65,5 +66,86 @@ pub trait EthSigner: Send + Sync {
/// Available accounts from this signer.
fn accounts(&self) -> Vec<H160>;
/// Sign a transaction message using the given account in message.
fn sign(&self, message: ethereum::TransactionMessage) -> Result<ethereum::Transaction, Error>;
fn sign(
&self,
message: ethereum::TransactionMessage,
address: &H160,
) -> Result<ethereum::Transaction, Error>;
}

pub struct EthDevSigner {
keys: Vec<secp256k1::SecretKey>,
}

impl EthDevSigner {
pub fn new() -> Self {
Self {
keys: vec![
secp256k1::SecretKey::parse(&[
0x11, 0x11, 0x11, 0x11, 0x11, 0x11, 0x11, 0x11,
0x11, 0x11, 0x11, 0x11, 0x11, 0x11, 0x11, 0x11,
0x11, 0x11, 0x11, 0x11, 0x11, 0x11, 0x11, 0x11,
0x11, 0x11, 0x11, 0x11, 0x11, 0x11, 0x11, 0x11,
]).expect("Test key is valid; qed"),
],
}
}
}

impl EthSigner for EthDevSigner {
fn accounts(&self) -> Vec<H160> {
self.keys.iter().map(|secret| {
let public = secp256k1::PublicKey::from_secret_key(secret);
let mut res = [0u8; 64];
res.copy_from_slice(&public.serialize()[1..65]);

H160::from(H256::from_slice(Keccak256::digest(&res).as_slice()))
}).collect()
}

fn sign(
&self,
message: ethereum::TransactionMessage,
address: &H160,
) -> Result<ethereum::Transaction, Error> {
let mut transaction = None;

for secret in &self.keys {
let key_address = {
let public = secp256k1::PublicKey::from_secret_key(secret);
let mut res = [0u8; 64];
res.copy_from_slice(&public.serialize()[1..65]);
H160::from(H256::from_slice(Keccak256::digest(&res).as_slice()))
};

if &key_address == address {
let signing_message = secp256k1::Message::parse_slice(&message.hash()[..])
.map_err(|_| internal_err("invalid signing message"))?;
let (signature, recid) = secp256k1::sign(&signing_message, secret);

let v = match message.chain_id {
None => 27 + recid.serialize() as u64,
Some(chain_id) => 2 * chain_id + 35 + recid.serialize() as u64,
};
let rs = signature.serialize();
let r = H256::from_slice(&rs[0..32]);
let s = H256::from_slice(&rs[32..64]);

transaction = Some(ethereum::Transaction {
nonce: message.nonce,
gas_price: message.gas_price,
gas_limit: message.gas_limit,
action: message.action,
value: message.value,
input: message.input.clone(),
signature: ethereum::TransactionSignature::new(v, r, s)
.ok_or(internal_err("signer generated invalid signature"))?,
});

break
}
}

transaction.ok_or(internal_err("signer not available"))
}
}
5 changes: 4 additions & 1 deletion template/node/src/cli.rs
Original file line number Diff line number Diff line change
Expand Up @@ -36,9 +36,12 @@ pub struct RunCmd {
#[structopt(flatten)]
pub base: sc_cli::RunCmd,

/// Force using Kusama native runtime.
/// Choose sealing method.
#[structopt(long = "sealing")]
pub sealing: Option<Sealing>,

#[structopt(long = "enable-dev-signer")]
pub enable_dev_signer: bool,
}

#[derive(Debug, StructOpt)]
Expand Down
2 changes: 1 addition & 1 deletion template/node/src/command.rs
Original file line number Diff line number Diff line change
Expand Up @@ -120,7 +120,7 @@ pub fn run() -> sc_cli::Result<()> {
runner.run_node_until_exit(|config| async move {
match config.role {
Role::Light => service::new_light(config),
_ => service::new_full(config, cli.run.sealing),
_ => service::new_full(config, cli.run.sealing, cli.run.enable_dev_signer),
}
})
}
Expand Down
16 changes: 14 additions & 2 deletions template/node/src/rpc.rs
Original file line number Diff line number Diff line change
Expand Up @@ -57,6 +57,8 @@ pub struct FullDeps<C, P> {
pub deny_unsafe: DenyUnsafe,
/// The Node authority flag
pub is_authority: bool,
/// Whether to enable dev signer
pub enable_dev_signer: bool,
/// Network service
pub network: Arc<NetworkService<Block, Hash>>,
/// Manual seal command sink
Expand All @@ -83,7 +85,10 @@ pub fn create_full<C, P, BE>(
{
use substrate_frame_rpc_system::{FullSystem, SystemApi};
use pallet_transaction_payment_rpc::{TransactionPayment, TransactionPaymentApi};
use frontier_rpc::{EthApi, EthApiServer, NetApi, NetApiServer, EthPubSubApi, EthPubSubApiServer};
use frontier_rpc::{
EthApi, EthApiServer, NetApi, NetApiServer, EthPubSubApi, EthPubSubApiServer,
EthDevSigner, EthSigner,
};

let mut io = jsonrpc_core::IoHandler::default();
let FullDeps {
Expand All @@ -92,7 +97,8 @@ pub fn create_full<C, P, BE>(
deny_unsafe,
is_authority,
network,
command_sink
command_sink,
enable_dev_signer,
} = deps;

io.extend_with(
Expand All @@ -101,12 +107,18 @@ pub fn create_full<C, P, BE>(
io.extend_with(
TransactionPaymentApi::to_delegate(TransactionPayment::new(client.clone()))
);

let mut signers = Vec::new();
if enable_dev_signer {
signers.push(Box::new(EthDevSigner::new()) as Box<dyn EthSigner>);
}
io.extend_with(
EthApiServer::to_delegate(EthApi::new(
client.clone(),
pool.clone(),
frontier_template_runtime::TransactionConverter,
network.clone(),
signers,
is_authority,
))
);
Expand Down
7 changes: 6 additions & 1 deletion template/node/src/service.rs
Original file line number Diff line number Diff line change
Expand Up @@ -153,7 +153,11 @@ pub fn new_partial(config: &Configuration, sealing: Option<Sealing>) -> Result<
}

/// Builds a new service for a full client.
pub fn new_full(config: Configuration, sealing: Option<Sealing>) -> Result<TaskManager, ServiceError> {
pub fn new_full(
config: Configuration,
sealing: Option<Sealing>,
enable_dev_signer: bool,
) -> Result<TaskManager, ServiceError> {
let sc_service::PartialComponents {
client, backend, mut task_manager, import_queue, keystore_container,
select_chain, transaction_pool, inherent_data_providers, other: consensus_result,
Expand Down Expand Up @@ -216,6 +220,7 @@ pub fn new_full(config: Configuration, sealing: Option<Sealing>) -> Result<TaskM
pool: pool.clone(),
deny_unsafe,
is_authority,
enable_dev_signer,
network: network.clone(),
command_sink: Some(command_sink.clone())
};
Expand Down

0 comments on commit 3e7265b

Please sign in to comment.