Skip to content

Commit d4e38ee

Browse files
authored
Add endpoint to return the network weight for POS chains (#377)
* Add endpoint to return the network weight for pos chains * Add pos network weight to getblockchaininfo rpc method
1 parent bdd6e67 commit d4e38ee

10 files changed

Lines changed: 89 additions & 12 deletions

File tree

Lines changed: 9 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -0,0 +1,9 @@
1+
using NBitcoin;
2+
3+
namespace Blockcore.Interfaces
4+
{
5+
public interface INetworkWeight
6+
{
7+
double GetPosNetworkWeight();
8+
}
9+
}

src/Features/Blockcore.Features.Miner/Api/Controllers/StakingController.cs

Lines changed: 30 additions & 5 deletions
Original file line numberDiff line numberDiff line change
@@ -66,7 +66,7 @@ public IActionResult GetStakingInfo()
6666
try
6767
{
6868
if (!this.fullNode.Network.Consensus.IsProofOfStake)
69-
return ErrorHelpers.BuildErrorResponse(HttpStatusCode.MethodNotAllowed, "Method not allowed", "Method not available for Proof of Stake");
69+
return ErrorHelpers.BuildErrorResponse(HttpStatusCode.MethodNotAllowed, "Method not allowed", "Method only available for Proof of Stake");
7070

7171
GetStakingInfoModel model = this.posMinting != null ? this.posMinting.GetGetStakingInfoModel() : new GetStakingInfoModel();
7272

@@ -79,6 +79,31 @@ public IActionResult GetStakingInfo()
7979
}
8080
}
8181

