Skip to content

Commit

Permalink
Btcpay abstract BTCPayNetwork -- Alternative PR to btcpayserver#865 (b…
Browse files Browse the repository at this point in the history
…tcpayserver#868)

* BitcoinSpecificBtcPayNetwork - abstract BTCPayNetwork

* some type fixes

* fix tests

* simplify fetching handler in invoice controller

* rename network base and bitcoin classes

* abstract serializer to network level

* fix serializer when network not provided

* fix serializer when network not provided

* fix serializer when network not provided

* try fixes for isolating pull request
  • Loading branch information
Kukks authored and NicolasDorier committed May 29, 2019
1 parent 90852fe commit d3e3c31
Show file tree
Hide file tree
Showing 39 changed files with 223 additions and 167 deletions.
82 changes: 55 additions & 27 deletions BTCPayServer.Common/BTCPayNetwork.cs
Original file line number Diff line number Diff line change
Expand Up @@ -5,6 +5,7 @@
using System.Threading.Tasks;
using NBitcoin;
using NBXplorer;
using Newtonsoft.Json;

namespace BTCPayServer
{
Expand Down Expand Up @@ -42,38 +43,18 @@ public static BTCPayDefaultSettings GetDefaultSettings(NetworkType chainType)
public string DefaultConfigurationFile { get; set; }
public int DefaultPort { get; set; }
}
public class BTCPayNetwork

