public void TryReadingNonExistentCoin() { var sozu = new VolatileCoinStore(); var inbox = new BoundedInbox(); var outbox = new BoundedInbox(); var controller = new CoinController(inbox, outbox, sozu, _hash); var clientId = new ClientId(); var reqId = new RequestId(1); var coin = GetCoin(_rand); var readCoinRequest = GetCoinRequest.From(reqId, clientId, coin.Outpoint, new BlockAlias(3), clientId.Mask); inbox.TryWrite(readCoinRequest.Span); controller.HandleRequest(); var raw = outbox.Peek(); var response = new GetCoinResponse(raw.Span); // verify response contents Assert.Equal(reqId, response.MessageHeader.RequestId); Assert.Equal(clientId, response.MessageHeader.ClientId); Assert.Equal(GetCoinStatus.OutpointNotFound, response.Status); }
public void ReadExistingCoin() { var sozu = new VolatileCoinStore(); var inbox = new BoundedInbox(); var outbox = new BoundedInbox(); var controller = new CoinController(inbox, outbox, sozu, _hash); var coin = GetCoin(_rand); sozu.AddProduction( _hash.Hash(ref coin.Outpoint), ref coin.Outpoint, false, coin.Payload, new BlockAlias(3), null); // lineage is not used in VolatileCoinStore var clientId = new ClientId(); var reqId = new RequestId(1); var context = new BlockAlias(3); var readCoinRequest = GetCoinRequest.From(reqId, clientId, coin.Outpoint, context, clientId.Mask); inbox.TryWrite(readCoinRequest.Span); controller.HandleRequest(); var raw = outbox.Peek(); var response = new GetCoinResponse(raw.Span); Assert.Equal(response.MessageHeader.MessageSizeInBytes, raw.Length); // verify response contents Assert.Equal(reqId, response.MessageHeader.RequestId); Assert.Equal(clientId, response.MessageHeader.ClientId); Assert.Equal(MessageKind.GetCoinResponse, response.MessageHeader.MessageKind); Assert.Equal(coin.Outpoint, response.Outpoint); Assert.Equal(OutpointFlags.None, response.OutpointFlags); Assert.Equal(context, response.Context.ConvertToBlockAlias(clientId.Mask)); Assert.Equal(context, response.Production.ConvertToBlockAlias(clientId.Mask)); Assert.Equal(BlockAlias.Undefined.ConvertToBlockHandle(clientId.Mask), response.Consumption); Assert.Equal(coin.Payload.Satoshis, response.Satoshis); Assert.Equal(coin.Payload.NLockTime, response.NLockTime); Assert.True(coin.Payload.Script.SequenceEqual(response.Script)); }
public void WriteReadCoins() { var instance = GetInstance(); var clientId = new ClientId(123); instance.Listener.GetNextClientId = () => clientId; instance.Start(); var localEndpoint = new IPEndPoint(IPAddress.Loopback, instance.Port); var rawSocket = new Socket(localEndpoint.AddressFamily, SocketType.Stream, ProtocolType.Tcp); rawSocket.Connect(localEndpoint); var socket = new SocketLikeAdapter(rawSocket); try { // Open block var openBlockRequest = OpenBlockRequest.ForGenesis(RequestId.MinRequestId); socket.Send(openBlockRequest.Span); var openBlockResponse = new OpenBlockResponse(new byte[OpenBlockResponse.SizeInBytes]); socket.Receive(openBlockResponse.Span); Assert.Equal(OpenBlockStatus.Success, openBlockResponse.Status); var reqNum = 0U; // Write 100 coins into this open block and save the outpoints to read them later var outpointSaverComm = new Outpoint[100]; var randyRandom = new Random(42); var produceCoinResponseBuffer = new byte[ProduceCoinResponse.SizeInBytes]; var consumeCoinResponseBuffer = new byte[ConsumeCoinResponse.SizeInBytes]; for (var i = 0; i < 100; i++) { var coinToWrite = GetCoin(randyRandom, openBlockResponse.Handle.ConvertToBlockAlias(clientId.Mask)); outpointSaverComm[i] = coinToWrite.Outpoint; var writeCoinRequest = ProduceCoinRequest.From( new RequestId(++reqNum), clientId, coinToWrite.Outpoint, (OutpointFlags)coinToWrite.OutpointFlags, openBlockResponse.Handle .ConvertToBlockAlias(clientId.Mask), // reconverted to BlockHandle after object construction coinToWrite.Payload.Satoshis, coinToWrite.Payload.NLockTime, coinToWrite.Payload.Script, clientId.Mask); socket.Send(writeCoinRequest.Span); var writeCoinResponse = new ProduceCoinResponse(produceCoinResponseBuffer); socket.Receive(writeCoinResponse.Span); Assert.Equal(ChangeCoinStatus.Success, writeCoinResponse.Status); // every second coin, write a consumption if (i % 2 == 0) { var writeCoinConsRequest = ConsumeCoinRequest.From( new RequestId(++reqNum), ref coinToWrite.Outpoint, // reconverted to BlockHandle after object construction openBlockResponse.Handle.ConvertToBlockAlias(clientId.Mask), clientId.Mask); socket.Send(writeCoinConsRequest.Span); var consumeCoinResponse = new ConsumeCoinResponse(consumeCoinResponseBuffer); socket.Receive(consumeCoinResponse.Span); Assert.Equal(ChangeCoinStatus.Success, consumeCoinResponse.Status); } } // end of write coins // Commit the block var commitBlockRequest = CommitBlockRequest.From(new RequestId(++reqNum), clientId, openBlockResponse.Handle, CommittedBlockId.Genesis); socket.Send(commitBlockRequest.Span); var commitBlockResponse = new CommitBlockResponse(new byte[CommitBlockResponse.SizeInBytes]); socket.Receive(commitBlockResponse.Span); Assert.Equal(CommitBlockStatus.Success, commitBlockResponse.Status); // Open a new block var openBlockRequest2 = OpenBlockRequest.From(new RequestId(++reqNum), clientId, CommittedBlockId.Genesis); socket.Send(openBlockRequest2.Span); var openBlockResponse2 = new OpenBlockResponse(new byte[OpenBlockResponse.SizeInBytes]); socket.Receive(openBlockResponse2.Span); Assert.Equal(OpenBlockStatus.Success, openBlockResponse2.Status); // Write 100 coins into the new block var outpointSaverUncomm = new Outpoint[100]; for (var i = 0; i < 100; i++) { var coinToWrite = GetCoin(randyRandom, openBlockResponse2.Handle.ConvertToBlockAlias(clientId.Mask)); outpointSaverUncomm[i] = coinToWrite.Outpoint; var writeCoinRequest = ProduceCoinRequest.From( new RequestId(++reqNum), clientId, coinToWrite.Outpoint, (OutpointFlags)coinToWrite.OutpointFlags, openBlockResponse2.Handle .ConvertToBlockAlias(clientId.Mask), // reconverted to BlockHandle after object construction coinToWrite.Payload.Satoshis, coinToWrite.Payload.NLockTime, coinToWrite.Payload.Script, clientId.Mask); socket.Send(writeCoinRequest.Span); var writeCoinResponse = new ProduceCoinResponse(produceCoinResponseBuffer); socket.Receive(writeCoinResponse.Span); Assert.Equal(ChangeCoinStatus.Success, writeCoinResponse.Status); // every second coin, write a consumption if (i % 2 == 0) { var writeCoinConsRequest = ConsumeCoinRequest.From( new RequestId(++reqNum), ref coinToWrite.Outpoint, openBlockResponse2.Handle .ConvertToBlockAlias(clientId .Mask), // reconverted to BlockHandle after object construction clientId.Mask); socket.Send(writeCoinConsRequest.Span); var consumeCoinResponse = new ConsumeCoinResponse(consumeCoinResponseBuffer); socket.Receive(consumeCoinResponse.Span); Assert.Equal(ChangeCoinStatus.Success, consumeCoinResponse.Status); } } // end of second write coins // Read coins from the committed block var headerBuffer = new byte[MessageHeader.SizeInBytes]; for (var i = 0; i < 100; i++) { var readCoinRequest = GetCoinRequest.From( new RequestId(++reqNum), clientId, outpointSaverComm[i], openBlockResponse.Handle.ConvertToBlockAlias(clientId.Mask), clientId.Mask); // reconverted to BlockHandle after object construction socket.Send(readCoinRequest.Span); socket.Receive(headerBuffer); var header = MemoryMarshal.Cast <byte, MessageHeader>(headerBuffer)[0]; Assert.Equal(MessageKind.GetCoinResponse, header.MessageKind); var readCoinResponseBuffer = new byte[header.MessageSizeInBytes]; headerBuffer.CopyTo(readCoinResponseBuffer, 0); socket.Receive(readCoinResponseBuffer.AsSpan(16)); var readCoinResponse = new GetCoinResponse(readCoinResponseBuffer); Assert.Equal(header.MessageSizeInBytes, readCoinResponse.Span.Length); Assert.Equal(openBlockResponse.Handle, readCoinResponse.Production); if (i % 2 == 0) { Assert.Equal(openBlockResponse.Handle.Value, readCoinResponse.Consumption.Value); } else { Assert.Equal(readCoinResponse.Consumption.Value, BlockAlias.Undefined.ConvertToBlockHandle(clientId.Mask).Value); } Assert.Equal(outpointSaverComm[i], readCoinResponse.Outpoint); } // Read coins from the uncommitted block for (var i = 0; i < 100; i++) { var readCoinRequest = GetCoinRequest.From( new RequestId(++reqNum), clientId, outpointSaverUncomm[i], openBlockResponse2.Handle.ConvertToBlockAlias(clientId.Mask), clientId.Mask); // reconverted to BlockHandle after object construction socket.Send(readCoinRequest.Span); socket.Receive(headerBuffer); var header = MemoryMarshal.Cast <byte, MessageHeader>(headerBuffer)[0]; Assert.Equal(MessageKind.GetCoinResponse, header.MessageKind); var readCoinResponseBuffer = new byte[header.MessageSizeInBytes]; headerBuffer.CopyTo(readCoinResponseBuffer, 0); socket.Receive(readCoinResponseBuffer.AsSpan(16)); var readCoinResponse = new GetCoinResponse(readCoinResponseBuffer); Assert.Equal(header.MessageSizeInBytes, readCoinResponse.Span.Length); Assert.Equal(openBlockResponse2.Handle.Value, readCoinResponse.Production.Value); if (i % 2 == 0) { Assert.Equal(openBlockResponse2.Handle.Value, readCoinResponse.Consumption.Value); } else { Assert.Equal(readCoinResponse.Consumption.Value, BlockAlias.Undefined.ConvertToBlockHandle(clientId.Mask).Value); } Assert.Equal(outpointSaverUncomm[i], readCoinResponse.Outpoint); } // Read a coin from the future var readFutureCoinRequest = GetCoinRequest.From( new RequestId(++reqNum), clientId, outpointSaverUncomm[0], openBlockResponse.Handle.ConvertToBlockAlias(clientId.Mask), clientId.Mask); // reconverted to BlockHandle after object construction socket.Send(readFutureCoinRequest.Span); socket.Receive(headerBuffer); { var header = MemoryMarshal.Cast <byte, MessageHeader>(headerBuffer)[0]; var readFutureCoinResponseBuffer = new byte[header.MessageSizeInBytes]; var readFutureCoinResponse = new GetCoinResponse(readFutureCoinResponseBuffer); headerBuffer.CopyTo(readFutureCoinResponseBuffer, 0); socket.Receive(readFutureCoinResponseBuffer.AsSpan(16)); Assert.Equal(GetCoinStatus.OutpointNotFound, readFutureCoinResponse.Status); } } finally { socket.Close(); instance.Stop(); } }