feat: eth: optimize receipt reading

This optimizes the eth APIs (except the fee history one) to lookup the
tipset state/receipts instead of computing the state.
This commit is contained in:
Steven Allen 2023-03-10 15:33:45 -08:00
parent 92bca485b6
commit 1cf57ffe2d
2 changed files with 49 additions and 17 deletions

View File

@ -237,6 +237,26 @@ func (cs *ChainStore) ReadMsgMetaCids(ctx context.Context, mmc cid.Cid) ([]cid.C
return blscids, secpkcids, nil return blscids, secpkcids, nil
} }
func (cs *ChainStore) ReadReceipts(ctx context.Context, root cid.Cid) ([]types.MessageReceipt, error) {
a, err := blockadt.AsArray(cs.ActorStore(ctx), root)
if err != nil {
return nil, err
}
receipts := make([]types.MessageReceipt, 0, a.Length())
var rcpt types.MessageReceipt
if err := a.ForEach(&rcpt, func(i int64) error {
if int64(len(receipts)) != i {
return xerrors.Errorf("missing receipt %d", i)
}
receipts = append(receipts, rcpt)
return nil
}); err != nil {
return nil, err
}
return receipts, nil
}
func (cs *ChainStore) MessagesForBlock(ctx context.Context, b *types.BlockHeader) ([]*types.Message, []*types.SignedMessage, error) { func (cs *ChainStore) MessagesForBlock(ctx context.Context, b *types.BlockHeader) ([]*types.Message, []*types.SignedMessage, error) {
blscids, secpkcids, err := cs.ReadMsgMetaCids(ctx, b.Messages) blscids, secpkcids, err := cs.ReadMsgMetaCids(ctx, b.Messages)
if err != nil { if err != nil {

View File

@ -1797,30 +1797,42 @@ func newEthBlockFromFilecoinTipSet(ctx context.Context, ts *types.TipSet, fullTx
return ethtypes.EthBlock{}, xerrors.Errorf("error loading messages for tipset: %v: %w", ts, err) return ethtypes.EthBlock{}, xerrors.Errorf("error loading messages for tipset: %v: %w", ts, err)
} }
block := ethtypes.NewEthBlock(len(msgs) > 0) _, rcptRoot, err := sa.StateManager.TipSetState(ctx, ts)
gasUsed := int64(0)
compOutput, err := sa.StateCompute(ctx, ts.Height(), nil, ts.Key())
if err != nil { if err != nil {
return ethtypes.EthBlock{}, xerrors.Errorf("failed to compute state: %w", err) return ethtypes.EthBlock{}, xerrors.Errorf("failed to compute state: %w", err)
} }
txIdx := 0 rcpts, err := cs.ReadReceipts(ctx, rcptRoot)
for _, msg := range compOutput.Trace { if err != nil {
// skip system messages like reward application and cron return ethtypes.EthBlock{}, xerrors.Errorf("error loading receipts for tipset: %v: %w", ts, err)
if msg.Msg.From == builtintypes.SystemActorAddr { }
continue
}
ti := ethtypes.EthUint64(txIdx) if len(msgs) != len(rcpts) {
txIdx++ return ethtypes.EthBlock{}, xerrors.Errorf("receipts and message array lengths didn't match for tipset: %v: %w", ts, err)
}
gasUsed += msg.MsgRct.GasUsed block := ethtypes.NewEthBlock(len(msgs) > 0)
smsgCid, err := getSignedMessage(ctx, cs, msg.MsgCid)
if err != nil { gasUsed := int64(0)
return ethtypes.EthBlock{}, xerrors.Errorf("failed to get signed msg %s: %w", msg.MsgCid, err) for i, msg := range msgs {
rcpt := rcpts[i]
ti := ethtypes.EthUint64(i)
gasUsed += rcpt.GasUsed
var smsg *types.SignedMessage
switch msg := msg.(type) {
case *types.SignedMessage:
smsg = msg
case *types.Message:
smsg = &types.SignedMessage{
Message: *msg,
Signature: crypto.Signature{
Type: crypto.SigTypeBLS,
},
}
default:
return ethtypes.EthBlock{}, xerrors.Errorf("failed to get signed msg %s: %w", msg.Cid(), err)
} }
tx, err := newEthTxFromSignedMessage(ctx, smsgCid, sa) tx, err := newEthTxFromSignedMessage(ctx, smsg, sa)
if err != nil { if err != nil {
return ethtypes.EthBlock{}, xerrors.Errorf("failed to convert msg to ethTx: %w", err) return ethtypes.EthBlock{}, xerrors.Errorf("failed to convert msg to ethTx: %w", err)
} }