Add lightning dependencies to tests and docker-compose

This commit is contained in:
nicolas.dorier 2018-02-23 15:21:42 +09:00
parent 2d1f4e5e0a
commit 200e259b82
15 changed files with 230 additions and 60 deletions

View file

@ -0,0 +1,23 @@
using System;
using System.Collections.Generic;
using System.Text;
using BTCPayServer.Payments.Lightning.CLightning;
using NBitcoin;
namespace BTCPayServer.Tests
{
public class ChargeTester
{
private ServerTester _Parent;
public ChargeTester(ServerTester serverTester, string environmentName, string defaultValue, string defaultHost, Network network)
{
this._Parent = serverTester;
var url = serverTester.GetEnvironment(environmentName, defaultValue);
Client = new ChargeClient(new Uri(url), network);
P2PHost = _Parent.GetEnvironment(environmentName + "_HOST", defaultHost);
}
public ChargeClient Client { get; set; }
public string P2PHost { get; }
}
}

View file

@ -2,17 +2,18 @@
using System.Collections.Generic;
using System.Text;
using System.Threading.Tasks;
using BTCPayServer.Eclair;
using BTCPayServer.Payments.Lightning.Eclair;
using NBitcoin;
namespace BTCPayServer.Tests
{
public class EclairTester
{
ServerTester parent;
public EclairTester(ServerTester parent, string environmentName, string defaultRPC, string defaultHost)
public EclairTester(ServerTester parent, string environmentName, string defaultRPC, string defaultHost, Network network)
{
this.parent = parent;
//RPC = new EclairRPCClient(new Uri(parent.GetEnvironment(environmentName, defaultRPC)), parent.Network);
RPC = new EclairRPCClient(new Uri(parent.GetEnvironment(environmentName, defaultRPC)), network);
P2PHost = parent.GetEnvironment(environmentName + "_HOST", defaultHost);
}

View file

@ -17,7 +17,7 @@ using System.Runtime.CompilerServices;
using System.Text;
using System.Threading.Tasks;
using System.Threading;
using BTCPayServer.Eclair;
using BTCPayServer.Payments.Lightning.Eclair;
using System.Globalization;
namespace BTCPayServer.Tests
@ -65,8 +65,9 @@ namespace BTCPayServer.Tests
PayTester.HostName = GetEnvironment("TESTS_HOSTNAME", "127.0.0.1");
PayTester.Start();
MerchantEclair = new EclairTester(this, "TEST_ECLAIR1", "http://127.0.0.1:30992/", "eclair1");
CustomerEclair = new EclairTester(this, "TEST_ECLAIR2", "http://127.0.0.1:30993/", "eclair2");
var btc = NetworkProvider.GetNetwork("BTC").NBitcoinNetwork;
CustomerEclair = new EclairTester(this, "TEST_ECLAIR", "http://eclair-cli:gpwefwmmewci@127.0.0.1:30992/", "eclair", btc);
MerchantCharge = new ChargeTester(this, "TEST_CHARGE", "http://api-token:foiewnccewuify@127.0.0.1:54938/", "lightning-charged", btc);
}
@ -83,12 +84,13 @@ namespace BTCPayServer.Tests
// Activate segwit
var blockCount = ExplorerNode.GetBlockCountAsync();
// Fetch node info, but that in cache
var merchant = MerchantEclair.GetNodeInfoAsync();
var merchantInfo = MerchantCharge.Client.GetInfoAsync();
var customer = CustomerEclair.GetNodeInfoAsync();
var channels = CustomerEclair.RPC.ChannelsAsync();
var connect = CustomerEclair.RPC.ConnectAsync(merchant.Result);
await Task.WhenAll(blockCount, merchant, customer, channels, connect);
var info = await merchantInfo;
var connect = CustomerEclair.RPC.ConnectAsync(new NodeInfo(info.Id, MerchantCharge.P2PHost, info.Port));
await Task.WhenAll(blockCount, customer, channels, connect);
// Mine until segwit is activated
if (blockCount.Result <= 432)
{
@ -98,6 +100,7 @@ namespace BTCPayServer.Tests
public EclairTester MerchantEclair { get; set; }
public EclairTester CustomerEclair { get; set; }
public ChargeTester MerchantCharge { get; private set; }
internal string GetEnvironment(string variable, string defaultValue)
{

View file

@ -46,20 +46,30 @@ namespace BTCPayServer.Tests
Assert.IsType<ViewResult>(await store.RequestPairing(pairingCode.ToString()));
await store.Pair(pairingCode.ToString(), StoreId);
}
public StoresController CreateStore(string cryptoCode = null)
public StoresController CreateStore()
{
return CreateStoreAsync(cryptoCode).GetAwaiter().GetResult();
return CreateStoreAsync().GetAwaiter().GetResult();
}
public string CryptoCode { get; set; } = "BTC";
public async Task<StoresController> CreateStoreAsync(string cryptoCode = null)
public async Task<StoresController> CreateStoreAsync()
{
cryptoCode = cryptoCode ?? CryptoCode;
SupportedNetwork = parent.NetworkProvider.GetNetwork(cryptoCode);
ExtKey = new ExtKey().GetWif(SupportedNetwork.NBitcoinNetwork);
var store = parent.PayTester.GetController<StoresController>(UserId);
await store.CreateStore(new CreateStoreViewModel() { Name = "Test Store" });
StoreId = store.CreatedStoreId;
return store;
}
public BTCPayNetwork SupportedNetwork { get; set; }
public void RegisterDerivationScheme(string crytoCode)
{
RegisterDerivationSchemeAsync(crytoCode).GetAwaiter().GetResult();
}
public async Task RegisterDerivationSchemeAsync(string cryptoCode)
{
SupportedNetwork = parent.NetworkProvider.GetNetwork(cryptoCode);
var store = parent.PayTester.GetController<StoresController>(UserId);
ExtKey = new ExtKey().GetWif(SupportedNetwork.NBitcoinNetwork);
DerivationScheme = new DerivationStrategyFactory(SupportedNetwork.NBitcoinNetwork).Parse(ExtKey.Neuter().ToString() + "-[legacy]");
var vm = (StoreViewModel)((ViewResult)await store.UpdateStore(StoreId)).Model;
vm.SpeedPolicy = SpeedPolicy.MediumSpeed;
@ -72,27 +82,6 @@ namespace BTCPayServer.Tests
DerivationScheme = DerivationScheme.ToString(),
Confirmation = true
}, "Save");
return store;
}
public BTCPayNetwork SupportedNetwork { get; set; }
public void RegisterDerivationScheme(string crytoCode)
{
RegisterDerivationSchemeAsync(crytoCode).GetAwaiter().GetResult();
}
public async Task RegisterDerivationSchemeAsync(string crytoCode)
{
var store = parent.PayTester.GetController<StoresController>(UserId);
var networkProvider = parent.PayTester.GetService<BTCPayNetworkProvider>();
var derivation = new DerivationStrategyFactory(networkProvider.GetNetwork(crytoCode).NBitcoinNetwork).Parse(ExtKey.Neuter().ToString() + "-[legacy]");
await store.AddDerivationScheme(StoreId, new DerivationSchemeViewModel()
{
CryptoCurrency = crytoCode,
DerivationSchemeFormat = crytoCode,
DerivationScheme = derivation.ToString(),
Confirmation = true
}, "Save");
}
public DerivationStrategyBase DerivationScheme { get; set; }

