diff --git a/src/Blockcore/Interfaces/INetworkWeight.cs b/src/Blockcore/Interfaces/INetworkWeight.cs
new file mode 100644
index 000000000..0037e2397
--- /dev/null
+++ b/src/Blockcore/Interfaces/INetworkWeight.cs
@@ -0,0 +1,9 @@
+using NBitcoin;
+
+namespace Blockcore.Interfaces
+{
+ public interface INetworkWeight
+ {
+ double GetPosNetworkWeight();
+ }
+}
diff --git a/src/Features/Blockcore.Features.Miner/Api/Controllers/StakingController.cs b/src/Features/Blockcore.Features.Miner/Api/Controllers/StakingController.cs
index 9f348f65f..cdbb4f428 100644
--- a/src/Features/Blockcore.Features.Miner/Api/Controllers/StakingController.cs
+++ b/src/Features/Blockcore.Features.Miner/Api/Controllers/StakingController.cs
@@ -66,7 +66,7 @@ public IActionResult GetStakingInfo()
try
{
if (!this.fullNode.Network.Consensus.IsProofOfStake)
- return ErrorHelpers.BuildErrorResponse(HttpStatusCode.MethodNotAllowed, "Method not allowed", "Method not available for Proof of Stake");
+ return ErrorHelpers.BuildErrorResponse(HttpStatusCode.MethodNotAllowed, "Method not allowed", "Method only available for Proof of Stake");
GetStakingInfoModel model = this.posMinting != null ? this.posMinting.GetGetStakingInfoModel() : new GetStakingInfoModel();
@@ -79,6 +79,31 @@ public IActionResult GetStakingInfo()
}
}
+ ///
+ /// Get staking info from the miner.
+ ///
+ /// All staking info details as per the GetStakingInfoModel.
+ [Route("getnetworkstakinginfo")]
+ [HttpGet]
+ public IActionResult GetNetworkStakingInfo()
+ {
+ try
+ {
+ if (!this.fullNode.Network.Consensus.IsProofOfStake)
+ return ErrorHelpers.BuildErrorResponse(HttpStatusCode.MethodNotAllowed, "Method not allowed", "Method only available for Proof of Stake");
+
+ double networkWeight = this.posMinting.GetNetworkWeight();
+ double posDifficulty = this.posMinting.GetDifficulty(null);
+
+ return this.Json(new GetNetworkStakingInfoModel { Difficulty = posDifficulty, NetStakeWeight = (long)networkWeight });
+ }
+ catch (Exception e)
+ {
+ this.logger.LogError("Exception occurred: {0}", e.ToString());
+ return ErrorHelpers.BuildErrorResponse(HttpStatusCode.BadRequest, e.Message, e.ToString());
+ }
+ }
+
///
/// Start staking.
///
@@ -93,7 +118,7 @@ public IActionResult StartStaking([FromBody] StartStakingRequest request)
try
{
if (!this.fullNode.Network.Consensus.IsProofOfStake)
- return ErrorHelpers.BuildErrorResponse(HttpStatusCode.MethodNotAllowed, "Method not allowed", "Method not available for Proof of Stake");
+ return ErrorHelpers.BuildErrorResponse(HttpStatusCode.MethodNotAllowed, "Method not allowed", "Method only available for Proof of Stake");
if (!this.ModelState.IsValid)
{
@@ -139,7 +164,7 @@ public IActionResult StopStaking([FromBody] bool corsProtection = true)
try
{
if (!this.fullNode.Network.Consensus.IsProofOfStake)
- return ErrorHelpers.BuildErrorResponse(HttpStatusCode.MethodNotAllowed, "Method not allowed", "Method not available for Proof of Stake");
+ return ErrorHelpers.BuildErrorResponse(HttpStatusCode.MethodNotAllowed, "Method not allowed", "Method only available for Proof of Stake");
this.fullNode.NodeFeature(true).StopStaking();
return this.Ok();
@@ -162,7 +187,7 @@ public IActionResult StakingExpiry([FromBody] StakingExpiryRequest request)
try
{
if (!this.fullNode.Network.Consensus.IsProofOfStake)
- return ErrorHelpers.BuildErrorResponse(HttpStatusCode.MethodNotAllowed, "Method not allowed", "Method not available for Proof of Stake");
+ return ErrorHelpers.BuildErrorResponse(HttpStatusCode.MethodNotAllowed, "Method not allowed", "Method only available for Proof of Stake");
if (!this.minerSettings.EnforceStakingFlag)
return ErrorHelpers.BuildErrorResponse(HttpStatusCode.Forbidden, "Operation not allowed", "This operation is only allowed if EnforceStakingFlag is true");
@@ -196,7 +221,7 @@ public IActionResult GetStakingNotExpired([FromBody] StakingNotExpiredRequest re
try
{
if (!this.fullNode.Network.Consensus.IsProofOfStake)
- return ErrorHelpers.BuildErrorResponse(HttpStatusCode.MethodNotAllowed, "Method not allowed", "Method not available for Proof of Stake");
+ return ErrorHelpers.BuildErrorResponse(HttpStatusCode.MethodNotAllowed, "Method not allowed", "Method only available for Proof of Stake");
if (!this.minerSettings.EnforceStakingFlag)
return ErrorHelpers.BuildErrorResponse(HttpStatusCode.Forbidden, "Operation not allowed", "This operation is only allowed if EnforceStakingFlag is true");
diff --git a/src/Features/Blockcore.Features.Miner/Api/Models/GetNetworkStakingInfoModel.cs b/src/Features/Blockcore.Features.Miner/Api/Models/GetNetworkStakingInfoModel.cs
new file mode 100644
index 000000000..7d4bbc56d
--- /dev/null
+++ b/src/Features/Blockcore.Features.Miner/Api/Models/GetNetworkStakingInfoModel.cs
@@ -0,0 +1,20 @@
+using System;
+using Newtonsoft.Json;
+
+namespace Blockcore.Features.Miner.Api.Models
+{
+ ///
+ /// Data structure returned by RPC command "getstakinginfo".
+ ///
+ public class GetNetworkStakingInfoModel
+ {
+ /// Target difficulty that the next block must meet.
+ [JsonProperty(PropertyName = "difficulty")]
+ public double Difficulty { get; set; }
+
+ /// Estimation of the total staking weight of all nodes on the network.
+ [JsonProperty(PropertyName = "netStakeWeight")]
+ public long NetStakeWeight { get; set; }
+
+ }
+}
diff --git a/src/Features/Blockcore.Features.Miner/Blockcore.Features.Miner.csproj b/src/Features/Blockcore.Features.Miner/Blockcore.Features.Miner.csproj
index 6dc16157c..bbd23358d 100644
--- a/src/Features/Blockcore.Features.Miner/Blockcore.Features.Miner.csproj
+++ b/src/Features/Blockcore.Features.Miner/Blockcore.Features.Miner.csproj
@@ -18,9 +18,6 @@
-
-
-
1701;1702;1705;IDE0008;
diff --git a/src/Features/Blockcore.Features.Miner/MiningFeature.cs b/src/Features/Blockcore.Features.Miner/MiningFeature.cs
index dbd744dfa..36d1e3002 100644
--- a/src/Features/Blockcore.Features.Miner/MiningFeature.cs
+++ b/src/Features/Blockcore.Features.Miner/MiningFeature.cs
@@ -17,6 +17,7 @@
using Blockcore.Features.RPC;
using Blockcore.Features.Wallet;
using Blockcore.Features.Wallet.UI;
+using Blockcore.Interfaces;
using Blockcore.Interfaces.UI;
using Blockcore.Mining;
using Blockcore.Networks;
@@ -256,7 +257,8 @@ public static IFullNodeBuilder AddPowPosMining(this IFullNodeBuilder fullNodeBui
.FeatureServices(services =>
{
services.AddSingleton();
- services.AddSingleton();
+ services.AddSingleton()
+ .AddSingleton(provider => (PosMinting)provider.GetService());
services.AddSingleton();
services.AddSingleton();
services.AddSingleton();
diff --git a/src/Features/Blockcore.Features.Miner/Staking/PosMinting.cs b/src/Features/Blockcore.Features.Miner/Staking/PosMinting.cs
index 11fc8dbeb..142562692 100644
--- a/src/Features/Blockcore.Features.Miner/Staking/PosMinting.cs
+++ b/src/Features/Blockcore.Features.Miner/Staking/PosMinting.cs
@@ -71,7 +71,7 @@ namespace Blockcore.Features.Miner.Staking
/// and the new value depends on the kernel, it is hard to predict its value in the future.
///
///
- public class PosMinting : IPosMinting
+ public class PosMinting : IPosMinting, INetworkWeight
{
///
/// Indicates the current state: idle, staking requested, staking in progress and stop staking requested.
@@ -1189,6 +1189,11 @@ public double GetNetworkWeight()
return res;
}
+ public double GetPosNetworkWeight()
+ {
+ return GetNetworkWeight();
+ }
+
///
public GetStakingInfoModel GetGetStakingInfoModel()
{
diff --git a/src/Features/Blockcore.Features.RPC/Controllers/FullNodeController.cs b/src/Features/Blockcore.Features.RPC/Controllers/FullNodeController.cs
index ee65e47ce..f9a6f106a 100644
--- a/src/Features/Blockcore.Features.RPC/Controllers/FullNodeController.cs
+++ b/src/Features/Blockcore.Features.RPC/Controllers/FullNodeController.cs
@@ -50,6 +50,9 @@ public class FullNodeController : FeatureController
/// An interface implementation used to retrieve the network difficulty target.
private readonly INetworkDifficulty networkDifficulty;
+ /// An interface implementation used to retrieve the total network weight.
+ private readonly INetworkWeight networkWeight;
+
/// An interface implementation for the blockstore.
private readonly IBlockStore blockStore;
@@ -73,7 +76,8 @@ public FullNodeController(
IConsensusManager consensusManager = null,
IBlockStore blockStore = null,
IInitialBlockDownloadState ibdState = null,
- IStakeChain stakeChain = null)
+ IStakeChain stakeChain = null,
+ INetworkWeight networkWeight = null)
: base(
fullNode: fullNode,
network: network,
@@ -91,6 +95,7 @@ public FullNodeController(
this.blockStore = blockStore;
this.ibdState = ibdState;
this.stakeChain = stakeChain;
+ this.networkWeight = networkWeight;
}
///
@@ -462,6 +467,7 @@ public BlockchainInfoModel GetBlockchainInfo()
Headers = (uint)(this.ChainIndexer?.Height ?? 0),
BestBlockHash = this.ChainState?.ConsensusTip?.HashBlock,
Difficulty = this.GetNetworkDifficulty()?.Difficulty ?? 0.0,
+ NetworkWeight = (long)this.GetPosNetworkWeight(),
MedianTime = this.ChainState?.ConsensusTip?.GetMedianTimePast().ToUnixTimeSeconds() ?? 0,
VerificationProgress = 0.0,
IsInitialBlockDownload = this.ibdState?.IsInitialBlockDownload() ?? true,
@@ -550,5 +556,10 @@ private Target GetNetworkDifficulty()
{
return this.networkDifficulty?.GetNetworkDifficulty();
}
+
+ private double GetPosNetworkWeight()
+ {
+ return this.networkWeight?.GetPosNetworkWeight() ?? 0;
+ }
}
}
\ No newline at end of file
diff --git a/src/Features/Blockcore.Features.RPC/Models/BlockchainInfoModel.cs b/src/Features/Blockcore.Features.RPC/Models/BlockchainInfoModel.cs
index 83de2bfe4..16feac040 100644
--- a/src/Features/Blockcore.Features.RPC/Models/BlockchainInfoModel.cs
+++ b/src/Features/Blockcore.Features.RPC/Models/BlockchainInfoModel.cs
@@ -11,6 +11,7 @@ namespace Blockcore.Features.RPC.Models
// * "headers": xxxxxx, (numeric) the current number of headers we have validated
// "bestblockhash": "...", (string) the hash of the currently best block
// "difficulty": xxxxxx, (numeric) the current difficulty
+ // "networkWeight: xxxxx, (numeric) the total network weight
// * "mediantime": xxxxxx, (numeric) median time for the current best block
// * "verificationprogress": xxxx, (numeric) estimate of verification progress[0..1]
// * "initialblockdownload": xxxx, (bool) (debug information) estimate of whether this node is in Initial Block Download mode.
@@ -64,6 +65,9 @@ public class BlockchainInfoModel
[JsonProperty(PropertyName = "difficulty")]
public double Difficulty { get; set; }
+
+ [JsonProperty(PropertyName = "networkWeight")]
+ public long NetworkWeight { get; set; }
[JsonProperty(PropertyName = "mediantime")]
public long MedianTime { get; set; }
diff --git a/src/Node/Blockcore.Node/Properties/launchSettings.json b/src/Node/Blockcore.Node/Properties/launchSettings.json
index 51416cf1d..8a806e1f8 100644
--- a/src/Node/Blockcore.Node/Properties/launchSettings.json
+++ b/src/Node/Blockcore.Node/Properties/launchSettings.json
@@ -76,6 +76,10 @@
"commandName": "Project",
"commandLineArgs": "--chain=X42 -server -rpcallowip=127.0.0.1 -rpcbind=127.0.0.1 -rpcpassword=rpcpassword -rpcuser=rpcuser -datadir=nodedata -testnet"
},
+ "XDS (MAIN)": {
+ "commandName": "Project",
+ "commandLineArgs": "--chain=XDS -server -rpcallowip=127.0.0.1 -rpcbind=127.0.0.1 -rpcpassword=rpcpassword -rpcuser=rpcuser"
+ },
"XDS (MAIN/LOCAL)": {
"commandName": "Project",
"commandLineArgs": "--chain=XDS -server -rpcallowip=127.0.0.1 -rpcbind=127.0.0.1 -rpcpassword=rpcpassword -rpcuser=rpcuser -datadir=nodedata"
diff --git a/src/Tests/Blockcore.Features.Miner.Tests/Controllers/StakingControllerTest.cs b/src/Tests/Blockcore.Features.Miner.Tests/Controllers/StakingControllerTest.cs
index eefbd2133..9c4322ecb 100644
--- a/src/Tests/Blockcore.Features.Miner.Tests/Controllers/StakingControllerTest.cs
+++ b/src/Tests/Blockcore.Features.Miner.Tests/Controllers/StakingControllerTest.cs
@@ -262,7 +262,7 @@ public void StartStaking_OnProofOfWorkNetwork_Returns_MethodNotAllowed()
ErrorModel error = errorResponse.Errors[0];
Assert.Equal(405, error.Status);
- Assert.Equal("Method not available for Proof of Stake", error.Description);
+ Assert.Equal("Method only available for Proof of Stake", error.Description);
}
}
}