Skip to content
This repository has been archived by the owner on Aug 16, 2021. It is now read-only.

Can generate blocks through RPC #220

Merged
merged 1 commit into from
Jul 12, 2017
Merged
Show file tree
Hide file tree
Changes from all commits
Commits
File filter

Filter by extension

Filter by extension

Conversations
Failed to load comments.
Loading
Jump to
Jump to file
Failed to load files.
Loading
Diff view
Diff view
4 changes: 3 additions & 1 deletion Stratis.Bitcoin.IntegrationTests/NodeBuilder.cs
Original file line number Diff line number Diff line change
@@ -1,4 +1,5 @@
using NBitcoin;
using Stratis.Bitcoin.Miner;
using NBitcoin.DataEncoders;
using NBitcoin.Protocol;
using NBitcoin.RPC;
Expand Down Expand Up @@ -76,10 +77,11 @@ public static FullNode BuildFullNode(NodeSettings args)
.UseConsensus()
.UseBlockStore()
.UseMempool()
.AddMining()
.UseWallet()
.AddRPC()
.Build();

node.WalletManager.CreateWallet("blabla", "test");
return node;
}

Expand Down
13 changes: 13 additions & 0 deletions Stratis.Bitcoin.IntegrationTests/WalletTests.cs
Original file line number Diff line number Diff line change
Expand Up @@ -77,6 +77,19 @@ public void WalletCanReceiveAndSendCorrectly()

}

[Fact]
public void CanMineBlocks()
{
using(NodeBuilder builder = NodeBuilder.Create())
{
var stratisNodeSync = builder.CreateStratisNode();
builder.StartAll();
var rpc = stratisNodeSync.CreateRPCClient();
rpc.SendCommand(NBitcoin.RPC.RPCOperations.generate, 10);
Assert.Equal(10, rpc.GetBlockCount());
}
}

