示例#1
0
        private byte[] GetCheckableRound(bool isContainPreviousInValue = true)
        {
            var minersInformation = new Dictionary <string, MinerInRound>();

            foreach (var minerInRound in RealTimeMinersInformation.Clone())
            {
                var checkableMinerInRound = minerInRound.Value.Clone();
                checkableMinerInRound.EncryptedPieces.Clear();
                checkableMinerInRound.DecryptedPieces.Clear();
                checkableMinerInRound.ActualMiningTimes.Clear();
                if (!isContainPreviousInValue)
                {
                    checkableMinerInRound.PreviousInValue = Hash.Empty;
                }

                minersInformation.Add(minerInRound.Key, checkableMinerInRound);
            }

            var checkableRound = new Round
            {
                RoundNumber = RoundNumber,
                TermNumber  = TermNumber,
                RealTimeMinersInformation = { minersInformation },
                BlockchainAge             = BlockchainAge
            };

            return(checkableRound.ToByteArray());
        }
示例#2
0
        public bool IsTimeSlotPassed(string publicKey, Timestamp currentBlockTime)
        {
            var miningInterval = GetMiningInterval();

            if (!RealTimeMinersInformation.ContainsKey(publicKey))
            {
                return(false);
            }
            var minerInRound = RealTimeMinersInformation[publicKey];

            if (RoundNumber != 1)
            {
                return(minerInRound.ExpectedMiningTime + new Duration {
                    Seconds = miningInterval.Div(1000)
                } <
                       currentBlockTime);
            }

            var actualStartTimes = FirstMiner().ActualMiningTimes;

            if (actualStartTimes.Count == 0)
            {
                return(false);
            }

            var actualStartTime = actualStartTimes.First();
            var runningTime     = currentBlockTime - actualStartTime;
            var expectedOrder   = runningTime.Seconds.Div(miningInterval.Div(1000)).Add(1);

            return(minerInRound.Order < expectedOrder);
        }
示例#3
0
        public Round RecoverFromUpdateValue(Round providedRound, string pubkey)
        {
            if (!RealTimeMinersInformation.ContainsKey(pubkey) ||
                !providedRound.RealTimeMinersInformation.ContainsKey(pubkey))
            {
                return(this);
            }

            var minerInRound        = RealTimeMinersInformation[pubkey];
            var providedInformation = providedRound.RealTimeMinersInformation[pubkey];

            minerInRound.OutValue                       = providedInformation.OutValue;
            minerInRound.Signature                      = providedInformation.Signature;
            minerInRound.ProducedBlocks                 = providedInformation.ProducedBlocks;
            minerInRound.ProducedTinyBlocks             = providedInformation.ProducedTinyBlocks;
            minerInRound.PreviousInValue                = providedInformation.PreviousInValue;
            minerInRound.ImpliedIrreversibleBlockHeight = providedInformation.ImpliedIrreversibleBlockHeight;
            minerInRound.ActualMiningTimes.Add(providedInformation.ActualMiningTimes);

            foreach (var information in providedRound.RealTimeMinersInformation)
            {
                RealTimeMinersInformation[information.Key].SupposedOrderOfNextRound =
                    information.Value.SupposedOrderOfNextRound;
                RealTimeMinersInformation[information.Key].FinalOrderOfNextRound =
                    information.Value.FinalOrderOfNextRound;
                RealTimeMinersInformation[information.Key].PreviousInValue =
                    information.Value.PreviousInValue;
            }

            return(this);
        }
示例#4
0
 public Timestamp GetExpectedMiningTime(string publicKey)
 {
     return(RealTimeMinersInformation.ContainsKey(publicKey)
         ? RealTimeMinersInformation[publicKey].ExpectedMiningTime
         : new Timestamp {
         Seconds = long.MaxValue
     });
 }
