Beispiel #1
0
        public void CommitBlock(BlockHandle handle, CommittedBlockId blockId)
        {
            var returnCode = PInvokes.terab_utxo_commit_block(_connection, handle, ref blockId);

            if (returnCode != ReturnCode.SUCCESS)
            {
                throw new TerabException("CommitBlock failed.", returnCode);
            }
        }
Beispiel #2
0
        private static unsafe CommittedBlockId GetMockBlockId(byte filler)
        {
            var blockId = new CommittedBlockId();

            for (var i = 0; i < CommittedBlockId.SizeInBytes; i++)
            {
                blockId.Data[i] = filler;
            }

            return(blockId);
        }
Beispiel #3
0
        public BlockHandle GetCommittedBlock(CommittedBlockId blockId)
        {
            var returnCode = PInvokes.terab_utxo_get_committed_block(
                _connection, ref blockId, out BlockHandle handle);

            if (returnCode != ReturnCode.SUCCESS)
            {
                throw new TerabException("GetCommittedBlock failed.", returnCode);
            }

            return(handle);
        }
Beispiel #4
0
        private static unsafe CommittedBlockId GetBlockId()
        {
            var buffer = new byte[32];

            RandomNumberGenerator.Fill(buffer);

            var blockId = new CommittedBlockId();

            for (var i = 0; i < 32; i++)
            {
                blockId.Data[i] = buffer[i];
            }

            return(blockId);
        }
Beispiel #5
0
        public unsafe void DeepChain()
        {
            var store = new ChainStore(new MemoryMappedFileSlim(MemoryMappedFile.CreateNew(null,
                                                                                           BlockHeight * 120 + 4096 - (BlockHeight * 120) % 4096)));

            store.Initialize();

            var watch = new Stopwatch();

            watch.Start();

            store.TryOpenBlock(CommittedBlockId.GenesisParent, out var ub);

            for (var i = 0; i < BlockHeight; i++)
            {
                var blockId = new CommittedBlockId();
                for (var j = 0; j < 4; j++)
                {
                    blockId.Data[j] = (byte)(j >> (i * 8));
                }
                blockId.Data[5] = 1; // ensure non-zero

                store.TryCommitBlock(ub.Alias, blockId, out var cb);

                // Filtering to improve speed.
                // Only ~1ms, but we can have a million calls.
                if (i <= 1000)
                {
                    var lineage2 = store.GetLineage();
                    Assert.False(lineage2.IsUncommitted(cb.Alias));
                }

                store.TryOpenBlock(blockId, out ub);
            }

            //  ~0.013ms to open & commit a new block against 500k blocks.
            _log.Log(LogSeverity.Info, $"{(double)watch.ElapsedMilliseconds / BlockHeight} ms per block (pure I/O).");

            watch.Reset();
            watch.Start();

            // ~70ms against 500k blocks with orphan at zero height (when disabling 'OldestOrphanHeight').
            var lastLineage = store.GetLineage();

            Assert.True(lastLineage.IsUncommitted(ub.Alias));

            _log.Log(LogSeverity.Info, $"{(double)watch.ElapsedMilliseconds } ms on GetLineage last block (at {BlockHeight} height).");
        }
Beispiel #6
0
        private static void CommitBlock(BlockHandle handle, CommittedBlockId blockId, ISocketLike socket)
        {
            var request = CommitBlockRequest.From(
                RequestId.MinRequestId, ClientId.MinClientId, handle, blockId);

            socket.Send(request.Span);

            var response = new CommitBlockResponse(new byte[CommitBlockResponse.SizeInBytes]);

            socket.Receive(response.Span);

            if (response.Status != CommitBlockStatus.Success)
            {
                throw new InvalidOperationException("Failed to commit block.");
            }
        }
