private void OnTimer(Timer timer) { if (context.BlockSent()) { return; } if (timer.Height != context.BlockIndex || timer.ViewNumber != context.ViewNumber) { return; } Log($"timeout: height={timer.Height} view={timer.ViewNumber}"); if (context.IsPrimary() && !context.RequestSentOrReceived()) { SendPrepareRequest(); } else if ((context.IsPrimary() && context.RequestSentOrReceived()) || context.IsBackup()) { if (context.CommitSent()) { // Re-send commit periodically by sending recover message in case of a network issue. Log($"send recovery to resend commit"); localNode.Tell(new LocalNode.SendDirectly { Inventory = context.MakeRecoveryMessage() }); ChangeTimer(TimeSpan.FromSeconds(Blockchain.SecondsPerBlock << 1)); } else { RequestChangeView(); } } }