/// <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); }
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); }
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); }
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 }); }
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(); } }
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; }