Skip to content

Commit

Permalink
Optimizations for the ethash family: allow use of full DAG and light …
Browse files Browse the repository at this point in the history
…cache DAG
  • Loading branch information
xiaolin1579 committed Aug 2, 2023
1 parent b0ea263 commit 753c90e
Show file tree
Hide file tree
Showing 25 changed files with 842 additions and 903 deletions.
8 changes: 7 additions & 1 deletion src/Miningcore/AutofacModule.cs
Original file line number Diff line number Diff line change
Expand Up @@ -11,6 +11,7 @@
using Miningcore.Configuration;
using Miningcore.Crypto;
using Miningcore.Crypto.Hashing.Equihash;
using Miningcore.Crypto.Hashing.Ethash;
using Miningcore.Messaging;
using Miningcore.Mining;
using Miningcore.Notifications;
Expand Down Expand Up @@ -87,6 +88,12 @@ protected override void Load(ContainerBuilder builder)
.PropertiesAutowired()
.AsSelf();

builder.RegisterAssemblyTypes(ThisAssembly)
.Where(t => t.GetCustomAttributes<IdentifierAttribute>().Any() &&
t.GetInterfaces().Any(i => i.IsAssignableFrom(typeof(IEthashLight))))
.Named<IEthashLight>(t => t.GetCustomAttributes<IdentifierAttribute>().First().Name)
.PropertiesAutowired();

builder.RegisterAssemblyTypes(ThisAssembly)
.Where(t => t.IsAssignableTo<ControllerBase>())
.PropertiesAutowired()
Expand Down Expand Up @@ -163,7 +170,6 @@ protected override void Load(ContainerBuilder builder)
//////////////////////
// Ethereum

builder.RegisterType<EthereumJobManager>();
builder.RegisterType<EthereumJobManager>();

//////////////////////
Expand Down
9 changes: 7 additions & 2 deletions src/Miningcore/Blockchain/Ethereum/EthereumConstants.cs
Original file line number Diff line number Diff line change
Expand Up @@ -6,8 +6,6 @@ namespace Miningcore.Blockchain.Ethereum;
public class EthereumConstants
{
public const ulong EpochLength = 30000;
public const ulong CacheSizeForTesting = 1024;
public const ulong DagSizeForTesting = 1024 * 32;
public static BigInteger BigMaxValue = BigInteger.Pow(2, 256);
public static double Pow2x32 = Math.Pow(2, 32);
public static BigInteger BigPow2x32 = new(Pow2x32);
Expand Down Expand Up @@ -109,6 +107,11 @@ public class PomConstants
public const decimal BaseRewardInitial = 7.0m;
}

public class TeapartyConstants
{
public const decimal BaseRewardInitial = 0.1m;
}

