【劉文彬】EOS商業落地利器:多簽名操做與應用

原文連接:醒者呆的博客園,www.cnblogs.com/Evsward/p/m…html

eos主網上線在即,它之因此能受到各方青睞,主要是看中了它在將來商業應用落地的潛力。在這期間,完善的帳戶與權限系統是必要條件。 關鍵字:eos,帳戶,錢包,權限,多重簽名,eosio.msig,proposal,權重,閾值node

概況

  • 帳戶:是存儲在區塊鏈上的人們可識別的ID。
  • 權限:每一個事務都有,它是由已配置許可的帳戶所評估的。
  • 閾值:每一個被命名的權限都有一個有效範圍,必須知足是在許可下的一個簽名事務,將被視爲有效。
  • 簽名:事務的簽名是經過利用一個客戶端來執行,該客戶端擁有一個已加載並已解鎖的錢包。
  • 錢包:能夠保護及使用你的keys的一個軟件。這些keys多是也可能不是區塊鏈受權的一個許可帳戶。

錢包

錢包是一個客戶端,用於存儲keys,可能與也可能不與一個或多個帳戶進行關聯。一個錢包會有鎖定和解鎖兩種狀態,理想狀態下,它是被一個高熵密碼所保護。EOSIO有一個命令行客戶端cleos,與一個輕客戶端keosd交互,它倆構成了eos錢包的這種模式。bash

帳戶

一個私人個體或者一個組織均可以擁有帳戶,在交易或者其餘push一個事務到區塊鏈上的時候,帳戶是必須的。 Authorities(權限) 和 Permissions(許可)併發

這兩個概念特別容易搞混爲一談,這裏給作一下區分。app

Authorities決定了是否每個給出的action都被正確受權。
複製代碼

每一個帳戶都有兩個與生俱來的權限命名:ide

  • owner,象徵着一個帳戶的全部權。只有不多的事務會須要這種權限。但最值得注意的是,actions能夠對owner的權限作出各類改變。因此通常來講,建議owner被冷藏存儲,不告訴任何人。owner能夠用來回復另外一個可能已遭泄露的許可。
  • active,用於轉移資金,投票生產者以及作其餘高級帳戶的變動操做。惟一不一樣的是,它不可以改變owner。

除了這兩個與生俱來的權限。一個帳戶也能擁有自定義命名的權限,它能夠進一步擴展帳戶管理。自定義權限很是靈活而且提出了衆多可能的用例實現。在開發者社區,這些問題已經被提了出來,包括他們是如何工做的,以及若是有的話是什麼約定被採用了。許可對於任何給定的權限能夠被分配到一個或多個公鑰或者一個有效的帳戶名稱。學習

綜合實踐

下面是結合全部上述概念以及一些小例子,用來展現如何實際使用它們。區塊鏈

默認帳戶配置(單簽名)

這裏主要講述當一個帳戶被建立之後,它是如何配置的。它分別擁有owner和active權限,可獨立設置key,兩個keys都是權重爲1,且許可的閾值也都是1。該帳戶在執行某個操做action時,須要經過默認的配置,單獨簽名受權一個本機權限。測試

建立帳戶演示ui

Usage: cleos create account [OPTIONS] creator name OwnerKey [ActiveKey]
複製代碼

(在eos正式版本中,activeKey已不強制,變爲可選)在建立帳戶時,須要指定其owner和active兩個權限的key,這裏要使用公鑰。因此,

liuwenbin@liuwenbin:~$ cleos create account eosio lllwwwbbb "EOS6MRyAjQq8ud7hVNYcfnVPJqcVpscN5So8BhtHuGYqET5GDW5CV"
executed transaction: 7afb37faf4fadaf1b23bbf33a2ec316baf41fcd8e5587f4b2307db091c372829  200 bytes  209 us
# eosio <= eosio::newaccount {"creator":"eosio","name":"lllwwwbbb","owner":{"threshold":1,"keys":[{"key":"EOS6MRyAjQq8ud7hVNYcfnV...
warning: transaction executed locally, but may not be confirmed by the network yet
複製代碼

這個版本只須要指定一個owner權限的key便可建立帳戶。active權限是小於owner的,因此顯得不那麼重要。

多簽名帳戶

上面單簽名的內容很簡單,之因此介紹它,是爲了與本節多簽名帳戶進行比較學習。
複製代碼

