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) {
|
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)
|
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)
|
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:
|
// Sign calculates an ECDSA signature for:
|
||||||
// keccak256("\x19Ethereum Signed Message:\n" + len(message) + message).
|
// 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
|
RPCEVMTimeout() time.Duration // global timeout for eth_call over rpc: DoS protection
|
||||||
RPCTxFeeCap() float64 // global tx fee cap for all transaction related APIs
|
RPCTxFeeCap() float64 // global tx fee cap for all transaction related APIs
|
||||||
UnprotectedAllowed() bool // allows only for EIP155 transactions.
|
UnprotectedAllowed() bool // allows only for EIP155 transactions.
|
||||||
|
RPCTxSyncDefaultTimeout() time.Duration
|
||||||
|
RPCTxSyncMaxTimeout() time.Duration
|
||||||
|
|
||||||
// Blockchain API
|
// Blockchain API
|
||||||
SetHead(number uint64)
|
SetHead(number uint64)
|
||||||
|
|
|
||||||
|
|
@ -21,6 +21,7 @@ import (
|
||||||
"fmt"
|
"fmt"
|
||||||
|
|
||||||
"github.com/ethereum/go-ethereum/accounts/abi"
|
"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/common/hexutil"
|
||||||
"github.com/ethereum/go-ethereum/core"
|
"github.com/ethereum/go-ethereum/core"
|
||||||
"github.com/ethereum/go-ethereum/core/vm"
|
"github.com/ethereum/go-ethereum/core/vm"
|
||||||
|
|
@ -33,6 +34,11 @@ type revertError struct {
|
||||||
reason string // revert reason hex encoded
|
reason string // revert reason hex encoded
|
||||||
}
|
}
|
||||||
|
|
||||||
|
type txSyncTimeoutError struct {
|
||||||
|
msg string
|
||||||
|
hash common.Hash
|
||||||
|
}
|
||||||
|
|
||||||
// ErrorCode returns the JSON error code for a revert.
|
// ErrorCode returns the JSON error code for a revert.
|
||||||
// See: https://ethereum.org/en/developers/docs/apis/json-rpc/#error-codes
|
// See: https://ethereum.org/en/developers/docs/apis/json-rpc/#error-codes
|
||||||
func (e *revertError) ErrorCode() int {
|
func (e *revertError) ErrorCode() int {
|
||||||
|
|
@ -108,6 +114,7 @@ const (
|
||||||
errCodeInvalidParams = -32602
|
errCodeInvalidParams = -32602
|
||||||
errCodeReverted = -32000
|
errCodeReverted = -32000
|
||||||
errCodeVMError = -32015
|
errCodeVMError = -32015
|
||||||
|
errCodeTxSyncTimeout = 4
|
||||||
)
|
)
|
||||||
|
|
||||||
func txValidationError(err error) *invalidTxError {
|
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) Error() string { return e.message }
|
||||||
func (e *blockGasLimitReachedError) ErrorCode() int { return errCodeBlockGasLimitReached }
|
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