View file

@ -22,7 +22,7 @@ using BTCPayServer.Data;
using Microsoft.EntityFrameworkCore;
using BTCPayServer.Services.Rates;
using Microsoft.Extensions.Caching.Memory;
using BTCPayServer.Eclair;
using BTCPayServer.Payments.Lightning.Eclair;
using System.Collections.Generic;
using BTCPayServer.Models.StoreViewModels;
using System.Threading.Tasks;
@ -241,6 +241,7 @@ namespace BTCPayServer.Tests
tester.Start();
var user = tester.NewAccount();
user.GrantAccess();
user.RegisterDerivationScheme("BTC");
var invoice = user.BitPay.CreateInvoice(new Invoice()
{
Buyer = new Buyer() { email = "test@fwf.com" },
@ -288,16 +289,17 @@ namespace BTCPayServer.Tests
Assert.Equal("0.00000000001", light.ToString());
}
//[Fact]
//public void CanSendLightningPayment()
//{
[Fact]
public void CanSendLightningPayment()
{
// using (var tester = ServerTester.Create())
// {
// tester.Start();
// tester.PrepareLightning();
// }
//}
using (var tester = ServerTester.Create())
{
tester.Start();
tester.PrepareLightning();
}
}
[Fact]
public void CanUseServerInitiatedPairingCode()
@ -334,6 +336,7 @@ namespace BTCPayServer.Tests
tester.Start();
var acc = tester.NewAccount();
acc.GrantAccess();
acc.RegisterDerivationScheme("BTC");
var invoice = acc.BitPay.CreateInvoice(new Invoice()
{
Price = 5.0,
@ -386,12 +389,12 @@ namespace BTCPayServer.Tests
tester.Start();
var user = tester.NewAccount();
user.GrantAccess();
user.RegisterDerivationScheme("BTC");
var invoice = user.BitPay.CreateInvoice(new Invoice()
{
Price = 5000.0,
Currency = "USD"
}, Facade.Merchant);
var payment1 = invoice.BtcDue + Money.Coins(0.0001m);
var payment2 = invoice.BtcDue;
var tx1 = new uint256(tester.ExplorerNode.SendCommand("sendtoaddress", new object[]
@ -454,6 +457,7 @@ namespace BTCPayServer.Tests
var user = tester.NewAccount();
Assert.False(user.BitPay.TestAccess(Facade.Merchant));
user.GrantAccess();
user.RegisterDerivationScheme("BTC");
Assert.True(user.BitPay.TestAccess(Facade.Merchant));
}
}
@ -467,7 +471,7 @@ namespace BTCPayServer.Tests
tester.Start();
var user = tester.NewAccount();
user.GrantAccess();
user.RegisterDerivationScheme("BTC");
// First we try payment with a merchant having only BTC
var invoice1 = user.BitPay.CreateInvoice(new Invoice()
@ -509,8 +513,8 @@ namespace BTCPayServer.Tests
{
tester.Start();
var user = tester.NewAccount();
user.CryptoCode = "LTC";
user.GrantAccess();
user.RegisterDerivationScheme("LTC");
// First we try payment with a merchant having only BTC
var invoice = user.BitPay.CreateInvoice(new Invoice()
@ -569,7 +573,7 @@ namespace BTCPayServer.Tests
tester.Start();
var user = tester.NewAccount();
user.GrantAccess();
user.RegisterDerivationScheme("BTC");
// First we try payment with a merchant having only BTC
var invoice = user.BitPay.CreateInvoice(new Invoice()
{
@ -658,6 +662,7 @@ namespace BTCPayServer.Tests
tester.Start();
var user = tester.NewAccount();
user.GrantAccess();
user.RegisterDerivationScheme("BTC");
var invoice = user.BitPay.CreateInvoice(new Invoice()
{
Price = 5000.0,

View file

@ -17,11 +17,12 @@ services:
TESTS_POSTGRES: User ID=postgres;Host=postgres;Port=5432;Database=btcpayserver
TESTS_PORT: 80
TESTS_HOSTNAME: tests
TEST_ECLAIR: http://eclair-cli:gpwefwmmewci@eclair:8080/
TEST_CHARGE: http://api-token:foiewnccewuify@lightning-charged:9112/
expose:
- "80"
links:
- nbxplorer
- postgres
- dev
extra_hosts:
- "tests:127.0.0.1"
@ -35,6 +36,8 @@ services:
links:
- nbxplorer
- postgres
- eclair
- lightning-charged
nbxplorer:
image: nicolasdorier/nbxplorer:1.0.1.14
@ -72,11 +75,56 @@ services:
rpcport=43782
port=39388
whitelist=0.0.0.0/0
zmqpubrawblock=tcp://0.0.0.0:29000
zmqpubrawtx=tcp://0.0.0.0:29000
txindex=1
ports:
- "43782:43782"
expose:
- "43782" # RPC
- "39388" # P2P
volumes:
- "bitcoin_datadir:/data"
lightning-charged:
image: shesek/lightning-charge:0.3.1
environment:
NETWORK: regtest
API_TOKEN: foiewnccewuify
SKIP_BITCOIND: 1
BITCOIND_RPCCONNECT: bitcoind
volumes:
- "bitcoin_datadir:/etc/bitcoin"
expose:
- "9112" # Charge
- "9735" # Lightning
ports:
- "54938:9112" # Charge
links:
- bitcoind
eclair:
image: acinq/eclair@sha256:758eaf02683046a096ee03390d3a54df8fcfca50883f7560ab946a36ee4e81d8
environment:
JAVA_OPTS: >
-Xmx512m
-Declair.printToConsole
-Declair.bitcoind.host=bitcoind
-Declair.bitcoind.rpcport=43782
-Declair.bitcoind.rpcuser=ceiwHEbqWI83
-Declair.bitcoind.rpcpassword=DwubwWsoo3
-Declair.bitcoind.zmq=tcp://bitcoind:29000
-Declair.api.enabled=true
-Declair.api.password=gpwefwmmewci
-Declair.chain=regtest
-Declair.api.binding-ip=0.0.0.0
links:
- bitcoind
ports:
- "30992:8080" # api port
expose:
- "9735" # server port
- "8080" # api port
litecoind:
container_name: btcpayserver_dev_litecoind
@ -102,3 +150,6 @@ services:
- "39372:5432"
expose:
- "5432"
volumes:
bitcoin_datadir:

View file

@ -194,7 +194,7 @@ namespace BTCPayServer.Hosting
}
app.UseMiddleware<BTCPayMiddleware>();
return app;
return app;
}
static void Retry(Action act)

View file

@ -0,0 +1,74 @@
using System;
using System.Collections.Generic;
using System.Linq;
using System.Net;
using System.Net.Http;
using System.Net.Http.Headers;
using System.Text;
using System.Threading.Tasks;
using NBitcoin;
using Newtonsoft.Json;
namespace BTCPayServer.Payments.Lightning.CLightning
{
public class ChargeClient
{
private Uri _Uri;
public Uri Uri
{
get
{
return _Uri;
}
}
private Network _Network;
static HttpClient _Client = new HttpClient();
public ChargeClient(Uri uri, Network network)
{
if (uri == null)
throw new ArgumentNullException(nameof(uri));
if (network == null)
throw new ArgumentNullException(nameof(network));
this._Uri = uri;
this._Network = network;
if (uri.UserInfo == null)
throw new ArgumentException(paramName:nameof(uri), message:"User information not present in uri");
var userInfo = uri.UserInfo.Split(':');
if(userInfo.Length != 2)
throw new ArgumentException(paramName: nameof(uri), message: "User information not present in uri");
Credentials = new NetworkCredential(userInfo[0], userInfo[1]);
}
public NetworkCredential Credentials { get; set; }
public GetInfoResponse GetInfo()
{
return GetInfoAsync().GetAwaiter().GetResult();
}
public async Task<GetInfoResponse> GetInfoAsync()
{
var request = Get("info");
var message = await _Client.SendAsync(request);
message.EnsureSuccessStatusCode();
var content = await message.Content.ReadAsStringAsync();
return JsonConvert.DeserializeObject<GetInfoResponse>(content);
}
private HttpRequestMessage Get(string path)
{
var uri = GetFullUri(path);
var request = new HttpRequestMessage(HttpMethod.Get, uri);
request.Headers.Authorization = new AuthenticationHeaderValue("Basic", Convert.ToBase64String(Encoding.ASCII.GetBytes($"{Credentials.UserName}:{Credentials.Password}")));
return request;
}
private Uri GetFullUri(string partialUrl)
{
var uri = _Uri.AbsoluteUri;
if (!uri.EndsWith("/", StringComparison.InvariantCultureIgnoreCase))
uri += "/";
return new Uri(uri + partialUrl);
}
}
}

View file

@ -0,0 +1,17 @@
using System;
using System.Collections.Generic;
using System.Linq;
using System.Threading.Tasks;
namespace BTCPayServer.Payments.Lightning.CLightning
{
public class GetInfoResponse
{
public string Id { get; set; }
public int Port { get; set; }
public string[] Address { get; set; }
public string Version { get; set; }
public int BlockHeight { get; set; }
public string Network { get; set; }
}
}

View file

@ -3,7 +3,7 @@ using System.Collections.Generic;
using System.Linq;
using System.Threading.Tasks;
namespace BTCPayServer.Eclair
namespace BTCPayServer.Payments.Lightning.Eclair
{
public class AllChannelResponse
{

View file

@ -3,7 +3,7 @@ using System.Collections.Generic;
using System.Linq;
using System.Threading.Tasks;
namespace BTCPayServer.Eclair
namespace BTCPayServer.Payments.Lightning.Eclair
{
public class ChannelResponse
{

View file

@ -9,7 +9,7 @@ using NBitcoin;
using NBitcoin.JsonConverters;
using NBitcoin.RPC;
namespace BTCPayServer.Eclair
namespace BTCPayServer.Payments.Lightning.Eclair
{
public class EclairRPCClient
{
@ -21,8 +21,13 @@ namespace BTCPayServer.Eclair
throw new ArgumentNullException(nameof(network));
Address = address;
Network = network;
if (string.IsNullOrEmpty(address.UserInfo))
throw new ArgumentException(paramName: nameof(address), message: "User info in the url should be provided");
Password = address.UserInfo;
}
public string Password { get; set; }
public Network Network { get; private set; }
@ -165,6 +170,8 @@ namespace BTCPayServer.Eclair
var webRequest = (HttpWebRequest)WebRequest.Create(Address.AbsoluteUri);
webRequest.ContentType = "application/json";
webRequest.Method = "POST";
var auth = Convert.ToBase64String(Encoding.ASCII.GetBytes(Password));
webRequest.Headers[HttpRequestHeader.Authorization] = $"Basic {auth}";
return webRequest;
}

View file

@ -5,7 +5,7 @@ using System.Threading.Tasks;
using NBitcoin;
using Newtonsoft.Json;
namespace BTCPayServer.Eclair
namespace BTCPayServer.Payments.Lightning.Eclair
{
public class GetInfoResponse
{

View file

@ -4,7 +4,7 @@ using System.Globalization;
using System.Linq;
using System.Threading.Tasks;
namespace BTCPayServer.Eclair
namespace BTCPayServer.Payments.Lightning.Eclair
{
public enum LightMoneyUnit : ulong
{

View file

@ -3,7 +3,7 @@ using System.Collections.Generic;
using System.Linq;
using System.Threading.Tasks;
namespace BTCPayServer.Eclair
namespace BTCPayServer.Payments.Lightning.Eclair
{
public class NodeInfo
{