/// <summary>
        /// Same process for every behaviour.
        /// </summary>
        /// <param name="input"></param>
        /// <param name="callerMethodName"></param>
        private void ProcessConsensusInformation(dynamic input, [CallerMemberName] string callerMethodName = null)
        {
            Context.LogDebug(() => $"Processing {callerMethodName}");

            /* Privilege check. */
            if (!PreCheck())
            {
                return;
            }

            State.RoundBeforeLatestExecution.Value = GetCurrentRoundInformation(new Empty());

            // The only difference.
            switch (input)
            {
                case Round round when callerMethodName == nameof(NextRound):
                    ProcessNextRound(round);
                    break;
                case Round round when callerMethodName == nameof(NextTerm):
                    ProcessNextTerm(round);
                    break;
                case UpdateValueInput updateValueInput:
                    ProcessUpdateValue(updateValueInput);
                    break;
                case TinyBlockInput tinyBlockInput:
                    ProcessTinyBlock(tinyBlockInput);
                    break;
            }

            var miningInformationUpdated = new MiningInformationUpdated
            {
                // _processingBlockMinerPubkey is set during above process.
                Pubkey = _processingBlockMinerPubkey,
                Behaviour = callerMethodName,
                MiningTime = Context.CurrentBlockTime,
                BlockHeight = Context.CurrentHeight,
                PreviousBlockHash = Context.PreviousBlockHash
            };
            Context.Fire(miningInformationUpdated);
            Context.LogDebug(() => $"Synced mining information: {miningInformationUpdated}");

            // Make sure the method GetMaximumBlocksCount executed no matter what consensus behaviour is.
            var minersCountInTheory = GetMaximumBlocksCount();
            ResetLatestProviderToTinyBlocksCount(minersCountInTheory);

            if (TryToGetCurrentRoundInformation(out var currentRound))
            {
                Context.LogDebug(() =>
                    $"Current round information:\n{currentRound.ToString(_processingBlockMinerPubkey)}");
            }

            // Clear cache.
            _processingBlockMinerPubkey = null;
        }
Beispiel #2
0
        /// <summary>
        /// Same process for every behaviour.
        /// </summary>
        /// <param name="input"></param>
        /// <param name="callerMethodName"></param>
        private void ProcessConsensusInformation(dynamic input, [CallerMemberName] string callerMethodName = null)
        {
            EnsureTransactionOnlyExecutedOnceInOneBlock();

            Context.LogDebug(() => $"Processing {callerMethodName}");

            /* Privilege check. */
            if (!PreCheck())
            {
                return;
            }

            State.RoundBeforeLatestExecution.Value = GetCurrentRoundInformation(new Empty());

            // The only difference.
            switch (input)
            {
            case Round round when callerMethodName == nameof(NextRound):
                ProcessNextRound(round);
                break;

            case Round round when callerMethodName == nameof(NextTerm):
                ProcessNextTerm(round);
                break;

            case UpdateValueInput updateValueInput:
                ProcessUpdateValue(updateValueInput);
                break;

            case TinyBlockInput tinyBlockInput:
                ProcessTinyBlock(tinyBlockInput);
                break;
            }

            var miningInformationUpdated = new MiningInformationUpdated
            {
                // _processingBlockMinerPubkey is set during PreCheck.
                Pubkey            = _processingBlockMinerPubkey,
                Behaviour         = callerMethodName,
                MiningTime        = Context.CurrentBlockTime,
                BlockHeight       = Context.CurrentHeight,
                PreviousBlockHash = Context.PreviousBlockHash
            };

            Context.LogDebug(() => $"Synced mining information: {miningInformationUpdated}");

            // Make sure the method GetMaximumBlocksCount executed no matter what consensus behaviour is.
            var minersCountInTheory = GetMaximumBlocksCount();

            ResetLatestProviderToTinyBlocksCount(minersCountInTheory);

            if (TryToGetCurrentRoundInformation(out var currentRound))
            {
                Context.LogDebug(() =>
                                 $"Current round information:\n{currentRound.ToString(_processingBlockMinerPubkey)}");
            }

            var latestSignature    = GetLatestSignature(currentRound);
            var previousRandomHash = State.RandomHashes[Context.CurrentHeight.Sub(1)];
            var randomHash         = previousRandomHash == null
                ? latestSignature
                : HashHelper.Xor(previousRandomHash, latestSignature);

            State.RandomHashes[Context.CurrentHeight] = randomHash;

            Context.LogDebug(() => $"New random hash generated: {randomHash} - height {Context.CurrentHeight}");

            if (!State.IsMainChain.Value && currentRound.RoundNumber > 1)
            {
                ReleaseSideChainDividendsPool();
            }

            // Clear cache.
            _processingBlockMinerPubkey = null;
        }