public void CanCalculateStandardPhases()
        {
            StandardCycles cycles = new StandardCycles(Network.Main.Consensus, true);

            Assert.NotNull(cycles.GetStandardCycle("shorty"));

            cycles = new StandardCycles(Network.Main.Consensus, false);
            Assert.Null(cycles.GetStandardCycle("shorty"));

            var kotori = cycles.GetStandardCycle("kotori");

            Assert.Equal(Money.Coins(1), kotori.Denomination);
            Assert.Equal(TimeSpan.FromDays(1), kotori.GetLength(false));
            Assert.Equal(TimeSpan.FromDays(2), kotori.GetLength(true));
            Assert.Equal(Money.Coins(1), kotori.CoinsPerDay());
        }
        public TumblerConfiguration LoadArgs(String[] args)
        {
            ConfigurationFile = args.Where(a => a.StartsWith("-conf=", StringComparison.Ordinal)).Select(a => a.Substring("-conf=".Length).Replace("\"", "")).FirstOrDefault();
            DataDir           = args.Where(a => a.StartsWith("-datadir=", StringComparison.Ordinal)).Select(a => a.Substring("-datadir=".Length).Replace("\"", "")).FirstOrDefault();
            if (DataDir != null && ConfigurationFile != null)
            {
                var isRelativePath = Path.GetFullPath(ConfigurationFile).Length > ConfigurationFile.Length;
                if (isRelativePath)
                {
                    ConfigurationFile = Path.Combine(DataDir, ConfigurationFile);
                }
            }

            Network = args.Contains("-testnet", StringComparer.OrdinalIgnoreCase) ? Network.TestNet :
                      args.Contains("-regtest", StringComparer.OrdinalIgnoreCase) ? Network.RegTest :
                      Network.Main;

            if (ConfigurationFile != null)
            {
                AssetConfigFileExists();
                var configTemp = TextFileConfiguration.Parse(File.ReadAllText(ConfigurationFile));

                Network = configTemp.GetOrDefault <bool>("testnet", false) ? Network.TestNet :
                          configTemp.GetOrDefault <bool>("regtest", false) ? Network.RegTest :
                          Network.Main;
            }
            if (DataDir == null)
            {
                DataDir = DefaultDataDirectory.GetDefaultDirectory("NTumbleBitServer", Network);
            }

            if (ConfigurationFile == null)
            {
                ConfigurationFile = GetDefaultConfigurationFile(Network);
            }
            Logs.Configuration.LogInformation("Network: " + Network);

            Logs.Configuration.LogInformation("Data directory set to " + DataDir);
            Logs.Configuration.LogInformation("Configuration file set to " + ConfigurationFile);

            if (!Directory.Exists(DataDir))
            {
                throw new ConfigurationException("Data directory does not exists");
            }

            var consoleConfig = new TextFileConfiguration(args);
            var config        = TextFileConfiguration.Parse(File.ReadAllText(ConfigurationFile));

            consoleConfig.MergeInto(config, true);

            if (config.Contains("help"))
            {
                Console.WriteLine("Details on the wiki page :  https://github.com/NTumbleBit/NTumbleBit/wiki/Server-Config");
                OpenBrowser("https://github.com/NTumbleBit/NTumbleBit/wiki/Server-Config");
                Environment.Exit(0);
            }

            var standardCycles = new StandardCycles(Network);
            var cycleName      = "kotori";        //config.GetOrDefault<string>("cycle", standardCycles.Debug ? "shorty2x" : "shorty2x");

            Logs.Configuration.LogInformation($"Using cycle {cycleName}");

            var standardCycle = standardCycles.GetStandardCycle(cycleName);

            if (standardCycle == null)
            {
                throw new ConfigException($"Invalid cycle name, choose among {String.Join(",", standardCycles.ToEnumerable().Select(c => c.FriendlyName).ToArray())}");
            }

            ClassicTumblerParameters.CycleGenerator = standardCycle.Generator;
            ClassicTumblerParameters.Denomination   = standardCycle.Denomination;
            var torEnabled = config.GetOrDefault <bool>("tor.enabled", true);

            if (torEnabled)
            {
                TorSettings = TorConnectionSettings.ParseConnectionSettings("tor", config);
            }

            Cooperative = config.GetOrDefault <bool>("cooperative", true);

            var defaultPort = config.GetOrDefault <int>("port", 37123);

            OnlyMonitor = config.GetOrDefault <bool>("onlymonitor", false);
            string listenAddress = config.GetOrDefault <string>("listen", Utils.GetInternetConnectedAddress().ToString());

            Listen = new IPEndPoint(IPAddress.Parse(listenAddress), defaultPort);

            RPC               = RPCArgs.Parse(config, Network);
            TorPath           = config.GetOrDefault <string>("torpath", "tor");
            DBreezeRepository = new DBreezeRepository(Path.Combine(DataDir, "db2"));
            Tracker           = new Tracker(DBreezeRepository, Network);

            // The worst case scenario is tumbler posting Puzzle which than fails and the tumbler has to get a refund.
            // This it(`T[Puzzle]`) 447B + (`T[Refund]` for (`T[Puzzle]`)) 651B = 1098B
            // Assuming the average transaction fee @ 50 sat / B we get: 1098B * 50 sat / B = 0.00054900 BTC just the network fees
            // For the denomination 0.1 BTC the 1 % fee would be 0.001 BTC
            // Combining the network fees with 1 % fees for 0.1 BTC denomination gives us 0.00054900 BTC + 0.001 BTC = 0.00154900 BTC ≈ 0.00155 BTC
            // The overall tumbler fee will work out to be 1.55 % of the denomination
            var defaultFee = new Money(0.00155m, MoneyUnit.BTC);

            ClassicTumblerParameters.Fee = config.GetOrDefault <Money>("tumbler.fee", defaultFee);

            TumblerProtocol = config.GetOrDefault <TumblerProtocolType>("tumbler.protocol", TumblerProtocolType.Tcp);

            RPCClient rpc = null;

            try
            {
                rpc = RPC.ConfigureRPCClient(Network);
            }
            catch
            {
                throw new ConfigException("Please, fix rpc settings in " + ConfigurationFile);
            }

            Services = ExternalServices.CreateFromRPCClient(rpc, DBreezeRepository, Tracker, true);
            return(this);
        }
