Merge pull request #10052 from filecoin-project/iand/issue-9849-filters
itests: Add tests for EthGetLogs filter combinations
This commit is contained in:
commit
1ea57740aa
@ -100,9 +100,18 @@ func (f *EventFilter) CollectEvents(ctx context.Context, te *TipSetEvents, rever
|
||||
continue
|
||||
}
|
||||
|
||||
decodedEntries := make([]types.EventEntry, len(ev.Entries))
|
||||
for i, entry := range ev.Entries {
|
||||
decodedEntries[i] = types.EventEntry{
|
||||
Flags: entry.Flags,
|
||||
Key: entry.Key,
|
||||
Value: decodeLogBytes(entry.Value),
|
||||
}
|
||||
}
|
||||
|
||||
// event matches filter, so record it
|
||||
cev := &CollectedEvent{
|
||||
Entries: ev.Entries,
|
||||
Entries: decodedEntries,
|
||||
EmitterAddr: addr,
|
||||
EventIdx: evIdx,
|
||||
Reverted: revert,
|
||||
|
@ -225,7 +225,7 @@ func (ei *EventIndex) CollectEvents(ctx context.Context, te *TipSetEvents, rever
|
||||
// This function swallows errors and returns the original array if it failed
|
||||
// to decode.
|
||||
func decodeLogBytes(orig []byte) []byte {
|
||||
if orig == nil {
|
||||
if len(orig) == 0 {
|
||||
return orig
|
||||
}
|
||||
decoded, err := cbg.ReadByteArray(bytes.NewReader(orig), uint64(len(orig)))
|
||||
|
@ -36,10 +36,7 @@ var ErrInvalidAddress = errors.New("invalid Filecoin Eth address")
|
||||
type EthUint64 uint64
|
||||
|
||||
func (e EthUint64) MarshalJSON() ([]byte, error) {
|
||||
if e == 0 {
|
||||
return json.Marshal("0x0")
|
||||
}
|
||||
return json.Marshal(fmt.Sprintf("0x%x", e))
|
||||
return json.Marshal(e.Hex())
|
||||
}
|
||||
|
||||
func (e *EthUint64) UnmarshalJSON(b []byte) error {
|
||||
@ -64,6 +61,13 @@ func EthUint64FromHex(s string) (EthUint64, error) {
|
||||
return EthUint64(parsedInt), nil
|
||||
}
|
||||
|
||||
func (e EthUint64) Hex() string {
|
||||
if e == 0 {
|
||||
return "0x0"
|
||||
}
|
||||
return fmt.Sprintf("0x%x", e)
|
||||
}
|
||||
|
||||
// EthBigInt represents a large integer whose zero value serializes to "0x0".
|
||||
type EthBigInt big.Int
|
||||
|
||||
|
1
itests/contracts/EventMatrix.hex
Normal file
1
itests/contracts/EventMatrix.hex
Normal file
@ -0,0 +1 @@
|
||||
608060405234801561001057600080fd5b506105eb806100206000396000f3fe608060405234801561001057600080fd5b50600436106100a95760003560e01c8063c755553811610071578063c755553814610198578063cbfc3b58146101c6578063cc6f8faf14610212578063cd5b6c3d14610254578063e2a614731461028c578063fb62b28b146102d8576100a9565b80630919b8be146100ae5780636199074d146100e657806366eef3461461012857806375091b1f14610132578063a63ae81a1461016a575b600080fd5b6100e4600480360360408110156100c457600080fd5b81019080803590602001909291908035906020019092919050505061031a565b005b610126600480360360608110156100fc57600080fd5b8101908080359060200190929190803590602001909291908035906020019092919050505061035d565b005b610130610391565b005b6101686004803603604081101561014857600080fd5b8101908080359060200190929190803590602001909291905050506103bf565b005b6101966004803603602081101561018057600080fd5b81019080803590602001909291905050506103fb565b005b6101c4600480360360208110156101ae57600080fd5b8101908080359060200190929190505050610435565b005b610210600480360360808110156101dc57600080fd5b8101908080359060200190929190803590602001909291908035906020019092919080359060200190929190505050610465565b005b6102526004803603606081101561022857600080fd5b810190808035906020019092919080359060200190929190803590602001909291905050506104ba565b005b61028a6004803603604081101561026a57600080fd5b8101908080359060200190929190803590602001909291905050506104f8565b005b6102d6600480360360808110156102a257600080fd5b810190808035906020019092919080359060200190929190803590602001909291908035906020019092919050505061052a565b005b610318600480360360608110156102ee57600080fd5b8101908080359060200190929190803590602001909291908035906020019092919050505061056a565b005b7f5469c6b769315f5668523937f05ca07d4cc87849432bc5f5907f1d90fa73b9f98282604051808381526020018281526020019250505060405180910390a15050565b8082847fb89dabcdb7ff41f1794c0da92f65ece6c19b6b0caeac5407b2a721efe27c080460405160405180910390a4505050565b7fc3f6f1c76bd4e74ee5782052b0b4f8bd5c50b86c3c5a2f52638e03066e50a91b60405160405180910390a1565b817f6709824ebe5f6e620ca3f4b02a3428e8ce2dc97c550816eaeeb3a342b214bd85826040518082815260200191505060405180910390a25050565b7fc804e53d6048af1b3e6a352e246d5f3864fea9d635ace499e023a58c383b3a88816040518082815260200191505060405180910390a150565b807f44a227a31429ab5eb00daf6611c6422f10571619f2267e0e149e9ebe6d2a5d0560405160405180910390a250565b7f28d45631a87b2a52a9625f8520fa37ff8c4d926cdf17042e241985da5cb7b850848484846040518085815260200184815260200183815260200182815260200194505050505060405180910390a150505050565b81837fcd5fe5fbc1d27b90036997224cea7aa565e3779622867265081f636b3a5ccb08836040518082815260200191505060405180910390a3505050565b80827f232f09cef3babc26e58d1cc1346c0a8bc626ffe600c9605b5d747783eda484a760405160405180910390a35050565b8183857f812e73dbcf7e267f27ecb1383bfc902a6650b41b6e7d03ac265108c369673d95846040518082815260200191505060405180910390a450505050565b7fd4d143faaf60340ad98e1f2c96fc26f5695834c21b5200edad339ee7e9a372cc83838360405180848152602001838152602001828152602001935050505060405180910390a150505056fea265627a7a72315820954561fde80ab925299e0a9f3356b01f64fb1976dd335ac2ebd9367441e29f0564736f6c63430005110032
|
51
itests/contracts/EventMatrix.sol
Normal file
51
itests/contracts/EventMatrix.sol
Normal file
@ -0,0 +1,51 @@
|
||||
pragma solidity ^0.5.0;
|
||||
|
||||
contract EventMatrix {
|
||||
event EventZeroData();
|
||||
event EventOneData(uint a);
|
||||
event EventTwoData(uint a, uint b);
|
||||
event EventThreeData(uint a, uint b, uint c);
|
||||
event EventFourData(uint a, uint b, uint c, uint d);
|
||||
|
||||
event EventOneIndexed(uint indexed a);
|
||||
event EventTwoIndexed(uint indexed a, uint indexed b);
|
||||
event EventThreeIndexed(uint indexed a, uint indexed b, uint indexed c);
|
||||
|
||||
event EventOneIndexedWithData(uint indexed a, uint b);
|
||||
event EventTwoIndexedWithData(uint indexed a, uint indexed b, uint c);
|
||||
event EventThreeIndexedWithData(uint indexed a, uint indexed b, uint indexed c, uint d);
|
||||
|
||||
function logEventZeroData() public {
|
||||
emit EventZeroData();
|
||||
}
|
||||
function logEventOneData(uint a) public {
|
||||
emit EventOneData(a);
|
||||
}
|
||||
function logEventTwoData(uint a, uint b) public {
|
||||
emit EventTwoData(a,b);
|
||||
}
|
||||
function logEventThreeData(uint a, uint b, uint c) public {
|
||||
emit EventThreeData(a,b,c);
|
||||
}
|
||||
function logEventFourData(uint a, uint b, uint c, uint d) public {
|
||||
emit EventFourData(a,b,c,d);
|
||||
}
|
||||
function logEventOneIndexed(uint a) public {
|
||||
emit EventOneIndexed(a);
|
||||
}
|
||||
function logEventTwoIndexed(uint a, uint b) public {
|
||||
emit EventTwoIndexed(a,b);
|
||||
}
|
||||
function logEventThreeIndexed(uint a, uint b, uint c) public {
|
||||
emit EventThreeIndexed(a,b,c);
|
||||
}
|
||||
function logEventOneIndexedWithData(uint a, uint b) public {
|
||||
emit EventOneIndexedWithData(a,b);
|
||||
}
|
||||
function logEventTwoIndexedWithData(uint a, uint b, uint c) public {
|
||||
emit EventTwoIndexedWithData(a,b,c);
|
||||
}
|
||||
function logEventThreeIndexedWithData(uint a, uint b, uint c, uint d) public {
|
||||
emit EventThreeIndexedWithData(a,b,c,d);
|
||||
}
|
||||
}
|
47
itests/contracts/events.asm
Normal file
47
itests/contracts/events.asm
Normal file
@ -0,0 +1,47 @@
|
||||
# https://github.com/filecoin-project/builtin-actors/blob/b1ba61053de2ceaddd5116e87823d20a8f5e38d7/actors/evm/tests/events.rs
|
||||
# method dispatch:
|
||||
# - 0x00000000 -> log_zero_data
|
||||
# - 0x00000001 -> log_zero_nodata
|
||||
# - 0x00000002 -> log_four_data
|
||||
%dispatch_begin()
|
||||
%dispatch(0x00, log_zero_data)
|
||||
%dispatch(0x01, log_zero_nodata)
|
||||
%dispatch(0x02, log_four_data)
|
||||
%dispatch_end()
|
||||
#### log a zero topic event with data
|
||||
log_zero_data:
|
||||
jumpdest
|
||||
push8 0x1122334455667788
|
||||
push1 0x00
|
||||
mstore
|
||||
push1 0x08
|
||||
push1 0x18 ## index 24 into memory as mstore writes a full word
|
||||
log0
|
||||
push1 0x00
|
||||
push1 0x00
|
||||
return
|
||||
#### log a zero topic event with no data
|
||||
log_zero_nodata:
|
||||
jumpdest
|
||||
push1 0x00
|
||||
push1 0x00
|
||||
log0
|
||||
push1 0x00
|
||||
push1 0x00
|
||||
return
|
||||
#### log a four topic event with data
|
||||
log_four_data:
|
||||
jumpdest
|
||||
push8 0x1122334455667788
|
||||
push1 0x00
|
||||
mstore
|
||||
push4 0x4444
|
||||
push3 0x3333
|
||||
push2 0x2222
|
||||
push2 0x1111
|
||||
push1 0x08
|
||||
push1 0x18 ## index 24 into memory as mstore writes a full word
|
||||
log4
|
||||
push1 0x00
|
||||
push1 0x00
|
||||
return
|
File diff suppressed because it is too large
Load Diff
@ -83,6 +83,9 @@ func (e *EVM) DeployContractFromFilename(ctx context.Context, binFilename string
|
||||
contractHex, err := os.ReadFile(binFilename)
|
||||
require.NoError(e.t, err)
|
||||
|
||||
// strip any trailing newlines from the file
|
||||
contractHex = bytes.TrimRight(contractHex, "\n")
|
||||
|
||||
contract, err := hex.DecodeString(string(contractHex))
|
||||
require.NoError(e.t, err)
|
||||
|
||||
|
@ -1,6 +1,9 @@
|
||||
package kit
|
||||
|
||||
import (
|
||||
"io"
|
||||
"log"
|
||||
|
||||
logging "github.com/ipfs/go-log/v2"
|
||||
|
||||
"github.com/filecoin-project/lotus/lib/lotuslog"
|
||||
@ -20,3 +23,13 @@ func QuietMiningLogs() {
|
||||
_ = logging.SetLogLevel("rpc", "ERROR")
|
||||
_ = logging.SetLogLevel("dht/RtRefreshManager", "ERROR")
|
||||
}
|
||||
|
||||
func QuietAllLogsExcept(names ...string) {
|
||||
log.SetOutput(io.Discard) // suppress LogDatastore messages
|
||||
|
||||
lotuslog.SetupLogLevels()
|
||||
logging.SetAllLoggers(logging.LevelError)
|
||||
for _, name := range names {
|
||||
_ = logging.SetLogLevel(name, "INFO")
|
||||
}
|
||||
}
|
||||
|
@ -952,18 +952,20 @@ func (e *EthEvent) installEthFilterSpec(ctx context.Context, filterSpec *ethtype
|
||||
// Here the client is looking for events between the head and some future height
|
||||
ts := e.Chain.GetHeaviestTipSet()
|
||||
if maxHeight-ts.Height() > e.MaxFilterHeightRange {
|
||||
return nil, xerrors.Errorf("invalid epoch range")
|
||||
return nil, xerrors.Errorf("invalid epoch range: to block is too far in the future (maximum: %d)", e.MaxFilterHeightRange)
|
||||
}
|
||||
} else if minHeight >= 0 && maxHeight == -1 {
|
||||
// Here the client is looking for events between some time in the past and the current head
|
||||
ts := e.Chain.GetHeaviestTipSet()
|
||||
if ts.Height()-minHeight > e.MaxFilterHeightRange {
|
||||
return nil, xerrors.Errorf("invalid epoch range")
|
||||
return nil, xerrors.Errorf("invalid epoch range: from block is too far in the past (maximum: %d)", e.MaxFilterHeightRange)
|
||||
}
|
||||
|
||||
} else if minHeight >= 0 && maxHeight >= 0 {
|
||||
if minHeight > maxHeight || maxHeight-minHeight > e.MaxFilterHeightRange {
|
||||
return nil, xerrors.Errorf("invalid epoch range")
|
||||
if minHeight > maxHeight {
|
||||
return nil, xerrors.Errorf("invalid epoch range: to block (%d) must be after from block (%d)", minHeight, maxHeight)
|
||||
} else if maxHeight-minHeight > e.MaxFilterHeightRange {
|
||||
return nil, xerrors.Errorf("invalid epoch range: range between to and from blocks is too large (maximum: %d)", e.MaxFilterHeightRange)
|
||||
}
|
||||
}
|
||||
|
||||
@ -979,13 +981,16 @@ func (e *EthEvent) installEthFilterSpec(ctx context.Context, filterSpec *ethtype
|
||||
}
|
||||
|
||||
for idx, vals := range filterSpec.Topics {
|
||||
if len(vals) == 0 {
|
||||
continue
|
||||
}
|
||||
// Ethereum topics are emitted using `LOG{0..4}` opcodes resulting in topics1..4
|
||||
key := fmt.Sprintf("topic%d", idx+1)
|
||||
keyvals := make([][]byte, len(vals))
|
||||
for i, v := range vals {
|
||||
keyvals[i] = v[:]
|
||||
for _, v := range vals {
|
||||
buf := make([]byte, len(v[:]))
|
||||
copy(buf, v[:])
|
||||
keys[key] = append(keys[key], buf)
|
||||
}
|
||||
keys[key] = keyvals
|
||||
}
|
||||
|
||||
return e.EventFilterManager.Install(ctx, minHeight, maxHeight, tipsetCid, addresses, keys)
|
||||
@ -1228,7 +1233,7 @@ func ethFilterResultFromEvents(evs []*filter.CollectedEvent, sa StateAPI) (*etht
|
||||
var err error
|
||||
|
||||
for _, entry := range ev.Entries {
|
||||
value := ethtypes.EthBytes(leftpad32(decodeLogBytes(entry.Value)))
|
||||
value := ethtypes.EthBytes(leftpad32(entry.Value)) // value has already been cbor-decoded but see https://github.com/filecoin-project/ref-fvm/issues/1345
|
||||
if entry.Key == ethtypes.EthTopic1 || entry.Key == ethtypes.EthTopic2 || entry.Key == ethtypes.EthTopic3 || entry.Key == ethtypes.EthTopic4 {
|
||||
log.Topics = append(log.Topics, value)
|
||||
} else {
|
||||
@ -1771,7 +1776,7 @@ func newEthTxReceipt(ctx context.Context, tx ethtypes.EthTx, lookup *api.MsgLook
|
||||
}
|
||||
|
||||
for _, entry := range evt.Entries {
|
||||
value := ethtypes.EthBytes(leftpad32(decodeLogBytes(entry.Value)))
|
||||
value := ethtypes.EthBytes(leftpad32(entry.Value)) // value has already been cbor-decoded but see https://github.com/filecoin-project/ref-fvm/issues/1345
|
||||
if entry.Key == ethtypes.EthTopic1 || entry.Key == ethtypes.EthTopic2 || entry.Key == ethtypes.EthTopic3 || entry.Key == ethtypes.EthTopic4 {
|
||||
l.Topics = append(l.Topics, value)
|
||||
} else {
|
||||
@ -1882,21 +1887,6 @@ func EthTxHashGC(ctx context.Context, retentionDays int, manager *EthTxHashManag
|
||||
}
|
||||
}
|
||||
|
||||
// decodeLogBytes decodes a CBOR-serialized array into its original form.
|
||||
//
|
||||
// This function swallows errors and returns the original array if it failed
|
||||
// to decode.
|
||||
func decodeLogBytes(orig []byte) []byte {
|
||||
if orig == nil {
|
||||
return orig
|
||||
}
|
||||
decoded, err := cbg.ReadByteArray(bytes.NewReader(orig), uint64(len(orig)))
|
||||
if err != nil {
|
||||
return orig
|
||||
}
|
||||
return decoded
|
||||
}
|
||||
|
||||
// TODO we could also emit full EVM words from the EVM runtime, but not doing so
|
||||
// makes the contract slightly cheaper (and saves storage bytes), at the expense
|
||||
// of having to left pad in the API, which is a pretty acceptable tradeoff at
|
||||
|
Loading…
Reference in New Issue
Block a user