如何計(jì)算EOS代碼和ABI的哈希

如果你想知道在EOS上部署了什么版本的智能合約合是,你需要查看代碼哈希同辣。我們將看到如何計(jì)算代碼和ABI哈希冻记,并編寫一個(gè)函數(shù)晦毙,通過比較它們的哈希來查看本地WASM文件是否與正在運(yùn)行的協(xié)議相匹配。

EOS代碼的哈希

當(dāng)通過eosio setcode操作設(shè)置或更新合約時(shí)洽蛀,檢查合約代碼是否已經(jīng)在運(yùn)行摹迷。因此,通過查看setcode實(shí)現(xiàn)郊供,我們可以從WASM文件看到如何計(jì)算哈希值峡碉。

void apply_eosio_setcode(apply_context& context) {
   // some setup code

   fc::sha256 code_id; /// default ID == 0

   if( act.code.size() > 0 ) {
     code_id = fc::sha256::hash( act.code.data(), (uint32_t)act.code.size() );
     wasm_interface::validate(context.control, act.code);
   }

   const auto& account = db.get<account_object,by_name>(act.account);

   int64_t code_size = (int64_t)act.code.size();
   int64_t old_size  = (int64_t)account.code.size() * config::setcode_ram_bytes_multiplier;
   int64_t new_size  = code_size * config::setcode_ram_bytes_multiplier;

   EOS_ASSERT( account.code_version != code_id, set_exact_code, "contract is already running this version of code" );

   // ...
}

這只是一個(gè)簡單的WASM字節(jié)表示的sha256哈希值。(第二個(gè)參數(shù)只是字節(jié)數(shù)組的長度驮审,哈希函數(shù)需要它來知道要對多少字節(jié)進(jìn)行哈希處理鲫寄。)

在node.js中,我們可以通過哈希一個(gè)WASM文件并將其與區(qū)塊鏈上代碼的哈希值進(jìn)行比較來輕松實(shí)現(xiàn)這一點(diǎn)疯淫。

const fs = require(`fs`)
const crypto = require(`crypto`)

const loadFileContents = file => {
    if (!fs.existsSync(file)) {
        throw new Error(`Code file "${file}" does not exist.`)
    }

    // no encoding => read as Buffer
    return fs.readFileSync(file)
}

const createHash = contents => {
    const hash = crypto.createHash(`sha256`)
    hash.update(contents)
    const digest = hash.digest(`hex`)

    return digest
}

// fetch code contract from blockchain
const { code_hash: onChainCodeHash, abi_hash } = await api.rpc.fetch(`/v1/chain/get_raw_abi`, {
    account_name: `hello`,
})
const contents = loadFileContents(`contracts/hello.wasm`)
const codeHash = createHash(contents)

if (codeHash === onChainCodeHash) {
    console.log(`Code is up-to-date.`)
}

get-raw-abi函數(shù)是一個(gè)很好的API端點(diǎn)地来,可以通過一個(gè)查詢同時(shí)獲取帳戶的代碼和abi哈希。

注意熙掺,WASM文件和代碼哈希依賴于編譯期間使用的eosio cpp版本和-o優(yōu)化參數(shù)未斑。來自同一個(gè)C++代碼,代碼哈媳壹ǎ可能是不同的蜡秽。

EOS ABI 的哈希

我們可以嘗試同樣的方法來計(jì)算ABI哈希,但是缆镣,由于某種原因芽突,eosio setabi操作不檢查ABI哈希,因此允許使用相同的哈希進(jìn)行更新董瞻。

但是get-raw-abi-api端點(diǎn)返回一個(gè)abi哈希寞蚌,因此必須從某個(gè)地方獲取它。通過檢查nodeos-chain插件,我們可以看到它是為每個(gè)請求動(dòng)態(tài)計(jì)算的:

