예제 #1
0
        public void Sync()
        {
            var retrieveBlocksTasks = new SyncBlocksTask[_peers.Length];

            for (var peerIndex = 0; peerIndex < _peers.Length; peerIndex++)
            {
                retrieveBlocksTasks[peerIndex] = StartPeerSync(peerIndex);
            }

            do
            {
                var tasks = retrieveBlocksTasks.Select(rbt => rbt.Task).ToArray();
                // ReSharper disable once CoVariantArrayConversion
                Task.WaitAny(tasks);
                foreach (var peerTask in retrieveBlocksTasks)
                {
                    ProcessPeerBlocks(peerTask);
                }

                ProcessPendingBlocks();
            } while (SyncBlocks(retrieveBlocksTasks));
            //Continue only if block is full, otherwise peer do not have more blocks

            /*if (retrieveBlocksTask.Task.Result.Length >= _syncBlockPageSize)
             * {
             *      retrieveBlocksTasks[completeTaskIndex] = StartPeerSync(completeTaskIndex);
             *      return true;
             * }*/
        }
예제 #2
0
        private SyncBlocksTask StartPeerSync(int peerIndex, int syncBlockIndex, int syncBlockPageSize)
        {
            _feedback.SyncChainRetrieveBlocks(syncBlockIndex, syncBlockPageSize, _peers[peerIndex].Client.Host.AbsoluteUri);
            var result = new SyncBlocksTask(
                syncBlockIndex,
                syncBlockPageSize,
                _peers[peerIndex].Client.GetBlocksAsync(syncBlockIndex, syncBlockPageSize));

            return(result);
        }
예제 #3
0
        /// <summary>
        /// Try add retrieved peer blocks to block chain or add them as failed to be retried from another peer
        /// </summary>
        /// <param name="peerBlocksTask"></param>
        /// <returns>True if peer are processed successfully</returns>
        private void ProcessPeerBlocks(SyncBlocksTask peerBlocksTask)
        {
            if (peerBlocksTask.Ready)
            {
                if (peerBlocksTask.AwaitProcessing)
                {
                    if (!TryAddBlocks(peerBlocksTask))
                    {
                        FailPeerBlocks(peerBlocksTask);
                    }
                }

                peerBlocksTask.Processed = true;
            }
        }
예제 #4
0
        private bool TryAddBlocks(SyncBlocksTask peerBlocksTask)
        {
            var peerResult = peerBlocksTask.Task.Result;

            if (peerBlocksTask.StartIndex != peerResult[0].Signed.Data.Index)
            {
                return(false);
            }

            var peerBlockNextIndex = CalculatePeerBlockNextIndex(peerBlocksTask.StartIndex);

            if (peerBlockNextIndex >= 0)
            {
                return(AddNewChainBlocks(peerBlockNextIndex, peerResult));
            }
            //Add as pending blocks, as previous blocks are still not synced
            _feedback.SyncChainPendingBlocks(peerBlocksTask.StartIndex, peerBlocksTask.Task.Result.Length);
            _pendingBlocks.Add(peerBlocksTask.StartIndex, peerBlocksTask);
            return(true);
        }
예제 #5
0
 private void FailPeerBlocks(SyncBlocksTask peerBlocksTask)
 {
     _feedback.SyncChainInvalidBlocks(peerBlocksTask.StartIndex, _syncBlockPageSize);
     peerBlocksTask.Failed = true;
     _missingBlocks.Add(peerBlocksTask.StartIndex, peerBlocksTask);
 }