public async Task InitializeAsync(string workFolderPath, Network network) { using (BenchmarkLogger.Measure()) { WorkFolderPath = Guard.NotNullOrEmptyOrWhitespace(nameof(workFolderPath), workFolderPath, trim: true); IoHelpers.EnsureDirectoryExists(WorkFolderPath); Network = Guard.NotNull(nameof(network), network); IndexStore = new IndexStore(); TransactionStore = new AllTransactionStore(); var networkWorkFolderPath = Path.Combine(WorkFolderPath, Network.ToString()); var indexStoreFolderPath = Path.Combine(networkWorkFolderPath, "IndexStore"); SmartHeaderChain = new SmartHeaderChain(); MempoolService = new MempoolService(); var initTasks = new[] { IndexStore.InitializeAsync(indexStoreFolderPath, Network, SmartHeaderChain), TransactionStore.InitializeAsync(networkWorkFolderPath, Network) }; await Task.WhenAll(initTasks).ConfigureAwait(false); IsInitialized = true; } }
public async Task DoesntUpdateAsync(Network network) { await using var txStore = new AllTransactionStore(PrepareWorkDir(), network); await txStore.InitializeAsync(ensureBackwardsCompatibility : false); var tx = Common.RandomSmartTransaction(); Assert.False(txStore.TryUpdate(tx)); // Assert TryUpdate didn't modify anything. Assert.NotNull(txStore.ConfirmedStore); Assert.NotNull(txStore.MempoolStore); Assert.Empty(txStore.GetTransactions()); Assert.Empty(txStore.GetTransactionHashes()); Assert.Empty(txStore.MempoolStore.GetTransactions()); Assert.Empty(txStore.MempoolStore.GetTransactionHashes()); Assert.Empty(txStore.ConfirmedStore.GetTransactions()); Assert.Empty(txStore.ConfirmedStore.GetTransactionHashes()); uint256 txHash = Common.RandomSmartTransaction().GetHash(); Assert.False(txStore.Contains(txHash)); Assert.True(txStore.IsEmpty()); Assert.False(txStore.TryGetTransaction(txHash, out _)); }
public async Task CorrectsMempoolConfSeparateDupAsync() { PrepareTestEnv(out string dir, out Network network, out string mempoolFile, out string txFile, out SmartTransaction uTx1, out SmartTransaction uTx2, out SmartTransaction uTx3, out SmartTransaction cTx1, out SmartTransaction cTx2, out SmartTransaction cTx3); // Duplication in mempoool and confirmedtxs. var mempoolFileContent = new[] { uTx1.ToLine(), uTx2.ToLine(), uTx3.ToLine(), uTx2.ToLine() }; var txFileContent = new[] { cTx1.ToLine(), cTx2.ToLine(), cTx3.ToLine(), cTx3.ToLine() }; await File.WriteAllLinesAsync(mempoolFile, mempoolFileContent); await File.WriteAllLinesAsync(txFile, txFileContent); var txStore = new AllTransactionStore(); await txStore.InitializeAsync(dir, network, ensureBackwardsCompatibility : false); Assert.Equal(6, txStore.GetTransactions().Count()); Assert.Equal(6, txStore.GetTransactionHashes().Count()); Assert.Equal(3, txStore.MempoolStore.GetTransactions().Count()); Assert.Equal(3, txStore.MempoolStore.GetTransactionHashes().Count()); Assert.Equal(3, txStore.ConfirmedStore.GetTransactions().Count()); Assert.Equal(3, txStore.ConfirmedStore.GetTransactionHashes().Count()); }
public Global(string dataDir, string torLogsFile, Config config, UiConfig uiConfig, WalletManager walletManager) { using (BenchmarkLogger.Measure()) { StoppingCts = new CancellationTokenSource(); DataDir = dataDir; Config = config; UiConfig = uiConfig; TorSettings = new TorSettings(DataDir, torLogsFile, distributionFolderPath: EnvironmentHelpers.GetFullBaseDirectory()); Logger.InitializeDefaults(Path.Combine(DataDir, "Logs.txt")); HostedServices = new HostedServices(); WalletManager = walletManager; LegalDocuments = LegalDocuments.TryLoadAgreed(DataDir); WalletManager.OnDequeue += WalletManager_OnDequeue; WalletManager.WalletRelevantTransactionProcessed += WalletManager_WalletRelevantTransactionProcessed; var networkWorkFolderPath = Path.Combine(DataDir, "BitcoinStore", Network.ToString()); var transactionStore = new AllTransactionStore(networkWorkFolderPath, Network); var indexStore = new IndexStore(Path.Combine(networkWorkFolderPath, "IndexStore"), Network, new SmartHeaderChain()); var mempoolService = new MempoolService(); var blocks = new FileSystemBlockRepository(Path.Combine(networkWorkFolderPath, "Blocks"), Network); BitcoinStore = new BitcoinStore(indexStore, transactionStore, mempoolService, blocks); WasabiClientFactory wasabiClientFactory = Config.UseTor ? new WasabiClientFactory(Config.TorSocks5EndPoint, backendUriGetter: () => Config.GetCurrentBackendUri()) : new WasabiClientFactory(torEndPoint: null, backendUriGetter: () => Config.GetFallbackBackendUri()); Synchronizer = new WasabiSynchronizer(Network, BitcoinStore, wasabiClientFactory); } }
public async Task CanInitializeEmptyAsync(Network network) { var dir = PrepareWorkDir(); await using var txStore = new AllTransactionStore(dir, network); await txStore.InitializeAsync(ensureBackwardsCompatibility : false); Assert.NotNull(txStore.ConfirmedStore); Assert.NotNull(txStore.MempoolStore); Assert.Empty(txStore.GetTransactions()); Assert.Empty(txStore.GetTransactionHashes()); Assert.Empty(txStore.MempoolStore.GetTransactions()); Assert.Empty(txStore.MempoolStore.GetTransactionHashes()); Assert.Empty(txStore.ConfirmedStore.GetTransactions()); Assert.Empty(txStore.ConfirmedStore.GetTransactionHashes()); uint256 txHash = Common.RandomSmartTransaction().GetHash(); Assert.False(txStore.Contains(txHash)); Assert.True(txStore.IsEmpty()); Assert.False(txStore.TryGetTransaction(txHash, out _)); var mempoolFile = Path.Combine(dir, "Mempool", "Transactions.dat"); var txFile = Path.Combine(dir, "ConfirmedTransactions", Constants.ConfirmedTransactionsVersion, "Transactions.dat"); var mempoolContent = await File.ReadAllBytesAsync(mempoolFile); var txContent = await File.ReadAllBytesAsync(txFile); Assert.True(File.Exists(mempoolFile)); Assert.True(File.Exists(txFile)); Assert.Empty(mempoolContent); Assert.Empty(txContent); }
public static async Task <(string password, IRPCClient rpc, Network network, Coordinator coordinator, ServiceConfiguration serviceConfiguration, BitcoinStore bitcoinStore, Backend.Global global)> InitializeTestEnvironmentAsync( RegTestFixture regTestFixture, int numberOfBlocksToGenerate, [CallerFilePath] string callerFilePath = "", [CallerMemberName] string callerMemberName = "") { var global = regTestFixture.Global; await AssertFiltersInitializedAsync(regTestFixture, global); // Make sure filters are created on the server side. if (numberOfBlocksToGenerate != 0) { await global.RpcClient.GenerateAsync(numberOfBlocksToGenerate); // Make sure everything is confirmed. } global.Coordinator.UtxoReferee.Clear(); var network = global.RpcClient.Network; var serviceConfiguration = new ServiceConfiguration(MixUntilAnonymitySet.PrivacyLevelSome.ToString(), 2, 21, 50, regTestFixture.BackendRegTestNode.P2pEndPoint, Money.Coins(Constants.DefaultDustThreshold)); var dir = Tests.Common.GetWorkDir(callerFilePath, callerMemberName); var indexStore = new IndexStore(Path.Combine(dir, "indexStore"), network, new SmartHeaderChain()); var transactionStore = new AllTransactionStore(Path.Combine(dir, "transactionStore"), network); var mempoolService = new MempoolService(); var blocks = new FileSystemBlockRepository(Path.Combine(dir, "blocks"), network); var bitcoinStore = new BitcoinStore(indexStore, transactionStore, mempoolService, blocks); await bitcoinStore.InitializeAsync(); return("password", global.RpcClient, network, global.Coordinator, serviceConfiguration, bitcoinStore, global); }
public async Task MempoolNotifiesAsync() { using var services = new HostedServices(); var coreNode = await TestNodeBuilder.CreateAsync(services); await services.StartAllAsync(CancellationToken.None); using var node = await coreNode.CreateNewP2pNodeAsync(); try { var network = coreNode.Network; var rpc = coreNode.RpcClient; var dir = Path.Combine(Global.Instance.DataDir, EnvironmentHelpers.GetCallerFileName(), EnvironmentHelpers.GetMethodName()); var indexStore = new IndexStore(Path.Combine(dir, "indexStore"), network, new SmartHeaderChain()); var transactionStore = new AllTransactionStore(Path.Combine(dir, "transactionStore"), network); var mempoolService = new MempoolService(); var blocks = new FileSystemBlockRepository(Path.Combine(dir, "blocks"), network); var bitcoinStore = new BitcoinStore(indexStore, transactionStore, mempoolService, blocks); await bitcoinStore.InitializeAsync(); await rpc.GenerateAsync(101); node.Behaviors.Add(bitcoinStore.CreateUntrustedP2pBehavior()); node.VersionHandshake(); var addr = new Key().PubKey.GetSegwitAddress(network); var txNum = 10; var eventAwaiter = new EventsAwaiter <SmartTransaction>( h => bitcoinStore.MempoolService.TransactionReceived += h, h => bitcoinStore.MempoolService.TransactionReceived -= h, txNum); var txTasks = new List <Task <uint256> >(); var batch = rpc.PrepareBatch(); for (int i = 0; i < txNum; i++) { txTasks.Add(batch.SendToAddressAsync(addr, Money.Coins(1))); } var batchTask = batch.SendBatchAsync(); var stxs = await eventAwaiter.WaitAsync(TimeSpan.FromSeconds(21)); await batchTask; var hashes = await Task.WhenAll(txTasks); foreach (var stx in stxs) { Assert.Contains(stx.GetHash(), hashes); } } finally { await services.StopAllAsync(CancellationToken.None); node.Disconnect(); await coreNode.TryStopAsync(); } }
public async Task CorrectsMempoolConfBetweenDupAsync() { PrepareTestEnv(out string dir, out Network network, out string mempoolFile, out string txFile, out SmartTransaction uTx1, out SmartTransaction uTx2, out SmartTransaction uTx3, out SmartTransaction cTx1, out SmartTransaction cTx2, out SmartTransaction cTx3); // Duplication between mempool and confirmed txs. var mempoolFileContent = new[] { uTx1.ToLine(), uTx2.ToLine(), uTx3.ToLine(), new SmartTransaction(cTx1.Transaction, Height.Mempool).ToLine() }; var txFileContent = new[] { cTx1.ToLine(), cTx2.ToLine(), cTx3.ToLine(), new SmartTransaction(uTx1.Transaction, new Height(2)).ToLine() }; await File.WriteAllLinesAsync(mempoolFile, mempoolFileContent); await File.WriteAllLinesAsync(txFile, txFileContent); await using var txStore = new AllTransactionStore(dir, network); await txStore.InitializeAsync(ensureBackwardsCompatibility : false); Assert.Equal(6, txStore.GetTransactions().Count()); Assert.Equal(2, txStore.MempoolStore.GetTransactions().Count()); Assert.Equal(4, txStore.ConfirmedStore.GetTransactions().Count()); }
public async Task ReorgSameBlockAgainAsync() { int blocks = 300; int transactionsPerBlock = 3; string dir = PrepareWorkDir(); var network = Network.Main; await using var txStore = new AllTransactionStore(dir, network); await txStore.InitializeAsync(ensureBackwardsCompatibility : false); foreach (var height in Enumerable.Range(1, blocks)) { var blockHash = RandomUtils.GetUInt256(); foreach (var n in Enumerable.Range(0, transactionsPerBlock)) { txStore.AddOrUpdate(CreateTransaction(height, blockHash)); } } var storedTxs = txStore.GetTransactions(); Assert.Equal(blocks * transactionsPerBlock, storedTxs.Count()); var newestConfirmedTx = storedTxs.Last(); var tipHeight = blocks; var tipHash = newestConfirmedTx.BlockHash; Assert.Equal(tipHeight, newestConfirmedTx.Height.Value); // reorgs non-existing block var reorgedTxs = txStore.ReleaseToMempoolFromBlock(RandomUtils.GetUInt256()); Assert.Empty(reorgedTxs); // reorgs most recent block Assert.NotNull(tipHash); reorgedTxs = txStore.ReleaseToMempoolFromBlock(tipHash !); Assert.Equal(3, reorgedTxs.Count()); Assert.All(reorgedTxs, tx => Assert.False(tx?.Confirmed)); Assert.All(reorgedTxs, tx => Assert.True(txStore.TryGetTransaction(tx.GetHash(), out _))); Assert.False(txStore.TryGetTransaction(tipHash !, out _)); Assert.DoesNotContain(tipHash, txStore.GetTransactionHashes()); // reorgs the same block again reorgedTxs = txStore.ReleaseToMempoolFromBlock(tipHash !); Assert.Empty(reorgedTxs); Assert.False(txStore.TryGetTransaction(tipHash !, out _)); Assert.DoesNotContain(tipHash, txStore.GetTransactionHashes()); // reorgs deep block var oldestConfirmedTx = storedTxs.First(); var firstBlockHash = oldestConfirmedTx.BlockHash; // What to do here reorgedTxs = txStore.ReleaseToMempoolFromBlock(firstBlockHash !); Assert.NotEmpty(reorgedTxs); }
public BitcoinStore( IndexStore indexStore, AllTransactionStore transactionStore, MempoolService mempoolService) { IndexStore = indexStore; TransactionStore = transactionStore; MempoolService = mempoolService; }
/// <param name="allowUnconfirmed">Allow to spend unconfirmed transactions, if necessary.</param> public TransactionFactory(Network network, KeyManager keyManager, ICoinsView coins, AllTransactionStore transactionStore, string password = "", bool allowUnconfirmed = false) { Network = network; KeyManager = keyManager; Coins = coins; TransactionStore = transactionStore; Password = password; AllowUnconfirmed = allowUnconfirmed; }
public BitcoinStore( IndexStore indexStore, AllTransactionStore transactionStore, MempoolService mempoolService, IRepository <uint256, Block> blockRepository) { IndexStore = indexStore; TransactionStore = transactionStore; MempoolService = mempoolService; BlockRepository = blockRepository; }
public TransactionProcessor( AllTransactionStore transactionStore, KeyManager keyManager, Money dustThreshold, int privacyLevelThreshold = 100) { TransactionStore = Guard.NotNull(nameof(transactionStore), transactionStore); KeyManager = Guard.NotNull(nameof(keyManager), keyManager); DustThreshold = Guard.NotNull(nameof(dustThreshold), dustThreshold); Coins = new CoinsRegistry(privacyLevelThreshold); }
public TransactionProcessor( AllTransactionStore transactionStore, KeyManager keyManager, ObservableConcurrentHashSet <SmartCoin> coins, Money dustThreshold) { TransactionStore = Guard.NotNull(nameof(transactionStore), transactionStore); KeyManager = Guard.NotNull(nameof(keyManager), keyManager); Coins = Guard.NotNull(nameof(coins), coins); DustThreshold = Guard.NotNull(nameof(dustThreshold), dustThreshold); }
public BitcoinStore( string workFolderPath, Network network, IndexStore indexStore, AllTransactionStore transactionStore, MempoolService mempoolService) { WorkFolderPath = Guard.NotNullOrEmptyOrWhitespace(nameof(workFolderPath), workFolderPath, trim: true); IoHelpers.EnsureDirectoryExists(WorkFolderPath); Network = Guard.NotNull(nameof(network), network); IndexStore = indexStore; TransactionStore = transactionStore; MempoolService = mempoolService; }
private async Task <TransactionProcessor> CreateTransactionProcessorAsync([CallerMemberName] string callerName = "") { var keyManager = KeyManager.CreateNew(out _, "password"); keyManager.AssertCleanKeysIndexed(); var txStore = new AllTransactionStore(); var dir = Path.Combine(Global.Instance.DataDir, callerName, "TransactionStore"); await IoHelpers.DeleteRecursivelyWithMagicDustAsync(dir); await txStore.InitializeAsync(dir, Network.RegTest); return(new TransactionProcessor( txStore, keyManager, Money.Coins(0.0001m))); }
public Global(string dataDir, Config config, UiConfig uiConfig, WalletManager walletManager) { using (BenchmarkLogger.Measure()) { DataDir = dataDir; Config = config; UiConfig = uiConfig; TorSettings = new TorSettings(DataDir, distributionFolderPath: EnvironmentHelpers.GetFullBaseDirectory(), Config.TerminateTorOnExit, Environment.ProcessId); HostedServices = new HostedServices(); WalletManager = walletManager; var networkWorkFolderPath = Path.Combine(DataDir, "BitcoinStore", Network.ToString()); AllTransactionStore = new AllTransactionStore(networkWorkFolderPath, Network); SmartHeaderChain smartHeaderChain = new(maxChainSize : 20_000); IndexStore = new IndexStore(Path.Combine(networkWorkFolderPath, "IndexStore"), Network, smartHeaderChain); var mempoolService = new MempoolService(); var blocks = new FileSystemBlockRepository(Path.Combine(networkWorkFolderPath, "Blocks"), Network); BitcoinStore = new BitcoinStore(IndexStore, AllTransactionStore, mempoolService, blocks); if (Config.UseTor) { BackendHttpClientFactory = new HttpClientFactory(TorSettings.SocksEndpoint, backendUriGetter: () => Config.GetCurrentBackendUri()); ExternalHttpClientFactory = new HttpClientFactory(TorSettings.SocksEndpoint, backendUriGetter: null); } else { BackendHttpClientFactory = new HttpClientFactory(torEndPoint: null, backendUriGetter: () => Config.GetFallbackBackendUri()); ExternalHttpClientFactory = new HttpClientFactory(torEndPoint: null, backendUriGetter: null); } Synchronizer = new WasabiSynchronizer(BitcoinStore, BackendHttpClientFactory); LegalChecker = new(DataDir); TransactionBroadcaster = new TransactionBroadcaster(Network, BitcoinStore, BackendHttpClientFactory, WalletManager); RoundStateUpdaterCircuit = new PersonCircuit(); Cache = new MemoryCache(new MemoryCacheOptions { SizeLimit = 1_000, ExpirationScanFrequency = TimeSpan.FromSeconds(30) });
public Global(string dataDir, string torLogsFile, Config config, UiConfig uiConfig, WalletManager walletManager) { using (BenchmarkLogger.Measure()) { CrashReporter = new CrashReporter(); StoppingCts = new CancellationTokenSource(); DataDir = dataDir; Config = config; UiConfig = uiConfig; TorLogsFile = torLogsFile; Logger.InitializeDefaults(Path.Combine(DataDir, "Logs.txt")); HostedServices = new HostedServices(); WalletManager = walletManager; LegalDocuments = LegalDocuments.TryLoadAgreed(DataDir); WalletManager.OnDequeue += WalletManager_OnDequeue; WalletManager.WalletRelevantTransactionProcessed += WalletManager_WalletRelevantTransactionProcessed; var networkWorkFolderPath = Path.Combine(DataDir, "BitcoinStore", Network.ToString()); var transactionStore = new AllTransactionStore(networkWorkFolderPath, Network); var indexStore = new IndexStore(Path.Combine(networkWorkFolderPath, "IndexStore"), Network, new SmartHeaderChain()); var mempoolService = new MempoolService(); BitcoinStore = new BitcoinStore(indexStore, transactionStore, mempoolService); SingleInstanceChecker = new SingleInstanceChecker(Network); if (Config.UseTor) { Synchronizer = new WasabiSynchronizer(Network, BitcoinStore, () => Config.GetCurrentBackendUri(), Config.TorSocks5EndPoint); } else { Synchronizer = new WasabiSynchronizer(Network, BitcoinStore, Config.GetFallbackBackendUri(), null); } } }
public Global(string dataDir, Config config, UiConfig uiConfig, WalletManager walletManager) { using (BenchmarkLogger.Measure()) { StoppingCts = new CancellationTokenSource(); DataDir = dataDir; Config = config; UiConfig = uiConfig; TorSettings = new TorSettings(DataDir, distributionFolderPath: EnvironmentHelpers.GetFullBaseDirectory(), Config.TerminateTorOnExit, Environment.ProcessId); HostedServices = new HostedServices(); WalletManager = walletManager; WalletManager.OnDequeue += WalletManager_OnDequeue; WalletManager.WalletRelevantTransactionProcessed += WalletManager_WalletRelevantTransactionProcessed; var networkWorkFolderPath = Path.Combine(DataDir, "BitcoinStore", Network.ToString()); var transactionStore = new AllTransactionStore(networkWorkFolderPath, Network); var indexStore = new IndexStore(Path.Combine(networkWorkFolderPath, "IndexStore"), Network, new SmartHeaderChain()); var mempoolService = new MempoolService(); var blocks = new FileSystemBlockRepository(Path.Combine(networkWorkFolderPath, "Blocks"), Network); BitcoinStore = new BitcoinStore(indexStore, transactionStore, mempoolService, blocks); if (Config.UseTor) { BackendHttpClientFactory = new HttpClientFactory(TorSettings.SocksEndpoint, backendUriGetter: () => Config.GetCurrentBackendUri()); ExternalHttpClientFactory = new HttpClientFactory(TorSettings.SocksEndpoint, backendUriGetter: null); } else { BackendHttpClientFactory = new HttpClientFactory(torEndPoint: null, backendUriGetter: () => Config.GetFallbackBackendUri()); ExternalHttpClientFactory = new HttpClientFactory(torEndPoint: null, backendUriGetter: null); } Synchronizer = new WasabiSynchronizer(BitcoinStore, BackendHttpClientFactory); LegalChecker = new(DataDir); TransactionBroadcaster = new TransactionBroadcaster(Network, BitcoinStore, BackendHttpClientFactory, WalletManager); } }
public async Task CorrectsLabelDupAsync() { PrepareTestEnv(out string dir, out Network network, out string mempoolFile, out string txFile, out SmartTransaction uTx1, out SmartTransaction uTx2, out SmartTransaction uTx3, out SmartTransaction cTx1, out SmartTransaction cTx2, out SmartTransaction cTx3); // Duplication is resolved with labels merged. var mempoolFileContent = new[] { new SmartTransaction(uTx1.Transaction, uTx1.Height, label: "buz, qux").ToLine(), new SmartTransaction(uTx2.Transaction, uTx2.Height, label: "buz, qux").ToLine(), new SmartTransaction(uTx2.Transaction, uTx2.Height, label: "foo, bar").ToLine(), uTx3.ToLine(), new SmartTransaction(cTx1.Transaction, Height.Mempool, label: new SmartLabel("buz", "qux")).ToLine() }; var txFileContent = new[] { new SmartTransaction(cTx1.Transaction, cTx1.Height, label: new SmartLabel("foo", "bar")).ToLine(), cTx2.ToLine(), cTx3.ToLine(), new SmartTransaction(uTx1.Transaction, new Height(2), label: "foo, bar").ToLine() }; await File.WriteAllLinesAsync(mempoolFile, mempoolFileContent); await File.WriteAllLinesAsync(txFile, txFileContent); await using var txStore = new AllTransactionStore(dir, network); await txStore.InitializeAsync(ensureBackwardsCompatibility : false); Assert.Equal(6, txStore.GetTransactions().Count()); Assert.Equal(2, txStore.MempoolStore.GetTransactions().Count()); Assert.Equal(4, txStore.ConfirmedStore.GetTransactions().Count()); Assert.True(txStore.MempoolStore.Contains(uTx2.GetHash())); Assert.True(txStore.ConfirmedStore.Contains(uTx1.GetHash())); Assert.True(txStore.ConfirmedStore.Contains(cTx1.GetHash())); Assert.True(txStore.TryGetTransaction(uTx1.GetHash(), out _)); Assert.True(txStore.TryGetTransaction(uTx2.GetHash(), out _)); Assert.True(txStore.TryGetTransaction(cTx1.GetHash(), out _)); }
public async Task TestServicesAsync(string networkString) { await RuntimeParams.LoadAsync(); var network = Network.GetNetwork(networkString); var blocksToDownload = new List <uint256>(); if (network == Network.Main) { blocksToDownload.Add(new uint256("00000000000000000037c2de35bd85f3e57f14ddd741ce6cee5b28e51473d5d0")); blocksToDownload.Add(new uint256("000000000000000000115315a43cb0cdfc4ea54a0e92bed127f4e395e718d8f9")); blocksToDownload.Add(new uint256("00000000000000000011b5b042ad0522b69aae36f7de796f563c895714bbd629")); } else if (network == Network.TestNet) { blocksToDownload.Add(new uint256("0000000097a664c4084b49faa6fd4417055cb8e5aac480abc31ddc57a8208524")); blocksToDownload.Add(new uint256("000000009ed5b82259ecd2aa4cd1f119db8da7a70e7ea78d9c9f603e01f93bcc")); blocksToDownload.Add(new uint256("00000000e6da8c2da304e9f5ad99c079df2c3803b49efded3061ecaf206ddc66")); } else { throw new NotSupportedNetworkException(network); } var dataDir = Common.GetWorkDir(); var indexStore = new IndexStore(Path.Combine(dataDir, "indexStore"), network, new SmartHeaderChain()); await using var transactionStore = new AllTransactionStore(Path.Combine(dataDir, "transactionStore"), network); var mempoolService = new MempoolService(); var blocks = new FileSystemBlockRepository(Path.Combine(dataDir, "blocks"), network); await using BitcoinStore bitcoinStore = new(indexStore, transactionStore, mempoolService, blocks); await bitcoinStore.InitializeAsync(); var addressManagerFolderPath = Path.Combine(dataDir, "AddressManager"); var addressManagerFilePath = Path.Combine(addressManagerFolderPath, $"AddressManager{network}.dat"); var connectionParameters = new NodeConnectionParameters(); AddressManager addressManager; try { addressManager = await NBitcoinHelpers.LoadAddressManagerFromPeerFileAsync(addressManagerFilePath); Logger.LogInfo($"Loaded {nameof(AddressManager)} from `{addressManagerFilePath}`."); } catch (DirectoryNotFoundException) { addressManager = new AddressManager(); } catch (FileNotFoundException) { addressManager = new AddressManager(); } catch (OverflowException) { File.Delete(addressManagerFilePath); addressManager = new AddressManager(); } catch (FormatException) { File.Delete(addressManagerFilePath); addressManager = new AddressManager(); } connectionParameters.TemplateBehaviors.Add(new AddressManagerBehavior(addressManager)); connectionParameters.TemplateBehaviors.Add(bitcoinStore.CreateUntrustedP2pBehavior()); using var nodes = new NodesGroup(network, connectionParameters, requirements: Constants.NodeRequirements); KeyManager keyManager = KeyManager.CreateNew(out _, "password"); HttpClientFactory httpClientFactory = new(Common.TorSocks5Endpoint, backendUriGetter : () => new Uri("http://localhost:12345")); WasabiSynchronizer syncer = new(network, bitcoinStore, httpClientFactory); ServiceConfiguration serviceConfig = new(MixUntilAnonymitySet.PrivacyLevelStrong.ToString(), 2, 21, 50, new IPEndPoint(IPAddress.Loopback, network.DefaultPort), Money.Coins(Constants.DefaultDustThreshold)); CachedBlockProvider blockProvider = new( new P2pBlockProvider(nodes, null, httpClientFactory, serviceConfig, network), bitcoinStore.BlockRepository); using Wallet wallet = Wallet.CreateAndRegisterServices( network, bitcoinStore, keyManager, syncer, nodes, dataDir, new ServiceConfiguration(MixUntilAnonymitySet.PrivacyLevelStrong.ToString(), 2, 21, 50, new IPEndPoint(IPAddress.Loopback, network.DefaultPort), Money.Coins(Constants.DefaultDustThreshold)), syncer, blockProvider); Assert.True(Directory.Exists(blocks.BlocksFolderPath)); try { var mempoolTransactionAwaiter = new EventsAwaiter <SmartTransaction>( h => bitcoinStore.MempoolService.TransactionReceived += h, h => bitcoinStore.MempoolService.TransactionReceived -= h, 3); var nodeConnectionAwaiter = new EventsAwaiter <NodeEventArgs>( h => nodes.ConnectedNodes.Added += h, h => nodes.ConnectedNodes.Added -= h, 3); nodes.Connect(); var downloadTasks = new List <Task <Block> >(); using var cts = new CancellationTokenSource(TimeSpan.FromMinutes(4)); foreach (var hash in blocksToDownload) { downloadTasks.Add(blockProvider.GetBlockAsync(hash, cts.Token)); } await nodeConnectionAwaiter.WaitAsync(TimeSpan.FromMinutes(3)); var i = 0; var hashArray = blocksToDownload.ToArray(); foreach (var block in await Task.WhenAll(downloadTasks)) { Assert.True(File.Exists(Path.Combine(blocks.BlocksFolderPath, hashArray[i].ToString()))); i++; } await mempoolTransactionAwaiter.WaitAsync(TimeSpan.FromMinutes(1)); } finally { // So next test will download the block. foreach (var hash in blocksToDownload) { await blockProvider.BlockRepository.RemoveAsync(hash, CancellationToken.None); } if (wallet is { })
public async Task MempoolNotifiesAsync() { using var services = new HostedServices(); CoreNode coreNode = await TestNodeBuilder.CreateAsync(services); await services.StartAllAsync(); BitcoinStore?bitcoinStore = null; using var node = await coreNode.CreateNewP2pNodeAsync(); try { string dir = Common.GetWorkDir(); var network = coreNode.Network; var rpc = coreNode.RpcClient; var indexStore = new IndexStore(Path.Combine(dir, "indexStore"), network, new SmartHeaderChain()); var transactionStore = new AllTransactionStore(Path.Combine(dir, "transactionStore"), network); var mempoolService = new MempoolService(); var blocks = new FileSystemBlockRepository(Path.Combine(dir, "blocks"), network); // Construct BitcoinStore. bitcoinStore = new BitcoinStore(indexStore, transactionStore, mempoolService, blocks); await bitcoinStore.InitializeAsync(); await rpc.GenerateAsync(blockCount : 101); node.Behaviors.Add(bitcoinStore.CreateUntrustedP2pBehavior()); node.VersionHandshake(); BitcoinWitPubKeyAddress address = new Key().PubKey.GetSegwitAddress(network); // Number of transactions to send. const int TransactionsCount = 10; var eventAwaiter = new EventsAwaiter <SmartTransaction>( subscribe: h => mempoolService.TransactionReceived += h, unsubscribe: h => mempoolService.TransactionReceived -= h, count: TransactionsCount); var txHashesList = new List <Task <uint256> >(); IRPCClient rpcBatch = rpc.PrepareBatch(); // Add to the batch 10 RPC commands: Send 1 coin to the same address. for (int i = 0; i < TransactionsCount; i++) { txHashesList.Add(rpcBatch.SendToAddressAsync(address, Money.Coins(1))); } // Publish the RPC batch. Task rpcBatchTask = rpcBatch.SendBatchAsync(); // Wait until the mempool service receives all the sent transactions. IEnumerable <SmartTransaction> mempoolSmartTxs = await eventAwaiter.WaitAsync(TimeSpan.FromSeconds(30)); await rpcBatchTask; // Collect all the transaction hashes of the sent transactions. uint256[] hashes = await Task.WhenAll(txHashesList); // Check that all the received transaction hashes are in the set of sent transaction hashes. foreach (SmartTransaction tx in mempoolSmartTxs) { Assert.Contains(tx.GetHash(), hashes); } } finally { if (bitcoinStore is { } store) { await store.DisposeAsync(); } await services.StopAllAsync(); node.Disconnect(); await coreNode.TryStopAsync(); } }
public async Task ReorgAsync() { PrepareTestEnv( out string dir, out Network network, out string mempoolFile, out string txFile, out SmartTransaction uTx1, out SmartTransaction uTx2, out SmartTransaction uTx3, out SmartTransaction _, out SmartTransaction cTx2, out SmartTransaction cTx3); // Duplication is resolved with labels merged. var mempoolFileContent = new[] { uTx1.ToLine(), uTx2.ToLine(), uTx3.ToLine(), }; var txFileContent = new[] { cTx2.ToLine(), cTx3.ToLine() }; await File.WriteAllLinesAsync(mempoolFile, mempoolFileContent); await File.WriteAllLinesAsync(txFile, txFileContent); await using var txStore = new AllTransactionStore(dir, network); await txStore.InitializeAsync(ensureBackwardsCompatibility : false); // Two transactions are in the mempool store and unconfirmed. Assert.True(txStore.MempoolStore.TryGetTransaction(uTx1.GetHash(), out SmartTransaction myUnconfirmedTx1)); Assert.False(myUnconfirmedTx1.Confirmed); Assert.True(txStore.MempoolStore.TryGetTransaction(uTx2.GetHash(), out SmartTransaction myUnconfirmedTx2)); Assert.False(myUnconfirmedTx2.Confirmed); // Create the same transaction but now with a Height to make it confirmed. const int ReorgedBlockHeight = 34532; uint256 reorgedBlockHash = new uint256(5); var tx1Confirmed = new SmartTransaction(uTx1.Transaction, new Height(ReorgedBlockHeight), blockHash: reorgedBlockHash, label: "buz, qux"); var tx2Confirmed = new SmartTransaction(uTx2.Transaction, new Height(ReorgedBlockHeight), blockHash: reorgedBlockHash, label: "buz, qux"); Assert.True(txStore.TryUpdate(tx1Confirmed)); Assert.True(txStore.TryUpdate(tx2Confirmed)); // Two transactions are in the ConfirmedStore store and confirmed. Assert.True(txStore.ConfirmedStore.TryGetTransaction(uTx1.GetHash(), out SmartTransaction mytx1)); Assert.False(txStore.MempoolStore.TryGetTransaction(uTx1.GetHash(), out _)); Assert.True(mytx1.Confirmed); Assert.True(txStore.ConfirmedStore.TryGetTransaction(uTx2.GetHash(), out SmartTransaction mytx2)); Assert.False(txStore.MempoolStore.TryGetTransaction(uTx2.GetHash(), out _)); Assert.True(mytx2.Confirmed); // Now reorg. txStore.ReleaseToMempoolFromBlock(reorgedBlockHash); // Two transactions are in the mempool store and unconfirmed. Assert.True(txStore.MempoolStore.TryGetTransaction(uTx1.GetHash(), out SmartTransaction myReorgedTx1)); Assert.False(txStore.ConfirmedStore.TryGetTransaction(uTx1.GetHash(), out _)); Assert.False(myReorgedTx1.Confirmed); Assert.True(txStore.MempoolStore.TryGetTransaction(uTx2.GetHash(), out SmartTransaction myReorgedTx2)); Assert.False(txStore.ConfirmedStore.TryGetTransaction(uTx2.GetHash(), out _)); Assert.False(myReorgedTx2.Confirmed); }
public async Task CorrectsOrderAsync() { string dir = PrepareWorkDir(); var network = Network.TestNet; var mempoolFile = Path.Combine(dir, "Mempool", "Transactions.dat"); var txFile = Path.Combine(dir, "ConfirmedTransactions", Constants.ConfirmedTransactionsVersion, "Transactions.dat"); IoHelpers.EnsureContainingDirectoryExists(mempoolFile); IoHelpers.EnsureContainingDirectoryExists(txFile); var uTx1 = SmartTransaction.FromLine("34fc45781f2ac8e541b6045c2858c755dd2ab85e0ea7b5778b4d0cc191468571:01000000000102d5ae6e2612cdf8932d0e4f684d8ad9afdbca0afffba5c3dc0bf85f2b661bfb670000000000ffffffffbfd117908d5ba536624630519aaea7419605efa33bf1cb50c5ff7441f7b27a5b0100000000ffffffff01c6473d0000000000160014f9d25fe27812c3d35ad3819fcab8b95098effe15024730440220165730f8275434a5484b6aba3c71338a109b7cfd7380fdc18c6791a6afba9dee0220633b3b65313e57bdbd491d17232e6702912869d81461b4c939600d1cc99c06ec012102667c9fb272660cd6c06f853314b53c41da851f86024f9475ff15ea0636f564130247304402205e81562139231274cd7f705772c2810e34b7a291bd9882e6c567553babca9c7402206554ebd60d62a605a27bd4bf6482a533dd8dd35b12dc9d6abfa21738fdf7b57a012102b25dec5439a1aad8d901953a90d16252514a55f547fe2b85bc12e3f72cff1c4b00000000:Mempool::0::1570464578:False", network); var uTx2 = SmartTransaction.FromLine("b5cd5b4431891d913a6fbc0e946798b6f730c8b97f95a5c730c24189bed24ce7:01000000010113145dd6264da43406a0819b6e2d791ec9281322f33944ef034c3307f38c330000000000ffffffff0220a10700000000001600149af662cf9564700b93bd46fac8b51f64f2adad2343a5070000000000160014f1938902267eac1ae527128fe7773657d2b757b900000000:Mempool::0::1555590391:False", network); var uTx3 = SmartTransaction.FromLine("89e6788e63c5966fae0ccf6e85665ec62754f982b9593d7e3c4b78ac0e93208d:01000000000101f3e7c1bce1e0566800d8e6cae8f0d771a2ace8939cc6be7c8c21b05e590969530000000000ffffffff01cc2b0f0000000000160014e0ff6f42032bbfda63fabe0832b4ccb7be7350ae024730440220791e34413957c0f8348718d5d767f660657faf241801e74b5b81ac69e8912f60022041f3e9aeca137044565e1a81b6bcca74a88166436e5fa5f0e390448ac18fa5900121034dc07f3c26734591eb97f7e112888c3198d62bc3718106cba5a5688c62485b4500000000:Mempool::0::1555590448:False", network); var cTx1 = SmartTransaction.FromLine("95374c1037eb5268c8ae6681eb26756459d19754d41b660c251e6f62df586d29:0100000001357852bdf4e75a4ee2afe213463ff8afbed977ea5459a310777322504254ffdf0100000000ffffffff0240420f0000000000160014dc992214c430bf306fe446e9bac1dfc4ad4d3ee368cc100300000000160014005340d370675c47f7a04eb186200dd98c3d463c00000000:1580176:0000000034522ee38f074e1f4330b9c2f20c6a2b9a96de6f474a5f5f8fa76e2b:307::1569940579:False", network); var cTx2 = SmartTransaction.FromLine("af73b4c173da1bd24063e35a755babfa40728a282d6f56eeef4ce5a81ab26ee7:01000000013c81d2dcb25ad36781d1a6f9faa68f4a8b927f40e0b4e4b6184bb4761ebfc0dd0000000000ffffffff016f052e0000000000160014ae6e31ee9dae103f50979f761c2f9b44661da24f00000000:1580176:0000000034522ee38f074e1f4330b9c2f20c6a2b9a96de6f474a5f5f8fa76e2b:346::1569940633:False", network); var cTx3 = SmartTransaction.FromLine("ebcef423f6b03ef89dce076b53e624c966381f76e5d8b2b5034d3615ae950b2f:01000000000101296d58df626f1e250c661bd45497d159647526eb8166aec86852eb37104c37950100000000ffffffff01facb100300000000160014d5461e0e7077d62c4cf9c18a4e9ba10efd4930340247304402206d2c5b2b182474531ed07587e44ea22b136a37d5ddbd35aa2d984da7be5f7e5202202abd8435d9856e3d0892dbd54e9c05f2a20d9d5f333247314b925947a480a2eb01210321dd0574c773a35d4a7ebf17bf8f974b5665c0183598f1db53153e74c876768500000000:1580673:0000000017b09a77b815f3df513ff698d1f3b0e8c5e16ac0d6558e2d831f3bf9:130::1570462988:False", network); // Duplication in mempoool and confirmedtxs. var mempoolFileContent = new[] { uTx2.ToLine(), uTx1.ToLine(), uTx3.ToLine() }; var txFileContent = new[] { cTx3.ToLine(), cTx1.ToLine(), cTx2.ToLine() }; await File.WriteAllLinesAsync(mempoolFile, mempoolFileContent); await File.WriteAllLinesAsync(txFile, txFileContent); var expectedArray = new[] { uTx1, uTx2, uTx3, cTx1, cTx2, cTx3 }.OrderByBlockchain().ToList(); await using (var txStore = new AllTransactionStore(dir, network)) { await txStore.InitializeAsync(ensureBackwardsCompatibility : false); var txs = txStore.GetTransactions(); var txHashes = txStore.GetTransactionHashes(); Assert.Equal(txHashes, txs.Select(x => x.GetHash())); Assert.Equal(expectedArray, txs); } await using (var txStore = new AllTransactionStore(PrepareWorkDir(), network)) { await txStore.InitializeAsync(ensureBackwardsCompatibility : false); txStore.AddOrUpdate(uTx3); txStore.AddOrUpdate(uTx1); txStore.AddOrUpdate(uTx2); txStore.AddOrUpdate(cTx3); txStore.AddOrUpdate(cTx1); txStore.AddOrUpdate(cTx2); var txs = txStore.GetTransactions(); var txHashes = txStore.GetTransactionHashes(); Assert.Equal(txHashes, txs.Select(x => x.GetHash())); Assert.Equal(expectedArray, txs); } }