read_only::get_raw_abi_results read_only::get_raw_abi( const get_raw_abi_params& params )const {
   get_raw_abi_results result;
   result.account_name = params.account_name;

   const auto& d = db.db();
   const auto& accnt = d.get<account_object,by_name>(params.account_name);
   result.abi_hash = fc::sha256::hash( accnt.abi.data(), accnt.abi.size() );
   result.code_hash = accnt.code_version;
   if( !params.abi_hash || *params.abi_hash != result.abi_hash )
      result.abi = blob{{accnt.abi.begin(), accnt.abi.end()}};

   return result;
}

計(jì)算結(jié)果與ABI字節(jié)表示的代碼哈希 - SHA256 完全相同睬澡。然而固额,實(shí)際存儲ABI的方式有一個(gè)很大的區(qū)別。它不是作為熟悉的JSON文件存儲的煞聪,而是作為EOS稱之為原始ABI的打包方式存儲的斗躏。

從raw abi轉(zhuǎn)換為json很容易使用eosjs,但是從json轉(zhuǎn)換為raw abi需要一些nb的操作:

const {Serialize, Api} = require(`eosjs`)
const {TextEncoder, TextDecoder} = require(`util`) // node only; native TextEncoder/Decoder

const jsonToRawAbi = json => {
    const tmpApi = new Api({
        textDecoder: new TextDecoder(),
        textEncoder: new TextEncoder(),
    })
    const buffer = new Serialize.SerialBuffer({
        textEncoder: tmpApi.textEncoder,
        textDecoder: tmpApi.textDecoder,
    })

    const abiDefinition = tmpApi.abiTypes.get(`abi_def`)
    // need to make sure abi has every field in abiDefinition.fields
    // otherwise serialize throws
    const jsonExtended = abiDefinition.fields.reduce(
        (acc, {name: fieldName}) => Object.assign(acc, {[fieldName]: acc[fieldName] || []}),
        json,
    )
    abiDefinition.serialize(buffer, jsonExtended)

    if (!Serialize.supportedAbiVersion(buffer.getString())) {
        throw new Error(`Unsupported abi version`)
    }
    buffer.restartRead()

    // convert to node buffer
    return Buffer.from(buffer.asUint8Array())
}

每個(gè)ABI必須包含一組特定的字段昔脯,如version啄糙、typesstructs云稚、actions隧饼、tables,即版本静陈、類型燕雁、結(jié)構(gòu)、操作鲸拥、表等拐格,然后將這些字段序列化為更大的有效表示形式。

計(jì)算ABI哈希并用鏈上的值檢查它是很簡單的:

const contents = loadFileContents(`contracts/hello.abi`)

const abi = JSON.parse(contents.toString(`utf8`))
const serializedAbi = jsonToRawAbi(abi)

const abiHash = createHash(serializedAbi)

// fetch abi hash from blockchain
const { code_hash, abi_hash: onChainAbiHash } = await api.rpc.fetch(`/v1/chain/get_raw_abi`, {
    account_name: `hello`,
})

if (abiHash === onChainAbiHash) {
    console.log(`ABI is up-to-date.`)

    return null
}

======================================================================

