Skip to content

Commit bbc0fe1

Browse files
committed
etcd HA testing wip
1 parent aad4230 commit bbc0fe1

File tree

5 files changed

+397
-13
lines changed

5 files changed

+397
-13
lines changed
Lines changed: 302 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -0,0 +1,302 @@
1+
using System.Collections.Immutable;
2+
using System.Diagnostics;
3+
using System.Security.Cryptography;
4+
using Dasync.Collections;
5+
using Docker.DotNet;
6+
using dotnet_etcd;
7+
using Google.Protobuf;
8+
using Google.Protobuf.Collections;
9+
using Grpc.Core;
10+
using Invoicesrpc;
11+
// using LNBolt;
12+
using Lnrpc;
13+
using LNUnit.Extentions;
14+
using LNUnit.LND;
15+
using LNUnit.Setup;
16+
using LNUnit.Tests.Fixture;
17+
using Microsoft.Extensions.Caching.Memory;
18+
using Microsoft.Extensions.Configuration;
19+
using Microsoft.Extensions.DependencyInjection;
20+
using NBitcoin;
21+
using Routerrpc;
22+
using Serilog;
23+
using ServiceStack;
24+
using ServiceStack.Text;
25+
using Walletrpc;
26+
using AddressType = Lnrpc.AddressType;
27+
using Assert = NUnit.Framework.Assert;
28+
using ListUnspentRequest = Lnrpc.ListUnspentRequest;
29+
using Network = NBitcoin.Network;
30+
using Transaction = Walletrpc.Transaction;
31+
32+
namespace LNUnit.Tests.Abstract;
33+
34+
35+
public abstract class EctdLightningAbstractTests : IDisposable
36+
{
37+
public EctdLightningAbstractTests(string dbType,
38+
string lndImage = "custom_lnd",
39+
string tag = "latest",
40+
string lndRoot = "/root/.lnd",
41+
bool pullImage = false
42+
)
43+
{
44+
_dbType = dbType;
45+
_lndImage = lndImage;
46+
_tag = tag;
47+
_lndRoot = lndRoot;
48+
_pullImage = pullImage;
49+
}
50+
51+
[SetUp]
52+
public async Task PerTestSetUp()
53+
{
54+
Builder.CancelAllInterceptors();
55+
Builder.NewBlock(); //tick toc new block
56+
await Builder.NewBlock();
57+
}
58+
59+
[OneTimeSetUp]
60+
public async Task OneTimeSetup()
61+
{
62+
var configuration = new ConfigurationBuilder()
63+
.SetBasePath(Directory.GetCurrentDirectory()) // Set the current directory as the base path
64+
.AddJsonFile("appsettings.json", false, true)
65+
.AddJsonFile("appsettings.Development.json", false, true)
66+
.Build();
67+
var services = new ServiceCollection();
68+
var loggerConfiguration = new LoggerConfiguration().Enrich.FromLogContext();
69+
loggerConfiguration.ReadFrom.Configuration(configuration);
70+
Log.Logger = loggerConfiguration.CreateLogger();
71+
services.AddLogging();
72+
services.AddSerilog(Log.Logger, true);
73+
_serviceProvider = services.BuildServiceProvider();
74+
Builder = ActivatorUtilities.CreateInstance<LNUnitBuilder>(_serviceProvider);
75+
76+
if (_dbType == "postgres")
77+
{
78+
PostgresFixture.AddDb("alice");
79+
PostgresFixture.AddDb("bob");
80+
PostgresFixture.AddDb("carol");
81+
}
82+
83+
await _client.CreateDockerImageFromPath("../../../../Docker/lnd", ["custom_lnd", "custom_lnd:latest"]);
84+
await _client.CreateDockerImageFromPath("./../../../../Docker/bitcoin/30.0", ["bitcoin:latest", "bitcoin:30.0"]);
85+
await SetupNetwork(_lndImage, _tag, _lndRoot, _pullImage, bitcoinImage: "bitcoin", bitcoinTag: "30.0", pullBitcoinImage: false);
86+
}
87+
88+
89+
90+
public string DbContainerName { get; set; } = "postgres";
91+
private readonly DockerClient _client = new DockerClientConfiguration().CreateClient();
92+
93+
private ServiceProvider _serviceProvider;
94+
95+
public void Dispose()
96+
{
97+
GC.SuppressFinalize(this);
98+
99+
// Remove containers
100+
_client.RemoveContainer("miner").GetAwaiter().GetResult();
101+
_client.RemoveContainer("alice").GetAwaiter().GetResult();
102+
_client.RemoveContainer("bob").GetAwaiter().GetResult();
103+
_client.RemoveContainer("carol").GetAwaiter().GetResult();
104+
105+
Builder?.Destroy();
106+
Builder?.Dispose();
107+
_client.Dispose();
108+
}
109+
110+
public LNUnitBuilder? Builder { get; private set; }
111+
112+
113+
public async Task SetupNetwork(string lndImage = "lightninglabs/lnd", string lndTag = "daily-testing-only",
114+
string lndRoot = "/root/.lnd", bool pullLndImage = false, string bitcoinImage = "polarlightning/bitcoind", string bitcoinTag = "29.0",
115+
bool pullBitcoinImage = false)
116+
{
117+
await _client.RemoveContainer("miner");
118+
await _client.RemoveContainer("alice");
119+
await _client.RemoveContainer("bob");
120+
await _client.RemoveContainer("carol");
121+
await _client.RemoveContainer("etcd");
122+
123+
Builder.AddBitcoinCoreNode(image: bitcoinImage, tag: bitcoinTag, pullImage: pullBitcoinImage);
124+
125+
if (pullLndImage)
126+
{
127+
await _client.PullImageAndWaitForCompleted(lndImage, lndTag);
128+
}
129+
130+
if (pullBitcoinImage)
131+
{
132+
await _client.PullImageAndWaitForCompleted(bitcoinImage, bitcoinTag);
133+
}
134+
135+
136+
Builder.AddPolarLNDNode("alice",
137+
[
138+
new LNUnitNetworkDefinition.Channel
139+
{
140+
ChannelSize = 10_000_000, //10MSat
141+
RemoteName = "bob"
142+
},
143+
new LNUnitNetworkDefinition.Channel
144+
{
145+
ChannelSize = 10_000_000, //10MSat
146+
RemoteName = "bob"
147+
},
148+
new LNUnitNetworkDefinition.Channel
149+
{
150+
ChannelSize = 10_000_000, //10MSat
151+
RemoteName = "bob"
152+
},
153+
new LNUnitNetworkDefinition.Channel
154+
{
155+
ChannelSize = 10_000_000, //10MSat
156+
RemoteName = "bob"
157+
}
158+
], imageName: lndImage, tagName: lndTag, pullImage: false, acceptKeysend: true, mapTotmp: false,
159+
postgresDSN: _dbType == "postgres" ? PostgresFixture.LNDConnectionStrings["alice"] : null, lndkSupport: false, nativeSql: _dbType != "boltdb", storeFinalHtlcResolutions: true);
160+
161+
Builder.AddPolarLNDNode("bob",
162+
[
163+
new LNUnitNetworkDefinition.Channel
164+
{
165+
ChannelSize = 10_000_000, //10MSat
166+
RemotePushOnStart = 1_000_000, // 1MSat
167+
RemoteName = "alice"
168+
}
169+
], imageName: lndImage, tagName: lndTag, pullImage: false, acceptKeysend: true, mapTotmp: false,
170+
postgresDSN: _dbType == "postgres" ? PostgresFixture.LNDConnectionStrings["bob"] : null, lndkSupport: false, nativeSql: _dbType != "boltdb");
171+
172+
Builder.AddPolarLNDNode("carol",
173+
[
174+
new LNUnitNetworkDefinition.Channel
175+
{
176+
ChannelSize = 10_000_000, //10MSat
177+
RemotePushOnStart = 1_000_000, // 1MSat
178+
RemoteName = "bob"
179+
},
180+
new LNUnitNetworkDefinition.Channel
181+
{
182+
ChannelSize = 10_000_000, //10MSat
183+
RemotePushOnStart = 1_000_000, // 1MSat
184+
RemoteName = "bob"
185+
},
186+
new LNUnitNetworkDefinition.Channel
187+
{
188+
ChannelSize = 10_000_000, //10MSat
189+
RemotePushOnStart = 1_000_000, // 1MSat
190+
RemoteName = "bob"
191+
},
192+
new LNUnitNetworkDefinition.Channel
193+
{
194+
ChannelSize = 10_000_000, //10MSat
195+
RemotePushOnStart = 1_000_000, // 1MSat
196+
RemoteName = "bob"
197+
}
198+
], imageName: lndImage, tagName: lndTag, pullImage: false, acceptKeysend: true, mapTotmp: false,
199+
postgresDSN: _dbType == "postgres" ? PostgresFixture.LNDConnectionStrings["carol"] : null, lndkSupport: false, nativeSql: _dbType != "boltdb");
200+
201+
await Builder.Build(lndRoot: lndRoot, ectdEnabled:true);
202+
203+
await WaitNodesReady();
204+
await WaitGraphReady();
205+
}
206+
207+
private async Task WaitNodesReady()
208+
{
209+
var a = await Builder.WaitUntilAliasIsServerReady("alice");
210+
var b = await Builder.WaitUntilAliasIsServerReady("bob");
211+
var c = await Builder.WaitUntilAliasIsServerReady("carol");
212+
//Task.WaitAll(a, b, c);
213+
}
214+
215+
private async Task WaitGraphReady(string fromAlias = "alice")
216+
{
217+
var graphReady = false;
218+
while (!graphReady)
219+
{
220+
var graph = await Builder.GetGraphFromAlias(fromAlias);
221+
if (graph.Nodes.Count < 3)
222+
{
223+
"Graph not ready...".Print();
224+
await Task.Delay(250); //let the graph sync
225+
}
226+
else
227+
{
228+
graphReady = true;
229+
}
230+
}
231+
}
232+
233+
234+
public async Task<bool> IsRunning()
235+
{
236+
try
237+
{
238+
var inspect = await _client.Containers.InspectContainerAsync(DbContainerName);
239+
return inspect.State.Running;
240+
}
241+
catch
242+
{
243+
// ignored
244+
}
245+
246+
return false;
247+
}
248+
249+
[Test]
250+
public async Task CheckEctdRunning()
251+
{
252+
var inspect = await _client.Containers.InspectContainerAsync("etcd");
253+
Assert.IsTrue(inspect.State.Running, "Etcd running is not running");
254+
var x = new EtcdClient("http://localhost:2379");
255+
256+
257+
}
258+
259+
[Test]
260+
[Timeout(2000)]
261+
[Category("Version")]
262+
[NonParallelizable]
263+
public async Task CheckLNDVersion()
264+
{
265+
var n = await Builder.WaitUntilAliasIsServerReady("alice");
266+
var info = n.LightningClient.GetInfo(new GetInfoRequest());
267+
info.Version.Print();
268+
}
269+
270+
271+
private readonly MemoryCache _aliasCache = new(new MemoryCacheOptions { SizeLimit = 10000 });
272+
protected readonly string _dbType;
273+
protected readonly string _lndImage;
274+
protected readonly string _tag;
275+
protected readonly string _lndRoot;
276+
protected readonly bool _pullImage;
277+
278+
private async Task<string> ToAlias(LNDNodeConnection c, string remotePubkey)
279+
{
280+
_aliasCache.TryGetValue(remotePubkey, out string alias);
281+
if (alias.IsNullOrEmpty())
282+
try
283+
{
284+
var nodeInfo = await c.LightningClient.GetNodeInfoAsync(new NodeInfoRequest { PubKey = remotePubkey });
285+
_aliasCache.Set(remotePubkey, nodeInfo.Node.Alias,
286+
new MemoryCacheEntryOptions
287+
{
288+
AbsoluteExpirationRelativeToNow = TimeSpan.FromHours(1),
289+
Size = 1
290+
});
291+
return nodeInfo.Node.Alias;
292+
}
293+
catch (Exception e)
294+
{
295+
return remotePubkey;
296+
}
297+
298+
return alias;
299+
}
300+
301+
302+
}
Lines changed: 20 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -0,0 +1,20 @@
1+
2+
3+
namespace LNUnit.Tests.Fixture;
4+
5+
//[Ignore("only local")]
6+
//[TestFixture("postgres", "lightninglabs/lnd", "v0.18.3-beta", "/root/.lnd", true)]
7+
[TestFixture("postgres", "custom_lnd", "latest", "/home/lnd/.lnd", false)]
8+
public class EtcdLightningFixturePostgres : LNUnit.Tests.Abstract.EctdLightningAbstractTests
9+
{
10+
public EtcdLightningFixturePostgres(string dbType = "postgres",
11+
string lndImage = "custom_lnd",
12+
string tag = "latest",
13+
string lndRoot = "/root/.lnd",
14+
bool pullImage = false
15+
) : base(dbType, lndImage, tag, lndRoot, pullImage)
16+
{
17+
18+
}
19+
}
20+

