在以太坊上實現聯盟鏈的小結
搞了三四個月聯盟鏈,基本上算是告一段落,大概梳理下所做的東西,希望能對要做聯盟鏈的人有所幫助。
在寫這篇文章前,簡單介紹下聯盟鏈的功能。
- 國密和國際算法切換
- 參數toml配置
- 有幣無幣
- 支持gmssl
- p2p的證書准入
- 委員會成員更新
- solc編譯器
- tendermint共識
- 權限准入
- 交易校驗
- rpc api
- 狀態存儲
- 系統合約
加密算法
-
國密和S256,P256
支持國密sm2,sm3,sm4,國際的支持p256,比特幣和以太坊都使用的s256.剛開始做的時候計算支持p256和國密,因爲go sdk裏面證書使用了p256。後在做的過程中發現國外證書很多還需要支持RSA,遂引入了gmssl,委員會中的PK公鑰和證書做了分離。
recover公鑰
Toml文件配置
toml文件的優點在於不需要在啓動的時候指定一系列參數
-
節點信息
- 網絡ID 同步模式
- 委員會私鑰
- IP和端口
-
txpool
- gas門檻
- txpool賬戶數
-
節點rpc端口api
- 存儲目錄
- ipc websocket
- 開放api
- rpc 端口
-
p2p節點配置
- 證書
- 節點私鑰
- 節點連接數
- 監聽地址
創世區塊
創世裏面指定了 UseGas
指定有無幣, KindOfCrypto
指定加密類型, PermisionWlSendTx
, PermisionWlCreateTx
是權限裏面是白名單還說黑名單有效, Committee
指定了委員會的成員信息, CertList
指定證書列表。
return &Genesis{ Config: params.TestnetChainConfig, UseGas: 1, IsCoin: 1, KindOfCrypto: 2, PermisionWlSendTx: 1, PermisionWlCreateTx: 1, Timestamp: 1537891200, Coinbase: common.HexToAddress("0x0000000000000000000000000000000000000000"), ParentHash: common.HexToHash("0x0000000000000000000000000000000000000000000000000000000000000000"), Alloc: map[common.Address]types.GenesisAccount{ common.HexToAddress("0x68231C69431Cd7592356aBaC59E7A9D325406653"): {Balance: amount1}, }, Committee: []*types.CommitteeMember{ {Coinbase: getAddressFromPub(seedkey1), Publickey: seedkey1}, }, CertList: certList, }
有無幣
當無幣時 EstimateGas
, SuggestPrice
評估 gaslimit
和 gas
的方法需要返回0, tx_pool
中關於 gas
的判斷和 evm
扣除 gas
的操作都要去掉。
GMSSL
這個模塊主要做證書的生成,自認證,頒發證書,支持國密和RSA。
P2P證書的准入
節點啓動的時候,委員會成員具有根證書,新接入的節點需要跟證書授權。
- 節點發現中加入證書校驗,校驗通過發送鄰居節點。
- 在祕鑰交換中也會校驗證書,校驗通過會建立連接。
- 支持tls,在開發中。
委員會成員更新
委員會成員的更新需要當屆成員發起提案,當三分之二成員對同一個成員發起了 提案
,則此成員在 下一屆
會成爲新的委員會成員。提案是通過 交易
達成的,在鏈上部署了一個證書 系統合約
,所有的委員會只需發一筆交易,即可對一個成員的 刪除
和 添加
.
solc編譯器
由於abi中 函數的簽名
用通過 sha3函數名+參數
得到的,所以如果你用以太坊提供的solc程序編譯的合約,在鏈上是部署不成功的,這時需要用國密的solc編譯器編譯。
tendermint共識
衆所周知,POW的共識TPS很低,想提高TPS,BFT算法是很好的選擇,tendermint共識做的非常棒,能在5s內出塊。
權限准入
這個恐怕是聯盟鏈裏面最複雜的場景了,花費了很長時間測試。主要有兩個 基本功能
- 發交易權限
- 創建合約權限
這兩大基本權限衍生出 管理員
和 普通成員
。管理員可以授予新成員普通成員權限和管理員權限。
-
組權限
:如果想對一批人進行管理,這裏引入了組權限
,即創建一個羣組,將一成員加到組裏面,如果想移除組裏所有人的權限,可刪除組。組裏面也有成員
和管理員
權限。 -
合約訪問權限
:自己的創建的合約,可設置誰可以訪問,只有添加到訪問列表裏的成員纔可訪問合約,這裏面也有成員
和管理員
權限。
權限是 系統合約
實現的,任何的權限控制都需要通過 交易
來完成,權限是 立即生效
的,這個和證書合約有所不同。
裏面用到了 大量的map
,導致存儲的時候需要實現rlp方法,對 map
進行 排序
。
交易校驗
由於國密recover公鑰沒有現成的實現,在交易字段裏面加入了PK,這個和SDK聯調的時候還是有一些問題,首先hash算法要匹配,計算出的TxHash要一樣, RLP數據
的順序也需一致。校驗簽名通過之後,用 PK
計算 賬戶地址
。
RPC API
rpc
中加入了證書和權限的一些查詢方法,通過修改web3ext.go完成的, inputDefaultBlockNumberFormatter
這個字段在console裏面可以不需要輸入,通過json rpc的時候則需要填寫,例如 latest
。
狀態存儲
合約和權限都是系統合約,存儲的方式與合約存儲一致,在狀態裏面加了種類型,方便狀態回退。
系統合約
系統合約類似預編譯合約,功能比以太坊裏面的預編譯合約強大一些,可操作狀態,系統合約裏面 不可存時間
,會造成狀態不一致,系統合約debug比較煩, Receipt
裏面 無Error
字段, Dapp
很難查詢合約 執行失敗
原因。
在寫這篇文章前,簡單介紹下聯盟鏈的功能。
- 國密和國際算法切換
- 參數toml配置
- 有幣無幣
- 支持gmssl
- p2p的證書准入
- 委員會成員更新
- solc編譯器
- tendermint共識
- 權限准入
- 交易校驗
- rpc api
- 狀態存儲
- 系統合約
加密算法
-
國密和S256,P256
支持國密sm2,sm3,sm4,國際的支持p256,比特幣和以太坊都使用的s256.剛開始做的時候計算支持p256和國密,因爲go sdk裏面證書使用了p256。後在做的過程中發現國外證書很多還需要支持RSA,遂引入了gmssl,委員會中的PK公鑰和證書做了分離。
recover公鑰
Toml文件配置
toml文件的優點在於不需要在啓動的時候指定一系列參數
-
節點信息
- 網絡ID 同步模式
- 委員會私鑰
- IP和端口
-
txpool
- gas門檻
- txpool賬戶數
-
節點rpc端口api
- 存儲目錄
- ipc websocket
- 開放api
- rpc 端口
-
p2p節點配置
- 證書
- 節點私鑰
- 節點連接數
- 監聽地址
創世區塊
創世裏面指定了 UseGas
指定有無幣, KindOfCrypto
指定加密類型, PermisionWlSendTx
, PermisionWlCreateTx
是權限裏面是白名單還說黑名單有效, Committee
指定了委員會的成員信息, CertList
指定證書列表。
return &Genesis{ Config: params.TestnetChainConfig, UseGas: 1, IsCoin: 1, KindOfCrypto: 2, PermisionWlSendTx: 1, PermisionWlCreateTx: 1, Timestamp: 1537891200, Coinbase: common.HexToAddress("0x0000000000000000000000000000000000000000"), ParentHash: common.HexToHash("0x0000000000000000000000000000000000000000000000000000000000000000"), Alloc: map[common.Address]types.GenesisAccount{ common.HexToAddress("0x68231C69431Cd7592356aBaC59E7A9D325406653"): {Balance: amount1}, }, Committee: []*types.CommitteeMember{ {Coinbase: getAddressFromPub(seedkey1), Publickey: seedkey1}, }, CertList: certList, }
有無幣
當無幣時 EstimateGas
, SuggestPrice
評估 gaslimit
和 gas
的方法需要返回0, tx_pool
中關於 gas
的判斷和 evm
扣除 gas
的操作都要去掉。
GMSSL
這個模塊主要做證書的生成,自認證,頒發證書,支持國密和RSA。
P2P證書的准入
節點啓動的時候,委員會成員具有根證書,新接入的節點需要跟證書授權。
- 節點發現中加入證書校驗,校驗通過發送鄰居節點。
- 在祕鑰交換中也會校驗證書,校驗通過會建立連接。
- 支持tls,在開發中。
委員會成員更新
委員會成員的更新需要當屆成員發起提案,當三分之二成員對同一個成員發起了 提案
,則此成員在 下一屆
會成爲新的委員會成員。提案是通過 交易
達成的,在鏈上部署了一個證書 系統合約
,所有的委員會只需發一筆交易,即可對一個成員的 刪除
和 添加
.
solc編譯器
由於abi中 函數的簽名
用通過 sha3函數名+參數
得到的,所以如果你用以太坊提供的solc程序編譯的合約,在鏈上是部署不成功的,這時需要用國密的solc編譯器編譯。
tendermint共識
衆所周知,POW的共識TPS很低,想提高TPS,BFT算法是很好的選擇,tendermint共識做的非常棒,能在5s內出塊。
權限准入
這個恐怕是聯盟鏈裏面最複雜的場景了,花費了很長時間測試。主要有兩個 基本功能
- 發交易權限
- 創建合約權限
這兩大基本權限衍生出 管理員
和 普通成員
。管理員可以授予新成員普通成員權限和管理員權限。
-
組權限
:如果想對一批人進行管理,這裏引入了組權限
,即創建一個羣組,將一成員加到組裏面,如果想移除組裏所有人的權限,可刪除組。組裏面也有成員
和管理員
權限。 -
合約訪問權限
:自己的創建的合約,可設置誰可以訪問,只有添加到訪問列表裏的成員纔可訪問合約,這裏面也有成員
和管理員
權限。
權限是 系統合約
實現的,任何的權限控制都需要通過 交易
來完成,權限是 立即生效
的,這個和證書合約有所不同。
裏面用到了 大量的map
,導致存儲的時候需要實現rlp方法,對 map
進行 排序
。
交易校驗
由於國密recover公鑰沒有現成的實現,在交易字段裏面加入了PK,這個和SDK聯調的時候還是有一些問題,首先hash算法要匹配,計算出的TxHash要一樣, RLP數據
的順序也需一致。校驗簽名通過之後,用 PK
計算 賬戶地址
。
RPC API
rpc
中加入了證書和權限的一些查詢方法,通過修改web3ext.go完成的, inputDefaultBlockNumberFormatter
這個字段在console裏面可以不需要輸入,通過json rpc的時候則需要填寫,例如 latest
。
狀態存儲
合約和權限都是系統合約,存儲的方式與合約存儲一致,在狀態裏面加了種類型,方便狀態回退。
系統合約
系統合約類似預編譯合約,功能比以太坊裏面的預編譯合約強大一些,可操作狀態,系統合約裏面 不可存時間
,會造成狀態不一致,系統合約debug比較煩, Receipt
裏面 無Error
字段, Dapp
很難查詢合約 執行失敗
原因。
本文參與登鏈社區寫作激勵計劃 ,好文好收益,歡迎正在閱讀的你也加入。
- 發表於 7分鐘前
- 閱讀 ( 6 )
- 學分 ( 0 )
- 分類:Geth