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 prepare 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(); Dictionary <UInt160, Transaction> scriptHashDictionary = new Dictionary <UInt160, Transaction>(); Console.WriteLine("Mempool count " + transactions.Count.ToString()); for (int i = 0; i < transactions.Count; i++) { if (transactions[i].Type == TransactionType.MinerTransaction || transactions[i].Type == TransactionType.AnonymousContractTransaction || transactions[i].Type == TransactionType.RingConfidentialTransaction) { continue; } if (transactions[i].Inputs == null || transactions[i].Inputs.Length == 0) { continue; } if (transactions[i].References == null) { transactions.RemoveAt(i); i--; continue; } if (transactions[i].Inputs.Length > 0 && transactions[i].References.ContainsKey(transactions[i].Inputs[0]) && LocalNode.KnownHashes.Count > 0) { UInt160 scripthash = transactions[i].References[transactions[i].Inputs[0]].ScriptHash; if (scriptHashDictionary.ContainsKey(scripthash)) { Transaction prevTx = scriptHashDictionary[scripthash]; if (LocalNode.KnownHashes.IndexOf(prevTx.Hash) > LocalNode.KnownHashes.IndexOf(transactions[i].Hash)) { scriptHashDictionary[scripthash] = transactions[i]; transactions.Remove(prevTx); } else { transactions.RemoveAt(i); } i--; } else { scriptHashDictionary.Add(scripthash, transactions[i]); } } } Transaction[] tmpool = LocalNode.GetMemoryPool().ToArray(); List <Transaction> consensus_transactions = new List <Transaction>(); for (int i = 0; i < transactions.Count; i++) { Transaction tx = transactions[i]; if (!tx.Verify(tmpool)) { Console.Write("Transaction verify failed : "); transactions.RemoveAt(i); LocalNode.RemoveTxFromMempool(tx.Hash); i--; Console.WriteLine(tx.ToJsonString()); continue; } UInt160 fromScriptHash = LocalNode.GetFromAddressFromTx(tx); Console.WriteLine("Step_1_2"); if (Blockchain.IsConsensusAddress(fromScriptHash)) { consensus_transactions.Add(tx); continue; } else if (tx.GetFee() == Fixed8.Zero && fromScriptHash != UInt160.Zero) { if (LocalNode.freetx_pool.ContainsKey(fromScriptHash) && LocalNode.freetx_pool[fromScriptHash].Count >= Blockchain.Default.FreeTransactionLimitPerPeriod && Blockchain.Default.Height - LocalNode.freetx_pool[fromScriptHash].ElementAt(LocalNode.freetx_pool[fromScriptHash].Count - 1) < Blockchain.Default.FreeTransactionBlockPeriodNum) { UInt256 removalHash = transactions[i].Hash; Console.WriteLine("TX removed " + removalHash); LocalNode.RemoveTxFromMempool(removalHash); transactions.RemoveAt(i); i--; } else { localNode.AddFreeTxAddressToPool(fromScriptHash); foreach (RemoteNode node in LocalNode.Default.GetRemoteNodes()) // enqueue message { node.EnqueueMessage("blockfree", fromScriptHash); } } } } if (transactions.Count >= MaxTransactionsPerBlock) { transactions = consensus_transactions.Concat(transactions.OrderByDescending(p => p.NetworkFee / p.Size).Take(MaxTransactionsPerBlock - 1 - consensus_transactions.Count).ToList()).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.CurrentConsensus = wallet.GetChangeAddress(); context.NextConsensus = Blockchain.GetConsensusAddress(Blockchain.Default.GetValidators(transactions).ToArray()); context.Signatures[context.MyIndex] = context.MakeHeader().Sign((KeyPair)wallet.GetKey(context.Validators[context.MyIndex])); } SignAndRelay(context.MakePrepareRequest()); 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(); } } }