-
Notifications
You must be signed in to change notification settings - Fork 1
handle error #59
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
handle error #59
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 | ||||
---|---|---|---|---|---|---|
|
@@ -132,7 +132,11 @@ func (e *EspressoReader) Run(ctx context.Context, ready chan<- struct{}) error { | |||||
slog.Debug("Espresso:", "app", appAddress, "currentBlockHeight", currentEspressoBlockHeight) | ||||||
|
||||||
var l1FinalizedTimestamp uint64 | ||||||
lastProcessedL1Block, l1FinalizedTimestamp = e.readL1(ctx, app, currentEspressoBlockHeight, lastProcessedL1Block) | ||||||
lastProcessedL1Block, l1FinalizedTimestamp, err = e.readL1(ctx, app, currentEspressoBlockHeight, lastProcessedL1Block) | ||||||
if err != nil { | ||||||
slog.Error("failed reading L1", "error", err) | ||||||
break | ||||||
} | ||||||
e.readEspresso(ctx, app, currentEspressoBlockHeight, namespace, lastProcessedL1Block, l1FinalizedTimestamp) | ||||||
} | ||||||
} | ||||||
|
@@ -172,14 +176,19 @@ func (e *EspressoReader) bootstrap(ctx context.Context, app evmreader.TypeExport | |||||
err = json.Unmarshal(nsTableBytes, &nsTables) | ||||||
if err != nil { | ||||||
slog.Error("failed fetching ns tables", "error", err, "ns table", nsTables) | ||||||
return err | ||||||
} else { | ||||||
for index, nsTable := range nsTables { | ||||||
nsTableBytes, _ := base64.StdEncoding.DecodeString(nsTable) | ||||||
ns := e.espressoHelper.extractNS(nsTableBytes) | ||||||
currentEspressoBlock := batchStartingBlock + uint64(index) | ||||||
if slices.Contains(ns, uint32(namespace)) { | ||||||
slog.Debug("found namespace contained in", "block", currentEspressoBlock) | ||||||
l1FinalizedHeight, l1FinalizedTimestamp = e.readL1(ctx, app, currentEspressoBlock, l1FinalizedHeight) | ||||||
l1FinalizedHeight, l1FinalizedTimestamp, err = e.readL1(ctx, app, currentEspressoBlock, l1FinalizedHeight) | ||||||
if err != nil { | ||||||
slog.Error("failed reading L1", "error", err) | ||||||
return err | ||||||
} | ||||||
e.readEspresso(ctx, app, currentEspressoBlock, namespace, l1FinalizedHeight, l1FinalizedTimestamp) | ||||||
} else { | ||||||
err = e.repository.UpdateLastProcessedEspressoBlock(ctx, app.IApplicationAddress, currentEspressoBlock) | ||||||
|
@@ -197,7 +206,7 @@ func (e *EspressoReader) bootstrap(ctx context.Context, app evmreader.TypeExport | |||||
return nil | ||||||
} | ||||||
|
||||||
func (e *EspressoReader) readL1(ctx context.Context, app evmreader.TypeExportApplication, currentBlockHeight uint64, lastProcessedL1Block uint64) (uint64, uint64) { | ||||||
func (e *EspressoReader) readL1(ctx context.Context, app evmreader.TypeExportApplication, currentBlockHeight uint64, lastProcessedL1Block uint64) (uint64, uint64, error) { | ||||||
l1FinalizedLatestHeight, l1FinalizedTimestamp := e.espressoHelper.getL1FinalizedHeight(ctx, currentBlockHeight, e.maxDelay, e.url) | ||||||
// read L1 if there might be update | ||||||
if l1FinalizedLatestHeight > lastProcessedL1Block { | ||||||
|
@@ -207,12 +216,16 @@ func (e *EspressoReader) readL1(ctx context.Context, app evmreader.TypeExportApp | |||||
apps = append(apps, app) // make app into 1-element array | ||||||
|
||||||
// start reading from the block after the prev height | ||||||
e.evmReader.ReadAndStoreInputs(ctx, lastProcessedL1Block, l1FinalizedLatestHeight, apps) | ||||||
err := e.evmReader.ReadAndStoreInputs(ctx, lastProcessedL1Block, l1FinalizedLatestHeight, apps) | ||||||
if err != nil { | ||||||
slog.Error("failed to read and store L1 inputs", "error", err) | ||||||
return 0, 0, err | ||||||
} | ||||||
// check for claim status and output execution | ||||||
// e.evmReader.CheckForClaimStatus(ctx, apps, l1FinalizedLatestHeight) // checked by the node | ||||||
// e.evmReader.CheckForOutputExecution(ctx, apps, l1FinalizedLatestHeight) // checked by the node | ||||||
} | ||||||
return l1FinalizedLatestHeight, l1FinalizedTimestamp | ||||||
return l1FinalizedLatestHeight, l1FinalizedTimestamp, nil | ||||||
} | ||||||
|
||||||
type EspressoInput struct { | ||||||
|
@@ -441,7 +454,7 @@ func (e *EspressoReader) readEspresso(ctx context.Context, appEvmType evmreader. | |||||
) | ||||||
if err != nil { | ||||||
slog.Error("could not store Espresso input", "err", err) | ||||||
continue | ||||||
return | ||||||
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. Returning here exits the entire readEspresso loop instead of skipping the failed log; consider using
Suggested change
Copilot uses AI. Check for mistakes. Positive FeedbackNegative Feedback 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. no. The loop should be exited 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.
In Go, it's common practice to return the error to the caller rather than relying on |
||||||
} | ||||||
|
||||||
// update nonce | ||||||
|
Original file line number | Diff line number | Diff line change | ||||||
---|---|---|---|---|---|---|---|---|
|
@@ -107,18 +107,24 @@ func (s *EspressoReaderService) requestNonce(w http.ResponseWriter, r *http.Requ | |||||||
w.Header().Set("Access-Control-Allow-Origin", "*") | ||||||||
w.Header().Set("Access-Control-Allow-Headers", "Access-Control-Allow-Headers, Origin,Accept, X-Requested-With, Content-Type, Access-Control-Request-Method, Access-Control-Request-Headers") | ||||||||
if r.Method != http.MethodPost { | ||||||||
w.WriteHeader(http.StatusMethodNotAllowed) | ||||||||
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. Set the Content-Type header before writing JSON, e.g.,
Suggested change
Copilot uses AI. Check for mistakes. Positive FeedbackNegative Feedback |
||||||||
json.NewEncoder(w).Encode(map[string]string{"error": "Only POST method is allowed"}) | ||||||||
return | ||||||||
} | ||||||||
|
||||||||
body, err := io.ReadAll(r.Body) | ||||||||
if err != nil { | ||||||||
slog.Error("could not read body", "err", err) | ||||||||
// TODO: error? | ||||||||
slog.Error("could not read request body", "error", err) | ||||||||
http.Error(w, "Failed to read request body", http.StatusBadRequest) | ||||||||
return | ||||||||
} | ||||||||
defer r.Body.Close() | ||||||||
|
||||||||
nonceRequest := &NonceRequest{} | ||||||||
if err := json.Unmarshal(body, nonceRequest); err != nil { | ||||||||
slog.Error("could not unmarshal", "err", err) | ||||||||
// ? | ||||||||
slog.Error("could not unmarshal request body", "error", err, "body", string(body)) | ||||||||
http.Error(w, "Invalid request body", http.StatusBadRequest) | ||||||||
return | ||||||||
} | ||||||||
|
||||||||
senderAddress := common.HexToAddress(nonceRequest.MsgSender) | ||||||||
|
@@ -128,9 +134,15 @@ func (s *EspressoReaderService) requestNonce(w http.ResponseWriter, r *http.Requ | |||||||
if nonceCache[applicationAddress] == nil { | ||||||||
nonceCache[applicationAddress] = make(map[common.Address]uint64) | ||||||||
} | ||||||||
if nonceCache[applicationAddress][senderAddress] == 0 { | ||||||||
_, exists := nonceCache[applicationAddress][senderAddress] | ||||||||
if !exists { | ||||||||
ctx := r.Context() | ||||||||
nonce = s.queryNonceFromDb(ctx, senderAddress, applicationAddress) | ||||||||
nonce, err = s.queryNonceFromDb(ctx, senderAddress, applicationAddress) | ||||||||
if err != nil { | ||||||||
slog.Error("failed to query nonce from database", "error", err, "senderAddress", senderAddress, "applicationAddress", applicationAddress) | ||||||||
http.Error(w, "Failed to retrieve nonce", http.StatusInternalServerError) | ||||||||
return | ||||||||
} | ||||||||
nonceCache[applicationAddress][senderAddress] = nonce | ||||||||
} else { | ||||||||
nonce = nonceCache[applicationAddress][senderAddress] | ||||||||
|
@@ -139,10 +151,6 @@ func (s *EspressoReaderService) requestNonce(w http.ResponseWriter, r *http.Requ | |||||||
slog.Debug("got nonce request", "senderAddress", senderAddress, "applicationAddress", applicationAddress) | ||||||||
|
||||||||
nonceResponse := NonceResponse{Nonce: nonce} | ||||||||
if err != nil { | ||||||||
slog.Error("error json marshal nonce response", "err", err) | ||||||||
// ? | ||||||||
} | ||||||||
|
||||||||
err = json.NewEncoder(w).Encode(nonceResponse) | ||||||||
if err != nil { | ||||||||
|
@@ -156,14 +164,14 @@ func (s *EspressoReaderService) requestNonce(w http.ResponseWriter, r *http.Requ | |||||||
func (s *EspressoReaderService) queryNonceFromDb( | ||||||||
ctx context.Context, | ||||||||
senderAddress common.Address, | ||||||||
applicationAddress common.Address) uint64 { | ||||||||
applicationAddress common.Address) (uint64, error) { | ||||||||
nonce, err := s.database.GetEspressoNonce(ctx, senderAddress.Hex(), applicationAddress.Hex()) | ||||||||
if err != nil { | ||||||||
slog.Error("failed to get espresso nonce", "error", err) | ||||||||
// TODO: error? | ||||||||
return 0, err | ||||||||
} | ||||||||
|
||||||||
return nonce | ||||||||
return nonce, nil | ||||||||
} | ||||||||
|
||||||||
type SubmitResponse struct { | ||||||||
|
@@ -175,20 +183,23 @@ func (s *EspressoReaderService) submit(w http.ResponseWriter, r *http.Request) { | |||||||
w.Header().Set("Access-Control-Allow-Origin", "*") | ||||||||
w.Header().Set("Access-Control-Allow-Headers", "Access-Control-Allow-Headers, Origin,Accept, X-Requested-With, Content-Type, Access-Control-Request-Method, Access-Control-Request-Headers") | ||||||||
if r.Method != http.MethodPost { | ||||||||
// TODO: error? | ||||||||
w.WriteHeader(http.StatusMethodNotAllowed) | ||||||||
json.NewEncoder(w).Encode(map[string]string{"error": "Only POST method is allowed"}) | ||||||||
return | ||||||||
} | ||||||||
|
||||||||
body, err := io.ReadAll(r.Body) | ||||||||
if err != nil { | ||||||||
slog.Error("could not read body", "err", err) | ||||||||
slog.Error("could not read request body", "error", err) | ||||||||
http.Error(w, "Failed to read request body", http.StatusBadRequest) | ||||||||
return | ||||||||
} | ||||||||
slog.Debug("got submit request", "request body", string(body)) | ||||||||
|
||||||||
msgSender, typedData, sigHash, err := ExtractSigAndData(string(body)) | ||||||||
if err != nil { | ||||||||
slog.Error("transaction not correctly formatted", "error", err) | ||||||||
// TODO: error? | ||||||||
http.Error(w, "Invalid transaction format", http.StatusBadRequest) | ||||||||
return | ||||||||
} | ||||||||
submitResponse := SubmitResponse{Id: sigHash} | ||||||||
|
@@ -198,43 +209,62 @@ func (s *EspressoReaderService) submit(w http.ResponseWriter, r *http.Request) { | |||||||
client := client.NewClient(s.EspressoBaseUrl) | ||||||||
ctx := r.Context() | ||||||||
_, namespace, err := getEspressoConfig(ctx, appAddress, s.database, s.blockchainHttpEndpoint) | ||||||||
if err != nil { | ||||||||
slog.Error("failed to get espresso config", "error", err, "appAddress", appAddress) | ||||||||
http.Error(w, "Failed to get application configuration", http.StatusInternalServerError) | ||||||||
return | ||||||||
} | ||||||||
var tx types.Transaction | ||||||||
tx.Namespace = namespace | ||||||||
tx.Payload = body | ||||||||
_, err = client.SubmitTransaction(ctx, tx) | ||||||||
if err != nil { | ||||||||
slog.Error("espresso tx submit error", "err", err) | ||||||||
// TODO: error? | ||||||||
slog.Error("espresso tx submit error", "error", err) | ||||||||
http.Error(w, "Failed to submit transaction to Espresso", http.StatusInternalServerError) | ||||||||
return | ||||||||
} | ||||||||
|
||||||||
err = json.NewEncoder(w).Encode(submitResponse) | ||||||||
if err != nil { | ||||||||
slog.Info("Internal server error", | ||||||||
"service", "espresso submit endpoint", | ||||||||
"err", err) | ||||||||
http.Error(w, err.Error(), http.StatusInternalServerError) | ||||||||
// TODO: error? | ||||||||
if err := json.NewEncoder(w).Encode(submitResponse); err != nil { | ||||||||
slog.Error("failed to encode submit response", "error", err, "submitResponse", submitResponse) | ||||||||
http.Error(w, "Internal server error", http.StatusInternalServerError) | ||||||||
return | ||||||||
} | ||||||||
|
||||||||
// update nonce cache | ||||||||
if nonceCache[appAddress] == nil { | ||||||||
slog.Error("Should query nonce before submit") | ||||||||
// TODO: error? | ||||||||
slog.Error("Should query nonce before submit", "appAddress", appAddress) | ||||||||
http.Error(w, "Nonce not initialized for this application. Please request a nonce first.", http.StatusBadRequest) | ||||||||
return | ||||||||
} | ||||||||
nonceInRequestFloat, ok := typedData.Message["nonce"].(float64) | ||||||||
if !ok { | ||||||||
slog.Error("Nonce not found or invalid type in request", "typedData", typedData) | ||||||||
http.Error(w, "Invalid or missing nonce in request", http.StatusBadRequest) | ||||||||
return | ||||||||
} | ||||||||
nonceInRequest := uint64(typedData.Message["nonce"].(float64)) | ||||||||
if nonceCache[appAddress][msgSender] == 0 { | ||||||||
nonceInRequest := uint64(nonceInRequestFloat) | ||||||||
|
||||||||
cachedNonce, exists := nonceCache[appAddress][msgSender] | ||||||||
if !exists { | ||||||||
ctx := r.Context() | ||||||||
nonceInDb := s.queryNonceFromDb(ctx, msgSender, appAddress) | ||||||||
nonceInDb, err := s.queryNonceFromDb(ctx, msgSender, appAddress) | ||||||||
if err != nil { | ||||||||
slog.Error("failed to query nonce from database during submit", "error", err, "senderAddress", msgSender, "applicationAddress", appAddress) | ||||||||
http.Error(w, "Failed to retrieve nonce for validation", http.StatusInternalServerError) | ||||||||
return | ||||||||
} | ||||||||
if nonceInRequest != nonceInDb { | ||||||||
slog.Error("Nonce in request is incorrect") | ||||||||
// TODO: error? | ||||||||
slog.Error("Nonce in request is incorrect", "nonceInRequest", nonceInRequest, "nonceInDb", nonceInDb, "senderAddress", msgSender, "applicationAddress", appAddress) | ||||||||
http.Error(w, "Incorrect nonce", http.StatusBadRequest) | ||||||||
return | ||||||||
} | ||||||||
nonceCache[appAddress][msgSender] = nonceInDb + 1 | ||||||||
} else { | ||||||||
if nonceInRequest != cachedNonce { | ||||||||
slog.Error("Nonce in request is incorrect", "requestNonce", nonceInRequest, "cachedNonce", cachedNonce, "senderAddress", msgSender, "applicationAddress", appAddress) | ||||||||
http.Error(w, "Incorrect nonce", http.StatusBadRequest) | ||||||||
return | ||||||||
} | ||||||||
nonceCache[appAddress][msgSender]++ | ||||||||
} | ||||||||
} | ||||||||
|
Original file line number | Diff line number | Diff line change | ||||
---|---|---|---|---|---|---|
|
@@ -153,19 +153,23 @@ func (r *EvmReader) ReadAndStoreInputs( | |||||
combinedIndex, err := r.repository.GetInputIndexWithTx(ctx, dbTx, address.Hex()) | ||||||
if err != nil { | ||||||
slog.Error("evmreader: failed to read index", "app", address, "error", err) | ||||||
return errors.New("evmreader: failed to read index") | ||||||
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. Wrap and return the original error to preserve context, e.g., fmt.Errorf("evmreader: failed to read index: %w", err).
Suggested change
Copilot uses AI. Check for mistakes. Positive FeedbackNegative Feedback 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. This change doesn't seem necessary 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.
The only drawback here is that the original error is not preserved in the tracker. 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. The original error message is printed as error message. So should be fine |
||||||
} | ||||||
if combinedIndex != input.Index && r.shouldModifyIndex == true { | ||||||
slog.Info("evmreader: Overriding input index", "onchain-index", input.Index, "new-index", combinedIndex) | ||||||
input.Index = combinedIndex | ||||||
modifiedRawData, err := r.modifyIndexInRaw(input.RawData, combinedIndex) | ||||||
if err == nil { | ||||||
input.RawData = modifiedRawData | ||||||
if err != nil { | ||||||
slog.Error("evmreader: failed to modify index", "app", address, "error", err) | ||||||
return errors.New("evmreader: failed to modify index") | ||||||
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. Wrap the original error when returning, e.g., fmt.Errorf("evmreader: failed to modify index: %w", err).
Suggested change
Copilot uses AI. Check for mistakes. Positive FeedbackNegative Feedback |
||||||
} | ||||||
input.RawData = modifiedRawData | ||||||
} | ||||||
// update input index | ||||||
err = r.repository.UpdateInputIndexWithTx(ctx, dbTx, address.Hex()) | ||||||
if err != nil { | ||||||
slog.Error("failed to update index", "app", address, "error", err) | ||||||
return errors.New("evmreader: failed to update index") | ||||||
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. Wrap the repository error to keep the original error context, e.g., fmt.Errorf("evmreader: failed to update index: %w", err).
Suggested change
Copilot uses AI. Check for mistakes. Positive FeedbackNegative Feedback |
||||||
} | ||||||
epochInputMap[currentEpoch] = append(currentInputs, input) | ||||||
|
||||||
|
@@ -201,15 +205,13 @@ func (r *EvmReader) ReadAndStoreInputs( | |||||
"address", address, | ||||||
"error", err, | ||||||
) | ||||||
dbTx.Rollback(ctx) | ||||||
continue | ||||||
return errors.New("evmreader: Error storing inputs and epochs") | ||||||
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. Use consistent lowercase for error messages and wrap the original error, e.g., fmt.Errorf("evmreader: error storing inputs and epochs: %w", err).
Suggested change
Copilot uses AI. Check for mistakes. Positive FeedbackNegative Feedback |
||||||
} | ||||||
// Commit transaction | ||||||
err = dbTx.Commit(ctx) | ||||||
if err != nil { | ||||||
slog.Error("could not commit db tx", "err", err) | ||||||
dbTx.Rollback(ctx) | ||||||
continue | ||||||
return errors.New("evmreader: could not commit db tx") | ||||||
} | ||||||
|
||||||
// Store everything | ||||||
|
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.
is it ok to just skip?
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.
you're right. This should be a
break