Skip to content
New issue

Have a question about this project? Sign up for a free GitHub account to open an issue and contact its maintainers and the community.

By clicking “Sign up for GitHub”, you agree to our terms of service and privacy statement. We’ll occasionally send you account related emails.

Already on GitHub? Sign in to your account

EPoSe Movement #1 - EPoW : Proposing Changes in Block Reward Algorithm #78

Open
Xecute0101 opened this issue May 13, 2019 · 65 comments
Open
Assignees
Labels

Comments

@Xecute0101
Copy link
Contributor

@Xecute0101 Xecute0101 commented May 13, 2019

This is the first proposal to change our reward system for Qwertycoin Network.

Purpose: Qwertycoin aims to incentivize/disincentivize the network through a systematic approach by adjusting equations related to block reward calculations.

Current Status:

  1. Basic Block Reward Emission Equation (Abbreviated):
    ((Total Supply - Previously Emitted Supply) / Emission Factor) - Penalty for Block Size

Proposed Change:

  1. Basic Block Reward Emission Equation (Abbreviated):
    (((Total Supply - Previously Emitted Supply) / Emission Factor) - Penalty for Block Size) * ((Timestamp of New Block - Timestamp of Previous Block) / Block Target)

Premises:

  1. The block reward is designed to decrease per each block based on the previous emission.
  2. Since Basic Block Reward Emission is controlled and reduced to a fraction of normal block reward from such attacks, the overall block reward reduction will not be affected by this change.

Implications of This Change:

  1. By reinforcing the consistency of block reward emission over time (instead of block rewards by its sequence in the blockchain), the network hash rate is expected to be supported continuously and find an equilibrium automatically.
  2. Even if an attacker creates a high difficulty for the next block and exit, existing miners are incentivized to receive a huge block reward when they find the next block.
  3. Prevention of attacks with intermittent hash rate jumps must be dealt in a separate issue.
@Xecute0101 Xecute0101 changed the title EPoSe Movement #1 - Proposing Changes in Block Reward Related Equations. EPoSe Movement #1 - Proposing Changes in Block Reward Related Equation. May 13, 2019
@nnian nnian self-assigned this May 13, 2019
@nnian nnian added the enhancement label May 13, 2019
@Xecute0101

This comment has been minimized.

Copy link
Contributor Author

@Xecute0101 Xecute0101 commented May 16, 2019

There shall be lower and upper bounds for this timestamp factor. Considering 2 for upper bound and 0 for lower bound.

@Xecute0101

This comment has been minimized.

Copy link
Contributor Author

@Xecute0101 Xecute0101 commented May 18, 2019

The difficulty algorithm will be modified that it will help to keep the block time as consistent as possible.

@aivve

This comment has been minimized.

Copy link

@aivve aivve commented Jun 3, 2019

You may find something usable here concerning punishing miners for deviation from T seredat/karbowanec@231db52#commitcomment-23983192

@Xecute0101

This comment has been minimized.

Copy link
Contributor Author

@Xecute0101 Xecute0101 commented Jun 3, 2019

I am leaning towards fixing difficulty algo for the efficiency of blockchain instead of controlling the number of blocks:

  1. If there are many pending txs, for an example, under a massive tx attack or we have txs from a lot of users that goes over the maximum size of a transaction set in the config file, diff algo should lowered difficulty to allow those to be included in the blocks and help reduce network backlog and mempool loads. Together with the reward penalty, malicious miners will be penalized for the size of the block, short duration of timestamp between blocks for zero gain.
@aivve

This comment has been minimized.

Copy link

@aivve aivve commented Jun 3, 2019

Joining and synchronizing node can't verify that at the time some block was mined mempool was overcrowded. You can only estimate by taking into account transactions from previous blocks. If transaction count is above median you can lower the difficulty, this way it will be verifiable by the algorithm.

@Xecute0101

This comment has been minimized.

Copy link
Contributor Author

@Xecute0101 Xecute0101 commented Jun 5, 2019

Joining and synchronizing node can't verify that at the time some block was mined mempool was overcrowded. You can only estimate by taking into account transactions from previous blocks. If transaction count is above median you can lower the difficulty, this way it will be verifiable by the algorithm.

So for this, an index of mempool status at the time of the most recent block can be included in the block header blob like an index figure. Is this what you mean?

@aivve

This comment has been minimized.

Copy link

@aivve aivve commented Jun 5, 2019

Yes, but this is an overhead impossible to agree upon and verify, whereas you already have required data that allow you to estimate the demand for transactions - their count in previous blocks. Create a median of transaction count and use it to adjust difficulty to speedup blocks so you can include transactions faster. But this duplicates the job done by variable block size - if there is demand for transactions block size will grow to accommodate. There's no need to speed up block time.

From the other hand thus you will have two mechanisms to cope with the upsurge of transactions in the case of rapid adoption or usage.

@Xecute0101

This comment has been minimized.

Copy link
Contributor Author

@Xecute0101 Xecute0101 commented Jun 10, 2019

This difficulty adjustment will only activate when total pending tx size is beyond max block size. Now when it is below 1mb(current limit).

Even in case when attackers are posting tons of txs to fill up the mempool and lower difficulty for more block rewards, the proposed changes in block rewards will prevent them from any gains. They will just spend a lot of coins.

