private void OnTimeout(object state) { lock (context) { if (timer_height != context.BlockIndex || timer_view != context.ViewNumber) { return; } Log($"timeout: height={timer_height} view={timer_view} state={context.State}"); if (context.State.HasFlag(ConsensusState.Primary) && !context.State.HasFlag(ConsensusState.RequestSent)) { Log($"send perpare request: height={timer_height} view={timer_view}"); context.State |= ConsensusState.RequestSent; if (!context.State.HasFlag(ConsensusState.SignatureSent)) { context.Timestamp = Math.Max(DateTime.Now.ToTimestamp(), Blockchain.Default.GetHeader(context.PrevHash).Timestamp + 1); context.Nonce = GetNonce(); List <Transaction> transactions = LocalNode.GetMemoryPool().Where(p => CheckPolicy(p)).ToList(); if (transactions.Count >= MaxTransactionsPerBlock) { transactions = transactions.OrderByDescending(p => p.NetworkFee / p.Size).Take(MaxTransactionsPerBlock - 1).ToList(); } transactions.Insert(0, CreateMinerTransaction(transactions, context.BlockIndex, context.Nonce)); context.TransactionHashes = transactions.Select(p => p.Hash).ToArray(); context.Transactions = transactions.ToDictionary(p => p.Hash); context.NextConsensus = Blockchain.GetConsensusAddress(Blockchain.Default.GetValidators(transactions).ToArray()); context.Signatures[context.MyIndex] = context.MakeHeader().Sign(wallet.GetKey(context.Validators[context.MyIndex])); } SignAndRelay(context.MakePerpareRequest()); timer.Change(TimeSpan.FromSeconds(Blockchain.SecondsPerBlock << (timer_view + 1)), Timeout.InfiniteTimeSpan); } else if ((context.State.HasFlag(ConsensusState.Primary) && context.State.HasFlag(ConsensusState.RequestSent)) || context.State.HasFlag(ConsensusState.Backup)) { RequestChangeView(); } } }