一、目錄
☞事件的定義
☞web3事件監聽
☞檢索日誌
☞底層日誌接口
二、事件的定義
事件是使用EVM日誌內置功能的方便工具,在DAPP的接口中,它可以反過來調用Javascript的監聽事件的回調。
事件在合約中可被繼承。當被調用時,會觸發參數存儲到交易的日誌中(一種區塊鏈上的特殊數據結構)。這些日誌與合約的地址關聯,併合併到區塊鏈中,只要區塊可以訪問就一直存在(至少Frontier,Homestead是這樣,但Serenity也許也是這樣)。日誌和事件在合約內不可直接被訪問,即使是創建日誌的合約。
日誌的SPV(簡單支付驗證)是可能的,如果一個外部的實體提供了一個這樣證明的合約,它可以證明日誌在區塊鏈是否存在。但需要留意的是,由於合約中僅能訪問最近的256個區塊哈希,所以還需要提供區塊頭信息。
可以最多有三個參數被設置爲indexed,來設置是否被索引。設置爲索引後,可以允許通過這個參數來查找日誌,甚至可以按特定的值過濾。
如果數組(包括string和bytes)類型被標記爲索引項,會用它對應的Keccak-256哈希值做爲topic。
除非是匿名事件,否則事件簽名(比如:Deposit(address,hash256,uint256))是其中一個topic,同時也意味着對於匿名事件無法通過名字來過濾。
所有未被索引的參數將被做爲日誌的一部分被保存起來。
被索引的參數將不會保存它們自己,你可以搜索他們的值,但不能檢索值本身。下面我們來看看,如何在Solidity中實現一個事件:
從上面的例子中,我們使用event關鍵字定義一個事件,參數列表中爲要記錄的日誌參數的名稱及類型。
匿名和非匿名事件的結果對比:
下圖是通過掃描器觀察到的匿名和非匿名事件情況:
如圖所示,非匿名事件中的四個參數分別對應了四個topic,類似爲四個值分別建立對應的索引。
三、deleteweb3事件監聽
在web3.js中,提供了響應事件的方法,如下:
另外一種簡便寫法是直接加入事件回調,這樣就不用再寫watch的部分:
注意:在操作執行完成後,我們要記得調用event.stopWatching();來終止監聽。
四、檢索日誌
4.1Indexed屬性
可以在事件參數上增加indexed屬性,最多可以對三個參數增加這樣的屬性。加上這個屬性,可以允許你在web3.js中通過對加了這個屬性的參數進行值過濾,方式如下:
上面實現的是對value值爲100的日誌,過濾後的返回。
如果你想同時匹配多個值,還可以傳入一個要匹配的數組。
增加了indexed的參數值會存到日誌結構的Topic部分,便於快速查找。而未加indexed的參數值會存在data部分,成爲原始日誌。需要注意的是,如果增加indexed屬性的是數組類型(包括string和bytes),那麼只會在Topic存儲對應的數據的web3.sha3哈希值,將不會再存原始數據。因爲Topic是用於快速查找的,不能存任意長度的數據,所以通過Topic實際存的是數組這種非固定長度數據哈希結果。要查找時,是將要查找內容哈希後與Topic內容進行匹配,但我們不能反推哈希結果,從而得不到原始值。
4.2 顯式轉換
事件還支持傳入其它參數對象來限定可檢索的範圍,支持fromBlock,toBlock等過濾條件。
上面的代碼實現了從第一塊開始搜索日誌。
五、底層的日誌接口
可以通過底層的日誌接口來訪問底層的日誌機制。通過函數log0,log1,log2,log3,log4。logi支持i + 1個類型爲bytes32的參數。其中第一個參數是日誌的data部分,其它參數爲topic。所以下述事件:
使用API的等同寫法爲:
下面是一個使用log3打印日誌的例子:
第一個參數爲事件簽名的哈希值keccak256("Deposit(address,bytes32,uint256)"),後面三個是按順序的indexed的值。
-END-