LNUnit.Tests/LNUnit.Tests.csproj

Lines changed: 1 addition & 5 deletions
Original file line numberDiff line numberDiff line change
@@ -12,11 +12,7 @@
1212

1313
<ItemGroup>
1414
<PackageReference Include="Docker.DotNet" Version="3.125.15"/>
15-
<PackageReference Include="Google.Protobuf" Version="3.27.3" />
16-
<PackageReference Include="Grpc.Net.ClientFactory" Version="2.71.0" />
17-
<PackageReference Include="Grpc.Net.Client" Version="2.71.0" />
18-
<PackageReference Include="Grpc.Net.Common" Version="2.71.0" />
19-
15+
<PackageReference Include="dotnet-etcd" Version="8.0.1" />
2016
<PackageReference Include="JunitXml.TestLogger" Version="3.1.12" />
2117
<PackageReference Include="Microsoft.AspNetCore.Mvc.Testing" Version="9.0.9" />
2218
<PackageReference Include="Microsoft.Data.Sqlite" Version="9.0.9" />

LNUnit/Setup/DockerHelper.cs

Lines changed: 12 additions & 6 deletions
Original file line numberDiff line numberDiff line change
@@ -1,5 +1,6 @@
11
using Docker.DotNet;
22
using Docker.DotNet.Models;
3+
using ServiceStack;
34
using SharpCompress.Common;
45
using SharpCompress.Writers;
56