多簽名帳戶,一個帳戶假設爲Jack的owner和active權限分別被受權爲其餘兩個帳戶Alice和Bob的許可。

@Jack

permission account weight threshold
owner 2
@Alice 1
@Bob 1
active 1
@Alice 1
@Bob 1

多帳戶權限演示

首先,咱們建立至少三對key:

liuwenbin@liuwenbin:~$ cleos wallet keys
[
  "EOS5WsMPtPqW8d3yxfCWP9WJcbkD3wDBWDfyV2CLagC7tWKT9wGkX",
  "EOS5nrEfZ4wcnmt2u2PGWDneZDNevQ6MoiF4RE3hpLKHk2rWpBB8x",
  "EOS6MRyAjQq8ud7hVNYcfnVPJqcVpscN5So8BhtHuGYqET5GDW5CV",
  "EOS6PTrfoaTYRHUhCedBf6b9CX3KDpJoWry6WQHe3WkpdFTMV2f78"
]
複製代碼

而後,分別使用不一樣的public key建立三個帳戶:jack, alice和bob,建立成功之後,咱們先來查看當前jack帳戶的permission內容:

liuwenbin@liuwenbin:~$ cleos get account jack
permissions:
     owner     1:    1 EOS5WsMPtPqW8d3yxfCWP9WJcbkD3wDBWDfyV2CLagC7tWKT9wGkX
        active     1:    1 EOS5WsMPtPqW8d3yxfCWP9WJcbkD3wDBWDfyV2CLagC7tWKT9wGkX
複製代碼

接着,按照上面咱們設計的表格內容,咱們先對jack的owner權限進行修改:

liuwenbin@liuwenbin:~$ cleos set account permission jack owner '{"threshold":2,"keys":[],"accounts":[{"permission":{"actor":"alice","permission":"owner"},"weight":1},{"permission":{"actor":"bob","permission":"owner"},"weight":1}],"waits":[]}' -p jack@owner
executed transaction: 494777ac55fa19144027ba5fdf75dcdaab4c4d52cdcaa13c0b6ecabfe622ffd1  160 bytes  136 us
# eosio <= eosio::updateauth {"account":"jack","permission":"owner","parent":"","auth":{"threshold":2,"keys":[],"accounts":[{"per...
warning: transaction executed locally, but may not be confirmed by the network yet
複製代碼
注意這裏使用到了 cleos set account permission 命令。這條命令中比較重要的部分是第三個參數authority的內容。
複製代碼

authority的內容能夠是:

  • NULL,表明刪除權限
  • public key,將該權限的內容設置爲一個公鑰
  • JSON字符串,完整地複雜地設置一個帳戶某個權限的內容
  • 一個文件名,同上,只不過改成將完整配置放在文件中讀取

根據咱們以上對jack owner權限的設計方案,是屬於比較複雜的權限內容,所以這裏採用的是第三種方式,及JSON字符串的方式。那麼JSON字符串的格式是什麼?咱們例舉本次生效的配置格式化以下:

{
    "threshold": 2,
    "keys": [],
    "accounts": [
        {
            "permission": {
                "actor": "alice",
                "permission": "owner"
            },
            "weight": 1
        },
        {
            "permission": {
                "actor": "bob",
                "permission": "owner"
            },
            "weight": 1
        }
    ],
    "waits": []
}
複製代碼

咱們分別來介紹這裏面的字段:

threshold

目前最多隻有兩個帳戶,每一個帳戶的權重都是1,因此threshold的取值範圍是1或者2。

1:在@Jack帳戶上執行任何須要owner權限的操做必須由@Alice或者@Bob帳戶任意一個帳戶進行簽名受權。
2:在@Jack帳戶上執行任何須要owner權限的操做必須由@Alice和@Bob帳戶進行多簽名受權。
複製代碼

keys

也能夠經過JSON字符串設置祕鑰,這與在命令中第三個參數直接使用公鑰是相同的效果。可是要注意的是,若是該帳戶已經經過JSON設置了複雜的權限內容,再次修改的時候必定還須要使用原JSON數據進行增量修改,若使用命令行加公鑰的方式會直接覆蓋掉原JSON設置的複雜權限內容。

accounts

權限是經過其餘帳戶來受權,其中包括:

  • permission:某個帳戶actor的某個權限
  • weight,與上面的threshold呼應使用
  • 咱們這裏就是經過設置該字段來實現的多帳戶簽名。

