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

Correct format of eth_signTransaction #3503

Merged
merged 1 commit into from
Nov 18, 2016
Merged
Show file tree
Hide file tree
Changes from all commits
Commits
File filter

Filter by extension

Filter by extension

Conversations
Failed to load comments.
Loading
Jump to
Jump to file
Failed to load files.
Loading
Diff view
Diff view
4 changes: 2 additions & 2 deletions rpc/src/v1/helpers/dispatch.rs
Original file line number Diff line number Diff line change
Expand Up @@ -28,6 +28,7 @@ use jsonrpc_core::Error;
use v1::helpers::{errors, TransactionRequest, FilledTransactionRequest, ConfirmationPayload};
use v1::types::{
H256 as RpcH256, H520 as RpcH520, Bytes as RpcBytes,
RichRawTransaction as RpcRichRawTransaction,
ConfirmationPayload as RpcConfirmationPayload,
ConfirmationResponse,
SignRequest as RpcSignRequest,
Expand All @@ -47,8 +48,7 @@ pub fn execute<C, M>(client: &C, miner: &M, accounts: &AccountProvider, payload:
},
ConfirmationPayload::SignTransaction(request) => {
sign_no_dispatch(client, miner, accounts, request, pass)
.map(|tx| rlp::encode(&tx).to_vec())
.map(RpcBytes)
.map(RpcRichRawTransaction::from)
.map(ConfirmationResponse::SignTransaction)
},
ConfirmationPayload::Signature(address, hash) => {
Expand Down
4 changes: 4 additions & 0 deletions rpc/src/v1/impls/eth.rs
Original file line number Diff line number Diff line change
Expand Up @@ -619,6 +619,10 @@ impl<C, SN: ?Sized, S: ?Sized, M, EM> Eth for EthClient<C, SN, S, M, EM> where
}
}

fn submit_transaction(&self, raw: Bytes) -> Result<RpcH256, Error> {
self.send_raw_transaction(raw)
}

fn call(&self, request: CallRequest, num: Trailing<BlockNumber>) -> Result<Bytes, Error> {
try!(self.active());

Expand Down
5 changes: 3 additions & 2 deletions rpc/src/v1/impls/signing.rs
Original file line number Diff line number Diff line change
Expand Up @@ -34,6 +34,7 @@ use v1::traits::{EthSigning, ParitySigning};
use v1::types::{
H160 as RpcH160, H256 as RpcH256, U256 as RpcU256, Bytes as RpcBytes, H520 as RpcH520,
Either as RpcEither,
RichRawTransaction as RpcRichRawTransaction,
TransactionRequest as RpcTransactionRequest,
ConfirmationPayload as RpcConfirmationPayload,
ConfirmationResponse as RpcConfirmationResponse
Expand Down Expand Up @@ -201,11 +202,11 @@ impl<C: 'static, M: 'static> EthSigning for SigningQueueClient<C, M> where
});
}