[Fact]
public void WalletCanReorg()
{
Expand Down
8 changes: 8 additions & 0 deletions Stratis.Bitcoin/Miner/PowMining.cs
Original file line number Diff line number Diff line change
Expand Up @@ -17,6 +17,14 @@ namespace Stratis.Bitcoin.Miner
{
public class ReserveScript
{
public ReserveScript()
{

}
public ReserveScript(Script reserveSfullNodecript)
{
this.reserveSfullNodecript = reserveSfullNodecript;
}
public Script reserveSfullNodecript { get; set; }
}

Expand Down
8 changes: 8 additions & 0 deletions Stratis.Bitcoin/RPC/Controllers/FullNodeController.cs
Original file line number Diff line number Diff line change
Expand Up @@ -4,6 +4,7 @@
using Stratis.Bitcoin.RPC.Models;
using System;
using System.Collections.Generic;
using Microsoft.Extensions.DependencyInjection;
using System.Linq;
using System.Threading.Tasks;
using Stratis.Bitcoin.BlockStore;
Expand Down Expand Up @@ -73,6 +74,13 @@ public async Task<TransactionModel> GetRawTransaction(string txid, int verbose =
return new TransactionBriefModel(trx);
}

[ActionName("getblockcount")]
public int GetBlockCount()
{
var consensusLoop = this.FullNode.Services.ServiceProvider.GetRequiredService<ConsensusLoop>();
Copy link
Contributor

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

You could use the ChainState on this.FullNode

Copy link
Contributor Author

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

I don't have ChainState in IFullNode

return consensusLoop.Tip.Height;
}

[ActionName("getinfo")]
public GetInfoModel GetInfo()
{
Expand Down
72 changes: 72 additions & 0 deletions Stratis.Bitcoin/RPC/Controllers/WalletRPCController.cs
Original file line number Diff line number Diff line change
@@ -0,0 +1,72 @@
using Microsoft.AspNetCore.Mvc;
using Stratis.Bitcoin.Miner;
using System;
using System.Linq;
using System.Collections.Generic;
using System.Text;
using Microsoft.Extensions.DependencyInjection;
using Stratis.Bitcoin.Wallet;
using NBitcoin;

namespace Stratis.Bitcoin.RPC.Controllers
{
public class WalletRPCController : BaseRPCController
{
public class UsedWallet
{
public string WalletName
{
get; set;
}
public HdAccount Account
{
get;
set;
}
}
public WalletRPCController(IServiceProvider serviceProvider, IWalletManager walletManager)
Copy link
Contributor

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

FYI PowMining should be in the DI as well (after we fix the registration issue)

Copy link
Contributor Author

@NicolasDorier NicolasDorier Jul 12, 2017

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

This is an optional dependency though, is there better way to express ?

Copy link
Contributor

@dangershony dangershony Jul 12, 2017

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

Ah yes hmmm, not without design changes.

{
this.WalletManager = walletManager;
this.serviceProvider = serviceProvider;
}

IServiceProvider serviceProvider;

public IWalletManager WalletManager
{
get; set;
}

[ActionName("generate")]
public List<uint256> Generate(int nBlock)
{
var mining = serviceProvider.GetRequiredService<PowMining>();
var wallet = GetWallet();
var address = this.WalletManager.GetUnusedAddress(wallet.WalletName, wallet.Account.Name);
return mining.GenerateBlocks(new ReserveScript(address.Pubkey), (ulong)nBlock, int.MaxValue);
}

private UsedWallet GetWallet()
{
var w = this.WalletManager.GetWallets().FirstOrDefault();
if(w == null)
throw new RPCServerException(NBitcoin.RPC.RPCErrorCode.RPC_INVALID_REQUEST, "No wallet found");
var account = this.WalletManager.GetAccounts(w).FirstOrDefault();
return new UsedWallet()
{
Account = account,
WalletName = w
};
}

private string GetAccountName()
{
return this.WalletManager.GetAccounts(GetWalletName()).FirstOrDefault().Name;
}

private string GetWalletName()
{
return this.WalletManager.GetWallets().FirstOrDefault();
}
}
}
19 changes: 19 additions & 0 deletions Stratis.Bitcoin/RPC/RPCMiddleware.cs
Original file line number Diff line number Diff line change
Expand Up @@ -51,11 +51,22 @@ public async Task Invoke(HttpContext httpContext)
JObject response = CreateError(RPCErrorCode.RPC_MISC_ERROR, "Argument error: " + ex.Message);
await httpContext.Response.WriteAsync(response.ToString(Formatting.Indented));
}
else if(ex is RPCServerException)
{
var rpcEx = (RPCServerException)ex;
JObject response = CreateError(rpcEx.ErrorCode, ex.Message);
await httpContext.Response.WriteAsync(response.ToString(Formatting.Indented));
}
else if(httpContext.Response?.StatusCode == 404)
{
JObject response = CreateError(RPCErrorCode.RPC_METHOD_NOT_FOUND, "Method not found");
await httpContext.Response.WriteAsync(response.ToString(Formatting.Indented));
}
else if(IsDependencyFailure(ex))
{
JObject response = CreateError(RPCErrorCode.RPC_METHOD_NOT_FOUND, ex.Message);
await httpContext.Response.WriteAsync(response.ToString(Formatting.Indented));
}
else if(httpContext.Response?.StatusCode == 500 || ex != null)
{
JObject response = CreateError(RPCErrorCode.RPC_INTERNAL_ERROR, "Internal error");
Expand All @@ -64,6 +75,14 @@ public async Task Invoke(HttpContext httpContext)
}
}

private bool IsDependencyFailure(Exception ex)
{
var invalidOp = ex as InvalidOperationException;
if(invalidOp == null)
return false;
return invalidOp.Source.Equals("Microsoft.Extensions.DependencyInjection.Abstractions", StringComparison.Ordinal);
}

private bool Authorized(HttpContext httpContext)
{
if(!this.authorization.IsAuthorized(httpContext.Connection.RemoteIpAddress))
Expand Down
20 changes: 20 additions & 0 deletions Stratis.Bitcoin/RPC/RPCServerException.cs
Original file line number Diff line number Diff line change
@@ -0,0 +1,20 @@
using NBitcoin.RPC;
using System;
using System.Collections.Generic;
using System.Text;

namespace Stratis.Bitcoin.RPC
{
public class RPCServerException : Exception
{
public RPCServerException(RPCErrorCode errorCode, string message) : base(message)
{
this.ErrorCode = errorCode;
}

public RPCErrorCode ErrorCode
{
get; set;
}
}
}
6 changes: 6 additions & 0 deletions Stratis.Bitcoin/RPC/WebHostExtensions.cs
Original file line number Diff line number Diff line change
@@ -1,5 +1,7 @@
using Microsoft.AspNetCore.Hosting;
using Microsoft.Extensions.DependencyInjection;
using Stratis.Bitcoin.Miner;
using Stratis.Bitcoin.Wallet;
using System;
using System.Collections.Generic;
using System.Linq;
Expand All @@ -24,6 +26,10 @@ public static IWebHostBuilder ForFullNode(this IWebHostBuilder hostBuilder, Full
s.AddSingleton(fullNode.BlockStoreManager);
s.AddSingleton(fullNode.MempoolManager);
s.AddSingleton(fullNode.ConnectionManager);
s.AddSingleton(fullNode.Services.ServiceProvider.GetService<IWalletManager>());
var pow = fullNode.Services.ServiceProvider.GetService<PowMining>();
if(pow != null)
s.AddSingleton(pow);
});
return hostBuilder;
}
Expand Down
6 changes: 6 additions & 0 deletions Stratis.Bitcoin/Wallet/IWalletManager.cs
Original file line number Diff line number Diff line change
Expand Up @@ -187,6 +187,12 @@ public interface IWalletManager : IDisposable
/// </summary>
/// <returns></returns>
string GetWalletFileExtension();

/// <summary>
/// Get all the wallets name
/// </summary>
/// <returns></returns>
string[] GetWallets();

/// <summary>
/// Updates the wallet with the height of the last block synced.
Expand Down
2 changes: 2 additions & 0 deletions Stratis.Bitcoin/Wallet/WalletFeature.cs
Original file line number Diff line number Diff line change
Expand Up @@ -5,6 +5,7 @@
using Stratis.Bitcoin.Builder;
using Stratis.Bitcoin.Builder.Feature;
using Stratis.Bitcoin.Wallet.Notifications;
using Stratis.Bitcoin.RPC.Controllers;

namespace Stratis.Bitcoin.Wallet
{
Expand Down Expand Up @@ -57,6 +58,7 @@ public static IFullNodeBuilder UseWallet(this IFullNodeBuilder fullNodeBuilder)
services.AddSingleton<IWalletManager, WalletManager>();
services.AddSingleton<IWalletFeePolicy, WalletFeePolicy>();
services.AddSingleton<WalletController>();
services.AddSingleton<WalletRPCController>();
});
});

Expand Down
5 changes: 5 additions & 0 deletions Stratis.Bitcoin/Wallet/WalletManager.cs
Original file line number Diff line number Diff line change
Expand Up @@ -1051,6 +1051,11 @@ internal void LoadKeysLookup()
this.keysLookup = lookup;
}

public string[] GetWallets()
{
return this.Wallets.Select(w => w.Name).ToArray();
}

/// <summary>
/// Gets a wallet given its name.
/// </summary>
Expand Down