Files
lotus/node/modules/eth.go

248 lines
7.1 KiB
Go

package modules
import (
"context"
"time"
"go.uber.org/fx"
"golang.org/x/xerrors"
"github.com/filecoin-project/go-address"
"github.com/filecoin-project/go-state-types/abi"
"github.com/filecoin-project/lotus/api"
"github.com/filecoin-project/lotus/chain/events"
"github.com/filecoin-project/lotus/chain/events/filter"
"github.com/filecoin-project/lotus/chain/index"
"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/chain/types/ethtypes"
"github.com/filecoin-project/lotus/node/config"
"github.com/filecoin-project/lotus/node/impl/eth"
"github.com/filecoin-project/lotus/node/impl/full"
"github.com/filecoin-project/lotus/node/modules/helpers"
)
type EthTransactionParams struct {
fx.In
MetricsCtx helpers.MetricsCtx
Lifecycle fx.Lifecycle
ChainStore eth.ChainStore
StateManager eth.StateManager
StateAPI eth.StateAPI
MpoolAPI eth.MpoolAPI
EthEventsExtended eth.EthEventsInternal
Indexer index.Indexer
}
func MakeEthTransaction(cfg config.FevmConfig) func(EthTransactionParams) (eth.EthTransactionAPI, error) {
return func(params EthTransactionParams) (eth.EthTransactionAPI, error) {
// Prime the tipset cache with the entire chain to make sure tx and block lookups are fast
params.Lifecycle.Append(fx.Hook{
OnStart: func(context.Context) error {
go func() {
start := time.Now()
log.Infoln("Start prefilling GetTipsetByHeight cache")
_, err := params.ChainStore.GetTipsetByHeight(params.MetricsCtx, abi.ChainEpoch(0), params.ChainStore.GetHeaviestTipSet(), false)
if err != nil {
log.Warnf("error when prefilling GetTipsetByHeight cache: %w", err)
}
log.Infof("Prefilling GetTipsetByHeight done in %s", time.Since(start))
}()
return nil
},
})
return eth.NewEthTransactionAPI(
params.ChainStore,
params.StateManager,
params.StateAPI,
params.MpoolAPI,
params.Indexer,
params.EthEventsExtended,
cfg.EthBlkCacheSize,
)
}
}
func MakeEthTrace(cfg config.FevmConfig) func(
chainStore eth.ChainStore,
stateManager eth.StateManager,
ethTransaction eth.EthTransactionAPI,
) eth.EthTraceAPI {
return func(
chainStore eth.ChainStore,
stateManager eth.StateManager,
ethTransaction eth.EthTransactionAPI,
) eth.EthTraceAPI {
return eth.NewEthTraceAPI(chainStore, stateManager, ethTransaction, cfg.EthTraceFilterMaxResults)
}
}
type EventHelperAPI struct {
fx.In
full.ChainAPI
full.StateAPI
}
var _ events.EventHelperAPI = &EventHelperAPI{}
type EthEventsParams struct {
fx.In
MetricsCtx helpers.MetricsCtx
Lifecycle fx.Lifecycle
EventFilterManager *filter.EventFilterManager
ChainStore *store.ChainStore
StateManager *stmgr.StateManager
EventHelperAPI EventHelperAPI
MessagePool *messagepool.MessagePool
Indexer index.Indexer
}
func MakeEthEventsExtended(cfg config.EventsConfig, enableEthRPC bool) func(EthEventsParams) (eth.EthEventsInternal, error) {
return func(params EthEventsParams) (eth.EthEventsInternal, error) {
lctx := helpers.LifecycleCtx(params.MetricsCtx, params.Lifecycle)
var (
subscribtionCtx context.Context = lctx
chainStore eth.ChainStore = params.ChainStore
stateManager eth.StateManager = params.StateManager
chainIndexer index.Indexer = params.Indexer
eventFilterManager *filter.EventFilterManager
tipSetFilterManager *filter.TipSetFilterManager
memPoolFilterManager *filter.MemPoolFilterManager
filterStore filter.FilterStore
subscriptionManager *eth.EthSubscriptionManager
maxFilterHeightRange abi.ChainEpoch = abi.ChainEpoch(cfg.MaxFilterHeightRange)
)
if !enableEthRPC {
// all event functionality is disabled
// the historic filter API relies on the real time one
return eth.NewEthEventsAPI(
subscribtionCtx,
chainStore,
stateManager,
chainIndexer,
eventFilterManager,
tipSetFilterManager,
memPoolFilterManager,
filterStore,
subscriptionManager,
maxFilterHeightRange,
), nil
}
subscriptionManager = eth.NewEthSubscriptionManager(chainStore, stateManager)
filterStore = filter.NewMemFilterStore(cfg.MaxFilters)
tipSetFilterManager = &filter.TipSetFilterManager{MaxFilterResults: cfg.MaxFilterResults}
memPoolFilterManager = &filter.MemPoolFilterManager{MaxFilterResults: cfg.MaxFilterResults}
eventFilterManager = params.EventFilterManager
ee := eth.NewEthEventsAPI(
subscribtionCtx,
chainStore,
stateManager,
chainIndexer,
eventFilterManager,
tipSetFilterManager,
memPoolFilterManager,
filterStore,
subscriptionManager,
maxFilterHeightRange,
)
params.Lifecycle.Append(fx.Hook{
OnStart: func(context.Context) error {
ev, err := events.NewEvents(lctx, &params.EventHelperAPI)
if err != nil {
return err
}
// ignore returned tipsets
_ = ev.Observe(tipSetFilterManager)
ch, err := params.MessagePool.Updates(lctx)
if err != nil {
return err
}
go memPoolFilterManager.WaitForMpoolUpdates(lctx, ch)
go ee.GC(lctx, time.Duration(cfg.FilterTTL))
return nil
},
})
return ee, nil
}
}
// GatewayEthSend is a helper to provide the Gateway with the EthSendAPI but block the use of
// EthSendRawTransactionUntrusted. The Gateway API doesn't expose this method, so this is a
// precautionary measure.
type GatewayEthSend struct {
fx.In
api.Gateway
}
func (*GatewayEthSend) EthSendRawTransactionUntrusted(ctx context.Context, rawTx ethtypes.EthBytes) (ethtypes.EthHash, error) {
return ethtypes.EthHash{}, xerrors.New("EthSendRawTransactionUntrusted is not supported in gateway mode")
}
type EventFilterManagerParams struct {
fx.In
MetricsCtx helpers.MetricsCtx
Lifecycle fx.Lifecycle
ChainStore *store.ChainStore
StateManager *stmgr.StateManager
EventHelperAPI EventHelperAPI
Indexer index.Indexer
}
func MakeEventFilterManager(cfg config.EventsConfig) func(EventFilterManagerParams) (*filter.EventFilterManager, error) {
return func(params EventFilterManagerParams) (*filter.EventFilterManager, error) {
lctx := helpers.LifecycleCtx(params.MetricsCtx, params.Lifecycle)
// Enable indexing of actor events
fm := &filter.EventFilterManager{
ChainStore: params.ChainStore,
ChainIndexer: params.Indexer,
AddressResolver: func(ctx context.Context, emitter abi.ActorID, ts *types.TipSet) address.Address {
idAddr, err := address.NewIDAddress(uint64(emitter))
if err != nil {
return address.Undef
}
actor, err := params.StateManager.LoadActor(ctx, idAddr, ts)
if err != nil || actor.DelegatedAddress == nil {
return idAddr
}
return *actor.DelegatedAddress
},
MaxFilterResults: cfg.MaxFilterResults,
}
params.Lifecycle.Append(fx.Hook{
OnStart: func(context.Context) error {
ev, err := events.NewEvents(lctx, &params.EventHelperAPI)
if err != nil {
return err
}
_ = ev.Observe(fm)
return nil
},
})
return fm, nil
}
}