如何計算EOS代碼和ABI的哈希,針對這個問題,這篇文章詳細介紹了相對應(yīng)的分析和解答,希望可以幫助更多想解決這個問題的小伙伴找到更簡單易行的方法。
站在用戶的角度思考問題,與客戶深入溝通,找到芝罘網(wǎng)站設(shè)計與芝罘網(wǎng)站推廣的解決方案,憑借多年的經(jīng)驗,讓設(shè)計與互聯(lián)網(wǎng)技術(shù)結(jié)合,創(chuàng)造個性化、用戶體驗好的作品,建站類型包括:成都網(wǎng)站設(shè)計、網(wǎng)站建設(shè)、企業(yè)官網(wǎng)、英文網(wǎng)站、手機端網(wǎng)站、網(wǎng)站推廣、空間域名、虛擬主機、企業(yè)郵箱。業(yè)務(wù)覆蓋芝罘地區(qū)。
如果你想知道在EOS上部署了什么版本的智能合約,你需要查看代碼哈希。我們將看到如何計算代碼和ABI哈希,并編寫一個函數(shù),通過比較它們的哈希來查看本地WASM文件是否與正在運行的協(xié)議相匹配。
當(dāng)通過eosio
setcode
操作設(shè)置或更新合約時,檢查合約代碼是否已經(jīng)在運行。因此,通過查看setcode
實現(xiàn),我們可以從WASM文件看到如何計算哈希值。
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" ); // ... }
這只是一個簡單的WASM字節(jié)表示的sha256哈希值。(第二個參數(shù)只是字節(jié)數(shù)組的長度,哈希函數(shù)需要它來知道要對多少字節(jié)進行哈希處理。)
在node.js中,我們可以通過哈希一個WASM文件并將其與區(qū)塊鏈上代碼的哈希值進行比較來輕松實現(xià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ù)是一個很好的API端點,可以通過一個查詢同時獲取帳戶的代碼和abi哈希。
注意,WASM文件和代碼哈希依賴于編譯期間使用的eosio cpp
版本和-o
優(yōu)化參數(shù)。來自同一個C++代碼,代碼哈??赡苁遣煌?。
我們可以嘗試同樣的方法來計算ABI哈希,但是,由于某種原因,eosio setabi
操作不檢查ABI哈希,因此允許使用相同的哈希進行更新。
但是get-raw-abi-api
端點返回一個abi哈希,因此必須從某個地方獲取它。通過檢查nodeos-chain
插件,我們可以看到它是為每個請求動態(tài)計算的:
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; }
計算結(jié)果與ABI字節(jié)表示的代碼哈希 - SHA256 完全相同。然而,實際存儲ABI的方式有一個很大的區(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()) }
每個ABI必須包含一組特定的字段,如version
、types
、structs
、actions
、tables
,即版本、類型、結(jié)構(gòu)、操作、表等,然后將這些字段序列化為更大的有效表示形式。
計算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 }
關(guān)于如何計算EOS代碼和ABI的哈希問題的解答就分享到這里了,希望以上內(nèi)容可以對大家有一定的幫助,如果你還有很多疑惑沒有解開,可以關(guān)注創(chuàng)新互聯(lián)行業(yè)資訊頻道了解更多相關(guān)知識。
當(dāng)前標(biāo)題:如何計算EOS代碼和ABI的哈希
標(biāo)題路徑:http://jinyejixie.com/article26/pppsjg.html
成都網(wǎng)站建設(shè)公司_創(chuàng)新互聯(lián),為您提供ChatGPT、域名注冊、關(guān)鍵詞優(yōu)化、手機網(wǎng)站建設(shè)、定制開發(fā)、用戶體驗
聲明:本網(wǎng)站發(fā)布的內(nèi)容(圖片、視頻和文字)以用戶投稿、用戶轉(zhuǎn)載內(nèi)容為主,如果涉及侵權(quán)請盡快告知,我們將會在第一時間刪除。文章觀點不代表本網(wǎng)站立場,如需處理請聯(lián)系客服。電話:028-86922220;郵箱:631063699@qq.com。內(nèi)容未經(jīng)允許不得轉(zhuǎn)載,或轉(zhuǎn)載時需注明來源: 創(chuàng)新互聯(lián)