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 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 CoreNodeParams( Network network, MempoolService mempoolService, HostedServices hostedServices, string dataDir, bool tryRestart, bool tryDeleteDataDir, EndPointStrategy p2pEndPointStrategy, EndPointStrategy rpcEndPointStrategy, int?txIndex, int?prune, string userAgent) { Network = Guard.NotNull(nameof(network), network); MempoolService = Guard.NotNull(nameof(mempoolService), mempoolService); HostedServices = Guard.NotNull(nameof(hostedServices), hostedServices); DataDir = Guard.NotNullOrEmptyOrWhitespace(nameof(dataDir), dataDir); TryRestart = tryRestart; TryDeleteDataDir = tryDeleteDataDir; P2pEndPointStrategy = Guard.NotNull(nameof(p2pEndPointStrategy), p2pEndPointStrategy); RpcEndPointStrategy = Guard.NotNull(nameof(rpcEndPointStrategy), rpcEndPointStrategy); TxIndex = txIndex; Prune = prune; UserAgent = Guard.NotNullOrEmptyOrWhitespace(nameof(userAgent), userAgent, trim: true); }
public CoreNodeParams( Network network, MempoolService mempoolService, string dataDir, bool tryRestart, bool tryDeleteDataDir, EndPointStrategy p2pEndPointStrategy, EndPointStrategy rpcEndPointStrategy, int?txIndex, int?prune, string mempoolReplacement, string userAgent, Money?fallbackFee, IMemoryCache cache) { Network = Guard.NotNull(nameof(network), network); MempoolService = Guard.NotNull(nameof(mempoolService), mempoolService); DataDir = Guard.NotNullOrEmptyOrWhitespace(nameof(dataDir), dataDir); TryRestart = tryRestart; TryDeleteDataDir = tryDeleteDataDir; P2pEndPointStrategy = Guard.NotNull(nameof(p2pEndPointStrategy), p2pEndPointStrategy); RpcEndPointStrategy = Guard.NotNull(nameof(rpcEndPointStrategy), rpcEndPointStrategy); TxIndex = txIndex; Prune = prune; MempoolReplacement = mempoolReplacement; UserAgent = Guard.NotNullOrEmptyOrWhitespace(nameof(userAgent), userAgent, trim: true); FallbackFee = fallbackFee; Cache = Guard.NotNull(nameof(cache), cache); }
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; } }
private static CoreNodeParams CreateDefaultCoreNodeParams(MempoolService mempoolService, string dataDir) { var nodeParameters = new CoreNodeParams( Network.RegTest, mempoolService ?? new MempoolService(), dataDir, tryRestart: true, tryDeleteDataDir: true, EndPointStrategy.Random, EndPointStrategy.Random, txIndex: 1, prune: 0, mempoolReplacement: "fee,optin", userAgent: $"/WasabiClient:{Constants.ClientVersion}/", fallbackFee: Money.Coins(0.0002m), // https://github.com/bitcoin/bitcoin/pull/16524 new MemoryCache(new MemoryCacheOptions())); nodeParameters.ListenOnion = 0; nodeParameters.Discover = 0; nodeParameters.DnsSeed = 0; nodeParameters.FixedSeeds = 0; nodeParameters.Upnp = 0; nodeParameters.NatPmp = 0; nodeParameters.PersistMempool = 0; return(nodeParameters); }
protected override bool ProcessInventoryVector(InventoryVector inv, EndPoint remoteSocketEndpoint) { if (inv.Type.HasFlag(InventoryType.MSG_TX)) { if (MempoolService.TryGetFromBroadcastStore(inv.Hash, out TransactionBroadcastEntry entry)) // If we have the transaction then adjust confirmation. { if (entry.NodeRemoteSocketEndpoint == remoteSocketEndpoint.ToString()) { return(false); // Wtf, why are you trying to broadcast it back to us? } entry.ConfirmPropagationOnce(); } // If we already processed it or we're in trusted node mode, then don't ask for it. if (MempoolService.TrustedNodeMode || MempoolService.IsProcessed(inv.Hash)) { return(false); } return(true); } return(false); }
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); } }
protected override bool ProcessInventoryVector(InventoryVector inv, EndPoint remoteSocketEndpoint) { if (inv.Type.HasFlag(InventoryType.MSG_TX)) { if (MempoolService.TryGetFromBroadcastStore(inv.Hash, out TransactionBroadcastEntry entry)) // If we have the transaction then adjust confirmation. { if (entry.NodeRemoteSocketEndpoint == remoteSocketEndpoint.ToString()) { return(false); // Wtf, why are you trying to broadcast it back to us? } entry.ConfirmPropagationForGood(); } // If we already processed it continue. if (MempoolService.IsProcessed(inv.Hash)) { return(false); } return(true); } if (inv.Type.HasFlag(InventoryType.MSG_BLOCK)) { BlockInv?.Invoke(this, inv.Hash); } return(false); }
public BitcoinStore( IndexStore indexStore, AllTransactionStore transactionStore, MempoolService mempoolService) { IndexStore = indexStore; TransactionStore = transactionStore; MempoolService = mempoolService; }
public BitcoinStore( IndexStore indexStore, AllTransactionStore transactionStore, MempoolService mempoolService, IRepository <uint256, Block> blockRepository) { IndexStore = indexStore; TransactionStore = transactionStore; MempoolService = mempoolService; BlockRepository = blockRepository; }
public P2pNode(Network network, EndPoint endPoint, MempoolService mempoolService, string userAgent) { Network = Guard.NotNull(nameof(network), network); EndPoint = Guard.NotNull(nameof(endPoint), endPoint); MempoolService = Guard.NotNull(nameof(mempoolService), mempoolService); UserAgent = Guard.NotNullOrEmptyOrWhitespace(nameof(userAgent), userAgent, trim: true); Stop = new CancellationTokenSource(); NodeEventsSubscribed = false; SubscriptionLock = new object(); P2pReconnector = new P2pReconnector(TimeSpan.FromSeconds(7), this); }
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; }
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(); var indexStoreFolderPath = Path.Combine(WorkFolderPath, Network.ToString(), "IndexStore"); HashChain = new HashChain(); MempoolService = new MempoolService(); await IndexStore.InitializeAsync(indexStoreFolderPath, Network, HashChain).ConfigureAwait(false); } }
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, 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 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 TrustedP2pBehavior(MempoolService mempoolService) : base(mempoolService) { }
public MempoolController(IMempoolService <PublicEntryDao> mempoolService) { _mempoolService = (MempoolService)mempoolService; }
public static async Task <CoreNode> CreateAsync(HostedServices hostedServices, [CallerFilePath] string callerFilePath = null, [CallerMemberName] string callerMemberName = null, string additionalFolder = null, MempoolService mempoolService = null) { var network = Network.RegTest; return(await CoreNode.CreateAsync( new CoreNodeParams( network, mempoolService ?? new MempoolService(), hostedServices, Path.Combine(Global.Instance.DataDir, EnvironmentHelpers.ExtractFileName(callerFilePath), callerMemberName, additionalFolder ?? ""), tryRestart : true, tryDeleteDataDir : true, EndPointStrategy.Random, EndPointStrategy.Random, txIndex : 1, prune : 0, mempoolReplacement : "fee,optin", userAgent : $"/WasabiClient:{Constants.ClientVersion}/", fallbackFee : Money.Coins(0.0002m), // https://github.com/bitcoin/bitcoin/pull/16524 new MemoryCache(new MemoryCacheOptions())), CancellationToken.None)); }
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 static async Task <CoreNode> CreateAsync([CallerFilePath] string callerFilePath = null, [CallerMemberName] string callerMemberName = null, string additionalFolder = null, MempoolService mempoolService = null) { var network = Network.RegTest; return(await CoreNode.CreateAsync( new CoreNodeParams( network, mempoolService ?? new MempoolService(), Path.Combine(Global.Instance.DataDir, EnvironmentHelpers.ExtractFileName(callerFilePath), callerMemberName, additionalFolder ?? ""), tryRestart : true, tryDeleteDataDir : true, EndPointStrategy.Random, EndPointStrategy.Random, txIndex : 1, prune : 0, userAgent : $"/WasabiClient:{Constants.ClientVersion.ToString()}/"), CancellationToken.None)); }
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 InitializeNoWalletAsync() { WalletService = null; ChaumianClient = null; AddressManager = null; TorManager = null; #region ConfigInitialization Config = new Config(Path.Combine(DataDir, "Config.json")); await Config.LoadOrCreateDefaultFileAsync(); Logger.LogInfo <Config>($"{nameof(Config)} is successfully initialized."); #endregion ConfigInitialization BitcoinStore = new BitcoinStore(); var bstoreInitTask = BitcoinStore.InitializeAsync(Path.Combine(DataDir, "BitcoinStore"), Network); var hwiInitTask = HwiProcessManager.InitializeAsync(DataDir, Network); var addressManagerFolderPath = Path.Combine(DataDir, "AddressManager"); AddressManagerFilePath = Path.Combine(addressManagerFolderPath, $"AddressManager{Network}.dat"); var addrManTask = InitializeAddressManagerBehaviorAsync(); var blocksFolderPath = Path.Combine(DataDir, $"Blocks{Network}"); var connectionParameters = new NodeConnectionParameters { UserAgent = "/Satoshi:0.18.0/" }; if (Config.UseTor) { Synchronizer = new WasabiSynchronizer(Network, BitcoinStore, () => Config.GetCurrentBackendUri(), Config.TorSocks5EndPoint); } else { Synchronizer = new WasabiSynchronizer(Network, BitcoinStore, Config.GetFallbackBackendUri(), null); } UpdateChecker = new UpdateChecker(Synchronizer.WasabiClient); #region ProcessKillSubscription AppDomain.CurrentDomain.ProcessExit += async(s, e) => await TryDesperateDequeueAllCoinsAsync(); Console.CancelKeyPress += async(s, e) => { e.Cancel = true; Logger.LogWarning("Process was signaled for killing.", nameof(Global)); KillRequested = true; await TryDesperateDequeueAllCoinsAsync(); Dispatcher.UIThread.PostLogException(() => { Application.Current?.MainWindow?.Close(); }); await DisposeAsync(); Logger.LogInfo($"Wasabi stopped gracefully.", Logger.InstanceGuid.ToString()); }; #endregion ProcessKillSubscription #region TorProcessInitialization if (Config.UseTor) { TorManager = new TorProcessManager(Config.TorSocks5EndPoint, TorLogsFile); } else { TorManager = TorProcessManager.Mock(); } TorManager.Start(false, DataDir); var fallbackRequestTestUri = new Uri(Config.GetFallbackBackendUri(), "/api/software/versions"); TorManager.StartMonitor(TimeSpan.FromSeconds(3), TimeSpan.FromSeconds(7), DataDir, fallbackRequestTestUri); Logger.LogInfo <TorProcessManager>($"{nameof(TorProcessManager)} is initialized."); #endregion TorProcessInitialization #region MempoolInitialization MempoolService = new MempoolService(); connectionParameters.TemplateBehaviors.Add(new MempoolBehavior(MempoolService)); #endregion MempoolInitialization #region HwiProcessInitialization try { await hwiInitTask; } catch (Exception ex) { Logger.LogError(ex, nameof(Global)); } #endregion HwiProcessInitialization #region BitcoinStoreInitialization await bstoreInitTask; #endregion BitcoinStoreInitialization #region AddressManagerInitialization AddressManagerBehavior addressManagerBehavior = await addrManTask; connectionParameters.TemplateBehaviors.Add(addressManagerBehavior); #endregion AddressManagerInitialization #region P2PInitialization if (Network == Network.RegTest) { Nodes = new NodesGroup(Network, requirements: Constants.NodeRequirements); try { Node node = await Node.ConnectAsync(Network.RegTest, new IPEndPoint(IPAddress.Loopback, 18444)); Nodes.ConnectedNodes.Add(node); RegTestMempoolServingNode = await Node.ConnectAsync(Network.RegTest, new IPEndPoint(IPAddress.Loopback, 18444)); RegTestMempoolServingNode.Behaviors.Add(new MempoolBehavior(MempoolService)); } catch (SocketException ex) { Logger.LogError(ex, nameof(Global)); } } else { if (Config.UseTor is true) { // onlyForOnionHosts: false - Connect to clearnet IPs through Tor, too. connectionParameters.TemplateBehaviors.Add(new SocksSettingsBehavior(Config.TorSocks5EndPoint, onlyForOnionHosts: false, networkCredential: null, streamIsolation: true)); // allowOnlyTorEndpoints: true - Connect only to onions and do not connect to clearnet IPs at all. // This of course makes the first setting unnecessary, but it's better if that's around, in case someone wants to tinker here. connectionParameters.EndpointConnector = new DefaultEndpointConnector(allowOnlyTorEndpoints: Network == Network.Main); await AddKnownBitcoinFullNodeAsHiddenServiceAsync(AddressManager); } Nodes = new NodesGroup(Network, connectionParameters, requirements: Constants.NodeRequirements); RegTestMempoolServingNode = null; } Nodes.Connect(); Logger.LogInfo("Start connecting to nodes..."); if (RegTestMempoolServingNode != null) { RegTestMempoolServingNode.VersionHandshake(); Logger.LogInfo("Start connecting to mempool serving regtest node..."); } #endregion P2PInitialization #region SynchronizerInitialization var requestInterval = TimeSpan.FromSeconds(30); if (Network == Network.RegTest) { requestInterval = TimeSpan.FromSeconds(5); } int maxFiltSyncCount = Network == Network.Main ? 1000 : 10000; // On testnet, filters are empty, so it's faster to query them together Synchronizer.Start(requestInterval, TimeSpan.FromMinutes(5), maxFiltSyncCount); Logger.LogInfo("Start synchronizing filters..."); #endregion SynchronizerInitialization Initialized = true; }
protected P2pBehavior(MempoolService mempoolService) { MempoolService = Guard.NotNull(nameof(mempoolService), mempoolService); }
public async Task TestServicesAsync(string networkString) { await RuntimeParams.LoadAsync(); var network = Network.GetNetwork(networkString); var blocksToDownload = new HashSet <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 NotSupportedException($"{nameof(Network)} not supported: {network}."); } var addressManagerFolderPath = Path.Combine(Global.Instance.DataDir, "AddressManager"); var addressManagerFilePath = Path.Combine(addressManagerFolderPath, $"AddressManager{network}.dat"); var blocksFolderPath = Path.Combine(Global.Instance.DataDir, "Blocks", network.ToString()); var connectionParameters = new NodeConnectionParameters(); AddressManager addressManager = null; try { addressManager = await NBitcoinHelpers.LoadAddressManagerFromPeerFileAsync(addressManagerFilePath); Logger.LogInfo <AddressManager>($"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)); var mempoolService = new MempoolService(); connectionParameters.TemplateBehaviors.Add(new MempoolBehavior(mempoolService)); var nodes = new NodesGroup(network, connectionParameters, requirements: Constants.NodeRequirements); BitcoinStore bitcoinStore = new BitcoinStore(); await bitcoinStore.InitializeAsync(Path.Combine(Global.Instance.DataDir, EnvironmentHelpers.GetMethodName()), network); KeyManager keyManager = KeyManager.CreateNew(out _, "password"); WasabiSynchronizer syncer = new WasabiSynchronizer(network, bitcoinStore, new Uri("http://localhost:12345"), Global.Instance.TorSocks5Endpoint); WalletService walletService = new WalletService( bitcoinStore, keyManager, syncer, new CcjClient(syncer, network, keyManager, new Uri("http://localhost:12345"), Global.Instance.TorSocks5Endpoint), mempoolService, nodes, Global.Instance.DataDir, new ServiceConfiguration(50, 2, 21, 50, new IPEndPoint(IPAddress.Loopback, network.DefaultPort), Money.Coins(0.0001m))); Assert.True(Directory.Exists(blocksFolderPath)); try { mempoolService.TransactionReceived += MempoolService_TransactionReceived; nodes.Connect(); var times = 0; while (nodes.ConnectedNodes.Count < 3) { if (times > 4200) // 7 minutes { throw new TimeoutException("Connection test timed out."); } await Task.Delay(100); times++; } times = 0; while (Interlocked.Read(ref _mempoolTransactionCount) < 3) { if (times > 3000) // 3 minutes { throw new TimeoutException($"{nameof(MempoolService)} test timed out."); } await Task.Delay(100); times++; } foreach (var hash in blocksToDownload) { using (var cts = new CancellationTokenSource(TimeSpan.FromMinutes(3))) { var block = await walletService.FetchBlockAsync(hash, cts.Token); Assert.True(File.Exists(Path.Combine(blocksFolderPath, hash.ToString()))); Logger.LogInfo <P2pTests>($"Full block is downloaded: {hash}."); } } } finally { nodes.ConnectedNodes.Added -= ConnectedNodes_Added; nodes.ConnectedNodes.Removed -= ConnectedNodes_Removed; mempoolService.TransactionReceived -= MempoolService_TransactionReceived; // So next test will download the block. foreach (var hash in blocksToDownload) { await walletService?.DeleteBlockAsync(hash); } if (walletService != null) { await walletService.StopAsync(); } if (Directory.Exists(blocksFolderPath)) { Directory.Delete(blocksFolderPath, recursive: true); } IoHelpers.EnsureContainingDirectoryExists(addressManagerFilePath); addressManager?.SavePeerFile(addressManagerFilePath, network); Logger.LogInfo <P2pTests>($"Saved {nameof(AddressManager)} to `{addressManagerFilePath}`."); nodes?.Dispose(); await syncer?.StopAsync(); } }