示例#1
0
        /// <summary>
        /// Generate encrypted messages and put them to round information.
        /// </summary>
        /// <returns></returns>
        private async Task <Dictionary <string, AElfConsensusTriggerInformation> > GenerateEncryptedMessagesAsync()
        {
            var firstRound = await AEDPoSContractStub.GetCurrentRoundInformation.CallAsync(new Empty());

            var randomHashes = Enumerable.Range(0, EconomicContractsTestConstants.InitialCoreDataCenterCount)
                               .Select(_ => Hash.FromString("randomHashes")).ToList();
            var triggers = Enumerable.Range(0, EconomicContractsTestConstants.InitialCoreDataCenterCount).Select(i =>
                                                                                                                 new AElfConsensusTriggerInformation
            {
                Pubkey  = ByteString.CopyFrom(InitialCoreDataCenterKeyPairs[i].PublicKey),
                InValue = randomHashes[i]
            }).ToDictionary(t => t.Pubkey.ToHex(), t => t);

            foreach (var minerInRound in firstRound.RealTimeMinersInformation.Values.OrderBy(m => m.Order))
            {
                var currentKeyPair = InitialCoreDataCenterKeyPairs.First(p => p.PublicKey.ToHex() == minerInRound.Pubkey);

                KeyPairProvider.SetKeyPair(currentKeyPair);

                BlockTimeProvider.SetBlockTime(minerInRound.ExpectedMiningTime);

                var tester            = GetAEDPoSContractStub(currentKeyPair);
                var headerInformation = new AElfConsensusHeaderInformation();
                headerInformation.MergeFrom(
                    (await AEDPoSContractStub.GetConsensusExtraData.CallAsync(triggers[minerInRound.Pubkey]
                                                                              .ToBytesValue())).Value);

                // Update consensus information.
                var toUpdate = headerInformation.Round.ExtractInformationToUpdateConsensus(minerInRound.Pubkey);
                await tester.UpdateValue.SendAsync(toUpdate);
            }

            return(triggers);
        }
        internal static AElfConsensusHeaderInformation ToConsensusHeaderInformation(this BytesValue bytesValue)
        {
            var headerInformation = new AElfConsensusHeaderInformation();

            headerInformation.MergeFrom(bytesValue.Value);
            return(headerInformation);
        }
示例#3
0
        public override TransactionList GenerateConsensusTransactions(BytesValue input)
        {
            var triggerInformation = new AElfConsensusTriggerInformation();

            triggerInformation.MergeFrom(input.Value);
            // Some basic checks.
            Assert(triggerInformation.Pubkey.Any(),
                   "Data to request consensus information should contain pubkey.");

            var pubkey = triggerInformation.Pubkey;
            var consensusInformation = new AElfConsensusHeaderInformation();

            consensusInformation.MergeFrom(GetConsensusBlockExtraData(input, true).Value);
            var transactionList = GenerateTransactionListByExtraData(consensusInformation, pubkey);

            return(transactionList);
        }
示例#4
0
        public async Task DecryptMessage_Test()
        {
            var previousTriggers = await GenerateEncryptedMessagesAsync();

            await BootMinerChangeRoundAsync();

            var currentRound = await AEDPoSContractStub.GetCurrentRoundInformation.CallAsync(new Empty());

            var randomHashes = Enumerable.Range(0, EconomicContractsTestConstants.InitialCoreDataCenterCount)
                               .Select(_ => Hash.FromString("randomHashes")).ToList();
            var triggers = Enumerable.Range(0, EconomicContractsTestConstants.InitialCoreDataCenterCount).Select(i =>
                                                                                                                 new AElfConsensusTriggerInformation
            {
                Pubkey             = ByteString.CopyFrom(InitialCoreDataCenterKeyPairs[i].PublicKey),
                RandomHash         = randomHashes[i],
                PreviousRandomHash = previousTriggers[InitialCoreDataCenterKeyPairs[i].PublicKey.ToHex()].RandomHash
            }).ToDictionary(t => t.Pubkey.ToHex(), t => t);

            // Just `MinimumCount + 1` miners produce blocks.
            foreach (var minerInRound in currentRound.RealTimeMinersInformation.Values.OrderBy(m => m.Order)
                     .Take(MinimumCount + 1))
            {
                var currentKeyPair = InitialCoreDataCenterKeyPairs.First(p => p.PublicKey.ToHex() == minerInRound.Pubkey);

                KeyPairProvider.SetKeyPair(currentKeyPair);

                BlockTimeProvider.SetBlockTime(minerInRound.ExpectedMiningTime);

                var tester            = GetAEDPoSContractStub(currentKeyPair);
                var headerInformation = new AElfConsensusHeaderInformation();
                headerInformation.MergeFrom(
                    (await AEDPoSContractStub.GetInformationToUpdateConsensus.CallAsync(triggers[minerInRound.Pubkey]
                                                                                        .ToBytesValue())).Value);
                // Update consensus information.
                var toUpdate = headerInformation.Round.ExtractInformationToUpdateConsensus(minerInRound.Pubkey);
                await tester.UpdateValue.SendAsync(toUpdate);
            }

            // Won't pass because currently we postpone the revealing of in values to extra block time slot.
            // But in values all filled.
//            var secondRound = await BootMiner.GetCurrentRoundInformation.CallAsync(new Empty());
//            secondRound.RealTimeMinersInformation.Values.Count(v => v.PreviousInValue != null)
//                .ShouldBe(AEDPoSContractTestConstants.InitialMinersCount);
        }
