1. 程式人生 > 實用技巧 >波場共識機制 DPoS

波場共識機制 DPoS

概況

區塊鏈是一個分散式的記賬系統,在一個區塊鏈系統中可以有成千上萬的節點,他們各自獨立儲存一份相同的賬本,而新的交易資料想要被寫入帳本,需要獲得這些節點的認可。在不可信的分散式環境中實現這一目標是一個很複雜的系統工程。區塊鏈系統正常執行,即區塊鏈中各節點總能儲存同一份賬本,前提是系統中絕大部分的節點是誠實可靠的。為了保證誠實可靠的節點能夠共同監督交易資料寫入賬本,每個區塊鏈系統都需要構建自己的共識,共識就相當於區塊鏈的憲法。共識保證了即便是在不可信的分散式環境下,只要絕大多數節點遵守共識的規定,就一定能獲得確定可信結果。因此共識的意義在於,區塊鏈中的誠信節點可以最終達成賬本的一致只要他們嚴格遵守這份共識。

共識有多種型別,目前使用最多的是POW、POS、DPOS,當然不同的區塊鏈系統中都會有一些特有的具體實現上的不同。本文主要介紹波場的共識就是基於DPOS的,同時向大家說明一下DPOS中的基本元件和機制。

記賬流程

區塊鏈系統的記賬人,他們收集區塊鏈網路中新產生的交易,並對這些交易的合法性進行驗證,然後把這些交易打包在一個區塊中,作為新的一頁賬記錄在賬本上,然後將賬頁在整個區塊鏈網路中進行廣播,其他的節點收到新的賬頁,也會驗證賬頁中交易資料的合法性,並新增到自己的賬本中。記賬人一直重複這個過程,這樣只要區塊鏈系統中新的交易資料都會記錄在賬本里面

DPOS概述

共識的作用是在區塊鏈系統中選出記賬人,記賬人驗證交易資料並進行記賬,進而向區塊鏈網路中的其他節點廣播新的賬目,並獲得其他節點對於新賬目的認可。DPOS作為共識的一類特定實現是這樣的:

DPOS共識在區塊鏈系統中根據節點獲取選票的多少確定出部分節點作為記賬。首先區塊鏈系統開始啟動執行的時候,會發行一定數量的通證,然後將通證分給區塊鏈系統中的節點,節點可以憑藉一部分通證申請成為這個區塊鏈系統記賬人的候選人,區塊鏈系統中任何持有通證的節點都可以為這些候選人進行投票,每經過一段時間t會統計所有候選人獲得的選票數量,選票數量排在前面的N個節點會成為下一段時間t內的記賬人,再經過t的時間,又會重新統計一遍新的記賬人,以此類推迴圈往復。

定義

波場

指波場的區塊鏈網路。本文不區分波場、波場區塊鏈、波場區塊鏈系統等概念。

波場幣

指由波場區塊鏈系統發行並在系統中流轉的權益通證,代號是TRX。

記賬候選人

指波場中有成為記賬人資格的節點。

記賬人

指波場中獲得記賬資格的節點,通常DPOS共識中將記賬人稱為witness,波場也將記賬人稱為super node(簡稱SR),波場設定記賬人的數量是27個。下文不區分記賬人、witness、supernode、SR等概念。

記賬

指驗證交易並將交易記錄成賬目的過程,由於波場中的賬目是用區塊承載的,因此記賬的過程也被稱為生產區塊,下文不區分記賬和生產區塊。

記賬順序

即出塊順序。按照27個記賬人得票多少的降序作為記賬順序。

區塊時間

波場中設定一個區塊時間是3秒鐘,即每3秒會生產出一個區塊。

槽位

每一個區塊生產出來可以放到一個槽位,被稱為slot,每當一個區塊生產出來就會佔用一個槽位。例如,1分鐘有20個slot,當1個區塊時間內有1個區塊生產出來,對應的slot會被填滿,如果沒有區塊被生產出來,那麼對應的slot就是空的,下個區塊生產出來的時候會填充到新的對應的slot中。

出塊輪