分享一些比特幣刑赶、以太坊捏浊、EOS等區(qū)塊鏈相關(guān)的交互式在線編程實(shí)戰(zhàn)教程:

  • EOS入門教程,本課程幫助你快速入門EOS區(qū)塊鏈去中心化應(yīng)用的開發(fā)撞叨,內(nèi)容涵蓋EOS工具鏈金踪、賬戶與錢包、發(fā)行代幣牵敷、智能合約開發(fā)與部署胡岔、使用代碼與智能合約交互等核心知識點(diǎn),最后綜合運(yùn)用各知識點(diǎn)完成一個(gè)便簽DApp的開發(fā)劣领。
  • 深入淺出玩轉(zhuǎn)EOS錢包開發(fā)姐军,本課程以手機(jī)EOS錢包的完整開發(fā)過程為主線铁材,深入學(xué)習(xí)EOS區(qū)塊鏈應(yīng)用開發(fā)尖淘,課程內(nèi)容即涵蓋賬戶、計(jì)算資源著觉、智能合約村生、動(dòng)作與交易等EOS區(qū)塊鏈的核心概念,同時(shí)也講解如何使用eosjs和eosjs-ecc開發(fā)包訪問EOS區(qū)塊鏈饼丘,以及如何在React前端應(yīng)用中集成對EOS區(qū)塊鏈的支持趁桃。課程內(nèi)容深入淺出,非常適合前端工程師深入學(xué)習(xí)EOS區(qū)塊鏈應(yīng)用開發(fā)。
  • java比特幣開發(fā)教程卫病,本課程面向初學(xué)者油啤,內(nèi)容即涵蓋比特幣的核心概念,例如區(qū)塊鏈存儲蟀苛、去中心化共識機(jī)制益咬、密鑰與腳本、交易與UTXO等帜平,同時(shí)也詳細(xì)講解如何在Java代碼中集成比特幣支持功能幽告,例如創(chuàng)建地址、管理錢包裆甩、構(gòu)造裸交易等冗锁,是Java工程師不可多得的比特幣開發(fā)學(xué)習(xí)課程。
  • php比特幣開發(fā)教程嗤栓,本課程面向初學(xué)者冻河,內(nèi)容即涵蓋比特幣的核心概念,例如區(qū)塊鏈存儲茉帅、去中心化共識機(jī)制芋绸、密鑰與腳本、交易與UTXO等担敌,同時(shí)也詳細(xì)講解如何在Php代碼中集成比特幣支持功能摔敛,例如創(chuàng)建地址、管理錢包全封、構(gòu)造裸交易等马昙,是Php工程師不可多得的比特幣開發(fā)學(xué)習(xí)課程。
  • c#比特幣開發(fā)教程刹悴,本課程面向初學(xué)者行楞,內(nèi)容即涵蓋比特幣的核心概念,例如區(qū)塊鏈存儲土匀、去中心化共識機(jī)制子房、密鑰與腳本、交易與UTXO等就轧,同時(shí)也詳細(xì)講解如何在C#代碼中集成比特幣支持功能证杭,例如創(chuàng)建地址、管理錢包妒御、構(gòu)造裸交易等解愤,是C#工程師不可多得的比特幣開發(fā)學(xué)習(xí)課程。
  • java以太坊開發(fā)教程乎莉,主要是針對java和android程序員進(jìn)行區(qū)塊鏈以太坊開發(fā)的web3j詳解送讲。
  • python以太坊奸笤,主要是針對python工程師使用web3.py進(jìn)行區(qū)塊鏈以太坊開發(fā)的詳解。
  • php以太坊哼鬓,主要是介紹使用php進(jìn)行智能合約開發(fā)交互监右,進(jìn)行賬號創(chuàng)建、交易异希、轉(zhuǎn)賬秸侣、代幣開發(fā)以及過濾器和交易等內(nèi)容。
  • 以太坊入門教程宠互,主要介紹智能合約與dapp應(yīng)用開發(fā)味榛,適合入門。
  • 以太坊開發(fā)進(jìn)階教程予跌,主要是介紹使用node.js搏色、mongodb、區(qū)塊鏈券册、ipfs實(shí)現(xiàn)去中心化電商DApp實(shí)戰(zhàn)频轿,適合進(jìn)階。
  • ERC721以太坊通證實(shí)戰(zhàn)烁焙,課程以一個(gè)數(shù)字藝術(shù)品創(chuàng)作與分享DApp的實(shí)戰(zhàn)開發(fā)為主線航邢,深入講解以太坊非同質(zhì)化通證的概念、標(biāo)準(zhǔn)與開發(fā)方案骄蝇。內(nèi)容包含ERC-721標(biāo)準(zhǔn)的自主實(shí)現(xiàn)膳殷,講解OpenZeppelin合約代碼庫二次開發(fā),實(shí)戰(zhàn)項(xiàng)目采用Truffle九火,IPFS赚窃,實(shí)現(xiàn)了通證以及去中心化的通證交易所。
  • C#以太坊岔激,主要講解如何使用C#開發(fā)基于.Net的以太坊應(yīng)用勒极,包括賬戶管理、狀態(tài)與交易虑鼎、智能合約開發(fā)與交互辱匿、過濾器和交易等。
  • Hyperledger Fabric 區(qū)塊鏈開發(fā)詳解炫彩,本課程面向初學(xué)者匾七,內(nèi)容即包含Hyperledger Fabric的身份證書與MSP服務(wù)、權(quán)限策略媒楼、通道配置與啟動(dòng)乐尊、鏈碼通信接口等核心概念戚丸,也包含F(xiàn)abric網(wǎng)絡(luò)設(shè)計(jì)划址、nodejs鏈碼與應(yīng)用開發(fā)的操作實(shí)踐扔嵌,是Nodejs工程師學(xué)習(xí)Fabric區(qū)塊鏈開發(fā)的最佳選擇。
  • Hyperledger Fabric java 區(qū)塊鏈開發(fā)詳解夺颤,課程面向初學(xué)者痢缎,內(nèi)容即包含Hyperledger Fabric的身份證書與MSP服務(wù)、權(quán)限策略世澜、頻道配置與啟動(dòng)独旷、鏈碼通信接口等核心概念,也包含F(xiàn)abric網(wǎng)絡(luò)設(shè)計(jì)寥裂、java鏈碼與應(yīng)用開發(fā)的操作實(shí)踐嵌洼,是java工程師學(xué)習(xí)Fabric區(qū)塊鏈開發(fā)的最佳選擇。
  • tendermint區(qū)塊鏈開發(fā)詳解封恰,本課程適合希望使用tendermint進(jìn)行區(qū)塊鏈開發(fā)的工程師麻养,課程內(nèi)容即包括tendermint應(yīng)用開發(fā)模型中的核心概念,例如ABCI接口诺舔、默克爾樹鳖昌、多版本狀態(tài)庫等,也包括代幣發(fā)行等豐富的實(shí)操代碼低飒,是go語言工程師快速入門區(qū)塊鏈開發(fā)的最佳選擇许昨。

