public void TestContainsKey() { AddTransactions(10); var txToAdd = CreateTransaction(); _unit.TryAdd(txToAdd.Hash, txToAdd); _unit.ContainsKey(txToAdd.Hash).Should().BeTrue(); _unit.InvalidateVerifiedTransactions(); _unit.ContainsKey(txToAdd.Hash).Should().BeTrue(); }
public void TestContainsKey() { var snapshot = GetSnapshot(); AddTransactions(10); var txToAdd = CreateTransaction(); _unit.TryAdd(txToAdd, snapshot); _unit.ContainsKey(txToAdd.Hash).Should().BeTrue(); _unit.InvalidateVerifiedTransactions(); _unit.ContainsKey(txToAdd.Hash).Should().BeTrue(); }
/// <summary> /// Allocate a block of memory based upon a best fit policy. /// </summary> /// <param name="iBlockSizeRequest"></param> /// <returns></returns> public MemoryBlock Allocate(int iBlockSizeRequest) { try { IEnumerable <KeyValuePair <int, List <int> > > availableMemoryBlocks = from entry in MemoryPool where (entry.Key) >= iBlockSizeRequest orderby entry.Key ascending select entry; if (0 == availableMemoryBlocks.Count()) { return(new MemoryBlock()); } KeyValuePair <int, List <int> > smallestBlocks = availableMemoryBlocks.First(); int iBlockSize = smallestBlocks.Key; int iBlockAddress = smallestBlocks.Value.First(); smallestBlocks.Value.RemoveAt(0); if (0 == smallestBlocks.Value.Count()) { MemoryPool.Remove(iBlockSize); } if (iBlockSize > iBlockSizeRequest) { int iBlockRemainderSize = iBlockSize - iBlockSizeRequest; int iBlockRemainderAddress = iBlockAddress + iBlockSizeRequest; if (MemoryPool.ContainsKey(iBlockRemainderSize)) { Debug.Assert(!MemoryPool[iBlockRemainderSize].Contains(iBlockRemainderAddress)); MemoryPool[iBlockRemainderSize].Add(iBlockRemainderAddress); } else { MemoryPool.Add(iBlockRemainderSize, new List <int>() { iBlockRemainderAddress }); } } return(new MemoryBlock() { BlockAddress = iBlockAddress, BlockSize = iBlockSizeRequest }); } catch (Exception) { throw; } }
async Task HandleAdvertise(InventoryMessage message, int peerId) { // Data should not contain anything. (To prevent DDoS) if (!message.Data.IsNull()) { throw new ArgumentException(); } var haveObject = message.IsBlock ? Blocks.ContainsKey(message.ObjectId) : MemoryPool.ContainsKey(message.ObjectId); if (haveObject) { return; } message.Type = Request; await ConnectionManager.SendAsync(message, peerId); }
bool TryAddTransactionToMemoryPool(ByteString id, byte[] data) { // Data should not exceed the maximum size. if (data.Length > MaximumTransactionSize) { throw new ArgumentException(); } // Integrity check. var computedId = Hash.ComputeDoubleSHA256(data); if (!ByteString.CopyFrom(computedId).Equals(id)) { throw new ArgumentException(); } if (MemoryPool.ContainsKey(id)) { return(false); } var tx = BlockchainUtil.DeserializeTransaction(data); // Ignore the coinbase transactions. if (tx.InEntries.Count == 0) { return(false); } lock (MemoryPool) { if (MemoryPool.ContainsKey(id)) { return(false); } MemoryPool.Add(id, tx); } return(true); }
async Task HandleBody(InventoryMessage message, int peerId) { // Data should not exceed the maximum size. var data = message.Data; if (data.Length > MaximumBlockSize) { throw new ArgumentException(); } // ハッシュ値正しい? var id = message.IsBlock ? BlockchainUtil.ComputeBlockId(data) : Hash.ComputeDoubleSHA256(data); if (!ByteString.CopyFrom(id).Equals(message.ObjectId)) { return; } if (message.IsBlock) { // ミューテックス lock (Blocks) { if (Blocks.ContainsKey(message.ObjectId)) { return; } // ハッシュテーブルに追加 Blocks.Add(message.ObjectId, data); } var block = BlockchainUtil.DeserializeBlock(data); // 前のブロックも知らなかったら前のももらう var prevId = block.PreviousHash; if (!Blocks.ContainsKey(prevId)) { await ConnectionManager.SendAsync(new InventoryMessage { Type = Request, IsBlock = true, ObjectId = prevId, }, peerId); } Executor.ProcessBlock(block); } else { if (MemoryPool.ContainsKey(message.ObjectId)) { return; } var tx = BlockchainUtil.DeserializeTransaction(data); // Ignore the coinbase transactions. if (tx.InEntries.Count == 0) { return; } lock (MemoryPool) { if (MemoryPool.ContainsKey(message.ObjectId)) { return; } MemoryPool.Add(message.ObjectId, tx); } } message.Type = Advertise; message.Data = null; // 他の人に教えてあげる await ConnectionManager.BroadcastAsync(message, peerId); }
async Task HandleBody(InventoryMessage message, int peerId) { // Data should not exceed the maximum size. var data = message.Data; if (data.Length > MaximumBlockSize) { throw new ArgumentException(); } var id = message.IsBlock ? BlockchainUtil.ComputeBlockId(data) : Hash.ComputeDoubleSHA256(data); if (!ByteString.CopyFrom(id).Equals(message.ObjectId)) { return; } if (message.IsBlock) { lock (Blocks)//並列処理を避ける { if (Blocks.ContainsKey(message.ObjectId)) { return; } Blocks.Add(message.ObjectId, data); } var prevId = Deserialize <Block>(data).PreviousHash; if (!Blocks.ContainsKey(prevId)) { await ConnectionManager.SendAsync(new InventoryMessage//当該ブロックの前のブロックを持っていない場合はそれもRequestする(前のblockのIDが必要なため { Type = Request, IsBlock = true, ObjectId = prevId, }, peerId); } else { Executor.ProcessBlock(data, prevId); } } else { if (MemoryPool.ContainsKey(message.ObjectId)) { return; } var tx = BlockchainUtil.DeserializeTransaction(data); // Ignore the coinbase transactions. if (tx.InEntries.Count == 0) { return; } lock (MemoryPool) { if (MemoryPool.ContainsKey(message.ObjectId)) { return; } MemoryPool.Add(message.ObjectId, tx); } } message.Type = Advertise; message.Data = null; await ConnectionManager.BroadcastAsync(message, peerId); }//ネットワーク全体にもらったブロックを発信する