82+
/// <summary>
83+
/// Get staking info from the miner.
84+
/// </summary>
85+
/// <returns>All staking info details as per the GetStakingInfoModel.</returns>
86+
[Route("getnetworkstakinginfo")]
87+
[HttpGet]
88+
public IActionResult GetNetworkStakingInfo()
89+
{
90+
try
91+
{
92+
if (!this.fullNode.Network.Consensus.IsProofOfStake)
93+
return ErrorHelpers.BuildErrorResponse(HttpStatusCode.MethodNotAllowed, "Method not allowed", "Method only available for Proof of Stake");
94+
95+
double networkWeight = this.posMinting.GetNetworkWeight();
96+
double posDifficulty = this.posMinting.GetDifficulty(null);
97+
98+
return this.Json(new GetNetworkStakingInfoModel { Difficulty = posDifficulty, NetStakeWeight = (long)networkWeight });
99+
}
100+
catch (Exception e)
101+
{
102+
this.logger.LogError("Exception occurred: {0}", e.ToString());
103+
return ErrorHelpers.BuildErrorResponse(HttpStatusCode.BadRequest, e.Message, e.ToString());
104+
}
105+
}
106+
82107
/// <summary>
83108
/// Start staking.
84109
/// </summary>
@@ -93,7 +118,7 @@ public IActionResult StartStaking([FromBody] StartStakingRequest request)
93118
try
94119
{
95120
if (!this.fullNode.Network.Consensus.IsProofOfStake)
96-
return ErrorHelpers.BuildErrorResponse(HttpStatusCode.MethodNotAllowed, "Method not allowed", "Method not available for Proof of Stake");
121+
return ErrorHelpers.BuildErrorResponse(HttpStatusCode.MethodNotAllowed, "Method not allowed", "Method only available for Proof of Stake");
97122

98123
if (!this.ModelState.IsValid)
99124
{
@@ -139,7 +164,7 @@ public IActionResult StopStaking([FromBody] bool corsProtection = true)
139164
try
140165
{
141166
if (!this.fullNode.Network.Consensus.IsProofOfStake)
142-
return ErrorHelpers.BuildErrorResponse(HttpStatusCode.MethodNotAllowed, "Method not allowed", "Method not available for Proof of Stake");
167+
return ErrorHelpers.BuildErrorResponse(HttpStatusCode.MethodNotAllowed, "Method not allowed", "Method only available for Proof of Stake");
143168

144169
this.fullNode.NodeFeature<MiningFeature>(true).StopStaking();
145170
return this.Ok();
@@ -162,7 +187,7 @@ public IActionResult StakingExpiry([FromBody] StakingExpiryRequest request)
162187
try
163188
{
164189
if (!this.fullNode.Network.Consensus.IsProofOfStake)
165-
return ErrorHelpers.BuildErrorResponse(HttpStatusCode.MethodNotAllowed, "Method not allowed", "Method not available for Proof of Stake");
190+
return ErrorHelpers.BuildErrorResponse(HttpStatusCode.MethodNotAllowed, "Method not allowed", "Method only available for Proof of Stake");
166191

167192
if (!this.minerSettings.EnforceStakingFlag)
168193
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
196221
try
197222
{
198223
if (!this.fullNode.Network.Consensus.IsProofOfStake)
199-
return ErrorHelpers.BuildErrorResponse(HttpStatusCode.MethodNotAllowed, "Method not allowed", "Method not available for Proof of Stake");
224+
return ErrorHelpers.BuildErrorResponse(HttpStatusCode.MethodNotAllowed, "Method not allowed", "Method only available for Proof of Stake");
200225

201226
if (!this.minerSettings.EnforceStakingFlag)
202227
return ErrorHelpers.BuildErrorResponse(HttpStatusCode.Forbidden, "Operation not allowed", "This operation is only allowed if EnforceStakingFlag is true");
Lines changed: 20 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -0,0 +1,20 @@
1+
using System;
2+
using Newtonsoft.Json;
3+
4+
namespace Blockcore.Features.Miner.Api.Models
5+
{
6+
/// <summary>
7+
/// Data structure returned by RPC command "getstakinginfo".
8+
/// </summary>
9+
public class GetNetworkStakingInfoModel
10+
{
11+
/// <summary>Target difficulty that the next block must meet.</summary>
12+
[JsonProperty(PropertyName = "difficulty")]
13+
public double Difficulty { get; set; }
14+
15+
/// <summary>Estimation of the total staking weight of all nodes on the network.</summary>
16+
[JsonProperty(PropertyName = "netStakeWeight")]
17+
public long NetStakeWeight { get; set; }
18+
19+
}
20+
}

src/Features/Blockcore.Features.Miner/Blockcore.Features.Miner.csproj

Lines changed: 0 additions & 3 deletions
Original file line numberDiff line numberDiff line change
@@ -18,9 +18,6 @@
1818
<ProjectReference Include="..\Blockcore.Features.Wallet\Blockcore.Features.Wallet.csproj" />
1919
<ProjectReference Include="..\..\Blockcore\Blockcore.csproj" />
2020
</ItemGroup>
21-
<ItemGroup>
22-
<Folder Include="Api\" />
23-
</ItemGroup>
2421
<PropertyGroup Condition="'$(Configuration)|$(Platform)'=='Debug|AnyCPU'">
2522
<NoWarn>1701;1702;1705;IDE0008;</NoWarn>
2623
<DocumentationFile>

src/Features/Blockcore.Features.Miner/MiningFeature.cs

Lines changed: 3 additions & 1 deletion
Original file line numberDiff line numberDiff line change
@@ -17,6 +17,7 @@
1717
using Blockcore.Features.RPC;
1818
using Blockcore.Features.Wallet;
1919
using Blockcore.Features.Wallet.UI;
20+
using Blockcore.Interfaces;
2021
using Blockcore.Interfaces.UI;
2122
using Blockcore.Mining;
2223
using Blockcore.Networks;
@@ -256,7 +257,8 @@ public static IFullNodeBuilder AddPowPosMining(this IFullNodeBuilder fullNodeBui
256257
.FeatureServices(services =>
257258
{
258259
services.AddSingleton<IPowMining, PowMining>();
259-
services.AddSingleton<IPosMinting, PosMinting>();
260+
services.AddSingleton<IPosMinting, PosMinting>()
261+
.AddSingleton<INetworkWeight, PosMinting>(provider => (PosMinting)provider.GetService<IPosMinting>());
260262
services.AddSingleton<IBlockProvider, BlockProvider>();
261263
services.AddSingleton<BlockDefinition, PowBlockDefinition>();
262264
services.AddSingleton<BlockDefinition, PosBlockDefinition>();

src/Features/Blockcore.Features.Miner/Staking/PosMinting.cs

Lines changed: 6 additions & 1 deletion
Original file line numberDiff line numberDiff line change
@@ -71,7 +71,7 @@ namespace Blockcore.Features.Miner.Staking
7171
/// and the new value depends on the kernel, it is hard to predict its value in the future.
7272
/// </para>
7373
/// </remarks>
74-
public class PosMinting : IPosMinting
74+
public class PosMinting : IPosMinting, INetworkWeight
7575
{
7676
/// <summary>
7777
/// Indicates the current state: idle, staking requested, staking in progress and stop staking requested.
@@ -1189,6 +1189,11 @@ public double GetNetworkWeight()
11891189
return res;
11901190
}
11911191

1192+
public double GetPosNetworkWeight()
1193+
{
1194+
return GetNetworkWeight();
1195+
}
1196+
11921197
/// <inheritdoc/>
11931198
public GetStakingInfoModel GetGetStakingInfoModel()
11941199
{

src/Features/Blockcore.Features.RPC/Controllers/FullNodeController.cs

Lines changed: 12 additions & 1 deletion
Original file line numberDiff line numberDiff line change
@@ -50,6 +50,9 @@ public class FullNodeController : FeatureController
5050
/// <summary>An interface implementation used to retrieve the network difficulty target.</summary>
5151
private readonly INetworkDifficulty networkDifficulty;
5252

53+
/// <summary>An interface implementation used to retrieve the total network weight.</summary>
54+
private readonly INetworkWeight networkWeight;
55+
5356
/// <summary>An interface implementation for the blockstore.</summary>
5457
private readonly IBlockStore blockStore;
5558

@@ -73,7 +76,8 @@ public FullNodeController(
7376
IConsensusManager consensusManager = null,
7477
IBlockStore blockStore = null,
7578
IInitialBlockDownloadState ibdState = null,
76-
IStakeChain stakeChain = null)
79+
IStakeChain stakeChain = null,
80+
INetworkWeight networkWeight = null)
7781
: base(
7882
fullNode: fullNode,
7983
network: network,
@@ -91,6 +95,7 @@ public FullNodeController(
9195
this.blockStore = blockStore;
9296
this.ibdState = ibdState;
9397
this.stakeChain = stakeChain;
98+
this.networkWeight = networkWeight;
9499
}
95100

96101
/// <summary>
@@ -462,6 +467,7 @@ public BlockchainInfoModel GetBlockchainInfo()
462467
Headers = (uint)(this.ChainIndexer?.Height ?? 0),
463468
BestBlockHash = this.ChainState?.ConsensusTip?.HashBlock,
464469
Difficulty = this.GetNetworkDifficulty()?.Difficulty ?? 0.0,
470+
NetworkWeight = (long)this.GetPosNetworkWeight(),
465471
MedianTime = this.ChainState?.ConsensusTip?.GetMedianTimePast().ToUnixTimeSeconds() ?? 0,
466472
VerificationProgress = 0.0,
467473
IsInitialBlockDownload = this.ibdState?.IsInitialBlockDownload() ?? true,
@@ -550,5 +556,10 @@ private Target GetNetworkDifficulty()
550556
{
551557
return this.networkDifficulty?.GetNetworkDifficulty();
552558
}
559+
560+
private double GetPosNetworkWeight()
561+
{
562+
return this.networkWeight?.GetPosNetworkWeight() ?? 0;
563+
}
553564
}
554565
}

src/Features/Blockcore.Features.RPC/Models/BlockchainInfoModel.cs

Lines changed: 4 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -11,6 +11,7 @@ namespace Blockcore.Features.RPC.Models
1111
// * "headers": xxxxxx, (numeric) the current number of headers we have validated
1212
// "bestblockhash": "...", (string) the hash of the currently best block
1313
// "difficulty": xxxxxx, (numeric) the current difficulty
14+
// "networkWeight: xxxxx, (numeric) the total network weight
1415
// * "mediantime": xxxxxx, (numeric) median time for the current best block
1516
// * "verificationprogress": xxxx, (numeric) estimate of verification progress[0..1]
1617
// * "initialblockdownload": xxxx, (bool) (debug information) estimate of whether this node is in Initial Block Download mode.
@@ -64,6 +65,9 @@ public class BlockchainInfoModel
6465

6566
[JsonProperty(PropertyName = "difficulty")]
6667
public double Difficulty { get; set; }
68+
69+
[JsonProperty(PropertyName = "networkWeight")]
70+
public long NetworkWeight { get; set; }
6771

6872
[JsonProperty(PropertyName = "mediantime")]
6973
public long MedianTime { get; set; }

src/Node/Blockcore.Node/Properties/launchSettings.json

Lines changed: 4 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -76,6 +76,10 @@
7676
"commandName": "Project",
7777
"commandLineArgs": "--chain=X42 -server -rpcallowip=127.0.0.1 -rpcbind=127.0.0.1 -rpcpassword=rpcpassword -rpcuser=rpcuser -datadir=nodedata -testnet"
7878
},
79+
"XDS (MAIN)": {
80+
"commandName": "Project",
81+
"commandLineArgs": "--chain=XDS -server -rpcallowip=127.0.0.1 -rpcbind=127.0.0.1 -rpcpassword=rpcpassword -rpcuser=rpcuser"
82+
},
7983
"XDS (MAIN/LOCAL)": {
8084
"commandName": "Project",
8185
"commandLineArgs": "--chain=XDS -server -rpcallowip=127.0.0.1 -rpcbind=127.0.0.1 -rpcpassword=rpcpassword -rpcuser=rpcuser -datadir=nodedata"

src/Tests/Blockcore.Features.Miner.Tests/Controllers/StakingControllerTest.cs

Lines changed: 1 addition & 1 deletion
Original file line numberDiff line numberDiff line change
@@ -262,7 +262,7 @@ public void StartStaking_OnProofOfWorkNetwork_Returns_MethodNotAllowed()
262262

263263
ErrorModel error = errorResponse.Errors[0];
264264
Assert.Equal(405, error.Status);
265-
Assert.Equal("Method not available for Proof of Stake", error.Description);
265+
Assert.Equal("Method only available for Proof of Stake", error.Description);
266266
}
267267
}
268268
}

0 commit comments

Comments
 (0)