+
+
diff --git a/Lib9c b/Lib9c
index aa95dcffd..f8d681a6a 160000
--- a/Lib9c
+++ b/Lib9c
@@ -1 +1 @@
-Subproject commit aa95dcffd5f6dac64da413aa1b67bbf6a61b0be9
+Subproject commit f8d681a6a622431eacb989477071613ce2b5fc5c
diff --git a/NineChronicles.Headless.AccessControlCenter/AcsService.cs b/NineChronicles.Headless.AccessControlCenter/AccService.cs
similarity index 58%
rename from NineChronicles.Headless.AccessControlCenter/AcsService.cs
rename to NineChronicles.Headless.AccessControlCenter/AccService.cs
index 596d54fad..167beac3b 100644
--- a/NineChronicles.Headless.AccessControlCenter/AcsService.cs
+++ b/NineChronicles.Headless.AccessControlCenter/AccService.cs
@@ -2,16 +2,16 @@
using Microsoft.AspNetCore.Builder;
using Microsoft.AspNetCore.Hosting;
using Microsoft.AspNetCore.Server.Kestrel.Core;
-using Microsoft.Extensions.Configuration;
using Microsoft.Extensions.DependencyInjection;
using Microsoft.Extensions.Hosting;
+using Microsoft.OpenApi.Models;
using NineChronicles.Headless.AccessControlCenter.AccessControlService;
namespace NineChronicles.Headless.AccessControlCenter
{
- public class AcsService
+ public class AccService
{
- public AcsService(Configuration configuration)
+ public AccService(Configuration configuration)
{
Configuration = configuration;
}
@@ -49,6 +49,33 @@ public void ConfigureServices(IServiceCollection services)
{
services.AddControllers();
+ services.AddSwaggerGen(c =>
+ {
+ c.SwaggerDoc(
+ "v1",
+ new OpenApiInfo { Title = "Access Control Center API", Version = "v1" }
+ );
+ c.DocInclusionPredicate(
+ (docName, apiDesc) =>
+ {
+ var controllerType =
+ apiDesc.ActionDescriptor
+ as Microsoft.AspNetCore.Mvc.Controllers.ControllerActionDescriptor;
+ if (controllerType != null)
+ {
+ var assemblyName = controllerType.ControllerTypeInfo.Assembly
+ .GetName()
+ .Name;
+ var namespaceName = controllerType.ControllerTypeInfo.Namespace;
+ return namespaceName?.StartsWith(
+ "NineChronicles.Headless.AccessControlCenter"
+ ) ?? false;
+ }
+ return false;
+ }
+ );
+ });
+
var accessControlService = MutableAccessControlServiceFactory.Create(
Enum.Parse(
Configuration.AccessControlServiceType,
@@ -62,10 +89,11 @@ public void ConfigureServices(IServiceCollection services)
public void Configure(IApplicationBuilder app, IWebHostEnvironment env)
{
- if (env.IsDevelopment())
+ app.UseSwagger();
+ app.UseSwaggerUI(c =>
{
- app.UseDeveloperExceptionPage();
- }
+ c.SwaggerEndpoint("/swagger/v1/swagger.json", "Access Control Center API V1");
+ });
app.UseRouting();
app.UseAuthorization();
diff --git a/NineChronicles.Headless.AccessControlCenter/AccessControlService/IMutableAccessControlService.cs b/NineChronicles.Headless.AccessControlCenter/AccessControlService/IMutableAccessControlService.cs
index aa8207174..b5d52f697 100644
--- a/NineChronicles.Headless.AccessControlCenter/AccessControlService/IMutableAccessControlService.cs
+++ b/NineChronicles.Headless.AccessControlCenter/AccessControlService/IMutableAccessControlService.cs
@@ -6,8 +6,8 @@ namespace NineChronicles.Headless.AccessControlCenter.AccessControlService
{
public interface IMutableAccessControlService : IAccessControlService
{
- void DenyAccess(Address address);
- void AllowAccess(Address address);
- List ListBlockedAddresses(int offset, int limit);
+ void AddTxQuota(Address address, int quota);
+ void RemoveTxQuota(Address address);
+ List ListTxQuotaAddresses(int offset, int limit);
}
}
diff --git a/NineChronicles.Headless.AccessControlCenter/AccessControlService/MutableRedisAccessControlService.cs b/NineChronicles.Headless.AccessControlCenter/AccessControlService/MutableRedisAccessControlService.cs
index 89c614a0a..9cb412d88 100644
--- a/NineChronicles.Headless.AccessControlCenter/AccessControlService/MutableRedisAccessControlService.cs
+++ b/NineChronicles.Headless.AccessControlCenter/AccessControlService/MutableRedisAccessControlService.cs
@@ -2,34 +2,42 @@
using System.Linq;
using Libplanet.Crypto;
using NineChronicles.Headless.Services;
+using StackExchange.Redis;
namespace NineChronicles.Headless.AccessControlCenter.AccessControlService
{
- public class MutableRedisAccessControlService : RedisAccessControlService, IMutableAccessControlService
+ public class MutableRedisAccessControlService
+ : RedisAccessControlService,
+ IMutableAccessControlService
{
- public MutableRedisAccessControlService(string storageUri) : base(storageUri)
+ public MutableRedisAccessControlService(string storageUri)
+ : base(storageUri)
{
}
- public void DenyAccess(Address address)
+ public void AddTxQuota(Address address, int quota)
{
- _db.StringSet(address.ToString(), "denied");
+ _db.StringSet(address.ToString(), quota.ToString());
}
- public void AllowAccess(Address address)
+ public void RemoveTxQuota(Address address)
{
_db.KeyDelete(address.ToString());
}
- public List ListBlockedAddresses(int offset, int limit)
+ public List ListTxQuotaAddresses(int offset, int limit)
{
var server = _db.Multiplexer.GetServer(_db.Multiplexer.GetEndPoints().First());
- return server
- .Keys()
- .Select(k => new Address(k.ToString()))
- .Skip(offset)
- .Take(limit)
- .ToList();
+
+ var result = (RedisResult[]?)
+ server.Execute("SCAN", offset.ToString(), "COUNT", limit.ToString());
+ if (result != null)
+ {
+ RedisKey[] keys = (RedisKey[])result[1]!;
+ return keys.Select(k => new Address(k.ToString())).ToList();
+ }
+
+ return new List();
}
}
}
diff --git a/NineChronicles.Headless.AccessControlCenter/AccessControlService/MutableSqliteAccessControlService.cs b/NineChronicles.Headless.AccessControlCenter/AccessControlService/MutableSqliteAccessControlService.cs
index 1d9455118..daa2a9c37 100644
--- a/NineChronicles.Headless.AccessControlCenter/AccessControlService/MutableSqliteAccessControlService.cs
+++ b/NineChronicles.Headless.AccessControlCenter/AccessControlService/MutableSqliteAccessControlService.cs
@@ -1,3 +1,4 @@
+using System;
using System.Collections.Generic;
using Microsoft.Data.Sqlite;
using Libplanet.Crypto;
@@ -7,55 +8,56 @@ namespace NineChronicles.Headless.AccessControlCenter.AccessControlService
{
public class MutableSqliteAccessControlService : SQLiteAccessControlService, IMutableAccessControlService
{
- private const string DenyAccessSql =
- "INSERT OR IGNORE INTO blocklist (address) VALUES (@Address)";
- private const string AllowAccessSql = "DELETE FROM blocklist WHERE address=@Address";
+ private const string AddTxQuotaSql =
+ "INSERT OR IGNORE INTO txquotalist (address, quota) VALUES (@Address, @Quota)";
+ private const string RemoveTxQuotaSql = "DELETE FROM txquotalist WHERE address=@Address";
public MutableSqliteAccessControlService(string connectionString) : base(connectionString)
{
}
- public void DenyAccess(Address address)
+ public void AddTxQuota(Address address, int quota)
{
using var connection = new SqliteConnection(_connectionString);
connection.Open();
using var command = connection.CreateCommand();
- command.CommandText = DenyAccessSql;
+ command.CommandText = AddTxQuotaSql;
command.Parameters.AddWithValue("@Address", address.ToString());
+ command.Parameters.AddWithValue("@Quota", quota);
command.ExecuteNonQuery();
}
- public void AllowAccess(Address address)
+ public void RemoveTxQuota(Address address)
{
using var connection = new SqliteConnection(_connectionString);
connection.Open();
using var command = connection.CreateCommand();
- command.CommandText = AllowAccessSql;
+ command.CommandText = RemoveTxQuotaSql;
command.Parameters.AddWithValue("@Address", address.ToString());
command.ExecuteNonQuery();
}
- public List ListBlockedAddresses(int offset, int limit)
+ public List ListTxQuotaAddresses(int offset, int limit)
{
- var blockedAddresses = new List();
+ var txQuotaAddresses = new List();
using var connection = new SqliteConnection(_connectionString);
connection.Open();
using var command = connection.CreateCommand();
- command.CommandText = $"SELECT address FROM blocklist LIMIT @Limit OFFSET @Offset";
+ command.CommandText = $"SELECT address FROM txquotalist LIMIT @Limit OFFSET @Offset";
command.Parameters.AddWithValue("@Limit", limit);
command.Parameters.AddWithValue("@Offset", offset);
using var reader = command.ExecuteReader();
while (reader.Read())
{
- blockedAddresses.Add(new Address(reader.GetString(0)));
+ txQuotaAddresses.Add(new Address(reader.GetString(0)));
}
- return blockedAddresses;
+ return txQuotaAddresses;
}
}
}
diff --git a/NineChronicles.Headless.AccessControlCenter/Controllers/AccessControlServiceController.cs b/NineChronicles.Headless.AccessControlCenter/Controllers/AccessControlServiceController.cs
index 685dca35e..40117f900 100644
--- a/NineChronicles.Headless.AccessControlCenter/Controllers/AccessControlServiceController.cs
+++ b/NineChronicles.Headless.AccessControlCenter/Controllers/AccessControlServiceController.cs
@@ -1,3 +1,4 @@
+using System;
using System.Collections.Generic;
using Microsoft.AspNetCore.Mvc;
using NineChronicles.Headless.AccessControlCenter.AccessControlService;
@@ -17,30 +18,50 @@ public AccessControlServiceController(IMutableAccessControlService accessControl
}
[HttpGet("entries/{address}")]
- public ActionResult IsAccessDenied(string address)
+ public ActionResult GetTxQuota(string address)
{
- return _accessControlService.IsAccessDenied(new Address(address));
+ return _accessControlService.GetTxQuota(new Address(address));
}
- [HttpPost("entries/{address}/deny")]
- public ActionResult DenyAccess(string address)
+ [HttpPost("entries/add-tx-quota/{address}/{quota:int}")]
+ public ActionResult AddTxQuota(string address, int quota)
{
- _accessControlService.DenyAccess(new Address(address));
+ var maxQuota = 10;
+ if (quota > maxQuota)
+ {
+ return BadRequest($"The quota cannot exceed {maxQuota}.");
+ }
+
+ _accessControlService.AddTxQuota(new Address(address), quota);
return Ok();
}
- [HttpPost("entries/{address}/allow")]
- public ActionResult AllowAccess(string address)
+ [HttpPost("entries/remove-tx-quota/{address}")]
+ public ActionResult RemoveTxQuota(string address)
{
- _accessControlService.AllowAccess(new Address(address));
+ _accessControlService.RemoveTxQuota(new Address(address));
return Ok();
}
[HttpGet("entries")]
public ActionResult> ListBlockedAddresses(int offset, int limit)
{
+ var maxLimit = 10;
+ if (_accessControlService is MutableRedisAccessControlService)
+ {
+ maxLimit = 10;
+ }
+ else if (_accessControlService is MutableSqliteAccessControlService)
+ {
+ maxLimit = 100;
+ }
+ if (limit > maxLimit)
+ {
+ return BadRequest($"The limit cannot exceed {maxLimit}.");
+ }
+
return _accessControlService
- .ListBlockedAddresses(offset, limit)
+ .ListTxQuotaAddresses(offset, limit)
.Select(a => a.ToString())
.ToList();
}
diff --git a/NineChronicles.Headless.AccessControlCenter/NineChronicles.Headless.AccessControlCenter.csproj b/NineChronicles.Headless.AccessControlCenter/NineChronicles.Headless.AccessControlCenter.csproj
index 74be55c3b..1ca96b941 100644
--- a/NineChronicles.Headless.AccessControlCenter/NineChronicles.Headless.AccessControlCenter.csproj
+++ b/NineChronicles.Headless.AccessControlCenter/NineChronicles.Headless.AccessControlCenter.csproj
@@ -22,6 +22,7 @@
allruntime; build; native; contentfiles; analyzers; buildtransitive
+
diff --git a/NineChronicles.Headless.AccessControlCenter/Program.cs b/NineChronicles.Headless.AccessControlCenter/Program.cs
index ee262e673..c506b85dc 100644
--- a/NineChronicles.Headless.AccessControlCenter/Program.cs
+++ b/NineChronicles.Headless.AccessControlCenter/Program.cs
@@ -20,7 +20,7 @@ public static void Main(string[] args)
var acsConfig = new Configuration();
config.Bind(acsConfig);
- var service = new AcsService(acsConfig);
+ var service = new AccService(acsConfig);
var hostBuilder = service.Configure(Host.CreateDefaultBuilder(), acsConfig.Port);
var host = hostBuilder.Build();
host.Run();
diff --git a/NineChronicles.Headless.Executable/NineChronicles.Headless.Executable.csproj b/NineChronicles.Headless.Executable/NineChronicles.Headless.Executable.csproj
index 95b3ae808..433336e26 100644
--- a/NineChronicles.Headless.Executable/NineChronicles.Headless.Executable.csproj
+++ b/NineChronicles.Headless.Executable/NineChronicles.Headless.Executable.csproj
@@ -20,6 +20,7 @@
+
diff --git a/NineChronicles.Headless.Executable/Program.cs b/NineChronicles.Headless.Executable/Program.cs
index 731fb0380..9828513a3 100644
--- a/NineChronicles.Headless.Executable/Program.cs
+++ b/NineChronicles.Headless.Executable/Program.cs
@@ -43,6 +43,7 @@
namespace NineChronicles.Headless.Executable
{
+ [HasSubCommands(typeof(Cocona.Docs.DocumentCommand), "docs")]
[HasSubCommands(typeof(AccountCommand), "account")]
[HasSubCommands(typeof(ValidationCommand), "validation")]
[HasSubCommands(typeof(ChainCommand), "chain")]
diff --git a/NineChronicles.Headless.Tests/GraphTypes/States/Models/CrystalMonsterCollectionMultiplierSheetTypeTest.cs b/NineChronicles.Headless.Tests/GraphTypes/States/Models/CrystalMonsterCollectionMultiplierSheetTypeTest.cs
index a1a20e7a5..491f17b83 100644
--- a/NineChronicles.Headless.Tests/GraphTypes/States/Models/CrystalMonsterCollectionMultiplierSheetTypeTest.cs
+++ b/NineChronicles.Headless.Tests/GraphTypes/States/Models/CrystalMonsterCollectionMultiplierSheetTypeTest.cs
@@ -59,6 +59,16 @@ public async Task Query()
["level"] = 5,
["multiplier"] = 300,
},
+ new Dictionary
+ {
+ ["level"] = 6,
+ ["multiplier"] = 300,
+ },
+ new Dictionary
+ {
+ ["level"] = 7,
+ ["multiplier"] = 300,
+ },
};
var expected = new Dictionary { { "orderedList", list } };
Assert.Equal(expected, data);
diff --git a/NineChronicles.Headless/GraphTypes/States/CombinationSlotStateType.cs b/NineChronicles.Headless/GraphTypes/States/CombinationSlotStateType.cs
index b6742f078..dbc19948c 100644
--- a/NineChronicles.Headless/GraphTypes/States/CombinationSlotStateType.cs
+++ b/NineChronicles.Headless/GraphTypes/States/CombinationSlotStateType.cs
@@ -16,10 +16,13 @@ public CombinationSlotStateType()
nameof(CombinationSlotState.UnlockBlockIndex),
description: "Block index at the combination slot can be usable.",
resolve: context => context.Source.UnlockBlockIndex);
+#pragma warning disable CS0618
Field>(
- nameof(CombinationSlotState.UnlockStage),
+ nameof(
+ CombinationSlotState.UnlockStage),
description: "Stage id at the combination slot unlock.",
resolve: context => context.Source.UnlockStage);
+#pragma warning restore CS0618
Field>(
nameof(CombinationSlotState.StartBlockIndex),
description: "Block index at the combination started.",
diff --git a/NineChronicles.Headless/Services/RedisAccessControlService.cs b/NineChronicles.Headless/Services/RedisAccessControlService.cs
index b1dfb5e74..40769292d 100644
--- a/NineChronicles.Headless/Services/RedisAccessControlService.cs
+++ b/NineChronicles.Headless/Services/RedisAccessControlService.cs
@@ -1,6 +1,8 @@
+using System;
using StackExchange.Redis;
using Libplanet.Crypto;
using Nekoyume.Blockchain;
+using Serilog;
namespace NineChronicles.Headless.Services
{
@@ -14,9 +16,17 @@ public RedisAccessControlService(string storageUri)
_db = redis.GetDatabase();
}
- public bool IsAccessDenied(Address address)
+ public int? GetTxQuota(Address address)
{
- return _db.KeyExists(address.ToString());
+ RedisValue result = _db.StringGet(address.ToString());
+ if (!result.IsNull)
+ {
+ Log.ForContext("Source", nameof(IAccessControlService))
+ .Debug("\"{Address}\" Tx Quota: {Quota}", address, result);
+ return Convert.ToInt32(result);
+ }
+
+ return null;
}
}
}
diff --git a/NineChronicles.Headless/Services/SQLiteAccessControlService.cs b/NineChronicles.Headless/Services/SQLiteAccessControlService.cs
index 0a9c1e456..f3e7263c8 100644
--- a/NineChronicles.Headless/Services/SQLiteAccessControlService.cs
+++ b/NineChronicles.Headless/Services/SQLiteAccessControlService.cs
@@ -1,15 +1,17 @@
+using System;
using Microsoft.Data.Sqlite;
using Libplanet.Crypto;
using Nekoyume.Blockchain;
+using Serilog;
namespace NineChronicles.Headless.Services
{
public class SQLiteAccessControlService : IAccessControlService
{
private const string CreateTableSql =
- "CREATE TABLE IF NOT EXISTS blocklist (address VARCHAR(42))";
- private const string CheckAccessSql =
- "SELECT EXISTS(SELECT 1 FROM blocklist WHERE address=@Address)";
+ "CREATE TABLE IF NOT EXISTS txquotalist (address VARCHAR(42), quota INT)";
+ private const string GetTxQuotaSql =
+ "SELECT quota FROM txquotalist WHERE address=@Address";
protected readonly string _connectionString;
@@ -24,18 +26,23 @@ public SQLiteAccessControlService(string connectionString)
command.ExecuteNonQuery();
}
- public bool IsAccessDenied(Address address)
+ public int? GetTxQuota(Address address)
{
using var connection = new SqliteConnection(_connectionString);
connection.Open();
using var command = connection.CreateCommand();
- command.CommandText = CheckAccessSql;
+ command.CommandText = GetTxQuotaSql;
command.Parameters.AddWithValue("@Address", address.ToString());
- var result = command.ExecuteScalar();
+ var queryResult = command.ExecuteScalar();
- return result is not null && (long)result == 1;
+ if (queryResult != null)
+ {
+ return Convert.ToInt32(queryResult);
+ }
+
+ return null;
}
}
}
diff --git a/README.md b/README.md
index 28430b15f..08982cd5a 100644
--- a/README.md
+++ b/README.md
@@ -3,166 +3,16 @@
[![Planetarium Discord invite](https://img.shields.io/discord/539405872346955788?color=6278DA&label=Planetarium&logo=discord&logoColor=white)](https://discord.gg/JyujU8E4SD)
[![Planetarium-Dev Discord Invite](https://img.shields.io/discord/928926944937013338?color=6278DA&label=Planetarium-dev&logo=discord&logoColor=white)](https://discord.gg/RYJDyFRYY7)
-## Table of Contents
-
-- [Run](#run)
-- [Docker Build](#docker-build)
- * [Format](#format)
-- [How to run NineChronicles Headless on AWS EC2 instance using Docker](#how-to-run-ninechronicles-headless-on-aws-ec2-instance-using-docker)
- * [On Your AWS EC2 Instance](#on-your-aws-ec2-instance)
- * [Building Your Own Docker Image from Your Local Machine](#building-your-own-docker-image-from-your-local-machine)
-- [Nine Chronicles GraphQL API Documentation](#nine-chronicles-graphql-api-documentation)
-- [Create A New Genesis Block](#create-a-new-genesis-block)
-
## Run
+If you want to run node to interact with mainnet, you can run the below command line:
+
```
-$ dotnet run --project ./NineChronicles.Headless.Executable/ -- --help
-
-Usage: NineChronicles.Headless.Executable [command]
-Usage: NineChronicles.Headless.Executable
-
-// basic
-[--app-protocol-version ]
-[--trusted-app-protocol-version-signer ...]
-[--genesis-block-path ]
-[--host ]
-[--port ]
-[--swarm-private-key ]
-
-// Policy
-[--skip-preload]
-[--chain-tip-stale-behavior-type ]
-[--confirmations ]
-[--tx-life-time ]
-[--message-timeout ]
-[--tip-timeout ]
-[--demand-buffer ]
-[--tx-quota-per-signer ]
-[--maximum-poll-peers ]
-
-// Store
-[--store-type ]
-[--store-path ]
-[--no-reduce-store]
-
-// Network
-[--network-type ]
-[--ice-server ...]
-[--peer ...]
-[--static-peer ...]
-[--minimum-broadcast-target ]
-[--bucket-size ]
-
-// render
-[--nonblock-renderer]
-[--nonblock-renderer-queue ]
-[--strict-rendering]
-[--log-action-renders]
-
-// consensus
-[--consensus-port ]
-[--consensus-private-key ]
-[--consensus-seed ...]
-
-// RPC
-[--rpc-server]
-[--rpc-listen-host ]
-[--rpc-listen-port ]
-[--rpc-remote-server]
-[--rpc-http-server]
-
-// GraphQL
-[--graphql-server]
-[--graphql-host ]
-[--graphql-port ]
-[--graphql-secret-token-path ]
-[--no-cors]
-
-// Sentry
-[--sentry-dsn ]
-[--sentry-trace-sample-rate ]
-
-// ETC
-[--config ]
-[--help]
-[--version]
-
-// Miner (Deprecated)
-[--no-miner]
-[--miner-count ]
-[--miner-private-key ]
-[--miner.block-interval ]
-
-
-NineChronicles.Headless.Executable
-
-Commands:
- account
- validation
- chain
- key
- apv
- action
- state
- tx
- market
- genesis
- replay
-
-Options:
- -V, --app-protocol-version App protocol version token.
- -G, --genesis-block-path Genesis block path of blockchain. Blockchain is recognized by its genesis block.
- -H, --host Hostname of this node for another nodes to access. This is not listening host like 0.0.0.0
- -P, --port Port of this node for another nodes to access.
- --swarm-private-key The private key used for signing messages and to specify your node. If you leave this null, a randomly generated value will be used.
- --no-miner Disable block mining.
- --miner-count The number of miner task(thread).
- --miner-private-key The private key used for mining blocks. Must not be null if you want to turn on mining with libplanet-node.
- --miner.block-interval The miner's break time after mining a block. The unit is millisecond.
- --store-type The type of storage to store blockchain data. If not provided, "LiteDB" will be used as default. Available type: ["rocksdb", "memory"]
- --store-path Path of storage. This value is required if you use persistent storage e.g. "rocksdb"
- --no-reduce-store Do not reduce storage. Enabling this option will use enormous disk spaces.
- -I, --ice-server ... ICE server to NAT traverse.
- --peer ... Seed peer list to communicate to another nodes.
- -T, --trusted-app-protocol-version-signer ... Trustworthy signers who claim new app protocol versions
- --rpc-server Use this option if you want to make unity clients to communicate with this server with RPC
- --rpc-listen-host RPC listen host
- --rpc-listen-port RPC listen port
- --rpc-remote-server Do a role as RPC remote server? If you enable this option, multiple Unity clients can connect to your RPC server.
- --rpc-http-server If you enable this option with "rpcRemoteServer" option at the same time, RPC server will use HTTP/1, not gRPC.
- --graphql-server Use this option if you want to enable GraphQL server to enable querying data.
- --graphql-host GraphQL listen host
- --graphql-port GraphQL listen port
- --graphql-secret-token-path The path to write GraphQL secret token. If you want to protect this headless application, you should use this option and take it into headers.
- --no-cors Run without CORS policy.
- --confirmations The number of required confirmations to recognize a block.
- --nonblock-renderer Uses non-blocking renderer, which prevents the blockchain & swarm from waiting slow rendering. Turned off by default.
- --nonblock-renderer-queue The size of the queue used by the non-blocking renderer. Ignored if --nonblock-renderer is turned off.
- --strict-rendering Flag to turn on validating action renderer.
- --log-action-renders Log action renders besides block renders. --rpc-server implies this.
- --network-type Network type. (Allowed values: Main, Internal, Permanent, Test, Default)
- --tx-life-time The lifetime of each transaction, which uses minute as its unit.
- --message-timeout The grace period for new messages, which uses second as its unit.
- --tip-timeout The grace period for tip update, which uses second as its unit.
- --demand-buffer A number of block size that determines how far behind the demand the tip of the chain will publish `NodeException` to GraphQL subscriptions.
- --static-peer ... A list of peers that the node will continue to maintain.
- --skip-preload Run node without preloading.
- --minimum-broadcast-target Minimum number of peers to broadcast message.
- --bucket-size Number of the peers can be stored in each bucket.
- --chain-tip-stale-behavior-type Determines behavior when the chain's tip is stale. "reboot" and "preload" is available and "reboot" option is selected by default.
- --tx-quota-per-signer The number of maximum transactions can be included in stage per signer.
- --maximum-poll-peers The maximum number of peers to poll blocks. int.MaxValue by default.
- --consensus-port Port used for communicating consensus related messages. null by default.
- --consensus-private-key The private key used for signing consensus messages. Cannot be null.
- --consensus-seed ... A list of seed peers to join the block consensus.
- -C, --config Absolute path of "appsettings.json" file to provide headless configurations. (Default: appsettings.json)
- --sentry-dsn Sentry DSN
- --sentry-trace-sample-rate Trace sample rate for sentry
- -h, --help Show help message
- --version Show version
+dotnet run --project NineChronicles.Headless.Executable -C appsettings.mainnet.json --store-path={PATH_TO_STORE}
```
+For more information on the command line options, refer to the [CLI Documentation](https://planetarium.github.io/NineChronicles.Headless/cli).
+
### Use `appsettings.{network}.json` to provide CLI options
You can provide headless CLI options using file, `appsettings.json`. You'll find the default file at [here](NineChronicles.Headless.Executable/appsettings.json).
@@ -286,7 +136,7 @@ $ docker push [/]:[]
Check out [Nine Chronicles GraphQL API Tutorial](https://www.notion.so/Getting-Started-with-Nine-Chronicles-GraphQL-API-a14388a910844a93ab8dc0a2fe269f06) to get you started with using GraphQL API with NineChronicles Headless.
-For more information on the GraphQL API, refer to the [NineChronicles Headless GraphQL Documentation](http://api.nine-chronicles.com/).
+For more information on the GraphQL API, refer to the [NineChronicles Headless GraphQL Documentation](https://planetarium.github.io/NineChronicles.Headless/graphql).
---