Exemplo n.º 1
0
        public static void Main(string[] args)
        {
            var serviceProvider = new ServiceCollection()
                                  .AddLogging()
                                  .AddSingleton <ITumblerService, TumblerService>()
                                  .BuildServiceProvider();

            serviceProvider
            .GetService <ILoggerFactory>()
            .AddConsole(LogLevel.Debug);

            // TODO: It is messy having both a BreezeServer logger and an NTumbleBit logger
            var logger = serviceProvider.GetService <ILoggerFactory>()
                         .CreateLogger <Program>();

            logger.LogInformation("{Time} Reading Breeze server configuration", DateTime.Now);

            // Check OS-specific default config path for the config file. Create default file if it does not exist
            var configDir  = BreezeConfiguration.GetDefaultDataDir("BreezeServer");
            var configPath = Path.Combine(configDir, "breeze.conf");

            logger.LogInformation("{Time} Configuration file path {Path}", DateTime.Now, configPath);

            var config = new BreezeConfiguration(configPath);

            var dbPath = Path.Combine(configDir, "db");

            logger.LogInformation("{Time} Database path {Path}", DateTime.Now, dbPath);

            var db = new DBUtils(dbPath);

            logger.LogInformation("{Time} Checking node registration on the blockchain", DateTime.Now);

            var registration = new BreezeRegistration();

            if (!registration.CheckBreezeRegistration(config, db))
            {
                logger.LogInformation("{Time} Creating or updating node registration", DateTime.Now);
                var regTx = registration.PerformBreezeRegistration(config, db);
                if (regTx != null)
                {
                    logger.LogInformation("{Time} Submitted transaction {TxId} via RPC for broadcast", DateTime.Now, regTx.GetHash().ToString());
                }
                else
                {
                    logger.LogInformation("{Time} Unable to broadcast transaction via RPC", DateTime.Now);
                    Environment.Exit(0);
                }
            }
            else
            {
                logger.LogInformation("{Time} Node registration has already been performed", DateTime.Now);
            }

            logger.LogInformation("{Time} Starting Tumblebit server", DateTime.Now);

            db.UpdateOrInsert <string>("TumblerStartupLog", DateTime.Now.ToString("yyyyMMddHHmmss"), "Tumbler starting", (o, n) => n);

            var tumbler = serviceProvider.GetService <ITumblerService>();

            tumbler.StartTumbler(config.IsTestNet);
        }
