private IEnumerable <(long, MerklePath)> GetEnumerableMerklePath(IList <SideChainBlockData> indexedSideChainBlockDataResult, int sideChainId) { var binaryMerkleTree = new BinaryMerkleTree(); foreach (var blockInfo in indexedSideChainBlockDataResult) { binaryMerkleTree.AddNode(blockInfo.TransactionMerkleTreeRoot); } binaryMerkleTree.ComputeRootHash(); // This is to tell side chain the merkle path for one side chain block, // which could be removed with subsequent improvement. // This assumes indexing multi blocks from one chain at once, actually only one block every time right now. var merklepathList = new List <(long, MerklePath)>(); for (var i = 0; i < indexedSideChainBlockDataResult.Count; i++) { var info = indexedSideChainBlockDataResult[i]; if (!info.ChainId.Equals(sideChainId)) { continue; } var merklePath = binaryMerkleTree.GenerateMerklePath(i); merklepathList.Add((info.Height, merklePath)); } //Logger.LogTrace($"Got merkle path list size {merklepathList.Count}"); return(merklepathList); }
public void MultiNodesTest() { var tree1 = BinaryMerkleTree.FromLeafNodes(CreateLeaves(new[] { "a", "e" })); //See if the hash of merkle tree is equal to the element’s hash. var root1 = tree1.Root; Assert.Equal(GetHashFromStrings("a", "e"), root1); var tree2 = BinaryMerkleTree.FromLeafNodes(CreateLeaves(new[] { "a", "e", "l" })); var root2 = tree2.Root; Hash right = GetHashFromStrings("l", "l"); Assert.Equal(HashHelper.ConcatAndCompute(root1, right), root2); var tree3 = BinaryMerkleTree.FromLeafNodes(CreateLeaves(new[] { "a", "e", "l", "f" })); var root3 = tree3.Root; Hash right2 = GetHashFromStrings("l", "f"); Assert.Equal(HashHelper.ConcatAndCompute(root1, right2), root3); var tree4 = BinaryMerkleTree.FromLeafNodes(CreateLeaves(new[] { "a", "e", "l", "f", "a" })); var root4 = tree4.Root; Hash l2 = GetHashFromStrings("a", "a"); Hash l3 = HashHelper.ConcatAndCompute(l2, l2); Assert.Equal(HashHelper.ConcatAndCompute(root3, l3), root4); }
private Hash ComputeRootHash(IEnumerable <SideChainBlockData> blockInfo) { var binaryMerkleTree = BinaryMerkleTree.FromLeafNodes(blockInfo.Select(sideChainBlockData => sideChainBlockData.TransactionStatusMerkleTreeRoot)); return(binaryMerkleTree.Root); }
public async Task PrepareExtraDataForNextMiningAsync_Test() { var sideChainId = 123; var sideChainBlockInfoCache = new List <SideChainBlockData>(); var cachingCount = 5; for (int i = 0; i < cachingCount + CrossChainConstants.DefaultBlockCacheEntityCount; i++) { sideChainBlockInfoCache.Add(new SideChainBlockData() { ChainId = sideChainId, Height = (i + 1), TransactionStatusMerkleTreeRoot = HashHelper.ComputeFrom((sideChainId + 1).ToString()) }); } var crossChainBlockData = new CrossChainBlockData { SideChainBlockDataList = { sideChainBlockInfoCache } }; _crossChainTestHelper.AddFakePendingCrossChainIndexingProposal(sideChainId, CreatePendingChainIndexingProposalStatus(SampleAddress.AddressList[0], HashHelper.ComputeFrom("ProposalId"), crossChainBlockData) ); var res = await _crossChainIndexingDataService.PrepareExtraDataForNextMiningAsync(Hash.Empty, 1); var crossChainExtraData = CrossChainExtraData.Parser.ParseFrom(res); var expectedMerkleTreeRoot = BinaryMerkleTree .FromLeafNodes(sideChainBlockInfoCache.Select(s => s.TransactionStatusMerkleTreeRoot)).Root; Assert.Equal(expectedMerkleTreeRoot, crossChainExtraData.TransactionStatusMerkleTreeRoot); Assert.Equal(res, crossChainBlockData.ExtractCrossChainExtraDataFromCrossChainBlockData()); }
private Hash ComputeRootWithMultiHash(IEnumerable <Hash> nodes) { var binaryMerkleTree = new BinaryMerkleTree(); binaryMerkleTree.AddNodes(nodes); return(binaryMerkleTree.ComputeRootHash()); }
public void MerklePathTest2LeafNodes() { var hashes = CreateLeaves(new[] { "a", "e" }); var tree = BinaryMerkleTree.FromLeafNodes(hashes); // test invalid index Assert.Throws <InvalidOperationException>(() => tree.GenerateMerklePath(2)); // test "a" var path = tree.GenerateMerklePath(0); Assert.NotNull(path); Assert.True(1 == path.MerklePathNodes.Count); var realPath1 = GenerateMerklePath(new[] { 1 }, tree.Nodes); Assert.Equal(realPath1, path); // test "e" path = tree.GenerateMerklePath(1); Assert.NotNull(path); Assert.True(1 == path.MerklePathNodes.Count); var realPath2 = GenerateMerklePath(new[] { 0 }, tree.Nodes); Assert.Equal(realPath2, path); }
public async Task Execute_Block_NonCancellable() { var blockHeader = new BlockHeader { Height = 2, PreviousBlockHash = Hash.Empty, Time = DateTime.UtcNow.ToTimestamp() }; var txs = BuildTransactions(5); var block = await _blockExecutingService.ExecuteBlockAsync(blockHeader, txs); var allTxIds = txs.Select(x => x.GetHash()).ToList(); block.Body.TransactionsCount.ShouldBe(txs.Count); var binaryMerkleTree = new BinaryMerkleTree(); binaryMerkleTree.AddNodes(allTxIds); var merkleTreeRoot = binaryMerkleTree.ComputeRootHash(); block.Header.MerkleTreeRootOfTransactions.ShouldBe(merkleTreeRoot); block.Body.Transactions.ShouldBe(allTxIds); block.Body.TransactionList.ShouldBe(txs); }
public async Task <ByteString> GetExtraDataForFillingBlockHeaderAsync(BlockHeader blockHeader) { if (blockHeader.Height == Constants.GenesisBlockHeight) { return(ByteString.Empty); } var newCrossChainBlockData = await _crossChainIndexingDataService.GetCrossChainBlockDataForNextMiningAsync(blockHeader.PreviousBlockHash, blockHeader.Height - 1); if (newCrossChainBlockData == null || newCrossChainBlockData.SideChainBlockData.Count == 0) { return(ByteString.Empty); } var txRootHashList = newCrossChainBlockData.SideChainBlockData.Select(scb => scb.TransactionStatusMerkleTreeRoot).ToList(); var calculatedSideChainTransactionsRoot = BinaryMerkleTree.FromLeafNodes(txRootHashList).Root; Logger.LogTrace("Cross chain extra data generated."); return(new CrossChainExtraData { TransactionStatusMerkleTreeRoot = calculatedSideChainTransactionsRoot } .ToByteString()); }
public void MerkleProofTest_MultiLeaves() { string hex1 = "5a7d71da020cae179a0dfe82bd3c967e1573377578f4cc87bc21f74f2556c0ef"; var hash1 = CreateLeafFromHex(hex1); string hex2 = "a28bf94d0491a234d1e99abc62ed344eb55bb11aeecacc35c1b75bfa85c8983f"; var hash2 = CreateLeafFromHex(hex2); string hex3 = "bf6ae8809d017f07b27ad1620839c6503666fb55f7fe7ac70881e8864ce5a3ff"; var hash3 = CreateLeafFromHex(hex3); string hex4 = "bac4adcf8066921237320cdcddb721f5ba5d34065b9c54fe7f9893d8dfe52f17"; var hash4 = CreateLeafFromHex(hex4); string hex5 = "bac4adcf8066921237320cdcddb721f5ba5d34065b9c54fe7f9893d8dfe52f17"; var hash5 = CreateLeafFromHex(hex5); var tree = BinaryMerkleTree.FromLeafNodes(new[] { hash1, hash2, hash3, hash4, hash5 }); //See if the hash of merkle tree is equal to the element’s hash. var root = tree.Root; var path = tree.GenerateMerklePath(4); var calculatedRoot = path.ComputeRootWithLeafNode(hash5); //Assert.Contains(hash3, path.Path); Assert.Equal(root, calculatedRoot); }
public void MerklePathTest2LeafNodes() { var hashes = CreateLeaves(new[] { "a", "e" }); var tree = new BinaryMerkleTree(); tree.AddNodes(hashes); var path = tree.GenerateMerklePath(0); Assert.Null(path); tree.ComputeRootHash(); // test invalid index path = tree.GenerateMerklePath(2); Assert.Null(path); // test "a" path = tree.GenerateMerklePath(0); Assert.NotNull(path); Assert.True(1 == path.Path.Count); var realPath = new List <Hash> { tree.Nodes[1] }; Assert.Equal(realPath, path.Path.ToList()); // test "e" path = tree.GenerateMerklePath(1); Assert.NotNull(path); Assert.True(1 == path.Path.Count); realPath = new List <Hash> { tree.Nodes[0] }; Assert.Equal(realPath, path.Path.ToList()); }
public async Task CrossChain_Verification() { int parentChainId = 123; long lockedToken = 10; var sideChainId = await InitAndCreateSideChain(parentChainId, lockedToken); var txId = Hash.FromString("sideChainBlockHash"); var binaryMerkleTree = new BinaryMerkleTree(); var fakeHash1 = Hash.FromString("fake1"); var fakeHash2 = Hash.FromString("fake2"); var rawBytes = txId.DumpByteArray().Concat(EncodingHelper.GetBytesFromUtf8String(TransactionResultStatus.Mined.ToString())) .ToArray(); var hash = Hash.FromRawBytes(rawBytes); binaryMerkleTree.AddNodes(new[] { hash, fakeHash1, fakeHash2 }); var merkleTreeRoot = binaryMerkleTree.ComputeRootHash(); var merklePath = binaryMerkleTree.GenerateMerklePath(0); var parentChainHeight = 1; Hash fakeTransactionStatusMerkleRoot = Hash.FromString("TransactionStatusMerkleRoot"); var parentChainBlockData = new ParentChainBlockData { Root = new ParentChainBlockRootInfo { ParentChainHeight = parentChainHeight, ParentChainId = parentChainId, CrossChainExtraData = new CrossChainExtraData { SideChainTransactionsRoot = merkleTreeRoot }, TransactionStatusMerkleRoot = fakeTransactionStatusMerkleRoot } }; var crossChainBlockData = new CrossChainBlockData { ParentChainBlockData = { parentChainBlockData } }; var indexingTx = await GenerateTransactionAsync(CrossChainContractAddress, CrossChainConstants.CrossChainIndexingMethodName, null, crossChainBlockData); var block = await MineAsync(new List <Transaction> { indexingTx }); var verificationInput = new VerifyTransactionInput() { TransactionId = txId, ParentChainHeight = parentChainHeight }; verificationInput.Path.AddRange(merklePath.Path); var txRes = await ExecuteContractWithMiningAsync( CrossChainContractAddress, nameof(CrossChainContract.VerifyTransaction), verificationInput); var verified = BoolValue.Parser.ParseFrom(txRes.ReturnValue).Value; Assert.True(verified); }
/// <summary> /// Get the merkle path of a transaction. /// </summary> /// <param name="transactionId"></param> /// <returns></returns> public async Task <MerklePathDto> GetMerklePathByTransactionIdAsync(string transactionId) { Hash transactionIdHash; try { transactionIdHash = Hash.LoadFromHex(transactionId); } catch { throw new UserFriendlyException(Error.Message[Error.InvalidTransactionId], Error.InvalidTransactionId.ToString()); } var transactionResult = await GetMinedTransactionResultAsync(transactionIdHash); var blockHash = transactionResult.BlockHash; var blockInfo = await _blockchainService.GetBlockByHashAsync(blockHash); var transactionIds = blockInfo.Body.TransactionIds; var index = transactionIds.IndexOf(transactionIdHash); if (index == -1) { throw new UserFriendlyException(Error.Message[Error.NotFound], Error.NotFound.ToString()); } var leafNodes = await GetLeafNodesAsync(blockInfo.TransactionIds); var binaryMerkleTree = BinaryMerkleTree.FromLeafNodes(leafNodes); var path = binaryMerkleTree.GenerateMerklePath(index); var merklePath = _objectMapper.Map <MerklePath, MerklePathDto>(path); return(merklePath); }
public async Task <ByteString> GetExtraDataForFillingBlockHeaderAsync(BlockHeader blockHeader) { if (blockHeader.Height == KernelConstants.GenesisBlockHeight) { return(ByteString.Empty); } //Logger.LogTrace($"Get new cross chain data with hash {blockHeader.PreviousBlockHash}, height {blockHeader.Height - 1}"); var newCrossChainBlockData = await _crossChainDataProvider.GetCrossChainBlockDataForNextMiningAsync(blockHeader.PreviousBlockHash, blockHeader.Height - 1); if (newCrossChainBlockData == null || newCrossChainBlockData.SideChainBlockData.Count == 0) { return(ByteString.Empty); } var txRootHashList = newCrossChainBlockData.SideChainBlockData.Select(scb => scb.TransactionMerkleTreeRoot); var calculatedSideChainTransactionsRoot = new BinaryMerkleTree().AddNodes(txRootHashList).ComputeRootHash(); return(new CrossChainExtraData { SideChainTransactionsRoot = calculatedSideChainTransactionsRoot } .ToByteString()); }
public void MerkleProofTest_MultiLeaves() { var tree = new BinaryMerkleTree(); string hex1 = "5a7d71da020cae179a0dfe82bd3c967e1573377578f4cc87bc21f74f2556c0ef"; var hash1 = CreateLeafFromHex(hex1); string hex2 = "a28bf94d0491a234d1e99abc62ed344eb55bb11aeecacc35c1b75bfa85c8983f"; var hash2 = CreateLeafFromHex(hex2); string hex3 = "bf6ae8809d017f07b27ad1620839c6503666fb55f7fe7ac70881e8864ce5a3ff"; var hash3 = CreateLeafFromHex(hex3); string hex4 = "bac4adcf8066921237320cdcddb721f5ba5d34065b9c54fe7f9893d8dfe52f17"; var hash4 = CreateLeafFromHex(hex4); string hex5 = "bac4adcf8066921237320cdcddb721f5ba5d34065b9c54fe7f9893d8dfe52f17"; var hash5 = Hash.FromRawBytes(ByteArrayHelpers.FromHexString(hex5) .Concat(Encoding.UTF8.GetBytes(TransactionResultStatus.Mined.ToString())).ToArray()); tree.AddNodes(new [] { hash1, hash2, hash3, hash4, hash5 }); //See if the hash of merkle tree is equal to the element’s hash. var root = tree.ComputeRootHash(); var path = tree.GenerateMerklePath(4); var calculatedRoot = path.ComputeRootWith(hash5); //Assert.Contains(hash3, path.Path); Assert.Equal(root, calculatedRoot); }
private Dictionary <long, MerklePath> GetEnumerableMerklePath(IList <SideChainBlockData> indexedSideChainBlockDataResult, int sideChainId) { var binaryMerkleTree = BinaryMerkleTree.FromLeafNodes( indexedSideChainBlockDataResult.Select(sideChainBlockData => sideChainBlockData.TransactionStatusMerkleTreeRoot)); // This is to tell side chain the merkle path for one side chain block, // which could be removed with subsequent improvement. var res = new Dictionary <long, MerklePath>(); for (var i = 0; i < indexedSideChainBlockDataResult.Count; i++) { var info = indexedSideChainBlockDataResult[i]; if (!info.ChainId.Equals(sideChainId)) { continue; } var merklePath = binaryMerkleTree.GenerateMerklePath(i); res.Add(info.Height, merklePath); } return(res); }
public async Task Execute_Block_Cancellable() { var blockHeader = _kernelTestHelper.GenerateBlock(1, Hash.Empty).Header; var nonCancellableTxs = BuildTransactions(5); var cancellableTxs = BuildTransactions(5); var cancelToken = new CancellationTokenSource(); cancelToken.Cancel(); var block = await _blockExecutingService.ExecuteBlockAsync(blockHeader, nonCancellableTxs, cancellableTxs, cancelToken.Token); var allTxIds = nonCancellableTxs.Select(x => x.GetHash()).ToList(); allTxIds.Add(cancellableTxs[0].GetHash()); allTxIds.Add(cancellableTxs[1].GetHash()); allTxIds.Add(cancellableTxs[2].GetHash()); var allTxs = new List <Transaction>(); allTxs.AddRange(nonCancellableTxs); allTxs.Add(cancellableTxs[0]); allTxs.Add(cancellableTxs[1]); allTxs.Add(cancellableTxs[2]); block.Body.TransactionsCount.ShouldBe(allTxs.Count); var binaryMerkleTree = BinaryMerkleTree.FromLeafNodes(allTxIds); var merkleTreeRoot = binaryMerkleTree.Root; block.Header.MerkleTreeRootOfTransactions.ShouldBe(merkleTreeRoot); block.Body.TransactionIds.ShouldBe(allTxIds); }
private bool ValidateBlockExtraDataAsync(CrossChainBlockData crossChainBlockData, CrossChainExtraData extraData) { var txRootHashList = crossChainBlockData.SideChainBlockData.Select(scb => scb.TransactionStatusMerkleTreeRoot).ToList(); var calculatedSideChainTransactionsRoot = BinaryMerkleTree.FromLeafNodes(txRootHashList).Root; return(calculatedSideChainTransactionsRoot.Equals(extraData.TransactionStatusMerkleTreeRoot)); }
public void MerkleNodesCountTest(int leafCount, int expectCount) { var hashes = CreateLeaves(leafCount); var tree = BinaryMerkleTree.FromLeafNodes(hashes); var nodesCount = tree.Nodes.Count; Assert.Equal(expectCount, nodesCount); }
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 MerklePathTest(int leafCount, int index) { var hashes = CreateLeaves(leafCount); var tree = BinaryMerkleTree.FromLeafNodes(hashes.ToArray()); var root = tree.Root; var path = tree.GenerateMerklePath(index); var calculatedRoot = path.ComputeRootWithLeafNode(hashes[index]); Assert.Equal(root, calculatedRoot); }
public void SingleNodeTest() { string hex = "5a7d71da020cae179a0dfe82bd3c967e1573377578f4cc87bc21f74f2556c0ef"; var tree = BinaryMerkleTree.FromLeafNodes(new[] { CreateLeafFromHex(hex) }); //See if the hash of merkle tree is equal to the element’s hash. var root = tree.Root; var expected = GetHashFromHexString(hex, hex); Assert.Equal(expected, root); }
/// <summary> /// Calculate the <see cref="BinaryMerkleTree.Root"/> with path and provided leaf. /// </summary> /// <param name="merklePath"></param> /// <param name="leaf"></param> /// <returns></returns> public static Hash ComputeRootWith(this MerklePath merklePath, Hash leaf) { Hash hash = leaf.Clone(); foreach (var node in merklePath.Path) { hash = BinaryMerkleTree.CalculateRootFromMultiHash(new[] { hash, node }); } return(hash); }
private Hash GetHashFromStrings(params string[] strings) { var hash = Hash.FromString(strings[0]); foreach (var s in strings.Skip(1)) { hash = BinaryMerkleTree.CalculateRootFromMultiHash(new [] { hash, Hash.FromString(s) }); } return(hash); }
public void MerklePathTest(int leaveCount, int index) { var hashes = CreateLeaves(leaveCount); var bmt = new BinaryMerkleTree(); bmt.AddNodes(hashes); var root = bmt.ComputeRootHash(); var path = bmt.GenerateMerklePath(index); var calculatedRoot = path.ComputeRootWith(hashes[index]); Assert.Equal(root, calculatedRoot); }
public void MerkleProofTest() { string hex = "5a7d71da020cae179a0dfe82bd3c967e1573377578f4cc87bc21f74f2556c0ef"; var leaf = CreateLeafFromHex(hex); var tree = BinaryMerkleTree.FromLeafNodes(new[] { leaf }); //See if the hash of merkle tree is equal to the element’s hash. var root = tree.Root; var path = tree.GenerateMerklePath(0); var calculatedRoot = path.ComputeRootWithLeafNode(leaf); Assert.Equal(root, calculatedRoot); }
private Hash CalculateTransactionStatusMerkleTreeRoot(List <ExecutionReturnSet> blockExecutionReturnSet) { var executionReturnSet = blockExecutionReturnSet.Select(executionReturn => (executionReturn.TransactionId, executionReturn.Status)); var nodes = new List <Hash>(); foreach (var(transactionId, status) in executionReturnSet) { nodes.Add(GetHashCombiningTransactionAndStatus(transactionId, status)); } return(BinaryMerkleTree.FromLeafNodes(nodes).Root); }
public async Task CrossChain_MerklePath() { int parentChainId = 123; long lockedToken = 10; long parentChainHeightOfCreation = 10; var sideChainId = await InitAndCreateSideChainAsync(parentChainHeightOfCreation, parentChainId, lockedToken); var transactionId = Hash.FromString("sideChainBlockHash"); var fakeHash1 = Hash.FromString("fake1"); var fakeHash2 = Hash.FromString("fake2"); var binaryMerkleTree = BinaryMerkleTree.FromLeafNodes(new[] { transactionId, fakeHash1, fakeHash2 }); var merkleTreeRoot = binaryMerkleTree.Root; var merklePath = binaryMerkleTree.GenerateMerklePath(0); Hash fakeTransactionStatusMerkleRoot = Hash.FromString("TransactionStatusMerkleRoot"); var parentChainBlockData = CreateParentChainBlockData(parentChainHeightOfCreation, parentChainId, fakeTransactionStatusMerkleRoot); long sideChainHeight = 1; parentChainBlockData.IndexedMerklePath.Add(sideChainHeight, merklePath); var crossChainBlockData = new CrossChainBlockData { ParentChainBlockData = { parentChainBlockData } }; var indexingTx = await GenerateTransactionAsync(CrossChainContractAddress, CrossChainConstants.CrossChainIndexingMethodName, null, crossChainBlockData); var block = await MineAsync(new List <Transaction> { indexingTx }); var crossChainMerkleProofContext = CrossChainMerkleProofContext.Parser.ParseFrom( await CallContractMethodAsync(CrossChainContractAddress, nameof(CrossChainContractContainer.CrossChainContractStub .GetBoundParentChainHeightAndMerklePathByHeight), new SInt64Value() { Value = sideChainHeight })); Assert.Equal(merklePath.ToByteString(), crossChainMerkleProofContext.MerklePathForParentChainRoot.ToByteString()); var calculatedRoot = crossChainMerkleProofContext.MerklePathForParentChainRoot .ComputeRootWithLeafNode(transactionId); Assert.Equal(merkleTreeRoot, calculatedRoot); }
public void SingleNodeTest() { var tree = new BinaryMerkleTree(); string hex = "5a7d71da020cae179a0dfe82bd3c967e1573377578f4cc87bc21f74f2556c0ef"; tree.AddNode(CreateLeafFromHex(hex)); //See if the hash of merkle tree is equal to the element’s hash. var root = tree.ComputeRootHash(); var expected = GetHashFromHexString(hex, hex); Assert.Equal(expected, root); }
public static ByteString ExtractCrossChainExtraDataFromCrossChainBlockData( this IndexedSideChainBlockData indexedSideChainBlockData) { var txRootHashList = indexedSideChainBlockData.SideChainBlockDataList .Select(scb => scb.TransactionStatusMerkleTreeRoot).ToList(); var calculatedSideChainTransactionsRoot = BinaryMerkleTree.FromLeafNodes(txRootHashList).Root; return(new CrossChainExtraData { TransactionStatusMerkleTreeRoot = calculatedSideChainTransactionsRoot } .ToByteString()); }
public async Task CrossChain_MerklePath() { int parentChainId = 123; long lockedToken = 10; var sideChainId = await InitAndCreateSideChain(parentChainId, lockedToken); var txHash = Hash.FromString("sideChainBlockHash"); var binaryMerkleTree = new BinaryMerkleTree(); var fakeHash1 = Hash.FromString("fake1"); var fakeHash2 = Hash.FromString("fake2"); binaryMerkleTree.AddNodes(new[] { txHash, fakeHash1, fakeHash2 }); var merkleTreeRoot = binaryMerkleTree.ComputeRootHash(); var merklePath = binaryMerkleTree.GenerateMerklePath(0); Hash fakeTransactionStatusMerkleRoot = Hash.FromString("TransactionStatusMerkleRoot"); var parentChainBlockData = new ParentChainBlockData { Root = new ParentChainBlockRootInfo { ParentChainHeight = 1, ParentChainId = parentChainId, TransactionStatusMerkleRoot = fakeTransactionStatusMerkleRoot } }; long sideChainHeight = 1; parentChainBlockData.IndexedMerklePath.Add(sideChainHeight, merklePath); var crossChainBlockData = new CrossChainBlockData { ParentChainBlockData = { parentChainBlockData } }; var indexingTx = await GenerateTransactionAsync(CrossChainContractAddress, CrossChainConstants.CrossChainIndexingMethodName, null, crossChainBlockData); var block = await MineAsync(new List <Transaction> { indexingTx }); var crossChainMerkleProofContext = CrossChainMerkleProofContext.Parser.ParseFrom(await CallContractMethodAsync(CrossChainContractAddress, nameof(CrossChainContract.GetBoundParentChainHeightAndMerklePathByHeight), new SInt64Value() { Value = sideChainHeight })); Assert.Equal(merklePath, crossChainMerkleProofContext.MerklePathForParentChainRoot); Assert.Equal(merkleTreeRoot, crossChainMerkleProofContext.MerklePathForParentChainRoot.ComputeRootWith(txHash)); }