Example #1
0
        public override Empty NextRound(Round input)
        {
            if (TryToGetRoundNumber(out var currentRoundNumber))
            {
                Assert(currentRoundNumber < input.RoundNumber, "Incorrect round number for next round.");
            }

            if (currentRoundNumber == 1)
            {
                SetBlockchainStartTimestamp(input.GetStartTime().ToTimestamp());
                State.DividendContract.Value =
                    State.BasicContractZero.GetContractAddressByName.Call(State.DividendContractSystemName.Value);
                State.TokenContract.Value =
                    State.BasicContractZero.GetContractAddressByName.Call(State.TokenContractSystemName.Value);
            }

            // Update the age of this blockchain
            UpdateBlockchainAge(input.BlockchainAge);

            Assert(TryToGetCurrentRoundInformation(out _), "Failed to get current round information.");
            //UpdateHistoryInformation(input);
            Assert(TryToAddRoundInformation(input), "Failed to add round information.");
            Assert(TryToUpdateRoundNumber(input.RoundNumber), "Failed to update round number.");
            TryToFindLIB();
            return(new Empty());
        }
Example #2
0
        /// <summary>
        /// This method for now is able to handle the situation of a miner keeping offline so many rounds,
        /// by using missedRoundsCount.
        /// </summary>
        /// <param name="round"></param>
        /// <param name="miningInterval"></param>
        /// <param name="missedRoundsCount"></param>
        /// <returns></returns>
        public static Timestamp GetExpectedEndTime(this Round round, int missedRoundsCount = 0, int miningInterval = 0)
        {
            if (miningInterval == 0)
            {
                miningInterval = round.GetMiningInterval();
            }

            return(round.GetStartTime().AddMilliseconds(round.TotalMilliseconds(miningInterval))
                   // Arrange an ending time if this node missed so many rounds.
                   .AddMilliseconds(missedRoundsCount * round.TotalMilliseconds(miningInterval))
                   .ToTimestamp());
        }
Example #3
0
        private void InitialSettings(Round firstRound)
        {
            State.CurrentTermNumberField.Value  = 1;
            State.CurrentRoundNumberField.Value = 1;
            State.AgeField.Value = 1;
            State.TermToFirstRoundMap[1L.ToInt64Value()] = 1L.ToInt64Value();
            SetBlockchainStartTimestamp(firstRound.GetStartTime().ToTimestamp());
            State.MiningIntervalField.Value = firstRound.GetMiningInterval();

            SetInitialMinersAliases(firstRound.RealTimeMinersInformation.Keys);
            SetInitialMinersHistory(firstRound.RealTimeMinersInformation.Keys);

            var miners = firstRound.RealTimeMinersInformation.Keys.ToList().ToMiners(1);

            miners.TermNumber = 1;
            SetMiners(miners);
        }
Example #4
0
        /// <summary>
        /// If one node produced block this round or missed his time slot,
        /// whatever how long he missed, we can give him a consensus command with new time slot
        /// to produce a block (for terminating current round and start new round).
        /// The schedule generated by this command will be cancelled
        /// if this node executed blocks from other nodes.
        ///
        /// Notice:
        /// This method shouldn't return the expected mining time from round information.
        /// To prevent this kind of misuse, this method will return a invalid timestamp
        /// when this node hasn't missed his time slot.
        /// </summary>
        /// <returns></returns>
        public static Timestamp ArrangeAbnormalMiningTime(this Round round, string publicKey, DateTime dateTime,
                                                          int miningInterval = 0)
        {
            if (!round.RealTimeMinersInformation.ContainsKey(publicKey))
            {
                return(DateTime.MaxValue.ToUniversalTime().ToTimestamp());
            }

            if (miningInterval == 0)
            {
                miningInterval = round.GetMiningInterval();
            }

            if (!round.IsTimeSlotPassed(publicKey, dateTime, out var minerInRound) && minerInRound.OutValue == null)
            {
                return(DateTime.MaxValue.ToUniversalTime().ToTimestamp());
            }

            if (round.GetExtraBlockProducerInformation().PublicKey == publicKey)
            {
                var distance = (round.GetExtraBlockMiningTime() - dateTime).TotalMilliseconds;
                if (distance > 0)
                {
                    return(round.GetExtraBlockMiningTime().ToTimestamp());
                }
            }

            if (round.RealTimeMinersInformation.ContainsKey(publicKey) && miningInterval > 0)
            {
                var distanceToRoundStartTime = (dateTime - round.GetStartTime()).TotalMilliseconds;
                var missedRoundsCount        = (int)(distanceToRoundStartTime / round.TotalMilliseconds(miningInterval));
                var expectedEndTime          = round.GetExpectedEndTime(missedRoundsCount, miningInterval);
                return(expectedEndTime.ToDateTime().AddMilliseconds(minerInRound.Order * miningInterval).ToTimestamp());
            }

            // Never do the mining if this node has no privilege to mime or the mining interval is invalid.
            return(DateTime.MaxValue.ToUniversalTime().ToTimestamp());
        }