I'm hoping to find a current reference that explains how the dynamic block size/fee calculation works? This link has a nice explanation, but a community member on reddit suggested it was out-of-date (and the numbers computed certainly don't match up with today's ultra low fees). There's another excellent reference here that explains the block size penalty, but I think it may also be out-of-date, or at least I don't quite understand how to calculate the fee from just this information... especially during "normal" operation where there is no penalty.

It also seems like this would leave the Monero vulnerable to moderate spam attacks given the current medians block sizes are so far below 300 kB... I know the Monero team is pretty on top of these things, so assuming they have implemented additional safeguards?

I think ultimately I'm trying to figure out: - how does Monero set the fee during normal operation? - what safeguards (price disincentives) are in place to protect the blockchain against a spam attack?

Thanks for any ideas! I apologize if there is an answer floating around to this question, but I couldn't find it... and trying to interpret the source code is not going too well.

2 Answers 2


I can only provide a partial answer. I had a similar question How are fees computed? and was linked to the same note on fees that you mentioned. I ultimately found the note to be out of date as well.

It looks like the only description available is to read the code. I believe the fee is being computed in Blockchain::get_dynamic_base_fee and the method seems to depend on whether the version is using fee per byte or per kilo-byte (I believe currently the former is the case).

However, you should be aware that this is not actually fee per byte of transaction size! I guess that would be too easy. It's in fact a based on transaction weight. For most transactions weight = size, but for bulletproof transactions with more than (I think) two outputs, it is computed in a different way. For these transactions weight > size. My guess this is to make sure that these transactions are not too cheap.

It's been awhile since I looked at that, so I forget the exact calculation. If you find it please share.

Edit: Based on the comments below, I believe the weight is computed as follows.

Let s be the size of the transaction, and o be the number of outputs, and w be the weight.

  • If o < 3 then w = s, otherwise
  • Let b = 368
  • Let l be the size of the vector L associated with the transactions bulletproof*
  • Let c = 0.8(b * 2^(l - 6) - 32(9 + 2l))
  • Then w = s + c

*Sorry I am not sure what the L vector is, but it seems to be associated with number of outputs, maybe 6 + log(number_of_outputs)?

Also, basically the base fee per byte is computed as:

(r * 3000 * 2^64) / 5*(300000^2)

Where r is the current block reward. The calculation is provided that median block size is < 300000 bytes which I believe normally is the case.

Please, if this is wrong correct me. I just thought it might be nice to have written up somewhere, so people dont have to go through the code everytime.

  • Bulletproofs scale logarithmically with respect to size. The weight parameter simply accounts for this 'discrepancy'.
    – dEBRUYNE
    Sep 26, 2019 at 13:24
  • Do you remember or have a reference to the algorithm to compute weight? Sep 26, 2019 at 14:11
  • 1
    @PyrolitePancake here
    – jtgrassie
    Sep 26, 2019 at 18:34
  • There is also some further explanation in this thread: reddit.com/r/Monero/comments/av0cn3/…
    – dEBRUYNE
    Sep 26, 2019 at 18:42
  • Thanks for taking the time to write this up! I agree it looks correct based on the source code. Going to try to plug in some numbers later and see if they line up with recent fees.
    – rsi33
    Sep 27, 2019 at 14:56

I'm going to do my best to answer your questions but I'm afraid I'm no ArticMine, who I'm sure could answer far more eloquently.

I'm hoping to find a current reference that explains how the dynamic block size/fee calculation works? ... how does Monero set the fee during normal operation?

Beyond the code (e.g. source for getting a fee estimate), A note on fees is the most recent explanation I can find. And whilst there have been tweaks since the addition of Bulletproofs, it is largely still relevant/accurate.

The biggest change to the various calculations when Bulletproofs were introduced, was a need to factor in the huge space savings Bulletproofs introduced. Therefore, instead of simply using size as weight, the notion of a "clawback" was introduced to offset this space saving when calculating a txs weight. This can be observed in commit 5ffb2ff9. Therefore, whilst the terms size and weight were previously the same thing (e.g. size), weight no longer strictly equals size.

Another recent change can be observed in commit b8787f43, quoting the commit message:

