public async Task GetBlock_Header_And_Body_Test() { var header = new BlockHeader() { ChainId = _chainId, Height = 1 }; var hash = header.GetHash(); await _blockManager.AddBlockHeaderAsync(header); var h = await _blockManager.GetBlockHeaderAsync(hash); Assert.Equal(header, h); var body = new BlockBody() { BlockHeader = hash }; await _blockManager.AddBlockBodyAsync(hash, body); var block = await _blockManager.GetBlockAsync(hash); Assert.Equal(block.Header, header); Assert.Equal(block.Body, body); }
public void CalculateBodyHash_Test() { //transaction count == 0 var blockBody = new BlockBody { BlockHeader = Hash.FromString("header") }; Should.Throw <InvalidOperationException>(() => blockBody.GetHash()); //block header == null blockBody = new BlockBody { TransactionIds = { Hash.FromString("tx1") }, }; Should.Throw <InvalidOperationException>(() => blockBody.GetHash()); blockBody = new BlockBody { BlockHeader = Hash.FromString("header"), TransactionIds = { new[] { Hash.FromString("tx1"), Hash.FromString("tx2"), Hash.FromString("tx3"), } } }; var hash = blockBody.GetHash(); hash.ShouldNotBeNull(); }
private Block GenerateBlockInformation(long height, bool withBlockExtraData) { var header = new BlockHeader() { Height = height, PreviousBlockHash = Hash.Generate() }; if (withBlockExtraData) { header.BlockExtraDatas.Add(ByteString.CopyFromUtf8("test1")); } var body = new BlockBody { BlockHeader = header.GetHash(), TransactionList = { new Transaction() }, Transactions = { Hash.Generate() } }; return(new Block { Height = header.Height, Header = header, Body = body }); }
protected virtual async Task <Block> FillBlockAfterExecutionAsync(BlockHeader blockHeader, List <Transaction> transactions, ReturnSetCollection returnSetCollection) { Logger.LogTrace("Start block field filling after execution."); var bloom = new Bloom(); var blockStateSet = new BlockStateSet { BlockHeight = blockHeader.Height, PreviousHash = blockHeader.PreviousBlockHash }; foreach (var returnSet in returnSetCollection.Executed) { foreach (var change in returnSet.StateChanges) { blockStateSet.Changes[change.Key] = change.Value; blockStateSet.Deletes.Remove(change.Key); } foreach (var delete in returnSet.StateDeletes) { blockStateSet.Deletes.AddIfNotContains(delete.Key); blockStateSet.Changes.Remove(delete.Key); } bloom.Combine(new[] { new Bloom(returnSet.Bloom.ToByteArray()) }); } blockHeader.Bloom = ByteString.CopyFrom(bloom.Data); blockHeader.MerkleTreeRootOfWorldState = CalculateWorldStateMerkleTreeRoot(blockStateSet); var allExecutedTransactionIds = transactions.Select(x => x.GetHash()).ToList(); var orderedReturnSets = returnSetCollection.ToList().AsParallel() .OrderBy(d => allExecutedTransactionIds.IndexOf(d.TransactionId)).ToList(); blockHeader.MerkleTreeRootOfTransactionStatus = CalculateTransactionStatusMerkleTreeRoot(orderedReturnSets); blockHeader.MerkleTreeRootOfTransactions = CalculateTransactionMerkleTreeRoot(allExecutedTransactionIds); var blockHash = blockHeader.GetHashWithoutCache(); var blockBody = new BlockBody(); blockBody.TransactionIds.AddRange(allExecutedTransactionIds); var block = new Block { Header = blockHeader, Body = blockBody }; blockStateSet.BlockHash = blockHash; Logger.LogTrace("Set block state set."); await _blockchainStateService.SetBlockStateSetAsync(blockStateSet); Logger.LogTrace("Finish block field filling after execution."); return(block); }
public BlockBodiesMessage(Block[] blocks) { Bodies = new BlockBody[blocks.Length]; for (int i = 0; i < blocks.Length; i++) { Bodies[i] = blocks[i] == null ? null : blocks[i].Body; } }
public void CreateGenesis() { var pp = "F:\\Projects\\MemeIum\\Keys"; var addresses = $"{pp}\\addr.txt"; Logger.Log("Genesis tests", 1); var bb = Services.GetService <IBlockChainService>(); var ww = Services.GetService <IWalletService>(); var miner = Services.GetService <IMinerService>(); var tx = new List <Transaction>(); var vouts = new List <InBlockTransactionVOut>(); var toAddr = new List <string>(File.ReadAllLines(addresses)); var mevout = new TransactionVOut() { Amount = 42000L * 100000L, FromAddress = ww.Address, ToAddress = ww.Address }; TransactionVOut.SetUniqueIdForVOut(mevout); vouts.Add(mevout.GetInBlockTransactionVOut()); var tBody = new TransactionBody() { FromAddress = ww.Address, Message = "Genesis block memes", PubKey = ww.PubKey, VInputs = new List <TransactionVIn>(), VOuts = vouts }; tx.Add(ww.MakeTransaction(tBody)); var body = new BlockBody() { Height = 0, LastBlockId = "0", MinerVOut = miner.GetMinerVOut(tx, 0), Nounce = "42", Target = FirstTarget(), Tx = tx }; var genesis = new Block() { Body = body, TimeOfCreation = DateTime.UtcNow }; Block.SetUniqueBlockId(genesis); bb.SaveBlock(genesis); Console.WriteLine("done"); Console.WriteLine(genesis.Body.Id); }
public async Task <Block> FillBlockAfterExecutionAsync(BlockHeader blockHeader, List <Transaction> transactions, List <ExecutionReturnSet> blockExecutionReturnSet) { var bloom = new Bloom(); var blockStateSet = new BlockStateSet { BlockHeight = blockHeader.Height, PreviousHash = blockHeader.PreviousBlockHash }; foreach (var returnSet in blockExecutionReturnSet) { foreach (var change in returnSet.StateChanges) { blockStateSet.Changes[change.Key] = change.Value; } if (returnSet.Status == TransactionResultStatus.Mined) { bloom.Combine(new[] { new Bloom(returnSet.Bloom.ToByteArray()) }); } } blockHeader.Bloom = ByteString.CopyFrom(bloom.Data); var merkleTreeRootOfWorldState = ComputeHash(GetDeterministicByteArrays(blockStateSet)); blockHeader.MerkleTreeRootOfWorldState = merkleTreeRootOfWorldState; var allExecutedTransactionIds = transactions.Select(x => x.GetHash()).ToList(); var bmt = new BinaryMerkleTree(); bmt.AddNodes(allExecutedTransactionIds); blockHeader.MerkleTreeRootOfTransactions = bmt.ComputeRootHash(); _blockExtraDataService.FillMerkleTreeRootExtraDataForTransactionStatus(blockHeader, blockExecutionReturnSet.Select(executionReturn => (executionReturn.TransactionId, executionReturn.Status))); var blockBody = new BlockBody(); blockBody.Transactions.AddRange(allExecutedTransactionIds); blockBody.TransactionList.AddRange(transactions); var block = new Block { Header = blockHeader, Body = blockBody }; blockBody.BlockHeader = blockHeader.GetHash(); blockStateSet.BlockHash = blockHeader.GetHash(); await _blockchainStateManager.SetBlockStateSetAsync(blockStateSet); return(block); }
public void Roundtrip_with_nulls() { BlockBodiesMessage message = new() { Bodies = new BlockBody[1] { null } }; var serializer = new BlockBodiesMessageSerializer(); SerializerTester.TestZero(serializer, message); } }
public void BlockBody_Test() { var transactionItems = GenerateFakeTransactions(3); var blockBody = new BlockBody() { TransactionIds = { transactionItems.Item2 } }; blockBody.TransactionsCount.ShouldBe(3); }
/// <summary> /// Response to recording request from side chain node. /// One request to many responses. /// </summary> /// <param name="request"></param> /// <param name="responseStream"></param> /// <param name="context"></param> /// <returns></returns> public override async Task RecordServerStreaming(RequestBlockInfo request, IServerStreamWriter <ResponseParentChainBlockInfo> responseStream, ServerCallContext context) { _logger?.Trace("Parent Chain Server received IndexedInfo message."); try { var height = request.NextHeight; var sideChainId = request.ChainId; while (height <= await BlockChain.GetCurrentBlockHeightAsync()) { IBlock block = await BlockChain.GetBlockByHeightAsync(height); BlockHeader header = block?.Header; BlockBody body = block?.Body; var res = new ResponseParentChainBlockInfo { Success = block != null }; if (res.Success) { res.BlockInfo = new ParentChainBlockInfo { Root = new ParentChainBlockRootInfo { Height = height, SideChainBlockHeadersRoot = header?.SideChainBlockHeadersRoot, SideChainTransactionsRoot = header?.SideChainTransactionsRoot, ChainId = header?.ChainId } }; var tree = await _binaryMerkleTreeManager .GetSideChainTransactionRootsMerkleTreeByHeightAsync(header?.ChainId, height); //Todo: this is to tell side chain the height of side chain block in this main chain block, which could be removed with subsequent improvement. body?.IndexedInfo.Where(predicate: i => i.ChainId.Equals(sideChainId)) .Select((info, index) => new KeyValuePair <ulong, MerklePath>(info.Height, tree.GenerateMerklePath(index))) .ForEach(kv => res.BlockInfo.IndexedBlockInfo.Add(kv.Key, kv.Value)); } //_logger?.Log(LogLevel.Trace, $"Parent Chain Server responsed IndexedInfo message of height {height}"); await responseStream.WriteAsync(res); height++; } } catch (Exception e) { _logger?.Error(e, "Miner server RecordDuplexStreaming failed."); } }
public Task <BlockBody[]> GetBlockBodies(IList <Keccak> blockHashes, CancellationToken token) { BlockBody[] result = new BlockBody[blockHashes.Count]; for (int i = 0; i < blockHashes.Count; i++) { Block block = _remoteTree.FindBlock(blockHashes[i], BlockTreeLookupOptions.RequireCanonical); result[i] = new BlockBody(block.Transactions, block.Ommers); } return(Task.FromResult(result)); }
public Task <BlockBody[]> GetBlocks(Keccak[] blockHashes, CancellationToken token) { BlockBody[] result = new BlockBody[blockHashes.Length]; for (int i = 0; i < blockHashes.Length; i++) { Block block = _remoteTree.FindBlock(blockHashes[i], true); result[i] = new BlockBody(block.Transactions, block.Ommers); } return(Task.FromResult(result)); }
public void SetBody(int index, BlockBody body) { Block block = Blocks[_indexMapping[index]]; if (body == null) { throw new EthSyncException($"{_syncPeer} sent an empty body for {block.ToString(Block.Format.Short)}."); } block.Body = body; }
public void BlockBody_Test() { var blockHeader = GenerateBlockHeader(); var transactionItems = GenerateFakeTransactions(3); var blockBody = new BlockBody() { BlockHeader = blockHeader.GetHash(), TransactionIds = { transactionItems.Item2 } }; blockBody.TransactionsCount.ShouldBe(3); }
public async Task <Block> FillBlockAfterExecutionAsync(BlockHeader blockHeader, List <Transaction> transactions, List <ExecutionReturnSet> blockExecutionReturnSet) { var bloom = new Bloom(); var blockStateSet = new BlockStateSet { BlockHeight = blockHeader.Height, PreviousHash = blockHeader.PreviousBlockHash }; foreach (var returnSet in blockExecutionReturnSet) { foreach (var change in returnSet.StateChanges) { blockStateSet.Changes[change.Key] = change.Value; } if (returnSet.Status == TransactionResultStatus.Mined) { bloom.Combine(new[] { new Bloom(returnSet.Bloom.ToByteArray()) }); } } blockHeader.Bloom = ByteString.CopyFrom(bloom.Data); blockHeader.MerkleTreeRootOfWorldState = CalculateWorldStateMerkleTreeRoot(blockStateSet); blockHeader.MerkleTreeRootOfTransactionStatus = CalculateTransactionStatusMerkleTreeRoot(blockExecutionReturnSet); var allExecutedTransactionIds = transactions.Select(x => x.GetHash()).ToList(); blockHeader.MerkleTreeRootOfTransactions = CalculateTransactionMerkleTreeRoot(allExecutedTransactionIds); var blockHash = blockHeader.GetHashWithoutCache(); var blockBody = new BlockBody { BlockHeader = blockHash }; blockBody.TransactionIds.AddRange(allExecutedTransactionIds); var block = new Block { Header = blockHeader, Body = blockBody }; blockBody.BlockHeader = blockHash; blockStateSet.BlockHash = blockHash; await _blockchainStateManager.SetBlockStateSetAsync(blockStateSet); return(block); }
public void SetBody(int index, BlockBody body) { int mappedIndex = _indexMapping[index]; Block block = Blocks[mappedIndex]; if (body == null) { throw new EthSyncException($"{_syncPeer} sent an empty body for {block.ToString(Block.Format.Short)}."); } Blocks[mappedIndex] = block.WithReplacedBody(body); }
private BlockBody ParseBlockBody() { var node = new BlockBody(); var statements = ExtractAllChildren(new Func <Statement>[] { ParseStatement }); node.AddChildren(statements); return(node); }
public async Task <BlockBody[]> BuildBlocksResponse(Keccak[] blockHashes, Response flags) { bool consistent = flags.HasFlag(Response.Consistent); bool validSeals = flags.HasFlag(Response.ValidSeals); bool noEmptySpaces = flags.HasFlag(Response.NoEmptySpace); bool justFirst = flags.HasFlag(Response.JustFirstHeader); bool allKnown = flags.HasFlag(Response.AllKnown); bool timeoutOnFullBatch = flags.HasFlag(Response.TimeoutOnFullBatch); if (timeoutOnFullBatch && blockHashes.Length == SyncBatchSize.Max) { throw new TimeoutException(); } BlockHeader startHeader = _blockTree.FindHeader(blockHashes[0], false); if (startHeader == null) { startHeader = Build.A.BlockHeader.WithHash(blockHashes[0]).TestObject; } BlockHeader[] blockHeaders = new BlockHeader[blockHashes.Length]; BlockBody[] blockBodies = new BlockBody[blockHashes.Length]; blockBodies[0] = new BlockBody(new Transaction[0], new BlockHeader[0]); blockHeaders[0] = startHeader; if (!justFirst) { for (int i = 1; i < blockHashes.Length; i++) { blockHeaders[i] = consistent ? Build.A.BlockHeader.WithParent(blockHeaders[i - 1]).TestObject : Build.A.BlockHeader.WithNumber(blockHeaders[i - 1].Number + 1).TestObject; _testHeaderMapping[startHeader.Number + i] = blockHeaders[i].Hash; Block block = consistent ? Build.A.Block.WithHeader(blockHeaders[i]).TestObject : Build.A.Block.WithHeader(blockHeaders[i - 1]).TestObject; blockBodies[i] = new BlockBody(block.Transactions, block.Ommers); if (allKnown) { _blockTree.SuggestBlock(block); } } } BlockBodiesMessage message = new BlockBodiesMessage(blockBodies); byte[] messageSerialized = _bodiesSerializer.Serialize(message); return(await Task.FromResult(_bodiesSerializer.Deserialize(messageSerialized).Bodies)); }
private void PrepareBodiesResponse(BodiesSyncBatch bodiesSyncBatch, LatencySyncPeerMock syncPeer, IBlockTree tree) { int requestSize = bodiesSyncBatch.Request.Length; int responseSize = bodiesSyncBatch.Request.Length; if (_incorrectByTooLongMessages.Contains(syncPeer)) { responseSize *= 2; TestContext.WriteLine($"{_time,6} | SYNC PEER {syncPeer.Node:s} WILL SEND TOO LONG MESSAGE ({responseSize} INSTEAD OF {requestSize})"); } else if (_incorrectByTooShortMessages.Contains(syncPeer)) { responseSize = Math.Max(1, responseSize / 2); TestContext.WriteLine($"{_time,6} | SYNC PEER {syncPeer.Node:s} WILL SEND TOO SHORT MESSAGE ({responseSize} INSTEAD OF {requestSize})"); } bodiesSyncBatch.Response = new BlockBody[responseSize]; int maxResponseSize = _peerMaxResponseSizes.ContainsKey(syncPeer) ? Math.Min(responseSize, _peerMaxResponseSizes[syncPeer]) : responseSize; for (int i = 0; i < Math.Min(maxResponseSize, requestSize); i++) { Block block = tree.FindBlock(bodiesSyncBatch.Request[i], BlockTreeLookupOptions.None); bodiesSyncBatch.Response[i] = new BlockBody(block.Transactions, block.Ommers); } if (_maliciousByShortAtStart.Contains(syncPeer)) { bodiesSyncBatch.Response[0] = null; TestContext.WriteLine($"{_time,6} | SYNC PEER {syncPeer.Node:s} WILL SEND A MALICIOUS (SHORT AT START) MESSAGE"); } if (_maliciousByInvalidTxs.Contains(syncPeer)) { for (int i = 0; i < bodiesSyncBatch.Response.Length; i++) { BlockBody valid = bodiesSyncBatch.Response[i]; bodiesSyncBatch.Response[i] = new BlockBody(new[] { Build.A.Transaction.WithData(Bytes.FromHexString("bad")).TestObject }, valid.Ommers); } } if (_maliciousByInvalidOmmers.Contains(syncPeer)) { for (int i = 0; i < bodiesSyncBatch.Response.Length; i++) { BlockBody valid = bodiesSyncBatch.Response[i]; bodiesSyncBatch.Response[i] = new BlockBody(valid.Transactions, new[] { Build.A.BlockHeader.WithAuthor(new Address(Keccak.Compute("bad_ommer").Bytes.Take(20).ToArray())).TestObject }); } } }
private bool TryPrepareBlock(BlockInfo blockInfo, BlockBody blockBody, out Block?block) { BlockHeader header = _blockTree.FindHeader(blockInfo.BlockHash); bool txRootIsValid = new TxTrie(blockBody.Transactions).RootHash == header.TxRoot; bool ommersHashIsValid = OmmersHash.Calculate(blockBody.Ommers) == header.OmmersHash; if (txRootIsValid && ommersHashIsValid) { block = new Block(header, blockBody); } else { block = null; } return(block != null); }
public GethLikeTxTrace?Trace(long blockNumber, Transaction tx, GethTraceOptions options, CancellationToken cancellationToken) { Block block = _blockTree.FindBlock(blockNumber, BlockTreeLookupOptions.RequireCanonical); if (block == null) { throw new InvalidOperationException("Only historical blocks"); } if (tx.Hash == null) { throw new InvalidOperationException("Cannot trace transactions without tx hash set."); } block = block.WithReplacedBodyCloned(BlockBody.WithOneTransactionOnly(tx)); GethLikeBlockTracer blockTracer = new(tx.Hash, options); _processor.Process(block, ProcessingOptions.Trace, blockTracer.WithCancellation(cancellationToken)); return(blockTracer.BuildResult().SingleOrDefault()); }
public Task <BlockBody[]> GetBlocks(Keccak[] blockHashes, CancellationToken token) { if (_causeTimeoutOnBlocks) { return(Task.FromException <BlockBody[]>(new TimeoutException())); } BlockBody[] result = new BlockBody[blockHashes.Length]; for (int i = 0; i < blockHashes.Length; i++) { foreach (Block block in Blocks) { if (block.Hash == blockHashes[i]) { result[i] = new BlockBody(block.Transactions, block.Ommers); } } } return(Task.FromResult(result)); }
public Task <BlockBody[]> GetBlockBodies(IReadOnlyList <Keccak> blockHashes, CancellationToken token) { if (_causeTimeoutOnBlocks) { return(Task.FromException <BlockBody[]>(new TimeoutException())); } BlockBody[] result = new BlockBody[blockHashes.Count]; for (int i = 0; i < blockHashes.Count; i++) { foreach (Block block in Blocks) { if (block.Hash == blockHashes[i]) { result[i] = new BlockBody(block.Transactions, block.Uncles); } } } return(Task.FromResult(result)); }
public void CalculateBodyHash_Test() { //transaction count == 0 var blockBody = new BlockBody(); Should.Throw <InvalidOperationException>(() => blockBody.GetHash()); blockBody = new BlockBody { TransactionIds = { new[] { HashHelper.ComputeFrom("tx1"), HashHelper.ComputeFrom("tx2"), HashHelper.ComputeFrom("tx3"), } } }; var hash = blockBody.GetHash(); hash.ShouldNotBeNull(); }
public GethLikeTxTrace?Trace(BlockParameter blockParameter, Transaction tx, GethTraceOptions options, CancellationToken cancellationToken) { Block block = _blockTree.FindBlock(blockParameter); if (block is null) { throw new InvalidOperationException($"Cannot find block {blockParameter}"); } tx.Hash ??= tx.CalculateHash(); block = block.WithReplacedBodyCloned(BlockBody.WithOneTransactionOnly(tx)); ITransactionProcessorAdapter currentAdapter = _transactionProcessorAdapter.CurrentAdapter; _transactionProcessorAdapter.CurrentAdapter = new TraceTransactionProcessorAdapter(_transactionProcessorAdapter.TransactionProcessor); try { return(Trace(block, tx.Hash, cancellationToken, options)); } finally { _transactionProcessorAdapter.CurrentAdapter = currentAdapter; } }
public void BlockBody_Test() { var blockHeader = new BlockHeader() { PreviousBlockHash = Hash.Generate(), ChainId = 1234, Height = 1, }; var transactionItems = GenerateFakeTransactions(3); var blockBody = new BlockBody() { BlockHeader = blockHeader.GetHash(), TransactionList = { transactionItems.Item1 }, Transactions = { transactionItems.Item2 }, BinaryMerkleTree = { Nodes = { Hash.Generate(), Hash.Generate() }, LeafCount = 2 } }; blockBody.TransactionsCount.ShouldBe(3); blockBody.BinaryMerkleTree.ShouldNotBe(null); }
private void InitData(string path) { List <Block> BlockList = Tools.BytesToBlock(Tools.ReadPcapngFile(path)); List <PacketData> Packist = new List <PacketData>(); IEnumerator itor = BlockList.GetEnumerator(); while (itor.MoveNext()) { if (Tools.BytesToInt((itor.Current as Block).BlockType, 0) == 6) { BlockBody blockBody = new BlockBody((itor.Current as Block).BlockBody); if (blockBody.PacketData.Length > 66) { PacketData packetData = new PacketData(blockBody.PacketData); packetData.Time = blockBody.Time; if (packetData.IP_Protocol == 6) { Packist.Add(packetData); } } } } DispatcherPacket(Packist); }
public static long EstimateSize(BlockBody blockBody) { if (blockBody == null) { return(0); } long estimate = 80L; estimate += (blockBody.Transactions?.Length ?? 0) * 8L; estimate += (blockBody.Ommers?.Length ?? 0) * 8L; foreach (Transaction transaction in blockBody.Transactions ?? Array.Empty <Transaction>()) { estimate += EstimateSize(transaction); } foreach (BlockHeader header in blockBody.Ommers ?? Array.Empty <BlockHeader>()) { estimate += EstimateSize(header); } return(estimate); }
public async Task AddBlockBodyAsync(Hash blockHash, BlockBody blockBody) { await _dataStore.InsertAsync(blockHash.Clone().OfType(HashType.BlockBodyHash), blockBody); }
public void Serialization_ByteArray_Test() { //Hash test var hash = HashHelper.ComputeFrom("hash"); var hashArray = SerializationHelper.Serialize(hash); var hash1 = SerializationHelper.Deserialize <Hash>(hashArray); hash.ShouldBe(hash1); //Address test var address = SampleAddress.AddressList[0]; var addressArray = SerializationHelper.Serialize(address); var address1 = SerializationHelper.Deserialize <Address>(addressArray); address.ShouldBe(address1); //Transaction test var transaction = new Transaction { From = SampleAddress.AddressList[1], To = SampleAddress.AddressList[2], Params = ByteString.CopyFromUtf8("test"), MethodName = "TestMethod", RefBlockNumber = 1, RefBlockPrefix = ByteString.Empty }; var transactionArray = SerializationHelper.Serialize(transaction); var transaction1 = SerializationHelper.Deserialize <Transaction>(transactionArray); transaction.ShouldBe(transaction1); //Block header test var header = new BlockHeader { ChainId = ChainHelper.ConvertBase58ToChainId("AELF"), Height = AElfConstants.GenesisBlockHeight, Bloom = ByteString.CopyFromUtf8("bloom"), PreviousBlockHash = HashHelper.ComputeFrom("PreviousBlockHash"), MerkleTreeRootOfTransactions = HashHelper.ComputeFrom("MerkleTreeRootOfTransactions"), MerkleTreeRootOfWorldState = HashHelper.ComputeFrom("MerkleTreeRootOfWorldState"), Time = TimestampHelper.GetUtcNow(), MerkleTreeRootOfTransactionStatus = HashHelper.ComputeFrom("MerkleTreeRootOfTransactionStatus") }; var headerArray = SerializationHelper.Serialize(header); var header1 = SerializationHelper.Deserialize <BlockHeader>(headerArray); header.ShouldBe(header1); //Block body test var body = new BlockBody { TransactionIds = { transaction.GetHash() } }; var bodyArray = SerializationHelper.Serialize(body); var body1 = SerializationHelper.Deserialize <BlockBody>(bodyArray); body.ShouldBe(body1); //Block test var block = new Block { Body = body, Header = header, }; var blockArray = SerializationHelper.Serialize(block); var block1 = SerializationHelper.Deserialize <Block>(blockArray); block.ShouldBe(block1); }