diff --git a/src/Features/Blockcore.Features.BlockStore/Controllers/BlockStoreClient.cs b/src/Features/Blockcore.Features.BlockStore/Api/BlockStoreClient.cs
similarity index 94%
rename from src/Features/Blockcore.Features.BlockStore/Controllers/BlockStoreClient.cs
rename to src/Features/Blockcore.Features.BlockStore/Api/BlockStoreClient.cs
index 86348d372..1caa32286 100644
--- a/src/Features/Blockcore.Features.BlockStore/Controllers/BlockStoreClient.cs
+++ b/src/Features/Blockcore.Features.BlockStore/Api/BlockStoreClient.cs
@@ -4,9 +4,11 @@
using System.Threading.Tasks;
using Blockcore.Controllers;
using Blockcore.Controllers.Models;
+using Blockcore.Features.BlockStore.Api.Contollers;
+using Blockcore.Features.BlockStore.Api.Models;
using Microsoft.Extensions.Logging;
-namespace Blockcore.Features.BlockStore.Controllers
+namespace Blockcore.Features.BlockStore.Api
{
/// Rest client for .
public interface IBlockStoreClient : IRestApiClientBase
diff --git a/src/Features/Blockcore.Features.BlockStore/Controllers/BlockStoreController.cs b/src/Features/Blockcore.Features.BlockStore/Api/Controllers/BlockStoreController.cs
similarity index 95%
rename from src/Features/Blockcore.Features.BlockStore/Controllers/BlockStoreController.cs
rename to src/Features/Blockcore.Features.BlockStore/Api/Controllers/BlockStoreController.cs
index e4f053d92..705f7544b 100644
--- a/src/Features/Blockcore.Features.BlockStore/Controllers/BlockStoreController.cs
+++ b/src/Features/Blockcore.Features.BlockStore/Api/Controllers/BlockStoreController.cs
@@ -3,6 +3,7 @@
using Blockcore.Base;
using Blockcore.Controllers.Models;
using Blockcore.Features.BlockStore.AddressIndexing;
+using Blockcore.Features.BlockStore.Api.Models;
using Blockcore.Features.BlockStore.Models;
using Blockcore.Interfaces;
using Blockcore.Utilities;
@@ -12,16 +13,8 @@
using Microsoft.Extensions.Logging;
using NBitcoin;
-namespace Blockcore.Features.BlockStore.Controllers
+namespace Blockcore.Features.BlockStore.Api.Contollers
{
- public static class BlockStoreRouteEndPoint
- {
- public const string GetAddressesBalances = "getaddressesbalances";
- public const string GetVerboseAddressesBalances = "getverboseaddressesbalances";
- public const string GetAddressIndexerTip = "addressindexertip";
- public const string GetBlock = "block";
- public const string GetBlockCount = "GetBlockCount";
- }
/// Controller providing operations on a blockstore.
[ApiController]
diff --git a/src/Features/Blockcore.Features.BlockStore/Api/Controllers/BlockStoreRPCController.cs b/src/Features/Blockcore.Features.BlockStore/Api/Controllers/BlockStoreRPCController.cs
new file mode 100644
index 000000000..33ca4aa90
--- /dev/null
+++ b/src/Features/Blockcore.Features.BlockStore/Api/Controllers/BlockStoreRPCController.cs
@@ -0,0 +1,107 @@
+using System.Collections.Generic;
+using Blockcore.Consensus;
+using Blockcore.Controllers;
+using Blockcore.Features.RPC;
+using Blockcore.Features.RPC.Exceptions;
+using Blockcore.Interfaces;
+using Blockcore.Primitives;
+using Microsoft.AspNetCore.Mvc;
+using NBitcoin;
+
+namespace Blockcore.Features.BlockStore.Api.Controllers
+{
+ ///
+ /// Controller providing RPC operations on a watch-only wallet.
+ ///
+ public class BlockStoreRPCController : FeatureController
+ {
+ /// Consensus manager class.
+ private readonly IConsensusManager consensusManager;
+
+ /// Thread safe access to the best chain of block headers from genesis.
+ private readonly ChainIndexer chainIndexer;
+
+ /// Provides access to the block store database.
+ private readonly IBlockStore blockStore;
+
+ ///
+ public BlockStoreRPCController(
+ IFullNode fullNode,
+ IConsensusManager consensusManager,
+ ChainIndexer chainIndexer,
+ Network network,
+ IBlockStore blockStore) : base(fullNode: fullNode, consensusManager: consensusManager, chainIndexer: chainIndexer, network: network)
+ {
+ this.consensusManager = consensusManager;
+ this.chainIndexer = chainIndexer;
+ this.blockStore = blockStore;
+ }
+
+ ///
+ /// By default this function only works when there is an unspent output in the utxo for this transaction.
+ /// To make it work, you need to maintain a transaction index, using the -txindex command line option.
+ ///
+ /// The txids to filter
+ /// If specified, looks for txid in the block with this hash
+ ///
+ [ActionName("gettxoutproof")]
+ [ActionDescription("Checks if transactions are within block. Returns proof of transaction inclusion (raw MerkleBlock).")]
+ public MerkleBlock GetTxOutProof(string[] txids, string blockhash = "")
+ {
+ List transactionIds = new List();
+ ChainedHeaderBlock block = null;
+ foreach (var txString in txids)
+ {
+ transactionIds.Add(uint256.Parse(txString));
+ }
+
+ if (!string.IsNullOrEmpty(blockhash))
+ {
+ // Loop through txids and veryify that the transaction is in the block.
+ foreach (var transactionId in transactionIds)
+ {
+ var hashBlock = uint256.Parse(blockhash);
+ ChainedHeader chainedHeader = this.GetTransactionBlock(transactionId);
+ if (chainedHeader.HashBlock != hashBlock)
+ {
+ throw new RPCServerException(RPCErrorCode.RPC_INVALID_ADDRESS_OR_KEY, "Not all transactions found in specified or retrieved block");
+ }
+ if (block == null && chainedHeader.BlockDataAvailability == BlockDataAvailabilityState.BlockAvailable) // Only get the block once.
+ {
+ block = this.consensusManager.GetBlockData(chainedHeader.HashBlock);
+ }
+ }
+ }
+ else
+ {
+ // Loop through txids and try to find which block they're in. Exit loop once a block is found.
+ foreach (var transactionId in transactionIds)
+ {
+ ChainedHeader chainedHeader = this.GetTransactionBlock(transactionId);
+ if (chainedHeader.BlockDataAvailability == BlockDataAvailabilityState.BlockAvailable)
+ {
+ block = this.consensusManager.GetBlockData(chainedHeader.HashBlock);
+ break;
+ }
+ }
+ }
+ if (block == null)
+ {
+ throw new RPCServerException(RPCErrorCode.RPC_INVALID_ADDRESS_OR_KEY, "Block not found");
+ }
+ var result = new MerkleBlock(block.Block, transactionIds.ToArray());
+ return result;
+ }
+
+ internal ChainedHeader GetTransactionBlock(uint256 trxid)
+ {
+ ChainedHeader block = null;
+ uint256 blockid = this.blockStore?.GetBlockIdByTransactionId(trxid);
+ if (blockid != null)
+ {
+ block = this.chainIndexer?.GetHeader(blockid);
+ }
+ return block;
+ }
+ }
+}
diff --git a/src/Features/Blockcore.Features.BlockStore/Api/Models/BlockStoreRouteEndPoint.cs b/src/Features/Blockcore.Features.BlockStore/Api/Models/BlockStoreRouteEndPoint.cs
new file mode 100644
index 000000000..c0a1a7614
--- /dev/null
+++ b/src/Features/Blockcore.Features.BlockStore/Api/Models/BlockStoreRouteEndPoint.cs
@@ -0,0 +1,11 @@
+namespace Blockcore.Features.BlockStore.Api.Models
+{
+ public static class BlockStoreRouteEndPoint
+ {
+ public const string GetAddressesBalances = "getaddressesbalances";
+ public const string GetVerboseAddressesBalances = "getverboseaddressesbalances";
+ public const string GetAddressIndexerTip = "addressindexertip";
+ public const string GetBlock = "block";
+ public const string GetBlockCount = "GetBlockCount";
+ }
+}
diff --git a/src/Features/Blockcore.Features.BlockStore/Blockcore.Features.BlockStore.csproj b/src/Features/Blockcore.Features.BlockStore/Blockcore.Features.BlockStore.csproj
index b5489edeb..5cdef4b06 100644
--- a/src/Features/Blockcore.Features.BlockStore/Blockcore.Features.BlockStore.csproj
+++ b/src/Features/Blockcore.Features.BlockStore/Blockcore.Features.BlockStore.csproj
@@ -20,6 +20,7 @@
+
diff --git a/src/Features/Blockcore.Features.RPC/RPCClient.cs b/src/Features/Blockcore.Features.RPC/RPCClient.cs
index e8a6005f4..f498abad0 100644
--- a/src/Features/Blockcore.Features.RPC/RPCClient.cs
+++ b/src/Features/Blockcore.Features.RPC/RPCClient.cs
@@ -85,8 +85,8 @@ blockchain getchaintips
blockchain getdifficulty
blockchain getmempoolinfo
blockchain getrawmempool Yes
- blockchain gettxout Yes
- blockchain gettxoutproof
+ blockchain gettxout Yes
+ blockchain gettxoutproof Yes
blockchain verifytxoutproof
blockchain gettxoutsetinfo
blockchain verifychain
diff --git a/src/Tests/Blockcore.Features.BlockStore.Tests/BlockStoreControllerTests.cs b/src/Tests/Blockcore.Features.BlockStore.Tests/BlockStoreControllerTests.cs
index 66f062f40..2d95e9a22 100644
--- a/src/Tests/Blockcore.Features.BlockStore.Tests/BlockStoreControllerTests.cs
+++ b/src/Tests/Blockcore.Features.BlockStore.Tests/BlockStoreControllerTests.cs
@@ -3,7 +3,7 @@
using Blockcore.Base;
using Blockcore.Controllers.Models;
using Blockcore.Features.BlockStore.AddressIndexing;
-using Blockcore.Features.BlockStore.Controllers;
+using Blockcore.Features.BlockStore.Api.Contollers;
using Blockcore.Features.BlockStore.Models;
using Blockcore.Interfaces;
using Blockcore.Tests.Common;