public bool TryGetAtHeight(int height, [MaybeNullWhen(false)] out HeaderNode?headerNode) { using (GlobalLocks.ReadOnMainAsync().GetAwaiter().GetResult()) { return(HeadersTree.TryGetNodeOnBestChain(height, out headerNode)); } }
public bool TryGetNext(HeaderNode headerNode, [MaybeNullWhen(false)] out HeaderNode nextHeaderNode) { using (GlobalLocks.ReadOnMainAsync().GetAwaiter().GetResult()) { if (IsInBestChain(headerNode) && HeadersTree.TryGetNodeOnBestChain(headerNode.Height + 1, out nextHeaderNode)) { return(true); } nextHeaderNode = null; return(false); } }
/// <summary> /// Processes the headers. /// It's invoked because of "headers" or "cmpctblock" message /// </summary> /// <param name="headers">The headers.</param> /// <returns></returns> private async Task <bool> ProcessHeadersAsync(BlockHeader[] headers) { int protocolVersion = PeerContext.NegotiatedProtocolVersion.Version; int headersCount = headers.Length; if (headersCount == 0) { logger.LogDebug("Peer didn't returned any headers, let's assume we reached its tip."); return(true); } using (GlobalLocks.ReadOnMainAsync().GetAwaiter().GetResult()) { if (await HandleAsNotConnectingAnnouncementAsync(headers).ConfigureAwait(false)) { // fully handled as non connecting announcement return(true); } // compute hashes in parallel to speed up the operation and check sent headers are sequential. Parallel.ForEach(headers, header => { header.Hash = _blockHeaderHashCalculator.ComputeHash(header, protocolVersion); }); } // Ensure headers are consecutive. for (int i = 1; i < headersCount; i++) { if (headers[i].PreviousBlockHash != headers[i - 1].Hash) { Misbehave(20, "Non continuous headers sequence."); return(false); } } //enqueue headers for validation await _headerValidator.RequestValidationAsync(new HeadersToValidate(headers, PeerContext)).ConfigureAwait(false); return(true); }
public HeaderNode FindForkInGlobalIndex(BlockLocator locator) { using (GlobalLocks.ReadOnMainAsync().GetAwaiter().GetResult()) { // Find the latest block common to locator and chain - we expect that // locator.vHave is sorted descending by height. foreach (UInt256?hash in locator.BlockLocatorHashes) { if (TryGetKnownHeaderNode(hash, out HeaderNode? pindex)) { if (IsInBestChain(pindex)) { return(pindex); } if (pindex.GetAncestor(ChainTip.Height) == ChainTip) { return(ChainTip); } } } } return(HeadersTree.Genesis); }
public BlockHeader GetTipHeader() { using Microsoft.VisualStudio.Threading.AsyncReaderWriterLock.Releaser readMainLock = GlobalLocks.ReadOnMainAsync().GetAwaiter().GetResult(); if (!_blockHeaderRepository.TryGet(ChainTip.Hash, out BlockHeader? header)) { ThrowHelper.ThrowBlockHeaderRepositoryException($"Unexpected error, cannot fetch the tip at height {ChainTip.Height}."); } return(header !); }
public BlockLocator?GetLocator(HeaderNode headerNode) { using Microsoft.VisualStudio.Threading.AsyncReaderWriterLock.Releaser readMainLock = GlobalLocks.ReadOnMainAsync().GetAwaiter().GetResult(); return(HeadersTree.GetLocator(headerNode)); }
public bool TryGetKnownHeaderNode(UInt256?blockHash, [MaybeNullWhen(false)] out HeaderNode node) { //using var readLock = new ReadLock(this.theLock); using Microsoft.VisualStudio.Threading.AsyncReaderWriterLock.Releaser readMainLock = GlobalLocks.ReadOnMainAsync().GetAwaiter().GetResult(); return(HeadersTree.TryGetNode(blockHash, false, out node)); }
public bool TryGetBestChainHeaderNode(UInt256 blockHash, [MaybeNullWhen(false)] out HeaderNode node) { using Microsoft.VisualStudio.Threading.AsyncReaderWriterLock.Releaser readMainLock = GlobalLocks.ReadOnMainAsync().GetAwaiter().GetResult(); return(HeadersTree.TryGetNode(blockHash, true, out node)); }
private async Task SyncLoopAsync(CancellationToken cancellationToken) { using Microsoft.VisualStudio.Threading.AsyncReaderWriterLock.Releaser readLock = GlobalLocks.ReadOnMainAsync().GetAwaiter().GetResult(); HeaderNode?bestHeaderNode = _chainState.BestHeader; if (!_chainState.TryGetBlockHeader(bestHeaderNode, out BlockHeader? bestBlockHeader)) { ThrowHelper.ThrowNotSupportedException("BestHeader should always be available, this should never happen"); } if (!_status.IsSynchronizingHeaders) { _status.IsSynchronizingHeaders = true; _status.HeadersSyncTimeout = _dateTimeProvider.GetTimeMicros() + HEADERS_DOWNLOAD_TIMEOUT_BASE + HEADERS_DOWNLOAD_TIMEOUT_PER_HEADER * ( (_dateTimeProvider.GetAdjustedTimeAsUnixTimestamp() - bestBlockHeader.TimeStamp) / _consensusParameters.PowTargetSpacing ); /* If possible, start at the block preceding the currently * best known header. This ensures that we always get a * non-empty list of headers back as long as the peer * is up-to-date. With a non-empty response, we can initialise * the peer's known best block. This wouldn't be possible * if we requested starting at pindexBestHeader and * got back an empty response. */ HeaderNode?pindexStart = bestHeaderNode.Previous ?? bestHeaderNode; logger.LogDebug("Starting syncing headers from height {LocatorHeight} (peer starting height: {StartingHeight})", pindexStart.Height, _status.PeerStartingHeight); var newGetHeaderRequest = new GetHeadersMessage { Version = (uint)PeerContext.NegotiatedProtocolVersion.Version, BlockLocator = _chainState.GetLocator(pindexStart), HashStop = UInt256.Zero }; await SendMessageAsync(newGetHeaderRequest).ConfigureAwait(false); } CheckSyncStallingLocked(bestBlockHeader); ConsiderEviction(_dateTimeProvider.GetTime()); }