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

Make RPC methods easier to create with binders, improve testing #221

Merged
merged 4 commits 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
2 changes: 1 addition & 1 deletion Stratis.Bitcoin.Common/Stratis.Bitcoin.Common.csproj
Original file line number Diff line number Diff line change
@@ -1,7 +1,7 @@
<Project Sdk="Microsoft.NET.Sdk">

<PropertyGroup>
<TargetFramework>netstandard1.6</TargetFramework>
<TargetFrameworks>net462;netstandard1.6</TargetFrameworks>
</PropertyGroup>

<PropertyGroup Condition="'$(Configuration)|$(Platform)'=='Debug|AnyCPU'">
Expand Down
681 changes: 681 additions & 0 deletions Stratis.Bitcoin.IntegrationTests/Data/test.wallet.json

Large diffs are not rendered by default.

6 changes: 5 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,13 @@ public static FullNode BuildFullNode(NodeSettings args)
.UseConsensus()
.UseBlockStore()
.UseMempool()
.AddMining()
.UseWallet()
.AddRPC()
.Build();

var testWalletPath = Path.Combine(node.DataFolder.WalletPath, "test.wallet.json");
File.Copy("Data/test.wallet.json", testWalletPath);
//node.WalletManager.CreateWallet("blabla", "test");
return node;
}

Expand Down
14 changes: 14 additions & 0 deletions Stratis.Bitcoin.IntegrationTests/Program.cs
Original file line number Diff line number Diff line change
@@ -0,0 +1,14 @@
using System;
using System.Collections.Generic;
using System.Text;

namespace Stratis.Bitcoin.IntegrationTests
{
class Program
{
public static void Main(string[] args)
{
new WalletTests().CanSendToAddress();
}
}
}
Original file line number Diff line number Diff line change
@@ -1,7 +1,11 @@
<Project Sdk="Microsoft.NET.Sdk">

<PropertyGroup Label="Configuration" Condition="'$(Configuration)|$(TargetFramework)|$(Platform)'=='Debug|net462|AnyCPU'">
<OutputType>exe</OutputType>
</PropertyGroup>

<PropertyGroup>
<TargetFramework>netcoreapp1.1</TargetFramework>
<TargetFrameworks>net462;netcoreapp1.1</TargetFrameworks>
<AssemblyName>Stratis.Bitcoin.IntegrationTests</AssemblyName>
<PackageId>Stratis.Bitcoin.IntegrationTests</PackageId>
<GenerateRuntimeConfigurationFiles>true</GenerateRuntimeConfigurationFiles>
Expand All @@ -14,7 +18,8 @@
<GenerateAssemblyProductAttribute>false</GenerateAssemblyProductAttribute>
<GenerateAssemblyCopyrightAttribute>false</GenerateAssemblyCopyrightAttribute>
<GenerateAssemblyVersionAttribute>false</GenerateAssemblyVersionAttribute>
<GenerateAssemblyFileVersionAttribute>false</GenerateAssemblyFileVersionAttribute>
<GenerateAssemblyFileVersionAttribute>false</GenerateAssemblyFileVersionAttribute>
<GenerateProgramFile>false</GenerateProgramFile>
</PropertyGroup>

<PropertyGroup Condition="'$(Configuration)|$(Platform)'=='Debug|AnyCPU'">
Expand All @@ -38,6 +43,9 @@
</ItemGroup>

<ItemGroup>
<None Update="Data\test.wallet.json">
<CopyToOutputDirectory>Always</CopyToOutputDirectory>
</None>
<None Update="xunit.runner.json">
<CopyToOutputDirectory>PreserveNewest</CopyToOutputDirectory>
</None>
Expand Down
28 changes: 28 additions & 0 deletions Stratis.Bitcoin.IntegrationTests/WalletTests.cs
Original file line number Diff line number Diff line change
Expand Up @@ -77,6 +77,34 @@ 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 CanSendToAddress()
{
using(NodeBuilder builder = NodeBuilder.Create())
{
var stratisNodeSync = builder.CreateStratisNode();
builder.StartAll();
var rpc = stratisNodeSync.CreateRPCClient();
rpc.SendCommand(NBitcoin.RPC.RPCOperations.generate, 101);
var address = new Key().PubKey.GetAddress(rpc.Network);
var tx = rpc.SendToAddress(address, Money.Coins(1.0m));
Assert.NotNull(tx);
}
}

