<blockquote>
<p>I thought vbytes were equal to weight units divided by 4</p>
</blockquote>
<p>It is [1], but <strong>rounded up to the next integer</strong>, so the implementation in <code>bitcoind</code> is :</p>
<pre><code>int64_t GetVirtualTransactionSize(int64_t nWeight, int64_t nSigOpCost, unsigned int bytes_per_sigop)
{
    return (std::max(nWeight, nSigOpCost * bytes_per_sigop) + WITNESS_SCALE_FACTOR - 1) / WITNESS_SCALE_FACTOR;
}
</code></pre>
<p>(Where <code>WITNESS_SCALE_FACTOR = 4</code>).</p>
<p>In addition, <code>bitcoind</code> not only uses <code>vbyte</code>s for user interface but also for mempool logic and the <code>DEFAULT_MIN_RELAY_TX_FEE</code> constant is set in <code>vbyte</code>s :</p>
<pre><code>static const unsigned int DEFAULT_MIN_RELAY_TX_FEE = 1000;
</code></pre>
<p>In order to check it for standardness <code>bitcoind</code> will compute your transaction size as rounded up (if not a multiple of <code>4</code>), and will record your transaction feerate as rounded <em>down</em>.<br />
It will then compare this to the minimum relay feerate (<code>1000</code>) : a feerate of <code>250</code>sat per KW will pass only if the size of your transaction (in weight units) is a multiple of <code>4</code>.</p>
<p>It might be clearer with code, here is a Python function which illustrates this behaviour :</p>
<pre><code>&gt;&gt;&gt; def bitcoind_fun(tx_weight, feerate_perkw):
...     fees = tx_weight * feerate_perkw // 1000
...     print(&quot;Your transaction will pay {} sats of fees, is {} WU large (a feerate of {}sat/Kw)&quot;.format(fees, tx_weight, feerate_perkw))
...     tx_vbytes_for_bitcoind = (tx_weight + 3) // 4
...     tx_feerate_vbytes_for_bitcoind = fees * 1000 // tx_vbytes_for_bitcoind
...     print(&quot;bitcoind reads your transaction as paying {} sats of fees for a transaction of {} vbytes, so a {}sat/perKvb feerate&quot;.format(fees, tx_vbytes_for_bitcoind, tx_feerate_vbytes_for_bitcoind))
</code></pre>
<p>Which if you run with a <code>tx_weight</code> which is a multiple of <code>4</code> will pass, otherwise it won't :</p>
<pre><code>&gt;&gt;&gt; bitcoind_fun(1600, 250)
Your transaction will pay 400 sats of fees, is 1600 WU large (a feerate of 250sat/Kw)
bitcoind reads your transaction as paying 400 sats of fees for a transaction of 400 vbytes, so a 1000sat/perKvb feerate
&gt;&gt;&gt; bitcoind_fun(1601, 250)
Your transaction will pay 400 sats of fees, is 1601 WU large (a feerate of 250sat/Kw)
bitcoind reads your transaction as paying 400 sats of fees for a transaction of 401 vbytes, so a 997sat/perKvb feerate
&gt;&gt;&gt; bitcoind_fun(1602, 250)
Your transaction will pay 400 sats of fees, is 1602 WU large (a feerate of 250sat/Kw)
bitcoind reads your transaction as paying 400 sats of fees for a transaction of 401 vbytes, so a 997sat/perKvb feerate
</code></pre>
<p>So we use 253 as the feerate floor to always be safe :</p>
<pre><code>&gt;&gt;&gt; bitcoind_fun(1600, 253)
Your transaction will pay 404 sats of fees, is 1600 WU large (a feerate of 253sat/Kw)
bitcoind reads your transaction as paying 404 sats of fees for a transaction of 400 vbytes, so a 1010sat/perKvb feerate
&gt;&gt;&gt; bitcoind_fun(1601, 253)
Your transaction will pay 405 sats of fees, is 1601 WU large (a feerate of 253sat/Kw)
bitcoind reads your transaction as paying 405 sats of fees for a transaction of 401 vbytes, so a 1009sat/perKvb feerate
&gt;&gt;&gt; bitcoind_fun(1602, 253)
Your transaction will pay 405 sats of fees, is 1602 WU large (a feerate of 253sat/Kw)
bitcoind reads your transaction as paying 405 sats of fees for a transaction of 401 vbytes, so a 1009sat/perKvb feerate
</code></pre>
<p>By the way the comment in the code you put is wrong : it's not <code>(3 * weight) / 4 </code> but <code>(3 + weight) / 4</code>.</p>
<hr />
<p>[1] Excluding sig OPs limits that artificially increases the virtual size to further prevent DOS.</p>
<p>PS: In the same vein, see <a href="https://github.com/bitcoin/bitcoin/issues/13283" rel="nofollow noreferrer">https://github.com/bitcoin/bitcoin/issues/13283</a>.</p>

