public IndexBuilderService(RPCClient rpc, TrustedNodeNotifyingBehavior trustedNodeNotifyingBehavior, string indexFilePath, string bech32UtxoSetFilePath) { RpcClient = Guard.NotNull(nameof(rpc), rpc); TrustedNodeNotifyingBehavior = Guard.NotNull(nameof(trustedNodeNotifyingBehavior), trustedNodeNotifyingBehavior); IndexFilePath = Guard.NotNullOrEmptyOrWhitespace(nameof(indexFilePath), indexFilePath); Bech32UtxoSetFilePath = Guard.NotNullOrEmptyOrWhitespace(nameof(bech32UtxoSetFilePath), bech32UtxoSetFilePath); Bech32UtxoSet = new Dictionary <OutPoint, Script>(); Bech32UtxoSetHistory = new List <ActionHistoryHelper>(capacity: 100); Index = new List <FilterModel>(); IndexLock = new AsyncLock(); StartingFilter = StartingFilters.GetStartingFilter(RpcClient.Network); StartingHeight = StartingFilters.GetStartingHeight(RpcClient.Network); _running = 0; IoHelpers.EnsureContainingDirectoryExists(IndexFilePath); if (File.Exists(IndexFilePath)) { if (RpcClient.Network == Network.RegTest) { File.Delete(IndexFilePath); // RegTest is not a global ledger, better to delete it. } else { var height = StartingHeight; foreach (var line in File.ReadAllLines(IndexFilePath)) { var filter = FilterModel.FromHeightlessLine(line, height); height++; Index.Add(filter); } } } IoHelpers.EnsureContainingDirectoryExists(bech32UtxoSetFilePath); if (File.Exists(bech32UtxoSetFilePath)) { if (RpcClient.Network == Network.RegTest) { File.Delete(bech32UtxoSetFilePath); // RegTest is not a global ledger, better to delete it. } else { foreach (var line in File.ReadAllLines(Bech32UtxoSetFilePath)) { var parts = line.Split(':'); var txHash = new uint256(parts[0]); var nIn = int.Parse(parts[1]); var script = new Script(ByteHelpers.FromHex(parts[2]), true); Bech32UtxoSet.Add(new OutPoint(txHash, nIn), script); } } } TrustedNodeNotifyingBehavior.BlockInv += TrustedNodeNotifyingBehavior_BlockInv; }
public void ShouldFindNeverUsedKey() { var filters = new[] { FilterModel.FromHeightlessLine("000000000000de90e633e1b1330859842795d39018d033044e8b003e8cbf58e4:050a2f58828c9820642769ae320a40", 0) }; var unusedKeyIndex = ExtPubKeyExplorer.GetUnusedBech32Keys(1, true, ExtPubKey.GetWif(Network.Main), filters).First().ScriptPubKey.ToCompressedBytes(); Assert.Equal(DerivateScript(true, 0), unusedKeyIndex); }
public static FilterModel GetStartingFilter(Network network) { if (network == Network.Main) { return(FilterModel.FromHeightlessLine("0000000000000000001c8018d9cb3b742ef25114f27563e3fc4a1902167f9893:02832810ec08a0", GetStartingHeight(network))); } if (network == Network.TestNet) { return(FilterModel.FromHeightlessLine("00000000000f0d5edcaeba823db17f366be49a80d91d15b77747c2e017b8c20a:017821b8", GetStartingHeight(network))); } if (network == Network.RegTest) { return(FilterModel.FromHeightlessLine("0f9188f13cb7b2c71f2a335e3a4fc328bf5beb436012afca590b1a11466e2206", GetStartingHeight(network))); } throw new NotSupportedException($"{network} is not supported."); }
public async Task ForeachFiltersAsync(Func <FilterModel, Task> todo, Height fromHeight) { using (await MatureIndexFileManager.Mutex.LockAsync()) using (await IndexLock.LockAsync()) { var firstImmatureHeight = ImmatureFilters.FirstOrDefault()?.BlockHeight; if (!firstImmatureHeight.HasValue || firstImmatureHeight.Value > fromHeight) { if (MatureIndexFileManager.Exists()) { Height height = StartingHeight; using (var sr = MatureIndexFileManager.OpenText(16384)) { while (!sr.EndOfStream) { var line = await sr.ReadLineAsync(); if (firstImmatureHeight == height) { break; // Let's use our the immature filters from here on. The content is the same, just someone else modified the file. } if (height < fromHeight.Value) { height++; continue; } var filter = FilterModel.FromHeightlessLine(line, height); await todo(filter); height++; } } } } foreach (FilterModel filter in ImmatureFilters) { await todo(filter); } } }
private void ProcessLine(Height height, string line, bool enqueue) { var filter = FilterModel.FromHeightlessLine(line, height); ProcessFilter(filter, enqueue); }