diff --git a/Cargo.lock b/Cargo.lock
index 2b3859c0a..8379e101e 100644
--- a/Cargo.lock
+++ b/Cargo.lock
@@ -920,7 +920,7 @@ dependencies = [
[[package]]
name = "parity-dapps-wallet"
version = "0.5.0"
-source = "git+https://github.com/ethcore/parity-dapps-wallet-rs.git#37b1691d74ad9bdabc64f58684d9d0a6d1aeef66"
+source = "git+https://github.com/ethcore/parity-dapps-wallet-rs.git#25402ce0a02ae49eb66c9e3852b392267a027ea3"
dependencies = [
"parity-dapps 0.3.0 (git+https://github.com/ethcore/parity-dapps-rs.git)",
]
diff --git a/ethcore/res/ethereum/morden.json b/ethcore/res/ethereum/morden.json
index 1d1dec0b7..1e385558d 100644
--- a/ethcore/res/ethereum/morden.json
+++ b/ethcore/res/ethereum/morden.json
@@ -34,7 +34,17 @@
"gasLimit": "0x2fefd8"
},
"nodes": [
- "enode://b1217cbaa440e35ed471157123fe468e19e8b5ad5bedb4b1fdbcbdab6fb2f5ed3e95dd9c24a22a79fdb2352204cea207df27d92bfd21bfd41545e8b16f637499@104.44.138.37:30303"
+ "enode://b1217cbaa440e35ed471157123fe468e19e8b5ad5bedb4b1fdbcbdab6fb2f5ed3e95dd9c24a22a79fdb2352204cea207df27d92bfd21bfd41545e8b16f637499@104.44.138.37:30303",
+ "enode://7ee7195bfac561ec938a72cd84cd1a5d2b334415263feddc325b20b5010446fc6c361297d13decab4039028fa659c1e27cca1396574b87cc7b29eea2985e97fe@108.61.197.28:30303",
+ "enode://933c5d5470b77537e7d9c1ee686132b5032dd3e2a096d2f64d2004df4ce9fca4ad6da5e358edcc8f81e65f047e40045600181f5fb35066e771025f6cca8e7952@46.101.114.191:30303",
+ "enode://ad4028ba28783d5bf58f512cb4e24a8ce980d768177c4974e1140b16b925132c947349db9ca3646752891b382dafc839a0c0716c3764c1ed9d424f09d13d01cf@148.251.220.116:30303",
+ "enode://c54ddaacddc7029683c80edae91015520eb2712176fbe6fdb7a5a074659270638f1266cba1731681c7cb785bceb02ca8d8b23024e3ec736fc5579f2042be97ae@54.175.255.230:30303",
+ "enode://ceb5c0f85eb994dbe9693bf46d99b03f6b838d17cc74e68d5eb003171ff39e5f120b17f965b267c319303f94d80b9d994b77062fb1486d76ce95d9f3d8fe1cb4@46.101.122.141:30303",
+ "enode://e731347db0521f3476e6bbbb83375dcd7133a1601425ebd15fd10f3835fd4c304fba6282087ca5a0deeafadf0aa0d4fd56c3323331901c1f38bd181c283e3e35@128.199.55.137:30303",
+ "enode://e941c58fed2709d792f552f408d2162c3d0a5597d22d1da617a9c9e6181f3251056a96adb45ae22eba70119355227298dc7e6dff805b092bae7da2f8564de422@85.25.217.23:30303",
+ "enode://f4b73c9d11a780293ff0ca7afa12c67797afdc33a4797a7c2ecc5b87e455b32a8b9e9804f2004072bac38350bf82d52521d1a09590d2079705fc8357aef2bf9c@71.202.223.50:56603",
+ "enode://1173eea53e0cb2b8da92423e44cf4cbafbc8ea16c1558cf06e18dfc5a2fc9b140cc802a4362b4c773fb1442541e6f2a225b200bb4c1f6b347e7510a50fa4873f@104.41.138.167:30300",
+ "enode://1aad341327808738ad34655611f1b13293c4155dde36c8e3788128829f15cc6db2da9435f29520553d4efc134aadc50115690194ac3af519aac7a388b524811e@109.188.125.2:30303"
],
"accounts": {
"0000000000000000000000000000000000000001": { "balance": "1", "nonce": "1048576", "builtin": { "name": "ecrecover", "pricing": { "linear": { "base": 3000, "word": 0 } } } },
diff --git a/parity/migration.rs b/parity/migration.rs
index 76bf494ab..d41c502cc 100644
--- a/parity/migration.rs
+++ b/parity/migration.rs
@@ -14,13 +14,13 @@
// You should have received a copy of the GNU General Public License
// along with Parity. If not, see .
-use std::{fs, env};
+use std::fs;
use std::fs::File;
use std::io::{Read, Write, Error as IoError, ErrorKind};
use std::path::PathBuf;
use std::fmt::{Display, Formatter, Error as FmtError};
use util::migration::{Manager as MigrationManager, Config as MigrationConfig, MigrationIterator};
-use util::kvdb::Database;
+use util::kvdb::{Database, DatabaseConfig};
use ethcore::migrations;
/// Database is assumed to be at default version, when no version file is found.
@@ -109,10 +109,19 @@ fn extras_database_path(path: &PathBuf) -> PathBuf {
}
/// Temporary database path used for migration.
-fn temp_database_path() -> PathBuf {
- let mut dir = env::temp_dir();
- dir.push("parity_migration");
- dir
+fn temp_database_path(path: &PathBuf) -> PathBuf {
+ let mut temp_path = path.clone();
+ temp_path.pop();
+ temp_path.push("temp_migration");
+ temp_path
+}
+
+/// Database backup
+fn backup_database_path(path: &PathBuf) -> PathBuf {
+ let mut backup_path = path.clone();
+ backup_path.pop();
+ backup_path.push("temp_backup");
+ backup_path
}
/// Default migration settings.
@@ -144,26 +153,40 @@ fn migrate_database(version: u32, path: PathBuf, migrations: MigrationManager) -
println!("Migrating database {} from version {} to {}", path.to_string_lossy(), version, CURRENT_VERSION);
- // get temp path
- let temp_path = temp_database_path();
+ let temp_path = temp_database_path(&path);
+ let backup_path = backup_database_path(&path);
// remote the dir if it exists
let _ = fs::remove_dir_all(&temp_path);
+ let _ = fs::remove_dir_all(&backup_path);
{
+ let db_config = DatabaseConfig {
+ prefix_size: None,
+ max_open_files: 64,
+ };
+
// open old database
- let old = try!(Database::open_default(path.to_str().unwrap()).map_err(|_| Error::MigrationFailed));
+ let old = try!(Database::open(&db_config, path.to_str().unwrap()).map_err(|_| Error::MigrationFailed));
// create new database
- let mut temp = try!(Database::open_default(temp_path.to_str().unwrap()).map_err(|_| Error::MigrationFailed));
+ let mut temp = try!(Database::open(&db_config, temp_path.to_str().unwrap()).map_err(|_| Error::MigrationFailed));
// migrate old database to the new one
try!(migrations.execute(MigrationIterator::from(old.iter()), version, &mut temp).map_err(|_| Error::MigrationFailed));
}
- // replace the old database with the new one
- try!(fs::remove_dir_all(&path));
- try!(fs::rename(&temp_path, &path));
+ // create backup
+ try!(fs::rename(&path, &backup_path));
+ // replace the old database with the new one
+ if let Err(err) = fs::rename(&temp_path, &path) {
+ // if something went wrong, bring back backup
+ try!(fs::rename(&backup_path, path));
+ return Err(From::from(err));
+ }
+
+ // remove backup
+ try!(fs::remove_dir_all(&backup_path));
println!("Migration finished");
Ok(())
diff --git a/rpc/src/v1/tests/eth.rs b/rpc/src/v1/tests/eth.rs
index d52fc9f4c..e69de29bb 100644
--- a/rpc/src/v1/tests/eth.rs
+++ b/rpc/src/v1/tests/eth.rs
@@ -1,724 +0,0 @@
-// 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 .
-
-use std::str::FromStr;
-use std::collections::HashMap;
-use std::sync::{Arc, RwLock};
-use jsonrpc_core::IoHandler;
-use util::hash::{Address, H256, FixedHash};
-use util::numbers::{Uint, U256};
-use util::keys::{TestAccount, TestAccountProvider};
-use ethcore::client::{TestBlockChainClient, EachBlockWith, Executed, TransactionID};
-use ethcore::log_entry::{LocalizedLogEntry, LogEntry};
-use ethcore::receipt::LocalizedReceipt;
-use ethcore::transaction::{Transaction, Action};
-use ethminer::ExternalMiner;
-use v1::{Eth, EthClient};
-use v1::tests::helpers::{TestSyncProvider, Config, TestMinerService};
-
-fn blockchain_client() -> Arc {
- let client = TestBlockChainClient::new();
- Arc::new(client)
-}
-
-fn accounts_provider() -> Arc {
- let mut accounts = HashMap::new();
- accounts.insert(Address::from(1), TestAccount::new("test"));
- let ap = TestAccountProvider::new(accounts);
- Arc::new(ap)
-}
-
-fn sync_provider() -> Arc {
- Arc::new(TestSyncProvider::new(Config {
- network_id: U256::from(3),
- num_peers: 120,
- }))
-}
-
-fn miner_service() -> Arc {
- Arc::new(TestMinerService::default())
-}
-
-struct EthTester {
- pub client: Arc,
- pub sync: Arc,
- pub accounts_provider: Arc,
- miner: Arc,
- hashrates: Arc>>,
- pub io: IoHandler,
-}
-
-impl Default for EthTester {
- fn default() -> Self {
- let client = blockchain_client();
- let sync = sync_provider();
- let ap = accounts_provider();
- let miner = miner_service();
- let hashrates = Arc::new(RwLock::new(HashMap::new()));
- let external_miner = Arc::new(ExternalMiner::new(hashrates.clone()));
- let eth = EthClient::new(&client, &sync, &ap, &miner, &external_miner).to_delegate();
- let io = IoHandler::new();
- io.add_delegate(eth);
- EthTester {
- client: client,
- sync: sync,
- accounts_provider: ap,
- miner: miner,
- io: io,
- hashrates: hashrates,
- }
- }
-}
-
-#[test]
-fn rpc_eth_protocol_version() {
- let request = r#"{"jsonrpc": "2.0", "method": "eth_protocolVersion", "params": [], "id": 1}"#;
- let response = r#"{"jsonrpc":"2.0","result":"63","id":1}"#;
-
- assert_eq!(EthTester::default().io.handle_request(request), Some(response.to_owned()));
-}
-
-#[test]
-#[ignore]
-fn rpc_eth_syncing() {
- unimplemented!()
-}
-
-#[test]
-fn rpc_eth_hashrate() {
- let tester = EthTester::default();
- tester.hashrates.write().unwrap().insert(H256::from(0), U256::from(0xfffa));
- tester.hashrates.write().unwrap().insert(H256::from(0), U256::from(0xfffb));
- tester.hashrates.write().unwrap().insert(H256::from(1), U256::from(0x1));
-
- let request = r#"{"jsonrpc": "2.0", "method": "eth_hashrate", "params": [], "id": 1}"#;
- let response = r#"{"jsonrpc":"2.0","result":"0xfffc","id":1}"#;
-
- assert_eq!(tester.io.handle_request(request), Some(response.to_owned()));
-}
-
-#[test]
-fn rpc_eth_submit_hashrate() {
- let tester = EthTester::default();
-
- let request = r#"{
- "jsonrpc": "2.0",
- "method": "eth_submitHashrate",
- "params": [
- "0x0000000000000000000000000000000000000000000000000000000000500000",
- "0x59daa26581d0acd1fce254fb7e85952f4c09d0915afd33d3886cd914bc7d283c"],
- "id": 1
- }"#;
- let response = r#"{"jsonrpc":"2.0","result":true,"id":1}"#;
-
- assert_eq!(tester.io.handle_request(request), Some(response.to_owned()));
- assert_eq!(tester.hashrates.read().unwrap().get(&H256::from("0x59daa26581d0acd1fce254fb7e85952f4c09d0915afd33d3886cd914bc7d283c")).cloned(),
- Some(U256::from(0x500_000)));
-}
-
-#[test]
-#[ignore]
-fn rpc_eth_author() {
- unimplemented!()
-}
-
-#[test]
-fn rpc_eth_mining() {
- let tester = EthTester::default();
-
- let request = r#"{"jsonrpc": "2.0", "method": "eth_mining", "params": [], "id": 1}"#;
- let response = r#"{"jsonrpc":"2.0","result":false,"id":1}"#;
- assert_eq!(tester.io.handle_request(request), Some(response.to_owned()));
-
- tester.hashrates.write().unwrap().insert(H256::from(1), U256::from(0x1));
-
- let request = r#"{"jsonrpc": "2.0", "method": "eth_mining", "params": [], "id": 1}"#;
- let response = r#"{"jsonrpc":"2.0","result":true,"id":1}"#;
- assert_eq!(tester.io.handle_request(request), Some(response.to_owned()));
-}
-
-#[test]
-fn rpc_eth_gas_price() {
- let request = r#"{"jsonrpc": "2.0", "method": "eth_gasPrice", "params": [], "id": 1}"#;
- let response = r#"{"jsonrpc":"2.0","result":"0x04a817c800","id":1}"#;
-
- assert_eq!(EthTester::default().io.handle_request(request), Some(response.to_owned()));
-}
-
-#[test]
-fn rpc_eth_accounts() {
- let request = r#"{"jsonrpc": "2.0", "method": "eth_accounts", "params": [], "id": 1}"#;
- let response = r#"{"jsonrpc":"2.0","result":["0x0000000000000000000000000000000000000001"],"id":1}"#;
-
- assert_eq!(EthTester::default().io.handle_request(request), Some(response.to_owned()));
-}
-
-#[test]
-fn rpc_eth_block_number() {
- let tester = EthTester::default();
- tester.client.add_blocks(10, EachBlockWith::Nothing);
-
- let request = r#"{"jsonrpc": "2.0", "method": "eth_blockNumber", "params": [], "id": 1}"#;
- let response = r#"{"jsonrpc":"2.0","result":"0x0a","id":1}"#;
-
- assert_eq!(tester.io.handle_request(request), Some(response.to_owned()));
-}
-
-#[test]
-fn rpc_eth_balance() {
- let tester = EthTester::default();
- tester.client.set_balance(Address::from(1), U256::from(5));
-
- let request = r#"{
- "jsonrpc": "2.0",
- "method": "eth_getBalance",
- "params": ["0x0000000000000000000000000000000000000001", "latest"],
- "id": 1
- }"#;
- let response = r#"{"jsonrpc":"2.0","result":"0x05","id":1}"#;
-
- assert_eq!(tester.io.handle_request(request), Some(response.to_owned()));
-}
-
-#[ignore] //TODO: propert test
-#[test]
-fn rpc_eth_balance_pending() {
- let tester = EthTester::default();
-
- let request = r#"{
- "jsonrpc": "2.0",
- "method": "eth_getBalance",
- "params": ["0x0000000000000000000000000000000000000001", "latest"],
- "id": 1
- }"#;
- let response = r#"{"jsonrpc":"2.0","result":"0x","id":1}"#;
-
- assert_eq!(tester.io.handle_request(request), Some(response.to_owned()));
-}
-
-#[test]
-fn rpc_eth_storage_at() {
- let tester = EthTester::default();
- tester.client.set_storage(Address::from(1), H256::from(4), H256::from(7));
-
- let request = r#"{
- "jsonrpc": "2.0",
- "method": "eth_getStorageAt",
- "params": ["0x0000000000000000000000000000000000000001", "0x4", "latest"],
- "id": 1
- }"#;
- let response = r#"{"jsonrpc":"2.0","result":"0x07","id":1}"#;
-
- assert_eq!(tester.io.handle_request(request), Some(response.to_owned()));
-}
-
-#[test]
-fn rpc_eth_transaction_count() {
- let request = r#"{
- "jsonrpc": "2.0",
- "method": "eth_getTransactionCount",
- "params": ["0x0000000000000000000000000000000000000001", "latest"],
- "id": 1
- }"#;
- let response = r#"{"jsonrpc":"2.0","result":"0x00","id":1}"#;
-
- assert_eq!(EthTester::default().io.handle_request(request), Some(response.to_owned()));
-}
-
-#[test]
-fn rpc_eth_block_transaction_count_by_hash() {
- let request = r#"{
- "jsonrpc": "2.0",
- "method": "eth_getBlockTransactionCountByHash",
- "params": ["0xb903239f8543d04b5dc1ba6579132b143087c68db1b2168786408fcbce568238"],
- "id": 1
- }"#;
- let response = r#"{"jsonrpc":"2.0","result":null,"id":1}"#;
-
- assert_eq!(EthTester::default().io.handle_request(request), Some(response.to_owned()));
-}
-
-#[test]
-fn rpc_eth_transaction_count_by_number() {
- let request = r#"{
- "jsonrpc": "2.0",
- "method": "eth_getBlockTransactionCountByNumber",
- "params": ["latest"],
- "id": 1
- }"#;
- let response = r#"{"jsonrpc":"2.0","result":"0x00","id":1}"#;
-
- assert_eq!(EthTester::default().io.handle_request(request), Some(response.to_owned()));
-}
-
-#[test]
-fn rpc_eth_transaction_count_by_number_pending() {
- let request = r#"{
- "jsonrpc": "2.0",
- "method": "eth_getBlockTransactionCountByNumber",
- "params": ["pending"],
- "id": 1
- }"#;
- let response = r#"{"jsonrpc":"2.0","result":"0x01","id":1}"#;
-
- assert_eq!(EthTester::default().io.handle_request(request), Some(response.to_owned()));
-}
-
-#[test]
-fn rpc_eth_pending_transaction_by_hash() {
- use util::*;
- use ethcore::transaction::*;
-
- let tester = EthTester::default();
- {
- let tx: SignedTransaction = decode(&FromHex::from_hex("f85f800182520894095e7baea6a6c7c4c2dfeb977efac326af552d870a801ba048b55bfa915ac795c431978d8a6a992b628d557da5ff759b307d495a36649353a0efffd310ac743f371de3b9f7f9cb56c0b28ad43601b4ab949f53faa07bd2c804").unwrap());
- tester.miner.pending_transactions.lock().unwrap().insert(H256::zero(), tx);
- }
-
- let response = r#"{"jsonrpc":"2.0","result":{"blockHash":null,"blockNumber":null,"from":"0x0f65fe9276bc9a24ae7083ae28e2660ef72df99e","gas":"0x5208","gasPrice":"0x01","hash":"0x41df922fd0d4766fcc02e161f8295ec28522f329ae487f14d811e4b64c8d6e31","input":"0x","nonce":"0x00","to":"0x095e7baea6a6c7c4c2dfeb977efac326af552d87","transactionIndex":null,"value":"0x0a"},"id":1}"#;
- let request = r#"{
- "jsonrpc": "2.0",
- "method": "eth_getTransactionByHash",
- "params": ["0x0000000000000000000000000000000000000000000000000000000000000000"],
- "id": 1
- }"#;
- assert_eq!(tester.io.handle_request(request), Some(response.to_owned()));
-}
-
-
-#[test]
-fn rpc_eth_uncle_count_by_block_hash() {
- let request = r#"{
- "jsonrpc": "2.0",
- "method": "eth_getUncleCountByBlockHash",
- "params": ["0xb903239f8543d04b5dc1ba6579132b143087c68db1b2168786408fcbce568238"],
- "id": 1
- }"#;
- let response = r#"{"jsonrpc":"2.0","result":null,"id":1}"#;
-
- assert_eq!(EthTester::default().io.handle_request(request), Some(response.to_owned()));
-}
-
-#[test]
-fn rpc_eth_uncle_count_by_block_number() {
- let request = r#"{
- "jsonrpc": "2.0",
- "method": "eth_getUncleCountByBlockNumber",
- "params": ["latest"],
- "id": 1
- }"#;
- let response = r#"{"jsonrpc":"2.0","result":"0x00","id":1}"#;
-
- assert_eq!(EthTester::default().io.handle_request(request), Some(response.to_owned()));
-}
-
-#[test]
-fn rpc_eth_code() {
- let tester = EthTester::default();
- tester.client.set_code(Address::from(1), vec![0xff, 0x21]);
-
- let request = r#"{
- "jsonrpc": "2.0",
- "method": "eth_getCode",
- "params": ["0x0000000000000000000000000000000000000001", "latest"],
- "id": 1
- }"#;
- let response = r#"{"jsonrpc":"2.0","result":"0xff21","id":1}"#;
-
- assert_eq!(tester.io.handle_request(request), Some(response.to_owned()));
-}
-
-#[test]
-fn rpc_eth_call() {
- let tester = EthTester::default();
- tester.client.set_execution_result(Executed {
- gas: U256::zero(),
- gas_used: U256::from(0xff30),
- refunded: U256::from(0x5),
- cumulative_gas_used: U256::zero(),
- logs: vec![],
- contracts_created: vec![],
- output: vec![0x12, 0x34, 0xff],
- trace: None,
- });
-
- let request = r#"{
- "jsonrpc": "2.0",
- "method": "eth_call",
- "params": [{
- "from": "0xb60e8dd61c5d32be8058bb8eb970870f07233155",
- "to": "0xd46e8dd67c5d32be8058bb8eb970870f07244567",
- "gas": "0x76c0",
- "gasPrice": "0x9184e72a000",
- "value": "0x9184e72a",
- "data": "0xd46e8dd67c5d32be8d46e8dd67c5d32be8058bb8eb970870f072445675058bb8eb970870f072445675"
- },
- "latest"],
- "id": 1
- }"#;
- let response = r#"{"jsonrpc":"2.0","result":"0x1234ff","id":1}"#;
-
- assert_eq!(tester.io.handle_request(request), Some(response.to_owned()));
-}
-
-#[test]
-fn rpc_eth_call_default_block() {
- let tester = EthTester::default();
- tester.client.set_execution_result(Executed {
- gas: U256::zero(),
- gas_used: U256::from(0xff30),
- refunded: U256::from(0x5),
- cumulative_gas_used: U256::zero(),
- logs: vec![],
- contracts_created: vec![],
- output: vec![0x12, 0x34, 0xff],
- trace: None,
- });
-
- let request = r#"{
- "jsonrpc": "2.0",
- "method": "eth_call",
- "params": [{
- "from": "0xb60e8dd61c5d32be8058bb8eb970870f07233155",
- "to": "0xd46e8dd67c5d32be8058bb8eb970870f07244567",
- "gas": "0x76c0",
- "gasPrice": "0x9184e72a000",
- "value": "0x9184e72a",
- "data": "0xd46e8dd67c5d32be8d46e8dd67c5d32be8058bb8eb970870f072445675058bb8eb970870f072445675"
- }],
- "id": 1
- }"#;
- let response = r#"{"jsonrpc":"2.0","result":"0x1234ff","id":1}"#;
-
- assert_eq!(tester.io.handle_request(request), Some(response.to_owned()));
-}
-
-#[test]
-fn rpc_eth_estimate_gas() {
- let tester = EthTester::default();
- tester.client.set_execution_result(Executed {
- gas: U256::zero(),
- gas_used: U256::from(0xff30),
- refunded: U256::from(0x5),
- cumulative_gas_used: U256::zero(),
- logs: vec![],
- contracts_created: vec![],
- output: vec![0x12, 0x34, 0xff],
- trace: None,
- });
-
- let request = r#"{
- "jsonrpc": "2.0",
- "method": "eth_estimateGas",
- "params": [{
- "from": "0xb60e8dd61c5d32be8058bb8eb970870f07233155",
- "to": "0xd46e8dd67c5d32be8058bb8eb970870f07244567",
- "gas": "0x76c0",
- "gasPrice": "0x9184e72a000",
- "value": "0x9184e72a",
- "data": "0xd46e8dd67c5d32be8d46e8dd67c5d32be8058bb8eb970870f072445675058bb8eb970870f072445675"
- },
- "latest"],
- "id": 1
- }"#;
- let response = r#"{"jsonrpc":"2.0","result":"0xff35","id":1}"#;
-
- assert_eq!(tester.io.handle_request(request), Some(response.to_owned()));
-}
-
-#[test]
-fn rpc_eth_estimate_gas_default_block() {
- let tester = EthTester::default();
- tester.client.set_execution_result(Executed {
- gas: U256::zero(),
- gas_used: U256::from(0xff30),
- refunded: U256::from(0x5),
- cumulative_gas_used: U256::zero(),
- logs: vec![],
- contracts_created: vec![],
- output: vec![0x12, 0x34, 0xff],
- trace: None,
- });
-
- let request = r#"{
- "jsonrpc": "2.0",
- "method": "eth_estimateGas",
- "params": [{
- "from": "0xb60e8dd61c5d32be8058bb8eb970870f07233155",
- "to": "0xd46e8dd67c5d32be8058bb8eb970870f07244567",
- "gas": "0x76c0",
- "gasPrice": "0x9184e72a000",
- "value": "0x9184e72a",
- "data": "0xd46e8dd67c5d32be8d46e8dd67c5d32be8058bb8eb970870f072445675058bb8eb970870f072445675"
- }],
- "id": 1
- }"#;
- let response = r#"{"jsonrpc":"2.0","result":"0xff35","id":1}"#;
-
- assert_eq!(tester.io.handle_request(request), Some(response.to_owned()));
-}
-
-#[test]
-fn rpc_eth_send_transaction() {
- let account = TestAccount::new("123");
- let address = account.address();
- let secret = account.secret.clone();
-
- let tester = EthTester::default();
- tester.accounts_provider.accounts.write().unwrap().insert(address.clone(), account);
- let request = r#"{
- "jsonrpc": "2.0",
- "method": "eth_sendTransaction",
- "params": [{
- "from": ""#.to_owned() + format!("0x{:?}", 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![]
- }.sign(&secret);
-
- let response = r#"{"jsonrpc":"2.0","result":""#.to_owned() + format!("0x{:?}", t.hash()).as_ref() + r#"","id":1}"#;
-
- assert_eq!(tester.io.handle_request(request.as_ref()), Some(response));
-
- tester.miner.last_nonces.write().unwrap().insert(address.clone(), U256::zero());
-
- 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![]
- }.sign(&secret);
-
- let response = r#"{"jsonrpc":"2.0","result":""#.to_owned() + format!("0x{:?}", t.hash()).as_ref() + r#"","id":1}"#;
-
- assert_eq!(tester.io.handle_request(request.as_ref()), Some(response));
-}
-
-#[test]
-fn rpc_eth_sign_and_send_transaction_with_invalid_password() {
- let account = TestAccount::new("password123");
- let address = account.address();
-
- let tester = EthTester::default();
- tester.accounts_provider.accounts.write().unwrap().insert(address.clone(), account);
- let request = r#"{
- "jsonrpc": "2.0",
- "method": "eth_signAndSendTransaction",
- "params": [{
- "from": ""#.to_owned() + format!("0x{:?}", address).as_ref() + r#"",
- "to": "0xd46e8dd67c5d32be8058bb8eb970870f07244567",
- "gas": "0x76c0",
- "gasPrice": "0x9184e72a000",
- "value": "0x9184e72a"
- }, "password321"],
- "id": 1
- }"#;
-
- let response = r#"{"jsonrpc":"2.0","result":"0x0000000000000000000000000000000000000000000000000000000000000000","id":1}"#;
-
- assert_eq!(tester.io.handle_request(request.as_ref()), Some(response.into()));
-}
-
-#[test]
-fn rpc_eth_sign_and_send_transaction() {
- let account = TestAccount::new("password123");
- let address = account.address();
- let secret = account.secret.clone();
-
- let tester = EthTester::default();
- tester.accounts_provider.accounts.write().unwrap().insert(address.clone(), account);
- let request = r#"{
- "jsonrpc": "2.0",
- "method": "eth_signAndSendTransaction",
- "params": [{
- "from": ""#.to_owned() + format!("0x{:?}", address).as_ref() + r#"",
- "to": "0xd46e8dd67c5d32be8058bb8eb970870f07244567",
- "gas": "0x76c0",
- "gasPrice": "0x9184e72a000",
- "value": "0x9184e72a"
- }, "password123"],
- "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![]
- }.sign(&secret);
-
- let response = r#"{"jsonrpc":"2.0","result":""#.to_owned() + format!("0x{:?}", t.hash()).as_ref() + r#"","id":1}"#;
-
- assert_eq!(tester.io.handle_request(request.as_ref()), Some(response));
-
- tester.miner.last_nonces.write().unwrap().insert(address.clone(), U256::zero());
-
- 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![]
- }.sign(&secret);
-
- let response = r#"{"jsonrpc":"2.0","result":""#.to_owned() + format!("0x{:?}", t.hash()).as_ref() + r#"","id":1}"#;
-
- assert_eq!(tester.io.handle_request(request.as_ref()), Some(response));
-}
-
-#[test]
-#[ignore]
-fn rpc_eth_send_raw_transaction() {
- unimplemented!()
-}
-
-#[test]
-#[ignore]
-fn rpc_eth_sign() {
- unimplemented!()
-}
-
-#[test]
-fn rpc_eth_transaction_receipt() {
- let receipt = LocalizedReceipt {
- transaction_hash: H256::zero(),
- transaction_index: 0,
- block_hash: H256::from_str("ed76641c68a1c641aee09a94b3b471f4dc0316efe5ac19cf488e2674cf8d05b5").unwrap(),
- block_number: 0x4510c,
- cumulative_gas_used: U256::from(0x20),
- gas_used: U256::from(0x10),
- contract_address: None,
- logs: vec![LocalizedLogEntry {
- entry: LogEntry {
- address: Address::from_str("33990122638b9132ca29c723bdf037f1a891a70c").unwrap(),
- topics: vec![
- H256::from_str("a6697e974e6a320f454390be03f74955e8978f1a6971ea6730542e37b66179bc").unwrap(),
- H256::from_str("4861736852656700000000000000000000000000000000000000000000000000").unwrap()
- ],
- data: vec![],
- },
- block_hash: H256::from_str("ed76641c68a1c641aee09a94b3b471f4dc0316efe5ac19cf488e2674cf8d05b5").unwrap(),
- block_number: 0x4510c,
- transaction_hash: H256::new(),
- transaction_index: 0,
- log_index: 1,
- }]
- };
-
- let hash = H256::from_str("b903239f8543d04b5dc1ba6579132b143087c68db1b2168786408fcbce568238").unwrap();
- let tester = EthTester::default();
- tester.client.set_transaction_receipt(TransactionID::Hash(hash), receipt);
-
- let request = r#"{
- "jsonrpc": "2.0",
- "method": "eth_getTransactionReceipt",
- "params": ["0xb903239f8543d04b5dc1ba6579132b143087c68db1b2168786408fcbce568238"],
- "id": 1
- }"#;
- let response = r#"{"jsonrpc":"2.0","result":{"blockHash":"0xed76641c68a1c641aee09a94b3b471f4dc0316efe5ac19cf488e2674cf8d05b5","blockNumber":"0x04510c","contractAddress":null,"cumulativeGasUsed":"0x20","gasUsed":"0x10","logs":[{"address":"0x33990122638b9132ca29c723bdf037f1a891a70c","blockHash":"0xed76641c68a1c641aee09a94b3b471f4dc0316efe5ac19cf488e2674cf8d05b5","blockNumber":"0x04510c","data":"0x","logIndex":"0x01","topics":["0xa6697e974e6a320f454390be03f74955e8978f1a6971ea6730542e37b66179bc","0x4861736852656700000000000000000000000000000000000000000000000000"],"transactionHash":"0x0000000000000000000000000000000000000000000000000000000000000000","transactionIndex":"0x00","type":"mined"}],"transactionHash":"0x0000000000000000000000000000000000000000000000000000000000000000","transactionIndex":"0x00"},"id":1}"#;
-
- assert_eq!(tester.io.handle_request(request), Some(response.to_owned()));
-}
-
-#[test]
-fn rpc_eth_transaction_receipt_null() {
- let tester = EthTester::default();
-
- let request = r#"{
- "jsonrpc": "2.0",
- "method": "eth_getTransactionReceipt",
- "params": ["0xb903239f8543d04b5dc1ba6579132b143087c68db1b2168786408fcbce568238"],
- "id": 1
- }"#;
- let response = r#"{"jsonrpc":"2.0","result":null,"id":1}"#;
-
- assert_eq!(tester.io.handle_request(request), Some(response.to_owned()));
-}
-
-#[test]
-fn rpc_eth_compilers() {
- let request = r#"{"jsonrpc": "2.0", "method": "eth_getCompilers", "params": [], "id": 1}"#;
- let response = r#"{"jsonrpc":"2.0","result":[],"id":1}"#;
-
- assert_eq!(EthTester::default().io.handle_request(request), Some(response.to_owned()));
-}
-
-#[test]
-fn rpc_eth_compile_lll() {
- let request = r#"{"jsonrpc": "2.0", "method": "eth_compileLLL", "params": [], "id": 1}"#;
- let response = r#"{"jsonrpc":"2.0","error":{"code":-32603,"message":"Internal error","data":null},"id":1}"#;
-
- assert_eq!(EthTester::default().io.handle_request(request), Some(response.to_owned()));
-}
-
-#[test]
-fn rpc_eth_compile_solidity() {
- let request = r#"{"jsonrpc": "2.0", "method": "eth_compileSolidity", "params": [], "id": 1}"#;
- let response = r#"{"jsonrpc":"2.0","error":{"code":-32603,"message":"Internal error","data":null},"id":1}"#;
-
- assert_eq!(EthTester::default().io.handle_request(request), Some(response.to_owned()));
-}
-
-#[test]
-fn rpc_eth_compile_serpent() {
- let request = r#"{"jsonrpc": "2.0", "method": "eth_compileSerpent", "params": [], "id": 1}"#;
- let response = r#"{"jsonrpc":"2.0","error":{"code":-32603,"message":"Internal error","data":null},"id":1}"#;
-
- assert_eq!(EthTester::default().io.handle_request(request), Some(response.to_owned()));
-}
-
-#[test]
-fn returns_no_work_if_cant_mine() {
- let eth_tester = EthTester::default();
- eth_tester.client.set_queue_size(10);
-
- let request = r#"{"jsonrpc": "2.0", "method": "eth_getWork", "params": [], "id": 1}"#;
- let response = r#"{"jsonrpc":"2.0","result":["","",""],"id":1}"#;
-
- assert_eq!(eth_tester.io.handle_request(request), Some(response.to_owned()));
-}
-
-#[ignore]
-// enable once TestMinerService supports the mining API.
-#[test]
-fn returns_error_if_can_mine_and_no_closed_block() {
- use ethsync::{SyncState};
-
- let eth_tester = EthTester::default();
- eth_tester.sync.status.write().unwrap().state = SyncState::Idle;
-
- let request = r#"{"jsonrpc": "2.0", "method": "eth_getWork", "params": [], "id": 1}"#;
- let response = r#"{"jsonrpc":"2.0","error":{"code":-32603,"message":"Internal error","data":null},"id":1}"#;
-
- assert_eq!(eth_tester.io.handle_request(request), Some(response.to_owned()));
-}
diff --git a/rpc/src/v1/tests/mocked/eth.rs b/rpc/src/v1/tests/mocked/eth.rs
new file mode 100644
index 000000000..d52fc9f4c
--- /dev/null
+++ b/rpc/src/v1/tests/mocked/eth.rs
@@ -0,0 +1,724 @@
+// 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 .
+
+use std::str::FromStr;
+use std::collections::HashMap;
+use std::sync::{Arc, RwLock};
+use jsonrpc_core::IoHandler;
+use util::hash::{Address, H256, FixedHash};
+use util::numbers::{Uint, U256};
+use util::keys::{TestAccount, TestAccountProvider};
+use ethcore::client::{TestBlockChainClient, EachBlockWith, Executed, TransactionID};
+use ethcore::log_entry::{LocalizedLogEntry, LogEntry};
+use ethcore::receipt::LocalizedReceipt;
+use ethcore::transaction::{Transaction, Action};
+use ethminer::ExternalMiner;
+use v1::{Eth, EthClient};
+use v1::tests::helpers::{TestSyncProvider, Config, TestMinerService};
+
+fn blockchain_client() -> Arc {
+ let client = TestBlockChainClient::new();
+ Arc::new(client)
+}
+
+fn accounts_provider() -> Arc {
+ let mut accounts = HashMap::new();
+ accounts.insert(Address::from(1), TestAccount::new("test"));
+ let ap = TestAccountProvider::new(accounts);
+ Arc::new(ap)
+}
+
+fn sync_provider() -> Arc {
+ Arc::new(TestSyncProvider::new(Config {
+ network_id: U256::from(3),
+ num_peers: 120,
+ }))
+}
+
+fn miner_service() -> Arc {
+ Arc::new(TestMinerService::default())
+}
+
+struct EthTester {
+ pub client: Arc,
+ pub sync: Arc,
+ pub accounts_provider: Arc,
+ miner: Arc,
+ hashrates: Arc>>,
+ pub io: IoHandler,
+}
+
+impl Default for EthTester {
+ fn default() -> Self {
+ let client = blockchain_client();
+ let sync = sync_provider();
+ let ap = accounts_provider();
+ let miner = miner_service();
+ let hashrates = Arc::new(RwLock::new(HashMap::new()));
+ let external_miner = Arc::new(ExternalMiner::new(hashrates.clone()));
+ let eth = EthClient::new(&client, &sync, &ap, &miner, &external_miner).to_delegate();
+ let io = IoHandler::new();
+ io.add_delegate(eth);
+ EthTester {
+ client: client,
+ sync: sync,
+ accounts_provider: ap,
+ miner: miner,
+ io: io,
+ hashrates: hashrates,
+ }
+ }
+}
+
+#[test]
+fn rpc_eth_protocol_version() {
+ let request = r#"{"jsonrpc": "2.0", "method": "eth_protocolVersion", "params": [], "id": 1}"#;
+ let response = r#"{"jsonrpc":"2.0","result":"63","id":1}"#;
+
+ assert_eq!(EthTester::default().io.handle_request(request), Some(response.to_owned()));
+}
+
+#[test]
+#[ignore]
+fn rpc_eth_syncing() {
+ unimplemented!()
+}
+
+#[test]
+fn rpc_eth_hashrate() {
+ let tester = EthTester::default();
+ tester.hashrates.write().unwrap().insert(H256::from(0), U256::from(0xfffa));
+ tester.hashrates.write().unwrap().insert(H256::from(0), U256::from(0xfffb));
+ tester.hashrates.write().unwrap().insert(H256::from(1), U256::from(0x1));
+
+ let request = r#"{"jsonrpc": "2.0", "method": "eth_hashrate", "params": [], "id": 1}"#;
+ let response = r#"{"jsonrpc":"2.0","result":"0xfffc","id":1}"#;
+
+ assert_eq!(tester.io.handle_request(request), Some(response.to_owned()));
+}
+
+#[test]
+fn rpc_eth_submit_hashrate() {
+ let tester = EthTester::default();
+
+ let request = r#"{
+ "jsonrpc": "2.0",
+ "method": "eth_submitHashrate",
+ "params": [
+ "0x0000000000000000000000000000000000000000000000000000000000500000",
+ "0x59daa26581d0acd1fce254fb7e85952f4c09d0915afd33d3886cd914bc7d283c"],
+ "id": 1
+ }"#;
+ let response = r#"{"jsonrpc":"2.0","result":true,"id":1}"#;
+
+ assert_eq!(tester.io.handle_request(request), Some(response.to_owned()));
+ assert_eq!(tester.hashrates.read().unwrap().get(&H256::from("0x59daa26581d0acd1fce254fb7e85952f4c09d0915afd33d3886cd914bc7d283c")).cloned(),
+ Some(U256::from(0x500_000)));
+}
+
+#[test]
+#[ignore]
+fn rpc_eth_author() {
+ unimplemented!()
+}
+
+#[test]
+fn rpc_eth_mining() {
+ let tester = EthTester::default();
+
+ let request = r#"{"jsonrpc": "2.0", "method": "eth_mining", "params": [], "id": 1}"#;
+ let response = r#"{"jsonrpc":"2.0","result":false,"id":1}"#;
+ assert_eq!(tester.io.handle_request(request), Some(response.to_owned()));
+
+ tester.hashrates.write().unwrap().insert(H256::from(1), U256::from(0x1));
+
+ let request = r#"{"jsonrpc": "2.0", "method": "eth_mining", "params": [], "id": 1}"#;
+ let response = r#"{"jsonrpc":"2.0","result":true,"id":1}"#;
+ assert_eq!(tester.io.handle_request(request), Some(response.to_owned()));
+}
+
+#[test]
+fn rpc_eth_gas_price() {
+ let request = r#"{"jsonrpc": "2.0", "method": "eth_gasPrice", "params": [], "id": 1}"#;
+ let response = r#"{"jsonrpc":"2.0","result":"0x04a817c800","id":1}"#;
+
+ assert_eq!(EthTester::default().io.handle_request(request), Some(response.to_owned()));
+}
+
+#[test]
+fn rpc_eth_accounts() {
+ let request = r#"{"jsonrpc": "2.0", "method": "eth_accounts", "params": [], "id": 1}"#;
+ let response = r#"{"jsonrpc":"2.0","result":["0x0000000000000000000000000000000000000001"],"id":1}"#;
+
+ assert_eq!(EthTester::default().io.handle_request(request), Some(response.to_owned()));
+}
+
+#[test]
+fn rpc_eth_block_number() {
+ let tester = EthTester::default();
+ tester.client.add_blocks(10, EachBlockWith::Nothing);
+
+ let request = r#"{"jsonrpc": "2.0", "method": "eth_blockNumber", "params": [], "id": 1}"#;
+ let response = r#"{"jsonrpc":"2.0","result":"0x0a","id":1}"#;
+
+ assert_eq!(tester.io.handle_request(request), Some(response.to_owned()));
+}
+
+#[test]
+fn rpc_eth_balance() {
+ let tester = EthTester::default();
+ tester.client.set_balance(Address::from(1), U256::from(5));
+
+ let request = r#"{
+ "jsonrpc": "2.0",
+ "method": "eth_getBalance",
+ "params": ["0x0000000000000000000000000000000000000001", "latest"],
+ "id": 1
+ }"#;
+ let response = r#"{"jsonrpc":"2.0","result":"0x05","id":1}"#;
+
+ assert_eq!(tester.io.handle_request(request), Some(response.to_owned()));
+}
+
+#[ignore] //TODO: propert test
+#[test]
+fn rpc_eth_balance_pending() {
+ let tester = EthTester::default();
+
+ let request = r#"{
+ "jsonrpc": "2.0",
+ "method": "eth_getBalance",
+ "params": ["0x0000000000000000000000000000000000000001", "latest"],
+ "id": 1
+ }"#;
+ let response = r#"{"jsonrpc":"2.0","result":"0x","id":1}"#;
+
+ assert_eq!(tester.io.handle_request(request), Some(response.to_owned()));
+}
+
+#[test]
+fn rpc_eth_storage_at() {
+ let tester = EthTester::default();
+ tester.client.set_storage(Address::from(1), H256::from(4), H256::from(7));
+
+ let request = r#"{
+ "jsonrpc": "2.0",
+ "method": "eth_getStorageAt",
+ "params": ["0x0000000000000000000000000000000000000001", "0x4", "latest"],
+ "id": 1
+ }"#;
+ let response = r#"{"jsonrpc":"2.0","result":"0x07","id":1}"#;
+
+ assert_eq!(tester.io.handle_request(request), Some(response.to_owned()));
+}
+
+#[test]
+fn rpc_eth_transaction_count() {
+ let request = r#"{
+ "jsonrpc": "2.0",
+ "method": "eth_getTransactionCount",
+ "params": ["0x0000000000000000000000000000000000000001", "latest"],
+ "id": 1
+ }"#;
+ let response = r#"{"jsonrpc":"2.0","result":"0x00","id":1}"#;
+
+ assert_eq!(EthTester::default().io.handle_request(request), Some(response.to_owned()));
+}
+
+#[test]
+fn rpc_eth_block_transaction_count_by_hash() {
+ let request = r#"{
+ "jsonrpc": "2.0",
+ "method": "eth_getBlockTransactionCountByHash",
+ "params": ["0xb903239f8543d04b5dc1ba6579132b143087c68db1b2168786408fcbce568238"],
+ "id": 1
+ }"#;
+ let response = r#"{"jsonrpc":"2.0","result":null,"id":1}"#;
+
+ assert_eq!(EthTester::default().io.handle_request(request), Some(response.to_owned()));
+}
+
+#[test]
+fn rpc_eth_transaction_count_by_number() {
+ let request = r#"{
+ "jsonrpc": "2.0",
+ "method": "eth_getBlockTransactionCountByNumber",
+ "params": ["latest"],
+ "id": 1
+ }"#;
+ let response = r#"{"jsonrpc":"2.0","result":"0x00","id":1}"#;
+
+ assert_eq!(EthTester::default().io.handle_request(request), Some(response.to_owned()));
+}
+
+#[test]
+fn rpc_eth_transaction_count_by_number_pending() {
+ let request = r#"{
+ "jsonrpc": "2.0",
+ "method": "eth_getBlockTransactionCountByNumber",
+ "params": ["pending"],
+ "id": 1
+ }"#;
+ let response = r#"{"jsonrpc":"2.0","result":"0x01","id":1}"#;
+
+ assert_eq!(EthTester::default().io.handle_request(request), Some(response.to_owned()));
+}
+
+#[test]
+fn rpc_eth_pending_transaction_by_hash() {
+ use util::*;
+ use ethcore::transaction::*;
+
+ let tester = EthTester::default();
+ {
+ let tx: SignedTransaction = decode(&FromHex::from_hex("f85f800182520894095e7baea6a6c7c4c2dfeb977efac326af552d870a801ba048b55bfa915ac795c431978d8a6a992b628d557da5ff759b307d495a36649353a0efffd310ac743f371de3b9f7f9cb56c0b28ad43601b4ab949f53faa07bd2c804").unwrap());
+ tester.miner.pending_transactions.lock().unwrap().insert(H256::zero(), tx);
+ }
+
+ let response = r#"{"jsonrpc":"2.0","result":{"blockHash":null,"blockNumber":null,"from":"0x0f65fe9276bc9a24ae7083ae28e2660ef72df99e","gas":"0x5208","gasPrice":"0x01","hash":"0x41df922fd0d4766fcc02e161f8295ec28522f329ae487f14d811e4b64c8d6e31","input":"0x","nonce":"0x00","to":"0x095e7baea6a6c7c4c2dfeb977efac326af552d87","transactionIndex":null,"value":"0x0a"},"id":1}"#;
+ let request = r#"{
+ "jsonrpc": "2.0",
+ "method": "eth_getTransactionByHash",
+ "params": ["0x0000000000000000000000000000000000000000000000000000000000000000"],
+ "id": 1
+ }"#;
+ assert_eq!(tester.io.handle_request(request), Some(response.to_owned()));
+}
+
+
+#[test]
+fn rpc_eth_uncle_count_by_block_hash() {
+ let request = r#"{
+ "jsonrpc": "2.0",
+ "method": "eth_getUncleCountByBlockHash",
+ "params": ["0xb903239f8543d04b5dc1ba6579132b143087c68db1b2168786408fcbce568238"],
+ "id": 1
+ }"#;
+ let response = r#"{"jsonrpc":"2.0","result":null,"id":1}"#;
+
+ assert_eq!(EthTester::default().io.handle_request(request), Some(response.to_owned()));
+}
+
+#[test]
+fn rpc_eth_uncle_count_by_block_number() {
+ let request = r#"{
+ "jsonrpc": "2.0",
+ "method": "eth_getUncleCountByBlockNumber",
+ "params": ["latest"],
+ "id": 1
+ }"#;
+ let response = r#"{"jsonrpc":"2.0","result":"0x00","id":1}"#;
+
+ assert_eq!(EthTester::default().io.handle_request(request), Some(response.to_owned()));
+}
+
+#[test]
+fn rpc_eth_code() {
+ let tester = EthTester::default();
+ tester.client.set_code(Address::from(1), vec![0xff, 0x21]);
+
+ let request = r#"{
+ "jsonrpc": "2.0",
+ "method": "eth_getCode",
+ "params": ["0x0000000000000000000000000000000000000001", "latest"],
+ "id": 1
+ }"#;
+ let response = r#"{"jsonrpc":"2.0","result":"0xff21","id":1}"#;
+
+ assert_eq!(tester.io.handle_request(request), Some(response.to_owned()));
+}
+
+#[test]
+fn rpc_eth_call() {
+ let tester = EthTester::default();
+ tester.client.set_execution_result(Executed {
+ gas: U256::zero(),
+ gas_used: U256::from(0xff30),
+ refunded: U256::from(0x5),
+ cumulative_gas_used: U256::zero(),
+ logs: vec![],
+ contracts_created: vec![],
+ output: vec![0x12, 0x34, 0xff],
+ trace: None,
+ });
+
+ let request = r#"{
+ "jsonrpc": "2.0",
+ "method": "eth_call",
+ "params": [{
+ "from": "0xb60e8dd61c5d32be8058bb8eb970870f07233155",
+ "to": "0xd46e8dd67c5d32be8058bb8eb970870f07244567",
+ "gas": "0x76c0",
+ "gasPrice": "0x9184e72a000",
+ "value": "0x9184e72a",
+ "data": "0xd46e8dd67c5d32be8d46e8dd67c5d32be8058bb8eb970870f072445675058bb8eb970870f072445675"
+ },
+ "latest"],
+ "id": 1
+ }"#;
+ let response = r#"{"jsonrpc":"2.0","result":"0x1234ff","id":1}"#;
+
+ assert_eq!(tester.io.handle_request(request), Some(response.to_owned()));
+}
+
+#[test]
+fn rpc_eth_call_default_block() {
+ let tester = EthTester::default();
+ tester.client.set_execution_result(Executed {
+ gas: U256::zero(),
+ gas_used: U256::from(0xff30),
+ refunded: U256::from(0x5),
+ cumulative_gas_used: U256::zero(),
+ logs: vec![],
+ contracts_created: vec![],
+ output: vec![0x12, 0x34, 0xff],
+ trace: None,
+ });
+
+ let request = r#"{
+ "jsonrpc": "2.0",
+ "method": "eth_call",
+ "params": [{
+ "from": "0xb60e8dd61c5d32be8058bb8eb970870f07233155",
+ "to": "0xd46e8dd67c5d32be8058bb8eb970870f07244567",
+ "gas": "0x76c0",
+ "gasPrice": "0x9184e72a000",
+ "value": "0x9184e72a",
+ "data": "0xd46e8dd67c5d32be8d46e8dd67c5d32be8058bb8eb970870f072445675058bb8eb970870f072445675"
+ }],
+ "id": 1
+ }"#;
+ let response = r#"{"jsonrpc":"2.0","result":"0x1234ff","id":1}"#;
+
+ assert_eq!(tester.io.handle_request(request), Some(response.to_owned()));
+}
+
+#[test]
+fn rpc_eth_estimate_gas() {
+ let tester = EthTester::default();
+ tester.client.set_execution_result(Executed {
+ gas: U256::zero(),
+ gas_used: U256::from(0xff30),
+ refunded: U256::from(0x5),
+ cumulative_gas_used: U256::zero(),
+ logs: vec![],
+ contracts_created: vec![],
+ output: vec![0x12, 0x34, 0xff],
+ trace: None,
+ });
+
+ let request = r#"{
+ "jsonrpc": "2.0",
+ "method": "eth_estimateGas",
+ "params": [{
+ "from": "0xb60e8dd61c5d32be8058bb8eb970870f07233155",
+ "to": "0xd46e8dd67c5d32be8058bb8eb970870f07244567",
+ "gas": "0x76c0",
+ "gasPrice": "0x9184e72a000",
+ "value": "0x9184e72a",
+ "data": "0xd46e8dd67c5d32be8d46e8dd67c5d32be8058bb8eb970870f072445675058bb8eb970870f072445675"
+ },
+ "latest"],
+ "id": 1
+ }"#;
+ let response = r#"{"jsonrpc":"2.0","result":"0xff35","id":1}"#;
+
+ assert_eq!(tester.io.handle_request(request), Some(response.to_owned()));
+}
+
+#[test]
+fn rpc_eth_estimate_gas_default_block() {
+ let tester = EthTester::default();
+ tester.client.set_execution_result(Executed {
+ gas: U256::zero(),
+ gas_used: U256::from(0xff30),
+ refunded: U256::from(0x5),
+ cumulative_gas_used: U256::zero(),
+ logs: vec![],
+ contracts_created: vec![],
+ output: vec![0x12, 0x34, 0xff],
+ trace: None,
+ });
+
+ let request = r#"{
+ "jsonrpc": "2.0",
+ "method": "eth_estimateGas",
+ "params": [{
+ "from": "0xb60e8dd61c5d32be8058bb8eb970870f07233155",
+ "to": "0xd46e8dd67c5d32be8058bb8eb970870f07244567",
+ "gas": "0x76c0",
+ "gasPrice": "0x9184e72a000",
+ "value": "0x9184e72a",
+ "data": "0xd46e8dd67c5d32be8d46e8dd67c5d32be8058bb8eb970870f072445675058bb8eb970870f072445675"
+ }],
+ "id": 1
+ }"#;
+ let response = r#"{"jsonrpc":"2.0","result":"0xff35","id":1}"#;
+
+ assert_eq!(tester.io.handle_request(request), Some(response.to_owned()));
+}
+
+#[test]
+fn rpc_eth_send_transaction() {
+ let account = TestAccount::new("123");
+ let address = account.address();
+ let secret = account.secret.clone();
+
+ let tester = EthTester::default();
+ tester.accounts_provider.accounts.write().unwrap().insert(address.clone(), account);
+ let request = r#"{
+ "jsonrpc": "2.0",
+ "method": "eth_sendTransaction",
+ "params": [{
+ "from": ""#.to_owned() + format!("0x{:?}", 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![]
+ }.sign(&secret);
+
+ let response = r#"{"jsonrpc":"2.0","result":""#.to_owned() + format!("0x{:?}", t.hash()).as_ref() + r#"","id":1}"#;
+
+ assert_eq!(tester.io.handle_request(request.as_ref()), Some(response));
+
+ tester.miner.last_nonces.write().unwrap().insert(address.clone(), U256::zero());
+
+ 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![]
+ }.sign(&secret);
+
+ let response = r#"{"jsonrpc":"2.0","result":""#.to_owned() + format!("0x{:?}", t.hash()).as_ref() + r#"","id":1}"#;
+
+ assert_eq!(tester.io.handle_request(request.as_ref()), Some(response));
+}
+
+#[test]
+fn rpc_eth_sign_and_send_transaction_with_invalid_password() {
+ let account = TestAccount::new("password123");
+ let address = account.address();
+
+ let tester = EthTester::default();
+ tester.accounts_provider.accounts.write().unwrap().insert(address.clone(), account);
+ let request = r#"{
+ "jsonrpc": "2.0",
+ "method": "eth_signAndSendTransaction",
+ "params": [{
+ "from": ""#.to_owned() + format!("0x{:?}", address).as_ref() + r#"",
+ "to": "0xd46e8dd67c5d32be8058bb8eb970870f07244567",
+ "gas": "0x76c0",
+ "gasPrice": "0x9184e72a000",
+ "value": "0x9184e72a"
+ }, "password321"],
+ "id": 1
+ }"#;
+
+ let response = r#"{"jsonrpc":"2.0","result":"0x0000000000000000000000000000000000000000000000000000000000000000","id":1}"#;
+
+ assert_eq!(tester.io.handle_request(request.as_ref()), Some(response.into()));
+}
+
+#[test]
+fn rpc_eth_sign_and_send_transaction() {
+ let account = TestAccount::new("password123");
+ let address = account.address();
+ let secret = account.secret.clone();
+
+ let tester = EthTester::default();
+ tester.accounts_provider.accounts.write().unwrap().insert(address.clone(), account);
+ let request = r#"{
+ "jsonrpc": "2.0",
+ "method": "eth_signAndSendTransaction",
+ "params": [{
+ "from": ""#.to_owned() + format!("0x{:?}", address).as_ref() + r#"",
+ "to": "0xd46e8dd67c5d32be8058bb8eb970870f07244567",
+ "gas": "0x76c0",
+ "gasPrice": "0x9184e72a000",
+ "value": "0x9184e72a"
+ }, "password123"],
+ "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![]
+ }.sign(&secret);
+
+ let response = r#"{"jsonrpc":"2.0","result":""#.to_owned() + format!("0x{:?}", t.hash()).as_ref() + r#"","id":1}"#;
+
+ assert_eq!(tester.io.handle_request(request.as_ref()), Some(response));
+
+ tester.miner.last_nonces.write().unwrap().insert(address.clone(), U256::zero());
+
+ 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![]
+ }.sign(&secret);
+
+ let response = r#"{"jsonrpc":"2.0","result":""#.to_owned() + format!("0x{:?}", t.hash()).as_ref() + r#"","id":1}"#;
+
+ assert_eq!(tester.io.handle_request(request.as_ref()), Some(response));
+}
+
+#[test]
+#[ignore]
+fn rpc_eth_send_raw_transaction() {
+ unimplemented!()
+}
+
+#[test]
+#[ignore]
+fn rpc_eth_sign() {
+ unimplemented!()
+}
+
+#[test]
+fn rpc_eth_transaction_receipt() {
+ let receipt = LocalizedReceipt {
+ transaction_hash: H256::zero(),
+ transaction_index: 0,
+ block_hash: H256::from_str("ed76641c68a1c641aee09a94b3b471f4dc0316efe5ac19cf488e2674cf8d05b5").unwrap(),
+ block_number: 0x4510c,
+ cumulative_gas_used: U256::from(0x20),
+ gas_used: U256::from(0x10),
+ contract_address: None,
+ logs: vec![LocalizedLogEntry {
+ entry: LogEntry {
+ address: Address::from_str("33990122638b9132ca29c723bdf037f1a891a70c").unwrap(),
+ topics: vec![
+ H256::from_str("a6697e974e6a320f454390be03f74955e8978f1a6971ea6730542e37b66179bc").unwrap(),
+ H256::from_str("4861736852656700000000000000000000000000000000000000000000000000").unwrap()
+ ],
+ data: vec![],
+ },
+ block_hash: H256::from_str("ed76641c68a1c641aee09a94b3b471f4dc0316efe5ac19cf488e2674cf8d05b5").unwrap(),
+ block_number: 0x4510c,
+ transaction_hash: H256::new(),
+ transaction_index: 0,
+ log_index: 1,
+ }]
+ };
+
+ let hash = H256::from_str("b903239f8543d04b5dc1ba6579132b143087c68db1b2168786408fcbce568238").unwrap();
+ let tester = EthTester::default();
+ tester.client.set_transaction_receipt(TransactionID::Hash(hash), receipt);
+
+ let request = r#"{
+ "jsonrpc": "2.0",
+ "method": "eth_getTransactionReceipt",
+ "params": ["0xb903239f8543d04b5dc1ba6579132b143087c68db1b2168786408fcbce568238"],
+ "id": 1
+ }"#;
+ let response = r#"{"jsonrpc":"2.0","result":{"blockHash":"0xed76641c68a1c641aee09a94b3b471f4dc0316efe5ac19cf488e2674cf8d05b5","blockNumber":"0x04510c","contractAddress":null,"cumulativeGasUsed":"0x20","gasUsed":"0x10","logs":[{"address":"0x33990122638b9132ca29c723bdf037f1a891a70c","blockHash":"0xed76641c68a1c641aee09a94b3b471f4dc0316efe5ac19cf488e2674cf8d05b5","blockNumber":"0x04510c","data":"0x","logIndex":"0x01","topics":["0xa6697e974e6a320f454390be03f74955e8978f1a6971ea6730542e37b66179bc","0x4861736852656700000000000000000000000000000000000000000000000000"],"transactionHash":"0x0000000000000000000000000000000000000000000000000000000000000000","transactionIndex":"0x00","type":"mined"}],"transactionHash":"0x0000000000000000000000000000000000000000000000000000000000000000","transactionIndex":"0x00"},"id":1}"#;
+
+ assert_eq!(tester.io.handle_request(request), Some(response.to_owned()));
+}
+
+#[test]
+fn rpc_eth_transaction_receipt_null() {
+ let tester = EthTester::default();
+
+ let request = r#"{
+ "jsonrpc": "2.0",
+ "method": "eth_getTransactionReceipt",
+ "params": ["0xb903239f8543d04b5dc1ba6579132b143087c68db1b2168786408fcbce568238"],
+ "id": 1
+ }"#;
+ let response = r#"{"jsonrpc":"2.0","result":null,"id":1}"#;
+
+ assert_eq!(tester.io.handle_request(request), Some(response.to_owned()));
+}
+
+#[test]
+fn rpc_eth_compilers() {
+ let request = r#"{"jsonrpc": "2.0", "method": "eth_getCompilers", "params": [], "id": 1}"#;
+ let response = r#"{"jsonrpc":"2.0","result":[],"id":1}"#;
+
+ assert_eq!(EthTester::default().io.handle_request(request), Some(response.to_owned()));
+}
+
+#[test]
+fn rpc_eth_compile_lll() {
+ let request = r#"{"jsonrpc": "2.0", "method": "eth_compileLLL", "params": [], "id": 1}"#;
+ let response = r#"{"jsonrpc":"2.0","error":{"code":-32603,"message":"Internal error","data":null},"id":1}"#;
+
+ assert_eq!(EthTester::default().io.handle_request(request), Some(response.to_owned()));
+}
+
+#[test]
+fn rpc_eth_compile_solidity() {
+ let request = r#"{"jsonrpc": "2.0", "method": "eth_compileSolidity", "params": [], "id": 1}"#;
+ let response = r#"{"jsonrpc":"2.0","error":{"code":-32603,"message":"Internal error","data":null},"id":1}"#;
+
+ assert_eq!(EthTester::default().io.handle_request(request), Some(response.to_owned()));
+}
+
+#[test]
+fn rpc_eth_compile_serpent() {
+ let request = r#"{"jsonrpc": "2.0", "method": "eth_compileSerpent", "params": [], "id": 1}"#;
+ let response = r#"{"jsonrpc":"2.0","error":{"code":-32603,"message":"Internal error","data":null},"id":1}"#;
+
+ assert_eq!(EthTester::default().io.handle_request(request), Some(response.to_owned()));
+}
+
+#[test]
+fn returns_no_work_if_cant_mine() {
+ let eth_tester = EthTester::default();
+ eth_tester.client.set_queue_size(10);
+
+ let request = r#"{"jsonrpc": "2.0", "method": "eth_getWork", "params": [], "id": 1}"#;
+ let response = r#"{"jsonrpc":"2.0","result":["","",""],"id":1}"#;
+
+ assert_eq!(eth_tester.io.handle_request(request), Some(response.to_owned()));
+}
+
+#[ignore]
+// enable once TestMinerService supports the mining API.
+#[test]
+fn returns_error_if_can_mine_and_no_closed_block() {
+ use ethsync::{SyncState};
+
+ let eth_tester = EthTester::default();
+ eth_tester.sync.status.write().unwrap().state = SyncState::Idle;
+
+ let request = r#"{"jsonrpc": "2.0", "method": "eth_getWork", "params": [], "id": 1}"#;
+ let response = r#"{"jsonrpc":"2.0","error":{"code":-32603,"message":"Internal error","data":null},"id":1}"#;
+
+ assert_eq!(eth_tester.io.handle_request(request), Some(response.to_owned()));
+}
diff --git a/rpc/src/v1/tests/ethcore.rs b/rpc/src/v1/tests/mocked/ethcore.rs
similarity index 100%
rename from rpc/src/v1/tests/ethcore.rs
rename to rpc/src/v1/tests/mocked/ethcore.rs
diff --git a/rpc/src/v1/tests/mocked/mod.rs b/rpc/src/v1/tests/mocked/mod.rs
new file mode 100644
index 000000000..98caf6e08
--- /dev/null
+++ b/rpc/src/v1/tests/mocked/mod.rs
@@ -0,0 +1,24 @@
+// 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 .
+
+//! RPC serialization tests.
+
+mod eth;
+mod net;
+mod web3;
+mod personal;
+mod ethcore;
+mod rpc;
diff --git a/rpc/src/v1/tests/net.rs b/rpc/src/v1/tests/mocked/net.rs
similarity index 100%
rename from rpc/src/v1/tests/net.rs
rename to rpc/src/v1/tests/mocked/net.rs
diff --git a/rpc/src/v1/tests/personal.rs b/rpc/src/v1/tests/mocked/personal.rs
similarity index 100%
rename from rpc/src/v1/tests/personal.rs
rename to rpc/src/v1/tests/mocked/personal.rs
diff --git a/rpc/src/v1/tests/rpc.rs b/rpc/src/v1/tests/mocked/rpc.rs
similarity index 100%
rename from rpc/src/v1/tests/rpc.rs
rename to rpc/src/v1/tests/mocked/rpc.rs
diff --git a/rpc/src/v1/tests/web3.rs b/rpc/src/v1/tests/mocked/web3.rs
similarity index 100%
rename from rpc/src/v1/tests/web3.rs
rename to rpc/src/v1/tests/mocked/web3.rs
diff --git a/rpc/src/v1/tests/mod.rs b/rpc/src/v1/tests/mod.rs
index 04e0dc142..f5e7d1404 100644
--- a/rpc/src/v1/tests/mod.rs
+++ b/rpc/src/v1/tests/mod.rs
@@ -1,31 +1,8 @@
-// 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 .
-
-//!TODO: load custom blockchain state and test
+//! RPC unit test moduleS
pub mod helpers;
+
#[cfg(test)]
-mod eth;
+mod mocked;
#[cfg(test)]
-mod net;
-#[cfg(test)]
-mod web3;
-#[cfg(test)]
-mod personal;
-#[cfg(test)]
-mod ethcore;
-#[cfg(test)]
-mod rpc;
+mod eth;
\ No newline at end of file
diff --git a/util/src/journaldb/archivedb.rs b/util/src/journaldb/archivedb.rs
index 4fa8ce6f3..b554db885 100644
--- a/util/src/journaldb/archivedb.rs
+++ b/util/src/journaldb/archivedb.rs
@@ -47,7 +47,9 @@ impl ArchiveDB {
/// Create a new instance from file
pub fn new(path: &str) -> ArchiveDB {
let opts = DatabaseConfig {
- prefix_size: Some(12) //use 12 bytes as prefix, this must match account_db prefix
+ //use 12 bytes as prefix, this must match account_db prefix
+ prefix_size: Some(12),
+ max_open_files: 256,
};
let backing = Database::open(&opts, path).unwrap_or_else(|e| {
panic!("Error opening state db: {}", e);
diff --git a/util/src/journaldb/earlymergedb.rs b/util/src/journaldb/earlymergedb.rs
index 62fe0023a..7cb117447 100644
--- a/util/src/journaldb/earlymergedb.rs
+++ b/util/src/journaldb/earlymergedb.rs
@@ -77,7 +77,9 @@ impl EarlyMergeDB {
/// Create a new instance from file
pub fn new(path: &str) -> EarlyMergeDB {
let opts = DatabaseConfig {
- prefix_size: Some(12) //use 12 bytes as prefix, this must match account_db prefix
+ //use 12 bytes as prefix, this must match account_db prefix
+ prefix_size: Some(12),
+ max_open_files: 256,
};
let backing = Database::open(&opts, path).unwrap_or_else(|e| {
panic!("Error opening state db: {}", e);
diff --git a/util/src/journaldb/overlayrecentdb.rs b/util/src/journaldb/overlayrecentdb.rs
index 9c68b9255..86d8d5c4d 100644
--- a/util/src/journaldb/overlayrecentdb.rs
+++ b/util/src/journaldb/overlayrecentdb.rs
@@ -107,7 +107,9 @@ impl OverlayRecentDB {
/// Create a new instance from file
pub fn from_prefs(path: &str) -> OverlayRecentDB {
let opts = DatabaseConfig {
- prefix_size: Some(12) //use 12 bytes as prefix, this must match account_db prefix
+ //use 12 bytes as prefix, this must match account_db prefix
+ prefix_size: Some(12),
+ max_open_files: 256,
};
let backing = Database::open(&opts, path).unwrap_or_else(|e| {
panic!("Error opening state db: {}", e);
diff --git a/util/src/journaldb/refcounteddb.rs b/util/src/journaldb/refcounteddb.rs
index 0df4d76b1..7f24a729c 100644
--- a/util/src/journaldb/refcounteddb.rs
+++ b/util/src/journaldb/refcounteddb.rs
@@ -49,7 +49,9 @@ impl RefCountedDB {
/// Create a new instance given a `backing` database.
pub fn new(path: &str) -> RefCountedDB {
let opts = DatabaseConfig {
- prefix_size: Some(12) //use 12 bytes as prefix, this must match account_db prefix
+ //use 12 bytes as prefix, this must match account_db prefix
+ prefix_size: Some(12),
+ max_open_files: 256,
};
let backing = Database::open(&opts, path).unwrap_or_else(|e| {
panic!("Error opening state db: {}", e);
diff --git a/util/src/kvdb.rs b/util/src/kvdb.rs
index c0eb7c10c..40b7ef090 100644
--- a/util/src/kvdb.rs
+++ b/util/src/kvdb.rs
@@ -51,7 +51,9 @@ impl DBTransaction {
/// Database configuration
pub struct DatabaseConfig {
/// Optional prefix size in bytes. Allows lookup by partial key.
- pub prefix_size: Option
+ pub prefix_size: Option,
+ /// Max number of open files.
+ pub max_open_files: i32,
}
/// Database iterator
@@ -75,13 +77,13 @@ pub struct Database {
impl Database {
/// Open database with default settings.
pub fn open_default(path: &str) -> Result {
- Database::open(&DatabaseConfig { prefix_size: None }, path)
+ Database::open(&DatabaseConfig { prefix_size: None, max_open_files: 256 }, path)
}
/// Open database file. Creates if it does not exist.
pub fn open(config: &DatabaseConfig, path: &str) -> Result {
let mut opts = Options::new();
- opts.set_max_open_files(256);
+ opts.set_max_open_files(config.max_open_files);
opts.create_if_missing(true);
opts.set_use_fsync(false);
opts.set_compaction_style(DBCompactionStyle::DBUniversalCompaction);
@@ -203,10 +205,10 @@ mod tests {
let path = RandomTempPath::create_dir();
let smoke = Database::open_default(path.as_path().to_str().unwrap()).unwrap();
assert!(smoke.is_empty());
- test_db(&DatabaseConfig { prefix_size: None });
- test_db(&DatabaseConfig { prefix_size: Some(1) });
- test_db(&DatabaseConfig { prefix_size: Some(8) });
- test_db(&DatabaseConfig { prefix_size: Some(32) });
+ test_db(&DatabaseConfig { prefix_size: None, max_open_files: 256 });
+ test_db(&DatabaseConfig { prefix_size: Some(1), max_open_files: 256 });
+ test_db(&DatabaseConfig { prefix_size: Some(8), max_open_files: 256 });
+ test_db(&DatabaseConfig { prefix_size: Some(32), max_open_files: 256 });
}
}