Ejemplo n.º 1
0
        private static IStore LoadStore(Options options)
        {
            bool   readOnlyMode = options.Seeds is null;
            IStore innerStore;

            switch (options.StoreType)
            {
            case "rocksdb":
                innerStore = new RocksDBStore.RocksDBStore(options.StorePath);
                break;

            case "default":
                innerStore = new DefaultStore(
                    options.StorePath,
                    flush: false,
                    readOnly: readOnlyMode);
                break;

            default:
                // FIXME: give available store type as argument hint without code duplication.
                var    availableStoreTypes = new[] { "rocksdb", "default" };
                string longOptionName      = options.GetType().GetProperty(nameof(options.StoreType))
                                             .GetCustomAttribute <OptionAttribute>().LongName;
                throw new InvalidOptionValueException(
                          "--" + longOptionName,
                          options.StoreType,
                          availableStoreTypes);
            }

            IStore store;

            if (options.Seeds.Any())
            {
                // Wrap up store to use more useful features.
                store = new RichStore(
                    innerStore,
                    path: options.StorePath,
                    flush: false,
                    readOnly: readOnlyMode
                    );
            }
            else
            {
                // If there were no given seeds,
                // use the store directly.
                store = innerStore;
            }

            return(store);
        }
Ejemplo n.º 2
0
        public static async Task Main(string[] args)
        {
            Options options = Options.Parse(args, Console.Error);

            var loggerConfig = new LoggerConfiguration();

            loggerConfig = options.Debug
                ? loggerConfig.MinimumLevel.Debug()
                : loggerConfig.MinimumLevel.Information();
            loggerConfig = loggerConfig
                           .MinimumLevel.Override("Microsoft", LogEventLevel.Information)
                           .Enrich.FromLogContext()
                           .WriteTo.Console();
            Log.Logger = loggerConfig.CreateLogger();

            bool readOnlyMode = options.Seeds is null;

            // Initialized DefaultStore.
            IStore store = new DefaultStore(
                path: options.StorePath,
                flush: false,
                readOnly: readOnlyMode
                );

            if (options.Seeds.Any())
            {
                // Warp up store.
                store = new RichStore(
                    store,
                    path: options.StorePath,
                    flush: false,
                    readOnly: readOnlyMode
                    );
            }

            IBlockPolicy <AppAgnosticAction> policy = new BlockPolicy <AppAgnosticAction>(
                null,
                blockIntervalMilliseconds: options.BlockIntervalMilliseconds,
                minimumDifficulty: options.MinimumDifficulty,
                difficultyBoundDivisor: options.DifficultyBoundDivisor);
            var blockChain = new BlockChain <AppAgnosticAction>(policy, store, options.GenesisBlock);

            Startup.BlockChainSingleton = blockChain;
            Startup.StoreSingleton      = store;

            IWebHost webHost = WebHost.CreateDefaultBuilder()
                               .UseStartup <ExplorerStartup <AppAgnosticAction, Startup> >()
                               .UseSerilog()
                               .UseUrls($"http://{options.Host}:{options.Port}/")
                               .Build();

            Swarm <AppAgnosticAction> swarm = null;

            if (options.Seeds.Any())
            {
                Console.WriteLine(
                    $"Seeds are {options.SeedStrings.Aggregate(string.Empty, (s, s1) => s + s1)}");

                // TODO: Take privateKey as a CLI option
                // TODO: Take appProtocolVersion as a CLI option
                // TODO: Take host as a CLI option
                // TODO: Take listenPort as a CLI option
                if (options.IceServer is null)
                {
                    Console.Error.WriteLine(
                        "error: -s/--seed option requires -I/--ice-server as well."
                        );
                    Environment.Exit(1);
                    return;
                }

                Console.WriteLine("Creating Swarm.");

                var privateKey = new PrivateKey();

                // FIXME: The appProtocolVersion should be fixed properly.
                swarm = new Swarm <AppAgnosticAction>(
                    blockChain,
                    privateKey,
                    options.AppProtocolVersionToken is string t
                        ? AppProtocolVersion.FromToken(t)
                        : default(AppProtocolVersion),
                    differentAppProtocolVersionEncountered: (p, pv, lv) => true,
                    iceServers: new[] { options.IceServer }
                    );
            }

            using (var cts = new CancellationTokenSource())
                using (swarm)
                {
                    Console.CancelKeyPress += (sender, eventArgs) =>
                    {
                        eventArgs.Cancel = true;
                        cts.Cancel();
                    };

                    try
                    {
                        await Task.WhenAll(
                            webHost.RunAsync(cts.Token),
                            StartSwarmAsync(swarm, options.Seeds, cts.Token)
                            );
                    }
                    catch (OperationCanceledException)
                    {
                        await swarm?.StopAsync(waitFor : TimeSpan.FromSeconds(1))
                        .ContinueWith(_ => NetMQConfig.Cleanup(false));
                    }
                }
        }