diff --git a/Lib9c b/Lib9c index eb4e8827d..84ce195e9 160000 --- a/Lib9c +++ b/Lib9c @@ -1 +1 @@ -Subproject commit eb4e8827dd6fd2e8b88812fdfed725e2c3beb334 +Subproject commit 84ce195e9da6c0c393439ec405f01b48651488b3 diff --git a/NineChronicles.Headless/GraphQLService.cs b/NineChronicles.Headless/GraphQLService.cs index d62efad09..b62528d3b 100644 --- a/NineChronicles.Headless/GraphQLService.cs +++ b/NineChronicles.Headless/GraphQLService.cs @@ -1,4 +1,5 @@ using System; +using System.Collections.Concurrent; using System.Collections.Generic; using AspNetCoreRateLimit; using GraphQL.Server; @@ -200,7 +201,7 @@ public void Configure(IApplicationBuilder app, IWebHostEnvironment env) // Capture requests if (Convert.ToBoolean(Configuration.GetSection("MultiAccountManaging")["EnableManaging"])) { - Dictionary> ipSignerList = new(); + ConcurrentDictionary> ipSignerList = new(); app.UseMiddleware( StandaloneContext, ipSignerList, diff --git a/NineChronicles.Headless/HostBuilderExtensions.cs b/NineChronicles.Headless/HostBuilderExtensions.cs index 25e37cc22..ff4940bf9 100644 --- a/NineChronicles.Headless/HostBuilderExtensions.cs +++ b/NineChronicles.Headless/HostBuilderExtensions.cs @@ -4,9 +4,7 @@ using Microsoft.Extensions.DependencyInjection; using Microsoft.Extensions.Hosting; using NineChronicles.Headless.Properties; -using System.Net; using Lib9c.Formatters; -using Libplanet.Action; using Libplanet.Crypto; using Libplanet.Headless.Hosting; using MessagePack; @@ -14,10 +12,8 @@ using Microsoft.AspNetCore.Hosting; using Microsoft.AspNetCore.Server.Kestrel.Core; using Microsoft.Extensions.Configuration; -using Nekoyume.Action; using NineChronicles.Headless.Middleware; using NineChronicles.Headless.Services; -using Sentry; namespace NineChronicles.Headless { @@ -82,7 +78,7 @@ IConfiguration configuration options.MaxReceiveMessageSize = null; if (Convert.ToBoolean(configuration.GetSection("MultiAccountManaging")["EnableManaging"])) { - Dictionary> ipSignerList = new(); + ConcurrentDictionary> ipSignerList = new(); options.Interceptors.Add( standaloneContext, ipSignerList, diff --git a/NineChronicles.Headless/Middleware/GrpcMultiAccountManagementMiddleware.cs b/NineChronicles.Headless/Middleware/GrpcMultiAccountManagementMiddleware.cs index 0f3d995f2..5afe4b556 100644 --- a/NineChronicles.Headless/Middleware/GrpcMultiAccountManagementMiddleware.cs +++ b/NineChronicles.Headless/Middleware/GrpcMultiAccountManagementMiddleware.cs @@ -1,4 +1,5 @@ using System; +using System.Collections.Concurrent; using System.Collections.Generic; using Grpc.Core; using Grpc.Core.Interceptors; @@ -13,17 +14,17 @@ namespace NineChronicles.Headless.Middleware { public class GrpcMultiAccountManagementMiddleware : Interceptor { - private static readonly Dictionary MultiAccountTxIntervalTracker = new(); - private static readonly Dictionary MultiAccountManagementList = new(); + private static readonly ConcurrentDictionary MultiAccountTxIntervalTracker = new(); + private static readonly ConcurrentDictionary MultiAccountManagementList = new(); private readonly ILogger _logger; private StandaloneContext _standaloneContext; - private readonly Dictionary> _ipSignerList; + private readonly ConcurrentDictionary> _ipSignerList; private readonly ActionEvaluationPublisher _actionEvaluationPublisher; private readonly IOptions _options; public GrpcMultiAccountManagementMiddleware( StandaloneContext standaloneContext, - Dictionary> ipSignerList, + ConcurrentDictionary> ipSignerList, ActionEvaluationPublisher actionEvaluationPublisher, IOptions options) { @@ -36,12 +37,12 @@ public GrpcMultiAccountManagementMiddleware( private static void ManageMultiAccount(Address agent) { - MultiAccountManagementList.Add(agent, DateTimeOffset.Now); + MultiAccountManagementList.TryAdd(agent, DateTimeOffset.Now); } private static void RestoreMultiAccount(Address agent) { - MultiAccountManagementList.Remove(agent); + MultiAccountManagementList.TryRemove(agent, out _); } public override async Task UnaryServerHandler( @@ -95,7 +96,7 @@ public override async Task UnaryServerHandler( { _logger.Information( $"[GRPC-MULTI-ACCOUNT-MANAGER] Adding agent {agent} to the agent tracker."); - MultiAccountTxIntervalTracker.Add(agent, DateTimeOffset.Now); + MultiAccountTxIntervalTracker.TryAdd(agent, DateTimeOffset.Now); } else { @@ -105,7 +106,7 @@ public override async Task UnaryServerHandler( _logger.Information( $"[GRPC-MULTI-ACCOUNT-MANAGER] Resetting Agent {agent}'s time because " + $"it has been more than {_options.Value.TxIntervalMinutes} minutes since the last transaction."); - MultiAccountTxIntervalTracker[agent] = DateTimeOffset.Now; + MultiAccountTxIntervalTracker.TryUpdate(agent, DateTimeOffset.Now, MultiAccountTxIntervalTracker[agent]); } else { @@ -114,7 +115,7 @@ public override async Task UnaryServerHandler( $"{_options.Value.ManagementTimeMinutes} minutes due to " + $"{_ipSignerList[remoteIp].Count} associated accounts."); ManageMultiAccount(agent); - MultiAccountTxIntervalTracker[agent] = DateTimeOffset.Now; + MultiAccountTxIntervalTracker.TryUpdate(agent, DateTimeOffset.Now, MultiAccountTxIntervalTracker[agent]); throw new RpcException(new Status(StatusCode.Cancelled, "Request cancelled.")); } } @@ -127,8 +128,7 @@ public override async Task UnaryServerHandler( _logger.Information( $"[GRPC-MULTI-ACCOUNT-MANAGER] Restoring Agent {agent} after {_options.Value.ManagementTimeMinutes} minutes."); RestoreMultiAccount(agent); - MultiAccountTxIntervalTracker[agent] = - DateTimeOffset.Now.AddMinutes(-_options.Value.TxIntervalMinutes); + MultiAccountTxIntervalTracker.TryUpdate(agent, DateTimeOffset.Now.AddMinutes(-_options.Value.TxIntervalMinutes), MultiAccountTxIntervalTracker[agent]); _logger.Information( $"[GRPC-MULTI-ACCOUNT-MANAGER] Current time: {DateTimeOffset.Now} Added time: {DateTimeOffset.Now.AddMinutes(-_options.Value.TxIntervalMinutes)}."); } diff --git a/NineChronicles.Headless/Middleware/HttpMultiAccountManagementMiddleware.cs b/NineChronicles.Headless/Middleware/HttpMultiAccountManagementMiddleware.cs index 5f5498e7d..4fee61167 100644 --- a/NineChronicles.Headless/Middleware/HttpMultiAccountManagementMiddleware.cs +++ b/NineChronicles.Headless/Middleware/HttpMultiAccountManagementMiddleware.cs @@ -1,4 +1,5 @@ using System; +using System.Collections.Concurrent; using System.Collections.Generic; using System.IO; using System.Linq; @@ -18,19 +19,19 @@ namespace NineChronicles.Headless.Middleware { public class HttpMultiAccountManagementMiddleware { - private static readonly Dictionary MultiAccountTxIntervalTracker = new(); - private static readonly Dictionary MultiAccountManagementList = new(); + private static readonly ConcurrentDictionary MultiAccountTxIntervalTracker = new(); + private static readonly ConcurrentDictionary MultiAccountManagementList = new(); private readonly RequestDelegate _next; private readonly ILogger _logger; private StandaloneContext _standaloneContext; - private readonly Dictionary> _ipSignerList; + private readonly ConcurrentDictionary> _ipSignerList; private readonly IOptions _options; private ActionEvaluationPublisher _publisher; public HttpMultiAccountManagementMiddleware( RequestDelegate next, StandaloneContext standaloneContext, - Dictionary> ipSignerList, + ConcurrentDictionary> ipSignerList, IOptions options, ActionEvaluationPublisher publisher) { @@ -44,12 +45,12 @@ public HttpMultiAccountManagementMiddleware( private static void ManageMultiAccount(Address agent) { - MultiAccountManagementList.Add(agent, DateTimeOffset.Now); + MultiAccountManagementList.TryAdd(agent, DateTimeOffset.Now); } private static void RestoreMultiAccount(Address agent) { - MultiAccountManagementList.Remove(agent); + MultiAccountManagementList.TryRemove(agent, out _); } public async Task InvokeAsync(HttpContext context) @@ -92,20 +93,20 @@ and not ClaimStakeReward if (!MultiAccountTxIntervalTracker.ContainsKey(agent)) { _logger.Information($"[GRAPHQL-MULTI-ACCOUNT-MANAGER] Adding agent {agent} to the agent tracker."); - MultiAccountTxIntervalTracker.Add(agent, DateTimeOffset.Now); + MultiAccountTxIntervalTracker.TryAdd(agent, DateTimeOffset.Now); } else { if ((DateTimeOffset.Now - MultiAccountTxIntervalTracker[agent]).Minutes >= _options.Value.TxIntervalMinutes) { _logger.Information($"[GRAPHQL-MULTI-ACCOUNT-MANAGER] Resetting Agent {agent}'s time because it has been more than {_options.Value.TxIntervalMinutes} minutes since the last transaction."); - MultiAccountTxIntervalTracker[agent] = DateTimeOffset.Now; + MultiAccountTxIntervalTracker.TryUpdate(agent, DateTimeOffset.Now, MultiAccountTxIntervalTracker[agent]); } else { _logger.Information($"[GRAPHQL-MULTI-ACCOUNT-MANAGER] Managing Agent {agent} for {_options.Value.ManagementTimeMinutes} minutes due to {_ipSignerList[remoteIp].Count} associated accounts."); ManageMultiAccount(agent); - MultiAccountTxIntervalTracker[agent] = DateTimeOffset.Now; + MultiAccountTxIntervalTracker.TryUpdate(agent, DateTimeOffset.Now, MultiAccountTxIntervalTracker[agent]); await CancelRequestAsync(context); return; } @@ -118,7 +119,7 @@ and not ClaimStakeReward { _logger.Information($"[GRAPHQL-MULTI-ACCOUNT-MANAGER] Restoring Agent {agent} after {_options.Value.ManagementTimeMinutes} minutes."); RestoreMultiAccount(agent); - MultiAccountTxIntervalTracker[agent] = DateTimeOffset.Now.AddMinutes(-_options.Value.TxIntervalMinutes); + MultiAccountTxIntervalTracker.TryUpdate(agent, DateTimeOffset.Now.AddMinutes(-_options.Value.TxIntervalMinutes), MultiAccountTxIntervalTracker[agent]); _logger.Information($"[GRAPHQL-MULTI-ACCOUNT-MANAGER] Current time: {DateTimeOffset.Now} Added time: {DateTimeOffset.Now.AddMinutes(-_options.Value.TxIntervalMinutes)}."); } else diff --git a/NineChronicles.Headless/Middleware/IpBanMiddleware.cs b/NineChronicles.Headless/Middleware/IpBanMiddleware.cs index 89b1558a2..8f391e56e 100644 --- a/NineChronicles.Headless/Middleware/IpBanMiddleware.cs +++ b/NineChronicles.Headless/Middleware/IpBanMiddleware.cs @@ -1,5 +1,5 @@ using System; -using System.Collections.Generic; +using System.Collections.Concurrent; using System.Threading.Tasks; using Microsoft.AspNetCore.Http; using Microsoft.Extensions.Options; @@ -11,7 +11,7 @@ namespace NineChronicles.Headless.Middleware { public class IpBanMiddleware { - private static Dictionary _bannedIps = new(); + private static ConcurrentDictionary _bannedIps = new(); private readonly RequestDelegate _next; private readonly ILogger _logger; private readonly IOptions _options; @@ -27,7 +27,7 @@ public static void BanIp(string ip) { if (!_bannedIps.ContainsKey(ip)) { - _bannedIps.Add(ip, DateTimeOffset.Now); + _bannedIps.TryAdd(ip, DateTimeOffset.Now); } } @@ -35,7 +35,7 @@ public static void UnbanIp(string ip) { if (_bannedIps.ContainsKey(ip)) { - _bannedIps.Remove(ip); + _bannedIps.TryRemove(ip, out _); } }