public void TestCommitBlock() { var(_, inbox, outbox, chainController, c5, _) = TestOpenBlock(); // C(0) -> C(1) -> C(2) -> C(3) -> C(4) // | \-> C(4-1) // | \-> U(4-2) // \-> C(2-1) -> C(3-1) var request = CommitBlockRequest.From( _r1, c5, _4_2.ConvertToBlockHandle(c5.Mask), GetMockBlockId(42)); inbox.TryWrite(request.Span); chainController.HandleRequest(); outbox.Next(); var result = new CommitBlockResponse(outbox.Peek().Span); Assert.Equal(MessageKind.CommitBlockResponse, result.MessageHeader.MessageKind); Assert.Equal(_r1, result.MessageHeader.RequestId); Assert.Equal(c5, result.MessageHeader.ClientId); // TODO: [vermorel] persistence unit tests should be isolated //var persister = new BlockchainPersister(TerabConfiguration.CommittedBlocksPersistencePath, // TerabConfiguration.UncommittedBlocksPersistencePath); //var newChain = persister.ReadBlockchain(); //Assert.True(chain.GetLastCommitted().BlockId.Equals(newChain.GetLastCommitted().BlockId)); }
public CommitBlockResponse CommitBlock(CommitBlockRequest request) { var status = _store.TryCommitBlock(request.BlockAlias, request.BlockId, out _); var requestId = request.MessageHeader.RequestId; var clientId = request.MessageHeader.ClientId; switch (status) { case CommitBlockStatus.Success: RefreshAndPropagateLineage(); return(new CommitBlockResponse(requestId, clientId, Messaging.CommitBlockStatus.Success, _pool)); case CommitBlockStatus.BlockNotFound: return(new CommitBlockResponse(requestId, clientId, Messaging.CommitBlockStatus.BlockNotFound, _pool)); case CommitBlockStatus.BlockIdMismatch: return(new CommitBlockResponse(requestId, clientId, Messaging.CommitBlockStatus.BlockIdMismatch, _pool)); default: throw new NotSupportedException(); } }
public void terab_utxo_commit_block() { terab_utxo_get_uncommitted_block(); _socket.ExpectReceive(data => { data.Clear(); Assert.True(data.Length == MessageHeader.SizeInBytes); var header = new MessageHeader(CommitBlockRequest.SizeInBytes, _r1, _c0, MessageKind.CommitBlock); var headerStorage = new MessageHeader[1]; headerStorage[0] = header; var headerBytes = MemoryMarshal.Cast <MessageHeader, byte>(headerStorage); headerBytes.CopyTo(data); return(MessageHeader.SizeInBytes); }); _socket.ExpectReceive(data => { data.Clear(); Assert.True(data.Length >= CommitBlockRequest.SizeInBytes - MessageHeader.SizeInBytes); var request = CommitBlockRequest.From( _r1, _c0, new BlockAlias(0, 0).ConvertToBlockHandle(_handleMask), CommittedBlockId.Genesis); request.Span.Slice(16).CopyTo(data); return(CommitBlockRequest.SizeInBytes - MessageHeader.SizeInBytes); }); _socket.ExpectConnected(() => true); _socket.ExpectConnected(() => true); _socket.ExpectSend(data => { Assert.Equal(CommitBlockResponse.SizeInBytes, data.Length); return(CommitBlockResponse.SizeInBytes); }); Assert.True(_clientConn.HandleRequest()); Assert.True(_dispatcher.HandleRequest()); Assert.True(_chainController.HandleRequest()); Assert.True(_dispatcher.HandleRequest()); Assert.True(_clientConn.HandleResponse()); _socket.ExpectAllDone(); }
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."); } }
private static void EnsureGenesisExists(ISocketLike socket) { var openGenesisRequest = OpenBlockRequest.ForGenesis(RequestId.MinRequestId); socket.Send(openGenesisRequest.Span); var openGenesisResponse = new OpenBlockResponse(new byte[OpenBlockResponse.SizeInBytes]); socket.Receive(openGenesisResponse.Span); if (openGenesisResponse.Status == OpenBlockStatus.Success) { var commitGenesisRequest = CommitBlockRequest.From( RequestId.MinRequestId, ClientId.MinClientId, openGenesisResponse.Handle, CommittedBlockId.Genesis); socket.Send(commitGenesisRequest.Span); var commitGenesisResponse = new CommitBlockResponse(new byte[CommitBlockResponse.SizeInBytes]); socket.Receive(commitGenesisResponse.Span); } }
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(); } }