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