Yet this difficulty adjustment will improve the efficiency in handling large amount of traffic. To protect nodes from excessive memory use, using database structure such as RocksDB or LMDB for txs in mempool will definitely improve the overall stability.

@nnian

This comment has been minimized.

Copy link
Member

@nnian nnian commented Jun 20, 2019

Is Basic Block Reward Emission Equation (Abbreviated): (((Total Supply - Previously Emitted Supply) / Emission Factor) - Penalty for Block Size) * ((Timestamp of New Block - Timestamp of Previous Block) / Block Target)
the desired new formula for calculating the next block reward? Or do we have to change the formula again?

@Xecute0101

This comment has been minimized.

Copy link
Contributor Author

@Xecute0101 Xecute0101 commented Jun 20, 2019

we just need to multiply ((timestamp of new block - timestamp of previous block)/blocktarget) to existing reward formula.

@Xecute0101

This comment has been minimized.

Copy link
Contributor Author

@Xecute0101 Xecute0101 commented Jun 23, 2019

I propose to create a variable, called Consistency = ((Timestamp of New Block - Timestamp of Previous Block) / Block Target) and set the minimum and maximum range for this variable between 0 and 2.

@Xecute0101

This comment has been minimized.

Copy link
Contributor Author

@Xecute0101 Xecute0101 commented Jun 26, 2019

@speqtr will work on the implementation.

@speqtr

This comment has been minimized.

Copy link
Contributor

@speqtr speqtr commented Jul 1, 2019

Updated block reward formula implementation is available in PR #99.

@speqtr

This comment has been minimized.

Copy link
Contributor

@speqtr speqtr commented Jul 1, 2019

In addition to lower and upper limits (0 and 2) for consistency, I propose to add "smart rounding" for all the values within 0..2 range. This way it will make consistency value more predictable. For example:

  • everything lower than 0.25 should be rounded to 0;
  • everything between 0.25 and 0.75 should be rounded to 0.5;
  • everything between 0.75 and 1.0 should be rounded to 1.0;
  • etc.
@Xecute0101

This comment has been minimized.

Copy link
Contributor Author

@Xecute0101 Xecute0101 commented Jul 2, 2019

Thanks for the input @speqtr.

I think that consistency is just a reflection of what the entire network is doing, So rounding may not be necessary at this point so let's keep that point open to see how network behaves and decide whether to implement rounding or not.

But the number of decimals for consistency may need to be declared. 3 decimal points would be appropriate at the moment, meaning 4th decimal will be rounded to 3rd decimal points.

We need to see how this equation behaves to our current hashrate pattern before deploying. Can you please check? @nnian

@speqtr

This comment has been minimized.

Copy link
Contributor

@speqtr speqtr commented Jul 2, 2019

@nnian I can see that PR #99 was merged first and then instantly reverted (removed from master branch). Do I need to reopen it? Or will you manually re-add changes from PR #99 later?

@nnian

This comment has been minimized.

Copy link
Member

@nnian nnian commented Jul 2, 2019

Maybe you'll open it again and we'll discuss my concerns? With an implementation of a update height. What do you think about? I had commented on your PR a few times just a few minutes ago.

@speqtr

This comment has been minimized.

Copy link
Contributor

@speqtr speqtr commented Jul 2, 2019

@nnian later today I'll open new PR with the same changes as in PR #99 so we could add "activation height" for new block reward formula and then merge it once again.

@nnian

This comment has been minimized.

Copy link
Member

@nnian nnian commented Jul 2, 2019

Okay, sounds great. I think we shouldn't change the block reward without the assurance that every user has the same daemon version.

@speqtr

This comment has been minimized.

Copy link
Contributor

@speqtr speqtr commented Jul 2, 2019

New PR containing updated block reward formula is available. PR #101.

@Xecute0101

This comment has been minimized.

Copy link
Contributor Author

@Xecute0101 Xecute0101 commented Jul 15, 2019

What this change entails...

General PoW Condition

The above graph shows how block reward emission has been for all PoWs. Heavily relying on difficulty to get to that green zone to make the block time and thereby block reward consistent. Miners were able to attack block rewards by utilizing massive hashrate to find blocks in a short period of time.

EPoSe PoW Condition

EPoSe PoW will change this like above graph with a maximum cap up to 2X normal rewards for longer solve time but almost zero block rewards in case of any timestamp attacks by posting many blocks in a short period of time.

With this solution in place, miners will be awarded proportionally to their contribution time to QWC blockchain. Also the block reward emission will be consistent over time. This "time" is the essence of all EPoSe implementations.

Difficulty algo is based on expectation based on previous history whereas this block reward algo is based on the results miners post. Diff algo is very difficult or almost impossible to be precise when there are sudden changes in miners' behavior. EPoSe block reward algo will tame this side effect in short.

This is a major step in order to make PoW part of EPoSe(Egalitarian Proof of Service) fair for all miners and users.

Thanks for the work and I think we can close this issue until we have a problem from this change.

@speqtr

This comment has been minimized.

Copy link
Contributor

@speqtr speqtr commented Jul 15, 2019

Thanks for the work and I think we can close this issue until we have a problem from this change.

@Xecute0101 Hopefully, we won't have any problems with this change 🙂

@aivve

This comment has been minimized.

Copy link

@aivve aivve commented Jul 15, 2019