Exemplo n.º 2
0
        public static void Main(string[] args)
        {
            var comparer          = new CommandlineArgumentComparer();
            var isRegTest         = args.Contains("regtest", comparer);
            var isTestNet         = args.Contains("testnet", comparer);
            var forceRegistration = args.Contains("forceRegistration", comparer);

            var useTor = !args.Contains("noTor", comparer);

            TumblerProtocolType?tumblerProtocol = null;

            try
            {
                string tumblerProtocolString = args.Where(a => a.StartsWith("-tumblerProtocol=")).Select(a => a.Substring("-tumblerProtocol=".Length).Replace("\"", "")).FirstOrDefault();
                if (!isRegTest && (tumblerProtocolString != null || !useTor))
                {
                    Console.WriteLine("Options -TumblerProtocol and -NoTor can only be used in combination with -RegTest switch.");
                    return;
                }

                if (tumblerProtocolString != null)
                {
                    tumblerProtocol = Enum.Parse <TumblerProtocolType>(tumblerProtocolString, true);
                }

                if (useTor && tumblerProtocol.HasValue && tumblerProtocol.Value == TumblerProtocolType.Http)
                {
                    Console.WriteLine("TumblerProtocol can only be changed to Http when Tor is disabled. Please use -NoTor switch to disable Tor.");
                    return;
                }
            }
            catch
            {
                Console.WriteLine($"Incorrect tumbling prococol specified; the valid values are {TumblerProtocolType.Tcp} and {TumblerProtocolType.Http}");
                return;
            }

            var serviceProvider = new ServiceCollection()
                                  .AddLogging()
                                  .AddSingleton <ITumblerService, TumblerService>()
                                  .BuildServiceProvider();

            serviceProvider
            .GetService <ILoggerFactory>()
            .AddConsole(LogLevel.Debug);

            // TODO: It is messy having both a BreezeServer logger and an NTumbleBit logger
            var logger = serviceProvider.GetService <ILoggerFactory>()
                         .CreateLogger <Program>();

            logger.LogInformation("{Time} Reading Breeze server configuration", DateTime.Now);

            // Check OS-specific default config path for the config file. Create default file if it does not exist
            string configDir = BreezeConfiguration.GetDefaultDataDir("BreezeServer");

            if (isRegTest)
            {
                configDir = Path.Combine(configDir, "ImpleumRegTest");
            }
            else if (isTestNet)
            {
                configDir = Path.Combine(configDir, "ImpleumTest");
            }
            else
            {
                configDir = Path.Combine(configDir, "ImpleumMain");
            }

            string configPath = Path.Combine(configDir, "breeze.conf");

            logger.LogInformation("{Time} Configuration file path {Path}", DateTime.Now, configPath);

            BreezeConfiguration config = new BreezeConfiguration(configPath);

            if (!useTor)
            {
                config.UseTor = false;
            }

            logger.LogInformation("{Time} Pre-initialising server to obtain parameters for configuration", DateTime.Now);

            var preTumblerConfig = serviceProvider.GetService <ITumblerService>();

            preTumblerConfig.StartTumbler(config, true, torMandatory: !isRegTest, tumblerProtocol: tumblerProtocol);

            string configurationHash = preTumblerConfig.runtime.ClassicTumblerParameters.GetHash().ToString();
            string onionAddress      = preTumblerConfig.runtime.TorUri.Host.Substring(0, 16);

            NTumbleBit.RsaKey tumblerKey = preTumblerConfig.runtime.TumblerKey;

            // No longer need this instance of the class
            if (config.UseTor)
            {
                preTumblerConfig.runtime.TorConnection.Dispose();
            }
            preTumblerConfig = null;

            string regStorePath = Path.Combine(configDir, "registrationHistory.json");

            logger.LogInformation("{Time} Registration history path {Path}", DateTime.Now, regStorePath);
            logger.LogInformation("{Time} Checking node registration", DateTime.Now);

            BreezeRegistration registration = new BreezeRegistration();

            if (forceRegistration || !registration.CheckBreezeRegistration(config, regStorePath, configurationHash, onionAddress, tumblerKey))
            {
                logger.LogInformation("{Time} Creating or updating node registration", DateTime.Now);
                var regTx = registration.PerformBreezeRegistration(config, regStorePath, configurationHash, onionAddress, tumblerKey);
                if (regTx != null)
                {
                    logger.LogInformation("{Time} Submitted transaction {TxId} via RPC for broadcast", DateTime.Now, regTx.GetHash().ToString());
                }
                else
                {
                    logger.LogInformation("{Time} Unable to broadcast transaction via RPC", DateTime.Now);
                    Environment.Exit(0);
                }
            }
            else
            {
                logger.LogInformation("{Time} Node registration has already been performed", DateTime.Now);
            }

            // Perform collateral balance check and report the result
            Money collateralShortfall;

            if (registration.VerifyCollateral(config, out collateralShortfall))
            {
                logger.LogInformation($"{{Time}} The collateral address {config.TumblerEcdsaKeyAddress} has sufficient funds.", DateTime.Now);
            }
            else
            {
                logger.LogWarning($"{{Time}} The collateral address {config.TumblerEcdsaKeyAddress} doesn't have enough funds. Collateral requirement is {RegistrationParameters.MASTERNODE_COLLATERAL_THRESHOLD} but only {collateralShortfall} is available at the collateral address. This is expected if you have only just run the masternode for the first time. Please send funds to the collateral address no later than {RegistrationParameters.WINDOW_PERIOD_BLOCK_COUNT} blocks after the registration transaction.", DateTime.Now);
            }

            logger.LogInformation("{Time} Starting Tumblebit server", DateTime.Now);

            // The TimeStamp and BlockSignature flags could be set to true when the Stratis network is instantiated.
            // We need to set it to false here to ensure compatibility with the Bitcoin protocol.
            Transaction.TimeStamp = false;
            Block.BlockSignature  = false;

            var tumbler = serviceProvider.GetService <ITumblerService>();

            tumbler.StartTumbler(config, false, torMandatory: !isRegTest, tumblerProtocol: tumblerProtocol);
        }