示例#5
0
        public override ValidationResult ValidateConsensusAfterExecution(BytesValue input)
        {
            var headerInformation = new AElfConsensusHeaderInformation();

            headerInformation.MergeFrom(input.Value);
            if (TryToGetCurrentRoundInformation(out var currentRound))
            {
                if (headerInformation.Behaviour == AElfConsensusBehaviour.UpdateValue)
                {
                    headerInformation.Round =
                        currentRound.RecoverFromUpdateValue(headerInformation.Round,
                                                            headerInformation.SenderPubkey.ToHex());
                }

                if (headerInformation.Behaviour == AElfConsensusBehaviour.TinyBlock)
                {
                    headerInformation.Round =
                        currentRound.RecoverFromTinyBlock(headerInformation.Round,
                                                          headerInformation.SenderPubkey.ToHex());
                }

                var isContainPreviousInValue = !currentRound.IsMinerListJustChanged;
                if (headerInformation.Round.GetHash(isContainPreviousInValue) !=
                    currentRound.GetHash(isContainPreviousInValue))
                {
                    Context.LogDebug(() => $"Round information of block header:\n{headerInformation.Round}");
                    Context.LogDebug(() => $"Round information of executing result:\n{currentRound}");
                    return(new ValidationResult
                    {
                        Success = false, Message = "Current round information is different with consensus extra data."
                    });
                }
            }

            return(new ValidationResult {
                Success = true
            });
        }
示例#6
0
        private async Task <AElfConsensusTriggerInformation> GetConsensusTriggerInfoAsync(
            AEDPoSContractImplContainer.AEDPoSContractImplStub contractStub, BytesValue pubkey)
        {
            var command = await contractStub.GetConsensusCommand.CallAsync(pubkey);

            var hint = AElfConsensusHint.Parser.ParseFrom(command.Hint);
            var triggerInformation = new AElfConsensusTriggerInformation
            {
                Behaviour = hint.Behaviour,
                // It doesn't matter for testing.
                InValue         = Hash.FromString($"InValueOf{pubkey}"),
                PreviousInValue = Hash.FromString($"InValueOf{pubkey}"),
                Pubkey          = pubkey.Value
            };

            var consensusExtraData = await contractStub.GetConsensusExtraData.CallAsync(new BytesValue
            {
                Value = triggerInformation.ToByteString()
            });

            var consensusHeaderInformation = new AElfConsensusHeaderInformation();

            consensusHeaderInformation.MergeFrom(consensusExtraData.Value);
            Debug.WriteLine($"Current header information: {consensusHeaderInformation}");

            // Validate consensus extra data.
            {
                var validationResult =
                    await _contractStubs.First().ValidateConsensusBeforeExecution.CallAsync(consensusExtraData);

                if (!validationResult.Success)
                {
                    throw new Exception($"Consensus extra data validation failed: {validationResult.Message}");
                }
            }

            return(triggerInformation);
        }
        public override ValidationResult ValidateConsensusAfterExecution(BytesValue input1)
        {
            var input = new AElfConsensusHeaderInformation();

            input.MergeFrom(input1.Value);
            if (TryToGetCurrentRoundInformation(out var currentRound))
            {
                var isContainPreviousInValue =
                    input.Behaviour != AElfConsensusBehaviour.UpdateValueWithoutPreviousInValue;
                if (input.Round.GetHash(isContainPreviousInValue) != currentRound.GetHash(isContainPreviousInValue))
                {
                    Context.LogDebug(() => $"Round information of block header:\n{input.Round}");
                    Context.LogDebug(() => $"Round information of executing result:\n{currentRound}");
                    return(new ValidationResult
                    {
                        Success = false, Message = "Current round information is different with consensus extra data."
                    });
                }
            }

            return(new ValidationResult {
                Success = true
            });
        }
        public override TransactionList GenerateConsensusTransactions(BytesValue input)
        {
            var triggerInformation = new AElfConsensusTriggerInformation();

            triggerInformation.MergeFrom(input.Value);
            // Some basic checks.
            Assert(triggerInformation.Pubkey.Any(),
                   "Data to request consensus information should contain public key.");

            var publicKey            = triggerInformation.Pubkey;
            var consensusInformation = new AElfConsensusHeaderInformation();

            consensusInformation.MergeFrom(GetConsensusBlockExtraData(input, true).Value);
            var round     = consensusInformation.Round;
            var behaviour = consensusInformation.Behaviour;

            switch (behaviour)
            {
            case AElfConsensusBehaviour.UpdateValueWithoutPreviousInValue:
            case AElfConsensusBehaviour.UpdateValue:
                return(new TransactionList
                {
                    Transactions =
                    {
                        GenerateTransaction(nameof(UpdateValue),
                                            round.ExtractInformationToUpdateConsensus(publicKey.ToHex()))
                    }
                });

            case AElfConsensusBehaviour.TinyBlock:
                var minerInRound = round.RealTimeMinersInformation[publicKey.ToHex()];
                return(new TransactionList
                {
                    Transactions =
                    {
                        GenerateTransaction(nameof(UpdateTinyBlockInformation),
                                            new TinyBlockInput
                        {
                            ActualMiningTime = minerInRound.ActualMiningTimes.Last(),
                            ProducedBlocks = minerInRound.ProducedBlocks,
                            RoundId = round.RoundId
                        })
                    }
                });

            case AElfConsensusBehaviour.NextRound:
                return(new TransactionList
                {
                    Transactions =
                    {
                        GenerateTransaction(nameof(NextRound), round)
                    }
                });

            case AElfConsensusBehaviour.NextTerm:
                return(new TransactionList
                {
                    Transactions =
                    {
                        GenerateTransaction(nameof(NextTerm), round)
                    }
                });

            default:
                throw new ArgumentOutOfRangeException();
            }
        }
