Esempio n. 1
0
        /// <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);
 }