public override void OnBlocksDownloaded(Peer peer, Block block, int blocksLeft) { if (blocksLeft == 0) { DoneDownload(); _done.Release(); } if (blocksLeft < 0 || _originalBlocksLeft <= 0) return; var pct = 100.0 - (100.0*(blocksLeft/(double) _originalBlocksLeft)); if ((int) pct != _lastPercent) { Progress(pct, UnixTime.FromUnixTime(block.TimeSeconds*1000)); _lastPercent = (int) pct; } }
/// <summary> /// Sends coins to the given address, via the given <see cref="Peer"/>. /// Change is returned to the first key in the wallet. /// </summary> /// <param name="peer">The peer to send via.</param> /// <param name="to">Which address to send coins to.</param> /// <param name="nanocoins">How many nanocoins to send. You can use Utils.ToNanoCoins() to calculate this.</param> /// <returns>The <see cref="Transaction"/> that was created or null if there was insufficient balance to send the coins.</returns> /// <exception cref="IOException">If there was a problem broadcasting the transaction.</exception> public Transaction SendCoins(Peer peer, Address to, ulong nanocoins) { lock (this) { var tx = CreateSend(to, nanocoins); if (tx == null) // Not enough money! :-( return null; peer.BroadcastTransaction(tx); ConfirmSend(tx); return tx; } }
public override void OnChainDownloadStarted(Peer peer, int blocksLeft) { StartDownload(blocksLeft); _originalBlocksLeft = blocksLeft; }
private void StartBlockChainDownloadFromPeer(Peer peer) { lock (syncRoot) { peer.BlocksDownloaded += (sender, e) => _downloadListener.OnBlocksDownloaded((Peer)sender, e.Block, e.BlocksLeft); peer.ChainDownloadStarted += (sender, e) => _downloadListener.OnChainDownloadStarted((Peer)sender, e.BlocksLeft); try { peer.StartBlockChainDownload(); } catch (IOException e) { Log.Error("failed to start block chain download from " + peer, e); return; } _downloadPeer = peer; } }
private void ConnectAndRun(Peer peer, CancellationToken token) { try { Log.Info("Connecting to " + peer); peer.Connect(); HandleNewPeer(peer); peer.Run(token); } catch (PeerException ex) { // Do not propagate PeerException - log and try next peer. Suppress stack traces for // exceptions we expect as part of normal network behaviour. var cause = ex.InnerException; if (cause is SocketException) { if (((SocketException)cause).SocketErrorCode == SocketError.TimedOut) { Log.Info("Timeout talking to " + peer + ": " + cause.Message); } else { Log.Info("Could not connect to " + peer + ": " + cause.Message); } } else if (cause is IOException) { Log.Info("Error talking to " + peer + ": " + cause.Message); } else { Log.Error("Unexpected exception whilst talking to " + peer, ex); } } finally { peer.Disconnect(); HandlePeerDeath(peer); } }
/// <summary> /// Try connecting to a peer. If we exceed the number of connections, delay and try /// again. /// </summary> /// <exception cref="ThreadInterruptedException"/> private void AllocateNextPeer() { PeerAddress address; if (!_inactives.TryDequeue(out address)) { return; } try { var peer = new Peer(networkParams, address, _blockStore.GetChainHead().Height, _chain); var workerAllocated = peerConnectionPool.TryAllocateWorker(token => ConnectAndRun(peer, token)); if (!workerAllocated) { _inactives.Enqueue(address); return; } } catch (BlockStoreException e) { // Fatal error Log.Error("Block store corrupt?", e); _running = false; throw new Exception(e.Message, e); } }
protected void HandlePeerDeath(Peer peer) { lock (syncRoot) { lock (_peers) { _peers.Remove(peer); } if (peer == _downloadPeer) { _downloadPeer = null; lock (_peers) { var firstPeer = _peers.FirstOrDefault(); if (_downloadListener != null && firstPeer != null) { StartBlockChainDownloadFromPeer(firstPeer); } } } if (PeerDisconnected != null) { PeerDisconnected(this, new PeerDisconnectedEventArgs(_peers.Count)); } } }
protected void HandleNewPeer(Peer peer) { lock (syncRoot) { _peers.Add(peer); if (_downloadListener != null && _downloadPeer == null) { StartBlockChainDownloadFromPeer(peer); } if (PeerConnected != null) { PeerConnected(this, new PeerConnectedEventArgs(_peers.Count)); } } }