diff --git a/sdk/node/Libplanet.Node.Executable/appsettings-schema.json b/sdk/node/Libplanet.Node.Executable/appsettings-schema.json index e62fc67e480..76d3ba96b68 100644 --- a/sdk/node/Libplanet.Node.Executable/appsettings-schema.json +++ b/sdk/node/Libplanet.Node.Executable/appsettings-schema.json @@ -1189,7 +1189,7 @@ "BlocksyncSeedPeer": { "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}$" + "pattern": "^$|^(?:[0-9a-fA-F]{130}|[0-9a-fA-F]{66}),(?:(?:[a-zA-Z0-9\\-\\.]+)|(?:\\d{1,3}\\.\\d{1,3}\\.\\d{1,3}\\.\\d{1,3})),\\d{1,5}$" } } }, @@ -1209,7 +1209,7 @@ "ConsensusSeedPeer": { "type": "string", "description": "The endpoint of the node to consensus.", - "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}$" + "pattern": "^$|^(?:[0-9a-fA-F]{130}|[0-9a-fA-F]{66}),(?:(?:[a-zA-Z0-9\\-\\.]+)|(?:\\d{1,3}\\.\\d{1,3}\\.\\d{1,3}\\.\\d{1,3})),\\d{1,5}$" } } } diff --git a/sdk/node/Libplanet.Node/BoundPeerUtility.cs b/sdk/node/Libplanet.Node/BoundPeerUtility.cs deleted file mode 100644 index f3f21b39764..00000000000 --- a/sdk/node/Libplanet.Node/BoundPeerUtility.cs +++ /dev/null @@ -1,33 +0,0 @@ -using System.Net; -using Libplanet.Crypto; -using Libplanet.Net; - -namespace Libplanet.Node; - -public static class BoundPeerUtility -{ - public static BoundPeer Parse(string text) - { - var items = text.Split(',', StringSplitOptions.RemoveEmptyEntries); - if (items.Length == 2) - { - var publicKey = PublicKey.FromHex(items[0]); - var endPoint = (DnsEndPoint)EndPointUtility.Parse(items[1].Trim()); - return new BoundPeer(publicKey, endPoint); - } - - throw new FormatException($"'{text}' is not supported."); - } - - public static string ToString(BoundPeer boundPeer) - { - var publicKey = boundPeer.PublicKey.ToHex(compress: false); - var endPoint = EndPointUtility.ToString(boundPeer.EndPoint); - return $"{publicKey}, {endPoint}"; - } - - public static BoundPeer ParseOrFallback(string text, Func fallback) - { - return text == string.Empty ? fallback() : Parse(text); - } -} diff --git a/sdk/node/Libplanet.Node/DataAnnotations/BoundPeerAttribute.cs b/sdk/node/Libplanet.Node/DataAnnotations/BoundPeerAttribute.cs index 26d99bf2d26..fc1ae1f1f77 100644 --- a/sdk/node/Libplanet.Node/DataAnnotations/BoundPeerAttribute.cs +++ b/sdk/node/Libplanet.Node/DataAnnotations/BoundPeerAttribute.cs @@ -7,10 +7,21 @@ namespace Libplanet.Node.DataAnnotations; public sealed class BoundPeerAttribute : RegularExpressionAttribute { public BoundPeerAttribute() - : base( - @$"^$|^{PublicKeyAttribute.OriginPattern},\s*{DnsEndPointAttribute.OriginPattern}$") + : base(GetPattern()) { } + + private static string GetPattern() + { + var items = new string[] + { + PublicKeyAttribute.OriginPattern, + DnsEndPointAttribute.HostPattern, + DnsEndPointAttribute.PortPattern, + }; + var pattern = string.Join(",", items); + return @$"^$|^{pattern}$"; + } } [AttributeUsage(AttributeTargets.Property)] diff --git a/sdk/node/Libplanet.Node/DataAnnotations/DnsEndPointAttribute.cs b/sdk/node/Libplanet.Node/DataAnnotations/DnsEndPointAttribute.cs index d43fa7899e4..f36f29dfd04 100644 --- a/sdk/node/Libplanet.Node/DataAnnotations/DnsEndPointAttribute.cs +++ b/sdk/node/Libplanet.Node/DataAnnotations/DnsEndPointAttribute.cs @@ -6,8 +6,12 @@ namespace Libplanet.Node.DataAnnotations; [AttributeUsage(AttributeTargets.Property)] public sealed class DnsEndPointAttribute : RegularExpressionAttribute { - public const string OriginPattern - = @"(?:(?:[a-zA-Z0-9\-\.]+)|(?:\d{1,3}\.\d{1,3}\.\d{1,3}\.\d{1,3})):\d{1,5}"; + public const string HostPattern + = @"(?:(?:[a-zA-Z0-9\-\.]+)|(?:\d{1,3}\.\d{1,3}\.\d{1,3}\.\d{1,3}))"; + + public const string PortPattern = @"\d{1,5}"; + public static readonly string OriginPattern + = $"{HostPattern}:{PortPattern}"; public DnsEndPointAttribute() : base($"^{OriginPattern}$") diff --git a/sdk/node/Libplanet.Node/DataAnnotations/PublicKeyAttribute.cs b/sdk/node/Libplanet.Node/DataAnnotations/PublicKeyAttribute.cs index a7b9f93a9df..86db84a8550 100644 --- a/sdk/node/Libplanet.Node/DataAnnotations/PublicKeyAttribute.cs +++ b/sdk/node/Libplanet.Node/DataAnnotations/PublicKeyAttribute.cs @@ -6,7 +6,7 @@ namespace Libplanet.Node.DataAnnotations; [AttributeUsage(AttributeTargets.Property)] public sealed class PublicKeyAttribute : RegularExpressionAttribute { - public const string OriginPattern = "[0-9a-fA-F]{130}|[0-9a-fA-F]{66}"; + public const string OriginPattern = "(?:[0-9a-fA-F]{130}|[0-9a-fA-F]{66})"; public PublicKeyAttribute() : base($"^{OriginPattern}$") diff --git a/sdk/node/Libplanet.Node/Services/SwarmService.cs b/sdk/node/Libplanet.Node/Services/SwarmService.cs index 7b44889b641..63980869acd 100644 --- a/sdk/node/Libplanet.Node/Services/SwarmService.cs +++ b/sdk/node/Libplanet.Node/Services/SwarmService.cs @@ -52,7 +52,7 @@ public async Task StartAsync(CancellationToken cancellationToken) PrivateKey = ByteUtil.Hex(seedPrivateKey.ByteArray), EndPoint = EndPointUtility.ToString(EndPointUtility.Next()), }); - _options.BlocksyncSeedPeer = BoundPeerUtility.ToString(_blocksyncSeed.BoundPeer); + _options.BlocksyncSeedPeer = _blocksyncSeed.BoundPeer.PeerString; await _blocksyncSeed.StartAsync(cancellationToken); } @@ -63,8 +63,7 @@ public async Task StartAsync(CancellationToken cancellationToken) PrivateKey = ByteUtil.Hex(seedPrivateKey.ByteArray), EndPoint = EndPointUtility.ToString(EndPointUtility.Next()), }); - validatorOptions.ConsensusSeedPeer - = BoundPeerUtility.ToString(_consensusSeed.BoundPeer); + validatorOptions.ConsensusSeedPeer = _consensusSeed.BoundPeer.PeerString; await _consensusSeed.StartAsync(cancellationToken); } @@ -74,7 +73,7 @@ public async Task StartAsync(CancellationToken cancellationToken) var swarmTransport = await CreateTransport( privateKey: privateKey, endPoint: swarmEndPoint); - var blocksyncSeedPeer = BoundPeerUtility.Parse(nodeOptions.BlocksyncSeedPeer); + var blocksyncSeedPeer = BoundPeer.ParsePeer(nodeOptions.BlocksyncSeedPeer); var swarmOptions = new Net.Options.SwarmOptions { StaticPeers = [blocksyncSeedPeer], @@ -185,7 +184,7 @@ private static async Task CreateTransport( private static ConsensusReactorOption CreateConsensusReactorOption( PrivateKey privateKey, ValidatorOptions options) { - var consensusSeedPeer = BoundPeerUtility.Parse(options.ConsensusSeedPeer); + var consensusSeedPeer = BoundPeer.ParsePeer(options.ConsensusSeedPeer); var consensusEndPoint = (DnsEndPoint)EndPointUtility.Parse(options.EndPoint); return new ConsensusReactorOption {