fix: eth: re-execute tipsets on missing events (#11588)
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 #11335
This commit is contained in:
parent
4d73febaf7
commit
efb9422c01
@ -13,6 +13,16 @@ import (
|
|||||||
)
|
)
|
||||||
|
|
||||||
func (sm *StateManager) TipSetState(ctx context.Context, ts *types.TipSet) (st cid.Cid, rec cid.Cid, err error) {
|
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")
|
ctx, span := trace.StartSpan(ctx, "tipSetState")
|
||||||
defer span.End()
|
defer span.End()
|
||||||
if span.IsRecordingEvents() {
|
if span.IsRecordingEvents() {
|
||||||
@ -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
|
// First, try to find the tipset in the current chain. If found, we can avoid re-executing
|
||||||
// it.
|
// it.
|
||||||
if st, rec, found := tryLookupTipsetState(ctx, sm.cs, ts); found {
|
if !recompute {
|
||||||
return st, rec, nil
|
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)
|
st, rec, err = sm.tsExec.ExecuteTipSet(ctx, sm, ts, sm.tsExecMonitor, false)
|
||||||
|
@ -422,15 +422,7 @@ func (a *EthModule) EthGetTransactionReceiptLimited(ctx context.Context, txHash
|
|||||||
return nil, xerrors.Errorf("failed to convert %s into an Eth Txn: %w", txHash, err)
|
return nil, xerrors.Errorf("failed to convert %s into an Eth Txn: %w", txHash, err)
|
||||||
}
|
}
|
||||||
|
|
||||||
var events []types.Event
|
receipt, err := newEthTxReceipt(ctx, tx, msgLookup, a.ChainAPI, a.StateAPI)
|
||||||
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)
|
|
||||||
if err != nil {
|
if err != nil {
|
||||||
return nil, xerrors.Errorf("failed to convert %s into an Eth Receipt: %w", txHash, err)
|
return nil, xerrors.Errorf("failed to convert %s into an Eth Receipt: %w", txHash, err)
|
||||||
}
|
}
|
||||||
|
@ -654,7 +654,7 @@ func newEthTxFromMessageLookup(ctx context.Context, msgLookup *api.MsgLookup, tx
|
|||||||
return tx, nil
|
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 (
|
var (
|
||||||
transactionIndex ethtypes.EthUint64
|
transactionIndex ethtypes.EthUint64
|
||||||
blockHash ethtypes.EthHash
|
blockHash ethtypes.EthHash
|
||||||
@ -695,7 +695,7 @@ func newEthTxReceipt(ctx context.Context, tx ethtypes.EthTx, lookup *api.MsgLook
|
|||||||
receipt.CumulativeGasUsed = ethtypes.EmptyEthInt
|
receipt.CumulativeGasUsed = ethtypes.EmptyEthInt
|
||||||
|
|
||||||
// TODO: avoid loading the tipset twice (once here, once when we convert the message to a txn)
|
// 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 {
|
if err != nil {
|
||||||
return api.EthTxReceipt{}, xerrors.Errorf("failed to lookup tipset %s when constructing the eth txn receipt: %w", lookup.TipSet, err)
|
return api.EthTxReceipt{}, xerrors.Errorf("failed to lookup tipset %s when constructing the eth txn receipt: %w", lookup.TipSet, err)
|
||||||
}
|
}
|
||||||
@ -706,7 +706,7 @@ func newEthTxReceipt(ctx context.Context, tx ethtypes.EthTx, lookup *api.MsgLook
|
|||||||
}
|
}
|
||||||
|
|
||||||
// The tx is located in the parent tipset
|
// 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 {
|
if err != nil {
|
||||||
return api.EthTxReceipt{}, xerrors.Errorf("failed to lookup tipset %s when constructing the eth txn receipt: %w", ts.Parents(), err)
|
return api.EthTxReceipt{}, xerrors.Errorf("failed to lookup tipset %s when constructing the eth txn receipt: %w", ts.Parents(), err)
|
||||||
}
|
}
|
||||||
@ -731,6 +731,24 @@ func newEthTxReceipt(ctx context.Context, tx ethtypes.EthTx, lookup *api.MsgLook
|
|||||||
receipt.ContractAddress = &addr
|
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 {
|
if len(events) > 0 {
|
||||||
receipt.Logs = make([]ethtypes.EthLog, 0, len(events))
|
receipt.Logs = make([]ethtypes.EthLog, 0, len(events))
|
||||||
for i, evt := range events {
|
for i, evt := range events {
|
||||||
|
Loading…
Reference in New Issue
Block a user