波場設定每6個小時作為一個出塊輪,稱為一個Epoch。每個出塊輪最後的2個出塊時間是一個維護期。每個出塊輪的維護期決定下一個出塊輪的出塊順序。

維護期

波場設定是2個區塊時間,即6秒鐘。這段時間用於統計候選人得票數。因為24個小時有4個出塊輪,自然就有4個維護期,維護期中不進行區塊生產,主要用來確定下個出塊輪的出塊順序。

選舉機制

選票

波場中設定擁有一個TRX就可以擁有一張選票的權利。

投票過程

波場中設定對候選人的投票過程是一筆特殊型別的交易,節點可以通過生成一筆投票交易對候選人進行投票。

統計票

每個維護期內,統計一次候選人的票數,將獲得票數最多的27個候選人作為下一個出塊週期的記賬人。

產塊機制

在一個出塊輪中,27個記賬人按照記賬順序依次生產區塊。每個記賬人只能在輪到自己產塊時進行區塊生產,記賬人將多筆驗證合法的交易資料打包到每個區塊之中,同時每個區塊都會將上個區塊的雜湊值(hash)作為本區塊的父雜湊值(parentHash)填入區塊中,同時用自己的私鑰對本區塊的資料進行簽名,將簽名結果(witness_signature)也填入區塊中,同時被填入區塊的還有記賬人的地址,區塊高度,區塊生成的時刻等資料。
通過每個區塊儲存了上個區塊hash值的方式,從而在邏輯上將區塊相互關聯了起來,最後組成了一條鏈的結構

理想情況下,採用DPOS共識的區塊鏈系統的記賬過程就是按照事先計算好的記賬順序,由witness輪流依序產塊,但實際情況下,區塊鏈網路是一個分散式的、不可信的複雜系統,體現在
1)由於網路鏈路環境不佳導致witness生產的區塊並不會在有效時間內被其他的witness收到;
2)並不能保證某個witness執行始終正常;
3)某些witness惡意生產分叉的區塊企圖將鏈分叉。


前文已經提到區塊鏈系統正常執行的基礎是系統中絕大部分的節點是誠實可靠的,再進一步探討這個問題,區塊鏈系統安全的首要保證的是賬本的安全,賬本既不能被惡意寫入不合法的資料,賬本在各個節點上儲存的副本也應該是一致的。如果從DPOS共識的角度上來看,記賬過程是由witness完成,因此波場的安全取決於大部分witness的可靠性,波場設定了不可逆轉區塊,也稱為固化塊。同時為了抵抗少部分記賬節點的惡意行為,波場採用基於最長鏈的原則確認為主鏈

固化塊原則

剛生產出來的區塊處於未確認狀態,只有被27個Witness中70%以上(即27 * 70% = 18, 向下取整)的witness"認可"的區塊才被認為是不可逆區塊,一般稱為固化塊,此時固化塊中包含的交易已經被整個區塊鏈網路確認。此處對未確認狀態區塊"認可"的方式是Witness在其之後生產後繼區塊,如圖d中Witness C生產的第103塊,Witness E在第103塊的基礎上生產了104‘,Witness G、A、B分別生產的第105‘、106’、107‘實質上也是103塊的後繼區塊,故也是對C生產的第103塊的認可。可知,當高度為121的區塊被生產出來的時候,第103塊就成為固化塊,因為此時103區塊已經有了18個後繼區塊,此處需要強調的一點是:生產這18個區塊的Witness互不相同,並且和生產第103個區塊的Witness也不同

最長鏈原則

當區塊鏈產生分叉之後,誠實的witness總是選擇在當前最長的那個分叉鏈上繼續生產區塊

激勵模型

為了保證區塊鏈系統安全高效地執行,波場設定激勵模型用於鼓勵更多的節點加入到波場網路中,從而擴大網路規模,對於記賬人當他們完成出塊任務,給予相應的TRX獎勵。波場設定witness每生產一個被固化的區塊,就會獲得32個TRX的獎勵;對於所有記賬人(包括記賬候選人)的得票在前127名的,每個Epoch的維護期會依據得票率的多少分配固定的獎勵.

