Ethereum中Event

概述

本篇文章將描述EthereumEvent系統(tǒng)。在以太坊的合約代碼中,經(jīng)常會看到emit SomeEvent(...)的調(diào)用,對這里比較有困惑,查找了好些資料,整理出如下文檔。

官網(wǎng)描述

solidity官方文檔,對Event有如下描述:

  • Event是以太坊EVM日志功能的頂層抽象;
  • 應(yīng)用程序可以通過Ethereum client的RPC接口來訂閱、監(jiān)聽指定的Event。

在Ethereum的節(jié)點中,Event通過機(jī)制如下實現(xiàn):

solidity的合約通過編譯為字節(jié)碼,存儲至Ethereum的區(qū)塊鏈中;當(dāng)一個交易中有合約調(diào)用時,先從區(qū)塊鏈的數(shù)據(jù)庫中加載當(dāng)前Ethereum的合約字節(jié)碼(通過合約地址標(biāo)識),然后依據(jù)交易傳入的ABI信息,調(diào)用合約中相應(yīng)的功能;當(dāng)合約中某個功能有Event調(diào)用時,字節(jié)碼指令(LOG?)會將Event參數(shù)存儲在交易日志中--塊鏈中的特殊數(shù)據(jù)結(jié)構(gòu);
該日志結(jié)構(gòu)與合約地址關(guān)聯(lián),被寫入塊鏈存儲且永不刪除(在以太坊的Frontier、Homestead階段,永遠(yuǎn)不會刪除這些日志數(shù)據(jù);但在Serenity階段,可能這些Log會從塊鏈數(shù)據(jù)中刪除)。
在以太坊的智能合約中,無法訪問這些日志數(shù)據(jù)。

以太坊的日志也可以提供SPV(simple payment verification)證明;可以通過提供塊哈希,以及merkle樹路徑,來驗證某條log存在于指定的區(qū)塊中。

同時可以給Event中最多三個參數(shù)添加索引indexed屬性,以太坊會將這些索引參數(shù)添加至類似于topics的結(jié)構(gòu)中,而不是放到日志的數(shù)據(jù)部分;如果使用數(shù)組作為索引,會計算該數(shù)組的Keccak-256索引,然后存儲在topics結(jié)構(gòu)中,因為一個topic只能存放32字節(jié)的數(shù)據(jù)。

所有不帶索引indexed屬性的參數(shù)會被編碼進(jìn)Log的數(shù)據(jù)部分。

可以使用topics中的條目來搜索一些區(qū)塊中的特定事件;也可以通過合約地址來過濾事件。

以太坊中的LOG指令處理

LOG0: {
            execute:    makeLog(0),
            ...
        },
LOG1: {
            execute:    makeLog(1),
            ...
        },
...         
LOG4: {
            execute:    makeLog(4),
            ...
        },
    
        
        
// following functions are used by the instruction jump  table

// make log instruction function
func makeLog(size int) executionFunc {
    return func(pc *uint64, interpreter *EVMInterpreter, contract *Contract, memory *Memory, stack *Stack) ([]byte, error) {
        topics := make([]common.Hash, size)
        mStart, mSize := stack.pop(), stack.pop()
        for i := 0; i < size; i++ {
            topics[i] = common.BigToHash(stack.pop())
        }

        d := memory.GetCopy(mStart.Int64(), mSize.Int64())
        interpreter.evm.StateDB.AddLog(&types.Log{
            Address: contract.Address(),
            Topics:  topics,
            Data:    d,
            // This is a non-consensus field, but assigned here because
            // core/state doesn't know the current block number.
            BlockNumber: interpreter.evm.BlockNumber.Uint64(),
        })

        interpreter.intPool.put(mStart, mSize)
        return nil, nil
    }
}

在事件處理中,非索引indexed屬性的參數(shù)會被編碼為LOG的數(shù)據(jù)部分,放在調(diào)用合約數(shù)據(jù)的第一個參數(shù)位置,剩余的索引參數(shù)緊隨其后。當(dāng)前以太坊支持5個LOG指令(log0, log1, log2, log3, log4),log?中的?表示最多支持幾個索引;由于Log本身有一個索引,即Event的簽名.

查閱的資料

Where do contract event logs get stored in the Ethereum architecture?

?著作權(quán)歸作者所有,轉(zhuǎn)載或內(nèi)容合作請聯(lián)系作者
【社區(qū)內(nèi)容提示】社區(qū)部分內(nèi)容疑似由AI輔助生成,瀏覽時請結(jié)合常識與多方信息審慎甄別。
平臺聲明:文章內(nèi)容(如有圖片或視頻亦包括在內(nèi))由作者上傳并發(fā)布,文章內(nèi)容僅代表作者本人觀點,簡書系信息發(fā)布平臺,僅提供信息存儲服務(wù)。

相關(guān)閱讀更多精彩內(nèi)容

友情鏈接更多精彩內(nèi)容