Skip to content

Commit

Permalink
WIP
Browse files Browse the repository at this point in the history
  • Loading branch information
s2quake committed Aug 27, 2024
1 parent 3b344cd commit 9dcdc98
Show file tree
Hide file tree
Showing 18 changed files with 547 additions and 31 deletions.
Original file line number Diff line number Diff line change
Expand Up @@ -12,6 +12,7 @@
<ItemGroup>
<PackageReference Include="Grpc.AspNetCore" Version="2.40.0"/>
<PackageReference Include="Grpc.AspNetCore.Server.Reflection" Version="2.64.0" />
<PackageReference Include="Serilog.Sinks.Console" Version="6.0.0" />
</ItemGroup>

<ItemGroup>
Expand All @@ -21,6 +22,7 @@
</ItemGroup>

<ItemGroup>
<ProjectReference Include="..\..\..\src\Libplanet.Crypto.Secp256k1\Libplanet.Crypto.Secp256k1.csproj" />
<ProjectReference Include="..\Libplanet.Node.Extensions\Libplanet.Node.Extensions.csproj" />
<ProjectReference Include="..\Libplanet.Node\Libplanet.Node.csproj" />
<ProjectReference Include="..\Libplanet.Node.Swagger\Libplanet.Node.Swagger.csproj" />
Expand Down
25 changes: 25 additions & 0 deletions sdk/node/Libplanet.Node.Executable/Program.cs
Original file line number Diff line number Diff line change
Expand Up @@ -3,6 +3,8 @@
using Libplanet.Node.Options.Schema;
using Microsoft.AspNetCore;
using Microsoft.AspNetCore.Server.Kestrel.Core;
using Serilog;
using Serilog.Events;