Exemplo n.º 3
0
        public static void Main(string[] args)
        {
            var serviceProvider = new ServiceCollection()
                                  .AddLogging()
                                  .AddSingleton <ITumblerService, TumblerService>()
                                  .BuildServiceProvider();

            serviceProvider
            .GetService <ILoggerFactory>()
            .AddConsole(LogLevel.Debug);

            // TODO: It is messy having both a BreezeServer logger and an NTumbleBit logger
            var logger = serviceProvider.GetService <ILoggerFactory>()
                         .CreateLogger <Program>();

            logger.LogInformation("{Time} Reading Breeze server configuration", DateTime.Now);

            // Check OS-specific default config path for the config file. Create default file if it does not exist
            string configDir  = BreezeConfiguration.GetDefaultDataDir("BreezeServer");
            string configPath = Path.Combine(configDir, "breeze.conf");

            logger.LogInformation("{Time} Configuration file path {Path}", DateTime.Now, configPath);

            BreezeConfiguration config = new BreezeConfiguration(configPath);

            logger.LogInformation("{Time} Pre-initialising server to obtain parameters for configuration", DateTime.Now);

            var preTumblerConfig = serviceProvider.GetService <ITumblerService>();

            preTumblerConfig.StartTumbler(config.IsTestNet, true);

            string configurationHash = preTumblerConfig.runtime.ClassicTumblerParameters.GetHash().ToString();
            string onionAddress      = preTumblerConfig.runtime.TorUri.Host.Substring(0, 16);

            NTumbleBit.RsaKey tumblerKey = preTumblerConfig.runtime.TumblerKey;

            // Mustn't be occupying hidden service URL when the TumblerService is reinitialised
            preTumblerConfig.runtime.TorConnection.Dispose();

            // No longer need this instance of the class
            preTumblerConfig = null;

            string regStorePath = Path.Combine(configDir, "registrationHistory.json");

            logger.LogInformation("{Time} Registration history path {Path}", DateTime.Now, regStorePath);
            logger.LogInformation("{Time} Checking node registration", DateTime.Now);

            BreezeRegistration registration = new BreezeRegistration();

            if (!registration.CheckBreezeRegistration(config, regStorePath, configurationHash, onionAddress, tumblerKey))
            {
                logger.LogInformation("{Time} Creating or updating node registration", DateTime.Now);
                var regTx = registration.PerformBreezeRegistration(config, regStorePath, configurationHash, onionAddress, tumblerKey);
                if (regTx != null)
                {
                    logger.LogInformation("{Time} Submitted transaction {TxId} via RPC for broadcast", DateTime.Now, regTx.GetHash().ToString());
                }
                else
                {
                    logger.LogInformation("{Time} Unable to broadcast transaction via RPC", DateTime.Now);
                    Environment.Exit(0);
                }
            }
            else
            {
                logger.LogInformation("{Time} Node registration has already been performed", DateTime.Now);
            }

            logger.LogInformation("{Time} Starting Tumblebit server", DateTime.Now);

            var tumbler = serviceProvider.GetService <ITumblerService>();

            tumbler.StartTumbler(config.IsTestNet, false);
        }
