Skip to content

Commit

Permalink
fix reward formula
Browse files Browse the repository at this point in the history
  • Loading branch information
RosenKrumov committed Apr 25, 2024
1 parent 09eb494 commit a6869ba
Showing 1 changed file with 70 additions and 61 deletions.
131 changes: 70 additions & 61 deletions src/validation.cpp
Original file line number Diff line number Diff line change
Expand Up @@ -767,14 +767,14 @@ static bool AcceptToMemoryPoolWorker(const CChainParams& chainparams, CTxMemPool
for (QtumTransaction qtumTransaction : qtumTransactions) {
if (qtumTransaction.receiveAddress() == uintToh160(Params().GetConsensus().lydraAddress) &&
std::find(lydra_tx_senders.begin(), lydra_tx_senders.end(), qtumTransaction.sender()) != lydra_tx_senders.end()) {
return state.DoS(100, error("%s: Cannot mint to same address while another mint is pending", __func__),
REJECT_INVALID, "another-mint-pending");
return state.DoS(100, error("%s: Cannot mint to same address while another mint is pending", __func__),
REJECT_INVALID, "another-mint-pending");
}
}
}
}
}

for (const CTxIn& txin : tx.vin) {
CTxDestination dest;
const CTxOut& prevout = view.GetOutputFor(txin);
Expand Down Expand Up @@ -809,33 +809,32 @@ static bool AcceptToMemoryPoolWorker(const CChainParams& chainparams, CTxMemPool

for (const auto& addr_pair : addresses_index) {
// Get address utxos
std::vector<std::pair<CAddressUnspentKey, CAddressUnspentValue> > unspentOutputs;
std::vector<std::pair<CAddressUnspentKey, CAddressUnspentValue>> unspentOutputs;
if (!GetAddressUnspent(addr_pair.first, addr_pair.second, unspentOutputs)) {
//throw error("No information available for address");
// throw error("No information available for address");
}

// Add the utxos to the list if they are mature and at least the minimum value
int coinbaseMaturity = Params().GetConsensus().CoinbaseMaturity(chainActive.Height() + 1);
CAmount rembalance = 0;
for (std::vector<std::pair<CAddressUnspentKey, CAddressUnspentValue> >::const_iterator i=unspentOutputs.begin(); i!=unspentOutputs.end(); i++) {

for (std::vector<std::pair<CAddressUnspentKey, CAddressUnspentValue>>::const_iterator i = unspentOutputs.begin(); i != unspentOutputs.end(); i++) {
int nDepth = chainActive.Height() - i->second.blockHeight + 1;
//if (nDepth < coinbaseMaturity)
//continue;
// if (nDepth < coinbaseMaturity)
// continue;

rembalance += i->second.satoshis;
}

auto all_inputs = addresses_inputs[addrhash_dest[addr_pair.first]];
auto all_outputs = addresses_outputs[addrhash_dest[addr_pair.first]];
Lydra l;
uint64_t locked_hydra_amount;
l.getLockedHydraAmountPerAddress(boost::get<CKeyID>(&addrhash_dest[addr_pair.first])->GetReverseHex(), locked_hydra_amount);

if (rembalance - all_inputs + all_outputs < locked_hydra_amount) {
LogPrintf("Address -> %s | rembalance -> %d | spent -> %d | locked -> %d/n",
boost::get<CKeyID>(&addrhash_dest[addr_pair.first])->GetReverseHex(),
rembalance, all_outputs-all_inputs, locked_hydra_amount);
LogPrintf("Address -> %s | rembalance -> %d | spent -> %d | locked -> %d/n",
boost::get<CKeyID>(&addrhash_dest[addr_pair.first])->GetReverseHex(),
rembalance, all_outputs - all_inputs, locked_hydra_amount);
return state.DoS(100, error("%s: Spending more than available HYDRA amount. The rest is locked for LYDRA tokens.", __func__),
REJECT_INVALID, "spend-more-than-locked");
}
Expand Down Expand Up @@ -1490,34 +1489,50 @@ CAmount GetBlockSubsidy(int nHeight, const Consensus::Params& consensusParams)
dgp.fillBlockRewardBlocksInfo();
dgp.fillBlockRewardPercentageInfo();

if (nHeight > 5100) {
while (dgp.blockRewardVoteBlocks.size() == 0) {
dgp.fillBlockRewardBlocksInfo();
dgp.fillBlockRewardPercentageInfo();
int a = 0;
while (a < 5000000)
a++;
}
}

CAmount prevTotalSupplay = consensusParams.initialCoinsSupply * 100;
CAmount blocksPerYear = consensusParams.blocksPerYear * 100;
int lastPercentage = 20; // dgp.blockRewardVotePercentages[0];
int lastHeight = 5001; // dgp.blockRewardVoteBlocks[0];

if (dgp.blockRewardVoteBlocks.size() > 0) {
lastPercentage = dgp.blockRewardVotePercentages[dgp.blockRewardVotePercentages.size() - 1];
lastHeight = dgp.blockRewardVoteBlocks[dgp.blockRewardVoteBlocks.size() - 1];
if (dgp.blockRewardVoteBlocks.size() == 0) {
dgp.blockRewardVoteBlocks.push_back(5001);
dgp.blockRewardVotePercentages.push_back(20);
}

for (int i = 1; i < dgp.blockRewardVotePercentages.size(); i++) {
for (int j = dgp.blockRewardVoteBlocks[i - 1]; i < dgp.blockRewardVoteBlocks[i]; i++) {
prevTotalSupplay += (dgp.blockRewardVotePercentages[i] * prevTotalSupplay) / blocksPerYear;
for (int i = 0; i < dgp.blockRewardVotePercentages.size(); i++) {
int lastHeight = 0;
if (i == dgp.blockRewardVotePercentages.size() - 1) {
lastHeight = nHeight;
} else {
lastHeight = dgp.blockRewardVoteBlocks[i + 1];
}
}

for (int i = lastHeight; i < nHeight; i++) {
if (i >= consensusParams.nRewardFixHeight) {
prevTotalSupplay += (lastPercentage * prevTotalSupplay) / (blocksPerYear * 4);
} else {
prevTotalSupplay += (lastPercentage * prevTotalSupplay) / blocksPerYear;
for (int j = dgp.blockRewardVoteBlocks[i]; j < lastHeight; j++) {
if (j >= consensusParams.nRewardFixHeight) {
prevTotalSupplay += (dgp.blockRewardVotePercentages[i] * prevTotalSupplay) / (blocksPerYear * 4);
} else {
prevTotalSupplay += (dgp.blockRewardVotePercentages[i] * prevTotalSupplay) / blocksPerYear;
}
}
}

if (nHeight >= consensusParams.nRewardOffsetHeight) {
prevTotalSupplay -= consensusParams.nRewardOffsetAmount;
}

int lastPercentage = 0;
for (int i = 0; i < dgp.blockRewardVoteBlocks.size(); i++) {
if (nHeight >= dgp.blockRewardVoteBlocks[i]) lastPercentage = dgp.blockRewardVotePercentages[i];
}

CAmount reward = (lastPercentage * prevTotalSupplay) / blocksPerYear;

return reward / (100 * blocktimeDownscaleFactor);
Expand Down Expand Up @@ -2503,10 +2518,6 @@ bool CheckReward(const CBlock& block, CValidationState& state, int nHeight, cons
error("CheckReward(): coinstake pays too much (actual=%d vs limit=%d)",
nActualStakeReward, blockReward),
REJECT_INVALID, "bad-cs-amount");
uint64_t actualReward = nValueOut - nValueIn;
if (actualReward != subsidy - coinAmountThatSouldBeBurned)
return state.DoS(100, error("CheckReward(): Unknown error caused actual block reward to be different than the expected one"),
REJECT_INVALID, "incorrect-block-reward");

// The first proof-of-stake blocks get full reward, the rest of them are split between recipients
int rewardRecipients = 1;
Expand Down Expand Up @@ -3071,15 +3082,14 @@ bool CheckBlockLydraSpending(std::vector<CTransactionRef> vtx)
{
std::map<CTxDestination, CAmount> addresses_balances;

for (unsigned int i = 0; i < vtx.size(); i++)
{
const CTransaction &tx = *(vtx[i]);
for (unsigned int i = 0; i < vtx.size(); i++) {
const CTransaction& tx = *(vtx[i]);
if (tx.IsCoinBase() || tx.IsCoinStake()) continue;
std::map<CTxDestination, CAmount> addresses_inputs;
std::map<CTxDestination, CAmount> addresses_outputs;
std::set<std::pair<uint256, int>> addresses_index;
std::map<uint256, CTxDestination> addrhash_dest;
std::set<uint256> addresses_index_checked;
std::set<uint256> addresses_index_checked;
for (const CTxIn& txin : tx.vin) {
CTxDestination dest;
CCoinsViewCache view(pcoinsTip.get());
Expand All @@ -3096,16 +3106,16 @@ bool CheckBlockLydraSpending(std::vector<CTransactionRef> vtx)
addresses_inputs[dest] += prevout.nValue;
else
addresses_inputs[dest] = prevout.nValue;
if(!addresses_balances.count(dest)) {
if (!addresses_balances.count(dest)) {
// Get address utxos
std::vector<std::pair<CAddressUnspentKey, CAddressUnspentValue> > unspentOutputs;
std::vector<std::pair<CAddressUnspentKey, CAddressUnspentValue>> unspentOutputs;
if (!GetAddressUnspent(hashBytes, type, unspentOutputs)) {
return false;
}
// Add the utxos to the list if they are mature and at least the minimum value
int coinbaseMaturity = Params().GetConsensus().CoinbaseMaturity(chainActive.Height() + 1);
CAmount rembalance = 0;
for (std::vector<std::pair<CAddressUnspentKey, CAddressUnspentValue> >::const_iterator i=unspentOutputs.begin(); i!=unspentOutputs.end(); i++) {
for (std::vector<std::pair<CAddressUnspentKey, CAddressUnspentValue>>::const_iterator i = unspentOutputs.begin(); i != unspentOutputs.end(); i++) {
int nDepth = chainActive.Height() - i->second.blockHeight + 1;
if (i->second.coinStake && nDepth < coinbaseMaturity)
continue;
Expand All @@ -3118,15 +3128,15 @@ bool CheckBlockLydraSpending(std::vector<CTransactionRef> vtx)
for (size_t j = 0; j < tx.vout.size(); j++) {
const CTxOut& out = tx.vout[j];
CTxDestination dest;
if (ExtractDestination(out.scriptPubKey, dest)) {
if (ExtractDestination(out.scriptPubKey, dest)) {
if (addresses_outputs.find(dest) != addresses_outputs.end())
addresses_outputs[dest] += out.nValue;
else
addresses_outputs[dest] = out.nValue;
}
}
for (const auto& addr_pair : addresses_index) {
// if(addresses_balances.count(addrhash_dest[addr_pair.first]) &&
// if(addresses_balances.count(addrhash_dest[addr_pair.first]) &&
// addresses_inputs.count(addrhash_dest[addr_pair.first]) &&
// addresses_outputs.count(addrhash_dest[addr_pair.first])) {
auto all_inputs = addresses_inputs[addrhash_dest[addr_pair.first]];
Expand All @@ -3138,7 +3148,7 @@ bool CheckBlockLydraSpending(std::vector<CTransactionRef> vtx)
return false;
}
if (!addresses_index_checked.count(addr_pair.first)) {
addresses_balances[addrhash_dest[addr_pair.first]] =
addresses_balances[addrhash_dest[addr_pair.first]] =
addresses_balances[addrhash_dest[addr_pair.first]] - all_inputs + all_outputs;
addresses_index_checked.insert(addr_pair.first);
}
Expand Down Expand Up @@ -3428,10 +3438,10 @@ bool CChainState::ConnectBlock(const CBlock& block, CValidationState& state, CBl
nValueCoinPrev = coin.out.nValue;
}

if(pindex->nHeight >= chainparams.GetConsensus().nLydraOverspendingFixHeight) {
if(!CheckBlockLydraSpending(block.vtx))
return state.DoS(100, error("%s: LYDRA overspending detected", __func__),
REJECT_INVALID, "bad-txns-lydra-overspending");
if (pindex->nHeight >= chainparams.GetConsensus().nLydraOverspendingFixHeight) {
if (!CheckBlockLydraSpending(block.vtx))
return state.DoS(100, error("%s: LYDRA overspending detected", __func__),
REJECT_INVALID, "bad-txns-lydra-overspending");
}

for (unsigned int i = 0; i < block.vtx.size(); i++) {
Expand Down Expand Up @@ -3508,19 +3518,18 @@ bool CChainState::ConnectBlock(const CBlock& block, CValidationState& state, CBl
if (!tx.IsCoinStake()) {
for (const auto& addr_pair : addresses_index) {
// Get address utxos
std::vector<std::pair<CAddressUnspentKey, CAddressUnspentValue> > unspentOutputs;
std::vector<std::pair<CAddressUnspentKey, CAddressUnspentValue>> unspentOutputs;
if (!GetAddressUnspent(addr_pair.first, addr_pair.second, unspentOutputs)) {
//throw error("No information available for address");
// throw error("No information available for address");
}

// Add the utxos to the list if they are mature and at least the minimum value
int coinbaseMaturity = Params().GetConsensus().CoinbaseMaturity(chainActive.Height() + 1);
CAmount rembalance = 0;
for (std::vector<std::pair<CAddressUnspentKey, CAddressUnspentValue> >::const_iterator i=unspentOutputs.begin(); i!=unspentOutputs.end(); i++) {

for (std::vector<std::pair<CAddressUnspentKey, CAddressUnspentValue>>::const_iterator i = unspentOutputs.begin(); i != unspentOutputs.end(); i++) {
int nDepth = chainActive.Height() - i->second.blockHeight + 1;
//if (nDepth < coinbaseMaturity)
//continue;
// if (nDepth < coinbaseMaturity)
// continue;

rembalance += i->second.satoshis;
}
Expand All @@ -3531,9 +3540,9 @@ bool CChainState::ConnectBlock(const CBlock& block, CValidationState& state, CBl
l.getLockedHydraAmountPerAddress(boost::get<CKeyID>(&addrhash_dest[addr_pair.first])->GetReverseHex(), locked_hydra_amount);

if (rembalance - all_inputs + all_outputs < locked_hydra_amount) {
LogPrintf("Address -> %s | rembalance -> %d | spent -> %d | locked -> %d/n",
boost::get<CKeyID>(&addrhash_dest[addr_pair.first])->GetReverseHex(),
rembalance, all_outputs-all_inputs, locked_hydra_amount);
LogPrintf("Address -> %s | rembalance -> %d | spent -> %d | locked -> %d/n",
boost::get<CKeyID>(&addrhash_dest[addr_pair.first])->GetReverseHex(),
rembalance, all_outputs - all_inputs, locked_hydra_amount);
return error("%s: Spending more than available HYDRA amount. The rest is locked for LYDRA tokens.", __func__);
}
}
Expand Down Expand Up @@ -5202,7 +5211,7 @@ bool CheckFirstCoinstakeOutput(const CBlock& block)

#ifdef ENABLE_WALLET
// novacoin: attempt to generate suitable proof-of-stake
bool SignBlock(std::shared_ptr<CBlock> pblock, CWallet& wallet, const CAmount& nTotalFees, uint32_t nTime, std::set<std::pair<const CWalletTx*,unsigned int> >& setCoins, std::vector<COutPoint>& setSelectedCoins, std::vector<COutPoint>& setDelegateCoins, bool selectedOnly, bool tryOnly)
bool SignBlock(std::shared_ptr<CBlock> pblock, CWallet& wallet, const CAmount& nTotalFees, uint32_t nTime, std::set<std::pair<const CWalletTx*, unsigned int>>& setCoins, std::vector<COutPoint>& setSelectedCoins, std::vector<COutPoint>& setDelegateCoins, bool selectedOnly, bool tryOnly)
{
// if we are trying to sign
// something except proof-of-stake block template
Expand All @@ -5228,7 +5237,7 @@ bool SignBlock(std::shared_ptr<CBlock> pblock, CWallet& wallet, const CAmount& n
if (wallet.IsStakeClosing()) return false;
auto locked_chain = wallet.chain().lock();
LOCK(wallet.cs_wallet);
if (wallet.CreateCoinStake(*locked_chain, wallet, pblock->nBits, nTotalFees, nTimeBlock, txCoinStake, key, setCoins, setSelectedCoins, setDelegateCoins, selectedOnly, vchPoD, headerPrevout)){
if (wallet.CreateCoinStake(*locked_chain, wallet, pblock->nBits, nTotalFees, nTimeBlock, txCoinStake, key, setCoins, setSelectedCoins, setDelegateCoins, selectedOnly, vchPoD, headerPrevout)) {
if (nTimeBlock >= chainActive.Tip()->GetMedianTimePast() + 1) {
// make sure coinstake would meet timestamp protocol
// as it would be the same as the block timestamp
Expand All @@ -5237,7 +5246,7 @@ bool SignBlock(std::shared_ptr<CBlock> pblock, CWallet& wallet, const CAmount& n
pblock->hashMerkleRoot = BlockMerkleRoot(*pblock);
pblock->prevoutStake = headerPrevout;

if(tryOnly)
if (tryOnly)
return true;

// Check timestamp against prev
Expand Down Expand Up @@ -7206,7 +7215,7 @@ void CChainState::CheckBlockIndex(const Consensus::Params& consensusParams)
assert(pindex->GetBlockHash() == consensusParams.hashGenesisBlock); // Genesis block's hash must match.
assert(pindex == chainActive.Genesis()); // The current active chain's genesis block must be this block.
}
if (!pindex->HaveTxsDownloaded()) assert(pindex->nSequenceId <= 0); // nSequenceId can't be set positive for blocks that aren't linked (negative is used for preciousblock)
if (!pindex->HaveTxsDownloaded()) assert(pindex->nSequenceId <= 0); // nSequenceId can't be set positive for blocks that aren't linked (negative is used for preciousblock)
// VALID_TRANSACTIONS is equivalent to nTx > 0 for all nodes (whether or not pruning has occurred).
// HAVE_DATA is only equivalent to nTx > 0 (or VALID_TRANSACTIONS) if no pruning has occurred.
if (!fHavePruned) {
Expand All @@ -7227,11 +7236,11 @@ void CChainState::CheckBlockIndex(const Consensus::Params& consensusParams)
assert(nHeight < 2 || (pindex->pskip && (pindex->pskip->nHeight < nHeight))); // The pskip pointer must point back for all but the first 2 blocks.
assert(pindexFirstNotTreeValid == nullptr); // All mapBlockIndex entries must at least be TREE valid
if ((pindex->nStatus & BLOCK_VALID_MASK) >= BLOCK_VALID_TREE)
assert(pindexFirstNotTreeValid == nullptr); // TREE valid implies all parents are TREE valid
assert(pindexFirstNotTreeValid == nullptr); // TREE valid implies all parents are TREE valid
if ((pindex->nStatus & BLOCK_VALID_MASK) >= BLOCK_VALID_CHAIN)
assert(pindexFirstNotChainValid == nullptr); // CHAIN valid implies all parents are CHAIN valid
assert(pindexFirstNotChainValid == nullptr); // CHAIN valid implies all parents are CHAIN valid
if ((pindex->nStatus & BLOCK_VALID_MASK) >= BLOCK_VALID_SCRIPTS)
assert(pindexFirstNotScriptsValid == nullptr); // SCRIPTS valid implies all parents are SCRIPTS valid
assert(pindexFirstNotScriptsValid == nullptr); // SCRIPTS valid implies all parents are SCRIPTS valid
if (pindexFirstInvalid == nullptr) {
// Checks for not-invalid blocks.
assert((pindex->nStatus & BLOCK_FAILED_MASK) == 0); // The failed mask cannot be set for blocks without invalid parents.
Expand Down

0 comments on commit a6869ba

Please sign in to comment.