Skip to content

Commit 34bda5e

Browse files
committed
core, eth, les, rpc: polish catalyst errors, add context
1 parent 4a4d531 commit 34bda5e

File tree

4 files changed

+47
-26
lines changed

4 files changed

+47
-26
lines changed

core/beacon/errors.go

+37-4
Original file line numberDiff line numberDiff line change
@@ -21,6 +21,39 @@ import (
2121
"github.com/ethereum/go-ethereum/rpc"
2222
)
2323

24+
// EngineAPIError is a standardized error message between consensus and execution
25+
// clients, also containing any custom error message Geth might include.
26+
type EngineAPIError struct {
27+
code int
28+
msg string
29+
err error
30+
}
31+
32+
func (e *EngineAPIError) ErrorCode() int { return e.code }
33+
func (e *EngineAPIError) Error() string { return e.msg }
34+
func (e *EngineAPIError) ErrorData() interface{} {
35+
if e.err == nil {
36+
return nil
37+
}
38+
return struct {
39+
Error string `json:"err"`
40+
}{e.err.Error()}
41+
}
42+
43+
// With returns a copy of the error with a new embedded custom data field.
44+
func (e *EngineAPIError) With(err error) *EngineAPIError {
45+
return &EngineAPIError{
46+
code: e.code,
47+
msg: e.msg,
48+
err: err,
49+
}
50+
}
51+
52+
var (
53+
_ rpc.Error = new(EngineAPIError)
54+
_ rpc.DataError = new(EngineAPIError)
55+
)
56+
2457
var (
2558
// VALID is returned by the engine API in the following calls:
2659
// - newPayloadV1: if the payload was already known or was just validated and executed
@@ -43,10 +76,10 @@ var (
4376

4477
INVALIDBLOCKHASH = "INVALID_BLOCK_HASH"
4578

46-
GenericServerError = rpc.CustomError{Code: -32000, ValidationError: "Server error"}
47-
UnknownPayload = rpc.CustomError{Code: -38001, ValidationError: "Unknown payload"}
48-
InvalidForkChoiceState = rpc.CustomError{Code: -38002, ValidationError: "Invalid forkchoice state"}
49-
InvalidPayloadAttributes = rpc.CustomError{Code: -38003, ValidationError: "Invalid payload attributes"}
79+
GenericServerError = &EngineAPIError{code: -32000, msg: "Server error"}
80+
UnknownPayload = &EngineAPIError{code: -38001, msg: "Unknown payload"}
81+
InvalidForkChoiceState = &EngineAPIError{code: -38002, msg: "Invalid forkchoice state"}
82+
InvalidPayloadAttributes = &EngineAPIError{code: -38003, msg: "Invalid payload attributes"}
5083

5184
STATUS_INVALID = ForkChoiceResponse{PayloadStatus: PayloadStatusV1{Status: INVALID}, PayloadID: nil}
5285
STATUS_SYNCING = ForkChoiceResponse{PayloadStatus: PayloadStatusV1{Status: SYNCING}, PayloadID: nil}

eth/catalyst/api.go

+7-9
Original file line numberDiff line numberDiff line change
@@ -166,10 +166,10 @@ func (api *ConsensusAPI) ForkchoiceUpdatedV1(update beacon.ForkchoiceStateV1, pa
166166
finalBlock := api.eth.BlockChain().GetBlockByHash(update.FinalizedBlockHash)
167167
if finalBlock == nil {
168168
log.Warn("Final block not available in database", "hash", update.FinalizedBlockHash)
169-
return beacon.STATUS_INVALID, &beacon.InvalidForkChoiceState
169+
return beacon.STATUS_INVALID, beacon.InvalidForkChoiceState.With(errors.New("final block not available in database"))
170170
} else if rawdb.ReadCanonicalHash(api.eth.ChainDb(), finalBlock.NumberU64()) != update.FinalizedBlockHash {
171171
log.Warn("Final block not in canonical chain", "number", block.NumberU64(), "hash", update.HeadBlockHash)
172-
return beacon.STATUS_INVALID, &beacon.InvalidForkChoiceState
172+
return beacon.STATUS_INVALID, beacon.InvalidForkChoiceState.With(errors.New("final block not in canonical chain"))
173173
}
174174
// Set the finalized block
175175
api.eth.BlockChain().SetFinalized(finalBlock)
@@ -179,21 +179,19 @@ func (api *ConsensusAPI) ForkchoiceUpdatedV1(update beacon.ForkchoiceStateV1, pa
179179
safeBlock := api.eth.BlockChain().GetBlockByHash(update.SafeBlockHash)
180180
if safeBlock == nil {
181181
log.Warn("Safe block not available in database")
182-
return beacon.STATUS_INVALID, &beacon.InvalidForkChoiceState
182+
return beacon.STATUS_INVALID, beacon.InvalidForkChoiceState.With(errors.New("safe block not available in database"))
183183
}
184184
if rawdb.ReadCanonicalHash(api.eth.ChainDb(), safeBlock.NumberU64()) != update.SafeBlockHash {
185185
log.Warn("Safe block not in canonical chain")
186-
return beacon.STATUS_INVALID, &beacon.InvalidForkChoiceState
186+
return beacon.STATUS_INVALID, beacon.InvalidForkChoiceState.With(errors.New("safe block not in canonical chain"))
187187
}
188188
}
189-
190189
valid := func(id *beacon.PayloadID) beacon.ForkChoiceResponse {
191190
return beacon.ForkChoiceResponse{
192191
PayloadStatus: beacon.PayloadStatusV1{Status: beacon.VALID, LatestValidHash: &update.HeadBlockHash},
193192
PayloadID: id,
194193
}
195194
}
196-
197195
// If payload generation was requested, create a new block to be potentially
198196
// sealed by the beacon client. The payload will be requested later, and we
199197
// might replace it arbitrarily many times in between.
@@ -202,14 +200,14 @@ func (api *ConsensusAPI) ForkchoiceUpdatedV1(update beacon.ForkchoiceStateV1, pa
202200
empty, err := api.eth.Miner().GetSealingBlockSync(update.HeadBlockHash, payloadAttributes.Timestamp, payloadAttributes.SuggestedFeeRecipient, payloadAttributes.Random, true)
203201
if err != nil {
204202
log.Error("Failed to create empty sealing payload", "err", err)
205-
return valid(nil), &beacon.InvalidPayloadAttributes
203+
return valid(nil), beacon.InvalidPayloadAttributes.With(err)
206204
}
207205
// Send a request to generate a full block in the background.
208206
// The result can be obtained via the returned channel.
209207
resCh, err := api.eth.Miner().GetSealingBlockAsync(update.HeadBlockHash, payloadAttributes.Timestamp, payloadAttributes.SuggestedFeeRecipient, payloadAttributes.Random, false)
210208
if err != nil {
211209
log.Error("Failed to create async sealing payload", "err", err)
212-
return valid(nil), &beacon.InvalidPayloadAttributes
210+
return valid(nil), beacon.InvalidPayloadAttributes.With(err)
213211
}
214212
id := computePayloadId(update.HeadBlockHash, payloadAttributes)
215213
api.localBlocks.put(id, &payload{empty: empty, result: resCh})
@@ -248,7 +246,7 @@ func (api *ConsensusAPI) GetPayloadV1(payloadID beacon.PayloadID) (*beacon.Execu
248246
log.Trace("Engine API request received", "method", "GetPayload", "id", payloadID)
249247
data := api.localBlocks.get(payloadID)
250248
if data == nil {
251-
return nil, &beacon.UnknownPayload
249+
return nil, beacon.UnknownPayload
252250
}
253251
return data, nil
254252
}

les/catalyst/api.go

+3-3
Original file line numberDiff line numberDiff line change
@@ -98,7 +98,7 @@ func (api *ConsensusAPI) ForkchoiceUpdatedV1(heads beacon.ForkchoiceStateV1, pay
9898

9999
// GetPayloadV1 returns a cached payload by id. It's not supported in les mode.
100100
func (api *ConsensusAPI) GetPayloadV1(payloadID beacon.PayloadID) (*beacon.ExecutableDataV1, error) {
101-
return nil, &beacon.GenericServerError
101+
return nil, beacon.GenericServerError.With(errors.New("not supported in light client mode"))
102102
}
103103

104104
// ExecutePayloadV1 creates an Eth1 block, inserts it in the chain, and returns the status of the chain.
@@ -157,7 +157,7 @@ func (api *ConsensusAPI) checkTerminalTotalDifficulty(head common.Hash) error {
157157
// make sure the parent has enough terminal total difficulty
158158
header := api.les.BlockChain().GetHeaderByHash(head)
159159
if header == nil {
160-
return &beacon.GenericServerError
160+
return errors.New("unknown header")
161161
}
162162
td := api.les.BlockChain().GetTd(header.Hash(), header.Number.Uint64())
163163
if td != nil && td.Cmp(api.les.BlockChain().Config().TerminalTotalDifficulty) < 0 {
@@ -176,7 +176,7 @@ func (api *ConsensusAPI) setCanonical(newHead common.Hash) error {
176176
}
177177
newHeadHeader := api.les.BlockChain().GetHeaderByHash(newHead)
178178
if newHeadHeader == nil {
179-
return &beacon.GenericServerError
179+
return errors.New("unknown header")
180180
}
181181
if err := api.les.BlockChain().SetCanonical(newHeadHeader); err != nil {
182182
return err

rpc/errors.go

-10
Original file line numberDiff line numberDiff line change
@@ -54,7 +54,6 @@ var (
5454
_ Error = new(invalidRequestError)
5555
_ Error = new(invalidMessageError)
5656
_ Error = new(invalidParamsError)
57-
_ Error = new(CustomError)
5857
)
5958

6059
const defaultErrorCode = -32000
@@ -102,12 +101,3 @@ type invalidParamsError struct{ message string }
102101
func (e *invalidParamsError) ErrorCode() int { return -32602 }
103102

104103
func (e *invalidParamsError) Error() string { return e.message }
105-
106-
type CustomError struct {
107-
Code int
108-
ValidationError string
109-
}
110-
111-
func (e *CustomError) ErrorCode() int { return e.Code }
112-
113-
func (e *CustomError) Error() string { return e.ValidationError }

0 commit comments

Comments
 (0)