waits

設置延時時間,最大不超過max_transacton_delay的配置值。


下面來設置其active權限,active權限與owner權限不一樣的是threshold的值,以及

帳戶除了owner權限是根權限之外,active自己是其子權限,而 cleos set account permission 命令設置的權限默認都是active的子權限,注意,咱們在設置active權限自己的時候,要手動指定其父權限爲owner,不然會默認指向本身,報錯。
複製代碼
liuwenbin@liuwenbin:~$ cleos set account permission jack active '{"threshold":1,"keys":[],"accounts":[{"permission":{"actor":"alice","permission":"owner"},"weight":1},{"permission":{"actor":"bob","permission":"owner"},"weight":1}],"waits":[]}' owner -p jack@owner
executed transaction: 0865e7e9122354a2c29fd9ab48bb39b8a7bd758fdd7c4dc376e21ce45d8e23fb  176 bytes  461 us
# eosio <= eosio::updateauth {"account":"jack","permission":"active","parent":"owner","auth":{"threshold":1,"keys":[],"accounts":...
warning: transaction executed locally, but may not be confirmed by the network yet
複製代碼

這樣,jack帳戶的權限就所有按照以上權限設計表格設置完畢了,下面咱們使用命令來驗證一下目前jack帳戶的權限內容:

liuwenbin@liuwenbin:~$ cleos get account jack
permissions:
     owner     2:    1 alice@owner, 1 bob@owner,
        active     1:    1 alice@owner, 1 bob@owner,
複製代碼

多簽名演示

一. 部署eosio.msig合約

首先要注意的是,EOS中對多簽名的支持是經過eosio.msig智能合約來支持的,所以秉承eos"專人專責"的設計規範,咱們先建立一個帳戶eosio.msig,並用該帳戶部署eosio.msig合約。
複製代碼

若是不是本身新增或者對原合約有修改的話,推薦直接使用build目錄下的contract,已經生成好了相關的wast以及abi文件。

二. 部署eosio.token合約

這裏咱們使用token合約的相關權限操做進行多簽名的演示。一樣的,咱們也建立一個帳戶eosio.token並用其部署eosio.token合約。建立一個SYS token,併發放給jack,bob和alice三人分別100個。而後咱們調用命令:

liuwenbin@liuwenbin:~$ cleos push action eosio.token transfer '["jack","bob","50 SYS"]' -p jack@owner
executed transaction: 8166f8503a098eeab6642afe375167e18bf79d0d904015f5bba19524ce2d56d6  144 bytes  846 us
# eosio.token <= eosio.token::transfer {"from":"jack","to":"bob","quantity":"50 SYS","memo":""}
# jack <= eosio.token::transfer {"from":"jack","to":"bob","quantity":"50 SYS","memo":""}
# bob <= eosio.token::transfer {"from":"jack","to":"bob","quantity":"50 SYS","memo":""}
warning: transaction executed locally, but may not be confirmed by the network yet
liuwenbin@liuwenbin:~$ cleos get currency balance eosio.token alice
100 SYS
liuwenbin@liuwenbin:~$ cleos get currency balance eosio.token jack
50 SYS
liuwenbin@liuwenbin:~$ cleos get currency balance eosio.token bob
150 SYS
複製代碼

該命令執行成功,是由jack@owner權限許可的該命令操做。

三. 描述問題,引出多簽名

咱們在上一小節中介紹到了,jack的owner權限是與bob和alice相關的。因此可能遇到這麼一個狀況,jack今天不在,而它又須要以上的操做怎麼辦?那麼是否能夠經過上面對jack權限的設置,在jack不在的狀況下經過bob和alice的操做完成本屬於jack權限許可的操做呢?是的,這就是多簽名的概念和意義。

四. 創建多簽名操做提案

首先,eos中關於多簽名的命令是multisig,這也是經過第一步中eosio.msig合約實現的。

