Skip to content
This repository has been archived by the owner on Oct 20, 2023. It is now read-only.

Commit

Permalink
Merge pull request #1519 from oliverw/dev
Browse files Browse the repository at this point in the history
Dev
  • Loading branch information
Oliver Weichhold authored Dec 1, 2022
2 parents b1c46a3 + f93bee0 commit 171a262
Show file tree
Hide file tree
Showing 51 changed files with 2,151 additions and 950 deletions.
2 changes: 1 addition & 1 deletion .github/workflows/dotnet.yml
Original file line number Diff line number Diff line change
Expand Up @@ -27,4 +27,4 @@ jobs:
- name: Build
run: dotnet build --no-restore src
- name: Test
run: dotnet test --no-build --verbosity normal src
run: dotnet test --logger:"console;verbosity=detailed" --no-build --verbosity normal src
2 changes: 2 additions & 0 deletions .gitignore
Original file line number Diff line number Diff line change
Expand Up @@ -204,3 +204,5 @@ fabric.properties

# End of https://www.toptal.com/developers/gitignore/api/rider
.idea

.fake
9 changes: 4 additions & 5 deletions README.md
Original file line number Diff line number Diff line change
Expand Up @@ -223,14 +223,13 @@ Once again, do not run a production pool on Windows! This is not a supported con

To support this project you can become a [sponsor](https://github.com/sponsors/oliverw) or send a donation to the following accounts:

* XMR: `46S2AEwYmD9fnmZkxCpXf1T3U3DyEq3Ekb8Lg9kgUMGABn9Fp9q5nE2fBcXebrjrXfZHy5uC5HfLE6X4WLtSm35wUr9Mh46`
* BTC: `bc1quzdczlpfn3n4xvpdz0x9h79569afhg0ashwxxp`
* BCH: `qrf6uhhapq7fgkjv2ce2hcjqpk8ec2zc25et4xsphv`
* LTC: `LTK6CWastkmBzGxgQhTTtCUjkjDA14kxzC`
* ETH: `miningcore.eth (ENS Address)`
* BTC: `miningcore.eth (ENS Address)`
* LTC: `miningcore.eth (ENS Address)`
* DOGE: `DGDuKRhBewGP1kbUz4hszNd2p6dDzWYy9Q`
* ETH: `0xcb55abBfe361B12323eb952110cE33d5F28BeeE1`
* ETC: `0xF8cCE9CE143C68d3d4A7e6bf47006f21Cfcf93c0`
* DASH: `XqpBAV9QCaoLnz42uF5frSSfrJTrqHoxjp`
* ZEC: `t1YHZHz2DGVMJiggD2P4fBQ2TAPgtLSUwZ7`
* BTG: `GQb77ZuMCyJGZFyxpzqNfm7GB1rQreP4n6`
* ERGO: `9foYU8JkoqWBSDA3ba8VHfduPXV2NaVNPPAFkdYoR9t9cPQGMv4`
* XMR: `46S2AEwYmD9fnmZkxCpXf1T3U3DyEq3Ekb8Lg9kgUMGABn9Fp9q5nE2fBcXebrjrXfZHy5uC5HfLE6X4WLtSm35wUr9Mh46`
45 changes: 0 additions & 45 deletions appveyor.yml

This file was deleted.

Binary file modified libs/runtimes/win-x64/libmultihash.dll
Binary file not shown.
8 changes: 8 additions & 0 deletions miningcore.code-workspace
Original file line number Diff line number Diff line change
@@ -0,0 +1,8 @@
{
"folders": [
{
"path": "."
}
],
"settings": {}
}
Original file line number Diff line number Diff line change
Expand Up @@ -39,7 +39,7 @@ public void Setup()
clock = ModuleInitializer.Container.Resolve<IMasterClock>();
logger = new NullLogger(LogManager.LogFactory);

connection = new(logger, rmsm, clock, ConnectionId);
connection = new(logger, rmsm, clock, ConnectionId, false);
wrapper = new(connection);
}

