From 0c08b122280a5190192cede2c3341baabc38753b Mon Sep 17 00:00:00 2001 From: TymKh Date: Thu, 11 Sep 2025 17:45:16 +0200 Subject: [PATCH 1/2] support protectRefund field --- server/configuration_watcher.go | 12 ++++++------ server/configuration_watcher_test.go | 12 ++++++------ server/request_processor.go | 2 +- server/url_params.go | 6 +++++- types/types.go | 1 + 5 files changed, 19 insertions(+), 14 deletions(-) diff --git a/server/configuration_watcher.go b/server/configuration_watcher.go index 6b08b9a..9eaa5f3 100644 --- a/server/configuration_watcher.go +++ b/server/configuration_watcher.go @@ -33,12 +33,12 @@ func parseURLToParameters(rawURL string) (URLParameters, error) { if err != nil { return URLParameters{}, fmt.Errorf("failed to parse URL: %w", err) } - + params, err := ExtractParametersFromUrl(parsedURL, nil) if err != nil { return URLParameters{}, fmt.Errorf("failed to extract parameters: %w", err) } - + return params, nil } @@ -55,7 +55,7 @@ func NewConfigurationWatcher(customersConfig CustomersConfig) (*ConfigurationWat } parsedCustomersConfig[customerID] = allowedConfigs } - + // Parse presets for header-based override parsedPresets := make(map[string]URLParameters) for originID, presetURL := range customersConfig.Presets { @@ -68,10 +68,10 @@ func NewConfigurationWatcher(customersConfig CustomersConfig) (*ConfigurationWat parsedPresets[originID] = params log.Info("Loaded preset configuration", "originID", originID) } - + return &ConfigurationWatcher{ ParsedCustomersConfig: parsedCustomersConfig, - ParsedPresets: parsedPresets, + ParsedPresets: parsedPresets, }, nil } @@ -79,7 +79,7 @@ func ReadCustomerConfigFromFile(fileName string) (*ConfigurationWatcher, error) if fileName == "" { return &ConfigurationWatcher{ ParsedCustomersConfig: make(map[string][]URLParameters), - ParsedPresets: make(map[string]URLParameters), + ParsedPresets: make(map[string]URLParameters), }, nil } data, err := os.ReadFile(fileName) diff --git a/server/configuration_watcher_test.go b/server/configuration_watcher_test.go index 4d242ce..56d3784 100644 --- a/server/configuration_watcher_test.go +++ b/server/configuration_watcher_test.go @@ -16,11 +16,11 @@ func TestConfigurationWatcherPresets(t *testing.T) { "quicknode": "/fast?originId=quicknode&refund=0x1234567890123456789012345678901234567890:90", }, } - + watcher, err := NewConfigurationWatcher(config) require.NoError(t, err) require.NotNil(t, watcher) - + // Core functionality: preset should be parsed and available preset, exists := watcher.ParsedPresets["quicknode"] require.True(t, exists) @@ -40,15 +40,15 @@ func TestConfigurationWatcherInvalidPresets(t *testing.T) { "invalid": "://invalid-url", // This should be skipped }, } - + watcher, err := NewConfigurationWatcher(config) require.NoError(t, err) // Should not fail startup - + // Valid preset loaded _, exists := watcher.ParsedPresets["valid"] require.True(t, exists) - + // Invalid preset skipped _, exists = watcher.ParsedPresets["invalid"] require.False(t, exists) -} \ No newline at end of file +} diff --git a/server/request_processor.go b/server/request_processor.go index 6d8f5ce..2436eda 100644 --- a/server/request_processor.go +++ b/server/request_processor.go @@ -320,7 +320,7 @@ func (r *RpcRequest) sendTxToRelay() { sendPrivateTxArgs := types.SendPrivateTxRequestWithPreferences{} sendPrivateTxArgs.Tx = r.rawTxHex sendPrivateTxArgs.Preferences = &r.urlParams.pref - + // Replace null addresses (origin placeholders) with sender if needed if len(r.urlParams.pref.Validity.Refund) > 0 { sender := common.HexToAddress(r.txFrom) diff --git a/server/url_params.go b/server/url_params.go index 42d2237..1a1e1f0 100644 --- a/server/url_params.go +++ b/server/url_params.go @@ -139,7 +139,7 @@ func ExtractParametersFromUrl(reqUrl *url.URL, allBuilders []string) (params URL } addressPart := strings.ToLower(split[0]) - + // Handle origin keyword if addressPart == OriginKeyword { addresses[i] = common.Address{} @@ -188,6 +188,10 @@ func ExtractParametersFromUrl(reqUrl *url.URL, allBuilders []string) (params URL if len(useMempoolQuery) != 0 && useMempoolQuery[0] == "true" { params.pref.Privacy.UseMempool = true } + protectRefundQuery := normalizedQuery["protectrefund"] + if len(protectRefundQuery) != 0 && protectRefundQuery[0] == "true" { + params.pref.Privacy.ProtectRefund = true + } canRevertQuery := normalizedQuery["canrevert"] if len(canRevertQuery) != 0 && canRevertQuery[0] == "true" { params.pref.CanRevert = true diff --git a/types/types.go b/types/types.go index e96864d..23c7ff2 100644 --- a/types/types.go +++ b/types/types.go @@ -118,6 +118,7 @@ type TxPrivacyPreferences struct { Hints []string `json:"hints"` Builders []string `json:"builders"` UseMempool bool `json:"useMempool"` + ProtectRefund bool `json:"protectRefund"` AllowTEE bool `json:"allowTee,omitempty"` MempoolRPC string `json:"mempoolRpc"` AuctionTimeout uint64 `json:"auctionTimeout,omitempty"` From c16fd6806293127ca43feff36aeefb615ba0025b Mon Sep 17 00:00:00 2001 From: TymKh Date: Fri, 12 Sep 2025 16:47:10 +0200 Subject: [PATCH 2/2] fix test --- tests/e2e_test.go | 10 +++------- 1 file changed, 3 insertions(+), 7 deletions(-) diff --git a/tests/e2e_test.go b/tests/e2e_test.go index 1fc78e8..d46ddb2 100644 --- a/tests/e2e_test.go +++ b/tests/e2e_test.go @@ -228,11 +228,11 @@ func TestMetamaskFix(t *testing.T) { req_getTransactionCount := types.NewJsonRpcRequest(1, "eth_getTransactionCount", []interface{}{testutils.TestTx_MM2_From, "latest"}) txCountBefore := testutils.SendRpcAndParseResponseOrFailNowString(t, req_getTransactionCount) - //first sendRawTransaction call: rawTx that triggers the error (creates MM cache entry) + // first sendRawTransaction call: rawTx that triggers the error (creates MM cache entry) req_sendRawTransaction := types.NewJsonRpcRequest(1, "eth_sendRawTransaction", []interface{}{testutils.TestTx_MM2_RawTx}) r1 := testutils.SendRpcAndParseResponseOrFailNowAllowRpcError(t, req_sendRawTransaction) require.NotNil(t, r1.Error, r1.Error) // tx will actually fail due to incorrect nonce but it's fine for this test, since we mark it as sent to relay - //fmt.Printf("\n\n\n\n\n") + // fmt.Printf("\n\n\n\n\n") // call getTxReceipt to trigger query to Tx API req_getTransactionReceipt := types.NewJsonRpcRequest(1, "eth_getTransactionReceipt", []interface{}{testutils.TestTx_MM2_Hash}) @@ -279,7 +279,7 @@ func TestRelayTx(t *testing.T) { // Ensure that request was signed properly pubkey := crypto.PubkeyToAddress(relaySigningKey.PublicKey).Hex() - require.Equal(t, pubkey+":0x06e1ea66c5fc1017787369beffc9c9acd82570b4ec4ea075c708f2351a26fdff4abbf601037884d0785ff88985b590f7b865852a4100d5670605a56b9118804900", testutils.MockBackendLastRawRequest.Header.Get("X-Flashbots-Signature")) + require.Equal(t, pubkey+":0xfa3496a32970eb2caccb7cd361c9384e21e84363501cde0f325a529c2773c0a1638abf84d4d14db65b29140e2b61d1a91d0c2621abb0fb0d2eda73f1992a58d501", testutils.MockBackendLastRawRequest.Header.Get("X-Flashbots-Signature")) // Check result - should be the tx hash var res string @@ -451,7 +451,6 @@ func TestBatch_eth_transaction(t *testing.T) { for _, j := range res { assert.Equal(t, m[j.Id.(float64)], j) } - } // Test batch request with different eth transaction @@ -494,7 +493,6 @@ func TestBatch_eth_call(t *testing.T) { for _, j := range res { assert.Equal(t, m[j.Id.(float64)], j) } - } // Test batch request with different transaction @@ -727,9 +725,7 @@ func Test_StoreValidateTxs(t *testing.T) { require.Equal(t, 10, len(entry.TxSmartContractMethod)) require.False(t, entry.Fast) } - } - } // Test that origin keyword in refund config is replaced with sender address