Skip to content

Commit

Permalink
New stuff
Browse files Browse the repository at this point in the history
  • Loading branch information
jianmingyong committed May 13, 2023
1 parent f5a4687 commit f9b4056
Show file tree
Hide file tree
Showing 9 changed files with 311 additions and 126 deletions.
Original file line number Diff line number Diff line change
Expand Up @@ -18,6 +18,10 @@ private static partial class Native
public static partial bool XenophyteCentralizedAlgorithm_MakeEncryptedShare(ReadOnlySpan<byte> input, int inputLength, Span<byte> encryptedShare, Span<byte> hashEncryptedShare, ReadOnlySpan<byte> xorKey, int xorKeyLength, int aesKeySize, ReadOnlySpan<byte> aesKey, ReadOnlySpan<byte> aesIv, int aesRound);
}

public const string JobTypeEasy = "Easy Block";
public const string JobTypeSemiRandom = "Semi Random";
public const string JobTypeRandom = "Random";

[MethodImpl(MethodImplOptions.AggressiveInlining)]
public static int GenerateEasyBlockNumbers(long minValue, long maxValue, Span<long> output)
{
Expand All @@ -35,4 +39,12 @@ public static bool MakeEncryptedShare(ReadOnlySpan<byte> input, Span<byte> encry
{
return Native.XenophyteCentralizedAlgorithm_MakeEncryptedShare(input, input.Length, encryptedShare, hashEncryptedShare, xorKey, xorKey.Length, aesKey.Length * 8, aesKey, aesIv, aesRound);
}

public static (int startIndex, int size) GetJobChunk(int totalSize, int numberOfChunks, int threadId)
{
var (quotient, remainder) = Math.DivRem(totalSize, numberOfChunks);
var startIndex = threadId * quotient + Math.Min(threadId, remainder);
var chunkLength = quotient + (threadId < remainder ? 1 : 0);
return (startIndex, chunkLength);
}
}
12 changes: 3 additions & 9 deletions Xenopool/Server/Logger.cs
Original file line number Diff line number Diff line change
Expand Up @@ -25,17 +25,11 @@ public static partial class Logger
[LoggerMessage(EventId = 10, Level = LogLevel.Information, Message = $"use {{mode}} {CyanForegroundColor}{{host}}{Reset}")]
public static partial void PrintConnected(ILogger logger, string mode, string host);

[LoggerMessage(EventId = 11, Level = LogLevel.Information, Message = $"{GreenForegroundColor}READY (CPU) {WhiteForegroundColor}threads {CyanForegroundColor}{{threads}}{Reset}")]
public static partial void PrintCpuMinerReady(ILogger logger, int threads);

[LoggerMessage(EventId = 12, Level = LogLevel.Information, Message = $"{MagentaForegroundColor}{{job}}{Reset} from {WhiteForegroundColor}{{host}}{Reset} diff {WhiteForegroundColor}{{difficulty}}{Reset} algo {WhiteForegroundColor}{{algorithm}}{Reset} height {WhiteForegroundColor}{{height}}{Reset}")]
public static partial void PrintJob(ILogger logger, string job, string host, long difficulty, string algorithm, int height);

[LoggerMessage(EventId = 13, Level = LogLevel.Information, Message = $"{BlueForegroundColor}Thread: {{threadId,-2}} | Job Type: {{jobType}} | Job Iterations: {{jobTotal}} | Job Chunk: {{startIndex}}-{{endIndex}} ({{size}}){Reset}")]
public static partial void PrintCurrentChunkedThreadJob(ILogger logger, int threadId, string jobType, long jobTotal, long startIndex, long endIndex, long size);

[LoggerMessage(EventId = 15, Level = LogLevel.Information, Message = $"{GreenForegroundColor}Thread: {{threadId,-2}} | Job Type: {{jobType}} | Block found: {{firstNumber}} {{operatorSymbol}} {{secondNumber}} = {{result}}{Reset}")]
public static partial void PrintBlockFound(ILogger logger, int threadId, string jobType, long firstNumber, char operatorSymbol, long secondNumber, long result);

[LoggerMessage(EventId = 15, Level = LogLevel.Information, Message = $"{GreenForegroundColor}Job Type: {{jobType}} | Block found: {{firstNumber}} {{operatorSymbol}} {{secondNumber}} = {{result}}{Reset}")]
public static partial void PrintBlockFound(ILogger logger, string jobType, long firstNumber, char operatorSymbol, long secondNumber, long result);

[LoggerMessage(EventId = 16, Level = LogLevel.Information, Message = $"{GreenForegroundColor}accepted {Reset}({{goodTotal}}/{{badTotal}}) {GrayForegroundColor}({{ping}} ms){Reset}")]
public static partial void PrintBlockAcceptResult(ILogger logger, int goodTotal, int badTotal, double ping);
Expand Down
45 changes: 14 additions & 31 deletions Xenopool/Server/Pool/PoolClient.cs
Original file line number Diff line number Diff line change
@@ -1,46 +1,29 @@
using Xenopool.Server.Database.Repository;
using Xenopool.Server.Database.Tables;
using Xenopool.Server.Database.Tables;

namespace Xenopool.Server.Pool;

public sealed class PoolClient : IDisposable
public sealed class PoolClient
{
public sealed class Worker
{
private readonly PoolAccount _poolAccount;
private readonly string _workerId;
private readonly PoolAccount _poolAccount;
private readonly string _workerId;

private DateTime _lastRequestTime = DateTime.Now;

public Worker(PoolAccount poolAccount, string workerId)
{
_poolAccount = poolAccount;
_workerId = workerId;
}
private DateTime _lastRequestTime = DateTime.Now;

public bool IsExpire()
{
return (DateTime.Now - _lastRequestTime).TotalMinutes > 1;
}
private ulong _sharePoints = 0;

public void Ping()
{
_lastRequestTime = DateTime.Now;
}
public PoolClient(PoolAccount poolAccount, string workerId)
{
_poolAccount = poolAccount;
_workerId = workerId;
}

public PoolAccount Account { get; }

private readonly PoolAccountRepository _poolAccountRepository;

public PoolClient(PoolAccountRepository poolAccountRepository, string walletAddress)
public bool IsExpire()
{
_poolAccountRepository = poolAccountRepository;
Account = poolAccountRepository.GetAccount(walletAddress) ?? poolAccountRepository.CreateAccount(walletAddress);
return (DateTime.Now - _lastRequestTime).TotalMinutes > 1;
}

public void Dispose()
public void Ping()
{
_poolAccountRepository.Dispose();
_lastRequestTime = DateTime.Now;
}
}
71 changes: 0 additions & 71 deletions Xenopool/Server/Pool/PoolClientCollection.cs

This file was deleted.

99 changes: 99 additions & 0 deletions Xenopool/Server/Pool/PoolClientManager.cs
Original file line number Diff line number Diff line change
@@ -0,0 +1,99 @@
using Grpc.Core;
using Microsoft.EntityFrameworkCore;
using Xenolib.Algorithms.Xenophyte.Centralized.Networking.Pool;
using Xenolib.Utilities.Buffer;
using Xenopool.Server.Database;
using Xenopool.Server.Database.Repository;

namespace Xenopool.Server.Pool;

public sealed class PoolClientManager : IDisposable
{
private readonly PoolAccountRepository _poolAccountRepository;
private readonly Timer _poolClientValidityCheck;

private readonly SemaphoreSlim _semaphoreSlim = new(1, 1);
private readonly Dictionary<string, PoolClient> _poolClients = new();

public PoolClientManager(IDbContextFactory<SqliteDatabaseContext> contextFactory)
{
_poolAccountRepository = new PoolAccountRepository(contextFactory.CreateDbContext());
_poolClientValidityCheck = new Timer(CheckClientValidity, null, TimeSpan.FromMinutes(1), TimeSpan.FromMinutes(1));
}

public async Task<LoginResponse> AddClientAsync(LoginRequest request, ServerCallContext context)
{
try
{
await _semaphoreSlim.WaitAsync(context.CancellationToken);

var account = await _poolAccountRepository.GetAccountAsync(request.WalletAddress, context.CancellationToken) ?? _poolAccountRepository.CreateAccount(request.WalletAddress);

if (account.IsBanned)
{
return new LoginResponse { Status = false, Reason = account.BanReason ?? string.Empty };
}

string guid;

do
{
guid = Guid.NewGuid().ToString();
} while (!_poolClients.TryAdd(guid, new PoolClient(account, request.WorkerId)));

return new LoginResponse { Status = true, Token = guid };
}
finally
{
if (_semaphoreSlim.CurrentCount == 0) _semaphoreSlim.Release();
}
}

public async Task<PoolClient?> GetClientAsync(string token, CancellationToken cancellationToken = default)
{
try
{
await _semaphoreSlim.WaitAsync(cancellationToken);
return _poolClients.TryGetValue(token, out var poolClient) ? poolClient : null;
}
finally
{
if (_semaphoreSlim.CurrentCount == 0) _semaphoreSlim.Release();
}
}

private void CheckClientValidity(object? _)
{
try
{
_semaphoreSlim.Wait();

using var expiredPoolClients = ArrayPoolOwner<string>.Rent(_poolClients.Count);
var expiredPoolClientCount = 0;

foreach (var poolClient in _poolClients)
{
if (poolClient.Value.IsExpire())
{
expiredPoolClients.Span[expiredPoolClientCount++] = poolClient.Key;
}
}

for (var i = 0; i < expiredPoolClientCount; i++)
{
_poolClients.Remove(expiredPoolClients.Span[i]);
}
}
finally
{
if (_semaphoreSlim.CurrentCount == 0) _semaphoreSlim.Release();
}
}

public void Dispose()
{
_poolAccountRepository.Dispose();
_poolClientValidityCheck.Dispose();
_semaphoreSlim.Dispose();
}
}
39 changes: 31 additions & 8 deletions Xenopool/Server/Pool/PoolService.cs
Original file line number Diff line number Diff line change
Expand Up @@ -7,26 +7,49 @@ namespace Xenopool.Server.Pool;
public sealed class PoolService : Xenolib.Algorithms.Xenophyte.Centralized.Networking.Pool.Pool.PoolBase
{
private readonly SoloMiningNetwork _soloMiningNetwork;
private readonly PoolClientCollection _poolClientCollection;
private readonly PoolClientManager _poolClientManager;

public PoolService(SoloMiningNetwork soloMiningNetwork, PoolClientCollection poolClientCollection)
public PoolService(SoloMiningNetwork soloMiningNetwork, PoolClientManager poolClientManager)
{
_soloMiningNetwork = soloMiningNetwork;
_poolClientCollection = poolClientCollection;
_poolClientManager = poolClientManager;
}

public override async Task<LoginResponse> Login(LoginRequest request, ServerCallContext context)
{
return await _poolClientCollection.RegisterClientAsync(request);
return await _poolClientManager.AddClientAsync(request, context);
}

public override Task<BlockHeaderResponse> GetBlockHeader(BlockHeaderRequest request, ServerCallContext context)
public override async Task<BlockHeaderResponse> GetBlockHeader(BlockHeaderRequest request, ServerCallContext context)
{
if (_poolClientCollection.PoolWorkers.TryGetValue(request.Token, out var worker))
var poolClient = await _poolClientManager.GetClientAsync(request.Token, context.CancellationToken);

if (poolClient == null)
{
return Task.FromResult(_soloMiningNetwork.BlockHeaderResponse);
return new BlockHeaderResponse { Status = false, Reason = "User not authorized." };
}

poolClient.Ping();

return await Task.FromResult(_soloMiningNetwork.BlockHeaderResponse);
}

return Task.FromResult(new BlockHeaderResponse { Status = false, Reason = "User not authorized." });
public override async Task<JobHeaderResponse> RequestNewJob(JobHeaderRequest request, ServerCallContext context)
{
var poolClient = await _poolClientManager.GetClientAsync(request.Token, context.CancellationToken);

if (poolClient == null)
{
return new JobHeaderResponse { Status = false, Reason = "User not authorized." };
}

poolClient.Ping();

return await base.RequestNewJob(request, context);
}

public override Task<JobSubmitResponse> SubmitJob(JobSubmitRequest request, ServerCallContext context)
{
return base.SubmitJob(request, context);
}
}
2 changes: 1 addition & 1 deletion Xenopool/Server/Program.cs
Original file line number Diff line number Diff line change
Expand Up @@ -25,7 +25,7 @@ public static void Main(string[] args)

builder.Services.AddSingleton<RpcWalletNetwork>();
builder.Services.AddSingleton<SoloMiningNetwork>();
builder.Services.AddSingleton<PoolClientCollection>();
builder.Services.AddSingleton<PoolClientManager>();

builder.Services.AddHostedService<ConsoleService>();

Expand Down
4 changes: 2 additions & 2 deletions Xenopool/Server/RpcWallet/RpcWalletNetwork.cs
Original file line number Diff line number Diff line change
Expand Up @@ -65,13 +65,13 @@ public async Task<bool> CheckIfWalletAddressExistAsync(CancellationToken cancell

private async Task<int> GetTotalWalletIndexAsync(CancellationToken cancellationToken = default)
{
var response = await DoGetRequestAsync<GetTotalWalletIndexResponse>("get_total_wallet_index", GetTotalWalletIndexResponseContext.Default.GetTotalWalletIndexResponse, cancellationToken);
var response = await DoGetRequestAsync("get_total_wallet_index", GetTotalWalletIndexResponseContext.Default.GetTotalWalletIndexResponse, cancellationToken);
return response?.Result ?? 0;
}

private async Task<string> GetWalletAddressByIndexAsync(int index, CancellationToken cancellationToken = default)
{
var response = await DoGetRequestAsync<GetWalletAddressByIndexResponse>($"get_wallet_address_by_index|{index}", GetWalletAddressByIndexResponseContext.Default.GetWalletAddressByIndexResponse, cancellationToken);
var response = await DoGetRequestAsync($"get_wallet_address_by_index|{index}", GetWalletAddressByIndexResponseContext.Default.GetWalletAddressByIndexResponse, cancellationToken);
return response?.Result ?? "wallet_not_exist";
}

Expand Down
Loading

0 comments on commit f9b4056

Please sign in to comment.