Expand Down
119 changes: 119 additions & 0 deletions src/Miningcore.Tests/Blockchain/Bitcoin/BitcoinJobTests.cs
Original file line number Diff line number Diff line change
@@ -0,0 +1,119 @@
using Autofac;
using Microsoft.IO;
using Miningcore.Blockchain.Bitcoin;
using Miningcore.Configuration;
using Miningcore.Stratum;
using Miningcore.Tests.Util;
using NBitcoin;
using Newtonsoft.Json;
using NLog;
using Xunit;
#pragma warning disable 8974

namespace Miningcore.Tests.Blockchain.Bitcoin;

public class BitcoinJobTests : TestBase
{
[Fact]
public void Process_Valid_Block()
{
var (job, worker) = CreateJob();

var submitParams = JsonConvert.DeserializeObject<object[]>("[\"yXHmbak4AdgK5vWamwqFtEijn2NpgLvmi4\",\"00000001\",\"01000000\",\"63445774\",\"51036775\"]", jsonSerializerSettings);

// extract params
var extraNonce2 = submitParams[2] as string;
var nTime = submitParams[3] as string;
var nonce = submitParams[4] as string;

// validate & process
var (share, blockHex) = job.ProcessShare(worker, extraNonce2, nTime, nonce);

Assert.NotNull(share);
Assert.Equal("00000056300e9fd18624edd7eaa8bcd6c8466d7eb8cf91b4e60f9d35fa97f504", share.BlockHash);
Assert.Equal("000000204b0e40a0b523ec3d00fc1a7cee084165a111646b9b35e50936ada1861a0100000362a84c2b4b2e530ec640e2a7f85e05da2c42c8e3645a5bbc2245e74ec1ae967457446371d7011e756703510103000500010000000000000000000000000000000000000000000000000000000000000000ffffffff1d03b66a0c04745744630060000001010000000a4d696e696e67636f7265000000000241016d40000000001976a91464f2b2b84f62d68a2cd7f7f5fb2b5aa75ef716d788ac2c56f32a000000001976a9141a9cab092e161f3822af4b27f4f33051dbb7d32088ac00000000460200b66a0c00fbab6816312c05803d026cce30fec0332c059f66e421ab0bf65b96ea9efb8a22e12cfc31666208b47a006e5b74f95a4c0797b6bc620ea1cc07cb53616e547302", blockHex);
Assert.Equal(813750, share.BlockHeight);
Assert.True(share.IsBlockCandidate);
}

[Fact]
public void Process_Duplicate_Submission()
{
var (job, worker) = CreateJob();

var submitParams = JsonConvert.DeserializeObject<object[]>("[\"yXHmbak4AdgK5vWamwqFtEijn2NpgLvmi4\",\"00000001\",\"01000000\",\"63445774\",\"51036775\"]", jsonSerializerSettings);

// extract params
var extraNonce2 = submitParams[2] as string;
var nTime = submitParams[3] as string;
var nonce = submitParams[4] as string;

// validate & process
var (share, _) = job.ProcessShare(worker, extraNonce2, nTime, nonce);

Assert.NotNull(share);
Assert.True(share.IsBlockCandidate);

Assert.ThrowsAny<StratumException>(()=> job.ProcessShare(worker, extraNonce2, nTime, nonce));
}

[Fact]
public void Process_Invalid_Nonce()
{
var (job, worker) = CreateJob();

var submitParams = JsonConvert.DeserializeObject<object[]>("[\"yXHmbak4AdgK5vWamwqFtEijn2NpgLvmi4\",\"00000001\",\"01000000\",\"63445774\",\"61036775\"]", jsonSerializerSettings);

// extract params
var extraNonce2 = submitParams[2] as string;
var nTime = submitParams[3] as string;
var nonce = submitParams[4] as string;

// validate & process
Assert.ThrowsAny<StratumException>(()=> job.ProcessShare(worker, extraNonce2, nTime, nonce));
}

[Fact]
public void Process_Invalid_Time()
{
var (job, worker) = CreateJob();

var submitParams = JsonConvert.DeserializeObject<object[]>("[\"yXHmbak4AdgK5vWamwqFtEijn2NpgLvmi4\",\"00000001\",\"01000000\",\"13445774\",\"51036775\"]", jsonSerializerSettings);

// extract params
var extraNonce2 = submitParams[2] as string;
var nTime = submitParams[3] as string;
var nonce = submitParams[4] as string;

// validate & process
Assert.ThrowsAny<StratumException>(()=> job.ProcessShare(worker, extraNonce2, nTime, nonce));
}

private (BitcoinJob, StratumConnection) CreateJob()
{
var job = new BitcoinJob();
var coin = (BitcoinTemplate) ModuleInitializer.CoinTemplates["dash"];
var pc = new PoolConfig { Template = coin };

var blockTemplate = JsonConvert.DeserializeObject<Miningcore.Blockchain.Bitcoin.DaemonResponses.BlockTemplate>("{\"version\":536870912,\"previousBlockhash\":\"0000011a86a1ad3609e5359b6b6411a1654108ee7c1afc003dec23b5a0400e4b\",\"coinbaseValue\":1801475949,\"target\":\"000001d771000000000000000000000000000000000000000000000000000000\",\"nonceRange\":\"00000000ffffffff\",\"curTime\":1665423220,\"bits\":\"1e01d771\",\"height\":813750,\"transactions\":[],\"coinbaseAux\":{\"flags\":null},\"default_witness_commitment\":null,\"capabilities\":[\"proposal\"],\"rules\":[\"csv\",\"dip0001\",\"bip147\",\"dip0003\",\"dip0008\",\"realloc\",\"dip0020\",\"dip0024\"],\"vbavailable\":{},\"vbrequired\":0,\"longpollid\":\"0000011a86a1ad3609e5359b6b6411a1654108ee7c1afc003dec23b5a0400e4b814670\",\"mintime\":1665422408,\"mutable\":[\"time\",\"transactions\",\"prevblock\"],\"sigoplimit\":40000,\"sizelimit\":2000000,\"previousbits\":\"1e01bee4\",\"masternode\":[{\"payee\":\"yVXDAM73Tg6A44Bm3qduXsMCYxzuqBCT48\",\"script\":\"76a91464f2b2b84f62d68a2cd7f7f5fb2b5aa75ef716d788ac\",\"amount\":1080885569}],\"masternode_payments_started\":true,\"masternode_payments_enforced\":true,\"superblock\":[],\"superblocks_started\":true,\"superblocks_enabled\":true,\"coinbase_payload\":\"0200b66a0c00fbab6816312c05803d026cce30fec0332c059f66e421ab0bf65b96ea9efb8a22e12cfc31666208b47a006e5b74f95a4c0797b6bc620ea1cc07cb53616e547302\"}", jsonSerializerSettings);
var clock = MockMasterClock.FromTicks(638010200200475015);
var poolAddressDestination = BitcoinUtils.AddressToDestination("yNkA6gVSPqKzW6WmJtTazRLKbSkQA5ND2h", Network.TestNet);
var network = Network.GetNetwork("testnet");

var context = new BitcoinWorkerContext
{
Miner = "yXHmbak4AdgK5vWamwqFtEijn2NpgLvmi4",
ExtraNonce1 = "60000001",
Difficulty = 0.01,
UserAgent = "cpuminer-multi/1.3.1"
};

var worker = new StratumConnection(new NullLogger(LogManager.LogFactory), container.Resolve<RecyclableMemoryStreamManager>(), clock, "1", false);
worker.SetContext(context);

job.Init(blockTemplate, "1", pc, null, new ClusterConfig(), clock, poolAddressDestination, network, false,
coin.ShareMultiplier, coin.CoinbaseHasherValue, coin.HeaderHasherValue, coin.BlockHasherValue);

return (job, worker);
}
}
66 changes: 66 additions & 0 deletions src/Miningcore.Tests/Coins/CoinTemplateValidationTest.cs
Original file line number Diff line number Diff line change
@@ -0,0 +1,66 @@
using System.Linq;
using System.Reflection;
using System.Runtime.Serialization;
using Miningcore.Configuration;
using Xunit;
using Xunit.Abstractions;
#pragma warning disable 8974