@@ -15,7 +16,7 @@ public static class DockerHelper
1516
/// <param name="client"></param>
1617
/// <param name="imageName"></param>
1718
/// <param name="tag"></param>
18-
public static async Task PullImageAndWaitForCompleted(this DockerClient client, string imageName, string tag)
19+
public static async Task PullImageAndWaitForCompleted(this DockerClient client, string imageName, string tag, string? repo = null)
1920
{
2021
var done = false;
2122
var p = new Progress<JSONMessage>();
@@ -24,12 +25,17 @@ public static async Task PullImageAndWaitForCompleted(this DockerClient client,
2425
if (message.Status.StartsWith("Digest: sha256:") || message.Status.EndsWith("Already exists"))
2526
done = true;
2627
};
28+
var i = new ImagesCreateParameters
29+
{
30+
FromImage = imageName,
31+
Tag = tag
32+
};
33+
if (!repo.IsNullOrEmpty())
34+
{
35+
i.Repo = repo;
36+
}
2737
await client.Images.CreateImageAsync(
28-
new ImagesCreateParameters
29-
{
30-
FromImage = imageName,
31-
Tag = tag
32-
},
38+
i,
3339
// new AuthConfig
3440
// {
3541
// Email = "test@example.com",

0 commit comments

Comments
 (0)