async Task <bool> DownloadBlockSlices(RemoteSyncItem remote, ChainSyncItem chainSyncItem)
        {
            var chainType  = chainSyncItem.ChainType;
            var chainId    = chainSyncItem.ChainId;
            var chainIndex = chainSyncItem.ChainIndex;

            chainSyncItem.UpdateLastBlockInfo((await remote.Client.DownloadLastBlockInfo(chainType, chainId, chainIndex)).Data);

            var lastBlockId = chainSyncItem.BlockState.LastBlockId;

            if (lastBlockId <= Protocol.InvalidBlockId)
            {
                Log.Debug($"Skipping block slice download for chain {chainId}/{chainIndex}, blockid invalid.", this);
                return(true);
            }

            var remoteLastAvailableSlice = BlockSliceInfo.GetSliceIndex(lastBlockId) - 1;

            if (remoteLastAvailableSlice < 0) // -1: ignore last "hot" slice
            {
                Log.Debug($"Skipping block slice download for chain {chainId}/{chainIndex}, no available remote stored slice found.", this);
                return(true);
            }

            var localStartSlice = 0L;
            var localLast       = BlockStorage.GetBlockSlices(_storage, chainType, chainId, chainIndex, true).LastOrDefault();

            if (localLast.Value != null)
            {
                localStartSlice = localLast.Value.SliceIndex + 1;
            }

            if (!(chainSyncItem.LowestFoundBlockSliceId <= localStartSlice))
            {
                Log.Error($"Download block slices for chain {chainId}/{chainIndex} failed, last local slice is {localStartSlice}, lowest remote slice found is {chainSyncItem.LowestFoundBlockSliceId}.", this);
                return(false);
            }

            var count = 0;

            for (var sliceIndex = localStartSlice; sliceIndex <= remoteLastAvailableSlice; sliceIndex++)
            {
                Log.Trace($"Downloading block slice {sliceIndex}/{remoteLastAvailableSlice} for chain {chainId}/{chainIndex}.", this);
                var sliceData = (await remote.Client.DownloadBlockSlice(_storage, chainType, chainId, chainIndex, sliceIndex)).Data;

                var error = false;
                if (sliceData == null || !sliceData.Move())
                {
                    Log.Trace($"Block slice {sliceIndex} download failed.", this);
                    sliceData?.Delete();
                    error = true;
                }

                sliceData?.Dispose();

                if (error)
                {
                    return(false);
                }

                count++;
            }

            if (count > 0)
            {
                return(await DownloadBlockSlices(remote, chainSyncItem));
            }

            return(true);
        }