Skip to content

Commit b52aa03

Browse files
Wallet moved to litedb (#179)
* Adding a wallet store based on litedb * Fix all build errors apart for tests * Wallet uses litedb fully * Wallet db file per wallet * Fix more tests and generate test chains * Fix some tests * Fix some more tests * Fix some more tests * Solution compiles * Wallet manager tests passing * Wallet tip in store and fix tests * Fixing more tests * All tests pass * Upgrade litedb - all tests pass * Fix integration tests * Improve wallet perf * move wallet db to its own folder * move wallet to its own db * Rename TransactionData to TransactionOutputData * Rename wallet files * Fix tests * Check for consumers on broadcaster * Add consumer count to event consumer interface * uniform wallet value format * Fix wallet backup bug * Cold stake page optimization * Fix bug * fix calculation error on balance * delete unused method totalUnconfirmedBalance * More optimization and add account index to trx store * Create litedb queries to optimize balance checks * Only calculate spendable amounts when its used Co-authored-by: Hunter <thecryptohunter@protonmail.com>
1 parent 6c84da2 commit b52aa03

87 files changed

Lines changed: 2853 additions & 1788 deletions

File tree

Some content is hidden

Large Commits have some content hidden by default. Use the searchbox below for content that may be hidden.

src/Blockcore/Blockcore.csproj

Lines changed: 1 addition & 1 deletion
Original file line numberDiff line numberDiff line change
@@ -17,7 +17,7 @@
1717
<ItemGroup>
1818
<PackageReference Include="ConcurrentHashSet" Version="1.1.0" />
1919
<PackageReference Include="DBreeze" Version="1.95.0" />
20-
<PackageReference Include="LiteDB" Version="4.1.4" />
20+
<PackageReference Include="LiteDB" Version="5.0.8" />
2121
<PackageReference Include="Microsoft.AspNetCore.Mvc.Versioning" Version="4.1.1" />
2222
<PackageReference Include="Microsoft.Extensions.Http" Version="3.1.4" />
2323
<PackageReference Include="NLog" Version="4.7.0" />

src/Blockcore/Broadcasters/BroadcasterBase.cs

Lines changed: 6 additions & 3 deletions
Original file line numberDiff line numberDiff line change
@@ -40,14 +40,17 @@ public void Init(ClientEventBroadcasterSettings broadcasterSettings)
4040
$"Broadcast {this.GetType().Name}",
4141
async token =>
4242
{
43-
foreach (EventBase clientEvent in this.GetMessages())
43+
if (this.eventsHub.HasConsumers)
4444
{
45-
this.eventsHub.OnEvent(clientEvent);
45+
foreach (EventBase clientEvent in this.GetMessages())
46+
{
47+
this.eventsHub.OnEvent(clientEvent);
48+
}
4649
}
4750
},
4851
this.nodeLifetime.ApplicationStopping,
4952
repeatEvery: TimeSpan.FromSeconds(Math.Max(broadcasterSettings.BroadcastFrequencySeconds, 5)),
50-
startAfter: TimeSpans.FiveSeconds);
53+
startAfter: TimeSpans.TenSeconds);
5154
}
5255

5356
protected abstract IEnumerable<EventBase> GetMessages();

src/Blockcore/Broadcasters/IEventsSubscriptionService.cs

Lines changed: 2 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -9,6 +9,8 @@ public interface IEventsSubscriptionService
99
{
1010
void Init();
1111

12+
bool HasConsumers { get; }
13+
1214
void Subscribe(string id, string name);
1315

1416
void Unsubscribe(string id, string name);

src/Blockcore/Configuration/DataFolder.cs

Lines changed: 4 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -33,6 +33,7 @@ public DataFolder(string path)
3333
this.WalletPath = Path.Combine(path);
3434
this.LogPath = Path.Combine(path, "logs");
3535
this.ApplicationsPath = Path.Combine(path, "apps");
36+
this.WalletFolderPath = Path.Combine(path, "txdb");
3637
this.DnsMasterFilePath = path;
3738
this.SmartContractStatePath = Path.Combine(path, "contracts");
3839
this.ProvenBlockHeaderPath = Path.Combine(path, "provenheaders");
@@ -77,6 +78,9 @@ public DataFolder(string path)
7778
/// <seealso cref="Features.Wallet.WalletManager.LoadWallet"/>
7879
public string WalletPath { get; internal set; }
7980

81+
/// <summary>Path to wallet folder.</summary>
82+
public string WalletFolderPath { get; internal set; }
83+
8084
/// <summary>Path to log files.</summary>
8185
/// <seealso cref="Logging.LoggingConfiguration"/>
8286
public string LogPath { get; internal set; }

src/Blockcore/Utilities/FileStorage.cs

Lines changed: 38 additions & 1 deletion
Original file line numberDiff line numberDiff line change
@@ -193,6 +193,43 @@ public T LoadByFileName(string fileName)
193193
return JsonConvert.DeserializeObject<T>(File.ReadAllText(filePath));
194194
}
195195

