Skip to content

Commit

Permalink
fix: Handle invalid signatures correctly, move signature checks earli…
Browse files Browse the repository at this point in the history
…er to avoid storing request body.
  • Loading branch information
ryanschneider committed Aug 7, 2024
1 parent 2b63fdd commit d90fb9b
Show file tree
Hide file tree
Showing 4 changed files with 32 additions and 13 deletions.
4 changes: 2 additions & 2 deletions adapters/flashbots/signature.go
Original file line number Diff line number Diff line change
Expand Up @@ -16,7 +16,7 @@ var (
ErrInvalidSignature = errors.New("invalid signature provided")
)

func ParseSignature(header string, body []byte) (string, error) {
func ParseSignature(header string, body []byte) (signingAddress string, err error) {
if header == "" {
return "", ErrNoSignature
}
Expand All @@ -29,7 +29,7 @@ func ParseSignature(header string, body []byte) (string, error) {
return VerifySignature(body, splitSig[0], splitSig[1])
}

func VerifySignature(body []byte, signingAddressStr, signatureStr string) (string, error) {
func VerifySignature(body []byte, signingAddressStr, signatureStr string) (signingAddress string, err error) {
signature, err := hexutil.Decode(signatureStr)
if err != nil || len(signature) == 0 {
return "", fmt.Errorf("%w: %w", ErrInvalidSignature, err)
Expand Down
8 changes: 5 additions & 3 deletions server/request_handler.go
Original file line number Diff line number Diff line change
Expand Up @@ -148,9 +148,11 @@ func (r *RpcRequestHandler) processRequest(client RPCProxyClient, jsonReq *types
// Handle single request
rpcReq := NewRpcRequest(r.logger, client, jsonReq, r.relaySigningKey, r.relayUrl, origin, referer, isWhitehatBundleCollection, whitehatBundleId, entry, urlParams, r.chainID, r.rpcCache)

if r.req.Header.Get("X-Flashbots-Signature") != "" {
rpcReq.flashbotsSignature = r.req.Header.Get("X-Flashbots-Signature")
rpcReq.flashbotsSignatureBody = body
if err := rpcReq.CheckFlashbotsSignature(r.req.Header.Get("X-Flashbots-Signature"), body); err != nil {
r.logger.Warn("[processRequest] CheckFlashbotsSignature", "error", err)
rpcReq.writeRpcError(err.Error(), types.JsonRpcInvalidRequest)
r._writeRpcResponse(rpcReq.jsonRes)
return
}
res := rpcReq.ProcessRequest()
// Write response
Expand Down
9 changes: 3 additions & 6 deletions server/request_intercepts.go
Original file line number Diff line number Diff line change
@@ -1,11 +1,9 @@
package server

import (
"errors"
"fmt"
"strings"

"github.com/flashbots/rpc-endpoint/adapters/flashbots"
"github.com/flashbots/rpc-endpoint/types"
)

Expand Down Expand Up @@ -154,8 +152,7 @@ func (r *RpcRequest) intercept_eth_call_to_FlashRPC_Contract() (requestFinished
}

func (r *RpcRequest) intercept_signed_eth_getTransactionCount() (requestFinished bool) {
signingAddress, err := flashbots.ParseSignature(r.flashbotsSignature, r.flashbotsSignatureBody)
if errors.Is(err, flashbots.ErrNoSignature) {
if r.flashbotsSigningAddress == "" {
r.logger.Info("[eth_getTransactionCount] No signature found")
return false
}
Expand All @@ -177,8 +174,8 @@ func (r *RpcRequest) intercept_signed_eth_getTransactionCount() (requestFinished
return false
}
addr = strings.ToLower(addr)
if addr != strings.ToLower(signingAddress) {
r.logger.Info("[eth_getTransactionCount] address mismatch", "addr", addr, "signingAddress", signingAddress)
if addr != strings.ToLower(r.flashbotsSigningAddress) {
r.logger.Info("[eth_getTransactionCount] address mismatch", "addr", addr, "signingAddress", r.flashbotsSigningAddress)
return false
}

Expand Down
24 changes: 22 additions & 2 deletions server/request_processor.go
Original file line number Diff line number Diff line change
Expand Up @@ -13,6 +13,7 @@ import (
"strings"
"time"

"github.com/flashbots/rpc-endpoint/adapters/flashbots"
"github.com/flashbots/rpc-endpoint/application"
"github.com/flashbots/rpc-endpoint/database"

Expand Down Expand Up @@ -42,8 +43,7 @@ type RpcRequest struct {
urlParams URLParameters
chainID []byte
rpcCache *application.RpcCache
flashbotsSignature string
flashbotsSignatureBody []byte
flashbotsSigningAddress string
}

func NewRpcRequest(
Expand Down Expand Up @@ -501,3 +501,23 @@ func (r *RpcRequest) writeRpcResult(result interface{}) {
Result: resBytes,
}
}

// CheckFlashbotsSignature parses and validates the Flashbots signature if present,
// returning an error if the signature is invalid. If the signature is present and valid
// the signing address is stored in the request.
func (r *RpcRequest) CheckFlashbotsSignature(signature string, body []byte) error {
// Most requests don't have a signature, so avoid parsing it if it's empty
if signature == "" {
return nil
}
signingAddress, err := flashbots.ParseSignature(signature, body)
if err != nil {
if errors.Is(err, flashbots.ErrNoSignature) {
return nil
} else {
return err
}
}
r.flashbotsSigningAddress = signingAddress
return nil
}

0 comments on commit d90fb9b

Please sign in to comment.