CC BY-SA 4.0
2020-05-14T23:21:15.690Z
I see, so the core issue is rounding *up* when calculating the tx size, and rounding *down* when calculating the fee rate. That is very tricky. Thank you for such a clear explanation!  
Darius
CC BY-SA 4.0
2020-05-15T09:51:10.827Z
The round down is actually a *consequence* of the round up but yes that's the point. You are welcome :)
Antoine Poinsot
CC BY-SA 4.0
2020-05-14T17:15:46.483Z
2021-03-11T09:20:22.517Z
2021-03-11T09:20:22.517Z
Antoine Poinsot
<p>Naively, we would expect a minRelayTxFee of 1000 sat/kb to correspond to 250 sat/kw. However, apparently this is not so according to <a href="https://github.com/ACINQ/eclair/issues/1188" rel="nofollow noreferrer">this issue (ACINQ)</a>, which also references <a href="https://github.com/ElementsProject/lightning/pull/1251" rel="nofollow noreferrer">this issue (c-lightning)</a>. </p>

<blockquote>
<pre><code>  /** 
    * why 253 and not 250 since feerate-per-kw is feerate-per-kb / 250 and the minimum relay fee rate is 1000 satoshi/Kb ? 
    * 
    * because bitcoin core uses neither the actual tx size in bytes or the tx weight to check fees, but a "virtual size" 
    * which is (3 * weight) / 4 ... 
    * so we want : 
    * fee &gt; 1000 * virtual size 
    * feerate-per-kw * weight &gt; 1000 * (3 * weight / 4) 
    * feerate_per-kw &gt; 250 + 3000 / (4 * weight) 
    * with a conservative minimum weight of 400, we get a minimum feerate_per-kw of 253 
    * 
    * see https://github.com/ElementsProject/lightning/pull/1251 
    **/ 
   val MinimumFeeratePerKw = 253
</code></pre>
</blockquote>

<p>I thought vbytes were equal to weight units divided by 4 and rounded up, so I don't understand where <code>(3 * weight) / 4</code> comes from.</p>

CC BY-SA 4.0
2020-05-14T18:41:29.533Z
I think this is a typo. It's `(3 + weight) / 4`, not `(3 * weight) / 4`.
Pieter Wuille
<bitcoin-core><transaction-fees><segregated-witness><non-standard-transaction>
Why is a minRelayTxFee of 1000 sat/kb not equivalent to 250 sat/kw?
Darius
# Why is a minRelayTxFee of 1000 sat/kb not equivalent to 250 sat/kw?

(Asked by: username_0 on 2020-05-14)

