Ethereum以太坊事件日志查询参数

阿里云国内75折 回扣 微信号:monov8
阿里云国际,腾讯云国际,低至75折。AWS 93折 免费开户实名账号 代冲值 优惠多多 微信号:monov8 飞机:@monov6

目录

一、Ethereum事件日志查询参数

  • addresses合约地址列表
  • fromBlock开始区块
  • toBlock结束区块
  • topics主题数组
  • blockhash区块哈希优先级高于fromBlock、toBlock

这里主要介绍topics参数其他参数都比较好理解topics是长度为4的数组集合topic分为2种一种事件签名topic另一种indexed索引参数值topic。
topics的的0号位子数组放事件签名哈希1/2/3号位子数组对应放事件的indexed索引参数值对应的哈希。
以demo合约举例

pragma solidity ^0.4.4;

contract Hello {
    string name;
    event LogSet(string s);
    event LogSet1(string indexed s1);
    event LogSet2(string indexed s1, string indexed s2);
    event LogSet3(string indexed s1, string indexed s2, string indexed s3);

    constructor() public {
        name = "hello";
    }

    function get() public view returns (string) {
        return name;
    }

    function set(string newName) public {
        name = newName;
        emit LogSet(newName);
        emit LogSet1(newName);
        emit LogSet2(newName, "name2");
        emit LogSet3(newName, "name2", "name3");
    }
}

如果合约调用set(“Tom”)事件LogSet3的1号位indexed索引参数值为"Tom"2号位为"name2"3号位为"name3"。
注意
合约事件里最多只能有3个indexed索引参数。
如果事件定义改为

event LogSet3(string indexed s1, string s2, string indexed s3);

事件LogSet3的1号位indexed索引参数值为"Tom"2号位为"name3"没有3号位。

二、需求

部署一个新的Hello合约并调用一次set函数以触发生成4条不同的事件日志。要求查询该合约的LogSet3事件日志。

三、实现

第一步合约部署前获取到最新块高作为fromBlock假设9684。
第二步部署Hello合约并调用set函数入参newName=“Tom”假设获取到新合约地址0x0dba67483eddb71a84ac0834cd4c8c89dc971d4b。
第三步再次获取最新块高作为toBlock假设9686。
第四步计算事件LogSet3(string,string,string)的签名得到0x3e03ccf7099c79040ac78f368a6a038e5d7918b8504f8cc99fd4d1ae71181e7b。
第五步计算第一个indexed索引参数值"Tom"的哈希0x6984758a5a2907300d836a0ed6101bb5426c0a4422c0d996e8bbf9e59bb8c7cc计算第二个indexed索引参数值"name2"的哈希0x7d51639d4f8290223cffdcc7a75498fd9c00ab65e7daf27837046fec6a6d6504计算第三个indexed索引参数值"name3"的哈希0x289ff8670e65b79f5a7c14daf83f381a29ae238fff49f37396cc9100fb243074。
第六步组装日志查询请求参数如下

{
    "addresses": [
        "0x0dba67483eddb71a84ac0834cd4c8c89dc971d4b"
    ],
    "toBlock": "9686",
    "topics": [
        [
            "0x3e03ccf7099c79040ac78f368a6a038e5d7918b8504f8cc99fd4d1ae71181e7b"
        ],
        [
            "0x6984758a5a2907300d836a0ed6101bb5426c0a4422c0d996e8bbf9e59bb8c7cc"
        ],
        [
            "0x7d51639d4f8290223cffdcc7a75498fd9c00ab65e7daf27837046fec6a6d6504"
        ],
        [
            "0x289ff8670e65b79f5a7c14daf83f381a29ae238fff49f37396cc9100fb243074"
        ]
    ],
    "fromBlock": "9684"
}

实际上如果指定了具体的Hello合约地址请求参数里不需要第一个和第二个索引参数topic也可以唯一区分开该合约的其他三个事件如此请求参数如下

{
    "addresses": [
        "0x0dba67483eddb71a84ac0834cd4c8c89dc971d4b"
    ],
    "toBlock": "9686",
    "topics": [
        [
            "0x3e03ccf7099c79040ac78f368a6a038e5d7918b8504f8cc99fd4d1ae71181e7b"
        ],
        null,
        null,
        [
            "0x289ff8670e65b79f5a7c14daf83f381a29ae238fff49f37396cc9100fb243074"
        ]
    ],
    "fromBlock": "9684"
}

四、其他

如果事件参数中包含枚举类型如何正确计算该事件签名的topic。
在solidity中的enum类型实际上是无符号整数当枚举数量是小于等于2562的8次方个则enum是uint8类型的如果大于256且小于等于655362的16次方则enum是uint16类型的以次类推。其实在remix中也可以看到枚举内的数量小于256枚举类型自动使用uint8如下
uint8
所以对上面的例子事件签名DataSaved(ProofType,bytes)是错误的,DataSaved(enum,bytes)也是错误的。正确应该是DataSaved(uint8,bytes)
如果ProofType枚举的类型从2种变为257种在remix里重新部署合约后可以看到uint8自动变为uint16如下
uint16

阿里云国内75折 回扣 微信号:monov8
阿里云国际,腾讯云国际,低至75折。AWS 93折 免费开户实名账号 代冲值 优惠多多 微信号:monov8 飞机:@monov6
标签: 区块链