コード例 #1
0
        private void OnChangeViewReceived(ExtensiblePayload payload, ChangeView message)
        {
            if (message.NewViewNumber <= context.ViewNumber)
            {
                OnRecoveryRequestReceived(payload, message);
            }

            if (context.CommitSent)
            {
                return;
            }

            var expectedView = context.GetMessage <ChangeView>(context.ChangeViewPayloads[message.ValidatorIndex])?.NewViewNumber ?? 0;

            if (message.NewViewNumber <= expectedView)
            {
                return;
            }

            Log($"{nameof(OnChangeViewReceived)}: height={message.BlockIndex} view={message.ViewNumber} index={message.ValidatorIndex} nv={message.NewViewNumber} reason={message.Reason}");
            context.ChangeViewPayloads[message.ValidatorIndex] = payload;
            CheckExpectedView(message.NewViewNumber);
        }
コード例 #2
0
        private void OnChangeViewReceived(ConsensusPayload payload, ChangeView message)
        {
            if (message.NewViewNumber <= context.ViewNumber)
            {
                OnRecoveryRequestReceived(payload);
            }

            if (context.CommitSent())
            {
                return;
            }

            var expectedView = context.ChangeViewPayloads[payload.ValidatorIndex]?.GetDeserializedMessage <ChangeView>().NewViewNumber ?? (byte)0;

            if (message.NewViewNumber <= expectedView)
            {
                return;
            }

            Log($"{nameof(OnChangeViewReceived)}: height={payload.BlockIndex} view={message.ViewNumber} index={payload.ValidatorIndex} nv={message.NewViewNumber}");
            context.ChangeViewPayloads[payload.ValidatorIndex] = payload;
            CheckExpectedView(message.NewViewNumber);
        }
コード例 #3
0
 private void CheckExpectedView(byte viewNumber)
 {
     if (context.ViewNumber >= viewNumber)
     {
         return;
     }
     // if there are `M` change view payloads with NewViewNumber greater than viewNumber, then, it is safe to move
     if (context.ChangeViewPayloads.Count(p => p != null && p.GetDeserializedMessage <ChangeView>().NewViewNumber >= viewNumber) >= context.M)
     {
         if (!context.WatchOnly)
         {
             ChangeView message = context.ChangeViewPayloads[context.MyIndex]?.GetDeserializedMessage <ChangeView>();
             // Communicate the network about my agreement to move to `viewNumber`
             // if my last change view payload, `message`, has NewViewNumber lower than current view to change
             if (message is null || message.NewViewNumber < viewNumber)
             {
                 localNode.Tell(new LocalNode.SendDirectly {
                     Inventory = context.MakeChangeView(ChangeViewReason.ChangeAgreement)
                 });
             }
         }
         InitializeConsensus(viewNumber);
     }
 }
コード例 #4
0
        private void OnChangeViewReceived(ConsensusPayload payload, ChangeView message)
        {
            // We keep track of the payload hashes received in this block, and don't respond with recovery
            // in response to the same payload that we already responded to previously.
            // ChangeView messages include a Timestamp when the change view is sent, thus if a node restarts
            // and issues a change view for the same view, it will have a different hash and will correctly respond
            // again; however replay attacks of the ChangeView message from arbitrary nodes will not trigger an
            // additional recovery message response.
            if (!knownHashes.Add(payload.Hash))
            {
                return;
            }
            if (message.NewViewNumber <= context.ViewNumber)
            {
                if (context.WatchOnly())
                {
                    return;
                }
                if (!context.CommitSent())
                {
                    bool shouldSendRecovery = false;
                    // Limit recovery to be sent from, at least, `f` nodes when the request is from a lower view number.
                    int allowedRecoveryNodeCount = context.F();
                    for (int i = 0; i < allowedRecoveryNodeCount; i++)
                    {
                        var eligibleResponders = context.Validators.Length - 1;
                        var chosenIndex        = (payload.ValidatorIndex + i + message.NewViewNumber) % eligibleResponders;
                        if (chosenIndex >= payload.ValidatorIndex)
                        {
                            chosenIndex++;
                        }
                        if (chosenIndex != context.MyIndex)
                        {
                            continue;
                        }
                        shouldSendRecovery = true;
                        break;
                    }

                    if (!shouldSendRecovery)
                    {
                        return;
                    }
                }
                Log($"send recovery from view: {message.ViewNumber} to view: {context.ViewNumber}");
                localNode.Tell(new LocalNode.SendDirectly {
                    Inventory = context.MakeRecoveryMessage()
                });
            }

            if (context.CommitSent())
            {
                return;
            }

            var expectedView = context.ChangeViewPayloads[payload.ValidatorIndex]?.GetDeserializedMessage <ChangeView>().NewViewNumber ?? (byte)0;

            if (message.NewViewNumber <= expectedView)
            {
                return;
            }

            Log($"{nameof(OnChangeViewReceived)}: height={payload.BlockIndex} view={message.ViewNumber} index={payload.ValidatorIndex} nv={message.NewViewNumber}");
            context.ChangeViewPayloads[payload.ValidatorIndex] = payload;
            CheckExpectedView(message.NewViewNumber);
        }