public async Task Does_not_do_full_sync_when_not_needed_with_split() { BlockTree minerTree = Build.A.BlockTree(_genesisBlock).OfChainLength(6).TestObject; ISynchronizationPeer miner1 = new SynchronizationPeerMock(minerTree); AutoResetEvent resetEvent = new AutoResetEvent(false); _manager.SyncEvent += (sender, args) => { if (args.SyncStatus == SyncStatus.Completed || args.SyncStatus == SyncStatus.Failed) { resetEvent.Set(); } }; _manager.Start(); Task addMiner1Task = _manager.AddPeer(miner1); await Task.WhenAll(addMiner1Task); resetEvent.WaitOne(_standardTimeoutUnit); Assert.AreEqual(minerTree.BestSuggested.Hash, _blockTree.BestSuggested.Hash, "client agrees with miner before split"); Block newBlock = Build.A.Block.WithParent(minerTree.Head).TestObject; minerTree.SuggestBlock(newBlock); minerTree.UpdateMainChain(newBlock); ISynchronizationPeer miner2 = Substitute.For <ISynchronizationPeer>(); miner2.GetHeadBlockNumber(Arg.Any <CancellationToken>()).Returns(miner1.GetHeadBlockNumber(CancellationToken.None)); miner2.GetHeadBlockHash(Arg.Any <CancellationToken>()).Returns(miner1.GetHeadBlockHash(CancellationToken.None)); miner2.NodeId.Returns(new NodeId(TestObject.PublicKeyB)); Assert.AreEqual(newBlock.Number, await miner2.GetHeadBlockNumber(Arg.Any <CancellationToken>()), "number as expected"); Assert.AreEqual(newBlock.Hash, await miner2.GetHeadBlockHash(default(CancellationToken)), "hash as expected"); await _manager.AddPeer(miner2); resetEvent.WaitOne(_standardTimeoutUnit); await miner2.Received().GetBlockHeaders(6, 1, 0, default(CancellationToken)); }
private async Task InitPeerInfo(ISynchronizationPeer peer, CancellationToken token) { if (_logger.IsTrace) { _logger.Trace($"Requesting head block info from {peer.NodeId}"); } Task <Keccak> getHashTask = peer.GetHeadBlockHash(token); Task <UInt256> getNumberTask = peer.GetHeadBlockNumber(token); // Task<UInt256> getDifficultyTask = peer.GetHeadDifficulty(token); await Task.WhenAny(Task.WhenAll(getHashTask, getNumberTask), Task.Delay(10000, token)).ContinueWith( t => { if (t.IsFaulted) { if (_logger.IsTrace) { _logger.Trace($"InitPeerInfo failed for node: {peer.NodeId}{Environment.NewLine}{t.Exception}"); } RemovePeer(peer); SyncEvent?.Invoke(this, new SyncEventArgs(peer, SyncStatus.InitFailed)); } else if (t.IsCanceled) { RemovePeer(peer); SyncEvent?.Invoke(this, new SyncEventArgs(peer, SyncStatus.InitCancelled)); token.ThrowIfCancellationRequested(); } else { if (_logger.IsTrace) { _logger.Trace($"Received head block info from {peer.NodeId} with head block numer {getNumberTask.Result}"); } SyncEvent?.Invoke( this, new SyncEventArgs(peer, SyncStatus.InitCompleted) { NodeBestBlockNumber = getNumberTask.Result, OurBestBlockNumber = _blockTree.BestSuggested.Number }); bool result = _peers.TryGetValue(peer.NodeId, out PeerInfo peerInfo); if (!result) { _logger.Error($"Initializing PeerInfo failed for {peer.NodeId}"); throw new EthSynchronizationException($"Initializing peer info failed for {peer.NodeId.ToString()}"); } peerInfo.NumberAvailable = getNumberTask.Result; // peerInfo.Difficulty = getDifficultyTask.Result; peerInfo.NumberReceived = _blockTree.BestSuggested.Number; peerInfo.IsInitialized = true; } }, token); }
private async Task InitPeerInfo(ISynchronizationPeer peer, CancellationToken token) { Task <Keccak> getHashTask = peer.GetHeadBlockHash(); if (_logger.IsDebugEnabled) { _logger.Debug($"Requesting head block info from {peer.NodeId}"); } Task <BigInteger> getNumberTask = peer.GetHeadBlockNumber(token); await Task.WhenAll(getHashTask, getNumberTask).ContinueWith( t => { if (t.IsFaulted) { if (_logger.IsErrorEnabled) { if (t.Exception != null && t.Exception.InnerExceptions.Any(x => x is TimeoutException)) { _logger.Warn($"InitPeerInfo failed for node: {peer.NodeId}. {t.Exception?.Message}"); } else { _logger.Error($"InitPeerInfo failedf or node: {peer.NodeId}.", t.Exception); } } SyncFailed?.Invoke(this, new SyncEventArgs(peer)); } else if (t.IsCanceled) { token.ThrowIfCancellationRequested(); } }, token); if (_logger.IsDebugEnabled) { _logger.Info($"Received head block info from {peer.NodeId} with head block numer {getNumberTask.Result}"); } bool addResult = _peers.TryAdd(peer.NodeId, new PeerInfo(peer, getNumberTask.Result) { NumberReceived = BlockTree.BestSuggested.Number }); // TODO: cheating now with assumign the consistency of the chains if (!addResult) { _logger.Error($"Adding {nameof(PeerInfo)} failed for {peer.NodeId}"); } }
public async Task Does_not_do_full_sync_when_not_needed_with_split() { BlockTree minerTree = Build.A.BlockTree(_genesisBlock).OfChainLength(6).TestObject; ISynchronizationPeer miner1 = new SynchronizationPeerMock(minerTree); ManualResetEvent resetEvent = new ManualResetEvent(false); _manager.SyncEvent += (sender, args) => { resetEvent.Set(); }; Task addMiner1Task = _manager.AddPeer(miner1); await Task.WhenAll(addMiner1Task); resetEvent.WaitOne(TimeSpan.FromSeconds(1)); Assert.AreEqual(minerTree.BestSuggested.Hash, _blockTree.BestSuggested.Hash, "client agrees with miner before split"); Block newBlock = Build.A.Block.WithParent(minerTree.Head).TestObject; minerTree.SuggestBlock(newBlock); minerTree.MarkAsProcessed(newBlock.Hash); minerTree.MoveToMain(newBlock.Hash); ISynchronizationPeer miner2 = Substitute.For <ISynchronizationPeer>(); miner2.GetHeadBlockNumber(Arg.Any <CancellationToken>()).Returns(miner1.GetHeadBlockNumber(Arg.Any <CancellationToken>())); miner2.GetHeadBlockHash(Arg.Any <CancellationToken>()).Returns(miner1.GetHeadBlockHash(default(CancellationToken))); miner2.NodeId.Returns(new NodeId(TestObject.PublicKeyB)); Assert.AreEqual(newBlock.Number, await miner2.GetHeadBlockNumber(Arg.Any <CancellationToken>()), "number as expected"); Assert.AreEqual(newBlock.Hash, await miner2.GetHeadBlockHash(default(CancellationToken)), "hash as expected"); await _manager.AddPeer(miner2); await miner2.Received().GetBlockHeaders(6, 1, 0, default(CancellationToken)); }