示例#1
0
        public async Task HandleEventAsync(ConsensusRequestMiningEventData eventData)
        {
            try
            {
                _taskQueueManager.Enqueue(async() =>
                {
                    if (eventData.BlockTime > new Timestamp {
                        Seconds = 3600
                    } &&
                        eventData.BlockTime + eventData.BlockExecutionTime <
                        TimestampHelper.GetUtcNow())
                    {
                        Logger.LogTrace(
                            $"Will cancel mining due to timeout: Actual mining time: {eventData.BlockTime}, " +
                            $"execution limit: {eventData.BlockExecutionTime.Milliseconds()} ms.");
                    }

                    var block = await _minerService.MineAsync(eventData.PreviousBlockHash,
                                                              eventData.PreviousBlockHeight,
                                                              eventData.BlockTime, eventData.BlockExecutionTime);

                    await _blockchainService.AddBlockAsync(block);

                    var chain = await _blockchainService.GetChainAsync();
                    await LocalEventBus.PublishAsync(new BlockMinedEventData()
                    {
                        BlockHeader = block.Header,
                        HasFork     = block.Height <= chain.BestChainHeight
                    });

                    // Self mined block do not need do verify
                    _taskQueueManager.Enqueue(async() => await _blockAttachService.AttachBlockAsync(block),
                                              KernelConstants.UpdateChainQueueName);
                }, KernelConstants.ConsensusRequestMiningQueueName);
            }
            catch (Exception e)
            {
                Logger.LogError(e.ToString());
                throw;
            }
        }
        private bool ValidateBlockMiningTime(Timestamp blockTime, Timestamp miningDueTime,
                                             Duration blockExecutionDuration)
        {
            if (IsGenesisBlockMining(blockTime))
            {
                return(true);
            }

            if (miningDueTime < blockTime + blockExecutionDuration)
            {
                Logger.LogWarning(
                    $"Mining canceled because mining time slot expired. MiningDueTime: {miningDueTime}, BlockTime: {blockTime}, Duration: {blockExecutionDuration}");
                return(false);
            }

            if (blockTime + blockExecutionDuration < TimestampHelper.GetUtcNow())
            {
                Logger.LogTrace($"Will cancel mining due to timeout: Actual mining time: {blockTime}, " +
                                $"execution limit: {blockExecutionDuration.Milliseconds()} ms.");
                return(false);
            }

            return(true);
        }
示例#3
0
        public async Task HandleEvent_Test()
        {
            BlockMinedEventData blockMinedEventData = null;

            _localEventBus.Subscribe <BlockMinedEventData>(d =>
            {
                blockMinedEventData = d;
                return(Task.CompletedTask);
            });

            var chain = await _blockchainService.GetChainAsync();

            var bestChainHash   = chain.BestChainHash;
            var bestChainHeight = chain.BestChainHeight;

            _testContext.MockConsensusService.Verify(
                s => s.TriggerConsensusAsync(It.IsAny <ChainContext>()), Times.Exactly(10));

            {
                var eventData = new ConsensusRequestMiningEventData(HashHelper.ComputeFrom("NotBestChain"),
                                                                    bestChainHeight,
                                                                    TimestampHelper.GetUtcNow(), TimestampHelper.DurationFromMilliseconds(500),
                                                                    TimestampHelper.GetUtcNow().AddMilliseconds(499));

                await HandleConsensusRequestMiningEventAsync(eventData);

                blockMinedEventData.ShouldBeNull();
                chain = await _blockchainService.GetChainAsync();

                chain.BestChainHeight.ShouldBe(bestChainHeight);
                chain.BestChainHash.ShouldBe(bestChainHash);

                _testContext.MockConsensusService.Verify(
                    s => s.TriggerConsensusAsync(It.IsAny <ChainContext>()), Times.Exactly(10));
            }

            {
                var eventData = new ConsensusRequestMiningEventData(bestChainHash, bestChainHeight,
                                                                    TimestampHelper.GetUtcNow(), TimestampHelper.DurationFromMilliseconds(500),
                                                                    TimestampHelper.GetUtcNow().AddMilliseconds(499));

                await HandleConsensusRequestMiningEventAsync(eventData);

                blockMinedEventData.ShouldBeNull();
                chain = await _blockchainService.GetChainAsync();

                chain.BestChainHeight.ShouldBe(bestChainHeight);
                chain.BestChainHash.ShouldBe(bestChainHash);

                _testContext.MockConsensusService.Verify(
                    s => s.TriggerConsensusAsync(It.IsAny <ChainContext>()), Times.Exactly(11));
            }

            {
                var eventData = new ConsensusRequestMiningEventData(bestChainHash, bestChainHeight,
                                                                    TimestampHelper.GetUtcNow(), TimestampHelper.DurationFromMilliseconds(500),
                                                                    TimestampHelper.GetUtcNow().AddSeconds(30));

                await HandleConsensusRequestMiningEventAsync(eventData);

                blockMinedEventData.ShouldNotBeNull();
                blockMinedEventData.BlockHeader.Height.ShouldBe(bestChainHeight + 1);
                blockMinedEventData.BlockHeader.PreviousBlockHash.ShouldBe(bestChainHash);

                chain = await _blockchainService.GetChainAsync();

                chain.Branches.ShouldContainKey(blockMinedEventData.BlockHeader.GetHash().ToStorageKey());

                (await _blockchainService.HasBlockAsync(blockMinedEventData.BlockHeader.GetHash())).ShouldBeTrue();

                _testContext.MockConsensusService.Verify(
                    s => s.TriggerConsensusAsync(It.IsAny <ChainContext>()), Times.Exactly(11));
            }
        }
