diff --git a/cmd/utils/flags.go b/cmd/utils/flags.go index 844397b734..2ad2e0b356 100644 --- a/cmd/utils/flags.go +++ b/cmd/utils/flags.go @@ -639,13 +639,13 @@ var ( RPCTxSyncDefaultTimeoutFlag = &cli.DurationFlag{ Name: "rpc.txsync.defaulttimeout", Usage: "Default timeout for eth_sendRawTransactionSync (e.g. 2s, 500ms)", - Value: ethconfig.Defaults.TxSyncDefaultTimeout, + Value: time.Duration(ethconfig.Defaults.TxSyncDefaultTimeout) * time.Millisecond, Category: flags.APICategory, } RPCTxSyncMaxTimeoutFlag = &cli.DurationFlag{ Name: "rpc.txsync.maxtimeout", Usage: "Maximum allowed timeout for eth_sendRawTransactionSync (e.g. 5m)", - Value: ethconfig.Defaults.TxSyncMaxTimeout, + Value: time.Duration(ethconfig.Defaults.TxSyncMaxTimeout) * time.Millisecond, Category: flags.APICategory, } RPCGlobalRangeLimitFlag = &cli.Uint64Flag{ @@ -1772,10 +1772,10 @@ func SetEthConfig(ctx *cli.Context, stack *node.Node, cfg *ethconfig.Config) { cfg.LogQueryLimit = ctx.Int(RPCGlobalLogQueryLimit.Name) } if ctx.IsSet(RPCTxSyncDefaultTimeoutFlag.Name) { - cfg.TxSyncDefaultTimeout = ctx.Duration(RPCTxSyncDefaultTimeoutFlag.Name) + cfg.TxSyncDefaultTimeout = uint64(ctx.Duration(RPCTxSyncDefaultTimeoutFlag.Name).Milliseconds()) } if ctx.IsSet(RPCTxSyncMaxTimeoutFlag.Name) { - cfg.TxSyncMaxTimeout = ctx.Duration(RPCTxSyncMaxTimeoutFlag.Name) + cfg.TxSyncMaxTimeout = uint64(ctx.Duration(RPCTxSyncMaxTimeoutFlag.Name).Milliseconds()) } if ctx.IsSet(RPCGlobalRangeLimitFlag.Name) { cfg.RangeLimit = ctx.Uint64(RPCGlobalRangeLimitFlag.Name) diff --git a/eth/api_backend.go b/eth/api_backend.go index 3f826b7861..0174b690bb 100644 --- a/eth/api_backend.go +++ b/eth/api_backend.go @@ -492,10 +492,10 @@ func (b *EthAPIBackend) StateAtTransaction(ctx context.Context, block *types.Blo return b.eth.stateAtTransaction(ctx, block, txIndex, reexec) } -func (b *EthAPIBackend) RPCTxSyncDefaultTimeout() time.Duration { +func (b *EthAPIBackend) RPCTxSyncDefaultTimeout() uint64 { return b.eth.config.TxSyncDefaultTimeout } -func (b *EthAPIBackend) RPCTxSyncMaxTimeout() time.Duration { +func (b *EthAPIBackend) RPCTxSyncMaxTimeout() uint64 { return b.eth.config.TxSyncMaxTimeout } diff --git a/eth/ethconfig/config.go b/eth/ethconfig/config.go index e58c4b884a..cc4eeb74ca 100644 --- a/eth/ethconfig/config.go +++ b/eth/ethconfig/config.go @@ -72,9 +72,9 @@ var Defaults = Config{ RPCGasCap: 50000000, RPCEVMTimeout: 5 * time.Second, GPO: FullNodeGPO, - RPCTxFeeCap: 1, // 1 ether - TxSyncDefaultTimeout: 20 * time.Second, - TxSyncMaxTimeout: 1 * time.Minute, + RPCTxFeeCap: 1, // 1 ether + TxSyncDefaultTimeout: uint64(20000), // 20 seconds in milliseconds + TxSyncMaxTimeout: uint64(60000), // 1 minute in milliseconds SlowBlockThreshold: time.Second * 2, RangeLimit: 0, } @@ -203,8 +203,8 @@ type Config struct { OverrideVerkle *uint64 `toml:",omitempty"` // EIP-7966: eth_sendRawTransactionSync timeouts - TxSyncDefaultTimeout time.Duration `toml:",omitempty"` - TxSyncMaxTimeout time.Duration `toml:",omitempty"` + TxSyncDefaultTimeout uint64 `toml:",omitempty"` + TxSyncMaxTimeout uint64 `toml:",omitempty"` // RangeLimit restricts the maximum range (end - start) for range queries. RangeLimit uint64 `toml:",omitempty"` diff --git a/eth/ethconfig/gen_config.go b/eth/ethconfig/gen_config.go index 6f94a409e5..93d8cc57e7 100644 --- a/eth/ethconfig/gen_config.go +++ b/eth/ethconfig/gen_config.go @@ -61,13 +61,13 @@ func (c Config) MarshalTOML() (interface{}, error) { RPCGasCap uint64 RPCEVMTimeout time.Duration RPCTxFeeCap float64 - OverrideOsaka *uint64 `toml:",omitempty"` - OverrideBPO1 *uint64 `toml:",omitempty"` - OverrideBPO2 *uint64 `toml:",omitempty"` - OverrideVerkle *uint64 `toml:",omitempty"` - TxSyncDefaultTimeout time.Duration `toml:",omitempty"` - TxSyncMaxTimeout time.Duration `toml:",omitempty"` - RangeLimit uint64 `toml:",omitempty"` + OverrideOsaka *uint64 `toml:",omitempty"` + OverrideBPO1 *uint64 `toml:",omitempty"` + OverrideBPO2 *uint64 `toml:",omitempty"` + OverrideVerkle *uint64 `toml:",omitempty"` + TxSyncDefaultTimeout uint64 `toml:",omitempty"` + TxSyncMaxTimeout uint64 `toml:",omitempty"` + RangeLimit uint64 `toml:",omitempty"` } var enc Config enc.Genesis = c.Genesis @@ -171,13 +171,13 @@ func (c *Config) UnmarshalTOML(unmarshal func(interface{}) error) error { RPCGasCap *uint64 RPCEVMTimeout *time.Duration RPCTxFeeCap *float64 - OverrideOsaka *uint64 `toml:",omitempty"` - OverrideBPO1 *uint64 `toml:",omitempty"` - OverrideBPO2 *uint64 `toml:",omitempty"` - OverrideVerkle *uint64 `toml:",omitempty"` - TxSyncDefaultTimeout *time.Duration `toml:",omitempty"` - TxSyncMaxTimeout *time.Duration `toml:",omitempty"` - RangeLimit *uint64 `toml:",omitempty"` + OverrideOsaka *uint64 `toml:",omitempty"` + OverrideBPO1 *uint64 `toml:",omitempty"` + OverrideBPO2 *uint64 `toml:",omitempty"` + OverrideVerkle *uint64 `toml:",omitempty"` + TxSyncDefaultTimeout *uint64 `toml:",omitempty"` + TxSyncMaxTimeout *uint64 `toml:",omitempty"` + RangeLimit *uint64 `toml:",omitempty"` } var dec Config if err := unmarshal(&dec); err != nil { diff --git a/internal/ethapi/api.go b/internal/ethapi/api.go index e0baccbfe7..f81932e70f 100644 --- a/internal/ethapi/api.go +++ b/internal/ethapi/api.go @@ -1689,19 +1689,18 @@ func (api *TransactionAPI) SendRawTransactionSync(ctx context.Context, input hex } var ( - maxTimeout = api.b.RPCTxSyncMaxTimeout() - defaultTimeout = api.b.RPCTxSyncDefaultTimeout() - timeout = defaultTimeout + maxTimeoutMs = api.b.RPCTxSyncMaxTimeout() + defaultTimeoutMs = api.b.RPCTxSyncDefaultTimeout() + effectiveMs = defaultTimeoutMs ) if timeoutMs != nil && *timeoutMs > 0 { - req := time.Duration(*timeoutMs) * time.Millisecond - if req > maxTimeout { - timeout = maxTimeout + if *timeoutMs > maxTimeoutMs { + effectiveMs = maxTimeoutMs } else { - timeout = req + effectiveMs = *timeoutMs } } - receiptCtx, cancel := context.WithTimeout(ctx, timeout) + receiptCtx, cancel := context.WithTimeout(ctx, time.Duration(effectiveMs)*time.Millisecond) defer cancel() // Fast path. @@ -1716,7 +1715,10 @@ func (api *TransactionAPI) SendRawTransactionSync(ctx context.Context, input hex // If server-side wait window elapsed, return the structured timeout. if errors.Is(receiptCtx.Err(), context.DeadlineExceeded) { return nil, &txSyncTimeoutError{ - msg: fmt.Sprintf("The transaction was added to the transaction pool but wasn't processed in %v", timeout), + msg: fmt.Sprintf( + "The transaction was added to the transaction pool but wasn't processed in %v", + time.Duration(effectiveMs)*time.Millisecond, + ), hash: hash, } } diff --git a/internal/ethapi/api_test.go b/internal/ethapi/api_test.go index 3668bd0e14..2179f9f7a0 100644 --- a/internal/ethapi/api_test.go +++ b/internal/ethapi/api_test.go @@ -447,8 +447,8 @@ type testBackend struct { sentTx *types.Transaction sentTxHash common.Hash - syncDefaultTimeout time.Duration - syncMaxTimeout time.Duration + syncDefaultTimeout uint64 // in milliseconds + syncMaxTimeout uint64 // in milliseconds } func fakeBlockHash(txh common.Hash) common.Hash { @@ -3949,20 +3949,20 @@ func (b configTimeBackend) CurrentHeader() *types.Header { return &types.Header{Time: b.time} } -func (b *testBackend) RPCTxSyncDefaultTimeout() time.Duration { +func (b *testBackend) RPCTxSyncDefaultTimeout() uint64 { if b.syncDefaultTimeout != 0 { return b.syncDefaultTimeout } - return 2 * time.Second + return 2000 // 2 seconds in milliseconds } -func (b *testBackend) RPCTxSyncMaxTimeout() time.Duration { +func (b *testBackend) RPCTxSyncMaxTimeout() uint64 { if b.syncMaxTimeout != 0 { return b.syncMaxTimeout } - return 5 * time.Minute + return 300000 // 5 minutes in milliseconds } -func (b *backendMock) RPCTxSyncDefaultTimeout() time.Duration { return 2 * time.Second } -func (b *backendMock) RPCTxSyncMaxTimeout() time.Duration { return 5 * time.Minute } +func (b *backendMock) RPCTxSyncDefaultTimeout() uint64 { return 2000 } // 2 seconds +func (b *backendMock) RPCTxSyncMaxTimeout() uint64 { return 300000 } // 5 minutes func makeSignedRaw(t *testing.T, api *TransactionAPI, from, to common.Address, value *big.Int) (hexutil.Bytes, *types.Transaction) { t.Helper() diff --git a/internal/ethapi/backend.go b/internal/ethapi/backend.go index af3d592b82..7ad15b67a2 100644 --- a/internal/ethapi/backend.go +++ b/internal/ethapi/backend.go @@ -53,8 +53,8 @@ type Backend interface { RPCEVMTimeout() time.Duration // global timeout for eth_call over rpc: DoS protection RPCTxFeeCap() float64 // global tx fee cap for all transaction related APIs UnprotectedAllowed() bool // allows only for EIP155 transactions. - RPCTxSyncDefaultTimeout() time.Duration - RPCTxSyncMaxTimeout() time.Duration + RPCTxSyncDefaultTimeout() uint64 // default timeout for eth_sendRawTransactionSync in milliseconds + RPCTxSyncMaxTimeout() uint64 // maximum timeout for eth_sendRawTransactionSync in milliseconds // Blockchain API SetHead(number uint64)