Beispiel #7
0
        /// <summary>
        /// Allocate an array. Intended for testing purposes only.
        /// </summary>
        internal static OpenBlockRequest From(
            RequestId requestId, ClientId clientId, CommittedBlockId parentId)
        {
            var request = new OpenBlockRequest {
                _buffer = new Span <byte>(new byte[sizeof(Header)])
            };

            request.MessageHeader.MessageSizeInBytes = Header.SizeInBytes;
            request.MessageHeader.RequestId          = requestId;
            request.MessageHeader.ClientId           = clientId;
            request.MessageHeader.MessageKind        = MessageKind.OpenBlock;

            request.AsHeader.ParentId = parentId;

            return(request);
        }
Beispiel #8
0
        /// <summary>
        /// Allocate an array. Intended for testing purposes only.
        /// </summary>
        internal static CommitBlockRequest From(
            RequestId requestId, ClientId clientId, BlockHandle handle, CommittedBlockId blockId)
        {
            var request = new CommitBlockRequest {
                _buffer = new Span <byte>(new byte[sizeof(Header)])
            };

            request.MessageHeader.MessageSizeInBytes = Header.SizeInBytes;
            request.MessageHeader.RequestId          = requestId;
            request.MessageHeader.ClientId           = clientId;
            request.MessageHeader.MessageKind        = MessageKind.CommitBlock;

            request.AsHeader.Handle  = handle;
            request.AsHeader.BlockId = blockId;

            return(request);
        }
Beispiel #9
0
        public BlockHandle OpenBlock(CommittedBlockId parent, out UncommittedBlockId ucid)
        {
            ucid = default;

            var returnCode = PInvokes.terab_utxo_open_block(
                _connection,
                ref parent,
                out BlockHandle handle,
                ref ucid);

            if (returnCode != ReturnCode.SUCCESS)
            {
                throw new TerabException("OpenBlock failed.", returnCode);
            }

            return(handle);
        }
Beispiel #10
0
        private static BlockHandle OpenBlock(CommittedBlockId parentId, ISocketLike socket, ILog log)
        {
            var openBlockRequest = OpenBlockRequest.From(
                RequestId.MinRequestId, ClientId.MinClientId, parentId);

            socket.Send(openBlockRequest.Span);

            var openBlockResponse = new OpenBlockResponse(new byte[OpenBlockResponse.SizeInBytes]);

            socket.Receive(openBlockResponse.Span);

            if (openBlockResponse.Status != OpenBlockStatus.Success)
            {
                throw new InvalidOperationException("Failed to open block.");
            }

            log.Log(LogSeverity.Info, "Block opened, writing coins...");

            return(openBlockResponse.Handle);
        }
Beispiel #11
0
        public void TryAddConsumptionInPastTest()
        {
            var volatileStore = new VolatilePackStore(1, new[] { 4096 });
            var hash          = GetMockHash().Object;
            var rand          = new Random(2);

            // Create a real lineage
            var cBlocks = new List <CommittedBlock>();

            cBlocks.Add(new CommittedBlock(CommittedBlockId.Genesis, BlockAlias.Genesis, BlockAlias.GenesisParent));
            var firstBlockAlias = new BlockAlias(1, 0);

            cBlocks.Add(new CommittedBlock(
                            CommittedBlockId.ReadFromHex("AAAAAAAABBBBBBBBCCCCCCCCDDDDDDDDAAAAAAAABBBBBBBBCCCCCCCCDDDDDDDD"),
                            firstBlockAlias, BlockAlias.Genesis));
            var futureBlockAlias = new BlockAlias(2, 0);

            cBlocks.Add(new CommittedBlock(
                            CommittedBlockId.ReadFromHex("AAAABBBBBBBBCCCCCCCCDDDDDDDDAAAAAAAABBBBBBBBCCCCCCCCDDDDDDDDAAAA"),
                            futureBlockAlias, firstBlockAlias));

            var realLineage = new Lineage(cBlocks, new List <UncommittedBlock>(), 100);

            var sozu = GetSozuTable(volatileStore, hash);

            var coin1 = GetCoin(rand);

            // The next two commands will work because the fact that a block is uncommitted is not verified anymore.
            // If this test is moved into the ICoinStore at any point, adding a previous consumption should fail
            // already because a 'previous' block always has to be committed.
            var ret = sozu.AddProduction(hash.Hash(ref coin1.Outpoint), ref coin1.Outpoint, false, coin1.Payload,
                                         futureBlockAlias,
                                         realLineage);

            Assert.Equal(CoinChangeStatus.Success, ret);

            var cons = sozu.AddConsumption(hash.Hash(ref coin1.Outpoint), ref coin1.Outpoint, firstBlockAlias,
                                           realLineage);

            Assert.Equal(CoinChangeStatus.InvalidContext, cons);
        }
