Skip to content
Merged
Show file tree
Hide file tree
Changes from all commits
Commits
File filter

Filter by extension

Filter by extension

Conversations
Failed to load comments.
Loading
Jump to
Jump to file
Failed to load files.
Loading
Diff view
Diff view
129 changes: 129 additions & 0 deletions examples/waglayla_pool.json
Original file line number Diff line number Diff line change
@@ -0,0 +1,129 @@
{
"logging": {
"level": "debug",
"enableConsoleLog": true,
"enableConsoleColors": true,
"logFile": "",
"apiLogFile": "",
"logBaseDirectory": "",
"perPoolLogFile": false,
},
"banning": {
"manager": "Integrated",
"banOnJunkReceive": true,
"banOnInvalidShares": false
},
"notifications": {
"enabled": false,
"email": {
"host": "smtp.example.com",
"port": 587,
"user": "user",
"password": "password",
"fromAddress": "info@yourpool.org",
"fromName": "support"
},
"admin": {
"enabled": false,
"emailAddress": "user@example.com",
"notifyBlockFound": true
}
},
"persistence": {
"postgres": {
"host": "127.0.0.1",
"port": 5432,
"user": "miningcore",
"password": "password",
"database": "miningcore",
"createPoolStats": true,
"migrateToLatest": true
}
},
"paymentProcessing": {
"enabled": true,
"interval": 600,
"shareRecoveryFile": "recovered-shares.txt"
},
"api": {
"enabled": true,
"listenAddress": "*",
"port": 4000,
"metricsIpWhitelist": [],
"rateLimiting": {
"disabled": true,
"rules": [
{
"Endpoint": "*",
"Period": "1s",
"Limit": 5
}
],
"ipWhitelist": [
""
]
}
},
"pools": [{
"id": "wala1",
"enabled": true,
"coin": "waglayla",
"address": "waglayla:qpy5wlu5mxpq86cefnvfylv7p8emuhttprs5dqm8mwn3ynz2a7zags93a8g05",
"rewardRecipients": [
{
"type": "op",
"address": "waglayla:qpy5wlu5mxpq86cefnvfylv7p8emuhttprs5dqm8mwn3ynz2a7zags93a8g05",
"percentage": 1
}
],
"protobufWalletRpcServiceName": "waglaylawalletd.waglaylawalletd",
"enableAsicBoost": true,
"clientConnectionTimeout": 600,
"banning": {
"enabled": true,
"time": 600,
"invalidPercent": 50,
"checkThreshold": 50
},
"ports": {
"3094": {
"listenAddress": "0.0.0.0",
"difficulty": 4,
"varDiff": {
"minDiff": 2,
"maxDiff": null,
"targetTime": 15,
"retargetTime": 90,
"variancePercent": 100,
"maxDelta": 512
}
}
},
"daemons": [
{
"host": "127.0.0.1",
"port": 12110,
"user": null,
"password": null
},
{
"host": "127.0.0.1",
"port": 8082,
"user": null,
"password": null,
"category": "wallet"
}
],
"paymentProcessing": {
"enabled": true,
"walletPassword": "<The WagLayla's wallet password which owns the pool address>",
"minimumPayment": 1,
"versionEnablingMaxFee": "v0.12.18-rc5",
"maxFee": 200000,
"payoutScheme": "PPLNS",
"payoutSchemeConfig": {
"factor": 0.5
}
}
}]
}
134 changes: 58 additions & 76 deletions src/Miningcore/Blockchain/Kaspa/Custom/Waglayla/WaglaylaJob.cs
Original file line number Diff line number Diff line change
@@ -1,4 +1,4 @@
using System;
using System.Text;
using System.Numerics;
using Miningcore.Crypto;
using Miningcore.Crypto.Hashing.Algorithms;
Expand All @@ -7,98 +7,80 @@
using Miningcore.Util;
using NBitcoin;

namespace Miningcore.Blockchain.Kaspa.Custom.Waglayla;
namespace Miningcore.Blockchain.Kaspa.Custom.WagLayla;