This makes miners to forge timestamps as close to target as possible to get max reward. The way CN pools operate they are not ready for this, they normally prepare block template with timestamp once and issue it to miners to hash, therefore every CN block has timestamp like one block behind (close to prev. block real solution time). This is easy to fix in pool software (in modified daemon in fact), instead of current timestamp during block template creation they will use prev block timestamp + target. Some fast and large miner may forge timestamps ahead from real time hitting FTL limit, I don't know what happens then and for other honest miners. What happens if miner forges timestamp ahead and then honest miner's solve time becomes negative?

@Xecute0101

This comment has been minimized.

Copy link
Contributor Author

@Xecute0101 Xecute0101 commented Jul 25, 2019

Let's try to make a small change to the equation.

Previously, the most recent change in the formula is like this.


If consistency is less than equal to 1,

New Basic Block Reward Emission Equation (Abbreviated) = Basic Block Reward Emission Equation (previous equation) x consistency

=> If they solve the block too quickly with less effort, miners will get proportionally less rewards. So no more luck factor. If miners try to forge timestamps of blocks close to each other to get more block rewards, they will be penalized.


Else if consistency is greater than 1 and if ((difficulty windows * difficulty target) - (total timestamp difference for the duration of difficulty windows)) is greater than or equal to 0,

Basic Block Reward Emission Equation (previous equation) x
maximum between consistency or (1+ min.((((difficulty windows * difficulty target) - (total timestamp difference for the duration of difficulty windows))/(difficulty target))), 1)

=> If miners or pools try to forge the timestamp before pool operates, it will be compared to range of block's timestamp to see how much time gap there is to allow additional reward. This is the solution for honest miners.


Else if consistency is greater than 1 and if ((difficulty windows * difficulty target) - (total timestamp difference for the duration of difficulty windows)) is less than 0,

Basic Block Reward Emission Equation (previous equation) x 0.0001

=> If miners or pools try to forge the timestamp before pool operates, it will be compared to range of block's timestamp to see how much time gap there is to allow additional reward. If they go over the range of time then all miners will be penalized. So this will force miners and pools to correct the timestamp forging.

In case the hashrate is actually dropping due to less popularity or network issue, this part of equation will not cause any harmful effect as the issuance of new coins will be restricted until the network finds the new equilibrium.


If some miner forge timestamp and the honest miner finds it faster, then miner who forge timestamp will get orphan block. There is really no incentive for them to try to do this. They may succeed in a block or two but will fail shortly after. This may not be the perfect fix but it will serve its purpose for the time being.

@Xecute0101

This comment has been minimized.

Copy link
Contributor Author

@Xecute0101 Xecute0101 commented Jul 25, 2019

Zawy, the difficulty algo dev mentioned this in PR #99 that

But make sure out of sequence timestamps are handled correctly:

// Safely handle out-of-sequence timestamps
if ( timestamps[i]  >= previous_timestamp ) {   this_timestamp = timestamps[i];  } 
else {  this_timestamp = previous_timestamp+1;   }

Do we have this measure in place? If not, we should. @speqtr @Sw0rdf1sh1 @nnian

@aivve

This comment has been minimized.

Copy link

@aivve aivve commented Feb 12, 2020

Just tighten the limits so they can't fake timestamps.

@Xecute0101

This comment has been minimized.

Copy link
Contributor Author

@Xecute0101 Xecute0101 commented Feb 12, 2020

We need to get this calculation right, first I think. If anyone of you is going to test this, change the height in the config and try to see the error msg displays correct rewards.

@aivve

This comment has been minimized.

Copy link

@aivve aivve commented Feb 12, 2020

Also originally doubles were avoided in CryptoNote... Perhaps find a way to calculate this using integer math.

@zawy12

This comment has been minimized.

Copy link

@zawy12 zawy12 commented Feb 12, 2020

Increasing reward based on solvetime has the same effect as decreasing difficulty. Miners are only interested in getting the highest reward/difficulty ratio.

Another option I've been thinking about (that deadalnix and jl777 like) actually depends on on-off mining. The idea is that your dedicated miners can be identified as being the ones who are still mining when the difficulty is high. Ostensibly, they will not attack the coin and you want them to win in a chain race. They paid a higher price in the past so give them something extra to win chain races. As an example plan, if difficulty is more than 1 std deviation (16% of blocks) above the 1 day average, then credit the miner's output address with 1/2 of the above-average difficulty. This can be thought of as a 2nd coin that can't be sent to any other address. If there is a battle between 2 or more tips with at least 3 blocks each, then miners with this coin saved up from the past can use it to artificially lower difficulty to win a chain race. They can "get back" 1/2 of the excess difficulty they spent on blocks that were in the the upper 16% of difficulties. It specifically is NOT meant to motivate the mining of higher difficulty. We want higher difficulty so that we can identify our friends, and let them win chain races. A limit might be placed on the amount of "credit" they can get, and the credit might deteriorate over a year. So if you have 10% of your miners really dedicated, and 16% of your difficulty swings everyday are 20% too high, then that 10% of miners are getting 16% / 2 * 20% = 1.6% of the day's chain work back as credit. In 100 days they will 160% of a days chain work to fight attacks.

I need to do an issue-article on this.

@Xecute0101

This comment has been minimized.

Copy link
Contributor Author

@Xecute0101 Xecute0101 commented Feb 12, 2020

Yes, it should be deleted

Or just in case, commenting out the line would be okay too.

@Xecute0101

This comment has been minimized.