jack不在,要想經過bob和alice兩我的來審批本屬於jack的操做,這就要比jack本人操做要麻煩一點,須要新建一個提案。
複製代碼
liuwenbin@liuwenbin:~$ cleos multisig propose nojack '[{"actor":"alice","permission":"owner"},{"actor":"bob","permission":"owner"}]' '[{"actor":"jack","permission":"owner"}]' eosio.token transfer '{"from":"jack","to":"bob","quantity":"5 SYS","memo":"test multisig"}' -p eosio.msig
executed transaction: a223945e79c92cd5ca5243d64dce02ecf9bb1420e6ca3b5e5ac3fdae3dd4e8c3  240 bytes  389 us
# eosio.msig <= eosio.msig::propose {"proposer":"eosio.msig","proposal_name":"nojack","requested":[{"actor":"alice","permission":"owner"...
warning: transaction executed locally, but may not be confirmed by the network yet
複製代碼
注意在提案中的定義操做要輸入完整的key-value對應參數關係。本例中,transfer後面的參數的定義內容與上面直接用jack是一致的,但格式是完整格式,上面jack單簽名時是使用的簡略版,可自行對比發現。

這個提案結尾須要一個帳戶受權,這個帳戶是不作限制的,只是爲了往後操做這個提案自己,所以這裏選擇一個不想關的用來部署eosio.msig合約的帳戶eosio.msig簽名受權該提案。
複製代碼

五. 查看提案

liuwenbin@liuwenbin:~$ cleos multisig review eosio.msig nojack
{
  "proposal_name": "nojack",
  "packed_transaction": "38d0295b000000000000000000000100a6823403ea3055000000572d3ccdcd0100000000000091790000000080ab26a72e00000000000091790000000000000e3d320000000000000000535953000000000d74657374206d756c746973696700",
  "transaction": {
    "expiration": "2018-06-20T03:55:36",
    "ref_block_num": 0,
    "ref_block_prefix": 0,
    "max_net_usage_words": 0,
    "max_cpu_usage_ms": 0,
    "delay_sec": 0,
    "context_free_actions": [],
    "actions": [{
        "account": "eosio.token",
        "name": "transfer",
        "authorization": [{
            "actor": "jack",
            "permission": "owner"
          }
        ],
        "data": {
          "from": "jack",
          "to": "bob",
          "quantity": "50 SYS",
          "memo": "test multisig"
        },
        "hex_data": "00000000000091790000000000000e3d320000000000000000535953000000000d74657374206d756c7469736967"
      }
    ],
    "transaction_extensions": []
  }
}
複製代碼

重點查看該提案設定的action,包括該action須要的權限,操做名,參數等。

六. 查看提案審批狀況

multisig合約定義了兩個數據表,其中一個approvals表就是記錄了提案的審批狀態。

liuwenbin@liuwenbin:~/.local/share/eosio/nodeos/config$ cleos get table eosio.msig eosio.msig approvals                                {
  "rows": [{
      "proposal_name": "nojack",
      "requested_approvals": [{
          "actor": "alice",
          "permission": "owner"
        },{
          "actor": "bob",
          "permission": "owner"
        }
      ],
      "provided_approvals": []
    }],
  "more": false
}
複製代碼

七. 審批提案

提案建立完成之後,就須要alice和bob這兩個帳戶分別進行審批,他們各自都須要使用本身的owner權限簽名審批這個動做。

liuwenbin@liuwenbin:~$ cleos multisig approve eosio.msig nojack '{"actor":"alice","permission":"owner"}' -p alice@owner
executed transaction: be473b9abcc361a6d4c00d726318d06cb98775bd9390f2ebe1e4e8d72afd5de2  128 bytes  269 us
# eosio.msig <= eosio.msig::approve {"proposer":"eosio.msig","proposal_name":"nojack","level":{"actor":"alice","permission":"owner"}}
warning: transaction executed locally, but may not be confirmed by the network yet
liuwenbin@liuwenbin:~$ cleos multisig approve eosio.msig nojack '{"actor":"bob","permission":"owner"}' -p bob@owner
executed transaction: 98c707b04ef43b17e25bfb5fb6700300f438ea3af08f5c5f44724bb7f66c9eb2  128 bytes  441 us
# eosio.msig <= eosio.msig::approve {"proposer":"eosio.msig","proposal_name":"nojack","level":{"actor":"bob","permission":"owner"}}
warning: transaction executed locally, but may not be confirmed by the network yet
複製代碼

八. 返回第6步

liuwenbin@liuwenbin:~/.local/share/eosio/nodeos/config$ cleos get table eosio.msig eosio.msig approvals                                {
  "rows": [{
      "proposal_name": "nojack",
      "requested_approvals": [],
      "provided_approvals": [{
          "actor": "alice",
          "permission": "owner"
        },{
          "actor": "bob",
          "permission": "owner"
        }
       ]
    }],
  "more": false
}
複製代碼

