-
Notifications
You must be signed in to change notification settings - Fork 21.4k
internal/ethapi: add eth_SendRawTransactionSync #32830
New issue
Have a question about this project? Sign up for a free GitHub account to open an issue and contact its maintainers and the community.
By clicking “Sign up for GitHub”, you agree to our terms of service and privacy statement. We’ll occasionally send you account related emails.
Already on GitHub? Sign in to your account
base: master
Are you sure you want to change the base?
Changes from 17 commits
ca42c98
a33a1c9
0684a33
e7a48a5
e3fa487
1e697d9
4c5beb4
a463b32
3a3c46a
3d083d0
862c07e
91be12e
960d6c3
4c075f6
2ed437e
3aa3538
455f09d
1d662b5
3ab8ec8
409eea4
eed426c
File filter
Filter by extension
Conversations
Jump to
Diff view
Diff view
There are no files selected for viewing
Original file line number | Diff line number | Diff line change |
---|---|---|
|
@@ -1652,6 +1652,91 @@ 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 until the transaction has been included in a block and return the receipt, or the timeout. | ||
func (api *TransactionAPI) SendRawTransactionSync(ctx context.Context, input hexutil.Bytes, timeoutMs *hexutil.Uint64) (map[string]interface{}, error) { | ||
s1na marked this conversation as resolved.
Show resolved
Hide resolved
|
||
tx := new(types.Transaction) | ||
if err := tx.UnmarshalBinary(input); err != nil { | ||
return nil, err | ||
} | ||
|
||
ch := make(chan core.ChainEvent, 128) | ||
sub := api.b.SubscribeChainEvent(ch) | ||
subErrCh := sub.Err() | ||
defer sub.Unsubscribe() | ||
|
||
hash, err := SubmitTransaction(ctx, api.b, tx) | ||
if err != nil { | ||
return nil, err | ||
} | ||
|
||
maxTimeout := api.b.RPCTxSyncMaxTimeout() | ||
defaultTimeout := api.b.RPCTxSyncDefaultTimeout() | ||
|
||
timeout := defaultTimeout | ||
if timeoutMs != nil && *timeoutMs > 0 { | ||
req := time.Duration(*timeoutMs) * time.Millisecond | ||
if req > maxTimeout { | ||
timeout = maxTimeout | ||
} else { | ||
timeout = req | ||
} | ||
} | ||
|
||
receiptCtx, cancel := context.WithTimeout(ctx, timeout) | ||
defer cancel() | ||
|
||
// Fast path. | ||
if r, err := api.GetTransactionReceipt(receiptCtx, hash); err == nil && r != nil { | ||
return r, nil | ||
} | ||
|
||
for { | ||
select { | ||
case <-receiptCtx.Done(): | ||
// Upstream cancellation -> bubble it; otherwise emit the timeout error | ||
if err := ctx.Err(); err != nil { | ||
s1na marked this conversation as resolved.
Show resolved
Hide resolved
There was a problem hiding this comment. Choose a reason for hiding this commentThe reason will be displayed to describe this comment to others. Learn more. I don't follow why you then go with the caller's context error. Deadlines from the parent context will propagate to receiptCtx also. And receiptCtx generally might "know more" what went wrong. There was a problem hiding this comment. Choose a reason for hiding this commentThe reason will be displayed to describe this comment to others. Learn more. Ah I missed the fallback return. Still not clear to me why we need this condition. The receiptCtx should contain an error from its parent ctx |
||
return nil, err | ||
} | ||
return nil, &txSyncTimeoutError{ | ||
msg: fmt.Sprintf("The transaction was added to the transaction pool but wasn't processed in %v.", timeout), | ||
hash: hash, | ||
} | ||
|
||
case err, ok := <-subErrCh: | ||
if !ok || err == nil { | ||
// subscription closed; disable this case | ||
|
||
subErrCh = nil | ||
continue | ||
} | ||
return nil, err | ||
|
||
case ev := <-ch: | ||
rs := ev.Receipts | ||
txs := ev.Transactions | ||
if len(rs) == 0 || len(rs) != len(txs) { | ||
continue | ||
} | ||
for i := range rs { | ||
if rs[i].TxHash == hash { | ||
if rs[i].BlockNumber != nil && rs[i].BlockHash != (common.Hash{}) { | ||
signer := types.LatestSigner(api.b.ChainConfig()) | ||
return MarshalReceipt( | ||
rs[i], | ||
rs[i].BlockHash, | ||
rs[i].BlockNumber.Uint64(), | ||
signer, | ||
txs[i], | ||
int(rs[i].TransactionIndex), | ||
), nil | ||
} | ||
return api.GetTransactionReceipt(receiptCtx, hash) | ||
} | ||
} | ||
} | ||
} | ||
} | ||
|
||
// Sign calculates an ECDSA signature for: | ||
// keccak256("\x19Ethereum Signed Message:\n" + len(message) + message). | ||
// | ||
|
There was a problem hiding this comment.
Choose a reason for hiding this comment
The reason will be displayed to describe this comment to others. Learn more.
Use tx.MarshalBinary
There was a problem hiding this comment.
Choose a reason for hiding this comment
The reason will be displayed to describe this comment to others. Learn more.
What about naming it SendTransactionSync? and the other one SendRawTransactionSync
There was a problem hiding this comment.
Choose a reason for hiding this comment
The reason will be displayed to describe this comment to others. Learn more.
Also I think timeout should be optional
Uh oh!
There was an error while loading. Please reload this page.
There was a problem hiding this comment.
Choose a reason for hiding this comment
The reason will be displayed to describe this comment to others. Learn more.
changed in 1d662b50a