Copy link
Contributor Author

@Xecute0101 Xecute0101 commented Feb 12, 2020

2020-Feb-12 15:50:23.631190 ERROR Coinbase transaction spend too much money: 135845.06483386, block reward is 67922.53241693

This happened when consistency was not used and I wanted to test out where to put this consistency variable. It just happens to be right after baseReward. I just did "*0.5" like this.

uint64_t baseReward = ((m_moneySupply - alreadyGeneratedCoins) >> m_emissionSpeedFactor) * 0.5;

bool Currency::getBlockReward(
    uint8_t blockMajorVersion,
    size_t medianSize,
    size_t currentBlockSize,
    uint64_t alreadyGeneratedCoins,
    uint64_t fee,
    uint64_t &reward,
    int64_t &emissionChange,
    uint32_t height,
    uint64_t blockTarget) const
{
    assert(alreadyGeneratedCoins <= m_moneySupply);
    assert(m_emissionSpeedFactor > 0 && m_emissionSpeedFactor <= 8 * sizeof(uint64_t));
    
    // Consistency

    double consistency = 1.0;
    if (height >= CryptoNote::parameters::UPGRADE_HEIGHT_REWARD_SCHEME && difficultyTarget() != 0) {
        // blockTarget is (Timestamp of New Block - Timestamp of Previous Block)
        consistency = blockTarget / difficultyTarget();

        // consistency range is 0..2
        consistency = std::max<double>(consistency, 0.0);
        consistency = std::min<double>(consistency, 2.0);
    }

    // Tail emission

    uint64_t baseReward = ((m_moneySupply - alreadyGeneratedCoins) >> m_emissionSpeedFactor) * 0.5;
    if (alreadyGeneratedCoins + CryptoNote::parameters::TAIL_EMISSION_REWARD >= m_moneySupply
        || baseReward < CryptoNote::parameters::TAIL_EMISSION_REWARD) {
        baseReward = CryptoNote::parameters::TAIL_EMISSION_REWARD;
    }

    size_t blockGrantedFullRewardZone = blockGrantedFullRewardZoneByBlockVersion(blockMajorVersion);
    medianSize = std::max(medianSize, blockGrantedFullRewardZone);
    if (currentBlockSize > medianSize * UINT64_C(2)) {
        logger(TRACE)
            << "Block cumulative size is too big: "
            << currentBlockSize
            << ", expected less than "
            << medianSize * UINT64_C(2);
        return false;
    }

    uint64_t penalizedBaseReward = getPenalizedAmount(baseReward, medianSize, currentBlockSize);
    uint64_t penalizedFee = fee;
    if (blockMajorVersion >= BLOCK_MAJOR_VERSION_2 || cryptonoteCoinVersion() == 1) {
        penalizedFee = getPenalizedAmount(fee, medianSize, currentBlockSize);
    }

    uint64_t penalizedReward = static_cast<uint64_t>(penalizedBaseReward + penalizedFee);

    emissionChange = penalizedReward - fee;
    reward = static_cast<uint64_t>(penalizedReward);

    return true;

I also tried to multiply consistency in place of 0.5, then the block reward was 0.0000000000. This means that the consistency is returning 0.

2020-Feb-13 07:01:37.370251 ERROR Coinbase transaction doesn't use full amount of block reward: spent 135845.06483386, block reward is 16301407.78006320

Above happens when difficultyTarget() is multiplied in place of 0.5 meaning the value of difficultyTarget() is 120 and it is returning value properly.

2020-Feb-13 07:05:48.258607 ERROR Coinbase transaction doesn't use a full amount of block reward: spent 135845.06483386, block reward is 9101619.34386862

Above happens when blockTarget() is multiplied in place of 0.5 meaning the value of blockTarget() is 67 and it is returning value properly.

@Xecute0101

This comment has been minimized.

Copy link
Contributor Author

@Xecute0101 Xecute0101 commented Feb 13, 2020

When Coinbase transaction is less than reward (minerReward<reward), following msg should be displayed per Blockchain::validate_miner_transaction() in Blockchain.cpp file.

if (minerReward > reward) {
        logger(ERROR, BRIGHT_RED)
            << "Coinbase transaction spend too much money: " << m_currency.formatAmount(minerReward)
            << ", block reward is " << m_currency.formatAmount(reward);

2020-Feb-13 07:15:41.977399 ERROR Coinbase transaction spend too much money: 135845.06483386, block reward is 75846.82786557

The above happens when the following code changed.

consistency = (double)blockTarget / (double)difficultyTarget();

uint64_t baseReward = ((m_moneySupply - alreadyGeneratedCoins) >> m_emissionSpeedFactor) * consistency;

When Coinbase transaction is greater than reward (minerReward>reward), the following msg should be displayed per Blockchain::validate_miner_transaction() in Blockchain.cpp file.

else if (minerReward < reward) {
        logger(ERROR, BRIGHT_RED)
            << "Coinbase transaction doesn't use full amount of block reward: spent "
            << m_currency.formatAmount(minerReward)
            << ", block reward is "
            << m_currency.formatAmount(reward);

Correct messages were displayed from the examples of previous comment.

@Xecute0101

This comment has been minimized.

Copy link
Contributor Author

@Xecute0101 Xecute0101 commented Feb 13, 2020

The working code looks like

bool Currency::getBlockReward(
    uint8_t blockMajorVersion,
    size_t medianSize,
    size_t currentBlockSize,
    uint64_t alreadyGeneratedCoins,
    uint64_t fee,
    uint64_t &reward,
    int64_t &emissionChange,
    uint32_t height,
    uint64_t blockTarget) const
{
    // assert(alreadyGeneratedCoins <= m_moneySupply);
    assert(m_emissionSpeedFactor > 0 && m_emissionSpeedFactor <= 8 * sizeof(uint64_t));
    
    // Consistency

    double consistency = 1.0;
    if (height >= CryptoNote::parameters::UPGRADE_HEIGHT_REWARD_SCHEME && difficultyTarget() != 0) {
        // blockTarget is (Timestamp of New Block - Timestamp of Previous Block)
        consistency = (double) blockTarget / (double) difficultyTarget();

        // consistency range is 0..2
        consistency = std::max<double>(consistency, 0.0);
        consistency = std::min<double>(consistency, 2.0);
    }

    // Tail emission

    uint64_t baseReward = ((m_moneySupply - alreadyGeneratedCoins) >> m_emissionSpeedFactor) * consistency;
    if (alreadyGeneratedCoins + CryptoNote::parameters::TAIL_EMISSION_REWARD >= m_moneySupply
        || baseReward < CryptoNote::parameters::TAIL_EMISSION_REWARD) {
        baseReward = CryptoNote::parameters::TAIL_EMISSION_REWARD;
    }

    size_t blockGrantedFullRewardZone = blockGrantedFullRewardZoneByBlockVersion(blockMajorVersion);
    medianSize = std::max(medianSize, blockGrantedFullRewardZone);
    if (currentBlockSize > medianSize * UINT64_C(2)) {
        logger(TRACE)
            << "Block cumulative size is too big: "
            << currentBlockSize
            << ", expected less than "
            << medianSize * UINT64_C(2);
        return false;
    }

    uint64_t penalizedBaseReward = getPenalizedAmount(baseReward, medianSize, currentBlockSize);
    uint64_t penalizedFee = fee;
    if (blockMajorVersion >= BLOCK_MAJOR_VERSION_2 || cryptonoteCoinVersion() == 1) {
        penalizedFee = getPenalizedAmount(fee, medianSize, currentBlockSize);
    }

    emissionChange = penalizedBaseReward - (fee - penalizedFee);
    reward = penalizedBaseReward + penalizedFee;

    return true;
}

@nnian @exploshot @speqtr @aivve

@Xecute0101 Xecute0101 changed the title EPoSe Movement #1 - Proposing Changes in Block Reward Related Equation. EPoSe Movement #1 - Proposing Changes in Block Reward Algorithm Feb 16, 2020
@Xecute0101

This comment has been minimized.

Copy link
Contributor Author

@Xecute0101 Xecute0101 commented Feb 21, 2020

Added #include <cmath> and double exponent = 0.25;
and changed consistency formula when it is above 1.

bool Currency::getBlockReward(
    uint8_t blockMajorVersion,
    size_t medianSize,
    size_t currentBlockSize,
    uint64_t alreadyGeneratedCoins,
    uint64_t fee,
    uint64_t &reward,
    int64_t &emissionChange,
    uint32_t height,
    uint64_t blockTarget) const
{
    // assert(alreadyGeneratedCoins <= m_moneySupply);
    assert(m_emissionSpeedFactor > 0 && m_emissionSpeedFactor <= 8 * sizeof(uint64_t));
    
    // Consistency
    double consistency = 1.0;
    double exponent = 0.25; 
    if (height >= CryptoNote::parameters::UPGRADE_HEIGHT_REWARD_SCHEME && difficultyTarget() != 0) {
        // blockTarget is (Timestamp of New Block - Timestamp of Previous Block)
        consistency = (double) blockTarget / (double) difficultyTarget();
        
        // consistency range is 0..2
        if (consistency < 1.0) {
            consistency = std::max<double>(consistency, 0.0);
        }
        else if (consistency > 1.0) {
            consistency = pow(consistency, exponent);
            consistency = std::min<double>(consistency, 2.0);
        }
        else {
            consistency = 1.0;
        }
    }  
        
    // Tail emission
    uint64_t baseReward = ((m_moneySupply - alreadyGeneratedCoins) >> m_emissionSpeedFactor) * consistency;
    if (alreadyGeneratedCoins + CryptoNote::parameters::TAIL_EMISSION_REWARD >= m_moneySupply
        || baseReward < CryptoNote::parameters::TAIL_EMISSION_REWARD) {
        baseReward = CryptoNote::parameters::TAIL_EMISSION_REWARD;
    }

    size_t blockGrantedFullRewardZone = blockGrantedFullRewardZoneByBlockVersion(blockMajorVersion);
    medianSize = std::max(medianSize, blockGrantedFullRewardZone);
    if (currentBlockSize > medianSize * UINT64_C(2)) {
        logger(TRACE)
            << "Block cumulative size is too big: "
            << currentBlockSize
            << ", expected less than "
            << medianSize * UINT64_C(2);
        return false;
    }

    uint64_t penalizedBaseReward = getPenalizedAmount(baseReward, medianSize, currentBlockSize);
    uint64_t penalizedFee = fee;
    if (blockMajorVersion >= BLOCK_MAJOR_VERSION_2 || cryptonoteCoinVersion() == 1) {
        penalizedFee = getPenalizedAmount(fee, medianSize, currentBlockSize);
    }

    emissionChange = penalizedBaseReward - (fee - penalizedFee);
    reward = penalizedBaseReward + penalizedFee;

    return true;
}
@Xecute0101

This comment has been minimized.

Copy link
Contributor Author

@Xecute0101 Xecute0101 commented Feb 21, 2020

For mining rewards over 120 seconds, double exponent = 0.25; is used for raising consistency to a power of (1/4). The impact of this is shown in the attached excel file. EPoW.Worksheet R0.xlsx

Any extra time over difficulty target(120 sec) will get additional reward but does not provide enough incentives to forge a timestamp beyond the real time because it yields less profit than mining a next block less than 120 seconds.

image

The significance of QWC's EPoW is that it is a completely independent approach to influence miners' behaviors from difficulty adjustments and an egalitarian reward system to all mining environments.

I think we are ready to commit this to our main repo. Any devil's advocate?
@nnian @speqtr @aivve @zawy12 @exploshot

@Xecute0101

This comment has been minimized.

Copy link
Contributor Author

@Xecute0101 Xecute0101 commented Feb 21, 2020

You can find PR to dev repo from here.

@zawy12

This comment has been minimized.

Copy link

@zawy12 zawy12 commented Feb 21, 2020

It appears you're make substantial changes to reward if there is a fast solvetime. The purpose of the solvetime is to prevent orphans due to finding blocks at about the same time. So you don't want to motivate a narrow range of mining with > 20% changes in difficulty per block, or it indicates you should have been already been using blocks 1/2 the size that come 2x faster. In other words, if this is right, 120 seconds was always wrong.

More importantly, you don't want to give an advantage to on-off mining over dedicated mining like this, unless you change the required POW every block, which would be a great improvement to security that I discuss here.

The max change per block I would do would be about 20% less reward (or 20% higher difficulty which is the same thing) for having a solvetime of 1 second. It should be done like the following which is about a 1% change per 6 seconds for T=120, So your FTL needs to be less than 6 seconds. An selfish mine attacker will find that there is no way to manipulate this to increase his gains above simply using honest timestamps. This formula will not throw off you coin emission rate if hashrate is constant and in most cases even if hashrate is varying. This is a more precise version of what I said July 2019.

// Disallow negative solvetimes by method you posted July 19 above (that I just now saw)
maxFractionChange = 0.2; //  20%
N= 1/maxFractionChange;  // N=5
T=120;
Reward = RewardPerBlock * (1 + currentSolveTime/T/N - 1/N);

I do not know for sure the above will keep coin emission rate and total coin emission correct. After thinking about how to make sure coin emission is correct, I wrote an article Perfecting Coin Emission Rate. Plug the RewardPerBlock from that article into the above reward formula.

To prevent negative solvetimes, sequential timestamps on block headers must be forced (even if honest miners have to get a fake timestamp in the template and even if it is past the FTL), or something like this code must be used:

previous = timestamps[0];
for ( uint64_t i = 1; i <= N; i++) {  // N is most recent block
      if (timestamps[i] > previous_timestamp  ) {   
            this_timestamp = timestamps[i];
      } else {  this_timestamp = previous_timestamp+1 ;   }
      solvetimes[i] = this_timestamp - previous_timestamp;
      previous_timestamp = this_timestamp;
}
// do algorithm with the individual solvetimes stored in solvetimes vector.
@Xecute0101

This comment has been minimized.

Copy link
Contributor Author

@Xecute0101 Xecute0101 commented Feb 21, 2020

@zawy12 Thanks for your opinion.

EPoW reward algorithm is entirely different from the conventional reward algorithm as you can see in the graph. When miners have a faster solvetime, their block reward is reduced proportionally until 120 seconds. This is not promoting miners to mine quicker at all.

Miners simply don't have any incentives to influence thereby fluctuate > 20% difficulty at all under 120 seconds. More so after 120 seconds. They just need to mine with their honest hash rate to get the maximum benefit.

Regarding on-off mining, that is like holding a lot of hash rate and dumping it at a specific instance when miners get the best reward/difficulty ratio or rewards/mining. The current system is also susceptible as well as after EPoW algorithm. That is another important subject that needs to be dealt with separately besides this update.

Negative solvetime will yield zero. So that is a miners' dumb move because it give consistency a value of zero. nada for blockReward.

const uint64_t CRYPTONOTE_BLOCK_FUTURE_TIME_LIMIT_V1 = DIFFICULTY_TARGET * 6;

This part needs to be narrowed down to let's say 10 seconds from current 720 seconds to prevent miners fooling around with timestamp.

@Xecute0101

This comment has been minimized.

Copy link
Contributor Author

@Xecute0101 Xecute0101 commented Feb 21, 2020

previous = timestamps[0];
for ( uint64_t i = 1; i <= N; i++) {  // N is most recent block
      if (timestamps[i] > previous_timestamp  ) {   
            this_timestamp = timestamps[i];
      } else {  this_timestamp = previous_timestamp+1 ;   }
      solvetimes[i] = this_timestamp - previous_timestamp;
      previous_timestamp = this_timestamp;
}
// do algorithm with the individual solvetimes stored in solvetimes vector.

Shouldn't this be included in the block validation portion of the code?

@zawy12

This comment has been minimized.

Copy link

@zawy12 zawy12 commented Feb 21, 2020

Yes, it would be better to simply force sequential timestamps instead of using that code.

I understand what you're doing. A >51% attacker strike>will may likely do a selfish mine and set every timestamp equal to target solvetime. This will make his blocks < 1/2 the cost of your dedicated miners who are more likely to get fast solvetimes due to the exponential distribution. Even simply opportunistic on-off mining getting any block taking longer than average will cause dedicated miner to suffer loses. The dedicated miners are the only source of security.

You could make your method less severe against the fast solvetimes (or use my precise method) and combine it with my dedicated miner credit system to stop any 51% attack in its tracks. This is what I described in a long paragraph above on February 12, turned into an article to describe it more fully.

@Xecute0101

This comment has been minimized.

Copy link
Contributor Author

@Xecute0101 Xecute0101 commented Feb 21, 2020

The only way I see the proposed formula is that the relaxation of blockReward using

Reward = RewardPerBlock * (1 + currentSolveTime/T/N - 1/N);

gives more incentives (within the initial window of 120 seconds) for larger miners to get larger block rewards by doing on-off mining or doing normal mining with higher probability of winning block rewards for less work. Isn't this true? Or am I not properly understanding your equation?

I was going to write about the 51% attack but it was another subject so I erased it and I really resent doing so. We know that the only way to reduce the risk of 51% attack is to reduce the difficultyTarget to a lower number when blockReward is fixed per block. At 1 second time, even 9 to 1 hash distribution still gives the minority to win at 11%.

Under EPoW, when a 51% attacker decided to broadcast at difficultytarget for the maximum reward even though he/she found the block at an earlier time or a large on-off miner, who dont want to increase difficulty by coming in early under EPoW due to less reward and therefore come in at larger reward timing, it gives more chances to the minority to work on solving until the time larger miners broadcast.

The accumulation of probability in finding a block is far greater and egalitarian to the minority miners in this case.

I mean all in all, isn't this better than current block reward algorithm?

@zawy12

This comment has been minimized.

Copy link

@zawy12 zawy12 commented Feb 21, 2020

To explain my equation, from 1 second to 2x T seconds, reward goes from 80% to 120% of the baseline reward. You get the baseline reward for giving a block a timestamp (solvetime) of T=120. I don't really understand your questions or points. My point is that it can be done, but it strongly motivates large miners to do a selfish mine. If they can't change coins in about 30 seconds, it sort of requires them to do a selfish mine. Even my 20% is a large motivation to do a selfish mine. There's not a good solution except to suffer as usual or become a KMD coin.

@Xecute0101 Xecute0101 changed the title EPoSe Movement #1 - Proposing Changes in Block Reward Algorithm EPoSe Movement #1 - EPoW : Proposing Changes in Block Reward Algorithm Feb 22, 2020
@Xecute0101 Xecute0101 changed the title EPoSe Movement #1 - EPoW : Proposing Changes in Block Reward Algorithm EPoSe Movement #1 - EPoW:Proposing Changes in Block Reward Algorithm Feb 22, 2020
@Xecute0101

This comment has been minimized.

Copy link
Contributor Author

@Xecute0101 Xecute0101 commented Feb 22, 2020

@zawy12, I fully understand the impact of the equation but was not agreeing on how it is better and its implications on changes in miners' behaviors. I do appreciate sharing your thoughts and opinions. I am glad that we have different opinions in a way.

@Xecute0101 Xecute0101 changed the title EPoSe Movement #1 - EPoW:Proposing Changes in Block Reward Algorithm EPoSe Movement #1 - EPoW : Proposing Changes in Block Reward Algorithm Feb 22, 2020
@zawy12

This comment has been minimized.

Copy link

@zawy12 zawy12 commented Feb 22, 2020

I can't follow what you're saying except that you think it's not going to be a problem. I'm saying it's a risk. I'm not sure I've said anything that is an opinion.

The exponential distribution means 63% of blocks are found less than T. 50% are less than 0.69xT.
An integral I just did indicates those 63% of blocks will get an average reward of 0.26 of the baseline. The rest of the solves will take substantially loner so that the average solvetime will be T. A 51% miner doing a selfish mine will also find a lot of fast blocks and a few really long-solvetime blocks. He only needs to set timestamps for every solvetime equal to T so he sacrifices the few large rewards to not suffer all the large discounts in reward that he would have gotten like the other miners, so he gets at least 3x what your dedicated miners will be getting. So instead of getting 2x profit from normal 50% selfish mining attack that gets 100% of the blocks, he'll get about 3x to 4x more profit than honest miners.

@Xecute0101

This comment has been minimized.

Copy link
Contributor Author

@Xecute0101 Xecute0101 commented Feb 22, 2020

I created a model based on your description. Take a look at it first. EPoW Worksheet R1.xlsx

In the sheet RS 0-240 63% Modeling, you will see that reward penalty from your equation is not stringent enough over time to change larger miners' behaviors of fast mining because within that time frame the reward/second is still way too big.

Power of 1/2 seems to yield the closest penalty for the reduction % in mining time for larger miners but chose 1/4 in the current PR just to be on the safe side.

Larger miners will reject selfish mining because their rewards will be substantially less for doing so.
If they are after taking the maximum block reward at 120 seconds, honest miners have more additional time to solve the block before them unlike how it is done now.

@zawy12

This comment has been minimized.

Copy link

@zawy12 zawy12 commented Feb 22, 2020

If they are after taking the maximum block reward at 120 seconds, honest miners have more additional time to solve the block before them unlike how it is done now.

On average, your normal miners will solve blocks at 120 s if there is no on-off mining. If there is on-off mining to get the higher reward, there will not be many long solvetimes to bring the average down to offset the fast solvetimes, so the dedicated miners will have to suffer a larger difficulty for the < 120 solves in order to keep the avg 120 s. A > 50% will look at this and say "there's no way I'm going to accept 1/2 or 1/3 reward by giving fast solvetimes" and he will set all his timestamps to 119 seconds to beat out both the dedicated miners and the on-off miners in a secret aka private aka selfish mine for as many blocks as he wants. If there is no on-off mining then the private mine will only give the normal 100% benefit no matter what his timestamps, as long as they are not too far into the future and you have a tight FTL.

Typically, like your coin in the past, the on-off miners will come in at >3x and sometimes 40x your baseline (dedicated) hashrate if your difficulty is 5% to 20% below average, and stop when it is 5% to 20% above average. See your chart below from January 2019. It sounds like you have a much different assumption about miner motivation. This is why I suggest a "small" +/- 20% change. The 20% is a large value for me because it is pushing the limits of what I consider safe, trying to not encourage miners from doing the on-off mining which will encourage constant private mining attacks.

image

@Xecute0101

This comment has been minimized.

Copy link
Contributor Author

@Xecute0101 Xecute0101 commented Feb 22, 2020

Then now, I will assess two more models along with decision trees.
One with optimized on-off mining and one without it. I will post an update soon.

Assumption 1)
A > 50% will look at this and say "there's no way I'm going to accept 1/2 or 1/3 reward by giving fast solvetimes" and he will set all his timestamps to 119 seconds to beat out both the dedicated miners and the on-off miners in a secret aka private aka selfish mine for as many blocks as he wants.

Assumption 2)
If there is no on-off mining then the private mine will only give the normal 100% benefit no matter what his timestamps, as long as they are not too far into the future and you have a tight FTL.

@Xecute0101

This comment has been minimized.

Copy link
Contributor Author

@Xecute0101 Xecute0101 commented Feb 22, 2020

My assumptions are the followings:

Large Miner Behaviour #1 a-1) Secret, Selfish, Private Mining (Realistic)

r1a-1) Since rewards is proportional to reported solvetime (block timestamp) up to 120 seconds from previous block timestamp, mining many short solvetime blocks will only increase difficulty without any additional gains as was in CryptoNote block reward algorithm.

