mirror of
https://github.com/ethereum/go-ethereum.git
synced 2026-07-23 05:06:43 +00:00
feat: initial api with default timeouts
This commit is contained in:
parent
11208553dd
commit
ca42c98c60
4 changed files with 79 additions and 0 deletions
|
|
@ -486,3 +486,11 @@ func (b *EthAPIBackend) StateAtBlock(ctx context.Context, block *types.Block, re
|
|||
func (b *EthAPIBackend) StateAtTransaction(ctx context.Context, block *types.Block, txIndex int, reexec uint64) (*types.Transaction, vm.BlockContext, *state.StateDB, tracers.StateReleaseFunc, error) {
|
||||
return b.eth.stateAtTransaction(ctx, block, txIndex, reexec)
|
||||
}
|
||||
|
||||
func (b *EthAPIBackend) RPCTxSyncDefaultTimeout() time.Duration {
|
||||
return 2 * time.Second
|
||||
}
|
||||
|
||||
func (b *EthAPIBackend) RPCTxSyncMaxTimeout() time.Duration {
|
||||
return 5 * time.Minute
|
||||
}
|
||||
|
|
|
|||
|
|
@ -1652,6 +1652,62 @@ func (api *TransactionAPI) SendRawTransaction(ctx context.Context, input hexutil
|
|||
return SubmitTransaction(ctx, api.b, tx)
|
||||
}
|
||||
|
||||
// SendRawTransactionSync will add the signed transaction to the transaction pool
|
||||
// and wait for the transaction to be mined until the timeout (in milliseconds) is reached.
|
||||
func (api *TransactionAPI) SendRawTransactionSync(ctx context.Context, input hexutil.Bytes, timeoutMs *hexutil.Uint64) (map[string]interface{}, error) {
|
||||
tx := new(types.Transaction)
|
||||
if err := tx.UnmarshalBinary(input); err != nil {
|
||||
return nil, err
|
||||
}
|
||||
hash, err := SubmitTransaction(ctx, api.b, tx)
|
||||
if err != nil {
|
||||
return nil, err
|
||||
}
|
||||
|
||||
// compute effective timeout
|
||||
max := api.b.RPCTxSyncMaxTimeout()
|
||||
def := api.b.RPCTxSyncDefaultTimeout()
|
||||
|
||||
eff := def
|
||||
if timeoutMs != nil && *timeoutMs > 0 {
|
||||
req := time.Duration(*timeoutMs) * time.Millisecond
|
||||
if req > max {
|
||||
eff = max
|
||||
} else {
|
||||
eff = req // allow shorter than default
|
||||
}
|
||||
}
|
||||
|
||||
// Wait for receipt until timeout
|
||||
receiptCtx, cancel := context.WithTimeout(ctx, eff)
|
||||
defer cancel()
|
||||
|
||||
ticker := time.NewTicker(time.Millisecond * 100)
|
||||
defer ticker.Stop()
|
||||
|
||||
for {
|
||||
select {
|
||||
case <-ticker.C:
|
||||
receipt, getErr := api.GetTransactionReceipt(receiptCtx, hash)
|
||||
// If tx-index still building, keep polling
|
||||
if getErr != nil && !errors.Is(getErr, NewTxIndexingError()) {
|
||||
// transient or other error: just keep polling
|
||||
}
|
||||
if receipt != nil {
|
||||
return receipt, nil
|
||||
}
|
||||
case <-receiptCtx.Done():
|
||||
if err := ctx.Err(); err != nil {
|
||||
return nil, err // context canceled / deadline exceeded upstream
|
||||
}
|
||||
return nil, &txSyncTimeoutError{
|
||||
msg: fmt.Sprintf("The transaction was added to the transaction pool but wasn't processed in %v.", eff),
|
||||
hash: hash,
|
||||
}
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
// Sign calculates an ECDSA signature for:
|
||||
// keccak256("\x19Ethereum Signed Message:\n" + len(message) + message).
|
||||
//
|
||||
|
|
|
|||
|
|
@ -53,6 +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
|
||||
|
||||
// Blockchain API
|
||||
SetHead(number uint64)
|
||||
|
|
|
|||
|
|
@ -21,6 +21,7 @@ import (
|
|||
"fmt"
|
||||
|
||||
"github.com/ethereum/go-ethereum/accounts/abi"
|
||||
"github.com/ethereum/go-ethereum/common"
|
||||
"github.com/ethereum/go-ethereum/common/hexutil"
|
||||
"github.com/ethereum/go-ethereum/core"
|
||||
"github.com/ethereum/go-ethereum/core/vm"
|
||||
|
|
@ -33,6 +34,11 @@ type revertError struct {
|
|||
reason string // revert reason hex encoded
|
||||
}
|
||||
|
||||
type txSyncTimeoutError struct {
|
||||
msg string
|
||||
hash common.Hash
|
||||
}
|
||||
|
||||
// ErrorCode returns the JSON error code for a revert.
|
||||
// See: https://ethereum.org/en/developers/docs/apis/json-rpc/#error-codes
|
||||
func (e *revertError) ErrorCode() int {
|
||||
|
|
@ -108,6 +114,7 @@ const (
|
|||
errCodeInvalidParams = -32602
|
||||
errCodeReverted = -32000
|
||||
errCodeVMError = -32015
|
||||
errCodeTxSyncTimeout = 4
|
||||
)
|
||||
|
||||
func txValidationError(err error) *invalidTxError {
|
||||
|
|
@ -168,3 +175,9 @@ type blockGasLimitReachedError struct{ message string }
|
|||
|
||||
func (e *blockGasLimitReachedError) Error() string { return e.message }
|
||||
func (e *blockGasLimitReachedError) ErrorCode() int { return errCodeBlockGasLimitReached }
|
||||
|
||||
func (e *txSyncTimeoutError) Error() string { return e.msg }
|
||||
func (e *txSyncTimeoutError) ErrorCode() int { return errCodeTxSyncTimeout }
|
||||
|
||||
// ErrorData should be JSON-safe; return the 0x-hex string.
|
||||
func (e *txSyncTimeoutError) ErrorData() interface{} { return e.hash.Hex() }
|
||||
|
|
|
|||
Loading…
Reference in a new issue