예제 #3
0
        public TumblerConfiguration LoadArgs(String[] args)
        {
            ConfigurationFile = args.Where(a => a.StartsWith("-conf=", StringComparison.Ordinal)).Select(a => a.Substring("-conf=".Length).Replace("\"", "")).FirstOrDefault();
            DataDir           = args.Where(a => a.StartsWith("-datadir=", StringComparison.Ordinal)).Select(a => a.Substring("-datadir=".Length).Replace("\"", "")).FirstOrDefault();
            if (DataDir != null && ConfigurationFile != null)
            {
                var isRelativePath = Path.GetFullPath(ConfigurationFile).Length > ConfigurationFile.Length;
                if (isRelativePath)
                {
                    ConfigurationFile = Path.Combine(DataDir, ConfigurationFile);
                }
            }

            Network = args.Contains("-testnet", StringComparer.OrdinalIgnoreCase) ? Network.TestNet :
                      args.Contains("-regtest", StringComparer.OrdinalIgnoreCase) ? Network.RegTest :
                      Network.Main;

            if (ConfigurationFile != null)
            {
                AssetConfigFileExists();
                var configTemp = TextFileConfiguration.Parse(File.ReadAllText(ConfigurationFile));
                Network = configTemp.GetOrDefault <bool>("testnet", false) ? Network.TestNet :
                          configTemp.GetOrDefault <bool>("regtest", false) ? Network.RegTest :
                          Network.Main;
            }
            if (DataDir == null)
            {
                DataDir = DefaultDataDirectory.GetDefaultDirectory("NTumbleBitServer", Network);
            }

            if (ConfigurationFile == null)
            {
                ConfigurationFile = GetDefaultConfigurationFile();
            }
            Logs.Configuration.LogInformation("Network: " + Network);

            Logs.Configuration.LogInformation("Data directory set to " + DataDir);
            Logs.Configuration.LogInformation("Configuration file set to " + ConfigurationFile);

            if (!Directory.Exists(DataDir))
            {
                throw new ConfigurationException("Data directory does not exists");
            }

            var consoleConfig = new TextFileConfiguration(args);
            var config        = TextFileConfiguration.Parse(File.ReadAllText(ConfigurationFile));

            consoleConfig.MergeInto(config, true);

            if (config.Contains("help"))
            {
                Console.WriteLine("Details on the wiki page :  https://github.com/NTumbleBit/NTumbleBit/wiki/Server-Config");
                OpenBrowser("https://github.com/NTumbleBit/NTumbleBit/wiki/Server-Config");
                Environment.Exit(0);
            }

            var standardCycles = new StandardCycles(Network);
            var cycleName      = config.GetOrDefault <string>("cycle", standardCycles.Debug ? "shorty" : "kotori");

            Logs.Configuration.LogInformation($"Using cycle {cycleName}");
            ClassicTumblerParameters.CycleGenerator = standardCycles.GetStandardCycle(cycleName)?.Generator;
            if (ClassicTumblerParameters.CycleGenerator == null)
            {
                throw new ConfigException($"Invalid cycle name, choose among {String.Join(",", standardCycles.ToEnumerable().Select(c => c.FriendlyName).ToArray())}");
            }

            var torEnabled = config.GetOrDefault <bool>("tor.enabled", true);

            if (torEnabled)
            {
                TorSettings = TorConnectionSettings.ParseConnectionSettings("tor", config);
            }

            Cooperative = config.GetOrDefault <bool>("cooperative", true);

            var defaultPort = config.GetOrDefault <int>("port", 37123);

            OnlyMonitor = config.GetOrDefault <bool>("onlymonitor", false);
            Listen      = new IPEndPoint(IPAddress.Parse("127.0.0.1"), defaultPort);

            RPC               = RPCArgs.Parse(config, Network);
            TorPath           = config.GetOrDefault <string>("torpath", "tor");
            DBreezeRepository = new DBreezeRepository(Path.Combine(DataDir, "db2"));
            Tracker           = new Tracker(DBreezeRepository, Network);

            RPCClient rpc = null;

            try
            {
                rpc = RPC.ConfigureRPCClient(Network);
            }
            catch
            {
                throw new ConfigException("Please, fix rpc settings in " + ConfigurationFile);
            }

            Services = ExternalServices.CreateFromRPCClient(rpc, DBreezeRepository, Tracker);
            return(this);
        }
