Merge branch 'master' into ui-2

This commit is contained in:
Jaco Greeff 2017-05-02 13:40:05 +02:00
commit b57e8f6f0d
24 changed files with 3980 additions and 69 deletions

3842
CHANGELOG.md Normal file

File diff suppressed because it is too large Load Diff

6
Cargo.lock generated
View File

@ -1778,7 +1778,7 @@ dependencies = [
[[package]]
name = "parity-ui-precompiled"
version = "1.4.0"
source = "git+https://github.com/paritytech/js-precompiled.git#e2616ff5fba5ee7bf35b9dbd29ea896b2ed8ecea"
source = "git+https://github.com/paritytech/js-precompiled.git#6ae27a1126a30b21bac014d8d2a5eaac0c38ba1f"
dependencies = [
"parity-dapps-glue 1.7.0 (registry+https://github.com/rust-lang/crates.io-index)",
]
@ -2044,7 +2044,7 @@ dependencies = [
[[package]]
name = "rocksdb"
version = "0.4.5"
source = "git+https://github.com/paritytech/rust-rocksdb#8579e896a98cdeff086392236d411dd4aa141774"
source = "git+https://github.com/paritytech/rust-rocksdb#acd192f6ee017a3e8be704958617349d20ee783b"
dependencies = [
"libc 0.2.21 (registry+https://github.com/rust-lang/crates.io-index)",
"rocksdb-sys 0.3.0 (git+https://github.com/paritytech/rust-rocksdb)",
@ -2053,7 +2053,7 @@ dependencies = [
[[package]]
name = "rocksdb-sys"
version = "0.3.0"
source = "git+https://github.com/paritytech/rust-rocksdb#8579e896a98cdeff086392236d411dd4aa141774"
source = "git+https://github.com/paritytech/rust-rocksdb#acd192f6ee017a3e8be704958617349d20ee783b"
dependencies = [
"gcc 0.3.43 (registry+https://github.com/rust-lang/crates.io-index)",
"libc 0.2.21 (registry+https://github.com/rust-lang/crates.io-index)",

View File

@ -1,9 +1,9 @@
# [Parity](https://ethcore.io/parity.html)
# [Parity](https://parity.io/parity.html)
### Fast, light, and robust Ethereum implementation
### [Download latest release](https://github.com/paritytech/parity/releases)
[![build status](https://gitlab.ethcore.io/parity/parity/badges/master/build.svg)](https://gitlab.ethcore.io/parity/parity/commits/master) [![Coverage Status][coveralls-image]][coveralls-url] [![GPLv3][license-image]][license-url]
[![build status](https://gitlab.parity.io/parity/parity/badges/master/build.svg)](https://gitlab.parity.io/parity/parity/commits/master) [![Coverage Status][coveralls-image]][coveralls-url] [![GPLv3][license-image]][license-url]
### Join the chat!

View File

@ -123,7 +123,7 @@ impl Light {
return Err(io::Error::new(io::ErrorKind::Other, "Cache file size mismatch"));
}
let num_nodes = cache_size / NODE_BYTES;
let mut nodes: Vec<Node> = Vec::new();
let mut nodes: Vec<Node> = Vec::with_capacity(num_nodes);
nodes.resize(num_nodes, unsafe { mem::uninitialized() });
let buf = unsafe { slice::from_raw_parts_mut(nodes.as_mut_ptr() as *mut u8, cache_size) };
file.read_exact(buf)?;
@ -342,7 +342,6 @@ fn calculate_dag_item(node_index: u32, cache: &[Node]) -> Node {
}
fn light_new(block_number: u64) -> Light {
let seed_compute = SeedHashCompute::new();
let seedhash = seed_compute.get_seedhash(block_number);
let cache_size = get_cache_size(block_number);

View File

@ -211,7 +211,7 @@ mod tests {
}
fn fetch_with_abort(&self, url: &str, _abort: fetch::Abort) -> Self::Result {
assert_eq!(url, "https://ethcore.io/assets/images/ethcore-black-horizontal.png");
assert_eq!(url, "https://parity.io/assets/images/ethcore-black-horizontal.png");
future::ok(if self.return_success {
let cursor = ::std::io::Cursor::new(b"result");
fetch::Response::from_reader(cursor)

View File

@ -370,7 +370,7 @@ pub mod tests {
// then
assert_eq!(res, Some(URLHintResult::Content(Content {
url: "https://ethcore.io/assets/images/ethcore-black-horizontal.png".into(),
url: "https://parity.io/assets/images/ethcore-black-horizontal.png".into(),
mime: mime!(Image/Png),
owner: Address::from_str("deadcafebeefbeefcafedeaddeedfeedffffffff").unwrap(),
})))
@ -395,11 +395,11 @@ pub mod tests {
#[test]
fn should_guess_mime_type_from_url() {
let url1 = "https://ethcore.io/parity";
let url2 = "https://ethcore.io/parity#content-type=image/png";
let url3 = "https://ethcore.io/parity#something&content-type=image/png";
let url4 = "https://ethcore.io/parity.png#content-type=image/jpeg";
let url5 = "https://ethcore.io/parity.png";
let url1 = "https://parity.io/parity";
let url2 = "https://parity.io/parity#content-type=image/png";
let url3 = "https://parity.io/parity#something&content-type=image/png";
let url4 = "https://parity.io/parity.png#content-type=image/jpeg";
let url5 = "https://parity.io/parity.png";
assert_eq!(guess_mime_type(url1), None);

View File

@ -1,6 +1,6 @@
{
"name": "parity.js",
"version": "1.7.62",
"version": "1.7.63",
"main": "release/index.js",
"jsnext:main": "src/index.js",
"author": "Parity Team <admin@parity.io>",

View File

@ -22,6 +22,6 @@ export default (
<li>We collect your email address when you use this service. This is temporarily kept in memory, and then encrypted and stored in our EU servers. We only retain the cryptographic hash of the email address to prevent duplicated accounts. The cryptographic hash of your email address is also stored on the blockchain which is public by design. You consent to this use.</li>
<li>You pay a fee for the cost of this service using the account you want to verify.</li>
<li>Your email address is transmitted to a third party EU email verification service mailjet for the sole purpose of the email verification. You consent to this use. Mailjet's privacy policy is here: <a href='https://www.mailjet.com/privacy-policy'>https://www.mailjet.com/privacy-policy</a>.</li>
<li><i>Parity Technology Limited</i> is registered in England and Wales under company number <code>09760015</code> and complies with the Data Protection Act 1998 (UK). You may contact us via email at <a href={ 'mailto:admin@parity.io' }>admin@parity.io</a>. Our general privacy policy can be found here: <a href={ 'https://ethcore.io/legal.html' }>https://ethcore.io/legal.html</a>.</li>
<li><i>Parity Technology Limited</i> is registered in England and Wales under company number <code>09760015</code> and complies with the Data Protection Act 1998 (UK). You may contact us via email at <a href={ 'mailto:admin@parity.io' }>admin@parity.io</a>. Our general privacy policy can be found here: <a href={ 'https://parity.io/legal.html' }>https://parity.io/legal.html</a>.</li>
</ul>
);

View File

@ -22,6 +22,6 @@ export default (
<li>We collect your phone number when you use this service. This is temporarily kept in memory, and then encrypted and stored in our EU servers. We only retain the cryptographic hash of the number to prevent duplicated accounts. You consent to this use.</li>
<li>You pay a fee for the cost of this service using the account you want to verify.</li>
<li>Your phone number is transmitted to a third party US SMS verification service Twilio for the sole purpose of the SMS verification. You consent to this use. Twilios privacy policy is here: <a href={ 'https://www.twilio.com/legal/privacy/developer' }>https://www.twilio.com/legal/privacy/developer</a>.</li>
<li><i>Parity Technology Limited</i> is registered in England and Wales under company number <code>09760015</code> and complies with the Data Protection Act 1998 (UK). You may contact us via email at <a href={ 'mailto:admin@parity.io' }>admin@parity.io</a>. Our general privacy policy can be found here: <a href={ 'https://ethcore.io/legal.html' }>https://ethcore.io/legal.html</a>.</li>
<li><i>Parity Technology Limited</i> is registered in England and Wales under company number <code>09760015</code> and complies with the Data Protection Act 1998 (UK). You may contact us via email at <a href={ 'mailto:admin@parity.io' }>admin@parity.io</a>. Our general privacy policy can be found here: <a href={ 'https://parity.io/legal.html' }>https://parity.io/legal.html</a>.</li>
</ul>
);

View File

@ -3,7 +3,7 @@
"url": "chaindeploy",
"name": "Chain Deployment",
"description": "Deploy all basic contracts, names & applications to the network",
"author": "Parity Team <admin@ethcore.io>",
"author": "Parity Team <admin@parity.io>",
"version": "1.0.0",
"visible": false,
"noselect": false
@ -13,7 +13,7 @@
"url": "tokendeploy",
"name": "Token Deployment",
"description": "Deploy new basic tokens that you are able to send around",
"author": "Parity Team <admin@ethcore.io>",
"author": "Parity Team <admin@parity.io>",
"version": "1.0.0",
"visible": true
},
@ -22,7 +22,7 @@
"url": "registry",
"name": "Registry",
"description": "A global registry of addresses on the network",
"author": "Parity Team <admin@ethcore.io>",
"author": "Parity Team <admin@parity.io>",
"version": "1.0.0",
"visible": true
},
@ -31,7 +31,7 @@
"url": "tokenreg",
"name": "Token Registry",
"description": "A registry of transactable tokens on the network",
"author": "Parity Team <admin@ethcore.io>",
"author": "Parity Team <admin@parity.io>",
"version": "1.0.0",
"visible": true,
"secure": true
@ -41,7 +41,7 @@
"url": "signaturereg",
"name": "Method Registry",
"description": "A registry of method signatures for lookups on transactions",
"author": "Parity Team <admin@ethcore.io>",
"author": "Parity Team <admin@parity.io>",
"version": "1.0.0",
"visible": true
},
@ -50,7 +50,7 @@
"url": "githubhint",
"name": "GitHub Hint",
"description": "A mapping of GitHub URLs to hashes for use in contracts as references",
"author": "Parity Team <admin@ethcore.io>",
"author": "Parity Team <admin@parity.io>",
"version": "1.0.0",
"visible": false,
"secure": true
@ -60,7 +60,7 @@
"url": "localtx",
"name": "TxQueue Viewer",
"description": "Have a peek at the internals of your node's transaction queue",
"author": "Parity Team <admin@ethcore.io>",
"author": "Parity Team <admin@parity.io>",
"version": "1.0.0",
"visible": true,
"secure": true
@ -70,7 +70,7 @@
"url": "dappreg",
"name": "Dapp Registration",
"description": "Enables the registration and content management of dapps on the network",
"author": "Parity Team <admin@ethcore.io>",
"author": "Parity Team <admin@parity.io>",
"version": "1.0.0",
"visible": false,
"secure": true
@ -80,7 +80,7 @@
"url": "web",
"name": "Browser",
"description": "A Web 2.0 hosted pseudo-dapps browser",
"author": "Parity Team <admin@ethcore.io>",
"author": "Parity Team <admin@parity.io>",
"version": "1.0.0",
"visible": true,
"skipBuild": true,
@ -92,7 +92,7 @@
"name": "Parity/Web3 console",
"description": "A Javascript development console complete with web3 and parity objects",
"version": "0.3",
"author": "Gav Wood <gavin@ethcore.io>",
"author": "Gav Wood <gavin@parity.io>",
"position": "top-right",
"visible": true,
"secure": true,

View File

@ -42,7 +42,7 @@ impl WebApp for App {
Info {
name: "Parity UI",
version: env!("CARGO_PKG_VERSION"),
author: "Ethcore <admin@ethcore.io>",
author: "Ethcore <admin@parity.io>",
description: "New UI for Parity.",
icon_url: "icon.png",
}

View File

@ -76,7 +76,7 @@ export default class TnC extends Component {
<p>You agree that you are solely responsible for (and that EthCore has no responsibility to you or to any third party for) any breach of your obligations under these terms and for the consequences (including any loss or damage which EthCore may suffer) of any such breach.</p>
<h3>Privacy and your personal information</h3>
<p>You agree to the use of your data (if any is gathered) in accordance with EthCores privacy policies: <a href='https://ethcore.io/legal.html' target='_blank'>https://ethcore.io/legal.html</a>. This policy explains how EthCore treats your personal information (if any is gathered), and protects your privacy, when you use EthCores Products.</p>
<p>You agree to the use of your data (if any is gathered) in accordance with EthCores privacy policies: <a href='https://parity.io/legal.html' target='_blank'>https://parity.io/legal.html</a>. This policy explains how EthCore treats your personal information (if any is gathered), and protects your privacy, when you use EthCores Products.</p>
<h3>Content in Parity</h3>
<p>You understand that all information and data (such as smart contracts, data files, written text, computer software, music, audio files or other sounds, photographs, videos or other images) which you may have access to as part of, or through your use of, EthCores Product are the sole responsibility of the person from which such content originated. All such information is referred to below as the Content.</p>
@ -87,7 +87,7 @@ export default class TnC extends Component {
<h3>Proprietary rights</h3>
<p>You acknowledge and agree that EthCore own all legal right, title and interest in and to the Parity and EthCores Products, including any intellectual property rights which subsist in Parity and EthCores Products (whether those rights happen to be registered or not, and wherever in the world those rights may exist).</p>
<p>Unless you have agreed otherwise in writing with EthCore, nothing in the Terms gives you a right to use any of EthCores trade names, trade marks, service marks, logos, domain names, and other distinctive brand features.</p>
<p>If you have been given an explicit right to use any of these brand features in a separate written agreement with EthCore, then you agree that your use of such features shall be in compliance with that agreement, any applicable provisions of these terms, and EthCores brand feature use guidelines as updated from time to time. These guidelines can be viewed online at <a href='https://ethcore.io/press.html' target='_blank'>https://ethcore.io/press.html</a>.</p>
<p>If you have been given an explicit right to use any of these brand features in a separate written agreement with EthCore, then you agree that your use of such features shall be in compliance with that agreement, any applicable provisions of these terms, and EthCores brand feature use guidelines as updated from time to time. These guidelines can be viewed online at <a href='https://parity.io/press.html' target='_blank'>https://parity.io/press.html</a>.</p>
<p>EthCore acknowledges and agrees that it obtains no right, title or interest from you (or your licensors) under these terms in or to any content that you submit, post, transmit or display on, or through, Parity, including any intellectual property rights which subsist in that content (whether those rights happen to be registered or not, and wherever in the world those rights may exist). Unless you have agreed otherwise in writing with EthCore, you agree that you are responsible for protecting and enforcing those rights and that EthCore has no obligation to do so on your behalf.</p>
<p>You agree that you shall not remove, obscure, or alter any proprietary rights notices (including copyright and trade mark notices) which may be affixed to or contained within Parity or EthCores Products.</p>
<p>Unless you have been expressly authorized to do so in writing by EthCore, you agree that in using Parity, you will not use any trade mark, service mark, trade name, logo of any company or organization in a way that is likely or intended to cause confusion about the owner or authorized user of such marks, names or logos.</p>
@ -145,7 +145,7 @@ export default class TnC extends Component {
<p>You acknowledge and agree that EthCore is not liable for any loss or damage which may be incurred by you as a result of the availability of those external sites or resources, or as a result of any reliance placed by you on the completeness, accuracy or existence of any advertising, products or other materials on, or available from, such web sites or resources.</p>
<h3>Changes to the Terms</h3>
<p>EthCore may make changes to these from time to time. When these changes are made, EthCore will make a new copy of these terms available at https://ethcore.io/legal.html and any new terms will be made available to you from within, or through, the affected EthCores Product.</p>
<p>EthCore may make changes to these from time to time. When these changes are made, EthCore will make a new copy of these terms available at https://parity.io/legal.html and any new terms will be made available to you from within, or through, the affected EthCores Product.</p>
<p>You understand and agree that if you use Parity or EthCores Products after the date on which the Terms have changed, EthCore will treat your use as acceptance of the updated terms.</p>
<h3>General legal terms</h3>

View File

@ -19,7 +19,7 @@ use std::cmp::max;
const MIN_BC_CACHE_MB: u32 = 4;
const MIN_DB_CACHE_MB: u32 = 2;
const MIN_BLOCK_QUEUE_SIZE_LIMIT_MB: u32 = 16;
const DEFAULT_BLOCK_QUEUE_SIZE_LIMIT_MB: u32 = 50;
const DEFAULT_BLOCK_QUEUE_SIZE_LIMIT_MB: u32 = 40;
const DEFAULT_TRACE_CACHE_SIZE: u32 = 20;
const DEFAULT_STATE_CACHE_SIZE: u32 = 25;
@ -41,7 +41,7 @@ pub struct CacheConfig {
impl Default for CacheConfig {
fn default() -> Self {
CacheConfig::new(64, 8, DEFAULT_BLOCK_QUEUE_SIZE_LIMIT_MB, DEFAULT_STATE_CACHE_SIZE)
CacheConfig::new(32, 8, DEFAULT_BLOCK_QUEUE_SIZE_LIMIT_MB, DEFAULT_STATE_CACHE_SIZE)
}
}
@ -113,7 +113,7 @@ mod tests {
let config = CacheConfig::new_with_total_cache_size(200);
assert_eq!(config.db, 140);
assert_eq!(config.blockchain(), 20);
assert_eq!(config.queue(), 50);
assert_eq!(config.queue(), 40);
assert_eq!(config.state(), 30);
assert_eq!(config.jump_tables(), 10);
}
@ -129,6 +129,6 @@ mod tests {
#[test]
fn test_cache_config_default() {
assert_eq!(CacheConfig::default(),
CacheConfig::new(64, 8, super::DEFAULT_BLOCK_QUEUE_SIZE_LIMIT_MB, super::DEFAULT_STATE_CACHE_SIZE));
CacheConfig::new(32, 8, super::DEFAULT_BLOCK_QUEUE_SIZE_LIMIT_MB, super::DEFAULT_STATE_CACHE_SIZE));
}
}

View File

@ -294,13 +294,13 @@ usage! {
or |c: &Config| otry!(c.footprint).pruning.clone(),
flag_pruning_history: u64 = 64u64,
or |c: &Config| otry!(c.footprint).pruning_history.clone(),
flag_pruning_memory: usize = 75usize,
flag_pruning_memory: usize = 32usize,
or |c: &Config| otry!(c.footprint).pruning_memory.clone(),
flag_cache_size_db: u32 = 64u32,
flag_cache_size_db: u32 = 32u32,
or |c: &Config| otry!(c.footprint).cache_size_db.clone(),
flag_cache_size_blocks: u32 = 8u32,
or |c: &Config| otry!(c.footprint).cache_size_blocks.clone(),
flag_cache_size_queue: u32 = 50u32,
flag_cache_size_queue: u32 = 40u32,
or |c: &Config| otry!(c.footprint).cache_size_queue.clone(),
flag_cache_size_state: u32 = 25u32,
or |c: &Config| otry!(c.footprint).cache_size_state.clone(),

View File

@ -1124,7 +1124,7 @@ mod tests {
format: Default::default(),
pruning: Default::default(),
pruning_history: 64,
pruning_memory: 75,
pruning_memory: 32,
compaction: Default::default(),
wal: true,
tracing: Default::default(),
@ -1147,7 +1147,7 @@ mod tests {
file_path: Some("blockchain.json".into()),
pruning: Default::default(),
pruning_history: 64,
pruning_memory: 75,
pruning_memory: 32,
format: Default::default(),
compaction: Default::default(),
wal: true,
@ -1170,7 +1170,7 @@ mod tests {
file_path: Some("state.json".into()),
pruning: Default::default(),
pruning_history: 64,
pruning_memory: 75,
pruning_memory: 32,
format: Default::default(),
compaction: Default::default(),
wal: true,
@ -1195,7 +1195,7 @@ mod tests {
file_path: Some("blockchain.json".into()),
pruning: Default::default(),
pruning_history: 64,
pruning_memory: 75,
pruning_memory: 32,
format: Some(DataFormat::Hex),
compaction: Default::default(),
wal: true,
@ -1231,7 +1231,7 @@ mod tests {
spec: Default::default(),
pruning: Default::default(),
pruning_history: 64,
pruning_memory: 75,
pruning_memory: 32,
daemon: None,
logger_config: Default::default(),
miner_options: Default::default(),
@ -1369,13 +1369,13 @@ mod tests {
let conf0 = parse(&["parity"]);
let conf1 = parse(&["parity", "--jsonrpc-hosts", "none"]);
let conf2 = parse(&["parity", "--jsonrpc-hosts", "all"]);
let conf3 = parse(&["parity", "--jsonrpc-hosts", "ethcore.io,something.io"]);
let conf3 = parse(&["parity", "--jsonrpc-hosts", "parity.io,something.io"]);
// then
assert_eq!(conf0.rpc_hosts(), Some(Vec::new()));
assert_eq!(conf1.rpc_hosts(), Some(Vec::new()));
assert_eq!(conf2.rpc_hosts(), None);
assert_eq!(conf3.rpc_hosts(), Some(vec!["ethcore.io".into(), "something.io".into()]));
assert_eq!(conf3.rpc_hosts(), Some(vec!["parity.io".into(), "something.io".into()]));
}
#[test]
@ -1386,13 +1386,13 @@ mod tests {
let conf0 = parse(&["parity"]);
let conf1 = parse(&["parity", "--ipfs-api-hosts", "none"]);
let conf2 = parse(&["parity", "--ipfs-api-hosts", "all"]);
let conf3 = parse(&["parity", "--ipfs-api-hosts", "ethcore.io,something.io"]);
let conf3 = parse(&["parity", "--ipfs-api-hosts", "parity.io,something.io"]);
// then
assert_eq!(conf0.ipfs_hosts(), Some(Vec::new()));
assert_eq!(conf1.ipfs_hosts(), Some(Vec::new()));
assert_eq!(conf2.ipfs_hosts(), None);
assert_eq!(conf3.ipfs_hosts(), Some(vec!["ethcore.io".into(), "something.io".into()]));
assert_eq!(conf3.ipfs_hosts(), Some(vec!["parity.io".into(), "something.io".into()]));
}
#[test]
@ -1402,12 +1402,12 @@ mod tests {
// when
let conf0 = parse(&["parity"]);
let conf1 = parse(&["parity", "--ipfs-api-cors", "*"]);
let conf2 = parse(&["parity", "--ipfs-api-cors", "http://ethcore.io,http://something.io"]);
let conf2 = parse(&["parity", "--ipfs-api-cors", "http://parity.io,http://something.io"]);
// then
assert_eq!(conf0.ipfs_cors(), None);
assert_eq!(conf1.ipfs_cors(), Some(vec!["*".into()]));
assert_eq!(conf2.ipfs_cors(), Some(vec!["http://ethcore.io".into(),"http://something.io".into()]));
assert_eq!(conf2.ipfs_cors(), Some(vec!["http://parity.io".into(),"http://something.io".into()]));
}
#[test]

View File

@ -58,7 +58,7 @@ pub trait Dispatcher: Send + Sync + Clone {
// type Out<T>: IntoFuture<T, Error>
/// Fill optional fields of a transaction request, fetching gas price but not nonce.
fn fill_optional_fields(&self, request: TransactionRequest, default_sender: Address)
fn fill_optional_fields(&self, request: TransactionRequest, default_sender: Address, force_nonce: bool)
-> BoxFuture<FilledTransactionRequest, Error>;
/// Sign the given transaction request without dispatching, fetching appropriate nonce.
@ -96,17 +96,30 @@ impl<C, M> Clone for FullDispatcher<C, M> {
}
}
impl<C: MiningBlockChainClient, M: MinerService> FullDispatcher<C, M> {
fn fill_nonce(nonce: Option<U256>, from: &Address, miner: &M, client: &C) -> U256 {
nonce
.or_else(|| miner.last_nonce(from).map(|nonce| nonce + U256::one()))
.unwrap_or_else(|| client.latest_nonce(from))
}
}
impl<C: MiningBlockChainClient, M: MinerService> Dispatcher for FullDispatcher<C, M> {
fn fill_optional_fields(&self, request: TransactionRequest, default_sender: Address)
fn fill_optional_fields(&self, request: TransactionRequest, default_sender: Address, force_nonce: bool)
-> BoxFuture<FilledTransactionRequest, Error>
{
let (client, miner) = (take_weakf!(self.client), take_weakf!(self.miner));
let request = request;
let from = request.from.unwrap_or(default_sender);
let nonce = match force_nonce {
false => request.nonce,
true => Some(Self::fill_nonce(request.nonce, &from, &miner, &client)),
};
future::ok(FilledTransactionRequest {
from: request.from.unwrap_or(default_sender),
from: from,
used_default_from: request.from.is_none(),
to: request.to,
nonce: request.nonce,
nonce: nonce,
gas_price: request.gas_price.unwrap_or_else(|| default_gas_price(&*client, &*miner)),
gas: request.gas.unwrap_or_else(|| miner.sensible_gas_limit()),
value: request.value.unwrap_or_else(|| 0.into()),
@ -123,12 +136,7 @@ impl<C: MiningBlockChainClient, M: MinerService> Dispatcher for FullDispatcher<C
let address = filled.from;
future::done({
let t = Transaction {
nonce: filled.nonce
.or_else(|| miner
.last_nonce(&filled.from)
.map(|nonce| nonce + U256::one()))
.unwrap_or_else(|| client.latest_nonce(&filled.from)),
nonce: Self::fill_nonce(filled.nonce, &filled.from, &miner, &client),
action: filled.to.map_or(Action::Create, Action::Call),
gas: filled.gas,
gas_price: filled.gas_price,
@ -288,18 +296,20 @@ impl LightDispatcher {
}
impl Dispatcher for LightDispatcher {
fn fill_optional_fields(&self, request: TransactionRequest, default_sender: Address)
fn fill_optional_fields(&self, request: TransactionRequest, default_sender: Address, force_nonce: bool)
-> BoxFuture<FilledTransactionRequest, Error>
{
const DEFAULT_GAS_PRICE: U256 = U256([0, 0, 0, 21_000_000]);
let gas_limit = self.client.best_block_header().gas_limit();
let request_gas_price = request.gas_price.clone();
let request_nonce = request.nonce.clone();
let from = request.from.unwrap_or(default_sender);
let with_gas_price = move |gas_price| {
let request = request;
FilledTransactionRequest {
from: request.from.unwrap_or(default_sender),
from: from.clone(),
used_default_from: request.from.is_none(),
to: request.to,
nonce: request.nonce,
@ -312,7 +322,7 @@ impl Dispatcher for LightDispatcher {
};
// fast path for known gas price.
match request_gas_price {
let gas_price = match request_gas_price {
Some(gas_price) => future::ok(with_gas_price(gas_price)).boxed(),
None => fetch_gas_price_corpus(
self.sync.clone(),
@ -323,6 +333,20 @@ impl Dispatcher for LightDispatcher {
Some(median) => future::ok(*median),
None => future::ok(DEFAULT_GAS_PRICE), // fall back to default on error.
}).map(with_gas_price).boxed()
};
match (request_nonce, force_nonce) {
(_, false) | (Some(_), true) => gas_price,
(None, true) => {
let next_nonce = self.next_nonce(from);
gas_price.and_then(move |mut filled| next_nonce
.map_err(|_| errors::no_light_peers())
.map(move |nonce| {
filled.nonce = Some(nonce);
filled
})
).boxed()
},
}
}
@ -563,12 +587,12 @@ pub fn from_rpc<D>(payload: RpcConfirmationPayload, default_account: Address, di
{
match payload {
RpcConfirmationPayload::SendTransaction(request) => {
dispatcher.fill_optional_fields(request.into(), default_account)
dispatcher.fill_optional_fields(request.into(), default_account, false)
.map(ConfirmationPayload::SendTransaction)
.boxed()
},
RpcConfirmationPayload::SignTransaction(request) => {
dispatcher.fill_optional_fields(request.into(), default_account)
dispatcher.fill_optional_fields(request.into(), default_account, false)
.map(ConfirmationPayload::SignTransaction)
.boxed()
},

View File

@ -115,7 +115,7 @@ impl<D: Dispatcher + 'static> Personal for PersonalClient<D> {
Err(e) => return future::err(e).boxed(),
};
dispatcher.fill_optional_fields(request.into(), default)
dispatcher.fill_optional_fields(request.into(), default, false)
.and_then(move |filled| {
let condition = filled.condition.clone().map(Into::into);
dispatcher.sign(accounts, filled, SignWith::Password(password))

View File

@ -27,7 +27,7 @@ use jsonrpc_core::Error;
use v1::helpers::{
errors, oneshot,
DefaultAccount,
SIGNING_QUEUE_LIMIT, SigningQueue, ConfirmationPromise, ConfirmationResult, SignerService
SIGNING_QUEUE_LIMIT, SigningQueue, ConfirmationPromise, ConfirmationResult, SignerService,
};
use v1::helpers::dispatch::{self, Dispatcher};
use v1::helpers::accounts::unwrap_provider;
@ -137,6 +137,12 @@ impl<D: Dispatcher + 'static> SigningQueueClient<D> {
impl<D: Dispatcher + 'static> ParitySigning for SigningQueueClient<D> {
type Metadata = Metadata;
fn compose_transaction(&self, meta: Metadata, transaction: RpcTransactionRequest) -> BoxFuture<RpcTransactionRequest, Error> {
let accounts = try_bf!(self.account_provider());
let default_account = accounts.dapp_default_address(meta.dapp_id().into()).ok().unwrap_or_default();
self.dispatcher.fill_optional_fields(transaction.into(), default_account, true).map(Into::into).boxed()
}
fn post_sign(&self, meta: Metadata, address: RpcH160, data: RpcBytes) -> BoxFuture<RpcEither<RpcU256, RpcConfirmationResponse>, Error> {
let pending = self.pending.clone();
self.dispatch(

View File

@ -111,6 +111,12 @@ impl<D: Dispatcher + 'static> EthSigning for SigningUnsafeClient<D>
impl<D: Dispatcher + 'static> ParitySigning for SigningUnsafeClient<D> {
type Metadata = Metadata;
fn compose_transaction(&self, meta: Metadata, transaction: RpcTransactionRequest) -> BoxFuture<RpcTransactionRequest, Error> {
let accounts = try_bf!(self.account_provider());
let default_account = accounts.dapp_default_address(meta.dapp_id().into()).ok().unwrap_or_default();
self.dispatcher.fill_optional_fields(transaction.into(), default_account, true).map(Into::into).boxed()
}
fn decrypt_message(&self, _: Metadata, address: RpcH160, data: RpcBytes) -> BoxFuture<RpcBytes, Error> {
self.handle(RpcConfirmationPayload::Decrypt((address.clone(), data).into()), address.into())
.then(|res| match res {

View File

@ -198,7 +198,7 @@ fn rpc_parity_set_hash_content() {
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_hashContent", "params":["https://ethcore.io/assets/images/ethcore-black-horizontal.png"], "id": 1}"#;
let request = r#"{"jsonrpc": "2.0", "method": "parity_hashContent", "params":["https://parity.io/assets/images/ethcore-black-horizontal.png"], "id": 1}"#;
let response = r#"{"jsonrpc":"2.0","result":"0x2be00befcf008bc0e7d9cdefc194db9c75352e8632f48498b5a6bfce9f02c88e","id":1}"#;
assert_eq!(io.handle_request_sync(request), Some(response.to_owned()));

View File

@ -439,3 +439,29 @@ fn should_add_decryption_to_the_queue() {
let res = promise.wait().unwrap();
assert_eq!(res, Some(response.to_owned()));
}
#[test]
fn should_compose_transaction() {
// given
let tester = eth_signing();
let acc = Random.generate().unwrap();
assert_eq!(tester.signer.requests().len(), 0);
let from = format!("{:?}", acc.address());
// when
let request = r#"{
"jsonrpc": "2.0",
"method": "parity_composeTransaction",
"params": [{"from":"0x"#.to_owned() + &from + r#"","value":"0x5"}],
"id": 1
}"#;
let response = r#"{"jsonrpc":"2.0","result":{"condition":null,"data":"0x","from":"0x"#.to_owned()
+ &from
+ r#"","gas":"0x5208","gasPrice":"0x4a817c800","nonce":"0x0","to":null,"value":"0x5"},"id":1}"#;
// then
let res = tester.io.handle_request(&request).wait().unwrap();
assert_eq!(res, Some(response.to_owned()));
}

View File

@ -25,6 +25,11 @@ build_rpc_trait! {
pub trait ParitySigning {
type Metadata;
/// Given partial transaction request produces transaction with all fields filled in.
/// Such transaction can be then signed externally.
#[rpc(meta, name = "parity_composeTransaction")]
fn compose_transaction(&self, Self::Metadata, TransactionRequest) -> BoxFuture<TransactionRequest, Error>;
/// Posts sign request asynchronously.
/// Will return a confirmation ID for later use with check_transaction.
#[rpc(meta, name = "parity_postSign")]

View File

@ -1,7 +1,7 @@
[package]
authors = ["Ethcore <admin@ethcore.io>"]
authors = ["Ethcore <admin@parity.io>"]
description = "Parity Cli Tool"
homepage = "http://ethcore.io"
homepage = "http://parity.io"
license = "GPL-3.0"
name = "rpc-cli"
version = "1.4.0"

View File

@ -35,6 +35,7 @@ use std::fs::File;
const DB_BACKGROUND_FLUSHES: i32 = 2;
const DB_BACKGROUND_COMPACTIONS: i32 = 2;
const DB_WRITE_BUFFER_SIZE: usize = 2048 * 1000;
/// Required length of prefixes.
pub const PREFIX_LEN: usize = 12;
@ -440,6 +441,7 @@ fn col_config(col: u32, config: &DatabaseConfig) -> Options {
opts.set_compaction_style(DBCompactionStyle::DBUniversalCompaction);
opts.set_target_file_size_base(config.compaction.initial_file_size);
opts.set_target_file_size_multiplier(config.compaction.file_size_multiplier);
opts.set_db_write_buffer_size(DB_WRITE_BUFFER_SIZE);
let col_opt = config.columns.map(|_| col);
@ -487,6 +489,7 @@ impl Database {
opts.set_max_open_files(config.max_open_files);
opts.create_if_missing(true);
opts.set_use_fsync(false);
opts.set_db_write_buffer_size(DB_WRITE_BUFFER_SIZE);
opts.set_max_background_flushes(DB_BACKGROUND_FLUSHES);
opts.set_max_background_compactions(DB_BACKGROUND_COMPACTIONS);