diff --git a/src/Stratis.Bitcoin.Features.Api/NodeController.cs b/src/Stratis.Bitcoin.Features.Api/NodeController.cs
index 934a2b4c5b..79544a06ad 100644
--- a/src/Stratis.Bitcoin.Features.Api/NodeController.cs
+++ b/src/Stratis.Bitcoin.Features.Api/NodeController.cs
@@ -156,6 +156,7 @@ public IActionResult Status()
ProcessId = Process.GetCurrentProcess().Id,
Network = this.fullNode.Network.Name,
ConsensusHeight = this.chainState.ConsensusTip?.Height,
+ HeaderHeight = this.consensusManager.HeaderTip,
DataDirectoryPath = this.nodeSettings.DataDir,
Testnet = this.network.IsTest(),
RelayFee = this.nodeSettings.MinRelayTxFeeRate?.FeePerK?.ToUnit(MoneyUnit.BTC) ?? 0,
diff --git a/src/Stratis.Bitcoin.Features.PoA/Models/FederationMemberModel.cs b/src/Stratis.Bitcoin.Features.PoA/Models/FederationMemberModel.cs
index 547bfc4fce..a7eaca21b7 100644
--- a/src/Stratis.Bitcoin.Features.PoA/Models/FederationMemberModel.cs
+++ b/src/Stratis.Bitcoin.Features.PoA/Models/FederationMemberModel.cs
@@ -46,5 +46,8 @@ public sealed class FederationMemberDetailedModel : FederationMemberModel
[JsonProperty("rewardEstimatePerBlock")]
public double RewardEstimatePerBlock { get; set; }
+
+ [JsonProperty("miningStats")]
+ public MiningStatisticsModel MiningStatistics { get; set; }
}
}
\ No newline at end of file
diff --git a/src/Stratis.Bitcoin.Features.PoA/PoAMiner.cs b/src/Stratis.Bitcoin.Features.PoA/PoAMiner.cs
index d0d0e99934..7d1c583063 100644
--- a/src/Stratis.Bitcoin.Features.PoA/PoAMiner.cs
+++ b/src/Stratis.Bitcoin.Features.PoA/PoAMiner.cs
@@ -6,6 +6,7 @@
using System.Threading.Tasks;
using Microsoft.Extensions.Logging;
using NBitcoin;
+using Newtonsoft.Json;
using Stratis.Bitcoin.AsyncWork;
using Stratis.Bitcoin.Configuration;
using Stratis.Bitcoin.Configuration.Logging;
@@ -37,6 +38,12 @@ public interface IPoAMiner : IDisposable
{
/// Starts mining loop.
void InitializeMining();
+
+ ///
+ /// Returns mining statistics in the last amount of blocks equal to the federation size.
+ ///
+ /// Returns true if the miner produced a block in the last round and block producer hits.
+ MiningStatisticsModel MiningStatistics { get; }
}
///
@@ -73,6 +80,8 @@ public class PoAMiner : IPoAMiner
private readonly NodeSettings nodeSettings;
+ private MiningStatisticsModel miningStatistics;
+
private readonly IWalletManager walletManager;
protected readonly VotingManager votingManager;
@@ -418,7 +427,6 @@ private void AddComponentStats(StringBuilder log)
log.AppendLine();
return;
}
-
ChainedHeader tip = this.consensusManager.Tip;
ChainedHeader currentHeader = tip;
@@ -442,6 +450,8 @@ private void AddComponentStats(StringBuilder log)
if (timeHeader < currentHeader.Header.Time)
timeHeader += this.network.ConsensusOptions.TargetSpacingSeconds;
+ var statistics = new MiningStatisticsModel();
+
// Iterate mining slots.
for (int i = 0; i < maxDepth; i++)
{
@@ -449,7 +459,12 @@ private void AddComponentStats(StringBuilder log)
PubKey pubKey = modifiedFederation[headerSlot].PubKey;
- string pubKeyRepresentation = (pubKey == this.federationManager.CurrentFederationKey?.PubKey) ? "█████" : pubKey.ToString().Substring(0, pubKeyTakeCharacters);
+ string pubKeyRepresentation = pubKey.ToString().Substring(0, pubKeyTakeCharacters);
+ if (pubKey == this.federationManager.CurrentFederationKey?.PubKey)
+ {
+ pubKeyRepresentation = "█████";
+ statistics.ProducedBlockInLastRound = true;
+ }
// Mined in this slot?
if (timeHeader == currentHeader.Header.Time)
@@ -475,6 +490,9 @@ private void AddComponentStats(StringBuilder log)
log.AppendLine();
}
+ statistics.FederationSize = maxDepth;
+ statistics.MinerHits = hitCount;
+
log.Append("...");
log.AppendLine();
log.AppendLine($"Miner hits".PadRight(LoggingConfiguration.ColumnLength) + $": {hitCount} of {maxDepth}({(((float)hitCount / (float)maxDepth)).ToString("P2")})");
@@ -482,6 +500,12 @@ private void AddComponentStats(StringBuilder log)
log.AppendLine();
}
+ ///
+ public MiningStatisticsModel MiningStatistics
+ {
+ get { return this.miningStatistics; }
+ }
+
///
public virtual void Dispose()
{
@@ -491,4 +515,16 @@ public virtual void Dispose()
this.cancellation.Dispose();
}
}
+
+ public sealed class MiningStatisticsModel
+ {
+ [JsonProperty(PropertyName = "federationSize")]
+ public int FederationSize { get; set; }
+
+ [JsonProperty(PropertyName = "minerHits")]
+ public int MinerHits { get; set; }
+
+ [JsonProperty(PropertyName = "producedBlockInLastRound")]
+ public bool ProducedBlockInLastRound { get; set; }
+ }
}
diff --git a/src/Stratis.Bitcoin.Features.PoA/Voting/FederationController.cs b/src/Stratis.Bitcoin.Features.PoA/Voting/FederationController.cs
index bc861e5634..619c7f93ff 100644
--- a/src/Stratis.Bitcoin.Features.PoA/Voting/FederationController.cs
+++ b/src/Stratis.Bitcoin.Features.PoA/Voting/FederationController.cs
@@ -20,6 +20,7 @@ public sealed class FederationController : Controller
private readonly IIdleFederationMembersKicker idleFederationMembersKicker;
private readonly ILogger logger;
private readonly Network network;
+ private readonly IPoAMiner poaMiner;
private readonly ReconstructFederationService reconstructFederationService;
private readonly VotingManager votingManager;
@@ -29,12 +30,14 @@ public sealed class FederationController : Controller
VotingManager votingManager,
Network network,
IIdleFederationMembersKicker idleFederationMembersKicker,
+ IPoAMiner poAMiner,
ReconstructFederationService reconstructFederationService)
{
this.chainIndexer = chainIndexer;
this.federationManager = federationManager;
this.idleFederationMembersKicker = idleFederationMembersKicker;
this.network = network;
+ this.poaMiner = poAMiner;
this.reconstructFederationService = reconstructFederationService;
this.votingManager = votingManager;
@@ -126,6 +129,8 @@ public IActionResult GetCurrentMemberInfo()
federationMemberModel.RewardEstimatePerBlock = 9d / this.federationManager.GetFederationMembers().Count;
+ federationMemberModel.MiningStatistics = this.poaMiner.MiningStatistics;
+
return Json(federationMemberModel);
}
catch (Exception e)
diff --git a/src/Stratis.Bitcoin/Controllers/Models/StatusModel.cs b/src/Stratis.Bitcoin/Controllers/Models/StatusModel.cs
index effaf15628..170b066f67 100644
--- a/src/Stratis.Bitcoin/Controllers/Models/StatusModel.cs
+++ b/src/Stratis.Bitcoin/Controllers/Models/StatusModel.cs
@@ -38,9 +38,12 @@ public StatusModel()
/// System identifier of the node's process.
public int ProcessId { get; set; }
- /// The height of the consensus.
+ /// The height of consensus.
public int? ConsensusHeight { get; set; }
+ /// The height of the header store.
+ public int? HeaderHeight { get; set; }
+
/// Height of the most recent block in persistent storage.
///
public int BlockStoreHeight { get; set; }