2023-01-13 19:11:13 +00:00
|
|
|
package modules
|
|
|
|
|
|
|
|
import (
|
|
|
|
"context"
|
2023-01-19 22:44:58 +00:00
|
|
|
"path/filepath"
|
2023-01-13 19:11:13 +00:00
|
|
|
"time"
|
|
|
|
|
|
|
|
"github.com/multiformats/go-varint"
|
|
|
|
"go.uber.org/fx"
|
|
|
|
|
|
|
|
"github.com/filecoin-project/go-address"
|
|
|
|
"github.com/filecoin-project/go-state-types/abi"
|
|
|
|
builtintypes "github.com/filecoin-project/go-state-types/builtin"
|
|
|
|
|
|
|
|
"github.com/filecoin-project/lotus/chain/events"
|
|
|
|
"github.com/filecoin-project/lotus/chain/events/filter"
|
|
|
|
"github.com/filecoin-project/lotus/chain/messagepool"
|
|
|
|
"github.com/filecoin-project/lotus/chain/stmgr"
|
|
|
|
"github.com/filecoin-project/lotus/chain/store"
|
|
|
|
"github.com/filecoin-project/lotus/chain/types"
|
|
|
|
"github.com/filecoin-project/lotus/node/config"
|
|
|
|
"github.com/filecoin-project/lotus/node/impl/full"
|
|
|
|
"github.com/filecoin-project/lotus/node/modules/helpers"
|
2023-01-19 22:44:58 +00:00
|
|
|
"github.com/filecoin-project/lotus/node/repo"
|
2023-01-13 19:11:13 +00:00
|
|
|
)
|
|
|
|
|
|
|
|
type EventAPI struct {
|
|
|
|
fx.In
|
|
|
|
|
|
|
|
full.ChainAPI
|
|
|
|
full.StateAPI
|
|
|
|
}
|
|
|
|
|
|
|
|
var _ events.EventAPI = &EventAPI{}
|
|
|
|
|
2023-01-19 22:44:58 +00:00
|
|
|
func EthEventAPI(cfg config.FevmConfig) func(helpers.MetricsCtx, repo.LockedRepo, fx.Lifecycle, *store.ChainStore, *stmgr.StateManager, EventAPI, *messagepool.MessagePool, full.StateAPI, full.ChainAPI) (*full.EthEvent, error) {
|
|
|
|
return func(mctx helpers.MetricsCtx, r repo.LockedRepo, lc fx.Lifecycle, cs *store.ChainStore, sm *stmgr.StateManager, evapi EventAPI, mp *messagepool.MessagePool, stateapi full.StateAPI, chainapi full.ChainAPI) (*full.EthEvent, error) {
|
2023-01-13 19:11:13 +00:00
|
|
|
ctx := helpers.LifecycleCtx(mctx, lc)
|
|
|
|
|
|
|
|
ee := &full.EthEvent{
|
|
|
|
Chain: cs,
|
2023-01-19 22:44:58 +00:00
|
|
|
MaxFilterHeightRange: abi.ChainEpoch(cfg.Events.MaxFilterHeightRange),
|
2023-01-26 14:20:49 +00:00
|
|
|
SubscribtionCtx: ctx,
|
2023-01-13 19:11:13 +00:00
|
|
|
}
|
|
|
|
|
2023-01-19 22:44:58 +00:00
|
|
|
if !cfg.EnableEthRPC || cfg.Events.DisableRealTimeFilterAPI {
|
2023-01-13 19:11:13 +00:00
|
|
|
// all event functionality is disabled
|
|
|
|
// the historic filter API relies on the real time one
|
|
|
|
return ee, nil
|
|
|
|
}
|
|
|
|
|
|
|
|
ee.SubManager = &full.EthSubscriptionManager{
|
|
|
|
Chain: cs,
|
|
|
|
StateAPI: stateapi,
|
|
|
|
ChainAPI: chainapi,
|
|
|
|
}
|
2023-01-19 22:44:58 +00:00
|
|
|
ee.FilterStore = filter.NewMemFilterStore(cfg.Events.MaxFilters)
|
2023-01-13 19:11:13 +00:00
|
|
|
|
|
|
|
// Start garbage collection for filters
|
|
|
|
lc.Append(fx.Hook{
|
|
|
|
OnStart: func(context.Context) error {
|
2023-01-19 22:44:58 +00:00
|
|
|
go ee.GC(ctx, time.Duration(cfg.Events.FilterTTL))
|
2023-01-13 19:11:13 +00:00
|
|
|
return nil
|
|
|
|
},
|
|
|
|
})
|
|
|
|
|
|
|
|
// Enable indexing of actor events
|
|
|
|
var eventIndex *filter.EventIndex
|
2023-01-19 22:44:58 +00:00
|
|
|
if !cfg.Events.DisableHistoricFilterAPI {
|
|
|
|
var dbPath string
|
|
|
|
if cfg.Events.DatabasePath == "" {
|
|
|
|
sqlitePath, err := r.SqlitePath()
|
|
|
|
if err != nil {
|
|
|
|
return nil, err
|
|
|
|
}
|
|
|
|
dbPath = filepath.Join(sqlitePath, "events.db")
|
|
|
|
} else {
|
|
|
|
dbPath = cfg.Events.DatabasePath
|
|
|
|
}
|
|
|
|
|
2023-01-13 19:11:13 +00:00
|
|
|
var err error
|
2023-06-28 16:07:03 +00:00
|
|
|
eventIndex, err = filter.NewEventIndex(ctx, dbPath, chainapi.Chain)
|
2023-01-13 19:11:13 +00:00
|
|
|
if err != nil {
|
|
|
|
return nil, err
|
|
|
|
}
|
|
|
|
|
|
|
|
lc.Append(fx.Hook{
|
|
|
|
OnStop: func(context.Context) error {
|
|
|
|
return eventIndex.Close()
|
|
|
|
},
|
|
|
|
})
|
|
|
|
}
|
|
|
|
|
|
|
|
ee.EventFilterManager = &filter.EventFilterManager{
|
|
|
|
ChainStore: cs,
|
|
|
|
EventIndex: eventIndex, // will be nil unless EnableHistoricFilterAPI is true
|
|
|
|
AddressResolver: func(ctx context.Context, emitter abi.ActorID, ts *types.TipSet) (address.Address, bool) {
|
|
|
|
// we only want to match using f4 addresses
|
|
|
|
idAddr, err := address.NewIDAddress(uint64(emitter))
|
|
|
|
if err != nil {
|
|
|
|
return address.Undef, false
|
|
|
|
}
|
|
|
|
|
|
|
|
actor, err := sm.LoadActor(ctx, idAddr, ts)
|
|
|
|
if err != nil || actor.Address == nil {
|
|
|
|
return address.Undef, false
|
|
|
|
}
|
|
|
|
|
|
|
|
// if robust address is not f4 then we won't match against it so bail early
|
|
|
|
if actor.Address.Protocol() != address.Delegated {
|
|
|
|
return address.Undef, false
|
|
|
|
}
|
|
|
|
// we have an f4 address, make sure it's assigned by the EAM
|
|
|
|
if namespace, _, err := varint.FromUvarint(actor.Address.Payload()); err != nil || namespace != builtintypes.EthereumAddressManagerActorID {
|
|
|
|
return address.Undef, false
|
|
|
|
}
|
|
|
|
return *actor.Address, true
|
|
|
|
},
|
|
|
|
|
2023-01-19 22:44:58 +00:00
|
|
|
MaxFilterResults: cfg.Events.MaxFilterResults,
|
2023-01-13 19:11:13 +00:00
|
|
|
}
|
|
|
|
ee.TipSetFilterManager = &filter.TipSetFilterManager{
|
2023-01-19 22:44:58 +00:00
|
|
|
MaxFilterResults: cfg.Events.MaxFilterResults,
|
2023-01-13 19:11:13 +00:00
|
|
|
}
|
|
|
|
ee.MemPoolFilterManager = &filter.MemPoolFilterManager{
|
2023-01-19 22:44:58 +00:00
|
|
|
MaxFilterResults: cfg.Events.MaxFilterResults,
|
2023-01-13 19:11:13 +00:00
|
|
|
}
|
|
|
|
|
|
|
|
const ChainHeadConfidence = 1
|
|
|
|
|
|
|
|
lc.Append(fx.Hook{
|
|
|
|
OnStart: func(context.Context) error {
|
2023-04-20 21:44:16 +00:00
|
|
|
ev, err := events.NewEvents(ctx, &evapi)
|
2023-01-13 19:11:13 +00:00
|
|
|
if err != nil {
|
|
|
|
return err
|
|
|
|
}
|
|
|
|
// ignore returned tipsets
|
|
|
|
_ = ev.Observe(ee.EventFilterManager)
|
|
|
|
_ = ev.Observe(ee.TipSetFilterManager)
|
|
|
|
|
|
|
|
ch, err := mp.Updates(ctx)
|
|
|
|
if err != nil {
|
|
|
|
return err
|
|
|
|
}
|
|
|
|
go ee.MemPoolFilterManager.WaitForMpoolUpdates(ctx, ch)
|
|
|
|
|
|
|
|
return nil
|
|
|
|
},
|
|
|
|
})
|
|
|
|
|
|
|
|
return ee, nil
|
|
|
|
}
|
|
|
|
}
|