超級代表

TRON網路中有27個出塊者,即超級代表。
任何賬戶都可以申請成為超級代表候選人。每個賬戶都可以投票給超級代表候選人,獲取投票數最高的27個候選人就是超級代表,第28~127名為超級合夥人。超級代表會有出塊和打包交易的義務,同時也會獲得相應的投票和出塊獎勵,並且有權力參與波場網路動態引數提議的投票。100名超級合夥人可以獲得投票獎勵。

超級代表和激勵機制

選舉超級代表

使用者需要獲得投票權來給超級代表投票,即TRON Power(TP)。TP的數量取決於選民的凍結資產(TRX),1 TP = 凍結1TRX。
在釋放(解凍)之後,會失去對應的TP,同時正在進行的和對於未來的投票都將失效。
TRON網路只記錄最近一次的投票,之前的投票會被覆蓋。
投票統計每6小時統計一次,超級代表和超級合夥人也就每6個小時變更一次。票數排名前27位為超級代表,排名28-127為超級合夥人,排名128以後為超級代表候選人。
根據TRON網路的規則,申請成為超級代表需要燃燒9999個TRX,以此來預防惡意的行為。

獎勵

超級代表獎勵: 波場網路每3秒生成一個區塊,每個塊將16個TRX授予出塊的超級代表。
投票獎勵:波場網路每生成一個區塊, 127名超級代表和合夥人將按照獲得的投票比例瓜分160TRX,每6小時共產生獎勵1152000TRX。 每年投票的總獎勵額約為 1,681,920,000 TRX。超級代表和合夥人獲得的投票獎勵也會根據佣金比例扣除後按照選民投票比例分配給選民。
在2021年1月1日之前,TRON網路將不會出現通貨膨脹,TRON基金會將在該日期之前提供100%的區塊獎勵和候選人獎勵。
每當超級代表完成出塊時,獎勵將會打到超級賬本中的子賬戶。 超級代表可以檢視,但不能直接使用此資產。 可以每24小時取款,把獎勵從子帳戶轉移到超級代表的帳戶。

獎勵計算
獎勵總額=投票獎勵 x (佣金比例) +出塊獎勵 x (佣金比例)

超級代表佣金
預設比例20%,另外80%分發給選民。超級代表可通過介面修改該數值。

投票獎勵
每個區塊給予160個TRX作為投票獎勵。
投票統計資料每6小時計算一次,超級代表根據投票結果而變化。
對於所有127名超級代表候選人,每日共投票獎勵:
160(TRX /塊)x 7200(塊/選舉)x 4(選舉 /天)= 4608,000(TRX /天)1。
對於每位候選人,每日投票獎勵= 4,608,000 x(SR獲得的投票/全網總票數)x 20%
由於可能的丟塊,Reward 可能會小於理論數.

出塊獎勵
SR逐個出塊,出塊獎勵為每個區塊16個TRX。
對於所有27位超級代表,每日共出塊獎勵:
16(TRX /塊)x 7200(塊/選舉)x 4(選舉 /天)= 460,800(TRX /天)
對於每位超級代表,每日出塊獎勵=460,800 / 27 x 20%= 3413 TRX

選民獎勵
以預設的超級代表或超級合夥人佣金比例計算,80%的獎勵分發給了選民,每個投票對應每6小時的獎勵= 80% x 7200(塊/選舉) x 160 /total votes + 80% x 7200(塊/選舉) x 16 / 27 / sr votes)。total votes為全網總投票數,sr votes為超級代表獲得的投票數。因此每個選民需要知道超級代表佣金率、全網總投票數和sr獲得的投票數就可以計算獎勵,此資料會對所有人開放。

基於提案對引數進行調整

DPOS的一個重要的特性是任何系統引數的調整都可以通過鏈上的提案發起,記賬人通過對提案的投票來決定提案是否生效。這樣的好處是在鏈上新增加一些特性不需要進行硬分叉升級,波場目前能夠支援的系統引數調整有:

#CommandValue
0getMaintenanceTimeInterval
(修改超級代表調整時間間隔)
6 Hours
[3 27, 24 3600] s
1getAccountUpgradeCost
(修改賬戶升級為超級代表的費用)
9999 TRX
[0, 100000000000] TRX
2getCreateAccountFee
(修改建立賬戶費用)
0.1 TRX
[0, 100000000000] TRX
3getTransactionFee
(修改TRX抵扣頻寬的費用)
10 Sun/Byte
[0, 100000000000] TRX
4getAssetIssueFee
(修改資產發行費用)
1024 TRX
[0, 100000000000] TRX
5getWitnessPayPerBlock
(修改超級代表出塊獎勵)
16 TRX
[0, 100000000000] TRX
6getWitnessStandbyAllowance
(修改分給前127名超級代表候選人的獎勵)
115200 TRX
[0, 100000000000] TRX
7getCreateNewAccountFeeInSystemContract
(修改系統建立賬戶的費用)
0 TRX
8getCreateNewAccountBandwidthRate
(提議7、8,組合使用,用於修改建立賬戶時對資源或TRX的消耗)
1 Bandwith/Byte
9getAllowCreationOfContracts
(控制虛擬機器功能的開啟 )
1
{0, 1}
10getRemoveThePowerOfTheGr
(用於清除GR的創世票數)
1
{0, 1}
11getEnergyFee
(修改能量費用)
10 Sun
[0, 100000000000] TRX
12getExchangeCreateFee
(修改建立交易對的費用)
1024 TRX
[0, 100000000000] TRX
13getMaxCpuTimeOfOneTx
(修改交易最長執行時間)
50 ms
[0, 1000] ms
14getAllowUpdateAccountName
(允許使用者更改暱稱以及暱稱同名)
0
{0, 1}
15getAllowSameTokenName
(允許建立相同名稱的token)
1
{0, 1}
16getAllowDelegateResource
(控制資源代理功能的開啟)
1
{0, 1}
18getAllowTvmTransferTrc10
(允許智慧合約呼叫TRC10 token的介面)
1
{0, 1}
19getTotalEnergyCurrentLimit
(修改ENERGY總量)
50000000000
20getAllowMultiSign
(允許開啟多重簽名)
1
{0, 1}
21getAllowAdaptiveEnergy
(允許ENERGY總量自適應調整)
0
{0, 1}
22getUpdateAccountPermissionFee
(修改賬戶許可權費用)
100 TRX
23getMultiSignFee
(修改賬戶許可權費用)
1 TRX
24getAllowProtoFilterNum
(允許更新protobuf的數字)
0
{0, 1}
26getAllowTvmConstantinople
(允許TVM支援君士坦丁堡更新)
1
{0, 1}
27getAllowShieldedTransaction
(允許匿名交易開啟)
0
{0, 1}
28getShieldedTransactionFee
(修改匿名交易手續費)
10 TRX
[0, 10000] TRX
29getAdaptiveResourceLimitMultiplier
(用於修改動態能量最大值)
1000
[1, 10000]
30getChangeDelegation
(修改更換委託機制)
1
{0, 1}
31getWitness127PayPerBlock
(修改票數排名獎勵)
160TRX
[0, 100000000000] TRX
32getAllowTvmSolidity059
(允許虛擬機器支援0.5.9版本的Solidity編譯器)
0
{0, 1}
33getAdaptiveResourceLimitTargetRatio
(修改能量目標值)
10
[1, 1000]

頻寬和能量機制

資源模型

TRON網路中的資源有4種:頻寬,CPU,儲存和記憶體。得益於波場獨有的記憶體模型,TRON網路中的記憶體資源幾乎是無限的。
TRON網路引入了Bandwidth Point 和 Energy 兩種資源概念。其中Bandwidth Point表示頻寬資源,Energy表示CPU和儲存資源。
注意:
系統交易僅消耗Bandwidth Point
智慧合約的操作不僅要消耗Bandwidth Point,還會消耗Energy

頻寬