Beispiel #12
0
        public GetBlockInfoResponse(
            ref MessageHeader requestHeader,
            CommittedBlockId committedBlockId,
            BlockAlias alias,
            BlockAlias parent,
            int blockHeight,
            BlockHandleMask mask,
            SpanPool <byte> pool)
        {
            _buffer = pool.GetSpan(Header.SizeInBytes);

            AsHeader.ResponseHeader                    = requestHeader;
            AsHeader.ResponseHeader.MessageKind        = MessageKind.BlockInfoResponse;
            AsHeader.ResponseHeader.MessageSizeInBytes = Header.SizeInBytes;

            AsHeader.CommittedBlockId = committedBlockId;
            AsHeader.Handle           = alias.ConvertToBlockHandle(mask);
            AsHeader.Parent           = parent.ConvertToBlockHandle(mask);
            AsHeader.BlockHeight      = blockHeight;
            AsHeader.IsCommitted      = true;
        }
Beispiel #13
0
        public void TryGetCoinInFutureTest()
        {
            var volatileStore = new VolatilePackStore(1, new[] { 4096 });
            var hash          = GetMockHash().Object;
            var rand          = new Random(2);

            // Create a real lineage. It doesn't matter if all blocks are committed because we are just reading.
            var cBlocks = new List <CommittedBlock>();

            cBlocks.Add(new CommittedBlock(CommittedBlockId.Genesis, BlockAlias.Genesis, BlockAlias.GenesisParent));
            var firstBlockAlias = new BlockAlias(1, 0);

            cBlocks.Add(new CommittedBlock(
                            CommittedBlockId.ReadFromHex("AAAAAAAABBBBBBBBCCCCCCCCDDDDDDDDAAAAAAAABBBBBBBBCCCCCCCCDDDDDDDD"),
                            firstBlockAlias, BlockAlias.Genesis));
            var futureBlockAlias = new BlockAlias(2, 0);

            cBlocks.Add(new CommittedBlock(
                            CommittedBlockId.ReadFromHex("AAAABBBBBBBBCCCCCCCCDDDDDDDDAAAAAAAABBBBBBBBCCCCCCCCDDDDDDDDAAAA"),
                            futureBlockAlias, firstBlockAlias));

            var realLineage = new Lineage(cBlocks, new List <UncommittedBlock>(), 100);

            var sozu = GetSozuTable(volatileStore, hash);

            var coin1 = GetCoin(rand);

            var ret = sozu.AddProduction(hash.Hash(ref coin1.Outpoint), ref coin1.Outpoint, false, coin1.Payload,
                                         futureBlockAlias,
                                         realLineage);

            Assert.Equal(CoinChangeStatus.Success, ret);

            var read = sozu.TryGet(hash.Hash(ref coin1.Outpoint), ref coin1.Outpoint, firstBlockAlias,
                                   realLineage, out var coin, out var prod, out var cons);

            Assert.False(read);
        }
