/// <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 = HashHelper.HexStringToHash(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 = new MerklePathDto { MerklePathNodes = new List <MerklePathNodeDto>() }; foreach (var node in path.MerklePathNodes) { merklePath.MerklePathNodes.Add(new MerklePathNodeDto { Hash = node.Hash.ToHex(), IsLeftChildNode = node.IsLeftChildNode }); } return(merklePath); }
/// <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 = HashHelper.HexStringToHash(transactionId); } catch { throw new UserFriendlyException(Error.Message[Error.InvalidTransactionId], Error.InvalidTransactionId.ToString()); } var transactionResult = await GetTransactionResultAsync(transactionIdHash); switch (transactionResult.Status) { case TransactionResultStatus.Mined: { var block = await _blockchainService.GetBlockAtHeightAsync(transactionResult.BlockNumber); transactionResult.BlockHash = block.GetHash(); break; } case TransactionResultStatus.Failed: throw new UserFriendlyException(Error.Message[Error.NotFound], Error.NotFound.ToString()); case TransactionResultStatus.NotExisted: throw new UserFriendlyException(Error.Message[Error.NotFound], Error.NotFound.ToString()); } 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 transactionResultList = new List <TransactionResult>(); foreach (var item in blockInfo.TransactionIds) { var result = await GetTransactionResultAsync(item); transactionResultList.Add(result); } var transactionResultSet = transactionResultList.Select(txResult => (txResult.TransactionId, txResult.Status)); var leafNodes = new List <Hash>(); foreach (var(txId, status) in transactionResultSet) { leafNodes.Add(GetHashCombiningTransactionAndStatus(txId, status)); } var binaryMerkleTree = BinaryMerkleTree.FromLeafNodes(leafNodes); var path = binaryMerkleTree.GenerateMerklePath(index); var merklePath = new MerklePathDto { MerklePathNodes = new List <MerklePathNodeDto>() }; foreach (var node in path.MerklePathNodes) { merklePath.MerklePathNodes.Add(new MerklePathNodeDto { Hash = node.Hash.ToHex(), IsLeftChildNode = node.IsLeftChildNode }); } return(merklePath); }