Skip to content

Commit

Permalink
fix: eth: re-execute tipsets on missing events (filecoin-project#11588)
Browse files Browse the repository at this point in the history
This will re-execute tipsets to forcibly re-compute and store events
when they're missing. This is effectively lazy backfilling of events.

NOTE: This _won't_ backfill the index itself, it'll just give us the
events.

fixes filecoin-project#11335
  • Loading branch information
Stebalien authored and ribasushi committed May 16, 2024
1 parent 11fd750 commit e048aae
Show file tree
Hide file tree
Showing 3 changed files with 36 additions and 14 deletions.
16 changes: 14 additions & 2 deletions chain/stmgr/execute.go
Original file line number Diff line number Diff line change
Expand Up @@ -13,6 +13,16 @@ import (
)

func (sm *StateManager) TipSetState(ctx context.Context, ts *types.TipSet) (st cid.Cid, rec cid.Cid, err error) {
return sm.tipSetState(ctx, ts, false)
}

// Recompute the tipset state without trying to lookup a pre-computed result in the chainstore.
// Useful if we know that our local chain-state isn't complete (e.g., we've discarded the events).
func (sm *StateManager) RecomputeTipSetState(ctx context.Context, ts *types.TipSet) (st cid.Cid, rec cid.Cid, err error) {
return sm.tipSetState(ctx, ts, true)
}

func (sm *StateManager) tipSetState(ctx context.Context, ts *types.TipSet, recompute bool) (st cid.Cid, rec cid.Cid, err error) {
ctx, span := trace.StartSpan(ctx, "tipSetState")
defer span.End()
if span.IsRecordingEvents() {
Expand Down Expand Up @@ -65,8 +75,10 @@ func (sm *StateManager) TipSetState(ctx context.Context, ts *types.TipSet) (st c

// First, try to find the tipset in the current chain. If found, we can avoid re-executing
// it.
if st, rec, found := tryLookupTipsetState(ctx, sm.cs, ts); found {
return st, rec, nil
if !recompute {
if st, rec, found := tryLookupTipsetState(ctx, sm.cs, ts); found {
return st, rec, nil
}
}

st, rec, err = sm.tsExec.ExecuteTipSet(ctx, sm, ts, sm.tsExecMonitor, false)
Expand Down
10 changes: 1 addition & 9 deletions node/impl/full/eth.go
Original file line number Diff line number Diff line change
Expand Up @@ -424,15 +424,7 @@ func (a *EthModule) EthGetTransactionReceiptLimited(ctx context.Context, txHash
return nil, xerrors.Errorf("failed to convert %s into an Eth Txn: %w", txHash, err)
}

var events []types.Event
if rct := msgLookup.Receipt; rct.EventsRoot != nil {
events, err = a.ChainAPI.ChainGetEvents(ctx, *rct.EventsRoot)
if err != nil {
return nil, xerrors.Errorf("failed get events for %s", txHash)
}
}

receipt, err := newEthTxReceipt(ctx, tx, msgLookup, events, a.Chain, a.StateAPI)
receipt, err := newEthTxReceipt(ctx, tx, msgLookup, a.ChainAPI, a.StateAPI)
if err != nil {
return nil, xerrors.Errorf("failed to convert %s into an Eth Receipt: %w", txHash, err)
}
Expand Down
24 changes: 21 additions & 3 deletions node/impl/full/eth_utils.go
Original file line number Diff line number Diff line change
Expand Up @@ -659,7 +659,7 @@ func newEthTxFromMessageLookup(ctx context.Context, msgLookup *api.MsgLookup, tx
return tx, nil
}

func newEthTxReceipt(ctx context.Context, tx ethtypes.EthTx, lookup *api.MsgLookup, events []types.Event, cs *store.ChainStore, sa StateAPI) (api.EthTxReceipt, error) {
func newEthTxReceipt(ctx context.Context, tx ethtypes.EthTx, lookup *api.MsgLookup, ca ChainAPI, sa StateAPI) (api.EthTxReceipt, error) {
var (
transactionIndex ethtypes.EthUint64
blockHash ethtypes.EthHash
Expand Down Expand Up @@ -700,7 +700,7 @@ func newEthTxReceipt(ctx context.Context, tx ethtypes.EthTx, lookup *api.MsgLook
receipt.CumulativeGasUsed = ethtypes.EmptyEthInt

// TODO: avoid loading the tipset twice (once here, once when we convert the message to a txn)
ts, err := cs.GetTipSetFromKey(ctx, lookup.TipSet)
ts, err := ca.Chain.GetTipSetFromKey(ctx, lookup.TipSet)
if err != nil {
return api.EthTxReceipt{}, xerrors.Errorf("failed to lookup tipset %s when constructing the eth txn receipt: %w", lookup.TipSet, err)
}
Expand All @@ -711,7 +711,7 @@ func newEthTxReceipt(ctx context.Context, tx ethtypes.EthTx, lookup *api.MsgLook
}

// The tx is located in the parent tipset
parentTs, err := cs.LoadTipSet(ctx, ts.Parents())
parentTs, err := ca.Chain.LoadTipSet(ctx, ts.Parents())
if err != nil {
return api.EthTxReceipt{}, xerrors.Errorf("failed to lookup tipset %s when constructing the eth txn receipt: %w", ts.Parents(), err)
}
Expand All @@ -736,6 +736,24 @@ func newEthTxReceipt(ctx context.Context, tx ethtypes.EthTx, lookup *api.MsgLook
receipt.ContractAddress = &addr
}

var events []types.Event
if rct := lookup.Receipt; rct.EventsRoot != nil {
events, err = ca.ChainGetEvents(ctx, *rct.EventsRoot)
if err != nil {
// Fore-recompute, we must have enabled the Event APIs after computing this
// tipset.
if _, _, err := sa.StateManager.RecomputeTipSetState(ctx, ts); err != nil {

return api.EthTxReceipt{}, xerrors.Errorf("failed get events: %w", err)
}
// Try again
events, err = ca.ChainGetEvents(ctx, *rct.EventsRoot)
if err != nil {
return api.EthTxReceipt{}, xerrors.Errorf("failed get events: %w", err)
}
}
}

if len(events) > 0 {
receipt.Logs = make([]ethtypes.EthLog, 0, len(events))
for i, evt := range events {
Expand Down

0 comments on commit e048aae

Please sign in to comment.