public class BTCPayNetwork:BTCPayNetworkBase
{
public Network NBitcoinNetwork { get; set; }
public string CryptoCode { get; internal set; }
public string BlockExplorerLink { get; internal set; }
public string UriScheme { get; internal set; }
public string DisplayName { get; set; }

[Obsolete("Should not be needed")]
public bool IsBTC
{
get
{
return CryptoCode == "BTC";
}
}

public string CryptoImagePath { get; set; }
public string LightningImagePath { get; set; }
public NBXplorer.NBXplorerNetwork NBXplorerNetwork { get; set; }

public bool SupportRBF { get; internal set; }
public string LightningImagePath { get; set; }
public BTCPayDefaultSettings DefaultSettings { get; set; }
public KeyPath CoinType { get; internal set; }
public int MaxTrackedConfirmation { get; internal set; } = 6;
public string[] DefaultRateRules { get; internal set; } = Array.Empty<string>();
public bool SupportRBF { get; internal set; }
public Dictionary<uint, DerivationType> ElectrumMapping = new Dictionary<uint, DerivationType>();
public override string ToString()
{
return CryptoCode;
}



public KeyPath GetRootKeyPath(DerivationType type)
{
KeyPath baseKey;
Expand Down Expand Up @@ -105,7 +86,54 @@ public KeyPath GetRootKeyPath(DerivationType type)
public KeyPath GetRootKeyPath()
{
return new KeyPath(NBitcoinNetwork.Consensus.SupportSegwit ? "49'" : "44'")
.Derive(CoinType);
.Derive(CoinType);
}

public override T ToObject<T>(string json)
{
return NBXplorerNetwork.Serializer.ToObject<T>(json);
}

public override string ToString<T>(T obj)
{
return NBXplorerNetwork.Serializer.ToString(obj);
}
}

public abstract class BTCPayNetworkBase
{

public string CryptoCode { get; internal set; }
public string BlockExplorerLink { get; internal set; }
public string UriScheme { get; internal set; }
public string DisplayName { get; set; }

[Obsolete("Should not be needed")]
public bool IsBTC
{
get
{
return CryptoCode == "BTC";
}
}

public string CryptoImagePath { get; set; }

public int MaxTrackedConfirmation { get; internal set; } = 6;
public string[] DefaultRateRules { get; internal set; } = Array.Empty<string>();
public override string ToString()
{
return CryptoCode;
}

public virtual T ToObject<T>(string json)
{
return JsonConvert.DeserializeObject<T>(json);
}

public virtual string ToString<T>(T obj)
{
return JsonConvert.SerializeObject(obj);
}
}
}
30 changes: 15 additions & 15 deletions BTCPayServer.Common/BTCPayNetworkProvider.cs
Original file line number Diff line number Diff line change
Expand Up @@ -10,7 +10,7 @@ namespace BTCPayServer
{
public partial class BTCPayNetworkProvider
{
Dictionary<string, BTCPayNetwork> _Networks = new Dictionary<string, BTCPayNetwork>();
Dictionary<string, BTCPayNetworkBase> _Networks = new Dictionary<string, BTCPayNetworkBase>();


private readonly NBXplorerNetworkProvider _NBXplorerNetworkProvider;
Expand All @@ -26,7 +26,7 @@ public NBXplorerNetworkProvider NBXplorerNetworkProvider
{
NetworkType = filtered.NetworkType;
_NBXplorerNetworkProvider = new NBXplorerNetworkProvider(filtered.NetworkType);
_Networks = new Dictionary<string, BTCPayNetwork>();
_Networks = new Dictionary<string, BTCPayNetworkBase>();
cryptoCodes = cryptoCodes.Select(c => c.ToUpperInvariant()).ToArray();
foreach (var network in filtered._Networks)
{
Expand Down Expand Up @@ -54,15 +54,15 @@ public BTCPayNetworkProvider(NetworkType networkType)
InitViacoin();

// Assume that electrum mappings are same as BTC if not specified
foreach (var network in _Networks)
foreach (var network in _Networks.Values.OfType<BTCPayNetwork>())
{
if(network.Value.ElectrumMapping.Count == 0)
if(network.ElectrumMapping.Count == 0)
{
network.Value.ElectrumMapping = GetNetwork("BTC").ElectrumMapping;
if (!network.Value.NBitcoinNetwork.Consensus.SupportSegwit)
network.ElectrumMapping = GetNetwork<BTCPayNetwork>("BTC").ElectrumMapping;
if (!network.NBitcoinNetwork.Consensus.SupportSegwit)
{
network.Value.ElectrumMapping =
network.Value.ElectrumMapping
network.ElectrumMapping =
network.ElectrumMapping
.Where(kv => kv.Value == DerivationType.Legacy)
.ToDictionary(k => k.Key, k => k.Value);
}
Expand All @@ -86,14 +86,14 @@ public BTCPayNetworkProvider Filter(string[] cryptoCodes)
}

[Obsolete("To use only for legacy stuff")]
public BTCPayNetwork BTC => GetNetwork("BTC");
public BTCPayNetwork BTC => GetNetwork<BTCPayNetwork>("BTC");

public void Add(BTCPayNetwork network)
public void Add(BTCPayNetworkBase network)
{
_Networks.Add(network.CryptoCode.ToUpperInvariant(), network);
}

public IEnumerable<BTCPayNetwork> GetAll()
public IEnumerable<BTCPayNetworkBase> GetAll()
{
return _Networks.Values.ToArray();
}
Expand All @@ -103,14 +103,14 @@ public bool Support(string cryptoCode)
return _Networks.ContainsKey(cryptoCode.ToUpperInvariant());
}

public BTCPayNetwork GetNetwork(string cryptoCode)
public T GetNetwork<T>(string cryptoCode) where T: BTCPayNetworkBase
{
if(!_Networks.TryGetValue(cryptoCode.ToUpperInvariant(), out BTCPayNetwork network))
if(!_Networks.TryGetValue(cryptoCode.ToUpperInvariant(), out BTCPayNetworkBase network))
{
if (cryptoCode == "XBT")
return GetNetwork("BTC");
return GetNetwork<T>("BTC");
}
return network;
return network as T;
}
}
}
2 changes: 1 addition & 1 deletion BTCPayServer.Rating/CurrencyPair.cs
Original file line number Diff line number Diff line change
Expand Up @@ -53,7 +53,7 @@ public static bool TryParse(string str, out CurrencyPair value)
for (int i = 3; i < 5; i++)
{
var potentialCryptoName = currencyPair.Substring(0, i);
var network = _NetworkProvider.GetNetwork(potentialCryptoName);
var network = _NetworkProvider.GetNetwork<BTCPayNetworkBase>(potentialCryptoName);
if (network != null)
{
value = new CurrencyPair(network.CryptoCode, currencyPair.Substring(i));
Expand Down
10 changes: 5 additions & 5 deletions BTCPayServer.Tests/ServerTester.cs
Original file line number Diff line number Diff line change
Expand Up @@ -44,14 +44,14 @@ public ServerTester(string scope)
Directory.CreateDirectory(_Directory);

NetworkProvider = new BTCPayNetworkProvider(NetworkType.Regtest);
ExplorerNode = new RPCClient(RPCCredentialString.Parse(GetEnvironment("TESTS_BTCRPCCONNECTION", "server=http://127.0.0.1:43782;ceiwHEbqWI83:DwubwWsoo3")), NetworkProvider.GetNetwork("BTC").NBitcoinNetwork);
ExplorerNode = new RPCClient(RPCCredentialString.Parse(GetEnvironment("TESTS_BTCRPCCONNECTION", "server=http://127.0.0.1:43782;ceiwHEbqWI83:DwubwWsoo3")), NetworkProvider.GetNetwork<BTCPayNetwork>("BTC").NBitcoinNetwork);
ExplorerNode.ScanRPCCapabilities();
LTCExplorerNode = new RPCClient(RPCCredentialString.Parse(GetEnvironment("TESTS_LTCRPCCONNECTION", "server=http://127.0.0.1:43783;ceiwHEbqWI83:DwubwWsoo3")), NetworkProvider.GetNetwork("LTC").NBitcoinNetwork);
LTCExplorerNode = new RPCClient(RPCCredentialString.Parse(GetEnvironment("TESTS_LTCRPCCONNECTION", "server=http://127.0.0.1:43783;ceiwHEbqWI83:DwubwWsoo3")), NetworkProvider.GetNetwork<BTCPayNetwork>("LTC").NBitcoinNetwork);

ExplorerClient = new ExplorerClient(NetworkProvider.GetNetwork("BTC").NBXplorerNetwork, new Uri(GetEnvironment("TESTS_BTCNBXPLORERURL", "http://127.0.0.1:32838/")));
LTCExplorerClient = new ExplorerClient(NetworkProvider.GetNetwork("LTC").NBXplorerNetwork, new Uri(GetEnvironment("TESTS_LTCNBXPLORERURL", "http://127.0.0.1:32838/")));
ExplorerClient = new ExplorerClient(NetworkProvider.GetNetwork<BTCPayNetwork>("BTC").NBXplorerNetwork, new Uri(GetEnvironment("TESTS_BTCNBXPLORERURL", "http://127.0.0.1:32838/")));
LTCExplorerClient = new ExplorerClient(NetworkProvider.GetNetwork<BTCPayNetwork>("LTC").NBXplorerNetwork, new Uri(GetEnvironment("TESTS_LTCNBXPLORERURL", "http://127.0.0.1:32838/")));

var btc = NetworkProvider.GetNetwork("BTC").NBitcoinNetwork;
var btc = NetworkProvider.GetNetwork<BTCPayNetwork>("BTC").NBitcoinNetwork;
CustomerLightningD = LightningClientFactory.CreateClient(GetEnvironment("TEST_CUSTOMERLIGHTNINGD", "type=clightning;server=tcp://127.0.0.1:30992/"), btc);
MerchantLightningD = LightningClientFactory.CreateClient(GetEnvironment("TEST_MERCHANTLIGHTNINGD", "type=clightning;server=tcp://127.0.0.1:30993/"), btc);

Expand Down
2 changes: 1 addition & 1 deletion BTCPayServer.Tests/TestAccount.cs
Original file line number Diff line number Diff line change
Expand Up @@ -95,7 +95,7 @@ public WalletId RegisterDerivationScheme(string crytoCode, bool segwit = false)
}
public async Task<WalletId> RegisterDerivationSchemeAsync(string cryptoCode, bool segwit = false)
{
SupportedNetwork = parent.NetworkProvider.GetNetwork(cryptoCode);
SupportedNetwork = parent.NetworkProvider.GetNetwork<BTCPayNetwork>(cryptoCode);
var store = parent.PayTester.GetController<StoresController>(UserId, StoreId);
ExtKey = new ExtKey().GetWif(SupportedNetwork.NBitcoinNetwork);
DerivationScheme = new DerivationStrategyFactory(SupportedNetwork.NBitcoinNetwork).Parse(ExtKey.Neuter().ToString() + (segwit ? "" : "-[legacy]"));
Expand Down
16 changes: 8 additions & 8 deletions BTCPayServer.Tests/UnitTest1.cs
Original file line number Diff line number Diff line change
Expand Up @@ -1499,8 +1499,8 @@ public void CanParseDerivationScheme()
var testnetNetworkProvider = new BTCPayNetworkProvider(NetworkType.Testnet);
var regtestNetworkProvider = new BTCPayNetworkProvider(NetworkType.Regtest);
var mainnetNetworkProvider = new BTCPayNetworkProvider(NetworkType.Mainnet);
var testnetParser = new DerivationSchemeParser(testnetNetworkProvider.GetNetwork("BTC"));
var mainnetParser = new DerivationSchemeParser(mainnetNetworkProvider.GetNetwork("BTC"));
var testnetParser = new DerivationSchemeParser(testnetNetworkProvider.GetNetwork<BTCPayNetwork>("BTC"));
var mainnetParser = new DerivationSchemeParser(mainnetNetworkProvider.GetNetwork<BTCPayNetwork>("BTC"));
NBXplorer.DerivationStrategy.DerivationStrategyBase result;
// Passing electrum stuff
// Passing a native segwit from mainnet to a testnet parser, means the testnet parser will try to convert it into segwit
Expand Down Expand Up @@ -1543,16 +1543,16 @@ public void CanParseDerivationScheme()
result = testnetParser.Parse(tpub);
Assert.Equal($"{tpub}-[p2sh]", result.ToString());

var regtestParser = new DerivationSchemeParser(regtestNetworkProvider.GetNetwork("BTC"));
var regtestParser = new DerivationSchemeParser(regtestNetworkProvider.GetNetwork<BTCPayNetwork>("BTC"));
var parsed = regtestParser.Parse("xpub6DG1rMYXiQtCc6CfdLFD9CtxqhzzRh7j6Sq6EdE9abgYy3cfDRrniLLv2AdwqHL1exiLnnKR5XXcaoiiexf3Y9R6J6rxkJtqJHzNzMW9QMZ-[p2sh]");
Assert.Equal("tpubDDdeNbNDRgqestPX5XEJM8ELAq6eR5cne5RPbBHHvWSSiLHNHehsrn1kGCijMnHFSsFFQMqHcdMfGzDL3pWHRasPMhcGRqZ4tFankQ3i4ok-[p2sh]", parsed.ToString());

// Let's make sure we can't generate segwit with dogecoin
regtestParser = new DerivationSchemeParser(regtestNetworkProvider.GetNetwork("DOGE"));
regtestParser = new DerivationSchemeParser(regtestNetworkProvider.GetNetwork<BTCPayNetwork>("DOGE"));
parsed = regtestParser.Parse("xpub6DG1rMYXiQtCc6CfdLFD9CtxqhzzRh7j6Sq6EdE9abgYy3cfDRrniLLv2AdwqHL1exiLnnKR5XXcaoiiexf3Y9R6J6rxkJtqJHzNzMW9QMZ-[p2sh]");
Assert.Equal("tpubDDdeNbNDRgqestPX5XEJM8ELAq6eR5cne5RPbBHHvWSSiLHNHehsrn1kGCijMnHFSsFFQMqHcdMfGzDL3pWHRasPMhcGRqZ4tFankQ3i4ok-[legacy]", parsed.ToString());

regtestParser = new DerivationSchemeParser(regtestNetworkProvider.GetNetwork("DOGE"));
regtestParser = new DerivationSchemeParser(regtestNetworkProvider.GetNetwork<BTCPayNetwork>("DOGE"));
parsed = regtestParser.Parse("tpubDDdeNbNDRgqestPX5XEJM8ELAq6eR5cne5RPbBHHvWSSiLHNHehsrn1kGCijMnHFSsFFQMqHcdMfGzDL3pWHRasPMhcGRqZ4tFankQ3i4ok-[p2sh]");
Assert.Equal("tpubDDdeNbNDRgqestPX5XEJM8ELAq6eR5cne5RPbBHHvWSSiLHNHehsrn1kGCijMnHFSsFFQMqHcdMfGzDL3pWHRasPMhcGRqZ4tFankQ3i4ok-[legacy]", parsed.ToString());
}
Expand All @@ -1569,7 +1569,7 @@ public void CanAddDerivationSchemes()
user.RegisterDerivationScheme("BTC");
user.RegisterDerivationScheme("LTC");
user.RegisterLightningNode("BTC", LightningConnectionType.CLightning);
var btcNetwork = tester.PayTester.Networks.GetNetwork("BTC");
var btcNetwork = tester.PayTester.Networks.GetNetwork<BTCPayNetwork>("BTC");
var invoice = user.BitPay.CreateInvoice(new Invoice()
{
Price = 1.5m,
Expand Down Expand Up @@ -2709,7 +2709,7 @@ public void CheckRatesProvider()
[Trait("Fast", "Fast")]
public void ParseDerivationSchemeSettings()
{
var mainnet = new BTCPayNetworkProvider(NetworkType.Mainnet).GetNetwork("BTC");
var mainnet = new BTCPayNetworkProvider(NetworkType.Mainnet).GetNetwork<BTCPayNetwork>("BTC");
var root = new Mnemonic("usage fever hen zero slide mammal silent heavy donate budget pulse say brain thank sausage brand craft about save attract muffin advance illegal cabbage").DeriveExtKey();
Assert.True(DerivationSchemeSettings.TryParseFromColdcard("{\"keystore\": {\"ckcc_xpub\": \"xpub661MyMwAqRbcGVBsTGeNZN6QGVHmMHLdSA4FteGsRrEriu4pnVZMZWnruFFFXkMnyoBjyHndD3Qwcfz4MPzBUxjSevweNFQx7SAYZATtcDw\", \"xpub\": \"ypub6WWc2gWwHbdnAAyJDnR4SPL1phRh7REqrPBfZeizaQ1EmTshieRXJC3Z5YoU4wkcdKHEjQGkh6AYEzCQC1Kz3DNaWSwdc1pc8416hAjzqyD\", \"label\": \"Coldcard Import 0x60d1af8b\", \"ckcc_xfp\": 1624354699, \"type\": \"hardware\", \"hw_type\": \"coldcard\", \"derivation\": \"m/49'/0'/0'\"}, \"wallet_type\": \"standard\", \"use_encryption\": false, \"seed_version\": 17}", mainnet, out var settings));
Assert.Equal(root.GetPublicKey().GetHDFingerPrint(), settings.AccountKeySettings[0].RootFingerprint);
Expand All @@ -2719,7 +2719,7 @@ public void ParseDerivationSchemeSettings()
Assert.Equal("ypub6WWc2gWwHbdnAAyJDnR4SPL1phRh7REqrPBfZeizaQ1EmTshieRXJC3Z5YoU4wkcdKHEjQGkh6AYEzCQC1Kz3DNaWSwdc1pc8416hAjzqyD", settings.AccountOriginal);
Assert.Equal(root.Derive(new KeyPath("m/49'/0'/0'")).Neuter().PubKey.WitHash.ScriptPubKey.Hash.ScriptPubKey, settings.AccountDerivation.Derive(new KeyPath()).ScriptPubKey);

var testnet = new BTCPayNetworkProvider(NetworkType.Testnet).GetNetwork("BTC");
var testnet = new BTCPayNetworkProvider(NetworkType.Testnet).GetNetwork<BTCPayNetwork>("BTC");

// Should be legacy
Assert.True(DerivationSchemeSettings.TryParseFromColdcard("{\"keystore\": {\"ckcc_xpub\": \"tpubD6NzVbkrYhZ4YHNiuTdTmHRmbcPRLfqgyneZFCL1mkzkUBjXriQShxTh9HL34FK2mhieasJVk9EzJrUfkFqRNQBjiXgx3n5BhPkxKBoFmaS\", \"xpub\": \"tpubDDWYqT3P24znfsaGX7kZcQhNc5LAjnQiKQvUCHF2jS6dsgJBRtymopEU5uGpMaR5YChjuiExZG1X2aTbqXkp82KqH5qnqwWHp6EWis9ZvKr\", \"label\": \"Coldcard Import 0x60d1af8b\", \"ckcc_xfp\": 1624354699, \"type\": \"hardware\", \"hw_type\": \"coldcard\", \"derivation\": \"m/44'/1'/0'\"}, \"wallet_type\": \"standard\", \"use_encryption\": false, \"seed_version\": 17}", testnet, out settings));
Expand Down
4 changes: 2 additions & 2 deletions BTCPayServer/Configuration/BTCPayServerOptions.cs
Original file line number Diff line number Diff line change
Expand Up @@ -81,12 +81,12 @@ public void LoadArgs(IConfiguration conf)
NetworkProvider = new BTCPayNetworkProvider(NetworkType).Filter(supportedChains.ToArray());
foreach (var chain in supportedChains)
{
if (NetworkProvider.GetNetwork(chain) == null)
if (NetworkProvider.GetNetwork<BTCPayNetworkBase>(chain) == null)
throw new ConfigException($"Invalid chains \"{chain}\"");
}

var validChains = new List<string>();
foreach (var net in NetworkProvider.GetAll())
foreach (var net in NetworkProvider.GetAll().OfType<BTCPayNetwork>())
{
NBXplorerConnectionSetting setting = new NBXplorerConnectionSetting();
setting.CryptoCode = net.CryptoCode;
Expand Down
4 changes: 2 additions & 2 deletions BTCPayServer/Configuration/DefaultConfiguration.cs
Original file line number Diff line number Diff line change
Expand Up @@ -46,7 +46,7 @@ protected override CommandLineApplication CreateCommandLineApplicationCore()
app.Option("--debuglog", "A rolling log file for debug messages.", CommandOptionType.SingleValue);
app.Option("--debugloglevel", "The severity you log (default:information)", CommandOptionType.SingleValue);
app.Option("--disable-registration", "Disables new user registrations (default:true)", CommandOptionType.SingleValue);
foreach (var network in provider.GetAll())
foreach (var network in provider.GetAll().OfType<BTCPayNetwork>())
{
var crypto = network.CryptoCode.ToLowerInvariant();
app.Option($"--{crypto}explorerurl", $"URL of the NBXplorer for {network.CryptoCode} (default: {network.NBXplorerNetwork.DefaultSettings.DefaultUrl})", CommandOptionType.SingleValue);
Expand Down Expand Up @@ -121,7 +121,7 @@ protected override string GetDefaultConfigurationFileTemplate(IConfiguration con
builder.AppendLine("#mysql=User ID=root;Password=myPassword;Host=localhost;Port=3306;Database=myDataBase;");
builder.AppendLine();
builder.AppendLine("### NBXplorer settings ###");
foreach (var n in new BTCPayNetworkProvider(networkType).GetAll())
foreach (var n in new BTCPayNetworkProvider(networkType).GetAll().OfType<BTCPayNetwork>())
{
builder.AppendLine($"#{n.CryptoCode}.explorer.url={n.NBXplorerNetwork.DefaultSettings.DefaultUrl}");
builder.AppendLine($"#{n.CryptoCode}.explorer.cookiefile={ n.NBXplorerNetwork.DefaultSettings.DefaultCookieFile}");
Expand Down
Loading

0 comments on commit d3e3c31

Please sign in to comment.