交易以位元組陣列的形式在網路中傳輸及儲存,一條交易消耗的Bandwidth Points = 交易位元組數 * Bandwidth Point費率。當前Bandwidth Point費率 = 1。
如一條交易的位元組陣列長度為200,那麼該交易需要消耗200 Bandwidth Points。
注意: 由於網路中總凍結資金以及賬戶的凍結資金隨時可能發生變化,因此賬戶擁有的Bandwidth Points不是固定值。

Bandwidth Points的來源

Bandwidth Points的獲取分兩種:

  1. 通過凍結TRX獲取的Bandwidth Point, 額度 = 為獲取Bandwidth Point凍結的TRX / 整個網路為獲取Bandwidth Points凍結的TRX 總額 * 43_200_000_000。 也就是所有使用者按凍結TRX平分固定額度的Bandwidth Points。
  2. 每個賬號每天有固定免費額度的頻寬,為5000。

Bandwidth Points的消耗

除了查詢操作,任何交易都需要消耗bandwidth points。
還有一種情況,如果是轉賬,包括普通轉賬或發行Token轉賬,如果目標賬戶不存在,轉賬操作則會建立賬戶並轉賬,只會扣除建立賬戶消耗的Bandwidth Points,轉賬不會再消耗額外的Bandwidth Points。

Bandwidth Points的計算規則

Bandwidth Points是一個賬戶1天內能夠使用的總位元組數。一定時間內,整個網路能夠處理的Bandwidth為確定值。
如果交易需要建立新賬戶,Bandwidth Points消耗如下:

  1. 嘗試消耗交易發起者凍結獲取的Bandwidth Points。如果交易發起者Bandwidth Points不足,則進入下一步
  2. 嘗試消耗交易發起者的TRX,這部分燒掉0.1TRX

如果交易是Token轉賬,Bandwidth Points消耗如下:

  1. 依次驗證 發行Token資產總的免費Bandwidth Points是否足夠消耗,轉賬發起者的Token剩餘免費Bandwidth Points是否足夠消耗,Token發行者凍結TRX獲取Bandwidth Points剩餘量是否足夠消耗。如果滿足則扣除Token發行者的Bandwidth Points,任意一個不滿足則進入下一步
  2. 嘗試消耗交易發起者凍結獲取的Bandwidth Points。如果交易發起者Bandwidth Points不足,則進入下一步
  3. 嘗試消耗交易發起者的免費Bandwidth Points。如果免費Bandwidth Points也不足,則進入下一步
  4. 嘗試消耗交易發起者的TRX,交易的位元組數 * 10 sun

如果交易普通交易,Bandwidth Points消耗如下:

  1. 嘗試消耗交易發起者凍結獲取的Bandwidth Points。如果交易發起者Bandwidth Points不足,則進入下一步
  2. 嘗試消耗交易發起者的免費Bandwidth Points。如果免費Bandwidth Points也不足,則進入下一步
  3. 嘗試消耗交易發起者的TRX,交易的位元組數 * 10 sun

頻寬的自動恢復

在網路總鎖定資金以及賬戶鎖定資金不變的情況下,賬戶的頻寬的已使用量隨著時間增加而按比例衰減,24h衰減到0。如時間T1時刻,賬戶頻寬已使用量為U,到T1+12h,賬戶再次使用頻寬u,此時賬戶已使用頻寬為 U/2 + u。具體公式如下:

即可以理解為每24h,使用者已使用的頻寬值重置為0

能量

智慧合約執行時執行每一條指令都需要消耗一定的系統資源,資源的多少用Energy的值來衡量。

Energy的獲取

凍結獲取Energy,即將持有的trx鎖定,無法進行交易,作為抵押,並以此獲得免費使用Energy的權利。具體計算與全網所有賬戶凍結有關,可參考相關部分計算。

FreezeBalance 凍結獲得能量
通過凍結TRX獲取的Energy, 額度 = 為獲取Energy凍結的TRX / 整個網路為獲取Energy凍結的TRX 總額 * 50_000_000_000。
也就是所有使用者按凍結TRX平分固定額度的Energy

