簡(jiǎn)介
本篇將為大家介紹eosio.msig的源碼實(shí)現(xiàn),合約代碼庫(kù)詳見(jiàn):eosio.msig。eosio.msig主要有propose、approve、unapprove、cancel、exec、invalidate這幾種方法,下面會(huì)詳細(xì)逐一介紹每種方法的功能和實(shí)現(xiàn)細(xì)節(jié)。
主要合約方法
eosio.msig合約,在eosio.msig.hpp頭文件中,主要定義了以下六個(gè)合約方法:
-?propose:提出提案
-?approve:通過(guò)提案
-?unapprove:不通過(guò)提案
-?cancel:取消提案
- exec:執(zhí)行提案
-?invalidate:撤回對(duì)之前所有該賬戶通過(guò)、但未被最終執(zhí)行的提案的通過(guò)授權(quán)

propose方法
propose方法主要功能是提出提案,對(duì)應(yīng)上篇提到的 `cleos multisig propose` 命令,傳參如下:
-?proposer:提案賬戶
-?proposal_name:提案名
-?requested:提案通過(guò)所需權(quán)限
-?trx:提案具體執(zhí)行的交易內(nèi)容
為了節(jié)省資源開(kāi)銷(xiāo),propose方法并不會(huì)根據(jù) `cleos multisig propose` 傳入的參數(shù)一一做解析,而是直接解析input data

之后,會(huì)做一系列前置檢驗(yàn)工作:proposer提案賬戶授權(quán)是否正確、交易是否超時(shí)、propose_name是否存在、提案通過(guò)所需權(quán)限是否正確等

之后,將提案和提案合約的內(nèi)容存表,將提案通過(guò)所需的權(quán)限存入requested_approvals表中,我們上篇文章所提到 `cleos get table eosio.msig <proposer account>?approvals` 命令查詢的就是這張表

approve方法
approve方法的主要功能是通過(guò)提案,對(duì)應(yīng)上篇提到的?`cleos multisig approve`?命令,傳參如下:
- proposer:提案人
- proposal_name:提案名
- permissions:使用哪個(gè)權(quán)限批準(zhǔn)這個(gè)提案
首先,系統(tǒng)會(huì)查找提案合約內(nèi)容,查找 requested_approvals 表中需要通過(guò)的權(quán)限中,是否有和傳入permission匹配項(xiàng)。若有匹配項(xiàng),將此權(quán)限加入?provided_approvals 表,即表示該權(quán)限通過(guò)此提案,并從 requested_approvals 表中移除該權(quán)限。

unapprove方法
unapprove方法的主要功能是不通過(guò)提案,對(duì)應(yīng)上篇提到的?`cleos multisig unapprove`?命令,傳參如下:
- proposer:提案人
- proposal_name:提案名
- permissions:使用哪個(gè)權(quán)限拒絕這個(gè)提案
首先,系統(tǒng)會(huì)查找提案合約內(nèi)容,查找?provided_approvals?表中通過(guò)的權(quán)限中,是否有和傳入permission匹配項(xiàng)。若有匹配項(xiàng),將此權(quán)限加入requested_approvals?表,即表示該權(quán)限還沒(méi)通過(guò)此提案,并從?provided_approvals?表中移除該權(quán)限。

cancel方法
cancel方法的主要功能是取消提案,對(duì)應(yīng)上篇提到的?`cleos multisig cancel`?命令,傳參如下:
- proposer:提案賬戶
- proposal_name:提案名
- canceler:取消賬戶
首先,先查找表獲取提案內(nèi)容。如果canceler賬戶和提案賬戶不同,則在提案交易過(guò)期之前,canceler都不能取消提案。若能取消,將提案從表中移除。

exec方法
exec方法的主要功能是執(zhí)行提案,對(duì)應(yīng)上篇提到的?`cleos multisig exec`?命令,傳參如下:
- proposer:提案賬戶
- proposal_name:提案名
- executer:執(zhí)行賬戶
首先,需要做前置檢查,檢查交易是否過(guò)期

然后,查 provided_approvals 表獲取通過(guò)提案交易的權(quán)限們,對(duì)比 inv_table 表,如果權(quán)限不在?inv_table?表中或者 last_invalidation_time 已經(jīng)小于當(dāng)前時(shí)間,代表權(quán)限有效,放入approvals表中。inv_table 表的用途在下一個(gè)invalidate方法中介紹

最后,執(zhí)行提案。如果交易執(zhí)行權(quán)限檢驗(yàn)無(wú)誤,會(huì)發(fā)起一個(gè)defer延遲合約,去執(zhí)行提案交易。如果執(zhí)行成功,`cleos get actions <executer account>` 會(huì)產(chǎn)生兩條actions,一條是exec的交易,一條是提案執(zhí)行的交易。

invalidate方法
invalidate方法的主要功能是:如果account之前通過(guò)的提案還未執(zhí)行,就可以使用該方法將提案一鍵設(shè)置為無(wú)效。這個(gè)方法主要是解決:賬戶權(quán)限變更時(shí),之前通過(guò)但未執(zhí)行的提案一旦執(zhí)行會(huì)盜取賬戶權(quán)限的問(wèn)題,詳見(jiàn)issue。該方法傳參如下:
- account:提案的批準(zhǔn)賬戶
該功能的實(shí)現(xiàn)非常簡(jiǎn)單,首先,inv_table 是用來(lái)存放權(quán)限的,它的兩個(gè)字段 account 和last_invalidation_time 分別是賬戶名和賬戶權(quán)限最近失效時(shí)間。last_invalidation_time 時(shí)間之前,account的提案批準(zhǔn)權(quán)限都不可用,在該時(shí)間之后account的提案批準(zhǔn)權(quán)限才能生效。
因此,如果想使account之前審批通過(guò)的所有提案都失效的話,就將?last_invalidation_time 設(shè)置為當(dāng)前時(shí)間即可。exec方法在執(zhí)行之前會(huì)檢查?inv_table,則包含在 inv_table 中的account,即便批準(zhǔn)了該提案,該批準(zhǔn)也會(huì)作廢

后記
不好意思,最近因?yàn)殡s七雜八的事情,很久沒(méi)更新博文,以后會(huì)更新的稍微勤快點(diǎn),請(qǐng)各位看客見(jiàn)諒。eosio.msig合約的介紹就到這里。后面的文章,將為大家介紹eosio.system合約,該合約是投票選舉超級(jí)節(jié)點(diǎn)的核心合約,盡請(qǐng)期待!