예제 #4
0
        public TumblerServerTester(string directory, bool shouldBeStandard)
        {
            try
            {
                var rootTestData = "TestData";
                directory  = rootTestData + "/" + directory;
                _Directory = directory;
                if (!Directory.Exists(rootTestData))
                {
                    Directory.CreateDirectory(rootTestData);
                }

                if (!TryDelete(directory, false))
                {
                    foreach (var process in Process.GetProcessesByName("bitcoind"))
                    {
                        if (process.MainModule.FileName.Replace("\\", "/").StartsWith(Path.GetFullPath(rootTestData).Replace("\\", "/"), StringComparison.Ordinal))
                        {
                            process.Kill();
                            process.WaitForExit();
                        }
                    }
                    TryDelete(directory, true);
                }

                _NodeBuilder = NodeBuilder.Create(directory);
                _NodeBuilder.ConfigParameters.Add("prematurewitness", "1");
                _NodeBuilder.ConfigParameters.Add("walletprematurewitness", "1");

                _TumblerNode = _NodeBuilder.CreateNode(false);
                _AliceNode   = _NodeBuilder.CreateNode(false);
                _BobNode     = _NodeBuilder.CreateNode(false);

                Directory.CreateDirectory(directory);

                _NodeBuilder.StartAll();

                //Activate segwit
                SyncNodes();
                _TumblerNode.Generate(440);
                _TumblerNode.CreateRPCClient().SendToAddress(_AliceNode.CreateRPCClient().GetNewAddress(), Money.Coins(100m));
                _TumblerNode.Generate(1);
                SyncNodes();

                var conf = new TumblerConfiguration();
                conf.DataDir = Path.Combine(directory, "server");
                Directory.CreateDirectory(conf.DataDir);
                File.WriteAllBytes(Path.Combine(conf.DataDir, "Tumbler.pem"), TestKeys.Default.ToBytes());
                File.WriteAllBytes(Path.Combine(conf.DataDir, "Voucher.pem"), TestKeys.Default2.ToBytes());

                conf.RPC.Url = TumblerNode.CreateRPCClient().Address;
                var creds = ExtractCredentials(File.ReadAllText(_TumblerNode.Config));
                conf.RPC.User      = creds.Item1;
                conf.RPC.Password  = creds.Item2;
                conf.TorMandatory  = false;
                conf.Network       = Network.RegTest;
                conf.Listen        = new System.Net.IPEndPoint(IPAddress.Parse("127.0.0.1"), 5000);
                conf.AllowInsecure = !shouldBeStandard;

                conf.NoRSAProof = !shouldBeStandard;
                if (!shouldBeStandard)
                {
                    conf.ClassicTumblerParameters.FakePuzzleCount                 = 10;
                    conf.ClassicTumblerParameters.FakeTransactionCount            = 10;
                    conf.ClassicTumblerParameters.RealTransactionCount            = 10;
                    conf.ClassicTumblerParameters.RealPuzzleCount                 = 2;
                    conf.ClassicTumblerParameters.CycleGenerator.FirstCycle.Start = 105;
                }
                else
                {
                    var standard = new StandardCycles(conf.Network).Shorty2x;
                    conf.ClassicTumblerParameters.CycleGenerator = standard.Generator;
                    conf.ClassicTumblerParameters.Denomination   = standard.Denomination;
                }

                var runtime = TumblerRuntime.FromConfiguration(conf, new AcceptAllClientInteraction());
                _Host = new WebHostBuilder()
                        .UseAppConfiguration(runtime)
                        .UseContentRoot(Path.GetFullPath(directory))
                        .UseStartup <Startup>()
                        .Build();

                _Host.Start();
                ServerRuntime = runtime;

                //Overrides server fee
                ((RPCFeeService)runtime.Services.FeeService).FallBackFeeRate     = new FeeRate(Money.Satoshis(100), 1);
                ((RPCWalletService)runtime.Services.WalletService).BatchInterval = TimeSpan.FromMilliseconds(10);
                ((RPCWalletService)runtime.Services.WalletService).AddressGenerationBatchInterval = TimeSpan.FromMilliseconds(10);
                ((RPCBroadcastService)runtime.Services.BroadcastService).BatchInterval            = TimeSpan.FromMilliseconds(10);
                ((RPCBlockExplorerService)runtime.Services.BlockExplorerService).BatchInterval    = TimeSpan.FromMilliseconds(10);


                var clientConfig = new TumblerClientConfiguration();
                clientConfig.DataDir       = Path.Combine(directory, "client");
                clientConfig.AllowInsecure = !shouldBeStandard;
                Directory.CreateDirectory(clientConfig.DataDir);
                clientConfig.Network              = conf.Network;
                clientConfig.CheckIp              = false;
                clientConfig.TorMandatory         = false;
                clientConfig.OutputWallet.KeyPath = new KeyPath("0");
                clientConfig.OutputWallet.RootKey = new ExtKey().Neuter().GetWif(conf.Network);
                clientConfig.RPCArgs.Url          = AliceNode.CreateRPCClient().Address;
                creds = ExtractCredentials(File.ReadAllText(AliceNode.Config));
                clientConfig.RPCArgs.User     = creds.Item1;
                clientConfig.RPCArgs.Password = creds.Item2;
                clientConfig.TumblerServer    = runtime.TumblerUris.First();

                ClientRuntime = TumblerClientRuntime.FromConfiguration(clientConfig, new AcceptAllClientInteraction());

                //Overrides client fee
                ((RPCFeeService)ClientRuntime.Services.FeeService).FallBackFeeRate = new FeeRate(Money.Satoshis(50), 1);
            }
            catch { Dispose(); throw; }
        }
