Skip to content

Commit

Permalink
feat: Add AppProtocolVersion property to SwarmOptions
Browse files Browse the repository at this point in the history
  • Loading branch information
s2quake committed Aug 29, 2024
1 parent 8a8b57a commit 4e09152
Show file tree
Hide file tree
Showing 11 changed files with 80 additions and 20 deletions.
5 changes: 5 additions & 0 deletions sdk/node/Libplanet.Node.Executable/appsettings-schema.json
Original file line number Diff line number Diff line change
Expand Up @@ -1183,6 +1183,11 @@
"type": "string",
"pattern": "^(?:(?:[a-zA-Z0-9\\-\\.]+)|(?:\\d{1,3}\\.\\d{1,3}\\.\\d{1,3}\\.\\d{1,3})):\\d{1,5}$"
},
"AppProtocolVersion": {
"type": "string",
"description": "The version of the application protocol.",
"pattern": "^(?<version>\\d+)/(?<address>[0-9a-fA-F]{40})/(?<signature>(?:[A-Za-z0-9+\\.]{4})*(?:[A-Za-z0-9+\\.]{2}==|[A-Za-z0-9+\\.]{3}=)?)/(?<extra>(?:[A-Za-z0-9+\\.]{4})*(?:[A-Za-z0-9+\\.]{2}==|[A-Za-z0-9+\\.]{3}=)?)$"
},
"BlocksyncSeedPeer": {
"type": "string",
"description": "The endpoint of the node to block sync.",
Expand Down
Original file line number Diff line number Diff line change
Expand Up @@ -12,7 +12,8 @@
}
},
"Swarm": {
"IsEnabled": true
"IsEnabled": true,
"AppProtocolVersion": "200210/AB2da648b9154F2cCcAFBD85e0Bc3d51f97330Fc/MEUCIQCBr..8VdITFe9nMTobl4akFid.s8G2zy2pBidAyRXSeAIgER77qX+eywjgyth6QYi7rQw5nK3KXO6cQ6ngUh.CyfU=/ZHU5OnRpbWVzdGFtcHUxMDoyMDI0LTA3LTMwZQ=="
},
"Validator": {
"IsEnabled": true
Expand Down
4 changes: 2 additions & 2 deletions sdk/node/Libplanet.Node.Tests/Services/PeerTest.cs
Original file line number Diff line number Diff line change
Expand Up @@ -43,7 +43,7 @@ public void Update_Test()
public async Task PingAsync_TestAsync()
{
var pongMsg = new PongMsg();
var apv = GenesisOptions.AppProtocolVersion;
var apv = AppProtocolVersion.Sign(new(), 0);
using var messageBoundPeer = new RandomBoundPeer();
var message = new Message(pongMsg, apv, messageBoundPeer, DateTimeOffset.Now, []);
var transportMock = new Mock<ITransport>();
Expand All @@ -69,7 +69,7 @@ public async Task PingAsync_TestAsync()
public async Task PingAsync_Cancel_TestAsync()
{
var pongMsg = new PongMsg();
var apv = GenesisOptions.AppProtocolVersion;
var apv = AppProtocolVersion.Sign(new(), 0);
using var messageBoundPeer = new RandomBoundPeer();
var message = new Message(pongMsg, apv, messageBoundPeer, DateTimeOffset.Now, []);
var transportMock = new Mock<ITransport>();
Expand Down
4 changes: 2 additions & 2 deletions sdk/node/Libplanet.Node.Tests/Services/SeedTest.cs
Original file line number Diff line number Diff line change
Expand Up @@ -99,7 +99,7 @@ await Assert.ThrowsAsync<InvalidOperationException>(async () =>
public async Task MessageReceived_TestAsync()
{
// Given
var apv = GenesisOptions.AppProtocolVersion;
var apv = AppProtocolVersion.Sign(new(), 0);
var remotePrivateKey = new RandomPrivateKey();
using var remoteEndPoint = new RandomEndPoint();
var remoteBoundPeer = new BoundPeer(remotePrivateKey.PublicKey, remoteEndPoint);
Expand Down Expand Up @@ -146,7 +146,7 @@ await transport.SendMessageAsync(
public async Task GetNeighborsMsg_TestAsync()
{
// Given
var apv = GenesisOptions.AppProtocolVersion;
var apv = AppProtocolVersion.Sign(new(), 0);
var length = Random.Shared.Next(3, 10);
var remotePrivateKeys = new RandomPrivateKey[length];
var remoteEndPoints = new RandomEndPoint[length];
Expand Down
Original file line number Diff line number Diff line change
@@ -0,0 +1,33 @@
#pragma warning disable SA1402 // File may only contain a single type
using System.ComponentModel.DataAnnotations;

namespace Libplanet.Node.DataAnnotations;

[AttributeUsage(AttributeTargets.Property)]
public sealed class AppProtocolVersionAttribute : RegularExpressionAttribute
{
public const string VersionPattern = @"\d+";
public const string AddressPattern = @"[0-9a-fA-F]{40}";
public const string Base64Pattern
= @"(?:[A-Za-z0-9+\.]{4})*(?:[A-Za-z0-9+\.]{2}==|[A-Za-z0-9+\.]{3}=)?";

public static readonly string OriginPattern = GenerateOriginPattern();

public AppProtocolVersionAttribute()
: base($"^{OriginPattern}$")
{
}

private static string GenerateOriginPattern()
{
var items = new string[]
{
$"(?<version>{VersionPattern})",
$"(?<address>{AddressPattern})",
$"(?<signature>{Base64Pattern})",
$"(?<extra>{Base64Pattern})",
};

return string.Join('/', items);
}
}
8 changes: 0 additions & 8 deletions sdk/node/Libplanet.Node/Options/GenesisOptions.cs
Original file line number Diff line number Diff line change
@@ -1,6 +1,4 @@
using System.ComponentModel;
using Libplanet.Crypto;
using Libplanet.Net;
using Libplanet.Node.DataAnnotations;

namespace Libplanet.Node.Options;
Expand All @@ -11,12 +9,6 @@ public sealed class GenesisOptions : OptionsBase<GenesisOptions>
{
public const string Position = "Genesis";

public static readonly PrivateKey AppProtocolKey
= PrivateKey.FromString("2a15e7deaac09ce631e1faa184efadb175b6b90989cf1faed9dfc321ad1db5ac");

public static readonly AppProtocolVersion AppProtocolVersion = AppProtocolVersion.Sign(
AppProtocolKey, 1);

[PrivateKey]
[Description("The key of the genesis block.")]
public string GenesisKey { get; set; } = string.Empty;
Expand Down
4 changes: 4 additions & 0 deletions sdk/node/Libplanet.Node/Options/SeedOptions.cs
Original file line number Diff line number Diff line change
Expand Up @@ -13,6 +13,10 @@ public sealed class SeedOptions : OptionsBase<SeedOptions>
[Description("The private key of the seed node.")]
public string PrivateKey { get; set; } = string.Empty;

[AppProtocolVersion]
[Description("The version of the application protocol.")]
public string AppProtocolVersion { get; set; } = string.Empty;

[DnsEndPoint]
[Description("The endpoint of the seed node.")]
public string EndPoint { get; set; } = string.Empty;
Expand Down
4 changes: 4 additions & 0 deletions sdk/node/Libplanet.Node/Options/SwarmOptions.cs
Original file line number Diff line number Diff line change
Expand Up @@ -17,6 +17,10 @@ public sealed class SwarmOptions : OptionsBase<SwarmOptions>
[DnsEndPoint]
public string EndPoint { get; set; } = string.Empty;

[AppProtocolVersion]
[Description("The version of the application protocol.")]
public string AppProtocolVersion { get; set; } = string.Empty;

[BoundPeer]
[Description("The endpoint of the node to block sync.")]
public string BlocksyncSeedPeer { get; set; } = string.Empty;
Expand Down
12 changes: 12 additions & 0 deletions sdk/node/Libplanet.Node/Options/SwarmOptionsConfigurator.cs
Original file line number Diff line number Diff line change
@@ -1,5 +1,6 @@
using Libplanet.Common;
using Libplanet.Crypto;
using Libplanet.Net;
using Microsoft.Extensions.Logging;

namespace Libplanet.Node.Options;
Expand All @@ -25,5 +26,16 @@ protected override void OnConfigure(SwarmOptions options)
"Node's endpoint is not set. A new endpoint is generated: {EndPoint}",
options.EndPoint);
}

if (options.AppProtocolVersion == string.Empty)
{
var privateKey = PrivateKey.FromString(options.PrivateKey);
var version = 0;
options.AppProtocolVersion = AppProtocolVersion.Sign(privateKey, version).Token;
logger.LogWarning(
"SwarmOptions.AppProtocolVersion is not set. A new version is " +
"generated: {AppProtocolVersion}",
options.AppProtocolVersion);
}
}
}
2 changes: 1 addition & 1 deletion sdk/node/Libplanet.Node/Services/Seed.cs
Original file line number Diff line number Diff line change
Expand Up @@ -100,7 +100,7 @@ public async ValueTask DisposeAsync()
private async Task<NetMQTransport> CreateTransport()
{
var privateKey = PrivateKey.FromString(seedOptions.PrivateKey);
var appProtocolVersion = GenesisOptions.AppProtocolVersion;
var appProtocolVersion = AppProtocolVersion.FromToken(seedOptions.AppProtocolVersion);
var appProtocolVersionOptions = new AppProtocolVersionOptions
{
AppProtocolVersion = appProtocolVersion,
Expand Down
21 changes: 15 additions & 6 deletions sdk/node/Libplanet.Node/Services/SwarmService.cs
Original file line number Diff line number Diff line change
Expand Up @@ -51,6 +51,7 @@ public async Task StartAsync(CancellationToken cancellationToken)
{
PrivateKey = ByteUtil.Hex(seedPrivateKey.ByteArray),
EndPoint = EndPointUtility.ToString(EndPointUtility.Next()),
AppProtocolVersion = _options.AppProtocolVersion,
});
_options.BlocksyncSeedPeer = _blocksyncSeed.BoundPeer.PeerString;
await _blocksyncSeed.StartAsync(cancellationToken);
Expand All @@ -62,17 +63,20 @@ public async Task StartAsync(CancellationToken cancellationToken)
{
PrivateKey = ByteUtil.Hex(seedPrivateKey.ByteArray),
EndPoint = EndPointUtility.ToString(EndPointUtility.Next()),
AppProtocolVersion = _options.AppProtocolVersion,
});
validatorOptions.ConsensusSeedPeer = _consensusSeed.BoundPeer.PeerString;
await _consensusSeed.StartAsync(cancellationToken);
}

var nodeOptions = _options;
var privateKey = PrivateKey.FromString(nodeOptions.PrivateKey);
var appProtocolVersion = AppProtocolVersion.FromToken(nodeOptions.AppProtocolVersion);
var swarmEndPoint = (DnsEndPoint)EndPointUtility.Parse(nodeOptions.EndPoint);
var swarmTransport = await CreateTransport(
privateKey: privateKey,
endPoint: swarmEndPoint);
endPoint: swarmEndPoint,
appProtocolVersion: appProtocolVersion);
var blocksyncSeedPeer = BoundPeer.ParsePeer(nodeOptions.BlocksyncSeedPeer);
var swarmOptions = new Net.Options.SwarmOptions
{
Expand All @@ -84,7 +88,8 @@ public async Task StartAsync(CancellationToken cancellationToken)
};

var consensusTransport = validatorOptions is not null
? await CreateConsensusTransportAsync(privateKey, validatorOptions, cancellationToken)
? await CreateConsensusTransportAsync(
privateKey, appProtocolVersion, validatorOptions, cancellationToken)
: null;
var consensusReactorOption = validatorOptions is not null
? CreateConsensusReactorOption(privateKey, validatorOptions)
Expand Down Expand Up @@ -171,11 +176,11 @@ public async ValueTask DisposeAsync()
}

private static async Task<NetMQTransport> CreateTransport(
PrivateKey privateKey, DnsEndPoint endPoint)
PrivateKey privateKey, DnsEndPoint endPoint, AppProtocolVersion appProtocolVersion)
{
var appProtocolVersionOptions = new Net.Options.AppProtocolVersionOptions
{
AppProtocolVersion = GenesisOptions.AppProtocolVersion,
AppProtocolVersion = appProtocolVersion,
};
var hostOptions = new Net.Options.HostOptions(endPoint.Host, [], endPoint.Port);
return await NetMQTransport.Create(privateKey, appProtocolVersionOptions, hostOptions);
Expand All @@ -197,12 +202,16 @@ private static ConsensusReactorOption CreateConsensusReactorOption(
}

private static async Task<NetMQTransport> CreateConsensusTransportAsync(
PrivateKey privateKey, ValidatorOptions options, CancellationToken cancellationToken)
PrivateKey privateKey,
AppProtocolVersion appProtocolVersion,
ValidatorOptions options,
CancellationToken cancellationToken)
{
var consensusEndPoint = (DnsEndPoint)EndPointUtility.Parse(options.EndPoint);
await Task.Delay(1, cancellationToken);
return await CreateTransport(
privateKey: privateKey,
endPoint: consensusEndPoint);
endPoint: consensusEndPoint,
appProtocolVersion: appProtocolVersion);
}
}

0 comments on commit 4e09152

Please sign in to comment.