Beispiel #1
0
        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();
            }
        }
Beispiel #2
0
        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();
            }
        }
Beispiel #3
0
        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();
            }
        }
Beispiel #4
0
        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.");
                }
            }
        }