ArticMine's new block weight algorithm

This curbs runaway growth while still allowing substantial
spikes in block weight

Original specification from ArticMine:

here is the scaling proposal
Define: LongTermBlockWeight
Before fork:
LongTermBlockWeight = BlockWeight
At or after fork:
LongTermBlockWeight = min(BlockWeight, 1.4*LongTermEffectiveMedianBlockWeight)
Note: To avoid possible consensus issues over rounding the LongTermBlockWeight for a given block should be calculated to the nearest byte, and stored as a integer in the block itself. The stored LongTermBlockWeight is then used for future calculations of the LongTermEffectiveMedianBlockWeight and not recalculated each time.
Define:   LongTermEffectiveMedianBlockWeight
LongTermEffectiveMedianBlockWeight = max(300000, MedianOverPrevious100000Blocks(LongTermBlockWeight))
Change Definition of EffectiveMedianBlockWeight
From (current definition)
EffectiveMedianBlockWeight  = max(300000, MedianOverPrevious100Blocks(BlockWeight))
To (proposed definition)
EffectiveMedianBlockWeight  = min(max(300000, MedianOverPrevious100Blocks(BlockWeight)), 50*LongTermEffectiveMedianBlockWeight)
1) There are no other changes to the existing penalty formula, median calculation, fees etc.
2) There is the requirement to store the LongTermBlockWeight of a block unencrypted in the block itself. This  is to avoid possible consensus issues over rounding and also to prevent the calculations from becoming unwieldy as we move away from the fork.
3) When the  EffectiveMedianBlockWeight cap is reached it is still possible to mine blocks up to 2x the EffectiveMedianBlockWeight by paying the corresponding penalty.

Note: the long term block weight is stored in the database, but not in the actual block itself,
since it requires recalculating anyway for verification.

It also seems like this would leave the Monero vulnerable to moderate spam attacks ... what safeguards (price disincentives) are in place to protect the blockchain against a spam attack?

Now we need to take a step back. A spender putting too much data in a tx, they pay higher tx fees. Send lots of txs, they have to pay the fees on each. But, in general, a spam attacker wants to get these txs onto the blockchain, so now we need to also look from the miners perspective. A miner is incentivized to produce blocks of optimum size based on normal network usage. Trying to stuff the blocks with too many txs based on past/recent usage, they get penalized. For an attacker to incentivize miners to create larger than normal blocks, fees would need to go up, to compensate for the reward penalty. Therefore to flood the blockchain with spam txs, the more one deviates from normal usage, the more it's going to cost. This is why fees are calculated not just on tx weight, but also median block weight.

  • Thanks for the helpful reply. Seems like the longer term blockweight median will considerably increase the pain felt by a determined spammer. Is it correct to say that during a period of increased transactions (whether spam or due to market moves, etc.), that the fee consists of two terms, fee = fee_dynamic + fee_penalty? And that the latter is the exact fee/kB needed to offset the penalty incurred by miners?
    – rsi33
    Sep 27, 2019 at 14:45
  • "fee consists of two terms, fee = fee_dynamic + fee_penalty?" <- Not really. There is a fee a spender has to pay on their tx, which forms part of the total reward paid to the miner. The penalty fee is what is deducted from the total miner reward. The miner reward is the sum of tx fees + coinbase reward - penalty fee, for the block mined.
    – jtgrassie
    Sep 27, 2019 at 15:39
  • That makes sense. But, in the case of a high traffic period, a user with a high priority transaction would have to pay a much higher fee multiple in order to incentivize miners to include it, no? And they would calculate the required figure using the penalty formula. (Or do all those transactions basically get canned until traffic goes back down?)
    – rsi33
    Sep 27, 2019 at 16:14
  • A tx that doesn't pay enough fees will likely not be mined until such a time there are few txs pending in the tx pool. txs get dropped from the tx pool after 3 days.
    – jtgrassie
    Oct 1, 2019 at 15:38

Your Answer

By clicking “Post Your Answer”, you agree to our terms of service and acknowledge you have read our privacy policy.

Not the answer you're looking for? Browse other questions tagged or ask your own question.