能夠看到,原requested_approvals中的待審批項已經所有轉到了provided_approvals 已審批列表中。

這裏咱們能夠經過unapprove命令將已審批項轉至未審批集合中去。unapprove的參數與以上approve徹底相同。
複製代碼

九. 執行提案

以上兩個非jack帳戶的審批過程就是多簽名的內容,多簽名執行成功之後,能夠開始執行提案。

liuwenbin@liuwenbin:~$ cleos multisig exec eosio.msig nojack -p eosio.msig
executed transaction: 8734cd573e33c0bbc9f13372f4950908312afdac0146bccae624dba53995bf4b  160 bytes  441 us
# eosio.msig <= eosio.msig::exec {"proposer":"eosio.msig","proposal_name":"nojack","executer":"eosio.msig"}
warning: transaction executed locally, but may not be confirmed by the network yet
複製代碼

解決問題:以上提案執行過程會出現執行失敗的狀況,錯誤信息:

{"auth":{"actor":"jack","permission":"owner"},"provided_delay":0,"provided_permissions":[{"actor":"eosio.msig","permission":"eosio.code"}],"provided_keys":[],"delay_max_limit_ms":388800000}
複製代碼
解決方法是要部署system合約並利用system合約爲多簽名合約的功能受權,受權成功之後再執行便可成功。
複製代碼

cleos push action eosio setpriv '["eosio.msig", 1]' -p eosio 1個小坑:是在部署system合約時報錯transaction took too long, 這種狀況只須要在執行命令時加 -x 參數,默認值是30s,改成60讓時間延長一些便可執行成功。

TODO:立刻會根據當前eos最新版本v1.0.6發出一篇關於環境搭建的配置文章,以免將來踩到與此相似的環境問題。
複製代碼

十. 驗證結果

執行成功之後,再次檢查各帳戶的SYS餘額,可以發現此提案的轉帳50個SYS的操做已經生效。

liuwenbin@liuwenbin:~$ cleos get currency balance eosio.token alice
100 SYS
liuwenbin@liuwenbin:~$ cleos get currency balance eosio.token jack
45 SYS
liuwenbin@liuwenbin:~$ cleos get currency balance eosio.token bob
155 SYS
複製代碼

自定義權限

上面提到了,除了owner和active權限以外,咱們還能夠自定義權限。仍在以上@Jack帳戶中進行補充,增長一個自定義權限,名爲publish:

permission account weight threshold
publish 2
@Alice 2
@Bob 2
"EOS6MRyAjQq8ud7hVNYcfnVPJqcVpscN5So8BhtHuGYqET5GDW5CV" 1

weight:

權重,這是相對於上面threshold閾值的概念,就拿上面的屬於帳戶@Jack的publish權限來說,它包含三個子權限分別是:

  • @Alice帳戶,權重爲2
  • @Bob帳戶,權重爲2
  • 一個keys,權重爲1

而此時publish權限的閾值設定爲2,也就是說,@Alice或@Bob任意一個帳戶都可以簽名受權@Jack帳戶的publish權限,由於這兩個帳戶的權重均爲2,任意一個簽名均可保證夠到publish權限的閾值2。而若是隻有權重爲1的keys簽名,則必須再有以上任意一個帳戶來同時簽名,總權重達到了3,超過了publish閾值2才能夠成功受權。

自定義權限部分的演示與上面的相似,經過set account permission能夠設置有key,有帳戶,不一樣權重的十分複雜的權限內容。這裏再也不贅述。
複製代碼

總結

本文能夠分爲兩部分,第一部分是如何爲一個帳戶設置複雜的權限體系,第二部分是如何利用帳戶權限進行多帳戶簽名。這部份內容十分靈活,依據這個流程,咱們能夠根據業務場景須要,調整設計。例如,多帳戶必須均簽名才能經過某一個操做,或者多帳戶只要其中一個或者多個簽名便可經過某一個操做。經過本文所述,都可實現。

參考資料

  • EOS官方文檔
  • 本地環境測試(基於EOS v1.0.5)

相關文章和視頻推薦

圓方圓學院聚集大批區塊鏈名師,打造精品的區塊鏈技術課程。 在各大平臺都長期有優質免費公開課,歡迎報名收看。

公開課地址:ke.qq.com/course/3451…

相關文章
相關標籤/搜索