예제 #5
0
        public async Task ConfigureAsync(TumblerClientConfigurationBase configuration, ClientInteraction interaction)
        {
            interaction = interaction ?? new AcceptAllClientInteraction();

            Network       = configuration.Network;
            TumblerServer = configuration.TumblerServer;
            BobSettings   = configuration.BobConnectionSettings;
            AliceSettings = configuration.AliceConnectionSettings;
            AllowInsecure = configuration.AllowInsecure;

            if (this.TumblerServer.IsOnion)
            {
                await SetupTorAsync(interaction, configuration.TorPath).ConfigureAwait(false);
            }
            else if (configuration.TorMandatory)
            {
                throw new ConfigException("The tumbler server should use TOR");
            }

            Cooperative = configuration.Cooperative;
            Repository  = configuration.DBreezeRepository;
            _Disposables.Add(Repository);
            Tracker           = configuration.Tracker;
            Services          = configuration.Services;
            DestinationWallet = configuration.DestinationWallet;

            TumblerParameters = Repository.Get <ClassicTumbler.ClassicTumblerParameters>("Configuration", TumblerServer.ToString());

            if (TumblerParameters != null && TumblerParameters.GetHash() != configuration.TumblerServer.ConfigurationHash)
            {
                TumblerParameters = null;
            }

            if (!configuration.OnlyMonitor)
            {
                var client = CreateTumblerClient(0);
                if (TumblerParameters == null)
                {
                    Logs.Configuration.LogInformation("Downloading tumbler information of " + configuration.TumblerServer.ToString());
                    var parameters = Retry(3, () => client.GetTumblerParameters());
                    if (parameters == null)
                    {
                        throw new ConfigException("Unable to download tumbler's parameters");
                    }

                    if (parameters.GetHash() != configuration.TumblerServer.ConfigurationHash)
                    {
                        throw new ConfigException("The tumbler returned an invalid configuration");
                    }

                    var standardCycles = new StandardCycles(configuration.Network);
                    var standardCycle  = standardCycles.GetStandardCycle(parameters);
                    if (parameters.ExpectedAddress != TumblerServer.GetRoutableUri(false).AbsoluteUri)
                    {
                        throw new ConfigException("This tumbler has parameters used for an unexpected uri");
                    }
                    Logs.Configuration.LogInformation("Checking RSA key proof and standardness of the settings...");
                    if (standardCycle == null || !parameters.IsStandard())
                    {
                        Logs.Configuration.LogWarning("This tumbler has non standard parameters");
                        if (!AllowInsecure)
                        {
                            throw new ConfigException("This tumbler has non standard parameters");
                        }
                        standardCycle = null;
                    }

                    await interaction.ConfirmParametersAsync(parameters, standardCycle).ConfigureAwait(false);

                    Repository.UpdateOrInsert("Configuration", TumblerServer.ToString(), parameters, (o, n) => n);
                    TumblerParameters = parameters;

                    Logs.Configuration.LogInformation("Tumbler parameters saved");
                }

                Logs.Configuration.LogInformation($"Using tumbler {TumblerServer.ToString()}");
            }
        }
        public async Task ConfigureAsync(TumblerClientConfiguration configuration, ClientInteraction interaction)
        {
            interaction = interaction ?? new AcceptAllClientInteraction();

            Network       = configuration.Network;
            TumblerServer = configuration.TumblerServer;
            BobSettings   = configuration.BobConnectionSettings;
            AliceSettings = configuration.AliceConnectionSettings;
            AllowInsecure = configuration.AllowInsecure;

            await SetupTorAsync(interaction, configuration.TorPath).ConfigureAwait(false);

            RPCClient rpc = null;

            try
            {
                rpc = configuration.RPCArgs.ConfigureRPCClient(configuration.Network);
            }
            catch
            {
                throw new ConfigException("Please, fix rpc settings in " + configuration.ConfigurationFile);
            }

            var dbreeze = new DBreezeRepository(Path.Combine(configuration.DataDir, "db2"));

            Cooperative = configuration.Cooperative;
            Repository  = dbreeze;
            _Disposables.Add(dbreeze);
            Tracker  = new Tracker(dbreeze, Network);
            Services = ExternalServices.CreateFromRPCClient(rpc, dbreeze, Tracker);

            if (configuration.OutputWallet.RootKey != null && configuration.OutputWallet.KeyPath != null)
            {
                DestinationWallet = new ClientDestinationWallet(configuration.OutputWallet.RootKey, configuration.OutputWallet.KeyPath, dbreeze, configuration.Network);
            }
            else if (configuration.OutputWallet.RPCArgs != null)
            {
                try
                {
                    DestinationWallet = new RPCDestinationWallet(configuration.OutputWallet.RPCArgs.ConfigureRPCClient(Network));
                }
                catch
                {
                    throw new ConfigException("Please, fix outputwallet rpc settings in " + configuration.ConfigurationFile);
                }
            }
            else
            {
                throw new ConfigException("Missing configuration for outputwallet");
            }

            TumblerParameters = dbreeze.Get <ClassicTumbler.ClassicTumblerParameters>("Configuration", configuration.TumblerServer.Uri.AbsoluteUri);

            if (TumblerParameters != null && TumblerParameters.GetHash() != configuration.TumblerServer.ConfigurationHash)
            {
                TumblerParameters = null;
            }

            if (!configuration.OnlyMonitor)
            {
                var client = CreateTumblerClient(0);
                if (TumblerParameters == null)
                {
                    Logs.Configuration.LogInformation("Downloading tumbler information of " + configuration.TumblerServer.Uri.AbsoluteUri);
                    var parameters = Retry(3, () => client.GetTumblerParameters());
                    if (parameters == null)
                    {
                        throw new ConfigException("Unable to download tumbler's parameters");
                    }

                    if (parameters.GetHash() != configuration.TumblerServer.ConfigurationHash)
                    {
                        throw new ConfigException("The tumbler returned an invalid configuration");
                    }

                    var standardCycles = new StandardCycles(configuration.Network);
                    var standardCycle  = standardCycles.GetStandardCycle(parameters);

                    if (standardCycle == null || !parameters.IsStandard())
                    {
                        Logs.Configuration.LogWarning("This tumbler has non standard parameters");
                        if (!AllowInsecure)
                        {
                            throw new ConfigException("This tumbler has non standard parameters");
                        }
                        standardCycle = null;
                    }

                    await interaction.ConfirmParametersAsync(parameters, standardCycle).ConfigureAwait(false);

                    Repository.UpdateOrInsert("Configuration", TumblerServer.Uri.AbsoluteUri, parameters, (o, n) => n);
                    TumblerParameters = parameters;

                    Logs.Configuration.LogInformation("Tumbler parameters saved");
                }

                Logs.Configuration.LogInformation($"Using tumbler {TumblerServer.Uri.AbsoluteUri}");
            }
        }
        public async Task ConfigureAsync(TumblerClientConfigurationBase configuration, TumblerProtocolType tumblerProtocol, ClientInteraction interaction = null, bool connectionTest = false)
        {
            interaction = interaction ?? new AcceptAllClientInteraction();
            Network     = configuration.Network;

            // if connectiontest then just test the connection, don't care about anything else
            // todo: refactor it in NTumbleBit for proper connectionTest, it's hacking
            if (connectionTest)
            {
                TumblerServer = configuration.TumblerServer;
                BobSettings   = configuration.BobConnectionSettings;
                AliceSettings = configuration.AliceConnectionSettings;
                AllowInsecure = configuration.AllowInsecure;
                if (this.TumblerServer.IsOnion)
                {
                    await SetupTorAsync(interaction, configuration.TorPath).ConfigureAwait(false);
                }
                else if (configuration.TorMandatory)
                {
                    throw new ConfigException("The tumbler server should use TOR");
                }
                var client = CreateTumblerClient(0, tumblerProtocol, connectTimeout: TimeSpan.FromSeconds(15));
                TumblerParameters = Retry(1, () => client.GetTumblerParameters());
                if (TumblerParameters == null)
                {
                    throw new ConfigException("Unable to download tumbler's parameters");
                }
                return;
            }

            Repository = configuration.DBreezeRepository;
            _Disposables.Add(Repository);
            Tracker  = configuration.Tracker;
            Services = configuration.Services;

            if (!configuration.OnlyMonitor)
            {
                DataDir       = configuration.DataDir;
                TumblerServer = configuration.TumblerServer;
                BobSettings   = configuration.BobConnectionSettings;
                AliceSettings = configuration.AliceConnectionSettings;
                AllowInsecure = configuration.AllowInsecure;

                if (this.TumblerServer.IsOnion)
                {
                    await SetupTorAsync(interaction, configuration.TorPath).ConfigureAwait(false);
                }
                else if (configuration.TorMandatory)
                {
                    throw new ConfigException("The tumbler server should use TOR");
                }

                Cooperative = configuration.Cooperative;

                DestinationWallet = configuration.DestinationWallet;

                try
                {
                    TumblerParameters = Repository.Get <ClassicTumblerParameters>("Configuration", configuration.TumblerServer.ToString());
                }
                catch
                {
                    TumblerParameters = null;
                }
                if (TumblerParameters != null && TumblerParameters.GetHash() != configuration.TumblerServer.ConfigurationHash)
                {
                    TumblerParameters = null;
                }

                var client = CreateTumblerClient(0, tumblerProtocol);

                Logs.Configuration.LogInformation("Downloading tumbler information of " + configuration.TumblerServer.ToString());
                var parameters = Retry(3, () => client.GetTumblerParameters());
                if (parameters == null)
                {
                    throw new ConfigException("Unable to download tumbler's parameters");
                }

                if (parameters.GetHash() != configuration.TumblerServer.ConfigurationHash)
                {
                    throw new ConfigException("The tumbler returned an invalid configuration");
                }

                var standardCycles = new StandardCycles(configuration.Network);
                var standardCycle  = standardCycles.GetStandardCycle(parameters);
                if (parameters.ExpectedAddress != TumblerServer.GetRoutableUri(false).AbsoluteUri)
                {
                    throw new ConfigException("This tumbler has parameters used for an unexpected uri");
                }
                Logs.Configuration.LogInformation("Checking RSA key proof and standardness of the settings...");
                try
                {
                    if (standardCycle == null || !parameters.IsStandard())
                    {
                        Logs.Configuration.LogWarning("This tumbler has non standard parameters");
                        if (!AllowInsecure)
                        {
                            throw new ConfigException("This tumbler has non standard parameters");
                        }
                        standardCycle = null;
                    }
                }
                catch (Exception e)
                {
                    Console.WriteLine("Exception checking tumbler parameters: " + e);
                }

                await interaction.ConfirmParametersAsync(parameters, standardCycle).ConfigureAwait(false);

                if (TumblerParameters == null)
                {
                    Repository.UpdateOrInsert("Configuration", TumblerServer.ToString(), parameters, (o, n) => n);
                    TumblerParameters = parameters;
                    Logs.Configuration.LogInformation("Tumbler parameters saved");
                }

                Logs.Configuration.LogInformation($"Using tumbler {TumblerServer.ToString()}");
            }
        }