fn sign_transaction(&self, ready: Ready<RpcBytes>, request: RpcTransactionRequest) {
fn sign_transaction(&self, ready: Ready<RpcRichRawTransaction>, request: RpcTransactionRequest) {
let res = self.active().and_then(|_| self.dispatch(RpcConfirmationPayload::SignTransaction(request)));
self.handle_dispatch(res, |response| {
match response {
Ok(RpcConfirmationResponse::SignTransaction(rlp)) => ready.ready(Ok(rlp)),
Ok(RpcConfirmationResponse::SignTransaction(tx)) => ready.ready(Ok(tx)),
Err(e) => ready.ready(Err(e)),
e => ready.ready(Err(errors::internal("Unexpected result.", e))),
}
Expand Down
5 changes: 3 additions & 2 deletions rpc/src/v1/impls/signing_unsafe.rs
Original file line number Diff line number Diff line change
Expand Up @@ -31,6 +31,7 @@ use v1::types::{
U256 as RpcU256,
H160 as RpcH160, H256 as RpcH256, H520 as RpcH520, Bytes as RpcBytes,
Either as RpcEither,
RichRawTransaction as RpcRichRawTransaction,
TransactionRequest as RpcTransactionRequest,
ConfirmationPayload as RpcConfirmationPayload,
ConfirmationResponse as RpcConfirmationResponse,
Expand Down Expand Up @@ -100,9 +101,9 @@ impl<C: 'static, M: 'static> EthSigning for SigningUnsafeClient<C, M> where
ready.ready(result);
}

fn sign_transaction(&self, ready: Ready<RpcBytes>, request: RpcTransactionRequest) {
fn sign_transaction(&self, ready: Ready<RpcRichRawTransaction>, request: RpcTransactionRequest) {
let result = match self.handle(RpcConfirmationPayload::SignTransaction(request)) {
Ok(RpcConfirmationResponse::SignTransaction(rlp)) => Ok(rlp),
Ok(RpcConfirmationResponse::SignTransaction(tx)) => Ok(tx),
Err(e) => Err(e),
e => Err(errors::internal("Unexpected result", e)),
};
Expand Down
26 changes: 22 additions & 4 deletions rpc/src/v1/tests/mocked/eth.rs
Original file line number Diff line number Diff line change
Expand Up @@ -18,8 +18,10 @@ use std::str::FromStr;
use std::collections::HashMap;
use std::sync::Arc;
use std::time::{Instant, Duration};
use rustc_serialize::hex::ToHex;
use time::get_time;
use rlp;
use jsonrpc_core::IoHandler;

use util::{Uint, U256, Address, H256, FixedHash, Mutex};
use ethcore::account_provider::AccountProvider;
use ethcore::client::{TestBlockChainClient, EachBlockWith, Executed, TransactionID};
Expand All @@ -28,10 +30,10 @@ use ethcore::receipt::LocalizedReceipt;
use ethcore::transaction::{Transaction, Action};
use ethcore::miner::{ExternalMiner, MinerService};
use ethsync::SyncState;

use jsonrpc_core::IoHandler;
use v1::{Eth, EthClient, EthClientOptions, EthFilter, EthFilterClient, EthSigning, SigningUnsafeClient};
use v1::tests::helpers::{TestSyncProvider, Config, TestMinerService, TestSnapshotService};
use rustc_serialize::hex::ToHex;
use time::get_time;

fn blockchain_client() -> Arc<TestBlockChainClient> {
let client = TestBlockChainClient::new();
Expand Down Expand Up @@ -798,9 +800,25 @@ fn rpc_eth_sign_transaction() {
};
let signature = tester.accounts_provider.sign(address, None, t.hash(None)).unwrap();
let t = t.with_signature(signature, None);
let signature = t.signature();
let rlp = rlp::encode(&t);

let response = r#"{"jsonrpc":"2.0","result":"0x"#.to_owned() + &rlp.to_hex() + r#"","id":1}"#;
let response = r#"{"jsonrpc":"2.0","result":{"#.to_owned() +
r#""raw":"0x"# + &rlp.to_hex() + r#"","# +
r#""tx":{"# +
r#""blockHash":null,"blockNumber":null,"creates":null,"# +
&format!("\"from\":\"0x{:?}\",", &address) +
r#""gas":"0x76c0","gasPrice":"0x9184e72a000","# +
&format!("\"hash\":\"0x{:?}\",", t.hash()) +
r#""input":"0x","nonce":"0x1","# +
&format!("\"publicKey\":\"0x{:?}\",", t.public_key().unwrap()) +
&format!("\"r\":\"0x{}\",", signature.r().to_hex()) +
&format!("\"raw\":\"0x{}\",", rlp.to_hex()) +
&format!("\"s\":\"0x{}\",", signature.s().to_hex()) +
r#""to":"0xd46e8dd67c5d32be8058bb8eb970870f07244567","transactionIndex":null,"# +
&format!("\"v\":{},", signature.v()) +
r#""value":"0x9184e72a""# +
r#"}},"id":1}"#;

tester.miner.last_nonces.write().insert(address.clone(), U256::zero());

Expand Down
20 changes: 18 additions & 2 deletions rpc/src/v1/tests/mocked/signing.rs
Original file line number Diff line number Diff line change
Expand Up @@ -268,16 +268,32 @@ fn should_add_sign_transaction_to_the_queue() {
};
let signature = tester.accounts.sign(address, Some("test".into()), t.hash(None)).unwrap();
let t = t.with_signature(signature, None);
let signature = t.signature();
let rlp = rlp::encode(&t);

let response = r#"{"jsonrpc":"2.0","result":"0x"#.to_owned() + &rlp.to_hex() + r#"","id":1}"#;
let response = r#"{"jsonrpc":"2.0","result":{"#.to_owned() +
r#""raw":"0x"# + &rlp.to_hex() + r#"","# +
r#""tx":{"# +
r#""blockHash":null,"blockNumber":null,"creates":null,"# +
&format!("\"from\":\"0x{:?}\",", &address) +
r#""gas":"0x76c0","gasPrice":"0x9184e72a000","# +
&format!("\"hash\":\"0x{:?}\",", t.hash()) +
r#""input":"0x","nonce":"0x1","# +
&format!("\"publicKey\":\"0x{:?}\",", t.public_key().unwrap()) +
&format!("\"r\":\"0x{}\",", signature.r().to_hex()) +
&format!("\"raw\":\"0x{}\",", rlp.to_hex()) +
&format!("\"s\":\"0x{}\",", signature.s().to_hex()) +
r#""to":"0xd46e8dd67c5d32be8058bb8eb970870f07244567","transactionIndex":null,"# +
&format!("\"v\":{},", signature.v()) +
r#""value":"0x9184e72a""# +
r#"}},"id":1}"#;

// then
tester.miner.last_nonces.write().insert(address.clone(), U256::zero());
let async_result = tester.io.handle_request(&request).unwrap();
assert_eq!(tester.signer.requests().len(), 1);
// respond
tester.signer.request_confirmed(1.into(), Ok(ConfirmationResponse::SignTransaction(rlp.to_vec().into())));
tester.signer.request_confirmed(1.into(), Ok(ConfirmationResponse::SignTransaction(t.into())));
assert!(async_result.on_result(move |res| {
assert_eq!(res, response.to_owned());
}));
Expand Down
4 changes: 4 additions & 0 deletions rpc/src/v1/traits/eth.rs
Original file line number Diff line number Diff line change
Expand Up @@ -102,6 +102,10 @@ build_rpc_trait! {
#[rpc(name = "eth_sendRawTransaction")]
fn send_raw_transaction(&self, Bytes) -> Result<H256, Error>;

/// Alias of `eth_sendRawTransaction`.
#[rpc(name = "eth_submitTransaction")]
fn submit_transaction(&self, Bytes) -> Result<H256, Error>;

/// Call contract, returning the output data.
#[rpc(name = "eth_call")]
fn call(&self, CallRequest, Trailing<BlockNumber>) -> Result<Bytes, Error>;
Expand Down
8 changes: 4 additions & 4 deletions rpc/src/v1/traits/eth_signing.rs
Original file line number Diff line number Diff line change
Expand Up @@ -17,7 +17,7 @@
//! Eth rpc interface.

use v1::helpers::auto_args::{WrapAsync, Ready};
use v1::types::{H160, H256, H520, TransactionRequest, Bytes};
use v1::types::{H160, H256, H520, TransactionRequest, RichRawTransaction};

build_rpc_trait! {
/// Signing methods implementation relying on unlocked accounts.
Expand All @@ -33,9 +33,9 @@ build_rpc_trait! {
fn send_transaction(&self, Ready<H256>, TransactionRequest);

/// Signs transactions without dispatching it to the network.
/// Returns signed transaction RLP representation.
/// It can be later submitted using `eth_sendRawTransaction`.
/// Returns signed transaction RLP representation and the transaction itself.
/// It can be later submitted using `eth_sendRawTransaction/eth_submitTransaction`.
#[rpc(async, name = "eth_signTransaction")]
fn sign_transaction(&self, Ready<Bytes>, TransactionRequest);
fn sign_transaction(&self, Ready<RichRawTransaction>, TransactionRequest);
}
}
6 changes: 3 additions & 3 deletions rpc/src/v1/types/confirmations.rs
Original file line number Diff line number Diff line change
Expand Up @@ -18,7 +18,7 @@

use std::fmt;
use serde::{Serialize, Serializer};
use v1::types::{U256, TransactionRequest, H160, H256, H520, Bytes};
use v1::types::{U256, TransactionRequest, RichRawTransaction, H160, H256, H520, Bytes};
use v1::helpers;

/// Confirmation waiting in a queue
Expand Down Expand Up @@ -76,12 +76,12 @@ impl From<(H160, Bytes)> for DecryptRequest {
}

/// Confirmation response for particular payload
#[derive(Debug, Clone, Eq, PartialEq, Hash)]
#[derive(Debug, Clone, PartialEq)]
pub enum ConfirmationResponse {
/// Transaction Hash
SendTransaction(H256),
/// Transaction RLP
SignTransaction(Bytes),
SignTransaction(RichRawTransaction),
/// Signature
Signature(H520),
/// Decrypted data
Expand Down
2 changes: 1 addition & 1 deletion rpc/src/v1/types/mod.rs.in
Original file line number Diff line number Diff line change
Expand Up @@ -44,7 +44,7 @@ pub use self::hash::{H64, H160, H256, H512, H520, H2048};
pub use self::index::Index;
pub use self::log::Log;
pub use self::sync::{SyncStatus, SyncInfo, Peers, PeerInfo, PeerNetworkInfo, PeerProtocolsInfo, PeerEthereumProtocolInfo};
pub use self::transaction::Transaction;
pub use self::transaction::{Transaction, RichRawTransaction};
pub use self::transaction_request::TransactionRequest;
pub use self::receipt::Receipt;
pub use self::rpc_settings::RpcSettings;
Expand Down
22 changes: 21 additions & 1 deletion rpc/src/v1/types/transaction.rs
Original file line number Diff line number Diff line change
Expand Up @@ -19,7 +19,7 @@ use ethcore::transaction::{LocalizedTransaction, Action, SignedTransaction};
use v1::types::{Bytes, H160, H256, U256, H512};

/// Transaction
#[derive(Debug, Default, Serialize)]
#[derive(Debug, Default, Clone, PartialEq, Serialize)]
pub struct Transaction {
/// Hash
pub hash: H256,
Expand Down Expand Up @@ -62,6 +62,26 @@ pub struct Transaction {
pub s: H256,
}

/// Geth-compatible output for eth_signTransaction method
#[derive(Debug, Default, Clone, PartialEq, Serialize)]
pub struct RichRawTransaction {
/// Raw transaction RLP
pub raw: Bytes,
/// Transaction details
#[serde(rename="tx")]
pub transaction: Transaction
}

impl From<SignedTransaction> for RichRawTransaction {
fn from(t: SignedTransaction) -> Self {
let tx: Transaction = t.into();
RichRawTransaction {
raw: tx.raw.clone(),
transaction: tx,
}
}
}

impl From<LocalizedTransaction> for Transaction {
fn from(t: LocalizedTransaction) -> Transaction {
let signature = t.signature();
Expand Down