namespace Miningcore.Tests.Coins;

public class CoinTemplateValidationTest : TestBase
{
private readonly ITestOutputHelper output;

public CoinTemplateValidationTest(ITestOutputHelper output)
{
this.output = output;
}

[Fact]
public void Validate_Coin_Templates()
{
var cft = typeof(CoinFamily).GetTypeInfo();
var cryptonightHashType = typeof(CryptonightHashType).GetTypeInfo();

foreach(var template in ModuleInitializer.CoinTemplates)
{
var t = template.Value;

output.WriteLine($"* {t.Name ?? t.Symbol ?? t.CanonicalName}");

Assert.NotEmpty(t.Name);
Assert.NotEmpty(t.Symbol);
Assert.True(CoinTemplate.Families.ContainsKey(t.Family));
Assert.NotNull(cft.DeclaredMembers.SingleOrDefault(x => x.Name == t.Family.ToString())?.GetCustomAttribute<EnumMemberAttribute>(false));

switch(t)
{
case BitcoinTemplate bt when t is BitcoinTemplate:
{
if(bt.CoinbaseHasher != null)
Assert.Null(Record.Exception(() => bt.CoinbaseHasherValue));

if(bt.HeaderHasher != null)
Assert.Null(Record.Exception(() => bt.HeaderHasherValue));

if(bt.BlockHasher != null)
Assert.Null(Record.Exception(() => bt.BlockHasherValue));

if(bt.PoSBlockHasher != null)
Assert.Null(Record.Exception(() => bt.PoSBlockHasherValue));
break;
}

case CryptonoteCoinTemplate cnt when t is CryptonoteCoinTemplate:
{
Assert.NotNull(cryptonightHashType.DeclaredMembers.SingleOrDefault(x => x.Name == cnt.Hash.ToString())?.GetCustomAttribute<EnumMemberAttribute>(false));

break;
}
}

Assert.NotEmpty(t.GetAlgorithmName());
}
}
}
21 changes: 21 additions & 0 deletions src/Miningcore.Tests/Crypto/HashingTests.cs
Original file line number Diff line number Diff line change
Expand Up @@ -176,6 +176,16 @@ public void Sha256D_Hash()
Assert.Equal("4f4eb6dbba8198745a278997e154e8309b571259e33fce4d3a31adea39dc9173", result);
}