196+
/// <summary>
197+
/// Creates a copy of legacy wallets in to v2 wallets.
198+
/// </summary>
199+
/// <param name="fileExtension">The extension.</param>
200+
/// <returns>A list of objects of type <see cref="T"/> whose persisted files have the specified extension. </returns>
201+
public IEnumerable<T> CloneLegacyWallet(string fileExtension)
202+
{
203+
Guard.NotEmpty(fileExtension, nameof(fileExtension));
204+
205+
// Get the paths of files with the extension
206+
IEnumerable<string> filesPaths = this.GetFilesPaths(fileExtension);
207+
208+
var files = new List<T>();
209+
foreach (string filePath in filesPaths)
210+
{
211+
if (File.ReadAllText(filePath).Contains("blockLocator"))
212+
{
213+
// This is an old legacy wallet, back it up and migrate.
214+
215+
string fileName = Path.GetFileName(filePath);
216+
string newFileName = fileName.Replace(fileExtension, $"{fileExtension}.backup");
217+
string newFilePath = Path.Combine(this.FolderPath, newFileName);
218+
219+
if (!this.Exists(newFilePath))
220+
{
221+
File.Copy(filePath, newFilePath);
222+
223+
// Upgrade the wallet
224+
T loadedFile = this.LoadByFileName(fileName);
225+
this.SaveToFile(loadedFile, fileName);
226+
}
227+
}
228+
}
229+
230+
return files;
231+
}
232+
196233
/// <summary>
197234
/// Loads all the objects that have file with the specified extension.
198235
/// </summary>
@@ -218,4 +255,4 @@ public IEnumerable<T> LoadByFileExtension(string fileExtension)
218255
return files;
219256
}
220257
}
221-
}
258+
}

src/Blockcore/Utilities/HashHeightPair.cs

Lines changed: 41 additions & 1 deletion
Original file line numberDiff line numberDiff line change
@@ -1,4 +1,5 @@
1-
using NBitcoin;
1+
using System;
2+
using NBitcoin;
23

34
namespace Blockcore.Utilities
45
{
@@ -94,5 +95,44 @@ public override int GetHashCode()
9495
{
9596
return base.GetHashCode();
9697
}
98+
99+
public static bool TryParse(string str, out HashHeightPair result)
100+
{
101+
Guard.NotEmpty(str, nameof(str));
102+
103+
result = null;
104+
105+
string[] splitted = str.Split('-');
106+
if (splitted.Length != 2)
107+
{
108+
return false;
109+
}
110+
111+
if (!int.TryParse(splitted[0], out int index))
112+
{
113+
return false;
114+
}
115+
116+
if (!uint256.TryParse(splitted[1], out uint256 hash))
117+
{
118+
return false;
119+
}
120+
121+
result = new HashHeightPair(hash, index);
122+
123+
return true;
124+
}
125+
126+
public static HashHeightPair Parse(string str)
127+
{
128+
HashHeightPair result;
129+
130+
if (TryParse(str, out result))
131+
{
132+
return result;
133+
}
134+
135+
throw new FormatException("The format of the outpoint is incorrect");
136+
}
97137
}
98138
}
Lines changed: 46 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -0,0 +1,46 @@
1+
using System;
2+
using System.IO;
3+
using NBitcoin;
4+
using Newtonsoft.Json;
5+
6+
namespace Blockcore.Utilities.JsonConverters
7+
{
8+
/// <summary>
9+
/// Converter used to convert a <see cref="OutPoint"/> to and from JSON.
10+
/// </summary>
11+
/// <seealso cref="Newtonsoft.Json.JsonConverter" />
12+
public class OutPointJsonConverter : JsonConverter
13+
{
14+
/// <inheritdoc />
15+
public override bool CanConvert(Type objectType)
16+
{
17+
return typeof(OutPoint) == objectType;
18+
}
19+
20+
/// <inheritdoc />
21+
public override object ReadJson(JsonReader reader, Type objectType, object existingValue, JsonSerializer serializer)
22+
{
23+
if (reader.TokenType == JsonToken.Null)
24+
return null;
25+
26+
try
27+
{
28+
return OutPoint.Parse((string)reader.Value);
29+
}
30+
catch (EndOfStreamException)
31+
{
32+
}
33+
catch (FormatException)
34+
{
35+
}
36+
37+
throw new JsonObjectException("Invalid bitcoin object of type " + objectType.Name, reader);
38+
}
39+
40+
/// <inheritdoc />
41+
public override void WriteJson(JsonWriter writer, object value, JsonSerializer serializer)
42+
{
43+
writer.WriteValue(value.ToString());
44+
}
45+
}
46+
}

