一,生產者註冊
EOS可以執行system合約的regproducer或者unregprod動作,實現生產者註冊或者取消生產者註冊。
1,合約中生產者註冊表定義
其中:
owner :生產者賬號名稱。
total_votes :獲得的投票總數量。
producer_key :生產者公私鑰。
is_active :是否是激活狀態。
url :生產者的url地址。
unpaid_blocks :該生產者未獲取生產者獎勵的生產的區塊數量。
last_claim_time :上次獲得生產者獎勵的時間。
location :最近鄰調度的相對位置。(未使用)
2,設置節點生產者賬戶
3,生產者註冊
註冊生產者:
如果該生產者已存在於生產者註冊表,則修改生產者的公鑰、URL地址,獲得投票置0、激活該生產者。
如果不存在於生產者註冊表,則添加該生產者記錄,激活該生產者。
4,取消生產者註冊
取消註冊生產者:
將該生產者對應生產者註冊表的記錄修改,生產者的公鑰置空、激活狀態爲false。
該生產者記錄並不刪除。
rmvproducer同樣可以取消生產者註冊,需要系統管理員權限。
二,生產者選舉投票
所有賬戶可以對已經註冊的生產者進行選舉投票,選舉出可以生產區塊的生產者列表。
1,合約中賬戶投票表定義
其中:
owner :投票者賬戶名稱。
proxy :代理賬戶名稱。
producers :投票者投票的生產者列表,一個投票者可以同時對最多30個生產者進行投票。
staked :投票者質押資源(NET&CPU)的貨幣總額。
last_vote_weight:該投票者上次的投票的權重。
proxied_vote_weight:該賬戶如果是投票代理賬戶,該值爲代理的投票權重。
is_proxy :該賬戶是否是投票代理賬戶。
- 一個賬戶只能擁有一個投票代理人。
- 投票代理人可爲多個賬戶代理投票。
- 代理人不允許再被代理。
- 賬戶一旦指定代理就不能直接投票生產者。(proxy 或者producers必須有一個爲空)
- 該表中對應賬號的記錄僅在相關賬號質押資源或者註冊代理人時被添加。
2,資源質押投票者權重累計
投票者擁有的投票權重來自於投票者帳戶對資源質押的貨幣總額的計算。
在質押資源動作完成時,根據質押人賬戶質押資源(NET&CPU)的總金額,修改賬戶投票表。
- 資源質押的金額隻影響質押人投票權重,與受益人無關。
- 質押人賬戶如存在於賬戶投票表中,則累計該表中該賬號下的資源質押總金額。
- 質押人賬戶如不存在,則在該表中創建該賬號的記錄,對其質押總金額賦值。
- N(b1)預留開發者投票賬戶。(未使用)
- 如果該賬戶已經投過票或者設置過代理,重新計算資源質押對應的投票權重。
3,投票權重的計算
- 投標權重係數 = (2的(當前時間距離2000年的年數)次方)。
- 投票權重 = 質押金額*投標權重係數;
- 即投票時間或者指定代理人時間越新投票權重係數越大。(鼓勵用戶不斷投票)
4,投票代理人註冊
一個賬戶需要被註冊爲投票代理人後才能具備代理其他賬戶進行選舉投票的能力。
regproxy註冊代理人動作:
如註冊的代理人存在於賬戶投票表中,將註冊的代理人在對應賬戶投票表的記錄的is_proxy置爲true或者false;對其質押資源可產生的投票權重進行投票。
如註冊的代理人不存在於賬戶投票表中,添加該賬戶記錄is_proxy置爲true或者false。
5,投票
投票人通過voteproducer的動作,可以執行生產者選舉投票或者指定投票代理人投票的操作,但2個操作不能同時執行。即執行該函數的參數proxy或者producers必須有一個爲空。
proxy不爲空,表示執行指定代理人操作,根據投票人資源質押金額計算出的投票權重會累積到代理人的proxied_vote_weight的代理權重中;並將代理人的代理權重增量累積到選舉的生產者列表對應生產者的生產者註冊表的記錄total_votes生產者投票累計權重中。
producers不爲空,表示執行投票操作,根據投票人資源質押金額計算出的投票權重增量累積到選舉的生產者列表對應生產者的生產者註冊表的記錄total_votes生產者投票累計權重中;如果投票者是代理人,則增量需要計算proxied_vote_weight代理的投票權重。
propagate_weight_change函數完成對選舉生產者的投票權重累計,即p.total_votes += delta;並累計所有投票的權重,_gstate.total_producer_vote_weight += delta。
三,生產者列表狀態
EOS系統中的生產者列表有3個狀態,選舉產生的新的生產者列表依次過渡,最終成爲可輪替生產區塊的生產者序列。
active schedule : 當前生產者列表,存放在當前生產區塊的block_header_state記錄中。
pending schedule : 待定生產者列表,存放在當前生產區塊的block_header_state記錄中。
proposed schedule: 提議生產者列表,存放在chainbase的global_property_object表中:
proposed_schedule_block_num:提議的生產者列表產生對應區塊的塊號。
1,proposed schedule生產者列表的產生
對生產者的選舉投票不是直接產生結果,需要在區塊生產者獎勵計數函數onblock中,判斷選舉是否有效。
選舉有效的條件 :
- total_activated_stake系統激活的債卷(參與投票的對應資源質押的貨幣總金額)總量超過或等於min_activated_stake(150'000'000'0000)。
- 距離上次生產者選舉投票結果變化超過120個區塊的生產週期(1分鐘)。
更新生產者選舉結果 :
- 從選舉的生產者中選出前最多21個,生產者爲激活狀態且獲得投票權重大於0的生產者。
- 新的選舉結果,只能增加生產者個數不允許減少。
- 選舉出的新的生產者列表按照名稱排序。
- 調用set_proposed_producers注入函數,將選舉出的新的生產者列表置爲proposed。
設置proposed schedule生產者列表 :
將新的選舉結果置爲proposed schedule,需要:
- 上一個proposed schedule已經轉換爲pending schedule。
- 新的選舉結果與上一個proposed schedule不相同。
- 如果正在生產的區塊的pending_schedule存在,則新的選舉結果與pending_schedule不相同。
- 如果正在生產的區塊的pending_schedule不存在,則新的選舉結果與active_schedule不相同。
2,pending schedule生產者列表的替換
EOS中將proposed schedule切換至pending schedule的處理,在controller::start_block中:
將proposed schedule切換至pending schedule需要:
- 提案生產者列表有效。
- 提案生產者列表產生的對應的區塊已經變爲不可逆。
- pending schedule已經爲空,即上一次pending schedule已經轉換爲active schedule。
設置pending schedule:
- 記錄新的pending schedule生產者列表的hash,確保其不會被修改。
- 記錄設置pending schedule對應的區塊塊號。
將proposed schedule切換至pending schedule後,proposed schedule的記錄對象將被清空。
3,active schedule生產者列表的替換
創建一個新的正在生產區塊時,next會調用新區快對象的maybe_promote_pending,處理是否需要將pending schedule切換爲active schedule。
這時調用set_new_producers,是當pending schedule不爲空且沒有切換過active schedule,將pending schedule中的生產者列表傳遞給下一個區塊。
將pending schedule切換至active schedule的條件:
- pending schedule不爲空。
- 設置pending schedule的區塊已經不可逆。
切換操作:
-
將pending schedule中的內容移至active schedule,pending schedule的內容被清空。
-
遍歷新的生產者列表,如該生產者在老的生產者列表裏存在,則保留原生產者的區塊生產信息;如不存在,用當前不可逆塊號賦值給新的生產者的區塊生產信息。(producer_to_last_produced:生產者生產區塊表;producer_to_last_implied_irb:生產者生產不可逆區塊表。)
- 將當前區塊號賦給該塊的生產者對應的producer_to_last_produced。
四,節點生產區塊
1,節點狀態
EOS中節點的狀態根據是否準備好出塊可以分爲兩個:
producer_plugin_impl對象的_production_enabled屬性爲false:同步狀態,即當前節點正在接收其他節點發來的區塊做同步操作。
producer_plugin_impl對象的_production_enabled屬性爲true:生產狀態,即當前節點已經完成所有的區塊同步操作,可以生產區塊。
主節點初始啓動時,"enable-stale-production”選項必須爲true,_production_enabled爲true。
所有其他節點,在完成所有區塊同步後,_production_enabled被置爲true。(如果下一個塊的截止時間大於當前時間,意味着同步完成)
2,節點生產區塊的條件
- _production_enabled爲true,本節點已經完成同步可以出塊。
- _producers中包含了當前時間該出塊的生產者,即本節點是超級節點且輪到本節點出塊順序。
- 生產者出塊的簽名公私鑰存在。
- 距離本節點最後一個不可逆塊的時間小於_max_irreversible_block_age_us限制,_max_irreversible_block_age_us默認-1(不限制)。
- 生產者對應的水印值小於當前生產區塊的塊號+1,區塊生產順序無錯誤。
四 ,鏈接
瞭解最新更多區塊鏈相關文章
敬請關注星鏈微信公衆號,星鏈與你共成長