/// <summary> /// Tries to executes the specified blocks. /// </summary> /// <param name="pendingBlocks"></param> /// <returns></returns> internal async Task <List <PendingBlock> > TryExecuteBlocks(List <PendingBlock> pendingBlocks) { var toRemove = new List <PendingBlock>(); var executed = new List <PendingBlock>(); var blcks = pendingBlocks.ToList(); foreach (var pendingBlock in blcks) { var block = pendingBlock.Block; var res = await _mainChainNode.ExecuteAndAddBlock(block); pendingBlock.BlockValidationResult = res.BlockValidationResult; var blockHexHash = block.GetHash().Value.ToByteArray().ToHex(); int blockIndex = (int)block.Header.Index; if (res.ValidationError == BlockValidationResult.Success) { if (res.Executed) { // The block was executed and validation was a success: remove the pending block. toRemove.Add(pendingBlock); executed.Add(pendingBlock); Interlocked.Increment(ref CurrentExecHeight); lock (currentBlockRequestLock) { _currentBlockRequests.Remove(blockIndex); } _logger?.Debug( $"Block {{ id : {blockHexHash}, index: {blockIndex} }} was successfully executed."); } else { // Validation was successful, but execution failed. _logger?.Warn($"Block {{ id : {blockHexHash}, index: {blockIndex} }} was not executed."); } } else { // The blocks validation failed if (res.BlockValidationResult == BlockValidationResult.AlreadyExecuted || res.BlockValidationResult == BlockValidationResult.OrphanBlock) { // The block is an earlier block and one with the same // height as already been executed so it can safely be // removed from the pending blocks. toRemove.Add(pendingBlock); if (IsInitialSyncInProgress && blockIndex == CurrentExecHeight) { Interlocked.Increment(ref CurrentExecHeight); } _logger?.Warn($"Block {{ id : {blockHexHash}, index: {blockIndex} }} " + $"ignored because validation returned {res.BlockValidationResult}."); } else if (res.BlockValidationResult == BlockValidationResult.Pending) { // The current blocks index is higher than the current height so we're missing if (!ShouldDoInitialSync && (int)block.Header.Index > CurrentExecHeight) { //_networkManager.QueueBlockRequestByIndex(CurrentExecHeight); _logger?.Warn($"Block {{ id : {blockHexHash}, index: {blockIndex} }} is pending, " + $"requesting block with index {CurrentExecHeight}."); break; } } else { _logger?.Warn( $"Block execution failed: {res.Executed}, {res.BlockValidationResult} - {{ id : {blockHexHash}, index: {blockIndex} }}"); } } } // remove the pending blocks foreach (var pdBlock in toRemove) { lock (objLock) { _syncService.RemovePendingBlock(pdBlock); } } if (ShouldDoInitialSync && CurrentExecHeight > SyncTargetHeight && BlockCollection.PendingBlocks.Count == 0) { ShouldDoInitialSync = false; IsInitialSyncInProgress = false; _logger?.Debug("Initial sync is finished at height: " + CurrentExecHeight); SyncFinished?.Invoke(this, EventArgs.Empty); } return(executed); }
public void OnGabSyncFinished(GABHandler gab) { SyncFinished?.Invoke(gab); }