關於Monero手續費的一份筆記

近期社群中不斷有抱怨認為Monero交易的手續費過於昂貴。雖然我們並不同意其中的一些意見,但我們還是必須先徹底地分析一下這個情況。在那之前我們必須回應一點,有些抱怨認為開發者理當要將手續費直接修改降低後釋出新版本,但這樣的作法是因小失大的,因為 1. 這個方法只是把問題向後拖延;2. 改變參數與公式需要進行硬分叉,而這需要全面的共識;3. 每當價格變化後就得介入調整手續費的作法與去中心化的生態是矛盾的。 這就讓我們拿幾個同是使用工作證明(POW)的區塊鏈貨幣來做個每單位容量(kB)手續費比較:

  • 比特幣 Bitcoin: ~$26.90
  • 乙太幣 Ethereum: ~$2.91
  • 萊特幣 Litecoin: ~$0.10
  • 達世幣 Dash: ~$0.07
  • 門羅幣 Monero: ~$0.24

比較起來,Monero的每單位容量手續費其實並不算高。但是由於每筆交易所需的容量較大,實質的費用就因此變得相當高。但必須注意的是,Monero較大的交易容量是來自於預設的隱私保護功能。例如隱藏交易金額功能RingCT中的Range proofs可以佔到12kB的容量;但RingCT在強化交易隱私上是絕對必要的,當這功能還沒有啟用時,讓許多交易洩漏了隱私。 不過有個好消息是,未來Bulletproofs協定的啟用將會降低Monero至少80%的交易容量。 為了完整分析整個問題,讓我們來看看程式碼裡的參數,就從打包區塊(挖礦)的動態區塊演算法與獎勵懲罰公式開始吧,這部分的公式如下: 懲罰 = 基礎獎勵 * ((區塊容量 /  M*N) - 1)² 所以實際的獎勵為: 新獎勵 = 基礎獎勵 - 懲罰
其中:

  • MN是過去最新的N個區塊的容量中位數,N在Monero中被設定為100
  • 區塊容量是指目前正在打包的區塊容量
  • 基礎獎勵是根據當下的發行曲線的位置或是尾段發行量(tail emission)而決定
  • 新獎勵是礦工實際獲得的獎勵
  • 區塊容量的上限為2MN

而在公式中基礎獎勵被定義如下: 基礎獎勵 = 2 * ((S - A) * 2-20 * 10-12)
其中:

  • 2是調整區塊間隔時間為兩分鐘的因子
  • S是原子單位(atomic units)的初始值 = 264 - 1