예제 #8
0
        public TumblerConfiguration LoadArgs(NetworksSelector networkSet, String[] args)
        {
            ConfigurationFile = args.Where(a => a.StartsWith("-conf=", StringComparison.Ordinal)).Select(a => a.Substring("-conf=".Length).Replace("\"", "")).FirstOrDefault();
            DataDir           = args.Where(a => a.StartsWith("-datadir=", StringComparison.Ordinal)).Select(a => a.Substring("-datadir=".Length).Replace("\"", "")).FirstOrDefault();
            if (DataDir != null && ConfigurationFile != null)
            {
                var isRelativePath = Path.GetFullPath(ConfigurationFile).Length > ConfigurationFile.Length;
                if (isRelativePath)
                {
                    ConfigurationFile = Path.Combine(DataDir, ConfigurationFile);
                }
            }

            Network = args.Contains("-testnet", StringComparer.OrdinalIgnoreCase) ? networkSet.Testnet() :
                      args.Contains("-regtest", StringComparer.OrdinalIgnoreCase) ? networkSet.Regtest() :
                      networkSet.Mainnet();

            if (ConfigurationFile != null)
            {
                AssetConfigFileExists();
                var configTemp = TextFileConfiguration.Parse(File.ReadAllText(ConfigurationFile));
                Network = configTemp.GetOrDefault <bool>("testnet", false) ? networkSet.Testnet() :
                          configTemp.GetOrDefault <bool>("regtest", false) ? networkSet.Regtest() :
                          networkSet.Mainnet();
            }
            if (DataDir == null)
            {
                DataDir = DefaultDataDirectory.GetDefaultDirectory("NTumbleBitServer", Network);
            }

            if (ConfigurationFile == null)
            {
                ConfigurationFile = GetDefaultConfigurationFile(Network);
            }
            Logs.Configuration.LogInformation("Network: " + Network);

            Logs.Configuration.LogInformation("Data directory set to " + DataDir);
            Logs.Configuration.LogInformation("Configuration file set to " + ConfigurationFile);

            if (!Directory.Exists(DataDir))
            {
                throw new ConfigurationException("Data directory does not exists");
            }

            var consoleConfig = new TextFileConfiguration(args);
            var config        = TextFileConfiguration.Parse(File.ReadAllText(ConfigurationFile));

            consoleConfig.MergeInto(config, true);

            if (config.Contains("help"))
            {
                Console.WriteLine("Details on the wiki page :  https://github.com/NTumbleBit/NTumbleBit/wiki/Server-Config");
                OpenBrowser("https://github.com/NTumbleBit/NTumbleBit/wiki/Server-Config");
                Environment.Exit(0);
            }

            var standardCycles = new StandardCycles(Network);
            var cycleName      = config.GetOrDefault <string>("cycle", standardCycles.Debug ? "shorty2x" : "kotori");

            Logs.Configuration.LogInformation($"Using cycle {cycleName}");

            var standardCycle = standardCycles.GetStandardCycle(cycleName);

            if (standardCycle == null)
            {
                throw new ConfigException($"Invalid cycle name, choose among {String.Join(",", standardCycles.ToEnumerable().Select(c => c.FriendlyName).ToArray())}");
            }

            ClassicTumblerParameters.CycleGenerator = standardCycle.Generator;
            ClassicTumblerParameters.Denomination   = standardCycle.Denomination;
            var torEnabled = config.GetOrDefault <bool>("tor.enabled", true);

            if (torEnabled)
            {
                TorSettings = TorConnectionSettings.ParseConnectionSettings("tor", config);
            }

            Cooperative = config.GetOrDefault <bool>("cooperative", true);

            var defaultPort = config.GetOrDefault <int>("port", 37123);

            OnlyMonitor = config.GetOrDefault <bool>("onlymonitor", false);
            Listen      = new IPEndPoint(IPAddress.Parse("127.0.0.1"), defaultPort);

            RPC = RPCArgs.Parse(config, Network);

            //0.1% fee by default
            var defaultFee = Money.Satoshis((decimal)ClassicTumblerParameters.Denomination.Satoshi * 0.001m);

            ClassicTumblerParameters.Fee = config.GetOrDefault <Money>("tumbler.fee", defaultFee);
            TorPath = config.GetOrDefault <string>("torpath", "tor");
            return(this);
        }