r2a-1) A miner wants to maximize rewards all the time, therefore, post the optimum timestamp = previous timestamp + 120 seconds though the block was solved before the posted timestamp.

r3a-1) Posting timestamp = previous timestamp + 120 seconds allows large portion of honest miners to take advantage of additional solvetime until previous timestamp + 120 seconds.

r4a-1) Win/Loss ratio within 120 seconds timestamp period will be determined by the distribution of hash rate between participating parties.

r5a-1) So the miner considers doing on-off mining with 119 seconds timestamp.

r6a-1) The best on-off mining timing and duration will be determined by the private or secrete hash rate.

r7a-1) The on-off mining practice shall not influence difficulty too much.

Large Miner Behaviour #2 a-2) 100% Honest Mining (Unrealistic)

r1a-2) Receives proportional rewards based on actual mining time / design mining time.
r2a-2) Difficulty algorithm operates within its equilibrium range.
r3a-2) Preventing larger miners to win more blocks is unavoidable. This can be forcefully done using reward distribution change including uptime nodes.

@zawy12

This comment has been minimized.

Copy link

@zawy12 zawy12 commented Feb 22, 2020

"Assumption 1)" describes a security hole. It may not happen if the coin can't be easily sold on an exchange. Assuming a security hole will be exploited is the only correct assumption.