FreezeBalance 恢復能量
所消耗的能量會在24小時內平滑減少至0。
示例:
在某一時刻A的Energy已使用量為72_000_000 Energy,在沒有其他消耗或凍結的操作下:
一小時後A的Energy已使用量為 72_000_000 - (72_000_000 (6060/606024)) Energy = 69_000_000 Energy
24小時後A的Energy已使用量為 0 Energy。

如何填寫feeLimit

在本節範圍內,將合約的開發部署人員,簡稱為“開發者”;將呼叫合約的使用者或者其他合約,簡稱為“呼叫者”。
呼叫合約消耗的Energy能以一定比例摺合成trx(或者sun),所以在本節範圍內,指代合約消耗的資源時,並不嚴格區分Energy和 trx;僅在作為 數值的單位時,才區分Energy、trx和sun。
合理設定feeLimit,一方面能儘量保證正常執行;另外一方面,如果合約所需Energy過大,又不會過多消耗呼叫者的trx。在設定feeLimit之前,需要了解幾個概念:

  1. 合法的feeLimit為0 - 10^9 之間的整數值,單位是sun,摺合0 - 1000 trx;
  2. 不同複雜度的合約,每次正常執行消耗不同的Energy;相同合約每次消耗的Energy基本相同;執行合約時,逐條指令計算並扣除Energy,如果超過feeLimit的限制,則合約執行失敗,已扣除的Energy不退還;
  3. 目前feeLimit僅指呼叫者願意承擔的Energy摺合的trx;執行合約允許的最大Energy還包括開發者承擔的部分;
  4. 一個惡意合約,如果最終執行超時,或者因bug合約崩潰,則會扣除該合約允許的所有energy;
  5. 開發者可能會承擔一定比例的Energy消耗(比如承擔90%)。但是,當開發者賬戶的Energy不足以支付時,剩餘部分完全由呼叫者承擔。在feeLimit限制範圍內,如呼叫者的Energy不足,則會燃燒等價值的trx。
    開發者通常會有充足的Energy,以鼓勵低成本呼叫;呼叫者在估算feeLimit時,可以假設開發者能夠承擔其承諾比例的Energy,如果一次呼叫因為feeLimit不足而失敗,可以再適當擴大。

Energy的計算

  1. tron為了懲罰惡意開發者,對於異常合約,如果執行超時(超過50ms),或因bug異常退出(不包含revert),會扣除本次的最大可用Energy。若合約正常執行,或revert,則僅扣除執行相關指令所需的Energy;
  2. 開發者可以設定執行合約時,消耗Energy中自己承擔的比例,該比例後續可修改。一次合約呼叫消耗的Energy,若開發者的Energy不足以支付其承擔的部分,剩餘部分全由呼叫者支付;
  3. 目前執行一個合約,可用的Energy總數由 呼叫者呼叫時設定的feeLimit 和 開發者承擔部分共同決定

注意:

  1. 若開發者不確定合約是否正常,請勿將使用者承擔比例設定為0%,否則在被判為惡意執行時,會扣除開發者的所有Energy。
  2. 因此建議開發者設定的使用者承擔的比例為10%~100%。

如果合約執行成功,沒有發生任何異常,則會扣除合約執行實際消耗的Energy,一般都遠遠小於此次呼叫能夠使用的Energy。如果發生了Assert-style異常,則會消耗feeLimit對應的所有的Energy。

注意:
開發者建立合約的時候,consume_user_resource_percent不要設定成0,也就是開發者自己承擔所有資源消耗。
開發者自己承擔所有資源消耗,意味著當發生了Assert-style異常時,會消耗開發者凍結的所有Energy。

資源委託

在TRON中,一個賬戶可以通過凍結TRX來獲取頻寬和能量。同時,也可以把凍結TRX獲取的頻寬或者能量委託(delegate)給其他地址。
此時,主賬號擁有凍結的TRX以及相應的投票權,受委託賬戶擁有凍結獲取的資源(頻寬或者能量)。
和普通凍結一樣,委託資源也至少凍結3天。

參考文件
https://tronprotocol.github.io/documentation-zh/introduction/dpos/
https://cn.developers.tron.network/docs/%E8%B5%84%E6%BA%90%E6%A8%A1%E5%9E%8B