Merge branch 'master' into rotating-key
Conflicts: ethcore/src/account_provider/mod.rs rpc/src/v1/types/mod.rs.in
This commit is contained in:
@@ -12,8 +12,9 @@ build = "build.rs"
|
||||
log = "0.3"
|
||||
serde = "0.8"
|
||||
serde_json = "0.8"
|
||||
jsonrpc-core = "3.0"
|
||||
jsonrpc-http-server = { git = "https://github.com/ethcore/jsonrpc-http-server.git" }
|
||||
jsonrpc-core = { git = "https://github.com/ethcore/jsonrpc.git" }
|
||||
jsonrpc-http-server = { git = "https://github.com/ethcore/jsonrpc.git" }
|
||||
jsonrpc-ipc-server = { git = "https://github.com/ethcore/jsonrpc.git" }
|
||||
ethcore-io = { path = "../util/io" }
|
||||
ethcore-util = { path = "../util" }
|
||||
ethcore = { path = "../ethcore" }
|
||||
@@ -30,7 +31,6 @@ rustc-serialize = "0.3"
|
||||
transient-hashmap = "0.1"
|
||||
serde_macros = { version = "0.8.0", optional = true }
|
||||
clippy = { version = "0.0.103", optional = true}
|
||||
json-ipc-server = { git = "https://github.com/ethcore/json-ipc-server.git" }
|
||||
ethcore-ipc = { path = "../ipc/rpc" }
|
||||
time = "0.1"
|
||||
|
||||
|
||||
@@ -1,7 +1,7 @@
|
||||
[package]
|
||||
description = "Rpc test client."
|
||||
name = "rpctest"
|
||||
version = "1.4.0"
|
||||
version = "1.5.0"
|
||||
license = "GPL-3.0"
|
||||
authors = ["Ethcore <admin@ethcore.io>"]
|
||||
|
||||
|
||||
@@ -32,7 +32,7 @@ extern crate ethcrypto as crypto;
|
||||
extern crate ethstore;
|
||||
extern crate ethsync;
|
||||
extern crate transient_hashmap;
|
||||
extern crate json_ipc_server as ipc;
|
||||
extern crate jsonrpc_ipc_server as ipc;
|
||||
extern crate ethcore_ipc;
|
||||
extern crate time;
|
||||
extern crate rlp;
|
||||
@@ -51,8 +51,9 @@ extern crate ethcore_devtools as devtools;
|
||||
use std::sync::Arc;
|
||||
use std::net::SocketAddr;
|
||||
use io::PanicHandler;
|
||||
use self::jsonrpc_core::{IoHandler, IoDelegate};
|
||||
use jsonrpc_core::{IoHandler, IoDelegate};
|
||||
|
||||
pub use ipc::{Server as IpcServer, Error as IpcServerError};
|
||||
pub use jsonrpc_http_server::{ServerBuilder, Server, RpcServerError};
|
||||
pub mod v1;
|
||||
pub use v1::{SigningQueue, SignerService, ConfirmationsQueue, NetworkSettings};
|
||||
@@ -66,7 +67,7 @@ pub trait Extendable {
|
||||
|
||||
/// Http server.
|
||||
pub struct RpcServer {
|
||||
handler: Arc<jsonrpc_core::io::IoHandler>,
|
||||
handler: Arc<IoHandler>,
|
||||
}
|
||||
|
||||
impl Extendable for RpcServer {
|
||||
|
||||
@@ -20,7 +20,6 @@ extern crate ethash;
|
||||
|
||||
use std::io::{Write};
|
||||
use std::process::{Command, Stdio};
|
||||
use std::collections::BTreeSet;
|
||||
use std::thread;
|
||||
use std::time::{Instant, Duration};
|
||||
use std::sync::{Arc, Weak};
|
||||
@@ -46,7 +45,7 @@ use self::ethash::SeedHashCompute;
|
||||
use v1::traits::Eth;
|
||||
use v1::types::{
|
||||
RichBlock, Block, BlockTransactions, BlockNumber, Bytes, SyncStatus, SyncInfo,
|
||||
Transaction, CallRequest, Index, Filter, Log, Receipt, Work,
|
||||
Transaction, CallRequest, Index, Filter, Log, Receipt, Work, DappId,
|
||||
H64 as RpcH64, H256 as RpcH256, H160 as RpcH160, U256 as RpcU256,
|
||||
};
|
||||
use v1::helpers::{CallRequest as CRequest, errors, limit_logs};
|
||||
@@ -335,15 +334,15 @@ impl<C, SN: ?Sized, S: ?Sized, M, EM> Eth for EthClient<C, SN, S, M, EM> where
|
||||
Ok(RpcU256::from(default_gas_price(&*client, &*miner)))
|
||||
}
|
||||
|
||||
fn accounts(&self) -> Result<Vec<RpcH160>, Error> {
|
||||
fn accounts(&self, id: Trailing<DappId>) -> Result<Vec<RpcH160>, Error> {
|
||||
try!(self.active());
|
||||
|
||||
let store = take_weak!(self.accounts);
|
||||
let accounts = try!(store.accounts().map_err(|e| errors::internal("Could not fetch accounts.", e)));
|
||||
let addresses = try!(store.addresses_info().map_err(|e| errors::internal("Could not fetch accounts.", e)));
|
||||
let dapp = id.0;
|
||||
|
||||
let set: BTreeSet<Address> = accounts.into_iter().chain(addresses.keys().cloned()).collect();
|
||||
Ok(set.into_iter().map(Into::into).collect())
|
||||
let store = take_weak!(self.accounts);
|
||||
let accounts = try!(store.dapps_addresses(dapp.into()).map_err(|e| errors::internal("Could not fetch accounts.", e)));
|
||||
|
||||
Ok(accounts.into_iter().map(Into::into).collect())
|
||||
}
|
||||
|
||||
fn block_number(&self) -> Result<RpcU256, Error> {
|
||||
|
||||
@@ -25,7 +25,7 @@ use ethcore::client::MiningBlockChainClient;
|
||||
|
||||
use jsonrpc_core::{Value, Error, to_value};
|
||||
use v1::traits::ParityAccounts;
|
||||
use v1::types::{H160 as RpcH160, H256 as RpcH256};
|
||||
use v1::types::{H160 as RpcH160, H256 as RpcH256, DappId};
|
||||
use v1::helpers::errors;
|
||||
|
||||
/// Account management (personal) rpc implementation.
|
||||
@@ -57,7 +57,7 @@ impl<C: 'static> ParityAccounts for ParityAccountsClient<C> where C: MiningBlock
|
||||
let info = try!(store.accounts_info().map_err(|e| errors::account("Could not fetch account info.", e)));
|
||||
let other = store.addresses_info().expect("addresses_info always returns Ok; qed");
|
||||
|
||||
Ok(info.into_iter().chain(other.into_iter()).map(|(a, v)| {
|
||||
Ok(other.into_iter().chain(info.into_iter()).map(|(a, v)| {
|
||||
let m = map![
|
||||
"name".to_owned() => to_value(&v.name),
|
||||
"meta".to_owned() => to_value(&v.meta),
|
||||
@@ -126,6 +126,16 @@ impl<C: 'static> ParityAccounts for ParityAccountsClient<C> where C: MiningBlock
|
||||
.map_err(|e| errors::account("Could not delete account.", e))
|
||||
}
|
||||
|
||||
fn remove_address(&self, addr: RpcH160) -> Result<bool, Error> {
|
||||
try!(self.active());
|
||||
let store = take_weak!(self.accounts);
|
||||
let addr: Address = addr.into();
|
||||
|
||||
store.remove_address(addr)
|
||||
.expect("remove_address always returns Ok; qed");
|
||||
Ok(true)
|
||||
}
|
||||
|
||||
fn set_account_name(&self, addr: RpcH160, name: String) -> Result<bool, Error> {
|
||||
try!(self.active());
|
||||
let store = take_weak!(self.accounts);
|
||||
@@ -152,6 +162,15 @@ impl<C: 'static> ParityAccounts for ParityAccountsClient<C> where C: MiningBlock
|
||||
Ok(false)
|
||||
}
|
||||
|
||||
fn set_dapps_addresses(&self, dapp: DappId, addresses: Vec<RpcH160>) -> Result<bool, Error> {
|
||||
let store = take_weak!(self.accounts);
|
||||
let addresses = addresses.into_iter().map(Into::into).collect();
|
||||
|
||||
store.set_dapps_addresses(dapp.into(), addresses)
|
||||
.map_err(|e| errors::account("Couldn't set dapps addresses.", e))
|
||||
.map(|_| true)
|
||||
}
|
||||
|
||||
fn import_geth_accounts(&self, addresses: Vec<RpcH160>) -> Result<Vec<RpcH160>, Error> {
|
||||
let store = take_weak!(self.accounts);
|
||||
|
||||
|
||||
@@ -116,6 +116,12 @@ impl<C, M, F> ParitySet for ParitySetClient<C, M, F> where
|
||||
Ok(true)
|
||||
}
|
||||
|
||||
fn set_engine_signer(&self, address: H160, password: String) -> Result<bool, Error> {
|
||||
try!(self.active());
|
||||
try!(take_weak!(self.miner).set_engine_signer(address.into(), password).map_err(Into::into).map_err(errors::from_password_error));
|
||||
Ok(true)
|
||||
}
|
||||
|
||||
fn set_transactions_limit(&self, limit: usize) -> Result<bool, Error> {
|
||||
try!(self.active());
|
||||
|
||||
|
||||
@@ -30,7 +30,7 @@ use devtools::RandomTempPath;
|
||||
use util::Hashable;
|
||||
use io::IoChannel;
|
||||
use util::{U256, H256, Uint, Address};
|
||||
use jsonrpc_core::IoHandler;
|
||||
use jsonrpc_core::{IoHandler, GenericIoHandler};
|
||||
use ethjson::blockchain::BlockChain;
|
||||
|
||||
use v1::impls::{EthClient, SigningUnsafeClient};
|
||||
@@ -116,6 +116,7 @@ impl EthTester {
|
||||
fn from_spec(spec: Spec) -> Self {
|
||||
let dir = RandomTempPath::new();
|
||||
let account_provider = account_provider();
|
||||
spec.engine.register_account_provider(account_provider.clone());
|
||||
let miner_service = miner_service(&spec, account_provider.clone());
|
||||
let snapshot_service = snapshot_service();
|
||||
|
||||
|
||||
@@ -25,6 +25,7 @@ use ethcore::header::BlockNumber;
|
||||
use ethcore::transaction::SignedTransaction;
|
||||
use ethcore::receipt::{Receipt, RichReceipt};
|
||||
use ethcore::miner::{MinerService, MinerStatus, TransactionImportResult, LocalTransactionStatus};
|
||||
use ethcore::account_provider::Error as AccountError;
|
||||
|
||||
/// Test miner service.
|
||||
pub struct TestMinerService {
|
||||
@@ -40,6 +41,8 @@ pub struct TestMinerService {
|
||||
pub pending_receipts: Mutex<BTreeMap<H256, Receipt>>,
|
||||
/// Last nonces.
|
||||
pub last_nonces: RwLock<HashMap<Address, U256>>,
|
||||
/// Password held by Engine.
|
||||
pub password: RwLock<String>,
|
||||
|
||||
min_gas_price: RwLock<U256>,
|
||||
gas_range_target: RwLock<(U256, U256)>,
|
||||
@@ -61,6 +64,7 @@ impl Default for TestMinerService {
|
||||
min_gas_price: RwLock::new(U256::from(20_000_000)),
|
||||
gas_range_target: RwLock::new((U256::from(12345), U256::from(54321))),
|
||||
author: RwLock::new(Address::zero()),
|
||||
password: RwLock::new(String::new()),
|
||||
extra_data: RwLock::new(vec![1, 2, 3, 4]),
|
||||
limit: RwLock::new(1024),
|
||||
tx_gas_limit: RwLock::new(!U256::zero()),
|
||||
@@ -83,6 +87,12 @@ impl MinerService for TestMinerService {
|
||||
*self.author.write() = author;
|
||||
}
|
||||
|
||||
fn set_engine_signer(&self, address: Address, password: String) -> Result<(), AccountError> {
|
||||
*self.author.write() = address;
|
||||
*self.password.write() = password;
|
||||
Ok(())
|
||||
}
|
||||
|
||||
fn set_extra_data(&self, extra_data: Bytes) {
|
||||
*self.extra_data.write() = extra_data;
|
||||
}
|
||||
|
||||
@@ -23,7 +23,7 @@ use ethsync::{SyncProvider, SyncStatus, SyncState, PeerInfo, TransactionStats};
|
||||
/// TestSyncProvider config.
|
||||
pub struct Config {
|
||||
/// Protocol version.
|
||||
pub network_id: usize,
|
||||
pub network_id: u64,
|
||||
/// Number of peers.
|
||||
pub num_peers: usize,
|
||||
}
|
||||
|
||||
@@ -31,7 +31,7 @@ use ethcore::transaction::{Transaction, Action};
|
||||
use ethcore::miner::{ExternalMiner, MinerService};
|
||||
use ethsync::SyncState;
|
||||
|
||||
use jsonrpc_core::IoHandler;
|
||||
use jsonrpc_core::{IoHandler, GenericIoHandler};
|
||||
use v1::{Eth, EthClient, EthClientOptions, EthFilter, EthFilterClient, EthSigning, SigningUnsafeClient};
|
||||
use v1::tests::helpers::{TestSyncProvider, Config, TestMinerService, TestSnapshotService};
|
||||
|
||||
@@ -354,18 +354,17 @@ fn rpc_eth_gas_price() {
|
||||
#[test]
|
||||
fn rpc_eth_accounts() {
|
||||
let tester = EthTester::default();
|
||||
let address = tester.accounts_provider.new_account("").unwrap();
|
||||
let address2 = Address::default();
|
||||
|
||||
tester.accounts_provider.set_address_name(address2, "Test Account".into()).unwrap();
|
||||
let _address = tester.accounts_provider.new_account("").unwrap();
|
||||
|
||||
// even with some account it should return empty list (no dapp detected)
|
||||
let request = r#"{"jsonrpc": "2.0", "method": "eth_accounts", "params": [], "id": 1}"#;
|
||||
let response = r#"{"jsonrpc":"2.0","result":[""#.to_owned()
|
||||
+ &format!("0x{:?}", address2)
|
||||
+ r#"",""#
|
||||
+ &format!("0x{:?}", address)
|
||||
+ r#""],"id":1}"#;
|
||||
let response = r#"{"jsonrpc":"2.0","result":[],"id":1}"#;
|
||||
assert_eq!(tester.io.handle_request_sync(request), Some(response.to_owned()));
|
||||
|
||||
// when we add visible address it should return that.
|
||||
tester.accounts_provider.set_dapps_addresses("app1".into(), vec![10.into()]).unwrap();
|
||||
let request = r#"{"jsonrpc": "2.0", "method": "eth_accounts", "params": ["app1"], "id": 1}"#;
|
||||
let response = r#"{"jsonrpc":"2.0","result":["0x000000000000000000000000000000000000000a"],"id":1}"#;
|
||||
assert_eq!(tester.io.handle_request_sync(request), Some(response.to_owned()));
|
||||
}
|
||||
|
||||
@@ -495,7 +494,7 @@ fn rpc_eth_pending_transaction_by_hash() {
|
||||
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","publicKey":"0x7ae46da747962c2ee46825839c1ef9298e3bd2e70ca2938495c3693a485ec3eaa8f196327881090ff64cf4fbb0a48485d4f83098e189ed3b7a87d5941b59f789","r":"0x48b55bfa915ac795c431978d8a6a992b628d557da5ff759b307d495a36649353","raw":"0xf85f800182520894095e7baea6a6c7c4c2dfeb977efac326af552d870a801ba048b55bfa915ac795c431978d8a6a992b628d557da5ff759b307d495a36649353a0efffd310ac743f371de3b9f7f9cb56c0b28ad43601b4ab949f53faa07bd2c804","s":"0xefffd310ac743f371de3b9f7f9cb56c0b28ad43601b4ab949f53faa07bd2c804","to":"0x095e7baea6a6c7c4c2dfeb977efac326af552d87","transactionIndex":null,"v":0,"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","networkId":null,"nonce":"0x0","publicKey":"0x7ae46da747962c2ee46825839c1ef9298e3bd2e70ca2938495c3693a485ec3eaa8f196327881090ff64cf4fbb0a48485d4f83098e189ed3b7a87d5941b59f789","r":"0x48b55bfa915ac795c431978d8a6a992b628d557da5ff759b307d495a36649353","raw":"0xf85f800182520894095e7baea6a6c7c4c2dfeb977efac326af552d870a801ba048b55bfa915ac795c431978d8a6a992b628d557da5ff759b307d495a36649353a0efffd310ac743f371de3b9f7f9cb56c0b28ad43601b4ab949f53faa07bd2c804","s":"0xefffd310ac743f371de3b9f7f9cb56c0b28ad43601b4ab949f53faa07bd2c804","standardV":"0x0","to":"0x095e7baea6a6c7c4c2dfeb977efac326af552d87","transactionIndex":null,"v":"0x1b","value":"0xa"},"id":1}"#;
|
||||
let request = r#"{
|
||||
"jsonrpc": "2.0",
|
||||
"method": "eth_getTransactionByHash",
|
||||
@@ -810,13 +809,16 @@ fn rpc_eth_sign_transaction() {
|
||||
&format!("\"from\":\"0x{:?}\",", &address) +
|
||||
r#""gas":"0x76c0","gasPrice":"0x9184e72a000","# +
|
||||
&format!("\"hash\":\"0x{:?}\",", t.hash()) +
|
||||
r#""input":"0x","nonce":"0x1","# +
|
||||
r#""input":"0x","# +
|
||||
&format!("\"networkId\":{},", t.network_id().map_or("null".to_owned(), |n| format!("{}", n))) +
|
||||
r#""nonce":"0x1","# +
|
||||
&format!("\"publicKey\":\"0x{:?}\",", t.public_key().unwrap()) +
|
||||
&format!("\"r\":\"0x{}\",", signature.r().to_hex()) +
|
||||
&format!("\"r\":\"0x{}\",", U256::from(signature.r()).to_hex()) +
|
||||
&format!("\"raw\":\"0x{}\",", rlp.to_hex()) +
|
||||
&format!("\"s\":\"0x{}\",", signature.s().to_hex()) +
|
||||
&format!("\"s\":\"0x{}\",", U256::from(signature.s()).to_hex()) +
|
||||
&format!("\"standardV\":\"0x{}\",", U256::from(t.standard_v()).to_hex()) +
|
||||
r#""to":"0xd46e8dd67c5d32be8058bb8eb970870f07244567","transactionIndex":null,"# +
|
||||
&format!("\"v\":{},", signature.v()) +
|
||||
&format!("\"v\":\"0x{}\",", U256::from(t.original_v()).to_hex()) +
|
||||
r#""value":"0x9184e72a""# +
|
||||
r#"}},"id":1}"#;
|
||||
|
||||
|
||||
@@ -15,7 +15,7 @@
|
||||
// along with Parity. If not, see <http://www.gnu.org/licenses/>.
|
||||
|
||||
use std::sync::Arc;
|
||||
use jsonrpc_core::IoHandler;
|
||||
use jsonrpc_core::{IoHandler, GenericIoHandler};
|
||||
use v1::{Net, NetClient};
|
||||
use v1::tests::helpers::{Config, TestSyncProvider};
|
||||
|
||||
|
||||
@@ -23,7 +23,7 @@ use ethcore::client::{TestBlockChainClient};
|
||||
use ethcore::miner::LocalTransactionStatus;
|
||||
use ethstore::ethkey::{Generator, Random};
|
||||
|
||||
use jsonrpc_core::IoHandler;
|
||||
use jsonrpc_core::{IoHandler, GenericIoHandler};
|
||||
use v1::{Parity, ParityClient};
|
||||
use v1::helpers::{SignerService, NetworkSettings};
|
||||
use v1::tests::helpers::{TestSyncProvider, Config, TestMinerService};
|
||||
|
||||
@@ -19,7 +19,7 @@ use std::sync::Arc;
|
||||
use ethcore::account_provider::AccountProvider;
|
||||
use ethcore::client::TestBlockChainClient;
|
||||
|
||||
use jsonrpc_core::IoHandler;
|
||||
use jsonrpc_core::{IoHandler, GenericIoHandler};
|
||||
use v1::{ParityAccounts, ParityAccountsClient};
|
||||
|
||||
struct ParityAccountsTester {
|
||||
@@ -116,6 +116,21 @@ fn should_be_able_to_set_meta() {
|
||||
assert_eq!(res, Some(response));
|
||||
}
|
||||
|
||||
#[test]
|
||||
fn rpc_parity_set_dapps_accounts() {
|
||||
// given
|
||||
let tester = setup();
|
||||
assert_eq!(tester.accounts.dapps_addresses("app1".into()).unwrap(), vec![]);
|
||||
|
||||
// when
|
||||
let request = r#"{"jsonrpc": "2.0", "method": "parity_setDappsAddresses","params":["app1",["0x000000000000000000000000000000000000000a"]], "id": 1}"#;
|
||||
let response = r#"{"jsonrpc":"2.0","result":true,"id":1}"#;
|
||||
assert_eq!(tester.io.handle_request_sync(request), Some(response.to_owned()));
|
||||
|
||||
// then
|
||||
assert_eq!(tester.accounts.dapps_addresses("app1".into()).unwrap(), vec![10.into()]);
|
||||
}
|
||||
|
||||
#[test]
|
||||
fn should_be_able_to_kill_account() {
|
||||
let tester = setup();
|
||||
@@ -138,3 +153,31 @@ fn should_be_able_to_kill_account() {
|
||||
assert_eq!(accounts.len(), 0);
|
||||
}
|
||||
|
||||
#[test]
|
||||
fn should_be_able_to_remove_address() {
|
||||
let tester = setup();
|
||||
|
||||
// add an address
|
||||
let request = r#"{"jsonrpc": "2.0", "method": "parity_setAccountName", "params": ["0x000baba1000baba2000baba3000baba4000baba5", "Test"], "id": 1}"#;
|
||||
let response = r#"{"jsonrpc":"2.0","result":true,"id":1}"#;
|
||||
let res = tester.io.handle_request_sync(&request);
|
||||
assert_eq!(res, Some(response.into()));
|
||||
|
||||
// verify it exists
|
||||
let request = r#"{"jsonrpc": "2.0", "method": "parity_accountsInfo", "params": [], "id": 2}"#;
|
||||
let res = tester.io.handle_request_sync(request);
|
||||
let response = r#"{"jsonrpc":"2.0","result":{"0x000baba1000baba2000baba3000baba4000baba5":{"meta":"{}","name":"Test","uuid":null}},"id":2}"#;
|
||||
assert_eq!(res, Some(response.into()));
|
||||
|
||||
// remove the address
|
||||
let request = r#"{"jsonrpc": "2.0", "method": "parity_removeAddress", "params": ["0x000baba1000baba2000baba3000baba4000baba5"], "id": 3}"#;
|
||||
let response = r#"{"jsonrpc":"2.0","result":true,"id":3}"#;
|
||||
let res = tester.io.handle_request_sync(&request);
|
||||
assert_eq!(res, Some(response.into()));
|
||||
|
||||
// verify empty
|
||||
let request = r#"{"jsonrpc": "2.0", "method": "parity_accountsInfo", "params": [], "id": 4}"#;
|
||||
let res = tester.io.handle_request_sync(request);
|
||||
let response = r#"{"jsonrpc":"2.0","result":{},"id":4}"#;
|
||||
assert_eq!(res, Some(response.into()));
|
||||
}
|
||||
|
||||
@@ -23,7 +23,7 @@ use ethcore::miner::MinerService;
|
||||
use ethcore::client::TestBlockChainClient;
|
||||
use ethsync::ManageNetwork;
|
||||
|
||||
use jsonrpc_core::IoHandler;
|
||||
use jsonrpc_core::{IoHandler, GenericIoHandler};
|
||||
use v1::{ParitySet, ParitySetClient};
|
||||
use v1::tests::helpers::{TestMinerService, TestFetch};
|
||||
use super::manage_network::TestManageNetwork;
|
||||
@@ -106,6 +106,23 @@ fn rpc_parity_set_author() {
|
||||
assert_eq!(miner.author(), Address::from_str("cd1722f3947def4cf144679da39c4c32bdc35681").unwrap());
|
||||
}
|
||||
|
||||
#[test]
|
||||
fn rpc_parity_set_engine_signer() {
|
||||
let miner = miner_service();
|
||||
let client = client_service();
|
||||
let network = network_service();
|
||||
let io = IoHandler::new();
|
||||
io.add_delegate(parity_set_client(&client, &miner, &network).to_delegate());
|
||||
|
||||
let request = r#"{"jsonrpc": "2.0", "method": "parity_setEngineSigner", "params":["0xcd1722f3947def4cf144679da39c4c32bdc35681", "password"], "id": 1}"#;
|
||||
let response = r#"{"jsonrpc":"2.0","result":true,"id":1}"#;
|
||||
|
||||
assert_eq!(io.handle_request_sync(request), Some(response.to_owned()));
|
||||
assert_eq!(miner.author(), Address::from_str("cd1722f3947def4cf144679da39c4c32bdc35681").unwrap());
|
||||
assert_eq!(*miner.password.read(), "password".to_string());
|
||||
}
|
||||
|
||||
|
||||
#[test]
|
||||
fn rpc_parity_set_transactions_limit() {
|
||||
let miner = miner_service();
|
||||
|
||||
@@ -16,7 +16,7 @@
|
||||
|
||||
use std::sync::Arc;
|
||||
use std::str::FromStr;
|
||||
use jsonrpc_core::IoHandler;
|
||||
use jsonrpc_core::{IoHandler, GenericIoHandler};
|
||||
use util::{U256, Uint, Address};
|
||||
use ethcore::account_provider::AccountProvider;
|
||||
use v1::{PersonalClient, Personal};
|
||||
|
||||
@@ -15,7 +15,7 @@
|
||||
// along with Parity. If not, see <http://www.gnu.org/licenses/>.
|
||||
|
||||
use std::collections::BTreeMap;
|
||||
use jsonrpc_core::IoHandler;
|
||||
use jsonrpc_core::{IoHandler, GenericIoHandler};
|
||||
use v1::{Rpc, RpcClient};
|
||||
|
||||
|
||||
|
||||
@@ -23,7 +23,7 @@ use ethcore::client::TestBlockChainClient;
|
||||
use ethcore::transaction::{Transaction, Action};
|
||||
use rlp::encode;
|
||||
|
||||
use jsonrpc_core::IoHandler;
|
||||
use jsonrpc_core::{IoHandler, GenericIoHandler};
|
||||
use v1::{SignerClient, Signer};
|
||||
use v1::tests::helpers::TestMinerService;
|
||||
use v1::helpers::{SigningQueue, SignerService, FilledTransactionRequest, ConfirmationPayload};
|
||||
@@ -89,7 +89,7 @@ fn should_return_list_of_items_to_confirm() {
|
||||
let request = r#"{"jsonrpc":"2.0","method":"signer_requestsToConfirm","params":[],"id":1}"#;
|
||||
let response = concat!(
|
||||
r#"{"jsonrpc":"2.0","result":["#,
|
||||
r#"{"id":"0x1","payload":{"transaction":{"data":"0x","from":"0x0000000000000000000000000000000000000001","gas":"0x989680","gasPrice":"0x2710","nonce":null,"to":"0xd46e8dd67c5d32be8058bb8eb970870f07244567","value":"0x1"}}},"#,
|
||||
r#"{"id":"0x1","payload":{"sendTransaction":{"data":"0x","from":"0x0000000000000000000000000000000000000001","gas":"0x989680","gasPrice":"0x2710","nonce":null,"to":"0xd46e8dd67c5d32be8058bb8eb970870f07244567","value":"0x1"}}},"#,
|
||||
r#"{"id":"0x2","payload":{"sign":{"address":"0x0000000000000000000000000000000000000001","hash":"0x0000000000000000000000000000000000000000000000000000000000000005"}}}"#,
|
||||
r#"],"id":1}"#
|
||||
);
|
||||
|
||||
@@ -15,10 +15,10 @@
|
||||
// along with Parity. If not, see <http://www.gnu.org/licenses/>.
|
||||
|
||||
use std::str::FromStr;
|
||||
use std::sync::Arc;
|
||||
use std::sync::{mpsc, Arc};
|
||||
use rlp;
|
||||
|
||||
use jsonrpc_core::{IoHandler, Success};
|
||||
use jsonrpc_core::{IoHandler, Success, GenericIoHandler};
|
||||
use v1::impls::SigningQueueClient;
|
||||
use v1::traits::{EthSigning, ParitySigning, Parity};
|
||||
use v1::helpers::{SignerService, SigningQueue};
|
||||
@@ -87,13 +87,16 @@ fn should_add_sign_to_queue() {
|
||||
let response = r#"{"jsonrpc":"2.0","result":"0x0000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000","id":1}"#;
|
||||
|
||||
// then
|
||||
let async_result = tester.io.handle_request(&request).unwrap();
|
||||
let (tx, rx) = mpsc::channel();
|
||||
tester.io.handle_request(&request, move |response| {
|
||||
tx.send(response).unwrap();
|
||||
});
|
||||
assert_eq!(tester.signer.requests().len(), 1);
|
||||
// respond
|
||||
tester.signer.request_confirmed(1.into(), Ok(ConfirmationResponse::Signature(0.into())));
|
||||
assert!(async_result.on_result(move |res| {
|
||||
assert_eq!(res, response.to_owned());
|
||||
}));
|
||||
|
||||
let res = rx.try_recv().unwrap();
|
||||
assert_eq!(res, Some(response.to_owned()));
|
||||
}
|
||||
|
||||
#[test]
|
||||
@@ -227,13 +230,16 @@ fn should_add_transaction_to_queue() {
|
||||
let response = r#"{"jsonrpc":"2.0","result":"0x0000000000000000000000000000000000000000000000000000000000000000","id":1}"#;
|
||||
|
||||
// then
|
||||
let async_result = tester.io.handle_request(&request).unwrap();
|
||||
let (tx, rx) = mpsc::channel();
|
||||
tester.io.handle_request(&request, move |response| {
|
||||
tx.send(response).unwrap();
|
||||
});
|
||||
assert_eq!(tester.signer.requests().len(), 1);
|
||||
// respond
|
||||
tester.signer.request_confirmed(1.into(), Ok(ConfirmationResponse::SendTransaction(0.into())));
|
||||
assert!(async_result.on_result(move |res| {
|
||||
assert_eq!(res, response.to_owned());
|
||||
}));
|
||||
|
||||
let res = rx.try_recv().unwrap();
|
||||
assert_eq!(res, Some(response.to_owned()));
|
||||
}
|
||||
|
||||
#[test]
|
||||
@@ -278,25 +284,31 @@ fn should_add_sign_transaction_to_the_queue() {
|
||||
&format!("\"from\":\"0x{:?}\",", &address) +
|
||||
r#""gas":"0x76c0","gasPrice":"0x9184e72a000","# +
|
||||
&format!("\"hash\":\"0x{:?}\",", t.hash()) +
|
||||
r#""input":"0x","nonce":"0x1","# +
|
||||
r#""input":"0x","# +
|
||||
&format!("\"networkId\":{},", t.network_id().map_or("null".to_owned(), |n| format!("{}", n))) +
|
||||
r#""nonce":"0x1","# +
|
||||
&format!("\"publicKey\":\"0x{:?}\",", t.public_key().unwrap()) +
|
||||
&format!("\"r\":\"0x{}\",", signature.r().to_hex()) +
|
||||
&format!("\"r\":\"0x{}\",", U256::from(signature.r()).to_hex()) +
|
||||
&format!("\"raw\":\"0x{}\",", rlp.to_hex()) +
|
||||
&format!("\"s\":\"0x{}\",", signature.s().to_hex()) +
|
||||
&format!("\"s\":\"0x{}\",", U256::from(signature.s()).to_hex()) +
|
||||
&format!("\"standardV\":\"0x{}\",", U256::from(t.standard_v()).to_hex()) +
|
||||
r#""to":"0xd46e8dd67c5d32be8058bb8eb970870f07244567","transactionIndex":null,"# +
|
||||
&format!("\"v\":{},", signature.v()) +
|
||||
&format!("\"v\":\"0x{}\",", U256::from(t.original_v()).to_hex()) +
|
||||
r#""value":"0x9184e72a""# +
|
||||
r#"}},"id":1}"#;
|
||||
|
||||
// then
|
||||
let (tx, rx) = mpsc::channel();
|
||||
tester.miner.last_nonces.write().insert(address.clone(), U256::zero());
|
||||
let async_result = tester.io.handle_request(&request).unwrap();
|
||||
tester.io.handle_request(&request, move |response| {
|
||||
tx.send(response).unwrap();
|
||||
});
|
||||
assert_eq!(tester.signer.requests().len(), 1);
|
||||
// respond
|
||||
tester.signer.request_confirmed(1.into(), Ok(ConfirmationResponse::SignTransaction(t.into())));
|
||||
assert!(async_result.on_result(move |res| {
|
||||
assert_eq!(res, response.to_owned());
|
||||
}));
|
||||
|
||||
let res = rx.try_recv().unwrap();
|
||||
assert_eq!(res, Some(response.to_owned()));
|
||||
}
|
||||
|
||||
#[test]
|
||||
@@ -387,11 +399,14 @@ fn should_add_decryption_to_the_queue() {
|
||||
let response = r#"{"jsonrpc":"2.0","result":"0x0102","id":1}"#;
|
||||
|
||||
// then
|
||||
let async_result = tester.io.handle_request(&request).unwrap();
|
||||
let (tx, rx) = mpsc::channel();
|
||||
tester.io.handle_request(&request, move |response| {
|
||||
tx.send(response).unwrap();
|
||||
});
|
||||
assert_eq!(tester.signer.requests().len(), 1);
|
||||
// respond
|
||||
tester.signer.request_confirmed(1.into(), Ok(ConfirmationResponse::Decrypt(vec![0x1, 0x2].into())));
|
||||
assert!(async_result.on_result(move |res| {
|
||||
assert_eq!(res, response.to_owned());
|
||||
}));
|
||||
|
||||
let res = rx.try_recv().unwrap();
|
||||
assert_eq!(res, Some(response.to_owned()));
|
||||
}
|
||||
|
||||
@@ -14,7 +14,7 @@
|
||||
// You should have received a copy of the GNU General Public License
|
||||
// along with Parity. If not, see <http://www.gnu.org/licenses/>.
|
||||
|
||||
use jsonrpc_core::IoHandler;
|
||||
use jsonrpc_core::{IoHandler, GenericIoHandler};
|
||||
use util::version;
|
||||
use v1::{Web3, Web3Client};
|
||||
|
||||
|
||||
@@ -17,7 +17,7 @@
|
||||
//! Eth rpc interface.
|
||||
use jsonrpc_core::Error;
|
||||
|
||||
use v1::types::{RichBlock, BlockNumber, Bytes, CallRequest, Filter, FilterChanges, Index};
|
||||
use v1::types::{RichBlock, BlockNumber, Bytes, CallRequest, Filter, FilterChanges, Index, DappId};
|
||||
use v1::types::{Log, Receipt, SyncStatus, Transaction, Work};
|
||||
use v1::types::{H64, H160, H256, U256};
|
||||
|
||||
@@ -52,7 +52,7 @@ build_rpc_trait! {
|
||||
|
||||
/// Returns accounts list.
|
||||
#[rpc(name = "eth_accounts")]
|
||||
fn accounts(&self) -> Result<Vec<H160>, Error>;
|
||||
fn accounts(&self, Trailing<DappId>) -> Result<Vec<H160>, Error>;
|
||||
|
||||
/// Returns highest block number.
|
||||
#[rpc(name = "eth_blockNumber")]
|
||||
|
||||
@@ -19,7 +19,7 @@ use std::collections::BTreeMap;
|
||||
use jsonrpc_core::{Value, Error};
|
||||
|
||||
use v1::helpers::auto_args::Wrap;
|
||||
use v1::types::{H160, H256};
|
||||
use v1::types::{H160, H256, DappId};
|
||||
|
||||
build_rpc_trait! {
|
||||
/// Personal Parity rpc interface.
|
||||
@@ -58,6 +58,11 @@ build_rpc_trait! {
|
||||
#[rpc(name = "parity_killAccount")]
|
||||
fn kill_account(&self, H160, String) -> Result<bool, Error>;
|
||||
|
||||
/// Permanently deletes an address from the addressbook
|
||||
/// Arguments: `address`
|
||||
#[rpc(name = "parity_removeAddress")]
|
||||
fn remove_address(&self, H160) -> Result<bool, Error>;
|
||||
|
||||
/// Set an account's name.
|
||||
#[rpc(name = "parity_setAccountName")]
|
||||
fn set_account_name(&self, H160, String) -> Result<bool, Error>;
|
||||
@@ -66,10 +71,14 @@ build_rpc_trait! {
|
||||
#[rpc(name = "parity_setAccountMeta")]
|
||||
fn set_account_meta(&self, H160, String) -> Result<bool, Error>;
|
||||
|
||||
/// Returns accounts information.
|
||||
/// Sets account visibility
|
||||
#[rpc(name = "parity_setAccountVisiblity")]
|
||||
fn set_account_visibility(&self, H160, H256, bool) -> Result<bool, Error>;
|
||||
|
||||
/// Sets accounts exposed for particular dapp.
|
||||
#[rpc(name = "parity_setDappsAddresses")]
|
||||
fn set_dapps_addresses(&self, DappId, Vec<H160>) -> Result<bool, Error>;
|
||||
|
||||
/// Imports a number of Geth accounts, with the list provided as the argument.
|
||||
#[rpc(name = "parity_importGethAccounts")]
|
||||
fn import_geth_accounts(&self, Vec<H160>) -> Result<Vec<H160>, Error>;
|
||||
@@ -79,4 +88,3 @@ build_rpc_trait! {
|
||||
fn geth_accounts(&self) -> Result<Vec<H160>, Error>;
|
||||
}
|
||||
}
|
||||
|
||||
|
||||
@@ -44,6 +44,10 @@ build_rpc_trait! {
|
||||
#[rpc(name = "parity_setAuthor")]
|
||||
fn set_author(&self, H160) -> Result<bool, Error>;
|
||||
|
||||
/// Sets account for signing consensus messages.
|
||||
#[rpc(name = "parity_setEngineSigner")]
|
||||
fn set_engine_signer(&self, H160, String) -> Result<bool, Error>;
|
||||
|
||||
/// Sets the limits for transaction queue.
|
||||
#[rpc(name = "parity_setTransactionsLimit")]
|
||||
fn set_transactions_limit(&self, usize) -> Result<bool, Error>;
|
||||
|
||||
@@ -139,7 +139,7 @@ mod tests {
|
||||
fn test_serialize_block_transactions() {
|
||||
let t = BlockTransactions::Full(vec![Transaction::default()]);
|
||||
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","publicKey":null,"v":0,"r":"0x0000000000000000000000000000000000000000000000000000000000000000","s":"0x0000000000000000000000000000000000000000000000000000000000000000"}]"#);
|
||||
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,"networkId":null,"standardV":"0x0","v":"0x0","r":"0x0","s":"0x0"}]"#);
|
||||
|
||||
let t = BlockTransactions::Hashes(vec![H256::default().into()]);
|
||||
let serialized = serde_json::to_string(&t).unwrap();
|
||||
|
||||
@@ -114,10 +114,10 @@ pub struct ConfirmationResponseWithToken {
|
||||
#[derive(Debug, Clone, Eq, PartialEq, Hash, Serialize)]
|
||||
pub enum ConfirmationPayload {
|
||||
/// Send Transaction
|
||||
#[serde(rename="transaction")]
|
||||
#[serde(rename="sendTransaction")]
|
||||
SendTransaction(TransactionRequest),
|
||||
/// Sign Transaction
|
||||
#[serde(rename="transaction")]
|
||||
#[serde(rename="signTransaction")]
|
||||
SignTransaction(TransactionRequest),
|
||||
/// Signature
|
||||
#[serde(rename="sign")]
|
||||
@@ -230,7 +230,49 @@ mod tests {
|
||||
|
||||
// when
|
||||
let res = serde_json::to_string(&ConfirmationRequest::from(request));
|
||||
let expected = r#"{"id":"0xf","payload":{"transaction":{"from":"0x0000000000000000000000000000000000000000","to":null,"gasPrice":"0x2710","gas":"0x3a98","value":"0x186a0","data":"0x010203","nonce":"0x1"}}}"#;
|
||||
let expected = r#"{"id":"0xf","payload":{"sendTransaction":{"from":"0x0000000000000000000000000000000000000000","to":null,"gasPrice":"0x2710","gas":"0x3a98","value":"0x186a0","data":"0x010203","nonce":"0x1"}}}"#;
|
||||
|
||||
// then
|
||||
assert_eq!(res.unwrap(), expected.to_owned());
|
||||
}
|
||||
|
||||
#[test]
|
||||
fn should_serialize_sign_transaction_confirmation() {
|
||||
// given
|
||||
let request = helpers::ConfirmationRequest {
|
||||
id: 15.into(),
|
||||
payload: helpers::ConfirmationPayload::SignTransaction(helpers::FilledTransactionRequest {
|
||||
from: 0.into(),
|
||||
to: None,
|
||||
gas: 15_000.into(),
|
||||
gas_price: 10_000.into(),
|
||||
value: 100_000.into(),
|
||||
data: vec![1, 2, 3],
|
||||
nonce: Some(1.into()),
|
||||
}),
|
||||
};
|
||||
|
||||
// when
|
||||
let res = serde_json::to_string(&ConfirmationRequest::from(request));
|
||||
let expected = r#"{"id":"0xf","payload":{"signTransaction":{"from":"0x0000000000000000000000000000000000000000","to":null,"gasPrice":"0x2710","gas":"0x3a98","value":"0x186a0","data":"0x010203","nonce":"0x1"}}}"#;
|
||||
|
||||
// then
|
||||
assert_eq!(res.unwrap(), expected.to_owned());
|
||||
}
|
||||
|
||||
#[test]
|
||||
fn should_serialize_decrypt_confirmation() {
|
||||
// given
|
||||
let request = helpers::ConfirmationRequest {
|
||||
id: 15.into(),
|
||||
payload: helpers::ConfirmationPayload::Decrypt(
|
||||
10.into(), vec![1, 2, 3].into(),
|
||||
),
|
||||
};
|
||||
|
||||
// when
|
||||
let res = serde_json::to_string(&ConfirmationRequest::from(request));
|
||||
let expected = r#"{"id":"0xf","payload":{"decrypt":{"address":"0x000000000000000000000000000000000000000a","msg":"0x010203"}}}"#;
|
||||
|
||||
// then
|
||||
assert_eq!(res.unwrap(), expected.to_owned());
|
||||
|
||||
60
rpc/src/v1/types/dapp_id.rs
Normal file
60
rpc/src/v1/types/dapp_id.rs
Normal file
@@ -0,0 +1,60 @@
|
||||
// Copyright 2015, 2016 Ethcore (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/>.
|
||||
|
||||
//! Dapp Id type
|
||||
|
||||
/// Dapplication Internal Id
|
||||
#[derive(Debug, Default, Clone, Eq, PartialEq, Hash, Serialize, Deserialize)]
|
||||
pub struct DappId(pub String);
|
||||
|
||||
impl Into<String> for DappId {
|
||||
fn into(self) -> String {
|
||||
self.0
|
||||
}
|
||||
}
|
||||
|
||||
#[cfg(test)]
|
||||
mod tests {
|
||||
|
||||
use serde_json;
|
||||
use super::DappId;
|
||||
|
||||
#[test]
|
||||
fn should_serialize_dapp_id() {
|
||||
// given
|
||||
let id = DappId("testapp".into());
|
||||
|
||||
// when
|
||||
let res = serde_json::to_string(&id).unwrap();
|
||||
|
||||
// then
|
||||
assert_eq!(res, r#""testapp""#);
|
||||
}
|
||||
|
||||
#[test]
|
||||
fn should_deserialize_dapp_id() {
|
||||
// given
|
||||
let id = r#""testapp""#;
|
||||
|
||||
// when
|
||||
let res: DappId = serde_json::from_str(id).unwrap();
|
||||
|
||||
// then
|
||||
assert_eq!(res, DappId("testapp".into()));
|
||||
}
|
||||
|
||||
|
||||
}
|
||||
@@ -19,6 +19,7 @@ mod block;
|
||||
mod block_number;
|
||||
mod call_request;
|
||||
mod confirmations;
|
||||
mod dapp_id;
|
||||
mod filter;
|
||||
mod hash;
|
||||
mod index;
|
||||
@@ -39,8 +40,10 @@ pub use self::block::{RichBlock, Block, BlockTransactions};
|
||||
pub use self::block_number::BlockNumber;
|
||||
pub use self::call_request::CallRequest;
|
||||
pub use self::confirmations::{
|
||||
ConfirmationPayload, ConfirmationRequest, ConfirmationResponse, ConfirmationResponseWithToken, TransactionModification, SignRequest, DecryptRequest, Either
|
||||
ConfirmationPayload, ConfirmationRequest, ConfirmationResponse, ConfirmationResponseWithToken,
|
||||
TransactionModification, SignRequest, DecryptRequest, Either
|
||||
};
|
||||
pub use self::dapp_id::DappId;
|
||||
pub use self::filter::{Filter, FilterChanges};
|
||||
pub use self::hash::{H64, H160, H256, H512, H520, H2048};
|
||||
pub use self::index::Index;
|
||||
|
||||
@@ -57,12 +57,18 @@ pub struct Transaction {
|
||||
/// Public key of the signer.
|
||||
#[serde(rename="publicKey")]
|
||||
pub public_key: Option<H512>,
|
||||
/// The V field of the signature.
|
||||
pub v: u8,
|
||||
/// The network id of the transaction, if any.
|
||||
#[serde(rename="networkId")]
|
||||
pub network_id: Option<u64>,
|
||||
/// The standardised V field of the signature (0 or 1).
|
||||
#[serde(rename="standardV")]
|
||||
pub standard_v: U256,
|
||||
/// The standardised V field of the signature.
|
||||
pub v: U256,
|
||||
/// The R field of the signature.
|
||||
pub r: H256,
|
||||
pub r: U256,
|
||||
/// The S field of the signature.
|
||||
pub s: H256,
|
||||
pub s: U256,
|
||||
}
|
||||
|
||||
/// Local Transaction Status
|
||||
@@ -176,7 +182,9 @@ impl From<LocalizedTransaction> for Transaction {
|
||||
},
|
||||
raw: ::rlp::encode(&t.signed).to_vec().into(),
|
||||
public_key: t.public_key().ok().map(Into::into),
|
||||
v: signature.v(),
|
||||
network_id: t.network_id(),
|
||||
standard_v: t.standard_v().into(),
|
||||
v: t.original_v().into(),
|
||||
r: signature.r().into(),
|
||||
s: signature.s().into(),
|
||||
}
|
||||
@@ -207,7 +215,9 @@ impl From<SignedTransaction> for Transaction {
|
||||
},
|
||||
raw: ::rlp::encode(&t).to_vec().into(),
|
||||
public_key: t.public_key().ok().map(Into::into),
|
||||
v: signature.v(),
|
||||
network_id: t.network_id(),
|
||||
standard_v: t.standard_v().into(),
|
||||
v: t.original_v().into(),
|
||||
r: signature.r().into(),
|
||||
s: signature.s().into(),
|
||||
}
|
||||
@@ -238,7 +248,7 @@ mod tests {
|
||||
fn test_transaction_serialize() {
|
||||
let t = Transaction::default();
|
||||
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","publicKey":null,"v":0,"r":"0x0000000000000000000000000000000000000000000000000000000000000000","s":"0x0000000000000000000000000000000000000000000000000000000000000000"}"#);
|
||||
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,"networkId":null,"standardV":"0x0","v":"0x0","r":"0x0","s":"0x0"}"#);
|
||||
}
|
||||
|
||||
#[test]
|
||||
|
||||
@@ -14,9 +14,7 @@
|
||||
// You should have received a copy of the GNU General Public License
|
||||
// along with Parity. If not, see <http://www.gnu.org/licenses/>.
|
||||
|
||||
use std::cmp;
|
||||
use std::str::FromStr;
|
||||
use rustc_serialize::hex::ToHex;
|
||||
use serde;
|
||||
use util::{U256 as EthU256, U128 as EthU128, Uint};
|
||||
|
||||
@@ -50,18 +48,7 @@ macro_rules! impl_uint {
|
||||
|
||||
impl serde::Serialize for $name {
|
||||
fn serialize<S>(&self, serializer: &mut S) -> Result<(), S::Error> where S: serde::Serializer {
|
||||
let mut hex = "0x".to_owned();
|
||||
let mut bytes = [0u8; 8 * $size];
|
||||
self.0.to_big_endian(&mut bytes);
|
||||
let len = cmp::max((self.0.bits() + 7) / 8, 1);
|
||||
let bytes_hex = bytes[bytes.len() - len..].to_hex();
|
||||
|
||||
if bytes_hex.starts_with('0') {
|
||||
hex.push_str(&bytes_hex[1..]);
|
||||
} else {
|
||||
hex.push_str(&bytes_hex);
|
||||
}
|
||||
serializer.serialize_str(&hex)
|
||||
serializer.serialize_str(&format!("0x{}", self.0.to_hex()))
|
||||
}
|
||||
}
|
||||
|
||||
|
||||
Reference in New Issue
Block a user