"Assumption 2)" is a mathematical fact (except it's too optimistic, see below). An attacker will mine with>50%, getting the 119 s stamps quickly (say, with 60% or 80% HR), but he will hold them until the future time arrives. If some other chain has more work by that time (they accidentally solved their blocks faster than his timestamps at 119 s), then he has to come back and mine a few more blocks with low reward to pull back ahead.

Your spreadsheet columns look like they are calculating rewards but you call the "solvetimes". If the difficulty and hashrate are stable, all of them have the same solvetime which is the time column.

I forgot that your method is not "symmetrical" so your rewards are showing around 20% below CN rewards. Due to this my Assumption 2 is 20% too optimistic. A selfish mine will get 120% of coin instead of the 50% if he was an honest miner. My algorithm is symmetrical which is why the rewards are the same as CN. There's no additional 20% gain from selfish mining because it has the correct kind of symmetry. You're having to do a lot of modelling because of the lack of symmetry and you're looking for an optimal tradeoff based on intuition. My equation is the optimal one.

@Xecute0101

This comment has been minimized.

Copy link
Contributor Author

@Xecute0101 Xecute0101 commented Feb 23, 2020

@zawy12, it was a nice discussion and thanks for the valuable input. We will test both algos and implement what fits the best to our intention.

Sign up for free to join this conversation on GitHub. Already have an account? Sign in to comment
Projects
None yet
Linked pull requests

Successfully merging a pull request may close this issue.

None yet
5 participants
You can’t perform that action at this time.