private bool AddTransaction(Transaction tx, bool verify) { if (Blockchain.Default.ContainsTransaction(tx.Hash) || (verify && !tx.Verify(context.Transactions.Values)) || !CheckPolicy(tx)) { Log($"reject tx: {tx.Hash}{Environment.NewLine}{tx.ToArray().ToHexString()}"); RequestChangeView(); return(false); } context.Transactions[tx.Hash] = tx; if (context.TransactionHashes.Length == context.Transactions.Count) { if (Blockchain.GetConsensusAddress(Blockchain.Default.GetValidators(context.Transactions.Values).ToArray()).Equals(context.NextConsensus)) { Log($"send perpare response"); // 设置共识状态为已发送签名 context.State |= ConsensusState.SignatureSent; // 添加本地签名到签名列表 context.Signatures[context.MyIndex] = context.MakeHeader().Sign(context.KeyPair); // 广播共识响应 SignAndRelay(context.MakePrepareResponse(context.Signatures[context.MyIndex])); // 检查签名状态是否符合共识要求 CheckSignatures(); } else { RequestChangeView(); return(false); } } return(true); }
private bool AddTransaction(Transaction tx, bool verify) { if (context.Snapshot.ContainsTransaction(tx.Hash) || (verify && !tx.Verify(context.Snapshot, context.Transactions.Values)) || !Plugin.CheckPolicy(tx)) { Log($"reject tx: {tx.Hash}{Environment.NewLine}{tx.ToArray().ToHexString()}", LogLevel.Warning); RequestChangeView(); return(false); } context.Transactions[tx.Hash] = tx; if (context.TransactionHashes.Length == context.Transactions.Count) { if (context.VerifyRequest()) { Log($"send prepare response"); context.State |= ConsensusState.SignatureSent; context.Signatures[context.MyIndex] = context.MakeHeader().Sign(context.KeyPair); SignAndRelay(context.MakePrepareResponse(context.Signatures[context.MyIndex])); CheckSignatures(); } else { RequestChangeView(); return(false); } } return(true); }
private void OnTimer(Timer timer) { if (timer.Height != context.BlockIndex || timer.ViewNumber != context.ViewNumber) { return; } Log($"timeout: height={timer.Height} view={timer.ViewNumber} state={context.State}"); Log($"send prepare request: height={timer.Height} view={timer.ViewNumber}"); { FillContext(); context.Timestamp = Math.Max(DateTime.UtcNow.ToTimestamp(), context.Snapshot.GetHeader(context.PrevHash).Timestamp + 1); context.Signatures[context.MyIndex] = context.MakeHeader().Sign(context.KeyPair); if (context.TransactionHashes.All(p => context.Transactions.ContainsKey(p))) { Contract contract = Contract.CreateSignatureContract(context.Validators[0]); Block block = context.MakeHeader(); ContractParametersContext sc = new ContractParametersContext(block); wallet.Sign(sc); sc.Verifiable.Witnesses = sc.GetWitnesses(); block.Transactions = context.TransactionHashes.Select(p => context.Transactions[p]).ToArray(); Log($"relay block: {block.Hash}"); system.LocalNode.Tell(new LocalNode.Relay { Inventory = block }); } } ChangeTimer(TimeSpan.FromSeconds(Blockchain.SecondsPerBlock << (timer.ViewNumber + 1))); }
private bool AddTransaction(Transaction tx, bool verify) { ReportNeoBlockchain reportObj = new ReportNeoBlockchain("[NeoConsensusService-AddTransaction]"); if (Blockchain.Default.ContainsTransaction(tx.Hash) || (verify && !tx.Verify(context.Transactions.Values)) || !CheckPolicy(tx)) { Log($"reject tx: {tx.Hash}{Environment.NewLine}{tx.ToArray().ToHexString()}"); RequestChangeView(); return(false); } context.Transactions[tx.Hash] = tx; if (context.TransactionHashes.Length == context.Transactions.Count) { if (Blockchain.GetConsensusAddress(Blockchain.Default.GetValidators(context.Transactions.Values).ToArray()).Equals(context.NextConsensus)) { Log($"send perpare response"); context.State |= ConsensusState.SignatureSent; context.Signatures[context.MyIndex] = context.MakeHeader().Sign(context.KeyPair); SignAndRelay(context.MakePrepareResponse(context.Signatures[context.MyIndex])); CheckSignatures(); } else { RequestChangeView(); return(false); } } reportObj.appendElapsedTime(); return(true); }
private void OnPrepareRequestReceived(ConsensusPayload payload, PrepareRequest message) { if (context.State.HasFlag(ConsensusState.RequestReceived)) { return; } if (payload.ValidatorIndex != context.PrimaryIndex) { return; } Log($"{nameof(OnPrepareRequestReceived)}: height={payload.BlockIndex} view={message.ViewNumber} index={payload.ValidatorIndex} tx={message.TransactionHashes.Length}"); if (!context.State.HasFlag(ConsensusState.Backup)) { return; } if (payload.Timestamp <= context.Snapshot.GetHeader(context.PrevHash).Timestamp || payload.Timestamp > DateTime.UtcNow.AddMinutes(10).ToTimestamp()) { Log($"Timestamp incorrect: {payload.Timestamp}", LogLevel.Warning); return; } context.State |= ConsensusState.RequestReceived; context.Timestamp = payload.Timestamp; context.Nonce = message.Nonce; context.NextConsensus = message.NextConsensus; context.TransactionHashes = message.TransactionHashes; context.Transactions = new Dictionary <UInt256, Transaction>(); byte[] hashData = context.MakeHeader().GetHashData(); if (!Crypto.Default.VerifySignature(hashData, message.Signature, context.Validators[payload.ValidatorIndex].EncodePoint(false))) { return; } for (int i = 0; i < context.Signatures.Length; i++) { if (context.Signatures[i] != null) { if (!Crypto.Default.VerifySignature(hashData, context.Signatures[i], context.Validators[i].EncodePoint(false))) { context.Signatures[i] = null; } } } context.Signatures[payload.ValidatorIndex] = message.Signature; Dictionary <UInt256, Transaction> mempool = Blockchain.Singleton.GetMemoryPool().ToDictionary(p => p.Hash); List <Transaction> unverified = new List <Transaction>(); foreach (UInt256 hash in context.TransactionHashes.Skip(1)) { if (mempool.TryGetValue(hash, out Transaction tx)) { if (!AddTransaction(tx, false)) { return; } } else { tx = Blockchain.Singleton.GetUnverifiedTransaction(hash); if (tx != null) { unverified.Add(tx); } } } foreach (Transaction tx in unverified) { if (!AddTransaction(tx, true)) { return; } } if (!AddTransaction(message.MinerTransaction, true)) { return; } if (context.Transactions.Count < context.TransactionHashes.Length) { UInt256[] hashes = context.TransactionHashes.Where(i => !context.Transactions.ContainsKey(i)).ToArray(); system.TaskManager.Tell(new TaskManager.RestartTasks { Payload = InvPayload.Create(InventoryType.TX, hashes) }); } }