diff --git a/go/enclave/nodetype/common.go b/go/enclave/nodetype/common.go index bff4a94447..c414f63c81 100644 --- a/go/enclave/nodetype/common.go +++ b/go/enclave/nodetype/common.go @@ -20,7 +20,7 @@ func ExportCrossChainData(ctx context.Context, storage storage.Storage, fromSeqN return nil, errutil.ErrCrossChainBundleNoBatches } - //todo - siliev - all those fetches need to be atomic + // todo - siliev - all those fetches need to be atomic header, err := storage.FetchHeadBatchHeader(ctx) if err != nil { return nil, err diff --git a/tools/walletextension/rpcapi/transaction_api.go b/tools/walletextension/rpcapi/transaction_api.go index 3833db0e77..a0a8baedd4 100644 --- a/tools/walletextension/rpcapi/transaction_api.go +++ b/tools/walletextension/rpcapi/transaction_api.go @@ -101,7 +101,7 @@ func (s *TransactionAPI) GetTransactionReceipt(ctx context.Context, hash common. } func (s *TransactionAPI) SendTransaction(ctx context.Context, args gethapi.TransactionArgs) (common.Hash, error) { - txRec, err := ExecAuthRPC[common.Hash](ctx, s.we, &ExecCfg{account: args.From}, "eth_sendTransaction", args) + txRec, err := ExecAuthRPC[common.Hash](ctx, s.we, &ExecCfg{account: args.From, timeout: sendTransactionDuration}, "eth_sendTransaction", args) if err != nil { return common.Hash{}, err } @@ -131,7 +131,7 @@ func (s *TransactionAPI) FillTransaction(ctx context.Context, args gethapi.Trans } func (s *TransactionAPI) SendRawTransaction(ctx context.Context, input hexutil.Bytes) (common.Hash, error) { - txRec, err := ExecAuthRPC[common.Hash](ctx, s.we, &ExecCfg{tryAll: true}, "eth_sendRawTransaction", input) + txRec, err := ExecAuthRPC[common.Hash](ctx, s.we, &ExecCfg{tryAll: true, timeout: sendTransactionDuration}, "eth_sendRawTransaction", input) if err != nil { return common.Hash{}, err } diff --git a/tools/walletextension/rpcapi/utils.go b/tools/walletextension/rpcapi/utils.go index 732fd45d2e..13d6197b2d 100644 --- a/tools/walletextension/rpcapi/utils.go +++ b/tools/walletextension/rpcapi/utils.go @@ -34,13 +34,15 @@ const ( ethCallAddrPadding = "000000000000000000000000" notAuthorised = "not authorised" + serverBusy = "server busy. please retry later" longCacheTTL = 5 * time.Hour shortCacheTTL = 1 * time.Minute // hardcoding the maximum time for an RPC request // this value will be propagated to the node and enclave and all the operations - maximumRPCCallDuration = 5 * time.Second + maximumRPCCallDuration = 5 * time.Second + sendTransactionDuration = 20 * time.Second ) var rpcNotImplemented = fmt.Errorf("rpc endpoint not implemented") @@ -52,6 +54,7 @@ type ExecCfg struct { tryUntilAuthorised bool adjustArgs func(acct *GWAccount) []any cacheCfg *CacheCfg + timeout time.Duration } type CacheStrategy uint8 @@ -136,10 +139,19 @@ func ExecAuthRPC[R any](ctx context.Context, w *Services, cfg *ExecCfg, method s } // wrap the context with a timeout to prevent long executions - timeoutContext, cancelCtx := context.WithTimeout(ctx, maximumRPCCallDuration) + deadline := cfg.timeout + // if not set, use default + if deadline == 0 { + deadline = maximumRPCCallDuration + } + timeoutContext, cancelCtx := context.WithTimeout(ctx, deadline) defer cancelCtx() err := rpcClient.CallContext(timeoutContext, &result, method, adjustedArgs...) + // return a friendly error to the user + if err != nil && errors.Is(err, context.DeadlineExceeded) { + return nil, fmt.Errorf(serverBusy) + } return result, err }) if err != nil {