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

Commit

Permalink
Dev (#252)
Browse files Browse the repository at this point in the history
* Don't enforce daemon owning pool wallet if payment-processing is disabled
* Persistence configuration is optional if payment-processing is disabled and the pool is in relay-mode
* Share relay config
* Dummy persistence
* Bitcoin ZMQ block notify topic is now configurable
* Share relay connect option
* BTCP explorer links
* ZCash & BTCP PowLimit configuration
* Block effort calc
* Fix BTCP hashrate hack
* Blockinfo API results
* Increase write throuput of share db inserts
* Monero double transfer RPC failure response handling
  • Loading branch information
Oliver Weichhold authored Mar 10, 2018
1 parent 84740ae commit df5ecf2
Show file tree
Hide file tree
Showing 40 changed files with 344 additions and 138 deletions.
8 changes: 7 additions & 1 deletion src/MiningCore/Api/ApiServer.cs
Original file line number Diff line number Diff line change
Expand Up @@ -21,6 +21,7 @@ SOFTWARE OR THE USE OR OTHER DEALINGS IN THE SOFTWARE.
using System;
using System.Collections.Generic;
using System.Data;
using System.Globalization;
using System.IO;
using System.Linq;
using System.Net;
Expand Down Expand Up @@ -361,7 +362,12 @@ private async Task PagePoolBlocksPagedAsync(HttpContext context, Match m)
blockInfobaseDict.TryGetValue(!string.IsNullOrEmpty(block.Type) ? block.Type : string.Empty, out var blockInfobaseUrl);

if (!string.IsNullOrEmpty(blockInfobaseUrl))
block.InfoLink = string.Format(blockInfobaseUrl, block.BlockHeight);
{
if(blockInfobaseUrl.Contains(CoinMetaData.BlockHeightPH))
block.InfoLink = blockInfobaseUrl.Replace(CoinMetaData.BlockHeightPH, block.BlockHeight.ToString(CultureInfo.InvariantCulture));
else if(blockInfobaseUrl.Contains(CoinMetaData.BlockHashPH) && !string.IsNullOrEmpty(block.Hash))
block.InfoLink = blockInfobaseUrl.Replace(CoinMetaData.BlockHashPH, block.Hash);
}
}
}

Expand Down
1 change: 1 addition & 0 deletions src/MiningCore/Api/Responses/GetBlocksResponse.cs
Original file line number Diff line number Diff line change
Expand Up @@ -33,6 +33,7 @@ public class Block
public string TransactionConfirmationData { get; set; }
public decimal Reward { get; set; }
public string InfoLink { get; set; }
public string Hash { get; set; }
public DateTime Created { get; set; }
}
}
1 change: 1 addition & 0 deletions src/MiningCore/AutoMapperProfile.cs
Original file line number Diff line number Diff line change
Expand Up @@ -38,6 +38,7 @@ public AutoMapperProfile()

CreateMap<IShare, Block>()
.ForMember(dest => dest.Reward, opt => opt.MapFrom(src => src.BlockReward))
.ForMember(dest => dest.Hash, opt => opt.MapFrom(src => src.BlockHash))
.ForMember(dest => dest.Status, opt => opt.Ignore());

CreateMap<BlockStatus, string>().ConvertUsing(e => e.ToString().ToLower());
Expand Down
10 changes: 10 additions & 0 deletions src/MiningCore/Blockchain/Abstractions.cs
Original file line number Diff line number Diff line change
Expand Up @@ -70,6 +70,11 @@ public interface IShare
/// </summary>
string IpAddress { get; }

/// <summary>
/// Submission source (pool, external stratum etc)
/// </summary>
string Source { get; set; }

/// <summary>
/// Stratum difficulty assigned to the miner at the time the share was submitted/accepted (used for payout
/// calculations)
Expand All @@ -86,6 +91,11 @@ public interface IShare
/// </summary>
decimal BlockReward { get; set; }

/// <summary>
/// Block hash
/// </summary>
string BlockHash { get; set; }

