public async Task <BytesValue> GetTriggerInformationForConsensusTransactionsAsync(BytesValue consensusCommandBytes) { if (consensusCommandBytes == null) { return(new AElfConsensusTriggerInformation { Pubkey = PublicKey, Behaviour = AElfConsensusBehaviour.UpdateValue }.ToBytesValue()); } var command = consensusCommandBytes.ToConsensusCommand(); var behaviour = command.Hint.ToAElfConsensusHint().Behaviour; var bestChainLastBlockHeader = await _blockchainService.GetBestChainLastBlockHeaderAsync(); if (behaviour == AElfConsensusBehaviour.UpdateValue || behaviour == AElfConsensusBehaviour.UpdateValueWithoutPreviousInValue) { var trigger = new AElfConsensusTriggerInformation { Pubkey = PublicKey, RandomHash = _randomHashCacheService.GetRandomHash(bestChainLastBlockHeader.GetHash()), PreviousRandomHash = _randomHashCacheService.GetLatestGeneratedBlockRandomHash(), Behaviour = behaviour }; return(trigger.ToBytesValue()); } return(new AElfConsensusTriggerInformation { Pubkey = PublicKey, Behaviour = behaviour }.ToBytesValue()); }
private void UpdateLatestSecretPieces(Round updatedRound, string pubkey, AElfConsensusTriggerInformation triggerInformation) { foreach (var encryptedPiece in triggerInformation.EncryptedPieces) { updatedRound.RealTimeMinersInformation[pubkey].EncryptedPieces .Add(encryptedPiece.Key, encryptedPiece.Value); } foreach (var decryptedPiece in triggerInformation.DecryptedPieces) { if (updatedRound.RealTimeMinersInformation.ContainsKey(decryptedPiece.Key)) { updatedRound.RealTimeMinersInformation[decryptedPiece.Key].DecryptedPieces[pubkey] = decryptedPiece.Value; } } foreach (var revealedInValue in triggerInformation.RevealedInValues) { if (updatedRound.RealTimeMinersInformation.ContainsKey(revealedInValue.Key) && (updatedRound.RealTimeMinersInformation[revealedInValue.Key].PreviousInValue == Hash.Empty || updatedRound.RealTimeMinersInformation[revealedInValue.Key].PreviousInValue == null)) { updatedRound.RealTimeMinersInformation[revealedInValue.Key].PreviousInValue = revealedInValue.Value; } } }
private BytesValue GetConsensusBlockExtraData(BytesValue input, bool isGeneratingTransactions = false) { var triggerInformation = new AElfConsensusTriggerInformation(); triggerInformation.MergeFrom(input.Value); Assert(triggerInformation.Pubkey.Any(), "Invalid pubkey."); if (!TryToGetCurrentRoundInformation(out var currentRound)) { Assert(false, "Failed to get current round information."); } var publicKeyBytes = triggerInformation.Pubkey; var pubkey = publicKeyBytes.ToHex(); LogIfPreviousMinerHasNotProduceEnoughTinyBlocks(currentRound, pubkey); var information = new AElfConsensusHeaderInformation(); switch (triggerInformation.Behaviour) { case AElfConsensusBehaviour.UpdateValue: information = GetConsensusExtraDataToPublishOutValue(currentRound, pubkey, triggerInformation); if (!isGeneratingTransactions) { information.Round = information.Round.GetUpdateValueRound(pubkey); } break; case AElfConsensusBehaviour.TinyBlock: information = GetConsensusExtraDataForTinyBlock(currentRound, pubkey, triggerInformation); break; case AElfConsensusBehaviour.NextRound: information = GetConsensusExtraDataForNextRound(currentRound, pubkey, triggerInformation); break; case AElfConsensusBehaviour.NextTerm: information = GetConsensusExtraDataForNextTerm(pubkey, triggerInformation); break; } if (!isGeneratingTransactions) { information.Round.DeleteSecretSharingInformation(); } return(information.ToBytesValue()); }
public BytesValue GetTriggerInformationForConsensusTransactions(BytesValue consensusCommandBytes) { if (consensusCommandBytes == null) { return(new AElfConsensusTriggerInformation { Pubkey = Pubkey, Behaviour = AElfConsensusBehaviour.UpdateValue }.ToBytesValue()); } var command = consensusCommandBytes.ToConsensusCommand(); var hint = command.Hint.ToAElfConsensusHint(); if (hint.Behaviour == AElfConsensusBehaviour.UpdateValue) { var inValue = _inValueCache.GetInValue(hint.RoundId); var trigger = new AElfConsensusTriggerInformation { Pubkey = Pubkey, InValue = inValue, PreviousInValue = _inValueCache.GetInValue(hint.PreviousRoundId), Behaviour = hint.Behaviour, }; var secretPieces = _secretSharingService.GetEncryptedPieces(hint.RoundId); foreach (var secretPiece in secretPieces) { trigger.EncryptedPieces.Add(secretPiece.Key, ByteString.CopyFrom(secretPiece.Value)); } var decryptedPieces = _secretSharingService.GetDecryptedPieces(hint.RoundId); foreach (var decryptedPiece in decryptedPieces) { trigger.DecryptedPieces.Add(decryptedPiece.Key, ByteString.CopyFrom(decryptedPiece.Value)); } var revealedInValues = _secretSharingService.GetRevealedInValues(hint.RoundId); foreach (var revealedInValue in revealedInValues) { trigger.RevealedInValues.Add(revealedInValue.Key, revealedInValue.Value); } return(trigger.ToBytesValue()); } return(new AElfConsensusTriggerInformation { Pubkey = Pubkey, Behaviour = hint.Behaviour }.ToBytesValue()); }
private AElfConsensusHeaderInformation GetConsensusExtraDataForNextTerm(string publicKey, AElfConsensusTriggerInformation triggerInformation) { var firstRoundOfNextTerm = GenerateFirstRoundOfNextTerm(publicKey, State.MiningInterval.Value); Assert(firstRoundOfNextTerm.RoundId != 0, "Failed to generate new round information."); return(new AElfConsensusHeaderInformation { SenderPubkey = publicKey.ToByteString(), Round = firstRoundOfNextTerm, Behaviour = triggerInformation.Behaviour }); }
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); }
private AElfConsensusHeaderInformation GetConsensusExtraDataForNextTerm(string pubkey, AElfConsensusTriggerInformation triggerInformation) { var firstRoundOfNextTerm = GenerateFirstRoundOfNextTerm(pubkey, State.MiningInterval.Value); Assert(firstRoundOfNextTerm.RoundId != 0, "Failed to generate new round information."); if (firstRoundOfNextTerm.RealTimeMinersInformation.ContainsKey(pubkey)) { firstRoundOfNextTerm.RealTimeMinersInformation[pubkey].ProducedTinyBlocks = 1; } return(new AElfConsensusHeaderInformation { SenderPubkey = pubkey.ToByteString(), Round = firstRoundOfNextTerm, Behaviour = triggerInformation.Behaviour }); }
public async Task MineBlockAsync(List <Transaction> transactions = null) { if (!_isSystemContractsDeployed) { return; } if (transactions != null) { await _testDataProvider.AddTransactionListAsync(transactions); } var currentBlockTime = _testDataProvider.GetBlockTime(); var(contractStub, pubkey) = GetProperContractStub(currentBlockTime); 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. RandomHash = Hash.FromString($"RandomHashOf{pubkey}"), PreviousRandomHash = Hash.FromString($"RandomHashOf{pubkey}"), Pubkey = pubkey.Value }; var consensusTransaction = await contractStub.GenerateConsensusTransactions.CallAsync(new BytesValue { Value = triggerInformation.ToByteString() }); await MineAsync(contractStub, consensusTransaction.Transactions.First()); _currentRound = await _contractStubs.First().GetCurrentRoundInformation.CallAsync(new Empty()); _testDataProvider.SetBlockTime( consensusTransaction.Transactions.First().MethodName == nameof(AEDPoSContractImplContainer.AEDPoSContractImplStub.NextTerm) ? currentBlockTime.AddMilliseconds(AEDPoSExtensionConstants.MiningInterval) : currentBlockTime.AddMilliseconds(AEDPoSExtensionConstants.ActualMiningInterval)); await _testDataProvider.ResetAsync(); }
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 BytesValue GetTriggerInformationForBlockHeaderExtraData(BytesValue consensusCommandBytes) { if (consensusCommandBytes == null) { return(new AElfConsensusTriggerInformation { Pubkey = Pubkey, Behaviour = AElfConsensusBehaviour.UpdateValue }.ToBytesValue()); } var command = consensusCommandBytes.ToConsensusCommand(); var hint = command.Hint.ToAElfConsensusHint(); if (hint.Behaviour == AElfConsensusBehaviour.UpdateValue) { var newInValue = _inValueCache.GetInValue(hint.RoundId); var previousInValue = _inValueCache.GetInValue(hint.PreviousRoundId); Logger.LogTrace($"New in value {newInValue} for round of id {hint.RoundId}"); Logger.LogTrace($"Previous in value {previousInValue} for round of id {hint.PreviousRoundId}"); var trigger = new AElfConsensusTriggerInformation { Pubkey = Pubkey, InValue = newInValue, PreviousInValue = previousInValue, Behaviour = hint.Behaviour }; return(trigger.ToBytesValue()); } return(new AElfConsensusTriggerInformation { Pubkey = Pubkey, Behaviour = hint.Behaviour }.ToBytesValue()); }
private AElfConsensusHeaderInformation GetConsensusExtraDataForNextRound(Round currentRound, string pubkey, AElfConsensusTriggerInformation triggerInformation) { if (!GenerateNextRoundInformation(currentRound, Context.CurrentBlockTime, out var nextRound)) { Assert(false, "Failed to generate next round information."); } if (!nextRound.RealTimeMinersInformation.Keys.Contains(pubkey)) { return(new AElfConsensusHeaderInformation { SenderPubkey = pubkey.ToByteString(), Round = nextRound, Behaviour = triggerInformation.Behaviour }); } RevealSharedInValues(currentRound, pubkey); nextRound.RealTimeMinersInformation[pubkey].ProducedBlocks = nextRound.RealTimeMinersInformation[pubkey].ProducedBlocks.Add(1); Context.LogDebug(() => $"Mined blocks: {nextRound.GetMinedBlocks()}"); nextRound.ExtraBlockProducerOfPreviousRound = pubkey; nextRound.RealTimeMinersInformation[pubkey].ProducedTinyBlocks = 1; nextRound.RealTimeMinersInformation[pubkey].ActualMiningTimes .Add(Context.CurrentBlockTime); return(new AElfConsensusHeaderInformation { SenderPubkey = pubkey.ToByteString(), Round = nextRound, Behaviour = triggerInformation.Behaviour }); }
private AElfConsensusHeaderInformation GetConsensusExtraDataForTinyBlock(Round currentRound, string pubkey, AElfConsensusTriggerInformation triggerInformation) { currentRound.RealTimeMinersInformation[pubkey].ProducedTinyBlocks = currentRound .RealTimeMinersInformation[pubkey].ProducedTinyBlocks.Add(1); currentRound.RealTimeMinersInformation[pubkey].ProducedBlocks = currentRound.RealTimeMinersInformation[pubkey].ProducedBlocks.Add(1); currentRound.RealTimeMinersInformation[pubkey].ActualMiningTimes .Add(Context.CurrentBlockTime); return(new AElfConsensusHeaderInformation { SenderPubkey = pubkey.ToByteString(), Round = currentRound.GetTinyBlockRound(pubkey), Behaviour = triggerInformation.Behaviour }); }
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; }
private AElfConsensusHeaderInformation GetConsensusExtraDataToPublishOutValue(Round currentRound, string publicKey, AElfConsensusTriggerInformation triggerInformation) { currentRound.RealTimeMinersInformation[publicKey].ProducedTinyBlocks = currentRound .RealTimeMinersInformation[publicKey].ProducedTinyBlocks.Add(1); currentRound.RealTimeMinersInformation[publicKey].ProducedBlocks = currentRound.RealTimeMinersInformation[publicKey].ProducedBlocks.Add(1); currentRound.RealTimeMinersInformation[publicKey].ActualMiningTimes .Add(Context.CurrentBlockTime); Assert(triggerInformation.RandomHash != null, "Random hash should not be null."); var inValue = currentRound.CalculateInValue(triggerInformation.RandomHash); var outValue = Hash.FromMessage(inValue); var signature = Hash.FromTwoHashes(outValue, triggerInformation.RandomHash); // Just initial signature value. var previousInValue = Hash.Empty; // Just initial previous in value. if (TryToGetPreviousRoundInformation(out var previousRound) && !IsFirstRoundOfCurrentTerm(out _)) { signature = previousRound.CalculateSignature(inValue); if (triggerInformation.PreviousRandomHash != null && triggerInformation.PreviousRandomHash != Hash.Empty) { // If PreviousRandomHash is null or Hash.Empty, it means the sender unable or unwilling to publish his previous in value. previousInValue = previousRound.CalculateInValue(triggerInformation.PreviousRandomHash); // Self check. if (Hash.FromMessage(previousInValue) != previousRound.RealTimeMinersInformation[publicKey].OutValue) { Context.LogDebug(() => "Failed to produce block at previous round?"); previousInValue = Hash.Empty; } } } var updatedRound = currentRound.ApplyNormalConsensusData(publicKey, previousInValue, outValue, signature); updatedRound.RealTimeMinersInformation[publicKey].ImpliedIrreversibleBlockHeight = Context.CurrentHeight; ShareInValueOfCurrentRound(updatedRound, previousRound, inValue, publicKey); // To publish Out Value. return(new AElfConsensusHeaderInformation { SenderPubkey = publicKey.ToByteString(), Round = updatedRound, Behaviour = triggerInformation.Behaviour }); }
private AElfConsensusHeaderInformation GetConsensusExtraDataToPublishOutValue(Round currentRound, string pubkey, AElfConsensusTriggerInformation triggerInformation) { currentRound.RealTimeMinersInformation[pubkey].ProducedTinyBlocks = currentRound .RealTimeMinersInformation[pubkey].ProducedTinyBlocks.Add(1); currentRound.RealTimeMinersInformation[pubkey].ProducedBlocks = currentRound.RealTimeMinersInformation[pubkey].ProducedBlocks.Add(1); currentRound.RealTimeMinersInformation[pubkey].ActualMiningTimes .Add(Context.CurrentBlockTime); Assert(triggerInformation.InValue != null, "In value should not be null."); var outValue = Hash.FromMessage(triggerInformation.InValue); var signature = Hash.FromTwoHashes(outValue, triggerInformation.InValue); // Just initial signature value. var previousInValue = Hash.Empty; // Just initial previous in value. if (TryToGetPreviousRoundInformation(out var previousRound) && !IsFirstRoundOfCurrentTerm(out _)) { signature = previousRound.CalculateSignature(triggerInformation.InValue); Context.LogDebug( () => $"Previous in value in trigger information: {triggerInformation.PreviousInValue}"); if (triggerInformation.PreviousInValue != null && triggerInformation.PreviousInValue != Hash.Empty) { // Self check. if (Hash.FromMessage(triggerInformation.PreviousInValue) != previousRound.RealTimeMinersInformation[pubkey].OutValue) { Context.LogDebug(() => "Failed to produce block at previous round?"); previousInValue = Hash.Empty; } else { previousInValue = triggerInformation.PreviousInValue; } } } var updatedRound = currentRound.ApplyNormalConsensusData(pubkey, previousInValue, outValue, signature); Context.LogDebug( () => $"Previous in value after ApplyNormalConsensusData: {updatedRound.RealTimeMinersInformation[pubkey].PreviousInValue}"); updatedRound.RealTimeMinersInformation[pubkey].ImpliedIrreversibleBlockHeight = Context.CurrentHeight; // Update secret pieces of latest in value. foreach (var encryptedPiece in triggerInformation.EncryptedPieces) { updatedRound.RealTimeMinersInformation[pubkey].EncryptedPieces .Add(encryptedPiece.Key, encryptedPiece.Value); } foreach (var decryptedPiece in triggerInformation.DecryptedPieces) { if (updatedRound.RealTimeMinersInformation.ContainsKey(decryptedPiece.Key)) { updatedRound.RealTimeMinersInformation[decryptedPiece.Key].DecryptedPieces[pubkey] = decryptedPiece.Value; } } foreach (var revealedInValue in triggerInformation.RevealedInValues) { if (updatedRound.RealTimeMinersInformation.ContainsKey(revealedInValue.Key) && (updatedRound.RealTimeMinersInformation[revealedInValue.Key].PreviousInValue == Hash.Empty || updatedRound.RealTimeMinersInformation[revealedInValue.Key].PreviousInValue == null)) { updatedRound.RealTimeMinersInformation[revealedInValue.Key].PreviousInValue = revealedInValue.Value; } } // To publish Out Value. return(new AElfConsensusHeaderInformation { SenderPubkey = pubkey.ToByteString(), Round = updatedRound, Behaviour = triggerInformation.Behaviour }); }
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(); } }
private AElfConsensusHeaderInformation GetConsensusExtraDataToPublishOutValue(Round currentRound, string pubkey, AElfConsensusTriggerInformation triggerInformation) { currentRound.RealTimeMinersInformation[pubkey].ProducedTinyBlocks = currentRound .RealTimeMinersInformation[pubkey].ProducedTinyBlocks.Add(1); currentRound.RealTimeMinersInformation[pubkey].ProducedBlocks = currentRound.RealTimeMinersInformation[pubkey].ProducedBlocks.Add(1); currentRound.RealTimeMinersInformation[pubkey].ActualMiningTimes .Add(Context.CurrentBlockTime); Assert(triggerInformation.InValue != null, "In value should not be null."); var outValue = Hash.FromMessage(triggerInformation.InValue); var signature = Hash.FromTwoHashes(outValue, triggerInformation.InValue); // Just initial signature value. var previousInValue = Hash.Empty; // Just initial previous in value. if (TryToGetPreviousRoundInformation(out var previousRound) && !IsFirstRoundOfCurrentTerm(out _)) { if (triggerInformation.PreviousInValue != null && triggerInformation.PreviousInValue != Hash.Empty) { Context.LogDebug( () => $"Previous in value in trigger information: {triggerInformation.PreviousInValue}"); // Self check. if (previousRound.RealTimeMinersInformation.ContainsKey(pubkey) && Hash.FromMessage(triggerInformation.PreviousInValue) != previousRound.RealTimeMinersInformation[pubkey].OutValue) { Context.LogDebug(() => "Failed to produce block at previous round?"); previousInValue = Hash.Empty; } else { previousInValue = triggerInformation.PreviousInValue; } signature = previousRound.CalculateSignature(triggerInformation.PreviousInValue); } else { var fakePreviousInValue = Hash.FromString(pubkey.Append(Context.CurrentHeight.ToString())); if (previousRound.RealTimeMinersInformation.ContainsKey(pubkey) && previousRound.RoundNumber != 1) { var appointedPreviousInValue = previousRound.RealTimeMinersInformation[pubkey].InValue; if (appointedPreviousInValue != null) { fakePreviousInValue = appointedPreviousInValue; } Context.LogDebug(() => $"TEST:\n{previousRound.ToString(pubkey)}\nInValue: {fakePreviousInValue}"); signature = previousRound.CalculateSignature(fakePreviousInValue); } else { // This miner appears first time in current round, like as a replacement of evil miner. signature = previousRound.CalculateSignature(fakePreviousInValue); } } } var updatedRound = currentRound.ApplyNormalConsensusData(pubkey, previousInValue, outValue, signature); Context.LogDebug( () => $"Previous in value after ApplyNormalConsensusData: " + $"{updatedRound.RealTimeMinersInformation[pubkey].PreviousInValue}"); updatedRound.RealTimeMinersInformation[pubkey].ImpliedIrreversibleBlockHeight = Context.CurrentHeight; // Update secret pieces of latest in value. UpdateLatestSecretPieces(updatedRound, pubkey, triggerInformation); // To publish Out Value. return(new AElfConsensusHeaderInformation { SenderPubkey = pubkey.ToByteString(), Round = updatedRound, Behaviour = triggerInformation.Behaviour }); }