示例#9
0
        public async Task MineBlockAsync(List <Transaction> transactions = null, bool withException = false)
        {
            if (!_isSystemContractsDeployed)
            {
                return;
            }

            if (transactions != null)
            {
                await _testDataProvider.AddTransactionListAsync(transactions);
            }

            var currentBlockTime = _testDataProvider.GetBlockTime();

            {
                {
                    var currentRound = await _contractStubs.First().GetCurrentRoundInformation.CallAsync(new Empty());

                    if (currentRound.RoundNumber == 0)
                    {
                        throw new InitializationFailedException("Can't find current round information.");
                    }
                }
            }

            var maximumBlocksCount = (await _contractStubs.First().GetMaximumBlocksCount.CallAsync(new Empty())).Value;

            var(contractStub, pubkey) = GetProperContractStub(currentBlockTime, maximumBlocksCount);
            currentBlockTime          = _testDataProvider.GetBlockTime();

            {
                var currentRound = await _contractStubs.First().GetCurrentRoundInformation.CallAsync(new Empty());

                if (currentRound.RoundNumber == 0)
                {
                    throw new InitializationFailedException("Can't find current round information.");
                }
            }

            var command = await contractStub.GetConsensusCommand.CallAsync(pubkey);

            var hint = AElfConsensusHint.Parser.ParseFrom(command.Hint);
            var triggerInformation = new AElfConsensusTriggerInformation
            {
                Behaviour = hint.Behaviour,
                // It doesn't matter for testing.
                InValue         = Hash.FromString($"InValueOf{pubkey}"),
                PreviousInValue = Hash.FromString($"InValueOf{pubkey}"),
                Pubkey          = pubkey.Value
            };

            var consensusExtraData = await contractStub.GetConsensusExtraData.CallAsync(new BytesValue
            {
                Value = triggerInformation.ToByteString()
            });

            var consensusHeaderInformation = new AElfConsensusHeaderInformation();

            consensusHeaderInformation.MergeFrom(consensusExtraData.Value);
            Debug.WriteLine($"Current header information: {consensusHeaderInformation}");

            // Validate consensus extra data.
            {
                var validationResult =
                    await _contractStubs.First().ValidateConsensusBeforeExecution.CallAsync(consensusExtraData);

                if (!validationResult.Success)
                {
                    throw new Exception($"Consensus extra data validation failed: {validationResult.Message}");
                }
            }

            var consensusTransaction = await contractStub.GenerateConsensusTransactions.CallAsync(new BytesValue
            {
                Value = triggerInformation.ToByteString()
            });

            await MineAsync(contractStub, consensusTransaction.Transactions.First(), withException);

            _currentRound = await _contractStubs.First().GetCurrentRoundInformation.CallAsync(new Empty());

            Debug.WriteLine($"Update current round information.{_currentRound}");
            if (!_isSkipped)
            {
                if (_currentRound.RealTimeMinersInformation.Any(i => i.Value.MissedTimeSlots != 0))
                {
                    var previousRound = await _contractStubs.First().GetPreviousRoundInformation.CallAsync(new Empty());

                    throw new BlockMiningException(
                              $"Someone missed time slot.\n{_currentRound}\n{previousRound}\nCurrent block time: {currentBlockTime}");
                }
            }

            _testDataProvider.SetBlockTime(
                consensusTransaction.Transactions.First().MethodName ==
                nameof(AEDPoSContractImplContainer.AEDPoSContractImplStub.NextTerm)
                    ? currentBlockTime.AddMilliseconds(AEDPoSExtensionConstants.MiningInterval)
                    : currentBlockTime.AddMilliseconds(AEDPoSExtensionConstants.ActualMiningInterval));

            await _testDataProvider.ResetAsync();

            _isSkipped = false;
        }