Skip to content

Commit

Permalink
Add missing mrc fees to reward used for SplitCoinStakeOutput
Browse files Browse the repository at this point in the history
In V13 testing with simultaneous mrcs and mandatory sidestakes,
stakes were being rejected because the calculated total reward
to the staker did not include mrc fees. This apparently has been
an existing omission, but since sidestakes were not validated it
went undetected. Now that mandatory sidestakes are validated in
terms of both destination and amount, they were being rejected
by the validator as being too low.

Adding the mrc fees due to the staker to the staker's reward
fixes the problem.
  • Loading branch information
jamescowens committed Mar 17, 2024
1 parent 4089e7d commit 79cfae6
Show file tree
Hide file tree
Showing 3 changed files with 34 additions and 7 deletions.
38 changes: 32 additions & 6 deletions src/miner.cpp
Original file line number Diff line number Diff line change
Expand Up @@ -150,7 +150,7 @@ bool TrySignClaim(

// This is in anonymous namespace because it is only to be used by miner code here in this file.
bool CreateMRCRewards(CBlock &blocknew, std::map<GRC::Cpid, std::pair<uint256, GRC::MRC>>& mrc_map,
std::map<GRC::Cpid, uint256>& mrc_tx_map, uint32_t& claim_contract_version,
std::map<GRC::Cpid, uint256>& mrc_tx_map, CAmount& reward, uint32_t& claim_contract_version,
GRC::Claim& claim, CWallet* pwallet) EXCLUSIVE_LOCKS_REQUIRED(cs_main)
{
// For convenience
Expand All @@ -160,7 +160,7 @@ bool CreateMRCRewards(CBlock &blocknew, std::map<GRC::Cpid, std::pair<uint256, G
// coinstake.vout size should be 2 at this point. If not something is really wrong so assert immediately.
assert(coinstake.vout.size() == 2);

CAmount rewards = 0;
CAmount mrc_rewards = 0;
CAmount staker_fees = 0;
CAmount foundation_fees = 0;

Expand Down Expand Up @@ -202,7 +202,7 @@ bool CreateMRCRewards(CBlock &blocknew, std::map<GRC::Cpid, std::pair<uint256, G

if (reward) {
mrc_outputs.push_back(CTxOut(reward, script_beacon_key));
rewards += reward;
mrc_rewards += reward;
}

if (foundation_fee_fraction.IsNonZero()) {
Expand Down Expand Up @@ -236,7 +236,7 @@ bool CreateMRCRewards(CBlock &blocknew, std::map<GRC::Cpid, std::pair<uint256, G
FormatMoney(mrc.m_research_subsidy),
mrc.m_version,
FormatMoney(reward),
FormatMoney(rewards),
FormatMoney(mrc_rewards),
FormatMoney(staker_fees + foundation_fees),
FormatMoney(staker_fees),
FormatMoney(foundation_fees));
Expand All @@ -247,6 +247,9 @@ bool CreateMRCRewards(CBlock &blocknew, std::map<GRC::Cpid, std::pair<uint256, G
// Now that the MRC outputs are created, add the fees to the staker to the coinstake output 1 value.
coinstake.vout[1].nValue += staker_fees;

// Increment the reward parameter to include the staker_fees. This is important for mandatory sidestakes later.
reward += staker_fees;

if (foundation_fees > 0) {
// TODO: Make foundation address a defaulted but protocol overridable parameter.

Expand Down Expand Up @@ -287,7 +290,7 @@ bool CreateMRCRewards(CBlock &blocknew, std::map<GRC::Cpid, std::pair<uint256, G
FormatMoney(claim.m_block_subsidy),
FormatMoney(staker_fees),
FormatMoney(foundation_fees),
FormatMoney(rewards));
FormatMoney(mrc_rewards));

// Now the claim is complete. Put on the coinbase.
blocknew.vtx[0].vContracts.emplace_back(GRC::MakeContract<GRC::Claim>(
Expand Down Expand Up @@ -1439,7 +1442,8 @@ void StakeMiner(CWallet *pwallet)

// * Add MRC outputs to coinstake. This has to be done before the coinstake splitting/sidestaking, because
// Some of the MRC fees go to the miner as part of the reward, and this affects the SplitCoinStakeOutput calculation.
if (!CreateMRCRewards(StakeBlock, mrc_map, mrc_tx_map, claim_contract_version, claim, pwallet)) continue;
// Note that nReward here now includes the mrc fees to the staker.
if (!CreateMRCRewards(StakeBlock, mrc_map, mrc_tx_map, nReward, claim_contract_version, claim, pwallet)) continue;

g_timer.GetTimes(function + "CreateMRC", "miner");

Expand Down Expand Up @@ -1467,6 +1471,28 @@ void StakeMiner(CWallet *pwallet)

g_miner_status.IncrementBlocksCreated();

if (LogInstance().WillLogCategory(BCLog::LogFlags::VERBOSE)) {
COutPoint stake_prevout = StakeBlock.vtx[1].vin[0].prevout;
CTransaction stake_input;
ReadTxFromDisk(stake_input, stake_prevout);

LogPrintf("INFO: %s: stake input = %s",
__func__,
FormatMoney(stake_input.vout[stake_prevout.n].nValue));

for (unsigned int i = 1; i < StakeBlock.vtx[1].vout.size(); ++i) {
CTxDestination destination;

ExtractDestination(StakeBlock.vtx[1].vout[i].scriptPubKey, destination);

LogPrintf("INFO: %s: stake output[%u] = %s, destination = %s",
__func__,
i,
FormatMoney(StakeBlock.vtx[1].vout[i].nValue),
CBitcoinAddress(destination).ToString());
}
}

// * delegate to ProcessBlock
if (!ProcessBlock(nullptr, &StakeBlock, true)) {
error("%s: Block vehemently rejected", __func__);
Expand Down
1 change: 1 addition & 0 deletions src/miner.h
Original file line number Diff line number Diff line change
Expand Up @@ -31,6 +31,7 @@ bool GetStakeSplitStatusAndParams(int64_t& nMinStakeSplitValue, double& dEfficie
bool CreateMRCRewards(CBlock &blocknew,
std::map<GRC::Cpid, std::pair<uint256, GRC::MRC>>& mrc_map,
std::map<GRC::Cpid, uint256>& mrc_tx_map,
CAmount& reward,
uint32_t& claim_contract_version,
GRC::Claim& claim,
CWallet* pwallet) EXCLUSIVE_LOCKS_REQUIRED(cs_main);
Expand Down
2 changes: 1 addition & 1 deletion src/test/gridcoin/mrc_tests.cpp
Original file line number Diff line number Diff line change
Expand Up @@ -263,7 +263,7 @@ BOOST_AUTO_TEST_CASE(it_creates_valid_mrc_claims)

BOOST_CHECK(CreateGridcoinReward(block, pindex->pprev, reward, claim));

BOOST_CHECK(CreateMRCRewards(block, mrc_map, mrc_tx_map, claim_contract_version, claim, wallet));
BOOST_CHECK(CreateMRCRewards(block, mrc_map, mrc_tx_map, reward, claim_contract_version, claim, wallet));

// TODO(div72): Separate this test into pieces and actually have it do
// some useful testing by testing the validation logic against it.
Expand Down

0 comments on commit 79cfae6

Please sign in to comment.