示例#5
0
文件: Round.cs 项目: zhxymh/AElf
        internal bool IsTimeSlotPassed(string publicKey, DateTime dateTime,
                                       out MinerInRound minerInRound)
        {
            minerInRound = null;
            var miningInterval = GetMiningInterval();

            if (!RealTimeMinersInformation.ContainsKey(publicKey))
            {
                return(false);
            }
            minerInRound = RealTimeMinersInformation[publicKey];
            return(minerInRound.ExpectedMiningTime.ToDateTime().AddMilliseconds(miningInterval) <= dateTime);
        }
示例#6
0
        public Round ApplyNormalConsensusData(string publicKey, Hash previousInValue,
                                              Hash outValue, Hash signature)
        {
            if (!RealTimeMinersInformation.ContainsKey(publicKey))
            {
                return(this);
            }

            RealTimeMinersInformation[publicKey].OutValue  = outValue;
            RealTimeMinersInformation[publicKey].Signature = signature;
            if (previousInValue != Hash.Empty)
            {
                RealTimeMinersInformation[publicKey].PreviousInValue = previousInValue;
            }

            var minersCount = RealTimeMinersInformation.Count;
            var sigNum      = signature.ToInt64();

            var supposedOrderOfNextRound = GetAbsModulus(sigNum, minersCount) + 1;

            // Check the existence of conflicts about OrderOfNextRound.
            // If so, modify others'.
            var conflicts = RealTimeMinersInformation.Values
                            .Where(i => i.FinalOrderOfNextRound == supposedOrderOfNextRound).ToList();

            foreach (var orderConflictedMiner in conflicts)
            {
                // Multiple conflicts is unlikely.

                for (var i = supposedOrderOfNextRound + 1; i < minersCount * 2; i++)
                {
                    var maybeNewOrder = i > minersCount ? i % minersCount : i;
                    if (RealTimeMinersInformation.Values.All(m => m.FinalOrderOfNextRound != maybeNewOrder))
                    {
                        RealTimeMinersInformation[orderConflictedMiner.Pubkey].FinalOrderOfNextRound =
                            maybeNewOrder;
                        break;
                    }
                }
            }

            RealTimeMinersInformation[publicKey].SupposedOrderOfNextRound = supposedOrderOfNextRound;
            // Initialize FinalOrderOfNextRound as the value of SupposedOrderOfNextRound
            RealTimeMinersInformation[publicKey].FinalOrderOfNextRound = supposedOrderOfNextRound;

            return(this);
        }
示例#7
0
        public Round RecoverFromTinyBlock(Round providedRound, string pubkey)
        {
            if (!RealTimeMinersInformation.ContainsKey(pubkey) ||
                !providedRound.RealTimeMinersInformation.ContainsKey(pubkey))
            {
                return(this);
            }

            var minerInRound        = RealTimeMinersInformation[pubkey];
            var providedInformation = providedRound.RealTimeMinersInformation[pubkey];

            minerInRound.ProducedBlocks                 = providedInformation.ProducedBlocks;
            minerInRound.ProducedTinyBlocks             = providedInformation.ProducedTinyBlocks;
            minerInRound.ImpliedIrreversibleBlockHeight = providedInformation.ImpliedIrreversibleBlockHeight;
            minerInRound.ActualMiningTimes.Add(providedInformation.ActualMiningTimes);

            return(this);
        }