[Fact]
public void WalletCanReorg()
{
Expand Down
2 changes: 1 addition & 1 deletion Stratis.Bitcoin.Tests/Stratis.Bitcoin.Tests.csproj
Original file line number Diff line number Diff line change
@@ -1,7 +1,7 @@
<Project Sdk="Microsoft.NET.Sdk">

<PropertyGroup>
<TargetFramework>netcoreapp1.1</TargetFramework>
<TargetFrameworks>net462;netcoreapp1.1</TargetFrameworks>
<AssemblyName>Stratis.Bitcoin.Tests</AssemblyName>
<PackageId>Stratis.Bitcoin.Tests</PackageId>
<GenerateRuntimeConfigurationFiles>true</GenerateRuntimeConfigurationFiles>
Expand Down
6 changes: 3 additions & 3 deletions Stratis.Bitcoin/Consensus/CoinViews/CachedCoinView.cs
Original file line number Diff line number Diff line change
Expand Up @@ -19,7 +19,7 @@ class CacheItem
public TxOut[] OriginalOutputs;
}

private readonly ReaderWriterLock lockobj;
private readonly Stratis.Bitcoin.Utilities.ReaderWriterLock lockobj;
private readonly Dictionary<uint256, CacheItem> unspents;
private uint256 blockHash;
private uint256 innerBlockHash;
Expand All @@ -33,7 +33,7 @@ public CachedCoinView(DBreezeCoinView inner, StakeChainStore stakeChainStore = n
this.inner = inner;
this.stakeChainStore = stakeChainStore;
this.MaxItems = 100000;
this.lockobj = new ReaderWriterLock();
this.lockobj = new Stratis.Bitcoin.Utilities.ReaderWriterLock();
this.unspents = new Dictionary<uint256, CacheItem>();
this.PerformanceCounter = new CachePerformanceCounter();
}
Expand All @@ -49,7 +49,7 @@ public CachedCoinView(InMemoryCoinView inner, StakeChainStore stakeChainStore =
this.inner = inner;
this.stakeChainStore = stakeChainStore;
this.MaxItems = 100000;
this.lockobj = new ReaderWriterLock();
this.lockobj = new Stratis.Bitcoin.Utilities.ReaderWriterLock();
this.unspents = new Dictionary<uint256, CacheItem>();
this.PerformanceCounter = new CachePerformanceCounter();
}
Expand Down
2 changes: 1 addition & 1 deletion Stratis.Bitcoin/MemoryPool/MemPoolCoinView.cs
Original file line number Diff line number Diff line change
Expand Up @@ -31,7 +31,7 @@ public MempoolCoinView(CoinView inner, TxMempool memPool, AsyncLock mempoolSched
public async Task LoadView(Transaction trx)
{
// lookup all ids (duplicate ids are ignored in case a trx spends outputs from the same parent)
var ids = trx.Inputs.Select(n => n.PrevOut.Hash).Distinct().Append(trx.GetHash()).ToList();
var ids = trx.Inputs.Select(n => n.PrevOut.Hash).Distinct().Concat(new[] { trx.GetHash() }).ToList();
var coins = await this.Inner.FetchCoinsAsync(ids.ToArray());
// find coins currently in the mempool
var mempoolcoins = await this.mempoolScheduler.ReadAsync(() =>
Expand Down
9 changes: 9 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 Expand Up @@ -159,6 +167,7 @@ public List<uint256> GenerateBlocks(ReserveScript reserveScript, ulong generate,
// ensure the block is written to disk
ulong retry = 0;
while (++retry < maxTries &&
nHeight != nHeight &&
Copy link
Contributor

Choose a reason for hiding this comment

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

Super duper

Copy link
Contributor Author

Choose a reason for hiding this comment

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

oops lol

!this.blockRepository.ExistAsync(blockResult.ChainedBlock.HashBlock).GetAwaiter().GetResult())
Thread.Sleep(100);

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>();
return consensusLoop.Tip.Height;
}

[ActionName("getinfo")]
public GetInfoModel GetInfo()
{
Expand Down
79 changes: 79 additions & 0 deletions Stratis.Bitcoin/RPC/Controllers/WalletRPCController.cs
Original file line number Diff line number Diff line change
@@ -0,0 +1,79 @@
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)
{
this.WalletManager = walletManager;
this.serviceProvider = serviceProvider;
}

IServiceProvider serviceProvider;

public IWalletManager WalletManager
{
get; set;
}


[ActionName("sendtoaddress")]
public uint256 SendToAddress(BitcoinAddress bitcoinAddress, Money amount)
{
return uint256.Zero;
}

[ActionName("generate")]
public List<uint256> Generate(int nBlock)
{
var mining = this.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();
}
}
}
65 changes: 65 additions & 0 deletions Stratis.Bitcoin/RPC/ModelBinders/DestinationModelBinder.cs
Original file line number Diff line number Diff line change
@@ -0,0 +1,65 @@
using Microsoft.AspNetCore.Mvc.ModelBinding;
using NBitcoin;
using System.Reflection;
using System;
using System.Threading.Tasks;
using Microsoft.AspNetCore.Mvc.Internal;

namespace Stratis.Bitcoin.RPC.ModelBinders
{
public class DestinationModelBinder : IModelBinder, IModelBinderProvider
{
public DestinationModelBinder()
{

}

#region IModelBinder Members

public Task BindModelAsync(ModelBindingContext bindingContext)
{
if(!SupportType(bindingContext.ModelType))
{
return TaskCache.CompletedTask;
}

ValueProviderResult val = bindingContext.ValueProvider.GetValue(
bindingContext.ModelName);
if(val == null)
{
return TaskCache.CompletedTask;
}

string key = val.FirstValue as string;
if(key == null)
{
return TaskCache.CompletedTask;
}

var network = (Network)bindingContext.HttpContext.RequestServices.GetService(typeof(Network));
//TODO: Use var data = Network.Parse(key, network); when NBitcoin is updated to latest version
var data = BitcoinAddress.Create(key, network);
if(!bindingContext.ModelType.IsInstanceOfType(data))
{
throw new FormatException("Invalid destination type");
}
bindingContext.Result = ModelBindingResult.Success(data);
return TaskCache.CompletedTask;
}

private static bool SupportType(Type type)
{
return (typeof(Base58Data).GetTypeInfo().IsAssignableFrom(type) ||
typeof(IDestination).GetTypeInfo().IsAssignableFrom(type));
}

public IModelBinder GetBinder(ModelBinderProviderContext context)
{
if(SupportType(context.Metadata.ModelType))
return this;
return null;
}

#endregion
}
}
43 changes: 43 additions & 0 deletions Stratis.Bitcoin/RPC/ModelBinders/MoneyModelBinder.cs
Original file line number Diff line number Diff line change
@@ -0,0 +1,43 @@
using Microsoft.AspNetCore.Mvc.Internal;
using Microsoft.AspNetCore.Mvc.ModelBinding;
using NBitcoin;
using System;
using System.Collections.Generic;
using System.Linq;
using System.Text;
using System.Threading.Tasks;

namespace Stratis.Bitcoin.RPC.ModelBinders
{
public class MoneyModelBinder : IModelBinder, IModelBinderProvider
{
public Task BindModelAsync(ModelBindingContext bindingContext)
{
if(bindingContext.ModelType != typeof(Money))
{
return TaskCache.CompletedTask;
}

ValueProviderResult val = bindingContext.ValueProvider.GetValue(
bindingContext.ModelName);
if(val == null)
{
return TaskCache.CompletedTask;
}

string key = val.FirstValue as string;
if(key == null)
{
return TaskCache.CompletedTask;
}
return Task.FromResult(Money.Parse(key));
}

public IModelBinder GetBinder(ModelBinderProviderContext context)
{
if(context.Metadata.ModelType == typeof(Money))
return this;
return null;
}
}
}
Loading