diff --git a/.github/workflows/dotnet.yml b/.github/workflows/dotnet.yml index 96739ceec..5a20a8e1b 100644 --- a/.github/workflows/dotnet.yml +++ b/.github/workflows/dotnet.yml @@ -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 diff --git a/.gitignore b/.gitignore index 45ea3b60e..c318eebe2 100644 --- a/.gitignore +++ b/.gitignore @@ -204,3 +204,5 @@ fabric.properties # End of https://www.toptal.com/developers/gitignore/api/rider .idea + +.fake \ No newline at end of file diff --git a/README.md b/README.md index f2559acf1..eef7db057 100644 --- a/README.md +++ b/README.md @@ -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` diff --git a/appveyor.yml b/appveyor.yml deleted file mode 100644 index 5c51ce830..000000000 --- a/appveyor.yml +++ /dev/null @@ -1,45 +0,0 @@ -#---------------------------------# -# environment configuration # -#---------------------------------# - -# Build worker image (VM template) -image: -- Visual Studio 2022 -- Ubuntu2004 - -#---------------------------------# -# build configuration # -#---------------------------------# - -# scripts to run before build -before_build: - - cd src - - dotnet restore - -build_script: - - # Install Linux build-dependencies - - sh: sudo apt-get update -y && sudo apt-get -y install cmake build-essential libssl-dev pkg-config libboost-all-dev libsodium-dev libzmq5 - - # Publish - - cd Miningcore - - dotnet publish -c Release --framework net6.0 - - # Publish Artifacts - - sh: (cd bin/Release/net6.0 && mkdir miningcore && cp -r publish/* miningcore && tar cf miningcore-linux-ubuntu-x64.tar.gz miningcore && appveyor PushArtifact miningcore-linux-ubuntu-x64.tar.gz) - - cmd: cd bin\Release\net6.0 && mkdir miningcore && xcopy publish\* miningcore /S && 7z a miningcore-win-x64.zip miningcore && appveyor PushArtifact miningcore-win-x64.zip && cd ..\..\.. - - # Build Tests - - cd ../Miningcore.Tests - - dotnet build -c Release --framework net6.0 - -#---------------------------------# -# tests configuration # -#---------------------------------# - -# to run tests again only selected assemblies and/or categories -test_script: - - dotnet test -c Release --no-build - -before_test: - - sh: cp -v $APPVEYOR_BUILD_FOLDER/src/Miningcore/bin/Release/net6.0/publish/*.so $APPVEYOR_BUILD_FOLDER/src/Miningcore.Tests/bin/Release/net6.0/ - -#---------------------------------# -# notifications # -#---------------------------------# diff --git a/libs/runtimes/win-x64/libmultihash.dll b/libs/runtimes/win-x64/libmultihash.dll index d3d74ab92..8db1c52fc 100644 Binary files a/libs/runtimes/win-x64/libmultihash.dll and b/libs/runtimes/win-x64/libmultihash.dll differ diff --git a/miningcore.code-workspace b/miningcore.code-workspace new file mode 100644 index 000000000..876a1499c --- /dev/null +++ b/miningcore.code-workspace @@ -0,0 +1,8 @@ +{ + "folders": [ + { + "path": "." + } + ], + "settings": {} +} \ No newline at end of file diff --git a/src/Miningcore.Tests/Benchmarks/Stratum/StratumConnectionBenchmarks.cs b/src/Miningcore.Tests/Benchmarks/Stratum/StratumConnectionBenchmarks.cs index 7860c77a2..5c23c4ea3 100644 --- a/src/Miningcore.Tests/Benchmarks/Stratum/StratumConnectionBenchmarks.cs +++ b/src/Miningcore.Tests/Benchmarks/Stratum/StratumConnectionBenchmarks.cs @@ -39,7 +39,7 @@ public void Setup() clock = ModuleInitializer.Container.Resolve(); logger = new NullLogger(LogManager.LogFactory); - connection = new(logger, rmsm, clock, ConnectionId); + connection = new(logger, rmsm, clock, ConnectionId, false); wrapper = new(connection); } diff --git a/src/Miningcore.Tests/Blockchain/Bitcoin/BitcoinJobTests.cs b/src/Miningcore.Tests/Blockchain/Bitcoin/BitcoinJobTests.cs new file mode 100644 index 000000000..a4957010c --- /dev/null +++ b/src/Miningcore.Tests/Blockchain/Bitcoin/BitcoinJobTests.cs @@ -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("[\"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("[\"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(()=> job.ProcessShare(worker, extraNonce2, nTime, nonce)); + } + + [Fact] + public void Process_Invalid_Nonce() + { + var (job, worker) = CreateJob(); + + var submitParams = JsonConvert.DeserializeObject("[\"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(()=> job.ProcessShare(worker, extraNonce2, nTime, nonce)); + } + + [Fact] + public void Process_Invalid_Time() + { + var (job, worker) = CreateJob(); + + var submitParams = JsonConvert.DeserializeObject("[\"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(()=> 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("{\"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(), 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); + } +} diff --git a/src/Miningcore.Tests/Coins/CoinTemplateValidationTest.cs b/src/Miningcore.Tests/Coins/CoinTemplateValidationTest.cs new file mode 100644 index 000000000..db826f07e --- /dev/null +++ b/src/Miningcore.Tests/Coins/CoinTemplateValidationTest.cs @@ -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(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(false)); + + break; + } + } + + Assert.NotEmpty(t.GetAlgorithmName()); + } + } +} diff --git a/src/Miningcore.Tests/Crypto/HashingTests.cs b/src/Miningcore.Tests/Crypto/HashingTests.cs index 4613e07f4..3c89ae1bd 100644 --- a/src/Miningcore.Tests/Crypto/HashingTests.cs +++ b/src/Miningcore.Tests/Crypto/HashingTests.cs @@ -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() { @@ -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() { diff --git a/src/Miningcore.Tests/Miningcore.Tests.csproj b/src/Miningcore.Tests/Miningcore.Tests.csproj index 1f77735bb..1da5ff8bf 100644 --- a/src/Miningcore.Tests/Miningcore.Tests.csproj +++ b/src/Miningcore.Tests/Miningcore.Tests.csproj @@ -35,10 +35,10 @@ - + - - + + diff --git a/src/Miningcore.Tests/Stratum/StratumConnectionTests.cs b/src/Miningcore.Tests/Stratum/StratumConnectionTests.cs index c9e973aa5..26c331424 100644 --- a/src/Miningcore.Tests/Stratum/StratumConnectionTests.cs +++ b/src/Miningcore.Tests/Stratum/StratumConnectionTests.cs @@ -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) @@ -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; @@ -82,7 +82,7 @@ await Assert.ThrowsAnyAsync(()=> (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; diff --git a/src/Miningcore.Tests/TestBase.cs b/src/Miningcore.Tests/TestBase.cs index 1e89becd9..6c1b3dbfd 100644 --- a/src/Miningcore.Tests/TestBase.cs +++ b/src/Miningcore.Tests/TestBase.cs @@ -1,3 +1,6 @@ +using Autofac; +using Newtonsoft.Json; + namespace Miningcore.Tests; public abstract class TestBase @@ -5,5 +8,11 @@ public abstract class TestBase protected TestBase() { ModuleInitializer.Initialize(); + + container = ModuleInitializer.Container; + jsonSerializerSettings = container.Resolve(); } + + protected readonly IContainer container; + protected readonly JsonSerializerSettings jsonSerializerSettings; } diff --git a/src/Miningcore.Tests/Util/MockMasterClock.cs b/src/Miningcore.Tests/Util/MockMasterClock.cs index 705d64b75..0f1e888da 100644 --- a/src/Miningcore.Tests/Util/MockMasterClock.cs +++ b/src/Miningcore.Tests/Util/MockMasterClock.cs @@ -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) + }; + } } diff --git a/src/Miningcore/Api/Controllers/PoolApiController.cs b/src/Miningcore/Api/Controllers/PoolApiController.cs index 410213410..2649a6c94 100644 --- a/src/Miningcore/Api/Controllers/PoolApiController.cs +++ b/src/Miningcore/Api/Controllers/PoolApiController.cs @@ -68,7 +68,15 @@ public async Task Get(CancellationToken ct, [FromQuery] uint t // enrich result.TotalPaid = await cf.Run(con => statsRepo.GetTotalPoolPaymentsAsync(con, config.Id, ct)); result.TotalBlocks = await cf.Run(con => blocksRepo.GetPoolBlockCountAsync(con, config.Id, ct)); - result.LastPoolBlockTime = await cf.Run(con => blocksRepo.GetLastPoolBlockTimeAsync(con, config.Id)); + var lastBlockTime = await cf.Run(con => blocksRepo.GetLastPoolBlockTimeAsync(con, config.Id)); + result.LastPoolBlockTime = lastBlockTime; + + if(lastBlockTime.HasValue) + { + DateTime startTime = lastBlockTime.Value; + var poolEffort = await cf.Run(con => shareRepo.GetEffortBetweenCreatedAsync(con, config.Id, pool.ShareMultiplier, startTime, clock.Now)); + result.PoolEffort = poolEffort.Value; + } var from = clock.Now.AddHours(-topMinersRange); @@ -128,7 +136,15 @@ public async Task GetPoolInfoAsync(string poolId, CancellationT // enrich response.Pool.TotalPaid = await cf.Run(con => statsRepo.GetTotalPoolPaymentsAsync(con, pool.Id, ct)); response.Pool.TotalBlocks = await cf.Run(con => blocksRepo.GetPoolBlockCountAsync(con, pool.Id, ct)); - response.Pool.LastPoolBlockTime = await cf.Run(con => blocksRepo.GetLastPoolBlockTimeAsync(con, pool.Id)); + var lastBlockTime = await cf.Run(con => blocksRepo.GetLastPoolBlockTimeAsync(con, pool.Id)); + response.Pool.LastPoolBlockTime = lastBlockTime; + + if(lastBlockTime.HasValue) + { + DateTime startTime = lastBlockTime.Value; + var poolEffort = await cf.Run(con => shareRepo.GetEffortBetweenCreatedAsync(con, pool.Id, poolInstance.ShareMultiplier, startTime, clock.Now)); + response.Pool.PoolEffort = poolEffort.Value; + } var from = clock.Now.AddHours(-topMinersRange); diff --git a/src/Miningcore/Api/Middlewares/IPAccessWhitelistMiddleware.cs b/src/Miningcore/Api/Middlewares/IPAccessWhitelistMiddleware.cs index 45181fa8d..2f4301034 100644 --- a/src/Miningcore/Api/Middlewares/IPAccessWhitelistMiddleware.cs +++ b/src/Miningcore/Api/Middlewares/IPAccessWhitelistMiddleware.cs @@ -1,32 +1,35 @@ using Microsoft.AspNetCore.Http; using NLog; using System.Net; +using Miningcore.Configuration; +using Miningcore.Extensions; namespace Miningcore.Api.Middlewares; public class IPAccessWhitelistMiddleware { - public IPAccessWhitelistMiddleware(RequestDelegate next, string[] locations, IPAddress[] whitelist) + public IPAccessWhitelistMiddleware(RequestDelegate next, string[] locations, IPAddress[] whitelist, bool gpdrCompliantLogging) { this.whitelist = whitelist; this.next = next; this.locations = locations; + this.gpdrCompliantLogging = gpdrCompliantLogging; } private readonly RequestDelegate next; private readonly ILogger logger = LogManager.GetCurrentClassLogger(); private readonly IPAddress[] whitelist; private readonly string[] locations; + private readonly bool gpdrCompliantLogging; public async Task Invoke(HttpContext context) { if(locations.Any(x => context.Request.Path.Value.StartsWith(x))) { var remoteAddress = context.Connection.RemoteIpAddress; - if(!whitelist.Any(x => x.Equals(remoteAddress))) { - logger.Info(() => $"Unauthorized request attempt to {context.Request.Path.Value} from {remoteAddress}"); + logger.Info(() => $"Unauthorized request attempt to {context.Request.Path.Value} from {remoteAddress.CensorOrReturn(gpdrCompliantLogging)}"); context.Response.StatusCode = (int) HttpStatusCode.Forbidden; await context.Response.WriteAsync("You are not in my access list. Good Bye.\n"); diff --git a/src/Miningcore/Api/Responses/GetPoolsResponse.cs b/src/Miningcore/Api/Responses/GetPoolsResponse.cs index b73f53bc0..5d531ef0d 100644 --- a/src/Miningcore/Api/Responses/GetPoolsResponse.cs +++ b/src/Miningcore/Api/Responses/GetPoolsResponse.cs @@ -72,6 +72,7 @@ public partial class PoolInfo public decimal TotalPaid { get; set; } public uint TotalBlocks { get; set; } public DateTime? LastPoolBlockTime { get; set; } + public double PoolEffort { get; set; } } public class GetPoolsResponse diff --git a/src/Miningcore/Blockchain/Bitcoin/BitcoinJob.cs b/src/Miningcore/Blockchain/Bitcoin/BitcoinJob.cs index d204b09f9..38ea3701e 100644 --- a/src/Miningcore/Blockchain/Bitcoin/BitcoinJob.cs +++ b/src/Miningcore/Blockchain/Bitcoin/BitcoinJob.cs @@ -593,7 +593,7 @@ public void Init(BlockTemplate blockTemplate, string jobId, { masterNodeParameters = BlockTemplate.Extra.SafeExtensionDataAs(); - if(coin.Symbol == "RTM") + if((coin.Symbol == "RTM") || (coin.Symbol == "THOON") || (coin.Symbol == "YERB") || (coin.Symbol == "BTRM")) { if(masterNodeParameters.Extra?.ContainsKey("smartnode") == true) { diff --git a/src/Miningcore/Blockchain/Ergo/ErgoClientFactory.cs b/src/Miningcore/Blockchain/Ergo/ErgoClientFactory.cs index a3336c3b6..8fc42692f 100644 --- a/src/Miningcore/Blockchain/Ergo/ErgoClientFactory.cs +++ b/src/Miningcore/Blockchain/Ergo/ErgoClientFactory.cs @@ -24,7 +24,7 @@ public static ErgoClient CreateClient(PoolConfig poolConfig, ClusterConfig clust var result = new ErgoClient(baseUrl.ToString(), new HttpClient(new HttpClientHandler { - AutomaticDecompression = DecompressionMethods.Deflate | DecompressionMethods.GZip, + AutomaticDecompression = DecompressionMethods.All, ServerCertificateCustomValidationCallback = (message, cert, chain, errors) => true, })); diff --git a/src/Miningcore/Blockchain/Ethereum/Configuration/EthereumPoolPaymentProcessingConfigExtra.cs b/src/Miningcore/Blockchain/Ethereum/Configuration/EthereumPoolPaymentProcessingConfigExtra.cs index fea560afd..977eb5895 100644 --- a/src/Miningcore/Blockchain/Ethereum/Configuration/EthereumPoolPaymentProcessingConfigExtra.cs +++ b/src/Miningcore/Blockchain/Ethereum/Configuration/EthereumPoolPaymentProcessingConfigExtra.cs @@ -21,4 +21,9 @@ public class EthereumPoolPaymentProcessingConfigExtra /// maximum amount you’re willing to pay /// public ulong MaxFeePerGas { get; set; } + + /// + /// Search offset to start looking for uncles + /// + public uint BlockSearchOffset { get; set; } = 50; } diff --git a/src/Miningcore/Blockchain/Ethereum/DaemonRequests/SendTransactionRequest.cs b/src/Miningcore/Blockchain/Ethereum/DaemonRequests/SendTransactionRequest.cs index 4ecf42fb8..4494b9440 100644 --- a/src/Miningcore/Blockchain/Ethereum/DaemonRequests/SendTransactionRequest.cs +++ b/src/Miningcore/Blockchain/Ethereum/DaemonRequests/SendTransactionRequest.cs @@ -53,3 +53,43 @@ public class SendTransactionRequest [JsonConverter(typeof(HexToIntegralTypeJsonConverter))] public ulong MaxFeePerGas { get; set; } } + + +public class SendTransactionRequestPink +{ + /// + /// The address the transaction is send from. + /// + public string From { get; set; } + + /// + /// The address the transaction is directed to. + /// + public string To { get; set; } + + /// + /// (Optional) (default: 90000) Integer of the gas provided for the transaction execution. It will return unused gas + /// + [JsonConverter(typeof(HexToIntegralTypeJsonConverter))] + [JsonProperty(NullValueHandling = NullValueHandling.Ignore)] + public ulong? Gas { get; set; } + + /// + /// (Optional) Integer of the gas price used for each paid gas + /// + [JsonConverter(typeof(HexToIntegralTypeJsonConverter))] + [JsonProperty(NullValueHandling = NullValueHandling.Ignore)] + public ulong? GasPrice { get; set; } + + /// + /// (Optional) Integer of the value send with this transaction + /// + [JsonConverter(typeof(HexToIntegralTypeJsonConverter))] + public string Value { get; set; } + + /// + /// The compiled code of a contract OR the hash of the invoked method signature and encoded parameters. + /// + [JsonProperty(NullValueHandling = NullValueHandling.Ignore)] + public string Data { get; set; } +} \ No newline at end of file diff --git a/src/Miningcore/Blockchain/Ethereum/EthereumConstants.cs b/src/Miningcore/Blockchain/Ethereum/EthereumConstants.cs index b94e1bc29..79794f11e 100644 --- a/src/Miningcore/Blockchain/Ethereum/EthereumConstants.cs +++ b/src/Miningcore/Blockchain/Ethereum/EthereumConstants.cs @@ -17,6 +17,7 @@ public class EthereumConstants public const string EthereumStratumVersion = "EthereumStratum/1.0.0"; public const decimal StaticTransactionFeeReserve = 0.0025m; // in ETH public const string BlockTypeUncle = "uncle"; + public const string BlockTypeBlock = "block"; #if !DEBUG public const int MinPayoutPeerCount = 1; @@ -46,12 +47,24 @@ public class CallistoConstants public const decimal TreasuryPercent = 50m; } +public class EthOneConstants +{ + public const decimal BaseRewardInitial = 2.0m; +} + +public class PinkConstants +{ + public const decimal BaseRewardInitial = 1.0m; +} + public enum EthereumNetworkType { Main = 1, Ropsten = 3, Callisto = 820, MainPow = 10001, + EtherOne = 4949, + Pink = 10100, Unknown = -1, } @@ -62,7 +75,9 @@ public enum GethChainType Ropsten, Callisto, MainPow = 10001, - + EtherOne = 4949, + Pink = 10100, + Unknown = -1, } diff --git a/src/Miningcore/Blockchain/Ethereum/EthereumPayoutHandler.cs b/src/Miningcore/Blockchain/Ethereum/EthereumPayoutHandler.cs index 9f8c18992..159a30873 100644 --- a/src/Miningcore/Blockchain/Ethereum/EthereumPayoutHandler.cs +++ b/src/Miningcore/Blockchain/Ethereum/EthereumPayoutHandler.cs @@ -50,7 +50,6 @@ public EthereumPayoutHandler( private RpcClient rpcClient; private EthereumNetworkType networkType; private GethChainType chainType; - private const int BlockSearchOffset = 50; private EthereumPoolConfigExtra extraPoolConfig; private EthereumPoolPaymentProcessingConfigExtra extraConfig; @@ -125,7 +124,7 @@ public async Task ClassifyBlocksAsync(IMiningPool pool, Block[] blocks, var gasUsed = blockHashResponse.Response.GasUsed; var burnedFee = (decimal) 0; - if(extraPoolConfig?.ChainTypeOverride == "Ethereum") + if(extraPoolConfig?.ChainTypeOverride == "Ethereum" || extraPoolConfig?.ChainTypeOverride == "Main" || extraPoolConfig?.ChainTypeOverride == "MainPow" || extraPoolConfig?.ChainTypeOverride == "EtherOne" || extraPoolConfig?.ChainTypeOverride == "Pink") burnedFee = (baseGas * gasUsed / EthereumConstants.Wei); block.Hash = blockHash; @@ -133,7 +132,7 @@ public async Task ClassifyBlocksAsync(IMiningPool pool, Block[] blocks, block.ConfirmationProgress = 1; block.BlockHeight = (ulong) blockInfo.Height; block.Reward = GetBaseBlockReward(chainType, block.BlockHeight); // base reward - block.Type = "block"; + block.Type = EthereumConstants.BlockTypeBlock; if(extraConfig?.KeepUncles == false) block.Reward += blockInfo.Uncles.Length * (block.Reward / 32); // uncle rewards @@ -150,8 +149,8 @@ public async Task ClassifyBlocksAsync(IMiningPool pool, Block[] blocks, } // search for a block containing our block as an uncle by checking N blocks in either direction - var heightMin = block.BlockHeight - BlockSearchOffset; - var heightMax = Math.Min(block.BlockHeight + BlockSearchOffset, latestBlockHeight); + var heightMin = block.BlockHeight - extraConfig.BlockSearchOffset; + var heightMax = Math.Min(block.BlockHeight + extraConfig.BlockSearchOffset, latestBlockHeight); var range = new List(); for(var k = heightMin; k < heightMax; k++) @@ -180,30 +179,44 @@ public async Task ClassifyBlocksAsync(IMiningPool pool, Block[] blocks, .Select(x => x.Response.ToObject()) .FirstOrDefault(x => string.Equals(x.Miner, poolConfig.Address, StringComparison.OrdinalIgnoreCase)); - if(uncle != null) + if(uncle != null) + { + // mature? + if(block.Reward == 0) + block.Reward = GetUncleReward(chainType, uncle.Height.Value, blockInfo2.Height.Value); + + if(latestBlockHeight - uncle.Height.Value >= EthereumConstants.MinConfimations) { - // mature? - if(block.Reward == 0) - block.Reward = GetUncleReward(chainType, uncle.Height.Value, blockInfo2.Height.Value); - if(latestBlockHeight - uncle.Height.Value >= EthereumConstants.MinConfimations) + // make sure there is no other uncle from that block stored in the DB already. + // when there is more than 1 uncle mined by us within the BlockSearchOffset + // range, the pool automatically assumes the first found block is the correct one. + // This is not always the case, so we need to check the DB for any other + // uncles from that block and continue searching if there any others. + // Otherwise the payouter will crash and no further blocks will be unlocked. + var duplBlock = await cf.Run(con => blockRepo.GetBlockByHeightAsync(con, poolConfig.Id, Convert.ToInt64(uncle.Height.Value))); + if(duplBlock != null && duplBlock.Type == EthereumConstants.BlockTypeUncle) { - block.Reward = GetUncleReward(chainType, uncle.Height.Value, blockInfo2.Height.Value); - block.Status = BlockStatus.Confirmed; - block.ConfirmationProgress = 1; - block.BlockHeight = uncle.Height.Value; - block.Type = EthereumConstants.BlockTypeUncle; - - logger.Info(() => $"[{LogCategory}] Unlocked uncle for block {blockInfo2.Height.Value} at height {uncle.Height.Value} worth {FormatAmount(block.Reward)}"); - - messageBus.NotifyBlockUnlocked(poolConfig.Id, block, coin); + logger.Info(() => $"[{LogCategory}] Found another uncle from block {uncle.Height.Value} in the DB. Continuing search for uncle."); + continue; } - else - logger.Info(() => $"[{LogCategory}] Got immature matching uncle for block {blockInfo2.Height.Value}. Will try again."); + block.Reward = GetUncleReward(chainType, uncle.Height.Value, blockInfo2.Height.Value); + block.Status = BlockStatus.Confirmed; + block.ConfirmationProgress = 1; + block.BlockHeight = uncle.Height.Value; + block.Type = EthereumConstants.BlockTypeUncle; - break; + logger.Info(() => $"[{LogCategory}] Unlocked uncle for block {blockInfo2.Height.Value} at height {uncle.Height.Value} worth {FormatAmount(block.Reward)}"); + + messageBus.NotifyBlockUnlocked(poolConfig.Id, block, coin); } + + else + logger.Info(() => $"[{LogCategory}] Got immature matching uncle for block {blockInfo2.Height.Value}. Will try again."); + + break; + } } } @@ -237,7 +250,7 @@ public async Task PayoutAsync(IMiningPool pool, Balance[] balances, Cancellation // ensure we have peers var infoResponse = await rpcClient.ExecuteAsync(logger, EC.GetPeerCount, ct); - if((networkType == EthereumNetworkType.Main || networkType == EthereumNetworkType.MainPow) && + if((networkType == EthereumNetworkType.Main || networkType == EthereumNetworkType.MainPow || extraPoolConfig?.ChainTypeOverride == "EtherOne" || extraPoolConfig?.ChainTypeOverride == "Pink") && (infoResponse.Error != null || string.IsNullOrEmpty(infoResponse.Response) || infoResponse.Response.IntegralFromHex() < EthereumConstants.MinPayoutPeerCount)) { @@ -315,6 +328,12 @@ internal static decimal GetBaseBlockReward(GethChainType chainType, ulong height return EthereumConstants.HomesteadBlockReward; + case GethChainType.EtherOne: + return EthOneConstants.BaseRewardInitial; + + case GethChainType.Pink: + return PinkConstants.BaseRewardInitial; + case GethChainType.Callisto: return CallistoConstants.BaseRewardInitial * (CallistoConstants.TreasuryPercent / 100); @@ -393,7 +412,7 @@ private async Task PayoutAsync(Balance balance, CancellationToken ct) Value = amount.ToString("x").TrimStart('0'), }; - if(extraPoolConfig?.ChainTypeOverride == "Ethereum") + if(extraPoolConfig?.ChainTypeOverride == "Ethereum" || extraPoolConfig?.ChainTypeOverride == "Main" || extraPoolConfig?.ChainTypeOverride == "MainPow" || extraPoolConfig?.ChainTypeOverride == "EtherOne" ) { var maxPriorityFeePerGas = await rpcClient.ExecuteAsync(logger, EC.MaxPriorityFeePerGas, ct); request.Gas = extraConfig.Gas; @@ -401,7 +420,21 @@ private async Task PayoutAsync(Balance balance, CancellationToken ct) request.MaxFeePerGas = extraConfig.MaxFeePerGas; } - var response = await rpcClient.ExecuteAsync(logger, EC.SendTx, ct, new[] { request }); + RpcResponse response; + if(extraPoolConfig?.ChainTypeOverride == "Pink") + { + var requestPink = new SendTransactionRequestPink + { + From = poolConfig.Address, + To = balance.Address, + Value = amount.ToString("x").TrimStart('0'), + Gas = extraConfig.Gas + }; + response = await rpcClient.ExecuteAsync(logger, EC.SendTx, ct, new[] { requestPink }); + } + else { + response = await rpcClient.ExecuteAsync(logger, EC.SendTx, ct, new[] { request }); + } if(response.Error != null) throw new Exception($"{EC.SendTx} returned error: {response.Error.Message} code {response.Error.Code}"); diff --git a/src/Miningcore/Configuration/ClusterConfig.cs b/src/Miningcore/Configuration/ClusterConfig.cs index 459a06746..d430976d1 100644 --- a/src/Miningcore/Configuration/ClusterConfig.cs +++ b/src/Miningcore/Configuration/ClusterConfig.cs @@ -531,6 +531,7 @@ public partial class ClusterLoggingConfig public string ApiLogFile { get; set; } public bool PerPoolLogFile { get; set; } public string LogBaseDirectory { get; set; } + public bool GPDRCompliant { get; set; } } public partial class NetworkEndpointConfig diff --git a/src/Miningcore/Crypto/Hashing/Algorithms/Sha256DT.cs b/src/Miningcore/Crypto/Hashing/Algorithms/Sha256DT.cs new file mode 100644 index 000000000..be4824fe3 --- /dev/null +++ b/src/Miningcore/Crypto/Hashing/Algorithms/Sha256DT.cs @@ -0,0 +1,21 @@ +using Miningcore.Contracts; +using Miningcore.Native; + +namespace Miningcore.Crypto.Hashing.Algorithms; + +[Identifier("sha256dt")] +public unsafe class Sha256DT : IHashAlgorithm +{ + public void Digest(ReadOnlySpan data, Span result, params object[] extra) + { + Contract.Requires(result.Length >= 32); + + fixed (byte* input = data) + { + fixed (byte* output = result) + { + Multihash.sha256dt(input, output); + } + } + } +} diff --git a/src/Miningcore/Crypto/Hashing/Algorithms/Sha512256D.cs b/src/Miningcore/Crypto/Hashing/Algorithms/Sha512256D.cs new file mode 100644 index 000000000..678c21803 --- /dev/null +++ b/src/Miningcore/Crypto/Hashing/Algorithms/Sha512256D.cs @@ -0,0 +1,22 @@ +using Miningcore.Contracts; +using Miningcore.Native; + +namespace Miningcore.Crypto.Hashing.Algorithms; + +[Identifier("sha512/256d")] +public unsafe class Sha512256D : IHashAlgorithm +{ + public void Digest(ReadOnlySpan data, Span result, params object[] extra) + { + Contract.Requires(result.Length >= 32); + + fixed (byte* input = data) + { + fixed (byte* output = result) + { + Multihash.sha512_256(input, output, (uint) data.Length); + Multihash.sha512_256(output, output, 32); + } + } + } +} diff --git a/src/Miningcore/Extensions/IpAddressExtensions.cs b/src/Miningcore/Extensions/IpAddressExtensions.cs index 95f303130..c89e18c33 100644 --- a/src/Miningcore/Extensions/IpAddressExtensions.cs +++ b/src/Miningcore/Extensions/IpAddressExtensions.cs @@ -24,4 +24,35 @@ public static bool IsEqual(this IPAddress address, IPAddress other) return false; } + + public static IPAddress CensorOrReturn(this IPAddress address, bool censor) + { + Contract.RequiresNonNull(address); + + if(!censor) + return address; + + if(address.IsIPv4MappedToIPv6) + address = address.MapToIPv4(); + + var ipBytes = address.GetAddressBytes(); + + if(ipBytes.Length == 4) + { + // IPv4 + // keep the first and last part + ipBytes[2] = 0; + ipBytes[3] = 0; + } + + else if(ipBytes.Length == 16) + { + // IPv6 + // keep the first 2 and last 2 parts + for(var i = 4; i < 12; i++) + ipBytes[i] = 0; + } + + return new IPAddress(ipBytes); + } } diff --git a/src/Miningcore/Miningcore.csproj b/src/Miningcore/Miningcore.csproj index 8cbdf18b5..4e1d428a2 100644 --- a/src/Miningcore/Miningcore.csproj +++ b/src/Miningcore/Miningcore.csproj @@ -45,42 +45,42 @@ - + all runtime; build; native; contentfiles; analyzers; buildtransitive - - - - + + + + all runtime; build; native; contentfiles; analyzers; buildtransitive - - + + - + - - - + + + - - + + - - + + - - - + + + diff --git a/src/Miningcore/Native/Multihash.cs b/src/Miningcore/Native/Multihash.cs index 2febb4407..8ebb2294d 100644 --- a/src/Miningcore/Native/Multihash.cs +++ b/src/Miningcore/Native/Multihash.cs @@ -144,4 +144,10 @@ public static unsafe class Multihash [DllImport("libmultihash", EntryPoint = "equihash_verify_96_5_export", CallingConvention = CallingConvention.Cdecl)] public static extern bool equihash_verify_96_5(byte* header, int headerLength, byte* solution, int solutionLength, string personalization); + + [DllImport("libmultihash", EntryPoint = "sha512_256_export", CallingConvention = CallingConvention.Cdecl)] + public static extern void sha512_256(byte* input, void* output, uint inputLength); + + [DllImport("libmultihash", EntryPoint = "sha256dt_export", CallingConvention = CallingConvention.Cdecl)] + public static extern void sha256dt(byte* input, void* output); } diff --git a/src/Miningcore/Payments/PayoutManager.cs b/src/Miningcore/Payments/PayoutManager.cs index 727ba6ed0..95288c7c9 100644 --- a/src/Miningcore/Payments/PayoutManager.cs +++ b/src/Miningcore/Payments/PayoutManager.cs @@ -62,11 +62,11 @@ public PayoutManager(IComponentContext ctx, private readonly ClusterConfig clusterConfig; private readonly CompositeDisposable disposables = new(); - #if !DEBUG +#if !DEBUG private static readonly TimeSpan initialRunDelay = TimeSpan.FromMinutes(1); - #else +#else private static readonly TimeSpan initialRunDelay = TimeSpan.FromSeconds(15); - #endif +#endif private void AttachPool(IMiningPool pool) { diff --git a/src/Miningcore/Persistence/Postgres/Repositories/BlockRepository.cs b/src/Miningcore/Persistence/Postgres/Repositories/BlockRepository.cs index a23835c2a..beba700a1 100644 --- a/src/Miningcore/Persistence/Postgres/Repositories/BlockRepository.cs +++ b/src/Miningcore/Persistence/Postgres/Repositories/BlockRepository.cs @@ -51,12 +51,12 @@ public async Task PageBlocksAsync(IDbConnection con, string poolId, Blo ORDER BY created DESC OFFSET @offset FETCH NEXT @pageSize ROWS ONLY"; return (await con.QueryAsync(new CommandDefinition(query, new - { - poolId, - status = status.Select(x => x.ToString().ToLower()).ToArray(), - offset = page * pageSize, - pageSize - }, cancellationToken: ct))) + { + poolId, + status = status.Select(x => x.ToString().ToLower()).ToArray(), + offset = page * pageSize, + pageSize + }, cancellationToken: ct))) .Select(mapper.Map) .ToArray(); } @@ -67,11 +67,11 @@ public async Task PageBlocksAsync(IDbConnection con, BlockStatus[] stat ORDER BY created DESC OFFSET @offset FETCH NEXT @pageSize ROWS ONLY"; return (await con.QueryAsync(new CommandDefinition(query, new - { - status = status.Select(x => x.ToString().ToLower()).ToArray(), - offset = page * pageSize, - pageSize - }, cancellationToken: ct))) + { + status = status.Select(x => x.ToString().ToLower()).ToArray(), + offset = page * pageSize, + pageSize + }, cancellationToken: ct))) .Select(mapper.Map) .ToArray(); } @@ -91,11 +91,11 @@ public async Task GetBlockBeforeAsync(IDbConnection con, string poolId, B ORDER BY created DESC FETCH NEXT 1 ROWS ONLY"; return (await con.QueryAsync(query, new - { - poolId, - before, - status = status.Select(x => x.ToString().ToLower()).ToArray() - })) + { + poolId, + before, + status = status.Select(x => x.ToString().ToLower()).ToArray() + })) .Select(mapper.Map) .FirstOrDefault(); } @@ -113,4 +113,13 @@ public Task GetPoolBlockCountAsync(IDbConnection con, string poolId, Cance return con.ExecuteScalarAsync(query, new { poolId }); } + + public async Task GetBlockByHeightAsync(IDbConnection con, string poolId, long height) + { + const string query = @"SELECT * FROM blocks WHERE poolid = @poolId AND blockheight = @height"; + + var entity = await con.QuerySingleOrDefaultAsync(new CommandDefinition(query, new { poolId, height })); + + return entity == null ? null : mapper.Map(entity); + } } diff --git a/src/Miningcore/Persistence/Postgres/Repositories/ShareRepository.cs b/src/Miningcore/Persistence/Postgres/Repositories/ShareRepository.cs index 76556a219..f06d6ed7f 100644 --- a/src/Miningcore/Persistence/Postgres/Repositories/ShareRepository.cs +++ b/src/Miningcore/Persistence/Postgres/Repositories/ShareRepository.cs @@ -75,6 +75,13 @@ public Task CountSharesByMinerAsync(IDbConnection con, IDbTransaction tx, return con.QuerySingleAsync(new CommandDefinition(query, new { poolId, miner}, tx, cancellationToken: ct)); } + public Task GetEffortBetweenCreatedAsync(IDbConnection con, string poolId, double shareConst, DateTime start, DateTime end) + { + const string query = "SELECT SUM((difficulty * @shareConst) / networkdifficulty) FROM shares WHERE poolid = @poolId AND created > @start AND created < @end"; + + return con.QuerySingleAsync(query, new { poolId, shareConst, start, end }); + } + public async Task DeleteSharesByMinerAsync(IDbConnection con, IDbTransaction tx, string poolId, string miner, CancellationToken ct) { const string query = "DELETE FROM shares WHERE poolid = @poolId AND miner = @miner"; diff --git a/src/Miningcore/Persistence/Repositories/IBlockRepository.cs b/src/Miningcore/Persistence/Repositories/IBlockRepository.cs index 683d2b5eb..8cf1959da 100644 --- a/src/Miningcore/Persistence/Repositories/IBlockRepository.cs +++ b/src/Miningcore/Persistence/Repositories/IBlockRepository.cs @@ -15,4 +15,5 @@ public interface IBlockRepository Task GetBlockBeforeAsync(IDbConnection con, string poolId, BlockStatus[] status, DateTime before); Task GetPoolBlockCountAsync(IDbConnection con, string poolId, CancellationToken ct); Task GetLastPoolBlockTimeAsync(IDbConnection con, string poolId); + Task GetBlockByHeightAsync(IDbConnection con, string poolId, long height); } diff --git a/src/Miningcore/Persistence/Repositories/IShareRepository.cs b/src/Miningcore/Persistence/Repositories/IShareRepository.cs index 4be1fb976..e2357641c 100644 --- a/src/Miningcore/Persistence/Repositories/IShareRepository.cs +++ b/src/Miningcore/Persistence/Repositories/IShareRepository.cs @@ -14,6 +14,7 @@ public interface IShareRepository Task DeleteSharesByMinerAsync(IDbConnection con, IDbTransaction tx, string poolId, string miner, CancellationToken ct); Task GetAccumulatedShareDifficultyBetweenAsync(IDbConnection con, string poolId, DateTime start, DateTime end, CancellationToken ct); Task GetEffectiveAccumulatedShareDifficultyBetweenAsync(IDbConnection con, string poolId, DateTime start, DateTime end, CancellationToken ct); + Task GetEffortBetweenCreatedAsync(IDbConnection con, string poolId, double shareConst, DateTime start, DateTime end); Task GetHashAccumulationBetweenAsync(IDbConnection con, string poolId, DateTime start, DateTime end, CancellationToken ct); Task GetRecentyUsedIpAddressesAsync(IDbConnection con, IDbTransaction tx, string poolId, string miner, CancellationToken ct); diff --git a/src/Miningcore/Program.cs b/src/Miningcore/Program.cs index cb5581159..42bc7761d 100644 --- a/src/Miningcore/Program.cs +++ b/src/Miningcore/Program.cs @@ -365,12 +365,15 @@ protected override async Task ExecuteAsync(CancellationToken ct) var coinTemplates = LoadCoinTemplates(); logger.Info($"{coinTemplates.Keys.Count} coins loaded from '{string.Join(", ", clusterConfig.CoinTemplates)}'"); - await Guard(()=> Task.WhenAll(clusterConfig.Pools + var tasks = clusterConfig.Pools .Where(config => config.Enabled) - .Select(config => RunPool(config, coinTemplates, ct))), - ex => + .Select(config => RunPool(config, coinTemplates, ct)); + + await Guard(()=> Task.WhenAll(tasks), ex => + { + switch(ex) { - if(ex is PoolStartupException pse) + case PoolStartupException pse: { var _logger = pse.PoolId != null ? LogUtil.GetPoolScopedLogger(GetType(), pse.PoolId) : logger; _logger.Error(() => $"{pse.Message}"); @@ -378,11 +381,13 @@ await Guard(()=> Task.WhenAll(clusterConfig.Pools logger.Error(() => "Cluster cannot start. Good Bye!"); hal.StopApplication(); + break; } - else + default: throw ex; - }); + } + }); } private async Task RunPool(PoolConfig poolConfig, Dictionary coinTemplates, CancellationToken ct) @@ -618,12 +623,12 @@ private static void Logo() "); Console.WriteLine(" https://github.com/oliverw/miningcore\n"); Console.WriteLine(" Donate to one of these addresses to support the project:\n"); - Console.WriteLine(" BTC - 17QnVor1B6oK1rWnVVBrdX9gFzVkZZbhDm"); - Console.WriteLine(" LTC - LTK6CWastkmBzGxgQhTTtCUjkjDA14kxzC"); + Console.WriteLine(" ETH - miningcore.eth (ENS Address)"); + Console.WriteLine(" BTC - miningcore.eth (ENS Address)"); + Console.WriteLine(" LTC - miningcore.eth (ENS Address)"); Console.WriteLine(" DASH - XqpBAV9QCaoLnz42uF5frSSfrJTrqHoxjp"); Console.WriteLine(" ZEC - t1YHZHz2DGVMJiggD2P4fBQ2TAPgtLSUwZ7"); Console.WriteLine(" ZCL - t1MFU1vD3YKgsK6Uh8hW7UTY8mKAV2xVqBr"); - Console.WriteLine(" ETH - 0xcb55abBfe361B12323eb952110cE33d5F28BeeE1"); Console.WriteLine(" ETC - 0xF8cCE9CE143C68d3d4A7e6bf47006f21Cfcf93c0"); Console.WriteLine(" XMR - 475YVJbPHPedudkhrcNp1wDcLMTGYusGPF5fqE7XjnragVLPdqbCHBdZg3dF4dN9hXMjjvGbykS6a77dTAQvGrpiQqHp2eH"); Console.WriteLine(); @@ -945,7 +950,7 @@ private static void UseIpWhiteList(IApplicationBuilder app, bool defaultToLoopba logger.Info(() => $"API Access to {string.Join(",", locations)} restricted to {string.Join(",", ipList.Select(x => x.ToString()))}"); - app.UseMiddleware(locations, ipList.ToArray()); + app.UseMiddleware(locations, ipList.ToArray(), clusterConfig.Logging.GPDRCompliant); } } diff --git a/src/Miningcore/Rpc/RpcClient.cs b/src/Miningcore/Rpc/RpcClient.cs index eb053cd5a..057c1fe32 100644 --- a/src/Miningcore/Rpc/RpcClient.cs +++ b/src/Miningcore/Rpc/RpcClient.cs @@ -49,7 +49,7 @@ public RpcClient(DaemonEndpointConfig endPoint, JsonSerializerSettings serialize private static readonly HttpClient httpClient = new(new HttpClientHandler { - AutomaticDecompression = DecompressionMethods.Deflate | DecompressionMethods.GZip, + AutomaticDecompression = DecompressionMethods.All, ServerCertificateCustomValidationCallback = (message, cert, chain, errors) => true, }); diff --git a/src/Miningcore/Stratum/StratumConnection.cs b/src/Miningcore/Stratum/StratumConnection.cs index 368ac81d4..9748d91c1 100644 --- a/src/Miningcore/Stratum/StratumConnection.cs +++ b/src/Miningcore/Stratum/StratumConnection.cs @@ -27,7 +27,7 @@ namespace Miningcore.Stratum; public class StratumConnection { - public StratumConnection(ILogger logger, RecyclableMemoryStreamManager rmsm, IMasterClock clock, string connectionId) + public StratumConnection(ILogger logger, RecyclableMemoryStreamManager rmsm, IMasterClock clock, string connectionId, bool gpdrCompliantLogging) { this.logger = logger; this.rmsm = rmsm; @@ -42,6 +42,7 @@ public StratumConnection(ILogger logger, RecyclableMemoryStreamManager rmsm, IMa this.clock = clock; ConnectionId = connectionId; IsAlive = true; + this.gpdrCompliantLogging = gpdrCompliantLogging; } private readonly ILogger logger; @@ -49,6 +50,7 @@ public StratumConnection(ILogger logger, RecyclableMemoryStreamManager rmsm, IMa private readonly IMasterClock clock; private const int MaxInboundRequestLength = 0x8000; + public static readonly Encoding Encoding = new UTF8Encoding(false); private Stream networkStream; private readonly Pipe receivePipe; @@ -56,6 +58,7 @@ public StratumConnection(ILogger logger, RecyclableMemoryStreamManager rmsm, IMa private WorkerContextBase context; private readonly Subject terminated = new(); private bool expectingProxyHeader; + private bool gpdrCompliantLogging; private static readonly JsonSerializer serializer = new() { @@ -113,11 +116,10 @@ await sslStream.AuthenticateAsServerAsync(new SslServerAuthenticationOptions networkStream = sslStream; - logger.Info(() => $"[{ConnectionId}] {sslStream.SslProtocol.ToString().ToUpper()}-{sslStream.CipherAlgorithm.ToString().ToUpper()} Connection from {RemoteEndpoint.Address}:{RemoteEndpoint.Port} accepted on port {endpoint.IPEndPoint.Port}"); + logger.Info(() => $"[{ConnectionId}] {sslStream.SslProtocol.ToString().ToUpper()}-{sslStream.CipherAlgorithm.ToString().ToUpper()} Connection from {RemoteEndpoint.Address.CensorOrReturn(gpdrCompliantLogging)}:{RemoteEndpoint.Port} accepted on port {endpoint.IPEndPoint.Port}"); } - else - logger.Info(() => $"[{ConnectionId}] Connection from {RemoteEndpoint.Address}:{RemoteEndpoint.Port} accepted on port {endpoint.IPEndPoint.Port}"); + logger.Info(() => $"[{ConnectionId}] Connection from {RemoteEndpoint.Address.CensorOrReturn(gpdrCompliantLogging)}:{RemoteEndpoint.Port} accepted on port {endpoint.IPEndPoint.Port}"); // Async I/O loop(s) var tasks = new[] @@ -235,7 +237,7 @@ private async Task FillReceivePipeAsync(CancellationToken ct) if(cb == 0) break; // EOF - logger.Debug(() => $"[{ConnectionId}] [NET] Received data: {StratumConstants.Encoding.GetString(memory.Slice(0, cb).Span)}"); + logger.Debug(() => $"[{ConnectionId}] [NET] Received data: {Encoding.GetString(memory.Slice(0, cb).Span)}"); LastReceive = clock.Now; @@ -264,7 +266,7 @@ private async Task ProcessReceivePipeAsync(CancellationToken ct, if(buffer.Length > MaxInboundRequestLength) throw new InvalidDataException($"Incoming data exceeds maximum of {MaxInboundRequestLength}"); - logger.Debug(() => $"[{ConnectionId}] [PIPE] Received data: {result.Buffer.AsString(StratumConstants.Encoding)}"); + logger.Debug(() => $"[{ConnectionId}] [PIPE] Received data: {result.Buffer.AsString(Encoding)}"); do { @@ -341,12 +343,12 @@ private async Task SendMessage(object msg, CancellationToken ct) await using var stream = rmsm.GetStream(nameof(StratumConnection)) as RecyclableMemoryStream; // serialize - await using (var writer = new StreamWriter(stream!, StratumConstants.Encoding, -1, true)) + await using (var writer = new StreamWriter(stream!, Encoding, -1, true)) { serializer.Serialize(writer, msg); } - logger.Debug(() => $"[{ConnectionId}] Sending: {StratumConstants.Encoding.GetString(stream.GetReadOnlySequence())}"); + logger.Debug(() => $"[{ConnectionId}] Sending: {Encoding.GetString(stream.GetReadOnlySequence())}"); // append newline stream.WriteByte((byte) '\n'); @@ -366,7 +368,7 @@ private async Task ProcessRequestAsync( ReadOnlySequence lineBuffer) { await using var stream = rmsm.GetStream(nameof(StratumConnection), lineBuffer.ToSpan()) as RecyclableMemoryStream; - using var reader = new JsonTextReader(new StreamReader(stream!, StratumConstants.Encoding)); + using var reader = new JsonTextReader(new StreamReader(stream!, Encoding)); var request = serializer.Deserialize(reader); @@ -383,7 +385,7 @@ private bool ProcessProxyHeader(ReadOnlySequence seq, TcpProxyProtocolConf { expectingProxyHeader = false; - var line = seq.AsString(StratumConstants.Encoding); + var line = seq.AsString(Encoding); var peerAddress = RemoteEndpoint.Address; if(line.StartsWith("PROXY ")) @@ -403,7 +405,7 @@ private bool ProcessProxyHeader(ReadOnlySequence seq, TcpProxyProtocolConf // Update client RemoteEndpoint = new IPEndPoint(IPAddress.Parse(remoteAddress), int.Parse(remotePort)); - logger.Info(() => $"Real-IP via Proxy-Protocol: {RemoteEndpoint.Address}"); + logger.Info(() => $"Real-IP via Proxy-Protocol: {RemoteEndpoint.Address.CensorOrReturn(gpdrCompliantLogging)}"); } else diff --git a/src/Miningcore/Stratum/StratumConstants.cs b/src/Miningcore/Stratum/StratumConstants.cs deleted file mode 100644 index aaf35b3d2..000000000 --- a/src/Miningcore/Stratum/StratumConstants.cs +++ /dev/null @@ -1,8 +0,0 @@ -using System.Text; - -namespace Miningcore.Stratum; - -public class StratumConstants -{ - public static readonly Encoding Encoding = new UTF8Encoding(false); -} diff --git a/src/Miningcore/Stratum/StratumServer.cs b/src/Miningcore/Stratum/StratumServer.cs index 7d35a6439..14b690957 100644 --- a/src/Miningcore/Stratum/StratumServer.cs +++ b/src/Miningcore/Stratum/StratumServer.cs @@ -154,9 +154,9 @@ private void AcceptConnection(Socket socket, StratumEndpoint port, X509Certifica return; // init connection - var connection = new StratumConnection(logger, rmsm, clock, CorrelationIdGenerator.GetNextId()); + var connection = new StratumConnection(logger, rmsm, clock, CorrelationIdGenerator.GetNextId(), clusterConfig.Logging.GPDRCompliant); - logger.Info(() => $"[{connection.ConnectionId}] Accepting connection from {remoteEndpoint.Address}:{remoteEndpoint.Port} ..."); + logger.Info(() => $"[{connection.ConnectionId}] Accepting connection from {remoteEndpoint.Address.CensorOrReturn(clusterConfig.Logging.GPDRCompliant)}:{remoteEndpoint.Port} ..."); RegisterConnection(connection); OnConnect(connection, port.IPEndPoint); diff --git a/src/Miningcore/coins.json b/src/Miningcore/coins.json index 3d5148099..fa4a37586 100644 --- a/src/Miningcore/coins.json +++ b/src/Miningcore/coins.json @@ -12,15 +12,23 @@ "hash": "sha256d" }, "headerHasher": { - "hash": "x16rv2" + "hash": "x16r-v2" }, "blockHasher": { "hash": "reverse", - "args": [ { "hash": "x16rv2" } ] + "args": [ + { + "hash": "x16r-v2" + } + ] }, "posBlockHasher": { "hash": "reverse", - "args": [ { "hash": "x16rv2" } ] + "args": [ + { + "hash": "x16r-v2" + } + ] }, "hasMasterNodes": true, "shareMultiplier": 4096, @@ -28,58 +36,6 @@ "explorerTxLink": "https://explorer.fiveg.cash/tx/{0}", "explorerAccountLink": "https://explorer.fiveg.cash/address/{0}" }, - - "actinium": { - "name": "Actinium", - "symbol": "ACM", - "family": "bitcoin", - "website": "https://actinium.org/", - "market": "", - "twitter": "https://twitter.com/ActiniumCrypto", - "telegram": "https://t.me/actiniumcrypto", - "discord": "https://discord.gg/cC5JGSv", - "coinbaseHasher": { - "hash": "sha256d" - }, - "headerHasher": { - "hash": "lyra2z" - }, - "blockHasher": { - "hash": "reverse", - "args": [ { "hash": "lyra2z" } ] - }, - "shareMultiplier": 4096, - "explorerBlockLink": "https://explorer.actinium.org/block/$hash$", - "explorerTxLink": "https://explorer.actinium.org/tx/{0}", - "explorerAccountLink": "https://explorer.actinium.org/address/{0}" - }, - - "alpscoin": { - "name": "Alpenstars", - "symbol": "ALPS", - "family": "bitcoin", - "website": "https://axerunners.com/", - "market": "", - "twitter": "https://twitter.com/search?q=$axe", - "telegram": "https://t.me/axerunners", - "discord": "https://discordapp.com/invite/BqhteaU", - "coinbaseHasher": { - "hash": "sha256d" - }, - "headerHasher": { - "hash": "lyra2z" - }, - "blockHasher": { - "hash": "reverse", - "args": [ { "hash": "lyra2z" } ] - }, - "hasMasterNodes": true, - "shareMultiplier": 4096, - "explorerBlockLink": "http://blockexplorer.alps.network/block/$hash$", - "explorerTxLink": "http://blockexplorer.alps.network/tx/{0}", - "explorerAccountLink": "http://blockexplorer.alps.network/address/{0}" - }, - "auroracoin-sha256": { "name": "Auroracoin Sha256", "canonicalName": "Auroracoin", @@ -98,14 +54,19 @@ }, "blockHasher": { "hash": "reverse", - "args": [ { "hash": "sha256d" } ] + "args": [ + { + "hash": "sha256d" + } + ] }, - "blockTemplateRpcExtraParams": [ "sha256d" ], + "blockTemplateRpcExtraParams": [ + "sha256d" + ], "explorerBlockLink": "https://chainz.cryptoid.info/aur/block.dws?$height$.htm", "explorerTxLink": "https://chainz.cryptoid.info/aur/tx.dws?{0}.htm", "explorerAccountLink": "https://chainz.cryptoid.info/aur/address.dws?{0}.htm" }, - "auroracoin-scrypt": { "name": "Auroracoin Scrypt", "canonicalName": "Auroracoin", @@ -121,19 +82,27 @@ }, "headerHasher": { "hash": "scrypt", - "args": [ 1024, 1 ] + "args": [ + 1024, + 1 + ] }, "blockHasher": { "hash": "reverse", - "args": [ { "hash": "sha256d" } ] + "args": [ + { + "hash": "sha256d" + } + ] }, - "blockTemplateRpcExtraParams": [ "scrypt" ], + "blockTemplateRpcExtraParams": [ + "scrypt" + ], "shareMultiplier": 65536, "explorerBlockLink": "https://chainz.cryptoid.info/aur/block.dws?$height$.htm", "explorerTxLink": "https://chainz.cryptoid.info/aur/tx.dws?{0}.htm", "explorerAccountLink": "https://chainz.cryptoid.info/aur/address.dws?{0}.htm" }, - "auroracoin-skein": { "name": "Auroracoin Skein", "canonicalName": "Auroracoin", @@ -152,14 +121,19 @@ }, "blockHasher": { "hash": "reverse", - "args": [ { "hash": "sha256d" } ] + "args": [ + { + "hash": "sha256d" + } + ] }, - "blockTemplateRpcExtraParams": [ "skein" ], + "blockTemplateRpcExtraParams": [ + "skein" + ], "explorerBlockLink": "https://chainz.cryptoid.info/aur/block.dws?$height$.htm", "explorerTxLink": "https://chainz.cryptoid.info/aur/tx.dws?{0}.htm", "explorerAccountLink": "https://chainz.cryptoid.info/aur/address.dws?{0}.htm" }, - "auroracoin-qubit": { "name": "Auroracoin Qubit", "canonicalName": "Auroracoin", @@ -178,14 +152,19 @@ }, "blockHasher": { "hash": "reverse", - "args": [ { "hash": "sha256d" } ] + "args": [ + { + "hash": "sha256d" + } + ] }, - "blockTemplateRpcExtraParams": [ "qubit" ], + "blockTemplateRpcExtraParams": [ + "qubit" + ], "explorerBlockLink": "https://chainz.cryptoid.info/aur/block.dws?$height$.htm", "explorerTxLink": "https://chainz.cryptoid.info/aur/tx.dws?{0}.htm", "explorerAccountLink": "https://chainz.cryptoid.info/aur/address.dws?{0}.htm" }, - "auroracoin-groestl": { "name": "Auroracoin Groestl", "canonicalName": "Auroracoin", @@ -200,45 +179,24 @@ "hash": "sha256d" }, "headerHasher": { - "hash": "groestlmyriad" + "hash": "groestl-myriad" }, "blockHasher": { "hash": "reverse", - "args": [ { "hash": "sha256d" } ] + "args": [ + { + "hash": "sha256d" + } + ] }, "shareMultiplier": 4096, - "blockTemplateRpcExtraParams": [ "groestl" ], + "blockTemplateRpcExtraParams": [ + "groestl" + ], "explorerBlockLink": "https://chainz.cryptoid.info/aur/block.dws?$height$.htm", "explorerTxLink": "https://chainz.cryptoid.info/aur/tx.dws?{0}.htm", "explorerAccountLink": "https://chainz.cryptoid.info/aur/address.dws?{0}.htm" }, - - "arowanacoin": { - "name": "Arowanacoin", - "canonicalName": "Arowanacoin", - "symbol": "ARWN", - "family": "bitcoin", - "website": "", - "market": "", - "twitter": "", - "telegram": "", - "discord": "", - "coinbaseHasher": { - "hash": "sha256d" - }, - "headerHasher": { - "hash": "yespowerarwn" - }, - "blockHasher": { - "hash": "reverse", - "args": [ { "hash": "sha256d" } ] - }, - "shareMultiplier": 4336808, - "explorerBlockLink": "http://explorer.arowanacoin.org/block/$hash$", - "explorerTxLink": "http://explorer.arowanacoin.org/tx/{0}", - "explorerAccountLink": "http://explorer.arowanacoin.org/address/{0}" - }, - "australia-cash": { "name": "Australia Cash", "canonicalName": "Australia-Cash", @@ -254,18 +212,24 @@ }, "headerHasher": { "hash": "scrypt", - "args": [ 1024, 1 ] + "args": [ + 1024, + 1 + ] }, "blockHasher": { "hash": "reverse", - "args": [ { "hash": "sha256d" } ] + "args": [ + { + "hash": "sha256d" + } + ] }, "shareMultiplier": 65536, "explorerBlockLink": "https://openchains.info/coin/australiacash/block/$height$", "explorerTxLink": "https://openchains.info/coin/australiacash/tx/{0}", "explorerAccountLink": "https://openchains.info/coin/australiacash/address/{0}" }, - "axe": { "name": "Axe", "canonicalName": "Axe", @@ -284,14 +248,17 @@ }, "blockHasher": { "hash": "reverse", - "args": [ { "hash": "x11" } ] + "args": [ + { + "hash": "x11" + } + ] }, "hasMasterNodes": true, "explorerBlockLink": "https://axe-explorer.arcpool.com/block/$hash$", "explorerTxLink": "https://axe-explorer.arcpool.com/tx/{0}", "explorerAccountLink": "https://axe-explorer.arcpool.com/address/{0}" }, - "barrelcrudecoin": { "name": "BarrelCrudeCoin", "canonicalName": "BarrelCrudeCoin", @@ -306,18 +273,24 @@ }, "headerHasher": { "hash": "scrypt", - "args": [ 1024, 1 ] + "args": [ + 1024, + 1 + ] }, "blockHasher": { "hash": "reverse", - "args": [ { "hash": "sha256d" } ] + "args": [ + { + "hash": "sha256d" + } + ] }, "shareMultiplier": 65536, "explorerBlockLink": "http://explorer.kriptokyng.com:3001/block/$height$", "explorerTxLink": "http://explorer.kriptokyng.com:3001/tx/{0}", "explorerAccountLink": "http://explorer.kriptokyng.com:3001/address/{0}" }, - "bitcoin": { "name": "Bitcoin", "canonicalName": "Bitcoin", @@ -336,14 +309,17 @@ }, "blockHasher": { "hash": "reverse", - "args": [ { "hash": "sha256d" } ] + "args": [ + { + "hash": "sha256d" + } + ] }, "coinbaseIgnoreAuxFlags": true, - "explorerBlockLink": "https://btc.tokenview.com/block/$height$", - "explorerTxLink": "https://btc.tokenview.com/tx/{0}", - "explorerAccountLink": "https://btc.tokenview.com/address/{0}" + "explorerBlockLink": "https://www.blockchain.com/btc/block/$hash$", + "explorerTxLink": "https://www.blockchain.com/btc/tx/{0}", + "explorerAccountLink": "https://www.blockchain.com/btc/address/{0}" }, - "bitcoin-cash": { "name": "Bitcoin Cash", "canonicalName": "Bitcoin-Cash", @@ -362,13 +338,16 @@ }, "blockHasher": { "hash": "reverse", - "args": [ { "hash": "sha256d" } ] + "args": [ + { + "hash": "sha256d" + } + ] }, - "explorerBlockLink": "https://bch.tokenview.com/block/$height$", - "explorerTxLink": "https://bch.tokenview.com/tx/{0}", - "explorerAccountLink": "https://bch.tokenview.com/address/{0}" + "explorerBlockLink": "https://bchblockexplorer.com/block/$height$", + "explorerTxLink": "https://bchblockexplorer.com/tx/{0}", + "explorerAccountLink": "https://bchblockexplorer.com/address/{0}" }, - "bitcoin-diamond": { "name": "Bitcoin Diamond", "canonicalName": "Bitcoin-Diamond", @@ -387,13 +366,16 @@ }, "blockHasher": { "hash": "reverse", - "args": [ { "hash": "sha256d" } ] + "args": [ + { + "hash": "sha256d" + } + ] }, "explorerBlockLink": "http://explorer.btcd.io/#/blockInfo?hash=$hash$", "explorerTxLink": "http://explorer.btcd.io/#/TX?TX={0}", "explorerAccountLink": "http://explorer.btcd.io/#/address?address={0}" }, - "bitcoin-sv": { "name": "BitcoinSV", "canonicalName": "Bitcoin-SV", @@ -412,13 +394,16 @@ }, "blockHasher": { "hash": "reverse", - "args": [ { "hash": "sha256d" } ] + "args": [ + { + "hash": "sha256d" + } + ] }, "explorerBlockLink": "https://bsv.tokenview.com/block/$height$", "explorerTxLink": "https://bsv.tokenview.com/tx/{0}", "explorerAccountLink": "https://bsv.tokenview.com/address/{0}" }, - "bitcoinnickel": { "name": "Bitcoinnickel", "canonicalName": "Bitcoinnickel", @@ -437,13 +422,16 @@ }, "blockHasher": { "hash": "reverse", - "args": [ { "hash": "sha256d" } ] + "args": [ + { + "hash": "sha256d" + } + ] }, "explorerBlockLink": "https://explorer.btcnickel.com/block/$hash$", "explorerTxLink": "https://explorer.btcnickel.com/tx/{0}", "explorerAccountLink": "https://explorer.btcnickel.com/address/{0}" }, - "bitflate": { "name": "Bitflate", "canonicalName": "Bitflate", @@ -462,13 +450,16 @@ }, "blockHasher": { "hash": "reverse", - "args": [ { "hash": "sha256d" } ] + "args": [ + { + "hash": "sha256d" + } + ] }, "explorerBlockLink": "https://explorer.bitflate.org/block/$hash$", "explorerTxLink": "https://explorer.bitflate.org/tx/{0}", "explorerAccountLink": "https://explorer.bitflate.org/address/{0}" }, - "bolivarcoin": { "name": "Bolivarcoin", "canonicalName": "Bolivarcoin", @@ -487,14 +478,17 @@ }, "blockHasher": { "hash": "reverse", - "args": [ { "hash": "x11" } ] + "args": [ + { + "hash": "x11" + } + ] }, "hasMasterNodes": true, "explorerBlockLink": "https://chainz.cryptoid.info/boli/block.dws?$height$.htm", "explorerTxLink": "https://chainz.cryptoid.info/boli/tx.dws?{0}.htm", "explorerAccountLink": "https://chainz.cryptoid.info/boli/address.dws?{0}.htm" }, - "browncoin": { "name": "Browncoin", "symbol": "BRWN", @@ -512,7 +506,11 @@ }, "blockHasher": { "hash": "reverse", - "args": [ { "hash": "sha256d" } ] + "args": [ + { + "hash": "sha256d" + } + ] }, "shareMultiplier": 256, "coinbaseMinConfimations": 1001, @@ -520,7 +518,6 @@ "explorerTxLink": "https://openchains.info/coin/browncoin/tx/{0}", "explorerAccountLink": "https://openchains.info/coin/browncoin/address/{0}" }, - "butkoin-sha256": { "name": "ButKoin Sha256", "canonicalName": "ButKoin", @@ -539,16 +536,21 @@ }, "blockHasher": { "hash": "reverse", - "args": [ { "hash": "sha256d" } ] + "args": [ + { + "hash": "sha256d" + } + ] }, - "blockTemplateRpcExtraParams": [ "sha256d" ], + "blockTemplateRpcExtraParams": [ + "sha256d" + ], "hasFounderFee": true, "hasMasterNodes": true, "explorerBlockLink": "https://blocks.butcoin.tech/block/$hash$", "explorerTxLink": "https://blocks.butcoin.tech/tx/{0}", "explorerAccountLink": "https://blocks.butcoin.tech/address/{0}" }, - "butkoin-scrypt": { "name": "ButKoin Scrypt", "canonicalName": "ButKoin", @@ -564,18 +566,28 @@ }, "headerHasher": { "hash": "scrypt", - "args": [ 1024, 1 ] + "args": [ + 1024, + 1 + ] }, "blockHasher": { "hash": "reverse", - "args": [ { "hash": "sha256d" } ] + "args": [ + { + "hash": "sha256d" + } + ] }, "posBlockHasher": { "hash": "reverse", "args": [ { "hash": "scrypt", - "args": [ 1024, 1 ] + "args": [ + 1024, + 1 + ] } ] }, @@ -586,35 +598,6 @@ "explorerTxLink": "https://blocks.butcoin.tech/tx/{0}", "explorerAccountLink": "https://blocks.butcoin.tech/address/{0}" }, - - "butkoin-yespower": { - "name": "ButKoin YesPower", - "canonicalName": "ButKoin", - "symbol": "BUTK", - "family": "bitcoin", - "website": "https://butcoin.tech/", - "market": "", - "twitter": "https://twitter.com/ButKoin", - "telegram": "", - "discord": "https://discord.com/invite/j7T82mKkrw", - "coinbaseHasher": { - "hash": "sha256d" - }, - "headerHasher": { - "hash": "yespowersugar" - }, - "blockHasher": { - "hash": "reverse", - "args": [ { "hash": "sha256d" } ] - }, - "shareMultiplier": 4194304, - "hasFounderFee": true, - "hasMasterNodes": true, - "explorerBlockLink": "https://blocks.butcoin.tech/block/$hash$", - "explorerTxLink": "https://blocks.butcoin.tech/tx/{0}", - "explorerAccountLink": "https://blocks.butcoin.tech/address/{0}" - }, - "cannabiscoin": { "name": "Cannabiscoin", "canonicalName": "Cannabiscoin", @@ -633,64 +616,16 @@ }, "blockHasher": { "hash": "reverse", - "args": [ { "hash": "x11" } ] + "args": [ + { + "hash": "x11" + } + ] }, "explorerBlockLink": "https://cann.tokenview.com/en/block/$height$", "explorerTxLink": "https://cann.tokenview.com/en/tx/{0}", "explorerAccountLink": "https://cann.tokenview.com/en/address/{0}" }, - - "combode": { - "name": "Combode", - "symbol": "CBE", - "family": "bitcoin", - "website": "", - "market": "", - "twitter": "", - "telegram": "", - "discord": "", - "coinbaseHasher": { - "hash": "sha256d" - }, - "headerHasher": { - "hash": "phi5" - }, - "blockHasher": { - "hash": "reverse", - "args": [ { "hash": "phi5" } ] - }, - "hasMasterNodes": true, - "explorerBlockLink": "https://cbe.explorer.alphax.pro/block/$hash$", - "explorerTxLink": "https://cbe.explorer.alphax.pro/tx/{0}", - "explorerAccountLink": "https://cbe.explorer.alphax.pro/address/{0}" - }, - - "cpuchain": { - "name": "CPUchain", - "canonicalName": "CPUchain", - "symbol": "CPU", - "family": "bitcoin", - "website": "", - "market": "", - "twitter": "", - "telegram": "", - "discord": "", - "coinbaseHasher": { - "hash": "sha256d" - }, - "headerHasher": { - "hash": "cpupower" - }, - "blockHasher": { - "hash": "reverse", - "args": [ { "hash": "cpupower" } ] - }, - "shareMultiplier": 65536, - "explorerBlockLink": "https://explorer.cpuchain.org/block/$height$", - "explorerTxLink": "https://explorer.cpuchain.org/{0}", - "explorerAccountLink": "https://explorer.cpuchain.org/{0}" - }, - "danecoin": { "name": "Danecoin", "canonicalName": "Danecoin", @@ -709,13 +644,16 @@ }, "blockHasher": { "hash": "reverse", - "args": [ { "hash": "sha256d" } ] + "args": [ + { + "hash": "sha256d" + } + ] }, "explorerBlockLink": "https://explorer.danecoin.org/block/$hash$", "explorerTxLink": "https://explorer.danecoin.org/tx/{0}", "explorerAccountLink": "https://explorer.danecoin.org/address/{0}" }, - "dash": { "name": "Dash", "canonicalName": "Dash", @@ -734,14 +672,17 @@ }, "blockHasher": { "hash": "reverse", - "args": [ { "hash": "x11" } ] + "args": [ + { + "hash": "x11" + } + ] }, "hasMasterNodes": true, "explorerBlockLink": "https://chainz.cryptoid.info/dash/block.dws?$height$.htm", "explorerTxLink": "https://chainz.cryptoid.info/dash/tx.dws?{0}.htm", "explorerAccountLink": "https://chainz.cryptoid.info/dash/address.dws?{0}.htm" }, - "digibyte-sha256": { "name": "Digibyte Sha256", "canonicalName": "Digibyte", @@ -760,14 +701,19 @@ }, "blockHasher": { "hash": "reverse", - "args": [ { "hash": "sha256d" } ] + "args": [ + { + "hash": "sha256d" + } + ] }, - "blockTemplateRpcExtraParams": [ "sha256d" ], + "blockTemplateRpcExtraParams": [ + "sha256d" + ], "explorerBlockLink": "https://chainz.cryptoid.info/dgb/block.dws?$height$.htm", "explorerTxLink": "https://chainz.cryptoid.info/dgb/tx.dws?{0}.htm", "explorerAccountLink": "https://chainz.cryptoid.info/dgb/address.dws?{0}.htm" }, - "digibyte-scrypt": { "name": "Digibyte Scrypt", "canonicalName": "Digibyte", @@ -783,19 +729,27 @@ }, "headerHasher": { "hash": "scrypt", - "args": [ 1024, 1 ] + "args": [ + 1024, + 1 + ] }, "blockHasher": { "hash": "reverse", - "args": [ { "hash": "sha256d" } ] + "args": [ + { + "hash": "sha256d" + } + ] }, "shareMultiplier": 65536, - "blockTemplateRpcExtraParams": [ "scrypt" ], + "blockTemplateRpcExtraParams": [ + "scrypt" + ], "explorerBlockLink": "https://chainz.cryptoid.info/dgb/block.dws?$height$.htm", "explorerTxLink": "https://chainz.cryptoid.info/dgb/tx.dws?{0}.htm", "explorerAccountLink": "https://chainz.cryptoid.info/dgb/address.dws?{0}.htm" }, - "digibyte-skein": { "name": "Digibyte Skein", "canonicalName": "Digibyte", @@ -814,14 +768,19 @@ }, "blockHasher": { "hash": "reverse", - "args": [ { "hash": "sha256d" } ] + "args": [ + { + "hash": "sha256d" + } + ] }, - "blockTemplateRpcExtraParams": [ "skein" ], + "blockTemplateRpcExtraParams": [ + "skein" + ], "explorerBlockLink": "https://chainz.cryptoid.info/dgb/block.dws?$height$.htm", "explorerTxLink": "https://chainz.cryptoid.info/dgb/tx.dws?{0}.htm", "explorerAccountLink": "https://chainz.cryptoid.info/dgb/address.dws?{0}.htm" }, - "digibyte-qubit": { "name": "Digibyte Qubit", "canonicalName": "Digibyte", @@ -840,14 +799,19 @@ }, "blockHasher": { "hash": "reverse", - "args": [ { "hash": "sha256d" } ] + "args": [ + { + "hash": "sha256d" + } + ] }, - "blockTemplateRpcExtraParams": [ "qubit" ], + "blockTemplateRpcExtraParams": [ + "qubit" + ], "explorerBlockLink": "https://chainz.cryptoid.info/dgb/block.dws?$height$.htm", "explorerTxLink": "https://chainz.cryptoid.info/dgb/tx.dws?{0}.htm", "explorerAccountLink": "https://chainz.cryptoid.info/dgb/address.dws?{0}.htm" }, - "digibyte-groestl": { "name": "Digibyte Groestl", "canonicalName": "Digibyte", @@ -862,19 +826,24 @@ "hash": "sha256s" }, "headerHasher": { - "hash": "groestlmyriad" + "hash": "groestl-myriad" }, "blockHasher": { "hash": "reverse", - "args": [ { "hash": "sha256d" } ] + "args": [ + { + "hash": "sha256d" + } + ] }, "shareMultiplier": 256, - "blockTemplateRpcExtraParams": [ "groestl" ], + "blockTemplateRpcExtraParams": [ + "groestl" + ], "explorerBlockLink": "https://chainz.cryptoid.info/dgb/block.dws?$height$.htm", "explorerTxLink": "https://chainz.cryptoid.info/dgb/tx.dws?{0}.htm", "explorerAccountLink": "https://chainz.cryptoid.info/dgb/address.dws?{0}.htm" }, - "dogecoin": { "name": "Dogecoin", "canonicalName": "Dogecoin", @@ -890,11 +859,18 @@ }, "headerHasher": { "hash": "scrypt", - "args": [ 1024, 1 ] + "args": [ + 1024, + 1 + ] }, "blockHasher": { "hash": "reverse", - "args": [ { "hash": "sha256d" } ] + "args": [ + { + "hash": "sha256d" + } + ] }, "shareMultiplier": 65536, "coinbaseMinConfimations": 251, @@ -902,7 +878,6 @@ "explorerTxLink": "https://dogechain.info/tx/{0}", "explorerAccountLink": "https://dogechain.info/address/{0}" }, - "ecash": { "name": "eCash", "canonicalName": "eCash", @@ -921,39 +896,17 @@ }, "blockHasher": { "hash": "reverse", - "args": [ { "hash": "sha256d" } ] + "args": [ + { + "hash": "sha256d" + } + ] }, "explorerBlockLink": "https://blockchair.com/ecash/block/$height$", "explorerTxLink": "https://blockchair.com/ecash/transaction/{0}", "explorerAccountLink": "https://blockchair.com/ecash/address/{0}", "hasMinerFund": true }, - - "elicoin": { - "name": "Elicoin", - "symbol": "ELI", - "family": "bitcoin", - "website": "", - "market": "", - "twitter": "", - "telegram": "", - "discord": "", - "coinbaseHasher": { - "hash": "sha256d" - }, - "headerHasher": { - "hash": "yescryptR16" - }, - "blockHasher": { - "hash": "reverse", - "args": [ { "hash": "sha256d" } ] - }, - "shareMultiplier": 1048576, - "explorerBlockLink": "http://block.elicoin.net/?page=block&hash=$hash$", - "explorerTxLink": "http://block.elicoin.net/?page=tx&id={0}", - "explorerAccountLink": "http://block.elicoin.net/?page=search&id={0}" - }, - "emark": { "name": "Deutsche eMark", "canonicalName": "Deutsche-eMark", @@ -972,7 +925,11 @@ }, "blockHasher": { "hash": "reverse", - "args": [ { "hash": "sha256d" } ] + "args": [ + { + "hash": "sha256d" + } + ] }, "coinbaseTxVersion": 2, "coinbaseTxComment": "DEM KriptoKyng", @@ -980,7 +937,6 @@ "explorerTxLink": "https://chainz.cryptoid.info/dem/tx.dws?{0}.htm", "explorerAccountLink": "https://chainz.cryptoid.info/dem/address.dws?{0}.htm" }, - "emrals": { "name": "Emrals", "canonicalName": "Emrals", @@ -999,14 +955,17 @@ }, "blockHasher": { "hash": "reverse", - "args": [ { "hash": "x11" } ] + "args": [ + { + "hash": "x11" + } + ] }, "hasMasterNodes": true, "explorerBlockLink": "http://explorer.emrals.com/block/$height$", "explorerTxLink": "http://explorer.emrals.com/tx/{0}", "explorerAccountLink": "http://explorer.emrals.com/address/{0}" }, - "ergon": { "name": "Ergon", "canonicalName": "Ergon", @@ -1025,14 +984,17 @@ }, "blockHasher": { "hash": "reverse", - "args": [ { "hash": "sha256d" } ] + "args": [ + { + "hash": "sha256d" + } + ] }, "hasCoinbasePayload": true, "explorerBlockLink": "https://explorer.ergon.network/block.dws?$height$.htm", "explorerTxLink": "https://explorer.ergon.network/tx.dws?{0}.htm", "explorerAccountLink": "https://explorer.ergon.network/address.dws?{0}.htm" }, - "etitanium": { "name": "eTitanium ", "canonicalName": "eTitanium ", @@ -1051,13 +1013,16 @@ }, "blockHasher": { "hash": "reverse", - "args": [ { "hash": "sha256d" } ] + "args": [ + { + "hash": "sha256d" + } + ] }, "explorerBlockLink": "https://explorer.etitanium.net/block/$hash$", "explorerTxLink": "https://explorer.etitanium.net/tx/{0}", "explorerAccountLink": "https://explorer.etitanium.net/address/{0}" - }, - + }, "exosis": { "name": "Exosis", "canonicalName": "Exosis", @@ -1076,7 +1041,11 @@ }, "blockHasher": { "hash": "reverse", - "args": [ { "hash": "x16r" } ] + "args": [ + { + "hash": "x16r" + } + ] }, "shareMultiplier": 256, "hasMasterNodes": true, @@ -1084,7 +1053,6 @@ "explorerTxLink": "https://www.blockseek.io/exo/tx/{0}", "explorerAccountLink": "https://www.blockseek.io/exo/address/{0}" }, - "fanaticos-cash": { "name": "Fanaticos Cash", "symbol": "FCH", @@ -1102,13 +1070,16 @@ }, "blockHasher": { "hash": "reverse", - "args": [ { "hash": "sha256d" } ] + "args": [ + { + "hash": "sha256d" + } + ] }, "explorerBlockLink": "https://explorer.fanaticoscriptos.com/block/$hash$", "explorerTxLink": "https://explorer.fanaticoscriptos.com/tx/{0}", "explorerAccountLink": "https://explorer.fanaticoscriptos.com/address/{0}" }, - "feathercoin": { "name": "Feathercoin", "symbol": "FTC", @@ -1123,14 +1094,18 @@ }, "headerHasher": { "hash": "neoscrypt", - "args": [ 0 ] + "args": [ + 0 + ] }, "blockHasher": { "hash": "reverse", "args": [ { "hash": "neoscrypt", - "args": [ 0 ] + "args": [ + 0 + ] } ] }, @@ -1139,7 +1114,6 @@ "explorerTxLink": "https://chainz.cryptoid.info/ftc/tx.dws?{0}.htm", "explorerAccountLink": "https://chainz.cryptoid.info/ftc/address.dws?{0}.htm" }, - "flapx": { "name": "Flapx Coin", "symbol": "FLAPX", @@ -1154,18 +1128,28 @@ }, "headerHasher": { "hash": "scrypt", - "args": [ 1024, 1 ] + "args": [ + 1024, + 1 + ] }, "blockHasher": { "hash": "reverse", - "args": [ { "hash": "sha256d" } ] + "args": [ + { + "hash": "sha256d" + } + ] }, "posBlockHasher": { "hash": "reverse", "args": [ { "hash": "scrypt", - "args": [ 1024, 1 ] + "args": [ + 1024, + 1 + ] } ] }, @@ -1174,7 +1158,6 @@ "explorerTxLink": "http://70.179.122.29:60000/tx/{0}", "explorerAccountLink": "http://70.179.122.29:60000/address/{0}" }, - "flo": { "name": "Florin", "canonicalName": "Flo", @@ -1190,18 +1173,28 @@ }, "headerHasher": { "hash": "scrypt", - "args": [ 1024, 1 ] + "args": [ + 1024, + 1 + ] }, "blockHasher": { "hash": "reverse", - "args": [ { "hash": "sha256d" } ] - }, + "args": [ + { + "hash": "sha256d" + } + ] + }, "posBlockHasher": { "hash": "reverse", "args": [ { "hash": "scrypt", - "args": [ 1024, 1 ] + "args": [ + 1024, + 1 + ] } ] }, @@ -1212,7 +1205,6 @@ "explorerTxLink": "https://livenet.flocha.in/tx/{0}", "explorerAccountLink": "https://livenet.flocha.in/address/{0}" }, - "foxdcoin": { "name": "FoxDcoin", "canonicalName": "FoxDcoin", @@ -1227,77 +1219,33 @@ "hash": "sha256d" }, "headerHasher": { - "hash": "x16rv2" + "hash": "x16r-v2" }, "blockHasher": { "hash": "reverse", - "args": [ { "hash": "x16rv2" } ] - }, - "posBlockHasher": { - "hash": "reverse", - "args": [ { "hash": "x16rv2" } ] - }, - "shareMultiplier": 4096, - "explorerBlockLink": "https://explorer.foxdcoin.com/block-height/$height$", - "explorerTxLink": "https://explorer.foxdcoin.com/tx/{0}", - "explorerAccountLink": "https://explorer.foxdcoin.com/address/{0}" - }, - - "freecash": { - "name": "Free Cash", - "canonicalName": "Freecash", - "symbol": "FCH", - "family": "bitcoin", - "website": "", - "market": "", - "twitter": "", - "telegram": "", - "discord": "", - "coinbaseHasher": { - "hash": "sha256d" - }, - "headerHasher": { - "hash": "sha256d" - }, - "blockHasher": { - "hash": "reverse", - "args": [ { "hash": "sha256d" } ] - }, - "hasCoinbaseDevReward": true, - "explorerBlockLink": "https://freecash.info/block?height=$height$", - "explorerTxLink": "https://freecash.info/transaction?hash={0}", - "explorerAccountLink": "https://freecash.info/address?address={0}" - }, - - "geekcash": { - "name": "Geek Cash", - "symbol": "GEEK", - "family": "bitcoin", - "website": "", - "market": "", - "twitter": "", - "telegram": "", - "discord": "", - "coinbaseHasher": { - "hash": "sha256d" - }, - "headerHasher": { - "hash": "geek" + "args": [ + { + "hash": "x16r-v2" + } + ] }, - "blockHasher": { + "posBlockHasher": { "hash": "reverse", - "args": [ { "hash": "geek" } ] + "args": [ + { + "hash": "x16r-v2" + } + ] }, - "hasMasterNodes": true, - "explorerBlockLink": "http://explorer.geekcash.org/block/$hash$", - "explorerTxLink": "http://explorer.geekcash.org/tx/{0}", - "explorerAccountLink": "http://explorer.geekcash.org/address/{0}" + "shareMultiplier": 4096, + "explorerBlockLink": "https://explorer.foxdcoin.com/block-height/$height$", + "explorerTxLink": "https://explorer.foxdcoin.com/tx/{0}", + "explorerAccountLink": "https://explorer.foxdcoin.com/address/{0}" }, - - "globalboost": { - "name": "GlobalBoost", - "canonicalName": "GlobalBoost", - "symbol": "BSTY", + "freecash": { + "name": "Free Cash", + "canonicalName": "Freecash", + "symbol": "FCH", "family": "bitcoin", "website": "", "market": "", @@ -1308,21 +1256,24 @@ "hash": "sha256d" }, "headerHasher": { - "hash": "yescrypt" + "hash": "sha256d" }, "blockHasher": { "hash": "reverse", - "args": [ { "hash": "sha256d" } ] + "args": [ + { + "hash": "sha256d" + } + ] }, - "shareMultiplier": 1048576, - "explorerBlockLink": "https://bstyexplorer.globalboost.info/block/$height$", - "explorerTxLink": "https://bstyexplorer.globalboost.info/tx/{0}", - "explorerAccountLink": "https://bstyexplorer.globalboost.info/address/{0}" + "hasCoinbaseDevReward": true, + "explorerBlockLink": "https://freecash.info/block?height=$height$", + "explorerTxLink": "https://freecash.info/transaction?hash={0}", + "explorerAccountLink": "https://freecash.info/address?address={0}" }, - - "goldcash": { - "name": "Gold Cash", - "symbol": "GOLD", + "geekcash": { + "name": "Geek Cash", + "symbol": "GEEK", "family": "bitcoin", "website": "", "market": "", @@ -1333,18 +1284,21 @@ "hash": "sha256d" }, "headerHasher": { - "hash": "yescryptR16" + "hash": "geek" }, "blockHasher": { "hash": "reverse", - "args": [ { "hash": "sha256d" } ] + "args": [ + { + "hash": "geek" + } + ] }, - "shareMultiplier": 1048576, - "explorerBlockLink": "http://www.goldcashblockexplorer.co.uk/block/$height$", - "explorerTxLink": "http://www.goldcashblockexplorer.co.uk/tx/{0}", - "explorerAccountLink": "http://www.goldcashblockexplorer.co.uk/address/{0}" + "hasMasterNodes": true, + "explorerBlockLink": "http://explorer.geekcash.org/block/$hash$", + "explorerTxLink": "http://explorer.geekcash.org/tx/{0}", + "explorerAccountLink": "http://explorer.geekcash.org/address/{0}" }, - "groestlcoin": { "name": "Groestlcoin", "canonicalName": "Groestlcoin", @@ -1363,14 +1317,17 @@ }, "blockHasher": { "hash": "reverse", - "args": [ { "hash": "groestl" } ] + "args": [ + { + "hash": "groestl" + } + ] }, "shareMultiplier": 4096, "explorerBlockLink": "https://groestlsight.groestlcoin.org/block/$height$", "explorerTxLink": "https://groestlsight.groestlcoin.org/tx/{0}", "explorerAccountLink": "https://groestlsight.groestlcoin.org/address/{0}" }, - "help-the-homeless": { "name": "Help The Homeless", "symbol": "HTH", @@ -1388,7 +1345,11 @@ }, "blockHasher": { "hash": "reverse", - "args": [ { "hash": "x16r" } ] + "args": [ + { + "hash": "x16r" + } + ] }, "shareMultiplier": 256, "hasMasterNodes": true, @@ -1396,7 +1357,6 @@ "explorerTxLink": "http://explorer.hthcoin.world/tx/{0}", "explorerAccountLink": "http://explorer.hthcoin.world/address/{0}" }, - "hfrcoin": { "name": "HFRcoin", "canonicalName": "HFRcoin", @@ -1412,18 +1372,28 @@ }, "headerHasher": { "hash": "scrypt", - "args": [ 1024, 1 ] + "args": [ + 1024, + 1 + ] }, "blockHasher": { "hash": "reverse", - "args": [ { "hash": "sha256d" } ] + "args": [ + { + "hash": "sha256d" + } + ] }, "posBlockHasher": { "hash": "reverse", "args": [ { "hash": "scrypt", - "args": [ 1024, 1 ] + "args": [ + 1024, + 1 + ] } ] }, @@ -1432,7 +1402,6 @@ "explorerTxLink": "http://hfrco.in/blockcrawler/tx/{0}", "explorerAccountLink": "http://hfrco.in/blockcrawler/address/{0}" }, - "indexchain": { "name": "IndexChain", "symbol": "IDX", @@ -1446,15 +1415,23 @@ "hash": "sha256d" }, "headerHasher": { - "hash": "x16rv2" + "hash": "x16r-v2" }, "blockHasher": { "hash": "reverse", - "args": [ { "hash": "x16rv2" } ] + "args": [ + { + "hash": "x16r-v2" + } + ] }, "posBlockHasher": { "hash": "reverse", - "args": [ { "hash": "x16rv2" } ] + "args": [ + { + "hash": "x16r-v2" + } + ] }, "shareMultiplier": 4096, "hasMasterNodes": true, @@ -1462,8 +1439,6 @@ "explorerTxLink": "http://157.245.248.32:3000/#/tx/{0}", "explorerAccountLink": "http://157.245.248.32:3000/#/address/{0}" }, - - "lanacoin": { "name": "Lanacoin", "canonicalName": "Lana", @@ -1482,13 +1457,16 @@ }, "blockHasher": { "hash": "reverse", - "args": [ { "hash": "sha256d" } ] + "args": [ + { + "hash": "sha256d" + } + ] }, "explorerBlockLink": "https://chainz.cryptoid.info/lana/block.dws?$height$.htm", "explorerTxLink": "https://chainz.cryptoid.info/lana/tx.dws?{0}.htm", "explorerAccountLink": "https://chainz.cryptoid.info/lana/address.dws?{0}.htm" }, - "levocoin": { "name": "Levocoin", "symbol": "LEVO", @@ -1506,14 +1484,17 @@ }, "blockHasher": { "hash": "reverse", - "args": [ { "hash": "x11" } ] + "args": [ + { + "hash": "x11" + } + ] }, "hasMasterNodes": true, "explorerBlockLink": "http://blockexplorer.levocoin.io/block/$height$", "explorerTxLink": "http://blockexplorer.levocoin.io/tx/{0}", "explorerAccountLink": "http://blockexplorer.levocoin.io/address/{0}" }, - "litecoin": { "name": "Litecoin", "canonicalName": "Litecoin", @@ -1529,18 +1510,28 @@ }, "headerHasher": { "hash": "scrypt", - "args": [ 1024, 1 ] + "args": [ + 1024, + 1 + ] }, "blockHasher": { "hash": "reverse", - "args": [ { "hash": "sha256d" } ] + "args": [ + { + "hash": "sha256d" + } + ] }, "posBlockHasher": { "hash": "reverse", "args": [ { "hash": "scrypt", - "args": [ 1024, 1 ] + "args": [ + 1024, + 1 + ] } ] }, @@ -1549,7 +1540,6 @@ "explorerTxLink": "https://chainz.cryptoid.info/ltc/tx.dws?{0}.htm", "explorerAccountLink": "https://chainz.cryptoid.info/ltc/address.dws?{0}.htm" }, - "litecoin-cash": { "name": "Litecoin Cash", "canonicalName": "Litecoin-Cash", @@ -1564,44 +1554,20 @@ "hash": "sha256d" }, "headerHasher": { - "hash": "minotaur" + "hash": "sha256d" }, "blockHasher": { "hash": "reverse", - "args": [ { "hash": "sha256d" } ] + "args": [ + { + "hash": "sha256d" + } + ] }, - "shareMultiplier": 4096, "explorerBlockLink": "https://chainz.cryptoid.info/lcc/block.dws?$height$.htm", "explorerTxLink": "https://chainz.cryptoid.info/lcc/tx.dws?{0}.htm", "explorerAccountLink": "https://chainz.cryptoid.info/lcc/address.dws?{0}.htm" }, - - "litecoin-finance": { - "name": "Litecoin Finance", - "canonicalName": "Litecoin Finance", - "symbol": "LTFN", - "family": "bitcoin", - "website": "https://axerunners.com/", - "market": "https://coinmarketcap.com/currencies/litecoin-finance/", - "twitter": "https://twitter.com/search?q=$axe", - "telegram": "https://t.me/axerunners", - "discord": "https://discordapp.com/invite/BqhteaU", - "coinbaseHasher": { - "hash": "sha256d" - }, - "headerHasher": { - "hash": "yespowerr16" - }, - "blockHasher": { - "hash": "reverse", - "args": [ { "hash": "sha256d" } ] - }, - "shareMultiplier": 65536, - "explorerBlockLink": "https://openchains.info/coin/ltfn/block/$height$", - "explorerTxLink": "https://openchains.info/coin/ltfn/tx/{0}", - "explorerAccountLink": "https://openchains.info/coin/ltfn/address/{0}" - }, - "luckybit": { "name": "Lucky Bit", "symbol": "LUCKY", @@ -1616,14 +1582,18 @@ }, "headerHasher": { "hash": "neoscrypt", - "args": [ 0 ] + "args": [ + 0 + ] }, "blockHasher": { "hash": "reverse", "args": [ { "hash": "neoscrypt", - "args": [ 0 ] + "args": [ + 0 + ] } ] }, @@ -1633,33 +1603,6 @@ "explorerTxLink": "https://openchains.info/coin/luckybit/tx/{0}", "explorerAccountLink": "https://openchains.info/coin/luckybit/address/{0}" }, - - "magpiecoin": { - "name": "MagPie Coin", - "symbol": "MGPC", - "family": "bitcoin", - "website": "", - "market": "", - "twitter": "", - "telegram": "", - "discord": "", - "coinbaseHasher": { - "hash": "sha256d" - }, - "headerHasher": { - "hash": "yespowermgpc" - }, - "blockHasher": { - "hash": "reverse", - "args": [ { "hash": "sha256d" } ] - }, - "shareMultiplier": 65536, - "coinbaseMinConfimations": 401, - "explorerBlockLink": "https://mgpc.explorer.alphax.pro/block/$hash$", - "explorerTxLink": "https://mgpc.explorer.alphax.pro/tx/{0}", - "explorerAccountLink": "https://mgpc.explorer.alphax.pro/address/{0}" - }, - "maza": { "name": "Maza", "canonicalName": "Maza", @@ -1678,14 +1621,16 @@ }, "blockHasher": { "hash": "reverse", - "args": [ { "hash": "sha256d" } ] + "args": [ + { + "hash": "sha256d" + } + ] }, - "blockTemplateRpcExtraParams": [ "sha256d" ], "explorerBlockLink": "https://mazacha.in/block/$hash$", "explorerTxLink": "https://mazacha.in/tx/{0}", "explorerAccountLink": "https://mazacha.in/address/{0}" }, - "mincoin": { "name": "Mincoin", "canonicalName": "Mincoin", @@ -1700,18 +1645,24 @@ }, "headerHasher": { "hash": "scrypt", - "args": [ 1024, 1 ] + "args": [ + 1024, + 1 + ] }, "blockHasher": { "hash": "reverse", - "args": [ { "hash": "sha256d" } ] + "args": [ + { + "hash": "sha256d" + } + ] }, "shareMultiplier": 65536, "explorerBlockLink": "https://chainz.cryptoid.info/mnc/block.dws?$height$.htm", "explorerTxLink": "https://chainz.cryptoid.info/mnc/tx.dws?{0}.htm", "explorerAccountLink": "https://chainz.cryptoid.info/mnc/address.dws?{0}.htm" }, - "monacoin": { "name": "Monacoin", "canonicalName": "Monacoin", @@ -1726,18 +1677,21 @@ "hash": "sha256d" }, "headerHasher": { - "hash": "lyra2rev2" + "hash": "lyra2-rev2" }, "blockHasher": { "hash": "reverse", - "args": [ { "hash": "sha256d" } ] + "args": [ + { + "hash": "sha256d" + } + ] }, "shareMultiplier": 256, "explorerBlockLink": "https://bchain.info/MONA/block/$height$", "explorerTxLink": "https://bchain.info/MONA/tx/{0}", "explorerAccountLink": "https://bchain.info/MONA/addr/{0}" }, - "mooncoin": { "name": "Mooncoin", "canonicalName": "Mooncoin", @@ -1753,18 +1707,28 @@ }, "headerHasher": { "hash": "scrypt", - "args": [ 1024, 1 ] + "args": [ + 1024, + 1 + ] }, "blockHasher": { "hash": "reverse", - "args": [ { "hash": "sha256d" } ] + "args": [ + { + "hash": "sha256d" + } + ] }, "posBlockHasher": { "hash": "reverse", "args": [ { "hash": "scrypt", - "args": [ 1024, 1 ] + "args": [ + 1024, + 1 + ] } ] }, @@ -1773,7 +1737,6 @@ "explorerTxLink": "https://chainz.cryptoid.info/moon/tx.dws?{0}.htm", "explorerAccountLink": "https://chainz.cryptoid.info/moon/address.dws?{0}.htm" }, - "namecoin": { "name": "Namecoin", "canonicalName": "Namecoin", @@ -1792,13 +1755,16 @@ }, "blockHasher": { "hash": "reverse", - "args": [ { "hash": "sha256d" } ] + "args": [ + { + "hash": "sha256d" + } + ] }, "explorerBlockLink": "https://explorer.namecoin.info/b/$height$", "explorerTxLink": "https://explorer.namecoin.info/tx/{0}", "explorerAccountLink": "https://explorer.namecoin.info/a/{0}" }, - "note-blockchain": { "name": "Note Blockchain", "canonicalName": "Note-Blockchain", @@ -1814,18 +1780,28 @@ }, "headerHasher": { "hash": "scrypt", - "args": [ 1024, 1 ] + "args": [ + 1024, + 1 + ] }, "blockHasher": { "hash": "reverse", - "args": [ { "hash": "sha256d" } ] + "args": [ + { + "hash": "sha256d" + } + ] }, "posBlockHasher": { "hash": "reverse", "args": [ { "hash": "scrypt", - "args": [ 1024, 1 ] + "args": [ + 1024, + 1 + ] } ] }, @@ -1834,7 +1810,6 @@ "explorerTxLink": "https://openchains.info/coin/ntbc/tx/{0}", "explorerAccountLink": "https://openchains.info/coin/ntbc/address/{0}" }, - "opticalbitcoin": { "name": "Optical BTC", "symbol": "OBTC", @@ -1852,13 +1827,16 @@ }, "blockHasher": { "hash": "reverse", - "args": [ { "hash": "heavyhash" } ] + "args": [ + { + "hash": "heavyhash" + } + ] }, "explorerBlockLink": "https://explorer.powx.org/block/$hash$", "explorerTxLink": "https://explorer.powx.org/tx/{0}", "explorerAccountLink": "https://explorer.powx.org/address/{0}" }, - "paccoin": { "name": "Paccoin", "symbol": "PAC", @@ -1876,14 +1854,17 @@ }, "blockHasher": { "hash": "reverse", - "args": [ { "hash": "x11" } ] + "args": [ + { + "hash": "x11" + } + ] }, "hasMasterNodes": true, "explorerBlockLink": "http://explorer.paccoin.net/block/$hash$", "explorerTxLink": "http://explorer.paccoin.net/tx/{0}", "explorerAccountLink": "http://explorer.paccoin.net/address/{0}" }, - "pakcoin": { "name": "Pakcoin", "symbol": "PAK", @@ -1898,18 +1879,28 @@ }, "headerHasher": { "hash": "scrypt", - "args": [ 1024, 1 ] + "args": [ + 1024, + 1 + ] }, "blockHasher": { "hash": "reverse", - "args": [ { "hash": "sha256d" } ] + "args": [ + { + "hash": "sha256d" + } + ] }, "posBlockHasher": { "hash": "reverse", "args": [ { "hash": "scrypt", - "args": [ 1024, 1 ] + "args": [ + 1024, + 1 + ] } ] }, @@ -1918,7 +1909,6 @@ "explorerTxLink": "https://chainz.cryptoid.info/pak/tx.dws?{0}.htm", "explorerAccountLink": "https://chainz.cryptoid.info/pak/address.dws?{0}.htm" }, - "peercoin": { "name": "Peercoin", "canonicalName": "Peercoin", @@ -1937,14 +1927,17 @@ }, "blockHasher": { "hash": "reverse", - "args": [ { "hash": "sha256d" } ] + "args": [ + { + "hash": "sha256d" + } + ] }, "coinbaseMinConfimations": 501, "explorerBlockLink": "https://chainz.cryptoid.info/ppc/block.dws?$height$.htm", "explorerTxLink": "https://chainz.cryptoid.info/ppc/tx.dws?{0}.htm", "explorerAccountLink": "https://chainz.cryptoid.info/ppc/address.dws?{0}.htm" }, - "picacoin": { "name": "Picacoin", "canonicalName": "Picacoin", @@ -1963,14 +1956,16 @@ }, "blockHasher": { "hash": "reverse", - "args": [ { "hash": "sha256d" } ] + "args": [ + { + "hash": "sha256d" + } + ] }, "explorerBlockLink": "https://openchains.info/coin/picacoin/block/$height$", "explorerTxLink": "https://openchains.info/coin/picacoin/tx/{0}", "explorerAccountLink": "https://openchains.info/coin/picacoin/address/{0}" - }, - "polcoin": { "name": "Polcoin", "canonicalName": "Polcoin", @@ -1989,13 +1984,16 @@ }, "blockHasher": { "hash": "reverse", - "args": [ { "hash": "sha256d" } ] + "args": [ + { + "hash": "sha256d" + } + ] }, "explorerBlockLink": "https://eksplorator.polcoin.pl/block/$hash$", "explorerTxLink": "hhttps://eksplorator.polcoin.pl/tx/{0}", "explorerAccountLink": "https://eksplorator.polcoin.pl/address/{0}" }, - "profithunters": { "name": "Profit Hunters", "symbol": "PHC", @@ -2010,18 +2008,28 @@ }, "headerHasher": { "hash": "scrypt", - "args": [ 1024, 1 ] + "args": [ + 1024, + 1 + ] }, "blockHasher": { "hash": "reverse", - "args": [ { "hash": "sha256d" } ] + "args": [ + { + "hash": "sha256d" + } + ] }, "posBlockHasher": { "hash": "reverse", "args": [ { "hash": "scrypt", - "args": [ 1024, 1 ] + "args": [ + 1024, + 1 + ] } ] }, @@ -2031,7 +2039,6 @@ "explorerTxLink": "https://explorer.miningpower.net/index.php?transaction={0}", "explorerAccountLink": "https://explorer.miningpower.net/index.php?wallet={0}" }, - "pyrk-sha256": { "name": "Pyrk Sha256", "canonicalName": "Pyrk", @@ -2050,14 +2057,17 @@ }, "blockHasher": { "hash": "reverse", - "args": [ { "hash": "sha256d" } ] + "args": [ + { + "hash": "sha256d" + } + ] }, "hasMasterNodes": true, "explorerBlockLink": "https://explorer.pyrk.org/blockheight/$height$", "explorerTxLink": "https://explorer.pyrk.org/tx/{0}", "explorerAccountLink": "https://explorer.pyrk.org/address/{0}" }, - "pyrk-scrypt": { "name": "Pyrk Scrypt", "canonicalName": "Pyrk", @@ -2073,18 +2083,28 @@ }, "headerHasher": { "hash": "scrypt", - "args": [ 1024, 1 ] + "args": [ + 1024, + 1 + ] }, "blockHasher": { "hash": "reverse", - "args": [ { "hash": "sha256d" } ] + "args": [ + { + "hash": "sha256d" + } + ] }, "posBlockHasher": { "hash": "reverse", "args": [ { "hash": "scrypt", - "args": [ 1024, 1 ] + "args": [ + 1024, + 1 + ] } ] }, @@ -2094,7 +2114,6 @@ "explorerTxLink": "https://explorer.pyrk.org/tx/{0}", "explorerAccountLink": "https://explorer.pyrk.org/address/{0}" }, - "pyrk-x11": { "name": "Pyrk X11", "canonicalName": "Pyrk", @@ -2113,14 +2132,17 @@ }, "blockHasher": { "hash": "reverse", - "args": [ { "hash": "sha256d" } ] + "args": [ + { + "hash": "sha256d" + } + ] }, "hasMasterNodes": true, "explorerBlockLink": "https://explorer.pyrk.org/blockheight/$height$", "explorerTxLink": "https://explorer.pyrk.org/tx/{0}", "explorerAccountLink": "https://explorer.pyrk.org/address/{0}" }, - "raptoreum": { "name": "Raptoreum", "canonicalName": "Raptoreum", @@ -2139,66 +2161,123 @@ }, "blockHasher": { "hash": "reverse", - "args": [ { "hash": "sha256d" } ] + "args": [ + { + "hash": "sha256d" + } + ] }, "hasFounderFee": true, "hasMasterNodes": true, + "foundersRewardAddress": [ + "RTtyQU6DoSuNWetT4WUem5qXP5jNYGpwat" + ], "shareMultiplier": 65536, "explorerBlockLink": "https://explorer.raptoreum.com/block-height/$height$", "explorerTxLink": "https://explorer.raptoreum.com/tx/{0}", "explorerAccountLink": "https://explorer.raptoreum.com/address/{0}" }, - - "reacoin": { - "name": "Reacoin", - "canonicalName": "Reacoin", - "symbol": "REAN", + "gspcoin": { + "name": "Gsp Coin", + "canonicalName": "GspCoin", + "symbol": "GSPC", "family": "bitcoin", - "website": "https://reacoin.io/", - "market": "", - "twitter": "https://twitter.com/REABRAND1OF1", - "telegram": "https://t.me/ReacoinREA", - "discord": "https://discord.com/invite/pXPVNBW7ZB", + "website": "https://coin.globalsocialpost.com/", + "market": "https://www.bitoreum.exchange/trading/gspcusdt", + "twitter": "https://twitter.com/gspcoin", + "discord": "https://discord.gg/Anh2sr4txV", "coinbaseHasher": { "hash": "sha256d" }, "headerHasher": { - "hash": "yescryptR16" + "hash": "ghostrider" }, "blockHasher": { "hash": "reverse", - "args": [ { "hash": "sha256d" } ] + "args": [ + { + "hash": "sha256d" + } + ] }, - "shareMultiplier": 1048576, - "explorerBlockLink": "https://explorer.reacoin.com/block-height/$height$", - "explorerTxLink": "https://explorer.reacoin.com/tx/{0}", - "explorerAccountLink": "https://explorer.reacoin.com/address/{0}" + "hasFounderFee": true, + "hasMasterNodes": true, + "foundersRewardAddress": [ + "GZBNAiLokyYvSwNLftReXuYbvdmzNoorGj" + ], + "shareMultiplier": 65536, + "explorerBlockLink": "https://explorer.globalsocialpost.com/block/$height$", + "explorerTxLink": "https://explorer.globalsocialpost.com/tx/{0}", + "explorerAccountLink": "https://explorer.globalsocialpost.com/address/{0}" }, - - "ring": { - "name": "Ring", - "canonicalName": "Ring", - "symbol": "RNG", + "radiant": { + "name": "Radiant", + "symbol": "RXD", "family": "bitcoin", - "website": "", - "market": "", - "twitter": "", - "telegram": "", - "discord": "", "coinbaseHasher": { "hash": "sha256d" }, "headerHasher": { - "hash": "minotaur" + "hash": "sha512/256d" }, "blockHasher": { "hash": "reverse", - "args": [ { "hash": "sha256d" } ] + "args": [ { "hash": "sha512/256d" } ] + }, + "explorerBlockLink": "https://explorer.radiantblockchain.org/block-height/$height$", + "explorerTxLink": "https://explorer.radiantblockchain.org/tx/{0}", + "explorerAccountLink": "https://explorer.radiantblockchain.org/address/{0}" + }, + "novo": { + "name": "Novo", + "symbol": "NOVO", + "family": "bitcoin", + "coinbaseHasher": { + "hash": "sha256d" + }, + "headerHasher": { + "hash": "sha256dt" + }, + "blockHasher": { + "hash": "reverse", + "args": [ { "hash": "sha256dt" } ] + }, + "explorerBlockLink": "https://explorer.novochain.ovh/block/$height$", + "explorerTxLink": "https://explorer.novochain.ovh/tx/{0}", + "explorerAccountLink": "https://explorer.novochain.ovh/address/{0}" + }, + "bitoreum": { + "name": "Bitoreum", + "canonicalName": "Bitoreum", + "symbol": "BTRM", + "family": "bitcoin", + "website": "https://bitoreum.org/", + "market": "https://www.coingecko.com/en/coins/bitoreum", + "twitter": "https://twitter.com/bitoreum", + "discord": "https://discord.gg/E3E9Ef3kZT", + "coinbaseHasher": { + "hash": "sha256d" }, - "shareMultiplier": 4096, - "explorerBlockLink": "https://chainz.cryptoid.info/rng/block.dws?$height$.htm", - "explorerTxLink": "https://chainz.cryptoid.info/rng/tx.dws?{0}.htm", - "explorerAccountLink": "https://chainz.cryptoid.info/rng/address.dws?{0}.htm" + "headerHasher": { + "hash": "ghostrider" + }, + "blockHasher": { + "hash": "reverse", + "args": [ + { + "hash": "sha256d" + } + ] + }, + "hasFounderFee": true, + "hasMasterNodes": true, + "foundersRewardAddress": [ + "BanxgMPcMpXnuWQ2ogfQqEkwwVtjhAhXBR" + ], + "shareMultiplier": 65536, + "explorerBlockLink": "https://explorer.bitoreum.org/block/$hash$", + "explorerTxLink": "https://explorer.bitoreum.org/tx/{0}", + "explorerAccountLink": "https://explorer.bitoreum.org/address/{0}" }, "rosecoin": { @@ -2215,18 +2294,28 @@ }, "headerHasher": { "hash": "scrypt", - "args": [ 1024, 1 ] + "args": [ + 1024, + 1 + ] }, "blockHasher": { "hash": "reverse", - "args": [ { "hash": "sha256d" } ] + "args": [ + { + "hash": "sha256d" + } + ] }, "posBlockHasher": { "hash": "reverse", "args": [ { "hash": "scrypt", - "args": [ 1024, 1 ] + "args": [ + 1024, + 1 + ] } ] }, @@ -2235,7 +2324,6 @@ "explorerTxLink": "https://be.rosebird.org/tx/{0}", "explorerAccountLink": "https://be.rosebird.org/address/{0}" }, - "shroud": { "name": "ShroudX", "symbol": "SHRX", @@ -2249,15 +2337,23 @@ "hash": "sha256d" }, "headerHasher": { - "hash": "x16rv2" + "hash": "x16r-v2" }, "blockHasher": { "hash": "reverse", - "args": [ { "hash": "x16rv2" } ] + "args": [ + { + "hash": "x16r-v2" + } + ] }, "posBlockHasher": { "hash": "reverse", - "args": [ { "hash": "x16rv2" } ] + "args": [ + { + "hash": "x16r-v2" + } + ] }, "hasMasterNodes": true, "shareMultiplier": 4096, @@ -2265,7 +2361,6 @@ "explorerTxLink": "https://explorer.shroudx.eu/tx/{0}", "explorerAccountLink": "https://explorer.shroudx.eu/address/{0}" }, - "smileycoin-sha256": { "name": "Smileycoin Sha256", "canonicalName": "Smileycoin", @@ -2284,14 +2379,19 @@ }, "blockHasher": { "hash": "reverse", - "args": [ { "hash": "sha256d" } ] + "args": [ + { + "hash": "sha256d" + } + ] }, - "blockTemplateRpcExtraParams": [ "sha256d" ], + "blockTemplateRpcExtraParams": [ + "sha256d" + ], "explorerBlockLink": "https://chainz.cryptoid.info/smly/block.dws?$height$.htm", "explorerTxLink": "https://chainz.cryptoid.info/smly/tx.dws?{0}.htm", "explorerAccountLink": "https://chainz.cryptoid.info/smly/address.dws?{0}.htm" }, - "smileycoin-scrypt": { "name": "Smileycoin Scrypt", "canonicalName": "Smileycoin", @@ -2307,19 +2407,27 @@ }, "headerHasher": { "hash": "scrypt", - "args": [ 1024, 1 ] + "args": [ + 1024, + 1 + ] }, "blockHasher": { "hash": "reverse", - "args": [ { "hash": "sha256d" } ] + "args": [ + { + "hash": "sha256d" + } + ] }, - "blockTemplateRpcExtraParams": [ "scrypt" ], + "blockTemplateRpcExtraParams": [ + "scrypt" + ], "shareMultiplier": 65536, "explorerBlockLink": "https://chainz.cryptoid.info/smly/block.dws?$height$.htm", "explorerTxLink": "https://chainz.cryptoid.info/smly/tx.dws?{0}.htm", "explorerAccountLink": "https://chainz.cryptoid.info/smly/address.dws?{0}.htm" }, - "smileycoin-skein": { "name": "Smileycoin Skein", "canonicalName": "Smileycoin", @@ -2338,14 +2446,19 @@ }, "blockHasher": { "hash": "reverse", - "args": [ { "hash": "sha256d" } ] + "args": [ + { + "hash": "sha256d" + } + ] }, - "blockTemplateRpcExtraParams": [ "skein" ], + "blockTemplateRpcExtraParams": [ + "skein" + ], "explorerBlockLink": "https://chainz.cryptoid.info/smly/block.dws?$height$.htm", "explorerTxLink": "https://chainz.cryptoid.info/smly/tx.dws?{0}.htm", "explorerAccountLink": "https://chainz.cryptoid.info/smly/address.dws?{0}.htm" }, - "smileycoin-qubit": { "name": "Smileycoin Qubit", "canonicalName": "Smileycoin", @@ -2364,14 +2477,19 @@ }, "blockHasher": { "hash": "reverse", - "args": [ { "hash": "sha256d" } ] + "args": [ + { + "hash": "sha256d" + } + ] }, - "blockTemplateRpcExtraParams": [ "qubit" ], + "blockTemplateRpcExtraParams": [ + "qubit" + ], "explorerBlockLink": "https://chainz.cryptoid.info/smly/block.dws?$height$.htm", "explorerTxLink": "https://chainz.cryptoid.info/smly/tx.dws?{0}.htm", "explorerAccountLink": "https://chainz.cryptoid.info/smly/address.dws?{0}.htm" }, - "smileycoin-groestl": { "name": "Smileycoin Groestl", "canonicalName": "Smileycoin", @@ -2386,19 +2504,24 @@ "hash": "sha256d" }, "headerHasher": { - "hash": "groestlmyriad" + "hash": "groestl-myriad" }, "blockHasher": { "hash": "reverse", - "args": [ { "hash": "sha256d" } ] + "args": [ + { + "hash": "sha256d" + } + ] }, "shareMultiplier": 4096, - "blockTemplateRpcExtraParams": [ "groestl" ], + "blockTemplateRpcExtraParams": [ + "groestl" + ], "explorerBlockLink": "https://chainz.cryptoid.info/smly/block.dws?$height$.htm", "explorerTxLink": "https://chainz.cryptoid.info/smly/tx.dws?{0}.htm", "explorerAccountLink": "https://chainz.cryptoid.info/smly/address.dws?{0}.htm" }, - "sparkspay": { "name": "SparksPay", "canonicalName": "SparkPay", @@ -2414,14 +2537,18 @@ }, "headerHasher": { "hash": "neoscrypt", - "args": [ 0 ] + "args": [ + 0 + ] }, "blockHasher": { "hash": "reverse", "args": [ { "hash": "neoscrypt", - "args": [ 0 ] + "args": [ + 0 + ] } ] }, @@ -2431,7 +2558,6 @@ "explorerTxLink": "https://chainz.cryptoid.info/spk/tx.dws?{0}.htm", "explorerAccountLink": "https://chainz.cryptoid.info/spk/address.dws?{0}.htm" }, - "stakecube": { "name": "StakeCube", "canonicalName": "Stakecube", @@ -2450,40 +2576,17 @@ }, "blockHasher": { "hash": "reverse", - "args": [ { "hash": "x11" } ] + "args": [ + { + "hash": "x11" + } + ] }, "hasMasterNodes": true, "explorerBlockLink": "https://scc.ccore.online/block/$height$", "explorerTxLink": "https://scc.ccore.online/tx/{0}", - "explorerAccountLink":"https://scc.ccore.online/address/{0}" - }, - - "sugarchain": { - "name": "Sugarchain", - "canonicalName": "Sugarchain", - "symbol": "SUGAR", - "family": "bitcoin", - "website": "https://sugarchain.org/", - "market": "https://coinmarketcap.com/currencies/sugarchain/", - "twitter": "https://twitter.com/sugarchain_dev", - "telegram": "https://t.me/sugarchain", - "discord": "", - "coinbaseHasher": { - "hash": "sha256d" - }, - "headerHasher": { - "hash": "yespowersugar" - }, - "blockHasher": { - "hash": "reverse", - "args": [ { "hash": "sha256d" } ] - }, - "shareMultiplier": 4194304, - "explorerBlockLink": "https://1explorer.sugarchain.org/block/$hash$", - "explorerTxLink": "https://1explorer.sugarchain.org/tx/{0}", - "explorerAccountLink": "https://1explorer.sugarchain.org/address/{0}" + "explorerAccountLink": "https://scc.ccore.online/address/{0}" }, - "susucoin": { "name": "Susucoin", "canonicalName": "Susucoin", @@ -2502,13 +2605,16 @@ }, "blockHasher": { "hash": "reverse", - "args": [ { "hash": "sha256d" } ] + "args": [ + { + "hash": "sha256d" + } + ] }, "explorerBlockLink": "https://explore.susukino.com//block/$hash$", "explorerTxLink": "https://explore.susukino.com/tx/{0}", "explorerAccountLink": "https://explore.susukino.com/address/{0}" }, - "swippcoin": { "name": "Swipp", "symbol": "SWP", @@ -2526,14 +2632,17 @@ }, "blockHasher": { "hash": "reverse", - "args": [ { "hash": "x11" } ] + "args": [ + { + "hash": "x11" + } + ] }, "hasMasterNodes": true, "explorerBlockLink": "http://explorer.swippcoin.com/block/$height$", "explorerTxLink": "http://explorer.swippcoin.com/tx/{0}", "explorerAccountLink": "http://explorer.swippcoin.com/address/{0}" }, - "terracoin": { "name": "Terracoin", "canonicalName": "Terracoin", @@ -2552,13 +2661,16 @@ }, "blockHasher": { "hash": "reverse", - "args": [ { "hash": "sha256d" } ] + "args": [ + { + "hash": "sha256d" + } + ] }, "explorerBlockLink": "http://insight.terracoin.io/block/$hash$", "explorerTxLink": "http://insight.terracoin.io/tx/{0}", "explorerAccountLink": "http://insight.terracoin.io/address/{0}" }, - "tdcoin": { "name": "TDCOIN", "symbol": "TDC", @@ -2576,13 +2688,16 @@ }, "blockHasher": { "hash": "reverse", - "args": [ { "hash": "sha256d" } ] + "args": [ + { + "hash": "sha256d" + } + ] }, "explorerBlockLink": "https://www.tdcoincore.org/bcexplorer/blockh/$height$", "explorerTxLink": "https://www.tdcoincore.org/bcexplorer/tx/{0}", "explorerAccountLink": "https://www.tdcoincore.org/bcexplorer/address/{0}" }, - "theholyroger": { "name": "The Holy Roger", "symbol": "ROGER", @@ -2597,18 +2712,28 @@ }, "headerHasher": { "hash": "scrypt", - "args": [ 1024, 1 ] + "args": [ + 1024, + 1 + ] }, "blockHasher": { "hash": "reverse", - "args": [ { "hash": "sha256d" } ] + "args": [ + { + "hash": "sha256d" + } + ] }, "posBlockHasher": { "hash": "reverse", "args": [ { "hash": "scrypt", - "args": [ 1024, 1 ] + "args": [ + 1024, + 1 + ] } ] }, @@ -2617,7 +2742,6 @@ "explorerTxLink": "https://explorer.theholyroger.com/tx/{0}", "explorerAccountLink": "https://explorer.theholyroger.com/address/{0}" }, - "thooneum": { "name": "Thooneum", "canonicalName": "Thooneum", @@ -2636,7 +2760,11 @@ }, "blockHasher": { "hash": "reverse", - "args": [ { "hash": "sha256d" } ] + "args": [ + { + "hash": "sha256d" + } + ] }, "hasFounderFee": true, "hasMasterNodes": true, @@ -2645,11 +2773,9 @@ "explorerTxLink": "http://rtm.timyg.org:6950/tx/{0}", "explorerAccountLink": "http://rtm.timyg.org:6950/address/{0}" }, - - "tidecoin": { - "name": "Tidecoin", - "canonicalName": "Tidecoin", - "symbol": "TDC", + "titcoin": { + "name": "Titcoin", + "symbol": "TIT", "family": "bitcoin", "website": "", "market": "", @@ -2660,42 +2786,20 @@ "hash": "sha256d" }, "headerHasher": { - "hash": "yespowertide" + "hash": "sha256d" }, "blockHasher": { "hash": "reverse", - "args": [ { "hash": "sha256d" } ] - }, - "shareMultiplier": 3145728, - "explorerBlockLink": "http://explorer.tidecoin.org/block/$hash$", - "explorerTxLink": "http://explorer.tidecoin.org/tx/{0}", - "explorerAccountLink": "http://explorer.tidecoin.org/address/{0}" - }, - - "titcoin": { - "name": "Titcoin", - "symbol": "TIT", - "family": "bitcoin", - "website": "", - "market": "", - "twitter": "", - "telegram": "", - "discord": "", - "coinbaseHasher": { - "hash": "sha256d" + "args": [ + { + "hash": "sha256d" + } + ] }, - "headerHasher": { - "hash": "sha256d" - }, - "blockHasher": { - "hash": "reverse", - "args": [ { "hash": "sha256d" } ] - }, - "explorerBlockLink": "https://www.blockexperts.com/tit/height/$height$", - "explorerTxLink": "https://www.blockexperts.com/tit/tx/{0}", - "explorerAccountLink": "https://www.blockexperts.com/tit/address/{0}" + "explorerBlockLink": "https://www.blockexperts.com/tit/height/$height$", + "explorerTxLink": "https://www.blockexperts.com/tit/tx/{0}", + "explorerAccountLink": "https://www.blockexperts.com/tit/address/{0}" }, - "tiltcoin": { "name": "TILTCoin", "canonicalName": "TILTCoin", @@ -2711,45 +2815,24 @@ }, "headerHasher": { "hash": "scrypt", - "args": [ 1024, 1 ] + "args": [ + 1024, + 1 + ] }, "blockHasher": { "hash": "reverse", - "args": [ { "hash": "sha256d" } ] + "args": [ + { + "hash": "sha256d" + } + ] }, "shareMultiplier": 65536, "explorerBlockLink": "https://explorer.tiltcoin.io/block/$hash$", "explorerTxLink": "https://explorer.tiltcoin.io/tx/{0}", "explorerAccountLink": "https://explorer.tiltcoin.io/address/{0}" }, - - "veco": { - "name": "Veco", - "canonicalName": "Veco", - "symbol": "VECO", - "family": "bitcoin", - "website": "https://veco.to/", - "market": "https://coinmarketcap.com/currencies/veco/", - "twitter": "https://twitter.com/VECO_Community", - "telegram": "", - "discord": "https://discordapp.com/invite/Z7j9mz6", - "coinbaseHasher": { - "hash": "sha256d" - }, - "headerHasher": { - "hash": "yespower" - }, - "blockHasher": { - "hash": "reverse", - "args": [ { "hash": "yespower" } ] - }, - "hasMasterNodes": true, - "shareMultiplier": 65536, - "explorerBlockLink": "http://block.veco.to/block/$hash$", - "explorerTxLink": "http://block.veco.to/tx/{0}", - "explorerAccountLink": "http://block.veco.to/address/{0}" - }, - "veles-sha256": { "name": "Veles-Sha256", "canonicalName": "Veles", @@ -2768,14 +2851,17 @@ }, "blockHasher": { "hash": "reverse", - "args": [ { "hash": "sha256d" } ] + "args": [ + { + "hash": "sha256d" + } + ] }, "hasMasterNodes": true, "explorerBlockLink": "https://chainz.cryptoid.info/vls/block.dws?$height$.htm", "explorerTxLink": "https://chainz.cryptoid.info/vls/tx.dws?{0}.htm", "explorerAccountLink": "https://chainz.cryptoid.info/vls/address.dws?{0}.htm" - }, - + }, "veles-scrypt": { "name": "Veles Scrypt", "canonicalName": "Veles", @@ -2787,22 +2873,32 @@ "telegram": "", "discord": "", "coinbaseHasher": { - "hash": "sha256d" + "hash": "sha256d" }, "headerHasher": { "hash": "scrypt", - "args": [ 1024, 1 ] + "args": [ + 1024, + 1 + ] }, "blockHasher": { "hash": "reverse", - "args": [ { "hash": "sha256d" } ] + "args": [ + { + "hash": "sha256d" + } + ] }, "posBlockHasher": { "hash": "reverse", "args": [ { "hash": "scrypt", - "args": [ 1024, 1 ] + "args": [ + 1024, + 1 + ] } ] }, @@ -2812,7 +2908,6 @@ "explorerTxLink": "https://chainz.cryptoid.info/vls/tx.dws?{0}.htm", "explorerAccountLink": "https://chainz.cryptoid.info/vls/address.dws?{0}.htm" }, - "verge-lyra": { "name": "Verge Lyra", "canonicalName": "Verge", @@ -2827,25 +2922,29 @@ "hash": "sha256d" }, "headerHasher": { - "hash": "lyra2rev2" + "hash": "lyra2-rev2" }, "blockHasher": { "hash": "reverse", "args": [ { "hash": "scrypt", - "args": [ 1024, 1 ] + "args": [ + 1024, + 1 + ] } ] }, "isPseudoPoS": true, - "blockTemplateRpcExtraParams": [ "lyra" ], + "blockTemplateRpcExtraParams": [ + "lyra" + ], "shareMultiplier": 256, "explorerBlockLink": "https://verge-blockchain.info/block/$hash$", "explorerTxLink": "https://verge-blockchain.info/tx/{0}", "explorerAccountLink": "https://verge-blockchain.info/address/{0}" }, - "verge-scrypt": { "name": "Verge-Scrypt", "canonicalName": "Verge", @@ -2861,25 +2960,32 @@ }, "headerHasher": { "hash": "scrypt", - "args": [ 1024, 1 ] + "args": [ + 1024, + 1 + ] }, "blockHasher": { "hash": "reverse", "args": [ { "hash": "scrypt", - "args": [ 1024, 1 ] + "args": [ + 1024, + 1 + ] } ] }, "isPseudoPoS": true, - "blockTemplateRpcExtraParams": [ "scrypt" ], + "blockTemplateRpcExtraParams": [ + "scrypt" + ], "shareMultiplier": 65536, "explorerBlockLink": "https://verge-blockchain.info/block/$hash$", "explorerTxLink": "https://verge-blockchain.info/tx/{0}", "explorerAccountLink": "https://verge-blockchain.info/address/{0}" }, - "verge-x17": { "name": "Verge X17", "canonicalName": "Verge", @@ -2901,17 +3007,21 @@ "args": [ { "hash": "scrypt", - "args": [ 1024, 1 ] + "args": [ + 1024, + 1 + ] } ] }, "isPseudoPoS": true, - "blockTemplateRpcExtraParams": [ "x17" ], + "blockTemplateRpcExtraParams": [ + "x17" + ], "explorerBlockLink": "https://verge-blockchain.info/block/$hash$", "explorerTxLink": "https://verge-blockchain.info/tx/{0}", "explorerAccountLink": "https://verge-blockchain.info/address/{0}" }, - "verge-blake": { "name": "Verge Blake", "canonicalName": "Verge", @@ -2933,17 +3043,21 @@ "args": [ { "hash": "scrypt", - "args": [ 1024, 1 ] + "args": [ + 1024, + 1 + ] } ] }, "isPseudoPoS": true, - "blockTemplateRpcExtraParams": [ "blake" ], + "blockTemplateRpcExtraParams": [ + "blake" + ], "explorerBlockLink": "https://verge-blockchain.info/block/$hash$", "explorerTxLink": "https://verge-blockchain.info/tx/{0}", "explorerAccountLink": "https://verge-blockchain.info/address/{0}" }, - "verge-groestl": { "name": "Verge Groestl", "canonicalName": "Verge", @@ -2958,24 +3072,28 @@ "hash": "sha256d" }, "headerHasher": { - "hash": "groestlmyriad" + "hash": "groestl-myriad" }, "blockHasher": { "hash": "reverse", "args": [ { "hash": "scrypt", - "args": [ 1024, 1 ] + "args": [ + 1024, + 1 + ] } ] }, "isPseudoPoS": true, - "blockTemplateRpcExtraParams": [ "groestl" ], + "blockTemplateRpcExtraParams": [ + "groestl" + ], "explorerBlockLink": "https://verge-blockchain.info/block/$hash$", "explorerTxLink": "https://verge-blockchain.info/tx/{0}", "explorerAccountLink": "https://verge-blockchain.info/address/{0}" }, - "vertcoin": { "name": "Vertcoin", "symbol": "VTC", @@ -2993,14 +3111,17 @@ }, "blockHasher": { "hash": "reverse", - "args": [ { "hash": "sha256d" } ] + "args": [ + { + "hash": "sha256d" + } + ] }, "shareMultiplier": 256, "explorerBlockLink": "https://chainz.cryptoid.info/vtc/block.dws?$height$.htm", "explorerTxLink": "https://chainz.cryptoid.info/vtc/tx.dws?{0}.htm", "explorerAccountLink": "https://chainz.cryptoid.info/vtc/address.dws?{0}.htm" }, - "viacoin": { "name": "Viacoin", "canonicalName": "Viacoin", @@ -3016,18 +3137,28 @@ }, "headerHasher": { "hash": "scrypt", - "args": [ 1024, 1 ] + "args": [ + 1024, + 1 + ] }, "blockHasher": { "hash": "reverse", - "args": [ { "hash": "sha256d" } ] + "args": [ + { + "hash": "sha256d" + } + ] }, "posBlockHasher": { "hash": "reverse", "args": [ { "hash": "scrypt", - "args": [ 1024, 1 ] + "args": [ + 1024, + 1 + ] } ] }, @@ -3036,7 +3167,6 @@ "explorerTxLink": "https://chainz.cryptoid.info/via/tx.dws?{0}.htm", "explorerAccountLink": "https://chainz.cryptoid.info/via/address.dws?{0}.htm" }, - "voltpotcoin": { "name": "Volt Pot Coin", "canonicalName": "Auroracoin", @@ -3052,18 +3182,28 @@ }, "headerHasher": { "hash": "scrypt", - "args": [ 1024, 1 ] + "args": [ + 1024, + 1 + ] }, "blockHasher": { "hash": "reverse", - "args": [ { "hash": "sha256d" } ] + "args": [ + { + "hash": "sha256d" + } + ] }, "posBlockHasher": { "hash": "reverse", "args": [ { "hash": "scrypt", - "args": [ 1024, 1 ] + "args": [ + 1024, + 1 + ] } ] }, @@ -3072,7 +3212,6 @@ "explorerTxLink": "https://explorer.voltpot.org/tx/{0}", "explorerAccountLink": "https://explorer.voltpot.org/address/{0}" }, - "widecoin": { "name": "Widecoin", "canonicalName": "Widecoin", @@ -3091,13 +3230,16 @@ }, "blockHasher": { "hash": "reverse", - "args": [ { "hash": "sha256d" } ] + "args": [ + { + "hash": "sha256d" + } + ] }, "explorerBlockLink": "https://explorer.widecoin.org/block-height/$height$", "explorerTxLink": "https://explorer.widecoin.org/tx/{0}", "explorerAccountLink": "https://explorer.widecoin.org/address/{0}" }, - "worldcoin": { "name": "Worldcoin", "canonicalName": "Worldcoin", @@ -3113,18 +3255,24 @@ }, "headerHasher": { "hash": "scrypt", - "args": [ 1024, 1 ] + "args": [ + 1024, + 1 + ] }, "blockHasher": { "hash": "reverse", - "args": [ { "hash": "sha256d" } ] + "args": [ + { + "hash": "sha256d" + } + ] }, "shareMultiplier": 65536, "explorerBlockLink": "https://chainz.cryptoid.info/wdc/block.dws?$height$.htm", "explorerTxLink": "https://chainz.cryptoid.info/wdc/tx.dws?{0}.htm", "explorerAccountLink": "https://chainz.cryptoid.info/wdc/address.dws?{0}.htm" }, - "xenios": { "name": "Xenios", "canonicalName": "Xenios", @@ -3143,14 +3291,17 @@ }, "blockHasher": { "hash": "reverse", - "args": [ { "hash": "x11" } ] + "args": [ + { + "hash": "x11" + } + ] }, "hasMasterNodes": true, "explorerBlockLink": "http://blockexplorer.xenioscoin.com/block/$hash$", "explorerTxLink": "http://blockexplorer.xenioscoin.com/tx/{0}", "explorerAccountLink": "http://blockexplorer.xenioscoin.com/address/{0}" }, - "xazab": { "name": "Xazab", "canonicalName": "Xazab", @@ -3169,40 +3320,17 @@ }, "blockHasher": { "hash": "reverse", - "args": [ { "hash": "x11" } ] + "args": [ + { + "hash": "x11" + } + ] }, "hasMasterNodes": true, "explorerBlockLink": "https://explorer.xazab.xyz/insight/block/$height$", "explorerTxLink": "https://explorer.xazab.xyz/insight/tx/{0}", "explorerAccountLink": "https://explorer.xazab.xyz/insight/address/{0}" }, - - "yenten": { - "name": "Yenten", - "canonicalName": "Yenten", - "symbol": "YTN", - "family": "bitcoin", - "website": "http://yentencoin.info/", - "market": "https://coinmarketcap.com/currencies/yenten", - "twitter": "https://twitter.com/yentencoin", - "telegram": "https://t.me/yenten", - "discord": "https://discord.gg/RTbPxu3", - "coinbaseHasher": { - "hash": "sha256d" - }, - "headerHasher": { - "hash": "yespowerr16" - }, - "blockHasher": { - "hash": "reverse", - "args": [ { "hash": "yespowerr16" } ] - }, - "shareMultiplier": 65536, - "explorerBlockLink": "http://ytn.ccore.online/block/$height$", - "explorerTxLink": "http://ytn.ccore.online/transaction/{0}", - "explorerAccountLink": "http://ytn.ccore.online/address/{0}" - }, - "yerbas": { "name": "Yerbas", "canonicalName": "Yerbas", @@ -3220,7 +3348,11 @@ }, "blockHasher": { "hash": "reverse", - "args": [ { "hash": "sha256d" } ] + "args": [ + { + "hash": "sha256d" + } + ] }, "hasFounderFee": true, "hasMasterNodes": true, @@ -3229,7 +3361,6 @@ "explorerTxLink": "https://explorer.yerbas.org/tx/{0}", "explorerAccountLink": "https://explorer.yerbas.org/address/{0}" }, - "zetacoin": { "name": "Zetacoin", "canonicalName": "Zetacoin", @@ -3248,13 +3379,16 @@ }, "blockHasher": { "hash": "reverse", - "args": [ { "hash": "sha256d" } ] + "args": [ + { + "hash": "sha256d" + } + ] }, "explorerBlockLink": "https://chainz.cryptoid.info/zet/block.dws?$height$.htm", "explorerTxLink": "https://chainz.cryptoid.info/zet/tx.dws?{0}.htm", "explorerAccountLink": "https://chainz.cryptoid.info/zet/address.dws?{0}.htm" }, - "bitcoin-gold": { "name": "Bitcoin Gold", "canonicalName": "Bitcoin Gold", @@ -3272,7 +3406,11 @@ "solutionPreambleSize": 1, "solver": { "hash": "equihash", - "args": [ 144, 5, "BgoldPoW" ] + "args": [ + 144, + 5, + "BgoldPoW" + ] }, "coinbaseTxNetwork": "main", "payFoundersReward": false @@ -3283,7 +3421,11 @@ "solutionPreambleSize": 1, "solver": { "hash": "equihash", - "args": [ 144, 5, "BgoldPoW" ] + "args": [ + 144, + 5, + "BgoldPoW" + ] }, "coinbaseTxNetwork": "testnet", "payFoundersReward": false @@ -3294,7 +3436,11 @@ "solutionPreambleSize": 1, "solver": { "hash": "equihash", - "args": [ 144, 5, "BgoldPoW" ] + "args": [ + 144, + 5, + "BgoldPoW" + ] }, "coinbaseTxNetwork": "regtest", "payFoundersReward": false @@ -3306,7 +3452,6 @@ "explorerTxLink": "https://explorer.bitcoingold.org/insight/tx/{0}", "explorerAccountLink": "https://explorer.bitcoingold.org/insight/address/{0}" }, - "flux": { "name": "Flux", "canonicalName": "Flux", @@ -3324,7 +3469,11 @@ "solutionPreambleSize": 1, "solver": { "hash": "equihash", - "args": [ 144, 5, "BgoldPoW" ] + "args": [ + 144, + 5, + "BgoldPoW" + ] }, "coinbaseTxNetwork": "main", "payFoundersReward": false @@ -3335,7 +3484,11 @@ "solutionPreambleSize": 1, "solver": { "hash": "equihash", - "args": [ 144, 5, "BgoldPoW" ] + "args": [ + 144, + 5, + "BgoldPoW" + ] }, "coinbaseTxNetwork": "testnet", "payFoundersReward": false @@ -3346,7 +3499,11 @@ "solutionPreambleSize": 1, "solver": { "hash": "equihash", - "args": [ 144, 5, "BgoldPoW" ] + "args": [ + 144, + 5, + "BgoldPoW" + ] }, "coinbaseTxNetwork": "regtest", "payFoundersReward": false @@ -3358,7 +3515,6 @@ "explorerTxLink": "https://explorer.bitcoingold.org/insight/tx/{0}", "explorerAccountLink": "https://explorer.bitcoingold.org/insight/address/{0}" }, - "bitcoin-private": { "name": "Bitcoin Private", "symbol": "BTCP", @@ -3375,7 +3531,11 @@ "solutionPreambleSize": 3, "solver": { "hash": "equihash", - "args": [ 200, 9, "ZcashPoW" ] + "args": [ + 200, + 9, + "ZcashPoW" + ] }, "coinbaseTxNetwork": "main", "payFoundersReward": false @@ -3386,7 +3546,11 @@ "solutionPreambleSize": 3, "solver": { "hash": "equihash", - "args": [ 200, 9, "ZcashPoW" ] + "args": [ + 200, + 9, + "ZcashPoW" + ] }, "coinbaseTxNetwork": "testnet", "payFoundersReward": false @@ -3397,7 +3561,11 @@ "solutionPreambleSize": 3, "solver": { "hash": "equihash", - "args": [ 200, 9, "ZcashPoW" ] + "args": [ + 200, + 9, + "ZcashPoW" + ] }, "coinbaseTxNetwork": "regtest", "payFoundersReward": false @@ -3409,7 +3577,6 @@ "explorerTxLink": "https://explorer.btcprivate.org/tx/{0}", "explorerAccountLink": "https://explorer.btcprivate.org/address/{0}" }, - "bithereum": { "name": "Bithereum", "symbol": "BTH", @@ -3426,7 +3593,11 @@ "solutionPreambleSize": 1, "solver": { "hash": "equihash", - "args": [ 144, 5, "BethdPoW" ] + "args": [ + 144, + 5, + "BethdPoW" + ] }, "coinbaseTxNetwork": "main", "payFoundersReward": false @@ -3437,7 +3608,11 @@ "solutionPreambleSize": 1, "solver": { "hash": "equihash", - "args": [ 144, 5, "BethdPoW" ] + "args": [ + 144, + 5, + "BethdPoW" + ] }, "coinbaseTxNetwork": "testnet", "payFoundersReward": false @@ -3448,7 +3623,11 @@ "solutionPreambleSize": 1, "solver": { "hash": "equihash", - "args": [ 144, 5, "BethdPoW" ] + "args": [ + 144, + 5, + "BethdPoW" + ] }, "coinbaseTxNetwork": "regtest", "payFoundersReward": false @@ -3460,7 +3639,6 @@ "explorerTxLink": "https://explorer.bithereum.network/tx/{0}", "explorerAccountLink": "https://explorer.bithereum.network/address/{0}" }, - "minexcoin": { "name": "Minexcoin", "symbol": "MNX", @@ -3477,7 +3655,11 @@ "solutionPreambleSize": 1, "solver": { "hash": "equihash", - "args": [ 96, 5, "ZcashPoW" ] + "args": [ + 96, + 5, + "ZcashPoW" + ] }, "coinbaseTxNetwork": "main", "payFoundersReward": false @@ -3488,7 +3670,11 @@ "solutionPreambleSize": 1, "solver": { "hash": "equihash", - "args": [ 96, 5, "ZcashPoW" ] + "args": [ + 96, + 5, + "ZcashPoW" + ] }, "coinbaseTxNetwork": "testnet", "payFoundersReward": false @@ -3499,7 +3685,11 @@ "solutionPreambleSize": 1, "solver": { "hash": "equihash", - "args": [ 96, 5, "ZcashPoW" ] + "args": [ + 96, + 5, + "ZcashPoW" + ] }, "coinbaseTxNetwork": "regtest", "payFoundersReward": false @@ -3511,7 +3701,6 @@ "explorerTxLink": "https://minexexplorer.com/transactions/view?hash={0}", "explorerAccountLink": "https://minexexplorer.com/address?hash={0}" }, - "veruscoin": { "name": "Veruscoin", "symbol": "VRSC", @@ -3528,7 +3717,11 @@ "solutionPreambleSize": 3, "solver": { "hash": "equihash", - "args": [ 200, 9, "Verushash" ] + "args": [ + 200, + 9, + "Verushash" + ] }, "coinbaseTxNetwork": "main", "payFoundersReward": false, @@ -3545,7 +3738,11 @@ "solutionPreambleSize": 3, "solver": { "hash": "equihash", - "args": [ 200, 9, "Verushash" ] + "args": [ + 200, + 9, + "Verushash" + ] }, "coinbaseTxNetwork": "testnet", "payFoundersReward": false @@ -3556,7 +3753,11 @@ "solutionPreambleSize": 3, "solver": { "hash": "equihash", - "args": [ 200, 9, "Verushash" ] + "args": [ + 200, + 9, + "Verushash" + ] }, "coinbaseTxNetwork": "regtest", "payFoundersReward": false @@ -3568,7 +3769,6 @@ "explorerTxLink": "https://explorer.veruscoin.io/tx/{0}", "explorerAccountLink": "https://explorer.veruscoin.io/address/{0}" }, - "zcash": { "name": "ZCash", "symbol": "ZEC", @@ -3585,7 +3785,11 @@ "solutionPreambleSize": 3, "solver": { "hash": "equihash", - "args": [ 200, 9, "ZcashPoW" ] + "args": [ + 200, + 9, + "ZcashPoW" + ] }, "coinbaseTxNetwork": "zcash-main", "payFoundersReward": true, @@ -3656,7 +3860,11 @@ "solutionPreambleSize": 3, "solver": { "hash": "equihash", - "args": [ 200, 9, "ZcashPoW" ] + "args": [ + 200, + 9, + "ZcashPoW" + ] }, "coinbaseTxNetwork": "zcash-test", "payFoundersReward": true, @@ -3727,12 +3935,18 @@ "solutionPreambleSize": 3, "solver": { "hash": "equihash", - "args": [ 200, 9, "ZcashPoW" ] + "args": [ + 200, + 9, + "ZcashPoW" + ] }, "coinbaseTxNetwork": "zcash-reg", "payFoundersReward": true, "percentFoundersReward": 20, - "foundersRewardAddresses": [ "t2FwcEhFdNXuFMv1tcYwaBJtYVtMj8b1uTg" ], + "foundersRewardAddresses": [ + "t2FwcEhFdNXuFMv1tcYwaBJtYVtMj8b1uTg" + ], "foundersRewardSubsidyHalvingInterval": 150 } }, @@ -3742,7 +3956,6 @@ "explorerTxLink": "https://explorer.zcha.in/transactions/{0}", "explorerAccountLink": "https://explorer.zcha.in/accounts/{0}" }, - "zclassic": { "name": "ZClassic", "symbol": "ZCL", @@ -3759,7 +3972,11 @@ "solutionPreambleSize": 3, "solver": { "hash": "equihash", - "args": [ 200, 9, "ZcashPoW" ] + "args": [ + 200, + 9, + "ZcashPoW" + ] }, "coinbaseTxNetwork": "main", "payFoundersReward": false @@ -3770,7 +3987,11 @@ "solutionPreambleSize": 3, "solver": { "hash": "equihash", - "args": [ 200, 9, "ZcashPoW" ] + "args": [ + 200, + 9, + "ZcashPoW" + ] }, "coinbaseTxNetwork": "testnet", "payFoundersReward": false @@ -3781,7 +4002,11 @@ "solutionPreambleSize": 3, "solver": { "hash": "equihash", - "args": [ 200, 9, "ZcashPoW" ] + "args": [ + 200, + 9, + "ZcashPoW" + ] }, "coinbaseTxNetwork": "regtest", "payFoundersReward": false @@ -3793,7 +4018,6 @@ "explorerTxLink": "http://explorer.zclmine.pro/transactions/{0}", "explorerAccountLink": "http://explorer.zclmine.pro/accounts/{0}" }, - "zencash": { "name": "Zencash", "symbol": "ZEN", @@ -3810,7 +4034,11 @@ "solutionPreambleSize": 3, "solver": { "hash": "equihash", - "args": [ 200, 9, "ZcashPoW" ] + "args": [ + 200, + 9, + "ZcashPoW" + ] }, "coinbaseTxNetwork": "main", "payFoundersReward": true, @@ -3883,7 +4111,11 @@ "solutionPreambleSize": 3, "solver": { "hash": "equihash", - "args": [ 200, 9, "ZcashPoW" ] + "args": [ + 200, + 9, + "ZcashPoW" + ] }, "coinbaseTxNetwork": "testnet", "payFoundersReward": true, @@ -3956,16 +4188,24 @@ "solutionPreambleSize": 3, "solver": { "hash": "equihash", - "args": [ 200, 9, "ZcashPoW" ] + "args": [ + 200, + 9, + "ZcashPoW" + ] }, "coinbaseTxNetwork": "regtest", "payFoundersReward": true, "percentFoundersReward": 8.5, - "foundersRewardAddresses": [ "zrKmSdqZKZjnARd5e8FfRg4v1m74X7twxGa" ], + "foundersRewardAddresses": [ + "zrKmSdqZKZjnARd5e8FfRg4v1m74X7twxGa" + ], "foundersRewardSubsidyHalvingInterval": 2000, "percentTreasuryReward": 12, "treasuryRewardStartBlockHeight": 139200, - "treasuryRewardAddresses": [ "zrKmSdqZKZjnARd5e8FfRg4v1m74X7twxGa" ], + "treasuryRewardAddresses": [ + "zrKmSdqZKZjnARd5e8FfRg4v1m74X7twxGa" + ], "treasuryRewardAddressChangeInterval": 100 } }, @@ -3975,7 +4215,6 @@ "explorerTxLink": "http://explorer.zensystem.io/transactions/{0}", "explorerAccountLink": "http://explorer.zensystem.io/accounts/{0}" }, - "monero": { "name": "Monero", "canonicalName": "Monero", @@ -4001,7 +4240,6 @@ "explorerBlockLink": "https://www.exploremonero.com/block/$height$", "explorerTxLink": "https://www.exploremonero.com/transaction/{0}" }, - "callisto": { "name": "Callisto Network", "canonicalName": "Callisto-Network", @@ -4019,7 +4257,6 @@ "explorerTxLink": "https://explorer.callisto.network/tx/{0}", "explorerAccountLink": "https://explorer.callisto.network/address/{0}" }, - "ethereum": { "name": "Ethereum", "canonicalName": "Ethereum", @@ -4037,7 +4274,6 @@ "explorerTxLink": "https://etherscan.io/tx/{0}", "explorerAccountLink": "https://etherscan.io/address/{0}" }, - "ethereum-pow": { "name": "EthereumPoW", "canonicalName": "EthereumPoW", @@ -4055,7 +4291,40 @@ "explorerTxLink": "https://www.oklink.com/en/ethw/tx/{0}", "explorerAccountLink": "https://www.oklink.com/en/ethw/address/{0}" }, - + "etherone": { + "name": "EtherOne", + "canonicalName": "EtherOne", + "symbol": "ETHONE", + "family": "ethereum", + "website": "https://etherone.one/", + "market": "", + "twitter": "https://twitter.com/EtherOneChain", + "telegram": "https://t.me/ether_one_blockchain", + "discord": "https://discord.com/invite/vF2SDb6Yz9", + "explorerBlockLinks": { + "block": "https://blockscout.etherone.one/block/$height$", + "uncle": "https://blockscout.etherone.one/uncles/$height$" + }, + "explorerTxLink": "https://blockscout.etherone.one/tx/{0}", + "explorerAccountLink": "https://blockscout.etherone.one/address/{0}" + }, + "pinkchain": { + "name": "PinkChain", + "canonicalName": "PinkChain", + "symbol": "PINK", + "family": "ethereum", + "website": "https://pinkchain.net/", + "market": "", + "twitter": "https://twitter.com/PinkchainNet", + "telegram": "https://t.me/PinkSmartChain", + "discord": "https://discord.gg/jzxrn5H4eQ", + "explorerBlockLinks": { + "block": "https://pinkscan.org/block/$height$", + "uncle": "https://pinkscan.org/uncle/$height$" + }, + "explorerTxLink": "https://pinkscan.org/tx/{0}", + "explorerAccountLink": "https://pinkscan.org/address/{0}" + }, "ergo": { "name": "Ergo", "canonicalName": "Ergo", diff --git a/src/Native/libcryptonight/Makefile b/src/Native/libcryptonight/Makefile index eb1d2fdc7..5d91ff233 100644 --- a/src/Native/libcryptonight/Makefile +++ b/src/Native/libcryptonight/Makefile @@ -8,7 +8,6 @@ OBJECTS = exports.o \ xmrig/crypto/cn/asm/cn_main_loop.o \ xmrig/crypto/cn/asm/CryptonightR_template.o \ xmrig/crypto/cn/r/CryptonightR_gen.o \ - xmrig/crypto/cn/gpu/cn_gpu_avx.o \ xmrig/crypto/cn/gpu/cn_gpu_ssse3.o \ xmrig-override/backend/cpu/platform/BasicCpuInfo.o \ \ diff --git a/src/Native/libcryptonight/xmrig/crypto/cn/CryptoNight_x86.h b/src/Native/libcryptonight/xmrig/crypto/cn/CryptoNight_x86.h index 8ad8be63f..c0063a87d 100644 --- a/src/Native/libcryptonight/xmrig/crypto/cn/CryptoNight_x86.h +++ b/src/Native/libcryptonight/xmrig/crypto/cn/CryptoNight_x86.h @@ -884,11 +884,15 @@ inline void cryptonight_single_hash_gpu(const uint8_t *__restrict__ input, size_ fesetround(FE_TONEAREST); # endif +#if true // OW: always use ssse3 to circumvent build problems with CN-GPU AVX impl on some linux systems without AVX2 support + cn_gpu_inner_ssse3(ctx[0]->state, ctx[0]->memory); +#else if (xmrig::Cpu::info()->hasAVX2()) { cn_gpu_inner_avx(ctx[0]->state, ctx[0]->memory); } else { cn_gpu_inner_ssse3(ctx[0]->state, ctx[0]->memory); } +#endif cn_implode_scratchpad(ctx[0]); keccakf(reinterpret_cast(ctx[0]->state), 24); diff --git a/src/Native/libmultihash/Makefile b/src/Native/libmultihash/Makefile index 301ed134a..d7f0618c9 100644 --- a/src/Native/libmultihash/Makefile +++ b/src/Native/libmultihash/Makefile @@ -21,7 +21,7 @@ OBJECTS = bcrypt.o blake.o c11.o dcrypt.o fresh.o lane.o \ equi/uint256.o equi/arith_uint256.o equi/crypto/hmac_sha512.o \ equi/crypto/sha1.o equi/crypto/sha512.o equi/crypto/sha256.o \ equi/crypto/hmac_sha256.o equi/crypto/equihash.o equi/crypto/ripemd160.o \ - equi/equihashverify.o + equi/equihashverify.o sha512_256.o sha256dt.o all: $(TARGET) diff --git a/src/Native/libmultihash/exports.cpp b/src/Native/libmultihash/exports.cpp index 6f0b76b54..715aaa763 100644 --- a/src/Native/libmultihash/exports.cpp +++ b/src/Native/libmultihash/exports.cpp @@ -49,6 +49,8 @@ SOFTWARE OR THE USE OR OTHER DEALINGS IN THE SOFTWARE. #include "x16rv2.h" #include "x21s.h" #include "sha256csm.h" +#include "sha512_256.h" +#include "sha256dt.h" #include "hmq17.h" #include "phi.h" #include "verthash/h2.h" @@ -269,6 +271,16 @@ extern "C" MODULE_API void x22i_export(const char* input, char* output, uint32_t x22i_hash(input, output, input_len); } +extern "C" MODULE_API void sha512_256_export(const unsigned char* input, unsigned char* output, uint32_t input_len) +{ + sha512_256(input, input_len, output); +} + +extern "C" MODULE_API void sha256dt_export(const char* input, char* output) +{ + sha256dt_hash(input, output); +} + extern "C" MODULE_API int verthash_init_export(const char* filename, int createIfMissing) { return verthash_init(filename, createIfMissing); diff --git a/src/Native/libmultihash/libmultihash.vcxproj b/src/Native/libmultihash/libmultihash.vcxproj index 26ac068e3..c7f34bc94 100644 --- a/src/Native/libmultihash/libmultihash.vcxproj +++ b/src/Native/libmultihash/libmultihash.vcxproj @@ -262,6 +262,7 @@ + @@ -312,6 +313,7 @@ + @@ -356,6 +358,7 @@ MaxSpeed + @@ -364,4 +367,4 @@ - \ No newline at end of file + diff --git a/src/Native/libmultihash/libmultihash.vcxproj.filters b/src/Native/libmultihash/libmultihash.vcxproj.filters index ab407216e..0ee5ca16d 100644 --- a/src/Native/libmultihash/libmultihash.vcxproj.filters +++ b/src/Native/libmultihash/libmultihash.vcxproj.filters @@ -98,6 +98,9 @@ Header Files + + Header Files + Header Files @@ -293,6 +296,12 @@ Header Files + + Header Files + + + Header Files + @@ -565,9 +574,15 @@ Source Files + + Source Files + + + Source Files + - \ No newline at end of file + diff --git a/src/Native/libmultihash/sha256dt.c b/src/Native/libmultihash/sha256dt.c new file mode 100644 index 000000000..39d313803 --- /dev/null +++ b/src/Native/libmultihash/sha256dt.c @@ -0,0 +1,23 @@ +#include +#include +#include +#include + +#include "sha256.h" +#include "sha256t.h" + +#include + +void sha256dt_hash(const char* input, char* output) +{ + char temp[32]; + + SHA256_CTX ctx; + SHA256t_Init(&ctx); + SHA256_Update(&ctx, input, 80); + SHA256_Final((unsigned char*) &temp, &ctx); + + SHA256t_Init(&ctx); + SHA256_Update(&ctx, &temp, 32); + SHA256_Final((unsigned char*) output, &ctx); +} diff --git a/src/Native/libmultihash/sha256dt.h b/src/Native/libmultihash/sha256dt.h new file mode 100644 index 000000000..44cf9d92b --- /dev/null +++ b/src/Native/libmultihash/sha256dt.h @@ -0,0 +1,14 @@ +#ifndef SHA256DT_H +#define SHA256DT_H + +#ifdef __cplusplus +extern "C" { +#endif + +void sha256dt_hash(const char* input, char* output); + +#ifdef __cplusplus +} +#endif + +#endif diff --git a/src/Native/libmultihash/sha256t.h b/src/Native/libmultihash/sha256t.h new file mode 100644 index 000000000..69234d37b --- /dev/null +++ b/src/Native/libmultihash/sha256t.h @@ -0,0 +1,20 @@ +#ifndef SHA256T_H +#define SHA256T_H + +#include "sha256.h" + +static void +SHA256t_Init(SHA256_CTX * ctx) +{ + ctx->count[0] = 0; + ctx->count[1] = 512; + ctx->state[0] = 0xDFA9BF2C; + ctx->state[1] = 0xB72074D4; + ctx->state[2] = 0x6BB01122; + ctx->state[3] = 0xD338E869; + ctx->state[4] = 0xAA3FF126; + ctx->state[5] = 0x475BBF30; + ctx->state[6] = 0x8FD52E5B; + ctx->state[7] = 0x9F75C9AD; +} +#endif diff --git a/src/Native/libmultihash/sha512_256.c b/src/Native/libmultihash/sha512_256.c new file mode 100644 index 000000000..715030bbd --- /dev/null +++ b/src/Native/libmultihash/sha512_256.c @@ -0,0 +1,365 @@ +/* + * FIPS 180-2 SHA-224/256/384/512 implementation + * Newest update: 30/05/2022 + * Last update: 02/02/2007 + * Issue date: 04/30/2005 + * + * Copyright (C) 2022, The Radiant Blockchain Developers + * Copyright (C) 2013, Con Kolivas + * Copyright (C) 2005, 2007 Olivier Gay + * All rights reserved. + * + * Redistribution and use in source and binary forms, with or without + * modification, are permitted provided that the following conditions + * are met: + * 1. Redistributions of source code must retain the above copyright + * notice, this list of conditions and the following disclaimer. + * 2. Redistributions in binary form must reproduce the above copyright + * notice, this list of conditions and the following disclaimer in the + * documentation and/or other materials provided with the distribution. + * 3. Neither the name of the project nor the names of its contributors + * may be used to endorse or promote products derived from this software + * without specific prior written permission. + * + * THIS SOFTWARE IS PROVIDED BY THE PROJECT AND CONTRIBUTORS ``AS IS'' AND + * ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT LIMITED TO, THE + * IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS FOR A PARTICULAR PURPOSE + * ARE DISCLAIMED. IN NO EVENT SHALL THE PROJECT OR CONTRIBUTORS BE LIABLE + * FOR ANY DIRECT, INDIRECT, INCIDENTAL, SPECIAL, EXEMPLARY, OR CONSEQUENTIAL + * DAMAGES (INCLUDING, BUT NOT LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS + * OR SERVICES; LOSS OF USE, DATA, OR PROFITS; OR BUSINESS INTERRUPTION) + * HOWEVER CAUSED AND ON ANY THEORY OF LIABILITY, WHETHER IN CONTRACT, STRICT + * LIABILITY, OR TORT (INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY + * OUT OF THE USE OF THIS SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF + * SUCH DAMAGE. + */ +#if 0 +#define UNROLL_LOOPS /* Enable loops unrolling */ +#endif +#include +#include + +#include "sha512_256.h" + +#define SHFR(x, n) (x >> n) +#define ROTR(x, n) ((x >> n) | (x << ((sizeof(x) << 3) - n))) +#define ROTL(x, n) ((x << n) | (x >> ((sizeof(x) << 3) - n))) +#define CH(x, y, z) ((x & y) ^ (~x & z)) +#define MAJ(x, y, z) ((x & y) ^ (x & z) ^ (y & z)) + +#define SHA512_F1(x) (ROTR(x, 28) ^ ROTR(x, 34) ^ ROTR(x, 39)) +#define SHA512_F2(x) (ROTR(x, 14) ^ ROTR(x, 18) ^ ROTR(x, 41)) +#define SHA512_F3(x) (ROTR(x, 1) ^ ROTR(x, 8) ^ SHFR(x, 7)) +#define SHA512_F4(x) (ROTR(x, 19) ^ ROTR(x, 61) ^ SHFR(x, 6)) + +#define UNPACK32(x, str) \ +{ \ + *((str) + 3) = (uint8_t) ((x) ); \ + *((str) + 2) = (uint8_t) ((x) >> 8); \ + *((str) + 1) = (uint8_t) ((x) >> 16); \ + *((str) + 0) = (uint8_t) ((x) >> 24); \ +} + +#define PACK32(str, x) \ +{ \ + *(x) = ((uint32_t) *((str) + 3) ) \ + | ((uint32_t) *((str) + 2) << 8) \ + | ((uint32_t) *((str) + 1) << 16) \ + | ((uint32_t) *((str) + 0) << 24); \ +} + +#define UNPACK64(x, str) \ +{ \ + *((str) + 7) = (uint8_t) ((x) ); \ + *((str) + 6) = (uint8_t) ((x) >> 8); \ + *((str) + 5) = (uint8_t) ((x) >> 16); \ + *((str) + 4) = (uint8_t) ((x) >> 24); \ + *((str) + 3) = (uint8_t) ((x) >> 32); \ + *((str) + 2) = (uint8_t) ((x) >> 40); \ + *((str) + 1) = (uint8_t) ((x) >> 48); \ + *((str) + 0) = (uint8_t) ((x) >> 56); \ +} + +#define PACK64(str, x) \ +{ \ + *(x) = ((uint64_t) *((str) + 7) ) \ + | ((uint64_t) *((str) + 6) << 8) \ + | ((uint64_t) *((str) + 5) << 16) \ + | ((uint64_t) *((str) + 4) << 24) \ + | ((uint64_t) *((str) + 3) << 32) \ + | ((uint64_t) *((str) + 2) << 40) \ + | ((uint64_t) *((str) + 1) << 48) \ + | ((uint64_t) *((str) + 0) << 56); \ +} + +/* Macros used for loops unrolling */ + +#define SHA512_SCR(i) \ +{ \ + w[i] = SHA512_F4(w[i - 2]) + w[i - 7] \ + + SHA512_F3(w[i - 15]) + w[i - 16]; \ +} + +#define SHA512_EXP(a, b, c, d, e, f, g ,h, j) \ +{ \ + t1 = wv[h] + SHA512_F2(wv[e]) + CH(wv[e], wv[f], wv[g]) \ + + sha512_k[j] + w[j]; \ + t2 = SHA512_F1(wv[a]) + MAJ(wv[a], wv[b], wv[c]); \ + wv[d] += t1; \ + wv[h] = t1 + t2; \ +} + +// The IV initial for sha512/256 is different than normal sha512 +uint64_t sha512_256_h0[8] = + {0x22312194FC2BF72CULL, 0x9F555FA3C84C64C2ULL, + 0x2393B86B6F53B151ULL, 0x963877195940EABDULL, + 0x96283EE2A88EFFE3ULL, 0xBE5E1E2553863992ULL, + 0x2B0199FC2C85B8AAULL, 0x0EB72DDC81C52CA2ULL}; + +uint64_t sha512_k[80] = + {0x428a2f98d728ae22ULL, 0x7137449123ef65cdULL, + 0xb5c0fbcfec4d3b2fULL, 0xe9b5dba58189dbbcULL, + 0x3956c25bf348b538ULL, 0x59f111f1b605d019ULL, + 0x923f82a4af194f9bULL, 0xab1c5ed5da6d8118ULL, + 0xd807aa98a3030242ULL, 0x12835b0145706fbeULL, + 0x243185be4ee4b28cULL, 0x550c7dc3d5ffb4e2ULL, + 0x72be5d74f27b896fULL, 0x80deb1fe3b1696b1ULL, + 0x9bdc06a725c71235ULL, 0xc19bf174cf692694ULL, + 0xe49b69c19ef14ad2ULL, 0xefbe4786384f25e3ULL, + 0x0fc19dc68b8cd5b5ULL, 0x240ca1cc77ac9c65ULL, + 0x2de92c6f592b0275ULL, 0x4a7484aa6ea6e483ULL, + 0x5cb0a9dcbd41fbd4ULL, 0x76f988da831153b5ULL, + 0x983e5152ee66dfabULL, 0xa831c66d2db43210ULL, + 0xb00327c898fb213fULL, 0xbf597fc7beef0ee4ULL, + 0xc6e00bf33da88fc2ULL, 0xd5a79147930aa725ULL, + 0x06ca6351e003826fULL, 0x142929670a0e6e70ULL, + 0x27b70a8546d22ffcULL, 0x2e1b21385c26c926ULL, + 0x4d2c6dfc5ac42aedULL, 0x53380d139d95b3dfULL, + 0x650a73548baf63deULL, 0x766a0abb3c77b2a8ULL, + 0x81c2c92e47edaee6ULL, 0x92722c851482353bULL, + 0xa2bfe8a14cf10364ULL, 0xa81a664bbc423001ULL, + 0xc24b8b70d0f89791ULL, 0xc76c51a30654be30ULL, + 0xd192e819d6ef5218ULL, 0xd69906245565a910ULL, + 0xf40e35855771202aULL, 0x106aa07032bbd1b8ULL, + 0x19a4c116b8d2d0c8ULL, 0x1e376c085141ab53ULL, + 0x2748774cdf8eeb99ULL, 0x34b0bcb5e19b48a8ULL, + 0x391c0cb3c5c95a63ULL, 0x4ed8aa4ae3418acbULL, + 0x5b9cca4f7763e373ULL, 0x682e6ff3d6b2b8a3ULL, + 0x748f82ee5defb2fcULL, 0x78a5636f43172f60ULL, + 0x84c87814a1f0ab72ULL, 0x8cc702081a6439ecULL, + 0x90befffa23631e28ULL, 0xa4506cebde82bde9ULL, + 0xbef9a3f7b2c67915ULL, 0xc67178f2e372532bULL, + 0xca273eceea26619cULL, 0xd186b8c721c0c207ULL, + 0xeada7dd6cde0eb1eULL, 0xf57d4f7fee6ed178ULL, + 0x06f067aa72176fbaULL, 0x0a637dc5a2c898a6ULL, + 0x113f9804bef90daeULL, 0x1b710b35131c471bULL, + 0x28db77f523047d84ULL, 0x32caab7b40c72493ULL, + 0x3c9ebe0a15c9bebcULL, 0x431d67c49c100d4cULL, + 0x4cc5d4becb3e42b6ULL, 0x597f299cfc657e2aULL, + 0x5fcb6fab3ad6faecULL, 0x6c44198c4a475817ULL}; + +/* SHA-512 functions */ + +void sha512_transf(sha512_ctx *ctx, const unsigned char *message, + unsigned int block_nb) +{ + uint64_t w[80]; + uint64_t wv[8]; + uint64_t t1, t2; + const unsigned char *sub_block; + int i, j; + + for (i = 0; i < (int) block_nb; i++) { + sub_block = message + (i << 7); + +#ifndef UNROLL_LOOPS + for (j = 0; j < 16; j++) { + PACK64(&sub_block[j << 3], &w[j]); + } + + for (j = 16; j < 80; j++) { + SHA512_SCR(j); + } + + for (j = 0; j < 8; j++) { + wv[j] = ctx->h[j]; + } + + for (j = 0; j < 80; j++) { + t1 = wv[7] + SHA512_F2(wv[4]) + CH(wv[4], wv[5], wv[6]) + + sha512_k[j] + w[j]; + t2 = SHA512_F1(wv[0]) + MAJ(wv[0], wv[1], wv[2]); + wv[7] = wv[6]; + wv[6] = wv[5]; + wv[5] = wv[4]; + wv[4] = wv[3] + t1; + wv[3] = wv[2]; + wv[2] = wv[1]; + wv[1] = wv[0]; + wv[0] = t1 + t2; + } + + for (j = 0; j < 8; j++) { + ctx->h[j] += wv[j]; + } +#else + PACK64(&sub_block[ 0], &w[ 0]); PACK64(&sub_block[ 8], &w[ 1]); + PACK64(&sub_block[ 16], &w[ 2]); PACK64(&sub_block[ 24], &w[ 3]); + PACK64(&sub_block[ 32], &w[ 4]); PACK64(&sub_block[ 40], &w[ 5]); + PACK64(&sub_block[ 48], &w[ 6]); PACK64(&sub_block[ 56], &w[ 7]); + PACK64(&sub_block[ 64], &w[ 8]); PACK64(&sub_block[ 72], &w[ 9]); + PACK64(&sub_block[ 80], &w[10]); PACK64(&sub_block[ 88], &w[11]); + PACK64(&sub_block[ 96], &w[12]); PACK64(&sub_block[104], &w[13]); + PACK64(&sub_block[112], &w[14]); PACK64(&sub_block[120], &w[15]); + + SHA512_SCR(16); SHA512_SCR(17); SHA512_SCR(18); SHA512_SCR(19); + SHA512_SCR(20); SHA512_SCR(21); SHA512_SCR(22); SHA512_SCR(23); + SHA512_SCR(24); SHA512_SCR(25); SHA512_SCR(26); SHA512_SCR(27); + SHA512_SCR(28); SHA512_SCR(29); SHA512_SCR(30); SHA512_SCR(31); + SHA512_SCR(32); SHA512_SCR(33); SHA512_SCR(34); SHA512_SCR(35); + SHA512_SCR(36); SHA512_SCR(37); SHA512_SCR(38); SHA512_SCR(39); + SHA512_SCR(40); SHA512_SCR(41); SHA512_SCR(42); SHA512_SCR(43); + SHA512_SCR(44); SHA512_SCR(45); SHA512_SCR(46); SHA512_SCR(47); + SHA512_SCR(48); SHA512_SCR(49); SHA512_SCR(50); SHA512_SCR(51); + SHA512_SCR(52); SHA512_SCR(53); SHA512_SCR(54); SHA512_SCR(55); + SHA512_SCR(56); SHA512_SCR(57); SHA512_SCR(58); SHA512_SCR(59); + SHA512_SCR(60); SHA512_SCR(61); SHA512_SCR(62); SHA512_SCR(63); + SHA512_SCR(64); SHA512_SCR(65); SHA512_SCR(66); SHA512_SCR(67); + SHA512_SCR(68); SHA512_SCR(69); SHA512_SCR(70); SHA512_SCR(71); + SHA512_SCR(72); SHA512_SCR(73); SHA512_SCR(74); SHA512_SCR(75); + SHA512_SCR(76); SHA512_SCR(77); SHA512_SCR(78); SHA512_SCR(79); + + wv[0] = ctx->h[0]; wv[1] = ctx->h[1]; + wv[2] = ctx->h[2]; wv[3] = ctx->h[3]; + wv[4] = ctx->h[4]; wv[5] = ctx->h[5]; + wv[6] = ctx->h[6]; wv[7] = ctx->h[7]; + + j = 0; + + do { + SHA512_EXP(0,1,2,3,4,5,6,7,j); j++; + SHA512_EXP(7,0,1,2,3,4,5,6,j); j++; + SHA512_EXP(6,7,0,1,2,3,4,5,j); j++; + SHA512_EXP(5,6,7,0,1,2,3,4,j); j++; + SHA512_EXP(4,5,6,7,0,1,2,3,j); j++; + SHA512_EXP(3,4,5,6,7,0,1,2,j); j++; + SHA512_EXP(2,3,4,5,6,7,0,1,j); j++; + SHA512_EXP(1,2,3,4,5,6,7,0,j); j++; + } while (j < 80); + + ctx->h[0] += wv[0]; ctx->h[1] += wv[1]; + ctx->h[2] += wv[2]; ctx->h[3] += wv[3]; + ctx->h[4] += wv[4]; ctx->h[5] += wv[5]; + ctx->h[6] += wv[6]; ctx->h[7] += wv[7]; +#endif /* !UNROLL_LOOPS */ + } +} + +void sha512_256(const unsigned char *message, unsigned int len, + unsigned char *digest) +{ + sha512_256_ctx ctx; + + sha512_256_init(&ctx); + sha512_256_update(&ctx, message, len); + sha512_256_final(&ctx, digest); +} + +// docker run -d --privileged --name docker -e DOCKER_TLS_CERTDIR=/certs -v docker-certs-ca:/certs/ca -v docker-certs-client:/certs/client docker:dind +void sha512_256_init(sha512_256_ctx *ctx) +{ +#ifndef UNROLL_LOOPS + int i; + for (i = 0; i < 8; i++) { + ctx->h[i] = sha512_256_h0[i]; + } +#else + ctx->h[0] = sha512_256_h0[0]; ctx->h[1] = sha512_256_h0[1]; + ctx->h[2] = sha512_256_h0[2]; ctx->h[3] = sha512_256_h0[3]; + ctx->h[4] = sha512_256_h0[4]; ctx->h[5] = sha512_256_h0[5]; + ctx->h[6] = sha512_256_h0[6]; ctx->h[7] = sha512_256_h0[7]; +#endif /* !UNROLL_LOOPS */ + + ctx->len = 0; + ctx->tot_len = 0; +} + +void sha512_256_update(sha512_256_ctx *ctx, const unsigned char *message, + unsigned int len) +{ + unsigned int block_nb; + unsigned int new_len, rem_len, tmp_len; + const unsigned char *shifted_message; + + tmp_len = SHA512_BLOCK_SIZE - ctx->len; + rem_len = len < tmp_len ? len : tmp_len; + + memcpy(&ctx->block[ctx->len], message, rem_len); + + if (ctx->len + len < SHA512_BLOCK_SIZE) { + ctx->len += len; + return; + } + + new_len = len - rem_len; + block_nb = new_len / SHA512_BLOCK_SIZE; + + shifted_message = message + rem_len; + + sha512_transf(ctx, ctx->block, 1); + sha512_transf(ctx, shifted_message, block_nb); + + rem_len = new_len % SHA512_BLOCK_SIZE; + + memcpy(ctx->block, &shifted_message[block_nb << 7], + rem_len); + + ctx->len = rem_len; + ctx->tot_len += (block_nb + 1) << 7; +} + +void sha512_256_final(sha512_256_ctx *ctx, unsigned char *digest) +{ + unsigned int block_nb; + unsigned int pm_len; + unsigned int len_b; + +#ifndef UNROLL_LOOPS + int i; +#endif + + block_nb = 1 + ((SHA512_BLOCK_SIZE - 17) + < (ctx->len % SHA512_BLOCK_SIZE)); + + len_b = (ctx->tot_len + ctx->len) << 3; + pm_len = block_nb << 7; + + memset(ctx->block + ctx->len, 0, pm_len - ctx->len); + ctx->block[ctx->len] = 0x80; + UNPACK32(len_b, ctx->block + pm_len - 4); + + sha512_transf(ctx, ctx->block, block_nb); + +// Sha512/256 is basically sha512 except we take only the left most 256 bits +// If loops are defined, then take the first 4 chunks (not 8) +#ifndef UNROLL_LOOPS + for (i = 0 ; i < 4; i++) { + UNPACK64(ctx->h[i], &digest[i << 3]); + } +#else + UNPACK64(ctx->h[0], &digest[ 0]); + UNPACK64(ctx->h[1], &digest[ 8]); + UNPACK64(ctx->h[2], &digest[16]); + UNPACK64(ctx->h[3], &digest[24]); + + // Sha512/256 is basically sha512 except we take only the left most 256 bits + // Regular sha512 takes the full 64 bits + /* + UNPACK64(ctx->h[4], &digest[32]); + UNPACK64(ctx->h[5], &digest[40]); + UNPACK64(ctx->h[6], &digest[48]); + UNPACK64(ctx->h[7], &digest[56]); + */ + +#endif /* !UNROLL_LOOPS */ +} diff --git a/src/Native/libmultihash/sha512_256.h b/src/Native/libmultihash/sha512_256.h new file mode 100644 index 000000000..01996ad2e --- /dev/null +++ b/src/Native/libmultihash/sha512_256.h @@ -0,0 +1,79 @@ +/* + * FIPS 180-2 SHA-224/256/384/512 implementation + * Last update: 02/02/2007 + * Issue date: 04/30/2005 + * + * Copyright (C) 2022, The Radiant Blockchain Developers + * Copyright (C) 2013, Con Kolivas + * Copyright (C) 2005, 2007 Olivier Gay + * All rights reserved. + * + * Redistribution and use in source and binary forms, with or without + * modification, are permitted provided that the following conditions + * are met: + * 1. Redistributions of source code must retain the above copyright + * notice, this list of conditions and the following disclaimer. + * 2. Redistributions in binary form must reproduce the above copyright + * notice, this list of conditions and the following disclaimer in the + * documentation and/or other materials provided with the distribution. + * 3. Neither the name of the project nor the names of its contributors + * may be used to endorse or promote products derived from this software + * without specific prior written permission. + * + * THIS SOFTWARE IS PROVIDED BY THE PROJECT AND CONTRIBUTORS ``AS IS'' AND + * ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT LIMITED TO, THE + * IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS FOR A PARTICULAR PURPOSE + * ARE DISCLAIMED. IN NO EVENT SHALL THE PROJECT OR CONTRIBUTORS BE LIABLE + * FOR ANY DIRECT, INDIRECT, INCIDENTAL, SPECIAL, EXEMPLARY, OR CONSEQUENTIAL + * DAMAGES (INCLUDING, BUT NOT LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS + * OR SERVICES; LOSS OF USE, DATA, OR PROFITS; OR BUSINESS INTERRUPTION) + * HOWEVER CAUSED AND ON ANY THEORY OF LIABILITY, WHETHER IN CONTRACT, STRICT + * LIABILITY, OR TORT (INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY + * OUT OF THE USE OF THIS SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF + * SUCH DAMAGE. + */ + +#include + +#ifndef SHA2_H +#define SHA2_H + +#define SHA512_BLOCK_SIZE (1024 / 8) + +#define SHFR(x, n) (x >> n) +#define ROTR(x, n) ((x >> n) | (x << ((sizeof(x) << 3) - n))) +#define CH(x, y, z) ((x & y) ^ (~x & z)) +#define MAJ(x, y, z) ((x & y) ^ (x & z) ^ (y & z)) + +//#ifndef SHA2_TYPES +//#define SHA2_TYPES +//typedef unsigned char uint8_t; +//typedef unsigned int uint32_t; +//typedef unsigned long long uint64_t; +//#endif + +#ifdef __cplusplus +extern "C" { +#endif + +typedef struct { + unsigned int tot_len; + unsigned int len; + unsigned char block[2 * SHA512_BLOCK_SIZE]; + uint64_t h[8]; +} sha512_ctx; + +typedef sha512_ctx sha512_256_ctx; + +void sha512_256_init(sha512_ctx *ctx); +void sha512_256_update(sha512_ctx *ctx, const unsigned char *message, + unsigned int len); +void sha512_256_final(sha512_ctx *ctx, unsigned char *digest); +void sha512_256(const unsigned char *message, unsigned int len, + unsigned char *digest); + +#ifdef __cplusplus +} +#endif + +#endif /* !SHA2_H */