Esempio n. 1
0
        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();
            }
        }
Esempio n. 2
0
        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);
        }
Esempio n. 3
0
 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);
 }
Esempio n. 4
0
 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;
            }
        }
Esempio n. 6
0
    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);
    }
Esempio n. 7
0
        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);
        }
Esempio n. 8
0
        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);
            }
        }
Esempio n. 9
0
        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);
        }
Esempio n. 10
0
 public BitcoinStore(
     IndexStore indexStore,
     AllTransactionStore transactionStore,
     MempoolService mempoolService)
 {
     IndexStore       = indexStore;
     TransactionStore = transactionStore;
     MempoolService   = mempoolService;
 }
Esempio n. 11
0
 public BitcoinStore(
     IndexStore indexStore,
     AllTransactionStore transactionStore,
     MempoolService mempoolService,
     IRepository <uint256, Block> blockRepository)
 {
     IndexStore       = indexStore;
     TransactionStore = transactionStore;
     MempoolService   = mempoolService;
     BlockRepository  = blockRepository;
 }
Esempio n. 12
0
    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;
        }
Esempio n. 14
0
        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);
            }
        }
Esempio n. 15
0
    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)
            });
Esempio n. 16
0
        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);
            }
        }
Esempio n. 17
0
        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);
                }
            }
        }
Esempio n. 18
0
 public TrustedP2pBehavior(MempoolService mempoolService) : base(mempoolService)
 {
 }
Esempio n. 19
0
 public MempoolController(IMempoolService <PublicEntryDao> mempoolService)
 {
     _mempoolService = (MempoolService)mempoolService;
 }
Esempio n. 20
0
        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();
            }
        }
Esempio n. 22
0
        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));
        }
Esempio n. 23
0
        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 { })
Esempio n. 24
0
        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;
        }
Esempio n. 25
0
 protected P2pBehavior(MempoolService mempoolService)
 {
     MempoolService = Guard.NotNull(nameof(mempoolService), mempoolService);
 }
Esempio n. 26
0
        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();
            }
        }