src/Features/Blockcore.Features.BlockStore/AddressIndexing/AddressIndexRepository.cs

Lines changed: 2 additions & 2 deletions
Original file line numberDiff line numberDiff line change
@@ -13,7 +13,7 @@ public class AddressIndexRepository : MemorySizeCache<string, AddressIndexerData
1313
{
1414
private const string DbAddressDataKey = "AddrData";
1515

16-
private readonly LiteCollection<AddressIndexerData> addressIndexerDataCollection;
16+
private readonly ILiteCollection<AddressIndexerData> addressIndexerDataCollection;
1717

1818
private readonly ILogger logger;
1919

@@ -58,7 +58,7 @@ public List<string> GetAddressesHigherThanHeight(int height)
5858
this.SaveAllItems();
5959

6060
// Need to specify index name explicitly so that it gets used for the query.
61-
IEnumerable<AddressIndexerData> affectedAddresses = this.addressIndexerDataCollection.Find(Query.GT("BalanceChangedHeightIndex", height));
61+
IEnumerable<AddressIndexerData> affectedAddresses = this.addressIndexerDataCollection.Find(a => a.BalanceChanges.Select(ab => ab.BalanceChangedHeight).Any(ab => ab > height));
6262

6363
// Per LiteDb documentation:
6464
// "Returning an IEnumerable your code still connected to datafile.

src/Features/Blockcore.Features.BlockStore/AddressIndexing/AddressIndexer.cs

Lines changed: 3 additions & 5 deletions
Original file line numberDiff line numberDiff line change
@@ -18,7 +18,6 @@
1818
using LiteDB;
1919
using Microsoft.Extensions.Logging;
2020
using NBitcoin;
21-
using FileMode = LiteDB.FileMode;
2221
using Script = NBitcoin.Script;
2322

2423
namespace Blockcore.Features.BlockStore.AddressIndexing
@@ -83,7 +82,7 @@ public class AddressIndexer : IAddressIndexer
8382

8483
private LiteDatabase db;
8584

86-
private LiteCollection<AddressIndexerTipData> tipDataStore;
85+
private ILiteCollection<AddressIndexerTipData> tipDataStore;
8786

8887
/// <summary>A mapping between addresses and their balance changes.</summary>
8988
/// <remarks>All access should be protected by <see cref="lockObject"/>.</remarks>
@@ -176,8 +175,7 @@ public void Initialize()
176175

177176
string dbPath = Path.Combine(this.dataFolder.RootPath, AddressIndexerDatabaseFilename);
178177

179-
FileMode fileMode = RuntimeInformation.IsOSPlatform(OSPlatform.OSX) ? FileMode.Exclusive : FileMode.Shared;
180-
this.db = new LiteDatabase(new ConnectionString() { Filename = dbPath, Mode = fileMode });
178+
this.db = new LiteDatabase(new ConnectionString() { Filename = dbPath, Upgrade = true });
181179

182180
this.addressIndexRepository = new AddressIndexRepository(this.db, this.loggerFactory);
183181

@@ -656,4 +654,4 @@ public void Dispose()
656654
this.db?.Dispose();
657655
}
658656
}
659-
}
657+
}

src/Features/Blockcore.Features.BlockStore/AddressIndexing/AddressIndexerOutpointsRepository.cs

Lines changed: 3 additions & 3 deletions
Original file line numberDiff line numberDiff line change
@@ -17,11 +17,11 @@ public sealed class AddressIndexerOutpointsRepository : MemoryCache<string, OutP
1717

1818
/// <summary>Represents the output collection.</summary>
1919
/// <remarks>Should be protected by <see cref="LockObject"/></remarks>
20-
private readonly LiteCollection<OutPointData> addressIndexerOutPointData;
20+
private readonly ILiteCollection<OutPointData> addressIndexerOutPointData;
2121

2222
/// <summary>Represents the rewind data collection.</summary>
2323
/// <remarks>Should be protected by <see cref="LockObject"/></remarks>
24-
private readonly LiteCollection<AddressIndexerRewindData> addressIndexerRewindData;
24+
private readonly ILiteCollection<AddressIndexerRewindData> addressIndexerRewindData;
2525

2626
private readonly ILogger logger;
2727

@@ -158,4 +158,4 @@ protected override bool IsCacheFullLocked(CacheItem item)
158158
return this.totalSize + 1 > this.maxCacheItems;
159159
}
160160
}
161-
}
161+
}

0 commit comments

Comments
 (0)