public class CanxiumConstants
{
public const decimal BaseRewardInitial = 0.1875m;
Expand All @@ -129,6 +132,7 @@ public enum EthereumNetworkType
Altcoin = 2330,
MaxxChain = 10201,
Pom = 801921,
Teaparty = 1773,
Canxium = 3003,

Unknown = -1,
Expand All @@ -149,6 +153,7 @@ public enum GethChainType
Altcoin = 2330,
MaxxChain = 10201,
Pom = 801921,
Teaparty = 1773,
Canxium = 3003,

Unknown = -1,
Expand Down
160 changes: 7 additions & 153 deletions src/Miningcore/Blockchain/Ethereum/EthereumJob.cs
Original file line number Diff line number Diff line change
@@ -1,8 +1,6 @@
using System.Globalization;
using System.Numerics;
using Miningcore.Crypto.Hashing.Etchash;
using Miningcore.Crypto.Hashing.Ethash;
using Miningcore.Crypto.Hashing.Ubqhash;
using Miningcore.Extensions;
using Miningcore.Stratum;
using NBitcoin;
Expand All @@ -12,11 +10,12 @@ namespace Miningcore.Blockchain.Ethereum;

public class EthereumJob
{
public EthereumJob(string id, EthereumBlockTemplate blockTemplate, ILogger logger)
public EthereumJob(string id, EthereumBlockTemplate blockTemplate, ILogger logger, IEthashLight ethash)
{
Id = id;
BlockTemplate = blockTemplate;
this.logger = logger;
this.ethash = ethash;

var target = blockTemplate.Target;
if(target.StartsWith("0x"))
Expand All @@ -31,6 +30,7 @@ public EthereumJob(string id, EthereumBlockTemplate blockTemplate, ILogger logge
public EthereumBlockTemplate BlockTemplate { get; }
private readonly uint256 blockTarget;
private readonly ILogger logger;
private readonly IEthashLight ethash;

public record SubmitResult(Share Share, string FullNonceHex = null, string HeaderHash = null, string MixHash = null);

Expand All @@ -53,154 +53,8 @@ private void RegisterNonce(StratumConnection worker, string nonce)
}
}

public async Task<SubmitResult> ProcessShareEtcHashAsync(StratumConnection worker,
string workerName, string fullNonceHex, EtchashFull etchash, CancellationToken ct)
{
// dupe check
lock(workerNonces)
{
RegisterNonce(worker, fullNonceHex);
}

var context = worker.ContextAs<EthereumWorkerContext>();

if(!ulong.TryParse(fullNonceHex, NumberStyles.HexNumber, CultureInfo.InvariantCulture, out var fullNonce))
throw new StratumException(StratumError.MinusOne, "bad nonce " + fullNonceHex);

// get dag for block
var dag = await etchash.GetDagAsync(BlockTemplate.Height, logger, CancellationToken.None);

// compute
if(!dag.Compute(logger, BlockTemplate.Header.HexToByteArray(), fullNonce, out var mixDigest, out var resultBytes))
throw new StratumException(StratumError.MinusOne, "bad hash");

// test if share meets at least workers current difficulty
resultBytes.ReverseInPlace();
var resultValue = new uint256(resultBytes);
var resultValueBig = resultBytes.AsSpan().ToBigInteger();
var shareDiff = (double) BigInteger.Divide(EthereumConstants.BigMaxValue, resultValueBig) / EthereumConstants.Pow2x32;
var stratumDifficulty = context.Difficulty;
var ratio = shareDiff / stratumDifficulty;
var isBlockCandidate = resultValue <= blockTarget;

if(!isBlockCandidate && ratio < 0.99)
{
// check if share matched the previous difficulty from before a vardiff retarget
if(context.VarDiff?.LastUpdate != null && context.PreviousDifficulty.HasValue)
{
ratio = shareDiff / context.PreviousDifficulty.Value;

if(ratio < 0.99)
throw new StratumException(StratumError.LowDifficultyShare, $"low difficulty share ({shareDiff})");

// use previous difficulty
stratumDifficulty = context.PreviousDifficulty.Value;
}

else
throw new StratumException(StratumError.LowDifficultyShare, $"low difficulty share ({shareDiff})");
}

var share = new Share
{
BlockHeight = (long) BlockTemplate.Height,
IpAddress = worker.RemoteEndpoint?.Address?.ToString(),
Miner = context.Miner,
Worker = workerName,
UserAgent = context.UserAgent,
IsBlockCandidate = isBlockCandidate,
Difficulty = stratumDifficulty * EthereumConstants.Pow2x32
};

if(share.IsBlockCandidate)
{
fullNonceHex = "0x" + fullNonceHex;
var headerHash = BlockTemplate.Header;
var mixHash = mixDigest.ToHexString(true);

share.TransactionConfirmationData = "";

return new SubmitResult(share, fullNonceHex, headerHash, mixHash);
}

return new SubmitResult(share);
}

public async Task<SubmitResult> ProcessShareAsync(StratumConnection worker,
string workerName, string fullNonceHex, EthashFull ethash, CancellationToken ct)
{
// dupe check
lock(workerNonces)
{
RegisterNonce(worker, fullNonceHex);
}

var context = worker.ContextAs<EthereumWorkerContext>();

if(!ulong.TryParse(fullNonceHex, NumberStyles.HexNumber, CultureInfo.InvariantCulture, out var fullNonce))
throw new StratumException(StratumError.MinusOne, "bad nonce " + fullNonceHex);

// get dag for block
var dag = await ethash.GetDagAsync(BlockTemplate.Height, logger, CancellationToken.None);

// compute
if(!dag.Compute(logger, BlockTemplate.Header.HexToByteArray(), fullNonce, out var mixDigest, out var resultBytes))
throw new StratumException(StratumError.MinusOne, "bad hash");

// test if share meets at least workers current difficulty
resultBytes.ReverseInPlace();
var resultValue = new uint256(resultBytes);
var resultValueBig = resultBytes.AsSpan().ToBigInteger();
var shareDiff = (double) BigInteger.Divide(EthereumConstants.BigMaxValue, resultValueBig) / EthereumConstants.Pow2x32;
var stratumDifficulty = context.Difficulty;
var ratio = shareDiff / stratumDifficulty;
var isBlockCandidate = resultValue <= blockTarget;

if(!isBlockCandidate && ratio < 0.99)
{
// check if share matched the previous difficulty from before a vardiff retarget
if(context.VarDiff?.LastUpdate != null && context.PreviousDifficulty.HasValue)
{
ratio = shareDiff / context.PreviousDifficulty.Value;

if(ratio < 0.99)
throw new StratumException(StratumError.LowDifficultyShare, $"low difficulty share ({shareDiff})");

// use previous difficulty
stratumDifficulty = context.PreviousDifficulty.Value;
}

else
throw new StratumException(StratumError.LowDifficultyShare, $"low difficulty share ({shareDiff})");
}

var share = new Share
{
BlockHeight = (long) BlockTemplate.Height,
IpAddress = worker.RemoteEndpoint?.Address?.ToString(),
Miner = context.Miner,
Worker = workerName,
UserAgent = context.UserAgent,
IsBlockCandidate = isBlockCandidate,
Difficulty = stratumDifficulty * EthereumConstants.Pow2x32
};

if(share.IsBlockCandidate)
{
fullNonceHex = "0x" + fullNonceHex;
var headerHash = BlockTemplate.Header;
var mixHash = mixDigest.ToHexString(true);

share.TransactionConfirmationData = "";

return new SubmitResult(share, fullNonceHex, headerHash, mixHash);
}

return new SubmitResult(share);
}

public async Task<SubmitResult> ProcessShareUbqHashAsync(StratumConnection worker,
string workerName, string fullNonceHex, UbqhashFull ubqhash, CancellationToken ct)
string workerName, string fullNonceHex, CancellationToken ct)
{
// dupe check
lock(workerNonces)
Expand All @@ -213,11 +67,11 @@ public async Task<SubmitResult> ProcessShareUbqHashAsync(StratumConnection worke
if(!ulong.TryParse(fullNonceHex, NumberStyles.HexNumber, CultureInfo.InvariantCulture, out var fullNonce))
throw new StratumException(StratumError.MinusOne, "bad nonce " + fullNonceHex);

// get dag for block
var dag = await ubqhash.GetDagAsync(BlockTemplate.Height, logger, CancellationToken.None);
// get dag/light cache for block
var cache = await ethash.GetCacheAsync(logger, BlockTemplate.Height, ct);

// compute
if(!dag.Compute(logger, BlockTemplate.Header.HexToByteArray(), fullNonce, out var mixDigest, out var resultBytes))
if(!cache.Compute(logger, BlockTemplate.Header.HexToByteArray(), fullNonce, out var mixDigest, out var resultBytes))
throw new StratumException(StratumError.MinusOne, "bad hash");

// test if share meets at least workers current difficulty
Expand Down
Loading

0 comments on commit 753c90e

Please sign in to comment.