public class WaglaylaJob: KaspaJob {
protected Blake3IHash blake3Hasher;
protected Sha3_256 sha3_256Hasher;

public WaglaylaJob(IHashAlgorithm customBlockHeaderHasher, IHashAlgorithm customCoinbaseHasher, IHashAlgorithm customShareHasher): base(customBlockHeaderHasher, customCoinbaseHasher, customShareHasher) {
this.blake3Hasher = new Blake3IHash();
this.sha3_256Hasher = new Sha3_256();
}

private Span<byte> MatrixMultiply(Span<byte> input)
public class WagLaylaJob : KaspaJobAltKHeavy
{
// Example placeholder matrix operation
byte[,] matrix = {
{ 1, 2, 3, 4 },
{ 5, 6, 7, 8 },
{ 9, 10, 11, 12 },
{ 13, 14, 15, 16 }
};

byte[] result = new byte[32];
for (int i = 0; i < 32; i++)
protected Blake3IHash blake3Hasher;
protected Sha3_256 sha3_256Hasher;

public WagLaylaJob(IHashAlgorithm customBlockHeaderHasher, IHashAlgorithm customCoinbaseHasher, IHashAlgorithm customShareHasher)
: base(customBlockHeaderHasher, customCoinbaseHasher, customShareHasher)
{
result[i] = 0;
for (int j = 0; j < 32; j++)
{
result[i] ^= (byte)(input[j] * matrix[i % 4, j % 4]); // Example multiplication
}
this.blake3Hasher = new Blake3IHash();
this.sha3_256Hasher = new Sha3_256();
}

return result.AsSpan();
}

protected override Share ProcessShareInternal(StratumConnection worker, string nonce) {
var context = worker.ContextAs < KaspaWorkerContext > ();

BlockTemplate.Header.Nonce = Convert.ToUInt64(nonce, 16);

var prePowHashBytes = SerializeHeader(BlockTemplate.Header, true);
Span < byte > blake3Bytes = stackalloc byte[32];
blake3Hasher.Digest(prePowHashBytes, blake3Bytes);
protected override Share ProcessShareInternal(StratumConnection worker, string nonce)
{
var context = worker.ContextAs<KaspaWorkerContext>();

Span < byte > sha3Bytes = stackalloc byte[32];
sha3_256Hasher.Digest(blake3Bytes, sha3Bytes);
BlockTemplate.Header.Nonce = Convert.ToUInt64(nonce, 16);

Span < byte > matrixResult = MatrixMultiply(sha3Bytes);
var prePowHashBytes = SerializeHeader(BlockTemplate.Header, true);
var coinbaseBytes = SerializeCoinbase(prePowHashBytes, BlockTemplate.Header.Timestamp, BlockTemplate.Header.Nonce);

Span < byte > waglaylaHash = stackalloc byte[32];
blake3Hasher.Digest(matrixResult, waglaylaHash);
Span<byte> sha3_256Bytes = stackalloc byte[32];
sha3_256Hasher.Digest(coinbaseBytes, sha3_256Bytes);

var targetHashCoinbaseBytes = new Target(new BigInteger(waglaylaHash.ToNewReverseArray(), true, true));
var hashCoinbaseBytesValue = targetHashCoinbaseBytes.ToUInt256();
Span<byte> hashCoinbaseBytes = stackalloc byte[32];
shareHasher.Digest(ComputeCoinbase(prePowHashBytes, sha3_256Bytes), hashCoinbaseBytes);

var shareDiff = (double) new BigRational(KaspaConstants.Diff1b, targetHashCoinbaseBytes.ToBigInteger()) * shareMultiplier;
var targetHashCoinbaseBytes = new Target(new BigInteger(hashCoinbaseBytes.ToNewReverseArray(), true, true));
var hashCoinbaseBytesValue = targetHashCoinbaseBytes.ToUInt256();

// diff check
var stratumDifficulty = context.Difficulty;
var ratio = shareDiff / stratumDifficulty;
var shareDiff = (double) new BigRational(KaspaConstants.Diff1b, targetHashCoinbaseBytes.ToBigInteger()) * shareMultiplier;

// check if the share meets the much harder block difficulty (block candidate)
var isBlockCandidate = hashCoinbaseBytesValue <= blockTargetValue;
//var isBlockCandidate = true;
// diff check
var stratumDifficulty = context.Difficulty;
var ratio = shareDiff / stratumDifficulty;

// test if share meets at least workers current difficulty
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;
// check if the share meets the much harder block difficulty (block candidate)
var isBlockCandidate = hashCoinbaseBytesValue <= blockTargetValue;

if (ratio < 0.99)
throw new StratumException(StratumError.LowDifficultyShare, $"low difficulty share ({shareDiff})");
// test if share meets at least workers current difficulty
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})");
}

// use previous difficulty
stratumDifficulty = context.PreviousDifficulty.Value;
} else
throw new StratumException(StratumError.LowDifficultyShare, $"low difficulty share ({shareDiff})");
}
var result = new Share
{
BlockHeight = (long) BlockTemplate.Header.DaaScore,
NetworkDifficulty = Difficulty,
Difficulty = context.Difficulty / shareMultiplier
};

var result = new Share {
BlockHeight = (long) BlockTemplate.Header.DaaScore,
NetworkDifficulty = Difficulty,
Difficulty = context.Difficulty / shareMultiplier
};
if(isBlockCandidate)
{
var hashBytes = SerializeHeader(BlockTemplate.Header, false);

if (isBlockCandidate) {
var hashBytes = SerializeHeader(BlockTemplate.Header, false);
result.IsBlockCandidate = true;
result.BlockHash = hashBytes.ToHexString();
}

result.IsBlockCandidate = true;
result.BlockHash = hashBytes.ToHexString();
return result;
}

