public void OpenGetBlockHandle() { var instance = GetInstance(); 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); // Get block handle var clientId = new ClientId(); var blockHandleRequest = GetBlockHandleRequest.From( new RequestId(1), clientId, openBlockResponse.UncommittedBlockId); socket.Send(blockHandleRequest.Span); var blockHandleResponse = new GetBlockHandleResponse(new byte[GetBlockHandleResponse.SizeInBytes]); socket.Receive(blockHandleResponse.Span); Assert.Equal(GetBlockHandleStatus.Success, blockHandleResponse.Status); Assert.Equal(openBlockResponse.Handle, blockHandleResponse.Handle); Assert.Equal(default(ClientId), blockHandleResponse.MessageHeader.ClientId); Assert.Equal(new RequestId(1), blockHandleResponse.MessageHeader.RequestId); } finally { socket.Close(); instance.Stop(); } }
public unsafe void OpenCommit() { var instance = GetInstance(); 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); // Commit block var blockId = new CommittedBlockId(); for (var i = 0; i < CommittedBlockId.SizeInBytes; i++) { blockId.Data[i] = (byte)i; } var commitBlockRequest = CommitBlockRequest.From( RequestId.MinRequestId, ClientId.MinClientId, openBlockResponse.Handle, blockId); socket.Send(commitBlockRequest.Span); var commitBlockResponse = new CommitBlockResponse(new byte[CommitBlockResponse.SizeInBytes]); socket.Receive(commitBlockResponse.Span); Assert.Equal(CommitBlockStatus.Success, commitBlockResponse.Status); // Get block info var getBlockInfoRequest = GetBlockInfoRequest.From( RequestId.MinRequestId, ClientId.MinClientId, openBlockResponse.Handle); socket.Send(getBlockInfoRequest.Span); var getBlockInfoResponse = new GetBlockInfoResponse(new byte[GetBlockInfoResponse.SizeInBytes]); socket.Receive(getBlockInfoResponse.Span); Assert.True(getBlockInfoResponse.CommittedBlockId.Equals(blockId)); } finally { socket.Close(); instance.Stop(); } }
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(); } }
private static void DoBenchmark(IPEndPoint endpoint, ILog log) { var rand = new Random(); // non-deterministic on purpose var genWatch = new Stopwatch(); genWatch.Start(); var generator = new CoinGenerator(rand); generator.GenerateSketches(CoinIoCount); log.Log(LogSeverity.Info, $"{CoinIoCount} coin I/Os generated in " + (genWatch.ElapsedMilliseconds / 1000f) + " seconds"); var rawSocket = new Socket(endpoint.AddressFamily, SocketType.Stream, ProtocolType.Tcp); rawSocket.Connect(endpoint); var socket = new SocketLikeAdapter(rawSocket); EnsureGenesisExists(socket); var handle = OpenBlock(CommittedBlockId.Genesis, socket, log); // Process coins var requestPool = new SpanPool <byte>(1024 * 1024); var responseBuffer = new Span <byte>(new byte[4096]); var watch = new Stopwatch(); var commitWatch = new Stopwatch(); var outpointSeed = generator.Random.Next(); for (var i = 0; i < generator.CoinSketches.Length; i++) { if (i % EpochSize == 0) { watch.Reset(); watch.Start(); } var sketch = generator.CoinSketches[i]; var outpoint = GetOutpoint(sketch, outpointSeed); if (sketch.IsProduction) { // intended side effect on 'requestPool' var writeCoinRequest = new ProduceCoinRequest( new RequestId((uint)i), ref outpoint, OutpointFlags.None, handle, satoshis: 123, nLockTime: 42, scriptSizeInBytes: 100, requestPool); var script = writeCoinRequest.Script; script[0] = (byte)i; } if (sketch.IsRead) { // intended side effect on 'requestPool' var readCoinRequest = new GetCoinRequest(new RequestId((uint)i), ref outpoint, handle, requestPool); } if (sketch.IsConsumption) { // intended side effect on 'requestPool' var writeCoinRequest = new ConsumeCoinRequest( new RequestId((uint)i), ref outpoint, handle, requestPool); } if (i % BatchSize == BatchSize - 1) { // send all the requests as a batch socket.Send(requestPool.Allocated()); requestPool.Reset(); for (var j = 0; j < BatchSize; j++) { socket.Receive(responseBuffer.Slice(0, 4)); var responseSize = responseBuffer[0]; socket.Receive(responseBuffer.Slice(4, responseSize - 4)); } } if (i % EpochSize == EpochSize - 1) { watch.Stop(); var nextBlockId = GetBlockId(); commitWatch.Reset(); commitWatch.Start(); CommitBlock(handle, nextBlockId, socket); commitWatch.Stop(); handle = OpenBlock(nextBlockId, socket, log); var elapsed = watch.ElapsedMilliseconds / 1000.0; // seconds var iops = (int)(EpochSize / elapsed); log.Log(LogSeverity.Info, $"Epoch {i / EpochSize} at {iops} IOps. Commit in {commitWatch.Elapsed.TotalMilliseconds} ms."); } } }