From 40d794ddfd736d7c8343a7a4b6a3e353cc1069ed Mon Sep 17 00:00:00 2001 From: "Denis S. Soldatov aka General-Beck" Date: Sat, 29 Oct 2016 01:47:05 +0700 Subject: [PATCH 01/42] Update gitlab-ci --- .gitlab-ci.yml | 4 ++-- 1 file changed, 2 insertions(+), 2 deletions(-) diff --git a/.gitlab-ci.yml b/.gitlab-ci.yml index e16350325..424f933fe 100644 --- a/.gitlab-ci.yml +++ b/.gitlab-ci.yml @@ -380,8 +380,8 @@ test-windows: before_script: - git submodule update --init --recursive script: - - export RUST_BACKTRACE=1 - - ./test.sh --verbose + - set RUST_BACKTRACE=1 + - PowerShell ./test.sh --verbose tags: - rust-windows dependencies: From 3e3230aa34d52311a047a6f0e6d744b57d20706d Mon Sep 17 00:00:00 2001 From: GitLab Build Bot Date: Fri, 28 Oct 2016 18:50:17 +0000 Subject: [PATCH 02/42] [ci skip] js-precompiled 20161028-184917 --- Cargo.lock | 2 +- 1 file changed, 1 insertion(+), 1 deletion(-) diff --git a/Cargo.lock b/Cargo.lock index b9d989fbd..ed9b0330b 100644 --- a/Cargo.lock +++ b/Cargo.lock @@ -1213,7 +1213,7 @@ dependencies = [ [[package]] name = "parity-ui-precompiled" version = "1.4.0" -source = "git+https://github.com/ethcore/js-precompiled.git#ba726039185238d6fd604f092b089a7d52c0f436" +source = "git+https://github.com/ethcore/js-precompiled.git#ed68f673cf7bb576c1a7d1c4328e44f28dea7713" dependencies = [ "parity-dapps-glue 1.4.0 (registry+https://github.com/rust-lang/crates.io-index)", ] From c61526f8d51efe6a02d4196a1da5872986ec686e Mon Sep 17 00:00:00 2001 From: Jaco Greeff Date: Sat, 29 Oct 2016 09:55:55 +0200 Subject: [PATCH 03/42] Eslint fixes (package upgrade) (#2957) --- js/src/dapps/githubhint/Application/application.js | 2 +- js/src/modals/FirstRun/firstRun.js | 2 +- 2 files changed, 2 insertions(+), 2 deletions(-) diff --git a/js/src/dapps/githubhint/Application/application.js b/js/src/dapps/githubhint/Application/application.js index ea7e760c5..8eb3902d3 100644 --- a/js/src/dapps/githubhint/Application/application.js +++ b/js/src/dapps/githubhint/Application/application.js @@ -151,7 +151,7 @@ export default class Application extends Component { let urlError = null; if (url && url.length) { - var re = /^https?:\/\/(?:www\.|(?!www))[^\s\.]+\.[^\s]{2,}/g; + const re = /^https?:\/\/(?:www\.|(?!www))[^\s\.]+\.[^\s]{2,}/g; // eslint-disable-line urlError = re.test(url) ? null : 'not matching rexex'; diff --git a/js/src/modals/FirstRun/firstRun.js b/js/src/modals/FirstRun/firstRun.js index e5033f9e6..2ba8cbbe8 100644 --- a/js/src/modals/FirstRun/firstRun.js +++ b/js/src/modals/FirstRun/firstRun.js @@ -122,7 +122,7 @@ export default class FirstRun extends Component { icon={ } label='Close' onClick={ this.onClose } /> - ); + ); } } From e1cf6f7dd072e24d36297e6fcc1691d8ed0d0a11 Mon Sep 17 00:00:00 2001 From: GitLab Build Bot Date: Sat, 29 Oct 2016 07:58:45 +0000 Subject: [PATCH 04/42] [ci skip] js-precompiled 20161029-075744 --- Cargo.lock | 2 +- 1 file changed, 1 insertion(+), 1 deletion(-) diff --git a/Cargo.lock b/Cargo.lock index ed9b0330b..8d040eade 100644 --- a/Cargo.lock +++ b/Cargo.lock @@ -1213,7 +1213,7 @@ dependencies = [ [[package]] name = "parity-ui-precompiled" version = "1.4.0" -source = "git+https://github.com/ethcore/js-precompiled.git#ed68f673cf7bb576c1a7d1c4328e44f28dea7713" +source = "git+https://github.com/ethcore/js-precompiled.git#93753cb4d50f85eca91e024196235c6f0deb3bd4" dependencies = [ "parity-dapps-glue 1.4.0 (registry+https://github.com/rust-lang/crates.io-index)", ] From 65c985bef3a6d2ffa1523f3699f941940b79fafa Mon Sep 17 00:00:00 2001 From: Jaco Greeff Date: Sat, 29 Oct 2016 13:04:47 +0200 Subject: [PATCH 05/42] Gavcoin event display updates (#2956) * Mapp all known addresses * Display timestamp in event log * Shorten addresses * Display "Pending" timestamps as well * Pending/Loading with empty timestamp --- .../dapps/gavcoin/Application/application.js | 12 ++--- js/src/dapps/gavcoin/Events/Event/event.js | 44 +++++++++++++++---- js/src/dapps/gavcoin/Events/events.css | 9 ++-- js/src/dapps/gavcoin/Events/events.js | 10 ++--- js/src/dapps/gavcoin/format/index.js | 4 ++ 5 files changed, 55 insertions(+), 24 deletions(-) diff --git a/js/src/dapps/gavcoin/Application/application.js b/js/src/dapps/gavcoin/Application/application.js index 1ae5d870a..c5eda9db8 100644 --- a/js/src/dapps/gavcoin/Application/application.js +++ b/js/src/dapps/gavcoin/Application/application.js @@ -53,6 +53,7 @@ export default class Application extends Component { action: null, address: null, accounts: [], + accountsInfo: {}, blockNumber: new BigNumber(-1), ethBalance: new BigNumber(0), gavBalance: new BigNumber(0), @@ -68,7 +69,7 @@ export default class Application extends Component { } render () { - const { accounts, address, blockNumber, gavBalance, loading, price, remaining, totalSupply } = this.state; + const { accounts, accountsInfo, address, blockNumber, gavBalance, loading, price, remaining, totalSupply } = this.state; if (loading) { return ( @@ -93,7 +94,7 @@ export default class Application extends Component { gavBalance={ gavBalance } onAction={ this.onAction } /> + accountsInfo={ accountsInfo } /> ); } @@ -216,8 +217,8 @@ export default class Application extends Component { api.personal.accountsInfo() ]); }) - .then(([address, addresses, infos]) => { - infos = infos || {}; + .then(([address, addresses, accountsInfo]) => { + accountsInfo = accountsInfo || {}; console.log(`gavcoin was found at ${address}`); const contract = api.newContract(abis.gavcoin, address); @@ -226,9 +227,10 @@ export default class Application extends Component { loading: false, address, contract, + accountsInfo, instance: contract.instance, accounts: addresses.map((address) => { - const info = infos[address] || {}; + const info = accountsInfo[address] || {}; return { address, diff --git a/js/src/dapps/gavcoin/Events/Event/event.js b/js/src/dapps/gavcoin/Events/Event/event.js index 0b4094ac0..c068454f0 100644 --- a/js/src/dapps/gavcoin/Events/Event/event.js +++ b/js/src/dapps/gavcoin/Events/Event/event.js @@ -14,10 +14,11 @@ // You should have received a copy of the GNU General Public License // along with Parity. If not, see . +import moment from 'moment'; import React, { Component, PropTypes } from 'react'; import IdentityIcon from '../../IdentityIcon'; -import { formatBlockNumber, formatCoins, formatEth } from '../../format'; +import { formatCoins, formatEth, formatHash } from '../../format'; import styles from '../events.css'; @@ -27,7 +28,8 @@ const EMPTY_COLUMN = ( export default class Event extends Component { static contextTypes = { - accounts: PropTypes.array.isRequired + accountsInfo: PropTypes.object.isRequired, + api: PropTypes.object.isRequired } static propTypes = { @@ -38,14 +40,23 @@ export default class Event extends Component { toAddress: PropTypes.string } + state = { + block: null + } + + componentDidMount () { + this.loadBlock(); + } + render () { const { event, fromAddress, toAddress, price, value } = this.props; - const { blockNumber, state, type } = event; + const { block } = this.state; + const { state, type } = event; const cls = `${styles.event} ${styles[state]} ${styles[type.toLowerCase()]}`; return ( - { this.renderBlockNumber(blockNumber) } + { this.renderTimestamp(block) } { this.renderType(type) } { this.renderValue(value) } { this.renderPrice(price) } @@ -55,10 +66,10 @@ export default class Event extends Component { ); } - renderBlockNumber (blockNumber) { + renderTimestamp (block) { return ( - { formatBlockNumber(blockNumber) } + { !block ? ' ' : moment(block.timestamp).fromNow() } ); } @@ -77,8 +88,8 @@ export default class Event extends Component { } renderAddressName (address) { - const { accounts } = this.context; - const account = accounts.find((_account) => _account.address === address); + const { accountsInfo } = this.context; + const account = accountsInfo[address]; if (account && account.name) { return ( @@ -90,7 +101,7 @@ export default class Event extends Component { return (
- { address } + { formatHash(address) }
); } @@ -126,4 +137,19 @@ export default class Event extends Component { ); } + + loadBlock () { + const { api } = this.context; + const { event } = this.props; + + if (!event || !event.blockNumber || event.blockNumber.eq(0)) { + return; + } + + api.eth + .getBlockByNumber(event.blockNumber) + .then((block) => { + this.setState({ block }); + }); + } } diff --git a/js/src/dapps/gavcoin/Events/events.css b/js/src/dapps/gavcoin/Events/events.css index 9be9b37af..cf9184744 100644 --- a/js/src/dapps/gavcoin/Events/events.css +++ b/js/src/dapps/gavcoin/Events/events.css @@ -16,18 +16,20 @@ */ .events { padding: 4em 2em; + text-align: center; } .list { - width: 100%; + margin: 0 auto; border: none; border-spacing: 0; + text-align: left; } .list td { vertical-align: top; - padding: 4px 0.5em; - max-height: 32px; + padding: 0.25em 1em; + max-height: 1.5em; } .event { @@ -38,7 +40,6 @@ .blocknumber, .ethvalue, .gavvalue { - font-family: 'Roboto Mono', monospace; } .blocknumber, diff --git a/js/src/dapps/gavcoin/Events/events.js b/js/src/dapps/gavcoin/Events/events.js index ba71d6541..97dac30bb 100644 --- a/js/src/dapps/gavcoin/Events/events.js +++ b/js/src/dapps/gavcoin/Events/events.js @@ -27,7 +27,7 @@ import styles from './events.css'; export default class Events extends Component { static childContextTypes = { - accounts: PropTypes.array + accountsInfo: PropTypes.object } static contextTypes = { @@ -36,7 +36,7 @@ export default class Events extends Component { } static propTypes = { - accounts: PropTypes.array + accountsInfo: PropTypes.object.isRequired } state = { @@ -84,11 +84,9 @@ export default class Events extends Component { } getChildContext () { - const { accounts } = this.props; + const { accountsInfo } = this.props; - return { - accounts - }; + return { accountsInfo }; } setupFilters () { diff --git a/js/src/dapps/gavcoin/format/index.js b/js/src/dapps/gavcoin/format/index.js index 5e32012d0..ee554bb60 100644 --- a/js/src/dapps/gavcoin/format/index.js +++ b/js/src/dapps/gavcoin/format/index.js @@ -50,3 +50,7 @@ export function formatCoins (amount, decimals = 6) { export function formatEth (eth, decimals = 3) { return api.util.fromWei(eth).toFormat(decimals); } + +export function formatHash (hash) { + return `${hash.substr(0, 10)}...${hash.substr(-8)}`; +} From 290ed3343f52e252b91d49edfdc94b10765c3776 Mon Sep 17 00:00:00 2001 From: GitLab Build Bot Date: Sat, 29 Oct 2016 11:06:59 +0000 Subject: [PATCH 06/42] [ci skip] js-precompiled 20161029-110604 --- Cargo.lock | 2 +- 1 file changed, 1 insertion(+), 1 deletion(-) diff --git a/Cargo.lock b/Cargo.lock index 8d040eade..870d39fa1 100644 --- a/Cargo.lock +++ b/Cargo.lock @@ -1213,7 +1213,7 @@ dependencies = [ [[package]] name = "parity-ui-precompiled" version = "1.4.0" -source = "git+https://github.com/ethcore/js-precompiled.git#93753cb4d50f85eca91e024196235c6f0deb3bd4" +source = "git+https://github.com/ethcore/js-precompiled.git#d35381a1442215c9b21f472c2a644d1ecbe43336" dependencies = [ "parity-dapps-glue 1.4.0 (registry+https://github.com/rust-lang/crates.io-index)", ] From 9e82eeccfeb05fc99bdd6d3ba332c0562b10e586 Mon Sep 17 00:00:00 2001 From: Arkadiy Paronyan Date: Sat, 29 Oct 2016 13:07:06 +0200 Subject: [PATCH 07/42] Snapshot sync improvements (#2960) * Status packet timeout * Snapshot collection state * Pause snapshot download * Updated tests --- sync/src/api.rs | 2 +- sync/src/chain.rs | 186 ++++++++++++++++++++++++++++--------- sync/src/snapshot.rs | 5 +- sync/src/tests/chain.rs | 5 + sync/src/tests/helpers.rs | 14 ++- sync/src/tests/snapshot.rs | 18 ++-- 6 files changed, 174 insertions(+), 56 deletions(-) diff --git a/sync/src/api.rs b/sync/src/api.rs index 67a81237a..abe18c3cd 100644 --- a/sync/src/api.rs +++ b/sync/src/api.rs @@ -58,7 +58,7 @@ impl Default for SyncConfig { network_id: U256::from(1), subprotocol_name: *b"eth", fork_block: None, - warp_sync: true, + warp_sync: false, } } } diff --git a/sync/src/chain.rs b/sync/src/chain.rs index d18adb6ea..06949682b 100644 --- a/sync/src/chain.rs +++ b/sync/src/chain.rs @@ -123,6 +123,7 @@ const MAX_NEW_BLOCK_AGE: BlockNumber = 20; const MAX_TRANSACTION_SIZE: usize = 300*1024; // Min number of blocks to be behind for a snapshot sync const SNAPSHOT_RESTORE_THRESHOLD: BlockNumber = 100000; +const SNAPSHOT_MIN_PEERS: usize = 3; const STATUS_PACKET: u8 = 0x00; const NEW_BLOCK_HASHES_PACKET: u8 = 0x01; @@ -147,21 +148,27 @@ const SNAPSHOT_DATA_PACKET: u8 = 0x14; pub const SNAPSHOT_SYNC_PACKET_COUNT: u8 = 0x15; -const HEADERS_TIMEOUT_SEC: f64 = 15f64; -const BODIES_TIMEOUT_SEC: f64 = 10f64; -const RECEIPTS_TIMEOUT_SEC: f64 = 10f64; -const FORK_HEADER_TIMEOUT_SEC: f64 = 3f64; -const SNAPSHOT_MANIFEST_TIMEOUT_SEC: f64 = 3f64; -const SNAPSHOT_DATA_TIMEOUT_SEC: f64 = 60f64; +const MAX_SNAPSHOT_CHUNKS_DOWNLOAD_AHEAD: usize = 3; + +const WAIT_PEERS_TIMEOUT_SEC: u64 = 5; +const STATUS_TIMEOUT_SEC: u64 = 5; +const HEADERS_TIMEOUT_SEC: u64 = 15; +const BODIES_TIMEOUT_SEC: u64 = 10; +const RECEIPTS_TIMEOUT_SEC: u64 = 10; +const FORK_HEADER_TIMEOUT_SEC: u64 = 3; +const SNAPSHOT_MANIFEST_TIMEOUT_SEC: u64 = 3; +const SNAPSHOT_DATA_TIMEOUT_SEC: u64 = 60; #[derive(Copy, Clone, Eq, PartialEq, Debug)] /// Sync state pub enum SyncState { - /// Waiting for pv64 peers to start snapshot syncing + /// Collecting enough peers to start syncing. + WaitingPeers, + /// Waiting for snapshot manifest download SnapshotManifest, /// Downloading snapshot data SnapshotData, - /// Waiting for snapshot restoration to complete + /// Waiting for snapshot restoration progress. SnapshotWaiting, /// Downloading new blocks Blocks, @@ -276,7 +283,7 @@ struct PeerInfo { /// Holds requested snapshot chunk hash if any. asking_snapshot_data: Option, /// Request timestamp - ask_time: f64, + ask_time: u64, /// Holds a set of transactions recently sent to this peer to avoid spamming. last_sent_transactions: HashSet, /// Pending request is expired and result should be ignored @@ -324,10 +331,13 @@ pub struct ChainSync { network_id: U256, /// Optional fork block to check fork_block: Option<(BlockNumber, H256)>, - /// Snapshot sync allowed. - snapshot_sync_enabled: bool, /// Snapshot downloader. snapshot: Snapshot, + /// Connected peers pending Status message. + /// Value is request timestamp. + handshaking_peers: HashMap, + /// Sync start timestamp. Measured when first peer is connected + sync_start_time: Option, } type RlpResponseResult = Result, PacketDecodeError>; @@ -337,20 +347,21 @@ impl ChainSync { pub fn new(config: SyncConfig, chain: &BlockChainClient) -> ChainSync { let chain_info = chain.chain_info(); let mut sync = ChainSync { - state: SyncState::Idle, + state: if config.warp_sync { SyncState::WaitingPeers } else { SyncState::Idle }, starting_block: chain.chain_info().best_block_number, highest_block: None, peers: HashMap::new(), + handshaking_peers: HashMap::new(), active_peers: HashSet::new(), new_blocks: BlockDownloader::new(false, &chain_info.best_block_hash, chain_info.best_block_number), old_blocks: None, last_sent_block_number: 0, network_id: config.network_id, fork_block: config.fork_block, - snapshot_sync_enabled: config.warp_sync, snapshot: Snapshot::new(), + sync_start_time: None, }; - sync.init_downloaders(chain); + sync.update_targets(chain); sync } @@ -442,20 +453,67 @@ impl ChainSync { self.active_peers.remove(&peer_id); } - fn start_snapshot_sync(&mut self, io: &mut SyncIo, peer_id: PeerId) { + fn maybe_start_snapshot_sync(&mut self, io: &mut SyncIo) { + if self.state != SyncState::WaitingPeers { + return; + } + let best_block = io.chain().chain_info().best_block_number; + + let (best_hash, max_peers, snapshot_peers) = { + //collect snapshot infos from peers + let snapshots = self.peers.iter() + .filter(|&(_, p)| p.is_allowed() && p.snapshot_number.map_or(false, |sn| best_block < sn && (sn - best_block) > SNAPSHOT_RESTORE_THRESHOLD)) + .filter_map(|(p, peer)| peer.snapshot_hash.map(|hash| (p, hash.clone()))); + + let mut snapshot_peers = HashMap::new(); + let mut max_peers: usize = 0; + let mut best_hash = None; + for (p, hash) in snapshots { + let peers = snapshot_peers.entry(hash).or_insert_with(Vec::new); + peers.push(*p); + if peers.len() > max_peers { + max_peers = peers.len(); + best_hash = Some(hash); + } + } + (best_hash, max_peers, snapshot_peers) + }; + + let timeout = self.sync_start_time.map_or(false, |t| ((time::precise_time_ns() - t) / 1_000_000_000) > WAIT_PEERS_TIMEOUT_SEC); + + if let (Some(hash), Some(peers)) = (best_hash, best_hash.map_or(None, |h| snapshot_peers.get(&h))) { + if max_peers >= SNAPSHOT_MIN_PEERS { + trace!(target: "sync", "Starting confirmed snapshot sync {:?} with {:?}", hash, peers); + self.start_snapshot_sync(io, peers); + } else if timeout { + trace!(target: "sync", "Starting unconfirmed snapshot sync {:?} with {:?}", hash, peers); + self.start_snapshot_sync(io, peers); + } + } else if timeout { + trace!(target: "sync", "No snapshots found, starting full sync"); + self.state = SyncState::Idle; + self.continue_sync(io); + } + } + + fn start_snapshot_sync(&mut self, io: &mut SyncIo, peers: &[PeerId]) { self.snapshot.clear(); - self.request_snapshot_manifest(io, peer_id); + for p in peers { + if self.peers.get(p).map_or(false, |p| p.asking == PeerAsking::Nothing) { + self.request_snapshot_manifest(io, *p); + } + } self.state = SyncState::SnapshotManifest; } /// Restart sync disregarding the block queue status. May end up re-downloading up to QUEUE_SIZE blocks pub fn restart(&mut self, io: &mut SyncIo) { - self.init_downloaders(io.chain()); + self.update_targets(io.chain()); self.reset_and_continue(io); } - /// Restart sync after bad block has been detected. May end up re-downloading up to QUEUE_SIZE blocks - fn init_downloaders(&mut self, chain: &BlockChainClient) { + /// Update sync after the blockchain has been changed externally. + pub fn update_targets(&mut self, chain: &BlockChainClient) { // Do not assume that the block queue/chain still has our last_imported_block let chain = chain.chain_info(); self.new_blocks = BlockDownloader::new(false, &chain.best_block_hash, chain.best_block_number); @@ -475,6 +533,7 @@ impl ChainSync { /// Called by peer to report status fn on_peer_status(&mut self, io: &mut SyncIo, peer_id: PeerId, r: &UntrustedRlp) -> Result<(), PacketDecodeError> { + self.handshaking_peers.remove(&peer_id); let protocol_version: u8 = try!(r.val_at(0)); let warp_protocol = io.protocol_version(&WARP_SYNC_PROTOCOL_ID, peer_id) != 0; let peer = PeerInfo { @@ -486,7 +545,7 @@ impl ChainSync { asking: PeerAsking::Nothing, asking_blocks: Vec::new(), asking_hash: None, - ask_time: 0f64, + ask_time: 0, last_sent_transactions: HashSet::new(), expired: false, confirmation: if self.fork_block.is_none() { ForkConfirmation::Confirmed } else { ForkConfirmation::Unconfirmed }, @@ -496,7 +555,12 @@ impl ChainSync { block_set: None, }; - trace!(target: "sync", "New peer {} (protocol: {}, network: {:?}, difficulty: {:?}, latest:{}, genesis:{})", peer_id, peer.protocol_version, peer.network_id, peer.difficulty, peer.latest_hash, peer.genesis); + if self.sync_start_time.is_none() { + self.sync_start_time = Some(time::precise_time_ns()); + } + + trace!(target: "sync", "New peer {} (protocol: {}, network: {:?}, difficulty: {:?}, latest:{}, genesis:{}, snapshot:{:?})", + peer_id, peer.protocol_version, peer.network_id, peer.difficulty, peer.latest_hash, peer.genesis, peer.snapshot_number); if io.is_expired() { trace!(target: "sync", "Status packet from expired session {}:{}", peer_id, io.peer_info(peer_id)); return Ok(()); @@ -578,7 +642,7 @@ impl ChainSync { } let item_count = r.item_count(); trace!(target: "sync", "{} -> BlockHeaders ({} entries), state = {:?}, set = {:?}", peer_id, item_count, self.state, block_set); - if self.state == SyncState::Idle && self.old_blocks.is_none() { + if (self.state == SyncState::Idle || self.state == SyncState::WaitingPeers) && self.old_blocks.is_none() { trace!(target: "sync", "Ignored unexpected block headers"); self.continue_sync(io); return Ok(()); @@ -875,7 +939,7 @@ impl ChainSync { } self.clear_peer_download(peer_id); if !self.reset_peer_asking(peer_id, PeerAsking::SnapshotManifest) || self.state != SyncState::SnapshotManifest { - trace!(target: "sync", "{}: Ignored unexpected manifest", peer_id); + trace!(target: "sync", "{}: Ignored unexpected/expired manifest", peer_id); self.continue_sync(io); return Ok(()); } @@ -918,7 +982,7 @@ impl ChainSync { match io.snapshot_service().status() { RestorationStatus::Inactive | RestorationStatus::Failed => { trace!(target: "sync", "{}: Snapshot restoration aborted", peer_id); - self.state = SyncState::Idle; + self.state = SyncState::WaitingPeers; self.snapshot.clear(); self.continue_sync(io); return Ok(()); @@ -960,6 +1024,7 @@ impl ChainSync { /// Called by peer when it is disconnecting pub fn on_peer_aborting(&mut self, io: &mut SyncIo, peer: PeerId) { trace!(target: "sync", "== Disconnecting {}: {}", peer, io.peer_info(peer)); + self.handshaking_peers.remove(&peer); if self.peers.contains_key(&peer) { debug!(target: "sync", "Disconnected {}", peer); self.clear_peer_download(peer); @@ -975,12 +1040,14 @@ impl ChainSync { if let Err(e) = self.send_status(io, peer) { debug!(target:"sync", "Error sending status request: {:?}", e); io.disable_peer(peer); + } else { + self.handshaking_peers.insert(peer, time::precise_time_ns()); } } /// Resume downloading fn continue_sync(&mut self, io: &mut SyncIo) { - if self.state != SyncState::Waiting && self.state != SyncState::SnapshotWaiting + if (self.state == SyncState::Blocks || self.state == SyncState::NewBlocks || self.state == SyncState::Idle) && !self.peers.values().any(|p| p.asking != PeerAsking::Nothing && p.block_set != Some(BlockSet::OldBlocks) && p.can_sync()) { self.complete_sync(io); } @@ -1040,11 +1107,9 @@ impl ChainSync { let higher_difficulty = peer_difficulty.map_or(true, |pd| pd > syncing_difficulty); if force || self.state == SyncState::NewBlocks || higher_difficulty || self.old_blocks.is_some() { match self.state { - SyncState::Idle if self.snapshot_sync_enabled - && chain_info.best_block_number < peer_snapshot_number - && (peer_snapshot_number - chain_info.best_block_number) > SNAPSHOT_RESTORE_THRESHOLD => { - trace!(target: "sync", "Starting snapshot sync: {} vs {}", peer_snapshot_number, chain_info.best_block_number); - self.start_snapshot_sync(io, peer_id); + SyncState::WaitingPeers => { + trace!(target: "sync", "Checking snapshot sync: {} vs {}", peer_snapshot_number, chain_info.best_block_number); + self.maybe_start_snapshot_sync(io); }, SyncState::Idle | SyncState::Blocks | SyncState::NewBlocks => { if io.chain().queue_info().is_full() { @@ -1070,6 +1135,13 @@ impl ChainSync { } }, SyncState::SnapshotData => { + if let RestorationStatus::Ongoing { state_chunks: _, block_chunks: _, state_chunks_done, block_chunks_done, } = io.snapshot_service().status() { + if self.snapshot.done_chunks() - (state_chunks_done + block_chunks_done) as usize > MAX_SNAPSHOT_CHUNKS_DOWNLOAD_AHEAD { + trace!(target: "sync", "Snapshot queue full, pausing sync"); + self.state = SyncState::SnapshotWaiting; + return; + } + } if peer_snapshot_hash.is_some() && peer_snapshot_hash == self.snapshot.snapshot_hash() { self.request_snapshot_data(io, peer_id); } @@ -1253,7 +1325,7 @@ impl ChainSync { warn!(target:"sync", "Asking {:?} while requesting {:?}", peer.asking, asking); } peer.asking = asking; - peer.ask_time = time::precise_time_s(); + peer.ask_time = time::precise_time_ns(); let result = if packet_id >= ETH_PACKET_COUNT { sync.send_protocol(WARP_SYNC_PROTOCOL_ID, peer_id, packet_id, packet) } else { @@ -1590,17 +1662,18 @@ impl ChainSync { #[cfg_attr(feature="dev", allow(match_same_arms))] pub fn maintain_peers(&mut self, io: &mut SyncIo) { - let tick = time::precise_time_s(); + let tick = time::precise_time_ns(); let mut aborting = Vec::new(); for (peer_id, peer) in &self.peers { + let elapsed = (tick - peer.ask_time) / 1_000_000_000; let timeout = match peer.asking { - PeerAsking::BlockHeaders => (tick - peer.ask_time) > HEADERS_TIMEOUT_SEC, - PeerAsking::BlockBodies => (tick - peer.ask_time) > BODIES_TIMEOUT_SEC, - PeerAsking::BlockReceipts => (tick - peer.ask_time) > RECEIPTS_TIMEOUT_SEC, + PeerAsking::BlockHeaders => elapsed > HEADERS_TIMEOUT_SEC, + PeerAsking::BlockBodies => elapsed > BODIES_TIMEOUT_SEC, + PeerAsking::BlockReceipts => elapsed > RECEIPTS_TIMEOUT_SEC, PeerAsking::Nothing => false, - PeerAsking::ForkHeader => (tick - peer.ask_time) > FORK_HEADER_TIMEOUT_SEC, - PeerAsking::SnapshotManifest => (tick - peer.ask_time) > SNAPSHOT_MANIFEST_TIMEOUT_SEC, - PeerAsking::SnapshotData => (tick - peer.ask_time) > SNAPSHOT_DATA_TIMEOUT_SEC, + PeerAsking::ForkHeader => elapsed > FORK_HEADER_TIMEOUT_SEC, + PeerAsking::SnapshotManifest => elapsed > SNAPSHOT_MANIFEST_TIMEOUT_SEC, + PeerAsking::SnapshotData => elapsed > SNAPSHOT_DATA_TIMEOUT_SEC, }; if timeout { trace!(target:"sync", "Timeout {}", peer_id); @@ -1611,16 +1684,42 @@ impl ChainSync { for p in aborting { self.on_peer_aborting(io, p); } + + // Check for handshake timeouts + for (peer, ask_time) in &self.handshaking_peers { + let elapsed = (tick - ask_time) / 1_000_000_000; + if elapsed > STATUS_TIMEOUT_SEC { + trace!(target:"sync", "Status timeout {}", peer); + io.disconnect_peer(*peer); + } + } } fn check_resume(&mut self, io: &mut SyncIo) { if self.state == SyncState::Waiting && !io.chain().queue_info().is_full() && self.state == SyncState::Waiting { self.state = SyncState::Blocks; self.continue_sync(io); - } else if self.state == SyncState::SnapshotWaiting && io.snapshot_service().status() == RestorationStatus::Inactive { - trace!(target:"sync", "Snapshot restoration is complete"); - self.restart(io); - self.continue_sync(io); + } else if self.state == SyncState::SnapshotWaiting { + match io.snapshot_service().status() { + RestorationStatus::Inactive => { + trace!(target:"sync", "Snapshot restoration is complete"); + self.restart(io); + self.continue_sync(io); + }, + RestorationStatus::Ongoing { state_chunks: _, block_chunks: _, state_chunks_done, block_chunks_done, } => { + if !self.snapshot.is_complete() && self.snapshot.done_chunks() - (state_chunks_done + block_chunks_done) as usize <= MAX_SNAPSHOT_CHUNKS_DOWNLOAD_AHEAD { + trace!(target:"sync", "Resuming snapshot sync"); + self.state = SyncState::SnapshotData; + self.continue_sync(io); + } + }, + RestorationStatus::Failed => { + trace!(target: "sync", "Snapshot restoration aborted"); + self.state = SyncState::WaitingPeers; + self.snapshot.clear(); + self.continue_sync(io); + }, + } } } @@ -1828,6 +1927,7 @@ impl ChainSync { /// Maintain other peers. Send out any new blocks and transactions pub fn maintain_sync(&mut self, io: &mut SyncIo) { + self.maybe_start_snapshot_sync(io); self.check_resume(io); } @@ -2050,7 +2150,7 @@ mod tests { asking: PeerAsking::Nothing, asking_blocks: Vec::new(), asking_hash: None, - ask_time: 0f64, + ask_time: 0, last_sent_transactions: HashSet::new(), expired: false, confirmation: super::ForkConfirmation::Confirmed, diff --git a/sync/src/snapshot.rs b/sync/src/snapshot.rs index ca9adf220..9f4262105 100644 --- a/sync/src/snapshot.rs +++ b/sync/src/snapshot.rs @@ -113,7 +113,7 @@ impl Snapshot { } pub fn done_chunks(&self) -> usize { - self.total_chunks() - self.completed_chunks.len() + self.completed_chunks.len() } pub fn is_complete(&self) -> bool { @@ -165,6 +165,7 @@ mod test { let mut snapshot = Snapshot::new(); let (manifest, mhash, state_chunks, block_chunks) = test_manifest(); snapshot.reset_to(&manifest, &mhash); + assert_eq!(snapshot.done_chunks(), 0); assert!(snapshot.validate_chunk(&H256::random().to_vec()).is_err()); let requested: Vec = (0..40).map(|_| snapshot.needed_chunk().unwrap()).collect(); @@ -194,6 +195,8 @@ mod test { } assert!(snapshot.is_complete()); + assert_eq!(snapshot.done_chunks(), 40); + assert_eq!(snapshot.done_chunks(), snapshot.total_chunks()); assert_eq!(snapshot.snapshot_hash(), Some(manifest.into_rlp().sha3())); } } diff --git a/sync/src/tests/chain.rs b/sync/src/tests/chain.rs index c54529beb..17c051162 100644 --- a/sync/src/tests/chain.rs +++ b/sync/src/tests/chain.rs @@ -18,6 +18,7 @@ use util::*; use ethcore::client::{TestBlockChainClient, BlockChainClient, BlockID, EachBlockWith}; use chain::{SyncState}; use super::helpers::*; +use SyncConfig; #[test] fn two_peers() { @@ -156,6 +157,10 @@ fn restart() { fn status_empty() { let net = TestNet::new(2); assert_eq!(net.peer(0).sync.read().status().state, SyncState::Idle); + let mut config = SyncConfig::default(); + config.warp_sync = true; + let net = TestNet::new_with_config(2, config); + assert_eq!(net.peer(0).sync.read().status().state, SyncState::WaitingPeers); } #[test] diff --git a/sync/src/tests/helpers.rs b/sync/src/tests/helpers.rs index 202ab4f17..d5e07a936 100644 --- a/sync/src/tests/helpers.rs +++ b/sync/src/tests/helpers.rs @@ -127,20 +127,24 @@ pub struct TestNet { impl TestNet { pub fn new(n: usize) -> TestNet { - Self::new_with_fork(n, None) + Self::new_with_config(n, SyncConfig::default()) } pub fn new_with_fork(n: usize, fork: Option<(BlockNumber, H256)>) -> TestNet { + let mut config = SyncConfig::default(); + config.fork_block = fork; + Self::new_with_config(n, config) + } + + pub fn new_with_config(n: usize, config: SyncConfig) -> TestNet { let mut net = TestNet { peers: Vec::new(), started: false, }; for _ in 0..n { let chain = TestBlockChainClient::new(); - let mut config = SyncConfig::default(); - config.fork_block = fork; let ss = Arc::new(TestSnapshotService::new()); - let sync = ChainSync::new(config, &chain); + let sync = ChainSync::new(config.clone(), &chain); net.peers.push(TestPeer { sync: RwLock::new(sync), snapshot_service: ss, @@ -164,7 +168,7 @@ impl TestNet { for client in 0..self.peers.len() { if peer != client { let mut p = self.peers.get_mut(peer).unwrap(); - p.sync.write().restart(&mut TestIo::new(&mut p.chain, &p.snapshot_service, &mut p.queue, Some(client as PeerId))); + p.sync.write().update_targets(&mut p.chain); p.sync.write().on_peer_connected(&mut TestIo::new(&mut p.chain, &p.snapshot_service, &mut p.queue, Some(client as PeerId)), client as PeerId); } } diff --git a/sync/src/tests/snapshot.rs b/sync/src/tests/snapshot.rs index 813513e84..5d0b21b47 100644 --- a/sync/src/tests/snapshot.rs +++ b/sync/src/tests/snapshot.rs @@ -19,6 +19,7 @@ use ethcore::snapshot::{SnapshotService, ManifestData, RestorationStatus}; use ethcore::header::BlockNumber; use ethcore::client::{EachBlockWith}; use super::helpers::*; +use SyncConfig; pub struct TestSnapshotService { manifest: Option, @@ -122,11 +123,16 @@ impl SnapshotService for TestSnapshotService { #[test] fn snapshot_sync() { ::env_logger::init().ok(); - let mut net = TestNet::new(2); - net.peer_mut(0).snapshot_service = Arc::new(TestSnapshotService::new_with_snapshot(16, H256::new(), 500000)); - net.peer_mut(0).chain.add_blocks(1, EachBlockWith::Nothing); - net.sync_steps(19); // status + manifest + chunks - assert_eq!(net.peer(1).snapshot_service.state_restoration_chunks.lock().len(), net.peer(0).snapshot_service.manifest.as_ref().unwrap().state_hashes.len()); - assert_eq!(net.peer(1).snapshot_service.block_restoration_chunks.lock().len(), net.peer(0).snapshot_service.manifest.as_ref().unwrap().block_hashes.len()); + let mut config = SyncConfig::default(); + config.warp_sync = true; + let mut net = TestNet::new_with_config(5, config); + let snapshot_service = Arc::new(TestSnapshotService::new_with_snapshot(16, H256::new(), 500000)); + for i in 0..4 { + net.peer_mut(i).snapshot_service = snapshot_service.clone(); + net.peer_mut(i).chain.add_blocks(1, EachBlockWith::Nothing); + } + net.sync_steps(50); + assert_eq!(net.peer(4).snapshot_service.state_restoration_chunks.lock().len(), net.peer(0).snapshot_service.manifest.as_ref().unwrap().state_hashes.len()); + assert_eq!(net.peer(4).snapshot_service.block_restoration_chunks.lock().len(), net.peer(0).snapshot_service.manifest.as_ref().unwrap().block_hashes.len()); } From f17cad9dff83a8d9a19af0b294ecb5ec8f456144 Mon Sep 17 00:00:00 2001 From: =?UTF-8?q?Tomasz=20Drwi=C4=99ga?= Date: Sat, 29 Oct 2016 13:08:49 +0200 Subject: [PATCH 08/42] Fixing clippy warnings 2 (#2961) --- ethcore/src/miner/banning_queue.rs | 4 ++-- ethcore/src/miner/transaction_queue.rs | 1 + ethcore/src/snapshot/account.rs | 2 +- parity/informant.rs | 2 +- sync/src/chain.rs | 2 +- util/src/trie/triedb.rs | 2 +- 6 files changed, 7 insertions(+), 6 deletions(-) diff --git a/ethcore/src/miner/banning_queue.rs b/ethcore/src/miner/banning_queue.rs index 0329503bf..f127dc7e8 100644 --- a/ethcore/src/miner/banning_queue.rs +++ b/ethcore/src/miner/banning_queue.rs @@ -130,7 +130,7 @@ impl BanningTransactionQueue { // Ban sender let sender_banned = self.ban_sender(sender); // Ban recipient and codehash - let is_banned = sender_banned || match transaction.action { + let recipient_or_code_banned = match transaction.action { Action::Call(recipient) => { self.ban_recipient(recipient) }, @@ -138,7 +138,7 @@ impl BanningTransactionQueue { self.ban_codehash(transaction.data.sha3()) }, }; - is_banned + sender_banned || recipient_or_code_banned }, None => false, } diff --git a/ethcore/src/miner/transaction_queue.rs b/ethcore/src/miner/transaction_queue.rs index f8baf8989..51c1863f6 100644 --- a/ethcore/src/miner/transaction_queue.rs +++ b/ethcore/src/miner/transaction_queue.rs @@ -110,6 +110,7 @@ impl PartialOrd for TransactionOrigin { } impl Ord for TransactionOrigin { + #[cfg_attr(feature="dev", allow(match_same_arms))] fn cmp(&self, other: &TransactionOrigin) -> Ordering { if *other == *self { return Ordering::Equal; diff --git a/ethcore/src/snapshot/account.rs b/ethcore/src/snapshot/account.rs index 7e4585365..38a4028e1 100644 --- a/ethcore/src/snapshot/account.rs +++ b/ethcore/src/snapshot/account.rs @@ -178,7 +178,7 @@ impl Account { CodeState::Hash => { let code_hash = try!(rlp.val_at(3)); if let Some(code) = code_map.get(&code_hash) { - acct_db.emplace(code_hash.clone(), DBValue::from_slice(&code)); + acct_db.emplace(code_hash.clone(), DBValue::from_slice(code)); } (code_hash, None) diff --git a/parity/informant.rs b/parity/informant.rs index 9b0b6c754..ae59cb9d0 100644 --- a/parity/informant.rs +++ b/parity/informant.rs @@ -184,7 +184,7 @@ impl ChainNotify for Informant { let ripe = Instant::now() > *last_import + Duration::from_secs(1) && !importing; let txs_imported = imported.iter() .take(imported.len() - if ripe {1} else {0}) - .filter_map(|h| self.client.block(BlockID::Hash(h.clone()))) + .filter_map(|h| self.client.block(BlockID::Hash(*h))) .map(|b| BlockView::new(&b).transactions_count()) .sum(); diff --git a/sync/src/chain.rs b/sync/src/chain.rs index 06949682b..72df47c07 100644 --- a/sync/src/chain.rs +++ b/sync/src/chain.rs @@ -1509,7 +1509,7 @@ impl ChainSync { } trace!(target: "sync", "{} -> GetNodeData: return {} entries", peer_id, added); let mut rlp = RlpStream::new_list(added); - for d in data.into_iter() { + for d in data { rlp.append(&d); } Ok(Some((NODE_DATA_PACKET, rlp))) diff --git a/util/src/trie/triedb.rs b/util/src/trie/triedb.rs index cd8c9939a..d929c9d68 100644 --- a/util/src/trie/triedb.rs +++ b/util/src/trie/triedb.rs @@ -133,7 +133,7 @@ impl<'db> TrieDB<'db> { } /// Get the data of the root node. - fn root_data<'a, R: 'a + Recorder>(&self, r: &'a mut R) -> super::Result { + fn root_data(&self, r: &mut R) -> super::Result { self.db.get(self.root).ok_or_else(|| Box::new(TrieError::InvalidStateRoot(*self.root))) .map(|node| { r.record(self.root, &*node, 0); node }) } From 227bf4b8c5c69d56a2a37b1404f98f1f0787e513 Mon Sep 17 00:00:00 2001 From: Robert Habermeier Date: Sat, 29 Oct 2016 13:09:16 +0200 Subject: [PATCH 09/42] Run cargo with verbose flag when testing (#2943) * Run cargo with verbose flag when testing * use full verbose flag --- test.sh | 2 +- 1 file changed, 1 insertion(+), 1 deletion(-) diff --git a/test.sh b/test.sh index 327d83deb..44bffa7d9 100755 --- a/test.sh +++ b/test.sh @@ -2,7 +2,7 @@ # Running Parity Full Test Sute FEATURES="json-tests" -OPTIONS="--release" +OPTIONS="--verbose --release" case $1 in --no-json) From 1a258fc0a732c780c8fb7f2344f1eb2f5a236330 Mon Sep 17 00:00:00 2001 From: GitLab Build Bot Date: Sat, 29 Oct 2016 11:21:07 +0000 Subject: [PATCH 10/42] [ci skip] js-precompiled 20161029-112006 --- Cargo.lock | 2 +- 1 file changed, 1 insertion(+), 1 deletion(-) diff --git a/Cargo.lock b/Cargo.lock index 870d39fa1..b680687e3 100644 --- a/Cargo.lock +++ b/Cargo.lock @@ -1213,7 +1213,7 @@ dependencies = [ [[package]] name = "parity-ui-precompiled" version = "1.4.0" -source = "git+https://github.com/ethcore/js-precompiled.git#d35381a1442215c9b21f472c2a644d1ecbe43336" +source = "git+https://github.com/ethcore/js-precompiled.git#18430becb29cdde5ee3f62ca81c5910e553b5b9b" dependencies = [ "parity-dapps-glue 1.4.0 (registry+https://github.com/rust-lang/crates.io-index)", ] From 598679000c3cee386e4023001e2fa02828419d70 Mon Sep 17 00:00:00 2001 From: GitLab Build Bot Date: Sat, 29 Oct 2016 11:29:09 +0000 Subject: [PATCH 11/42] [ci skip] js-precompiled 20161029-112814 --- Cargo.lock | 2 +- 1 file changed, 1 insertion(+), 1 deletion(-) diff --git a/Cargo.lock b/Cargo.lock index b680687e3..6dba19a11 100644 --- a/Cargo.lock +++ b/Cargo.lock @@ -1213,7 +1213,7 @@ dependencies = [ [[package]] name = "parity-ui-precompiled" version = "1.4.0" -source = "git+https://github.com/ethcore/js-precompiled.git#18430becb29cdde5ee3f62ca81c5910e553b5b9b" +source = "git+https://github.com/ethcore/js-precompiled.git#897a9afd0a4aa500e2e29e5d978618446a6b6086" dependencies = [ "parity-dapps-glue 1.4.0 (registry+https://github.com/rust-lang/crates.io-index)", ] From fe02f93e4cf6b63ab2a64ba8ffa6a128276dfee9 Mon Sep 17 00:00:00 2001 From: GitLab Build Bot Date: Sat, 29 Oct 2016 11:42:16 +0000 Subject: [PATCH 12/42] [ci skip] js-precompiled 20161029-114119 --- Cargo.lock | 2 +- 1 file changed, 1 insertion(+), 1 deletion(-) diff --git a/Cargo.lock b/Cargo.lock index 6dba19a11..3df83fb84 100644 --- a/Cargo.lock +++ b/Cargo.lock @@ -1213,7 +1213,7 @@ dependencies = [ [[package]] name = "parity-ui-precompiled" version = "1.4.0" -source = "git+https://github.com/ethcore/js-precompiled.git#897a9afd0a4aa500e2e29e5d978618446a6b6086" +source = "git+https://github.com/ethcore/js-precompiled.git#b65eb2375043a03d425a559910c1a4e5ab71d7d6" dependencies = [ "parity-dapps-glue 1.4.0 (registry+https://github.com/rust-lang/crates.io-index)", ] From 144930f12cf3541d6d3bf04792eaf16dbfc88152 Mon Sep 17 00:00:00 2001 From: =?UTF-8?q?Tomasz=20Drwi=C4=99ga?= Date: Sat, 29 Oct 2016 15:31:13 +0200 Subject: [PATCH 13/42] Updating ws-rs (#2962) --- Cargo.lock | 8 ++++---- 1 file changed, 4 insertions(+), 4 deletions(-) diff --git a/Cargo.lock b/Cargo.lock index 3df83fb84..845935e56 100644 --- a/Cargo.lock +++ b/Cargo.lock @@ -516,7 +516,7 @@ dependencies = [ "parity-ui 1.4.0", "rand 0.3.14 (registry+https://github.com/rust-lang/crates.io-index)", "rustc_version 0.1.7 (registry+https://github.com/rust-lang/crates.io-index)", - "ws 0.5.2 (git+https://github.com/ethcore/ws-rs.git?branch=mio-upstream-stable)", + "ws 0.5.3 (git+https://github.com/ethcore/ws-rs.git?branch=mio-upstream-stable)", ] [[package]] @@ -1884,8 +1884,8 @@ source = "registry+https://github.com/rust-lang/crates.io-index" [[package]] name = "ws" -version = "0.5.2" -source = "git+https://github.com/ethcore/ws-rs.git?branch=mio-upstream-stable#00bd2134b07b4bc8ea47b7f6c7afce16bbe34c8f" +version = "0.5.3" +source = "git+https://github.com/ethcore/ws-rs.git?branch=mio-upstream-stable#b4538aec81e4c19519469127cece5fe62c88bb04" dependencies = [ "bytes 0.4.0-dev (git+https://github.com/carllerche/bytes)", "httparse 1.1.2 (registry+https://github.com/rust-lang/crates.io-index)", @@ -2099,7 +2099,7 @@ dependencies = [ "checksum webpki 0.3.0 (registry+https://github.com/rust-lang/crates.io-index)" = "813503a5985585e0812d430cd1328ee322f47f66629c8ed4ecab939cf9e92f91" "checksum winapi 0.2.6 (registry+https://github.com/rust-lang/crates.io-index)" = "4dfaaa8fbdaa618fa6914b59b2769d690dd7521920a18d84b42d254678dd5fd4" "checksum winapi-build 0.1.1 (registry+https://github.com/rust-lang/crates.io-index)" = "2d315eee3b34aca4797b2da6b13ed88266e6d612562a0c46390af8299fc699bc" -"checksum ws 0.5.2 (git+https://github.com/ethcore/ws-rs.git?branch=mio-upstream-stable)" = "" +"checksum ws 0.5.3 (git+https://github.com/ethcore/ws-rs.git?branch=mio-upstream-stable)" = "" "checksum ws2_32-sys 0.2.1 (registry+https://github.com/rust-lang/crates.io-index)" = "d59cefebd0c892fa2dd6de581e937301d8552cb44489cdff035c6187cb63fa5e" "checksum xml-rs 0.3.4 (registry+https://github.com/rust-lang/crates.io-index)" = "65e74b96bd3179209dc70a980da6df843dff09e46eee103a0376c0949257e3ef" "checksum xmltree 0.3.2 (registry+https://github.com/rust-lang/crates.io-index)" = "472a9d37c7c53ab2391161df5b89b1f3bf76dab6ab150d7941ecbdd832282082" From 49a7b84f14d713a8fd1756cfe9f16d786641ad64 Mon Sep 17 00:00:00 2001 From: Jaco Greeff Date: Sat, 29 Oct 2016 15:32:10 +0200 Subject: [PATCH 14/42] Pass gas & gasPrice to token transfers (#2964) --- js/src/dapps/gavcoin/Actions/ActionBuyIn/actionBuyIn.js | 2 +- js/src/modals/Transfer/transfer.js | 8 +++++--- 2 files changed, 6 insertions(+), 4 deletions(-) diff --git a/js/src/dapps/gavcoin/Actions/ActionBuyIn/actionBuyIn.js b/js/src/dapps/gavcoin/Actions/ActionBuyIn/actionBuyIn.js index 42de205c1..fe67c3739 100644 --- a/js/src/dapps/gavcoin/Actions/ActionBuyIn/actionBuyIn.js +++ b/js/src/dapps/gavcoin/Actions/ActionBuyIn/actionBuyIn.js @@ -43,7 +43,7 @@ export default class ActionBuyIn extends Component { accountError: ERRORS.invalidAccount, amount: 0, amountError: ERRORS.invalidAmount, - maxPrice: api.util.fromWei(this.props.price.mul(1.2)).toString(), + maxPrice: api.util.fromWei(this.props.price.mul(1.2)).toFixed(0), maxPriceError: null, sending: false, complete: false diff --git a/js/src/modals/Transfer/transfer.js b/js/src/modals/Transfer/transfer.js index 2217d0e9c..0ffad525c 100644 --- a/js/src/modals/Transfer/transfer.js +++ b/js/src/modals/Transfer/transfer.js @@ -420,13 +420,15 @@ export default class Transfer extends Component { _sendToken () { const { account, balance } = this.props; - const { recipient, value, tag } = this.state; + const { gas, gasPrice, recipient, value, tag } = this.state; const token = balance.tokens.find((balance) => balance.token.tag === tag).token; return token.contract.instance.transfer .postTransaction({ from: account.address, - to: token.address + to: token.address, + gas, + gasPrice }, [ recipient, new BigNumber(value).mul(token.format).toFixed(0) @@ -483,7 +485,7 @@ export default class Transfer extends Component { to: token.address }, [ recipient, - new BigNumber(value || 0).mul(token.format).toString() + new BigNumber(value || 0).mul(token.format).toFixed(0) ]); } From 3a6c1c377c9a57d11d890cfecdff0f41e6b8f849 Mon Sep 17 00:00:00 2001 From: GitLab Build Bot Date: Sat, 29 Oct 2016 13:34:58 +0000 Subject: [PATCH 15/42] [ci skip] js-precompiled 20161029-133354 --- Cargo.lock | 2 +- 1 file changed, 1 insertion(+), 1 deletion(-) diff --git a/Cargo.lock b/Cargo.lock index 845935e56..62fa3d984 100644 --- a/Cargo.lock +++ b/Cargo.lock @@ -1213,7 +1213,7 @@ dependencies = [ [[package]] name = "parity-ui-precompiled" version = "1.4.0" -source = "git+https://github.com/ethcore/js-precompiled.git#b65eb2375043a03d425a559910c1a4e5ab71d7d6" +source = "git+https://github.com/ethcore/js-precompiled.git#39fa4ad1e1775e8f4efed7a94fa21318f8053091" dependencies = [ "parity-dapps-glue 1.4.0 (registry+https://github.com/rust-lang/crates.io-index)", ] From 99d6d87e78eb960fe9bb17052f95ec521b46cd58 Mon Sep 17 00:00:00 2001 From: Arkadiy Paronyan Date: Sat, 29 Oct 2016 17:38:34 +0200 Subject: [PATCH 16/42] Discovery performance optimization (#2972) --- util/network/ | 0 util/network/src/discovery.rs | 20 +++++++++++++------- util/network/src/host.rs | 2 +- 3 files changed, 14 insertions(+), 8 deletions(-) create mode 100644 util/network/ diff --git a/util/network/ b/util/network/ new file mode 100644 index 000000000..e69de29bb diff --git a/util/network/src/discovery.rs b/util/network/src/discovery.rs index 595ac7605..d9cd7a4d7 100644 --- a/util/network/src/discovery.rs +++ b/util/network/src/discovery.rs @@ -57,6 +57,7 @@ pub struct NodeEntry { pub struct BucketEntry { pub address: NodeEntry, + pub id_hash: H256, pub timeout: Option, } @@ -85,6 +86,7 @@ struct Datagramm { pub struct Discovery { id: NodeId, + id_hash: H256, secret: Secret, public_endpoint: NodeEndpoint, udp_socket: UdpSocket, @@ -109,6 +111,7 @@ impl Discovery { let socket = UdpSocket::bound(&listen).expect("Error binding UDP socket"); Discovery { id: key.public().clone(), + id_hash: key.public().sha3(), secret: key.secret().clone(), public_endpoint: public, token: token, @@ -150,8 +153,9 @@ impl Discovery { fn update_node(&mut self, e: NodeEntry) { trace!(target: "discovery", "Inserting {:?}", &e); + let id_hash = e.id.sha3(); let ping = { - let mut bucket = self.node_buckets.get_mut(Discovery::distance(&self.id, &e.id) as usize).unwrap(); + let mut bucket = self.node_buckets.get_mut(Discovery::distance(&self.id_hash, &id_hash) as usize).unwrap(); let updated = if let Some(node) = bucket.nodes.iter_mut().find(|n| n.address.id == e.id) { node.address = e.clone(); node.timeout = None; @@ -159,7 +163,7 @@ impl Discovery { } else { false }; if !updated { - bucket.nodes.push_front(BucketEntry { address: e, timeout: None }); + bucket.nodes.push_front(BucketEntry { address: e, timeout: None, id_hash: id_hash, }); } if bucket.nodes.len() > BUCKET_SIZE { @@ -174,7 +178,7 @@ impl Discovery { } fn clear_ping(&mut self, id: &NodeId) { - let mut bucket = self.node_buckets.get_mut(Discovery::distance(&self.id, id) as usize).unwrap(); + let mut bucket = self.node_buckets.get_mut(Discovery::distance(&self.id_hash, &id.sha3()) as usize).unwrap(); if let Some(node) = bucket.nodes.iter_mut().find(|n| &n.address.id == id) { node.timeout = None; } @@ -224,8 +228,8 @@ impl Discovery { self.discovery_round += 1; } - fn distance(a: &NodeId, b: &NodeId) -> u32 { - let d = a.sha3() ^ b.sha3(); + fn distance(a: &H256, b: &H256) -> u32 { + let d = *a ^ *b; let mut ret:u32 = 0; for i in 0..32 { let mut v: u8 = d[i]; @@ -279,11 +283,12 @@ impl Discovery { fn nearest_node_entries(target: &NodeId, buckets: &[NodeBucket]) -> Vec { let mut found: BTreeMap> = BTreeMap::new(); let mut count = 0; + let target_hash = target.sha3(); // Sort nodes by distance to target for bucket in buckets { for node in &bucket.nodes { - let distance = Discovery::distance(target, &node.address.id); + let distance = Discovery::distance(&target_hash, &node.id_hash); found.entry(distance).or_insert_with(Vec::new).push(&node.address); if count == BUCKET_SIZE { // delete the most distant element @@ -626,7 +631,8 @@ mod tests { for _ in 0..(16 + 10) { buckets[0].nodes.push_back(BucketEntry { address: NodeEntry { id: NodeId::new(), endpoint: ep.clone() }, - timeout: None + timeout: None, + id_hash: NodeId::new().sha3(), }); } let nearest = Discovery::nearest_node_entries(&NodeId::new(), &buckets); diff --git a/util/network/src/host.rs b/util/network/src/host.rs index 177a44843..d6e530d6f 100644 --- a/util/network/src/host.rs +++ b/util/network/src/host.rs @@ -61,7 +61,7 @@ const SYS_TIMER: usize = LAST_SESSION + 1; // Timeouts const MAINTENANCE_TIMEOUT: u64 = 1000; -const DISCOVERY_REFRESH_TIMEOUT: u64 = 7200; +const DISCOVERY_REFRESH_TIMEOUT: u64 = 60_000; const DISCOVERY_ROUND_TIMEOUT: u64 = 300; const NODE_TABLE_TIMEOUT: u64 = 300_000; From c342fa3035c729d8c9826e5a4ff27a6c4b612d14 Mon Sep 17 00:00:00 2001 From: Arkadiy Paronyan Date: Sat, 29 Oct 2016 17:38:50 +0200 Subject: [PATCH 17/42] WS bump (#2973) --- Cargo.lock | 8 ++++---- 1 file changed, 4 insertions(+), 4 deletions(-) diff --git a/Cargo.lock b/Cargo.lock index 62fa3d984..296c17c31 100644 --- a/Cargo.lock +++ b/Cargo.lock @@ -990,7 +990,7 @@ dependencies = [ [[package]] name = "mio" version = "0.6.0-dev" -source = "git+https://github.com/carllerche/mio?rev=62ec763c9cc34d8a452ed0392c575c50ddd5fc8d#62ec763c9cc34d8a452ed0392c575c50ddd5fc8d" +source = "git+https://github.com/ethcore/mio?branch=timer-fix#31eccc40ece3d47abaefaf23bb2114033175b972" dependencies = [ "kernel32-sys 0.2.2 (registry+https://github.com/rust-lang/crates.io-index)", "libc 0.2.15 (registry+https://github.com/rust-lang/crates.io-index)", @@ -1885,12 +1885,12 @@ source = "registry+https://github.com/rust-lang/crates.io-index" [[package]] name = "ws" version = "0.5.3" -source = "git+https://github.com/ethcore/ws-rs.git?branch=mio-upstream-stable#b4538aec81e4c19519469127cece5fe62c88bb04" +source = "git+https://github.com/ethcore/ws-rs.git?branch=mio-upstream-stable#0cd6c5e3e9d5e61a37d53eb8dcbad523dcc69314" dependencies = [ "bytes 0.4.0-dev (git+https://github.com/carllerche/bytes)", "httparse 1.1.2 (registry+https://github.com/rust-lang/crates.io-index)", "log 0.3.6 (registry+https://github.com/rust-lang/crates.io-index)", - "mio 0.6.0-dev (git+https://github.com/carllerche/mio?rev=62ec763c9cc34d8a452ed0392c575c50ddd5fc8d)", + "mio 0.6.0-dev (git+https://github.com/ethcore/mio?branch=timer-fix)", "rand 0.3.14 (registry+https://github.com/rust-lang/crates.io-index)", "sha1 0.2.0 (registry+https://github.com/rust-lang/crates.io-index)", "slab 0.2.0 (git+https://github.com/carllerche/slab?rev=5476efcafb)", @@ -1996,7 +1996,7 @@ dependencies = [ "checksum miniz-sys 0.1.7 (registry+https://github.com/rust-lang/crates.io-index)" = "9d1f4d337a01c32e1f2122510fed46393d53ca35a7f429cb0450abaedfa3ed54" "checksum mio 0.5.1 (git+https://github.com/ethcore/mio?branch=v0.5.x)" = "" "checksum mio 0.5.1 (registry+https://github.com/rust-lang/crates.io-index)" = "a637d1ca14eacae06296a008fa7ad955347e34efcb5891cfd8ba05491a37907e" -"checksum mio 0.6.0-dev (git+https://github.com/carllerche/mio?rev=62ec763c9cc34d8a452ed0392c575c50ddd5fc8d)" = "" +"checksum mio 0.6.0-dev (git+https://github.com/ethcore/mio?branch=timer-fix)" = "" "checksum miow 0.1.3 (registry+https://github.com/rust-lang/crates.io-index)" = "d5bfc6782530ac8ace97af10a540054a37126b63b0702ddaaa243b73b5745b9a" "checksum msdos_time 0.1.4 (registry+https://github.com/rust-lang/crates.io-index)" = "c04b68cc63a8480fb2550343695f7be72effdec953a9d4508161c3e69041c7d8" "checksum nanomsg 0.5.1 (git+https://github.com/ethcore/nanomsg.rs.git)" = "" From 4d1cfd67068d696533aece48c594d438d1a6fdde Mon Sep 17 00:00:00 2001 From: Jaco Greeff Date: Sat, 29 Oct 2016 17:39:08 +0200 Subject: [PATCH 18/42] Align password change dialog with create (#2970) --- .../PasswordManager/passwordManager.css | 10 +++++ .../modals/PasswordManager/passwordManager.js | 44 ++++++++++--------- 2 files changed, 34 insertions(+), 20 deletions(-) diff --git a/js/src/modals/PasswordManager/passwordManager.css b/js/src/modals/PasswordManager/passwordManager.css index aa0f72cb3..f538ef546 100644 --- a/js/src/modals/PasswordManager/passwordManager.css +++ b/js/src/modals/PasswordManager/passwordManager.css @@ -46,6 +46,16 @@ font-size: 1.1rem; } +.passwords { + display: flex; + flex-wrap: wrap; +} + +.password { + flex: 0 1 50%; + width: 50%; +} + .passwordHint { font-size: 0.9rem; color: lightgrey; diff --git a/js/src/modals/PasswordManager/passwordManager.js b/js/src/modals/PasswordManager/passwordManager.js index 800fba929..368664a71 100644 --- a/js/src/modals/PasswordManager/passwordManager.js +++ b/js/src/modals/PasswordManager/passwordManager.js @@ -181,33 +181,37 @@ export default class PasswordManager extends Component { disabled={ disabled } onSubmit={ this.handleChangePassword } onChange={ this.onEditCurrent } /> - - - - +
+
+ +
+
+ +
+
From e2b82e1e377fe5c7ade90bb5f989fd725ed87587 Mon Sep 17 00:00:00 2001 From: GitLab Build Bot Date: Sat, 29 Oct 2016 15:44:04 +0000 Subject: [PATCH 19/42] [ci skip] js-precompiled 20161029-154241 --- Cargo.lock | 2 +- 1 file changed, 1 insertion(+), 1 deletion(-) diff --git a/Cargo.lock b/Cargo.lock index 296c17c31..25343f4f9 100644 --- a/Cargo.lock +++ b/Cargo.lock @@ -1213,7 +1213,7 @@ dependencies = [ [[package]] name = "parity-ui-precompiled" version = "1.4.0" -source = "git+https://github.com/ethcore/js-precompiled.git#39fa4ad1e1775e8f4efed7a94fa21318f8053091" +source = "git+https://github.com/ethcore/js-precompiled.git#293affdf3aa7735862d5a83a4b1f1edc7edd5936" dependencies = [ "parity-dapps-glue 1.4.0 (registry+https://github.com/rust-lang/crates.io-index)", ] From fca545ce9822cb24a2b51845cebb292bc6842540 Mon Sep 17 00:00:00 2001 From: arkpar Date: Sat, 29 Oct 2016 17:59:27 +0200 Subject: [PATCH 20/42] Removed junk file --- util/network/ | 0 1 file changed, 0 insertions(+), 0 deletions(-) delete mode 100644 util/network/ diff --git a/util/network/ b/util/network/ deleted file mode 100644 index e69de29bb..000000000 From c24ac577fb2c5feaaac5e7f4223874f1afd01fca Mon Sep 17 00:00:00 2001 From: GitLab Build Bot Date: Sat, 29 Oct 2016 16:01:29 +0000 Subject: [PATCH 21/42] [ci skip] js-precompiled 20161029-160033 --- Cargo.lock | 2 +- 1 file changed, 1 insertion(+), 1 deletion(-) diff --git a/Cargo.lock b/Cargo.lock index 25343f4f9..b4477e976 100644 --- a/Cargo.lock +++ b/Cargo.lock @@ -1213,7 +1213,7 @@ dependencies = [ [[package]] name = "parity-ui-precompiled" version = "1.4.0" -source = "git+https://github.com/ethcore/js-precompiled.git#293affdf3aa7735862d5a83a4b1f1edc7edd5936" +source = "git+https://github.com/ethcore/js-precompiled.git#5c2278c4456a82229069f13b16ebf5bdb630e34c" dependencies = [ "parity-dapps-glue 1.4.0 (registry+https://github.com/rust-lang/crates.io-index)", ] From e304a2f3fe95b4bc0352299182e7c640630a65a9 Mon Sep 17 00:00:00 2001 From: Jaco Greeff Date: Sat, 29 Oct 2016 19:06:33 +0200 Subject: [PATCH 22/42] Add favicon (#2974) * Add favicon.ico * Add favicon to all html pages * Cleanup favicon background --- js/assets/images/ethcore-block-black.png | Bin 0 -> 11783 bytes js/assets/images/parity.ico | Bin 0 -> 1150 bytes js/src/dapps/basiccoin.html | 1 + js/src/dapps/gavcoin.html | 1 + js/src/dapps/githubhint.html | 1 + js/src/dapps/registry.html | 1 + js/src/dapps/signaturereg.html | 1 + js/src/dapps/tokenreg.html | 1 + js/src/dev.parity.html | 1 + js/src/dev.web3.html | 1 + js/src/index.html | 1 + js/src/index.js | 2 ++ js/webpack.config.js | 6 +++++- 13 files changed, 16 insertions(+), 1 deletion(-) create mode 100644 js/assets/images/ethcore-block-black.png create mode 100644 js/assets/images/parity.ico diff --git a/js/assets/images/ethcore-block-black.png b/js/assets/images/ethcore-block-black.png new file mode 100644 index 0000000000000000000000000000000000000000..780a5be5c6d2de859db903bb565e659e5dd1e2e4 GIT binary patch literal 11783 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 literal 0 HcmV?d00001 diff --git a/js/assets/images/parity.ico b/js/assets/images/parity.ico new file mode 100644 index 0000000000000000000000000000000000000000..4551b46bede66e0130b4c248e9c21cc0b5150153 GIT binary patch literal 1150 zcmZuwOHUeM6unKFxU5N&uG?L^?yu+{X_}C@Gj7}%SO_a=y6Hj|7!^fLjD&}Y0Rluo z5~D^z;|rpYpdiRYK@2JRXnk?e6X(7!2y#PteeHIrNadma2YvUoStE;%VxdC-AEiHkZMx*h2pKInvUG;h$)oK+h zD=WIcx3{Ny&d<+bv)Mp>tU<5W)4X^-*W|OVR;v}Kr>EK<`c6ztXl~rQy}iZ4!h&ii z@3}Eo>ZVTif?CGM$6>eI(Q36+3;kKg?d@&-CdaH%I-N!!5Kx@6!XA)IoV777DVNJ& zy{UnHBSvHIh%pX*h;cs5IMia|%=7s880+in>PO#=jSXb8S*;6WS1J{)GxunPLIGZ{ zSN&OQYF=AgLq4C^KCwT<%%1R@GeNGIpWpA-x)5V->=XTHoI`Ww4i69E^ZEYblEd6M zn>>&C?(FQq;c#GjdRlA5dQdxkOdaIWObz@uCMPE`Gc$vDJgzfOU(TJ=>D0ZWqoe;~ z^9=L + Basic Token Deployment diff --git a/js/src/dapps/gavcoin.html b/js/src/dapps/gavcoin.html index f777f2920..3b260bce1 100644 --- a/js/src/dapps/gavcoin.html +++ b/js/src/dapps/gavcoin.html @@ -4,6 +4,7 @@ + GAVcoin diff --git a/js/src/dapps/githubhint.html b/js/src/dapps/githubhint.html index 085b15953..4689fd7d9 100644 --- a/js/src/dapps/githubhint.html +++ b/js/src/dapps/githubhint.html @@ -4,6 +4,7 @@ + GitHub Hint diff --git a/js/src/dapps/registry.html b/js/src/dapps/registry.html index 83c5e8c9b..512932a0a 100644 --- a/js/src/dapps/registry.html +++ b/js/src/dapps/registry.html @@ -4,6 +4,7 @@ + Token Registry diff --git a/js/src/dapps/signaturereg.html b/js/src/dapps/signaturereg.html index be62400d2..3929b425c 100644 --- a/js/src/dapps/signaturereg.html +++ b/js/src/dapps/signaturereg.html @@ -4,6 +4,7 @@ + Method Signature Registry diff --git a/js/src/dapps/tokenreg.html b/js/src/dapps/tokenreg.html index bcf04e298..8510aa817 100644 --- a/js/src/dapps/tokenreg.html +++ b/js/src/dapps/tokenreg.html @@ -4,6 +4,7 @@ + Token Registry diff --git a/js/src/dev.parity.html b/js/src/dev.parity.html index 56811f7c2..c2eb392d3 100644 --- a/js/src/dev.parity.html +++ b/js/src/dev.parity.html @@ -4,6 +4,7 @@ + dev::Parity.js diff --git a/js/src/dev.web3.html b/js/src/dev.web3.html index e55e0109b..ced98fca7 100644 --- a/js/src/dev.web3.html +++ b/js/src/dev.web3.html @@ -4,6 +4,7 @@ + dev::Web3 diff --git a/js/src/index.html b/js/src/index.html index 4ca2e7c1a..397a827d0 100644 --- a/js/src/index.html +++ b/js/src/index.html @@ -4,6 +4,7 @@ + Parity