示例#4
0
        public async Task MinAsync_Success_Test()
        {
            var chain = await _chainService.GetChainAsync();

            var hash   = chain.BestChainHash;
            var height = chain.BestChainHeight;

            var blockHeader = await _minerService.CreateTemplateCacheAsync(hash, height, TimestampHelper.GetUtcNow(),
                                                                           TimestampHelper.DurationFromMinutes(1));

            var byteString = blockHeader.ToByteString();

            var bytes = byteString.ToByteArray();


            //Send Bytes to Client

            #region Client Side

            //Client side, you can search nonce and replace it

            var nonce = BitConverter.GetBytes(long.MaxValue - 1);

            var start = bytes.Find(nonce);

            start.ShouldBeGreaterThan(0);

            for (int i = 0; i < nonce.Length; i++)
            {
                bytes[start + i] = 9; //change nonce
            }

            bytes.Find(nonce).ShouldBe(-1);

            var newHeader = BlockHeader.Parser.ParseFrom(ByteString.CopyFrom(bytes));

            //Test mining method
            newHeader.GetHash().ShouldBe(Hash.FromRawBytes(newHeader.ToByteArray()));
            newHeader.GetHash().ShouldBe(Hash.FromRawBytes(bytes));


            //Start mining

            Random r = new Random();

            while (Hash.FromRawBytes(bytes).Value[0] != 0)
            {
                //find first hash byte is 0

                for (int i = 0; i < nonce.Length; i++)
                {
                    bytes[start + i] = (byte)r.Next();  //change nonce, very slow, just for demo
                }
            }

            #endregion

            //Send bytes to Server

            newHeader = BlockHeader.Parser.ParseFrom(ByteString.CopyFrom(bytes));

            var newHeaderHash = newHeader.GetHash();

            newHeaderHash.Value[0].ShouldBe((byte)0);  // first byte should be zero

            var block = await _minerService.ChangeTemplateCacheBlockHeaderAndClearCacheAsync(newHeader);

            block.GetHash().ShouldBe(newHeader.GetHash()); // check new block's header
            block.Header.Signature.ShouldBeEmpty();        // check signature
        }
        public Task HandleEventAsync(ConsensusRequestMiningEventData eventData)
        {
            try
            {
                _taskQueueManager.Enqueue(async() =>
                {
                    var chain = await _blockchainService.GetChainAsync();
                    if (eventData.PreviousBlockHash != chain.BestChainHash)
                    {
                        Logger.LogWarning("Mining canceled because best chain already updated.");
                        return;
                    }

                    if (!ValidateBlockMiningTime(eventData.BlockTime, eventData.MiningDueTime,
                                                 eventData.BlockExecutionTime))
                    {
                        await TriggerConsensusEventAsync(chain.BestChainHash, chain.BestChainHeight);
                        return;
                    }

                    var blockExecutionDuration =
                        CalculateBlockMiningDuration(eventData.BlockTime, eventData.BlockExecutionTime);

                    Block block;
                    try
                    {
                        block = await _minerService.MineAsync(eventData.PreviousBlockHash,
                                                              eventData.PreviousBlockHeight, eventData.BlockTime, blockExecutionDuration);
                    }
                    catch (Exception)
                    {
                        await TriggerConsensusEventAsync(chain.BestChainHash, chain.BestChainHeight);
                        throw;
                    }

                    if (TimestampHelper.GetUtcNow() <= eventData.MiningDueTime - blockExecutionDuration)
                    {
                        await _blockchainService.AddBlockAsync(block);

                        Logger.LogTrace("Before enqueue attach job.");
                        _taskQueueManager.Enqueue(async() => await _blockAttachService.AttachBlockAsync(block),
                                                  KernelConstants.UpdateChainQueueName);

                        Logger.LogTrace("Before publish block.");

                        await LocalEventBus.PublishAsync(new BlockMinedEventData
                        {
                            BlockHeader = block.Header,
//                            HasFork = block.Height <= chain.BestChainHeight
                        });
                    }
                    else
                    {
                        Logger.LogWarning(
                            $"Discard block {block.Height} and trigger once again because mining time slot expired. " +
                            $"MiningDueTime : {eventData.MiningDueTime}, " +
                            $"block execution duration limit : {blockExecutionDuration}");
                        await TriggerConsensusEventAsync(chain.BestChainHash, chain.BestChainHeight);
                    }
                }, KernelConstants.ConsensusRequestMiningQueueName);

                return(Task.CompletedTask);
            }
            catch (Exception e)
            {
                Logger.LogError(e.ToString());
                throw;
            }
        }
示例#6
0
        public async Task HandleEventAsync_Test()
        {
            var chain = await _chainService.GetChainAsync();

            var hash      = chain.BestChainHash;
            var height    = chain.BestChainHeight;
            var eventData =
                new ConsensusRequestMiningEventData(hash, height, TimestampHelper.GetUtcNow(),
                                                    TimestampHelper.DurationFromSeconds(60), TimestampHelper.GetUtcNow().AddDays(1));

            await _miningEventHandler.HandleEventAsync(eventData);
        }