A是目前的貨幣發行總量,可以在這裡查到,此外,目前顯示在區塊鏈瀏覽器上的發行總量數字必須乘上1012 (Monero有小數後12位)以轉換為原子單位。 最小的區塊容量限制為300kB,因此礦工得以最多將區塊使用至300kB而不會受到獎勵懲罰,也就是說,上述提到的懲罰公式僅在區塊容量超過300kB之後才會開始發揮作用。 舉個例子,現在有一個標準的Monero交易(兩個輸入兩個輸出約需13.2kB的容量)來了,讓我們來放入公式看看: 假設目前的區塊基礎獎勵是5.7 XMR: 懲罰 = (5.7 * ((313.2/300)-1)² ,約為0.011 XMR。另外可以注意的是與半年多前相比,目前基礎獎勵明顯低很多,也因此目前懲罰隨之降低。 而礦工不會無故擴張區塊容量。因此在容量超過300 kB之後,每多添加一筆交易時的手續費必須比這些懲罰來得多,否則礦工將會只在打包至300 kB的容量後就不願意處理其他的交易,這樣會導致交易網路的堵塞。以結論來說,目前的預設手續費(約0.013)就是為了讓礦工在多處理額外的交易而不會損失挖礦獎勵的收益。 從上述的懲罰公式可以發現,懲罰會隨著基礎獎勵的下降而減少,另外,將公式製圖後可以發現懲罰在一開始是比較緩和的,這代表著減少些許交易容量就可以降低相對更多的手續費,譬如,80%的交易容量降低可以減少90%的手續費。讓我們來用公式算個更精確的例子,假設使用單輸出的防彈協定(bulletproofs),交易的容量將會降至2.5 kB左右;另也假設我們希望礦工會願意擴張區塊容量來處理額外的兩筆交易而不會損失收益,也就是說在超過最小區塊限制後,礦工可以多處理兩筆交易而不會讓懲罰超過獎勵。將數字帶入後我們就得到: 懲罰 =  (5.7 * ((305/300)-1)²,約等於0.0016XMR,或0.0008XMR的單筆懲罰 當降低80%交易容量時卻保持著最小區塊容量限制似乎不太對,因此最小區塊容量限制可以被降低至100、150、200或250 kB,
讓我們再次把數字套入看看:

懲罰 = (5.7 * ((255/250)-1)²,約等於0.0023 XMR,或0.00115 XMR的單筆懲罰
懲罰 = (5.7 * ((205/200)-1)²,約等於0.0036 XMR,或0.0018 XMR的單筆懲罰
懲罰 = (5.7 * ((155/150)-1)²,約等於0.0063 XMR,或0.00315 XMR的單筆懲罰
懲罰 = (5.7 * ((105/100)-1)²,約等於0.014 XMR,或0.007 XMR的單筆懲罰

你可以依此公式(MN 對 x 與 區塊容量對 x+5)畫出一張圖觀察變化的結果。
大家也許會很好奇,那動態手續費演算法在這其中到底是扮演著什麼角色?首先必須澄清一下,預設的手續費僅僅只能應付最低限度的懲罰,也就是說,礦工只會在最小區塊容量之外多處理一筆交易。更精確的說,以目前的狀況就是製造出一個313kB的區塊(提醒一下,最小區塊容量限制是300kB)。當(最後一百個區塊的)中位數區塊容量開始成長時,動態手續費演算法才會開始發揮作用。 來看看動態手續費演算法的運作: 手續費 = (R/R0) * (M0/M) * F0 * (60/300) * 4 其中:

  • R 是基礎獎勵
  • R0 是基礎獎勵的初始參照值(10 XMR)
  • M 是區塊容量上限
  • M0 是最小區塊容量上限 (300 kB)
  • F0 是 0.002 XMR

舉個實際的例子,數月前區塊容量的中位數一度增加到了400 kB左右,當時標準手續費降低到了約0.0095xmr。我們可以在公式中看到,這是概略與理論值符合的。也就是: 手續費 = (6.5/10) * (300/400) * 0.002 = 0.00975 基本上中位區塊容量(其在公式中扮演的角色與最小區塊大小的基數相反)百分比倒數的增加即可視為手續費減少的百分比。舉個實際例子來說,若區塊容量的中位數增長到了600kB,就等於是擴容為兩倍(200%)的區塊,此時將可減免一半(1/200%)的單筆手續費。這個設計使得交易手續費會因交易的數量增加而下降。用意在於當Monero日益熱門時,增加的交易量將會降低每單位容量手續費。 那麼,為什麼近期價格的飆升並未造成每單位容量手續費的驟降呢?  這是因為近期價格上漲的效應比交易使用量這個影響因子大多了。而且區塊容量的中位數需要維持在比300kB大才能夠讓動態手續費演算法順利的運作,但目前Monero交易使用量並未維持在其之上。手續費演算法當初是被設計成要與價格連動的,但是我們可以發現Monero價格並未完美的與Monero的交易使用量連動。綜合以上,雖然Monero使用量成長了非常多,但還尚未超過300kB的動態門檻,且與價格的成長相比卻是小巫見大巫,因此最後造成每單位容量手續費尚未開始如預期的下降。 另從結合懲罰公式以及動態區塊大小公式與動態手續費公式看來,我們可以得知較高的最小區塊容量限制(比如300kB)會有著較低的起始手續費,但手續費的下降效應(因動態手續費演算法)也會較不明顯。反過來說,較低的最小區塊容量限制(比如150kB)會有較高的起始手續費,但手續費的減少就會較為明顯。

結論是,雖然目前手續費太高,但過一陣子之後很可能就不會再有這狀況,因為當使用量增加到一定程度後,動態公式就會開始發揮作用來減免手續費。此外,我們真正需要的是仔細研究最適當的最小區塊容量限制數值(如上段所述),因為我們比較希望能夠找到一個以後都不會再需要人工介入修改的參數。   最後一些尚需補充的要點:

  1. 手續費的_中位數_是從 Bitinfocharts取得的。
  2. 對於手續費懲罰的功能有更深入的探討(ArticMine著)的可以到這裡閱讀。
  3. 手續費懲罰的功能跟原先在 CryptoNote 白皮書上所寫的有某種程度上的差異了, 這裡有更多資訊。
  4. 程式碼的細節和確切植入的動態區塊大小演算法在這裡
  5. 程式碼的細節和確切植入的動態手續費演算法在這裡

  本文翻譯文章來源: https://getmonero.org/2017/12/11/A-note-on-fees.html