Deprecate account management (#10213)

* Extract accounts from ethcore.

* Fix ethcore.

* Get rid of AccountProvider in test_helpers

* Fix rest of the code.

* Re-use EngineSigner, fix tests.

* Simplify EngineSigner to always have an Address.

* Fix RPC tests.

* Add deprecation notice to RPCs.

* Feature to disable accounts.

* extract accounts in RPC

* Run with accounts in tests.

* Fix RPC compilation and tests.

* Fix compilation of the binary.

* Fix compilation of the binary.

* Fix compilation with accounts enabled.

* Fix tests.

* Update submodule.

* Remove android.

* Use derive for Default

* Don't build secretstore by default.

* Add link to issue.

* Refresh Cargo.lock.

* Fix miner tests.

* Update rpc/Cargo.toml

Co-Authored-By: tomusdrw <tomusdrw@users.noreply.github.com>

* Fix private tests.
This commit is contained in:
Tomasz Drwięga
2019-02-07 14:34:24 +01:00
committed by Afri Schoedon
parent 8fa56add47
commit d5c19f8719
102 changed files with 3222 additions and 2393 deletions

View File

@@ -18,7 +18,7 @@
use std::env;
use std::sync::Arc;
use ethcore::account_provider::AccountProvider;
use accounts::AccountProvider;
use ethcore::client::{BlockChainClient, Client, ClientConfig, ChainInfo, ImportBlock};
use ethcore::ethereum;
use ethcore::miner::Miner;
@@ -36,13 +36,12 @@ use parking_lot::Mutex;
use types::ids::BlockId;
use jsonrpc_core::IoHandler;
use v1::helpers::dispatch::FullDispatcher;
use v1::helpers::dispatch::{self, FullDispatcher};
use v1::helpers::nonce;
use v1::impls::{EthClient, EthClientOptions, SigningUnsafeClient};
use v1::metadata::Metadata;
use v1::tests::helpers::{TestSnapshotService, TestSyncProvider, Config};
use v1::traits::eth::Eth;
use v1::traits::eth_signing::EthSigning;
use v1::traits::{Eth, EthSigning};
use v1::types::U256 as NU256;
fn account_provider() -> Arc<AccountProvider> {
@@ -56,8 +55,8 @@ fn sync_provider() -> Arc<TestSyncProvider> {
}))
}
fn miner_service(spec: &Spec, accounts: Arc<AccountProvider>) -> Arc<Miner> {
Arc::new(Miner::new_for_tests(spec, Some(accounts)))
fn miner_service(spec: &Spec) -> Arc<Miner> {
Arc::new(Miner::new_for_tests(spec, None))
}
fn snapshot_service() -> Arc<TestSnapshotService> {
@@ -75,11 +74,11 @@ fn make_spec(chain: &BlockChain) -> Spec {
}
struct EthTester {
_runtime: Runtime,
client: Arc<Client>,
_miner: Arc<Miner>,
_runtime: Runtime,
_snapshot: Arc<TestSnapshotService>,
accounts: Arc<AccountProvider>,
client: Arc<Client>,
handler: IoHandler<Metadata>,
}
@@ -115,11 +114,11 @@ impl EthTester {
}
fn from_spec_conf(spec: Spec, config: ClientConfig) -> Self {
let runtime = Runtime::with_thread_count(1);
let account_provider = account_provider();
let opt_account_provider = account_provider.clone();
let miner_service = miner_service(&spec, account_provider.clone());
let ap = account_provider.clone();
let accounts = Arc::new(move || ap.accounts().unwrap_or_default()) as _;
let miner_service = miner_service(&spec);
let snapshot_service = snapshot_service();
let client = Client::new(
@@ -136,7 +135,7 @@ impl EthTester {
&client,
&snapshot_service,
&sync_provider,
&opt_account_provider,
&accounts,
&miner_service,
&external_miner,
EthClientOptions {
@@ -152,8 +151,9 @@ impl EthTester {
let reservations = Arc::new(Mutex::new(nonce::Reservations::new(runtime.executor())));
let dispatcher = FullDispatcher::new(client.clone(), miner_service.clone(), reservations, 50);
let signer = Arc::new(dispatch::Signer::new(account_provider.clone())) as _;
let eth_sign = SigningUnsafeClient::new(
&opt_account_provider,
&signer,
dispatcher,
);
@@ -162,11 +162,11 @@ impl EthTester {
handler.extend_with(eth_sign.to_delegate());
EthTester {
_runtime: runtime,
_miner: miner_service,
_runtime: runtime,
_snapshot: snapshot_service,
client: client,
accounts: account_provider,
client: client,
handler: handler,
}
}

View File

@@ -20,14 +20,12 @@ use std::sync::Arc;
use std::collections::{BTreeMap, BTreeSet, HashMap};
use bytes::Bytes;
use ethcore::account_provider::SignError as AccountError;
use ethcore::block::{SealedBlock, IsBlock};
use ethcore::client::{Nonce, PrepareOpenBlock, StateClient, EngineInfo};
use ethcore::engines::EthEngine;
use ethcore::engines::{EthEngine, signer::EngineSigner};
use ethcore::error::Error;
use ethcore::miner::{self, MinerService, AuthoringParams};
use ethereum_types::{H256, U256, Address};
use ethkey::Password;
use miner::pool::local_transactions::Status as LocalTransactionStatus;
use miner::pool::{verifier, VerifiedTransaction, QueueStatus};
use parking_lot::{RwLock, Mutex};
@@ -51,8 +49,8 @@ pub struct TestMinerService {
pub pending_receipts: Mutex<Vec<RichReceipt>>,
/// Next nonces.
pub next_nonces: RwLock<HashMap<Address, U256>>,
/// Password held by Engine.
pub password: RwLock<Password>,
/// Signer (if any)
pub signer: RwLock<Option<Box<EngineSigner>>>,
authoring_params: RwLock<AuthoringParams>,
}
@@ -65,12 +63,12 @@ impl Default for TestMinerService {
local_transactions: Default::default(),
pending_receipts: Default::default(),
next_nonces: Default::default(),
password: RwLock::new("".into()),
authoring_params: RwLock::new(AuthoringParams {
author: Address::zero(),
gas_range_target: (12345.into(), 54321.into()),
extra_data: vec![1, 2, 3, 4],
}),
signer: RwLock::new(None),
}
}
}
@@ -122,12 +120,11 @@ impl MinerService for TestMinerService {
self.authoring_params.read().clone()
}
fn set_author(&self, author: Address, password: Option<Password>) -> Result<(), AccountError> {
self.authoring_params.write().author = author;
if let Some(password) = password {
*self.password.write() = password;
fn set_author(&self, author: miner::Author) {
self.authoring_params.write().author = author.address();
if let miner::Author::Sealer(signer) = author {
*self.signer.write() = Some(signer);
}
Ok(())
}
fn set_extra_data(&self, extra_data: Bytes) {

View File

@@ -19,11 +19,10 @@ use std::collections::HashMap;
use std::sync::Arc;
use std::time::{Instant, Duration, SystemTime, UNIX_EPOCH};
use ethcore::account_provider::AccountProvider;
use accounts::AccountProvider;
use ethcore::client::{BlockChainClient, BlockId, EachBlockWith, Executed, TestBlockChainClient, TransactionId};
use ethcore::miner::MinerService;
use ethcore::miner::{self, MinerService};
use ethereum_types::{H160, H256, U256, Address};
use ethkey::Secret;
use miner::external::ExternalMiner;
use parity_runtime::Runtime;
use parking_lot::Mutex;
@@ -35,9 +34,7 @@ use types::log_entry::{LocalizedLogEntry, LogEntry};
use types::receipt::{LocalizedReceipt, TransactionOutcome};
use jsonrpc_core::IoHandler;
use v1::{Eth, EthClient, EthClientOptions, EthFilter, EthFilterClient, EthSigning, SigningUnsafeClient};
use v1::helpers::nonce;
use v1::helpers::dispatch::FullDispatcher;
use v1::{Eth, EthClient, EthClientOptions, EthFilter, EthFilterClient};
use v1::tests::helpers::{TestSyncProvider, Config, TestMinerService, TestSnapshotService};
use v1::metadata::Metadata;
@@ -88,21 +85,17 @@ impl EthTester {
let client = blockchain_client();
let sync = sync_provider();
let ap = accounts_provider();
let opt_ap = ap.clone();
let ap2 = ap.clone();
let opt_ap = Arc::new(move || ap2.accounts().unwrap_or_default()) as _;
let miner = miner_service();
let snapshot = snapshot_service();
let hashrates = Arc::new(Mutex::new(HashMap::new()));
let external_miner = Arc::new(ExternalMiner::new(hashrates.clone()));
let gas_price_percentile = options.gas_price_percentile;
let eth = EthClient::new(&client, &snapshot, &sync, &opt_ap, &miner, &external_miner, options).to_delegate();
let filter = EthFilterClient::new(client.clone(), miner.clone(), 60).to_delegate();
let reservations = Arc::new(Mutex::new(nonce::Reservations::new(runtime.executor())));
let dispatcher = FullDispatcher::new(client.clone(), miner.clone(), reservations, gas_price_percentile);
let sign = SigningUnsafeClient::new(&opt_ap, dispatcher).to_delegate();
let mut io: IoHandler<Metadata> = IoHandler::default();
io.extend_with(eth);
io.extend_with(sign);
io.extend_with(filter);
EthTester {
@@ -360,28 +353,6 @@ fn rpc_eth_submit_hashrate() {
U256::from(0x500_000));
}
#[test]
fn rpc_eth_sign() {
let tester = EthTester::default();
let account = tester.accounts_provider.insert_account(Secret::from([69u8; 32]), &"abcd".into()).unwrap();
tester.accounts_provider.unlock_account_permanently(account, "abcd".into()).unwrap();
let _message = "0cc175b9c0f1b6a831c399e26977266192eb5ffee6ae2fec3ad71c777531578f".from_hex().unwrap();
let req = r#"{
"jsonrpc": "2.0",
"method": "eth_sign",
"params": [
""#.to_owned() + &format!("0x{:x}", account) + r#"",
"0x0cc175b9c0f1b6a831c399e26977266192eb5ffee6ae2fec3ad71c777531578f"
],
"id": 1
}"#;
let res = r#"{"jsonrpc":"2.0","result":"0xa2870db1d0c26ef93c7b72d2a0830fa6b841e0593f7186bc6c7cc317af8cf3a42fda03bd589a49949aa05db83300cdb553116274518dbe9d90c65d0213f4af491b","id":1}"#;
assert_eq!(tester.io.handle_request_sync(&req), Some(res.into()));
}
#[test]
fn rpc_eth_author() {
let make_res = |addr| r#"{"jsonrpc":"2.0","result":""#.to_owned() + &format!("0x{:x}", addr) + r#"","id":1}"#;
@@ -405,7 +376,7 @@ fn rpc_eth_author() {
for i in 0..20 {
let addr = tester.accounts_provider.new_account(&format!("{}", i).into()).unwrap();
tester.miner.set_author(addr.clone(), None).unwrap();
tester.miner.set_author(miner::Author::External(addr));
assert_eq!(tester.io.handle_request_sync(request), Some(make_res(addr)));
}
@@ -414,7 +385,7 @@ fn rpc_eth_author() {
#[test]
fn rpc_eth_mining() {
let tester = EthTester::default();
tester.miner.set_author(Address::from_str("d46e8dd67c5d32be8058bb8eb970870f07244567").unwrap(), None).unwrap();
tester.miner.set_author(miner::Author::External(Address::from_str("d46e8dd67c5d32be8058bb8eb970870f07244567").unwrap()));
let request = r#"{"jsonrpc": "2.0", "method": "eth_mining", "params": [], "id": 1}"#;
let response = r#"{"jsonrpc":"2.0","result":false,"id":1}"#;
@@ -824,157 +795,6 @@ fn rpc_eth_estimate_gas_default_block() {
assert_eq!(tester.io.handle_request_sync(request), Some(response.to_owned()));
}
#[test]
fn rpc_eth_send_transaction() {
let tester = EthTester::default();
let address = tester.accounts_provider.new_account(&"".into()).unwrap();
tester.accounts_provider.unlock_account_permanently(address, "".into()).unwrap();
let request = r#"{
"jsonrpc": "2.0",
"method": "eth_sendTransaction",
"params": [{
"from": ""#.to_owned() + format!("0x{:x}", address).as_ref() + r#"",
"to": "0xd46e8dd67c5d32be8058bb8eb970870f07244567",
"gas": "0x76c0",
"gasPrice": "0x9184e72a000",
"value": "0x9184e72a"
}],
"id": 1
}"#;
let t = Transaction {
nonce: U256::zero(),
gas_price: U256::from(0x9184e72a000u64),
gas: U256::from(0x76c0),
action: Action::Call(Address::from_str("d46e8dd67c5d32be8058bb8eb970870f07244567").unwrap()),
value: U256::from(0x9184e72au64),
data: vec![]
};
let signature = tester.accounts_provider.sign(address, None, t.hash(None)).unwrap();
let t = t.with_signature(signature, None);
let response = r#"{"jsonrpc":"2.0","result":""#.to_owned() + format!("0x{:x}", t.hash()).as_ref() + r#"","id":1}"#;
assert_eq!(tester.io.handle_request_sync(&request), Some(response));
tester.miner.increment_nonce(&address);
let t = Transaction {
nonce: U256::one(),
gas_price: U256::from(0x9184e72a000u64),
gas: U256::from(0x76c0),
action: Action::Call(Address::from_str("d46e8dd67c5d32be8058bb8eb970870f07244567").unwrap()),
value: U256::from(0x9184e72au64),
data: vec![]
};
let signature = tester.accounts_provider.sign(address, None, t.hash(None)).unwrap();
let t = t.with_signature(signature, None);
let response = r#"{"jsonrpc":"2.0","result":""#.to_owned() + format!("0x{:x}", t.hash()).as_ref() + r#"","id":1}"#;
assert_eq!(tester.io.handle_request_sync(&request), Some(response));
}
#[test]
fn rpc_eth_sign_transaction() {
let tester = EthTester::default();
let address = tester.accounts_provider.new_account(&"".into()).unwrap();
tester.accounts_provider.unlock_account_permanently(address, "".into()).unwrap();
let request = r#"{
"jsonrpc": "2.0",
"method": "eth_signTransaction",
"params": [{
"from": ""#.to_owned() + format!("0x{:x}", address).as_ref() + r#"",
"to": "0xd46e8dd67c5d32be8058bb8eb970870f07244567",
"gas": "0x76c0",
"gasPrice": "0x9184e72a000",
"value": "0x9184e72a"
}],
"id": 1
}"#;
let t = Transaction {
nonce: U256::one(),
gas_price: U256::from(0x9184e72a000u64),
gas: U256::from(0x76c0),
action: Action::Call(Address::from_str("d46e8dd67c5d32be8058bb8eb970870f07244567").unwrap()),
value: U256::from(0x9184e72au64),
data: vec![]
};
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":{"#.to_owned() +
r#""raw":"0x"# + &rlp.to_hex() + r#"","# +
r#""tx":{"# +
r#""blockHash":null,"blockNumber":null,"# +
&format!("\"chainId\":{},", t.chain_id().map_or("null".to_owned(), |n| format!("{}", n))) +
r#""condition":null,"creates":null,"# +
&format!("\"from\":\"0x{:x}\",", &address) +
r#""gas":"0x76c0","gasPrice":"0x9184e72a000","# +
&format!("\"hash\":\"0x{:x}\",", t.hash()) +
r#""input":"0x","# +
r#""nonce":"0x1","# +
&format!("\"publicKey\":\"0x{:x}\",", t.recover_public().unwrap()) +
&format!("\"r\":\"0x{:x}\",", U256::from(signature.r())) +
&format!("\"raw\":\"0x{}\",", rlp.to_hex()) +
&format!("\"s\":\"0x{:x}\",", U256::from(signature.s())) +
&format!("\"standardV\":\"0x{:x}\",", U256::from(t.standard_v())) +
r#""to":"0xd46e8dd67c5d32be8058bb8eb970870f07244567","transactionIndex":null,"# +
&format!("\"v\":\"0x{:x}\",", U256::from(t.original_v())) +
r#""value":"0x9184e72a""# +
r#"}},"id":1}"#;
tester.miner.increment_nonce(&address);
assert_eq!(tester.io.handle_request_sync(&request), Some(response));
}
#[test]
fn rpc_eth_send_transaction_with_bad_to() {
let tester = EthTester::default();
let address = tester.accounts_provider.new_account(&"".into()).unwrap();
let request = r#"{
"jsonrpc": "2.0",
"method": "eth_sendTransaction",
"params": [{
"from": ""#.to_owned() + format!("0x{:x}", address).as_ref() + r#"",
"to": "",
"gas": "0x76c0",
"gasPrice": "0x9184e72a000",
"value": "0x9184e72a"
}],
"id": 1
}"#;
let response = r#"{"jsonrpc":"2.0","error":{"code":-32602,"message":"Invalid params: expected a hex-encoded hash with 0x prefix."},"id":1}"#;
assert_eq!(tester.io.handle_request_sync(&request), Some(response.into()));
}
#[test]
fn rpc_eth_send_transaction_error() {
let tester = EthTester::default();
let address = tester.accounts_provider.new_account(&"".into()).unwrap();
let request = r#"{
"jsonrpc": "2.0",
"method": "eth_sendTransaction",
"params": [{
"from": ""#.to_owned() + format!("0x{:x}", address).as_ref() + r#"",
"to": "0xd46e8dd67c5d32be8058bb8eb970870f07244567",
"gas": "0x76c0",
"gasPrice": "0x9184e72a000",
"value": "0x9184e72a"
}],
"id": 1
}"#;
let response = r#"{"jsonrpc":"2.0","error":{"code":-32020,"message":"Your account is locked. Unlock the account via CLI, personal_unlockAccount or use Trusted Signer.","data":"NotUnlocked"},"id":1}"#;
assert_eq!(tester.io.handle_request_sync(&request), Some(response.into()));
}
#[test]
fn rpc_eth_send_raw_transaction_error() {
let tester = EthTester::default();
@@ -1141,7 +961,7 @@ fn rpc_get_work_returns_no_work_if_cant_mine() {
#[test]
fn rpc_get_work_returns_correct_work_package() {
let eth_tester = EthTester::default();
eth_tester.miner.set_author(Address::from_str("d46e8dd67c5d32be8058bb8eb970870f07244567").unwrap(), None).unwrap();
eth_tester.miner.set_author(miner::Author::External(Address::from_str("d46e8dd67c5d32be8058bb8eb970870f07244567").unwrap()));
let request = r#"{"jsonrpc": "2.0", "method": "eth_getWork", "params": [], "id": 1}"#;
let response = r#"{"jsonrpc":"2.0","result":["0x76c7bd86693aee93d1a80a408a09a0585b1a1292afcb56192f171d925ea18e2d","0x0000000000000000000000000000000000000000000000000000000000000000","0x0000800000000000000000000000000000000000000000000000000000000000","0x1"],"id":1}"#;
@@ -1154,7 +974,7 @@ fn rpc_get_work_should_not_return_block_number() {
let eth_tester = EthTester::new_with_options(EthClientOptions::with(|options| {
options.send_block_number_in_get_work = false;
}));
eth_tester.miner.set_author(Address::from_str("d46e8dd67c5d32be8058bb8eb970870f07244567").unwrap(), None).unwrap();
eth_tester.miner.set_author(miner::Author::External(Address::from_str("d46e8dd67c5d32be8058bb8eb970870f07244567").unwrap()));
let request = r#"{"jsonrpc": "2.0", "method": "eth_getWork", "params": [], "id": 1}"#;
let response = r#"{"jsonrpc":"2.0","result":["0x76c7bd86693aee93d1a80a408a09a0585b1a1292afcb56192f171d925ea18e2d","0x0000000000000000000000000000000000000000000000000000000000000000","0x0000800000000000000000000000000000000000000000000000000000000000"],"id":1}"#;
@@ -1165,7 +985,7 @@ fn rpc_get_work_should_not_return_block_number() {
#[test]
fn rpc_get_work_should_timeout() {
let eth_tester = EthTester::default();
eth_tester.miner.set_author(Address::from_str("d46e8dd67c5d32be8058bb8eb970870f07244567").unwrap(), None).unwrap();
eth_tester.miner.set_author(miner::Author::External(Address::from_str("d46e8dd67c5d32be8058bb8eb970870f07244567").unwrap()));
let timestamp = SystemTime::now().duration_since(UNIX_EPOCH).unwrap().as_secs() - 1000; // Set latest block to 1000 seconds ago
eth_tester.client.set_latest_block_timestamp(timestamp);
let hash = eth_tester.miner.work_package(&*eth_tester.client).unwrap().0;

View File

@@ -23,13 +23,19 @@ mod eth_pubsub;
mod manage_network;
mod net;
mod parity;
#[cfg(any(test, feature = "accounts"))]
mod parity_accounts;
mod parity_set;
#[cfg(any(test, feature = "accounts"))]
mod personal;
mod pubsub;
mod rpc;
#[cfg(any(test, feature = "accounts"))]
mod secretstore;
mod signer;
#[cfg(any(test, feature = "accounts"))]
mod signing;
#[cfg(any(test, feature = "accounts"))]
mod signing_unsafe;
mod traces;
mod web3;

View File

@@ -15,7 +15,6 @@
// along with Parity Ethereum. If not, see <http://www.gnu.org/licenses/>.
use std::sync::Arc;
use ethcore::account_provider::AccountProvider;
use ethcore::client::{TestBlockChainClient, Executed, TransactionId};
use ethcore_logger::RotatingLogger;
use ethereum_types::{Address, U256, H256};
@@ -27,7 +26,8 @@ use types::receipt::{LocalizedReceipt, TransactionOutcome};
use jsonrpc_core::IoHandler;
use v1::{Parity, ParityClient};
use v1::metadata::Metadata;
use v1::helpers::{SignerService, NetworkSettings};
use v1::helpers::NetworkSettings;
use v1::helpers::external_signer::SignerService;
use v1::tests::helpers::{TestSyncProvider, Config, TestMinerService, TestUpdater};
use super::manage_network::TestManageNetwork;
use Host;
@@ -42,7 +42,6 @@ pub struct Dependencies {
pub logger: Arc<RotatingLogger>,
pub settings: Arc<NetworkSettings>,
pub network: Arc<ManageNetwork>,
pub accounts: Arc<AccountProvider>,
pub ws_address: Option<Host>,
}
@@ -67,7 +66,6 @@ impl Dependencies {
rpc_port: 8545,
}),
network: Arc::new(TestManageNetwork),
accounts: Arc::new(AccountProvider::transient_provider()),
ws_address: Some("127.0.0.1:18546".into()),
}
}
@@ -79,7 +77,6 @@ impl Dependencies {
self.sync.clone(),
self.updater.clone(),
self.network.clone(),
self.accounts.clone(),
self.logger.clone(),
self.settings.clone(),
signer,
@@ -101,47 +98,6 @@ impl Dependencies {
}
}
#[test]
fn rpc_parity_accounts_info() {
let deps = Dependencies::new();
let io = deps.default_client();
deps.accounts.new_account(&"".into()).unwrap();
let accounts = deps.accounts.accounts().unwrap();
assert_eq!(accounts.len(), 1);
let address = accounts[0];
deps.accounts.set_address_name(1.into(), "XX".into());
deps.accounts.set_account_name(address.clone(), "Test".into()).unwrap();
deps.accounts.set_account_meta(address.clone(), "{foo: 69}".into()).unwrap();
let request = r#"{"jsonrpc": "2.0", "method": "parity_accountsInfo", "params": [], "id": 1}"#;
let response = format!("{{\"jsonrpc\":\"2.0\",\"result\":{{\"0x{:x}\":{{\"name\":\"Test\"}}}},\"id\":1}}", address);
assert_eq!(io.handle_request_sync(request), Some(response));
}
#[test]
fn rpc_parity_default_account() {
let deps = Dependencies::new();
let io = deps.default_client();
// Check empty
let address = Address::default();
let request = r#"{"jsonrpc": "2.0", "method": "parity_defaultAccount", "params": [], "id": 1}"#;
let response = format!("{{\"jsonrpc\":\"2.0\",\"result\":\"0x{:x}\",\"id\":1}}", address);
assert_eq!(io.handle_request_sync(request), Some(response));
// With account
deps.accounts.new_account(&"".into()).unwrap();
let accounts = deps.accounts.accounts().unwrap();
assert_eq!(accounts.len(), 1);
let address = accounts[0];
let request = r#"{"jsonrpc": "2.0", "method": "parity_defaultAccount", "params": [], "id": 1}"#;
let response = format!("{{\"jsonrpc\":\"2.0\",\"result\":\"0x{:x}\",\"id\":1}}", address);
assert_eq!(io.handle_request_sync(request), Some(response));
}
#[test]
fn rpc_parity_consensus_capability() {
let deps = Dependencies::new();

View File

@@ -16,13 +16,14 @@
use std::sync::Arc;
use ethcore::account_provider::{AccountProvider, AccountProviderSettings};
use accounts::{AccountProvider, AccountProviderSettings};
use ethereum_types::Address;
use ethstore::EthStore;
use ethstore::accounts_dir::RootDiskDirectory;
use tempdir::TempDir;
use jsonrpc_core::IoHandler;
use v1::{ParityAccounts, ParityAccountsClient};
use v1::{ParityAccounts, ParityAccountsInfo, ParityAccountsClient};
struct ParityAccountsTester {
accounts: Arc<AccountProvider>,
@@ -42,8 +43,10 @@ fn accounts_provider_with_vaults_support(temp_path: &str) -> Arc<AccountProvider
fn setup_with_accounts_provider(accounts_provider: Arc<AccountProvider>) -> ParityAccountsTester {
let opt_ap = accounts_provider.clone();
let parity_accounts = ParityAccountsClient::new(&opt_ap);
let parity_accounts2 = ParityAccountsClient::new(&opt_ap);
let mut io = IoHandler::default();
io.extend_with(parity_accounts.to_delegate());
io.extend_with(ParityAccounts::to_delegate(parity_accounts));
io.extend_with(ParityAccountsInfo::to_delegate(parity_accounts2));
let tester = ParityAccountsTester {
accounts: accounts_provider,
@@ -61,6 +64,47 @@ fn setup_with_vaults_support(temp_path: &str) -> ParityAccountsTester {
setup_with_accounts_provider(accounts_provider_with_vaults_support(temp_path))
}
#[test]
fn rpc_parity_accounts_info() {
let tester = setup();
let io = tester.io;
tester.accounts.new_account(&"".into()).unwrap();
let accounts = tester.accounts.accounts().unwrap();
assert_eq!(accounts.len(), 1);
let address = accounts[0];
tester.accounts.set_address_name(1.into(), "XX".into());
tester.accounts.set_account_name(address.clone(), "Test".into()).unwrap();
tester.accounts.set_account_meta(address.clone(), "{foo: 69}".into()).unwrap();
let request = r#"{"jsonrpc": "2.0", "method": "parity_accountsInfo", "params": [], "id": 1}"#;
let response = format!("{{\"jsonrpc\":\"2.0\",\"result\":{{\"0x{:x}\":{{\"name\":\"Test\"}}}},\"id\":1}}", address);
assert_eq!(io.handle_request_sync(request), Some(response));
}
#[test]
fn rpc_parity_default_account() {
let tester = setup();
let io = tester.io;
// Check empty
let address = Address::default();
let request = r#"{"jsonrpc": "2.0", "method": "parity_defaultAccount", "params": [], "id": 1}"#;
let response = format!("{{\"jsonrpc\":\"2.0\",\"result\":\"0x{:x}\",\"id\":1}}", address);
assert_eq!(io.handle_request_sync(request), Some(response));
// With account
tester.accounts.new_account(&"".into()).unwrap();
let accounts = tester.accounts.accounts().unwrap();
assert_eq!(accounts.len(), 1);
let address = accounts[0];
let request = r#"{"jsonrpc": "2.0", "method": "parity_defaultAccount", "params": [], "id": 1}"#;
let response = format!("{{\"jsonrpc\":\"2.0\",\"result\":\"0x{:x}\",\"id\":1}}", address);
assert_eq!(io.handle_request_sync(request), Some(response));
}
#[test]
fn should_be_able_to_get_account_info() {
let tester = setup();

View File

@@ -54,7 +54,13 @@ fn parity_set_client(
updater: &Arc<TestUpdater>,
net: &Arc<TestManageNetwork>,
) -> TestParitySetClient {
ParitySetClient::new(client, miner, updater, &(net.clone() as Arc<ManageNetwork>), FakeFetch::new(Some(1)))
ParitySetClient::new(
client,
miner,
updater,
&(net.clone() as Arc<ManageNetwork>),
FakeFetch::new(Some(1)),
)
}
#[test]
@@ -161,23 +167,6 @@ fn rpc_parity_set_author() {
assert_eq!(miner.authoring_params().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 updater = updater_service();
let mut io = IoHandler::new();
io.extend_with(parity_set_client(&client, &miner, &updater, &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.authoring_params().author, Address::from_str("cd1722f3947def4cf144679da39c4c32bdc35681").unwrap());
assert_eq!(*miner.password.read(), "password".into());
}
#[test]
fn rpc_parity_set_transactions_limit() {
let miner = miner_service();
@@ -236,3 +225,29 @@ fn rpc_parity_remove_transaction() {
miner.pending_transactions.lock().insert(hash, signed);
assert_eq!(io.handle_request_sync(&request), Some(response.to_owned()));
}
#[test]
fn rpc_parity_set_engine_signer() {
use accounts::AccountProvider;
use bytes::ToPretty;
use v1::impls::ParitySetAccountsClient;
use v1::traits::ParitySetAccounts;
let account_provider = Arc::new(AccountProvider::transient_provider());
account_provider.insert_account(::hash::keccak("cow").into(), &"password".into()).unwrap();
let miner = miner_service();
let mut io = IoHandler::new();
io.extend_with(
ParitySetAccountsClient::new(&account_provider, &miner).to_delegate()
);
let request = r#"{"jsonrpc": "2.0", "method": "parity_setEngineSigner", "params":["0xcd2a3d9f938e13cd947ec05abc7fe734df8dd826", "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.authoring_params().author, Address::from_str("cd2a3d9f938e13cd947ec05abc7fe734df8dd826").unwrap());
let signature = miner.signer.read().as_ref().unwrap().sign(::hash::keccak("x")).unwrap().to_vec();
assert_eq!(&format!("{}", signature.pretty()), "6f46069ded2154af6e806706e4f7f6fd310ac45f3c6dccb85f11c0059ee20a09245df0a0008bb84a10882b1298284bc93058e7bc5938ea728e77620061687a6401");
}

View File

@@ -19,7 +19,7 @@ use std::str::FromStr;
use bytes::ToPretty;
use ethereum_types::{U256, Address};
use ethcore::account_provider::AccountProvider;
use accounts::AccountProvider;
use ethcore::client::TestBlockChainClient;
use jsonrpc_core::IoHandler;
use parking_lot::Mutex;

View File

@@ -17,7 +17,7 @@
use std::sync::Arc;
use crypto::DEFAULT_MAC;
use ethcore::account_provider::AccountProvider;
use accounts::AccountProvider;
use ethkey::{KeyPair, Signature, verify_public};
use serde_json;

View File

@@ -19,7 +19,7 @@ use std::str::FromStr;
use ethereum_types::{U256, Address};
use bytes::ToPretty;
use ethcore::account_provider::AccountProvider;
use accounts::AccountProvider;
use ethcore::client::TestBlockChainClient;
use parity_runtime::Runtime;
use parking_lot::Mutex;
@@ -32,8 +32,9 @@ use v1::{SignerClient, Signer, Origin};
use v1::metadata::Metadata;
use v1::tests::helpers::TestMinerService;
use v1::types::{Bytes as RpcBytes, H520};
use v1::helpers::{nonce, SigningQueue, SignerService, FilledTransactionRequest, ConfirmationPayload};
use v1::helpers::dispatch::{FullDispatcher, eth_data_hash};
use v1::helpers::{nonce, FilledTransactionRequest, ConfirmationPayload};
use v1::helpers::external_signer::{SigningQueue, SignerService};
use v1::helpers::dispatch::{self, FullDispatcher, eth_data_hash};
struct SignerTester {
_runtime: Runtime,
@@ -60,13 +61,14 @@ fn signer_tester() -> SignerTester {
let runtime = Runtime::with_thread_count(1);
let signer = Arc::new(SignerService::new_test(false));
let accounts = accounts_provider();
let account_signer = Arc::new(dispatch::Signer::new(accounts.clone()));
let client = blockchain_client();
let miner = miner_service();
let reservations = Arc::new(Mutex::new(nonce::Reservations::new(runtime.executor())));
let dispatcher = FullDispatcher::new(client, miner.clone(), reservations, 50);
let mut io = IoHandler::default();
io.extend_with(SignerClient::new(&accounts, dispatcher, &signer, runtime.executor()).to_delegate());
io.extend_with(SignerClient::new(account_signer, dispatcher, &signer, runtime.executor()).to_delegate());
SignerTester {
_runtime: runtime,
@@ -555,29 +557,3 @@ fn should_generate_new_token() {
// then
assert_eq!(tester.io.handle_request_sync(&request), Some(response.to_owned()));
}
#[test]
fn should_generate_new_web_proxy_token() {
use jsonrpc_core::{Response, Output, Value};
// given
let tester = signer_tester();
// when
let request = r#"{
"jsonrpc":"2.0",
"method":"signer_generateWebProxyAccessToken",
"params":["https://parity.io"],
"id":1
}"#;
let response = tester.io.handle_request_sync(&request).unwrap();
let result = serde_json::from_str(&response).unwrap();
if let Response::Single(Output::Success(ref success)) = result {
if let Value::String(ref token) = success.result {
assert_eq!(tester.signer.web_proxy_access_token_domain(&token), Some("https://parity.io".into()));
return;
}
}
assert!(false, "Expected successful response, got: {:?}", result);
}

View File

@@ -25,14 +25,15 @@ use jsonrpc_core::futures::Future;
use v1::impls::SigningQueueClient;
use v1::metadata::Metadata;
use v1::traits::{EthSigning, ParitySigning, Parity};
use v1::helpers::{nonce, SignerService, SigningQueue, FullDispatcher};
use v1::helpers::{nonce, dispatch, FullDispatcher};
use v1::helpers::external_signer::{SignerService, SigningQueue};
use v1::types::{ConfirmationResponse, RichRawTransaction};
use v1::tests::helpers::TestMinerService;
use v1::tests::mocked::parity;
use ethereum_types::{U256, Address};
use accounts::AccountProvider;
use bytes::ToPretty;
use ethcore::account_provider::AccountProvider;
use ethereum_types::{U256, Address};
use ethcore::client::TestBlockChainClient;
use ethkey::Secret;
use ethstore::ethkey::{Generator, Random};
@@ -57,6 +58,7 @@ impl Default for SigningTester {
let client = Arc::new(TestBlockChainClient::default());
let miner = Arc::new(TestMinerService::default());
let accounts = Arc::new(AccountProvider::transient_provider());
let account_signer = Arc::new(dispatch::Signer::new(accounts.clone())) as _;
let reservations = Arc::new(Mutex::new(nonce::Reservations::new(runtime.executor())));
let mut io = IoHandler::default();
@@ -64,9 +66,9 @@ impl Default for SigningTester {
let executor = Executor::new_thread_per_future();
let rpc = SigningQueueClient::new(&signer, dispatcher.clone(), executor.clone(), &accounts);
let rpc = SigningQueueClient::new(&signer, dispatcher.clone(), executor.clone(), &account_signer);
io.extend_with(EthSigning::to_delegate(rpc));
let rpc = SigningQueueClient::new(&signer, dispatcher, executor, &accounts);
let rpc = SigningQueueClient::new(&signer, dispatcher, executor, &account_signer);
io.extend_with(ParitySigning::to_delegate(rpc));
SigningTester {
@@ -84,6 +86,30 @@ fn eth_signing() -> SigningTester {
SigningTester::default()
}
#[test]
fn rpc_eth_sign() {
use rustc_hex::FromHex;
let tester = eth_signing();
let account = tester.accounts.insert_account(Secret::from([69u8; 32]), &"abcd".into()).unwrap();
tester.accounts.unlock_account_permanently(account, "abcd".into()).unwrap();
let _message = "0cc175b9c0f1b6a831c399e26977266192eb5ffee6ae2fec3ad71c777531578f".from_hex().unwrap();
let req = r#"{
"jsonrpc": "2.0",
"method": "eth_sign",
"params": [
""#.to_owned() + &format!("0x{:x}", account) + r#"",
"0x0cc175b9c0f1b6a831c399e26977266192eb5ffee6ae2fec3ad71c777531578f"
],
"id": 1
}"#;
let res = r#"{"jsonrpc":"2.0","result":"0xa2870db1d0c26ef93c7b72d2a0830fa6b841e0593f7186bc6c7cc317af8cf3a42fda03bd589a49949aa05db83300cdb553116274518dbe9d90c65d0213f4af491b","id":1}"#;
assert_eq!(tester.io.handle_request_sync(&req), Some(res.into()));
}
#[test]
fn should_add_sign_to_queue() {
// given

View File

@@ -0,0 +1,237 @@
// Copyright 2015-2018 Parity Technologies (UK) Ltd.
// This file is part of Parity.
// Parity is free software: you can redistribute it and/or modify
// it under the terms of the GNU General Public License as published by
// the Free Software Foundation, either version 3 of the License, or
// (at your option) any later version.
// Parity is distributed in the hope that it will be useful,
// but WITHOUT ANY WARRANTY; without even the implied warranty of
// MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the
// GNU General Public License for more details.
// You should have received a copy of the GNU General Public License
// along with Parity. If not, see <http://www.gnu.org/licenses/>.
use std::str::FromStr;
use std::sync::Arc;
use accounts::AccountProvider;
use ethcore::client::TestBlockChainClient;
use ethereum_types::{U256, Address};
use parity_runtime::Runtime;
use parking_lot::Mutex;
use rlp;
use rustc_hex::ToHex;
use types::transaction::{Transaction, Action};
use jsonrpc_core::IoHandler;
use v1::{EthClientOptions, EthSigning, SigningUnsafeClient};
use v1::helpers::nonce;
use v1::helpers::dispatch::{self, FullDispatcher};
use v1::tests::helpers::{TestMinerService};
use v1::metadata::Metadata;
fn blockchain_client() -> Arc<TestBlockChainClient> {
let client = TestBlockChainClient::new();
Arc::new(client)
}
fn accounts_provider() -> Arc<AccountProvider> {
Arc::new(AccountProvider::transient_provider())
}
fn miner_service() -> Arc<TestMinerService> {
Arc::new(TestMinerService::default())
}
struct EthTester {
pub runtime: Runtime,
pub client: Arc<TestBlockChainClient>,
pub accounts_provider: Arc<AccountProvider>,
pub miner: Arc<TestMinerService>,
pub io: IoHandler<Metadata>,
}
impl Default for EthTester {
fn default() -> Self {
Self::new_with_options(Default::default())
}
}
impl EthTester {
pub fn new_with_options(options: EthClientOptions) -> Self {
let runtime = Runtime::with_thread_count(1);
let client = blockchain_client();
let accounts_provider = accounts_provider();
let ap = Arc::new(dispatch::Signer::new(accounts_provider.clone())) as _;
let miner = miner_service();
let gas_price_percentile = options.gas_price_percentile;
let reservations = Arc::new(Mutex::new(nonce::Reservations::new(runtime.executor())));
let dispatcher = FullDispatcher::new(client.clone(), miner.clone(), reservations, gas_price_percentile);
let sign = SigningUnsafeClient::new(&ap, dispatcher).to_delegate();
let mut io: IoHandler<Metadata> = IoHandler::default();
io.extend_with(sign);
EthTester {
runtime,
client,
miner,
io,
accounts_provider,
}
}
}
#[test]
fn rpc_eth_send_transaction() {
let tester = EthTester::default();
let address = tester.accounts_provider.new_account(&"".into()).unwrap();
tester.accounts_provider.unlock_account_permanently(address, "".into()).unwrap();
let request = r#"{
"jsonrpc": "2.0",
"method": "eth_sendTransaction",
"params": [{
"from": ""#.to_owned() + format!("0x{:x}", address).as_ref() + r#"",
"to": "0xd46e8dd67c5d32be8058bb8eb970870f07244567",
"gas": "0x76c0",
"gasPrice": "0x9184e72a000",
"value": "0x9184e72a"
}],
"id": 1
}"#;
let t = Transaction {
nonce: U256::zero(),
gas_price: U256::from(0x9184e72a000u64),
gas: U256::from(0x76c0),
action: Action::Call(Address::from_str("d46e8dd67c5d32be8058bb8eb970870f07244567").unwrap()),
value: U256::from(0x9184e72au64),
data: vec![]
};
let signature = tester.accounts_provider.sign(address, None, t.hash(None)).unwrap();
let t = t.with_signature(signature, None);
let response = r#"{"jsonrpc":"2.0","result":""#.to_owned() + format!("0x{:x}", t.hash()).as_ref() + r#"","id":1}"#;
assert_eq!(tester.io.handle_request_sync(&request), Some(response));
tester.miner.increment_nonce(&address);
let t = Transaction {
nonce: U256::one(),
gas_price: U256::from(0x9184e72a000u64),
gas: U256::from(0x76c0),
action: Action::Call(Address::from_str("d46e8dd67c5d32be8058bb8eb970870f07244567").unwrap()),
value: U256::from(0x9184e72au64),
data: vec![]
};
let signature = tester.accounts_provider.sign(address, None, t.hash(None)).unwrap();
let t = t.with_signature(signature, None);
let response = r#"{"jsonrpc":"2.0","result":""#.to_owned() + format!("0x{:x}", t.hash()).as_ref() + r#"","id":1}"#;
assert_eq!(tester.io.handle_request_sync(&request), Some(response));
}
#[test]
fn rpc_eth_sign_transaction() {
let tester = EthTester::default();
let address = tester.accounts_provider.new_account(&"".into()).unwrap();
tester.accounts_provider.unlock_account_permanently(address, "".into()).unwrap();
let request = r#"{
"jsonrpc": "2.0",
"method": "eth_signTransaction",
"params": [{
"from": ""#.to_owned() + format!("0x{:x}", address).as_ref() + r#"",
"to": "0xd46e8dd67c5d32be8058bb8eb970870f07244567",
"gas": "0x76c0",
"gasPrice": "0x9184e72a000",
"value": "0x9184e72a"
}],
"id": 1
}"#;
let t = Transaction {
nonce: U256::one(),
gas_price: U256::from(0x9184e72a000u64),
gas: U256::from(0x76c0),
action: Action::Call(Address::from_str("d46e8dd67c5d32be8058bb8eb970870f07244567").unwrap()),
value: U256::from(0x9184e72au64),
data: vec![]
};
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":{"#.to_owned() +
r#""raw":"0x"# + &rlp.to_hex() + r#"","# +
r#""tx":{"# +
r#""blockHash":null,"blockNumber":null,"# +
&format!("\"chainId\":{},", t.chain_id().map_or("null".to_owned(), |n| format!("{}", n))) +
r#""condition":null,"creates":null,"# +
&format!("\"from\":\"0x{:x}\",", &address) +
r#""gas":"0x76c0","gasPrice":"0x9184e72a000","# +
&format!("\"hash\":\"0x{:x}\",", t.hash()) +
r#""input":"0x","# +
r#""nonce":"0x1","# +
&format!("\"publicKey\":\"0x{:x}\",", t.recover_public().unwrap()) +
&format!("\"r\":\"0x{:x}\",", U256::from(signature.r())) +
&format!("\"raw\":\"0x{}\",", rlp.to_hex()) +
&format!("\"s\":\"0x{:x}\",", U256::from(signature.s())) +
&format!("\"standardV\":\"0x{:x}\",", U256::from(t.standard_v())) +
r#""to":"0xd46e8dd67c5d32be8058bb8eb970870f07244567","transactionIndex":null,"# +
&format!("\"v\":\"0x{:x}\",", U256::from(t.original_v())) +
r#""value":"0x9184e72a""# +
r#"}},"id":1}"#;
tester.miner.increment_nonce(&address);
assert_eq!(tester.io.handle_request_sync(&request), Some(response));
}
#[test]
fn rpc_eth_send_transaction_with_bad_to() {
let tester = EthTester::default();
let address = tester.accounts_provider.new_account(&"".into()).unwrap();
let request = r#"{
"jsonrpc": "2.0",
"method": "eth_sendTransaction",
"params": [{
"from": ""#.to_owned() + format!("0x{:x}", address).as_ref() + r#"",
"to": "",
"gas": "0x76c0",
"gasPrice": "0x9184e72a000",
"value": "0x9184e72a"
}],
"id": 1
}"#;
let response = r#"{"jsonrpc":"2.0","error":{"code":-32602,"message":"Invalid params: expected a hex-encoded hash with 0x prefix."},"id":1}"#;
assert_eq!(tester.io.handle_request_sync(&request), Some(response.into()));
}
#[test]
fn rpc_eth_send_transaction_error() {
let tester = EthTester::default();
let address = tester.accounts_provider.new_account(&"".into()).unwrap();
let request = r#"{
"jsonrpc": "2.0",
"method": "eth_sendTransaction",
"params": [{
"from": ""#.to_owned() + format!("0x{:x}", address).as_ref() + r#"",
"to": "0xd46e8dd67c5d32be8058bb8eb970870f07244567",
"gas": "0x76c0",
"gasPrice": "0x9184e72a000",
"value": "0x9184e72a"
}],
"id": 1
}"#;
let response = r#"{"jsonrpc":"2.0","error":{"code":-32020,"message":"Your account is locked. Unlock the account via CLI, personal_unlockAccount or use Trusted Signer.","data":"NotUnlocked"},"id":1}"#;
assert_eq!(tester.io.handle_request_sync(&request), Some(response.into()));
}