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;
            }
        }
示例#2
0
        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 _));
        }
示例#3
0
        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());
        }
示例#4
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);
            }
        }
示例#5
0
        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);
        }
示例#6
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);
        }
        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();
            }
        }
示例#8
0
        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());
        }
示例#9
0
    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;
 }
示例#11
0
 /// <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;
 }
示例#12
0
 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);
 }
示例#14
0
 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)));
        }
示例#17
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)
            });
示例#18
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);
                }
            }
        }
示例#19
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);
            }
        }
示例#20
0
        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 _));
        }
示例#21
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 { })
        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();
            }
        }
示例#23
0
        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);
        }
示例#24
0
        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);
            }
        }