Exemplo n.º 4
0
        public void ParseTransaction(Transaction tx, Network network)
        {
            if (tx.Outputs.Count < 2)
            {
                throw new Exception("Transaction does not have sufficient outputs");
            }

            var breezeReg = new BreezeRegistration();

            // Assume the nulldata transaction marker is the first output

            //var firstOutputData = breezeReg.AddressToBytes(tx.Outputs[0].ScriptPubKey.GetDestinationAddress(network));

            // TODO: Validate that the marker bytes are present before proceeding

            // Peek at first non-nulldata address to get the length information,
            // this indicates if there will be a change address output or not

            var secondOutputData = breezeReg.AddressToBytes(tx.Outputs[1].ScriptPubKey.GetDestinationAddress(network));

            var protocolVersion = (int)secondOutputData[0];

            var headerLength = ((int)secondOutputData[2] << 8) + ((int)secondOutputData[1]);

            int numAddresses = headerLength / 20;

            if (headerLength % 20 != 0)
            {
                numAddresses++;
            }

            if (tx.Outputs.Count < (numAddresses + 1))
            {
                throw new Exception("Too few addresses in transaction output, registration transaction incomplete");
            }

            var addressList = new List <BitcoinAddress>();

            for (var i = 1; i < (numAddresses + 1); i++)
            {
                addressList.Add(tx.Outputs[i].ScriptPubKey.GetDestinationAddress(network));
            }

            var bitstream = breezeReg.AddressesToBytes(addressList);

            // Need to consume X bytes at a time off the bitstream and convert them to various
            // data types, then set member variables to the retrieved values.

            // Skip over protocol version and header length bytes
            var position = 3;

            ProtocolVersion = protocolVersion;

            // Either a valid IPv4 address, or all zero bytes
            bool allZeroes = true;

            byte[] ipv4temp = GetSubArray(bitstream, position, 4);

            for (var i = 0; i < ipv4temp.Length; i++)
            {
                if (ipv4temp[i] != 0)
                {
                    allZeroes = false;
                }
            }

            if (!allZeroes)
            {
                Ipv4Addr = new IPAddress(ipv4temp);
            }
            else
            {
                Ipv4Addr = null;
            }

            position += 4;

            // Either a valid IPv6 address, or all zero bytes
            allZeroes = true;
            byte[] ipv6temp = GetSubArray(bitstream, position, 16);

            for (var i = 0; i < ipv6temp.Length; i++)
            {
                if (ipv6temp[i] != 0)
                {
                    allZeroes = false;
                }
            }

            if (!allZeroes)
            {
                Ipv6Addr = new IPAddress(ipv6temp);
            }
            else
            {
                Ipv6Addr = null;
            }

            position += 16;

            // Either a valid onion address, or all zero bytes
            allZeroes = true;
            byte[] onionTemp = GetSubArray(bitstream, position, 16);

            for (var i = 0; i < onionTemp.Length; i++)
            {
                if (onionTemp[i] != 0)
                {
                    allZeroes = false;
                }
            }

            if (!allZeroes)
            {
                OnionAddress = Encoding.ASCII.GetString(onionTemp);
            }
            else
            {
                OnionAddress = null;
            }

            position += 16;

            var temp = GetSubArray(bitstream, position, 2);

            Port      = ((int)temp[1] << 8) + ((int)temp[0]);
            position += 2;

            temp = GetSubArray(bitstream, position, 2);
            var rsaLength = ((int)temp[1] << 8) + ((int)temp[0]);

            position += 2;

            RsaSignature = GetSubArray(bitstream, position, rsaLength);
            position    += rsaLength;

            temp = GetSubArray(bitstream, position, 2);
            var ecdsaLength = ((int)temp[1] << 8) + ((int)temp[0]);

            position += 2;

            EcdsaSignature = GetSubArray(bitstream, position, ecdsaLength);
            position      += ecdsaLength;

            // TODO: Validate signatures
        }