var builder = WebHost.CreateDefaultBuilder(args);
var assemblies = new string[]
Expand All @@ -14,6 +16,16 @@
builder.ConfigureLogging(logging =>
{
logging.AddConsole();

// Logging setting
var loggerConfig = new LoggerConfiguration();
loggerConfig = loggerConfig.MinimumLevel.Information();
loggerConfig = loggerConfig
.MinimumLevel.Override("Microsoft", LogEventLevel.Information)
.Enrich.FromLogContext()
.WriteTo.Console();

Log.Logger = loggerConfig.CreateLogger();
});
builder.ConfigureKestrel((context, options) =>
{
Expand All @@ -26,6 +38,19 @@
});
builder.ConfigureServices((context, services) =>
{
// string pluginPath = "/Users/bin_bash_shell/Workspaces/planetarium/NineChronicles/" +
// "lib9c/Lib9c.NCActionLoader/bin/Debug/net6.0/Lib9c.NCActionLoader.dll";
// string actionLoaderType = "Lib9c.NCActionLoader.NineChroniclesActionLoader";
// string blockPolicyType = "Lib9c.NCActionLoader.NineChroniclesPolicyActionRegistry";
// IActionLoader actionLoader = PluginLoader.LoadActionLoader(pluginPath, actionLoaderType);
// IPolicyActionsRegistry policyActionRegistry =
// PluginLoader.LoadPolicyActionRegistry(pluginPath, blockPolicyType);

// Libplanet.Crypto.CryptoConfig.CryptoBackend = new Secp256k1CryptoBackend<SHA256>();

// builder.Services.AddSingleton<IActionLoader>(actionLoader);
// builder.Services.AddSingleton<IPolicyActionsRegistry>(policyActionRegistry);

services.AddGrpc();
services.AddGrpcReflection();
services.AddLibplanetNode(context.Configuration);
Expand Down
32 changes: 29 additions & 3 deletions sdk/node/Libplanet.Node.Executable/appsettings-schema.json
Original file line number Diff line number Diff line change
Expand Up @@ -1106,6 +1106,22 @@
}
}
},
"Action": {
"title": "ActionOptions",
"type": "object",
"additionalProperties": false,
"properties": {
"ModulePath": {
"type": "string"
},
"ActionLoaderType": {
"type": "string"
},
"PolicyActionRegistryType": {
"type": "string"
}
}
},
"Genesis": {
"title": "GenesisOptions",
"type": "object",
Expand All @@ -1114,12 +1130,12 @@
"properties": {
"GenesisKey": {
"type": "string",
"description": "The key of the genesis block.",
"description": "The PrivateKey used to generate the genesis block. This property cannot be used with GenesisBlockPath.",
"pattern": "^[0-9a-fA-F]{64}$"
},
"Validators": {
"type": "array",
"description": "Public keys of the validators.",
"description": "Public keys of the validators. This property cannot be used with GenesisBlockPath.",
"items": {
"type": "string"
}
Expand All @@ -1131,7 +1147,7 @@
},
"GenesisBlockPath": {
"type": "string",
"description": "The path of the genesis block."
"description": "The path of the genesis block, which can be a file path or a URI.This property cannot be used with GenesisKey."
}
}
},
Expand Down Expand Up @@ -1221,6 +1237,12 @@
"type": "string",
"description": "The endpoint of the node to block sync.",
"pattern": "^$|^[0-9a-fA-F]{130}|[0-9a-fA-F]{66},\\s*(?:(?:[a-zA-Z0-9\\-\\.]+)|(?:\\d{1,3}\\.\\d{1,3}\\.\\d{1,3}\\.\\d{1,3})):\\d{1,5}$"
},
"TrustedAppProtocolVersionSigners": {
"type": "array",
"items": {
"type": "string"
}
}
}
},
Expand Down Expand Up @@ -1260,6 +1282,10 @@
"description": "Type 'ExplorerOptions' does not have a description.",
"$ref": "#/definitions/Explorer"
},
"Action": {
"description": "Type 'ActionOptions' does not have a description.",
"$ref": "#/definitions/Action"
},
"Genesis": {
"description": "Options for the genesis block.",
"$ref": "#/definitions/Genesis"
Expand Down
Original file line number Diff line number Diff line change
Expand Up @@ -24,6 +24,9 @@ public static ILibplanetNodeBuilder AddLibplanetNode(
.Bind(configuration.GetSection(StoreOptions.Position));
services.AddSingleton<IConfigureOptions<StoreOptions>, StoreOptionsConfigurator>();

services.AddOptions<ActionOptions>()
.Bind(configuration.GetSection(ActionOptions.Position));

services.AddOptions<SwarmOptions>()
.Bind(configuration.GetSection(SwarmOptions.Position));
services.AddSingleton<IConfigureOptions<SwarmOptions>, SwarmOptionsConfigurator>();
Expand Down
Original file line number Diff line number Diff line change
@@ -1,3 +1,5 @@
using Libplanet.Action;
using Libplanet.Action.Loader;
using Libplanet.Blockchain;
using Libplanet.Crypto;
using Libplanet.Node.Options;
Expand All @@ -20,6 +22,7 @@ public void Create_Test()
services.AddSingleton<IConfigureOptions<GenesisOptions>, GenesisOptionsConfigurator>();
services.AddOptions<StoreOptions>();
services.AddSingleton<IConfigureOptions<StoreOptions>, StoreOptionsConfigurator>();
services.AddOptions<ActionOptions>();
services.AddOptions<SwarmOptions>();
services.AddSingleton<IConfigureOptions<SwarmOptions>, SwarmOptionsConfigurator>();

Expand All @@ -28,11 +31,12 @@ public void Create_Test()
var logger = new NullLoggerFactory().CreateLogger<BlockChainService>();
var genesisOptions = serviceProvider.GetRequiredService<IOptions<GenesisOptions>>();
var storeOptions = serviceProvider.GetRequiredService<IOptions<StoreOptions>>();
var actionOptions = serviceProvider.GetRequiredService<IOptions<ActionOptions>>();
var blockChainService = new BlockChainService(
genesisOptions: genesisOptions,
storeOptions: storeOptions,
actionOptions: actionOptions,
policyService: policyService,
actionLoaderProviders: [],
logger: logger);
var blockChain = blockChainService.BlockChain;

Expand Down
79 changes: 79 additions & 0 deletions sdk/node/Libplanet.Node/Actions/ActionContextMarshaller.cs
Original file line number Diff line number Diff line change
@@ -0,0 +1,79 @@
using System.Security.Cryptography;
using Bencodex;
using Bencodex.Types;
using Libplanet.Action;
using Libplanet.Common;
using Libplanet.Crypto;
using Libplanet.Types.Tx;
using Boolean = Bencodex.Types.Boolean;

namespace Libplanet.Node.Actions;

public static class ActionContextMarshaller
{
private static readonly Codec Codec = new Codec();

public static byte[] Serialize(this ICommittedActionContext actionContext)
{
return Codec.Encode(Marshal(actionContext));
}

public static Dictionary Marshal(this ICommittedActionContext actionContext)
{
var dictionary = Bencodex.Types.Dictionary.Empty
.Add("signer", actionContext.Signer.ToHex())
.Add("miner", actionContext.Miner.ToHex())
.Add("block_index", actionContext.BlockIndex)
.Add("block_protocol_version", actionContext.BlockProtocolVersion)
.Add("previous_states", actionContext.PreviousState.ByteArray)
.Add("random_seed", actionContext.RandomSeed)
.Add("block_action", actionContext.IsPolicyAction);

if (actionContext.TxId is { } txId)
{
dictionary = dictionary.Add("tx_id", txId.ByteArray);
}

return dictionary;
}

public static ICommittedActionContext Unmarshal(Dictionary dictionary)
{
return new CommittedActionContext(
signer: new Address(((Text)dictionary["signer"]).Value),
txId: GetTxId(dictionary, "tx_id"),
miner: new Address(((Text)dictionary["miner"]).Value),
blockIndex: (Integer)dictionary["block_index"],
blockProtocolVersion: (Integer)dictionary["block_protocol_version"],
previousState: new HashDigest<SHA256>(dictionary["previous_states"]),
randomSeed: (Integer)dictionary["random_seed"],
isPolicyAction: (Boolean)dictionary["block_action"]
);

static TxId? GetTxId(Dictionary dictionary, string key)
{
if (dictionary.TryGetValue((Text)key, out IValue txIdValue)
&& txIdValue is Binary txIdBinaryValue)
{
return new TxId(txIdBinaryValue.ByteArray);
}
else
{
return null;
}
}
}

public static ICommittedActionContext Deserialize(byte[] serialized)
{
var decoded = Codec.Decode(serialized);
if (decoded is not Dictionary dictionary)
{
throw new ArgumentException(
message: $"Expected 'Dictionary' but {decoded.GetType().Name}",
paramName: nameof(serialized));
}

return Unmarshal(dictionary);
}
}
48 changes: 48 additions & 0 deletions sdk/node/Libplanet.Node/Actions/ActionEvaluationMarshaller.cs
Original file line number Diff line number Diff line change
@@ -0,0 +1,48 @@
using System.Security.Cryptography;
using Bencodex;
using Bencodex.Types;
using Libplanet.Action;
using Libplanet.Common;

namespace Libplanet.Node.Actions;

public static class ActionEvaluationMarshaller
{
private static readonly Codec Codec = new();

public static byte[] Serialize(this ICommittedActionEvaluation actionEvaluation)
{
return Codec.Encode(Marshal(actionEvaluation));
}

public static Dictionary Marshal(this ICommittedActionEvaluation actionEvaluation) =>
Dictionary.Empty
.Add("action", actionEvaluation.Action)
.Add("output_states", actionEvaluation.OutputState.ByteArray)
.Add("input_context", actionEvaluation.InputContext.Marshal())
.Add("exception", GetException(actionEvaluation.Exception));

public static ICommittedActionEvaluation Unmarshal(IValue value)
{
if (value is not Dictionary dictionary)
{
throw new ArgumentException("The value must be a dictionary.", nameof(value));
}

return new CommittedActionEvaluation(
dictionary["action"],
ActionContextMarshaller.Unmarshal((Dictionary)dictionary["input_context"]),
new HashDigest<SHA256>(dictionary["output_states"]),
dictionary["exception"] is Text typeName ? new Exception(typeName) : null
);
}

public static ICommittedActionEvaluation Deserialize(byte[] serialized)
{
var decoded = Codec.Decode(serialized);
return Unmarshal(decoded);
}

private static IValue GetException(Exception? exception)
=> exception?.GetType().FullName is { } typeName ? (Text)typeName : Null.Value;
}
70 changes: 70 additions & 0 deletions sdk/node/Libplanet.Node/Actions/PluggedActionEvaluator.cs
Original file line number Diff line number Diff line change
@@ -0,0 +1,70 @@
using System.Diagnostics;
using System.Reflection;
using System.Security.Cryptography;
using Lib9c.Plugin.Shared;

Check failure on line 4 in sdk/node/Libplanet.Node/Actions/PluggedActionEvaluator.cs

View workflow job for this annotation

GitHub Actions / docs

The type or namespace name 'Lib9c' could not be found (are you missing a using directive or an assembly reference?)

Check failure on line 4 in sdk/node/Libplanet.Node/Actions/PluggedActionEvaluator.cs

View workflow job for this annotation

GitHub Actions / docs

The type or namespace name 'Lib9c' could not be found (are you missing a using directive or an assembly reference?)

Check failure on line 4 in sdk/node/Libplanet.Node/Actions/PluggedActionEvaluator.cs

View workflow job for this annotation

GitHub Actions / check-build

The type or namespace name 'Lib9c' could not be found (are you missing a using directive or an assembly reference?)
using Libplanet.Action;
using Libplanet.Action.Loader;
using Libplanet.Common;
using Libplanet.Node.Actions;
using Libplanet.Store.Trie;
using Libplanet.Types.Blocks;

namespace Libplanet.Node.Actions;

public class PluggedActionEvaluator : IActionEvaluator
{
private readonly IPluginActionEvaluator _pluginActionEvaluator;

Check failure on line 16 in sdk/node/Libplanet.Node/Actions/PluggedActionEvaluator.cs

View workflow job for this annotation

GitHub Actions / docs

The type or namespace name 'IPluginActionEvaluator' could not be found (are you missing a using directive or an assembly reference?)

Check failure on line 16 in sdk/node/Libplanet.Node/Actions/PluggedActionEvaluator.cs

View workflow job for this annotation

GitHub Actions / check-build

The type or namespace name 'IPluginActionEvaluator' could not be found (are you missing a using directive or an assembly reference?)

public PluggedActionEvaluator(
string pluginPath,
string typeName,
IKeyValueStore keyValueStore,
IActionLoader actionLoader)
{
_pluginActionEvaluator = CreateActionEvaluator(pluginPath, typeName, keyValueStore);
ActionLoader = actionLoader;
}

public IActionLoader ActionLoader { get; }

public static Assembly LoadPlugin(string absolutePath)
{
var loadContext = new PluginLoadContext(absolutePath);
var pluginBaseName = Path.GetFileNameWithoutExtension(absolutePath)
?? throw new UnreachableException("Path.GetFileNameWithoutExtension returned null");
var pluginAssemblyName = new AssemblyName(pluginBaseName);
return loadContext.LoadFromAssemblyName(pluginAssemblyName);
}

public static IPluginActionEvaluator CreateActionEvaluator(

Check failure on line 39 in sdk/node/Libplanet.Node/Actions/PluggedActionEvaluator.cs

View workflow job for this annotation

GitHub Actions / docs

The type or namespace name 'IPluginActionEvaluator' could not be found (are you missing a using directive or an assembly reference?)

Check failure on line 39 in sdk/node/Libplanet.Node/Actions/PluggedActionEvaluator.cs

View workflow job for this annotation

GitHub Actions / check-build

The type or namespace name 'IPluginActionEvaluator' could not be found (are you missing a using directive or an assembly reference?)
Assembly assembly, string typeName, IPluginKeyValueStore keyValueStore)

Check failure on line 40 in sdk/node/Libplanet.Node/Actions/PluggedActionEvaluator.cs

View workflow job for this annotation

GitHub Actions / docs

The type or namespace name 'IPluginKeyValueStore' could not be found (are you missing a using directive or an assembly reference?)

Check failure on line 40 in sdk/node/Libplanet.Node/Actions/PluggedActionEvaluator.cs

View workflow job for this annotation

GitHub Actions / docs

The type or namespace name 'IPluginKeyValueStore' could not be found (are you missing a using directive or an assembly reference?)

Check failure on line 40 in sdk/node/Libplanet.Node/Actions/PluggedActionEvaluator.cs

View workflow job for this annotation

GitHub Actions / check-build

The type or namespace name 'IPluginKeyValueStore' could not be found (are you missing a using directive or an assembly reference?)
{
if (assembly.GetType(typeName) is Type type &&
Activator.CreateInstance(type, args: keyValueStore) as IPluginActionEvaluator
is IPluginActionEvaluator pluginActionEvaluator)
{
return pluginActionEvaluator;
}

throw new NullReferenceException("PluginActionEvaluator not found with given parameters");
}

public static IPluginActionEvaluator CreateActionEvaluator(

Check failure on line 52 in sdk/node/Libplanet.Node/Actions/PluggedActionEvaluator.cs

View workflow job for this annotation

GitHub Actions / docs

The type or namespace name 'IPluginActionEvaluator' could not be found (are you missing a using directive or an assembly reference?)

Check failure on line 52 in sdk/node/Libplanet.Node/Actions/PluggedActionEvaluator.cs

View workflow job for this annotation

GitHub Actions / check-build

The type or namespace name 'IPluginActionEvaluator' could not be found (are you missing a using directive or an assembly reference?)
string pluginPath, string typeName, IKeyValueStore keyValueStore)
{
var assembly = LoadPlugin(pluginPath);
var pluginKeyValueStore = new PluginKeyValueStore(keyValueStore);
return CreateActionEvaluator(assembly, typeName, pluginKeyValueStore);
}

public IReadOnlyList<ICommittedActionEvaluation> Evaluate(
IPreEvaluationBlock block,
HashDigest<SHA256>? baseStateRootHash)
{
var evaluations = _pluginActionEvaluator.Evaluate(
PreEvaluationBlockMarshaller.Serialize(block),
baseStateRootHash is { } srh ? srh.ToByteArray() : null)
.Select(ActionEvaluationMarshaller.Deserialize).ToList().AsReadOnly();
return evaluations;
}
}
Loading

0 comments on commit 9dcdc98

Please sign in to comment.