Beispiel #14
0
        private ILineage MakeLineage()
        {
            var blockId1   = CommittedBlockId.ReadFromHex("0000000000000000000000000000000000000000000000000000000000AAA333");
            var commBlock1 = new CommittedBlock(blockId1, BlockAlias.Genesis, BlockAlias.GenesisParent);
            var blockId2   = CommittedBlockId.ReadFromHex("0000000000000000000000000000000000000000000000000000000000BBB444");
            var commBlock2 = new CommittedBlock(blockId2, new BlockAlias(2), BlockAlias.Genesis);
            var blockId3   = CommittedBlockId.ReadFromHex("0000000000000000000000000000000000000000000000000000000000CCC555");
            var commBlock3 = new CommittedBlock(blockId3, new BlockAlias(3), new BlockAlias(2));

            var uncommBlock = new UncommittedBlock(UncommittedBlockId.Create(), new BlockAlias(4), new BlockAlias(3));

            var committedBlocks = new List <CommittedBlock>();

            committedBlocks.Add(commBlock1);
            committedBlocks.Add(commBlock2);
            committedBlocks.Add(commBlock3);

            var uncommittedBlocks = new List <UncommittedBlock>();

            uncommittedBlocks.Add(uncommBlock);

            return(new Lineage(committedBlocks, uncommittedBlocks, 100));
        }
Beispiel #15
0
        public OpenBlockStatus TryOpenBlock(CommittedBlockId parent, out UncommittedBlock freshBlock)
        {
            var blocks     = GetBlocks();
            var blockCount = AsHeader.BlockCount;
            var lowerIndex = Math.Max(0, blockCount - BlockScanLimit);

            freshBlock = default;

            if (blockCount == 0 && !parent.Equals(CommittedBlockId.GenesisParent))
            {
                return(OpenBlockStatus.ParentNotFound);
            }

            // Find the parent, and assess the block height
            int parentBlockHeight = -1;
            var parentAlias       = BlockAlias.Undefined;

            for (var i = blockCount - 1; i >= lowerIndex; i--)
            {
                ref var candidate = ref blocks[i];
                if (candidate.IsDeleted)
                {
                    continue;
                }

                if (candidate.BlockId.Equals(parent))
                {
                    parentBlockHeight = candidate.BlockHeight;
                    parentAlias       = candidate.Alias;
                    break;
                }

                if (i == 0)
                {
                    return(OpenBlockStatus.ParentNotFound);
                }
            }
Beispiel #16
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 #17
0
 internal static extern ReturnCode terab_utxo_open_block(
     SafeConnectionHandle connection,
     ref CommittedBlockId parentId,
     out BlockHandle handle,
     ref UncommittedBlockId ucid);
Beispiel #18
0
 internal static extern ReturnCode terab_utxo_commit_block(
     SafeConnectionHandle connection,
     BlockHandle handle,
     ref CommittedBlockId blockId);
Beispiel #19
0
 internal static extern ReturnCode terab_utxo_get_committed_block(
     SafeConnectionHandle connection,
     ref CommittedBlockId blockId,
     out BlockHandle handle);
Beispiel #20
0
        /// <summary>
        /// Allocate an array. Intended for testing purposes only.
        /// </summary>
        internal static GetBlockHandleRequest From(RequestId requestId, ClientId clientId, CommittedBlockId blockId)
        {
            var request = new GetBlockHandleRequest {
                _buffer = new Span <byte>(new byte[Header.SizeInBytes])
            };

            request.MessageHeader.MessageSizeInBytes = Header.SizeInBytes;
            request.MessageHeader.RequestId          = requestId;
            request.MessageHeader.ClientId           = clientId;
            request.MessageHeader.MessageKind        = MessageKind.GetBlockHandle;

            request.AsHeader.CommittedBlockId = blockId;
            request.AsHeader.IsCommitted      = true;

            return(request);
        }
Beispiel #21
0
 public CommittedBlock(CommittedBlockId blockId, BlockAlias alias, BlockAlias parent)
 {
     BlockId = blockId;
     Alias   = alias;
     Parent  = parent;
 }