[Fact]
public void Sha256DT_Hash()
{
var hasher = new Sha256DT();
var hash = new byte[32];
hasher.Digest(testValue2, hash);
var result = hash.ToHexString();
Assert.Equal("bf4735b3a0feebe83727a7a2327f8223eec7484190e8dd52611ce75b045a2e75", result);
}

[Fact]
public void Sha256S_Hash()
{
Expand All @@ -187,6 +197,17 @@ public void Sha256S_Hash()
Assert.Equal("bd75a82b9957d6d043076dea52262635042693f1fe23bcadadaecc908e1e5cc6", result);
}

[Fact]
public void Sha512256D_Hash()
{
var hasher = new Sha512256D();
var hash = new byte[32];
hasher.Digest(testValue, hash);
var result = hash.ToHexString();

Assert.Equal("6b86ce4bf945d8e935d51db4e32589acf6dbcda58ca1cef7568d52f704c46d7f", result);
}

[Fact]
public void X11_Hash()
{
Expand Down
6 changes: 3 additions & 3 deletions src/Miningcore.Tests/Miningcore.Tests.csproj
Original file line number Diff line number Diff line change
Expand Up @@ -35,10 +35,10 @@
<ItemGroup>
<PackageReference Include="BenchmarkDotNet" Version="0.13.2" />
<PackageReference Include="BenchmarkDotNet.Annotations" Version="0.13.2" />
<PackageReference Include="Microsoft.NET.Test.Sdk" Version="17.3.1" />
<PackageReference Include="Microsoft.NET.Test.Sdk" Version="17.4.0" />
<PackageReference Include="Microsoft.Reactive.Testing" Version="5.0.0" />
<PackageReference Include="NLog" Version="5.0.4" />
<PackageReference Include="Npgsql" Version="6.0.6" />
<PackageReference Include="NLog" Version="5.0.5" />
<PackageReference Include="Npgsql" Version="6.0.7" />
<PackageReference Include="NSubstitute" Version="4.4.0" />
<PackageReference Include="xunit" Version="2.4.2" />
<PackageReference Include="xunit.runner.visualstudio" Version="2.4.5">
Expand Down
6 changes: 3 additions & 3 deletions src/Miningcore.Tests/Stratum/StratumConnectionTests.cs
Original file line number Diff line number Diff line change
Expand Up @@ -34,7 +34,7 @@ public class StratumConnectionTests : TestBase
[Fact]
public async Task ProcessRequest_Handle_Valid_Request()
{
var connection = new StratumConnection(logger, rmsm, clock, ConnectionId);
var connection = new StratumConnection(logger, rmsm, clock, ConnectionId, false);
var wrapper = new PrivateObject(connection);

Task handler(StratumConnection con, JsonRpcRequest request, CancellationToken ct)
Expand All @@ -61,7 +61,7 @@ public async Task ProcessRequest_Throw_On_Unparseable_Request()
{
const string invalidRequestString = "foo bar\\n";

var connection = new StratumConnection(logger, rmsm, clock, ConnectionId);
var connection = new StratumConnection(logger, rmsm, clock, ConnectionId, false);
var wrapper = new PrivateObject(connection);
var callCount = 0;

Expand All @@ -82,7 +82,7 @@ await Assert.ThrowsAnyAsync<JsonException>(()=> (Task) wrapper.Invoke(ProcessReq
[Fact]
public async Task ProcessRequest_Honor_CancellationToken()
{
var connection = new StratumConnection(logger, rmsm, clock, ConnectionId);
var connection = new StratumConnection(logger, rmsm, clock, ConnectionId, false);
var wrapper = new PrivateObject(connection);
var callCount = 0;

Expand Down
9 changes: 9 additions & 0 deletions src/Miningcore.Tests/TestBase.cs
Original file line number Diff line number Diff line change
@@ -1,9 +1,18 @@
using Autofac;
using Newtonsoft.Json;

namespace Miningcore.Tests;

public abstract class TestBase
{
protected TestBase()
{
ModuleInitializer.Initialize();

container = ModuleInitializer.Container;
jsonSerializerSettings = container.Resolve<JsonSerializerSettings>();
}

protected readonly IContainer container;
protected readonly JsonSerializerSettings jsonSerializerSettings;
}
8 changes: 8 additions & 0 deletions src/Miningcore.Tests/Util/MockMasterClock.cs
Original file line number Diff line number Diff line change
Expand Up @@ -8,4 +8,12 @@ public class MockMasterClock : IMasterClock
public DateTime CurrentTime { get; set; }

public DateTime Now => CurrentTime;

public static MockMasterClock FromTicks(long value)
{
return new MockMasterClock
{
CurrentTime = new DateTime(value, DateTimeKind.Utc)
};
}
}
Loading

0 comments on commit 171a262

Please sign in to comment.