Tests for builtin actor events API
This commit is contained in:
1 parent
74a46fed3d
commit
0ca169d252
19 files changed
+519
-247
No files matched your search
@@ -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)
|
||||
})
|
||||
}
|
||||
}
|
||||
@@ -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)
|
||||
}
|
||||
|
||||
@@ -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
|
||||
},
|
||||
},
|
||||
|
||||
Reference in new issue
Block a user