private void OnFillMemoryPool(IEnumerable <Transaction> transactions) { // Invalidate all the transactions in the memory pool, to avoid any failures when adding new transactions. MemPool.InvalidateAllTransactions(); // Add the transactions to the memory pool foreach (var tx in transactions) { if (tx.Type == TransactionType.MinerTransaction) { continue; } if (Store.ContainsTransaction(tx.Hash)) { continue; } if (!Plugin.CheckPolicy(tx)) { continue; } // First remove the tx if it is unverified in the pool. MemPool.TryRemoveUnVerified(tx.Hash, out _); // Verify the the transaction if (!tx.Verify(currentSnapshot, MemPool.GetVerifiedTransactions())) { continue; } // Add to the memory pool MemPool.TryAdd(tx.Hash, tx); } // Transactions originally in the pool will automatically be reverified based on their priority. Sender.Tell(new FillCompleted()); }
private RelayResultReason OnNewTransaction(Transaction transaction) { if (transaction.Type == TransactionType.MinerTransaction) { return(RelayResultReason.Invalid); } if (ContainsTransaction(transaction.Hash)) { return(RelayResultReason.AlreadyExists); } if (!MemPool.CanTransactionFitInPool(transaction)) { return(RelayResultReason.OutOfMemory); } if (!transaction.Verify(currentSnapshot, MemPool.GetVerifiedTransactions())) { return(RelayResultReason.Invalid); } if (!Plugin.CheckPolicy(transaction)) { return(RelayResultReason.PolicyFail); } if (!MemPool.TryAdd(transaction.Hash, transaction)) { return(RelayResultReason.OutOfMemory); } system.LocalNode.Tell(new LocalNode.RelayDirectly { Inventory = transaction }); return(RelayResultReason.Succeed); }
private void OnFillMemoryPool(IEnumerable <Transaction> transactions) { // Invalidate all the transactions in the memory pool, to avoid any failures when adding new transactions. MemPool.InvalidateAllTransactions(); // Add the transactions to the memory pool foreach (var tx in transactions) { if (View.ContainsTransaction(tx.Hash)) { continue; } if (!NativeContract.Policy.CheckPolicy(tx, currentSnapshot)) { continue; } // First remove the tx if it is unverified in the pool. MemPool.TryRemoveUnVerified(tx.Hash, out _); // Verify the the transaction if (tx.Verify(currentSnapshot, MemPool.SendersFeeMonitor.GetSenderFee(tx.Sender)) != VerifyResult.Succeed) { continue; } // Add to the memory pool MemPool.TryAdd(tx.Hash, tx); } // Transactions originally in the pool will automatically be reverified based on their priority. Sender.Tell(new FillCompleted()); }
private VerifyResult OnNewTransaction(Transaction transaction) { if (ContainsTransaction(transaction.Hash)) { return(VerifyResult.AlreadyExists); } return(MemPool.TryAdd(transaction, currentSnapshot)); }
public bool ContainsTransaction(UInt256 hash) { if (MemPool.ContainsKey(hash)) { return(true); } return(NativeContract.Ledger.ContainsTransaction(StoreView, hash)); }
private void OnPersistCompleted(Block block) { block_cache.Remove(block.Hash); MemPool.UpdatePoolForBlockPersisted(block, currentSnapshot); Context.System.EventStream.Publish(new PersistCompleted { Block = block }); }
public bool ContainsTransaction(UInt256 hash) { if (MemPool.ContainsKey(hash)) { return(true); } return(View.ContainsTransaction(hash)); }
public Transaction GetTransaction(UInt256 hash) { if (MemPool.TryGetValue(hash, out Transaction transaction)) { return(transaction); } return(View.GetTransaction(hash)); }
public void Release(MemPool pool) { if (null != recivedata) { pool.Recycle(ref recivedata); recivedata = null; } sendData = null; }
private void OnPersistCompleted(Block block) { Debugger.Log(nameof(Blockchain), $"block persist completed=>{block.Index}/{block.Hash}", 2); block_cache.Remove(block.Hash); MemPool.UpdatePoolForBlockPersisted(block, currentSnapshot); Context.System.EventStream.Publish(new PersistCompleted { Block = block }); }
public bool HasTransactionInMemPool(string transactionId) { if (MemPool.ToList().FindAll(r => r.Body.TransactionId == transactionId) .Count > 0) { return(true); } return(false); }
private void OnPersistCompleted(Block block) { block_cache.Remove(block.Hash); MemPool.UpdatePoolForBlockPersisted(block, currentSnapshot); PersistCompleted completed = new PersistCompleted { Block = block }; system.Consensus?.Tell(completed); Distribute(completed); }
private List <Transaction> ChooseTxs() { if (MemPool.Count < 4200) { return(MemPool.ToList()); } else { var newPool = MemPool.OrderBy(CalculateFee).Take(4000); return(newPool.ToList()); } }
protected override void OnReceive(object message) { switch (message) { case Import import: OnImport(import.Blocks, import.Verify); break; case FillMemoryPool fill: OnFillMemoryPool(fill.Transactions); break; case Header[] headers: OnNewHeaders(headers); break; case Block block: Sender.Tell(OnNewBlock(block)); break; case Transaction[] transactions: { // This message comes from a mempool's revalidation, already relayed foreach (var tx in transactions) { OnNewTransaction(tx, false); } break; } case Transaction transaction: OnNewTransaction(transaction, true); break; case ParallelVerified parallelVerified: OnParallelVerified(parallelVerified); break; case ConsensusPayload payload: Sender.Tell(OnNewConsensus(payload)); break; case Idle _: if (MemPool.ReVerifyTopUnverifiedTransactionsIfNeeded(MaxTxToReverifyPerIdle, currentSnapshot)) { Self.Tell(Idle.Instance, ActorRefs.NoSender); } break; } }
protected override void OnReceive(object message) { switch (message) { case Import import: OnImport(import.Blocks); break; case ImportRoots importRoots: OnImportRoots(importRoots.Roots); break; case FillMemoryPool fill: OnFillMemoryPool(fill.Transactions); break; case Header[] headers: OnNewHeaders(headers); break; case Block block: Sender.Tell(OnNewBlock(block)); break; case Transaction transaction: Sender.Tell(OnNewTransaction(transaction)); break; case StateRoot stateRoot: OnNewStateRoot(stateRoot); break; case StateRoot[] stateRoots: OnStateRoots(stateRoots); break; case ConsensusPayload payload: Sender.Tell(OnNewConsensus(payload)); break; case Idle _: if (MemPool.ReVerifyTopUnverifiedTransactionsIfNeeded(MaxTxToReverifyPerIdle, currentSnapshot)) { Self.Tell(Idle.Instance, ActorRefs.NoSender); } break; } }
public Blockchain(NeoSystem system, IStore store) { this.system = system; this.MemPool = new MemoryPool(system, ProtocolSettings.Default.MemoryPoolMaxTransactions); this.Store = store; this.View = new ReadOnlyView(store); lock (lockObj) { if (singleton != null) { throw new InvalidOperationException(); } header_index.AddRange(View.HeaderHashList.Find().OrderBy(p => (uint)p.Key).SelectMany(p => p.Value.Hashes)); stored_header_count += (uint)header_index.Count; if (stored_header_count == 0) { header_index.AddRange(View.Blocks.Find().OrderBy(p => p.Value.Index).Select(p => p.Key)); } else { HashIndexState hashIndex = View.HeaderHashIndex.Get(); if (hashIndex.Index >= stored_header_count) { DataCache <UInt256, TrimmedBlock> cache = View.Blocks; for (UInt256 hash = hashIndex.Hash; hash != header_index[(int)stored_header_count - 1];) { header_index.Insert((int)stored_header_count, hash); hash = cache[hash].PrevHash; } } } if (header_index.Count == 0) { Persist(GenesisBlock); } else { UpdateCurrentSnapshot(); MemPool.LoadPolicy(currentSnapshot); } singleton = this; } }
//解包数据(data内容,写在对象里面) public bool Unpack(byte[] buffer, int offset, int bufferLen, MemPool pool) { int nPose = offset; serverID = buffer[nPose]; ++nPose; msgID = BitConverter.ToUInt16(buffer, nPose); nPose += 2; try { int nLen = bufferLen - MESSAGE_HEAD_LEN; recivedata = pool.Aloc(nLen);//new byte[nLen]; Array.Copy(buffer, offset + MESSAGE_HEAD_LEN, recivedata.item.data, 0, nLen); recivedata.item.nLen = nLen; } catch (Exception e) { Debug.LogError(e.Message); } return(true); }
private void OnFillMemoryPool(IEnumerable <Transaction> transactions) { // Invalidate all the transactions in the memory pool, to avoid any failures when adding new transactions. MemPool.InvalidateAllTransactions(); // Add the transactions to the memory pool foreach (var tx in transactions) { if (View.ContainsTransaction(tx.Hash)) { continue; } // First remove the tx if it is unverified in the pool. MemPool.TryRemoveUnVerified(tx.Hash, out _); // Add to the memory pool MemPool.TryAdd(tx, currentSnapshot); } // Transactions originally in the pool will automatically be reverified based on their priority. Sender.Tell(new FillCompleted()); }
protected override void OnReceive(object message) { switch (message) { case Register _: OnRegister(); break; case Import import: OnImport(import.Blocks); break; case Header[] headers: OnNewHeaders(headers); break; case Block block: Sender.Tell(OnNewBlock(block)); break; case Transaction transaction: Sender.Tell(OnNewTransaction(transaction)); break; case ConsensusPayload payload: Sender.Tell(OnNewConsensus(payload)); break; case Idle _: if (MemPool.ReVerifyTopUnverifiedTransactionsIfNeeded(MaxTxToReverifyPerIdle, currentSnapshot)) { Self.Tell(Idle.Instance, ActorRefs.NoSender); } break; case Terminated terminated: subscribers.Remove(terminated.ActorRef); break; } }
private VerifyResult OnNewTransaction(Transaction transaction) { if (ContainsTransaction(transaction.Hash)) { return(VerifyResult.AlreadyExists); } if (!MemPool.CanTransactionFitInPool(transaction)) { return(VerifyResult.OutOfMemory); } VerifyResult reason = transaction.Verify(currentSnapshot, MemPool.SendersFeeMonitor.GetSenderFee(transaction.Sender)); if (reason != VerifyResult.Succeed) { return(reason); } if (!MemPool.TryAdd(transaction.Hash, transaction)) { return(VerifyResult.OutOfMemory); } return(VerifyResult.Succeed); }
protected override void OnReceive(object message) { switch (message) { case Import import: OnImport(import.Blocks, import.Verify); break; case FillMemoryPool fill: OnFillMemoryPool(fill.Transactions); break; case Block block: OnInventory(block, false); break; case Transaction[] transactions: { // This message comes from a mempool's revalidation, already relayed foreach (var tx in transactions) { OnInventory(tx, false); } break; } case IInventory inventory: OnInventory(inventory); break; case Idle _: if (MemPool.ReVerifyTopUnverifiedTransactionsIfNeeded(MaxTxToReverifyPerIdle, currentSnapshot)) { Self.Tell(Idle.Instance, ActorRefs.NoSender); } break; } }
private void OnParallelVerified(ParallelVerified parallelVerified) { RelayResultReason reason = parallelVerified.VerifyResult; if (reason == RelayResultReason.Succeed) { if (!MemPool.CanTransactionFitInPool(parallelVerified.Transaction)) { reason = RelayResultReason.OutOfMemory; } else if (!MemPool.TryAdd(parallelVerified.Transaction.Hash, parallelVerified.Transaction)) { reason = RelayResultReason.OutOfMemory; } else if (parallelVerified.ShouldRelay) { system.LocalNode.Tell(new LocalNode.RelayDirectly { Inventory = parallelVerified.Transaction }); } } Sender.Tell(reason); }
private void Persist(Block block) { using (SnapshotView snapshot = GetSnapshot()) { if (block.Index == header_index.Count) { header_index.Add(block.Hash); snapshot.HeaderHashIndex.GetAndChange().Set(block); } List <ApplicationExecuted> all_application_executed = new List <ApplicationExecuted>(); snapshot.PersistingBlock = block; if (block.Index > 0) { using (ApplicationEngine engine = new ApplicationEngine(TriggerType.System, null, snapshot, 0, true)) { engine.LoadScript(onPersistNativeContractScript); if (engine.Execute() != VMState.HALT) { throw new InvalidOperationException(); } ApplicationExecuted application_executed = new ApplicationExecuted(engine); Context.System.EventStream.Publish(application_executed); all_application_executed.Add(application_executed); } } snapshot.Blocks.Add(block.Hash, block.Trim()); StoreView clonedSnapshot = snapshot.Clone(); // Warning: Do not write into variable snapshot directly. Write into variable clonedSnapshot and commit instead. foreach (Transaction tx in block.Transactions) { var state = new TransactionState { BlockIndex = block.Index, Transaction = tx }; clonedSnapshot.Transactions.Add(tx.Hash, state); clonedSnapshot.Transactions.Commit(); using (ApplicationEngine engine = new ApplicationEngine(TriggerType.Application, tx, clonedSnapshot, tx.SystemFee)) { engine.LoadScript(tx.Script); state.VMState = engine.Execute(); if (state.VMState == VMState.HALT) { clonedSnapshot.Commit(); } else { clonedSnapshot = snapshot.Clone(); } ApplicationExecuted application_executed = new ApplicationExecuted(engine); Context.System.EventStream.Publish(application_executed); all_application_executed.Add(application_executed); } } snapshot.BlockHashIndex.GetAndChange().Set(block); foreach (IPersistencePlugin plugin in Plugin.PersistencePlugins) { plugin.OnPersist(snapshot, all_application_executed); } snapshot.Commit(); List <Exception> commitExceptions = null; foreach (IPersistencePlugin plugin in Plugin.PersistencePlugins) { try { plugin.OnCommit(snapshot); } catch (Exception ex) { if (plugin.ShouldThrowExceptionFromCommit(ex)) { if (commitExceptions == null) { commitExceptions = new List <Exception>(); } commitExceptions.Add(ex); } } } if (commitExceptions != null) { throw new AggregateException(commitExceptions); } } UpdateCurrentSnapshot(); block_cache.Remove(block.PrevHash); MemPool.UpdatePoolForBlockPersisted(block, currentSnapshot); Context.System.EventStream.Publish(new PersistCompleted { Block = block }); }
private Task Peer_OnMemPool(BitcoinPeer s, MemPool mp) { throw new NotImplementedException(); }
private async Task ReadStream() { while (!Closing) { try { //try to read a header var hdata = new byte[24]; await Stream.ReadAsyncExact(hdata, 0, hdata.Length); var h = new MessageHeader(); h.ReadFromPayload(hdata, 0); if (h != null) { //read the payload var pl = new byte[h.PayloadSize]; await Stream.ReadAsyncExact(pl, 0, pl.Length); bool checksumOk = false; //verify hash using (var sha = SHA256.Create()) { var h1 = sha.ComputeHash(pl); var h2 = sha.ComputeHash(h1); checksumOk = h2[0] == h.Checksum[0] && h2[1] == h.Checksum[1] && h2[2] == h.Checksum[2] && h2[3] == h.Checksum[3]; } if (checksumOk) { switch (h.Command) { case "addr\0\0\0\0\0\0\0\0": { if (OnAddr != null) { var a = new Addr(); a.ReadFromPayload(pl, 0); await OnAddr?.Invoke(this, a); } break; } case "alert\0\0\0\0\0\0\0": { if (OnAlert != null) { var a = new Alert(); a.ReadFromPayload(pl, 0); await OnAlert?.Invoke(this, a); } break; } case "feefilter\0\0\0": { if (OnFeeFilter != null) { var f = new FeeFilter(); f.ReadFromPayload(pl, 0); await OnFeeFilter?.Invoke(this, f); } break; } case "filteradd\0\0\0": { if (OnFilterAdd != null) { var f = new FilterAdd(); f.ReadFromPayload(pl, 0); await OnFilterAdd?.Invoke(this, f); } break; } case "filterclear\0": { if (OnFilterClear != null) { var f = new FilterClear(); f.ReadFromPayload(pl, 0); await OnFilterClear?.Invoke(this, f); } break; } case "filterload\0\0": { if (OnFilterLoad != null) { var f = new FilterLoad(); f.ReadFromPayload(pl, 0); await OnFilterLoad?.Invoke(this, f); } break; } case "getaddr\0\0\0\0\0": { if (OnGetAddr != null) { var ga = new GetAddr(); ga.ReadFromPayload(pl, 0); await OnGetAddr?.Invoke(this, ga); } break; } case "getblocks\0\0\0": { if (OnGetBlocks != null) { var gb = new GetBlocks(); gb.ReadFromPayload(pl, 0); await OnGetBlocks?.Invoke(this, gb); } break; } case "getdata\0\0\0\0\0": { if (OnGetData != null) { var gd = new GetData(); gd.ReadFromPayload(pl, 0); await OnGetData?.Invoke(this, gd); } break; } case "getheaders\0\0": { if (OnGetHeaders != null) { var gh = new GetHeaders(); gh.ReadFromPayload(pl, 0); await OnGetHeaders?.Invoke(this, gh); } break; } case "headers\0\0\0\0\0": { if (OnHeaders != null) { var hd = new Headers(); hd.ReadFromPayload(pl, 0); await OnHeaders?.Invoke(this, hd); } break; } case "inv\0\0\0\0\0\0\0\0\0": { if (OnInv != null) { var iv = new Inv(); iv.ReadFromPayload(pl, 0); await OnInv?.Invoke(this, iv); } break; } case "mempool\0\0\0\0\0": { if (OnMemPool != null) { var mp = new MemPool(); mp.ReadFromPayload(pl, 0); await OnMemPool?.Invoke(this, mp); } break; } case "notfound\0\0\0\0": { if (OnNotFound != null) { var nf = new NotFound(); nf.ReadFromPayload(pl, 0); await OnNotFound?.Invoke(this, nf); } break; } case "ping\0\0\0\0\0\0\0\0": { if (OnPing != null) { var ping = new Ping(); ping.ReadFromPayload(pl, 0); await OnPing?.Invoke(this, ping); } break; } case "pong\0\0\0\0\0\0\0\0": { if (OnPong != null) { var pong = new Pong(); pong.ReadFromPayload(pl, 0); await OnPong?.Invoke(this, pong); } break; } case "reject\0\0\0\0\0\0": { if (OnReject != null) { var re = new Reject(); re.ReadFromPayload(pl, 0); await OnReject?.Invoke(this, re); } break; } case "sendheaders\0": { if (OnSendHeaders != null) { var sh = new SendHeaders(); sh.ReadFromPayload(pl, 0); await OnSendHeaders?.Invoke(this, sh); } break; } case "verack\0\0\0\0\0\0": { if (OnVerAck != null) { var va = new VerAck(); va.ReadFromPayload(pl, 0); await OnVerAck.Invoke(this, va); } break; } case "version\0\0\0\0\0": { if (OnVersion != null) { var v = new bitcoin_lib.P2P.Version(""); v.ReadFromPayload(pl, 0); await OnVersion?.Invoke(this, v); } break; } default: { //Console.WriteLine($"Got cmd: {h.Command}"); break; } } } else { Closing = true; } } } catch (Exception ex) { Closing = true; } } }
public void ClearAllTask() { Task Task; CPUContext CPUContext; MemoryPool MemPool; MemoryPoolFixedsize MemPoolFx; Mailbox Mailbox; Semaphore Semaphore; CyclicHandler CyclicHandler; UdpCep UdpCep; Udp6Cep Udp6Cep; TcpCep TcpCep; while (m_CyclicHandlerTable.Count != 0) { CyclicHandler = m_CyclicHandlerTable[0]; m_CyclicHandlerTable.RemoveAt(0); //if(CyclicHandler != null) // delete CyclicHandler; } do { LockTaskTable(); try { for (int i = 0; i < m_TaskTable.Count; i++) { Task = m_TaskTable[i]; CPUContext = (CPUContext)(Task.GetCPUContext()); if ((CPUContext == null) || CPUContext.IsFinished()) { m_TaskTable.RemoveAt(i); i--; continue; } try { CPUContext.Terminate(); } catch (System.Threading.ThreadAbortException) { } catch (Exception e) { System.Diagnostics.Debug.WriteLine(e.Message); } } } finally { UnlockTaskTable(); } System.Threading.Thread.Yield(); } while (m_TaskTable.Count != 0); while (m_MemPoolTable.Count != 0) { MemPool = m_MemPoolTable[0]; MemPool.EnumMemoryBlock(this, EnumBlockCallBack); m_MemPoolTable.RemoveAt(0); //delete MemPool; } while (m_MemPoolFxTable.Count != 0) { MemPoolFx = m_MemPoolFxTable[0]; m_MemPoolFxTable.RemoveAt(0); //delete MemPoolFx; } while (m_MailboxTable.Count != 0) { Mailbox = m_MailboxTable[0]; m_MailboxTable.RemoveAt(0); //delete Mailbox; } while (m_SemaphoreTable.Count != 0) { Semaphore = m_SemaphoreTable[0]; m_SemaphoreTable.RemoveAt(0); //delete Semaphore; } while (m_UdpCepTable.Count != 0) { UdpCep = m_UdpCepTable[0]; m_UdpCepTable.RemoveAt(0); //delete UdpCep; } while (m_Udp6CepTable.Count != 0) { Udp6Cep = m_Udp6CepTable[0]; m_Udp6CepTable.RemoveAt(0); //delete Udp6Cep; } while (m_TcpCepTable.Count != 0) { TcpCep = m_TcpCepTable[0]; m_TcpCepTable.RemoveAt(0); //delete TcpCep; } }
private async Task Peer_OnMessage(BitcoinPeer s, IStreamable msg) { switch (msg) { case bitcoin_lib.P2P.Version a: { PeerVersion = a; if (Peer.IsInbound) { await SendVersion(); } var va = new VerAck(); await s.WriteMessage(va); if (Peer.IsInbound && PeerVersion.HighestVersion >= 70014) { //send cmpct (i only want my version, i dont care about another version) //no version 1 msg will be sent if version 2 is supported var nVersion = (Peer.ChainParams.Services & (ulong)Services.NODE_WITNESS) != 0 ? 2ul : 1ul; var cmp = new SendCMPCT(); cmp.Version = nVersion; cmp.Enabled = true; await s.WriteMessage(cmp); } if (BlockChain.Mempool.Count == 0) { //ask for mempool var mp = new MemPool(); await s.WriteMessage(mp); } var ph = ((IPEndPoint)Peer.RemoteEndpoint).AsHash(); if (BlockChain.Peers.ContainsKey(ph)) { //update peer info BlockChain.Peers[ph].LastSeen = DateTime.Now; BlockChain.Peers[ph].LastVersion = a; } else { //ask the peer for addr info if this is the first time we seen them var ga = new GetAddr(); await s.WriteMessage(ga); } break; } case Inv a: { var gd = new GetData(); var to_get = new List <Inventory>(); var sw = new Stopwatch(); sw.Start(); to_get.AddRange(a.Inventory.Where(b => b.Type == InventoryType.MSG_TX && !BlockChain.Mempool.ContainsKey(b.Hash))); if ((PeerVersion.Services & (ulong)Services.NODE_WITNESS) == 1) { to_get.ForEach(b => b.Type = InventoryType.MSG_WITNESS_TX); } gd.Inventory = to_get.ToArray(); if (gd.Inventory.Length > 0) { //Console.WriteLine($"Asking for {gd.Count} tnxs, {sw.Elapsed.TotalMilliseconds.ToString("0.00")}ms"); await s.WriteMessage(gd); } break; } case Tx a: { if (!BlockChain.Mempool.ContainsKey(a.Hash)) { BlockChain.Mempool.Add(a.Hash, a); } break; } case VerAck a: { if (Peer.IsInbound) { await SendAddr(); } await s.WriteMessage(new Ping()); break; } case Addr a: { foreach (var ip in a.Ips) { var ph = new IPEndPoint(ip.Ip, ip.Port).AsHash(); if (!BlockChain.Peers.ContainsKey(ph)) { BlockChain.Peers.Add(ph, new PeerInfo() { Ip = Peer.RemoteEndpoint, LastSeen = DateTime.Now, LastVersion = new bitcoin_lib.P2P.Version() //add empty version }); } } break; } case Pong a: { if (PingTimer.IsRunning) { PingTimer.Stop(); } //Console.WriteLine($"[{RemoteEndpoint}]{PeerVersion.UserAgent} ping is: {LastPing.TotalMilliseconds.ToString("0.00")}ms"); break; } case Ping a: { var pong = new Pong(); pong.Nonce = a.Nonce; await s.WriteMessage(pong); break; } case MemPool a: { var inv = new Inv(); inv.Inventory = BlockChain.Mempool.Keys.Select(b => new Inventory() { Type = InventoryType.MSG_TX, Hash = b }).ToArray(); if (inv.Inventory.Length > 0) { await s.WriteMessage(inv); } break; } case SendCMPCT a: { if (CMPCTBlockVersion == 0 && a.Enabled && a.Version <= 2) { if (Peer.IsInbound) { //lock in cmpct var nVersion = (Peer.ChainParams.Services & (ulong)Services.NODE_WITNESS) != 0 ? 2ul : 1ul; if (a.Version == nVersion) { CMPCTBlockVersion = a.Version; Console.WriteLine($"Locking version {a.Version} cmpct block"); } } else { //reply to cmpct negotiation, if the node advertises witness use version 2 var nVersion = (PeerVersion.Services & (ulong)Services.NODE_WITNESS) != 0 ? 2ul : 1ul; if (a.Version == nVersion) { CMPCTBlockVersion = a.Version; } else if (nVersion != a.Version && CMPCTBlockVersion == 0) //if they only sent version 1 & they advertise NODE_WITNESS, use this version { CMPCTBlockVersion = a.Version; } var rsp = new SendCMPCT(); rsp.Version = CMPCTBlockVersion; rsp.Enabled = true; Console.WriteLine($"Sending version {rsp.Version} cmpct block"); await s.WriteMessage(rsp); } Console.WriteLine($"Peer is asking for version {a.Version} cmpct block"); } break; } } }