Naively, we would expect a minRelayTxFee of 1000 sat/kb to correspond to 250 sat/kw. However, apparently this is not so according to [this issue (ACINQ)](https://github.com/ACINQ/eclair/issues/1188), which also references [this issue (c-lightning)](https://github.com/ElementsProject/lightning/pull/1251).

> ```
>   /** 
>     * why 253 and not 250 since feerate-per-kw is feerate-per-kb / 250 and the minimum relay fee rate is 1000 satoshi/Kb ? 
>     * 
>     * because bitcoin core uses neither the actual tx size in bytes or the tx weight to check fees, but a "virtual size" 
>     * which is (3 * weight) / 4 ... 
>     * so we want : 
>     * fee > 1000 * virtual size 
>     * feerate-per-kw * weight > 1000 * (3 * weight / 4) 
>     * feerate_per-kw > 250 + 3000 / (4 * weight) 
>     * with a conservative minimum weight of 400, we get a minimum feerate_per-kw of 253 
>     * 
>     * see https://github.com/ElementsProject/lightning/pull/1251 
>     **/ 
>    val MinimumFeeratePerKw = 253
>
> ```

I thought vbytes were equal to weight units divided by 4 and rounded up, so I don't understand where `(3 * weight) / 4` comes from.

**Tags:** bitcoin-core, transaction-fees, segregated-witness, non-standard-transaction

> **Comments:**
> **username_1**: I think this is a typo. It's `(3 + weight) / 4`, not `(3 * weight) / 4`.  

---

## 1 answers

### Answer by username_2 on 2020-05-14. Score: 3 | Accepted answer

> I thought vbytes were equal to weight units divided by 4

It is [1], but **rounded up to the next integer**, so the implementation in `bitcoind` is :

```
int64_t GetVirtualTransactionSize(int64_t nWeight, int64_t nSigOpCost, unsigned int bytes_per_sigop)
{
    return (std::max(nWeight, nSigOpCost * bytes_per_sigop) + WITNESS_SCALE_FACTOR - 1) / WITNESS_SCALE_FACTOR;
}

```

(Where `WITNESS_SCALE_FACTOR = 4`).

In addition, `bitcoind` not only uses `vbyte`s for user interface but also for mempool logic and the `DEFAULT_MIN_RELAY_TX_FEE` constant is set in `vbyte`s :

```
static const unsigned int DEFAULT_MIN_RELAY_TX_FEE = 1000;

```

In order to check it for standardness `bitcoind` will compute your transaction size as rounded up (if not a multiple of `4`), and will record your transaction feerate as rounded *down*.  
It will then compare this to the minimum relay feerate (`1000`) : a feerate of `250`sat per KW will pass only if the size of your transaction (in weight units) is a multiple of `4`.

It might be clearer with code, here is a Python function which illustrates this behaviour :

```
>>> def bitcoind_fun(tx_weight, feerate_perkw):
...     fees = tx_weight * feerate_perkw // 1000
...     print("Your transaction will pay {} sats of fees, is {} WU large (a feerate of {}sat/Kw)".format(fees, tx_weight, feerate_perkw))
...     tx_vbytes_for_bitcoind = (tx_weight + 3) // 4
...     tx_feerate_vbytes_for_bitcoind = fees * 1000 // tx_vbytes_for_bitcoind
...     print("bitcoind reads your transaction as paying {} sats of fees for a transaction of {} vbytes, so a {}sat/perKvb feerate".format(fees, tx_vbytes_for_bitcoind, tx_feerate_vbytes_for_bitcoind))

```

Which if you run with a `tx_weight` which is a multiple of `4` will pass, otherwise it won't :

```
>>> bitcoind_fun(1600, 250)
Your transaction will pay 400 sats of fees, is 1600 WU large (a feerate of 250sat/Kw)
bitcoind reads your transaction as paying 400 sats of fees for a transaction of 400 vbytes, so a 1000sat/perKvb feerate
>>> bitcoind_fun(1601, 250)
Your transaction will pay 400 sats of fees, is 1601 WU large (a feerate of 250sat/Kw)
bitcoind reads your transaction as paying 400 sats of fees for a transaction of 401 vbytes, so a 997sat/perKvb feerate
>>> bitcoind_fun(1602, 250)
Your transaction will pay 400 sats of fees, is 1602 WU large (a feerate of 250sat/Kw)
bitcoind reads your transaction as paying 400 sats of fees for a transaction of 401 vbytes, so a 997sat/perKvb feerate

```

So we use 253 as the feerate floor to always be safe :

```
>>> bitcoind_fun(1600, 253)
Your transaction will pay 404 sats of fees, is 1600 WU large (a feerate of 253sat/Kw)
bitcoind reads your transaction as paying 404 sats of fees for a transaction of 400 vbytes, so a 1010sat/perKvb feerate
>>> bitcoind_fun(1601, 253)
Your transaction will pay 405 sats of fees, is 1601 WU large (a feerate of 253sat/Kw)
bitcoind reads your transaction as paying 405 sats of fees for a transaction of 401 vbytes, so a 1009sat/perKvb feerate
>>> bitcoind_fun(1602, 253)
Your transaction will pay 405 sats of fees, is 1602 WU large (a feerate of 253sat/Kw)
bitcoind reads your transaction as paying 405 sats of fees for a transaction of 401 vbytes, so a 1009sat/perKvb feerate

```

By the way the comment in the code you put is wrong : it's not `(3 * weight) / 4`  but `(3 + weight) / 4`.

---

[1] Excluding sig OPs limits that artificially increases the virtual size to further prevent DOS.

PS: In the same vein, see <https://github.com/bitcoin/bitcoin/issues/13283>.

> **Comments:**
> **username_0**: I see, so the core issue is rounding *up* when calculating the tx size, and rounding *down* when calculating the fee rate. That is very tricky. Thank you for such a clear explanation!    
> **username_2**: The round down is actually a *consequence* of the round up but yes that's the point. You are welcome :)  

---

