-
Notifications
You must be signed in to change notification settings - Fork 56
New issue
Have a question about this project? Sign up for a free GitHub account to open an issue and contact its maintainers and the community.
By clicking “Sign up for GitHub”, you agree to our terms of service and privacy statement. We’ll occasionally send you account related emails.
Already on GitHub? Sign in to your account
fix(octane/evmengine): handle engine errors #2469
Changes from all commits
File filter
Filter by extension
Conversations
Jump to
Diff view
Diff view
There are no files selected for viewing
Original file line number | Diff line number | Diff line change |
---|---|---|
|
@@ -6,6 +6,7 @@ import ( | |
"time" | ||
|
||
"github.com/omni-network/omni/lib/errors" | ||
"github.com/omni-network/omni/lib/log" | ||
|
||
"github.com/ethereum/go-ethereum/beacon/engine" | ||
"github.com/ethereum/go-ethereum/common" | ||
|
@@ -30,25 +31,14 @@ const ( | |
type EngineClient interface { | ||
Client | ||
|
||
// NewPayloadV2 creates an Eth1 block, inserts it in the chain, and returns the status of the chain. | ||
NewPayloadV2(ctx context.Context, params engine.ExecutableData) (engine.PayloadStatusV1, error) | ||
// NewPayloadV3 creates an Eth1 block, inserts it in the chain, and returns the status of the chain. | ||
NewPayloadV3(ctx context.Context, params engine.ExecutableData, versionedHashes []common.Hash, | ||
beaconRoot *common.Hash) (engine.PayloadStatusV1, error) | ||
|
||
// ForkchoiceUpdatedV2 has several responsibilities: | ||
// - It sets the chain the head. | ||
// - And/or it sets the chain's finalized block hash. | ||
// - And/or it starts assembling (async) a block with the payload attributes. | ||
ForkchoiceUpdatedV2(ctx context.Context, update engine.ForkchoiceStateV1, | ||
payloadAttributes *engine.PayloadAttributes) (engine.ForkChoiceResponse, error) | ||
|
||
// ForkchoiceUpdatedV3 is equivalent to V2 with the addition of parent beacon block root in the payload attributes. | ||
ForkchoiceUpdatedV3(ctx context.Context, update engine.ForkchoiceStateV1, | ||
payloadAttributes *engine.PayloadAttributes) (engine.ForkChoiceResponse, error) | ||
|
||
// GetPayloadV2 returns a cached payload by id. | ||
GetPayloadV2(ctx context.Context, payloadID engine.PayloadID) (*engine.ExecutionPayloadEnvelope, error) | ||
// GetPayloadV3 returns a cached payload by id. | ||
GetPayloadV3(ctx context.Context, payloadID engine.PayloadID) (*engine.ExecutionPayloadEnvelope, error) | ||
} | ||
|
@@ -77,50 +67,39 @@ func NewAuthClient(ctx context.Context, urlAddr string, jwtSecret []byte) (Engin | |
}, nil | ||
} | ||
|
||
func (c engineClient) NewPayloadV2(ctx context.Context, params engine.ExecutableData) (engine.PayloadStatusV1, error) { | ||
const endpoint = "new_payload_v2" | ||
defer latency(c.chain, endpoint)() | ||
|
||
var resp engine.PayloadStatusV1 | ||
err := c.cl.Client().CallContext(ctx, &resp, newPayloadV2, params) | ||
if err != nil { | ||
incError(c.chain, endpoint) | ||
return engine.PayloadStatusV1{}, errors.Wrap(err, "rpc new payload v2") | ||
} | ||
|
||
return resp, nil | ||
} | ||
|
||
func (c engineClient) NewPayloadV3(ctx context.Context, params engine.ExecutableData, versionedHashes []common.Hash, | ||
beaconRoot *common.Hash, | ||
) (engine.PayloadStatusV1, error) { | ||
const endpoint = "new_payload_v3" | ||
defer latency(c.chain, endpoint)() | ||
|
||
// isStatusOk returns true if the response status is valid. | ||
isStatusOk := func(status engine.PayloadStatusV1) bool { | ||
return map[string]bool{ | ||
engine.VALID: true, | ||
engine.INVALID: true, | ||
engine.SYNCING: true, | ||
engine.ACCEPTED: true, | ||
}[status.Status] | ||
} | ||
|
||
var resp engine.PayloadStatusV1 | ||
err := c.cl.Client().CallContext(ctx, &resp, newPayloadV3, params, versionedHashes, beaconRoot) | ||
if err != nil { | ||
if isStatusOk(resp) { | ||
// Swallow errors when geth returns errors along with proper responses (but at least log it). | ||
if err != nil { | ||
log.Warn(ctx, "Ignoring new_payload_v3 error with proper response", err, "status", resp.Status) | ||
} | ||
|
||
return resp, nil | ||
} else if err != nil { | ||
incError(c.chain, endpoint) | ||
return engine.PayloadStatusV1{}, errors.Wrap(err, "rpc new payload v3") | ||
} | ||
|
||
return resp, nil | ||
} | ||
|
||
func (c engineClient) ForkchoiceUpdatedV2(ctx context.Context, update engine.ForkchoiceStateV1, | ||
payloadAttributes *engine.PayloadAttributes, | ||
) (engine.ForkChoiceResponse, error) { | ||
const endpoint = "forkchoice_updated_v2" | ||
defer latency(c.chain, endpoint)() | ||
return engine.PayloadStatusV1{}, errors.Wrap(err, "rpc new payload") | ||
} /* else err==nil && status!=ok */ | ||
|
||
var resp engine.ForkChoiceResponse | ||
err := c.cl.Client().CallContext(ctx, &resp, forkchoiceUpdatedV2, update, payloadAttributes) | ||
if err != nil { | ||
incError(c.chain, endpoint) | ||
return engine.ForkChoiceResponse{}, errors.Wrap(err, "rpc forkchoice updated v2") | ||
} | ||
incError(c.chain, endpoint) | ||
|
||
return resp, nil | ||
return engine.PayloadStatusV1{}, errors.New("nil error and unknown status", "status", resp.Status) | ||
There was a problem hiding this comment. Choose a reason for hiding this commentThe reason will be displayed to describe this comment to others. Learn more. should this be a [BUG]? There was a problem hiding this comment. Choose a reason for hiding this commentThe reason will be displayed to describe this comment to others. Learn more. possibly yeah |
||
} | ||
|
||
func (c engineClient) ForkchoiceUpdatedV3(ctx context.Context, update engine.ForkchoiceStateV1, | ||
|
@@ -129,30 +108,33 @@ func (c engineClient) ForkchoiceUpdatedV3(ctx context.Context, update engine.For | |
const endpoint = "forkchoice_updated_v3" | ||
defer latency(c.chain, endpoint)() | ||
|
||
// isStatusOk returns true if the response status is valid. | ||
isStatusOk := func(resp engine.ForkChoiceResponse) bool { | ||
There was a problem hiding this comment. Choose a reason for hiding this commentThe reason will be displayed to describe this comment to others. Learn more. I'm curious about this code style: why do you prefer wrapping a map with a closure over simply using a map given it's used once in the function? There was a problem hiding this comment. Choose a reason for hiding this commentThe reason will be displayed to describe this comment to others. Learn more. functions are easy to read and document. Also slightly more concise
|
||
return map[string]bool{ | ||
engine.VALID: true, | ||
engine.INVALID: true, | ||
engine.SYNCING: true, | ||
engine.ACCEPTED: false, // Unexpected in ForkchoiceUpdated | ||
}[resp.PayloadStatus.Status] | ||
} | ||
|
||
var resp engine.ForkChoiceResponse | ||
err := c.cl.Client().CallContext(ctx, &resp, forkchoiceUpdatedV3, update, payloadAttributes) | ||
if err != nil { | ||
if isStatusOk(resp) { | ||
// Swallow errors when geth returns errors along with proper responses (but at least log it). | ||
if err != nil { | ||
log.Warn(ctx, "Ignoring forkchoice_updated_v3 error with proper response", err, "status", resp.PayloadStatus.Status) | ||
} | ||
|
||
return resp, nil | ||
} else if err != nil { | ||
incError(c.chain, endpoint) | ||
return engine.ForkChoiceResponse{}, errors.Wrap(err, "rpc forkchoice updated v3") | ||
} | ||
|
||
return resp, nil | ||
} | ||
|
||
func (c engineClient) GetPayloadV2(ctx context.Context, payloadID engine.PayloadID) ( | ||
*engine.ExecutionPayloadEnvelope, error, | ||
) { | ||
const endpoint = "get_payload_v2" | ||
defer latency(c.chain, endpoint)() | ||
} /* else err==nil && status!=ok */ | ||
|
||
var resp engine.ExecutionPayloadEnvelope | ||
err := c.cl.Client().CallContext(ctx, &resp, getPayloadV2, payloadID) | ||
if err != nil { | ||
incError(c.chain, endpoint) | ||
return nil, errors.Wrap(err, "rpc get payload v2") | ||
} | ||
incError(c.chain, endpoint) | ||
|
||
return &resp, nil | ||
return engine.ForkChoiceResponse{}, errors.New("nil error and unknown status", "status", resp.PayloadStatus.Status) | ||
} | ||
|
||
func (c engineClient) GetPayloadV3(ctx context.Context, payloadID engine.PayloadID) ( | ||
|
There was a problem hiding this comment.
Choose a reason for hiding this comment
The reason will be displayed to describe this comment to others. Learn more.
good idea