2021-12-31 08:59:02 +01:00
|
|
|
using System;
|
2024-06-21 03:15:30 +02:00
|
|
|
using System.Collections.Generic;
|
2022-05-03 08:12:10 +02:00
|
|
|
using System.Diagnostics;
|
2020-10-21 14:02:20 +02:00
|
|
|
using System.IO;
|
|
|
|
using System.IO.Compression;
|
|
|
|
using System.Linq;
|
|
|
|
using System.Reflection;
|
2022-05-03 08:12:10 +02:00
|
|
|
using System.Text;
|
2020-10-21 14:02:20 +02:00
|
|
|
using System.Text.Json;
|
2022-05-03 08:12:10 +02:00
|
|
|
using System.Threading.Tasks;
|
2020-11-17 13:46:23 +01:00
|
|
|
using BTCPayServer.Abstractions.Contracts;
|
2022-11-09 15:28:16 +01:00
|
|
|
using McMaster.NETCore.Plugins;
|
2022-05-03 08:12:10 +02:00
|
|
|
using NBitcoin.Crypto;
|
|
|
|
using NBitcoin.DataEncoders;
|
|
|
|
using NBitcoin.Secp256k1;
|
2020-10-21 14:02:20 +02:00
|
|
|
|
|
|
|
namespace BTCPayServer.PluginPacker
|
|
|
|
{
|
|
|
|
class Program
|
|
|
|
{
|
2022-05-03 08:12:10 +02:00
|
|
|
static async Task Main(string[] args)
|
2020-10-21 14:02:20 +02:00
|
|
|
{
|
2020-10-24 17:21:50 +02:00
|
|
|
if (args.Length < 3)
|
|
|
|
{
|
|
|
|
Console.WriteLine("Usage: btcpay-plugin [directory of compiled plugin] [name of plugin] [packed plugin output directory]");
|
|
|
|
return;
|
|
|
|
}
|
2020-10-21 14:02:20 +02:00
|
|
|
var directory = args[0];
|
|
|
|
var name = args[1];
|
2022-05-04 09:01:17 +02:00
|
|
|
var outputDir = Path.Combine(args[2], name);
|
2020-10-21 14:02:20 +02:00
|
|
|
var outputFile = Path.Combine(outputDir, name);
|
2023-02-02 10:13:56 +01:00
|
|
|
var rootDLLPath = Path.GetFullPath(Path.Combine(directory, name + ".dll"));
|
2021-12-31 08:59:02 +01:00
|
|
|
if (!File.Exists(rootDLLPath))
|
2020-10-21 14:02:20 +02:00
|
|
|
{
|
|
|
|
throw new Exception($"{rootDLLPath} could not be found");
|
|
|
|
}
|
|
|
|
|
2023-01-31 15:24:20 +01:00
|
|
|
var plugin = PluginLoader.CreateFromAssemblyFile(rootDLLPath, false, new[] { typeof(IBTCPayServerPlugin) }, o => o.PreferSharedTypes = true);
|
2022-11-09 15:28:16 +01:00
|
|
|
var assembly = plugin.LoadAssembly(name);
|
2020-10-21 14:02:20 +02:00
|
|
|
var extension = GetAllExtensionTypesFromAssembly(assembly).FirstOrDefault();
|
|
|
|
if (extension is null)
|
|
|
|
{
|
|
|
|
throw new Exception($"{rootDLLPath} is not a valid plugin");
|
|
|
|
}
|
|
|
|
|
|
|
|
var loadedPlugin = (IBTCPayServerPlugin)Activator.CreateInstance(extension);
|
|
|
|
var json = JsonSerializer.Serialize(loadedPlugin);
|
|
|
|
Directory.CreateDirectory(outputDir);
|
2022-05-03 08:12:10 +02:00
|
|
|
outputDir = Path.Combine(outputDir, loadedPlugin.Version.ToString());
|
|
|
|
Directory.CreateDirectory(outputDir);
|
|
|
|
outputFile = Path.Combine(outputDir, name);
|
2020-10-21 14:02:20 +02:00
|
|
|
if (File.Exists(outputFile + ".btcpay"))
|
|
|
|
{
|
|
|
|
File.Delete(outputFile + ".btcpay");
|
|
|
|
}
|
|
|
|
ZipFile.CreateFromDirectory(directory, outputFile + ".btcpay", CompressionLevel.Optimal, false);
|
2022-05-03 08:12:10 +02:00
|
|
|
await File.WriteAllTextAsync(outputFile + ".btcpay.json", json);
|
|
|
|
|
|
|
|
var sha256sums = new StringBuilder();
|
|
|
|
sha256sums.AppendLine(
|
2023-01-06 14:18:07 +01:00
|
|
|
$"{Encoders.Hex.EncodeData(Hashes.SHA256(Encoding.UTF8.GetBytes(json)))} {name}.btcpay.json");
|
|
|
|
|
2022-05-03 08:12:10 +02:00
|
|
|
sha256sums.AppendLine(
|
|
|
|
$"{Encoders.Hex.EncodeData(Hashes.SHA256(await File.ReadAllBytesAsync(outputFile + ".btcpay")))} {name}.btcpay");
|
|
|
|
|
|
|
|
var sha256dirs = Path.Combine(outputDir, "SHA256SUMS");
|
|
|
|
if (File.Exists(sha256dirs))
|
|
|
|
{
|
|
|
|
File.Delete(sha256dirs);
|
|
|
|
}
|
|
|
|
await File.WriteAllTextAsync(sha256dirs, sha256sums.ToString());
|
2023-01-06 14:18:07 +01:00
|
|
|
|
2022-05-30 11:36:25 +02:00
|
|
|
// try Windows executable first, fall back to macOS/Linux PowerShell
|
2022-05-03 08:12:10 +02:00
|
|
|
try
|
|
|
|
{
|
2022-05-30 11:36:25 +02:00
|
|
|
await CreateShasums("powershell.exe", sha256dirs, outputDir);
|
2022-05-03 08:12:10 +02:00
|
|
|
}
|
2022-06-28 10:38:59 +02:00
|
|
|
catch (Exception)
|
2022-05-03 08:12:10 +02:00
|
|
|
{
|
2022-05-30 11:36:25 +02:00
|
|
|
try
|
|
|
|
{
|
|
|
|
await CreateShasums("bash", sha256dirs, outputDir);
|
|
|
|
}
|
|
|
|
catch (Exception ex)
|
|
|
|
{
|
|
|
|
Console.WriteLine(
|
|
|
|
$"Attempted to sign hashes with gpg but maybe powershell is not installed?\n{ex.Message}");
|
|
|
|
}
|
2022-05-03 08:12:10 +02:00
|
|
|
}
|
2023-01-06 14:18:07 +01:00
|
|
|
|
2021-01-07 14:49:53 +01:00
|
|
|
Console.WriteLine($"Created {outputFile}.btcpay at {directory}");
|
2020-10-21 14:02:20 +02:00
|
|
|
}
|
2021-12-31 08:59:02 +01:00
|
|
|
|
2022-05-30 11:36:25 +02:00
|
|
|
private static async Task CreateShasums(string exec, string sha256dirs, string outputDir)
|
|
|
|
{
|
|
|
|
Process cmd = new();
|
|
|
|
cmd.StartInfo.FileName = exec;
|
|
|
|
cmd.StartInfo.RedirectStandardInput = true;
|
|
|
|
cmd.StartInfo.RedirectStandardOutput = true;
|
|
|
|
cmd.StartInfo.CreateNoWindow = false;
|
|
|
|
cmd.StartInfo.UseShellExecute = false;
|
|
|
|
cmd.Start();
|
|
|
|
|
|
|
|
await cmd.StandardInput.WriteLineAsync($"cat {sha256dirs} | gpg -s > {Path.Combine(outputDir, "SHA256SUMS.asc")}");
|
|
|
|
await cmd.StandardInput.FlushAsync();
|
|
|
|
cmd.StandardInput.Close();
|
|
|
|
await cmd.WaitForExitAsync();
|
|
|
|
Console.WriteLine(await cmd.StandardOutput.ReadToEndAsync());
|
|
|
|
}
|
|
|
|
|
2020-10-21 14:02:20 +02:00
|
|
|
private static Type[] GetAllExtensionTypesFromAssembly(Assembly assembly)
|
|
|
|
{
|
2024-06-21 03:15:30 +02:00
|
|
|
return GetLoadableTypes(assembly).Where(type =>
|
2020-10-21 14:02:20 +02:00
|
|
|
typeof(IBTCPayServerPlugin).IsAssignableFrom(type) &&
|
|
|
|
!type.IsAbstract).ToArray();
|
|
|
|
}
|
2024-06-21 03:15:30 +02:00
|
|
|
static Type[] GetLoadableTypes(Assembly assembly)
|
|
|
|
{
|
|
|
|
if (assembly == null)
|
|
|
|
throw new ArgumentNullException(nameof(assembly));
|
|
|
|
try
|
|
|
|
{
|
|
|
|
return assembly.GetTypes();
|
|
|
|
}
|
|
|
|
catch (ReflectionTypeLoadException e)
|
|
|
|
{
|
|
|
|
return e.Types.Where(t => t != null).ToArray();
|
|
|
|
}
|
|
|
|
}
|
2020-10-21 14:02:20 +02:00
|
|
|
}
|
|
|
|
}
|