Tests for builtin actor events API

This commit is contained in:
Aarsh Shah authored and Phi-rjan committed 2024-03-22 07:00:28 +01:00
1 parent 74a46fed3d
commit 0ca169d252
19 files changed
+519 -247

No files matched your search

-94
View File
@@ -1,94 +0,0 @@
package itests
import (
"context"
"fmt"
"testing"
"time"
"github.com/stretchr/testify/require"
"github.com/filecoin-project/go-address"
"github.com/filecoin-project/lotus/chain/types"
"github.com/filecoin-project/lotus/itests/kit"
)
func TestGetActorEvents(t *testing.T) {
t.Skip("skipping for now")
//require := require.New(t)
kit.QuietAllLogsExcept("events", "messagepool")
blockTime := 100 * time.Millisecond
client, _, ens := kit.EnsembleMinimal(t, kit.MockProofs(), kit.ThroughRPC())
ens.InterconnectAll().BeginMining(blockTime)
ctx, cancel := context.WithTimeout(context.Background(), time.Minute)
defer cancel()
// Set up the test fixture with a standard list of invocations
contract1, contract2, invocations := prepareEventMatrixInvocations(ctx, t, client)
fmt.Printf("contract1:%s; contract2:%s\n", contract1, contract2)
cf1, err := contract1.ToFilecoinAddress()
if err != nil {
panic(err)
}
cf2, err := contract2.ToFilecoinAddress()
if err != nil {
panic(err)
}
fmt.Printf("contract1 f4 is:%s; contract2 f4 is:%s\n", cf1.String(), cf2.String())
testCases := getCombinationFilterTestCases(contract1, contract2, "0x0")
messages := invokeAndWaitUntilAllOnChain(t, client, invocations)
// f410fiy2dwcbbvc5c6xwwrhlwgi2dby4rzgamxllpgva
for _, tc := range testCases {
tc := tc // appease the lint despot
t.Run(tc.name, func(t *testing.T) {
res, err := client.EthGetLogs(ctx, tc.spec)
require.NoError(t, err)
/*ch, _ := client.SubscribeActorEvents(ctx, &types.SubActorEventFilter{
Prefill: true,
ActorEventFilter: types.ActorEventFilter{
MinEpoch: 0,
MaxEpoch: 1000,
},
})
for i := range ch {
fmt.Println("Hello Chan", i.Entries[0].Key, i.Entries[0].Codec, i.EmitterAddr.String())
}*/
res2, _ := client.GetActorEvents(ctx, &types.ActorEventFilter{
MinEpoch: 0,
MaxEpoch: -1,
Addresses: []address.Address{cf2},
//EthAddresses: []ethtypes.EthAddress{
// contract1,
//},
})
for _, res := range res2 {
res := res
fmt.Println("Emitter Address is", res.EmitterAddr.String())
for _, entry := range res.Entries {
fmt.Println("Hello", entry.Key, entry.Codec, string(entry.Value))
}
}
fmt.Println("Hello", res2[0].Entries[0].Key, res2[0].Entries[0].Codec, res2[0].EmitterAddr.String())
elogs, err := parseEthLogsFromFilterResult(res)
require.NoError(t, err)
AssertEthLogs(t, elogs, tc.expected, messages)
})
}
}
+120 -26
View File
@@ -4,8 +4,10 @@ import (
"bytes"
"context"
"crypto/rand"
"encoding/json"
"fmt"
"os"
"sort"
"strings"
"testing"
"time"
@@ -149,22 +151,28 @@ func TestOnboardRawPieceVerified(t *testing.T) {
kit.Account(verifiedClientKey, abi.NewTokenAmount(bal.Int64())),
)
evtChan, err := miner.FullNode.SubscribeActorEvents(ctx, &types.SubActorEventFilter{
minerEvtsChan, err := miner.FullNode.SubscribeActorEvents(ctx, &types.SubActorEventFilter{
Filter: types.ActorEventFilter{
MinEpoch: -1,
MaxEpoch: -1,
Addresses: []address.Address{miner.ActorAddr},
},
Prefill: true,
})
require.NoError(t, err)
events := make([]types.ActorEvent, 0)
go func() {
for e := range evtChan {
fmt.Printf("%s Got ActorEvent: %+v", time.Now().Format(time.StampMilli), e)
events = append(events, *e)
}
}()
// only consume and match sector-activated events
sectorActivatedCbor, err := ipld.Encode(basicnode.NewString("sector-activated"), dagcbor.Encode)
require.NoError(t, err)
sectorActivatedEvtsCh, err := miner.FullNode.SubscribeActorEvents(ctx, &types.SubActorEventFilter{
Filter: types.ActorEventFilter{
Fields: map[string][]types.ActorEventBlock{
"$type": {
{Codec: 0x51, Value: sectorActivatedCbor},
},
},
},
Prefill: true,
})
require.NoError(t, err)
ens.InterconnectAll().BeginMiningMustPost(blocktime)
@@ -319,26 +327,112 @@ func TestOnboardRawPieceVerified(t *testing.T) {
allocations, err = client.StateGetAllocations(ctx, verifiedClientAddr, types.EmptyTSK)
require.NoError(t, err)
require.Len(t, allocations, 0)
eventsFromMessages := buildActorEventsFromMessages(ctx, t, miner.FullNode)
fmt.Println("eventsFromMessages", eventsFromMessages)
writeEventsToFile(ctx, t, miner.FullNode, eventsFromMessages)
evts, err := miner.FullNode.GetActorEvents(ctx, &types.ActorEventFilter{
MinEpoch: -1,
MaxEpoch: -1,
/* --- Tests for the Actor events API --- */
// Match events from Get API and receipts
allEvtsFromGetAPI, err := miner.FullNode.GetActorEvents(ctx, &types.ActorEventFilter{
FromEpoch: "earliest",
ToEpoch: "latest",
})
require.NoError(t, err)
for _, evt := range evts {
fmt.Printf("Got ActorEvent: %+v", evt)
}
matchEvents(t, eventsFromMessages, getEventsArray(allEvtsFromGetAPI))
eventsFromMessages := buildActorEventsFromMessages(t, ctx, miner.FullNode)
writeEventsToFile(t, ctx, miner.FullNode, eventsFromMessages)
for _, evt := range evts {
fmt.Printf("Got ActorEvent from messages: %+v", evt)
// match Miner Actor events from subscription channel and Miner Actor events obtained from receipts
var subMinerEvts []types.ActorEvent
for evt := range minerEvtsChan {
subMinerEvts = append(subMinerEvts, *evt)
if len(subMinerEvts) == 4 {
break
}
}
var allMinerEvts []types.ActorEvent
for _, evt := range eventsFromMessages {
if evt.EmitterAddr == miner.ActorAddr {
allMinerEvts = append(allMinerEvts, evt)
}
}
matchEvents(t, allMinerEvts, subMinerEvts)
// TODO: compare GetActorEvents & SubscribeActorEvents & eventsFromMessages for equality
// Match pre-filled events from sector activated channel and events obtained from receipts
var prefillSectorActivatedEvts []types.ActorEvent
for evt := range sectorActivatedEvtsCh {
prefillSectorActivatedEvts = append(prefillSectorActivatedEvts, *evt)
if len(prefillSectorActivatedEvts) == 2 {
break
}
}
require.Len(t, prefillSectorActivatedEvts, 2)
var sectorActivatedEvts []types.ActorEvent
for _, evt := range eventsFromMessages {
for _, entry := range evt.Entries {
if entry.Key == "$type" && bytes.Equal(entry.Value, sectorActivatedCbor) {
sectorActivatedEvts = append(sectorActivatedEvts, evt)
break
}
}
}
matchEvents(t, sectorActivatedEvts, prefillSectorActivatedEvts)
// Match pre-filled events from subscription channel and events obtained from receipts
allEvtsCh, err := miner.FullNode.SubscribeActorEvents(ctx, &types.SubActorEventFilter{
Filter: types.ActorEventFilter{
FromEpoch: "earliest",
ToEpoch: "latest",
},
Prefill: true,
})
require.NoError(t, err)
var prefillEvts []types.ActorEvent
for evt := range allEvtsCh {
prefillEvts = append(prefillEvts, *evt)
if len(prefillEvts) == len(eventsFromMessages) {
break
}
}
matchEvents(t, eventsFromMessages, prefillEvts)
}
func buildActorEventsFromMessages(t *testing.T, ctx context.Context, node v1api.FullNode) []types.ActorEvent {
func getEventsArray(ptr []*types.ActorEvent) []types.ActorEvent {
var evts []types.ActorEvent
for _, evt := range ptr {
evts = append(evts, *evt)
}
return evts
}
func matchEvents(t *testing.T, exp []types.ActorEvent, actual []types.ActorEvent) {
// height and tipset cid can mismatch because expected events are sourced using APIs that can put in different tipsets
for i := range exp {
exp[i].Height = 0
exp[i].TipSetKey = cid.Undef
}
for i := range actual {
actual[i].Height = 0
actual[i].TipSetKey = cid.Undef
}
require.Equal(t, len(exp), len(actual))
// marshal both arrays to json, sort by json, and compare
bz1, err := json.Marshal(exp)
require.NoError(t, err)
sort.Slice(bz1, func(i, j int) bool {
return bz1[i] <= bz1[j]
})
bz2, err := json.Marshal(actual)
require.NoError(t, err)
sort.Slice(bz2, func(i, j int) bool {
return bz2[i] <= bz2[j]
})
fmt.Println("bz1", string(bz1))
fmt.Println("bz2", string(bz2))
require.True(t, bytes.Equal(bz1, bz2))
}
func buildActorEventsFromMessages(ctx context.Context, t *testing.T, node v1api.FullNode) []types.ActorEvent {
actorEvents := make([]types.ActorEvent, 0)
head, err := node.ChainHead(ctx)
@@ -374,7 +468,7 @@ func buildActorEventsFromMessages(t *testing.T, ctx context.Context, node v1api.
Entries: evt.Entries,
EmitterAddr: addr,
Reverted: false,
Height: abi.ChainEpoch(height),
Height: ts.Height(),
TipSetKey: tsCid,
MsgCid: m.Cid,
})
@@ -386,7 +480,7 @@ func buildActorEventsFromMessages(t *testing.T, ctx context.Context, node v1api.
return actorEvents
}
func writeEventsToFile(t *testing.T, ctx context.Context, node v1api.FullNode, events []types.ActorEvent) {
func writeEventsToFile(ctx context.Context, t *testing.T, node v1api.FullNode, events []types.ActorEvent) {
file, err := os.Create("block.out")
require.NoError(t, err)
defer func() {
@@ -417,11 +511,11 @@ func writeEventsToFile(t *testing.T, ctx context.Context, node v1api.FullNode, e
if e.Key == "$type" && bytes.Equal(e.Value, claimKeyCbor) {
isClaim = true
} else if isClaim && e.Key == "id" {
nd, err := ipld.DecodeUsingPrototype([]byte(e.Value), dagcbor.Decode, bindnode.Prototype((*int64)(nil), nil))
nd, err := ipld.DecodeUsingPrototype(e.Value, dagcbor.Decode, bindnode.Prototype((*int64)(nil), nil))
require.NoError(t, err)
claimId = *bindnode.Unwrap(nd).(*int64)
} else if isClaim && e.Key == "provider" {
nd, err := ipld.DecodeUsingPrototype([]byte(e.Value), dagcbor.Decode, bindnode.Prototype((*int64)(nil), nil))
nd, err := ipld.DecodeUsingPrototype(e.Value, dagcbor.Decode, bindnode.Prototype((*int64)(nil), nil))
require.NoError(t, err)
providerId = *bindnode.Unwrap(nd).(*int64)
}
+3
View File
@@ -1,6 +1,8 @@
package kit
import (
"math"
"github.com/filecoin-project/go-state-types/abi"
"github.com/filecoin-project/go-state-types/big"
@@ -64,6 +66,7 @@ var DefaultNodeOpts = nodeOpts{
cfg.Fevm.EnableEthRPC = true
cfg.Fevm.EnableActorEventsAPI = true
cfg.Fevm.Events.MaxFilterHeightRange = math.MaxInt64
return nil
},
},