示例#8
0
文件: Round.cs 项目: zhxymh/AElf
        /// <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 Timestamp ArrangeAbnormalMiningTime(string publicKey, DateTime dateTime,
                                                   int miningInterval = 0)
        {
            if (!RealTimeMinersInformation.ContainsKey(publicKey))
            {
                return(new Timestamp {
                    Seconds = long.MaxValue
                });;
            }

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

            if (!IsTimeSlotPassed(publicKey, dateTime, out var minerInRound) && minerInRound.OutValue == null)
            {
                return(new Timestamp {
                    Seconds = long.MaxValue
                });;
            }

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

            if (RealTimeMinersInformation.ContainsKey(publicKey) && miningInterval > 0)
            {
                var distanceToRoundStartTime = (dateTime - GetStartTime()).TotalMilliseconds;
                var missedRoundsCount        = (int)(distanceToRoundStartTime / TotalMilliseconds(miningInterval));
                var expectedEndTime          = 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(new Timestamp {
                Seconds = long.MaxValue
            });;
        }
示例#9
0
        public Round GetSimpleRound()
        {
            var minersInformation = new Dictionary <string, MinerInRound>();

            foreach (var minerInRound in RealTimeMinersInformation.Clone())
            {
                var checkableMinerInRound = minerInRound.Value.Clone();
                checkableMinerInRound.EncryptedPieces.Clear();
                checkableMinerInRound.DecryptedPieces.Clear();
                checkableMinerInRound.ActualMiningTimes.Clear();
                minersInformation.Add(minerInRound.Key, checkableMinerInRound);
            }

            return(new Round
            {
                RoundNumber = RoundNumber,
                RealTimeMinersInformation = { minersInformation },
            });
        }
示例#10
0
        /// <summary>
        /// Maybe tune other miners' supposed order of next round,
        /// will record this purpose to their FinalOrderOfNextRound field.
        /// </summary>
        /// <param name="publicKey"></param>
        /// <returns></returns>
        public UpdateValueInput ExtractInformationToUpdateConsensus(string publicKey)
        {
            if (!RealTimeMinersInformation.ContainsKey(publicKey))
            {
                return(null);
            }

            var minerInRound = RealTimeMinersInformation[publicKey];

            var tuneOrderInformation = RealTimeMinersInformation.Values
                                       .Where(m => m.FinalOrderOfNextRound != m.SupposedOrderOfNextRound)
                                       .ToDictionary(m => m.Pubkey, m => m.FinalOrderOfNextRound);

            var decryptedPreviousInValues = RealTimeMinersInformation.Values.Where(v =>
                                                                                   v.Pubkey != publicKey && v.DecryptedPreviousInValues.ContainsKey(publicKey))
                                            .ToDictionary(info => info.Pubkey, info => info.DecryptedPreviousInValues[publicKey]);

            var minersPreviousInValues =
                RealTimeMinersInformation.Values.Where(info => info.PreviousInValue != null).ToDictionary(
                    info => info.Pubkey,
                    info => info.PreviousInValue);

            return(new UpdateValueInput
            {
                OutValue = minerInRound.OutValue,
                Signature = minerInRound.Signature,
                PreviousInValue = minerInRound.PreviousInValue ?? Hash.Empty,
                RoundId = RoundId,
                ProducedBlocks = minerInRound.ProducedBlocks,
                ActualMiningTime = minerInRound.ActualMiningTimes.Last(),
                SupposedOrderOfNextRound = minerInRound.SupposedOrderOfNextRound,
                TuneOrderInformation = { tuneOrderInformation },
                EncryptedInValues = { minerInRound.EncryptedInValues },
                DecryptedPreviousInValues = { decryptedPreviousInValues },
                MinersPreviousInValues = { minersPreviousInValues },
                ImpliedIrreversibleBlockHeight = minerInRound.ImpliedIrreversibleBlockHeight
            });
        }
示例#11
0
 /// <summary>
 /// Get miner's order of provided round information.
 /// If provided round doesn't contain this pubkey, return int.MaxValue.
 /// </summary>
 /// <param name="pubkey"></param>
 /// <returns></returns>
 public int GetMiningOrder(string pubkey)
 {
     return(RealTimeMinersInformation.ContainsKey(pubkey)
         ? RealTimeMinersInformation[pubkey].Order
         : int.MaxValue);
 }
示例#12
0
 public Timestamp GetExtraBlockMiningTime()
 {
     return(RealTimeMinersInformation.OrderBy(m => m.Value.Order).Last().Value
            .ExpectedMiningTime
            .AddMilliseconds(GetMiningInterval()));
 }
示例#13
0
文件: Round.cs 项目: zhxymh/AElf
 public MinerInRound GetExtraBlockProducerInformation()
 {
     return(RealTimeMinersInformation.First(bp => bp.Value.IsExtraBlockProducer).Value);
 }