/// <summary>
/// If this share presumably resulted in a block
/// </summary>
Expand Down
21 changes: 16 additions & 5 deletions src/MiningCore/Blockchain/Bitcoin/BitcoinJobManager.cs
Original file line number Diff line number Diff line change
Expand Up @@ -100,7 +100,7 @@ public BitcoinJobManager(

protected virtual void SetupJobUpdates()
{
if (!poolConfig.EnableInternalStratum)
if (poolConfig.EnableInternalStratum == false)
return;

jobRebroadcastTimeout = TimeSpan.FromSeconds(Math.Max(1, poolConfig.JobRebroadcastTimeout));
Expand All @@ -111,13 +111,21 @@ protected virtual void SetupJobUpdates()
// collect ports
var zmq = poolConfig.Daemons
.Where(x => !string.IsNullOrEmpty(x.Extra.SafeExtensionDataAs<BitcoinDaemonEndpointConfigExtra>()?.ZmqBlockNotifySocket))
.ToDictionary(x => x, x => x.Extra.SafeExtensionDataAs<BitcoinDaemonEndpointConfigExtra>().ZmqBlockNotifySocket);
.ToDictionary(x => x, x =>
{
var extra = x.Extra.SafeExtensionDataAs<BitcoinDaemonEndpointConfigExtra>();
var topic = !string.IsNullOrEmpty(extra.ZmqBlockNotifyTopic) ?
extra.ZmqBlockNotifyTopic :
BitcoinConstants.ZmqPublisherTopicBlockHash;

return (Socket: extra.ZmqBlockNotifySocket, Topic: topic);
});

if (zmq.Count > 0)
{
logger.Info(() => $"[{LogCat}] Subscribing to ZMQ push-updates from {string.Join(", ", zmq.Values)}");

var newJobsPubSub = daemon.ZmqSubscribe(zmq, BitcoinConstants.ZmqPublisherTopicBlockHash, 2)
var newJobsPubSub = daemon.ZmqSubscribe(zmq, 2)
.Select(frames =>
{
try
Expand Down Expand Up @@ -380,6 +388,8 @@ private async Task UpdateNetworkStatsLegacyAsync()

#region API-Surface

public BitcoinNetworkType NetworkType => networkType;

public IObservable<object> Jobs { get; private set; }

public virtual async Task<bool> ValidateAddressAsync(string address)
Expand Down Expand Up @@ -508,6 +518,7 @@ public virtual async Task<BitcoinShare> SubmitShareAsync(StratumClient worker, o
share.Miner = minerName;
share.Worker = workerName;
share.UserAgent = context.UserAgent;
share.Source = clusterConfig.ClusterName;
share.Created = clock.Now;

return share;
Expand All @@ -525,7 +536,7 @@ public virtual async Task<BitcoinShare> SubmitShareAsync(StratumClient worker, o
public override void Configure(PoolConfig poolConfig, ClusterConfig clusterConfig)
{
extraPoolConfig = poolConfig.Extra.SafeExtensionDataAs<BitcoinPoolConfigExtra>();
extraPoolPaymentProcessingConfig = poolConfig.PaymentProcessing.Extra.SafeExtensionDataAs<BitcoinPoolPaymentProcessingConfigExtra>();
extraPoolPaymentProcessingConfig = poolConfig.PaymentProcessing?.Extra?.SafeExtensionDataAs<BitcoinPoolPaymentProcessingConfigExtra>();

if (extraPoolConfig?.MaxActiveJobs.HasValue == true)
maxActiveJobs = extraPoolConfig.MaxActiveJobs.Value;
Expand Down Expand Up @@ -631,7 +642,7 @@ protected override async Task PostStartInitAsync()
if (!validateAddressResponse.IsValid)
logger.ThrowLogPoolStartupException($"Daemon reports pool-address '{poolConfig.Address}' as invalid", LogCat);

if (!validateAddressResponse.IsMine)
if (clusterConfig.PaymentProcessing?.Enabled == true && !validateAddressResponse.IsMine)
logger.ThrowLogPoolStartupException($"Daemon does not own pool-address '{poolConfig.Address}'", LogCat);

isPoS = difficultyResponse.Values().Any(x => x.Path == "proof-of-stake");
Expand Down
2 changes: 1 addition & 1 deletion src/MiningCore/Blockchain/Bitcoin/BitcoinPoolBase.cs
Original file line number Diff line number Diff line change
Expand Up @@ -287,7 +287,7 @@ protected override async Task SetupJobManager()

await manager.StartAsync();

if (poolConfig.EnableInternalStratum)
if (poolConfig.EnableInternalStratum == true)
{
disposables.Add(manager.Jobs.Subscribe(OnNewJob));

Expand Down
1 change: 0 additions & 1 deletion src/MiningCore/Blockchain/Bitcoin/BitcoinShare.cs
Original file line number Diff line number Diff line change
Expand Up @@ -23,6 +23,5 @@ namespace MiningCore.Blockchain.Bitcoin
public class BitcoinShare : ShareBase
{
public string BlockHex { get; set; }
public string BlockHash { get; set; }
}
}
Original file line number Diff line number Diff line change
Expand Up @@ -29,5 +29,11 @@ public class BitcoinDaemonEndpointConfigExtra
/// Should match the value of -zmqpubhashblock daemon start parameter
/// </summary>
public string ZmqBlockNotifySocket { get; set; }

/// <summary>
/// Optional: ZeroMQ block notify topic
/// Defaults to "hashblock" if left blank
/// </summary>
public string ZmqBlockNotifyTopic { get; set; }
}
}
5 changes: 4 additions & 1 deletion src/MiningCore/Blockchain/BitcoinGold/BitcoinGoldJob.cs
Original file line number Diff line number Diff line change
Expand Up @@ -97,9 +97,12 @@ public override void Init(ZCashBlockTemplate blockTemplate, string jobId,
this.poolAddressDestination = poolAddressDestination;
this.networkType = networkType;

if (ZCashConstants.CoinbaseTxConfig.TryGetValue(poolConfig.Coin.Type, out var coinbaseTx))
coinbaseTx.TryGetValue(networkType, out coinbaseTxConfig);

BlockTemplate = blockTemplate;
JobId = jobId;
Difficulty = (double)new BigRational(ZCashConstants.Diff1b, BlockTemplate.Target.HexToByteArray().ToBigInteger());
Difficulty = (double)new BigRational(coinbaseTxConfig.Diff1b, BlockTemplate.Target.HexToByteArray().ToBigInteger());

this.isPoS = isPoS;
this.shareMultiplier = shareMultiplier;
Expand Down
59 changes: 32 additions & 27 deletions src/MiningCore/Blockchain/CoinMetaData.cs
Original file line number Diff line number Diff line change
Expand Up @@ -8,43 +8,47 @@ namespace MiningCore.Blockchain
{
public static class CoinMetaData
{
public const string BlockHeightPH = "$height$";
public const string BlockHashPH = "$hash$";

public static readonly Dictionary<CoinType, Dictionary<string, string>> BlockInfoLinks = new Dictionary<CoinType, Dictionary<string, string>>
{
{ CoinType.ETH, new Dictionary<string, string>
{
{ string.Empty, "https://etherscan.io/block/{0}" },
{ EthereumConstants.BlockTypeUncle, "https://etherscan.io/uncle/{0}" },
{ string.Empty, $"https://etherscan.io/block/{BlockHeightPH}" },
{ EthereumConstants.BlockTypeUncle, $"https://etherscan.io/uncle/{BlockHeightPH}" },
}},

{ CoinType.ETC, new Dictionary<string, string>
{
{ string.Empty, "https://gastracker.io/block/{0}" },
{ EthereumConstants.BlockTypeUncle, "https://gastracker.io/uncle/{0}" }
{ string.Empty, $"https://gastracker.io/block/{BlockHeightPH}" },
{ EthereumConstants.BlockTypeUncle, $"https://gastracker.io/uncle/{BlockHeightPH}" }
}},

{ CoinType.XMR, new Dictionary<string, string> { { string.Empty, "https://chainradar.com/xmr/block/{0}" }}},
{ CoinType.ETN, new Dictionary<string, string> { { string.Empty, "https://blockexplorer.electroneum.com/block/{0}" } }},
{ CoinType.LTC, new Dictionary<string, string> { { string.Empty, "https://chainz.cryptoid.info/ltc/block.dws?{0}.htm" } }},
{ CoinType.BCH, new Dictionary<string, string> { { string.Empty, "https://www.blocktrail.com/BCC/block/{0}" }}},
{ CoinType.DASH, new Dictionary<string, string> { { string.Empty, "https://chainz.cryptoid.info/dash/block.dws?{0}.htm" }}},
{ CoinType.BTC, new Dictionary<string, string> { { string.Empty, "https://blockchain.info/block/{0}" }}},
{ CoinType.DOGE, new Dictionary<string, string> { { string.Empty, "https://dogechain.info/block/{0}" }}},
{ CoinType.ZEC, new Dictionary<string, string> { { string.Empty, "https://explorer.zcha.in/blocks/{0}" }}},
{ CoinType.ZCL, new Dictionary<string, string> { { string.Empty, "http://explorer.zclmine.pro/blocks/{0}" }}},
{ CoinType.ZEN, new Dictionary<string, string> { { string.Empty, "http://explorer.zensystem.io/blocks/{0}" } }},
{ CoinType.DGB, new Dictionary<string, string> { { string.Empty, "https://digiexplorer.info/block/{0}" }}},
{ CoinType.NMC, new Dictionary<string, string> { { string.Empty, "https://explorer.namecoin.info/b/{0}" }}},
{ CoinType.GRS, new Dictionary<string, string> { { string.Empty, "https://groestlsight.groestlcoin.org/block/{0}" }}},
{ CoinType.MONA, new Dictionary<string, string> { { string.Empty, "https://bchain.info/MONA/block/{0}" }}},
{ CoinType.GLT, new Dictionary<string, string> { { string.Empty, "https://bchain.info/GLT/block/{0}" }}},
{ CoinType.VTC, new Dictionary<string, string> { { string.Empty, "https://bchain.info/VTC/block/{0}" }}},
{ CoinType.BTG, new Dictionary<string, string> { { string.Empty, "https://btg-bitcore2.trezor.io/block/{0}" }}},
{ CoinType.ELLA, new Dictionary<string, string> { { string.Empty, "https://explorer.ellaism.org/block/{0}" }}},
{ CoinType.EXP, new Dictionary<string, string> { { string.Empty, "http://www.gander.tech/blocks/{0}" }}},
{ CoinType.AEON, new Dictionary<string, string> { { string.Empty, "https://chainradar.com/aeon/block/{0}" }}},
{ CoinType.STAK, new Dictionary<string, string> { { string.Empty, "https://straks.info/block/{0}" }}},
{ CoinType.MOON, new Dictionary<string, string> { { string.Empty, "https://chainz.cryptoid.info/moon/block.dws?{0}.htm" }}},
{ CoinType.XVG, new Dictionary<string, string> { { string.Empty, "https://verge-blockchain.info/block/{0}" } }},
{ CoinType.XMR, new Dictionary<string, string> { { string.Empty, $"https://chainradar.com/xmr/block/{BlockHeightPH}" }}},
{ CoinType.ETN, new Dictionary<string, string> { { string.Empty, $"https://blockexplorer.electroneum.com/block/{BlockHeightPH}" } }},
{ CoinType.LTC, new Dictionary<string, string> { { string.Empty, $"https://chainz.cryptoid.info/ltc/block.dws?{BlockHeightPH}.htm" } }},
{ CoinType.BCH, new Dictionary<string, string> { { string.Empty, $"https://www.blocktrail.com/BCC/block/{BlockHeightPH}" }}},
{ CoinType.DASH, new Dictionary<string, string> { { string.Empty, $"https://chainz.cryptoid.info/dash/block.dws?{BlockHeightPH}.htm" }}},
{ CoinType.BTC, new Dictionary<string, string> { { string.Empty, $"https://blockchain.info/block/{BlockHeightPH}" }}},
{ CoinType.DOGE, new Dictionary<string, string> { { string.Empty, $"https://dogechain.info/block/{BlockHeightPH}" }}},
{ CoinType.ZEC, new Dictionary<string, string> { { string.Empty, $"https://explorer.zcha.in/blocks/{BlockHashPH}" } }},
{ CoinType.BTCP, new Dictionary<string, string> { { string.Empty, $"http://explorer.btcprivate.org/block/{BlockHashPH}" } }},
{ CoinType.ZCL, new Dictionary<string, string> { { string.Empty, $"http://explorer.zclmine.pro/block/{BlockHeightPH}" }}},
{ CoinType.ZEN, new Dictionary<string, string> { { string.Empty, $"http://explorer.zensystem.io/block/{BlockHashPH}" } }},
{ CoinType.DGB, new Dictionary<string, string> { { string.Empty, $"https://digiexplorer.info/block/{BlockHeightPH}" }}},
{ CoinType.NMC, new Dictionary<string, string> { { string.Empty, $"https://explorer.namecoin.info/b/{BlockHeightPH}" }}},
{ CoinType.GRS, new Dictionary<string, string> { { string.Empty, $"https://groestlsight.groestlcoin.org/block/{BlockHeightPH}" }}},
{ CoinType.MONA, new Dictionary<string, string> { { string.Empty, $"https://bchain.info/MONA/block/{BlockHeightPH}" }}},
{ CoinType.GLT, new Dictionary<string, string> { { string.Empty, $"https://bchain.info/GLT/block/{BlockHeightPH}" }}},
{ CoinType.VTC, new Dictionary<string, string> { { string.Empty, $"https://bchain.info/VTC/block/{BlockHeightPH}" }}},
{ CoinType.BTG, new Dictionary<string, string> { { string.Empty, $"https://btg-bitcore2.trezor.io/block/{BlockHashPH}" } }},
{ CoinType.ELLA, new Dictionary<string, string> { { string.Empty, $"https://explorer.ellaism.org/block/{BlockHeightPH}" }}},
{ CoinType.EXP, new Dictionary<string, string> { { string.Empty, $"http://www.gander.tech/blocks/{BlockHeightPH}" }}},
{ CoinType.AEON, new Dictionary<string, string> { { string.Empty, $"https://chainradar.com/aeon/block/{BlockHeightPH}" }}},
{ CoinType.STAK, new Dictionary<string, string> { { string.Empty, $"https://straks.info/block/{BlockHeightPH}" }}},
{ CoinType.MOON, new Dictionary<string, string> { { string.Empty, $"https://chainz.cryptoid.info/moon/block.dws?{BlockHeightPH}.htm" }}},
{ CoinType.XVG, new Dictionary<string, string> { { string.Empty, $"https://verge-blockchain.info/block/{BlockHashPH}" } }},
};

public static readonly Dictionary<CoinType, string> TxInfoLinks = new Dictionary<CoinType, string>
Expand All @@ -61,6 +65,7 @@ public static class CoinMetaData
{ CoinType.ZEC, "https://explorer.zcha.in/transactions/{0}" },
{ CoinType.ZCL, "http://explorer.zclmine.pro/transactions/{0}" },
{ CoinType.ZEN, "http://explorer.zensystem.io/transactions/{0}" },
{ CoinType.BTCP, "https://explorer.btcprivate.org/transactions/{0}" },
{ CoinType.DGB, "https://digiexplorer.info/tx/{0}" },
{ CoinType.NMC, "https://explorer.namecoin.info/tx/{0}" },
{ CoinType.GRS, "https://groestlsight.groestlcoin.org/tx/{0}" },
Expand Down
1 change: 1 addition & 0 deletions src/MiningCore/Blockchain/Ethereum/EthereumJob.cs
Original file line number Diff line number Diff line change
Expand Up @@ -110,6 +110,7 @@ public async Task<EthereumShare> ProcessShareAsync(StratumClient worker, string
MixHash = mixDigest.ToHexString(true),
IsBlockCandidate = isBlockCandidate,
Difficulty = stratumDifficulty * EthereumConstants.Pow2x32,
BlockHash = mixDigest.ToHexString(true) // OW: is this correct?
};

if (share.IsBlockCandidate)
Expand Down
7 changes: 4 additions & 3 deletions src/MiningCore/Blockchain/Ethereum/EthereumJobManager.cs
Original file line number Diff line number Diff line change
Expand Up @@ -189,7 +189,7 @@ private async Task<EthereumBlockTemplate> GetBlockTemplateAsync()
private EthereumBlockTemplate AssembleBlockTemplate(Block block, string[] work)
{
// only parity returns the 4th element (block height)
if (work.Length < 3)
if (work.Length < 4)
{
logger.Error(() => $"[{LogCat}] Error(s) refreshing blocktemplate: getWork did not return blockheight. Are you really connected to a Parity daemon?");
return null;
Expand Down Expand Up @@ -433,6 +433,7 @@ public async Task<EthereumShare> SubmitShareAsync(StratumClient worker,
// enrich share with common data
share.PoolId = poolConfig.Id;
share.NetworkDifficulty = BlockchainStats.NetworkDifficulty;
share.Source = clusterConfig.ClusterName;
share.Created = clock.Now;

return share;
Expand Down Expand Up @@ -536,7 +537,7 @@ protected override async Task PostStartInitAsync()
var parityChain = results[4].Response.ToObject<string>();

// ensure pool owns wallet
if (!accounts.Contains(poolConfig.Address) || coinbase != poolConfig.Address)
if (clusterConfig.PaymentProcessing?.Enabled == true && !accounts.Contains(poolConfig.Address) || coinbase != poolConfig.Address)
logger.ThrowLogPoolStartupException($"Daemon does not own pool-address '{poolConfig.Address}'", LogCat);

EthereumUtils.DetectNetworkAndChain(netVersion, parityChain, out networkType, out chainType);
Expand Down Expand Up @@ -599,7 +600,7 @@ private void ConfigureRewards()

protected virtual void SetupJobUpdates()
{
if (!poolConfig.EnableInternalStratum)
if (poolConfig.EnableInternalStratum == false)
return;

var enableStreaming = extraPoolConfig?.EnableDaemonWebsocketStreaming == true;
Expand Down
6 changes: 3 additions & 3 deletions src/MiningCore/Blockchain/Ethereum/EthereumPool.cs
Original file line number Diff line number Diff line change
Expand Up @@ -261,7 +261,7 @@ protected override async Task SetupJobManager()

await manager.StartAsync();

if (poolConfig.EnableInternalStratum)
if (poolConfig.EnableInternalStratum == true)
{
disposables.Add(manager.Jobs.Subscribe(OnNewJob));

Expand Down Expand Up @@ -341,8 +341,8 @@ public override void Configure(PoolConfig poolConfig, ClusterConfig clusterConfi
base.Configure(poolConfig, clusterConfig);

// validate mandatory extra config
var extraConfig = poolConfig.PaymentProcessing.Extra.SafeExtensionDataAs<EthereumPoolPaymentProcessingConfigExtra>();
if (extraConfig?.CoinbasePassword == null)
var extraConfig = poolConfig.PaymentProcessing?.Extra?.SafeExtensionDataAs<EthereumPoolPaymentProcessingConfigExtra>();
if (clusterConfig.PaymentProcessing?.Enabled == true && extraConfig?.CoinbasePassword == null)
logger.ThrowLogPoolStartupException("\"paymentProcessing.coinbasePassword\" pool-configuration property missing or empty (required for unlocking wallet during payment processing)");
}

Expand Down
3 changes: 2 additions & 1 deletion src/MiningCore/Blockchain/Monero/MoneroJob.cs
Original file line number Diff line number Diff line change
Expand Up @@ -206,7 +206,8 @@ public MoneroShare ProcessShare(string nonce, uint workerExtraNonce, string work
IsBlockCandidate = isBlockCandidate,
BlobHex = blob.ToHexString(),
BlobHash = blockHash.ToHexString(),
Difficulty = stratumDifficulty,
BlockHash = blockHash.ToHexString(),
Difficulty = stratumDifficulty,
};

return result;
Expand Down
Loading

0 comments on commit df5ecf2

Please sign in to comment.