return result;
}
}
50 changes: 50 additions & 0 deletions src/Miningcore/Blockchain/Kaspa/KaspaJob.cs
Original file line number Diff line number Diff line change
Expand Up @@ -387,4 +387,54 @@ public virtual void Init(kaspad.RpcBlock blockTemplate, string jobId, double sha
blockTemplate.Header.Timestamp,
};
}
}

public class KaspaJobAltKHeavy : KaspaJob
{
public KaspaJobAltKHeavy(IHashAlgorithm customBlockHeaderHasher, IHashAlgorithm customCoinbaseHasher, IHashAlgorithm customShareHasher)
: base(customBlockHeaderHasher, customCoinbaseHasher, customShareHasher)
{
}

protected override Span<byte> ComputeCoinbase(Span<byte> prePowHash, Span<byte> data)
{
ushort[][] matrix = GenerateMatrix(prePowHash);
byte[] scratch = data.ToArray(); // Create a copy to work with

// Convert bytes to nibbles
ushort[] v = new ushort[64];
for (int i = 0; i < 16; i++)
{
v[i * 4] = (ushort)(scratch[i * 2] >> 4);
v[i * 4 + 1] = (ushort)(scratch[i * 2] & 0x0F);
v[i * 4 + 2] = (ushort)(scratch[i * 2 + 1] >> 4);
v[i * 4 + 3] = (ushort)(scratch[i * 2 + 1] & 0x0F);
}

// Perform matrix multiplication with XOR folding
for (int i = 0; i < 16; i++)
{
ushort sum1 = 0, sum2 = 0, sum3 = 0, sum4 = 0;

for (int j = 0; j < 64; j++)
{
sum1 += (ushort)(matrix[4 * i][j] * v[j]);
sum2 += (ushort)(matrix[4 * i + 1][j] * v[j]);
sum3 += (ushort)(matrix[4 * i + 2][j] * v[j]);
sum4 += (ushort)(matrix[4 * i + 3][j] * v[j]);
}

// XOR folding of sums
sum1 = (ushort)((sum1 & 0xF) ^ ((sum1 >> 4) & 0xF) ^ ((sum1 >> 8) & 0xF));
sum2 = (ushort)((sum2 & 0xF) ^ ((sum2 >> 4) & 0xF) ^ ((sum2 >> 8) & 0xF));
sum3 = (ushort)((sum3 & 0xF) ^ ((sum3 >> 4) & 0xF) ^ ((sum3 >> 8) & 0xF));
sum4 = (ushort)((sum4 & 0xF) ^ ((sum4 >> 4) & 0xF) ^ ((sum4 >> 8) & 0xF));

// XOR with original data
scratch[i * 2] ^= (byte)(((byte)sum1 << 4) | (byte)sum2);
scratch[i * 2 + 1] ^= (byte)(((byte)sum3 << 4) | (byte)sum4);
}

return scratch;
}
}
14 changes: 9 additions & 5 deletions src/Miningcore/Blockchain/Kaspa/KaspaJobManager.cs
Original file line number Diff line number Diff line change
Expand Up @@ -18,7 +18,7 @@
using Miningcore.Blockchain.Kaspa.Custom.Karlsencoin;
using Miningcore.Blockchain.Kaspa.Custom.Pyrin;
using Miningcore.Blockchain.Kaspa.Custom.Spectre;
using Miningcore.Blockchain.Kaspa.Custom.Waglayla;
using Miningcore.Blockchain.Kaspa.Custom.WagLayla;
using NLog;
using Miningcore.Configuration;
using Miningcore.Crypto;
Expand Down Expand Up @@ -345,15 +345,19 @@ private KaspaJob CreateJob(ulong blockHeight)
return new SpectreJob(customBlockHeaderHasher, customCoinbaseHasher, customShareHasher);
case "WALA":
if(customBlockHeaderHasher is not Blake3IHash)
customBlockHeaderHasher = new Blake3IHash();
{
string coinbaseBlockHash = KaspaConstants.CoinbaseBlockHash;
byte[] hashBytes = Encoding.UTF8.GetBytes(coinbaseBlockHash.PadRight(32, '\0')).Take(32).ToArray();
customBlockHeaderHasher = new Blake3IHash(hashBytes);
}

if(customCoinbaseHasher is not Sha3_256)
customCoinbaseHasher = new Sha3_256();
if(customCoinbaseHasher is not Blake3IHash)
customCoinbaseHasher = new Blake3IHash();

if(customShareHasher is not Blake3IHash)
customShareHasher = new Blake3IHash();

return new WaglaylaJob(customBlockHeaderHasher, customCoinbaseHasher, customShareHasher);
return new WagLaylaJob(customBlockHeaderHasher, customCoinbaseHasher, customShareHasher);

}

Expand Down
Loading
Loading