匯智網(wǎng)原創(chuàng)翻譯,轉(zhuǎn)載請標(biāo)明出處褥赊。這里是如何計(jì)算EOS代碼和ABI的哈希

?著作權(quán)歸作者所有,轉(zhuǎn)載或內(nèi)容合作請聯(lián)系作者
  • 序言:七十年代末糕档,一起剝皮案震驚了整個(gè)濱河市,隨后出現(xiàn)的幾起案子拌喉,更是在濱河造成了極大的恐慌翼岁,老刑警劉巖,帶你破解...
    沈念sama閱讀 218,858評論 6 508
  • 序言:濱河連續(xù)發(fā)生了三起死亡事件司光,死亡現(xiàn)場離奇詭異琅坡,居然都是意外死亡,警方通過查閱死者的電腦和手機(jī)残家,發(fā)現(xiàn)死者居然都...
    沈念sama閱讀 93,372評論 3 395
  • 文/潘曉璐 我一進(jìn)店門榆俺,熙熙樓的掌柜王于貴愁眉苦臉地迎上來,“玉大人坞淮,你說我怎么就攤上這事茴晋。” “怎么了回窘?”我有些...
    開封第一講書人閱讀 165,282評論 0 356
  • 文/不壞的土叔 我叫張陵诺擅,是天一觀的道長。 經(jīng)常有香客問我啡直,道長烁涌,這世上最難降的妖魔是什么苍碟? 我笑而不...
    開封第一講書人閱讀 58,842評論 1 295
  • 正文 為了忘掉前任,我火速辦了婚禮撮执,結(jié)果婚禮上微峰,老公的妹妹穿的比我還像新娘。我一直安慰自己抒钱,他們只是感情好蜓肆,可當(dāng)我...
    茶點(diǎn)故事閱讀 67,857評論 6 392
  • 文/花漫 我一把揭開白布。 她就那樣靜靜地躺著谋币,像睡著了一般仗扬。 火紅的嫁衣襯著肌膚如雪。 梳的紋絲不亂的頭發(fā)上蕾额,一...
    開封第一講書人閱讀 51,679評論 1 305
  • 那天厉颤,我揣著相機(jī)與錄音,去河邊找鬼凡简。 笑死逼友,一個(gè)胖子當(dāng)著我的面吹牛,可吹牛的內(nèi)容都是我干的秤涩。 我是一名探鬼主播帜乞,決...
    沈念sama閱讀 40,406評論 3 418
  • 文/蒼蘭香墨 我猛地睜開眼,長吁一口氣:“原來是場噩夢啊……” “哼筐眷!你這毒婦竟也來了黎烈?” 一聲冷哼從身側(cè)響起,我...
    開封第一講書人閱讀 39,311評論 0 276
  • 序言:老撾萬榮一對情侶失蹤匀谣,失蹤者是張志新(化名)和其女友劉穎照棋,沒想到半個(gè)月后,有當(dāng)?shù)厝嗽跇淞掷锇l(fā)現(xiàn)了一具尸體武翎,經(jīng)...
    沈念sama閱讀 45,767評論 1 315
  • 正文 獨(dú)居荒郊野嶺守林人離奇死亡烈炭,尸身上長有42處帶血的膿包…… 初始之章·張勛 以下內(nèi)容為張勛視角 年9月15日...
    茶點(diǎn)故事閱讀 37,945評論 3 336
  • 正文 我和宋清朗相戀三年,在試婚紗的時(shí)候發(fā)現(xiàn)自己被綠了宝恶。 大學(xué)時(shí)的朋友給我發(fā)了我未婚夫和他白月光在一起吃飯的照片符隙。...
    茶點(diǎn)故事閱讀 40,090評論 1 350
  • 序言:一個(gè)原本活蹦亂跳的男人離奇死亡,死狀恐怖垫毙,靈堂內(nèi)的尸體忽然破棺而出霹疫,到底是詐尸還是另有隱情,我是刑警寧澤综芥,帶...
    沈念sama閱讀 35,785評論 5 346
  • 正文 年R本政府宣布丽蝎,位于F島的核電站,受9級特大地震影響膀藐,放射性物質(zhì)發(fā)生泄漏屠阻。R本人自食惡果不足惜红省,卻給世界環(huán)境...
    茶點(diǎn)故事閱讀 41,420評論 3 331
  • 文/蒙蒙 一、第九天 我趴在偏房一處隱蔽的房頂上張望栏笆。 院中可真熱鬧类腮,春花似錦臊泰、人聲如沸蛉加。這莊子的主人今日做“春日...
    開封第一講書人閱讀 31,988評論 0 22
  • 文/蒼蘭香墨 我抬頭看了看天上的太陽针饥。三九已至,卻和暖如春需频,著一層夾襖步出監(jiān)牢的瞬間丁眼,已是汗流浹背。 一陣腳步聲響...
    開封第一講書人閱讀 33,101評論 1 271
  • 我被黑心中介騙來泰國打工昭殉, 沒想到剛下飛機(jī)就差點(diǎn)兒被人妖公主榨干…… 1. 我叫王不留苞七,地道東北人。 一個(gè)月前我還...
    沈念sama閱讀 48,298評論 3 372
  • 正文 我出身青樓挪丢,卻偏偏與公主長得像蹂风,于是被迫代替她去往敵國和親。 傳聞我的和親對象是個(gè)殘疾皇子乾蓬,可洞房花燭夜當(dāng)晚...
    茶點(diǎn)故事閱讀 45,033評論 2 355

推薦閱讀更多精彩內(nèi)容